Merge "Update test mission 1 marker file directory" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 1233fa1..fa11278 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -74,23 +74,27 @@
         "android.view.inputmethod.flags-aconfig-java",
         "android.webkit.flags-aconfig-java",
         "android.widget.flags-aconfig-java",
+        "backstage_power_flags_lib",
         "backup_flags_lib",
         "camera_platform_flags_core_java_lib",
         "com.android.hardware.input-aconfig-java",
         "com.android.input.flags-aconfig-java",
         "com.android.internal.compat.flags-aconfig-java",
         "com.android.internal.foldables.flags-aconfig-java",
+        "com.android.internal.os.flags-aconfig-java",
         "com.android.internal.pm.pkg.component.flags-aconfig-java",
         "com.android.media.flags.bettertogether-aconfig-java",
         "com.android.media.flags.editing-aconfig-java",
         "com.android.media.flags.performance-aconfig-java",
         "com.android.media.flags.projection-aconfig-java",
         "com.android.net.thread.platform.flags-aconfig-java",
+        "com.android.server.contextualsearch.flags-java",
         "com.android.server.flags.services-aconfig-java",
         "com.android.text.flags-aconfig-java",
         "com.android.window.flags.window-aconfig-java",
         "device_policy_aconfig_flags_lib",
         "display_flags_lib",
+        "dropbox_flags_lib",
         "framework-jobscheduler-job.flags-aconfig-java",
         "framework_graphics_flags_java_lib",
         "hwui_flags_java_lib",
@@ -172,6 +176,7 @@
 // DeviceStateManager
 aconfig_declarations {
     name: "android.hardware.devicestate.feature.flags-aconfig",
+    exportable: true,
     package: "android.hardware.devicestate.feature.flags",
     container: "system",
     srcs: ["core/java/android/hardware/devicestate/feature/*.aconfig"],
@@ -186,6 +191,7 @@
 // Input
 aconfig_declarations {
     name: "com.android.hardware.input.input-aconfig",
+    exportable: true,
     package: "com.android.hardware.input",
     container: "system",
     srcs: ["core/java/android/hardware/input/*.aconfig"],
@@ -369,6 +375,20 @@
     host_supported: true,
 }
 
+// OS Internal
+aconfig_declarations {
+    name: "com.android.internal.os.flags-aconfig",
+    package: "com.android.internal.os",
+    container: "system",
+    srcs: ["core/java/com/android/internal/os/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "com.android.internal.os.flags-aconfig-java",
+    aconfig_declarations: "com.android.internal.os.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // VirtualDeviceManager
 cc_aconfig_library {
     name: "android.companion.virtualdevice.flags-aconfig-cc",
@@ -470,6 +490,7 @@
 // Hardware
 aconfig_declarations {
     name: "android.hardware.flags-aconfig",
+    exportable: true,
     package: "android.hardware.flags",
     container: "system",
     srcs: ["core/java/android/hardware/flags/*.aconfig"],
@@ -567,6 +588,7 @@
 // Media Editing
 aconfig_declarations {
     name: "com.android.media.flags.editing-aconfig",
+    exportable: true,
     package: "com.android.media.editing.flags",
     container: "system",
     srcs: [
@@ -600,6 +622,7 @@
 aconfig_declarations {
     name: "com.android.media.flags.performance-aconfig",
     package: "com.android.media.performance.flags",
+    container: "system",
     srcs: [
         "media/java/android/media/flags/performance.aconfig",
     ],
@@ -614,6 +637,7 @@
 // Media TV
 aconfig_declarations {
     name: "android.media.tv.flags-aconfig",
+    exportable: true,
     package: "android.media.tv.flags",
     container: "system",
     srcs: ["media/java/android/media/tv/flags/media_tv.aconfig"],
@@ -628,6 +652,7 @@
 // OnDeviceIntelligence
 aconfig_declarations {
     name: "android.app.ondeviceintelligence-aconfig",
+    exportable: true,
     package: "android.app.ondeviceintelligence.flags",
     container: "system",
     srcs: ["core/java/android/app/ondeviceintelligence/flags/ondevice_intelligence.aconfig"],
@@ -659,6 +684,19 @@
     ],
 }
 
+java_aconfig_library {
+    name: "android.permission.flags-aconfig-java-host",
+    aconfig_declarations: "android.permission.flags-aconfig",
+    host_supported: true,
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+    min_sdk_version: "30",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.permission",
+        "com.android.nfcservices",
+    ],
+}
+
 // SQLite
 aconfig_declarations {
     name: "android.database.sqlite-aconfig",
@@ -682,6 +720,7 @@
 // Biometrics
 aconfig_declarations {
     name: "android.hardware.biometrics.flags-aconfig",
+    exportable: true,
     package: "android.hardware.biometrics",
     container: "system",
     srcs: ["core/java/android/hardware/biometrics/flags.aconfig"],
@@ -762,6 +801,7 @@
 // Broadcast Radio
 aconfig_declarations {
     name: "android.hardware.radio.flags-aconfig",
+    exportable: true,
     package: "android.hardware.radio",
     container: "system",
     srcs: ["core/java/android/hardware/radio/*.aconfig"],
@@ -798,6 +838,7 @@
 // Content Protection
 aconfig_declarations {
     name: "android.view.contentprotection.flags-aconfig",
+    exportable: true,
     package: "android.view.contentprotection.flags",
     container: "system",
     srcs: ["core/java/android/view/contentprotection/flags/*.aconfig"],
@@ -809,6 +850,20 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// Contextual Search system service
+aconfig_declarations {
+    name: "com.android.server.contextualsearch.flags-aconfig",
+    package: "com.android.server.contextualsearch.flags",
+    container: "system",
+    srcs: ["services/contextualsearch/flags/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "com.android.server.contextualsearch.flags-java",
+    aconfig_declarations: "com.android.server.contextualsearch.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // Server Services Flags
 aconfig_declarations {
     name: "com.android.server.flags.services-aconfig",
@@ -826,6 +881,7 @@
 // App prediction
 aconfig_declarations {
     name: "android.service.appprediction.flags-aconfig",
+    exportable: true,
     package: "android.service.appprediction.flags",
     container: "system",
     srcs: ["core/java/android/service/appprediction/flags/*.aconfig"],
@@ -840,6 +896,7 @@
 // Controls
 aconfig_declarations {
     name: "android.service.controls.flags-aconfig",
+    exportable: true,
     package: "android.service.controls.flags",
     container: "system",
     srcs: ["core/java/android/service/controls/flags/*.aconfig"],
@@ -854,6 +911,7 @@
 // Voice
 aconfig_declarations {
     name: "android.service.voice.flags-aconfig",
+    exportable: true,
     package: "android.service.voice.flags",
     container: "system",
     srcs: ["core/java/android/service/voice/flags/*.aconfig"],
@@ -885,6 +943,7 @@
 // Companion
 aconfig_declarations {
     name: "android.companion.flags-aconfig",
+    exportable: true,
     package: "android.companion",
     container: "system",
     srcs: ["core/java/android/companion/*.aconfig"],
@@ -899,6 +958,7 @@
 // Networking
 aconfig_declarations {
     name: "android.net.platform.flags-aconfig",
+    exportable: true,
     package: "android.net.platform.flags",
     container: "system",
     srcs: ["core/java/android/net/flags.aconfig"],
@@ -908,6 +968,7 @@
 // Thread network
 aconfig_declarations {
     name: "com.android.net.thread.platform.flags-aconfig",
+    exportable: true,
     package: "com.android.net.thread.platform.flags",
     container: "system",
     srcs: ["core/java/android/net/thread/flags.aconfig"],
@@ -1011,6 +1072,7 @@
     name: "framework-jobscheduler-job.flags-aconfig",
     package: "android.app.job",
     container: "system",
+    exportable: true,
     srcs: ["apex/jobscheduler/framework/aconfig/job.aconfig"],
 }
 
@@ -1078,6 +1140,7 @@
 // Smartspace
 aconfig_declarations {
     name: "android.app.smartspace.flags-aconfig",
+    exportable: true,
     package: "android.app.smartspace.flags",
     container: "system",
     srcs: ["core/java/android/app/smartspace/flags.aconfig"],
@@ -1113,6 +1176,7 @@
 // USB
 aconfig_declarations {
     name: "android.hardware.usb.flags-aconfig",
+    exportable: true,
     package: "android.hardware.usb.flags",
     container: "system",
     srcs: ["core/java/android/hardware/usb/flags/*.aconfig"],
@@ -1198,6 +1262,7 @@
 // Provider
 aconfig_declarations {
     name: "android.provider.flags-aconfig",
+    exportable: true,
     package: "android.provider",
     container: "system",
     srcs: ["core/java/android/provider/*.aconfig"],
@@ -1219,6 +1284,7 @@
 // Speech
 aconfig_declarations {
     name: "android.speech.flags-aconfig",
+    exportable: true,
     package: "android.speech.flags",
     container: "system",
     srcs: ["core/java/android/speech/flags/*.aconfig"],
@@ -1240,6 +1306,7 @@
 // Content
 aconfig_declarations {
     name: "android.content.flags-aconfig",
+    exportable: true,
     package: "android.content.flags",
     container: "system",
     srcs: ["core/java/android/content/flags/flags.aconfig"],
@@ -1268,6 +1335,7 @@
 // CrashRecovery Module
 aconfig_declarations {
     name: "android.crashrecovery.flags-aconfig",
+    exportable: true,
     package: "android.crashrecovery.flags",
     container: "system",
     srcs: ["packages/CrashRecovery/aconfig/flags.aconfig"],
@@ -1279,6 +1347,13 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+java_aconfig_library {
+    name: "android.crashrecovery.flags-aconfig-java-host",
+    aconfig_declarations: "android.crashrecovery.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+    host_supported: true,
+}
+
 // Backup
 java_aconfig_library {
     name: "backup_flags_lib",
@@ -1308,6 +1383,7 @@
 // Wearable Sensing
 aconfig_declarations {
     name: "android.app.wearable.flags-aconfig",
+    exportable: true,
     package: "android.app.wearable",
     container: "system",
     srcs: ["core/java/android/app/wearable/*.aconfig"],
@@ -1352,3 +1428,36 @@
     aconfig_declarations: "android.systemserver.flags-aconfig",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
+
+// backstage power
+aconfig_declarations {
+    name: "backstage_power_flags",
+    package: "com.android.server.power.optimization",
+    container: "system",
+    exportable: true,
+    srcs: [
+        "services/core/java/com/android/server/power/stats/flags.aconfig",
+    ],
+}
+
+java_aconfig_library {
+    name: "backstage_power_flags_lib",
+    aconfig_declarations: "backstage_power_flags",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+// Dropbox data
+aconfig_declarations {
+    name: "dropbox_flags",
+    package: "com.android.server.feature.flags",
+    container: "system",
+    srcs: [
+        "services/core/java/com/android/server/feature/dropbox_flags.aconfig",
+    ],
+}
+
+java_aconfig_library {
+    name: "dropbox_flags_lib",
+    aconfig_declarations: "dropbox_flags",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/Android.bp b/Android.bp
index 4f715f8..d6b303f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -97,7 +97,7 @@
         // AIDL sources from external directories
         ":android.frameworks.location.altitude-V2-java-source",
         ":android.hardware.biometrics.common-V4-java-source",
-        ":android.hardware.biometrics.fingerprint-V3-java-source",
+        ":android.hardware.biometrics.fingerprint-V5-java-source",
         ":android.hardware.biometrics.face-V4-java-source",
         ":android.hardware.gnss-V2-java-source",
         ":android.hardware.graphics.common-V3-java-source",
diff --git a/apct-tests/perftests/inputmethod/AndroidManifest.xml b/apct-tests/perftests/inputmethod/AndroidManifest.xml
index 3eea418..34f9692 100644
--- a/apct-tests/perftests/inputmethod/AndroidManifest.xml
+++ b/apct-tests/perftests/inputmethod/AndroidManifest.xml
@@ -22,7 +22,8 @@
     <application>
         <uses-library android:name="android.test.runner" />
         <activity android:name="android.perftests.utils.PerfTestActivity"
-            android:exported="true">
+                  android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar"
+                  android:exported="true">
           <intent-filter>
             <action android:name="com.android.perftests.core.PERFTEST" />
           </intent-filter>
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 6871762..762e2af 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -366,7 +366,7 @@
             mRunner.pauseTiming();
             Log.i(TAG, "Stopping timer");
 
-            stopUser(userId, /* force */true);
+            stopUser(userId);
             mRunner.resumeTimingForNextIteration();
         }
 
@@ -429,7 +429,7 @@
 
             mRunner.pauseTiming();
             Log.i(TAG, "Stopping timer");
-            stopUser(userId, /* force */true);
+            stopUser(userId);
             mRunner.resumeTimingForNextIteration();
         }
 
@@ -545,7 +545,7 @@
             mRunner.pauseTiming();
             Log.d(TAG, "Stopping timer");
             switchUserNoCheck(currentUserId);
-            stopUserAfterWaitingForBroadcastIdle(userId, /* force */true);
+            stopUserAfterWaitingForBroadcastIdle(userId);
             attestFalse("Failed to stop user " + userId, mAm.isUserRunning(userId));
             mRunner.resumeTimingForNextIteration();
         }
@@ -571,7 +571,7 @@
             mRunner.pauseTiming();
             Log.d(TAG, "Stopping timer");
             switchUserNoCheck(startUser);
-            stopUserAfterWaitingForBroadcastIdle(testUser, true);
+            stopUserAfterWaitingForBroadcastIdle(testUser);
             attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
             mRunner.resumeTimingForNextIteration();
         }
@@ -660,7 +660,7 @@
             mRunner.resumeTiming();
             Log.i(TAG, "Starting timer");
 
-            stopUser(userId, false);
+            stopUser(userId);
 
             mRunner.pauseTiming();
             Log.i(TAG, "Stopping timer");
@@ -685,7 +685,7 @@
             Log.d(TAG, "Starting timer");
             mRunner.resumeTiming();
 
-            stopUser(userId, false);
+            stopUser(userId);
 
             mRunner.pauseTiming();
             Log.d(TAG, "Stopping timer");
@@ -883,7 +883,7 @@
             final int userId = createManagedProfile();
             // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
             startUserInBackgroundAndWaitForUnlock(userId);
-            stopUserAfterWaitingForBroadcastIdle(userId, true);
+            stopUserAfterWaitingForBroadcastIdle(userId);
             mRunner.resumeTiming();
             Log.i(TAG, "Starting timer");
 
@@ -905,7 +905,7 @@
         startUserInBackgroundAndWaitForUnlock(userId);
         while (mRunner.keepRunning()) {
             mRunner.pauseTiming();
-            stopUserAfterWaitingForBroadcastIdle(userId, true);
+            stopUserAfterWaitingForBroadcastIdle(userId);
             mRunner.resumeTiming();
             Log.d(TAG, "Starting timer");
 
@@ -987,7 +987,7 @@
             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
             startUserInBackgroundAndWaitForUnlock(userId);
             startApp(userId, DUMMY_PACKAGE_NAME);
-            stopUserAfterWaitingForBroadcastIdle(userId, true);
+            stopUserAfterWaitingForBroadcastIdle(userId);
             SystemClock.sleep(1_000); // 1 second cool-down before re-starting profile.
             mRunner.resumeTiming();
             Log.i(TAG, "Starting timer");
@@ -1019,7 +1019,7 @@
             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
             startUserInBackgroundAndWaitForUnlock(userId);
             startApp(userId, DUMMY_PACKAGE_NAME);
-            stopUserAfterWaitingForBroadcastIdle(userId, true);
+            stopUserAfterWaitingForBroadcastIdle(userId);
             SystemClock.sleep(1_000); // 1 second cool-down before re-starting profile.
             mRunner.resumeTiming();
             Log.d(TAG, "Starting timer");
@@ -1144,7 +1144,7 @@
             mRunner.resumeTiming();
             Log.i(TAG, "Starting timer");
 
-            stopUser(userId, true);
+            stopUser(userId);
 
             mRunner.pauseTiming();
             Log.i(TAG, "Stopping timer");
@@ -1168,7 +1168,7 @@
             mRunner.resumeTiming();
             Log.d(TAG, "Starting timer");
 
-            stopUser(userId, true);
+            stopUser(userId);
 
             mRunner.pauseTiming();
             Log.d(TAG, "Stopping timer");
@@ -1294,15 +1294,15 @@
      * Do not call this method while timing is on. i.e. between mRunner.resumeTiming() and
      * mRunner.pauseTiming(). Otherwise it would cause the test results to be spiky.
      */
-    private void stopUserAfterWaitingForBroadcastIdle(int userId, boolean force)
+    private void stopUserAfterWaitingForBroadcastIdle(int userId)
             throws RemoteException {
         waitForBroadcastIdle();
-        stopUser(userId, force);
+        stopUser(userId);
     }
 
-    private void stopUser(int userId, boolean force) throws RemoteException {
+    private void stopUser(int userId) throws RemoteException {
         final CountDownLatch latch = new CountDownLatch(1);
-        mIam.stopUser(userId, force /* force */, new IStopUserCallback.Stub() {
+        mIam.stopUserWithCallback(userId, new IStopUserCallback.Stub() {
             @Override
             public void userStopped(int userId) throws RemoteException {
                 latch.countDown();
@@ -1352,7 +1352,7 @@
         attestTrue("Didn't switch back to user, " + origUser, origUser == mAm.getCurrentUser());
 
         if (stopNewUser) {
-            stopUserAfterWaitingForBroadcastIdle(testUser, true);
+            stopUserAfterWaitingForBroadcastIdle(testUser);
             attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
         }
 
@@ -1471,7 +1471,7 @@
     }
 
     private void removeUser(int userId) throws RemoteException {
-        stopUserAfterWaitingForBroadcastIdle(userId, true);
+        stopUserAfterWaitingForBroadcastIdle(userId);
         try {
             ShellHelper.runShellCommandWithTimeout("pm remove-user -w " + userId,
                     TIMEOUT_IN_SECOND);
@@ -1512,7 +1512,7 @@
 
             final boolean preStartComplete = mIam.startUserInBackgroundWithListener(userId,
                     preWaiter) && preWaiter.waitForFinish(TIMEOUT_IN_SECOND * 1000);
-            stopUserAfterWaitingForBroadcastIdle(userId, /* force */true);
+            stopUserAfterWaitingForBroadcastIdle(userId);
 
             assertTrue("Pre start was not performed for user" + userId, preStartComplete);
         }
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
index c9d45a6..db938e4 100644
--- a/apct-tests/perftests/packagemanager/AndroidTest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -76,11 +76,6 @@
         <option name="test-file-name" value="QueriesAll49.apk"/>
     </target_preparer>
 
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="com.android.perftests.packagemanager"/>
-        <option name="hidden-api-checks" value="false"/>
-    </test>
-
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="directory-keys" value="/data/local/PackageManagerPerfTests"/>
         <option name="collect-on-run-ended-only" value="true"/>
diff --git a/apct-tests/perftests/rubidium/Android.bp b/apct-tests/perftests/rubidium/Android.bp
deleted file mode 100644
index 4f4fb11..0000000
--- a/apct-tests/perftests/rubidium/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_team: "trendy_team_input_framework",
-    // 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: "RubidiumPerfTests",
-    srcs: ["src/**/*.java"],
-    min_sdk_version: "33",
-    static_libs: [
-        "androidx.test.rules",
-        "androidx.annotation_annotation",
-        "apct-perftests-utils",
-        "collector-device-lib-platform",
-        "compatibility-device-util-axt",
-        "platform-test-annotations",
-        "framework-adservices-lib",
-        "adservices-service-core",
-        "androidx.core_core",
-    ],
-    test_suites: ["device-tests"],
-    data: [":perfetto_artifacts"],
-    platform_apis: true,
-    certificate: "platform",
-}
diff --git a/apct-tests/perftests/rubidium/AndroidManifest.xml b/apct-tests/perftests/rubidium/AndroidManifest.xml
deleted file mode 100644
index 1c6b73c..0000000
--- a/apct-tests/perftests/rubidium/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.perftests.rubidium">
-
-    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.perftests.rubidium"/>
-</manifest>
diff --git a/apct-tests/perftests/rubidium/AndroidTest.xml b/apct-tests/perftests/rubidium/AndroidTest.xml
deleted file mode 100644
index f538cf5..0000000
--- a/apct-tests/perftests/rubidium/AndroidTest.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed undtradefed.testtype.AndroidJUniter the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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 RubidiumPerfTests metric instrumentation.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-metric-instrumentation" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="RubidiumPerfTests.apk" />
-    </target_preparer>
-
-    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
-        <option name="force-skip-system-props" value="true" />
-        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
-        <option name="run-command" value="cmd window dismiss-keyguard" />
-        <option name="run-command" value="cmd package compile -m speed com.android.perftests.rubidium" />
-    </target_preparer>
-
-    <!-- Needed for pushing the trace config file -->
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
-        <!--Install the content provider automatically when we push some file in sdcard folder.-->
-        <!--Needed to avoid the installation during the test suite.-->
-        <option name="push-file" key="trace_config_detailed.textproto" value="/sdcard/sample.textproto" />
-    </target_preparer>
-
-    <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
-    <option name="isolated-storage" value="false" />
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.perftests.rubidium" />
-        <option name="hidden-api-checks" value="false"/>
-
-        <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
-        <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" />
-
-        <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
-        <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
-
-        <!-- Kill background operations -->
-        <option name="instrumentation-arg" key="kill-bg" value="true" />
-
-        <!-- ProcLoadListener related arguments -->
-        <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
-        <option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
-        <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
-        <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
-        <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />
-
-        <!-- PerfettoListener related arguments -->
-        <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" />
-        <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" />
-    </test>
-
-    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-        <option name="directory-keys" value="/data/local/tmp/RubidiumPerfTests" />
-        <!-- Needed for pulling the collected trace config on to the host -->
-        <option name="pull-pattern-keys" value="perfetto_file_path" />
-    </metrics_collector>
-</configuration>
diff --git a/apct-tests/perftests/rubidium/OWNERS b/apct-tests/perftests/rubidium/OWNERS
deleted file mode 100644
index ba54a9d..0000000
--- a/apct-tests/perftests/rubidium/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
[email protected]
[email protected]
[email protected]
diff --git a/apct-tests/perftests/rubidium/assets/empty_generate_bid.js b/apct-tests/perftests/rubidium/assets/empty_generate_bid.js
deleted file mode 100644
index 38efc9e..0000000
--- a/apct-tests/perftests/rubidium/assets/empty_generate_bid.js
+++ /dev/null
@@ -1,11 +0,0 @@
-"use strict";
-
-function generateBid(ad) {
-  let input = ad.metadata.input;
-
-  return {
-    ad: 'example',
-    bid: input,
-    render: ad.renderUrl
-  }
-}
\ No newline at end of file
diff --git a/apct-tests/perftests/rubidium/assets/generate_bid.wasm b/apct-tests/perftests/rubidium/assets/generate_bid.wasm
deleted file mode 100644
index 5e7fe9e..0000000
--- a/apct-tests/perftests/rubidium/assets/generate_bid.wasm
+++ /dev/null
Binary files differ
diff --git a/apct-tests/perftests/rubidium/assets/generate_bid_using_wasm.js b/apct-tests/perftests/rubidium/assets/generate_bid_using_wasm.js
deleted file mode 100644
index bc50d0a..0000000
--- a/apct-tests/perftests/rubidium/assets/generate_bid_using_wasm.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function generateBid(ad, wasmModule) {
-  let input = ad.metadata.input;
-
-  const instance = new WebAssembly.Instance(wasmModule);
-
-  const memory = instance.exports.memory;
-  const input_in_memory = new Float32Array(memory.buffer, 0, 200);
-  for (let i = 0; i < input.length; ++i) {
-    input_in_memory[i] = input[i];
-  }
-  const results = [
-    instance.exports.nn_forward_model0(input_in_memory.length, input_in_memory),
-    instance.exports.nn_forward_model1(input_in_memory.length, input_in_memory),
-    instance.exports.nn_forward_model2(input_in_memory.length, input_in_memory),
-    instance.exports.nn_forward_model3(input_in_memory.length, input_in_memory),
-    instance.exports.nn_forward_model4(input_in_memory.length, input_in_memory),
-  ];
-  const bid = results.map(x => Math.max(x, 1)).reduce((x, y) => x * y);
-  return {
-    ad: 'example',
-    bid: bid,
-    render: ad.renderUrl
-  }
-}
\ No newline at end of file
diff --git a/apct-tests/perftests/rubidium/assets/rubidium_bidding_logic_compiled.js b/apct-tests/perftests/rubidium/assets/rubidium_bidding_logic_compiled.js
deleted file mode 100644
index 3f853f1..0000000
--- a/apct-tests/perftests/rubidium/assets/rubidium_bidding_logic_compiled.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-
- Copyright The Closure Library Authors.
- SPDX-License-Identifier: Apache-2.0
-*/
-'use strict';function ba(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}}var ca="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};
-function da(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");}var fa=da(this);function m(a,b){if(b)a:{var c=fa;a=a.split(".");for(var d=0;d<a.length-1;d++){var f=a[d];if(!(f in c))break a;c=c[f]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ca(c,a,{configurable:!0,writable:!0,value:b})}}
-m("Symbol",function(a){function b(e){if(this instanceof b)throw new TypeError("Symbol is not a constructor");return new c(d+(e||"")+"_"+f++,e)}function c(e,h){this.h=e;ca(this,"description",{configurable:!0,writable:!0,value:h})}if(a)return a;c.prototype.toString=function(){return this.h};var d="jscomp_symbol_"+(1E9*Math.random()>>>0)+"_",f=0;return b});
-m("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=fa[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&ca(d.prototype,a,{configurable:!0,writable:!0,value:function(){return ia(ba(this))}})}return a});function ia(a){a={next:a};a[Symbol.iterator]=function(){return this};return a}
-function p(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:ba(a)}}function ja(a){if(!(a instanceof Array)){a=p(a);for(var b,c=[];!(b=a.next()).done;)c.push(b.value);a=c}return a}var la="function"==typeof Object.create?Object.create:function(a){function b(){}b.prototype=a;return new b},ma;
-if("function"==typeof Object.setPrototypeOf)ma=Object.setPrototypeOf;else{var na;a:{var oa={a:!0},qa={};try{qa.__proto__=oa;na=qa.a;break a}catch(a){}na=!1}ma=na?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}var ra=ma;
-function q(a,b){a.prototype=la(b.prototype);a.prototype.constructor=a;if(ra)ra(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.Ia=b.prototype}function sa(){for(var a=Number(this),b=[],c=a;c<arguments.length;c++)b[c-a]=arguments[c];return b}function ta(a,b){return Object.prototype.hasOwnProperty.call(a,b)}
-m("WeakMap",function(a){function b(k){this.h=(g+=Math.random()+1).toString();if(k){k=p(k);for(var l;!(l=k.next()).done;)l=l.value,this.set(l[0],l[1])}}function c(){}function d(k){var l=typeof k;return"object"===l&&null!==k||"function"===l}function f(k){if(!ta(k,h)){var l=new c;ca(k,h,{value:l})}}function e(k){var l=Object[k];l&&(Object[k]=function(n){if(n instanceof c)return n;Object.isExtensible(n)&&f(n);return l(n)})}if(function(){if(!a||!Object.seal)return!1;try{var k=Object.seal({}),l=Object.seal({}),
-n=new a([[k,2],[l,3]]);if(2!=n.get(k)||3!=n.get(l))return!1;n.delete(k);n.set(l,4);return!n.has(k)&&4==n.get(l)}catch(t){return!1}}())return a;var h="$jscomp_hidden_"+Math.random();e("freeze");e("preventExtensions");e("seal");var g=0;b.prototype.set=function(k,l){if(!d(k))throw Error("Invalid WeakMap key");f(k);if(!ta(k,h))throw Error("WeakMap key fail: "+k);k[h][this.h]=l;return this};b.prototype.get=function(k){return d(k)&&ta(k,h)?k[h][this.h]:void 0};b.prototype.has=function(k){return d(k)&&ta(k,
-h)&&ta(k[h],this.h)};b.prototype.delete=function(k){return d(k)&&ta(k,h)&&ta(k[h],this.h)?delete k[h][this.h]:!1};return b});
-m("Map",function(a){function b(){var g={};return g.C=g.next=g.head=g}function c(g,k){var l=g.h;return ia(function(){if(l){for(;l.head!=g.h;)l=l.C;for(;l.next!=l.head;)return l=l.next,{done:!1,value:k(l)};l=null}return{done:!0,value:void 0}})}function d(g,k){var l=k&&typeof k;"object"==l||"function"==l?e.has(k)?l=e.get(k):(l=""+ ++h,e.set(k,l)):l="p_"+k;var n=g.u[l];if(n&&ta(g.u,l))for(g=0;g<n.length;g++){var t=n[g];if(k!==k&&t.key!==t.key||k===t.key)return{id:l,list:n,index:g,m:t}}return{id:l,list:n,
-index:-1,m:void 0}}function f(g){this.u={};this.h=b();this.size=0;if(g){g=p(g);for(var k;!(k=g.next()).done;)k=k.value,this.set(k[0],k[1])}}if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var g=Object.seal({x:4}),k=new a(p([[g,"s"]]));if("s"!=k.get(g)||1!=k.size||k.get({x:4})||k.set({x:4},"t")!=k||2!=k.size)return!1;var l=k.entries(),n=l.next();if(n.done||n.value[0]!=g||"s"!=n.value[1])return!1;n=l.next();return n.done||4!=n.value[0].x||
-"t"!=n.value[1]||!l.next().done?!1:!0}catch(t){return!1}}())return a;var e=new WeakMap;f.prototype.set=function(g,k){g=0===g?0:g;var l=d(this,g);l.list||(l.list=this.u[l.id]=[]);l.m?l.m.value=k:(l.m={next:this.h,C:this.h.C,head:this.h,key:g,value:k},l.list.push(l.m),this.h.C.next=l.m,this.h.C=l.m,this.size++);return this};f.prototype.delete=function(g){g=d(this,g);return g.m&&g.list?(g.list.splice(g.index,1),g.list.length||delete this.u[g.id],g.m.C.next=g.m.next,g.m.next.C=g.m.C,g.m.head=null,this.size--,
-!0):!1};f.prototype.clear=function(){this.u={};this.h=this.h.C=b();this.size=0};f.prototype.has=function(g){return!!d(this,g).m};f.prototype.get=function(g){return(g=d(this,g).m)&&g.value};f.prototype.entries=function(){return c(this,function(g){return[g.key,g.value]})};f.prototype.keys=function(){return c(this,function(g){return g.key})};f.prototype.values=function(){return c(this,function(g){return g.value})};f.prototype.forEach=function(g,k){for(var l=this.entries(),n;!(n=l.next()).done;)n=n.value,
-g.call(k,n[1],n[0],this)};f.prototype[Symbol.iterator]=f.prototype.entries;var h=0;return f});m("Number.isNaN",function(a){return a?a:function(b){return"number"===typeof b&&isNaN(b)}});function ua(a,b){a instanceof String&&(a+="");var c=0,d=!1,f={next:function(){if(!d&&c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d=!0;return{done:!0,value:void 0}}};f[Symbol.iterator]=function(){return f};return f}m("Array.prototype.values",function(a){return a?a:function(){return ua(this,function(b,c){return c})}});
-m("Set",function(a){function b(c){this.h=new Map;if(c){c=p(c);for(var d;!(d=c.next()).done;)this.add(d.value)}this.size=this.h.size}if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var c=Object.seal({x:4}),d=new a(p([c]));if(!d.has(c)||1!=d.size||d.add(c)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var f=d.entries(),e=f.next();if(e.done||e.value[0]!=c||e.value[1]!=c)return!1;e=f.next();return e.done||e.value[0]==c||4!=e.value[0].x||
-e.value[1]!=e.value[0]?!1:f.next().done}catch(h){return!1}}())return a;b.prototype.add=function(c){c=0===c?0:c;this.h.set(c,c);this.size=this.h.size;return this};b.prototype.delete=function(c){c=this.h.delete(c);this.size=this.h.size;return c};b.prototype.clear=function(){this.h.clear();this.size=0};b.prototype.has=function(c){return this.h.has(c)};b.prototype.entries=function(){return this.h.entries()};b.prototype.values=function(){return this.h.values()};b.prototype.keys=b.prototype.values;b.prototype[Symbol.iterator]=
-b.prototype.values;b.prototype.forEach=function(c,d){var f=this;this.h.forEach(function(e){return c.call(d,e,e,f)})};return b});m("globalThis",function(a){return a||fa});m("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});m("Array.prototype.includes",function(a){return a?a:function(b,c){var d=this;d instanceof String&&(d=String(d));var f=d.length;c=c||0;for(0>c&&(c=Math.max(c+f,0));c<f;c++){var e=d[c];if(e===b||Object.is(e,b))return!0}return!1}});
-m("String.prototype.includes",function(a){return a?a:function(b,c){if(null==this)throw new TypeError("The 'this' value for String.prototype.includes must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype.includes must not be a regular expression");return-1!==this.indexOf(b,c||0)}});m("Object.values",function(a){return a?a:function(b){var c=[],d;for(d in b)ta(b,d)&&c.push(b[d]);return c}});
-function va(a){var b=typeof a;return"object"==b&&null!=a||"function"==b};var wa={};var xa=Array.prototype.map?function(a,b){return Array.prototype.map.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=Array(c),f="string"===typeof a?a.split(""):a,e=0;e<c;e++)e in f&&(d[e]=b.call(void 0,f[e],e,a));return d};var ya={},za=null;function Aa(a,b){void 0===b&&(b=0);Ba();b=ya[b];for(var c=Array(Math.floor(a.length/3)),d=b[64]||"",f=0,e=0;f<a.length-2;f+=3){var h=a[f],g=a[f+1],k=a[f+2],l=b[h>>2];h=b[(h&3)<<4|g>>4];g=b[(g&15)<<2|k>>6];k=b[k&63];c[e++]=l+h+g+k}l=0;k=d;switch(a.length-f){case 2:l=a[f+1],k=b[(l&15)<<2]||d;case 1:a=a[f],c[e]=b[a>>2]+b[(a&3)<<4|l>>4]+k+d}return c.join("")}
-function Ca(a){var b=a.length,c=3*b/4;c%3?c=Math.floor(c):-1!="=.".indexOf(a[b-1])&&(c=-1!="=.".indexOf(a[b-2])?c-2:c-1);var d=new Uint8Array(c),f=0;Da(a,function(e){d[f++]=e});return f!==c?d.subarray(0,f):d}
-function Da(a,b){function c(k){for(;d<a.length;){var l=a.charAt(d++),n=za[l];if(null!=n)return n;if(!/^[\s\xa0]*$/.test(l))throw Error("Unknown base64 encoding at char: "+l);}return k}Ba();for(var d=0;;){var f=c(-1),e=c(0),h=c(64),g=c(64);if(64===g&&-1===f)break;b(f<<2|e>>4);64!=h&&(b(e<<4&240|h>>2),64!=g&&b(h<<6&192|g))}}
-function Ba(){if(!za){za={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;5>c;c++){var d=a.concat(b[c].split(""));ya[c]=d;for(var f=0;f<d.length;f++){var e=d[f];void 0===za[e]&&(za[e]=f)}}}};var Ea="undefined"!==typeof Uint8Array;function Fa(a){return null==a||Ga(a)?a:"string"===typeof a?Ca(a):null}function Ga(a){return Ea&&null!=a&&a instanceof Uint8Array}var Ha={};var Ia;function Qa(a){if(a!==Ha)throw Error("illegal external caller");}function Ra(a,b){Qa(b);this.aa=a;if(null!=a&&0===a.length)throw Error("ByteString should be constructed with non-empty values");}function Sa(){return Ia||(Ia=new Ra(null,Ha))}function Ta(a){var b=a.aa;return null==b?"":"string"===typeof b?b:a.aa=Aa(b)};var r="function"===typeof Symbol&&"symbol"===typeof Symbol()?Symbol():void 0;function u(a,b){if(r)return a[r]|=b;if(void 0!==a.A)return a.A|=b;Object.defineProperties(a,{A:{value:b,configurable:!0,writable:!0,enumerable:!1}});return b}function Ua(a,b){r?a[r]&&(a[r]&=~b):void 0!==a.A&&(a.A&=~b)}function v(a){var b;r?b=a[r]:b=a.A;return null==b?0:b}function Va(a,b){r?a[r]=b:void 0!==a.A?a.A=b:Object.defineProperties(a,{A:{value:b,configurable:!0,writable:!0,enumerable:!1}})}
-function $a(a){u(a,1);return a}function w(a){return!!(v(a)&2)}function ab(a){u(a,16);return a}function bb(a,b){Va(b,(a|0)&-51)}function cb(a,b){Va(b,(a|18)&-41)};var db={};function eb(a){return null!==a&&"object"===typeof a&&!Array.isArray(a)&&a.constructor===Object}function fb(a){a instanceof Ra&&(Qa(Ha),a=a.aa||"");return a}var gb,hb=[];Va(hb,23);gb=Object.freeze(hb);function ib(a){if(w(a.i))throw Error("Cannot mutate an immutable Message");}function jb(a){var b=a.length;(b=b?a[b-1]:void 0)&&eb(b)?b.g=1:(b={},a.push((b.g=1,b)))};function kb(a){return a}function lb(a){return a};function mb(a,b){a=a||{};b=b||{};var c={},d;for(d in a)c[d]=0;for(var f in b)c[f]=0;for(var e in c)if(!nb(a[e],b[e]))return!1;return!0}function ob(a){return a&&"object"===typeof a?a.i||a:a}
-function nb(a,b){a=fb(a);b=fb(b);a=ob(a);b=ob(b);if(a==b)return!0;if(Ea){var c=Ga(a),d=Ga(b);if(c||d){if(!c)if("string"===typeof a)a=Fa(a);else return!1;if(d)d=b;else if("string"===typeof b)d=Fa(b);else return!1;if(a.length!==d.length)return!1;for(b=0;b<a.length;b++)if(a[b]!==d[b])return!1;return!0}}if(null==a&&Array.isArray(b)&&v(b)&1&&!b.length||null==b&&Array.isArray(a)&&v(a)&1&&!a.length)return!0;if(!va(a)||!va(b))return"number"===typeof a&&isNaN(a)||"number"===typeof b&&isNaN(b)?String(a)==String(b):
-!1;if(a.constructor!=b.constructor)return!1;if(a.constructor===Array){d=a;c=a=void 0;for(var f=Math.max(d.length,b.length),e=0;e<f;e++){var h=d[e],g=b[e];h&&h.constructor==Object&&(a=h,h=void 0);g&&g.constructor==Object&&(c=g,g=void 0);if(!nb(h,g))return!1}return a||c?(a=a||{},c=c||{},mb(a,c)):!0}if(a.constructor===Object)return mb(a,b);throw Error("Invalid type in JSPB array");};var pb;function qb(a){switch(typeof a){case "number":return isFinite(a)?a:String(a);case "object":if(a)if(Array.isArray(a)){if(0!==(v(a)&128))return a=Array.prototype.slice.call(a),jb(a),a}else{if(Ga(a))return Aa(a);if(a instanceof Ra)return Ta(a)}}return a};function rb(a,b,c,d){if(null!=a){if(Array.isArray(a))a=sb(a,b,c,void 0!==d);else if(eb(a)){var f={},e;for(e in a)f[e]=rb(a[e],b,c,d);a=f}else a=b(a,d);return a}}function sb(a,b,c,d){var f=v(a);d=d?!!(f&16):void 0;a=Array.prototype.slice.call(a);for(var e=0;e<a.length;e++)a[e]=rb(a[e],b,c,d);c(f,a);return a}function tb(a){return a.Y===db?a.toJSON():qb(a)}function ub(a,b){a&128&&jb(b)};function vb(a){return a.h||(a.h=a.i[a.u+a.H]={})}function x(a,b,c){return-1===b?null:b>=a.u?a.h?a.h[b]:void 0:c&&a.h&&(c=a.h[b],null!=c)?c:a.i[b+a.H]}function wb(a,b,c,d){ib(a);return y(a,b,c,d)}function y(a,b,c,d){a.V&&(a.V=void 0);if(b>=a.u||d)return vb(a)[b]=c,a;a.i[b+a.H]=c;(c=a.h)&&b in c&&delete c[b];return a}
-function xb(a,b,c,d,f){var e=x(a,b,d);Array.isArray(e)||(e=gb);var h=v(e);h&1||$a(e);if(f)h&2||u(e,2),c&1||Object.freeze(e);else{f=!(c&2);var g=h&2;c&1||!g?f&&h&16&&!g&&Ua(e,16):(e=$a(Array.prototype.slice.call(e)),y(a,b,e,d))}return e}function yb(a,b){return xb(a,b,0,!1,w(a.i))}
-function B(a,b,c,d){var f=w(a.i),e=xb(a,b,1,d,f),h=v(e);if(!(h&4)){Object.isFrozen(e)&&(e=$a(e.slice()),y(a,b,e,d));for(var g=0,k=0;g<e.length;g++){var l=c(e[g]);null!=l&&(e[k++]=l)}k<g&&(e.length=k);u(e,5);f&&(u(e,2),Object.freeze(e))}!f&&(h&2||Object.isFrozen(e))&&(e=Array.prototype.slice.call(e),u(e,5),zb(a,b,e,d));return e}function Ub(a){return null==a?a:"string"===typeof a?a?new Ra(a,Ha):Sa():a.constructor===Ra?a:Ga(a)?a.length?new Ra(new Uint8Array(a),Ha):Sa():void 0}
-function E(a,b){a=x(a,b);return null==a?0:a}function zb(a,b,c,d){if(null==c)c=gb;else{var f=v(c);1!==(f&1)&&(Object.isFrozen(c)&&(c=Array.prototype.slice.call(c)),Va(c,f|1))}return wb(a,b,c,d)}function G(a,b,c,d){ib(a);c!==d?y(a,b,c):y(a,b,void 0,!1);return a}var Vb=Symbol(void 0);function Wb(a,b,c,d){var f=x(a,c,d);var e=!1;var h=null==f||"object"!==typeof f||(e=Array.isArray(f))||f.Y!==db?e?new b(f):void 0:f;h!==f&&null!=h&&(y(a,c,h,d),u(h.i,v(a.i)&-33));return h}
-function H(a,b,c){if(a=Wb(a,b,c,!1))b=a;else if(a=b[Vb])b=a;else{a=new b;if(wa!==wa)throw Error("requires a valid immutable API token");w(a.i)||((c=a.V)&&nb(c.i,a.i)?a=c:(c=Xb(a,!0),u(c.i,2),a=a.V=c));b=b[Vb]=a}return b}function J(a,b,c){var d=void 0===d?!1:d;b=Wb(a,b,c,d);if(null==b)return b;if(!w(a.i)){var f=Yb(b);f!==b&&(b=f,y(a,c,b,d))}return b}
-function Zb(a,b,c,d,f){a.o||(a.o={});var e=a.o[c],h=xb(a,c,3,void 0,f);if(e)f||(Object.isFrozen(e)?d||(e=Array.prototype.slice.call(e),a.o[c]=e):d&&Object.freeze(e));else{e=[];var g=!!(v(a.i)&16),k=w(h);!f&&k&&(h=$a(Array.prototype.slice.call(h)),y(a,c,h));for(var l=k,n=0;n<h.length;n++){var t=h[n];var I=b;var A=g,F=!1;F=void 0===F?!1:F;A=void 0===A?!1:A;I=Array.isArray(t)?new I(A?ab(t):t):F?new I:void 0;void 0!==I&&(l=l||w(t),e.push(I),k&&u(I.i,2))}a.o[c]=e;a=h;Object.isFrozen(a)||(b=v(a)|33,Va(a,
-l?b&-9:b|8));(f||d&&k)&&u(e,2);(f||d)&&Object.freeze(e)}return e}function K(a,b,c){var d=w(a.i);b=Zb(a,b,c,d,d);a=xb(a,c,3,void 0,d);if(!(d||v(a)&8)){for(d=0;d<b.length;d++){c=b[d];var f=Yb(c);c!==f&&(b[d]=f,a[d]=b[d].i)}u(a,8)}return b}function M(a,b,c){ib(a);null==c&&(c=void 0);return y(a,b,c)}function $b(a,b,c,d){ib(a);if(null!=c){var f=$a([]);for(var e=!1,h=0;h<c.length;h++)f[h]=c[h].i,e=e||w(f[h]);a.o||(a.o={});a.o[b]=c;c=f;e?Ua(c,8):u(c,8)}else a.o&&(a.o[b]=void 0),f=gb;return y(a,b,f,d)}
-function ac(a,b,c,d){ib(a);var f=Zb(a,c,b,!1,!1);c=null!=d?d:new c;a=xb(a,b,2,void 0,!1);f.push(c);a.push(c.i);w(c.i)&&Ua(a,8);return c}function N(a,b){return P(x(a,b),"0")}function P(a,b){return null==a?b:a}function R(a,b){a=x(a,b);return P(null==a?a:!!a,!1)}function S(a,b){a=x(a,b);return P(null==a?a:+a,0)}function T(a,b){return P(x(a,b),0)};function bc(a){var b=v(a);if(b&2)return a;a=xa(a,cc);cb(b,a);Object.freeze(a);return a}function dc(a,b,c){c=void 0===c?cb:c;if(null!=a){if(Ea&&a instanceof Uint8Array)return a.length?new Ra(new Uint8Array(a),Ha):Sa();if(Array.isArray(a)){var d=v(a);if(d&2)return a;if(b&&!(d&32)&&(d&16||0===d))return Va(a,d|2),a;a=sb(a,dc,c,!0);b=v(a);b&4&&b&2&&Object.freeze(a);return a}return a.Y===db?cc(a):a}}function cc(a){if(w(a.i))return a;a=Xb(a,!0);u(a.i,2);return a}
-function Xb(a,b){var c=a.i,d=ab([]),f=a.constructor.h;f&&d.push(f);0!==(v(c)&128)&&jb(d);b=b||w(a.i)?cb:bb;f=a.constructor;pb=d;d=new f(d);pb=void 0;a.ca&&(d.ca=a.ca.slice());f=!!(v(c)&16);for(var e=0;e<c.length;e++){var h=c[e];if(e===c.length-1&&eb(h))for(var g in h){var k=+g;if(Number.isNaN(k))vb(d)[k]=h[k];else{var l=h[g],n=a.o&&a.o[k];n?$b(d,k,bc(n),!0):wb(d,k,dc(l,f,b),!0)}}else k=e-a.H,(l=a.o&&a.o[k])?$b(d,k,bc(l),!1):wb(d,k,dc(h,f,b),!1)}return d}
-function Yb(a){if(!w(a.i))return a;var b=Xb(a,!1);b.V=a;return b};function V(a,b,c){null==a&&(a=pb);pb=void 0;var d=this.constructor.u||0,f=0<d,e=this.constructor.h,h=!1;if(null==a){a=e?[e]:[];var g=!0;Va(a,48)}else{if(!Array.isArray(a))throw Error();if(e&&e!==a[0])throw Error();var k=u(a,0),l=k;if(g=0!==(16&l))(h=0!==(32&l))||(l|=32);if(f)if(128&l)d=0;else{if(0<a.length){var n=a[a.length-1];if(eb(n)&&"g"in n){d=0;l|=128;delete n.g;var t=!0,I;for(I in n){t=!1;break}t&&a.pop()}}}else if(128&l)throw Error();k!==l&&Va(a,l)}this.H=(e?0:-1)-d;this.o=void 0;this.i=a;
-a:{e=this.i.length;d=e-1;if(e&&(e=this.i[d],eb(e))){this.h=e;this.u=d-this.H;break a}void 0!==b&&-1<b?(this.u=Math.max(b,d+1-this.H),this.h=void 0):this.u=Number.MAX_VALUE}if(!f&&this.h&&"g"in this.h)throw Error('Unexpected "g" flag in sparse object of message that is not a group type.');if(c){b=g&&!h&&!0;f=this.u;var A;for(g=0;g<c.length;g++)h=c[g],h<f?(h+=this.H,(d=a[h])?ec(d,b):a[h]=gb):(A||(A=vb(this)),(d=A[h])?ec(d,b):A[h]=gb)}}V.prototype.toJSON=function(){return sb(this.i,tb,ub)};
-function ec(a,b){if(Array.isArray(a)){var c=v(a),d=1;!b||c&2||(d|=16);(c&d)!==d&&Va(a,c|d)}}V.prototype.Y=db;V.prototype.toString=function(){return this.i.toString()};var fc=void 0;function gc(a){var b=fc;fc=void 0;if(!Array.isArray(a))throw b=b?b()+"\n":"",Error(b+String(a));return a};function hc(a){return JSON.stringify([a.map(function(b){var c={};return[(c[b.ta]=b.message.toJSON(),c)]})])};function ic(a){this.h=a}ic.prototype.sa=function(){var a=encodeURIComponent;var b=hc(sa.apply(0,arguments));for(var c=[],d=0,f=0;f<b.length;f++){var e=b.charCodeAt(f);255<e&&(c[d++]=e&255,e>>=8);c[d++]=e}b=Aa(c,3);a=a(b);this.h("https://pagead2.googlesyndication.com/pagead/ping?e=3&d="+a)};function jc(a){V.call(this,a)}q(jc,V);function kc(a){V.call(this,a)}q(kc,V);function lc(a){V.call(this,a,-1,mc)}q(lc,V);var mc=[6];function nc(a){V.call(this,a,-1,oc)}q(nc,V);var oc=[2,3,4];function pc(a){V.call(this,a,-1,qc)}q(pc,V);var qc=[2];function rc(a){V.call(this,a,-1,sc)}q(rc,V);var sc=[1,3,10,7,8];function tc(a){V.call(this,a)}q(tc,V);function uc(a){V.call(this,a,-1,vc)}q(uc,V);var vc=[3];function wc(a){V.call(this,a,-1,xc)}q(wc,V);var xc=[3];function yc(a){V.call(this,a,-1,zc)}q(yc,V);var zc=[2,3,5];function Ac(a){V.call(this,a,-1,Bc)}q(Ac,V);function Cc(a){V.call(this,a,-1,Dc)}q(Cc,V);function Ec(a){V.call(this,a,-1,Fc)}q(Ec,V);var Bc=[1,2],Dc=[3,4,9],Fc=[3,4,5,6,7];function Gc(a){V.call(this,a,-1,Hc)}q(Gc,V);var Hc=[15];function Ic(a){V.call(this,a)}q(Ic,V);function Jc(a){V.call(this,a,-1,Kc)}q(Jc,V);var Kc=[1];function Lc(a){V.call(this,a)}q(Lc,V);function Mc(a){V.call(this,a)}q(Mc,V);function Nc(a){V.call(this,a,-1,Oc)}q(Nc,V);var Oc=[9,10,11,12,13,14,15,17];function Pc(a){V.call(this,a,-1,Qc)}q(Pc,V);var Qc=[1];function Zd(a){V.call(this,a)}q(Zd,V);function $d(a){V.call(this,a,-1,ae)}q($d,V);function W(a){return J(a,be,3)}function ce(a){V.call(this,a,-1,de)}q(ce,V);function ee(a){V.call(this,a)}q(ee,V);function be(a){V.call(this,a)}q(be,V);function fe(a){V.call(this,a)}q(fe,V);function ge(a){V.call(this,a)}q(ge,V);function he(a){var b=new ge;return G(b,1,a,0)}function ie(a){V.call(this,a,-1,je)}q(ie,V);function ke(a){V.call(this,a)}q(ke,V);var ae=[2],de=[1,2,3],je=[1,3];function le(a){V.call(this,a,-1,me)}q(le,V);var me=[10];function ne(a){a.sa.apply(a,ja(sa.apply(1,arguments).map(function(b){return{ta:9,message:b}})))};function oe(a,b){return!b||0>=b?a:Math.min(a,b)}function X(a,b,c){return b?b:c?c:a?1:0}function pe(a,b){return a&&0<a.length?a:b&&0<b.length?b:[]}function qe(a){a=null==a?void 0:E(a,9);return void 0===a?!1:[61,51,52].includes(a)};function re(a,b){if(!b||0>=b)return{j:0,B:2};var c=null==a?void 0:J(a,ie,18),d,f=null==a?void 0:null==(d=W(a))?void 0:J(d,ie,11);d=null==a?void 0:J(a,fe,7);if(!c&&!f){var e;f=null==a?void 0:null==(e=W(a))?void 0:J(e,fe,4);e=X(!0,null==d?void 0:S(d,1),null==f?void 0:S(f,1));a=X(!1,null==d?void 0:S(d,2),null==f?void 0:S(f,2));c=X(!1,null==d?void 0:S(d,3),null==f?void 0:S(f,3));var h,g;d=X(!1,null==d?void 0:null==(h=J(d,ge,5))?void 0:S(h,1),null==f?void 0:null==(g=J(f,ge,5))?void 0:S(g,1));h=new fe;
-g=G(h,1,e,0);g=G(g,2,a,0);g=G(g,3,c,0);f=he(d);M(g,5,f);return{j:b*e*(1-1/(1+Math.exp(-a*(Math.log(b/1E6)-d-c)))),B:1,J:4,ba:h}}if(c||f){e=X(!1,null==c?void 0:S(c,2),null==f?void 0:S(f,2));a=pe(null==c?void 0:B(c,3,Number),null==f?void 0:B(f,3,Number));c=pe(null==c?void 0:yb(c,1),null==f?void 0:yb(f,1));h=[];g=p(c);for(f=g.next();!f.done;f=g.next())switch(f.value){case 1:h.push(1E-6*b);break;case 2:var k=f=void 0,l=null==(f=d)?void 0:null==(k=J(f,ge,5))?void 0:S(k,1);h.push("number"===typeof l?Math.exp(l):
-0)}d=se(a,h);1===d.B?(b=new ie,b=zb(b,3,a),b=zb(b,1,c),b=G(b,2,e,0),d.ba=b,b=d):b=0>=e||1<e?d:{j:b*e,B:d.B,J:9}}else b={j:0,B:3};return b}
-function se(a,b){if(0===a.length||0>a[0])return{j:0,B:5};var c=b.length;if(a.length!==1+2*(1+c))return{j:0,B:6};for(var d=c+2,f=a[1],e=a[d],h=0;h<c;h++){var g=1+h;if(0>=b[h]){if(1E-9>Math.abs(a[1+g])&&1E-9>Math.abs(a[d+g]))continue;return{j:0,B:4}}var k=Math.log(b[h]);f+=a[1+g]*k;e+=a[d+g]*k}return{j:1E9*Math.exp(-.5*(-(f+e)+Math.sqrt((f-e)*(f-e)+4*a[0]))),B:1,J:8}};function te(a,b){var c=null==a?void 0:J(a,fe,6),d,f=null==a?void 0:null==(d=W(a))?void 0:J(d,fe,3);if(!b||0>=b)return{j:0,J:1};if(1===(null==a?void 0:T(a,17)))return{j:b,J:2};var e;if(!(null==a?0:null==(e=W(a))?0:R(e,2)))return{j:.85*b,J:2};d=X(!0,null==c?void 0:S(c,4),null==f?void 0:S(f,4));e=X(!0,null==c?void 0:S(c,1),null==f?void 0:S(f,1));var h=X(!1,null==c?void 0:S(c,2),null==f?void 0:S(f,2)),g=X(!1,null==c?void 0:S(c,3),null==f?void 0:S(f,3)),k,l,n=X(!1,null==c?void 0:null==(k=J(c,ge,5))?void 0:
-S(k,1),null==f?void 0:null==(l=J(f,ge,5))?void 0:S(l,1));l=X(!1,null==c?void 0:S(c,9),null==f?void 0:S(f,9));k=new fe;var t=G(k,1,e,0);t=G(t,2,h,0);t=G(t,3,g,0);t=G(t,4,d,0);t=G(t,9,l,0);var I=he(n);M(t,5,I);t=3;d=d*b*e*(1-1/(1+Math.exp(-h*(Math.log(d*b/1E6)-n-g))));d<l*b&&(d=l*b,t=6);e=1E6*(null==a?NaN:S(a,8));var A;c=null!=(A=null==c?void 0:S(c,8))?A:0;var F;if((null==a?0:null==(F=W(a))?0:R(F,6))&&d<e&&e<b){var O;a=null!=(O=null==f?void 0:S(f,7))?O:0;d=e+a*(0===c?Math.log(b/e):(b-e)/(c-e))*1E6;
-t=7}return{j:d,J:t,ba:k}};function ue(a,b){if(!(0<B(a,2,Number).length&&B(a,2,Number).length===yb(a,3).length&&B(a,2,Number).length===B(a,4,Number).length))return 0;for(var c=0,d=0,f=1,e=p(yb(a,3)),h=e.next();!h.done;h=e.next()){var g=0;switch(h.value){case 1:g=B(a,2,Number)[d]*(b.M?Math.pow(b.M,B(a,4,Number)[d]):0);break;case 2:c=g=B(a,2,Number)[d]*(b.X?Math.pow(b.X,B(a,4,Number)[d]):0);break;case 3:g=B(a,2,Number)[d]}if(0===g)return 0;f*=g;d+=1}0<S(a,7)&&(f=Math.min(f,S(a,7)*c*1E3));return 1E6*f}
-function ve(a,b){var c=0;b&&(0<K(b,nc,7).length?c=ue(K(b,nc,7)[0],a):0<K(b,nc,8).length&&(c=ue(K(b,nc,8)[0],a)));return c};var we={Ga:0,Ca:1,xa:2,za:3,ya:4,Da:5,Ea:6,Ha:7,Ba:8,va:9,Fa:10,Aa:11,wa:12};function xe(a,b,c){if(E(a,2)!==E(b,2))return c;var d=!1;switch(E(a,2)){case 1:a:{var f,e=new Set(null!=(f=yb(a,3))?f:[]);b=p(yb(b,3));for(f=b.next();!f.done;f=b.next())if(e.has(f.value)){d=!0;break a}d=!1}break;case 0:a:{f=new Set(null!=(e=B(a,4,lb,!1))?e:[]);b=p(B(b,4,lb,!1));for(e=b.next();!e.done;e=b.next())if(f.has(e.value)){d=!0;break a}d=!1}break;case 2:b=new ye(b);d=(f=J(a,yc,5))?ze(b,f):!1;break;case 3:a:{f=new Set;e=p(B(a,9,Ub));for(d=e.next();!d.done;d=e.next())f.add(Ta(d.value));if(0===
-f.size)d=!0;else{b=p(B(b,6,Ub));for(e=b.next();!e.done;e=b.next())if(f.has(Ta(e.value))){d=!0;break a}d=!1}}break;case 4:d=Ae(a,b)}return R(a,6)?d?null:c:d?c:null}
-function Ae(a,b){a=J(a,uc,10);if(void 0===a)return!1;var c=K(b,wc,7);if(0===c.length)return!1;b=!0;c=p(c);for(var d=c.next();!d.done;d=c.next())if(d=d.value,T(d,1)===T(a,1)&&T(d,2)===T(a,2)){b&&(b=!1);var f=yb(d,3);if(0===f.length)return!1;d=!0;f=p(f);for(var e=f.next();!e.done;e=f.next()){e=e.value;var h=Math.floor(e/32),g=yb(a,3);if(!(h>=g.length||0!==(g[h]>>>e%32)%2)){d=!1;break}}if(d)return!0}return b}
-function ze(a,b){var c=E(b,1),d=K(b,tc,3),f=K(b,yc,2);switch(c){case 2:c=d.every(function(e){return Be(a,e)})&&f.every(function(e){return ze(a,e)});break;case 1:c=d.some(function(e){return Be(a,e)})||f.some(function(e){return ze(a,e)});break;default:throw Error("unexpected value "+c+"!");}return R(b,4)?!c:c}function ye(a){this.h=new Map;a=p(K(a,tc,5));for(var b=a.next();!b.done;b=a.next()){var c=b.value;b=P(x(c,1),0);c=P(x(c,2),0);var d=this.h.get(b);d||(d=new Set,this.h.set(b,d));d.add(c)}}
-function Be(a,b){var c=P(x(b,2),0);return(a=a.h.get(P(x(b,1),0)))?a.has(c):!1};function Ce(a,b){a=p((null==b?void 0:b.get(a))||[]);for(b=a.next();!b.done;b=a.next())if(b=b.value,b.count+1>b.ra)return!1;return!0};function De(a){a=a.split("!");for(var b="-1",c=0;c<a.length;c++)a[c].match(/^\dm\d+/)?c+=+a[c].substring(2):a[c].match(/^\d{2}m\d+/)?c+=+a[c].substring(3):a[c].match(/^1j\d+/)&&(b=a[c].substring(2));return b}
-function Ee(a,b){if(!a.pa)return 1;var c,d=null==(c=a.da)?void 0:c.some(function(h){var g;return null==(g=b.ga)?void 0:g.includes(h,0)}),f;c=null!=(f=b.interestGroupName)?f:void 0;if(void 0===c)return 10;f=De(c);if("-1"===f)return 11;var e;a=null==(e=a.da)?void 0:e.includes(f,0);return d&&!a?10:1};function Fe(a,b){return null==a.Z?!0:!a.Z.some(function(c){var d;return null==(d=b.ga)?void 0:d.includes(c,0)})};function Ge(a,b){return He(0,(null==a?void 0:K(a,pc,1))||[],(null==b?void 0:K(b,pc,1))||[])}function Ie(a,b){return He(1,(null==a?void 0:K(a,pc,2))||[],(null==b?void 0:K(b,pc,3))||[])}function Je(a,b){return He(1,(null==a?void 0:K(a,pc,3))||[],(null==b?void 0:K(b,pc,3))||[])}
-function He(a,b,c){var d=0,f=new Map;b=p(b);for(var e=b.next();!e.done;e=b.next())d=e.value,f.set(P(x(d,1),""),d),d=S(d,3);b=null;c=p(c);for(e=c.next();!e.done;e=c.next()){var h=e.value;d=S(h,3);if(e=f.get(P(x(h,1),""))){a:{b=a;e=B(e,2,Number);h=B(h,2,Number);if(e.length===h.length){for(var g=0,k=0;k<e.length;k++)g+=e[k]*h[k];e=g}else e=void 0;if(void 0!==e)switch(b){case 0:b=1/(1+Math.exp(-1*e));break a;case 1:b=Math.exp(e);break a}b=void 0}if(void 0!==b)return b;b=d}}var l;return null!=(l=b)?l:
-d};function Ke(a,b,c){"0"===a||c.has(a)||c.set(a,b.filter(function(d){return 0<T(d,3)}).map(function(d){var f=T(d,3);switch(E(d,1)){case 6:d=60*T(d,2);break;case 1:d=3600*T(d,2);break;case 2:d=86400*T(d,2);break;case 3:d=604800*T(d,2);break;case 4:d=2592E3*T(d,2);break;case 5:d=null;break;default:f=d=0}return{fa:d,ra:f,count:0}}))}function Le(a,b,c){if(b=c.get(b))for(b=p(b),c=b.next();!c.done;c=b.next())c=c.value,(null===c.fa||T(a,1)<=c.fa)&&c.count++};function Me(a){V.call(this,a,-1,Ne)}q(Me,V);var Ne=[1];var Oe={ad:{},bid:0,render:"",allowComponentAuction:!0};function Pe(){new Me;return function(a,b,c,d,f){return Qe(a,c,d,f)}}
-function Qe(a,b,c,d){b=b?new $d(gc(b)):void 0;var f,e;if(!b||!(K(b,ee,2).length||(null==(f=W(b))?0:R(f,1))||(null==(e=W(b))?0:R(e,5))))return Oe;f=new Jc(gc(a.userBiddingSignals));e=a.ads.map(function(g){return{renderUrl:g.renderUrl,metadata:new jc(gc(g.metadata))}});c=c[a.name]?new Pc(gc(c[a.name])):void 0;var h=d.prevWins.map(function(g){var k=new kc;k=G(k,1,g[0],0);g=new jc(gc(g[1].metadata));return M(k,2,g)});return Re(a.name,f,e,d,h,c,b)}
-function Re(a,b,c,d,f,e,h){var g=null,k=null,l=null;if(h&&(R(H(h,Zd,12),1)||R(H(h,Zd,12),2))){var n=new le;var t=G(n,2,0,0);var I=G(t,5,a,"");var A=G(I,7,!1,!1);var F=M(A,8,h);g=G(F,9,P(x(h,4),""),"");var O=globalThis.forDebuggingOnly;R(H(h,Zd,12),1)&&(k=new ic(O.reportAdAuctionWin));R(H(h,Zd,12),2)&&(l=new ic(O.reportAdAuctionLoss));if(R(H(h,Zd,12),5)){var Wa=M(g,6,b),ea=new lc;var Xa=G(ea,1,d.topWindowHostname,"");var Y=G(Xa,2,d.seller,"");var Q=G(Y,3,d.topLevelSeller,"");var We=G(Q,4,d.joinCount,
-0);var Xe=G(We,5,d.bidCount,0);var Ye=$b(Xe,6,f);var Ze=G(Ye,7,d.dataVersion,0);M(Wa,11,Ze);e&&M(g,3,e)}}var Ya=g,Rc,D={ea:null!=(Rc=null==h?void 0:W(h))?Rc:void 0,T:new Map,N:new Map,O:new Map,P:new Map,W:new Map,interestGroupName:null!=a?a:void 0,ua:E(b,2),ia:d.joinCount},ka=new Map;if(e){for(var Sc=p(K(e,Nc,1)),Ab=Sc.next();!Ab.done;Ab=Sc.next()){var L=Ab.value,$e=Se(N(L,1),N(L,2),N(L,3));ka.set($e,L);Ke(N(L,2),K(L,Lc,9),D.T);Ke(N(L,1),K(L,Lc,10),D.N);Ke(N(L,6),K(L,Lc,11),D.O);Ke(N(L,7),K(L,Lc,
-12),D.P);Ke(N(L,8),K(L,Lc,13),D.W)}for(var Tc=p(f),Bb=Tc.next();!Bb.done;Bb=Tc.next()){var Z=Bb.value;D.T&&Le(Z,N(H(Z,jc,2),2),D.T);D.N&&Le(Z,N(H(Z,jc,2),1),D.N);D.O&&Le(Z,N(H(Z,jc,2),4),D.O);D.P&&Le(Z,N(H(Z,jc,2),5),D.P);D.W&&Le(Z,N(H(Z,jc,2),6),D.W)}}var Uc=new Map;if(h)for(var Vc=p(K(h,ee,2)),Cb=Vc.next();!Cb.done;Cb=Vc.next()){var Db=Cb.value,af=Se(N(Db,1),N(Db,2),"");Uc.set(af,S(Db,3))}for(var Wc=[],Xc=p(c),Eb=Xc.next();!Eb.done;Eb=Xc.next()){var U=Eb.value,z={renderUrl:U.renderUrl,D:N(U.metadata,
-1),G:N(U.metadata,2),L:N(U.metadata,3),S:N(U.metadata,4),R:N(U.metadata,5),U:N(U.metadata,6),ja:N(U.metadata,7),ka:N(U.metadata,8),la:N(U.metadata,9),ma:N(U.metadata,10),l:0,I:0},pa=Se(z.D,z.G,z.L);z.K=Uc.get(Se(z.D,z.G,""));if(!z.K){var Yc=void 0,Zc=void 0,$c=void 0,ad=void 0;if(!(null==(Yc=h)?0:null==(Zc=W(Yc))?0:R(Zc,1))&&!(null==($c=h)?0:null==(ad=W($c))?0:R(ad,5))){Ya&&Te(Ya,z,5,1);continue}else if(!ka.get(pa)){Ya&&Te(Ya,z,6,1);continue}var bd=void 0,cd=void 0;z.v=null!=(cd=null==(bd=ka.get(pa))?
-void 0:J(bd,rc,4))?cd:void 0}var dd=void 0,ed=void 0;z.F=null!=(ed=null==(dd=ka.get(pa))?void 0:J(dd,Ac,5))?ed:void 0;var fd=void 0,gd=void 0,hd=null!=(gd=null==(fd=ka.get(pa))?void 0:K(fd,Mc,17))?gd:void 0;if(hd)for(var id=p(hd),Fb=id.next();!Fb.done;Fb=id.next()){var Ja=Fb.value;if(z.ja===N(Ja,1)&&z.ka===N(Ja,2)&&z.la===N(Ja,3)&&z.ma===N(Ja,4)){z.F||(z.F=new Ac);var Gb=J(Ja,Ac,5);if(Gb){for(var jd=p(K(Gb,Cc,1)),Hb=jd.next();!Hb.done;Hb=jd.next())ac(z.F,1,Cc,Hb.value);for(var kd=p(K(Gb,Ec,2)),Ib=
-kd.next();!Ib.done;Ib=kd.next())ac(z.F,2,Ec,Ib.value)}}}var ld=void 0,md=void 0;z.Z=null!=(md=null==(ld=ka.get(pa))?void 0:B(ld,14,kb))?md:void 0;var nd=void 0,od=void 0;z.da=null!=(od=null==(nd=ka.get(pa))?void 0:B(nd,15,kb))?od:void 0;var pd=void 0,qd=void 0;z.pa=null!=(qd=null==(pd=ka.get(pa))?void 0:R(pd,16))?qd:!1;Wc.push(z)}var Jb=null==h?void 0:J(h,Ac,5);if(Jb){for(var rd=new Map,sd=new Map,td=p(K(Jb,Cc,1)),Kb=td.next();!Kb.done;Kb=td.next()){var ud=Kb.value;rd.set(E(ud,1),ud)}for(var vd=p(K(Jb,
-Ec,2)),Lb=vd.next();!Lb.done;Lb=vd.next()){var wd=Lb.value;sd.set(E(wd,1),wd)}D.na=rd;D.oa=sd}var xd;D.ga=null!=(xd=B(b,1,kb))?xd:void 0;var ha={ads:Wc,signals:D};var Za=ha.signals;if(1!==Za.ua)var Mb=!0;else{var yd;if(null!=(yd=Za.ea)&&R(yd,8)){var zd;Mb=Za.ia<(null==(zd=Za.ea)?void 0:T(zd,9))?!1:!0}else Mb=!1}var Nb=Mb?1:8;if(1!==Nb&&null!==g)for(var Ad=p(ha.ads),Ob=Ad.next();!Ob.done;Ob=Ad.next())Te(g,Ob.value,Nb,2);var Bd=Oe,Cd=ha;if(1===Nb){for(var aa=g,Dd=null==h?void 0:W(h),Ed=[],Fd=new Map,
-Gd=p(ha.ads),Pb=Gd.next();!Pb.done;Pb=Gd.next()){var C=Pb.value,Hd=void 0;if(void 0!==Dd&&(null==(Hd=Dd)?0:R(Hd,10))&&(C.renderUrl.includes("/td/adfetch/dv3")||qe(C.v)))aa&&Te(aa,C,12,3);else{var Ka=ha.signals;if(!Ce(C.G,Ka.T)||!Ce(C.D,Ka.N)||C.S&&!Ce(C.S,Ka.O)||C.R&&!Ce(C.R,Ka.P)||C.U&&!Ce(C.U,Ka.W))aa&&Te(aa,C,3,3);else{if(C.F){var Id=ha.signals,Jd=Id.na,Kd=Id.oa,Ld=C.F;if(Jd&&Kd&&Ld)a:{for(var bf=Jd,cf=Kd,Md=Ld,Nd=p(K(Md,Cc,1)),Qb=Nd.next();!Qb.done;Qb=Nd.next()){var La=Qb.value,Ma=E(La,1),Rb=
-cf.get(Ma);if(Rb){var Na=null;if(R(La,7)){var Oa=Fd.get(Ma),Od=!0,Pd=P(x(La,8),0);if(void 0===Oa)Oa=new Map,Fd.set(Ma,Oa);else{var Sb=Oa.get(Pd);if(Sb){var Pa=Sb;break a}null===Sb&&(Od=!1)}Od&&(Na=xe(La,Rb,Ma),Oa.set(Pd,Na))}else Na=xe(La,Rb,Ma);if(Na){Pa=Na;break a}}}for(var Qd=p(K(Md,Ec,2)),Tb=Qd.next();!Tb.done;Tb=Qd.next()){var Rd=Tb.value,Sd=E(Rd,1),Td=bf.get(Sd);if(Td){var Ud=xe(Td,Rd,Sd);if(Ud){Pa=Ud;break a}}}Pa=null}else Pa=null;var Vd=Pa;if(Vd){aa&&Te(aa,C,4,3,Vd);continue}}if(Fe(C,ha.signals)){var Wd=
-Ee(C,ha.signals);1!==Wd?aa&&Te(aa,C,Wd,3):Ed.push(C)}else aa&&Te(aa,C,7,3)}}}Cd={ads:Ed,signals:ha.signals};Bd=Ue(Cd,g,h).ha}if(void 0!==h&&null!==g){if(k){var Xd=g,ef=k;G(Xd,2,1,0);ne(ef,Xd)}if(l){var Yd=g,ff=l;G(Yd,2,2,0);ne(ff,Yd)}}return Bd}
-function Te(a,b,c,d,f){a=ac(a,10,Ic);d=G(a,3,d,0);var e;var h=new Gc;h=G(h,1,b.renderUrl,"");h=G(h,2,b.D,"");h=G(h,3,b.G,"");h=G(h,4,b.L,"");h=G(h,12,b.l,0);h=G(h,13,b.I,0);var g=null!=(e=b.qa)?e:!1;e=G(h,16,g,!1);void 0!==b.S&&G(e,5,b.S,"");void 0!==b.R&&G(e,6,b.R,"");void 0!==b.U&&G(e,7,b.U,"");void 0!==b.v&&M(e,8,b.v);void 0!==b.X&&G(e,9,b.X,0);void 0!==b.M&&G(e,10,b.M,0);void 0!==b.K&&G(e,11,b.K,0);void 0!==b.F&&M(e,14,b.F);var k;b=p(null!=(k=b.Z)?k:[]);for(h=b.next();!h.done;h=b.next())k=e,h=
-h.value,ib(k),xb(k,15,2,!1,!1).push(h);M(d,1,e);void 0!==f&&G(a,5,f,0);Object.values(we).includes(c)&&G(a,2,c,0)}
-function Ue(a,b,c){for(var d=[],f=[],e=p(a.ads),h=e.next();!h.done;h=e.next())if(h=h.value,null!=h.K)h.l=h.K,h.qa=!0,d.push(h);else{var g=void 0,k=void 0;if(null==(g=c)?0:null==(k=W(g))?0:R(k,1))qe(h.v)?(g=void 0,h.M=Je(null==(g=c)?void 0:J(g,ce,1),h.v)):(g=void 0,h.X=Ge(null==(g=c)?void 0:J(g,ce,1),h.v),g=void 0,h.M=Ie(null==(g=c)?void 0:J(g,ce,1),h.v)),h.l=ve(h,h.v),h.l||(k=g=void 0,h.l=null!=(k=null==(g=h.v)?void 0:S(g,6))?k:0);else if(k=g=void 0,null==(g=c)?0:null==(k=W(g))?0:R(k,5))k=g=void 0,
-h.l=null!=(k=null==(g=h.v)?void 0:S(g,6))?k:0;k=g=void 0;if(null==(g=c)?0:null==(k=W(g))?0:R(k,7)){var l=k=g=void 0,n=void 0,t=void 0,I=void 0;if(h.D===(null==(g=c)?void 0:null==(k=J(g,ke,16))?void 0:N(k,2))&&h.G===(null==(l=c)?void 0:null==(n=J(l,ke,16))?void 0:N(n,3))&&a.signals.interestGroupName===(null==(t=c)?void 0:null==(I=J(t,ke,16))?void 0:P(x(I,1),""))){if(k=g=void 0,null==(g=c)?0:null==(k=J(g,ke,16))?0:R(k,7))l=k=g=void 0,n=null!=(l=null==(g=c)?void 0:null==(k=J(g,ke,16))?void 0:S(k,5))?
-l:0,h.l=0===n?1:n}else h.l=0}f.push(h)}d={renderUrl:"",D:"",G:"",L:"",l:0,I:0};var A,F;if((null==c?0:null==(A=W(c))?0:R(A,7))&&(null==c?0:null==(F=J(c,ke,16))?0:R(F,7)))c=a.ads.reduce(function(Y,Q){return Y.l<Q.l?Q:Y},d),c.I=c.l;else{A=a.ads.reduce(function(Y,Q){return!qe(Q.v)&&Y.l<Q.l?Q:Y},d);d=a.ads.reduce(function(Y,Q){return qe(Q.v)&&Y.l<Q.l?Q:Y},d);F=te(c,null==A?void 0:A.l);var O,Wa;F.j=oe(F.j,null==c?void 0:null==(O=W(c))?void 0:null==(Wa=J(O,fe,3))?void 0:S(Wa,6));O=re(c,null==d?void 0:d.l);
-var ea,Xa;O.j=oe(O.j,null==c?void 0:null==(ea=W(c))?void 0:null==(Xa=J(ea,fe,4))?void 0:S(Xa,6));F.j>O.j?(c=A,c.I=F.j):(c=d,c.I=O.j)}if(b)for(a=p(a.ads),h=a.next();!h.done;h=a.next())ea=h.value,Te(b,ea,Se(ea.D,ea.G,ea.L)===Se(c.D,c.G,c.L)?1:9,4);return{ha:{ad:{},bid:c.I/1E6,render:c.renderUrl,allowComponentAuction:!0},debugInfo:void 0}}function Se(a,b,c){return a.concat("+",b,"+",c)};function Ve(a,b,c,d,f){a={renderUrl:a.render_uri,metadata:a.metadata.metadata};f={owner:f.owner,name:f.name,biddingLogicUrl:"",userBiddingSignals:f.user_bidding_signals.signals,ads:[a]};a={topWindowHostname:"",seller:"",joinCount:0,bidCount:0,prevWins:[[0,a]]};b=Pe()(f,b,c.signals,d,a);c="";"string"===typeof b.render?c=b.render:(d=b.render,0<d.length&&(c=d[0]));return{status:0,ad:{render_uri:c,metadata:b.ad},bid:b.bid}};var df=globalThis;df.generateBid=function(a,b,c,d,f,e){return Ve(a,b,c,d,e)};df.generateBidIterative=function(a,b,c,d,f,e){f=(new Date).getTime();var h=[];a=p(a);for(var g=a.next();!g.done;g=a.next())g=Ve(g.value,b,c,d,e),h.push(g);return{responses:h,status:0,duration:(new Date).getTime()-f}};
diff --git a/apct-tests/perftests/rubidium/assets/rubidium_scoring_logic_compiled.js b/apct-tests/perftests/rubidium/assets/rubidium_scoring_logic_compiled.js
deleted file mode 100644
index 406a45d..0000000
--- a/apct-tests/perftests/rubidium/assets/rubidium_scoring_logic_compiled.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-
- Copyright The Closure Library Authors.
- SPDX-License-Identifier: Apache-2.0
-*/
-'use strict';function aa(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}}var ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};
-function ca(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");}var ea=ca(this);function n(a,b){if(b)a:{var c=ea;a=a.split(".");for(var d=0;d<a.length-1;d++){var f=a[d];if(!(f in c))break a;c=c[f]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}}
-n("Symbol",function(a){function b(e){if(this instanceof b)throw new TypeError("Symbol is not a constructor");return new c(d+(e||"")+"_"+f++,e)}function c(e,g){this.h=e;ba(this,"description",{configurable:!0,writable:!0,value:g})}if(a)return a;c.prototype.toString=function(){return this.h};var d="jscomp_symbol_"+(1E9*Math.random()>>>0)+"_",f=0;return b});
-n("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=ea[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&ba(d.prototype,a,{configurable:!0,writable:!0,value:function(){return fa(aa(this))}})}return a});function fa(a){a={next:a};a[Symbol.iterator]=function(){return this};return a}
-function p(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:aa(a)}}function ha(a){if(!(a instanceof Array)){a=p(a);for(var b,c=[];!(b=a.next()).done;)c.push(b.value);a=c}return a}var ia="function"==typeof Object.create?Object.create:function(a){function b(){}b.prototype=a;return new b},ja;
-if("function"==typeof Object.setPrototypeOf)ja=Object.setPrototypeOf;else{var ka;a:{var la={a:!0},ma={};try{ma.__proto__=la;ka=ma.a;break a}catch(a){}ka=!1}ja=ka?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}var na=ja;
-function r(a,b){a.prototype=ia(b.prototype);a.prototype.constructor=a;if(na)na(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.la=b.prototype}function oa(){for(var a=Number(this),b=[],c=a;c<arguments.length;c++)b[c-a]=arguments[c];return b}function t(a,b){return Object.prototype.hasOwnProperty.call(a,b)}
-n("WeakMap",function(a){function b(k){this.h=(h+=Math.random()+1).toString();if(k){k=p(k);for(var l;!(l=k.next()).done;)l=l.value,this.set(l[0],l[1])}}function c(){}function d(k){var l=typeof k;return"object"===l&&null!==k||"function"===l}function f(k){if(!t(k,g)){var l=new c;ba(k,g,{value:l})}}function e(k){var l=Object[k];l&&(Object[k]=function(m){if(m instanceof c)return m;Object.isExtensible(m)&&f(m);return l(m)})}if(function(){if(!a||!Object.seal)return!1;try{var k=Object.seal({}),l=Object.seal({}),
-m=new a([[k,2],[l,3]]);if(2!=m.get(k)||3!=m.get(l))return!1;m.delete(k);m.set(l,4);return!m.has(k)&&4==m.get(l)}catch(q){return!1}}())return a;var g="$jscomp_hidden_"+Math.random();e("freeze");e("preventExtensions");e("seal");var h=0;b.prototype.set=function(k,l){if(!d(k))throw Error("Invalid WeakMap key");f(k);if(!t(k,g))throw Error("WeakMap key fail: "+k);k[g][this.h]=l;return this};b.prototype.get=function(k){return d(k)&&t(k,g)?k[g][this.h]:void 0};b.prototype.has=function(k){return d(k)&&t(k,
-g)&&t(k[g],this.h)};b.prototype.delete=function(k){return d(k)&&t(k,g)&&t(k[g],this.h)?delete k[g][this.h]:!1};return b});
-n("Map",function(a){function b(){var h={};return h.v=h.next=h.head=h}function c(h,k){var l=h.h;return fa(function(){if(l){for(;l.head!=h.h;)l=l.v;for(;l.next!=l.head;)return l=l.next,{done:!1,value:k(l)};l=null}return{done:!0,value:void 0}})}function d(h,k){var l=k&&typeof k;"object"==l||"function"==l?e.has(k)?l=e.get(k):(l=""+ ++g,e.set(k,l)):l="p_"+k;var m=h.i[l];if(m&&t(h.i,l))for(h=0;h<m.length;h++){var q=m[h];if(k!==k&&q.key!==q.key||k===q.key)return{id:l,list:m,index:h,l:q}}return{id:l,list:m,
-index:-1,l:void 0}}function f(h){this.i={};this.h=b();this.size=0;if(h){h=p(h);for(var k;!(k=h.next()).done;)k=k.value,this.set(k[0],k[1])}}if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var h=Object.seal({x:4}),k=new a(p([[h,"s"]]));if("s"!=k.get(h)||1!=k.size||k.get({x:4})||k.set({x:4},"t")!=k||2!=k.size)return!1;var l=k.entries(),m=l.next();if(m.done||m.value[0]!=h||"s"!=m.value[1])return!1;m=l.next();return m.done||4!=m.value[0].x||
-"t"!=m.value[1]||!l.next().done?!1:!0}catch(q){return!1}}())return a;var e=new WeakMap;f.prototype.set=function(h,k){h=0===h?0:h;var l=d(this,h);l.list||(l.list=this.i[l.id]=[]);l.l?l.l.value=k:(l.l={next:this.h,v:this.h.v,head:this.h,key:h,value:k},l.list.push(l.l),this.h.v.next=l.l,this.h.v=l.l,this.size++);return this};f.prototype.delete=function(h){h=d(this,h);return h.l&&h.list?(h.list.splice(h.index,1),h.list.length||delete this.i[h.id],h.l.v.next=h.l.next,h.l.next.v=h.l.v,h.l.head=null,this.size--,
-!0):!1};f.prototype.clear=function(){this.i={};this.h=this.h.v=b();this.size=0};f.prototype.has=function(h){return!!d(this,h).l};f.prototype.get=function(h){return(h=d(this,h).l)&&h.value};f.prototype.entries=function(){return c(this,function(h){return[h.key,h.value]})};f.prototype.keys=function(){return c(this,function(h){return h.key})};f.prototype.values=function(){return c(this,function(h){return h.value})};f.prototype.forEach=function(h,k){for(var l=this.entries(),m;!(m=l.next()).done;)m=m.value,
-h.call(k,m[1],m[0],this)};f.prototype[Symbol.iterator]=f.prototype.entries;var g=0;return f});n("Number.isNaN",function(a){return a?a:function(b){return"number"===typeof b&&isNaN(b)}});function pa(a,b){a instanceof String&&(a+="");var c=0,d=!1,f={next:function(){if(!d&&c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d=!0;return{done:!0,value:void 0}}};f[Symbol.iterator]=function(){return f};return f}n("Array.prototype.values",function(a){return a?a:function(){return pa(this,function(b,c){return c})}});
-n("Set",function(a){function b(c){this.h=new Map;if(c){c=p(c);for(var d;!(d=c.next()).done;)this.add(d.value)}this.size=this.h.size}if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var c=Object.seal({x:4}),d=new a(p([c]));if(!d.has(c)||1!=d.size||d.add(c)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var f=d.entries(),e=f.next();if(e.done||e.value[0]!=c||e.value[1]!=c)return!1;e=f.next();return e.done||e.value[0]==c||4!=e.value[0].x||
-e.value[1]!=e.value[0]?!1:f.next().done}catch(g){return!1}}())return a;b.prototype.add=function(c){c=0===c?0:c;this.h.set(c,c);this.size=this.h.size;return this};b.prototype.delete=function(c){c=this.h.delete(c);this.size=this.h.size;return c};b.prototype.clear=function(){this.h.clear();this.size=0};b.prototype.has=function(c){return this.h.has(c)};b.prototype.entries=function(){return this.h.entries()};b.prototype.values=function(){return this.h.values()};b.prototype.keys=b.prototype.values;b.prototype[Symbol.iterator]=
-b.prototype.values;b.prototype.forEach=function(c,d){var f=this;this.h.forEach(function(e){return c.call(d,e,e,f)})};return b});n("globalThis",function(a){return a||ea});n("Object.values",function(a){return a?a:function(b){var c=[],d;for(d in b)t(b,d)&&c.push(b[d]);return c}});n("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});
-n("Array.prototype.includes",function(a){return a?a:function(b,c){var d=this;d instanceof String&&(d=String(d));var f=d.length;c=c||0;for(0>c&&(c=Math.max(c+f,0));c<f;c++){var e=d[c];if(e===b||Object.is(e,b))return!0}return!1}});
-n("String.prototype.includes",function(a){return a?a:function(b,c){if(null==this)throw new TypeError("The 'this' value for String.prototype.includes must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype.includes must not be a regular expression");return-1!==this.indexOf(b,c||0)}});function qa(a){var b=typeof a;return"object"==b&&null!=a||"function"==b};var ra={};var sa=Array.prototype.map?function(a,b){return Array.prototype.map.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=Array(c),f="string"===typeof a?a.split(""):a,e=0;e<c;e++)e in f&&(d[e]=b.call(void 0,f[e],e,a));return d};var ta={},u=null;function ua(a,b){void 0===b&&(b=0);va();b=ta[b];for(var c=Array(Math.floor(a.length/3)),d=b[64]||"",f=0,e=0;f<a.length-2;f+=3){var g=a[f],h=a[f+1],k=a[f+2],l=b[g>>2];g=b[(g&3)<<4|h>>4];h=b[(h&15)<<2|k>>6];k=b[k&63];c[e++]=l+g+h+k}l=0;k=d;switch(a.length-f){case 2:l=a[f+1],k=b[(l&15)<<2]||d;case 1:a=a[f],c[e]=b[a>>2]+b[(a&3)<<4|l>>4]+k+d}return c.join("")}
-function wa(a){var b=a.length,c=3*b/4;c%3?c=Math.floor(c):-1!="=.".indexOf(a[b-1])&&(c=-1!="=.".indexOf(a[b-2])?c-2:c-1);var d=new Uint8Array(c),f=0;xa(a,function(e){d[f++]=e});return f!==c?d.subarray(0,f):d}
-function xa(a,b){function c(k){for(;d<a.length;){var l=a.charAt(d++),m=u[l];if(null!=m)return m;if(!/^[\s\xa0]*$/.test(l))throw Error("Unknown base64 encoding at char: "+l);}return k}va();for(var d=0;;){var f=c(-1),e=c(0),g=c(64),h=c(64);if(64===h&&-1===f)break;b(f<<2|e>>4);64!=g&&(b(e<<4&240|g>>2),64!=h&&b(g<<6&192|h))}}
-function va(){if(!u){u={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;5>c;c++){var d=a.concat(b[c].split(""));ta[c]=d;for(var f=0;f<d.length;f++){var e=d[f];void 0===u[e]&&(u[e]=f)}}}};var ya="undefined"!==typeof Uint8Array;function za(a){return null==a||v(a)?a:"string"===typeof a?wa(a):null}function v(a){return ya&&null!=a&&a instanceof Uint8Array}var w={};var Aa;function Ba(a){if(a!==w)throw Error("illegal external caller");}function x(a,b){Ba(b);this.H=a;if(null!=a&&0===a.length)throw Error("ByteString should be constructed with non-empty values");}function Ca(){return Aa||(Aa=new x(null,w))}function Da(a){var b=a.H;return null==b?"":"string"===typeof b?b:a.H=ua(b)};var y="function"===typeof Symbol&&"symbol"===typeof Symbol()?Symbol():void 0;function z(a,b){if(y)return a[y]|=b;if(void 0!==a.u)return a.u|=b;Object.defineProperties(a,{u:{value:b,configurable:!0,writable:!0,enumerable:!1}});return b}function Ea(a,b){y?a[y]&&(a[y]&=~b):void 0!==a.u&&(a.u&=~b)}function A(a){var b;y?b=a[y]:b=a.u;return null==b?0:b}function B(a,b){y?a[y]=b:void 0!==a.u?a.u=b:Object.defineProperties(a,{u:{value:b,configurable:!0,writable:!0,enumerable:!1}})}
-function C(a){z(a,1);return a}function E(a){return!!(A(a)&2)}function Fa(a){z(a,16);return a}function Ga(a,b){B(b,(a|0)&-51)}function Ha(a,b){B(b,(a|18)&-41)};var F={};function H(a){return null!==a&&"object"===typeof a&&!Array.isArray(a)&&a.constructor===Object}var Ia;function Ja(a){a instanceof x&&(Ba(w),a=a.H||"");return a}var I,Ka=[];B(Ka,23);I=Object.freeze(Ka);function J(a){if(E(a.j))throw Error("Cannot mutate an immutable Message");}function La(a){var b=a.length;(b=b?a[b-1]:void 0)&&H(b)?b.g=1:(b={},a.push((b.g=1,b)))};function Ma(a){return a}function Na(a){return a};function Oa(a,b){a=a||{};b=b||{};var c={},d;for(d in a)c[d]=0;for(var f in b)c[f]=0;for(var e in c)if(!Pa(a[e],b[e]))return!1;return!0}function Qa(a){return a&&"object"===typeof a?a.j||a:a}
-function Pa(a,b){a=Ja(a);b=Ja(b);a=Qa(a);b=Qa(b);if(a==b)return!0;if(ya){var c=v(a),d=v(b);if(c||d){if(!c)if("string"===typeof a)a=za(a);else return!1;if(d)d=b;else if("string"===typeof b)d=za(b);else return!1;if(a.length!==d.length)return!1;for(b=0;b<a.length;b++)if(a[b]!==d[b])return!1;return!0}}if(null==a&&Array.isArray(b)&&A(b)&1&&!b.length||null==b&&Array.isArray(a)&&A(a)&1&&!a.length)return!0;if(!qa(a)||!qa(b))return"number"===typeof a&&isNaN(a)||"number"===typeof b&&isNaN(b)?String(a)==String(b):
-!1;if(a.constructor!=b.constructor)return!1;if(a.constructor===Array){d=a;c=a=void 0;for(var f=Math.max(d.length,b.length),e=0;e<f;e++){var g=d[e],h=b[e];g&&g.constructor==Object&&(a=g,g=void 0);h&&h.constructor==Object&&(c=h,h=void 0);if(!Pa(g,h))return!1}return a||c?(a=a||{},c=c||{},Oa(a,c)):!0}if(a.constructor===Object)return Oa(a,b);throw Error("Invalid type in JSPB array");};var K;function Ra(a){switch(typeof a){case "number":return isFinite(a)?a:String(a);case "object":if(a)if(Array.isArray(a)){if(0!==(A(a)&128))return a=Array.prototype.slice.call(a),La(a),a}else{if(v(a))return ua(a);if(a instanceof x)return Da(a)}}return a};function Sa(a,b,c,d){if(null!=a){if(Array.isArray(a))a=Ta(a,b,c,void 0!==d);else if(H(a)){var f={},e;for(e in a)f[e]=Sa(a[e],b,c,d);a=f}else a=b(a,d);return a}}function Ta(a,b,c,d){var f=A(a);d=d?!!(f&16):void 0;a=Array.prototype.slice.call(a);for(var e=0;e<a.length;e++)a[e]=Sa(a[e],b,c,d);c(f,a);return a}function Ua(a){return a.F===F?a.toJSON():Ra(a)}function Va(a){if(!a)return a;if("object"===typeof a){if(v(a))return new Uint8Array(a);if(a.F===F)return Wa(a)}return a}
-function Xa(a,b){a&128&&La(b)};function Ya(a){return a.h||(a.h=a.j[a.i+a.A]={})}function L(a,b,c){return-1===b?null:b>=a.i?a.h?a.h[b]:void 0:c&&a.h&&(c=a.h[b],null!=c)?c:a.j[b+a.A]}function M(a,b,c,d){a.o&&(a.o=void 0);if(b>=a.i||d)return Ya(a)[b]=c,a;a.j[b+a.A]=c;(c=a.h)&&b in c&&delete c[b];return a}
-function Za(a,b,c,d,f){var e=L(a,b,d);Array.isArray(e)||(e=I);var g=A(e);g&1||C(e);if(f)g&2||z(e,2),c&1||Object.freeze(e);else{f=!(c&2);var h=g&2;c&1||!h?f&&g&16&&!h&&Ea(e,16):(e=C(Array.prototype.slice.call(e)),M(a,b,e,d))}return e}function O(a,b){return Za(a,b,0,!1,E(a.j))}
-function P(a,b,c,d){var f=E(a.j),e=Za(a,b,1,d,f),g=A(e);if(!(g&4)){Object.isFrozen(e)&&(e=C(e.slice()),M(a,b,e,d));for(var h=0,k=0;h<e.length;h++){var l=c(e[h]);null!=l&&(e[k++]=l)}k<h&&(e.length=k);z(e,5);f&&(z(e,2),Object.freeze(e))}!f&&(g&2||Object.isFrozen(e))&&(e=Array.prototype.slice.call(e),z(e,5),c=e,null==c?c=I:(f=A(c),1!==(f&1)&&(Object.isFrozen(c)&&(c=Array.prototype.slice.call(c)),B(c,f|1))),J(a),M(a,b,c,d));return e}
-function $a(a){return null==a?a:"string"===typeof a?a?new x(a,w):Ca():a.constructor===x?a:v(a)?a.length?new x(new Uint8Array(a),w):Ca():void 0}function Q(a,b){a=L(a,b);return null==a?0:a}function R(a,b,c,d){J(a);c!==d?M(a,b,c):M(a,b,void 0,!1);return a}var ab=Symbol(void 0);function bb(a,b,c,d){var f=L(a,c,d);var e=!1;var g=null==f||"object"!==typeof f||(e=Array.isArray(f))||f.F!==F?e?new b(f):void 0:f;g!==f&&null!=g&&(M(a,c,g,d),z(g.j,A(a.j)&-33));return g}
-function S(a,b,c){if(a=bb(a,b,c,!1))b=a;else if(a=b[ab])b=a;else{a=new b;if(ra!==ra)throw Error("requires a valid immutable API token");E(a.j)||((c=a.o)&&Pa(c.j,a.j)?a=c:(c=cb(a,!0),z(c.j,2),a=a.o=c));b=b[ab]=a}return b}function T(a,b,c){var d=void 0===d?!1:d;b=bb(a,b,c,d);if(null==b)return b;if(!E(a.j)){var f=db(b);f!==b&&(b=f,M(a,c,b,d))}return b}
-function eb(a,b,c,d,f,e){a.m||(a.m={});var g=a.m[c],h=Za(a,c,3,d,e);if(g)e||(Object.isFrozen(g)?f||(g=Array.prototype.slice.call(g),a.m[c]=g):f&&Object.freeze(g));else{g=[];var k=!!(A(a.j)&16),l=E(h);!e&&l&&(h=C(Array.prototype.slice.call(h)),M(a,c,h,d));d=l;for(var m=0;m<h.length;m++){var q=h[m];var G=b;var D=k,N=!1;N=void 0===N?!1:N;D=void 0===D?!1:D;G=Array.isArray(q)?new G(D?Fa(q):q):N?new G:void 0;void 0!==G&&(d=d||E(q),g.push(G),l&&z(G.j,2))}a.m[c]=g;a=h;Object.isFrozen(a)||(b=A(a)|33,B(a,d?
-b&-9:b|8));(e||f&&l)&&z(g,2);(e||f)&&Object.freeze(g)}return g}function U(a,b,c,d){var f=E(a.j);b=eb(a,b,c,d,f,f);a=Za(a,c,3,d,f);if(!(f||A(a)&8)){for(f=0;f<b.length;f++)c=b[f],d=db(c),c!==d&&(b[f]=d,a[f]=b[f].j);z(a,8)}return b}function fb(a,b,c){J(a);null==c&&(c=void 0);return M(a,b,c)}function gb(a,b,c,d){J(a);if(null!=c){var f=C([]);for(var e=!1,g=0;g<c.length;g++)f[g]=c[g].j,e=e||E(f[g]);a.m||(a.m={});a.m[b]=c;c=f;e?Ea(c,8):z(c,8)}else a.m&&(a.m[b]=void 0),f=I;M(a,b,f,d)}
-function V(a,b){return null==a?b:a}function W(a,b){a=L(a,b);return V(null==a?a:!!a,!1)};function hb(a){var b=A(a);if(b&2)return a;a=sa(a,ib);Ha(b,a);Object.freeze(a);return a}function jb(a,b,c){c=void 0===c?Ha:c;if(null!=a){if(ya&&a instanceof Uint8Array)return a.length?new x(new Uint8Array(a),w):Ca();if(Array.isArray(a)){var d=A(a);if(d&2)return a;if(b&&!(d&32)&&(d&16||0===d))return B(a,d|2),a;a=Ta(a,jb,c,!0);b=A(a);b&4&&b&2&&Object.freeze(a);return a}return a.F===F?ib(a):a}}function ib(a){if(E(a.j))return a;a=cb(a,!0);z(a.j,2);return a}
-function cb(a,b){var c=a.j,d=Fa([]),f=a.constructor.h;f&&d.push(f);0!==(A(c)&128)&&La(d);b=b||E(a.j)?Ha:Ga;f=a.constructor;K=d;d=new f(d);K=void 0;a.C&&(d.C=a.C.slice());f=!!(A(c)&16);for(var e=0;e<c.length;e++){var g=c[e];if(e===c.length-1&&H(g))for(var h in g){var k=+h;if(Number.isNaN(k))Ya(d)[k]=g[k];else{var l=g[h],m=a.m&&a.m[k];m?gb(d,k,hb(m),!0):(l=jb(l,f,b),J(d),M(d,k,l,!0))}}else k=e-a.A,(l=a.m&&a.m[k])?gb(d,k,hb(l),!1):(g=jb(g,f,b),J(d),M(d,k,g,!1))}return d}
-function db(a){if(!E(a.j))return a;var b=cb(a,!1);b.o=a;return b};function X(a,b,c){null==a&&(a=K);K=void 0;var d=this.constructor.i||0,f=0<d,e=this.constructor.h,g=!1;if(null==a){a=e?[e]:[];var h=!0;B(a,48)}else{if(!Array.isArray(a))throw Error();if(e&&e!==a[0])throw Error();var k=z(a,0),l=k;if(h=0!==(16&l))(g=0!==(32&l))||(l|=32);if(f)if(128&l)d=0;else{if(0<a.length){var m=a[a.length-1];if(H(m)&&"g"in m){d=0;l|=128;delete m.g;var q=!0,G;for(G in m){q=!1;break}q&&a.pop()}}}else if(128&l)throw Error();k!==l&&B(a,l)}this.A=(e?0:-1)-d;this.m=void 0;this.j=a;a:{e=
-this.j.length;d=e-1;if(e&&(e=this.j[d],H(e))){this.h=e;this.i=d-this.A;break a}void 0!==b&&-1<b?(this.i=Math.max(b,d+1-this.A),this.h=void 0):this.i=Number.MAX_VALUE}if(!f&&this.h&&"g"in this.h)throw Error('Unexpected "g" flag in sparse object of message that is not a group type.');if(c){b=h&&!g&&!0;f=this.i;var D;for(h=0;h<c.length;h++)g=c[h],g<f?(g+=this.A,(d=a[g])?kb(d,b):a[g]=I):(D||(D=Ya(this)),(d=D[g])?kb(d,b):D[g]=I)}}X.prototype.toJSON=function(){var a=this.j;return Ia?a:Ta(a,Ua,Xa)};
-function Wa(a){var b=Ta(a.j,Va,Ga);Fa(b);K=b;b=new a.constructor(b);K=void 0;lb(b,a);return b}function kb(a,b){if(Array.isArray(a)){var c=A(a),d=1;!b||c&2||(d|=16);(c&d)!==d&&B(a,c|d)}}X.prototype.F=F;X.prototype.toString=function(){return this.j.toString()};function mb(a,b){return Ra(b)}
-function lb(a,b){b.C&&(a.C=b.C.slice());var c=b.m;if(c){var d=b.h,f;for(f in c)if(b=c[f]){var e=!(!d||!d[f]),g=+f;if(Array.isArray(b)){if(b.length)for(e=U(a,b[0].constructor,g,e),g=0;g<Math.min(e.length,b.length);g++)lb(e[g],b[g])}else throw a=typeof b,Error("unexpected object: type: "+("object"!=a?a:b?Array.isArray(b)?"array":a:"null")+": "+b);}}};var nb=void 0;function ob(a){var b=nb;nb=void 0;if(!Array.isArray(a))throw b=b?b()+"\n":"",Error(b+String(a));return a};function pb(a){return JSON.stringify([a.map(function(b){var c={};return[(c[b.L]=b.message.toJSON(),c)]})])};function qb(a){this.h=a}qb.prototype.K=function(){var a=encodeURIComponent;var b=pb(oa.apply(0,arguments));for(var c=[],d=0,f=0;f<b.length;f++){var e=b.charCodeAt(f);255<e&&(c[d++]=e&255,e>>=8);c[d++]=e}b=ua(c,3);a=a(b);this.h("https://pagead2.googlesyndication.com/pagead/ping?e=3&d="+a)};function rb(a){X.call(this,a)}r(rb,X);function sb(a){X.call(this,a,-1,tb)}r(sb,X);var tb=[3];function ub(a){X.call(this,a,-1,vb)}r(ub,X);var vb=[3];function wb(a){X.call(this,a,-1,xb)}r(wb,X);var xb=[2,3,5];function yb(a){X.call(this,a,-1,zb)}r(yb,X);function Ab(a){X.call(this,a,-1,Bb)}r(Ab,X);function Cb(a){X.call(this,a,-1,Db)}r(Cb,X);var zb=[1,2],Bb=[3,4,9],Db=[3,4,5,6,7];function Y(a){X.call(this,a)}r(Y,X);function Eb(a){X.call(this,a,-1,Fb)}r(Eb,X);var Fb=[1,2,3];function Gb(a){X.call(this,a,-1,Hb)}r(Gb,X);var Hb=[1];function Ib(a){X.call(this,a,-1,Jb)}r(Ib,X);var Jb=[1];function Kb(a){X.call(this,a,-1,Lb)}r(Kb,X);var Lb=[1];function Mb(a){X.call(this,a,-1,Nb)}r(Mb,X);var Nb=[1];function Z(a){X.call(this,a)}r(Z,X);function Ob(a){X.call(this,a,-1,Pb)}r(Ob,X);function Qb(a){X.call(this,a)}r(Qb,X);var Pb=[1];function Rb(a){X.call(this,a)}r(Rb,X);function Sb(a){X.call(this,a)}r(Sb,X);function Tb(a){X.call(this,a)}r(Tb,X);function Ub(a){X.call(this,a)}r(Ub,X);function Vb(a){X.call(this,a,-1,Wb)}r(Vb,X);var Wb=[1];function Xb(a){X.call(this,a,-1,Yb)}r(Xb,X);var Yb=[1,2];function Zb(a){X.call(this,a,-1,$b)}r(Zb,X);var $b=[1];function ac(a){X.call(this,a,-1,bc)}r(ac,X);var bc=[2,3,6,10];function cc(a){X.call(this,a)}r(cc,X);function dc(a,b){return R(a,1,b,"")}function ec(a,b){return fb(a,2,b)};var fc={ja:0,V:1,X:2,ca:3,Z:4,Y:5,aa:6,ba:7,da:8,ea:12,U:9,N:10,W:11};var gc={ka:0,ha:1,S:2,T:3,fa:4,M:5,ia:6,ga:7,P:8,O:9,R:10};function hc(a){X.call(this,a,-1,ic)}r(hc,X);function jc(a,b){fb(a,8,b)}function kc(a){X.call(this,a,-1,lc)}r(kc,X);function mc(a,b){return R(a,2,b,"")}function nc(a,b){return R(a,3,b,"")}var ic=[9],lc=[6];function oc(a){a.K.apply(a,ha(oa.apply(1,arguments).map(function(b){return{L:10,message:b}})))};function pc(a){X.call(this,a,-1,qc)}r(pc,X);var qc=[1];function rc(a,b,c){if(Q(a,2)!==Q(b,2))return c;var d=!1;switch(Q(a,2)){case 1:a:{var f,e=new Set(null!=(f=O(a,3))?f:[]);b=p(O(b,3));for(f=b.next();!f.done;f=b.next())if(e.has(f.value)){d=!0;break a}d=!1}break;case 0:a:{f=new Set(null!=(e=P(a,4,Na,!1))?e:[]);b=p(P(b,4,Na,!1));for(e=b.next();!e.done;e=b.next())if(f.has(e.value)){d=!0;break a}d=!1}break;case 2:b=new sc(b);d=(f=T(a,wb,5))?tc(b,f):!1;break;case 3:a:{f=new Set;e=p(P(a,9,$a));for(d=e.next();!d.done;d=e.next())f.add(Da(d.value));if(0===f.size)d=
-!0;else{b=p(P(b,6,$a));for(e=b.next();!e.done;e=b.next())if(f.has(Da(e.value))){d=!0;break a}d=!1}}break;case 4:d=uc(a,b)}return W(a,6)?d?null:c:d?c:null}
-function uc(a,b){a=T(a,sb,10);if(void 0===a)return!1;var c=U(b,ub,7);if(0===c.length)return!1;b=!0;c=p(c);for(var d=c.next();!d.done;d=c.next())if(d=d.value,V(L(d,1),0)===V(L(a,1),0)&&V(L(d,2),0)===V(L(a,2),0)){b&&(b=!1);var f=O(d,3);if(0===f.length)return!1;d=!0;f=p(f);for(var e=f.next();!e.done;e=f.next()){e=e.value;var g=Math.floor(e/32),h=O(a,3);if(!(g>=h.length||0!==(h[g]>>>e%32)%2)){d=!1;break}}if(d)return!0}return b}
-function tc(a,b){var c=Q(b,1),d=U(b,rb,3),f=U(b,wb,2);switch(c){case 2:c=d.every(function(e){return vc(a,e)})&&f.every(function(e){return tc(a,e)});break;case 1:c=d.some(function(e){return vc(a,e)})||f.some(function(e){return tc(a,e)});break;default:throw Error("unexpected value "+c+"!");}return W(b,4)?!c:c}function sc(a){this.h=new Map;a=p(U(a,rb,5));for(var b=a.next();!b.done;b=a.next()){var c=b.value;b=V(L(c,1),0);c=V(L(c,2),0);var d=this.h.get(b);d||(d=new Set,this.h.set(b,d));d.add(c)}}
-function vc(a,b){var c=V(L(b,2),0);return(a=a.h.get(V(L(b,1),0)))?a.has(c):!1};function wc(a,b){switch(a){case 2:return 187;case 3:return 138;case 4:return xc(b);case 5:return 80;case 6:return 7;case 7:return 2;case 8:return 7;default:return 4}}function xc(a){switch(a){case 2:return 12;case 3:return 14;case 4:return 15;case 5:return 219;case 6:return 82;case 7:return 80;case 8:return 71;case 9:return 16;default:return 4}};function yc(a){return"https://googleads.g.doubleclick.net"===a||"https://td.doubleclick.net"===a};function zc(a,b,c,d,f){this.J=a;this.postRevshareBidCpmUsdMicros=b;this.sellerSignals=c;this.h=d;this.D=f;this.o=new Map;if(W(S(c,Y,12),1)||W(S(c,Y,12),2))a=new hc,this.i=R(a,7,V(L(this.sellerSignals,2),""),"")}zc.prototype.reject=function(a,b){b=void 0===b?0:b;var c,d,f,e,g={ru:null!=(f=null==(c=this.h)?void 0:c.renderUrl)?f:"",igo:null!=(e=null==(d=this.h)?void 0:d.interestGroupOwner)?e:"",s:a,r:b};Ac(this,a,b);return{desirability:0,postRevshareBidCpmUsdMicros:0,debugInfo:this.D?g:void 0,debugEventMessage:this.debugEventMessage}};
-zc.prototype.accept=function(){var a,b,c,d,f={ru:null!=(c=null==(a=this.h)?void 0:a.renderUrl)?c:"",igo:null!=(d=null==(b=this.h)?void 0:b.interestGroupOwner)?d:"",s:1,r:1};Ac(this,1,1);return{desirability:this.postRevshareBidCpmUsdMicros,postRevshareBidCpmUsdMicros:this.postRevshareBidCpmUsdMicros,debugInfo:this.D?f:void 0,debugEventMessage:this.debugEventMessage}};
-function Ac(a,b,c){if(void 0!==a.i){var d=nc(mc(new kc,a.h.interestGroupOwner),a.h.renderUrl);yc(a.h.interestGroupOwner)||R(d,8,a.J,0);fb(a.i,4,d);W(S(a.sellerSignals,Y,12),5)&&(jc(fb(a.i,11,a.sellerSignals),ec(dc(new cc,a.h.renderUrl),a.I)),a.o.forEach(function(h,k){var l;null!=(l=a.i)&&(k=ec(dc(new cc,k),h),J(l),h=eb(l,cc,9,void 0,!1,!1),k=null!=k?k:new cc,l=Za(l,9,2,void 0,!1),h.push(k),l.push(k.j),E(k.j)&&Ea(l,8))}));if(Object.values(gc).includes(b)){var f;null!=(f=a.i)&&R(f,6,b,0)}if(Object.values(fc).includes(c)){var e;
-null!=(e=a.i)&&R(e,5,c,0)}if(1!==b||1!==c){var g;null!=(g=a.i)&&R(g,10,wc(b,c),0)}}}ea.Object.defineProperties(zc.prototype,{debugEventMessage:{configurable:!0,enumerable:!0,get:function(){var a;return null==(a=this.i)?void 0:Wa(a)}}});function Bc(a){var b;this.i=null!=(b=null==a?void 0:V(L(a,4),0))?b:0}Bc.prototype.h=function(a){if(!this.i)return 1;var b;return(null==(b=T(a,Vb,9))?0:O(b,1).includes(this.i))?2:1};function Cc(a,b){return 0===a.size?!1:void 0===b||0===b.length?!0:b.some(function(c){return a.has(c)})}function Dc(a){a=S(S(a,Z,2),Eb,1);this.i=new Set(O(a,1));this.o=W(a,4);this.D=W(a,5)}Dc.prototype.h=function(a){var b;if(Cc(this.i,null==(b=T(a,Xb,1))?void 0:O(b,1)))return 4;a=T(a,Xb,1);return!this.D||a&&!W(a,4)?!this.o||a&&!W(a,3)?1:3:4};function Ec(a){this.i=W(S(S(a,Z,2),Gb,3),2);this.o=new Set(O(S(S(a,Z,2),Gb,3),1))}Ec.prototype.h=function(a){var b=this;return this.i?1:void 0===bb(a,Zb,7,!1)||O(T(a,Zb,7),1).every(function(c){return b.o.has(c)})?1:5};function Fc(a){var b,c,d;this.i=new Set(null!=(d=null==a?void 0:null==(b=T(a,Z,2))?void 0:null==(c=T(b,Ib,4))?void 0:P(c,1,Na,!1))?d:[])}Fc.prototype.h=function(a){var b=this;return 0===this.i.size?1:0===P(a,10,Na,!1).length||P(a,10,Na,!1).some(function(c){return!b.i.has(c)})?6:1};function Gc(a){var b,c;this.i=null!=(c=null==a?void 0:null==(b=T(a,Ob,3))?void 0:U(b,Qb,1))?c:[]}Gc.prototype.h=function(a,b){if(null==b)return 7;if(0===this.i.length)return 1;a=p(this.i);for(var c=a.next();!c.done;c=a.next())if(c=c.value,null!=V(L(c,2),0)&&b<V(L(c,2),0))return 7;return 1};function Hc(a){var b,c,d;this.i=new Set(null!=(d=null==a?void 0:null==(b=T(a,Z,2))?void 0:null==(c=T(b,Kb,2))?void 0:P(c,1,Ma))?d:[])}Hc.prototype.h=function(a){var b=this;return 0!==this.i.size&&P(a,6,Ma).some(function(c){return b.i.has(c)})?8:1};function Ic(a){a=S(S(a,Z,2),Mb,5);this.i=W(a,2);this.o=new Set(O(a,1))}Ic.prototype.h=function(a){var b=this;return this.i?1:O(S(a,Zb,7),1).every(function(c){return b.o.has(c)})?1:9};function Jc(){new pc;return function(a,b,c,d,f){a=new Sb(ob(c.sellerSignals));b=Kc(b,a,d,f,W(a,8)||W(a,22));W(a,8)&&b.debugInfo&&console.log(b.debugInfo);if(W(a,22)&&b.debugInfo){d=b.debugInfo.s;c=b.debugInfo.r;var e,g,h={renderUrl:null!=(e=null==f?void 0:f.renderUrl)?e:"",interestGroupOwner:null!=(g=null==f?void 0:f.interestGroupOwner)?g:"",accepted:!0};if(1!==d||1!==c)h.accepted=!1,h.externalBidStatus=wc(d,c);console.log("Logging debug info of scoreAd().\n",h)}b.debugEventMessage&&(e=b.debugEventMessage,
-g=globalThis.forDebuggingOnly,W(S(a,Y,12),1)&&g.reportAdAuctionWin&&Lc(a,e,g.reportAdAuctionWin,1),W(S(a,Y,12),2)&&g.reportAdAuctionLoss&&Lc(a,e,g.reportAdAuctionLoss,2));return f.topLevelSeller?{desirability:b.desirability,bid:b.postRevshareBidCpmUsdMicros?b.postRevshareBidCpmUsdMicros/1E6:void 0,allowComponentAuction:!0}:{desirability:b.desirability,allowComponentAuction:!0}}}
-function Lc(a,b,c,d){R(b,2,d,0);d=T(b,kc,4);if(W(a,23)&&d&&!yc(V(L(d,2),""))){a=encodeURIComponent;a:{Ia=!0;try{var f=JSON.stringify(b.toJSON(),mb);break a}finally{Ia=!1}f=void 0}c("https://googleads.g.doubleclick.net/td/rdl?tdr="+a(f))}else oc(new qb(c),b)}
-function Mc(a,b){var c,d=null==(c=a.sellerSignals)?void 0:T(c,yb,3),f=null==b?void 0:T(b,yb,11);if(d&&f){c=new Map;for(var e=new Map,g=p(U(d,Ab,1)),h=g.next();!h.done;h=g.next())h=h.value,c.set(Q(h,1),h);d=p(U(d,Cb,2));for(g=d.next();!g.done;g=d.next())g=g.value,e.set(Q(g,1),g);d=new Map;if(g=c&&e&&f)a:{g=p(U(f,Ab,1));for(h=g.next();!h.done;h=g.next()){h=h.value;var k=Q(h,1),l=e.get(k);if(l){var m=null;if(W(h,7)){var q=d.get(k),G=!0,D=V(L(h,8),0);if(void 0===q)q=new Map,d.set(k,q);else{var N=q.get(D);
-if(N){g=N;break a}null===N&&(G=!1)}G&&(m=rc(h,l,k),q.set(D,m))}else m=rc(h,l,k);if(m){g=m;break a}}}f=p(U(f,Cb,2));for(e=f.next();!e.done;e=f.next())if(e=e.value,d=Q(e,1),g=c.get(d))if(e=rc(g,e,d)){g=e;break a}g=null}if(g)return{G:2,B:0}}a:{c=a.postRevshareBidCpmUsdMicros;var da;a=null!=(da=T(a.sellerSignals,Rb,1))?da:new Rb;da=p([new Bc(a),new Dc(a),new Ec(a),new Fc(a),new Gc(a),new Hc(a),new Ic(a)]);for(a=da.next();!a.done;a=da.next())if(a=a.value.h(b,c),1!==a){b=a;break a}b=1}return 1!==b?{G:4,
-B:b}:{G:0,B:1}}
-function Kc(a,b,c,d,f){var e=!!d.componentSeller,g=1E6*a,h=S(S(b,Tb,5),Ub,1);h=L(h,1);h=g*(V(null==h?h:+h,0)||1);a=new zc(a,h,b,d,f);if(d.topLevelSeller&&"https://pubads.g.doubleclick.net"!==d.topLevelSeller)return a.reject(9);var k;f=BigInt((null==(k=T(b,Tb,5))?void 0:V(L(k,2),"0"))||0);if(h<f)return a.reject(5);var l;b=BigInt((null==(l=T(b,Tb,5))?void 0:V(L(l,3),"0"))||0);if(0<b&&g>b)return a.reject(3);if(e)return a.accept();if(!d.renderUrl)return a.reject(7,11);e=null==c?void 0:c.renderUrl;if(null==
-e||!e[d.renderUrl])return a.reject(6,10);var m;e=new ac(ob(null!=(m=null==e?void 0:e[d.renderUrl])?m:[]));a.I=e;m=Mc(a,a.I);if(1!==m.B)return a.reject(m.G,m.B);var q;if(null==(q=d.adComponents)?0:q.length){q=!1;d=p(d.adComponents);for(m=d.next();!m.done;m=d.next())if(m=m.value,l=g=e=void 0,b=null!=(l=null==(e=c)?void 0:null==(g=e.adComponentRenderUrls)?void 0:g[m])?l:[],e=ob(b),e.length&&(q=!0,e=new ac(e),a.o.set(m,e),e=Mc(a,e),1!==e.B))return c=a.reject(e.G,e.B),c.debugInfo&&(c.debugInfo.acru=m),
-c;if(!q)return a.reject(8,12)}return a.accept()};function Nc(a,b,c,d,f){var e=a.metadata.metadata;c={seller:c.seller,decisionLogicUrl:c.decision_logic_uri,trustedScoringSignalsUrl:c.trusted_scoring_signal_uri,interestGroupBuyers:c.custom_audience_buyers,auctionSignals:f,sellerExperimentGroupId:void 0,sellerSignals:d.signals,perBuyerSignals:c.per_buyer_signals};a={topWindowHostname:"",interestGroupOwner:"",renderUrl:a.render_uri,biddingDurationMsec:0};b=Jc()(e,b,c,f,a);return{status:0,score:"number"===typeof b?b:b.desirability}};var Oc=globalThis;Oc.scoreAd=function(a,b,c,d,f){return Nc(a,b,c,d,f)};Oc.scoreAdIterative=function(a,b,c,d){var f=[],e=(new Date).getTime();a=p(a);for(var g=a.next();!g.done;g=a.next())g=g.value,g=Nc(g.ad,g.bid,b,c,d),f.push(g);return{responses:f,status:0,duration:(new Date).getTime()-e}};
diff --git a/apct-tests/perftests/rubidium/assets/turtledove_generate_bid.js b/apct-tests/perftests/rubidium/assets/turtledove_generate_bid.js
deleted file mode 100644
index 38d30ac..0000000
--- a/apct-tests/perftests/rubidium/assets/turtledove_generate_bid.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- Copyright The Closure Library Authors.
- SPDX-License-Identifier: Apache-2.0
-
- See cl/451090252 for how to generate this file.
-*/
-var n,aa=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}},ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a},ca=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");
-},da=ca(this),p=function(a,b){if(b)a:{var c=da;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}};
-p("Symbol",function(a){if(a)return a;var b=function(g,f){this.ra=g;ba(this,"description",{configurable:!0,writable:!0,value:f})};b.prototype.toString=function(){return this.ra};var c="jscomp_symbol_"+(1E9*Math.random()>>>0)+"_",d=0,e=function(g){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new b(c+(g||"")+"_"+d++,g)};return e});
-p("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=da[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&ba(d.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(aa(this))}})}return a});
-var ea=function(a){a={next:a};a[Symbol.iterator]=function(){return this};return a},r=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:aa(a)}},ha="function"==typeof Object.create?Object.create:function(a){var b=function(){};b.prototype=a;return new b},ia;
-if("function"==typeof Object.setPrototypeOf)ia=Object.setPrototypeOf;else{var ja;a:{var ka={a:!0},la={};try{la.__proto__=ka;ja=la.a;break a}catch(a){}ja=!1}ia=ja?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}
-var ma=ia,t=function(a,b){a.prototype=ha(b.prototype);a.prototype.constructor=a;if(ma)ma(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.za=b.prototype},u=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};
-p("WeakMap",function(a){function b(){}function c(l){var k=typeof l;return"object"===k&&null!==l||"function"===k}function d(l){if(!u(l,g)){var k=new b;ba(l,g,{value:k})}}function e(l){var k=Object[l];k&&(Object[l]=function(m){if(m instanceof b)return m;Object.isExtensible(m)&&d(m);return k(m)})}if(function(){if(!a||!Object.seal)return!1;try{var l=Object.seal({}),k=Object.seal({}),m=new a([[l,2],[k,3]]);if(2!=m.get(l)||3!=m.get(k))return!1;m.delete(l);m.set(k,4);return!m.has(l)&&4==m.get(k)}catch(q){return!1}}())return a;
-var g="$jscomp_hidden_"+Math.random();e("freeze");e("preventExtensions");e("seal");var f=0,h=function(l){this.M=(f+=Math.random()+1).toString();if(l){l=r(l);for(var k;!(k=l.next()).done;)k=k.value,this.set(k[0],k[1])}};h.prototype.set=function(l,k){if(!c(l))throw Error("Invalid WeakMap key");d(l);if(!u(l,g))throw Error("WeakMap key fail: "+l);l[g][this.M]=k;return this};h.prototype.get=function(l){return c(l)&&u(l,g)?l[g][this.M]:void 0};h.prototype.has=function(l){return c(l)&&u(l,g)&&u(l[g],this.M)};
-h.prototype.delete=function(l){return c(l)&&u(l,g)&&u(l[g],this.M)?delete l[g][this.M]:!1};return h});
-p("Map",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var h=Object.seal({x:4}),l=new a(r([[h,"s"]]));if("s"!=l.get(h)||1!=l.size||l.get({x:4})||l.set({x:4},"t")!=l||2!=l.size)return!1;var k=l.entries(),m=k.next();if(m.done||m.value[0]!=h||"s"!=m.value[1])return!1;m=k.next();return m.done||4!=m.value[0].x||"t"!=m.value[1]||!k.next().done?!1:!0}catch(q){return!1}}())return a;var b=new WeakMap,c=function(h){this.L={};this.A=g();
-this.size=0;if(h){h=r(h);for(var l;!(l=h.next()).done;)l=l.value,this.set(l[0],l[1])}};c.prototype.set=function(h,l){h=0===h?0:h;var k=d(this,h);k.list||(k.list=this.L[k.id]=[]);k.j?k.j.value=l:(k.j={next:this.A,B:this.A.B,head:this.A,key:h,value:l},k.list.push(k.j),this.A.B.next=k.j,this.A.B=k.j,this.size++);return this};c.prototype.delete=function(h){h=d(this,h);return h.j&&h.list?(h.list.splice(h.index,1),h.list.length||delete this.L[h.id],h.j.B.next=h.j.next,h.j.next.B=h.j.B,h.j.head=null,this.size--,
-!0):!1};c.prototype.clear=function(){this.L={};this.A=this.A.B=g();this.size=0};c.prototype.has=function(h){return!!d(this,h).j};c.prototype.get=function(h){return(h=d(this,h).j)&&h.value};c.prototype.entries=function(){return e(this,function(h){return[h.key,h.value]})};c.prototype.keys=function(){return e(this,function(h){return h.key})};c.prototype.values=function(){return e(this,function(h){return h.value})};c.prototype.forEach=function(h,l){for(var k=this.entries(),m;!(m=k.next()).done;)m=m.value,
-h.call(l,m[1],m[0],this)};c.prototype[Symbol.iterator]=c.prototype.entries;var d=function(h,l){var k=l&&typeof l;"object"==k||"function"==k?b.has(l)?k=b.get(l):(k=""+ ++f,b.set(l,k)):k="p_"+l;var m=h.L[k];if(m&&u(h.L,k))for(h=0;h<m.length;h++){var q=m[h];if(l!==l&&q.key!==q.key||l===q.key)return{id:k,list:m,index:h,j:q}}return{id:k,list:m,index:-1,j:void 0}},e=function(h,l){var k=h.A;return ea(function(){if(k){for(;k.head!=h.A;)k=k.B;for(;k.next!=k.head;)return k=k.next,{done:!1,value:l(k)};k=null}return{done:!0,
-value:void 0}})},g=function(){var h={};return h.B=h.next=h.head=h},f=0;return c});p("Number.isFinite",function(a){return a?a:function(b){return"number"!==typeof b?!1:!isNaN(b)&&Infinity!==b&&-Infinity!==b}});var na=function(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&c<a.length){var g=c++;return{value:b(g,a[g]),done:!1}}d=!0;return{done:!0,value:void 0}}};e[Symbol.iterator]=function(){return e};return e};
-p("Array.prototype.entries",function(a){return a?a:function(){return na(this,function(b,c){return[b,c]})}});p("Number.isNaN",function(a){return a?a:function(b){return"number"===typeof b&&isNaN(b)}});
-p("Set",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var c=Object.seal({x:4}),d=new a(r([c]));if(!d.has(c)||1!=d.size||d.add(c)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var e=d.entries(),g=e.next();if(g.done||g.value[0]!=c||g.value[1]!=c)return!1;g=e.next();return g.done||g.value[0]==c||4!=g.value[0].x||g.value[1]!=g.value[0]?!1:e.next().done}catch(f){return!1}}())return a;var b=function(c){this.m=new Map;if(c){c=
-r(c);for(var d;!(d=c.next()).done;)this.add(d.value)}this.size=this.m.size};b.prototype.add=function(c){c=0===c?0:c;this.m.set(c,c);this.size=this.m.size;return this};b.prototype.delete=function(c){c=this.m.delete(c);this.size=this.m.size;return c};b.prototype.clear=function(){this.m.clear();this.size=0};b.prototype.has=function(c){return this.m.has(c)};b.prototype.entries=function(){return this.m.entries()};b.prototype.values=function(){return this.m.values()};b.prototype.keys=b.prototype.values;
-b.prototype[Symbol.iterator]=b.prototype.values;b.prototype.forEach=function(c,d){var e=this;this.m.forEach(function(g){return c.call(d,g,g,e)})};return b});p("Array.from",function(a){return a?a:function(b,c,d){c=null!=c?c:function(h){return h};var e=[],g="undefined"!=typeof Symbol&&Symbol.iterator&&b[Symbol.iterator];if("function"==typeof g){b=g.call(b);for(var f=0;!(g=b.next()).done;)e.push(c.call(d,g.value,f++))}else for(g=b.length,f=0;f<g;f++)e.push(c.call(d,b[f],f));return e}});
-p("Object.entries",function(a){return a?a:function(b){var c=[],d;for(d in b)u(b,d)&&c.push([d,b[d]]);return c}});p("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});p("Array.prototype.includes",function(a){return a?a:function(b,c){var d=this;d instanceof String&&(d=String(d));var e=d.length;c=c||0;for(0>c&&(c=Math.max(c+e,0));c<e;c++){var g=d[c];if(g===b||Object.is(g,b))return!0}return!1}});
-p("String.prototype.includes",function(a){return a?a:function(b,c){if(null==this)throw new TypeError("The 'this' value for String.prototype.includes must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype.includes must not be a regular expression");return-1!==(this+"").indexOf(b,c||0)}});p("Array.prototype.values",function(a){return a?a:function(){return na(this,function(b,c){return c})}});
-var oa=this||self,pa=function(a){var b=typeof a;return"object"!=b?b:a?Array.isArray(a)?"array":b:"null"},ra=function(a,b){function c(){}c.prototype=b.prototype;a.za=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.Ca=function(d,e,g){for(var f=Array(arguments.length-2),h=2;h<arguments.length;h++)f[h-2]=arguments[h];return b.prototype[e].apply(d,f)}};function sa(a){if(Error.captureStackTrace)Error.captureStackTrace(this,sa);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))}ra(sa,Error);sa.prototype.name="CustomError";function ta(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");sa.call(this,c+a[d])}ra(ta,sa);ta.prototype.name="AssertionError";function ua(a,b,c,d){var e="Assertion failed";if(c){e+=": "+c;var g=d}else a&&(e+=": "+a,g=b);throw new ta(""+e,g||[]);}
-var v=function(a,b,c){a||ua("",null,b,Array.prototype.slice.call(arguments,2));return a},va=function(a,b,c){null==a&&ua("Expected to exist: %s.",[a],b,Array.prototype.slice.call(arguments,2));return a},wa=function(a,b){throw new ta("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));},w=function(a,b,c){Array.isArray(a)||ua("Expected array but got %s: %s.",[pa(a),a],b,Array.prototype.slice.call(arguments,2))},x=function(a,b,c,d){a instanceof b||ua("Expected instanceof %s but got %s.",
-[xa(b),xa(a)],c,Array.prototype.slice.call(arguments,3));return a};function xa(a){return a instanceof Function?a.displayName||a.name||"unknown type name":a instanceof Object?a.constructor.displayName||a.constructor.name||Object.prototype.toString.call(a):null===a?"null":typeof a};var ya={},za=null,Aa=function(a){var b,c=pa(a);v("array"==c||"object"==c&&"number"==typeof a.length,"encodeByteArray takes an array as a parameter");void 0===b&&(b=0);if(!za){za={};c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split("");for(var d=["+/=","+/","-_=","-_.","-_"],e=0;5>e;e++){var g=c.concat(d[e].split(""));ya[e]=g;for(var f=0;f<g.length;f++){var h=g[f],l=za[h];void 0===l?za[h]=f:v(l===f)}}}b=ya[b];c=Array(Math.floor(a.length/3));d=b[64]||"";for(e=g=0;g<a.length-2;g+=
-3){l=a[g];var k=a[g+1];h=a[g+2];f=b[l>>2];l=b[(l&3)<<4|k>>4];k=b[(k&15)<<2|h>>6];h=b[h&63];c[e++]=""+f+l+k+h}f=0;h=d;switch(a.length-g){case 2:f=a[g+1],h=b[(f&15)<<2]||d;case 1:a=a[g],c[e]=""+b[a>>2]+b[(a&3)<<4|f>>4]+h+d}return c.join("")};var Ba="undefined"!==typeof Uint8Array,Ca={};var Da,Ea=function(a){if(Ca!==Ca)throw Error("illegal external caller");this.qa=a;if(null!==a&&0===a.length)throw Error("ByteString should be constructed with non-empty values");};v(!0);var Fa={};var z="function"===typeof Symbol&&"symbol"===typeof Symbol()?Symbol("INTERNAL_ARRAY_STATE"):void 0;function Ga(a,b){Object.isFrozen(a)||(z?a[z]|=b:void 0!==a.F?a.F|=b:Object.defineProperties(a,{F:{value:b,configurable:!0,writable:!0,enumerable:!1}}))}var Ha=Object.getOwnPropertyDescriptor(Array.prototype,"wa");
-Object.defineProperties(Array.prototype,{wa:{get:function(){var a=A(this),b=[];1&a&&b.push("IS_REPEATED_FIELD");2&a&&b.push("IS_IMMUTABLE_ARRAY");4&a&&b.push("IS_API_FORMATTED");8&a&&b.push("ONLY_MUTABLE_VALUES");a=b.join(",");return Ha?Ha.get.call(this)+"|"+a:a},configurable:!0,enumerable:!1}});function A(a){w(a,"state is only maintained on arrays.");a=z?a[z]:a.F;return null==a?0:a}function B(a){w(a,"state is only maintained on arrays.");Ga(a,1);return a}
-function C(a){return Array.isArray(a)?!!(A(a)&2):!1}function Ia(a){if(!Array.isArray(a))throw Error("cannot mark non-array as immutable");Ga(a,2)}function Ja(a,b){if(!Array.isArray(a))throw Error("cannot mark non-array as mutable");b?Ga(a,8):Object.isFrozen(a)||(z?a[z]&=-9:void 0!==a.F&&(a.F&=-9))};function Ka(a){return null!==a&&"object"===typeof a&&!Array.isArray(a)&&a.constructor===Object}var La=Symbol("exempted jspb subclass"),Ma=Symbol("generated by jspb"),Na=Object.freeze(B([])),Oa=function(a){if(C(a.g))throw Error("Cannot mutate an immutable Message");},Pa="undefined"!=typeof Symbol&&"undefined"!=typeof Symbol.hasInstance;function Qa(a){return{value:a,configurable:!1,writable:!1,enumerable:!1}};function Ra(a){return a.displayName||a.name||"unknown type name"}function Sa(a,b){if(!(a instanceof b))throw Error("Expected instanceof "+Ra(b)+" but got "+(a&&Ra(a.constructor)));return a}function Ta(a,b,c){c=void 0===c?!1:c;if(Array.isArray(a))return new b(a);if(c)return new b};var Ua=function(){throw Error("please construct maps as mutable then call toImmutable");};if(Pa){var Va=function(){throw Error("Cannot perform instanceof checks on ImmutableMap");},Wa={};Object.defineProperties(Ua,(Wa[Symbol.hasInstance]=Qa(Va),Wa));v(Ua[Symbol.hasInstance]===Va,"defineProperties did not work: was it monkey-patched?")};function Xa(a){switch(typeof a){case "number":return isFinite(a)?a:String(a);case "object":if(a&&!Array.isArray(a)){if(Ba&&null!=a&&a instanceof Uint8Array)return Aa(a);if(a instanceof Ea){var b=a.qa;null!=b&&"string"!==typeof b&&(Ba&&b instanceof Uint8Array?b=Aa(b):(wa("Cannot coerce to b64 string: "+pa(b)),b=null));return(a.qa=b)||""}}}return a};function Ya(a,b){b=void 0===b?Za:b;w(a);return $a(a,b)}function ab(a,b){if(null!=a){if(Array.isArray(a))a=$a(a,b);else if(Ka(a)){var c={},d;for(d in a)c[d]=ab(a[d],b);a=c}else a=b(a);return a}}function $a(a,b){w(a);for(var c=a.slice(),d=0;d<c.length;d++)c[d]=ab(c[d],b);Array.isArray(a)&&A(a)&1&&B(c);return c}function bb(a){if(a&&"object"==typeof a&&a.toJSON)return a.toJSON();a=Xa(a);return Array.isArray(a)?Ya(a,bb):a}function Za(a){return Ba&&null!=a&&a instanceof Uint8Array?new Uint8Array(a):a};var cb=function(a){return a.C||(a.C=a.g[a.G+a.D]={})},db=function(a,b,c){return-1===b?null:b>=a.G?a.C?a.C[b]:void 0:(void 0===c?0:c)&&a.C&&(c=a.C[b],null!=c)?c:a.g[b+a.D]},D=function(a,b,c,d,e){d=void 0===d?!1:d;(void 0===e?0:e)||Oa(a);b<a.G&&!d?a.g[b+a.D]=c:cb(a)[b]=c},E=function(a,b,c,d){c=void 0===c?!0:c;var e=db(a,b,d);Array.isArray(e)||(e=Na);if(C(a.g))c&&(Ia(e),Object.freeze(e));else if(e===Na||C(e))e=B(e.slice()),D(a,b,e,d);return e},F=function(a,b){var c=Number,d=E(a,b,!1),e;if(e=d.length)e=
-d,w(e,"state is only maintained on arrays."),e=!(A(e)&4);if(e){Object.isFrozen(d)&&(d=B(d.slice()),D(a,b,d,void 0,!0));for(b=0;b<d.length;b++)d[b]=c(d[b]);c=d;w(c,"state is only maintained on arrays.");Ga(c,5)}C(a.g)&&Object.freeze(d);return d},G=function(a,b,c){a=db(a,b);return null==a?c:a},I=function(a,b){a=db(a,b);a=null==a?a:!!a;return null==a?!1:a},J=function(a,b){a=db(a,b);a=null==a?a:+a;return null==a?0:a};function L(a,b,c){Oa(a);0!==c?D(a,b,c):D(a,b,void 0,!1);return a}
-var M=function(a,b,c,d,e){e=void 0===e?!1:e;var g=e;if(-1===c)d=null;else{a.h||(a.h={});var f=a.h[c];if(f)d=f;else{var h=db(a,c,g);b=Ta(h,b,d);void 0==b?d=f:(d&&b.g!==h&&D(a,c,b.g,g,!0),a.h[c]=b,C(a.g)&&Ia(b.g),d=b)}}if(null==d)return d;C(d.g)&&!C(a.g)&&(d=d.fa(Fa),D(a,c,d.g,e),a.h[c]=d);return d},N=function(a,b,c,d){var e=d=void 0===d?!1:d;a.h||(a.h={});var g=C(a.g),f=a.h[c];if(!f){e=E(a,c,!0,e);f=[];var h=g||C(e);g=g||h;for(var l=0;l<e.length;l++){var k=e[l];g=g||C(k);k=Ta(k,b);void 0!==k&&(f.push(k),
-h&&Ia(k.g))}h&&(Ia(f),Object.freeze(f));a.h[c]=f;Ja(e,!g)}b=f;f=C(a.g);if(c=a=E(a,c,d)){if(!Array.isArray(a))throw Error("cannot check mutability state of non-array");c=!(A(a)&8)}if(c){for(c=0;c<b.length;c++)(d=b[c])&&C(d.g)&&!f&&(b[c]=b[c].fa(Fa),a[c]=b[c].g);Ja(a,!0)}return b},eb=function(a,b,c,d){Oa(a);a.h||(a.h={});b=null!=d?Sa(d,va(b)).g:d;a.h[c]=d;D(a,c,b)},O=function(a,b){return G(a,b,"0")};var P=function(a,b,c){x(this,P,"The message constructor should only be used by subclasses");v(this.constructor!==P,"Message is an abstract class and cannot be directly constructed");if(!0!==this[La]){v(!0===this[Ma],"Message can only be subclassed by proto gencode.");var d=Object.getPrototypeOf(v(Object.getPrototypeOf(this)));v(d.hasOwnProperty(Ma),"Generated jspb classes should not be extended")}a||(a=fb);fb=null;d=this.constructor.Ia;a||(a=d?[d]:[]);this.D=(d?0:-1)-(this.constructor.Ga||0);this.h=
-void 0;this.g=a;a:{d=this.g.length;a=d-1;if(d&&(d=this.g[a],Ka(d))){this.G=a-this.D;this.C=d;break a}void 0!==b&&-1<b?(this.G=Math.max(b,a+1-this.D),this.C=void 0):this.G=Number.MAX_VALUE}if(c)for(b=0;b<c.length;b++)if(a=c[b],a<this.G)a+=this.D,(d=this.g[a])?Array.isArray(d)&&B(d):this.g[a]=Na;else{d=cb(this);var e=d[a];e?Array.isArray(e)&&B(e):d[a]=Na}};n=P.prototype;n.toJSON=function(){return Ya(this.g,bb)};n.getExtension=function(a){x(this,a.va);return a.Ea(x(this,P))};
-n.hasExtension=function(a){x(this,a.va);v(!a.Ha,"repeated extensions don't support hasExtension");var b=x(this,P);return null!=db(b,a.Da)};n.clone=function(){var a=x(this,P),b=Ya(a.g);x(a,P);w(b);fb=b;b=new a.constructor(b);x(b,P);fb=null;gb(b,a);return b};n.toString=function(){return this.g.toString()};
-function gb(a,b){v(a,"expected `to` to be non-null");v(b,"expected `from` to be non-null");b.N&&(a.N=b.N.slice());var c=b.h;if(c){b=b.C;for(var d in c){var e=c[d];if(e){var g=!(!b||!b[d]),f=+d;if(Array.isArray(e)){if(e.length)for(g=N(a,e[0].constructor,f,g),f=0;f<Math.min(g.length,e.length);f++)gb(g[f],x(e[f],P))}else x(e,P),(g=M(a,e.constructor,f,void 0,g))&&gb(g,e)}}}}var fb;var hb=function(){P.call(this,void 0);throw Error("ImmutableMessage is not instantiable");};t(hb,P);hb.prototype.clone=function(){return P.prototype.clone.call(this)};if(Pa){var ib=function(){throw Error("Cannot perform instanceof checks for MutableMessage");},jb={};Object.defineProperties(hb,(jb[Symbol.hasInstance]=Qa(ib),jb));v(hb[Symbol.hasInstance]===ib,"broken defineProperties implementation")};var kb=function(){P.apply(this,arguments)};t(kb,P);kb.prototype.fa=function(){return this};if(Pa){var lb=function(){throw Error("Cannot perform instanceof checks for MutableMessage");},mb={};Object.defineProperties(kb,(mb[Symbol.hasInstance]=Qa(lb),mb));v(kb[Symbol.hasInstance]===lb,"defineProperties did not work: was it monkey-patched?")};function nb(a,b,c,d,e,g){if(a=a.h&&a.h[c])if(Array.isArray(a)){e=g.ba?B(a.slice()):a;g=0<e.length?e[0].constructor:void 0;Oa(b);if(null!=e){w(e);d=B([]);a=!1;for(var f=0;f<e.length;f++)d[f]=Sa(e[f],va(g)).g,a=a||C(d[f]);b.h||(b.h={});b.h[c]=e;Ja(d,!a)}else b.h&&(b.h[c]=void 0),d=Na;D(b,c,d)}else eb(b,a.constructor,c,x(a,P));else Ba&&d instanceof Uint8Array?(e=d,x(e,Uint8Array),e=e.length?new Ea(new Uint8Array(e)):Da||(Da=new Ea(null))):(Array.isArray(d)&&(e?Ia(d):Array.isArray(d)&&A(d)&1&&g.ba&&(d=
-d.slice())),e=d),D(b,c,e)};var Q=function(){kb.apply(this,arguments)};t(Q,kb);
-Q.prototype.fa=function(a){if(a!==Fa)throw Error("requires a valid immutable API token");if(C(this.g)){x(this,P);a={ba:!0};var b=C(this.g);if(b&&!a.ba)throw Error("copyRepeatedFields must be true for frozen messages");var c=new this.constructor;this.N&&(c.N=this.N.slice());for(var d=this.g,e=0;e<d.length;e++){var g=d[e];if(e===d.length-1&&Ka(g))for(h in g){var f=+h;Number.isNaN(f)?cb(c)[h]=g[h]:nb(this,c,f,g[h],b,a)}else nb(this,c,e-this.D,g,b,a)}var h=c}else h=this;return h};Q.prototype[Ma]=!0;
-if(Pa){var ob={};Object.defineProperties(Q,(ob[Symbol.hasInstance]=Qa(Object[Symbol.hasInstance]),ob));v(Q[Symbol.hasInstance]===Object[Symbol.hasInstance],"broken defineProperties implementation")};var pb=void 0;function qb(a){var b=pb;pb=void 0;var c=[],d=rb(a,c);if(!d&&c){var e="Expected Array<unknown>, got "+sb(a);c.push(e)}if(!d)throw a="",b&&(a=b()+"\n"),Error(a+"Guard Array<unknown> failed:\n"+c.reverse().join("\n"));return a}
-function sb(a,b){b=void 0===b?new Set:b;if(b.has(a))return"(Recursive reference)";switch(typeof a){case "object":if(a){var c=Object.getPrototypeOf(a);switch(c){case Map.prototype:case Set.prototype:case Array.prototype:b.add(a);var d="["+Array.from(a,function(e){return sb(e,b)}).join(", ")+"]";b.delete(a);c!==Array.prototype&&(d=tb(c.constructor)+"("+d+")");return d;case Object.prototype:return b.add(a),c="{"+Object.entries(a).map(function(e){var g=r(e);e=g.next().value;g=g.next().value;return e+
-": "+sb(g,b)}).join(", ")+"}",b.delete(a),c;default:return d="Object",c&&c.constructor&&(d=tb(c.constructor)),"function"===typeof a.toString&&a.toString!==Object.prototype.toString?d+"("+String(a)+")":"(object "+d+")"}}break;case "function":return"function "+tb(a);case "number":if(!Number.isFinite(a))return String(a);break;case "bigint":return a.toString(10)+"n"}return JSON.stringify(a)}function tb(a){var b=a.name;b||(b=(a=/function\s+([^\(]+)/m.exec(String(a)))?a[1]:"(Anonymous)");return b};var rb=function(a){a.Fa=function(){return"Array<unknown>"};return a}(function(a){return Array.isArray(a)});var ub=[[[["1646440773",[-.21289063,-.014526367,-.0046081543,-.013671875,-.012451172,.056152344,-.05029297,-.15234375,-.044677734,-.29101563,-.099121094,.0014190674,.08496094,.078125,-.009765625,-.09765625,-.045166016,.09765625,-.022583008,.23242188,-.04321289,.0126953125,.032226563,.064941406,.36132813,-.09716797,.28515625,.0074768066,-.11279297,-.0625,.012329102,-.076171875]]],[["1646451678",[-.18652344,.15917969,-.005340576,.055664063,.041015625,-.010253906,.06591797,-.071777344,.024536133,1.828125,
--.19140625,-.35351563,.13671875,.45117188,.12792969,-.03466797,.18261719,.19628906,.14160156,.17480469,-.04638672,-.06689453,-.30273438,.35351563,-.33789063,-.7578125,-.17675781,.05810547,-.002029419,.005279541,-.025756836,.15234375]]]],null,[1],"CMb9tKfcrvYCFawfBgAdboELOQ",null,[null,null,null,1,[]],[null,null,null,null,[]]];var vb={owner:"https://googleads.g.doubleclick.net/",name:"1j115753478",biddingLogicUrl:"https://googleads.g.doubleclick.net/td/bjs",dailyUpdateUrl:"https://googleads.g.doubleclick.net/td/update",trustedBiddingSignalsUrl:"https://googleads.g.doubleclick.net/td/sjs",trustedBiddingSignalsKeys:["1j115753478"],userBiddingSignals:[],ads:[{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=28447972118&cr_id=310927197288&cv_id=6",metadata:["28447972118","310927197288","6","377212838"]},
-{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=28447972118&cr_id=310927197291&cv_id=6",metadata:["28447972118","310927197291","6","377212838"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=28447972118&cr_id=310966379641&cv_id=5",metadata:["28447972118","310966379641","5","377212838"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=57015819359&cr_id=331239455455&cv_id=5",metadata:["57015819359","331239455455","5","1499135732"]},
-{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=57015819359&cr_id=331239455458&cv_id=4",metadata:["57015819359","331239455458","4","1499135732"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=57015819359&cr_id=331239455461&cv_id=5",metadata:["57015819359","331239455461","5","1499135732"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197294&cv_id=4",metadata:["52836427830","310927197294","4",
-"608936333"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197297&cv_id=4",metadata:["52836427830","310927197297","4","608936333"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197300&cv_id=4",metadata:["52836427830","310927197300","4","608936333"]}]};var wb={"1j115753478":[[["52836427830","310927197294","4",[[["1643849995",[3.09375,.8203125,1.4765625,-.55078125,1.9140625,-.78125,-1.1640625,-3.15625,1.25,3.421875,1.6484375,1.0625,4.96875,-.66796875,-1.4375,.87109375,1.6171875,-4.125,-2.375,3.421875,-2.359375,1.6015625,.625,-4.65625,-5.03125,.416015625,-4.03125,-.24609375,3.296875,-.052001953125,-3.75,3.765625]],["1643804092",[3.09375,.796875,1.46875,-.56640625,1.890625,-.76953125,-1.1484375,-3.140625,1.2109375,3.421875,1.625,1.046875,4.9375,-.65234375,
--1.421875,.84765625,1.6015625,-4.125,-2.359375,3.453125,-2.34375,1.5859375,.63671875,-4.65625,-5,.396484375,-4.03125,-.26171875,3.296875,-.068359375,-3.734375,3.75]]],null,[["1643822293",[-.039794921875,.035400390625,.357421875,.041748046875,.0054931640625,-.060791015625,.138671875,-.318359375,.2255859375,.10546875,.2099609375,-.240234375,-.07373046875,-.279296875,-.44140625,.015380859375,-.298828125,.119140625,-.09716796875,.1796875,.04248046875,.09033203125,.38671875,.412109375,-.357421875,.259765625,
--.24609375,-.3828125,.33984375,.07861328125,-.1259765625,.3046875]],["1643799063",[.0079345703125,.0546875,.353515625,.00958251953125,-.01318359375,-.10888671875,.13671875,-.373046875,.208984375,.09228515625,.1962890625,-.248046875,-.031494140625,-.2734375,-.42578125,.0035400390625,-.345703125,.1083984375,-.068359375,.173828125,.0810546875,.1162109375,.361328125,.451171875,-.3671875,.162109375,-.212890625,-.46484375,.337890625,.1083984375,-.177734375,.318359375]]],null,null,null,null,[[null,[318.3513488769531,
-1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197297","4",[[["1643849995",[3.125,.953125,1.484375,-.46875,2.109375,-.89453125,-1.265625,-3.15625,1.265625,3.421875,1.7578125,1.1796875,4.9375,-.6796875,-1.5234375,.953125,1.7734375,-4.125,-2.453125,3.4375,-2.375,1.6328125,.3984375,-4.375,-4.96875,.59375,-4.03125,-.08935546875,3.34375,.1806640625,-3.8125,3.796875]],["1643804092",[3.125,.90625,1.4609375,-.5,2.046875,-.8671875,
--1.234375,-3.140625,1.2265625,3.421875,1.71875,1.1328125,4.90625,-.65625,-1.4921875,.921875,1.734375,-4.125,-2.421875,3.46875,-2.34375,1.6015625,.4296875,-4.375,-4.9375,.55078125,-4.03125,-.123046875,3.328125,.1416015625,-3.78125,3.765625]]],null,[["1643822293",[-.060546875,.0185546875,.353515625,.02587890625,.00311279296875,-.07421875,.1533203125,-.3203125,.2470703125,.06689453125,.193359375,-.234375,.029296875,-.255859375,-.44921875,.0146484375,-.306640625,.11962890625,-.10498046875,.1865234375,
-.049072265625,.1162109375,.365234375,.42578125,-.359375,.26953125,-.2490234375,-.392578125,.306640625,.1103515625,-.1376953125,.310546875]],["1643799063",[-.015869140625,.02978515625,.337890625,-.00628662109375,-.0169677734375,-.12353515625,.1494140625,-.373046875,.232421875,.056640625,.1806640625,-.2353515625,.0966796875,-.2451171875,-.43359375,.004180908203125,-.353515625,.107421875,-.087890625,.1865234375,.087890625,.138671875,.345703125,.455078125,-.36328125,.181640625,-.224609375,-.486328125,
-.294921875,.13671875,-.19921875,.3203125]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197300","4",[[["1643849995",[3.109375,.99609375,1.59375,-.4609375,2.171875,-.91015625,-1.296875,-3.3125,1.3984375,3.4375,1.8046875,1.2578125,5.09375,-.7421875,-1.59375,1.0078125,1.8125,-4.1875,-2.578125,3.390625,-2.53125,1.765625,.54296875,-4.71875,-5.09375,.55859375,-4.09375,-.1318359375,
-3.328125,.0654296875,-3.890625,3.859375]],["1643804092",[3.109375,.953125,1.5703125,-.48828125,2.109375,-.88671875,-1.2734375,-3.296875,1.359375,3.4375,1.7734375,1.21875,5.0625,-.71875,-1.5625,.9765625,1.7734375,-4.1875,-2.53125,3.4375,-2.5,1.734375,.5703125,-4.71875,-5.0625,.5234375,-4.0625,-.1591796875,3.328125,.03515625,-3.84375,3.828125]]],null,[["1643822293",[-.048095703125,.0179443359375,.36328125,.033203125,.030029296875,-.07568359375,.15625,-.326171875,.224609375,.07568359375,.1787109375,
--.234375,-.0277099609375,-.265625,-.412109375,.00909423828125,-.3046875,.11865234375,-.103515625,.1767578125,.048095703125,.12158203125,.36328125,.421875,-.359375,.255859375,-.25,-.396484375,.29296875,.10205078125,-.1279296875,.318359375]],["1643799063",[-.0045166015625,.03173828125,.353515625,.003631591796875,.00927734375,-.126953125,.154296875,-.37890625,.208984375,.06689453125,.1708984375,-.234375,.03173828125,-.255859375,-.396484375,-.00384521484375,-.353515625,.10693359375,-.0830078125,.1708984375,
-.08935546875,.1474609375,.341796875,.44921875,-.3671875,.1669921875,-.224609375,-.482421875,.28125,.130859375,-.1796875,.326171875]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j380357233":[[["52836427830","310927197294","4",[[["1643849995",[4.53125,1.8671875,.13671875,3.3125,-7.5625,.546875,2.953125,-7.90625,4.71875,7.375,.0047607421875,-3.25,.74609375,.298828125,-1.34375,-2.4375,-6.34375,
--9.1875,-1.3359375,9.875,1.1796875,-3.15625,3.796875,-6.90625,-3.203125,-.09375,-7.65625,-.71875,4.65625,-.75390625,-6.28125,3.6875]],["1643804092",[4.53125,1.9453125,.19140625,3.40625,-7.53125,.52734375,2.9375,-7.9375,4.625,7.375,.01416015625,-3.25,.74609375,.28125,-1.34375,-2.484375,-6.34375,-9.25,-1.328125,9.9375,1.2421875,-3.171875,3.71875,-6.71875,-3.21875,-.0311279296875,-7.71875,-.69140625,4.65625,-.70703125,-6.40625,3.71875]]],null,[["1643822293",[-.09033203125,.037109375,.423828125,.0439453125,
-.0390625,-.04345703125,.162109375,-.3125,.2197265625,.06884765625,.25,-.240234375,-.07763671875,-.267578125,-.416015625,.0150146484375,-.2890625,.126953125,-.08740234375,.158203125,.035888671875,.130859375,.3515625,.412109375,-.38671875,.27734375,-.234375,-.408203125,.337890625,.0458984375,-.1328125,.36328125]],["1643799063",[-.044921875,.056640625,.3984375,.0162353515625,.01373291015625,-.08544921875,.1611328125,-.359375,.1982421875,.06298828125,.2421875,-.2421875,-.05078125,-.263671875,-.39453125,
-.001953125,-.33203125,.11767578125,-.060546875,.1513671875,.07080078125,.14453125,.3359375,.4453125,-.388671875,.1865234375,-.1904296875,-.48046875,.3359375,.0693359375,-.177734375,.37109375]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197297","4",[[["1643849995",[4.4375,1.90625,.20703125,3.125,-7.03125,.44140625,2.703125,-7.46875,4.5,7.1875,.080078125,-3.03125,.94140625,
-.25390625,-1.3203125,-2.25,-5.875,-8.875,-1.375,9.4375,1.0234375,-2.984375,3.453125,-6.46875,-3.171875,.007781982421875,-7.4375,-.62890625,4.5625,-.58984375,-6.125,3.609375]],["1643804092",[4.46875,1.9765625,.26171875,3.1875,-6.9375,.41015625,2.671875,-7.53125,4.375,7.21875,.09716796875,-3.015625,1.0078125,.232421875,-1.3203125,-2.28125,-5.84375,-8.875,-1.3828125,9.5625,1.0859375,-2.96875,3.359375,-6.3125,-3.234375,.06494140625,-7.5,-.6171875,4.5625,-.53125,-6.28125,3.703125]]],null,[["1643822293",
-[-.107421875,.017822265625,.427734375,.0274658203125,.0289306640625,-.05908203125,.17578125,-.31640625,.2373046875,.033447265625,.2470703125,-.23046875,.00579833984375,-.25,-.421875,.01385498046875,-.298828125,.1240234375,-.09912109375,.16796875,.036865234375,.1435546875,.33984375,.4296875,-.380859375,.28515625,-.232421875,-.427734375,.3125,.0654296875,-.1513671875,.373046875]],["1643799063",[-.07177734375,.024658203125,.396484375,-.0016937255859375,.01434326171875,-.11328125,.1748046875,-.3671875,
-.2255859375,.026611328125,.224609375,-.2197265625,.07470703125,-.232421875,-.396484375,.01507568359375,-.341796875,.11376953125,-.087890625,.16015625,.072265625,.173828125,.3203125,.44921875,-.3828125,.19921875,-.2080078125,-.5078125,.28125,.1044921875,-.21484375,.380859375]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197300","4",[[["1643849995",[4.5,1.96875,.2099609375,
-3.328125,-7.28125,.458984375,2.8125,-7.84375,4.84375,7.3125,.09814453125,-3.078125,.859375,.224609375,-1.4296875,-2.3125,-6.09375,-9.125,-1.4453125,9.75,1.0078125,-3,3.71875,-6.90625,-3.203125,-.04931640625,-7.5625,-.6328125,4.625,-.69140625,-6.25,3.671875]],["1643804092",[4.5,2.09375,.298828125,3.453125,-7.1875,.416015625,2.765625,-7.90625,4.75,7.3125,.1318359375,-3.046875,.9140625,.17578125,-1.4453125,-2.328125,-6.0625,-9.125,-1.46875,9.75,1.046875,-2.984375,3.59375,-6.6875,-3.25,.041015625,-7.625,
--.5859375,4.625,-.6171875,-6.40625,3.75]]],null,[["1643822293",[-.09765625,.0216064453125,.421875,.03955078125,.056396484375,-.0546875,.1767578125,-.31640625,.208984375,.04248046875,.2265625,-.2314453125,-.0419921875,-.2578125,-.3828125,.0084228515625,-.29296875,.123046875,-.09423828125,.1533203125,.0380859375,.1474609375,.333984375,.4140625,-.384765625,.275390625,-.232421875,-.4140625,.291015625,.06591796875,-.1337890625,.376953125]],["1643799063",[-.0673828125,.03271484375,.41796875,.01336669921875,
-.041748046875,-.10595703125,.1767578125,-.37109375,.1982421875,.0294189453125,.212890625,-.2275390625,.02880859375,-.248046875,-.361328125,.00909423828125,-.337890625,.115234375,-.0732421875,.14453125,.07080078125,.1875,.310546875,.4453125,-.39453125,.1875,-.203125,-.5078125,.26953125,.095703125,-.1962890625,.40625]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149038",
-null,[[["1643849995",[7.875,2.375,-3.078125,9.8125,-20.875,2.46875,9.1875,-18.25,10,13.0625,-1.1171875,-8.875,-6.9375,2.078125,-2.1875,-7.34375,-17.375,-19.375,.640625,21.375,7.0625,-9.875,7.875,-9.5625,-2.09375,.034423828125,-13.4375,-.3359375,8.5625,-.75390625,-11.375,6.15625]],["1643804092",[7.875,2.4375,-3.015625,10,-20.75,2.453125,9.1875,-18.25,9.6875,13,-1.1484375,-8.9375,-6.875,2.078125,-2.125,-7.4375,-17.5,-19.25,.71875,21.25,7.3125,-9.9375,7.65625,-9.125,-2.171875,.1513671875,-13.5625,-.34765625,
-8.5625,-.69921875,-11.6875,6.28125]]],null,[["1643822293",[-.337890625,-.1884765625,.1923828125,-.0213623046875,-.1953125,.5234375,.326171875,.0908203125,-.09033203125,.019775390625,.40234375,.462890625,-.19921875,-.08642578125,-.29296875,-.1943359375,.248046875,-.2470703125,-.2099609375,.2353515625,.0400390625,.1767578125,.828125,-.059326171875,-.0218505859375,.5703125,-.431640625,-.30859375,.19921875,.1455078125,-.486328125,-.2578125]],["1643799063",[-.37109375,-.1455078125,.361328125,-.0595703125,
--.1611328125,.5234375,.3203125,.07568359375,-.0791015625,.03173828125,.423828125,.4609375,-.2412109375,-.09130859375,-.310546875,-.193359375,.232421875,-.2353515625,-.19140625,.2177734375,.0205078125,.232421875,.8359375,-.04150390625,-.045166015625,.55078125,-.451171875,-.412109375,.298828125,.1220703125,-.56640625,-.11767578125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038",
-"113383149158",null,[[["1643849995",[8.1875,2.0625,-3.328125,9.5,-21.125,2.609375,9.3125,-17.875,9.5,13.375,-1.2578125,-9.1875,-7,2.265625,-1.9140625,-7.5,-17.625,-19.5,.953125,21.375,7.46875,-10.3125,7.65625,-9.125,-2.265625,.02490234375,-13.75,-.4375,8.8125,-.59765625,-11.4375,6.40625]],["1643804092",[8.125,2.140625,-3.25,9.6875,-21.125,2.59375,9.3125,-17.875,9.25,13.25,-1.25,-9.1875,-6.90625,2.234375,-1.8671875,-7.5625,-17.625,-19.5,1.0078125,21.25,7.625,-10.375,7.5,-8.8125,-2.359375,.1494140625,
--13.75,-.458984375,8.75,-.5625,-11.6875,6.5]]],null,[["1643822293",[-.349609375,-.19140625,.1767578125,-.0213623046875,-.197265625,.5234375,.330078125,.0927734375,-.0908203125,.027587890625,.3984375,.462890625,-.2001953125,-.0810546875,-.296875,-.19140625,.2490234375,-.244140625,-.2119140625,.2392578125,.0400390625,.181640625,.828125,-.05859375,-.0181884765625,.5703125,-.4296875,-.302734375,.1982421875,.1494140625,-.490234375,-.263671875]],["1643799063",[-.369140625,-.1435546875,.353515625,-.05908203125,
--.1552734375,.515625,.322265625,.0703125,-.07177734375,.04345703125,.421875,.45703125,-.248046875,-.08935546875,-.30859375,-.1953125,.2255859375,-.2333984375,-.1943359375,.220703125,.021484375,.2431640625,.83984375,-.0419921875,-.04052734375,.54296875,-.443359375,-.41015625,.30078125,.11767578125,-.5703125,-.12158203125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",
-null,[[["1643849995",[7.71875,2.21875,-2.984375,9.3125,-20.25,2.40625,8.875,-17.375,9.5,12.75,-1.1015625,-8.6875,-6.53125,2.03125,-2.03125,-7.09375,-16.875,-18.625,.61328125,20.625,6.84375,-9.625,7.625,-9.3125,-2.140625,-.0341796875,-13.125,-.435546875,8.375,-.8046875,-11.0625,6]],["1643804092",[7.65625,2.328125,-2.875,9.5,-20.125,2.375,8.8125,-17.375,9.3125,12.625,-1.09375,-8.625,-6.46875,1.9921875,-2.015625,-7.125,-16.875,-18.625,.671875,20.5,7,-9.625,7.4375,-8.9375,-2.15625,.1357421875,-13.125,
--.4140625,8.25,-.73046875,-11.25,6.0625]]],null,[["1643822293",[-.34765625,-.193359375,.208984375,-.025390625,-.201171875,.5234375,.330078125,.09326171875,-.09423828125,.0084228515625,.41015625,.46484375,-.1767578125,-.08251953125,-.310546875,-.19140625,.25,-.24609375,-.212890625,.2392578125,.0380859375,.17578125,.828125,-.0576171875,-.01904296875,.578125,-.43359375,-.31640625,.2060546875,.14453125,-.4921875,-.255859375]],["1643799063",[-.369140625,-.150390625,.37890625,-.0546875,-.1630859375,.53125,
-.3203125,.08251953125,-.08447265625,.01318359375,.43359375,.462890625,-.2392578125,-.09619140625,-.310546875,-.189453125,.2421875,-.2333984375,-.1953125,.2119140625,.0142822265625,.23046875,.83203125,-.0284423828125,-.047119140625,.55078125,-.447265625,-.427734375,.306640625,.115234375,-.57421875,-.107421875]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j395640136":[[["31279674038","113383149038",
-null,[[["1643849995",[3.34375,.197265625,.66015625,-.796875,1.1015625,-.5546875,-.78515625,-2.21875,.84765625,3.390625,1.28125,.482421875,3.9375,-.1865234375,-1.09375,.609375,1.1484375,-4.0625,-1.7890625,4.5625,-1.859375,.83203125,.64453125,-4,-4.09375,.02587890625,-3.734375,-.31640625,3.65625,-.025146484375,-2.5625,3.03125]],["1643804092",[3.34375,.177734375,.6484375,-.8125,1.078125,-.54296875,-.76953125,-2.203125,.81640625,3.40625,1.265625,.462890625,3.9375,-.171875,-1.078125,.59375,1.125,-4.09375,
--1.7734375,4.59375,-1.8359375,.8203125,.65625,-3.984375,-4.09375,.0101318359375,-3.75,-.33203125,3.671875,-.039794921875,-2.546875,3.015625]]],null,[["1643822293",[-.345703125,-.1962890625,.2109375,-.034912109375,-.2158203125,.5234375,.3359375,.09619140625,-.09326171875,.01385498046875,.427734375,.474609375,-.1806640625,-.0771484375,-.3203125,-.2060546875,.2451171875,-.2578125,-.2177734375,.2490234375,.035888671875,.1513671875,.84375,-.04638671875,-.01220703125,.5703125,-.439453125,-.32421875,.2138671875,
-.1513671875,-.50390625,-.263671875]],["1643799063",[-.3828125,-.1494140625,.384765625,-.058837890625,-.1826171875,.53125,.322265625,.0859375,-.08837890625,.0159912109375,.458984375,.462890625,-.2275390625,-.08984375,-.328125,-.1962890625,.23828125,-.23828125,-.189453125,.22265625,.01556396484375,.2109375,.83203125,-.0238037109375,-.044677734375,.55859375,-.453125,-.43359375,.31640625,.12158203125,-.57421875,-.11328125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,
-[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149158",null,[[["1643849995",[3.34375,.130859375,.62109375,-.84765625,.98046875,-.453125,-.68359375,-2.03125,.51953125,3.453125,1.140625,.291015625,3.96875,-.15625,-.8828125,.435546875,1.0078125,-4,-1.515625,4.15625,-1.5234375,.62890625,.37890625,-3.421875,-4.21875,.1220703125,-3.84375,-.345703125,3.5625,.10791015625,-2.828125,3.25]],["1643804092",[3.34375,.130859375,.62109375,-.8515625,.98046875,-.451171875,
--.68359375,-2.03125,.50390625,3.453125,1.1328125,.287109375,3.96875,-.1533203125,-.875,.427734375,1.0078125,-4,-1.5078125,4.15625,-1.515625,.625,.369140625,-3.390625,-4.21875,.1259765625,-3.84375,-.34765625,3.5625,.11181640625,-2.828125,3.25]]],null,[["1643822293",[-.3515625,-.1982421875,.185546875,-.027099609375,-.21875,.5234375,.333984375,.099609375,-.09423828125,.0244140625,.42578125,.47265625,-.1845703125,-.0751953125,-.314453125,-.2001953125,.2470703125,-.25390625,-.216796875,.248046875,.036865234375,
-.1533203125,.83984375,-.044189453125,-.00933837890625,.5703125,-.43359375,-.31640625,.212890625,.15625,-.5,-.275390625]],["1643799063",[-.38671875,-.138671875,.375,-.061767578125,-.177734375,.5234375,.3203125,.07666015625,-.080078125,.033447265625,.4453125,.447265625,-.2333984375,-.09130859375,-.333984375,-.19921875,.2265625,-.2275390625,-.18359375,.2255859375,.02197265625,.2197265625,.828125,-.0189208984375,-.047119140625,.55078125,-.44140625,-.4296875,.328125,.11962890625,-.5703125,-.11572265625]]],
-null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",null,[[["1643849995",[3.21875,.1484375,.6796875,-.8203125,1,-.486328125,-.73046875,-2.21875,.77734375,3.3125,1.1875,.419921875,3.875,-.1904296875,-1.015625,.52734375,1.046875,-3.984375,-1.7265625,4.46875,-1.8046875,.828125,.7421875,-4.03125,-4.0625,-.07080078125,-3.671875,-.3984375,3.53125,-.1494140625,-2.515625,2.953125]],
-["1643804092",[3.21875,.1416015625,.671875,-.828125,1,-.486328125,-.73046875,-2.21875,.75390625,3.3125,1.1796875,.416015625,3.890625,-.1796875,-1.015625,.51953125,1.046875,-3.984375,-1.71875,4.5,-1.7890625,.8203125,.73046875,-4,-4.0625,-.06640625,-3.6875,-.3984375,3.53125,-.142578125,-2.53125,2.96875]]],null,[["1643822293",[-.349609375,-.19921875,.2109375,-.03173828125,-.2158203125,.53515625,.333984375,.10400390625,-.11181640625,.00836181640625,.431640625,.4765625,-.16796875,-.07568359375,-.32421875,
--.201171875,.25390625,-.26171875,-.21875,.251953125,.032958984375,.142578125,.83984375,-.05126953125,-.00836181640625,.58203125,-.439453125,-.31640625,.21875,.1513671875,-.498046875,-.267578125]],["1643799063",[-.376953125,-.1513671875,.38671875,-.061279296875,-.1875,.53125,.322265625,.08642578125,-.08935546875,.01324462890625,.45703125,.462890625,-.224609375,-.08984375,-.333984375,-.19921875,.23828125,-.240234375,-.1962890625,.2197265625,.01519775390625,.2041015625,.8359375,-.0179443359375,-.041748046875,
-.5546875,-.451171875,-.43359375,.3203125,.123046875,-.578125,-.11962890625]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j396781473":[[["31279674038","113383149038",null,[[["1643849995",[3.28125,.37890625,.828125,-.734375,1.3359375,-.625,-.89453125,-2.390625,.7578125,3.40625,1.3515625,.58984375,4.125,-.2734375,-1.125,.6171875,1.2734375,-4.0625,-1.859375,4.3125,-1.84375,.953125,.427734375,
--3.71875,-4.28125,.2119140625,-3.828125,-.244140625,3.5625,.134765625,-2.9375,3.25]],["1643804092",[3.28125,.345703125,.80859375,-.75390625,1.2890625,-.6015625,-.87109375,-2.375,.72265625,3.40625,1.3203125,.5546875,4.09375,-.255859375,-1.09375,.5859375,1.234375,-4.0625,-1.828125,4.34375,-1.8125,.92578125,.4453125,-3.71875,-4.28125,.185546875,-3.84375,-.267578125,3.5625,.111328125,-2.921875,3.234375]]],null,[["1643822293",[-.32421875,-.203125,.212890625,-.006622314453125,-.224609375,.5234375,.330078125,
-.099609375,-.08203125,-.01239013671875,.41015625,.484375,-.140625,-.0751953125,-.3046875,-.17578125,.251953125,-.25,-.2119140625,.2119140625,.030029296875,.1689453125,.8359375,-.041748046875,-.022216796875,.5546875,-.412109375,-.34375,.1748046875,.1806640625,-.5,-.2470703125]],["1643799063",[-.3359375,-.1572265625,.376953125,-.039306640625,-.1982421875,.515625,.314453125,.076171875,-.0595703125,-.0079345703125,.43359375,.4765625,-.208984375,-.091796875,-.3125,-.1708984375,.23046875,-.23828125,-.1962890625,
-.1787109375,.01556396484375,.220703125,.84375,-.0184326171875,-.052001953125,.51953125,-.4296875,-.458984375,.263671875,.1494140625,-.58203125,-.10498046875]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149158",null,[[["1643849995",[3.328125,.369140625,.8125,-.7578125,1.3125,-.56640625,-.84375,-2.25,.478515625,3.484375,1.2734375,.462890625,4.21875,-.265625,-.96875,.4921875,
-1.2109375,-4.03125,-1.640625,3.875,-1.5546875,.7890625,.10302734375,-3.125,-4.4375,.375,-3.96875,-.2236328125,3.5,.3359375,-3.265625,3.515625]],["1643804092",[3.3125,.349609375,.80078125,-.76953125,1.28125,-.5546875,-.828125,-2.234375,.4453125,3.46875,1.25,.44140625,4.1875,-.251953125,-.94921875,.47265625,1.1875,-4.03125,-1.6171875,3.890625,-1.53125,.76953125,.10888671875,-3.109375,-4.4375,.359375,-3.953125,-.236328125,3.5,.32421875,-3.234375,3.5]]],null,[["1643822293",[-.326171875,-.201171875,.1884765625,
--.0014190673828125,-.2216796875,.53125,.330078125,.10107421875,-.0849609375,-.00994873046875,.404296875,.4765625,-.1513671875,-.07470703125,-.298828125,-.17578125,.25390625,-.2421875,-.2099609375,.2109375,.0322265625,.1728515625,.83203125,-.0380859375,-.0242919921875,.55859375,-.408203125,-.33984375,.177734375,.18359375,-.494140625,-.25390625]],["1643799063",[-.33984375,-.1474609375,.3515625,-.03466796875,-.1923828125,.5078125,.3125,.0712890625,-.057861328125,.01446533203125,.431640625,.46484375,
--.2109375,-.0927734375,-.310546875,-.17578125,.220703125,-.2294921875,-.1923828125,.1796875,.023681640625,.2314453125,.83984375,-.0205078125,-.049072265625,.51953125,-.41796875,-.4453125,.2734375,.1513671875,-.57421875,-.115234375]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",null,[[["1643849995",[3.15625,.34765625,.8515625,-.74609375,1.2578125,-.56640625,-.85546875,
--2.40625,.6953125,3.328125,1.265625,.546875,4.09375,-.283203125,-1.0625,.54296875,1.1953125,-3.984375,-1.8046875,4.1875,-1.796875,.95703125,.5,-3.75,-4.25,.1376953125,-3.78125,-.310546875,3.4375,.03173828125,-2.921875,3.1875]],["1643804092",[3.171875,.322265625,.8359375,-.765625,1.2265625,-.546875,-.8359375,-2.390625,.65625,3.328125,1.2421875,.515625,4.0625,-.265625,-1.0390625,.51953125,1.171875,-3.984375,-1.7734375,4.21875,-1.765625,.93359375,.5,-3.71875,-4.25,.12353515625,-3.78125,-.32421875,3.4375,
-.0242919921875,-2.921875,3.1875]]],null,[["1643822293",[-.32421875,-.21484375,.212890625,-.00543212890625,-.2333984375,.52734375,.333984375,.10498046875,-.08740234375,-.0296630859375,.416015625,.49609375,-.1357421875,-.072265625,-.302734375,-.1728515625,.2578125,-.259765625,-.2177734375,.208984375,.028564453125,.1640625,.83984375,-.042724609375,-.0184326171875,.55859375,-.41796875,-.345703125,.162109375,.185546875,-.5078125,-.25390625]],["1643799063",[-.345703125,-.1650390625,.375,-.041748046875,
--.1962890625,.51953125,.318359375,.08056640625,-.06396484375,-.004486083984375,.447265625,.486328125,-.197265625,-.0888671875,-.3203125,-.166015625,.234375,-.2431640625,-.2041015625,.1826171875,.01495361328125,.2216796875,.84765625,-.029052734375,-.044921875,.53125,-.431640625,-.4609375,.2578125,.1494140625,-.5859375,-.115234375]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j475122041":[[["60795725037",
-"306664789872",null,[[["1643849995",[3.421875,1.78125,1.6796875,.048095703125,2.796875,-1.3984375,-1.703125,-3.5625,1.328125,3.796875,2.265625,1.5,5.125,-.80078125,-1.8515625,1.1796875,2.203125,-4.53125,-2.78125,3.5625,-2.265625,1.6796875,-.76171875,-2.8125,-5.09375,1.5078125,-4.5,.59375,3.609375,1.359375,-4.78125,4.375]],["1643804092",[3.40625,1.75,1.6640625,.0306396484375,2.75,-1.3828125,-1.6875,-3.53125,1.3125,3.78125,2.25,1.4765625,5.09375,-.79296875,-1.828125,1.171875,2.171875,-4.53125,-2.765625,
-3.5625,-2.25,1.6640625,-.73046875,-2.84375,-5.0625,1.4765625,-4.5,.56640625,3.609375,1.3203125,-4.75,4.34375]]],null,[["1643822293",[1.2734375,1.0859375,.298828125,.09619140625,.10107421875,-.09375,-.52734375,-.953125,-.1259765625,-.5078125,-.1611328125,-.498046875,-1.3515625,-.412109375,.94140625,-.33984375,-.578125,.2578125,.47265625,-.478515625,.255859375,-.1005859375,-.06396484375,.166015625,-.9765625,.029541015625,.314453125,.0106201171875,.74609375,-.38671875,.83984375,.75390625]],["1643799063",
-[1.3046875,1.0625,.3828125,.06201171875,.1142578125,-.046875,-.52734375,-.94921875,-.134765625,-.56640625,-.08740234375,-.439453125,-1.3671875,-.4296875,1.046875,-.33203125,-.5625,.2734375,.50390625,-.54296875,.1728515625,-.123046875,-.0233154296875,.1962890625,-1.0546875,.05859375,.318359375,-.0537109375,.8125,-.423828125,.79296875,.953125]]],null,null,null,null,[[null,[61170.82421875,1],[1,2],[1,1],null,3]]],[null,[[3,0,null,["AdvControlbrand-unsafe"]]]],"1614272341"]]]};function xb(a,b){return!b||0>=b?a:Math.min(a,b)}function R(a,b,c){return b?b:c?c:a?1:0}function yb(a){a=null==a?void 0:G(a,9,0);return void 0===a?!1:[61,51,52].includes(a)};var S=function(a){Q.call(this,a,-1,zb)};t(S,Q);var zb=[2];var Ab=function(a){Q.call(this,a)};t(Ab,Q);var Cb=function(a){Q.call(this,a,-1,Bb)};t(Cb,Q);Cb.prototype.ca=function(){return N(this,Ab,3)};var Bb=[2,3];var Eb=function(a){Q.call(this,a,-1,Db)};t(Eb,Q);var Gb=function(a){Q.call(this,a,-1,Fb)};t(Gb,Q);var Ib=function(a){Q.call(this,a,-1,Hb)};t(Ib,Q);Ib.prototype.ca=function(){return N(this,Ab,5)};var Db=[1,2],Fb=[3,4],Hb=[3,4,5];var Kb=function(a){Q.call(this,a,-1,Jb)};t(Kb,Q);var T=function(a){return M(a,Lb,3)},Nb=function(a){Q.call(this,a,-1,Mb)};t(Nb,Q);Nb.prototype.Y=function(){return N(this,S,2)};Nb.prototype.ma=function(){return N(this,S,3)};var Ob=function(a){Q.call(this,a)};t(Ob,Q);Ob.prototype.u=function(){return O(this,1)};Ob.prototype.v=function(){return O(this,2)};Ob.prototype.da=function(){return J(this,3)};var Lb=function(a){Q.call(this,a)};t(Lb,Q);var U=function(a){Q.call(this,a)};t(U,Q);
-var V=function(a){Q.call(this,a)};t(V,Q);var Rb=function(a){var b=new V;return L(b,1,a)},X=function(a){Q.call(this,a)};t(X,Q);X.prototype.u=function(){return O(this,2)};X.prototype.v=function(){return O(this,3)};X.prototype.W=function(){return O(this,4)};X.prototype.da=function(){return J(this,5)};var Jb=[2],Mb=[1,2,3];function Sb(a,b,c){if(!b||0>=b)return{l:0,P:1};var d=R(!0,null==a?void 0:J(a,1),null==c?void 0:J(c,1)),e=R(!1,null==a?void 0:J(a,2),null==c?void 0:J(c,2)),g=R(!1,null==a?void 0:J(a,3),null==c?void 0:J(c,3)),f,h;a=R(!1,null==a?void 0:null==(f=M(a,V,5))?void 0:J(f,1),null==c?void 0:null==(h=M(c,V,5))?void 0:J(h,1));c=new U;f=L(c,1,d);f=L(f,2,e);f=L(f,3,g);h=Rb(a);eb(f,V,5,h);return{l:b*d*(1-1/(1+Math.exp(-e*(Math.log(b/1E6)-a-g)))),P:4,sa:c}};function Tb(a,b){var c=null==a?void 0:M(a,U,6),d,e=null==a?void 0:null==(d=T(a))?void 0:M(d,U,3);if(!b||0>=b)return{l:0,P:1};var g;if(!(null==a?0:null==(g=T(a))?0:I(g,2)))return{l:.85*b,P:2};d=R(!0,null==c?void 0:J(c,4),null==e?void 0:J(e,4));g=R(!0,null==c?void 0:J(c,1),null==e?void 0:J(e,1));var f=R(!1,null==c?void 0:J(c,2),null==e?void 0:J(e,2)),h=R(!1,null==c?void 0:J(c,3),null==e?void 0:J(e,3)),l,k;c=R(!1,null==c?void 0:null==(l=M(c,V,5))?void 0:J(l,1),null==e?void 0:null==(k=M(e,V,5))?void 0:
-J(k,1));l=new U;k=L(l,1,g);k=L(k,2,f);k=L(k,3,h);k=L(k,4,d);var m=Rb(c);eb(k,V,5,m);d=d*b*g*(1-1/(1+Math.exp(-f*(Math.log(d*b/1E6)-c-h))));g=1E6*(null==a?NaN:J(a,8));var q;if((null==a?0:null==(q=T(a))?0:I(q,6))&&d<g&&g<b){var y;d=g+1E6*(null!=(y=null==e?void 0:J(e,7))?y:0)*Math.log(b/g)}return{l:d,P:3,sa:l}};function Ub(a,b){if(!(0<F(a,2).length&&F(a,2).length===E(a,3).length&&F(a,2).length===F(a,4).length))return 0;for(var c=0,d=0,e=1,g=r(E(a,3)),f=g.next();!f.done;f=g.next()){var h=0;switch(f.value){case 1:h=F(a,2)[d]*(b.ea?Math.pow(b.ea,F(a,4)[d]):0);break;case 2:c=h=F(a,2)[d]*(b.oa?Math.pow(b.oa,F(a,4)[d]):0);break;case 3:h=F(a,2)[d]}if(0===h)return 0;e*=h;d+=1}0<J(a,7)&&(e=Math.min(e,J(a,7)*c*1E3));return 1E6*e}
-function Vb(a,b){var c=0;b&&(0<N(b,Wb,7).length?c=Ub(N(b,Wb,7)[0],a):0<N(b,Wb,8).length&&(c=Ub(N(b,Wb,8)[0],a)));return c};function Xb(a,b,c){if(G(a,2,0)!==G(b,2,0))return c;var d=!1;switch(G(a,2,0)){case 1:a:{var e,g=new Set(null!=(e=E(a,3))?e:[]);b=r(E(b,3));for(e=b.next();!e.done;e=b.next())if(g.has(e.value)){d=!0;break a}d=!1}break;case 0:a:{e=new Set(null!=(g=E(a,4))?g:[]);b=r(E(b,4));for(g=b.next();!g.done;g=b.next())if(e.has(g.value)){d=!0;break a}d=!1}break;case 2:b=new Yb(b),d=(e=M(a,Cb,5))?Zb(b,e):!1}return I(a,6)?d?null:c:d?c:null}
-function Zb(a,b){var c=G(b,1,0),d=b.ca(),e=N(b,Cb,2);switch(c){case 2:c=d.every(function(g){return $b(a,g)})&&e.every(function(g){return Zb(a,g)});break;case 1:c=d.some(function(g){return $b(a,g)})||e.some(function(g){return Zb(a,g)});break;default:throw Error("unexpected value "+c+"!");}return I(b,4)?!c:c}
-var Yb=function(a){this.ga=new Map;a=r(a.ca());for(var b=a.next();!b.done;b=a.next()){var c=b.value;b=G(c,1,0);c=G(c,2,0);var d=this.ga.get(b);d||(d=new Set,this.ga.set(b,d));d.add(c)}},$b=function(a,b){var c=G(b,2,0);return(a=a.ga.get(G(b,1,0)))?a.has(c):!1};function ac(a,b){a=r((null==b?void 0:b.get(a))||[]);for(b=a.next();!b.done;b=a.next())if(b=b.value,b.count+1>b.xa)return!1;return!0};function bc(a,b){return null==a.na?!0:!a.na.some(function(c){var d;return null==(d=b.Ba)?void 0:d.includes(c,0)})};var cc=function(a){Q.call(this,a)};t(cc,Q);n=cc.prototype;n.u=function(){return O(this,1)};n.v=function(){return O(this,2)};n.W=function(){return O(this,3)};n.V=function(){return O(this,4)};n.U=function(){return O(this,5)};n.X=function(){return O(this,6)};var ec=function(a){Q.call(this,a,-1,dc)};t(ec,Q);var dc=[1];function fc(a,b){var c=!0;c=void 0===c?!1:c;return gc(0,(null==a?void 0:N(a,S,1))||[],(null==b?void 0:N(b,S,1))||[],c)}function hc(a,b){var c=!0;c=void 0===c?!1:c;return gc(1,(null==a?void 0:a.Y())||[],(null==b?void 0:b.Y())||[],c)}function ic(a,b){var c=!0;c=void 0===c?!1:c;return gc(1,(null==a?void 0:a.ma())||[],(null==b?void 0:b.Y())||[],c)}
-function gc(a,b,c,d){var e=0,g=new Map;b=r(b);for(var f=b.next();!f.done;f=b.next())e=f.value,g.set(G(e,1,""),e),e=J(e,3);b=null;c=r(c);for(f=c.next();!f.done;f=c.next()){var h=f.value;e=J(h,3);if(f=d?g.values().next().value:g.get(G(h,1,""))){a:{b=a;f=F(f,2);h=F(h,2);if(f.length===h.length){for(var l=0,k=0;k<f.length;k++)l+=f[k]*h[k];f=l}else f=void 0;if(void 0!==f)switch(b){case 0:b=1/(1+Math.exp(-1*f));break a;case 1:b=Math.exp(f);break a}b=void 0}if(void 0!==b)return b;b=e}}var m;return null!=
-(m=b)?m:e};var jc=function(a){Q.call(this,a)};t(jc,Q);function kc(a,b,c){"0"===a||c.has(a)||c.set(a,b.filter(function(d){return 0<G(d,3,0)}).map(function(d){var e=G(d,3,0);switch(G(d,1,0)){case 6:d=60*G(d,2,0);break;case 1:d=3600*G(d,2,0);break;case 2:d=86400*G(d,2,0);break;case 3:d=604800*G(d,2,0);break;case 4:d=2592E3*G(d,2,0);break;case 5:d=null;break;default:e=d=0}return{pa:d,xa:e,count:0}}))}function lc(a,b,c){if(b=c.get(b))for(b=r(b),c=b.next();!c.done;c=b.next())c=c.value,(null===c.pa||a.Aa<=c.pa)&&c.count++};var Wb=function(a){Q.call(this,a,-1,mc)};t(Wb,Q);var mc=[2,3,4];var oc=function(a){Q.call(this,a,-1,nc)};t(oc,Q);oc.prototype.Y=function(){return N(this,S,3)};oc.prototype.ma=function(){return N(this,S,10)};var nc=[1,3,10,7,8];var qc=function(a){Q.call(this,a,-1,pc)};t(qc,Q);n=qc.prototype;n.u=function(){return O(this,1)};n.v=function(){return O(this,2)};n.W=function(){return O(this,3)};n.V=function(){return O(this,6)};n.U=function(){return O(this,7)};n.X=function(){return O(this,8)};var pc=[9,10,11,12,13,14];var sc=function(a){Q.call(this,a,-1,rc)};t(sc,Q);var rc=[1];var uc=function(a){Q.call(this,a,-1,tc)};t(uc,Q);var tc=[1];var vc={ad:{},bid:0,render:""};function wc(){new uc;return function(a,b,c,d,e){return xc(a,c,d,e)}}
-function xc(a,b,c,d){b=b?new Kb(qb(b)):void 0;var e,g;if(!b||!(N(b,Ob,2).length||(null==(e=T(b))?0:I(e,1))||(null==(g=T(b))?0:I(g,5))))return vc;e=new ec(qb(a.userBiddingSignals));g=a.ads.map(function(f){return{renderUrl:f.renderUrl,metadata:new cc(qb(f.metadata))}});c=c[a.name]?new sc(qb(c[a.name])):void 0;d=d.prevWins.map(function(f){return{Aa:f[0],I:new cc(qb(f[1].metadata))}});return yc(a.name,e,g,d,c,b)}
-function yc(a,b,c,d,e,g){var f,h={Ja:null!=(f=null==g?void 0:T(g))?f:void 0,T:new Map,O:new Map,R:new Map,S:new Map,Z:new Map,interestGroupName:null!=a?a:void 0};a=new Map;if(e){e=r(N(e,qc,1));for(f=e.next();!f.done;f=e.next())f=f.value,a.set(f.u().concat("+",f.v(),"+",f.W()),f),kc(f.v(),N(f,jc,9),h.T),kc(f.u(),N(f,jc,10),h.O),kc(f.V(),N(f,jc,11),h.R),kc(f.U(),N(f,jc,12),h.S),kc(f.X(),N(f,jc,13),h.Z);d=r(d);for(e=d.next();!e.done;e=d.next())e=e.value,h.T&&lc(e,e.I.v(),h.T),h.O&&lc(e,e.I.u(),h.O),
-h.R&&lc(e,e.I.V(),h.R),h.S&&lc(e,e.I.U(),h.S),h.Z&&lc(e,e.I.X(),h.Z)}e=new Map;if(g)for(d=r(N(g,Ob,2)),f=d.next();!f.done;f=d.next())f=f.value,e.set(f.u().concat("+",f.v(),"+",""),f.da());d=[];c=r(c);for(f=c.next();!f.done;f=c.next()){f=f.value;f={renderUrl:f.renderUrl,H:f.metadata.u(),K:f.metadata.v(),ka:f.metadata.W(),ja:f.metadata.V(),ia:f.metadata.U(),la:f.metadata.X(),i:0,J:0};var l=f.H.concat("+",f.K,"+",f.ka);f.aa=e.get(f.H.concat("+",f.K,"+",""));if(!f.aa){var k=void 0,m=void 0,q=void 0,y=
-void 0;if(!(null==(k=g)?0:null==(m=T(k))?0:I(m,1))&&!(null==(q=g)?0:null==(y=T(q))?0:I(y,5)))continue;else if(!a.get(l))continue;m=k=void 0;f.o=null!=(m=null==(k=a.get(l))?void 0:M(k,oc,4))?m:void 0}m=k=void 0;f.ha=null!=(m=null==(k=a.get(l))?void 0:M(k,Eb,5))?m:void 0;m=k=void 0;f.na=null!=(m=null==(k=a.get(l))?void 0:E(k,14))?m:void 0;d.push(f)}if(c=null==g?void 0:M(g,Eb,5)){a=new Map;e=new Map;f=r(N(c,Gb,1));for(l=f.next();!l.done;l=f.next())l=l.value,a.set(G(l,1,0),l);c=r(N(c,Ib,2));for(f=c.next();!f.done;f=
-c.next())f=f.value,e.set(G(f,1,0),f);h.ta=a;h.ua=e}var H;h.Ba=null!=(H=E(b,1))?H:void 0;b=[];H=new Map;a=r(d);for(d=a.next();!d.done;d=a.next())if(d=d.value,e=h,!(!ac(d.K,e.T)||!ac(d.H,e.O)||d.ja&&!ac(d.ja,e.R)||d.ia&&!ac(d.ia,e.S)||d.la&&!ac(d.la,e.Z))){if(d.ha){c=h;e=c.ta;c=c.ua;f=d.ha;if(e&&c&&f)a:{l=r(N(f,Gb,1));for(k=l.next();!k.done;k=l.next()){q=k.value;y=G(q,1,0);var fa=c.get(y);if(fa){if(I(q,7)){k=H.get(y);m=G(q,8,0);if(void 0===k)k=new Map,H.set(y,k);else{var qa=k.get(m);if(void 0!==qa){e=
-qa;break a}}q=Xb(q,fa,y);k.set(m,q)}else q=Xb(q,fa,y);if(q){e=q;break a}}}c=r(N(f,Ib,2));for(f=c.next();!f.done;f=c.next())if(f=f.value,l=G(f,1,0),k=e.get(l))if(f=Xb(k,f,l)){e=f;break a}e=null}else e=null;if(e)continue}bc(d,h)&&b.push(d)}return zc({ads:b,ya:h},g).bidResponse}
-function zc(a,b){for(var c=[],d=[],e=r(a.ads),g=e.next();!g.done;g=e.next()){g=g.value;var f=void 0,h=void 0;if(null==(f=b)?0:null==(h=T(f))?0:I(h,7)){var l=h=f=void 0,k=void 0,m=void 0,q=void 0;g.H===(null==(f=b)?void 0:null==(h=M(f,X,16))?void 0:h.u())&&g.K===(null==(l=b)?void 0:null==(k=M(l,X,16))?void 0:k.v())&&a.ya.interestGroupName===(null==(m=b)?void 0:null==(q=M(m,X,16))?void 0:G(q,1,""))?(l=h=f=void 0,k=null!=(l=null==(f=b)?void 0:null==(h=M(f,X,16))?void 0:h.da())?l:0,g.i=0===k?1E9:k):g.i=
-0}else if(null!=g.aa){g.i=g.aa;c.push(g);continue}else if(h=f=void 0,null==(f=b)?0:null==(h=T(f))?0:I(h,1))yb(g.o)?(f=void 0,g.ea=ic(null==(f=b)?void 0:M(f,Nb,1),g.o)):(f=void 0,g.oa=fc(null==(f=b)?void 0:M(f,Nb,1),g.o),f=void 0,g.ea=hc(null==(f=b)?void 0:M(f,Nb,1),g.o)),g.i=Vb(g,g.o),g.i||(h=f=void 0,g.i=null!=(h=null==(f=g.o)?void 0:J(f,6))?h:0);else if(h=f=void 0,null==(f=b)?0:null==(h=T(f))?0:I(h,5))h=f=void 0,g.i=null!=(h=null==(f=g.o)?void 0:J(f,6))?h:0;d.push(g)}c={renderUrl:"",H:"",K:"",ka:"",
-i:0,J:0};var y;if(null==b?0:null==(y=T(b))?0:I(y,7))b=a.ads.reduce(function(W,K){return W.i<K.i?K:W},c),b.J=b.i;else{y=a.ads.reduce(function(W,K){return!yb(K.o)&&W.i<K.i?K:W},c);c=a.ads.reduce(function(W,K){return yb(K.o)&&W.i<K.i?K:W},c);a=Tb(b,null==y?void 0:y.i);var H,fa;a.l=xb(a.l,null==b?void 0:null==(H=T(b))?void 0:null==(fa=M(H,U,3))?void 0:J(fa,6));var qa;H=Sb(null==b?void 0:M(b,U,7),null==c?void 0:c.i,null==b?void 0:null==(qa=T(b))?void 0:M(qa,U,4));var Pb,Qb;H.l=xb(H.l,null==b?void 0:null==
-(Pb=T(b))?void 0:null==(Qb=M(Pb,U,4))?void 0:J(Qb,6));a.l>H.l?(b=y,b.J=a.l):(b=c,b.J=H.l)}return{bidResponse:{ad:{},bid:b.J,render:b.renderUrl},debugInfo:void 0}};var Ac={generateBidTime:0,success:!1},Bc=["metrics"],Y=oa;Bc[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+Bc[0]);for(var Z;Bc.length&&(Z=Bc.shift());)Bc.length||void 0===Ac?Y=Y[Z]&&Y[Z]!==Object.prototype[Z]?Y[Z]:Y[Z]={}:Y[Z]=Ac;var Cc=function(){var a={maxFloorCpmUsdMicros:"6250"},b={topWindowHostname:"www.cnn.com",seller:"https://pubads.g.doubleclick.net",joinCount:7,bidCount:0,prevWins:[]},c=wc();return function(){return c(vb,a,ub,wb,b)}};
-
-function generateBid(){var a=Cc(),b=Date.now()
-;a=a();Ac.generateBidTime=Date.now()-b;Ac.success=JSON.stringify(a)===JSON.stringify({ad:{},bid:2937687.988333709,render:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197294&cv_id=4"});Ac.bidResponse=a;return Ac}
\ No newline at end of file
diff --git a/apct-tests/perftests/rubidium/assets/turtledove_parametrized_generateBid.js b/apct-tests/perftests/rubidium/assets/turtledove_parametrized_generateBid.js
deleted file mode 100644
index d8e0f8e..0000000
--- a/apct-tests/perftests/rubidium/assets/turtledove_parametrized_generateBid.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-
- Copyright The Closure Library Authors.
- SPDX-License-Identifier: Apache-2.0
-*/
-var n,aa=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}},ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a},ca=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");
-},ea=ca(this),q=function(a,b){if(b)a:{var c=ea;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}};
-q("Symbol",function(a){if(a)return a;var b=function(g,f){this.ra=g;ba(this,"description",{configurable:!0,writable:!0,value:f})};b.prototype.toString=function(){return this.ra};var c="jscomp_symbol_"+(1E9*Math.random()>>>0)+"_",d=0,e=function(g){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new b(c+(g||"")+"_"+d++,g)};return e});
-q("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=ea[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&ba(d.prototype,a,{configurable:!0,writable:!0,value:function(){return fa(aa(this))}})}return a});
-var fa=function(a){a={next:a};a[Symbol.iterator]=function(){return this};return a},r=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:aa(a)}},ha="function"==typeof Object.create?Object.create:function(a){var b=function(){};b.prototype=a;return new b},ia;
-if("function"==typeof Object.setPrototypeOf)ia=Object.setPrototypeOf;else{var ja;a:{var ka={a:!0},la={};try{la.__proto__=ka;ja=la.a;break a}catch(a){}ja=!1}ia=ja?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}
-var ma=ia,t=function(a,b){a.prototype=ha(b.prototype);a.prototype.constructor=a;if(ma)ma(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.za=b.prototype},u=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};
-q("WeakMap",function(a){function b(){}function c(k){var l=typeof k;return"object"===l&&null!==k||"function"===l}function d(k){if(!u(k,g)){var l=new b;ba(k,g,{value:l})}}function e(k){var l=Object[k];l&&(Object[k]=function(m){if(m instanceof b)return m;Object.isExtensible(m)&&d(m);return l(m)})}if(function(){if(!a||!Object.seal)return!1;try{var k=Object.seal({}),l=Object.seal({}),m=new a([[k,2],[l,3]]);if(2!=m.get(k)||3!=m.get(l))return!1;m.delete(k);m.set(l,4);return!m.has(k)&&4==m.get(l)}catch(p){return!1}}())return a;
-var g="$jscomp_hidden_"+Math.random();e("freeze");e("preventExtensions");e("seal");var f=0,h=function(k){this.M=(f+=Math.random()+1).toString();if(k){k=r(k);for(var l;!(l=k.next()).done;)l=l.value,this.set(l[0],l[1])}};h.prototype.set=function(k,l){if(!c(k))throw Error("Invalid WeakMap key");d(k);if(!u(k,g))throw Error("WeakMap key fail: "+k);k[g][this.M]=l;return this};h.prototype.get=function(k){return c(k)&&u(k,g)?k[g][this.M]:void 0};h.prototype.has=function(k){return c(k)&&u(k,g)&&u(k[g],this.M)};
-h.prototype.delete=function(k){return c(k)&&u(k,g)&&u(k[g],this.M)?delete k[g][this.M]:!1};return h});
-q("Map",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var h=Object.seal({x:4}),k=new a(r([[h,"s"]]));if("s"!=k.get(h)||1!=k.size||k.get({x:4})||k.set({x:4},"t")!=k||2!=k.size)return!1;var l=k.entries(),m=l.next();if(m.done||m.value[0]!=h||"s"!=m.value[1])return!1;m=l.next();return m.done||4!=m.value[0].x||"t"!=m.value[1]||!l.next().done?!1:!0}catch(p){return!1}}())return a;var b=new WeakMap,c=function(h){this.L={};this.A=g();
-this.size=0;if(h){h=r(h);for(var k;!(k=h.next()).done;)k=k.value,this.set(k[0],k[1])}};c.prototype.set=function(h,k){h=0===h?0:h;var l=d(this,h);l.list||(l.list=this.L[l.id]=[]);l.j?l.j.value=k:(l.j={next:this.A,B:this.A.B,head:this.A,key:h,value:k},l.list.push(l.j),this.A.B.next=l.j,this.A.B=l.j,this.size++);return this};c.prototype.delete=function(h){h=d(this,h);return h.j&&h.list?(h.list.splice(h.index,1),h.list.length||delete this.L[h.id],h.j.B.next=h.j.next,h.j.next.B=h.j.B,h.j.head=null,this.size--,
-!0):!1};c.prototype.clear=function(){this.L={};this.A=this.A.B=g();this.size=0};c.prototype.has=function(h){return!!d(this,h).j};c.prototype.get=function(h){return(h=d(this,h).j)&&h.value};c.prototype.entries=function(){return e(this,function(h){return[h.key,h.value]})};c.prototype.keys=function(){return e(this,function(h){return h.key})};c.prototype.values=function(){return e(this,function(h){return h.value})};c.prototype.forEach=function(h,k){for(var l=this.entries(),m;!(m=l.next()).done;)m=m.value,
-h.call(k,m[1],m[0],this)};c.prototype[Symbol.iterator]=c.prototype.entries;var d=function(h,k){var l=k&&typeof k;"object"==l||"function"==l?b.has(k)?l=b.get(k):(l=""+ ++f,b.set(k,l)):l="p_"+k;var m=h.L[l];if(m&&u(h.L,l))for(h=0;h<m.length;h++){var p=m[h];if(k!==k&&p.key!==p.key||k===p.key)return{id:l,list:m,index:h,j:p}}return{id:l,list:m,index:-1,j:void 0}},e=function(h,k){var l=h.A;return fa(function(){if(l){for(;l.head!=h.A;)l=l.B;for(;l.next!=l.head;)return l=l.next,{done:!1,value:k(l)};l=null}return{done:!0,
-value:void 0}})},g=function(){var h={};return h.B=h.next=h.head=h},f=0;return c});q("Number.isFinite",function(a){return a?a:function(b){return"number"!==typeof b?!1:!isNaN(b)&&Infinity!==b&&-Infinity!==b}});var oa=function(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&c<a.length){var g=c++;return{value:b(g,a[g]),done:!1}}d=!0;return{done:!0,value:void 0}}};e[Symbol.iterator]=function(){return e};return e};
-q("Array.prototype.entries",function(a){return a?a:function(){return oa(this,function(b,c){return[b,c]})}});q("Number.isNaN",function(a){return a?a:function(b){return"number"===typeof b&&isNaN(b)}});
-q("Set",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var c=Object.seal({x:4}),d=new a(r([c]));if(!d.has(c)||1!=d.size||d.add(c)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var e=d.entries(),g=e.next();if(g.done||g.value[0]!=c||g.value[1]!=c)return!1;g=e.next();return g.done||g.value[0]==c||4!=g.value[0].x||g.value[1]!=g.value[0]?!1:e.next().done}catch(f){return!1}}())return a;var b=function(c){this.m=new Map;if(c){c=
-r(c);for(var d;!(d=c.next()).done;)this.add(d.value)}this.size=this.m.size};b.prototype.add=function(c){c=0===c?0:c;this.m.set(c,c);this.size=this.m.size;return this};b.prototype.delete=function(c){c=this.m.delete(c);this.size=this.m.size;return c};b.prototype.clear=function(){this.m.clear();this.size=0};b.prototype.has=function(c){return this.m.has(c)};b.prototype.entries=function(){return this.m.entries()};b.prototype.values=function(){return this.m.values()};b.prototype.keys=b.prototype.values;
-b.prototype[Symbol.iterator]=b.prototype.values;b.prototype.forEach=function(c,d){var e=this;this.m.forEach(function(g){return c.call(d,g,g,e)})};return b});q("Array.from",function(a){return a?a:function(b,c,d){c=null!=c?c:function(h){return h};var e=[],g="undefined"!=typeof Symbol&&Symbol.iterator&&b[Symbol.iterator];if("function"==typeof g){b=g.call(b);for(var f=0;!(g=b.next()).done;)e.push(c.call(d,g.value,f++))}else for(g=b.length,f=0;f<g;f++)e.push(c.call(d,b[f],f));return e}});
-q("Object.entries",function(a){return a?a:function(b){var c=[],d;for(d in b)u(b,d)&&c.push([d,b[d]]);return c}});q("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});q("Array.prototype.includes",function(a){return a?a:function(b,c){var d=this;d instanceof String&&(d=String(d));var e=d.length;c=c||0;for(0>c&&(c=Math.max(c+e,0));c<e;c++){var g=d[c];if(g===b||Object.is(g,b))return!0}return!1}});
-q("String.prototype.includes",function(a){return a?a:function(b,c){if(null==this)throw new TypeError("The 'this' value for String.prototype.includes must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype.includes must not be a regular expression");return-1!==(this+"").indexOf(b,c||0)}});q("Array.prototype.values",function(a){return a?a:function(){return oa(this,function(b,c){return c})}});
-var pa=function(a){var b=typeof a;return"object"!=b?b:a?Array.isArray(a)?"array":b:"null"},qa=function(a,b){function c(){}c.prototype=b.prototype;a.za=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.Ca=function(d,e,g){for(var f=Array(arguments.length-2),h=2;h<arguments.length;h++)f[h-2]=arguments[h];return b.prototype[e].apply(d,f)}};function ra(a,b){if(Error.captureStackTrace)Error.captureStackTrace(this,ra);else{var c=Error().stack;c&&(this.stack=c)}a&&(this.message=String(a));void 0!==b&&(this.cause=b)}qa(ra,Error);ra.prototype.name="CustomError";function sa(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");ra.call(this,c+a[d])}qa(sa,ra);sa.prototype.name="AssertionError";function ta(a,b,c,d){var e="Assertion failed";if(c){e+=": "+c;var g=d}else a&&(e+=": "+a,g=b);throw new sa(""+e,g||[]);}
-var v=function(a,b,c){a||ta("",null,b,Array.prototype.slice.call(arguments,2));return a},ua=function(a,b,c){null==a&&ta("Expected to exist: %s.",[a],b,Array.prototype.slice.call(arguments,2));return a},va=function(a,b){throw new sa("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));},w=function(a,b,c){Array.isArray(a)||ta("Expected array but got %s: %s.",[pa(a),a],b,Array.prototype.slice.call(arguments,2))},x=function(a,b,c,d){a instanceof b||ta("Expected instanceof %s but got %s.",
-[wa(b),wa(a)],c,Array.prototype.slice.call(arguments,3));return a};function wa(a){return a instanceof Function?a.displayName||a.name||"unknown type name":a instanceof Object?a.constructor.displayName||a.constructor.name||Object.prototype.toString.call(a):null===a?"null":typeof a};var xa={},ya=null,za=function(a){var b,c=pa(a);v("array"==c||"object"==c&&"number"==typeof a.length,"encodeByteArray takes an array as a parameter");void 0===b&&(b=0);if(!ya){ya={};c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split("");for(var d=["+/=","+/","-_=","-_.","-_"],e=0;5>e;e++){var g=c.concat(d[e].split(""));xa[e]=g;for(var f=0;f<g.length;f++){var h=g[f],k=ya[h];void 0===k?ya[h]=f:v(k===f)}}}b=xa[b];c=Array(Math.floor(a.length/3));d=b[64]||"";for(e=g=0;g<a.length-2;g+=
-3){k=a[g];var l=a[g+1];h=a[g+2];f=b[k>>2];k=b[(k&3)<<4|l>>4];l=b[(l&15)<<2|h>>6];h=b[h&63];c[e++]=""+f+k+l+h}f=0;h=d;switch(a.length-g){case 2:f=a[g+1],h=b[(f&15)<<2]||d;case 1:a=a[g],c[e]=""+b[a>>2]+b[(a&3)<<4|f>>4]+h+d}return c.join("")};var Aa="undefined"!==typeof Uint8Array,Ba={};var Ca,Da=function(a){if(Ba!==Ba)throw Error("illegal external caller");this.qa=a;if(null!=a&&0===a.length)throw Error("ByteString should be constructed with non-empty values");};v(!0);var Ea={};var z="function"===typeof Symbol&&"symbol"===typeof Symbol()?Symbol("INTERNAL_ARRAY_STATE"):void 0;function Fa(a,b){Object.isFrozen(a)||(z?a[z]|=b:void 0!==a.F?a.F|=b:Object.defineProperties(a,{F:{value:b,configurable:!0,writable:!0,enumerable:!1}}))}var Ga=Object.getOwnPropertyDescriptor(Array.prototype,"wa");
-Object.defineProperties(Array.prototype,{wa:{get:function(){var a=A(this),b=[];1&a&&b.push("IS_REPEATED_FIELD");2&a&&b.push("IS_IMMUTABLE_ARRAY");4&a&&b.push("IS_API_FORMATTED");8&a&&b.push("ONLY_MUTABLE_VALUES");a=b.join(",");return Ga?Ga.get.call(this)+"|"+a:a},configurable:!0,enumerable:!1}});function A(a){w(a,"state is only maintained on arrays.");a=z?a[z]:a.F;return null==a?0:a}function B(a){w(a,"state is only maintained on arrays.");Fa(a,1);return a}
-function C(a){return Array.isArray(a)?!!(A(a)&2):!1}function Ha(a){if(!Array.isArray(a))throw Error("cannot mark non-array as immutable");Fa(a,2)}function Ia(a,b){if(!Array.isArray(a))throw Error("cannot mark non-array as mutable");b?Fa(a,8):Object.isFrozen(a)||(z?a[z]&=-9:void 0!==a.F&&(a.F&=-9))};function Ja(a){return null!==a&&"object"===typeof a&&!Array.isArray(a)&&a.constructor===Object}var Ka=Symbol("exempted jspb subclass"),La=Symbol("generated by jspb"),Ma=Object.freeze(B([])),Na=function(a){if(C(a.g))throw Error("Cannot mutate an immutable Message");},Oa="undefined"!=typeof Symbol&&"undefined"!=typeof Symbol.hasInstance;function Pa(a){return{value:a,configurable:!1,writable:!1,enumerable:!1}};function Qa(a){return a.displayName||a.name||"unknown type name"}function Ra(a,b){if(!(a instanceof b))throw Error("Expected instanceof "+Qa(b)+" but got "+(a&&Qa(a.constructor)));return a}function Sa(a,b,c){c=void 0===c?!1:c;if(Array.isArray(a))return new b(a);if(c)return new b};var Ta=function(){throw Error("please construct maps as mutable then call toImmutable");};if(Oa){var Ua=function(){throw Error("Cannot perform instanceof checks on ImmutableMap");},Va={};Object.defineProperties(Ta,(Va[Symbol.hasInstance]=Pa(Ua),Va));v(Ta[Symbol.hasInstance]===Ua,"defineProperties did not work: was it monkey-patched?")};function Wa(a){switch(typeof a){case "number":return isFinite(a)?a:String(a);case "object":if(a&&!Array.isArray(a)){if(Aa&&null!=a&&a instanceof Uint8Array)return za(a);if(a instanceof Da){var b=a.qa;null!=b&&"string"!==typeof b&&(Aa&&b instanceof Uint8Array?b=za(b):(va("Cannot coerce to b64 string: "+pa(b)),b=null));return null==b?"":a.qa=b}}}return a};function Xa(a,b){b=void 0===b?Ya:b;w(a);return Za(a,b)}function $a(a,b){if(null!=a){if(Array.isArray(a))a=Za(a,b);else if(Ja(a)){var c={},d;for(d in a)c[d]=$a(a[d],b);a=c}else a=b(a);return a}}function Za(a,b){w(a);for(var c=a.slice(),d=0;d<c.length;d++)c[d]=$a(c[d],b);Array.isArray(a)&&A(a)&1&&B(c);return c}function ab(a){if(a&&"object"==typeof a&&a.toJSON)return a.toJSON();a=Wa(a);return Array.isArray(a)?Xa(a,ab):a}function Ya(a){return Aa&&null!=a&&a instanceof Uint8Array?new Uint8Array(a):a};var bb=function(a){return a.C||(a.C=a.g[a.G+a.D]={})},D=function(a,b,c){return-1===b?null:b>=a.G?a.C?a.C[b]:void 0:(void 0===c?0:c)&&a.C&&(c=a.C[b],null!=c)?c:a.g[b+a.D]},E=function(a,b,c,d,e){d=void 0===d?!1:d;(void 0===e?0:e)||Na(a);b<a.G&&!d?a.g[b+a.D]=c:bb(a)[b]=c},F=function(a,b,c,d){c=void 0===c?!0:c;var e=D(a,b,d);Array.isArray(e)||(e=Ma);if(C(a.g))c&&(Ha(e),Object.freeze(e));else if(e===Ma||C(e))e=B(e.slice()),E(a,b,e,d);return e},G=function(a,b){var c=Number,d=F(a,b,!1),e;if(e=d.length)e=
-d,w(e,"state is only maintained on arrays."),e=!(A(e)&4);if(e){Object.isFrozen(d)&&(d=B(d.slice()),E(a,b,d,void 0,!0));for(b=0;b<d.length;b++)d[b]=c(d[b]);c=d;w(c,"state is only maintained on arrays.");Fa(c,5)}C(a.g)&&Object.freeze(d);return d},I=function(a,b,c){a=D(a,b);return null==a?c:a},J=function(a,b){a=D(a,b);a=null==a?a:!!a;return null==a?!1:a},L=function(a,b){a=D(a,b);a=null==a?a:+a;return null==a?0:a};function M(a,b,c){Na(a);0!==c?E(a,b,c):E(a,b,void 0,!1);return a}
-var N=function(a,b,c,d,e){e=void 0===e?!1:e;var g=e;if(-1===c)d=null;else{a.h||(a.h={});var f=a.h[c];if(f)d=f;else{var h=D(a,c,g);b=Sa(h,b,d);void 0==b?d=f:(d&&b.g!==h&&E(a,c,b.g,g,!0),a.h[c]=b,C(a.g)&&Ha(b.g),d=b)}}if(null==d)return d;C(d.g)&&!C(a.g)&&(d=d.fa(Ea),E(a,c,d.g,e),a.h[c]=d);return d},O=function(a,b,c,d){d=void 0===d?!1:d;var e=C(a.g),g=d,f=e;f=void 0===f?!0:f;a.h||(a.h={});var h=C(a.g);var k=a.h[c];g=F(a,c,!0,g);var l=h||C(g);if(!k){k=[];h=h||l;for(var m=0;m<g.length;m++){var p=g[m];
-h=h||C(p);p=Sa(p,b);void 0!==p&&(k.push(p),l&&Ha(p.g))}a.h[c]=k;Ia(g,!h)}b=l||f;f=C(k);b&&!f&&(Object.isFrozen(k)&&(a.h[c]=k=k.slice()),Ha(k),Object.freeze(k));!b&&f&&(a.h[c]=k=k.slice());a=F(a,c,d);if(!(c=e)&&(c=a)){if(!Array.isArray(a))throw Error("cannot check mutability state of non-array");c=!(A(a)&8)}if(c){for(c=0;c<k.length;c++)(d=k[c])&&C(d.g)&&!e&&(k[c]=k[c].fa(Ea),a[c]=k[c].g);Ia(a,!0)}return k},cb=function(a,b,c,d){Na(a);a.h||(a.h={});b=null!=d?Ra(d,ua(b)).g:d;a.h[c]=d;E(a,c,b)},P=function(a,
-b){return I(a,b,"0")};var Q=function(a,b,c){x(this,Q,"The message constructor should only be used by subclasses");v(this.constructor!==Q,"Message is an abstract class and cannot be directly constructed");if(!0!==this[Ka]){v(!0===this[La],"Message can only be subclassed by proto gencode.");var d=Object.getPrototypeOf(v(Object.getPrototypeOf(this)));v(d.hasOwnProperty(La),"Generated jspb classes should not be extended")}a||(a=db);db=null;d=this.constructor.Ia;a||(a=d?[d]:[]);this.D=(d?0:-1)-(this.constructor.Ga||0);this.h=
-void 0;this.g=a;a:{d=this.g.length;a=d-1;if(d&&(d=this.g[a],Ja(d))){this.G=a-this.D;this.C=d;break a}void 0!==b&&-1<b?(this.G=Math.max(b,a+1-this.D),this.C=void 0):this.G=Number.MAX_VALUE}if(c)for(b=0;b<c.length;b++)if(a=c[b],a<this.G)a+=this.D,(d=this.g[a])?Array.isArray(d)&&B(d):this.g[a]=Ma;else{d=bb(this);var e=d[a];e?Array.isArray(e)&&B(e):d[a]=Ma}};n=Q.prototype;n.toJSON=function(){return Xa(this.g,ab)};n.getExtension=function(a){x(this,a.va);return a.Ea(x(this,Q))};
-n.hasExtension=function(a){x(this,a.va);v(!a.Ha,"repeated extensions don't support hasExtension");var b=x(this,Q);return null!=D(b,a.Da)};n.clone=function(){var a=x(this,Q),b=Xa(a.g);x(a,Q);w(b);db=b;b=new a.constructor(b);x(b,Q);db=null;eb(b,a);return b};n.toString=function(){return this.g.toString()};
-function eb(a,b){v(a,"expected `to` to be non-null");v(b,"expected `from` to be non-null");b.N&&(a.N=b.N.slice());var c=b.h;if(c){b=b.C;for(var d in c){var e=c[d];if(e){var g=!(!b||!b[d]),f=+d;if(Array.isArray(e)){if(e.length)for(g=O(a,e[0].constructor,f,g),f=0;f<Math.min(g.length,e.length);f++)eb(g[f],x(e[f],Q))}else x(e,Q),(g=N(a,e.constructor,f,void 0,g))&&eb(g,e)}}}}var db;var fb=function(){Q.call(this,void 0);throw Error("ImmutableMessage is not instantiable");};t(fb,Q);fb.prototype.clone=function(){return Q.prototype.clone.call(this)};if(Oa){var gb=function(){throw Error("Cannot perform instanceof checks for MutableMessage");},hb={};Object.defineProperties(fb,(hb[Symbol.hasInstance]=Pa(gb),hb));v(fb[Symbol.hasInstance]===gb,"broken defineProperties implementation")};var R=function(){Q.apply(this,arguments)};t(R,Q);R.prototype.fa=function(){return this};if(Oa){var ib=function(){throw Error("Cannot perform instanceof checks for MutableMessage");},jb={};Object.defineProperties(R,(jb[Symbol.hasInstance]=Pa(ib),jb));v(R[Symbol.hasInstance]===ib,"defineProperties did not work: was it monkey-patched?")};function kb(a,b,c,d,e,g){if(a=a.h&&a.h[c])if(Array.isArray(a)){e=g.ba?B(a.slice()):a;g=0<e.length?e[0].constructor:void 0;Na(b);if(null!=e){w(e);d=B([]);a=!1;for(var f=0;f<e.length;f++)d[f]=Ra(e[f],ua(g)).g,a=a||C(d[f]);b.h||(b.h={});b.h[c]=e;Ia(d,!a)}else b.h&&(b.h[c]=void 0),d=Ma;E(b,c,d)}else cb(b,a.constructor,c,x(a,Q));else Aa&&d instanceof Uint8Array?(e=d,x(e,Uint8Array),e=e.length?new Da(new Uint8Array(e)):Ca||(Ca=new Da(null))):(Array.isArray(d)&&(e?Ha(d):Array.isArray(d)&&A(d)&1&&g.ba&&(d=
-d.slice())),e=d),E(b,c,e)};var S=function(){R.apply(this,arguments)};t(S,R);
-S.prototype.fa=function(a){if(a!==Ea)throw Error("requires a valid immutable API token");if(C(this.g)){x(this,Q);a={ba:!0};var b=C(this.g);if(b&&!a.ba)throw Error("copyRepeatedFields must be true for frozen messages");var c=new this.constructor;this.N&&(c.N=this.N.slice());for(var d=this.g,e=0;e<d.length;e++){var g=d[e];if(e===d.length-1&&Ja(g))for(h in g){var f=+h;Number.isNaN(f)?bb(c)[h]=g[h]:kb(this,c,f,g[h],b,a)}else kb(this,c,e-this.D,g,b,a)}var h=c}else h=this;return h};S.prototype[La]=!0;
-if(Oa){var lb={};Object.defineProperties(S,(lb[Symbol.hasInstance]=Pa(Object[Symbol.hasInstance]),lb));v(S[Symbol.hasInstance]===Object[Symbol.hasInstance],"broken defineProperties implementation")};var mb=void 0;function nb(a){var b=mb;mb=void 0;var c=[],d=ob(a,c);if(!d&&c){var e="Expected Array<unknown>, got "+pb(a);c.push(e)}if(!d)throw a="",b&&(a=b()+"\n"),Error(a+"Guard Array<unknown> failed:\n"+c.reverse().join("\n"));return a}
-function pb(a,b){b=void 0===b?new Set:b;if(b.has(a))return"(Recursive reference)";switch(typeof a){case "object":if(a){var c=Object.getPrototypeOf(a);switch(c){case Map.prototype:case Set.prototype:case Array.prototype:b.add(a);var d="["+Array.from(a,function(e){return pb(e,b)}).join(", ")+"]";b.delete(a);c!==Array.prototype&&(d=qb(c.constructor)+"("+d+")");return d;case Object.prototype:return b.add(a),c="{"+Object.entries(a).map(function(e){var g=r(e);e=g.next().value;g=g.next().value;return e+
-": "+pb(g,b)}).join(", ")+"}",b.delete(a),c;default:return d="Object",c&&c.constructor&&(d=qb(c.constructor)),"function"===typeof a.toString&&a.toString!==Object.prototype.toString?d+"("+String(a)+")":"(object "+d+")"}}break;case "function":return"function "+qb(a);case "number":if(!Number.isFinite(a))return String(a);break;case "bigint":return a.toString(10)+"n"}return JSON.stringify(a)}function qb(a){var b=a.name;b||(b=(a=/function\s+([^\(]+)/m.exec(String(a)))?a[1]:"(Anonymous)");return b};var ob=function(a){a.Fa=function(){return"Array<unknown>"};return a}(function(a){return Array.isArray(a)});var rb=[[[["1646440773",[-.21289063,-.014526367,-.0046081543,-.013671875,-.012451172,.056152344,-.05029297,-.15234375,-.044677734,-.29101563,-.099121094,.0014190674,.08496094,.078125,-.009765625,-.09765625,-.045166016,.09765625,-.022583008,.23242188,-.04321289,.0126953125,.032226563,.064941406,.36132813,-.09716797,.28515625,.0074768066,-.11279297,-.0625,.012329102,-.076171875]]],[["1646451678",[-.18652344,.15917969,-.005340576,.055664063,.041015625,-.010253906,.06591797,-.071777344,.024536133,1.828125,
--.19140625,-.35351563,.13671875,.45117188,.12792969,-.03466797,.18261719,.19628906,.14160156,.17480469,-.04638672,-.06689453,-.30273438,.35351563,-.33789063,-.7578125,-.17675781,.05810547,-.002029419,.005279541,-.025756836,.15234375]]]],null,[1],"CMb9tKfcrvYCFawfBgAdboELOQ",null,[null,null,null,1,[]],[null,null,null,null,[]]];var sb={"1j115753478":[[["52836427830","310927197294","4",[[["1643849995",[3.09375,.8203125,1.4765625,-.55078125,1.9140625,-.78125,-1.1640625,-3.15625,1.25,3.421875,1.6484375,1.0625,4.96875,-.66796875,-1.4375,.87109375,1.6171875,-4.125,-2.375,3.421875,-2.359375,1.6015625,.625,-4.65625,-5.03125,.416015625,-4.03125,-.24609375,3.296875,-.052001953125,-3.75,3.765625]],["1643804092",[3.09375,.796875,1.46875,-.56640625,1.890625,-.76953125,-1.1484375,-3.140625,1.2109375,3.421875,1.625,1.046875,4.9375,-.65234375,
--1.421875,.84765625,1.6015625,-4.125,-2.359375,3.453125,-2.34375,1.5859375,.63671875,-4.65625,-5,.396484375,-4.03125,-.26171875,3.296875,-.068359375,-3.734375,3.75]]],null,[["1643822293",[-.039794921875,.035400390625,.357421875,.041748046875,.0054931640625,-.060791015625,.138671875,-.318359375,.2255859375,.10546875,.2099609375,-.240234375,-.07373046875,-.279296875,-.44140625,.015380859375,-.298828125,.119140625,-.09716796875,.1796875,.04248046875,.09033203125,.38671875,.412109375,-.357421875,.259765625,
--.24609375,-.3828125,.33984375,.07861328125,-.1259765625,.3046875]],["1643799063",[.0079345703125,.0546875,.353515625,.00958251953125,-.01318359375,-.10888671875,.13671875,-.373046875,.208984375,.09228515625,.1962890625,-.248046875,-.031494140625,-.2734375,-.42578125,.0035400390625,-.345703125,.1083984375,-.068359375,.173828125,.0810546875,.1162109375,.361328125,.451171875,-.3671875,.162109375,-.212890625,-.46484375,.337890625,.1083984375,-.177734375,.318359375]]],null,null,null,null,[[null,[318.3513488769531,
-1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197297","4",[[["1643849995",[3.125,.953125,1.484375,-.46875,2.109375,-.89453125,-1.265625,-3.15625,1.265625,3.421875,1.7578125,1.1796875,4.9375,-.6796875,-1.5234375,.953125,1.7734375,-4.125,-2.453125,3.4375,-2.375,1.6328125,.3984375,-4.375,-4.96875,.59375,-4.03125,-.08935546875,3.34375,.1806640625,-3.8125,3.796875]],["1643804092",[3.125,.90625,1.4609375,-.5,2.046875,-.8671875,
--1.234375,-3.140625,1.2265625,3.421875,1.71875,1.1328125,4.90625,-.65625,-1.4921875,.921875,1.734375,-4.125,-2.421875,3.46875,-2.34375,1.6015625,.4296875,-4.375,-4.9375,.55078125,-4.03125,-.123046875,3.328125,.1416015625,-3.78125,3.765625]]],null,[["1643822293",[-.060546875,.0185546875,.353515625,.02587890625,.00311279296875,-.07421875,.1533203125,-.3203125,.2470703125,.06689453125,.193359375,-.234375,.029296875,-.255859375,-.44921875,.0146484375,-.306640625,.11962890625,-.10498046875,.1865234375,
-.049072265625,.1162109375,.365234375,.42578125,-.359375,.26953125,-.2490234375,-.392578125,.306640625,.1103515625,-.1376953125,.310546875]],["1643799063",[-.015869140625,.02978515625,.337890625,-.00628662109375,-.0169677734375,-.12353515625,.1494140625,-.373046875,.232421875,.056640625,.1806640625,-.2353515625,.0966796875,-.2451171875,-.43359375,.004180908203125,-.353515625,.107421875,-.087890625,.1865234375,.087890625,.138671875,.345703125,.455078125,-.36328125,.181640625,-.224609375,-.486328125,
-.294921875,.13671875,-.19921875,.3203125]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197300","4",[[["1643849995",[3.109375,.99609375,1.59375,-.4609375,2.171875,-.91015625,-1.296875,-3.3125,1.3984375,3.4375,1.8046875,1.2578125,5.09375,-.7421875,-1.59375,1.0078125,1.8125,-4.1875,-2.578125,3.390625,-2.53125,1.765625,.54296875,-4.71875,-5.09375,.55859375,-4.09375,-.1318359375,
-3.328125,.0654296875,-3.890625,3.859375]],["1643804092",[3.109375,.953125,1.5703125,-.48828125,2.109375,-.88671875,-1.2734375,-3.296875,1.359375,3.4375,1.7734375,1.21875,5.0625,-.71875,-1.5625,.9765625,1.7734375,-4.1875,-2.53125,3.4375,-2.5,1.734375,.5703125,-4.71875,-5.0625,.5234375,-4.0625,-.1591796875,3.328125,.03515625,-3.84375,3.828125]]],null,[["1643822293",[-.048095703125,.0179443359375,.36328125,.033203125,.030029296875,-.07568359375,.15625,-.326171875,.224609375,.07568359375,.1787109375,
--.234375,-.0277099609375,-.265625,-.412109375,.00909423828125,-.3046875,.11865234375,-.103515625,.1767578125,.048095703125,.12158203125,.36328125,.421875,-.359375,.255859375,-.25,-.396484375,.29296875,.10205078125,-.1279296875,.318359375]],["1643799063",[-.0045166015625,.03173828125,.353515625,.003631591796875,.00927734375,-.126953125,.154296875,-.37890625,.208984375,.06689453125,.1708984375,-.234375,.03173828125,-.255859375,-.396484375,-.00384521484375,-.353515625,.10693359375,-.0830078125,.1708984375,
-.08935546875,.1474609375,.341796875,.44921875,-.3671875,.1669921875,-.224609375,-.482421875,.28125,.130859375,-.1796875,.326171875]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j380357233":[[["52836427830","310927197294","4",[[["1643849995",[4.53125,1.8671875,.13671875,3.3125,-7.5625,.546875,2.953125,-7.90625,4.71875,7.375,.0047607421875,-3.25,.74609375,.298828125,-1.34375,-2.4375,-6.34375,
--9.1875,-1.3359375,9.875,1.1796875,-3.15625,3.796875,-6.90625,-3.203125,-.09375,-7.65625,-.71875,4.65625,-.75390625,-6.28125,3.6875]],["1643804092",[4.53125,1.9453125,.19140625,3.40625,-7.53125,.52734375,2.9375,-7.9375,4.625,7.375,.01416015625,-3.25,.74609375,.28125,-1.34375,-2.484375,-6.34375,-9.25,-1.328125,9.9375,1.2421875,-3.171875,3.71875,-6.71875,-3.21875,-.0311279296875,-7.71875,-.69140625,4.65625,-.70703125,-6.40625,3.71875]]],null,[["1643822293",[-.09033203125,.037109375,.423828125,.0439453125,
-.0390625,-.04345703125,.162109375,-.3125,.2197265625,.06884765625,.25,-.240234375,-.07763671875,-.267578125,-.416015625,.0150146484375,-.2890625,.126953125,-.08740234375,.158203125,.035888671875,.130859375,.3515625,.412109375,-.38671875,.27734375,-.234375,-.408203125,.337890625,.0458984375,-.1328125,.36328125]],["1643799063",[-.044921875,.056640625,.3984375,.0162353515625,.01373291015625,-.08544921875,.1611328125,-.359375,.1982421875,.06298828125,.2421875,-.2421875,-.05078125,-.263671875,-.39453125,
-.001953125,-.33203125,.11767578125,-.060546875,.1513671875,.07080078125,.14453125,.3359375,.4453125,-.388671875,.1865234375,-.1904296875,-.48046875,.3359375,.0693359375,-.177734375,.37109375]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197297","4",[[["1643849995",[4.4375,1.90625,.20703125,3.125,-7.03125,.44140625,2.703125,-7.46875,4.5,7.1875,.080078125,-3.03125,.94140625,
-.25390625,-1.3203125,-2.25,-5.875,-8.875,-1.375,9.4375,1.0234375,-2.984375,3.453125,-6.46875,-3.171875,.007781982421875,-7.4375,-.62890625,4.5625,-.58984375,-6.125,3.609375]],["1643804092",[4.46875,1.9765625,.26171875,3.1875,-6.9375,.41015625,2.671875,-7.53125,4.375,7.21875,.09716796875,-3.015625,1.0078125,.232421875,-1.3203125,-2.28125,-5.84375,-8.875,-1.3828125,9.5625,1.0859375,-2.96875,3.359375,-6.3125,-3.234375,.06494140625,-7.5,-.6171875,4.5625,-.53125,-6.28125,3.703125]]],null,[["1643822293",
-[-.107421875,.017822265625,.427734375,.0274658203125,.0289306640625,-.05908203125,.17578125,-.31640625,.2373046875,.033447265625,.2470703125,-.23046875,.00579833984375,-.25,-.421875,.01385498046875,-.298828125,.1240234375,-.09912109375,.16796875,.036865234375,.1435546875,.33984375,.4296875,-.380859375,.28515625,-.232421875,-.427734375,.3125,.0654296875,-.1513671875,.373046875]],["1643799063",[-.07177734375,.024658203125,.396484375,-.0016937255859375,.01434326171875,-.11328125,.1748046875,-.3671875,
-.2255859375,.026611328125,.224609375,-.2197265625,.07470703125,-.232421875,-.396484375,.01507568359375,-.341796875,.11376953125,-.087890625,.16015625,.072265625,.173828125,.3203125,.44921875,-.3828125,.19921875,-.2080078125,-.5078125,.28125,.1044921875,-.21484375,.380859375]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197300","4",[[["1643849995",[4.5,1.96875,.2099609375,
-3.328125,-7.28125,.458984375,2.8125,-7.84375,4.84375,7.3125,.09814453125,-3.078125,.859375,.224609375,-1.4296875,-2.3125,-6.09375,-9.125,-1.4453125,9.75,1.0078125,-3,3.71875,-6.90625,-3.203125,-.04931640625,-7.5625,-.6328125,4.625,-.69140625,-6.25,3.671875]],["1643804092",[4.5,2.09375,.298828125,3.453125,-7.1875,.416015625,2.765625,-7.90625,4.75,7.3125,.1318359375,-3.046875,.9140625,.17578125,-1.4453125,-2.328125,-6.0625,-9.125,-1.46875,9.75,1.046875,-2.984375,3.59375,-6.6875,-3.25,.041015625,-7.625,
--.5859375,4.625,-.6171875,-6.40625,3.75]]],null,[["1643822293",[-.09765625,.0216064453125,.421875,.03955078125,.056396484375,-.0546875,.1767578125,-.31640625,.208984375,.04248046875,.2265625,-.2314453125,-.0419921875,-.2578125,-.3828125,.0084228515625,-.29296875,.123046875,-.09423828125,.1533203125,.0380859375,.1474609375,.333984375,.4140625,-.384765625,.275390625,-.232421875,-.4140625,.291015625,.06591796875,-.1337890625,.376953125]],["1643799063",[-.0673828125,.03271484375,.41796875,.01336669921875,
-.041748046875,-.10595703125,.1767578125,-.37109375,.1982421875,.0294189453125,.212890625,-.2275390625,.02880859375,-.248046875,-.361328125,.00909423828125,-.337890625,.115234375,-.0732421875,.14453125,.07080078125,.1875,.310546875,.4453125,-.39453125,.1875,-.203125,-.5078125,.26953125,.095703125,-.1962890625,.40625]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149038",
-null,[[["1643849995",[7.875,2.375,-3.078125,9.8125,-20.875,2.46875,9.1875,-18.25,10,13.0625,-1.1171875,-8.875,-6.9375,2.078125,-2.1875,-7.34375,-17.375,-19.375,.640625,21.375,7.0625,-9.875,7.875,-9.5625,-2.09375,.034423828125,-13.4375,-.3359375,8.5625,-.75390625,-11.375,6.15625]],["1643804092",[7.875,2.4375,-3.015625,10,-20.75,2.453125,9.1875,-18.25,9.6875,13,-1.1484375,-8.9375,-6.875,2.078125,-2.125,-7.4375,-17.5,-19.25,.71875,21.25,7.3125,-9.9375,7.65625,-9.125,-2.171875,.1513671875,-13.5625,-.34765625,
-8.5625,-.69921875,-11.6875,6.28125]]],null,[["1643822293",[-.337890625,-.1884765625,.1923828125,-.0213623046875,-.1953125,.5234375,.326171875,.0908203125,-.09033203125,.019775390625,.40234375,.462890625,-.19921875,-.08642578125,-.29296875,-.1943359375,.248046875,-.2470703125,-.2099609375,.2353515625,.0400390625,.1767578125,.828125,-.059326171875,-.0218505859375,.5703125,-.431640625,-.30859375,.19921875,.1455078125,-.486328125,-.2578125]],["1643799063",[-.37109375,-.1455078125,.361328125,-.0595703125,
--.1611328125,.5234375,.3203125,.07568359375,-.0791015625,.03173828125,.423828125,.4609375,-.2412109375,-.09130859375,-.310546875,-.193359375,.232421875,-.2353515625,-.19140625,.2177734375,.0205078125,.232421875,.8359375,-.04150390625,-.045166015625,.55078125,-.451171875,-.412109375,.298828125,.1220703125,-.56640625,-.11767578125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038",
-"113383149158",null,[[["1643849995",[8.1875,2.0625,-3.328125,9.5,-21.125,2.609375,9.3125,-17.875,9.5,13.375,-1.2578125,-9.1875,-7,2.265625,-1.9140625,-7.5,-17.625,-19.5,.953125,21.375,7.46875,-10.3125,7.65625,-9.125,-2.265625,.02490234375,-13.75,-.4375,8.8125,-.59765625,-11.4375,6.40625]],["1643804092",[8.125,2.140625,-3.25,9.6875,-21.125,2.59375,9.3125,-17.875,9.25,13.25,-1.25,-9.1875,-6.90625,2.234375,-1.8671875,-7.5625,-17.625,-19.5,1.0078125,21.25,7.625,-10.375,7.5,-8.8125,-2.359375,.1494140625,
--13.75,-.458984375,8.75,-.5625,-11.6875,6.5]]],null,[["1643822293",[-.349609375,-.19140625,.1767578125,-.0213623046875,-.197265625,.5234375,.330078125,.0927734375,-.0908203125,.027587890625,.3984375,.462890625,-.2001953125,-.0810546875,-.296875,-.19140625,.2490234375,-.244140625,-.2119140625,.2392578125,.0400390625,.181640625,.828125,-.05859375,-.0181884765625,.5703125,-.4296875,-.302734375,.1982421875,.1494140625,-.490234375,-.263671875]],["1643799063",[-.369140625,-.1435546875,.353515625,-.05908203125,
--.1552734375,.515625,.322265625,.0703125,-.07177734375,.04345703125,.421875,.45703125,-.248046875,-.08935546875,-.30859375,-.1953125,.2255859375,-.2333984375,-.1943359375,.220703125,.021484375,.2431640625,.83984375,-.0419921875,-.04052734375,.54296875,-.443359375,-.41015625,.30078125,.11767578125,-.5703125,-.12158203125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",
-null,[[["1643849995",[7.71875,2.21875,-2.984375,9.3125,-20.25,2.40625,8.875,-17.375,9.5,12.75,-1.1015625,-8.6875,-6.53125,2.03125,-2.03125,-7.09375,-16.875,-18.625,.61328125,20.625,6.84375,-9.625,7.625,-9.3125,-2.140625,-.0341796875,-13.125,-.435546875,8.375,-.8046875,-11.0625,6]],["1643804092",[7.65625,2.328125,-2.875,9.5,-20.125,2.375,8.8125,-17.375,9.3125,12.625,-1.09375,-8.625,-6.46875,1.9921875,-2.015625,-7.125,-16.875,-18.625,.671875,20.5,7,-9.625,7.4375,-8.9375,-2.15625,.1357421875,-13.125,
--.4140625,8.25,-.73046875,-11.25,6.0625]]],null,[["1643822293",[-.34765625,-.193359375,.208984375,-.025390625,-.201171875,.5234375,.330078125,.09326171875,-.09423828125,.0084228515625,.41015625,.46484375,-.1767578125,-.08251953125,-.310546875,-.19140625,.25,-.24609375,-.212890625,.2392578125,.0380859375,.17578125,.828125,-.0576171875,-.01904296875,.578125,-.43359375,-.31640625,.2060546875,.14453125,-.4921875,-.255859375]],["1643799063",[-.369140625,-.150390625,.37890625,-.0546875,-.1630859375,.53125,
-.3203125,.08251953125,-.08447265625,.01318359375,.43359375,.462890625,-.2392578125,-.09619140625,-.310546875,-.189453125,.2421875,-.2333984375,-.1953125,.2119140625,.0142822265625,.23046875,.83203125,-.0284423828125,-.047119140625,.55078125,-.447265625,-.427734375,.306640625,.115234375,-.57421875,-.107421875]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j395640136":[[["31279674038","113383149038",
-null,[[["1643849995",[3.34375,.197265625,.66015625,-.796875,1.1015625,-.5546875,-.78515625,-2.21875,.84765625,3.390625,1.28125,.482421875,3.9375,-.1865234375,-1.09375,.609375,1.1484375,-4.0625,-1.7890625,4.5625,-1.859375,.83203125,.64453125,-4,-4.09375,.02587890625,-3.734375,-.31640625,3.65625,-.025146484375,-2.5625,3.03125]],["1643804092",[3.34375,.177734375,.6484375,-.8125,1.078125,-.54296875,-.76953125,-2.203125,.81640625,3.40625,1.265625,.462890625,3.9375,-.171875,-1.078125,.59375,1.125,-4.09375,
--1.7734375,4.59375,-1.8359375,.8203125,.65625,-3.984375,-4.09375,.0101318359375,-3.75,-.33203125,3.671875,-.039794921875,-2.546875,3.015625]]],null,[["1643822293",[-.345703125,-.1962890625,.2109375,-.034912109375,-.2158203125,.5234375,.3359375,.09619140625,-.09326171875,.01385498046875,.427734375,.474609375,-.1806640625,-.0771484375,-.3203125,-.2060546875,.2451171875,-.2578125,-.2177734375,.2490234375,.035888671875,.1513671875,.84375,-.04638671875,-.01220703125,.5703125,-.439453125,-.32421875,.2138671875,
-.1513671875,-.50390625,-.263671875]],["1643799063",[-.3828125,-.1494140625,.384765625,-.058837890625,-.1826171875,.53125,.322265625,.0859375,-.08837890625,.0159912109375,.458984375,.462890625,-.2275390625,-.08984375,-.328125,-.1962890625,.23828125,-.23828125,-.189453125,.22265625,.01556396484375,.2109375,.83203125,-.0238037109375,-.044677734375,.55859375,-.453125,-.43359375,.31640625,.12158203125,-.57421875,-.11328125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,
-[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149158",null,[[["1643849995",[3.34375,.130859375,.62109375,-.84765625,.98046875,-.453125,-.68359375,-2.03125,.51953125,3.453125,1.140625,.291015625,3.96875,-.15625,-.8828125,.435546875,1.0078125,-4,-1.515625,4.15625,-1.5234375,.62890625,.37890625,-3.421875,-4.21875,.1220703125,-3.84375,-.345703125,3.5625,.10791015625,-2.828125,3.25]],["1643804092",[3.34375,.130859375,.62109375,-.8515625,.98046875,-.451171875,
--.68359375,-2.03125,.50390625,3.453125,1.1328125,.287109375,3.96875,-.1533203125,-.875,.427734375,1.0078125,-4,-1.5078125,4.15625,-1.515625,.625,.369140625,-3.390625,-4.21875,.1259765625,-3.84375,-.34765625,3.5625,.11181640625,-2.828125,3.25]]],null,[["1643822293",[-.3515625,-.1982421875,.185546875,-.027099609375,-.21875,.5234375,.333984375,.099609375,-.09423828125,.0244140625,.42578125,.47265625,-.1845703125,-.0751953125,-.314453125,-.2001953125,.2470703125,-.25390625,-.216796875,.248046875,.036865234375,
-.1533203125,.83984375,-.044189453125,-.00933837890625,.5703125,-.43359375,-.31640625,.212890625,.15625,-.5,-.275390625]],["1643799063",[-.38671875,-.138671875,.375,-.061767578125,-.177734375,.5234375,.3203125,.07666015625,-.080078125,.033447265625,.4453125,.447265625,-.2333984375,-.09130859375,-.333984375,-.19921875,.2265625,-.2275390625,-.18359375,.2255859375,.02197265625,.2197265625,.828125,-.0189208984375,-.047119140625,.55078125,-.44140625,-.4296875,.328125,.11962890625,-.5703125,-.11572265625]]],
-null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",null,[[["1643849995",[3.21875,.1484375,.6796875,-.8203125,1,-.486328125,-.73046875,-2.21875,.77734375,3.3125,1.1875,.419921875,3.875,-.1904296875,-1.015625,.52734375,1.046875,-3.984375,-1.7265625,4.46875,-1.8046875,.828125,.7421875,-4.03125,-4.0625,-.07080078125,-3.671875,-.3984375,3.53125,-.1494140625,-2.515625,2.953125]],
-["1643804092",[3.21875,.1416015625,.671875,-.828125,1,-.486328125,-.73046875,-2.21875,.75390625,3.3125,1.1796875,.416015625,3.890625,-.1796875,-1.015625,.51953125,1.046875,-3.984375,-1.71875,4.5,-1.7890625,.8203125,.73046875,-4,-4.0625,-.06640625,-3.6875,-.3984375,3.53125,-.142578125,-2.53125,2.96875]]],null,[["1643822293",[-.349609375,-.19921875,.2109375,-.03173828125,-.2158203125,.53515625,.333984375,.10400390625,-.11181640625,.00836181640625,.431640625,.4765625,-.16796875,-.07568359375,-.32421875,
--.201171875,.25390625,-.26171875,-.21875,.251953125,.032958984375,.142578125,.83984375,-.05126953125,-.00836181640625,.58203125,-.439453125,-.31640625,.21875,.1513671875,-.498046875,-.267578125]],["1643799063",[-.376953125,-.1513671875,.38671875,-.061279296875,-.1875,.53125,.322265625,.08642578125,-.08935546875,.01324462890625,.45703125,.462890625,-.224609375,-.08984375,-.333984375,-.19921875,.23828125,-.240234375,-.1962890625,.2197265625,.01519775390625,.2041015625,.8359375,-.0179443359375,-.041748046875,
-.5546875,-.451171875,-.43359375,.3203125,.123046875,-.578125,-.11962890625]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j396781473":[[["31279674038","113383149038",null,[[["1643849995",[3.28125,.37890625,.828125,-.734375,1.3359375,-.625,-.89453125,-2.390625,.7578125,3.40625,1.3515625,.58984375,4.125,-.2734375,-1.125,.6171875,1.2734375,-4.0625,-1.859375,4.3125,-1.84375,.953125,.427734375,
--3.71875,-4.28125,.2119140625,-3.828125,-.244140625,3.5625,.134765625,-2.9375,3.25]],["1643804092",[3.28125,.345703125,.80859375,-.75390625,1.2890625,-.6015625,-.87109375,-2.375,.72265625,3.40625,1.3203125,.5546875,4.09375,-.255859375,-1.09375,.5859375,1.234375,-4.0625,-1.828125,4.34375,-1.8125,.92578125,.4453125,-3.71875,-4.28125,.185546875,-3.84375,-.267578125,3.5625,.111328125,-2.921875,3.234375]]],null,[["1643822293",[-.32421875,-.203125,.212890625,-.006622314453125,-.224609375,.5234375,.330078125,
-.099609375,-.08203125,-.01239013671875,.41015625,.484375,-.140625,-.0751953125,-.3046875,-.17578125,.251953125,-.25,-.2119140625,.2119140625,.030029296875,.1689453125,.8359375,-.041748046875,-.022216796875,.5546875,-.412109375,-.34375,.1748046875,.1806640625,-.5,-.2470703125]],["1643799063",[-.3359375,-.1572265625,.376953125,-.039306640625,-.1982421875,.515625,.314453125,.076171875,-.0595703125,-.0079345703125,.43359375,.4765625,-.208984375,-.091796875,-.3125,-.1708984375,.23046875,-.23828125,-.1962890625,
-.1787109375,.01556396484375,.220703125,.84375,-.0184326171875,-.052001953125,.51953125,-.4296875,-.458984375,.263671875,.1494140625,-.58203125,-.10498046875]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149158",null,[[["1643849995",[3.328125,.369140625,.8125,-.7578125,1.3125,-.56640625,-.84375,-2.25,.478515625,3.484375,1.2734375,.462890625,4.21875,-.265625,-.96875,.4921875,
-1.2109375,-4.03125,-1.640625,3.875,-1.5546875,.7890625,.10302734375,-3.125,-4.4375,.375,-3.96875,-.2236328125,3.5,.3359375,-3.265625,3.515625]],["1643804092",[3.3125,.349609375,.80078125,-.76953125,1.28125,-.5546875,-.828125,-2.234375,.4453125,3.46875,1.25,.44140625,4.1875,-.251953125,-.94921875,.47265625,1.1875,-4.03125,-1.6171875,3.890625,-1.53125,.76953125,.10888671875,-3.109375,-4.4375,.359375,-3.953125,-.236328125,3.5,.32421875,-3.234375,3.5]]],null,[["1643822293",[-.326171875,-.201171875,.1884765625,
--.0014190673828125,-.2216796875,.53125,.330078125,.10107421875,-.0849609375,-.00994873046875,.404296875,.4765625,-.1513671875,-.07470703125,-.298828125,-.17578125,.25390625,-.2421875,-.2099609375,.2109375,.0322265625,.1728515625,.83203125,-.0380859375,-.0242919921875,.55859375,-.408203125,-.33984375,.177734375,.18359375,-.494140625,-.25390625]],["1643799063",[-.33984375,-.1474609375,.3515625,-.03466796875,-.1923828125,.5078125,.3125,.0712890625,-.057861328125,.01446533203125,.431640625,.46484375,
--.2109375,-.0927734375,-.310546875,-.17578125,.220703125,-.2294921875,-.1923828125,.1796875,.023681640625,.2314453125,.83984375,-.0205078125,-.049072265625,.51953125,-.41796875,-.4453125,.2734375,.1513671875,-.57421875,-.115234375]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",null,[[["1643849995",[3.15625,.34765625,.8515625,-.74609375,1.2578125,-.56640625,-.85546875,
--2.40625,.6953125,3.328125,1.265625,.546875,4.09375,-.283203125,-1.0625,.54296875,1.1953125,-3.984375,-1.8046875,4.1875,-1.796875,.95703125,.5,-3.75,-4.25,.1376953125,-3.78125,-.310546875,3.4375,.03173828125,-2.921875,3.1875]],["1643804092",[3.171875,.322265625,.8359375,-.765625,1.2265625,-.546875,-.8359375,-2.390625,.65625,3.328125,1.2421875,.515625,4.0625,-.265625,-1.0390625,.51953125,1.171875,-3.984375,-1.7734375,4.21875,-1.765625,.93359375,.5,-3.71875,-4.25,.12353515625,-3.78125,-.32421875,3.4375,
-.0242919921875,-2.921875,3.1875]]],null,[["1643822293",[-.32421875,-.21484375,.212890625,-.00543212890625,-.2333984375,.52734375,.333984375,.10498046875,-.08740234375,-.0296630859375,.416015625,.49609375,-.1357421875,-.072265625,-.302734375,-.1728515625,.2578125,-.259765625,-.2177734375,.208984375,.028564453125,.1640625,.83984375,-.042724609375,-.0184326171875,.55859375,-.41796875,-.345703125,.162109375,.185546875,-.5078125,-.25390625]],["1643799063",[-.345703125,-.1650390625,.375,-.041748046875,
--.1962890625,.51953125,.318359375,.08056640625,-.06396484375,-.004486083984375,.447265625,.486328125,-.197265625,-.0888671875,-.3203125,-.166015625,.234375,-.2431640625,-.2041015625,.1826171875,.01495361328125,.2216796875,.84765625,-.029052734375,-.044921875,.53125,-.431640625,-.4609375,.2578125,.1494140625,-.5859375,-.115234375]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j475122041":[[["60795725037",
-"306664789872",null,[[["1643849995",[3.421875,1.78125,1.6796875,.048095703125,2.796875,-1.3984375,-1.703125,-3.5625,1.328125,3.796875,2.265625,1.5,5.125,-.80078125,-1.8515625,1.1796875,2.203125,-4.53125,-2.78125,3.5625,-2.265625,1.6796875,-.76171875,-2.8125,-5.09375,1.5078125,-4.5,.59375,3.609375,1.359375,-4.78125,4.375]],["1643804092",[3.40625,1.75,1.6640625,.0306396484375,2.75,-1.3828125,-1.6875,-3.53125,1.3125,3.78125,2.25,1.4765625,5.09375,-.79296875,-1.828125,1.171875,2.171875,-4.53125,-2.765625,
-3.5625,-2.25,1.6640625,-.73046875,-2.84375,-5.0625,1.4765625,-4.5,.56640625,3.609375,1.3203125,-4.75,4.34375]]],null,[["1643822293",[1.2734375,1.0859375,.298828125,.09619140625,.10107421875,-.09375,-.52734375,-.953125,-.1259765625,-.5078125,-.1611328125,-.498046875,-1.3515625,-.412109375,.94140625,-.33984375,-.578125,.2578125,.47265625,-.478515625,.255859375,-.1005859375,-.06396484375,.166015625,-.9765625,.029541015625,.314453125,.0106201171875,.74609375,-.38671875,.83984375,.75390625]],["1643799063",
-[1.3046875,1.0625,.3828125,.06201171875,.1142578125,-.046875,-.52734375,-.94921875,-.134765625,-.56640625,-.08740234375,-.439453125,-1.3671875,-.4296875,1.046875,-.33203125,-.5625,.2734375,.50390625,-.54296875,.1728515625,-.123046875,-.0233154296875,.1962890625,-1.0546875,.05859375,.318359375,-.0537109375,.8125,-.423828125,.79296875,.953125]]],null,null,null,null,[[null,[61170.82421875,1],[1,2],[1,1],null,3]]],[null,[[3,0,null,["AdvControlbrand-unsafe"]]]],"1614272341"]]]};function tb(a,b){return!b||0>=b?a:Math.min(a,b)}function T(a,b,c){return b?b:c?c:a?1:0}function ub(a){a=null==a?void 0:I(a,9,0);return void 0===a?!1:[61,51,52].includes(a)};var U=function(a){S.call(this,a,-1,vb)};t(U,S);var vb=[2];var wb=function(a){S.call(this,a)};t(wb,S);var yb=function(a){S.call(this,a,-1,xb)};t(yb,S);yb.prototype.ca=function(){return O(this,wb,3)};var xb=[2,3];var Ab=function(a){S.call(this,a,-1,zb)};t(Ab,S);var Cb=function(a){S.call(this,a,-1,Bb)};t(Cb,S);var Eb=function(a){S.call(this,a,-1,Db)};t(Eb,S);Eb.prototype.ca=function(){return O(this,wb,5)};var zb=[1,2],Bb=[3,4],Db=[3,4,5];var Gb=function(a){S.call(this,a,-1,Fb)};t(Gb,S);var W=function(a){return N(a,Hb,3)},Jb=function(a){S.call(this,a,-1,Ib)};t(Jb,S);Jb.prototype.Y=function(){return O(this,U,2)};Jb.prototype.ma=function(){return O(this,U,3)};var Kb=function(a){S.call(this,a)};t(Kb,S);Kb.prototype.u=function(){return P(this,1)};Kb.prototype.v=function(){return P(this,2)};Kb.prototype.da=function(){return L(this,3)};var Hb=function(a){S.call(this,a)};t(Hb,S);var X=function(a){S.call(this,a)};t(X,S);
-var Y=function(a){S.call(this,a)};t(Y,S);var Nb=function(a){var b=new Y;return M(b,1,a)},Z=function(a){S.call(this,a)};t(Z,S);Z.prototype.u=function(){return P(this,2)};Z.prototype.v=function(){return P(this,3)};Z.prototype.W=function(){return P(this,4)};Z.prototype.da=function(){return L(this,5)};var Fb=[2],Ib=[1,2,3];function Ob(a,b,c){if(!b||0>=b)return{l:0,P:1};var d=T(!0,null==a?void 0:L(a,1),null==c?void 0:L(c,1)),e=T(!1,null==a?void 0:L(a,2),null==c?void 0:L(c,2)),g=T(!1,null==a?void 0:L(a,3),null==c?void 0:L(c,3)),f,h;a=T(!1,null==a?void 0:null==(f=N(a,Y,5))?void 0:L(f,1),null==c?void 0:null==(h=N(c,Y,5))?void 0:L(h,1));c=new X;f=M(c,1,d);f=M(f,2,e);f=M(f,3,g);h=Nb(a);cb(f,Y,5,h);return{l:b*d*(1-1/(1+Math.exp(-e*(Math.log(b/1E6)-a-g)))),P:4,sa:c}};function Pb(a,b){var c=null==a?void 0:N(a,X,6),d,e=null==a?void 0:null==(d=W(a))?void 0:N(d,X,3);if(!b||0>=b)return{l:0,P:1};var g;if(!(null==a?0:null==(g=W(a))?0:J(g,2)))return{l:.85*b,P:2};d=T(!0,null==c?void 0:L(c,4),null==e?void 0:L(e,4));g=T(!0,null==c?void 0:L(c,1),null==e?void 0:L(e,1));var f=T(!1,null==c?void 0:L(c,2),null==e?void 0:L(e,2)),h=T(!1,null==c?void 0:L(c,3),null==e?void 0:L(e,3)),k,l;c=T(!1,null==c?void 0:null==(k=N(c,Y,5))?void 0:L(k,1),null==e?void 0:null==(l=N(e,Y,5))?void 0:
-L(l,1));k=new X;l=M(k,1,g);l=M(l,2,f);l=M(l,3,h);l=M(l,4,d);var m=Nb(c);cb(l,Y,5,m);d=d*b*g*(1-1/(1+Math.exp(-f*(Math.log(d*b/1E6)-c-h))));g=1E6*(null==a?NaN:L(a,8));var p;if((null==a?0:null==(p=W(a))?0:J(p,6))&&d<g&&g<b){var y;d=g+1E6*(null!=(y=null==e?void 0:L(e,7))?y:0)*Math.log(b/g)}return{l:d,P:3,sa:k}};function Qb(a,b){if(!(0<G(a,2).length&&G(a,2).length===F(a,3).length&&G(a,2).length===G(a,4).length))return 0;for(var c=0,d=0,e=1,g=r(F(a,3)),f=g.next();!f.done;f=g.next()){var h=0;switch(f.value){case 1:h=G(a,2)[d]*(b.ea?Math.pow(b.ea,G(a,4)[d]):0);break;case 2:c=h=G(a,2)[d]*(b.oa?Math.pow(b.oa,G(a,4)[d]):0);break;case 3:h=G(a,2)[d]}if(0===h)return 0;e*=h;d+=1}0<L(a,7)&&(e=Math.min(e,L(a,7)*c*1E3));return 1E6*e}
-function Rb(a,b){var c=0;b&&(0<O(b,Sb,7).length?c=Qb(O(b,Sb,7)[0],a):0<O(b,Sb,8).length&&(c=Qb(O(b,Sb,8)[0],a)));return c};function Tb(a,b,c){if(I(a,2,0)!==I(b,2,0))return c;var d=!1;switch(I(a,2,0)){case 1:a:{var e,g=new Set(null!=(e=F(a,3))?e:[]);b=r(F(b,3));for(e=b.next();!e.done;e=b.next())if(g.has(e.value)){d=!0;break a}d=!1}break;case 0:a:{e=new Set(null!=(g=F(a,4))?g:[]);b=r(F(b,4));for(g=b.next();!g.done;g=b.next())if(e.has(g.value)){d=!0;break a}d=!1}break;case 2:b=new Ub(b),d=(e=N(a,yb,5))?Vb(b,e):!1}return J(a,6)?d?null:c:d?c:null}
-function Vb(a,b){var c=I(b,1,0),d=b.ca(),e=O(b,yb,2);switch(c){case 2:c=d.every(function(g){return Wb(a,g)})&&e.every(function(g){return Vb(a,g)});break;case 1:c=d.some(function(g){return Wb(a,g)})||e.some(function(g){return Vb(a,g)});break;default:throw Error("unexpected value "+c+"!");}return J(b,4)?!c:c}
-var Ub=function(a){this.ga=new Map;a=r(a.ca());for(var b=a.next();!b.done;b=a.next()){var c=b.value;b=I(c,1,0);c=I(c,2,0);var d=this.ga.get(b);d||(d=new Set,this.ga.set(b,d));d.add(c)}},Wb=function(a,b){var c=I(b,2,0);return(a=a.ga.get(I(b,1,0)))?a.has(c):!1};function Xb(a,b){a=r((null==b?void 0:b.get(a))||[]);for(b=a.next();!b.done;b=a.next())if(b=b.value,b.count+1>b.xa)return!1;return!0};function Yb(a,b){return null==a.na?!0:!a.na.some(function(c){var d;return null==(d=b.Ba)?void 0:d.includes(c,0)})};var Zb=function(a){S.call(this,a)};t(Zb,S);n=Zb.prototype;n.u=function(){return P(this,1)};n.v=function(){return P(this,2)};n.W=function(){return P(this,3)};n.V=function(){return P(this,4)};n.U=function(){return P(this,5)};n.X=function(){return P(this,6)};var ac=function(a){S.call(this,a,-1,$b)};t(ac,S);var $b=[1];function bc(a,b){var c=!0;c=void 0===c?!1:c;return cc(0,(null==a?void 0:O(a,U,1))||[],(null==b?void 0:O(b,U,1))||[],c)}function dc(a,b){var c=!0;c=void 0===c?!1:c;return cc(1,(null==a?void 0:a.Y())||[],(null==b?void 0:b.Y())||[],c)}function ec(a,b){var c=!0;c=void 0===c?!1:c;return cc(1,(null==a?void 0:a.ma())||[],(null==b?void 0:b.Y())||[],c)}
-function cc(a,b,c,d){var e=0,g=new Map;b=r(b);for(var f=b.next();!f.done;f=b.next())e=f.value,g.set(I(e,1,""),e),e=L(e,3);b=null;c=r(c);for(f=c.next();!f.done;f=c.next()){var h=f.value;e=L(h,3);if(f=d?g.values().next().value:g.get(I(h,1,""))){a:{b=a;f=G(f,2);h=G(h,2);if(f.length===h.length){for(var k=0,l=0;l<f.length;l++)k+=f[l]*h[l];f=k}else f=void 0;if(void 0!==f)switch(b){case 0:b=1/(1+Math.exp(-1*f));break a;case 1:b=Math.exp(f);break a}b=void 0}if(void 0!==b)return b;b=e}}var m;return null!=
-(m=b)?m:e};var fc=function(a){S.call(this,a)};t(fc,S);function gc(a,b,c){"0"===a||c.has(a)||c.set(a,b.filter(function(d){return 0<I(d,3,0)}).map(function(d){var e=I(d,3,0);switch(I(d,1,0)){case 6:d=60*I(d,2,0);break;case 1:d=3600*I(d,2,0);break;case 2:d=86400*I(d,2,0);break;case 3:d=604800*I(d,2,0);break;case 4:d=2592E3*I(d,2,0);break;case 5:d=null;break;default:e=d=0}return{pa:d,xa:e,count:0}}))}function hc(a,b,c){if(b=c.get(b))for(b=r(b),c=b.next();!c.done;c=b.next())c=c.value,(null===c.pa||a.Aa<=c.pa)&&c.count++};var Sb=function(a){S.call(this,a,-1,ic)};t(Sb,S);var ic=[2,3,4];var kc=function(a){S.call(this,a,-1,jc)};t(kc,S);kc.prototype.Y=function(){return O(this,U,3)};kc.prototype.ma=function(){return O(this,U,10)};var jc=[1,3,10,7,8];var mc=function(a){S.call(this,a,-1,lc)};t(mc,S);n=mc.prototype;n.u=function(){return P(this,1)};n.v=function(){return P(this,2)};n.W=function(){return P(this,3)};n.V=function(){return P(this,6)};n.U=function(){return P(this,7)};n.X=function(){return P(this,8)};var lc=[9,10,11,12,13,14];var oc=function(a){S.call(this,a,-1,nc)};t(oc,S);var nc=[1];var qc=function(a){S.call(this,a,-1,pc)};t(qc,S);var pc=[1];var rc={ad:{},bid:0,render:""};function sc(){new qc;return function(a,b,c,d,e){return tc(a,c,d,e)}}
-function tc(a,b,c,d){b=b?new Gb(nb(b)):void 0;var e,g;if(!b||!(O(b,Kb,2).length||(null==(e=W(b))?0:J(e,1))||(null==(g=W(b))?0:J(g,5))))return rc;e=new ac(nb(a.userBiddingSignals));g=a.ads.map(function(f){return{renderUrl:f.renderUrl,metadata:new Zb(nb(f.metadata))}});c=c[a.name]?new oc(nb(c[a.name])):void 0;d=d.prevWins.map(function(f){return{Aa:f[0],I:new Zb(nb(f[1].metadata))}});return uc(a.name,e,g,d,c,b)}
-function uc(a,b,c,d,e,g){var f,h={Ja:null!=(f=null==g?void 0:W(g))?f:void 0,T:new Map,O:new Map,R:new Map,S:new Map,Z:new Map,interestGroupName:null!=a?a:void 0};a=new Map;if(e){e=r(O(e,mc,1));for(f=e.next();!f.done;f=e.next())f=f.value,a.set(f.u().concat("+",f.v(),"+",f.W()),f),gc(f.v(),O(f,fc,9),h.T),gc(f.u(),O(f,fc,10),h.O),gc(f.V(),O(f,fc,11),h.R),gc(f.U(),O(f,fc,12),h.S),gc(f.X(),O(f,fc,13),h.Z);d=r(d);for(e=d.next();!e.done;e=d.next())e=e.value,h.T&&hc(e,e.I.v(),h.T),h.O&&hc(e,e.I.u(),h.O),
-h.R&&hc(e,e.I.V(),h.R),h.S&&hc(e,e.I.U(),h.S),h.Z&&hc(e,e.I.X(),h.Z)}e=new Map;if(g)for(d=r(O(g,Kb,2)),f=d.next();!f.done;f=d.next())f=f.value,e.set(f.u().concat("+",f.v(),"+",""),f.da());d=[];c=r(c);for(f=c.next();!f.done;f=c.next()){f=f.value;f={renderUrl:f.renderUrl,H:f.metadata.u(),K:f.metadata.v(),ka:f.metadata.W(),ja:f.metadata.V(),ia:f.metadata.U(),la:f.metadata.X(),i:0,J:0};var k=f.H.concat("+",f.K,"+",f.ka);f.aa=e.get(f.H.concat("+",f.K,"+",""));if(!f.aa){var l=void 0,m=void 0,p=void 0,y=
-void 0;if(!(null==(l=g)?0:null==(m=W(l))?0:J(m,1))&&!(null==(p=g)?0:null==(y=W(p))?0:J(y,5)))continue;else if(!a.get(k))continue;m=l=void 0;f.o=null!=(m=null==(l=a.get(k))?void 0:N(l,kc,4))?m:void 0}m=l=void 0;f.ha=null!=(m=null==(l=a.get(k))?void 0:N(l,Ab,5))?m:void 0;m=l=void 0;f.na=null!=(m=null==(l=a.get(k))?void 0:F(l,14))?m:void 0;d.push(f)}if(c=null==g?void 0:N(g,Ab,5)){a=new Map;e=new Map;f=r(O(c,Cb,1));for(k=f.next();!k.done;k=f.next())k=k.value,a.set(I(k,1,0),k);c=r(O(c,Eb,2));for(f=c.next();!f.done;f=
-c.next())f=f.value,e.set(I(f,1,0),f);h.ta=a;h.ua=e}var H;h.Ba=null!=(H=F(b,1))?H:void 0;b=[];H=new Map;a=r(d);for(d=a.next();!d.done;d=a.next())if(d=d.value,e=h,!(!Xb(d.K,e.T)||!Xb(d.H,e.O)||d.ja&&!Xb(d.ja,e.R)||d.ia&&!Xb(d.ia,e.S)||d.la&&!Xb(d.la,e.Z))){if(d.ha){c=h;e=c.ta;c=c.ua;f=d.ha;if(e&&c&&f)a:{k=r(O(f,Cb,1));for(l=k.next();!l.done;l=k.next()){p=l.value;y=I(p,1,0);var da=c.get(y);if(da){if(J(p,7)){l=H.get(y);m=I(p,8,0);if(void 0===l)l=new Map,H.set(y,l);else{var na=l.get(m);if(void 0!==na){e=
-na;break a}}p=Tb(p,da,y);l.set(m,p)}else p=Tb(p,da,y);if(p){e=p;break a}}}c=r(O(f,Eb,2));for(f=c.next();!f.done;f=c.next())if(f=f.value,k=I(f,1,0),l=e.get(k))if(f=Tb(l,f,k)){e=f;break a}e=null}else e=null;if(e)continue}Yb(d,h)&&b.push(d)}return vc({ads:b,ya:h},g).bidResponse}
-function vc(a,b){for(var c=[],d=[],e=r(a.ads),g=e.next();!g.done;g=e.next()){g=g.value;var f=void 0,h=void 0;if(null==(f=b)?0:null==(h=W(f))?0:J(h,7)){var k=h=f=void 0,l=void 0,m=void 0,p=void 0;g.H===(null==(f=b)?void 0:null==(h=N(f,Z,16))?void 0:h.u())&&g.K===(null==(k=b)?void 0:null==(l=N(k,Z,16))?void 0:l.v())&&a.ya.interestGroupName===(null==(m=b)?void 0:null==(p=N(m,Z,16))?void 0:I(p,1,""))?(k=h=f=void 0,l=null!=(k=null==(f=b)?void 0:null==(h=N(f,Z,16))?void 0:h.da())?k:0,g.i=0===l?1E9:l):g.i=
-0}else if(null!=g.aa){g.i=g.aa;c.push(g);continue}else if(h=f=void 0,null==(f=b)?0:null==(h=W(f))?0:J(h,1))ub(g.o)?(f=void 0,g.ea=ec(null==(f=b)?void 0:N(f,Jb,1),g.o)):(f=void 0,g.oa=bc(null==(f=b)?void 0:N(f,Jb,1),g.o),f=void 0,g.ea=dc(null==(f=b)?void 0:N(f,Jb,1),g.o)),g.i=Rb(g,g.o),g.i||(h=f=void 0,g.i=null!=(h=null==(f=g.o)?void 0:L(f,6))?h:0);else if(h=f=void 0,null==(f=b)?0:null==(h=W(f))?0:J(h,5))h=f=void 0,g.i=null!=(h=null==(f=g.o)?void 0:L(f,6))?h:0;d.push(g)}c={renderUrl:"",H:"",K:"",ka:"",
-i:0,J:0};var y;if(null==b?0:null==(y=W(b))?0:J(y,7))b=a.ads.reduce(function(V,K){return V.i<K.i?K:V},c),b.J=b.i;else{y=a.ads.reduce(function(V,K){return!ub(K.o)&&V.i<K.i?K:V},c);c=a.ads.reduce(function(V,K){return ub(K.o)&&V.i<K.i?K:V},c);a=Pb(b,null==y?void 0:y.i);var H,da;a.l=tb(a.l,null==b?void 0:null==(H=W(b))?void 0:null==(da=N(H,X,3))?void 0:L(da,6));var na;H=Ob(null==b?void 0:N(b,X,7),null==c?void 0:c.i,null==b?void 0:null==(na=W(b))?void 0:N(na,X,4));var Lb,Mb;H.l=tb(H.l,null==b?void 0:null==
-(Lb=W(b))?void 0:null==(Mb=N(Lb,X,4))?void 0:L(Mb,6));a.l>H.l?(b=y,b.J=a.l):(b=c,b.J=H.l)}return{bidResponse:{ad:{},bid:b.J,render:b.renderUrl},debugInfo:void 0}};var wc=function(a){var b={maxFloorCpmUsdMicros:"6250"},c={topWindowHostname:"www.cnn.com",seller:"https://pubads.g.doubleclick.net",joinCount:7,bidCount:0,prevWins:[]},d=sc();return function(){return d(a,b,rb,sb,c)}};
-
-function generateBid(interestGroups){for(var a=[],b=Date.now(),c=r(interestGroups),d=c.next();!d.done;d=c.next()){var e={generateBidTime:0,success:!1},g=wc(d.value);d=Date.now();g=g();e.generateBidTime=Date.now()-d;e.success=JSON.stringify(g)===JSON.stringify({ad:{},bid:2937687.988333709,render:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197294&cv_id=4"});e.bidResponse=g;a.push(e)}a.push({generateBidTime:Date.now()-b,success:!0});return a;}
diff --git a/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java b/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
deleted file mode 100644
index fc3738c..0000000
--- a/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
+++ /dev/null
@@ -1,616 +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.rubidium.js;
-
-import static com.android.adservices.service.js.JSScriptArgument.arrayArg;
-import static com.android.adservices.service.js.JSScriptArgument.jsonArg;
-import static com.android.adservices.service.js.JSScriptArgument.numericArg;
-import static com.android.adservices.service.js.JSScriptArgument.recordArg;
-import static com.android.adservices.service.js.JSScriptArgument.stringArg;
-import static com.android.adservices.service.js.JSScriptArgument.stringArrayArg;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeTrue;
-
-import android.adservices.adselection.AdSelectionConfig;
-import android.adservices.adselection.AdWithBid;
-import android.adservices.common.AdData;
-import android.adservices.common.AdSelectionSignals;
-import android.adservices.common.AdTechIdentifier;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.net.Uri;
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.adservices.LoggerFactory;
-import com.android.adservices.data.adselection.CustomAudienceSignals;
-import com.android.adservices.service.adselection.AdCounterKeyCopier;
-import com.android.adservices.service.adselection.AdCounterKeyCopierNoOpImpl;
-import com.android.adservices.service.adselection.AdDataArgumentUtil;
-import com.android.adservices.service.adselection.AdSelectionConfigArgumentUtil;
-import com.android.adservices.service.adselection.AdWithBidArgumentUtil;
-import com.android.adservices.service.adselection.CustomAudienceBiddingSignalsArgumentUtil;
-import com.android.adservices.service.adselection.CustomAudienceScoringSignalsArgumentUtil;
-import com.android.adservices.service.common.NoOpRetryStrategyImpl;
-import com.android.adservices.service.js.IsolateSettings;
-import com.android.adservices.service.js.JSScriptArgument;
-import com.android.adservices.service.js.JSScriptArrayArgument;
-import com.android.adservices.service.js.JSScriptEngine;
-import com.android.adservices.service.js.JSScriptRecordArgument;
-import com.android.adservices.service.profiling.JSScriptEngineLogConstants;
-import com.android.adservices.service.profiling.Profiler;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListenableFuture;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.time.Clock;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.ZoneOffset;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-/** To run the unit tests for this class, run "atest RubidiumPerfTests:JSScriptEnginePerfTests" */
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class JSScriptEnginePerfTests {
-    private static final String TAG = JSScriptEngine.TAG;
-    private static final Context sContext = ApplicationProvider.getApplicationContext();
-    private static final ExecutorService sExecutorService = Executors.newFixedThreadPool(10);
-
-    private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
-    private static final JSScriptEngine sJSScriptEngine =
-            JSScriptEngine.getInstanceForTesting(
-                    sContext, Profiler.createInstance(JSScriptEngine.TAG), sLogger);
-    private static final Clock CLOCK = Clock.fixed(Instant.now(), ZoneOffset.UTC);
-    private static final Instant ACTIVATION_TIME = CLOCK.instant();
-    private static final Instant EXPIRATION_TIME = CLOCK.instant().plus(Duration.ofDays(1));
-    private static final AdSelectionSignals CONTEXTUAL_SIGNALS = AdSelectionSignals.EMPTY;
-    private static final AdCounterKeyCopier AD_COUNTER_KEY_COPIER_NO_OP =
-            new AdCounterKeyCopierNoOpImpl();
-
-    private final AdDataArgumentUtil mAdDataArgumentUtil =
-            new AdDataArgumentUtil(AD_COUNTER_KEY_COPIER_NO_OP);
-    private final AdWithBidArgumentUtil mAdWithBidArgumentUtil =
-            new AdWithBidArgumentUtil(mAdDataArgumentUtil);
-
-    @Rule
-    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
-
-    @Before
-    public void before() throws Exception {
-        // Warm up the sandbox env.
-        callJSEngine(
-                "function test() { return \"hello world\";" + " }", ImmutableList.of(), "test");
-    }
-
-    @After
-    public void after() {
-        sJSScriptEngine.shutdown();
-    }
-
-    @Test
-    public void evaluate_helloWorld() throws Exception {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        while (state.keepRunning()) {
-            String res =
-                    callJSEngine(
-                            "function test() { return \"hello world\";" + " }",
-                            ImmutableList.of(),
-                            "test");
-            assertThat(res).isEqualTo("\"hello world\"");
-        }
-    }
-
-    @Test
-    public void evaluate_emptyGenerateBid() throws Exception {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        state.pauseTiming();
-
-        InputStream testJsInputStream = sContext.getAssets().open("empty_generate_bid.js");
-        String jsTestFile = new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
-        JSScriptArgument adDataArgument =
-                recordArg(
-                        "ad",
-                        stringArg("render_url", "http://google.com"),
-                        recordArg("metadata", numericArg("input", 10)));
-        callJSEngine(jsTestFile, ImmutableList.of(adDataArgument), "generateBid");
-
-        state.resumeTiming();
-        while (state.keepRunning()) {
-            callJSEngine(jsTestFile, ImmutableList.of(adDataArgument), "generateBid");
-        }
-    }
-
-    @Test
-    public void evaluate_turtledoveSampleGenerateBid() throws Exception {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        state.pauseTiming();
-
-        InputStream testJsInputStream = sContext.getAssets().open("turtledove_generate_bid.js");
-        String jsTestFile = new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
-        // Initialize the environment with one call.
-        callJSEngine(jsTestFile, ImmutableList.of(), "generateBid");
-
-        state.resumeTiming();
-        while (state.keepRunning()) {
-            callJSEngine(jsTestFile, ImmutableList.of(), "generateBid");
-        }
-    }
-
-    @Test
-    public void evaluate_turtledoveSampleGenerateBid_parametrized_10Ads() throws Exception {
-        runParametrizedTurtledoveScript(10);
-    }
-
-    @Test
-    public void evaluate_turtledoveSampleGenerateBid_parametrized_25Ads() throws Exception {
-        runParametrizedTurtledoveScript(25);
-    }
-
-    @Test
-    public void evaluate_turtledoveSampleGenerateBid_parametrized_50Ads() throws Exception {
-        runParametrizedTurtledoveScript(50);
-    }
-
-    @Test
-    public void evaluate_turtledoveSampleGenerateBid_parametrized_75Ads() throws Exception {
-        runParametrizedTurtledoveScript(75);
-    }
-
-    @Test
-    public void evaluate_rubidiumGenerateBid_parametrized_1Ad() throws Exception {
-        runParameterizedRubidiumGenerateBid(1);
-    }
-
-    @Test
-    public void evaluate_rubidiumGenerateBid_parametrized_10Ads() throws Exception {
-        runParameterizedRubidiumGenerateBid(10);
-    }
-
-    @Test
-    public void evaluate_rubidiumGenerateBid_parametrized_25Ads() throws Exception {
-        runParameterizedRubidiumGenerateBid(25);
-    }
-
-    @Test
-    public void evaluate_rubidiumGenerateBid_parametrized_50Ads() throws Exception {
-        runParameterizedRubidiumGenerateBid(50);
-    }
-
-    @Test
-    public void evaluate_rubidiumGenerateBid_parametrized_75Ads() throws Exception {
-        runParameterizedRubidiumGenerateBid(75);
-    }
-
-    @Test
-    public void evaluate_rubidiumScoreAd_parametrized_1Ad() throws Exception {
-        runParameterizedRubidiumScoreAd(1);
-    }
-
-    @Test
-    public void evaluate_rubidiumScoreAd_parametrized_10Ads() throws Exception {
-        runParameterizedRubidiumScoreAd(10);
-    }
-
-    @Test
-    public void evaluate_rubidiumScoreAd_parametrized_25Ads() throws Exception {
-        runParameterizedRubidiumScoreAd(25);
-    }
-
-    @Test
-    public void evaluate_rubidiumScoreAd_parametrized_50Ads() throws Exception {
-        runParameterizedRubidiumScoreAd(50);
-    }
-
-    @Test
-    public void evaluate_rubidiumScoreAd_parametrized_75Ads() throws Exception {
-        runParameterizedRubidiumScoreAd(75);
-    }
-
-    @SuppressLint("DefaultLocale")
-    private void runParametrizedTurtledoveScript(int numAds) throws Exception {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        state.pauseTiming();
-        InputStream testJsInputStream =
-                sContext.getAssets().open("turtledove_parametrized_generateBid.js");
-        String jsTestFile = new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
-
-        state.resumeTiming();
-        while (state.keepRunning()) {
-            int numInterestGroups = 1;
-            String res =
-                    callJSEngine(
-                            sJSScriptEngine,
-                            jsTestFile,
-                            ImmutableList.of(
-                                    buildSampleInterestGroupArg(numInterestGroups, numAds)),
-                            "generateBid");
-
-            // I modified the Turtledove script to have the total execution time
-            // (across all IGs) as the last element in the response array.
-            JSONArray obj = new JSONArray(res);
-            long webviewExecTime = obj.getJSONObject(obj.length() - 1).getLong("generateBidTime");
-            String webviewExecTimeLog =
-                    String.format(
-                            "(%s: %d)",
-                            JSScriptEngineLogConstants.WEBVIEW_EXECUTION_TIME, webviewExecTime);
-            // The listener picks up logs from JSScriptEngine, so simulate logging from there.
-            Log.d(TAG, webviewExecTimeLog);
-        }
-    }
-
-    private JSScriptArrayArgument<JSScriptRecordArgument> buildSampleInterestGroupArg(
-            int numCustomAudiences, int numAds) {
-        JSScriptRecordArgument ad =
-                recordArg(
-                        "foo",
-                        ImmutableList.of(
-                                stringArg(
-                                        "renderUrl",
-                                        "https://googleads.g.doubleclick.net/ads/simple-ad"
-                                                + ".html?adg_id=52836427830&cr_id=310927197297"
-                                                + "&cv_id=4"),
-                                stringArrayArg(
-                                        "metadata",
-                                        ImmutableList.of(
-                                                "52836427830", "310927197297", "4", "608936333"))));
-
-        JSScriptRecordArgument interestGroupArg =
-                recordArg(
-                        "foo",
-                        stringArg("owner", "https://googleads.g.doubleclick.net/"),
-                        stringArg("name", "1j115753478"),
-                        stringArg("biddingLogicUrl", "https://googleads.g.doubleclick.net/td/bjs"),
-                        stringArg(
-                                "dailyUpdateUrl", "https://googleads.g.doubleclick.net/td/update"),
-                        stringArg(
-                                "trustedBiddingSignalsUrl",
-                                "https://googleads.g.doubleclick.net/td/sjs"),
-                        stringArrayArg(
-                                "trustedBiddingSignalsKeys", ImmutableList.of("1j115753478")),
-                        stringArrayArg("userBiddingSignals", ImmutableList.of()),
-                        new JSScriptArrayArgument("ads", Collections.nCopies(numAds, ad)));
-
-        return arrayArg("foo", Collections.nCopies(numCustomAudiences, interestGroupArg));
-    }
-
-    @Test
-    public void evaluate_turtledoveWasm() throws Exception {
-        assumeTrue(sJSScriptEngine.isWasmSupported().get(3, TimeUnit.SECONDS));
-
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        state.pauseTiming();
-
-        String jsTestFile = readAsset("generate_bid_using_wasm.js");
-        byte[] wasmTestFile = readBinaryAsset("generate_bid.wasm");
-        JSScriptArgument[] inputBytes = new JSScriptArgument[200];
-        Random rand = new Random();
-        for (int i = 0; i < inputBytes.length; i++) {
-            byte value = (byte) (rand.nextInt(2 * Byte.MAX_VALUE) - Byte.MIN_VALUE);
-            inputBytes[i] = JSScriptArgument.numericArg("_", value);
-        }
-        JSScriptArgument adDataArgument =
-                recordArg(
-                        "ad",
-                        stringArg("render_url", "http://google.com"),
-                        recordArg("metadata", JSScriptArgument.arrayArg("input", inputBytes)));
-
-        state.resumeTiming();
-        while (state.keepRunning()) {
-            callJSEngine(jsTestFile, wasmTestFile, ImmutableList.of(adDataArgument), "generateBid");
-        }
-    }
-
-    private String callJSEngine(
-            @NonNull String jsScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName)
-            throws Exception {
-        return callJSEngine(sJSScriptEngine, jsScript, args, functionName);
-    }
-
-    private String callJSEngine(
-            @NonNull String jsScript,
-            @NonNull byte[] wasmScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName)
-            throws Exception {
-        return callJSEngine(sJSScriptEngine, jsScript, wasmScript, args, functionName);
-    }
-
-    private static String callJSEngine(
-            @NonNull JSScriptEngine jsScriptEngine,
-            @NonNull String jsScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName)
-            throws Exception {
-        CountDownLatch resultLatch = new CountDownLatch(1);
-        ListenableFuture<String> futureResult =
-                callJSEngineAsync(jsScriptEngine, jsScript, args, functionName, resultLatch);
-        resultLatch.await();
-        return futureResult.get();
-    }
-
-    private String callJSEngine(
-            @NonNull JSScriptEngine jsScriptEngine,
-            @NonNull String jsScript,
-            @NonNull byte[] wasmScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName)
-            throws Exception {
-        CountDownLatch resultLatch = new CountDownLatch(1);
-        ListenableFuture<String> futureResult =
-                callJSEngineAsync(
-                        jsScriptEngine, jsScript, wasmScript, args, functionName, resultLatch);
-        resultLatch.await();
-        return futureResult.get();
-    }
-
-    private static ListenableFuture<String> callJSEngineAsync(
-            @NonNull String jsScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName,
-            @NonNull CountDownLatch resultLatch) {
-        return callJSEngineAsync(sJSScriptEngine, jsScript, args, functionName, resultLatch);
-    }
-
-    private static ListenableFuture<String> callJSEngineAsync(
-            @NonNull JSScriptEngine engine,
-            @NonNull String jsScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName,
-            @NonNull CountDownLatch resultLatch) {
-        Objects.requireNonNull(engine);
-        Objects.requireNonNull(resultLatch);
-        ListenableFuture<String> result = engine.evaluate(
-                jsScript,
-                args,
-                functionName,
-                IsolateSettings.forMaxHeapSizeEnforcementDisabled(),
-                new NoOpRetryStrategyImpl());
-        result.addListener(resultLatch::countDown, sExecutorService);
-        return result;
-    }
-
-    private ListenableFuture<String> callJSEngineAsync(
-            @NonNull JSScriptEngine engine,
-            @NonNull String jsScript,
-            @NonNull byte[] wasmScript,
-            @NonNull List<JSScriptArgument> args,
-            @NonNull String functionName,
-            @NonNull CountDownLatch resultLatch) {
-        Objects.requireNonNull(engine);
-        Objects.requireNonNull(resultLatch);
-        ListenableFuture<String> result = engine.evaluate(
-                jsScript,
-                wasmScript,
-                args,
-                functionName,
-                IsolateSettings.forMaxHeapSizeEnforcementDisabled(),
-                new NoOpRetryStrategyImpl());
-        result.addListener(resultLatch::countDown, sExecutorService);
-        return result;
-    }
-
-    private byte[] readBinaryAsset(@NonNull String assetName) throws IOException {
-        return sContext.getAssets().open(assetName).readAllBytes();
-    }
-
-    private String readAsset(@NonNull String assetName) throws IOException {
-        return new String(readBinaryAsset(assetName), StandardCharsets.UTF_8);
-    }
-
-    public void runParameterizedRubidiumGenerateBid(int numOfAds) throws Exception {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        state.pauseTiming();
-        List<AdData> adDataList = getSampleAdDataList(numOfAds, "https://ads.example/");
-        ImmutableList.Builder<JSScriptArgument> adDataListArgument = new ImmutableList.Builder<>();
-        for (AdData adData : adDataList) {
-            adDataListArgument.add(mAdDataArgumentUtil.asScriptArgument("ignored", adData));
-        }
-        AdSelectionSignals perBuyerSignals = generatePerBuyerSignals(numOfAds);
-        AdSelectionSignals auctionSignals = AdSelectionSignals.fromString("{\"auctionSignal1"
-                + "\":\"auctionValue1\",\"auctionSignal2\":\"auctionValue2\"}");
-
-        AdTechIdentifier buyer = AdTechIdentifier.fromString("https://example-dsp.com");
-        AdSelectionSignals trustedBiddingSignals = AdSelectionSignals.fromString("{\"key1"
-                + "\":\"tbs1\",\"key2\":{}}");
-        CustomAudienceSignals customAudienceSignals = getSampleCustomAudienceSignals(buyer,
-                "shoes-running");
-
-        ImmutableList<JSScriptArgument> args = ImmutableList.<JSScriptArgument>builder()
-                .add(arrayArg("ads", adDataListArgument.build()))
-                .add(jsonArg("auctionSignals", auctionSignals))
-                .add(jsonArg("perBuyerSignals", perBuyerSignals))
-                .add(jsonArg("trustedBiddingSignals", trustedBiddingSignals))
-                .add(jsonArg("contextualSignals", CONTEXTUAL_SIGNALS))
-                .add(CustomAudienceBiddingSignalsArgumentUtil.asScriptArgument(
-                        "customAudienceBiddingSignal", customAudienceSignals))
-                .build();
-        InputStream testJsInputStream = sContext.getAssets().open(
-                "rubidium_bidding_logic_compiled.js");
-        String jsTestFile = new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
-        //logging time taken to call JS
-        state.resumeTiming();
-        while (state.keepRunning()) {
-            String res = callJSEngine(jsTestFile, args, "generateBidIterative");
-            JSONObject jsonObject = new JSONObject(res);
-            long webviewExecTime = jsonObject.getLong("duration");
-            String webviewExecTimeLog =
-                    String.format(Locale.ENGLISH,
-                            "(%s: %d)",
-                            JSScriptEngineLogConstants.WEBVIEW_EXECUTION_TIME,
-                            webviewExecTime);
-            // The listener picks up logs from JSScriptEngine, so simulate logging from there.
-            Log.d(TAG, webviewExecTimeLog);
-        }
-    }
-
-    public void runParameterizedRubidiumScoreAd(int numOfAds) throws Exception {
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        state.pauseTiming();
-        String adRenderUrl = "https://rtb.example/creative";
-        List<AdWithBid> adWithBidList = getSampleAdDataWithBidList(numOfAds, adRenderUrl);
-        ImmutableList.Builder<JSScriptArgument> adWithBidArrayArgument =
-                new ImmutableList.Builder<>();
-        for (AdWithBid adWithBid : adWithBidList) {
-            adWithBidArrayArgument.add(
-                    mAdWithBidArgumentUtil.asScriptArgument("adWithBid", adWithBid));
-        }
-        AdTechIdentifier seller = AdTechIdentifier.fromString("www.example-ssp.com");
-        AdSelectionSignals sellerSignals = AdSelectionSignals.fromString("{\"signals\":[]}");
-        String trustedScoringSignalJson = String.format(Locale.ENGLISH,
-                "{\"renderUrl\":{\"%s\":[]}}", adRenderUrl);
-        AdSelectionSignals trustedScoringSignalsJson = AdSelectionSignals.fromString(
-                trustedScoringSignalJson);
-
-        AdTechIdentifier buyer1 = AdTechIdentifier.fromString("https://example-dsp.com");
-        AdSelectionSignals buyer1Signals = AdSelectionSignals.fromString("{\"https://example-dsp"
-                + ".com:1\":\"value1\",\"https://example-dsp.com:2\":\"value2\"}");
-        Map<AdTechIdentifier, AdSelectionSignals> perBuyerSignals = ImmutableMap.of(buyer1,
-                buyer1Signals);
-
-        AdSelectionConfig adSelectionConfig = getSampleAdSelectionConfig(seller, sellerSignals,
-                perBuyerSignals);
-        CustomAudienceSignals customAudienceSignals = getSampleCustomAudienceSignals(buyer1,
-                "shoes-running");
-
-        ImmutableList<JSScriptArgument> args = ImmutableList.<JSScriptArgument>builder()
-                .add(arrayArg("adsWithBids", adWithBidArrayArgument.build()))
-                .add(AdSelectionConfigArgumentUtil.asScriptArgument(adSelectionConfig,
-                        "adSelectionConfig"))
-                .add(jsonArg("sellerSignals", sellerSignals))
-                .add(jsonArg("trustedScoringSignals", trustedScoringSignalsJson))
-                .add(jsonArg("contextualSignals", CONTEXTUAL_SIGNALS))
-                .add(CustomAudienceScoringSignalsArgumentUtil.asScriptArgument(
-                        "customAudienceScoringSignal", customAudienceSignals))
-                .build();
-        InputStream testJsInputStream = sContext.getAssets().open(
-                "rubidium_scoring_logic_compiled.js");
-        String jsTestFile = new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
-        //logging time taken to call JS
-        state.resumeTiming();
-        while (state.keepRunning()) {
-            String res = callJSEngine(jsTestFile, args, "scoreAdIterative");
-            JSONObject jsonObject = new JSONObject(res);
-            long webviewExecTime = jsonObject.getLong("duration");
-            String webviewExecTimeLog =
-                    String.format(Locale.ENGLISH,
-                            "(%s: %d)",
-                            JSScriptEngineLogConstants.WEBVIEW_EXECUTION_TIME,
-                            webviewExecTime);
-            // The listener picks up logs from JSScriptEngine, so simulate logging from there.
-            Log.d(TAG, webviewExecTimeLog);
-        }
-    }
-
-    private List<AdWithBid> getSampleAdDataWithBidList(int size, String baseUri) {
-        double initialBid = 1.23;
-        return IntStream.rangeClosed(1, size).mapToObj(iterator -> {
-            Uri renderUri = Uri.parse(String.format(Locale.ENGLISH, "%s%d", baseUri, iterator));
-            String metaDataJson = String.format(Locale.ENGLISH, "{\"metadata\":[\"%d\",\"123\"]}",
-                    iterator);
-            AdData adData = new AdData.Builder().setRenderUri(renderUri).setMetadata(
-                    metaDataJson).build();
-            return new AdWithBid(adData, initialBid + iterator);
-        }).collect(Collectors.toCollection(ArrayList::new));
-    }
-
-    private List<AdData> getSampleAdDataList(int size, String baseUri) {
-        return IntStream.rangeClosed(1, size).mapToObj(iterator -> {
-            Uri renderUri = Uri.parse(String.format(Locale.ENGLISH, "%s%d", baseUri, iterator));
-            String metaDataJson = String.format(Locale.ENGLISH, "{\"metadata\":[\"%d\",\"123\"]}",
-                    iterator);
-            return new AdData.Builder().setRenderUri(renderUri).setMetadata(
-                    metaDataJson).build();
-        }).collect(Collectors.toCollection(ArrayList::new));
-    }
-
-    private CustomAudienceSignals getSampleCustomAudienceSignals(AdTechIdentifier buyer,
-            String name) {
-        String owner = "www.example-dsp.com";
-        AdSelectionSignals userBiddingSignals = AdSelectionSignals.fromString("{\"signals\":[]}");
-        return new CustomAudienceSignals.Builder()
-                .setOwner(owner)
-                .setBuyer(buyer)
-                .setActivationTime(ACTIVATION_TIME)
-                .setExpirationTime(EXPIRATION_TIME)
-                .setUserBiddingSignals(userBiddingSignals)
-                .setName(name)
-                .build();
-    }
-
-    private AdSelectionConfig getSampleAdSelectionConfig(AdTechIdentifier seller,
-            AdSelectionSignals sellerSignals,
-            Map<AdTechIdentifier, AdSelectionSignals> perBuyerSignals) {
-        Uri decisionLogicUri = Uri.parse("https://www.example-ssp.com/decide.js");
-        Uri trustedScoringSignalsUri = Uri.parse("https://www.example-ssp.com/signals");
-        List<AdTechIdentifier> buyers = ImmutableList.copyOf(
-                new ArrayList<>(perBuyerSignals.keySet()));
-        return new AdSelectionConfig.Builder()
-                .setSeller(seller)
-                .setDecisionLogicUri(decisionLogicUri)
-                .setCustomAudienceBuyers(buyers)
-                .setAdSelectionSignals(AdSelectionSignals.EMPTY)
-                .setSellerSignals(sellerSignals)
-                .setPerBuyerSignals(perBuyerSignals)
-                .setTrustedScoringSignalsUri(trustedScoringSignalsUri)
-                .build();
-    }
-
-    private AdSelectionSignals generatePerBuyerSignals(int size) {
-        String signalArrayFormat = "[\"%d\",\"123\",%d]";
-        String signalArray = IntStream.rangeClosed(1, size)
-                .mapToObj(i -> String.format(Locale.ENGLISH, signalArrayFormat, i, i))
-                .collect(Collectors.joining(", ", "[", "]"));
-        return AdSelectionSignals.fromString(
-                String.format(Locale.ENGLISH, "{\"signals\":[null,%s,[null]]}",
-                        signalArray));
-    }
-}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java b/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java
index f3bea17..0c2ee8c 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java
@@ -19,7 +19,9 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Insets;
 import android.os.Bundle;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.widget.EditText;
 import android.widget.LinearLayout;
@@ -42,6 +44,11 @@
         if (getIntent().getBooleanExtra(INTENT_EXTRA_ADD_EDIT_TEXT, false)) {
             final LinearLayout layout = new LinearLayout(this);
             layout.setOrientation(LinearLayout.VERTICAL);
+            layout.setOnApplyWindowInsetsListener((v, w) -> {
+                final Insets insets = w.getSystemWindowInsets();
+                v.setPadding(insets.left, insets.top, insets.right, insets.bottom);
+                return WindowInsets.CONSUMED;
+            });
 
             final EditText editText = new EditText(this);
             editText.setId(ID_EDITOR);
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
index 58434f1..22b6489 100644
--- a/apex/jobscheduler/OWNERS
+++ b/apex/jobscheduler/OWNERS
@@ -2,7 +2,6 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/apex/jobscheduler/framework/java/android/app/job/OWNERS b/apex/jobscheduler/framework/java/android/app/job/OWNERS
index b4a45f5..0b1e559 100644
--- a/apex/jobscheduler/framework/java/android/app/job/OWNERS
+++ b/apex/jobscheduler/framework/java/android/app/job/OWNERS
@@ -4,4 +4,3 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
diff --git a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
index ae98fe1..6c8af39 100644
--- a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
@@ -77,12 +77,6 @@
             @NonNull String notificationChannel, int userId, @NonNull String packageName);
 
     /**
-     * @return {@code true} if the given package holds the
-     * {@link android.Manifest.permission.RUN_BACKUP_JOBS} permission.
-     */
-    boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid);
-
-    /**
      * Report a snapshot of sync-related jobs back to the sync manager
      */
     JobStorePersistStats getPersistStats();
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index ace56d4..06c7d64 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -24,6 +24,7 @@
         "app-compat-annotations",
         "error_prone_annotations",
         "framework",
+        "keepanno-annotations",
         "services.core",
         "unsupportedappusage",
     ],
diff --git a/apex/jobscheduler/service/aconfig/device_idle.aconfig b/apex/jobscheduler/service/aconfig/device_idle.aconfig
index e8c99b1..c4d0d18 100644
--- a/apex/jobscheduler/service/aconfig/device_idle.aconfig
+++ b/apex/jobscheduler/service/aconfig/device_idle.aconfig
@@ -2,6 +2,16 @@
 container: "system"
 
 flag {
+  name: "remove_idle_location"
+  namespace: "location"
+  description: "Remove DeviceIdleController usage of location"
+  bug: "332770178"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
     name: "disable_wakelocks_in_light_idle"
     namespace: "backstage_power"
     description: "Disable wakelocks for background apps while Light Device Idle is active"
diff --git a/apex/jobscheduler/service/aconfig/job.aconfig b/apex/jobscheduler/service/aconfig/job.aconfig
index 75e2efd2..e20f525 100644
--- a/apex/jobscheduler/service/aconfig/job.aconfig
+++ b/apex/jobscheduler/service/aconfig/job.aconfig
@@ -28,3 +28,13 @@
     description: "Only relax a prefetch job's connectivity constraint when the device is charging and battery is not low"
     bug: "299329948"
 }
+
+flag {
+    name: "count_quota_fix"
+    namespace: "backstage_power"
+    description: "Fix job count quota check"
+    bug: "300862949"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4832ea6..11fa7b75 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -109,6 +109,7 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.deviceidle.ConstraintController;
 import com.android.server.deviceidle.DeviceIdleConstraintTracker;
+import com.android.server.deviceidle.Flags;
 import com.android.server.deviceidle.IDeviceIdleConstraint;
 import com.android.server.deviceidle.TvConstraintController;
 import com.android.server.net.NetworkPolicyManagerInternal;
@@ -2558,7 +2559,7 @@
         }
 
         boolean isLocationPrefetchEnabled() {
-            return mContext.getResources().getBoolean(
+            return !Flags.removeIdleLocation() && mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_autoPowerModePrefetchLocation);
         }
 
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 f9c8e0b..b982d12 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -1795,6 +1795,10 @@
 
         mUseFrozenStateToDropListenerAlarms = Flags.useFrozenStateToDropListenerAlarms();
         mStartUserBeforeScheduledAlarms = Flags.startUserBeforeScheduledAlarms();
+        if (mStartUserBeforeScheduledAlarms) {
+            mUserWakeupStore = new UserWakeupStore();
+            mUserWakeupStore.init();
+        }
         if (mUseFrozenStateToDropListenerAlarms) {
             final ActivityManager.UidFrozenStateChangedCallback callback = (uids, frozenStates) -> {
                 final int size = frozenStates.length;
@@ -1913,10 +1917,6 @@
                 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
             }
         }
-        if (mStartUserBeforeScheduledAlarms) {
-            mUserWakeupStore = new UserWakeupStore();
-            mUserWakeupStore.init();
-        }
         publishLocalService(AlarmManagerInternal.class, new LocalService());
         publishBinderService(Context.ALARM_SERVICE, mService);
     }
@@ -3863,7 +3863,7 @@
         long nextNonWakeup = 0;
         if (mAlarmStore.size() > 0) {
             long firstWakeup = mAlarmStore.getNextWakeupDeliveryTime();
-            if (mStartUserBeforeScheduledAlarms) {
+            if (mStartUserBeforeScheduledAlarms && mUserWakeupStore != null) {
                 final long firstUserWakeup = mUserWakeupStore.getNextWakeupTime();
                 if (firstUserWakeup >= 0 && firstUserWakeup < firstWakeup) {
                     firstWakeup = firstUserWakeup;
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 096238a..3bb395f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -1650,6 +1650,16 @@
                     continue;
                 }
 
+                if (Flags.countQuotaFix() && !nextPending.isReady()) {
+                    // This could happen when the constraints for the job have been marked
+                    // as unsatisfiled but hasn't been removed from the pending queue yet.
+                    if (DEBUG) {
+                        Slog.w(TAG, "Pending+not ready job: " + nextPending);
+                    }
+                    pendingJobQueue.remove(nextPending);
+                    continue;
+                }
+
                 if (DEBUG && isSimilarJobRunningLocked(nextPending)) {
                     Slog.w(TAG, "Already running similar job to: " + nextPending);
                 }
@@ -1737,10 +1747,9 @@
                     continue;
                 }
 
-                if (!nextPending.isReady()) {
-                    // This could happen when the job count reached its quota, the constrains
-                    // for the job has been updated but hasn't been removed from the pending
-                    // queue yet.
+                if (Flags.countQuotaFix() && !nextPending.isReady()) {
+                    // This could happen when the constraints for the job have been marked
+                    // as unsatisfiled but hasn't been removed from the pending queue yet.
                     if (DEBUG) {
                         Slog.w(TAG, "Pending+not ready job: " + nextPending);
                     }
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 10162fd..5d1433c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -4560,11 +4560,6 @@
         }
 
         @Override
-        public boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) {
-            return JobSchedulerService.this.hasRunBackupJobsPermission(packageName, packageUid);
-        }
-
-        @Override
         public JobStorePersistStats getPersistStats() {
             synchronized (mLock) {
                 return new JobStorePersistStats(mJobs.getPersistStats());
@@ -4727,27 +4722,6 @@
     }
 
     /**
-     * Returns whether the app holds the {@link Manifest.permission.RUN_BACKUP_JOBS} permission.
-     */
-    private boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) {
-        // This permission is currently hidden so always return false for now (see b/331272951)
-        return false;
-
-        /**
-        if (packageName == null) {
-            Slog.wtfStack(TAG,
-                    "Expected a non-null package name when calling hasRunBackupJobsPermission");
-            return false;
-        }
-
-        return PermissionChecker.checkPermissionForPreflight(getTestableContext(),
-                android.Manifest.permission.RUN_BACKUP_JOBS,
-                PermissionChecker.PID_UNKNOWN, packageUid, packageName)
-                    == PermissionChecker.PERMISSION_GRANTED;
-        */
-    }
-
-    /**
      * Binder stub trampoline implementation
      */
     final class JobSchedulerStub extends IJobScheduler.Stub {
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 9985543..7fca867 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
@@ -1203,14 +1203,9 @@
             return ACTIVE_INDEX;
         }
 
-        final boolean isEligibleAsBackupJob = false // this exemption is being disabled for now.
-                && job.getTriggerContentUris() != null
-                && job.getRequiredNetwork() != null
-                && !job.hasLateConstraint()
-                && mJobSchedulerInternal.hasRunBackupJobsPermission(sourcePackageName, sourceUid);
-        final boolean isBackupExempt = mHasMediaBackupExemption || isEligibleAsBackupJob;
         final int bucketWithBackupExemption;
-        if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX && isBackupExempt) {
+        if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX
+                && mHasMediaBackupExemption) {
             // Treat it as if it's at most WORKING_INDEX (lower index grants higher quota) since
             // media backup jobs are important to the user, and the source package may not have
             // been used directly in a while.
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 cfbfa5d..c240b3f 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
@@ -70,6 +70,7 @@
 import com.android.server.LocalServices;
 import com.android.server.PowerAllowlistInternal;
 import com.android.server.job.ConstantsProto;
+import com.android.server.job.Flags;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
 import com.android.server.usage.AppStandbyInternal;
@@ -886,6 +887,14 @@
         //   1. it was started while the app was in the TOP state
         //   2. the app is currently in the foreground
         //   3. the app overall is within its quota
+        if (!Flags.countQuotaFix()) {
+            return jobStatus.shouldTreatAsUserInitiatedJob()
+                    || isTopStartedJobLocked(jobStatus)
+                    || isUidInForeground(jobStatus.getSourceUid())
+                    || isWithinQuotaLocked(
+                    jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
+        }
+
         if (jobStatus.shouldTreatAsUserInitiatedJob()
                 || isTopStartedJobLocked(jobStatus)
                 || isUidInForeground(jobStatus.getSourceUid())) {
@@ -903,8 +912,9 @@
             return false;
         }
 
-        if (mService.isCurrentlyRunningLocked(jobStatus)) {
-            // if job is running, considered as in quota so it can keep running.
+        if (standbyBucket != RESTRICTED_INDEX && mService.isCurrentlyRunningLocked(jobStatus)) {
+            // Running job is considered as within quota except for the restricted one, which
+            // requires additional constraints.
             return true;
         }
 
@@ -1472,7 +1482,9 @@
                 stats.jobCountInRateLimitingWindow = 0;
             }
             stats.jobCountInRateLimitingWindow += count;
-            stats.bgJobCountInWindow += count;
+            if (Flags.countQuotaFix()) {
+                stats.bgJobCountInWindow += count;
+            }
         }
     }
 
@@ -1708,7 +1720,7 @@
                 }
             } else if (realStandbyBucket != EXEMPTED_INDEX && realStandbyBucket != ACTIVE_INDEX
                     && realStandbyBucket == js.getEffectiveStandbyBucket()
-                    && !mService.isCurrentlyRunningLocked(js)) {
+                    && !(Flags.countQuotaFix() && mService.isCurrentlyRunningLocked(js))) {
                 // An app in the ACTIVE bucket may be out of quota while the job could be in quota
                 // for some reason. Therefore, avoid setting the real value here and check each job
                 // individually. Running job need to determine its own quota status as well.
@@ -2150,10 +2162,12 @@
                 mBgJobCount++;
                 if (mRegularJobTimer) {
                     incrementJobCountLocked(mPkg.userId, mPkg.packageName, 1);
-                    final ExecutionStats stats = getExecutionStatsLocked(mPkg.userId,
-                            mPkg.packageName, jobStatus.getEffectiveStandbyBucket(), false);
-                    if (stats.bgJobCountInWindow >= stats.jobCountLimit) {
-                        mHandler.obtainMessage(MSG_REACHED_COUNT_QUOTA, mPkg).sendToTarget();
+                    if (Flags.countQuotaFix()) {
+                        final ExecutionStats stats = getExecutionStatsLocked(mPkg.userId,
+                                mPkg.packageName, jobStatus.getEffectiveStandbyBucket(), false);
+                        if (!isUnderJobCountQuotaLocked(stats)) {
+                            mHandler.obtainMessage(MSG_REACHED_COUNT_QUOTA, mPkg).sendToTarget();
+                        }
                     }
                 }
                 if (mRunningBgJobs.size() == 1) {
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 19bc716..410074e 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -130,6 +130,8 @@
 import com.android.server.LocalServices;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.usage.AppIdleHistory.AppUsageHistory;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.UsedByReflection;
 
 import libcore.util.EmptyArray;
 
@@ -588,6 +590,8 @@
         }
     }
 
+    // This constructor is reflectively invoked from framework code in AppStandbyInternal.
+    @UsedByReflection(kind = KeepItemKind.CLASS_AND_METHODS)
     public AppStandbyController(Context context) {
         this(new Injector(context, AppSchedulingModuleThread.get().getLooper()));
     }
@@ -1985,6 +1989,9 @@
                 mAdminProtectedPackages.put(userId, packageNames);
             }
         }
+        if (android.app.admin.flags.Flags.disallowUserControlBgUsageFix()) {
+            postCheckIdleStates(userId);
+        }
     }
 
     @Override
diff --git a/apex/jobscheduler/service/jni/Android.bp b/apex/jobscheduler/service/jni/Android.bp
index 34a1fa2..e8acff7 100644
--- a/apex/jobscheduler/service/jni/Android.bp
+++ b/apex/jobscheduler/service/jni/Android.bp
@@ -28,4 +28,8 @@
         "liblog",
         "libbase",
     ],
+    visibility: [
+        "//frameworks/base/apex:__subpackages__",
+        "//visibility:any_system_partition",
+    ],
 }
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index 1b1bc6b..f56a950 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -54,34 +54,34 @@
             baseline_file: ":non-updatable-lint-baseline.txt",
         },
     },
-    dists: [
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/public/api",
-            dest: "android-non-updatable.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/public/api",
-            dest: "android-non-updatable-removed.txt",
-        },
-    ],
     soong_config_variables: {
         release_hidden_api_exportable_stubs: {
             dists: [
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/public/api",
+                    dest: "android-non-updatable.txt",
                     tag: ".exportable.api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/public/api",
+                    dest: "android-non-updatable-removed.txt",
                     tag: ".exportable.removed-api.txt",
                 },
             ],
             conditions_default: {
                 dists: [
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/public/api",
+                        dest: "android-non-updatable.txt",
                         tag: ".api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/public/api",
+                        dest: "android-non-updatable-removed.txt",
                         tag: ".removed-api.txt",
                     },
                 ],
@@ -134,34 +134,34 @@
             baseline_file: ":non-updatable-system-lint-baseline.txt",
         },
     },
-    dists: [
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system/api",
-            dest: "android-non-updatable.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system/api",
-            dest: "android-non-updatable-removed.txt",
-        },
-    ],
     soong_config_variables: {
         release_hidden_api_exportable_stubs: {
             dists: [
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/system/api",
+                    dest: "android-non-updatable.txt",
                     tag: ".exportable.api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/system/api",
+                    dest: "android-non-updatable-removed.txt",
                     tag: ".exportable.removed-api.txt",
                 },
             ],
             conditions_default: {
                 dists: [
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/system/api",
+                        dest: "android-non-updatable.txt",
                         tag: ".api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/system/api",
+                        dest: "android-non-updatable-removed.txt",
                         tag: ".removed-api.txt",
                     },
                 ],
@@ -189,56 +189,58 @@
             baseline_file: ":non-updatable-test-lint-baseline.txt",
         },
     },
-    dists: [
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/test/api",
-            dest: "android.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/test/api",
-            dest: "removed.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/test/api",
-            dest: "android-non-updatable.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/test/api",
-            dest: "android-non-updatable-removed.txt",
-        },
-    ],
     soong_config_variables: {
         release_hidden_api_exportable_stubs: {
             dists: [
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/test/api",
+                    dest: "android.txt",
                     tag: ".exportable.api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/test/api",
+                    dest: "removed.txt",
                     tag: ".exportable.removed-api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/test/api",
+                    dest: "android-non-updatable.txt",
                     tag: ".exportable.api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/test/api",
+                    dest: "android-non-updatable-removed.txt",
                     tag: ".exportable.removed-api.txt",
                 },
             ],
             conditions_default: {
                 dists: [
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/test/api",
+                        dest: "android.txt",
                         tag: ".api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/test/api",
+                        dest: "removed.txt",
                         tag: ".removed-api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/test/api",
+                        dest: "android-non-updatable.txt",
                         tag: ".api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/test/api",
+                        dest: "android-non-updatable-removed.txt",
                         tag: ".removed-api.txt",
                     },
                 ],
@@ -271,34 +273,34 @@
             baseline_file: ":non-updatable-module-lib-lint-baseline.txt",
         },
     },
-    dists: [
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/module-lib/api",
-            dest: "android-non-updatable.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/module-lib/api",
-            dest: "android-non-updatable-removed.txt",
-        },
-    ],
     soong_config_variables: {
         release_hidden_api_exportable_stubs: {
             dists: [
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/module-lib/api",
+                    dest: "android-non-updatable.txt",
                     tag: ".exportable.api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/module-lib/api",
+                    dest: "android-non-updatable-removed.txt",
                     tag: ".exportable.removed-api.txt",
                 },
             ],
             conditions_default: {
                 dists: [
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/module-lib/api",
+                        dest: "android-non-updatable.txt",
                         tag: ".api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/module-lib/api",
+                        dest: "android-non-updatable-removed.txt",
                         tag: ".removed-api.txt",
                     },
                 ],
diff --git a/api/coverage/tools/Android.bp b/api/coverage/tools/Android.bp
index 3e16912..caaca99 100644
--- a/api/coverage/tools/Android.bp
+++ b/api/coverage/tools/Android.bp
@@ -30,3 +30,24 @@
         type: "full",
     },
 }
+
+java_test_host {
+    name: "extract-flagged-apis-test",
+    srcs: ["ExtractFlaggedApisTest.kt"],
+    libs: [
+        "extract_flagged_apis_proto",
+        "junit",
+        "libprotobuf-java-full",
+    ],
+    static_libs: [
+        "truth",
+        "truth-liteproto-extension",
+        "truth-proto-extension",
+    ],
+    data: [
+        ":extract-flagged-apis",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+}
diff --git a/api/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt
index d5adfd0..5efda98 100644
--- a/api/coverage/tools/ExtractFlaggedApis.kt
+++ b/api/coverage/tools/ExtractFlaggedApis.kt
@@ -17,6 +17,7 @@
 package android.platform.coverage
 
 import com.android.tools.metalava.model.ClassItem
+import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.MethodItem
 import com.android.tools.metalava.model.text.ApiFile
 import java.io.File
@@ -28,12 +29,10 @@
     val builder = FlagApiMap.newBuilder()
     for (pkg in cb.getPackages().packages) {
         val packageName = pkg.qualifiedName()
-        pkg.allClasses()
-            .filter { it.methods().size > 0 }
-            .forEach {
-                extractFlaggedApisFromClass(it, it.methods(), packageName, builder)
-                extractFlaggedApisFromClass(it, it.constructors(), packageName, builder)
-            }
+        pkg.allClasses().forEach {
+            extractFlaggedApisFromClass(it, it.methods(), packageName, builder)
+            extractFlaggedApisFromClass(it, it.constructors(), packageName, builder)
+        }
     }
     val flagApiMap = builder.build()
     FileWriter(args[1]).use { it.write(flagApiMap.toString()) }
@@ -45,20 +44,10 @@
     packageName: String,
     builder: FlagApiMap.Builder
 ) {
-    val classFlag =
-        classItem.modifiers
-            .findAnnotation("android.annotation.FlaggedApi")
-            ?.findAttribute("value")
-            ?.value
-            ?.value() as? String
+    if (methods.isEmpty()) return
+    val classFlag = getClassFlag(classItem)
     for (method in methods) {
-        val methodFlag =
-            method.modifiers
-                .findAnnotation("android.annotation.FlaggedApi")
-                ?.findAttribute("value")
-                ?.value
-                ?.value() as? String
-                ?: classFlag
+        val methodFlag = getFlagAnnotation(method) ?: classFlag
         val api =
             JavaMethod.newBuilder()
                 .setPackageName(packageName)
@@ -82,3 +71,23 @@
         builder.putFlagToApi(flag, apis)
     }
 }
+
+fun getClassFlag(classItem: ClassItem): String? {
+    var classFlag = getFlagAnnotation(classItem)
+    var cur = classItem
+    // If a class is not an inner class, use its @FlaggedApi annotation value.
+    // Otherwise, use the flag value of the closest outer class that is annotated by @FlaggedApi.
+    while (cur.isInnerClass() && classFlag == null) {
+        cur = cur.parent() as ClassItem
+        classFlag = getFlagAnnotation(cur)
+    }
+    return classFlag
+}
+
+fun getFlagAnnotation(item: Item): String? {
+    return item.modifiers
+        .findAnnotation("android.annotation.FlaggedApi")
+        ?.findAttribute("value")
+        ?.value
+        ?.value() as? String
+}
diff --git a/api/coverage/tools/ExtractFlaggedApisTest.kt b/api/coverage/tools/ExtractFlaggedApisTest.kt
new file mode 100644
index 0000000..427be36
--- /dev/null
+++ b/api/coverage/tools/ExtractFlaggedApisTest.kt
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.coverage
+
+import com.google.common.truth.extensions.proto.ProtoTruth.assertThat
+import com.google.protobuf.TextFormat
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.StandardOpenOption
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ExtractFlaggedApisTest {
+
+    companion object {
+        const val COMMAND = "java -jar extract-flagged-apis.jar %s %s"
+    }
+
+    private var apiTextFile: Path = Files.createTempFile("current", ".txt")
+    private var flagToApiMap: Path = Files.createTempFile("flag_api_map", ".textproto")
+
+    @Before
+    fun setup() {
+        apiTextFile = Files.createTempFile("current", ".txt")
+        flagToApiMap = Files.createTempFile("flag_api_map", ".textproto")
+    }
+
+    @After
+    fun cleanup() {
+        Files.deleteIfExists(apiTextFile)
+        Files.deleteIfExists(flagToApiMap)
+    }
+
+    @Test
+    fun extractFlaggedApis_onlyMethodFlag_useMethodFlag() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.net.ipsec.ike {
+              public final class IkeSession implements java.lang.AutoCloseable {
+                method @FlaggedApi("com.android.ipsec.flags.dumpsys_api") public void dump(@NonNull java.io.PrintWriter);
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api =
+            JavaMethod.newBuilder()
+                .setPackageName("android.net.ipsec.ike")
+                .setClassName("IkeSession")
+                .setMethodName("dump")
+        api.addParameters("java.io.PrintWriter")
+        addFlaggedApi(expected, api, "com.android.ipsec.flags.dumpsys_api")
+        assertThat(result).isEqualTo(expected.build())
+    }
+
+    @Test
+    fun extractFlaggedApis_onlyClassFlag_useClassFlag() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.net.ipsec.ike {
+              @FlaggedApi("com.android.ipsec.flags.dumpsys_api") public final class IkeSession implements java.lang.AutoCloseable {
+                method public void dump(@NonNull java.io.PrintWriter);
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api =
+            JavaMethod.newBuilder()
+                .setPackageName("android.net.ipsec.ike")
+                .setClassName("IkeSession")
+                .setMethodName("dump")
+        api.addParameters("java.io.PrintWriter")
+        addFlaggedApi(expected, api, "com.android.ipsec.flags.dumpsys_api")
+        assertThat(result).isEqualTo(expected.build())
+    }
+
+    @Test
+    fun extractFlaggedApis_flaggedConstructorsAreFlaggedApis() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.app.pinner {
+              @FlaggedApi("android.app.pinner_service_client_api") public class PinnerServiceClient {
+                ctor @FlaggedApi("android.app.pinner_service_client_api") public PinnerServiceClient();
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api =
+            JavaMethod.newBuilder()
+                .setPackageName("android.app.pinner")
+                .setClassName("PinnerServiceClient")
+                .setMethodName("PinnerServiceClient")
+        addFlaggedApi(expected, api, "android.app.pinner_service_client_api")
+        assertThat(result).isEqualTo(expected.build())
+    }
+
+    @Test
+    fun extractFlaggedApis_unflaggedNestedClassShouldUseOuterClassFlag() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.location.provider {
+              @FlaggedApi(Flags.FLAG_NEW_GEOCODER) public final class ForwardGeocodeRequest implements android.os.Parcelable {
+                method public int describeContents();
+              }
+              public static final class ForwardGeocodeRequest.Builder {
+                method @NonNull public android.location.provider.ForwardGeocodeRequest build();
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api1 =
+            JavaMethod.newBuilder()
+                .setPackageName("android.location.provider")
+                .setClassName("ForwardGeocodeRequest")
+                .setMethodName("describeContents")
+        addFlaggedApi(expected, api1, "Flags.FLAG_NEW_GEOCODER")
+        val api2 =
+            JavaMethod.newBuilder()
+                .setPackageName("android.location.provider")
+                .setClassName("ForwardGeocodeRequest.Builder")
+                .setMethodName("build")
+        addFlaggedApi(expected, api2, "Flags.FLAG_NEW_GEOCODER")
+        assertThat(result).ignoringRepeatedFieldOrder().isEqualTo(expected.build())
+    }
+
+    @Test
+    fun extractFlaggedApis_unflaggedNestedClassShouldUseOuterClassFlag_deeplyNested() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.package.xyz {
+              @FlaggedApi(outer_class_flag) public final class OuterClass {
+                method public int apiInOuterClass();
+              }
+              public final class OuterClass.Deeply.NestedClass {
+                method public void apiInNestedClass();
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api1 =
+            JavaMethod.newBuilder()
+                .setPackageName("android.package.xyz")
+                .setClassName("OuterClass")
+                .setMethodName("apiInOuterClass")
+        addFlaggedApi(expected, api1, "outer_class_flag")
+        val api2 =
+            JavaMethod.newBuilder()
+                .setPackageName("android.package.xyz")
+                .setClassName("OuterClass.Deeply.NestedClass")
+                .setMethodName("apiInNestedClass")
+        addFlaggedApi(expected, api2, "outer_class_flag")
+        assertThat(result).ignoringRepeatedFieldOrder().isEqualTo(expected.build())
+    }
+
+    private fun addFlaggedApi(builder: FlagApiMap.Builder, api: JavaMethod.Builder, flag: String) {
+        if (builder.containsFlagToApi(flag)) {
+            val updatedApis =
+                builder.getFlagToApiOrThrow(flag).toBuilder().addJavaMethods(api).build()
+            builder.putFlagToApi(flag, updatedApis)
+        } else {
+            val apis = FlaggedApis.newBuilder().addJavaMethods(api).build()
+            builder.putFlagToApi(flag, apis)
+        }
+    }
+
+    private fun createCommand(): Array<String> {
+        val command =
+            String.format(COMMAND, apiTextFile.toAbsolutePath(), flagToApiMap.toAbsolutePath())
+        return command.split(" ").toTypedArray()
+    }
+}
diff --git a/cmds/incident_helper/OWNERS b/cmds/incident_helper/OWNERS
index cede4ea..29f44ab 100644
--- a/cmds/incident_helper/OWNERS
+++ b/cmds/incident_helper/OWNERS
@@ -1,3 +1,2 @@
 [email protected]
[email protected]
 [email protected]
diff --git a/cmds/locksettings/TEST_MAPPING b/cmds/locksettings/TEST_MAPPING
index 7a449ef..af54a2d 100644
--- a/cmds/locksettings/TEST_MAPPING
+++ b/cmds/locksettings/TEST_MAPPING
@@ -11,5 +11,10 @@
                 }
             ]
         }
+    ],
+    "postsubmit": [
+        {
+            "name": "CtsDevicePolicyManagerTestCases_LockSettings_NoFlakes"
+        }
     ]
 }
diff --git a/cmds/uinput/README.md b/cmds/uinput/README.md
index f177586..5d3f12e 100644
--- a/cmds/uinput/README.md
+++ b/cmds/uinput/README.md
@@ -154,8 +154,24 @@
 
 #### `delay`
 
-Add a delay between the processing of commands. The delay will be timed from when the last delay
-ended, rather than from the current time, to allow for more precise timings to be produced.
+Add a delay between the processing of commands.
+
+The delay will be timed relative to the time base, a reference time which is set when the device is
+registered or by the `updateTimeBase` command. Take the following set of example commands:
+
+1. `register` device
+2. `delay` 500ms
+3. `inject` some events
+4. `delay` 10ms
+5. `inject` more events
+
+If the `register` command is executed at time _X_, the injection at step 3 will be scheduled for
+time _X_+500ms. Since scheduling isn't precise, they might actually be injected a few milliseconds
+later, but regardless of that the injection at step 5 will always be scheduled for _X_+510ms. This
+prevents scheduling delays from building up over time and slowing down the playback of recordings.
+However, it does mean that when you expect to wait for an indeterminate period of time, you should
+send `updateTimeBase` afterwards to prevent following events being scheduled in the past — see that
+command's section for an example.
 
 | Field         | Type          | Description                |
 |:-------------:|:-------------:|:-------------------------- |
@@ -173,6 +189,45 @@
 }
 ```
 
+#### `updateTimeBase`
+
+Update the time base from which the following events are scheduled to the current time. When
+controlling `uinput` over standard input, you should send this command if you want following events
+to be scheduled relative to now, rather than the last injection. See the following example set of
+commands and the times they will be scheduled to run at:
+
+1. `register` (say this occurs at time _X_)
+2. `delay` 500ms
+3. `inject`: scheduled for _X_+500ms
+4. `delay` 10ms
+5. `inject`: scheduled for _X_+510ms
+6. (wait a few seconds)
+7. `updateTimeBase` (say this occurs at time _Y_)
+8. `delay` 10ms
+9. `inject`: scheduled for _Y_+10ms
+
+Without the `updateTimeBase` command, the final injection would be scheduled for _X_+520ms, which
+would be in the past.
+
+This is useful if you are issuing commands in multiple stages with long or unknown delays in between
+them. For example, say you have a test that does the following:
+
+1. `register` a device
+2. `inject` a few events that should launch an app
+3. Wait for the app to launch (an indeterminate amount of time, possibly seconds)
+4. 1000 `inject` commands separated by `delay` commands of 10ms
+
+Without `updateTimeBase`, the `inject` commands of step 4 will be scheduled to start immediately
+after the events from step 2. That time is probably in the past, so many of the 1000 injections will
+be sent immediately. This will likely fill the kernel's event buffers, causing events to be dropped.
+Sending `updateTimeBase` before the `inject` commands in step 4 will schedule them relative to the
+current time, meaning that they will be all injected with the intended 10ms delays between them.
+
+| Field         | Type          | Description                     |
+|:-------------:|:-------------:|:------------------------------- |
+| `id`          | integer       | Device ID                       |
+| `command`     | string        | Must be set to "updateTimeBase" |
+
 #### `inject`
 
 Send an array of uinput event packets to the uinput device
diff --git a/cmds/uinput/src/com/android/commands/uinput/Device.java b/cmds/uinput/src/com/android/commands/uinput/Device.java
index b452fc7..2cac6313 100644
--- a/cmds/uinput/src/com/android/commands/uinput/Device.java
+++ b/cmds/uinput/src/com/android/commands/uinput/Device.java
@@ -102,7 +102,7 @@
         }
 
         mHandler.obtainMessage(MSG_OPEN_UINPUT_DEVICE, args).sendToTarget();
-        mTimeToSendNanos = SystemClock.uptimeNanos();
+        updateTimeBase();
     }
 
     private long getTimeToSendMillis() {
@@ -135,6 +135,13 @@
     }
 
     /**
+     * Set the reference time from which future injections are scheduled to the current time.
+     */
+    public void updateTimeBase() {
+        mTimeToSendNanos = SystemClock.uptimeNanos();
+    }
+
+    /**
      * Delay subsequent device activity by the specified amount of time.
      *
      * <p>Note that although the delay is specified in nanoseconds, due to limitations of {@link
@@ -216,7 +223,7 @@
                         break;
                     }
                     long offsetMicros = args.argl1;
-                    if (mLastInjectTimestampMicros == -1 || offsetMicros == -1) {
+                    if (mLastInjectTimestampMicros == -1) {
                         // There's often a delay of a few milliseconds between the time specified to
                         // Handler.sendMessageAtTime and the handler actually being called, due to
                         // the way threads are scheduled. We don't take this into account when
@@ -232,6 +239,9 @@
                         // To prevent this, we need to use the time at which we scheduled this first
                         // batch, rather than the actual current time.
                         mLastInjectTimestampMicros = args.argl2 / 1000;
+                    } else if (offsetMicros == -1) {
+                        // No timestamp offset is specified for this event, so use the current time.
+                        mLastInjectTimestampMicros = SystemClock.uptimeNanos() / 1000;
                     } else {
                         mLastInjectTimestampMicros += offsetMicros;
                     }
diff --git a/cmds/uinput/src/com/android/commands/uinput/Event.java b/cmds/uinput/src/com/android/commands/uinput/Event.java
index 9e7ee09..a3f3d1c 100644
--- a/cmds/uinput/src/com/android/commands/uinput/Event.java
+++ b/cmds/uinput/src/com/android/commands/uinput/Event.java
@@ -36,6 +36,7 @@
         DELAY,
         INJECT,
         SYNC,
+        UPDATE_TIME_BASE,
     }
 
     // Constants representing evdev event types, from include/uapi/linux/input-event-codes.h in the
diff --git a/cmds/uinput/src/com/android/commands/uinput/JsonStyleParser.java b/cmds/uinput/src/com/android/commands/uinput/JsonStyleParser.java
index 6994f0c..85a9e9b 100644
--- a/cmds/uinput/src/com/android/commands/uinput/JsonStyleParser.java
+++ b/cmds/uinput/src/com/android/commands/uinput/JsonStyleParser.java
@@ -25,6 +25,7 @@
 import java.io.Reader;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.function.Function;
 import java.util.stream.IntStream;
@@ -57,8 +58,7 @@
                     String name = mReader.nextName();
                     switch (name) {
                         case "id" -> eb.setId(readInt());
-                        case "command" -> eb.setCommand(
-                                Event.Command.valueOf(mReader.nextString().toUpperCase()));
+                        case "command" -> eb.setCommand(readCommand());
                         case "name" -> eb.setName(mReader.nextString());
                         case "vid" -> eb.setVendorId(readInt());
                         case "pid" -> eb.setProductId(readInt());
@@ -91,6 +91,18 @@
         return e;
     }
 
+    private Event.Command readCommand() throws IOException {
+        String commandStr = mReader.nextString();
+        return switch (commandStr.toLowerCase(Locale.ROOT)) {
+            case "register" -> Event.Command.REGISTER;
+            case "delay" -> Event.Command.DELAY;
+            case "inject" -> Event.Command.INJECT;
+            case "sync" -> Event.Command.SYNC;
+            case "updatetimebase" -> Event.Command.UPDATE_TIME_BASE;
+            default -> throw new IllegalStateException("Invalid command \"" + commandStr + "\"");
+        };
+    }
+
     private ArrayList<Integer> readInjectedEvents() throws IOException {
         ArrayList<Integer> data = new ArrayList<>();
         try {
diff --git a/cmds/uinput/src/com/android/commands/uinput/Uinput.java b/cmds/uinput/src/com/android/commands/uinput/Uinput.java
index 760e981..b9967fb 100644
--- a/cmds/uinput/src/com/android/commands/uinput/Uinput.java
+++ b/cmds/uinput/src/com/android/commands/uinput/Uinput.java
@@ -137,6 +137,7 @@
             case INJECT -> d.injectEvent(e.getInjections(), e.getTimestampOffsetMicros());
             case DELAY -> d.addDelayNanos(e.getDurationNanos());
             case SYNC -> d.syncEvent(e.getSyncToken());
+            case UPDATE_TIME_BASE -> d.updateTimeBase();
         }
     }
 
diff --git a/config/Android.bp b/config/Android.bp
index 6a6f848..dd681ca 100644
--- a/config/Android.bp
+++ b/config/Android.bp
@@ -33,3 +33,9 @@
     name: "preloaded-classes-denylist",
     srcs: ["preloaded-classes-denylist"],
 }
+
+prebuilt_etc {
+    name: "dirty-image-objects",
+    src: "dirty-image-objects",
+    filename: "dirty-image-objects",
+}
diff --git a/core/api/current.txt b/core/api/current.txt
index b19c3ab..7d9ce58 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -282,7 +282,7 @@
     field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE";
-    field @FlaggedApi("android.companion.flags.device_presence") public static final String REQUEST_OBSERVE_DEVICE_UUID_PRESENCE = "android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE";
+    field @FlaggedApi("android.companion.device_presence") public static final String REQUEST_OBSERVE_DEVICE_UUID_PRESENCE = "android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE";
     field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY";
     field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final String RUN_USER_INITIATED_JOBS = "android.permission.RUN_USER_INITIATED_JOBS";
@@ -511,7 +511,7 @@
     field public static final int autoSizeTextType = 16844085; // 0x1010535
     field public static final int autoStart = 16843445; // 0x10102b5
     field @Deprecated public static final int autoText = 16843114; // 0x101016a
-    field @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") public static final int autoTransact;
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int autoTransact;
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844118; // 0x1010556
@@ -1499,7 +1499,7 @@
     field public static final int shortcutId = 16844072; // 0x1010528
     field public static final int shortcutLongLabel = 16844074; // 0x101052a
     field public static final int shortcutShortLabel = 16844073; // 0x1010529
-    field @FlaggedApi("android.nfc.Flags.FLAG_OBSERVE_MODE") public static final int shouldDefaultToObserveMode;
+    field @FlaggedApi("android.nfc.nfc_observe_mode") public static final int shouldDefaultToObserveMode;
     field public static final int shouldDisableView = 16843246; // 0x10101ee
     field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c
     field public static final int showAsAction = 16843481; // 0x10102d9
@@ -9877,7 +9877,7 @@
     ctor public ObservingDevicePresenceRequest.Builder();
     method @NonNull public android.companion.ObservingDevicePresenceRequest build();
     method @NonNull public android.companion.ObservingDevicePresenceRequest.Builder setAssociationId(int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE) public android.companion.ObservingDevicePresenceRequest.Builder setUuid(@NonNull android.os.ParcelUuid);
+    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE, android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_SCAN}) public android.companion.ObservingDevicePresenceRequest.Builder setUuid(@NonNull android.os.ParcelUuid);
   }
 
   public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> {
@@ -32743,7 +32743,7 @@
     field public static final int S_V2 = 32; // 0x20
     field public static final int TIRAMISU = 33; // 0x21
     field public static final int UPSIDE_DOWN_CAKE = 34; // 0x22
-    field @FlaggedApi("android.os.android_os_build_vanilla_ice_cream") public static final int VANILLA_ICE_CREAM = 10000; // 0x2710
+    field public static final int VANILLA_ICE_CREAM = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -39388,10 +39388,8 @@
   }
 
   public final class FileIntegrityManager {
-    method @FlaggedApi("android.security.fsverity_api") @Nullable public byte[] getFsVerityDigest(@NonNull java.io.File) throws java.io.IOException;
     method public boolean isApkVeritySupported();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public boolean isAppSourceCertificateTrusted(@NonNull java.security.cert.X509Certificate) throws java.security.cert.CertificateEncodingException;
-    method @FlaggedApi("android.security.fsverity_api") public void setupFsVerity(@NonNull java.io.File) throws java.io.IOException;
   }
 
   public final class KeyChain {
@@ -54479,7 +54477,6 @@
     field @FlaggedApi("com.android.window.flags.cover_display_opt_in") public static final int COMPAT_SMALL_COVER_SCREEN_OPT_IN = 1; // 0x1
     field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
     field public static final String PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED = "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";
-    field @FlaggedApi("com.android.window.flags.untrusted_embedding_state_sharing") public static final String PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING = "android.window.PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING";
     field public static final String PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION";
     field public static final String PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH";
     field public static final String PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE = "android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index b767c52..e12da63 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12,7 +12,7 @@
     field public static final String ACCESS_DRM_CERTIFICATES = "android.permission.ACCESS_DRM_CERTIFICATES";
     field @Deprecated public static final String ACCESS_FM_RADIO = "android.permission.ACCESS_FM_RADIO";
     field public static final String ACCESS_FPS_COUNTER = "android.permission.ACCESS_FPS_COUNTER";
-    field @FlaggedApi("android.multiuser.flags.enable_permission_to_access_hidden_profiles") public static final String ACCESS_HIDDEN_PROFILES_FULL = "android.permission.ACCESS_HIDDEN_PROFILES_FULL";
+    field @FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles") public static final String ACCESS_HIDDEN_PROFILES_FULL = "android.permission.ACCESS_HIDDEN_PROFILES_FULL";
     field public static final String ACCESS_INSTANT_APPS = "android.permission.ACCESS_INSTANT_APPS";
     field @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") public static final String ACCESS_LAST_KNOWN_CELL_ID = "android.permission.ACCESS_LAST_KNOWN_CELL_ID";
     field public static final String ACCESS_LOCUS_ID_USAGE_STATS = "android.permission.ACCESS_LOCUS_ID_USAGE_STATS";
@@ -355,6 +355,7 @@
     field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
     field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
     field public static final String SERIAL_PORT = "android.permission.SERIAL_PORT";
+    field @FlaggedApi("android.security.fsverity_api") public static final String SETUP_FSVERITY = "android.permission.SETUP_FSVERITY";
     field public static final String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER";
     field public static final String SET_CLIP_SOURCE = "android.permission.SET_CLIP_SOURCE";
     field public static final String SET_DEFAULT_ACCOUNT_FOR_CONTACTS = "android.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS";
@@ -12106,6 +12107,11 @@
 
 package android.security {
 
+  public final class FileIntegrityManager {
+    method @FlaggedApi("android.security.fsverity_api") @Nullable public byte[] getFsVerityDigest(@NonNull java.io.File) throws java.io.IOException;
+    method @FlaggedApi("android.security.fsverity_api") public void setupFsVerity(@NonNull java.io.File) throws java.io.IOException;
+  }
+
   public final class KeyChain {
     method @Nullable @WorkerThread public static String getWifiKeyGrantAsUser(@NonNull android.content.Context, @NonNull android.os.UserHandle, @NonNull String);
     method @WorkerThread public static boolean hasWifiKeyGrantAsUser(@NonNull android.content.Context, @NonNull android.os.UserHandle, @NonNull String);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f36aeab..5a3ff83 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -157,7 +157,7 @@
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void setStopUserOnSwitch(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean startUserInBackgroundVisibleOnDisplay(int, int);
-    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean stopUser(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean stopUser(int);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle();
@@ -263,6 +263,7 @@
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setMode(int, int, String, int);
     method public static int strOpToOp(@NonNull String);
+    method public int unsafeCheckOpRawNoThrow(@NonNull String, @NonNull android.content.AttributionSource);
     field public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; // 0xffffffff
     field public static final int ATTRIBUTION_FLAGS_NONE = 0; // 0x0
     field public static final int ATTRIBUTION_FLAG_ACCESSOR = 1; // 0x1
@@ -589,6 +590,7 @@
     method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceNetworkLogs();
     method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void forceRemoveActiveAdmin(@NonNull android.content.ComponentName, int);
     method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceSecurityLogs();
+    method @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_internal_bug_fix_enabled") @RequiresPermission("android.permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT") public void forceSetMaxPolicyStorageLimit(int);
     method public void forceUpdateUserSetupComplete(int);
     method @NonNull public java.util.Set<java.lang.String> getDefaultCrossProfilePackages();
     method @Deprecated public int getDeviceOwnerType(@NonNull android.content.ComponentName);
@@ -599,6 +601,7 @@
     method public long getLastSecurityLogRetrievalTime();
     method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public java.util.Set<java.lang.String> getPolicyExemptApps();
+    method @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_internal_bug_fix_enabled") @RequiresPermission("android.permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT") public int getPolicySizeForAdmin(@NonNull android.app.admin.EnforcingAdmin);
     method public boolean isCurrentInputMethodSetByOwner();
     method public boolean isFactoryResetProtectionPolicySupported();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean isNewUserDisclaimerAcknowledged();
@@ -667,6 +670,10 @@
     field @NonNull public static final android.app.admin.DpcAuthority DPC_AUTHORITY;
   }
 
+  public final class EnforcingAdmin implements android.os.Parcelable {
+    ctor @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_internal_bug_fix_enabled") public EnforcingAdmin(@NonNull String, @NonNull android.app.admin.Authority, @NonNull android.os.UserHandle, @Nullable android.content.ComponentName);
+  }
+
   public final class FlagUnion extends android.app.admin.ResolutionMechanism<java.lang.Integer> {
     method public int describeContents();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -1765,19 +1772,22 @@
   public final class InputManager {
     method public void addUniqueIdAssociation(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void clearAllModifierKeyRemappings();
-    method @Nullable public String getCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier);
-    method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull android.view.InputDevice);
+    method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptors();
     method @NonNull public String getKeyboardLayoutTypeForLayoutDescriptor(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public java.util.Map<java.lang.Integer,java.lang.Integer> getModifierKeyRemapping();
     method public int getMousePointerSpeed();
     method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void remapModifierKey(int, int);
-    method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void removeKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
     method public void removeUniqueIdAssociation(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void setCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
     field public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; // 0x96aec7eL
   }
 
   public class InputSettings {
+    method @FlaggedApi("com.android.hardware.input.keyboard_a11y_bounce_keys_flag") public static int getAccessibilityBounceKeysThreshold(@NonNull android.content.Context);
+    method @FlaggedApi("com.android.hardware.input.keyboard_a11y_slow_keys_flag") public static int getAccessibilitySlowKeysThreshold(@NonNull android.content.Context);
+    method @FlaggedApi("com.android.hardware.input.keyboard_a11y_sticky_keys_flag") public static boolean isAccessibilityStickyKeysEnabled(@NonNull android.content.Context);
+    method @FlaggedApi("com.android.hardware.input.keyboard_a11y_bounce_keys_flag") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityBounceKeysThreshold(@NonNull android.content.Context, int);
+    method @FlaggedApi("com.android.hardware.input.keyboard_a11y_slow_keys_flag") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilitySlowKeysThreshold(@NonNull android.content.Context, int);
+    method @FlaggedApi("com.android.hardware.input.keyboard_a11y_sticky_keys_flag") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityStickyKeysEnabled(@NonNull android.content.Context, boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void setMaximumObscuringOpacityForTouch(@NonNull android.content.Context, @FloatRange(from=0, to=1) float);
     field public static final int DEFAULT_POINTER_SPEED = 0; // 0x0
   }
@@ -4126,7 +4136,6 @@
     method @NonNull public static String typeToString(int);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.window.BackNavigationInfo> CREATOR;
-    field public static final String KEY_TRIGGER_BACK = "TriggerBack";
     field public static final int TYPE_CALLBACK = 4; // 0x4
     field public static final int TYPE_CROSS_ACTIVITY = 2; // 0x2
     field public static final int TYPE_CROSS_TASK = 3; // 0x3
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7725561..5e9fdfb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1349,12 +1349,26 @@
     public static final int RESTRICTION_LEVEL_BACKGROUND_RESTRICTED = 50;
 
     /**
-     * The most restricted level where the apps are considered "in-hibernation",
-     * its package visibility to the rest of the system is limited.
+     * The restricted level where the apps are in a force-stopped state.
      *
      * @hide
      */
-    public static final int RESTRICTION_LEVEL_HIBERNATION = 60;
+    public static final int RESTRICTION_LEVEL_FORCE_STOPPED = 60;
+
+    /**
+     * The heavily background restricted level, where apps cannot start without an explicit
+     * launch by the user.
+     *
+     * @hide
+     */
+    public static final int RESTRICTION_LEVEL_USER_LAUNCH_ONLY = 70;
+
+    /**
+     * A reserved restriction level that is not well-defined.
+     *
+     * @hide
+     */
+    public static final int RESTRICTION_LEVEL_CUSTOM = 90;
 
     /**
      * Not a valid restriction level, it defines the maximum numerical value of restriction level.
@@ -1371,12 +1385,116 @@
             RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
             RESTRICTION_LEVEL_RESTRICTED_BUCKET,
             RESTRICTION_LEVEL_BACKGROUND_RESTRICTED,
-            RESTRICTION_LEVEL_HIBERNATION,
+            RESTRICTION_LEVEL_FORCE_STOPPED,
+            RESTRICTION_LEVEL_USER_LAUNCH_ONLY,
+            RESTRICTION_LEVEL_CUSTOM,
             RESTRICTION_LEVEL_MAX,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface RestrictionLevel{}
 
+    /**
+     * Maximum string length for sub reason for restriction.
+     *
+     * @hide
+     */
+    public static final int RESTRICTION_SUBREASON_MAX_LENGTH = 16;
+
+    /**
+     * Restriction reason unknown - do not use directly.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_UNKNOWN = 0;
+
+    /**
+     * Restriction reason to be used when this is normal behavior for the state.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_DEFAULT = 1;
+
+    /**
+     * Restriction reason is some kind of timeout that moves the app to a more restricted state.
+     * The threshold should specify how long the app was dormant, in milliseconds.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_DORMANT = 2;
+
+    /**
+     * Restriction reason to be used when removing a restriction due to direct or indirect usage
+     * of the app, especially to undo any automatic restrictions.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_USAGE = 3;
+
+    /**
+     * Restriction reason to be used when the user chooses to manually restrict the app, through
+     * UI or command line interface.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_USER = 4;
+
+    /**
+     * Restriction reason to be used when the user chooses to manually restrict the app on being
+     * prompted by the OS or some anomaly detection algorithm. For example, if the app is causing
+     * high battery drain or affecting system performance and the OS recommends that the user
+     * restrict the app.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_USER_NUDGED = 5;
+
+    /**
+     * Restriction reason to be used when the OS automatically detects that the app is causing
+     * system health issues such as performance degradation, battery drain, high memory usage, etc.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_SYSTEM_HEALTH = 6;
+
+    /**
+     * Restriction reason to be used when there is a server-side decision made to restrict an app
+     * that is showing widespread problems on user devices, or violating policy in some way.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_REMOTE_TRIGGER = 7;
+
+    /**
+     * Restriction reason to be used when some other problem requires restricting the app.
+     *
+     * For use with noteAppRestrictionEnabled()
+     * @hide
+     */
+    public static final int RESTRICTION_REASON_OTHER = 8;
+
+    /** @hide */
+    @IntDef(prefix = { "RESTRICTION_REASON_" }, value = {
+            RESTRICTION_REASON_UNKNOWN,
+            RESTRICTION_REASON_DEFAULT,
+            RESTRICTION_REASON_DORMANT,
+            RESTRICTION_REASON_USAGE,
+            RESTRICTION_REASON_USER,
+            RESTRICTION_REASON_USER_NUDGED,
+            RESTRICTION_REASON_SYSTEM_HEALTH,
+            RESTRICTION_REASON_REMOTE_TRIGGER,
+            RESTRICTION_REASON_OTHER
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RestrictionReason{}
+
     /** @hide */
     @android.ravenwood.annotation.RavenwoodKeep
     public static String restrictionLevelToName(@RestrictionLevel int level) {
@@ -1393,12 +1511,16 @@
                 return "restricted_bucket";
             case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
                 return "background_restricted";
-            case RESTRICTION_LEVEL_HIBERNATION:
-                return "hibernation";
+            case RESTRICTION_LEVEL_FORCE_STOPPED:
+                return "stopped";
+            case RESTRICTION_LEVEL_USER_LAUNCH_ONLY:
+                return "user_only";
+            case RESTRICTION_LEVEL_CUSTOM:
+                return "custom";
             case RESTRICTION_LEVEL_MAX:
                 return "max";
             default:
-                return "";
+                return String.valueOf(level);
         }
     }
 
@@ -5071,7 +5193,7 @@
      * <p><b>NOTE:</b> differently from {@link #switchUser(int)}, which stops the current foreground
      * user before starting a new one, this method does not stop the previous user running in
      * background in the display, and it will return {@code false} in this case. It's up to the
-     * caller to call {@link #stopUser(int, boolean)} before starting a new user.
+     * caller to call {@link #stopUser(int)} before starting a new user.
      *
      * @param userId user to be started in the display. It will return {@code false} if the user is
      * a profile, the {@link #getCurrentUser()}, the {@link UserHandle#SYSTEM system user}, or
@@ -5281,15 +5403,16 @@
      *
      * @hide
      */
+    @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
     @TestApi
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
-    public boolean stopUser(@UserIdInt int userId, boolean force) {
+    public boolean stopUser(@UserIdInt int userId) {
         if (userId == UserHandle.USER_SYSTEM) {
             return false;
         }
         try {
-            return USER_OP_SUCCESS == getService().stopUser(
-                    userId, force, /* callback= */ null);
+            return USER_OP_SUCCESS == getService().stopUserWithCallback(
+                    userId, /* callback= */ null);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -6126,6 +6249,43 @@
     }
 
     /**
+     * Requests the system to log the reason for restricting/unrestricting an app. This API
+     * should be called before applying any change to the restriction level.
+     * <p>
+     * The {@code enabled} value determines whether the state is being applied or removed.
+     * Not all restrictions are actual restrictions. For example,
+     * {@link #RESTRICTION_LEVEL_ADAPTIVE} is a normal state, where there is default lifecycle
+     * management applied to the app. Also, {@link #RESTRICTION_LEVEL_EXEMPTED} is used when the
+     * app is being put in a power-save allowlist.
+     *
+     * @param packageName the package name of the app
+     * @param uid the uid of the app
+     * @param restrictionLevel the restriction level specified in {@code RestrictionLevel}
+     * @param enabled whether the state is being applied or removed
+     * @param reason the reason for the restriction state change, from {@code RestrictionReason}
+     * @param subReason a string sub reason limited to 16 characters that specifies additional
+     *                  information about the reason for restriction.
+     * @param threshold for reasons that are due to exceeding some threshold, the threshold value
+     *                  must be specified. The unit of the threshold depends on the reason and/or
+     *                  subReason. For time, use milliseconds. For memory, use KB. For count, use
+     *                  the actual count or normalized as per-hour. For power, use milliwatts. Etc.
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.DEVICE_POWER)
+    public void noteAppRestrictionEnabled(@NonNull String packageName, int uid,
+            @RestrictionLevel int restrictionLevel, boolean enabled,
+            @RestrictionReason int reason,
+            @Nullable String subReason, long threshold) {
+        try {
+            getService().noteAppRestrictionEnabled(packageName, uid, restrictionLevel, enabled,
+                    reason, subReason, threshold);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Notifies {@link #getRunningAppProcesses app processes} that the system properties
      * have changed.
      *
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index e094ac6..9ea55f5 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -2205,19 +2205,6 @@
     }
 
     /**
-     * Sets background activity launch logic won't use pending intent creator foreground state.
-     *
-     * @hide
-     * @deprecated use {@link #setPendingIntentCreatorBackgroundActivityStartMode(int)} instead
-     */
-    @Deprecated
-    public ActivityOptions setIgnorePendingIntentCreatorForegroundState(boolean ignore) {
-        mPendingIntentCreatorBackgroundActivityStartMode = ignore
-                ? MODE_BACKGROUND_ACTIVITY_START_DENIED : MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
-        return this;
-    }
-
-    /**
      * Allow a {@link PendingIntent} to use the privilege of its creator to start background
      * activities.
      *
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e53bd39..bc66127 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1000,6 +1000,7 @@
         boolean autoStopProfiler;
         boolean streamingOutput;
         int mClockType;
+        int mProfilerOutputVersion;
         boolean profiling;
         boolean handlingProfiling;
         public void setProfiler(ProfilerInfo profilerInfo) {
@@ -1027,6 +1028,7 @@
             autoStopProfiler = profilerInfo.autoStopProfiler;
             streamingOutput = profilerInfo.streamingOutput;
             mClockType = profilerInfo.clockType;
+            mProfilerOutputVersion = profilerInfo.profilerOutputVersion;
         }
         public void startProfiling() {
             if (profileFd == null || profiling) {
@@ -1034,9 +1036,11 @@
             }
             try {
                 int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
+                int flags = 0;
+                flags = mClockType | ProfilerInfo.getFlagsForOutputVersion(mProfilerOutputVersion);
                 VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
-                        bufferSize * 1024 * 1024, mClockType, samplingInterval != 0,
-                        samplingInterval, streamingOutput);
+                        bufferSize * 1024 * 1024, flags, samplingInterval != 0, samplingInterval,
+                        streamingOutput);
                 profiling = true;
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Profiling failed on path " + profileFile, e);
@@ -1082,6 +1086,8 @@
         public boolean managed;
         public boolean mallocInfo;
         public boolean runGc;
+        // compression format to dump bitmaps, null if no bitmaps to be dumped
+        public String dumpBitmaps;
         String path;
         ParcelFileDescriptor fd;
         RemoteCallback finishCallback;
@@ -1486,11 +1492,12 @@
         }
 
         @Override
-        public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
-                ParcelFileDescriptor fd, RemoteCallback finishCallback) {
+        public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String dumpBitmaps,
+                String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
             DumpHeapData dhd = new DumpHeapData();
             dhd.managed = managed;
             dhd.mallocInfo = mallocInfo;
+            dhd.dumpBitmaps = dumpBitmaps;
             dhd.runGc = runGc;
             dhd.path = path;
             try {
@@ -2605,7 +2612,14 @@
                     break;
                 case EXECUTE_TRANSACTION:
                     final ClientTransaction transaction = (ClientTransaction) msg.obj;
-                    mTransactionExecutor.execute(transaction);
+                    final ClientTransactionListenerController controller =
+                            ClientTransactionListenerController.getInstance();
+                    controller.onClientTransactionStarted();
+                    try {
+                        mTransactionExecutor.execute(transaction);
+                    } finally {
+                        controller.onClientTransactionFinished();
+                    }
                     if (isSystem()) {
                         // Client transactions inside system process are recycled on the client side
                         // instead of ClientLifecycleManager to avoid being cleared before this
@@ -3717,12 +3731,6 @@
         return mActivities.get(token);
     }
 
-    @Nullable
-    @Override
-    public Context getWindowContext(@NonNull IBinder clientToken) {
-        return WindowTokenClientController.getInstance().getWindowContext(clientToken);
-    }
-
     @VisibleForTesting(visibility = PACKAGE)
     public Configuration getConfiguration() {
         return mConfigurationController.getConfiguration();
@@ -6744,6 +6752,21 @@
     void handleActivityConfigurationChanged(@NonNull ActivityClientRecord r,
             @NonNull Configuration overrideConfig, int displayId,
             @NonNull ActivityWindowInfo activityWindowInfo, boolean alwaysReportChange) {
+        final ClientTransactionListenerController controller =
+                ClientTransactionListenerController.getInstance();
+        final Context contextToUpdate = r.activity;
+        controller.onContextConfigurationPreChanged(contextToUpdate);
+        try {
+            handleActivityConfigurationChangedInner(r, overrideConfig, displayId,
+                    activityWindowInfo, alwaysReportChange);
+        } finally {
+            controller.onContextConfigurationPostChanged(contextToUpdate);
+        }
+    }
+
+    private void handleActivityConfigurationChangedInner(@NonNull ActivityClientRecord r,
+            @NonNull Configuration overrideConfig, int displayId,
+            @NonNull ActivityWindowInfo activityWindowInfo, boolean alwaysReportChange) {
         synchronized (mPendingOverrideConfigs) {
             final Configuration pendingOverrideConfig = mPendingOverrideConfigs.get(r.token);
             if (overrideConfig.isOtherSeqNewer(pendingOverrideConfig)) {
@@ -6859,6 +6882,9 @@
             System.runFinalization();
             System.gc();
         }
+        if (dhd.dumpBitmaps != null) {
+            Bitmap.dumpAll(dhd.dumpBitmaps);
+        }
         try (ParcelFileDescriptor fd = dhd.fd) {
             if (dhd.managed) {
                 Debug.dumpHprofData(dhd.path, fd.getFileDescriptor());
@@ -6886,6 +6912,9 @@
         if (dhd.finishCallback != null) {
             dhd.finishCallback.sendResult(null);
         }
+        if (dhd.dumpBitmaps != null) {
+            Bitmap.dumpAll(null); // clear dump
+        }
     }
 
     final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
@@ -7179,6 +7208,7 @@
             mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
             mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
             mProfiler.mClockType = data.initProfilerInfo.clockType;
+            mProfiler.mProfilerOutputVersion = data.initProfilerInfo.profilerOutputVersion;
             if (data.initProfilerInfo.attachAgentDuringBind) {
                 agent = data.initProfilerInfo.agent;
             }
diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java
index 0bae5e6..7724c23 100644
--- a/core/java/android/app/AppCompatTaskInfo.java
+++ b/core/java/android/app/AppCompatTaskInfo.java
@@ -16,60 +16,16 @@
 
 package android.app;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * Stores App Compat information about a particular Task.
  * @hide
  */
 public class AppCompatTaskInfo implements Parcelable {
-
-    /**
-     * Camera compat control isn't shown because it's not requested by heuristics.
-     */
-    public static final int CAMERA_COMPAT_CONTROL_HIDDEN = 0;
-
-    /**
-     * Camera compat control is shown with the treatment suggested.
-     */
-    public static final int CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED = 1;
-
-    /**
-     * Camera compat control is shown to allow reverting the applied treatment.
-     */
-    public static final int CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED = 2;
-
-    /**
-     * Camera compat control is dismissed by user.
-     */
-    public static final int CAMERA_COMPAT_CONTROL_DISMISSED = 3;
-
-    /**
-     * Enum for the Camera app compat control states.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "CAMERA_COMPAT_CONTROL_" }, value = {
-            CAMERA_COMPAT_CONTROL_HIDDEN,
-            CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED,
-            CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED,
-            CAMERA_COMPAT_CONTROL_DISMISSED,
-    })
-    public @interface CameraCompatControlState {};
-
-    /**
-     * State of the Camera app compat control which is used to correct stretched viewfinder
-     * in apps that don't handle all possible configurations and changes between them correctly.
-     */
-    @CameraCompatControlState
-    public int cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
-
     /**
      * Whether the direct top activity is eligible for letterbox education.
      */
@@ -135,6 +91,11 @@
      */
     public int topActivityLetterboxHeight;
 
+    /**
+     * Stores camera-related app compat information about a particular Task.
+     */
+    public CameraCompatTaskInfo cameraCompatTaskInfo = CameraCompatTaskInfo.create();
+
     private AppCompatTaskInfo() {
         // Do nothing
     }
@@ -167,18 +128,10 @@
             };
 
     /**
-     * @return {@value true} if the task has camera compat controls.
-     */
-    public boolean hasCameraCompatControl() {
-        return cameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN
-                && cameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED;
-    }
-
-    /**
      * @return {@value true} if the task has some compat ui.
      */
     public boolean hasCompatUI() {
-        return hasCameraCompatControl() || topActivityInSizeCompat
+        return cameraCompatTaskInfo.hasCameraCompatUI() || topActivityInSizeCompat
                 || topActivityEligibleForLetterboxEducation
                 || isLetterboxDoubleTapEnabled
                 || topActivityEligibleForUserAspectRatioButton;
@@ -208,7 +161,8 @@
                 && topActivityLetterboxHorizontalPosition
                     == that.topActivityLetterboxHorizontalPosition
                 && isUserFullscreenOverrideEnabled == that.isUserFullscreenOverrideEnabled
-                && isSystemFullscreenOverrideEnabled == that.isSystemFullscreenOverrideEnabled;
+                && isSystemFullscreenOverrideEnabled == that.isSystemFullscreenOverrideEnabled
+                && cameraCompatTaskInfo.equalsForTaskOrganizer(that.cameraCompatTaskInfo);
     }
 
     /**
@@ -229,18 +183,17 @@
                     == that.topActivityLetterboxHorizontalPosition
                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
-                && cameraCompatControlState == that.cameraCompatControlState
                 && isUserFullscreenOverrideEnabled == that.isUserFullscreenOverrideEnabled
-                && isSystemFullscreenOverrideEnabled == that.isSystemFullscreenOverrideEnabled;
+                && isSystemFullscreenOverrideEnabled == that.isSystemFullscreenOverrideEnabled
+                && cameraCompatTaskInfo.equalsForCompatUi(that.cameraCompatTaskInfo);
     }
 
     /**
-     * Reads the TaskInfo from a parcel.
+     * Reads the AppCompatTaskInfo from a parcel.
      */
     void readFromParcel(Parcel source) {
         topActivityInSizeCompat = source.readBoolean();
         topActivityEligibleForLetterboxEducation = source.readBoolean();
-        cameraCompatControlState = source.readInt();
         isLetterboxDoubleTapEnabled = source.readBoolean();
         topActivityEligibleForUserAspectRatioButton = source.readBoolean();
         topActivityBoundsLetterboxed = source.readBoolean();
@@ -251,16 +204,16 @@
         topActivityLetterboxHeight = source.readInt();
         isUserFullscreenOverrideEnabled = source.readBoolean();
         isSystemFullscreenOverrideEnabled = source.readBoolean();
+        cameraCompatTaskInfo = source.readTypedObject(CameraCompatTaskInfo.CREATOR);
     }
 
     /**
-     * Writes the TaskInfo to a parcel.
+     * Writes the AppCompatTaskInfo to a parcel.
      */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeBoolean(topActivityInSizeCompat);
         dest.writeBoolean(topActivityEligibleForLetterboxEducation);
-        dest.writeInt(cameraCompatControlState);
         dest.writeBoolean(isLetterboxDoubleTapEnabled);
         dest.writeBoolean(topActivityEligibleForUserAspectRatioButton);
         dest.writeBoolean(topActivityBoundsLetterboxed);
@@ -271,6 +224,7 @@
         dest.writeInt(topActivityLetterboxHeight);
         dest.writeBoolean(isUserFullscreenOverrideEnabled);
         dest.writeBoolean(isSystemFullscreenOverrideEnabled);
+        dest.writeTypedObject(cameraCompatTaskInfo, flags);
     }
 
     @Override
@@ -290,23 +244,7 @@
                 + " topActivityLetterboxHeight=" + topActivityLetterboxHeight
                 + " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled
                 + " isSystemFullscreenOverrideEnabled=" + isSystemFullscreenOverrideEnabled
-                + " cameraCompatControlState="
-                + cameraCompatControlStateToString(cameraCompatControlState)
+                + " cameraCompatTaskInfo=" + cameraCompatTaskInfo.toString()
                 + "}";
     }
-
-    /** Human readable version of the camera control state. */
-    @NonNull
-    public static String cameraCompatControlStateToString(
-            @CameraCompatControlState int cameraCompatControlState) {
-        switch (cameraCompatControlState) {
-            case CAMERA_COMPAT_CONTROL_HIDDEN: return "hidden";
-            case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED: return "treatment-suggested";
-            case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED: return "treatment-applied";
-            case CAMERA_COMPAT_CONTROL_DISMISSED: return "dismissed";
-            default:
-                throw new AssertionError(
-                        "Unexpected camera compat control state: " + cameraCompatControlState);
-        }
-    }
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7ae514a..b3312a8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1554,11 +1554,11 @@
             AppProtoEnums.APP_OP_READ_SYSTEM_GRAMMATICAL_GENDER;
 
     /**
-     * Allows an app with a major use case of backing-up or syncing content to run longer jobs.
+     * This app has been removed..
      *
      * @hide
      */
-    public static final int OP_RUN_BACKUP_JOBS = AppProtoEnums.APP_OP_RUN_BACKUP_JOBS;
+    private static final int OP_DEPRECATED_4 = AppProtoEnums.APP_OP_RUN_BACKUP_JOBS;
 
     /**
      * Whether the app has enabled to receive the icon overlay for fetching archived apps.
@@ -1738,7 +1738,6 @@
             OPSTR_ENABLE_MOBILE_DATA_BY_USER,
             OPSTR_RESERVED_FOR_TESTING,
             OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,
-            OPSTR_RUN_BACKUP_JOBS,
             OPSTR_ARCHIVE_ICON_OVERLAY,
             OPSTR_UNARCHIVAL_CONFIRMATION,
             OPSTR_EMERGENCY_LOCATION,
@@ -2447,11 +2446,11 @@
             "android:read_system_grammatical_gender";
 
     /**
-     * Allows an app whose primary use case is to backup or sync content to run longer jobs.
+     * App op has been removed.
      *
      * @hide
      */
-    public static final String OPSTR_RUN_BACKUP_JOBS = "android:run_backup_jobs";
+    public static final String OPSTR_DEPRECATED_4 = "android:deprecated_4";
 
     /**
      * Allows an app to access location without the traditional location permissions and while the
@@ -2578,7 +2577,6 @@
             OP_RECEIVE_SANDBOX_TRIGGER_AUDIO,
             OP_MEDIA_ROUTING_CONTROL,
             OP_READ_SYSTEM_GRAMMATICAL_GENDER,
-            OP_RUN_BACKUP_JOBS,
             OP_ARCHIVE_ICON_OVERLAY,
             OP_UNARCHIVAL_CONFIRMATION,
     };
@@ -3036,8 +3034,8 @@
                 // will make it an app-op permission in the future.
                 // .setPermission(Manifest.permission.READ_SYSTEM_GRAMMATICAL_GENDER)
                 .build(),
-        new AppOpInfo.Builder(OP_RUN_BACKUP_JOBS, OPSTR_RUN_BACKUP_JOBS, "RUN_BACKUP_JOBS")
-                .setPermission(Manifest.permission.RUN_BACKUP_JOBS).build(),
+        new AppOpInfo.Builder(OP_DEPRECATED_4, OPSTR_DEPRECATED_4, "DEPRECATED_4")
+                .setDefaultMode(AppOpsManager.MODE_IGNORED).build(),
         new AppOpInfo.Builder(OP_ARCHIVE_ICON_OVERLAY, OPSTR_ARCHIVE_ICON_OVERLAY,
                 "ARCHIVE_ICON_OVERLAY")
                 .setDefaultMode(MODE_ALLOWED).build(),
@@ -8790,6 +8788,18 @@
      * Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
      * @hide
      */
+    @TestApi
+    @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
+    public int unsafeCheckOpRawNoThrow(
+            @NonNull String op, @NonNull AttributionSource attributionSource) {
+        return unsafeCheckOpRawNoThrow(strOpToOp(op), attributionSource);
+    }
+
+    /**
+     * Returns the <em>raw</em> mode associated with the op.
+     * Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
+     * @hide
+     */
     public int unsafeCheckOpRawNoThrow(int op, int uid, @NonNull String packageName) {
         return unsafeCheckOpRawNoThrow(op, uid, packageName, Context.DEVICE_ID_DEFAULT);
     }
@@ -8800,8 +8810,8 @@
             if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
                 return mService.checkOperationRaw(op, uid, packageName, null);
             } else {
-                return mService.checkOperationRawForDevice(op, uid, packageName, null,
-                        Context.DEVICE_ID_DEFAULT);
+                return mService.checkOperationRawForDevice(
+                        op, uid, packageName, null, virtualDeviceId);
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 308178c..76d6547 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -671,7 +671,7 @@
         private String mName;
         private ComponentName mOwner;
         private Uri mConditionId;
-        private int mInterruptionFilter;
+        private int mInterruptionFilter = NotificationManager.INTERRUPTION_FILTER_PRIORITY;
         private boolean mEnabled = true;
         private ComponentName mConfigurationActivity = null;
         private ZenPolicy mPolicy = null;
diff --git a/core/java/android/app/CameraCompatTaskInfo.java b/core/java/android/app/CameraCompatTaskInfo.java
new file mode 100644
index 0000000..1e116b7
--- /dev/null
+++ b/core/java/android/app/CameraCompatTaskInfo.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Stores Camera Compat information about a particular Task.
+ * @hide
+ */
+public class CameraCompatTaskInfo implements Parcelable {
+    /**
+     * Camera compat control isn't shown because it's not requested by heuristics.
+     */
+    public static final int CAMERA_COMPAT_CONTROL_HIDDEN = 0;
+
+    /**
+     * Camera compat control is shown with the treatment suggested.
+     */
+    public static final int CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED = 1;
+
+    /**
+     * Camera compat control is shown to allow reverting the applied treatment.
+     */
+    public static final int CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED = 2;
+
+    /**
+     * Camera compat control is dismissed by user.
+     */
+    public static final int CAMERA_COMPAT_CONTROL_DISMISSED = 3;
+
+    /**
+     * Enum for the Camera app compat control states.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "CAMERA_COMPAT_CONTROL_" }, value = {
+            CAMERA_COMPAT_CONTROL_HIDDEN,
+            CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED,
+            CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED,
+            CAMERA_COMPAT_CONTROL_DISMISSED,
+    })
+    public @interface CameraCompatControlState {}
+
+    /**
+     * State of the Camera app compat control which is used to correct stretched viewfinder
+     * in apps that don't handle all possible configurations and changes between them correctly.
+     */
+    @CameraCompatControlState
+    public int cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
+
+    /**
+     * The value to use when no camera compat treatment should be applied to a windowed task.
+     */
+    public static final int CAMERA_COMPAT_FREEFORM_NONE = 0;
+
+    /**
+     * The value to use when portrait camera compat treatment should be applied to a windowed task.
+     */
+    public static final int CAMERA_COMPAT_FREEFORM_PORTRAIT = 1;
+
+    /**
+     * The value to use when landscape camera compat treatment should be applied to a windowed task.
+     */
+    public static final int CAMERA_COMPAT_FREEFORM_LANDSCAPE = 2;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "CAMERA_COMPAT_FREEFORM_" }, value = {
+            CAMERA_COMPAT_FREEFORM_NONE,
+            CAMERA_COMPAT_FREEFORM_PORTRAIT,
+            CAMERA_COMPAT_FREEFORM_LANDSCAPE,
+    })
+    public @interface FreeformCameraCompatMode {}
+
+    /**
+     * Whether the camera activity is letterboxed in freeform windowing mode to emulate expected
+     * aspect ratio for fixed-orientation apps.
+     *
+     * <p>This field is used by the WM and the camera framework, to coordinate camera compat mode
+     * setup.
+     */
+    @FreeformCameraCompatMode
+    public int freeformCameraCompatMode;
+
+    private CameraCompatTaskInfo() {
+        // Do nothing
+    }
+
+    @NonNull
+    static CameraCompatTaskInfo create() {
+        return new CameraCompatTaskInfo();
+    }
+
+    private CameraCompatTaskInfo(Parcel source) {
+        readFromParcel(source);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<CameraCompatTaskInfo> CREATOR =
+            new Creator<>() {
+                @Override
+                public CameraCompatTaskInfo createFromParcel(Parcel in) {
+                    return new CameraCompatTaskInfo(in);
+                }
+
+                @Override
+                public CameraCompatTaskInfo[] newArray(int size) {
+                    return new CameraCompatTaskInfo[size];
+                }
+            };
+
+    /**
+     * Reads the CameraCompatTaskInfo from a parcel.
+     */
+    void readFromParcel(Parcel source) {
+        cameraCompatControlState = source.readInt();
+        freeformCameraCompatMode = source.readInt();
+    }
+
+    /**
+     * Writes the CameraCompatTaskInfo to a parcel.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(cameraCompatControlState);
+        dest.writeInt(freeformCameraCompatMode);
+    }
+
+    /**
+     * @return {@value true} if the task has camera compat controls.
+     */
+    public boolean hasCameraCompatControl() {
+        return cameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN
+                && cameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED;
+    }
+
+    /**
+     * @return {@value true} if the task has some compat ui.
+     */
+    public boolean hasCameraCompatUI() {
+        return hasCameraCompatControl();
+    }
+
+    /**
+     * @return  {@code true} if the camera compat parameters that are important for task organizers
+     * are equal.
+     */
+    public boolean equalsForTaskOrganizer(@Nullable CameraCompatTaskInfo that) {
+        if (that == null) {
+            return false;
+        }
+        return freeformCameraCompatMode == that.freeformCameraCompatMode;
+    }
+
+    /**
+     * @return {@code true} if parameters that are important for size compat have changed.
+     */
+    public boolean equalsForCompatUi(@Nullable CameraCompatTaskInfo that) {
+        if (that == null) {
+            return false;
+        }
+        return cameraCompatControlState == that.cameraCompatControlState
+                && freeformCameraCompatMode == that.freeformCameraCompatMode;
+    }
+
+    @Override
+    public String toString() {
+        return "CameraCompatTaskInfo { cameraCompatControlState="
+                + cameraCompatControlStateToString(cameraCompatControlState)
+                + " freeformCameraCompatMode="
+                + freeformCameraCompatModeToString(freeformCameraCompatMode)
+                + "}";
+    }
+
+    /** Human readable version of the camera control state. */
+    @NonNull
+    public static String cameraCompatControlStateToString(
+            @CameraCompatControlState int cameraCompatControlState) {
+        return switch (cameraCompatControlState) {
+            case CAMERA_COMPAT_CONTROL_HIDDEN -> "hidden";
+            case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED -> "treatment-suggested";
+            case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED -> "treatment-applied";
+            case CAMERA_COMPAT_CONTROL_DISMISSED -> "dismissed";
+            default -> throw new AssertionError(
+                    "Unexpected camera compat control state: " + cameraCompatControlState);
+        };
+    }
+
+    /** Human readable version of the freeform camera compat mode. */
+    @NonNull
+    public static String freeformCameraCompatModeToString(
+            @FreeformCameraCompatMode int freeformCameraCompatMode) {
+        return switch (freeformCameraCompatMode) {
+            case CAMERA_COMPAT_FREEFORM_NONE -> "inactive";
+            case CAMERA_COMPAT_FREEFORM_PORTRAIT -> "portrait";
+            case CAMERA_COMPAT_FREEFORM_LANDSCAPE -> "landscape";
+            default -> throw new AssertionError(
+                    "Unexpected camera compat mode: " + freeformCameraCompatMode);
+        };
+    }
+}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 01153c9..f0c3196 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -23,7 +23,6 @@
 import android.app.servertransaction.DestroyActivityItem;
 import android.app.servertransaction.PendingTransactionActions;
 import android.app.servertransaction.TransactionExecutor;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
@@ -32,7 +31,6 @@
 import android.view.SurfaceControl;
 import android.window.ActivityWindowInfo;
 import android.window.SplashScreenView.SplashScreenViewParcelable;
-import android.window.WindowContext;
 import android.window.WindowContextInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -90,10 +88,6 @@
     /** Get activity instance for the token. */
     public abstract Activity getActivity(IBinder token);
 
-    /** Gets the {@link WindowContext} instance for the token. */
-    @Nullable
-    public abstract Context getWindowContext(@NonNull IBinder clientToken);
-
     // Prepare phase related logic and handlers. Methods that inform about about pending changes or
     // do other internal bookkeeping.
 
diff --git a/core/java/android/app/ConfigurationController.java b/core/java/android/app/ConfigurationController.java
index 18dc1ce1..62a50db 100644
--- a/core/java/android/app/ConfigurationController.java
+++ b/core/java/android/app/ConfigurationController.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.servertransaction.ClientTransactionListenerController;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
@@ -145,6 +146,24 @@
      */
     void handleConfigurationChanged(@Nullable Configuration config,
             @Nullable CompatibilityInfo compat) {
+        final ClientTransactionListenerController controller =
+                ClientTransactionListenerController.getInstance();
+        final Context contextToUpdate = ActivityThread.currentApplication();
+        controller.onContextConfigurationPreChanged(contextToUpdate);
+        try {
+            handleConfigurationChangedInner(config, compat);
+        } finally {
+            controller.onContextConfigurationPostChanged(contextToUpdate);
+        }
+    }
+
+    /**
+     * Update the configuration to latest.
+     * @param config The new configuration.
+     * @param compat The new compatibility information.
+     */
+    private void handleConfigurationChangedInner(@Nullable Configuration config,
+            @Nullable CompatibilityInfo compat) {
         int configDiff;
         boolean equivalent;
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ee0225f..e3380e0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -21,12 +21,14 @@
 import static android.os.StrictMode.vmIncorrectContextUseEnabled;
 import static android.view.WindowManager.LayoutParams.WindowType;
 
+import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.UiContext;
+import android.companion.virtual.VirtualDevice;
 import android.companion.virtual.VirtualDeviceManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.AttributionSource;
@@ -2288,7 +2290,35 @@
             Log.v(TAG, "Treating renounced permission " + permission + " as denied");
             return PERMISSION_DENIED;
         }
-        return PermissionManager.checkPermission(permission, pid, uid, getDeviceId());
+
+        // When checking a device-aware permission on a remote device, if the permission is CAMERA
+        // or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
+        // device doesn't have capability fall back to checking permission on the default device.
+        // Note: we only perform permission check redirection when the device id is not explicitly
+        // set in the context.
+        int deviceId = getDeviceId();
+        if (deviceId != Context.DEVICE_ID_DEFAULT
+                && !mIsExplicitDeviceId
+                && PermissionManager.DEVICE_AWARE_PERMISSIONS.contains(permission)) {
+            VirtualDeviceManager virtualDeviceManager =
+                    getSystemService(VirtualDeviceManager.class);
+            VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
+            if (virtualDevice != null) {
+                if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
+                                && !virtualDevice.hasCustomAudioInputSupport())
+                        || (Objects.equals(permission, Manifest.permission.CAMERA)
+                                && !virtualDevice.hasCustomCameraSupport())) {
+                    deviceId = Context.DEVICE_ID_DEFAULT;
+                }
+            } else {
+                Slog.e(
+                        TAG,
+                        "virtualDevice is not found when device id is not default. deviceId = "
+                                + deviceId);
+            }
+        }
+
+        return PermissionManager.checkPermission(permission, pid, uid, deviceId);
     }
 
     /** @hide */
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 85611e8..3765c81 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -394,7 +394,7 @@
     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,
-            boolean runGc, in String path, in ParcelFileDescriptor fd,
+            boolean runGc, in String dumpBitmaps, in String path, in ParcelFileDescriptor fd,
             in RemoteCallback finishCallback);
     @UnsupportedAppUsage
     boolean isUserRunning(int userid, int flags);
@@ -452,12 +452,14 @@
             in IBinder resultTo, in String resultWho, int requestCode, int flags,
             in ProfilerInfo profilerInfo, in Bundle options, int userId);
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    int stopUser(int userid, boolean force, in IStopUserCallback callback);
+    int stopUser(int userid, boolean stopProfileRegardlessOfParent, in IStopUserCallback callback);
+    int stopUserWithCallback(int userid, in IStopUserCallback callback);
+    int stopUserExceptCertainProfiles(int userid, boolean stopProfileRegardlessOfParent, in IStopUserCallback callback);
     /**
-     * Check {@link com.android.server.am.ActivityManagerService#stopUserWithDelayedLocking(int, boolean, IStopUserCallback)}
+     * Check {@link com.android.server.am.ActivityManagerService#stopUserWithDelayedLocking(int, IStopUserCallback)}
      * for details.
      */
-    int stopUserWithDelayedLocking(int userid, boolean force, in IStopUserCallback callback);
+    int stopUserWithDelayedLocking(int userid, in IStopUserCallback callback);
 
     @UnsupportedAppUsage
     void registerUserSwitchObserver(in IUserSwitchObserver observer, in String name);
@@ -499,6 +501,7 @@
             in String shareDescription);
 
     void requestInteractiveBugReport();
+    void requestBugReportWithExtraAttachment(in Uri extraAttachment);
     void requestFullBugReport();
     void requestRemoteBugReport(long nonce);
     boolean launchBugReportHandlerApp();
@@ -1006,4 +1009,12 @@
      * @param originatingUid The UID of the instrumented app that initialized the override
      */
     void clearAllOverridePermissionStates(int originatingUid);
+
+    /**
+     * Request the system to log the reason for restricting / unrestricting an app.
+     * @see ActivityManager#noteAppRestrictionEnabled
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.DEVICE_POWER)")
+    void noteAppRestrictionEnabled(in String packageName, int uid, int restrictionType,
+            boolean enabled, int reason, in String subReason, long threshold);
 }
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 251e4e8..a64261a 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -119,7 +119,8 @@
     void scheduleSuicide();
     void dispatchPackageBroadcast(int cmd, in String[] packages);
     void scheduleCrash(in String msg, int typeId, in Bundle extras);
-    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
+    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc,
+            in String dumpBitmaps, in String path,
             in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
     void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
             in String[] args);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 8f81ae2..cf06416 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -50,8 +50,8 @@
     void cancelAllNotifications(String pkg, int userId);
 
     void clearData(String pkg, int uid, boolean fromApp);
-    void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration, boolean isUiContext, int displayId, @nullable ITransientNotificationCallback callback);
-    void enqueueToast(String pkg, IBinder token, ITransientNotification callback, int duration, boolean isUiContext, int displayId);
+    boolean enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration, boolean isUiContext, int displayId, @nullable ITransientNotificationCallback callback);
+    boolean enqueueToast(String pkg, IBinder token, ITransientNotification callback, int duration, boolean isUiContext, int displayId);
     void cancelToast(String pkg, IBinder token);
     void finishToken(String pkg, IBinder token);
 
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fe261be..714454b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,14 +17,14 @@
 package android.app;
 
 import static android.annotation.Dimension.DP;
+import static android.app.Flags.evenlyDividedCallStyleActionLayout;
+import static android.app.Flags.updateRankingTime;
 import static android.app.admin.DevicePolicyResources.Drawables.Source.NOTIFICATION;
 import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
 import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
 import static android.app.admin.DevicePolicyResources.UNDEFINED;
 import static android.graphics.drawable.Icon.TYPE_URI;
 import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP;
-import static android.app.Flags.evenlyDividedCallStyleActionLayout;
-import static android.app.Flags.updateRankingTime;
 
 import static java.util.Objects.requireNonNull;
 
@@ -93,7 +93,10 @@
 import android.text.style.CharacterStyle;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.RelativeSizeSpan;
+import android.text.style.StrikethroughSpan;
+import android.text.style.StyleSpan;
 import android.text.style.TextAppearanceSpan;
+import android.text.style.UnderlineSpan;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
@@ -765,11 +768,24 @@
             MessagingStyle.class, CallStyle.class);
 
     /** @hide */
-    @IntDef(flag = true, prefix = { "FLAG_" }, value = {FLAG_SHOW_LIGHTS, FLAG_ONGOING_EVENT,
-            FLAG_INSISTENT, FLAG_ONLY_ALERT_ONCE,
-            FLAG_AUTO_CANCEL, FLAG_NO_CLEAR, FLAG_FOREGROUND_SERVICE, FLAG_HIGH_PRIORITY,
-            FLAG_LOCAL_ONLY, FLAG_GROUP_SUMMARY, FLAG_AUTOGROUP_SUMMARY, FLAG_BUBBLE,
-            FLAG_USER_INITIATED_JOB})
+    @IntDef(flag = true, prefix = {"FLAG_"}, value = {
+            FLAG_SHOW_LIGHTS,
+            FLAG_ONGOING_EVENT,
+            FLAG_INSISTENT,
+            FLAG_ONLY_ALERT_ONCE,
+            FLAG_AUTO_CANCEL,
+            FLAG_NO_CLEAR,
+            FLAG_FOREGROUND_SERVICE,
+            FLAG_HIGH_PRIORITY,
+            FLAG_LOCAL_ONLY,
+            FLAG_GROUP_SUMMARY,
+            FLAG_AUTOGROUP_SUMMARY,
+            FLAG_CAN_COLORIZE,
+            FLAG_BUBBLE,
+            FLAG_NO_DISMISS,
+            FLAG_FSI_REQUESTED_BUT_DENIED,
+            FLAG_USER_INITIATED_JOB
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface NotificationFlags{};
 
@@ -2582,6 +2598,7 @@
         this.when = System.currentTimeMillis();
         if (updateRankingTime()) {
             creationTime = when;
+            extras.putBoolean(EXTRA_SHOW_WHEN, true);
         } else {
             this.creationTime = System.currentTimeMillis();
         }
@@ -2597,6 +2614,7 @@
     {
         if (updateRankingTime()) {
             creationTime = when;
+            extras.putBoolean(EXTRA_SHOW_WHEN, true);
         }
         new Builder(context)
                 .setWhen(when)
@@ -2629,6 +2647,7 @@
         this.when = when;
         if (updateRankingTime()) {
             creationTime = when;
+            extras.putBoolean(EXTRA_SHOW_WHEN, true);
         } else {
             this.creationTime = System.currentTimeMillis();
         }
@@ -2654,8 +2673,16 @@
         if (mAllowlistToken == null) {
             mAllowlistToken = processAllowlistToken;
         }
-        // Propagate this token to all pending intents that are unmarshalled from the parcel.
-        parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
+        if (Flags.secureAllowlistToken()) {
+            // Propagate this token to all pending intents that are unmarshalled from the parcel,
+            // or keep the one we're already propagating, if that's the case.
+            if (!parcel.hasClassCookie(PendingIntent.class)) {
+                parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
+            }
+        } else {
+            // Propagate this token to all pending intents that are unmarshalled from the parcel.
+            parcel.setClassCookie(PendingIntent.class, mAllowlistToken);
+        }
 
         when = parcel.readLong();
         creationTime = parcel.readLong();
@@ -3078,6 +3105,25 @@
     }
 
     /**
+     * @hide
+     */
+    public int loadHeaderAppIconRes(Context context) {
+        ApplicationInfo info = null;
+        if (extras.containsKey(EXTRA_BUILDER_APPLICATION_INFO)) {
+            info = extras.getParcelable(
+                    EXTRA_BUILDER_APPLICATION_INFO,
+                    ApplicationInfo.class);
+        }
+        if (info == null) {
+            info = context.getApplicationInfo();
+        }
+        if (info != null) {
+            return info.icon;
+        }
+        return 0;
+    }
+
+    /**
      * Removes heavyweight parts of the Notification object for archival or for sending to
      * listeners when the full contents are not necessary.
      * @hide
@@ -3124,9 +3170,26 @@
                     + " instance is a custom Parcelable and not allowed in Notification");
             return cs.toString();
         }
+
         return removeTextSizeSpans(cs);
     }
 
+    private static CharSequence stripStyling(@Nullable CharSequence cs) {
+        if (cs == null) {
+            return cs;
+        }
+
+        return cs.toString();
+    }
+
+    private static CharSequence cleanUpNewLines(@Nullable CharSequence charSequence) {
+        if (charSequence == null) {
+            return charSequence;
+        }
+
+        return charSequence.toString().replaceAll("[\r\n]+", "\n");
+    }
+
     private static CharSequence removeTextSizeSpans(CharSequence charSequence) {
         if (charSequence instanceof Spanned) {
             Spanned ss = (Spanned) charSequence;
@@ -3189,9 +3252,29 @@
             PendingIntent.addOnMarshaledListener(addedListener);
         }
         try {
-            // IMPORTANT: Add marshaling code in writeToParcelImpl as we
-            // want to intercept all pending events written to the parcel.
-            writeToParcelImpl(parcel, flags);
+            if (Flags.secureAllowlistToken()) {
+                boolean mustClearCookie = false;
+                if (!parcel.hasClassCookie(Notification.class)) {
+                    // This is the "root" notification, and not an "inner" notification (including
+                    // publicVersion or anything else that might be embedded in extras).
+                    parcel.setClassCookie(Notification.class, this);
+                    mustClearCookie = true;
+                }
+                try {
+                    // IMPORTANT: Add marshaling code in writeToParcelImpl as we
+                    // want to intercept all pending events written to the parcel.
+                    writeToParcelImpl(parcel, flags);
+                } finally {
+                    if (mustClearCookie) {
+                        parcel.removeClassCookie(Notification.class, this);
+                    }
+                }
+            } else {
+                // IMPORTANT: Add marshaling code in writeToParcelImpl as we
+                // want to intercept all pending events written to the parcel.
+                writeToParcelImpl(parcel, flags);
+            }
+
             synchronized (this) {
                 // Must be written last!
                 parcel.writeArraySet(allPendingIntents);
@@ -3206,7 +3289,19 @@
     private void writeToParcelImpl(Parcel parcel, int flags) {
         parcel.writeInt(1);
 
-        parcel.writeStrongBinder(mAllowlistToken);
+        if (Flags.secureAllowlistToken()) {
+            Notification rootNotification = (Notification) parcel.getClassCookie(
+                    Notification.class);
+            if (rootNotification != null && rootNotification != this) {
+                // Always use the same token as the root notification
+                parcel.writeStrongBinder(rootNotification.mAllowlistToken);
+            } else {
+                parcel.writeStrongBinder(mAllowlistToken);
+            }
+        } else {
+            parcel.writeStrongBinder(mAllowlistToken);
+        }
+
         parcel.writeLong(when);
         parcel.writeLong(creationTime);
         if (mSmallIcon == null && icon != 0) {
@@ -3599,18 +3694,23 @@
      * Sets the token used for background operations for the pending intents associated with this
      * notification.
      *
-     * This token is automatically set during deserialization for you, you usually won't need to
-     * call this unless you want to change the existing token, if any.
+     * Note: Should <em>only</em> be invoked by NotificationManagerService, since this is normally
+     * populated by unparceling (and also used there). Any other usage is suspect.
      *
      * @hide
      */
-    public void clearAllowlistToken() {
-        mAllowlistToken = null;
+    public void overrideAllowlistToken(IBinder token) {
+        mAllowlistToken = token;
         if (publicVersion != null) {
-            publicVersion.clearAllowlistToken();
+            publicVersion.overrideAllowlistToken(token);
         }
     }
 
+    /** @hide */
+    public IBinder getAllowlistToken() {
+        return mAllowlistToken;
+    }
+
     /**
      * @hide
      */
@@ -3692,10 +3792,10 @@
         if (this.tickerText != null) {
             sb.append(" tick");
         }
-        sb.append(" defaults=0x");
-        sb.append(Integer.toHexString(this.defaults));
-        sb.append(" flags=0x");
-        sb.append(Integer.toHexString(this.flags));
+        sb.append(" defaults=");
+        sb.append(defaultsToString(this.defaults));
+        sb.append(" flags=");
+        sb.append(flagsToString(this.flags));
         sb.append(String.format(" color=0x%08x", this.color));
         if (this.category != null) {
             sb.append(" category=");
@@ -3764,6 +3864,124 @@
     }
 
     /**
+     * {@hide}
+     */
+    public static String flagsToString(@NotificationFlags int flags) {
+        final List<String> flagStrings = new ArrayList<String>();
+        if ((flags & FLAG_SHOW_LIGHTS) != 0) {
+            flagStrings.add("SHOW_LIGHTS");
+            flags &= ~FLAG_SHOW_LIGHTS;
+        }
+        if ((flags & FLAG_ONGOING_EVENT) != 0) {
+            flagStrings.add("ONGOING_EVENT");
+            flags &= ~FLAG_ONGOING_EVENT;
+        }
+        if ((flags & FLAG_INSISTENT) != 0) {
+            flagStrings.add("INSISTENT");
+            flags &= ~FLAG_INSISTENT;
+        }
+        if ((flags & FLAG_ONLY_ALERT_ONCE) != 0) {
+            flagStrings.add("ONLY_ALERT_ONCE");
+            flags &= ~FLAG_ONLY_ALERT_ONCE;
+        }
+        if ((flags & FLAG_AUTO_CANCEL) != 0) {
+            flagStrings.add("AUTO_CANCEL");
+            flags &= ~FLAG_AUTO_CANCEL;
+        }
+        if ((flags & FLAG_NO_CLEAR) != 0) {
+            flagStrings.add("NO_CLEAR");
+            flags &= ~FLAG_NO_CLEAR;
+        }
+        if ((flags & FLAG_FOREGROUND_SERVICE) != 0) {
+            flagStrings.add("FOREGROUND_SERVICE");
+            flags &= ~FLAG_FOREGROUND_SERVICE;
+        }
+        if ((flags & FLAG_HIGH_PRIORITY) != 0) {
+            flagStrings.add("HIGH_PRIORITY");
+            flags &= ~FLAG_HIGH_PRIORITY;
+        }
+        if ((flags & FLAG_LOCAL_ONLY) != 0) {
+            flagStrings.add("LOCAL_ONLY");
+            flags &= ~FLAG_LOCAL_ONLY;
+        }
+        if ((flags & FLAG_GROUP_SUMMARY) != 0) {
+            flagStrings.add("GROUP_SUMMARY");
+            flags &= ~FLAG_GROUP_SUMMARY;
+        }
+        if ((flags & FLAG_AUTOGROUP_SUMMARY) != 0) {
+            flagStrings.add("AUTOGROUP_SUMMARY");
+            flags &= ~FLAG_AUTOGROUP_SUMMARY;
+        }
+        if ((flags & FLAG_CAN_COLORIZE) != 0) {
+            flagStrings.add("CAN_COLORIZE");
+            flags &= ~FLAG_CAN_COLORIZE;
+        }
+        if ((flags & FLAG_BUBBLE) != 0) {
+            flagStrings.add("BUBBLE");
+            flags &= ~FLAG_BUBBLE;
+        }
+        if ((flags & FLAG_NO_DISMISS) != 0) {
+            flagStrings.add("NO_DISMISS");
+            flags &= ~FLAG_NO_DISMISS;
+        }
+        if ((flags & FLAG_FSI_REQUESTED_BUT_DENIED) != 0) {
+            flagStrings.add("FSI_REQUESTED_BUT_DENIED");
+            flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED;
+        }
+        if ((flags & FLAG_USER_INITIATED_JOB) != 0) {
+            flagStrings.add("USER_INITIATED_JOB");
+            flags &= ~FLAG_USER_INITIATED_JOB;
+        }
+        if (Flags.lifetimeExtensionRefactor()) {
+            if ((flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) != 0) {
+                flagStrings.add("LIFETIME_EXTENDED_BY_DIRECT_REPLY");
+                flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
+            }
+        }
+
+        if (flagStrings.isEmpty()) {
+            return "0";
+        }
+
+        if (flags != 0) {
+            flagStrings.add(String.format("UNKNOWN(0x%08x)", flags));
+        }
+
+        return String.join("|", flagStrings);
+    }
+
+    /** @hide */
+    public static String defaultsToString(int defaults) {
+        final List<String> defaultStrings = new ArrayList<String>();
+        if ((defaults & DEFAULT_ALL) == DEFAULT_ALL) {
+            defaultStrings.add("ALL");
+            defaults &= ~DEFAULT_ALL;
+        }
+        if ((defaults & DEFAULT_SOUND) != 0) {
+            defaultStrings.add("SOUND");
+            defaults &= ~DEFAULT_SOUND;
+        }
+        if ((defaults & DEFAULT_VIBRATE) != 0) {
+            defaultStrings.add("VIBRATE");
+            defaults &= ~DEFAULT_VIBRATE;
+        }
+        if ((defaults & DEFAULT_LIGHTS) != 0) {
+            defaultStrings.add("LIGHTS");
+            defaults &= ~DEFAULT_LIGHTS;
+        }
+
+        if (defaultStrings.isEmpty()) {
+            return "0";
+        }
+
+        if (defaults != 0) {
+            defaultStrings.add(String.format("UNKNOWN(0x%08x)", defaults));
+        }
+
+        return String.join("|", defaultStrings);
+    }
+
+    /**
      * @hide
      */
     public boolean hasCompletedProgress() {
@@ -4316,14 +4534,16 @@
         /**
          * Add a timestamp pertaining to the notification (usually the time the event occurred).
          *
-         * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not
-         * shown anymore by default and must be opted into by using
-         * {@link android.app.Notification.Builder#setShowWhen(boolean)}
-         *
          * @see Notification#when
          */
         @NonNull
         public Builder setWhen(long when) {
+            if (updateRankingTime()) {
+                // don't show a timestamp that's decades old
+                if (mN.extras.getBoolean(EXTRA_SHOW_WHEN, true) && when == 0) {
+                    return this;
+                }
+            }
             mN.when = when;
             return this;
         }
@@ -4331,8 +4551,6 @@
         /**
          * Control whether the timestamp set with {@link #setWhen(long) setWhen} is shown
          * in the content view.
-         * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this defaults to
-         * {@code false}. For earlier apps, the default is {@code true}.
          */
         @NonNull
         public Builder setShowWhen(boolean show) {
@@ -5505,7 +5723,8 @@
             boolean hasSecondLine = showProgress;
             if (p.hasTitle()) {
                 contentView.setViewVisibility(p.mTitleViewId, View.VISIBLE);
-                contentView.setTextViewText(p.mTitleViewId, ensureColorSpanContrast(p.mTitle, p));
+                contentView.setTextViewText(p.mTitleViewId,
+                        ensureColorSpanContrastOrStripStyling(p.mTitle, p));
                 setTextViewColorPrimary(contentView, p.mTitleViewId, p);
             } else if (p.mTitleViewId != R.id.title) {
                 // This alternate title view ID is not cleared by resetStandardTemplate
@@ -5515,7 +5734,8 @@
             if (p.mText != null && p.mText.length() != 0
                     && (!showProgress || p.mAllowTextWithProgress)) {
                 contentView.setViewVisibility(p.mTextViewId, View.VISIBLE);
-                contentView.setTextViewText(p.mTextViewId, ensureColorSpanContrast(p.mText, p));
+                contentView.setTextViewText(p.mTextViewId,
+                        ensureColorSpanContrastOrStripStyling(p.mText, p));
                 setTextViewColorSecondary(contentView, p.mTextViewId, p);
                 hasSecondLine = true;
             } else if (p.mTextViewId != R.id.text) {
@@ -5804,7 +6024,7 @@
                 headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
             }
             if (!TextUtils.isEmpty(headerText)) {
-                contentView.setTextViewText(R.id.header_text, ensureColorSpanContrast(
+                contentView.setTextViewText(R.id.header_text, ensureColorSpanContrastOrStripStyling(
                         processLegacyText(headerText), p));
                 setTextViewColorSecondary(contentView, R.id.header_text, p);
                 contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
@@ -5826,8 +6046,9 @@
                 return false;
             }
             if (!TextUtils.isEmpty(p.mHeaderTextSecondary)) {
-                contentView.setTextViewText(R.id.header_text_secondary, ensureColorSpanContrast(
-                        processLegacyText(p.mHeaderTextSecondary), p));
+                contentView.setTextViewText(R.id.header_text_secondary,
+                        ensureColorSpanContrastOrStripStyling(
+                                processLegacyText(p.mHeaderTextSecondary), p));
                 setTextViewColorSecondary(contentView, R.id.header_text_secondary, p);
                 contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
                 if (hasTextToLeft) {
@@ -5891,12 +6112,21 @@
         }
 
         private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) {
-            if (mN.mSmallIcon == null && mN.icon != 0) {
+            if (Flags.notificationsUseAppIcon()) {
+                // Override small icon with app icon
+                mN.mSmallIcon = Icon.createWithResource(mContext,
+                        mN.loadHeaderAppIconRes(mContext));
+            } else if (mN.mSmallIcon == null && mN.icon != 0) {
                 mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
             }
+
             contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
             contentView.setInt(R.id.icon, "setImageLevel", mN.iconLevel);
-            processSmallIconColor(mN.mSmallIcon, contentView, p);
+
+            // Don't change color if we're using the app icon.
+            if (!Flags.notificationsUseAppIcon()) {
+                processSmallIconColor(mN.mSmallIcon, contentView, p);
+            }
         }
 
         /**
@@ -6048,7 +6278,7 @@
                 big.setViewVisibility(R.id.notification_material_reply_text_1_container,
                         View.VISIBLE);
                 big.setTextViewText(R.id.notification_material_reply_text_1,
-                        ensureColorSpanContrast(replyText[0].getText(), p));
+                        ensureColorSpanContrastOrStripStyling(replyText[0].getText(), p));
                 setTextViewColorSecondary(big, R.id.notification_material_reply_text_1, p);
                 big.setViewVisibility(R.id.notification_material_reply_progress,
                         showSpinner ? View.VISIBLE : View.GONE);
@@ -6060,7 +6290,7 @@
                         && p.maxRemoteInputHistory > 1) {
                     big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE);
                     big.setTextViewText(R.id.notification_material_reply_text_2,
-                            ensureColorSpanContrast(replyText[1].getText(), p));
+                            ensureColorSpanContrastOrStripStyling(replyText[1].getText(), p));
                     setTextViewColorSecondary(big, R.id.notification_material_reply_text_2, p);
 
                     if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2].getText())
@@ -6068,7 +6298,7 @@
                         big.setViewVisibility(
                                 R.id.notification_material_reply_text_3, View.VISIBLE);
                         big.setTextViewText(R.id.notification_material_reply_text_3,
-                                ensureColorSpanContrast(replyText[2].getText(), p));
+                                ensureColorSpanContrastOrStripStyling(replyText[2].getText(), p));
                         setTextViewColorSecondary(big, R.id.notification_material_reply_text_3, p);
                     }
                 }
@@ -6500,21 +6730,37 @@
                                     mContext, getColors(p).getBackgroundColor(), mInNightMode),
                             R.dimen.notification_action_disabled_container_alpha);
                 }
-                if (isLegacy()) {
-                    title = ContrastColorUtil.clearColorSpans(title);
-                } else {
-                    // Check for a full-length span color to use as the button fill color.
-                    Integer fullLengthColor = getFullLengthSpanColor(title);
-                    if (fullLengthColor != null) {
-                        // Ensure the custom button fill has 1.3:1 contrast w/ notification bg.
-                        int notifBackgroundColor = getColors(p).getBackgroundColor();
-                        buttonFillColor = ensureButtonFillContrast(
-                                fullLengthColor, notifBackgroundColor);
+                if (Flags.cleanUpSpansAndNewLines()) {
+                    if (!isLegacy()) {
+                        // Check for a full-length span color to use as the button fill color.
+                        Integer fullLengthColor = getFullLengthSpanColor(title);
+                        if (fullLengthColor != null) {
+                            // Ensure the custom button fill has 1.3:1 contrast w/ notification bg.
+                            int notifBackgroundColor = getColors(p).getBackgroundColor();
+                            buttonFillColor = ensureButtonFillContrast(
+                                    fullLengthColor, notifBackgroundColor);
+                        }
                     }
-                    // Remove full-length color spans and ensure text contrast with the button fill.
-                    title = ContrastColorUtil.ensureColorSpanContrast(title, buttonFillColor);
+                } else {
+                    if (isLegacy()) {
+                        title = ContrastColorUtil.clearColorSpans(title);
+                    } else {
+                        // Check for a full-length span color to use as the button fill color.
+                        Integer fullLengthColor = getFullLengthSpanColor(title);
+                        if (fullLengthColor != null) {
+                            // Ensure the custom button fill has 1.3:1 contrast w/ notification bg.
+                            int notifBackgroundColor = getColors(p).getBackgroundColor();
+                            buttonFillColor = ensureButtonFillContrast(
+                                    fullLengthColor, notifBackgroundColor);
+                        }
+                        // Remove full-length color spans
+                        // and ensure text contrast with the button fill.
+                        title = ContrastColorUtil.ensureColorSpanContrast(title, buttonFillColor);
+                    }
                 }
-                final CharSequence label = ensureColorSpanContrast(title, p);
+
+
+                final CharSequence label = ensureColorSpanContrastOrStripStyling(title, p);
                 if (p.mCallStyleActions && evenlyDividedCallStyleActionLayout()) {
                     if (CallStyle.DEBUG_NEW_ACTION_LAYOUT) {
                         Log.d(TAG, "new action layout enabled, gluing instead of setting text");
@@ -6554,7 +6800,7 @@
                     button.setIntDimen(R.id.action0, "setMinimumWidth", minWidthDimen);
                 }
             } else {
-                button.setTextViewText(R.id.action0, ensureColorSpanContrast(
+                button.setTextViewText(R.id.action0, ensureColorSpanContrastOrStripStyling(
                         action.title, p));
                 button.setTextColor(R.id.action0, getStandardActionColor(p));
             }
@@ -6629,6 +6875,26 @@
         }
 
         /**
+         * @hide
+         */
+        public CharSequence ensureColorSpanContrastOrStripStyling(CharSequence cs,
+                StandardTemplateParams p) {
+            return ensureColorSpanContrastOrStripStyling(cs, getBackgroundColor(p));
+        }
+
+        /**
+         * @hide
+         */
+        public CharSequence ensureColorSpanContrastOrStripStyling(CharSequence cs,
+                int buttonFillColor) {
+            if (Flags.cleanUpSpansAndNewLines()) {
+                return stripStyling(cs);
+            }
+
+            return ContrastColorUtil.ensureColorSpanContrast(cs, buttonFillColor);
+        }
+
+        /**
          * Ensures contrast on color spans against a background color.
          * Note that any full-length color spans will be removed instead of being contrasted.
          *
@@ -6696,7 +6962,8 @@
          */
         private void processSmallIconColor(Icon smallIcon, RemoteViews contentView,
                 StandardTemplateParams p) {
-            boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
+            boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext,
+                    smallIcon);
             int color = getSmallIconColor(p);
             contentView.setInt(R.id.icon, "setBackgroundColor",
                     getBackgroundColor(p));
@@ -7853,8 +8120,9 @@
             RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource(),
                     p, null /* result */);
             if (mSummaryTextSet) {
-                contentView.setTextViewText(R.id.text, mBuilder.ensureColorSpanContrast(
-                        mBuilder.processLegacyText(mSummaryText), p));
+                contentView.setTextViewText(R.id.text,
+                        mBuilder.ensureColorSpanContrastOrStripStyling(
+                                mBuilder.processLegacyText(mSummaryText), p));
                 mBuilder.setTextViewColorSecondary(contentView, R.id.text, p);
                 contentView.setViewVisibility(R.id.text, View.VISIBLE);
             }
@@ -8087,6 +8355,9 @@
 
             // Replace the text with the big text, but only if the big text is not empty.
             CharSequence bigTextText = mBuilder.processLegacyText(mBigText);
+            if (Flags.cleanUpSpansAndNewLines()) {
+                bigTextText = cleanUpNewLines(stripStyling(bigTextText));
+            }
             if (!TextUtils.isEmpty(bigTextText)) {
                 p.text(bigTextText);
             }
@@ -8517,7 +8788,7 @@
             for (int i = 0; i < N; i++) {
                 final Message m = messages.get(i);
                 if (ensureContrast) {
-                    m.ensureColorContrast(backgroundColor);
+                    m.ensureColorContrastOrStripStyling(backgroundColor);
                 }
                 bundles[i] = m.toBundle();
             }
@@ -8543,7 +8814,9 @@
             } else {
                 title = sender;
             }
-
+            if (Flags.cleanUpSpansAndNewLines()) {
+                title = stripStyling(title);
+            }
             if (title != null) {
                 extras.putCharSequence(EXTRA_TITLE, title);
             }
@@ -8995,6 +9268,49 @@
             }
 
             /**
+             * Strip styling or updates TextAppearance spans in message text.
+             * @hide
+             */
+            public void ensureColorContrastOrStripStyling(int backgroundColor) {
+                if (Flags.cleanUpSpansAndNewLines()) {
+                    mText = stripNonStyleSpans(mText);
+                } else {
+                    ensureColorContrast(backgroundColor);
+                }
+            }
+
+            private CharSequence stripNonStyleSpans(CharSequence text) {
+
+                if (text instanceof Spanned) {
+                    Spanned ss = (Spanned) text;
+                    Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+                    SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+                    for (Object span : spans) {
+                        final Object resultSpan;
+                        if (span instanceof StyleSpan
+                                || span instanceof StrikethroughSpan
+                                || span instanceof UnderlineSpan) {
+                            resultSpan = span;
+                        } else if (span instanceof TextAppearanceSpan) {
+                            final TextAppearanceSpan originalSpan = (TextAppearanceSpan) span;
+                            resultSpan = new TextAppearanceSpan(
+                                    null,
+                                    originalSpan.getTextStyle(),
+                                    -1,
+                                    null,
+                                    null);
+                        } else {
+                            continue;
+                        }
+                        builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+                                ss.getSpanFlags(span));
+                    }
+                    return builder;
+                }
+                return text;
+            }
+
+            /**
              * Updates TextAppearance spans in the message text so it has sufficient contrast
              * against its background.
              * @hide
@@ -9324,7 +9640,8 @@
                 if (!TextUtils.isEmpty(str)) {
                     contentView.setViewVisibility(rowIds[i], View.VISIBLE);
                     contentView.setTextViewText(rowIds[i],
-                            mBuilder.ensureColorSpanContrast(mBuilder.processLegacyText(str), p));
+                            mBuilder.ensureColorSpanContrastOrStripStyling(
+                                    mBuilder.processLegacyText(str), p));
                     mBuilder.setTextViewColorSecondary(contentView, rowIds[i], p);
                     contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
                     if (first) {
diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java
index f7a3d78..bcae22a 100644
--- a/core/java/android/app/ProfilerInfo.java
+++ b/core/java/android/app/ProfilerInfo.java
@@ -32,7 +32,8 @@
  * {@hide}
  */
 public class ProfilerInfo implements Parcelable {
-
+    // Version of the profiler output
+    public static final int OUTPUT_VERSION_DEFAULT = 1;
     // CLOCK_TYPE_DEFAULT chooses the default used by ART. ART uses CLOCK_TYPE_DUAL by default (see
     // kDefaultTraceClockSource in art/runtime/runtime_globals.h).
     public static final int CLOCK_TYPE_DEFAULT = 0x000;
@@ -43,6 +44,9 @@
     public static final int CLOCK_TYPE_WALL = 0x010;
     public static final int CLOCK_TYPE_THREAD_CPU = 0x100;
     public static final int CLOCK_TYPE_DUAL = 0x110;
+    // The second and third bits of the flags field specify the trace format version. This should
+    // match with kTraceFormatVersionShift defined in art/runtime/trace.h.
+    public static final int TRACE_FORMAT_VERSION_SHIFT = 1;
 
     private static final String TAG = "ProfilerInfo";
 
@@ -83,8 +87,14 @@
      */
     public final int clockType;
 
+    /**
+     * Indicates the version of profiler output.
+     */
+    public final int profilerOutputVersion;
+
     public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop,
-            boolean streaming, String agent, boolean attachAgentDuringBind, int clockType) {
+            boolean streaming, String agent, boolean attachAgentDuringBind, int clockType,
+            int profilerOutputVersion) {
         profileFile = filename;
         profileFd = fd;
         samplingInterval = interval;
@@ -93,6 +103,7 @@
         this.clockType = clockType;
         this.agent = agent;
         this.attachAgentDuringBind = attachAgentDuringBind;
+        this.profilerOutputVersion = profilerOutputVersion;
     }
 
     public ProfilerInfo(ProfilerInfo in) {
@@ -104,6 +115,7 @@
         agent = in.agent;
         attachAgentDuringBind = in.attachAgentDuringBind;
         clockType = in.clockType;
+        profilerOutputVersion = in.profilerOutputVersion;
     }
 
     /**
@@ -125,13 +137,29 @@
     }
 
     /**
+     * Get the flags that need to be passed to VMDebug.startMethodTracing to specify the desired
+     * output format.
+     */
+    public static int getFlagsForOutputVersion(int version) {
+        // Only two version 1 and version 2 are supported. Just use the default if we see an unknown
+        // version.
+        if (version != 1 || version != 2) {
+            version = OUTPUT_VERSION_DEFAULT;
+        }
+
+        // The encoded version in the flags starts from 0, where as the version that we read from
+        // user starts from 1. So, subtract one before encoding it in the flags.
+        return (version - 1) << TRACE_FORMAT_VERSION_SHIFT;
+    }
+
+    /**
      * Return a new ProfilerInfo instance, with fields populated from this object,
      * and {@link agent} and {@link attachAgentDuringBind} as given.
      */
     public ProfilerInfo setAgent(String agent, boolean attachAgentDuringBind) {
         return new ProfilerInfo(this.profileFile, this.profileFd, this.samplingInterval,
                 this.autoStopProfiler, this.streamingOutput, agent, attachAgentDuringBind,
-                this.clockType);
+                this.clockType, this.profilerOutputVersion);
     }
 
     /**
@@ -172,6 +200,7 @@
         out.writeString(agent);
         out.writeBoolean(attachAgentDuringBind);
         out.writeInt(clockType);
+        out.writeInt(profilerOutputVersion);
     }
 
     /** @hide */
@@ -186,6 +215,7 @@
         proto.write(ProfilerInfoProto.STREAMING_OUTPUT, streamingOutput);
         proto.write(ProfilerInfoProto.AGENT, agent);
         proto.write(ProfilerInfoProto.CLOCK_TYPE, clockType);
+        proto.write(ProfilerInfoProto.PROFILER_OUTPUT_VERSION, profilerOutputVersion);
         proto.end(token);
     }
 
@@ -211,6 +241,7 @@
         agent = in.readString();
         attachAgentDuringBind = in.readBoolean();
         clockType = in.readInt();
+        profilerOutputVersion = in.readInt();
     }
 
     @Override
@@ -226,9 +257,9 @@
         return Objects.equals(profileFile, other.profileFile)
                 && autoStopProfiler == other.autoStopProfiler
                 && samplingInterval == other.samplingInterval
-                && streamingOutput == other.streamingOutput
-                && Objects.equals(agent, other.agent)
-                && clockType == other.clockType;
+                && streamingOutput == other.streamingOutput && Objects.equals(agent, other.agent)
+                && clockType == other.clockType
+                && profilerOutputVersion == other.profilerOutputVersion;
     }
 
     @Override
@@ -240,6 +271,7 @@
         result = 31 * result + (streamingOutput ? 1 : 0);
         result = 31 * result + Objects.hashCode(agent);
         result = 31 * result + clockType;
+        result = 31 * result + profilerOutputVersion;
         return result;
     }
 }
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 02d6944..257aff0 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1603,8 +1603,18 @@
             @SetWallpaperFlags int which, boolean originalBitmap) {
         checkExactlyOneWallpaperFlagSet(which);
         try {
-            return sGlobals.mService.getBitmapCrops(displaySizes, which, originalBitmap,
-                    mContext.getUserId());
+            List<Rect> result = sGlobals.mService.getBitmapCrops(
+                    displaySizes, which, originalBitmap, mContext.getUserId());
+            if (result != null) return result;
+            // mService.getBitmapCrops returns null if the requested wallpaper is an ImageWallpaper,
+            // but there are no crop hints and the bitmap size is unknown to the service (this
+            // mostly happens for the default wallpaper). In that case, fetch the bitmap dimensions
+            // and use the other getBitmapCrops API with no cropHints to figure out the crops.
+            Rect bitmapDimensions = peekBitmapDimensions(which, true);
+            if (bitmapDimensions == null) return List.of();
+            Point bitmapSize = new Point(bitmapDimensions.width(), bitmapDimensions.height());
+            return getBitmapCrops(bitmapSize, displaySizes, null);
+
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index aa3b71a..a12faca 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -100,9 +100,6 @@
     /** The current windowing mode of the configuration. */
     private @WindowingMode int mWindowingMode;
 
-    /** The display windowing mode of the configuration */
-    private @WindowingMode int mDisplayWindowingMode;
-
     /** Windowing mode is currently not defined. */
     public static final int WINDOWING_MODE_UNDEFINED = 0;
     /** Occupies the full area of the screen or the parent container. */
@@ -193,12 +190,9 @@
     /** Bit that indicates that the {@link #mRotation} changed.
      * @hide */
     public static final int WINDOW_CONFIG_ROTATION = 1 << 6;
-    /** Bit that indicates that the {@link #mDisplayWindowingMode} changed.
-     * @hide */
-    public static final int WINDOW_CONFIG_DISPLAY_WINDOWING_MODE = 1 << 7;
     /** Bit that indicates that the apparent-display changed.
      * @hide */
-    public static final int WINDOW_CONFIG_DISPLAY_ROTATION = 1 << 8;
+    public static final int WINDOW_CONFIG_DISPLAY_ROTATION = 1 << 7;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "WINDOW_CONFIG_" }, value = {
@@ -209,7 +203,6 @@
             WINDOW_CONFIG_ACTIVITY_TYPE,
             WINDOW_CONFIG_ALWAYS_ON_TOP,
             WINDOW_CONFIG_ROTATION,
-            WINDOW_CONFIG_DISPLAY_WINDOWING_MODE,
             WINDOW_CONFIG_DISPLAY_ROTATION,
     })
     public @interface WindowConfig {}
@@ -237,7 +230,6 @@
         dest.writeInt(mActivityType);
         dest.writeInt(mAlwaysOnTop);
         dest.writeInt(mRotation);
-        dest.writeInt(mDisplayWindowingMode);
         dest.writeInt(mDisplayRotation);
     }
 
@@ -250,7 +242,6 @@
         mActivityType = source.readInt();
         mAlwaysOnTop = source.readInt();
         mRotation = source.readInt();
-        mDisplayWindowingMode = source.readInt();
         mDisplayRotation = source.readInt();
     }
 
@@ -411,17 +402,6 @@
         return mWindowingMode;
     }
 
-    /** @hide */
-    public void setDisplayWindowingMode(@WindowingMode int windowingMode) {
-        mDisplayWindowingMode = windowingMode;
-    }
-
-    /** @hide */
-    @WindowingMode
-    public int getDisplayWindowingMode() {
-        return mDisplayWindowingMode;
-    }
-
     public void setActivityType(@ActivityType int activityType) {
         if (mActivityType == activityType) {
             return;
@@ -453,7 +433,6 @@
         setActivityType(other.mActivityType);
         setAlwaysOnTop(other.mAlwaysOnTop);
         setRotation(other.mRotation);
-        setDisplayWindowingMode(other.mDisplayWindowingMode);
     }
 
     /** Set this object to completely undefined.
@@ -472,7 +451,6 @@
         setActivityType(ACTIVITY_TYPE_UNDEFINED);
         setAlwaysOnTop(ALWAYS_ON_TOP_UNDEFINED);
         setRotation(ROTATION_UNDEFINED);
-        setDisplayWindowingMode(WINDOWING_MODE_UNDEFINED);
     }
 
     /** @hide */
@@ -543,11 +521,6 @@
             changed |= WINDOW_CONFIG_ROTATION;
             setRotation(delta.mRotation);
         }
-        if (delta.mDisplayWindowingMode != WINDOWING_MODE_UNDEFINED
-                && mDisplayWindowingMode != delta.mDisplayWindowingMode) {
-            changed |= WINDOW_CONFIG_DISPLAY_WINDOWING_MODE;
-            setDisplayWindowingMode(delta.mDisplayWindowingMode);
-        }
         if (delta.mDisplayRotation != ROTATION_UNDEFINED
                 && delta.mDisplayRotation != mDisplayRotation) {
             changed |= WINDOW_CONFIG_DISPLAY_ROTATION;
@@ -582,9 +555,6 @@
         if ((mask & WINDOW_CONFIG_ROTATION) != 0) {
             setRotation(delta.mRotation);
         }
-        if ((mask & WINDOW_CONFIG_DISPLAY_WINDOWING_MODE) != 0) {
-            setDisplayWindowingMode(delta.mDisplayWindowingMode);
-        }
         if ((mask & WINDOW_CONFIG_DISPLAY_ROTATION) != 0) {
             setDisplayRotation(delta.mDisplayRotation);
         }
@@ -639,11 +609,6 @@
             changes |= WINDOW_CONFIG_ROTATION;
         }
 
-        if ((compareUndefined || other.mDisplayWindowingMode != WINDOWING_MODE_UNDEFINED)
-                && mDisplayWindowingMode != other.mDisplayWindowingMode) {
-            changes |= WINDOW_CONFIG_DISPLAY_WINDOWING_MODE;
-        }
-
         if ((compareUndefined || other.mDisplayRotation != ROTATION_UNDEFINED)
                 && mDisplayRotation != other.mDisplayRotation) {
             changes |= WINDOW_CONFIG_DISPLAY_ROTATION;
@@ -697,8 +662,6 @@
         n = mRotation - that.mRotation;
         if (n != 0) return n;
 
-        n = mDisplayWindowingMode - that.mDisplayWindowingMode;
-        if (n != 0) return n;
         n = mDisplayRotation - that.mDisplayRotation;
         if (n != 0) return n;
 
@@ -728,7 +691,6 @@
         result = 31 * result + mActivityType;
         result = 31 * result + mAlwaysOnTop;
         result = 31 * result + mRotation;
-        result = 31 * result + mDisplayWindowingMode;
         result = 31 * result + mDisplayRotation;
         return result;
     }
@@ -742,7 +704,6 @@
                 + " mDisplayRotation=" + (mRotation == ROTATION_UNDEFINED
                         ? "undefined" : rotationToString(mDisplayRotation))
                 + " mWindowingMode=" + windowingModeToString(mWindowingMode)
-                + " mDisplayWindowingMode=" + windowingModeToString(mDisplayWindowingMode)
                 + " mActivityType=" + activityTypeToString(mActivityType)
                 + " mAlwaysOnTop=" + alwaysOnTopToString(mAlwaysOnTop)
                 + " mRotation=" + (mRotation == ROTATION_UNDEFINED
@@ -818,16 +779,6 @@
     }
 
     /**
-     * Returns true if the activities associated with this window configuration display a decor
-     * view.
-     * @hide
-     */
-    public boolean hasWindowDecorCaption() {
-        return mActivityType == ACTIVITY_TYPE_STANDARD && (mWindowingMode == WINDOWING_MODE_FREEFORM
-                || mDisplayWindowingMode == WINDOWING_MODE_FREEFORM);
-    }
-
-    /**
      * Returns true if the tasks associated with this window configuration can be resized
      * independently of their parent container.
      * @hide
diff --git a/core/java/android/app/admin/AccountTypePolicyKey.java b/core/java/android/app/admin/AccountTypePolicyKey.java
index 51f3137..02e492b 100644
--- a/core/java/android/app/admin/AccountTypePolicyKey.java
+++ b/core/java/android/app/admin/AccountTypePolicyKey.java
@@ -54,7 +54,7 @@
     @TestApi
     public AccountTypePolicyKey(@NonNull String key, @NonNull String accountType) {
         super(key);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxStringLength(accountType, "accountType");
         }
         mAccountType = Objects.requireNonNull((accountType));
diff --git a/core/java/android/app/admin/BundlePolicyValue.java b/core/java/android/app/admin/BundlePolicyValue.java
index cb5e986..c993671 100644
--- a/core/java/android/app/admin/BundlePolicyValue.java
+++ b/core/java/android/app/admin/BundlePolicyValue.java
@@ -31,7 +31,7 @@
 
     public BundlePolicyValue(Bundle value) {
         super(value);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxBundleFieldsLength(value);
         }
     }
diff --git a/core/java/android/app/admin/ComponentNamePolicyValue.java b/core/java/android/app/admin/ComponentNamePolicyValue.java
index a957dbf..a7a2f7d 100644
--- a/core/java/android/app/admin/ComponentNamePolicyValue.java
+++ b/core/java/android/app/admin/ComponentNamePolicyValue.java
@@ -31,7 +31,7 @@
 
     public ComponentNamePolicyValue(@NonNull ComponentName value) {
         super(value);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxComponentNameLength(value);
         }
     }
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index f21e11a..c7b0be7 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -244,6 +244,10 @@
      * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. You will generally handle
      * this in {@link DeviceAdminReceiver#onProfileProvisioningComplete}.
      *
+     * <p>The intent for this action may include the following extras:
+     * <ul>
+     *     <li>{@link DevicePolicyManager#EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}
+     *
      * @see DevicePolicyManager#ACTION_PROVISIONING_SUCCESSFUL
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -801,6 +805,9 @@
      * {@link DevicePolicyManager#ACTION_PROVISIONING_SUCCESSFUL} will also be sent to the same
      * application.
      *
+     * <p>The {@code Intent} may include any of the extras specified for
+     * {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
+     *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      */
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 42e82f6..9058713 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -54,6 +54,7 @@
 import static android.Manifest.permission.SET_TIME;
 import static android.Manifest.permission.SET_TIME_ZONE;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
+import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_INTERNAL_BUG_FIX_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_DEVICE_THEFT_API_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_ESIM_MANAGEMENT_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED;
@@ -191,32 +192,134 @@
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
-// TODO(b/172376923) - add CarDevicePolicyManager examples below (or remove reference to it).
 /**
- * Public interface for managing policies enforced on a device. Most clients of this class must be
- * registered with the system as a <a href="{@docRoot}guide/topics/admin/device-admin.html">device
- * administrator</a>. Additionally, a device administrator may be registered as either a profile or
- * device owner. A given method is accessible to all device administrators unless the documentation
- * for that method specifies that it is restricted to either device or profile owners. Any
- * application calling an api may only pass as an argument a device administrator component it
- * owns. Otherwise, a {@link SecurityException} will be thrown.
+ * Manages device policy and restrictions applied to the user of the device or
+ * apps running on the device.
  *
- * <p><b>Note: </b>on
- * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE automotive builds}, some methods can
- * throw an {@link UnsafeStateException} exception (for example, if the vehicle is moving), so
- * callers running on automotive builds should always check for that exception, otherwise they
- * might crash.
+ * <p>This class contains three types of methods:
+ * <ol><li>Those aimed at <a href="#managingapps">managing apps</a>
+ * <li>Those aimed at the <a href="#roleholder">Device Policy Management Role Holder</a>
+ * <li>Those aimed at <a href="#querying">apps which wish to respect device policy</a>
+ * </ol>
  *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about managing policies for device administration, read the <a href=
- * "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> developer
- * guide. </div>
+ * <p>The intended caller for each API is indicated in its Javadoc.
+ *
+ * <p id="managingapps"><b>Managing Apps</b>
+ * <p>Apps can be made capable of setting device policy ("Managing Apps") either by
+ * being set as a <a href="#deviceadmin">Device Administrator</a>, being set as a
+ * <a href="#devicepolicycontroller">Device Policy Controller</a>, or by holding the
+ * appropriate <a href="#permissions">Permissions</a>.
+ *
+ * <p id="deviceadmin">A <b>Device Administrator</b> is an app which is able to enforce device
+ * policies that it has declared in its device admin XML file. An app can prompt the user to give it
+ * device administator privileges using the {@link #ACTION_ADD_DEVICE_ADMIN} action.
+ *
+ * <p>For more information about Device Administration, read the
+ * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
+ * developer guide.
+ *
+ * <p id="devicepolicycontroller">Through <a href="#managed_provisioning">Managed Provisioning</a>,
+ * Device Administrator apps can also be recognised as <b>
+ Device Policy Controllers</b>. Device Policy Controllers can be one of
+ * two types:
+ * <ul>
+ * <li>A <i id="deviceowner">Device Owner</i>, which only ever exists on the
+ * {@link UserManager#isSystemUser System User} or {@link UserManager#isMainUser Main User}, is
+ * the most powerful type of Device Policy Controller and can affect policy across the device.
+ * <li>A <i id="profileowner">Profile Owner<i>, which can exist on any user, can
+ * affect policy on the user it is on, and when it is running on
+ * {@link UserManager#isProfile a profile} has
+ * <a href="#profile-on-parent">limited</a> ability to affect policy on its
+ * {@link UserManager#getProfileParent parent}.
+ * </ul>
+ *
+ * <p>Additional capabilities can be provided to Device Policy Controllers in
+ * the following circumstances:
+ * <ul>
+ * <li>A Profile Owner on an <a href="#organization-owned">organization owned</a> device has access
+ * to additional abilities, both <a href="#profile-on-parent-organization-owned">affecting policy on the profile's</a>
+ * {@link UserManager#getProfileParent parent} and also the profile itself.
+ * <li>A Profile Owner running on the {@link UserManager#isSystemUser System User} has access to
+ * additional capabilities which affect the {@link UserManager#isSystemUser System User} and
+ * also the whole device.
+ * <li>A Profile Owner running on an <a href="#affiliated">affiliated</a> user has
+ * capabilities similar to that of a <a href="#deviceowner">Device Owner</a>
+ * </ul>
+ *
+ * <p>For more information, see <a href="{@docRoot}work/dpc/build-dpc">Building a Device Policy
+ * Controller</a>.
+ *
+ * <p><a href="#permissions">Permissions</a> are generally only given to apps
+ * fulfilling particular key roles on the device (such as managing {@link DeviceLockManager
+device locks}).
+ *
+ * <p id="roleholder"><b>Device Policy Management Role Holder</b>
+ * <p>One app on the device fulfills the {@link RoleManager#ROLE_DEVICE_POLICY_MANAGEMENT Device
+Policy Management Role} and is trusted with managing the overall state of
+ * Device Policy. This has access to much more powerful methods than
+ * <a href="#managingapps">managing apps</a>.
+ *
+ * <p id="querying"><b>Querying Device Policy</b>
+ * <p>In most cases, regular apps do not need to concern themselves with device
+ * policy, and restrictions will be enforced automatically. There are some cases
+ * where an app may wish to query device policy to provide a better user
+ * experience. Only a small number of policies allow apps to query them directly.
+ * These APIs will typically have no special required permissions.
+ *
+ * <p id="managedprovisioning"><b>Managed Provisioning</b>
+ * <p>Managed Provisioning is the process of recognising an app as a
+ * <a href="#deviceowner">Device Owner</a> or <a href="#profileowner">Profile Owner</a>. It
+ * involves presenting education and consent screens to the user to ensure they
+ * are aware of the capabilities this grants the <a href="#devicepolicycontroller">Device Policy
+ * Controller</a>
+ *
+ * <p>For more information on provisioning, see <a href="{@docRoot}work/dpc/build-dpc">Building a
+ * Device Policy Controller</a>.
+ *
+ * <p id="managed_profile">A <b>Managed Profile</b> enables data separation. For example to use
+ * a device both for personal and corporate usage. The managed profile and its
+ * {@link UserManager#getProfileParent parent} share a launcher.
+ *
+ * <p id="affiliated"><b>Affiliation</b>
+ * <p>Using the {@link #setAffiliationIds} method, a
+ * <a href="#deviceowner">Device Owner</a> can set a list of affiliation ids for the
+ * {@link UserManager#isSystemUser System User}. Any <a href="#profileowner">Profile Owner</a> on
+ * the same device can also call {@link #setAffiliationIds} to set affiliation ids
+ * for the {@link UserManager user} it is on. When there is the same ID
+ * present in both lists, the user is said to be "affiliated" and we can refer to
+ * the <a href="#profileowner">Profile Owner</a> as a "profile owner on an affiliated
+ * user" or an "affiliated profile owner".
+ *
+ * Becoming affiliated grants the <a href="#profileowner">Profile Owner</a> capabilities similar to
+ * that of the <a href="#deviceowner">Device Owner</a>. It also allows use of the
+ * {@link #bindDeviceAdminServiceAsUser} APIs for direct communication between the
+ * <a href="#deviceowner">Device Owner</a> and
+ * affiliated <a href="#profileowner">Profile Owners</a>.
+ *
+ * <p id="organization-owned"><b>Organization Owned</b></p>
+ * An organization owned device is one which is not owned by the person making use of the device and
+ * is instead owned by an organization such as their employer or education provider. These devices
+ * are recognised as being organization owned either by the presence of a
+ * <a href="#deviceowner">device owner</a> or of a
+ * {@link #isOrganizationOwnedDeviceWithManagedProfile profile which has a profile owner is marked
+ * as organization owned}.
+ *
+ * <p id="profile-on-parent-organization-owned">Profile owners running on an
+ * <a href="organization-owned">organization owned</a> device can exercise additional capabilities
+ * using the {@link #getParentProfileInstance(ComponentName)} API which apply to the parent user.
+ * Each API will indicate if it is usable in this way.
+ *
+ * <p id="automotive"><b>Android Automotive</b>
+ * <p>On {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE
+ * "Android Automotive builds"}, some methods can throw
+ * {@link UnsafeStateException "an exception"} if an action is unsafe (for example, if the vehicle
+ * is moving). Callers running on
+ * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE
+ * "Android Automotive builds"} should always check for this exception.
  */
+
 @SystemService(Context.DEVICE_POLICY_SERVICE)
 @RequiresFeature(PackageManager.FEATURE_DEVICE_ADMIN)
-@SuppressLint("UseIcu")
 public class DevicePolicyManager {
 
     /** @hide */
@@ -256,7 +359,7 @@
      * Fetch the current value of mService.  This is used in the binder cache lambda
      * expressions.
      */
-    private final IDevicePolicyManager getService() {
+    private IDevicePolicyManager getService() {
         return mService;
     }
 
@@ -264,7 +367,7 @@
      * Fetch the current value of mParentInstance.  This is used in the binder cache
      * lambda expressions.
      */
-    private final boolean isParentInstance() {
+    private boolean isParentInstance() {
         return mParentInstance;
     }
 
@@ -272,7 +375,7 @@
      * Fetch the current value of mContext.  This is used in the binder cache lambda
      * expressions.
      */
-    private final Context getContext() {
+    private Context getContext() {
         return mContext;
     }
 
@@ -283,39 +386,80 @@
     }
 
     /**
-     * Activity action: Starts the provisioning flow which sets up a managed profile.
-     *
-     * <p>A managed profile allows data separation for example for the usage of a
-     * device as a personal and corporate device. The user which provisioning is started from and
-     * the managed profile share a launcher.
-     *
-     * <p>This intent will typically be sent by a mobile device management application (MDM).
-     * Provisioning adds a managed profile and sets the MDM as the profile owner who has full
-     * control over the profile.
+     * Activity action: Starts the provisioning flow which sets up a
+     * <a href="#managed-profile">managed profile</a>.
      *
      * <p>It is possible to check if provisioning is allowed or not by querying the method
      * {@link #isProvisioningAllowed(String)}.
      *
-     * <p>In version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this intent must contain the
-     * extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
-     * As of {@link android.os.Build.VERSION_CODES#M}, it should contain the extra
-     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead, although specifying only
-     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported.
+     * <p>The intent may contain the following extras:
      *
-     * <p>The intent may also contain the following extras:
-     * <ul>
-     * <li>{@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}, optional </li>
-     * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional, supported from
-     * {@link android.os.Build.VERSION_CODES#N}</li>
-     * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_LOGO_URI}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_SKIP_USER_CONSENT}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_DISCLAIMERS}, optional</li>
-     * </ul>
+     * <table>
+     *  <thead>
+     *      <tr>
+     *          <th>Extra</th>
+     *          <th></th>
+     *          <th>Supported Versions</th>
+     *      </tr>
+     *  </thead>
+     *  <tbody>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}</td>
+     *          <td colspan="2"></td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}</td>
+     *          <td></td>
+     *          <td>{@link android.os.Build.VERSION_CODES#N}+</td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}</td>
+     *          <td colspan="2"></td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_LOGO_URI}</td>
+     *          <td colspan="2"></td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_SKIP_USER_CONSENT}</td>
+     *          <td colspan="2"><b>Can only be used by an existing device owner trying to create a
+     *          managed profile</b></td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION}</td>
+     *          <td colspan="2"></td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_DISCLAIMERS}</td>
+     *          <td colspan="2"></td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}</td>
+     *          <td>
+     *              <b>Required if {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} is not
+     *              specified. Must match the package name of the calling application.</b>
+     *          </td>
+     *          <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}+</td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</td>
+     *          <td>
+     *              <b>Required if {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is not
+     *              specified. Package name must match the package name of the calling
+     *              application.</b>
+     *          </td>
+     *          <td>{@link android.os.Build.VERSION_CODES#M}+</td>
+     *      </tr>
+     *      <tr>
+     *          <td>{@link #EXTRA_PROVISIONING_ALLOW_OFFLINE}</td>
+     *          <td colspan="2">On {@link android.os.Build.VERSION_CODES#TIRAMISU}+, when set to
+     *          true this will <b>force</b> offline provisioning instead of allowing it</td>
+     *      </tr>
+     *  </tbody>
+     * </table>
      *
-     * <p>When managed provisioning has completed, broadcasts are sent to the application specified
-     * in the provisioning intent. The
+     * <p>When <a href="#managedprovisioning">managed provisioning</a> has completed, broadcasts
+     * are sent to the application specified in the provisioning intent. The
      * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} broadcast is sent in the
      * managed profile and the {@link #ACTION_MANAGED_PROFILE_PROVISIONED} broadcast is sent in
      * the primary profile.
@@ -324,25 +468,25 @@
      * completed, along with the above broadcast, activity intent
      * {@link #ACTION_PROVISIONING_SUCCESSFUL} will also be sent to the profile owner.
      *
-     * <p>If provisioning fails, the managedProfile is removed so the device returns to its
+     * <p>If provisioning fails, the managed profile is removed so the device returns to its
      * previous state.
      *
      * <p>If launched with {@link android.app.Activity#startActivityForResult(Intent, int)} a
-     * result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part of
+     * result code of {@link android.app.Activity#RESULT_OK} indicates that the synchronous part of
      * the provisioning flow was successful, although this doesn't guarantee the full flow will
-     * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
-     * that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
+     * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} indicates
+     * that the user backed-out of provisioning or some precondition for provisioning wasn't met.
      *
-     * <p>If a device policy management role holder (DPMRH) updater is present on the device, an
-     * internet connection attempt must be made prior to launching this intent. If internet
-     * connection could not be established, provisioning will fail unless {@link
+     * <p>If a <a href="#roleholder">device policy management role holder</a> updater is present on
+     * the device, an internet connection attempt must be made prior to launching this intent. If
+     * an internet connection can not be established, provisioning will fail unless {@link
      * #EXTRA_PROVISIONING_ALLOW_OFFLINE} is explicitly set to {@code true}, in which case
-     * provisioning will continue without using the DPMRH. If an internet connection has been
-     * established, the DPMRH updater will be launched, which will update the DPMRH if it's not
-     * present on the device, or if it's present and not valid.
-     *
-     * <p>If a DPMRH is present on the device and valid, the provisioning flow will be deferred to
-     * it.
+     * provisioning will continue without using the
+     * <a href="#roleholder">device policy management role holder</a>. If an internet connection
+     * has been established, the <a href="#roleholder">device policy management role holder</a>
+     * updater will be launched, which may update the
+     * <a href="#roleholder">device policy management role holder</a> before continuing
+     * provisioning.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_MANAGED_PROFILE
@@ -821,31 +965,25 @@
             "android.app.extra.FORCE_UPDATE_ROLE_HOLDER";
 
     /**
-     * A boolean extra indicating whether offline provisioning is allowed.
-     *
-     * <p>For the online provisioning flow, there will be an attempt to download and install
-     * the latest version of the device policy management role holder. The platform will then
-     * delegate provisioning to the device policy management role holder via role holder-specific
-     * provisioning actions.
-     *
-     * <p>For the offline provisioning flow, the provisioning flow will always be handled by
-     * the platform.
-     *
-     * <p>If this extra is set to {@code false}, the provisioning flow will enforce that an
-     * internet connection is established, which will start the online provisioning flow. If an
-     * internet connection cannot be established, provisioning will fail.
-     *
-     * <p>If this extra is set to {@code true}, the provisioning flow will still try to connect to
-     * the internet, but if it fails it will start the offline provisioning flow.
-     *
-     * <p>For T if this extra is set to {@code true}, the provisioning flow will be forced through
-     * the platform and there will be no attempt to download and install the device policy
-     * management role holder.
+     * A boolean extra indicating whether offline provisioning should be used.
      *
      * <p>The default value is {@code false}.
      *
-     * <p>This extra is respected when provided via the provisioning intent actions such as {@link
-     * #ACTION_PROVISION_MANAGED_PROFILE}.
+     * <p>Usually during the <a href="#managedprovisioning">provisioning flow</a>, there will be
+     * an attempt to download and install the latest version of the <a href="#roleholder">device
+     * policy management role holder</a>. The platform will then
+     * delegate provisioning to the <a href="#roleholder">device
+     *      * policy management role holder</a>.
+     *
+     * <p>When this extra is set to {@code true}, the
+     * <a href="#managedprovisioning">provisioning flow</a> will always be handled by the platform
+     * and the <a href="#roleholder">device policy management role holder</a>'s part skipped.
+     *
+     * <p>On Android versions prior to {@link Build.VERSION_CODES#TIRAMISU}, when this extra is
+     * {@code false}, the <a href="#managedprovisioning">provisioning flow</a> will enforce that an
+     * internet connection is established, or otherwise fail. When this extra is {@code true}, a
+     * connection will still be attempted but when it cannot be established provisioning will
+     * continue offline.
      */
     public static final String EXTRA_PROVISIONING_ALLOW_OFFLINE =
             "android.app.extra.PROVISIONING_ALLOW_OFFLINE";
@@ -1056,64 +1194,40 @@
     public static final long DEFAULT_STRONG_AUTH_TIMEOUT_MS = 72 * 60 * 60 * 1000; // 72h
 
     /**
-     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
-     * allows a mobile device management application or NFC programmer application which starts
-     * managed provisioning to pass data to the management application instance after provisioning.
+     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that is
+     * passed directly to the <a href="#devicepolicycontroller">Device Policy Controller</a>
+     * after <a href="#managed-provisioning">provisioning</a>.
+     *
      * <p>
-     * If used with {@link #ACTION_PROVISION_MANAGED_PROFILE} it can be used by the application that
-     * sends the intent to pass data to itself on the newly created profile.
-     * If used with {@link #ACTION_PROVISION_MANAGED_DEVICE} it allows passing data to the same
-     * instance of the app on the primary user.
      * Starting from {@link android.os.Build.VERSION_CODES#M}, if used with
      * {@link #MIME_TYPE_PROVISIONING_NFC} as part of NFC managed device provisioning, the NFC
      * message should contain a stringified {@link java.util.Properties} instance, whose string
      * properties will be converted into a {@link android.os.PersistableBundle} and passed to the
      * management application after provisioning.
-     *
-     * <p>Admin apps will receive this extra in their {@link #ACTION_GET_PROVISIONING_MODE} and
-     * {@link #ACTION_ADMIN_POLICY_COMPLIANCE} intent handlers. Additionally, {@link
-     * #ACTION_GET_PROVISIONING_MODE} may also return this extra which will then be sent over to
-     * {@link #ACTION_ADMIN_POLICY_COMPLIANCE}, alongside the original values that were passed to
-     * {@link #ACTION_GET_PROVISIONING_MODE}.
-     *
-     * <p>
-     * In both cases the application receives the data in
-     * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
-     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
-     * during the managed provisioning.
      */
     public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
             "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
 
     /**
-     * A String extra holding the package name of the mobile device management application that
-     * will be set as the profile owner or device owner.
+     * A String extra holding the package name of the application that
+     * will be set as <a href="#devicepolicycontroller">Device Policy Controller</a>.
      *
-     * <p>If an application starts provisioning directly via an intent with action
-     * {@link #ACTION_PROVISION_MANAGED_PROFILE} this package has to match the package name of the
-     * application that started provisioning. The package will be set as profile owner in that case.
+     * <p>When this extra is set, the application must have exactly one
+     * {@link DeviceAdminReceiver device admin receiver}. This receiver will be set as the
+     * <a href="#devicepolicycontroller">Device Policy Controller</a>.
      *
-     * <p>This package is set as device owner when device owner provisioning is started by an NFC
-     * message containing an NFC record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
-     *
-     * <p> When this extra is set, the application must have exactly one device admin receiver.
-     * This receiver will be set as the profile or device owner and active admin.
-     *
-     * @see DeviceAdminReceiver
-     * @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. This extra is still
-     * supported, but only if there is only one device admin receiver in the package that requires
-     * the permission {@link android.Manifest.permission#BIND_DEVICE_ADMIN}.
+     * @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}.
      */
     @Deprecated
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
 
     /**
-     * A ComponentName extra indicating the device admin receiver of the mobile device management
-     * application that will be set as the profile owner or device owner and active admin.
+     * A ComponentName extra indicating the {@link DeviceAdminReceiver device admin receiver} of
+     * the application that will be set as the <a href="#devicepolicycontroller">
+     *     Device Policy Controller</a>.
      *
      * <p>If an application starts provisioning directly via an intent with action
-     * {@link #ACTION_PROVISION_MANAGED_PROFILE} or
      * {@link #ACTION_PROVISION_MANAGED_DEVICE} the package name of this
      * component has to match the package name of the application that started provisioning.
      *
@@ -1122,35 +1236,28 @@
      * message containing an NFC record with MIME type
      * {@link #MIME_TYPE_PROVISIONING_NFC}. For the NFC record, the component name must be
      * flattened to a string, via {@link ComponentName#flattenToShortString()}.
-     *
-     * @see DeviceAdminReceiver
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
 
     /**
      * An {@link android.accounts.Account} extra holding the account to migrate during managed
-     * profile provisioning. If the account supplied is present in the primary user, it will be
-     * copied, along with its credentials to the managed profile and removed from the primary user.
+     * profile provisioning.
      *
-     * Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}, with managed account provisioning, or
-     * return as an extra to the intent result from the {@link #ACTION_GET_PROVISIONING_MODE}
-     * activity.
+     * <p>If the account supplied is present in the user, it will be copied, along with its
+     * credentials to the managed profile and removed from the user.
      */
-
     public static final String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE
         = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
 
     /**
-     * Boolean extra to indicate that the migrated account should be kept. This is used in
-     * conjunction with {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}. If it's set to {@code true},
-     * the account will not be removed from the primary user after it is migrated to the newly
-     * created user or profile.
+     * Boolean extra to indicate that the
+     * {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE migrated account} should be kept.
      *
-     * <p> Defaults to {@code false}
+     * <p>If it's set to {@code true}, the account will not be removed from the user after it is
+     * migrated to the newly created user or profile.
      *
-     * <p> Use with {@link #ACTION_PROVISION_MANAGED_PROFILE} or set as an extra to the
-     * intent result of the {@link #ACTION_GET_PROVISIONING_MODE} activity.
+     * <p>Defaults to {@code false}
      *
      * @see #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE
      */
@@ -1589,17 +1696,14 @@
             "android.app.action.PROVISIONING_SUCCESSFUL";
 
     /**
-     * A boolean extra indicating whether device encryption can be skipped as part of device owner
-     * or managed profile provisioning.
+     * A boolean extra indicating whether device encryption can be skipped as part of
+     * <a href="#managed-provisioning>provisioning</a>.
      *
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} or an intent with action
      * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
      *
      * <p>From {@link android.os.Build.VERSION_CODES#N} onwards, this is also supported for an
      * intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE}.
-     *
-     * <p>This extra can also be returned by the admin app when performing the admin-integrated
-     * provisioning flow as a result of the {@link #ACTION_GET_PROVISIONING_MODE} activity.
      */
     public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
              "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
@@ -1607,23 +1711,22 @@
     /**
      * A {@link Uri} extra pointing to a logo image. This image will be shown during the
      * provisioning. If this extra is not passed, a default image will be shown.
-     * <h5>The following URI schemes are accepted:</h5>
+     *
+     * <p><b>The following URI schemes are accepted:</b>
      * <ul>
      * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
      * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
      * </ul>
      *
-     * <p> It is the responsibility of the caller to provide an image with a reasonable
+     * <p>It is the responsibility of the caller to provide an image with a reasonable
      * pixel density for the device.
      *
-     * <p> If a content: URI is passed, the intent should have the flag
+     * <p>If a content: URI is passed, the intent should also have the flag
      * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and the uri should be added to the
-     * {@link android.content.ClipData} of the intent too.
+     * {@link android.content.ClipData} of the intent.
      *
-     * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE} or
-     * {@link #ACTION_PROVISION_MANAGED_DEVICE}
-     *
-     * @deprecated Logo customization is no longer supported in the provisioning flow.
+     * @deprecated Logo customization is no longer supported in the
+     *             <a href="#managedprovisioning">provisioning flow</a>.
      */
     @Deprecated
     public static final String EXTRA_PROVISIONING_LOGO_URI =
@@ -1631,7 +1734,8 @@
 
     /**
      * A {@link Bundle}[] extra consisting of list of disclaimer headers and disclaimer contents.
-     * Each {@link Bundle} must have both {@link #EXTRA_PROVISIONING_DISCLAIMER_HEADER}
+     *
+     * <p>Each {@link Bundle} must have both {@link #EXTRA_PROVISIONING_DISCLAIMER_HEADER}
      * as disclaimer header, and {@link #EXTRA_PROVISIONING_DISCLAIMER_CONTENT} as disclaimer
      * content.
      *
@@ -1652,20 +1756,21 @@
     /**
      * A String extra of localized disclaimer header.
      *
-     * <p> The extra is typically the company name of mobile device management application (MDM)
+     * <p>The extra is typically the company name of mobile device management application (MDM)
      * or the organization name.
      *
-     * <p> Use in Bundle {@link #EXTRA_PROVISIONING_DISCLAIMERS}
+     * <p>{@link ApplicationInfo#FLAG_SYSTEM System apps} can also insert a disclaimer by declaring
+     * an application-level meta-data in {@code AndroidManifest.xml}.
      *
-     * <p> System app, i.e. application with {@link ApplicationInfo#FLAG_SYSTEM}, can also insert a
-     * disclaimer by declaring an application-level meta-data in {@code AndroidManifest.xml}.
-     * Must use it with {@link #EXTRA_PROVISIONING_DISCLAIMER_CONTENT}. Here is the example:
-     *
+     * <p>For example:
      * <pre>
      *  &lt;meta-data
      *      android:name="android.app.extra.PROVISIONING_DISCLAIMER_HEADER"
      *      android:resource="@string/disclaimer_header"
      * /&gt;</pre>
+     *
+     * <p>This must be accompanied with another extra using the key
+     * {@link #EXTRA_PROVISIONING_DISCLAIMER_CONTENT}.
      */
     public static final String EXTRA_PROVISIONING_DISCLAIMER_HEADER =
             "android.app.extra.PROVISIONING_DISCLAIMER_HEADER";
@@ -1679,35 +1784,35 @@
      * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
      * </ul>
      *
-     * <p> Styled text is supported in the disclaimer content. The content is parsed by
-     * {@link android.text.Html#fromHtml(String)} and displayed in a
-     * {@link android.widget.TextView}.
+     * <p>Styled text is supported. This is parsed by {@link android.text.Html#fromHtml(String)}
+     * and displayed in a {@link android.widget.TextView}.
      *
-     * <p> If a <code>content:</code> URI is passed, URI is passed, the intent should have the flag
-     * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and the uri should be added to the
-     * {@link android.content.ClipData} of the intent too.
+     * <p>If a <code>content:</code> URI is passed, the intent should also have the
+     * flag {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and the uri should be added to the
+     * {@link android.content.ClipData} of the intent.
      *
-     * <p> Use in Bundle {@link #EXTRA_PROVISIONING_DISCLAIMERS}
-     *
-     * <p> System app, i.e. application with {@link ApplicationInfo#FLAG_SYSTEM}, can also insert a
+     * <p>{@link ApplicationInfo#FLAG_SYSTEM System apps} can also insert a
      * disclaimer by declaring an application-level meta-data in {@code AndroidManifest.xml}.
-     * Must use it with {@link #EXTRA_PROVISIONING_DISCLAIMER_HEADER}. Here is the example:
+     *
+     * <p>For example:
      *
      * <pre>
      *  &lt;meta-data
      *      android:name="android.app.extra.PROVISIONING_DISCLAIMER_CONTENT"
      *      android:resource="@string/disclaimer_content"
      * /&gt;</pre>
+     *
+     * <p>This must be accompanied with another extra using the key
+     * {@link #EXTRA_PROVISIONING_DISCLAIMER_HEADER}.
      */
     public static final String EXTRA_PROVISIONING_DISCLAIMER_CONTENT =
             "android.app.extra.PROVISIONING_DISCLAIMER_CONTENT";
 
     /**
-     * A boolean extra indicating if the user consent steps from the provisioning flow should be
-     * skipped. If unspecified, defaults to {@code false}.
+     * A boolean extra indicating if the user consent steps from the
+     * <a href="#managed-provisioning">provisioning flow</a> should be skipped.
      *
-     * It can only be used by an existing device owner trying to create a managed profile via
-     * {@link #ACTION_PROVISION_MANAGED_PROFILE}. Otherwise it is ignored.
+     * <p>If unspecified, defaults to {@code false}.
      *
      * @deprecated this extra is no longer relevant as device owners cannot create managed profiles
      */
@@ -7055,9 +7160,10 @@
     public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0;
 
     /**
-     * Disable all keyguard widgets. Has no effect starting from
-     * {@link android.os.Build.VERSION_CODES#LOLLIPOP} since keyguard widget is only supported
-     * on Android versions lower than 5.0.
+     * Disable all keyguard widgets. Has no effect between {@link
+     * android.os.Build.VERSION_CODES#LOLLIPOP} and {@link
+     * android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} (both inclusive), since keyguard widget is
+     * only supported on Android versions lower than 5.0 and versions higher than 14.
      */
     public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0;
 
@@ -7156,7 +7262,8 @@
     public static final int ORG_OWNED_PROFILE_KEYGUARD_FEATURES_PARENT_ONLY =
             DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
                     | DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
-                    | DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL;
+                    | DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+                    | DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL;
 
     /**
      * Keyguard features that when set on a normal or organization-owned managed profile, have
@@ -8977,6 +9084,10 @@
      * by applications in the managed profile.
      * </ul>
      * <p>
+     * From version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}, the profile owner of a
+     * managed profile can also set {@link #KEYGUARD_DISABLE_WIDGETS_ALL} which disables keyguard
+     * widgets for the managed profile.
+     * <p>
      * From version {@link android.os.Build.VERSION_CODES#R} the profile owner of an
      * organization-owned managed profile can set:
      * <ul>
@@ -8985,6 +9096,12 @@
      * <li>{@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS} which affects the parent user when called
      * on the parent profile.
      * </ul>
+     * Starting from version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} the profile
+     * owner of an organization-owned managed profile can set:
+     * <ul>
+     * <li>{@link #KEYGUARD_DISABLE_WIDGETS_ALL} which affects the parent user when called on the
+     * parent profile.
+     * </ul>
      * {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, {@link #KEYGUARD_DISABLE_FINGERPRINT},
      * {@link #KEYGUARD_DISABLE_FACE}, {@link #KEYGUARD_DISABLE_IRIS},
      * {@link #KEYGUARD_DISABLE_SECURE_CAMERA} and {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS}
@@ -10284,6 +10401,16 @@
      * get the list of app restrictions set by each admin via
      * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin}.
      *
+     * <p>Starting from Android Version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
+     * the device policy management role holder can also set app restrictions on any applications
+     * in the calling user, as well as the parent user of an organization-owned managed profile via
+     * the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)}. App restrictions set by the device policy
+     * management role holder are not returned by
+     * {@link UserManager#getApplicationRestrictions(String)}. The target application should use
+     * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} to retrieve
+     * them, alongside any app restrictions the profile or device owner might have set.
+     *
      * <p>NOTE: The method performs disk I/O and shouldn't be called on the main thread
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
@@ -10299,11 +10426,14 @@
     @WorkerThread
     public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
             Bundle settings) {
-        throwIfParentInstance("setApplicationRestrictions");
+        if (!Flags.dmrhCanSetAppRestriction()) {
+            throwIfParentInstance("setApplicationRestrictions");
+        }
+
         if (mService != null) {
             try {
                 mService.setApplicationRestrictions(admin, mContext.getPackageName(), packageName,
-                        settings);
+                        settings, mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11704,11 +11834,14 @@
     @WorkerThread
     public @NonNull Bundle getApplicationRestrictions(
             @Nullable ComponentName admin, String packageName) {
-        throwIfParentInstance("getApplicationRestrictions");
+        if (!Flags.dmrhCanSetAppRestriction()) {
+            throwIfParentInstance("getApplicationRestrictions");
+        }
+
         if (mService != null) {
             try {
                 return mService.getApplicationRestrictions(admin, mContext.getPackageName(),
-                        packageName);
+                        packageName, mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -13986,8 +14119,15 @@
     public @NonNull DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
         throwIfParentInstance("getParentProfileInstance");
         try {
-            if (!mService.isManagedProfile(admin)) {
-                throw new SecurityException("The current user does not have a parent profile.");
+            if (Flags.dmrhCanSetAppRestriction()) {
+                UserManager um = mContext.getSystemService(UserManager.class);
+                if (!um.isManagedProfile()) {
+                    throw new SecurityException("The current user does not have a parent profile.");
+                }
+            } else {
+                if (!mService.isManagedProfile(admin)) {
+                    throw new SecurityException("The current user does not have a parent profile.");
+                }
             }
             return new DevicePolicyManager(mContext, mService, true);
         } catch (RemoteException e) {
@@ -17537,6 +17677,48 @@
     }
 
     /**
+     * Force sets the maximum storage size allowed for policies associated with an admin regardless
+     * of the default value set in the system, unlike {@link #setMaxPolicyStorageLimit} which can
+     * only set it to a value higher than the default value set by the system.Setting a limit of -1
+     * effectively removes any storage restrictions.
+     *
+     * @param storageLimit Maximum storage allowed in bytes. Use -1 to disable limits.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT)
+    @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_INTERNAL_BUG_FIX_ENABLED)
+    public void forceSetMaxPolicyStorageLimit(int storageLimit) {
+        if (mService != null) {
+            try {
+                mService.forceSetMaxPolicyStorageLimit(mContext.getPackageName(), storageLimit);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Retrieves the size of the current policies set by the {@code admin}.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT)
+    @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_INTERNAL_BUG_FIX_ENABLED)
+    public int getPolicySizeForAdmin(@NonNull EnforcingAdmin admin) {
+        if (mService != null) {
+            try {
+                return mService.getPolicySizeForAdmin(mContext.getPackageName(), admin);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return -1;
+    }
+
+    /**
      * @return The headless device owner mode for the current set DO, returns
      * {@link DeviceAdminInfo#HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED} if no DO is set.
      *
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 1aee9fe..a9f2d74 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -317,11 +317,6 @@
     public abstract boolean isUserOrganizationManaged(@UserIdInt int userId);
 
     /**
-     * Returns whether the application exemptions feature flag is enabled.
-     */
-    public abstract boolean isApplicationExemptionsFlagEnabled();
-
-    /**
      * Returns a map of admin to {@link Bundle} map of restrictions set by the admins for the
      * provided {@code packageName} in the provided {@code userId}
      */
diff --git a/core/java/android/app/admin/EnforcingAdmin.java b/core/java/android/app/admin/EnforcingAdmin.java
index 7c718f6..f70a53f 100644
--- a/core/java/android/app/admin/EnforcingAdmin.java
+++ b/core/java/android/app/admin/EnforcingAdmin.java
@@ -16,9 +16,13 @@
 
 package android.app.admin;
 
+import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_INTERNAL_BUG_FIX_ENABLED;
+
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -60,6 +64,8 @@
      *
      * @hide
      */
+    @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_INTERNAL_BUG_FIX_ENABLED)
+    @TestApi
     public EnforcingAdmin(
             @NonNull String packageName, @NonNull Authority authority,
             @NonNull UserHandle userHandle, @Nullable ComponentName componentName) {
@@ -101,6 +107,16 @@
         return mUserHandle;
     }
 
+    /**
+     * Returns the {@link ComponentName} of the admin if applicable.
+     *
+     * @hide
+     */
+    @Nullable
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
     @Override
     public boolean equals(@Nullable Object o) {
         if (this == o) return true;
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d4589dc..d183713 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -244,8 +244,8 @@
     void setDefaultSmsApplication(in ComponentName admin, String callerPackageName, String packageName, boolean parent);
     void setDefaultDialerApplication(String packageName);
 
-    void setApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName, in Bundle settings);
-    Bundle getApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName);
+    void setApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName, in Bundle settings, in boolean parent);
+    Bundle getApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName, in boolean parent);
     boolean setApplicationRestrictionsManagingPackage(in ComponentName admin, in String packageName);
     String getApplicationRestrictionsManagingPackage(in ComponentName admin);
     boolean isCallerApplicationRestrictionsManagingPackage(in String callerPackage);
@@ -623,8 +623,10 @@
 
     int[] getSubscriptionIds(String callerPackageName);
 
-    void setMaxPolicyStorageLimit(String packageName, int storageLimit);
-    int getMaxPolicyStorageLimit(String packageName);
+    void setMaxPolicyStorageLimit(String callerPackageName, int storageLimit);
+    void forceSetMaxPolicyStorageLimit(String callerPackageName, int storageLimit);
+    int getMaxPolicyStorageLimit(String callerPackageName);
+    int getPolicySizeForAdmin(String callerPackageName, in EnforcingAdmin admin);
 
     int getHeadlessDeviceOwnerMode(String callerPackageName);
 }
diff --git a/core/java/android/app/admin/LockTaskPolicy.java b/core/java/android/app/admin/LockTaskPolicy.java
index a36ea05..68b4ad8 100644
--- a/core/java/android/app/admin/LockTaskPolicy.java
+++ b/core/java/android/app/admin/LockTaskPolicy.java
@@ -135,7 +135,7 @@
     }
 
     private void setPackagesInternal(Set<String> packages) {
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             for (String p : packages) {
                 PolicySizeVerifier.enforceMaxPackageNameLength(p);
             }
diff --git a/core/java/android/app/admin/PackagePermissionPolicyKey.java b/core/java/android/app/admin/PackagePermissionPolicyKey.java
index 389585f..1a04f6c 100644
--- a/core/java/android/app/admin/PackagePermissionPolicyKey.java
+++ b/core/java/android/app/admin/PackagePermissionPolicyKey.java
@@ -59,7 +59,7 @@
     public PackagePermissionPolicyKey(@NonNull String identifier, @NonNull String packageName,
             @NonNull String permissionName) {
         super(identifier);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxPackageNameLength(packageName);
             PolicySizeVerifier.enforceMaxStringLength(permissionName, "permissionName");
         }
diff --git a/core/java/android/app/admin/PackagePolicyKey.java b/core/java/android/app/admin/PackagePolicyKey.java
index 68dc797..9e31a23 100644
--- a/core/java/android/app/admin/PackagePolicyKey.java
+++ b/core/java/android/app/admin/PackagePolicyKey.java
@@ -55,7 +55,7 @@
     @TestApi
     public PackagePolicyKey(@NonNull String key, @NonNull String packageName) {
         super(key);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxPackageNameLength(packageName);
         }
         mPackageName = Objects.requireNonNull((packageName));
diff --git a/core/java/android/app/admin/Provisioning_OWNERS b/core/java/android/app/admin/Provisioning_OWNERS
index 8f71fc0..91b9761 100644
--- a/core/java/android/app/admin/Provisioning_OWNERS
+++ b/core/java/android/app/admin/Provisioning_OWNERS
@@ -1,4 +1,4 @@
 # Assign bugs to [email protected]
 [email protected]
[email protected] #{LAST_RESORT_SUGGESTION}
[email protected] #{LAST_RESORT_SUGGESTION}
 file:EnterprisePlatform_OWNERS
diff --git a/core/java/android/app/admin/StringPolicyValue.java b/core/java/android/app/admin/StringPolicyValue.java
index 8995c0f..6efe9ad 100644
--- a/core/java/android/app/admin/StringPolicyValue.java
+++ b/core/java/android/app/admin/StringPolicyValue.java
@@ -30,7 +30,7 @@
 
     public StringPolicyValue(@NonNull String value) {
         super(value);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxStringLength(value, "policyValue");
         }
     }
diff --git a/core/java/android/app/admin/StringSetPolicyValue.java b/core/java/android/app/admin/StringSetPolicyValue.java
index f37dfee..12b11f4 100644
--- a/core/java/android/app/admin/StringSetPolicyValue.java
+++ b/core/java/android/app/admin/StringSetPolicyValue.java
@@ -32,7 +32,7 @@
 
     public StringSetPolicyValue(@NonNull Set<String> value) {
         super(value);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             for (String str : value) {
                 PolicySizeVerifier.enforceMaxStringLength(str, "policyValue");
             }
diff --git a/core/java/android/app/admin/UserRestrictionPolicyKey.java b/core/java/android/app/admin/UserRestrictionPolicyKey.java
index ee90ccd..9054287 100644
--- a/core/java/android/app/admin/UserRestrictionPolicyKey.java
+++ b/core/java/android/app/admin/UserRestrictionPolicyKey.java
@@ -45,7 +45,7 @@
     @TestApi
     public UserRestrictionPolicyKey(@NonNull String identifier, @NonNull String restriction) {
         super(identifier);
-        if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxStringLength(restriction, "restriction");
         }
         mRestriction = Objects.requireNonNull(restriction);
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 6b2baa7..31c9a258 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -28,6 +28,17 @@
 }
 
 flag {
+  name: "device_policy_size_tracking_internal_bug_fix_enabled"
+  namespace: "enterprise"
+  description: "Bug fix for tracking the total policy size and have a max threshold"
+  bug: "281543351"
+  metadata {
+      purpose: PURPOSE_BUGFIX
+  }
+}
+
+
+flag {
   name: "onboarding_bugreport_v2_enabled"
   is_exported: true
   namespace: "enterprise"
@@ -185,6 +196,25 @@
   }
 }
 
+flag {
+  name: "power_exemption_bg_usage_fix"
+  namespace: "enterprise"
+  description: "Ensure aps with EXEMPT_FROM_POWER_RESTRICTIONS can execute in the background"
+  bug: "333379020"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+  name: "disallow_user_control_bg_usage_fix"
+  namespace: "enterprise"
+  description: "Make DPM.setUserControlDisabledPackages() ensure background usage is allowed"
+  bug: "326031059"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
 
 flag {
   name: "esim_management_ux_enabled"
@@ -204,6 +234,13 @@
 }
 
 flag {
+  name: "dmrh_can_set_app_restriction"
+  namespace: "enterprise"
+  description: "Allow DMRH to set application restrictions (both on the profile and the parent)"
+  bug: "328758346"
+}
+
+flag {
   name: "allow_screen_brightness_control_on_cope"
   namespace: "enterprise"
   description: "Allow COPE admin to control screen brightness and timeout."
@@ -211,6 +248,16 @@
 }
 
 flag {
+  name: "always_persist_do"
+  namespace: "enterprise"
+  description: "Always write device_owners2.xml so that migration flags aren't lost"
+  bug: "335232744"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "is_recursive_required_app_merging_enabled"
   namespace: "enterprise"
   description: "Guards a new flow for recursive required enterprise app list merging"
@@ -226,3 +273,23 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+    name: "headless_single_user_bad_device_admin_state_fix"
+    namespace: "enterprise"
+    description: "Fix the bad state in DPMS caused by an earlier bug related to the headless single user change"
+    bug: "332477138"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    name: "headless_single_user_fixes"
+    namespace: "enterprise"
+    description: "Various fixes for headless single user mode"
+    bug: "289515470"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 7548562..508077e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -2655,13 +2655,12 @@
             );
         }
         GetCredentialRequest getCredentialRequest = node.getPendingCredentialRequest();
-        if (getCredentialRequest == null) {
-            Log.i(TAG, prefix + " No Credential Manager Request");
-        } else {
-            Log.i(TAG, prefix + "  GetCredentialRequest: no. of options= "
-                    + getCredentialRequest.getCredentialOptions().size()
-            );
-        }
+        Log.i(TAG, prefix + "  Credential Manager info:"
+                + " hasCredentialManagerRequest=" + (getCredentialRequest != null)
+                + (getCredentialRequest != null
+                        ? ", sizeOfOptions=" + getCredentialRequest.getCredentialOptions().size()
+                        : "")
+        );
 
         final int NCHILDREN = node.getChildCount();
         if (NCHILDREN > 0) {
diff --git a/core/java/android/app/contextualsearch/CallbackToken.java b/core/java/android/app/contextualsearch/CallbackToken.java
index 378193f..94cdc73 100644
--- a/core/java/android/app/contextualsearch/CallbackToken.java
+++ b/core/java/android/app/contextualsearch/CallbackToken.java
@@ -68,6 +68,8 @@
      * invocations of this method will result in {@link OutcomeReceiver#onError} being called with
      * an {@link IllegalAccessException}.
      *
+     * Note that the callback could be invoked multiple times, e.g. in the case of split screen.
+     *
      * @param executor The executor which will be used to invoke the callback.
      * @param callback The callback which will be used to return {@link ContextualSearchState}
      *                 if/when it is available via {@link OutcomeReceiver#onResult}. It will also be
diff --git a/core/java/android/app/contextualsearch/ContextualSearchManager.java b/core/java/android/app/contextualsearch/ContextualSearchManager.java
index c080a6b..cfbe741 100644
--- a/core/java/android/app/contextualsearch/ContextualSearchManager.java
+++ b/core/java/android/app/contextualsearch/ContextualSearchManager.java
@@ -27,6 +27,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.util.Log;
 
 import java.lang.annotation.Retention;
@@ -51,6 +52,7 @@
      */
     public static final String EXTRA_ENTRYPOINT =
             "android.app.contextualsearch.extra.ENTRYPOINT";
+
     /**
      * Key to get the flag_secure value from the extras of the activity launched by contextual
      * search. The value will be true if flag_secure is found in any of the visible activities.
@@ -58,12 +60,14 @@
      */
     public static final String EXTRA_FLAG_SECURE_FOUND =
             "android.app.contextualsearch.extra.FLAG_SECURE_FOUND";
+
     /**
      * Key to get the screenshot from the extras of the activity launched by contextual search.
      * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
      */
     public static final String EXTRA_SCREENSHOT =
             "android.app.contextualsearch.extra.SCREENSHOT";
+
     /**
      * Key to check whether managed profile is visible from the extras of the activity launched by
      * contextual search. The value will be true if any one of the visible apps is managed.
@@ -71,6 +75,7 @@
      */
     public static final String EXTRA_IS_MANAGED_PROFILE_VISIBLE =
             "android.app.contextualsearch.extra.IS_MANAGED_PROFILE_VISIBLE";
+
     /**
      * Key to get the list of visible packages from the extras of the activity launched by
      * contextual search.
@@ -80,6 +85,18 @@
             "android.app.contextualsearch.extra.VISIBLE_PACKAGE_NAMES";
 
     /**
+     * Key to get the time the user made the invocation request, based on
+     * {@link SystemClock#uptimeMillis()}.
+     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * TODO: un-hide in W
+     *
+     * @hide
+     */
+    public static final String EXTRA_INVOCATION_TIME_MS =
+            "android.app.contextualsearch.extra.INVOCATION_TIME_MS";
+
+    /**
      * Key to get the binder token from the extras of the activity launched by contextual search.
      * This token is needed to invoke {@link CallbackToken#getContextualSearchState} method.
      * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index 0082732..e694ccc 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -1,6 +1,10 @@
 package: "android.app"
 container: "system"
 
+# Note: When adding a new flag here, consider including the word "notification(s)" in the flag name
+# when appropriate, as it's not currently part of the namespace so it may not be obvious what the
+# flag relates to.
+
 flag {
   name: "modes_api"
   is_exported: true
@@ -42,6 +46,13 @@
 }
 
 flag {
+  name: "notifications_use_app_icon"
+  namespace: "systemui"
+  description: "Experiment to replace the small icon in a notification with the app icon."
+  bug: "335211019"
+}
+
+flag {
   name: "keyguard_private_notifications"
   namespace: "systemui"
   description: "Fixes the behavior of KeyguardManager#setPrivateNotificationsAllowed()"
@@ -75,6 +86,16 @@
 }
 
 flag {
+  name: "secure_allowlist_token"
+  namespace: "systemui"
+  description: "Prevents allowlist_token from leaking out and foreign tokens from being accepted"
+  bug: "328254922"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "update_ranking_time"
   namespace: "systemui"
   description: "Updates notification sorting criteria to highlight new content while maintaining stability"
@@ -110,4 +131,11 @@
   namespace: "systemui"
   description: "No notifs can use USAGE_UNKNOWN or USAGE_MEDIA"
   bug: "331793339"
+}
+
+flag {
+  name: "clean_up_spans_and_new_lines"
+  namespace: "systemui"
+  description: "Cleans up spans and unnecessary new lines from standard notification templates"
+  bug: "313439845"
 }
\ No newline at end of file
diff --git a/core/java/android/app/ondeviceintelligence/Feature.java b/core/java/android/app/ondeviceintelligence/Feature.java
index fd0379a..bcc56073 100644
--- a/core/java/android/app/ondeviceintelligence/Feature.java
+++ b/core/java/android/app/ondeviceintelligence/Feature.java
@@ -137,8 +137,8 @@
         if (mModelName != null) flg |= 0x4;
         dest.writeByte(flg);
         dest.writeInt(mId);
-        if (mName != null) dest.writeString8(mName);
-        if (mModelName != null) dest.writeString8(mModelName);
+        if (mName != null) dest.writeString(mName);
+        if (mModelName != null) dest.writeString(mModelName);
         dest.writeInt(mType);
         dest.writeInt(mVariant);
         dest.writeTypedObject(mFeatureParams, flags);
diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
index 6317725..11d7ff8 100644
--- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
@@ -23,7 +23,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.os.IBinder;
@@ -60,12 +59,6 @@
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        return client.getActivity(getActivityToken());
-    }
-
     // ObjectPoolItem implementation
 
     private ActivityConfigurationChangeItem() {}
diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
index 6da871a..45bf235 100644
--- a/core/java/android/app/servertransaction/ActivityRelaunchItem.java
+++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
@@ -23,7 +23,6 @@
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
 import android.app.ResultInfo;
-import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -88,12 +87,6 @@
         client.reportRelaunch(r);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        return client.getActivity(getActivityToken());
-    }
-
     // ObjectPoolItem implementation
 
     private ActivityRelaunchItem() {}
diff --git a/core/java/android/app/servertransaction/ClientTransactionItem.java b/core/java/android/app/servertransaction/ClientTransactionItem.java
index a8d61db..99ebe1b 100644
--- a/core/java/android/app/servertransaction/ClientTransactionItem.java
+++ b/core/java/android/app/servertransaction/ClientTransactionItem.java
@@ -24,7 +24,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
 import android.os.IBinder;
 import android.os.Parcelable;
 
@@ -54,15 +53,6 @@
     }
 
     /**
-     * If this {@link ClientTransactionItem} is updating configuration, returns the {@link Context}
-     * it is updating; otherwise, returns {@code null}.
-     */
-    @Nullable
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        return null;
-    }
-
-    /**
      * Returns the activity token if this transaction item is activity-targeting. Otherwise,
      * returns {@code null}.
      */
diff --git a/core/java/android/app/servertransaction/ClientTransactionListenerController.java b/core/java/android/app/servertransaction/ClientTransactionListenerController.java
index c55b0f1..cda2867 100644
--- a/core/java/android/app/servertransaction/ClientTransactionListenerController.java
+++ b/core/java/android/app/servertransaction/ClientTransactionListenerController.java
@@ -16,6 +16,9 @@
 
 package android.app.servertransaction;
 
+import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay;
+import static android.view.Display.INVALID_DISPLAY;
+
 import static com.android.window.flags.Flags.activityWindowInfoFlag;
 import static com.android.window.flags.Flags.bundleClientTransactionFlag;
 
@@ -24,8 +27,11 @@
 import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.ActivityThread;
+import android.content.Context;
+import android.content.res.Configuration;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.IBinder;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.window.ActivityWindowInfo;
 
@@ -51,6 +57,17 @@
     private final ArraySet<BiConsumer<IBinder, ActivityWindowInfo>>
             mActivityWindowInfoChangedListeners = new ArraySet<>();
 
+    /**
+     * Keeps track of the Context whose Configuration will get updated, mapping to the config before
+     * the change.
+     */
+    @GuardedBy("mLock")
+    private final ArrayMap<Context, Configuration> mContextToPreChangedConfigMap = new ArrayMap<>();
+
+    /** Whether there is an {@link ClientTransaction} being executed. */
+    @GuardedBy("mLock")
+    private boolean mIsClientTransactionExecuting;
+
     /** Gets the singleton controller. */
     @NonNull
     public static ClientTransactionListenerController getInstance() {
@@ -126,18 +143,101 @@
         }
     }
 
-    /**
-     * Called when receives a {@link ClientTransaction} that is updating display-related
-     * window configuration.
-     */
-    public void onDisplayChanged(int displayId) {
-        if (!bundleClientTransactionFlag()) {
-            return;
+    /** Called when starts executing a remote {@link ClientTransaction}. */
+    public void onClientTransactionStarted() {
+        synchronized (mLock) {
+            mIsClientTransactionExecuting = true;
         }
-        if (ActivityThread.isSystem()) {
+    }
+
+    /** Called when finishes executing a remote {@link ClientTransaction}. */
+    public void onClientTransactionFinished() {
+        final ArraySet<Integer> configUpdatedDisplayIds;
+        synchronized (mLock) {
+            mIsClientTransactionExecuting = false;
+
+            // When {@link Configuration} is changed, we want to trigger display change callback as
+            // well, because Display reads some fields from {@link Configuration}.
+            if (mContextToPreChangedConfigMap.isEmpty()) {
+                return;
+            }
+
+            // Calculate display ids that have config changed.
+            configUpdatedDisplayIds = new ArraySet<>();
+            final int contextCount = mContextToPreChangedConfigMap.size();
+            try {
+                for (int i = 0; i < contextCount; i++) {
+                    final Context context = mContextToPreChangedConfigMap.keyAt(i);
+                    final Configuration preChangedConfig = mContextToPreChangedConfigMap.valueAt(i);
+                    if (shouldReportDisplayChange(context, preChangedConfig)) {
+                        configUpdatedDisplayIds.add(context.getDisplayId());
+                    }
+                }
+            } finally {
+                mContextToPreChangedConfigMap.clear();
+            }
+        }
+
+        // Dispatch the display changed callbacks.
+        final int displayCount = configUpdatedDisplayIds.size();
+        for (int i = 0; i < displayCount; i++) {
+            final int displayId = configUpdatedDisplayIds.valueAt(i);
+            onDisplayChanged(displayId);
+        }
+    }
+
+    /** Called before updating the Configuration of the given {@code context}. */
+    public void onContextConfigurationPreChanged(@NonNull Context context) {
+        if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
             // Not enable for system server.
             return;
         }
+        synchronized (mLock) {
+            if (mContextToPreChangedConfigMap.containsKey(context)) {
+                // There is an earlier change that hasn't been reported yet.
+                return;
+            }
+            mContextToPreChangedConfigMap.put(context,
+                    new Configuration(context.getResources().getConfiguration()));
+        }
+    }
+
+    /** Called after updating the Configuration of the given {@code context}. */
+    public void onContextConfigurationPostChanged(@NonNull Context context) {
+        if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
+            // Not enable for system server.
+            return;
+        }
+        int changedDisplayId = INVALID_DISPLAY;
+        synchronized (mLock) {
+            if (mIsClientTransactionExecuting) {
+                // Wait until #onClientTransactionFinished to prevent it from triggering the same
+                // #onDisplayChanged multiple times within the same ClientTransaction.
+                return;
+            }
+            final Configuration preChangedConfig = mContextToPreChangedConfigMap.remove(context);
+            if (preChangedConfig != null && shouldReportDisplayChange(context, preChangedConfig)) {
+                changedDisplayId = context.getDisplayId();
+            }
+        }
+
+        if (changedDisplayId != INVALID_DISPLAY) {
+            onDisplayChanged(changedDisplayId);
+        }
+    }
+
+    private boolean shouldReportDisplayChange(@NonNull Context context,
+            @NonNull Configuration preChangedConfig) {
+        final Configuration postChangedConfig = context.getResources().getConfiguration();
+        return !areConfigurationsEqualForDisplay(postChangedConfig, preChangedConfig);
+    }
+
+    /**
+     * Called when receives a {@link Configuration} changed event that is updating display-related
+     * window configuration.
+     */
+    @VisibleForTesting
+    public void onDisplayChanged(int displayId) {
         mDisplayManager.handleDisplayChangeFromWindowManager(displayId);
     }
 }
diff --git a/core/java/android/app/servertransaction/ConfigurationChangeItem.java b/core/java/android/app/servertransaction/ConfigurationChangeItem.java
index 0e327a7..22da706 100644
--- a/core/java/android/app/servertransaction/ConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ConfigurationChangeItem.java
@@ -18,9 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityThread;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.os.Parcel;
@@ -48,12 +46,6 @@
         client.handleConfigurationChanged(mConfiguration, mDeviceId);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        return ActivityThread.currentApplication();
-    }
-
     // ObjectPoolItem implementation
 
     private ConfigurationChangeItem() {}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index f02cb21..7dcbeba 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -24,14 +24,12 @@
 import android.annotation.Nullable;
 import android.app.ActivityClient;
 import android.app.ActivityOptions.SceneTransitionInfo;
-import android.app.ActivityThread;
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
 import android.app.IActivityClientController;
 import android.app.ProfilerInfo;
 import android.app.ResultInfo;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.res.CompatibilityInfo;
@@ -121,13 +119,6 @@
         client.countLaunchingActivities(-1);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        // LaunchActivityItem may update the global config with #mCurConfig.
-        return ActivityThread.currentApplication();
-    }
-
     // ObjectPoolItem implementation
 
     private LaunchActivityItem() {}
diff --git a/core/java/android/app/servertransaction/MoveToDisplayItem.java b/core/java/android/app/servertransaction/MoveToDisplayItem.java
index 0702c45..8706edd 100644
--- a/core/java/android/app/servertransaction/MoveToDisplayItem.java
+++ b/core/java/android/app/servertransaction/MoveToDisplayItem.java
@@ -22,7 +22,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.os.IBinder;
@@ -59,12 +58,6 @@
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        return client.getActivity(getActivityToken());
-    }
-
     // ObjectPoolItem implementation
 
     private MoveToDisplayItem() {}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index c837191..480205e 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -16,7 +16,6 @@
 
 package android.app.servertransaction;
 
-import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -32,17 +31,12 @@
 import static android.app.servertransaction.TransactionExecutorHelper.tId;
 import static android.app.servertransaction.TransactionExecutorHelper.transactionToString;
 
-import static com.android.window.flags.Flags.bundleClientTransactionFlag;
-
 import android.annotation.NonNull;
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.os.IBinder;
 import android.os.Trace;
-import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.IntArray;
 import android.util.Slog;
 
@@ -63,12 +57,6 @@
     private final PendingTransactionActions mPendingActions = new PendingTransactionActions();
     private final TransactionExecutorHelper mHelper = new TransactionExecutorHelper();
 
-    /**
-     * Keeps track of the Context whose Configuration got updated within a transaction, mapping to
-     * the config before the transaction.
-     */
-    private final ArrayMap<Context, Configuration> mContextToPreChangedConfigMap = new ArrayMap<>();
-
     /** Initialize an instance with transaction handler, that will execute all requested actions. */
     public TransactionExecutor(@NonNull ClientTransactionHandler clientTransactionHandler) {
         mTransactionHandler = clientTransactionHandler;
@@ -104,37 +92,6 @@
             Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
         }
 
-        if (!mContextToPreChangedConfigMap.isEmpty()) {
-            // Whether this transaction should trigger DisplayListener#onDisplayChanged.
-            try {
-                // Calculate display ids that have config changed.
-                final ArraySet<Integer> configUpdatedDisplayIds = new ArraySet<>();
-                final int contextCount = mContextToPreChangedConfigMap.size();
-                for (int i = 0; i < contextCount; i++) {
-                    final Context context = mContextToPreChangedConfigMap.keyAt(i);
-                    final Configuration preTransactionConfig =
-                            mContextToPreChangedConfigMap.valueAt(i);
-                    final Configuration postTransactionConfig = context.getResources()
-                            .getConfiguration();
-                    if (!areConfigurationsEqualForDisplay(
-                            postTransactionConfig, preTransactionConfig)) {
-                        configUpdatedDisplayIds.add(context.getDisplayId());
-                    }
-                }
-
-                // Dispatch the display changed callbacks.
-                final ClientTransactionListenerController controller =
-                        ClientTransactionListenerController.getInstance();
-                final int displayCount = configUpdatedDisplayIds.size();
-                for (int i = 0; i < displayCount; i++) {
-                    final int displayId = configUpdatedDisplayIds.valueAt(i);
-                    controller.onDisplayChanged(displayId);
-                }
-            } finally {
-                mContextToPreChangedConfigMap.clear();
-            }
-        }
-
         mPendingActions.clear();
         if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
     }
@@ -214,20 +171,6 @@
             }
         }
 
-        final boolean shouldTrackConfigUpdatedContext =
-                // No configuration change for local transaction.
-                !mTransactionHandler.isExecutingLocalTransaction()
-                        && bundleClientTransactionFlag();
-        final Context configUpdatedContext = shouldTrackConfigUpdatedContext
-                ? item.getContextToUpdate(mTransactionHandler)
-                : null;
-        if (configUpdatedContext != null
-                && !mContextToPreChangedConfigMap.containsKey(configUpdatedContext)) {
-            // Keep track of the first pre-executed config of each changed Context.
-            mContextToPreChangedConfigMap.put(configUpdatedContext,
-                    new Configuration(configUpdatedContext.getResources().getConfiguration()));
-        }
-
         item.execute(mTransactionHandler, mPendingActions);
 
         item.postExecute(mTransactionHandler, mPendingActions);
diff --git a/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java
index cbad92f..f6a7291 100644
--- a/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java
+++ b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
 import android.content.res.Configuration;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -46,12 +45,6 @@
         client.handleWindowContextInfoChanged(mClientToken, mInfo);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        return client.getWindowContext(mClientToken);
-    }
-
     // ObjectPoolItem implementation
 
     private WindowContextInfoChangeItem() {}
diff --git a/core/java/android/app/servertransaction/WindowStateResizeItem.java b/core/java/android/app/servertransaction/WindowStateResizeItem.java
index 1817c5e..da99096 100644
--- a/core/java/android/app/servertransaction/WindowStateResizeItem.java
+++ b/core/java/android/app/servertransaction/WindowStateResizeItem.java
@@ -22,10 +22,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityThread;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
-import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.Trace;
@@ -59,10 +56,6 @@
 
     /** {@code null} if this is not an Activity window. */
     @Nullable
-    private IBinder mActivityToken;
-
-    /** {@code null} if this is not an Activity window. */
-    @Nullable
     private ActivityWindowInfo mActivityWindowInfo;
 
     @Override
@@ -86,14 +79,6 @@
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     }
 
-    @Nullable
-    @Override
-    public Context getContextToUpdate(@NonNull ClientTransactionHandler client) {
-        // TODO(b/260873529): dispatch for mActivityToken as well.
-        // WindowStateResizeItem may update the global config with #mConfiguration.
-        return ActivityThread.currentApplication();
-    }
-
     // ObjectPoolItem implementation
 
     private WindowStateResizeItem() {}
@@ -103,8 +88,7 @@
             @NonNull ClientWindowFrames frames, boolean reportDraw,
             @NonNull MergedConfiguration configuration, @NonNull InsetsState insetsState,
             boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, int syncSeqId,
-            boolean dragResizing, @Nullable IBinder activityToken,
-            @Nullable ActivityWindowInfo activityWindowInfo) {
+            boolean dragResizing, @Nullable ActivityWindowInfo activityWindowInfo) {
         WindowStateResizeItem instance =
                 ObjectPool.obtain(WindowStateResizeItem.class);
         if (instance == null) {
@@ -120,7 +104,6 @@
         instance.mDisplayId = displayId;
         instance.mSyncSeqId = syncSeqId;
         instance.mDragResizing = dragResizing;
-        instance.mActivityToken = activityToken;
         instance.mActivityWindowInfo = activityWindowInfo != null
                 ? new ActivityWindowInfo(activityWindowInfo)
                 : null;
@@ -140,7 +123,6 @@
         mDisplayId = INVALID_DISPLAY;
         mSyncSeqId = -1;
         mDragResizing = false;
-        mActivityToken = null;
         mActivityWindowInfo = null;
         ObjectPool.recycle(this);
     }
@@ -160,7 +142,6 @@
         dest.writeInt(mDisplayId);
         dest.writeInt(mSyncSeqId);
         dest.writeBoolean(mDragResizing);
-        dest.writeStrongBinder(mActivityToken);
         dest.writeTypedObject(mActivityWindowInfo, flags);
     }
 
@@ -176,7 +157,6 @@
         mDisplayId = in.readInt();
         mSyncSeqId = in.readInt();
         mDragResizing = in.readBoolean();
-        mActivityToken = in.readStrongBinder();
         mActivityWindowInfo = in.readTypedObject(ActivityWindowInfo.CREATOR);
     }
 
@@ -209,7 +189,6 @@
                 && mDisplayId == other.mDisplayId
                 && mSyncSeqId == other.mSyncSeqId
                 && mDragResizing == other.mDragResizing
-                && Objects.equals(mActivityToken, other.mActivityToken)
                 && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo);
     }
 
@@ -226,7 +205,6 @@
         result = 31 * result + mDisplayId;
         result = 31 * result + mSyncSeqId;
         result = 31 * result + (mDragResizing ? 1 : 0);
-        result = 31 * result + Objects.hashCode(mActivityToken);
         result = 31 * result + Objects.hashCode(mActivityWindowInfo);
         return result;
     }
@@ -236,7 +214,6 @@
         return "WindowStateResizeItem{window=" + mWindow
                 + ", reportDrawn=" + mReportDraw
                 + ", configuration=" + mConfiguration
-                + ", activityToken=" + mActivityToken
                 + ", activityWindowInfo=" + mActivityWindowInfo
                 + "}";
     }
diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig
index 3bcc7c7..374be6f 100644
--- a/core/java/android/appwidget/flags.aconfig
+++ b/core/java/android/appwidget/flags.aconfig
@@ -33,3 +33,10 @@
   description: "Enable support for transporting draw instructions as data parcel"
   bug: "286130467"
 }
+
+flag {
+  name: "throttle_widget_updates"
+  namespace: "app_widgets"
+  description: "Throttle the widget view updates to mitigate transaction exceptions"
+  bug: "326145514"
+}
diff --git a/core/java/android/companion/ObservingDevicePresenceRequest.java b/core/java/android/companion/ObservingDevicePresenceRequest.java
index f1d594e..11ea735 100644
--- a/core/java/android/companion/ObservingDevicePresenceRequest.java
+++ b/core/java/android/companion/ObservingDevicePresenceRequest.java
@@ -183,7 +183,11 @@
          * @param uuid The ParcelUuid for observing device presence.
          */
         @NonNull
-        @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE)
+        @RequiresPermission(allOf = {
+                android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE,
+                android.Manifest.permission.BLUETOOTH_CONNECT,
+                android.Manifest.permission.BLUETOOTH_SCAN
+        })
         public Builder setUuid(@NonNull ParcelUuid uuid) {
             checkNotUsed();
             this.mUuid = uuid;
diff --git a/core/java/android/companion/virtual/camera/VirtualCameraConfig.java b/core/java/android/companion/virtual/camera/VirtualCameraConfig.java
index 06a0f5c..769b658 100644
--- a/core/java/android/companion/virtual/camera/VirtualCameraConfig.java
+++ b/core/java/android/companion/virtual/camera/VirtualCameraConfig.java
@@ -237,19 +237,15 @@
                 @IntRange(from = 1) int height,
                 @ImageFormat.Format int format,
                 @IntRange(from = 1) int maximumFramesPerSecond) {
-            // TODO(b/310857519): Check dimension upper limits based on the maximum texture size
-            // supported by the current device, instead of hardcoded limits.
-            if (width <= 0 || width > VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT) {
+            if (width <= 0) {
                 throw new IllegalArgumentException(
                         "Invalid width passed for stream config: " + width
-                                + ", must be between 1 and "
-                                + VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT);
+                                + ", must be greater than 0");
             }
-            if (height <= 0 || height > VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT) {
+            if (height <= 0) {
                 throw new IllegalArgumentException(
                         "Invalid height passed for stream config: " + height
-                                + ", must be between 1 and "
-                                + VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT);
+                                + ", must be greater than 0");
             }
             if (!isFormatSupported(format)) {
                 throw new IllegalArgumentException(
diff --git a/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java b/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java
index 00a814e..6ab66b3 100644
--- a/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java
+++ b/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java
@@ -39,11 +39,6 @@
 public final class VirtualCameraStreamConfig implements Parcelable {
     // TODO(b/310857519): Check if we should increase the fps upper limit in future.
     static final int MAX_FPS_UPPER_LIMIT = 60;
-    // This is the minimum guaranteed upper bound of texture size supported by all devices.
-    // Keep this in sync with kMaxTextureSize from services/camera/virtualcamera/util/Util.cc
-    // TODO(b/310857519): Remove this once we add support for fetching the maximum texture size
-    // supported by the current device.
-    static final int DIMENSION_UPPER_LIMIT = 2048;
 
     private final int mWidth;
     private final int mHeight;
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 18c81a2..3e23762 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -117,3 +117,14 @@
   description: "Enable virtual stylus input"
   bug: "304829446"
 }
+
+flag {
+  name: "intercept_intents_before_applying_policy"
+  is_exported: true
+  namespace: "virtual_devices"
+  description: "Apply intent interception before applying activity policy"
+  bug: "333444131"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
\ No newline at end of file
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b706cae..bad73fc 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3256,6 +3256,14 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system can <a
+     * href="{@docRoot}develop/background-work/background-tasks/broadcasts#android-14">place
+     * context-registered broadcasts in a queue while the app is in the <a
+     * href="{@docRoot}guide/components/activities/process-lifecycle">cached state</a>.
+     * When the app leaves the cached state, such as returning to the
+     * foreground, the system delivers any queued broadcasts. Multiple instances
+     * of certain broadcasts might be merged into one broadcast.
+     *
      * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
      * registered with this method will correctly respect the
      * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
@@ -3301,6 +3309,14 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system can <a
+     * href="{@docRoot}develop/background-work/background-tasks/broadcasts#android-14">place
+     * context-registered broadcasts in a queue while the app is in the <a
+     * href="{@docRoot}guide/components/activities/process-lifecycle">cached state</a>.
+     * When the app leaves the cached state, such as returning to the
+     * foreground, the system delivers any queued broadcasts. Multiple instances
+     * of certain broadcasts might be merged into one broadcast.
+     *
      * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
      * registered with this method will correctly respect the
      * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
@@ -3342,6 +3358,14 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system can <a
+     * href="{@docRoot}develop/background-work/background-tasks/broadcasts#android-14">place
+     * context-registered broadcasts in a queue while the app is in the <a
+     * href="{@docRoot}guide/components/activities/process-lifecycle">cached state</a>.
+     * When the app leaves the cached state, such as returning to the
+     * foreground, the system delivers any queued broadcasts. Multiple instances
+     * of certain broadcasts might be merged into one broadcast.
+     *
      * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
      * registered with this method will correctly respect the
      * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
@@ -3385,6 +3409,14 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system can <a
+     * href="{@docRoot}develop/background-work/background-tasks/broadcasts#android-14">place
+     * context-registered broadcasts in a queue while the app is in the <a
+     * href="{@docRoot}guide/components/activities/process-lifecycle">cached state</a>.
+     * When the app leaves the cached state, such as returning to the
+     * foreground, the system delivers any queued broadcasts. Multiple instances
+     * of certain broadcasts might be merged into one broadcast.
+     *
      * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
      * registered with this method will correctly respect the
      * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index e290722..86d061c 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -21,6 +21,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.Overridable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.Flags;
 import android.net.Uri;
@@ -186,6 +189,18 @@
     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 the intent sender application targets V or higher.
+     *
+     * @hide
+     */
+    @ChangeId
+    @Disabled
+    @Overridable
+    public static final long BLOCK_NULL_ACTION_INTENTS = 293560872;
+
+    /**
      * 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
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 535cebb..7ac9547 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1548,6 +1548,26 @@
     public static final long INSETS_DECOUPLED_CONFIGURATION_ENFORCED = 151861875L;
 
     /**
+     * When enabled, the activity will receive configuration decoupled from system bar insets.
+     *
+     * <p>This will only apply if the activity is targeting SDK level 34 or earlier versions.
+     *
+     * <p>This will only in effect if the device is trying to provide a different value by default
+     * other than the legacy value, i.e., the
+     * {@code Flags.allowsScreenSizeDecoupledFromStatusBarAndCutout()} is set to true.
+     *
+     * <p>If the {@code Flags.insetsDecoupledConfiguration()} is also set to true, all apps
+     * targeting SDK level 35 or later, and apps with this override flag will receive the insets
+     * decoupled configuration.
+     *
+     * @hide
+     */
+    @ChangeId
+    @Disabled
+    @Overridable
+    public static final long OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION = 327313645L;
+
+    /**
      * Optional set of a certificates identifying apps that are allowed to embed this activity. From
      * the "knownActivityEmbeddingCerts" attribute.
      */
diff --git a/core/java/android/content/pm/UserProperties.java b/core/java/android/content/pm/UserProperties.java
index 9159929..1d4403c 100644
--- a/core/java/android/content/pm/UserProperties.java
+++ b/core/java/android/content/pm/UserProperties.java
@@ -887,7 +887,7 @@
      * <p> Setting this property to true will enable the user's CE storage to remain unlocked when
      * the user is stopped using
      * {@link com.android.server.am.ActivityManagerService#stopUserWithDelayedLocking(int,
-     * boolean, IStopUserCallback)}.
+     * IStopUserCallback)}.
      *
      * <p> When this property is false, delayed locking may still be applicable at a global
      * level for all users via the {@code config_multiuserDelayUserDataLocking}. That is, delayed
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 0c0da31..c57a3a6 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -113,6 +113,26 @@
     is_fixed_read_only: true
 }
 
+flag {
+    name: "fix_avatar_picker_read_back_order"
+    namespace: "multiuser"
+    description: "Talkback focus doesn't move to the 'If you change your Google Account picture…' after swiping next to move the focus from 'Choose a picture'"
+    bug: "330835921"
+    metadata {
+    	purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+    name: "fix_avatar_picker_selected_read_back"
+    namespace: "multiuser"
+    description: "Talkback doesn't announce 'selected' after double tapping the button in the picture list in 'Choose a picture' page."
+    bug: "330840549"
+    metadata {
+    	purpose: PURPOSE_BUGFIX
+  }
+}
+
 # This flag guards the private space feature and all its implementations excluding the APIs. APIs are guarded by android.os.Flags.allow_private_profile.
 flag {
     name: "enable_private_space_features"
@@ -172,6 +192,13 @@
 }
 
 flag {
+    name: "schedule_stop_of_background_user"
+    namespace: "multiuser"
+    description: "Schedule background users to be stopped at a future point."
+    bug: "330351042"
+}
+
+flag {
     name: "disable_private_space_items_on_home"
     namespace: "profile_experiences"
     description: "Disables adding items belonging to Private Space on Home Screen manually as well as automatically"
diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java
index 625d7cb..c7237ea 100644
--- a/core/java/android/content/res/FontScaleConverterFactory.java
+++ b/core/java/android/content/res/FontScaleConverterFactory.java
@@ -58,6 +58,16 @@
         synchronized (LOOKUP_TABLES_WRITE_LOCK) {
             putInto(
                     sLookupTables,
+                    /* scaleKey= */ 1.05f,
+                    new FontScaleConverterImpl(
+                            /* fromSp= */
+                            new float[] {   8f,   10f,   12f,   14f,   18f,   20f,   24f,   30f,  100},
+                            /* toDp=   */
+                            new float[] { 8.4f, 10.5f, 12.6f, 14.8f, 18.6f, 20.6f, 24.4f,   30f,  100})
+            );
+
+            putInto(
+                    sLookupTables,
                     /* scaleKey= */ 1.1f,
                     new FontScaleConverterImpl(
                             /* fromSp= */
@@ -78,6 +88,16 @@
 
             putInto(
                     sLookupTables,
+                    /* scaleKey= */ 1.2f,
+                    new FontScaleConverterImpl(
+                            /* fromSp= */
+                            new float[] {   8f,   10f,   12f,   14f,   18f,   20f,   24f,   30f,  100},
+                            /* toDp=   */
+                            new float[] { 9.6f,   12f, 14.4f, 17.2f, 20.4f, 22.4f, 25.6f,   30f,  100})
+            );
+
+            putInto(
+                    sLookupTables,
                     /* scaleKey= */ 1.3f,
                     new FontScaleConverterImpl(
                             /* fromSp= */
@@ -117,7 +137,7 @@
             );
         }
 
-        sMinScaleBeforeCurvesApplied = getScaleFromKey(sLookupTables.keyAt(0)) - 0.02f;
+        sMinScaleBeforeCurvesApplied = getScaleFromKey(sLookupTables.keyAt(0)) - 0.01f;
         if (sMinScaleBeforeCurvesApplied <= 1.0f) {
             throw new IllegalStateException(
                     "You should only apply non-linear scaling to font scales > 1"
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index 93fa5d8..481ff2e 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -61,7 +61,9 @@
 @SystemService(Context.CREDENTIAL_SERVICE)
 @RequiresFeature(PackageManager.FEATURE_CREDENTIALS)
 public final class CredentialManager {
-    private static final String TAG = "CredentialManager";
+    /** @hide **/
+    @Hide
+    public static final String TAG = "CredentialManager";
     private static final Bundle OPTIONS_SENDER_BAL_OPTIN = ActivityOptions.makeBasic()
             .setPendingIntentBackgroundActivityStartMode(
                     ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle();
@@ -132,6 +134,13 @@
             "enable_credential_description_api";
 
     /**
+     * @hide
+     */
+    @Hide
+    public static final String EXTRA_AUTOFILL_RESULT_RECEIVER =
+            "android.credentials.AUTOFILL_RESULT_RECEIVER";
+
+    /**
      * @hide instantiated by ContextImpl.
      */
     public CredentialManager(Context context, ICredentialManager service) {
diff --git a/core/java/android/credentials/selection/Constants.java b/core/java/android/credentials/selection/Constants.java
index 2229f25..a620621 100644
--- a/core/java/android/credentials/selection/Constants.java
+++ b/core/java/android/credentials/selection/Constants.java
@@ -28,12 +28,5 @@
      */
     public static final String EXTRA_RESULT_RECEIVER =
             "android.credentials.selection.extra.RESULT_RECEIVER";
-
-    /**
-     * The intent extra key for the final result receiver object
-     */
-    public static final String EXTRA_FINAL_RESPONSE_RECEIVER =
-            "android.credentials.selection.extra.FINAL_RESPONSE_RECEIVER";
-
     private Constants() {}
 }
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 2081ced..3c4307c 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -22,6 +22,7 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.OperationApplicationException;
+import android.database.sqlite.Flags;
 import android.database.sqlite.SQLiteAbortException;
 import android.database.sqlite.SQLiteConstraintException;
 import android.database.sqlite.SQLiteDatabase;
@@ -1609,7 +1610,7 @@
      * Comments either start with "--" and run to the end of the line or are C-style block
      * comments.  The function returns null if a prefix could not be found.
      */
-    private static String getSqlStatementPrefixExtended(String sql) {
+    private static String getSqlStatementPrefixExtendedRegex(String sql) {
         Matcher m = sPrefixPattern.matcher(sql);
         if (m.lookingAt()) {
             return m.group(PREFIX_GROUP_NUM).toUpperCase(Locale.ROOT);
@@ -1619,6 +1620,61 @@
     }
 
     /**
+     * Return the index of the first character past comments and whitespace.  -1 is returned if
+     * a comment is malformed.
+     */
+    private static int getSqlStatementPrefixOffset(String s) {
+        final int limit = s.length() - 2;
+        if (limit < 0) return -1;
+        int i = 0;
+        while (i < limit) {
+            final char c = s.charAt(i);
+            if (c <= ' ') {
+                // This behavior conforms to String.trim(), which is used by the legacy Android
+                // SQL prefix logic.  This test is not unicode-aware.  Notice that it accepts the
+                // null character as whitespace even though the null character will terminate the
+                // SQL string in native code.
+                i++;
+            } else if (c == '-') {
+                if (s.charAt(i+1) != '-') return i;
+                i = s.indexOf('\n', i+2);
+                if (i < 0) return -1;
+                i++;
+            } else if (c == '/') {
+                if (s.charAt(i+1) != '*') return i;
+                i++;
+                do {
+                    i = s.indexOf('*', i+1);
+                    if (i < 0) return -1;
+                    i++;
+                } while (s.charAt(i) != '/');
+                i++;
+            } else {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Scan past leading comments without using the Java regex routines.
+     */
+    private static String getSqlStatementPrefixExtendedNoRegex(String sql) {
+        int n = getSqlStatementPrefixOffset(sql);
+        if (n < 0) {
+            // Bad comment syntax.
+            return null;
+        }
+        final int end = sql.length();
+        if (n > end) {
+            // Bad scanning.  This indicates a programming error.
+            return null;
+        }
+        final int eos = Math.min(n+3, end);
+        return sql.substring(n, eos).toUpperCase(Locale.ROOT);
+    }
+
+    /**
      * Return the extended statement type for the SQL statement.  This is not a public API and it
      * can return values that are not publicly visible.
      * @hide
@@ -1663,11 +1719,15 @@
      * @hide
      */
     public static int getSqlStatementTypeExtended(@NonNull String sql) {
-        int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql);
-        if (type == STATEMENT_COMMENT) {
-            type = categorizeStatement(getSqlStatementPrefixExtended(sql), sql);
+        if (Flags.simpleSqlCommentScanner()) {
+            return categorizeStatement(getSqlStatementPrefixExtendedNoRegex(sql), sql);
+        } else {
+            int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql);
+            if (type == STATEMENT_COMMENT) {
+                type = categorizeStatement(getSqlStatementPrefixExtendedRegex(sql), sql);
+            }
+            return type;
         }
-        return type;
     }
 
     /**
diff --git a/core/java/android/database/sqlite/flags.aconfig b/core/java/android/database/sqlite/flags.aconfig
index 3073e25..285f984 100644
--- a/core/java/android/database/sqlite/flags.aconfig
+++ b/core/java/android/database/sqlite/flags.aconfig
@@ -17,3 +17,11 @@
      description: "Permit updates to TEMP tables in read-only transactions"
      bug: "317993835"
 }
+
+flag {
+     name: "simple_sql_comment_scanner"
+     namespace: "system_performance"
+     is_fixed_read_only: true
+     description: "Scan SQL comments by hand instead of with a regex"
+     bug: "329118560"
+}
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index a51a740..d9a18d7 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -42,12 +42,6 @@
 
     private static DdmHandleHello mInstance = new DdmHandleHello();
 
-    private static final String[] FRAMEWORK_FEATURES = new String[] {
-        "opengl-tracing",
-        "view-hierarchy",
-        "support_boot_stages"
-    };
-
     /* singleton, do not instantiate */
     private DdmHandleHello() {}
 
@@ -193,22 +187,25 @@
         if (false)
             Log.v("ddm-heap", "Got feature list request");
 
-        int size = 4 + 4 * (vmFeatures.length + FRAMEWORK_FEATURES.length);
-        for (int i = vmFeatures.length-1; i >= 0; i--)
+        String[] fmFeatures = Debug.getFeatureList();
+        int size = 4 + 4 * (vmFeatures.length + fmFeatures.length);
+        for (int i = vmFeatures.length - 1; i >= 0; i--) {
             size += vmFeatures[i].length() * 2;
-        for (int i = FRAMEWORK_FEATURES.length-1; i>= 0; i--)
-            size += FRAMEWORK_FEATURES[i].length() * 2;
+        }
+        for (int i = fmFeatures.length - 1; i >= 0; i--) {
+            size += fmFeatures[i].length() * 2;
+        }
 
         ByteBuffer out = ByteBuffer.allocate(size);
         out.order(ChunkHandler.CHUNK_ORDER);
-        out.putInt(vmFeatures.length + FRAMEWORK_FEATURES.length);
+        out.putInt(vmFeatures.length + fmFeatures.length);
         for (int i = vmFeatures.length-1; i >= 0; i--) {
             out.putInt(vmFeatures[i].length());
             putString(out, vmFeatures[i]);
         }
-        for (int i = FRAMEWORK_FEATURES.length-1; i >= 0; i--) {
-            out.putInt(FRAMEWORK_FEATURES[i].length());
-            putString(out, FRAMEWORK_FEATURES[i]);
+        for (int i = fmFeatures.length - 1; i >= 0; i--) {
+            out.putInt(fmFeatures[i].length());
+            putString(out, fmFeatures[i]);
         }
 
         return new Chunk(CHUNK_FEAT, out);
diff --git a/core/java/android/hardware/CameraSessionStats.java b/core/java/android/hardware/CameraSessionStats.java
index 32938ff..e5c12e3 100644
--- a/core/java/android/hardware/CameraSessionStats.java
+++ b/core/java/android/hardware/CameraSessionStats.java
@@ -16,9 +16,11 @@
 package android.hardware;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Range;
 
 import java.util.ArrayList;
 import java.util.List;
+
 /**
  * The camera action state used for passing camera usage information from
  * camera service to camera service proxy .
@@ -66,6 +68,7 @@
     private int mVideoStabilizationMode;
     private boolean mUsedUltraWide;
     private boolean mUsedZoomOverride;
+    private Range<Integer> mMostRequestedFpsRange;
     private int mSessionIndex;
     private CameraExtensionSessionStats mCameraExtensionSessionStats;
 
@@ -86,6 +89,7 @@
         mVideoStabilizationMode = -1;
         mUsedUltraWide = false;
         mUsedZoomOverride = false;
+        mMostRequestedFpsRange = new Range<Integer>(0, 0);
         mSessionIndex = 0;
         mCameraExtensionSessionStats = new CameraExtensionSessionStats();
     }
@@ -109,6 +113,7 @@
         mVideoStabilizationMode = -1;
         mUsedUltraWide = false;
         mUsedZoomOverride = false;
+        mMostRequestedFpsRange = new Range<Integer>(0, 0);
         mSessionIndex = sessionIdx;
         mCameraExtensionSessionStats = new CameraExtensionSessionStats();
     }
@@ -158,6 +163,8 @@
         dest.writeBoolean(mUsedZoomOverride);
         dest.writeInt(mSessionIndex);
         mCameraExtensionSessionStats.writeToParcel(dest, 0);
+        dest.writeInt(mMostRequestedFpsRange.getLower());
+        dest.writeInt(mMostRequestedFpsRange.getUpper());
     }
 
     public void readFromParcel(Parcel in) {
@@ -188,6 +195,9 @@
 
         mSessionIndex = in.readInt();
         mCameraExtensionSessionStats = CameraExtensionSessionStats.CREATOR.createFromParcel(in);
+        int minFps = in.readInt();
+        int maxFps = in.readInt();
+        mMostRequestedFpsRange = new Range<Integer>(minFps, maxFps);
     }
 
     public String getCameraId() {
@@ -273,4 +283,8 @@
     public CameraExtensionSessionStats getExtensionSessionStats() {
         return mCameraExtensionSessionStats;
     }
+
+    public Range<Integer> getMostRequestedFpsRange() {
+        return mMostRequestedFpsRange;
+    }
 }
diff --git a/core/java/android/hardware/OverlayProperties.java b/core/java/android/hardware/OverlayProperties.java
index 4a4d451..7b452a8 100644
--- a/core/java/android/hardware/OverlayProperties.java
+++ b/core/java/android/hardware/OverlayProperties.java
@@ -74,7 +74,7 @@
      * and {@link HardwareBuffer.Format} is supported on the device.
      *
      * @return True if the device can support efficiently compositing the content described by the
-     *         dataspace and format. False if GPOU composition fallback is otherwise required.
+     *         dataspace and format. False if GPU composition fallback is otherwise required.
      */
     @FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API)
     public boolean isCombinationSupported(@DataSpace.ColorDataSpace int dataspace,
@@ -135,7 +135,6 @@
 
     private static native long nGetDestructor();
     private static native long nCreateDefault();
-    private static native boolean nSupportFp16ForHdr(long nativeObject);
     private static native boolean nSupportMixedColorSpaces(long nativeObject);
     private static native boolean nIsCombinationSupported(
             long nativeObject, int dataspace, int format);
diff --git a/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl b/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl
index 1488cff..63e1895 100644
--- a/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl
+++ b/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl
@@ -15,7 +15,13 @@
  */
 package android.hardware.biometrics;
 
-import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 
 /**
  * Low-level callback interface between <Biometric>Manager and <Auth>Service. Allows core system
@@ -25,41 +31,44 @@
  */
 oneway interface AuthenticationStateListener {
     /**
-     * Defines behavior in response to authentication starting
-     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for requesting
-     * authentication starting
+     * Defines behavior in response to biometric authentication being acquired.
+     * @param authInfo information related to the biometric authentication acquired.
      */
-    void onAuthenticationStarted(int requestReason);
+    void onAuthenticationAcquired(in AuthenticationAcquiredInfo authInfo);
 
     /**
-     * Defines behavior in response to authentication stopping
+     * Defines behavior in response to an unrecoverable error encountered during authentication.
+     * @param authInfo information related to the unrecoverable auth error encountered
      */
-    void onAuthenticationStopped();
-
-    /**
-     * Defines behavior in response to a successful authentication
-     * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested
-     *                      authentication
-     * @param userId The user Id for the requested authentication
-     */
-    void onAuthenticationSucceeded(int requestReason, int userId);
+    void onAuthenticationError(in AuthenticationErrorInfo authInfo);
 
     /**
      * Defines behavior in response to a failed authentication
-     * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested
-     *                      authentication
-     * @param userId The user Id for the requested authentication
+     * @param authInfo information related to the failed authentication
      */
-    void onAuthenticationFailed(int requestReason, int userId);
+    void onAuthenticationFailed(in AuthenticationFailedInfo authInfo);
 
     /**
-     * Defines behavior in response to biometric being acquired.
-     * @param biometricSourceType identifies [BiometricSourceType] biometric was acquired for
-     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
-     * @param acquiredInfo [BiometricFingerprintConstants.FingerprintAcquired] int corresponding to
-     *                     a known acquired message.
+     * Defines behavior in response to a recoverable error encountered during authentication.
+     * @param authInfo information related to the recoverable auth error encountered
      */
-    void onAuthenticationAcquired(
-        in BiometricSourceType biometricSourceType, int requestReason, int acquiredInfo
-    );
+    void onAuthenticationHelp(in AuthenticationHelpInfo authInfo);
+
+    /**
+     * Defines behavior in response to authentication starting
+     * @param authInfo information related to the authentication starting
+     */
+    void onAuthenticationStarted(in AuthenticationStartedInfo authInfo);
+
+    /**
+     * Defines behavior in response to authentication stopping
+     * @param authInfo information related to the authentication stopping
+     */
+    void onAuthenticationStopped(in AuthenticationStoppedInfo authInfo);
+
+    /**
+     * Defines behavior in response to a successful authentication
+     * @param authInfo information related to the successful authentication
+     */
+    void onAuthenticationSucceeded(in AuthenticationSucceededInfo authInfo);
 }
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 770448b..fc72db3 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -221,7 +221,8 @@
             FINGERPRINT_ACQUIRED_IMMOBILE,
             FINGERPRINT_ACQUIRED_TOO_BRIGHT,
             FINGERPRINT_ACQUIRED_POWER_PRESSED,
-            FINGERPRINT_ACQUIRED_RE_ENROLL})
+            FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL,
+            FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED})
     @Retention(RetentionPolicy.SOURCE)
     @interface FingerprintAcquired {}
 
@@ -316,7 +317,13 @@
      * This message is sent to encourage the user to re-enroll their fingerprints.
      * @hide
      */
-    int FINGERPRINT_ACQUIRED_RE_ENROLL = 12;
+    int FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL = 12;
+
+    /**
+     * This message is sent to force the user to re-enroll their fingerprints.
+     * @hide
+     */
+    int FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED = 13;
 
     /**
      * @hide
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.aidl
new file mode 100644
index 0000000..2c9a55b
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationAcquiredInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.java
new file mode 100644
index 0000000..09b52d6
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information related to biometric authentication being acquired.
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationAcquiredInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+    /**
+     * {@link BiometricFaceConstants.FaceAcquired} or
+     * {@link BiometricFingerprintConstants.FingerprintAcquired} int corresponding to
+     * a known acquired message.
+     */
+    private final int mAcquiredInfo;
+
+
+
+    // 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/biometrics/events/AuthenticationAcquiredInfo.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 */ AuthenticationAcquiredInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason,
+            int acquiredInfo) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mAcquiredInfo = acquiredInfo;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    /**
+     * {@link BiometricFaceConstants.FaceAcquired} or
+     * {@link BiometricFingerprintConstants.FingerprintAcquired} int corresponding to
+     * a known acquired message.
+     */
+    @DataClass.Generated.Member
+    public int getAcquiredInfo() {
+        return mAcquiredInfo;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationAcquiredInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationAcquiredInfo that = (AuthenticationAcquiredInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason
+                && mAcquiredInfo == that.mAcquiredInfo;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        _hash = 31 * _hash + mAcquiredInfo;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+        dest.writeInt(mAcquiredInfo);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationAcquiredInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+        int acquiredInfo = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mAcquiredInfo = acquiredInfo;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationAcquiredInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationAcquiredInfo>() {
+        @Override
+        public AuthenticationAcquiredInfo[] newArray(int size) {
+            return new AuthenticationAcquiredInfo[size];
+        }
+
+        @Override
+        public AuthenticationAcquiredInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationAcquiredInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationAcquiredInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+        private int mAcquiredInfo;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         * @param acquiredInfo
+         *   {@link BiometricFaceConstants.FaceAcquired} or
+         *   {@link BiometricFingerprintConstants.FingerprintAcquired} int corresponding to
+         *   a known acquired message.
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason,
+                int acquiredInfo) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+            mAcquiredInfo = acquiredInfo;
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /**
+         * {@link BiometricFaceConstants.FaceAcquired} or
+         * {@link BiometricFingerprintConstants.FingerprintAcquired} int corresponding to
+         * a known acquired message.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setAcquiredInfo(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mAcquiredInfo = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationAcquiredInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8; // Mark builder used
+
+            AuthenticationAcquiredInfo o = new AuthenticationAcquiredInfo(
+                    mBiometricSourceType,
+                    mRequestReason,
+                    mAcquiredInfo);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x8) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305187861L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationAcquiredInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nprivate final  int mAcquiredInfo\nclass AuthenticationAcquiredInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.aidl
new file mode 100644
index 0000000..cf30e46a
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationErrorInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.java
new file mode 100644
index 0000000..88ee9d6
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information related to a unrecoverable error encountered during biometric authentication.
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationErrorInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+    /**
+     * String shown on the UI for an authentication error.
+     */
+    @Nullable
+    private final String mErrString;
+
+    /**
+     * {@link BiometricFaceConstants.FaceError} or
+     * {@link BiometricFingerprintConstants.FingerprintError} int identifying the error message for
+     * an authentication error
+     */
+    private final int mErrCode;
+
+
+
+    // 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/biometrics/events/AuthenticationErrorInfo.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 */ AuthenticationErrorInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason,
+            @Nullable String errString,
+            int errCode) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mErrString = errString;
+        this.mErrCode = errCode;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    /**
+     * String shown on the UI for an authentication error.
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getErrString() {
+        return mErrString;
+    }
+
+    /**
+     * {@link BiometricFaceConstants.FaceError} or
+     * {@link BiometricFingerprintConstants.FingerprintError} int identifying the error message for
+     * an authentication error
+     */
+    @DataClass.Generated.Member
+    public int getErrCode() {
+        return mErrCode;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationErrorInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationErrorInfo that = (AuthenticationErrorInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason
+                && java.util.Objects.equals(mErrString, that.mErrString)
+                && mErrCode == that.mErrCode;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mErrString);
+        _hash = 31 * _hash + mErrCode;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        byte flg = 0;
+        if (mErrString != null) flg |= 0x4;
+        dest.writeByte(flg);
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+        if (mErrString != null) dest.writeString(mErrString);
+        dest.writeInt(mErrCode);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationErrorInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+        String errString = (flg & 0x4) == 0 ? null : in.readString();
+        int errCode = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mErrString = errString;
+        this.mErrCode = errCode;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationErrorInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationErrorInfo>() {
+        @Override
+        public AuthenticationErrorInfo[] newArray(int size) {
+            return new AuthenticationErrorInfo[size];
+        }
+
+        @Override
+        public AuthenticationErrorInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationErrorInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationErrorInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+        private @Nullable String mErrString;
+        private int mErrCode;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         * @param errString
+         *   String shown on the UI for an authentication error.
+         * @param errCode
+         *   {@link BiometricFaceConstants.FaceError} or
+         *   {@link BiometricFingerprintConstants.FingerprintError} int identifying the error message for
+         *   an authentication error
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason,
+                @Nullable String errString,
+                int errCode) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+            mErrString = errString;
+            mErrCode = errCode;
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /**
+         * String shown on the UI for an authentication error.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setErrString(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mErrString = value;
+            return this;
+        }
+
+        /**
+         * {@link BiometricFaceConstants.FaceError} or
+         * {@link BiometricFingerprintConstants.FingerprintError} int identifying the error message for
+         * an authentication error
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setErrCode(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mErrCode = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationErrorInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10; // Mark builder used
+
+            AuthenticationErrorInfo o = new AuthenticationErrorInfo(
+                    mBiometricSourceType,
+                    mRequestReason,
+                    mErrString,
+                    mErrCode);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x10) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305309794L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationErrorInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nprivate final @android.annotation.Nullable java.lang.String mErrString\nprivate final  int mErrCode\nclass AuthenticationErrorInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.aidl
new file mode 100644
index 0000000..5712f91
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationFailedInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.java
new file mode 100644
index 0000000..7218780
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information related to a failed biometric authentication.
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationFailedInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+    /**
+     * The user id for the requested authentication
+     */
+    private final int mUserId;
+
+
+
+    // 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/biometrics/events/AuthenticationFailedInfo.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 */ AuthenticationFailedInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason,
+            int userId) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mUserId = userId;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    /**
+     * The user id for the requested authentication
+     */
+    @DataClass.Generated.Member
+    public int getUserId() {
+        return mUserId;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationFailedInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationFailedInfo that = (AuthenticationFailedInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason
+                && mUserId == that.mUserId;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        _hash = 31 * _hash + mUserId;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+        dest.writeInt(mUserId);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationFailedInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+        int userId = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mUserId = userId;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationFailedInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationFailedInfo>() {
+        @Override
+        public AuthenticationFailedInfo[] newArray(int size) {
+            return new AuthenticationFailedInfo[size];
+        }
+
+        @Override
+        public AuthenticationFailedInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationFailedInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationFailedInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+        private int mUserId;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         * @param userId
+         *   The user id for the requested authentication
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason,
+                int userId) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+            mUserId = userId;
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /**
+         * The user id for the requested authentication
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setUserId(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mUserId = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationFailedInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8; // Mark builder used
+
+            AuthenticationFailedInfo o = new AuthenticationFailedInfo(
+                    mBiometricSourceType,
+                    mRequestReason,
+                    mUserId);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x8) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305348961L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationFailedInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nprivate final  int mUserId\nclass AuthenticationFailedInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.aidl
new file mode 100644
index 0000000..a5efb20
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationHelpInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.java
new file mode 100644
index 0000000..4ba8a5e
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information related to a recoverable error encountered during biometric authentication.
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationHelpInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+    /**
+     * Guidance help string shown on the UI for authentication help.
+     */
+    @Nullable
+    private final String mHelpString;
+
+    /**
+     * An integer identifying the help message for authentication help.
+     */
+    private final int mHelpCode;
+
+
+
+    // 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/biometrics/events/AuthenticationHelpInfo.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 */ AuthenticationHelpInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason,
+            @Nullable String helpString,
+            int helpCode) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mHelpString = helpString;
+        this.mHelpCode = helpCode;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    /**
+     * Guidance help string shown on the UI for authentication help.
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getHelpString() {
+        return mHelpString;
+    }
+
+    /**
+     * An integer identifying the help message for authentication help.
+     */
+    @DataClass.Generated.Member
+    public int getHelpCode() {
+        return mHelpCode;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationHelpInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationHelpInfo that = (AuthenticationHelpInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason
+                && java.util.Objects.equals(mHelpString, that.mHelpString)
+                && mHelpCode == that.mHelpCode;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mHelpString);
+        _hash = 31 * _hash + mHelpCode;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        byte flg = 0;
+        if (mHelpString != null) flg |= 0x4;
+        dest.writeByte(flg);
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+        if (mHelpString != null) dest.writeString(mHelpString);
+        dest.writeInt(mHelpCode);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationHelpInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+        String helpString = (flg & 0x4) == 0 ? null : in.readString();
+        int helpCode = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mHelpString = helpString;
+        this.mHelpCode = helpCode;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationHelpInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationHelpInfo>() {
+        @Override
+        public AuthenticationHelpInfo[] newArray(int size) {
+            return new AuthenticationHelpInfo[size];
+        }
+
+        @Override
+        public AuthenticationHelpInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationHelpInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationHelpInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+        private @Nullable String mHelpString;
+        private int mHelpCode;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         * @param helpString
+         *   Guidance help string shown on the UI for authentication help.
+         * @param helpCode
+         *   An integer identifying the help message for authentication help.
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason,
+                @Nullable String helpString,
+                int helpCode) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+            mHelpString = helpString;
+            mHelpCode = helpCode;
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /**
+         * Guidance help string shown on the UI for authentication help.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setHelpString(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mHelpString = value;
+            return this;
+        }
+
+        /**
+         * An integer identifying the help message for authentication help.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setHelpCode(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mHelpCode = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationHelpInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10; // Mark builder used
+
+            AuthenticationHelpInfo o = new AuthenticationHelpInfo(
+                    mBiometricSourceType,
+                    mRequestReason,
+                    mHelpString,
+                    mHelpCode);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x10) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305435226L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationHelpInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nprivate final @android.annotation.Nullable java.lang.String mHelpString\nprivate final  int mHelpCode\nclass AuthenticationHelpInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.aidl
new file mode 100644
index 0000000..325379c
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationStartedInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.java
new file mode 100644
index 0000000..06461ea
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information about a request to start biometric authentication
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationStartedInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+
+
+    // 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/biometrics/events/AuthenticationStartedInfo.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 */ AuthenticationStartedInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationStartedInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationStartedInfo that = (AuthenticationStartedInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationStartedInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationStartedInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationStartedInfo>() {
+        @Override
+        public AuthenticationStartedInfo[] newArray(int size) {
+            return new AuthenticationStartedInfo[size];
+        }
+
+        @Override
+        public AuthenticationStartedInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationStartedInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationStartedInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationStartedInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4; // Mark builder used
+
+            AuthenticationStartedInfo o = new AuthenticationStartedInfo(
+                    mBiometricSourceType,
+                    mRequestReason);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x4) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305495570L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationStartedInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nclass AuthenticationStartedInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.aidl
new file mode 100644
index 0000000..2414c5a
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationStoppedInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.java
new file mode 100644
index 0000000..43ed2ec
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information about a request to stop biometric authentication
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationStoppedInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+
+
+    // 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/biometrics/events/AuthenticationStoppedInfo.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 */ AuthenticationStoppedInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationStoppedInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationStoppedInfo that = (AuthenticationStoppedInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationStoppedInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationStoppedInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationStoppedInfo>() {
+        @Override
+        public AuthenticationStoppedInfo[] newArray(int size) {
+            return new AuthenticationStoppedInfo[size];
+        }
+
+        @Override
+        public AuthenticationStoppedInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationStoppedInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationStoppedInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationStoppedInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4; // Mark builder used
+
+            AuthenticationStoppedInfo o = new AuthenticationStoppedInfo(
+                    mBiometricSourceType,
+                    mRequestReason);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x4) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305502581L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationStoppedInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nclass AuthenticationStoppedInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.aidl b/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.aidl
new file mode 100644
index 0000000..21cc085
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+parcelable AuthenticationSucceededInfo;
diff --git a/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.java b/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.java
new file mode 100644
index 0000000..425966d
--- /dev/null
+++ b/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.events;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Information about a successful biometric authentication.
+ * @hide
+ */
+@DataClass(
+        genParcelable = true,
+        genAidl = true,
+        genBuilder = true,
+        genSetters = true,
+        genEqualsHashCode = true
+)
+public final class AuthenticationSucceededInfo implements Parcelable {
+    /** Identifies {@link BiometricSourceType} of authentication. */
+    @NonNull
+    private final BiometricSourceType mBiometricSourceType;
+
+    /** Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication. */
+    @BiometricRequestConstants.RequestReason
+    private final int mRequestReason;
+
+    /**
+     * Indicates whether auth was from strong biometric.
+     */
+    private final boolean mIsStrongBiometric;
+
+    /**
+     * The user id for the requested authentication
+     */
+    private final int mUserId;
+
+
+
+    // 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/biometrics/events/AuthenticationSucceededInfo.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 */ AuthenticationSucceededInfo(
+            @NonNull BiometricSourceType biometricSourceType,
+            @BiometricRequestConstants.RequestReason int requestReason,
+            boolean isStrongBiometric,
+            int userId) {
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mIsStrongBiometric = isStrongBiometric;
+        this.mUserId = userId;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Identifies {@link BiometricSourceType} of authentication.
+     */
+    @DataClass.Generated.Member
+    public @NonNull BiometricSourceType getBiometricSourceType() {
+        return mBiometricSourceType;
+    }
+
+    /**
+     * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+     * requesting authentication.
+     */
+    @DataClass.Generated.Member
+    public @BiometricRequestConstants.RequestReason int getRequestReason() {
+        return mRequestReason;
+    }
+
+    /**
+     * Indicates whether auth was from strong biometric.
+     */
+    @DataClass.Generated.Member
+    public boolean isIsStrongBiometric() {
+        return mIsStrongBiometric;
+    }
+
+    /**
+     * The user id for the requested authentication
+     */
+    @DataClass.Generated.Member
+    public int getUserId() {
+        return mUserId;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AuthenticationSucceededInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AuthenticationSucceededInfo that = (AuthenticationSucceededInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mBiometricSourceType, that.mBiometricSourceType)
+                && mRequestReason == that.mRequestReason
+                && mIsStrongBiometric == that.mIsStrongBiometric
+                && mUserId == that.mUserId;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mBiometricSourceType);
+        _hash = 31 * _hash + mRequestReason;
+        _hash = 31 * _hash + Boolean.hashCode(mIsStrongBiometric);
+        _hash = 31 * _hash + mUserId;
+        return _hash;
+    }
+
+    @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) { ... }
+
+        byte flg = 0;
+        if (mIsStrongBiometric) flg |= 0x4;
+        dest.writeByte(flg);
+        dest.writeTypedObject(mBiometricSourceType, flags);
+        dest.writeInt(mRequestReason);
+        dest.writeInt(mUserId);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AuthenticationSucceededInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        boolean isStrongBiometric = (flg & 0x4) != 0;
+        BiometricSourceType biometricSourceType = (BiometricSourceType) in.readTypedObject(BiometricSourceType.CREATOR);
+        int requestReason = in.readInt();
+        int userId = in.readInt();
+
+        this.mBiometricSourceType = biometricSourceType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBiometricSourceType);
+        this.mRequestReason = requestReason;
+        com.android.internal.util.AnnotationValidations.validate(
+                BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+        this.mIsStrongBiometric = isStrongBiometric;
+        this.mUserId = userId;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AuthenticationSucceededInfo> CREATOR
+            = new Parcelable.Creator<AuthenticationSucceededInfo>() {
+        @Override
+        public AuthenticationSucceededInfo[] newArray(int size) {
+            return new AuthenticationSucceededInfo[size];
+        }
+
+        @Override
+        public AuthenticationSucceededInfo createFromParcel(@NonNull Parcel in) {
+            return new AuthenticationSucceededInfo(in);
+        }
+    };
+
+    /**
+     * A builder for {@link AuthenticationSucceededInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull BiometricSourceType mBiometricSourceType;
+        private @BiometricRequestConstants.RequestReason int mRequestReason;
+        private boolean mIsStrongBiometric;
+        private int mUserId;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param biometricSourceType
+         *   Identifies {@link BiometricSourceType} of authentication.
+         * @param requestReason
+         *   Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         *   requesting authentication.
+         * @param isStrongBiometric
+         *   Indicates whether auth was from strong biometric.
+         * @param userId
+         *   The user id for the requested authentication
+         */
+        public Builder(
+                @NonNull BiometricSourceType biometricSourceType,
+                @BiometricRequestConstants.RequestReason int requestReason,
+                boolean isStrongBiometric,
+                int userId) {
+            mBiometricSourceType = biometricSourceType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mBiometricSourceType);
+            mRequestReason = requestReason;
+            com.android.internal.util.AnnotationValidations.validate(
+                    BiometricRequestConstants.RequestReason.class, null, mRequestReason);
+            mIsStrongBiometric = isStrongBiometric;
+            mUserId = userId;
+        }
+
+        /**
+         * Identifies {@link BiometricSourceType} of authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setBiometricSourceType(@NonNull BiometricSourceType value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mBiometricSourceType = value;
+            return this;
+        }
+
+        /**
+         * Indicates reason from {@link BiometricRequestConstants.RequestReason} for
+         * requesting authentication.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestReason(@BiometricRequestConstants.RequestReason int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mRequestReason = value;
+            return this;
+        }
+
+        /**
+         * Indicates whether auth was from strong biometric.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setIsStrongBiometric(boolean value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mIsStrongBiometric = value;
+            return this;
+        }
+
+        /**
+         * The user id for the requested authentication
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setUserId(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mUserId = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull AuthenticationSucceededInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10; // Mark builder used
+
+            AuthenticationSucceededInfo o = new AuthenticationSucceededInfo(
+                    mBiometricSourceType,
+                    mRequestReason,
+                    mIsStrongBiometric,
+                    mUserId);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x10) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1713305509212L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/hardware/biometrics/events/AuthenticationSucceededInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.hardware.biometrics.BiometricSourceType mBiometricSourceType\nprivate final @android.hardware.biometrics.BiometricRequestConstants.RequestReason int mRequestReason\nprivate final  boolean mIsStrongBiometric\nprivate final  int mUserId\nclass AuthenticationSucceededInfo extends java.lang.Object implements [android.os.Parcelable]\[email protected](genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index dca663d2..50d976f 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -1768,9 +1768,12 @@
          * @param sessionConfig The session configuration for which characteristics are fetched.
          * @return CameraCharacteristics specific to a given session configuration.
          *
-         * @throws IllegalArgumentException      if the session configuration is invalid
-         * @throws CameraAccessException         if the camera device is no longer connected or has
-         *                                       encountered a fatal error
+         * @throws IllegalArgumentException if the session configuration is invalid or if
+         *                                  {@link #isSessionConfigurationSupported} returns
+         *                                  {@code false} for the provided
+         *                                  {@link SessionConfiguration}
+         * @throws CameraAccessException    if the camera device is no longer connected or has
+         *                                  encountered a fatal error
          *
          * @see CameraCharacteristics#getAvailableSessionCharacteristicsKeys
          */
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 4cd40ea..90a2cf0 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1969,9 +1969,6 @@
 
         private static final String TAG = "CameraManagerGlobal";
 
-        private static final String BACK_CAMERA_ID = "0";
-        private static final String FRONT_CAMERA_ID = "1";
-
         private final boolean DEBUG = false;
 
         private final int CAMERA_SERVICE_RECONNECT_DELAY_MS = 1000;
@@ -2309,11 +2306,6 @@
                 return false;
             }
 
-            // External cameras should never be hidden.
-            if (!info.mCameraId.equals(FRONT_CAMERA_ID) && !info.mCameraId.equals(BACK_CAMERA_ID)) {
-                return false;
-            }
-
             return currentDeviceId != info.mDeviceId;
         }
 
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 735b20f..c82e7e8 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1494,7 +1494,7 @@
      * {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}.</p>
      * <p>Note that the actual achievable max framerate also depends on the minimum frame
      * duration of the output streams. The max frame rate will be
-     * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations)</code>. For example,
+     * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations))</code>. For example,
      * if the application sets this key to <code>{60, 60}</code>, but the maximum minFrameDuration among
      * all configured streams is 33ms, the maximum framerate won't be 60fps, but will be
      * 30fps.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 76287ca..5765a73 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -893,7 +893,7 @@
      * {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}.</p>
      * <p>Note that the actual achievable max framerate also depends on the minimum frame
      * duration of the output streams. The max frame rate will be
-     * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations)</code>. For example,
+     * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations))</code>. For example,
      * if the application sets this key to <code>{60, 60}</code>, but the maximum minFrameDuration among
      * all configured streams is 33ms, the maximum framerate won't be 60fps, but will be
      * 30fps.</p>
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
index 81d0976..372839d 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
@@ -104,8 +104,8 @@
             }
 
             try {
-                return cameraService.isSessionConfigurationWithParametersSupported(
-                        mCameraId, config, mContext.getDeviceId(),
+                return cameraService.isSessionConfigurationWithParametersSupported(mCameraId,
+                        mTargetSdkVersion, config, mContext.getDeviceId(),
                         mCameraManager.getDevicePolicyFromContext(mContext));
             } catch (ServiceSpecificException e) {
                 throw ExceptionUtils.throwAsPublicException(e);
diff --git a/core/java/android/hardware/face/FaceCallback.java b/core/java/android/hardware/face/FaceCallback.java
new file mode 100644
index 0000000..b69024f
--- /dev/null
+++ b/core/java/android/hardware/face/FaceCallback.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR_BASE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_VENDOR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_VENDOR_BASE;
+import static android.hardware.face.FaceManager.getAuthHelpMessage;
+import static android.hardware.face.FaceManager.getEnrollHelpMessage;
+import static android.hardware.face.FaceManager.getErrorString;
+
+import android.content.Context;
+import android.hardware.biometrics.CryptoObject;
+import android.hardware.face.FaceManager.AuthenticationCallback;
+import android.hardware.face.FaceManager.EnrollmentCallback;
+import android.hardware.face.FaceManager.FaceDetectionCallback;
+import android.hardware.face.FaceManager.GenerateChallengeCallback;
+import android.hardware.face.FaceManager.GetFeatureCallback;
+import android.hardware.face.FaceManager.RemovalCallback;
+import android.hardware.face.FaceManager.SetFeatureCallback;
+import android.util.Slog;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Encapsulates callbacks and client specific information for each face related request.
+ * @hide
+ */
+public class FaceCallback {
+    private static final String TAG = " FaceCallback";
+
+    @Nullable
+    private AuthenticationCallback mAuthenticationCallback;
+    @Nullable
+    private EnrollmentCallback mEnrollmentCallback;
+    @Nullable
+    private RemovalCallback mRemovalCallback;
+    @Nullable
+    private GenerateChallengeCallback mGenerateChallengeCallback;
+    @Nullable
+    private FaceDetectionCallback mFaceDetectionCallback;
+    @Nullable
+    private SetFeatureCallback mSetFeatureCallback;
+    @Nullable
+    private GetFeatureCallback mGetFeatureCallback;
+    @Nullable
+    private Face mRemovalFace;
+    @Nullable
+    private CryptoObject mCryptoObject;
+
+    /**
+     * Construction for face authentication client callback.
+     */
+    FaceCallback(AuthenticationCallback authenticationCallback, CryptoObject cryptoObject) {
+        mAuthenticationCallback = authenticationCallback;
+        mCryptoObject = cryptoObject;
+    }
+
+    /**
+     * Construction for face detect client callback.
+     */
+    FaceCallback(FaceDetectionCallback faceDetectionCallback) {
+        mFaceDetectionCallback = faceDetectionCallback;
+    }
+
+    /**
+     * Construction for face enroll client callback.
+     */
+    FaceCallback(EnrollmentCallback enrollmentCallback) {
+        mEnrollmentCallback = enrollmentCallback;
+    }
+
+    /**
+     * Construction for face generate challenge client callback.
+     */
+    FaceCallback(GenerateChallengeCallback generateChallengeCallback) {
+        mGenerateChallengeCallback = generateChallengeCallback;
+    }
+
+    /**
+     * Construction for face set feature client callback.
+     */
+    FaceCallback(SetFeatureCallback setFeatureCallback) {
+        mSetFeatureCallback = setFeatureCallback;
+    }
+
+    /**
+     * Construction for face get feature client callback.
+     */
+    FaceCallback(GetFeatureCallback getFeatureCallback) {
+        mGetFeatureCallback = getFeatureCallback;
+    }
+
+    /**
+     * Construction for single face removal client callback.
+     */
+    FaceCallback(RemovalCallback removalCallback, Face removalFace) {
+        mRemovalCallback = removalCallback;
+        mRemovalFace = removalFace;
+    }
+
+    /**
+     * Construction for all face removal client callback.
+     */
+    FaceCallback(RemovalCallback removalCallback) {
+        mRemovalCallback = removalCallback;
+    }
+
+    /**
+     * Propagate set feature completed via the callback.
+     * @param success if the operation was completed successfully
+     * @param feature the feature that was set
+     */
+    public void sendSetFeatureCompleted(boolean success, int feature) {
+        if (mSetFeatureCallback == null) {
+            return;
+        }
+        mSetFeatureCallback.onCompleted(success, feature);
+    }
+
+    /**
+     * Propagate get feature completed via the callback.
+     * @param success if the operation was completed successfully
+     * @param features list of features available
+     * @param featureState status of the features corresponding to the previous parameter
+     */
+    public void sendGetFeatureCompleted(boolean success, int[] features, boolean[] featureState) {
+        if (mGetFeatureCallback == null) {
+            return;
+        }
+        mGetFeatureCallback.onCompleted(success, features, featureState);
+    }
+
+    /**
+     * Propagate challenge generated completed via the callback.
+     * @param sensorId id of the corresponding sensor
+     * @param userId id of the corresponding sensor
+     * @param challenge value of the challenge generated
+     */
+    public void sendChallengeGenerated(int sensorId, int userId, long challenge) {
+        if (mGenerateChallengeCallback == null) {
+            return;
+        }
+        mGenerateChallengeCallback.onGenerateChallengeResult(sensorId, userId, challenge);
+    }
+
+    /**
+     * Propagate face detected completed via the callback.
+     * @param sensorId id of the corresponding sensor
+     * @param userId id of the corresponding user
+     * @param isStrongBiometric if the sensor is strong or not
+     */
+    public void sendFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
+        if (mFaceDetectionCallback == null) {
+            Slog.e(TAG, "sendFaceDetected, callback null");
+            return;
+        }
+        mFaceDetectionCallback.onFaceDetected(sensorId, userId, isStrongBiometric);
+    }
+
+    /**
+     * Propagate remove face completed via the callback.
+     * @param face removed identifier
+     * @param remaining number of face enrollments remaining
+     */
+    public void sendRemovedResult(Face face, int remaining) {
+        if (mRemovalCallback == null) {
+            return;
+        }
+        mRemovalCallback.onRemovalSucceeded(face, remaining);
+    }
+
+    /**
+     * Propagate errors via the callback.
+     * @param context corresponding context
+     * @param errMsgId represents the framework error id
+     * @param vendorCode represents the vendor error code
+     */
+    public void sendErrorResult(Context context, int errMsgId, int vendorCode) {
+        // emulate HAL 2.1 behavior and send real errMsgId
+        final int clientErrMsgId = errMsgId == FACE_ERROR_VENDOR
+                ? (vendorCode + FACE_ERROR_VENDOR_BASE) : errMsgId;
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
+                    getErrorString(context, errMsgId, vendorCode));
+        } else if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
+                    getErrorString(context, errMsgId, vendorCode));
+        } else if (mRemovalCallback != null) {
+            mRemovalCallback.onRemovalError(mRemovalFace, clientErrMsgId,
+                    getErrorString(context, errMsgId, vendorCode));
+        } else if (mFaceDetectionCallback != null) {
+            mFaceDetectionCallback.onDetectionError(errMsgId);
+            mFaceDetectionCallback = null;
+        }
+    }
+
+    /**
+     * Propagate enroll progress via the callback.
+     * @param remaining number of enrollment steps remaining
+     */
+    public void sendEnrollResult(int remaining) {
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentProgress(remaining);
+        }
+    }
+
+    /**
+     * Propagate authentication succeeded via the callback.
+     * @param face matched identifier
+     * @param userId id of the corresponding user
+     * @param isStrongBiometric if the sensor is strong or not
+     */
+    public void sendAuthenticatedSucceeded(Face face, int userId, boolean isStrongBiometric) {
+        if (mAuthenticationCallback != null) {
+            final FaceManager.AuthenticationResult result = new FaceManager.AuthenticationResult(
+                    mCryptoObject, face, userId, isStrongBiometric);
+            mAuthenticationCallback.onAuthenticationSucceeded(result);
+        }
+    }
+
+    /**
+     * Propagate authentication failed via the callback.
+     */
+    public void sendAuthenticatedFailed() {
+        if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationFailed();
+        }
+    }
+
+    /**
+     * Propagate acquired result via the callback.
+     * @param context corresponding context
+     * @param acquireInfo represents the framework acquired id
+     * @param vendorCode represents the vendor acquired code
+     */
+    public void sendAcquiredResult(Context context, int acquireInfo, int vendorCode) {
+        if (mAuthenticationCallback != null) {
+            final FaceAuthenticationFrame frame = new FaceAuthenticationFrame(
+                    new FaceDataFrame(acquireInfo, vendorCode));
+            sendAuthenticationFrame(context, frame);
+        } else if (mEnrollmentCallback != null) {
+            final FaceEnrollFrame frame = new FaceEnrollFrame(
+                    null /* cell */,
+                    FaceEnrollStages.UNKNOWN,
+                    new FaceDataFrame(acquireInfo, vendorCode));
+            sendEnrollmentFrame(context, frame);
+        }
+    }
+
+    /**
+     * Propagate authentication frame via the callback.
+     * @param context corresponding context
+     * @param frame authentication frame to be sent
+     */
+    public void sendAuthenticationFrame(@NonNull Context context,
+            @Nullable FaceAuthenticationFrame frame) {
+        if (frame == null) {
+            Slog.w(TAG, "Received null authentication frame");
+        } else if (mAuthenticationCallback != null) {
+            // TODO(b/178414967): Send additional frame data to callback
+            final int acquireInfo = frame.getData().getAcquiredInfo();
+            final int vendorCode = frame.getData().getVendorCode();
+            final int helpCode = getHelpCode(acquireInfo, vendorCode);
+            final String helpMessage = getAuthHelpMessage(context, acquireInfo, vendorCode);
+            mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
+
+            // Ensure that only non-null help messages are sent.
+            if (helpMessage != null) {
+                mAuthenticationCallback.onAuthenticationHelp(helpCode, helpMessage);
+            }
+        }
+    }
+
+    /**
+     * Propagate enrollment via the callback.
+     * @param context corresponding context
+     * @param frame enrollment frame to be sent
+     */
+    public void sendEnrollmentFrame(Context context, @Nullable FaceEnrollFrame frame) {
+        if (frame == null) {
+            Slog.w(TAG, "Received null enrollment frame");
+        } else if (mEnrollmentCallback != null) {
+            final FaceDataFrame data = frame.getData();
+            final int acquireInfo = data.getAcquiredInfo();
+            final int vendorCode = data.getVendorCode();
+            final int helpCode = getHelpCode(acquireInfo, vendorCode);
+            final String helpMessage = getEnrollHelpMessage(context, acquireInfo, vendorCode);
+            mEnrollmentCallback.onEnrollmentFrame(
+                    helpCode,
+                    helpMessage,
+                    frame.getCell(),
+                    frame.getStage(),
+                    data.getPan(),
+                    data.getTilt(),
+                    data.getDistance());
+        }
+    }
+
+    private static int getHelpCode(int acquireInfo, int vendorCode) {
+        return acquireInfo == FACE_ACQUIRED_VENDOR
+                ? vendorCode + FACE_ACQUIRED_VENDOR_BASE
+                : acquireInfo;
+    }
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 210ce2b..2592630 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -37,9 +37,9 @@
 import android.os.CancellationSignal;
 import android.os.CancellationSignal.OnCancelListener;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
-import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.Trace;
@@ -49,7 +49,6 @@
 import android.view.Surface;
 
 import com.android.internal.R;
-import com.android.internal.os.SomeArgs;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -63,71 +62,56 @@
 
     private static final String TAG = "FaceManager";
 
-    private static final int MSG_ENROLL_RESULT = 100;
-    private static final int MSG_ACQUIRED = 101;
-    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
-    private static final int MSG_AUTHENTICATION_FAILED = 103;
-    private static final int MSG_ERROR = 104;
-    private static final int MSG_REMOVED = 105;
-    private static final int MSG_GET_FEATURE_COMPLETED = 106;
-    private static final int MSG_SET_FEATURE_COMPLETED = 107;
-    private static final int MSG_CHALLENGE_GENERATED = 108;
-    private static final int MSG_FACE_DETECTED = 109;
-    private static final int MSG_AUTHENTICATION_FRAME = 112;
-    private static final int MSG_ENROLLMENT_FRAME = 113;
-
     private final IFaceService mService;
     private final Context mContext;
     private final IBinder mToken = new Binder();
-    @Nullable private AuthenticationCallback mAuthenticationCallback;
-    @Nullable private FaceDetectionCallback mFaceDetectionCallback;
-    @Nullable private EnrollmentCallback mEnrollmentCallback;
-    @Nullable private RemovalCallback mRemovalCallback;
-    @Nullable private SetFeatureCallback mSetFeatureCallback;
-    @Nullable private GetFeatureCallback mGetFeatureCallback;
-    @Nullable private GenerateChallengeCallback mGenerateChallengeCallback;
-    private CryptoObject mCryptoObject;
-    private Face mRemovalFace;
     private Handler mHandler;
     private List<FaceSensorPropertiesInternal> mProps = new ArrayList<>();
+    private HandlerExecutor mExecutor;
 
-    private final IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
+    private class FaceServiceReceiver extends IFaceServiceReceiver.Stub {
+        private final FaceCallback mFaceCallback;
+
+        FaceServiceReceiver(FaceCallback faceCallback) {
+            mFaceCallback = faceCallback;
+        }
 
         @Override // binder call
         public void onEnrollResult(Face face, int remaining) {
-            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, face).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendEnrollResult(remaining));
         }
 
         @Override // binder call
         public void onAcquired(int acquireInfo, int vendorCode) {
-            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendAcquiredResult(mContext, acquireInfo,
+                    vendorCode));
         }
 
         @Override // binder call
         public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId,
-                    isStrongBiometric ? 1 : 0, face).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendAuthenticatedSucceeded(face, userId,
+                    isStrongBiometric));
         }
 
         @Override // binder call
         public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
-            mHandler.obtainMessage(MSG_FACE_DETECTED, sensorId, userId, isStrongBiometric)
-                    .sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendFaceDetected(sensorId, userId,
+                    isStrongBiometric));
         }
 
         @Override // binder call
         public void onAuthenticationFailed() {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
+            mExecutor.execute(mFaceCallback::sendAuthenticatedFailed);
         }
 
         @Override // binder call
         public void onError(int error, int vendorCode) {
-            mHandler.obtainMessage(MSG_ERROR, error, vendorCode).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendErrorResult(mContext, error, vendorCode));
         }
 
         @Override // binder call
         public void onRemoved(Face face, int remaining) {
-            mHandler.obtainMessage(MSG_REMOVED, remaining, 0, face).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendRemovedResult(face, remaining));
             if (remaining == 0) {
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
                         Settings.Secure.FACE_UNLOCK_RE_ENROLL, 0,
@@ -137,34 +121,31 @@
 
         @Override
         public void onFeatureSet(boolean success, int feature) {
-            mHandler.obtainMessage(MSG_SET_FEATURE_COMPLETED, feature, 0, success).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendSetFeatureCompleted(success, feature));
         }
 
         @Override
         public void onFeatureGet(boolean success, int[] features, boolean[] featureState) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = success;
-            args.arg2 = features;
-            args.arg3 = featureState;
-            mHandler.obtainMessage(MSG_GET_FEATURE_COMPLETED, args).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendGetFeatureCompleted(success, features,
+                    featureState));
         }
 
         @Override
         public void onChallengeGenerated(int sensorId, int userId, long challenge) {
-            mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, userId, challenge)
-                    .sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendChallengeGenerated(sensorId, userId,
+                    challenge));
         }
 
         @Override
         public void onAuthenticationFrame(FaceAuthenticationFrame frame) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_FRAME, frame).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendAuthenticationFrame(mContext, frame));
         }
 
         @Override
         public void onEnrollmentFrame(FaceEnrollFrame frame) {
-            mHandler.obtainMessage(MSG_ENROLLMENT_FRAME, frame).sendToTarget();
+            mExecutor.execute(() -> mFaceCallback.sendEnrollmentFrame(mContext, frame));
         }
-    };
+    }
 
     /**
      * @hide
@@ -175,7 +156,8 @@
         if (mService == null) {
             Slog.v(TAG, "FaceAuthenticationManagerService was null");
         }
-        mHandler = new MyHandler(context);
+        mHandler = context.getMainThreadHandler();
+        mExecutor = new HandlerExecutor(mHandler);
         if (context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
                 == PackageManager.PERMISSION_GRANTED) {
             addAuthenticatorsRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
@@ -193,9 +175,11 @@
      */
     private void useHandler(Handler handler) {
         if (handler != null) {
-            mHandler = new MyHandler(handler.getLooper());
-        } else if (mHandler.getLooper() != mContext.getMainLooper()) {
-            mHandler = new MyHandler(mContext.getMainLooper());
+            mHandler = handler;
+            mExecutor = new HandlerExecutor(mHandler);
+        } else if (mHandler != mContext.getMainThreadHandler()) {
+            mHandler = mContext.getMainThreadHandler();
+            mExecutor = new HandlerExecutor(mHandler);
         }
     }
 
@@ -249,13 +233,12 @@
 
         if (mService != null) {
             try {
+                final FaceCallback faceCallback = new FaceCallback(callback, crypto);
                 useHandler(handler);
-                mAuthenticationCallback = callback;
-                mCryptoObject = crypto;
                 final long operationId = crypto != null ? crypto.getOpId() : 0;
                 Trace.beginSection("FaceManager#authenticate");
                 final long authId = mService.authenticate(
-                        mToken, operationId, mServiceReceiver, options);
+                        mToken, operationId, new FaceServiceReceiver(faceCallback), options);
                 if (cancel != null) {
                     cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
                 }
@@ -292,10 +275,11 @@
         options.setOpPackageName(mContext.getOpPackageName());
         options.setAttributionTag(mContext.getAttributionTag());
 
-        mFaceDetectionCallback = callback;
+        final FaceCallback faceCallback = new FaceCallback(callback);
 
         try {
-            final long authId = mService.detectFace(mToken, mServiceReceiver, options);
+            final long authId = mService.detectFace(mToken,
+                    new FaceServiceReceiver(faceCallback), options);
             cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId));
         } catch (RemoteException e) {
             Slog.w(TAG, "Remote exception when requesting finger detect", e);
@@ -367,11 +351,11 @@
 
         if (mService != null) {
             try {
-                mEnrollmentCallback = callback;
+                final FaceCallback faceCallback = new FaceCallback(callback);
                 Trace.beginSection("FaceManager#enroll");
                 final long enrollId = mService.enroll(userId, mToken, hardwareAuthToken,
-                        mServiceReceiver, mContext.getOpPackageName(), disabledFeatures,
-                        previewSurface, debugConsent, options);
+                        new FaceServiceReceiver(faceCallback), mContext.getOpPackageName(),
+                        disabledFeatures, previewSurface, debugConsent, options);
                 if (cancel != null) {
                     cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId));
                 }
@@ -419,10 +403,11 @@
 
         if (mService != null) {
             try {
-                mEnrollmentCallback = callback;
+                final FaceCallback faceCallback = new FaceCallback(callback);
                 Trace.beginSection("FaceManager#enrollRemotely");
                 final long enrolId = mService.enrollRemotely(userId, mToken, hardwareAuthToken,
-                        mServiceReceiver, mContext.getOpPackageName(), disabledFeatures);
+                        new FaceServiceReceiver(faceCallback), mContext.getOpPackageName(),
+                        disabledFeatures);
                 if (cancel != null) {
                     cancel.setOnCancelListener(new OnEnrollCancelListener(enrolId));
                 }
@@ -455,9 +440,9 @@
     public void generateChallenge(int sensorId, int userId, GenerateChallengeCallback callback) {
         if (mService != null) {
             try {
-                mGenerateChallengeCallback = callback;
-                mService.generateChallenge(mToken, sensorId, userId, mServiceReceiver,
-                        mContext.getOpPackageName());
+                final FaceCallback faceCallback = new FaceCallback(callback);
+                mService.generateChallenge(mToken, sensorId, userId,
+                        new FaceServiceReceiver(faceCallback), mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -528,9 +513,9 @@
             SetFeatureCallback callback) {
         if (mService != null) {
             try {
-                mSetFeatureCallback = callback;
+                final FaceCallback faceCallback = new FaceCallback(callback);
                 mService.setFeature(mToken, userId, feature, enabled, hardwareAuthToken,
-                        mServiceReceiver, mContext.getOpPackageName());
+                        new FaceServiceReceiver(faceCallback), mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -544,8 +529,8 @@
     public void getFeature(int userId, int feature, GetFeatureCallback callback) {
         if (mService != null) {
             try {
-                mGetFeatureCallback = callback;
-                mService.getFeature(mToken, userId, feature, mServiceReceiver,
+                final FaceCallback faceCallback = new FaceCallback(callback);
+                mService.getFeature(mToken, userId, feature, new FaceServiceReceiver(faceCallback),
                         mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -566,10 +551,9 @@
     public void remove(Face face, int userId, RemovalCallback callback) {
         if (mService != null) {
             try {
-                mRemovalCallback = callback;
-                mRemovalFace = face;
-                mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver,
-                        mContext.getOpPackageName());
+                final FaceCallback faceCallback = new FaceCallback(callback, face);
+                mService.remove(mToken, face.getBiometricId(), userId,
+                        new FaceServiceReceiver(faceCallback), mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -584,8 +568,9 @@
     public void removeAll(int userId, @NonNull RemovalCallback callback) {
         if (mService != null) {
             try {
-                mRemovalCallback = callback;
-                mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+                final FaceCallback faceCallback = new FaceCallback(callback);
+                mService.removeAll(mToken, userId, new FaceServiceReceiver(faceCallback),
+                        mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1270,203 +1255,6 @@
         }
     }
 
-    private class MyHandler extends Handler {
-        private MyHandler(Context context) {
-            super(context.getMainLooper());
-        }
-
-        private MyHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(android.os.Message msg) {
-            Trace.beginSection("FaceManager#handleMessage: " + Integer.toString(msg.what));
-            switch (msg.what) {
-                case MSG_ENROLL_RESULT:
-                    sendEnrollResult((Face) msg.obj, msg.arg1 /* remaining */);
-                    break;
-                case MSG_ACQUIRED:
-                    sendAcquiredResult(msg.arg1 /* acquire info */, msg.arg2 /* vendorCode */);
-                    break;
-                case MSG_AUTHENTICATION_SUCCEEDED:
-                    sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */,
-                            msg.arg2 == 1 /* isStrongBiometric */);
-                    break;
-                case MSG_AUTHENTICATION_FAILED:
-                    sendAuthenticatedFailed();
-                    break;
-                case MSG_ERROR:
-                    sendErrorResult(msg.arg1 /* errMsgId */, msg.arg2 /* vendorCode */);
-                    break;
-                case MSG_REMOVED:
-                    sendRemovedResult((Face) msg.obj, msg.arg1 /* remaining */);
-                    break;
-                case MSG_SET_FEATURE_COMPLETED:
-                    sendSetFeatureCompleted((boolean) msg.obj /* success */,
-                            msg.arg1 /* feature */);
-                    break;
-                case MSG_GET_FEATURE_COMPLETED:
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    sendGetFeatureCompleted((boolean) args.arg1 /* success */,
-                            (int[]) args.arg2 /* features */,
-                            (boolean[]) args.arg3 /* featureState */);
-                    args.recycle();
-                    break;
-                case MSG_CHALLENGE_GENERATED:
-                    sendChallengeGenerated(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
-                            (long) msg.obj /* challenge */);
-                    break;
-                case MSG_FACE_DETECTED:
-                    sendFaceDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
-                            (boolean) msg.obj /* isStrongBiometric */);
-                    break;
-                case MSG_AUTHENTICATION_FRAME:
-                    sendAuthenticationFrame((FaceAuthenticationFrame) msg.obj /* frame */);
-                    break;
-                case MSG_ENROLLMENT_FRAME:
-                    sendEnrollmentFrame((FaceEnrollFrame) msg.obj /* frame */);
-                    break;
-                default:
-                    Slog.w(TAG, "Unknown message: " + msg.what);
-            }
-            Trace.endSection();
-        }
-    }
-
-    private void sendSetFeatureCompleted(boolean success, int feature) {
-        if (mSetFeatureCallback == null) {
-            return;
-        }
-        mSetFeatureCallback.onCompleted(success, feature);
-    }
-
-    private void sendGetFeatureCompleted(boolean success, int[] features, boolean[] featureState) {
-        if (mGetFeatureCallback == null) {
-            return;
-        }
-        mGetFeatureCallback.onCompleted(success, features, featureState);
-    }
-
-    private void sendChallengeGenerated(int sensorId, int userId, long challenge) {
-        if (mGenerateChallengeCallback == null) {
-            return;
-        }
-        mGenerateChallengeCallback.onGenerateChallengeResult(sensorId, userId, challenge);
-    }
-
-    private void sendFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
-        if (mFaceDetectionCallback == null) {
-            Slog.e(TAG, "sendFaceDetected, callback null");
-            return;
-        }
-        mFaceDetectionCallback.onFaceDetected(sensorId, userId, isStrongBiometric);
-    }
-
-    private void sendRemovedResult(Face face, int remaining) {
-        if (mRemovalCallback == null) {
-            return;
-        }
-        mRemovalCallback.onRemovalSucceeded(face, remaining);
-    }
-
-    private void sendErrorResult(int errMsgId, int vendorCode) {
-        // emulate HAL 2.1 behavior and send real errMsgId
-        final int clientErrMsgId = errMsgId == FACE_ERROR_VENDOR
-                ? (vendorCode + FACE_ERROR_VENDOR_BASE) : errMsgId;
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
-                    getErrorString(mContext, errMsgId, vendorCode));
-        } else if (mAuthenticationCallback != null) {
-            mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
-                    getErrorString(mContext, errMsgId, vendorCode));
-        } else if (mRemovalCallback != null) {
-            mRemovalCallback.onRemovalError(mRemovalFace, clientErrMsgId,
-                    getErrorString(mContext, errMsgId, vendorCode));
-        } else if (mFaceDetectionCallback != null) {
-            mFaceDetectionCallback.onDetectionError(errMsgId);
-            mFaceDetectionCallback = null;
-        }
-    }
-
-    private void sendEnrollResult(Face face, int remaining) {
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onEnrollmentProgress(remaining);
-        }
-    }
-
-    private void sendAuthenticatedSucceeded(Face face, int userId, boolean isStrongBiometric) {
-        if (mAuthenticationCallback != null) {
-            final AuthenticationResult result =
-                    new AuthenticationResult(mCryptoObject, face, userId, isStrongBiometric);
-            mAuthenticationCallback.onAuthenticationSucceeded(result);
-        }
-    }
-
-    private void sendAuthenticatedFailed() {
-        if (mAuthenticationCallback != null) {
-            mAuthenticationCallback.onAuthenticationFailed();
-        }
-    }
-
-    private void sendAcquiredResult(int acquireInfo, int vendorCode) {
-        if (mAuthenticationCallback != null) {
-            final FaceAuthenticationFrame frame = new FaceAuthenticationFrame(
-                    new FaceDataFrame(acquireInfo, vendorCode));
-            sendAuthenticationFrame(frame);
-        } else if (mEnrollmentCallback != null) {
-            final FaceEnrollFrame frame = new FaceEnrollFrame(
-                    null /* cell */,
-                    FaceEnrollStages.UNKNOWN,
-                    new FaceDataFrame(acquireInfo, vendorCode));
-            sendEnrollmentFrame(frame);
-        }
-    }
-
-    private void sendAuthenticationFrame(@Nullable FaceAuthenticationFrame frame) {
-        if (frame == null) {
-            Slog.w(TAG, "Received null authentication frame");
-        } else if (mAuthenticationCallback != null) {
-            // TODO(b/178414967): Send additional frame data to callback
-            final int acquireInfo = frame.getData().getAcquiredInfo();
-            final int vendorCode = frame.getData().getVendorCode();
-            final int helpCode = getHelpCode(acquireInfo, vendorCode);
-            final String helpMessage = getAuthHelpMessage(mContext, acquireInfo, vendorCode);
-            mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
-
-            // Ensure that only non-null help messages are sent.
-            if (helpMessage != null) {
-                mAuthenticationCallback.onAuthenticationHelp(helpCode, helpMessage);
-            }
-        }
-    }
-
-    private void sendEnrollmentFrame(@Nullable FaceEnrollFrame frame) {
-        if (frame == null) {
-            Slog.w(TAG, "Received null enrollment frame");
-        } else if (mEnrollmentCallback != null) {
-            final FaceDataFrame data = frame.getData();
-            final int acquireInfo = data.getAcquiredInfo();
-            final int vendorCode = data.getVendorCode();
-            final int helpCode = getHelpCode(acquireInfo, vendorCode);
-            final String helpMessage = getEnrollHelpMessage(mContext, acquireInfo, vendorCode);
-            mEnrollmentCallback.onEnrollmentFrame(
-                    helpCode,
-                    helpMessage,
-                    frame.getCell(),
-                    frame.getStage(),
-                    data.getPan(),
-                    data.getTilt(),
-                    data.getDistance());
-        }
-    }
-
-    private static int getHelpCode(int acquireInfo, int vendorCode) {
-        return acquireInfo == FACE_ACQUIRED_VENDOR
-                ? vendorCode + FACE_ACQUIRED_VENDOR_BASE
-                : acquireInfo;
-    }
-
     /**
      * @hide
      */
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 553d9f7..5a0f3db 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -164,15 +164,9 @@
     void getFeature(IBinder token, int userId, int feature, IFaceServiceReceiver receiver,
             String opPackageName);
 
-    // Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because
-    // AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist,
-    // hidlSensors must be non-null and empty. See AuthService.java
-    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
-    void registerAuthenticators(in List<FaceSensorPropertiesInternal> hidlSensors);
-
     //Register all available face sensors.
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
-    void registerAuthenticatorsLegacy(in FaceSensorConfigurations faceSensorConfigurations);
+    void registerAuthenticators(in FaceSensorConfigurations faceSensorConfigurations);
 
     // Adds a callback which gets called when the service registers all of the face
     // authenticators. The callback is automatically removed after it's invoked.
diff --git a/core/java/android/hardware/fingerprint/FingerprintCallback.java b/core/java/android/hardware/fingerprint/FingerprintCallback.java
new file mode 100644
index 0000000..e4fbe6e
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintCallback.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR_BASE;
+import static android.hardware.fingerprint.FingerprintManager.getAcquiredString;
+import static android.hardware.fingerprint.FingerprintManager.getErrorString;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
+import android.hardware.fingerprint.FingerprintManager.CryptoObject;
+import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
+import android.hardware.fingerprint.FingerprintManager.FingerprintDetectionCallback;
+import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback;
+import android.hardware.fingerprint.FingerprintManager.RemovalCallback;
+import android.util.Slog;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Encapsulates callbacks and client specific information for each fingerprint related request.
+ * @hide
+ */
+public class FingerprintCallback {
+    private static final String TAG = "FingerprintCallback";
+    public static final int REMOVE_SINGLE = 1;
+    public static final int REMOVE_ALL = 2;
+    @IntDef({REMOVE_SINGLE, REMOVE_ALL})
+    public @interface RemoveRequest {}
+    @Nullable
+    private AuthenticationCallback mAuthenticationCallback;
+    @Nullable
+    private EnrollmentCallback mEnrollmentCallback;
+    @Nullable
+    private RemovalCallback mRemovalCallback;
+    @Nullable
+    private GenerateChallengeCallback mGenerateChallengeCallback;
+    @Nullable
+    private FingerprintDetectionCallback mFingerprintDetectionCallback;
+    @Nullable
+    private CryptoObject mCryptoObject;
+    @Nullable
+    private @RemoveRequest int mRemoveRequest;
+    @Nullable
+    private Fingerprint mRemoveFingerprint;
+
+    /**
+     * Construction for fingerprint authentication client callback.
+     */
+    FingerprintCallback(@NonNull AuthenticationCallback authenticationCallback,
+            @Nullable CryptoObject cryptoObject) {
+        mAuthenticationCallback = authenticationCallback;
+        mCryptoObject = cryptoObject;
+    }
+
+    /**
+     * Construction for fingerprint detect client callback.
+     */
+    FingerprintCallback(@NonNull FingerprintDetectionCallback fingerprintDetectionCallback) {
+        mFingerprintDetectionCallback = fingerprintDetectionCallback;
+    }
+
+    /**
+     * Construction for fingerprint enroll client callback.
+     */
+    FingerprintCallback(@NonNull EnrollmentCallback enrollmentCallback) {
+        mEnrollmentCallback = enrollmentCallback;
+    }
+
+    /**
+     * Construction for fingerprint generate challenge client callback.
+     */
+    FingerprintCallback(@NonNull GenerateChallengeCallback generateChallengeCallback) {
+        mGenerateChallengeCallback = generateChallengeCallback;
+    }
+
+    /**
+     * Construction for fingerprint removal client callback.
+     */
+    FingerprintCallback(@NonNull RemovalCallback removalCallback, @RemoveRequest int removeRequest,
+            @Nullable Fingerprint removeFingerprint) {
+        mRemovalCallback = removalCallback;
+        mRemoveRequest = removeRequest;
+        mRemoveFingerprint = removeFingerprint;
+    }
+
+    /**
+     * Propagate enroll progress via the callback.
+     * @param remaining number of enrollment steps remaining
+     */
+    public void sendEnrollResult(int remaining) {
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentProgress(remaining);
+        }
+    }
+
+    /**
+     * Propagate remove face completed via the callback.
+     * @param fingerprint removed identifier
+     * @param remaining number of face enrollments remaining
+     */
+    public void sendRemovedResult(@Nullable Fingerprint fingerprint, int remaining) {
+        if (mRemovalCallback == null) {
+            return;
+        }
+
+        if (mRemoveRequest == REMOVE_SINGLE) {
+            if (fingerprint == null) {
+                Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+                return;
+            }
+
+            if (mRemoveFingerprint == null) {
+                Slog.e(TAG, "Missing fingerprint");
+                return;
+            }
+
+            final int fingerId = fingerprint.getBiometricId();
+            int reqFingerId = mRemoveFingerprint.getBiometricId();
+            if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
+                Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+                return;
+            }
+        }
+
+        mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
+    }
+
+    /**
+     * Propagate authentication succeeded via the callback.
+     * @param fingerprint matched identifier
+     * @param userId id of the corresponding user
+     * @param isStrongBiometric if the sensor is strong or not
+     */
+    public void sendAuthenticatedSucceeded(@NonNull Fingerprint fingerprint, int userId,
+            boolean isStrongBiometric) {
+        if (mAuthenticationCallback == null) {
+            Slog.e(TAG, "Authentication succeeded but callback is null.");
+            return;
+        }
+
+        final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fingerprint,
+                userId, isStrongBiometric);
+        mAuthenticationCallback.onAuthenticationSucceeded(result);
+    }
+
+    /**
+     * Propagate authentication failed via the callback.
+     */
+    public void sendAuthenticatedFailed() {
+        if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationFailed();
+        }
+    }
+
+    /**
+     * Propagate acquired result via the callback.
+     * @param context corresponding context
+     * @param acquireInfo represents the framework acquired id
+     * @param vendorCode represents the vendor acquired code
+     */
+    public void sendAcquiredResult(@NonNull Context context, int acquireInfo, int vendorCode) {
+        if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
+        }
+        if (mEnrollmentCallback != null && acquireInfo != FINGERPRINT_ACQUIRED_START) {
+            mEnrollmentCallback.onAcquired(acquireInfo == FINGERPRINT_ACQUIRED_GOOD);
+        }
+        final String msg = getAcquiredString(context, acquireInfo, vendorCode);
+        if (msg == null) {
+            return;
+        }
+        // emulate HAL 2.1 behavior and send real acquiredInfo
+        final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
+                ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
+        } else if (mAuthenticationCallback != null) {
+            if (acquireInfo != FINGERPRINT_ACQUIRED_START) {
+                mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
+            }
+        }
+    }
+
+    /**
+     * Propagate errors via the callback.
+     * @param context corresponding context
+     * @param errMsgId represents the framework error id
+     * @param vendorCode represents the vendor error code
+     */
+    public void sendErrorResult(@NonNull Context context, int errMsgId, int vendorCode) {
+        // emulate HAL 2.1 behavior and send real errMsgId
+        final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
+                ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
+                    getErrorString(context, errMsgId, vendorCode));
+        } else if (mAuthenticationCallback != null) {
+            mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
+                    getErrorString(context, errMsgId, vendorCode));
+        } else if (mRemovalCallback != null) {
+            mRemovalCallback.onRemovalError(mRemoveFingerprint, clientErrMsgId,
+                    getErrorString(context, errMsgId, vendorCode));
+        } else if (mFingerprintDetectionCallback != null) {
+            mFingerprintDetectionCallback.onDetectionError(errMsgId);
+            mFingerprintDetectionCallback = null;
+        }
+    }
+
+    /**
+     * Propagate challenge generated completed via the callback.
+     * @param sensorId id of the corresponding sensor
+     * @param userId id of the corresponding sensor
+     * @param challenge value of the challenge generated
+     */
+    public void sendChallengeGenerated(long challenge, int sensorId, int userId) {
+        if (mGenerateChallengeCallback == null) {
+            Slog.e(TAG, "sendChallengeGenerated, callback null");
+            return;
+        }
+        mGenerateChallengeCallback.onChallengeGenerated(sensorId, userId, challenge);
+    }
+
+    /**
+     * Propagate fingerprint detected completed via the callback.
+     * @param sensorId id of the corresponding sensor
+     * @param userId id of the corresponding user
+     * @param isStrongBiometric if the sensor is strong or not
+     */
+    public void sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) {
+        if (mFingerprintDetectionCallback == null) {
+            Slog.e(TAG, "sendFingerprintDetected, callback null");
+            return;
+        }
+        mFingerprintDetectionCallback.onFingerprintDetected(sensorId, userId, isStrongBiometric);
+    }
+
+    /**
+     * Propagate udfps pointer down via the callback.
+     * @param sensorId id of the corresponding sensor
+     */
+    public void sendUdfpsPointerDown(int sensorId) {
+        if (mAuthenticationCallback == null) {
+            Slog.e(TAG, "sendUdfpsPointerDown, callback null");
+        } else {
+            mAuthenticationCallback.onUdfpsPointerDown(sensorId);
+        }
+
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onUdfpsPointerDown(sensorId);
+        }
+    }
+
+    /**
+     * Propagate udfps pointer up via the callback.
+     * @param sensorId id of the corresponding sensor
+     */
+    public void sendUdfpsPointerUp(int sensorId) {
+        if (mAuthenticationCallback == null) {
+            Slog.e(TAG, "sendUdfpsPointerUp, callback null");
+        } else {
+            mAuthenticationCallback.onUdfpsPointerUp(sensorId);
+        }
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onUdfpsPointerUp(sensorId);
+        }
+    }
+
+    /**
+     * Propagate udfps overlay shown via the callback.
+     */
+    public void sendUdfpsOverlayShown() {
+        if (mEnrollmentCallback != null) {
+            mEnrollmentCallback.onUdfpsOverlayShown();
+        }
+    }
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 81e321d..25bfb2a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -25,6 +25,8 @@
 import static android.Manifest.permission.USE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
 import static android.hardware.biometrics.Flags.FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT;
+import static android.hardware.fingerprint.FingerprintCallback.REMOVE_ALL;
+import static android.hardware.fingerprint.FingerprintCallback.REMOVE_SINGLE;
 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
 
 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE;
@@ -57,9 +59,9 @@
 import android.os.CancellationSignal;
 import android.os.CancellationSignal.OnCancelListener;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
-import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -94,19 +96,6 @@
 @RequiresFeature(PackageManager.FEATURE_FINGERPRINT)
 public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {
     private static final String TAG = "FingerprintManager";
-    private static final boolean DEBUG = true;
-    private static final int MSG_ENROLL_RESULT = 100;
-    private static final int MSG_ACQUIRED = 101;
-    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
-    private static final int MSG_AUTHENTICATION_FAILED = 103;
-    private static final int MSG_ERROR = 104;
-    private static final int MSG_REMOVED = 105;
-    private static final int MSG_CHALLENGE_GENERATED = 106;
-    private static final int MSG_FINGERPRINT_DETECTED = 107;
-    private static final int MSG_UDFPS_POINTER_DOWN = 108;
-    private static final int MSG_UDFPS_POINTER_UP = 109;
-    private static final int MSG_POWER_BUTTON_PRESSED = 110;
-    private static final int MSG_UDFPS_OVERLAY_SHOWN = 111;
 
     /**
      * @hide
@@ -148,34 +137,14 @@
      */
     public static final int SENSOR_ID_ANY = -1;
 
-    private static class RemoveTracker {
-        static final int REMOVE_SINGLE = 1;
-        static final int REMOVE_ALL = 2;
-        @IntDef({REMOVE_SINGLE, REMOVE_ALL})
-        @interface RemoveRequest {}
+    private final IFingerprintService mService;
+    private final Context mContext;
+    private final IBinder mToken = new Binder();
 
-        final @RemoveRequest int mRemoveRequest;
-        @Nullable final Fingerprint mSingleFingerprint;
-
-        RemoveTracker(@RemoveRequest int request, @Nullable Fingerprint fingerprint) {
-            mRemoveRequest = request;
-            mSingleFingerprint = fingerprint;
-        }
-    }
-
-    private IFingerprintService mService;
-    private Context mContext;
-    private IBinder mToken = new Binder();
-    private AuthenticationCallback mAuthenticationCallback;
-    private FingerprintDetectionCallback mFingerprintDetectionCallback;
-    private EnrollmentCallback mEnrollmentCallback;
-    private RemovalCallback mRemovalCallback;
-    private GenerateChallengeCallback mGenerateChallengeCallback;
-    private CryptoObject mCryptoObject;
-    @Nullable private RemoveTracker mRemoveTracker;
     private Handler mHandler;
     @Nullable private float[] mEnrollStageThresholds;
     private List<FingerprintSensorPropertiesInternal> mProps = new ArrayList<>();
+    private HandlerExecutor mExecutor;
 
     /**
      * Retrieves a list of properties for all fingerprint sensors on the device.
@@ -395,7 +364,7 @@
      * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback}
      */
     @Deprecated
-    public static abstract class AuthenticationCallback
+    public abstract static class AuthenticationCallback
             extends BiometricAuthenticator.AuthenticationCallback {
         /**
          * Called when an unrecoverable error has been encountered and the operation is complete.
@@ -479,7 +448,7 @@
      *
      * @hide
      */
-    public static abstract class EnrollmentCallback {
+    public abstract static class EnrollmentCallback {
         /**
          * Called when an unrecoverable error has been encountered and the operation is complete.
          * No further callbacks will be made on this object.
@@ -536,7 +505,7 @@
      *
      * @hide
      */
-    public static abstract class RemovalCallback {
+    public abstract static class RemovalCallback {
         /**
          * Called when the given fingerprint can't be removed.
          * @param fp The fingerprint that the call attempted to remove
@@ -559,7 +528,7 @@
     /**
      * @hide
      */
-    public static abstract class LockoutResetCallback {
+    public abstract static class LockoutResetCallback {
 
         /**
          * Called when lockout period expired and clients are allowed to listen for fingerprint
@@ -584,9 +553,11 @@
      */
     private void useHandler(Handler handler) {
         if (handler != null) {
-            mHandler = new MyHandler(handler.getLooper());
-        } else if (mHandler.getLooper() != mContext.getMainLooper()) {
-            mHandler = new MyHandler(mContext.getMainLooper());
+            mHandler = handler;
+            mExecutor = new HandlerExecutor(mHandler);
+        } else if (mHandler != mContext.getMainThreadHandler()) {
+            mHandler = mContext.getMainThreadHandler();
+            mExecutor = new HandlerExecutor(mHandler);
         }
     }
 
@@ -676,11 +647,12 @@
 
         if (mService != null) {
             try {
+                final FingerprintCallback fingerprintCallback = new FingerprintCallback(callback,
+                        crypto);
                 useHandler(handler);
-                mAuthenticationCallback = callback;
-                mCryptoObject = crypto;
                 final long operationId = crypto != null ? crypto.getOpId() : 0;
-                final long authId = mService.authenticate(mToken, operationId, mServiceReceiver, options);
+                final long authId = mService.authenticate(mToken, operationId,
+                        new FingerprintServiceReceiver(fingerprintCallback), options);
                 if (cancel != null) {
                     cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
                 }
@@ -715,10 +687,11 @@
         options.setOpPackageName(mContext.getOpPackageName());
         options.setAttributionTag(mContext.getAttributionTag());
 
-        mFingerprintDetectionCallback = callback;
+        final FingerprintCallback fingerprintCallback = new FingerprintCallback(callback);
 
         try {
-            final long authId = mService.detectFingerprint(mToken, mServiceReceiver, options);
+            final long authId = mService.detectFingerprint(mToken,
+                    new FingerprintServiceReceiver(fingerprintCallback), options);
             cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId));
         } catch (RemoteException e) {
             Slog.w(TAG, "Remote exception when requesting finger detect", e);
@@ -767,9 +740,10 @@
 
         if (mService != null) {
             try {
-                mEnrollmentCallback = callback;
+                final FingerprintCallback fingerprintCallback = new FingerprintCallback(callback);
                 final long enrollId = mService.enroll(mToken, hardwareAuthToken, userId,
-                        mServiceReceiver, mContext.getOpPackageName(), enrollReason, options);
+                        new FingerprintServiceReceiver(fingerprintCallback),
+                        mContext.getOpPackageName(), enrollReason, options);
                 if (cancel != null) {
                     cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId));
                 }
@@ -799,12 +773,13 @@
     @RequiresPermission(MANAGE_FINGERPRINT)
     public void generateChallenge(int sensorId, int userId, GenerateChallengeCallback callback) {
         if (mService != null) try {
-            mGenerateChallengeCallback = callback;
-            mService.generateChallenge(mToken, sensorId, userId, mServiceReceiver,
-                    mContext.getOpPackageName());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+                final FingerprintCallback fingerprintCallback = new FingerprintCallback(callback);
+                mService.generateChallenge(mToken, sensorId, userId,
+                        new FingerprintServiceReceiver(fingerprintCallback),
+                        mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
     }
 
     /**
@@ -875,13 +850,14 @@
     @RequiresPermission(MANAGE_FINGERPRINT)
     public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
         if (mService != null) try {
-            mRemovalCallback = callback;
-            mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_SINGLE, fp);
-            mService.remove(mToken, fp.getBiometricId(), userId, mServiceReceiver,
-                    mContext.getOpPackageName());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+                final FingerprintCallback fingerprintCallback = new FingerprintCallback(callback,
+                        REMOVE_SINGLE, fp);
+                mService.remove(mToken, fp.getBiometricId(), userId,
+                        new FingerprintServiceReceiver(fingerprintCallback),
+                        mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
     }
 
     /**
@@ -892,9 +868,11 @@
     public void removeAll(int userId, @NonNull RemovalCallback callback) {
         if (mService != null) {
             try {
-                mRemovalCallback = callback;
-                mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_ALL, null /* fp */);
-                mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+                final FingerprintCallback fingerprintCallback = new FingerprintCallback(callback,
+                        REMOVE_ALL, null);
+                mService.removeAll(mToken, userId,
+                        new FingerprintServiceReceiver(fingerprintCallback),
+                        mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -984,24 +962,6 @@
         }
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /**
-     * @hide
-     */
-    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
-    public void setSidefpsController(@NonNull ISidefpsController controller) {
-        if (mService == null) {
-            Slog.w(TAG, "setSidefpsController: no fingerprint service");
-            return;
-        }
-
-        try {
-            mService.setSidefpsController(controller);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
     /**
      * Forwards BiometricStateListener to FingerprintService
      * @param listener new BiometricStateListener being added
@@ -1162,7 +1122,7 @@
     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
     public void onPowerPressed() {
         Slog.i(TAG, "onPowerPressed");
-        mHandler.obtainMessage(MSG_POWER_BUTTON_PRESSED).sendToTarget();
+        mExecutor.execute(() -> sendPowerPressed());
     }
 
     /**
@@ -1346,199 +1306,6 @@
         }
     }
 
-    private class MyHandler extends Handler {
-        private MyHandler(Context context) {
-            super(context.getMainLooper());
-        }
-
-        private MyHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(android.os.Message msg) {
-            switch (msg.what) {
-                case MSG_ENROLL_RESULT:
-                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
-                    break;
-                case MSG_ACQUIRED:
-                    sendAcquiredResult(msg.arg1 /* acquire info */,
-                            msg.arg2 /* vendorCode */);
-                    break;
-                case MSG_AUTHENTICATION_SUCCEEDED:
-                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */,
-                            msg.arg2 == 1 /* isStrongBiometric */);
-                    break;
-                case MSG_AUTHENTICATION_FAILED:
-                    sendAuthenticatedFailed();
-                    break;
-                case MSG_ERROR:
-                    sendErrorResult(msg.arg1 /* errMsgId */, msg.arg2 /* vendorCode */);
-                    break;
-                case MSG_REMOVED:
-                    sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
-                    break;
-                case MSG_CHALLENGE_GENERATED:
-                    sendChallengeGenerated(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
-                            (long) msg.obj /* challenge */);
-                    break;
-                case MSG_FINGERPRINT_DETECTED:
-                    sendFingerprintDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
-                            (boolean) msg.obj /* isStrongBiometric */);
-                    break;
-                case MSG_UDFPS_POINTER_DOWN:
-                    sendUdfpsPointerDown(msg.arg1 /* sensorId */);
-                    break;
-                case MSG_UDFPS_POINTER_UP:
-                    sendUdfpsPointerUp(msg.arg1 /* sensorId */);
-                    break;
-                case MSG_POWER_BUTTON_PRESSED:
-                    sendPowerPressed();
-                    break;
-                case MSG_UDFPS_OVERLAY_SHOWN:
-                    sendUdfpsOverlayShown();
-                default:
-                    Slog.w(TAG, "Unknown message: " + msg.what);
-
-            }
-        }
-    }
-
-    private void sendRemovedResult(Fingerprint fingerprint, int remaining) {
-        if (mRemovalCallback == null) {
-            return;
-        }
-
-        if (mRemoveTracker == null) {
-            Slog.w(TAG, "Removal tracker is null");
-            return;
-        }
-
-        if (mRemoveTracker.mRemoveRequest == RemoveTracker.REMOVE_SINGLE) {
-            if (fingerprint == null) {
-                Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
-                return;
-            }
-
-            if (mRemoveTracker.mSingleFingerprint == null) {
-                Slog.e(TAG, "Missing fingerprint");
-                return;
-            }
-
-            final int fingerId = fingerprint.getBiometricId();
-            int reqFingerId = mRemoveTracker.mSingleFingerprint.getBiometricId();
-            if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
-                Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
-                return;
-            }
-        }
-
-        mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
-    }
-
-    private void sendEnrollResult(Fingerprint fp, int remaining) {
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onEnrollmentProgress(remaining);
-        }
-    }
-
-    private void sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric) {
-        if (mAuthenticationCallback != null) {
-            final AuthenticationResult result =
-                    new AuthenticationResult(mCryptoObject, fp, userId, isStrongBiometric);
-            mAuthenticationCallback.onAuthenticationSucceeded(result);
-        }
-    }
-
-    private void sendAuthenticatedFailed() {
-        if (mAuthenticationCallback != null) {
-            mAuthenticationCallback.onAuthenticationFailed();
-        }
-    }
-
-    private void sendAcquiredResult(int acquireInfo, int vendorCode) {
-        if (mAuthenticationCallback != null) {
-            mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
-        }
-        if (mEnrollmentCallback != null && acquireInfo != FINGERPRINT_ACQUIRED_START) {
-            mEnrollmentCallback.onAcquired(acquireInfo == FINGERPRINT_ACQUIRED_GOOD);
-        }
-        final String msg = getAcquiredString(mContext, acquireInfo, vendorCode);
-        if (msg == null) {
-            return;
-        }
-        // emulate HAL 2.1 behavior and send real acquiredInfo
-        final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
-                ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
-        } else if (mAuthenticationCallback != null) {
-            if (acquireInfo != BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START) {
-                mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
-            }
-        }
-    }
-
-    private void sendErrorResult(int errMsgId, int vendorCode) {
-        // emulate HAL 2.1 behavior and send real errMsgId
-        final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
-                ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
-                    getErrorString(mContext, errMsgId, vendorCode));
-        } else if (mAuthenticationCallback != null) {
-            mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
-                    getErrorString(mContext, errMsgId, vendorCode));
-        } else if (mRemovalCallback != null) {
-            final Fingerprint fp = mRemoveTracker != null
-                    ? mRemoveTracker.mSingleFingerprint : null;
-            mRemovalCallback.onRemovalError(fp, clientErrMsgId,
-                    getErrorString(mContext, errMsgId, vendorCode));
-        } else if (mFingerprintDetectionCallback != null) {
-            mFingerprintDetectionCallback.onDetectionError(errMsgId);
-            mFingerprintDetectionCallback = null;
-        }
-    }
-
-    private void sendChallengeGenerated(int sensorId, int userId, long challenge) {
-        if (mGenerateChallengeCallback == null) {
-            Slog.e(TAG, "sendChallengeGenerated, callback null");
-            return;
-        }
-        mGenerateChallengeCallback.onChallengeGenerated(sensorId, userId, challenge);
-    }
-
-    private void sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) {
-        if (mFingerprintDetectionCallback == null) {
-            Slog.e(TAG, "sendFingerprintDetected, callback null");
-            return;
-        }
-        mFingerprintDetectionCallback.onFingerprintDetected(sensorId, userId, isStrongBiometric);
-    }
-
-    private void sendUdfpsPointerDown(int sensorId) {
-        if (mAuthenticationCallback == null) {
-            Slog.e(TAG, "sendUdfpsPointerDown, callback null");
-        } else {
-            mAuthenticationCallback.onUdfpsPointerDown(sensorId);
-        }
-
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onUdfpsPointerDown(sensorId);
-        }
-    }
-
-    private void sendUdfpsPointerUp(int sensorId) {
-        if (mAuthenticationCallback == null) {
-            Slog.e(TAG, "sendUdfpsPointerUp, callback null");
-        } else {
-            mAuthenticationCallback.onUdfpsPointerUp(sensorId);
-        }
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onUdfpsPointerUp(sensorId);
-        }
-    }
-
     private void sendPowerPressed() {
         try {
             mService.onPowerPressed();
@@ -1547,12 +1314,6 @@
         }
     }
 
-    private void sendUdfpsOverlayShown() {
-        if (mEnrollmentCallback != null) {
-            mEnrollmentCallback.onUdfpsOverlayShown();
-        }
-    }
-
     /**
      * @hide
      */
@@ -1562,7 +1323,6 @@
         if (mService == null) {
             Slog.v(TAG, "FingerprintService was null");
         }
-        mHandler = new MyHandler(context);
         if (context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
                 == PackageManager.PERMISSION_GRANTED) {
             addAuthenticatorsRegisteredCallback(
@@ -1574,6 +1334,8 @@
                         }
                     });
         }
+        mHandler = context.getMainThreadHandler();
+        mExecutor = new HandlerExecutor(mHandler);
     }
 
     private int getCurrentUserId() {
@@ -1773,66 +1535,72 @@
         return null;
     }
 
-    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
+    class FingerprintServiceReceiver extends IFingerprintServiceReceiver.Stub {
+        private final FingerprintCallback mFingerprintCallback;
+
+        FingerprintServiceReceiver(FingerprintCallback fingerprintCallback) {
+            mFingerprintCallback = fingerprintCallback;
+        }
 
         @Override // binder call
         public void onEnrollResult(Fingerprint fp, int remaining) {
-            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, fp).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendEnrollResult(remaining));
         }
 
         @Override // binder call
         public void onAcquired(int acquireInfo, int vendorCode) {
-            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendAcquiredResult(mContext, acquireInfo,
+                    vendorCode));
         }
 
         @Override // binder call
         public void onAuthenticationSucceeded(Fingerprint fp, int userId,
                 boolean isStrongBiometric) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, isStrongBiometric ? 1 : 0,
-                    fp).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendAuthenticatedSucceeded(fp, userId,
+                    isStrongBiometric));
         }
 
         @Override
         public void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_DETECTED, sensorId, userId, isStrongBiometric)
-                    .sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendFingerprintDetected(sensorId, userId,
+                    isStrongBiometric));
         }
 
         @Override // binder call
         public void onAuthenticationFailed() {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
+            mExecutor.execute(mFingerprintCallback::sendAuthenticatedFailed);
         }
 
         @Override // binder call
         public void onError(int error, int vendorCode) {
-            mHandler.obtainMessage(MSG_ERROR, error, vendorCode).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendErrorResult(mContext, error,
+                    vendorCode));
         }
 
         @Override // binder call
         public void onRemoved(Fingerprint fp, int remaining) {
-            mHandler.obtainMessage(MSG_REMOVED, remaining, 0, fp).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendRemovedResult(fp, remaining));
         }
 
         @Override // binder call
         public void onChallengeGenerated(int sensorId, int userId, long challenge) {
-            mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, userId, challenge)
-                    .sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendChallengeGenerated(challenge, sensorId,
+                    userId));
         }
 
         @Override // binder call
         public void onUdfpsPointerDown(int sensorId) {
-            mHandler.obtainMessage(MSG_UDFPS_POINTER_DOWN, sensorId, 0).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendUdfpsPointerDown(sensorId));
         }
 
         @Override // binder call
         public void onUdfpsPointerUp(int sensorId) {
-            mHandler.obtainMessage(MSG_UDFPS_POINTER_UP, sensorId, 0).sendToTarget();
+            mExecutor.execute(() -> mFingerprintCallback.sendUdfpsPointerUp(sensorId));
         }
 
         @Override
         public void onUdfpsOverlayShown() {
-            mHandler.obtainMessage(MSG_UDFPS_OVERLAY_SHOWN).sendToTarget();
+            mExecutor.execute(mFingerprintCallback::sendUdfpsOverlayShown);
         }
-    };
-
+    }
 }
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 8b37c24..742fa57 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -27,7 +27,6 @@
 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
 import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.FingerprintEnrollOptions;
@@ -177,13 +176,7 @@
 
     //Register all available fingerprint sensors.
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
-    void registerAuthenticatorsLegacy(in FingerprintSensorConfigurations fingerprintSensorConfigurations);
-
-    // Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because
-    // AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist,
-    // hidlSensors must be non-null and empty. See AuthService.java
-    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
-    void registerAuthenticators(in List<FingerprintSensorPropertiesInternal> hidlSensors);
+    void registerAuthenticators(in FingerprintSensorConfigurations fingerprintSensorConfigurations);
 
     // Adds a callback which gets called when the service registers all of the fingerprint
     // authenticators. The callback is automatically removed after it's invoked.
@@ -206,10 +199,6 @@
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
     void setUdfpsOverlayController(in IUdfpsOverlayController controller);
 
-    // Sets the controller for managing the SideFPS overlay.
-    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
-    void setSidefpsController(in ISidefpsController controller);
-
     // Registers AuthenticationStateListener.
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
     void registerAuthenticationStateListener(AuthenticationStateListener listener);
diff --git a/core/java/android/hardware/fingerprint/ISidefpsController.aidl b/core/java/android/hardware/fingerprint/ISidefpsController.aidl
deleted file mode 100644
index 684f18f..0000000
--- a/core/java/android/hardware/fingerprint/ISidefpsController.aidl
+++ /dev/null
@@ -1,29 +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 android.hardware.fingerprint;
-
-/**
- * Interface for interacting with the side fingerprint sensor (side-fps) overlay.
- * @hide
- */
-oneway interface ISidefpsController {
-
-    // Shows the overlay for the given sensor with a reason from BiometricOverlayConstants.
-    void show(int sensorId, int reason);
-
-    // Hides the overlay.
-    void hide(int sensorId);
-}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 2816f77..1c37aa2 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -94,33 +94,8 @@
     // Keyboard layouts configuration.
     KeyboardLayout[] getKeyboardLayouts();
 
-    KeyboardLayout[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
-
     KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
 
-    String getCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier);
-
-    @EnforcePermission("SET_KEYBOARD_LAYOUT")
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
-            + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
-    void setCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor);
-
-    String[] getEnabledKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
-
-    @EnforcePermission("SET_KEYBOARD_LAYOUT")
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
-            + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
-    void addKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor);
-
-    @EnforcePermission("SET_KEYBOARD_LAYOUT")
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
-            + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
-    void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor);
-
-    // New Keyboard layout config APIs
     KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
             in InputDeviceIdentifier identifier, int userId, in InputMethodInfo imeInfo,
             in InputMethodSubtype imeSubtype);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a1242fb..f949158 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -473,22 +473,21 @@
     }
 
     /**
-     * Returns the descriptors of all supported keyboard layouts appropriate for the specified
-     * input device.
+     * Returns the descriptors of all supported keyboard layouts.
      * <p>
      * The input manager consults the built-in keyboard layouts as well as all keyboard layouts
      * advertised by applications using a {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
      * </p>
      *
-     * @param device The input device to query.
      * @return The ids of all keyboard layouts which are supported by the specified input device.
      *
      * @hide
      */
     @TestApi
     @NonNull
-    public List<String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull InputDevice device) {
-        KeyboardLayout[] layouts = getKeyboardLayoutsForInputDevice(device.getIdentifier());
+    @SuppressLint("UnflaggedApi")
+    public List<String> getKeyboardLayoutDescriptors() {
+        KeyboardLayout[] layouts = getKeyboardLayouts();
         List<String> res = new ArrayList<>();
         for (KeyboardLayout kl : layouts) {
             res.add(kl.getDescriptor());
@@ -511,33 +510,18 @@
     @TestApi
     @NonNull
     public String getKeyboardLayoutTypeForLayoutDescriptor(@NonNull String layoutDescriptor) {
-        KeyboardLayout[] layouts = getKeyboardLayouts();
-        for (KeyboardLayout kl : layouts) {
-            if (layoutDescriptor.equals(kl.getDescriptor())) {
-                return kl.getLayoutType();
-            }
-        }
-        return "";
+        KeyboardLayout layout = getKeyboardLayout(layoutDescriptor);
+        return layout == null ? "" : layout.getLayoutType();
     }
 
     /**
-     * Gets information about all supported keyboard layouts appropriate
-     * for a specific input device.
-     * <p>
-     * The input manager consults the built-in keyboard layouts as well
-     * as all keyboard layouts advertised by applications using a
-     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
-     * </p>
-     *
-     * @return A list of all supported keyboard layouts for a specific
-     * input device.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
     @NonNull
     public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
             @NonNull InputDeviceIdentifier identifier) {
-        return mGlobal.getKeyboardLayoutsForInputDevice(identifier);
+        return new KeyboardLayout[0];
     }
 
     /**
@@ -549,6 +533,7 @@
      *
      * @hide
      */
+    @Nullable
     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
         if (keyboardLayoutDescriptor == null) {
             throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
@@ -562,121 +547,45 @@
     }
 
     /**
-     * Gets the current keyboard layout descriptor for the specified input device.
-     *
-     * @param identifier Identifier for the input device
-     * @return The keyboard layout descriptor, or null if no keyboard layout has been set.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @TestApi
     @Nullable
     public String getCurrentKeyboardLayoutForInputDevice(
             @NonNull InputDeviceIdentifier identifier) {
-        try {
-            return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
+        return null;
     }
 
     /**
-     * Sets the current keyboard layout descriptor for the specified input device.
-     * <p>
-     * This method may have the side-effect of causing the input device in question to be
-     * reconfigured.
-     * </p>
-     *
-     * @param identifier The identifier for the input device.
-     * @param keyboardLayoutDescriptor The keyboard layout descriptor to use, must not be null.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @TestApi
-    @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void setCurrentKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
-            @NonNull String keyboardLayoutDescriptor) {
-        mGlobal.setCurrentKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
+            @NonNull String keyboardLayoutDescriptor) {}
 
     /**
-     * Gets all keyboard layout descriptors that are enabled for the specified input device.
-     *
-     * @param identifier The identifier for the input device.
-     * @return The keyboard layout descriptors.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
     public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
-        if (identifier == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-
-        try {
-            return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
+        return new String[0];
     }
 
     /**
-     * Adds the keyboard layout descriptor for the specified input device.
-     * <p>
-     * This method may have the side-effect of causing the input device in question to be
-     * reconfigured.
-     * </p>
-     *
-     * @param identifier The identifier for the input device.
-     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to add.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
             String keyboardLayoutDescriptor) {
-        if (identifier == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
-
-        try {
-            mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
     }
 
     /**
-     * Removes the keyboard layout descriptor for the specified input device.
-     * <p>
-     * This method may have the side-effect of causing the input device in question to be
-     * reconfigured.
-     * </p>
-     *
-     * @param identifier The identifier for the input device.
-     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to remove.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @TestApi
     @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void removeKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
             @NonNull String keyboardLayoutDescriptor) {
-        if (identifier == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
-
-        try {
-            mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
     }
 
     /**
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 7c104a0..7b29666 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -1068,36 +1068,21 @@
     }
 
     /**
-     * @see InputManager#getKeyboardLayoutsForInputDevice(InputDeviceIdentifier)
+     * TODO(b/330517633): Cleanup the unsupported API
      */
     @NonNull
     public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
             @NonNull InputDeviceIdentifier identifier) {
-        try {
-            return mIm.getKeyboardLayoutsForInputDevice(identifier);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
+        return new KeyboardLayout[0];
     }
 
     /**
-     * @see InputManager#setCurrentKeyboardLayoutForInputDevice
-     * (InputDeviceIdentifier, String)
+     * TODO(b/330517633): Cleanup the unsupported API
      */
-    @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void setCurrentKeyboardLayoutForInputDevice(
             @NonNull InputDeviceIdentifier identifier,
-            @NonNull String keyboardLayoutDescriptor) {
-        Objects.requireNonNull(identifier, "identifier must not be null");
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-        try {
-            mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
-                    keyboardLayoutDescriptor);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
-    }
+            @NonNull String keyboardLayoutDescriptor) {}
+
 
     /**
      * @see InputDevice#getSensorManager()
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 4328d9f..4c5ebe7 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -16,6 +16,9 @@
 
 package android.hardware.input;
 
+import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG;
+import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG;
+import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG;
 import static com.android.hardware.input.Flags.keyboardA11yBounceKeysFlag;
 import static com.android.hardware.input.Flags.keyboardA11ySlowKeysFlag;
 import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag;
@@ -23,6 +26,7 @@
 import static com.android.input.flags.Flags.enableInputFilterRustImpl;
 
 import android.Manifest;
+import android.annotation.FlaggedApi;
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
@@ -465,6 +469,8 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG)
     public static int getAccessibilityBounceKeysThreshold(@NonNull Context context) {
         if (!isAccessibilityBounceKeysFeatureEnabled()) {
             return 0;
@@ -487,6 +493,8 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG)
     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
     public static void setAccessibilityBounceKeysThreshold(@NonNull Context context,
             int thresholdTimeMillis) {
@@ -545,6 +553,8 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG)
     public static int getAccessibilitySlowKeysThreshold(@NonNull Context context) {
         if (!isAccessibilitySlowKeysFeatureFlagEnabled()) {
             return 0;
@@ -567,6 +577,8 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG)
     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
     public static void setAccessibilitySlowKeysThreshold(@NonNull Context context,
             int thresholdTimeMillis) {
@@ -614,6 +626,8 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG)
     public static boolean isAccessibilityStickyKeysEnabled(@NonNull Context context) {
         if (!isAccessibilityStickyKeysFeatureEnabled()) {
             return false;
@@ -635,6 +649,8 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG)
     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
     public static void setAccessibilityStickyKeysEnabled(@NonNull Context context,
             boolean enabled) {
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 2cd7aeb..278e863 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -56,6 +56,7 @@
 import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECTIONLESS_HANDWRITING_ERROR_OTHER;
 import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED;
 import static android.view.inputmethod.Flags.FLAG_CONNECTIONLESS_HANDWRITING;
+import static android.view.inputmethod.Flags.ctrlShiftShortcut;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -400,9 +401,14 @@
     private long mStylusHwSessionsTimeout = STYLUS_HANDWRITING_IDLE_TIMEOUT_MS;
     private Runnable mStylusWindowIdleTimeoutRunnable;
     private long mStylusWindowIdleTimeoutForTest;
-    /** Tracks last {@link MotionEvent#getToolType(int)} used for {@link MotionEvent#ACTION_DOWN}.
+    /**
+     * Tracks last {@link MotionEvent#getToolType(int)} used for {@link MotionEvent#ACTION_DOWN}.
      **/
     private int mLastUsedToolType;
+    /**
+     * Tracks the ctrl+shift shortcut
+     **/
+    private boolean mUsingCtrlShiftShortcut = false;
 
     /**
      * Returns whether {@link InputMethodService} is responsible for rendering the back button and
@@ -759,6 +765,7 @@
 
         private boolean mSystemCallingShowSoftInput;
         private boolean mSystemCallingHideSoftInput;
+        private boolean mSimultaneousStylusAndTouchEnabled;
 
         /**
          * {@inheritDoc}
@@ -1123,9 +1130,11 @@
             mShowInputRequested = false;
 
             mInkWindow.show();
+            mSimultaneousStylusAndTouchEnabled =
+                    com.android.input.flags.Flags.enableMultiDeviceInput();
 
             // deliver previous @param stylusEvents
-            stylusEvents.forEach(InputMethodService.this::onStylusHandwritingMotionEvent);
+            stylusEvents.forEach(this::deliverStylusHandwritingMotionEvent);
 
             // create receiver for channel
             mHandwritingEventReceiver = new InputEventReceiver(channel, Looper.getMainLooper()) {
@@ -1133,10 +1142,15 @@
                 public void onInputEvent(InputEvent event) {
                     boolean handled = false;
                     try {
-                        if (!(event instanceof MotionEvent)) {
+                        if (!(event instanceof MotionEvent motionEvent)) {
                             return;
                         }
-                        onStylusHandwritingMotionEvent((MotionEvent) event);
+                        if (!motionEvent.isStylusPointer()) {
+                            // Handwriting surface is touchable, we don't want these touch events
+                            // to get to the IME.
+                            return;
+                        }
+                        deliverStylusHandwritingMotionEvent(motionEvent);
                         scheduleHandwritingSessionTimeout();
                         handled = true;
                     } finally {
@@ -1147,6 +1161,27 @@
             scheduleHandwritingSessionTimeout();
         }
 
+        private void deliverStylusHandwritingMotionEvent(MotionEvent motionEvent) {
+            onStylusHandwritingMotionEvent(motionEvent);
+            if (!mSimultaneousStylusAndTouchEnabled) {
+                return;
+            }
+            switch (motionEvent.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    // Consume and ignore all touches while stylus is down to prevent
+                    // accidental touches from going to the app while writing.
+                    mPrivOps.setHandwritingSurfaceNotTouchable(false);
+                    break;
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    // Go back to only consuming stylus events so that the user
+                    // can continue to interact with the app using touch
+                    // when the stylus is not down.
+                    mPrivOps.setHandwritingSurfaceNotTouchable(true);
+                    break;
+            }
+        }
+
         /**
          * {@inheritDoc}
          * @hide
@@ -3612,7 +3647,8 @@
             // any KeyEvent keyDown should reset last toolType.
             updateEditorToolTypeInternal(MotionEvent.TOOL_TYPE_UNKNOWN);
         }
-        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
             final ExtractEditText eet = getExtractEditTextIfVisible();
             if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
                 return true;
@@ -3622,14 +3658,33 @@
                 return true;
             }
             return false;
-        } else if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && KeyEvent.metaStateHasModifiers(
+        } else if (keyCode == KeyEvent.KEYCODE_SPACE && KeyEvent.metaStateHasModifiers(
                 event.getMetaState() & ~KeyEvent.META_SHIFT_MASK, KeyEvent.META_CTRL_ON)) {
             if (mDecorViewVisible && mWindowVisible) {
                 int direction = (event.getMetaState() & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                 mPrivOps.switchKeyboardLayoutAsync(direction);
+                event.startTracking();
                 return true;
             }
         }
+
+        // Check if this may be a ctrl+shift shortcut
+        if (ctrlShiftShortcut()) {
+            if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
+                    || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
+                // Potentially Ctrl+Shift shortcut if Ctrl is currently pressed
+                mUsingCtrlShiftShortcut = KeyEvent.metaStateHasModifiers(
+                    event.getMetaState() & ~KeyEvent.META_SHIFT_MASK, KeyEvent.META_CTRL_ON);
+            } else if (keyCode == KeyEvent.KEYCODE_CTRL_LEFT
+                    || keyCode == KeyEvent.KEYCODE_CTRL_RIGHT) {
+                // Potentially Ctrl+Shift shortcut if Shift is currently pressed
+                mUsingCtrlShiftShortcut = KeyEvent.metaStateHasModifiers(
+                    event.getMetaState() & ~KeyEvent.META_CTRL_MASK, KeyEvent.META_SHIFT_ON);
+            } else {
+                mUsingCtrlShiftShortcut = false;
+            }
+        }
+
         return doMovementKey(keyCode, event, MOVEMENT_DOWN);
     }
 
@@ -3671,7 +3726,27 @@
      * them to perform navigation in the underlying application.
      */
     public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+        if (ctrlShiftShortcut()) {
+            if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
+                    || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT
+                    || keyCode == KeyEvent.KEYCODE_CTRL_LEFT
+                    || keyCode == KeyEvent.KEYCODE_CTRL_RIGHT) {
+                if (mUsingCtrlShiftShortcut
+                        && event.hasNoModifiers()) {
+                    mUsingCtrlShiftShortcut = false;
+                    if (mDecorViewVisible && mWindowVisible) {
+                        // Move to the next IME
+                        switchToNextInputMethod(false /* onlyCurrentIme */);
+                        // TODO(b/332937629): Make the event stream consistent again
+                        return true;
+                    }
+                }
+            } else {
+                mUsingCtrlShiftShortcut = false;
+            }
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
             final ExtractEditText eet = getExtractEditTextIfVisible();
             if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
                 return true;
@@ -3679,7 +3754,12 @@
             if (event.isTracking() && !event.isCanceled()) {
                 return handleBack(true);
             }
+        } else if (keyCode == KeyEvent.KEYCODE_SPACE) {
+            if (event.isTracking() && !event.isCanceled()) {
+                return true;
+            }
         }
+
         return doMovementKey(keyCode, event, MOVEMENT_UP);
     }
 
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 6246dd7..91cdf8d 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -124,6 +124,22 @@
             "vcn_network_selection_ipsec_packet_loss_percent_threshold";
 
     /**
+     * Key for detecting unusually large increases in IPsec packet sequence numbers.
+     *
+     * <p>If the sequence number increases by more than this value within a second, it may indicate
+     * an intentional leap on the server's downlink. To avoid false positives, the packet loss
+     * detector will suppress loss reporting.
+     *
+     * <p>By default, there's no maximum limit enforced, prioritizing detection of lossy networks.
+     * To reduce false positives, consider setting an appropriate maximum threshold.
+     *
+     * @hide
+     */
+    @NonNull
+    public static final String VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY =
+            "vcn_network_selection_max_seq_num_increase_per_second";
+
+    /**
      * Key for the list of timeouts in minute to stop penalizing an underlying network candidate
      *
      * @hide
@@ -180,6 +196,7 @@
                 VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
                 VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY,
                 VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY,
+                VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY,
                 VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY,
                 VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
                 VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY,
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index 15d671d..fea2c25 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -35,4 +35,14 @@
     namespace: "vcn"
     description: "Re-evaluate IPsec packet loss on LinkProperties or NetworkCapabilities change"
     bug: "323238888"
+}
+
+flag{
+    name: "handle_seq_num_leap"
+    namespace: "vcn"
+    description: "Do not report bad network when there is a suspected sequence number leap"
+    bug: "332598276"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
 }
\ No newline at end of file
diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
index d681a2c..d1531a1 100644
--- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
+++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
@@ -162,12 +162,21 @@
         result.putInt(IP_VERSION_KEY, params.getIpVersion());
         result.putInt(ENCAP_TYPE_KEY, params.getEncapType());
 
-        // TODO: b/185941731 Make sure IkeSessionParamsUtils is automatically updated when a new
-        // IKE_OPTION is defined in IKE module and added in the IkeSessionParams
         final List<Integer> enabledIkeOptions = new ArrayList<>();
-        for (int option : IKE_OPTIONS) {
-            if (isIkeOptionValid(option) && params.hasIkeOption(option)) {
-                enabledIkeOptions.add(option);
+
+        try {
+            // TODO: b/328844044: Ideally this code should gate the behavior by checking the
+            // com.android.ipsec.flags.enabled_ike_options_api flag but that flag is not accessible
+            // right now. We should either update the code when the flag is accessible or remove the
+            // legacy behavior after VIC SDK finalization
+            enabledIkeOptions.addAll(params.getIkeOptions());
+        } catch (Exception e) {
+            // getIkeOptions throws. It means the API is not available
+            enabledIkeOptions.clear();
+            for (int option : IKE_OPTIONS) {
+                if (isIkeOptionValid(option) && params.hasIkeOption(option)) {
+                    enabledIkeOptions.add(option);
+                }
             }
         }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 3977bdf..2b6b358 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -17,7 +17,6 @@
 package android.os;
 
 import android.Manifest;
-import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -1230,7 +1229,6 @@
         /**
          * Vanilla Ice Cream.
          */
-        @FlaggedApi(Flags.FLAG_ANDROID_OS_BUILD_VANILLA_ICE_CREAM)
         public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT;
     }
 
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index f785cca..a55398a 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -110,6 +110,12 @@
     private static final String DEFAULT_TRACE_BODY = "dmtrace";
     private static final String DEFAULT_TRACE_EXTENSION = ".trace";
 
+    private static final String[] FRAMEWORK_FEATURES = new String[] {
+        "opengl-tracing",
+        "view-hierarchy",
+        "support_boot_stages",
+    };
+
     /**
      * This class is used to retrieved various statistics about the memory mappings for this
      * process. The returned info is broken down by dalvik, native, and other. All results are in kB.
@@ -1106,6 +1112,17 @@
     }
 
     /**
+     * Returns an array of strings that identify Framework features. This is
+     * used by DDMS to determine what sorts of operations the Framework can
+     * perform.
+     *
+     * @hide
+     */
+    public static String[] getFeatureList() {
+        return FRAMEWORK_FEATURES;
+    }
+
+    /**
      * Change the JDWP port.
      *
      * @deprecated no longer needed or useful
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index d97ea54..e057a85 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -18,16 +18,21 @@
 package android.os;
 
 import android.os.IHintSession;
+import android.hardware.power.SessionConfig;
+import android.hardware.power.SessionTag;
 
 /** {@hide} */
 interface IHintManager {
     /**
      * Creates a {@link Session} for the given set of threads and associates to a binder token.
+     * Returns a config if creation is not supported, and HMS had to use the
+     * legacy creation method.
      */
-    IHintSession createHintSession(in IBinder token, in int[] tids, long durationNanos);
+    IHintSession createHintSessionWithConfig(in IBinder token, in int[] threadIds,
+            in long durationNanos, in SessionTag tag, out @nullable SessionConfig config);
 
     /**
-     * Get preferred rate limit in nano second.
+     * Get preferred rate limit in nanoseconds.
      */
     long getHintSessionPreferredRate();
 
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 2fe115f..5b711c9 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -25,8 +25,6 @@
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 
-import dalvik.annotation.optimization.CriticalNative;
-
 import java.io.FileDescriptor;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -80,7 +78,6 @@
     private native static void nativeDestroy(long ptr);
     @UnsupportedAppUsage
     private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
-    @CriticalNative
     private native static void nativeWake(long ptr);
     private native static boolean nativeIsPolling(long ptr);
     private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
diff --git a/core/java/android/os/OomKillRecord.java b/core/java/android/os/OomKillRecord.java
index ca1d49a..78fbce6 100644
--- a/core/java/android/os/OomKillRecord.java
+++ b/core/java/android/os/OomKillRecord.java
@@ -25,7 +25,7 @@
  * Note that this class fields' should be equivalent to the struct
  * <b>OomKill</b> inside
  * <pre>
- * system/memory/libmeminfo/libmemevents/include/memevents.h
+ * system/memory/libmeminfo/libmemevents/include/memevents/bpf_types.h
  * </pre>
  *
  * @hide
@@ -36,14 +36,27 @@
     private int mUid;
     private String mProcessName;
     private short mOomScoreAdj;
+    private long mTotalVmInKb;
+    private long mAnonRssInKb;
+    private long mFileRssInKb;
+    private long mShmemRssInKb;
+    private long mPgTablesInKb;
 
     public OomKillRecord(long timeStampInMillis, int pid, int uid,
-                            String processName, short oomScoreAdj) {
+                            String processName, short oomScoreAdj,
+                            long totalVmInKb, long anonRssInKb,
+                            long fileRssInKb, long shmemRssInKb,
+                            long pgTablesInKb) {
         this.mTimeStampInMillis = timeStampInMillis;
         this.mPid = pid;
         this.mUid = uid;
         this.mProcessName = processName;
         this.mOomScoreAdj = oomScoreAdj;
+        this.mTotalVmInKb = totalVmInKb;
+        this.mAnonRssInKb = anonRssInKb;
+        this.mFileRssInKb = fileRssInKb;
+        this.mShmemRssInKb = shmemRssInKb;
+        this.mPgTablesInKb = pgTablesInKb;
     }
 
     /**
@@ -55,7 +68,8 @@
         FrameworkStatsLog.write(
                 FrameworkStatsLog.KERNEL_OOM_KILL_OCCURRED,
                 mUid, mPid, mOomScoreAdj, mTimeStampInMillis,
-                mProcessName);
+                mProcessName, mTotalVmInKb, mAnonRssInKb,
+                mFileRssInKb, mShmemRssInKb, mPgTablesInKb);
     }
 
     public long getTimestampMilli() {
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 35a3a5f..136c45d 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -863,6 +863,28 @@
     }
 
     /** @hide */
+    public void removeClassCookie(Class clz, Object expectedCookie) {
+        if (mClassCookies != null) {
+            Object removedCookie = mClassCookies.remove(clz);
+            if (removedCookie != expectedCookie) {
+                Log.wtf(TAG, "Expected to remove " + expectedCookie + " (with key=" + clz
+                        + ") but instead removed " + removedCookie);
+            }
+        } else {
+            Log.wtf(TAG, "Expected to remove " + expectedCookie + " (with key=" + clz
+                    + ") but no cookies were present");
+        }
+    }
+
+    /**
+     * Whether {@link #setClassCookie} has been called with the specified {@code clz}.
+     * @hide
+     */
+    public boolean hasClassCookie(Class clz) {
+        return mClassCookies != null && mClassCookies.containsKey(clz);
+    }
+
+    /** @hide */
     public final void adoptClassCookies(Parcel from) {
         mClassCookies = from.mClassCookies;
     }
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 8a17742..bb74a3e 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -1436,10 +1436,10 @@
      * @throws IOException if the recovery system service could not be contacted
      */
     private boolean requestLskf(String packageName, IntentSender sender) throws IOException {
-        Log.i(TAG, String.format("<%s> is requesting LSFK", packageName));
+        Log.i(TAG, TextUtils.formatSimple("Package<%s> requesting LSKF", packageName));
         try {
             boolean validRequest = mService.requestLskf(packageName, sender);
-            Log.i(TAG, String.format("LSKF Request isValid = %b", validRequest));
+            Log.i(TAG, TextUtils.formatSimple("LSKF Request isValid = %b", validRequest));
             return validRequest;
         } catch (RemoteException | SecurityException e) {
             throw new IOException("could not request LSKF capture", e);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f172c3e..857a85d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -705,7 +705,7 @@
      * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_BLUETOOTH}
      * can set this restriction using the DevicePolicyManager APIs mentioned below.
      *
-     * <p>Default is <code>true</code> for managed profiles and false otherwise.
+     * <p>Default is <code>true</code> for managed and private profiles, false otherwise.
      *
      * <p>When a device upgrades to {@link android.os.Build.VERSION_CODES#O}, the system sets it
      * for all existing managed profiles.
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index ad74a9f..2ceb1c7 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -37,8 +37,10 @@
  * real-time.
  * @hide
  */
[email protected]
 @SystemApi
 public final class WifiActivityEnergyInfo implements Parcelable {
+    private static final long DEFERRED_ENERGY_ESTIMATE = -1;
     @ElapsedRealtimeLong
     private final long mTimeSinceBootMillis;
     @StackState
@@ -52,7 +54,7 @@
     @IntRange(from = 0)
     private final long mControllerIdleDurationMillis;
     @IntRange(from = 0)
-    private final long mControllerEnergyUsedMicroJoules;
+    private long mControllerEnergyUsedMicroJoules;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -99,9 +101,10 @@
                 rxDurationMillis,
                 scanDurationMillis,
                 idleDurationMillis,
-                calculateEnergyMicroJoules(txDurationMillis, rxDurationMillis, idleDurationMillis));
+                DEFERRED_ENERGY_ESTIMATE);
     }
 
+    @android.ravenwood.annotation.RavenwoodReplace
     private static long calculateEnergyMicroJoules(
             long txDurationMillis, long rxDurationMillis, long idleDurationMillis) {
         final Context context = ActivityThread.currentActivityThread().getSystemContext();
@@ -125,6 +128,11 @@
                 * voltage);
     }
 
+    private static long calculateEnergyMicroJoules$ravenwood(long txDurationMillis,
+            long rxDurationMillis, long idleDurationMillis) {
+        return 0;
+    }
+
     /** @hide */
     public WifiActivityEnergyInfo(
             @ElapsedRealtimeLong long timeSinceBootMillis,
@@ -152,7 +160,7 @@
                 + " mControllerRxDurationMillis=" + mControllerRxDurationMillis
                 + " mControllerScanDurationMillis=" + mControllerScanDurationMillis
                 + " mControllerIdleDurationMillis=" + mControllerIdleDurationMillis
-                + " mControllerEnergyUsedMicroJoules=" + mControllerEnergyUsedMicroJoules
+                + " mControllerEnergyUsedMicroJoules=" + getControllerEnergyUsedMicroJoules()
                 + " }";
     }
 
@@ -231,6 +239,11 @@
     /** Get the energy consumed by Wifi, in microjoules. */
     @IntRange(from = 0)
     public long getControllerEnergyUsedMicroJoules() {
+        if (mControllerEnergyUsedMicroJoules == DEFERRED_ENERGY_ESTIMATE) {
+            mControllerEnergyUsedMicroJoules = calculateEnergyMicroJoules(
+                    mControllerTxDurationMillis, mControllerRxDurationMillis,
+                    mControllerIdleDurationMillis);
+        }
         return mControllerEnergyUsedMicroJoules;
     }
 
diff --git a/core/java/android/os/storage/ICeStorageLockEventListener.java b/core/java/android/os/storage/ICeStorageLockEventListener.java
new file mode 100644
index 0000000..f16a7fe
--- /dev/null
+++ b/core/java/android/os/storage/ICeStorageLockEventListener.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+
+/**
+ * Callback class for receiving CE storage lock events from StorageManagerService.
+ * @hide
+ */
+public interface ICeStorageLockEventListener {
+
+    /**
+     * Called when the CE storage corresponding to the userId is locked
+     */
+    void onStorageLocked(int userId);
+}
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 6995ea8..8ba2fa4 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -16,10 +16,12 @@
 
 package android.os.storage;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.pm.UserInfo;
+import android.multiuser.Flags;
 import android.os.IInstalld;
 import android.os.IVold;
 import android.os.ParcelFileDescriptor;
@@ -201,4 +203,18 @@
      */
     public abstract int enableFsverity(IInstalld.IFsveritySetupAuthToken authToken, String filePath,
             String packageName) throws IOException;
+
+    /**
+     * Registers a {@link ICeStorageLockEventListener} for receiving CE storage lock events.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE)
+    public abstract void registerStorageLockEventListener(
+            @NonNull ICeStorageLockEventListener listener);
+
+    /**
+     * Unregisters the {@link ICeStorageLockEventListener} which was registered previously
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE)
+    public abstract void unregisterStorageLockEventListener(
+            @NonNull ICeStorageLockEventListener listener);
 }
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 4ae0a57..55011e5 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -98,6 +98,8 @@
 
     IBinder registerAttributionSource(in AttributionSourceState source);
 
+    int getRegisteredAttributionSourceCount(int uid);
+
     boolean isRegisteredAttributionSource(in AttributionSourceState source);
 
     int checkPermission(String packageName, String permissionName, String persistentDeviceId,
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 3441244d..55bb430 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -240,6 +240,16 @@
     public static final String EXTRA_PERMISSION_USAGES =
             "android.permission.extra.PERMISSION_USAGES";
 
+    /**
+     * Specify what permissions are device aware. Only device aware permissions can be granted to
+     * a remote device.
+     * @hide
+     */
+    public static final Set<String> DEVICE_AWARE_PERMISSIONS =
+            Flags.deviceAwarePermissionsEnabled()
+                    ? Set.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
+                    : Collections.emptySet();
+
     private final @NonNull Context mContext;
 
     private final IPackageManager mPackageManager;
@@ -1665,6 +1675,21 @@
     }
 
     /**
+     * Gets the number of currently registered attribution sources for a particular UID. This should
+     * only be used for testing purposes.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
+    public int getRegisteredAttributionSourceCountForTest(int uid) {
+        try {
+            return mPermissionManager.getRegisteredAttributionSourceCount(uid);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return -1;
+    }
+
+    /**
      * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
      * USED in CTS or local tests.
      *
diff --git a/core/java/android/permission/TEST_MAPPING b/core/java/android/permission/TEST_MAPPING
index 69113ef..a15d9bc 100644
--- a/core/java/android/permission/TEST_MAPPING
+++ b/core/java/android/permission/TEST_MAPPING
@@ -11,5 +11,29 @@
                 }
             ]
         }
+    ],
+    "postsubmit": [
+        {
+            "name": "CtsVirtualDevicesAudioTestCases",
+            "options": [
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "include-filter": "android.virtualdevice.cts.audio.VirtualAudioPermissionTest"
+                }
+            ]
+        },
+        {
+            "name": "CtsVirtualDevicesAppLaunchTestCases",
+            "options": [
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "include-filter": "android.virtualdevice.cts.applaunch.VirtualDevicePermissionTest"
+                }
+            ]
+        }
     ]
 }
\ No newline at end of file
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 92bbadc..6b5e17d 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -126,6 +126,30 @@
 }
 
 flag {
+  name: "sensitive_content_metrics_bugfix"
+  namespace: "permissions"
+  description: "Enables metrics bugfixes for sensitive content/notification features"
+  bug: "312784351"
+  # Referenced in WM where WM starts before DeviceConfig
+  is_fixed_read_only: true
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+  name: "sensitive_content_recents_screenshot_bugfix"
+  namespace: "permissions"
+  description: "Enables recents screenshot bugfixes for sensitive content/notification features"
+  bug: "312784351"
+  # Referenced in WM where WM starts before DeviceConfig
+  is_fixed_read_only: true
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
     name: "device_aware_permissions_enabled"
     is_fixed_read_only: true
     namespace: "permissions"
@@ -156,4 +180,3 @@
     description: "Use runtime permission state to determine appop state"
     bug: "266164193"
 }
-
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b7d421a..16649e8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -686,25 +686,6 @@
             "android.settings.MANAGE_APP_LONG_RUNNING_JOBS";
 
     /**
-     * Activity Action: Show settings to allow configuration of
-     * {@link Manifest.permission#RUN_BACKUP_JOBS} permission.
-     *
-     * Input: Optionally, the Intent's data URI can specify the application package name to
-     * directly invoke the management GUI specific to the package name. For example
-     * "package:com.my.app".
-     * <p>
-     * Output: When a package data uri is passed as input, the activity result is set to
-     * {@link android.app.Activity#RESULT_OK} if the permission was granted to the app. Otherwise,
-     * the result is set to {@link android.app.Activity#RESULT_CANCELED}.
-     *
-     * @hide
-     */
-    @FlaggedApi(Flags.FLAG_BACKUP_TASKS_SETTINGS_SCREEN)
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_REQUEST_RUN_BACKUP_JOBS =
-            "android.settings.REQUEST_RUN_BACKUP_JOBS";
-
-    /**
      * Activity Action: Show settings to allow configuration of cross-profile access for apps
      *
      * Input: Optionally, the Intent's data URI can specify the application package name to
@@ -8005,6 +7986,7 @@
          *
          * @hide
          */
+        @Readable
         public static final String ACCESSIBILITY_BOUNCE_KEYS = "accessibility_bounce_keys";
 
         /**
@@ -8016,6 +7998,7 @@
          *
          * @hide
          */
+        @Readable
         public static final String ACCESSIBILITY_SLOW_KEYS = "accessibility_slow_keys";
 
         /**
@@ -8025,6 +8008,7 @@
          *
          * @hide
          */
+        @Readable
         public static final String ACCESSIBILITY_STICKY_KEYS = "accessibility_sticky_keys";
 
         /**
@@ -9017,6 +9001,16 @@
                 "accessibility_display_daltonizer";
 
         /**
+         * Integer property that determines the saturation level of color correction. Default value
+         * is defined in Settings config.xml.
+         * [0-10] inclusive where 0 would look as if color space adustment is not applied at all.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_DISPLAY_DALTONIZER_SATURATION_LEVEL =
+                "accessibility_display_daltonizer_saturation_level";
+
+        /**
          * Setting that specifies whether automatic click when the mouse pointer stops moving is
          * enabled.
          *
@@ -10977,7 +10971,7 @@
                 "biometric_debug_enabled";
 
         /**
-         * Whether or not virtual sensors are enabled.
+         * Whether or not both fingerprint and face virtual sensors are enabled.
          * @hide
          */
         @TestApi
@@ -10985,6 +10979,22 @@
         public static final String BIOMETRIC_VIRTUAL_ENABLED = "biometric_virtual_enabled";
 
         /**
+         * Whether or not fingerprint virtual sensors are enabled.
+         * @hide
+         */
+        @FlaggedApi("com.android.server.biometrics.face_vhal_feature")
+        public static final String BIOMETRIC_FINGERPRINT_VIRTUAL_ENABLED =
+                "biometric_fingerprint_virtual_enabled";
+
+        /**
+         * Whether or not face virtual sensors are enabled.
+         * @hide
+         */
+        @FlaggedApi("com.android.server.biometrics.face_vhal_feature")
+        public static final String BIOMETRIC_FACE_VIRTUAL_ENABLED =
+                "biometric_face_virtual_enabled";
+
+        /**
          * Whether or not biometric is allowed on Keyguard.
          * @hide
          */
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
index 025aac9..478435b 100644
--- a/core/java/android/security/FileIntegrityManager.java
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -20,6 +20,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.os.IInstalld.IFsveritySetupAuthToken;
@@ -99,8 +101,11 @@
      * @throws IOException If the operation failed.
      *
      * @see <a href="https://www.kernel.org/doc/html/next/filesystems/fsverity.html">Kernel doc</a>
+     * @hide
      */
     @FlaggedApi(Flags.FLAG_FSVERITY_API)
+    @SuppressLint("StreamFiles")
+    @SystemApi
     public void setupFsVerity(@NonNull File file) throws IOException {
         if (!file.isAbsolute()) {
             // fs-verity is to be enabled by installd, which enforces the validation to the
@@ -138,8 +143,11 @@
      * @param file The file to measure the fs-verity digest.
      * @return The fs-verity digest in byte[], null if none.
      * @see <a href="https://www.kernel.org/doc/html/next/filesystems/fsverity.html">Kernel doc</a>
+     * @hide
      */
     @FlaggedApi(Flags.FLAG_FSVERITY_API)
+    @SuppressLint("StreamFiles")
+    @SystemApi
     public @Nullable byte[] getFsVerityDigest(@NonNull File file) throws IOException {
         return VerityUtils.getFsverityDigest(file.getPath());
     }
diff --git a/core/java/android/security/IFileIntegrityService.aidl b/core/java/android/security/IFileIntegrityService.aidl
index 1a6cf88..ddb662ad 100644
--- a/core/java/android/security/IFileIntegrityService.aidl
+++ b/core/java/android/security/IFileIntegrityService.aidl
@@ -28,6 +28,8 @@
     boolean isAppSourceCertificateTrusted(in byte[] certificateBytes, in String packageName);
 
     IInstalld.IFsveritySetupAuthToken createAuthToken(in ParcelFileDescriptor authFd);
+
+    @EnforcePermission("SETUP_FSVERITY")
     int setupFsverity(IInstalld.IFsveritySetupAuthToken authToken, in String filePath,
             in String packageName);
 }
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index e6a84df..269839b 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -37,7 +37,6 @@
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -642,7 +641,7 @@
 
         @Override
         public void onFillCredentialRequest(FillRequest request, IFillCallback callback,
-                IAutoFillManagerClient autofillClientCallback) {
+                IBinder autofillClientCallback) {
             ICancellationSignal transport = CancellationSignal.createTransport();
             try {
                 callback.onCancellable(transport);
@@ -724,7 +723,7 @@
      */
     public void onFillCredentialRequest(@NonNull FillRequest request,
             @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback,
-            @NonNull IAutoFillManagerClient autofillClientCallback) {}
+            @NonNull IBinder autofillClientCallback) {}
 
     /**
      * Called by the Android system to convert a credential manager response to a dataset
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index 2c2feae..3b64b8a 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -16,13 +16,13 @@
 
 package android.service.autofill;
 
+import android.os.IBinder;
 import android.service.autofill.ConvertCredentialRequest;
 import android.service.autofill.IConvertCredentialCallback;
 import android.service.autofill.FillRequest;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
 import android.service.autofill.SaveRequest;
-import android.view.autofill.IAutoFillManagerClient;
 import com.android.internal.os.IResultReceiver;
 
 /**
@@ -34,7 +34,7 @@
     void onConnectedStateChanged(boolean connected);
     void onFillRequest(in FillRequest request, in IFillCallback callback);
     void onFillCredentialRequest(in FillRequest request, in IFillCallback callback,
-        in IAutoFillManagerClient client);
+        in IBinder client);
     void onSaveRequest(in SaveRequest request, in ISaveCallback callback);
     void onSavedPasswordCountRequest(in IResultReceiver receiver);
     void onConvertCredentialRequest(in ConvertCredentialRequest convertCredentialRequest, in IConvertCredentialCallback convertCredentialCallback);
diff --git a/core/java/android/service/credentials/CredentialProviderInfoFactory.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
index c6d3d9b..92f2c32 100644
--- a/core/java/android/service/credentials/CredentialProviderInfoFactory.java
+++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
@@ -65,7 +65,7 @@
  * @hide
  */
 public final class CredentialProviderInfoFactory {
-    private static final String TAG = "CredentialProviderInfoFactory";
+    private static final String TAG = CredentialManager.TAG;
 
     private static final String TAG_CREDENTIAL_PROVIDER = "credential-provider";
     private static final String TAG_CAPABILITIES = "capabilities";
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 9a02b74b..5da0cb4 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -79,6 +79,11 @@
             mService.endDream(this);
         }
 
+        @Override
+        public void comeToFront() {
+            mService.comeToFront(this);
+        }
+
         private void onExitRequested() {
             try {
                 mDreamOverlayCallback.onExitRequested();
@@ -130,6 +135,16 @@
         });
     }
 
+    private void comeToFront(OverlayClient client) {
+        mExecutor.execute(() -> {
+            if (mCurrentClient != client) {
+                return;
+            }
+
+            onComeToFront();
+        });
+    }
+
     private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
         @Override
         public void getClient(IDreamOverlayClientCallback callback) {
@@ -190,6 +205,13 @@
     public void onWakeUp() {}
 
     /**
+     * This method is overridden by implementations to handle when the dream is coming to the front
+     * (after having lost focus to something on top of it).
+     * @hide
+     */
+    public void onComeToFront() {}
+
+    /**
      * 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)}.
      *
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 353828c..c26d83c 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.service.dreams.Flags.dreamHandlesConfirmKeys;
+import static android.service.dreams.Flags.dreamTracksFocus;
 
 import android.annotation.FlaggedApi;
 import android.annotation.IdRes;
@@ -52,6 +53,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.controls.flags.Flags;
+import android.service.dreams.utils.DreamAccessibility;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.MathUtils;
@@ -273,6 +275,7 @@
     private boolean mDebug = false;
 
     private ComponentName mDreamComponent;
+    private DreamAccessibility mDreamAccessibility;
     private boolean mShouldShowComplications;
 
     private DreamServiceWrapper mDreamServiceWrapper;
@@ -455,6 +458,15 @@
     /** {@inheritDoc} */
     @Override
     public void onWindowFocusChanged(boolean hasFocus) {
+        if (!dreamTracksFocus()) {
+            return;
+        }
+
+        try {
+            mDreamManager.onDreamFocusChanged(hasFocus);
+        } catch (RemoteException ex) {
+            // system server died
+        }
     }
 
     /** {@inheritDoc} */
@@ -664,6 +676,7 @@
      */
     public void setInteractive(boolean interactive) {
         mInteractive = interactive;
+        updateAccessibilityMessage();
     }
 
     /**
@@ -1149,6 +1162,19 @@
         wakeUp(false);
     }
 
+    /**
+     * Tells the dream to come to the front (which in turn tells the overlay to come to the front).
+     */
+    private void comeToFront() {
+        mOverlayConnection.addConsumer(overlay -> {
+            try {
+                overlay.comeToFront();
+            } catch (RemoteException e) {
+                Log.e(mTag, "could not tell overlay to come to front:" + e);
+            }
+        });
+    }
+
     private void wakeUp(boolean fromSystem) {
         if (mDebug) {
             Slog.v(mTag, "wakeUp(): fromSystem=" + fromSystem + ", mWaking=" + mWaking
@@ -1430,7 +1456,7 @@
         // Hide all insets when the dream is showing
         mWindow.getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
         mWindow.setDecorFitsSystemWindows(false);
-
+        updateAccessibilityMessage();
         mWindow.getDecorView().addOnAttachStateChangeListener(
                 new View.OnAttachStateChangeListener() {
                     private Consumer<IDreamOverlayClient> mDreamStartOverlayConsumer;
@@ -1477,6 +1503,15 @@
                 });
     }
 
+    private void updateAccessibilityMessage() {
+        if (mWindow == null) return;
+        if (mDreamAccessibility == null) {
+            final View rootView = mWindow.getDecorView();
+            mDreamAccessibility = new DreamAccessibility(this, rootView);
+        }
+        mDreamAccessibility.updateAccessibilityConfiguration(isInteractive());
+    }
+
     private boolean getWindowFlagValue(int flag, boolean defaultValue) {
         return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
     }
@@ -1596,6 +1631,15 @@
         public void wakeUp() {
             mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
         }
+
+        @Override
+        public void comeToFront() {
+            if (!dreamTracksFocus()) {
+                return;
+            }
+
+            mHandler.post(DreamService.this::comeToFront);
+        }
     }
 
     /** @hide */
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index e45384f..85f0368 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -48,4 +48,5 @@
     void setSystemDreamComponent(in ComponentName componentName);
     void registerDreamOverlayService(in ComponentName componentName);
     void startDreamActivity(in Intent intent);
+    void onDreamFocusChanged(in boolean hasFocus);
 }
diff --git a/core/java/android/service/dreams/IDreamOverlayClient.aidl b/core/java/android/service/dreams/IDreamOverlayClient.aidl
index 78b7280..5054d4d 100644
--- a/core/java/android/service/dreams/IDreamOverlayClient.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayClient.aidl
@@ -42,4 +42,7 @@
 
     /** Called when the dream has ended. */
     void endDream();
+
+    /** Called when the dream is coming to the front. */
+    void comeToFront();
 }
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
index 8b5d875..2e2651b 100644
--- a/core/java/android/service/dreams/IDreamService.aidl
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -25,4 +25,5 @@
     void attach(IBinder windowToken, boolean canDoze, boolean isPreviewMode, IRemoteCallback started);
     void detach();
     void wakeUp();
+    void comeToFront();
 }
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
index 2f45f34..0a458bc 100644
--- a/core/java/android/service/dreams/flags.aconfig
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -11,7 +11,7 @@
 
 flag {
   name: "dream_handles_confirm_keys"
-  namespace: "dreams"
+  namespace: "communal"
   description: "This flag enables dreams processing confirm keys to show the bouncer or dismiss "
        "the keyguard"
   bug: "326975875"
@@ -19,3 +19,10 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "dream_tracks_focus"
+  namespace: "communal"
+  description: "This flag enables the ability for dreams to track whether or not they have focus"
+  bug: "331798001"
+}
diff --git a/core/java/android/service/dreams/utils/DreamAccessibility.java b/core/java/android/service/dreams/utils/DreamAccessibility.java
new file mode 100644
index 0000000..c38f41b
--- /dev/null
+++ b/core/java/android/service/dreams/utils/DreamAccessibility.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.dreams.utils;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.internal.R;
+
+/**
+ * {@link DreamAccessibility} allows customization of accessibility
+ * actions for the root view of the dream overlay.
+ * @hide
+ */
+public class DreamAccessibility {
+    private final Context mContext;
+    private final View mView;
+    private final View.AccessibilityDelegate mAccessibilityDelegate;
+
+    public DreamAccessibility(@NonNull Context context, @NonNull View view) {
+        mContext = context;
+        mView = view;
+        mAccessibilityDelegate = createNewAccessibilityDelegate(mContext);
+    }
+
+    /**
+     * @param interactive
+     * Removes and add accessibility configuration depending if the dream is interactive or not
+     */
+    public void updateAccessibilityConfiguration(Boolean interactive) {
+        if (!interactive) {
+            addAccessibilityConfiguration();
+        } else {
+            removeCustomAccessibilityAction();
+        }
+    }
+
+    /**
+     * Configures the accessibility actions for the given root view.
+     */
+    private void addAccessibilityConfiguration() {
+        mView.setAccessibilityDelegate(mAccessibilityDelegate);
+    }
+
+    /**
+     * Removes Configured the accessibility actions for the given root view.
+     */
+    private void removeCustomAccessibilityAction() {
+        if (mView.getAccessibilityDelegate() == mAccessibilityDelegate) {
+            mView.setAccessibilityDelegate(null);
+        }
+    }
+
+    private View.AccessibilityDelegate createNewAccessibilityDelegate(Context context) {
+        return new View.AccessibilityDelegate() {
+            @Override
+            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                for (AccessibilityNodeInfo.AccessibilityAction action : info.getActionList()) {
+                    if (action.getId() == AccessibilityNodeInfo.ACTION_CLICK) {
+                        info.removeAction(action);
+                        break;
+                    }
+                }
+                info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
+                        AccessibilityNodeInfo.ACTION_CLICK,
+                        context.getResources().getString(R.string.dream_accessibility_action_click)
+                ));
+            }
+        };
+    }
+}
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 9696dbc..9c14946 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -20,6 +20,7 @@
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.app.Notification;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -146,8 +147,13 @@
 
     /**
      * Data type: boolean, when true it suggests that the content text of this notification is
-     * sensitive. A notification listener can use this information to redact notifications on locked
-     * devices.
+     * sensitive. The system uses this information to improve privacy around the notification
+     * content. In {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, sensitive notification content is
+     * redacted from updates to most {@link NotificationListenerService
+     * NotificationListenerServices}. Also if an app posts a sensitive notification while
+     * {@link android.media.projection.MediaProjection screen-sharing} is active, that app's windows
+     * are blocked from screen-sharing and a {@link android.widget.Toast Toast} is shown to inform
+     * the user about this.
      */
     public static final String KEY_SENSITIVE_CONTENT = "key_sensitive_content";
 
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 786d768..1d7091c 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -349,23 +349,29 @@
     /**
      * Indicates no explicit setting for which channels may bypass DND when this policy is active.
      * Defaults to {@link #CHANNEL_POLICY_PRIORITY}.
+     *
+     * @hide
      */
     @FlaggedApi(Flags.FLAG_MODES_API)
-    private static final int CHANNEL_POLICY_UNSET = 0;
+    public static final int CHANNEL_POLICY_UNSET = 0;
 
     /**
      * Indicates that channels marked as {@link NotificationChannel#canBypassDnd()} can bypass DND
      * when this policy is active.
+     *
+     * @hide
      */
     @FlaggedApi(Flags.FLAG_MODES_API)
-    private static final int CHANNEL_POLICY_PRIORITY = 1;
+    public static final int CHANNEL_POLICY_PRIORITY = 1;
 
     /**
      * Indicates that no channels can bypass DND when this policy is active, even those marked as
      * {@link NotificationChannel#canBypassDnd()}.
+     *
+     * @hide
      */
     @FlaggedApi(Flags.FLAG_MODES_API)
-    private static final int CHANNEL_POLICY_NONE = 2;
+    public static final int CHANNEL_POLICY_NONE = 2;
 
     /** @hide */
     public ZenPolicy() {
@@ -564,6 +570,13 @@
     }
 
     /**
+     * @hide
+     */
+    public @ChannelType int getAllowedChannels() {
+        return mAllowChannels;
+    }
+
+    /**
      * Whether this policy allows {@link NotificationChannel channels} marked as
      * {@link NotificationChannel#canBypassDnd()} to bypass DND. If {@link #STATE_ALLOW}, these
      * channels may bypass; if {@link #STATE_DISALLOW}, then even notifications from channels
@@ -999,6 +1012,12 @@
             mZenPolicy.mAllowChannels = allow ? CHANNEL_POLICY_PRIORITY : CHANNEL_POLICY_NONE;
             return this;
         }
+
+        /** @hide */
+        public @NonNull Builder allowChannels(@ChannelType int channelType) {
+            mZenPolicy.mAllowChannels = channelType;
+            return this;
+        }
     }
 
     @Override
diff --git a/core/java/android/service/notification/flags.aconfig b/core/java/android/service/notification/flags.aconfig
index b0c55a9..c5b4b41 100644
--- a/core/java/android/service/notification/flags.aconfig
+++ b/core/java/android/service/notification/flags.aconfig
@@ -15,7 +15,17 @@
   namespace: "systemui"
   description: "This flag controls the redacting of sensitive notifications from untrusted NotificationListenerServices"
   bug: "306271190"
+}
+
+flag {
+  name: "redact_sensitive_notifications_big_text_style"
   is_exported: true
+  namespace: "systemui"
+  description: "This flag controls the redacting of BigTextStyle fields in sensitive notifications"
+  bug: "335488909"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
 }
 
 flag {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 0fc51e7..582c90f 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -27,12 +27,15 @@
 import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
+import static com.android.window.flags.Flags.FLAG_OFFLOAD_COLOR_EXTRACTION;
 import static com.android.window.flags.Flags.noConsecutiveVisibilityEvents;
+import static com.android.window.flags.Flags.offloadColorExtraction;
 
 import android.animation.AnimationHandler;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
+import android.annotation.FlaggedApi;
 import android.annotation.FloatRange;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
@@ -832,6 +835,15 @@
         }
 
         /**
+         * Called when the dim amount of the wallpaper changed. This can be used to recompute the
+         * wallpaper colors based on the new dim, and call {@link #notifyColorsChanged()}.
+         * @hide
+         */
+        @FlaggedApi(FLAG_OFFLOAD_COLOR_EXTRACTION)
+        public void onDimAmountChanged(float dimAmount) {
+        }
+
+        /**
          * Called when an application has changed the desired virtual size of
          * the wallpaper.
          */
@@ -1043,6 +1055,10 @@
             }
 
             mPreviousWallpaperDimAmount = mWallpaperDimAmount;
+
+            // after the dim changes, allow colors to be immediately recomputed
+            mLastColorInvalidation = 0;
+            if (offloadColorExtraction()) onDimAmountChanged(mWallpaperDimAmount);
         }
 
         /**
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index fb57921..4281da1 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -1685,6 +1685,10 @@
         public final void onSimultaneousCallingStateChanged(int[] subIds) {
             // not supported on the deprecated interface - Use TelephonyCallback instead
         }
+
+        public final void onCarrierRoamingNtnModeChanged(boolean active) {
+            // not supported on the deprecated interface - Use TelephonyCallback instead
+        }
     }
 
     private void log(String s) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index dc6a035..b8b84d9 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -644,6 +644,15 @@
     public static final int EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED = 41;
 
     /**
+     * Event for listening to changes in carrier roaming non-terrestrial network mode.
+     *
+     * @see CarrierRoamingNtnModeListener
+     *
+     * @hide
+     */
+    public static final int EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED = 42;
+
+    /**
      * @hide
      */
     @IntDef(prefix = {"EVENT_"}, value = {
@@ -687,7 +696,8 @@
             EVENT_TRIGGER_NOTIFY_ANBR,
             EVENT_MEDIA_QUALITY_STATUS_CHANGED,
             EVENT_EMERGENCY_CALLBACK_MODE_CHANGED,
-            EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED
+            EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED,
+            EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TelephonyEvent {
@@ -1686,6 +1696,24 @@
     }
 
     /**
+     * Interface for carrier roaming non-terrestrial network listener.
+     *
+     * @hide
+     */
+    public interface CarrierRoamingNtnModeListener {
+        /**
+         * Callback invoked when carrier roaming non-terrestrial network mode changes.
+         *
+         * @param active {@code true} If the device is connected to carrier roaming
+         *                           non-terrestrial network or was connected within the
+         *                           {CarrierConfigManager
+         *                           #KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT} duration,
+         *                           {code false} otherwise.
+         */
+        void onCarrierRoamingNtnModeChanged(boolean active);
+    }
+
+    /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
      * <p>
@@ -2086,5 +2114,16 @@
             Binder.withCleanCallingIdentity(
                     () -> mExecutor.execute(() -> listener.onCallBackModeStopped(type, reason)));
         }
+
+        public void onCarrierRoamingNtnModeChanged(boolean active) {
+            if (!Flags.carrierEnabledSatelliteFlag()) return;
+
+            CarrierRoamingNtnModeListener listener =
+                    (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get();
+            if (listener == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> listener.onCarrierRoamingNtnModeChanged(active)));
+        }
     }
 }
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index d39c4ce..6160fdb 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1073,6 +1073,24 @@
     }
 
     /**
+     * Notify external listeners that carrier roaming non-terrestrial network mode changed.
+     * @param subId subscription ID.
+     * @param active {@code true} If the device is connected to carrier roaming
+     *                           non-terrestrial network or was connected within the
+     *                           {CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+     *                           duration, {code false} otherwise.
+     * @hide
+     */
+    public void notifyCarrierRoamingNtnModeChanged(int subId, boolean active) {
+        try {
+            sRegistry.notifyCarrierRoamingNtnModeChanged(subId, active);
+        } catch (RemoteException ex) {
+            // system server crash
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Processes potential event changes from the provided {@link TelephonyCallback}.
      *
      * @param telephonyCallback callback for monitoring callback changes to the telephony state.
@@ -1224,6 +1242,10 @@
             eventList.add(
                     TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);
         }
+
+        if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) {
+            eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED);
+        }
         return eventList;
     }
 
diff --git a/core/java/android/text/ClientFlags.java b/core/java/android/text/ClientFlags.java
index 32f05be..5d84d17 100644
--- a/core/java/android/text/ClientFlags.java
+++ b/core/java/android/text/ClientFlags.java
@@ -61,4 +61,11 @@
     public static boolean icuBidiMigration() {
         return TextFlags.isFeatureEnabled(Flags.FLAG_ICU_BIDI_MIGRATION);
     }
+
+    /**
+     * @see Flags#fixMisalignedContextMenu()
+     */
+    public static boolean fixMisalignedContextMenu() {
+        return TextFlags.isFeatureEnabled(Flags.FLAG_FIX_MISALIGNED_CONTEXT_MENU);
+    }
 }
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 38aeb37..161a79b 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -30,6 +30,8 @@
 import android.graphics.Rect;
 import android.graphics.text.LineBreakConfig;
 import android.graphics.text.MeasuredText;
+import android.icu.lang.UCharacter;
+import android.icu.lang.UCharacterDirection;
 import android.icu.text.Bidi;
 import android.text.AutoGrowArray.ByteArray;
 import android.text.AutoGrowArray.FloatArray;
@@ -711,7 +713,12 @@
                 // check the paragraph count here and replace the CR letters and re-calculate
                 // BiDi again.
                 for (int i = 0; i < mTextLength; ++i) {
-                    if (mCopiedBuffer[i] == '\r') {
+                    if (Character.isSurrogate(mCopiedBuffer[i])) {
+                        // All block separators are in BMP.
+                        continue;
+                    }
+                    if (UCharacter.getDirection(mCopiedBuffer[i])
+                            == UCharacterDirection.BLOCK_SEPARATOR) {
                         mCopiedBuffer[i] = OBJECT_REPLACEMENT_CHARACTER;
                     }
                 }
diff --git a/core/java/android/text/TextFlags.java b/core/java/android/text/TextFlags.java
index 770e5c9..9e02460 100644
--- a/core/java/android/text/TextFlags.java
+++ b/core/java/android/text/TextFlags.java
@@ -60,6 +60,7 @@
             Flags.FLAG_USE_BOUNDS_FOR_WIDTH,
             Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE,
             Flags.FLAG_ICU_BIDI_MIGRATION,
+            Flags.FLAG_FIX_MISALIGNED_CONTEXT_MENU,
     };
 
     /**
@@ -73,6 +74,7 @@
             Flags.useBoundsForWidth(),
             Flags.fixLineHeightForLocale(),
             Flags.icuBidiMigration(),
+            Flags.fixMisalignedContextMenu(),
     };
 
     /**
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index bde9c77..3015791 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -477,7 +477,12 @@
             }
             drawBounds.setEmpty();
             float w = measure(mLen, false, fmi, drawBounds, lineInfo);
-            float boundsWidth = drawBounds.width();
+            float boundsWidth;
+            if (w >= 0) {
+                boundsWidth = Math.max(drawBounds.right, w) - Math.min(0, drawBounds.left);
+            } else {
+                boundsWidth = Math.max(drawBounds.right, 0) - Math.min(w, drawBounds.left);
+            }
             if (Math.abs(w) > boundsWidth) {
                 return w;
             } else {
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 559fa96..56df328 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -53,6 +53,19 @@
 }
 
 flag {
+  name: "complete_font_load_in_system_services_ready"
+  namespace: "text"
+  description: "Fix to ensure that font loading is complete on system-services-ready boot phase."
+  # Make read only, as font loading is in the critical boot path which happens before the read-write
+  # flags propagate to the device.
+  is_fixed_read_only: true
+  bug: "327941215"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "phrase_strict_fallback"
   namespace: "text"
   description: "Feature flag for automatic fallback from phrase based line break to strict line break."
@@ -147,3 +160,24 @@
   description: "Feature flag for showing error message when user tries stylus handwriting on a text field which doesn't support it"
   bug: "297962571"
 }
+
+flag {
+  name: "fix_font_update_failure"
+  namespace: "text"
+  description: "There was a bug of updating system font from Android 13 to 14. This flag for fixing the migration failure."
+  is_fixed_read_only: true
+  bug: "331717791"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+  name: "fix_misaligned_context_menu"
+  namespace: "text"
+  description: "Fix the context menu misalignment and incosistent icon size."
+  bug: "332542108"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/core/java/android/tracing/perfetto/DataSource.java b/core/java/android/tracing/perfetto/DataSource.java
index d0c719b..b9ab82c 100644
--- a/core/java/android/tracing/perfetto/DataSource.java
+++ b/core/java/android/tracing/perfetto/DataSource.java
@@ -18,8 +18,6 @@
 
 import android.util.proto.ProtoInputStream;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 /**
  * Templated base class meant to be derived by embedders to create a custom data
  * source.
@@ -73,7 +71,25 @@
      */
     public final void trace(
             TraceFunction<DataSourceInstanceType, TlsStateType, IncrementalStateType> fun) {
-        nativeTrace(mNativeObj, fun);
+        boolean startedIterator = nativePerfettoDsTraceIterateBegin(mNativeObj);
+
+        if (!startedIterator) {
+            return;
+        }
+
+        try {
+            do {
+                int instanceIndex = nativeGetPerfettoDsInstanceIndex(mNativeObj);
+
+                TracingContext<DataSourceInstanceType, TlsStateType, IncrementalStateType> ctx =
+                        new TracingContext<>(this, instanceIndex);
+                fun.trace(ctx);
+
+                ctx.flush();
+            } while (nativePerfettoDsTraceIterateNext(mNativeObj));
+        } finally {
+            nativePerfettoDsTraceIterateBreak(mNativeObj);
+        }
     }
 
     /**
@@ -87,9 +103,7 @@
      * Override this method to create a custom TlsState object for your DataSource. A new instance
      * will be created per trace instance per thread.
      *
-     * NOTE: Should only be called from native side.
      */
-    @VisibleForTesting
     public TlsStateType createTlsState(CreateTlsStateArgs<DataSourceInstanceType> args) {
         return null;
     }
@@ -97,9 +111,8 @@
     /**
      * Override this method to create and use a custom IncrementalState object for your DataSource.
      *
-     * NOTE: Should only be called from native side.
      */
-    protected IncrementalStateType createIncrementalState(
+    public IncrementalStateType createIncrementalState(
             CreateIncrementalStateArgs<DataSourceInstanceType> args) {
         return null;
     }
@@ -154,8 +167,6 @@
             long dataSourcePtr, int bufferExhaustedPolicy);
 
     private static native long nativeCreate(DataSource thiz, String name);
-    private static native void nativeTrace(
-            long nativeDataSourcePointer, TraceFunction traceFunction);
     private static native void nativeFlushAll(long nativeDataSourcePointer);
     private static native long nativeGetFinalizer();
 
@@ -163,4 +174,9 @@
             long dataSourcePtr, int dsInstanceIdx);
     private static native void nativeReleasePerfettoInstanceLocked(
             long dataSourcePtr, int dsInstanceIdx);
+
+    private static native boolean nativePerfettoDsTraceIterateBegin(long dataSourcePtr);
+    private static native boolean nativePerfettoDsTraceIterateNext(long dataSourcePtr);
+    private static native void nativePerfettoDsTraceIterateBreak(long dataSourcePtr);
+    private static native int nativeGetPerfettoDsInstanceIndex(long dataSourcePtr);
 }
diff --git a/core/java/android/tracing/perfetto/TraceFunction.java b/core/java/android/tracing/perfetto/TraceFunction.java
index 62941df..d8854f9 100644
--- a/core/java/android/tracing/perfetto/TraceFunction.java
+++ b/core/java/android/tracing/perfetto/TraceFunction.java
@@ -16,8 +16,6 @@
 
 package android.tracing.perfetto;
 
-import java.io.IOException;
-
 /**
  * The interface for the trace function called from native on a trace call with a context.
  *
@@ -38,6 +36,5 @@
      *
      * @param ctx the tracing context to trace for in the trace function.
      */
-    void trace(TracingContext<DataSourceInstanceType, TlsStateType, IncrementalStateType> ctx)
-            throws IOException;
+    void trace(TracingContext<DataSourceInstanceType, TlsStateType, IncrementalStateType> ctx);
 }
diff --git a/core/java/android/tracing/perfetto/TracingContext.java b/core/java/android/tracing/perfetto/TracingContext.java
index c1a61a7..6b7df54 100644
--- a/core/java/android/tracing/perfetto/TracingContext.java
+++ b/core/java/android/tracing/perfetto/TracingContext.java
@@ -30,20 +30,19 @@
  *
  * @hide
  */
-public class TracingContext<DataSourceInstanceType extends DataSourceInstance,
-        TlsStateType, IncrementalStateType> {
+public class TracingContext<DataSourceInstanceType extends DataSourceInstance, TlsStateType,
+        IncrementalStateType> {
 
-    private final long mContextPtr;
-    private final TlsStateType mTlsState;
-    private final IncrementalStateType mIncrementalState;
+    private final DataSource<DataSourceInstanceType, TlsStateType, IncrementalStateType>
+            mDataSource;
+    private final int mInstanceIndex;
     private final List<ProtoOutputStream> mTracePackets = new ArrayList<>();
 
-    // Should only be created from the native side.
-    private TracingContext(long contextPtr, TlsStateType tlsState,
-            IncrementalStateType incrementalState) {
-        this.mContextPtr = contextPtr;
-        this.mTlsState = tlsState;
-        this.mIncrementalState = incrementalState;
+    TracingContext(DataSource<DataSourceInstanceType, TlsStateType, IncrementalStateType>
+            dataSource,
+            int instanceIndex) {
+        this.mDataSource = dataSource;
+        this.mInstanceIndex = instanceIndex;
     }
 
     /**
@@ -69,18 +68,26 @@
      * Stop timeout expires.
      */
     public void flush() {
-        nativeFlush(this, mContextPtr);
+        nativeFlush(mDataSource.mNativeObj, getAndClearAllPendingTracePackets());
     }
 
     /**
      * Can optionally be used to store custom per-sequence
      * session data, which is not reset when incremental state is cleared
      * (e.g. configuration options).
-     *
+     *h
      * @return The TlsState instance for the tracing thread and instance.
      */
     public TlsStateType getCustomTlsState() {
-        return this.mTlsState;
+        TlsStateType tlsState = (TlsStateType) nativeGetCustomTls(mDataSource.mNativeObj);
+        if (tlsState == null) {
+            final CreateTlsStateArgs<DataSourceInstanceType> args =
+                    new CreateTlsStateArgs<>(mDataSource, mInstanceIndex);
+            tlsState = mDataSource.createTlsState(args);
+            nativeSetCustomTls(mDataSource.mNativeObj, tlsState);
+        }
+
+        return tlsState;
     }
 
     /**
@@ -90,10 +97,18 @@
      * @return The current IncrementalState object instance.
      */
     public IncrementalStateType getIncrementalState() {
-        return this.mIncrementalState;
+        IncrementalStateType incrementalState =
+                (IncrementalStateType) nativeGetIncrementalState(mDataSource.mNativeObj);
+        if (incrementalState == null) {
+            final CreateIncrementalStateArgs<DataSourceInstanceType> args =
+                    new CreateIncrementalStateArgs<>(mDataSource, mInstanceIndex);
+            incrementalState = mDataSource.createIncrementalState(args);
+            nativeSetIncrementalState(mDataSource.mNativeObj, incrementalState);
+        }
+
+        return incrementalState;
     }
 
-    // Called from native to get trace packets
     private byte[][] getAndClearAllPendingTracePackets() {
         byte[][] res = new byte[mTracePackets.size()][];
         for (int i = 0; i < mTracePackets.size(); i++) {
@@ -105,5 +120,11 @@
         return res;
     }
 
-    private static native void nativeFlush(TracingContext thiz, long ctxPointer);
+    private static native void nativeFlush(long dataSourcePtr, byte[][] packetData);
+
+    private static native Object nativeGetCustomTls(long nativeDsPtr);
+    private static native void nativeSetCustomTls(long nativeDsPtr, Object tlsState);
+
+    private static native Object nativeGetIncrementalState(long nativeDsPtr);
+    private static native void nativeSetIncrementalState(long nativeDsPtr, Object incrementalState);
 }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 4d4cb6c..815fc58 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -87,12 +87,6 @@
             "settings_need_connected_ble_device_for_broadcast";
 
     /**
-     * Enable new language and keyboard settings UI
-     * @hide
-     */
-    public static final String SETTINGS_NEW_KEYBOARD_UI = "settings_new_keyboard_ui";
-
-    /**
      * Enable new modifier key settings UI
      * @hide
      */
@@ -221,7 +215,6 @@
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true");
         DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true");
         DEFAULT_FLAGS.put(SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, "true");
-        DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_UI, "true");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY, "true");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "true");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE, "false");
@@ -249,7 +242,6 @@
         PERSISTENT_FLAGS.add(SETTINGS_SUPPORT_LARGE_SCREEN);
         PERSISTENT_FLAGS.add(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS);
         PERSISTENT_FLAGS.add(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME);
-        PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_UI);
         PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY);
         PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_TRACKPAD);
         PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE);
diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java
index ea7efc7..c1ed19f 100644
--- a/core/java/android/util/PackageUtils.java
+++ b/core/java/android/util/PackageUtils.java
@@ -203,9 +203,8 @@
         }
 
         File f = new File(filePath);
-        try {
-            DigestInputStream digestInputStream = new DigestInputStream(new FileInputStream(f),
-                    messageDigest);
+        try (DigestInputStream digestInputStream = new DigestInputStream(new FileInputStream(f),
+                messageDigest)) {
             while (digestInputStream.read(fileBuffer) != -1);
         } catch (IOException e) {
             e.printStackTrace();
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 3e61539..f315f55 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -48,6 +48,7 @@
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityRequestPreparer;
+import android.view.accessibility.Flags;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 import android.window.ScreenCapture;
 
@@ -1286,6 +1287,15 @@
     }
 
     /**
+     * Destroy {@link AccessibilityInteractionController} and clean up the pending actions.
+     */
+    public void destroy() {
+        if (Flags.preventLeakingViewrootimpl()) {
+            mHandler.removeCallbacksAndMessages(null);
+        }
+    }
+
+    /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
      * querying window content. It is responsible to prefetch a batch of
      * AccessibilityNodeInfos in addition to the one for a requested node.
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index f4dadbb..beb4d95 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import static com.android.text.flags.Flags.handwritingCursorPosition;
+import static com.android.text.flags.Flags.handwritingUnsupportedMessage;
 
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
@@ -607,7 +608,9 @@
             final View candidateView = findBestCandidateView(hoverX, hoverY, /* isHover */ true);
 
             if (candidateView != null) {
-                mCachedHoverTarget = new WeakReference<>(candidateView);
+                if (!handwritingUnsupportedMessage()) {
+                    mCachedHoverTarget = new WeakReference<>(candidateView);
+                }
                 return candidateView;
             }
         }
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 253073a..69228ca 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -83,11 +83,7 @@
      */
     public static final int TEXT_HANDLE_MOVE = 9;
 
-    /**
-     * The user unlocked the device
-     * @hide
-     */
-    public static final int ENTRY_BUMP = 10;
+    // REMOVED: ENTRY_BUMP = 10
 
     /**
      * The user has moved the dragged object within a droppable area.
@@ -230,6 +226,22 @@
     public static final int LONG_PRESS_POWER_BUTTON = 10003;
 
     /**
+     * A haptic effect to signal the confirmation of a user biometric authentication
+     * (e.g. fingerprint reading).
+     * This is a private constant to be used only by system apps.
+     * @hide
+     */
+    public static final int BIOMETRIC_CONFIRM = 10004;
+
+    /**
+     * A haptic effect to signal the rejection of a user biometric authentication attempt
+     * (e.g. fingerprint reading).
+     * This is a private constant to be used only by system apps.
+     * @hide
+     */
+    public static final int BIOMETRIC_REJECT = 10005;
+
+    /**
      * Flag for {@link View#performHapticFeedback(int, int)
      * View.performHapticFeedback(int, int)}: Ignore the setting in the
      * view for whether to perform haptic feedback, do it always.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 51d7caa..65d9b3a 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -291,6 +291,15 @@
     int getDefaultDisplayRotation();
 
     /**
+     * Retrieve the display user rotation.
+     * @param displayId Id of the display
+     * @return Rotation one of {@link android.view.Surface#ROTATION_0},
+     *        {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
+     *        {@link android.view.Surface#ROTATION_270} or -1 if display is not found.
+     */
+    int getDisplayUserRotation(int displayId);
+
+    /**
      * Watch the rotation of the specified screen.  Returns the current rotation,
      * calls back when it changes.
      */
diff --git a/core/java/android/view/ImeBackAnimationController.java b/core/java/android/view/ImeBackAnimationController.java
index d14e858..ed049b5 100644
--- a/core/java/android/view/ImeBackAnimationController.java
+++ b/core/java/android/view/ImeBackAnimationController.java
@@ -18,6 +18,7 @@
 
 import static android.view.InsetsController.ANIMATION_TYPE_USER;
 import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 
@@ -28,11 +29,15 @@
 import android.annotation.Nullable;
 import android.graphics.Insets;
 import android.util.Log;
+import android.view.animation.BackGestureInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
+import android.view.inputmethod.ImeTracker;
 import android.window.BackEvent;
 import android.window.OnBackAnimationCallback;
 
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+
 /**
  * Controller for IME predictive back animation
  *
@@ -44,7 +49,7 @@
     private static final int POST_COMMIT_DURATION_MS = 200;
     private static final int POST_COMMIT_CANCEL_DURATION_MS = 50;
     private static final float PEEK_FRACTION = 0.1f;
-    private static final Interpolator STANDARD_DECELERATE = new PathInterpolator(0f, 0f, 0f, 1f);
+    private static final Interpolator BACK_GESTURE = new BackGestureInterpolator();
     private static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
             0.05f, 0.7f, 0.1f, 1f);
     private static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(0.3f, 0f, 1f, 1f);
@@ -56,6 +61,7 @@
     private float mLastProgress = 0f;
     private boolean mTriggerBack = false;
     private boolean mIsPreCommitAnimationInProgress = false;
+    private int mStartRootScrollY = 0;
 
     public ImeBackAnimationController(ViewRootImpl viewRoot) {
         mInsetsController = viewRoot.getInsetsController();
@@ -92,6 +98,7 @@
                     public void onReady(@NonNull WindowInsetsAnimationController controller,
                             @WindowInsets.Type.InsetsType int types) {
                         mWindowInsetsAnimationController = controller;
+                        if (isAdjustPan()) mStartRootScrollY = mViewRoot.mScrollY;
                         if (mIsPreCommitAnimationInProgress) {
                             setPreCommitProgress(mLastProgress);
                         } else {
@@ -140,8 +147,12 @@
             float hiddenY = mWindowInsetsAnimationController.getHiddenStateInsets().bottom;
             float shownY = mWindowInsetsAnimationController.getShownStateInsets().bottom;
             float imeHeight = shownY - hiddenY;
-            float interpolatedProgress = STANDARD_DECELERATE.getInterpolation(progress);
+            float interpolatedProgress = BACK_GESTURE.getInterpolation(progress);
             int newY = (int) (imeHeight - interpolatedProgress * (imeHeight * PEEK_FRACTION));
+            if (mStartRootScrollY != 0) {
+                mViewRoot.setScrollY(
+                        (int) (mStartRootScrollY * (1 - interpolatedProgress * PEEK_FRACTION)));
+            }
             mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, newY), 1f,
                     progress);
         }
@@ -191,6 +202,37 @@
         mPostCommitAnimator.setDuration(
                 triggerBack ? POST_COMMIT_DURATION_MS : POST_COMMIT_CANCEL_DURATION_MS);
         mPostCommitAnimator.start();
+        if (triggerBack) {
+            mInsetsController.setPredictiveBackImeHideAnimInProgress(true);
+            notifyHideIme();
+        }
+        if (mStartRootScrollY != 0) {
+            // RootView is panned, ensure that it is scrolled back to the intended scroll position
+            if (triggerBack) {
+                // requesting ime as invisible
+                mInsetsController.setRequestedVisibleTypes(0, ime());
+                // changes the animation state and notifies RootView of changed insets, which
+                // causes it to reset its scrollY to 0f (animated)
+                mInsetsController.onAnimationStateChanged(ime(), /*running*/ true);
+            } else {
+                // This causes RootView to update its scroll back to the panned position
+                mInsetsController.getHost().notifyInsetsChanged();
+            }
+        }
+    }
+
+    private void notifyHideIme() {
+        ImeTracker.Token statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
+                ImeTracker.ORIGIN_CLIENT,
+                SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL, true);
+        // This notifies the IME that it is being hidden. In response, the IME will unregister the
+        // animation callback, such that new back gestures happening during the post-commit phase of
+        // the hide animation can already dispatch to a new callback.
+        // Note that the IME will call hide() in InsetsController. InsetsController will not animate
+        // that hide request if it sees that ImeBackAnimationController is already animating
+        // the IME away
+        mInsetsController.getHost().getInputMethodManager()
+                .notifyImeHidden(mInsetsController.getHost().getWindowToken(), statsToken);
     }
 
     private void reset() {
@@ -199,6 +241,8 @@
         mLastProgress = 0f;
         mTriggerBack = false;
         mIsPreCommitAnimationInProgress = false;
+        mInsetsController.setPredictiveBackImeHideAnimInProgress(false);
+        mStartRootScrollY = 0;
     }
 
     private void resetPostCommitAnimator() {
@@ -213,6 +257,11 @@
                 == SOFT_INPUT_ADJUST_RESIZE;
     }
 
+    private boolean isAdjustPan() {
+        return (mViewRoot.mWindowAttributes.softInputMode & SOFT_INPUT_MASK_ADJUST)
+                == SOFT_INPUT_ADJUST_PAN;
+    }
+
     private boolean isHideAnimationInProgress() {
         return mPostCommitAnimator != null && mTriggerBack;
     }
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index b300022..62dbc39 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -66,7 +66,12 @@
                     "ImeInsetsSourceConsumer#onAnimationFinished",
                     mController.getHost().getInputMethodManager(), null /* icProto */);
         }
-        final boolean insetsChanged = super.onAnimationStateChanged(running);
+        boolean insetsChanged = super.onAnimationStateChanged(running);
+        if (running && !isShowRequested() && mController.isPredictiveBackImeHideAnimInProgress()) {
+            // IME predictive back animation switched from pre-commit to post-commit.
+            insetsChanged |= applyLocalVisibilityOverride();
+        }
+
         if (!isShowRequested()) {
             mIsRequestedVisibleAwaitingLeash = false;
             if (!running && !mHasPendingRequest) {
@@ -196,11 +201,11 @@
         if (!super.setControl(control, showTypes, hideTypes)) {
             return false;
         }
-        final boolean hasLeash = control != null && control.getLeash() != null;
-        if (!hasLeash && !mIsRequestedVisibleAwaitingLeash) {
+        if (control == null && !mIsRequestedVisibleAwaitingLeash) {
             mController.setRequestedVisibleTypes(0 /* visibleTypes */, getType());
             removeSurface();
         }
+        final boolean hasLeash = control != null && control.getLeash() != null;
         if (hasLeash) {
             mIsRequestedVisibleAwaitingLeash = false;
         }
@@ -243,7 +248,8 @@
      * {@link InputMethodManager#showSoftInput(View, int)} is called.
      */
     public void onShowRequested() {
-        if (mAnimationState == ANIMATION_STATE_HIDE) {
+        if (mAnimationState == ANIMATION_STATE_HIDE
+                || mController.isPredictiveBackImeHideAnimInProgress()) {
             mHasPendingRequest = true;
         }
     }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index b52003f..6c90011 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -22,7 +22,6 @@
 import static android.view.InsetsControllerProto.STATE;
 import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsSource.ID_IME_CAPTION_BAR;
-import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
 import static android.view.WindowInsets.Type.FIRST;
 import static android.view.WindowInsets.Type.LAST;
 import static android.view.WindowInsets.Type.all;
@@ -652,6 +651,7 @@
     private @Appearance int mAppearanceControlled;
     private @Appearance int mAppearanceFromResource;
     private boolean mBehaviorControlled;
+    private boolean mIsPredictiveBackImeHideAnimInProgress;
 
     private final Runnable mPendingControlTimeout = this::abortPendingImeControlRequest;
     private final ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
@@ -685,9 +685,6 @@
 
                 @Override
                 public void onIdNotFoundInState2(int index1, InsetsSource source1) {
-                    if (!CAPTION_ON_SHELL && source1.getType() == captionBar()) {
-                        return;
-                    }
                     if (source1.getId() == ID_IME_CAPTION_BAR) {
                         return;
                     }
@@ -848,15 +845,8 @@
     }
 
     public boolean onStateChanged(InsetsState state) {
-        boolean stateChanged = false;
-        if (!CAPTION_ON_SHELL) {
-            stateChanged = !mState.equals(state, true /* excludesCaptionBar */,
-                    false /* excludesInvisibleIme */)
-                    || captionInsetsUnchanged();
-        } else {
-            stateChanged = !mState.equals(state, false /* excludesCaptionBar */,
-                    false /* excludesInvisibleIme */);
-        }
+        boolean stateChanged = !mState.equals(state, false /* excludesCaptionBar */,
+                false /* excludesInvisibleIme */);
         if (!stateChanged && mLastDispatchedState.equals(state)) {
             return false;
         }
@@ -924,21 +914,6 @@
         }
     }
 
-    private boolean captionInsetsUnchanged() {
-        if (CAPTION_ON_SHELL) {
-            return false;
-        }
-        final InsetsSource source = mState.peekSource(ID_CAPTION_BAR);
-        if (source == null && mCaptionInsetsHeight == 0) {
-            return false;
-        }
-        if (source != null && mCaptionInsetsHeight == source.getFrame().height()) {
-            return false;
-        }
-
-        return true;
-    }
-
     /**
      * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, int, int, int, int, int,
      *      android.util.SparseIntArray)
@@ -1053,6 +1028,14 @@
         reportRequestedVisibleTypes();
     }
 
+    void setPredictiveBackImeHideAnimInProgress(boolean isInProgress) {
+        mIsPredictiveBackImeHideAnimInProgress = isInProgress;
+    }
+
+    boolean isPredictiveBackImeHideAnimInProgress() {
+        return mIsPredictiveBackImeHideAnimInProgress;
+    }
+
     @Override
     public void show(@InsetsType int types) {
         show(types, false /* fromIme */, null /* statsToken */);
@@ -1116,7 +1099,8 @@
                 }
                 continue;
             }
-            if (fromIme && animationType == ANIMATION_TYPE_USER) {
+            if (fromIme && animationType == ANIMATION_TYPE_USER
+                    && !mIsPredictiveBackImeHideAnimInProgress) {
                 // App is already controlling the IME, don't cancel it.
                 if (isIme) {
                     ImeTracker.forLogging().onFailed(
@@ -1212,7 +1196,8 @@
                 }
             }
             if (!requestedVisible && animationType == ANIMATION_TYPE_NONE
-                    || animationType == ANIMATION_TYPE_HIDE) {
+                    || animationType == ANIMATION_TYPE_HIDE || (animationType
+                    == ANIMATION_TYPE_USER && mIsPredictiveBackImeHideAnimInProgress)) {
                 // no-op: already hidden or animating out (because window visibility is
                 // applied before starting animation).
                 if (isImeAnimation) {
@@ -1635,7 +1620,7 @@
         onAnimationStateChanged(removedTypes, false /* running */);
     }
 
-    private void onAnimationStateChanged(@InsetsType int types, boolean running) {
+    void onAnimationStateChanged(@InsetsType int types, boolean running) {
         boolean insetsChanged = false;
         for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
             final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
@@ -1889,24 +1874,6 @@
     }
 
     @Override
-    public void setCaptionInsetsHeight(int height) {
-        // This method is to be removed once the caption is moved to the shell.
-        if (CAPTION_ON_SHELL) {
-            return;
-        }
-        if (mCaptionInsetsHeight != height) {
-            mCaptionInsetsHeight = height;
-            if (mCaptionInsetsHeight != 0) {
-                mState.getOrCreateSource(ID_CAPTION_BAR, captionBar()).setFrame(
-                        mFrame.left, mFrame.top, mFrame.right, mFrame.top + mCaptionInsetsHeight);
-            } else {
-                mState.removeSource(ID_CAPTION_BAR);
-            }
-            mHost.notifyInsetsChanged();
-        }
-    }
-
-    @Override
     public void setImeCaptionBarInsetsHeight(int height) {
         if (!ENABLE_HIDE_IME_CAPTION_BAR) {
             return;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 0ae3e59..56a24e4 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -3783,6 +3783,13 @@
             throw new IllegalArgumentException(
                     "idBits must contain at least one pointer from this motion event");
         }
+        final int currentBits = getPointerIdBits();
+        if ((currentBits & idBits) != idBits) {
+            throw new IllegalArgumentException(
+                    "idBits must be a non-empty subset of the pointer IDs from this MotionEvent, "
+                            + "got idBits: "
+                            + String.format("0x%x", idBits) + " for " + this);
+        }
         MotionEvent event = obtain();
         event.mNativePtr = nativeSplit(event.mNativePtr, this.mNativePtr, idBits);
         return event;
diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java
index 00a5806..5f461c5 100644
--- a/core/java/android/view/PendingInsetsController.java
+++ b/core/java/android/view/PendingInsetsController.java
@@ -45,7 +45,6 @@
     private InsetsController mReplayedInsetsController;
     private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
             = new ArrayList<>();
-    private int mCaptionInsetsHeight = 0;
     private int mImeCaptionBarInsetsHeight = 0;
     private WindowInsetsAnimationControlListener mLoggingListener;
     private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
@@ -99,11 +98,6 @@
     }
 
     @Override
-    public void setCaptionInsetsHeight(int height) {
-        mCaptionInsetsHeight = height;
-    }
-
-    @Override
     public void setImeCaptionBarInsetsHeight(int height) {
         mImeCaptionBarInsetsHeight = height;
     }
@@ -187,9 +181,6 @@
             controller.setSystemBarsAppearanceFromResource(
                     mAppearanceFromResource, mAppearanceFromResourceMask);
         }
-        if (mCaptionInsetsHeight != 0) {
-            controller.setCaptionInsetsHeight(mCaptionInsetsHeight);
-        }
         if (mImeCaptionBarInsetsHeight != 0) {
             controller.setImeCaptionBarInsetsHeight(mImeCaptionBarInsetsHeight);
         }
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 17d1404..7dc151d 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -288,7 +288,7 @@
         if (bitmap == null) {
             throw new IllegalArgumentException("bitmap must not be null");
         }
-        validateHotSpot(bitmap, hotSpotX, hotSpotY);
+        validateHotSpot(bitmap, hotSpotX, hotSpotY, false /* isScaled */);
 
         PointerIcon icon = new PointerIcon(TYPE_CUSTOM);
         icon.mBitmap = bitmap;
@@ -521,7 +521,9 @@
 
         BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
         final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable);
-        validateHotSpot(bitmap, hotSpotX, hotSpotY);
+        // The bitmap and hotspot are loaded from the context, which means it is implicitly scaled
+        // to the current display density, so treat this as a scaled icon when verifying hotspot.
+        validateHotSpot(bitmap, hotSpotX, hotSpotY, true /* isScaled */);
         // Set the properties now that we have successfully loaded the icon.
         mBitmap = bitmap;
         mHotSpotX = hotSpotX;
@@ -535,11 +537,16 @@
                 + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY + "}";
     }
 
-    private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) {
-        if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) {
+    private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY,
+            boolean isScaled) {
+        // Be more lenient when checking the hotspot for scaled icons to account for the restriction
+        // that bitmaps must have an integer size.
+        if (hotSpotX < 0 || (isScaled ? (int) hotSpotX > bitmap.getWidth()
+                : hotSpotX >= bitmap.getWidth())) {
             throw new IllegalArgumentException("x hotspot lies outside of the bitmap area");
         }
-        if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) {
+        if (hotSpotY < 0 || (isScaled ? (int) hotSpotY > bitmap.getHeight()
+                : hotSpotY >= bitmap.getHeight())) {
             throw new IllegalArgumentException("y hotspot lies outside of the bitmap area");
         }
     }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 188ad8f..56edfe72 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -103,9 +103,9 @@
             long nativeObject, float frameRate, int compatibility, int changeFrameRateStrategy);
     private static native void nativeDestroy(long nativeObject);
 
-    // 5MB is a wild guess for what the average surface should be. On most new phones, a full-screen
-    // surface is about 9MB... but not all surfaces are screen size. This should be a nice balance.
-    private static final long SURFACE_NATIVE_ALLOCATION_SIZE_BYTES = 5_000_000;
+    // 5KB is a balanced guess, since these are still pretty heavyweight objects, but if we make
+    // this too big, it can overwhelm the GC.
+    private static final long SURFACE_NATIVE_ALLOCATION_SIZE_BYTES = 5_000;
 
     public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index c95d6ff..a23df79 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -951,7 +951,7 @@
 
     private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
             boolean creating, boolean sizeChanged, boolean hintChanged, boolean relativeZChanged,
-            Transaction surfaceUpdateTransaction) {
+            boolean hdrHeadroomChanged, Transaction surfaceUpdateTransaction) {
         boolean realSizeChanged = false;
 
         mSurfaceLock.lock();
@@ -986,7 +986,7 @@
 
             updateBackgroundVisibility(surfaceUpdateTransaction);
             updateBackgroundColor(surfaceUpdateTransaction);
-            if (mLimitedHdrEnabled) {
+            if (mLimitedHdrEnabled && hdrHeadroomChanged) {
                 surfaceUpdateTransaction.setDesiredHdrHeadroom(
                         mBlastSurfaceControl, mHdrHeadroom);
             }
@@ -1203,7 +1203,7 @@
                 }
 
                 final boolean realSizeChanged = performSurfaceTransaction(viewRoot, translator,
-                        creating, sizeChanged, hintChanged, relativeZChanged,
+                        creating, sizeChanged, hintChanged, relativeZChanged, hdrHeadroomChanged,
                         surfaceUpdateTransaction);
 
                 try {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 5466bf5..ebc86ee 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -202,6 +202,14 @@
     // Set by native code, do not write!
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private long mNativeWindow;
+    // Used for VRR detecting "normal" frame rate rather than "high". This is the previous
+    // interval for drawing. This can be removed when NORMAL is the default rate for Views.
+    // (b/329156944)
+    private long mMinusTwoFrameIntervalMillis = 0;
+    // Used for VRR detecting "normal" frame rate rather than "high". This is the last
+    // frame time for drawing. This can be removed when NORMAL is the default rate for Views.
+    // (b/329156944)
+    private long mLastFrameTimeMillis = 0;
 
     /**
      * Creates a new TextureView.
@@ -890,12 +898,26 @@
      */
     @Override
     protected int calculateFrameRateCategory() {
-        if (mMinusTwoFrameIntervalMillis > 15 && mMinusOneFrameIntervalMillis > 15) {
+        long now = getDrawingTime();
+        // This isn't necessary when the default frame rate is NORMAL (b/329156944)
+        if (mMinusTwoFrameIntervalMillis > 15 && (now - mLastFrameTimeMillis) > 15) {
             return FRAME_RATE_CATEGORY_NORMAL;
         }
         return super.calculateFrameRateCategory();
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    protected void votePreferredFrameRate() {
+        super.votePreferredFrameRate();
+        // This isn't necessary when the default frame rate is NORMAL (b/329156944)
+        long now = getDrawingTime();
+        mMinusTwoFrameIntervalMillis = now - mLastFrameTimeMillis;
+        mLastFrameTimeMillis = now;
+    }
+
     @UnsupportedAppUsage
     private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
             surfaceTexture -> {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bd8e9c6..2a1eb97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -43,6 +43,7 @@
 import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
+import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
 import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
 import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
@@ -226,6 +227,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -909,6 +911,12 @@
     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
 
     /**
+     * The logging tag used by this class when logging verbose and chatty (high volume)
+     * autofill-related messages.
+     */
+    private static final String AUTOFILL_CHATTY_LOG_TAG = "View.Autofill.Chatty";
+
+    /**
      * The logging tag used by this class when logging content capture-related messages.
      */
     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
@@ -1131,7 +1139,7 @@
     private static final int FOCUSABLE_MASK = 0x00000011;
 
     /**
-     * This view will adjust its padding to fit sytem windows (e.g. status bar)
+     * This view will adjust its padding to fit system windows (e.g. status bar)
      */
     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
 
@@ -2426,6 +2434,26 @@
      */
     public static final int FRAME_RATE_CATEGORY_REASON_IDLE = 0x0700_0000;
 
+    /**
+     * This indicates that the frame rate category was chosen because it is currently boosting.
+     * @hide
+     */
+    public static final int FRAME_RATE_CATEGORY_REASON_BOOST = 0x0800_0000;
+
+    /**
+     * This indicates that the frame rate category was chosen because it is currently having
+     * touch boost.
+     * @hide
+     */
+    public static final int FRAME_RATE_CATEGORY_REASON_TOUCH = 0x0900_0000;
+
+    /**
+     * This indicates that the frame rate category was chosen because it is currently having
+     * touch boost.
+     * @hide
+     */
+    public static final int FRAME_RATE_CATEGORY_REASON_CONFLICTED = 0x0A00_0000;
+
     private static final int FRAME_RATE_CATEGORY_REASON_MASK = 0xFFFF_0000;
 
     /**
@@ -2442,6 +2470,8 @@
             toolkitFrameRateSmallUsesPercentReadOnly();
     private static final boolean sToolkitFrameRateViewEnablingReadOnlyFlagValue =
             toolkitFrameRateViewEnablingReadOnly();
+    private static boolean sToolkitFrameRateVelocityMappingReadOnlyFlagValue =
+            toolkitFrameRateVelocityMappingReadOnly();
 
     // Used to set frame rate compatibility.
     @Surface.FrameRateCompatibility int mFrameRateCompatibility =
@@ -3334,16 +3364,17 @@
     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
 
     /**
-     * Live region mode specifying that accessibility services should announce
-     * changes to this view.
+     * Live region mode specifying that accessibility services should notify users of changes to
+     * this view.
      * <p>
      * Use with {@link #setAccessibilityLiveRegion(int)}.
      */
     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
 
     /**
-     * Live region mode specifying that accessibility services should interrupt
-     * ongoing speech to immediately announce changes to this view.
+     * Live region mode specifying that accessibility services should immediately notify users of
+     * changes to this view. For example, a screen reader may interrupt ongoing speech to
+     * immediately announce these changes.
      * <p>
      * Use with {@link #setAccessibilityLiveRegion(int)}.
      */
@@ -3778,6 +3809,7 @@
      *      1                           PFLAG4_IS_COUNTED_AS_SENSITIVE
      *     1                            PFLAG4_HAS_DRAWN
      *    1                             PFLAG4_HAS_MOVED
+     *   1                              PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION
      * |-------|-------|-------|-------|
      */
 
@@ -3923,6 +3955,11 @@
      */
     private static final int PFLAG4_HAS_MOVED = 0x10000000;
 
+    /**
+     * Whether the invalidateViewProperty is involked at current frame.
+     */
+    private static final int PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION = 0x20000000;
+
     /* End of masks for mPrivateFlags4 */
 
     /** @hide */
@@ -5737,23 +5774,12 @@
      */
     private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
 
-    private static final int INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
-    private static final int INFREQUENT_UPDATE_COUNTS = 2;
+    static final float MAX_FRAME_RATE = 140;
 
     // The preferred frame rate of the view that is mainly used for
     // touch boosting, view velocity handling, and TextureView.
     private float mPreferredFrameRate = REQUESTED_FRAME_RATE_CATEGORY_DEFAULT;
 
-    private int mInfrequentUpdateCount = 0;
-    private long mLastUpdateTimeMillis = 0;
-    /**
-     * @hide
-     */
-    protected int mMinusOneFrameIntervalMillis = 0;
-    /**
-     * @hide
-     */
-    protected int mMinusTwoFrameIntervalMillis = 0;
     private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
 
     @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
@@ -8677,8 +8703,8 @@
     @CallSuper
     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
             @Nullable Rect previouslyFocusedRect) {
-        if (DBG) {
-            Log.d(VIEW_LOG_TAG, "onFocusChanged() entered. gainFocus: "
+        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+            Log.v(AUTOFILL_CHATTY_LOG_TAG, "onFocusChanged() entered. gainFocus: "
                     + gainFocus);
         }
         if (gainFocus) {
@@ -8746,8 +8772,8 @@
         if (canNotifyAutofillEnterExitEvent()) {
             AutofillManager afm = getAutofillManager();
             if (afm != null) {
-                if (DBG) {
-                    Log.d(VIEW_LOG_TAG, this + " afm is not null");
+                if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+                    Log.v(AUTOFILL_CHATTY_LOG_TAG, this + " afm is not null");
                 }
                 if (enter) {
                     // We have not been laid out yet, hence cannot evaluate
@@ -8760,8 +8786,8 @@
                     // animation beginning. On the time, the view is not visible
                     // to the user. And then as the animation progresses, the view
                     // becomes visible to the user.
-                    if (DBG) {
-                        Log.d(VIEW_LOG_TAG,
+                    if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+                        Log.v(AUTOFILL_CHATTY_LOG_TAG,
                                 "notifyEnterOrExitForAutoFillIfNeeded:"
                                 + " isLaidOut(): " + isLaidOut()
                                 + " isVisibleToUser(): " + isVisibleToUser()
@@ -8797,14 +8823,17 @@
      *
      * <p>
      * When transitioning from one Activity to another, instead of using
-     * setAccessibilityPaneTitle(), set a descriptive title for its window by using android:label
-     * for the matching <activity> entry in your application’s manifest or updating the title at
-     * runtime with{@link android.app.Activity#setTitle(CharSequence)}.
+     * {@code setAccessibilityPaneTitle()}, set a descriptive title for its window by using
+     * {@code android:label}
+     * for the matching Activity entry in your application's manifest or updating the title at
+     * runtime with {@link android.app.Activity#setTitle(CharSequence)}.
      *
      * <p>
+     * <aside>
      * <b>Note:</b> Use
      * {@link androidx.core.view.ViewCompat#setAccessibilityPaneTitle(View, CharSequence)}
-     * for backwards-compatibility. </aside>
+     * for backwards-compatibility.
+     * </aside>
      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
      *                               View is not a pane.
      *
@@ -8912,7 +8941,7 @@
      * They should not need to specify what exactly is announced to users.
      *
      * <p>
-     * In general, only announce transitions and don’t generate a confirmation message for simple
+     * In general, only announce transitions and don't generate a confirmation message for simple
      * actions like a button press. Label your controls concisely and precisely instead, and for
      * significant UI changes like window changes, use
      * {@link android.app.Activity#setTitle(CharSequence)} and
@@ -10990,28 +11019,28 @@
     }
 
     private boolean isAutofillable() {
-        if (DBG) {
-            Log.d(VIEW_LOG_TAG, "isAutofillable() entered.");
+        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+            Log.v(AUTOFILL_CHATTY_LOG_TAG, "isAutofillable() entered.");
         }
         if (getAutofillType() == AUTOFILL_TYPE_NONE) {
-            if (DBG) {
-                Log.d(VIEW_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
+            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+                Log.v(AUTOFILL_CHATTY_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
             }
             return false;
         }
 
         final AutofillManager afm = getAutofillManager();
         if (afm == null) {
-            if (DBG) {
-                Log.d(VIEW_LOG_TAG, "AutofillManager is null");
+            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+                Log.v(AUTOFILL_CHATTY_LOG_TAG, "AutofillManager is null");
             }
             return false;
         }
 
         // Check whether view is not part of an activity. If it's not, return false.
         if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
-            if (DBG) {
-                Log.d(VIEW_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
+            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+                Log.v(AUTOFILL_CHATTY_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
             }
             return false;
         }
@@ -11022,8 +11051,9 @@
         if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
                 || (!isImportantForAutofill()
                     && afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
-            if (DBG) {
-                Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill()
+            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+                Log.v(AUTOFILL_CHATTY_LOG_TAG,
+                        "isImportantForAutofill(): " + isImportantForAutofill()
                         + "afm.isAutofillable(): " + afm.isAutofillable(this));
             }
             return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
@@ -11031,8 +11061,8 @@
 
         // If the previous condition is not met, fall back to the previous way to trigger fill
         // request based on autofill importance instead.
-        if (DBG) {
-            Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
+        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+            Log.v(AUTOFILL_CHATTY_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
         }
         return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
     }
@@ -11048,8 +11078,8 @@
 
     /** @hide */
     public boolean canNotifyAutofillEnterExitEvent() {
-        if (DBG) {
-            Log.d(VIEW_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
+        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
+            Log.v(AUTOFILL_CHATTY_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
                     + " isAutofillable(): " + isAutofillable()
                     + " isAttachedToWindow(): " + isAttachedToWindow());
         }
@@ -13413,6 +13443,15 @@
     }
 
     /**
+     * @return True if the window has the {@link OnContentApplyWindowInsetsListener}, and this means
+     *         the framework will apply window insets on the content of the window.
+     * @hide
+     */
+    protected boolean hasContentOnApplyWindowInsetsListener() {
+        return mAttachInfo != null && mAttachInfo.mContentOnApplyWindowInsetsListener != null;
+    }
+
+    /**
      * Sets whether or not this view should account for system screen decorations
      * such as the status bar and inset its content; that is, controlling whether
      * the default implementation of {@link #fitSystemWindows(Rect)} will be
@@ -15305,33 +15344,56 @@
      * to the view's content description or text, or to the content descriptions
      * or text of the view's children (where applicable).
      * <p>
-     * To indicate that the user should be notified of changes, use
-     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. Announcements from this region are queued and
-     * do not disrupt ongoing speech.
+     * Different priority levels are available:
+     * <ul>
+     *   <li>
+     *       {@link #ACCESSIBILITY_LIVE_REGION_POLITE}:
+     *       Indicates that updates to the region should be presented to the user. Suitable in most
+     *       cases for prominent updates within app content that don't require the user's immediate
+     *       attention.
+     *   </li>
+     *   <li>
+     *       {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}: Indicates that updates to the region have
+     *       the highest priority and should be presented to the user immediately. This may result
+     *       in disruptive notifications from an accessibility service, which may potentially
+     *       interrupt other feedback or user actions, so it should generally be used only for
+     *       critical, time-sensitive information.
+     *   </li>
+     *   <li>
+     *       {@link #ACCESSIBILITY_LIVE_REGION_NONE}: Disables change announcements (the default for
+     *       most views).
+     *   </li>
+     * </ul>
      * <p>
-     * For example, selecting an option in a dropdown menu may update a panel below with the updated
-     * content. This panel may be marked as a live region with
-     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE} to notify users of the change.
+     * Examples:
+     * <ul>
+     *     <li>
+     *         Selecting an option in a dropdown menu updates a panel below with the updated
+     *         content. This panel may be marked as a live region with
+     *         {@link #ACCESSIBILITY_LIVE_REGION_POLITE} to notify users of the change. A screen
+     *         reader may queue changes as announcements that don't disrupt ongoing speech.
+     *      </li>
+     *      <li>
+     *          An emergency alert may be marked with {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
+     *          to immediately inform users of the emergency.
+     *      </li>
+     * </ul>
      * <p>
-     * For notifying users about errors, such as in a login screen with text that displays an
-     * "incorrect password" notification, that view should send an AccessibilityEvent of type
+     * For error notifications, like an "incorrect password" warning in a login screen, views
+     * should send a {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
+     * {@code AccessibilityEvent} with a content change type
      * {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR} and set
-     * {@link AccessibilityNodeInfo#setError(CharSequence)} instead. Custom widgets should expose
-     * error-setting methods that support accessibility automatically. For example, instead of
-     * explicitly sending this event when using a TextView, use
-     * {@link android.widget.TextView#setError(CharSequence)}.
+     * {@link AccessibilityNodeInfo#setError(CharSequence)}. Custom widgets should provide
+     * error-setting methods that support accessibility. For example, use
+     * {@link android.widget.TextView#setError(CharSequence)} instead of explicitly sending events.
      * <p>
-     * To disable change notifications for this view, use
-     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
-     * mode for most views.
+     * Don't use live regions for frequently-updating UI elements (e.g., progress bars), as this can
+     * overwhelm the user with feedback from accessibility services. If necessary, use
+     * {@link AccessibilityNodeInfo#setMinDurationBetweenContentChanges(Duration)} to throttle
+     * feedback and reduce disruptions.
      * <p>
-     * If the view's changes should interrupt ongoing speech and notify the user
-     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. This may result in disruptive
-     * announcements from an accessibility service, so it should generally be used only to convey
-     * information that is time-sensitive or critical for use of the application. Examples may
-     * include an incoming call or an emergency alert.
-     * <p>
-     * <b>Note:</b> Use {@link androidx.core.view.ViewCompat#setAccessibilityLiveRegion(View, int)}
+     * <aside><b>Note:</b> Use
+     * {@link androidx.core.view.ViewCompat#setAccessibilityLiveRegion(View, int)}
      * for backwards-compatibility. </aside>
      *
      * @param mode The live region mode for this view, one of:
@@ -20796,12 +20858,6 @@
             return;
         }
 
-        // For VRR to vote the preferred frame rate
-        if (sToolkitSetFrameRateReadOnlyFlagValue
-                && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
-            votePreferredFrameRate();
-        }
-
         // Reset content capture caches
         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
         mContentCaptureSessionCached = false;
@@ -20895,6 +20951,7 @@
         } else {
             damageInParent();
         }
+        mPrivateFlags4 |= PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
     }
 
     /**
@@ -20904,11 +20961,6 @@
      */
     protected void damageInParent() {
         if (mParent != null && mAttachInfo != null) {
-            // For VRR to vote the preferred frame rate
-            if (sToolkitSetFrameRateReadOnlyFlagValue
-                    && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
-                votePreferredFrameRate();
-            }
             mParent.onDescendantInvalidated(this, this);
         }
     }
@@ -23596,12 +23648,6 @@
             return renderNode;
         }
 
-        mPrivateFlags4 = (mPrivateFlags4 & ~PFLAG4_HAS_MOVED) | PFLAG4_HAS_DRAWN;
-        if (sToolkitSetFrameRateReadOnlyFlagValue
-                && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
-            updateInfrequentCount();
-        }
-
         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
                 || !renderNode.hasDisplayList()
                 || (mRecreateDisplayList)) {
@@ -23644,6 +23690,14 @@
                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
 
+                    // // For VRR to vote the preferred frame rate
+                    if (sToolkitSetFrameRateReadOnlyFlagValue
+                            && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
+                        votePreferredFrameRate();
+                    }
+
+                    mPrivateFlags4 |= PFLAG4_HAS_DRAWN;
+
                     // Fast path for layouts with no backgrounds
                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         dispatchDraw(canvas);
@@ -23663,9 +23717,20 @@
                 setDisplayListProperties(renderNode);
             }
         } else {
+            if ((mPrivateFlags4 & PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION)
+                    == PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION) {
+                // For VRR to vote the preferred frame rate
+                if (sToolkitSetFrameRateReadOnlyFlagValue
+                        && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
+                    votePreferredFrameRate();
+                }
+                mPrivateFlags4 &= ~PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
+            }
             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
         }
+        mPrivateFlags4 &= ~PFLAG4_HAS_MOVED;
+        mFrameContentVelocity = -1;
         return renderNode;
     }
 
@@ -24764,8 +24829,6 @@
         final int privateFlags = mPrivateFlags;
         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
 
-        mFrameContentVelocity = -1;
-
         /*
          * Draw traversal performs several drawing steps which must be executed
          * in the appropriate order:
@@ -32781,6 +32844,13 @@
             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME);
             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO);
             SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
+            SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_CREDENTIAL_MANAGER);
         }
 
         /**
@@ -33849,84 +33919,118 @@
      * @hide
      */
     protected int calculateFrameRateCategory() {
-        if (mMinusTwoFrameIntervalMillis + mMinusOneFrameIntervalMillis
-                < INFREQUENT_UPDATE_INTERVAL_MILLIS) {
-            return mSizeBasedFrameRateCategoryAndReason;
+        int category;
+        switch (getViewRootImpl().intermittentUpdateState()) {
+            case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT ->
+                    category = FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
+            case ViewRootImpl.INTERMITTENT_STATE_NOT_INTERMITTENT ->
+                    category = mSizeBasedFrameRateCategoryAndReason;
+            default -> category = mLastFrameRateCategory;
         }
-
-        if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
-            return FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
-        }
-        return mLastFrameRateCategory;
+        return category;
     }
 
-    private void votePreferredFrameRate() {
+    /**
+     * Used to vote the preferred frame rate and frame rate category to ViewRootImpl
+     *
+     * @hide
+     */
+    protected void votePreferredFrameRate() {
         // use toolkitSetFrameRate flag to gate the change
         ViewRootImpl viewRootImpl = getViewRootImpl();
-        int width = mRight - mLeft;
-        int height = mBottom - mTop;
-        float alpha = mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
-        int visibility = mViewFlags & VISIBILITY_MASK;
-
-        if (viewRootImpl != null && (width != 0 && height != 0)
-                && alpha != 0 && visibility == View.VISIBLE
-        ) {
-            if (mAttachInfo.mViewVelocityApi) {
-                float velocity = mFrameContentVelocity;
-                int mask = PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN;
-                if (velocity < 0f && (mPrivateFlags4 & mask) == mask) {
-                    // This current calculation is very simple. If something on the screen moved,
-                    // then it votes for the highest velocity. If it doesn't move, then return 0.
-                    velocity = Float.POSITIVE_INFINITY;
-                }
-                if (velocity > 0f) {
-                    float frameRate = convertVelocityToFrameRate(velocity);
-                    viewRootImpl.votePreferredFrameRate(frameRate, FRAME_RATE_COMPATIBILITY_GTE);
-                    return;
-                }
+        if (viewRootImpl == null) {
+            return; // can't vote if not connected
+        }
+        float velocity = mFrameContentVelocity;
+        float frameRate = mPreferredFrameRate;
+        ViewParent parent = mParent;
+        if (velocity <= 0 && Float.isNaN(frameRate)) {
+            // The most common case is when nothing is set, so this special case is called
+            // often.
+            if (mAttachInfo.mViewVelocityApi
+                    && (mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
+                    PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)
+                    && viewRootImpl.shouldCheckFrameRate(false)
+                    && parent instanceof View
+                    && ((View) parent).mFrameContentVelocity <= 0) {
+                viewRootImpl.votePreferredFrameRate(MAX_FRAME_RATE, FRAME_RATE_COMPATIBILITY_GTE);
             }
-            if (!willNotDraw()) {
-                if (sToolkitMetricsForFrameRateDecisionFlagValue) {
-                    float sizePercentage = width * height / mAttachInfo.mDisplayPixelCount;
-                    viewRootImpl.recordViewPercentage(sizePercentage);
-                }
-
-                int frameRateCategory;
-                if (Float.isNaN(mPreferredFrameRate)) {
-                    frameRateCategory = calculateFrameRateCategory();
-                } else if (mPreferredFrameRate < 0) {
-                    switch ((int) mPreferredFrameRate) {
-                        case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->
-                                frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
-                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
-                        case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->
-                                frameRateCategory = FRAME_RATE_CATEGORY_LOW
-                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
-                        case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->
-                                frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
-                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
-                        case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->
-                                frameRateCategory = FRAME_RATE_CATEGORY_HIGH
-                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
-                        default -> {
-                            // invalid frame rate, use default
-                            int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
-                                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-                            frameRateCategory = category
-                                    | FRAME_RATE_CATEGORY_REASON_INVALID;
-                        }
-                    }
-                } else {
-                    viewRootImpl.votePreferredFrameRate(mPreferredFrameRate,
-                            mFrameRateCompatibility);
-                    return;
-                }
-
+            if (!willNotDraw() && viewRootImpl.shouldCheckFrameRateCategory()) {
+                int frameRateCategory = calculateFrameRateCategory();
                 int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
                 int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
                 viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
                 mLastFrameRateCategory = frameRateCategory;
             }
+            return;
+        }
+        if (viewRootImpl.shouldCheckFrameRate(frameRate > 0f)) {
+            float velocityFrameRate = 0f;
+            if (mAttachInfo.mViewVelocityApi) {
+                if (velocity < 0f
+                        && (mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
+                        PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)
+                        && mParent instanceof View
+                        && ((View) mParent).mFrameContentVelocity <= 0
+                ) {
+                    // This current calculation is very simple. If something on the screen
+                    // moved, then it votes for the highest velocity.
+                    velocityFrameRate = MAX_FRAME_RATE;
+                } else if (velocity > 0f) {
+                    velocityFrameRate = convertVelocityToFrameRate(velocity);
+                }
+            }
+            if (velocityFrameRate > 0f || frameRate > 0f) {
+                int compatibility;
+                if (frameRate >= velocityFrameRate) {
+                    compatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
+                } else {
+                    compatibility = FRAME_RATE_COMPATIBILITY_GTE;
+                    frameRate = velocityFrameRate;
+                }
+                viewRootImpl.votePreferredFrameRate(frameRate, compatibility);
+            }
+        }
+
+        if (!willNotDraw() && viewRootImpl.shouldCheckFrameRateCategory()) {
+            if (sToolkitMetricsForFrameRateDecisionFlagValue) {
+                int width = mRight - mLeft;
+                int height = mBottom - mTop;
+                float sizePercentage = width * height / mAttachInfo.mDisplayPixelCount;
+                viewRootImpl.recordViewPercentage(sizePercentage);
+            }
+
+            int frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
+            if (Float.isNaN(frameRate)) {
+                frameRateCategory = calculateFrameRateCategory();
+            } else if (frameRate < 0) {
+                switch ((int) frameRate) {
+                    case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->
+                            frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
+                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+                    case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->
+                            frameRateCategory = FRAME_RATE_CATEGORY_LOW
+                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+                    case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->
+                            frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
+                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+                    case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->
+                            frameRateCategory = FRAME_RATE_CATEGORY_HIGH
+                                    | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+                    default -> {
+                        // invalid frame rate, use default
+                        int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
+                                ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
+                        frameRateCategory = category
+                                | FRAME_RATE_CATEGORY_REASON_INVALID;
+                    }
+                }
+            }
+
+            int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
+            int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
+            viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
+            mLastFrameRateCategory = frameRateCategory;
         }
     }
 
@@ -33934,7 +34038,7 @@
         float density = mAttachInfo.mDensity;
         float velocityDps = velocityPps / density;
         // Choose a frame rate in increments of 10fps
-        return Math.min(140f, 60f + (10f * (float) Math.floor(velocityDps / 300f)));
+        return Math.min(MAX_FRAME_RATE, 60f + (10f * (float) Math.floor(velocityDps / 300f)));
     }
 
     /**
@@ -34009,33 +34113,4 @@
         }
         return 0;
     }
-
-    /**
-     * This function is mainly used for migrating infrequent layer logic
-     * from SurfaceFlinger to Toolkit.
-     * The infrequent layer logic includes:
-     * - NORMAL for infrequent update: FT2-FT1 > 100 && FT3-FT2 > 100.
-     * - HIGH/NORMAL based on size for frequent update: (FT3-FT2) + (FT2 - FT1) < 100.
-     * - otherwise, use the previous category value.
-     */
-    private void updateInfrequentCount() {
-        if (!willNotDraw()) {
-            long currentTimeMillis = getDrawingTime();
-            int timeIntervalMillis =
-                    (int) Math.min(Integer.MAX_VALUE, currentTimeMillis - mLastUpdateTimeMillis);
-            mMinusTwoFrameIntervalMillis = mMinusOneFrameIntervalMillis;
-            mMinusOneFrameIntervalMillis = timeIntervalMillis;
-
-            mLastUpdateTimeMillis = currentTimeMillis;
-            if (mMinusTwoFrameIntervalMillis >= 30 && timeIntervalMillis < 2) {
-                return;
-            }
-            if (timeIntervalMillis >= INFREQUENT_UPDATE_INTERVAL_MILLIS) {
-                mInfrequentUpdateCount = mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS
-                        ? mInfrequentUpdateCount : mInfrequentUpdateCount + 1;
-            } else {
-                mInfrequentUpdateCount = 0;
-            }
-        }
-    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index db1b73f..84cde0d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -27,6 +27,7 @@
 import static android.view.DragEvent.ACTION_DRAG_LOCATION;
 import static android.view.InputDevice.SOURCE_CLASS_NONE;
 import static android.view.InsetsSource.ID_IME;
+import static android.view.Surface.FRAME_RATE_CATEGORY_DEFAULT;
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
@@ -34,14 +35,18 @@
 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_BOOST;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_CONFLICTED;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_IDLE;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_INVALID;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_LARGE;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_REQUESTED;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_SMALL;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_TOUCH;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_UNKNOWN;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_VELOCITY;
+import static android.view.View.MAX_FRAME_RATE;
 import static android.view.View.PFLAG_DRAW_ANIMATION;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -84,6 +89,7 @@
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
@@ -105,12 +111,12 @@
 import static android.view.accessibility.Flags.forceInvertColor;
 import static android.view.accessibility.Flags.reduceWindowContentChangedEventThrottle;
 import static android.view.flags.Flags.sensitiveContentAppProtection;
+import static android.view.flags.Flags.toolkitFrameRateFunctionEnablingReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateTypingReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
+import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
 import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
 import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
-import static android.view.flags.Flags.toolkitFrameRateFunctionEnablingReadOnly;
-import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
 import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
 import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER;
 
@@ -234,6 +240,7 @@
 import android.view.autofill.AutofillManager;
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.ContentCaptureSession;
+import android.view.flags.Flags;
 import android.view.inputmethod.ImeTracker;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Scroller;
@@ -257,7 +264,6 @@
 import com.android.internal.inputmethod.InputMethodDebug;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.SomeArgs;
-import com.android.internal.policy.DecorView;
 import com.android.internal.policy.PhoneFallbackEventHandler;
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
@@ -335,13 +341,6 @@
     private static final boolean USE_ASYNC_PERFORM_HAPTIC_FEEDBACK = true;
 
     /**
-     * Whether the caption is drawn by the shell.
-     * @hide
-     */
-    public static final boolean CAPTION_ON_SHELL =
-            SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", true);
-
-    /**
      * Whether the client (system UI) is handling the transient gesture and the corresponding
      * animation.
      * @hide
@@ -393,6 +392,26 @@
 
     private static final int UNSET_SYNC_ID = -1;
 
+    private static final int INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
+    private static final int INFREQUENT_UPDATE_COUNTS = 2;
+
+    /**
+     * The {@link #intermittentUpdateState()} value when the ViewRootImpl isn't intermittent.
+     */
+    public static final int INTERMITTENT_STATE_NOT_INTERMITTENT = 1;
+
+    /**
+     * The {@link #intermittentUpdateState()} value when the ViewRootImpl is transitioning either
+     * to or from intermittent to not intermittent. This indicates that the frame rate shouldn't
+     * change.
+     */
+    public static final int INTERMITTENT_STATE_IN_TRANSITION = -1;
+
+    /**
+     * The {@link #intermittentUpdateState()} value when the ViewRootImpl is intermittent.
+     */
+    public static final int INTERMITTENT_STATE_INTERMITTENT = 0;
+
     /**
      * Minimum time to wait before reporting changes to keep clear areas.
      */
@@ -624,6 +643,15 @@
     // Is the stylus pointer icon enabled
     private final boolean mIsStylusPointerIconEnabled;
 
+    // VRR check for number of infrequent updates
+    private int mInfrequentUpdateCount = 0;
+    // VRR time of last update
+    private long mLastUpdateTimeMillis = 0;
+    // VRR interval since the previous
+    private int mMinusOneFrameIntervalMillis = 0;
+    // VRR interval between the previous and the frame before
+    private int mMinusTwoFrameIntervalMillis = 0;
+
     /**
      * Update the Choreographer's FrameInfo object with the timing information for the current
      * ViewRootImpl instance. Erase the data in the current ViewFrameInfo to prepare for the next
@@ -1049,10 +1077,10 @@
 
     // The preferred frame rate category of the view that
     // could be updated on a frame-by-frame basis.
-    private int mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
+    private int mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_DEFAULT;
     // The preferred frame rate category of the last frame that
     // could be used to lower frame rate after touch boost
-    private int mLastPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
+    private int mLastPreferredFrameRateCategory = FRAME_RATE_CATEGORY_DEFAULT;
     // The preferred frame rate of the view that is mainly used for
     // touch boosting, view velocity handling, and TextureView.
     private float mPreferredFrameRate = 0;
@@ -1069,6 +1097,7 @@
     // Used to check if there is a message in the message queue
     // for idleness handling.
     private boolean mHasIdledMessage = false;
+    private boolean mDrawnThisFrame = false;
     // Used to check if there is a conflict between different frame rate voting.
     // Take 24 and 30 as an example, 24 is not a divisor of 30.
     // We consider there is a conflict.
@@ -1156,7 +1185,9 @@
     private static boolean sToolkitFrameRateTypingReadOnlyFlagValue;
     private static final boolean sToolkitFrameRateViewEnablingReadOnlyFlagValue;
     private static boolean sToolkitFrameRateVelocityMappingReadOnlyFlagValue =
-            toolkitFrameRateVelocityMappingReadOnly();;
+            toolkitFrameRateVelocityMappingReadOnly();
+    private static boolean sToolkitEnableInvalidateCheckThreadFlagValue =
+            Flags.enableInvalidateCheckThread();
 
     static {
         sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
@@ -1441,6 +1472,7 @@
                 // Keep track of the actual window flags supplied by the client.
                 mClientWindowLayoutFlags = attrs.flags;
 
+                adjustLayoutInDisplayCutoutMode(attrs);
                 setAccessibilityFocus(null, null);
 
                 if (view instanceof RootViewSurfaceTaker) {
@@ -2043,6 +2075,9 @@
             final int appearance = mWindowAttributes.insetsFlags.appearance;
             final int behavior = mWindowAttributes.insetsFlags.behavior;
 
+            // Calling this before copying prevents redundant LAYOUT_CHANGED.
+            final int layoutInDisplayCutoutModeFromCaller = adjustLayoutInDisplayCutoutMode(attrs);
+
             final int changes = mWindowAttributes.copyFrom(attrs);
             if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
                 // Recompute system ui visibility.
@@ -2059,6 +2094,9 @@
                 mWindowAttributes.packageName = mBasePackageName;
             }
 
+            // Restore the layoutInDisplayCutoutMode of the caller;
+            attrs.layoutInDisplayCutoutMode = layoutInDisplayCutoutModeFromCaller;
+
             // Restore preserved flags.
             mWindowAttributes.systemUiVisibility = systemUiVisibility;
             mWindowAttributes.subtreeSystemUiVisibility = subtreeSystemUiVisibility;
@@ -2101,6 +2139,19 @@
         }
     }
 
+    private int adjustLayoutInDisplayCutoutMode(WindowManager.LayoutParams attrs) {
+        final int originalMode = attrs.layoutInDisplayCutoutMode;
+        if ((attrs.privateFlags & PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED) != 0
+                && attrs.isFullscreen()
+                && attrs.getFitInsetsTypes() == 0
+                && attrs.getFitInsetsSides() == 0) {
+            if (originalMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
+                attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+            }
+        }
+        return originalMode;
+    }
+
     void handleAppVisibility(boolean visible) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
             Trace.instant(Trace.TRACE_TAG_VIEW, TextUtils.formatSimple(
@@ -2378,8 +2429,9 @@
 
     @Override
     public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
-        // TODO: Re-enable after camera is fixed or consider targetSdk checking this
-        // checkThread();
+        if (sToolkitEnableInvalidateCheckThreadFlagValue) {
+            checkThread();
+        }
         if ((descendant.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
             mIsAnimating = true;
         }
@@ -3176,22 +3228,6 @@
         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
     }
 
-    private boolean updateCaptionInsets() {
-        if (CAPTION_ON_SHELL) {
-            return false;
-        }
-        if (!(mView instanceof DecorView)) return false;
-        final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight();
-        final Rect captionFrame = new Rect();
-        if (captionInsetsHeight != 0) {
-            captionFrame.set(mWinFrame.left, mWinFrame.top, mWinFrame.right,
-                            mWinFrame.top + captionInsetsHeight);
-        }
-        if (mAttachInfo.mCaptionInsets.equals(captionFrame)) return false;
-        mAttachInfo.mCaptionInsets.set(captionFrame);
-        return true;
-    }
-
     private boolean shouldDispatchCutout() {
         return mWindowAttributes.layoutInDisplayCutoutMode
                         == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
@@ -3645,9 +3681,6 @@
                     mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
                     dispatchApplyInsets = true;
                 }
-                if (updateCaptionInsets()) {
-                    dispatchApplyInsets = true;
-                }
                 if (dispatchApplyInsets || mLastSystemUiVisibility !=
                         mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
                     mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
@@ -4217,17 +4250,29 @@
         // For the variable refresh rate project.
         // We set the preferred frame rate and frame rate category at the end of performTraversals
         // when the values are applicable.
-        setPreferredFrameRate(mPreferredFrameRate);
-        setPreferredFrameRateCategory(mPreferredFrameRateCategory);
-        mFrameRateCategoryHighCount = mFrameRateCategoryHighCount > 0
-                ? mFrameRateCategoryHighCount - 1 : mFrameRateCategoryHighCount;
-        mFrameRateCategoryNormalCount = mFrameRateCategoryNormalCount > 0
-                ? mFrameRateCategoryNormalCount - 1 : mFrameRateCategoryNormalCount;
-        mFrameRateCategoryLowCount = mFrameRateCategoryLowCount > 0
-                ? mFrameRateCategoryLowCount - 1 : mFrameRateCategoryLowCount;
-        mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
-        mPreferredFrameRate = -1;
-        mIsFrameRateConflicted = false;
+        if (mDrawnThisFrame) {
+            mDrawnThisFrame = false;
+            updateInfrequentCount();
+            setCategoryFromCategoryCounts();
+            setPreferredFrameRate(mPreferredFrameRate);
+            setPreferredFrameRateCategory(mPreferredFrameRateCategory);
+            if (!mIsFrameRateConflicted) {
+                mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
+                mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING,
+                        FRAME_RATE_SETTING_REEVALUATE_TIME);
+            }
+            checkIdleness();
+            mFrameRateCategoryHighCount = mFrameRateCategoryHighCount > 0
+                    ? mFrameRateCategoryHighCount - 1 : mFrameRateCategoryHighCount;
+            mFrameRateCategoryNormalCount = mFrameRateCategoryNormalCount > 0
+                    ? mFrameRateCategoryNormalCount - 1 : mFrameRateCategoryNormalCount;
+            mFrameRateCategoryLowCount = mFrameRateCategoryLowCount > 0
+                    ? mFrameRateCategoryLowCount - 1 : mFrameRateCategoryLowCount;
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_DEFAULT;
+            mPreferredFrameRate = -1;
+            mIsFrameRateConflicted = false;
+            mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_UNKNOWN;
+        }
     }
 
     private void createSyncIfNeeded() {
@@ -5907,6 +5952,13 @@
         return handled;
     }
 
+    void setScrollY(int scrollY) {
+        if (mScroller != null) {
+            mScroller.abortAnimation();
+        }
+        mScrollY = scrollY;
+    }
+
     /**
      * @hide
      */
@@ -6098,6 +6150,11 @@
         mAccessibilityInteractionConnectionManager.ensureNoConnection();
         mAccessibilityInteractionConnectionManager.ensureNoDirectConnection();
         removeSendWindowContentChangedCallback();
+        if (android.view.accessibility.Flags.preventLeakingViewrootimpl()
+                && mAccessibilityInteractionController != null) {
+            mAccessibilityInteractionController.destroy();
+            mAccessibilityInteractionController = null;
+        }
 
         destroyHardwareRenderer();
 
@@ -6384,6 +6441,12 @@
                     return "MSG_KEEP_CLEAR_RECTS_CHANGED";
                 case MSG_REFRESH_POINTER_ICON:
                     return "MSG_REFRESH_POINTER_ICON";
+                case MSG_TOUCH_BOOST_TIMEOUT:
+                    return "MSG_TOUCH_BOOST_TIMEOUT";
+                case MSG_CHECK_INVALIDATION_IDLE:
+                    return "MSG_CHECK_INVALIDATION_IDLE";
+                case MSG_FRAME_RATE_SETTING:
+                    return "MSG_FRAME_RATE_SETTING";
             }
             return super.getMessageName(message);
         }
@@ -6648,8 +6711,6 @@
                      */
                     mIsFrameRateBoosting = false;
                     mIsTouchBoosting = false;
-                    setPreferredFrameRateCategory(Math.max(mPreferredFrameRateCategory,
-                            mLastPreferredFrameRateCategory));
                     break;
                 case MSG_CHECK_INVALIDATION_IDLE:
                     if (!mHasInvalidation && !mIsFrameRateBoosting && !mIsTouchBoosting) {
@@ -7695,7 +7756,6 @@
                     mWindowAttributes.type)) {
                 // set the frame rate to the maximum value.
                 mIsTouchBoosting = true;
-                setPreferredFrameRateCategory(mPreferredFrameRateCategory);
             }
             /**
              * We want to lower the refresh rate when MotionEvent.ACTION_UP,
@@ -9025,20 +9085,26 @@
                     mTempInsets, mTempControls, mRelayoutBundle);
             mRelayoutRequested = true;
 
+            if (activityWindowInfoFlag() && mPendingActivityWindowInfo != null) {
+                ActivityWindowInfo outInfo = null;
+                try {
+                    outInfo = mRelayoutBundle.getParcelable(
+                            IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO,
+                            ActivityWindowInfo.class);
+                    mRelayoutBundle.remove(IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO);
+                } catch (IllegalStateException e) {
+                    Log.e(TAG, "Failed to get ActivityWindowInfo from relayout Bundle", e);
+                }
+                if (outInfo != null) {
+                    mPendingActivityWindowInfo.set(outInfo);
+                }
+            }
             final int maybeSyncSeqId = mRelayoutBundle.getInt(
                     IWindowSession.KEY_RELAYOUT_BUNDLE_SEQID);
             if (maybeSyncSeqId > 0) {
                 mSyncSeqId = maybeSyncSeqId;
             }
-            if (activityWindowInfoFlag() && mPendingActivityWindowInfo != null) {
-                final ActivityWindowInfo outInfo = mRelayoutBundle.getParcelable(
-                        IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO,
-                        ActivityWindowInfo.class);
-                if (outInfo != null) {
-                    mPendingActivityWindowInfo.set(outInfo);
-                }
-            }
-            mRelayoutBundle.clear();
+
             mWinFrameInScreen.set(mTmpFrames.frame);
             if (mTranslator != null) {
                 mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame);
@@ -9581,6 +9647,8 @@
             }
             mRemoved = true;
             mOnBackInvokedDispatcher.detachFromWindow();
+            removeVrrMessages();
+
             if (mAdded) {
                 dispatchDetachedFromWindow();
             }
@@ -12485,57 +12553,59 @@
         EventLog.writeEvent(LOGTAG_VIEWROOT_DRAW_EVENT, mTag, msg);
     }
 
+    /**
+     * Sets the mPreferredFrameRateCategory from the high, high_hint, normal, and low counts.
+     */
+    private void setCategoryFromCategoryCounts() {
+        switch (mPreferredFrameRateCategory) {
+            case FRAME_RATE_CATEGORY_LOW -> mFrameRateCategoryLowCount = FRAME_RATE_CATEGORY_COUNT;
+            case FRAME_RATE_CATEGORY_NORMAL ->
+                    mFrameRateCategoryNormalCount = FRAME_RATE_CATEGORY_COUNT;
+            case FRAME_RATE_CATEGORY_HIGH_HINT ->
+                    mFrameRateCategoryHighHintCount = FRAME_RATE_CATEGORY_COUNT;
+            case FRAME_RATE_CATEGORY_HIGH ->
+                    mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
+        }
+        if (mFrameRateCategoryHighCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
+        } else if (mFrameRateCategoryHighHintCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH_HINT;
+        } else if (mFrameRateCategoryNormalCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NORMAL;
+        } else if (mFrameRateCategoryLowCount > 0) {
+            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_LOW;
+        }
+    }
+
     private void setPreferredFrameRateCategory(int preferredFrameRateCategory) {
-        if (!shouldSetFrameRateCategory()
-                || (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE
-                && sToolkitFrameRateVelocityMappingReadOnlyFlagValue)) {
+        if (!shouldSetFrameRateCategory()) {
             return;
         }
-        int categoryFromConflictedFrameRates = FRAME_RATE_CATEGORY_NO_PREFERENCE;
-        if (mIsFrameRateConflicted) {
-            categoryFromConflictedFrameRates = mPreferredFrameRate > 60
-                    ? FRAME_RATE_CATEGORY_HIGH : FRAME_RATE_CATEGORY_NORMAL;
-        }
 
-        int frameRateCategory = mIsTouchBoosting
-                ? FRAME_RATE_CATEGORY_HIGH_HINT
-                : Math.max(preferredFrameRateCategory, categoryFromConflictedFrameRates);
+        int frameRateCategory;
+        int frameRateReason;
+        String view;
 
-        // FRAME_RATE_CATEGORY_HIGH has a higher precedence than FRAME_RATE_CATEGORY_HIGH_HINT
-        // For now, FRAME_RATE_CATEGORY_HIGH_HINT is used for boosting with user interaction.
-        // FRAME_RATE_CATEGORY_HIGH is for boosting without user interaction
-        // (e.g., Window Initialization).
-        if (mIsFrameRateBoosting || mInsetsAnimationRunning
-                || (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE
-                        && mPreferredFrameRate > 0)) {
+        if (mIsFrameRateBoosting || mInsetsAnimationRunning) {
             frameRateCategory = FRAME_RATE_CATEGORY_HIGH;
-            if (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE) {
-                // We've received a velocity, so we'll let the velocity control the
-                // frame rate unless we receive additional motion events.
-                mIsTouchBoosting = false;
-                mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_VELOCITY;
-                mFrameRateCategoryView = null;
-            } else {
-                mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_UNKNOWN;
-            }
+            frameRateReason = FRAME_RATE_CATEGORY_REASON_BOOST;
+            view = null;
+        } else if (mIsTouchBoosting && preferredFrameRateCategory < FRAME_RATE_CATEGORY_HIGH_HINT) {
+            frameRateCategory = FRAME_RATE_CATEGORY_HIGH_HINT;
+            frameRateReason = FRAME_RATE_CATEGORY_REASON_TOUCH;
+            view = null;
+        } else {
+            frameRateCategory = preferredFrameRateCategory;
+            frameRateReason = mFrameRateCategoryChangeReason;
+            view = mFrameRateCategoryView;
         }
 
         try {
-            if (mLastPreferredFrameRateCategory != frameRateCategory) {
+            if (frameRateCategory != FRAME_RATE_CATEGORY_DEFAULT
+                    && mLastPreferredFrameRateCategory != frameRateCategory) {
                 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
-                    String reason = reasonToString(mFrameRateCategoryChangeReason);
-                    String sourceView = mFrameRateCategoryView == null ? "-"
-                            : mFrameRateCategoryView;
-                    if (preferredFrameRateCategory == FRAME_RATE_CATEGORY_HIGH_HINT) {
-                        reason = "touch boost";
-                        sourceView = "-";
-                    } else if (categoryFromConflictedFrameRates == frameRateCategory
-                            && frameRateCategory != preferredFrameRateCategory
-                            && mIsFrameRateConflicted
-                    ) {
-                        reason = "conflict";
-                        sourceView = "-";
-                    }
+                    String reason = reasonToString(frameRateReason);
+                    String sourceView = view == null ? "-" : view;
                     String category = categoryToString(frameRateCategory);
                     Trace.traceBegin(
                             Trace.TRACE_TAG_VIEW, "ViewRootImpl#setFrameRateCategory "
@@ -12545,8 +12615,8 @@
                 if (sToolkitFrameRateFunctionEnablingReadOnlyFlagValue) {
                     mFrameRateTransaction.setFrameRateCategory(mSurfaceControl,
                         frameRateCategory, false).applyAsyncUnsafe();
-                    mLastPreferredFrameRateCategory = frameRateCategory;
                 }
+                mLastPreferredFrameRateCategory = frameRateCategory;
             }
         } catch (Exception e) {
             Log.e(mTag, "Unable to set frame rate category", e);
@@ -12579,24 +12649,21 @@
             case FRAME_RATE_CATEGORY_REASON_VELOCITY -> str = "velocity";
             case FRAME_RATE_CATEGORY_REASON_IDLE -> str = "idle";
             case FRAME_RATE_CATEGORY_REASON_UNKNOWN -> str = "unknown";
+            case FRAME_RATE_CATEGORY_REASON_BOOST -> str = "boost";
+            case FRAME_RATE_CATEGORY_REASON_TOUCH -> str = "touch";
+            case FRAME_RATE_CATEGORY_REASON_CONFLICTED -> str = "conflicted";
             default -> str = String.valueOf(reason);
         }
         return str;
     }
 
     private void setPreferredFrameRate(float preferredFrameRate) {
-        if (!shouldSetFrameRate()) {
-            return;
-        }
-        if (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE
-                && preferredFrameRate > 0 && !sToolkitFrameRateVelocityMappingReadOnlyFlagValue) {
-            mIsTouchBoosting = false;
+        if (!shouldSetFrameRate() || preferredFrameRate < 0) {
             return;
         }
 
         try {
-            if (mLastPreferredFrameRate != preferredFrameRate
-                    && preferredFrameRate >= 0) {
+            if (mLastPreferredFrameRate != preferredFrameRate) {
                 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                     Trace.traceBegin(
                             Trace.TRACE_TAG_VIEW, "ViewRootImpl#setFrameRate "
@@ -12605,9 +12672,9 @@
                 }
                 if (sToolkitFrameRateFunctionEnablingReadOnlyFlagValue) {
                     mFrameRateTransaction.setFrameRate(mSurfaceControl, preferredFrameRate,
-                    mFrameRateCompatibility).applyAsyncUnsafe();
-                    mLastPreferredFrameRate = preferredFrameRate;
+                            mFrameRateCompatibility).applyAsyncUnsafe();
                 }
+                mLastPreferredFrameRate = preferredFrameRate;
             }
         } catch (Exception e) {
             Log.e(mTag, "Unable to set frame rate", e);
@@ -12616,12 +12683,6 @@
         }
     }
 
-    private void sendDelayedEmptyMessage(int message, int delayedTime) {
-        mHandler.removeMessages(message);
-
-        mHandler.sendEmptyMessageDelayed(message, delayedTime);
-    }
-
     private boolean shouldSetFrameRateCategory() {
         // use toolkitSetFrameRate flag to gate the change
         return  mSurface.isValid() && shouldEnableDvrr();
@@ -12650,34 +12711,53 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
     public void votePreferredFrameRateCategory(int frameRateCategory, int reason, View view) {
-        switch (frameRateCategory) {
-            case FRAME_RATE_CATEGORY_LOW -> mFrameRateCategoryLowCount = FRAME_RATE_CATEGORY_COUNT;
-            case FRAME_RATE_CATEGORY_NORMAL ->
-                    mFrameRateCategoryNormalCount = FRAME_RATE_CATEGORY_COUNT;
-            case FRAME_RATE_CATEGORY_HIGH_HINT ->
-                    mFrameRateCategoryHighHintCount = FRAME_RATE_CATEGORY_COUNT;
-            case FRAME_RATE_CATEGORY_HIGH ->
-                    mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
-        }
-
-        int oldCategory = mPreferredFrameRateCategory;
-        if (mFrameRateCategoryHighCount > 0) {
-            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
-        } else if (mFrameRateCategoryHighHintCount > 0) {
-            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH_HINT;
-        } else if (mFrameRateCategoryNormalCount > 0) {
-            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NORMAL;
-        } else if (mFrameRateCategoryLowCount > 0) {
-            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_LOW;
+        if (frameRateCategory > mPreferredFrameRateCategory) {
+            mPreferredFrameRateCategory = frameRateCategory;
+            mFrameRateCategoryChangeReason = reason;
+            // mFrameRateCategoryView = view == null ? "-" : view.getClass().getSimpleName();
         }
         mHasInvalidation = true;
-        checkIdleness();
-        if (mPreferredFrameRateCategory != oldCategory
-                && mPreferredFrameRateCategory == frameRateCategory
-        ) {
-            mFrameRateCategoryChangeReason = reason;
-            mFrameRateCategoryView = view == null ? "null" : view.getClass().getSimpleName();
+        mDrawnThisFrame = true;
+    }
+
+    /**
+     * Returns {@link #INTERMITTENT_STATE_INTERMITTENT} when the ViewRootImpl has only been
+     * updated intermittently, {@link #INTERMITTENT_STATE_NOT_INTERMITTENT} when it is
+     * not updated intermittently, and {@link #INTERMITTENT_STATE_IN_TRANSITION} when it
+     * is transitioning between {@link #INTERMITTENT_STATE_NOT_INTERMITTENT} and
+     * {@link #INTERMITTENT_STATE_INTERMITTENT}.
+     */
+    int intermittentUpdateState() {
+        if (mMinusOneFrameIntervalMillis + mMinusTwoFrameIntervalMillis
+                < INFREQUENT_UPDATE_INTERVAL_MILLIS) {
+            return INTERMITTENT_STATE_NOT_INTERMITTENT;
         }
+        if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
+            return INTERMITTENT_STATE_INTERMITTENT;
+        }
+        return INTERMITTENT_STATE_IN_TRANSITION;
+    }
+
+    /**
+     * Returns whether a View should vote for frame rate category. When the category is HIGH
+     * already, there's no need to calculate the category on the View and vote.
+     */
+    public boolean shouldCheckFrameRateCategory() {
+        return mPreferredFrameRateCategory < FRAME_RATE_CATEGORY_HIGH;
+    }
+
+    /**
+     * Returns whether a View should vote for frame rate. When the maximum frame rate has already
+     * been voted for, there's no point in calculating and voting for the frame rate. When
+     * isDirect is false, then it will return false when the velocity-calculated frame rate
+     * can be avoided.
+     * @param isDirect true when the frame rate has been set directly on the View or false if
+     *                 the calculation is based only on velocity.
+     */
+    public boolean shouldCheckFrameRate(boolean isDirect) {
+        return mPreferredFrameRate < MAX_FRAME_RATE
+                || (!isDirect && !sToolkitFrameRateVelocityMappingReadOnlyFlagValue
+                && mPreferredFrameRateCategory < FRAME_RATE_CATEGORY_HIGH);
     }
 
     /**
@@ -12703,24 +12783,47 @@
         if (frameRate <= 0) {
             return;
         }
+        if (frameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE) {
+            mIsTouchBoosting = false;
+            if (!sToolkitFrameRateVelocityMappingReadOnlyFlagValue) {
+                mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
+                mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
+                mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_VELOCITY;
+                mFrameRateCategoryView = null;
+                mHasInvalidation = true;
+                mDrawnThisFrame = true;
+                return;
+            }
+        }
+        float nextFrameRate;
+        int nextFrameRateCompatibility;
+        if (frameRate > mPreferredFrameRate) {
+            nextFrameRate = frameRate;
+            nextFrameRateCompatibility = frameRateCompatibility;
+        } else {
+            nextFrameRate = mPreferredFrameRate;
+            nextFrameRateCompatibility = mFrameRateCompatibility;
+        }
+
         if (mPreferredFrameRate > 0 && mPreferredFrameRate % frameRate != 0
                 && frameRate % mPreferredFrameRate != 0) {
             mIsFrameRateConflicted = true;
-            mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
-        }
-        if (frameRate > mPreferredFrameRate) {
-            mFrameRateCompatibility = frameRateCompatibility;
+            if (nextFrameRate > 60 && mFrameRateCategoryHighCount != FRAME_RATE_CATEGORY_COUNT) {
+                mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
+                mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_CONFLICTED;
+                mFrameRateCategoryView = null;
+            } else if (mFrameRateCategoryHighCount == 0 && mFrameRateCategoryHighHintCount == 0
+                    && mFrameRateCategoryNormalCount < FRAME_RATE_CATEGORY_COUNT) {
+                mFrameRateCategoryNormalCount = FRAME_RATE_CATEGORY_COUNT;
+                mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_CONFLICTED;
+                mFrameRateCategoryView = null;
+            }
         }
 
-        mPreferredFrameRate = Math.max(mPreferredFrameRate, frameRate);
+        mPreferredFrameRate = nextFrameRate;
+        mFrameRateCompatibility = nextFrameRateCompatibility;
         mHasInvalidation = true;
-
-        if (!mIsFrameRateConflicted) {
-            mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
-            mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING,
-                    FRAME_RATE_SETTING_REEVALUATE_TIME);
-        }
-        checkIdleness();
+        mDrawnThisFrame = true;
     }
 
     /**
@@ -12790,7 +12893,6 @@
 
     private void boostFrameRate(int boostTimeOut) {
         mIsFrameRateBoosting = true;
-        setPreferredFrameRateCategory(mPreferredFrameRateCategory);
         mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
         mHandler.sendEmptyMessageDelayed(MSG_TOUCH_BOOST_TIMEOUT,
                 boostTimeOut);
@@ -12849,4 +12951,35 @@
             mHasIdledMessage = true;
         }
     }
+
+    private void removeVrrMessages() {
+        mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
+        mHandler.removeMessages(MSG_CHECK_INVALIDATION_IDLE);
+        mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
+    }
+
+    /**
+     * This function is mainly used for migrating infrequent layer logic
+     * from SurfaceFlinger to Toolkit.
+     * The infrequent layer logic includes:
+     * - NORMAL for infrequent update: FT2-FT1 > 100 && FT3-FT2 > 100.
+     * - HIGH/NORMAL based on size for frequent update: (FT3-FT2) + (FT2 - FT1) < 100.
+     * - otherwise, use the previous category value.
+     */
+    private void updateInfrequentCount() {
+        long currentTimeMillis = mAttachInfo.mDrawingTime;
+        int timeIntervalMillis =
+                (int) Math.min(Integer.MAX_VALUE, currentTimeMillis - mLastUpdateTimeMillis);
+        mMinusTwoFrameIntervalMillis = mMinusOneFrameIntervalMillis;
+        mMinusOneFrameIntervalMillis = timeIntervalMillis;
+
+        mLastUpdateTimeMillis = currentTimeMillis;
+        if (timeIntervalMillis >= INFREQUENT_UPDATE_INTERVAL_MILLIS) {
+            int infrequentUpdateCount = mInfrequentUpdateCount;
+            mInfrequentUpdateCount = infrequentUpdateCount == INFREQUENT_UPDATE_COUNTS
+                    ? infrequentUpdateCount : infrequentUpdateCount + 1;
+        } else {
+            mInfrequentUpdateCount = 0;
+        }
+    }
 }
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 6c852c3..86e5bea 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -76,6 +76,21 @@
             "android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION";
 
     /**
+     * Key used for writing the type of the view that generated the virtual structure of its
+     * children.
+     *
+     * For example, if the virtual structure is generated by a webview, the value would be
+     * "WebView". If the virtual structure is generated by a compose view, then the value would be
+     * "ComposeView". The value is of type String.
+     *
+     * This value is added to mainly help with debugging purpose.
+     *
+     * @hide
+     */
+    public static final String EXTRA_VIRTUAL_STRUCTURE_TYPE =
+            "android.view.ViewStructure.extra.VIRTUAL_STRUCTURE_TYPE";
+
+    /**
      * Set the identifier for this view.
      *
      * @param id The view's identifier, as per {@link View#getId View.getId()}.
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 1ffffb3..19c98a2 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -284,15 +284,6 @@
     @Appearance int getSystemBarsAppearance();
 
     /**
-     * Notify the caption insets height change. The information will be used on the client side to,
-     * make sure the InsetsState has the correct caption insets.
-     *
-     * @param height the height of caption bar insets.
-     * @hide
-     */
-    void setCaptionInsetsHeight(int height);
-
-    /**
      * Sets the insets height for the IME caption bar, which corresponds to the
      * "fake" IME navigation bar.
      *
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 59cb450..afe5b7e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1565,8 +1565,9 @@
      *     android:value="true|false"/&gt;
      * &lt;/activity&gt;
      * </pre>
+     *
+     * @hide
      */
-    @FlaggedApi(Flags.FLAG_UNTRUSTED_EMBEDDING_STATE_SHARING)
     String PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING =
             "android.window.PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING";
 
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 12ce0f4..bdfc236 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -27,6 +27,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresNoPermission;
 import android.annotation.SuppressLint;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -1190,6 +1191,8 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    @RequiresNoPermission
     public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info,
                 int interactionId) {
         synchronized (mInstanceLock) {
@@ -1231,6 +1234,8 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    @RequiresNoPermission
     public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
                 int interactionId) {
         synchronized (mInstanceLock) {
@@ -1260,6 +1265,7 @@
      * {@inheritDoc}
      */
     @Override
+    @RequiresNoPermission
     public void setPrefetchAccessibilityNodeInfoResult(@NonNull List<AccessibilityNodeInfo> infos,
                                                        int interactionId) {
         int interactionIdWaitingForPrefetchResultCopy = -1;
@@ -1324,6 +1330,8 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    @RequiresNoPermission
     public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId) {
         synchronized (mInstanceLock) {
             if (interactionId > mInteractionId) {
@@ -1372,6 +1380,7 @@
      * @param interactionId The interaction id of the request.
      */
     @Override
+    @RequiresNoPermission
     public void sendTakeScreenshotOfWindowError(
             @AccessibilityService.ScreenshotErrorCode int errorCode, int interactionId) {
         synchronized (mInstanceLock) {
@@ -1729,6 +1738,7 @@
      * @param interactionId The interaction id of the request.
      */
     @Override
+    @RequiresNoPermission
     public void sendAttachOverlayResult(
             @AccessibilityService.AttachOverlayResult int result, int interactionId) {
         if (!Flags.a11yOverlayCallbacks()) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 03ba8ae..a5ba294 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -159,7 +159,7 @@
      * <p> To avoid disconnected trees, this flag will also prefetch the parent. Siblings will be
      * prefetched before descendants.
      *
-     * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
+     * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used.
      */
     public static final int FLAG_PREFETCH_SIBLINGS = 1 << 1;
 
@@ -171,7 +171,7 @@
      * {@link #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST} or this will trigger an
      * IllegalArgumentException.
      *
-     * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
+     * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used.
      */
     public static final int FLAG_PREFETCH_DESCENDANTS_HYBRID = 1 << 2;
 
@@ -181,7 +181,7 @@
      * {@link #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST} or this will trigger an
      * IllegalArgumentException.
      *
-     * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
+     * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used.
      */
     public static final int FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST = 1 << 3;
 
@@ -191,7 +191,7 @@
      * {@link #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST} or this will trigger an
      * IllegalArgumentException.
      *
-     * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
+     * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used.
      */
     public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 1 << 4;
 
@@ -199,7 +199,7 @@
      * Prefetching flag that specifies prefetching should not be interrupted by a request to
      * retrieve a node or perform an action on a node.
      *
-     * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
+     * <p> See {@link #FLAG_PREFETCH_ANCESTORS} for information on where these flags can be used.
      */
     public static final int FLAG_PREFETCH_UNINTERRUPTIBLE = 1 << 5;
 
@@ -1295,6 +1295,8 @@
     /**
      * Get the child at given index.
      *
+     * <p>
+     * See {@link #getParent(int)} for a description of prefetching.
      * @param index The child index.
      * @param prefetchingStrategy the prefetching strategy.
      * @return The child node.
@@ -1302,7 +1304,6 @@
      * @throws IllegalStateException If called outside of an {@link AccessibilityService} and before
      *                               calling {@link #setQueryFromAppProcessEnabled}.
      *
-     * @see AccessibilityNodeInfo#getParent(int) for a description of prefetching.
      */
     @Nullable
     public AccessibilityNodeInfo getChild(int index, @PrefetchingStrategy int prefetchingStrategy) {
@@ -1903,8 +1904,13 @@
      * Accessibility service will throttle those content change events and only handle one event
      * per minute for that view.
      * </p>
+     * <p>
+     * Example UI elements that frequently update and may benefit from a duration are progress bars,
+     * timers, and stopwatches.
+     * </p>
      *
-     * @see AccessibilityEvent#getContentChangeTypes for all content change types.
+     * @see AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
+     * @see AccessibilityEvent#getContentChangeTypes
      * @param duration the minimum duration between content change events.
      *                                         Negative duration would be treated as zero.
      */
@@ -3954,7 +3960,7 @@
     /**
      * Returns the container title.
      *
-     * @see #setContainerTitle for details.
+     * @see #setContainerTitle
      */
     @Nullable
     public CharSequence getContainerTitle() {
@@ -5187,8 +5193,8 @@
          * <p>The node that is focused should return {@code true} for
          * {@link AccessibilityNodeInfo#isFocused()}.
          *
-         * @see #ACTION_ACCESSIBILITY_FOCUS for the difference between system and accessibility
-         * focus.
+         * See {@link #ACTION_ACCESSIBILITY_FOCUS} for the difference between system and
+         * accessibility focus.
          */
         public static final AccessibilityAction ACTION_FOCUS =
                 new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS);
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index fe59519..a9e5db5 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -34,6 +34,7 @@
      * @param interactionId The interaction id to match the result with the request.
      */
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+    @RequiresNoPermission
     void setFindAccessibilityNodeInfoResult(in AccessibilityNodeInfo info, int interactionId);
 
     /**
@@ -43,6 +44,7 @@
      * @param interactionId The interaction id to match the result with the request.
      */
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+    @RequiresNoPermission
     void setFindAccessibilityNodeInfosResult(in List<AccessibilityNodeInfo> infos,
         int interactionId);
 
@@ -52,6 +54,7 @@
      * @param root The {@link AccessibilityNodeInfo} for which the prefetching is based off of.
      * @param infos The result {@link AccessibilityNodeInfo}s.
      */
+     @RequiresNoPermission
     void setPrefetchAccessibilityNodeInfoResult(
         in List<AccessibilityNodeInfo> infos, int interactionId);
 
@@ -62,15 +65,18 @@
      * @param interactionId The interaction id to match the result with the request.
      */
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+    @RequiresNoPermission
     void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
 
     /**
     * Sends an error code for a window screenshot request to the requesting client.
     */
+    @RequiresNoPermission
     void sendTakeScreenshotOfWindowError(int errorCode, int interactionId);
 
     /**
     * Sends an result code for an attach overlay request to the requesting client.
     */
+    @RequiresNoPermission
     void sendAttachOverlayResult(int result, int interactionId);
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 614df7c..cd11314 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -42,112 +42,154 @@
  */
 interface IAccessibilityManager {
 
+    @RequiresNoPermission
     oneway void interrupt(int userId);
 
+    @RequiresNoPermission
     oneway void sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
 
+    @RequiresNoPermission
     long addClient(IAccessibilityManagerClient client, int userId);
 
+    @RequiresNoPermission
     boolean removeClient(IAccessibilityManagerClient client, int userId);
 
+    @RequiresNoPermission
     ParceledListSlice<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);
 
+    @RequiresNoPermission
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
 
+    @RequiresNoPermission
     int addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken,
             in IAccessibilityInteractionConnection connection,
             String packageName, int userId);
 
+    @RequiresNoPermission
     void removeAccessibilityInteractionConnection(IWindow windowToken);
 
+    @EnforcePermission("MODIFY_ACCESSIBILITY_DATA")
     void setPictureInPictureActionReplacingConnection(
             in IAccessibilityInteractionConnection connection);
 
+    @EnforcePermission("RETRIEVE_WINDOW_CONTENT")
     void registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient client,
         in AccessibilityServiceInfo info, int userId, int flags);
 
+    @RequiresNoPermission
     void unregisterUiTestAutomationService(IAccessibilityServiceClient client);
 
     // Used by UiAutomation
+    @EnforcePermission("RETRIEVE_WINDOW_CONTENT")
     IBinder getWindowToken(int windowId, int userId);
 
+    @EnforcePermission("STATUS_BAR_SERVICE")
     void notifyAccessibilityButtonClicked(int displayId, String targetName);
 
+
+    @EnforcePermission("STATUS_BAR_SERVICE")
     void notifyAccessibilityButtonVisibilityChanged(boolean available);
 
-    // Requires Manifest.permission.MANAGE_ACCESSIBILITY
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     void performAccessibilityShortcut(String targetName);
 
-    // Requires Manifest.permission.MANAGE_ACCESSIBILITY
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     List<String> getAccessibilityShortcutTargets(int shortcutType);
 
     // System process only
+    @RequiresNoPermission
     boolean sendFingerprintGesture(int gestureKeyCode);
 
     // System process only
+    @RequiresNoPermission
     int getAccessibilityWindowId(IBinder windowToken);
 
+    @RequiresNoPermission
     long getRecommendedTimeoutMillis();
 
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     oneway void registerSystemAction(in RemoteAction action, int actionId);
+
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     oneway void unregisterSystemAction(int actionId);
+
+    @EnforcePermission("STATUS_BAR_SERVICE")
     oneway void setMagnificationConnection(in IMagnificationConnection connection);
 
+    @RequiresNoPermission
     void associateEmbeddedHierarchy(IBinder host, IBinder embedded);
 
+    @RequiresNoPermission
     void disassociateEmbeddedHierarchy(IBinder token);
 
+    @RequiresNoPermission
     int getFocusStrokeWidth();
 
+    @RequiresNoPermission
     int getFocusColor();
 
+    @RequiresNoPermission
     boolean isAudioDescriptionByDefaultEnabled();
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)")
+    @EnforcePermission("SET_SYSTEM_AUDIO_CAPTION")
     void setSystemAudioCaptioningEnabled(boolean isEnabled, int userId);
 
+    @RequiresNoPermission
     boolean isSystemAudioCaptioningUiEnabled(int userId);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)")
+    @EnforcePermission("SET_SYSTEM_AUDIO_CAPTION")
     void setSystemAudioCaptioningUiEnabled(boolean isEnabled, int userId);
 
+    @RequiresNoPermission
     oneway void setAccessibilityWindowAttributes(int displayId, int windowId, int userId, in AccessibilityWindowAttributes attributes);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+    // Requires CREATE_VIRTUAL_DEVICE permission. Also requires either a11y permission or role.
+    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
     boolean registerProxyForDisplay(IAccessibilityServiceClient proxy, int displayId);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+    // Requires CREATE_VIRTUAL_DEVICE permission. Also requires either a11y permission or role.
+    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
     boolean unregisterProxyForDisplay(int displayId);
 
     // Used by UiAutomation for tests on the InputFilter
+    @EnforcePermission("INJECT_EVENTS")
     void injectInputEventToInputFilter(in InputEvent event);
 
+    @RequiresNoPermission
     boolean startFlashNotificationSequence(String opPkg, int reason, IBinder token);
+
+    @RequiresNoPermission
     boolean stopFlashNotificationSequence(String opPkg);
+
+    @RequiresNoPermission
     boolean startFlashNotificationEvent(String opPkg, int reason, String reasonPkg);
 
+    @RequiresNoPermission
     boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId);
+
+    @RequiresNoPermission
     boolean sendRestrictedDialogIntent(String packageName, int uid, int userId);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     boolean isAccessibilityServiceWarningRequired(in AccessibilityServiceInfo info);
 
     parcelable WindowTransformationSpec {
         float[] transformationMatrix;
         MagnificationSpec magnificationSpec;
     }
+    @RequiresNoPermission
     WindowTransformationSpec getWindowTransformationSpec(int windowId);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)")
+    @EnforcePermission("INTERNAL_SYSTEM_WINDOW")
     void attachAccessibilityOverlayToDisplay(int displayId, in SurfaceControl surfaceControl);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.STATUS_BAR_SERVICE,android.Manifest.permission.MANAGE_ACCESSIBILITY})")
+    @EnforcePermission(allOf={"STATUS_BAR_SERVICE","MANAGE_ACCESSIBILITY"})
     oneway void notifyQuickSettingsTilesChanged(int userId, in List<ComponentName> tileComponentNames);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     oneway void enableShortcutsForTargets(boolean enable, int shortcutTypes, in List<String> shortcutTargets, int userId);
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+    @EnforcePermission("MANAGE_ACCESSIBILITY")
     Bundle getA11yFeatureToTileMap(int userId);
 }
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
index f4aef22..da2bf9d 100644
--- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -81,6 +81,16 @@
 }
 
 flag {
+    name: "migrate_enable_shortcuts"
+    namespace: "accessibility"
+    description: "Refactors deprecated code to use AccessibilityManager#enableShortcutsForTargets."
+    bug: "332006721"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "motion_event_observing"
     is_exported: true
     namespace: "accessibility"
@@ -133,6 +143,16 @@
 }
 
 flag {
+    name: "prevent_leaking_viewrootimpl"
+    namespace: "accessibility"
+    description: "Clear pending messages and callbacks of the handler in AccessibilityInteractionController when the ViewRootImpl is detached from Window to prevent leaking ViewRootImpl"
+    bug: "320701910"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "support_system_pinch_zoom_opt_out_apis"
     namespace: "accessibility"
     description: "Feature flag for declaring system pinch zoom opt-out apis"
diff --git a/core/java/android/view/animation/BackGestureInterpolator.java b/core/java/android/view/animation/BackGestureInterpolator.java
new file mode 100644
index 0000000..c1595db
--- /dev/null
+++ b/core/java/android/view/animation/BackGestureInterpolator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.animation;
+/**
+ * Decelerating interpolator with a very slight acceleration phase at the beginning.
+ * @hide
+ */
+public class BackGestureInterpolator extends PathInterpolator {
+    public BackGestureInterpolator() {
+        super(0.1f, 0.1f, 0f, 1f);
+    }
+}
diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig
index e8e02ec..33b29c7 100644
--- a/core/java/android/view/flags/view_flags.aconfig
+++ b/core/java/android/view/flags/view_flags.aconfig
@@ -51,3 +51,11 @@
     description: "Enable default arrow icon when hovering on buttons or clickable widgets."
     bug: "299269803"
 }
+
+flag {
+    name: "enable_invalidate_check_thread"
+    namespace: "toolkit"
+    description: "Enable checkThread call in ViewRootImpl#onDescendentInvalidated"
+    bug: "333752000"
+    is_fixed_read_only: true
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 80b2396..8174da6 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1153,6 +1153,9 @@
                     }
                     final boolean startInput;
                     synchronized (mH) {
+                        if (reason == UnbindReason.DISCONNECT_IME) {
+                            mImeDispatcher.clear();
+                        }
                         if (getBindSequenceLocked() != sequence) {
                             return;
                         }
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index 4c3a290..d79903b 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -94,3 +94,15 @@
     bug: "322836622"
     is_fixed_read_only: true
 }
+
+flag {
+    name: "ctrl_shift_shortcut"
+    namespace: "input_method"
+    description: "Ctrl+Shift shortcut to switch IMEs"
+    bug: "327198899"
+    is_fixed_read_only: true
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 8f1b72e..1034479 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -40,6 +40,7 @@
 import android.util.AndroidRuntimeException;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 
 import java.io.File;
 import java.lang.reflect.Method;
@@ -609,7 +610,7 @@
             startedRelroProcesses = WebViewLibraryLoader.prepareNativeLibraries(packageInfo);
         } catch (Throwable t) {
             // Log and discard errors at this stage as we must not crash the system server.
-            Log.e(LOGTAG, "error preparing webview native library", t);
+            Slog.wtf(LOGTAG, "error preparing webview native library", t);
         }
 
         WebViewZygote.onWebViewProviderChanged(packageInfo);
diff --git a/core/java/android/webkit/WebViewLibraryLoader.java b/core/java/android/webkit/WebViewLibraryLoader.java
index a68a577..1a8745c 100644
--- a/core/java/android/webkit/WebViewLibraryLoader.java
+++ b/core/java/android/webkit/WebViewLibraryLoader.java
@@ -25,6 +25,7 @@
 import android.os.Build;
 import android.os.Process;
 import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
@@ -137,7 +138,7 @@
             if (!success) throw new Exception("Failed to start the relro file creator process");
         } catch (Throwable t) {
             // Log and discard errors as we must not crash the system server.
-            Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t);
+            Slog.wtf(LOGTAG, "error starting relro file creator for abi " + abi, t);
             crashHandler.run();
         }
     }
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 356d059..6e43d0f 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -69,6 +69,7 @@
 import com.android.internal.R;
 
 import java.text.NumberFormat;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Locale;
 
@@ -139,6 +140,14 @@
  * <p>The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary
  * if your application uses a light colored theme (a white background).</p>
  *
+ * <h4>Accessibility</h4>
+ * <p>
+ * Consider using
+ * {@link AccessibilityNodeInfo#setMinDurationBetweenContentChanges(Duration)} to
+ * convey to accessibility services that changes can be throttled. This may reduce the
+ * frequency of potentially disruptive notifications.
+ * </p>
+ *
  * <p><strong>XML attributes</b></strong>
  * <p>
  * See {@link android.R.styleable#ProgressBar ProgressBar Attributes},
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 42c2d80..b5bf529 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -568,7 +568,7 @@
                     handled = pageScroll(View.FOCUS_DOWN);
                     break;
                 case KeyEvent.KEYCODE_SPACE:
-                    pageScroll(event.isShiftPressed() ? View.FOCUS_UP : View.FOCUS_DOWN);
+                    handled = pageScroll(event.isShiftPressed() ? View.FOCUS_UP : View.FOCUS_DOWN);
                     break;
             }
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fbb5116..fb1c331 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11254,8 +11254,10 @@
                 width = des;
             } else {
                 if (mUseBoundsForWidth) {
-                    width = Math.max(boring.width,
-                            (int) Math.ceil(boring.getDrawingBoundingBox().width()));
+                    RectF bbox = boring.getDrawingBoundingBox();
+                    float rightMax = Math.max(bbox.right, boring.width);
+                    float leftMin = Math.min(bbox.left, 0);
+                    width = Math.max(boring.width, (int) Math.ceil(rightMax - leftMin));
                 } else {
                     width = boring.width;
                 }
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 65984f5..ead8887 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -45,8 +45,10 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.IAccessibilityManager;
+import android.widget.flags.Flags;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -205,27 +207,41 @@
         INotificationManager service = getService();
         String pkg = mContext.getOpPackageName();
         TN tn = mTN;
-        tn.mNextView = new WeakReference<>(mNextView);
+        if (Flags.toastNoWeakref()) {
+            tn.mNextView = mNextView;
+        } else {
+            tn.mNextViewWeakRef = new WeakReference<>(mNextView);
+        }
         final boolean isUiContext = mContext.isUiContext();
         final int displayId = mContext.getDisplayId();
 
+        boolean wasEnqueued = false;
         try {
             if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
                 if (mNextView != null) {
                     // It's a custom toast
-                    service.enqueueToast(pkg, mToken, tn, mDuration, isUiContext, displayId);
+                    wasEnqueued = service.enqueueToast(pkg, mToken, tn, mDuration, isUiContext,
+                            displayId);
                 } else {
                     // It's a text toast
                     ITransientNotificationCallback callback =
                             new CallbackBinder(mCallbacks, mHandler);
-                    service.enqueueTextToast(pkg, mToken, mText, mDuration, isUiContext, displayId,
-                            callback);
+                    wasEnqueued = service.enqueueTextToast(pkg, mToken, mText, mDuration,
+                            isUiContext, displayId, callback);
                 }
             } else {
-                service.enqueueToast(pkg, mToken, tn, mDuration, isUiContext, displayId);
+                wasEnqueued = service.enqueueToast(pkg, mToken, tn, mDuration, isUiContext,
+                        displayId);
             }
         } catch (RemoteException e) {
             // Empty
+        } finally {
+            if (Flags.toastNoWeakref()) {
+                if (!wasEnqueued) {
+                    tn.mNextViewWeakRef = null;
+                    tn.mNextView = null;
+                }
+            }
         }
     }
 
@@ -581,6 +597,16 @@
         }
     }
 
+    /**
+     * Get the Toast.TN ITransientNotification object
+     * @return TN
+     * @hide
+     */
+    @VisibleForTesting
+    public TN getTn() {
+        return mTN;
+    }
+
     // =======================================================================================
     // All the gunk below is the interaction with the Notification Service, which handles
     // the proper ordering of these system-wide.
@@ -599,7 +625,11 @@
         return sService;
     }
 
-    private static class TN extends ITransientNotification.Stub {
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public static class TN extends ITransientNotification.Stub {
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
         private final WindowManager.LayoutParams mParams;
 
@@ -620,7 +650,9 @@
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
         View mView;
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
-        WeakReference<View> mNextView;
+        WeakReference<View> mNextViewWeakRef;
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        View mNextView;
         int mDuration;
 
         WindowManager mWM;
@@ -662,14 +694,22 @@
                             handleHide();
                             // Don't do this in handleHide() because it is also invoked by
                             // handleShow()
-                            mNextView = null;
+                            if (Flags.toastNoWeakref()) {
+                                mNextView = null;
+                            } else {
+                                mNextViewWeakRef = null;
+                            }
                             break;
                         }
                         case CANCEL: {
                             handleHide();
                             // Don't do this in handleHide() because it is also invoked by
                             // handleShow()
-                            mNextView = null;
+                            if (Flags.toastNoWeakref()) {
+                                mNextView = null;
+                            } else {
+                                mNextViewWeakRef = null;
+                            }
                             try {
                                 getService().cancelToast(mPackageName, mToken);
                             } catch (RemoteException e) {
@@ -716,21 +756,43 @@
         }
 
         public void handleShow(IBinder windowToken) {
-            if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
-                    + " mNextView=" + mNextView);
+            if (Flags.toastNoWeakref()) {
+                if (localLOGV) {
+                    Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+                            + " mNextView=" + mNextView);
+                }
+            } else {
+                if (localLOGV) {
+                    Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+                            + " mNextView=" + mNextViewWeakRef);
+                }
+            }
             // If a cancel/hide is pending - no need to show - at this point
             // the window token is already invalid and no need to do any work.
             if (mHandler.hasMessages(CANCEL) || mHandler.hasMessages(HIDE)) {
                 return;
             }
-            if (mNextView != null && mView != mNextView.get()) {
-                // remove the old view if necessary
-                handleHide();
-                mView = mNextView.get();
-                if (mView != null) {
-                    mPresenter.show(mView, mToken, windowToken, mDuration, mGravity, mX, mY,
-                            mHorizontalMargin, mVerticalMargin,
-                            new CallbackBinder(getCallbacks(), mHandler));
+            if (Flags.toastNoWeakref()) {
+                if (mNextView != null && mView != mNextView) {
+                    // remove the old view if necessary
+                    handleHide();
+                    mView = mNextView;
+                    if (mView != null) {
+                        mPresenter.show(mView, mToken, windowToken, mDuration, mGravity, mX, mY,
+                                mHorizontalMargin, mVerticalMargin,
+                                new CallbackBinder(getCallbacks(), mHandler));
+                    }
+                }
+            } else {
+                if (mNextViewWeakRef != null && mView != mNextViewWeakRef.get()) {
+                    // remove the old view if necessary
+                    handleHide();
+                    mView = mNextViewWeakRef.get();
+                    if (mView != null) {
+                        mPresenter.show(mView, mToken, windowToken, mDuration, mGravity, mX, mY,
+                                mHorizontalMargin, mVerticalMargin,
+                                new CallbackBinder(getCallbacks(), mHandler));
+                    }
                 }
             }
         }
@@ -745,6 +807,23 @@
                 mView = null;
             }
         }
+
+        /**
+         * Get the next view to show for enqueued toasts
+         * Custom toast views are deprecated.
+         * @see #setView(View)
+         *
+         * @return next view
+         * @hide
+         */
+        @VisibleForTesting
+        public View getNextView() {
+            if (Flags.toastNoWeakref()) {
+                return mNextView;
+            } else {
+                return (mNextViewWeakRef != null) ? mNextViewWeakRef.get() : null;
+            }
+        }
     }
 
     /**
diff --git a/core/java/android/widget/flags/notification_widget_flags.aconfig b/core/java/android/widget/flags/notification_widget_flags.aconfig
index b530e71..95794f3 100644
--- a/core/java/android/widget/flags/notification_widget_flags.aconfig
+++ b/core/java/android/widget/flags/notification_widget_flags.aconfig
@@ -26,4 +26,14 @@
   metadata {
     purpose: PURPOSE_BUGFIX
   }
-}
\ No newline at end of file
+}
+
+flag {
+  name: "toast_no_weakref"
+  namespace: "systemui"
+  description: "Do not use WeakReference for custom view Toast"
+  bug: "321732224"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/core/java/android/window/BackNavigationInfo.java b/core/java/android/window/BackNavigationInfo.java
index 4816f35..b1cf834 100644
--- a/core/java/android/window/BackNavigationInfo.java
+++ b/core/java/android/window/BackNavigationInfo.java
@@ -72,8 +72,17 @@
     /**
      * Key to access the boolean value passed in {#mOnBackNavigationDone} result bundle
      * that represents if back navigation has been triggered.
+     * @hide
      */
-    public static final String KEY_TRIGGER_BACK = "TriggerBack";
+    public static final String KEY_NAVIGATION_FINISHED = "NavigationFinished";
+
+    /**
+     * Key to access the boolean value passed in {#mOnBackNavigationDone} result bundle
+     * that represents if back gesture has been triggered.
+     * @hide
+     */
+    public static final String KEY_GESTURE_FINISHED = "GestureFinished";
+
 
     /**
      * Defines the type of back destinations a back even can lead to. This is used to define the
@@ -192,7 +201,21 @@
     public void onBackNavigationFinished(boolean triggerBack) {
         if (mOnBackNavigationDone != null) {
             Bundle result = new Bundle();
-            result.putBoolean(KEY_TRIGGER_BACK, triggerBack);
+            result.putBoolean(KEY_NAVIGATION_FINISHED, triggerBack);
+            mOnBackNavigationDone.sendResult(result);
+        }
+    }
+
+    /**
+     * Callback to be called when the back gesture is finished in order to notify the server that
+     * it can ask app to start rendering.
+     * @hide
+     * @param triggerBack Boolean indicating if back gesture has been triggered.
+     */
+    public void onBackGestureFinished(boolean triggerBack) {
+        if (mOnBackNavigationDone != null) {
+            Bundle result = new Bundle();
+            result.putBoolean(KEY_GESTURE_FINISHED, triggerBack);
             mOnBackNavigationDone.sendResult(result);
         }
     }
diff --git a/core/java/android/window/IRemoteTransition.aidl b/core/java/android/window/IRemoteTransition.aidl
index ec8b66d..33421ba 100644
--- a/core/java/android/window/IRemoteTransition.aidl
+++ b/core/java/android/window/IRemoteTransition.aidl
@@ -19,6 +19,7 @@
 import android.view.SurfaceControl;
 import android.window.IRemoteTransitionFinishedCallback;
 import android.window.TransitionInfo;
+import android.window.WindowAnimationState;
 
 /**
  * Interface allowing remote processes to play transition animations.
@@ -61,6 +62,19 @@
             in IRemoteTransitionFinishedCallback finishCallback);
 
     /**
+     * Takes over the animation of the windows from an existing transition. Once complete, the
+     * implementation should call `finishCallback`.
+     *
+     * @param transition An identifier for the transition to be taken over.
+     * @param states The animation states of the windows involved in the transition. These must be
+     *               sorted in the same way as the Changes inside `info`, and each state may be
+     *               null.
+     */
+    void takeOverAnimation(in IBinder transition, in TransitionInfo info,
+            in SurfaceControl.Transaction t, in IRemoteTransitionFinishedCallback finishCallback,
+            in WindowAnimationState[] states);
+
+    /**
      * Called when a different handler has consumed the transition
      *
      * @param transition An identifier for the transition that was consumed.
diff --git a/core/java/android/window/RemoteTransitionStub.java b/core/java/android/window/RemoteTransitionStub.java
new file mode 100644
index 0000000..4a97b1e
--- /dev/null
+++ b/core/java/android/window/RemoteTransitionStub.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.SurfaceControl;
+
+/**
+ * Utility base implementation of {@link IRemoteTransition} that users can extend to avoid stubbing.
+ *
+ * @hide
+ */
+public abstract class RemoteTransitionStub extends IRemoteTransition.Stub {
+    @Override
+    public void mergeAnimation(IBinder transition, TransitionInfo info,
+            SurfaceControl.Transaction t, IBinder mergeTarget,
+            IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {}
+
+
+    @Override
+    public void takeOverAnimation(IBinder transition, TransitionInfo info,
+            SurfaceControl.Transaction startTransaction,
+            IRemoteTransitionFinishedCallback finishCallback,
+            WindowAnimationState[] states) throws RemoteException {
+        throw new RemoteException("Takeovers are not supported by this IRemoteTransition");
+    }
+
+
+    @Override
+    public void onTransitionConsumed(IBinder transition, boolean aborted)
+            throws RemoteException {}
+}
diff --git a/core/java/android/window/TaskFragmentCreationParams.java b/core/java/android/window/TaskFragmentCreationParams.java
index 93297e6..89327fe 100644
--- a/core/java/android/window/TaskFragmentCreationParams.java
+++ b/core/java/android/window/TaskFragmentCreationParams.java
@@ -18,10 +18,13 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.WindowingMode;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
+import android.content.pm.ActivityInfo.ScreenOrientation;
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -101,11 +104,20 @@
      */
     private final boolean mAllowTransitionWhenEmpty;
 
+    /**
+     * The override orientation for the TaskFragment. This is effective only for a system organizer.
+     * The value is ignored otherwise. Default to {@code SCREEN_ORIENTATION_UNSPECIFIED}.
+     *
+     * @see TaskFragmentOrganizer#registerOrganizer(boolean)
+     */
+    private final @ScreenOrientation int mOverrideOrientation;
+
     private TaskFragmentCreationParams(
             @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
             @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds,
             @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken,
-            @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty) {
+            @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty,
+            @ScreenOrientation int overrideOrientation) {
         if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) {
             throw new IllegalArgumentException("pairedPrimaryFragmentToken and"
                     + " pairedActivityToken should not be set at the same time.");
@@ -118,6 +130,7 @@
         mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
         mPairedActivityToken = pairedActivityToken;
         mAllowTransitionWhenEmpty = allowTransitionWhenEmpty;
+        mOverrideOrientation = overrideOrientation;
     }
 
     @NonNull
@@ -168,6 +181,11 @@
         return mAllowTransitionWhenEmpty;
     }
 
+    /** @hide */
+    public @ScreenOrientation int getOverrideOrientation() {
+        return mOverrideOrientation;
+    }
+
     private TaskFragmentCreationParams(Parcel in) {
         mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
         mFragmentToken = in.readStrongBinder();
@@ -177,6 +195,7 @@
         mPairedPrimaryFragmentToken = in.readStrongBinder();
         mPairedActivityToken = in.readStrongBinder();
         mAllowTransitionWhenEmpty = in.readBoolean();
+        mOverrideOrientation = in.readInt();
     }
 
     /** @hide */
@@ -190,6 +209,7 @@
         dest.writeStrongBinder(mPairedPrimaryFragmentToken);
         dest.writeStrongBinder(mPairedActivityToken);
         dest.writeBoolean(mAllowTransitionWhenEmpty);
+        dest.writeInt(mOverrideOrientation);
     }
 
     @NonNull
@@ -217,6 +237,7 @@
                 + " pairedFragmentToken=" + mPairedPrimaryFragmentToken
                 + " pairedActivityToken=" + mPairedActivityToken
                 + " allowTransitionWhenEmpty=" + mAllowTransitionWhenEmpty
+                + " overrideOrientation=" + mOverrideOrientation
                 + "}";
     }
 
@@ -252,6 +273,8 @@
 
         private boolean mAllowTransitionWhenEmpty;
 
+        private @ScreenOrientation int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+
         public Builder(@NonNull TaskFragmentOrganizerToken organizer,
                 @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
             mOrganizer = organizer;
@@ -330,12 +353,28 @@
             return this;
         }
 
+        /**
+         * Sets the override orientation for the TaskFragment. This is effective only for a system
+         * organizer. The value is ignored otherwise. Default to
+         * {@code SCREEN_ORIENTATION_UNSPECIFIED}.
+         *
+         * @see TaskFragmentOrganizer#registerOrganizer(boolean)
+         *
+         * @hide
+         */
+        @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
+        @NonNull
+        public Builder setOverrideOrientation(@ScreenOrientation int overrideOrientation) {
+            mOverrideOrientation = overrideOrientation;
+            return this;
+        }
+
         /** Constructs the options to create TaskFragment with. */
         @NonNull
         public TaskFragmentCreationParams build() {
             return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
                     mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken,
-                    mPairedActivityToken, mAllowTransitionWhenEmpty);
+                    mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation);
         }
     }
 }
diff --git a/core/java/android/window/TaskFragmentOperation.java b/core/java/android/window/TaskFragmentOperation.java
index 43df4f9..d0f3c3e 100644
--- a/core/java/android/window/TaskFragmentOperation.java
+++ b/core/java/android/window/TaskFragmentOperation.java
@@ -195,12 +195,6 @@
     @Nullable
     private final TaskFragmentAnimationParams mAnimationParams;
 
-    private final boolean mIsolatedNav;
-
-    private final boolean mDimOnTask;
-
-    private final boolean mMoveToBottomIfClearWhenLaunch;
-
     private final boolean mBooleanValue;
 
     @Nullable
@@ -211,7 +205,6 @@
             @Nullable IBinder activityToken, @Nullable Intent activityIntent,
             @Nullable Bundle bundle, @Nullable IBinder secondaryFragmentToken,
             @Nullable TaskFragmentAnimationParams animationParams,
-            boolean isolatedNav, boolean dimOnTask, boolean moveToBottomIfClearWhenLaunch,
             boolean booleanValue, @Nullable SurfaceControl.Transaction surfaceTransaction) {
         mOpType = opType;
         mTaskFragmentCreationParams = taskFragmentCreationParams;
@@ -220,9 +213,6 @@
         mBundle = bundle;
         mSecondaryFragmentToken = secondaryFragmentToken;
         mAnimationParams = animationParams;
-        mIsolatedNav = isolatedNav;
-        mDimOnTask = dimOnTask;
-        mMoveToBottomIfClearWhenLaunch = moveToBottomIfClearWhenLaunch;
         mBooleanValue = booleanValue;
         mSurfaceTransaction = surfaceTransaction;
     }
@@ -235,9 +225,6 @@
         mBundle = in.readBundle(getClass().getClassLoader());
         mSecondaryFragmentToken = in.readStrongBinder();
         mAnimationParams = in.readTypedObject(TaskFragmentAnimationParams.CREATOR);
-        mIsolatedNav = in.readBoolean();
-        mDimOnTask = in.readBoolean();
-        mMoveToBottomIfClearWhenLaunch = in.readBoolean();
         mBooleanValue = in.readBoolean();
         mSurfaceTransaction = in.readTypedObject(SurfaceControl.Transaction.CREATOR);
     }
@@ -251,9 +238,6 @@
         dest.writeBundle(mBundle);
         dest.writeStrongBinder(mSecondaryFragmentToken);
         dest.writeTypedObject(mAnimationParams, flags);
-        dest.writeBoolean(mIsolatedNav);
-        dest.writeBoolean(mDimOnTask);
-        dest.writeBoolean(mMoveToBottomIfClearWhenLaunch);
         dest.writeBoolean(mBooleanValue);
         dest.writeTypedObject(mSurfaceTransaction, flags);
     }
@@ -328,29 +312,6 @@
         return mAnimationParams;
     }
 
-    /**
-     * Returns whether the activity navigation on this TaskFragment is isolated. This is only
-     * useful when the op type is {@link OP_TYPE_SET_ISOLATED_NAVIGATION}.
-     */
-    public boolean isIsolatedNav() {
-        return mIsolatedNav;
-    }
-
-    /**
-     * Returns whether the dim layer should apply on the parent Task.
-     */
-    public boolean isDimOnTask() {
-        return mDimOnTask;
-    }
-
-    /**
-     * Returns whether the TaskFragment should move to bottom of task when any activity below it
-     * is launched in clear top mode.
-     */
-    public boolean isMoveToBottomIfClearWhenLaunch() {
-        return mMoveToBottomIfClearWhenLaunch;
-    }
-
     /** Returns the boolean value for this operation. */
     public boolean getBooleanValue() {
         return mBooleanValue;
@@ -389,9 +350,6 @@
         if (mAnimationParams != null) {
             sb.append(", animationParams=").append(mAnimationParams);
         }
-        sb.append(", isolatedNav=").append(mIsolatedNav);
-        sb.append(", dimOnTask=").append(mDimOnTask);
-        sb.append(", moveToBottomIfClearWhenLaunch=").append(mMoveToBottomIfClearWhenLaunch);
         sb.append(", booleanValue=").append(mBooleanValue);
         if (mSurfaceTransaction != null) {
             sb.append(", surfaceTransaction=").append(mSurfaceTransaction);
@@ -404,8 +362,8 @@
     @Override
     public int hashCode() {
         return Objects.hash(mOpType, mTaskFragmentCreationParams, mActivityToken, mActivityIntent,
-                mBundle, mSecondaryFragmentToken, mAnimationParams, mIsolatedNav, mDimOnTask,
-                mMoveToBottomIfClearWhenLaunch, mBooleanValue, mSurfaceTransaction);
+                mBundle, mSecondaryFragmentToken, mAnimationParams, mBooleanValue,
+                mSurfaceTransaction);
     }
 
     @Override
@@ -421,9 +379,6 @@
                 && Objects.equals(mBundle, other.mBundle)
                 && Objects.equals(mSecondaryFragmentToken, other.mSecondaryFragmentToken)
                 && Objects.equals(mAnimationParams, other.mAnimationParams)
-                && mIsolatedNav == other.mIsolatedNav
-                && mDimOnTask == other.mDimOnTask
-                && mMoveToBottomIfClearWhenLaunch == other.mMoveToBottomIfClearWhenLaunch
                 && mBooleanValue == other.mBooleanValue
                 && Objects.equals(mSurfaceTransaction, other.mSurfaceTransaction);
     }
@@ -457,12 +412,6 @@
         @Nullable
         private TaskFragmentAnimationParams mAnimationParams;
 
-        private boolean mIsolatedNav;
-
-        private boolean mDimOnTask;
-
-        private boolean mMoveToBottomIfClearWhenLaunch;
-
         private boolean mBooleanValue;
 
         @Nullable
@@ -531,36 +480,7 @@
         }
 
         /**
-         * Sets the activity navigation of this TaskFragment to be isolated.
-         */
-        @NonNull
-        public Builder setIsolatedNav(boolean isolatedNav) {
-            mIsolatedNav = isolatedNav;
-            return this;
-        }
-
-        /**
-         * Sets the dimming to apply on the parent Task if any.
-         */
-        @NonNull
-        public Builder setDimOnTask(boolean dimOnTask) {
-            mDimOnTask = dimOnTask;
-            return this;
-        }
-
-        /**
-         * Sets whether the TaskFragment should move to bottom of task when any activity below it
-         * is launched in clear top mode.
-         */
-        @NonNull
-        public Builder setMoveToBottomIfClearWhenLaunch(boolean moveToBottomIfClearWhenLaunch) {
-            mMoveToBottomIfClearWhenLaunch = moveToBottomIfClearWhenLaunch;
-            return this;
-        }
-
-        /**
          * Sets the boolean value for this operation.
-         * TODO(b/327338038) migrate other boolean values to use shared mBooleanValue
          */
         @NonNull
         public Builder setBooleanValue(boolean booleanValue) {
@@ -588,8 +508,7 @@
         public TaskFragmentOperation build() {
             return new TaskFragmentOperation(mOpType, mTaskFragmentCreationParams, mActivityToken,
                     mActivityIntent, mBundle, mSecondaryFragmentToken, mAnimationParams,
-                    mIsolatedNav, mDimOnTask, mMoveToBottomIfClearWhenLaunch, mBooleanValue,
-                    mSurfaceTransaction);
+                    mBooleanValue, mSurfaceTransaction);
         }
     }
 }
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 6d36b57..b9ffdbc 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -24,7 +24,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.app.ActivityManager;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.SurfaceControl;
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 5227724..bcae571 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -523,6 +523,9 @@
         if ((flags & FLAG_FIRST_CUSTOM) != 0) {
             sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM");
         }
+        if ((flags & FLAG_CONFIG_AT_END) != 0) {
+            sb.append(sb.length() == 0 ? "" : "|").append("CONFIG_AT_END");
+        }
         if ((flags & FLAG_MOVED_TO_TOP) != 0) {
             sb.append(sb.length() == 0 ? "" : "|").append("MOVE_TO_TOP");
         }
@@ -538,6 +541,11 @@
         // If the change has no parent (it is root), then it is independent
         if (change.getParent() == null) return true;
 
+        if (change.getLastParent() != null && !change.getLastParent().equals(change.getParent())) {
+            // If the change has been reparented, then it's independent.
+            return true;
+        }
+
         // non-visibility changes will just be folded into the parent change, so they aren't
         // independent either.
         if (change.getMode() == TRANSIT_CHANGE) return false;
diff --git a/core/java/android/window/WindowAnimationState.aidl b/core/java/android/window/WindowAnimationState.aidl
new file mode 100644
index 0000000..e662860
--- /dev/null
+++ b/core/java/android/window/WindowAnimationState.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.graphics.PointF;
+import android.graphics.RectF;
+
+/**
+ * Properties of a window animation at a given point in time.
+ *
+ * {@hide}
+ */
+parcelable WindowAnimationState {
+    long timestamp;
+    RectF bounds;
+    float scale;
+    float topLeftRadius;
+    float topRightRadius;
+    float bottomRightRadius;
+    float bottomLeftRadius;
+    PointF velocityPxPerMs;
+}
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 76a34ae..5e88d97c 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -88,6 +88,19 @@
     }
 
     /**
+     * Clear the transaction object.
+     * This is equivalent to a new empty {@link WindowContainerTransaction} in content.
+     *
+     * @hide
+     */
+    public void clear() {
+        mChanges.clear();
+        mHierarchyOps.clear();
+        mErrorCallbackToken = null;
+        mTaskFragmentOrganizer = null;
+    }
+
+    /**
      * Resize a container.
      */
     @NonNull
@@ -1285,6 +1298,12 @@
             if ((mChangeMask & CHANGE_FOCUSABLE) != 0) {
                 sb.append("focusable:" + mFocusable + ",");
             }
+            if ((mChangeMask & CHANGE_FORCE_TRANSLUCENT) != 0) {
+                sb.append("forceTranslucent:" + mForceTranslucent + ",");
+            }
+            if ((mChangeMask & CHANGE_HIDDEN) != 0) {
+                sb.append("hidden:" + mHidden + ",");
+            }
             if ((mChangeMask & CHANGE_DRAG_RESIZING) != 0) {
                 sb.append("dragResizing:" + mDragResizing + ",");
             }
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index bcbac93..47a4052 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -36,6 +36,8 @@
 import androidx.annotation.VisibleForTesting;
 
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -75,14 +77,17 @@
     @Nullable
     private ImeBackAnimationController mImeBackAnimationController;
 
+    @GuardedBy("mLock")
     /** Convenience hashmap to quickly decide if a callback has been added. */
     private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
     /** Holds all callbacks by priorities. */
 
     @VisibleForTesting
+    @GuardedBy("mLock")
     public final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
             mOnBackInvokedCallbacks = new TreeMap<>();
     private Checker mChecker;
+    private final Object mLock = new Object();
 
     public WindowOnBackInvokedDispatcher(@NonNull Context context) {
         mChecker = new Checker(context);
@@ -94,20 +99,24 @@
      */
     public void attachToWindow(@NonNull IWindowSession windowSession, @NonNull IWindow window,
             @Nullable ImeBackAnimationController imeBackAnimationController) {
-        mWindowSession = windowSession;
-        mWindow = window;
-        mImeBackAnimationController = imeBackAnimationController;
-        if (!mAllCallbacks.isEmpty()) {
-            setTopOnBackInvokedCallback(getTopCallback());
+        synchronized (mLock) {
+            mWindowSession = windowSession;
+            mWindow = window;
+            mImeBackAnimationController = imeBackAnimationController;
+            if (!mAllCallbacks.isEmpty()) {
+                setTopOnBackInvokedCallback(getTopCallback());
+            }
         }
     }
 
     /** Detaches the dispatcher instance from its window. */
     public void detachFromWindow() {
-        clear();
-        mWindow = null;
-        mWindowSession = null;
-        mImeBackAnimationController = null;
+        synchronized (mLock) {
+            clear();
+            mWindow = null;
+            mWindowSession = null;
+            mImeBackAnimationController = null;
+        }
     }
 
     // TODO: Take an Executor for the callback to run on.
@@ -125,65 +134,71 @@
      */
     public void registerOnBackInvokedCallbackUnchecked(
             @NonNull OnBackInvokedCallback callback, @Priority int priority) {
-        if (mImeDispatcher != null) {
-            mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
-            return;
-        }
-        if (!mOnBackInvokedCallbacks.containsKey(priority)) {
-            mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
-        }
-        if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) {
-            callback = mImeBackAnimationController;
-        }
-        ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority);
-
-        // If callback has already been added, remove it and re-add it.
-        if (mAllCallbacks.containsKey(callback)) {
-            if (DEBUG) {
-                Log.i(TAG, "Callback already added. Removing and re-adding it.");
+        synchronized (mLock) {
+            if (mImeDispatcher != null) {
+                mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
+                return;
             }
-            Integer prevPriority = mAllCallbacks.get(callback);
-            mOnBackInvokedCallbacks.get(prevPriority).remove(callback);
-        }
+            if (!mOnBackInvokedCallbacks.containsKey(priority)) {
+                mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
+            }
+            if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) {
+                callback = mImeBackAnimationController;
+            }
+            ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority);
 
-        OnBackInvokedCallback previousTopCallback = getTopCallback();
-        callbacks.add(callback);
-        mAllCallbacks.put(callback, priority);
-        if (previousTopCallback == null
-                || (previousTopCallback != callback
-                        && mAllCallbacks.get(previousTopCallback) <= priority)) {
-            setTopOnBackInvokedCallback(callback);
+            // If callback has already been added, remove it and re-add it.
+            if (mAllCallbacks.containsKey(callback)) {
+                if (DEBUG) {
+                    Log.i(TAG, "Callback already added. Removing and re-adding it.");
+                }
+                Integer prevPriority = mAllCallbacks.get(callback);
+                mOnBackInvokedCallbacks.get(prevPriority).remove(callback);
+            }
+
+            OnBackInvokedCallback previousTopCallback = getTopCallback();
+            callbacks.add(callback);
+            mAllCallbacks.put(callback, priority);
+            if (previousTopCallback == null
+                    || (previousTopCallback != callback
+                    && mAllCallbacks.get(previousTopCallback) <= priority)) {
+                setTopOnBackInvokedCallback(callback);
+            }
         }
     }
 
     @Override
     public void unregisterOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
-        if (mImeDispatcher != null) {
-            mImeDispatcher.unregisterOnBackInvokedCallback(callback);
-            return;
-        }
-        if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) {
-            callback = mImeBackAnimationController;
-        }
-        if (!mAllCallbacks.containsKey(callback)) {
-            if (DEBUG) {
-                Log.i(TAG, "Callback not found. returning...");
+        synchronized (mLock) {
+            if (mImeDispatcher != null) {
+                mImeDispatcher.unregisterOnBackInvokedCallback(callback);
+                return;
             }
-            return;
-        }
-        OnBackInvokedCallback previousTopCallback = getTopCallback();
-        Integer priority = mAllCallbacks.get(callback);
-        ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority);
-        callbacks.remove(callback);
-        if (callbacks.isEmpty()) {
-            mOnBackInvokedCallbacks.remove(priority);
-        }
-        mAllCallbacks.remove(callback);
-        // Re-populate the top callback to WM if the removed callback was previously the top one.
-        if (previousTopCallback == callback) {
-            // We should call onBackCancelled() when an active callback is removed from dispatcher.
-            sendCancelledIfInProgress(callback);
-            setTopOnBackInvokedCallback(getTopCallback());
+            if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) {
+                callback = mImeBackAnimationController;
+            }
+            if (!mAllCallbacks.containsKey(callback)) {
+                if (DEBUG) {
+                    Log.i(TAG, "Callback not found. returning...");
+                }
+                return;
+            }
+            OnBackInvokedCallback previousTopCallback = getTopCallback();
+            Integer priority = mAllCallbacks.get(callback);
+            ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority);
+            callbacks.remove(callback);
+            if (callbacks.isEmpty()) {
+                mOnBackInvokedCallbacks.remove(priority);
+            }
+            mAllCallbacks.remove(callback);
+            // Re-populate the top callback to WM if the removed callback was previously the top
+            // one.
+            if (previousTopCallback == callback) {
+                // We should call onBackCancelled() when an active callback is removed from
+                // dispatcher.
+                sendCancelledIfInProgress(callback);
+                setTopOnBackInvokedCallback(getTopCallback());
+            }
         }
     }
 
@@ -191,15 +206,21 @@
      * Indicates if the dispatcher is actively dispatching to a callback.
      */
     public boolean isDispatching() {
-        return mIsDispatching;
+        synchronized (mLock) {
+            return mIsDispatching;
+        }
     }
 
     private void onStartDispatching() {
-        mIsDispatching = true;
+        synchronized (mLock) {
+            mIsDispatching = true;
+        }
     }
 
     private void onStopDispatching() {
-        mIsDispatching = false;
+        synchronized (mLock) {
+            mIsDispatching = false;
+        }
     }
 
     private void sendCancelledIfInProgress(@NonNull OnBackInvokedCallback callback) {
@@ -223,27 +244,29 @@
 
     /** Clears all registered callbacks on the instance. */
     public void clear() {
-        if (mImeDispatcher != null) {
-            mImeDispatcher.clear();
-            mImeDispatcher = null;
-        }
-        if (!mAllCallbacks.isEmpty()) {
-            OnBackInvokedCallback topCallback = getTopCallback();
-            if (topCallback != null) {
-                sendCancelledIfInProgress(topCallback);
-            } else {
-                // Should not be possible
-                Log.e(TAG, "There is no topCallback, even if mAllCallbacks is not empty");
+        synchronized (mLock) {
+            if (mImeDispatcher != null) {
+                mImeDispatcher.clear();
+                mImeDispatcher = null;
             }
-            // Clear binder references in WM.
-            setTopOnBackInvokedCallback(null);
-        }
+            if (!mAllCallbacks.isEmpty()) {
+                OnBackInvokedCallback topCallback = getTopCallback();
+                if (topCallback != null) {
+                    sendCancelledIfInProgress(topCallback);
+                } else {
+                    // Should not be possible
+                    Log.e(TAG, "There is no topCallback, even if mAllCallbacks is not empty");
+                }
+                // Clear binder references in WM.
+                setTopOnBackInvokedCallback(null);
+            }
 
-        // We should also stop running animations since all callbacks have been removed.
-        // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler.
-        Handler.getMain().post(mProgressAnimator::reset);
-        mAllCallbacks.clear();
-        mOnBackInvokedCallbacks.clear();
+            // We should also stop running animations since all callbacks have been removed.
+            // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler.
+            Handler.getMain().post(mProgressAnimator::reset);
+            mAllCallbacks.clear();
+            mOnBackInvokedCallbacks.clear();
+        }
     }
 
     private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {
@@ -275,13 +298,15 @@
     }
 
     public OnBackInvokedCallback getTopCallback() {
-        if (mAllCallbacks.isEmpty()) {
-            return null;
-        }
-        for (Integer priority : mOnBackInvokedCallbacks.descendingKeySet()) {
-            ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority);
-            if (!callbacks.isEmpty()) {
-                return callbacks.get(callbacks.size() - 1);
+        synchronized (mLock) {
+            if (mAllCallbacks.isEmpty()) {
+                return null;
+            }
+            for (Integer priority : mOnBackInvokedCallbacks.descendingKeySet()) {
+                ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority);
+                if (!callbacks.isEmpty()) {
+                    return callbacks.get(callbacks.size() - 1);
+                }
             }
         }
         return null;
@@ -315,16 +340,18 @@
     public void dump(String prefix, PrintWriter writer) {
         String innerPrefix = prefix + "    ";
         writer.println(prefix + "WindowOnBackDispatcher:");
-        if (mAllCallbacks.isEmpty()) {
-            writer.println(prefix + "<None>");
-            return;
-        }
+        synchronized (mLock) {
+            if (mAllCallbacks.isEmpty()) {
+                writer.println(prefix + "<None>");
+                return;
+            }
 
-        writer.println(innerPrefix + "Top Callback: " + getTopCallback());
-        writer.println(innerPrefix + "Callbacks: ");
-        mAllCallbacks.forEach((callback, priority) -> {
-            writer.println(innerPrefix + "  Callback: " + callback + " Priority=" + priority);
-        });
+            writer.println(innerPrefix + "Top Callback: " + getTopCallback());
+            writer.println(innerPrefix + "Callbacks: ");
+            mAllCallbacks.forEach((callback, priority) -> {
+                writer.println(innerPrefix + "  Callback: " + callback + " Priority=" + priority);
+            });
+        }
     }
 
     static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java
index 4a3aba1..cc54a93 100644
--- a/core/java/android/window/WindowTokenClient.java
+++ b/core/java/android/window/WindowTokenClient.java
@@ -19,12 +19,15 @@
 import static android.window.ConfigurationHelper.isDifferentDisplay;
 import static android.window.ConfigurationHelper.shouldUpdateResources;
 
+import static com.android.window.flags.Flags.windowTokenConfigThreadSafe;
+
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
 import android.app.ResourcesManager;
+import android.app.servertransaction.ClientTransactionListenerController;
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -137,12 +140,32 @@
      *                                 should be dispatched to listeners.
      */
     @AnyThread
-    public void onConfigurationChanged(Configuration newConfig, int newDisplayId,
+    public void onConfigurationChanged(@NonNull Configuration newConfig, int newDisplayId,
             boolean shouldReportConfigChange) {
         final Context context = mContextRef.get();
         if (context == null) {
             return;
         }
+        if (shouldReportConfigChange && windowTokenConfigThreadSafe()) {
+            // Only report to ClientTransactionListenerController when shouldReportConfigChange.
+            final ClientTransactionListenerController controller =
+                    getClientTransactionListenerController();
+            controller.onContextConfigurationPreChanged(context);
+            try {
+                onConfigurationChangedInner(context, newConfig, newDisplayId,
+                        shouldReportConfigChange);
+            } finally {
+                controller.onContextConfigurationPostChanged(context);
+            }
+        } else {
+            onConfigurationChangedInner(context, newConfig, newDisplayId, shouldReportConfigChange);
+        }
+    }
+
+    /** Handles onConfiguration changed. */
+    @VisibleForTesting
+    public void onConfigurationChangedInner(@NonNull Context context,
+            @NonNull Configuration newConfig, int newDisplayId, boolean shouldReportConfigChange) {
         CompatibilityInfo.applyOverrideScaleIfNeeded(newConfig);
         final boolean displayChanged;
         final boolean shouldUpdateResources;
@@ -220,4 +243,11 @@
             mContextRef.clear();
         }
     }
+
+    /** Gets {@link ClientTransactionListenerController}. */
+    @VisibleForTesting
+    @NonNull
+    public ClientTransactionListenerController getClientTransactionListenerController() {
+        return ClientTransactionListenerController.getInstance();
+    }
 }
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index efe31ff..55927cc 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -36,3 +36,31 @@
     description: "Enables a limit on the number of Tasks shown in Desktop Mode"
     bug: "332502912"
 }
+
+flag {
+    name: "enable_windowing_edge_drag_resize"
+    namespace: "lse_desktop_experience"
+    description: "Enables edge drag resizing for all input sources"
+    bug: "323383067"
+}
+
+flag {
+    name: "enable_desktop_windowing_taskbar_running_apps"
+    namespace: "lse_desktop_experience"
+    description: "Shows running apps in Desktop Mode Taskbar"
+    bug: "332504528"
+}
+
+flag {
+    name: "enable_desktop_windowing_wallpaper_activity"
+    namespace: "lse_desktop_experience"
+    description: "Enables desktop wallpaper activity to show wallpaper in the desktop mode"
+    bug: "309014605"
+}
+
+flag {
+    name: "enable_desktop_windowing_immersive_handle_hiding"
+    namespace: "lse_desktop_experience"
+    description: "Hides the App Handle when in fullscreen immersive mode"
+    bug: "336368019"
+}
diff --git a/core/java/android/window/flags/wallpaper_manager.aconfig b/core/java/android/window/flags/wallpaper_manager.aconfig
index aa92af2..150b04e 100644
--- a/core/java/android/window/flags/wallpaper_manager.aconfig
+++ b/core/java/android/window/flags/wallpaper_manager.aconfig
@@ -21,4 +21,14 @@
   namespace: "systemui"
   description: "Prevent the system from sending consecutive onVisibilityChanged(false) events."
   bug: "285631818"
+}
+
+flag {
+  name: "offload_color_extraction"
+  namespace: "systemui"
+  description: "Let ImageWallpaper take care of its wallpaper color extraction, instead of system_server"
+  bug: "328791519"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
 }
\ No newline at end of file
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index dd6b772a..87c47da 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -128,9 +128,28 @@
 }
 
 flag {
+  name: "fifo_priority_for_major_ui_processes"
+  namespace: "windowing_frontend"
+  description: "Use realtime priority for SystemUI and launcher"
+  bug: "288140556"
+  is_fixed_read_only: true
+}
+
+flag {
   name: "insets_decoupled_configuration"
   namespace: "windowing_frontend"
   description: "Configuration decoupled from insets"
   bug: "151861875"
   is_fixed_read_only: true
+}
+
+flag {
+  name: "keyguard_appear_transition"
+  namespace: "windowing_frontend"
+  description: "Add transition when keyguard appears"
+  bug: "327970608"
+  is_fixed_read_only: true
+  metadata {
+      purpose: PURPOSE_BUGFIX
+  }
 }
\ No newline at end of file
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 80265ec..001ed79 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -89,4 +89,24 @@
     description: "Whether to enable WM Extensions for all devices"
     bug: "306666082"
     is_fixed_read_only: true
+}
+
+flag {
+    namespace: "windowing_sdk"
+    name: "window_token_config_thread_safe"
+    description: "Ensure the Configuration pre/post changed is thread safe"
+    bug: "334285008"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    namespace: "windowing_sdk"
+    name: "always_defer_transition_when_apply_wct"
+    description: "Report error when defer transition fails when it should not"
+    bug: "335562144"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index a0c405e..06ae11fee 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -24,8 +24,10 @@
 import static com.android.internal.os.RoSystemProperties.SUPPORT_ONE_HANDED_MODE;
 import static com.android.internal.util.ArrayUtils.convertToLongArray;
 
+import android.Manifest;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.AlertDialog;
@@ -53,6 +55,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.Flags;
 import android.widget.Toast;
 
 import com.android.internal.R;
@@ -132,7 +135,7 @@
             DialogStatus.SHOWN,
     })
     /** Denotes the user shortcut type. */
-    @interface DialogStatus {
+    public @interface DialogStatus {
         int NOT_SHOWN = 0;
         int SHOWN  = 1;
     }
@@ -328,11 +331,14 @@
         warningToast.show();
     }
 
+    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
     private AlertDialog createShortcutWarningDialog(int userId) {
         List<AccessibilityTarget> targets = getTargets(mContext, HARDWARE);
         if (targets.size() == 0) {
             return null;
         }
+        final AccessibilityManager am = mFrameworkObjectProvider
+                .getAccessibilityManagerInstance(mContext);
 
         // Avoid non-a11y users accidentally turning shortcut on without reading this carefully.
         // Put "don't turn on" as the primary action.
@@ -360,10 +366,15 @@
                                 // to the Settings.
                                 final ComponentName configDefaultService =
                                         ComponentName.unflattenFromString(defaultService);
-                                Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
-                                        configDefaultService.flattenToString(),
-                                        userId);
+                                if (Flags.migrateEnableShortcuts()) {
+                                    am.enableShortcutsForTargets(true, HARDWARE,
+                                            Set.of(configDefaultService.flattenToString()), userId);
+                                } else {
+                                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                                            Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                                            configDefaultService.flattenToString(),
+                                            userId);
+                                }
                             }
                         })
                 .setPositiveButton(R.string.accessibility_shortcut_off,
@@ -373,13 +384,16 @@
                                             mContext,
                                             HARDWARE,
                                             userId);
-
-                            Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                                    Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "",
-                                    userId);
-                            ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
-                                    mContext, targetServices, userId);
-
+                            if (Flags.migrateEnableShortcuts()) {
+                                am.enableShortcutsForTargets(
+                                        false, HARDWARE, targetServices, userId);
+                            } else {
+                                Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                                        Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "",
+                                        userId);
+                                ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
+                                        mContext, targetServices, userId);
+                            }
                             // If canceled, treat as if the dialog has never been shown
                             Settings.Secure.putIntForUser(mContext.getContentResolver(),
                                     Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
index ba1dffc..66faa31 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
@@ -23,11 +23,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.Flags;
 
 import com.android.internal.accessibility.common.ShortcutConstants;
 import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
@@ -35,6 +38,8 @@
 import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.Set;
+
 /**
  * Abstract base class for creating various target related to accessibility service, accessibility
  * activity, and allowlisting features.
@@ -108,13 +113,21 @@
         }
     }
 
+    @SuppressLint("MissingPermission")
     @Override
     public void onCheckedChanged(boolean isChecked) {
         setShortcutEnabled(isChecked);
-        if (isChecked) {
-            optInValueToSettings(getContext(), getShortcutType(), getId());
+        if (Flags.migrateEnableShortcuts()) {
+            final AccessibilityManager am =
+                    getContext().getSystemService(AccessibilityManager.class);
+            am.enableShortcutsForTargets(
+                    isChecked, getShortcutType(), Set.of(mId), UserHandle.myUserId());
         } else {
-            optOutValueFromSettings(getContext(), getShortcutType(), getId());
+            if (isChecked) {
+                optInValueToSettings(getContext(), getShortcutType(), getId());
+            } else {
+                optOutValueFromSettings(getContext(), getShortcutType(), getId());
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java
index 7535979..f9efb50 100644
--- a/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java
@@ -17,17 +17,11 @@
 package com.android.internal.accessibility.dialog;
 
 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
-import static com.android.internal.accessibility.util.AccessibilityUtils.setAccessibilityServiceState;
-import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.NonNull;
-import android.content.ComponentName;
 import android.content.Context;
-import android.widget.Toast;
 
-import com.android.internal.R;
 import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
 import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
 
@@ -47,30 +41,10 @@
 
     @Override
     public void onCheckedChanged(boolean isChecked) {
-        switch (getShortcutType()) {
-            case SOFTWARE:
-                onCheckedFromAccessibilityButton(isChecked);
-                return;
-            case HARDWARE:
-                super.onCheckedChanged(isChecked);
-                return;
-            default:
-                throw new IllegalStateException("Unexpected shortcut type");
-        }
-    }
-
-    private void onCheckedFromAccessibilityButton(boolean isChecked) {
-        setShortcutEnabled(isChecked);
-        final ComponentName componentName = ComponentName.unflattenFromString(getId());
-        setAccessibilityServiceState(getContext(), componentName, isChecked);
-
-        if (!isChecked) {
-            optOutValueFromSettings(getContext(), UserShortcutType.HARDWARE, getId());
-
-            final String warningText =
-                    getContext().getString(R.string.accessibility_uncheck_legacy_item_warning,
-                            getLabel());
-            Toast.makeText(getContext(), warningText, Toast.LENGTH_SHORT).show();
+        if (getShortcutType() == HARDWARE) {
+            super.onCheckedChanged(isChecked);
+        } else {
+            throw new IllegalStateException("Unexpected shortcut type");
         }
     }
 }
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 6bd273b..4f55441 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -28,6 +28,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import static com.android.internal.app.ResolverActivity.EXTRA_CALLING_USER;
+import static com.android.internal.app.ResolverActivity.EXTRA_RESTRICT_TO_SINGLE_USER;
 import static com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE;
 
 import android.annotation.Nullable;
@@ -190,7 +191,7 @@
                 .thenApplyAsync(targetResolveInfo -> {
                     if (isResolverActivityResolveInfo(targetResolveInfo)) {
                         launchResolverActivityWithCorrectTab(intentReceived, className, newIntent,
-                                callingUserId, targetUserId);
+                                callingUserId, targetUserId, false);
                     // When switching to the personal profile, automatically start the activity
                     } else if (className.equals(FORWARD_INTENT_TO_PARENT)) {
                         startActivityAsCaller(newIntent, targetUserId);
@@ -218,7 +219,7 @@
                 .thenAcceptAsync(targetResolveInfo -> {
                     if (isResolverActivityResolveInfo(targetResolveInfo)) {
                         launchResolverActivityWithCorrectTab(intentReceived, className, newIntent,
-                                callingUserId, targetUserId);
+                                callingUserId, targetUserId, true);
                     } else {
                         maybeShowUserConsentMiniResolverPrivate(targetResolveInfo, newIntent,
                                 targetUserId);
@@ -490,7 +491,7 @@
     }
 
     private void launchResolverActivityWithCorrectTab(Intent intentReceived, String className,
-            Intent newIntent, int callingUserId, int targetUserId) {
+            Intent newIntent, int callingUserId, int targetUserId, boolean singleTabOnly) {
         // When showing the intent resolver, instead of forwarding to the other profile,
         // we launch it in the current user and select the other tab. This fixes b/155874820.
         //
@@ -505,6 +506,9 @@
         sanitizeIntent(intentReceived);
         intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
         intentReceived.putExtra(EXTRA_CALLING_USER, UserHandle.of(callingUserId));
+        if (singleTabOnly) {
+            intentReceived.putExtra(EXTRA_RESTRICT_TO_SINGLE_USER, true);
+        }
         startActivityAsCaller(intentReceived, null, false, userId);
         finish();
     }
diff --git a/core/java/com/android/internal/compat/Android.bp b/core/java/com/android/internal/compat/Android.bp
index 9ff05a6..8253aa8 100644
--- a/core/java/com/android/internal/compat/Android.bp
+++ b/core/java/com/android/internal/compat/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "compat_logging_flags",
     package: "com.android.internal.compat.flags",
+    container: "system",
     srcs: [
         "compat_logging_flags.aconfig",
     ],
diff --git a/core/java/com/android/internal/compat/compat_logging_flags.aconfig b/core/java/com/android/internal/compat/compat_logging_flags.aconfig
index a5c31ed..4f51626 100644
--- a/core/java/com/android/internal/compat/compat_logging_flags.aconfig
+++ b/core/java/com/android/internal/compat/compat_logging_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.internal.compat.flags"
+container: "system"
 
 flag {
     name: "skip_old_and_disabled_compat_logging"
@@ -6,4 +7,4 @@
     description: "Feature flag for skipping debug logging for changes that do not target the latest sdk or are disabled"
     bug: "323949942"
     is_fixed_read_only: true
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/foldables/Android.bp b/core/java/com/android/internal/foldables/Android.bp
index f1d06da..53a9be5 100644
--- a/core/java/com/android/internal/foldables/Android.bp
+++ b/core/java/com/android/internal/foldables/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "fold_lock_setting_flags",
     package: "com.android.internal.foldables.flags",
+    container: "system",
     srcs: [
         "fold_lock_setting_flags.aconfig",
     ],
diff --git a/core/java/com/android/internal/foldables/fold_lock_setting_flags.aconfig b/core/java/com/android/internal/foldables/fold_lock_setting_flags.aconfig
index d73e623..03b6a5b 100644
--- a/core/java/com/android/internal/foldables/fold_lock_setting_flags.aconfig
+++ b/core/java/com/android/internal/foldables/fold_lock_setting_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.internal.foldables.flags"
+container: "system"
 
 flag {
     name: "fold_lock_setting_enabled"
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index 457b9dd..63623c7 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -49,4 +49,5 @@
     void onStylusHandwritingReady(int requestId, int pid);
     void resetStylusHandwriting(int requestId);
     void switchKeyboardLayoutAsync(int direction);
+    void setHandwritingSurfaceNotTouchable(boolean notTouchable);
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 635a227..72c41be 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -144,6 +144,24 @@
     }
 
     /**
+     * Calls {@link IInputMethodPrivilegedOperations#setHandwritingSurfaceNotTouchable(boolean)}.
+     *
+     * @param notTouchable {@code true} to make handwriting surface not-touchable (pass-through).
+     */
+    @AnyThread
+    public void setHandwritingSurfaceNotTouchable(boolean notTouchable) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.setHandwritingSurfaceNotTouchable(notTouchable);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Calls {@link IInputMethodPrivilegedOperations#createInputContentUriToken(Uri, String,
      * AndroidFuture)}.
      *
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 2a522645..8aba36b 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -582,23 +582,6 @@
      * @param maxHistoryFiles      the largest number of history buffer files to keep
      * @param maxHistoryBufferSize the most amount of RAM to used for buffering of history steps
      */
-    public BatteryStatsHistory(File systemDir, int maxHistoryFiles, int maxHistoryBufferSize,
-            HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
-            MonotonicClock monotonicClock) {
-        this(systemDir, maxHistoryFiles, maxHistoryBufferSize,
-                stepDetailsCalculator, clock, monotonicClock, new TraceDelegate(),
-                new EventLogger());
-    }
-
-    public BatteryStatsHistory(File systemDir, int maxHistoryFiles, int maxHistoryBufferSize,
-            HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
-            MonotonicClock monotonicClock, TraceDelegate tracer, EventLogger eventLogger) {
-        this(Parcel.obtain(), systemDir, maxHistoryFiles, maxHistoryBufferSize,
-                stepDetailsCalculator, clock, monotonicClock, tracer, eventLogger);
-        initHistoryBuffer();
-    }
-
-    @VisibleForTesting
     public BatteryStatsHistory(Parcel historyBuffer, File systemDir,
             int maxHistoryFiles, int maxHistoryBufferSize,
             HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
@@ -607,12 +590,11 @@
                 clock, monotonicClock, tracer, eventLogger, null);
     }
 
-    private BatteryStatsHistory(Parcel historyBuffer, File systemDir,
+    private BatteryStatsHistory(@Nullable Parcel historyBuffer, @Nullable File systemDir,
             int maxHistoryFiles, int maxHistoryBufferSize,
-            HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
-            MonotonicClock monotonicClock, TraceDelegate tracer, EventLogger eventLogger,
-            BatteryStatsHistory writableHistory) {
-        mHistoryBuffer = historyBuffer;
+            @NonNull HistoryStepDetailsCalculator stepDetailsCalculator, @NonNull Clock clock,
+            @NonNull MonotonicClock monotonicClock, @NonNull TraceDelegate tracer,
+            @NonNull EventLogger eventLogger, @Nullable BatteryStatsHistory writableHistory) {
         mSystemDir = systemDir;
         mMaxHistoryBufferSize = maxHistoryBufferSize;
         mStepDetailsCalculator = stepDetailsCalculator;
@@ -625,9 +607,16 @@
             mMutable = false;
         }
 
+        if (historyBuffer != null) {
+            mHistoryBuffer = historyBuffer;
+        } else {
+            mHistoryBuffer = Parcel.obtain();
+            initHistoryBuffer();
+        }
+
         if (writableHistory != null) {
             mHistoryDir = writableHistory.mHistoryDir;
-        } else {
+        } else if (systemDir != null) {
             mHistoryDir = new BatteryHistoryDirectory(new File(systemDir, HISTORY_DIR),
                     monotonicClock, maxHistoryFiles);
             mHistoryDir.load();
@@ -636,35 +625,11 @@
                 activeFile = mHistoryDir.makeBatteryHistoryFile();
             }
             setActiveFile(activeFile);
+        } else {
+            mHistoryDir = null;
         }
     }
 
-    public BatteryStatsHistory(int maxHistoryBufferSize,
-            HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
-            MonotonicClock monotonicClock) {
-        this(maxHistoryBufferSize, stepDetailsCalculator, clock, monotonicClock,
-                new TraceDelegate(), new EventLogger());
-    }
-
-    @VisibleForTesting
-    public BatteryStatsHistory(int maxHistoryBufferSize,
-            HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
-            MonotonicClock monotonicClock, TraceDelegate traceDelegate,
-            EventLogger eventLogger) {
-        mMaxHistoryBufferSize = maxHistoryBufferSize;
-        mStepDetailsCalculator = stepDetailsCalculator;
-        mTracer = traceDelegate;
-        mClock = clock;
-        mMonotonicClock = monotonicClock;
-        mEventLogger = eventLogger;
-
-        mHistoryBuffer = Parcel.obtain();
-        mSystemDir = null;
-        mHistoryDir = null;
-        mWritableHistory = null;
-        initHistoryBuffer();
-    }
-
     /**
      * Used when BatteryStatsHistory object is created from deserialization of a BatteryUsageStats
      * parcel.
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index 83e9407..e2005d7 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -259,7 +259,9 @@
             final int extensionFlags = src.readInt();
             if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_DESCRIPTOR_FLAG) != 0) {
                 PowerStats.Descriptor descriptor = PowerStats.Descriptor.readSummaryFromParcel(src);
-                mDescriptorRegistry.register(descriptor);
+                if (descriptor != null) {
+                    mDescriptorRegistry.register(descriptor);
+                }
             }
             if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_FLAG) != 0) {
                 cur.powerStats = PowerStats.readFromParcel(src, mDescriptorRegistry);
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index eef6ce7..07fa679 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -229,6 +229,17 @@
     }
 
     /**
+     * Copies time-in-state and timestamps from the supplied counter.
+     */
+    public void copyStatesFrom(LongArrayMultiStateCounter counter) {
+        if (mStateCount != counter.mStateCount) {
+            throw new IllegalArgumentException(
+                    "State count is not the same: " + mStateCount + " vs. " + counter.mStateCount);
+        }
+        native_copyStatesFrom(mNativeObject, counter.mNativeObject);
+    }
+
+    /**
      * Sets the new values for the given state.
      */
     public void setValues(int state, long[] values) {
@@ -376,6 +387,10 @@
     private static native void native_setState(long nativeObject, int state, long timestampMs);
 
     @CriticalNative
+    private static native void native_copyStatesFrom(long nativeObjectTarget,
+            long nativeObjectSource);
+
+    @CriticalNative
     private static native void native_setValues(long nativeObject, int state,
             long longArrayContainerNativeObject);
 
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index ab982f5..9646ae9 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -18,6 +18,7 @@
 
 
 import android.annotation.LongDef;
+import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.annotation.XmlRes;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -352,19 +353,39 @@
      * WARNING: use only for testing!
      */
     @VisibleForTesting
-    public void forceInitForTesting(Context context, @XmlRes int xmlId) {
+    public void initForTesting(XmlPullParser parser) {
+        initForTesting(parser, null);
+    }
+
+    /**
+     * Reinitialize the PowerProfile with the provided XML, using optional Resources for fallback
+     * configuration settings.
+     * WARNING: use only for testing!
+     */
+    @VisibleForTesting
+    public void initForTesting(XmlPullParser parser, @Nullable Resources resources) {
         synchronized (sLock) {
             sPowerItemMap.clear();
             sPowerArrayMap.clear();
             sModemPowerProfile.clear();
-            initLocked(context, xmlId);
+
+            try {
+                readPowerValuesFromXml(parser, resources);
+            } finally {
+                if (parser instanceof XmlResourceParser) {
+                    ((XmlResourceParser) parser).close();
+                }
+            }
+            initLocked();
         }
     }
 
     @GuardedBy("sLock")
     private void initLocked(Context context, @XmlRes int xmlId) {
         if (sPowerItemMap.size() == 0 && sPowerArrayMap.size() == 0) {
-            readPowerValuesFromXml(context, xmlId);
+            final Resources resources = context.getResources();
+            XmlResourceParser parser = resources.getXml(xmlId);
+            readPowerValuesFromXml(parser, resources);
         }
         initLocked();
     }
@@ -377,9 +398,8 @@
         initModem();
     }
 
-    private void readPowerValuesFromXml(Context context, @XmlRes int xmlId) {
-        final Resources resources = context.getResources();
-        XmlResourceParser parser = resources.getXml(xmlId);
+    private static void readPowerValuesFromXml(XmlPullParser parser,
+            @Nullable Resources resources) {
         boolean parsingArray = false;
         ArrayList<Double> array = new ArrayList<>();
         String arrayName = null;
@@ -430,9 +450,17 @@
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
-            parser.close();
+            if (parser instanceof XmlResourceParser) {
+                ((XmlResourceParser) parser).close();
+            }
         }
 
+        if (resources != null) {
+            getDefaultValuesFromConfig(resources);
+        }
+    }
+
+    private static void getDefaultValuesFromConfig(Resources resources) {
         // Now collect other config variables.
         int[] configResIds = new int[]{
                 com.android.internal.R.integer.config_bluetooth_idle_cur_ma,
diff --git a/core/java/com/android/internal/os/PowerStats.java b/core/java/com/android/internal/os/PowerStats.java
index 56263fb..7c7c7b8 100644
--- a/core/java/com/android/internal/os/PowerStats.java
+++ b/core/java/com/android/internal/os/PowerStats.java
@@ -47,7 +47,7 @@
 
     private static final BatteryStatsHistory.VarintParceler VARINT_PARCELER =
             new BatteryStatsHistory.VarintParceler();
-    private static final byte PARCEL_FORMAT_VERSION = 1;
+    private static final byte PARCEL_FORMAT_VERSION = 2;
 
     private static final int PARCEL_FORMAT_VERSION_MASK = 0x000000FF;
     private static final int PARCEL_FORMAT_VERSION_SHIFT =
@@ -57,7 +57,12 @@
             Integer.numberOfTrailingZeros(STATS_ARRAY_LENGTH_MASK);
     public static final int MAX_STATS_ARRAY_LENGTH =
             (1 << Integer.bitCount(STATS_ARRAY_LENGTH_MASK)) - 1;
-    private static final int UID_STATS_ARRAY_LENGTH_MASK = 0x00FF0000;
+    private static final int STATE_STATS_ARRAY_LENGTH_MASK = 0x00FF0000;
+    private static final int STATE_STATS_ARRAY_LENGTH_SHIFT =
+            Integer.numberOfTrailingZeros(STATE_STATS_ARRAY_LENGTH_MASK);
+    public static final int MAX_STATE_STATS_ARRAY_LENGTH =
+            (1 << Integer.bitCount(STATE_STATS_ARRAY_LENGTH_MASK)) - 1;
+    private static final int UID_STATS_ARRAY_LENGTH_MASK = 0xFF000000;
     private static final int UID_STATS_ARRAY_LENGTH_SHIFT =
             Integer.numberOfTrailingZeros(UID_STATS_ARRAY_LENGTH_MASK);
     public static final int MAX_UID_STATS_ARRAY_LENGTH =
@@ -74,6 +79,10 @@
         private static final String XML_ATTR_ID = "id";
         private static final String XML_ATTR_NAME = "name";
         private static final String XML_ATTR_STATS_ARRAY_LENGTH = "stats-array-length";
+        private static final String XML_TAG_STATE = "state";
+        private static final String XML_ATTR_STATE_KEY = "key";
+        private static final String XML_ATTR_STATE_LABEL = "label";
+        private static final String XML_ATTR_STATE_STATS_ARRAY_LENGTH = "state-stats-array-length";
         private static final String XML_ATTR_UID_STATS_ARRAY_LENGTH = "uid-stats-array-length";
         private static final String XML_TAG_EXTRAS = "extras";
 
@@ -85,7 +94,24 @@
         public final int powerComponentId;
         public final String name;
 
+        /**
+         * Stats for the power component, such as the total usage time.
+         */
         public final int statsArrayLength;
+
+        /**
+         * Map of device state codes to their corresponding human-readable labels.
+         */
+        public final SparseArray<String> stateLabels;
+
+        /**
+         * Stats for a specific state of the power component, e.g. "mobile radio in the 5G mode"
+         */
+        public final int stateStatsArrayLength;
+
+        /**
+         * Stats for the usage of this power component by a specific UID (app)
+         */
         public final int uidStatsArrayLength;
 
         /**
@@ -95,17 +121,25 @@
         public final PersistableBundle extras;
 
         public Descriptor(@BatteryConsumer.PowerComponent int powerComponentId,
-                int statsArrayLength, int uidStatsArrayLength, @NonNull PersistableBundle extras) {
+                int statsArrayLength, @Nullable SparseArray<String> stateLabels,
+                int stateStatsArrayLength, int uidStatsArrayLength,
+                @NonNull PersistableBundle extras) {
             this(powerComponentId, BatteryConsumer.powerComponentIdToString(powerComponentId),
-                    statsArrayLength, uidStatsArrayLength, extras);
+                    statsArrayLength, stateLabels, stateStatsArrayLength, uidStatsArrayLength,
+                    extras);
         }
 
         public Descriptor(int customPowerComponentId, String name, int statsArrayLength,
+                @Nullable SparseArray<String> stateLabels, int stateStatsArrayLength,
                 int uidStatsArrayLength, PersistableBundle extras) {
             if (statsArrayLength > MAX_STATS_ARRAY_LENGTH) {
                 throw new IllegalArgumentException(
                         "statsArrayLength is too high. Max = " + MAX_STATS_ARRAY_LENGTH);
             }
+            if (stateStatsArrayLength > MAX_STATE_STATS_ARRAY_LENGTH) {
+                throw new IllegalArgumentException(
+                        "stateStatsArrayLength is too high. Max = " + MAX_STATE_STATS_ARRAY_LENGTH);
+            }
             if (uidStatsArrayLength > MAX_UID_STATS_ARRAY_LENGTH) {
                 throw new IllegalArgumentException(
                         "uidStatsArrayLength is too high. Max = " + MAX_UID_STATS_ARRAY_LENGTH);
@@ -113,11 +147,25 @@
             this.powerComponentId = customPowerComponentId;
             this.name = name;
             this.statsArrayLength = statsArrayLength;
+            this.stateLabels = stateLabels != null ? stateLabels : new SparseArray<>();
+            this.stateStatsArrayLength = stateStatsArrayLength;
             this.uidStatsArrayLength = uidStatsArrayLength;
             this.extras = extras;
         }
 
         /**
+         * Returns the label associated with the give state key, e.g. "5G-high" for the
+         * state of Mobile Radio representing the 5G mode and high signal power.
+         */
+        public String getStateLabel(int key) {
+            String label = stateLabels.get(key);
+            if (label != null) {
+                return label;
+            }
+            return name + "-" + Integer.toHexString(key);
+        }
+
+        /**
          * Writes the Descriptor into the parcel.
          */
         public void writeSummaryToParcel(Parcel parcel) {
@@ -125,11 +173,18 @@
                              & PARCEL_FORMAT_VERSION_MASK)
                             | ((statsArrayLength << STATS_ARRAY_LENGTH_SHIFT)
                                & STATS_ARRAY_LENGTH_MASK)
+                            | ((stateStatsArrayLength << STATE_STATS_ARRAY_LENGTH_SHIFT)
+                               & STATE_STATS_ARRAY_LENGTH_MASK)
                             | ((uidStatsArrayLength << UID_STATS_ARRAY_LENGTH_SHIFT)
                                & UID_STATS_ARRAY_LENGTH_MASK);
             parcel.writeInt(firstWord);
             parcel.writeInt(powerComponentId);
             parcel.writeString(name);
+            parcel.writeInt(stateLabels.size());
+            for (int i = 0, size = stateLabels.size(); i < size; i++) {
+                parcel.writeInt(stateLabels.keyAt(i));
+                parcel.writeString(stateLabels.valueAt(i));
+            }
             extras.writeToParcel(parcel, 0);
         }
 
@@ -148,13 +203,22 @@
             }
             int statsArrayLength =
                     (firstWord & STATS_ARRAY_LENGTH_MASK) >>> STATS_ARRAY_LENGTH_SHIFT;
+            int stateStatsArrayLength =
+                    (firstWord & STATE_STATS_ARRAY_LENGTH_MASK) >>> STATE_STATS_ARRAY_LENGTH_SHIFT;
             int uidStatsArrayLength =
                     (firstWord & UID_STATS_ARRAY_LENGTH_MASK) >>> UID_STATS_ARRAY_LENGTH_SHIFT;
             int powerComponentId = parcel.readInt();
             String name = parcel.readString();
+            int stateLabelCount = parcel.readInt();
+            SparseArray<String> stateLabels = new SparseArray<>(stateLabelCount);
+            for (int i = stateLabelCount; i > 0; i--) {
+                int key = parcel.readInt();
+                String label = parcel.readString();
+                stateLabels.put(key, label);
+            }
             PersistableBundle extras = parcel.readPersistableBundle();
-            return new Descriptor(powerComponentId, name, statsArrayLength, uidStatsArrayLength,
-                    extras);
+            return new Descriptor(powerComponentId, name, statsArrayLength, stateLabels,
+                    stateStatsArrayLength, uidStatsArrayLength, extras);
         }
 
         @Override
@@ -163,11 +227,13 @@
             if (!(o instanceof Descriptor)) return false;
             Descriptor that = (Descriptor) o;
             return powerComponentId == that.powerComponentId
-                   && statsArrayLength == that.statsArrayLength
-                   && uidStatsArrayLength == that.uidStatsArrayLength
-                   && Objects.equals(name, that.name)
-                   && extras.size() == that.extras.size()        // Unparcel the Parcel if not yet
-                   && Bundle.kindofEquals(extras,
+                    && statsArrayLength == that.statsArrayLength
+                    && stateLabels.contentEquals(that.stateLabels)
+                    && stateStatsArrayLength == that.stateStatsArrayLength
+                    && uidStatsArrayLength == that.uidStatsArrayLength
+                    && Objects.equals(name, that.name)
+                    && extras.size() == that.extras.size()        // Unparcel the Parcel if not yet
+                    && Bundle.kindofEquals(extras,
                     that.extras);  // Since the Parcel is now unparceled, do a deep comparison
         }
 
@@ -179,7 +245,14 @@
             serializer.attributeInt(null, XML_ATTR_ID, powerComponentId);
             serializer.attribute(null, XML_ATTR_NAME, name);
             serializer.attributeInt(null, XML_ATTR_STATS_ARRAY_LENGTH, statsArrayLength);
+            serializer.attributeInt(null, XML_ATTR_STATE_STATS_ARRAY_LENGTH, stateStatsArrayLength);
             serializer.attributeInt(null, XML_ATTR_UID_STATS_ARRAY_LENGTH, uidStatsArrayLength);
+            for (int i = stateLabels.size() - 1; i >= 0; i--) {
+                serializer.startTag(null, XML_TAG_STATE);
+                serializer.attributeInt(null, XML_ATTR_STATE_KEY, stateLabels.keyAt(i));
+                serializer.attribute(null, XML_ATTR_STATE_LABEL, stateLabels.valueAt(i));
+                serializer.endTag(null, XML_TAG_STATE);
+            }
             try {
                 serializer.startTag(null, XML_TAG_EXTRAS);
                 extras.saveToXml(serializer);
@@ -199,6 +272,8 @@
             int powerComponentId = -1;
             String name = null;
             int statsArrayLength = 0;
+            SparseArray<String> stateLabels = new SparseArray<>();
+            int stateStatsArrayLength = 0;
             int uidStatsArrayLength = 0;
             PersistableBundle extras = null;
             int eventType = parser.getEventType();
@@ -212,9 +287,16 @@
                             name = parser.getAttributeValue(null, XML_ATTR_NAME);
                             statsArrayLength = parser.getAttributeInt(null,
                                     XML_ATTR_STATS_ARRAY_LENGTH);
+                            stateStatsArrayLength = parser.getAttributeInt(null,
+                                    XML_ATTR_STATE_STATS_ARRAY_LENGTH);
                             uidStatsArrayLength = parser.getAttributeInt(null,
                                     XML_ATTR_UID_STATS_ARRAY_LENGTH);
                             break;
+                        case XML_TAG_STATE:
+                            int value = parser.getAttributeInt(null, XML_ATTR_STATE_KEY);
+                            String label = parser.getAttributeValue(null, XML_ATTR_STATE_LABEL);
+                            stateLabels.put(value, label);
+                            break;
                         case XML_TAG_EXTRAS:
                             extras = PersistableBundle.restoreFromXml(parser);
                             break;
@@ -225,11 +307,11 @@
             if (powerComponentId == -1) {
                 return null;
             } else if (powerComponentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
-                return new Descriptor(powerComponentId, name, statsArrayLength, uidStatsArrayLength,
-                        extras);
+                return new Descriptor(powerComponentId, name, statsArrayLength,
+                        stateLabels, stateStatsArrayLength, uidStatsArrayLength, extras);
             } else if (powerComponentId < BatteryConsumer.POWER_COMPONENT_COUNT) {
-                return new Descriptor(powerComponentId, statsArrayLength, uidStatsArrayLength,
-                        extras);
+                return new Descriptor(powerComponentId, statsArrayLength, stateLabels,
+                        stateStatsArrayLength, uidStatsArrayLength, extras);
             } else {
                 Slog.e(TAG, "Unrecognized power component: " + powerComponentId);
                 return null;
@@ -247,12 +329,14 @@
                 extras.size();  // Unparcel
             }
             return "PowerStats.Descriptor{"
-                   + "powerComponentId=" + powerComponentId
-                   + ", name='" + name + '\''
-                   + ", statsArrayLength=" + statsArrayLength
-                   + ", uidStatsArrayLength=" + uidStatsArrayLength
-                   + ", extras=" + extras
-                   + '}';
+                    + "powerComponentId=" + powerComponentId
+                    + ", name='" + name + '\''
+                    + ", statsArrayLength=" + statsArrayLength
+                    + ", stateStatsArrayLength=" + stateStatsArrayLength
+                    + ", stateLabels=" + stateLabels
+                    + ", uidStatsArrayLength=" + uidStatsArrayLength
+                    + ", extras=" + extras
+                    + '}';
         }
     }
 
@@ -293,6 +377,12 @@
     public long[] stats;
 
     /**
+     * Device-wide mode stats, used when the power component can operate in different modes,
+     * e.g. RATs such as LTE and 5G.
+     */
+    public final SparseArray<long[]> stateStats = new SparseArray<>();
+
+    /**
      * Per-UID CPU stats.
      */
     public final SparseArray<long[]> uidStats = new SparseArray<>();
@@ -313,6 +403,15 @@
         parcel.writeInt(descriptor.powerComponentId);
         parcel.writeLong(durationMs);
         VARINT_PARCELER.writeLongArray(parcel, stats);
+
+        if (descriptor.stateStatsArrayLength != 0) {
+            parcel.writeInt(stateStats.size());
+            for (int i = 0; i < stateStats.size(); i++) {
+                parcel.writeInt(stateStats.keyAt(i));
+                VARINT_PARCELER.writeLongArray(parcel, stateStats.valueAt(i));
+            }
+        }
+
         parcel.writeInt(uidStats.size());
         for (int i = 0; i < uidStats.size(); i++) {
             parcel.writeInt(uidStats.keyAt(i));
@@ -347,6 +446,17 @@
             stats.durationMs = parcel.readLong();
             stats.stats = new long[descriptor.statsArrayLength];
             VARINT_PARCELER.readLongArray(parcel, stats.stats);
+
+            if (descriptor.stateStatsArrayLength != 0) {
+                int count = parcel.readInt();
+                for (int i = 0; i < count; i++) {
+                    int state = parcel.readInt();
+                    long[] stateStats = new long[descriptor.stateStatsArrayLength];
+                    VARINT_PARCELER.readLongArray(parcel, stateStats);
+                    stats.stateStats.put(state, stateStats);
+                }
+            }
+
             int uidCount = parcel.readInt();
             for (int i = 0; i < uidCount; i++) {
                 int uid = parcel.readInt();
@@ -376,6 +486,14 @@
         if (stats.length > 0) {
             sb.append("=").append(Arrays.toString(stats));
         }
+        if (descriptor.stateStatsArrayLength != 0) {
+            for (int i = 0; i < stateStats.size(); i++) {
+                sb.append(" [");
+                sb.append(descriptor.getStateLabel(stateStats.keyAt(i)));
+                sb.append("]=");
+                sb.append(Arrays.toString(stateStats.valueAt(i)));
+            }
+        }
         for (int i = 0; i < uidStats.size(); i++) {
             sb.append(uidPrefix)
                     .append(UserHandle.formatUid(uidStats.keyAt(i)))
@@ -391,6 +509,18 @@
         pw.println("PowerStats: " + descriptor.name + " (" + descriptor.powerComponentId + ')');
         pw.increaseIndent();
         pw.print("duration", durationMs).println();
+        if (descriptor.statsArrayLength != 0) {
+            pw.print("stats", Arrays.toString(stats)).println();
+        }
+        if (descriptor.stateStatsArrayLength != 0) {
+            for (int i = 0; i < stateStats.size(); i++) {
+                pw.print("state ");
+                pw.print(descriptor.getStateLabel(stateStats.keyAt(i)));
+                pw.print(": ");
+                pw.print(Arrays.toString(stateStats.valueAt(i)));
+                pw.println();
+            }
+        }
         for (int i = 0; i < uidStats.size(); i++) {
             pw.print("UID ");
             pw.print(uidStats.keyAt(i));
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5297006..b9cc457 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -397,6 +397,14 @@
                 null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
                 false /*isNative*/));
 
+        if (Flags.enableApacheHttpLegacyPreload()) {
+            libs.add(new SharedLibraryInfo(
+                    "/system/framework/org.apache.http.legacy.jar", null /*packageName*/,
+                    null /*codePaths*/, null /*name*/, 0 /*version*/,
+                    SharedLibraryInfo.TYPE_BUILTIN, null /*declaringPackage*/,
+                    null /*dependentPackages*/, null /*dependencies*/, false /*isNative*/));
+        }
+
         // WindowManager Extensions is an optional shared library that is required for WindowManager
         // Jetpack to fully function. Since it is a widely used library, preload it to improve apps
         // startup performance.
diff --git a/core/java/com/android/internal/os/flags.aconfig b/core/java/com/android/internal/os/flags.aconfig
new file mode 100644
index 0000000..c8d6810
--- /dev/null
+++ b/core/java/com/android/internal/os/flags.aconfig
@@ -0,0 +1,11 @@
+package: "com.android.internal.os"
+container: "system"
+
+flag {
+    name: "enable_apache_http_legacy_preload"
+    namespace: "system_performance"
+    description: "Enables zygote preload of non-BCP org.apache.http.legacy.jar library."
+    # Fixed read-only is required as the flag is read during zygote init.
+    is_fixed_read_only: true
+    bug: "241474956"
+}
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
index e12becd..97ce96e 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
@@ -238,6 +238,7 @@
      */
     public static final int PARSE_IGNORE_OVERLAY_REQUIRED_SYSTEM_PROPERTY = 1 << 7;
     public static final int PARSE_APK_IN_APEX = 1 << 9;
+    public static final int PARSE_APEX = 1 << 10;
 
     public static final int PARSE_CHATTY = 1 << 31;
 
@@ -339,6 +340,9 @@
         if ((flags & PARSE_APK_IN_APEX) != 0) {
             liteParseFlags |= PARSE_APK_IN_APEX;
         }
+        if ((flags & PARSE_APEX) != 0) {
+            liteParseFlags |= PARSE_APEX;
+        }
         final ParseResult<PackageLite> liteResult =
                 ApkLiteParseUtils.parseClusterPackageLite(input, packageDir, liteParseFlags);
         if (liteResult.isError()) {
@@ -530,7 +534,7 @@
 
         afterParseBaseApplication(pkg);
 
-        final ParseResult<ParsingPackage> result = validateBaseApkTags(input, pkg);
+        final ParseResult<ParsingPackage> result = validateBaseApkTags(input, pkg, flags);
         if (result.isError()) {
             return result;
         }
@@ -1012,10 +1016,11 @@
             }
         }
 
-        return validateBaseApkTags(input, pkg);
+        return validateBaseApkTags(input, pkg, flags);
     }
 
-    private ParseResult<ParsingPackage> validateBaseApkTags(ParseInput input, ParsingPackage pkg) {
+    private ParseResult<ParsingPackage> validateBaseApkTags(ParseInput input, ParsingPackage pkg,
+            int flags) {
         if (!ParsedAttributionUtils.isCombinationValid(pkg.getAttributions())) {
             return input.error(
                     INSTALL_PARSE_FAILED_BAD_MANIFEST,
@@ -1047,6 +1052,16 @@
             adjustPackageToBeUnresizeableAndUnpipable(pkg);
         }
 
+        // An Apex package shouldn't have permission declarations
+        final boolean isApex = (flags & PARSE_APEX) != 0;
+        if (isApex && !pkg.getPermissions().isEmpty()) {
+            return input.error(
+                    INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+                    pkg.getPackageName()
+                            + " is an APEX package and shouldn't declare permissions."
+            );
+        }
+
         return input.success(pkg);
     }
 
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 6848646..c6e8bf7 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -56,7 +56,6 @@
     // during a configuration change.
     private int mLastContentWidth;
     private int mLastContentHeight;
-    private int mLastCaptionHeight;
     private int mLastXOffset;
     private int mLastYOffset;
 
@@ -269,7 +268,7 @@
             final boolean firstCall = mLastContentWidth == 0;
             // The current content buffer is drawn here.
             mLastContentWidth = xSize;
-            mLastContentHeight = ySize - mLastCaptionHeight;
+            mLastContentHeight = ySize;
             mLastXOffset = xOffset;
             mLastYOffset = yOffset;
 
@@ -278,12 +277,11 @@
                     mLastXOffset,
                     mLastYOffset,
                     mLastXOffset + mLastContentWidth,
-                    mLastYOffset + mLastCaptionHeight + mLastContentHeight);
+                    mLastYOffset + mLastContentHeight);
 
             // If this was the first call and redrawLocked got already called prior
             // to us, we should re-issue a redrawLocked now.
-            return firstCall
-                    && (mLastCaptionHeight != 0 || !mDecorView.isShowingCaption());
+            return firstCall;
         }
     }
 
@@ -303,22 +301,9 @@
      */
     private void redrawLocked(Rect newBounds, boolean fullscreen) {
 
-        // While a configuration change is taking place the view hierarchy might become
-        // inaccessible. For that case we remember the previous metrics to avoid flashes.
-        // Note that even when there is no visible caption, the caption child will exist.
-        final int captionHeight = mDecorView.getCaptionHeight();
-
-        // The caption height will probably never dynamically change while we are resizing.
-        // Once set to something other then 0 it should be kept that way.
-        if (captionHeight != 0) {
-            // Remember the height of the caption.
-            mLastCaptionHeight = captionHeight;
-        }
-
         // Make sure that the other thread has already prepared the render draw calls for the
         // content. If any size is 0, we have to wait for it to be drawn first.
-        if ((mLastCaptionHeight == 0 && mDecorView.isShowingCaption()) ||
-                mLastContentWidth == 0 || mLastContentHeight == 0) {
+        if (mLastContentWidth == 0 || mLastContentHeight == 0) {
             return;
         }
 
@@ -337,13 +322,13 @@
                 ? mUserCaptionBackgroundDrawable : mCaptionBackgroundDrawable;
 
         if (drawable != null) {
-            drawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
+            drawable.setBounds(0, 0, left + width, top);
             drawable.draw(canvas);
         }
 
         // The backdrop: clear everything with the background. Clipping is done elsewhere.
         if (mResizingBackgroundDrawable != null) {
-            mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
+            mResizingBackgroundDrawable.setBounds(0, 0, left + width, top + height);
             mResizingBackgroundDrawable.draw(canvas);
         }
         mFrameAndBackdropNode.endRecording();
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index a65a1bb..ab37252 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -26,9 +26,6 @@
 import static android.view.View.MeasureSpec.getMode;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
-import static android.view.Window.DECOR_CAPTION_SHADE_DARK;
-import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT;
 import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
@@ -38,9 +35,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 
 import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
@@ -83,7 +77,6 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.PendingInsetsController;
-import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
@@ -116,7 +109,6 @@
 import com.android.internal.view.menu.MenuHelper;
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.BackgroundFallback;
-import com.android.internal.widget.DecorCaptionView;
 import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
 
 import java.util.List;
@@ -189,8 +181,6 @@
 
     private final Rect mFrameOffsets = new Rect();
 
-    private boolean mHasCaption = false;
-
     private boolean mChanging;
 
     private Drawable mMenuBackground;
@@ -247,11 +237,6 @@
 
     private Rect mTempRect;
 
-    // This is the caption view for the window, containing the caption and window control
-    // buttons. The visibility of this decor depends on the workspace and the window type.
-    // If the window type does not require such a view, this member might be null.
-    private DecorCaptionView mDecorCaptionView;
-
     private boolean mWindowResizeCallbacksAdded = false;
     private Drawable.Callback mLastBackgroundDrawableCb = null;
     private BackdropFrameRenderer mBackdropFrameRenderer = null;
@@ -524,24 +509,6 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         int action = event.getAction();
-        if (mHasCaption && isShowingCaption()) {
-            // Don't dispatch ACTION_DOWN to the captionr if the window is resizable and the event
-            // was (starting) outside the window. Window resizing events should be handled by
-            // WindowManager.
-            // TODO: Investigate how to handle the outside touch in window manager
-            //       without generating these events.
-            //       Currently we receive these because we need to enlarge the window's
-            //       touch region so that the monitor channel receives the events
-            //       in the outside touch area.
-            if (action == MotionEvent.ACTION_DOWN) {
-                final int x = (int) event.getX();
-                final int y = (int) event.getY();
-                if (isOutOfInnerBounds(x, y)) {
-                    return true;
-                }
-            }
-        }
-
         if (mFeatureId >= 0) {
             if (action == MotionEvent.ACTION_DOWN) {
                 int x = (int)event.getX();
@@ -1041,7 +1008,6 @@
     @Override
     public void onWindowSystemUiVisibilityChanged(int visible) {
         updateColorViews(null /* insets */, true /* animate */);
-        updateDecorCaptionStatus(getResources().getConfiguration());
 
         if (mStatusGuard != null && mStatusGuard.getVisibility() == VISIBLE) {
             updateStatusGuardColor();
@@ -1214,11 +1180,6 @@
                     mLastTopInset, false /* matchVertical */, statusBarNeedsLeftInset,
                     statusBarSideInset, animate && !disallowAnimate,
                     mForceWindowDrawsBarBackgrounds, requestedVisibleTypes);
-
-            if (mHasCaption) {
-                mDecorCaptionView.getCaption().setBackgroundColor(statusBarColor);
-                updateDecorCaptionShade();
-            }
         }
 
         // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
@@ -1483,7 +1444,7 @@
                 mWindow.getAttributes().flags, force);
         boolean show = state.attributes.isVisible(state.present, color,
                 mWindow.getAttributes().flags, force);
-        boolean showView = show && !isResizing() && !mHasCaption && size > 0;
+        boolean showView = show && !isResizing() && size > 0;
 
         boolean visibilityChanged = false;
         View view = state.view;
@@ -1950,9 +1911,6 @@
     @Override
     public void onRootViewScrollYChanged(int rootScrollY) {
         mRootScrollY = rootScrollY;
-        if (mDecorCaptionView != null) {
-            mDecorCaptionView.onRootViewScrollYChanged(rootScrollY);
-        }
         updateColorViewTranslations();
     }
 
@@ -2141,31 +2099,6 @@
             .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
     }
 
-    /**
-     * Informs the decor if the caption is attached and visible.
-     * @param attachedAndVisible true when the decor is visible.
-     * Note that this will even be called if there is no caption.
-     **/
-    void enableCaption(boolean attachedAndVisible) {
-        if (mHasCaption != attachedAndVisible) {
-            mHasCaption = attachedAndVisible;
-            if (getForeground() != null) {
-                drawableChanged();
-            }
-            notifyCaptionHeightChanged();
-        }
-    }
-
-    /**
-     * An interface to be called when the caption visibility or height changed, to report the
-     * corresponding insets change to the InsetsController.
-     */
-    public void notifyCaptionHeightChanged() {
-        if (!CAPTION_ON_SHELL) {
-            getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
-        }
-    }
-
     void setWindow(PhoneWindow phoneWindow) {
         mWindow = phoneWindow;
         Context context = getContext();
@@ -2191,8 +2124,6 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        updateDecorCaptionStatus(newConfig);
-
         initializeElevation();
     }
 
@@ -2214,29 +2145,6 @@
                 & View.SYSTEM_UI_FLAG_FULLSCREEN));
     }
 
-    private void updateDecorCaptionStatus(Configuration config) {
-        final boolean displayWindowDecor = config.windowConfiguration.hasWindowDecorCaption()
-                && !isFillingScreen(config);
-        if (mDecorCaptionView == null && displayWindowDecor) {
-            // Configuration now requires a caption.
-            final LayoutInflater inflater = mWindow.getLayoutInflater();
-            mDecorCaptionView = createDecorCaptionView(inflater);
-            if (mDecorCaptionView != null) {
-                if (mDecorCaptionView.getParent() == null) {
-                    addView(mDecorCaptionView, 0,
-                            new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-                }
-                removeView(mContentRoot);
-                mDecorCaptionView.addView(mContentRoot,
-                        new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
-            }
-        } else if (mDecorCaptionView != null) {
-            // We might have to change the kind of surface before we do anything else.
-            mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
-            enableCaption(displayWindowDecor);
-        }
-    }
-
     void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
         if (mBackdropFrameRenderer != null) {
             loadBackgroundDrawablesIfNeeded();
@@ -2246,20 +2154,10 @@
                     getCurrentColor(mNavigationColorViewState));
         }
 
-        mDecorCaptionView = createDecorCaptionView(inflater);
         final View root = inflater.inflate(layoutResource, null);
-        if (mDecorCaptionView != null) {
-            if (mDecorCaptionView.getParent() == null) {
-                addView(mDecorCaptionView,
-                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-            }
-            mDecorCaptionView.addView(root,
-                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
-        } else {
 
-            // Put it below the color views.
-            addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-        }
+        // Put it below the color views.
+        addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
         mContentRoot = (ViewGroup) root;
         initializeElevation();
     }
@@ -2285,89 +2183,6 @@
         }
     }
 
-    // Free floating overlapping windows require a caption.
-    private DecorCaptionView createDecorCaptionView(LayoutInflater inflater) {
-        DecorCaptionView decorCaptionView = null;
-        for (int i = getChildCount() - 1; i >= 0 && decorCaptionView == null; i--) {
-            View view = getChildAt(i);
-            if (view instanceof DecorCaptionView) {
-                // The decor was most likely saved from a relaunch - so reuse it.
-                decorCaptionView = (DecorCaptionView) view;
-                removeViewAt(i);
-            }
-        }
-        final WindowManager.LayoutParams attrs = mWindow.getAttributes();
-        final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
-                attrs.type == TYPE_APPLICATION || attrs.type == TYPE_DRAWN_APPLICATION;
-        final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration;
-        // Only a non floating application window on one of the allowed workspaces can get a caption
-        if (!mWindow.isFloating() && isApplication && winConfig.hasWindowDecorCaption()
-                && !CAPTION_ON_SHELL) {
-            // Dependent on the brightness of the used title we either use the
-            // dark or the light button frame.
-            if (decorCaptionView == null) {
-                decorCaptionView = inflateDecorCaptionView(inflater);
-            }
-            decorCaptionView.setPhoneWindow(mWindow, true /*showDecor*/);
-        } else {
-            decorCaptionView = null;
-        }
-
-        // Tell the decor if it has a visible caption.
-        enableCaption(decorCaptionView != null);
-        return decorCaptionView;
-    }
-
-    private DecorCaptionView inflateDecorCaptionView(LayoutInflater inflater) {
-        final Context context = getContext();
-        // We make a copy of the inflater, so it has the right context associated with it.
-        inflater = inflater.from(context);
-        final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,
-                null);
-        setDecorCaptionShade(view);
-        return view;
-    }
-
-    private void setDecorCaptionShade(DecorCaptionView view) {
-        final int shade = mWindow.getDecorCaptionShade();
-        switch (shade) {
-            case DECOR_CAPTION_SHADE_LIGHT:
-                setLightDecorCaptionShade(view);
-                break;
-            case DECOR_CAPTION_SHADE_DARK:
-                setDarkDecorCaptionShade(view);
-                break;
-            default: {
-                if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) {
-                    setDarkDecorCaptionShade(view);
-                } else {
-                    setLightDecorCaptionShade(view);
-                }
-                break;
-            }
-        }
-    }
-
-    void updateDecorCaptionShade() {
-        if (mDecorCaptionView != null) {
-            setDecorCaptionShade(mDecorCaptionView);
-        }
-    }
-
-    private void setLightDecorCaptionShade(DecorCaptionView view) {
-        view.findViewById(R.id.maximize_window).setBackgroundResource(
-                R.drawable.decor_maximize_button_light);
-        view.findViewById(R.id.close_window).setBackgroundResource(
-                R.drawable.decor_close_button_light);
-    }
-
-    private void setDarkDecorCaptionShade(DecorCaptionView view) {
-        view.findViewById(R.id.maximize_window).setBackgroundResource(
-                R.drawable.decor_maximize_button_dark);
-        view.findViewById(R.id.close_window).setBackgroundResource(
-                R.drawable.decor_close_button_dark);
-    }
-
     /**
      * Returns the color used to fill areas the app has not rendered content to yet when the
      * user is resizing the window of an activity in multi-window mode.
@@ -2405,17 +2220,11 @@
     }
 
     void clearContentView() {
-        if (mDecorCaptionView != null) {
-            mDecorCaptionView.removeContentView();
-        } else {
-            // This window doesn't have caption, so we need to remove everything except our views
-            // we might have added.
-            for (int i = getChildCount() - 1; i >= 0; i--) {
-                View v = getChildAt(i);
-                if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
-                        && v != mStatusGuard) {
-                    removeViewAt(i);
-                }
+        for (int i = getChildCount() - 1; i >= 0; i--) {
+            View v = getChildAt(i);
+            if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
+                    && v != mStatusGuard) {
+                removeViewAt(i);
             }
         }
     }
@@ -2439,23 +2248,6 @@
         if (mBackdropFrameRenderer != null) {
             return;
         }
-        final ThreadedRenderer renderer = getThreadedRenderer();
-        if (renderer != null && !CAPTION_ON_SHELL) {
-            loadBackgroundDrawablesIfNeeded();
-            WindowInsets rootInsets = getRootWindowInsets();
-            mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
-                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
-                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
-                    getCurrentColor(mNavigationColorViewState), fullscreen,
-                    rootInsets.getInsets(WindowInsets.Type.systemBars()));
-
-            // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
-            // If we want to get the shadow shown while resizing, we would need to elevate a new
-            // element which owns the caption and has the elevation.
-            updateElevation();
-
-            updateColorViews(null /* insets */, false);
-        }
         getViewRootImpl().requestInvalidateRootRenderNode();
     }
 
@@ -2576,23 +2368,6 @@
         }
     }
 
-    boolean isShowingCaption() {
-        return mDecorCaptionView != null && mDecorCaptionView.isCaptionShowing();
-    }
-
-    int getCaptionHeight() {
-        return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
-    }
-
-    /**
-     * @hide
-     * @return the height of insets covering the top of window content area.
-     */
-    public int getCaptionInsetsHeight() {
-        if (!mWindow.isOverlayWithDecorCaptionEnabled()) return 0;
-        return getCaptionHeight();
-    }
-
     /**
      * Converts a DIP measure into physical pixels.
      * @param dip The dip value.
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index e6a2a6c..52487fb 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -363,8 +363,6 @@
     private boolean mIsStartingWindow;
     private int mTheme = -1;
 
-    private int mDecorCaptionShade = DECOR_CAPTION_SHADE_AUTO;
-
     private boolean mUseDecorContext = false;
 
     /** @see ViewRootImpl#mActivityConfigCallback */
@@ -2488,9 +2486,6 @@
             setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
             params.setFitInsetsSides(0);
             params.setFitInsetsTypes(0);
-            if (mEdgeToEdgeEnforced) {
-                params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-            }
         }
 
         if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
@@ -4048,14 +4043,7 @@
 
     @Override
     public void setDecorCaptionShade(int decorCaptionShade) {
-        mDecorCaptionShade = decorCaptionShade;
-        if (mDecor != null) {
-            mDecor.updateDecorCaptionShade();
-        }
-    }
-
-    int getDecorCaptionShade() {
-        return mDecorCaptionShade;
+        // TODO(b/328668781): Make proper treatment to this public API per the outcome of the bug.
     }
 
     @Override
diff --git a/core/java/com/android/internal/power/ModemPowerProfile.java b/core/java/com/android/internal/power/ModemPowerProfile.java
index b15c10e..64d3139 100644
--- a/core/java/com/android/internal/power/ModemPowerProfile.java
+++ b/core/java/com/android/internal/power/ModemPowerProfile.java
@@ -17,14 +17,16 @@
 package com.android.internal.power;
 
 import android.annotation.IntDef;
-import android.content.res.XmlResourceParser;
+import android.os.BatteryStats;
 import android.telephony.ModemActivityInfo;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseDoubleArray;
 
+import com.android.internal.os.PowerProfile;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -95,6 +97,8 @@
      */
     public static final int MODEM_DRAIN_TYPE_TX = 0x3000_0000;
 
+    private static final int IGNORE = -1;
+
     @IntDef(prefix = {"MODEM_DRAIN_TYPE_"}, value = {
             MODEM_DRAIN_TYPE_SLEEP,
             MODEM_DRAIN_TYPE_IDLE,
@@ -256,7 +260,7 @@
     /**
      * Generates a ModemPowerProfile object from the <modem /> element of a power_profile.xml
      */
-    public void parseFromXml(XmlResourceParser parser) throws IOException,
+    public void parseFromXml(XmlPullParser parser) throws IOException,
             XmlPullParserException {
         final int depth = parser.getDepth();
         while (XmlUtils.nextElementWithin(parser, depth)) {
@@ -286,7 +290,7 @@
     }
 
     /** Parse the <active /> XML element */
-    private void parseActivePowerConstantsFromXml(XmlResourceParser parser)
+    private void parseActivePowerConstantsFromXml(XmlPullParser parser)
             throws IOException, XmlPullParserException {
         // Parse attributes to get the type of active modem usage the power constants are for.
         final int ratType;
@@ -339,7 +343,7 @@
         }
     }
 
-    private static int getTypeFromAttribute(XmlResourceParser parser, String attr,
+    private static int getTypeFromAttribute(XmlPullParser parser, String attr,
             SparseArray<String> names) {
         final String value = XmlUtils.readStringAttribute(parser, attr);
         if (value == null) {
@@ -382,6 +386,84 @@
         }
     }
 
+    public static long getAverageBatteryDrainKey(@ModemDrainType int drainType,
+            @BatteryStats.RadioAccessTechnology int rat, @ServiceState.FrequencyRange int freqRange,
+            int txLevel) {
+        long key = PowerProfile.SUBSYSTEM_MODEM;
+
+        // Attach Modem drain type to the key if specified.
+        if (drainType != IGNORE) {
+            key |= drainType;
+        }
+
+        // Attach RadioAccessTechnology to the key if specified.
+        switch (rat) {
+            case IGNORE:
+                // do nothing
+                break;
+            case BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER:
+                key |= MODEM_RAT_TYPE_DEFAULT;
+                break;
+            case BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE:
+                key |= MODEM_RAT_TYPE_LTE;
+                break;
+            case BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR:
+                key |= MODEM_RAT_TYPE_NR;
+                break;
+            default:
+                Log.w(TAG, "Unexpected RadioAccessTechnology : " + rat);
+        }
+
+        // Attach NR Frequency Range to the key if specified.
+        switch (freqRange) {
+            case IGNORE:
+                // do nothing
+                break;
+            case ServiceState.FREQUENCY_RANGE_UNKNOWN:
+                key |= MODEM_NR_FREQUENCY_RANGE_DEFAULT;
+                break;
+            case ServiceState.FREQUENCY_RANGE_LOW:
+                key |= MODEM_NR_FREQUENCY_RANGE_LOW;
+                break;
+            case ServiceState.FREQUENCY_RANGE_MID:
+                key |= MODEM_NR_FREQUENCY_RANGE_MID;
+                break;
+            case ServiceState.FREQUENCY_RANGE_HIGH:
+                key |= MODEM_NR_FREQUENCY_RANGE_HIGH;
+                break;
+            case ServiceState.FREQUENCY_RANGE_MMWAVE:
+                key |= MODEM_NR_FREQUENCY_RANGE_MMWAVE;
+                break;
+            default:
+                Log.w(TAG, "Unexpected NR frequency range : " + freqRange);
+        }
+
+        // Attach transmission level to the key if specified.
+        switch (txLevel) {
+            case IGNORE:
+                // do nothing
+                break;
+            case 0:
+                key |= MODEM_TX_LEVEL_0;
+                break;
+            case 1:
+                key |= MODEM_TX_LEVEL_1;
+                break;
+            case 2:
+                key |= MODEM_TX_LEVEL_2;
+                break;
+            case 3:
+                key |= MODEM_TX_LEVEL_3;
+                break;
+            case 4:
+                key |= MODEM_TX_LEVEL_4;
+                break;
+            default:
+                Log.w(TAG, "Unexpected transmission level : " + txLevel);
+        }
+        return key;
+    }
+
     /**
      * Returns the average battery drain in milli-amps of the modem for a given drain type.
      * Returns {@link Double.NaN} if a suitable value is not found for the given key.
@@ -444,6 +526,7 @@
         }
         return sb.toString();
     }
+
     private static void appendFieldToString(StringBuilder sb, String fieldName,
             SparseArray<String> names, int key) {
         sb.append(fieldName);
diff --git a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
index 2096ba4..d244874 100644
--- a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
@@ -66,6 +66,7 @@
     private final TraceBuffer mBuffer;
     private final LegacyProtoLogViewerConfigReader mViewerConfig;
     private final TreeMap<String, IProtoLogGroup> mLogGroups;
+    private final Runnable mCacheUpdater;
     private final int mPerChunkSize;
 
     private boolean mProtoLogEnabled;
@@ -73,20 +74,21 @@
     private final Object mProtoLogEnabledLock = new Object();
 
     public LegacyProtoLogImpl(String outputFile, String viewerConfigFilename,
-            TreeMap<String, IProtoLogGroup> logGroups) {
+            TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
         this(new File(outputFile), viewerConfigFilename, BUFFER_CAPACITY,
-                new LegacyProtoLogViewerConfigReader(), PER_CHUNK_SIZE, logGroups);
+                new LegacyProtoLogViewerConfigReader(), PER_CHUNK_SIZE, logGroups, cacheUpdater);
     }
 
     public LegacyProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity,
             LegacyProtoLogViewerConfigReader viewerConfig, int perChunkSize,
-            TreeMap<String, IProtoLogGroup> logGroups) {
+            TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
         mLogFile = file;
         mBuffer = new TraceBuffer(bufferCapacity);
         mLegacyViewerConfigFilename = viewerConfigFilename;
         mViewerConfig = viewerConfig;
         mPerChunkSize = perChunkSize;
-        this.mLogGroups = logGroups;
+        mLogGroups = logGroups;
+        mCacheUpdater = cacheUpdater;
     }
 
     /**
@@ -285,6 +287,8 @@
                 return -1;
             }
         }
+
+        mCacheUpdater.run();
         return 0;
     }
 
@@ -399,5 +403,12 @@
     public int stopLoggingToLogcat(String[] groups, ILogger logger) {
         return setLogging(true /* setTextLogging */, false, logger, groups);
     }
+
+    @Override
+    public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
+        // In legacy logging we just enable an entire group at a time without more granular control,
+        // so we ignore the level argument to this function.
+        return group.isLogToLogcat() || (group.isLogToProto() && isProtoEnabled());
+    }
 }
 
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 561ca21..b3e1df1 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -16,34 +16,34 @@
 
 package com.android.internal.protolog;
 
-import static android.internal.perfetto.protos.PerfettoTrace.InternedData.PROTOLOG_STACKTRACE;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedData.PROTOLOG_STRING_ARGS;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedString.IID;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedString.STR;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.BOOLEAN_PARAMS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.DOUBLE_PARAMS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.MESSAGE_ID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.SINT64_PARAMS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.STACKTRACE_IID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.STR_PARAM_IIDS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.GROUPS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.ID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.NAME;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.TAG;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MESSAGES;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.GROUP_ID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.LEVEL;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.INTERNED_DATA;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.PROTOLOG_MESSAGE;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.PROTOLOG_VIEWER_CONFIG;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.SEQUENCE_FLAGS;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.SEQ_INCREMENTAL_STATE_CLEARED;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.SEQ_NEEDS_INCREMENTAL_STATE;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.TIMESTAMP;
+import static android.internal.perfetto.protos.InternedDataOuterClass.InternedData.PROTOLOG_STACKTRACE;
+import static android.internal.perfetto.protos.InternedDataOuterClass.InternedData.PROTOLOG_STRING_ARGS;
+import static android.internal.perfetto.protos.ProfileCommon.InternedString.IID;
+import static android.internal.perfetto.protos.ProfileCommon.InternedString.STR;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.BOOLEAN_PARAMS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.DOUBLE_PARAMS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.MESSAGE_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.SINT64_PARAMS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.STACKTRACE_IID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.STR_PARAM_IIDS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.GROUPS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.NAME;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.TAG;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.GROUP_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LEVEL;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.INTERNED_DATA;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_MESSAGE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_VIEWER_CONFIG;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.SEQUENCE_FLAGS;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.SEQ_INCREMENTAL_STATE_CLEARED;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.SEQ_NEEDS_INCREMENTAL_STATE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.TIMESTAMP;
 
 import android.annotation.Nullable;
-import android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData;
+import android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData;
 import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -52,6 +52,8 @@
 import android.tracing.perfetto.InitArguments;
 import android.tracing.perfetto.Producer;
 import android.tracing.perfetto.TracingContext;
+import android.util.ArrayMap;
+import android.util.Log;
 import android.util.LongArray;
 import android.util.Slog;
 import android.util.proto.ProtoInputStream;
@@ -66,10 +68,12 @@
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -83,18 +87,22 @@
     private final AtomicInteger mTracingInstances = new AtomicInteger();
 
     private final ProtoLogDataSource mDataSource = new ProtoLogDataSource(
-            this.mTracingInstances::incrementAndGet,
+            this::onTracingInstanceStart,
             this::dumpTransitionTraceConfig,
-            this.mTracingInstances::decrementAndGet
+            this::onTracingInstanceStop
     );
     private final ProtoLogViewerConfigReader mViewerConfigReader;
     private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
     private final TreeMap<String, IProtoLogGroup> mLogGroups;
+    private final Runnable mCacheUpdater;
+
+    private final Map<LogLevel, Integer> mDefaultLogLevelCounts = new ArrayMap<>();
+    private final Map<IProtoLogGroup, Map<LogLevel, Integer>> mLogLevelCounts = new ArrayMap<>();
 
     private final ExecutorService mBackgroundLoggingService = Executors.newCachedThreadPool();
 
     public PerfettoProtoLogImpl(String viewerConfigFilePath,
-            TreeMap<String, IProtoLogGroup> logGroups) {
+            TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
         this(() -> {
             try {
                 return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
@@ -102,28 +110,32 @@
                 Slog.w(LOG_TAG, "Failed to load viewer config file " + viewerConfigFilePath, e);
                 return null;
             }
-        }, logGroups);
+        }, logGroups, cacheUpdater);
     }
 
     public PerfettoProtoLogImpl(
             ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
-            TreeMap<String, IProtoLogGroup> logGroups
+            TreeMap<String, IProtoLogGroup> logGroups,
+            Runnable cacheUpdater
     ) {
         this(viewerConfigInputStreamProvider,
-                new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider), logGroups);
+                new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider), logGroups,
+                cacheUpdater);
     }
 
     @VisibleForTesting
     public PerfettoProtoLogImpl(
             ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
             ProtoLogViewerConfigReader viewerConfigReader,
-            TreeMap<String, IProtoLogGroup> logGroups
+            TreeMap<String, IProtoLogGroup> logGroups,
+            Runnable cacheUpdater
     ) {
         Producer.init(InitArguments.DEFAULTS);
         mDataSource.register(DataSourceParams.DEFAULTS);
         this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
         this.mViewerConfigReader = viewerConfigReader;
         this.mLogGroups = logGroups;
+        this.mCacheUpdater = cacheUpdater;
     }
 
     /**
@@ -156,78 +168,92 @@
         }
 
         mDataSource.trace(ctx -> {
-            final ProtoOutputStream os = ctx.newTracePacket();
+            try {
+                final ProtoOutputStream os = ctx.newTracePacket();
 
-            os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
+                os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
 
-            final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
-            while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                if (pis.getFieldNumber() == (int) MESSAGES) {
-                    final long inMessageToken = pis.start(MESSAGES);
-                    final long outMessagesToken = os.start(MESSAGES);
-
-                    while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                        switch (pis.getFieldNumber()) {
-                            case (int) MessageData.MESSAGE_ID:
-                                os.write(MessageData.MESSAGE_ID,
-                                        pis.readLong(MessageData.MESSAGE_ID));
-                                break;
-                            case (int) MESSAGE:
-                                os.write(MESSAGE, pis.readString(MESSAGE));
-                                break;
-                            case (int) LEVEL:
-                                os.write(LEVEL, pis.readInt(LEVEL));
-                                break;
-                            case (int) GROUP_ID:
-                                os.write(GROUP_ID, pis.readInt(GROUP_ID));
-                                break;
-                            default:
-                                throw new RuntimeException(
-                                        "Unexpected field id " + pis.getFieldNumber());
-                        }
+                final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
+                while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                    if (pis.getFieldNumber() == (int) MESSAGES) {
+                        writeViewerConfigMessage(pis, os);
                     }
 
-                    pis.end(inMessageToken);
-                    os.end(outMessagesToken);
-                }
-
-                if (pis.getFieldNumber() == (int) GROUPS) {
-                    final long inGroupToken = pis.start(GROUPS);
-                    final long outGroupToken = os.start(GROUPS);
-
-                    while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                        switch (pis.getFieldNumber()) {
-                            case (int) ID:
-                                int id = pis.readInt(ID);
-                                os.write(ID, id);
-                                break;
-                            case (int) NAME:
-                                String name = pis.readString(NAME);
-                                os.write(NAME, name);
-                                break;
-                            case (int) TAG:
-                                String tag = pis.readString(TAG);
-                                os.write(TAG, tag);
-                                break;
-                            default:
-                                throw new RuntimeException(
-                                        "Unexpected field id " + pis.getFieldNumber());
-                        }
+                    if (pis.getFieldNumber() == (int) GROUPS) {
+                        writeViewerConfigGroup(pis, os);
                     }
-
-                    pis.end(inGroupToken);
-                    os.end(outGroupToken);
                 }
+
+                os.end(outProtologViewerConfigToken);
+
+                ctx.flush();
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
             }
-
-            os.end(outProtologViewerConfigToken);
-
-            ctx.flush();
         });
 
         mDataSource.flush();
     }
 
+    private static void writeViewerConfigGroup(
+            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
+        final long inGroupToken = pis.start(GROUPS);
+        final long outGroupToken = os.start(GROUPS);
+
+        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (pis.getFieldNumber()) {
+                case (int) ID:
+                    int id = pis.readInt(ID);
+                    os.write(ID, id);
+                    break;
+                case (int) NAME:
+                    String name = pis.readString(NAME);
+                    os.write(NAME, name);
+                    break;
+                case (int) TAG:
+                    String tag = pis.readString(TAG);
+                    os.write(TAG, tag);
+                    break;
+                default:
+                    throw new RuntimeException(
+                            "Unexpected field id " + pis.getFieldNumber());
+            }
+        }
+
+        pis.end(inGroupToken);
+        os.end(outGroupToken);
+    }
+
+    private static void writeViewerConfigMessage(
+            ProtoInputStream pis, ProtoOutputStream os) throws IOException {
+        final long inMessageToken = pis.start(MESSAGES);
+        final long outMessagesToken = os.start(MESSAGES);
+
+        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (pis.getFieldNumber()) {
+                case (int) MessageData.MESSAGE_ID:
+                    os.write(MessageData.MESSAGE_ID,
+                            pis.readLong(MessageData.MESSAGE_ID));
+                    break;
+                case (int) MESSAGE:
+                    os.write(MESSAGE, pis.readString(MESSAGE));
+                    break;
+                case (int) LEVEL:
+                    os.write(LEVEL, pis.readInt(LEVEL));
+                    break;
+                case (int) GROUP_ID:
+                    os.write(GROUP_ID, pis.readInt(GROUP_ID));
+                    break;
+                default:
+                    throw new RuntimeException(
+                            "Unexpected field id " + pis.getFieldNumber());
+            }
+        }
+
+        pis.end(inMessageToken);
+        os.end(outMessagesToken);
+    }
+
     private void logToLogcat(String tag, LogLevel level, long messageHash,
             @Nullable String messageString, Object[] args) {
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "logToLogcat");
@@ -413,7 +439,8 @@
         return sw.toString();
     }
 
-    private int internStacktraceString(TracingContext<ProtoLogDataSource.Instance,
+    private int internStacktraceString(TracingContext<
+            ProtoLogDataSource.Instance,
             ProtoLogDataSource.TlsState,
             ProtoLogDataSource.IncrementalState> ctx,
             String stacktrace) {
@@ -423,9 +450,8 @@
     }
 
     private int internStringArg(
-            TracingContext<ProtoLogDataSource.Instance,
-            ProtoLogDataSource.TlsState,
-            ProtoLogDataSource.IncrementalState> ctx,
+            TracingContext<ProtoLogDataSource.Instance, ProtoLogDataSource.TlsState,
+                    ProtoLogDataSource.IncrementalState> ctx,
             String string
     ) {
         final ProtoLogDataSource.IncrementalState incrementalState = ctx.getIncrementalState();
@@ -434,9 +460,8 @@
     }
 
     private int internString(
-            TracingContext<ProtoLogDataSource.Instance,
-                ProtoLogDataSource.TlsState,
-                ProtoLogDataSource.IncrementalState> ctx,
+            TracingContext<ProtoLogDataSource.Instance, ProtoLogDataSource.TlsState,
+                    ProtoLogDataSource.IncrementalState> ctx,
             Map<String, Integer> internMap,
             long fieldId,
             String string
@@ -494,6 +519,29 @@
         return setTextLogging(false, logger, groups);
     }
 
+    @Override
+    public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
+        return group.isLogToLogcat() || getLogFromLevel(group).ordinal() <= level.ordinal();
+    }
+
+    private LogLevel getLogFromLevel(IProtoLogGroup group) {
+        if (mLogLevelCounts.containsKey(group)) {
+            for (LogLevel logLevel : LogLevel.values()) {
+                if (mLogLevelCounts.get(group).getOrDefault(logLevel, 0) > 0) {
+                    return logLevel;
+                }
+            }
+        } else {
+            for (LogLevel logLevel : LogLevel.values()) {
+                if (mDefaultLogLevelCounts.getOrDefault(logLevel, 0) > 0) {
+                    return logLevel;
+                }
+            }
+        }
+
+        return LogLevel.WTF;
+    }
+
     /**
      * Start logging the stack trace of the when the log message happened for target groups
      * @return status code
@@ -521,6 +569,8 @@
                 return -1;
             }
         }
+
+        mCacheUpdater.run();
         return 0;
     }
 
@@ -567,6 +617,61 @@
         return -1;
     }
 
+    private synchronized void onTracingInstanceStart(ProtoLogDataSource.ProtoLogConfig config) {
+        this.mTracingInstances.incrementAndGet();
+
+        final LogLevel defaultLogFrom = config.getDefaultGroupConfig().logFrom;
+        mDefaultLogLevelCounts.put(defaultLogFrom,
+                mDefaultLogLevelCounts.getOrDefault(defaultLogFrom, 0) + 1);
+
+        final Set<String> overriddenGroupTags = config.getGroupTagsWithOverriddenConfigs();
+
+        for (String overriddenGroupTag : overriddenGroupTags) {
+            IProtoLogGroup group = mLogGroups.get(overriddenGroupTag);
+
+            mLogLevelCounts.putIfAbsent(group, new ArrayMap<>());
+            final Map<LogLevel, Integer> logLevelsCountsForGroup = mLogLevelCounts.get(group);
+
+            final LogLevel logFromLevel = config.getConfigFor(overriddenGroupTag).logFrom;
+            logLevelsCountsForGroup.put(logFromLevel,
+                    logLevelsCountsForGroup.getOrDefault(logFromLevel, 0) + 1);
+        }
+
+        mCacheUpdater.run();
+    }
+
+    private synchronized void onTracingInstanceStop(ProtoLogDataSource.ProtoLogConfig config) {
+        this.mTracingInstances.decrementAndGet();
+
+        final LogLevel defaultLogFrom = config.getDefaultGroupConfig().logFrom;
+        mDefaultLogLevelCounts.put(defaultLogFrom,
+                mDefaultLogLevelCounts.get(defaultLogFrom) - 1);
+        if (mDefaultLogLevelCounts.get(defaultLogFrom) <= 0) {
+            mDefaultLogLevelCounts.remove(defaultLogFrom);
+        }
+
+        final Set<String> overriddenGroupTags = config.getGroupTagsWithOverriddenConfigs();
+
+        for (String overriddenGroupTag : overriddenGroupTags) {
+            IProtoLogGroup group = mLogGroups.get(overriddenGroupTag);
+
+            mLogLevelCounts.putIfAbsent(group, new ArrayMap<>());
+            final Map<LogLevel, Integer> logLevelsCountsForGroup = mLogLevelCounts.get(group);
+
+            final LogLevel logFromLevel = config.getConfigFor(overriddenGroupTag).logFrom;
+            logLevelsCountsForGroup.put(logFromLevel,
+                    logLevelsCountsForGroup.get(logFromLevel) - 1);
+            if (logLevelsCountsForGroup.get(logFromLevel) <= 0) {
+                logLevelsCountsForGroup.remove(logFromLevel);
+            }
+            if (logLevelsCountsForGroup.isEmpty()) {
+                mLogLevelCounts.remove(group);
+            }
+        }
+
+        mCacheUpdater.run();
+    }
+
     static void logAndPrintln(@Nullable PrintWriter pw, String msg) {
         Slog.i(LOG_TAG, msg);
         if (pw != null) {
diff --git a/core/java/com/android/internal/protolog/ProtoLogDataSource.java b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
index a2d5e70..6ab79b9 100644
--- a/core/java/com/android/internal/protolog/ProtoLogDataSource.java
+++ b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
@@ -16,14 +16,16 @@
 
 package com.android.internal.protolog;
 
-import static android.internal.perfetto.protos.PerfettoTrace.DataSourceConfig.PROTOLOG_CONFIG;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogConfig.GROUP_OVERRIDES;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogConfig.TRACING_MODE;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogGroup.COLLECT_STACKTRACE;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogGroup.GROUP_NAME;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogGroup.LOG_FROM;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.DEFAULT;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.ENABLE_ALL;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.GROUP_OVERRIDES;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.TRACING_MODE;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.COLLECT_STACKTRACE;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.GROUP_NAME;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.LOG_FROM;
 
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
+import android.internal.perfetto.protos.ProtologCommon;
 import android.tracing.perfetto.CreateIncrementalStateArgs;
 import android.tracing.perfetto.CreateTlsStateArgs;
 import android.tracing.perfetto.DataSource;
@@ -39,16 +41,19 @@
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
 
 public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
         ProtoLogDataSource.TlsState,
         ProtoLogDataSource.IncrementalState> {
 
-    private final Runnable mOnStart;
+    private final Consumer<ProtoLogConfig> mOnStart;
     private final Runnable mOnFlush;
-    private final Runnable mOnStop;
+    private final Consumer<ProtoLogConfig> mOnStop;
 
-    public ProtoLogDataSource(Runnable onStart, Runnable onFlush, Runnable onStop) {
+    public ProtoLogDataSource(Consumer<ProtoLogConfig> onStart, Runnable onFlush,
+            Consumer<ProtoLogConfig> onStop) {
         super("android.protolog");
         this.mOnStart = onStart;
         this.mOnFlush = onFlush;
@@ -62,7 +67,7 @@
         try {
             while (configStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                 try {
-                    if (configStream.getFieldNumber() == (int) PROTOLOG_CONFIG) {
+                    if (configStream.getFieldNumber() == (int) DataSourceConfig.PROTOLOG_CONFIG) {
                         if (config != null) {
                             throw new RuntimeException("ProtoLog config already set in loop");
                         }
@@ -138,7 +143,7 @@
         public boolean clearReported = false;
     }
 
-    private static class ProtoLogConfig {
+    public static class ProtoLogConfig {
         private final LogLevel mDefaultLogFromLevel;
         private final Map<String, GroupConfig> mGroupConfigs;
 
@@ -151,13 +156,17 @@
             this.mGroupConfigs = groupConfigs;
         }
 
-        private GroupConfig getConfigFor(String groupTag) {
+        public GroupConfig getConfigFor(String groupTag) {
             return mGroupConfigs.getOrDefault(groupTag, getDefaultGroupConfig());
         }
 
-        private GroupConfig getDefaultGroupConfig() {
+        public GroupConfig getDefaultGroupConfig() {
             return new GroupConfig(mDefaultLogFromLevel, false);
         }
+
+        public Set<String> getGroupTagsWithOverriddenConfigs() {
+            return mGroupConfigs.keySet();
+        }
     }
 
     public static class GroupConfig {
@@ -172,7 +181,7 @@
 
     private ProtoLogConfig readProtoLogConfig(ProtoInputStream configStream)
             throws IOException {
-        final long config_token = configStream.start(PROTOLOG_CONFIG);
+        final long config_token = configStream.start(DataSourceConfig.PROTOLOG_CONFIG);
 
         LogLevel defaultLogFromLevel = LogLevel.WTF;
         final Map<String, GroupConfig> groupConfigs = new HashMap<>();
@@ -181,9 +190,9 @@
             if (configStream.getFieldNumber() == (int) TRACING_MODE) {
                 int tracingMode = configStream.readInt(TRACING_MODE);
                 switch (tracingMode) {
-                    case PerfettoTrace.ProtoLogConfig.DEFAULT:
+                    case DEFAULT:
                         break;
-                    case PerfettoTrace.ProtoLogConfig.ENABLE_ALL:
+                    case ENABLE_ALL:
                         defaultLogFromLevel = LogLevel.DEBUG;
                         break;
                     default:
@@ -203,27 +212,27 @@
                     if (configStream.getFieldNumber() == (int) LOG_FROM) {
                         final int logFromInt = configStream.readInt(LOG_FROM);
                         switch (logFromInt) {
-                            case (PerfettoTrace.PROTOLOG_LEVEL_DEBUG): {
+                            case (ProtologCommon.PROTOLOG_LEVEL_DEBUG): {
                                 logFromLevel = LogLevel.DEBUG;
                                 break;
                             }
-                            case (PerfettoTrace.PROTOLOG_LEVEL_VERBOSE): {
+                            case (ProtologCommon.PROTOLOG_LEVEL_VERBOSE): {
                                 logFromLevel = LogLevel.VERBOSE;
                                 break;
                             }
-                            case (PerfettoTrace.PROTOLOG_LEVEL_INFO): {
+                            case (ProtologCommon.PROTOLOG_LEVEL_INFO): {
                                 logFromLevel = LogLevel.INFO;
                                 break;
                             }
-                            case (PerfettoTrace.PROTOLOG_LEVEL_WARN): {
+                            case (ProtologCommon.PROTOLOG_LEVEL_WARN): {
                                 logFromLevel = LogLevel.WARN;
                                 break;
                             }
-                            case (PerfettoTrace.PROTOLOG_LEVEL_ERROR): {
+                            case (ProtologCommon.PROTOLOG_LEVEL_ERROR): {
                                 logFromLevel = LogLevel.ERROR;
                                 break;
                             }
-                            case (PerfettoTrace.PROTOLOG_LEVEL_WTF): {
+                            case (ProtologCommon.PROTOLOG_LEVEL_WTF): {
                                 logFromLevel = LogLevel.WTF;
                                 break;
                             }
@@ -255,18 +264,18 @@
 
     public static class Instance extends DataSourceInstance {
 
-        private final Runnable mOnStart;
+        private final Consumer<ProtoLogConfig> mOnStart;
         private final Runnable mOnFlush;
-        private final Runnable mOnStop;
+        private final Consumer<ProtoLogConfig> mOnStop;
         private final ProtoLogConfig mConfig;
 
         public Instance(
                 DataSource<Instance, TlsState, IncrementalState> dataSource,
                 int instanceIdx,
                 ProtoLogConfig config,
-                Runnable onStart,
+                Consumer<ProtoLogConfig> onStart,
                 Runnable onFlush,
-                Runnable onStop
+                Consumer<ProtoLogConfig> onStop
         ) {
             super(dataSource, instanceIdx);
             this.mOnStart = onStart;
@@ -277,7 +286,7 @@
 
         @Override
         public void onStart(StartCallbackArguments args) {
-            this.mOnStart.run();
+            this.mOnStart.accept(this.mConfig);
         }
 
         @Override
@@ -287,7 +296,7 @@
 
         @Override
         public void onStop(StopCallbackArguments args) {
-            this.mOnStop.run();
+            this.mOnStop.accept(this.mConfig);
         }
     }
 }
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index 487ae814..6d142af 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.protolog;
 
+import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.CACHE_UPDATER;
 import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_OUTPUT_FILE_PATH;
 import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_VIEWER_CONFIG_PATH;
 import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LOG_GROUPS;
@@ -49,6 +50,9 @@
     @ProtoLogToolInjected(LOG_GROUPS)
     private static TreeMap<String, IProtoLogGroup> sLogGroups;
 
+    @ProtoLogToolInjected(CACHE_UPDATER)
+    private static Runnable sCacheUpdater;
+
     /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
     public static void d(IProtoLogGroup group, long messageHash, int paramsMask,
             @Nullable String messageString,
@@ -94,9 +98,12 @@
         getSingleInstance().log(LogLevel.WTF, group, messageHash, paramsMask, messageString, args);
     }
 
-    public static boolean isEnabled(IProtoLogGroup group) {
-        // TODO: Implement for performance reasons, with optional level parameter?
-        return true;
+    /**
+     * Should return true iff we should be logging to either protolog or logcat for this group
+     * and log level.
+     */
+    public static boolean isEnabled(IProtoLogGroup group, LogLevel level) {
+        return getSingleInstance().isEnabled(group, level);
     }
 
     /**
@@ -105,11 +112,14 @@
     public static synchronized IProtoLog getSingleInstance() {
         if (sServiceInstance == null) {
             if (android.tracing.Flags.perfettoProtologTracing()) {
-                sServiceInstance = new PerfettoProtoLogImpl(sViewerConfigPath, sLogGroups);
+                sServiceInstance = new PerfettoProtoLogImpl(
+                        sViewerConfigPath, sLogGroups, sCacheUpdater);
             } else {
                 sServiceInstance = new LegacyProtoLogImpl(
-                        sLegacyOutputFilePath, sLegacyViewerConfigPath, sLogGroups);
+                        sLegacyOutputFilePath, sLegacyViewerConfigPath, sLogGroups, sCacheUpdater);
             }
+
+            sCacheUpdater.run();
         }
         return sServiceInstance;
     }
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 88a7b54..b7b2424 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -1,8 +1,8 @@
 package com.android.internal.protolog;
 
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MESSAGES;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
 
 import android.util.ArrayMap;
 import android.util.proto.ProtoInputStream;
diff --git a/core/java/com/android/internal/protolog/common/IProtoLog.java b/core/java/com/android/internal/protolog/common/IProtoLog.java
index c06d14b..f72d9f7 100644
--- a/core/java/com/android/internal/protolog/common/IProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/IProtoLog.java
@@ -52,4 +52,12 @@
      * @return status code
      */
     int stopLoggingToLogcat(String[] groups, ILogger logger);
+
+    /**
+     * Should return true iff logging is enabled to ProtoLog or to Logcat for this group and level.
+     * @param group ProtoLog group to check for.
+     * @param level ProtoLog level to check for.
+     * @return If we need to log this group and level to either ProtoLog or Logcat.
+     */
+    boolean isEnabled(IProtoLogGroup group, LogLevel level);
 }
diff --git a/core/java/com/android/internal/protolog/common/IProtoLogGroup.java b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
index 4e9686f99..149aa7a 100644
--- a/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
@@ -38,6 +38,7 @@
 
     /**
      * returns true is any logging is enabled for this group.
+     * @deprecated TODO(b/324128613) remove once we migrate fully to Perfetto
      */
     default boolean isLogToAny() {
         return isLogToLogcat() || isLogToProto();
@@ -50,6 +51,7 @@
 
     /**
      * set binary logging for this group.
+     * @deprecated TODO(b/324128613) remove once we migrate fully to Perfetto
      */
     void setLogToProto(boolean logToProto);
 
diff --git a/core/java/com/android/internal/protolog/common/ProtoLog.java b/core/java/com/android/internal/protolog/common/ProtoLog.java
index 18e3f66..8149cd5 100644
--- a/core/java/com/android/internal/protolog/common/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/ProtoLog.java
@@ -135,7 +135,7 @@
      * @param group Group to check enable status of.
      * @return true iff this is being logged.
      */
-    public static boolean isEnabled(IProtoLogGroup group) {
+    public static boolean isEnabled(IProtoLogGroup group, LogLevel level) {
         if (REQUIRE_PROTOLOGTOOL) {
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
diff --git a/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java b/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java
index 17c82d7..2d39f3b 100644
--- a/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java
+++ b/core/java/com/android/internal/protolog/common/ProtoLogToolInjected.java
@@ -23,7 +23,11 @@
 @Target({ElementType.FIELD, ElementType.PARAMETER})
 public @interface ProtoLogToolInjected {
     enum Value {
-        VIEWER_CONFIG_PATH, LEGACY_OUTPUT_FILE_PATH, LEGACY_VIEWER_CONFIG_PATH, LOG_GROUPS
+        VIEWER_CONFIG_PATH,
+        LEGACY_OUTPUT_FILE_PATH,
+        LEGACY_VIEWER_CONFIG_PATH,
+        LOG_GROUPS,
+        CACHE_UPDATER
     }
 
     Value value();
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index f5b1a47..f931a76 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -28,6 +28,7 @@
 import android.media.MediaRoute2Info;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.view.KeyEvent;
 import android.service.notification.StatusBarNotification;
 
@@ -384,9 +385,11 @@
     /**
      * Shows the media output switcher dialog.
      *
-     * @param packageName of the session for which the output switcher is shown.
+     * @param targetPackageName The package name for which to show the output switcher.
+     * @param targetUserHandle The UserHandle on which the package for which to show the output
+     *     switcher is running.
      */
-    void showMediaOutputSwitcher(String packageName);
+    void showMediaOutputSwitcher(String targetPackageName, in UserHandle targetUserHandle);
 
     /** Enters desktop mode from the current focused app.
     *
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 969f95d..792c223 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -81,4 +81,5 @@
     void onCallBackModeStarted(int type);
     void onCallBackModeStopped(int type, int reason);
     void onSimultaneousCallingStateChanged(in int[] subIds);
+    void onCarrierRoamingNtnModeChanged(in boolean active);
 }
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0203ea4..04332cd 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -120,4 +120,5 @@
 
     void notifyCallbackModeStarted(int phoneId, int subId, int type);
     void notifyCallbackModeStopped(int phoneId, int subId, int type, int reason);
+    void notifyCarrierRoamingNtnModeChanged(int subId, in boolean active);
 }
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index cb1abf1..468705d 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -21,6 +21,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.text.ClientFlags;
 import android.text.TextFlags;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -290,7 +291,8 @@
     private void insertIconView() {
         LayoutInflater inflater = getInflater();
         mIconView = (ImageView) inflater.inflate(
-                mUseNewContextMenu ? com.android.internal.R.layout.list_menu_item_fixed_size_icon :
+                mUseNewContextMenu && !ClientFlags.fixMisalignedContextMenu()
+                        ? com.android.internal.R.layout.list_menu_item_fixed_size_icon :
                         com.android.internal.R.layout.list_menu_item_icon,
                 this, false);
         addContentView(mIconView, 0);
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 1979e4f..c254e99 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -16,24 +16,27 @@
 
 package com.android.internal.view.menu;
 
+import android.app.AppGlobals;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Parcelable;
+import android.text.ClientFlags;
+import android.text.TextFlags;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnKeyListener;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.widget.AdapterView.OnItemClickListener;
 import android.widget.FrameLayout;
 import android.widget.ListView;
 import android.widget.MenuPopupWindow;
 import android.widget.PopupWindow;
-import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
 import android.widget.PopupWindow.OnDismissListener;
+import android.widget.TextView;
 
 import java.util.Objects;
 
@@ -44,6 +47,8 @@
 final class StandardMenuPopup extends MenuPopup implements OnDismissListener, OnItemClickListener,
         MenuPresenter, OnKeyListener {
     private static final int ITEM_LAYOUT = com.android.internal.R.layout.popup_menu_item_layout;
+    private static final int ITEM_LAYOUT_MATERIAL =
+            com.android.internal.R.layout.popup_menu_item_layout_material;
 
     private final Context mContext;
 
@@ -53,6 +58,7 @@
     private final int mPopupMaxWidth;
     private final int mPopupStyleAttr;
     private final int mPopupStyleRes;
+
     // The popup window is final in order to couple its lifecycle to the lifecycle of the
     // StandardMenuPopup.
     private final MenuPopupWindow mPopup;
@@ -114,10 +120,16 @@
     public StandardMenuPopup(Context context, MenuBuilder menu, View anchorView, int popupStyleAttr,
             int popupStyleRes, boolean overflowOnly) {
         mContext = Objects.requireNonNull(context);
+        boolean useNewContextMenu = AppGlobals.getIntCoreSetting(
+                TextFlags.KEY_ENABLE_NEW_CONTEXT_MENU,
+                TextFlags.ENABLE_NEW_CONTEXT_MENU_DEFAULT ? 1 : 0) != 0;
+
         mMenu = menu;
         mOverflowOnly = overflowOnly;
         final LayoutInflater inflater = LayoutInflater.from(context);
-        mAdapter = new MenuAdapter(menu, inflater, mOverflowOnly, ITEM_LAYOUT);
+        mAdapter = new MenuAdapter(menu, inflater, mOverflowOnly,
+                ClientFlags.fixMisalignedContextMenu() && useNewContextMenu
+                        ? ITEM_LAYOUT_MATERIAL : ITEM_LAYOUT);
         mPopupStyleAttr = popupStyleAttr;
         mPopupStyleRes = popupStyleRes;
 
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index adbf645..0992db9 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -436,7 +436,7 @@
         // overlay.
         mContentInsets.set(mBaseContentInsets);
         mInnerInsets = mBaseInnerInsets;
-        if (!mOverlayMode && !stable) {
+        if (!mOverlayMode && !stable && hasContentOnApplyWindowInsetsListener()) {
             mContentInsets.top += topInset;
             mContentInsets.bottom += bottomInset;
             // Content view has been shrunk, shrink all insets to match.
diff --git a/core/java/com/android/internal/widget/BigPictureNotificationImageView.java b/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
index f95f5db..7e7aba2 100644
--- a/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
+++ b/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
@@ -26,6 +26,7 @@
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.widget.ImageView;
 import android.widget.RemoteViews;
 
@@ -126,11 +127,19 @@
 
     private Drawable loadImage(Icon icon) {
         if (icon == null) return null;
+
         Drawable drawable = LocalImageResolver.resolveImage(icon, mContext, mMaximumDrawableWidth,
                 mMaximumDrawableHeight);
-        if (drawable == null) {
-            return icon.loadDrawable(mContext);
+        if (drawable != null) {
+            return drawable;
         }
-        return drawable;
+
+        drawable = icon.loadDrawable(mContext);
+        if (drawable != null) {
+            return drawable;
+        }
+
+        Log.e(TAG, "Couldn't load drawable for icon: " + icon);
+        return null;
     }
 }
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 9c63d0d..bd654fa 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -1212,6 +1212,10 @@
                 }
             }
         }
+        if (android.app.Flags.cleanUpSpansAndNewLines() && conversationText != null) {
+            // remove formatting from title.
+            conversationText = conversationText.toString();
+        }
 
         if (conversationIcon == null) {
             conversationIcon = largeIcon;
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
deleted file mode 100644
index 362fd7b..0000000
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.view.Window;
-
-import com.android.internal.R;
-import com.android.internal.policy.DecorView;
-import com.android.internal.policy.PhoneWindow;
-
-import java.util.ArrayList;
-
-/**
- * This class represents the special screen elements to control a window on freeform
- * environment.
- * As such this class handles the following things:
- * <ul>
- * <li>The caption, containing the system buttons like maximize, close and such as well as
- * allowing the user to drag the window around.</li>
- * </ul>
- * After creating the view, the function {@link #setPhoneWindow} needs to be called to make
- * the connection to it's owning PhoneWindow.
- * Note: At this time the application can change various attributes of the DecorView which
- * will break things (in subtle/unexpected ways):
- * <ul>
- * <li>setOutlineProvider</li>
- * <li>setSurfaceFormat</li>
- * <li>..</li>
- * </ul>
- *
- * Here describe the behavior of overlaying caption on the content and drawing.
- *
- * First, no matter where the content View gets added, it will always be the first child and the
- * caption will be the second. This way the caption will always be drawn on top of the content when
- * overlaying is enabled.
- *
- * Second, the touch dispatch is customized to handle overlaying. This is what happens when touch
- * is dispatched on the caption area while overlaying it on content:
- * <ul>
- * <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
- * down action is performed on top close or maximize buttons; the reason for that is we want these
- * buttons to always work.</li>
- * <li>The caption view will try to consume the event to apply the dragging logic.</li>
- * <li>If the touch event is not consumed by the caption, the content View will receive the touch
- * event</li>
- * </ul>
- */
-public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
-        GestureDetector.OnGestureListener {
-    private PhoneWindow mOwner = null;
-    private boolean mShow = false;
-
-    // True if the window is being dragged.
-    private boolean mDragging = false;
-
-    private boolean mOverlayWithAppContent = false;
-
-    private View mCaption;
-    private View mContent;
-    private View mMaximize;
-    private View mClose;
-
-    // Fields for detecting drag events.
-    private int mTouchDownX;
-    private int mTouchDownY;
-    private boolean mCheckForDragging;
-    private int mDragSlop;
-
-    // Fields for detecting and intercepting click events on close/maximize.
-    private ArrayList<View> mTouchDispatchList = new ArrayList<>(2);
-    // We use the gesture detector to detect clicks on close/maximize buttons and to be consistent
-    // with existing click detection.
-    private GestureDetector mGestureDetector;
-    private final Rect mCloseRect = new Rect();
-    private final Rect mMaximizeRect = new Rect();
-    private View mClickTarget;
-    private int mRootScrollY;
-
-    public DecorCaptionView(Context context) {
-        super(context);
-        init(context);
-    }
-
-    public DecorCaptionView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init(context);
-    }
-
-    public DecorCaptionView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init(context);
-    }
-
-    private void init(Context context) {
-        mDragSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        mGestureDetector = new GestureDetector(context, this);
-        setContentDescription(context.getString(R.string.accessibility_freeform_caption,
-                context.getPackageManager().getApplicationLabel(context.getApplicationInfo())));
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mCaption = getChildAt(0);
-    }
-
-    public void setPhoneWindow(PhoneWindow owner, boolean show) {
-        mOwner = owner;
-        mShow = show;
-        mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled();
-        updateCaptionVisibility();
-        // By changing the outline provider to BOUNDS, the window can remove its
-        // background without removing the shadow.
-        mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
-        mMaximize = findViewById(R.id.maximize_window);
-        mClose = findViewById(R.id.close_window);
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        // If the user starts touch on the maximize/close buttons, we immediately intercept, so
-        // that these buttons are always clickable.
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            final int x = (int) ev.getX();
-            final int y = (int) ev.getY();
-            // Only offset y for containment tests because the actual views are already translated.
-            if (mMaximizeRect.contains(x, y - mRootScrollY)) {
-                mClickTarget = mMaximize;
-            }
-            if (mCloseRect.contains(x, y - mRootScrollY)) {
-                mClickTarget = mClose;
-            }
-        }
-        return mClickTarget != null;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (mClickTarget != null) {
-            mGestureDetector.onTouchEvent(event);
-            final int action = event.getAction();
-            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
-                mClickTarget = null;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onTouch(View v, MotionEvent e) {
-        // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch)
-        // the old input device events get cancelled first. So no need to remember the kind of
-        // input device we are listening to.
-        final int x = (int) e.getX();
-        final int y = (int) e.getY();
-        final boolean fromMouse = e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE;
-        final boolean primaryButton = (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0;
-        final int actionMasked = e.getActionMasked();
-        switch (actionMasked) {
-            case MotionEvent.ACTION_DOWN:
-                if (!mShow) {
-                    // When there is no caption we should not react to anything.
-                    return false;
-                }
-                // Checking for a drag action is started if we aren't dragging already and the
-                // starting event is either a left mouse button or any other input device.
-                if (!fromMouse || primaryButton) {
-                    mCheckForDragging = true;
-                    mTouchDownX = x;
-                    mTouchDownY = y;
-                }
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (!mDragging && mCheckForDragging && (fromMouse || passedSlop(x, y))) {
-                    mCheckForDragging = false;
-                    mDragging = true;
-                    startMovingTask(e.getRawX(), e.getRawY());
-                    // After the above call the framework will take over the input.
-                    // This handler will receive ACTION_CANCEL soon (possible after a few spurious
-                    // ACTION_MOVE events which are safe to ignore).
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                if (!mDragging) {
-                    break;
-                }
-                // Abort the ongoing dragging.
-                if (actionMasked == MotionEvent.ACTION_UP) {
-                    // If it receives ACTION_UP event, the dragging is already finished and also
-                    // the system can not end drag on ACTION_UP event. So request to finish
-                    // dragging.
-                    finishMovingTask();
-                }
-                mDragging = false;
-                return !mCheckForDragging;
-        }
-        return mDragging || mCheckForDragging;
-    }
-
-    @Override
-    public boolean shouldDelayChildPressedState() {
-        return false;
-    }
-
-    private boolean passedSlop(int x, int y) {
-        return Math.abs(x - mTouchDownX) > mDragSlop || Math.abs(y - mTouchDownY) > mDragSlop;
-    }
-
-    /**
-     * The phone window configuration has changed and the caption needs to be updated.
-     * @param show True if the caption should be shown.
-     */
-    public void onConfigurationChanged(boolean show) {
-        mShow = show;
-        updateCaptionVisibility();
-    }
-
-    @Override
-    public void addView(View child, int index, ViewGroup.LayoutParams params) {
-        if (!(params instanceof MarginLayoutParams)) {
-            throw new IllegalArgumentException(
-                    "params " + params + " must subclass MarginLayoutParams");
-        }
-        // Make sure that we never get more then one client area in our view.
-        if (index >= 2 || getChildCount() >= 2) {
-            throw new IllegalStateException("DecorCaptionView can only handle 1 client view");
-        }
-        // To support the overlaying content in the caption, we need to put the content view as the
-        // first child to get the right Z-Ordering.
-        super.addView(child, 0, params);
-        mContent = child;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int captionHeight;
-        if (mCaption.getVisibility() != View.GONE) {
-            measureChildWithMargins(mCaption, widthMeasureSpec, 0, heightMeasureSpec, 0);
-            captionHeight = mCaption.getMeasuredHeight();
-        } else {
-            captionHeight = 0;
-        }
-        if (mContent != null) {
-            if (mOverlayWithAppContent) {
-                measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec, 0);
-            } else {
-                measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec,
-                        captionHeight);
-            }
-        }
-
-        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
-                MeasureSpec.getSize(heightMeasureSpec));
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        final int captionHeight;
-        if (mCaption.getVisibility() != View.GONE) {
-            mCaption.layout(0, 0, mCaption.getMeasuredWidth(), mCaption.getMeasuredHeight());
-            captionHeight = mCaption.getBottom() - mCaption.getTop();
-            mMaximize.getHitRect(mMaximizeRect);
-            mClose.getHitRect(mCloseRect);
-        } else {
-            captionHeight = 0;
-            mMaximizeRect.setEmpty();
-            mCloseRect.setEmpty();
-        }
-
-        if (mContent != null) {
-            if (mOverlayWithAppContent) {
-                mContent.layout(0, 0, mContent.getMeasuredWidth(), mContent.getMeasuredHeight());
-            } else {
-                mContent.layout(0, captionHeight, mContent.getMeasuredWidth(),
-                        captionHeight + mContent.getMeasuredHeight());
-            }
-        }
-
-        ((DecorView) mOwner.getDecorView()).notifyCaptionHeightChanged();
-
-        // This assumes that the caption bar is at the top.
-        mOwner.notifyRestrictedCaptionAreaCallback(mMaximize.getLeft(), mMaximize.getTop(),
-                mClose.getRight(), mClose.getBottom());
-    }
-
-    /**
-     * Updates the visibility of the caption.
-     **/
-    private void updateCaptionVisibility() {
-        mCaption.setVisibility(mShow ? VISIBLE : GONE);
-        mCaption.setOnTouchListener(this);
-    }
-
-    /**
-     * Maximize or restore the window by moving it to the maximized or freeform workspace stack.
-     **/
-    private void toggleFreeformWindowingMode() {
-        Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
-        if (callback != null) {
-            callback.toggleFreeformWindowingMode();
-        }
-    }
-
-    public boolean isCaptionShowing() {
-        return mShow;
-    }
-
-    public int getCaptionHeight() {
-        return (mCaption != null) ? mCaption.getHeight() : 0;
-    }
-
-    public void removeContentView() {
-        if (mContent != null) {
-            removeView(mContent);
-            mContent = null;
-        }
-    }
-
-    public View getCaption() {
-        return mCaption;
-    }
-
-    @Override
-    public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new MarginLayoutParams(getContext(), attrs);
-    }
-
-    @Override
-    protected LayoutParams generateDefaultLayoutParams() {
-        return new MarginLayoutParams(MarginLayoutParams.MATCH_PARENT,
-                MarginLayoutParams.MATCH_PARENT);
-    }
-
-    @Override
-    protected LayoutParams generateLayoutParams(LayoutParams p) {
-        return new MarginLayoutParams(p);
-    }
-
-    @Override
-    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
-        return p instanceof MarginLayoutParams;
-    }
-
-    @Override
-    public boolean onDown(MotionEvent e) {
-        return false;
-    }
-
-    @Override
-    public void onShowPress(MotionEvent e) {
-
-    }
-
-    @Override
-    public boolean onSingleTapUp(MotionEvent e) {
-        if (mClickTarget == mMaximize) {
-            toggleFreeformWindowingMode();
-        } else if (mClickTarget == mClose) {
-            mOwner.dispatchOnWindowDismissed(
-                    true /*finishTask*/, false /*suppressWindowTransition*/);
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-        return false;
-    }
-
-    @Override
-    public void onLongPress(MotionEvent e) {
-
-    }
-
-    @Override
-    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-        return false;
-    }
-
-    /**
-     * Called when {@link android.view.ViewRootImpl} scrolls for adjustPan.
-     */
-    public void onRootViewScrollYChanged(int scrollY) {
-        // Offset the caption opposite the root scroll. This keeps the caption at the
-        // top of the window during adjustPan.
-        if (mCaption != null) {
-            mRootScrollY = scrollY;
-            mCaption.setTranslationY(scrollY);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index 9ef7ce38..c5d74fc 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -132,7 +132,11 @@
 
         // Fallback to straight drawable load if we fail with more efficient approach.
         try {
-            return icon.loadDrawable(context);
+            final Drawable iconDrawable = icon.loadDrawable(context);
+            if (iconDrawable == null) {
+                Log.w(TAG, "Couldn't load drawable for icon: " + icon);
+            }
+            return iconDrawable;
         } catch (Resources.NotFoundException e) {
             return null;
         }
@@ -233,8 +237,7 @@
             });
 
         // ImageDecoder documentation is misleading a bit - it'll throw NotFoundException
-        // in some cases despite it not saying so. Rethrow it as an IOException to keep
-        // our API contract.
+        // in some cases despite it not saying so.
         } catch (IOException | Resources.NotFoundException e) {
             Log.d(TAG, "Couldn't use ImageDecoder for drawable, falling back to non-resized load.");
             return null;
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index f8f1049..97a2d3b 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.app.Flags;
 import android.app.Person;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -200,6 +201,10 @@
         if (nameOverride == null) {
             nameOverride = sender.getName();
         }
+        if (Flags.cleanUpSpansAndNewLines() && nameOverride != null) {
+            // remove formatting from sender name
+            nameOverride = nameOverride.toString();
+        }
         mSenderName = nameOverride;
         if (mSingleLine && !TextUtils.isEmpty(nameOverride)) {
             nameOverride = mContext.getResources().getString(
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 03b57d0..80a7599 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -21,6 +21,7 @@
     config_namespace: "ANDROID",
     bool_variables: [
         "release_binder_death_recipient_weak_from_jni",
+        "release_package_libandroid_runtime_punch_holes",
     ],
     properties: [
         "cflags",
@@ -63,6 +64,9 @@
         release_binder_death_recipient_weak_from_jni: {
             cflags: ["-DBINDER_DEATH_RECIPIENT_WEAK_FROM_JNI"],
         },
+        release_package_libandroid_runtime_punch_holes: {
+            cflags: ["-DENABLE_PUNCH_HOLES"],
+        },
     },
 
     cpp_std: "gnu++20",
@@ -78,6 +82,14 @@
         "android_util_StringBlock.cpp",
         "android_util_XmlBlock.cpp",
         "android_util_jar_StrictJarFile.cpp",
+        "android_view_InputDevice.cpp",
+        "android_view_KeyCharacterMap.cpp",
+        "android_view_KeyEvent.cpp",
+        "android_view_MotionEvent.cpp",
+        "android_view_Surface.cpp",
+        "android_view_VelocityTracker.cpp",
+        "android_view_VerifiedKeyEvent.cpp",
+        "android_view_VerifiedMotionEvent.cpp",
         "com_android_internal_util_VirtualRefBasePtr.cpp",
         "core_jni_helpers.cpp",
         ":deviceproductinfoconstants_aidl",
@@ -123,6 +135,7 @@
             srcs: [
                 "AndroidRuntime.cpp",
                 "com_android_internal_content_F2fsUtils.cpp",
+                "com_android_internal_content_FileSystemUtils.cpp",
                 "com_android_internal_content_NativeLibraryHelper.cpp",
                 "com_google_android_gles_jni_EGLImpl.cpp",
                 "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
@@ -153,16 +166,11 @@
                 "android_view_CompositionSamplingListener.cpp",
                 "android_view_DisplayEventReceiver.cpp",
                 "android_view_InputChannel.cpp",
-                "android_view_InputDevice.cpp",
                 "android_view_InputEventReceiver.cpp",
                 "android_view_InputEventSender.cpp",
                 "android_view_InputQueue.cpp",
-                "android_view_KeyCharacterMap.cpp",
-                "android_view_KeyEvent.cpp",
-                "android_view_MotionEvent.cpp",
                 "android_view_MotionPredictor.cpp",
                 "android_view_PointerIcon.cpp",
-                "android_view_Surface.cpp",
                 "android_view_SurfaceControl.cpp",
                 "android_view_SurfaceControlHdrLayerInfoListener.cpp",
                 "android_view_WindowManagerGlobal.cpp",
@@ -170,9 +178,6 @@
                 "android_view_SurfaceSession.cpp",
                 "android_view_TextureView.cpp",
                 "android_view_TunnelModeEnabledListener.cpp",
-                "android_view_VelocityTracker.cpp",
-                "android_view_VerifiedKeyEvent.cpp",
-                "android_view_VerifiedMotionEvent.cpp",
                 "android_text_Hyphenator.cpp",
                 "android_os_Debug.cpp",
                 "android_os_GraphicsEnvironment.cpp",
@@ -389,7 +394,8 @@
                 "-Wno-unused-function",
             ],
             srcs: [
-                "LayoutlibLoader.cpp",
+                "platform/host/HostRuntime.cpp",
+                "platform/host/native_window_jni.cpp",
             ],
             include_dirs: [
                 "external/vulkan-headers/include",
@@ -409,6 +415,7 @@
                 "libhostgraphics",
                 "libhwui",
                 "libimage_type_recognition",
+                "libinput",
                 "libjpeg",
                 "libpiex",
                 "libpng",
@@ -436,16 +443,9 @@
                 "android_os_MessageQueue.cpp",
                 "android_os_Parcel.cpp",
 
-                "android_view_KeyCharacterMap.cpp",
-                "android_view_KeyEvent.cpp",
                 "android_view_InputChannel.cpp",
-                "android_view_InputDevice.cpp",
                 "android_view_InputEventReceiver.cpp",
                 "android_view_InputEventSender.cpp",
-                "android_view_MotionEvent.cpp",
-                "android_view_VelocityTracker.cpp",
-                "android_view_VerifiedKeyEvent.cpp",
-                "android_view_VerifiedMotionEvent.cpp",
 
                 "android_util_AssetManager.cpp",
                 "android_util_Binder.cpp",
@@ -453,7 +453,6 @@
                 "android_util_FileObserver.cpp",
             ],
             static_libs: [
-                "libinput",
                 "libbinderthreadstateutils",
                 "libsqlite",
                 "libgui_window_info_static",
diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp
deleted file mode 100644
index 83b6afa..0000000
--- a/core/jni/LayoutlibLoader.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android/graphics/jni_runtime.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/jni_macros.h>
-#include <unicode/putil.h>
-#include <unicode/udata.h>
-
-#include <clocale>
-#include <sstream>
-#include <unordered_map>
-#include <vector>
-
-#include "android_view_InputDevice.h"
-#include "core_jni_helpers.h"
-#include "jni.h"
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#endif
-
-#include <iostream>
-
-using namespace std;
-
-/*
- * This is responsible for setting up the JNI environment for communication between
- * the Java and native parts of layoutlib, including registering native methods.
- * This is mostly achieved by copying the way it is done in the platform
- * (see AndroidRuntime.cpp).
- */
-
-static JavaVM* javaVM;
-static jclass bridge;
-static jclass layoutLog;
-static jmethodID getLogId;
-static jmethodID logMethodId;
-
-extern int register_android_os_Binder(JNIEnv* env);
-extern int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env);
-
-typedef void (*FreeFunction)(void*);
-
-static void NativeAllocationRegistry_Delegate_nativeApplyFreeFunction(JNIEnv*, jclass,
-                                                                      jlong freeFunction,
-                                                                      jlong ptr) {
-    void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
-    FreeFunction nativeFreeFunction =
-            reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
-    nativeFreeFunction(nativePtr);
-}
-
-static JNINativeMethod gMethods[] = {
-        NATIVE_METHOD(NativeAllocationRegistry_Delegate, nativeApplyFreeFunction, "(JJ)V"),
-};
-
-int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "libcore/util/NativeAllocationRegistry_Delegate", gMethods,
-                                    NELEM(gMethods));
-}
-
-namespace android {
-
-extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
-extern int register_android_content_AssetManager(JNIEnv* env);
-extern int register_android_content_StringBlock(JNIEnv* env);
-extern int register_android_content_XmlBlock(JNIEnv* env);
-extern int register_android_content_res_ApkAssets(JNIEnv* env);
-extern int register_android_database_CursorWindow(JNIEnv* env);
-extern int register_android_database_SQLiteConnection(JNIEnv* env);
-extern int register_android_database_SQLiteGlobal(JNIEnv* env);
-extern int register_android_database_SQLiteDebug(JNIEnv* env);
-extern int register_android_os_FileObserver(JNIEnv* env);
-extern int register_android_os_MessageQueue(JNIEnv* env);
-extern int register_android_os_Parcel(JNIEnv* env);
-extern int register_android_os_SystemClock(JNIEnv* env);
-extern int register_android_os_SystemProperties(JNIEnv* env);
-extern int register_android_os_Trace(JNIEnv* env);
-extern int register_android_text_AndroidCharacter(JNIEnv* env);
-extern int register_android_util_EventLog(JNIEnv* env);
-extern int register_android_util_Log(JNIEnv* env);
-extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
-extern int register_android_view_KeyCharacterMap(JNIEnv* env);
-extern int register_android_view_KeyEvent(JNIEnv* env);
-extern int register_android_view_InputDevice(JNIEnv* env);
-extern int register_android_view_MotionEvent(JNIEnv* env);
-extern int register_android_view_ThreadedRenderer(JNIEnv* env);
-extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env);
-extern int register_android_view_VelocityTracker(JNIEnv* env);
-extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
-
-#define REG_JNI(name)      { name }
-struct RegJNIRec {
-    int (*mProc)(JNIEnv*);
-};
-
-// Map of all possible class names to register to their corresponding JNI registration function pointer
-// The actual list of registered classes will be determined at runtime via the 'native_classes' System property
-static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = {
-        {"android.animation.PropertyValuesHolder",
-         REG_JNI(register_android_animation_PropertyValuesHolder)},
-#ifdef __linux__
-        {"android.content.res.ApkAssets", REG_JNI(register_android_content_res_ApkAssets)},
-        {"android.content.res.AssetManager", REG_JNI(register_android_content_AssetManager)},
-        {"android.database.CursorWindow", REG_JNI(register_android_database_CursorWindow)},
-        {"android.database.sqlite.SQLiteConnection",
-         REG_JNI(register_android_database_SQLiteConnection)},
-        {"android.database.sqlite.SQLiteGlobal", REG_JNI(register_android_database_SQLiteGlobal)},
-        {"android.database.sqlite.SQLiteDebug", REG_JNI(register_android_database_SQLiteDebug)},
-#endif
-        {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)},
-        {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)},
-#ifdef __linux__
-        {"android.os.Binder", REG_JNI(register_android_os_Binder)},
-        {"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)},
-        {"android.os.MessageQueue", REG_JNI(register_android_os_MessageQueue)},
-        {"android.os.Parcel", REG_JNI(register_android_os_Parcel)},
-#endif
-        {"android.os.SystemClock", REG_JNI(register_android_os_SystemClock)},
-        {"android.os.SystemProperties", REG_JNI(register_android_os_SystemProperties)},
-        {"android.os.Trace", REG_JNI(register_android_os_Trace)},
-        {"android.text.AndroidCharacter", REG_JNI(register_android_text_AndroidCharacter)},
-        {"android.util.EventLog", REG_JNI(register_android_util_EventLog)},
-        {"android.util.Log", REG_JNI(register_android_util_Log)},
-        {"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)},
-        {"android.view.KeyCharacterMap", REG_JNI(register_android_view_KeyCharacterMap)},
-        {"android.view.KeyEvent", REG_JNI(register_android_view_KeyEvent)},
-        {"android.view.InputDevice", REG_JNI(register_android_view_InputDevice)},
-        {"android.view.MotionEvent", REG_JNI(register_android_view_MotionEvent)},
-        {"android.view.VelocityTracker", REG_JNI(register_android_view_VelocityTracker)},
-        {"com.android.internal.util.VirtualRefBasePtr",
-         REG_JNI(register_com_android_internal_util_VirtualRefBasePtr)},
-        {"libcore.util.NativeAllocationRegistry_Delegate",
-         REG_JNI(register_libcore_util_NativeAllocationRegistry_Delegate)},
-};
-
-static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& jniRegMap,
-        const vector<string>& classesToRegister, JNIEnv* env) {
-
-    for (const string& className : classesToRegister) {
-        if (jniRegMap.at(className).mProc(env) < 0) {
-            return -1;
-        }
-    }
-
-    if (register_android_graphics_classes(env) < 0) {
-        return -1;
-    }
-
-    return 0;
-}
-
-int AndroidRuntime::registerNativeMethods(JNIEnv* env,
-        const char* className, const JNINativeMethod* gMethods, int numMethods) {
-    return jniRegisterNativeMethods(env, className, gMethods, numMethods);
-}
-
-JNIEnv* AndroidRuntime::getJNIEnv() {
-    JNIEnv* env;
-    if (javaVM->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
-        return nullptr;
-    return env;
-}
-
-JavaVM* AndroidRuntime::getJavaVM() {
-    return javaVM;
-}
-
-static vector<string> parseCsv(const string& csvString) {
-    vector<string>   result;
-    istringstream stream(csvString);
-    string segment;
-    while(getline(stream, segment, ','))
-    {
-        result.push_back(segment);
-    }
-    return result;
-}
-
-void LayoutlibLogger(base::LogId, base::LogSeverity severity, const char* tag, const char* file,
-                     unsigned int line, const char* message) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jint logPrio = severity;
-    jstring tagString = env->NewStringUTF(tag);
-    jstring messageString = env->NewStringUTF(message);
-
-    jobject bridgeLog = env->CallStaticObjectMethod(bridge, getLogId);
-
-    env->CallVoidMethod(bridgeLog, logMethodId, logPrio, tagString, messageString);
-
-    env->DeleteLocalRef(tagString);
-    env->DeleteLocalRef(messageString);
-    env->DeleteLocalRef(bridgeLog);
-}
-
-void LayoutlibAborter(const char* abort_message) {
-    // Layoutlib should not call abort() as it would terminate Studio.
-    // Throw an exception back to Java instead.
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jniThrowRuntimeException(env, "The Android framework has encountered a fatal error");
-}
-
-// This method has been copied/adapted from system/core/init/property_service.cpp
-// If the ro.product.cpu.abilist* properties have not been explicitly
-// set, derive them from ro.system.product.cpu.abilist* properties.
-static void property_initialize_ro_cpu_abilist() {
-    const std::string EMPTY = "";
-    const char* kAbilistProp = "ro.product.cpu.abilist";
-    const char* kAbilist32Prop = "ro.product.cpu.abilist32";
-    const char* kAbilist64Prop = "ro.product.cpu.abilist64";
-
-    // If the properties are defined explicitly, just use them.
-    if (base::GetProperty(kAbilistProp, EMPTY) != EMPTY) {
-        return;
-    }
-
-    std::string abilist32_prop_val;
-    std::string abilist64_prop_val;
-    const auto abilist32_prop = "ro.system.product.cpu.abilist32";
-    const auto abilist64_prop = "ro.system.product.cpu.abilist64";
-    abilist32_prop_val = base::GetProperty(abilist32_prop, EMPTY);
-    abilist64_prop_val = base::GetProperty(abilist64_prop, EMPTY);
-
-    // Merge ABI lists for ro.product.cpu.abilist
-    auto abilist_prop_val = abilist64_prop_val;
-    if (abilist32_prop_val != EMPTY) {
-        if (abilist_prop_val != EMPTY) {
-            abilist_prop_val += ",";
-        }
-        abilist_prop_val += abilist32_prop_val;
-    }
-
-    // Set these properties
-    const std::pair<const char*, const std::string&> set_prop_list[] = {
-            {kAbilistProp, abilist_prop_val},
-            {kAbilist32Prop, abilist32_prop_val},
-            {kAbilist64Prop, abilist64_prop_val},
-    };
-    for (const auto& [prop, prop_val] : set_prop_list) {
-        base::SetProperty(prop, prop_val);
-    }
-}
-
-static void* mmapFile(const char* dataFilePath) {
-#ifdef _WIN32
-    // Windows needs file path in wide chars to handle unicode file paths
-    int size = MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, NULL, 0);
-    std::vector<wchar_t> wideDataFilePath(size);
-    MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, wideDataFilePath.data(), size);
-    HANDLE file =
-            CreateFileW(wideDataFilePath.data(), GENERIC_READ, FILE_SHARE_READ, nullptr,
-                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, nullptr);
-    if ((HANDLE)INVALID_HANDLE_VALUE == file) {
-        return nullptr;
-    }
-
-    struct CloseHandleWrapper {
-        void operator()(HANDLE h) { CloseHandle(h); }
-    };
-    std::unique_ptr<void, CloseHandleWrapper> mmapHandle(
-            CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
-    if (!mmapHandle) {
-        return nullptr;
-    }
-    return MapViewOfFile(mmapHandle.get(), FILE_MAP_READ, 0, 0, 0);
-#else
-    int fd = open(dataFilePath, O_RDONLY);
-    if (fd == -1) {
-        return nullptr;
-    }
-
-    struct stat sb;
-    if (fstat(fd, &sb) == -1) {
-        close(fd);
-        return nullptr;
-    }
-
-    void* addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-    if (addr == MAP_FAILED) {
-        close(fd);
-        return nullptr;
-    }
-
-    close(fd);
-    return addr;
-#endif
-}
-
-static bool init_icu(const char* dataPath) {
-    void* addr = mmapFile(dataPath);
-    UErrorCode err = U_ZERO_ERROR;
-    udata_setCommonData(addr, &err);
-    if (err != U_ZERO_ERROR) {
-        return false;
-    }
-    return true;
-}
-
-// Creates an array of InputDevice from key character map files
-static void init_keyboard(JNIEnv* env, const vector<string>& keyboardPaths) {
-    jclass inputDevice = FindClassOrDie(env, "android/view/InputDevice");
-    jobjectArray inputDevicesArray =
-            env->NewObjectArray(keyboardPaths.size(), inputDevice, nullptr);
-    int keyboardId = 1;
-
-    for (const string& path : keyboardPaths) {
-        base::Result<std::shared_ptr<KeyCharacterMap>> charMap =
-                KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE);
-
-        InputDeviceInfo info = InputDeviceInfo();
-        info.initialize(keyboardId, 0, 0, InputDeviceIdentifier(),
-                        "keyboard " + std::to_string(keyboardId), true, false, 0);
-        info.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-        info.setKeyCharacterMap(*charMap);
-
-        jobject inputDeviceObj = android_view_InputDevice_create(env, info);
-        if (inputDeviceObj) {
-            env->SetObjectArrayElement(inputDevicesArray, keyboardId - 1, inputDeviceObj);
-            env->DeleteLocalRef(inputDeviceObj);
-        }
-        keyboardId++;
-    }
-
-    if (bridge == nullptr) {
-        bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
-        bridge = MakeGlobalRefOrDie(env, bridge);
-    }
-    jmethodID setInputManager = GetStaticMethodIDOrDie(env, bridge, "setInputManager",
-                                                       "([Landroid/view/InputDevice;)V");
-    env->CallStaticVoidMethod(bridge, setInputManager, inputDevicesArray);
-    env->DeleteLocalRef(inputDevicesArray);
-}
-
-} // namespace android
-
-using namespace android;
-
-// Called right before aborting by LOG_ALWAYS_FATAL. Print the pending exception.
-void abort_handler(const char* abort_message) {
-    ALOGE("About to abort the process...");
-
-    JNIEnv* env = NULL;
-    if (javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        ALOGE("vm->GetEnv() failed");
-        return;
-    }
-    if (env->ExceptionOccurred() != NULL) {
-        ALOGE("Pending exception:");
-        env->ExceptionDescribe();
-    }
-    ALOGE("Aborting because: %s", abort_message);
-}
-
-JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
-    javaVM = vm;
-    JNIEnv* env = nullptr;
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        return JNI_ERR;
-    }
-
-    __android_log_set_aborter(abort_handler);
-
-    init_android_graphics();
-
-    // Configuration is stored as java System properties.
-    // Get a reference to System.getProperty
-    jclass system = FindClassOrDie(env, "java/lang/System");
-    jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty",
-                                                         "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
-
-    // Java system properties that contain LayoutLib config. The initial values in the map
-    // are the default values if the property is not specified.
-    std::unordered_map<std::string, std::string> systemProperties =
-            {{"core_native_classes", ""},
-             {"register_properties_during_load", ""},
-             {"icu.data.path", ""},
-             {"use_bridge_for_logging", ""},
-             {"keyboard_paths", ""}};
-
-    for (auto& [name, defaultValue] : systemProperties) {
-        jstring propertyString =
-                (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
-                                                     env->NewStringUTF(name.c_str()),
-                                                     env->NewStringUTF(defaultValue.c_str()));
-        const char* propertyChars = env->GetStringUTFChars(propertyString, 0);
-        systemProperties[name] = string(propertyChars);
-        env->ReleaseStringUTFChars(propertyString, propertyChars);
-    }
-    // Get the names of classes that need to register their native methods
-    vector<string> classesToRegister = parseCsv(systemProperties["core_native_classes"]);
-
-    if (systemProperties["register_properties_during_load"] == "true") {
-        // Set the system properties first as they could be used in the static initialization of
-        // other classes
-        if (register_android_os_SystemProperties(env) < 0) {
-            return JNI_ERR;
-        }
-        classesToRegister.erase(find(classesToRegister.begin(), classesToRegister.end(),
-                                     "android.os.SystemProperties"));
-        bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
-        bridge = MakeGlobalRefOrDie(env, bridge);
-        jmethodID setSystemPropertiesMethod =
-                GetStaticMethodIDOrDie(env, bridge, "setSystemProperties", "()V");
-        env->CallStaticVoidMethod(bridge, setSystemPropertiesMethod);
-        property_initialize_ro_cpu_abilist();
-    }
-
-    if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) {
-        return JNI_ERR;
-    }
-
-    if (!systemProperties["icu.data.path"].empty()) {
-        // Set the location of ICU data
-        bool icuInitialized = init_icu(systemProperties["icu.data.path"].c_str());
-        if (!icuInitialized) {
-            return JNI_ERR;
-        }
-    }
-
-    if (systemProperties["use_bridge_for_logging"] == "true") {
-        layoutLog = FindClassOrDie(env, "com/android/ide/common/rendering/api/ILayoutLog");
-        layoutLog = MakeGlobalRefOrDie(env, layoutLog);
-        logMethodId = GetMethodIDOrDie(env, layoutLog, "logAndroidFramework",
-                                       "(ILjava/lang/String;Ljava/lang/String;)V");
-        if (bridge == nullptr) {
-            bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
-            bridge = MakeGlobalRefOrDie(env, bridge);
-        }
-        getLogId = GetStaticMethodIDOrDie(env, bridge, "getLog",
-                                          "()Lcom/android/ide/common/rendering/api/ILayoutLog;");
-        android::base::SetLogger(LayoutlibLogger);
-        android::base::SetAborter(LayoutlibAborter);
-    } else {
-        // initialize logging, so ANDROD_LOG_TAGS env variable is respected
-        android::base::InitLogging(nullptr, android::base::StderrLogger);
-    }
-
-    // Use English locale for number format to ensure correct parsing of floats when using strtof
-    setlocale(LC_NUMERIC, "en_US.UTF-8");
-
-    if (!systemProperties["keyboard_paths"].empty()) {
-        vector<string> keyboardPaths = parseCsv(systemProperties["keyboard_paths"]);
-        init_keyboard(env, keyboardPaths);
-    } else {
-        fprintf(stderr, "Skip initializing keyboard\n");
-    }
-
-    return JNI_VERSION_1_6;
-}
-
-JNIEXPORT void JNI_OnUnload(JavaVM* vm, void*) {
-    JNIEnv* env = nullptr;
-    vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
-    env->DeleteGlobalRef(bridge);
-    env->DeleteGlobalRef(layoutLog);
-}
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 593bdf0..163f32e 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -110,3 +110,6 @@
 
 # PerformanceHintManager
 per-file android_os_PerformanceHintManager.cpp = file:/ADPF_OWNERS
+
+# IF Tools
+per-file android_tracing_Perfetto* = file:platform/development:/tools/winscope/OWNERS
diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp
index 9525605..30d9ea1 100644
--- a/core/jni/android_os_MessageQueue.cpp
+++ b/core/jni/android_os_MessageQueue.cpp
@@ -225,7 +225,7 @@
     nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
 }
 
-static void android_os_MessageQueue_nativeWake(jlong ptr) {
+static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
     NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
     nativeMessageQueue->wake();
 }
diff --git a/core/jni/android_text_Hyphenator.cpp b/core/jni/android_text_Hyphenator.cpp
index 7c976b7..b6bf617 100644
--- a/core/jni/android_text_Hyphenator.cpp
+++ b/core/jni/android_text_Hyphenator.cpp
@@ -36,43 +36,41 @@
     return SYSTEM_HYPHENATOR_PREFIX + lowerLocale + SYSTEM_HYPHENATOR_SUFFIX;
 }
 
-static std::pair<const uint8_t*, uint32_t> mmapPatternFile(const std::string& locale) {
+static const uint8_t* mmapPatternFile(const std::string& locale) {
     const std::string hyFilePath = buildFileName(locale);
     const int fd = open(hyFilePath.c_str(), O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
-        return std::make_pair(nullptr, 0); // Open failed.
+        return nullptr;  // Open failed.
     }
 
     struct stat st = {};
     if (fstat(fd, &st) == -1) {  // Unlikely to happen.
         close(fd);
-        return std::make_pair(nullptr, 0);
+        return nullptr;
     }
 
     void* ptr = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0 /* offset */);
     close(fd);
     if (ptr == MAP_FAILED) {
-        return std::make_pair(nullptr, 0);
+        return nullptr;
     }
-    return std::make_pair(reinterpret_cast<const uint8_t*>(ptr), st.st_size);
+    return reinterpret_cast<const uint8_t*>(ptr);
 }
 
 static void addHyphenatorWithoutPatternFile(const std::string& locale, int minPrefix,
         int minSuffix) {
-    minikin::addHyphenator(locale,
-                           minikin::Hyphenator::loadBinary(nullptr, 0, minPrefix, minSuffix,
-                                                           locale));
+    minikin::addHyphenator(locale, minikin::Hyphenator::loadBinary(
+            nullptr, minPrefix, minSuffix, locale));
 }
 
 static void addHyphenator(const std::string& locale, int minPrefix, int minSuffix) {
-    auto [ptr, size] = mmapPatternFile(locale);
+    const uint8_t* ptr = mmapPatternFile(locale);
     if (ptr == nullptr) {
         ALOGE("Unable to find pattern file or unable to map it for %s", locale.c_str());
         return;
     }
-    minikin::addHyphenator(locale,
-                           minikin::Hyphenator::loadBinary(ptr, size, minPrefix, minSuffix,
-                                                           locale));
+    minikin::addHyphenator(locale, minikin::Hyphenator::loadBinary(
+            ptr, minPrefix, minSuffix, locale));
 }
 
 static void addHyphenatorAlias(const std::string& from, const std::string& to) {
diff --git a/core/jni/android_tracing_PerfettoDataSource.cpp b/core/jni/android_tracing_PerfettoDataSource.cpp
index 25ff853..f82ebfe 100644
--- a/core/jni/android_tracing_PerfettoDataSource.cpp
+++ b/core/jni/android_tracing_PerfettoDataSource.cpp
@@ -45,12 +45,6 @@
 static struct {
     jclass clazz;
     jmethodID init;
-    jmethodID getAndClearAllPendingTracePackets;
-} gTracingContextClassInfo;
-
-static struct {
-    jclass clazz;
-    jmethodID init;
 } gCreateTlsStateArgsClassInfo;
 
 static struct {
@@ -68,32 +62,10 @@
     jobject jobj;
 };
 
-static void traceAllPendingPackets(JNIEnv* env, jobject jCtx, PerfettoDsTracerIterator* ctx) {
-    jobjectArray packets =
-            (jobjectArray)env
-                    ->CallObjectMethod(jCtx,
-                                       gTracingContextClassInfo.getAndClearAllPendingTracePackets);
-    if (env->ExceptionOccurred()) {
-        env->ExceptionDescribe();
-        env->ExceptionClear();
-
-        LOG_ALWAYS_FATAL("Failed to call java context finalize method");
-    }
-
-    int packets_count = env->GetArrayLength(packets);
-    for (int i = 0; i < packets_count; i++) {
-        jbyteArray packet_proto_buffer = (jbyteArray)env->GetObjectArrayElement(packets, i);
-
-        jbyte* raw_proto_buffer = env->GetByteArrayElements(packet_proto_buffer, 0);
-        int buffer_size = env->GetArrayLength(packet_proto_buffer);
-
-        struct PerfettoDsRootTracePacket trace_packet;
-        PerfettoDsTracerPacketBegin(ctx, &trace_packet);
-        PerfettoPbMsgAppendBytes(&trace_packet.msg.msg, (const uint8_t*)raw_proto_buffer,
-                                 buffer_size);
-        PerfettoDsTracerPacketEnd(ctx, &trace_packet);
-    }
-}
+// In a single thread there can be only one trace point active across all data source, so we can use
+// a single global thread_local variable to keep track of the active tracer iterator.
+thread_local static bool gInIteration;
+thread_local static struct PerfettoDsTracerIterator gIterator;
 
 PerfettoDataSource::PerfettoDataSource(JNIEnv* env, jobject javaDataSource,
                                        std::string dataSourceName)
@@ -121,87 +93,124 @@
     return instance;
 }
 
-jobject PerfettoDataSource::createTlsStateGlobalRef(JNIEnv* env, PerfettoDsInstanceIndex inst_id) {
-    ScopedLocalRef<jobject> args(env,
-                                 env->NewObject(gCreateTlsStateArgsClassInfo.clazz,
-                                                gCreateTlsStateArgsClassInfo.init, mJavaDataSource,
-                                                inst_id));
-
-    ScopedLocalRef<jobject> tslState(env,
-                                     env->CallObjectMethod(mJavaDataSource,
-                                                           gPerfettoDataSourceClassInfo
-                                                                   .createTlsState,
-                                                           args.get()));
-
-    if (env->ExceptionCheck()) {
-        LOGE_EX(env);
-        env->ExceptionClear();
-        LOG_ALWAYS_FATAL("Failed to create new Java Perfetto incremental state");
+bool PerfettoDataSource::TraceIterateBegin() {
+    if (gInIteration) {
+        return false;
     }
 
-    return env->NewGlobalRef(tslState.get());
-}
+    gIterator = PerfettoDsTraceIterateBegin(&dataSource);
 
-jobject PerfettoDataSource::createIncrementalStateGlobalRef(JNIEnv* env,
-                                                            PerfettoDsInstanceIndex inst_id) {
-    ScopedLocalRef<jobject> args(env,
-                                 env->NewObject(gCreateIncrementalStateArgsClassInfo.clazz,
-                                                gCreateIncrementalStateArgsClassInfo.init,
-                                                mJavaDataSource, inst_id));
-
-    ScopedLocalRef<jobject> incrementalState(env,
-                                             env->CallObjectMethod(mJavaDataSource,
-                                                                   gPerfettoDataSourceClassInfo
-                                                                           .createIncrementalState,
-                                                                   args.get()));
-
-    if (env->ExceptionCheck()) {
-        LOGE_EX(env);
-        env->ExceptionClear();
-        LOG_ALWAYS_FATAL("Failed to create Java Perfetto incremental state");
+    if (gIterator.impl.tracer == nullptr) {
+        return false;
     }
 
-    return env->NewGlobalRef(incrementalState.get());
+    gInIteration = true;
+    return true;
 }
 
-void PerfettoDataSource::trace(JNIEnv* env, jobject traceFunction) {
-    PERFETTO_DS_TRACE(dataSource, ctx) {
-        ALOG(LOG_DEBUG, LOG_TAG, "\tin native trace callback function %p", this);
-        TlsState* tls_state =
-                reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &ctx));
-        IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
-                PerfettoDsGetIncrementalState(&dataSource, &ctx));
+bool PerfettoDataSource::TraceIterateNext() {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried calling TraceIterateNext outside of a tracer iteration.");
+        return false;
+    }
 
-        ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state = %p", tls_state);
-        ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state = %p", incr_state);
+    PerfettoDsTraceIterateNext(&dataSource, &gIterator);
 
-        ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state->jobj = %p", tls_state->jobj);
-        ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state->jobj = %p", incr_state->jobj);
+    if (gIterator.impl.tracer == nullptr) {
+        // Reached end of iterator. No more datasource instances.
+        gInIteration = false;
+        return false;
+    }
 
-        ScopedLocalRef<jobject> jCtx(env,
-                                     env->NewObject(gTracingContextClassInfo.clazz,
-                                                    gTracingContextClassInfo.init, &ctx,
-                                                    tls_state->jobj, incr_state->jobj));
+    return true;
+}
 
-        ALOG(LOG_DEBUG, LOG_TAG, "\t jCtx = %p", jCtx.get());
+void PerfettoDataSource::TraceIterateBreak() {
+    if (!gInIteration) {
+        return;
+    }
 
-        jclass objclass = env->GetObjectClass(traceFunction);
-        jmethodID method =
-                env->GetMethodID(objclass, "trace", "(Landroid/tracing/perfetto/TracingContext;)V");
-        if (method == 0) {
-            LOG_ALWAYS_FATAL("Failed to get method id");
-        }
+    PerfettoDsTraceIterateBreak(&dataSource, &gIterator);
+    gInIteration = false;
+}
 
-        env->ExceptionClear();
+PerfettoDsInstanceIndex PerfettoDataSource::GetInstanceIndex() {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried calling GetInstanceIndex outside of a tracer iteration.");
+        return -1;
+    }
 
-        env->CallVoidMethod(traceFunction, method, jCtx.get());
-        if (env->ExceptionOccurred()) {
-            env->ExceptionDescribe();
-            env->ExceptionClear();
-            LOG_ALWAYS_FATAL("Failed to call java trace method");
-        }
+    return gIterator.impl.inst_id;
+}
 
-        traceAllPendingPackets(env, jCtx.get(), &ctx);
+jobject PerfettoDataSource::GetCustomTls() {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried getting CustomTls outside of a tracer iteration.");
+        return nullptr;
+    }
+
+    TlsState* tls_state =
+            reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &gIterator));
+
+    return tls_state->jobj;
+}
+
+void PerfettoDataSource::SetCustomTls(jobject tlsState) {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried getting CustomTls outside of a tracer iteration.");
+        return;
+    }
+
+    TlsState* tls_state =
+            reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &gIterator));
+
+    tls_state->jobj = tlsState;
+}
+
+jobject PerfettoDataSource::GetIncrementalState() {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried getting IncrementalState outside of a tracer iteration.");
+        return nullptr;
+    }
+
+    IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
+            PerfettoDsGetIncrementalState(&dataSource, &gIterator));
+
+    return incr_state->jobj;
+}
+
+void PerfettoDataSource::SetIncrementalState(jobject incrementalState) {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried getting IncrementalState outside of a tracer iteration.");
+        return;
+    }
+
+    IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
+            PerfettoDsGetIncrementalState(&dataSource, &gIterator));
+
+    incr_state->jobj = incrementalState;
+}
+
+void PerfettoDataSource::WritePackets(JNIEnv* env, jobjectArray packets) {
+    if (!gInIteration) {
+        LOG_ALWAYS_FATAL("Tried writing packets outside of a tracer iteration.");
+        return;
+    }
+
+    int packets_count = env->GetArrayLength(packets);
+    for (int i = 0; i < packets_count; i++) {
+        jbyteArray packet_proto_buffer = (jbyteArray)env->GetObjectArrayElement(packets, i);
+
+        jbyte* raw_proto_buffer = env->GetByteArrayElements(packet_proto_buffer, nullptr);
+        int buffer_size = env->GetArrayLength(packet_proto_buffer);
+
+        struct PerfettoDsRootTracePacket trace_packet;
+        PerfettoDsTracerPacketBegin(&gIterator, &trace_packet);
+        PerfettoPbMsgAppendBytes(&trace_packet.msg.msg, (const uint8_t*)raw_proto_buffer,
+                                 buffer_size);
+        PerfettoDsTracerPacketEnd(&gIterator, &trace_packet);
+
+        env->ReleaseByteArrayElements(packet_proto_buffer, raw_proto_buffer, 0 /* default mode */);
     }
 }
 
@@ -218,9 +227,7 @@
 
 jlong nativeCreate(JNIEnv* env, jclass clazz, jobject javaDataSource, jstring name) {
     const char* nativeString = env->GetStringUTFChars(name, 0);
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeCreate(%p, %s)", javaDataSource, nativeString);
     PerfettoDataSource* dataSource = new PerfettoDataSource(env, javaDataSource, nativeString);
-    ALOG(LOG_DEBUG, LOG_TAG, "\tdatasource* = %p", dataSource);
     env->ReleaseStringUTFChars(name, nativeString);
 
     dataSource->incStrong((void*)nativeCreate);
@@ -229,39 +236,27 @@
 }
 
 void nativeDestroy(void* ptr) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeCreate(%p)", ptr);
     PerfettoDataSource* dataSource = reinterpret_cast<PerfettoDataSource*>(ptr);
     dataSource->decStrong((void*)nativeCreate);
 }
 
 static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeGetFinalizer()");
     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&nativeDestroy));
 }
 
-void nativeTrace(JNIEnv* env, jclass clazz, jlong dataSourcePtr, jobject traceFunctionInterface) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeTrace(%p)", (void*)dataSourcePtr);
-    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
-
-    datasource->trace(env, traceFunctionInterface);
-}
-
-void nativeFlush(JNIEnv* env, jclass clazz, jobject jCtx, jlong ctxPtr) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeFlush(%p, %p)", jCtx, (void*)ctxPtr);
-    auto* ctx = reinterpret_cast<struct PerfettoDsTracerIterator*>(ctxPtr);
-    traceAllPendingPackets(env, jCtx, ctx);
-    PerfettoDsTracerFlush(ctx, nullptr, nullptr);
+void nativeFlush(JNIEnv* env, jclass clazz, jlong ds_ptr, jobjectArray packets) {
+    ALOG(LOG_DEBUG, LOG_TAG, "nativeFlush(%p)", (void*)ds_ptr);
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(ds_ptr);
+    datasource->WritePackets(env, packets);
 }
 
 void nativeFlushAll(JNIEnv* env, jclass clazz, jlong ptr) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeFlushAll(%p)", (void*)ptr);
     sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(ptr);
     datasource->flushAll();
 }
 
 void nativeRegisterDataSource(JNIEnv* env, jclass clazz, jlong datasource_ptr,
-                              int buffer_exhausted_policy) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeRegisterDataSource(%p)", (void*)datasource_ptr);
+                              jint buffer_exhausted_policy) {
     sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(datasource_ptr);
 
     struct PerfettoDsParams params = PerfettoDsParamsDefault();
@@ -283,25 +278,13 @@
 
         auto* datasource_instance =
                 new PerfettoDataSourceInstance(env, java_data_source_instance.get(), inst_id);
-
-        ALOG(LOG_DEBUG, LOG_TAG, "on_setup_cb ds=%p, ds_instance=%p", datasource,
-             datasource_instance);
-
         return static_cast<void*>(datasource_instance);
     };
 
     params.on_create_tls_cb = [](struct PerfettoDsImpl* ds_impl, PerfettoDsInstanceIndex inst_id,
                                  struct PerfettoDsTracerImpl* tracer, void* user_arg) -> void* {
-        JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
-
-        auto* datasource = reinterpret_cast<PerfettoDataSource*>(user_arg);
-
-        jobject java_tls_state = datasource->createTlsStateGlobalRef(env, inst_id);
-
-        auto* tls_state = new TlsState(java_tls_state);
-
-        ALOG(LOG_DEBUG, LOG_TAG, "on_create_tls_cb ds=%p, tsl_state=%p", datasource, tls_state);
-
+        // Populated later and only if required by the java side
+        auto* tls_state = new TlsState(NULL);
         return static_cast<void*>(tls_state);
     };
 
@@ -310,23 +293,16 @@
 
         TlsState* tls_state = reinterpret_cast<TlsState*>(ptr);
 
-        ALOG(LOG_DEBUG, LOG_TAG, "on_delete_tls_cb %p", tls_state);
-
-        env->DeleteGlobalRef(tls_state->jobj);
+        if (tls_state->jobj != NULL) {
+            env->DeleteGlobalRef(tls_state->jobj);
+        }
         delete tls_state;
     };
 
     params.on_create_incr_cb = [](struct PerfettoDsImpl* ds_impl, PerfettoDsInstanceIndex inst_id,
                                   struct PerfettoDsTracerImpl* tracer, void* user_arg) -> void* {
-        JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
-
-        auto* datasource = reinterpret_cast<PerfettoDataSource*>(user_arg);
-        jobject java_incr_state = datasource->createIncrementalStateGlobalRef(env, inst_id);
-
-        auto* incr_state = new IncrementalState(java_incr_state);
-
-        ALOG(LOG_DEBUG, LOG_TAG, "on_create_incr_cb ds=%p, incr_state=%p", datasource, incr_state);
-
+        // Populated later and only if required by the java side
+        auto* incr_state = new IncrementalState(NULL);
         return static_cast<void*>(incr_state);
     };
 
@@ -335,9 +311,9 @@
 
         IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(ptr);
 
-        ALOG(LOG_DEBUG, LOG_TAG, "on_delete_incr_cb incr_state=%p", incr_state);
-
-        env->DeleteGlobalRef(incr_state->jobj);
+        if (incr_state->jobj != NULL) {
+            env->DeleteGlobalRef(incr_state->jobj);
+        }
         delete incr_state;
     };
 
@@ -346,9 +322,6 @@
         JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
 
         auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
-
-        ALOG(LOG_DEBUG, LOG_TAG, "on_start_cb ds_instance=%p", datasource_instance);
-
         datasource_instance->onStart(env);
     };
 
@@ -357,9 +330,6 @@
         JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
 
         auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
-
-        ALOG(LOG_DEBUG, LOG_TAG, "on_flush_cb ds_instance=%p", datasource_instance);
-
         datasource_instance->onFlush(env);
     };
 
@@ -368,9 +338,6 @@
         JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
 
         auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
-
-        ALOG(LOG_DEBUG, LOG_TAG, "on_stop_cb ds_instance=%p", datasource_instance);
-
         datasource_instance->onStop(env);
     };
 
@@ -378,18 +345,14 @@
                               void* inst_ctx) -> void {
         auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
 
-        ALOG(LOG_DEBUG, LOG_TAG, "on_destroy_cb ds_instance=%p", datasource_instance);
-
         delete datasource_instance;
     };
 
     PerfettoDsRegister(&datasource->dataSource, datasource->dataSourceName.c_str(), params);
 }
 
-jobject nativeGetPerfettoInstanceLocked(JNIEnv* env, jclass clazz, jlong dataSourcePtr,
+jobject nativeGetPerfettoInstanceLocked(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr,
                                         PerfettoDsInstanceIndex instance_idx) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeGetPerfettoInstanceLocked ds=%p, idx=%d", (void*)dataSourcePtr,
-         instance_idx);
     sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
     auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(
             PerfettoDsImplGetInstanceLocked(datasource->dataSource.impl, instance_idx));
@@ -401,24 +364,62 @@
         return nullptr;
     }
 
-    ALOG(LOG_DEBUG, LOG_TAG, "\tnativeGetPerfettoInstanceLocked got lock ds=%p, idx=%d",
-         (void*)dataSourcePtr, instance_idx);
     return datasource_instance->GetJavaDataSourceInstance();
 }
 
-void nativeReleasePerfettoInstanceLocked(JNIEnv* env, jclass clazz, jlong dataSourcePtr,
+void nativeReleasePerfettoInstanceLocked(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr,
                                          PerfettoDsInstanceIndex instance_idx) {
-    ALOG(LOG_DEBUG, LOG_TAG, "nativeReleasePerfettoInstanceLocked got lock ds=%p, idx=%d",
-         (void*)dataSourcePtr, instance_idx);
     sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
     PerfettoDsImplReleaseInstanceLocked(datasource->dataSource.impl, instance_idx);
 }
 
+bool nativePerfettoDsTraceIterateBegin(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    return datasource->TraceIterateBegin();
+}
+
+bool nativePerfettoDsTraceIterateNext(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    return datasource->TraceIterateNext();
+}
+
+void nativePerfettoDsTraceIterateBreak(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    return datasource->TraceIterateBreak();
+}
+
+jint nativeGetPerfettoDsInstanceIndex(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    return (jint)datasource->GetInstanceIndex();
+}
+
+jobject nativeGetCustomTls(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    return datasource->GetCustomTls();
+}
+
+void nativeSetCustomTls(JNIEnv* env, jclass /* clazz */, jlong dataSourcePtr, jobject tlsState) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    tlsState = env->NewGlobalRef(tlsState);
+    return datasource->SetCustomTls(tlsState);
+}
+
+jobject nativeGetIncrementalState(JNIEnv* /* env */, jclass /* clazz */, jlong dataSourcePtr) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    return datasource->GetIncrementalState();
+}
+
+void nativeSetIncrementalState(JNIEnv* env, jclass /* clazz */, jlong dataSourcePtr,
+                               jobject incrementalState) {
+    sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
+    incrementalState = env->NewGlobalRef(incrementalState);
+    return datasource->SetIncrementalState(incrementalState);
+}
+
 const JNINativeMethod gMethods[] = {
         /* name, signature, funcPtr */
         {"nativeCreate", "(Landroid/tracing/perfetto/DataSource;Ljava/lang/String;)J",
          (void*)nativeCreate},
-        {"nativeTrace", "(JLandroid/tracing/perfetto/TraceFunction;)V", (void*)nativeTrace},
         {"nativeFlushAll", "(J)V", (void*)nativeFlushAll},
         {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer},
         {"nativeRegisterDataSource", "(JI)V", (void*)nativeRegisterDataSource},
@@ -426,11 +427,19 @@
          (void*)nativeGetPerfettoInstanceLocked},
         {"nativeReleasePerfettoInstanceLocked", "(JI)V",
          (void*)nativeReleasePerfettoInstanceLocked},
-};
+
+        {"nativePerfettoDsTraceIterateBegin", "(J)Z", (void*)nativePerfettoDsTraceIterateBegin},
+        {"nativePerfettoDsTraceIterateNext", "(J)Z", (void*)nativePerfettoDsTraceIterateNext},
+        {"nativePerfettoDsTraceIterateBreak", "(J)V", (void*)nativePerfettoDsTraceIterateBreak},
+        {"nativeGetPerfettoDsInstanceIndex", "(J)I", (void*)nativeGetPerfettoDsInstanceIndex}};
 
 const JNINativeMethod gMethodsTracingContext[] = {
         /* name, signature, funcPtr */
-        {"nativeFlush", "(Landroid/tracing/perfetto/TracingContext;J)V", (void*)nativeFlush},
+        {"nativeFlush", "(J[[B)V", (void*)nativeFlush},
+        {"nativeGetCustomTls", "(J)Ljava/lang/Object;", (void*)nativeGetCustomTls},
+        {"nativeGetIncrementalState", "(J)Ljava/lang/Object;", (void*)nativeGetIncrementalState},
+        {"nativeSetCustomTls", "(JLjava/lang/Object;)V", (void*)nativeSetCustomTls},
+        {"nativeSetIncrementalState", "(JLjava/lang/Object;)V", (void*)nativeSetIncrementalState},
 };
 
 int register_android_tracing_PerfettoDataSource(JNIEnv* env) {
@@ -461,14 +470,6 @@
                              "(Landroid/tracing/perfetto/CreateIncrementalStateArgs;)Ljava/lang/"
                              "Object;");
 
-    clazz = env->FindClass("android/tracing/perfetto/TracingContext");
-    gTracingContextClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
-    gTracingContextClassInfo.init = env->GetMethodID(gTracingContextClassInfo.clazz, "<init>",
-                                                     "(JLjava/lang/Object;Ljava/lang/Object;)V");
-    gTracingContextClassInfo.getAndClearAllPendingTracePackets =
-            env->GetMethodID(gTracingContextClassInfo.clazz, "getAndClearAllPendingTracePackets",
-                             "()[[B");
-
     clazz = env->FindClass("android/tracing/perfetto/CreateTlsStateArgs");
     gCreateTlsStateArgsClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
     gCreateTlsStateArgsClassInfo.init =
diff --git a/core/jni/android_tracing_PerfettoDataSource.h b/core/jni/android_tracing_PerfettoDataSource.h
index 906d9f5..fe15184 100644
--- a/core/jni/android_tracing_PerfettoDataSource.h
+++ b/core/jni/android_tracing_PerfettoDataSource.h
@@ -44,9 +44,17 @@
     jobject newInstance(JNIEnv* env, void* ds_config, size_t ds_config_size,
                         PerfettoDsInstanceIndex inst_id);
 
-    jobject createTlsStateGlobalRef(JNIEnv* env, PerfettoDsInstanceIndex inst_id);
-    jobject createIncrementalStateGlobalRef(JNIEnv* env, PerfettoDsInstanceIndex inst_id);
-    void trace(JNIEnv* env, jobject trace_function);
+    bool TraceIterateBegin();
+    bool TraceIterateNext();
+    void TraceIterateBreak();
+    PerfettoDsInstanceIndex GetInstanceIndex();
+    void WritePackets(JNIEnv* env, jobjectArray packets);
+
+    jobject GetCustomTls();
+    void SetCustomTls(jobject);
+    jobject GetIncrementalState();
+    void SetIncrementalState(jobject);
+
     void flushAll();
 
 private:
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index b801a69..3e3af40 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -28,6 +28,8 @@
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
 
+#include <sstream>
+
 #include "android_os_Parcel.h"
 #include "android_util_Binder.h"
 #include "core_jni_helpers.h"
@@ -598,8 +600,8 @@
 
 // ----------------- @CriticalNative ------------------------------
 
-static jlong android_view_MotionEvent_nativeCopy(jlong destNativePtr, jlong sourceNativePtr,
-        jboolean keepHistory) {
+static jlong android_view_MotionEvent_nativeCopy(CRITICAL_JNI_PARAMS_COMMA jlong destNativePtr,
+                                                 jlong sourceNativePtr, jboolean keepHistory) {
     MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
     if (!destEvent) {
         destEvent = new MotionEvent();
@@ -609,8 +611,8 @@
     return reinterpret_cast<jlong>(destEvent);
 }
 
-static jlong android_view_MotionEvent_nativeSplit(jlong destNativePtr, jlong sourceNativePtr,
-                                                  jint idBits) {
+static jlong android_view_MotionEvent_nativeSplit(CRITICAL_JNI_PARAMS_COMMA jlong destNativePtr,
+                                                  jlong sourceNativePtr, jint idBits) {
     MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
     if (!destEvent) {
         destEvent = new MotionEvent();
@@ -621,168 +623,192 @@
     return reinterpret_cast<jlong>(destEvent);
 }
 
-static jint android_view_MotionEvent_nativeGetId(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetId(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getId();
 }
 
-static jint android_view_MotionEvent_nativeGetDeviceId(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetDeviceId(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getDeviceId();
 }
 
-static jint android_view_MotionEvent_nativeGetSource(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetSource(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getSource();
 }
 
-static void android_view_MotionEvent_nativeSetSource(jlong nativePtr, jint source) {
+static void android_view_MotionEvent_nativeSetSource(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                     jint source) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setSource(source);
 }
 
-static jint android_view_MotionEvent_nativeGetDisplayId(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetDisplayId(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getDisplayId();
 }
 
-static void android_view_MotionEvent_nativeSetDisplayId(jlong nativePtr, jint displayId) {
+static void android_view_MotionEvent_nativeSetDisplayId(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                        jint displayId) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->setDisplayId(displayId);
 }
 
-static jint android_view_MotionEvent_nativeGetAction(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetAction(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getAction();
 }
 
-static void android_view_MotionEvent_nativeSetAction(jlong nativePtr, jint action) {
+static void android_view_MotionEvent_nativeSetAction(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                     jint action) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setAction(action);
 }
 
-static int android_view_MotionEvent_nativeGetActionButton(jlong nativePtr) {
+static int android_view_MotionEvent_nativeGetActionButton(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getActionButton();
 }
 
-static void android_view_MotionEvent_nativeSetActionButton(jlong nativePtr, jint button) {
+static void android_view_MotionEvent_nativeSetActionButton(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr, jint button) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setActionButton(button);
 }
 
-static jboolean android_view_MotionEvent_nativeIsTouchEvent(jlong nativePtr) {
+static jboolean android_view_MotionEvent_nativeIsTouchEvent(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->isTouchEvent();
 }
 
-static jint android_view_MotionEvent_nativeGetFlags(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetFlags(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getFlags();
 }
 
-static void android_view_MotionEvent_nativeSetFlags(jlong nativePtr, jint flags) {
+static void android_view_MotionEvent_nativeSetFlags(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                    jint flags) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setFlags(flags);
 }
 
-static jint android_view_MotionEvent_nativeGetEdgeFlags(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetEdgeFlags(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getEdgeFlags();
 }
 
-static void android_view_MotionEvent_nativeSetEdgeFlags(jlong nativePtr, jint edgeFlags) {
+static void android_view_MotionEvent_nativeSetEdgeFlags(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                        jint edgeFlags) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setEdgeFlags(edgeFlags);
 }
 
-static jint android_view_MotionEvent_nativeGetMetaState(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetMetaState(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getMetaState();
 }
 
-static jint android_view_MotionEvent_nativeGetButtonState(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetButtonState(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getButtonState();
 }
 
-static void android_view_MotionEvent_nativeSetButtonState(jlong nativePtr, jint buttonState) {
+static void android_view_MotionEvent_nativeSetButtonState(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                          jint buttonState) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setButtonState(buttonState);
 }
 
-static jint android_view_MotionEvent_nativeGetClassification(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetClassification(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return static_cast<jint>(event->getClassification());
 }
 
-static void android_view_MotionEvent_nativeOffsetLocation(jlong nativePtr, jfloat deltaX,
-        jfloat deltaY) {
+static void android_view_MotionEvent_nativeOffsetLocation(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                          jfloat deltaX, jfloat deltaY) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->offsetLocation(deltaX, deltaY);
 }
 
-static jfloat android_view_MotionEvent_nativeGetRawXOffset(jlong nativePtr) {
+static jfloat android_view_MotionEvent_nativeGetRawXOffset(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getRawXOffset();
 }
 
-static jfloat android_view_MotionEvent_nativeGetRawYOffset(jlong nativePtr) {
+static jfloat android_view_MotionEvent_nativeGetRawYOffset(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getRawYOffset();
 }
 
-static jfloat android_view_MotionEvent_nativeGetXPrecision(jlong nativePtr) {
+static jfloat android_view_MotionEvent_nativeGetXPrecision(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getXPrecision();
 }
 
-static jfloat android_view_MotionEvent_nativeGetYPrecision(jlong nativePtr) {
+static jfloat android_view_MotionEvent_nativeGetYPrecision(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getYPrecision();
 }
 
-static jfloat android_view_MotionEvent_nativeGetXCursorPosition(jlong nativePtr) {
+static jfloat android_view_MotionEvent_nativeGetXCursorPosition(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getXCursorPosition();
 }
 
-static jfloat android_view_MotionEvent_nativeGetYCursorPosition(jlong nativePtr) {
+static jfloat android_view_MotionEvent_nativeGetYCursorPosition(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getYCursorPosition();
 }
 
-static void android_view_MotionEvent_nativeSetCursorPosition(jlong nativePtr, jfloat x, jfloat y) {
+static void android_view_MotionEvent_nativeSetCursorPosition(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr, jfloat x, jfloat y) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setCursorPosition(x, y);
 }
 
-static jlong android_view_MotionEvent_nativeGetDownTimeNanos(jlong nativePtr) {
+static jlong android_view_MotionEvent_nativeGetDownTimeNanos(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return event->getDownTime();
 }
 
-static void android_view_MotionEvent_nativeSetDownTimeNanos(jlong nativePtr, jlong downTimeNanos) {
+static void android_view_MotionEvent_nativeSetDownTimeNanos(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr, jlong downTimeNanos) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->setDownTime(downTimeNanos);
 }
 
-static jint android_view_MotionEvent_nativeGetPointerCount(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetPointerCount(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return jint(event->getPointerCount());
 }
 
-static jint android_view_MotionEvent_nativeFindPointerIndex(jlong nativePtr, jint pointerId) {
+static jint android_view_MotionEvent_nativeFindPointerIndex(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr, jint pointerId) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return jint(event->findPointerIndex(pointerId));
 }
 
-static jint android_view_MotionEvent_nativeGetHistorySize(jlong nativePtr) {
+static jint android_view_MotionEvent_nativeGetHistorySize(
+        CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     return jint(event->getHistorySize());
 }
 
-static void android_view_MotionEvent_nativeScale(jlong nativePtr, jfloat scale) {
+static void android_view_MotionEvent_nativeScale(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr,
+                                                 jfloat scale) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
     event->scale(scale);
 }
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 869b53d..ac6298d 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -27,15 +27,19 @@
 #include <android_runtime/android_graphics_SurfaceTexture.h>
 #include <android_runtime/android_view_Surface.h>
 #include <android_runtime/Log.h>
+#ifdef __ANDROID__
 #include <private/android/AHardwareBufferHelpers.h>
 
 #include "android_os_Parcel.h"
 #include <binder/Parcel.h>
 
 #include <gui/BLASTBufferQueue.h>
+#endif
 #include <gui/Surface.h>
+#ifdef __ANDROID__
 #include <gui/SurfaceControl.h>
 #include <gui/view/Surface.h>
+#endif
 
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
@@ -67,6 +71,7 @@
     jfieldID bottom;
 } gRectClassInfo;
 
+#ifdef __ANDROID__
 class JNamedColorSpace {
 public:
     // ColorSpace.Named.SRGB.ordinal() = 0;
@@ -84,6 +89,7 @@
             return ui::Dataspace::V0_SRGB;
     }
 }
+#endif
 
 // ----------------------------------------------------------------------------
 
@@ -144,6 +150,7 @@
 
 // ----------------------------------------------------------------------------
 
+#ifdef __ANDROID__
 static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
         jobject surfaceTextureObj) {
     sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
@@ -162,6 +169,7 @@
     surface->incStrong(&sRefBaseOwner);
     return jlong(surface.get());
 }
+#endif
 
 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
@@ -269,7 +277,7 @@
 }
 
 // ----------------------------------------------------------------------------
-
+#ifdef __ANDROID__
 static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
         jlong surfaceControlNativeObj) {
     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
@@ -380,6 +388,7 @@
     // to the Parcel
     surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
 }
+#endif
 
 static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
@@ -412,6 +421,7 @@
     return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
 }
 
+#ifdef __ANDROID__
 static jint nativeAttachAndQueueBufferWithColorSpace(JNIEnv* env, jclass clazz, jlong nativeObject,
                                                      jobject hardwareBuffer, jint colorSpaceId) {
     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
@@ -422,6 +432,7 @@
             fromNamedColorSpaceValueToDataspace(colorSpaceId));
     return err;
 }
+#endif
 
 static jint nativeSetSharedBufferModeEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
         jboolean enabled) {
@@ -457,8 +468,10 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gSurfaceMethods[] = {
+#ifdef __ANDROID__
         {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
          (void*)nativeCreateFromSurfaceTexture},
+#endif
         {"nativeRelease", "(J)V", (void*)nativeRelease},
         {"nativeIsValid", "(J)Z", (void*)nativeIsValid},
         {"nativeIsConsumerRunningBehind", "(J)Z", (void*)nativeIsConsumerRunningBehind},
@@ -467,21 +480,27 @@
         {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
          (void*)nativeUnlockCanvasAndPost},
         {"nativeAllocateBuffers", "(J)V", (void*)nativeAllocateBuffers},
+#ifdef __ANDROID__
         {"nativeCreateFromSurfaceControl", "(J)J", (void*)nativeCreateFromSurfaceControl},
         {"nativeGetFromSurfaceControl", "(JJ)J", (void*)nativeGetFromSurfaceControl},
         {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J", (void*)nativeReadFromParcel},
         {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel},
+#endif
         {"nativeGetWidth", "(J)I", (void*)nativeGetWidth},
         {"nativeGetHeight", "(J)I", (void*)nativeGetHeight},
         {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber},
         {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode},
         {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
+#ifdef __ANDROID__
         {"nativeAttachAndQueueBufferWithColorSpace", "(JLandroid/hardware/HardwareBuffer;I)I",
          (void*)nativeAttachAndQueueBufferWithColorSpace},
+#endif
         {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
         {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
         {"nativeSetFrameRate", "(JFII)I", (void*)nativeSetFrameRate},
+#ifdef __ANDROID__
         {"nativeGetFromBlastBufferQueue", "(JJ)J", (void*)nativeGetFromBlastBufferQueue},
+#endif
         {"nativeDestroy", "(J)V", (void*)nativeDestroy},
 };
 
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
new file mode 100644
index 0000000..31f4e64
--- /dev/null
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FileSystemUtils"
+
+#include "com_android_internal_content_FileSystemUtils.h"
+
+#include <android-base/file.h>
+#include <android-base/hex.h>
+#include <android-base/unique_fd.h>
+#include <bionic/macros.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/Log.h>
+
+#include <array>
+#include <fstream>
+#include <vector>
+
+using android::base::borrowed_fd;
+using android::base::HexString;
+using android::base::ReadFullyAtOffset;
+
+namespace android {
+
+bool punchWithBlockAlignment(borrowed_fd fd, uint64_t start, uint64_t length, uint64_t blockSize) {
+    uint64_t end;
+    if (__builtin_add_overflow(start, length, &end)) {
+        ALOGE("Overflow occurred when calculating end");
+        return false;
+    }
+
+    start = align_up(start, blockSize);
+    end = align_down(end, blockSize);
+
+    uint64_t alignedLength;
+    if (__builtin_sub_overflow(end, start, &alignedLength)) {
+        ALOGE("Overflow occurred when calculating length");
+        return false;
+    }
+
+    if (alignedLength < blockSize) {
+        ALOGW("Skipping punching hole as aligned length is less than block size");
+        return false;
+    }
+
+    ALOGD("Punching hole in file - start: %" PRIu64 " len:%" PRIu64 "", start, alignedLength);
+
+    int result =
+            fallocate(fd.get(), FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, start, alignedLength);
+    if (result < 0) {
+        ALOGE("fallocate failed to punch hole, error:%d", errno);
+        return false;
+    }
+
+    return true;
+}
+
+bool punchHoles(const char *filePath, const uint64_t offset,
+                const std::vector<Elf64_Phdr> &programHeaders) {
+    struct stat64 beforePunch;
+    if (int result = lstat64(filePath, &beforePunch); result != 0) {
+        ALOGE("lstat64 failed for filePath %s, error:%d", filePath, errno);
+        return false;
+    }
+
+    uint64_t blockSize = beforePunch.st_blksize;
+    IF_ALOGD() {
+        ALOGD("Total number of LOAD segments %zu", programHeaders.size());
+
+        ALOGD("Size before punching holes st_blocks: %" PRIu64
+              ", st_blksize: %ld, st_size: %" PRIu64 "",
+              beforePunch.st_blocks, beforePunch.st_blksize,
+              static_cast<uint64_t>(beforePunch.st_size));
+    }
+
+    android::base::unique_fd fd(open(filePath, O_RDWR | O_CLOEXEC));
+    if (!fd.ok()) {
+        ALOGE("Can't open file to punch %s", filePath);
+        return false;
+    }
+
+    // read in chunks of 64KB
+    constexpr uint64_t kChunkSize = 64 * 1024;
+
+    // malloc is used to gracefully handle oom which might occur during the allocation of buffer.
+    // allocating using new or vector here results in oom/exception on failure where as malloc will
+    // return nullptr.
+    std::unique_ptr<uint8_t, decltype(&free)> buffer(static_cast<uint8_t *>(malloc(kChunkSize)),
+                                                     &free);
+    if (buffer == nullptr) {
+        ALOGE("Failed to allocate read buffer");
+        return false;
+    }
+
+    for (size_t index = 0; programHeaders.size() >= 2 && index < programHeaders.size() - 1;
+         index++) {
+        // find LOAD segments from program headers, calculate padding and punch holes
+        uint64_t punchOffset;
+        if (__builtin_add_overflow(programHeaders[index].p_offset, programHeaders[index].p_filesz,
+                                   &punchOffset)) {
+            ALOGE("Overflow occurred when adding offset and filesize");
+            return false;
+        }
+
+        uint64_t punchLen;
+        if (__builtin_sub_overflow(programHeaders[index + 1].p_offset, punchOffset, &punchLen)) {
+            ALOGE("Overflow occurred when calculating length");
+            return false;
+        }
+
+        if (punchLen < blockSize) {
+            continue;
+        }
+
+        // if we have a uncompressed file which is being opened from APK, use the offset to
+        // punch native lib inside Apk.
+        uint64_t punchStartOffset;
+        if (__builtin_add_overflow(offset, punchOffset, &punchStartOffset)) {
+            ALOGE("Overflow occurred when calculating length");
+            return false;
+        }
+
+        uint64_t position = punchStartOffset;
+        uint64_t endPosition;
+        if (__builtin_add_overflow(position, punchLen, &endPosition)) {
+            ALOGE("Overflow occurred when calculating length");
+            return false;
+        }
+
+        // Read content in kChunkSize and verify it is zero
+        while (position <= endPosition) {
+            uint64_t uncheckedChunkEnd;
+            if (__builtin_add_overflow(position, kChunkSize, &uncheckedChunkEnd)) {
+                ALOGE("Overflow occurred when calculating uncheckedChunkEnd");
+                return false;
+            }
+
+            uint64_t readLength;
+            if (__builtin_sub_overflow(std::min(uncheckedChunkEnd, endPosition), position,
+                                       &readLength)) {
+                ALOGE("Overflow occurred when calculating readLength");
+                return false;
+            }
+
+            if (!ReadFullyAtOffset(fd, buffer.get(), readLength, position)) {
+                ALOGE("Failed to read content to punch holes");
+                return false;
+            }
+
+            IF_ALOGD() {
+                ALOGD("Punching holes for length:%" PRIu64 " content which should be zero: %s",
+                      readLength, HexString(buffer.get(), readLength).c_str());
+            }
+
+            bool isZero = std::all_of(buffer.get(), buffer.get() + readLength,
+                                      [](uint8_t i) constexpr { return i == 0; });
+            if (!isZero) {
+                ALOGE("Found non zero content while trying to punch hole. Skipping operation");
+                return false;
+            }
+
+            position = uncheckedChunkEnd;
+        }
+
+        if (!punchWithBlockAlignment(fd, punchStartOffset, punchLen, blockSize)) {
+            return false;
+        }
+    }
+
+    IF_ALOGD() {
+        struct stat64 afterPunch;
+        if (int result = lstat64(filePath, &afterPunch); result != 0) {
+            ALOGD("lstat64 failed for filePath %s, error:%d", filePath, errno);
+            return false;
+        }
+        ALOGD("Size after punching holes st_blocks: %" PRIu64 ", st_blksize: %ld, st_size: %" PRIu64
+              "",
+              afterPunch.st_blocks, afterPunch.st_blksize,
+              static_cast<uint64_t>(afterPunch.st_size));
+    }
+
+    return true;
+}
+
+bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
+    // Open Elf file
+    Elf64_Ehdr ehdr;
+    std::ifstream inputStream(filePath, std::ifstream::in);
+
+    // If this is a zip file, set the offset so that we can read elf file directly
+    inputStream.seekg(offset);
+    // read executable headers
+    inputStream.read((char *)&ehdr, sizeof(ehdr));
+    if (!inputStream.good()) {
+        return false;
+    }
+
+    // only consider elf64 for punching holes
+    if (ehdr.e_ident[EI_CLASS] != ELFCLASS64) {
+        ALOGW("Provided file is not ELF64");
+        return false;
+    }
+
+    // read the program headers from elf file
+    uint64_t programHeaderOffset = ehdr.e_phoff;
+    uint16_t programHeaderNum = ehdr.e_phnum;
+
+    IF_ALOGD() {
+        ALOGD("Punching holes in file: %s programHeaderOffset: %" PRIu64 " programHeaderNum: %hu",
+              filePath, programHeaderOffset, programHeaderNum);
+    }
+
+    // if this is a zip file, also consider elf offset inside a file
+    uint64_t phOffset;
+    if (__builtin_add_overflow(offset, programHeaderOffset, &phOffset)) {
+        ALOGE("Overflow occurred when calculating phOffset");
+        return false;
+    }
+    inputStream.seekg(phOffset);
+
+    std::vector<Elf64_Phdr> programHeaders;
+    for (int headerIndex = 0; headerIndex < programHeaderNum; headerIndex++) {
+        Elf64_Phdr header;
+        inputStream.read((char *)&header, sizeof(header));
+        if (!inputStream.good()) {
+            return false;
+        }
+
+        if (header.p_type != PT_LOAD) {
+            continue;
+        }
+        programHeaders.push_back(header);
+    }
+
+    return punchHoles(filePath, offset, programHeaders);
+}
+
+bool punchHolesInZip(const char *filePath, uint64_t offset, uint16_t extraFieldLen) {
+    android::base::unique_fd fd(open(filePath, O_RDWR | O_CLOEXEC));
+    if (!fd.ok()) {
+        ALOGE("Can't open file to punch %s", filePath);
+        return false;
+    }
+
+    struct stat64 beforePunch;
+    if (int result = lstat64(filePath, &beforePunch); result != 0) {
+        ALOGE("lstat64 failed for filePath %s, error:%d", filePath, errno);
+        return false;
+    }
+
+    uint64_t blockSize = beforePunch.st_blksize;
+    IF_ALOGD() {
+        ALOGD("Extra field length: %hu,  Size before punching holes st_blocks: %" PRIu64
+              ", st_blksize: %ld, st_size: %" PRIu64 "",
+              extraFieldLen, beforePunch.st_blocks, beforePunch.st_blksize,
+              static_cast<uint64_t>(beforePunch.st_size));
+    }
+
+    if (extraFieldLen < blockSize) {
+        ALOGD("Skipping punching apk as extra field length is less than block size");
+        return false;
+    }
+
+    // content is preceded by extra field. Zip offset is offset of exact content.
+    // move back by extraFieldLen so that scan can be started at start of extra field.
+    uint64_t extraFieldStart;
+    if (__builtin_sub_overflow(offset, extraFieldLen, &extraFieldStart)) {
+        ALOGE("Overflow occurred when calculating start of extra field");
+        return false;
+    }
+
+    constexpr uint64_t kMaxSize = 64 * 1024;
+    // Use malloc to gracefully handle any oom conditions
+    std::unique_ptr<uint8_t, decltype(&free)> buffer(static_cast<uint8_t *>(malloc(kMaxSize)),
+                                                     &free);
+    if (buffer == nullptr) {
+        ALOGE("Failed to allocate read buffer");
+        return false;
+    }
+
+    // Read the entire extra fields at once and punch file according to zero stretches.
+    if (!ReadFullyAtOffset(fd, buffer.get(), extraFieldLen, extraFieldStart)) {
+        ALOGE("Failed to read extra field content");
+        return false;
+    }
+
+    IF_ALOGD() {
+        ALOGD("Extra field length: %hu content near offset: %s", extraFieldLen,
+              HexString(buffer.get(), extraFieldLen).c_str());
+    }
+
+    uint64_t currentSize = 0;
+    while (currentSize < extraFieldLen) {
+        uint64_t end = currentSize;
+        // find zero ranges
+        while (end < extraFieldLen && *(buffer.get() + end) == 0) {
+            ++end;
+        }
+
+        uint64_t punchLen;
+        if (__builtin_sub_overflow(end, currentSize, &punchLen)) {
+            ALOGW("Overflow occurred when calculating punching length");
+            return false;
+        }
+
+        // Don't punch for every stretch of zero which is found
+        if (punchLen > blockSize) {
+            uint64_t punchOffset;
+            if (__builtin_add_overflow(extraFieldStart, currentSize, &punchOffset)) {
+                ALOGW("Overflow occurred when calculating punch start offset");
+                return false;
+            }
+
+            if (!punchWithBlockAlignment(fd, punchOffset, punchLen, blockSize)) {
+                return false;
+            }
+        }
+        currentSize = end;
+        ++currentSize;
+    }
+
+    IF_ALOGD() {
+        struct stat64 afterPunch;
+        if (int result = lstat64(filePath, &afterPunch); result != 0) {
+            ALOGD("lstat64 failed for filePath %s, error:%d", filePath, errno);
+            return false;
+        }
+        ALOGD("punchHolesInApk:: Size after punching holes st_blocks: %" PRIu64
+              ", st_blksize: %ld, st_size: %" PRIu64 "",
+              afterPunch.st_blocks, afterPunch.st_blksize,
+              static_cast<uint64_t>(afterPunch.st_size));
+    }
+    return true;
+}
+
+}; // namespace android
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.h b/core/jni/com_android_internal_content_FileSystemUtils.h
new file mode 100644
index 0000000..52445e2
--- /dev/null
+++ b/core/jni/com_android_internal_content_FileSystemUtils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <sys/types.h>
+
+namespace android {
+
+/*
+ * This function deallocates space used by zero padding at the end of LOAD segments in given
+ * uncompressed ELF file. Read ELF headers and find out the offset and sizes of LOAD segments.
+ * [fallocate(2)](http://man7.org/linux/man-pages/man2/fallocate.2.html) is used to deallocate the
+ * zero ranges at the end of LOAD segments. If ELF file is present inside of ApK/Zip file, offset to
+ * the start of the ELF file should be provided.
+ */
+bool punchHolesInElf64(const char* filePath, uint64_t offset);
+
+/*
+ * This function punches holes in zero segments of Apk file which are introduced during the
+ * alignment. Alignment tools add padding inside of extra field in local file header. punch holes in
+ * extra field for zero stretches till the actual file content.
+ */
+bool punchHolesInZip(const char* filePath, uint64_t offset, uint16_t extraFieldLen);
+
+} // namespace android
\ No newline at end of file
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 149e57a..9b8dab7 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
@@ -36,6 +37,7 @@
 
 #include <memory>
 
+#include "com_android_internal_content_FileSystemUtils.h"
 #include "core_jni_helpers.h"
 
 #define RS_BITCODE_SUFFIX ".bc"
@@ -144,8 +146,9 @@
 
     uint16_t method;
     off64_t offset;
-
-    if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, nullptr, &offset, &when, &crc)) {
+    uint16_t extraFieldLength;
+    if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, nullptr, &offset, &when, &crc,
+                               &extraFieldLength)) {
         ALOGE("Couldn't read zip entry info\n");
         return INSTALL_FAILED_INVALID_APK;
     }
@@ -169,6 +172,21 @@
             return INSTALL_FAILED_INVALID_APK;
         }
 
+#ifdef ENABLE_PUNCH_HOLES
+        // if library is uncompressed, punch hole in it in place
+        if (!punchHolesInElf64(zipFile->getZipFileName(), offset)) {
+            ALOGW("Failed to punch uncompressed elf file :%s inside apk : %s at offset: "
+                  "%" PRIu64 "",
+                  fileName, zipFile->getZipFileName(), offset);
+        }
+
+        // if extra field for this zip file is present with some length, possibility is that it is
+        // padding added for zip alignment. Punch holes there too.
+        if (!punchHolesInZip(zipFile->getZipFileName(), offset, extraFieldLength)) {
+            ALOGW("Failed to punch apk : %s at extra field", zipFile->getZipFileName());
+        }
+#endif // ENABLE_PUNCH_HOLES
+
         return INSTALL_SUCCEEDED;
     }
 
@@ -269,6 +287,25 @@
         return INSTALL_FAILED_CONTAINER_ERROR;
     }
 
+#ifdef ENABLE_PUNCH_HOLES
+    // punch extracted elf files as well. This will fail where compression is on (like f2fs) but it
+    // will be useful for ext4 based systems
+    struct statfs64 fsInfo;
+    int result = statfs64(localFileName, &fsInfo);
+    if (result < 0) {
+        ALOGW("Failed to stat file :%s", localFileName);
+    }
+
+    if (result == 0 && fsInfo.f_type == EXT4_SUPER_MAGIC) {
+        ALOGD("Punching extracted elf file %s on fs:%" PRIu64 "", fileName,
+              static_cast<uint64_t>(fsInfo.f_type));
+        if (!punchHolesInElf64(localFileName, 0)) {
+            ALOGW("Failed to punch extracted elf file :%s from apk : %s", fileName,
+                  zipFile->getZipFileName());
+        }
+    }
+#endif // ENABLE_PUNCH_HOLES
+
     ALOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName);
 
     return INSTALL_SUCCEEDED;
diff --git a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
index 76b05ea..b3c41df 100644
--- a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
+++ b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
@@ -55,6 +55,14 @@
     counter->setState(state, timestamp);
 }
 
+static void native_copyStatesFrom(jlong nativePtrTarget, jlong nativePtrSource) {
+    battery::LongArrayMultiStateCounter *counterTarget =
+            reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtrTarget);
+    battery::LongArrayMultiStateCounter *counterSource =
+            reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtrSource);
+    counterTarget->copyStatesFrom(*counterSource);
+}
+
 static void native_setValues(jlong nativePtr, jint state, jlong longArrayContainerNativePtr) {
     battery::LongArrayMultiStateCounter *counter =
             reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);
@@ -219,6 +227,8 @@
         // @CriticalNative
         {"native_setState", "(JIJ)V", (void *)native_setState},
         // @CriticalNative
+        {"native_copyStatesFrom", "(JJ)V", (void *)native_copyStatesFrom},
+        // @CriticalNative
         {"native_setValues", "(JIJ)V", (void *)native_setValues},
         // @CriticalNative
         {"native_updateValues", "(JJJ)V", (void *)native_updateValues},
diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h
index 637b823..23cedb8 100644
--- a/core/jni/include/android_runtime/android_view_Surface.h
+++ b/core/jni/include/android_runtime/android_view_Surface.h
@@ -19,6 +19,7 @@
 
 #include <android/native_window.h>
 #include <ui/PublicFormat.h>
+#include <utils/StrongPointer.h>
 
 #include "jni.h"
 
diff --git a/core/jni/platform/OWNERS b/core/jni/platform/OWNERS
new file mode 100644
index 0000000..10ce5cf
--- /dev/null
+++ b/core/jni/platform/OWNERS
@@ -0,0 +1,4 @@
+include /graphics/java/android/graphics/OWNERS
+
[email protected]
[email protected]
diff --git a/core/jni/platform/host/HostRuntime.cpp b/core/jni/platform/host/HostRuntime.cpp
new file mode 100644
index 0000000..0433855
--- /dev/null
+++ b/core/jni/platform/host/HostRuntime.cpp
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/graphics/jni_runtime.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/jni_macros.h>
+#include <unicode/putil.h>
+#include <unicode/udata.h>
+
+#include <clocale>
+#include <sstream>
+#include <unordered_map>
+#include <vector>
+
+#include "android_view_InputDevice.h"
+#include "core_jni_helpers.h"
+#include "jni.h"
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#endif
+
+#include <iostream>
+
+using namespace std;
+
+/*
+ * This is responsible for setting up the JNI environment for communication between
+ * the Java and native parts of layoutlib, including registering native methods.
+ * This is mostly achieved by copying the way it is done in the platform
+ * (see AndroidRuntime.cpp).
+ */
+
+static JavaVM* javaVM;
+static jclass bridge;
+static jclass layoutLog;
+static jmethodID getLogId;
+static jmethodID logMethodId;
+
+extern int register_android_os_Binder(JNIEnv* env);
+extern int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env);
+
+typedef void (*FreeFunction)(void*);
+
+static void NativeAllocationRegistry_Delegate_nativeApplyFreeFunction(JNIEnv*, jclass,
+                                                                      jlong freeFunction,
+                                                                      jlong ptr) {
+    void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
+    FreeFunction nativeFreeFunction =
+            reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
+    nativeFreeFunction(nativePtr);
+}
+
+static JNINativeMethod gMethods[] = {
+        NATIVE_METHOD(NativeAllocationRegistry_Delegate, nativeApplyFreeFunction, "(JJ)V"),
+};
+
+int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "libcore/util/NativeAllocationRegistry_Delegate", gMethods,
+                                    NELEM(gMethods));
+}
+
+namespace android {
+
+extern int register_android_animation_PropertyValuesHolder(JNIEnv* env);
+extern int register_android_content_AssetManager(JNIEnv* env);
+extern int register_android_content_StringBlock(JNIEnv* env);
+extern int register_android_content_XmlBlock(JNIEnv* env);
+extern int register_android_content_res_ApkAssets(JNIEnv* env);
+extern int register_android_database_CursorWindow(JNIEnv* env);
+extern int register_android_database_SQLiteConnection(JNIEnv* env);
+extern int register_android_database_SQLiteGlobal(JNIEnv* env);
+extern int register_android_database_SQLiteDebug(JNIEnv* env);
+extern int register_android_os_FileObserver(JNIEnv* env);
+extern int register_android_os_MessageQueue(JNIEnv* env);
+extern int register_android_os_Parcel(JNIEnv* env);
+extern int register_android_os_SystemClock(JNIEnv* env);
+extern int register_android_os_SystemProperties(JNIEnv* env);
+extern int register_android_os_Trace(JNIEnv* env);
+extern int register_android_text_AndroidCharacter(JNIEnv* env);
+extern int register_android_util_EventLog(JNIEnv* env);
+extern int register_android_util_Log(JNIEnv* env);
+extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
+extern int register_android_view_KeyCharacterMap(JNIEnv* env);
+extern int register_android_view_KeyEvent(JNIEnv* env);
+extern int register_android_view_InputDevice(JNIEnv* env);
+extern int register_android_view_MotionEvent(JNIEnv* env);
+extern int register_android_view_ThreadedRenderer(JNIEnv* env);
+extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env);
+extern int register_android_view_VelocityTracker(JNIEnv* env);
+extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv* env);
+
+#define REG_JNI(name) \
+    { name }
+struct RegJNIRec {
+    int (*mProc)(JNIEnv*);
+};
+
+// Map of all possible class names to register to their corresponding JNI registration function
+// pointer The actual list of registered classes will be determined at runtime via the
+// 'native_classes' System property
+static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = {
+        {"android.animation.PropertyValuesHolder",
+         REG_JNI(register_android_animation_PropertyValuesHolder)},
+#ifdef __linux__
+        {"android.content.res.ApkAssets", REG_JNI(register_android_content_res_ApkAssets)},
+        {"android.content.res.AssetManager", REG_JNI(register_android_content_AssetManager)},
+        {"android.database.CursorWindow", REG_JNI(register_android_database_CursorWindow)},
+        {"android.database.sqlite.SQLiteConnection",
+         REG_JNI(register_android_database_SQLiteConnection)},
+        {"android.database.sqlite.SQLiteGlobal", REG_JNI(register_android_database_SQLiteGlobal)},
+        {"android.database.sqlite.SQLiteDebug", REG_JNI(register_android_database_SQLiteDebug)},
+#endif
+        {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)},
+        {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)},
+#ifdef __linux__
+        {"android.os.Binder", REG_JNI(register_android_os_Binder)},
+        {"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)},
+        {"android.os.MessageQueue", REG_JNI(register_android_os_MessageQueue)},
+        {"android.os.Parcel", REG_JNI(register_android_os_Parcel)},
+#endif
+        {"android.os.SystemClock", REG_JNI(register_android_os_SystemClock)},
+        {"android.os.SystemProperties", REG_JNI(register_android_os_SystemProperties)},
+        {"android.os.Trace", REG_JNI(register_android_os_Trace)},
+        {"android.text.AndroidCharacter", REG_JNI(register_android_text_AndroidCharacter)},
+        {"android.util.EventLog", REG_JNI(register_android_util_EventLog)},
+        {"android.util.Log", REG_JNI(register_android_util_Log)},
+        {"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)},
+        {"android.view.KeyCharacterMap", REG_JNI(register_android_view_KeyCharacterMap)},
+        {"android.view.KeyEvent", REG_JNI(register_android_view_KeyEvent)},
+        {"android.view.InputDevice", REG_JNI(register_android_view_InputDevice)},
+        {"android.view.MotionEvent", REG_JNI(register_android_view_MotionEvent)},
+        {"android.view.VelocityTracker", REG_JNI(register_android_view_VelocityTracker)},
+        {"com.android.internal.util.VirtualRefBasePtr",
+         REG_JNI(register_com_android_internal_util_VirtualRefBasePtr)},
+        {"libcore.util.NativeAllocationRegistry_Delegate",
+         REG_JNI(register_libcore_util_NativeAllocationRegistry_Delegate)},
+};
+
+static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& jniRegMap,
+                              const vector<string>& classesToRegister, JNIEnv* env) {
+    for (const string& className : classesToRegister) {
+        if (jniRegMap.at(className).mProc(env) < 0) {
+            return -1;
+        }
+    }
+
+    if (register_android_graphics_classes(env) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className,
+                                          const JNINativeMethod* gMethods, int numMethods) {
+    return jniRegisterNativeMethods(env, className, gMethods, numMethods);
+}
+
+JNIEnv* AndroidRuntime::getJNIEnv() {
+    JNIEnv* env;
+    if (javaVM->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) return nullptr;
+    return env;
+}
+
+JavaVM* AndroidRuntime::getJavaVM() {
+    return javaVM;
+}
+
+static vector<string> parseCsv(const string& csvString) {
+    vector<string> result;
+    istringstream stream(csvString);
+    string segment;
+    while (getline(stream, segment, ',')) {
+        result.push_back(segment);
+    }
+    return result;
+}
+
+void LayoutlibLogger(base::LogId, base::LogSeverity severity, const char* tag, const char* file,
+                     unsigned int line, const char* message) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jint logPrio = severity;
+    jstring tagString = env->NewStringUTF(tag);
+    jstring messageString = env->NewStringUTF(message);
+
+    jobject bridgeLog = env->CallStaticObjectMethod(bridge, getLogId);
+
+    env->CallVoidMethod(bridgeLog, logMethodId, logPrio, tagString, messageString);
+
+    env->DeleteLocalRef(tagString);
+    env->DeleteLocalRef(messageString);
+    env->DeleteLocalRef(bridgeLog);
+}
+
+void LayoutlibAborter(const char* abort_message) {
+    // Layoutlib should not call abort() as it would terminate Studio.
+    // Throw an exception back to Java instead.
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jniThrowRuntimeException(env, "The Android framework has encountered a fatal error");
+}
+
+// This method has been copied/adapted from system/core/init/property_service.cpp
+// If the ro.product.cpu.abilist* properties have not been explicitly
+// set, derive them from ro.system.product.cpu.abilist* properties.
+static void property_initialize_ro_cpu_abilist() {
+    const std::string EMPTY = "";
+    const char* kAbilistProp = "ro.product.cpu.abilist";
+    const char* kAbilist32Prop = "ro.product.cpu.abilist32";
+    const char* kAbilist64Prop = "ro.product.cpu.abilist64";
+
+    // If the properties are defined explicitly, just use them.
+    if (base::GetProperty(kAbilistProp, EMPTY) != EMPTY) {
+        return;
+    }
+
+    std::string abilist32_prop_val;
+    std::string abilist64_prop_val;
+    const auto abilist32_prop = "ro.system.product.cpu.abilist32";
+    const auto abilist64_prop = "ro.system.product.cpu.abilist64";
+    abilist32_prop_val = base::GetProperty(abilist32_prop, EMPTY);
+    abilist64_prop_val = base::GetProperty(abilist64_prop, EMPTY);
+
+    // Merge ABI lists for ro.product.cpu.abilist
+    auto abilist_prop_val = abilist64_prop_val;
+    if (abilist32_prop_val != EMPTY) {
+        if (abilist_prop_val != EMPTY) {
+            abilist_prop_val += ",";
+        }
+        abilist_prop_val += abilist32_prop_val;
+    }
+
+    // Set these properties
+    const std::pair<const char*, const std::string&> set_prop_list[] = {
+            {kAbilistProp, abilist_prop_val},
+            {kAbilist32Prop, abilist32_prop_val},
+            {kAbilist64Prop, abilist64_prop_val},
+    };
+    for (const auto& [prop, prop_val] : set_prop_list) {
+        base::SetProperty(prop, prop_val);
+    }
+}
+
+static void* mmapFile(const char* dataFilePath) {
+#ifdef _WIN32
+    // Windows needs file path in wide chars to handle unicode file paths
+    int size = MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, NULL, 0);
+    std::vector<wchar_t> wideDataFilePath(size);
+    MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, wideDataFilePath.data(), size);
+    HANDLE file =
+            CreateFileW(wideDataFilePath.data(), GENERIC_READ, FILE_SHARE_READ, nullptr,
+                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, nullptr);
+    if ((HANDLE)INVALID_HANDLE_VALUE == file) {
+        return nullptr;
+    }
+
+    struct CloseHandleWrapper {
+        void operator()(HANDLE h) {
+            CloseHandle(h);
+        }
+    };
+    std::unique_ptr<void, CloseHandleWrapper> mmapHandle(
+            CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
+    if (!mmapHandle) {
+        return nullptr;
+    }
+    return MapViewOfFile(mmapHandle.get(), FILE_MAP_READ, 0, 0, 0);
+#else
+    int fd = open(dataFilePath, O_RDONLY);
+    if (fd == -1) {
+        return nullptr;
+    }
+
+    struct stat sb;
+    if (fstat(fd, &sb) == -1) {
+        close(fd);
+        return nullptr;
+    }
+
+    void* addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (addr == MAP_FAILED) {
+        close(fd);
+        return nullptr;
+    }
+
+    close(fd);
+    return addr;
+#endif
+}
+
+static bool init_icu(const char* dataPath) {
+    void* addr = mmapFile(dataPath);
+    UErrorCode err = U_ZERO_ERROR;
+    udata_setCommonData(addr, &err);
+    if (err != U_ZERO_ERROR) {
+        return false;
+    }
+    return true;
+}
+
+// Creates an array of InputDevice from key character map files
+static void init_keyboard(JNIEnv* env, const vector<string>& keyboardPaths) {
+    jclass inputDevice = FindClassOrDie(env, "android/view/InputDevice");
+    jobjectArray inputDevicesArray =
+            env->NewObjectArray(keyboardPaths.size(), inputDevice, nullptr);
+    int keyboardId = 1;
+
+    for (const string& path : keyboardPaths) {
+        base::Result<std::shared_ptr<KeyCharacterMap>> charMap =
+                KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE);
+
+        InputDeviceInfo info = InputDeviceInfo();
+        info.initialize(keyboardId, 0, 0, InputDeviceIdentifier(),
+                        "keyboard " + std::to_string(keyboardId), true, false, 0);
+        info.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+        info.setKeyCharacterMap(*charMap);
+
+        jobject inputDeviceObj = android_view_InputDevice_create(env, info);
+        if (inputDeviceObj) {
+            env->SetObjectArrayElement(inputDevicesArray, keyboardId - 1, inputDeviceObj);
+            env->DeleteLocalRef(inputDeviceObj);
+        }
+        keyboardId++;
+    }
+
+    if (bridge == nullptr) {
+        bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
+        bridge = MakeGlobalRefOrDie(env, bridge);
+    }
+    jmethodID setInputManager = GetStaticMethodIDOrDie(env, bridge, "setInputManager",
+                                                       "([Landroid/view/InputDevice;)V");
+    env->CallStaticVoidMethod(bridge, setInputManager, inputDevicesArray);
+    env->DeleteLocalRef(inputDevicesArray);
+}
+
+} // namespace android
+
+using namespace android;
+
+// Called right before aborting by LOG_ALWAYS_FATAL. Print the pending exception.
+void abort_handler(const char* abort_message) {
+    ALOGE("About to abort the process...");
+
+    JNIEnv* env = NULL;
+    if (javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("vm->GetEnv() failed");
+        return;
+    }
+    if (env->ExceptionOccurred() != NULL) {
+        ALOGE("Pending exception:");
+        env->ExceptionDescribe();
+    }
+    ALOGE("Aborting because: %s", abort_message);
+}
+
+JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
+    javaVM = vm;
+    JNIEnv* env = nullptr;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    __android_log_set_aborter(abort_handler);
+
+    init_android_graphics();
+
+    // Configuration is stored as java System properties.
+    // Get a reference to System.getProperty
+    jclass system = FindClassOrDie(env, "java/lang/System");
+    jmethodID getPropertyMethod =
+            GetStaticMethodIDOrDie(env, system, "getProperty",
+                                   "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+
+    // Java system properties that contain LayoutLib config. The initial values in the map
+    // are the default values if the property is not specified.
+    std::unordered_map<std::string, std::string> systemProperties =
+            {{"core_native_classes", ""},
+             {"register_properties_during_load", ""},
+             {"icu.data.path", ""},
+             {"use_bridge_for_logging", ""},
+             {"keyboard_paths", ""}};
+
+    for (auto& [name, defaultValue] : systemProperties) {
+        jstring propertyString =
+                (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
+                                                     env->NewStringUTF(name.c_str()),
+                                                     env->NewStringUTF(defaultValue.c_str()));
+        const char* propertyChars = env->GetStringUTFChars(propertyString, 0);
+        systemProperties[name] = string(propertyChars);
+        env->ReleaseStringUTFChars(propertyString, propertyChars);
+    }
+    // Get the names of classes that need to register their native methods
+    vector<string> classesToRegister = parseCsv(systemProperties["core_native_classes"]);
+
+    if (systemProperties["register_properties_during_load"] == "true") {
+        // Set the system properties first as they could be used in the static initialization of
+        // other classes
+        if (register_android_os_SystemProperties(env) < 0) {
+            return JNI_ERR;
+        }
+        classesToRegister.erase(find(classesToRegister.begin(), classesToRegister.end(),
+                                     "android.os.SystemProperties"));
+        bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
+        bridge = MakeGlobalRefOrDie(env, bridge);
+        jmethodID setSystemPropertiesMethod =
+                GetStaticMethodIDOrDie(env, bridge, "setSystemProperties", "()V");
+        env->CallStaticVoidMethod(bridge, setSystemPropertiesMethod);
+        property_initialize_ro_cpu_abilist();
+    }
+
+    if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) {
+        return JNI_ERR;
+    }
+
+    if (!systemProperties["icu.data.path"].empty()) {
+        // Set the location of ICU data
+        bool icuInitialized = init_icu(systemProperties["icu.data.path"].c_str());
+        if (!icuInitialized) {
+            return JNI_ERR;
+        }
+    }
+
+    if (systemProperties["use_bridge_for_logging"] == "true") {
+        layoutLog = FindClassOrDie(env, "com/android/ide/common/rendering/api/ILayoutLog");
+        layoutLog = MakeGlobalRefOrDie(env, layoutLog);
+        logMethodId = GetMethodIDOrDie(env, layoutLog, "logAndroidFramework",
+                                       "(ILjava/lang/String;Ljava/lang/String;)V");
+        if (bridge == nullptr) {
+            bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
+            bridge = MakeGlobalRefOrDie(env, bridge);
+        }
+        getLogId = GetStaticMethodIDOrDie(env, bridge, "getLog",
+                                          "()Lcom/android/ide/common/rendering/api/ILayoutLog;");
+        android::base::SetLogger(LayoutlibLogger);
+        android::base::SetAborter(LayoutlibAborter);
+    } else {
+        // initialize logging, so ANDROD_LOG_TAGS env variable is respected
+        android::base::InitLogging(nullptr, android::base::StderrLogger);
+    }
+
+    // Use English locale for number format to ensure correct parsing of floats when using strtof
+    setlocale(LC_NUMERIC, "en_US.UTF-8");
+
+    if (!systemProperties["keyboard_paths"].empty()) {
+        vector<string> keyboardPaths = parseCsv(systemProperties["keyboard_paths"]);
+        init_keyboard(env, keyboardPaths);
+    } else {
+        fprintf(stderr, "Skip initializing keyboard\n");
+    }
+
+    return JNI_VERSION_1_6;
+}
+
+JNIEXPORT void JNI_OnUnload(JavaVM* vm, void*) {
+    JNIEnv* env = nullptr;
+    vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
+    env->DeleteGlobalRef(bridge);
+    env->DeleteGlobalRef(layoutLog);
+}
diff --git a/core/jni/platform/host/native_window_jni.cpp b/core/jni/platform/host/native_window_jni.cpp
new file mode 100644
index 0000000..c17c480
--- /dev/null
+++ b/core/jni/platform/host/native_window_jni.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+#include <android_runtime/android_view_Surface.h>
+#include <system/window.h>
+#include <utils/StrongPointer.h>
+
+using namespace android;
+
+ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) {
+    sp<ANativeWindow> win = android_view_Surface_getNativeWindow(env, surface);
+    if (win != NULL) {
+        ANativeWindow_acquire(win.get());
+    }
+    return win.get();
+}
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index b900fa6..b51f72d 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -11,7 +11,6 @@
 # Frameworks
 [email protected]
 [email protected]
[email protected]
 [email protected]
 per-file package_item_info.proto = file:/PACKAGE_MANAGER_OWNERS
 per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS
diff --git a/core/proto/android/app/profilerinfo.proto b/core/proto/android/app/profilerinfo.proto
index 86261ec..9941b83 100644
--- a/core/proto/android/app/profilerinfo.proto
+++ b/core/proto/android/app/profilerinfo.proto
@@ -36,4 +36,5 @@
     // Denotes an agent (and its parameters) to attach for profiling.
     optional string agent = 6;
     optional int32 clock_type = 7;
+    optional int32 profiler_output_version = 8;
 }
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 5ae365c..f5bbbb4 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -103,6 +103,7 @@
         optional SettingProto accessibility_pinch_to_zoom_anywhere_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto accessibility_single_finger_panning_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto accessibility_floating_menu_targets = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto display_daltonizer_saturation_level = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     }
     optional Accessibility accessibility = 2;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f743299..567844c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -581,6 +581,7 @@
 
     <protected-broadcast android:name="android.app.action.KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED" />
     <protected-broadcast android:name="NotificationManagerService.TIMEOUT" />
+    <protected-broadcast android:name="com.android.server.notification.TimeToLiveHelper" />
     <protected-broadcast android:name="NotificationHistoryDatabase.CLEANUP" />
     <protected-broadcast android:name="ScheduleConditionProvider.EVALUATE" />
     <protected-broadcast android:name="EventConditionProvider.EVALUATE" />
@@ -2593,6 +2594,13 @@
     <permission android:name="android.permission.VIBRATE_ALWAYS_ON"
         android:protectionLevel="signature" />
 
+    <!-- Allows access to system-only haptic feedback constants.
+         <p>Protection level: signature
+         @hide
+    -->
+    <permission android:name="android.permission.VIBRATE_SYSTEM_CONSTANTS"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows access to the vibrator state.
          <p>Protection level: signature
          @hide
@@ -3242,7 +3250,7 @@
 
     <!-- @SystemApi @hide Allows privileged applications to get details about hidden profile
         users.
-        @FlaggedApi("android.multiuser.flags.enable_permission_to_access_hidden_profiles") -->
+        @FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles") -->
     <permission
         android:name="android.permission.ACCESS_HIDDEN_PROFILES_FULL"
         android:protectionLevel="signature|privileged" />
@@ -3889,6 +3897,13 @@
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL"
                 android:protectionLevel="internal|role" />
 
+    <!-- Allows the holder to manage and retrieve max storage limit for admin policies. This
+        permission is only grantable on rooted devices.
+        @TestAPI
+        @hide -->
+    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT"
+                android:protectionLevel="internal" />
+
     <!-- Allows an application to access EnhancedConfirmationManager.
         @SystemApi
         @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled")
@@ -5875,7 +5890,7 @@
     <!-- Allows an application to subscribe to notifications about the nearby devices' presence
          status change base on the UUIDs.
          <p>Not for use by third-party applications.</p>
-         @FlaggedApi("android.companion.flags.device_presence")
+         @FlaggedApi("android.companion.device_presence")
     -->
     <permission android:name="android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE"
                 android:protectionLevel="signature|privileged" />
@@ -7970,17 +7985,6 @@
     <permission android:name="android.permission.RUN_USER_INITIATED_JOBS"
                 android:protectionLevel="normal"/>
 
-    <!-- @FlaggedApi("android.app.job.backup_jobs_exemption")
-         Gives applications with a <b>major use case</b> of backing-up or syncing content increased
-         job execution allowance in order to complete the related work. The jobs must have a valid
-         content URI trigger and network constraint set.
-         <p>This is a special access permission that can be revoked by the system or the user.
-         <p>Protection level: signature|privileged|appop
-         @hide
-     -->
-    <permission android:name="android.permission.RUN_BACKUP_JOBS"
-                android:protectionLevel="signature|privileged|appop"/>
-
     <!-- Allows an app access to the installer provided app metadata.
         @SystemApi
         @hide
@@ -8167,6 +8171,15 @@
     <permission android:name="android.permission.SCREEN_TIMEOUT_OVERRIDE"
                 android:protectionLevel="signature" />
 
+    <!-- @SystemApi
+        @FlaggedApi("android.security.fsverity_api")
+        Allows app to setup fs-verity through FileIntegrityManager.
+        <p>Protection level: signature|privileged
+        @hide
+    -->
+    <permission android:name="android.permission.SETUP_FSVERITY"
+                android:protectionLevel="signature|privileged"/>
+
     <!-- Attribution for Geofencing service. -->
     <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
     <!-- Attribution for Country Detector. -->
@@ -8400,9 +8413,11 @@
                 android:process=":ui">
         </activity>
 
+        <!-- BlockedAppStreamingActivity is launched as the system user. -->
         <activity android:name="com.android.internal.app.BlockedAppStreamingActivity"
             android:theme="@style/Theme.Dialog.Confirmation"
             android:excludeFromRecents="true"
+            android:showForAllUsers="true"
             android:process=":ui">
         </activity>
 
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 4e61ff2..3489cac 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -4,7 +4,6 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
@@ -49,7 +48,7 @@
 # Wear
 per-file res/*-watch/* = file:/WEAR_OWNERS
 
-# Peformance
+# Performance
 per-file res/values/config.xml = file:/PERFORMANCE_OWNERS
 per-file res/values/symbols.xml = file:/PERFORMANCE_OWNERS
 
@@ -63,3 +62,11 @@
 
 # TV Input Framework
 per-file res/values/config_tv_external_input_logging.xml = file:/services/core/java/com/android/server/tv/OWNERS
+
+# SysUi Color Team
+per-file res/values/colors.xml = [email protected]
+per-file res/values/attrs.xml = [email protected]
+per-file res/values/styles.xml = [email protected]
+per-file res/values/symbols.xml = [email protected]
+per-file res/values/themes_device_defaults.xml = [email protected]
+per-file res/values/styles_material.xml = [email protected]
\ No newline at end of file
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index f3acab0..822aa22 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -14,185 +14,101 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:aapt="http://schemas.android.com/aapt"
     android:width="512dp"
     android:height="512dp"
     android:viewportWidth="512"
     android:viewportHeight="512">
+  <!-- space -->
   <path
-      android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0">
-    <aapt:attr name="android:fillColor">
-      <gradient 
-          android:startX="256"
-          android:startY="21.81"
-          android:endX="256"
-          android:endY="350.42"
-          android:type="linear">
-        <item android:offset="0" android:color="#FF073042"/>
-        <item android:offset="1" android:color="#FF073042"/>
-      </gradient>
-    </aapt:attr>
-  </path>
+      android:pathData="M256,446.36C229.63,446.36 212.19,428.06 194.8,397.94C177.41,367.82 91.54,219.08 74.14,188.96C56.75,158.84 49.63,134.59 62.81,111.75C76,88.91 100.56,82.95 135.35,82.95C170.13,82.95 341.87,82.95 376.65,82.95C411.44,82.95 436,88.91 449.19,111.75C462.37,134.59 455.25,158.84 437.86,188.96C420.46,219.08 334.59,367.82 317.2,397.94C299.81,428.06 282.37,446.36 256,446.36H256Z"
+      android:fillColor="#202124"/>
   <group>
     <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M256,446.36C229.63,446.36 212.19,428.06 194.8,397.94C177.41,367.82 91.54,219.08 74.14,188.96C56.75,158.84 49.63,134.59 62.81,111.75C76,88.91 100.56,82.95 135.35,82.95C170.13,82.95 341.87,82.95 376.65,82.95C411.44,82.95 436,88.91 449.19,111.75C462.37,134.59 455.25,158.84 437.86,188.96C420.46,219.08 334.59,367.82 317.2,397.94C299.81,428.06 282.37,446.36 256,446.36H256Z"/>
+    <!-- thrust plume -->
     <path
-        android:pathData="m195.27,187.64l2.25,-6.69c13.91,78.13 50.84,284.39 50.84,50.33 0,-0.97 0.72,-1.81 1.62,-1.81h12.69c0.9,0 1.62,0.83 1.62,1.8 -0.2,409.91 -69.03,-43.64 -69.03,-43.64Z"
-        android:fillColor="#3ddc84"/>
+        android:pathData="M253,153C249.82,187.48 225.67,262.17 167.98,285.04C110.3,307.92 73.96,318.12 63,320.36L256,399L449,320.36C438.04,318.12 401.7,307.92 344.02,285.04C286.33,262.17 262.18,187.48 259,153H256H253Z"
+        android:fillColor="#C6FF00"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M253,153C251.5,187.42 241.7,261.98 214.5,284.82C187.3,307.65 170.17,317.84 165,320.08L256,398.58L347,320.08C341.83,317.84 324.7,307.65 297.5,284.82C270.3,261.98 260.5,187.42 259,153H256H253Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M256,153m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
+        android:fillColor="#ffffff"/>
+    <!-- android head and body -->
+    <path
+        android:pathData="M151,350h199v104h-199z"
+        android:fillColor="#5F6368"/>
+    <path
+        android:pathData="M358.42,350.44C358.36,350.02 358.29,349.6 358.22,349.18C357.8,346.6 357.27,344.04 356.65,341.52C355.57,337.12 354.21,332.82 352.59,328.66C351.22,325.13 349.66,321.7 347.93,318.38C345.7,314.11 343.18,310.01 340.41,306.11C337.01,301.34 333.21,296.86 329.06,292.74C327.32,291.01 325.52,289.34 323.65,287.73C319.62,284.26 315.32,281.09 310.78,278.26C310.82,278.19 310.85,278.12 310.89,278.05C312.97,274.46 315.05,270.88 317.13,267.29C319.17,263.78 321.2,260.28 323.23,256.77C324.69,254.26 326.15,251.74 327.61,249.22C327.95,248.62 328.22,248.01 328.43,247.37C329,245.61 329.02,243.76 328.57,242.03C328.45,241.61 328.31,241.19 328.14,240.78C327.97,240.38 327.77,239.98 327.54,239.6C326.76,238.29 325.65,237.16 324.26,236.33C323.02,235.6 321.64,235.16 320.23,235.03C319.64,234.98 319.04,234.99 318.45,235.05C317.96,235.1 317.47,235.19 316.99,235.32C315.26,235.77 313.67,236.72 312.42,238.08C311.98,238.57 311.58,239.12 311.23,239.71C309.77,242.23 308.31,244.75 306.85,247.27L300.76,257.78C298.68,261.37 296.6,264.96 294.52,268.55C294.29,268.94 294.06,269.33 293.83,269.73C293.52,269.6 293.21,269.48 292.89,269.36C281.43,264.99 269,262.6 256.01,262.6C255.65,262.6 255.3,262.6 254.94,262.6C243.39,262.72 232.29,264.73 221.93,268.33C220.73,268.75 219.55,269.19 218.38,269.65C218.16,269.29 217.95,268.92 217.74,268.55C215.66,264.96 213.58,261.38 211.5,257.79C209.47,254.28 207.43,250.78 205.4,247.27C203.94,244.76 202.48,242.23 201.02,239.72C200.68,239.12 200.28,238.58 199.83,238.09C198.59,236.72 196.99,235.78 195.27,235.32C194.79,235.2 194.3,235.1 193.81,235.05C193.22,234.99 192.62,234.99 192.03,235.04C190.61,235.16 189.23,235.6 188,236.34C186.6,237.16 185.5,238.3 184.71,239.6C184.49,239.99 184.29,240.38 184.12,240.79C183.95,241.2 183.8,241.61 183.69,242.04C183.23,243.76 183.26,245.62 183.82,247.38C184.03,248.01 184.3,248.63 184.65,249.23C186.11,251.74 187.57,254.26 189.02,256.78C191.06,260.28 193.09,263.79 195.12,267.29C197.2,270.88 199.28,274.47 201.36,278.06C201.38,278.09 201.4,278.12 201.41,278.15C197.22,280.76 193.23,283.64 189.47,286.8C187.21,288.69 185.04,290.68 182.96,292.75C178.81,296.87 175.01,301.35 171.6,306.12C168.82,310.02 166.31,314.11 164.09,318.39C162.35,321.71 160.79,325.14 159.42,328.67C157.8,332.83 156.44,337.13 155.36,341.53C154.75,344.05 154.22,346.6 153.79,349.19C153.72,349.61 153.66,350.03 153.59,350.45C153.36,351.95 153.16,353.46 153,354.98L359,354.98C358.84,353.46 358.64,351.95 358.41,350.45L358.42,350.44Z"
+        android:fillColor="#5F6368"/>
   </group>
+  <!-- stars -->
   <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
     <path
-        android:pathData="m158.77,180.68l-33.17,57.45c-1.9,3.3 -0.77,7.52 2.53,9.42 3.3,1.9 7.52,0.77 9.42,-2.53l33.59,-58.17c54.27,24.33 116.34,24.33 170.61,0l33.59,58.17c1.97,3.26 6.21,4.3 9.47,2.33 3.17,-1.91 4.26,-5.99 2.47,-9.23l-33.16,-57.45c56.95,-30.97 95.91,-88.64 101.61,-156.76H57.17c5.7,68.12 44.65,125.79 101.61,156.76Z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M131.04,134.34H127V138.38H131.04V134.34Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M250.26,187.66L262.17,187.66A2.13,2.13 0,0 1,264.3 189.78L264.3,217.85A2.13,2.13 0,0 1,262.17 219.98L250.26,219.98A2.13,2.13 0,0 1,248.14 217.85L248.14,189.78A2.13,2.13 0,0 1,250.26 187.66z"
-        android:fillColor="#3ddc84"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M167.04,256H163V260.04H167.04V256Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M250.12,170.29L262.32,170.29A1.98,1.98 0,0 1,264.3 172.26L264.3,176.39A1.98,1.98 0,0 1,262.32 178.37L250.12,178.37A1.98,1.98 0,0 1,248.14 176.39L248.14,172.26A1.98,1.98 0,0 1,250.12 170.29z"
-        android:fillColor="#3ddc84"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M373.49,127H369.45V131.04H373.49V127Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M171.92,216.82h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M292.04,226H288V230.04H292.04V226Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M188.8,275.73h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M319.04,186.91H315V190.95H319.04V186.91Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M369.04,337.63h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M355.04,222H351V226.04H355.04V222Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M285.93,252.22h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M192.04,136H188V140.04H192.04V136Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M318.96,218.84h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M336.08,196H328V204.08H336.08V196Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M294.05,288.55h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M222.04,212H218V216.04H222.04V212Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M330.82,273.31h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M163.08,175H155V183.08H163.08V175Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M188.8,298.95h4.04v4.04h-4.04z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M211.08,143H203V151.08H211.08V143Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M220.14,238.94h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M369.08,204H361V212.08H369.08V204Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M272.1,318.9h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M169.21,204.34H161.13V212.42H169.21V204.34Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M293.34,349.25h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+        android:pathData="M383.04,160.07H374.95V168.15H383.04V160.07Z"
+        android:fillColor="#ffffff"/>
     <path
-        android:pathData="M161.05,254.24h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
+        android:pathData="M192.08,183H184V191.08H192.08V183Z"
+        android:fillColor="#ffffff"/>
   </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
-    <path
-        android:pathData="M378.92,192h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
-  </group>
-  <group>
-    <clip-path
-        android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
-    <path
-        android:pathData="M137.87,323.7h8.08v8.08h-8.08z"
-        android:fillColor="#fff"/>
-  </group>
+  <!-- patch frame -->
   <path
-      android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"
-      android:strokeWidth="56.561"
+      android:pathData="M256,446.36C229.63,446.36 212.19,428.06 194.8,397.94C177.41,367.82 91.54,219.08 74.14,188.96C56.75,158.84 49.63,134.59 62.81,111.75C76,88.91 100.56,82.95 135.35,82.95C170.13,82.95 341.87,82.95 376.65,82.95C411.44,82.95 436,88.91 449.19,111.75C462.37,134.59 455.25,158.84 437.86,188.96C420.46,219.08 334.59,367.82 317.2,397.94C299.81,428.06 282.37,446.36 256,446.36H256Z"
+      android:strokeWidth="55"
       android:fillColor="#00000000"
-      android:strokeColor="#f86734"/>
+      android:strokeColor="#34A853"/>
+  <!-- text: ANDROID -->
   <path
-      android:pathData="m256.22,126.57c-6.69,0 -12.12,5.27 -12.12,11.77v14.52c0,1.25 1.02,2.27 2.27,2.27h0c1.25,0 2.27,-1.02 2.27,-2.27v-3.91c0,-2.51 2.04,-4.55 4.55,-4.55h6.06c2.51,0 4.55,2.04 4.55,4.55v3.91c0,1.25 1.02,2.27 2.27,2.27s2.27,-1.02 2.27,-2.27v-14.52c0,-6.5 -5.43,-11.77 -12.12,-11.77Z"
-      android:fillColor="#3ddc84"/>
+      android:pathData="M170.11,92.71C170.97,94.9 171.41,96 171.41,96C171.41,96 170.37,96 168.29,96C166.22,96 165.18,96 165.18,96C165.18,96 164.93,95.27 164.42,93.82L159.71,80.63L158.82,77.75H158.61L157.82,80.63L153.28,93.82C152.82,95.27 152.6,96 152.6,96C152.6,96 151.54,96 149.43,96C147.33,96 146.28,96 146.28,96C146.28,96 146.7,94.89 147.56,92.67L155.21,72.87C155.89,71.07 156.23,70.17 156.23,70.17C156.23,70.17 157.06,70.17 158.72,70.17C160.52,70.17 161.42,70.17 161.42,70.17C161.42,70.17 161.76,71.07 162.46,72.87L170.11,92.71ZM166.04,91.12H158.64V86.91H164.42L166.04,91.12ZM158.64,91.12H151.08L152.63,86.91H158.64V91.12ZM203.85,93.46C203.85,95.15 203.85,96 203.85,96C203.85,96 202.95,96 201.15,96C199.38,96 198.5,96 198.5,96C198.5,96 198.03,95.26 197.08,93.79L188.08,79.75H187.88L188.01,83.45V93.25C188.01,95.08 188.01,96 188.01,96C188.01,96 187.03,96 185.09,96C183.15,96 182.17,96 182.17,96C182.17,96 182.17,95.08 182.17,93.25L182.16,73.9C182.16,71.45 182.16,70.22 182.16,70.22C182.16,70.22 183.19,70.22 185.25,70.22C187.24,70.22 188.24,70.22 188.24,70.22C188.24,70.22 188.7,70.96 189.63,72.42L198.16,85.85H198.36L198.21,82.09V72.89C198.21,71.11 198.21,70.22 198.21,70.22C198.21,70.22 199.15,70.22 201.04,70.22C202.91,70.22 203.85,70.22 203.85,70.22C203.85,70.22 203.85,71.11 203.85,72.89V93.46ZM226.52,96H220.17C218.24,96 217.27,96 217.27,96C217.27,96 217.27,95.02 217.27,93.05V73.19C217.27,71.21 217.27,70.22 217.27,70.22C217.27,70.22 218.24,70.22 220.17,70.22H226.52C230.46,70.22 233.63,71.41 236.03,73.77C238.43,76.12 239.63,79.23 239.63,83.09C239.63,86.98 238.43,90.11 236.03,92.47C233.63,94.82 230.46,96 226.52,96ZM223.17,75.64V90.74H226.18C228.46,90.77 230.27,90.11 231.62,88.78C232.96,87.44 233.63,85.57 233.63,83.17C233.63,80.78 232.96,78.93 231.62,77.62C230.28,76.3 228.47,75.64 226.18,75.64H223.17ZM257.51,93.23C257.51,95.08 257.51,96 257.51,96C257.51,96 256.54,96 254.6,96C252.66,96 251.7,96 251.7,96C251.7,96 251.7,95.09 251.7,93.26V73.19C251.7,71.21 251.7,70.22 251.7,70.22C251.7,70.22 252.66,70.22 254.6,70.22H261.89C264.44,70.22 266.6,70.98 268.35,72.49C270.1,74 270.98,76.03 270.98,78.56C270.98,80.9 270.14,82.83 268.47,84.35C266.81,85.87 264.65,86.62 262.01,86.62H254.02V82.41H261.33C262.4,82.41 263.29,82.08 264.01,81.42C264.73,80.75 265.09,79.88 265.09,78.81C265.09,77.84 264.74,77.03 264.05,76.38C263.35,75.72 262.49,75.39 261.47,75.39H257.51V93.23ZM264.77,93.82L258.66,84.46L264.8,84.25L271.23,93.62C272.37,95.21 272.94,96 272.94,96C272.94,96 271.82,96 269.57,96C267.3,96 266.17,96 266.17,96C266.17,96 265.7,95.27 264.77,93.82ZM296.04,96.58C292.33,96.58 289.16,95.33 286.52,92.85C283.89,90.37 282.58,87.11 282.58,83.09C282.58,79.07 283.9,75.83 286.54,73.36C289.19,70.88 292.36,69.65 296.04,69.65C299.71,69.65 302.87,70.9 305.51,73.41C308.16,75.91 309.49,79.13 309.49,83.09C309.49,87.03 308.17,90.26 305.53,92.8C302.9,95.32 299.74,96.58 296.04,96.58ZM296.04,90.83C298.19,90.83 299.98,90.1 301.41,88.64C302.85,87.17 303.57,85.33 303.57,83.09C303.57,80.84 302.84,78.99 301.39,77.55C299.95,76.11 298.17,75.39 296.04,75.39C293.92,75.39 292.13,76.12 290.68,77.57C289.24,79.01 288.52,80.85 288.52,83.09C288.52,85.35 289.23,87.2 290.66,88.66C292.1,90.11 293.89,90.83 296.04,90.83ZM327.64,93.05C327.64,95.02 327.64,96 327.64,96C327.64,96 326.63,96 324.61,96C322.59,96 321.57,96 321.57,96C321.57,96 321.57,95.02 321.57,93.05V73.18C321.57,71.21 321.57,70.22 321.57,70.22C321.57,70.22 322.58,70.22 324.6,70.22C326.63,70.22 327.64,70.22 327.64,70.22C327.64,70.22 327.64,71.21 327.64,73.18V93.05ZM350.31,96H343.96C342.03,96 341.06,96 341.06,96C341.06,96 341.06,95.02 341.06,93.05V73.19C341.06,71.21 341.06,70.22 341.06,70.22C341.06,70.22 342.03,70.22 343.96,70.22H350.31C354.25,70.22 357.42,71.41 359.82,73.77C362.22,76.12 363.42,79.23 363.42,83.09C363.42,86.98 362.22,90.11 359.82,92.47C357.42,94.82 354.25,96 350.31,96ZM346.96,75.64V90.74H349.97C352.25,90.77 354.06,90.11 355.41,88.78C356.75,87.44 357.42,85.57 357.42,83.17C357.42,80.78 356.75,78.93 355.41,77.62C354.07,76.3 352.26,75.64 349.97,75.64H346.96Z"
+      android:fillColor="#E9F3EB"/>
+  <!-- text: 15 -->
   <path
-      android:pathData="m93.34,116.36l3.85,-4.36 29.64,9.76 -4.44,5.03 -6.23,-2.1 -7.86,8.91 2.86,5.92 -4.43,5.03 -13.39,-28.18ZM110.43,122.76l-8.86,-3.02 4.11,8.41 4.76,-5.39Z"
-      android:fillColor="#fff"/>
+      android:pathData="M236.59,363.25C236.59,365.75 236.59,367 236.59,367C236.59,367 235.32,367 232.79,367C230.32,367 229.09,367 229.09,367C229.09,367 229.09,365.75 229.09,363.25V305.85L216.64,314.75C215,315.92 214.19,316.5 214.19,316.5C214.19,316.5 213.54,315.5 212.24,313.5C210.97,311.6 210.34,310.65 210.34,310.65C210.34,310.62 211.2,309.98 212.94,308.75L227.64,298.2C230.3,296.23 231.64,295.25 231.64,295.25C231.64,295.25 232.1,295.25 233.04,295.25C235.4,295.25 236.59,295.25 236.59,295.25C236.59,295.25 236.59,296.47 236.59,298.9V363.25ZM247.09,330L251.19,299C251.52,296.6 251.69,295.4 251.69,295.4C251.69,295.4 252.77,295.4 254.94,295.4H284.54C286.97,295.4 288.19,295.4 288.19,295.4C288.19,295.4 288.19,296.58 288.19,298.95C288.19,301.48 288.19,302.75 288.19,302.75C288.19,302.75 286.97,302.75 284.54,302.75H257.49L254.19,327.45L254.39,327.5C256.09,325.77 258.27,324.38 260.94,323.35C263.61,322.28 266.65,321.75 270.09,321.75C276.55,321.75 281.99,323.97 286.39,328.4C290.79,332.8 292.99,338.32 292.99,344.95C292.99,351.75 290.8,357.4 286.44,361.9C282.11,366.37 276.42,368.6 269.39,368.6C263.09,368.6 257.77,367 253.44,363.8C249.1,360.6 246.26,356.85 244.89,352.55C244.26,350.32 243.94,349.2 243.94,349.2C243.94,349.2 245.09,348.77 247.39,347.9C249.79,347 250.99,346.55 250.99,346.55C250.99,346.55 251.3,347.73 251.94,350.1C252.8,352.73 254.71,355.27 257.64,357.7C260.61,360.13 264.44,361.35 269.14,361.35C274.27,361.35 278.24,359.88 281.04,356.95C283.84,353.98 285.24,350.03 285.24,345.1C285.24,340.37 283.67,336.52 280.54,333.55C277.44,330.58 273.4,329.1 268.44,329.1C265.47,329.1 262.95,329.52 260.89,330.35C258.82,331.15 257.09,332.28 255.69,333.75C254.39,335.25 253.74,336 253.74,336C253.74,336 252.55,335.52 250.19,334.55C247.85,333.62 246.69,333.15 246.69,333.15C246.69,333.15 246.82,332.1 247.09,330Z"
+      android:fillColor="#E9F3EB"/>
+  <!-- spacecraft -->
   <path
-      android:pathData="m153.62,100.85l-21.71,-6.2 10.38,14.38 -5.21,3.76 -16.78,-23.26 4.49,-3.24 21.65,6.19 -10.35,-14.35 5.24,-3.78 16.78,23.26 -4.49,3.24Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m161.46,63.15l8.99,-3.84c7.43,-3.18 15.96,0.12 19.09,7.44 3.13,7.32 -0.38,15.76 -7.81,18.94l-8.99,3.84 -11.28,-26.38ZM179.41,80.26c4.46,-1.91 5.96,-6.72 4.15,-10.96 -1.81,-4.24 -6.33,-6.48 -10.79,-4.57l-3.08,1.32 6.64,15.53 3.08,-1.32Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m204.23,47.57l11.1,-2.2c5.31,-1.05 9.47,2.08 10.4,6.76 0.72,3.65 -0.76,6.37 -4.07,8.34l12.4,10.44 -7.57,1.5 -11.65,-9.76 -1.03,0.2 2.3,11.61 -6.3,1.25 -5.57,-28.14ZM216.78,56.7c1.86,-0.37 3,-1.71 2.68,-3.33 -0.34,-1.7 -1.88,-2.43 -3.74,-2.06l-4.04,0.8 1.07,5.39 4.04,-0.8Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m244.29,55.6c0.13,-8.16 6.86,-14.72 15.06,-14.58 8.16,0.13 14.72,6.9 14.58,15.06s-6.91,14.72 -15.06,14.58c-8.2,-0.13 -14.71,-6.9 -14.58,-15.06ZM267.44,55.98c0.08,-4.64 -3.54,-8.66 -8.18,-8.74 -4.68,-0.08 -8.42,3.82 -8.5,8.47 -0.08,4.65 3.54,8.66 8.22,8.74 4.64,0.08 8.39,-3.82 8.46,-8.47Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m294.39,44.84l6.31,1.23 -5.49,28.16 -6.31,-1.23 5.49,-28.16Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m321.94,51.41l9.14,3.48c7.55,2.88 11.39,11.17 8.56,18.61 -2.83,7.44 -11.22,11.07 -18.77,8.19l-9.14,-3.48 10.22,-26.8ZM322.96,76.19c4.53,1.73 8.95,-0.69 10.6,-5 1.64,-4.3 -0.05,-9.06 -4.58,-10.78l-3.13,-1.19 -6.01,15.78 3.13,1.19Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m381.41,89.24l-4.21,-3.21 3.65,-4.78 9.06,6.91 -17.4,22.81 -4.85,-3.7 13.75,-18.02Z"
-      android:fillColor="#fff"/>
-  <path
-      android:pathData="m397.96,126.37l-9.56,-10.26 3.61,-3.36 22.8,-1.25 3.74,4.02 -12.35,11.51 2.51,2.69 -4.08,3.8 -2.51,-2.69 -4.55,4.24 -4.16,-4.46 4.55,-4.24ZM407.83,117.17l-10.28,0.58 4.49,4.82 5.79,-5.4Z"
-      android:fillColor="#fff"/>
+      android:pathData="M256.12,121C249.43,121 244,126.27 244,132.77V147.29C244,148.54 245.02,149.56 246.27,149.56C247.53,149.56 248.55,148.55 248.55,147.29V143.38C248.55,140.87 250.58,138.83 253.09,138.83H259.15C261.66,138.83 263.7,140.87 263.7,143.38V147.29C263.7,148.54 264.71,149.56 265.97,149.56C267.23,149.56 268.24,148.55 268.24,147.29V132.77C268.24,126.27 262.82,121 256.12,121H256.12Z"
+      android:fillColor="#E9F3EB"/>
 </vector>
-
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 53a6836..8ae2a9b 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2023 The Android Open Source Project
+Copyright (C) 2024 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -19,36 +19,20 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
+  <group>
+    <clip-path
+        android:pathData="M12,20.923C10.764,20.923 9.946,20.065 9.131,18.653C8.316,17.241 4.291,10.269 3.476,8.857C2.66,7.445 2.326,6.309 2.944,5.238C3.563,4.167 4.714,3.888 6.344,3.888C7.975,3.888 16.025,3.888 17.656,3.888C19.286,3.888 20.437,4.167 21.056,5.238C21.674,6.309 21.34,7.445 20.524,8.857C19.709,10.269 15.684,17.241 14.869,18.653C14.054,20.065 13.236,20.923 12,20.923H12Z"/>
     <path
-        android:name="ring"
-        android:pathData="M 12 21 C 16.971 21 21 16.971 21 12 C 21 7.029 16.971 3 12 3 C 7.029 3 3 7.029 3 12 C 3 16.971 7.029 21 12 21 Z"
-        android:fillColor="#00000000"
-        android:strokeColor="#ffffff"
-        android:strokeWidth="2"/>
-    <group android:name="group">
-        <clip-path
-            android:pathData="M 20.5 12 C 20.5 16.694 16.694 20.5 12 20.5 C 7.306 20.5 3.5 16.694 3.5 12 C 3.5 7.306 7.306 3.5 12 3.5 C 16.694 3.5 20.5 7.306 20.5 12 Z"/>
-        <path
-            android:pathData="M 14.812 9.023 C 13.014 9.707 11.027 9.707 9.229 9.023 L 8.265 10.693 C 8.06 11.048 7.605 11.17 7.25 10.964 C 6.895 10.759 6.773 10.305 6.978 9.949 L 7.899 8.355 C 5.988 7.137 4.702 5.084 4.502 2.695 L 4.456 2.153 L 19.584 2.153 L 19.539 2.695 C 19.339 5.084 18.052 7.137 16.142 8.355 L 17.067 9.958 C 17.259 10.307 17.142 10.746 16.801 10.952 C 16.45 11.165 15.993 11.052 15.781 10.701 L 15.775 10.693 L 14.812 9.023 Z"
-            android:fillColor="#ffffff"/>
-        <group android:name="stars">
-            <path android:pathData="
-                M 7,14  h1v1h-1z
-                M 13,15 h1v1h-1z
-                M 14,11 h1v1h-1z
-
-                M 11,17 h0.5v0.5h-0.5z
-                M 10,15 h0.5v0.5h-0.5z
-                M 13,18 h0.5v0.5h-0.5z
-                M 17,15 h0.5v0.5h-0.5z
-                M 15,14 h0.5v0.5h-0.5z
-                M 18,12 h0.5v0.5h-0.5z
-                M 5,13  h0.5v0.5h-0.5z
-                M 5,10  h0.5v0.5h-0.5z
-                M 9,11  h0.5v0.5h-0.5z
-                M 8,17  h0.5v0.5h-0.5z
-                M 12,12 h0.5v0.5h-0.5z
-            " android:fillColor="#ffffff"/>
-        </group>
-    </group>
+        android:pathData="M5,14.978h14v9.8h-14z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M18.722,15.576C18.717,15.548 18.713,15.521 18.708,15.493C18.68,15.324 18.646,15.156 18.605,14.991C18.534,14.701 18.445,14.42 18.339,14.146C18.249,13.915 18.146,13.69 18.033,13.472C17.886,13.192 17.722,12.923 17.539,12.667C17.316,12.354 17.067,12.06 16.795,11.789C16.68,11.676 16.562,11.566 16.44,11.461C16.175,11.233 15.893,11.025 15.595,10.839C15.598,10.834 15.6,10.83 15.602,10.825C15.739,10.59 15.875,10.355 16.012,10.119C16.145,9.889 16.279,9.659 16.412,9.429C16.508,9.264 16.604,9.098 16.699,8.933C16.722,8.894 16.74,8.854 16.753,8.812C16.791,8.696 16.792,8.575 16.762,8.462C16.754,8.434 16.745,8.406 16.734,8.38C16.723,8.353 16.71,8.327 16.695,8.302C16.644,8.216 16.571,8.142 16.479,8.087C16.399,8.039 16.308,8.011 16.215,8.002C16.176,7.999 16.137,7.999 16.098,8.003C16.066,8.007 16.034,8.013 16.002,8.021C15.889,8.051 15.785,8.113 15.703,8.202C15.674,8.235 15.647,8.27 15.624,8.309C15.529,8.475 15.433,8.64 15.337,8.805L14.937,9.495C14.801,9.731 14.664,9.966 14.528,10.202C14.513,10.227 14.498,10.253 14.483,10.279C14.462,10.271 14.442,10.263 14.421,10.255C13.669,9.968 12.853,9.811 12,9.811C11.977,9.811 11.954,9.811 11.931,9.811C11.172,9.819 10.444,9.951 9.764,10.188C9.686,10.215 9.608,10.244 9.531,10.274C9.517,10.25 9.503,10.226 9.489,10.202C9.353,9.966 9.216,9.731 9.08,9.495C8.946,9.265 8.813,9.035 8.679,8.805C8.584,8.64 8.488,8.475 8.392,8.31C8.37,8.271 8.343,8.235 8.314,8.203C8.232,8.113 8.127,8.051 8.014,8.021C7.983,8.013 7.951,8.007 7.919,8.004C7.88,8 7.841,7.999 7.802,8.003C7.709,8.011 7.618,8.039 7.537,8.088C7.446,8.142 7.373,8.217 7.322,8.302C7.307,8.327 7.294,8.353 7.283,8.38C7.271,8.407 7.262,8.434 7.255,8.462C7.225,8.575 7.226,8.697 7.264,8.812C7.277,8.854 7.295,8.894 7.318,8.934C7.413,9.099 7.509,9.264 7.605,9.429C7.738,9.659 7.872,9.889 8.005,10.119C8.141,10.355 8.278,10.59 8.414,10.826C8.415,10.828 8.417,10.83 8.418,10.832C8.143,11.003 7.881,11.192 7.634,11.4C7.486,11.524 7.343,11.654 7.207,11.79C6.935,12.061 6.685,12.354 6.462,12.668C6.279,12.923 6.114,13.192 5.968,13.472C5.855,13.691 5.752,13.915 5.662,14.147C5.556,14.42 5.467,14.702 5.396,14.991C5.355,15.157 5.321,15.324 5.293,15.494C5.288,15.521 5.284,15.549 5.279,15.576C5.264,15.675 5.251,15.774 5.241,15.874L18.759,15.874C18.749,15.774 18.736,15.675 18.72,15.576L18.722,15.576Z"
+        android:fillColor="#ffffff"/>
+  </group>
+  <path
+      android:pathData="M12,20.923C10.764,20.923 9.946,20.065 9.131,18.653C8.316,17.241 4.291,10.269 3.476,8.857C2.66,7.445 2.326,6.309 2.944,5.238C3.563,4.167 4.714,3.888 6.344,3.888C7.975,3.888 16.025,3.888 17.656,3.888C19.286,3.888 20.437,4.167 21.056,5.238C21.674,6.309 21.34,7.445 20.524,8.857C19.709,10.269 15.684,17.241 14.869,18.653C14.054,20.065 13.236,20.923 12,20.923H12Z"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ffffff"/>
 </vector>
+
diff --git a/core/res/res/drawable/ic_android_satellite_24px.xml b/core/res/res/drawable/ic_android_satellite_24px.xml
new file mode 100644
index 0000000..15f2884
--- /dev/null
+++ b/core/res/res/drawable/ic_android_satellite_24px.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M487,600L392,505L346,551L376,580Q399,603 399,637Q399,671 376,694L333,737Q310,760 276.5,760Q243,760 220,737L103,620Q80,597 80,563.5Q80,530 103,507L146,464Q169,441 203,441Q237,441 260,464L289,494L335,448L160,273L273,160L448,335L493,290L464,260Q441,237 441,203Q441,169 464,146L507,103Q530,80 563.5,80Q597,80 620,103L737,220Q760,243 760,276.5Q760,310 737,333L694,376Q671,399 637,399Q603,399 580,376L550,347L505,392L600,487L487,600ZM520,880L520,800Q637,800 718.5,718.5Q800,637 800,520L880,520Q880,595 851.5,660.5Q823,726 774.5,774.5Q726,823 660.5,851.5Q595,880 520,880ZM520,720L520,640Q570,640 605,605Q640,570 640,520L720,520Q720,603 661.5,661.5Q603,720 520,720ZM520,203L550,233L593,190L563,160Q563,160 563,160Q563,160 563,160L520,203Q520,203 520,203Q520,203 520,203ZM160,563L190,593L233,550L203,520Q203,520 203,520Q203,520 203,520L160,563Q160,563 160,563Q160,563 160,563ZM637,320L680,277Q680,277 680,277Q680,277 680,277L650,247L607,290L637,320Q637,320 637,320Q637,320 637,320ZM277,680L320,637Q320,637 320,637Q320,637 320,637L290,607L247,650L277,680Q277,680 277,680Q277,680 277,680Z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_private_profile_badge.xml b/core/res/res/drawable/ic_private_profile_badge.xml
index b042c39..8f7bbb5 100644
--- a/core/res/res/drawable/ic_private_profile_badge.xml
+++ b/core/res/res/drawable/ic_private_profile_badge.xml
@@ -20,6 +20,10 @@
         android:viewportWidth="24"
         android:viewportHeight="24">
         <path
-            android:pathData="M5,3H19C20.1,3 21,3.9 21,5V19C21,20.1 20.1,21 19,21H5C3.9,21 3,20.1 3,19V5C3,3.9 3.9,3 5,3ZM13.5,15.501L12.93,12.271C13.57,11.941 14,11.271 14,10.501C14,9.401 13.1,8.501 12,8.501C10.9,8.501 10,9.401 10,10.501C10,11.271 10.43,11.941 11.07,12.271L10.5,15.501H13.5Z"
+            android:pathData="M12,2L4,5V11.09C4,16.14 7.41,20.85 12,22C16.59,20.85 20,16.14 20,11.09V5L12,2ZM15,15V17H13V18H11V12.84C9.56,12.41 8.5,11.09 8.5,9.5C8.5,7.57 10.07,6 12,6C13.93,6 15.5,7.57 15.5,9.5C15.5,11.08 14.44,12.41 13,12.84V15H15Z"
+            android:fillColor="#3C4043"
+            android:fillType="evenOdd"/>
+        <path
+            android:pathData="M12,11C12.828,11 13.5,10.328 13.5,9.5C13.5,8.672 12.828,8 12,8C11.172,8 10.5,8.672 10.5,9.5C10.5,10.328 11.172,11 12,11Z"
             android:fillColor="#3C4043"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_private_profile_icon_badge.xml b/core/res/res/drawable/ic_private_profile_icon_badge.xml
index 5f1f1b7..4143c3b 100644
--- a/core/res/res/drawable/ic_private_profile_icon_badge.xml
+++ b/core/res/res/drawable/ic_private_profile_icon_badge.xml
@@ -24,8 +24,12 @@
         android:scaleY=".66"
         android:translateX="42"
         android:translateY="42">
-            <path
-                android:pathData="M5,3H19C20.1,3 21,3.9 21,5V19C21,20.1 20.1,21 19,21H5C3.9,21 3,20.1 3,19V5C3,3.9 3.9,3 5,3ZM13.5,15.501L12.93,12.271C13.57,11.941 14,11.271 14,10.501C14,9.401 13.1,8.501 12,8.501C10.9,8.501 10,9.401 10,10.501C10,11.271 10.43,11.941 11.07,12.271L10.5,15.501H13.5Z"
-                android:fillColor="#3C4043"/>
+        <path
+            android:pathData="M12,2L4,5V11.09C4,16.14 7.41,20.85 12,22C16.59,20.85 20,16.14 20,11.09V5L12,2ZM15,15V17H13V18H11V12.84C9.56,12.41 8.5,11.09 8.5,9.5C8.5,7.57 10.07,6 12,6C13.93,6 15.5,7.57 15.5,9.5C15.5,11.08 14.44,12.41 13,12.84V15H15Z"
+            android:fillColor="#3C4043"
+            android:fillType="evenOdd"/>
+        <path
+            android:pathData="M12,11C12.828,11 13.5,10.328 13.5,9.5C13.5,8.672 12.828,8 12,8C11.172,8 10.5,8.672 10.5,9.5C10.5,10.328 11.172,11 12,11Z"
+            android:fillColor="#3C4043"/>
     </group>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/pointer_spot_anchor_vector.xml b/core/res/res/drawable/pointer_spot_anchor_vector.xml
index 54de2ae..89990b8 100644
--- a/core/res/res/drawable/pointer_spot_anchor_vector.xml
+++ b/core/res/res/drawable/pointer_spot_anchor_vector.xml
@@ -22,4 +22,8 @@
         <path android:fillColor="#ADC6E7" android:pathData="M12 3c-4.963 0-9 4.038-9 9 0 4.963 4.037 9 9 9s9-4.037 9-9c0-4.962-4.037-9-9-9m0 17c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8" />
         <path android:fillColor="#ADC6E7" android:pathData="M12 5c-3.859 0-7 3.14-7 7s3.141 7 7 7 7-3.141 7-7-3.141-7-7-7m0 13c-3.309 0-6-2.691-6-6s2.691-6 6-6 6 2.691 6 6-2.691 6-6 6" />
     </group>
+    <path
+        android:pathData="M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0 -16m0 15a7 7 0 1 1 0 -14 7 7 0 0 1 0 14"
+        android:fillColor="#99FFFFFF"
+        android:fillType="evenOdd"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/pointer_spot_hover_vector.xml b/core/res/res/drawable/pointer_spot_hover_vector.xml
index ef596c4..4bf5fbc 100644
--- a/core/res/res/drawable/pointer_spot_hover_vector.xml
+++ b/core/res/res/drawable/pointer_spot_hover_vector.xml
@@ -22,4 +22,7 @@
         <path android:fillColor="#ADC6E7" android:pathData="M12 3c-4.963 0-9 4.038-9 9 0 4.963 4.037 9 9 9s9-4.037 9-9c0-4.962-4.037-9-9-9m0 17c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8" />
         <path android:fillColor="#ADC6E7" android:pathData="M12 7c-2.757 0-5 2.243-5 5s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5m0 9c-2.206 0-4-1.794-4-4s1.794-4 4-4 4 1.794 4 4-1.794 4-4 4" />
     </group>
+    <path
+        android:pathData="M12 3.998a8.002 8.002 0 1 0 0 16.004 8.002 8.002 0 0 0 0 -16.004m0 13.004a5.002 5.002 0 1 1 0 -10.004 5.002 5.002 0 0 1 0 10.004"
+        android:fillColor="#99FFFFFF"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/pointer_spot_touch_vector.xml b/core/res/res/drawable/pointer_spot_touch_vector.xml
index afd2956..a25ffe0 100644
--- a/core/res/res/drawable/pointer_spot_touch_vector.xml
+++ b/core/res/res/drawable/pointer_spot_touch_vector.xml
@@ -21,4 +21,7 @@
     <path
         android:fillColor="#ADC6E7"
         android:pathData="M21 12c0-4.963-4.038-9-9-9s-9 4.037-9 9 4.038 9 9 9 9-4.037 9-9m-9 8c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8" />
+    <path
+        android:pathData="M12 12m-8 0a8 8 0 1 1 16 0a8 8 0 1 1 -16 0"
+        android:fillColor="#99FFFFFF"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/stat_sys_private_profile_status.xml b/core/res/res/drawable/stat_sys_private_profile_status.xml
index 429070e..958a4d7 100644
--- a/core/res/res/drawable/stat_sys_private_profile_status.xml
+++ b/core/res/res/drawable/stat_sys_private_profile_status.xml
@@ -20,6 +20,10 @@
         android:viewportWidth="24"
         android:viewportHeight="24">
     <path
+        android:pathData="M12,2L4,5V11.09C4,16.14 7.41,20.85 12,22C16.59,20.85 20,16.14 20,11.09V5L12,2ZM15,15V17H13V18H11V12.84C9.56,12.41 8.5,11.09 8.5,9.5C8.5,7.57 10.07,6 12,6C13.93,6 15.5,7.57 15.5,9.5C15.5,11.08 14.44,12.41 13,12.84V15H15Z"
         android:fillColor="@android:color/white"
-        android:pathData="M5,3H19C20.1,3 21,3.9 21,5V19C21,20.1 20.1,21 19,21H5C3.9,21 3,20.1 3,19V5C3,3.9 3.9,3 5,3ZM13.5,15.501L12.93,12.271C13.57,11.941 14,11.271 14,10.501C14,9.401 13.1,8.501 12,8.501C10.9,8.501 10,9.401 10,10.501C10,11.271 10.43,11.941 11.07,12.271L10.5,15.501H13.5Z"/>
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M12,11C12.828,11 13.5,10.328 13.5,9.5C13.5,8.672 12.828,8 12,8C11.172,8 10.5,8.672 10.5,9.5C10.5,10.328 11.172,11 12,11Z"
+        android:fillColor="@android:color/white"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/layout/cascading_menu_item_layout_material.xml b/core/res/res/layout/cascading_menu_item_layout_material.xml
index 168ed78..36b29c3 100644
--- a/core/res/res/layout/cascading_menu_item_layout_material.xml
+++ b/core/res/res/layout/cascading_menu_item_layout_material.xml
@@ -35,7 +35,6 @@
         android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="48dip"
-        android:layout_marginStart="12dip"
         android:layout_marginEnd="12dip"
         android:duplicateParentState="true" >
 
@@ -46,7 +45,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
-            android:layout_marginStart="6dip"
+            android:layout_marginStart="18dip"
             android:textAppearance="?attr/textAppearanceLargePopupMenu"
             android:singleLine="true"
             android:duplicateParentState="true"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index be1c939..6f06d80 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -80,6 +80,7 @@
         android:layout_height="match_parent"
         android:layout_alignParentStart="true"
         android:importantForAccessibility="no"
+        android:focusable="false"
         />
 
     <include layout="@layout/notification_expand_button"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 710a70a..64227d8 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -55,6 +55,7 @@
         android:layout_height="match_parent"
         android:layout_gravity="start"
         android:importantForAccessibility="no"
+        android:focusable="false"
         />
 
     <LinearLayout
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index df32d30..8a94c48 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -54,6 +54,7 @@
         android:layout_height="match_parent"
         android:layout_gravity="start"
         android:importantForAccessibility="no"
+        android:focusable="false"
         />
 
     <LinearLayout
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index 3e82bd1..a83d923 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -67,6 +67,7 @@
                 android:layout_height="match_parent"
                 android:layout_gravity="start"
                 android:importantForAccessibility="no"
+                android:focusable="false"
                 />
 
             <!--
diff --git a/core/res/res/layout/popup_menu_item_layout_material.xml b/core/res/res/layout/popup_menu_item_layout_material.xml
new file mode 100644
index 0000000..c5ca7a5
--- /dev/null
+++ b/core/res/res/layout/popup_menu_item_layout_material.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+
+     Forked from the popup_menu_item_layout.xml for material support. When you edit this file, you
+     may also need to update that file.
+-->
+
+<com.android.internal.view.menu.ListMenuItemView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minWidth="196dip"
+    android:orientation="vertical" >
+
+    <ImageView
+        android:id="@+id/group_divider"
+        android:layout_width="match_parent"
+        android:layout_height="1dip"
+        android:layout_marginTop="4dip"
+        android:layout_marginBottom="4dip"
+        android:background="@drawable/list_divider_material" />
+
+    <LinearLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/dropdownListPreferredItemHeight"
+        android:paddingEnd="16dip"
+        android:duplicateParentState="true" >
+
+        <!-- Icon will be inserted here. -->
+
+        <!-- The title and summary have some gap between them,
+        and this 'group' should be centered vertically. -->
+        <RelativeLayout
+            android:layout_width="0dip"
+            android:layout_weight="1"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_marginStart="16dip"
+            android:duplicateParentState="true">
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentStart="true"
+                android:textAppearance="?attr/textAppearanceLargePopupMenu"
+                android:singleLine="true"
+                android:duplicateParentState="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                android:textAlignment="viewStart" />
+
+            <TextView
+                android:id="@+id/shortcut"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/title"
+                android:layout_alignParentStart="true"
+                android:textAppearance="?attr/textAppearanceSmallPopupMenu"
+                android:singleLine="true"
+                android:duplicateParentState="true"
+                android:textAlignment="viewStart" />
+
+        </RelativeLayout>
+
+        <ImageView
+            android:id="@+id/submenuarrow"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_marginStart="8dp"
+            android:scaleType="center"
+            android:visibility="gone" />
+
+        <!-- Checkbox, and/or radio button will be inserted here. -->
+
+    </LinearLayout>
+
+</com.android.internal.view.menu.ListMenuItemView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 63cd6b9..8218ff1 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -259,7 +259,7 @@
     <string name="global_action_emergency" msgid="1387617624177105088">"Noodgeval"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"Foutverslag"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"Beëindig sessie"</string>
-    <string name="global_action_screenshot" msgid="2610053466156478564">"Skermkiekie"</string>
+    <string name="global_action_screenshot" msgid="2610053466156478564">"Skermskoot"</string>
     <string name="bugreport_title" msgid="8549990811777373050">"Foutverslag"</string>
     <string name="bugreport_message" msgid="5212529146119624326">"Dit sal inligting oor die huidige toestand van jou toestel insamel om as \'n e-posboodskap te stuur. Dit sal \'n tydjie neem vandat die foutverslag begin is totdat dit reg is om gestuur te word; wees asseblief geduldig."</string>
     <string name="bugreport_option_interactive_title" msgid="7968287837902871289">"Interaktiewe verslag"</string>
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Neem skermkiekie"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan \'n skermkiekie neem."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Voorskou, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die app toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Vingerafdruk word nie herken nie"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Vingerafdruk word nie herken nie"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Kan nie gesig herken nie. Gebruik eerder vingerafdruk."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Gesig nie herken nie. Gebruik eerder vingerafdruk."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Vingerafdruk is gestaaf"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gesig is gestaaf"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesig is gestaaf; druk asseblief bevestig"</string>
@@ -1426,7 +1428,7 @@
     <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>
-    <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"Wys bo-oor ander programme"</string>
+    <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"Wys bo-oor ander apps"</string>
     <string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> word bo-oor ander programme gewys"</string>
     <string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g> wys bo-oor ander programme"</string>
     <string name="alert_windows_notification_message" msgid="6538171456970725333">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk gebruik nie, tik om instellings oop te maak en skakel dit af."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vra PIN voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vra ontsluitpatroon voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vra wagwoord voordat jy ontspeld"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Geïnstalleer deur jou administrateur"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Opgedateer deur jou administrateur"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Uitgevee deur jou administrateur"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -1929,12 +1932,9 @@
     <string name="zen_mode_implicit_trigger_description" msgid="5714956693073007111">"Bestuur deur <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aan"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Af"</string>
-    <!-- no translation found for zen_mode_trigger_summary_divider_text (7461583466043698862) -->
-    <skip />
-    <!-- no translation found for zen_mode_trigger_summary_range_symbol_combination (1804900738798069619) -->
-    <skip />
-    <!-- no translation found for zen_mode_trigger_event_calendar_any (2086784607921121803) -->
-    <skip />
+    <string name="zen_mode_trigger_summary_divider_text" msgid="7461583466043698862">", "</string>
+    <string name="zen_mode_trigger_summary_range_symbol_combination" msgid="1804900738798069619">"<xliff:g id="START">%1$s</xliff:g>-<xliff:g id="END">%2$s</xliff:g>"</string>
+    <string name="zen_mode_trigger_event_calendar_any" msgid="2086784607921121803">"Enige kalender"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> demp sekere klanke"</string>
     <string name="system_error_wipe_data" msgid="5910572292172208493">"Daar is \'n interne probleem met jou toestel en dit sal dalk onstabiel wees totdat jy \'n fabriekterugstelling doen."</string>
     <string name="system_error_manufacturer" msgid="703545241070116315">"Daar is \'n interne probleem met jou toestel. Kontak jou vervaardiger vir besonderhede."</string>
@@ -1973,7 +1973,7 @@
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Ongekategoriseer"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Jy stel die belangrikheid van hierdie kennisgewings."</string>
     <string name="importance_from_person" msgid="4235804979664465383">"Dit is belangrik as gevolg van die mense wat betrokke is."</string>
-    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Gepasmaakte programkennisgewing"</string>
+    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Gepasmaakte appkennisgewing"</string>
     <string name="user_creation_account_exists" msgid="2239146360099708035">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep (\'n gebruiker met hierdie rekening bestaan reeds)?"</string>
     <string name="user_creation_adding" msgid="7305185499667958364">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep?"</string>
     <string name="supervised_user_creation_label" msgid="6884904353827427515">"Voeg gebruiker onder toesig by"</string>
@@ -2179,7 +2179,7 @@
     <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Kitsinstellings"</string>
     <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Kragdialoog"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Sluitskerm"</string>
-    <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skermkiekie"</string>
+    <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skermskoot"</string>
     <string name="accessibility_system_action_headset_hook_label" msgid="8524691721287425468">"Kopstuk haak"</string>
     <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Toeganklikheidkortpad op skerm"</string>
     <string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"Toeganklikheidkortpadkieser op skerm"</string>
@@ -2396,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Toets"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Gemeenskaplik"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Appinhoud is weens sekuriteit van skermdeling verberg"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Outomaties aan satelliet gekoppel"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Jy kan boodskappe stuur en ontvang sonder ’n selfoon- of wi-fi-netwerk"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Maak Boodskappe oop"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 799a7ab..b1f9447 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ቅጽበታዊ ገፅ እይታን ያነሳል"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"የማሳያው ቅጽበታዊ ገፅ እይታን ማንሳት ይችላል።"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ቅድመ ዕይታ፣ <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"የሁኔታ አሞሌ መሆን"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"የጣት አሻራ አልታወቀም"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"የጣት አሻራ አልታወቀም"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"መልክን መለየት አልተቻለም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ፊቱ አልታወቀም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"የጣት አሻራ ትክክለኛነት ተረጋግጧል"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ፊት ተረጋግጧል"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ፊት ተረጋግጧል፣ እባክዎ አረጋግጥን ይጫኑ"</string>
@@ -1894,9 +1896,10 @@
     <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g>ን አባዛ"</string>
     <string name="private_profile_label_badge" msgid="1712086003787839183">"የግል <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ከመንቀል በፊት ፒን ጠይቅ"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ከመንቀል በፊት የማስከፈቻ ሥርዓተ-ጥለት ጠይቅ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"በእርስዎ አስተዳዳሪ ተጭኗል"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ሥራ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ሙከራ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"የጋራ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ለደኅንነት ሲባል የመተግበሪያ ይዘት ከማያ ገጽ ማጋራት ተደብቋል"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ከሳተላይት ጋር በራስ-ሰር ተገናኝቷል"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"ያለ ሞባይል ወይም የWi-Fi አውታረ መረብ መልዕክቶችን መላክ እና መቀበል ይችላሉ"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"መልዕክቶች ይክፈቱ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index fad2cd6..453998f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -195,10 +195,10 @@
     <string name="low_memory" product="default" msgid="2539532364144025569">"مساحة تخزين الهاتف ممتلئة. احذف بعض الملفات لإخلاء مساحة."</string>
     <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{تم تثبيت مرجع التصديق.}zero{تم تثبيت مراجع التصديق.}two{تم تثبيت مرجعَي التصديق.}few{تم تثبيت مراجع التصديق.}many{تم تثبيت مراجع التصديق.}other{تم تثبيت مراجع التصديق.}}"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"بواسطة جهة خارجية غير معلومة"</string>
-    <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"بواسطة مشرف الملف الشخصي للعمل"</string>
+    <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"بواسطة مشرف ملف العمل"</string>
     <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"بواسطة <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
-    <string name="work_profile_deleted" msgid="5891181538182009328">"تم حذف الملف الشخصي للعمل."</string>
-    <string name="work_profile_deleted_details" msgid="3773706828364418016">"تطبيق المشرف للملف الشخصي للعمل مفقود أو تالف لذا تم حذف الملف الشخصي للعمل والبيانات ذات الصلة. اتصل بالمشرف للحصول على المساعدة."</string>
+    <string name="work_profile_deleted" msgid="5891181538182009328">"تم حذف ملف العمل."</string>
+    <string name="work_profile_deleted_details" msgid="3773706828364418016">"تطبيق المشرف لملف العمل مفقود أو تالف لذا تم حذف ملف العمل والبيانات ذات الصلة. اتصل بالمشرف للحصول على المساعدة."</string>
     <string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"لم يعد ملفك الشخصي للعمل متاحًا على هذا الجهاز"</string>
     <string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"تم إجراء محاولات كثيرة جدًا لإدخال كلمة المرور"</string>
     <string name="device_ownership_relinquished" msgid="4080886992183195724">"تنازل المشرف عن الجهاز للاستخدام الشخصي"</string>
@@ -218,9 +218,9 @@
     <string name="factory_reset_warning" msgid="6858705527798047809">"سيتم محو بيانات جهازك."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
-    <string name="personal_apps_suspension_title" msgid="7561416677884286600">"تفعيل الملف الشخصي للعمل"</string>
+    <string name="personal_apps_suspension_title" msgid="7561416677884286600">"تفعيل ملف العمل"</string>
     <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>. لا يسمح مشرف تكنولوجيا المعلومات في مؤسستك بإيقاف الملف الشخصي للعمل أكثر من <xliff:g id="NUMBER">%3$d</xliff:g> يوم."</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>. لا يسمح مشرف تكنولوجيا المعلومات في مؤسستك بإيقاف ملف العمل أكثر من <xliff:g id="NUMBER">%3$d</xliff:g> يوم."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"تفعيل"</string>
     <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"المكالمات والرسائل غير مفعّلة"</string>
     <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"لقد أوقفت تطبيقات العمل مؤقتًا. لن تتلقّى مكالمات هاتفية أو رسائل نصية."</string>
@@ -312,9 +312,9 @@
     <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="user_owner_app_label" msgid="1553595155465750298">"التبديل إلى تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" في الملف الشخصي"</string>
-    <string name="managed_profile_app_label" msgid="367401088383965725">"التبديل إلى تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" في الملف الشخصي للعمل"</string>
+    <string name="managed_profile_app_label" msgid="367401088383965725">"التبديل إلى تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" في ملف العمل"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"جهات الاتصال"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"الوصول إلى جهات اتصالك"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"الموقع الجغرافي"</string>
@@ -360,6 +360,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"نسخة حصرية، \"<xliff:g id="DREAM_NAME">%1$s</xliff:g>\""</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string>
@@ -666,7 +668,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"لم يتمّ التعرّف على البصمة."</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"لم يتمّ التعرّف على بصمة الإصبع."</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"يتعذّر التعرّف على الوجه. استخدِم بصمة الإصبع بدلاً من ذلك."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"لم يتم التعرّف على الوجه. استخدِم بصمة إصبعك."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"تم مصادقة بصمة الإصبع"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"تمّت مصادقة الوجه"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"تمّت مصادقة الوجه، يُرجى الضغط على \"تأكيد\"."</string>
@@ -708,10 +710,10 @@
     <string name="face_acquired_too_dark" msgid="8539853432479385326">"الإضاءة غير كافية"</string>
     <string name="face_acquired_too_close" msgid="4453646176196302462">"يُرجى إبعاد الهاتف عنك."</string>
     <string name="face_acquired_too_far" msgid="2922278214231064859">"يُرجى تقريب الهاتف منك"</string>
-    <string name="face_acquired_too_high" msgid="8278815780046368576">"يُرجى رفع الهاتف للأعلى"</string>
-    <string name="face_acquired_too_low" msgid="4075391872960840081">"يُرجى خفض الهاتف للأسفل"</string>
-    <string name="face_acquired_too_right" msgid="6245286514593540859">"يُرجى تحريك الهاتف لجهة اليسار"</string>
-    <string name="face_acquired_too_left" msgid="9201762240918405486">"يُرجى تحريك الهاتف لجهة اليمين"</string>
+    <string name="face_acquired_too_high" msgid="8278815780046368576">"ارفع الهاتف للأعلى"</string>
+    <string name="face_acquired_too_low" msgid="4075391872960840081">"خفّض الهاتف للأسفل"</string>
+    <string name="face_acquired_too_right" msgid="6245286514593540859">"حرِّك الهاتف لجهة اليسار"</string>
+    <string name="face_acquired_too_left" msgid="9201762240918405486">"حرِّك الهاتف لجهة اليمين"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"يُرجى النظر إلى جهازك مباشرة أكثر."</string>
     <string name="face_acquired_not_detected" msgid="1057966913397548150">"ارفع هاتفك إلى مستوى العينَين لأنّه تتعذّر رؤية وجهك"</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"حركة أكثر من اللازم. يُرجى حمل الهاتف بثبات."</string>
@@ -999,7 +1001,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"صحيح!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"أعد المحاولة"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"أعد المحاولة"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"فتح قفل جميع الميزات والبيانات"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"فتح القفل للوصول إلى جميع الميزات والبيانات"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات فتح الجهاز بالتعرف على الوجه"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"‏لا تتوفر شريحة SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"‏لا تتوفر شريحة SIM في الجهاز اللوحي."</string>
@@ -1401,7 +1403,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"تم اكتشاف ملحق صوتي تناظري"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"الجهاز الذي تم توصيله بالهاتف غير متوافق معه. انقر للحصول على المزيد من المعلومات."</string>
     <string name="adb_active_notification_title" msgid="408390247354560331">"‏تم توصيل USB لتصحيح أخطاء الجهاز"</string>
-    <string name="adb_active_notification_message" msgid="5617264033476778211">"‏انقر لإيقاف تصحيح أخطاء الجهاز عبر USB."</string>
+    <string name="adb_active_notification_message" msgid="5617264033476778211">"‏انقر لإيقاف تصحيح أخطاء الجهاز عبر USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"‏اختيار إيقاف تصحيح أخطاء USB."</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"تم تفعيل ميزة \"تصحيح الأخطاء اللاسلكي\"."</string>
     <string name="adbwifi_active_notification_message" msgid="930987922852867972">"انقر لإيقاف ميزة \"تصحيح الأخطاء اللاسلكي\"."</string>
@@ -1660,7 +1662,7 @@
     <string name="media_route_button_content_description" msgid="2299223698196869956">"البث"</string>
     <string name="media_route_chooser_title" msgid="6646594924991269208">"الاتصال بجهاز"</string>
     <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"بث الشاشة على الجهاز"</string>
-    <string name="media_route_chooser_searching" msgid="6119673534251329535">"جارٍ البحث عن الأجهزة…"</string>
+    <string name="media_route_chooser_searching" msgid="6119673534251329535">"جارٍ البحث عن أجهزة…"</string>
     <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"الإعدادات"</string>
     <string name="media_route_controller_disconnect" msgid="7362617572732576959">"قطع الاتصال"</string>
     <string name="media_route_status_scanning" msgid="8045156315309594482">"البحث عن الشبكات..."</string>
@@ -1898,15 +1900,16 @@
     <string name="clone_profile_label_badge" msgid="1871997694718793964">"نسخة طبق الأصل عن \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
     <string name="private_profile_label_badge" msgid="1712086003787839183">"ملف شخصي خاص على <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"طلب إدخال رقم التعريف الشخصي قبل إزالة التثبيت"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"طلب إدخال النقش الخاص بإلغاء القفل قبل إزالة التثبيت"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"طلب إدخال نقش فتح القفل قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"طلب إدخال كلمة المرور قبل إزالة التثبيت"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"تم التثبيت بواسطة المشرف"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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="data_saver_description" msgid="4995164271550590517">"للمساعدة في خفض استخدام البيانات، تمنع ميزة \"توفير البيانات\" بعض التطبيقات من إرسال البيانات وتلقّيها في الخلفية. يمكن للتطبيقات المتاحة لديك الآن استخدام البيانات، ولكن لا يمكنها الإكثار من ذلك. وهذا يعني أن الصور مثلاً لا تظهر حتى تنقر عليها."</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>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{لمدة دقيقة واحدة (حتى {formattedTime})}zero{لمدة # دقيقة (حتى {formattedTime})}two{لمدة دقيقتين (حتى {formattedTime})}few{لمدة # دقائق (حتى {formattedTime})}many{لمدة # دقيقة (حتى {formattedTime})}other{لمدة # دقيقة (حتى {formattedTime})}}"</string>
@@ -1948,7 +1951,7 @@
     <string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏تم تغيير طلب SS إلى طلب USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏تم التغيير إلى طلب SS الجديد."</string>
     <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"تنبيه بشأن تصيّد احتيالي"</string>
-    <string name="notification_work_profile_content_description" msgid="5296477955677725799">"الملف الشخصي للعمل"</string>
+    <string name="notification_work_profile_content_description" msgid="5296477955677725799">"ملف العمل"</string>
     <string name="notification_alerted_content_description" msgid="6139691253611265992">"تمّ تفعيل التنبيه"</string>
     <string name="notification_verified_content_description" msgid="6401483602782359391">"تم التحقّق من المتّصل"</string>
     <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"توسيع"</string>
@@ -2027,8 +2030,8 @@
     <string name="new_sms_notification_title" msgid="6528758221319927107">"لديك رسائل جديدة"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"‏فتح تطبيق الرسائل القصيرة SMS للعرض"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"قد تكون بعض الوظائف مُقيّدة."</string>
-    <string name="profile_encrypted_detail" msgid="5279730442756849055">"تم قفل الملف الشخصي للعمل."</string>
-    <string name="profile_encrypted_message" msgid="1128512616293157802">"انقر لإلغاء قفل الملف الشخصي للعمل"</string>
+    <string name="profile_encrypted_detail" msgid="5279730442756849055">"تم قفل ملف العمل."</string>
+    <string name="profile_encrypted_message" msgid="1128512616293157802">"انقر لإلغاء قفل ملف العمل"</string>
     <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"تم الاتصال بـ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
     <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"انقر لعرض الملفات"</string>
     <string name="pin_target" msgid="8036028973110156895">"تثبيت"</string>
@@ -2213,7 +2216,7 @@
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ما مِن تطبيقات شخصية."</string>
     <string name="miniresolver_open_work" msgid="6286176185835401931">"هل تريد فتح تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملفك الشخصي للعمل؟"</string>
     <string name="miniresolver_open_in_personal" msgid="807427577794490375">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في الملف الشخصي؟"</string>
-    <string name="miniresolver_open_in_work" msgid="941341494673509916">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في الملف الشخصي للعمل؟"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"هل تريد فتح المحتوى في تطبيق \"<xliff:g id="APP">%s</xliff:g>\" في ملف العمل؟"</string>
     <string name="miniresolver_call_in_work" msgid="528779988307529039">"هل تريد الاتصال من تطبيق العمل؟"</string>
     <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"هل تريد الانتقال إلى تطبيق العمل؟"</string>
     <string name="miniresolver_call_information" msgid="6739417525304184083">"تسمح لك مؤسستك بإجراء المكالمات من تطبيقات العمل فقط."</string>
@@ -2397,9 +2400,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ملف العمل 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ملف شخصي تجريبي"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"ملف شخصي مشترك"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"تم إخفاء محتوى التطبيق بعد تفعيل ميزة \"مشاركة الشاشة\" للحفاظ على أمانك"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"تم الاتصال تلقائيًا بالقمر الصناعي"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"‏يمكنك إرسال الرسائل واستلامها بدون شبكة الجوّال أو شبكة Wi-Fi."</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"فتح تطبيق \"الرسائل\""</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 8b3f832..89a6f97 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্ৰীনশ্বট লওক"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিছপ্লে’খনৰ এটা স্ক্ৰীনশ্বট ল\'ব পাৰে।"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"পূৰ্বদৰ্শন কৰক, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপ্‌টোক অনুমতি দিয়ে।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ফিংগাৰপ্ৰিণ্ট চিনাক্ত কৰিব পৰা নাই"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ফিংগাৰপ্ৰিণ্ট চিনাক্ত কৰিব পৰা নাই"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"মুখাৱয়ব চিনিব নোৱাৰি। ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"মুখাৱয়ব চিনাক্ত কৰিব পৰা নাই। ইয়াৰ পৰিৱৰ্তে ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ফিংগাৰপ্ৰিণ্টৰ সত্যাপন কৰা হ’ল"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল, অনুগ্ৰহ কৰি ‘নিশ্চিত কৰক’ বুটামটো টিপক"</string>
@@ -692,7 +694,7 @@
     <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"আনলক কৰিবলৈ আন এটা উপায় ব্যৱহাৰ কৰি চাওক"</string>
     <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"আপোনাৰ আঙুলিকেইটা তিতি থকাৰ দৰে পৰিস্থিতিত, আপোনাৰ ফিংগাৰপ্ৰিণ্ট চিনাক্ত কৰিব নোৱাৰিলে ফে’চ আনলক সুবিধাটো ব্যৱহাৰ কৰক"</string>
     <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"পৰ্যাপ্ত পোহৰ নথকাৰ দৰে পৰিস্থিতিত, আপোনাৰ মুখাৱয়ব চিনাক্ত কৰিব নোৱাৰিলে ফিংগাৰপ্ৰিণ্ট আনলক সুবিধাটো ব্যৱহাৰ কৰক"</string>
-    <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেচ আনলক"</string>
+    <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফে’চ আনলক"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ফেচ আনলক ব্যৱহাৰ কৰোঁতে সমস্যা হৈছে"</string>
     <string name="face_recalibrate_notification_content" msgid="3064513770251355594">"আপোনাৰ মুখাৱয়বৰ মডেলটো মচিবলৈ টিপক, তাৰ পাছত পুনৰ আপোনাৰ মুখাৱয়ব যোগ দিয়ক"</string>
     <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"ফেচ আনলক সুবিধাটো ব্যৱহাৰ কৰিবলৈ ছেটিং &gt; গোপনীয়তাত "<b>"কেমেৰাৰ এক্সেছ"</b>" অন কৰক"</string>
@@ -1066,7 +1068,7 @@
     <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"আনলক ক্ষেত্ৰ বিস্তাৰ কৰক।"</string>
     <string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"শ্লাইডৰদ্বাৰা আনলক।"</string>
     <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"আৰ্হিৰদ্বাৰা আনলক।"</string>
-    <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"ফেচ আনলক।"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"ফে’চ আনলক।"</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"পিনৰদ্বাৰা আনলক।"</string>
     <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"ছিম পিন আনলক।"</string>
     <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"ছিম পিইউকে আনলক।"</string>
@@ -1726,7 +1728,7 @@
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"আপোনাক সাধ্য সুবিধাৰ প্ৰয়োজনসমূহৰ জৰিয়তে সহায় কৰা এপ্‌সমূহৰ বাবে সম্পূর্ণ নিয়ন্ত্ৰণৰ সুবিধাটো সঠিক যদিও অধিকাংশ এপৰ বাবে এয়া সঠিক নহয়।"</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"চাওক আৰু স্ক্ৰীন নিয়ন্ত্ৰণ কৰক"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"ই স্ক্ৰীনত থকা আটাইখিনি সমল পঢ়িব পাৰে আৰু অন্য এপ্‌সমূহৰ ওপৰত সমল প্ৰদর্শন কৰিব পাৰে।"</string>
-    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"কার্যসমূহ চাওক আৰু কৰক"</string>
+    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"কার্যসমূহ চোৱা আৰু কৰা"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"ই আপুনি কোনো এপ্ বা হার্ডৱেৰ ছেন্সৰৰ সৈতে কৰা ভাব-বিনিময় আৰু আপোনাৰ হৈ অন্য কোনো লোকে এপৰ সৈতে কৰা ভাব-বিনিময় ট্ৰেক কৰিব পাৰে।"</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"অনুমতি দিয়ক"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"অস্বীকাৰ কৰক"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন কৰাৰ পূৰ্বে পিন দিবলৈ কওক"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন কৰাৰ পূৰ্বে আনলক আৰ্হি দিবলৈ কওক"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন কৰাৰ পূৰ্বে পাছৱৰ্ড দিবলৈ কওক"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"আপোনাৰ প্ৰশাসকে ইনষ্টল কৰিছে"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"কৰ্মস্থান ৩"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"পৰীক্ষা"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"শ্বেয়াৰ কৰা"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"সুৰক্ষাৰ বাবে এপৰ সমল স্ক্ৰীণ শ্বেয়াৰ কৰাৰ পৰা লুকুৱাই ৰখা হৈছে"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"উপগ্ৰহৰ সৈতে স্বয়ংক্ৰিয়ভাৱে সংযুক্ত হৈছে"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"আপুনি ম’বাইল বা ৱাই-ফাই নেটৱৰ্কৰ জৰিয়তে পাঠ বাৰ্তা পঠিয়াব বা লাভ কৰিব পাৰে"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages খোলক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index c0b886b..3bc5b92 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran şəkli çəkin"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran şəkli çəkilə bilər."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Önizləmə, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Barmaq izi tanınmır"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Barmaq izi tanınmır"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Tanımaq olmur. Barmaq izini işlədin."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Üz tanınmadı. Barmaq izindən istifadə edin."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Barmaq izi doğrulandı"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Üz doğrulandı"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Üz təsdiq edildi, təsdiq düyməsinə basın"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ayırmadan öncə PIN istənilsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Qrafik açar istənilsin"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ayırmadan öncə parol istənilsin"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Admin tərəfindən quraşdırıldı"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Admin tərəfindən yeniləndi"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Admin tərəfindən silindi"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Kommunal"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Güvənlik üçün tətbiq kontenti ekran paylaşımından gizlədildi"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Peykə avtomatik qoşulub"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Mobil və ya Wi-Fi şəbəkəsi olmadan mesaj göndərə və qəbul edə bilərsiniz"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Mesajı açın"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a275cab..5a79197 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Napravi snimak ekrana"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može da napravi snimak ekrana."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmena statusne trake"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"funkcionisanje kao statusna traka"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Otisak prsta nije prepoznat"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Otisak prsta nije prepoznat"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Lice nije prepoznato. Koristite otisak prsta."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Lice nije prepoznato. Koristite otisak prsta."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisak prsta je potvrđen"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je potvrđeno"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je potvrđeno. Pritisnite Potvrdi"</string>
@@ -1223,7 +1225,7 @@
     <string name="whichEditApplicationLabel" msgid="1463288652070140285">"Izmeni"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"Delite"</string>
     <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Delite pomoću aplikacije %1$s"</string>
-    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Deli"</string>
+    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Deljenje"</string>
     <string name="whichSendToApplication" msgid="77101541959464018">"Pošaljite pomoću:"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Pošaljite pomoću: %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Pošalji"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži šablon za otključavanje pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku pre otkačinjanja"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalirao je administrator"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je administrator"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je administrator"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Potvrdi"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Posao 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Zajedničko"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sadržaj aplikacije je skriven za deljenje sadržaja ekrana zbog bezbednosti"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatski povezano sa satelitom"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Možete da šaljete i primate poruke bez mobilne ili WiFi mreže"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Otvori Messages"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index c0d930f..9f07bd4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зрабіць здымак экрана"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Можна зрабіць здымак экрана."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Перадпрагляд, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Адбітак пальца не распазнаны"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Адбітак пальца не распазнаны"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Твар не распазнаны. Скарыстайце адбітак пальца."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Твар не распазнаны. Выкарыстайце адбітак пальца."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Адбітак пальца распазнаны"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Твар распазнаны"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Твар распазнаны. Націсніце, каб пацвердзіць"</string>
@@ -1898,7 +1900,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запытваць PIN-код перад адмацаваннем"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запытваць узор разблакіроўкі перад адмацаваннем"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запытваць пароль перад адмацаваннем"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Усталяваны вашым адміністратарам"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Працоўны 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Тэставы"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Супольны"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Змесціва праграмы выключана з абагульвання экрана ў мэтах бяспекі"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Аўтаматычна падключана да сістэм спадарожнікавай сувязі"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Вы можаце адпраўляць і атрымліваць паведамленні без доступу да мабільнай сеткі або Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Адкрыць Паведамленні"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5c793e5..eefbdf6 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Създаване на екранна снимка"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да създава екранни снимки."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Визуализация на „<xliff:g id="DREAM_NAME">%1$s</xliff:g>“"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"деактивиране или промяна на лентата на състоянието"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"изпълняване на ролята на лента на състоянието"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Отпечатъкът не е разпознат"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Отпечатъкът не е разпознат"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Лицето не е разпознато. Използвайте отпечатък."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Лицето не е разпознато. Използвайте отпечатък."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечатъкът е удостоверен"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицето е удостоверено"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е удостоверено. Моля, натиснете „Потвърждаване“"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запитване за ПИН код преди освобождаване"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитване за фигура за отключване преди освобождаване"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитване за парола преди освобождаване"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Инсталирано от администратора ви"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Служебни 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Тестване"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Общи"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Съдържанието на приложението е скрито от функцията за споделяне на екрана от съображения за сигурност"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Автоматично установена връзка със сателит"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Можете да изпращате и получавате съобщения без мобилна или Wi-Fi мрежа"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Отваряне на Messages"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 8946607..d2ccc0d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্রিনশট নিন"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিসপ্লের একটি স্ক্রিনশট নিতে পারেন।"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"প্রিভিউ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ফিঙ্গারপ্রিন্ট শনাক্ত করা যায়নি"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ফিঙ্গারপ্রিন্ট শনাক্ত করা যায়নি"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"মুখ শনাক্ত করতে পারছি না। পরিবর্তে আঙ্গুলের ছাপ ব্যবহার করুন।"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"মুখ শনাক্ত করা যায়নি। এর পরিবর্তে ফিঙ্গারপ্রিন্ট ব্যবহার করুন।"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"আঙ্গুলের ছাপ যাচাই করা হয়েছে"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ফেস যাচাই করা হয়েছে"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ফেস যাচাই করা হয়েছে, \'কনফার্ম করুন\' বোতাম প্রেস করুন"</string>
@@ -1743,7 +1745,7 @@
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"কালার ইনভার্সন"</string>
     <string name="color_correction_feature_name" msgid="7975133554160979214">"রঙ সংশোধন করা"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এক হাতে ব্যবহার করার মোড"</string>
-    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিরিক্ত কম ব্রাইটনেস"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিরিক্ত কম উজ্জ্বলতা"</string>
     <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>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন করার আগে পিন চান"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"আপনার প্রশাসক ইনস্টল করেছেন"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"৩য় অফিস"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"পরীক্ষা"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"কমিউনাল"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"নিরাপত্তার জন্য স্ক্রিন শেয়ার করা থেকে লুকানো অ্যাপের কন্টেন্ট"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"স্যাটেলাইটের সাথে অটোমেটিক কানেক্ট করা হয়েছে"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"আপনি কোনও মেবাইল বা ওয়াই-ফাই নেটওয়ার্ক ছাড়াই মেসেজ পাঠাতে ও পেতে পারবেন"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages খুলুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 2d08a22..0ee66fc 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"praviti snimke ekrana"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može napraviti snimak ekrana."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili mijenjanje statusne trake"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"funkcioniranje u vidu statusne trake"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Otisak prsta nije prepoznat"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Otisak prsta nije prepoznat"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Nije moguće prepoznati lice. Koristite otisak prsta."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Lice nije prepoznato. Upotrijebite otisak prsta."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisak prsta je potvrđen"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je provjereno"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je provjereno, pritisnite dugme za potvrdu"</string>
@@ -829,7 +831,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Postavljanje pravila za lozinke"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN-ovima."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Praćenje pokušaja otključavanja ekrana"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Prati broj pogrešno unijetih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše sve podatke s njega ukoliko se previše puta unese pogrešna lozinka."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Prati broj pogrešno unesenih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše sve podatke s njega ukoliko se previše puta unese pogrešna lozinka."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Praćenje broja unosa netačnih lozinki pri otključavanju ekrana i zaključavanje Android TV uređaja ili brisanje svih podataka Android TV uređaja u slučaju prevelikog broja unosa netačnih lozinki."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati koliko puta je lozinka neispravno unijeta prilikom otključavanja ekrana i zaključava informativno-zabavni sistem ili briše sve podatke informativno-zabavnog sistema ako se lozinka neispravno unese previše puta."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Prati broj pogrešno unesenih lozinki prilikom otključavanja ekrana i zaključava telefon ili briše sve podatke s telefona ukoliko se previše puta unese pogrešna lozinka."</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN prije nego se otkači"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje prije poništavanja kačenja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku prije nego se otkači"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalirao je vaš administrator"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je vaš administrator"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je vaš administrator"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Uredu"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"3. poslovno"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Testno"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Opće"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sadržaj aplikacije je sakriven od dijeljenja ekrana radi sigurnosti"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatski je povezano sa satelitom"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Možete slati i primati poruke bez mobilne ili WiFi mreže"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Otvorite Messages"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 263d129..48ebcad 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fer una captura de pantalla"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pot fer una captura de la pantalla."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Previsualitza, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra d\'estat"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"aparèixer a la barra d\'estat"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"L\'empremta digital no s\'ha reconegut"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"L\'empremta digital no s\'ha reconegut"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"No podem detectar la cara. Usa l\'empremta digital."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"La cara no s\'ha reconegut. Usa l\'empremta digital."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"L\'empremta digital s\'ha autenticat"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Cara autenticada; prem el botó per confirmar"</string>
@@ -842,10 +844,10 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Bloquejar la pantalla"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Controla com i quan es bloqueja la pantalla."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Esborrar totes les dades"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Esborra les dades de la tauleta sense avisar, i restableix les dades de fàbrica."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Esborra les dades de la tauleta sense avisar mitjançant el restabliment de les dades de fàbrica."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Suprimeix les dades del dispositiu Android TV sense previ avís mitjançant el restabliment de les dades de fàbrica."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Esborra les dades del sistema d\'informació i entreteniment sense avisar mitjançant el restabliment de les dades de fàbrica."</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Esborra les dades del telèfon sense avisar, i restableix les dades de fàbrica."</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Esborra les dades del telèfon sense avisar mitjançant el restabliment de les dades de fàbrica."</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Esborra les dades del perfil"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Esborrar les dades de l\'usuari"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Esborra les dades de l\'usuari desades a la tauleta sense avisar-ne."</string>
@@ -996,7 +998,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcte!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Torna-ho a provar"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Torna-ho a provar"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbl. per accedir a totes les funcions i dades"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloqueja per accedir a les funcions i dades"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"S\'ha superat el nombre màxim d\'intents de Desbloqueig facial"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"No hi ha cap SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"No hi ha cap SIM a la tauleta."</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sol·licita el PIN per deixar de fixar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sol·licita el patró de desbloqueig per deixar de fixar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demana la contrasenya per deixar de fixar"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instal·lat per l\'administrador"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string>
@@ -2032,7 +2035,7 @@
     <string name="pin_specific_target" msgid="7824671240625957415">"Fixa <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="unpin_target" msgid="3963318576590204447">"No fixis"</string>
     <string name="unpin_specific_target" msgid="3859828252160908146">"No fixis <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="app_info" msgid="6113278084877079851">"Informació de l\'aplicació"</string>
+    <string name="app_info" msgid="6113278084877079851">"Informació de l\'app"</string>
     <string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="demo_starting_message" msgid="6577581216125805905">"S\'està iniciant la demostració…"</string>
     <string name="demo_restarting_message" msgid="1160053183701746766">"S\'està restablint el dispositiu…"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Treball 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Prova"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Compartit"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Contingut de l\'aplicació amagat de la compartició de pantalla per motius de seguretat"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"S\'ha connectat automàticament a un satèl·lit"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Pots enviar i rebre missatges sense una xarxa mòbil o Wi‑Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Obre Missatges"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index a8ad543..fef6fa6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pořídit snímek obrazovky"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Může pořídit snímek obrazovky."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Náhled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"zakázání či změny stavového řádku"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávání se za stavový řádek"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Otisk prstu nebyl rozpoznán"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Otisk prstu nebyl rozpoznán"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Obličej se nepodařilo rozpoznat. Použijte místo něj otisk prstu."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Obličej nebyl rozpoznán. Použijte místo něj otisk prstu."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Otisk byl ověřen"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Obličej byl ověřen"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Obličej byl ověřen, stiskněte tlačítko pro potvrzení"</string>
@@ -833,16 +835,16 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout tablet nebo vymazat z tabletu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud jich bude zadáno příliš mnoho, uzamknout zařízení Android TV nebo z něj vymazat všechna data."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout informační a zábavní systém nebo vymazat veškerá data v informačním a zábavním systému, pokud je zadáno příliš mnoho nesprávných hesel."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout telefon nebo vymazat z telefonu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sleduje počet nesprávných hesel zadaných při odemykání obrazovky a uzamkne telefon nebo vymaže z telefonu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamknout tablet nebo vymazat veškerá data uživatele."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud jich bude zadáno příliš mnoho, uzamknout zařízení Android TV nebo z něj vymazat všechna data tohoto uživatele."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamknout informační a zábavní systém nebo vymazat veškerá data profilu."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamknout telefon nebo vymazat veškerá data uživatele."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitoruje počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamkne telefon nebo vymaže veškerá data uživatele."</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"Změnit zámek obrazovky"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"Změní se zámek obrazovky."</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"Uzamknout obrazovku"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Určíte, jak a kdy se obrazovka uzamkne."</string>
-    <string name="policylab_wipeData" msgid="1359485247727537311">"Vymazat všechna data"</string>
+    <string name="policylab_wipeData" msgid="1359485247727537311">"Mazat všechna data"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez upozornění smazat všechna data tabletu obnovením továrních dat."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Provést obnovení továrních dat a bez upozornění tím vymazat data v zařízení Android TV."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Bez upozornění se smažou všechna data informačního a zábavního systému obnovením továrních dat."</string>
@@ -1727,9 +1729,9 @@
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Chcete službě <xliff:g id="SERVICE">%1$s</xliff:g> povolit plnou kontrolu nad vaším zařízením?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"Plná kontrola je vhodná u aplikací, které vám pomáhají s usnadněním přístupu. U většiny aplikací však vhodná není."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Zobrazení a ovládání obrazovky"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Služba může číst veškerý obsah obrazovky a zobrazovat ho přes ostatní aplikace."</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Služba může číst veškerý obsah obrazovky a zobrazovat ho přes ostatní aplikace."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Zobrazení a provádění akcí"</string>
-    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Služba může sledovat vaše interakce s aplikací nebo hardwarovým senzorem a komunikovat s aplikacemi namísto vás."</string>
+    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Služba může sledovat vaše interakce s aplikací nebo hardwarovým senzorem a komunikovat s aplikacemi za vás."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Povolit"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Zakázat"</string>
     <string name="accessibility_dialog_button_uninstall" msgid="2952465517671708108">"Odinstalovat"</string>
@@ -1745,7 +1747,7 @@
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"Převrácení barev"</string>
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Korekce barev"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jedné ruky"</string>
-    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Velmi tmavé"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Velmi tmavé zobrazení"</string>
     <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>
@@ -1898,13 +1900,14 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Před uvolněním požádat o PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Před uvolněním požádat o bezpečnostní gesto"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Před odepnutím požádat o heslo"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Nainstalováno administrátorem"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Aktualizováno administrátorem"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Smazáno administrátorem"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
     <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Spořič baterie zapíná tmavý motiv a omezuje či vypíná aktivitu na pozadí, některé vizuální efekty, některé funkce a připojení k některým sítím."</string>
     <string name="battery_saver_description" msgid="8518809702138617167">"Spořič baterie zapíná tmavý motiv a omezuje či vypíná aktivitu na pozadí, některé vizuální efekty, některé funkce a připojení k některým sítím."</string>
-    <string name="data_saver_description" msgid="4995164271550590517">"S cílem snížit spotřebu dat brání spořič dat některým aplikacím odesílat nebo přijímat data na pozadí. Aplikace, kterou právě používáte, data přenášet může, ale může tak činit méně často. V důsledku toho se například obrázky nemusejí zobrazit, dokud na ně neklepnete."</string>
+    <string name="data_saver_description" msgid="4995164271550590517">"S cílem snížit spotřebu dat brání spořič dat některým aplikacím odesílat nebo přijímat data na pozadí. Aplikace, kterou právě používáte, sice data využívat může, ale méně často. Může to například znamenat, že obrázky se zobrazí, až na ně klepnete."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Chcete zapnout Spořič dat?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Zapnout"</string>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Na jednu minutu (do {formattedTime})}few{Na # minuty (do {formattedTime})}many{Na # minuty (do {formattedTime})}other{Na # minut (do {formattedTime})}}"</string>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Práce 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Komunální"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Obsah aplikace je z bezpečnostních důvodů při sdílení obrazovky skryt"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automaticky připojeno k satelitu"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Zprávy můžete odesílat a přijímat bez mobilní sítě nebo sítě Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Otevřít Zprávy"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 59be3dd..03b17b0 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tag screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan tage et screenshot af skærmen."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingeraftrykket blev ikke genkendt"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingeraftrykket blev ikke genkendt"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ansigtet blev ikke genkendt. Brug fingeraftryk i stedet."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeraftrykket blev godkendt"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansigtet er godkendt"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansigtet er godkendt. Tryk på Bekræft."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Bed om pinkode inden frigørelse"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Bed om oplåsningsmønster ved deaktivering"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bed om adgangskode inden frigørelse"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installeret af din administrator"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Opdateret af din administrator"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet af din administrator"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Arbejde 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Fælles"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Af sikkerhedsmæssige årsager vises appindhold ikke ved skærmdeling"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Der blev automatisk oprettet forbindelse til satellit"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Du kan sende og modtage beskeder uden et mobil- eller Wi-Fi-netværk"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Åbn Beskeder"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b4882fe..ae1da16 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Vorschau – <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingerabdruck nicht erkannt"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingerabdruck nicht erkannt"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Gesicht wurde nicht erkannt. Verwende stattdessen den Fingerabdruck."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Gesicht nicht erkannt. Verwende den Fingerabdruck."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerabdruck wurde authentifiziert"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gesicht authentifiziert"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesicht authentifiziert, bitte bestätigen"</string>
@@ -706,7 +708,7 @@
     <string name="face_acquired_too_far" msgid="2922278214231064859">"Bewege das Smartphone näher heran"</string>
     <string name="face_acquired_too_high" msgid="8278815780046368576">"Bewege das Smartphone nach oben"</string>
     <string name="face_acquired_too_low" msgid="4075391872960840081">"Bewege das Smartphone nach unten"</string>
-    <string name="face_acquired_too_right" msgid="6245286514593540859">"Bewege das Smartphone nach links"</string>
+    <string name="face_acquired_too_right" msgid="6245286514593540859">"Bewege das Smart­phone nach links"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Bewege das Smartphone nach rechts"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Bitte sieh direkt auf dein Gerät."</string>
     <string name="face_acquired_not_detected" msgid="1057966913397548150">"Gesicht nicht erkannt. Smartphone auf Augenhöhe halten."</string>
@@ -1751,7 +1753,7 @@
     <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>
-    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Wenn du zwischen den Funktionen wechseln möchtest, halte die Schaltfläche \"Bedienungshilfen\" gedrückt."</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Wenn du zwischen den Funktionen wechseln möchtest, halte die Schaltfläche „Bedienungshilfen“ gedrückt."</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Wenn du zwischen den Funktionen wechseln möchtest, wische mit zwei Fingern nach oben und halte."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Wenn du zwischen den Funktionen wechseln möchtest, wische mit drei Fingern nach oben und halte."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Vergrößerung"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vor dem Beenden nach PIN fragen"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vor dem Beenden nach Passwort fragen"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Von deinem Administrator installiert"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Von deinem Administrator aktualisiert"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Von deinem Administrator gelöscht"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -1929,12 +1932,9 @@
     <string name="zen_mode_implicit_trigger_description" msgid="5714956693073007111">"Verwaltet von <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"An"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Aus"</string>
-    <!-- no translation found for zen_mode_trigger_summary_divider_text (7461583466043698862) -->
-    <skip />
-    <!-- no translation found for zen_mode_trigger_summary_range_symbol_combination (1804900738798069619) -->
-    <skip />
-    <!-- no translation found for zen_mode_trigger_event_calendar_any (2086784607921121803) -->
-    <skip />
+    <string name="zen_mode_trigger_summary_divider_text" msgid="7461583466043698862">", "</string>
+    <string name="zen_mode_trigger_summary_range_symbol_combination" msgid="1804900738798069619">"<xliff:g id="START">%1$s</xliff:g>–<xliff:g id="END">%2$s</xliff:g>"</string>
+    <string name="zen_mode_trigger_event_calendar_any" msgid="2086784607921121803">"Alle Kalender"</string>
     <string name="muted_by" msgid="91464083490094950">"Einige Töne werden von <xliff:g id="THIRD_PARTY">%1$s</xliff:g> stummgeschaltet"</string>
     <string name="system_error_wipe_data" msgid="5910572292172208493">"Es liegt ein internes Problem mit deinem Gerät vor. Möglicherweise verhält es sich instabil, bis du es auf die Werkseinstellungen zurücksetzt."</string>
     <string name="system_error_manufacturer" msgid="703545241070116315">"Es liegt ein internes Problem mit deinem Gerät vor. Bitte wende dich diesbezüglich an den Hersteller."</string>
@@ -2396,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Geschäftlich 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Gemeinsam genutzt"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App-Inhalte werden aus Sicherheitsgründen bei der Bildschirmfreigabe ausgeblendet"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatisch mit Satellit verbunden"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Du kannst Nachrichten ohne Mobilfunknetz oder WLAN senden und empfangen"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages öffnen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1b88a6a..b9d9c3c 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Λήψη στιγμιότυπου οθόνης"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Μπορεί να τραβήξει στιγμιότυπο της οθόνης."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Προεπισκόπηση, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Δεν είναι δυνατή η αναγνώριση του δακτυλικού αποτυπώματος"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Δεν είναι δυνατή η αναγνώριση του δακτυλικού αποτυπώματος"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Το πρόσωπο δεν αναγνωρίζεται. Χρησιμ. δακτ. αποτ."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Δεν αναγνωρίστηκε. Χρήση δακτυλικού αποτυπώματος."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Εγκαταστάθηκε από τον διαχειριστή σας"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Εργασία 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Δοκιμή"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Κοινόχρηστο"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Για λόγους ασφάλειας, έγινε απόκρυψη του περιεχομένου της εφαρμογής από την κοινή χρήση οθόνης"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Συνδέθηκε αυτόματα με δορυφόρο"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Μπορείτε να στέλνετε και να λαμβάνετε μηνύματα χωρίς δίκτυο κινητής τηλεφωνίας ή Wi-Fi."</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Άνοιγμα Messages"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 5a6c620..e825eae 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingerprint not recognised"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingerprint not recognised"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Can’t recognise face. Use fingerprint instead."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Face not recognised. Use fingerprint instead."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installed by your admin"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Auto-connected to satellite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"You can send and receive messages without a mobile or Wi-Fi network"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Open Messages"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 86fe49c..71b5903 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingerprint not recognized"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingerprint not recognized"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Can’t recognize face. Use fingerprint instead."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Face not recognized. Use fingerprint instead."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated, please press confirm"</string>
@@ -1896,7 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installed by your admin"</string>
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Installed by your admin.\nGo to settings to view granted permissions"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,6 +2395,7 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
+    <string name="redacted_notification_message" msgid="1520587845842228816">"Sensitive notification content hidden"</string>
     <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
     <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Auto connected to satellite"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 4972e1b..f0c5d7a 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingerprint not recognised"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingerprint not recognised"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Can’t recognise face. Use fingerprint instead."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Face not recognised. Use fingerprint instead."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installed by your admin"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Auto-connected to satellite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"You can send and receive messages without a mobile or Wi-Fi network"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Open Messages"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c35c2ff..648693f 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingerprint not recognised"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingerprint not recognised"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Can’t recognise face. Use fingerprint instead."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Face not recognised. Use fingerprint instead."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingerprint authenticated"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Face authenticated"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installed by your admin"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Updated by your admin"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Deleted by your admin"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App content hidden from screen share for security"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Auto-connected to satellite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"You can send and receive messages without a mobile or Wi-Fi network"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Open Messages"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index b7f49980..25d6c18 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎Take screenshot‎‏‎‎‏‎"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎Can take a screenshot of the display.‎‏‎‎‏‎"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎Preview, ‎‏‎‎‏‏‎<xliff:g id="DREAM_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎disable or modify status bar‎‏‎‎‏‎"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎Allows the app to disable the status bar or add and remove system icons.‎‏‎‎‏‎"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎be the status bar‎‏‎‎‏‎"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎Fingerprint not recognized‎‏‎‎‏‎"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎Fingerprint not recognized‎‏‎‎‏‎"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎Can’t recognize face. Use fingerprint instead.‎‏‎‎‏‎"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎Face not recognized. Use fingerprint instead.‎‏‎‎‏‎"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎Fingerprint authenticated‎‏‎‎‏‎"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎Face authenticated‎‏‎‎‏‎"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎Face authenticated, please press confirm‎‏‎‎‏‎"</string>
@@ -1896,7 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎Ask for PIN before unpinning‎‏‎‎‏‎"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎Ask for unlock pattern before unpinning‎‏‎‎‏‎"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎Ask for password before unpinning‎‏‎‎‏‎"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎Installed by your admin‎‏‎‎‏‎"</string>
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎Installed by your admin.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Go to settings to view granted permissions‎‏‎‎‏‎"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎Updated by your admin‎‏‎‎‏‎"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎Deleted by your admin‎‏‎‎‏‎"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎OK‎‏‎‎‏‎"</string>
@@ -2393,6 +2395,7 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎Work 3‎‏‎‎‏‎"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎Test‎‏‎‎‏‎"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎Communal‎‏‎‎‏‎"</string>
+    <string name="redacted_notification_message" msgid="1520587845842228816">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎Sensitive notification content hidden‎‏‎‎‏‎"</string>
     <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
     <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‎App content hidden from screen share for security‎‏‎‎‏‎"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‎‎Auto connected to satellite‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 4f7f7a7..953bfbd 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar capturas de pantalla."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"No se reconoció la huella dactilar"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"No se reconoció la huella dactilar"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"No se reconoce el rostro. Usa la huella dactilar."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"No se reconoció el rostro. Usa la huella dactilar."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Se autenticó la huella dactilar"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Se autenticó el rostro"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se autenticó el rostro; presiona Confirmar"</string>
@@ -1728,7 +1730,7 @@
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Ver y controlar la pantalla"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Puede leer todo el contenido en la pantalla y mostrar contenido sobre otras apps."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Ver y realizar acciones"</string>
-    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Puede realizar el seguimiento de tus interacciones con una app o un sensor de hardware, así como interactuar con las apps por ti."</string>
+    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Puede seguir tus interacciones con una app o un sensor de hardware, así como interactuar con las apps por ti."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Permitir"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Rechazar"</string>
     <string name="accessibility_dialog_button_uninstall" msgid="2952465517671708108">"Desinstalar"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para quitar fijación"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicitar desbloqueo para quitar fijación"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para quitar fijación"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Tu administrador instaló este paquete"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Tu administrador actualizó este paquete"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Tu administrador borró este paquete"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Trabajo 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Probar"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Compartido"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Se ocultó el contenido de la app durante el uso compartido de la pantalla por motivos de seguridad"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Conexión automática a satélite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Puedes enviar y recibir mensajes incluso si no tienes conexión a una red móvil o Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Abrir Mensajes"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index bf9d526..ba2c5e5 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"inhabilitar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Huella digital no reconocida"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Huella digital no reconocida"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"No se reconoce la cara. Usa la huella digital."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Cara no reconocida. Usa la huella digital."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Se ha autenticado la huella digital"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Cara autenticada"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se ha autenticado la cara, pulsa para confirmar"</string>
@@ -710,7 +712,7 @@
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Mueve el teléfono hacia la izquierda"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Mueve el teléfono hacia la derecha"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Mira de forma más directa al dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"No se detecta tu cara. Sujeta el teléfono a la altura de los ojos."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"No se puede detectar tu cara. Sujeta el teléfono a la altura de los ojos."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"El teléfono se mueve demasiado. Mantenlo quieto."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vuelve a registrar tu cara."</string>
     <string name="face_acquired_too_different" msgid="4505278456634706967">"Cara no reconocida. Inténtalo de nuevo."</string>
@@ -1512,7 +1514,7 @@
     <string name="deny" msgid="6632259981847676572">"Denegar"</string>
     <string name="permission_request_notification_title" msgid="1810025922441048273">"Permiso solicitado"</string>
     <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Permiso solicitado\npara la cuenta <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
-    <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"Permiso solicitado por <xliff:g id="APP">%1$s</xliff:g>\npara acceder a la cuenta<xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
+    <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"Permiso solicitado por <xliff:g id="APP">%1$s</xliff:g>\npara acceder a la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
     <string name="forward_intent_to_owner" msgid="4620359037192871015">"Estás usando esta aplicación fuera del perfil de trabajo"</string>
     <string name="forward_intent_to_work" msgid="3620262405636021151">"Estás usando esta aplicación en tu perfil de trabajo"</string>
     <string name="input_method_binding_label" msgid="1166731601721983656">"Método de introducción de texto"</string>
@@ -1897,13 +1899,14 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para desactivar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir patrón de desbloqueo para dejar de fijar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para desactivar"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalado por el administrador"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado por el administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado por el administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
     <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Ahorro de batería activa el tema oscuro y limita o desactiva la actividad en segundo plano, algunos efectos visuales, ciertas funciones y algunas conexiones de red."</string>
     <string name="battery_saver_description" msgid="8518809702138617167">"Ahorro de batería activa el tema oscuro y limita o desactiva la actividad en segundo plano, algunos efectos visuales, ciertas funciones y algunas conexiones de red."</string>
-    <string name="data_saver_description" msgid="4995164271550590517">"Para reducir el uso de datos, el ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano. Si estás usando una aplicación, podrá acceder a datos, pero con menos frecuencia. Esto significa que es posible que, por ejemplo, algunas imágenes no se muestren hasta que las toques."</string>
+    <string name="data_saver_description" msgid="4995164271550590517">"Para reducir el uso de datos, Ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano. Si estás usando una aplicación, podrá acceder a datos, pero con menos frecuencia. Esto significa que es posible que, por ejemplo, algunas imágenes no se muestren hasta que las toques."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"¿Activar Ahorro de datos?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Durante un minuto (hasta las {formattedTime})}many{Durante # minutos (hasta las {formattedTime})}other{Durante # minutos (hasta las {formattedTime})}}"</string>
@@ -2032,7 +2035,7 @@
     <string name="pin_specific_target" msgid="7824671240625957415">"Fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="unpin_target" msgid="3963318576590204447">"No fijar"</string>
     <string name="unpin_specific_target" msgid="3859828252160908146">"No fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="app_info" msgid="6113278084877079851">"Información de la aplicación"</string>
+    <string name="app_info" msgid="6113278084877079851">"Información de la app"</string>
     <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demostración…"</string>
     <string name="demo_restarting_message" msgid="1160053183701746766">"Restableciendo dispositivo…"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Trabajo 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Prueba"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Común"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Contenido de la aplicación oculto en pantalla compartida por motivos de seguridad"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Conectado automáticamente al satélite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Puedes enviar y recibir mensajes sin una red móvil o Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Abre Mensajes"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index cc82e47..b100016 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Jäädvusta ekraanipilt"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Saab jäädvustada ekraanipildi."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Eelvaade, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Sõrmejälge ei tuvastatud"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Sõrmejälge ei tuvastatud"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Nägu ei õnnestu tuvastada. Kasutage sõrmejälge."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Nägu ei tuvastatud. Kasutage sõrmejälge."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Sõrmejälg autenditi"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Nägu on autenditud"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Nägu on autenditud, vajutage käsku Kinnita"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Enne vabastamist küsi PIN-koodi"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Enne vabastamist küsi avamismustrit"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Enne vabastamist küsi parooli"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Administraator on selle installinud"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Administraator on seda värskendanud"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administraator on selle kustutanud"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Töö 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Jagatud"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Rakenduse sisu on ekraani jagamises turvalisuse huvides peidetud"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Satelliidiga loodi automaatselt ühendus"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Teil on võimalik sõnumeid saata ja vastu võtta ilma mobiilside- ja WiFi-võrguta"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Ava rakendus Messages"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 34c0663..4613ac6 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pantaila-argazkiak atera."</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Aurrebista, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzeko edo sistema-ikonoak gehitzeko edo kentzeko baimena ematen dio aplikazioari."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Ez da ezagutu hatz-marka"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Ez da ezagutu hatz-marka"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Ezin da hauteman aurpegia. Erabili hatz-marka."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ez da ezagutu aurpegia. Erabili hatz-marka."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Autentifikatu da hatz-marka"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Autentifikatu da aurpegia"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autentifikatu da aurpegia; sakatu Berretsi"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Eskatu PINa aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Eskatu pasahitza aingura kendu aurretik"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Administratzaileak instalatu du"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2047,7 +2050,7 @@
     <string name="app_category_maps" msgid="6395725487922533156">"Mapak eta nabigazioa"</string>
     <string name="app_category_productivity" msgid="1844422703029557883">"Produktibitatea"</string>
     <string name="app_category_accessibility" msgid="6643521607848547683">"Erabilerraztasuna"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Gailuaren memoria"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Gailuko biltegia"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB bidezko arazketa"</string>
     <string name="time_picker_hour_label" msgid="4208590187662336864">"ordu"</string>
     <string name="time_picker_minute_label" msgid="8307452311269824553">"minutu"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Lanekoa 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Probakoa"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Partekatua"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Aplikazioko edukia ezkutatu egin da pantaila partekatzeko eginbidetik, segurtasuna bermatzeko"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatikoki konektatu da satelitera"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Mezuak bidal eta jaso ditzakezu sare mugikorrik edo wifi-sarerik gabe"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Ireki Mezuak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4f2484e..439eb9b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"گرفتن نماگرفت"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"می‌تواند از نمایشگر نماگرفت بگیرد."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"پیش‌نما، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"‏به برنامه اجازه می‎دهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"اثر انگشت تشخیص داده نشد"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"اثر انگشت تشخیص داده نشد"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"اثر انگشت اصالت‌سنجی شد"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چهره اصالت‌سنجی شد"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چهره اصالت‌سنجی شد، لطفاً تأیید را فشار دهید"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"درخواست کد پین قبل از برداشتن پین"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"درخواست الگوی بازگشایی قفل قبل‌از برداشتن سنجاق"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"درخواست گذرواژه قبل از برداشتن سنجاق"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"توسط سرپرست سیستم نصب شد"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"کار ۳"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"آزمایش"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"عمومی"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"به‌دلایل امنیتی، محتوای برنامه از دید هم‌رسانی صفحه‌نمایش پنهان شد"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"به‌طور خودکار به ماهواره متصل شد"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"‏می‌توانید بدون شبکه تلفن همراه یا Wi-Fi پیام ارسال و دریافت کنید"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"باز کردن «پیام‌ها»"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 81b9848..aa87f24 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ota kuvakaappaus"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Voi ottaa kuvakaappauksen näytöstä."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Esikatselu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Sormenjälkeä ei tunnistettu"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Sormenjälkeä ei tunnistettu"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Kasvoja ei voi tunnistaa. Käytä sormenjälkeä."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Kasvoja ei tunnistettu. Käytä sormenjälkeä."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Sormenjälki tunnistettu"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Kasvot tunnistettu"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Kasvot tunnistettu, valitse Vahvista"</string>
@@ -841,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Lukita ruudun"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Hallinnoida, milloin ja miten näyttö lukittuu."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Pyyhkiä kaikki tiedot"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Tyhjennä tablet-laitteen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Tyhjentää tablet-laitteen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Tyhjentää Android TV ‑laitteen tiedot ilman varoitusta palauttamalla tehdasasetukset."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Poistaa infotainment-järjestelmän datan ilman varoitusta palauttamalla tehdasasetukset."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Tyhjentää puhelimen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
@@ -1384,7 +1386,7 @@
     <string name="no_permissions" msgid="5729199278862516390">"Lupia ei tarvita"</string>
     <string name="perm_costs_money" msgid="749054595022779685">"tämä voi maksaa"</string>
     <string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="1674124518282666955">"Laite lataa USB-yhteydellä"</string>
+    <string name="usb_charging_notification_title" msgid="1674124518282666955">"Laitetta ladataan USB:llä"</string>
     <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Ladataan yhdistettyä laitetta USB:n kautta"</string>
     <string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB-tiedostonsiirto on käytössä"</string>
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP USB:n kautta on käytössä"</string>
@@ -1655,7 +1657,7 @@
     <string name="wireless_display_route_description" msgid="8297563323032966831">"Langaton näyttö"</string>
     <string name="media_route_button_content_description" msgid="2299223698196869956">"Suoratoisto"</string>
     <string name="media_route_chooser_title" msgid="6646594924991269208">"Yhdistä laitteeseen"</string>
-    <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"Lähetä näyttö laitteeseen"</string>
+    <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"Striimaa näyttö laitteeseen"</string>
     <string name="media_route_chooser_searching" msgid="6119673534251329535">"Etsitään laitteita…"</string>
     <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"Asetukset"</string>
     <string name="media_route_controller_disconnect" msgid="7362617572732576959">"Katkaise yhteys"</string>
@@ -1896,15 +1898,16 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pyydä PIN ennen irrotusta"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pyydä salasana ennen irrotusta"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Järjestelmänvalvoja asensi tämän."</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Järjestelmänvalvoja päivitti tämän."</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Järjestelmänvalvoja poisti tämän."</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
     <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Virransäästö laittaa tumman teeman päälle ja rajoittaa tai laittaa pois päältä taustatoimintoja, tiettyjä ominaisuuksia sekä joitakin visuaalisia tehosteita ja verkkoyhteyksiä."</string>
     <string name="battery_saver_description" msgid="8518809702138617167">"Virransäästö laittaa tumman teeman päälle ja rajoittaa tai laittaa pois päältä taustatoimintoja, tiettyjä ominaisuuksia sekä joitakin visuaalisia tehosteita ja verkkoyhteyksiä."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Data Saver estää joitakin sovelluksia lähettämästä tai vastaanottamasta tietoja taustalla, jotta datan käyttöä voidaan vähentää. Käytössäsi oleva sovellus voi yhä käyttää dataa, mutta se saattaa tehdä niin tavallista harvemmin. Tämä voi tarkoittaa esimerkiksi sitä, että kuva ladataan vasta, kun kosketat sitä."</string>
-    <string name="data_saver_enable_title" msgid="7080620065745260137">"Otetaanko Data Saver käyttöön?"</string>
-    <string name="data_saver_enable_button" msgid="4399405762586419726">"Ota käyttöön"</string>
+    <string name="data_saver_enable_title" msgid="7080620065745260137">"Laitetaanko Data Saver päälle?"</string>
+    <string name="data_saver_enable_button" msgid="4399405762586419726">"Laita päälle"</string>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Yhdeksi minuutiksi ({formattedTime} asti)}other{# minuutiksi ({formattedTime} asti)}}"</string>
     <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Yhdeksi minuutiksi ({formattedTime} asti)}other{# minuutiksi ({formattedTime} asti)}}"</string>
     <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Yhdeksi tunniksi ({formattedTime} asti)}other{# tunniksi ({formattedTime} asti)}}"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Työ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Testi"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Jaettu"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sovelluksen sisältö piilotettu näytön jakamiselta turvallisuussyistä"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Yhdistetty automaattisesti satelliittiin"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Voit lähettää ja vastaanottaa viestejä ilman mobiili‑ tai Wi-Fi-verkkoa"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Avaa Messages"</string>
diff --git a/core/res/res/values-fr-feminine/strings.xml b/core/res/res/values-fr-feminine/strings.xml
index 2ad85d1..c9c3675 100644
--- a/core/res/res/values-fr-feminine/strings.xml
+++ b/core/res/res/values-fr-feminine/strings.xml
@@ -20,5 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connectée à un réseau mobile plus sécurisé."</string>
+    <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connectée à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonnée"</string>
 </resources>
diff --git a/core/res/res/values-fr-masculine/strings.xml b/core/res/res/values-fr-masculine/strings.xml
index 744ef2b..288c2ca 100644
--- a/core/res/res/values-fr-masculine/strings.xml
+++ b/core/res/res/values-fr-masculine/strings.xml
@@ -20,5 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connecté à un réseau mobile plus sécurisé."</string>
+    <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
 </resources>
diff --git a/core/res/res/values-fr-neuter/strings.xml b/core/res/res/values-fr-neuter/strings.xml
index b4f4cc7..15e3076 100644
--- a/core/res/res/values-fr-neuter/strings.xml
+++ b/core/res/res/values-fr-neuter/strings.xml
@@ -20,5 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connecté·e à un réseau mobile plus sécurisé."</string>
+    <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté·e à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné·e"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 15d36f5..1ce5ba0 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre une capture de l\'écran."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Empreinte digitale non reconnue"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Empreinte digitale non reconnue"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Visage non reconnu. Utilisez l\'empreinte digitale."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur le bouton Confirmer"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le NIP avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installé par votre administrateur"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Mise à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -1930,12 +1933,9 @@
     <string name="zen_mode_implicit_trigger_description" msgid="5714956693073007111">"Géré par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activé"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Désactivé"</string>
-    <!-- no translation found for zen_mode_trigger_summary_divider_text (7461583466043698862) -->
-    <skip />
-    <!-- no translation found for zen_mode_trigger_summary_range_symbol_combination (1804900738798069619) -->
-    <skip />
-    <!-- no translation found for zen_mode_trigger_event_calendar_any (2086784607921121803) -->
-    <skip />
+    <string name="zen_mode_trigger_summary_divider_text" msgid="7461583466043698862">", "</string>
+    <string name="zen_mode_trigger_summary_range_symbol_combination" msgid="1804900738798069619">"<xliff:g id="START">%1$s</xliff:g> – <xliff:g id="END">%2$s</xliff:g>"</string>
+    <string name="zen_mode_trigger_event_calendar_any" msgid="2086784607921121803">"N\'importe quel agenda"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> désactive certains sons"</string>
     <string name="system_error_wipe_data" msgid="5910572292172208493">"Un problème interne est survenu avec votre appareil. Il se peut qu\'il soit instable jusqu\'à ce que vous le réinitialisiez à ses paramètres par défaut."</string>
     <string name="system_error_manufacturer" msgid="703545241070116315">"Un problème interne est survenu avec votre appareil. Communiquez avec le fabricant pour obtenir plus de détails."</string>
@@ -1997,7 +1997,7 @@
     <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Urgence"</string>
     <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Config. Verrouillage d\'écran"</string>
     <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Config. Verrouillage d\'écran"</string>
-    <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Config. VÉ pour util. Esp. pr."</string>
+    <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Configurez verrouillage de l\'écran pour utiliser Espace privé"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"L\'application n\'est pas accessible"</string>
     <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas accessible pour le moment."</string>
     <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non accessible"</string>
@@ -2397,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Professionnel 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Commun"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Le contenu de l\'application est masqué du Partage d\'écran par mesure de sécurité"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Connecté au satellite automatiquement"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Vous pouvez envoyer et recevoir des messages sans avoir recours à un appareil mobile ou à un réseau Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Ouvrir Messages"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 0346822..f94ebac 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -161,7 +161,7 @@
     <string name="scNullCipherIssueEncryptedTitle" msgid="8426373579673205292">"Connexion chiffrée au réseau <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
     <string name="scNullCipherIssueEncryptedSummary" msgid="6437468449554283998">"Vous êtes désormais connecté à un réseau mobile plus sécurisé."</string>
     <string name="scNullCipherIssueNonEncryptedTitle" msgid="2069674849204163569">"Connexion non chiffrée au réseau <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
-    <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté à un réseau mobile non chiffré. Vos appels, messages ainsi que vos données sont vulnérables et donc, susceptibles d\'être interceptés."</string>
+    <string name="scNullCipherIssueNonEncryptedSummary" msgid="3577092996366374833">"Vous êtes connecté à un réseau mobile non chiffré. Vos appels, messages et données sont susceptibles d\'être interceptés."</string>
     <string name="scNullCipherIssueActionSettings" msgid="8378372959891478470">"Paramètres de sécurité des réseaux mobiles"</string>
     <string name="scNullCipherIssueActionLearnMore" msgid="7896642417214757769">"En savoir plus"</string>
     <string name="fcComplete" msgid="1080909484660507044">"Code de service terminé"</string>
@@ -330,7 +330,7 @@
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"enregistrer des fichiers audio"</string>
     <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Activité physique"</string>
     <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"accéder aux données d\'activité physique"</string>
-    <string name="permgrouplab_camera" msgid="9090413408963547706">"Caméra"</string>
+    <string name="permgrouplab_camera" msgid="9090413408963547706">"Appareil photo"</string>
     <string name="permgroupdesc_camera" msgid="7585150538459320326">"prendre des photos et enregistrer des vidéos"</string>
     <string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"Appareils à proximité"</string>
     <string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"détecter des appareils à proximité et s\'y connecter"</string>
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre des captures d\'écran."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"Désactivation ou modification de la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"remplacer la barre d\'état"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Empreinte digitale non reconnue"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Empreinte digitale non reconnue"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Visage non reconnu. Utilisez votre empreinte."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Visage non reconnu. Utilisez votre empreinte."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string>
@@ -726,7 +728,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Impossible de créer votre empreinte faciale. Réessayez."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Lunettes sombres détectées. Votre visage doit être entièrement visible."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Visage partiellement couvert. Votre visage doit être entièrement visible."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Masque détecté. Votre visage doit être entièrement visible."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Imposs. valider visage. Matériel non disponible."</string>
@@ -829,7 +831,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les codes d\'accès de verrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Contrôler les tentatives de déverrouillage de l\'écran"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller la tablette ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Contrôler le nombre de mots de passe incorrects saisis pour déverrouiller l\'écran, et verrouiller la tablette ou effacer toutes ses données si trop de mots de passe incorrects sont saisis"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Contrôle le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouille votre appareil Android TV ou en efface toutes les données si le nombre maximal de mots de passe incorrects autorisé est dépassé."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le système d\'infoloisirs ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le téléphone ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string>
@@ -1059,7 +1061,7 @@
     <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>"</string>
     <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Sélecteur d\'utilisateur"</string>
     <string name="keyguard_accessibility_status" msgid="6792745049712397237">"État"</string>
-    <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Caméra"</string>
+    <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Appareil photo"</string>
     <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Commandes multimédias"</string>
     <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Début de la réorganisation des widgets"</string>
     <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Réorganisation des widgets terminée."</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le code avant de retirer l\'épingle"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant de retirer l\'épingle"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant de retirer l\'épingle"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installé par votre administrateur"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2124,7 +2127,7 @@
     <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Fermer"</string>
     <string name="notification_app_name_system" msgid="3045196791746735601">"Système"</string>
     <string name="notification_app_name_settings" msgid="9088548800899952531">"Paramètres"</string>
-    <string name="notification_appops_camera_active" msgid="8177643089272352083">"Caméra"</string>
+    <string name="notification_appops_camera_active" msgid="8177643089272352083">"Appareil photo"</string>
     <string name="notification_appops_microphone_active" msgid="581333393214739332">"Micro"</string>
     <string name="notification_appops_overlay_active" msgid="5571732753262836481">"se superpose aux autres applications sur l\'écran"</string>
     <string name="notification_feedback_indicator" msgid="663476517711323016">"Envoyer des commentaires"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Professionnel 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Commun"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Le contenu de l\'appli est masqué lors du partage d\'écran pour des raisons de sécurité"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Connecté automatiquement au réseau satellite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Vous pouvez envoyer et recevoir des messages sans connexion au réseau mobile ou Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Ouvrir Messages"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index fa48e96..e3f2f3a 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Facer captura de pantalla"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode facer capturas de pantalla."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar ou modificar a barra de estado"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite á aplicación desactivar a barra de estado ou engadir e quitar as iconas do sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"actuar como a barra de estado"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Non se recoñeceu a impresión dixital"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Non se recoñeceu a impresión dixital"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Non se recoñeceu a cara. Usa a impresión dixital."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Non se recoñeceu a cara. Usa a impresión dixital."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Autenticouse a impresión dixital"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Autenticouse a cara"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autenticouse a cara, preme Confirmar"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcto!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Téntao de novo"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Téntao de novo"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloquea para gozar todas as funcións e datos"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Desbloquear para gozar de todas as funcións e datos"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Superouse o número máximo de intentos de desbloqueo facial"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Non hai SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Non hai ningunha SIM na tableta."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar a fixación"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrón de desbloqueo antes de soltar a fixación"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir contrasinal antes de soltar a fixación"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalado polo teu administrador"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado polo teu administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado polo teu administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
@@ -1970,7 +1973,7 @@
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Sen clasificar"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Ti defines a importancia destas notificacións."</string>
     <string name="importance_from_person" msgid="4235804979664465383">"É importante polas persoas involucradas."</string>
-    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Notificación de aplicacións personalizada"</string>
+    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Notificación de aplicación personalizada"</string>
     <string name="user_creation_account_exists" msgid="2239146360099708035">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Xa existe un usuario con esta conta)"</string>
     <string name="user_creation_adding" msgid="7305185499667958364">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="supervised_user_creation_label" msgid="6884904353827427515">"Engadir usuario supervisado"</string>
@@ -2031,7 +2034,7 @@
     <string name="pin_specific_target" msgid="7824671240625957415">"Fixar a <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="unpin_target" msgid="3963318576590204447">"Deixar de fixar"</string>
     <string name="unpin_specific_target" msgid="3859828252160908146">"Deixar de fixar a <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <string name="app_info" msgid="6113278084877079851">"Información da aplicación"</string>
+    <string name="app_info" msgid="6113278084877079851">"Información da app"</string>
     <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demostración…"</string>
     <string name="demo_restarting_message" msgid="1160053183701746766">"Restablecendo dispositivo…"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Traballo 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Proba"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Compartido"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Por motivos de seguranza, ocultouse o contido da aplicación para que no se mostre na pantalla compartida"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Conexión automática ao satélite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Podes enviar e recibir mensaxes sen unha rede de telefonía móbil ou wifi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Abrir Mensaxes"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index fb202ba..e08a62b 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"સ્ક્રીનશૉટ લો"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ડિસ્પ્લેનો સ્ક્રીનશૉટ લઈ શકે છે."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"પ્રીવ્યૂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ફિંગરપ્રિન્ટ ઓળખી શકાઈ નથી"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ફિંગરપ્રિન્ટ ઓળખી શકાઈ નથી"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ચહેરો ઓળખી શકતા નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ચહેરો ઓળખાયો નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ફિંગરપ્રિન્ટ પ્રમાણિત કરી"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ચહેરા પ્રમાણિત"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ચહેરા પ્રમાણિત, કૃપા કરીને કન્ફર્મ કરો"</string>
@@ -828,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"પાસવર્ડ નિયમો સેટ કરો"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"સ્ક્રીન લૉક પાસવર્ડ અને પિનમાં મંજૂર લંબાઈ અને અક્ષરોને નિયંત્રિત કરો."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"સ્ક્રીનને અનલૉક કરવાના પ્રયત્નોને મૉનિટર કરો"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડ્સની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ્સ લખ્યાં છે તો ટેબ્લેટને લૉક કરો અથવા ટેબ્લેટનો તમામ ડેટા કાઢી નાખો."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ લખ્યાં છે તો ટૅબ્લેટને લૉક કરો અથવા ટૅબ્લેટનો તમામ ડેટા કાઢી નાખો."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"સ્ક્રીનને અનલૉક કરતી વખતે ટાઇપ કરેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ ટાઇપ કર્યા હોય, તો તમારા Android TV ડિવાઇસના ડેટાને લૉક કરો અથવા આ વપરાશકર્તાનો બધો ડેટા કાઢી નાખો."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ લખ્યા હોય તો ઇન્ફોટેનમેન્ટ સિસ્ટમને લૉક કરો અથવા ઇન્ફોટેનમેન્ટ સિસ્ટમનો બધો ડેટા કાઢી નાખો."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડ્સની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ્સ લખ્યાં છે તો ફોનને લૉક કરો અથવા ફોનનો તમામ ડેટા કાઢી નાખો."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"અનપિન કરતા પહેલાં પિન માટે પૂછો"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"અનપિન કરતા પહેલાં અનલૉક પૅટર્ન માટે પૂછો"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"તમારા વ્યવસ્થાપક દ્વારા ઇન્સ્ટૉલ કરવામાં આવેલ છે"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ઑફિસ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"પરીક્ષણ કરો"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"કૉમ્યુનલ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"સુરક્ષા માટે સ્ક્રીન શેર કરતી વખતે ઍપનું કન્ટેન્ટ છુપાવેલું છે"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"સેટેલાઇટ સાથે ઑટોમૅટિક રીતે કનેક્ટેડ"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"તમે મોબાઇલ અથવા વાઇ-ફાઇ નેટવર્ક વિના મેસેજ મોકલી અને પ્રાપ્ત કરી શકો છો"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ખોલો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index fd99d19..f393074 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -278,7 +278,7 @@
     <string name="global_action_settings" msgid="4671878836947494217">"सेटिंग"</string>
     <string name="global_action_assist" msgid="2517047220311505805">"सहायता"</string>
     <string name="global_action_voice_assist" msgid="6655788068555086695">"आवाज़ से डिवाइस का इस्तेमाल"</string>
-    <string name="global_action_lockdown" msgid="2475471405907902963">"फ़ाेन लॉक करें"</string>
+    <string name="global_action_lockdown" msgid="2475471405907902963">"लॉकडाउन"</string>
     <string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
     <string name="notification_hidden_text" msgid="2835519769868187223">"नई सूचना"</string>
     <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"सामान्य कीबोर्ड"</string>
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट लें"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिसप्ले का स्क्रीनशॉट लिया जा सकता है."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> की झलक"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्‍टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string>
@@ -452,7 +454,7 @@
     <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"इससे ऐप्लिकेशन, \"specialUse\" टाइप वाली फ़ोरग्राउंड सेवाओं का इस्तेमाल कर पाता है"</string>
     <string name="permlab_getPackageSize" msgid="375391550792886641">"पता करें कि ऐप मेमोरी में कितनी जगह है"</string>
     <string name="permdesc_getPackageSize" msgid="742743530909966782">"ऐप को उसका कोड, डेटा, और कैश मेमोरी के आकारों को फिर से पाने देता है"</string>
-    <string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्‍टम सेटिंग बदलें"</string>
+    <string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्‍टम की सेटिंग में बदलाव करे"</string>
     <string name="permdesc_writeSettings" msgid="8293047411196067188">"ऐप्लिकेशन को सिस्टम सेटिंग डेटा में बदलाव करने देता है. नुकसान पहुंचाने वाले ऐप्लिकेशन आपके सिस्टम के कॉन्फ़िगरेशन को खराब सकते हैं."</string>
     <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"प्रारंभ होने पर चलाएं"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"ऐप्लिकेशन को सिस्टम से बूटिंग पूरी करते ही अपने आप शुरू करने देता है. इससे टैबलेट को शुरू होने में ज़्यादा समय लग सकता है और ऐप्लिकेशन निरंतर चलाकर संपूर्ण टैबलेट को धीमा करने देता है."</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"फ़िंगरप्रिंट की पहचान नहीं हो पाई"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"फ़िंगरप्रिंट की पहचान नहीं हो पाई"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"चेहरे की पहचान नहीं हुई. फ़िंगरप्रिंट इस्तेमाल करें."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"चेहरा नहीं पहचाना गया. फ़िंगरप्रिंट इस्तेमाल करें."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"फ़िंगरप्रिंट की पुष्टि हो गई"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"चेहरे की पहचान की गई"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string>
@@ -828,10 +830,10 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करना"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"स्‍क्रीन लॉक पासवर्ड और पिन की लंबाई और उनमें स्वीकृत वर्णों को नियंत्रित करना."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"स्‍क्रीन अनलॉक करने की कोशिशों पर नज़र रखना"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्‍क्रीन को अनलॉक करते समय गलत लिखे गए पासवर्ड की संख्‍या पर निगरानी करें, और बहुत ज़्यादा बार गलत पासवर्ड लिखे जाने पर टैबलेट लॉक करें या टैबलेट का संपूर्ण डेटा मिटाएं."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रीन को अनलॉक करते समय ध्यान रखा जाएगा कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो यह टैबलेट को तुरंत लॉक कर देगा या इसका पूरा डेटा मिटा देगा."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने Android TV डिवाइस को तुरंत लॉक करें या इसका सभी डेटा मिटाएं."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो सूचना और मनोरंजन की सुविधा देने वाले डिवाइस को लॉक करें या इस डिवाइस का सारा डेटा मिटाएं."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने फ़ोन को तुरंत लॉक करें या फ़ोन का सारा डेटा मिटा दें."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन को अनलॉक करते समय ध्यान रखेगा कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला जाएगा, तो फ़ोन को तुरंत लॉक करेगा या फ़ोन का सारा डेटा मिटा देगा."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्‍क्रीन का लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार ज़्यादा पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने Android TV डिवाइस को तुरंत लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटाएं."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो सूचना और मनोरंजन की सुविधा देने वाले डिवाइस को लॉक करें या इस प्रोफ़ाइल का सारा डेटा मिटाएं."</string>
@@ -841,10 +843,10 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"स्‍क्रीन लॉक करना"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"इससे यह कंट्रोल होता है कि स्क्रीन कैसे और कब लॉक हो."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"सारा डेटा मिटाना"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"फ़ैक्‍टरी डेटा रीसेट करके चेतावनी दिए बिना फ़ोन का डेटा मिटाना."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"इससे फ़ैक्ट्री डेटा रीसेट करके, चेतावनी दिए बिना फ़ोन का डेटा मिटा दिया जाता है."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"फ़ैक्ट्री डेटा रीसेट करके अपने Android TV डिवाइस का डेटा बिना चेतावनी दिए मिटाएं."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"फ़ैक्ट्री डेटा रीसेट करके, बिना किसी चेतावनी के सूचना और मनोरंजन की सुविधा देने वाले डिवाइस में सेव डेटा को हमेशा के लिए मिटाएं."</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"इससे फ़ैक्‍टरी डेटा रीसेट करके, चेतावनी दिए बिना फ़ोन का डेटा मिट जाता है."</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"फ़ैक्‍टरी डेटा रीसेट करके, चेतावनी दिए बिना फ़ोन का डेटा मिटा देगा."</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"प्रोफ़ाइल का डेटा मिटाना"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"उपयोगकर्ता डेटा मिटाएं"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"इस टैबलेट पर मौजूद इस उपयोगकर्ता का डेटा बिना चेतावनी के मिटा दें."</string>
@@ -990,7 +992,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"लॉक खोलने के लिए मेन्यू दबाएं या आपातलकालीन कॉल करें."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
     <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"अनलॉक करने के लिए आकार आरेखित करें"</string>
-    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"आपातकाल"</string>
+    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"आपातकालीन कॉल"</string>
     <string name="lockscreen_return_to_call" msgid="3156883574692006382">"कॉल पर वापस लौटें"</string>
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"सही!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"फिर से कोशिश करें"</string>
@@ -1655,7 +1657,7 @@
     <string name="wireless_display_route_description" msgid="8297563323032966831">"वायरलेस डिसप्ले"</string>
     <string name="media_route_button_content_description" msgid="2299223698196869956">"कास्ट करें"</string>
     <string name="media_route_chooser_title" msgid="6646594924991269208">"डिवाइस से कनेक्ट करें"</string>
-    <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"स्क्रीन को डिवाइस में कास्ट करें"</string>
+    <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"स्क्रीन को डिवाइस पर कास्ट करें"</string>
     <string name="media_route_chooser_searching" msgid="6119673534251329535">"डिवाइस खोजे जा रहे हैं…"</string>
     <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"सेटिंग"</string>
     <string name="media_route_controller_disconnect" msgid="7362617572732576959">"डिसकनेक्ट करें"</string>
@@ -1722,14 +1724,14 @@
     <string name="accessibility_shortcut_off" msgid="3651336255403648739">"चालू न करें"</string>
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"चालू है"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"बंद है"</string>
-    <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> को अपना डिवाइस पूरी तरह कंट्रोल करने की मंज़ूरी दें?"</string>
+    <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> को अपना डिवाइस पूरी तरह कंट्रोल करने की अनुमति देनी है?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"पूरी तरह कंट्रोल करने की अनुमति उन ऐप्लिकेशन के लिए ठीक है जो सुलभता से जुड़ी ज़रूरतों के लिए बने हैं, लेकिन ज़्यादातर ऐप्लिकेशन के लिए यह ठीक नहीं है."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रीन को देखें और कंट्रोल करें"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"यह स्क्रीन पर दिखने वाले कॉन्टेंट को पढ़ सकता है और उसे दूसरे ऐप्लिकेशन के ऊपर दिखा सकता है."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"देखें और कार्रवाई करें"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"यह आपके और किसी ऐप्लिकेशन या हार्डवेयर सेंसर के बीच होने वाले इंटरैक्शन को ट्रैक कर सकता है और आपकी तरफ़ से ऐप्लिकेशन के साथ इंटरैक्ट कर सकता है."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"अनुमति दें"</string>
-    <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"इंकार करें"</string>
+    <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"न दें"</string>
     <string name="accessibility_dialog_button_uninstall" msgid="2952465517671708108">"अनइंस्टॉल करें"</string>
     <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ऐप्लिकेशन की वजह से, अनुमति का अनुरोध समझने में परेशानी हो रही है. इसलिए, आपके जवाब की पुष्टि नहीं की जा सकी."</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"किसी सुविधा का इस्तेमाल करने के लिए, उस पर टैप करें:"</string>
@@ -1761,7 +1763,7 @@
     <string name="owner_name" msgid="8713560351570795743">"मालिक"</string>
     <string name="guest_name" msgid="8502103277839834324">"मेहमान"</string>
     <string name="error_message_title" msgid="4082495589294631966">"गड़बड़ी"</string>
-    <string name="error_message_change_not_allowed" msgid="843159705042381454">"आपका व्यवस्थापक इस बदलाव की अनुमति नहीं देता"</string>
+    <string name="error_message_change_not_allowed" msgid="843159705042381454">"आपका एडमिन इस बदलाव की अनुमति नहीं देता"</string>
     <string name="app_not_found" msgid="3429506115332341800">"इस कार्यवाही को प्रबंधित करने के लिए कोई ऐप्स  नहीं मिला"</string>
     <string name="revoke" msgid="5526857743819590458">"रद्द करें"</string>
     <string name="mediasize_iso_a0" msgid="7039061159929977973">"ISO A0"</string>
@@ -1896,13 +1898,14 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करने से पहले पिन के लिए पूछें"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करने से पहले लॉक खोलने के पैटर्न के लिए पूछें"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"आपके व्यवस्थापक ने इंस्टॉल किया है"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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="data_saver_description" msgid="4995164271550590517">"डेटा खर्च को कम करने के लिए, डेटा बचाने की सेटिंग कुछ ऐप्लिकेशन को बैकग्राउंड में डेटा भेजने या डेटा पाने से रोकती है. फ़िलहाल, जिस ऐप्लिकेशन का इस्तेमाल किया जा रहा है वह डेटा ऐक्सेस कर सकता है, लेकिन ऐसा कभी-कभी ही हो पाएगा. उदाहरण के लिए, इमेज तब तक नहीं दिखेंगी, जब तक उन पर टैप नहीं किया जाएगा."</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>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{एक मिनट के लिए ({formattedTime} तक)}one{# मिनट के लिए ({formattedTime} तक)}other{# मिनट के लिए ({formattedTime} तक)}}"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ऑफ़िस 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"टेस्ट"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"कम्यूनिटी"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रीन शेयर करने के दौरान सुरक्षा के लिए, ऐप्लिकेशन का कॉन्टेंट छिपाया गया"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"सैटलाइट से अपने-आप कनेक्ट हो गया"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"मोबाइल या वाई-फ़ाई नेटवर्क के बिना भी मैसेज भेजे और पाए जा सकते हैं"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ऐप्लिकेशन खोलें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 5ac09ec..33cde13 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Snimi zaslon"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Možete napraviti snimku zaslona."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmjena trake statusa"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"biti traka statusa"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Otisak prsta nije prepoznat"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Otisak prsta nije prepoznat"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Prepoznavanje lica nije uspjelo. Upotrijebite otisak prsta."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Lice nije prepoznato. Upotrijebite otisak prsta."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Autentificirano otiskom prsta"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Lice je autentificirano"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je autentificirano, pritisnite Potvrdi"</string>
@@ -1420,7 +1422,7 @@
     <string name="share_remote_bugreport_action" msgid="7630880678785123682">"DIJELI"</string>
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"ODBIJ"</string>
     <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="show_ime" msgid="6406112007347443383">"Zadržava se na zaslonu dok je fizička tipkovnica aktivna"</string>
     <string name="hardware" msgid="3611039921284836033">"Upotreba zaslonske tipkovnice"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Konfigurirajte uređaj <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"Konfigurirajte fizičke tipkovnice"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži zaporku radi otkvačivanja"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalirao administrator"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao administrator"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao administrator"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"U redu"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Posao 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Zajedničko"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Sadržaj aplikacije sakriven je od dijeljenja zaslona radi sigurnosti"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatski povezano sa satelitom"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Možete slati i primati poruke bez mobilne mreže ili Wi-Fi mreže"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Otvori Poruke"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 06ca1b6..acf2266 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Képernyőkép készítése"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Készíthet képernyőképet a kijelzőről."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Előnézet, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"állapotsor kikapcsolása vagy módosítása"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"az állapotsor szerepének átvétele"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Az ujjlenyomat nem ismerhető fel"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Az ujjlenyomat nem ismerhető fel"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Az arc nem felismerhető. Használjon ujjlenyomatot."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Sikertelen arcfelismerés. Használja ujjlenyomatát."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Ujjlenyomat hitelesítve"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Arc hitelesítve"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Arc hitelesítve; nyomja meg a Megerősítés lehetőséget"</string>
@@ -1723,7 +1725,7 @@
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"BE"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"KI"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Teljes körű vezérlést biztosít eszköze felett a(z) <xliff:g id="SERVICE">%1$s</xliff:g> szolgáltatás számára?"</string>
-    <string name="accessibility_service_warning_description" msgid="291674995220940133">"A teljes vezérlés indokolt olyan alkalmazásoknál, amelyek kisegítő lehetőségeket nyújtanak, a legtöbb alkalmazásnál azonban nem."</string>
+    <string name="accessibility_service_warning_description" msgid="291674995220940133">"A teljes körű vezérlés indokolt olyan alkalmazásoknál, amelyek kisegítő lehetőségeket nyújtanak, a legtöbb alkalmazásnál azonban nem."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Képernyő megtekintése és kezelése"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Elolvashatja a képernyő tartalmát, és tartalmakat jeleníthet meg más alkalmazások felett."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Műveletek megtekintése és elvégzése"</string>
@@ -1894,9 +1896,10 @@
     <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> klónozása"</string>
     <string name="private_profile_label_badge" msgid="1712086003787839183">"Privát <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a kitűzés feloldásához"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a rögzítés feloldásához"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a kitűzés feloldásához"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Jelszó kérése a rögzítés feloldásához"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"A rendszergazda által telepítve"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"A rendszergazda által frissítve"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"A rendszergazda által törölve"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"3. munkahelyi"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Teszt"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Közös"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"A biztonság érdekében a képernyőmegosztástól elrejtett alkalmazástartalom"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatikusan csatlakozva a műholdhoz"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Küldhet és fogadhat üzeneteket mobil- és Wi-Fi-hálózat nélkül is"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"A Messages megnyitása"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 89e087e..8ca4708 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Սքրինշոթի ստեղծում"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Կարող է ստեղծել էկրանի սքրինշոթ։"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Նախադիտում, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string>
@@ -647,22 +649,22 @@
     <string name="biometric_error_generic" msgid="6784371929985434439">"Չհաջողվեց նույնականացնել"</string>
     <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Էկրանի կողպում"</string>
     <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Շարունակելու համար ապակողպեք էկրանը"</string>
-    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Մատը ուժեղ սեղմեք սկաների վրա"</string>
+    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Մատը ուժեղ սեղմեք սկաներին"</string>
     <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Մատնահետքը չի ճանաչվել։ Նորից փորձեք։"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Մաքրեք մատնահետքերի սկաները և նորից փորձեք"</string>
     <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Մաքրեք սկաները և նորից փորձեք"</string>
-    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Մատը ուժեղ սեղմեք սկաների վրա"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Մատը ուժեղ սեղմեք սկաներին"</string>
     <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_try_adjusting" msgid="3667006071003809364">"Փորձեք փոխել մատի դիրքը"</string>
-    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Թեթևակի փոխեք մատի դիրքն ամեն անգամ"</string>
+    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Ամեն անգամ թեթևակի փոխեք մատի դիրքը"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Մատնահետքը չի ճանաչվել"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Մատնահետքը չի ճանաչվել"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Դեմքը չի հաջողվում ճանաչել։ Օգտագործեք մատնահետքը։"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Դեմքը չի ճանաչվել։ Օգտագործեք մատնահետքը։"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Մատնահետքը նույնականացվեց"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Դեմքը ճանաչվեց"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Դեմքը ճանաչվեց: Սեղմեք «Հաստատել»:"</string>
@@ -704,8 +706,8 @@
     <string name="face_acquired_too_dark" msgid="8539853432479385326">"Թույլ լուսավորություն"</string>
     <string name="face_acquired_too_close" msgid="4453646176196302462">"Փոքր-ինչ հեռու պահեք հեռախոսը"</string>
     <string name="face_acquired_too_far" msgid="2922278214231064859">"Մոտեցրեք հեռախոսը"</string>
-    <string name="face_acquired_too_high" msgid="8278815780046368576">"Պահեք հեռախոսն ավելի վերև"</string>
-    <string name="face_acquired_too_low" msgid="4075391872960840081">"Պահեք հեռախոսն ավելի ներքև"</string>
+    <string name="face_acquired_too_high" msgid="8278815780046368576">"Հեռախոսը շարժեք ավելի վերև"</string>
+    <string name="face_acquired_too_low" msgid="4075391872960840081">"Հեռախոսը շարժեք ավելի ներքև"</string>
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Հեռախոսը շարժեք դեպի ձախ"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Հեռախոսը շարժեք դեպի աջ"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Նայեք ուղիղ էկրանին։"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Հարցնել PIN կոդը"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Հարցնել ապակողպող նախշը"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Հարցնել գաղտնաբառը"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Տեղադրվել է ձեր ադմինիստրատորի կողմից"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -1970,7 +1973,7 @@
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Չդասակարգված"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Դուք սահմանել եք այս ծանուցումների կարևորությունը:"</string>
     <string name="importance_from_person" msgid="4235804979664465383">"Կարևոր է, քանի որ որոշակի մարդիկ են ներգրավված:"</string>
-    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Հավելվածի հատուկ ծանուցում"</string>
+    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Հատուկ հավելվածի ծանուցում"</string>
     <string name="user_creation_account_exists" msgid="2239146360099708035">"Թույլատրե՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտատեր ստեղծել (նման հաշվով Օգտատեր արդեն գոյություն ունի):"</string>
     <string name="user_creation_adding" msgid="7305185499667958364">"Թույլատրե՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտատեր ստեղծել:"</string>
     <string name="supervised_user_creation_label" msgid="6884904353827427515">"Ավելացնել վերահսկվող օգտատեր"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Աշխատանքային 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Փորձնական"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Ընդհանուր"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Անվտանգության նկատառումներից ելնելով՝ հավելվածի բովանդակությունը թաքցվել է էկրանի ցուցադրումից"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Ավտոմատ միացել է արբանյակին"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Դուք կարող եք ուղարկել և ստանալ հաղորդագրություններ՝ առանց բջջային կամ Wi-Fi կապի"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Բացել Messages-ը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 616b30b..5d2ffd4 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Dapat mengambil screenshot tampilan."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pratinjau, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"nonaktifkan atau ubah bilah status"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"jadikan bilah status"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Sidik jari tidak dikenali"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Sidik jari tidak dikenali"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Tidak dapat mengenali wajah. Gunakan sidik jari."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Wajah tidak dikenali. Gunakan sidik jari."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Sidik jari diautentikasi"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Wajah diautentikasi"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah diautentikasi, silakan tekan konfirmasi"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Perbaiki!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Coba lagi"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Coba lagi"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Membuka kunci untuk semua fitur dan data"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Buka kunci untuk melihat semua fitur dan data"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Percobaan Buka dengan Wajah melebihi batas maksimum"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Tidak ada SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Tidak ada SIM di tablet."</string>
@@ -1367,7 +1369,7 @@
     <string name="sim_removed_message" msgid="8469588437451533845">"Jaringan seluler tidak akan tersedia sampai Anda memulai ulang dengan SIM yang valid."</string>
     <string name="sim_done_button" msgid="6464250841528410598">"Selesai"</string>
     <string name="sim_added_title" msgid="2976783426741012468">"SIM ditambahkan"</string>
-    <string name="sim_added_message" msgid="6602906609509958680">"Mulai ulang perangkat Anda untuk mengakses jaringan selular."</string>
+    <string name="sim_added_message" msgid="6602906609509958680">"Mulai ulang perangkat Anda untuk mengakses jaringan seluler."</string>
     <string name="sim_restart_button" msgid="8481803851341190038">"Mulai Ulang"</string>
     <string name="install_carrier_app_notification_title" msgid="5712723402213090102">"Aktifkan layanan seluler"</string>
     <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Download aplikasi operator untuk mengaktifkan SIM baru"</string>
@@ -1725,9 +1727,9 @@
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Izinkan <xliff:g id="SERVICE">%1$s</xliff:g> mengontrol perangkat Anda secara penuh?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"Kontrol penuh sesuai untuk aplikasi yang mendukung kebutuhan aksesibilitas Anda, tetapi tidak untuk sebagian besar aplikasi."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Melihat dan mengontrol layar"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Voice Access dapat membaca semua konten di layar dan menampilkan konten di atas aplikasi lain."</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Membaca semua konten di layar dan menampilkan konten di atas aplikasi lain."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Menampilkan dan melakukan tindakan"</string>
-    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Voice Access dapat melacak interaksi Anda dengan aplikasi atau sensor hardware, dan berinteraksi dengan aplikasi untuk Anda."</string>
+    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Melacak interaksi Anda dengan aplikasi atau sensor hardware, dan berinteraksi dengan aplikasi untuk Anda."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Izinkan"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Tolak"</string>
     <string name="accessibility_dialog_button_uninstall" msgid="2952465517671708108">"Uninstal"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Meminta PIN sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Meminta sandi sebelum melepas sematan"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Diinstal oleh admin Anda"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Diupdate oleh admin Anda"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Dihapus oleh admin Anda"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Oke"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Pengujian"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Konten aplikasi disembunyikan dari berbagi layar untuk alasan keamanan"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Menghubungkan otomatis ke satelit"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Anda dapat mengirim dan menerima pesan tanpa jaringan seluler atau Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Buka Message"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 5d55ba8..b304edc 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -306,7 +306,7 @@
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string>
     <string name="foreground_service_multiple_separator" msgid="5002287361849863168">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
     <string name="safeMode" msgid="8974401416068943888">"Örugg stilling"</string>
-    <string name="android_system_label" msgid="5974767339591067210">"Android kerfið"</string>
+    <string name="android_system_label" msgid="5974767339591067210">"Android-kerfið"</string>
     <string name="user_owner_label" msgid="8628726904184471211">"Skipta yfir í einkasnið"</string>
     <string name="managed_profile_label" msgid="7316778766973512382">"Skipta yfir í vinnusnið"</string>
     <string name="user_owner_app_label" msgid="1553595155465750298">"Skipta yfir í einkasnið <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Taka skjámynd"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Getur tekið skjámynd af skjánum."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Forskoðun, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"slökkva á eða breyta stöðustiku"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vera stöðustikan"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingrafar þekkist ekki"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingrafar þekkist ekki"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Andlit þekkist ekki. Notaðu fingrafar í staðinn."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ekki tókst að bera kennsl á andlit. Notaðu fingrafar í staðinn."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingrafar staðfest"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Andlit staðfest"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Andlit staðfest, ýttu til að staðfesta"</string>
@@ -1723,9 +1725,9 @@
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"KVEIKT"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"SLÖKKT"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Viltu leyfa „<xliff:g id="SERVICE">%1$s</xliff:g>“ að hafa fulla stjórn yfir tækinu þínu?"</string>
-    <string name="accessibility_service_warning_description" msgid="291674995220940133">"Full stjórnun er viðeigandi fyrir forrit sem hjálpa þér ef þú hefur ekki aðgang, en ekki fyrir flest forrit."</string>
+    <string name="accessibility_service_warning_description" msgid="291674995220940133">"Full stjórn er viðeigandi fyrir forrit sem hjálpa þér ef þú hefur ekki aðgang, en ekki fyrir flest forrit."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Skoða og stjórna skjá"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Það getur lesið allt efni á skjánum og birt efni yfir öðrum forritum."</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Getur lesið allt efni á skjánum og birt efni yfir öðrum forritum."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Skoða og framkvæma aðgerðir"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Það getur fylgst með samskiptum þínum við forrit eða skynjara vélbúnaðar og haft samskipti við forrit fyrir þína hönd."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Leyfa"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Biðja um PIN-númer til að losa"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Biðja um opnunarmynstur til að losa"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Biðja um aðgangsorð til að losa"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Kerfisstjóri setti upp"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Kerfisstjóri uppfærði"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Vinna 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Prófun"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Sameiginlegt"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Efni forrits falið í skjádeilingu af öryggisástæðum"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Tengdist sjálfkrafa við gervihnött"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Þú getur sent og móttekið skilaboð án tengingar við farsímakerfi eða Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Opna Messages"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 9d8d74a..00b79b6 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Acquisire screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Può acquisire uno screenshot del display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> in anteprima"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"disattivazione o modifica della barra di stato"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ruolo di barra di stato"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Impronta non riconosciuta"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Impronta non riconosciuta"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Impossibile riconoscere il volto. Usa l\'impronta."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Volto non riconosciuto. Usa l\'impronta."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Impronta autenticata"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Volto autenticato"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Volto autenticato, premi Conferma"</string>
@@ -1193,7 +1195,7 @@
     <string name="low_internal_storage_view_text_no_boot" msgid="7368968163411251788">"Memoria insufficiente per il sistema. Assicurati di avere 250 MB di spazio libero e riavvia."</string>
     <string name="app_running_notification_title" msgid="8985999749231486569">"<xliff:g id="APP_NAME">%1$s</xliff:g> è in esecuzione"</string>
     <string name="app_running_notification_text" msgid="5120815883400228566">"Tocca per ulteriori informazioni o per interrompere l\'app."</string>
-    <string name="ok" msgid="2646370155170753815">"OK"</string>
+    <string name="ok" msgid="2646370155170753815">"Ok"</string>
     <string name="cancel" msgid="6908697720451760115">"Annulla"</string>
     <string name="yes" msgid="9069828999585032361">"OK"</string>
     <string name="no" msgid="5122037903299899715">"Annulla"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Richiedi il PIN per lo sblocco"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Richiedi sequenza di sblocco prima di sbloccare"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Richiedi password prima di sbloccare"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installato dall\'amministratore"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Lavoro 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Condiviso"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Contenuti dell\'app nascosti dalla condivisione schermo per sicurezza"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Connessione automatica al satellite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Puoi inviare e ricevere messaggi senza una rete mobile o Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Apri Messaggi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index c256de9..861e294 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"צילום המסך"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"תצוגה מקדימה, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"השבתה או שינוי של שורת הסטטוס"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשרת לאפליקציה להשבית את שורת הסטטוס או להוסיף ולהסיר סמלי מערכת."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"טביעת האצבע לא זוהתה"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"טביעת האצבע לא זוהתה"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"לא ניתן לזהות את הפנים. יש להשתמש בטביעת אצבע במקום."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"הפנים לא זוהו. צריך להשתמש בטביעת אצבע במקום זאת."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"טביעת האצבע אומתה"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"זיהוי הפנים בוצע"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"יש לבקש קוד אימות לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"צריך לבקש קו ביטול נעילה לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"יש לבקש סיסמה לפני ביטול הצמדה"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"הותקנה על ידי מנהל המערכת"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2167,7 +2170,7 @@
     <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"‏Bluetooth יישאר מופעל במהלך מצב טיסה"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"בטעינה"</string>
     <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} ועוד קובץ אחד}one{{file_name} ועוד # קבצים}two{{file_name} ועוד # קבצים}other{{file_name} ועוד # קבצים}}"</string>
-    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"אין אנשים שניתן לשתף איתם"</string>
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"אין המלצות עם מי לשתף"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"רשימת האפליקציות"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"‏לאפליקציה זו לא ניתנה הרשאת הקלטה, אבל אפשר להקליט אודיו באמצעות התקן ה-USB הזה."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"בית"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"פרופיל עבודה 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"בדיקה"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"שיתופי"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"תוכן האפליקציה מוסתר משיתוף המסך מטעמי אבטחה"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"חיבור אוטומטי ללוויין"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"‏אפשר לשלוח ולקבל הודעות ללא רשת סלולרית או רשת Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"‏לפתיחת Messages"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index eee2e3d..a9365d5 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -196,7 +196,7 @@
     <string name="work_profile_deleted" msgid="5891181538182009328">"仕事用プロファイルが削除されました"</string>
     <string name="work_profile_deleted_details" msgid="3773706828364418016">"仕事用プロファイルの管理アプリがないか、破損しています。そのため仕事用プロファイルと関連データが削除されました。管理者にサポートをご依頼ください。"</string>
     <string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"お使いの仕事用プロファイルはこのデバイスで使用できなくなりました"</string>
-    <string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"パスワード入力回数が上限を超えました"</string>
+    <string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"パスワード入力回数が上限に達しました"</string>
     <string name="device_ownership_relinquished" msgid="4080886992183195724">"管理者により、デバイスの個人使用が許可されました"</string>
     <string name="network_logging_notification_title" msgid="554983187553845004">"管理対象のデバイス"</string>
     <string name="network_logging_notification_text" msgid="1327373071132562512">"このデバイスは組織によって管理され、ネットワーク トラフィックが監視される場合があります。詳しくはタップしてください。"</string>
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"スクリーンショットの撮影"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ディスプレイのスクリーンショットを撮影できます。"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"プレビュー - <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"指紋を認識できません"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"指紋を認識できません"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"顔を認識できません。指紋認証を使用してください。"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"顔を認識できません。指紋認証を使用してください。"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋認証を完了しました"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"顔を認証しました"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"顔を認証しました。[確認] を押してください"</string>
@@ -671,8 +673,8 @@
     <string name="fingerprint_error_timeout" msgid="7361192266621252164">"指紋の設定がタイムアウトしました。もう一度お試しください。"</string>
     <string name="fingerprint_error_canceled" msgid="5541771463159727513">"指紋認証操作がキャンセルされました"</string>
     <string name="fingerprint_error_user_canceled" msgid="2017941773466506863">"指紋認証操作がユーザーによりキャンセルされました"</string>
-    <string name="fingerprint_error_lockout" msgid="6626753679019351368">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string>
+    <string name="fingerprint_error_lockout" msgid="6626753679019351368">"試行回数が上限に達しました。代わりに画面ロックを使用してください。"</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限に達しました。代わりに画面ロックを使用してください。"</string>
     <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"指紋を処理できません。もう一度お試しください。"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="3144806556204061862">"指紋が登録されていません"</string>
     <string name="fingerprint_error_hw_not_present" msgid="5898827259419366359">"このデバイスには指紋認証センサーがありません"</string>
@@ -734,8 +736,8 @@
     <string name="face_error_canceled" msgid="2164434737103802131">"顔の操作をキャンセルしました。"</string>
     <string name="face_error_user_canceled" msgid="5766472033202928373">"顔認証はユーザーによりキャンセルされました"</string>
     <string name="face_error_lockout" msgid="7864408714994529437">"試行回数の上限です。後でもう一度お試しください。"</string>
-    <string name="face_error_lockout_permanent" msgid="8533257333130473422">"試行回数が上限を超えました。顔認証を利用できません。"</string>
-    <string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"試行回数が上限を超えました。代わりに画面ロック解除を入力してください。"</string>
+    <string name="face_error_lockout_permanent" msgid="8533257333130473422">"試行回数が上限に達しました。顔認証を利用できません。"</string>
+    <string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"試行回数が上限に達しました。代わりに画面ロック解除を入力してください。"</string>
     <string name="face_error_unable_to_process" msgid="5723292697366130070">"顔を確認できません。もう一度お試しください。"</string>
     <string name="face_error_not_enrolled" msgid="1134739108536328412">"顔認証を設定していません"</string>
     <string name="face_error_hw_not_present" msgid="7940978724978763011">"このデバイスは顔認証に対応していません"</string>
@@ -828,14 +830,14 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"画面ロックのパスワードとPINの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"画面ロック解除試行の監視"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はタブレットをロックするかタブレットのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合は Android TV デバイスをロックするか Android TV デバイスのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はインフォテインメント システムをロックするかインフォテインメント システムのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はモバイルデバイスをロックするかモバイルデバイスのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合はタブレットをロックするかこのユーザーのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合は Android TV デバイスをロックするかこのユーザーのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はインフォテインメント システムをロックするかこのプロファイルのデータをすべて消去します。"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合はスマートフォンをロックするかこのユーザーのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"画面のロック解除に失敗した回数を監視し、多すぎる場合はタブレットをロックするかタブレットのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"画面のロック解除に失敗した回数を監視し、多すぎる場合は Android TV デバイスをロックするか Android TV デバイスのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"画面のロック解除に失敗した回数を監視し、多すぎる場合はインフォテインメント システムをロックするかインフォテインメント システムのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"画面のロック解除に失敗した回数を監視し、多すぎる場合はモバイルデバイスをロックするかモバイルデバイスのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"画面のロック解除に失敗した回数を監視し、多すぎる場合はタブレットをロックするかこのユーザーのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"画面のロック解除に失敗した回数を監視し、多すぎる場合は Android TV デバイスをロックするかこのユーザーのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"画面のロック解除に失敗した回数を監視し、多すぎる場合はインフォテインメント システムをロックするかこのプロファイルのデータをすべて消去します。"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"画面のロック解除に失敗した回数を監視し、多すぎる場合はスマートフォンをロックするかこのユーザーのデータをすべて消去します。"</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"画面ロックの変更"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"画面ロックを変更します。"</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"画面のロック"</string>
@@ -1420,7 +1422,7 @@
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"共有しない"</string>
     <string name="select_input_method" msgid="3971267998568587025">"入力方法の選択"</string>
     <string name="show_ime" msgid="6406112007347443383">"物理キーボードが有効になっていても画面に表示させます"</string>
-    <string name="hardware" msgid="3611039921284836033">"画面キーボードの使用"</string>
+    <string name="hardware" msgid="3611039921284836033">"画面キーボードを使用"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"<xliff:g id="DEVICE_NAME">%s</xliff:g>の設定"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"物理キーボードの設定"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"タップして言語とレイアウトを選択してください"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"オフライン再生を解除する前にPINの入力を求める"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"オフライン再生を解除する前にパスワードの入力を求める"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"管理者によりインストールされています"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"仕事用 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"テスト"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"セキュリティ上、画面共有ではアプリの内容は非表示となります"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"衛星に自動接続しました"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"モバイル ネットワークや Wi-Fi ネットワークを使わずにメッセージを送受信できます"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"メッセージ アプリを開く"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index ececd92..9cfc999 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ეკრანის ანაბეჭდის გადაღება"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"შეუძლია ეკრანის ანაბეჭდის გადაღება."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"გადახედვა, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"თითის ანაბეჭდის ამოცნობა ვერ მოხერხდა"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"თითის ანაბეჭდის ამოცნობა ვერ მოხერხდა"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"სახის ამოცნობა ვერ ხერხდება. სანაცვლოდ თითის ანაბეჭდი გამოიყენეთ."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"სახის ამოცნობა ვერ მოხერხდა. ცადეთ თითის ანაბეჭდი."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"თითის ანაბეჭდი ავტორიზებულია"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"სახე ავტორიზებულია"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"სახე ავტორიზებულია, დააჭირეთ დადასტურებას"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"დაინსტალირებულია თქვენი ადმინისტრატორის მიერ"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"სამსახური 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"სატესტო"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"საერთო"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ეკრანის გაზიარებიდან აპის კონტენტი დამალულია უსაფრთხოების მიზნით"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"სატელიტთან ავტომატურად დაკავშირებულია"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"შეგიძლიათ გაგზავნოთ და მიიღოთ შეტყობინებები მობილური ან Wi-Fi ქსელის გარეშე"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages-ის გახსნა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 38c6f77..ebfd196 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот жасау"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдің скриншотын жасай аласыз."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Алғы көрініс, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Саусақ ізі танылмады."</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Саусақ ізі танылмады."</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Саусақ ізі аутентификацияланды"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Бет танылды"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Бет танылды, \"Растау\" түймесін басыңыз"</string>
@@ -831,7 +833,7 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экран бекітпесін ашқан кезде терілген қате құпия сөздердің санын бақылау және планшетті бекіту немесе тым көп қате құпия сөздер терілген болса, планшеттің бүкіл деректерін өшіру."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Экранның құлпын ашу кезінде қате енгізілген құпия сөздердің санын бақылау, құпия сөз тым көп қате енгізілген жағдайда, Android TV құрылғысын құлыптау және Android TV құрылғыңыздың барлық деректерінен тазарту."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Экран құлпын ашқан кезде, терілген қате құпия сөздердің саны бақыланады, сондай-ақ құпия сөздер бірнеше рет қате терілсе, ақпараттық-сауықтық жүйе құлыпталады немесе оның барлық дерегі жойылады."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экран бекітпесін ашқан кезде терілген қате құпия сөздердің санын бақылау және телефонды бекіту немесе тым көп қате құпия сөздер терілген болса, телефонның бүкіл деректерін өшіру."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экран құлпын ашқан кезде терілген қате құпия сөздердің санын бақылау және құпия сөз тым көп рет қате терілгенде, телефонды құлыптау немесе оның бүкіл деректерін өшіру."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Экран бекітпесін ашқанда терілген қате құпия сөздердің санын бақылау және тым көп қате құпия сөздер терілсе, планшетті бекіту немесе осы пайдаланушының барлық деректерін өшіру."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Экранның құлпын ашу кезінде қате енгізілген құпия сөздердің санын бақылау, құпия сөз тым көп қате енгізілген жағдайда, Android TV құрылғысын құлыптау және барлық пайдаланушы деректерінен тазарту."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Экран құлпын ашқан кезде, терілген қате құпия сөздердің саны бақыланады, сондай-ақ құпия сөздер бірнеше рет қате терілсе, ақпараттық-сауықтық жүйе құлыпталады немесе осы профильдің барлық дерегі жойылады."</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Дұрыс!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Қайталап көріңіз"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Қайталап көріңіз"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Мүмкіндіктер мен деректер үшін құлыпты ашыңыз"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Барлық функция мен дерек үшін құлыпты ашыңыз"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Бет тану арқылы ашу әрекеттері анықталған шегінен асып кетті"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"SIM картасы жоқ."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Планшетте SIM картасы жоқ."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Босату алдында PIN кодын сұрау"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Босату алдында құпия сөзді сұрау"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Әкімші орнатқан"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -1970,7 +1973,7 @@
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Санатқа жатқызылмаған"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Сіз осы хабарландырулардың маңыздылығын орнатасыз."</string>
     <string name="importance_from_person" msgid="4235804979664465383">"Қатысты адамдарға байланысты бұл маңызды."</string>
-    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Арнаулы хабар хабарландыруы"</string>
+    <string name="notification_history_title_placeholder" msgid="7748630986182249599">"Арнаулы қолданба хабарландыруы"</string>
     <string name="user_creation_account_exists" msgid="2239146360099708035">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты бар жаңа пайдаланушы (мұндай аккаунтқа ие пайдаланушы бұрыннан бар) жасауға рұқсат етілсін бе?"</string>
     <string name="user_creation_adding" msgid="7305185499667958364">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты бар жаңа пайдаланушы жасауға рұқсат етілсін бе?"</string>
     <string name="supervised_user_creation_label" msgid="6884904353827427515">"Бақыланатын пайдаланушыны қосу"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Жұмыс 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Сынақ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Жалпы"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Қауіпсіздік мақсатында қолданба контенті экранды көрсету кезінде жасырылды."</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Жерсерік қызметіне автоматты түрде қосылды"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Мобильдік не Wi-Fi желісіне қосылмастан хабар жібере аласыз және ала аласыз."</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages қолданбасын ашу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 6c0a195..5f6cd38 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ថត​អេក្រង់"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"អាច​ថត​អេក្រង់​នៃ​ផ្ទាំង​អេក្រង់​បាន។"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"មើល​សាកល្បង <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"មិនស្គាល់ស្នាមម្រាមដៃទេ"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"មិនស្គាល់ស្នាមម្រាមដៃទេ"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"មិនអាចសម្គាល់មុខបានទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"មិន​ស្គាល់​មុខទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"បាន​ផ្ទៀង​ផ្ទាត់​ស្នាម​ម្រាមដៃ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"បានផ្ទៀងផ្ទាត់​មុខ"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"បានផ្ទៀងផ្ទាត់​មុខ សូម​ចុច​បញ្ជាក់"</string>
@@ -828,14 +830,14 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"តាមដាន​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ពិនិត្យ​ចំនួន​​បញ្ចូល​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។ ពេល​ដោះ​សោ​អេក្រង់ និង​ចាក់​សោ​ទូរស័ព្ទ ឬ​លុប​ទិន្នន័យ​ទូរស័ព្ទ​ទាំងអស់​ ប្រសិន​បើ​មាន​ពាក្យ​សម្ងាត់​បញ្ចូល​មិន​ត្រឹមត្រូវ​ច្រើន​ដង​ពេក។"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ពិនិត្យ​មើលចំនួនដងនៃការ​​វាយបញ្ចូល​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ នៅពេល​ដោះ​សោ​អេក្រង់ និង​ចាក់​សោ​ថេប្លេត ឬ​លុប​ទិន្នន័យ​ថេប្លេតទាំងអស់​ ប្រសិន​បើ​វាយបញ្ចូលពាក្យ​សម្ងាត់​​មិន​ត្រឹមត្រូវ​ច្រើន​ដង​ពេក។"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ពិនិត្យ​ចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះ​សោអេក្រង់ និងចាក់​សោឧបករណ៍ Android TV របស់អ្នក ឬ​លុបទិន្នន័យ​ឧបករណ៍ Android TV របស់អ្នកទាំងអស់ ប្រសិនបើ​វាយបញ្ចូល​ពាក្យសម្ងាត់​ខុសច្រើនដងពេក។"</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ពិនិត្យមើល​ចំនួនដងនៃការវាយបញ្ចូល​ពាក្យសម្ងាត់​មិនត្រឹមត្រូវ នៅពេល​ដោះសោ​អេក្រង់ និងចាក់សោ​ប្រព័ន្ធ​ព័ត៌មាន​និងកម្សាន្ត ឬ​លុបទិន្នន័យ​ទាំងអស់​របស់ប្រព័ន្ធ​ព័ត៌មាន​និងកម្សាន្ត ប្រសិនបើ​វាយបញ្ចូល​ពាក្យសម្ងាត់​មិនត្រឹមត្រូវ​ច្រើនដងពេក។"</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ពិនិត្យ​ចំនួន​​បញ្ចូល​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។ ពេល​ដោះ​សោ​អេក្រង់ និង​ចាក់​សោ​ទូរស័ព្ទ ឬ​លុប​ទិន្នន័យ​ទូរស័ព្ទ​ទាំងអស់​ ប្រសិន​បើ​មាន​ពាក្យ​សម្ងាត់​បញ្ចូល​មិន​ត្រឹមត្រូវ​ច្រើន​ដង​ពេក។"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ពិនិត្យ​មើលចំនួនដងនៃការ​​វាយបញ្ចូល​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ នៅពេល​ដោះ​សោ​អេក្រង់ និង​ចាក់​សោ​ទូរសព្ទ ឬ​លុប​ទិន្នន័យ​ទូរសព្ទទាំងអស់​ ប្រសិន​បើ​វាយបញ្ចូលពាក្យ​សម្ងាត់​​មិន​ត្រឹមត្រូវ​ច្រើន​ដង​ពេក។"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោថេប្លេត ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ពិនិត្យ​ចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះ​សោអេក្រង់ និងចាក់​សោឧបករណ៍ Android TV របស់អ្នក ឬ​លុបទិន្នន័យ​របស់អ្នកប្រើប្រាស់នេះ​ទាំងអស់ ប្រសិនបើ​វាយបញ្ចូល​ពាក្យសម្ងាត់​ខុសច្រើនដងពេក។"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ពិនិត្យមើល​ចំនួនដងនៃការវាយបញ្ចូល​ពាក្យសម្ងាត់​មិនត្រឹមត្រូវ នៅពេល​ដោះសោ​អេក្រង់ និងចាក់សោ​ប្រព័ន្ធ​ព័ត៌មាន​និងកម្សាន្ត ឬ​លុបទិន្នន័យ​ទាំងអស់​របស់កម្រងព័ត៌មាននេះ ប្រសិនបើ​វាយបញ្ចូល​ពាក្យសម្ងាត់​មិនត្រឹមត្រូវ​ច្រើនដងពេក។"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ពិនិត្យ​មើលចំនួនដងនៃការ​​វាយបញ្ចូល​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ នៅពេល​ដោះ​សោ​អេក្រង់ និង​ចាក់​សោ​ទូរសព្ទ ឬ​លុប​ទិន្នន័យ​ទូរសព្ទទាំងអស់​ ប្រសិន​បើ​វាយបញ្ចូលពាក្យ​សម្ងាត់​​មិន​ត្រឹមត្រូវ​ច្រើន​ដង​ពេក។"</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"ប្តូរការចាក់សោអេក្រង់"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"ប្តូរការចាក់សោអេក្រង់។"</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"ចាក់សោ​អេក្រង់"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ត្រឹមត្រូវ!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ព្យាយាម​ម្ដង​ទៀត"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"ព្យាយាម​ម្ដង​ទៀត"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"ដោះសោលក្ខណៈពិសេស និងទិន្នន័យទាំងអស់"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"ដោះសោមុខងារ និងទិន្នន័យទាំងអស់"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"បាន​លើស​ការ​ព្យាយាម​ដោះ​សោ​តាម​ទម្រង់​មុខ"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"គ្មានស៊ីមទេ"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"គ្មានស៊ីមក្នុងថេប្លេតទេ។"</string>
@@ -1761,7 +1763,7 @@
     <string name="owner_name" msgid="8713560351570795743">"ម្ចាស់"</string>
     <string name="guest_name" msgid="8502103277839834324">"ភ្ញៀវ"</string>
     <string name="error_message_title" msgid="4082495589294631966">"កំហុស"</string>
-    <string name="error_message_change_not_allowed" msgid="843159705042381454">"ការ​ផ្លាស់ប្ដូរ​នេះ​មិន​ត្រូវ​បាន​អនុញ្ញាត​ដោយ​អ្នក​គ្រប់គ្រង​របស់​អ្នក"</string>
+    <string name="error_message_change_not_allowed" msgid="843159705042381454">"ការ​ផ្លាស់ប្ដូរ​នេះ​មិន​ត្រូវ​បាន​អនុញ្ញាត​ដោយ​អ្នក​គ្រប់គ្រង​របស់​អ្នកទេ"</string>
     <string name="app_not_found" msgid="3429506115332341800">"រក​មិន​ឃើញ​កម្មវិធី​ ដើម្បី​គ្រប់គ្រង​សកម្មភាព​នេះ"</string>
     <string name="revoke" msgid="5526857743819590458">"ដកហូត"</string>
     <string name="mediasize_iso_a0" msgid="7039061159929977973">"ISO A0"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"សួរ​រក​កូដ PIN មុន​ពេលដកខ្ទាស់"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"សួរ​រក​លំនាំ​ដោះ​សោ​មុន​ពេលដោះខ្ទាស់"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"សួរ​រក​ពាក្យ​សម្ងាត់​មុន​ពេល​ផ្ដាច់"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"​ដំឡើង​ដោយ​អ្នកគ្រប់គ្រង​របស់​អ្នក"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ការងារទី 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ការធ្វើ​តេស្ត"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"ទូទៅ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"បានលាក់ខ្លឹមសារកម្មវិធីពីការបង្ហាញ​អេក្រង់ដើម្បីសុវត្ថិភាព"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ភ្ជាប់ដោយស្វ័យប្រវត្តិទៅផ្កាយរណប"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"អ្នកអាចផ្ញើ និងទទួលសារដោយមិនប្រើបណ្តាញទូរសព្ទចល័ត ឬ Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"បើក​កម្មវិធី Messages"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index faa46ba..ec92812 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ಪ್ರದರ್ಶನದ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಲ್ಲದು."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ಪೂರ್ವವೀಕ್ಷಣೆ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ಮುಖ ಗುರುತಿಸಲಾಗಿಲ್ಲ. ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string>
@@ -1419,7 +1421,7 @@
     <string name="share_remote_bugreport_action" msgid="7630880678785123682">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"ನಿರಾಕರಿಸಿ"</string>
     <string name="select_input_method" msgid="3971267998568587025">"ಇನ್‌ಪುಟ್‌‌ ವಿಧಾನವನ್ನು ಆರಿಸಿ"</string>
-    <string name="show_ime" msgid="6406112007347443383">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಪರದೆಯ ಮೇಲಿರಿಸಿ"</string>
+    <string name="show_ime" msgid="6406112007347443383">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಸ್ಕ್ರೀನ್ ಮೇಲಿರಿಸಿ"</string>
     <string name="hardware" msgid="3611039921284836033">"ಆನ್-ಸ್ಕ್ರೀನ್ ಕೀಬೋರ್ಡ್ ಬಳಸಿ"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"<xliff:g id="DEVICE_NAME">%s</xliff:g> ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್‌ಗಳನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಸ್ಥಾಪಿಸಿದ್ದಾರೆ"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ಕೆಲಸ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ಪರೀಕ್ಷೆ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"ಸಮುದಾಯ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ಭದ್ರತೆಗಾಗಿ ಸ್ಕ್ರೀನ್‌‌ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯಲ್ಲಿ ಆ್ಯಪ್ ಕಂಟೆಂಟ್‌ ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ಸ್ಯಾಟಲೈಟ್‌ಗೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"ನೀವು ಮೊಬೈಲ್ ಅಥವಾ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್ ಇಲ್ಲದೆಯೇ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಮತ್ತು ಸ್ವೀಕರಿಸಬಹುದು"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ಅನ್ನು ತೆರೆಯಿರಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 9eaa414..5a1af5e 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"스크린샷 촬영"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"디스플레이 스크린샷을 촬영할 수 있습니다."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"미리보기, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"지문이 인식되지 않았습니다."</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"지문을 인식할 수 없습니다."</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"지문이 인증됨"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"얼굴이 인증되었습니다"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"얼굴이 인증되었습니다. 확인을 누르세요"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"고정 해제 이전에 PIN 요청"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"고정 해제 시 잠금 해제 패턴 요청"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"고정 해제 이전에 비밀번호 요청"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"관리자에 의해 설치되었습니다."</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"직장 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"테스트"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"공동"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"보안을 위해 화면 공유에서 앱 콘텐츠가 숨겨집니다."</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"위성에 자동 연결됨"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"모바일 또는 Wi-Fi 네트워크 없이 메시지를 주고 받을 수 있습니다"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"메시지 열기"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 9efccff..6731984 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдин скриншотун тартып алсаңыз болот."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Алдын ала көрүү, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Манжа изи таанылган жок"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Манжа изи таанылган жок"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Жүз таанылган жок. Манжа изин колдонуңуз."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Манжа изи текшерилди"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Жүздүн аныктыгы текшерилди"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Туура!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Дагы аракет кылыңыз"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Дагы аракет кылыңыз"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Элементтердин жана дайындардын кулпусун ачуу"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Функциялар менен колдонмолордун кулпусун ачуу"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Жүзүнөн таанып ачуу аракеттеринин чегинен аштыңыз"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"SIM карта жок"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Планшетте SIM карта жок."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бошотуудан мурун PIN суралсын"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бошотуудан мурун графикалык ачкыч суралсын"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Бошотуудан мурун сырсөз суралсын"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Администраторуңуз орнотуп койгон"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Жумуш 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Сыноо"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Жалпы"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Коопсуздук үчүн колдонмодогу контент бөлүшүлгөн экрандан жашырылды"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Спутникке автоматтык түрдө туташтырылган"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Сиз мобилдик же Wi-Fi тармагы жок эле билдирүүлөрдү жөнөтүп, ала аласыз"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Жазышуулар колдонмосун ачуу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 752e68e..12adb17 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ຖ່າຍຮູບໜ້າຈໍ"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ຕົວຢ່າງ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນ​ແຖບ​ສະ​ຖາ​ນະ"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ບໍ່ຮູ້ຈັກລາຍນິ້ວມື"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ບໍ່ຮູ້ຈັກລາຍນິ້ວມື"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ໃຊ້ລາຍນິ້ວມືແທນ."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ພິສູດຢືນຢັນລາຍນິ້ວມືແລ້ວ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ, ກະລຸນາກົດຢືນຢັນ"</string>
@@ -1877,7 +1879,7 @@
     <string name="restr_pin_try_later" msgid="5897719962541636727">"ລອງໃໝ່ອີກຄັ້ງໃນພາຍຫລັງ."</string>
     <string name="immersive_cling_title" msgid="2307034298721541791">"ການ​ເບິ່ງ​ເຕັມ​ໜ້າ​ຈໍ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ຫາກຕ້ອງການອອກ, ໃຫ້ຮູດຈາກທາງເທິງລົງມາທາງລຸ່ມ."</string>
-    <string name="immersive_cling_positive" msgid="7047498036346489883">"ໄດ້​ແລ້ວ"</string>
+    <string name="immersive_cling_positive" msgid="7047498036346489883">"ເຂົ້າ​ໃຈ​ແລ້ວ"</string>
     <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ໝຸນເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
     <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ເປີດ <xliff:g id="NAME">%s</xliff:g> ໃນໂໝດເຕັມຈໍເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
     <string name="done_label" msgid="7283767013231718521">"ແລ້ວໆ"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"​ຖາມ​ຫາ PIN ກ່ອນ​ຍົກ​ເລີກ​ການປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"​ຖາມ​ຫາ​ຮູບ​ແບບ​ປົດ​ລັອກ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"ຖືກຕິດຕັ້ງໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ວຽກ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ທົດສອບ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"ສ່ວນກາງ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ເນື້ອຫາແອັບຖືກເຊື່ອງໄວ້ຈາກການແບ່ງປັນໜ້າຈໍເພື່ອຄວາມປອດໄພ"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ເຊື່ອມຕໍ່ກັບດາວທຽມໂດຍອັດຕະໂນມັດ"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"ທ່ານສາມາດສົ່ງ ແລະ ຮັບຂໍ້ຄວາມໂດຍບໍ່ຕ້ອງໃຊ້ເຄືອຂ່າຍມືຖື ຫຼື Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"ເປີດ Messages"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2fd6ded..3a95d2c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrano kopijos kūrimas"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Galima sukurti vaizdo ekrano kopiją."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Peržiūra, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"išjungti ar keisti būsenos juostą"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"būti būsenos juosta"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Piršto atspaudas neatpažintas"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Piršto atspaudas neatpažintas"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Veidas neatpažintas. Naudokite kontrolinį kodą."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Veidas neatpažintas. Naudokite piršto atspaudą."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Piršto antspaudas autentifikuotas"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Veidas autentifikuotas"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Veidas autentifikuotas, paspauskite patvirtinimo mygtuką"</string>
@@ -1898,7 +1900,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prašyti PIN kodo prieš atsegant"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Prašyti atrakinimo piešinio prieš atsegant"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Prašyti slaptažodžio prieš atsegant"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Įdiegė administratorius"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Atnaujino administratorius"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Ištrynė administratorius"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Gerai"</string>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Darbas (3)"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Bandymas"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Bendruomenės"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Programos turinys paslėptas bendrinant ekraną saugumo sumetimais"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatiškai prisijungta prie palydovinio ryšio"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Galite siųsti ir gauti pranešimus be mobiliojo ryšio ar „Wi-Fi“ tinklo"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Atidaryti programą „Messages“"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 066cd4b..7e5ee3b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrānuzņēmuma izveide"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Var izveidot displeja ekrānuzņēmumu."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (priekšskatījums)"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Pirksta nospiedums netika atpazīts"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Pirksta nospiedums netika atpazīts"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Nevar atpazīt seju. Lietojiet pirksta nospiedumu."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Seja nav atpazīta. Lietojiet pirksta nospiedumu."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Pirksta nospiedums tika autentificēts."</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Seja autentificēta"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Seja ir autentificēta. Nospiediet pogu Apstiprināt."</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prasīt PIN kodu pirms atspraušanas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pirms atspraušanas pieprasīt atbloķēšanas kombināciju"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pirms atspraušanas pieprasīt paroli"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalēja administrators"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Atjaunināja administrators"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Dzēsa administrators"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Labi"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Darbam (3.)"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Testēšanai"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Kopīgs"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Drošības nolūkos lietotnes saturs kopīgotajā ekrānā ir paslēpts"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automātiski izveidots savienojums ar satelītu"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Varat sūtīt un saņemt ziņojumus bez mobilā vai Wi-Fi tīkla."</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Atvērt lietotni Ziņojumi"</string>
diff --git a/core/res/res/values-mcc404/config.xml b/core/res/res/values-mcc404/config.xml
index 4cadef7..0cb1029 100644
--- a/core/res/res/values-mcc404/config.xml
+++ b/core/res/res/values-mcc404/config.xml
@@ -18,8 +18,6 @@
 -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Whether camera shutter sound is forced or not  (country specific). -->
-    <bool name="config_camera_sound_forced">true</bool>
     <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
     <bool name="config_showAreaUpdateInfoSettings">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc405/config.xml b/core/res/res/values-mcc405/config.xml
index 4cadef7..0cb1029 100644
--- a/core/res/res/values-mcc405/config.xml
+++ b/core/res/res/values-mcc405/config.xml
@@ -18,8 +18,6 @@
 -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Whether camera shutter sound is forced or not  (country specific). -->
-    <bool name="config_camera_sound_forced">true</bool>
     <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
     <bool name="config_showAreaUpdateInfoSettings">true</bool>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index a8d5ea4..3df020a 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зачувување слика од екранот"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да зачува слика од екранот."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"оневозможи или измени статусна лента"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"да стане статусна лента"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Отпечатокот не е препознаен"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Отпечатокот не е препознаен"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Не се препознава ликот. Користете отпечаток."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ликот не е препознаен. Користете отпечаток."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечатокот е проверен"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицето е проверено"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е проверено, притиснете го копчето „Потврди“"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Точно!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Обидете се повторно"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Обидете се повторно"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Отклучи за сите функции и податоци"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Отклучете за пристап до сите функции и податоци"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Максималниот број обиди на отклучување со лик е надминат"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Нема SIM-картичка"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Нема SIM-картичка во таблетот."</string>
@@ -1105,7 +1107,7 @@
     <string name="menu_sym_shortcut_label" msgid="4037566049061218776">"копче Sym+"</string>
     <string name="menu_function_shortcut_label" msgid="2367112760987662566">"копче Function+"</string>
     <string name="menu_space_shortcut_label" msgid="5949311515646872071">"празен простор"</string>
-    <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"внеси"</string>
+    <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"enter"</string>
     <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"избриши"</string>
     <string name="search_go" msgid="2141477624421347086">"Пребарај"</string>
     <string name="search_hint" msgid="455364685740251925">"Пребарување…"</string>
@@ -1674,7 +1676,7 @@
     <string name="kg_wrong_password" msgid="2384677900494439426">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="3680925703673166482">"Погрешен PIN"</string>
     <string name="kg_pattern_instructions" msgid="8366024510502517748">"Употреби ја својата шема"</string>
-    <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Внеси PIN на SIM картичка"</string>
+    <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Внесете PIN за SIM-картичката"</string>
     <string name="kg_pin_instructions" msgid="7355933174673539021">"Впишете PIN"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"Внеси лозинка"</string>
     <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM картичката е сега оневозможена. Внесете ПУК код за да продолжите. Контактирајте го операторот за детали."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Побарај PIN пред откачување"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Побарај шема за откл. пред откачување"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Побарај лозинка пред откачување"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Инсталирано од администраторот"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Работен профил 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Профил за тестирање"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Профил на заедницата"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Од безбедносни причини, содржините на апликацијата се скриени од споделувањето екран"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Поврзано со сателит автоматски"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Може да испраќате и примате пораки без мобилна или Wi-Fi мрежа"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Отворете ја Messages"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 32f2daf..b719ba1 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്‍ഷോട്ട് എടുക്കുക"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്‌പ്ലേയുടെ സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"പ്രിവ്യൂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ഫിംഗർപ്രിന്റ് തിരിച്ചറിഞ്ഞില്ല"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ഫിംഗർപ്രിന്റ് തിരിച്ചറിഞ്ഞില്ല"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"മുഖം തിരിച്ചറിയാനായില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"മുഖം തിരിച്ചറിഞ്ഞിട്ടില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string>
@@ -831,7 +833,7 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്‌വ്ഡുകൾ ടൈപ്പുചെയ്‌തിട്ടുണ്ടെങ്കിൽ ടാബ്‌ലെറ്റ് ലോക്കുചെയ്യുകയോ ടാബ്‌ലെറ്റിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോ ചെയ്യുക."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"സ്‌ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android TV ലോക്ക് ചെയ്യുകയോ Android TV-യിലെ എല്ലാ ഡാറ്റയും മായ്‌ക്കുകയോ ചെയ്യുക."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"സ്ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക. നിരവധി തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌താൽ, ഇൻഫോറ്റേയിൻമെന്റ് സിസ്‌റ്റം ലോക്ക് ചെയ്യുകയോ ഇൻഫോറ്റേയിൻമെന്റ് സിസ്‌റ്റത്തിന്റെ ഡാറ്റ മുഴുവനും മായ്ക്കുകയോ ചെയ്യുക."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്‌വ്ഡുകൾ ടൈപ്പുചെയ്‌തിട്ടുണ്ടെങ്കിൽ ഫോൺ ലോക്കുചെയ്യുകയോ ഫോണിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോചെയ്യുക."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പുചെയ്‌തിട്ടുണ്ടെങ്കിൽ ഫോൺ ലോക്കുചെയ്യുകയോ ഫോണിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോചെയ്യുക."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"സ്‌ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ പാസ്‌വേഡ് ടൈപ്പുചെയ്‌തെങ്കിൽ ടാബ്‌ലെറ്റ് ലോക്കുചെയ്യുകയോ ഈ എല്ലാ ഉപയോക്തൃവിവരവും മായ്‌ക്കുകയോ ചെയ്യുക."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"സ്‌ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android TV ലോക്ക് ചെയ്യുകയോ ഈ ഉപയോക്തൃ ഡാറ്റയെല്ലാം മായ്‌ക്കുകയോ ചെയ്യുക."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"സ്ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്‌ത പാസ്‌വേഡുകളുടെ എണ്ണം നിരീക്ഷിച്ച്, നിരവധി തെറ്റായ പാസ്‌വേഡുകൾ ടൈപ്പ് ചെയ്‌താൽ ഇൻഫോറ്റേയിൻമെന്റ് സിസ്‌റ്റം ലോക്ക് ചെയ്യുകയോ ഈ പ്രൊഫൈലിന്റെ ഡാറ്റ മുഴുവനും മായ്ക്കുകയോ ചെയ്യുക."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"അൺപിന്നിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടൂ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"അൺപിന്നിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടൂ"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"നിങ്ങളുടെ അഡ്‌മിൻ ഇൻസ്റ്റാൾ ചെയ്യുന്നത്"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ഔദ്യോഗികം 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ടെസ്‌റ്റ്"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"കമ്മ്യൂണൽ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ആപ്പ് ഉള്ളടക്കം, അതിന്റെ സുരക്ഷയ്ക്കായി സ്ക്രീൻ പങ്കിടലിൽ നിന്ന് മറച്ചിരിക്കുന്നു"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"സാറ്റലൈറ്റിലേക്ക് സ്വയമേവ കണക്റ്റ് ചെയ്തു"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"മൊബൈലോ വൈഫൈ നെറ്റ്‌വർക്കോ ഇല്ലാതെ തന്നെ സന്ദേശങ്ങൾ അയയ്‌ക്കാനും സ്വീകരിക്കാനും നിങ്ങൾക്ക് കഴിയും"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages തുറക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index a926e60..e6f57a3 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Дэлгэцийн зургийг дарах"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дэлгэцийн зургийг дарах боломжтой."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Урьдчилан үзэх, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Хурууны хээг таньсангүй"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Хурууны хээг таньсангүй"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Царай таних боломжгүй. Оронд нь хурууны хээ ашигла"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Царайг таньсангүй. Оронд нь хурууны хээ ашигла."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Хурууны хээг нотолсон"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Царайг баталгаажууллаа"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string>
@@ -828,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Нууц үгний дүрмийг тохируулах"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Дэлгэц түгжих нууц үг болон ПИН кодны урт болон нийт тэмдэгтийн уртыг хянах."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Дэлгэцийн түгжээг тайлах оролдлогыг хянах"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал таблетыг түгжих болон таблетын бүх датаг арилгана"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Дэлгэцийн түгжээг тайлах үед нууц үгийг буруу оруулах тоог хянах ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал таблетыг түгжинэ эсвэл таблетын бүх өгөгдлийг устгана."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл үүний бүх өгөгдлийг устгана."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Дэлгэцийн түгжээг тайлахад буруу бичиж оруулсан нууц үгний тоог хянаж, инфотэйнмент системийг түгжих эсвэл хэт олон удаа нууц үгийг буруу бичиж оруулсан тохиолдолд инфотэйнмент системийн бүх өгөгдлийг устгана."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах, ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал утсыг түгжиж эсвэл утасны бүх өгөгдлийг арилгана"</string>
@@ -841,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Дэлгэц түгжих"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Дэлгэц хэзээ яаж түгжихийг удирдах"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Бүх өгөгдлийг арилгах"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Үйлдвэрийн дата утгыг өгсөнөөр таблетын дата шууд арилгагдана."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Үйлдвэрийн өгөгдлийн төлөвт шилжсэнээр таблетын өгөгдлийг шууд арилгана уу."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Таны Android TV төхөөрөмжийн өгөгдлийг танд анхааруулалгүйгээр үйлдвэрээс гарсан төлөвт шилжүүлэн устгана."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Үйлдвэрийн өгөгдлийн төлөвт үйлдлийг гүйцэтгэснээр инфотэйнмент системийн өгөгдлийг сануулгагүйгээр устгана."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Сануулахгүйгээр утасны бүх өгөгдлийг арилгаж, үйлдвэрийн өгөгдлийн тохиргоонд шинэчилнэ"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бэхэлснийг болиулахаасаа өмнө ПИН асуух"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бэхэлснийг болиулахаас өмнө түгжээ тайлах хээ асуух"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Таны админ суулгасан"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Ажил 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Туршилт"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Нийтийн"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Аюулгүй байдлын улмаас аппын контентыг дэлгэц хуваалцахаас нуусан"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Хиймэл дагуулд автоматаар холбогдсон"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Та мобайл эсвэл Wi-Fi сүлжээгүйгээр мессеж илгээх болон хүлээн авах боломжтой"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Мессежийг нээх"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index c10b7413..a0529665 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट घ्या"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेचा स्क्रीनशॉट घेऊ शकतो."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"पूर्वावलोकन, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अ‍ॅप ला अनुमती देते."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string>
@@ -615,7 +617,7 @@
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"कीलॉक आणि कोणतीही संबद्ध पासवर्ड सुरक्षितता अक्षम करण्यासाठी अ‍ॅप ला अनुमती देते. उदाहरणार्थ, येणारा फोन कॉल प्राप्त करताना फोन कीलॉक अक्षम करतो, नंतर जेव्हा कॉल समाप्त होतो तेव्हा तो कीलॉक पुन्हा-सक्षम करतो."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"स्क्रीन लॉक क्लिष्टतेची विनंती करा"</string>
     <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"अ‍ॅपला स्क्रीन लॉक क्लिष्टता पातळी (उच्च, मध्यम, खालची किंवा काहीही नाही) जाणून घेऊ देते, जी लांबीची संभाव्य रेंज आणि स्क्रीन लॉकचा प्रकार सूचित करते. अ‍ॅप वापरकर्त्यांना असेदेखील सुचवू शकते की त्यांनी स्क्रीन लॉक ठरावीक पातळीपर्यंत अपडेट करावे, परंतु वापरकर्ते त्याकडे मोकळेपणाने दुर्लक्ष करू शकतात आणि तेथून नेव्हिगेट करू शकतात. स्क्रीन लॉक प्लेनटेक्स्टमध्ये स्टोअर केले जात नसल्यामुळे अ‍ॅपला नेमका पासवर्ड माहीत नसतो याची नोंद घ्या."</string>
-    <string name="permlab_postNotification" msgid="4875401198597803658">"सूचना दाखवा"</string>
+    <string name="permlab_postNotification" msgid="4875401198597803658">"नोटिफिकेशन दाखवा"</string>
     <string name="permdesc_postNotification" msgid="5974977162462877075">"ॲपला सूचना दाखवू देते"</string>
     <string name="permlab_turnScreenOn" msgid="219344053664171492">"स्क्रीन सुरू करा"</string>
     <string name="permdesc_turnScreenOn" msgid="4394606875897601559">"अ‍ॅपला स्क्रीन सुरू करण्याची परवानगी देते."</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"फिंगरप्रिंट ओळखली नाही"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"फिंगरप्रिंट ओळखली नाही"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"चेहरा ओळखता आला नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिंट ऑथेंटिकेट केली आहे"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरा ऑथेंटिकेशन केलेला आहे, कृपया कन्फर्म प्रेस करा"</string>
@@ -828,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करा"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रीन लॉक पासवर्ड आणि पिन मध्ये अनुमती दिलेले लांबी आणि वर्ण नियंत्रित करा."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक प्रयत्नांवर लक्ष ठेवा"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"टाइप केलेल्या अयोग्य पासवर्डांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा टॅबलेट लॉक करा किंवा बरेच पासवर्ड टाइप केले असल्यास टॅबलेटचा सर्व डेटा मिटवा."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"टाइप केलेल्या चुकीच्या पासवर्डच्या संख्येचे निरीक्षण करा. स्क्रीन अनलॉक करताना, टॅबलेट लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास, टॅबलेटचा सर्व डेटा मिटवा."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्ड संख्येचे परीक्षण करते आणि Android TV डिव्हाइस लॉक करते किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास Android TV डिव्हाइसचा सर्व डेटा मिटवते."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"टाइप केलेल्या चुकीच्या पासवर्डच्या संख्येचे निरीक्षण करा. स्क्रीन अनलॉक करताना, इंफोटेनमेंट सिस्टीम लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास, इंफोटेनमेंट सिस्टीमचा सर्व डेटा मिटवा."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन अनलॉक करताना टाइप केलेल्या अयोग्य पासवर्डच्या संख्येवर लक्ष ठेवा. बरेच पासवर्ड टाइप केले असल्यास फोन लॉक करा किंवा फोनचा सर्व डेटा मिटवा."</string>
@@ -841,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"स्क्रीन लॉक करा"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"स्क्रीन कशी आणि केव्हा लॉक होते ते नियंत्रित करा."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"सर्व डेटा मिटवा"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"फॅक्टरी डेटा रीसेट करून चेतावणीशिवाय टॅब्लेटचा डेटा मिटवा."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"फॅक्टरी डेटा रीसेट करून चेतावणीशिवाय टॅबलेटचा डेटा मिटवा."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"चेतावणी न देता फॅक्टरी डेटा रीसेट करून Android TV डिव्हाइसचा डेटा मिटवा."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"फॅक्टरी डेटा रीसेट करून कोणत्याही चेतावणीशिवाय इंफोटेनमेंट सिस्टीमचा डेटा मिटवा."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"फॅक्टरी डेटा रीसेट करून चेतावणीशिवाय फोनचा डेटा मिटवा."</string>
@@ -1761,7 +1763,7 @@
     <string name="owner_name" msgid="8713560351570795743">"मालक"</string>
     <string name="guest_name" msgid="8502103277839834324">"अतिथी"</string>
     <string name="error_message_title" msgid="4082495589294631966">"एरर"</string>
-    <string name="error_message_change_not_allowed" msgid="843159705042381454">"या बदलास आपल्या प्रशासकाद्वारे अनुमती नाही"</string>
+    <string name="error_message_change_not_allowed" msgid="843159705042381454">"या बदलासाठी तुमच्या अ‍ॅडमिनची अनुमती नाही"</string>
     <string name="app_not_found" msgid="3429506115332341800">"ही क्रिया हाताळण्यासाठी कोणताही ॲप्लिकेशन आढळला नाही"</string>
     <string name="revoke" msgid="5526857743819590458">"मागे घ्‍या"</string>
     <string name="mediasize_iso_a0" msgid="7039061159929977973">"ISO A0"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करण्‍यापूर्वी पिन विचारा"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करण्‍यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"आपल्या प्रशासकाने इंस्टॉल केले"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ऑफिस ३"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"चाचणी"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रीन शेअर करताना सुरक्षेसाठी अ‍ॅपमधील आशय लपवला आहे"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"उपग्रहाशी आपोआप कनेक्ट केलेले आहे"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"तुम्ही मोबाइल किंवा वाय-फाय नेटवर्कशिवाय मेसेज पाठवू आणि मिळवू शकता"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages उघडा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 4a4ea88..904d9150 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil tangkapan skrin"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Boleh mengambil tangkapan skrin paparan."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pratonton, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Cap jari tidak dikenali"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Cap jari tidak dikenali"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Tidak mengenali wajah. Gunakan cap jari."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Wajah tidak dikenali. Gunakan cap jari."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Cap jari disahkan"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Wajah disahkan"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah disahkan, sila tekan sahkan"</string>
@@ -706,10 +708,10 @@
     <string name="face_acquired_too_far" msgid="2922278214231064859">"Dekatkan telefon"</string>
     <string name="face_acquired_too_high" msgid="8278815780046368576">"Tinggikan lagi telefon"</string>
     <string name="face_acquired_too_low" msgid="4075391872960840081">"Rendahkan lagi telefon"</string>
-    <string name="face_acquired_too_right" msgid="6245286514593540859">"Gerakkan telefon ke kiri anda"</string>
-    <string name="face_acquired_too_left" msgid="9201762240918405486">"Gerakkan telefon ke kanan anda"</string>
+    <string name="face_acquired_too_right" msgid="6245286514593540859">"Gerakkan telefon ke kiri"</string>
+    <string name="face_acquired_too_left" msgid="9201762240918405486">"Gerakkan telefon ke kanan"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Sila lihat terus pada peranti anda."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Wajah tidak kelihatan. Pegang telefon pada paras mata."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Wajah tidak kelihatan. Pegang telefon pada aras mata."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Terlalu bnyk gerakan. Pegang telefon dgn stabil."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Sila daftarkan semula wajah anda."</string>
     <string name="face_acquired_too_different" msgid="4505278456634706967">"Wajah tidak dikenali. Cuba lagi."</string>
@@ -844,7 +846,7 @@
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Memadamkan data tablet tanpa amaran dengan melakukan tetapan semula data kilang."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Padamkan data peranti Android TV anda tanpa amaran dengan melaksanakan tetapan semula data kilang."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Memadam data sistem maklumat hibur tanpa amaran dengan melakukan tetapan semula data kilang."</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Padamkan data telefon tanpa amaran dengan melakukan tetapan semula data kilang."</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Memadam data telefon tanpa amaran dengan melakukan tetapan semula data kilang."</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Padam data profil"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Padam data pengguna"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Padam data pengguna ini pada tablet ini tanpa amaran."</string>
@@ -1030,7 +1032,7 @@
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"Anda telah mencuba untuk membuka kunci tablet secara salah sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Tablet kini akan ditetapkan semula ke tetapan lalai kilang."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"Anda telah cuba membuka peranti Android TV secara salah sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Peranti Android TV anda kini akan ditetapkan semula kepada tetapan lalai kilang."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Anda telah mencuba untuk membuka kunci telefon secara salah sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Telefon kini akan ditetapkan semula kepada tetapan lalai kilang."</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"Cuba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"Cuba lagi selepas <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Lupa corak?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Buka kunci akaun"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Terlalu banyak percubaan melukis corak"</string>
@@ -1517,7 +1519,7 @@
     <string name="input_method_binding_label" msgid="1166731601721983656">"Kaedah input"</string>
     <string name="sync_binding_label" msgid="469249309424662147">"Penyegerakan"</string>
     <string name="accessibility_binding_label" msgid="1974602776545801715">"Kebolehaksesan"</string>
-    <string name="wallpaper_binding_label" msgid="1197440498000786738">"Kertas dinding"</string>
+    <string name="wallpaper_binding_label" msgid="1197440498000786738">"Hiasan latar"</string>
     <string name="chooser_wallpaper" msgid="3082405680079923708">"Tukar hiasan latar"</string>
     <string name="notification_listener_binding_label" msgid="2702165274471499713">"Pendengar pemberitahuan"</string>
     <string name="vr_listener_binding_label" msgid="8013112996671206429">"Pendengar VR"</string>
@@ -1726,7 +1728,7 @@
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"Kawalan penuh sesuai untuk apl yang membantu anda berkaitan dengan keperluan kebolehaksesan tetapi bukan untuk kebanyakan apl."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Melihat dan mengawal skrin"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Ciri ini boleh membaca semua kandungan pada skrin dan memaparkan kandungan di atas apl lain."</string>
-    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Lihat dan laksanakan tindakan"</string>
+    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Melihat dan melaksanakan tindakan"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Ciri ini boleh menjejaki interaksi anda dengan apl atau penderia perkakasan dan berinteraksi dengan apl bagi pihak anda."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Benarkan"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Tolak"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Minta PIN sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Minta corak buka kunci sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Minta kata laluan sebelum menyahsemat"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Dipasang oleh pentadbir anda"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Dikemas kini oleh pentadbir anda"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Dipadamkan oleh pentadbir anda"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Ujian"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Kandungan apl disembunyikan daripada perkongsian skrin untuk keselamatan"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Disambungkan secara automatik kepada satelit"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Anda boleh menghantar dan menerima mesej tanpa rangkaian mudah alih atau Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Buka Messages"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 8346134..e965f47 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ဖန်သားပြင်ပြသမှုကို ဓာတ်ပုံရိုက်နိုင်ပါသည်။"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> အစမ်းကြည့်ခြင်း"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"လက်ဗွေကို မသိရှိပါ"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"လက်ဗွေကို မသိရှိပါ"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"မျက်နှာကို မမှတ်မိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"မျက်နှာကို မမှတ်မိပါ။ ၎င်းအစား လက်ဗွေသုံးပါ။"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string>
@@ -828,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"စကားဝှက်စည်းမျဥ်းကိုသတ်မှတ်ရန်"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"မျက်နှာပြင်သော့ခတ်သည့် စကားဝှက်များနှင့် PINများရှိ ခွင့်ပြုထားသည့် စာလုံးအရေအတွက်နှင့် အက္ခရာများအား ထိန်းချုပ်ရန်။"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"မျက်နှာပြင်လော့ခ်ဖွင့်ရန် ကြိုးပမ်းမှုများကို စောင့်ကြည့်ခြင်း"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက်၊ စကားဝှက် ရိုက်ထည့်မှု သိပ်များနေလျှင် တက်ဘလက်ကို သော့ခတ်ရန် သို့မဟုတ် တက်ဘလက် ဒေတာ အားလုံးကို ဖျက်ရန်။"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"မျက်နှာပြင် လော့ခ်ဖွင့်ရန် အတွက် မမှန်ကန်သော စကားဝှက် ထည့်သွင်းမှု အကြိမ်ရေကို စောင့်ကြည့်ပြီး မှားယွင်းသည့်စကားဝှက် ထည့်သွင်းမှု အလွန်များပါက တက်ဘလက်ကို လော့ခ်ချသည် (သို့) တက်ဘလက် ဒေတာ အားလုံးကို ဖျက်သည်။"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"မျက်နှာပြင်ကို လော့ခ်ဖွင့်သည့်အခါ စကားဝှက်မှားယွင်းစွာ ရိုက်သွင်းသည့်အကြိမ်ရေကို စောင့်ကြည့်ပြီး မှားယွင်းသည့်အကြိမ်ရေ အလွန်များလာပါက သင့် Android TV စက်ပစ္စည်းကို လော့ခ်ချခြင်း သို့မဟုတ် သင့် Android TV ရှိ အသုံးပြုသူဒေတာများအားလုံးကို ဖျက်ခြင်းတို့ ပြုလုပ်သွားပါမည်။"</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ဖန်သားပြင်လော့ခ်ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက် စကားဝှက် မမှန်မကန် ရိုက်ထည့်မှု များနေလျှင် သတင်းနှင့်ဖျော်ဖြေရေး စနစ်ကို လော့ခ်ချသည် (သို့) ၎င်း၏ ဒေတာအားလုံးကို ဖျက်သည်။"</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"မျက်နှာပြင်ကို လောခ်ဖွင့်ရန်အတွက် ရိုက်ထည့်သည့် မှားယွင်းသောစကားဝှက် အကြိမ်ရေကို စောင့်ကြည့်ပြီး မမှန်သောစကားဝှက် ရိုက်ထည့်မှု အလွန်များနေလျှင် ဖုန်းကိုလော့ခ်ချသည် (သို့) ဖုန်း ဒေတာအားလုံးကို ဖျက်သည်။"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"မှန်ပါသည်"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ထပ် စမ်းပါ"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"ထပ် စမ်းပါ"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"ဝန်ဆောင်မှုနှင့် ဒေတာအားလုံးအတွက် လော့ခ်ဖွင့်ပါ"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"ဝန်ဆောင်မှုနှင့် ဒေတာအားလုံးသုံးရန် လော့ခ်ဖွင့်ပါ"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"မျက်မှာပြ လော့ခ်ဖွင့်ခြင်း ခွင့်ပြုသော အကြိမ်ရေထက် ကျော်လွန်သွားပါပြီ"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"ဆင်းမ်ကတ် မရှိပါ"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"တက်ဘလက်တွင် ဆင်းမ်ကတ်မရှိပါ။"</string>
@@ -1894,9 +1896,10 @@
     <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ပုံတူပွား"</string>
     <string name="private_profile_label_badge" msgid="1712086003787839183">"သီးသန့် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ပင်မဖြုတ်မီ လော့ခ်ဖွင့်ပုံစံကို မေးရန်"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"သင်၏ စီမံခန့်ခွဲသူက ထည့်သွင်းထားသည်"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"အလုပ် ၃"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"စမ်းသပ်မှု"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"အများသုံး"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"အက်ပ်အကြောင်းအရာသည် လုံခြုံရေးအတွက် မျက်နှာပြင် မျှဝေခြင်းမှ ဖျောက်ထားသည်"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ဂြိုဟ်တုနှင့် အလိုအလျောက် ချိတ်ဆက်ထားသည်"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"မိုဘိုင်း (သို့) Wi-Fi ကွန်ရက်မရှိဘဲ မက်ဆေ့ဂျ်များကို ပို့နိုင်၊ လက်ခံနိုင်သည်"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ဖွင့်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 252b413..c6a2f44 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skjermdump"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ikke ta en skjermdump av skjermen."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Forhåndsvisning, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Gjenkjenner ikke fingeravtrykket"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Gjenkjenner ikke fingeravtrykket"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Ansiktet gjenkjennes ikke. Bruk fingeravtrykk."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ansiktet ble ikke gjenkjent. Bruk fingeravtrykk."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeravtrykket er godkjent"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansiktet er autentisert"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet er autentisert. Trykk på Bekreft"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Krev PIN-kode for å løsne app"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Krev opplåsingsmønster for å løsne apper"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Krev passord for å løsne apper"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Installert av administratoren din"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Jobb 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Felles"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Av sikkerhetsgrunner er appinnholdet skjult for skjermdelingen"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatisk tilkoblet satellitt"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Du kan sende og motta meldinger uten mobil- eller wifi-nettverk"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Åpne Meldinger"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 6035bb1..230e701 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -340,7 +340,7 @@
     <string name="permgrouplab_sensors" msgid="9134046949784064495">"बडी सेन्सरहरू"</string>
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"तपाईंको महत्त्वपूर्ण संकेत बारे सेन्सर डेटा पहुँच गर्नुहोस्"</string>
     <string name="permgrouplab_notifications" msgid="5472972361980668884">"सूचनाहरू"</string>
-    <string name="permgroupdesc_notifications" msgid="4608679556801506580">"सूचनाहरू देखाइयोस्"</string>
+    <string name="permgroupdesc_notifications" msgid="4608679556801506580">"सूचनाहरू देखाउनुहोस्"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विन्डो सामग्रीको पुनःबहाली गर्नुहोस्।"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"तपाईँको अन्तरक्रिया भइरहेको विन्डोको सामग्रीको निरीक्षण गर्नुहोस्।"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"छोएर गरिने खोजलाई सुचारु गर्नुहोस्"</string>
@@ -352,17 +352,19 @@
     <string name="capability_title_canPerformGestures" msgid="9106545062106728987">"जेस्चरहरू सम्बन्धी कार्य गर्नुहोस्"</string>
     <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ट्याप, स्वाइप गर्न, थिच्न र अन्य जेस्चरहरू सम्बन्धी कार्य गर्न सक्छ"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फिंगरप्रिन्टका जेस्चरहरू"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका जेस्चर खिच्‍न सक्छ।"</string>
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रिनसट लिनुहोस्"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेको स्क्रिनसट लिन सकिन्छ।"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"प्रिभ्यू, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन एपलाई अनुमति दिन्छ।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टाटस बार हुन दिनुहोस्"</string>
     <string name="permdesc_statusBarService" msgid="6652917399085712557">"एपलाई स्थिति पट्टि हुन अनुमति दिन्छ।"</string>
     <string name="permlab_expandStatusBar" msgid="1184232794782141698">"स्थिति पट्टिलाई विस्तृत/सङ्कुचित गर्नुहोस्"</string>
     <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"एपलाई स्थिति पट्टि विस्तार वा संकुचन गर्न अनुमति दिन्छ।"</string>
-    <string name="permlab_fullScreenIntent" msgid="4310888199502509104">"लक गरिएको डिभाइसमा स्क्रिनभरि देखिने सूचनाहरू देखाइयोस्"</string>
+    <string name="permlab_fullScreenIntent" msgid="4310888199502509104">"लक गरिएको डिभाइसमा स्क्रिनभरि देखिने सूचनाहरू देखाउनुहोस्"</string>
     <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"यो अनुमति दिइएमा एपले लक गरिएको डिभाइसमा स्क्रिनभरि देखिने सूचनाहरू देखाउन सक्छ"</string>
     <string name="permlab_install_shortcut" msgid="7451554307502256221">"सर्टकट इन्स्टल गर्ने"</string>
     <string name="permdesc_install_shortcut" msgid="4476328467240212503">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा एपलाई सर्टकटमा हाल्ने अनुमति दिन्छ।"</string>
@@ -395,7 +397,7 @@
     <string name="permlab_receiveWapPush" msgid="4223747702856929056">"टेक्स्ट म्यासेजहरू (WAP) प्राप्त गर्नुहोस्"</string>
     <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP म्यासेजहरू प्राप्त गर्न र प्रशोधन गर्न एपलाई अनुमति दिन्छ। यो अनुमतिमा मोनिटर गर्ने वा तपाईँलाई पठाइएका म्यासेजहरू तपाईँलाई नदेखाई मेट्ने क्षमता समावेश हुन्छ।"</string>
     <string name="permlab_getTasks" msgid="7460048811831750262">"चलिरहेका एपहरू पुनःबहाली गर्नुहोस्"</string>
-    <string name="permdesc_getTasks" msgid="7388138607018233726">"वर्तमानमा र भरखरै चलिरहेका कार्यहरू बारेको सूचना पुनःबहाली गर्न एपलाई अनुमित दिन्छ। यसले उपकरणमा प्रयोग भएका अनुप्रयोगहरूको बारेमा सूचना पत्ता लगाउन एपलाई अनुमति दिन सक्छ।"</string>
+    <string name="permdesc_getTasks" msgid="7388138607018233726">"वर्तमानमा र भरखरै चलिरहेका कार्यहरू बारेको सूचना पुनःबहाली गर्न एपलाई अनुमित दिन्छ। यसले उपकरणमा प्रयोग भएका एपहरूको बारेमा सूचना पत्ता लगाउन एपलाई अनुमति दिन सक्छ।"</string>
     <string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"प्रोफाइल र यन्त्र मालिकहरूको व्यवस्थापन गराउनुहोस्"</string>
     <string name="permdesc_manageProfileAndDeviceOwners" msgid="7304240671781989283">"एपहरूलाई प्रोफाइल र यन्त्र मालिकहरू सेट गर्ने अनुमति दिनुहोस्।"</string>
     <string name="permlab_reorderTasks" msgid="7598562301992923804">"चलिरहेका एपहरूलाई पुनःक्रम गराउनुहोस्"</string>
@@ -403,7 +405,7 @@
     <string name="permlab_enableCarMode" msgid="893019409519325311">"कार मोड सक्षम गर्नुहोस्"</string>
     <string name="permdesc_enableCarMode" msgid="56419168820473508">"कार मोडलाई सक्षम पार्न एपलाई अनुमति दिन्छ।"</string>
     <string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"एपहरू बन्द गर्नुहोस्"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"एपलाई अन्य अनुप्रयोगहरूको पृष्ठभूमि प्रक्रियाहरू बन्द गर्न अनुमति दिन्छ। यसले अन्य एपहरूलाई चल्नबाट रोक्न सक्दछ।"</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"एपलाई अन्य एपहरूको पृष्ठभूमि प्रक्रियाहरू बन्द गर्न अनुमति दिन्छ। यसले अन्य एपहरूलाई चल्नबाट रोक्न सक्दछ।"</string>
     <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"यो एप अन्य एपहरूमाथि देखा पर्न सक्छ"</string>
     <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"यो एप अन्य एपहरूमाथि वा स्क्रिनका अन्य भागहरूमा देखा पर्न सक्छ। यसले एपको सामान्य प्रयोगमा अवरोध पुर्‍याउन सक्छ र अन्य एपहरू देखा पर्ने तरिकालाई परिवर्तन गर्न सक्छ।"</string>
     <string name="permlab_hideOverlayWindows" msgid="6382697828482271802">"एपका अन्य ओभरलेहरू लुकाउने अनुमति"</string>
@@ -452,7 +454,7 @@
     <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"यसले एपलाई \"specialUse\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू प्रयोग गर्ने अनुमति दिन्छ"</string>
     <string name="permlab_getPackageSize" msgid="375391550792886641">"एप भण्डारण ठाउँको मापन गर्नुहोस्"</string>
     <string name="permdesc_getPackageSize" msgid="742743530909966782">"एपलाई यसको कोड, डेटा, र क्यास आकारहरू पुनःप्राप्त गर्न अनुमति दिन्छ।"</string>
-    <string name="permlab_writeSettings" msgid="8057285063719277394">"प्रणाली सेटिङहरू परिमार्जन गर्नुहोस्"</string>
+    <string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्टम सेटिङ परिमार्जन गर्नुहोस्"</string>
     <string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टमका सेटिङ डेटालाई परिवर्तन गर्नको लागि एपलाई अनुमति दिन्छ। खराब एपहरूले सायद तपाईँको प्रणालीको कन्फिगरेसनलाई क्षति पुर्‍याउन सक्छन्।"</string>
     <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"स्टार्टअपमा चलाउनुहोस्"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"आनुप्रयोगलाई प्रणाली बुट प्रक्रिया पूर्ण हुने बितिकै आफैलाई सुरु गर्ने अनुमति दिन्छ। यसले ट्याब्लेट सुरु गर्नमा ढिला गर्न सक्दछ र एपलाई समग्रमा ट्याब्लेट सधैँ चालु गरेर ढिला बनाउँदछ।"</string>
@@ -476,9 +478,9 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"आगमन तथा बहर्गमन डेटासहित तपाईँको ट्याब्लेटको कल लगको परिमार्जन गर्न एपलाई अनुमति दिन्छ। खराब एपहरूले यसलाई तपाईँको कल लग परिमार्जन गर्न वा मेटाउन प्रयोग गर्न सक्छन्।"</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"एपलाई तपाईंको Android टिभी डिभाइसको आगमन र बहिर्गमन कलसम्बन्धी डेटासहित कल लग परिमार्जन गर्ने अनुमति दिन्छ। हानिकारक एपहरूले यसलाई तपाईंको कल लग मेटाउन वा परिमार्जन गर्न प्रयोग गर्न सक्छन्।"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"एपलाई तपाईंको फोनको आउने र बाहिर जाने कलहरूको बारेको डेटा सहित कल लग परिमार्जन गर्न अनुमति दिन्छ। खराब एपहरूले यसलाई तपाईंको कल लग मेटाउन वा परिमार्जन गर्न प्रयोग गर्न सक्दछ।"</string>
-    <string name="permlab_bodySensors" msgid="662918578601619569">"प्रयोग गरिएका बेला हृदयको गति जस्ता बडी सेन्सरसम्बन्धी डेटा हेरियोस् र प्रयोग गरियोस्"</string>
+    <string name="permlab_bodySensors" msgid="662918578601619569">"प्रयोग गरिएका बेला हृदयको गति जस्ता बडी सेन्सरसम्बन्धी डेटा हेरियोस् र प्रयोग गर्नुहोस्"</string>
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"यसले यो एप प्रयोग गरिँदै गरेका बेला यसलाई हृदयको गति, शरीरको तापक्रम तथा रगतमा रहेको अक्सिजनको प्रतिशत जस्ता बडी सेन्सरसम्बन्धी डेटा हेर्ने तथा प्रयोग गर्ने अनुमति दिन्छ।"</string>
-    <string name="permlab_bodySensors_background" msgid="4912560779957760446">"ब्याकग्राउन्डमा चलेका बेला हृदयको गति जस्ता बडी सेन्सरसम्बन्धी डेटा हेरियोस् र प्रयोग गरियोस्"</string>
+    <string name="permlab_bodySensors_background" msgid="4912560779957760446">"ब्याकग्राउन्डमा चलेका बेला हृदयको गति जस्ता बडी सेन्सरसम्बन्धी डेटा हेरियोस् र प्रयोग गर्नुहोस्"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"यसले यो एप ब्याकग्राउन्डमा चलेका बेला यसलाई हृदयको गति, शरीरको तापक्रम तथा रगतमा रहेको अक्सिजनको प्रतिशत जस्ता बडी सेन्सरसम्बन्धी डेटा हेर्ने तथा प्रयोग गर्ने अनुमति दिन्छ।"</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"पात्रोका कार्यक्रम र विवरणहरू पढ्ने"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"यस एपले तपाईंको ट्याब्लेटमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
@@ -615,7 +617,7 @@
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"कुनै सम्बन्धित पासवर्ड सुरक्षा र किलकलाई असक्षम पार्न एपलाई अनुमति दिन्छ। उदाहरणको लागि, अन्तर्गमन फोन कल प्राप्त गर्दा फोनले किलकलाई असक्षम पार्छ, त्यसपछि कल सकिएको बेला किलक पुनःसक्षम पार्छ।"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"स्क्रिन लकको जटिलतासम्बन्धी जानकारी प्राप्त गर्ने अनुरोध गर्नुहोस्"</string>
     <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"यसले एपलाई स्क्रिन लकको जटिलताको स्तर (उच्च, मध्यम, न्यून वा कुनै पनि होइन) थाहा पाउने अनुमति दिन्छ जसले स्क्रिन लकको लम्बाइको सम्भावित दायरा र त्यसको प्रकारलाई जनाउँछ। यसै गरी, यो एपले प्रयोगकर्ताहरूलाई स्क्रिन लक अद्यावधिक गर्ने सुझाव पनि दिन सक्छ तर प्रयोगकर्ताहरू उक्त सुझावको बेवास्ता गरी बाहिर निस्कन सक्छन्। स्क्रिन लक सादा पाठको ढाँचामा भण्डारण नगरिने हुँदा यो एपलाई वास्तविक पासवर्ड थाहा नहुने कुराको हेक्का राख्नुहोस्।"</string>
-    <string name="permlab_postNotification" msgid="4875401198597803658">"सूचनाहरू देखाइयोस्"</string>
+    <string name="permlab_postNotification" msgid="4875401198597803658">"सूचनाहरू देखाउनुहोस्"</string>
     <string name="permdesc_postNotification" msgid="5974977162462877075">"यो एपलाई सूचना देखाउन दिनुहोस्"</string>
     <string name="permlab_turnScreenOn" msgid="219344053664171492">"स्क्रिन अन गर्ने"</string>
     <string name="permdesc_turnScreenOn" msgid="4394606875897601559">"यो एपलाई स्क्रिन अन गर्ने अनुमति दिन्छ।"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"फिंगरप्रिन्ट पहिचान गर्न सकिएन"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"फिंगरप्रिन्ट पहिचान गर्न सकिएन"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"फिंगरप्रिन्ट प्रमाणीकरण गरियो"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"अनुहार प्रमाणीकरण गरियो"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string>
@@ -782,35 +784,35 @@
     <string name="permlab_control_incall_experience" msgid="6436863486094352987">"आउने-कल प्रयोगकर्ता अनुभव प्रदान गर्नुहोस्"</string>
     <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"एपलाई आउने-कल प्रयोगकर्ता अनुभव प्रदान गर्न अनुमति दिन्छ।"</string>
     <string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"नेटवर्क उपयोगको इतिहास पढ्नुहोस्"</string>
-    <string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"निश्चित नेटवर्कहरू र अनुप्रयोगहरूको लागि ऐतिहासिक नेटवर्क उपयोग पढ्नको लागि एपलाई अनुमति दिन्छ।"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"निश्चित नेटवर्कहरू र एपहरूको लागि ऐतिहासिक नेटवर्क उपयोग पढ्नको लागि एपलाई अनुमति दिन्छ।"</string>
     <string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"नेटवर्क नीति प्रबन्ध गर्नुहोस्"</string>
     <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"नेटवर्क नीतिहरू व्यवस्थापन गर्न र एप-विशेष नियमहरू परिभाषित गर्न एपलाई अनुमति दिन्छ।"</string>
     <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"नेटवर्क उपयोग लेखालाई परिमार्जन गर्नुहोस्"</string>
-    <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"एपलाई कसरी अनुप्रयोगहरूको विरूद्धमा कसरी नेटवर्क उपयोगी अकाउन्टेड छ भनेर परिमार्जन गर्न अनुमति दिन्छ। साधारण अनुप्रयोगहरूद्वारा प्रयोगको लागि होइन।"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"एपलाई कसरी एपहरूको विरूद्धमा कसरी नेटवर्क उपयोगी अकाउन्टेड छ भनेर परिमार्जन गर्न अनुमति दिन्छ। साधारण अनुप्रयोगहरूद्वारा प्रयोगको लागि होइन।"</string>
     <string name="permlab_accessNotifications" msgid="7130360248191984741">"सूचनाहरू पहुँच गर्नुहोस्"</string>
     <string name="permdesc_accessNotifications" msgid="761730149268789668">"अन्य एपहरूबाट पोस्ट गरिएकासहित पुनःप्राप्त गर्न, परीक्षण गर्न र सूचनाहरू हटाउन एपहरूलाई अनुमति दिन्छ।"</string>
     <string name="permlab_bindNotificationListenerService" msgid="5848096702733262458">"जानकारी श्रोता सेवामा बाँध्नुहोस्"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="4970553694467137126">"होल्डरलाई सूचना श्रोता सेवाको शीर्ष-स्तरको इन्टरफेस बाँध्न अनुमति दिन्छ। सामान्य एपहरूलाई कहिले पनि आवश्यक नपर्न सक्दछ।"</string>
     <string name="permlab_bindConditionProviderService" msgid="5245421224814878483">"सर्त प्रदायक सेवामा जोड्न"</string>
-    <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"सर्त प्रदायक सेवाको माथिल्लो स्तरको इन्टरफेसमा जोड्न बाहकलाई अनुमति दिन्छ। साधारण अनुप्रयोगहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"सर्त प्रदायक सेवाको माथिल्लो स्तरको इन्टरफेसमा जोड्न बाहकलाई अनुमति दिन्छ। साधारण एपहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।"</string>
     <string name="permlab_bindDreamService" msgid="4776175992848982706">"सपना सेवामा बाँध्नुहोस्"</string>
-    <string name="permdesc_bindDreamService" msgid="9129615743300572973">"होल्डरलाई सपना सेवाको माथिल्लो स्तरको इन्टरफेसमा बाँध्न अनुमति दिन्छ। साधारण अनुप्रयोगहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।"</string>
+    <string name="permdesc_bindDreamService" msgid="9129615743300572973">"होल्डरलाई सपना सेवाको माथिल्लो स्तरको इन्टरफेसमा बाँध्न अनुमति दिन्छ। साधारण एपहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।"</string>
     <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"वाहक-प्रदान विन्यास एप सुरु गर्नुहोस्"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"प्रयोगकर्तालाई वाहक-प्रदान विन्यास एप सुरु गर्न अनुमति दिन्छ। साधारण एपहरूलाई कहिल्यै आवश्यक पर्ने छैन।"</string>
     <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"सञ्जाल अवस्थाका पर्यवेक्षणका लागि सुन्नुहोस्"</string>
     <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"सञ्जाल अवस्थाका पर्यवेक्षण सुन्नका लागि एपलाई अनुमति दिन्छ।सामान्य एपलाई चाँहिदै नचाँहिन सक्छ।"</string>
-    <string name="permlab_setInputCalibration" msgid="932069700285223434">"इनपुट उपकरण क्यालिब्रेसन परिवर्तन गर्नुहोस्"</string>
-    <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"एपलाई टच स्क्रीनको प्यारामिटरहरू क्यालिब्रेसन परिमार्जन गर्न अनुमति दिन्छ। साधारण अनुप्रयोगहरूको लागि कहिल्यै आवश्यक पर्दैन।"</string>
+    <string name="permlab_setInputCalibration" msgid="932069700285223434">"इनपुट डिभाइस क्यालिब्रेसन परिवर्तन गर्नुहोस्"</string>
+    <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"एपलाई टच स्क्रीनको प्यारामिटरहरू क्यालिब्रेसन परिमार्जन गर्न अनुमति दिन्छ। साधारण एपहरूको लागि कहिल्यै आवश्यक पर्दैन।"</string>
     <string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"DRM प्रमाणपत्रको पहुँच"</string>
-    <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM प्रमाणपत्रहरू प्रावधान र प्रयोग गर्ने निवेदनको अनुमति दिन्छ। साधारण अनुप्रयोगहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM प्रमाणपत्रहरू प्रावधान र प्रयोग गर्ने निवेदनको अनुमति दिन्छ। साधारण एपहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।"</string>
     <string name="permlab_handoverStatus" msgid="7620438488137057281">"Android Beam स्थानान्तरण अवस्था प्राप्त गर्नुहोस्"</string>
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"यस आवेदनले वर्तमान Android Beam स्थानान्तरण बारेमा जानकारी प्राप्त गर्न अनुमति दिन्छ"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"DRM सर्टिफिकेट हटाउनुहोस्"</string>
-    <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM प्रमाणपत्रहरू हटाउन एपलाई अनुमति दिन्छ। सामान्य अनुप्रयोगहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
+    <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM प्रमाणपत्रहरू हटाउन एपलाई अनुमति दिन्छ। सामान्य एपहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"वाहक मेसेजिङ सेवामा आबद्ध हुनुहोस्"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"धारकलाई वाहक मेसेजिङ सेवाको उच्च-स्तरको इन्टरफेसमा आबद्ध हुन अनुमति दिनुहोस्। सामान्य एपहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
     <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"वाहक सेवाहरु बाँध्न"</string>
-    <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"होल्डरलाई वाहक सेवाहरु बाँध्न अनुमति दिनुहोस्। सामान्य अनुप्रयोगहरूको लागि यो कहिल्यै आवश्यक पर्दैन।"</string>
+    <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"होल्डरलाई वाहक सेवाहरु बाँध्न अनुमति दिनुहोस्। सामान्य एपहरूको लागि यो कहिल्यै आवश्यक पर्दैन।"</string>
     <string name="permlab_access_notification_policy" msgid="5524112842876975537">"बाधा नपुर्याउँनुहोस् पहुँच गर्नुहोस्"</string>
     <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"बाधा नपुर्याउँनुहोस् कन्फिगरेसन पढ्न र लेख्‍नको लागि एपलाई अनुमति दिनुहोस्।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"हेर्ने अनुमतिको प्रयोग सुरु गर्नुहोस्"</string>
@@ -821,7 +823,7 @@
     <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"होल्डरलाई एपका सुविधासम्बन्धी जानकारी हेर्न दिन्छ।"</string>
     <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"नमुना लिने उच्च दरमा सेन्सरसम्बन्धी डेटा प्रयोग गर्ने"</string>
     <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"यो अनुमति दिइएमा एपले २०० हर्जभन्दा बढी दरमा सेन्सरसम्बन्धी डेटाको नमुना लिन सक्छ"</string>
-    <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"एप स्वतः अपडेट गरियोस्"</string>
+    <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"एप स्वतः अपडेट गर्नुहोस्"</string>
     <string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"तपाईंले यो अनुमति दिनुभयो भने होल्डरले पहिले नै इन्स्टल गरेको एप स्वतः अपडेट गर्न पाउँछ"</string>
     <string name="permlab_writeVerificationStateE2eeContactKeys" msgid="3990742344778360457">"अन्य एपको स्वामित्वमा रहेका E2EE कन्ट्याक्ट कीहरूको प्रमाणीकरणको स्थिति अपडेट गर्ने"</string>
     <string name="permdesc_writeVerificationStateE2eeContactKeys" msgid="8453156829747427041">"यसले एपलाई अन्य एपको स्वामित्वमा रहेका E2EE कन्ट्याक्ट कीहरूको प्रमाणीकरणको स्थिति अपडेट गर्न दिन्छ"</string>
@@ -830,11 +832,11 @@
     <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रिन अनलक गर्न गरिएको प्रयासको अनुगमन गर्ने"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने ट्याब्लेट लक गर्नुहोस् वा ट्याब्लेटका सबै डेटा मेट्नुहोस्।"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा डिभाइसमा भएको सम्पूर्ण डेटा मेटाउनुहोस्।"</string>
-    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गरियोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गरियोस् वा यस इन्फोटेनमेन्ट प्रणालीका सबै डेटा मेटाइयोस्।"</string>
+    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गर्नुहोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गर्नुहोस् वा यस इन्फोटेनमेन्ट प्रणालीका सबै डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप भएको छ हेर्नुहोस् र निकै धेरै पटक गलत पासवर्ड टाइप भएको भने फोन लक गर्नुहोस् वा फोनका सबै डेटा मेट्नुहोस्।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा ट्याब्लेट लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा यो प्रयोगकर्ताको सम्पूर्ण डेटा मेटाउनुहोस्।"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गरियोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गरियोस् वा यस प्रोफाइलका सबै डेटा मेटाइयोस्।"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गर्नुहोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गर्नुहोस् वा यस प्रोफाइलका सबै डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा फोन लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"स्क्रिन लक परिवर्तन गर्ने"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"स्क्रिन लक परिवर्तन गर्नुहोस्।"</string>
@@ -843,13 +845,13 @@
     <string name="policylab_wipeData" msgid="1359485247727537311">"सबै डेटा मेट्ने"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"फ्याक्ट्रूी रिसेट गरेर चेतावनी नआउँदै ट्याबल्टको डेटा मेट्नुहोस्।"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"फ्याक्ट्री डेटा रिसेट गरेर चेतावनी नदिइकन आफ्नो Android टिभी डिभाइसको डेटा मेटाउनुहोस्।"</string>
-    <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"यो इन्फोटेनमेन्ट प्रणालीको डेटा कुनै चेतावनीविनै फ्याक्ट्री डेटा रिसेट गरेर मेटाइयोस्।"</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"फ्याक्ट्रूी रिसेट गरेर चेतावनी नदिइकन फोनको डेटा मेट्न।"</string>
-    <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"प्रोफाइल डेटा मेटाइयोस्"</string>
+    <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"यो इन्फोटेनमेन्ट प्रणालीको डेटा कुनै चेतावनीविनै फ्याक्ट्री डेटा रिसेट गरेर मेटाउनुहोस्।"</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"फ्याक्ट्रूी रिसेट गरेर चेतावनी नदिइकन फोनको डेटा मेट्नुहोस्।"</string>
+    <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"प्रोफाइल डेटा मेटाउनुहोस्"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"प्रयोगकर्ता डेटा मेट्नुहोस्"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"चेतावनी बिना यो ट्याब्लेटमा यस प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"यो Android टिभी डिभाइसमा भएको यस प्रयोगकर्ताको डेटा चेतावनी नदिइकन मेटाउनुहोस्।"</string>
-    <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"यो इन्फोटेनमेन्ट प्रणालीमा भएको यस प्रोफाइलको डेटा कुनै चेतावनीविनै मेटाइयोस्।"</string>
+    <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"यो इन्फोटेनमेन्ट प्रणालीमा भएको यस प्रोफाइलको डेटा कुनै चेतावनीविनै मेटाउनुहोस्।"</string>
     <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"चेतावनी बिना यो फोनमा यस प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string>
     <string name="policylab_setGlobalProxy" msgid="215332221188670221">"उपकरण विश्वव्यापी प्रोक्सी मिलाउनुहोस्"</string>
     <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"नीति सक्षम हुँदा प्रयोग गरिनको लागि यन्त्र ग्लोवल प्रोक्सी सेट गर्नुहोस्। केवल यन्त्र मालिकले ग्लोवल प्रोक्सी सेट गर्न सक्नुहुन्छ।"</string>
@@ -1405,7 +1407,7 @@
     <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"परीक्षण प्याकेज मोड सक्षम पारियो"</string>
     <string name="test_harness_mode_notification_message" msgid="3039123743127958420">"परीक्षण प्याकेज मोड असक्षम पार्न फ्याक्ट्री रिसेट गर्नुहोस्।"</string>
     <string name="console_running_notification_title" msgid="6087888939261635904">"क्रमसम्बन्धी कन्सोल सक्षम पारियो"</string>
-    <string name="console_running_notification_message" msgid="7892751888125174039">"कार्यसम्पादनमा प्रभाव परेको छ। यसलाई असक्षम पार्न बुटलोडरको जाँच गर्नुहोस्।"</string>
+    <string name="console_running_notification_message" msgid="7892751888125174039">"पर्फर्मेन्समा प्रभाव परेको छ। यसलाई असक्षम पार्न बुटलोडरको जाँच गर्नुहोस्।"</string>
     <string name="mte_override_notification_title" msgid="4731115381962792944">"परीक्षणका क्रममा रहेको MTE अन गरियो"</string>
     <string name="mte_override_notification_message" msgid="2441170442725738942">"पर्फर्मेन्स र स्थिरता प्रभावित हुन सक्छ। अफ गर्न रिबुट गर्नुहोस्। तपाईंले arm64.memtag.bootctl प्रयोग गरी अन गर्नुभएको थियो भने अफ गर्नुअघि यसलाई परिवर्तन गरी \"कुनै पनि होइन\" बनाउनुहोस्।"</string>
     <string name="usb_contaminant_detected_title" msgid="4359048603069159678">"USB पोर्टमा तरल पदार्थ वा धुलो भएको कुरा पत्ता लाग्यो"</string>
@@ -1419,14 +1421,14 @@
     <string name="share_remote_bugreport_action" msgid="7630880678785123682">"सेयर गर्नुहोस्"</string>
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"अस्वीकार गर्नुहोस्"</string>
     <string name="select_input_method" msgid="3971267998568587025">"निवेश विधि छान्नुहोस्"</string>
-    <string name="show_ime" msgid="6406112007347443383">"फिजिकल किबोर्ड सक्रिय हुँदा यसलाई स्क्रिनमा राखियोस्"</string>
+    <string name="show_ime" msgid="6406112007347443383">"फिजिकल किबोर्ड सक्रिय हुँदा यसलाई स्क्रिनमा राख्नुहोस्"</string>
     <string name="hardware" msgid="3611039921284836033">"अनस्क्रिन किबोर्ड प्रयोग गर्नुहोस्"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"<xliff:g id="DEVICE_NAME">%s</xliff:g> कन्फिगर गर्नुहोस्"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"भौतिक किबोर्डहरू कन्फिगर गर्नुहोस्"</string>
     <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>
-    <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"अरू एपमाथि देखाइयोस्"</string>
+    <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"अरू एपमाथि देखाउनुहोस्"</string>
     <string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> अन्य एपहरूमा देखिँदैछ"</string>
     <string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g> अन्य एपहरूमा देखिँदैछ"</string>
     <string name="alert_windows_notification_message" msgid="6538171456970725333">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले यो विशेषता प्रयोग नगरेको चाहनुहुन्न भने सेटिङहरू खोली यसलाई निष्क्रिय पार्न ट्याप गर्नुहोस्।"</string>
@@ -1529,7 +1531,7 @@
     <string name="vpn_text_long" msgid="278540576806169831">"<xliff:g id="SESSION">%s</xliff:g>सँग जोडिएको। नेटवर्क प्रबन्ध गर्न हान्नुहोस्।"</string>
     <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"VPN जडान सधै जोड्दै…"</string>
     <string name="vpn_lockdown_connected" msgid="2853127976590658469">"सधैँ खुल्ला हुने VPN जोडिएको"</string>
-    <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"सधैँ-सक्रिय रहने VPN सेवाबाट विच्छेद गरियो"</string>
+    <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"सधैँ-सक्रिय रहने VPN सेवाबाट डिस्कनेक्ट गरियो"</string>
     <string name="vpn_lockdown_error" msgid="4453048646854247947">"सधैँ सक्रिय रहने VPN सेवामा जडान गर्न सकिएन"</string>
     <string name="vpn_lockdown_config" msgid="8331697329868252169">"नेटवर्क वा VPN सम्बन्धी सेटिङहरू परिवर्तन गर्नुहोस्"</string>
     <string name="upload_file" msgid="8651942222301634271">"फाइल छान्नुहोस्"</string>
@@ -1718,11 +1720,11 @@
     <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम की थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> नामक पहुँचसम्बन्धी सुविधा  सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
-    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गरियोस्"</string>
-    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"सक्रिय नगरियोस्"</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गर्नुहोस्"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"सक्रिय नगर्नुहोस्"</string>
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"सक्रिय"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"निष्क्रिय"</string>
-    <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> लाई तपाईंको यन्त्र पूर्ण रूपमा नियन्त्रण गर्न दिने हो?"</string>
+    <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> लाई तपाईंको डिभाइस पूर्ण रूपमा नियन्त्रण गर्न दिने हो?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"एक्सेसिबिलिटीसम्बन्धी आवश्यकतामा सहयोग गर्ने एपको पूर्ण नियन्त्रण गर्न दिनु उपयुक्त हुन्छ तर अधिकांश एपका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रिन हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"यसले स्क्रिनमा देखिने सबै सामग्री पढ्न सक्छ र अन्य एपहरूमा उक्त सामग्री देखाउन सक्छ।"</string>
@@ -1741,10 +1743,10 @@
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"सर्टकटलाई निष्क्रिय पार्नुहोस्"</string>
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"कलर इन्भर्सन"</string>
-    <string name="color_correction_feature_name" msgid="7975133554160979214">"रङ सच्याउने सुविधा"</string>
+    <string name="color_correction_feature_name" msgid="7975133554160979214">"कलर करेक्सन"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string>
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string>
-    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"श्रवण यन्त्रहरू"</string>
+    <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="3760999147597564314">"भोल्युम बटनहरू थिच्न छाड्नुहोस्। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन गर्न दुवै भोल्युम बटन फेरि ३ सेकेन्डसम्म थिचिराख्नुहोस्।"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन गर्नुअघि PIN मागियोस्"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन गर्नअघि अनलक प्याटर्न माग्नुहोस्"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"तपाईंका प्रशासकले स्थापना गर्नुभएको"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2167,7 +2170,7 @@
     <string name="car_loading_profile" msgid="8219978381196748070">"लोड गर्दै"</string>
     <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # फाइल}other{{file_name} + # वटा फाइल}}"</string>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"कुनै पनि व्यक्तिसँग सेयर गर्ने सिफारिस गरिएको छैन"</string>
-    <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"अनुप्रयोगहरूको सूची"</string>
+    <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"एपहरूको सूची"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"यो एपलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले यो USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"होम"</string>
     <string name="accessibility_system_action_back_label" msgid="4205361367345537608">"पछाडि फर्कनुहोस्"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"कार्य प्रोफाइल ३"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"परीक्षण"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"स्क्रिन सेयर गर्दा सुरक्षाका लागि एपमा भएको सामग्री लुकाइएको छ"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"स्याटलाइटमा स्वतः कनेक्ट गरियो"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"तपाईं मोबाइल वा Wi-Fi नेटवर्कविनै म्यासेज पठाउन र प्राप्त गर्न सक्नुहुन्छ"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages खोल्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5870ca3..5de3287 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Voorbeeld, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Vingerafdruk niet herkend"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Vingerafdruk niet herkend"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Gezicht niet herkend. Gebruik je vingerafdruk."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Gezicht niet herkend. Gebruik je vingerafdruk."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Vingerafdruk geverifieerd"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Gezicht geverifieerd"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gezicht geverifieerd. Druk op Bevestigen."</string>
@@ -725,7 +727,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Kan gezichtsmodel niet maken. Probeer het opnieuw."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Donkere bril waargenomen. Je gezicht moet helemaal zichtbaar zijn."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Gezichtsbedekking waargenomen. Je hele gezicht moet zichtbaar zijn."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Gezichtsbedekking waargenomen. Je gezicht moet helemaal zichtbaar zijn."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Kan gezicht niet verifiëren. Hardware niet beschikbaar."</string>
@@ -828,20 +830,20 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"De lengte en het aantal tekens beheren die zijn toegestaan in wachtwoorden en pincodes voor schermvergrendeling."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Pogingen voor schermontgrendeling bijhouden"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de tablet vergrendelen of alle gegevens op de tablet wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Houd bij hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en vergrendel de tablet of wis alle gegevens op de tablet als te veel onjuiste wachtwoorden worden ingevoerd."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en het Android TV-apparaat vergrendelen of alle gegevens van het Android TV-apparaat wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
-    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Bijhouden hoe vaak onjuiste wachtwoorden worden getypt als het scherm wordt ontgrendeld, en het infotainmentsysteem vergrendelen of alle gegevens op het infotainmentsysteem wissen als te veel onjuiste wachtwoorden worden getypt."</string>
+    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld, en het infotainmentsysteem vergrendelen of alle gegevens op het infotainmentsysteem wissen bij te veel onjuiste wachtwoorden."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens op de telefoon wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de tablet vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Houd bij hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en vergrendel de tablet of wis alle gegevens op de tablet als te veel onjuiste wachtwoorden worden ingevoerd."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en het Android TV-apparaat vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Bijhouden hoe vaak onjuiste wachtwoorden worden getypt als het scherm wordt ontgrendeld, en het infotainmentsysteem vergrendelen of alle gegevens van dit profiel wissen als te veel onjuiste wachtwoorden worden getypt."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd als het scherm wordt ontgrendeld, en het infotainmentsysteem vergrendelen of alle gegevens van dit profiel wissen bij te veel onjuiste wachtwoorden."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens van deze gebruiker wissen bij te veel onjuiste wachtwoorden."</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"De schermvergrendeling wijzigen"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"Wijzig de schermvergrendeling."</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"Het scherm vergrendelen"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Beheer hoe en wanneer het scherm wordt vergrendeld."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Alle gegevens wissen"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"De gegevens van de tablet zonder waarschuwing wissen door de fabrieksinstellingen te herstellen."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Wis de gegevens van de tablet zonder waarschuwing door de fabrieksinstellingen te herstellen."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"De gegevens van het Android TV-apparaat zonder waarschuwing wissen door de fabrieksinstellingen terug te zetten."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"De gegevens van het infotainmentsysteem zonder waarschuwing wissen door de fabrieksinstellingen terug te zetten."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Wis de gegevens van de telefoon zonder waarschuwing door de fabrieksinstellingen te herstellen."</string>
@@ -1894,15 +1896,16 @@
     <string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloon van <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="private_profile_label_badge" msgid="1712086003787839183">"Privé <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vraag pin voor losmaken"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vraag om ontgrendelingspatroon voor losmaken"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ontgrendelingspatroon vragen om app los te maken"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vraag wachtwoord voor losmaken"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Geïnstalleerd door je beheerder"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Geüpdatet door je beheerder"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Verwijderd door je beheerder"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
     <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Met Batterijbesparing wordt het donkere thema aangezet en worden achtergrondactiviteit, bepaalde visuele effecten, bepaalde functies en sommige netwerkverbindingen beperkt of uitgezet."</string>
     <string name="battery_saver_description" msgid="8518809702138617167">"Met Batterijbesparing wordt het donkere thema aangezet en worden achtergrondactiviteit, bepaalde visuele effecten, bepaalde functies en sommige netwerkverbindingen beperkt of uitgezet."</string>
-    <string name="data_saver_description" msgid="4995164271550590517">"Databesparing beperkt het datagebruik door te voorkomen dat sommige apps gegevens sturen of ontvangen op de achtergrond. De apps die je open hebt, kunnen nog steeds data verbruiken, maar doen dit minder vaak. Afbeeldingen worden dan bijvoorbeeld niet getoond totdat je erop tikt."</string>
+    <string name="data_saver_description" msgid="4995164271550590517">"Databesparing beperkt het datagebruik door te voorkomen dat sommige apps gegevens sturen of ontvangen op de achtergrond. De apps die je open hebt, kunnen nog steeds data verbruiken, maar doen dit minder vaak. Afbeeldingen worden bijvoorbeeld pas getoond als je erop tikt."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Databesparing aanzetten?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Aanzetten"</string>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Gedurende 1 minuut (tot {formattedTime})}other{Gedurende # minuten (tot {formattedTime})}}"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Gemeenschappelijk"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"App-content verborgen voor scherm delen vanwege beveiligingsrisico\'s"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatisch verbonden met satelliet"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Je kunt berichten sturen en krijgen zonder een mobiel of wifi-netwerk"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Berichten openen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 4174d04..6f186ff 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ସ୍କ୍ରିନସଟ୍ ନିଅନ୍ତୁ"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ଡିସପ୍ଲେର ଏକ ସ୍କ୍ରିନସଟ୍ ନିଆଯାଇପାରେ।"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ପ୍ରିଭ୍ୟୁ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍‌ ବାର୍‌କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍‍କୁ, ସ୍ଥିତି ବାର୍‍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍‍ ଆଇକନ୍‍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍‍ ବାର୍‍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ଟିପଚିହ୍ନ ଚିହ୍ନଟ ହେଲା ନାହିଁ"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ଟିପଚିହ୍ନ ଚିହ୍ନଟ ହେଲା ନାହିଁ"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ଫେସ୍ ଚିହ୍ନଟ କରିହେବ ନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ଟିପଚିହ୍ନ ପ୍ରମାଣିତ ହେଲା"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string>
@@ -831,7 +833,7 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟ୍‍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ର ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ମନିଟର କରନ୍ତୁ ଏବଂ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମକୁ ଲକ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ। ସ୍କ୍ରିନ ଅନଲକ କରିବାବେଳେ ଏବଂ ଫୋନକୁ ଲକ କରିବା ସମୟରେ ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ କରାଯାଇଥାଏ, ତେବେ ଫୋନର ସମସ୍ତ ଡାଟା ଡିଲିଟ କରେ।"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ଫୋନ ଅନଲକ କରିବା ବେଳେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରିବା ଏବଂ ଯଦି ଏକାଧିକ ଥର ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଫୋନକୁ ଲକ କରିବା ବା ଫୋନର ସମସ୍ତ ଡାଟା ଇରେଜ କରିବା।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ମନିଟର କରନ୍ତୁ ଏବଂ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମକୁ ଲକ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଏହି ପ୍ରୋଫାଇଲର ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
@@ -844,7 +846,7 @@
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟାବ୍‍ଲେଟ୍‍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ବିନା ଚେତାବନୀରେ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ର ଡାଟା ଲିଭାନ୍ତୁ।"</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ବିନା ଚେତାବନୀରେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ଫୋନର ଡାଟା ଲିଭାଇଥାଏ।"</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ବିନା ଚେତାବନୀରେ ଫେକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ଫୋନର ଡାଟା ଇରେଜ କରିବା।"</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ପ୍ରୋଫାଇଲ ଡାଟା ଖାଲି କରନ୍ତୁ"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ୟୁଜର୍‍ ଡାଟା ଲିଭାନ୍ତୁ"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ବିନା ଚେତାବନୀରେ ଏହି ଟାବଲେଟରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ଠିକ୍!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"ସମସ୍ତ ସୁବିଧା ତଥା ଡାଟା ପାଇଁ ଅନଲକ୍‍ କରନ୍ତୁ"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"ସବୁ ଫିଚର ଓ ଡାଟା ପାଇଁ ଅନଲକ କରନ୍ତୁ"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ସର୍ବାଧିକ ଫେସ୍ ଅନଲକ୍‍ ପ୍ରଚେଷ୍ଟା ଅତିକ୍ରମ କରିଛି"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"କୌଣସି SIM ନାହିଁ"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"ଟାବଲେଟରେ କୌଣସି SIM ନାହିଁ।"</string>
@@ -1754,7 +1756,7 @@
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ଫିଚରଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ଫିଚରଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ଫିଚରଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ, ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ।"</string>
-    <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"ମ୍ୟାଗ୍ନିଫିକେସନ୍‍"</string>
+    <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"ମେଗ୍ନିଫିକେସନ"</string>
     <string name="user_switched" msgid="7249833311585228097">"ବର୍ତ୍ତମାନର ୟୁଜର୍‌ ହେଉଛନ୍ତି <xliff:g id="NAME">%1$s</xliff:g>।"</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g>ରେ ସ୍ୱିଚ କରନ୍ତୁ…"</string>
     <string name="user_logging_out_message" msgid="7216437629179710359">"<xliff:g id="NAME">%1$s</xliff:g>ଙ୍କୁ ଲଗଆଉଟ୍‍ କରାଯାଉଛି…"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ PIN ପଚାରନ୍ତୁ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ ଲକ୍‌ ଖୋଲିବା ପାଟର୍ନ ପଚାରନ୍ତୁ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ ପାସ୍‌ୱର୍ଡ ପଚାରନ୍ତୁ"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"ଆପଣଙ୍କ ଆଡମିନ୍‌‌ ଇନଷ୍ଟଲ୍‍ କରିଛନ୍ତି"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ୱାର୍କ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ଟେଷ୍ଟ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"କମ୍ୟୁନାଲ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ସୁରକ୍ଷା ପାଇଁ ସ୍କ୍ରିନ ସେୟାରରୁ ଆପ ବିଷୟବସ୍ତୁକୁ ଲୁଚାଯାଇଛି"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ସାଟେଲାଇଟ ସହ ସ୍ୱତଃ କନେକ୍ଟ ହୋଇଛି"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"ଏକ ମୋବାଇଲ କିମ୍ବା ୱାଇ-ଫାଇ ନେଟୱାର୍କ ବିନା ଆପଣ ମେସେଜ ପଠାଇପାରିବେ ଏବଂ ପାଇପାରିବେ"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ଖୋଲନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 3e7b27e..7f83ddb 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ਡਿਸਪਲੇ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈ ਸਕਦੀ ਹੈ।"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ਪੂਰਵ-ਝਲਕ ਦੇਖੋ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ਚਿਹਰਾ ਨਹੀਂ ਪਛਾਣ ਸਕਦੇ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ। ਇਸਦੀ ਥਾਂ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string>
@@ -841,10 +843,10 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"ਸਕ੍ਰੀਨ ਲਾਕ ਕਰੋ"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"ਸਕ੍ਰੀਨ ਦਾ ਕਿਵੇਂ ਅਤੇ ਕਦੋਂ ਲਾਕ ਹੋਣਾ ਕੰਟਰੋਲ ਕਰੋ।"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੈਬਲੈੱਟ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰ ਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੈਬਲੈੱਟ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਫ਼ੋਨ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰ ਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਫ਼ੋਨ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟਾਓ"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ਉਪਭੋਗਤਾ  ਡਾਟਾ  ਮਿਟਾਓ"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ ਟੈਬਲੈੱਟ ਤੇ ਮੌਜੂਦ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
@@ -1724,10 +1726,10 @@
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"ਬੰਦ"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪੂਰਾ ਕੰਟਰੋਲ ਦੇਣਾ ਹੈ?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"ਪੂਰਾ ਕੰਟਰੋਲ ਉਨ੍ਹਾਂ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਹੈ ਜੋ ਪਹੁੰਚਯੋਗਤਾ ਸੰਬੰਧੀ ਲੋੜਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕਰਦੀਆਂ ਹਨ, ਪਰ ਜ਼ਿਆਦਾਤਰ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਨਹੀਂ ਹੁੰਦਾ।"</string>
-    <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"ਸਕ੍ਰੀਨ ਨੂੰ ਦੇਖੋ ਅਤੇ ਕੰਟਰੋਲ ਕਰੋ"</string>
+    <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"ਸਕ੍ਰੀਨ ਨੂੰ ਦੇਖਣਾ ਅਤੇ ਕੰਟਰੋਲ ਕਰਨਾ"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"ਇਹ ਸਕ੍ਰੀਨ \'ਤੇ ਸਾਰੀ ਸਮੱਗਰੀ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਸਮੱਗਰੀ ਨੂੰ ਦੂਜੀਆਂ ਐਪਾਂ ਦੇ ਉੱਪਰ ਦਿਖਾ ਸਕਦੀ ਹੈ।"</string>
-    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"ਕਾਰਵਾਈਆਂ ਦੇਖੋ ਅਤੇ ਕਰੋ"</string>
-    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"ਇਹ ਕਿਸੇ ਐਪ ਜਾਂ ਹਾਰਡਵੇਅਰ ਸੈਂਸਰ ਦੇ ਨਾਲ ਤੁਹਾਡੀਆਂ ਅੰਤਰਕਿਰਿਆਵਾਂ ਨੂੰ ਟਰੈਕ ਕਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਤੁਹਾਡੀ ਤਰਫ਼ੋਂ ਐਪਾਂ ਦੇ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"ਕਾਰਵਾਈਆਂ ਦੇਖਣਾ ਅਤੇ ਕਰਨਾ"</string>
+    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"ਇਹ ਕਿਸੇ ਐਪ ਜਾਂ ਹਾਰਡਵੇਅਰ ਸੈਂਸਰ ਦੇ ਨਾਲ ਤੁਹਾਡੀਆਂ ਅੰਤਰਕਿਰਿਆਵਾਂ ਨੂੰ ਟਰੈਕ ਕਰ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੀ ਤਰਫ਼ੋਂ ਐਪਾਂ ਦੇ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"ਕਰਨ ਦਿਓ"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ਨਾ ਕਰਨ ਦਿਓ"</string>
     <string name="accessibility_dialog_button_uninstall" msgid="2952465517671708108">"ਅਣਸਥਾਪਤ ਕਰੋ"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਿੰਨ ਮੰਗੋ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਣਲਾਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ਅਣਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤਾ ਗਿਆ"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ਕੰਮ ਸੰਬੰਧੀ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ਜਾਂਚ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"ਭਾਈਚਾਰਕ"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ਐਪ ਸਮੱਗਰੀ ਨੂੰ ਸੁਰੱਖਿਆ ਲਈ ਸਕ੍ਰੀਨ ਸਾਂਝਾਕਰਨ ਤੋਂ ਲੁਕਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"ਸੈਟੇਲਾਈਟ ਨਾਲ ਸਵੈ-ਕਨੈਕਟ ਹੋਇਆ"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"ਤੁਸੀਂ ਮੋਬਾਈਲ ਜਾਂ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੋਂ ਬਿਨਾਂ ਸੁਨੇਹੇ ਭੇਜ ਅਤੇ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ਐਪ ਖੋਲ੍ਹੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index ca126f7..a6937d2 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Robienie zrzutu ekranu"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Może robić zrzuty ekranu wyświetlacza."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Podgląd, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string>
@@ -649,11 +651,11 @@
     <string name="biometric_error_generic" msgid="6784371929985434439">"Podczas uwierzytelniania wystąpił błąd"</string>
     <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Używaj blokady ekranu"</string>
     <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Użyj blokady ekranu, aby kontynuować"</string>
-    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Mocno naciśnij czujnik"</string>
+    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Mocno naciśnij czytnik"</string>
     <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Nie rozpoznano odcisku palca. Spróbuj ponownie."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Wyczyść czytnik linii papilarnych i spróbuj ponownie"</string>
     <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Wyczyść czujnik i spróbuj ponownie"</string>
-    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Mocno naciśnij czujnik"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Mocno naciśnij czytnik"</string>
     <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Palec został obrócony zbyt wolno. Spróbuj ponownie."</string>
     <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Użyj odcisku innego palca"</string>
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Zbyt jasno"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Nie rozpoznano odcisku palca"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Nie rozpoznano odcisku palca"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Nie rozpoznaję twarzy. Użyj odcisku palca."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Nie rozpoznano twarzy. Użyj odcisku palca."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Uwierzytelniono odciskiem palca"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Twarz rozpoznana"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Twarz rozpoznana, kliknij Potwierdź"</string>
@@ -997,7 +999,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Poprawnie!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Spróbuj ponownie."</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"Spróbuj ponownie."</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Odblokowanie wszystkich funkcji i danych"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"Odblokuj, by używać wszystkich funkcji i danych"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Przekroczono maksymalną liczbę prób rozpoznania twarzy."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Brak karty SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Brak karty SIM w tablecie."</string>
@@ -1763,7 +1765,7 @@
     <string name="owner_name" msgid="8713560351570795743">"Właściciel"</string>
     <string name="guest_name" msgid="8502103277839834324">"Gość"</string>
     <string name="error_message_title" msgid="4082495589294631966">"Błąd"</string>
-    <string name="error_message_change_not_allowed" msgid="843159705042381454">"Ta zmiana nie jest dozwolona przez administratora"</string>
+    <string name="error_message_change_not_allowed" msgid="843159705042381454">"Ta zmiana nie jest dozwolona przez administratora."</string>
     <string name="app_not_found" msgid="3429506115332341800">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
     <string name="revoke" msgid="5526857743819590458">"Cofnij"</string>
     <string name="mediasize_iso_a0" msgid="7039061159929977973">"ISO A0"</string>
@@ -1898,14 +1900,15 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Podaj PIN, aby odpiąć"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Aby odpiąć, poproś o wzór odblokowania"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Aby odpiąć, poproś o hasło"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Zainstalowany przez administratora"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
     <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Oszczędzanie baterii uruchamia ciemny motyw oraz wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne, pewne funkcje oraz wybrane połączenia sieciowe."</string>
     <string name="battery_saver_description" msgid="8518809702138617167">"Oszczędzanie baterii uruchamia ciemny motyw oraz wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne, pewne funkcje oraz wybrane połączenia sieciowe."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Oszczędzanie danych uniemożliwia niektórym aplikacjom wysyłanie i odbieranie danych w tle, zmniejszając w ten sposób ich użycie. Aplikacja, z której w tej chwili korzystasz, może uzyskiwać dostęp do danych, ale rzadziej. Może to powodować, że obrazy będą się wyświetlać dopiero po kliknięciu."</string>
-    <string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć Oszczędzanie danych?"</string>
+    <string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć oszczędzanie danych?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Włącz"</string>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Przez 1 minutę (do {formattedTime})}few{Przez # minuty (do {formattedTime})}many{Przez # minut (do {formattedTime})}other{Przez # minuty (do {formattedTime})}}"</string>
     <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Przez 1 min (do {formattedTime})}few{Przez # min (do {formattedTime})}many{Przez # min (do {formattedTime})}other{Przez # min (do {formattedTime})}}"</string>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Służbowy 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Testowy"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Wspólny"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Ze względów bezpieczeństwa zawartość aplikacji jest niewidoczna podczas udostępniania ekranu"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatycznie połączono z satelitą"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Możesz wymieniać wiadomości bez dostępu do sieci komórkowej lub Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Otwórz Wiadomości"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c53b1d5..d0dcc33 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Impressão digital não reconhecida"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Impressão digital não reconhecida"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Rosto não reconhecido. Use a impressão digital."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Impressão digital autenticada"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string>
@@ -726,7 +728,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Falha ao criar o modelo de rosto. Tente de novo."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Óculos escuros detectados. Seu rosto precisa estar completamente visível."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Máscara detectada. Seu rosto precisa estar visível."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Tem algo cobrindo seu rosto. Ele precisa estar visível."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Impossível verificar rosto. Hardware indisponível."</string>
@@ -1371,8 +1373,8 @@
     <string name="sim_added_message" msgid="6602906609509958680">"Reinicie o dispositivo para acessar a rede móvel."</string>
     <string name="sim_restart_button" msgid="8481803851341190038">"Reiniciar"</string>
     <string name="install_carrier_app_notification_title" msgid="5712723402213090102">"Ativar serviço móvel"</string>
-    <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Faça o download do app da operadora para ativar seu novo chip"</string>
-    <string name="install_carrier_app_notification_text_app_name" msgid="4086877327264106484">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo chip"</string>
+    <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Baixe o app da operadora para ativar seu novo chip"</string>
+    <string name="install_carrier_app_notification_text_app_name" msgid="4086877327264106484">"Baixe o app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo chip"</string>
     <string name="install_carrier_app_notification_button" msgid="6257740533102594290">"Fazer download do app"</string>
     <string name="carrier_app_notification_title" msgid="5815477368072060250">"Novo chip inserido"</string>
     <string name="carrier_app_notification_text" msgid="6567057546341958637">"Toque para configurar"</string>
@@ -1744,7 +1746,7 @@
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Correção de cor"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo uma mão"</string>
-    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer a tela"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer ainda mais a tela"</string>
     <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>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalado pelo seu administrador"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Excluído pelo seu administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Público"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conteúdo do app oculto no compartilhamento de tela por motivos de segurança"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Conectado automaticamente ao satélite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Você pode enviar e receber mensagens sem um dispositivo móvel ou uma rede Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Abrir o app Mensagens"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6b6f5c5..4772ff8 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer captura de ecrã"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"É possível tirar uma captura de ecrã."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pré-visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar barra de estado"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite à app desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ser apresentada na barra de estado"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Impressão digital não reconhecida"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Impressão digital não reconhecida"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Impos. reconh. rosto. Utilize a impressão digital."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Rosto não reconhecido. Use a impressão digital."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"A impressão digital foi autenticada."</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado."</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado. Prima Confirmar."</string>
@@ -845,7 +847,7 @@
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apagar os dados do tablet sem avisar através de uma reposição de dados de fábrica."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Apagar os dados do seu dispositivo Android TV sem avisar ao efetuar uma reposição de dados de fábrica."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apague os dados do sistema de infoentretenimento sem aviso ao executar uma reposição de dados de fábrica."</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados do telemóvel sem avisar ao efetuar uma reposição de dados de fábrica."</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados do telemóvel sem avisar repondo os dados de fábrica."</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Apague os dados do perfil"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Apagar os dados do utilizador"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Apagar os dados deste utilizador neste tablet sem aviso."</string>
@@ -1393,7 +1395,7 @@
     <string name="usb_midi_notification_title" msgid="7404506788950595557">"O MIDI através de USB está ativado"</string>
     <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositivo ligado como câmara Web"</string>
     <string name="usb_accessory_notification_title" msgid="1385394660861956980">"Acessório USB ligado"</string>
-    <string name="usb_notification_message" msgid="4715163067192110676">"Toque para obter mais opções."</string>
+    <string name="usb_notification_message" msgid="4715163067192110676">"Toque para ver mais opções."</string>
     <string name="usb_power_notification_message" msgid="7284765627437897702">"A carregar o dispositivo ligado. Toque para obter mais opções."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Acessório de áudio analógico detetado"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"O dispositivo ligado não é compatível com este telemóvel. Toque para saber mais."</string>
@@ -1724,10 +1726,10 @@
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"ATIVADO"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"DESATIVADO"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Permitir que o serviço <xliff:g id="SERVICE">%1$s</xliff:g> tenha controlo total sobre o seu dispositivo?"</string>
-    <string name="accessibility_service_warning_description" msgid="291674995220940133">"O controlo total é adequado para aplicações que ajudam nas necessidades de acessibilidade, mas não para a maioria das apps."</string>
+    <string name="accessibility_service_warning_description" msgid="291674995220940133">"O controlo total é adequado para apps que ajudam nas necessidades de acessibilidade, mas não para a maioria das apps."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Ver e controlar o ecrã"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Pode ler todo o conteúdo do ecrã e sobrepor conteúdo a outras aplicações."</string>
-    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Veja e execute ações"</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Pode ler todo o conteúdo do ecrã e sobrepor conteúdo a outras apps."</string>
+    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Ver e executar ações"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Pode monitorizar as suas interações com uma app ou um sensor de hardware e interagir com apps em seu nome."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Permitir"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Recusar"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de soltar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir palavra-passe antes de soltar"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalado pelo seu gestor"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu gestor"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado pelo seu gestor"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Comum"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conteúdo da app ocultado da partilha de ecrã por motivos de segurança"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Ligação de satélite estabelecida automaticamente"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Pode enviar e receber mensagens sem uma rede móvel ou Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Abre a app Mensagens"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c53b1d5..d0dcc33 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Impressão digital não reconhecida"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Impressão digital não reconhecida"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Rosto não reconhecido. Use a impressão digital."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Impressão digital autenticada"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Rosto autenticado"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string>
@@ -726,7 +728,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Falha ao criar o modelo de rosto. Tente de novo."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Óculos escuros detectados. Seu rosto precisa estar completamente visível."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Máscara detectada. Seu rosto precisa estar visível."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Tem algo cobrindo seu rosto. Ele precisa estar visível."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Impossível verificar rosto. Hardware indisponível."</string>
@@ -1371,8 +1373,8 @@
     <string name="sim_added_message" msgid="6602906609509958680">"Reinicie o dispositivo para acessar a rede móvel."</string>
     <string name="sim_restart_button" msgid="8481803851341190038">"Reiniciar"</string>
     <string name="install_carrier_app_notification_title" msgid="5712723402213090102">"Ativar serviço móvel"</string>
-    <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Faça o download do app da operadora para ativar seu novo chip"</string>
-    <string name="install_carrier_app_notification_text_app_name" msgid="4086877327264106484">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo chip"</string>
+    <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Baixe o app da operadora para ativar seu novo chip"</string>
+    <string name="install_carrier_app_notification_text_app_name" msgid="4086877327264106484">"Baixe o app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo chip"</string>
     <string name="install_carrier_app_notification_button" msgid="6257740533102594290">"Fazer download do app"</string>
     <string name="carrier_app_notification_title" msgid="5815477368072060250">"Novo chip inserido"</string>
     <string name="carrier_app_notification_text" msgid="6567057546341958637">"Toque para configurar"</string>
@@ -1744,7 +1746,7 @@
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Correção de cor"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo uma mão"</string>
-    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer a tela"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer ainda mais a tela"</string>
     <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>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalado pelo seu administrador"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Atualizado pelo seu administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Excluído pelo seu administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Público"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conteúdo do app oculto no compartilhamento de tela por motivos de segurança"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Conectado automaticamente ao satélite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Você pode enviar e receber mensagens sem um dispositivo móvel ou uma rede Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Abrir o app Mensagens"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5a449e3..0a31bf8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fă o captură de ecran"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Poate face o captură de ecran."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Previzualizare, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Amprenta nu a fost recunoscută"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Amprenta nu a fost recunoscută"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Chipul nu a fost recunoscut. Folosește amprenta."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Fața nu a fost recunoscută. Folosește amprenta."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Amprentă autentificată"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Chip autentificat"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Chip autentificat, apasă pe Confirmă"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicită codul PIN înainte de a anula fixarea"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicită mai întâi modelul pentru deblocare"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicită parola înainte de a anula fixarea"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instalat de administrator"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizat de administrator"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Șters de administrator"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Serviciu 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Comun"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Conținutul aplicației este ascuns de permiterea accesului la ecran din motive de securitate"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"S-a conectat automat la satelit"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Poți să trimiți și să primești mesaje fără o rețea mobilă sau Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Deschide Mesaje"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 59982ef..1ae0499 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать снимки экрана."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g>: предпросмотр"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string>
@@ -653,7 +655,7 @@
     <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Отпечаток пальца не распознан. Повторите попытку."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Очистите сканер отпечатков пальцев и повторите попытку."</string>
     <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Очистите сканер и повторите попытку."</string>
-    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Плотно прижмите палец к сканеру."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Плотно прижмите палец к сканеру"</string>
     <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>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Отпечаток не распознан."</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Отпечаток не распознан."</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Не удалось распознать лицо. Используйте отпечаток."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Лицо не распознано. Используйте отпечаток."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отпечаток пальца проверен"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лицо распознано"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицо распознано, нажмите кнопку \"Подтвердить\""</string>
@@ -830,10 +832,10 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Настройка правил для паролей"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролировать длину и символы при вводе пароля и PIN-кода."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Отслеживание попыток разблокировать экран"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Отслеживает попытки ввода пароля при разблокировке экрана и блокирует планшетный ПК или удаляет с него все данные, если было сделано слишком много таких попыток."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Отслеживать попытки ввода пароля при разблокировке экрана и блокировать планшет или удалять с него все данные, если было сделано слишком много таких попыток."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Блокировать устройство Android TV или удалять с него все ваши данные при слишком большом количестве неудачных попыток ввести пароль для разблокировки экрана."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Блокировать информационно-развлекательную систему или удалять из нее все данные, если совершено слишком много неудачных попыток ввести пароль для разблокировки экрана."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Отслеживает попытки ввода пароля при разблокировке экрана и блокирует телефон или удаляет с него все данные, если было сделано слишком много таких попыток."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Отслеживать попытки ввода пароля при разблокировке экрана и блокировать телефон или удалять с него все данные, если было сделано слишком много таких попыток."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Отслеживать неверно введенные пароли при разблокировке экрана и блокировать планшет или удалять с него все данные, если сделано слишком много неудачных попыток."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Блокировать устройство Android TV или удалять с него все данные этого пользователя при слишком большом количестве неудачных попыток ввести пароль для разблокировки экрана."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Блокировать информационно-развлекательную систему или удалять все данные профиля, если совершено слишком много неудачных попыток ввести пароль для разблокировки экрана."</string>
@@ -843,7 +845,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Блокировка экрана"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Управлять способом и временем блокировки экрана."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Удаление всех данных"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Удалять все данные на планшетном ПК без предупреждения путем сброса настроек."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Удалять все данные на планшете без предупреждения путем сброса настроек."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Удалять данные с устройства Android TV без предупреждения, выполняя восстановление заводских настроек."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Сбрасывать настройки без предупреждения, таким образом удаляя все данные из информационно-развлекательной системы."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Удалять все данные на телефоне без предупреждения путем сброса настроек."</string>
@@ -1898,7 +1900,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запрашивать PIN-код"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запрашивать графический ключ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запрашивать пароль"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Установлено администратором"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Рабочий 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Тестовый"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Совместный"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Содержимое приложения исключено из демонстрации экрана в целях безопасности."</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Автоматически подключено к системам спутниковой связи"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Вы можете отправлять и получать сообщения без доступа к мобильной сети или Wi-Fi."</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Открыть Сообщения"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 04b2c52..ee0cda2 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"තිර රුව ගන්න"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"සංදර්ශකයේ තිර රුවක් ගැනීමට හැකිය."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"පෙරදසුන, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්‍රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ඇඟිලි සලකුණ හඳුනා නොගන්නා ලදි"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ඇඟිලි සලකුණ හඳුනා නොගන්නා ලදි"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"මුහුණ හැඳිනිය නොහැක. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත ක."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"මුහුණ හඳුනා නොගැනිණි. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත කරන්න."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ඇඟිලි සලකුණ සත්‍යාපනය කරන ලදී"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"මුහුණ සත්‍යාපනය කරන ලදී"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"මුහුණ සත්‍යාපනය කරන ලදී, කරුණාකර තහවුරු කරන්න ඔබන්න"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ගැලවීමට පෙර PIN විමසන්න"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"ඔබගේ පරිපාලක මඟින් ස්ථාපනය කර ඇත"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"කාර්යාලය 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"පරීක්ෂණය"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"වාර්ගික"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ආරක්ෂාව සඳහා යෙදුම් අන්තර්ගතය තිරය බෙදා ගැනීමෙන් සඟවා ඇත"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"චන්ද්‍රිකාවට ස්වයංක්‍රීයව සම්බන්ධ වේ"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"ඔබට ජංගම හෝ Wi-Fi ජාලයක් නොමැතිව පණිවිඩ යැවීමට සහ ලැබීමට හැක"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages විවෘත කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 76cad30..3058de5 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Vytvoriť snímku obrazovky"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Je možné vytvoriť snímku obrazovky."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Ukážka, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Odtlačok prsta nebol rozpoznaný"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Odtlačok prsta nebol rozpoznaný"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Tvár sa nedá rozpoznať. Použite odtlačok prsta."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Tvár nebola rozpoznaná. Použite odtlačok prsta."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Odtlačok prsta bol overený"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Tvár bola overená"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string>
@@ -727,7 +729,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Model tváre sa nedá vytvoriť. Skúste to znova."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Boli rozpoznané tmavé okuliare. Musí vám byť vidieť celú tvár."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Bolo rozpoznané rúško. Musí vám byť vidieť celú tvár."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Máte čiastočne zakrytú tvár. Musí byť viditeľná celá."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Tvár sa nedá overiť. Hardvér nie je k dispozícii."</string>
@@ -833,7 +835,7 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a zamknúť tablet alebo vymazať všetky údaje tabletu v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovanie počtu nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknutie zariadenia Android TV alebo vymazanie všetkých jeho údajov."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamknite palubný systém alebo vymažte všetky údaje v palubnom systéme v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a zamknúť telefón alebo vymazať všetky údaje v telefóne v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sleduje počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamkne telefón alebo vymaže z telefónu všetky dáta, ak bolo zadaných príliš veľa nesprávnych hesiel."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknite tablet alebo vymažte všetky údaje tohto používateľa."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Sledovanie počtu nesprávnych hesiel zadaných pri odomykaní obrazovky a ak je ich zadaných príliš mnoho, uzamknutie zariadenia Android TV alebo vymazanie všetkých údajov tohto používateľa."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknite palubný systém alebo vymažte všetky údaje tohto profilu."</string>
@@ -846,7 +848,7 @@
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez predchádzajúceho upozornenia vymazať všetky dáta obnovením výrobných nastavení tabletu."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Vymazanie údajov v zariadení Android TV bez upozornenia obnovením výrobných nastavení."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Vymažte údaje palubného systému bez upozornenia obnovením výrobných nastavení."</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Bez predchádzajúceho upozornenia vymazať všetky dáta obnovením výrobných nastavení telefónu."</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Bez predchádzajúceho upozornenia vymaže všetky dáta obnovením výrobných nastavení telefónu."</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Vymazanie údajov profilu"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Vymazať údaje používateľa"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Vymažte bez upozornenia údaje tohto používateľa na tomto tablete."</string>
@@ -1898,7 +1900,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pred odopnutím požiadať o číslo PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odopnutím požiadať o heslo"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Nainštaloval správca"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Aktualizoval správca"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Odstránil správca"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"3. pracovný"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Testovací"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Spoločný"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Obsah aplikácie bol na účely zabezpečenia skrytý v zdieľaní obrazovky"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automaticky pripojené k satelitu"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Správy môžete odosielať a prijímať bez mobilnej siete či siete Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Otvoriť Správy"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5983929..0215c39 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ustvarjanje posnetka zaslona"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Lahko naredi posnetek zaslona."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Predogled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Prstni odtis ni prepoznan."</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Prstni odtis ni prepoznan."</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Obraza ni mogoče prepoznati. Uporabite prstni odtis."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Obraz ni prepoznan. Uporabite prstni odtis."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Pristnost prstnega odtisa je preverjena"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Pristnost obraza je potrjena"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Pristnost obraza je preverjena. Pritisnite gumb »Potrdi«."</string>
@@ -1898,7 +1900,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zahtevaj PIN pred odpenjanjem"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odpenjanjem vprašaj za geslo"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Namestil skrbnik"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Delo 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Preizkus"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Skupno"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Pri deljenju zaslona je vsebina aplikacije skrita zaradi varnosti"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Samodejno vzpostavljena povezava s satelitom"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Sporočila SMS lahko pošiljate in prejemate brez mobilnega omrežja ali omrežja Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Odpri Sporočila"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 5a02d56..1f42949 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Nxirr një pamje të ekranit"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Mund të nxjerrë një pamje e ekranit."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Versioni paraprak, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Gjurma e gishtit nuk u njoh"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Gjurma e gishtit nuk u njoh"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Nuk mund ta dallojë fytyrën. Përdor më mirë gjurmën e gishtit."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Fytyra nuk njihet. Përdor gjurmën e gishtit."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Gjurma e gishtit u vërtetua"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Fytyra u vërtetua"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Fytyra u vërtetua, shtyp \"Konfirmo\""</string>
@@ -828,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Cakto rregullat e fjalëkalimit"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrollo gjatësinë dhe karakteret e lejuara në fjalëkalimet dhe kodet PIN të kyçjes së ekranit."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitoron tentativat e shkyçjes së ekranit"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitoro numrin e fjalëkalimeve të shkruar gabim kur shkyç ekranin. Kyç tabletin ose fshi të gjitha të dhënat e tij, nëse shkruhen shumë fjalëkalime të pasakta."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin. Kyç tabletin ose fshi të gjitha të dhënat e tij, nëse shkruhen shumë fjalëkalime të pasakta."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin dhe kyç pajisjen tënde Android TV ose spastro të gjitha të dhënat e pajisjes sate Android TV nëse shkruhen gabim shumë fjalëkalime."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin dhe kyç sistemin info-argëtues ose spastro të gjitha të dhënat e tij nëse shkruhen shumë fjalëkalime të gabuara."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitoron numrin e fjalëkalimeve të shkruar gabim kur shkyç ekranin. Kyç telefonin ose fshin të gjitha të dhënat e tij, nëse shkruhen shumë fjalëkalime të pasakta."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zhgozhdimi kërkon PIN-in"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Kërko motivin e shkyçjes para heqjes së gozhdimit"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Instaluar nga administratori"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Përditësuar nga administratori"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Fshirë nga administratori"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Në rregull"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Puna 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"I përbashkët"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Përmbajtja e aplikacionit është fshehur nga ndarja e ekranit për arsye sigurie"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"U lidh automatikisht me satelitin"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Mund të dërgosh dhe të marrësh mesazhe pa një rrjet celular apo rrjet Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Hap \"Mesazhet\""</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 637371c..6768e29 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -357,6 +357,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Направи снимак екрана"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи снимак екрана."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"онемогућавање или измена статусне траке"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"функционисање као статусна трака"</string>
@@ -663,7 +665,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Отисак прста није препознат"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Отисак прста није препознат"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Лице није препознато. Користите отисак прста."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Лице није препознато. Користите отисак прста."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Отисак прста је потврђен"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Лице је потврђено"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лице је потврђено. Притисните Потврди"</string>
@@ -1223,7 +1225,7 @@
     <string name="whichEditApplicationLabel" msgid="1463288652070140285">"Измени"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"Делите"</string>
     <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Делите помоћу апликације %1$s"</string>
-    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Дели"</string>
+    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Дељење"</string>
     <string name="whichSendToApplication" msgid="77101541959464018">"Пошаљите помоћу:"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Пошаљите помоћу: %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Пошаљи"</string>
@@ -1897,7 +1899,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Тражи PIN пре откачињања"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Тражи шаблон за откључавање пре откачињања"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тражи лозинку пре откачињања"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Инсталирао је администратор"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2394,9 +2397,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Посао 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Тест"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Заједничко"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Садржај апликације је скривен за дељење садржаја екрана због безбедности"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Аутоматски повезано са сателитом"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Можете да шаљете и примате поруке без мобилне или WiFi мреже"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Отвори Messages"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2dde3a8..fb0caa9 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -50,7 +50,7 @@
       <item quantity="other">Du har <xliff:g id="NUMBER_1">%d</xliff:g> försök kvar innan SIM-kortet låses.</item>
       <item quantity="one">Du har <xliff:g id="NUMBER_0">%d</xliff:g> försök kvar innan SIM-kortet låses.</item>
     </plurals>
-    <string name="imei" msgid="2157082351232630390">"IMEI-kod"</string>
+    <string name="imei" msgid="2157082351232630390">"IMEI"</string>
     <string name="meid" msgid="3291227361605924674">"MEID"</string>
     <string name="ClipMmi" msgid="4110549342447630629">"Nummerpresentatör för inkommande samtal"</string>
     <string name="ClirMmi" msgid="6752346475055446417">"Dölj nummerpresentatör för utgående samtal"</string>
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skärmbild"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ta en skärmbild av skärmen."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Förhandsgranskar <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"inaktivera eller ändra statusfält"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"visas i statusfältet"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Fingeravtrycket känns inte igen"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Fingeravtrycket känns inte igen"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Ansiktet kändes inte igen. Använd fingeravtryck."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ansiktet känns inte igen. Använd fingeravtryck."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Fingeravtrycket har autentiserats"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ansiktet har autentiserats"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet har autentiserats. Tryck på Bekräfta"</string>
@@ -831,7 +833,7 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Övervaka antalet felaktiga lösenord som angetts för skärmlåset och lås surfplattan eller ta bort alla data från surfplattan om för många felaktiga försök görs."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås Android TV-enheten eller rensa all data på Android TV-enheten om för många felaktiga lösenord har skrivits in."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Övervaka antalet felaktiga lösenord som angetts för skärmlåset och lås infotainmentsystemet eller rensa all data från infotainmentsystemet om för många felaktiga försök görs."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Övervaka antalet felaktiga lösenord som angivits för skärmlåset och lås mobilen eller ta bort alla data från mobilen om för många felaktiga försök görs."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Övervaka antalet felaktiga lösenord som angivits för skärmlåset och lås telefonen eller ta bort alla data från telefonen om för många felaktiga försök görs."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås surfplattan eller rensa alla uppgifter för den här användaren om för många felaktiga lösenord har skrivits in."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås Android TV-enheten eller rensa alla uppgifter för den här användaren om för många felaktiga lösenord har skrivits in."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Övervaka antalet felaktiga lösenord som angetts för skärmlåset och lås infotainmentsystemet eller rensa all data från profilen om för många felaktiga lösenord har skrivits in."</string>
@@ -844,7 +846,7 @@
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Ta bort data från surfplattan utan förvarning genom att återställa standardinställningarna."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Radera data på Android TV-enheten utan förvarning genom att återställa standardinställningarna."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Rensa data från infotainmentsystemet utan förvarning genom att återställa standardinställningarna."</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ta bort data från mobilen utan förvarning genom att återställa standardinställningarna."</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ta bort data från telefonen utan förvarning genom att återställa standardinställningarna."</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Rensa profildata"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Radera användaruppgifter"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Rensa användarens uppgifter på den här surfplattan utan förvarning."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Be om pinkod innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Be om lösenord innan skärmen slutar fästas"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Administratören installerade paketet"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Administratören uppdaterade paketet"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratören raderade paketet"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Arbete 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Allmän"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Av säkerhetsskäl döljs appinnehållet vid skärmdelning"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Automatiskt ansluten till satellit"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Du kan skicka och ta emot meddelanden utan mobil- eller wifi-nätverk"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Öppna Messages"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 2936716..89ded88 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Piga picha ya skrini"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Inaweza kupiga picha ya skrini ya onyesho."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Onyesho la kukagua, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Alama ya kidole haijatambuliwa"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Alama ya kidole haijatambuliwa"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Imeshindwa kutambua uso. Tumia alama ya kidole."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Uso hautambuliki. Tumia alama ya kidole."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Imethibitisha alama ya kidole"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Uso umethibitishwa"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Itisha PIN kabla hujabandua"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Omba mchoro wa kufungua kabla hujabandua"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Omba nenosiri kabla hujabandua"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Imesakinishwa na msimamizi wako"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Imesasishwa na msimamizi wako"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Imefutwa na msimamizi wako"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Sawa"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Wa 3 wa Kazini"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Jaribio"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Unaoshirikiwa"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Maudhui ya programu yamefichwa ili yasionekane kwenye skrini ya pamoja kwa sababu za kiusalama"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Imeunganishwa kiotomatiki na satelaiti"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Unaweza kutuma na kupokea ujumbe bila mtandao wa simu au Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Fungua Programu ya Messages"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 28ee91d..1c65e61 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ஸ்கிரீன்ஷாட்டை எடுக்கும்"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"டிஸ்ப்ளேவை ஸ்கிரீன்ஷாட் எடுக்க முடியும்."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"மாதிரிக்காட்சி, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"கைரேகை அங்கீகரிக்கப்படவில்லை"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"கைரேகை அங்கீகரிக்கப்படவில்லை"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"முகத்தை அடையாளம் காண முடியவில்லை. கைரேகையைப் பயன்படுத்தவும்."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"முகம் கண்டறிய முடியவில்லை. கைரேகை பயன்படுத்துக."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"கைரேகை அங்கீகரிக்கப்பட்டது"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"முகம் அங்கீகரிக்கப்பட்டது"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"முகம் அங்கீகரிக்கப்பட்டது. ’உறுதிப்படுத்துக’ என்பதை அழுத்துக"</string>
@@ -725,7 +727,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"முகத் தோற்றம் பதிவாகவில்லை. மீண்டும் முயலவும்."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"அடர் நிறக் கண்ணாடிகள் கண்டறியப்பட்டுள்ளது. உங்கள் முகத்தை முழுமையாகக் காட்டவும்."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"முகம் மறைக்கப்பட்டுள்ளது. உங்கள் முகத்தை முழுமையாகக் காட்டவும்."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"முகத்தை மறைக்காமல் முழுமையாகக் காட்டவும்."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"முகத்தைச் சரிபார்க்க இயலவில்லை. வன்பொருள் இல்லை."</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"அகற்றும் முன் PINஐக் கேள்"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"அகற்றும் முன் அன்லாக் பேட்டர்னைக் கேள்"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"உங்கள் நிர்வாகி நிறுவியுள்ளார்"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"பணி 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"பரிசோதனை"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"பொது"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"பாதுகாப்பிற்காக, திரைப் பகிர்வில் இருந்து ஆப்ஸ் உள்ளடக்கம் மறைக்கப்பட்டுள்ளது"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"சாட்டிலைட்டுடன் தானாக இணைக்கப்பட்டது"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"மொபைல்/வைஃபை நெட்வொர்க் இல்லாமல் நீங்கள் மெசேஜ்களை அனுப்பலாம் பெறலாம்"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ஆப்ஸைத் திறக்கவும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index c64c9b6d..423cf88 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్‌షాట్‌ను తీయండి"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్‌ప్లే యొక్క స్క్రీన్‌షాట్ తీసుకోవచ్చు."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ప్రివ్యూ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడం లేదా మార్చడం"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్‌ పట్టీగా ఉండటం"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"వేలిముద్ర గుర్తించబడలేదు"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"వేలిముద్ర గుర్తించబడలేదు"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ముఖం గుర్తించలేము. బదులుగా వేలిముద్ర ఉపయోగించండి."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ముఖం గుర్తించలేదు. బదులుగా వేలిముద్ర ఉపయోగించండి."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"వేలిముద్ర ప్రమాణీకరించబడింది"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ముఖం ప్రమాణీకరించబడింది"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ముఖం ప్రమాణీకరించబడింది, దయచేసి ధృవీకరించును నొక్కండి"</string>
@@ -688,7 +690,7 @@
   </string-array>
     <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"వేలిముద్ర చిహ్నం"</string>
-    <string name="device_unlock_notification_name" msgid="2632928999862915709">"పరికర అన్‌లాక్"</string>
+    <string name="device_unlock_notification_name" msgid="2632928999862915709">"డివైజ్ అన్‌లాక్"</string>
     <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"అన్‌లాక్ చేయడానికి మరొక మార్గాన్ని ట్రై చేయండి"</string>
     <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"మీ వేళ్లు తడిగా ఉండటం లేక ఇతరత్రా కారణాల వల్ల మీ వేలిముద్రను గుర్తించకపోతే, ఫేస్ అన్‌లాక్‌ను ఉపయోగించండి"</string>
     <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"తగినంత వెలుతురు లేకపోవడం లేక ఇతరత్రా కారణాల వల్ల మీ ఫేస్ గుర్తించబడనప్పుడు, వేలిముద్ర అన్‌లాక్‌ను ఉపయోగించండి"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"సరైనది!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"మళ్లీ ట్రై చేయండి"</string>
     <string name="lockscreen_password_wrong" msgid="8605355913868947490">"మళ్లీ ట్రై చేయండి"</string>
-    <string name="lockscreen_storage_locked" msgid="634993789186443380">"అన్ని లక్షణాలు మరియు డేటా కోసం అన్‌లాక్ చేయండి"</string>
+    <string name="lockscreen_storage_locked" msgid="634993789186443380">"అన్ని ఫీచర్ల కోసం, డేటా కోసం అన్‌లాక్ చేయండి"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"ఫేస్ అన్‌లాక్ ప్రయత్నాల గరిష్ఠ పరిమితిని మించిపోయారు"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"SIM లేదు"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"టాబ్లెట్‌లో SIM లేదు."</string>
@@ -1222,7 +1224,7 @@
     <string name="whichEditApplicationLabel" msgid="1463288652070140285">"ఎడిట్"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"షేర్ చేయండి"</string>
     <string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$sతో షేర్ చేయండి"</string>
-    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"షేర్ చేయి"</string>
+    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"షేర్ చేయండి"</string>
     <string name="whichSendToApplication" msgid="77101541959464018">"దీన్ని ఉపయోగించి పంపండి"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$sని ఉపయోగించి పంపండి"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"పంపండి"</string>
@@ -1416,7 +1418,7 @@
     <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"బగ్ రిపోర్ట్‌ను షేర్ చేయాలా?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ రిపోర్ట్‌ను షేర్ చేస్తోంది..."</string>
     <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ అడ్మిన్ ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ రిపోర్ట్‌ను రిక్వెస్ట్ చేశారు. యాప్‌లు మరియు డేటా షేర్ చేయబడవచ్చు."</string>
-    <string name="share_remote_bugreport_action" msgid="7630880678785123682">"షేర్ చేయి"</string>
+    <string name="share_remote_bugreport_action" msgid="7630880678785123682">"షేర్ చేయండి"</string>
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"తిరస్కరిస్తున్నాను"</string>
     <string name="select_input_method" msgid="3971267998568587025">"ఇన్‌పుట్ పద్ధతిని ఎంచుకోండి"</string>
     <string name="show_ime" msgid="6406112007347443383">"దీన్ని భౌతిక కీబోర్డ్ యాక్టివ్‌గా ఉన్నప్పుడు స్క్రీన్‌పై ఉంచుతుంది"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"అన్‌పిన్ చేయడానికి ముందు పిన్‌ కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"అన్‌పిన్ చేయడానికి ముందు అన్‌లాక్ ఆకృతి కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"మీ నిర్వాహకులు ఇన్‌స్టాల్ చేశారు"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"ఆఫీస్ 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"పరీక్ష"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"కమ్యూనల్"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"సెక్యూరిటీ కోసం స్క్రీన్ షేర్ నుండి యాప్ కంటెంట్ దాచబడింది"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"శాటిలైట్‌కు ఆటోమేటిక్‌గా కనెక్ట్ చేయబడింది"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"మీరు మొబైల్ లేదా Wi-Fi నెట్‌వర్క్ లేకుండా మెసేజ్‌లను పంపవచ్చు, స్వీకరించవచ్చు"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Messagesను తెరవండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 7555f26..47d1c44 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ถ่ายภาพหน้าจอ"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ถ่ายภาพหน้าจอได้"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"ตัวอย่าง <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"ไม่รู้จักลายนิ้วมือ"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ไม่รู้จักลายนิ้วมือ"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"ตรวจสอบสิทธิ์ลายนิ้วมือแล้ว"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ตรวจสอบสิทธิ์ใบหน้าแล้ว โปรดกดยืนยัน"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ขอ PIN ก่อนเลิกปักหมุด"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ขอรูปแบบการปลดล็อกก่อนเลิกปักหมุด"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ขอรหัสผ่านก่อนเลิกปักหมุด"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"ติดตั้งโดยผู้ดูแลระบบ"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"งาน 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ทดสอบ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"ส่วนกลาง"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"ซ่อนเนื้อหาแอปจากการแชร์หน้าจอเพื่อความปลอดภัย"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"เชื่อมต่อกับดาวเทียมโดยอัตโนมัติ"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"คุณรับส่งข้อความผ่านดาวเทียมได้โดยไม่ต้องใช้เครือข่ายมือถือหรือ Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"เปิด Messages"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 112da5c..1f9b48f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Kumuha ng screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puwedeng kumuha ng screenshot ng display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Hindi nakilala ang fingerprint"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Hindi nakilala ang fingerprint"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Hindi makilala ang mukha. Gumamit ng fingerprint."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Hindi nakilala ang mukha. Gumamit ng fingerprint."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Na-authenticate ang fingerprint"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Na-authenticate ang mukha"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Na-authenticate ang mukha, pakipindot ang kumpirmahin"</string>
@@ -709,7 +711,7 @@
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Iusog pakaliwa ang telepono mo"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Iusog pakanan ang telepono mo"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Tumingin nang mas direkta sa iyong device."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Hindi makita ang mukha mo. Hawakan ang telepono kapantay ng mata."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Hindi makita ang mukha mo. Ipantay ang telepono sa mata."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Masyadong magalaw. Hawakang mabuti ang telepono."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Paki-enroll muli ang iyong mukha."</string>
     <string name="face_acquired_too_different" msgid="4505278456634706967">"Hindi nakilala ang mukha. Subukan ulit."</string>
@@ -1222,7 +1224,7 @@
     <string name="whichEditApplicationLabel" msgid="1463288652070140285">"I-edit"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"Ibahagi"</string>
     <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Ibahagi gamit ang %1$s"</string>
-    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Ibahagi"</string>
+    <string name="whichSendApplicationLabel" msgid="7467813004769188515">"I-share"</string>
     <string name="whichSendToApplication" msgid="77101541959464018">"Ipadala gamit ang"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Ipadala gamit ang %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Ipadala"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Humingi ng PIN bago mag-unpin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Humingi ng password bago mag-unpin"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Na-install ng iyong admin"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Na-update ng iyong admin"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Na-delete ng iyong admin"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Trabaho 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Nakatago ang content ng app mula sa pagbabahagi ng screen para sa seguridad"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Awtomatikong nakakonekta sa satellite"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Puwede kang magpadala at tumanggap ng mga mensahe nang walang mobile o Wi-Fi network"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Buksan ang Messages"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 2ca545b..60c4a70 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran görüntüsü al"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran görüntüsü alınabilir."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Önizleme, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Parmak izi tanınmadı"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Parmak izi tanınmadı"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Yüz tanınamadı. Bunun yerine parmak izi kullanın."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Yüz tanınmadı. Bunun yerine parmak izi kullanın."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Parmak izi kimlik doğrulaması yapıldı"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Yüz kimliği doğrulandı"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yüz kimliği doğrulandı, lütfen onayla\'ya basın"</string>
@@ -1396,8 +1398,8 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"Bağlı cihaz şarj ediliyor. Diğer seçenekler için dokunun."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Analog ses aksesuarı algılandı"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Takılan cihaz bu telefonla uyumlu değil. Daha fazla bilgi edinmek için dokunun."</string>
-    <string name="adb_active_notification_title" msgid="408390247354560331">"USB hata ayıklaması bağlandı"</string>
-    <string name="adb_active_notification_message" msgid="5617264033476778211">"USB hata ayıklamayı kapatmak için dokunun"</string>
+    <string name="adb_active_notification_title" msgid="408390247354560331">"USB üzerinden hata ayıklama bağlandı"</string>
+    <string name="adb_active_notification_message" msgid="5617264033476778211">"USB üzerinden hata ayıklamayı kapatmak için dokunun"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB hata ayıklamasını devre dışı bırakmak için seçin."</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Kablosuz hata ayıklama bağlı"</string>
     <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Kablosuz hata ayıklamayı kapatmak için dokunun"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Yöneticiniz tarafından yüklendi"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Yöneticiniz tarafından güncellendi"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Yöneticiniz tarafından silindi"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Tamam"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Paylaşılan"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Uygulama içerikleri, güvenlik nedeniyle ekran paylaşımında gizlendi"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Uyduya otomatik olarak bağlandı"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Mobil veya kablosuz ağa bağlı olmadan mesaj alıp gönderebilirsiniz"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Mesajlar\'ı aç"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index df2c715..f8f3a23 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -358,6 +358,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Робити знімки екрана"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може робити знімки екрана."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (попередній перегляд)"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string>
@@ -664,7 +666,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Відбиток пальця не розпізнано"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Відбиток пальця не розпізнано"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Обличчя не розпізнано. Скористайтеся відбитком пальця."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Обличчя не розпізнано. Скористайтеся відбитком."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Відбиток пальця автентифіковано"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Обличчя автентифіковано"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string>
@@ -830,7 +832,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Укажіть максимальну довжину та кількість символів для паролів розблокування екрана та PIN-кодів."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Відстежувати спроби розблокування екрана"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати планшетний ПК або стирати всі його дані, якщо введено забагато неправильних паролів."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати планшет або стирати всі його дані, якщо введено забагато неправильних паролів."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте пристрій Android TV або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана, і блокуйте інформаційно-розважальну систему або видаляйте всі її дані, якщо пароль введено неправильно забагато разів."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати  телефон або стирати всі його дані, якщо введено забагато неправильних паролів."</string>
@@ -843,7 +845,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Блокувати екран"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Контролювати, як і коли блокується екран."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Видаляти всі дані"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Стирати дані планшетного ПК без попередження, відновлюючи заводські налаштування."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Стирати дані планшета без попередження, відновлюючи заводські налаштування."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Видаляйте дані пристрою Android TV без попередження шляхом відновлення заводських налаштувань."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Видаляйте всі дані інформаційно-розважальної системи без попередження, відновлюючи заводські налаштування."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Стирати дані телефона без попередження, відновивши заводські налаштування."</string>
@@ -1185,7 +1187,7 @@
     <string name="deleteText" msgid="4200807474529938112">"Видалити"</string>
     <string name="inputMethod" msgid="1784759500516314751">"Метод введення"</string>
     <string name="editTextMenuTitle" msgid="857666911134482176">"Дії з текстом"</string>
-    <string name="error_handwriting_unsupported" msgid="7809438534946014050">"Рукописне введення не підтримується в цьому полі"</string>
+    <string name="error_handwriting_unsupported" msgid="7809438534946014050">"У цьому полі не підтримується рукописне введення"</string>
     <string name="error_handwriting_unsupported_password" msgid="5095401146106891087">"Рукописне введення не підтримується в полях паролів"</string>
     <string name="input_method_nav_back_button_desc" msgid="3655838793765691787">"Назад"</string>
     <string name="input_method_ime_switch_button_desc" msgid="2736542240252198501">"Змінити метод введення"</string>
@@ -1898,7 +1900,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-код для відкріплення"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитувати ключ розблокування перед відкріпленням"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитувати пароль перед відкріпленням"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Установлено адміністратором"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2395,9 +2398,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Робочий профіль 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Тестовий профіль"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Спільний профіль"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"З міркувань безпеки вміст додатка приховано під час показу екрана"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Автоматично підключено до супутника"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Ви можете надсилати й отримувати повідомлення, не використовуючи Wi-Fi або мобільну мережу"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Відкрийте Повідомлення"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 29bd5be..a07189a 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"اسکرین شاٹ لیں"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ڈسپلے کا اسکرین شاٹ لیا جا سکتا ہے۔"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"پیش منظر، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"فنگر پرنٹ کی شناخت نہیں ہو سکی"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"فنگر پرنٹ کی شناخت نہیں ہو سکی"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"چہرہ پہچانا نہیں گیا۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"فنگر پرنٹ کی تصدیق ہو گئی"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"چہرے کی تصدیق ہو گئی"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چہرے کی تصدیق ہو گئی، براہ کرم \'تصدیق کریں\' کو دبائيں"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"‏پن ہٹانے سے پہلے PIN طلب کریں"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"آپ کے منتظم کے ذریعے انسٹال کیا گیا"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"تیسری دفتری پروفائل"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"ٹیسٹ"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"کمیونل"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"سیکیورٹی کے مد نظر ایپ کا مواد اسکرین کے اشتراک سے چھپا ہوا ہے"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"سٹلائٹ سے خودکار طور پر منسلک ہے"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"‏آپ موبائل یا Wi-Fi نیٹ ورک کے بغیر پیغامات بھیج اور موصول کر سکتے ہیں"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"پیغامات ایپ کو کھولیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index dddc3d6..b66d8c7 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Skrinshot olish"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekrandan skrinshot olishi mumkin."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Razm solish, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"holat panelini o‘zgartirish yoki o‘chirish"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"holat qatorida ko‘rinishi"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Barmoq izi aniqlanmadi"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Barmoq izi aniqlanmadi"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Bu yuz notanish. Barmoq izi orqali urining."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Yuz aniqlanmadi. Barmoq izi orqali urining."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Barmoq izi tekshirildi"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Yuzingiz aniqlandi"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yuzingiz aniqlandi, tasdiqlash uchun bosing"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Yechishda PIN kod talab qilinsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Yechishdan oldin grafik kalit so‘ralsin"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bo‘shatishdan oldin parol so‘ralsin"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Administrator tomonidan o‘rnatilgan"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Ish 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Umumiy"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Ekran namoyishida xavfsizlik maqsadida ilova kontenti berkitildi"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Sputnikka avtomatik ulandi"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Mobil yoki Wi-Fi tarmoqsiz xabarlarni yuborishingiz va qabul qilishingiz mumkin"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Xabarlar ilovasini ochish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 073a1a8..e4aadac 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Chụp ảnh màn hình"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Có thể chụp ảnh màn hình."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Bản xem trước, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Không nhận dạng được vân tay"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Không nhận dạng được vân tay"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Không thể nhận dạng khuôn mặt. Hãy dùng vân tay."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Không nhận dạng được khuôn mặt. Hãy dùng vân tay."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Đã xác thực vân tay"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Đã xác thực khuôn mặt"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Đã xác thực khuôn mặt, vui lòng nhấn để xác nhận"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Hỏi mã PIN trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Hỏi mật khẩu trước khi bỏ ghim"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Do quản trị viên của bạn cài đặt"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Do quản trị viên của bạn cập nhật"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Do quản trị viên của bạn xóa"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
@@ -2178,9 +2181,9 @@
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Khóa màn hình"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Chụp ảnh màn hình"</string>
     <string name="accessibility_system_action_headset_hook_label" msgid="8524691721287425468">"Giá treo tai nghe"</string>
-    <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Phím tắt hỗ trợ tiếp cận trên màn hình"</string>
-    <string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"Bộ chọn phím tắt hỗ trợ tiếp cận trên màn hình"</string>
-    <string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"Phím tắt hỗ trợ tiếp cận"</string>
+    <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Lối tắt hỗ trợ tiếp cận trên màn hình"</string>
+    <string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"Bộ chọn lối tắt hỗ trợ tiếp cận trên màn hình"</string>
+    <string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"Lối tắt hỗ trợ tiếp cận"</string>
     <string name="accessibility_system_action_dismiss_notification_shade" msgid="8931637495533770352">"Đóng Ngăn thông báo"</string>
     <string name="accessibility_system_action_dpad_up_label" msgid="1029042950229333782">"Chuyển lên trên bằng bàn phím di chuyển"</string>
     <string name="accessibility_system_action_dpad_down_label" msgid="3441918448624921461">"Chuyển xuống dưới bằng bàn phím di chuyển"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Công việc 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Kiểm thử"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Dùng chung"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Nội dung ứng dụng bị ẩn khỏi tính năng chia sẻ màn hình vì lý do bảo mật"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Đã tự động kết nối với vệ tinh"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Bạn có thể gửi và nhận tin nhắn mà không cần có mạng di động hoặc mạng Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Mở ứng dụng Tin nhắn"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ff2d4fc..ac4681b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -256,7 +256,7 @@
     <string name="global_action_power_off" msgid="4404936470711393203">"关机"</string>
     <string name="global_action_power_options" msgid="1185286119330160073">"电源"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"重启"</string>
-    <string name="global_action_emergency" msgid="1387617624177105088">"紧急呼救"</string>
+    <string name="global_action_emergency" msgid="1387617624177105088">"紧急呼叫"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"错误报告"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"结束会话"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"屏幕截图"</string>
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"预览,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"未能识别指纹"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"未能识别指纹"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"无法识别人脸。请改用指纹。"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"无法识别面孔。请改用指纹。"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"已验证指纹"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"面孔已验证"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已验证,请按确认按钮"</string>
@@ -844,7 +846,7 @@
     <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"恢复出厂设置时,系统会在不发出警告的情况下清除平板电脑上的数据。"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"不事先发出警告就以恢复出厂设置的方式清空 Android TV 设备中的数据。"</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"在不发出警告的情况下,通过恢复出厂设置来清除信息娱乐系统上的数据。"</string>
-    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"恢复出厂设置时,系统会在不发出警告的情况下清除手机上的数据。"</string>
+    <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"恢复出厂设置,不发出警告就直接清除手机上的数据。"</string>
     <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"清除个人资料数据"</string>
     <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"清空用户数据"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"清空此用户在这台平板电脑上的数据,而不事先发出警告。"</string>
@@ -990,7 +992,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"按 Menu 解锁或进行紧急呼救。"</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"按 MENU 解锁。"</string>
     <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"绘制解锁图案"</string>
-    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"紧急呼救"</string>
+    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"紧急呼叫"</string>
     <string name="lockscreen_return_to_call" msgid="3156883574692006382">"返回通话"</string>
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"正确!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"重试"</string>
@@ -1012,7 +1014,7 @@
     <string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"停止"</string>
     <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"快退"</string>
     <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"快进"</string>
-    <string name="emergency_calls_only" msgid="3057351206678279851">"只能拨打紧急呼救电话"</string>
+    <string name="emergency_calls_only" msgid="3057351206678279851">"只能拨打紧急呼叫电话"</string>
     <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"网络已锁定"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="2867953953604224166">"SIM 卡已用 PUK 码锁定。"</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"请参阅《用户指南》或与客服人员联系。"</string>
@@ -1894,9 +1896,10 @@
     <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g>克隆"</string>
     <string name="private_profile_label_badge" msgid="1712086003787839183">"私人“<xliff:g id="LABEL">%1$s</xliff:g>”"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消时要求输入PIN码"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消时要求绘制解锁图案"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定前要求绘制解锁图案"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消时要求输入密码"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"已由您的管理员安装"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -1977,7 +1980,7 @@
     <string name="language_selection_title" msgid="52674936078683285">"添加语言"</string>
     <string name="country_selection_title" msgid="5221495687299014379">"地区偏好设置"</string>
     <string name="search_language_hint" msgid="7004225294308793583">"输入语言名称"</string>
-    <string name="language_picker_section_suggested" msgid="6556199184638990447">"建议语言"</string>
+    <string name="language_picker_section_suggested" msgid="6556199184638990447">"建议的语言"</string>
     <string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"推荐地区"</string>
     <string name="language_picker_section_suggested_bilingual" msgid="5932198319583556613">"建议的语言"</string>
     <string name="region_picker_section_suggested_bilingual" msgid="704607569328224133">"建议的地区"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"测试"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"为安全起见而在屏幕共享画面中处于隐藏状态的应用内容"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"自动连接到卫星"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"您无需使用移动网络或 WLAN 网络便能收发消息"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"打开“信息”应用"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 6f560bb..1b1a9d5 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕擷圖"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕截圖。"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"無法辨識指紋"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"無法辨識指紋"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"無法辨識面孔,請改用指紋完成驗證。"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"無法辨識面孔,請改用指紋。"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"驗證咗指紋"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"面孔已經驗證"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已經驗證,請㩒一下 [確認]"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須提供解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"已由你的管理員安裝"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"測試"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"為安全起見,應用程式內容已從分享螢幕畫面隱藏"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"已自動連線至衛星"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"你可在沒有流動/Wi-Fi 網絡的情況下收發訊息"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"開啟「訊息」"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 8b2d534..76ed403 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕畫面"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕畫面。"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"指紋辨識失敗"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"指紋辨識失敗"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"無法辨識臉孔,請改用指紋完成驗證。"</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"無法辨識臉孔,請改用指紋。"</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"指紋驗證成功"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"臉孔驗證成功"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"臉孔驗證成功,請按下 [確認] 按鈕"</string>
@@ -828,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"管理螢幕鎖定密碼和 PIN 碼支援的字元和長度上限。"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"監控螢幕解鎖時密碼輸入錯誤的次數;如果密碼輸入錯誤的次數過多,則會鎖住平板電腦或全部清除平板電腦中的資料。"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"監控螢幕解鎖時密碼輸入錯誤的次數;如果錯誤次數過多,會鎖住平板電腦或清除平板電腦的所有資料。"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"監控螢幕解鎖密碼輸入錯誤的次數。如果輸入錯誤的次數超過上限,系統會將 Android TV 裝置鎖定,或清除 Android TV 裝置的所有資料。"</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"監控密碼輸入錯誤的次數。解鎖螢幕時,如果密碼輸入錯誤次數過多,系統就會鎖住資訊娛樂系統或清除資訊娛樂系統的所有資料。"</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"監控螢幕解鎖時密碼輸入錯誤的次數;如果密碼輸入錯誤的次數過多,則會鎖住手機或清除手機的所有資料。"</string>
@@ -1725,7 +1727,7 @@
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"要將裝置的完整控制權授予「<xliff:g id="SERVICE">%1$s</xliff:g>」嗎?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"如果你有無障礙服務需求,建議可將完整控制權授予具有相關功能的應用程式,但請勿將完整控制權授予大多數的應用程式。"</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"查看及控制螢幕"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"可讀取螢幕上的所有內容及在其他應用程式上顯示內容。"</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"可讀取螢幕上的所有內容,並在其他應用程式上顯示內容。"</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"查看及執行動作"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"可追蹤你與應用程式或硬體感應器的互動,並代表你與應用程式進行互動。"</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"允許"</string>
@@ -1896,13 +1898,14 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須畫出解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"已由你的管理員安裝"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <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="data_saver_description" msgid="4995164271550590517">"「數據節省模式」可防止部分應用程式在背景收發資料,以節省數據用量。你有一個使用中的應用程式仍可存取資料,但存取頻率可能會變低。舉例來說,圖片可能要等到你輕觸後才會顯示。"</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>
     <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{1 分鐘 (直到 {formattedTime})}other{# 分鐘 (直到 {formattedTime})}}"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"測試"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"通用"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"為安全起見,分享螢幕畫面未顯示應用程式內容"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"已自動連上衛星"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"你可以收發訊息,沒有行動/Wi-Fi 網路也無妨"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"開啟「訊息」應用程式"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 922172c..b44d5cd 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -356,6 +356,8 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Thatha isithombe-skrini"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ingathatha isithombe-skrini sesiboniso"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Hlola kuqala, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
+    <skip />
     <string name="permlab_statusBar" msgid="8798267849526214017">"khubaza noma guqula ibha yomumo"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"yiba yibha yesimo"</string>
@@ -662,7 +664,7 @@
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Isigxivizo somunwe asaziwa"</string>
     <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"Isigxivizo somunwe asaziwa"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6226091888364083421">"Ayibazi ubuso. Sebenzisa izigxivizo zeminwe kunalokho."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5590293588784953188">"Ubuso abaziwa. Sebenzisa izigxivizo zeminwe kunalokho."</string>
     <string name="fingerprint_authenticated" msgid="2024862866860283100">"Izigxivizo zeminwe zigunyaziwe"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Ubuso bufakazelwe ubuqiniso"</string>
     <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string>
@@ -1896,7 +1898,8 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Cela iphinikhodi ngaphambi kokuphina"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
-    <string name="package_installed_device_owner" msgid="7035926868974878525">"Kufakwe umlawuli wakho"</string>
+    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
+    <skip />
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Kubuyekezwe umlawuli wakho"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Kususwe umlawuli wakho"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"KULUNGILE"</string>
@@ -2393,9 +2396,10 @@
     <string name="profile_label_work_3" msgid="4834572253956798917">"Umsebenzi 3"</string>
     <string name="profile_label_test" msgid="9168641926186071947">"Hlola"</string>
     <string name="profile_label_communal" msgid="8743921499944800427">"Okomphakathi"</string>
-    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
-    <!-- no translation found for screen_not_shared_sensitive_content (7058419185079565001) -->
+    <!-- no translation found for redacted_notification_message (1520587845842228816) -->
     <skip />
+    <string name="redacted_notification_action_title" msgid="6942924973335920935"></string>
+    <string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"Okuqukethwe kwe-app kufihliwe kusuka ekwabelaneni kwesikrini ngokuvikelwa"</string>
     <string name="satellite_notification_title" msgid="4026338973463121526">"Ixhumeke ngokuzenzakalelayo kusathelayithi"</string>
     <string name="satellite_notification_summary" msgid="5207364139430767162">"Ungathumela futhi wamukele imilayezo ngaphandle kwenethiwekhi yeselula noma ye-Wi-Fi"</string>
     <string name="satellite_notification_open_message" msgid="4149234979688273729">"Vula Imilayezo"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b262ebd..37d39a7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2300,7 +2300,7 @@
              ensure that the status bar has enough contrast with the contents of this app, and set
              an appropriate effective bar background accordingly.
              See: {@link android.R.attr#enforceStatusBarContrast}
-             <p>If the app targets
+             <p>If the window belongs to an app targeting
              {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM VANILLA_ICE_CREAM} or above,
              this attribute is ignored.
              @deprecated Draw proper background behind
@@ -2320,7 +2320,7 @@
              ensure that the navigation bar has enough contrast with the contents of this app, and
              set an appropriate effective bar background accordingly.
              See: {@link android.R.attr#enforceNavigationBarContrast}
-             <p>If the app targets
+             <p>If the window belongs to an app targeting
              {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM VANILLA_ICE_CREAM} or above,
              this attribute is ignored.
              @deprecated Draw proper background behind
@@ -2335,7 +2335,7 @@
              have been requested to be translucent with
              {@link android.R.attr#windowTranslucentNavigation}.
              Corresponds to {@link android.view.Window#setNavigationBarDividerColor(int)}.
-             <p>If the app targets
+             <p>If the window belongs to an app targeting
              {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM VANILLA_ICE_CREAM} or above,
              this attribute is ignored.
              @deprecated Draw proper background behind
@@ -2431,7 +2431,9 @@
 
         <!-- Controls how the window is laid out if there is a {@code DisplayCutout}.
         <p>
-        Defaults to {@code default}.
+        Defaults to {@code default}. But if the window fills the screen, and it belongs to an app
+        targeting {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM VANILLA_ICE_CREAM} or
+        above, the behavior will be the same as specifying {@code always} regardless.
         <p>
         See also
         {@link android.view.WindowManager.LayoutParams#layoutInDisplayCutoutMode
@@ -2528,8 +2530,8 @@
 
         <!-- Flag indicating whether this window would opt-out the edge-to-edge enforcement.
 
-             <p>If this is false, the edge-to-edge enforcement will be applied to the window if its
-             app targets
+             <p>If this is false, the edge-to-edge enforcement will be applied to the window if it
+             belongs to an app targeting
              {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM VANILLA_ICE_CREAM} or above.
              The affected behaviors are:
              <ul>
@@ -2537,9 +2539,8 @@
                  through the {@link android.view.WindowInsets} to the content view, as if calling
                  {@link android.view.Window#setDecorFitsSystemWindows(boolean)} with false.
                  <li>{@link android.view.WindowManager.LayoutParams#layoutInDisplayCutoutMode} of
-                 the non-floating windows will be set to {@link
+                 the fill-screen windows will behave as specifying {@link
                  android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS}.
-                 Changing it to other values will cause {@link lang.IllegalArgumentException}.
                  <li>The framework will set {@link android.R.attr#statusBarColor},
                  {@link android.R.attr#navigationBarColor}, and
                  {@link android.R.attr#navigationBarDividerColor} to transparent.
@@ -4476,22 +4477,22 @@
     </declare-styleable>
 
     <!-- Specify one or more <code>polling-loop-filter</code> elements inside a
-         <code>host-apdu-service</code> to indicate polling loop frames that
-         your service can handle. -->
-    <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") -->
+         <code>host-apdu-service</code> or <code>offhost-apdu-service</code> to indicate polling
+         loop frames that your service can handle. -->
+    <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
     <declare-styleable name="PollingLoopFilter">
         <!-- The polling loop frame. This attribute is mandatory. -->
         <attr name="name" />
         <!-- Whether or not the system should automatically start a transaction when this polling
          loop filter matches. If not set, default value is false. -->
-        <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") -->
+        <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
         <attr name="autoTransact" format="boolean"/>
     </declare-styleable>
 
     <!-- Specify one or more <code>polling-loop-pattern-filter</code> elements inside a
-         <code>host-apdu-service</code> to indicate polling loop frames that
-         your service can handle. -->
-    <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") -->
+         <code>host-apdu-service</code> or <code>offhost-apdu-service</code>  to indicate polling
+         loop frames that your service can handle. -->
+    <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
     <declare-styleable name="PollingLoopPatternFilter">
         <!-- The patter to match polling loop frames to, must to be compatible with
          {@link java.util.regex.Pattern#compile(String)} and only contain hexadecimal numbers and
@@ -4499,7 +4500,7 @@
         <attr name="name" />
         <!-- Whether or not the system should automatically start a transaction when this polling
          loop filter matches. If not set, default value is false. -->
-        <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") -->
+        <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
         <attr name="autoTransact" format="boolean"/>
     </declare-styleable>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d4db244..1a61870 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3009,6 +3009,10 @@
     <!-- Maximum number of users we allow to be running at a time -->
     <integer name="config_multiuserMaxRunningUsers">3</integer>
 
+    <!-- Number of seconds of uptime after a full user enters the background before we attempt to
+         stop it due to inactivity. Set to -1 to disable scheduling stopping background users. -->
+    <integer name="config_backgroundUserScheduledStopTimeSecs">1800</integer> <!-- 30 minutes -->
+
     <!-- Whether to delay user data locking for background user.
          If false, user switched-out from user switching will still be in running state until
          config_multiuserMaxRunningUsers is reached. Once config_multiuserMaxRunningUsers is
@@ -4334,9 +4338,6 @@
     -->
     <bool name="config_wallpaperTopApp">false</bool>
 
-    <!-- True if the device supports dVRR  -->
-    <bool name="config_supportsDvrr">false</bool>
-
     <!-- True if the device supports at least one form of multi-window.
          E.g. freeform, split-screen, picture-in-picture. -->
     <bool name="config_supportsMultiWindow">true</bool>
@@ -7018,4 +7019,9 @@
     <!-- Frame rate compatibility value for Wallpaper
          FRAME_RATE_COMPATIBILITY_MIN (102) is used by default for lower power consumption -->
     <integer name="config_wallpaperFrameRateCompatibility">102</integer>
+
+    <!-- Min time in milliseconds to complete an emergency gesture for it count.
+         If the gesture is completed faster than this, we assume it's not performed by human and the
+         event gets ignored. -->
+    <integer name="config_defaultMinEmergencyGestureTapDurationMillis">200</integer>
 </resources>
diff --git a/core/res/res/values/config_battery_stats.xml b/core/res/res/values/config_battery_stats.xml
index e42962c..8d97362 100644
--- a/core/res/res/values/config_battery_stats.xml
+++ b/core/res/res/values/config_battery_stats.xml
@@ -32,6 +32,12 @@
     devices-->
     <integer name="config_defaultPowerStatsThrottlePeriodCpu">60000</integer>
 
+    <!-- Mobile Radio power stats collection throttle period in milliseconds. -->
+    <integer name="config_defaultPowerStatsThrottlePeriodMobileRadio">3600000</integer>
+
+    <!-- Mobile Radio power stats collection throttle period in milliseconds. -->
+    <integer name="config_defaultPowerStatsThrottlePeriodWifi">3600000</integer>
+
     <!-- PowerStats aggregation period in milliseconds. This is the interval at which the power
     stats aggregation procedure is performed and the results stored in PowerStatsStore. -->
     <integer name="config_powerStatsAggregationPeriod">14400000</integer>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 7c9f2ef..a248ede 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -235,6 +235,12 @@
     <integer name="config_esim_bootstrap_data_limit_bytes">-1</integer>
     <java-symbol type="integer" name="config_esim_bootstrap_data_limit_bytes" />
 
+    <!-- Reevaluate existing data networks for bootstrap sim data usage at mentioned intervals
+         during esim bootstrap activation. If the value set is 0 or -1, default interval of
+         60000 millis will be set. -->
+    <integer name="config_reevaluate_bootstrap_sim_data_usage_millis">60000</integer>
+    <java-symbol type="integer" name="config_reevaluate_bootstrap_sim_data_usage_millis" />
+
     <!-- Telephony config for the PLMNs of all satellite providers. This is used by satellite modem
          to identify providers that should be ignored if the carrier config
          carrier_supported_satellite_services_per_provider_bundle does not support them.
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 4be8c1b..c84f781 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -145,7 +145,7 @@
     <public name="fragmentSuffix"/>
     <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
     <public name="useBoundsForWidth"/>
-    <!-- @FlaggedApi("android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP") -->
+    <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
     <public name="autoTransact"/>
     <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
     <public name="windowOptOutEdgeToEdgeEnforcement"/>
@@ -159,7 +159,7 @@
     <public name="contentSensitivity" />
     <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
     <public name="supportsConnectionlessStylusHandwriting" />
-    <!-- @FlaggedApi("android.nfc.Flags.FLAG_OBSERVE_MODE") -->
+    <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
     <public name="shouldDefaultToObserveMode"/>
     <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
     <public name="allowCrossUidActivitySwitchFromBelow"/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f3aa27f..e96240d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1018,6 +1018,9 @@
     <!-- The title to use when a dream is opened in preview mode. [CHAR LIMIT=NONE] -->
     <string name="dream_preview_title">Preview, <xliff:g id="dream_name" example="Clock">%1$s</xliff:g></string>
 
+    <!-- The title to use when a dream is open in accessibility mode to let users know to double tap to dismiss the dream  [CHAR LIMIT=32] -->
+    <string name="dream_accessibility_action_click">dismiss</string>
+
     <!--  Permissions -->
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1888,7 +1891,7 @@
     <!-- Message shown when UDFPS fails to match -->
     <string name="fingerprint_udfps_error_not_match">Fingerprint not recognized</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>
+    <string name="fingerprint_dialog_use_fingerprint_instead">Face not recognized. Use fingerprint instead.</string>
 
     <!-- Accessibility message announced when a fingerprint has been authenticated [CHAR LIMIT=NONE] -->
     <string name="fingerprint_authenticated">Fingerprint authenticated</string>
@@ -5188,7 +5191,7 @@
     <string name="lock_to_app_unlock_password">Ask for password before unpinning</string>
 
     <!-- Notification shown when device owner silently installs a package [CHAR LIMIT=NONE] -->
-    <string name="package_installed_device_owner">Installed by your admin</string>
+    <string name="package_installed_device_owner">Installed by your admin.\nGo to settings to view granted permissions</string>
     <!-- Notification shown when device owner silently updates a package [CHAR LIMIT=NONE] -->
     <string name="package_updated_device_owner">Updated by your admin</string>
     <!-- Notification shown when device owner silently deletes a package [CHAR LIMIT=NONE] -->
@@ -6436,10 +6439,8 @@
     <!-- Communal profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] -->
     <string name="profile_label_communal">Communal</string>
 
-    <!-- Notification message used when a notification's normal message contains sensitive information. -->
-    <!-- TODO b/301960090: replace with redacted message string and action title, when/if UX provides one -->
-    <!-- DO NOT TRANSLATE -->
-    <string name="redacted_notification_message"></string>
+    <!-- Notification message used when a notification's normal message contains sensitive information [CHAR_LIMIT=NOTIF_BODY] -->
+    <string name="redacted_notification_message">Sensitive notification content hidden</string>
     <!-- Notification action title used instead of a notification's normal title sensitive [CHAR_LIMIT=NOTIF_BODY] -->
     <string name="redacted_notification_action_title"></string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f33e277..4f19c27 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -404,7 +404,6 @@
   <java-symbol type="bool" name="config_supportAudioSourceUnprocessed" />
   <java-symbol type="bool" name="config_freeformWindowManagement" />
   <java-symbol type="bool" name="config_supportsBubble" />
-  <java-symbol type="bool" name="config_supportsDvrr" />
   <java-symbol type="bool" name="config_supportsMultiWindow" />
   <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" />
   <java-symbol type="bool" name="config_supportsMultiDisplay" />
@@ -489,6 +488,7 @@
   <java-symbol type="integer" name="config_lockSoundVolumeDb" />
   <java-symbol type="integer" name="config_multiuserMaximumUsers" />
   <java-symbol type="integer" name="config_multiuserMaxRunningUsers" />
+  <java-symbol type="integer" name="config_backgroundUserScheduledStopTimeSecs" />
   <java-symbol type="bool" name="config_multiuserDelayUserDataLocking" />
   <java-symbol type="bool" name="config_multiuserVisibleBackgroundUsers" />
   <java-symbol type="bool" name="config_multiuserVisibleBackgroundUsersOnDefaultDisplay" />
@@ -1528,6 +1528,7 @@
   <java-symbol type="layout" name="number_picker" />
   <java-symbol type="layout" name="permissions_package_list_item" />
   <java-symbol type="layout" name="popup_menu_item_layout" />
+  <java-symbol type="layout" name="popup_menu_item_layout_material" />
   <java-symbol type="layout" name="popup_menu_header_item_layout" />
   <java-symbol type="layout" name="remote_views_adapter_default_loading_view" />
   <java-symbol type="layout" name="search_bar" />
@@ -4471,6 +4472,7 @@
   <java-symbol type="string" name="capability_title_canTakeScreenshot" />
 
   <java-symbol type="string" name="dream_preview_title" />
+  <java-symbol type="string" name="dream_accessibility_action_click" />
 
   <java-symbol type="string" name="config_servicesExtensionPackage" />
 
@@ -5217,6 +5219,8 @@
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" />
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
   <java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodCpu" />
+  <java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodMobileRadio" />
+  <java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodWifi" />
   <java-symbol type="integer" name="config_powerStatsAggregationPeriod" />
   <java-symbol type="integer" name="config_aggregatedPowerStatsSpanDuration" />
 
@@ -5379,6 +5383,7 @@
   <java-symbol type="string" name="satellite_notification_open_message" />
   <java-symbol type="string" name="satellite_notification_how_it_works" />
   <java-symbol type="drawable" name="ic_satellite_alt_24px" />
+  <java-symbol type="drawable" name="ic_android_satellite_24px" />
 
   <!-- DisplayManager configs. -->
   <java-symbol type="bool" name="config_evenDimmerEnabled" />
@@ -5401,4 +5406,6 @@
 
   <!-- Frame rate compatibility value for Wallpaper -->
   <java-symbol type="integer" name="config_wallpaperFrameRateCompatibility" />
+
+  <java-symbol type="integer" name="config_defaultMinEmergencyGestureTapDurationMillis" />
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index c8625b9..9bb72d9 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -28,7 +28,7 @@
          standard SMS rate. The user is warned when the destination phone number matches the
          "pattern" or "premium" regexes, and does not match the "free" or "standard" regexes. -->
 
-    <!-- Harmonised European Short Codes are 6 digit numbers starting with 116 (free helplines).
+    <!-- Harmonised European Short Codes are 7 digit numbers starting with 116 (free helplines).
          Premium patterns include short codes from: http://aonebill.com/coverage&tariffs
          and http://mobilcent.com/info-worldwide.asp and extracted from:
          http://smscoin.net/software/engine/WordPress/Paid+SMS-registration/ -->
@@ -39,8 +39,8 @@
     <!-- Albania: 5 digits, known short codes listed -->
     <shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
 
-    <!-- Argentina: 5 digits, known short codes listed -->
-    <shortcode country="ar" pattern="\\d{5}" free="11711|28291|44077|78887" />
+    <!-- Argentina: 6 digits, known short codes listed -->
+    <shortcode country="ar" pattern="\\d{1,6}" free="11711|28291|44077|78887|191289|39010" />
 
     <!-- Armenia: 3-5 digits, emergency numbers 10[123] -->
     <shortcode country="am" pattern="\\d{3,5}" premium="11[2456]1|3024" free="10[123]|71522|71512|71502" />
@@ -67,7 +67,7 @@
     <shortcode country="bh" pattern="\\d{1,5}" free="81181|85999" />
 
     <!-- Brazil: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000" />
+    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000|2652" />
 
     <!-- Belarus: 4 digits -->
     <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
@@ -163,7 +163,7 @@
     <shortcode country="in" pattern="\\d{1,5}" free="59336|53969" />
 
     <!-- Indonesia: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="id" pattern="\\d{1,5}" free="99477|6006|46645|363|93457" />
+    <shortcode country="id" pattern="\\d{1,5}" free="99477|6006|46645|363|93457|99265" />
 
     <!-- Ireland: 5 digits, 5xxxx (50xxx=free, 5[12]xxx=standard), plus EU:
          http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf -->
@@ -172,6 +172,9 @@
     <!-- Israel: 1-5 digits, known premium codes listed -->
     <shortcode country="il" pattern="\\d{1,5}" premium="4422|4545" free="37477|6681" />
 
+    <!-- Iran: 4-6 digits, known premium codes listed -->
+    <shortcode country="ir" pattern="\\d{4,6}" free="700791|700792" />
+
     <!-- Italy: 5 digits (premium=41xxx,42xxx), plus EU:
          https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006B0001PDFE.pdf -->
     <shortcode country="it" pattern="\\d{5}" premium="44[0-4]\\d{2}|47[0-4]\\d{2}|48[0-4]\\d{2}|44[5-9]\\d{4}|47[5-9]\\d{4}|48[5-9]\\d{4}|455\\d{2}|499\\d{2}" free="116\\d{3}|4112503|40\\d{0,12}" standard="430\\d{2}|431\\d{2}|434\\d{4}|435\\d{4}|439\\d{7}" />
@@ -219,11 +222,11 @@
     <!-- Mozambique: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="mz" pattern="\\d{1,5}" free="1714" />
 
-    <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
-    <shortcode country="mx" pattern="\\d{4,6}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346" />
+    <!-- Mexico: 4-7 digits (not confirmed), known premium codes listed -->
+    <shortcode country="mx" pattern="\\d{4,7}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346|3030303" />
 
     <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
-    <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" />
+    <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668|66966" />
 
     <!-- Namibia: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="na" pattern="\\d{1,5}" free="40005" />
@@ -255,6 +258,9 @@
     <!-- Palestine: 5 digits, known premium codes listed -->
     <shortcode country="ps" pattern="\\d{1,5}" free="37477|6681" />
 
+    <!-- Paraguay: 6 digits, known premium codes listed -->
+    <shortcode country="py" pattern="\\d{6}" free="191289" />
+
     <!-- Poland: 4-5 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="pl" pattern="\\d{4,5}" premium="74240|79(?:10|866)|92525" free="116\\d{3}|8012|80921" />
 
@@ -275,7 +281,7 @@
     <shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)|8424" free="6954|8501" standard="2037|2044"/>
 
     <!-- Rwanda: 4 digits -->
-    <shortcode country="rw" pattern="\\d{4}" free="5060" />
+    <shortcode country="rw" pattern="\\d{4}" free="5060|5061" />
 
     <!-- Saudi Arabia -->
     <shortcode country="sa" pattern="\\d{1,5}" free="8145" />
@@ -309,7 +315,10 @@
     <shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" />
 
     <!-- Tanzania: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="tz" pattern="\\d{1,5}" free="15046|15234" />
+    <shortcode country="tz" pattern="\\d{1,5}" free="15046|15234|15324" />
+
+    <!-- Tunisia: 5 digits, known premium codes listed -->
+    <shortcode country="tn" pattern="\\d{5}" free="85799" />
 
     <!-- Turkey -->
     <shortcode country="tr" pattern="\\d{1,5}" free="7529|5528|6493|3193" />
@@ -324,8 +333,11 @@
          visual voicemail code for T-Mobile: 122 -->
     <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611|96831" />
 
-    <!--Uruguay : 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="uy" pattern="\\d{1,5}" free="55002" />
+    <!--Uruguay : 1-6 digits (standard system default, not country specific) -->
+    <shortcode country="uy" pattern="\\d{1,6}" free="55002|191289" />
+
+    <!-- Venezuela: 1-6 digits (standard system default, not country specific) -->
+    <shortcode country="ve" pattern="\\d{1,6}" free="538352" />
 
     <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055|8079" />
@@ -336,6 +348,9 @@
     <!-- South Africa -->
     <shortcode country="za" pattern="\\d{1,5}" free="44136|30791|36056|33009" />
 
+    <!-- Yemen -->
+    <shortcode country="ye" pattern="\\d{1,4}" free="5081" />
+
     <!-- Zimbabwe -->
     <shortcode country="zw" pattern="\\d{1,5}" free="33679" />
 
diff --git a/core/tests/FileSystemUtilsTest/Android.bp b/core/tests/FileSystemUtilsTest/Android.bp
new file mode 100644
index 0000000..53c22df
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/Android.bp
@@ -0,0 +1,78 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_android_kernel",
+}
+
+cc_library {
+    name: "libpunchtest",
+    stl: "none",
+    host_supported: true,
+    srcs: ["jni/android_test_jni_source.cpp"],
+    header_libs: ["jni_headers"],
+}
+
+android_test_helper_app {
+    name: "embedded_native_libs_test_app",
+    srcs: ["apk_embedded_native_libs/src/**/*.java"],
+    manifest: "apk_embedded_native_libs/embedded_native_libs_test_app.xml",
+    compile_multilib: "64",
+    jni_libs: [
+        "libpunchtest",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "platform-test-annotations",
+    ],
+    use_embedded_native_libs: true,
+}
+
+android_test_helper_app {
+    name: "extract_native_libs_test_app",
+    srcs: ["apk_extract_native_libs/src/**/*.java"],
+    manifest: "apk_extract_native_libs/extract_native_libs_test_app.xml",
+    compile_multilib: "64",
+    jni_libs: [
+        "libpunchtest",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "platform-test-annotations",
+    ],
+    use_embedded_native_libs: false,
+}
+
+java_test_host {
+    name: "FileSystemUtilsTests",
+    // Include all test java files
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "junit",
+        "platform-test-annotations",
+        "truth",
+    ],
+    libs: [
+        "tradefed",
+        "compatibility-host-util",
+        "compatibility-tradefed",
+    ],
+    data: [
+        ":embedded_native_libs_test_app",
+        ":extract_native_libs_test_app",
+    ],
+    test_suites: ["general-tests"],
+    test_config: "AndroidTest.xml",
+}
diff --git a/core/tests/FileSystemUtilsTest/AndroidManifest.xml b/core/tests/FileSystemUtilsTest/AndroidManifest.xml
new file mode 100644
index 0000000..acd5ef3
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          android:installLocation="internalOnly"
+          package="com.android.internal.content.fstests">
+
+    <instrumentation
+            android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.internal.content.fstests"
+            android:label="Frameworks FileSystemUtils Tests" />
+
+</manifest>
diff --git a/core/tests/FileSystemUtilsTest/AndroidTest.xml b/core/tests/FileSystemUtilsTest/AndroidTest.xml
new file mode 100644
index 0000000..27f49b2
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration description="Runs FileSystemUtilsTest.">
+    <option name="test-suite-tag" value="apct"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="embedded_native_libs_test_app.apk" />
+        <option name="test-file-name" value="extract_native_libs_test_app.apk" />
+    </target_preparer>
+
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="FileSystemUtilsTests.jar" />
+    </test>
+</configuration>
diff --git a/core/tests/FileSystemUtilsTest/TEST_MAPPING b/core/tests/FileSystemUtilsTest/TEST_MAPPING
new file mode 100644
index 0000000..d41e981
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "FileSystemUtilsTests"
+    }
+  ]
+}
diff --git a/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/embedded_native_libs_test_app.xml b/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/embedded_native_libs_test_app.xml
new file mode 100644
index 0000000..868f7f3
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/embedded_native_libs_test_app.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.test.embedded">
+    <application android:extractNativeLibs="false">
+        <uses-library android:name="android.test.runner"/>
+        <activity android:name=".MainActivity"
+                  android:exported="true"
+                  android:process=":NewProcess">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+    </application>
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.test.embedded"/>
+</manifest>
\ No newline at end of file
diff --git a/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/src/android/test/embedded/MainActivity.java b/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/src/android/test/embedded/MainActivity.java
new file mode 100644
index 0000000..efa2a39
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/src/android/test/embedded/MainActivity.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.embedded;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.VisibleForTesting;
+
+public class MainActivity extends Activity {
+
+    static {
+        System.loadLibrary("punchtest");
+    }
+
+    @VisibleForTesting
+    static final String INTENT_TYPE = "android.test.embedded.EMBEDDED_LIB_LOADED";
+
+    @VisibleForTesting
+    static final String KEY_OPERAND_1 = "OP1";
+
+    @VisibleForTesting
+    static final String KEY_OPERAND_2 = "OP2";
+
+    @VisibleForTesting
+    static final String KEY_RESULT = "RESULT";
+
+    @Override
+    public void onCreate(Bundle savedOnstanceState) {
+        super.onCreate(savedOnstanceState);
+
+        Intent received =  getIntent();
+        int op1 = received.getIntExtra(KEY_OPERAND_1, -1);
+        int op2 = received.getIntExtra(KEY_OPERAND_2, -1);
+        int result = add(op1, op2);
+
+        // Send broadcast so that test can know app has launched and lib is loaded
+        // attach result which has been fetched from JNI lib
+        Intent intent = new Intent(INTENT_TYPE);
+        intent.putExtra(KEY_RESULT, result);
+        sendBroadcast(intent);
+    }
+
+    private native int add(int op1, int op2);
+}
diff --git a/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/src/android/test/embedded/PunchEmbeddedLibTest.java b/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/src/android/test/embedded/PunchEmbeddedLibTest.java
new file mode 100644
index 0000000..d7d67b8
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/apk_embedded_native_libs/src/android/test/embedded/PunchEmbeddedLibTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.embedded;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class PunchEmbeddedLibTest {
+
+    @Test
+    public void testPunchedNativeLibs_embeddedLib() throws Exception {
+        Context context = InstrumentationRegistry.getContext();
+        CountDownLatch receivedSignal = new CountDownLatch(1);
+
+        // Test app is expected to receive this and perform addition of operands using punched lib
+        int op1 = 48;
+        int op2 = 75;
+        IntentFilter intentFilter = new IntentFilter(MainActivity.INTENT_TYPE);
+        BroadcastReceiver broadcastReceiver =
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        receivedSignal.countDown();
+                        int result = intent.getIntExtra(MainActivity.KEY_RESULT, 1000);
+                        Assert.assertEquals(result, op1 + op2);
+
+                    }
+                };
+        context.registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_EXPORTED);
+
+        Intent launchIntent =
+                context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
+        launchIntent.putExtra(MainActivity.KEY_OPERAND_1, op1);
+        launchIntent.putExtra(MainActivity.KEY_OPERAND_2, op2);
+        context.startActivity(launchIntent);
+
+        Assert.assertTrue("Failed to launch app", receivedSignal.await(10, TimeUnit.SECONDS));
+    }
+}
diff --git a/core/tests/FileSystemUtilsTest/apk_extract_native_libs/extract_native_libs_test_app.xml b/core/tests/FileSystemUtilsTest/apk_extract_native_libs/extract_native_libs_test_app.xml
new file mode 100644
index 0000000..6db96f7
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/apk_extract_native_libs/extract_native_libs_test_app.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.test.extract">
+    <application android:extractNativeLibs="true">
+        <uses-library android:name="android.test.runner"/>
+        <activity android:name=".MainActivity"
+                  android:exported="true"
+                  android:process=":NewProcess">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+    </application>
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.test.extract"/>
+</manifest>
\ No newline at end of file
diff --git a/core/tests/FileSystemUtilsTest/apk_extract_native_libs/src/android/test/extract/MainActivity.java b/core/tests/FileSystemUtilsTest/apk_extract_native_libs/src/android/test/extract/MainActivity.java
new file mode 100644
index 0000000..b1c157e
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/apk_extract_native_libs/src/android/test/extract/MainActivity.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.extract;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.VisibleForTesting;
+
+public class MainActivity extends Activity {
+
+    static {
+        System.loadLibrary("punchtest");
+    }
+
+    @VisibleForTesting
+    static final String INTENT_TYPE = "android.test.extract.EXTRACTED_LIB_LOADED";
+
+    @VisibleForTesting
+    static final String KEY_OPERAND_1 = "OP1";
+
+    @VisibleForTesting
+    static final String KEY_OPERAND_2 = "OP2";
+
+    @VisibleForTesting
+    static final String KEY_RESULT = "RESULT";
+
+    @Override
+    public void onCreate(Bundle savedOnstanceState) {
+        super.onCreate(savedOnstanceState);
+
+        Intent received =  getIntent();
+        int op1 = received.getIntExtra(KEY_OPERAND_1, -1);
+        int op2 = received.getIntExtra(KEY_OPERAND_2, -1);
+        int result = subtract(op1, op2);
+
+        // Send broadcast so that test can know app has launched and lib is loaded
+        // attach result which has been fetched from JNI lib
+        Intent intent = new Intent(INTENT_TYPE);
+        intent.putExtra(KEY_RESULT, result);
+        sendBroadcast(intent);
+    }
+
+    private native int subtract(int op1, int op2);
+}
diff --git a/core/tests/FileSystemUtilsTest/apk_extract_native_libs/src/android/test/extract/PunchExtractedLibTest.java b/core/tests/FileSystemUtilsTest/apk_extract_native_libs/src/android/test/extract/PunchExtractedLibTest.java
new file mode 100644
index 0000000..7cc1017
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/apk_extract_native_libs/src/android/test/extract/PunchExtractedLibTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.extract;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class PunchExtractedLibTest {
+
+    @Test
+    public void testPunchedNativeLibs_extractedLib() throws Exception {
+        Context context = InstrumentationRegistry.getContext();
+        CountDownLatch receivedSignal = new CountDownLatch(1);
+
+        // Test app is expected to receive this and perform subtraction using extracted lib
+        int op1 = 100;
+        int op2 = 71;
+        IntentFilter intentFilter = new IntentFilter(MainActivity.INTENT_TYPE);
+        BroadcastReceiver broadcastReceiver =
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        receivedSignal.countDown();
+                        int result = intent.getIntExtra(MainActivity.KEY_RESULT, 1000);
+                        Assert.assertEquals(result, op1 - op2);
+                    }
+                };
+        context.registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_EXPORTED);
+
+        Intent launchIntent =
+                context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
+        launchIntent.putExtra(MainActivity.KEY_OPERAND_1, op1);
+        launchIntent.putExtra(MainActivity.KEY_OPERAND_2, op2);
+        context.startActivity(launchIntent);
+
+        Assert.assertTrue("Failed to launch app", receivedSignal.await(10, TimeUnit.SECONDS));
+    }
+}
diff --git a/core/tests/FileSystemUtilsTest/jni/android_test_jni_source.cpp b/core/tests/FileSystemUtilsTest/jni/android_test_jni_source.cpp
new file mode 100644
index 0000000..2a5ba81
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/jni/android_test_jni_source.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+
+// This will be called from embedded_native_libs_test_app
+extern "C" JNIEXPORT
+jint JNICALL Java_android_test_embedded_MainActivity_add(JNIEnv*, jclass, jint op1, jint op2) {
+    return op1 + op2;
+}
+
+// This will be called from extract_native_libs_test_app
+extern "C" JNIEXPORT
+jint JNICALL Java_android_test_extract_MainActivity_subtract(JNIEnv*, jclass, jint op1, jint op2) {
+    return op1 - op2;
+}
+
+// Initialize JNI
+jint JNI_OnLoad(JavaVM *jvm, void */* reserved */) {
+    JNIEnv *e;
+
+    // Check JNI version
+    if (jvm->GetEnv((void **) &e, JNI_VERSION_1_6)) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_6;
+}
diff --git a/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java b/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java
new file mode 100644
index 0000000..77802e5
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.content;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AppModeFull;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class FileSystemUtilsTest extends BaseHostJUnit4Test {
+
+    @Test
+    @AppModeFull
+    public void runPunchedApp_embeddedNativeLibs() throws DeviceNotAvailableException {
+        String appPackage = "android.test.embedded";
+        String testName = "PunchEmbeddedLibTest";
+        assertTrue(isPackageInstalled(appPackage));
+        runDeviceTests(appPackage, appPackage + "." + testName);
+    }
+
+    @Test
+    @AppModeFull
+    public void runPunchedApp_extractedNativeLibs() throws DeviceNotAvailableException {
+        String appPackage = "android.test.extract";
+        String testName = "PunchExtractedLibTest";
+        assertTrue(isPackageInstalled(appPackage));
+        runDeviceTests(appPackage, appPackage + "." + testName);
+    }
+}
diff --git a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
index 6cc5485..8072d69 100644
--- a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
+++ b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.os.bugreports.tests;
 
+import static android.content.Context.RECEIVER_EXPORTED;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertNotNull;
@@ -358,7 +360,10 @@
         // shell UID rather than our own.
         BugreportBroadcastReceiver br = new BugreportBroadcastReceiver();
         InstrumentationRegistry.getContext()
-                .registerReceiver(br, new IntentFilter(INTENT_BUGREPORT_FINISHED));
+                .registerReceiver(
+                        br,
+                        new IntentFilter(INTENT_BUGREPORT_FINISHED),
+                        RECEIVER_EXPORTED);
         UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
                 .executeShellCommand("am bug-report");
 
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 4808204..04e90ba 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -154,6 +154,12 @@
         "android.test.runner",
         "org.apache.http.legacy",
     ],
+    uses_libs: [
+        "android.test.runner",
+    ],
+    optional_uses_libs: [
+        "org.apache.http.legacy",
+    ],
     sdk_version: "core_platform",
 }
 
@@ -267,5 +273,10 @@
         generate_get_transaction_name: true,
         local_include_dirs: ["aidl"],
     },
+    java_resources: [
+        "res/xml/power_profile_test.xml",
+        "res/xml/power_profile_test_cpu_legacy.xml",
+        "res/xml/power_profile_test_modem.xml",
+    ],
     auto_gen_config: true,
 }
diff --git a/core/tests/coretests/res/xml/power_profile_test.xml b/core/tests/coretests/res/xml/power_profile_test.xml
index 322ae05..7356c9e 100644
--- a/core/tests/coretests/res/xml/power_profile_test.xml
+++ b/core/tests/coretests/res/xml/power_profile_test.xml
@@ -98,4 +98,16 @@
         <value>40</value>
         <value>50</value>
     </array>
-</device>
\ No newline at end of file
+
+    <!-- Idle current for bluetooth in mA.-->
+    <item name="bluetooth.controller.idle">0.02</item>
+
+    <!-- Rx current for bluetooth in mA.-->
+    <item name="bluetooth.controller.rx">3</item>
+
+    <!-- Tx current for bluetooth in mA-->
+    <item name="bluetooth.controller.tx">5</item>
+
+    <!-- Operating voltage for bluetooth in mV.-->
+    <item name="bluetooth.controller.voltage">3300</item>
+</device>
diff --git a/core/tests/coretests/src/android/app/ActivityManagerTest.java b/core/tests/coretests/src/android/app/ActivityManagerTest.java
index d930e4d..3c042ba 100644
--- a/core/tests/coretests/src/android/app/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/ActivityManagerTest.java
@@ -78,6 +78,6 @@
     public void testRestrictionLevel() throws Exception {
         // For the moment mostly want to confirm we don't crash
         assertNotNull(ActivityManager.restrictionLevelToName(
-                ActivityManager.RESTRICTION_LEVEL_HIBERNATION));
+                ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED));
     }
 }
diff --git a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
index 3cb62b9..565e21d 100644
--- a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
@@ -40,6 +40,8 @@
     private static final String LIB_A = "/system/framework/android.hidl.base-V1.0-java.jar";
     // a library installed onto the device which only depends on A
     private static final String LIB_DEP_A = "/system/framework/android.hidl.manager-V1.0-java.jar";
+    // a commonly used, non-BCP, app-facing library installed onto the device
+    private static final String LIB_APACHE_HTTP = "/system/framework/org.apache.http.legacy.jar";
 
     private static SharedLibraryInfo createLib(String zip) {
         return new SharedLibraryInfo(
@@ -137,4 +139,15 @@
 
         loaders.createAndCacheNonBootclasspathSystemClassLoaders(Lists.newArrayList(libB, libA));
     }
+
+    @Test
+    public void testCacheApacheHttpLegacy() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libApacheHttp = createLib(LIB_APACHE_HTTP);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(Lists.newArrayList(libApacheHttp));
+
+        assertNotNull(loaders.getCachedNonBootclasspathSystemLib(
+                LIB_APACHE_HTTP, null, null, null));
+    }
 }
diff --git a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
index a5c8545..5765562 100644
--- a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
+++ b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
@@ -189,12 +189,16 @@
 
     @Test
     @EnableFlags(Flags.FLAG_MODES_API)
-    public void builder_defaultTypeUnknown() {
+    public void builder_defaultsAreSensible() {
         AutomaticZenRule rule = new AutomaticZenRule.Builder("name",
                 Uri.parse("conditionId")).build();
 
         assertThat(rule.getType()).isEqualTo(AutomaticZenRule.TYPE_UNKNOWN);
+        assertThat(rule.getInterruptionFilter()).isEqualTo(
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY);
+        assertThat(rule.isEnabled()).isTrue();
     }
+
     @Test
     @EnableFlags(Flags.FLAG_MODES_API)
     public void validate_builderWithValidType_succeeds() throws Exception {
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java
index 2ce7a7d..a0aff6e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionItemTest.java
@@ -16,7 +16,6 @@
 
 package android.app.servertransaction;
 
-import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static org.junit.Assert.assertEquals;
@@ -29,9 +28,6 @@
 import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.ClientTransactionHandler;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -107,35 +103,6 @@
     }
 
     @Test
-    public void testActivityConfigurationChangeItem_getContextToUpdate() {
-        final ActivityConfigurationChangeItem item = ActivityConfigurationChangeItem
-                .obtain(mActivityToken, mConfiguration, mActivityWindowInfo);
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(mActivity, context);
-    }
-
-    @Test
-    public void testActivityRelaunchItem_getContextToUpdate() {
-        final ActivityRelaunchItem item = ActivityRelaunchItem
-                .obtain(mActivityToken, null /* pendingResults */, null  /* pendingNewIntents */,
-                        0 /* configChange */, mMergedConfiguration, false /* preserveWindow */,
-                        mActivityWindowInfo);
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(mActivity, context);
-    }
-
-    @Test
-    public void testConfigurationChangeItem_getContextToUpdate() {
-        final ConfigurationChangeItem item = ConfigurationChangeItem
-                .obtain(mConfiguration, DEVICE_ID_DEFAULT);
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(ActivityThread.currentApplication(), context);
-    }
-
-    @Test
     public void testDestroyActivityItem_preExecute() {
         final DestroyActivityItem item = DestroyActivityItem
                 .obtain(mActivityToken, false /* finished */);
@@ -166,26 +133,6 @@
     }
 
     @Test
-    public void testLaunchActivityItem_getContextToUpdate() {
-        final LaunchActivityItem item = new TestUtils.LaunchActivityItemBuilder(
-                mActivityToken, new Intent(), new ActivityInfo())
-                .build();
-
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(ActivityThread.currentApplication(), context);
-    }
-
-    @Test
-    public void testMoveToDisplayItem_getContextToUpdate() {
-        final MoveToDisplayItem item = MoveToDisplayItem
-                .obtain(mActivityToken, DEFAULT_DISPLAY, mConfiguration, mActivityWindowInfo);
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(mActivity, context);
-    }
-
-    @Test
     public void testWindowContextInfoChangeItem_execute() {
         final WindowContextInfoChangeItem item = WindowContextInfoChangeItem
                 .obtain(mWindowClientToken, mConfiguration, DEFAULT_DISPLAY);
@@ -196,17 +143,6 @@
     }
 
     @Test
-    public void testWindowContextInfoChangeItem_getContextToUpdate() {
-        doReturn(mWindowContext).when(mHandler).getWindowContext(mWindowClientToken);
-
-        final WindowContextInfoChangeItem item = WindowContextInfoChangeItem
-                .obtain(mWindowClientToken, mConfiguration, DEFAULT_DISPLAY);
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(mWindowContext, context);
-    }
-
-    @Test
     public void testWindowContextWindowRemovalItem_execute() {
         final WindowContextWindowRemovalItem item = WindowContextWindowRemovalItem.obtain(
                 mWindowClientToken);
@@ -220,7 +156,7 @@
         final WindowStateResizeItem item = WindowStateResizeItem.obtain(mWindow, mFrames,
                 true /* reportDraw */, mMergedConfiguration, mInsetsState, true /* forceLayout */,
                 true /* alwaysConsumeSystemBars */, 123 /* displayId */, 321 /* syncSeqId */,
-                true /* dragResizing */, mActivityToken, mActivityWindowInfo);
+                true /* dragResizing */, mActivityWindowInfo);
         item.execute(mHandler, mPendingActions);
 
         verify(mWindow).resized(mFrames,
@@ -228,16 +164,4 @@
                 true /* alwaysConsumeSystemBars */, 123 /* displayId */, 321 /* syncSeqId */,
                 true /* dragResizing */, mActivityWindowInfo);
     }
-
-    @Test
-    public void testWindowStateResizeItem_getContextToUpdate() {
-        final WindowStateResizeItem item = WindowStateResizeItem.obtain(mWindow, mFrames,
-                true /* reportDraw */, mMergedConfiguration, mInsetsState, true /* forceLayout */,
-                true /* alwaysConsumeSystemBars */, 123 /* displayId */, 321 /* syncSeqId */,
-                true /* dragResizing */, mActivityToken, mActivityWindowInfo);
-        final Context context = item.getContextToUpdate(mHandler);
-
-        assertEquals(ActivityThread.currentApplication(), context);
-    }
-
 }
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
index 77d31a5..b6f4429 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
@@ -21,13 +21,24 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.window.flags.Flags.FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG;
+import static com.android.window.flags.Flags.FLAG_WINDOW_TOKEN_CONFIG_THREAD_SAFE;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doNothing;
 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.spy;
 import static org.mockito.Mockito.verify;
 
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerGlobal;
@@ -39,6 +50,7 @@
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.DisplayInfo;
 import android.window.ActivityWindowInfo;
+import android.window.WindowTokenClient;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -49,6 +61,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -76,6 +89,13 @@
     private BiConsumer<IBinder, ActivityWindowInfo> mActivityWindowInfoListener;
     @Mock
     private IBinder mActivityToken;
+    @Mock
+    private Activity mActivity;
+    @Mock
+    private Resources mResources;
+
+    private Configuration mConfiguration;
+
 
     private DisplayManagerGlobal mDisplayManager;
     private Handler mHandler;
@@ -88,7 +108,12 @@
         MockitoAnnotations.initMocks(this);
         mDisplayManager = new DisplayManagerGlobal(mIDisplayManager);
         mHandler = getInstrumentation().getContext().getMainThreadHandler();
-        mController = ClientTransactionListenerController.createInstanceForTesting(mDisplayManager);
+        mController = spy(ClientTransactionListenerController
+                .createInstanceForTesting(mDisplayManager));
+
+        mConfiguration = new Configuration();
+        doReturn(mConfiguration).when(mResources).getConfiguration();
+        doReturn(mResources).when(mActivity).getResources();
     }
 
     @Test
@@ -107,6 +132,43 @@
     }
 
     @Test
+    public void testOnContextConfigurationChanged() {
+        doNothing().when(mController).onDisplayChanged(anyInt());
+        doReturn(123).when(mActivity).getDisplayId();
+
+        // Not trigger onDisplayChanged when there is no change.
+        mController.onContextConfigurationPreChanged(mActivity);
+        mController.onContextConfigurationPostChanged(mActivity);
+
+        verify(mController, never()).onDisplayChanged(anyInt());
+
+        mController.onContextConfigurationPreChanged(mActivity);
+        mConfiguration.windowConfiguration.setMaxBounds(new Rect(0, 0, 100, 200));
+        mController.onContextConfigurationPostChanged(mActivity);
+
+        verify(mController).onDisplayChanged(123);
+    }
+
+    @Test
+    public void testOnContextConfigurationChanged_duringClientTransaction() {
+        doNothing().when(mController).onDisplayChanged(anyInt());
+        doReturn(123).when(mActivity).getDisplayId();
+
+        // Not trigger onDisplayChanged until ClientTransaction finished execution.
+        mController.onClientTransactionStarted();
+
+        mController.onContextConfigurationPreChanged(mActivity);
+        mConfiguration.windowConfiguration.setMaxBounds(new Rect(0, 0, 100, 200));
+        mController.onContextConfigurationPostChanged(mActivity);
+
+        verify(mController, never()).onDisplayChanged(anyInt());
+
+        mController.onClientTransactionFinished();
+
+        verify(mController).onDisplayChanged(123);
+    }
+
+    @Test
     public void testActivityWindowInfoChangedListener() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ACTIVITY_WINDOW_INFO_FLAG);
 
@@ -125,4 +187,38 @@
 
         verify(mActivityWindowInfoListener, never()).accept(any(), any());
     }
+
+    @Test
+    public void testWindowTokenClient_onConfigurationChanged() {
+        mSetFlagsRule.enableFlags(FLAG_WINDOW_TOKEN_CONFIG_THREAD_SAFE);
+
+        doNothing().when(mController).onContextConfigurationPreChanged(any());
+        doNothing().when(mController).onContextConfigurationPostChanged(any());
+
+        final WindowTokenClient windowTokenClient = spy(new WindowTokenClient());
+        final Context context = mock(Context.class);
+        windowTokenClient.attachContext(context);
+
+        doReturn(mController).when(windowTokenClient).getClientTransactionListenerController();
+        doNothing().when(windowTokenClient).onConfigurationChangedInner(any(), any(), anyInt(),
+                anyBoolean());
+
+        // Not trigger when shouldReportConfigChange is false.
+        windowTokenClient.onConfigurationChanged(mConfiguration, 123 /* newDisplayId */,
+                false /* shouldReportConfigChange*/);
+
+        verify(mController, never()).onContextConfigurationPreChanged(any());
+        verify(mController, never()).onContextConfigurationPostChanged(any());
+
+        // Trigger in order when shouldReportConfigChange is true.
+        clearInvocations(windowTokenClient);
+        final InOrder inOrder = inOrder(mController, windowTokenClient);
+        windowTokenClient.onConfigurationChanged(mConfiguration, 123 /* newDisplayId */,
+                true /* shouldReportConfigChange*/);
+
+        inOrder.verify(mController).onContextConfigurationPreChanged(context);
+        inOrder.verify(windowTokenClient).onConfigurationChangedInner(context, mConfiguration,
+                123 /* newDisplayId */, true /* shouldReportConfigChange*/);
+        inOrder.verify(mController).onContextConfigurationPostChanged(context);
+    }
 }
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index a2a5433..c7d5825 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -175,10 +175,12 @@
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(-1f)).isFalse()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(0.85f)).isFalse()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.02f)).isFalse()
+        assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.05f)).isTrue()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.10f)).isTrue()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.15f)).isTrue()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.1499999f))
                 .isTrue()
+        assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.2f)).isTrue()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.5f)).isTrue()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(2f)).isTrue()
         assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(3f)).isTrue()
diff --git a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
index 2323527..e25fdf9 100644
--- a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
@@ -78,7 +78,8 @@
         final int sel = STATEMENT_SELECT;
         assertEquals(sel, getSqlStatementType("SELECT"));
         assertEquals(sel, getSqlStatementType("  SELECT"));
-        assertEquals(sel, getSqlStatementType(" \n SELECT"));
+        assertEquals(sel, getSqlStatementType(" \n\r\f\t SELECT"));
+        assertEquals(sel, getSqlStatementType(" \n\r\f\t SEL"));
 
         final int upd = STATEMENT_UPDATE;
         assertEquals(upd, getSqlStatementType("UPDATE"));
@@ -89,12 +90,21 @@
         assertEquals(ddl, getSqlStatementType("ALTER TABLE t1 ADD COLUMN j int"));
         assertEquals(ddl, getSqlStatementType("CREATE TABLE t1 (i int)"));
 
+        // Verify that the answers are case-insensitive
+        assertEquals(sel, getSqlStatementType("select"));
+        assertEquals(sel, getSqlStatementType("sElect"));
+        assertEquals(sel, getSqlStatementType("sELECT"));
+        assertEquals(sel, getSqlStatementType("seLECT"));
+
         // Short statements, leading comments, and WITH are decoded to "other" in the public API.
         final int othr = STATEMENT_OTHER;
         assertEquals(othr, getSqlStatementType("SE"));
         assertEquals(othr, getSqlStatementType("SE LECT"));
         assertEquals(othr, getSqlStatementType("-- cmt\n SE"));
         assertEquals(othr, getSqlStatementType("WITH"));
+        assertEquals(othr, getSqlStatementType("-"));
+        assertEquals(othr, getSqlStatementType("--"));
+        assertEquals(othr, getSqlStatementType("*/* foo */ SEL"));
 
         // Verify that leading line-comments are skipped.
         assertEquals(sel, getSqlStatementType("-- cmt\n SELECT"));
diff --git a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
index 3a872b5..5bf88da 100644
--- a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
@@ -28,7 +28,9 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -97,7 +99,7 @@
         mLooper = new TestLooper();
         mHandler = new Handler(mLooper.getLooper());
 
-        when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        when(mContext.getMainThreadHandler()).thenReturn(mHandler);
         when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
         when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
         when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
@@ -210,6 +212,39 @@
         verify(mFaceDetectionCallback).onDetectionError(anyInt());
     }
 
+    @Test
+    public void authenticate_onErrorCanceled() throws RemoteException {
+        final FaceManager.AuthenticationCallback authenticationCallback1 = mock(
+                FaceManager.AuthenticationCallback.class);
+        final FaceManager.AuthenticationCallback authenticationCallback2 = mock(
+                FaceManager.AuthenticationCallback.class);
+
+        final ArgumentCaptor<IFaceServiceReceiver> faceServiceReceiverArgumentCaptor =
+                ArgumentCaptor.forClass(IFaceServiceReceiver.class);
+
+        mFaceManager.authenticate(null, new CancellationSignal(),
+                authenticationCallback1, mHandler,
+                new FaceAuthenticateOptions.Builder().build());
+        mFaceManager.authenticate(null, new CancellationSignal(),
+                authenticationCallback2, mHandler,
+                new FaceAuthenticateOptions.Builder().build());
+
+        verify(mService, times(2)).authenticate(any(IBinder.class), eq(0L),
+                faceServiceReceiverArgumentCaptor.capture(), any());
+
+        final List<IFaceServiceReceiver> faceServiceReceivers =
+                faceServiceReceiverArgumentCaptor.getAllValues();
+        faceServiceReceivers.get(0).onError(5 /* error */, 0 /* vendorCode */);
+        mLooper.dispatchAll();
+
+        verify(authenticationCallback1).onAuthenticationError(eq(5), anyString());
+        verify(authenticationCallback2, never()).onAuthenticationError(anyInt(), anyString());
+
+        faceServiceReceivers.get(1).onError(5 /* error */, 0 /* vendorCode */);
+        mLooper.dispatchAll();
+        verify(authenticationCallback2).onAuthenticationError(eq(5), anyString());
+    }
+
     private void initializeProperties() throws RemoteException {
         verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
 
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
index ce7d6a9..c3ea7d3 100644
--- a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
@@ -26,7 +26,9 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -93,6 +95,7 @@
         mHandler = new Handler(mLooper.getLooper());
 
         when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        when(mContext.getMainThreadHandler()).thenReturn(mHandler);
         when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
         when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
         when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
@@ -187,4 +190,38 @@
 
         verify(mFingerprintDetectionCallback).onDetectionError(anyInt());
     }
+
+    @Test
+    public void authenticate_onErrorCanceled() throws RemoteException {
+        final FingerprintManager.AuthenticationCallback authenticationCallback1 = mock(
+                FingerprintManager.AuthenticationCallback.class);
+        final FingerprintManager.AuthenticationCallback authenticationCallback2 = mock(
+                FingerprintManager.AuthenticationCallback.class);
+
+        final ArgumentCaptor<IFingerprintServiceReceiver> fingerprintServiceReceiverArgumentCaptor =
+                ArgumentCaptor.forClass(IFingerprintServiceReceiver.class);
+
+        mFingerprintManager.authenticate(null, new CancellationSignal(),
+                authenticationCallback1, mHandler,
+                new FingerprintAuthenticateOptions.Builder().build());
+        mFingerprintManager.authenticate(null, new CancellationSignal(),
+                authenticationCallback2, mHandler,
+                new FingerprintAuthenticateOptions.Builder().build());
+
+        verify(mService, times(2)).authenticate(any(IBinder.class), eq(0L),
+                fingerprintServiceReceiverArgumentCaptor.capture(), any());
+
+        final List<IFingerprintServiceReceiver> fingerprintServiceReceivers =
+                fingerprintServiceReceiverArgumentCaptor.getAllValues();
+        fingerprintServiceReceivers.get(0).onError(5 /* error */, 0 /* vendorCode */);
+        mLooper.dispatchAll();
+
+        verify(authenticationCallback1).onAuthenticationError(eq(5), anyString());
+        verify(authenticationCallback2, never()).onAuthenticationError(anyInt(), anyString());
+
+        fingerprintServiceReceivers.get(1).onError(5 /* error */, 0 /* vendorCode */);
+        mLooper.dispatchAll();
+
+        verify(authenticationCallback2).onAuthenticationError(eq(5), anyString());
+    }
 }
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index 442394e3..0697c96 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+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.assertThrows;
@@ -24,6 +26,7 @@
 import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Log;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -31,6 +34,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ParcelTest {
@@ -349,6 +354,50 @@
     }
 
     @Test
+    public void testClassCookies() {
+        Parcel p = Parcel.obtain();
+        assertThat(p.hasClassCookie(ParcelTest.class)).isFalse();
+
+        p.setClassCookie(ParcelTest.class, "string_cookie");
+        assertThat(p.hasClassCookie(ParcelTest.class)).isTrue();
+        assertThat(p.getClassCookie(ParcelTest.class)).isEqualTo("string_cookie");
+
+        p.removeClassCookie(ParcelTest.class, "string_cookie");
+        assertThat(p.hasClassCookie(ParcelTest.class)).isFalse();
+        assertThat(p.getClassCookie(ParcelTest.class)).isEqualTo(null);
+
+        p.setClassCookie(ParcelTest.class, "to_be_discarded_cookie");
+        p.recycle();
+        assertThat(p.getClassCookie(ParcelTest.class)).isNull();
+    }
+
+    @Test
+    public void testClassCookies_removeUnexpected() {
+        Parcel p = Parcel.obtain();
+
+        assertLogsWtf(() -> p.removeClassCookie(ParcelTest.class, "not_present"));
+
+        p.setClassCookie(ParcelTest.class, "value");
+
+        assertLogsWtf(() -> p.removeClassCookie(ParcelTest.class, "different"));
+        assertThat(p.getClassCookie(ParcelTest.class)).isNull(); // still removed
+
+        p.recycle();
+    }
+
+    private static void assertLogsWtf(Runnable test) {
+        ArrayList<Log.TerribleFailure> wtfs = new ArrayList<>();
+        Log.TerribleFailureHandler oldHandler = Log.setWtfHandler(
+                (tag, what, system) -> wtfs.add(what));
+        try {
+            test.run();
+        } finally {
+            Log.setWtfHandler(oldHandler);
+        }
+        assertThat(wtfs).hasSize(1);
+    }
+
+    @Test
     @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testHasBinders_AfterWritingBinderToParcel() {
         Binder binder = new Binder();
@@ -360,7 +409,6 @@
         assertTrue(pA.hasBinders());
     }
 
-
     @Test
     @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testHasBindersInRange_AfterWritingBinderToParcel() {
diff --git a/core/tests/coretests/src/android/tracing/OWNERS b/core/tests/coretests/src/android/tracing/OWNERS
new file mode 100644
index 0000000..86a7e88
--- /dev/null
+++ b/core/tests/coretests/src/android/tracing/OWNERS
@@ -0,0 +1 @@
+include platform/development:/tools/winscope/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java
index 030d420..6ae3d65 100644
--- a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java
+++ b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java
@@ -16,14 +16,15 @@
 
 package android.tracing.perfetto;
 
-import static android.internal.perfetto.protos.PerfettoTrace.TestEvent.PAYLOAD;
-import static android.internal.perfetto.protos.PerfettoTrace.TestEvent.TestPayload.SINGLE_INT;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.FOR_TESTING;
+import static android.internal.perfetto.protos.TestEventOuterClass.TestEvent.PAYLOAD;
+import static android.internal.perfetto.protos.TestEventOuterClass.TestEvent.TestPayload.SINGLE_INT;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.FOR_TESTING;
 
 import static java.io.File.createTempFile;
 import static java.nio.file.Files.createTempDirectory;
 
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
+import android.internal.perfetto.protos.TestConfigOuterClass.TestConfig;
 import android.tools.ScenarioBuilder;
 import android.tools.Tag;
 import android.tools.io.TraceType;
@@ -46,6 +47,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import perfetto.protos.PerfettoConfig;
+import perfetto.protos.TracePacketOuterClass;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -56,9 +60,6 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
-import perfetto.protos.PerfettoConfig;
-import perfetto.protos.TracePacketOuterClass;
-
 @RunWith(AndroidJUnit4.class)
 public class DataSourceTest {
     private final File mTracingDirectory = createTempDirectory("temp").toFile();
@@ -328,19 +329,19 @@
         int configDummyIntValue = 0;
         while (configStream.get().nextField() != ProtoInputStream.NO_MORE_FIELDS) {
             if (configStream.get().getFieldNumber()
-                    == (int) PerfettoTrace.DataSourceConfig.FOR_TESTING) {
+                    == (int) DataSourceConfig.FOR_TESTING) {
                 final long forTestingToken = configStream.get()
-                        .start(PerfettoTrace.DataSourceConfig.FOR_TESTING);
+                        .start(DataSourceConfig.FOR_TESTING);
                 while (configStream.get().nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                     if (configStream.get().getFieldNumber()
-                            == (int) PerfettoTrace.TestConfig.DUMMY_FIELDS) {
+                            == (int) TestConfig.DUMMY_FIELDS) {
                         final long dummyFieldsToken = configStream.get()
-                                .start(PerfettoTrace.TestConfig.DUMMY_FIELDS);
+                                .start(TestConfig.DUMMY_FIELDS);
                         while (configStream.get().nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                             if (configStream.get().getFieldNumber()
-                                    == (int) PerfettoTrace.TestConfig.DummyFields.FIELD_INT32) {
+                                    == (int) TestConfig.DummyFields.FIELD_INT32) {
                                 int val = configStream.get().readInt(
-                                        PerfettoTrace.TestConfig.DummyFields.FIELD_INT32);
+                                        TestConfig.DummyFields.FIELD_INT32);
                                 if (val != 0) {
                                     configDummyIntValue = val;
                                     break;
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 97f894f..4fb85c1f 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -25,9 +25,7 @@
 import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
 import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
-import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
 import static android.view.WindowInsets.Type.all;
-import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowInsets.Type.defaultVisible;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
@@ -49,7 +47,6 @@
 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.verify;
@@ -805,48 +802,6 @@
     }
 
     @Test
-    public void testCaptionInsetsStateAssemble() {
-        if (CAPTION_ON_SHELL) {
-            // For this case, the test is covered by WindowContainerInsetsSourceProviderTest, This
-            // test can be removed after the caption is moved to shell completely.
-            return;
-        }
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            final Rect frame = new Rect(0, 0, 100, 300);
-            final int captionBarHeight = 100;
-            final InsetsState state = mController.getState();
-            mController.onFrameChanged(frame);
-            mController.setCaptionInsetsHeight(captionBarHeight);
-            // The caption bar insets height should be the same as the caption bar height.
-            assertEquals(captionBarHeight, state.calculateInsets(frame, captionBar(), false).top);
-            // Test update to remove the caption bar
-            mController.setCaptionInsetsHeight(0);
-            // The caption bar source should not be there at all, because we don't add empty
-            // caption to the state from the server.
-            for (int i = state.sourceSize() - 1; i >= 0; i--) {
-                assertNotEquals(captionBar(), state.sourceAt(i).getType());
-            }
-        });
-    }
-
-    @Test
-    public void testNotifyCaptionInsetsOnlyChange() {
-        if (CAPTION_ON_SHELL) {
-            // For this case, the test is covered by WindowContainerInsetsSourceProviderTest, This
-            // test can be removed after the caption is moved to shell completely.
-            return;
-        }
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            reset(mTestHost);
-            mController.setCaptionInsetsHeight(100);
-            verify(mTestHost).notifyInsetsChanged();
-            reset(mTestHost);
-            mController.setCaptionInsetsHeight(0);
-            verify(mTestHost).notifyInsetsChanged();
-        });
-    }
-
-    @Test
     public void testRequestedState() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             mController.hide(statusBars() | navigationBars());
diff --git a/core/tests/coretests/src/android/view/MotionEventTest.java b/core/tests/coretests/src/android/view/MotionEventTest.java
index c4c983d..bad0485 100644
--- a/core/tests/coretests/src/android/view/MotionEventTest.java
+++ b/core/tests/coretests/src/android/view/MotionEventTest.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 
 import android.graphics.Matrix;
 import android.platform.test.annotations.Presubmit;
@@ -47,21 +48,25 @@
 public class MotionEventTest {
     private static final int ID_SOURCE_MASK = 0x3 << 30;
 
+    private PointerCoords pointerCoords(float x, float y) {
+        final var coords = new PointerCoords();
+        coords.x = x;
+        coords.y = y;
+        return coords;
+    }
+
+    private PointerProperties fingerProperties(int id) {
+        final var props = new PointerProperties();
+        props.id = id;
+        props.toolType = TOOL_TYPE_FINGER;
+        return props;
+    }
+
     @Test
     public void testObtainWithDisplayId() {
         final int pointerCount = 1;
-        PointerProperties[] properties = new PointerProperties[pointerCount];
-        final PointerCoords[] coords = new PointerCoords[pointerCount];
-        for (int i = 0; i < pointerCount; i++) {
-            final PointerCoords c = new PointerCoords();
-            c.x = i * 10;
-            c.y = i * 20;
-            coords[i] = c;
-            final PointerProperties p = new PointerProperties();
-            p.id = i;
-            p.toolType = TOOL_TYPE_FINGER;
-            properties[i] = p;
-        }
+        final var properties = new PointerProperties[]{fingerProperties(0)};
+        final var coords = new PointerCoords[]{pointerCoords(10, 20)};
 
         int displayId = 2;
         MotionEvent motionEvent = MotionEvent.obtain(0, 0, ACTION_DOWN,
@@ -125,18 +130,8 @@
     @Test
     public void testCalculatesCursorPositionForMultiTouchMouseEvents() {
         final int pointerCount = 2;
-        final PointerProperties[] properties = new PointerProperties[pointerCount];
-        final PointerCoords[] coords = new PointerCoords[pointerCount];
-
-        for (int i = 0; i < pointerCount; ++i) {
-            properties[i] = new PointerProperties();
-            properties[i].id = i;
-            properties[i].toolType = MotionEvent.TOOL_TYPE_FINGER;
-
-            coords[i] = new PointerCoords();
-            coords[i].x = 20 + i * 20;
-            coords[i].y = 60 - i * 20;
-        }
+        final var properties = new PointerProperties[]{fingerProperties(0), fingerProperties(1)};
+        final var coords = new PointerCoords[]{pointerCoords(20, 60), pointerCoords(40, 40)};
 
         final MotionEvent event = MotionEvent.obtain(0 /* downTime */,
                 0 /* eventTime */, ACTION_POINTER_DOWN, pointerCount, properties, coords,
@@ -238,4 +233,66 @@
         assertEquals(10, (int) event.getX());
         assertEquals(20, (int) event.getY());
     }
+
+    @Test
+    public void testSplit() {
+        final int pointerCount = 2;
+        final var properties = new PointerProperties[]{fingerProperties(0), fingerProperties(1)};
+        final var coords = new PointerCoords[]{pointerCoords(20, 60), pointerCoords(40, 40)};
+
+        final MotionEvent event = MotionEvent.obtain(0 /* downTime */,
+                0 /* eventTime */, MotionEvent.ACTION_MOVE, pointerCount, properties, coords,
+                0 /* metaState */, 0 /* buttonState */, 1 /* xPrecision */, 1 /* yPrecision */,
+                0 /* deviceId */, 0 /* edgeFlags */, InputDevice.SOURCE_TOUCHSCREEN,
+                0 /* flags */);
+
+        final int idBits = ~0b1 & event.getPointerIdBits();
+        final MotionEvent splitEvent = event.split(idBits);
+        assertEquals(1, splitEvent.getPointerCount());
+        assertEquals(1, splitEvent.getPointerId(0));
+        assertEquals(40, (int) splitEvent.getX());
+        assertEquals(40, (int) splitEvent.getY());
+    }
+
+    @Test
+    public void testSplitFailsWhenNoIdsSpecified() {
+        final int pointerCount = 2;
+        final var properties = new PointerProperties[]{fingerProperties(0), fingerProperties(1)};
+        final var coords = new PointerCoords[]{pointerCoords(20, 60), pointerCoords(40, 40)};
+
+        final MotionEvent event = MotionEvent.obtain(0 /* downTime */,
+                0 /* eventTime */, MotionEvent.ACTION_MOVE, pointerCount, properties, coords,
+                0 /* metaState */, 0 /* buttonState */, 1 /* xPrecision */, 1 /* yPrecision */,
+                0 /* deviceId */, 0 /* edgeFlags */, InputDevice.SOURCE_TOUCHSCREEN,
+                0 /* flags */);
+
+        try {
+            final MotionEvent splitEvent = event.split(0);
+            fail("Splitting event with id bits 0 should throw: " + splitEvent);
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testSplitFailsWhenIdBitsDoNotMatch() {
+        final int pointerCount = 2;
+        final var properties = new PointerProperties[]{fingerProperties(0), fingerProperties(1)};
+        final var coords = new PointerCoords[]{pointerCoords(20, 60), pointerCoords(40, 40)};
+
+        final MotionEvent event = MotionEvent.obtain(0 /* downTime */,
+                0 /* eventTime */, MotionEvent.ACTION_MOVE, pointerCount, properties, coords,
+                0 /* metaState */, 0 /* buttonState */, 1 /* xPrecision */, 1 /* yPrecision */,
+                0 /* deviceId */, 0 /* edgeFlags */, InputDevice.SOURCE_TOUCHSCREEN,
+                0 /* flags */);
+
+        try {
+            final int idBits = 0b100;
+            final MotionEvent splitEvent = event.split(idBits);
+            fail("Splitting event with id bits that do not match any pointers should throw: "
+                    + splitEvent);
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index dcfbf64..4b9aaae 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -19,7 +19,6 @@
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
-import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
 import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY;
 import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY;
 import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
@@ -27,18 +26,23 @@
 import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
+import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
 
 import static junit.framework.Assert.assertEquals;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.annotation.NonNull;
 import android.app.Activity;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.util.DisplayMetrics;
+import android.widget.FrameLayout;
 
 import androidx.test.annotation.UiThreadTest;
 import androidx.test.filters.SmallTest;
@@ -69,6 +73,8 @@
     private Activity mActivity;
     private View mMovingView;
     private ViewRootImpl mViewRoot;
+    private CountDownLatch mAfterDrawLatch;
+    private Throwable mAfterDrawThrowable;
 
     @Before
     public void setUp() throws Throwable {
@@ -82,23 +88,34 @@
             parent = parent.getParent();
         }
         mViewRoot = (ViewRootImpl) parent;
+        mAfterDrawThrowable = null;
     }
 
-    @UiThreadTest
     @Test
     @RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void frameRateChangesWhenContentMoves() {
-        mMovingView.offsetLeftAndRight(100);
-        float frameRate = mViewRoot.getPreferredFrameRate();
-        assertTrue(frameRate > 0);
+    public void frameRateChangesWhenContentMoves() throws Throwable {
+        waitForFrameRateCategoryToSettle();
+        mActivityRule.runOnUiThread(() -> {
+            mMovingView.offsetLeftAndRight(100);
+            runAfterDraw(() -> {
+                if (toolkitFrameRateVelocityMappingReadOnly()) {
+                    float frameRate = mViewRoot.getLastPreferredFrameRate();
+                    assertTrue(frameRate > 0);
+                } else {
+                    assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                            mViewRoot.getLastPreferredFrameRateCategory());
+                }
+            });
+        });
+        waitForAfterDraw();
     }
 
     @UiThreadTest
     @Test
     @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
     public void firstFrameNoMovement() {
-        assertEquals(0f, mViewRoot.getPreferredFrameRate(), 0f);
+        assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
     }
 
     @Test
@@ -141,9 +158,34 @@
         mActivityRule.runOnUiThread(() -> {
             mMovingView.setFrameContentVelocity(1f);
             mMovingView.invalidate();
-            assertEquals(60f, mViewRoot.getPreferredFrameRate(), 0f);
-            assertEquals(FRAME_RATE_COMPATIBILITY_GTE, mViewRoot.getFrameRateCompatibility());
+            runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f));
         });
+        waitForAfterDraw();
+    }
+
+    @Test
+    @RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API,
+            FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY,
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
+    public void velocityWithChildMovement() throws Throwable {
+        FrameLayout frameLayout = new FrameLayout(mActivity);
+        mActivityRule.runOnUiThread(() -> {
+            ViewGroup.LayoutParams fullSize = new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+            mActivity.setContentView(frameLayout, fullSize);
+            if (mMovingView.getParent() instanceof ViewGroup) {
+                ((ViewGroup) mMovingView.getParent()).removeView(mMovingView);
+            }
+            frameLayout.addView(mMovingView, fullSize);
+        });
+        waitForFrameRateCategoryToSettle();
+        mActivityRule.runOnUiThread(() -> {
+            frameLayout.setFrameContentVelocity(1f);
+            mMovingView.offsetTopAndBottom(100);
+            runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f));
+        });
+        waitForAfterDraw();
     }
 
     @Test
@@ -161,23 +203,11 @@
         mActivityRule.runOnUiThread(() -> {
             mMovingView.setFrameContentVelocity(1_000_000_000f);
             mMovingView.invalidate();
-            assertEquals(140f, mViewRoot.getPreferredFrameRate(), 0f);
-            assertEquals(FRAME_RATE_COMPATIBILITY_GTE, mViewRoot.getFrameRateCompatibility());
-        });
-    }
-
-    private void waitForFrameRateCategoryToSettle() throws Throwable {
-        for (int i = 0; i < 5; i++) {
-            final CountDownLatch drawLatch = new CountDownLatch(1);
-
-            // Now that it is small, any invalidation should have a normal category
-            mActivityRule.runOnUiThread(() -> {
-                mMovingView.invalidate();
-                mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch::countDown);
+            runAfterDraw(() -> {
+                assertEquals(140f, mViewRoot.getLastPreferredFrameRate(), 0f);
             });
-
-            assertTrue(drawLatch.await(1, TimeUnit.SECONDS));
-        }
+        });
+        waitForAfterDraw();
     }
 
     @Test
@@ -211,8 +241,10 @@
             mMovingView.invalidate();
             int expected = toolkitFrameRateBySizeReadOnly()
                     ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
-            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
+            runAfterDraw(
+                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     @Test
@@ -245,8 +277,10 @@
             mMovingView.invalidate();
             int expected = toolkitFrameRateBySizeReadOnly()
                     ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
-            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
+            runAfterDraw(
+                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     @Test
@@ -279,8 +313,10 @@
             mMovingView.invalidate();
             int expected = toolkitFrameRateBySizeReadOnly()
                     ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
-            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
+            runAfterDraw(
+                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     @Test
@@ -313,8 +349,10 @@
             mMovingView.invalidate();
             int expected = toolkitFrameRateDefaultNormalReadOnly()
                     ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
+            runAfterDraw(
+                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     @Test
@@ -347,8 +385,10 @@
             mMovingView.invalidate();
             int expected = toolkitFrameRateDefaultNormalReadOnly()
                     ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
+            runAfterDraw(
+                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     @Test
@@ -367,8 +407,75 @@
             mMovingView.invalidate();
             int expected = toolkitFrameRateDefaultNormalReadOnly()
                     ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected,
-                    mViewRoot.getPreferredFrameRateCategory());
+            runAfterDraw(() -> assertEquals(expected,
+                    mViewRoot.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
+    }
+
+    @Test
+    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY,
+            FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY
+    })
+    public void frameRateAndCategory() throws Throwable {
+        mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+        waitForFrameRateCategoryToSettle();
+        mActivityRule.runOnUiThread(() -> {
+            mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_LOW);
+            mMovingView.setFrameContentVelocity(1f);
+            mMovingView.invalidate();
+            runAfterDraw(() -> {
+                assertEquals(FRAME_RATE_CATEGORY_LOW,
+                        mViewRoot.getLastPreferredFrameRateCategory());
+                assertEquals(60f, mViewRoot.getLastPreferredFrameRate());
+            });
+        });
+        waitForAfterDraw();
+    }
+
+    private void runAfterDraw(@NonNull Runnable runnable) {
+        Handler handler = new Handler(Looper.getMainLooper());
+        mAfterDrawLatch = new CountDownLatch(1);
+        ViewTreeObserver.OnDrawListener listener = new ViewTreeObserver.OnDrawListener() {
+            @Override
+            public void onDraw() {
+                handler.postAtFrontOfQueue(() -> {
+                    mMovingView.getViewTreeObserver().removeOnDrawListener(this);
+                    try {
+                        runnable.run();
+                    } catch (Throwable t) {
+                        mAfterDrawThrowable = t;
+                    }
+                    mAfterDrawLatch.countDown();
+                });
+            }
+        };
+        mMovingView.getViewTreeObserver().addOnDrawListener(listener);
+    }
+
+    private void waitForAfterDraw() throws Throwable {
+        assertTrue(mAfterDrawLatch.await(1, TimeUnit.SECONDS));
+        if (mAfterDrawThrowable != null) {
+            throw mAfterDrawThrowable;
+        }
+    }
+
+    private void waitForFrameRateCategoryToSettle() throws Throwable {
+        for (int i = 0; i < 5 || mViewRoot.getIsFrameRateBoosting(); i++) {
+            final CountDownLatch drawLatch = new CountDownLatch(1);
+
+            // Now that it is small, any invalidation should have a normal category
+            ViewTreeObserver.OnDrawListener listener = drawLatch::countDown;
+
+            mActivityRule.runOnUiThread(() -> {
+                mMovingView.invalidate();
+                mMovingView.getViewTreeObserver().addOnDrawListener(listener);
+            });
+
+            assertTrue(drawLatch.await(1, TimeUnit.SECONDS));
+            mActivityRule.runOnUiThread(
+                    () -> mMovingView.getViewTreeObserver().removeOnDrawListener(listener));
+        }
     }
 }
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 90ee36e..20fb6e3 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -22,6 +22,7 @@
 import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY;
 import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY;
 import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
+import static android.view.Surface.FRAME_RATE_CATEGORY_DEFAULT;
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
@@ -43,17 +44,21 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
 import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
+import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
+import android.annotation.NonNull;
 import android.app.Instrumentation;
 import android.app.UiModeManager;
 import android.content.Context;
@@ -107,6 +112,7 @@
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private ViewRootImpl mViewRootImpl;
+    private View mView;
     private volatile boolean mKeyReceived = false;
 
     private static Context sContext;
@@ -116,6 +122,9 @@
     // state after the test completes.
     private static boolean sOriginalTouchMode;
 
+    private CountDownLatch mAfterDrawLatch;
+    private Throwable mAfterDrawThrowable;
+
     @Rule
     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
@@ -148,6 +157,16 @@
 
             setForceDarkSysProp(false);
         });
+        if (mView != null) {
+            sInstrumentation.runOnMainSync(() -> {
+                WindowManager wm = sContext.getSystemService(WindowManager.class);
+                wm.removeView(mView);
+            });
+            mView = null;
+        }
+        mViewRootImpl = null;
+        mAfterDrawLatch = null;
+        mAfterDrawThrowable = null;
     }
 
     @Test
@@ -309,7 +328,7 @@
      */
     @Test
     public void requestScrollCapture_timeout() {
-        final View view = new View(sContext);
+        View view = new View(sContext);
         view.setScrollCaptureCallback(new TestScrollCaptureCallback()); // Does nothing
         sInstrumentation.runOnMainSync(() -> {
             WindowManager.LayoutParams wmlp =
@@ -337,9 +356,9 @@
 
     @Test
     public void whenTouchModeChanges_viewRootIsNotified() throws Exception {
-        View view = new View(sContext);
-        attachViewToWindow(view);
-        ViewTreeObserver viewTreeObserver = view.getRootView().getViewTreeObserver();
+        mView = new View(sContext);
+        attachViewToWindow(mView);
+        ViewTreeObserver viewTreeObserver = mView.getRootView().getViewTreeObserver();
         CountDownLatch latch = new CountDownLatch(1);
         ViewTreeObserver.OnTouchModeChangeListener touchModeListener = (boolean inTouchMode) -> {
             assertWithMessage("addOnTouchModeChangeListener parameter").that(
@@ -349,10 +368,10 @@
         viewTreeObserver.addOnTouchModeChangeListener(touchModeListener);
 
         try {
-            view.requestFocusFromTouch();
+            mView.requestFocusFromTouch();
 
             assertThat(latch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(view.isInTouchMode()).isFalse();
+            assertThat(mView.isInTouchMode()).isFalse();
         } finally {
             viewTreeObserver.removeOnTouchModeChangeListener(touchModeListener);
         }
@@ -360,25 +379,25 @@
 
     @Test
     public void whenDispatchFakeFocus_focusDoesNotPersist() throws Exception {
-        View view = new View(sContext);
-        attachViewToWindow(view);
-        view.clearFocus();
+        mView = new View(sContext);
+        attachViewToWindow(mView);
+        mView.clearFocus();
 
-        assertThat(view.hasWindowFocus()).isFalse();
+        assertThat(mView.hasWindowFocus()).isFalse();
 
-        mViewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
 
         mViewRootImpl.dispatchCompatFakeFocus();
-        assertThat(view.hasWindowFocus()).isFalse();
+        assertThat(mView.hasWindowFocus()).isFalse();
     }
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
     public void whenViewIsAttachedToWindow_getHostToken() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
+        mView = new View(sContext);
+        attachViewToWindow(mView);
 
-        mViewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
 
         assertThat(mViewRootImpl.getInputTransferToken()).isNotEqualTo(null);
     }
@@ -478,13 +497,13 @@
     @UiThreadTest
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_getDefaultValues() {
         ViewRootImpl viewRootImpl = new ViewRootImpl(sContext,
                 sContext.getDisplayNoVerify());
-        assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                FRAME_RATE_CATEGORY_NO_PREFERENCE);
-        assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1);
+        assertEquals(FRAME_RATE_CATEGORY_DEFAULT,
+                viewRootImpl.getLastPreferredFrameRateCategory());
+        assertEquals(0, viewRootImpl.getLastPreferredFrameRate(), 0.1);
     }
 
     /**
@@ -496,29 +515,32 @@
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_BY_SIZE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_visibility_bySize() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
+    public void votePreferredFrameRate_voteFrameRateCategory_visibility_bySize() throws Throwable {
+        mView = new View(sContext);
+        attachViewToWindow(mView);
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
+        ViewTreeObserver.OnDrawListener failIfDrawn = () -> fail("Should not draw invisible views");
         sInstrumentation.runOnMainSync(() -> {
-            view.setVisibility(View.INVISIBLE);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            mView.setVisibility(View.INVISIBLE);
+            mView.invalidate();
+            mView.getViewTreeObserver().addOnDrawListener(failIfDrawn);
         });
         sInstrumentation.waitForIdleSync();
+        mView.getViewTreeObserver().removeOnDrawListener(failIfDrawn);
+
+        sInstrumentation.runOnMainSync(() -> {
+            mView.setVisibility(View.VISIBLE);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
+        });
+        waitForAfterDraw();
+        sInstrumentation.waitForIdleSync();
 
         sInstrumentation.runOnMainSync(() -> {
-            view.setVisibility(View.VISIBLE);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NORMAL);
-        });
-        sInstrumentation.waitForIdleSync();
-
-        sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getIsFrameRateBoosting(), true);
+            assertTrue(mViewRootImpl.getIsFrameRateBoosting());
         });
     }
 
@@ -530,9 +552,9 @@
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_BY_SIZE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_smallSize_bySize() {
-        View view = new View(sContext);
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
+    public void votePreferredFrameRate_voteFrameRateCategory_smallSize_bySize() throws Throwable {
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
         wmlp.width = 1;
@@ -540,15 +562,18 @@
 
         sInstrumentation.runOnMainSync(() -> {
             WindowManager wm = sContext.getSystemService(WindowManager.class);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
         sInstrumentation.runOnMainSync(() -> {
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_LOW,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     /**
@@ -559,9 +584,9 @@
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_BY_SIZE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_normalSize_bySize() {
-        View view = new View(sContext);
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
+    public void votePreferredFrameRate_voteFrameRateCategory_normalSize_bySize() throws Throwable {
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
 
@@ -572,15 +597,18 @@
             display.getMetrics(metrics);
             wmlp.width = (int) (metrics.widthPixels * 0.9);
             wmlp.height = (int) (metrics.heightPixels * 0.9);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
         sInstrumentation.runOnMainSync(() -> {
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     /**
@@ -593,30 +621,56 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_visibility_defaultHigh() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+    public void votePreferredFrameRate_voteFrameRateCategory_visibility_defaultHigh()
+            throws Throwable {
+        mView = new View(sContext);
+        WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+        wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
+
         sInstrumentation.runOnMainSync(() -> {
-            view.setVisibility(View.INVISIBLE);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            DisplayMetrics metrics = sContext.getResources().getDisplayMetrics();
+            wmlp.width = metrics.widthPixels / 2;
+            wmlp.height = metrics.heightPixels / 2;
+            WindowManager wm = sContext.getSystemService(WindowManager.class);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
+        ViewTreeObserver.OnDrawListener failIfDrawn = () -> fail("Draw was not expected!");
+        sInstrumentation.runOnMainSync(() -> {
+            mView.setVisibility(View.INVISIBLE);
+            mView.invalidate();
+            mView.getViewTreeObserver().addOnDrawListener(failIfDrawn);
+        });
+        sInstrumentation.waitForIdleSync();
+        sInstrumentation.runOnMainSync(
+                () -> mView.getViewTreeObserver().removeOnDrawListener(failIfDrawn));
+
+        sInstrumentation.runOnMainSync(() -> {
+            mView.setVisibility(View.VISIBLE);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
+        });
+        waitForAfterDraw();
+        sInstrumentation.waitForIdleSync();
 
         sInstrumentation.runOnMainSync(() -> {
-            view.setVisibility(View.VISIBLE);
-            view.invalidate();
+            assertTrue(mViewRootImpl.getIsFrameRateBoosting());
+        });
+
+        waitForFrameRateCategoryToSettle(mView);
+
+        sInstrumentation.runOnMainSync(() -> {
+            mView.setVisibility(View.VISIBLE);
+            mView.invalidate();
             int expected = toolkitFrameRateDefaultNormalReadOnly()
                     ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected, viewRootImpl.getPreferredFrameRateCategory());
+            runAfterDraw(() -> assertEquals(expected,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
-        sInstrumentation.waitForIdleSync();
-
-        sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getIsFrameRateBoosting(), true);
-        });
+        waitForAfterDraw();
     }
 
     /**
@@ -628,8 +682,9 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_smallSize_defaultHigh() {
-        View view = new View(sContext);
+    public void votePreferredFrameRate_voteFrameRateCategory_smallSize_defaultHigh()
+            throws Throwable {
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
         wmlp.width = 1;
@@ -637,15 +692,20 @@
 
         sInstrumentation.runOnMainSync(() -> {
             WindowManager wm = sContext.getSystemService(WindowManager.class);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
         sInstrumentation.runOnMainSync(() -> {
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
+            mView.invalidate();
+            int expected = toolkitFrameRateBySizeReadOnly() ? FRAME_RATE_CATEGORY_LOW
+                    : FRAME_RATE_CATEGORY_NORMAL;
+            runAfterDraw(() -> assertEquals(expected,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     /**
@@ -657,8 +717,9 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_normalSize_defaultHigh() {
-        View view = new View(sContext);
+    public void votePreferredFrameRate_voteFrameRateCategory_normalSize_defaultHigh()
+            throws Throwable {
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
 
@@ -669,17 +730,20 @@
             display.getMetrics(metrics);
             wmlp.width = (int) (metrics.widthPixels * 0.9);
             wmlp.height = (int) (metrics.heightPixels * 0.9);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
         sInstrumentation.runOnMainSync(() -> {
-            view.invalidate();
+            mView.invalidate();
             int expected = toolkitFrameRateDefaultNormalReadOnly()
                     ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected, viewRootImpl.getPreferredFrameRateCategory());
+            runAfterDraw(() -> assertEquals(expected,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     /**
@@ -688,41 +752,41 @@
      */
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_voteFrameRateCategory_aggregate() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mView = new View(sContext);
+        attachViewToWindow(mView);
+        mViewRootImpl = mView.getViewRootImpl();
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            assertEquals(FRAME_RATE_CATEGORY_DEFAULT,
+                    mViewRootImpl.getPreferredFrameRateCategory());
         });
 
         // reset the frame rate category counts
         for (int i = 0; i < 5; i++) {
             sInstrumentation.runOnMainSync(() -> {
-                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
-                view.invalidate();
+                mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                mView.invalidate();
             });
             sInstrumentation.waitForIdleSync();
         }
 
         sInstrumentation.runOnMainSync(() -> {
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_HIGH_HINT);
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_LOW, mViewRootImpl.getPreferredFrameRateCategory());
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_NORMAL, mViewRootImpl.getPreferredFrameRateCategory());
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_HIGH_HINT,
+                    mViewRootImpl.getPreferredFrameRateCategory());
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
+            mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
+            assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
         });
     }
 
@@ -734,55 +798,67 @@
      */
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_voteFrameRate_aggregate() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mView = new View(sContext);
+        attachViewToWindow(mView);
+        mViewRootImpl = mView.getViewRootImpl();
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
+            assertEquals(0, mViewRootImpl.getPreferredFrameRate(), 0.1);
+            assertEquals(mViewRootImpl.getFrameRateCompatibility(),
                     FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-            viewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_GTE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_GTE);
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-            viewRootImpl.votePreferredFrameRate(30, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 30, 0.1);
+            assertFalse(mViewRootImpl.isFrameRateConflicted());
+            mViewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_GTE);
+            if (toolkitFrameRateVelocityMappingReadOnly()) {
+                assertEquals(24, mViewRootImpl.getPreferredFrameRate(), 0.1);
+                assertEquals(FRAME_RATE_COMPATIBILITY_GTE,
+                        mViewRootImpl.getFrameRateCompatibility());
+                assertFalse(mViewRootImpl.isFrameRateConflicted());
+            } else {
+                assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                        mViewRootImpl.getPreferredFrameRateCategory());
+            }
+            mViewRootImpl.votePreferredFrameRate(30, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
+            assertEquals(30, mViewRootImpl.getPreferredFrameRate(), 0.1);
             // If there is a conflict, then set compatibility to
             // FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            // Should be true since there is a conflict between 24 and 30.
-            assertEquals(viewRootImpl.isFrameRateConflicted(), true);
-            view.invalidate();
+            assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    mViewRootImpl.getFrameRateCompatibility());
+            if (toolkitFrameRateVelocityMappingReadOnly()) {
+                // Should be true since there is a conflict between 24 and 30.
+                assertTrue(mViewRootImpl.isFrameRateConflicted());
+            }
+
+            mView.invalidate();
         });
         sInstrumentation.waitForIdleSync();
 
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-            viewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 60, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_GTE);
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-            viewRootImpl.votePreferredFrameRate(120, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 120, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
+            assertFalse(mViewRootImpl.isFrameRateConflicted());
+            mViewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE);
+            if (toolkitFrameRateVelocityMappingReadOnly()) {
+                assertEquals(60, mViewRootImpl.getPreferredFrameRate(), 0.1);
+                assertEquals(FRAME_RATE_COMPATIBILITY_GTE,
+                        mViewRootImpl.getFrameRateCompatibility());
+            } else {
+                assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                        mViewRootImpl.getPreferredFrameRateCategory());
+            }
+            assertFalse(mViewRootImpl.isFrameRateConflicted());
+            mViewRootImpl.votePreferredFrameRate(120, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
+            assertEquals(120, mViewRootImpl.getPreferredFrameRate(), 0.1);
+            assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    mViewRootImpl.getFrameRateCompatibility());
             // Should be false since 60 is a divisor of 120.
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-            viewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 120, 0.1);
+            assertFalse(mViewRootImpl.isFrameRateConflicted());
+            mViewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE);
+            assertEquals(120, mViewRootImpl.getPreferredFrameRate(), 0.1);
             // compatibility should be remained the same (FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
             // since the frame rate 60 is smaller than 120.
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
+            assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    mViewRootImpl.getFrameRateCompatibility());
             // Should be false since 60 is a divisor of 120.
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-
+            assertFalse(mViewRootImpl.isFrameRateConflicted());
         });
     }
 
@@ -795,37 +871,49 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRate_category() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
+    public void votePreferredFrameRate_voteFrameRate_category() throws Throwable {
+        mView = new View(sContext);
+        attachViewToWindow(mView);
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            assertEquals(FRAME_RATE_CATEGORY_DEFAULT,
+                    mViewRootImpl.getPreferredFrameRateCategory());
         });
 
         // reset the frame rate category counts
         for (int i = 0; i < 5; i++) {
             sInstrumentation.runOnMainSync(() -> {
-                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
-                view.invalidate();
+                mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                mView.invalidate();
             });
             sInstrumentation.waitForIdleSync();
         }
 
+        waitForFrameRateCategoryToSettle(mView);
+
         sInstrumentation.runOnMainSync(() -> {
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_LOW);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NORMAL);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_HIGH);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_LOW);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_LOW,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
+        sInstrumentation.runOnMainSync(() -> {
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
+        });
+        waitForAfterDraw();
+        sInstrumentation.runOnMainSync(() -> {
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_HIGH);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
+        });
+        waitForAfterDraw();
     }
 
     /**
@@ -837,8 +925,8 @@
             FLAG_VIEW_VELOCITY_API,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateCategory_velocityToHigh() {
-        View view = new View(sContext);
+    public void votePreferredFrameRate_voteFrameRateCategory_velocityToHigh() throws Throwable {
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
         wmlp.width = 1;
@@ -846,21 +934,32 @@
 
         sInstrumentation.runOnMainSync(() -> {
             WindowManager wm = sContext.getSystemService(WindowManager.class);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
 
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1);
-            view.setFrameContentVelocity(100);
-            view.invalidate();
-            assertTrue(viewRootImpl.getPreferredFrameRate() > 0);
+            assertEquals(0, mViewRootImpl.getPreferredFrameRate(), 0.1);
+            mView.setFrameContentVelocity(100);
+            mView.invalidate();
+            runAfterDraw(() -> {
+                if (toolkitFrameRateVelocityMappingReadOnly()) {
+                    int expected = toolkitFrameRateBySizeReadOnly()
+                            ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
+                    assertEquals(expected, mViewRootImpl.getLastPreferredFrameRateCategory());
+                    assertTrue(mViewRootImpl.getLastPreferredFrameRate() >= 60f);
+                } else {
+                    assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                            mViewRootImpl.getLastPreferredFrameRateCategory());
+                    assertEquals(0, mViewRootImpl.getLastPreferredFrameRate(), 0.1);
+                }
+            });
         });
+        waitForAfterDraw();
         sInstrumentation.waitForIdleSync();
-        assertEquals(viewRootImpl.getLastPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
-        assertEquals(viewRootImpl.getLastPreferredFrameRate(), 0 , 0.1);
     }
 
     /**
@@ -868,9 +967,9 @@
      */
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_insetsAnimation() {
-        View view = new View(sContext);
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
 
@@ -881,21 +980,21 @@
             display.getMetrics(metrics);
             wmlp.width = (int) (metrics.widthPixels * 0.9);
             wmlp.height = (int) (metrics.heightPixels * 0.9);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        ViewRootImpl viewRootImpl = mView.getViewRootImpl();
         sInstrumentation.runOnMainSync(() -> {
-            view.invalidate();
+            mView.invalidate();
             viewRootImpl.notifyInsetsAnimationRunningStateChanged(true);
-            view.invalidate();
+            mView.invalidate();
         });
         sInstrumentation.waitForIdleSync();
 
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getLastPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_HIGH);
+            assertEquals(FRAME_RATE_CATEGORY_HIGH,
+                    viewRootImpl.getLastPreferredFrameRateCategory());
         });
     }
 
@@ -905,17 +1004,17 @@
      */
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_frameRateBoostOnTouch() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
+        mView = new View(sContext);
+        attachViewToWindow(mView);
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        ViewRootImpl viewRootImpl = mView.getViewRootImpl();
         final WindowManager.LayoutParams attrs = viewRootImpl.mWindowAttributes;
-        assertEquals(attrs.getFrameRateBoostOnTouchEnabled(), true);
-        assertEquals(viewRootImpl.getFrameRateBoostOnTouchEnabled(),
-                attrs.getFrameRateBoostOnTouchEnabled());
+        assertTrue(attrs.getFrameRateBoostOnTouchEnabled());
+        assertEquals(attrs.getFrameRateBoostOnTouchEnabled(),
+                viewRootImpl.getFrameRateBoostOnTouchEnabled());
 
         sInstrumentation.runOnMainSync(() -> {
             attrs.setFrameRateBoostOnTouchEnabled(false);
@@ -925,9 +1024,9 @@
 
         sInstrumentation.runOnMainSync(() -> {
             final WindowManager.LayoutParams newAttrs = viewRootImpl.mWindowAttributes;
-            assertEquals(newAttrs.getFrameRateBoostOnTouchEnabled(), false);
-            assertEquals(viewRootImpl.getFrameRateBoostOnTouchEnabled(),
-                    newAttrs.getFrameRateBoostOnTouchEnabled());
+            assertFalse(newAttrs.getFrameRateBoostOnTouchEnabled());
+            assertEquals(newAttrs.getFrameRateBoostOnTouchEnabled(),
+                    viewRootImpl.getFrameRateBoostOnTouchEnabled());
         });
     }
 
@@ -938,37 +1037,37 @@
      */
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_voteFrameRateTimeOut() throws InterruptedException {
         final long delay = 200L;
 
-        View view = new View(sContext);
-        attachViewToWindow(view);
+        mView = new View(sContext);
+        attachViewToWindow(mView);
         sInstrumentation.waitForIdleSync();
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        ViewRootImpl viewRootImpl = mView.getViewRootImpl();
 
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
+            assertEquals(0, viewRootImpl.getPreferredFrameRate(), 0.1);
+            assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    viewRootImpl.getFrameRateCompatibility());
+            assertFalse(viewRootImpl.isFrameRateConflicted());
             viewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRate(), 24, 0.1);
-            assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-            assertEquals(viewRootImpl.isFrameRateConflicted(), false);
+            assertEquals(24, viewRootImpl.getPreferredFrameRate(), 0.1);
+            assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    viewRootImpl.getFrameRateCompatibility());
+            assertFalse(viewRootImpl.isFrameRateConflicted());
+            mView.invalidate();
+            assertEquals(24, viewRootImpl.getPreferredFrameRate(), 0.1);
+            assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    viewRootImpl.getFrameRateCompatibility());
+            assertFalse(viewRootImpl.isFrameRateConflicted());
         });
 
         Thread.sleep(delay);
-        assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1);
-        assertEquals(viewRootImpl.getFrameRateCompatibility(),
-                FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
-        assertEquals(viewRootImpl.isFrameRateConflicted(), false);
+        assertEquals(0, viewRootImpl.getPreferredFrameRate(), 0.1);
+        assertEquals(FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                viewRootImpl.getFrameRateCompatibility());
+        assertFalse(viewRootImpl.isFrameRateConflicted());
     }
 
     /**
@@ -978,38 +1077,45 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_voteFrameRateOnly() {
-        View view = new View(sContext);
+    public void votePreferredFrameRate_voteFrameRateOnly() throws Throwable {
+        mView = new View(sContext);
         float frameRate = 20;
-        attachViewToWindow(view);
+        attachViewToWindow(mView);
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
         sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            assertEquals(FRAME_RATE_CATEGORY_DEFAULT,
+                    mViewRootImpl.getPreferredFrameRateCategory());
 
-            view.setRequestedFrameRate(frameRate);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
-            assertEquals(viewRootImpl.getPreferredFrameRate(), frameRate, 0.1);
+            mView.setRequestedFrameRate(frameRate);
+            mView.invalidate();
+            runAfterDraw(() -> {
+                int expected = toolkitFrameRateDefaultNormalReadOnly()
+                        ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
+                assertEquals(expected, mViewRootImpl.getLastPreferredFrameRateCategory());
+                assertEquals(frameRate, mViewRootImpl.getLastPreferredFrameRate(), 0.1);
+            });
         });
+        waitForAfterDraw();
 
         // reset the frame rate category counts
         for (int i = 0; i < 5; i++) {
             sInstrumentation.runOnMainSync(() -> {
-                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
-                view.invalidate();
+                mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                mView.invalidate();
             });
             sInstrumentation.waitForIdleSync();
         }
 
         sInstrumentation.runOnMainSync(() -> {
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_LOW);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_LOW);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_LOW,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     /**
@@ -1022,10 +1128,10 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_infrequentLayer_defaultHigh() throws InterruptedException {
+    public void votePreferredFrameRate_infrequentLayer_defaultHigh() throws Throwable {
         final long delay = 200L;
 
-        View view = new View(sContext);
+        mView = new View(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
 
@@ -1036,26 +1142,29 @@
             display.getMetrics(metrics);
             wmlp.width = (int) (metrics.widthPixels * 0.9);
             wmlp.height = (int) (metrics.heightPixels * 0.9);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
+        waitForFrameRateCategoryToSettle(mView);
 
         // In transition from frequent update to infrequent update
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
-            view.invalidate();
+            mView.invalidate();
             int expected = toolkitFrameRateDefaultNormalReadOnly()
                     ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected, viewRootImpl.getPreferredFrameRateCategory());
+            runAfterDraw(() -> assertEquals(expected,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
 
         // reset the frame rate category counts
         for (int i = 0; i < 5; i++) {
             sInstrumentation.runOnMainSync(() -> {
-                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
-                view.invalidate();
+                mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                mView.invalidate();
             });
             sInstrumentation.waitForIdleSync();
         }
@@ -1063,26 +1172,32 @@
         // In transition from frequent update to infrequent update
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            mView.invalidate();
+            runAfterDraw(() -> {
+                assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
+                        mViewRootImpl.getLastPreferredFrameRateCategory());
+            });
         });
+        waitForAfterDraw();
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
 
         // Infrequent update
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     /**
@@ -1090,17 +1205,17 @@
      */
     @Test
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
-            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY})
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
     public void votePreferredFrameRate_isFrameRatePowerSavingsBalanced() {
-        View view = new View(sContext);
-        attachViewToWindow(view);
+        mView = new View(sContext);
+        attachViewToWindow(mView);
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRoot = view.getViewRootImpl();
+        ViewRootImpl viewRoot = mView.getViewRootImpl();
         final WindowManager.LayoutParams attrs = viewRoot.mWindowAttributes;
-        assertEquals(attrs.isFrameRatePowerSavingsBalanced(), true);
-        assertEquals(viewRoot.isFrameRatePowerSavingsBalanced(),
-                attrs.isFrameRatePowerSavingsBalanced());
+        assertTrue(attrs.isFrameRatePowerSavingsBalanced());
+        assertEquals(attrs.isFrameRatePowerSavingsBalanced(),
+                viewRoot.isFrameRatePowerSavingsBalanced());
 
         sInstrumentation.runOnMainSync(() -> {
             attrs.setFrameRatePowerSavingsBalanced(false);
@@ -1110,9 +1225,9 @@
 
         sInstrumentation.runOnMainSync(() -> {
             final WindowManager.LayoutParams newAttrs = viewRoot.mWindowAttributes;
-            assertEquals(newAttrs.isFrameRatePowerSavingsBalanced(), false);
-            assertEquals(viewRoot.isFrameRatePowerSavingsBalanced(),
-                    newAttrs.isFrameRatePowerSavingsBalanced());
+            assertFalse(newAttrs.isFrameRatePowerSavingsBalanced());
+            assertEquals(newAttrs.isFrameRatePowerSavingsBalanced(),
+                    viewRoot.isFrameRatePowerSavingsBalanced());
         });
     }
 
@@ -1125,10 +1240,10 @@
     @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
             FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
-    public void votePreferredFrameRate_applyTextureViewHeuristic() throws InterruptedException {
+    public void votePreferredFrameRate_applyTextureViewHeuristic() throws Throwable {
         final long delay = 30L;
 
-        TextureView view = new TextureView(sContext);
+        mView = new TextureView(sContext);
         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
 
@@ -1139,38 +1254,32 @@
             display.getMetrics(metrics);
             wmlp.width = (int) (metrics.widthPixels * 0.9);
             wmlp.height = (int) (metrics.heightPixels * 0.9);
-            wm.addView(view, wmlp);
+            wm.addView(mView, wmlp);
         });
         sInstrumentation.waitForIdleSync();
 
-        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        mViewRootImpl = mView.getViewRootImpl();
 
-        sInstrumentation.runOnMainSync(() -> {
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
-            view.invalidate();
-            int expected = toolkitFrameRateDefaultNormalReadOnly()
-                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
-            assertEquals(expected, viewRootImpl.getPreferredFrameRateCategory());
-        });
+        waitForFrameRateCategoryToSettle(mView);
 
          // reset the frame rate category counts
         for (int i = 0; i < 5; i++) {
             Thread.sleep(delay);
             sInstrumentation.runOnMainSync(() -> {
-                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
-                view.invalidate();
+                mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+                mView.invalidate();
             });
             sInstrumentation.waitForIdleSync();
         }
 
         Thread.sleep(delay);
         sInstrumentation.runOnMainSync(() -> {
-            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
-            view.invalidate();
-            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
-                    FRAME_RATE_CATEGORY_NORMAL);
+            mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
+            mView.invalidate();
+            runAfterDraw(() -> assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+                    mViewRootImpl.getLastPreferredFrameRateCategory()));
         });
+        waitForAfterDraw();
     }
 
     @Test
@@ -1287,6 +1396,7 @@
      */
     private void checkKeyEvent(Runnable setup, boolean shouldReceiveKey) {
         final KeyView view = new KeyView(sContext);
+        mView = view;
 
         attachViewToWindow(view);
 
@@ -1300,7 +1410,7 @@
             mViewRootImpl.dispatchInputEvent(event);
         });
         sInstrumentation.waitForIdleSync();
-        assertEquals(mKeyReceived, shouldReceiveKey);
+        assertEquals(shouldReceiveKey, mKeyReceived);
     }
 
     private void attachViewToWindow(View view) {
@@ -1313,4 +1423,48 @@
         });
         sInstrumentation.waitForIdleSync();
     }
+
+    private void runAfterDraw(@NonNull Runnable runnable) {
+        mAfterDrawLatch = new CountDownLatch(1);
+        ViewTreeObserver.OnDrawListener listener = new ViewTreeObserver.OnDrawListener() {
+            @Override
+            public void onDraw() {
+                mView.getHandler().postAtFrontOfQueue(() -> {
+                    mView.getViewTreeObserver().removeOnDrawListener(this);
+                    try {
+                        runnable.run();
+                    } catch (Throwable t) {
+                        mAfterDrawThrowable = t;
+                    }
+                    mAfterDrawLatch.countDown();
+                });
+            }
+        };
+        mView.getViewTreeObserver().addOnDrawListener(listener);
+    }
+
+    private void waitForAfterDraw() throws Throwable {
+        assertTrue(mAfterDrawLatch.await(1, TimeUnit.SECONDS));
+        if (mAfterDrawThrowable != null) {
+            throw mAfterDrawThrowable;
+        }
+    }
+
+    private void waitForFrameRateCategoryToSettle(View view) throws Throwable {
+        for (int i = 0; i < 5 || mViewRootImpl.getIsFrameRateBoosting(); i++) {
+            final CountDownLatch drawLatch = new CountDownLatch(1);
+
+            // Now that it is small, any invalidation should have a normal category
+            ViewTreeObserver.OnDrawListener listener = drawLatch::countDown;
+
+            sInstrumentation.runOnMainSync(() -> {
+                view.invalidate();
+                view.getViewTreeObserver().addOnDrawListener(listener);
+            });
+
+            assertTrue(drawLatch.await(1, TimeUnit.SECONDS));
+            sInstrumentation.runOnMainSync(
+                    () -> view.getViewTreeObserver().removeOnDrawListener(listener));
+        }
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index 365f348..d560ef2 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -64,6 +64,9 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Vibrator;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech;
 import android.speech.tts.Voice;
@@ -71,6 +74,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.Flags;
 import android.view.accessibility.IAccessibilityManager;
 import android.widget.Toast;
 
@@ -83,9 +87,11 @@
 
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
@@ -93,11 +99,14 @@
 import java.lang.reflect.Field;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 @RunWith(AndroidJUnit4.class)
 public class AccessibilityShortcutControllerTest {
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     private static final String SERVICE_NAME_STRING = "fake.package/fake.service.name";
     private static final CharSequence PACKAGE_NAME_STRING = "Service name";
     private static final String SERVICE_NAME_SUMMARY = "Summary";
@@ -126,6 +135,7 @@
     private @Mock TextToSpeech mTextToSpeech;
     private @Mock Voice mVoice;
     private @Mock Ringtone mRingtone;
+    private @Captor ArgumentCaptor<List<String>> mListCaptor;
 
     private MockContentResolver mContentResolver;
     private WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
@@ -410,6 +420,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void testClickingDisableButtonInDialog_shouldClearShortcutId() throws Exception {
         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
         configureValidShortcutService();
@@ -423,6 +434,29 @@
                 captor.capture());
         captor.getValue().onClick(null, DialogInterface.BUTTON_POSITIVE);
 
+        verify(mAccessibilityManagerService).enableShortcutsForTargets(
+                eq(false), eq(HARDWARE), mListCaptor.capture(), anyInt());
+        assertThat(mListCaptor.getValue()).containsExactly(SERVICE_NAME_STRING);
+        assertThat(Settings.Secure.getInt(
+                mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN)).isEqualTo(
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN);
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
+    public void testClickingDisableButtonInDialog_shouldClearShortcutId_old() throws Exception {
+        configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
+        configureValidShortcutService();
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN);
+        getController().performAccessibilityShortcut();
+
+        ArgumentCaptor<DialogInterface.OnClickListener> captor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder).setPositiveButton(eq(R.string.accessibility_shortcut_off),
+                captor.capture());
+        captor.getValue().onClick(null, DialogInterface.BUTTON_POSITIVE);
+
         assertThat(
                 Settings.Secure.getString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)
         ).isEmpty();
@@ -432,6 +466,8 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_UPDATE_ALWAYS_ON_A11Y_SERVICE)
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void turnOffVolumeShortcutForAlwaysOnA11yService_shouldTurnOffA11yService()
             throws Exception {
         configureApplicationTargetSdkVersion(Build.VERSION_CODES.R);
@@ -443,6 +479,8 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_UPDATE_ALWAYS_ON_A11Y_SERVICE)
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void turnOffVolumeShortcutForAlwaysOnA11yService_hasOtherTypesShortcut_shouldNotTurnOffA11yService()
             throws Exception {
         configureApplicationTargetSdkVersion(Build.VERSION_CODES.R);
@@ -489,6 +527,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void testTurnOnDefaultA11yServiceInDialog_defaultServiceShortcutTurnsOn()
             throws Exception {
         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
@@ -503,15 +542,39 @@
                 captor.capture());
         captor.getValue().onClick(null, DialogInterface.BUTTON_NEGATIVE);
 
-        assertThat(
-                Settings.Secure.getString(mContentResolver,
-                        ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)).isEqualTo(SERVICE_NAME_STRING);
+        verify(mAccessibilityManagerService).enableShortcutsForTargets(
+                eq(true), eq(HARDWARE), mListCaptor.capture(), anyInt());
+        assertThat(mListCaptor.getValue()).containsExactly(SERVICE_NAME_STRING);
         assertThat(Settings.Secure.getInt(
                 mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN)).isEqualTo(
                 AccessibilityShortcutController.DialogStatus.SHOWN);
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
+    public void testTurnOnDefaultA11yServiceInDialog_defaultServiceShortcutTurnsOn_old()
+            throws Exception {
+        configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
+        configureDefaultAccessibilityService();
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN);
+        getController().performAccessibilityShortcut();
+
+        ArgumentCaptor<DialogInterface.OnClickListener> captor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder).setNegativeButton(eq(R.string.accessibility_shortcut_on),
+                captor.capture());
+        captor.getValue().onClick(null, DialogInterface.BUTTON_NEGATIVE);
+
+        assertThat(Settings.Secure.getString(mContentResolver,
+                ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)).isEqualTo(SERVICE_NAME_STRING);
+        assertThat(Settings.Secure.getInt(
+                mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN)).isEqualTo(
+                AccessibilityShortcutController.DialogStatus.SHOWN);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void testTurnOffDefaultA11yServiceInDialog_defaultServiceShortcutTurnsOff()
             throws Exception {
         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
@@ -526,9 +589,32 @@
                 captor.capture());
         captor.getValue().onClick(null, DialogInterface.BUTTON_POSITIVE);
 
-        assertThat(
-                Settings.Secure.getString(mContentResolver,
-                        ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)).isEmpty();
+        verify(mAccessibilityManagerService).enableShortcutsForTargets(
+                eq(false), eq(HARDWARE), mListCaptor.capture(), anyInt());
+        assertThat(mListCaptor.getValue()).isEmpty();
+        assertThat(Settings.Secure.getInt(
+                mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN)).isEqualTo(
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN);
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
+    public void testTurnOffDefaultA11yServiceInDialog_defaultServiceShortcutTurnsOff_old()
+            throws Exception {
+        configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
+        configureDefaultAccessibilityService();
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN);
+        getController().performAccessibilityShortcut();
+
+        ArgumentCaptor<DialogInterface.OnClickListener> captor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder).setPositiveButton(eq(R.string.accessibility_shortcut_off),
+                captor.capture());
+        captor.getValue().onClick(null, DialogInterface.BUTTON_POSITIVE);
+
+        assertThat(Settings.Secure.getString(mContentResolver,
+                ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)).isEmpty();
         assertThat(Settings.Secure.getInt(
                 mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN)).isEqualTo(
                 AccessibilityShortcutController.DialogStatus.NOT_SHOWN);
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java b/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java
index 2ea044c..9cac312 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTargetTest.java
@@ -19,8 +19,10 @@
 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.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
@@ -31,8 +33,12 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.Flags;
 import android.view.accessibility.IAccessibilityManager;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -47,10 +53,13 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.util.Collections;
+import java.util.List;
 
 /**
  * Unit Tests for
@@ -59,9 +68,13 @@
 @RunWith(AndroidJUnit4.class)
 public class InvisibleToggleAccessibilityServiceTargetTest {
     @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    @Rule
     public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
     @Mock
     private IAccessibilityManager mAccessibilityManagerService;
+    @Captor
+    private ArgumentCaptor<List<String>> mListCaptor;
 
     private static final String ALWAYS_ON_SERVICE_PACKAGE_LABEL = "always on a11y service";
     private static final String ALWAYS_ON_SERVICE_COMPONENT_NAME =
@@ -104,6 +117,32 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
+    public void onCheckedChanged_true_callA11yManagerToUpdateShortcuts() throws Exception {
+        mSut.onCheckedChanged(true);
+
+        verify(mAccessibilityManagerService).enableShortcutsForTargets(
+                eq(true),
+                eq(ShortcutConstants.UserShortcutType.HARDWARE),
+                mListCaptor.capture(),
+                anyInt());
+        assertThat(mListCaptor.getValue()).containsExactly(ALWAYS_ON_SERVICE_COMPONENT_NAME);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
+    public void onCheckedChanged_false_callA11yManagerToUpdateShortcuts() throws Exception {
+        mSut.onCheckedChanged(false);
+        verify(mAccessibilityManagerService).enableShortcutsForTargets(
+                eq(false),
+                eq(ShortcutConstants.UserShortcutType.HARDWARE),
+                mListCaptor.capture(),
+                anyInt());
+        assertThat(mListCaptor.getValue()).containsExactly(ALWAYS_ON_SERVICE_COMPONENT_NAME);
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void onCheckedChanged_turnOnShortcut_hasOtherShortcut_serviceKeepsOn() {
         enableA11yService(/* enable= */ true);
         addShortcutForA11yService(
@@ -116,6 +155,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void onCheckedChanged_turnOnShortcut_noOtherShortcut_shouldTurnOnService() {
         enableA11yService(/* enable= */ false);
         addShortcutForA11yService(
@@ -128,6 +168,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void onCheckedChanged_turnOffShortcut_hasOtherShortcut_serviceKeepsOn() {
         enableA11yService(/* enable= */ true);
         addShortcutForA11yService(
@@ -140,6 +181,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_MIGRATE_ENABLE_SHORTCUTS)
     public void onCheckedChanged_turnOffShortcut_noOtherShortcut_shouldTurnOffService() {
         enableA11yService(/* enable= */ true);
         addShortcutForA11yService(
diff --git a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
index 533b799..fa5d72a 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
@@ -55,6 +55,21 @@
     }
 
     @Test
+    public void copyStatesFrom() {
+        LongArrayMultiStateCounter source = new LongArrayMultiStateCounter(2, 1);
+        updateValue(source, new long[]{0}, 1000);
+        source.setState(0, 1000);
+        source.setState(1, 2000);
+
+        LongArrayMultiStateCounter target = new LongArrayMultiStateCounter(2, 1);
+        target.copyStatesFrom(source);
+        updateValue(target, new long[]{1000}, 5000);
+
+        assertCounts(target, 0, new long[]{250});
+        assertCounts(target, 1, new long[]{750});
+    }
+
+    @Test
     public void setValue() {
         LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4);
 
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
index c0f0714..951fa98 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
@@ -21,20 +21,21 @@
 import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
 import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;
 
-import static org.junit.Assert.fail;
+import static com.google.common.truth.Truth.assertThat;
 
-import android.annotation.XmlRes;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.annotations.DisabledOnRavenwood;
 import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Xml;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.frameworks.coretests.R;
 import com.android.internal.power.ModemPowerProfile;
 import com.android.internal.util.XmlUtils;
 
@@ -43,6 +44,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.StringReader;
 
 /*
  * Keep this file in sync with frameworks/base/core/res/res/xml/power_profile_test.xml and
@@ -53,7 +59,6 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-@IgnoreUnderRavenwood(blockedBy = PowerProfile.class)
 public class PowerProfileTest {
     @Rule
     public final RavenwoodRule mRavenwood = new RavenwoodRule();
@@ -62,17 +67,15 @@
     static final String ATTR_NAME = "name";
 
     private PowerProfile mProfile;
-    private Context mContext;
 
     @Before
     public void setUp() {
-        mContext = InstrumentationRegistry.getContext();
-        mProfile = new PowerProfile(mContext);
+        mProfile = new PowerProfile();
     }
 
     @Test
     public void testPowerProfile() {
-        mProfile.forceInitForTesting(mContext, R.xml.power_profile_test);
+        mProfile.initForTesting(resolveParser("power_profile_test"));
 
         assertEquals(5.0, mProfile.getAveragePower(PowerProfile.POWER_CPU_SUSPEND));
         assertEquals(1.11, mProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE));
@@ -127,11 +130,36 @@
                 PowerProfile.SUBSYSTEM_MODEM | ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT
                         | ModemPowerProfile.MODEM_DRAIN_TYPE_TX
                         | ModemPowerProfile.MODEM_TX_LEVEL_4));
+
+        assertEquals(0.02, mProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE));
+        assertEquals(3, mProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX));
+        assertEquals(5, mProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX));
+        assertEquals(3300, mProfile.getAveragePower(
+                PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE));
     }
+
+    @DisabledOnRavenwood
+    @Test
+    public void configDefaults() throws XmlPullParserException {
+        Resources mockResources = mock(Resources.class);
+        when(mockResources.getInteger(com.android.internal.R.integer.config_bluetooth_rx_cur_ma))
+                .thenReturn(123);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new StringReader(
+                "<device name='Android'>"
+                + "<item name='bluetooth.controller.idle'>10</item>"
+                + "</device>"));
+        mProfile.initForTesting(parser, mockResources);
+        assertThat(mProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE))
+                .isEqualTo(10);
+        assertThat(mProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX))
+                .isEqualTo(123);
+    }
+
     @Test
     public void testPowerProfile_legacyCpuConfig() {
         // This power profile has per-cluster data, rather than per-policy
-        mProfile.forceInitForTesting(mContext, R.xml.power_profile_test_cpu_legacy);
+        mProfile.initForTesting(resolveParser("power_profile_test_cpu_legacy"));
 
         assertEquals(2.11, mProfile.getAveragePowerForCpuScalingPolicy(0));
         assertEquals(2.22, mProfile.getAveragePowerForCpuScalingPolicy(4));
@@ -148,7 +176,7 @@
 
     @Test
     public void testModemPowerProfile_defaultRat() throws Exception {
-        final XmlResourceParser parser = getTestModemElement(R.xml.power_profile_test_modem,
+        final XmlPullParser parser = getTestModemElement("power_profile_test_modem",
                 "testModemPowerProfile_defaultRat");
         ModemPowerProfile mpp = new ModemPowerProfile();
         mpp.parseFromXml(parser);
@@ -216,7 +244,7 @@
 
     @Test
     public void testModemPowerProfile_partiallyDefined() throws Exception {
-        final XmlResourceParser parser = getTestModemElement(R.xml.power_profile_test_modem,
+        final XmlPullParser parser = getTestModemElement("power_profile_test_modem",
                 "testModemPowerProfile_partiallyDefined");
         ModemPowerProfile mpp = new ModemPowerProfile();
         mpp.parseFromXml(parser);
@@ -369,7 +397,7 @@
 
     @Test
     public void testModemPowerProfile_fullyDefined() throws Exception {
-        final XmlResourceParser parser = getTestModemElement(R.xml.power_profile_test_modem,
+        final XmlPullParser parser = getTestModemElement("power_profile_test_modem",
                 "testModemPowerProfile_fullyDefined");
         ModemPowerProfile mpp = new ModemPowerProfile();
         mpp.parseFromXml(parser);
@@ -519,11 +547,10 @@
                 | ModemPowerProfile.MODEM_DRAIN_TYPE_TX | ModemPowerProfile.MODEM_TX_LEVEL_4));
     }
 
-    private XmlResourceParser getTestModemElement(@XmlRes int xmlId, String elementName)
+    private XmlPullParser getTestModemElement(String resourceName, String elementName)
             throws Exception {
+        XmlPullParser parser = resolveParser(resourceName);
         final String element = TAG_TEST_MODEM;
-        final Resources resources = mContext.getResources();
-        XmlResourceParser parser = resources.getXml(xmlId);
         while (true) {
             XmlUtils.nextElement(parser);
             final String e = parser.getName();
@@ -535,10 +562,26 @@
 
             return parser;
         }
-        fail("Unanable to find element " + element + " with name " + elementName);
+        fail("Unable to find element " + element + " with name " + elementName);
         return null;
     }
 
+    private XmlPullParser resolveParser(String resourceName) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            try {
+                return Xml.resolvePullParser(getClass().getClassLoader()
+                        .getResourceAsStream("res/xml/" + resourceName + ".xml"));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            Context context = androidx.test.InstrumentationRegistry.getContext();
+            Resources resources = context.getResources();
+            int resId = resources.getIdentifier(resourceName, "xml", context.getPackageName());
+            return resources.getXml(resId);
+        }
+    }
+
     private void assertEquals(double expected, double actual) {
         Assert.assertEquals(expected, actual, 0.1);
     }
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java b/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
index b99e202..6402206 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
@@ -21,20 +21,27 @@
 import android.os.BatteryConsumer;
 import android.os.Parcel;
 import android.os.PersistableBundle;
-import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.SparseArray;
+import android.util.Xml;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class PowerStatsTest {
     @Rule
     public final RavenwoodRule mRavenwood = new RavenwoodRule();
@@ -47,7 +54,10 @@
         mRegistry = new PowerStats.DescriptorRegistry();
         PersistableBundle extras = new PersistableBundle();
         extras.putBoolean("hasPowerMonitor", true);
-        mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU, 3, 2, extras);
+        SparseArray<String> stateLabels = new SparseArray<>();
+        stateLabels.put(0x0F, "idle");
+        mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU, 3, stateLabels,
+                1, 2, extras);
         mRegistry.register(mDescriptor);
     }
 
@@ -58,6 +68,8 @@
         stats.stats[0] = 10;
         stats.stats[1] = 20;
         stats.stats[2] = 30;
+        stats.stateStats.put(0x0F, new long[]{16});
+        stats.stateStats.put(0xF0, new long[]{17});
         stats.uidStats.put(42, new long[]{40, 50});
         stats.uidStats.put(99, new long[]{60, 70});
 
@@ -73,6 +85,7 @@
         assertThat(newDescriptor.powerComponentId).isEqualTo(BatteryConsumer.POWER_COMPONENT_CPU);
         assertThat(newDescriptor.name).isEqualTo("cpu");
         assertThat(newDescriptor.statsArrayLength).isEqualTo(3);
+        assertThat(newDescriptor.stateStatsArrayLength).isEqualTo(1);
         assertThat(newDescriptor.uidStatsArrayLength).isEqualTo(2);
         assertThat(newDescriptor.extras.getBoolean("hasPowerMonitor")).isTrue();
 
@@ -81,6 +94,11 @@
         PowerStats newStats = PowerStats.readFromParcel(newParcel, mRegistry);
         assertThat(newStats.durationMs).isEqualTo(1234);
         assertThat(newStats.stats).isEqualTo(new long[]{10, 20, 30});
+        assertThat(newStats.stateStats.size()).isEqualTo(2);
+        assertThat(newStats.stateStats.get(0x0F)).isEqualTo(new long[]{16});
+        assertThat(newStats.descriptor.getStateLabel(0x0F)).isEqualTo("idle");
+        assertThat(newStats.stateStats.get(0xF0)).isEqualTo(new long[]{17});
+        assertThat(newStats.descriptor.getStateLabel(0xF0)).isEqualTo("cpu-f0");
         assertThat(newStats.uidStats.size()).isEqualTo(2);
         assertThat(newStats.uidStats.get(42)).isEqualTo(new long[]{40, 50});
         assertThat(newStats.uidStats.get(99)).isEqualTo(new long[]{60, 70});
@@ -90,9 +108,33 @@
     }
 
     @Test
+    public void xmlFormat() throws Exception {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        TypedXmlSerializer serializer = Xml.newBinarySerializer();
+        serializer.setOutput(out, StandardCharsets.UTF_8.name());
+        mDescriptor.writeXml(serializer);
+        serializer.flush();
+
+        byte[] bytes = out.toByteArray();
+
+        TypedXmlPullParser parser = Xml.newBinaryPullParser();
+        parser.setInput(new ByteArrayInputStream(bytes), StandardCharsets.UTF_8.name());
+        PowerStats.Descriptor actual = PowerStats.Descriptor.createFromXml(parser);
+
+        assertThat(actual.powerComponentId).isEqualTo(BatteryConsumer.POWER_COMPONENT_CPU);
+        assertThat(actual.name).isEqualTo("cpu");
+        assertThat(actual.statsArrayLength).isEqualTo(3);
+        assertThat(actual.stateStatsArrayLength).isEqualTo(1);
+        assertThat(actual.getStateLabel(0x0F)).isEqualTo("idle");
+        assertThat(actual.getStateLabel(0xF0)).isEqualTo("cpu-f0");
+        assertThat(actual.uidStatsArrayLength).isEqualTo(2);
+        assertThat(actual.extras.getBoolean("hasPowerMonitor")).isEqualTo(true);
+    }
+
+    @Test
     public void parceling_unrecognizedPowerComponent() {
         PowerStats stats = new PowerStats(
-                new PowerStats.Descriptor(777, "luck", 3, 2, new PersistableBundle()));
+                new PowerStats.Descriptor(777, "luck", 3, null, 1, 2, new PersistableBundle()));
         stats.durationMs = 1234;
 
         Parcel parcel = Parcel.obtain();
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
index 82251b8..4921e4a 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
@@ -20,7 +20,6 @@
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
 
@@ -82,14 +81,8 @@
         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeUnset);
         installDecor();
 
-        if ((mPhoneWindow.getAttributes().privateFlags & PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED) != 0
-                && !mPhoneWindow.isFloating()) {
-            assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
-                    is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS));
-        } else {
-            assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
-                    is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT));
-        }
+        assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
+                is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT));
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java
index 8d66cfc..1dbb775 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java
@@ -29,6 +29,7 @@
 import android.content.Context;
 import android.graphics.Insets;
 import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
 import android.view.DisplayCutout;
 import android.view.View;
 import android.view.View.OnApplyWindowInsetsListener;
@@ -49,6 +50,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@Presubmit
 public class ActionBarOverlayLayoutTest {
 
     private static final Insets TOP_INSET_5 = Insets.of(0, 5, 0, 0);
@@ -167,10 +169,67 @@
         assertThat(mContentInsetsListener.captured, is(insetsWith(Insets.NONE, NO_CUTOUT)));
     }
 
+    @Test
+    public void topInset_cutout_noContentOnApplyWindowInsetsListener() {
+        mLayout.setHasContentOnApplyWindowInsetsListener(false);
+        mLayout.dispatchApplyWindowInsets(insetsWith(TOP_INSET_5, CUTOUT_5));
+
+        assertThat(mContentInsetsListener.captured, nullValue());
+
+        mLayout.measure(EXACTLY_1000, EXACTLY_1000);
+
+        // Action bar height is added to the top inset
+        assertThat(mContentInsetsListener.captured, is(insetsWith(TOP_INSET_25, CUTOUT_5)));
+    }
+
+    @Test
+    public void topInset_cutout__hasContentOnApplyWindowInsetsListener() {
+        mLayout.setHasContentOnApplyWindowInsetsListener(true);
+        mLayout.dispatchApplyWindowInsets(insetsWith(TOP_INSET_5, CUTOUT_5));
+
+        assertThat(mContentInsetsListener.captured, nullValue());
+
+        mLayout.measure(EXACTLY_1000, EXACTLY_1000);
+
+        assertThat(mContentInsetsListener.captured, is(insetsWith(Insets.NONE, NO_CUTOUT)));
+    }
+
+    @Test
+    public void topInset_noCutout_noContentOnApplyWindowInsetsListener() {
+        mLayout.setHasContentOnApplyWindowInsetsListener(false);
+        mLayout.dispatchApplyWindowInsets(insetsWith(TOP_INSET_5, NO_CUTOUT));
+
+        assertThat(mContentInsetsListener.captured, nullValue());
+
+        mLayout.measure(EXACTLY_1000, EXACTLY_1000);
+
+        // Action bar height is added to the top inset
+        assertThat(mContentInsetsListener.captured, is(insetsWith(TOP_INSET_25, NO_CUTOUT)));
+    }
+
+    @Test
+    public void topInset_noCutout__hasContentOnApplyWindowInsetsListener() {
+        mLayout.setHasContentOnApplyWindowInsetsListener(true);
+        mLayout.dispatchApplyWindowInsets(insetsWith(TOP_INSET_5, NO_CUTOUT));
+
+        assertThat(mContentInsetsListener.captured, nullValue());
+
+        mLayout.measure(EXACTLY_1000, EXACTLY_1000);
+
+        assertThat(mContentInsetsListener.captured, is(insetsWith(Insets.NONE, NO_CUTOUT)));
+    }
+
     private WindowInsets insetsWith(Insets content, DisplayCutout cutout) {
-        return new WindowInsets(WindowInsets.createCompatTypeMap(content.toRect()), null, null,
-                false, 0, 0, cutout, null, null, null, WindowInsets.Type.systemBars(), false,
-                null, null, 0, 0);
+        final Insets cutoutInsets = cutout != null
+                ? Insets.of(cutout.getSafeInsets())
+                : Insets.NONE;
+        return new WindowInsets.Builder()
+                .setSystemWindowInsets(content)
+                .setDisplayCutout(cutout)
+                .setInsets(WindowInsets.Type.displayCutout(), cutoutInsets)
+                .setInsetsIgnoringVisibility(WindowInsets.Type.displayCutout(), cutoutInsets)
+                .setVisible(WindowInsets.Type.displayCutout(), true)
+                .build();
     }
 
     private ViewGroup createViewGroupWithId(int id) {
@@ -181,14 +240,16 @@
 
     static class TestActionBarOverlayLayout extends ActionBarOverlayLayout {
         private boolean mStable;
+        private boolean mHasContentOnApplyWindowInsetsListener;
 
         public TestActionBarOverlayLayout(Context context) {
             super(context);
+            mHasContentOnApplyWindowInsetsListener = true;
         }
 
         @Override
         public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
-            if (mStable) {
+            if (mStable || !hasContentOnApplyWindowInsetsListener()) {
                 // Emulate the effect of makeOptionalFitsSystemWindows, because we can't do that
                 // without being attached to a window.
                 outLocalInsets.setEmpty();
@@ -202,6 +263,15 @@
             setSystemUiVisibility(stable ? SYSTEM_UI_FLAG_LAYOUT_STABLE : 0);
         }
 
+        void setHasContentOnApplyWindowInsetsListener(boolean hasListener) {
+            mHasContentOnApplyWindowInsetsListener = hasListener;
+        }
+
+        @Override
+        protected boolean hasContentOnApplyWindowInsetsListener() {
+            return mHasContentOnApplyWindowInsetsListener;
+        }
+
         @Override
         public int getWindowSystemUiVisibility() {
             return getSystemUiVisibility();
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index 2d778b1..aca52a8 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -40,6 +40,7 @@
         "platform-test-annotations",
         "truth",
         "testables",
+        "flag-junit",
     ],
 
     libs: [
diff --git a/core/tests/mockingcoretests/src/android/widget/OWNERS b/core/tests/mockingcoretests/src/android/widget/OWNERS
new file mode 100644
index 0000000..c0cbea9
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/widget/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
\ No newline at end of file
diff --git a/core/tests/mockingcoretests/src/android/widget/ToastTest.java b/core/tests/mockingcoretests/src/android/widget/ToastTest.java
new file mode 100644
index 0000000..79bc81d
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/widget/ToastTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import android.app.INotificationManager;
+import android.content.Context;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.view.View;
+import android.widget.flags.Flags;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+
+/**
+ * ToastTest tests {@link Toast}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ToastTest {
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    private Context mContext;
+    private MockitoSession mMockingSession;
+    private static INotificationManager.Stub sMockNMS;
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getContext();
+        mMockingSession =
+              ExtendedMockito.mockitoSession()
+                  .strictness(Strictness.LENIENT)
+                  .mockStatic(ServiceManager.class)
+                  .startMocking();
+
+        //Toast caches the NotificationManager service as static class member
+        if (sMockNMS == null) {
+            sMockNMS = mock(INotificationManager.Stub.class);
+        }
+        doReturn(sMockNMS).when(sMockNMS).queryLocalInterface("android.app.INotificationManager");
+        doReturn(sMockNMS).when(() -> ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockingSession != null) {
+            mMockingSession.finishMocking();
+        }
+        reset(sMockNMS);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_TOAST_NO_WEAKREF)
+    public void enqueueFail_nullifiesNextView() throws RemoteException {
+        Looper.prepare();
+
+        // allow 1st toast and fail on the 2nd
+        when(sMockNMS.enqueueToast(anyString(), any(), any(), anyInt(), anyBoolean(),
+              anyInt())).thenReturn(true, false);
+
+        // first toast is enqueued
+        Toast t = Toast.makeText(mContext, "Toast1", Toast.LENGTH_SHORT);
+        t.setView(mock(View.class));
+        t.show();
+        Toast.TN tn = t.getTn();
+        assertThat(tn.getNextView()).isNotNull();
+
+        // second toast is not enqueued
+        t = Toast.makeText(mContext, "Toast2", Toast.LENGTH_SHORT);
+        t.setView(mock(View.class));
+        t.show();
+        tn = t.getTn();
+        assertThat(tn.getNextView()).isNull();
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_TOAST_NO_WEAKREF)
+    public void enqueueFail_doesNotNullifyNextView() throws RemoteException {
+        Looper.prepare();
+
+        // allow 1st toast and fail on the 2nd
+        when(sMockNMS.enqueueToast(anyString(), any(), any(), anyInt(), anyBoolean(),
+              anyInt())).thenReturn(true, false);
+
+        // first toast is enqueued
+        Toast t = Toast.makeText(mContext, "Toast1", Toast.LENGTH_SHORT);
+        t.setView(mock(View.class));
+        t.show();
+        Toast.TN tn = t.getTn();
+        assertThat(tn.getNextView()).isNotNull();
+
+        // second toast is not enqueued
+        t = Toast.makeText(mContext, "Toast2", Toast.LENGTH_SHORT);
+        t.setView(mock(View.class));
+        t.show();
+        tn = t.getTn();
+        assertThat(tn.getNextView()).isNotNull();
+    }
+}
diff --git a/core/tests/overlaytests/device_non_system/Android.bp b/core/tests/overlaytests/device_non_system/Android.bp
new file mode 100644
index 0000000..dd7786a
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // 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: "OverlayDeviceTestsNonSystem",
+    team: "trendy_team_android_resources",
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    static_libs: [
+        "androidx.test.rules",
+        "testng",
+        "compatibility-device-util-axt",
+    ],
+    test_suites: ["device-tests"],
+    data: [
+        ":OverlayDeviceTestsNonSystem_AppOverlay",
+    ],
+}
diff --git a/core/tests/overlaytests/device_non_system/AndroidManifest.xml b/core/tests/overlaytests/device_non_system/AndroidManifest.xml
new file mode 100644
index 0000000..a37d168
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.overlaytest.non_system">
+
+    <uses-sdk android:minSdkVersion="34" />
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.overlaytest.non_system"
+        android:label="Runtime resource overlay tests for non system app" />
+</manifest>
diff --git a/core/tests/overlaytests/device_non_system/AndroidTest.xml b/core/tests/overlaytests/device_non_system/AndroidTest.xml
new file mode 100644
index 0000000..fc47e6a
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/AndroidTest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Test module config for OverlayDeviceTestsNonSystem">
+    <option name="test-tag" value="OverlayDeviceTestsNonSystem" />
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="OverlayDeviceTestsNonSystem_AppOverlay.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunOnSecondaryUserTargetPreparer">
+        <option name="test-package-name" value="com.android.overlaytest.non_system" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="test-user-token" value="%TEST_USER%"/>
+        <option name="run-command"
+            value="cmd overlay enable --user %TEST_USER% com.android.overlaytest.non_system.app_overlay" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="OverlayDeviceTestsNonSystem.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.overlaytest.non_system" />
+    </test>
+</configuration>
diff --git a/core/tests/overlaytests/device_non_system/res/layout/layout.xml b/core/tests/overlaytests/device_non_system/res/layout/layout.xml
new file mode 100644
index 0000000..2cb2013
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/res/layout/layout.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/text_view_id"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:text="@string/test_string" />
+</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/overlaytests/device_non_system/res/values/overlayable.xml b/core/tests/overlaytests/device_non_system/res/values/overlayable.xml
new file mode 100644
index 0000000..f8017bc
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/res/values/overlayable.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <overlayable name="TestResources">
+        <policy type="public">
+            <item type="string" name="test_string" />
+        </policy>
+    </overlayable>
+</resources>
\ No newline at end of file
diff --git a/core/tests/overlaytests/device_non_system/res/values/strings.xml b/core/tests/overlaytests/device_non_system/res/values/strings.xml
new file mode 100644
index 0000000..ff501a0
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+    <string name="test_string">Original</string>
+</resources>
\ No newline at end of file
diff --git a/core/tests/overlaytests/device_non_system/src/com/android/overlaytest/OverlayTest.java b/core/tests/overlaytests/device_non_system/src/com/android/overlaytest/OverlayTest.java
new file mode 100644
index 0000000..2b0fe6c
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/src/com/android/overlaytest/OverlayTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.overlaytest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.overlaytest.non_system.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * This test class is to verify overlay behavior for non-system apps.
+ */
+@RunWith(JUnit4.class)
+public class OverlayTest {
+    @Test
+    public void testStringOverlay() throws Throwable {
+        final LayoutInflater inflater = LayoutInflater.from(InstrumentationRegistry.getContext());
+        final View layout = inflater.inflate(R.layout.layout, null);
+        TextView tv = layout.findViewById(R.id.text_view_id);
+        assertNotNull(tv);
+        assertEquals("Overlaid", tv.getText().toString());
+    }
+}
diff --git a/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/Android.bp b/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/Android.bp
new file mode 100644
index 0000000..b5e6d9c
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // 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: "OverlayDeviceTestsNonSystem_AppOverlay",
+    team: "trendy_team_android_resources",
+    sdk_version: "current",
+    certificate: "platform",
+    aaptflags: ["--no-resource-removal"],
+}
diff --git a/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/AndroidManifest.xml b/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..4df80c0
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.overlaytest.non_system.app_overlay"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <application android:hasCode="false" />
+    <overlay android:targetPackage="com.android.overlaytest.non_system"
+        android:targetName="TestResources"
+        android:isStatic="true"
+        android:resourcesMap="@xml/overlays"/>
+</manifest>
\ No newline at end of file
diff --git a/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/res/xml/overlays.xml b/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/res/xml/overlays.xml
new file mode 100644
index 0000000..d0d4bfe
--- /dev/null
+++ b/core/tests/overlaytests/device_non_system/test-apps/AppOverlay/res/xml/overlays.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<overlay>
+    <item target="string/test_string" value="Overlaid"/>
+</overlay>
\ No newline at end of file
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index cd68503..7a4b6bc 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -68,5 +68,6 @@
         <permission name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
         <permission name="android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS" />
         <permission name="android.permission.SATELLITE_COMMUNICATION" />
+        <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index bca741f..66b47dae 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -52,6 +52,7 @@
         <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
+        <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/>
         <permission name="android.permission.READ_WALLPAPER_INTERNAL"/>
         <permission name="android.permission.REAL_GET_TASKS"/>
         <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
diff --git a/data/etc/core.protolog.pb b/data/etc/core.protolog.pb
index 826adc39..97147a0 100644
--- a/data/etc/core.protolog.pb
+++ b/data/etc/core.protolog.pb
Binary files differ
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fc4277e..82d2381 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -594,6 +594,8 @@
         <permission name="android.permission.EMERGENCY_INSTALL_PACKAGES" />
         <!-- Permission required for Cts test - CtsSettingsTestCases -->
         <permission name="android.permission.PREPARE_FACTORY_RESET" />
+        <!-- Permission required for CTS test - FileIntegrityManagerTest -->
+        <permission name="android.permission.SETUP_FSVERITY" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index d410d5f..483b693 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -709,18 +709,6 @@
       "group": "WM_DEBUG_CONFIGURATION",
       "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
     },
-    "2959074735946674755": {
-      "message": "Trying to update display configuration for system\/invalid process.",
-      "level": "WARN",
-      "group": "WM_DEBUG_CONFIGURATION",
-      "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
-    },
-    "5668810920995272206": {
-      "message": "Trying to update display configuration for invalid process, pid=%d",
-      "level": "WARN",
-      "group": "WM_DEBUG_CONFIGURATION",
-      "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
-    },
     "-1123414663662718691": {
       "message": "setVr2dDisplayId called for: %d",
       "level": "DEBUG",
@@ -1057,12 +1045,6 @@
       "group": "WM_DEBUG_BACK_PREVIEW",
       "at": "com\/android\/server\/wm\/BackNavigationController.java"
     },
-    "-1459414342866553129": {
-      "message": "Current focused window being animated by recents. Overriding back callback to recents controller callback.",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_BACK_PREVIEW",
-      "at": "com\/android\/server\/wm\/BackNavigationController.java"
-    },
     "2881085074175114605": {
       "message": "Focused window didn't have a valid surface drawn.",
       "level": "DEBUG",
@@ -3469,6 +3451,12 @@
       "group": "WM_DEBUG_WALLPAPER",
       "at": "com\/android\/server\/wm\/WallpaperController.java"
     },
+    "257349083882992098": {
+      "message": "updateWallpaperTokens requestedVisibility=%b on keyguardLocked=%b",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WALLPAPER",
+      "at": "com\/android\/server\/wm\/WallpaperController.java"
+    },
     "7408402065665963407": {
       "message": "Wallpaper at display %d - visibility: %b, keyguardLocked: %b",
       "level": "VERBOSE",
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index f9347ee..e8b4104 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -424,12 +424,14 @@
 key 582   VOICE_ASSIST
 # Linux KEY_ASSISTANT
 key 583   ASSIST
+key 585   EMOJI_PICKER
 key 656   MACRO_1
 key 657   MACRO_2
 key 658   MACRO_3
 key 659   MACRO_4
 
 # Keys defined by HID usages
+key usage 0x0c0065 SCREENSHOT                FALLBACK_USAGE_MAPPING
 key usage 0x0c0067 WINDOW                    FALLBACK_USAGE_MAPPING
 key usage 0x0c006F BRIGHTNESS_UP             FALLBACK_USAGE_MAPPING
 key usage 0x0c0070 BRIGHTNESS_DOWN           FALLBACK_USAGE_MAPPING
diff --git a/graphics/java/Android.bp b/graphics/java/Android.bp
index ece453d..f4abd0a 100644
--- a/graphics/java/Android.bp
+++ b/graphics/java/Android.bp
@@ -11,6 +11,7 @@
 aconfig_declarations {
     name: "framework_graphics_flags",
     package: "com.android.graphics.flags",
+    container: "system",
     srcs: ["android/framework_graphics.aconfig"],
 }
 
diff --git a/graphics/java/android/framework_graphics.aconfig b/graphics/java/android/framework_graphics.aconfig
index 1e41b4d..4ab09eb 100644
--- a/graphics/java/android/framework_graphics.aconfig
+++ b/graphics/java/android/framework_graphics.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.graphics.flags"
+container: "system"
 
 flag {
      name: "exact_compute_bounds"
@@ -14,4 +15,4 @@
      namespace: "core_graphics"
      description: "Feature flag for YUV image compress to Ultra HDR."
      bug: "308978825"
-}
\ No newline at end of file
+}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 250362b..319f115 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -41,12 +41,15 @@
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.IOException;
+import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.lang.ref.WeakReference;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
 import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.WeakHashMap;
 
 public final class Bitmap implements Parcelable {
     private static final String TAG = "Bitmap";
@@ -120,6 +123,11 @@
     }
 
     /**
+     * @hide
+     */
+    private static final WeakHashMap<Bitmap, Void> sAllBitmaps = new WeakHashMap<>();
+
+    /**
      * Private constructor that must receive an already allocated native bitmap
      * int (pointer).
      */
@@ -162,6 +170,9 @@
                     Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
         }
         registry.registerNativeAllocation(this, nativeBitmap);
+        synchronized (Bitmap.class) {
+          sAllBitmaps.put(this, null);
+        }
     }
 
     /**
@@ -1510,6 +1521,86 @@
     }
 
     /**
+     * @hide
+     */
+    private static final class DumpData {
+        private int count;
+        private int format;
+        private long[] natives;
+        private byte[][] buffers;
+        private int max;
+
+        public DumpData(@NonNull CompressFormat format, int max) {
+            this.max = max;
+            this.format = format.nativeInt;
+            this.natives = new long[max];
+            this.buffers = new byte[max][];
+            this.count = 0;
+        }
+
+        public void add(long nativePtr, byte[] buffer) {
+            natives[count] = nativePtr;
+            buffers[count] = buffer;
+            count = (count >= max) ? max : count + 1;
+        }
+
+        public int size() {
+            return count;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    private static DumpData dumpData = null;
+
+
+    /**
+     * @hide
+     *
+     * Dump all the bitmaps with their contents compressed into dumpData
+     *
+     * @param format  format of the compressed image, null to clear dump data
+     */
+    public static void dumpAll(@Nullable String format) {
+        if (format == null) {
+            /* release the dump data */
+            dumpData = null;
+            return;
+        }
+        final CompressFormat fmt;
+        if (format.equals("jpg") || format.equals("jpeg")) {
+            fmt = CompressFormat.JPEG;
+        } else if (format.equals("png")) {
+            fmt = CompressFormat.PNG;
+        } else if (format.equals("webp")) {
+            fmt = CompressFormat.WEBP_LOSSLESS;
+        } else {
+            Log.w(TAG, "No bitmaps dumped: unrecognized format " + format);
+            return;
+        }
+
+        final ArrayList<Bitmap> allBitmaps;
+        synchronized (Bitmap.class) {
+          allBitmaps = new ArrayList<>(sAllBitmaps.size());
+          for (Bitmap bitmap : sAllBitmaps.keySet()) {
+            if (bitmap != null && !bitmap.isRecycled()) {
+              allBitmaps.add(bitmap);
+            }
+          }
+        }
+
+        dumpData = new DumpData(fmt, allBitmaps.size());
+        for (Bitmap bitmap : allBitmaps) {
+            ByteArrayOutputStream bas = new ByteArrayOutputStream();
+            if (bitmap.compress(fmt, 90, bas)) {
+                dumpData.add(bitmap.getNativeInstance(), bas.toByteArray());
+            }
+        }
+        Log.i(TAG, dumpData.size() + "/" + allBitmaps.size() + " bitmaps dumped");
+    }
+
+    /**
      * Number of bytes of temp storage we use for communicating between the
      * native compressor and the java OutputStream.
      */
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index efbbfc2..24aea37 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -229,4 +229,24 @@
                     "Keystore error while trying to get apps affected by SID.");
         }
     }
+
+    /**
+    * Deletes all keys in all KeyMint devices.
+    * Called by RecoverySystem before rebooting to recovery in order to delete all KeyMint keys,
+    * including synthetic password protector keys (used by LockSettingsService), as well as keys
+    * protecting DE and metadata encryption keys (used by vold). This ensures that FBE-encrypted
+    * data is unrecoverable even if the data wipe in recovery is interrupted or skipped.
+    */
+    public static void deleteAllKeys() throws KeyStoreException {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().deleteAllKeys();
+        } catch (RemoteException | NullPointerException e) {
+            throw new KeyStoreException(SYSTEM_ERROR,
+                    "Failure to connect to Keystore while trying to delete all keys.");
+        } catch (ServiceSpecificException e) {
+            throw new KeyStoreException(e.errorCode,
+                    "Keystore error while trying to delete all keys.");
+        }
+    }
 }
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
deleted file mode 100644
index 6404c4b..0000000
--- a/keystore/java/android/security/Authorization.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.hardware.biometrics.BiometricConstants;
-import android.hardware.security.keymint.HardwareAuthToken;
-import android.hardware.security.keymint.HardwareAuthenticatorType;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
-import android.os.StrictMode;
-import android.security.authorization.IKeystoreAuthorization;
-import android.system.keystore2.ResponseCode;
-import android.util.Log;
-
-/**
- * @hide This is the client side for IKeystoreAuthorization AIDL.
- * It shall only be used by biometric authentication providers and Gatekeeper.
- */
-public class Authorization {
-    private static final String TAG = "KeystoreAuthorization";
-
-    public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
-
-    /**
-     * @return an instance of IKeystoreAuthorization
-     */
-    public static IKeystoreAuthorization getService() {
-        return IKeystoreAuthorization.Stub.asInterface(
-                    ServiceManager.checkService("android.security.authorization"));
-    }
-
-    /**
-     * Adds an auth token to keystore2.
-     *
-     * @param authToken created by Android authenticators.
-     * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
-     */
-    public static int addAuthToken(@NonNull HardwareAuthToken authToken) {
-        StrictMode.noteSlowCall("addAuthToken");
-        try {
-            getService().addAuthToken(authToken);
-            return 0;
-        } catch (RemoteException | NullPointerException e) {
-            Log.w(TAG, "Can not connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ServiceSpecificException e) {
-            return e.errorCode;
-        }
-    }
-
-    /**
-     * Add an auth token to Keystore 2.0 in the legacy serialized auth token format.
-     * @param authToken
-     * @return 0 if successful or a {@code ResponseCode}.
-     */
-    public static int addAuthToken(@NonNull byte[] authToken) {
-        return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
-    }
-
-    /**
-     * Tells Keystore that the device is now unlocked for a user.
-     *
-     * @param userId - the user's Android user ID
-     * @param password - a secret derived from the user's synthetic password, if the unlock method
-     *                   is LSKF (or equivalent) and thus has made the synthetic password available
-     * @return 0 if successful or a {@code ResponseCode}.
-     */
-    public static int onDeviceUnlocked(int userId, @Nullable byte[] password) {
-        StrictMode.noteDiskWrite();
-        try {
-            getService().onDeviceUnlocked(userId, password);
-            return 0;
-        } catch (RemoteException | NullPointerException e) {
-            Log.w(TAG, "Can not connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ServiceSpecificException e) {
-            return e.errorCode;
-        }
-    }
-
-    /**
-     * Tells Keystore that the device is now locked for a user.
-     *
-     * @param userId - the user's Android user ID
-     * @param unlockingSids - list of biometric SIDs with which the device may be unlocked again
-     * @param weakUnlockEnabled - true if non-strong biometric or trust agent unlock is enabled
-     * @return 0 if successful or a {@code ResponseCode}.
-     */
-    public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
-            boolean weakUnlockEnabled) {
-        StrictMode.noteDiskWrite();
-        try {
-            getService().onDeviceLocked(userId, unlockingSids, weakUnlockEnabled);
-            return 0;
-        } catch (RemoteException | NullPointerException e) {
-            Log.w(TAG, "Can not connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ServiceSpecificException e) {
-            return e.errorCode;
-        }
-    }
-
-    /**
-     * Gets the last authentication time of the given user and authenticators.
-     *
-     * @param userId user id
-     * @param authenticatorTypes an array of {@link HardwareAuthenticatorType}.
-     * @return the last authentication time or
-     * {@link BiometricConstants#BIOMETRIC_NO_AUTHENTICATION}.
-     */
-    public static long getLastAuthenticationTime(
-            long userId, @HardwareAuthenticatorType int[] authenticatorTypes) {
-        try {
-            return getService().getLastAuthTime(userId, authenticatorTypes);
-        } catch (RemoteException | NullPointerException e) {
-            Log.w(TAG, "Can not connect to keystore", e);
-            return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
-        } catch (ServiceSpecificException e) {
-            return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
-        }
-    }
-
-}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 2cac2e1..d1d7c14 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,9 +16,6 @@
 
 package android.security;
 
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.StrictMode;
-
 /**
  * This class provides some constants and helper methods related to Android's Keystore service.
  * This class was originally much larger, but its functionality was superseded by other classes.
@@ -31,24 +28,4 @@
 
     // Used for UID field to indicate the calling UID.
     public static final int UID_SELF = -1;
-
-    private static final KeyStore KEY_STORE = new KeyStore();
-
-    @UnsupportedAppUsage
-    public static KeyStore getInstance() {
-        return KEY_STORE;
-    }
-
-    /**
-     * Add an authentication record to the keystore authorization table.
-     *
-     * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
-     * @return 0 on success, otherwise an error value corresponding to a
-     * {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
-     */
-    public int addAuthToken(byte[] authToken) {
-        StrictMode.noteDiskWrite();
-
-        return Authorization.addAuthToken(authToken);
-    }
 }
diff --git a/keystore/java/android/security/KeyStoreAuthorization.java b/keystore/java/android/security/KeyStoreAuthorization.java
new file mode 100644
index 0000000..14d715f
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreAuthorization.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricConstants;
+import android.hardware.security.keymint.HardwareAuthToken;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.os.StrictMode;
+import android.security.authorization.IKeystoreAuthorization;
+import android.system.keystore2.ResponseCode;
+import android.util.Log;
+
+/**
+ * @hide This is the client side for IKeystoreAuthorization AIDL.
+ * It shall only be used by biometric authentication providers and Gatekeeper.
+ */
+public class KeyStoreAuthorization {
+    private static final String TAG = "KeyStoreAuthorization";
+
+    public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
+
+    private static final KeyStoreAuthorization sInstance = new KeyStoreAuthorization();
+
+    public static KeyStoreAuthorization getInstance() {
+        return sInstance;
+    }
+
+    /**
+     * @return an instance of IKeystoreAuthorization
+     */
+    private IKeystoreAuthorization getService() {
+        return IKeystoreAuthorization.Stub.asInterface(
+                    ServiceManager.checkService("android.security.authorization"));
+    }
+
+    /**
+     * Adds an auth token to keystore2.
+     *
+     * @param authToken created by Android authenticators.
+     * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
+     */
+    public int addAuthToken(@NonNull HardwareAuthToken authToken) {
+        StrictMode.noteSlowCall("addAuthToken");
+        try {
+            getService().addAuthToken(authToken);
+            return 0;
+        } catch (RemoteException | NullPointerException e) {
+            Log.w(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        } catch (ServiceSpecificException e) {
+            return e.errorCode;
+        }
+    }
+
+    /**
+     * Add an auth token to Keystore 2.0 in the legacy serialized auth token format.
+     * @param authToken
+     * @return 0 if successful or a {@code ResponseCode}.
+     */
+    public int addAuthToken(@NonNull byte[] authToken) {
+        return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
+    }
+
+    /**
+     * Tells Keystore that the device is now unlocked for a user.
+     *
+     * @param userId - the user's Android user ID
+     * @param password - a secret derived from the user's synthetic password, if the unlock method
+     *                   is LSKF (or equivalent) and thus has made the synthetic password available
+     * @return 0 if successful or a {@code ResponseCode}.
+     */
+    public int onDeviceUnlocked(int userId, @Nullable byte[] password) {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().onDeviceUnlocked(userId, password);
+            return 0;
+        } catch (RemoteException | NullPointerException e) {
+            Log.w(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        } catch (ServiceSpecificException e) {
+            return e.errorCode;
+        }
+    }
+
+    /**
+     * Tells Keystore that the device is now locked for a user.
+     *
+     * @param userId - the user's Android user ID
+     * @param unlockingSids - list of biometric SIDs with which the device may be unlocked again
+     * @param weakUnlockEnabled - true if non-strong biometric or trust agent unlock is enabled
+     * @return 0 if successful or a {@code ResponseCode}.
+     */
+    public int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
+            boolean weakUnlockEnabled) {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().onDeviceLocked(userId, unlockingSids, weakUnlockEnabled);
+            return 0;
+        } catch (RemoteException | NullPointerException e) {
+            Log.w(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        } catch (ServiceSpecificException e) {
+            return e.errorCode;
+        }
+    }
+
+    /**
+     * Gets the last authentication time of the given user and authenticators.
+     *
+     * @param userId user id
+     * @param authenticatorTypes an array of {@link HardwareAuthenticatorType}.
+     * @return the last authentication time or
+     * {@link BiometricConstants#BIOMETRIC_NO_AUTHENTICATION}.
+     */
+    public long getLastAuthTime(long userId, @HardwareAuthenticatorType int[] authenticatorTypes) {
+        try {
+            return getService().getLastAuthTime(userId, authenticatorTypes);
+        } catch (RemoteException | NullPointerException e) {
+            Log.w(TAG, "Error getting last auth time: " + e);
+            return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+        } catch (ServiceSpecificException e) {
+            // This is returned when the feature flag test fails in keystore2
+            if (e.errorCode == ResponseCode.PERMISSION_DENIED) {
+                throw new UnsupportedOperationException();
+            }
+            return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+        }
+    }
+
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
index b8ac191..a0d6fce 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
@@ -25,14 +25,15 @@
 import static android.window.TaskFragmentOperation.OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE;
 import static android.window.TaskFragmentOperation.OP_TYPE_SET_DECOR_SURFACE_BOOSTED;
 
-import static androidx.window.extensions.embedding.DividerAttributes.RATIO_UNSET;
-import static androidx.window.extensions.embedding.DividerAttributes.WIDTH_UNSET;
+import static androidx.window.extensions.embedding.DividerAttributes.RATIO_SYSTEM_DEFAULT;
+import static androidx.window.extensions.embedding.DividerAttributes.WIDTH_SYSTEM_DEFAULT;
 import static androidx.window.extensions.embedding.SplitAttributesHelper.isReversedLayout;
 import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_BOTTOM;
 import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_LEFT;
 import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_RIGHT;
 import static androidx.window.extensions.embedding.SplitPresenter.CONTAINER_POSITION_TOP;
 
+import android.annotation.DimenRes;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
 import android.content.Context;
@@ -61,9 +62,11 @@
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.GuardedBy;
-import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.window.extensions.core.util.function.Consumer;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -76,12 +79,13 @@
  * Manages the rendering and interaction of the divider.
  */
 class DividerPresenter implements View.OnTouchListener {
+    static final float RATIO_EXPANDED_PRIMARY = 1.0f;
+    static final float RATIO_EXPANDED_SECONDARY = 0.0f;
     private static final String WINDOW_NAME = "AE Divider";
     private static final int VEIL_LAYER = 0;
     private static final int DIVIDER_LAYER = 1;
 
     // TODO(b/327067596) Update based on UX guidance.
-    private static final Color DEFAULT_DIVIDER_COLOR = Color.valueOf(Color.BLACK);
     private static final Color DEFAULT_PRIMARY_VEIL_COLOR = Color.valueOf(Color.BLACK);
     private static final Color DEFAULT_SECONDARY_VEIL_COLOR = Color.valueOf(Color.GRAY);
     @VisibleForTesting
@@ -162,54 +166,55 @@
                 return;
             }
 
+            final SplitAttributes splitAttributes = topSplitContainer.getCurrentSplitAttributes();
+            final DividerAttributes dividerAttributes = splitAttributes.getDividerAttributes();
+
             // Clean up the decor surface if DividerAttributes is null.
-            final DividerAttributes dividerAttributes =
-                    topSplitContainer.getCurrentSplitAttributes().getDividerAttributes();
             if (dividerAttributes == null) {
                 removeDecorSurfaceAndDivider(wct);
                 return;
             }
 
-            if (topSplitContainer.getCurrentSplitAttributes().getSplitType()
-                    instanceof SplitAttributes.SplitType.ExpandContainersSplitType) {
-                // No divider is needed for ExpandContainersSplitType.
-                removeDivider();
-                return;
-            }
+            // At this point, a divider is required.
 
-            // Skip updating when the TFs have not been updated to match the SplitAttributes.
-            if (topSplitContainer.getPrimaryContainer().getLastRequestedBounds().isEmpty()
-                    || topSplitContainer.getSecondaryContainer().getLastRequestedBounds()
-                    .isEmpty()) {
-                return;
-            }
-
+            // Create the decor surface if one is not available yet.
             final SurfaceControl decorSurface = parentInfo.getDecorSurface();
             if (decorSurface == null) {
                 // Clean up when the decor surface is currently unavailable.
                 removeDivider();
                 // Request to create the decor surface
-                createOrMoveDecorSurface(wct, topSplitContainer.getPrimaryContainer());
+                createOrMoveDecorSurfaceLocked(wct, topSplitContainer.getPrimaryContainer());
                 return;
             }
 
-            // make the top primary container the owner of the decor surface.
-            if (!Objects.equals(mDecorSurfaceOwner,
-                    topSplitContainer.getPrimaryContainer().getTaskFragmentToken())) {
-                createOrMoveDecorSurface(wct, topSplitContainer.getPrimaryContainer());
+            // Update the decor surface owner if needed.
+            boolean isDraggableExpandType =
+                    SplitAttributesHelper.isDraggableExpandType(splitAttributes);
+            final TaskFragmentContainer decorSurfaceOwnerContainer = isDraggableExpandType
+                    ? topSplitContainer.getSecondaryContainer()
+                    : topSplitContainer.getPrimaryContainer();
+
+            if (!Objects.equals(
+                    mDecorSurfaceOwner, decorSurfaceOwnerContainer.getTaskFragmentToken())) {
+                createOrMoveDecorSurfaceLocked(wct, decorSurfaceOwnerContainer);
             }
+            final boolean isVerticalSplit = isVerticalSplit(topSplitContainer);
+            final boolean isReversedLayout = isReversedLayout(
+                    topSplitContainer.getCurrentSplitAttributes(),
+                    parentInfo.getConfiguration());
 
             updateProperties(
                     new Properties(
                             parentInfo.getConfiguration(),
                             dividerAttributes,
                             decorSurface,
-                            getInitialDividerPosition(topSplitContainer),
-                            isVerticalSplit(topSplitContainer),
-                            isReversedLayout(
-                                    topSplitContainer.getCurrentSplitAttributes(),
-                                    parentInfo.getConfiguration()),
-                            parentInfo.getDisplayId()));
+                            getInitialDividerPosition(
+                                    topSplitContainer, isVerticalSplit, isReversedLayout),
+                            isVerticalSplit,
+                            isReversedLayout,
+                            parentInfo.getDisplayId(),
+                            isDraggableExpandType
+                    ));
         }
     }
 
@@ -242,14 +247,21 @@
      *
      * See {@link TaskFragmentOperation#OP_TYPE_CREATE_OR_MOVE_TASK_FRAGMENT_DECOR_SURFACE}.
      */
-    @GuardedBy("mLock")
-    private void createOrMoveDecorSurface(
+    void createOrMoveDecorSurface(
             @NonNull WindowContainerTransaction wct, @NonNull TaskFragmentContainer container) {
+        synchronized (mLock) {
+            createOrMoveDecorSurfaceLocked(wct, container);
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void createOrMoveDecorSurfaceLocked(
+            @NonNull WindowContainerTransaction wct, @NonNull TaskFragmentContainer container) {
+        mDecorSurfaceOwner = container.getTaskFragmentToken();
         final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
                 OP_TYPE_CREATE_OR_MOVE_TASK_FRAGMENT_DECOR_SURFACE)
                 .build();
-        wct.addTaskFragmentOperation(container.getTaskFragmentToken(), operation);
-        mDecorSurfaceOwner = container.getTaskFragmentToken();
+        wct.addTaskFragmentOperation(mDecorSurfaceOwner, operation);
     }
 
     @GuardedBy("mLock")
@@ -274,15 +286,28 @@
     }
 
     @VisibleForTesting
-    static int getInitialDividerPosition(@NonNull SplitContainer splitContainer) {
+    static int getInitialDividerPosition(
+            @NonNull SplitContainer splitContainer,
+            boolean isVerticalSplit,
+            boolean isReversedLayout) {
         final Rect primaryBounds =
                 splitContainer.getPrimaryContainer().getLastRequestedBounds();
         final Rect secondaryBounds =
                 splitContainer.getSecondaryContainer().getLastRequestedBounds();
-        if (isVerticalSplit(splitContainer)) {
-            return Math.min(primaryBounds.right, secondaryBounds.right);
+        final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
+
+        if (SplitAttributesHelper.isDraggableExpandType(splitAttributes)) {
+            // If the container is fully expanded by dragging the divider, we display the divider
+            // on the edge.
+            final int dividerWidth = getDividerWidthPx(splitAttributes.getDividerAttributes());
+            final int fullyExpandedPosition = isVerticalSplit
+                    ? primaryBounds.right - dividerWidth
+                    : primaryBounds.bottom - dividerWidth;
+            return isReversedLayout ? fullyExpandedPosition : 0;
         } else {
-            return Math.min(primaryBounds.bottom, secondaryBounds.bottom);
+            return isVerticalSplit
+                    ? Math.min(primaryBounds.right, secondaryBounds.right)
+                    : Math.min(primaryBounds.bottom, secondaryBounds.bottom);
         }
     }
 
@@ -316,7 +341,7 @@
                 applicationContext.getResources().getDisplayMetrics());
     }
 
-    private static int getDimensionDp(@IdRes int resId) {
+    private static int getDimensionDp(@DimenRes int resId) {
         final Context context = ActivityThread.currentActivityThread().getApplication();
         final int px = context.getResources().getDimensionPixelSize(resId);
         return (int) TypedValue.convertPixelsToDimension(
@@ -359,14 +384,14 @@
     @VisibleForTesting
     static int getBoundsOffsetForDivider(
             int dividerWidthPx,
-            @NonNull SplitAttributes.SplitType splitType,
+            @NonNull SplitType splitType,
             @SplitPresenter.ContainerPosition int position) {
-        if (splitType instanceof SplitAttributes.SplitType.ExpandContainersSplitType) {
-            // No divider is needed for the ExpandContainersSplitType.
+        if (splitType instanceof ExpandContainersSplitType) {
+            // No divider offset is needed for the ExpandContainersSplitType.
             return 0;
         }
         int primaryOffset;
-        if (splitType instanceof final SplitAttributes.SplitType.RatioSplitType splitRatio) {
+        if (splitType instanceof final RatioSplitType splitRatio) {
             // When a divider is present, both containers shrink by an amount proportional to their
             // split ratio and sum to the width of the divider, so that the ending sizing of the
             // containers still maintain the same ratio.
@@ -393,7 +418,8 @@
      * Sanitizes and sets default values in the {@link DividerAttributes}.
      *
      * Unset values will be set with system default values. See
-     * {@link DividerAttributes#WIDTH_UNSET} and {@link DividerAttributes#RATIO_UNSET}.
+     * {@link DividerAttributes#WIDTH_SYSTEM_DEFAULT} and
+     * {@link DividerAttributes#RATIO_SYSTEM_DEFAULT}.
      *
      * @param dividerAttributes input {@link DividerAttributes}
      * @return a {@link DividerAttributes} that has all values properly set.
@@ -405,7 +431,10 @@
             return null;
         }
         int widthDp = dividerAttributes.getWidthDp();
-        if (widthDp == WIDTH_UNSET) {
+        float minRatio = dividerAttributes.getPrimaryMinRatio();
+        float maxRatio = dividerAttributes.getPrimaryMaxRatio();
+
+        if (widthDp == WIDTH_SYSTEM_DEFAULT) {
             widthDp = DEFAULT_DIVIDER_WIDTH_DP;
         }
 
@@ -413,16 +442,14 @@
             // Draggable divider width must be larger than the drag handle size.
             widthDp = Math.max(widthDp,
                     getDimensionDp(R.dimen.activity_embedding_divider_touch_target_width));
-        }
 
-        float minRatio = dividerAttributes.getPrimaryMinRatio();
-        if (minRatio == RATIO_UNSET) {
-            minRatio = DEFAULT_MIN_RATIO;
-        }
-
-        float maxRatio = dividerAttributes.getPrimaryMaxRatio();
-        if (maxRatio == RATIO_UNSET) {
-            maxRatio = DEFAULT_MAX_RATIO;
+            // Update minRatio and maxRatio only when it is a draggable divider.
+            if (minRatio == RATIO_SYSTEM_DEFAULT) {
+                minRatio = DEFAULT_MIN_RATIO;
+            }
+            if (maxRatio == RATIO_SYSTEM_DEFAULT) {
+                maxRatio = DEFAULT_MAX_RATIO;
+            }
         }
 
         return new DividerAttributes.Builder(dividerAttributes)
@@ -438,7 +465,7 @@
             final Rect taskBounds = mProperties.mConfiguration.windowConfiguration.getBounds();
             mDividerPosition = calculateDividerPosition(
                     event, taskBounds, mRenderer.mDividerWidthPx, mProperties.mDividerAttributes,
-                    mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout);
+                    mProperties.mIsVerticalSplit, calculateMinPosition(), calculateMaxPosition());
             mRenderer.setDividerPosition(mDividerPosition);
             switch (event.getAction()) {
                 case MotionEvent.ACTION_DOWN:
@@ -456,23 +483,27 @@
             }
         }
 
-        // Returns false so that the default button click callback is still triggered, i.e. the
-        // button UI transitions into the "pressed" state.
-        return false;
+        // Returns true to prevent the default button click callback. The button pressed state is
+        // set/unset when starting/finishing dragging.
+        return true;
     }
 
     @GuardedBy("mLock")
     private void onStartDragging() {
         mRenderer.mIsDragging = true;
+        mRenderer.mDragHandle.setPressed(mRenderer.mIsDragging);
         final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
         mRenderer.updateSurface(t);
         mRenderer.showVeils(t);
-        final IBinder decorSurfaceOwner = mDecorSurfaceOwner;
 
         // Callbacks must be executed on the executor to release mLock and prevent deadlocks.
         mCallbackExecutor.execute(() -> {
             mDragEventCallback.onStartDragging(
-                    wct -> setDecorSurfaceBoosted(wct, decorSurfaceOwner, true /* boosted */, t));
+                    wct -> {
+                        synchronized (mLock) {
+                            setDecorSurfaceBoosted(wct, mDecorSurfaceOwner, true /* boosted */, t);
+                        }
+                    });
         });
     }
 
@@ -485,18 +516,62 @@
 
     @GuardedBy("mLock")
     private void onFinishDragging() {
+        mDividerPosition = adjustDividerPositionForSnapPoints(mDividerPosition);
+        mRenderer.setDividerPosition(mDividerPosition);
+
         final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
         mRenderer.updateSurface(t);
         mRenderer.hideVeils(t);
-        final IBinder decorSurfaceOwner = mDecorSurfaceOwner;
 
         // Callbacks must be executed on the executor to release mLock and prevent deadlocks.
+        // mDecorSurfaceOwner may change between here and when the callback is executed,
+        // e.g. when the decor surface owner becomes the secondary container when it is expanded to
+        // fullscreen.
         mCallbackExecutor.execute(() -> {
             mDragEventCallback.onFinishDragging(
                     mTaskId,
-                    wct -> setDecorSurfaceBoosted(wct, decorSurfaceOwner, false /* boosted */, t));
+                    wct -> {
+                        synchronized (mLock) {
+                            setDecorSurfaceBoosted(wct, mDecorSurfaceOwner, false /* boosted */, t);
+                        }
+                    });
         });
         mRenderer.mIsDragging = false;
+        mRenderer.mDragHandle.setPressed(mRenderer.mIsDragging);
+    }
+
+    /**
+     * Returns the divider position adjusted for the min max ratio and fullscreen expansion.
+     *
+     * If the dragging position is above the {@link DividerAttributes#getPrimaryMaxRatio()} or below
+     * {@link DividerAttributes#getPrimaryMinRatio()} and
+     * {@link DividerAttributes#isDraggingToFullscreenAllowed} is {@code true}, the system will
+     * choose a snap algorithm to adjust the ending position to either fully expand one container or
+     * move the divider back to the specified min/max ratio.
+     *
+     * TODO(b/327067596) implement snap algorithm
+     *
+     * The adjusted divider position is in the range of [minPosition, maxPosition] for a split, 0
+     * for expanded right (bottom) container, or task width (height) minus the divider width for
+     * expanded left (top) container.
+     */
+    @GuardedBy("mLock")
+    private int adjustDividerPositionForSnapPoints(int dividerPosition) {
+        final Rect taskBounds = mProperties.mConfiguration.windowConfiguration.getBounds();
+        final int minPosition = calculateMinPosition();
+        final int maxPosition = calculateMaxPosition();
+        final int fullyExpandedPosition = mProperties.mIsVerticalSplit
+                ? taskBounds.right - mRenderer.mDividerWidthPx
+                : taskBounds.bottom - mRenderer.mDividerWidthPx;
+        if (isDraggingToFullscreenAllowed(mProperties.mDividerAttributes)) {
+            if (dividerPosition < minPosition) {
+                return 0;
+            }
+            if (dividerPosition > maxPosition) {
+                return fullyExpandedPosition;
+            }
+        }
+        return Math.clamp(dividerPosition, minPosition, maxPosition);
     }
 
     private static void setDecorSurfaceBoosted(
@@ -520,7 +595,7 @@
     @VisibleForTesting
     static int calculateDividerPosition(@NonNull MotionEvent event, @NonNull Rect taskBounds,
             int dividerWidthPx, @NonNull DividerAttributes dividerAttributes,
-            boolean isVerticalSplit, boolean isReversedLayout) {
+            boolean isVerticalSplit, int minPosition, int maxPosition) {
         // The touch event is in display space. Converting it into the task window space.
         final int touchPositionInTaskSpace = isVerticalSplit
                 ? (int) (event.getRawX()) - taskBounds.left
@@ -530,15 +605,31 @@
         // position is offset by half of the divider width.
         int dividerPosition = touchPositionInTaskSpace - dividerWidthPx / 2;
 
-        // Limit the divider position to the min and max ratios set in DividerAttributes.
-        // TODO(b/327536303) Handle when the divider is dragged to the edge.
-        dividerPosition = Math.max(dividerPosition, calculateMinPosition(
-                taskBounds, dividerWidthPx, dividerAttributes, isVerticalSplit, isReversedLayout));
-        dividerPosition = Math.min(dividerPosition, calculateMaxPosition(
-                taskBounds, dividerWidthPx, dividerAttributes, isVerticalSplit, isReversedLayout));
+        // If dragging to fullscreen is not allowed, limit the divider position to the min and max
+        // ratios set in DividerAttributes. Otherwise, dragging beyond the min and max ratios is
+        // temporarily allowed and the final ratio will be adjusted in onFinishDragging.
+        if (!isDraggingToFullscreenAllowed(dividerAttributes)) {
+            dividerPosition = Math.clamp(dividerPosition, minPosition, maxPosition);
+        }
         return dividerPosition;
     }
 
+    @GuardedBy("mLock")
+    private int calculateMinPosition() {
+        return calculateMinPosition(
+                mProperties.mConfiguration.windowConfiguration.getBounds(),
+                mRenderer.mDividerWidthPx, mProperties.mDividerAttributes,
+                mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout);
+    }
+
+    @GuardedBy("mLock")
+    private int calculateMaxPosition() {
+        return calculateMaxPosition(
+                mProperties.mConfiguration.windowConfiguration.getBounds(),
+                mRenderer.mDividerWidthPx, mProperties.mDividerAttributes,
+                mProperties.mIsVerticalSplit, mProperties.mIsReversedLayout);
+    }
+
     /** Calculates the min position of the divider that the user is allowed to drag to. */
     @VisibleForTesting
     static int calculateMinPosition(@NonNull Rect taskBounds, int dividerWidthPx,
@@ -581,13 +672,24 @@
                     mProperties.mConfiguration.windowConfiguration.getBounds(),
                     mRenderer.mDividerWidthPx,
                     mProperties.mIsVerticalSplit,
-                    mProperties.mIsReversedLayout);
+                    mProperties.mIsReversedLayout,
+                    calculateMinPosition(),
+                    calculateMaxPosition(),
+                    isDraggingToFullscreenAllowed(mProperties.mDividerAttributes));
         }
     }
 
+    private static boolean isDraggingToFullscreenAllowed(
+            @NonNull DividerAttributes dividerAttributes) {
+        // TODO(b/293654166) Use DividerAttributes.isDraggingToFullscreenAllowed when extension is
+        // updated.
+        return true;
+    }
+
     /**
      * Returns the new split ratio of the {@link SplitContainer} based on the current divider
      * position.
+     *
      * @param topSplitContainer the {@link SplitContainer} for which to compute the split ratio.
      * @param dividerPosition the divider position. See {@link #mDividerPosition}.
      * @param taskBounds the task bounds
@@ -599,7 +701,9 @@
      *                         bottom-to-top. If {@code false}, the split is not reversed, i.e.
      *                         left-to-right or top-to-bottom. See
      *                         {@link SplitAttributesHelper#isReversedLayout}
-     * @return the computed split ratio of the primary container.
+     * @return the computed split ratio of the primary container. If the primary container is fully
+     * expanded, {@link #RATIO_EXPANDED_PRIMARY} is returned. If the secondary container is fully
+     * expanded, {@link #RATIO_EXPANDED_SECONDARY} is returned.
      */
     @VisibleForTesting
     static float calculateNewSplitRatio(
@@ -608,15 +712,33 @@
             @NonNull Rect taskBounds,
             int dividerWidthPx,
             boolean isVerticalSplit,
-            boolean isReversedLayout) {
+            boolean isReversedLayout,
+            int minPosition,
+            int maxPosition,
+            boolean isDraggingToFullscreenAllowed) {
+
+        // Handle the fully expanded cases.
+        if (isDraggingToFullscreenAllowed) {
+            // The divider position is already adjusted by the snap algorithm in onFinishDragging.
+            // If the divider position is not in the range [minPosition, maxPosition], then one of
+            // the containers is fully expanded.
+            if (dividerPosition < minPosition) {
+                return isReversedLayout ? RATIO_EXPANDED_PRIMARY : RATIO_EXPANDED_SECONDARY;
+            }
+            if (dividerPosition > maxPosition) {
+                return isReversedLayout ? RATIO_EXPANDED_SECONDARY : RATIO_EXPANDED_PRIMARY;
+            }
+        } else {
+            dividerPosition = Math.clamp(dividerPosition, minPosition, maxPosition);
+        }
+
+        final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer();
+        final Rect origPrimaryBounds = primaryContainer.getLastRequestedBounds();
         final int usableSize = isVerticalSplit
                 ? taskBounds.width() - dividerWidthPx
                 : taskBounds.height() - dividerWidthPx;
 
-        final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer();
-        final Rect origPrimaryBounds = primaryContainer.getLastRequestedBounds();
-
-        float newRatio;
+        final float newRatio;
         if (isVerticalSplit) {
             final int newPrimaryWidth = isReversedLayout
                     ? (origPrimaryBounds.right - (dividerPosition + dividerWidthPx))
@@ -677,6 +799,7 @@
 
         private final int mDisplayId;
         private final boolean mIsReversedLayout;
+        private final boolean mIsDraggableExpandType;
 
         @VisibleForTesting
         Properties(
@@ -686,7 +809,8 @@
                 int initialDividerPosition,
                 boolean isVerticalSplit,
                 boolean isReversedLayout,
-                int displayId) {
+                int displayId,
+                boolean isDraggableExpandType) {
             mConfiguration = configuration;
             mDividerAttributes = dividerAttributes;
             mDecorSurface = decorSurface;
@@ -694,6 +818,7 @@
             mIsVerticalSplit = isVerticalSplit;
             mIsReversedLayout = isReversedLayout;
             mDisplayId = displayId;
+            mIsDraggableExpandType = isDraggableExpandType;
         }
 
         /**
@@ -714,7 +839,8 @@
                     && a.mInitialDividerPosition == b.mInitialDividerPosition
                     && a.mIsVerticalSplit == b.mIsVerticalSplit
                     && a.mDisplayId == b.mDisplayId
-                    && a.mIsReversedLayout == b.mIsReversedLayout;
+                    && a.mIsReversedLayout == b.mIsReversedLayout
+                    && a.mIsDraggableExpandType == b.mIsDraggableExpandType;
         }
 
         private static boolean areSameSurfaces(
@@ -761,6 +887,7 @@
         private SurfaceControl mSecondaryVeil;
         private boolean mIsDragging;
         private int mDividerPosition;
+        private View mDragHandle;
 
         private Renderer(@NonNull Properties properties, @NonNull View.OnTouchListener listener) {
             mProperties = properties;
@@ -857,6 +984,7 @@
                             PixelFormat.TRANSLUCENT);
             lp.setTitle(WINDOW_NAME);
             mViewHost.setView(mDividerLayout, lp);
+            mViewHost.relayout(lp);
         }
 
         /**
@@ -867,7 +995,12 @@
          */
         private void updateDivider(@NonNull SurfaceControl.Transaction t) {
             mDividerLayout.removeAllViews();
-            mDividerLayout.setBackgroundColor(DEFAULT_DIVIDER_COLOR.toArgb());
+            if (mProperties.mIsDraggableExpandType) {
+                // If a container is fully expanded, the divider overlays on the expanded container.
+                mDividerLayout.setBackgroundColor(Color.TRANSPARENT);
+            } else {
+                mDividerLayout.setBackgroundColor(mProperties.mDividerAttributes.getDividerColor());
+            }
             if (mProperties.mDividerAttributes.getDividerType()
                     == DividerAttributes.DIVIDER_TYPE_DRAGGABLE) {
                 createVeils();
@@ -916,6 +1049,7 @@
             }
 
             button.setOnTouchListener(mListener);
+            mDragHandle = button;
             mDividerLayout.addView(button);
         }
 
@@ -928,7 +1062,7 @@
                     .setHidden(!visible)
                     .setCallsite("DividerManager.createChildSurface")
                     .setBufferSize(bounds.width(), bounds.height())
-                    .setColorLayer()
+                    .setEffectLayer()
                     .build();
         }
 
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 32f2d67..a23a4741 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -354,14 +354,14 @@
     void setTaskFragmentIsolatedNavigation(@NonNull WindowContainerTransaction wct,
             @NonNull IBinder fragmentToken, boolean isolatedNav) {
         final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
-                OP_TYPE_SET_ISOLATED_NAVIGATION).setIsolatedNav(isolatedNav).build();
+                OP_TYPE_SET_ISOLATED_NAVIGATION).setBooleanValue(isolatedNav).build();
         wct.addTaskFragmentOperation(fragmentToken, operation);
     }
 
     void setTaskFragmentDimOnTask(@NonNull WindowContainerTransaction wct,
             @NonNull IBinder fragmentToken, boolean dimOnTask) {
         final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
-                OP_TYPE_SET_DIM_ON_TASK).setDimOnTask(dimOnTask).build();
+                OP_TYPE_SET_DIM_ON_TASK).setBooleanValue(dimOnTask).build();
         wct.addTaskFragmentOperation(fragmentToken, operation);
     }
 
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitAttributesHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitAttributesHelper.java
index 042a68a6..4541a84 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitAttributesHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitAttributesHelper.java
@@ -20,6 +20,7 @@
 import android.view.View;
 
 import androidx.annotation.NonNull;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
 
 /** Helper functions for {@link SplitAttributes} */
 class SplitAttributesHelper {
@@ -43,4 +44,17 @@
                         "Invalid layout direction:" + splitAttributes.getLayoutDirection());
         }
     }
+
+    /**
+     * Returns whether the {@link SplitAttributes} is an {@link ExpandContainersSplitType} and it
+     * should show a draggable handle that allows the user to drag and restore it into a split.
+     * This state is a result of user dragging the divider to fully expand the secondary container.
+     */
+    static boolean isDraggableExpandType(@NonNull SplitAttributes splitAttributes) {
+        final DividerAttributes dividerAttributes = splitAttributes.getDividerAttributes();
+        return splitAttributes.getSplitType() instanceof ExpandContainersSplitType
+                && dividerAttributes != null
+                && dividerAttributes.getDividerType() == DividerAttributes.DIVIDER_TYPE_DRAGGABLE;
+
+    }
 }
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 b9b86f0..46a3e7f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
 import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT;
 import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
@@ -115,6 +116,11 @@
     static final boolean ENABLE_SHELL_TRANSITIONS =
             SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
 
+    // TODO(b/243518738): Move to WM Extensions if we have requirement of overlay without
+    //  association. It's not set in WM Extensions nor Wm Jetpack library currently.
+    private static final String KEY_OVERLAY_ASSOCIATE_WITH_LAUNCHING_ACTIVITY =
+            "androidx.window.extensions.embedding.shouldAssociateWithLaunchingActivity";
+
     @VisibleForTesting
     @GuardedBy("mLock")
     final SplitPresenter mPresenter;
@@ -855,9 +861,9 @@
         // container update.
         updateDivider(wct, taskContainer);
 
-        // If the last direct activity of the host task is dismissed and the overlay container is
-        // the only taskFragment, the overlay container should also be dismissed.
-        dismissOverlayContainerIfNeeded(wct, taskContainer);
+        // If the last direct activity of the host task is dismissed and there's an always-on-top
+        // overlay container in the task, the overlay container should also be dismissed.
+        dismissAlwaysOnTopOverlayIfNeeded(wct, taskContainer);
 
         if (!shouldUpdateContainer) {
             return;
@@ -1405,9 +1411,27 @@
         launchPlaceholderIfNecessary(wct, activity, false /* isOnCreated */);
     }
 
+    @GuardedBy("mLock")
+    private void onActivityPaused(@NonNull WindowContainerTransaction wct,
+                                  @NonNull Activity activity) {
+        // Checks if there's any finishing activity in paused state associate with an overlay
+        // container. #OnActivityPostDestroyed is a very late signal, which is called after activity
+        // is not visible and the next activity shows on screen.
+        if (!activity.isFinishing()) {
+            // onPaused is triggered without finishing. Early return.
+            return;
+        }
+        // Check if we should dismiss the overlay container with this finishing activity.
+        final IBinder activityToken = activity.getActivityToken();
+        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
+            mTaskContainers.valueAt(i).onFinishingActivityPaused(wct, activityToken);
+        }
+        updateCallbackIfNecessary();
+    }
+
     @VisibleForTesting
     @GuardedBy("mLock")
-    void onActivityDestroyed(@NonNull Activity activity) {
+    void onActivityDestroyed(@NonNull WindowContainerTransaction wct, @NonNull Activity activity) {
         if (!activity.isFinishing()) {
             // onDestroyed is triggered without finishing. This happens when the activity is
             // relaunched. In this case, we don't want to cleanup the record.
@@ -1417,7 +1441,7 @@
         // organizer.
         final IBinder activityToken = activity.getActivityToken();
         for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
-            mTaskContainers.valueAt(i).onActivityDestroyed(activityToken);
+            mTaskContainers.valueAt(i).onActivityDestroyed(wct, activityToken);
         }
         // We didn't trigger the callback if there were any pending appeared activities, so check
         // again after the pending is removed.
@@ -1597,7 +1621,8 @@
             @Nullable Activity launchingActivity) {
         return createEmptyContainer(wct, intent, taskId,
                 new ActivityStackAttributes.Builder().build(), launchingActivity,
-                null /* overlayTag */, null /* launchOptions */);
+                null /* overlayTag */, null /* launchOptions */,
+                false /* shouldAssociateWithLaunchingActivity */);
     }
 
     /**
@@ -1612,7 +1637,7 @@
             @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
             @NonNull ActivityStackAttributes activityStackAttributes,
             @Nullable Activity launchingActivity, @Nullable String overlayTag,
-            @Nullable Bundle launchOptions) {
+            @Nullable Bundle launchOptions, boolean associateLaunchingActivity) {
         // We need an activity in the organizer process in the same Task to use as the owner
         // activity, as well as to get the Task window info.
         final Activity activityInTask;
@@ -1630,7 +1655,7 @@
         }
         final TaskFragmentContainer container = newContainer(null /* pendingAppearedActivity */,
                 intent, activityInTask, taskId, null /* pairedPrimaryContainer*/, overlayTag,
-                launchOptions);
+                launchOptions, associateLaunchingActivity);
         final IBinder taskFragmentToken = container.getTaskFragmentToken();
         // Note that taskContainer will not exist before calling #newContainer if the container
         // is the first embedded TF in the task.
@@ -1722,7 +1747,7 @@
             @NonNull Activity activityInTask, int taskId) {
         return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
                 activityInTask, taskId, null /* pairedPrimaryContainer */, null /* tag */,
-                null /* launchOptions */);
+                null /* launchOptions */, false /* associateLaunchingActivity */);
     }
 
     @GuardedBy("mLock")
@@ -1730,7 +1755,7 @@
             @NonNull Activity activityInTask, int taskId) {
         return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
                 activityInTask, taskId, null /* pairedPrimaryContainer */, null /* tag */,
-                null /* launchOptions */);
+                null /* launchOptions */, false /* associateLaunchingActivity */);
     }
 
     @GuardedBy("mLock")
@@ -1739,7 +1764,7 @@
             @NonNull TaskFragmentContainer pairedPrimaryContainer) {
         return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
                 activityInTask, taskId, pairedPrimaryContainer, null /* tag */,
-                null /* launchOptions */);
+                null /* launchOptions */, false /* associateLaunchingActivity */);
     }
 
     /**
@@ -1751,19 +1776,21 @@
      * @param activityInTask          activity in the same Task so that we can get the Task bounds
      *                                if needed.
      * @param taskId                  parent Task of the new TaskFragment.
-     * @param pairedPrimaryContainer  the paired primary {@link TaskFragmentContainer}. When it is
+     * @param pairedContainer  the paired primary {@link TaskFragmentContainer}. When it is
      *                                set, the new container will be added right above it.
      * @param overlayTag              The tag for the new created overlay container. It must be
      *                                needed if {@code isOverlay} is {@code true}. Otherwise,
      *                                it should be {@code null}.
      * @param launchOptions           The launch options bundle to create a container. Must be
      *                                specified for overlay container.
+     * @param associateLaunchingActivity {@code true} to indicate this overlay container
+     *                                   should associate with launching activity.
      */
     @GuardedBy("mLock")
     TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
             @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId,
-            @Nullable TaskFragmentContainer pairedPrimaryContainer, @Nullable String overlayTag,
-            @Nullable Bundle launchOptions) {
+            @Nullable TaskFragmentContainer pairedContainer, @Nullable String overlayTag,
+            @Nullable Bundle launchOptions, boolean associateLaunchingActivity) {
         if (activityInTask == null) {
             throw new IllegalArgumentException("activityInTask must not be null,");
         }
@@ -1773,8 +1800,8 @@
         }
         final TaskContainer taskContainer = mTaskContainers.get(taskId);
         final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
-                pendingAppearedIntent, taskContainer, this, pairedPrimaryContainer, overlayTag,
-                launchOptions);
+                pendingAppearedIntent, taskContainer, this, pairedContainer, overlayTag,
+                launchOptions, associateLaunchingActivity ? activityInTask : null);
         return container;
     }
 
@@ -1963,7 +1990,7 @@
             @NonNull TaskFragmentContainer container) {
         final TaskContainer taskContainer = container.getTaskContainer();
 
-        if (dismissOverlayContainerIfNeeded(wct, taskContainer)) {
+        if (dismissAlwaysOnTopOverlayIfNeeded(wct, taskContainer)) {
             return;
         }
 
@@ -1987,22 +2014,27 @@
         }
     }
 
-    /** Dismisses the overlay container in the {@code taskContainer} if needed. */
+    /**
+     * Dismisses {@link TaskFragmentContainer#isAlwaysOnTopOverlay()} in the {@code taskContainer}
+     * if needed.
+     */
     @GuardedBy("mLock")
-    private boolean dismissOverlayContainerIfNeeded(@NonNull WindowContainerTransaction wct,
-            @NonNull TaskContainer taskContainer) {
-        final TaskFragmentContainer overlayContainer = taskContainer.getOverlayContainer();
-        if (overlayContainer == null) {
+    private boolean dismissAlwaysOnTopOverlayIfNeeded(@NonNull WindowContainerTransaction wct,
+                                                      @NonNull TaskContainer taskContainer) {
+        // Dismiss always-on-top overlay container if it's the only container in the task and
+        // there's no direct activity in the parent task.
+        final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers();
+        if (containers.size() != 1 || taskContainer.hasDirectActivity()) {
             return false;
         }
-        // Dismiss the overlay container if it's the only container in the task and there's no
-        // direct activity in the parent task.
-        if (taskContainer.getTaskFragmentContainers().size() == 1
-                && !taskContainer.hasDirectActivity()) {
-            mPresenter.cleanupContainer(wct, overlayContainer, false /* shouldFinishDependant */);
-            return true;
+
+        final TaskFragmentContainer container = containers.getLast();
+        if (!container.isAlwaysOnTopOverlay()) {
+            return false;
         }
-        return false;
+
+        mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependant */);
+        return true;
     }
 
     /**
@@ -2141,6 +2173,10 @@
             return false;
         }
 
+        if (container != null && container.getTaskContainer().isPlaceholderRuleSuppressed()) {
+            return false;
+        }
+
         final TaskContainer.TaskProperties taskProperties = mPresenter.getTaskProperties(activity);
         final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(activity,
                 placeholderRule.getPlaceholderIntent());
@@ -2236,6 +2272,9 @@
         if (SplitPresenter.shouldShowSplit(splitAttributes)) {
             return false;
         }
+        if (SplitPresenter.shouldShowPlaceholderWhenExpanded(splitAttributes)) {
+            return false;
+        }
 
         mTransactionManager.getCurrentTransactionRecord()
                 .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
@@ -2586,25 +2625,42 @@
     /**
      * Gets all overlay containers from all tasks in this process, or an empty list if there's
      * no overlay container.
-     * <p>
-     * Note that we only support one overlay container for each task, but an app could have multiple
-     * tasks.
      */
     @VisibleForTesting
     @GuardedBy("mLock")
     @NonNull
-    List<TaskFragmentContainer> getAllOverlayTaskFragmentContainers() {
+    List<TaskFragmentContainer> getAllNonFinishingOverlayContainers() {
         final List<TaskFragmentContainer> overlayContainers = new ArrayList<>();
         for (int i = 0; i < mTaskContainers.size(); i++) {
             final TaskContainer taskContainer = mTaskContainers.valueAt(i);
-            final TaskFragmentContainer overlayContainer = taskContainer.getOverlayContainer();
-            if (overlayContainer != null) {
-                overlayContainers.add(overlayContainer);
-            }
+            final List<TaskFragmentContainer> overlayContainersPerTask = taskContainer
+                    .getTaskFragmentContainers()
+                    .stream()
+                    .filter(c -> c.isOverlay() && !c.isFinished())
+                    .toList();
+            overlayContainers.addAll(overlayContainersPerTask);
         }
         return overlayContainers;
     }
 
+    /**
+     * Creates an overlay container or updates a visible overlay container if its
+     * {@link TaskFragmentContainer#getTaskId()}, {@link TaskFragmentContainer#getOverlayTag()}
+     * and {@link TaskFragmentContainer#getAssociatedActivityToken()} matches.
+     * <p>
+     * This method will also dismiss any existing overlay container if:
+     * <ul>
+     *   <li>it's visible but not meet the criteria to update overlay</li>
+     *   <li>{@link TaskFragmentContainer#getOverlayTag()} matches but not meet the criteria to
+     *   update overlay</li>
+     * </ul>
+     *
+     * @param wct the {@link WindowContainerTransaction}
+     * @param options the {@link ActivityOptions} to launch the overlay
+     * @param intent the intent of activity to launch
+     * @param launchActivity the activity to launch the overlay container
+     * @return the overlay container
+     */
     @VisibleForTesting
     // Suppress GuardedBy warning because lint ask to mark this method as
     // @GuardedBy(container.mController.mLock), which is mLock itself
@@ -2615,8 +2671,10 @@
             @NonNull WindowContainerTransaction wct, @NonNull Bundle options,
             @NonNull Intent intent, @NonNull Activity launchActivity) {
         final List<TaskFragmentContainer> overlayContainers =
-                getAllOverlayTaskFragmentContainers();
+                getAllNonFinishingOverlayContainers();
         final String overlayTag = Objects.requireNonNull(options.getString(KEY_OVERLAY_TAG));
+        final boolean associateLaunchingActivity = options
+                .getBoolean(KEY_OVERLAY_ASSOCIATE_WITH_LAUNCHING_ACTIVITY, true);
 
         // If the requested bounds of OverlayCreateParams are smaller than minimum dimensions
         // specified by Intent, expand the overlay container to fill the parent task instead.
@@ -2637,35 +2695,91 @@
         final int taskId = getTaskId(launchActivity);
         if (!overlayContainers.isEmpty()) {
             for (final TaskFragmentContainer overlayContainer : overlayContainers) {
-                if (!overlayTag.equals(overlayContainer.getOverlayTag())
-                        && taskId == overlayContainer.getTaskId()) {
-                    // If there's an overlay container with different tag shown in the same
-                    // task, dismiss the existing overlay container.
-                    mPresenter.cleanupContainer(wct, overlayContainer,
-                            false /* shouldFinishDependant */);
-                }
-                if (overlayTag.equals(overlayContainer.getOverlayTag())
-                        && taskId != overlayContainer.getTaskId()) {
+                final boolean isTopNonFinishingOverlay = overlayContainer.equals(
+                        overlayContainer.getTaskContainer().getTopNonFinishingTaskFragmentContainer(
+                                true /* includePin */, true /* includeOverlay */));
+                if (taskId != overlayContainer.getTaskId()) {
                     // If there's an overlay container with same tag in a different task,
                     // dismiss the overlay container since the tag must be unique per process.
+                    if (overlayTag.equals(overlayContainer.getOverlayTag())) {
+                        Log.w(TAG, "The overlay container with tag:"
+                                + overlayContainer.getOverlayTag() + " is dismissed because"
+                                + " there's an existing overlay container with the same tag but"
+                                + " different task ID:" + overlayContainer.getTaskId() + ". "
+                                + "The new associated activity is " + launchActivity);
+                        mPresenter.cleanupContainer(wct, overlayContainer,
+                                false /* shouldFinishDependant */);
+                    }
+                    continue;
+                }
+                if (!overlayTag.equals(overlayContainer.getOverlayTag())) {
+                    // If there's an overlay container with different tag on top in the same
+                    // task, dismiss the existing overlay container.
+                    if (isTopNonFinishingOverlay) {
+                        mPresenter.cleanupContainer(wct, overlayContainer,
+                                false /* shouldFinishDependant */);
+                    }
+                    continue;
+                }
+                // The overlay container has the same tag and task ID with the new launching
+                // overlay container.
+                if (!isTopNonFinishingOverlay) {
+                    // Dismiss the invisible overlay container regardless of activity
+                    // association if it collides the tag of new launched overlay container .
+                    Log.w(TAG, "The invisible overlay container with tag:"
+                            + overlayContainer.getOverlayTag() + " is dismissed because"
+                            + " there's a launching overlay container with the same tag."
+                            + " The new associated activity is " + launchActivity);
                     mPresenter.cleanupContainer(wct, overlayContainer,
                             false /* shouldFinishDependant */);
+                    continue;
                 }
-                if (overlayTag.equals(overlayContainer.getOverlayTag())
-                        && taskId == overlayContainer.getTaskId()) {
-                    mPresenter.applyActivityStackAttributes(wct, overlayContainer, attrs,
-                            getMinDimensions(intent));
-                    // We can just return the updated overlay container and don't need to
-                    // check other condition since we only have one OverlayCreateParams, and
-                    // if the tag and task are matched, it's impossible to match another task
-                    // or tag since tags and tasks are all unique.
-                    return overlayContainer;
+                // Requesting an always-on-top overlay.
+                if (!associateLaunchingActivity) {
+                    if (overlayContainer.isAssociatedWithActivity()) {
+                        // Dismiss the overlay container since it has associated with an activity.
+                        Log.w(TAG, "The overlay container with tag:"
+                                + overlayContainer.getOverlayTag() + " is dismissed because"
+                                + " there's an existing overlay container with the same tag but"
+                                + " different associated launching activity. The overlay container"
+                                + " doesn't associate with any activity.");
+                        mPresenter.cleanupContainer(wct, overlayContainer,
+                                false /* shouldFinishDependant */);
+                        continue;
+                    } else {
+                        // The existing overlay container doesn't associate an activity as well.
+                        // Just update the overlay and return.
+                        // Note that going to this condition means the tag, task ID matches a
+                        // visible always-on-top overlay, and won't dismiss any overlay any more.
+                        mPresenter.applyActivityStackAttributes(wct, overlayContainer, attrs,
+                                getMinDimensions(intent));
+                        return overlayContainer;
+                    }
                 }
+                if (launchActivity.getActivityToken()
+                        != overlayContainer.getAssociatedActivityToken()) {
+                    Log.w(TAG, "The overlay container with tag:"
+                            + overlayContainer.getOverlayTag() + " is dismissed because"
+                            + " there's an existing overlay container with the same tag but"
+                            + " different associated launching activity. The new associated"
+                            + " activity is " + launchActivity);
+                    // The associated activity must be the same, or it will be dismissed.
+                    mPresenter.cleanupContainer(wct, overlayContainer,
+                            false /* shouldFinishDependant */);
+                    continue;
+                }
+                // Reaching here means the launching activity launch an overlay container with the
+                // same task ID, tag, while there's a previously launching visible overlay
+                // container. We'll regard it as updating the existing overlay container.
+                mPresenter.applyActivityStackAttributes(wct, overlayContainer, attrs,
+                        getMinDimensions(intent));
+                return overlayContainer;
+
             }
         }
         // Launch the overlay container to the task with taskId.
         return createEmptyContainer(wct, intent, taskId, attrs, launchActivity, overlayTag,
-                options);
+                options, associateLaunchingActivity);
     }
 
     private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter {
@@ -2754,6 +2868,23 @@
         }
 
         @Override
+        public void onActivityPostPaused(@NonNull Activity activity) {
+            if (activity.isChild()) {
+                // Skip Activity that is child of another Activity (ActivityGroup) because it's
+                // window will just be a child of the parent Activity window.
+                return;
+            }
+            synchronized (mLock) {
+                final TransactionRecord transactionRecord = mTransactionManager
+                        .startNewTransaction();
+                transactionRecord.setOriginType(TRANSIT_CLOSE);
+                SplitController.this.onActivityPaused(
+                        transactionRecord.getTransaction(), activity);
+                transactionRecord.apply(false /* shouldApplyIndependently */);
+            }
+        }
+
+        @Override
         public void onActivityPostDestroyed(@NonNull Activity activity) {
             if (activity.isChild()) {
                 // Skip Activity that is child of another Activity (ActivityGroup) because it's
@@ -2761,7 +2892,12 @@
                 return;
             }
             synchronized (mLock) {
-                SplitController.this.onActivityDestroyed(activity);
+                final TransactionRecord transactionRecord = mTransactionManager
+                        .startNewTransaction();
+                transactionRecord.setOriginType(TRANSIT_CLOSE);
+                SplitController.this.onActivityDestroyed(
+                        transactionRecord.getTransaction(), activity);
+                transactionRecord.apply(false /* shouldApplyIndependently */);
             }
         }
     }
@@ -3111,7 +3247,12 @@
             if (taskContainer != null) {
                 final DividerPresenter dividerPresenter =
                         mDividerPresenters.get(taskContainer.getTaskId());
-                taskContainer.updateTopSplitContainerForDivider(dividerPresenter);
+                final List<TaskFragmentContainer> containersToFinish = new ArrayList<>();
+                taskContainer.updateTopSplitContainerForDivider(
+                        dividerPresenter, containersToFinish);
+                for (final TaskFragmentContainer container : containersToFinish) {
+                    mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
+                }
                 updateContainersInTask(wct, taskContainer);
             }
             action.accept(wct);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 0d31266..6231ea0 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -467,6 +467,11 @@
             reorderTaskFragmentToFront(wct,
                     pinnedContainer.getSecondaryContainer().getTaskFragmentToken());
         }
+        final TaskFragmentContainer alwaysOnTopOverlayContainer = container.getTaskContainer()
+                .getAlwaysOnTopOverlayContainer();
+        if (alwaysOnTopOverlayContainer != null) {
+            reorderTaskFragmentToFront(wct, alwaysOnTopOverlayContainer.getTaskFragmentToken());
+        }
     }
 
     @Override
@@ -565,7 +570,7 @@
 
     @Override
     void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder primary,
-            @Nullable IBinder secondary) {
+                                  @Nullable IBinder secondary) {
         final TaskFragmentContainer container = mController.getContainer(primary);
         if (container == null) {
             throw new IllegalStateException("setCompanionTaskFragment on TaskFragment that is"
@@ -590,7 +595,12 @@
         final Rect relativeBounds = sanitizeBounds(attributes.getRelativeBounds(), minDimensions,
                 taskBounds);
         final boolean isFillParent = relativeBounds.isEmpty();
-        final boolean isIsolatedNavigated = !isFillParent && container.isOverlay();
+        // Note that we only set isolated navigation for overlay container without activity
+        // association. Activity will be launched to an expanded container on top of the overlay
+        // if the overlay is associated with an activity. Thus, an overlay with activity association
+        // will never be isolated navigated.
+        final boolean isIsolatedNavigated = container.isOverlay()
+                && !container.isAssociatedWithActivity() && !isFillParent;
         final boolean dimOnTask = !isFillParent
                 && attributes.getWindowAttributes().getDimAreaBehavior() == DIM_AREA_ON_TASK
                 && Flags.fullscreenDimFlag();
@@ -716,6 +726,12 @@
         return !(splitAttributes.getSplitType() instanceof ExpandContainersSplitType);
     }
 
+    static boolean shouldShowPlaceholderWhenExpanded(@NonNull SplitAttributes splitAttributes) {
+        // The placeholder should be kept if the expand split type is a result of user dragging
+        // the divider.
+        return SplitAttributesHelper.isDraggableExpandType(splitAttributes);
+    }
+
     @NonNull
     SplitAttributes computeSplitAttributes(@NonNull TaskProperties taskProperties,
             @NonNull SplitRule rule, @NonNull SplitAttributes defaultSplitAttributes,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index a215bdf..fdf0910 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -22,6 +22,9 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.inMultiWindowMode;
 
+import static androidx.window.extensions.embedding.DividerPresenter.RATIO_EXPANDED_PRIMARY;
+import static androidx.window.extensions.embedding.DividerPresenter.RATIO_EXPANDED_SECONDARY;
+
 import android.app.Activity;
 import android.app.ActivityClient;
 import android.app.WindowConfiguration;
@@ -40,6 +43,9 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
+import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -64,9 +70,11 @@
     @Nullable
     private SplitPinContainer mSplitPinContainer;
 
-    /** The overlay container in this Task. */
+    /**
+     * The {@link TaskFragmentContainer#isAlwaysOnTopOverlay()} in the Task.
+     */
     @Nullable
-    private TaskFragmentContainer mOverlayContainer;
+    private TaskFragmentContainer mAlwaysOnTopOverlayContainer;
 
     @NonNull
     private final Configuration mConfiguration;
@@ -89,6 +97,25 @@
     final Set<IBinder> mFinishedContainer = new ArraySet<>();
 
     /**
+     * The {@link RatioSplitType} that will be applied to newly added containers. This is to ensure
+     * the required UX that, after user dragging the divider, the split ratio is persistent after
+     * launching a new activity into a new TaskFragment in the same Task.
+     */
+    private RatioSplitType mOverrideSplitType;
+
+    /**
+     * If {@code true}, suppress the placeholder rules in the {@link TaskContainer}.
+     * <p>
+     * This is used in case the user drags the divider to fully expand the primary container and
+     * dismiss the secondary container while a {@link SplitPlaceholderRule} is used. Without this
+     * flag, after dismissing the secondary container, a placeholder will be launched again.
+     * <p>
+     * This flag is set true when the primary container is fully expanded and cleared when a new
+     * split is added to the {@link TaskContainer}.
+     */
+    private boolean mPlaceholderRuleSuppressed;
+
+    /**
      * The {@link TaskContainer} constructor
      *
      * @param taskId         The ID of the Task, which must match {@link Activity#getTaskId()} with
@@ -211,10 +238,19 @@
         return mContainers.isEmpty() && mFinishedContainer.isEmpty();
     }
 
-    /** Called when the activity is destroyed. */
-    void onActivityDestroyed(@NonNull IBinder activityToken) {
+    /** Called when the activity {@link Activity#isFinishing()} and paused. */
+    void onFinishingActivityPaused(@NonNull WindowContainerTransaction wct,
+                                   @NonNull IBinder activityToken) {
         for (TaskFragmentContainer container : mContainers) {
-            container.onActivityDestroyed(activityToken);
+            container.onFinishingActivityPaused(wct, activityToken);
+        }
+    }
+
+    /** Called when the activity is destroyed. */
+    void onActivityDestroyed(@NonNull WindowContainerTransaction wct,
+                             @NonNull IBinder activityToken) {
+        for (TaskFragmentContainer container : mContainers) {
+            container.onActivityDestroyed(wct, activityToken);
         }
     }
 
@@ -282,10 +318,12 @@
         return null;
     }
 
-    /** Returns the overlay container in the task, or {@code null} if it doesn't exist. */
+    /**
+     * Returns the always-on-top overlay container in the task, or {@code null} if it doesn't exist.
+     */
     @Nullable
-    TaskFragmentContainer getOverlayContainer() {
-        return mOverlayContainer;
+    TaskFragmentContainer getAlwaysOnTopOverlayContainer() {
+        return mAlwaysOnTopOverlayContainer;
     }
 
     int indexOf(@NonNull TaskFragmentContainer child) {
@@ -313,6 +351,11 @@
     }
 
     void addSplitContainer(@NonNull SplitContainer splitContainer) {
+        // Reset the placeholder rule suppression when a new split container is added.
+        mPlaceholderRuleSuppressed = false;
+
+        applyOverrideSplitTypeIfNeeded(splitContainer);
+
         if (splitContainer instanceof SplitPinContainer) {
             mSplitPinContainer = (SplitPinContainer) splitContainer;
             mSplitContainers.add(splitContainer);
@@ -327,6 +370,39 @@
         }
     }
 
+    boolean isPlaceholderRuleSuppressed() {
+        return mPlaceholderRuleSuppressed;
+    }
+
+    // If there is an override SplitType due to user dragging the divider, the split ratio should
+    // be applied to newly added SplitContainers.
+    private void applyOverrideSplitTypeIfNeeded(@NonNull SplitContainer splitContainer) {
+        if (mOverrideSplitType == null) {
+            return;
+        }
+        final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
+        final DividerAttributes dividerAttributes = splitAttributes.getDividerAttributes();
+        if (!(splitAttributes.getSplitType() instanceof RatioSplitType)) {
+            // Skip if the original split type is not a ratio type.
+            return;
+        }
+        if (dividerAttributes == null
+                || dividerAttributes.getDividerType() != DividerAttributes.DIVIDER_TYPE_DRAGGABLE) {
+            // Skip if the split does not have a draggable divider.
+            return;
+        }
+        updateDefaultSplitAttributes(splitContainer, mOverrideSplitType);
+    }
+
+    private static void updateDefaultSplitAttributes(
+            @NonNull SplitContainer splitContainer, @NonNull SplitType overrideSplitType) {
+        splitContainer.updateDefaultSplitAttributes(
+                new SplitAttributes.Builder(splitContainer.getDefaultSplitAttributes())
+                        .setSplitType(overrideSplitType)
+                        .build()
+        );
+    }
+
     void removeSplitContainers(@NonNull List<SplitContainer> containers) {
         mSplitContainers.removeAll(containers);
     }
@@ -398,18 +474,47 @@
         return mContainers;
     }
 
-    void updateTopSplitContainerForDivider(@NonNull DividerPresenter dividerPresenter) {
+    void updateTopSplitContainerForDivider(
+            @NonNull DividerPresenter dividerPresenter,
+            @NonNull List<TaskFragmentContainer> outContainersToFinish) {
         final SplitContainer topSplitContainer = getTopNonFinishingSplitContainer();
         if (topSplitContainer == null) {
             return;
         }
-
+        final TaskFragmentContainer primaryContainer = topSplitContainer.getPrimaryContainer();
         final float newRatio = dividerPresenter.calculateNewSplitRatio(topSplitContainer);
-        topSplitContainer.updateDefaultSplitAttributes(
-                new SplitAttributes.Builder(topSplitContainer.getDefaultSplitAttributes())
-                        .setSplitType(new SplitAttributes.SplitType.RatioSplitType(newRatio))
-                        .build()
-        );
+
+        // If the primary container is fully expanded, we should finish all the associated
+        // secondary containers.
+        if (newRatio == RATIO_EXPANDED_PRIMARY) {
+            for (final SplitContainer splitContainer : mSplitContainers) {
+                if (primaryContainer == splitContainer.getPrimaryContainer()) {
+                    outContainersToFinish.add(splitContainer.getSecondaryContainer());
+                }
+            }
+
+            // Temporarily suppress the placeholder rule in the TaskContainer. This will be restored
+            // if a new split is added into the TaskContainer.
+            mPlaceholderRuleSuppressed = true;
+
+            mOverrideSplitType = null;
+            return;
+        }
+
+        final SplitType newSplitType;
+        if (newRatio == RATIO_EXPANDED_SECONDARY) {
+            newSplitType = new ExpandContainersSplitType();
+            // We do not want to apply ExpandContainersSplitType to new split containers.
+            mOverrideSplitType = null;
+        } else {
+            // We save the override RatioSplitType and apply to new split containers.
+            newSplitType = mOverrideSplitType = new RatioSplitType(newRatio);
+        }
+        for (final SplitContainer splitContainer : mSplitContainers) {
+            if (primaryContainer == splitContainer.getPrimaryContainer()) {
+                updateDefaultSplitAttributes(splitContainer, newSplitType);
+            }
+        }
     }
 
     @Nullable
@@ -430,7 +535,21 @@
         updateSplitPinContainerIfNecessary();
         // Update overlay container after split pin container since the overlay should be on top of
         // pin container.
-        updateOverlayContainerIfNecessary();
+        updateAlwaysOnTopOverlayIfNecessary();
+    }
+
+    private void updateAlwaysOnTopOverlayIfNecessary() {
+        final List<TaskFragmentContainer> alwaysOnTopOverlays = mContainers
+                .stream().filter(TaskFragmentContainer::isAlwaysOnTopOverlay).toList();
+        if (alwaysOnTopOverlays.size() > 1) {
+            throw new IllegalStateException("There must be at most one always-on-top overlay "
+                    + "container per Task");
+        }
+        mAlwaysOnTopOverlayContainer = alwaysOnTopOverlays.isEmpty()
+                ? null : alwaysOnTopOverlays.getFirst();
+        if (mAlwaysOnTopOverlayContainer != null) {
+            moveContainerToLastIfNecessary(mAlwaysOnTopOverlayContainer);
+        }
     }
 
     private void updateSplitPinContainerIfNecessary() {
@@ -458,18 +577,6 @@
         }
     }
 
-    private void updateOverlayContainerIfNecessary() {
-        final List<TaskFragmentContainer> overlayContainers = mContainers.stream()
-                .filter(TaskFragmentContainer::isOverlay).toList();
-        if (overlayContainers.size() > 1) {
-            throw new IllegalStateException("There must be at most one overlay container per Task");
-        }
-        mOverlayContainer = overlayContainers.isEmpty() ? null : overlayContainers.get(0);
-        if (mOverlayContainer != null) {
-            moveContainerToLastIfNecessary(mOverlayContainer);
-        }
-    }
-
     /** Moves the {@code container} to the last to align taskFragments' z-order. */
     private void moveContainerToLastIfNecessary(@NonNull TaskFragmentContainer container) {
         final int index = mContainers.indexOf(container);
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 e20a3e0..094ebcb 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -113,6 +113,18 @@
     @NonNull
     private final Bundle mLaunchOptions = new Bundle();
 
+    /**
+     * The associated {@link Activity#getActivityToken()} of the overlay container.
+     * Must be {@code null} for non-overlay container.
+     * <p>
+     * If an overlay container is associated with an activity, this overlay container will be
+     * dismissed when the associated activity is destroyed. If the overlay container is visible,
+     * activity will be launched on top of the overlay container and expanded to fill the parent
+     * container.
+     */
+    @Nullable
+    private final IBinder mAssociatedActivityToken;
+
     /** Indicates whether the container was cleaned up after the last activity was removed. */
     private boolean mIsFinished;
 
@@ -178,7 +190,7 @@
 
     /**
      * @see #TaskFragmentContainer(Activity, Intent, TaskContainer, SplitController,
-     * TaskFragmentContainer, String, Bundle)
+     * TaskFragmentContainer, String, Bundle, Activity)
      */
     TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
                           @Nullable Intent pendingAppearedIntent,
@@ -187,7 +199,7 @@
                           @Nullable TaskFragmentContainer pairedPrimaryContainer) {
         this(pendingAppearedActivity, pendingAppearedIntent, taskContainer,
                 controller, pairedPrimaryContainer, null /* overlayTag */,
-                null /* launchOptions */);
+                null /* launchOptions */, null /* associatedActivity */);
     }
 
     /**
@@ -197,12 +209,14 @@
      * @param overlayTag                Sets to indicate this taskFragment is an overlay container
      * @param launchOptions             The launch options to create this container. Must not be
      *                                  {@code null} for an overlay container
+     * @param associatedActivity        the associated activity of the overlay container. Must be
+     *                                  {@code null} for a non-overlay container.
      */
     TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
             @Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
             @NonNull SplitController controller,
             @Nullable TaskFragmentContainer pairedPrimaryContainer, @Nullable String overlayTag,
-            @Nullable Bundle launchOptions) {
+            @Nullable Bundle launchOptions, @Nullable Activity associatedActivity) {
         if ((pendingAppearedActivity == null && pendingAppearedIntent == null)
                 || (pendingAppearedActivity != null && pendingAppearedIntent != null)) {
             throw new IllegalArgumentException(
@@ -214,7 +228,13 @@
         mOverlayTag = overlayTag;
         if (overlayTag != null) {
             Objects.requireNonNull(launchOptions);
+        } else if (associatedActivity != null) {
+            throw new IllegalArgumentException("Associated activity must be null for "
+                    + "non-overlay activity.");
         }
+        mAssociatedActivityToken = associatedActivity != null
+                ? associatedActivity.getActivityToken() : null;
+
         if (launchOptions != null) {
             mLaunchOptions.putAll(launchOptions);
         }
@@ -420,14 +440,38 @@
         }
     }
 
+    /** Called when the activity {@link Activity#isFinishing()} and paused. */
+    void onFinishingActivityPaused(@NonNull WindowContainerTransaction wct,
+                                   @NonNull IBinder activityToken) {
+        finishSelfWithActivityIfNeeded(wct, activityToken);
+    }
+
     /** Called when the activity is destroyed. */
-    void onActivityDestroyed(@NonNull IBinder activityToken) {
+    void onActivityDestroyed(@NonNull WindowContainerTransaction wct,
+                             @NonNull IBinder activityToken) {
         removePendingAppearedActivity(activityToken);
         if (mInfo != null) {
             // Remove the activity now because there can be a delay before the server callback.
             mInfo.getActivities().remove(activityToken);
         }
         mActivitiesToFinishOnExit.remove(activityToken);
+        finishSelfWithActivityIfNeeded(wct, activityToken);
+    }
+
+    @VisibleForTesting
+    void finishSelfWithActivityIfNeeded(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder activityToken) {
+        if (mIsFinished) {
+            return;
+        }
+        // Early return if this container is not an overlay with activity association.
+        if (!isOverlay() || !isAssociatedWithActivity()) {
+            return;
+        }
+        if (mAssociatedActivityToken == activityToken) {
+            // If the associated activity is destroyed, also finish this overlay container.
+            mController.mPresenter.cleanupContainer(wct, this, false /* shouldFinishDependent */);
+        }
     }
 
     @Nullable
@@ -961,6 +1005,32 @@
         return mLaunchOptions;
     }
 
+    /**
+     * Returns the associated Activity token of this overlay container. It must be {@code null}
+     * for non-overlay container.
+     * <p>
+     * If an overlay container is associated with an activity, this overlay container will be
+     * dismissed when the associated activity is destroyed. If the overlay container is visible,
+     * activity will be launched on top of the overlay container and expanded to fill the parent
+     * container.
+     */
+    @Nullable
+    IBinder getAssociatedActivityToken() {
+        return mAssociatedActivityToken;
+    }
+
+    boolean isAssociatedWithActivity() {
+        return mAssociatedActivityToken != null;
+    }
+
+    /**
+     * Returns {@code true} if the overlay container should be always on top, which should be
+     * a non-fill-parent overlay without activity association.
+     */
+    boolean isAlwaysOnTopOverlay() {
+        return isOverlay() && !isAssociatedWithActivity();
+    }
+
     @Override
     public String toString() {
         return toString(true /* includeContainersToFinishOnExit */);
@@ -980,6 +1050,7 @@
                 + " runningActivityCount=" + getRunningActivityCount()
                 + " isFinished=" + mIsFinished
                 + " overlayTag=" + mOverlayTag
+                + " associatedActivity" + mAssociatedActivityToken
                 + " lastRequestedBounds=" + mLastRequestedBounds
                 + " pendingAppearedActivities=" + mPendingAppearedActivities
                 + (includeContainersToFinishOnExit ? " containersToFinishOnExit="
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java
index 47d01da..8aca92e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java
@@ -59,7 +59,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.concurrent.Executor;
 
@@ -74,6 +75,9 @@
 @RunWith(AndroidJUnit4.class)
 public class DividerPresenterTest {
     @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    @Rule
     public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
 
     private static final int MOCK_TASK_ID = 1234;
@@ -118,7 +122,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mSetFlagRule.enableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_INTERACTIVE_DIVIDER_FLAG);
 
         when(mTaskContainer.getTaskId()).thenReturn(MOCK_TASK_ID);
@@ -144,10 +147,12 @@
                 new Configuration(),
                 DEFAULT_DIVIDER_ATTRIBUTES,
                 mSurfaceControl,
-                getInitialDividerPosition(mSplitContainer),
+                getInitialDividerPosition(
+                        mSplitContainer, true /* isVerticalSplit */, false /* isReversedLayout */),
                 true /* isVerticalSplit */,
                 false /* isReversedLayout */,
-                Display.DEFAULT_DISPLAY);
+                Display.DEFAULT_DISPLAY,
+                false /* isDraggableExpandType */);
 
         mDividerPresenter = new DividerPresenter(
                 MOCK_TASK_ID, mDragEventCallback, mock(Executor.class));
@@ -261,6 +266,22 @@
     }
 
     @Test
+    public void testSanitizeDividerAttributes_setDefaultValues_fixedDivider() {
+        DividerAttributes attributes =
+                new DividerAttributes.Builder(DividerAttributes.DIVIDER_TYPE_FIXED).build();
+        DividerAttributes sanitized = DividerPresenter.sanitizeDividerAttributes(attributes);
+
+        assertEquals(DividerAttributes.DIVIDER_TYPE_FIXED, sanitized.getDividerType());
+        assertEquals(DividerPresenter.DEFAULT_DIVIDER_WIDTH_DP, sanitized.getWidthDp());
+
+        // The ratios should not be set for fixed divider
+        assertEquals(DividerAttributes.RATIO_SYSTEM_DEFAULT, sanitized.getPrimaryMinRatio(),
+                0.0f /* delta */);
+        assertEquals(DividerAttributes.RATIO_SYSTEM_DEFAULT, sanitized.getPrimaryMaxRatio(),
+                0.0f /* delta */);
+    }
+
+    @Test
     public void testSanitizeDividerAttributes_notChangingValidValues() {
         DividerAttributes attributes =
                 new DividerAttributes.Builder(DividerAttributes.DIVIDER_TYPE_DRAGGABLE)
@@ -348,7 +369,8 @@
                         dividerWidthPx,
                         dividerAttributes,
                         true /* isVerticalSplit */,
-                        false /* isReversedLayout */));
+                        0 /* minPosition */,
+                        900 /* maxPosition */));
 
         // Top-to-bottom split
         when(event.getRawY()).thenReturn(1000f); // Touch event is in display space
@@ -361,7 +383,8 @@
                         dividerWidthPx,
                         dividerAttributes,
                         false /* isVerticalSplit */,
-                        false /* isReversedLayout */));
+                        0 /* minPosition */,
+                        900 /* maxPosition */));
     }
 
     @Test
@@ -453,7 +476,6 @@
         final Rect primaryBounds = new Rect(0, 0, 500, 2000);
         final Rect secondaryBounds = new Rect(600, 0, 1100, 2000);
         final int dividerWidthPx = 100;
-        final int dividerPosition = 300;
 
         final TaskFragmentContainer mockPrimaryContainer =
                 createMockTaskFragmentContainer(mPrimaryContainerToken, primaryBounds);
@@ -462,6 +484,8 @@
         when(mSplitContainer.getPrimaryContainer()).thenReturn(mockPrimaryContainer);
         when(mSplitContainer.getSecondaryContainer()).thenReturn(mockSecondaryContainer);
 
+        // Test the normal case
+        int dividerPosition = 300;
         assertEquals(
                 0.3f, // Primary is 300px after dragging.
                 DividerPresenter.calculateNewSplitRatio(
@@ -470,7 +494,43 @@
                         taskBounds,
                         dividerWidthPx,
                         true /* isVerticalSplit */,
-                        false /* isReversedLayout */),
+                        false /* isReversedLayout */,
+                        200 /* minPosition */,
+                        1000 /* maxPosition */,
+                        false /* isDraggingToFullscreenAllowed */),
+                0.0001 /* delta */);
+
+        // Test the case when dragging to fullscreen is allowed and divider is dragged to the edge
+        dividerPosition = 0;
+        assertEquals(
+                DividerPresenter.RATIO_EXPANDED_SECONDARY,
+                DividerPresenter.calculateNewSplitRatio(
+                        mSplitContainer,
+                        dividerPosition,
+                        taskBounds,
+                        dividerWidthPx,
+                        true /* isVerticalSplit */,
+                        false /* isReversedLayout */,
+                        200 /* minPosition */,
+                        1000 /* maxPosition */,
+                        true /* isDraggingToFullscreenAllowed */),
+                0.0001 /* delta */);
+
+        // Test the case when dragging to fullscreen is not allowed and divider is dragged to the
+        // edge.
+        dividerPosition = 0;
+        assertEquals(
+                0.2f, // Adjusted to the minPosition 200
+                DividerPresenter.calculateNewSplitRatio(
+                        mSplitContainer,
+                        dividerPosition,
+                        taskBounds,
+                        dividerWidthPx,
+                        true /* isVerticalSplit */,
+                        false /* isReversedLayout */,
+                        200 /* minPosition */,
+                        1000 /* maxPosition */,
+                        false /* isDraggingToFullscreenAllowed */),
                 0.0001 /* delta */);
     }
 
@@ -482,7 +542,6 @@
         final Rect primaryBounds = new Rect(0, 0, 2000, 1100);
         final Rect secondaryBounds = new Rect(0, 0, 2000, 500);
         final int dividerWidthPx = 100;
-        final int dividerPosition = 300;
 
         final TaskFragmentContainer mockPrimaryContainer =
                 createMockTaskFragmentContainer(mPrimaryContainerToken, primaryBounds);
@@ -491,6 +550,8 @@
         when(mSplitContainer.getPrimaryContainer()).thenReturn(mockPrimaryContainer);
         when(mSplitContainer.getSecondaryContainer()).thenReturn(mockSecondaryContainer);
 
+        // Test the normal case
+        int dividerPosition = 300;
         assertEquals(
                 // After dragging, secondary is [0, 0, 2000, 300]. Primary is [0, 400, 2000, 1100].
                 0.7f,
@@ -500,7 +561,46 @@
                         taskBounds,
                         dividerWidthPx,
                         false /* isVerticalSplit */,
-                        true /* isReversedLayout */),
+                        true /* isReversedLayout */,
+                        200 /* minPosition */,
+                        1000 /* maxPosition */,
+                        true /* isDraggingToFullscreenAllowed */),
+                0.0001 /* delta */);
+
+        // Test the case when dragging to fullscreen is not allowed and divider is dragged to the
+        // edge.
+        dividerPosition = 0;
+        assertEquals(
+                // The primary (bottom) container is expanded
+                DividerPresenter.RATIO_EXPANDED_PRIMARY,
+                DividerPresenter.calculateNewSplitRatio(
+                        mSplitContainer,
+                        dividerPosition,
+                        taskBounds,
+                        dividerWidthPx,
+                        false /* isVerticalSplit */,
+                        true /* isReversedLayout */,
+                        200 /* minPosition */,
+                        1000 /* maxPosition */,
+                        true /* isDraggingToFullscreenAllowed */),
+                0.0001 /* delta */);
+
+        // Test the case when dragging to fullscreen is not allowed and divider is dragged to the
+        // edge.
+        dividerPosition = 0;
+        assertEquals(
+                // Adjusted to minPosition 200, so the primary (bottom) container is 800.
+                0.8f,
+                DividerPresenter.calculateNewSplitRatio(
+                        mSplitContainer,
+                        dividerPosition,
+                        taskBounds,
+                        dividerWidthPx,
+                        false /* isVerticalSplit */,
+                        true /* isReversedLayout */,
+                        200 /* minPosition */,
+                        1000 /* maxPosition */,
+                        false /* isDraggingToFullscreenAllowed */),
                 0.0001 /* delta */);
     }
 
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 6f37e9c..76e6a0f 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
@@ -42,10 +42,12 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
 
@@ -61,6 +63,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class JetpackTaskFragmentOrganizerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
     @Mock
     private WindowContainerTransaction mTransaction;
     @Mock
@@ -73,7 +78,6 @@
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
         mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback);
         mOrganizer.registerOrganizer();
         spyOn(mOrganizer);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index 28fbadb..50abdfd 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -39,6 +39,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -80,7 +81,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -97,6 +99,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class OverlayPresentationTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
 
     @Rule
     public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
@@ -125,7 +129,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         doReturn(new WindowLayoutInfo(new ArrayList<>())).when(mWindowLayoutComponent)
                 .getCurrentWindowLayoutInfo(anyInt(), any());
         DeviceStateManagerFoldingFeatureProducer producer =
@@ -177,37 +180,59 @@
     }
 
     @Test
-    public void testGetOverlayContainers() {
-        assertThat(mSplitController.getAllOverlayTaskFragmentContainers()).isEmpty();
+    public void testGetAllNonFinishingOverlayContainers() {
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers()).isEmpty();
 
         final TaskFragmentContainer overlayContainer1 =
                 createTestOverlayContainer(TASK_ID, "test1");
 
-        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(overlayContainer1);
 
-        assertThrows(
-                "The exception must throw if there are two overlay containers in the same task.",
-                IllegalStateException.class,
-                () -> createTestOverlayContainer(TASK_ID, "test2"));
+        final TaskFragmentContainer overlayContainer2 =
+                createTestOverlayContainer(TASK_ID, "test2");
+
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
+                .containsExactly(overlayContainer1, overlayContainer2);
 
         final TaskFragmentContainer overlayContainer3 =
                 createTestOverlayContainer(TASK_ID + 1, "test3");
 
-        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
-                .containsExactly(overlayContainer1, overlayContainer3);
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
+                .containsExactly(overlayContainer1, overlayContainer2, overlayContainer3);
+
+        final TaskFragmentContainer finishingOverlayContainer =
+                createTestOverlayContainer(TASK_ID, "test4");
+        spyOn(finishingOverlayContainer);
+        doReturn(true).when(finishingOverlayContainer).isFinished();
+
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
+                .containsExactly(overlayContainer1, overlayContainer2, overlayContainer3);
     }
 
     @Test
-    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_anotherTagInTask_dismissOverlay() {
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_anotherTagInTask() {
+        createExistingOverlayContainers(false /* visible */);
+        createMockTaskFragmentContainer(mActivity);
+
+        final TaskFragmentContainer overlayContainer =
+                createOrUpdateOverlayTaskFragmentIfNeeded("test3");
+
+        assertWithMessage("overlayContainer1 is still there since it's not visible.")
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
+                .containsExactly(mOverlayContainer1, mOverlayContainer2, overlayContainer);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlay_visibleOverlaySameTagInTask_dismissOverlay() {
         createExistingOverlayContainers();
 
         final TaskFragmentContainer overlayContainer =
                 createOrUpdateOverlayTaskFragmentIfNeeded("test3");
 
-        assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
-                + " is launched to the same task")
-                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+        assertWithMessage("overlayContainer1 must be dismissed since it's visible"
+                + " in the same task.")
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(mOverlayContainer2, overlayContainer);
     }
 
@@ -222,23 +247,24 @@
         assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
                 + " is launched with the same tag as an existing overlay container in a different "
                 + "task")
-                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(mOverlayContainer2, overlayContainer);
     }
 
     @Test
-    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_sameTagAndTask_updateOverlay() {
+    public void testCreateOrUpdateOverlay_sameTagTaskAndActivity_updateOverlay() {
         createExistingOverlayContainers();
 
         final Rect bounds = new Rect(0, 0, 100, 100);
         mSplitController.setActivityStackAttributesCalculator(params ->
                 new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
         final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
-                "test1");
+                mOverlayContainer1.getOverlayTag(),
+                mOverlayContainer1.getTopNonFinishingActivity());
 
         assertWithMessage("overlayContainer1 must be updated since the new overlay container"
                 + " is launched with the same tag and task")
-                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(mOverlayContainer1, mOverlayContainer2);
 
         assertThat(overlayContainer).isEqualTo(mOverlayContainer1);
@@ -247,6 +273,37 @@
     }
 
     @Test
+    public void testCreateOrUpdateOverlay_sameTagAndTaskButNotActivity_dismissOverlay() {
+        createExistingOverlayContainers();
+
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        mSplitController.setActivityStackAttributesCalculator(params ->
+                new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                mOverlayContainer1.getOverlayTag(), mActivity);
+
+        assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
+                + " is associated with different launching activity")
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
+                .containsExactly(mOverlayContainer2, overlayContainer);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_dismissOverlay() {
+        createExistingOverlayContainers(false /* visible */);
+        createMockTaskFragmentContainer(mActivity);
+
+        final TaskFragmentContainer overlayContainer =
+                createOrUpdateOverlayTaskFragmentIfNeeded("test2");
+
+        // OverlayContainer2 is dismissed since new container is launched with the
+        // same tag in different task.
+        assertWithMessage("overlayContainer1 must be dismissed")
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
+                .containsExactly(mOverlayContainer1, overlayContainer);
+    }
+
+    @Test
     public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_dismissMultipleOverlays() {
         createExistingOverlayContainers();
 
@@ -257,15 +314,19 @@
         // different tag. OverlayContainer2 is dismissed since new container is launched with the
         // same tag in different task.
         assertWithMessage("overlayContainer1 and overlayContainer2 must be dismissed")
-                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .that(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(overlayContainer);
     }
 
     private void createExistingOverlayContainers() {
-        mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1");
-        mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2");
+        createExistingOverlayContainers(true /* visible */);
+    }
+
+    private void createExistingOverlayContainers(boolean visible) {
+        mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible);
+        mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", visible);
         List<TaskFragmentContainer> overlayContainers = mSplitController
-                .getAllOverlayTaskFragmentContainers();
+                .getAllNonFinishingOverlayContainers();
         assertThat(overlayContainers).containsExactly(mOverlayContainer1, mOverlayContainer2);
     }
 
@@ -294,9 +355,9 @@
                 new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
         final TaskFragmentContainer overlayContainer =
                 createOrUpdateOverlayTaskFragmentIfNeeded("test");
-        setupTaskFragmentInfo(overlayContainer, mActivity);
+        setupTaskFragmentInfo(overlayContainer, mActivity, true /* isVisible */);
 
-        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(overlayContainer);
         assertThat(overlayContainer.getTaskId()).isEqualTo(TASK_ID);
         assertThat(overlayContainer.areLastRequestedBoundsEqual(bounds)).isTrue();
@@ -304,14 +365,16 @@
     }
 
     @Test
-    public void testGetTopNonFishingTaskFragmentContainerWithOverlay() {
-        final TaskFragmentContainer overlayContainer =
-                createTestOverlayContainer(TASK_ID, "test1");
-
-        // Add a SplitPinContainer, the overlay should be on top
+    public void testGetTopNonFishingTaskFragmentContainerWithoutAssociatedOverlay() {
         final Activity primaryActivity = createMockActivity();
         final Activity secondaryActivity = createMockActivity();
-
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        mSplitController.setActivityStackAttributesCalculator(params ->
+                new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
+        final TaskFragmentContainer overlayContainer =
+                createTestOverlayContainer(TASK_ID, "test1", true /* isVisible */,
+                        false /* shouldAssociateWithActivity */);
+        overlayContainer.setIsolatedNavigationEnabled(true);
         final TaskFragmentContainer primaryContainer =
                 createMockTaskFragmentContainer(primaryActivity);
         final TaskFragmentContainer secondaryContainer =
@@ -353,10 +416,10 @@
 
     @Test
     public void testGetTopNonFinishingActivityWithOverlay() {
-        TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test1");
-
         final Activity activity = createMockActivity();
         final TaskFragmentContainer container = createMockTaskFragmentContainer(activity);
+        final TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID,
+                "test1");
         final TaskContainer task = container.getTaskContainer();
 
         assertThat(task.getTopNonFinishingActivity(true /* includeOverlay */))
@@ -373,8 +436,9 @@
     }
 
     @Test
-    public void testUpdateOverlayContainer_dismissOverlayIfNeeded() {
-        TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test");
+    public void testUpdateOverlayContainer_dismissNonAssociatedOverlayIfNeeded() {
+        TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test",
+                true /* isVisible */, false /* associatedLaunchingActivity */);
 
         mSplitController.updateOverlayContainer(mTransaction, overlayContainer);
 
@@ -443,11 +507,10 @@
 
     @Test
     public void testOnTaskFragmentParentInfoChanged_positionOnlyChange_earlyReturn() {
-        final TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test");
+        final TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test",
+                true /* isVisible */, false /* associatedLaunchingActivity */);
         final TaskContainer taskContainer = overlayContainer.getTaskContainer();
 
-        assertThat(taskContainer.getOverlayContainer()).isEqualTo(overlayContainer);
-
         spyOn(taskContainer);
         final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
         final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
@@ -463,16 +526,15 @@
 
         assertWithMessage("The overlay container must still be dismissed even if "
                 + "#updateContainer is not called")
-                .that(taskContainer.getOverlayContainer()).isNull();
+                .that(taskContainer.getTaskFragmentContainers()).isEmpty();
     }
 
     @Test
-    public void testOnTaskFragmentParentInfoChanged_invisibleTask_callDismissOverlayContainer() {
-        final TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test");
+    public void testOnTaskFragmentParentInfoChanged_invisibleTask_callDismissNonAssocOverlay() {
+        final TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test",
+                true /* isVisible */, false /* associatedLaunchingActivity */);
         final TaskContainer taskContainer = overlayContainer.getTaskContainer();
 
-        assertThat(taskContainer.getOverlayContainer()).isEqualTo(overlayContainer);
-
         spyOn(taskContainer);
         final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
         final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
@@ -487,7 +549,7 @@
 
         assertWithMessage("The overlay container must still be dismissed even if "
                 + "#updateContainer is not called")
-                .that(taskContainer.getOverlayContainer()).isNull();
+                .that(taskContainer.getTaskFragmentContainers()).isEmpty();
     }
 
     @Test
@@ -510,7 +572,7 @@
     }
 
     @Test
-    public void testApplyActivityStackAttributesForOverlayContainer() {
+    public void testApplyActivityStackAttributesForOverlayContainerAssociatedWithActivity() {
         final TaskFragmentContainer container = createTestOverlayContainer(TASK_ID, TEST_TAG);
         final IBinder token = container.getTaskFragmentToken();
         final ActivityStackAttributes attributes = new ActivityStackAttributes.Builder()
@@ -527,7 +589,35 @@
                 WINDOWING_MODE_MULTI_WINDOW);
         verify(mSplitPresenter).updateAnimationParams(mTransaction, token,
                 TaskFragmentAnimationParams.DEFAULT);
-        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction, container, true);
+        // Set isolated navigation to false if the overlay container is associated with
+        // the launching activity.
+        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction, container, false);
+        verify(mSplitPresenter).setTaskFragmentDimOnTask(mTransaction, token, true);
+    }
+
+    @Test
+    public void testApplyActivityStackAttributesForOverlayContainerWithoutAssociatedActivity() {
+        final TaskFragmentContainer container = createTestOverlayContainer(TASK_ID, TEST_TAG,
+                true, /* isVisible */ false /* associatedWithLaunchingActivity */);
+        final IBinder token = container.getTaskFragmentToken();
+        final ActivityStackAttributes attributes = new ActivityStackAttributes.Builder()
+                .setRelativeBounds(new Rect(0, 0, 200, 200))
+                .setWindowAttributes(new WindowAttributes(DIM_AREA_ON_TASK))
+                .build();
+
+        mSplitPresenter.applyActivityStackAttributes(mTransaction, container,
+                attributes, null /* minDimensions */);
+
+        verify(mSplitPresenter).resizeTaskFragmentIfRegistered(mTransaction, container,
+                attributes.getRelativeBounds());
+        verify(mSplitPresenter).updateTaskFragmentWindowingModeIfRegistered(mTransaction,
+                container, WINDOWING_MODE_MULTI_WINDOW);
+        verify(mSplitPresenter).updateAnimationParams(mTransaction, token,
+                TaskFragmentAnimationParams.DEFAULT);
+        // Set isolated navigation to false if the overlay container is associated with
+        // the launching activity.
+        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction,
+                container, true);
         verify(mSplitPresenter).setTaskFragmentDimOnTask(mTransaction, token, true);
     }
 
@@ -563,8 +653,7 @@
         mSplitPresenter.applyActivityStackAttributes(mTransaction, container, attributes,
                 new Size(relativeBounds.width() + 1, relativeBounds.height()));
 
-        verify(mSplitPresenter).resizeTaskFragmentIfRegistered(mTransaction, container,
-                new Rect());
+        verify(mSplitPresenter).resizeTaskFragmentIfRegistered(mTransaction, container, new Rect());
         verify(mSplitPresenter).updateTaskFragmentWindowingModeIfRegistered(mTransaction, container,
                 WINDOWING_MODE_UNDEFINED);
         verify(mSplitPresenter).updateAnimationParams(mTransaction, token,
@@ -573,16 +662,65 @@
         verify(mSplitPresenter).setTaskFragmentDimOnTask(mTransaction, token, false);
     }
 
+    @Test
+    public void testFinishSelfWithActivityIfNeeded() {
+        TaskFragmentContainer container = createMockTaskFragmentContainer(mActivity);
+
+        container.finishSelfWithActivityIfNeeded(mTransaction, mActivity.getActivityToken());
+
+        verify(mSplitPresenter, never()).cleanupContainer(any(), any(), anyBoolean());
+
+        TaskFragmentContainer overlayWithoutAssociation = createTestOverlayContainer(TASK_ID,
+                "test", false /* associateLaunchingActivity */);
+
+        overlayWithoutAssociation.finishSelfWithActivityIfNeeded(mTransaction,
+                mActivity.getActivityToken());
+
+        verify(mSplitPresenter, never()).cleanupContainer(any(), any(), anyBoolean());
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
+                .contains(overlayWithoutAssociation);
+
+        TaskFragmentContainer overlayWithAssociation =
+                createOrUpdateOverlayTaskFragmentIfNeeded("test");
+        overlayWithAssociation.setInfo(mTransaction, createMockTaskFragmentInfo(
+                overlayWithAssociation, mActivity, true /* isVisible */));
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
+                .contains(overlayWithAssociation);
+        clearInvocations(mSplitPresenter);
+
+        overlayWithAssociation.finishSelfWithActivityIfNeeded(mTransaction, new Binder());
+
+        verify(mSplitPresenter, never()).cleanupContainer(any(), any(), anyBoolean());
+
+        overlayWithAssociation.finishSelfWithActivityIfNeeded(mTransaction,
+                mActivity.getActivityToken());
+
+        verify(mSplitPresenter).cleanupContainer(mTransaction, overlayWithAssociation, false);
+
+        assertThat(mSplitController.getAllNonFinishingOverlayContainers())
+                .doesNotContain(overlayWithAssociation);
+    }
+
     /**
-     * A simplified version of {@link SplitController.ActivityStartMonitor
-     * #createOrUpdateOverlayTaskFragmentIfNeeded}
+     * A simplified version of {@link SplitController#createOrUpdateOverlayTaskFragmentIfNeeded}
      */
     @Nullable
     private TaskFragmentContainer createOrUpdateOverlayTaskFragmentIfNeeded(@NonNull String tag) {
         final Bundle launchOptions = new Bundle();
         launchOptions.putString(KEY_OVERLAY_TAG, tag);
+        return createOrUpdateOverlayTaskFragmentIfNeeded(tag, mActivity);
+    }
+
+    /**
+     * A simplified version of {@link SplitController#createOrUpdateOverlayTaskFragmentIfNeeded}
+     */
+    @Nullable
+    private TaskFragmentContainer createOrUpdateOverlayTaskFragmentIfNeeded(
+            @NonNull String tag, @NonNull Activity activity) {
+        final Bundle launchOptions = new Bundle();
+        launchOptions.putString(KEY_OVERLAY_TAG, tag);
         return mSplitController.createOrUpdateOverlayTaskFragmentIfNeeded(mTransaction,
-                launchOptions, mIntent, mActivity);
+                launchOptions, mIntent, activity);
     }
 
     /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
@@ -590,23 +728,41 @@
     private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) {
         final TaskFragmentContainer container = mSplitController.newContainer(activity,
                 activity.getTaskId());
-        setupTaskFragmentInfo(container, activity);
+        setupTaskFragmentInfo(container, activity, false /* isVisible */);
         return container;
     }
 
     @NonNull
     private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag) {
+        return createTestOverlayContainer(taskId, tag, false /* isVisible */,
+                true /* associateLaunchingActivity */);
+    }
+
+    @NonNull
+    private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
+            boolean isVisible) {
+        return createTestOverlayContainer(taskId, tag, isVisible,
+                true /* associateLaunchingActivity */);
+    }
+
+    // TODO(b/243518738): add more test coverage on overlay container without activity association
+    //  once we have use cases.
+    @NonNull
+    private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
+                boolean isVisible, boolean associateLaunchingActivity) {
         Activity activity = createMockActivity();
         TaskFragmentContainer overlayContainer = mSplitController.newContainer(
                 null /* pendingAppearedActivity */, mIntent, activity, taskId,
-                null /* pairedPrimaryContainer */, tag, Bundle.EMPTY);
-        setupTaskFragmentInfo(overlayContainer, activity);
+                null /* pairedPrimaryContainer */, tag, Bundle.EMPTY,
+                associateLaunchingActivity);
+        setupTaskFragmentInfo(overlayContainer, activity, isVisible);
         return overlayContainer;
     }
 
     private void setupTaskFragmentInfo(@NonNull TaskFragmentContainer container,
-                                       @NonNull Activity activity) {
-        final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity);
+                                       @NonNull Activity activity,
+                                       boolean isVisible) {
+        final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity, isVisible);
         container.setInfo(mTransaction, info);
         mSplitPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), info);
     }
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index c246a19..8bc3a30 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
@@ -111,7 +111,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -137,6 +138,9 @@
             new ComponentName("test", "placeholder"));
 
     @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    @Rule
     public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
 
     private Activity mActivity;
@@ -166,7 +170,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         doReturn(new WindowLayoutInfo(new ArrayList<>())).when(mWindowLayoutComponent)
                 .getCurrentWindowLayoutInfo(anyInt(), any());
         DeviceStateManagerFoldingFeatureProducer producer =
@@ -227,13 +230,13 @@
 
         // When the activity is not finishing, do not clear the record.
         doReturn(false).when(mActivity).isFinishing();
-        mSplitController.onActivityDestroyed(mActivity);
+        mSplitController.onActivityDestroyed(mTransaction, mActivity);
 
         assertTrue(tf.hasActivity(mActivity.getActivityToken()));
 
         // Clear the record when the activity is finishing and destroyed.
         doReturn(true).when(mActivity).isFinishing();
-        mSplitController.onActivityDestroyed(mActivity);
+        mSplitController.onActivityDestroyed(mTransaction, mActivity);
 
         assertFalse(tf.hasActivity(mActivity.getActivityToken()));
     }
@@ -612,7 +615,7 @@
 
         assertFalse(result);
         verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any(),
-                anyString(), any());
+                anyString(), any(), anyBoolean());
     }
 
     @Test
@@ -775,7 +778,7 @@
 
         assertTrue(result);
         verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any(),
-                anyString(), any());
+                anyString(), any(), anyBoolean());
         verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
     }
 
@@ -818,7 +821,7 @@
 
         assertTrue(result);
         verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any(),
-                anyString(), any());
+                anyString(), any(), anyBoolean());
         verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
     }
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index 62d8aa3..c677484 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -85,10 +85,12 @@
 import androidx.window.extensions.layout.WindowLayoutInfo;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
 
@@ -106,6 +108,10 @@
 public class SplitPresenterTest {
 
     private Activity mActivity;
+
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
     @Mock
     private Resources mActivityResources;
     @Mock
@@ -119,7 +125,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         doReturn(new WindowLayoutInfo(new ArrayList<>())).when(mWindowLayoutComponent)
                 .getCurrentWindowLayoutInfo(anyInt(), any());
         DeviceStateManagerFoldingFeatureProducer producer =
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index a5995a3..8913b22 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -42,11 +42,12 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.List;
 
@@ -60,14 +61,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TaskContainerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
     @Mock
     private SplitController mController;
 
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-    }
-
     @Test
     public void testGetWindowingModeForSplitTaskFragment() {
         final TaskContainer taskContainer = createTestTaskContainer();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
index 379ea0c..a1e9f08 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
@@ -27,10 +27,12 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 /**
  * Test class for {@link TaskFragmentAnimationController}.
@@ -42,13 +44,15 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TaskFragmentAnimationControllerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
     @Mock
     private TaskFragmentOrganizer mOrganizer;
     private TaskFragmentAnimationController mAnimationController;
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
         mAnimationController = new TaskFragmentAnimationController(mOrganizer);
     }
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index cc00a49..abfc9c8 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -51,10 +51,12 @@
 import com.google.android.collect.Lists;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -71,6 +73,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TaskFragmentContainerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
     @Mock
     private SplitPresenter mPresenter;
     private SplitController mController;
@@ -83,7 +88,6 @@
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
         DeviceStateManagerFoldingFeatureProducer producer =
                 mock(DeviceStateManagerFoldingFeatureProducer.class);
         WindowLayoutComponentImpl component = mock(WindowLayoutComponentImpl.class);
@@ -402,7 +406,7 @@
 
         assertTrue(container.hasActivity(mActivity.getActivityToken()));
 
-        taskContainer.onActivityDestroyed(mActivity.getActivityToken());
+        taskContainer.onActivityDestroyed(mTransaction, mActivity.getActivityToken());
 
         // It should not contain the destroyed Activity.
         assertFalse(container.hasActivity(mActivity.getActivityToken()));
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java
index 459b6d2..2598dd6 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java
@@ -41,10 +41,12 @@
 import androidx.window.extensions.embedding.TransactionManager.TransactionRecord;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 /**
  * Test class for {@link TransactionManager}.
@@ -56,6 +58,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TransactionManagerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
 
     @Mock
     private TaskFragmentOrganizer mOrganizer;
@@ -63,7 +67,6 @@
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
         mTransactionManager = new TransactionManager(mOrganizer);
     }
 
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index 36d3313..7a98683 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -23,4 +23,12 @@
     <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
     <uses-permission android:name="android.permission.WAKEUP_SURFACE_FLINGER" />
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+
+    <application>
+        <activity
+            android:name=".desktopmode.DesktopWallpaperActivity"
+            android:excludeFromRecents="true"
+            android:launchMode="singleInstance"
+            android:theme="@style/DesktopWallpaperTheme" />
+    </application>
 </manifest>
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 0c4fd14..ebebd8a 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,5 +1,5 @@
 [email protected]
 
 # Give submodule owners in shell resource approval
-per-file res*/*/*.xml = [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
+per-file res*/*/*.xml = [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
 per-file res*/*/tv_*.xml = [email protected]
diff --git a/libs/WindowManager/Shell/aconfig/Android.bp b/libs/WindowManager/Shell/aconfig/Android.bp
index 1a98ffc..7f8f57b 100644
--- a/libs/WindowManager/Shell/aconfig/Android.bp
+++ b/libs/WindowManager/Shell/aconfig/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "com_android_wm_shell_flags",
     package: "com.android.wm.shell",
+    container: "system",
     srcs: [
         "multitasking.aconfig",
     ],
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index b61dda4..7ff204c 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.wm.shell"
+container: "system"
 
 flag {
     name: "enable_app_pairs"
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
index e73d880..8487e379 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
@@ -18,6 +18,7 @@
 import android.content.Context
 import android.content.Intent
 import android.content.pm.ShortcutInfo
+import android.content.res.Resources
 import android.graphics.Insets
 import android.graphics.PointF
 import android.graphics.Rect
@@ -43,6 +44,9 @@
 
     private lateinit var positioner: BubblePositioner
     private val context = ApplicationProvider.getApplicationContext<Context>()
+    private val resources: Resources
+        get() = context.resources
+
     private val defaultDeviceConfig =
         DeviceConfig(
             windowBounds = Rect(0, 0, 1000, 2000),
@@ -205,6 +209,58 @@
     }
 
     @Test
+    fun testBubbleBarExpandedViewHeightAndWidth() {
+        val deviceConfig =
+            defaultDeviceConfig.copy(
+                // portrait orientation
+                isLandscape = false,
+                isLargeScreen = true,
+                insets = Insets.of(10, 20, 5, 15),
+                windowBounds = Rect(0, 0, 1800, 2600)
+            )
+        val bubbleBarBounds = Rect(1700, 2500, 1780, 2600)
+
+        positioner.setShowingInBubbleBar(true)
+        positioner.update(deviceConfig)
+        positioner.bubbleBarBounds = bubbleBarBounds
+
+        val spaceBetweenTopInsetAndBubbleBarInLandscape = 1680
+        val expandedViewVerticalSpacing =
+            resources.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding)
+        val expectedHeight =
+            spaceBetweenTopInsetAndBubbleBarInLandscape - 2 * expandedViewVerticalSpacing
+        val expectedWidth = resources.getDimensionPixelSize(R.dimen.bubble_bar_expanded_view_width)
+
+        assertThat(positioner.getExpandedViewWidthForBubbleBar(false)).isEqualTo(expectedWidth)
+        assertThat(positioner.getExpandedViewHeightForBubbleBar(false)).isEqualTo(expectedHeight)
+    }
+
+    @Test
+    fun testBubbleBarExpandedViewHeightAndWidth_screenWidthTooSmall() {
+        val screenWidth = 300
+        val deviceConfig =
+            defaultDeviceConfig.copy(
+                // portrait orientation
+                isLandscape = false,
+                isLargeScreen = true,
+                insets = Insets.of(10, 20, 5, 15),
+                windowBounds = Rect(0, 0, screenWidth, 2600)
+            )
+        val bubbleBarBounds = Rect(100, 2500, 280, 2550)
+        positioner.setShowingInBubbleBar(true)
+        positioner.update(deviceConfig)
+        positioner.bubbleBarBounds = bubbleBarBounds
+
+        val spaceBetweenTopInsetAndBubbleBarInLandscape = 180
+        val expandedViewSpacing =
+            resources.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding)
+        val expectedHeight = spaceBetweenTopInsetAndBubbleBarInLandscape - 2 * expandedViewSpacing
+        val expectedWidth = screenWidth - 15 /* horizontal insets */ - 2 * expandedViewSpacing
+        assertThat(positioner.getExpandedViewWidthForBubbleBar(false)).isEqualTo(expectedWidth)
+        assertThat(positioner.getExpandedViewHeightForBubbleBar(false)).isEqualTo(expectedHeight)
+    }
+
+    @Test
     fun testGetExpandedViewHeight_max() {
         val deviceConfig =
             defaultDeviceConfig.copy(
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
index ef7478c..c0ff192 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
@@ -22,14 +22,15 @@
     android:layout_height="wrap_content"
     android:gravity="center_horizontal">
 
-    <ImageButton
+    <com.android.wm.shell.windowdecor.HandleImageButton
         android:id="@+id/caption_handle"
         android:layout_width="@dimen/desktop_mode_fullscreen_decor_caption_width"
         android:layout_height="@dimen/desktop_mode_fullscreen_decor_caption_height"
         android:paddingVertical="16dp"
+        android:paddingHorizontal="10dp"
         android:contentDescription="@string/handle_text"
         android:src="@drawable/decor_handle_dark"
         tools:tint="@color/desktop_mode_caption_handle_bar_dark"
         android:scaleType="fitXY"
-        android:background="?android:selectableItemBackground"/>
+        android:background="@android:color/transparent"/>
 </com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index dd6f845..b9ff5c6 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Maak toe"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Maak kieslys toe"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Maak kieslys oop"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimeer skerm"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Gryp skerm vas"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 18a4ccf..81ab3ab 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ዝጋ"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"ምናሌ ዝጋ"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"ምናሌን ክፈት"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"የማያ ገጹ መጠን አሳድግ"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ማያ ገጹን አሳድግ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 7ca335e..3974c39 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"إغلاق"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"إغلاق القائمة"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"فتح القائمة"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"تكبير الشاشة إلى أقصى حدّ"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"التقاط صورة للشاشة"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 944c4f2..a1ce1b3 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"বন্ধ কৰক"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"মেনু বন্ধ কৰক"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"মেনু খোলক"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"স্ক্ৰীন মেক্সিমাইজ কৰক"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"স্ক্ৰীন স্নেপ কৰক"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index c320e41..71dfe5a 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Bağlayın"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Menyunu bağlayın"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Menyunu açın"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranı maksimum böyüdün"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ekranı çəkin"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 19ca4d3..f483609 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite meni"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Otvorite meni"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Povećaj ekran"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Uklopi ekran"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 74ae1d7..81d066f 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Закрыць"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыць меню"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Адкрыць меню"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Разгарнуць на ўвесь экран"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Размясціць на палавіне экрана"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 1b753f5..8f828bad 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Затваряне"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Затваряне на менюто"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Отваряне на менюто"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Увеличаване на екрана"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Прилепване на екрана"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 2ea22cc..e0a2ea8 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"বন্ধ করুন"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"\'মেনু\' বন্ধ করুন"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"মেনু খুলুন"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"স্ক্রিন বড় করুন"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"স্ক্রিনে অ্যাপ মানানসই হিসেবে ছোট বড় করুন"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 13655b3..41c72c1 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zatvaranje"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvaranje menija"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Otvaranje menija"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimiziraj ekran"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snimi ekran"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index cb897c5..6792272 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Tanca"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Tanca el menú"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Obre el menú"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximitza la pantalla"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajusta la pantalla"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index ded2707..aafb2e1 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zavřít"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zavřít nabídku"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Otevřít nabídku"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximalizovat obrazovku"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Rozpůlit obrazovku"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 2bdb29d..8878910 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Luk"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Luk menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Åbn menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimér skærm"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Tilpas skærm"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index e99d9d0..bcdc2a9 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -62,7 +62,7 @@
     <string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> von <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="8071515017164630429">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> aus <xliff:g id="APP_NAME">%2$s</xliff:g> und <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> weiteren"</string>
     <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"Nach oben links verschieben"</string>
-    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Nach rechts oben verschieben"</string>
+    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Nach oben rechts verschieben"</string>
     <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"Nach unten links verschieben"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Nach unten rechts verschieben"</string>
     <string name="bubble_accessibility_announce_expand" msgid="5388792092888203776">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> maximieren"</string>
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Schließen"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Menü schließen"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Menü öffnen"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Bildschirm maximieren"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Bildschirm teilen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index d8bb740..14e5e2f 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Κλείσιμο"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Κλείσιμο μενού"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Άνοιγμα μενού"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Μεγιστοποίηση οθόνης"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Προβολή στο μισό της οθόνης"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 5e1b274..7427b62 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Close"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Open menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap screen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index 2525b32..cb9ee4f 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Close"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Close Menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Open Menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximize Screen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap Screen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 5e1b274..7427b62 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Close"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Open menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap screen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 5e1b274..7427b62 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Close"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Open menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap screen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 0623bef..8498807 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎Close‎‏‎‎‏‎"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‎Close Menu‎‏‎‎‏‎"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎Open Menu‎‏‎‎‏‎"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎Maximize Screen‎‏‎‎‏‎"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎Snap Screen‎‏‎‎‏‎"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 9fe77dd..406c1f3 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Abrir el menú"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar pantalla"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index b88f215..0583d79 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Abrir menú"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar pantalla"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 529b6d1..70547f5 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Sule"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Sule menüü"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Ava menüü"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Kuva täisekraanil"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Kuva poolel ekraanil"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 7438f42..4be35ea 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Itxi"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Itxi menua"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Ireki menua"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Handitu pantaila"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Zatitu pantaila"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index f7fcb21..32d5f5f 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"بستن"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"بستن منو"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"باز کردن منو"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"بزرگ کردن صفحه"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"بزرگ کردن صفحه"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 4001073..6f03545 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Sulje"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Sulje valikko"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Avaa valikko"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Suurenna näyttö"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Jaa näyttö"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index b54f9cf..1fde4cf 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Fermer"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Ouvrir le menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Agrandir l\'écran"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Aligner l\'écran"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 357ff91..e7233ae 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Fermer"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Ouvrir le menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Mettre en plein écran"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fractionner l\'écran"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index a621907..c371f7f 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -61,10 +61,10 @@
     <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Engadir de novo á pilla"</string>
     <string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="8071515017164630429">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g> e <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> máis"</string>
-    <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"Mover á parte super. esquerda"</string>
-    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Mover á parte superior dereita"</string>
-    <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"Mover á parte infer. esquerda"</string>
-    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Mover á parte inferior dereita"</string>
+    <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"Mover arriba á esquerda"</string>
+    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Mover arriba á dereita"</string>
+    <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"Mover abaixo á esquerda"</string>
+    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Mover abaixo á dereita"</string>
     <string name="bubble_accessibility_announce_expand" msgid="5388792092888203776">"despregar <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Pechar"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Pechar o menú"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Abrir menú"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Encaixar pantalla"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index 43c178f..7e3d7a3 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"બંધ કરો"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"મેનૂ બંધ કરો"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"મેનૂ ખોલો"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"સ્ક્રીન કરો મોટી કરો"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"સ્ક્રીન સ્નૅપ કરો"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 9f6a57f..cd0f4e3 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"बंद करें"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"मेन्यू बंद करें"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"मेन्यू खोलें"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रीन को बड़ा करें"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"स्नैप स्क्रीन"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 4378c56..fc39420 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Otvaranje izbornika"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimalno povećaj zaslon"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Izradi snimku zaslona"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index e5f199f..a8cc5c1 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Bezárás"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Menü bezárása"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Menü megnyitása"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Képernyő méretének maximalizálása"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Igazodás a képernyő adott részéhez"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index e0a5afe..7f37277 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Փակել"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Փակել ընտրացանկը"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Բացել ընտրացանկը"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ծավալել էկրանը"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ծալել էկրանը"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 8025837..3cf55fa 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Tutup"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Buka Menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Perbesar Layar"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Gabungkan Layar"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index cece56e..6aa56f9 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Loka"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Loka valmynd"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Opna valmynd"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Stækka skjá"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Smelluskjár"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 731db8c..3c1d5e4 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Chiudi"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Chiudi il menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Apri menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Massimizza schermo"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Aggancia schermo"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index adf55f3..a0c3b3a 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"סגירה"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"סגירת התפריט"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"פתיחת התפריט"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"הגדלת המסך"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"כיווץ המסך"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 3543222..fb726c1 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"閉じる"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"メニューを閉じる"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"メニューを開く"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"画面の最大化"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"画面のスナップ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 1e6e657..e9f620a 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"დახურვა"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"მენიუს დახურვა"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"მენიუს გახსნა"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"აპლიკაციის გაშლა სრულ ეკრანზე"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"აპლიკაციის დაპატარავება ეკრანზე"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 6d9ff26..34e4103 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Жабу"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Мәзірді жабу"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Мәзірді ашу"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Экранды ұлғайту"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Экранды бөлу"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 586ef73..362bbad 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"បិទ"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"បិទ​ម៉ឺនុយ"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"បើកម៉ឺនុយ"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ពង្រីកអេក្រង់"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ថតអេក្រង់"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 78ca0c7..77cc4a4 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ಮುಚ್ಚಿ"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"ಮೆನು ಮುಚ್ಚಿ"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"ಮೆನು ತೆರೆಯಿರಿ"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಮ್ಯಾಕ್ಸಿಮೈಸ್ ಮಾಡಿ"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ಸ್ನ್ಯಾಪ್ ಸ್ಕ್ರೀನ್"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 70aa376..e8b5522 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"닫기"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"메뉴 닫기"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"메뉴 열기"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"화면 최대화"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"화면 분할"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index b2a0a49..7b7779d 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Жабуу"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Менюну жабуу"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Менюну ачуу"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Экранды чоңойтуу"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Экранды сүрөткө тартып алуу"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 1cbdbd4..a351963 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ປິດ"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"ປິດເມນູ"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"ເປີດເມນູ"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ປັບຈໍໃຫຍ່ສຸດ"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ສະແນັບໜ້າຈໍ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index d154c57..e4dd739 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Uždaryti"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Uždaryti meniu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Atidaryti meniu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Išskleisti ekraną"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Sutraukti ekraną"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index ce26950..99aebf6 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Aizvērt"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Aizvērt izvēlni"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Atvērt izvēlni"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimizēt ekrānu"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fiksēt ekrānu"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 9d69c50..c152c60 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Затворете"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Затворете го менито"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Отвори го менито"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Максимизирај го екранот"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Подели го екранот на половина"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index c0e8338..90275cd 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"അടയ്ക്കുക"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"മെനു അടയ്ക്കുക"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"മെനു തുറക്കുക"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"സ്‌ക്രീൻ വലുതാക്കുക"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"സ്‌ക്രീൻ സ്‌നാപ്പ് ചെയ്യുക"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index ba5d283f..4a9fab92 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Хаах"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Цэсийг хаах"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Цэс нээх"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Дэлгэцийг томруулах"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Дэлгэцийг таллах"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 17601c1..5874bff 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"बंद करा"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"मेनू बंद करा"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"मेनू उघडा"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रीन मोठी करा"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"स्क्रीन स्नॅप करा"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index d5547fa..4de8a7b 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Tutup"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Buka Menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimumkan Skrin"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Tangkap Skrin"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 07bfc99..5b9e9cb 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ပိတ်ရန်"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"မီနူး ပိတ်ရန်"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"မီနူး ဖွင့်ရန်"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"စခရင်ကို ချဲ့မည်"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"စခရင်ကို ချုံ့မည်"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index f609d01..9f03d8b 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Lukk"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Lukk menyen"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Åpne menyen"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimer skjermen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fest skjermen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 9a26b7e..a5bd2ab 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -69,7 +69,7 @@
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> कोल्याप्स गर्नुहोस्"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> का सेटिङहरू"</string>
     <string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल खारेज गर्नुहोस्"</string>
-    <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"वार्तालाप बबलको रूपमा नदेखाइयोस्"</string>
+    <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"वार्तालाप बबलको रूपमा नदेखाउनुहोस्"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"बबलहरू प्रयोग गरी कुराकानी गर्नुहोस्"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"नयाँ वार्तालापहरू तैरने आइकन वा बबलका रूपमा देखिन्छन्। बबल खोल्न ट्याप गर्नुहोस्। बबल सार्न सो बबललाई ड्र्याग गर्नुहोस्।"</string>
     <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"जुनसुकै बेला बबलहरू नियन्त्रण गर्नुहोस्"</string>
@@ -99,7 +99,7 @@
     <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"यो एप तपाईंको स्क्रिनमा अझ राम्रोसँग देखियोस् भन्नाका लागि तपाईं सो एप रिस्टार्ट गर्न सक्नुहुन्छ तर तपाईंले अहिलेसम्म गरेका क्रियाकलाप वा सेभ गर्न बाँकी परिवर्तनहरू हट्न सक्छन्"</string>
     <string name="letterbox_restart_cancel" msgid="1342209132692537805">"रद्द गर्नुहोस्"</string>
     <string name="letterbox_restart_restart" msgid="8529976234412442973">"रिस्टार्ट गर्नुहोस्"</string>
-    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"फेरि नदेखाइयोस्"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"फेरि नदेखाउनुहोस्"</string>
     <string name="letterbox_reachability_reposition_text" msgid="3522042240665748268">"यो एप सार्न डबल\nट्याप गर्नुहोस्"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ठुलो बनाउनुहोस्"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"मिनिमाइज गर्नुहोस्"</string>
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"बन्द गर्नुहोस्"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"मेनु बन्द गर्नुहोस्"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"मेनु खोल्नुहोस्"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रिन ठुलो बनाउनुहोस्"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"स्क्रिन स्न्याप गर्नुहोस्"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index a38cb75..0cd27c5 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Sluiten"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Menu sluiten"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Menu openen"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Scherm maximaliseren"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Scherm halveren"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index e3097be..bf75185 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"ମେନୁ ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"ମେନୁ ଖୋଲନ୍ତୁ"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ସ୍କ୍ରିନକୁ ବଡ଼ କରନ୍ତୁ"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ସ୍କ୍ରିନକୁ ସ୍ନାପ କରନ୍ତୁ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 3aea6f6..325c1e8 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ਬੰਦ ਕਰੋ"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"ਮੀਨੂ ਬੰਦ ਕਰੋ"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"ਮੀਨੂ ਖੋਲ੍ਹੋ"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ਸਕ੍ਰੀਨ ਦਾ ਆਕਾਰ ਵਧਾਓ"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ਸਕ੍ਰੀਨ ਨੂੰ ਸਨੈਪ ਕਰੋ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index aec3722..a7648c8 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zamknij"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zamknij menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Otwórz menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksymalizuj ekran"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Przyciągnij ekran"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index ba24d7b..e47d151 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Abrir o menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ampliar tela"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar tela"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index f636da79..1210fe8 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -62,9 +62,9 @@
     <string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="8071515017164630429">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> do <xliff:g id="APP_NAME">%2$s</xliff:g> e mais<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>."</string>
     <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"Mover p/ parte sup. esquerda"</string>
-    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Mover parte superior direita"</string>
+    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Mover p/ parte sup. direita"</string>
     <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"Mover p/ parte infer. esquerda"</string>
-    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Mover parte inferior direita"</string>
+    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Mover p/ parte inf. direita"</string>
     <string name="bubble_accessibility_announce_expand" msgid="5388792092888203776">"expandir <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"reduzir <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"Definições de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Abrir menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar ecrã"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Encaixar ecrã"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index ba24d7b..e47d151 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Abrir o menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ampliar tela"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar tela"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index c20f350..ae871f3 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Închide"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Închide meniul"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Deschide meniul"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizează fereastra"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Micșorează fereastra și fixeaz-o"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 49347d2..971e146 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -61,10 +61,10 @@
     <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Добавить обратно в стек"</string>
     <string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> из приложения \"<xliff:g id="APP_NAME">%2$s</xliff:g>\""</string>
     <string name="bubble_content_description_stack" msgid="8071515017164630429">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> от приложения \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" и ещё <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
-    <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"Перенести в левый верхний угол"</string>
-    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Перенести в правый верхний угол"</string>
-    <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"Перенести в левый нижний угол"</string>
-    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Перенести в правый нижний угол"</string>
+    <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"Переместить в левый верхний угол"</string>
+    <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"Переместить в правый верхний угол"</string>
+    <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"Переместить в левый нижний угол"</string>
+    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"Переместить в правый нижний угол"</string>
     <string name="bubble_accessibility_announce_expand" msgid="5388792092888203776">"Развернуть <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Свернуть <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: настройки"</string>
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Закрыть"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыть меню"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Открыть меню"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Развернуть на весь экран"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Свернуть"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index e5a9746..ef1381c 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"වසන්න"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"මෙනුව වසන්න"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"මෙනුව විවෘත කරන්න"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"තිරය උපරිම කරන්න"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ස්නැප් තිරය"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index c2d20dd..55a0312 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zavrieť"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zavrieť ponuku"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Otvoriť ponuku"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximalizovať obrazovku"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Zobraziť polovicu obrazovky"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index cfe4480..bb123dc 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Zapri"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Zapri meni"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Odpri meni"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimiraj zaslon"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Pripni zaslon"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index cba98c2f..c74a8cd 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Mbyll"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Mbyll menynë"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Hap menynë"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimizo ekranin"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Regjistro ekranin"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 5031f5b..0694a97 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Затворите"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Затворите мени"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Отворите мени"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Повећај екран"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Уклопи екран"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 742be37..8e0bcfe 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Stäng"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Stäng menyn"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Öppna menyn"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximera skärmen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fäst skärmen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 68a7262d..41180ab 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Funga"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Funga Menyu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Fungua Menyu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Panua Dirisha kwenye Skrini"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Panga Madirisha kwenye Skrini"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index fe8fa05..01ac78d 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"மூடும்"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"மெனுவை மூடும்"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"மெனுவைத் திற"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"திரையைப் பெரிதாக்கு"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"திரையை ஸ்னாப் செய்"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 9be3f33..6224e72 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"మూసివేయండి"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"మెనూను మూసివేయండి"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"మెనూను తెరవండి"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"స్క్రీన్ సైజ్‌ను పెంచండి"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"స్క్రీన్‌ను స్నాప్ చేయండి"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index cd3bf6a..fe0b74c 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -64,7 +64,7 @@
     <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"ย้ายไปด้านซ้ายบน"</string>
     <string name="bubble_accessibility_action_move_top_right" msgid="5864594920870245525">"ย้ายไปด้านขวาบน"</string>
     <string name="bubble_accessibility_action_move_bottom_left" msgid="850271002773745634">"ย้ายไปด้านซ้ายล่าง"</string>
-    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"ย้ายไปด้านขาวล่าง"</string>
+    <string name="bubble_accessibility_action_move_bottom_right" msgid="2107626346109206352">"ย้ายไปด้านขวาล่าง"</string>
     <string name="bubble_accessibility_announce_expand" msgid="5388792092888203776">"ขยาย <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ยุบ <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
     <string name="bubbles_app_settings" msgid="3617224938701566416">"การตั้งค่า <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"ปิด"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"ปิดเมนู"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"เปิดเมนู"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ขยายหน้าจอให้ใหญ่สุด"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"สแนปหน้าจอ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index bf05e14..786e99c 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Isara"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Isara ang Menu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Buksan ang Menu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"I-maximize ang Screen"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"I-snap ang Screen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 2dfa38a..e953f58 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Kapat"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Menüyü kapat"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Menüyü Aç"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranı Büyüt"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ekranın Yarısına Tuttur"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 57ca64f..fbdf42e 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Закрити"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Закрити меню"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Відкрити меню"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Розгорнути екран"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Зафіксувати екран"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 0770373..5562fa7 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"بند کریں"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"مینیو بند کریں"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"مینو کھولیں"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"اسکرین کو بڑا کریں"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"اسکرین کا اسناپ شاٹ لیں"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index e2d1f47..50e4232 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Yopish"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Menyuni yopish"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Menyuni ochish"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranni yoyish"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ekranni biriktirish"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 4608b2b..6da8588 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Đóng"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Đóng trình đơn"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Mở Trình đơn"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Mở rộng màn hình"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Điều chỉnh kích thước màn hình"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index cbb857c..4318caf 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"关闭"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"关闭菜单"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"打开菜单"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"最大化屏幕"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"屏幕快照"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index d89b2c2..72cd39d 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"關閉"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"打開選單"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"畫面最大化"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"貼齊畫面"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 4ce50a4..c06d7b1 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"關閉"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"開啟選單"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"畫面最大化"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"貼齊畫面"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index fa680f6..755414e 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -117,4 +117,6 @@
     <string name="close_text" msgid="4986518933445178928">"Vala"</string>
     <string name="collapse_menu_text" msgid="7515008122450342029">"Vala Imenyu"</string>
     <string name="expand_menu_text" msgid="3847736164494181168">"Vula Imenyu"</string>
+    <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Khulisa Isikrini Sifike Ekugcineni"</string>
+    <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Thwebula Isikrini"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index a541c59..c2ba064 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -45,9 +45,6 @@
     <!-- Allow PIP to resize to a slightly bigger state upon touch/showing the menu -->
     <bool name="config_pipEnableResizeForMenu">true</bool>
 
-    <!-- PiP minimum size, which is a % based off the shorter side of display width and height -->
-    <fraction name="config_pipShortestEdgePercent">40%</fraction>
-
     <!-- Time (duration in milliseconds) that the shell waits for an app to close the PiP by itself
          if a custom action is present before closing it. -->
     <integer name="config_pipForceCloseDelay">1000</integer>
@@ -91,11 +88,45 @@
         16x16
     </string>
 
+    <!-- Default percentages for the PIP size logic.
+         1. Determine max widths
+         Subtract width of system UI and default padding from the shortest edge of the device.
+         This is the max width.
+         2. Calculate Default and Mins
+         Default is config_pipSystemPreferredDefaultSizePercent of max-width/height.
+         Min is config_pipSystemPreferredMinimumSizePercent of it. -->
+    <item name="config_pipSystemPreferredDefaultSizePercent" format="float" type="dimen">0.6</item>
+    <item name="config_pipSystemPreferredMinimumSizePercent" format="float" type="dimen">0.5</item>
+    <!-- Default percentages for the PIP size logic when the Display is close to square.
+         This is used instead when the display is square-ish, like fold-ables when unfolded,
+         to make sure that default PiP does not cover the hinge (halfway of the display).
+         0. Determine if the display is square-ish
+         If min(displayWidth, displayHeight) / max(displayWidth, displayHeight) is greater than
+         config_pipSquareDisplayThresholdForSystemPreferredSize, we use the percent for
+         square display listed below.
+         1. Determine max widths
+         Subtract width of system UI and default padding from the shortest edge of the device.
+         This is the max width.
+         2. Calculate Default and Mins
+         Default is config_pipSystemPreferredDefaultSizePercentForSquareDisplay of max-width/height.
+         Min is config_pipSystemPreferredMinimumSizePercentForSquareDisplay of it. -->
+    <item name="config_pipSquareDisplayThresholdForSystemPreferredSize"
+        format="float" type="dimen">0.95</item>
+    <item name="config_pipSystemPreferredDefaultSizePercentForSquareDisplay"
+        format="float" type="dimen">0.5</item>
+    <item name="config_pipSystemPreferredMinimumSizePercentForSquareDisplay"
+        format="float" type="dimen">0.4</item>
+
     <!-- The percentage of the screen width to use for the default width or height of
          picture-in-picture windows. Regardless of the percent set here, calculated size will never
-         be smaller than @dimen/default_minimal_size_pip_resizable_task. -->
+         be smaller than @dimen/default_minimal_size_pip_resizable_task.
+         This is used in legacy spec, use config_pipSystemPreferredDefaultSizePercent instead. -->
     <item name="config_pictureInPictureDefaultSizePercent" format="float" type="dimen">0.23</item>
 
+    <!-- PiP minimum size, which is a % based off the shorter side of display width and height.
+         This is used in legacy spec, use config_pipSystemPreferredMinimumSizePercent instead. -->
+    <fraction name="config_pipShortestEdgePercent">40%</fraction>
+
     <!-- The default aspect ratio for picture-in-picture windows. -->
     <item name="config_pictureInPictureDefaultAspectRatio" format="float" type="dimen">
         1.777778
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 39dd4d3..c2c90c8 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -254,6 +254,8 @@
     <dimen name="bubble_bar_expanded_view_caption_dot_size">4dp</dimen>
     <!-- The spacing between the dots for the caption menu in the bubble bar expanded view.. -->
     <dimen name="bubble_bar_expanded_view_caption_dot_spacing">4dp</dimen>
+    <!-- Width of the expanded bubble bar view shown when the bubble is expanded. -->
+    <dimen name="bubble_bar_expanded_view_width">412dp</dimen>
     <!-- Minimum width of the bubble bar manage menu. -->
     <dimen name="bubble_bar_manage_menu_min_width">200dp</dimen>
     <!-- Size of the dismiss icon in the bubble bar manage menu. -->
@@ -423,8 +425,9 @@
     <!-- Height of desktop mode caption for fullscreen tasks. -->
     <dimen name="desktop_mode_fullscreen_decor_caption_height">36dp</dimen>
 
-    <!-- Width of desktop mode caption for fullscreen tasks. -->
-    <dimen name="desktop_mode_fullscreen_decor_caption_width">128dp</dimen>
+    <!-- Width of desktop mode caption for fullscreen tasks.
+        80 dp for handle + 20 dp for room to grow on the sides when hovered. -->
+    <dimen name="desktop_mode_fullscreen_decor_caption_width">100dp</dimen>
 
     <!-- Required empty space to be visible for partially offscreen tasks. -->
     <dimen name="freeform_required_visible_empty_space_in_header">48dp</dimen>
@@ -512,8 +515,20 @@
     <!-- The size of the icon shown in the resize veil. -->
     <dimen name="desktop_mode_resize_veil_icon_size">96dp</dimen>
 
+    <!-- The with of the border around the app task for edge resizing, when
+         enable_windowing_edge_drag_resize is enabled. -->
+    <dimen name="desktop_mode_edge_handle">12dp</dimen>
+
+    <!-- The original width of the border around the app task for edge resizing, when
+         enable_windowing_edge_drag_resize is disabled. -->
     <dimen name="freeform_resize_handle">15dp</dimen>
 
+    <!-- The size of the corner region for drag resizing with touch, when a larger touch region is
+         appropriate. Applied when enable_windowing_edge_drag_resize is enabled. -->
+    <dimen name="desktop_mode_corner_resize_large">48dp</dimen>
+
+    <!-- The original size of the corner region for darg resizing, when
+         enable_windowing_edge_drag_resize is disabled. -->
     <dimen name="freeform_resize_corner">44dp</dimen>
 
     <!-- The width of the area at the sides of the screen where a freeform task will transition to
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index 08c2a02..13c0e66 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -23,6 +23,14 @@
         <item name="android:windowAnimationStyle">@style/Animation.ForcedResizable</item>
     </style>
 
+    <!-- Theme used for the activity that shows below the desktop mode windows to show wallpaper -->
+    <style name="DesktopWallpaperTheme" parent="@android:style/Theme.Wallpaper.NoTitleBar">
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+        <item name="android:windowAnimationStyle">@null</item>
+    </style>
+
     <style name="Animation.ForcedResizable" parent="@android:style/Animation">
         <item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item>
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index d8d0d87..3244837 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell;
 
+
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -30,7 +31,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager.RunningTaskInfo;
-import android.app.AppCompatTaskInfo;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.TaskInfo;
 import android.app.WindowConfiguration;
 import android.content.LocusId;
@@ -718,8 +719,7 @@
     }
 
     @Override
-    public void onCameraControlStateUpdated(
-            int taskId, @AppCompatTaskInfo.CameraCompatControlState int state) {
+    public void onCameraControlStateUpdated(int taskId, @CameraCompatControlState int state) {
         final TaskAppearedInfo info;
         synchronized (mLock) {
             info = mTasks.get(taskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
index 1996367..ce0bf8b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
@@ -17,6 +17,7 @@
 package com.android.wm.shell.animation;
 
 import android.graphics.Path;
+import android.view.animation.BackGestureInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.view.animation.PathInterpolator;
@@ -95,6 +96,15 @@
     public static final PathInterpolator DIM_INTERPOLATOR =
             new PathInterpolator(.23f, .87f, .52f, -0.11f);
 
+    /**
+     * Use this interpolator for animating progress values coming from the back callback to get
+     * the predictive-back-typical decelerate motion.
+     *
+     * This interpolator is similar to {@link Interpolators#STANDARD_DECELERATE} but has a slight
+     * acceleration phase at the start.
+     */
+    public static final Interpolator BACK_GESTURE = new BackGestureInterpolator();
+
     // Create the default emphasized interpolator
     private static PathInterpolator createEmphasizedInterpolator() {
         Path path = new Path();
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 97bf8f7..d3fe4f8 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
@@ -32,6 +32,7 @@
 import android.app.IActivityTaskManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.hardware.input.InputManager;
 import android.net.Uri;
@@ -71,6 +72,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
 import com.android.wm.shell.shared.annotations.ShellMainThread;
+import com.android.wm.shell.sysui.ConfigurationChangeListener;
 import com.android.wm.shell.sysui.ShellCommandHandler;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
@@ -81,7 +83,8 @@
 /**
  * Controls the window animation run when a user initiates a back gesture.
  */
-public class BackAnimationController implements RemoteCallable<BackAnimationController> {
+public class BackAnimationController implements RemoteCallable<BackAnimationController>,
+        ConfigurationChangeListener {
     private static final String TAG = "ShellBackPreview";
     private static final int SETTING_VALUE_OFF = 0;
     private static final int SETTING_VALUE_ON = 1;
@@ -248,6 +251,7 @@
         mShellController.addExternalInterface(KEY_EXTRA_SHELL_BACK_ANIMATION,
                 this::createExternalInterface, this);
         mShellCommandHandler.addDumpCallback(this::dump, this);
+        mShellController.addConfigurationChangeListener(this);
     }
 
     private void setupAnimationDeveloperSettingsObserver(
@@ -297,6 +301,11 @@
     private final BackAnimationImpl mBackAnimation = new BackAnimationImpl();
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mShellBackAnimationRegistry.onConfigurationChanged(newConfig);
+    }
+
+    @Override
     public Context getContext() {
         return mContext;
     }
@@ -828,6 +837,8 @@
 
         // The next callback should be {@link #onBackAnimationFinished}.
         if (mCurrentTracker.getTriggerBack()) {
+            // notify gesture finished
+            mBackNavigationInfo.onBackGestureFinished(true);
             dispatchOrAnimateOnBackInvoked(mActiveCallback, mCurrentTracker);
         } else {
             tryDispatchOnBackCancelled(mActiveCallback);
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 a32b435..4988a94 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -28,6 +28,7 @@
 import android.window.IBackAnimationRunner;
 import android.window.IOnBackInvokedCallback;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.jank.Cuj.CujType;
 import com.android.wm.shell.common.InteractionJankMonitorUtils;
 
@@ -108,7 +109,8 @@
         }
     }
 
-    private boolean shouldMonitorCUJ(RemoteAnimationTarget[] apps) {
+    @VisibleForTesting
+    boolean shouldMonitorCUJ(RemoteAnimationTarget[] apps) {
         return apps.length > 0 && mCujType != NO_CUJ;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
index c6d4620..808c212 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
@@ -68,7 +68,7 @@
 
     private val backAnimRect = Rect()
 
-    private val cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
+    private var cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
 
     private val backAnimationRunner = BackAnimationRunner(
         Callback(), Runner(), context, Cuj.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY
@@ -87,13 +87,19 @@
     private val enteringStartOffset =
         context.resources.getDimension(R.dimen.cross_activity_back_entering_start_offset)
 
-    private val gestureInterpolator = Interpolators.STANDARD_DECELERATE
+    private val gestureInterpolator = Interpolators.BACK_GESTURE
     private val postCommitInterpolator = Interpolators.FAST_OUT_SLOW_IN
     private val verticalMoveInterpolator: Interpolator = DecelerateInterpolator()
 
     private var scrimLayer: SurfaceControl? = null
     private var maxScrimAlpha: Float = 0f
 
+    private var isLetterboxed = false
+
+    override fun onConfigurationChanged(newConfiguration: Configuration) {
+        cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
+    }
+
     override fun getRunner() = backAnimationRunner
 
     private fun startBackAnimation(backMotionEvent: BackMotionEvent) {
@@ -108,9 +114,15 @@
         initialTouchPos.set(backMotionEvent.touchX, backMotionEvent.touchY)
 
         transaction.setAnimationTransaction()
-
+        isLetterboxed = closingTarget!!.taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed
+        if (isLetterboxed) {
+            // Include letterbox in back animation
+            backAnimRect.set(closingTarget!!.windowConfiguration.bounds)
+        } else {
+            // otherwise play animation on localBounds only
+            backAnimRect.set(closingTarget!!.localBounds)
+        }
         // Offset start rectangle to align task bounds.
-        backAnimRect.set(closingTarget!!.localBounds)
         backAnimRect.offsetTo(0, 0)
 
         startClosingRect.set(backAnimRect)
@@ -237,6 +249,7 @@
         }
         finishCallback = null
         removeScrimLayer()
+        isLetterboxed = false
     }
 
     private fun applyTransform(leash: SurfaceControl?, rect: RectF, alpha: Float) {
@@ -270,10 +283,15 @@
         scrimLayer = scrimBuilder.build()
         val colorComponents = floatArrayOf(0f, 0f, 0f)
         maxScrimAlpha = if (isDarkTheme) MAX_SCRIM_ALPHA_DARK else MAX_SCRIM_ALPHA_LIGHT
+        val scrimCrop = if (isLetterboxed) {
+            closingTarget!!.windowConfiguration.bounds
+        } else {
+            closingTarget!!.localBounds
+        }
         transaction
             .setColor(scrimLayer, colorComponents)
             .setAlpha(scrimLayer!!, maxScrimAlpha)
-            .setCrop(scrimLayer!!, closingTarget!!.localBounds)
+            .setCrop(scrimLayer!!, scrimCrop)
             .setRelativeLayer(scrimLayer!!, closingTarget!!.leash, -1)
             .show(scrimLayer)
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
index 987001d..ee898a7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
@@ -29,6 +29,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Matrix;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -80,7 +81,7 @@
     private static final int POST_ANIMATION_DURATION_MS = 500;
 
     private final Rect mStartTaskRect = new Rect();
-    private final float mCornerRadius;
+    private float mCornerRadius;
 
     // The closing window properties.
     private final Rect mClosingStartRect = new Rect();
@@ -92,7 +93,7 @@
 
     private final PointF mInitialTouchPos = new PointF();
     private final Interpolator mPostAnimationInterpolator = Interpolators.EMPHASIZED;
-    private final Interpolator mProgressInterpolator = Interpolators.STANDARD_DECELERATE;
+    private final Interpolator mProgressInterpolator = Interpolators.BACK_GESTURE;
     private final Interpolator mVerticalMoveInterpolator = new DecelerateInterpolator();
     private final Matrix mTransformMatrix = new Matrix();
 
@@ -120,6 +121,11 @@
         mContext = context;
     }
 
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
+    }
+
     private static float mapRange(float value, float min, float max) {
         return min + (value * (max - min));
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
index e33aa75..838dab4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
@@ -29,6 +29,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.RemoteException;
@@ -63,7 +64,7 @@
 public class CustomizeActivityAnimation extends ShellBackAnimation {
     private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
     private final BackAnimationRunner mBackAnimationRunner;
-    private final float mCornerRadius;
+    private float mCornerRadius;
     private final SurfaceControl.Transaction mTransaction;
     private final BackAnimationBackground mBackground;
     private RemoteAnimationTarget mEnteringTarget;
@@ -88,6 +89,7 @@
     final Transformation mTransformation = new Transformation();
 
     private final Choreographer mChoreographer;
+    private final Context mContext;
 
     @Inject
     public CustomizeActivityAnimation(Context context, BackAnimationBackground background) {
@@ -108,6 +110,12 @@
                 .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
         mTransaction = transaction == null ? new SurfaceControl.Transaction() : transaction;
         mChoreographer = choreographer != null ? choreographer : Choreographer.getInstance();
+        mContext = context;
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
     }
 
     private float getLatestProgress() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java
index dc65919..8a0daaa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.back;
 
+import android.content.res.Configuration;
 import android.window.BackNavigationInfo;
 
 import javax.inject.Qualifier;
@@ -48,4 +49,8 @@
     public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo) {
         return false;
     }
+
+    void onConfigurationChanged(Configuration newConfig) {
+
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
index 26d2097..7a6032c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.res.Configuration;
 import android.util.Log;
 import android.util.SparseArray;
 import android.window.BackNavigationInfo;
@@ -27,8 +28,9 @@
     private static final String TAG = "ShellBackPreview";
 
     private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>();
-    private final ShellBackAnimation mDefaultCrossActivityAnimation;
+    private ShellBackAnimation mDefaultCrossActivityAnimation;
     private final ShellBackAnimation mCustomizeActivityAnimation;
+    private final ShellBackAnimation mCrossTaskAnimation;
 
     public ShellBackAnimationRegistry(
             @ShellBackAnimation.CrossActivity @Nullable ShellBackAnimation crossActivityAnimation,
@@ -57,6 +59,7 @@
 
         mDefaultCrossActivityAnimation = crossActivityAnimation;
         mCustomizeActivityAnimation = customizeActivityAnimation;
+        mCrossTaskAnimation = crossTaskAnimation;
 
         // TODO(b/236760237): register dialog close animation when it's completed.
     }
@@ -64,10 +67,18 @@
     void registerAnimation(
             @BackNavigationInfo.BackTargetType int type, @NonNull BackAnimationRunner runner) {
         mAnimationDefinition.set(type, runner);
+        // Only happen in test
+        if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
+            mDefaultCrossActivityAnimation = null;
+        }
     }
 
     void unregisterAnimation(@BackNavigationInfo.BackTargetType int type) {
         mAnimationDefinition.remove(type);
+        // Only happen in test
+        if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
+            mDefaultCrossActivityAnimation = null;
+        }
     }
 
     /**
@@ -125,6 +136,18 @@
                 BackNavigationInfo.TYPE_CROSS_ACTIVITY, mDefaultCrossActivityAnimation.getRunner());
     }
 
+    void onConfigurationChanged(Configuration newConfig) {
+        if (mCustomizeActivityAnimation != null) {
+            mCustomizeActivityAnimation.onConfigurationChanged(newConfig);
+        }
+        if (mDefaultCrossActivityAnimation != null) {
+            mDefaultCrossActivityAnimation.onConfigurationChanged(newConfig);
+        }
+        if (mCrossTaskAnimation != null) {
+            mCrossTaskAnimation.onConfigurationChanged(newConfig);
+        }
+    }
+
     BackAnimationRunner getAnimationRunnerAndInit(BackNavigationInfo backNavigationInfo) {
         int type = backNavigationInfo.getType();
         // Initiate customized cross-activity animation, or fall back to cross activity animation
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
index a67821b..0297901 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
@@ -288,13 +288,16 @@
 
     /** Sets the position of the dot and badge, animating them out and back in if requested. */
     void animateDotBadgePositions(boolean onLeft) {
-        mOnLeft = onLeft;
-
-        if (onLeft != getDotOnLeft() && shouldDrawDot()) {
-            animateDotScale(0f /* showDot */, () -> {
-                invalidate();
-                animateDotScale(1.0f, null /* after */);
-            });
+        if (onLeft != getDotOnLeft()) {
+            if (shouldDrawDot()) {
+                animateDotScale(0f /* showDot */, () -> {
+                    mOnLeft = onLeft;
+                    invalidate();
+                    animateDotScale(1.0f, null /* after */);
+                });
+            } else {
+                mOnLeft = onLeft;
+            }
         }
         // TODO animate badge
         showBadge();
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 0867a44..d295877 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
@@ -455,8 +455,7 @@
                         ProtoLog.d(WM_SHELL_BUBBLES,
                                 "onActivityRestartAttempt - taskId=%d selecting matching bubble=%s",
                                 task.taskId, b.getKey());
-                        mBubbleData.setSelectedBubble(b);
-                        mBubbleData.setExpanded(true);
+                        mBubbleData.setSelectedBubbleAndExpandStack(b);
                         return;
                     }
                 }
@@ -593,13 +592,6 @@
         }
     }
 
-    private void openBubbleOverflow() {
-        ensureBubbleViewsAndWindowCreated();
-        mBubbleData.setShowingOverflow(true);
-        mBubbleData.setSelectedBubble(mBubbleData.getOverflow());
-        mBubbleData.setExpanded(true);
-    }
-
     /**
      * Called when the status bar has become visible or invisible (either permanently or
      * temporarily).
@@ -1247,8 +1239,7 @@
         }
         if (mBubbleData.hasBubbleInStackWithKey(b.getKey())) {
             // already in the stack
-            mBubbleData.setSelectedBubble(b);
-            mBubbleData.setExpanded(true);
+            mBubbleData.setSelectedBubbleAndExpandStack(b);
         } else if (mBubbleData.hasOverflowBubbleWithKey(b.getKey())) {
             // promote it out of the overflow
             promoteBubbleFromOverflow(b);
@@ -1273,8 +1264,7 @@
             String key = entry.getKey();
             Bubble bubble = mBubbleData.getBubbleInStackWithKey(key);
             if (bubble != null) {
-                mBubbleData.setSelectedBubble(bubble);
-                mBubbleData.setExpanded(true);
+                mBubbleData.setSelectedBubbleAndExpandStack(bubble);
             } else {
                 bubble = mBubbleData.getOverflowBubbleWithKey(key);
                 if (bubble != null) {
@@ -1367,8 +1357,7 @@
             } else {
                 // App bubble is not selected, select it & expand
                 Log.i(TAG, "  showOrHideAppBubble, expand and select existing app bubble");
-                mBubbleData.setSelectedBubble(existingAppBubble);
-                mBubbleData.setExpanded(true);
+                mBubbleData.setSelectedBubbleAndExpandStack(existingAppBubble);
             }
         } else {
             // Check if it exists in the overflow
@@ -2335,6 +2324,11 @@
             mMainExecutor.execute(() ->
                     mController.setBubbleBarLocation(location));
         }
+
+        @Override
+        public void setBubbleBarBounds(Rect bubbleBarBounds) {
+            mMainExecutor.execute(() -> mBubblePositioner.setBubbleBarBounds(bubbleBarBounds));
+        }
     }
 
     private class BubblesImpl implements Bubbles {
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 61f0ed2..ae3d0c5 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
@@ -365,6 +365,19 @@
         mSelectedBubble = bubble;
     }
 
+    /**
+     * Sets the selected bubble and expands it.
+     *
+     * <p>This dispatches a single state update for both changes and should be used instead of
+     * calling {@link #setSelectedBubble(BubbleViewProvider)} followed by
+     * {@link #setExpanded(boolean)} immediately after, which will generate 2 separate updates.
+     */
+    public void setSelectedBubbleAndExpandStack(BubbleViewProvider bubble) {
+        setSelectedBubbleInternal(bubble);
+        setExpandedInternal(true);
+        dispatchPendingChanges();
+    }
+
     public void setSelectedBubble(BubbleViewProvider bubble) {
         setSelectedBubbleInternal(bubble);
         dispatchPendingChanges();
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 74f087b..4e8afcc 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
@@ -68,6 +68,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.Flags;
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.AlphaOptimizedButton;
 import com.android.wm.shell.common.TriangleShape;
@@ -446,6 +447,8 @@
             mManageButton.setVisibility(GONE);
         } else {
             mTaskView = bubbleTaskView.getTaskView();
+            // reset the insets that might left after TaskView is shown in BubbleBarExpandedView
+            mTaskView.setCaptionInsets(null);
             bubbleTaskView.setDelegateListener(mTaskViewListener);
 
             // set a fixed width so it is not recalculated as part of a rotation. the width will be
@@ -668,6 +671,11 @@
         }
     }
 
+    /** Sets the alpha for the pointer. */
+    public void setPointerAlpha(float alpha) {
+        mPointerView.setAlpha(alpha);
+    }
+
     /**
      * Get alpha from underlying {@code TaskView} if this view is for a bubble.
      * Or get alpha for the overflow view if this view is for overflow.
@@ -698,12 +706,14 @@
         }
     }
 
-    /**
-     * Sets the alpha of the background and the pointer view.
-     */
+    /** Sets the alpha of the background. */
     public void setBackgroundAlpha(float alpha) {
-        mPointerView.setAlpha(alpha);
-        setAlpha(alpha);
+        if (Flags.enableNewBubbleAnimations()) {
+            setAlpha(alpha);
+        } else {
+            mPointerView.setAlpha(alpha);
+            setAlpha(alpha);
+        }
     }
 
     /**
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 4d5e516..14c3a070 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
@@ -149,9 +149,10 @@
         mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
 
         if (mShowingInBubbleBar) {
-            mExpandedViewLargeScreenWidth = isLandscape()
-                    ? (int) (bounds.width() * EXPANDED_VIEW_BUBBLE_BAR_LANDSCAPE_WIDTH_PERCENT)
-                    : (int) (bounds.width() * EXPANDED_VIEW_BUBBLE_BAR_PORTRAIT_WIDTH_PERCENT);
+            mExpandedViewLargeScreenWidth = Math.min(
+                    res.getDimensionPixelSize(R.dimen.bubble_bar_expanded_view_width),
+                    mPositionRect.width() - 2 * mExpandedViewPadding
+            );
         } else if (mDeviceConfig.isSmallTablet()) {
             mExpandedViewLargeScreenWidth = (int) (bounds.width()
                     * EXPANDED_VIEW_SMALL_TABLET_WIDTH_PERCENT);
@@ -839,11 +840,42 @@
      * How tall the expanded view should be when showing from the bubble bar.
      */
     public int getExpandedViewHeightForBubbleBar(boolean isOverflow) {
-        return isOverflow
-                ? mOverflowHeight
-                : getExpandedViewBottomForBubbleBar() - mInsets.top - mExpandedViewPadding;
+        if (isOverflow) {
+            return mOverflowHeight;
+        } else {
+            return getBubbleBarExpandedViewHeightForLandscape();
+        }
     }
 
+    /**
+     * Calculate the height of expanded view in landscape mode regardless current orientation.
+     * Here is an explanation:
+     * ------------------------ mScreenRect.top
+     * |         top inset ↕  |
+     * |-----------------------
+     * |      16dp spacing ↕  |
+     * |           ---------  | --- expanded view top
+     * |           |       |  |   ↑
+     * |           |       |  |   ↓ expanded view height
+     * |           ---------  | --- expanded view bottom
+     * |      16dp spacing ↕  |   ↑
+     * |         @bubble bar@ |   | height of the bubble bar container
+     * ------------------------   | already includes bottom inset and spacing
+     * |      bottom inset ↕  |   ↓
+     * |----------------------| --- mScreenRect.bottom
+     */
+    private int getBubbleBarExpandedViewHeightForLandscape() {
+        int heightOfBubbleBarContainer =
+                mScreenRect.height() - getExpandedViewBottomForBubbleBar();
+        // getting landscape height from screen rect
+        int expandedViewHeight = Math.min(mScreenRect.width(), mScreenRect.height());
+        expandedViewHeight -= heightOfBubbleBarContainer; /* removing bubble container height */
+        expandedViewHeight -= mInsets.top; /* removing top inset */
+        expandedViewHeight -= mExpandedViewPadding; /* removing spacing */
+        return expandedViewHeight;
+    }
+
+
     /** The bottom position of the expanded view when showing above the bubble bar. */
     public int getExpandedViewBottomForBubbleBar() {
         return mBubbleBarBounds.top - mExpandedViewPadding;
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 8da85d2..dcc536b 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
@@ -2358,9 +2358,9 @@
         } else {
             index = getBubbleIndex(mExpandedBubble);
         }
-        PointF p = mPositioner.getExpandedBubbleXY(index, getState());
+        PointF bubbleXY = mPositioner.getExpandedBubbleXY(index, getState());
         final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
-                mPositioner.showBubblesVertically() ? p.y : p.x);
+                mPositioner.showBubblesVertically() ? bubbleXY.y : bubbleXY.x);
         mExpandedViewContainer.setTranslationX(0f);
         mExpandedViewContainer.setTranslationY(translationY);
         mExpandedViewContainer.setAlpha(1f);
@@ -2371,40 +2371,42 @@
                 ? mStackAnimationController.getStackPosition().y
                 : mStackAnimationController.getStackPosition().x;
         final float bubbleWillBeAt = showVertically
-                ? p.y
-                : p.x;
+                ? bubbleXY.y
+                : bubbleXY.x;
         final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
 
         // Wait for the path animation target to reach its end, and add a small amount of extra time
         // if the bubble is moving a lot horizontally.
-        long startDelay = 0L;
+        final long startDelay;
 
         // Should not happen since we lay out before expanding, but just in case...
         if (getWidth() > 0) {
             startDelay = (long)
                     (ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION * 1.2f
                             + (distanceAnimated / getWidth()) * 30);
+        } else {
+            startDelay = 0L;
         }
 
         // Set the pivot point for the scale, so the expanded view animates out from the bubble.
         if (showVertically) {
             float pivotX;
             if (mStackOnLeftOrWillBe) {
-                pivotX = p.x + mBubbleSize + mExpandedViewPadding;
+                pivotX = bubbleXY.x + mBubbleSize + mExpandedViewPadding;
             } else {
-                pivotX = p.x - mExpandedViewPadding;
+                pivotX = bubbleXY.x - mExpandedViewPadding;
             }
             mExpandedViewContainerMatrix.setScale(
                     1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                     1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                     pivotX,
-                    p.y + mBubbleSize / 2f);
+                    bubbleXY.y + mBubbleSize / 2f);
         } else {
             mExpandedViewContainerMatrix.setScale(
                     1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                     1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
-                    p.x + mBubbleSize / 2f,
-                    p.y + mBubbleSize + mExpandedViewPadding);
+                    bubbleXY.x + mBubbleSize / 2f,
+                    bubbleXY.y + mBubbleSize + mExpandedViewPadding);
         }
         mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 16134d3..c9f0f0d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -44,4 +44,6 @@
     oneway void showUserEducation(in int positionX, in int positionY) = 8;
 
     oneway void setBubbleBarLocation(in BubbleBarLocation location) = 9;
+
+    oneway void setBubbleBarBounds(in Rect bubbleBarBounds) = 10;
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index 8af4c75..45ad631 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -166,13 +166,8 @@
         bbev.setTaskViewAlpha(0f);
         bbev.setVisibility(VISIBLE);
 
-        // Set the pivot point for the scale, so the view animates out from the bubble bar.
-        Rect bubbleBarBounds = mPositioner.getBubbleBarBounds();
-        mExpandedViewContainerMatrix.setScale(
-                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
-                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
-                bubbleBarBounds.centerX(),
-                bubbleBarBounds.top);
+        setScaleFromBubbleBar(mExpandedViewContainerMatrix,
+                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT);
 
         bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
 
@@ -214,8 +209,8 @@
         }
         bbev.setScaleX(1f);
         bbev.setScaleY(1f);
-        mExpandedViewContainerMatrix.setScaleX(1f);
-        mExpandedViewContainerMatrix.setScaleY(1f);
+
+        setScaleFromBubbleBar(mExpandedViewContainerMatrix, 1f);
 
         PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
         PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
@@ -240,6 +235,16 @@
         mExpandedViewAlphaAnimator.reverse();
     }
 
+    private void setScaleFromBubbleBar(AnimatableScaleMatrix matrix, float scale) {
+        // Set the pivot point for the scale, so the view animates out from the bubble bar.
+        Rect bubbleBarBounds = mPositioner.getBubbleBarBounds();
+        matrix.setScale(
+                scale,
+                scale,
+                bubbleBarBounds.centerX(),
+                bubbleBarBounds.top);
+    }
+
     /**
      * Animate the expanded bubble when it is being dragged
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt
index 18c7bdd..7eb0f26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.content.res.Resources
-import android.os.SystemProperties
 import android.util.Size
 import com.android.wm.shell.R
 import java.io.PrintWriter
@@ -36,30 +35,81 @@
     private var mOverrideMinSize: Size? = null
 
 
-    /** Default and minimum percentages for the PIP size logic.  */
-    private val mDefaultSizePercent: Float
-    private val mMinimumSizePercent: Float
+    /**
+     * Default percentages for the PIP size logic.
+     * 1. Determine max widths
+     * Subtract width of system UI and default padding from the shortest edge of the device.
+     * This is the max width.
+     * 2. Calculate Default and Mins
+     * Default is mSystemPreferredDefaultSizePercent of max-width/height.
+     * Min is mSystemPreferredMinimumSizePercent of it.
+     *
+     * NOTE: Do not use this directly, use the mPreferredDefaultSizePercent getter instead.
+     */
+    private var mSystemPreferredDefaultSizePercent = 0.6f
+    /** Minimum percentages for the PIP size logic. */
+    private var mSystemPreferredMinimumSizePercent = 0.5f
+
+    /** Threshold to categorize the Display as square, calculated as min(w, h) / max(w, h). */
+    private var mSquareDisplayThresholdForSystemPreferredSize = 0.95f
+    /**
+     * Default percentages for the PIP size logic when the Display is square-ish.
+     * This is used instead when the display is square-ish, like fold-ables when unfolded,
+     * to make sure that default PiP does not cover the hinge (halfway of the display).
+     * 1. Determine max widths
+     * Subtract width of system UI and default padding from the shortest edge of the device.
+     * This is the max width.
+     * 2. Calculate Default and Mins
+     * Default is mSystemPreferredDefaultSizePercent of max-width/height.
+     * Min is mSystemPreferredMinimumSizePercent of it.
+     *
+     * NOTE: Do not use this directly, use the mPreferredDefaultSizePercent getter instead.
+     */
+    private var mSystemPreferredDefaultSizePercentForSquareDisplay = 0.5f
+    /** Minimum percentages for the PIP size logic. */
+    private var mSystemPreferredMinimumSizePercentForSquareDisplay = 0.4f
+
+    private val mIsSquareDisplay
+        get() = minOf(pipDisplayLayoutState.displayLayout.width(),
+                        pipDisplayLayoutState.displayLayout.height()).toFloat() /
+                maxOf(pipDisplayLayoutState.displayLayout.width(),
+                        pipDisplayLayoutState.displayLayout.height()) >
+                mSquareDisplayThresholdForSystemPreferredSize
+    private val mPreferredDefaultSizePercent
+        get() = if (mIsSquareDisplay) mSystemPreferredDefaultSizePercentForSquareDisplay else
+            mSystemPreferredDefaultSizePercent
+
+    private val mPreferredMinimumSizePercent
+        get() = if (mIsSquareDisplay) mSystemPreferredMinimumSizePercentForSquareDisplay else
+            mSystemPreferredMinimumSizePercent
 
     /** Aspect ratio that the PIP size spec logic optimizes for.  */
     private var mOptimizedAspectRatio = 0f
 
     init {
-        mDefaultSizePercent = SystemProperties
-                .get("com.android.wm.shell.pip.phone.def_percentage", "0.6").toFloat()
-        mMinimumSizePercent = SystemProperties
-                .get("com.android.wm.shell.pip.phone.min_percentage", "0.5").toFloat()
-
         reloadResources()
     }
 
     private fun reloadResources() {
-        val res: Resources = context.getResources()
+        val res: Resources = context.resources
 
         mDefaultMinSize = res.getDimensionPixelSize(
                 R.dimen.default_minimal_size_pip_resizable_task)
         mOverridableMinSize = res.getDimensionPixelSize(
                 R.dimen.overridable_minimal_size_pip_resizable_task)
 
+        mSystemPreferredDefaultSizePercent = res.getFloat(
+                R.dimen.config_pipSystemPreferredDefaultSizePercent)
+        mSystemPreferredMinimumSizePercent = res.getFloat(
+                R.dimen.config_pipSystemPreferredMinimumSizePercent)
+
+        mSquareDisplayThresholdForSystemPreferredSize = res.getFloat(
+                R.dimen.config_pipSquareDisplayThresholdForSystemPreferredSize)
+        mSystemPreferredDefaultSizePercentForSquareDisplay = res.getFloat(
+                R.dimen.config_pipSystemPreferredDefaultSizePercentForSquareDisplay)
+        mSystemPreferredMinimumSizePercentForSquareDisplay = res.getFloat(
+                R.dimen.config_pipSystemPreferredMinimumSizePercentForSquareDisplay)
+
         val requestedOptAspRatio = res.getFloat(R.dimen.config_pipLargeScreenOptimizedAspectRatio)
         // make sure the optimized aspect ratio is valid with a default value to fall back to
         mOptimizedAspectRatio = if (requestedOptAspRatio > 1) {
@@ -128,7 +178,7 @@
             return minSize
         }
         val maxSize = getMaxSize(aspectRatio)
-        val defaultWidth = Math.max(Math.round(maxSize.width * mDefaultSizePercent),
+        val defaultWidth = Math.max(Math.round(maxSize.width * mPreferredDefaultSizePercent),
                 minSize.width)
         val defaultHeight = Math.round(defaultWidth / aspectRatio)
         return Size(defaultWidth, defaultHeight)
@@ -146,8 +196,8 @@
             return adjustOverrideMinSizeToAspectRatio(aspectRatio)!!
         }
         val maxSize = getMaxSize(aspectRatio)
-        var minWidth = Math.round(maxSize.width * mMinimumSizePercent)
-        var minHeight = Math.round(maxSize.height * mMinimumSizePercent)
+        var minWidth = Math.round(maxSize.width * mPreferredMinimumSizePercent)
+        var minHeight = Math.round(maxSize.height * mPreferredMinimumSizePercent)
 
         // make sure the calculated min size is not smaller than the allowed default min size
         if (aspectRatio > 1f) {
@@ -244,8 +294,8 @@
         pw.println(innerPrefix + "mOverrideMinSize=" + mOverrideMinSize)
         pw.println(innerPrefix + "mOverridableMinSize=" + mOverridableMinSize)
         pw.println(innerPrefix + "mDefaultMinSize=" + mDefaultMinSize)
-        pw.println(innerPrefix + "mDefaultSizePercent=" + mDefaultSizePercent)
-        pw.println(innerPrefix + "mMinimumSizePercent=" + mMinimumSizePercent)
+        pw.println(innerPrefix + "mDefaultSizePercent=" + mPreferredDefaultSizePercent)
+        pw.println(innerPrefix + "mMinimumSizePercent=" + mPreferredMinimumSizePercent)
         pw.println(innerPrefix + "mOptimizedAspectRatio=" + mOptimizedAspectRatio)
     }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
index b87c2f6..7ceaaea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
@@ -125,6 +125,7 @@
     private @Nullable Runnable mOnMinimalSizeChangeCallback;
     private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
     private List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>();
+    private List<Consumer<Float>> mOnAspectRatioChangedCallbacks = new ArrayList<>();
 
     // the size of the current bounds relative to the max size spec
     private float mBoundsScale;
@@ -297,7 +298,12 @@
 
     /** Set the PIP aspect ratio. */
     public void setAspectRatio(float aspectRatio) {
-        mAspectRatio = aspectRatio;
+        if (Float.compare(mAspectRatio, aspectRatio) != 0) {
+            mAspectRatio = aspectRatio;
+            for (Consumer<Float> callback : mOnAspectRatioChangedCallbacks) {
+                callback.accept(mAspectRatio);
+            }
+        }
     }
 
     /** Get the PIP aspect ratio. */
@@ -527,6 +533,23 @@
         mOnPipExclusionBoundsChangeCallbacks.remove(onPipExclusionBoundsChangeCallback);
     }
 
+    /** Adds callback to listen on aspect ratio change. */
+    public void addOnAspectRatioChangedCallback(
+            @NonNull Consumer<Float> onAspectRatioChangedCallback) {
+        if (!mOnAspectRatioChangedCallbacks.contains(onAspectRatioChangedCallback)) {
+            mOnAspectRatioChangedCallbacks.add(onAspectRatioChangedCallback);
+            onAspectRatioChangedCallback.accept(mAspectRatio);
+        }
+    }
+
+    /** Removes callback to listen on aspect ratio change. */
+    public void removeOnAspectRatioChangedCallback(
+            @NonNull Consumer<Float> onAspectRatioChangedCallback) {
+        if (mOnAspectRatioChangedCallbacks.contains(onAspectRatioChangedCallback)) {
+            mOnAspectRatioChangedCallbacks.remove(onAspectRatioChangedCallback);
+        }
+    }
+
     public LauncherState getLauncherState() {
         return mLauncherState;
     }
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 86571cf..5c292f1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -20,7 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.content.Context;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java
index a0986fa..2b0bd32 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java
@@ -16,10 +16,10 @@
 
 package com.android.wm.shell.compatui;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 
 import android.annotation.IdRes;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
index dbf7186..4e5c2fa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
@@ -16,16 +16,16 @@
 
 package com.android.wm.shell.compatui;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppCompatTaskInfo;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.TaskInfo;
 import android.content.Context;
 import android.graphics.Rect;
@@ -81,7 +81,8 @@
         super(context, taskInfo, syncQueue, taskListener, displayLayout);
         mCallback = callback;
         mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat;
-        mCameraCompatControlState = taskInfo.appCompatTaskInfo.cameraCompatControlState;
+        mCameraCompatControlState =
+                taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState;
         mCompatUIHintsState = compatUIHintsState;
         mCompatUIConfiguration = compatUIConfiguration;
         mOnRestartButtonClicked = onRestartButtonClicked;
@@ -135,7 +136,8 @@
         final boolean prevHasSizeCompat = mHasSizeCompat;
         final int prevCameraCompatControlState = mCameraCompatControlState;
         mHasSizeCompat = taskInfo.appCompatTaskInfo.topActivityInSizeCompat;
-        mCameraCompatControlState = taskInfo.appCompatTaskInfo.cameraCompatControlState;
+        mCameraCompatControlState =
+                taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState;
 
         if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) {
             return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
index 7c28099..8fb4bdb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
@@ -237,7 +237,8 @@
         final int letterboxWidth = taskInfo.topActivityLetterboxWidth;
         // App is not visibly letterboxed if it covers status bar/bottom insets or matches the
         // stable bounds, so don't show the button
-        if (stableBounds.height() <= letterboxHeight && stableBounds.width() <= letterboxWidth) {
+        if (stableBounds.height() <= letterboxHeight && stableBounds.width() <= letterboxWidth
+                && !taskInfo.isUserFullscreenOverrideEnabled) {
             return false;
         }
 
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 73228de..6834e6d 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
@@ -107,6 +107,7 @@
 import com.android.wm.shell.taskview.TaskViewFactoryController;
 import com.android.wm.shell.taskview.TaskViewTransitions;
 import com.android.wm.shell.transition.HomeTransitionObserver;
+import com.android.wm.shell.transition.MixedTransitionHandler;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
 import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -675,6 +676,22 @@
         return new TaskViewTransitions(transitions);
     }
 
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract MixedTransitionHandler optionalMixedTransitionHandler();
+
+    @WMSingleton
+    @Provides
+    static Optional<MixedTransitionHandler> provideMixedTransitionHandler(
+            @DynamicOverride Optional<MixedTransitionHandler> mixedTransitionHandler
+    ) {
+        if (mixedTransitionHandler.isPresent()) {
+            return mixedTransitionHandler;
+        }
+        return Optional.empty();
+    }
+
     //
     // Keyguard transitions (optional feature)
     //
@@ -934,6 +951,7 @@
             Optional<OneHandedController> oneHandedControllerOptional,
             Optional<HideDisplayCutoutController> hideDisplayCutoutControllerOptional,
             Optional<ActivityEmbeddingController> activityEmbeddingOptional,
+            Optional<MixedTransitionHandler> mixedTransitionHandler,
             Transitions transitions,
             StartingWindowController startingWindow,
             ProtoLogController protoLogController,
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 b933e5d..b574b81 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
@@ -29,6 +29,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.launcher3.icons.IconProvider;
+import com.android.window.flags.Flags;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.WindowManagerShellWrapper;
@@ -59,6 +60,8 @@
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
+import com.android.wm.shell.desktopmode.DesktopTasksTransitionObserver;
 import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
 import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
 import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
@@ -84,6 +87,7 @@
 import com.android.wm.shell.taskview.TaskViewTransitions;
 import com.android.wm.shell.transition.DefaultMixedHandler;
 import com.android.wm.shell.transition.HomeTransitionObserver;
+import com.android.wm.shell.transition.MixedTransitionHandler;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
 import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -241,6 +245,7 @@
                 mainChoreographer,
                 taskOrganizer,
                 displayController,
+                rootTaskDisplayAreaOrganizer,
                 syncQueue,
                 transitions);
     }
@@ -369,8 +374,9 @@
     //
 
     @WMSingleton
+    @DynamicOverride
     @Provides
-    static DefaultMixedHandler provideDefaultMixedHandler(
+    static MixedTransitionHandler provideMixedTransitionHandler(
             ShellInit shellInit,
             Optional<SplitScreenController> splitScreenOptional,
             @Nullable PipTransitionController pipTransitionController,
@@ -515,23 +521,39 @@
             LaunchAdjacentController launchAdjacentController,
             RecentsTransitionHandler recentsTransitionHandler,
             MultiInstanceHelper multiInstanceHelper,
-            @ShellMainThread ShellExecutor mainExecutor
-    ) {
+            @ShellMainThread ShellExecutor mainExecutor,
+            Optional<DesktopTasksLimiter> desktopTasksLimiter) {
         return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
                 displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
                 dragAndDropController, transitions, enterDesktopTransitionHandler,
                 exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler,
                 dragToDesktopTransitionHandler, desktopModeTaskRepository,
                 desktopModeLoggerTransitionObserver, launchAdjacentController,
-                recentsTransitionHandler, multiInstanceHelper, mainExecutor);
+                recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter);
     }
 
     @WMSingleton
     @Provides
+    static Optional<DesktopTasksLimiter> provideDesktopTasksLimiter(
+            Transitions transitions,
+            @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
+            ShellTaskOrganizer shellTaskOrganizer) {
+        if (!DesktopModeStatus.isEnabled() || !Flags.enableDesktopWindowingTaskLimit()) {
+            return Optional.empty();
+        }
+        return Optional.of(
+                new DesktopTasksLimiter(
+                        transitions, desktopModeTaskRepository, shellTaskOrganizer));
+    }
+
+
+    @WMSingleton
+    @Provides
     static DragToDesktopTransitionHandler provideDragToDesktopTransitionHandler(
             Context context,
             Transitions transitions,
-            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
+            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+            Optional<DesktopTasksLimiter> desktopTasksLimiter) {
         return new DragToDesktopTransitionHandler(context, transitions,
                 rootTaskDisplayAreaOrganizer);
     }
@@ -539,7 +561,8 @@
     @WMSingleton
     @Provides
     static EnterDesktopTaskTransitionHandler provideEnterDesktopModeTaskTransitionHandler(
-            Transitions transitions) {
+            Transitions transitions,
+            Optional<DesktopTasksLimiter> desktopTasksLimiter) {
         return new EnterDesktopTaskTransitionHandler(transitions);
     }
 
@@ -568,6 +591,18 @@
 
     @WMSingleton
     @Provides
+    static Optional<DesktopTasksTransitionObserver> provideDesktopTasksTransitionObserver(
+            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
+            Transitions transitions,
+            ShellInit shellInit
+    ) {
+        return desktopModeTaskRepository.flatMap(repository ->
+                Optional.of(new DesktopTasksTransitionObserver(repository, transitions, shellInit))
+        );
+    }
+
+    @WMSingleton
+    @Provides
     static DesktopModeLoggerTransitionObserver provideDesktopModeLoggerTransitionObserver(
             ShellInit shellInit,
             Transitions transitions,
@@ -622,7 +657,7 @@
     @Provides
     static Object provideIndependentShellComponentsToCreate(
             DragAndDropController dragAndDropController,
-            DefaultMixedHandler defaultMixedHandler) {
+            Optional<DesktopTasksTransitionObserver> desktopTasksTransitionObserverOptional) {
         return new Object();
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index b86e39f..4eff3f0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -23,19 +23,25 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.FloatingContentCoordinator;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SystemWindows;
 import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.common.pip.PipBoundsState;
 import com.android.wm.shell.common.pip.PipDisplayLayoutState;
 import com.android.wm.shell.common.pip.PipMediaController;
+import com.android.wm.shell.common.pip.PipPerfHintController;
+import com.android.wm.shell.common.pip.PipSnapAlgorithm;
 import com.android.wm.shell.common.pip.PipUiEventLogger;
 import com.android.wm.shell.common.pip.PipUtils;
+import com.android.wm.shell.common.pip.SizeSpecSource;
 import com.android.wm.shell.dagger.WMShellBaseModule;
 import com.android.wm.shell.dagger.WMSingleton;
 import com.android.wm.shell.pip2.phone.PhonePipMenuController;
 import com.android.wm.shell.pip2.phone.PipController;
+import com.android.wm.shell.pip2.phone.PipMotionHelper;
 import com.android.wm.shell.pip2.phone.PipScheduler;
+import com.android.wm.shell.pip2.phone.PipTouchHandler;
 import com.android.wm.shell.pip2.phone.PipTransition;
 import com.android.wm.shell.shared.annotations.ShellMainThread;
 import com.android.wm.shell.sysui.ShellController;
@@ -62,6 +68,7 @@
             PipBoundsState pipBoundsState,
             PipBoundsAlgorithm pipBoundsAlgorithm,
             Optional<PipController> pipController,
+            PipTouchHandler pipTouchHandler,
             @NonNull PipScheduler pipScheduler) {
         return new PipTransition(context, shellInit, shellTaskOrganizer, transitions,
                 pipBoundsState, null, pipBoundsAlgorithm, pipScheduler);
@@ -109,4 +116,34 @@
         return new PhonePipMenuController(context, pipBoundsState, pipMediaController,
                 systemWindows, pipUiEventLogger, mainExecutor, mainHandler);
     }
+
+
+    @WMSingleton
+    @Provides
+    static PipTouchHandler providePipTouchHandler(Context context,
+            ShellInit shellInit,
+            PhonePipMenuController menuPhoneController,
+            PipBoundsAlgorithm pipBoundsAlgorithm,
+            @NonNull PipBoundsState pipBoundsState,
+            @NonNull SizeSpecSource sizeSpecSource,
+            PipMotionHelper pipMotionHelper,
+            FloatingContentCoordinator floatingContentCoordinator,
+            PipUiEventLogger pipUiEventLogger,
+            @ShellMainThread ShellExecutor mainExecutor,
+            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
+        return new PipTouchHandler(context, shellInit, menuPhoneController, pipBoundsAlgorithm,
+                pipBoundsState, sizeSpecSource, pipMotionHelper, floatingContentCoordinator,
+                pipUiEventLogger, mainExecutor, pipPerfHintControllerOptional);
+    }
+
+    @WMSingleton
+    @Provides
+    static PipMotionHelper providePipMotionHelper(Context context,
+            PipBoundsState pipBoundsState, PhonePipMenuController menuController,
+            PipSnapAlgorithm pipSnapAlgorithm,
+            FloatingContentCoordinator floatingContentCoordinator,
+            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
+        return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm,
+                floatingContentCoordinator, pipPerfHintControllerOptional);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
index e1e41ee..f1a475a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
@@ -36,7 +36,14 @@
                     true
                 }
             }
-
+            "moveToNextDisplay" -> {
+                if (!runMoveToNextDisplay(args, pw)) {
+                    pw.println("Task not found. Please enter a valid taskId.")
+                    false
+                } else {
+                    true
+                }
+            }
             else -> {
                 pw.println("Invalid command: ${args[0]}")
                 false
@@ -61,8 +68,28 @@
         return controller.moveToDesktop(taskId, WindowContainerTransaction())
     }
 
+    private fun runMoveToNextDisplay(args: Array<String>, pw: PrintWriter): Boolean {
+        if (args.size < 2) {
+            // First argument is the action name.
+            pw.println("Error: task id should be provided as arguments")
+            return false
+        }
+
+        val taskId = try {
+            args[1].toInt()
+        } catch (e: NumberFormatException) {
+            pw.println("Error: task id should be an integer")
+            return false
+        }
+
+        controller.moveToNextDisplay(taskId)
+        return true
+    }
+
     override fun printShellCommandHelp(pw: PrintWriter, prefix: String) {
         pw.println("$prefix moveToDesktop <taskId> ")
         pw.println("$prefix  Move a task with given id to desktop mode.")
+        pw.println("$prefix moveToNextDisplay <taskId> ")
+        pw.println("$prefix  Move a task with given id to next display.")
     }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 32c22c0..fcddcad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -77,6 +77,22 @@
             "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
 
     /**
+     * Default value for {@code MAX_TASK_LIMIT}.
+     */
+    @VisibleForTesting
+    public static final int DEFAULT_MAX_TASK_LIMIT = 4;
+
+    // TODO(b/335131008): add a config-overlay field for the max number of tasks in Desktop Mode
+    /**
+     * Flag declaring the maximum number of Tasks to show in Desktop Mode at any one time.
+     *
+     * <p> The limit does NOT affect Picture-in-Picture, Bubbles, or System Modals (like a screen
+     * recording window, or Bluetooth pairing window).
+     */
+    private static final int MAX_TASK_LIMIT = SystemProperties.getInt(
+            "persist.wm.debug.desktop_max_task_limit", DEFAULT_MAX_TASK_LIMIT);
+
+    /**
      * Return {@code true} if desktop windowing is enabled
      */
     public static boolean isEnabled() {
@@ -124,6 +140,13 @@
     }
 
     /**
+     * Return the maximum limit on the number of Tasks to show in Desktop Mode at any one time.
+     */
+    static int getMaxTaskLimit() {
+        return MAX_TASK_LIMIT;
+    }
+
+    /**
      * Return {@code true} if the current device supports desktop mode.
      */
     @VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
index 120d681..2d508b2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
@@ -22,6 +22,7 @@
 import android.util.ArraySet
 import android.util.SparseArray
 import android.view.Display.INVALID_DISPLAY
+import android.window.WindowContainerToken
 import androidx.core.util.forEach
 import androidx.core.util.keyIterator
 import androidx.core.util.valueIterator
@@ -46,9 +47,12 @@
          */
         val activeTasks: ArraySet<Int> = ArraySet(),
         val visibleTasks: ArraySet<Int> = ArraySet(),
+        val minimizedTasks: ArraySet<Int> = ArraySet(),
         var stashed: Boolean = false
     )
 
+    // Token of the current wallpaper activity, used to remove it when the last task is removed
+    var wallpaperActivityToken: WindowContainerToken? = null
     // Tasks currently in freeform mode, ordered from top to bottom (top is at index 0).
     private val freeformTasksInZOrder = mutableListOf<Int>()
     private val activeTasksListeners = ArraySet<ActiveTasksListener>()
@@ -199,6 +203,22 @@
         }
     }
 
+    /** Return whether the given Task is minimized. */
+    fun isMinimizedTask(taskId: Int): Boolean {
+        return displayData.valueIterator().asSequence().any { data ->
+            data.minimizedTasks.contains(taskId)
+        }
+    }
+
+    /**
+     *  Check if a task with the given [taskId] is the only active task on its display
+     */
+    fun isOnlyActiveTask(taskId: Int): Boolean {
+        return displayData.valueIterator().asSequence().any { data ->
+            data.activeTasks.singleOrNull() == taskId
+        }
+    }
+
     /**
      * Get a set of the active tasks for given [displayId]
      */
@@ -207,6 +227,25 @@
     }
 
     /**
+     * Returns whether Desktop Mode is currently showing any tasks, i.e. whether any Desktop Tasks
+     * are visible.
+     */
+    fun isDesktopModeShowing(displayId: Int): Boolean = getVisibleTaskCount(displayId) > 0
+
+    /**
+     * Returns a list of Tasks IDs representing all active non-minimized Tasks on the given display,
+     * ordered from front to back.
+     */
+    fun getActiveNonMinimizedTasksOrderedFrontToBack(displayId: Int): List<Int> {
+        val activeTasks = getActiveTasks(displayId)
+        val allTasksInZOrder = getFreeformTasksInZOrder()
+        return activeTasks
+                // Don't show already minimized Tasks
+                .filter { taskId -> !isMinimizedTask(taskId) }
+                .sortedBy { taskId -> allTasksInZOrder.indexOf(taskId) }
+    }
+
+    /**
      * Get a list of freeform tasks, ordered from top-bottom (top at index 0).
      */
      // TODO(b/278084491): pass in display id
@@ -243,6 +282,7 @@
         val prevCount = getVisibleTaskCount(displayId)
         if (visible) {
             displayData.getOrCreate(displayId).visibleTasks.add(taskId)
+            unminimizeTask(displayId, taskId)
         } else {
             displayData[displayId]?.visibleTasks?.remove(taskId)
         }
@@ -300,6 +340,24 @@
         freeformTasksInZOrder.add(0, taskId)
     }
 
+    /** Mark a Task as minimized. */
+    fun minimizeTask(displayId: Int, taskId: Int) {
+        KtProtoLog.v(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopModeTaskRepository: minimize Task: display=%d, task=%d",
+                displayId, taskId)
+        displayData.getOrCreate(displayId).minimizedTasks.add(taskId)
+    }
+
+    /** Mark a Task as non-minimized. */
+    fun unminimizeTask(displayId: Int, taskId: Int) {
+        KtProtoLog.v(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopModeTaskRepository: unminimize Task: display=%d, task=%d",
+                displayId, taskId)
+        displayData[displayId]?.minimizedTasks?.remove(taskId)
+    }
+
     /**
      * Remove the task from the ordered list.
      */
@@ -313,7 +371,7 @@
         boundsBeforeMaximizeByTaskId.remove(taskId)
         KtProtoLog.d(
             WM_SHELL_DESKTOP_MODE,
-            "DesktopTaskRepo: remaining freeform tasks: " + freeformTasksInZOrder.toDumpString()
+            "DesktopTaskRepo: remaining freeform tasks: %s", freeformTasksInZOrder.toDumpString(),
         )
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index e210ea7..0a9e5d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -40,6 +40,7 @@
 import android.view.WindowManager.TRANSIT_CHANGE
 import android.view.WindowManager.TRANSIT_NONE
 import android.view.WindowManager.TRANSIT_OPEN
+import android.view.WindowManager.TRANSIT_TO_BACK
 import android.view.WindowManager.TRANSIT_TO_FRONT
 import android.window.RemoteTransition
 import android.window.TransitionInfo
@@ -87,6 +88,7 @@
 import com.android.wm.shell.windowdecor.extension.isFreeform
 import com.android.wm.shell.windowdecor.extension.isFullscreen
 import java.io.PrintWriter
+import java.util.Optional
 import java.util.concurrent.Executor
 import java.util.function.Consumer
 
@@ -112,7 +114,8 @@
         private val launchAdjacentController: LaunchAdjacentController,
         private val recentsTransitionHandler: RecentsTransitionHandler,
         private val multiInstanceHelper: MultiInstanceHelper,
-        @ShellMainThread private val mainExecutor: ShellExecutor
+        @ShellMainThread private val mainExecutor: ShellExecutor,
+        private val desktopTasksLimiter: Optional<DesktopTasksLimiter>,
 ) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler,
     DragAndDropController.DragAndDropListener {
 
@@ -340,11 +343,13 @@
         )
         exitSplitIfApplicable(wct, task)
         // Bring other apps to front first
-        bringDesktopAppsToFront(task.displayId, wct)
+        val taskToMinimize =
+                bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId)
         addMoveToDesktopChanges(wct, task)
 
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            enterDesktopTaskTransitionHandler.moveToDesktop(wct)
+            val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct)
+            addPendingMinimizeTransition(transition, taskToMinimize)
         } else {
             shellTaskOrganizer.applyTransaction(wct)
         }
@@ -382,10 +387,13 @@
         val wct = WindowContainerTransaction()
         exitSplitIfApplicable(wct, taskInfo)
         moveHomeTaskToFront(wct)
-        bringDesktopAppsToFront(taskInfo.displayId, wct)
+        val taskToMinimize =
+                bringDesktopAppsToFrontBeforeShowingNewTask(
+                        taskInfo.displayId, wct, taskInfo.taskId)
         addMoveToDesktopChanges(wct, taskInfo)
         wct.setBounds(taskInfo.token, freeformBounds)
-        dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct)
+        val transition = dragToDesktopTransitionHandler.finishDragToDesktopTransition(wct)
+        transition?.let { addPendingMinimizeTransition(it, taskToMinimize) }
     }
 
     /**
@@ -401,6 +409,22 @@
         shellTaskOrganizer.applyTransaction(wct)
     }
 
+    /**
+     * Perform clean up of the desktop wallpaper activity if the closed window task is
+     * the last active task.
+     *
+     * @param wct transaction to modify if the last active task is closed
+     * @param taskId task id of the window that's being closed
+     */
+    fun onDesktopWindowClose(
+        wct: WindowContainerTransaction,
+        taskId: Int
+    ) {
+        if (desktopModeTaskRepository.isOnlyActiveTask(taskId)) {
+            removeWallpaperActivity(wct)
+        }
+    }
+
     /** Move a task with given `taskId` to fullscreen */
     fun moveToFullscreen(taskId: Int) {
         shellTaskOrganizer.getRunningTaskInfo(taskId)?.let { task ->
@@ -491,8 +515,10 @@
 
         val wct = WindowContainerTransaction()
         wct.reorder(taskInfo.token, true)
+        val taskToMinimize = addAndGetMinimizeChangesIfNeeded(taskInfo.displayId, wct, taskInfo)
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            transitions.startTransition(TRANSIT_TO_FRONT, wct, null /* handler */)
+            val transition = transitions.startTransition(TRANSIT_TO_FRONT, wct, null /* handler */)
+            addPendingMinimizeTransition(transition, taskToMinimize)
         } else {
             shellTaskOrganizer.applyTransaction(wct)
         }
@@ -588,7 +614,7 @@
             if (taskBoundsBeforeMaximize != null) {
                 destinationBounds.set(taskBoundsBeforeMaximize)
             } else {
-                getDefaultDesktopTaskBounds(displayLayout, destinationBounds)
+                destinationBounds.set(getDefaultDesktopTaskBounds(displayLayout))
             }
         } else {
             // Save current bounds so that task can be restored back to original bounds if necessary
@@ -624,18 +650,14 @@
         }
     }
 
-    private fun getDefaultDesktopTaskBounds(displayLayout: DisplayLayout, outBounds: Rect) {
+    private fun getDefaultDesktopTaskBounds(displayLayout: DisplayLayout): Rect {
         // TODO(b/319819547): Account for app constraints so apps do not become letterboxed
-        val screenBounds = Rect(0, 0, displayLayout.width(), displayLayout.height())
-        // Update width and height with default desktop mode values
-        val desiredWidth = screenBounds.width().times(DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt()
-        val desiredHeight = screenBounds.height().times(DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt()
-        outBounds.set(0, 0, desiredWidth, desiredHeight)
-        // Center the task in screen bounds
-        outBounds.offset(
-            screenBounds.centerX() - outBounds.centerX(),
-            screenBounds.centerY() - outBounds.centerY()
-        )
+        val desiredWidth = (displayLayout.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt()
+        val desiredHeight = (displayLayout.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt()
+        val heightOffset = (displayLayout.height() - desiredHeight) / 2
+        val widthOffset = (displayLayout.width() - desiredWidth) / 2
+        return Rect(widthOffset, heightOffset,
+            desiredWidth + widthOffset, desiredHeight + heightOffset)
     }
 
     private fun getSnapBounds(taskInfo: RunningTaskInfo, position: SnapPosition): Rect {
@@ -676,19 +698,44 @@
             ?: WINDOWING_MODE_UNDEFINED
     }
 
-    private fun bringDesktopAppsToFront(displayId: Int, wct: WindowContainerTransaction) {
-        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: bringDesktopAppsToFront")
-        val activeTasks = desktopModeTaskRepository.getActiveTasks(displayId)
+    private fun bringDesktopAppsToFrontBeforeShowingNewTask(
+            displayId: Int,
+            wct: WindowContainerTransaction,
+            newTaskIdInFront: Int
+    ): RunningTaskInfo? = bringDesktopAppsToFront(displayId, wct, newTaskIdInFront)
 
-        // First move home to front and then other tasks on top of it
-        moveHomeTaskToFront(wct)
+    private fun bringDesktopAppsToFront(
+            displayId: Int,
+            wct: WindowContainerTransaction,
+            newTaskIdInFront: Int? = null
+    ): RunningTaskInfo? {
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksController: bringDesktopAppsToFront, newTaskIdInFront=%s",
+                newTaskIdInFront ?: "null")
 
-        val allTasksInZOrder = desktopModeTaskRepository.getFreeformTasksInZOrder()
-        activeTasks
-            // Sort descending as the top task is at index 0. It should be ordered to top last
-            .sortedByDescending { taskId -> allTasksInZOrder.indexOf(taskId) }
-            .mapNotNull { taskId -> shellTaskOrganizer.getRunningTaskInfo(taskId) }
-            .forEach { task -> wct.reorder(task.token, true /* onTop */) }
+        if (Flags.enableDesktopWindowingWallpaperActivity()) {
+            // Add translucent wallpaper activity to show the wallpaper underneath
+            addWallpaperActivity(wct)
+        } else {
+            // Move home to front
+            moveHomeTaskToFront(wct)
+        }
+
+        val nonMinimizedTasksOrderedFrontToBack =
+                desktopModeTaskRepository.getActiveNonMinimizedTasksOrderedFrontToBack(displayId)
+        // If we're adding a new Task we might need to minimize an old one
+        val taskToMinimize: RunningTaskInfo? =
+                if (newTaskIdInFront != null && desktopTasksLimiter.isPresent) {
+                    desktopTasksLimiter.get().getTaskToMinimizeIfNeeded(
+                            nonMinimizedTasksOrderedFrontToBack, newTaskIdInFront)
+                } else { null }
+        nonMinimizedTasksOrderedFrontToBack
+                // If there is a Task to minimize, let it stay behind the Home Task
+                .filter { taskId -> taskId != taskToMinimize?.taskId }
+                .mapNotNull { taskId -> shellTaskOrganizer.getRunningTaskInfo(taskId) }
+                .reversed() // Start from the back so the front task is brought forward last
+                .forEach { task -> wct.reorder(task.token, true /* onTop */) }
+        return taskToMinimize
     }
 
     private fun moveHomeTaskToFront(wct: WindowContainerTransaction) {
@@ -698,6 +745,26 @@
             ?.let { homeTask -> wct.reorder(homeTask.getToken(), true /* onTop */) }
     }
 
+    private fun addWallpaperActivity(wct: WindowContainerTransaction) {
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: addWallpaper")
+        val intent = Intent(context, DesktopWallpaperActivity::class.java)
+        val options = ActivityOptions.makeBasic().apply {
+            isPendingIntentBackgroundActivityLaunchAllowedByPermission = true
+            pendingIntentBackgroundActivityStartMode =
+                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+        }
+        val pendingIntent = PendingIntent.getActivity(context, /* requestCode = */ 0, intent,
+            PendingIntent.FLAG_IMMUTABLE)
+        wct.sendPendingIntent(pendingIntent, intent, options.toBundle())
+    }
+
+    private fun removeWallpaperActivity(wct: WindowContainerTransaction) {
+        desktopModeTaskRepository.wallpaperActivityToken?.let { token ->
+            KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: removeWallpaper")
+            wct.removeTask(token)
+        }
+    }
+
     fun releaseVisualIndicator() {
         val t = SurfaceControl.Transaction()
         visualIndicator?.releaseVisualIndicator(t)
@@ -745,6 +812,9 @@
                     reason = "recents animation is running"
                     false
                 }
+                // Handle back navigation for the last window if wallpaper available
+                shouldRemoveWallpaper(request) ->
+                    true
                 // Only handle open or to front transitions
                 request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> {
                     reason = "transition type not handled (${request.type})"
@@ -781,14 +851,15 @@
 
         val result = triggerTask?.let { task ->
             when {
+                request.type == TRANSIT_TO_BACK -> handleBackNavigation(task)
                 // If display has tasks stashed, handle as stashed launch
-                task.isStashed -> handleStashedTaskLaunch(task)
+                task.isStashed -> handleStashedTaskLaunch(task, transition)
                 // Check if the task has a top transparent activity
                 shouldLaunchAsModal(task) -> handleTransparentTaskLaunch(task)
                 // Check if fullscreen task should be updated
-                task.isFullscreen -> handleFullscreenTaskLaunch(task)
+                task.isFullscreen -> handleFullscreenTaskLaunch(task, transition)
                 // Check if freeform task should be updated
-                task.isFreeform -> handleFreeformTaskLaunch(task)
+                task.isFreeform -> handleFreeformTaskLaunch(task, transition)
                 else -> {
                     null
                 }
@@ -828,10 +899,20 @@
         return Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task)
     }
 
-    private fun handleFreeformTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction? {
+    private fun shouldRemoveWallpaper(request: TransitionRequestInfo): Boolean {
+        return Flags.enableDesktopWindowingWallpaperActivity() &&
+                request.type == TRANSIT_TO_BACK &&
+                request.triggerTask?.let { task ->
+                    desktopModeTaskRepository.isOnlyActiveTask(task.taskId)
+                } ?: false
+    }
+
+    private fun handleFreeformTaskLaunch(
+            task: RunningTaskInfo,
+            transition: IBinder
+    ): WindowContainerTransaction? {
         KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleFreeformTaskLaunch")
-        val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
-        if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
+        if (!desktopModeTaskRepository.isDesktopModeShowing(task.displayId)) {
             KtProtoLog.d(
                     WM_SHELL_DESKTOP_MODE,
                     "DesktopTasksController: switch freeform task to fullscreen oon transition" +
@@ -842,13 +923,23 @@
                 addMoveToFullscreenChanges(wct, task)
             }
         }
+        // Desktop Mode is showing and we're launching a new Task - we might need to minimize
+        // a Task.
+        val wct = WindowContainerTransaction()
+        val taskToMinimize = addAndGetMinimizeChangesIfNeeded(task.displayId, wct, task)
+        if (taskToMinimize != null) {
+            addPendingMinimizeTransition(transition, taskToMinimize)
+            return wct
+        }
         return null
     }
 
-    private fun handleFullscreenTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction? {
+    private fun handleFullscreenTaskLaunch(
+            task: RunningTaskInfo,
+            transition: IBinder
+    ): WindowContainerTransaction? {
         KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleFullscreenTaskLaunch")
-        val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
-        if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) {
+        if (desktopModeTaskRepository.isDesktopModeShowing(task.displayId)) {
             KtProtoLog.d(
                     WM_SHELL_DESKTOP_MODE,
                     "DesktopTasksController: switch fullscreen task to freeform on transition" +
@@ -857,21 +948,30 @@
             )
             return WindowContainerTransaction().also { wct ->
                 addMoveToDesktopChanges(wct, task)
+                // Desktop Mode is already showing and we're launching a new Task - we might need to
+                // minimize another Task.
+                val taskToMinimize = addAndGetMinimizeChangesIfNeeded(task.displayId, wct, task)
+                addPendingMinimizeTransition(transition, taskToMinimize)
             }
         }
         return null
     }
 
-    private fun handleStashedTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction {
+    private fun handleStashedTaskLaunch(
+            task: RunningTaskInfo,
+            transition: IBinder
+    ): WindowContainerTransaction {
         KtProtoLog.d(
                 WM_SHELL_DESKTOP_MODE,
                 "DesktopTasksController: launch apps with stashed on transition taskId=%d",
                 task.taskId
         )
         val wct = WindowContainerTransaction()
-        bringDesktopAppsToFront(task.displayId, wct)
+        val taskToMinimize =
+                bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId)
         addMoveToDesktopChanges(wct, task)
         desktopModeTaskRepository.setStashed(task.displayId, false)
+        addPendingMinimizeTransition(transition, taskToMinimize)
         return wct
     }
 
@@ -885,12 +985,26 @@
         }
     }
 
+    /** Handle back navigation by removing wallpaper activity if it's the last active task */
+    private fun handleBackNavigation(task: RunningTaskInfo): WindowContainerTransaction? {
+        if (desktopModeTaskRepository.isOnlyActiveTask(task.taskId) &&
+            desktopModeTaskRepository.wallpaperActivityToken != null) {
+            // Remove wallpaper activity when the last active task is removed
+            return WindowContainerTransaction().also { wct ->
+                removeWallpaperActivity(wct)
+            }
+        } else {
+            return null
+        }
+    }
+
     private fun addMoveToDesktopChanges(
         wct: WindowContainerTransaction,
         taskInfo: RunningTaskInfo
     ) {
-        val displayWindowingMode = taskInfo.configuration.windowConfiguration.displayWindowingMode
-        val targetWindowingMode = if (displayWindowingMode == WINDOWING_MODE_FREEFORM) {
+        val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(taskInfo.displayId)!!
+        val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
+        val targetWindowingMode = if (tdaWindowingMode == WINDOWING_MODE_FREEFORM) {
             // Display windowing is freeform, set to undefined and inherit it
             WINDOWING_MODE_UNDEFINED
         } else {
@@ -907,8 +1021,9 @@
         wct: WindowContainerTransaction,
         taskInfo: RunningTaskInfo
     ) {
-        val displayWindowingMode = taskInfo.configuration.windowConfiguration.displayWindowingMode
-        val targetWindowingMode = if (displayWindowingMode == WINDOWING_MODE_FULLSCREEN) {
+        val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(taskInfo.displayId)!!
+        val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
+        val targetWindowingMode = if (tdaWindowingMode == WINDOWING_MODE_FULLSCREEN) {
             // Display windowing is fullscreen, set to undefined and inherit it
             WINDOWING_MODE_UNDEFINED
         } else {
@@ -937,6 +1052,28 @@
         wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
     }
 
+    /** Returns the ID of the Task that will be minimized, or null if no task will be minimized. */
+    private fun addAndGetMinimizeChangesIfNeeded(
+            displayId: Int,
+            wct: WindowContainerTransaction,
+            newTaskInfo: RunningTaskInfo
+    ): RunningTaskInfo? {
+        if (!desktopTasksLimiter.isPresent) return null
+        return desktopTasksLimiter.get().addAndGetMinimizeTaskChangesIfNeeded(
+                displayId, wct, newTaskInfo)
+    }
+
+    private fun addPendingMinimizeTransition(
+            transition: IBinder,
+            taskToMinimize: RunningTaskInfo?
+    ) {
+        if (taskToMinimize == null) return
+        desktopTasksLimiter.ifPresent {
+            it.addPendingMinimizeChange(
+                    transition, taskToMinimize.displayId, taskToMinimize.taskId)
+        }
+    }
+
     /** Enter split by using the focused desktop task in given `displayId`. */
     fun enterSplit(
         displayId: Int,
@@ -1090,17 +1227,14 @@
      * @param taskInfo the task being dragged.
      * @param y height of drag, to be checked against status bar height.
      */
-    fun onDragPositioningEndThroughStatusBar(
-            inputCoordinates: PointF,
-            taskInfo: RunningTaskInfo,
-            freeformBounds: Rect
-    ) {
+    fun onDragPositioningEndThroughStatusBar(inputCoordinates: PointF, taskInfo: RunningTaskInfo) {
         val indicator = visualIndicator ?: return
         val indicatorType = indicator
             .updateIndicatorType(inputCoordinates, taskInfo.windowingMode)
         when (indicatorType) {
             DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR -> {
-                finalizeDragToDesktop(taskInfo, freeformBounds)
+                val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return
+                finalizeDragToDesktop(taskInfo, getDefaultDesktopTaskBounds(displayLayout))
             }
             DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR,
                     DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR -> {
@@ -1354,6 +1488,13 @@
                     "setTaskListener"
             ) { _ -> listener?.let { remoteListener.register(it) } ?: remoteListener.unregister() }
         }
+
+        override fun moveToDesktop(taskId: Int) {
+            ExecutorUtils.executeRemoteCallWithTaskPermission(
+                controller,
+                "moveToDesktop"
+            ) { c -> c.moveToDesktop(taskId) }
+        }
     }
 
     companion object {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
new file mode 100644
index 0000000..3404d37
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.os.IBinder
+import android.view.SurfaceControl
+import android.view.WindowManager.TRANSIT_TO_BACK
+import android.window.TransitionInfo
+import android.window.WindowContainerTransaction
+import androidx.annotation.VisibleForTesting
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.protolog.ShellProtoLogGroup
+import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.transition.Transitions.TransitionObserver
+import com.android.wm.shell.util.KtProtoLog
+
+/**
+ * Limits the number of tasks shown in Desktop Mode.
+ *
+ * This class should only be used if
+ * [com.android.window.flags.Flags.enableDesktopWindowingTaskLimit()] is true.
+ */
+class DesktopTasksLimiter (
+        transitions: Transitions,
+        private val taskRepository: DesktopModeTaskRepository,
+        private val shellTaskOrganizer: ShellTaskOrganizer,
+) {
+    private val minimizeTransitionObserver = MinimizeTransitionObserver()
+
+    init {
+        transitions.registerObserver(minimizeTransitionObserver)
+    }
+
+    private data class TaskDetails (val displayId: Int, val taskId: Int)
+
+    // TODO(b/333018485): replace this observer when implementing the minimize-animation
+    private inner class MinimizeTransitionObserver : TransitionObserver {
+        private val mPendingTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>()
+
+        fun addPendingTransitionToken(transition: IBinder, taskDetails: TaskDetails) {
+            mPendingTransitionTokensAndTasks[transition] = taskDetails
+        }
+
+        override fun onTransitionReady(
+                transition: IBinder,
+                info: TransitionInfo,
+                startTransaction: SurfaceControl.Transaction,
+                finishTransaction: SurfaceControl.Transaction
+        ) {
+            val taskToMinimize = mPendingTransitionTokensAndTasks.remove(transition) ?: return
+
+            if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return
+
+            if (!isTaskReorderedToBackOrInvisible(info, taskToMinimize)) {
+                KtProtoLog.v(
+                        ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+                        "DesktopTasksLimiter: task %d is not reordered to back nor invis",
+                        taskToMinimize.taskId)
+                return
+            }
+            [email protected](
+                    taskToMinimize.displayId, taskToMinimize.taskId)
+        }
+
+        /**
+         * Returns whether the given Task is being reordered to the back in the given transition, or
+         * is already invisible.
+         *
+         * <p> This check can be used to double-check that a task was indeed minimized before
+         * marking it as such.
+         */
+        private fun isTaskReorderedToBackOrInvisible(
+                info: TransitionInfo,
+                taskDetails: TaskDetails
+        ): Boolean {
+            val taskChange = info.changes.find { change ->
+                change.taskInfo?.taskId == taskDetails.taskId }
+            if (taskChange == null) {
+                return !taskRepository.isVisibleTask(taskDetails.taskId)
+            }
+            return taskChange.mode == TRANSIT_TO_BACK
+        }
+
+        override fun onTransitionStarting(transition: IBinder) {}
+
+        override fun onTransitionMerged(merged: IBinder, playing: IBinder) {
+            mPendingTransitionTokensAndTasks.remove(merged)?.let { taskToTransfer ->
+                mPendingTransitionTokensAndTasks[playing] = taskToTransfer
+            }
+        }
+
+        override fun onTransitionFinished(transition: IBinder, aborted: Boolean) {
+            KtProtoLog.v(
+                    ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+                    "DesktopTasksLimiter: transition %s finished", transition)
+            mPendingTransitionTokensAndTasks.remove(transition)
+        }
+    }
+
+    /**
+     * Mark a task as minimized, this should only be done after the corresponding transition has
+     * finished so we don't minimize the task if the transition fails.
+     */
+    private fun markTaskMinimized(displayId: Int, taskId: Int) {
+        KtProtoLog.v(
+                ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksLimiter: marking %d as minimized", taskId)
+        taskRepository.minimizeTask(displayId, taskId)
+    }
+
+    /**
+     * Add a minimize-transition to [wct] if adding [newFrontTaskInfo] brings us over the task
+     * limit.
+     *
+     * @param transition the transition that the minimize-transition will be appended to, or null if
+     * the transition will be started later.
+     * @return the ID of the minimized task, or null if no task is being minimized.
+     */
+    fun addAndGetMinimizeTaskChangesIfNeeded(
+            displayId: Int,
+            wct: WindowContainerTransaction,
+            newFrontTaskInfo: RunningTaskInfo,
+    ): RunningTaskInfo? {
+        KtProtoLog.v(
+                ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksLimiter: addMinimizeBackTaskChangesIfNeeded, newFrontTask=%d",
+                newFrontTaskInfo.taskId)
+        val newTaskListOrderedFrontToBack = createOrderedTaskListWithGivenTaskInFront(
+                taskRepository.getActiveNonMinimizedTasksOrderedFrontToBack(displayId),
+                newFrontTaskInfo.taskId)
+        val taskToMinimize = getTaskToMinimizeIfNeeded(newTaskListOrderedFrontToBack)
+        if (taskToMinimize != null) {
+            wct.reorder(taskToMinimize.token, false /* onTop */)
+            return taskToMinimize
+        }
+        return null
+    }
+
+    /**
+     * Add a pending minimize transition change, to update the list of minimized apps once the
+     * transition goes through.
+     */
+    fun addPendingMinimizeChange(transition: IBinder, displayId: Int, taskId: Int) {
+        minimizeTransitionObserver.addPendingTransitionToken(
+                transition, TaskDetails(displayId, taskId))
+    }
+
+    /**
+     * Returns the maximum number of tasks that should ever be displayed at the same time in Desktop
+     * Mode.
+     */
+    fun getMaxTaskLimit(): Int = DesktopModeStatus.getMaxTaskLimit()
+
+    /**
+     * Returns the Task to minimize given 1. a list of visible tasks ordered from front to back and
+     * 2. a new task placed in front of all the others.
+     */
+    fun getTaskToMinimizeIfNeeded(
+            visibleFreeformTaskIdsOrderedFrontToBack: List<Int>,
+            newTaskIdInFront: Int
+    ): RunningTaskInfo? {
+        return getTaskToMinimizeIfNeeded(
+                createOrderedTaskListWithGivenTaskInFront(
+                        visibleFreeformTaskIdsOrderedFrontToBack, newTaskIdInFront))
+    }
+
+    /** Returns the Task to minimize given a list of visible tasks ordered from front to back. */
+    fun getTaskToMinimizeIfNeeded(
+            visibleFreeformTaskIdsOrderedFrontToBack: List<Int>
+    ): RunningTaskInfo? {
+        if (visibleFreeformTaskIdsOrderedFrontToBack.size <= getMaxTaskLimit()) {
+            KtProtoLog.v(
+                    ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+                    "DesktopTasksLimiter: no need to minimize; tasks below limit")
+            // No need to minimize anything
+            return null
+        }
+        val taskToMinimize =
+                shellTaskOrganizer.getRunningTaskInfo(
+                        visibleFreeformTaskIdsOrderedFrontToBack.last())
+        if (taskToMinimize == null) {
+            KtProtoLog.e(
+                    ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+                    "DesktopTasksLimiter: taskToMinimize == null")
+            return null
+        }
+        return taskToMinimize
+    }
+
+    private fun createOrderedTaskListWithGivenTaskInFront(
+            existingTaskIdsOrderedFrontToBack: List<Int>,
+            newTaskId: Int
+    ): List<Int> {
+        return listOf(newTaskId) +
+                existingTaskIdsOrderedFrontToBack.filter { taskId -> taskId != newTaskId }
+    }
+
+    @VisibleForTesting
+    fun getTransitionObserver(): TransitionObserver {
+        return minimizeTransitionObserver
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
new file mode 100644
index 0000000..20df264
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode
+
+import android.os.IBinder
+import android.view.SurfaceControl
+import android.view.WindowManager
+import android.window.TransitionInfo
+import com.android.window.flags.Flags.enableDesktopWindowingWallpaperActivity
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.sysui.ShellInit
+import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.util.KtProtoLog
+
+/**
+ * A [Transitions.TransitionObserver] that observes shell transitions and updates
+ * the [DesktopModeTaskRepository] state TODO: b/332682201
+ * This observes transitions related to desktop mode
+ * and other transitions that originate both within and outside shell.
+ */
+class DesktopTasksTransitionObserver(
+    private val desktopModeTaskRepository: DesktopModeTaskRepository,
+    private val transitions: Transitions,
+    shellInit: ShellInit
+) : Transitions.TransitionObserver {
+
+    init {
+        if (Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.isEnabled()) {
+            shellInit.addInitCallback(::onInit, this)
+        }
+    }
+
+    fun onInit() {
+        KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "DesktopTasksTransitionObserver: onInit")
+        transitions.registerObserver(this)
+    }
+
+    override fun onTransitionReady(
+        transition: IBinder,
+        info: TransitionInfo,
+        startTransaction: SurfaceControl.Transaction,
+        finishTransaction: SurfaceControl.Transaction
+    ) {
+        // TODO: b/332682201 Update repository state
+        updateWallpaperToken(info)
+    }
+
+    override fun onTransitionStarting(transition: IBinder) {
+        // TODO: b/332682201 Update repository state
+    }
+
+    override fun onTransitionMerged(merged: IBinder, playing: IBinder) {
+        // TODO: b/332682201 Update repository state
+    }
+
+    override fun onTransitionFinished(transition: IBinder, aborted: Boolean) {
+        // TODO: b/332682201 Update repository state
+    }
+
+    private fun updateWallpaperToken(info: TransitionInfo) {
+        if (!enableDesktopWindowingWallpaperActivity()) {
+            return
+        }
+        info.changes.forEach { change ->
+            change.taskInfo?.let { taskInfo ->
+                if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) {
+                    when (change.mode) {
+                        WindowManager.TRANSIT_OPEN ->
+                            desktopModeTaskRepository.wallpaperActivityToken = taskInfo.token
+                        WindowManager.TRANSIT_CLOSE ->
+                            desktopModeTaskRepository.wallpaperActivityToken = null
+                        else -> {}
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt
new file mode 100644
index 0000000..c4a4474
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode
+
+import android.app.Activity
+import android.app.ActivityManager
+import android.content.ComponentName
+import android.os.Bundle
+import android.view.WindowManager
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.util.KtProtoLog
+
+/**
+ * A transparent activity used in the desktop mode to show the wallpaper under the freeform windows.
+ * This activity will be running in `FULLSCREEN` windowing mode, which ensures it hides Launcher.
+ * When entering desktop, we would ensure that it's added behind desktop apps and removed when
+ * leaving the desktop mode.
+ *
+ * Note! This activity should NOT interact directly with any other code in the Shell without calling
+ * onto the shell main thread. Activities are always started on the main thread.
+ */
+class DesktopWallpaperActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "DesktopWallpaperActivity: onCreate")
+        super.onCreate(savedInstanceState)
+        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
+    }
+
+    companion object {
+        private const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
+        private val wallpaperActivityComponent =
+            ComponentName(SYSTEM_UI_PACKAGE_NAME, DesktopWallpaperActivity::class.java.name)
+
+        @JvmStatic
+        fun isWallpaperTask(taskInfo: ActivityManager.RunningTaskInfo) =
+            taskInfo.baseIntent.component?.let(::isWallpaperComponent) ?: false
+
+        @JvmStatic
+        fun isWallpaperComponent(component: ComponentName) =
+            component == wallpaperActivityComponent
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index 0061d03..e341f2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -150,20 +150,20 @@
      * windowing mode changes to the dragged task. This is called when the dragged task is released
      * inside the desktop drop zone.
      */
-    fun finishDragToDesktopTransition(wct: WindowContainerTransaction) {
+    fun finishDragToDesktopTransition(wct: WindowContainerTransaction): IBinder? {
         if (!inProgress) {
             // Don't attempt to finish a drag to desktop transition since there is no transition in
             // progress which means that the drag to desktop transition was never successfully
             // started.
-            return
+            return null
         }
         if (requireTransitionState().startAborted) {
             // Don't attempt to complete the drag-to-desktop since the start transition didn't
             // succeed as expected. Just reset the state as if nothing happened.
             clearState()
-            return
+            return null
         }
-        transitions.startTransition(TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, wct, this)
+        return transitions.startTransition(TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, wct, this)
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
index 79bb540..74b8f83 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
@@ -78,10 +78,12 @@
     /**
      * Starts Transition of type TRANSIT_MOVE_TO_DESKTOP
      * @param wct WindowContainerTransaction for transition
+     * @return the token representing the started transition
      */
-    public void moveToDesktop(@NonNull WindowContainerTransaction wct) {
+    public IBinder moveToDesktop(@NonNull WindowContainerTransaction wct) {
         final IBinder token = mTransitions.startTransition(TRANSIT_MOVE_TO_DESKTOP, wct, this);
         mPendingTransitionTokens.add(token);
+        return token;
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl
index 6bdaf1e..fa43522 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl
@@ -45,4 +45,7 @@
 
     /** Set listener that will receive callbacks about updates to desktop tasks */
     oneway void setTaskListener(IDesktopTaskListener listener);
+
+    /** Move a task with given `taskId` to desktop */
+    void moveToDesktop(int taskId);
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index f2bdcae..6fea203 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -95,6 +95,7 @@
         if (DesktopModeStatus.isEnabled()) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
+                repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
                 if (taskInfo.isVisible) {
                     if (repository.addActiveTask(taskInfo.displayId, taskInfo.taskId)) {
                         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
@@ -116,6 +117,7 @@
         if (DesktopModeStatus.isEnabled()) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 repository.removeFreeformTask(taskInfo.taskId);
+                repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
                 if (repository.removeActiveTask(taskInfo.taskId)) {
                     ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
                             "Removing active freeform task: #%d", taskInfo.taskId);
@@ -162,6 +164,7 @@
         if (DesktopModeStatus.isEnabled() && taskInfo.isFocused) {
             mDesktopModeTaskRepository.ifPresent(repository -> {
                 repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
+                repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
             });
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS
index ec09827..afddfab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS
@@ -1,3 +1,2 @@
 # WM shell sub-module pip owner
 [email protected]
[email protected]
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 4c47737..eb845db 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
@@ -743,11 +743,6 @@
                             .alpha(tx, leash, 1f)
                             .round(tx, leash, shouldApplyCornerRadius())
                             .shadow(tx, leash, shouldApplyShadowRadius());
-                    // TODO(b/178632364): this is a work around for the black background when
-                    // entering PiP in button navigation mode.
-                    if (isInPipDirection(direction)) {
-                        tx.setWindowCrop(leash, getStartValue());
-                    }
                     tx.show(leash);
                     tx.apply();
                 }
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 c16eac8..e885262 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
@@ -96,6 +96,7 @@
 import com.android.wm.shell.transition.Transitions;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Consumer;
@@ -522,9 +523,27 @@
             mTaskOrganizer.reparentChildSurfaceToTask(taskId, overlay, t);
             t.setLayer(overlay, Integer.MAX_VALUE);
             t.apply();
+            // This serves as a last resort in case the Shell Transition is not handled properly.
+            // We want to make sure the overlay passed from Launcher gets removed eventually.
+            mayRemoveContentOverlay(overlay);
         }
     }
 
+    private void mayRemoveContentOverlay(SurfaceControl overlay) {
+        final WeakReference<SurfaceControl> overlayRef = new WeakReference<>(overlay);
+        final long timeoutDuration = (mEnterAnimationDuration
+                + CONTENT_OVERLAY_FADE_OUT_DELAY_MS
+                + EXTRA_CONTENT_OVERLAY_FADE_OUT_DELAY_MS) * 2L;
+        mMainExecutor.executeDelayed(() -> {
+            final SurfaceControl overlayLeash = overlayRef.get();
+            if (overlayLeash != null && overlayLeash.isValid() && overlayLeash == mPipOverlay) {
+                ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "Cleanup the overlay(%s) as a last resort.", overlayLeash);
+                removeContentOverlay(overlayLeash, null /* callback */);
+            }
+        }, timeoutDuration);
+    }
+
     /**
      * Callback when launcher aborts swipe-pip-to-home operation.
      */
@@ -578,6 +597,17 @@
             return;
         }
 
+        if (mPipTransitionState.isEnteringPip()
+                && !mPipTransitionState.getInSwipePipToHomeTransition()) {
+            // If we are still entering PiP with Shell playing enter animation, jump-cut to
+            // the end of the enter animation and reschedule exitPip to run after enter-PiP
+            // has finished its transition and allowed the client to draw in PiP mode.
+            mPipTransitionController.end(() -> {
+                exitPip(animationDurationMs, requestEnterSplit);
+            });
+            return;
+        }
+
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                 "exitPip: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
         final WindowContainerTransaction wct = new WindowContainerTransaction();
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 d60f5a6..fdde3ee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -43,7 +43,6 @@
 import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
 
-import android.animation.Animator;
 import android.annotation.IntDef;
 import android.app.ActivityManager;
 import android.app.TaskInfo;
@@ -348,9 +347,16 @@
 
     @Override
     public void end() {
-        Animator animator = mPipAnimationController.getCurrentAnimator();
-        if (animator != null && animator.isRunning()) {
-            animator.end();
+        end(null);
+    }
+
+    @Override
+    public void end(@Nullable Runnable onTransitionEnd) {
+        if (mPipAnimationController.isAnimating()) {
+            mPipAnimationController.getCurrentAnimator().end();
+        }
+        if (onTransitionEnd != null) {
+            onTransitionEnd.run();
         }
     }
 
@@ -818,8 +824,13 @@
             @NonNull Transitions.TransitionFinishCallback finishCallback,
             @NonNull TaskInfo taskInfo) {
         startTransaction.apply();
-        finishTransaction.setWindowCrop(info.getChanges().get(0).getLeash(),
-                mPipDisplayLayoutState.getDisplayBounds());
+        if (info.getChanges().isEmpty()) {
+            ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "removePipImmediately is called with empty changes");
+        } else {
+            finishTransaction.setWindowCrop(info.getChanges().get(0).getLeash(),
+                    mPipDisplayLayoutState.getDisplayBounds());
+        }
         mPipOrganizer.onExitPipFinished(taskInfo);
         finishCallback.onTransitionFinished(null);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 32442f7..4f71a02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -305,6 +305,14 @@
     public void end() {
     }
 
+    /**
+     * End the currently-playing PiP animation.
+     *
+     * @param onTransitionEnd callback to run upon finishing the playing transition.
+     */
+    public void end(@Nullable Runnable onTransitionEnd) {
+    }
+
     /** Starts the {@link android.window.SystemPerformanceHinter.HighPerfSession}. */
     public void startHighPerfSession() {}
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index c1adfff..d8ac8e9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -219,6 +219,7 @@
                 mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
                 this::onAccessibilityShowMenu, this::updateMovementBounds,
                 this::animateToUnStashedState, mainExecutor);
+        mPipBoundsState.addOnAspectRatioChangedCallback(this::updateMinMaxSize);
 
         // TODO(b/181599115): This should really be initializes as part of the pip controller, but
         // until all PIP implementations derive from the controller, just initialize the touch handler
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS
index 6dabb3b..79d1793 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS
@@ -1,4 +1,3 @@
 # WM shell sub-module pip owner
 [email protected]
[email protected]
 [email protected]
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java
new file mode 100644
index 0000000..e7e7970
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2.phone;
+
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.bubbles.DismissViewUtils;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.bubbles.DismissCircleView;
+import com.android.wm.shell.common.bubbles.DismissView;
+import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
+import com.android.wm.shell.common.pip.PipUiEventLogger;
+
+import kotlin.Unit;
+
+/**
+ * Handler of all Magnetized Object related code for PiP.
+ */
+public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListener {
+
+    /* The multiplier to apply scale the target size by when applying the magnetic field radius */
+    private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
+
+    /**
+     * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
+     * PIP.
+     */
+    private MagnetizedObject<Rect> mMagnetizedPip;
+
+    /**
+     * Container for the dismiss circle, so that it can be animated within the container via
+     * translation rather than within the WindowManager via slow layout animations.
+     */
+    private DismissView mTargetViewContainer;
+
+    /** Circle view used to render the dismiss target. */
+    private DismissCircleView mTargetView;
+
+    /**
+     * MagneticTarget instance wrapping the target view and allowing us to set its magnetic radius.
+     */
+    private MagnetizedObject.MagneticTarget mMagneticTarget;
+
+    // Allow dragging the PIP to a location to close it
+    private boolean mEnableDismissDragToEdge;
+
+    private int mTargetSize;
+    private int mDismissAreaHeight;
+    private float mMagneticFieldRadiusPercent = 1f;
+    private WindowInsets mWindowInsets;
+
+    private SurfaceControl mTaskLeash;
+    private boolean mHasDismissTargetSurface;
+
+    private final Context mContext;
+    private final PipMotionHelper mMotionHelper;
+    private final PipUiEventLogger mPipUiEventLogger;
+    private final WindowManager mWindowManager;
+    private final ShellExecutor mMainExecutor;
+
+    public PipDismissTargetHandler(Context context, PipUiEventLogger pipUiEventLogger,
+            PipMotionHelper motionHelper, ShellExecutor mainExecutor) {
+        mContext = context;
+        mPipUiEventLogger = pipUiEventLogger;
+        mMotionHelper = motionHelper;
+        mMainExecutor = mainExecutor;
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+    }
+
+    void init() {
+        Resources res = mContext.getResources();
+        mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
+        mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
+
+        if (mTargetViewContainer != null) {
+            // init can be called multiple times, remove the old one from view hierarchy first.
+            cleanUpDismissTarget();
+        }
+
+        mTargetViewContainer = new DismissView(mContext);
+        DismissViewUtils.setup(mTargetViewContainer);
+        mTargetView = mTargetViewContainer.getCircle();
+        mTargetViewContainer.setOnApplyWindowInsetsListener((view, windowInsets) -> {
+            if (!windowInsets.equals(mWindowInsets)) {
+                mWindowInsets = windowInsets;
+                updateMagneticTargetSize();
+            }
+            return windowInsets;
+        });
+
+        mMagnetizedPip = mMotionHelper.getMagnetizedPip();
+        mMagnetizedPip.clearAllTargets();
+        mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
+        updateMagneticTargetSize();
+
+        mMagnetizedPip.setAnimateStuckToTarget(
+                (target, velX, velY, flung, after) -> {
+                    if (mEnableDismissDragToEdge) {
+                        mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after);
+                    }
+                    return Unit.INSTANCE;
+                });
+        mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
+            @Override
+            public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target,
+                    @NonNull MagnetizedObject<?> draggedObject) {
+                // Show the dismiss target, in case the initial touch event occurred within
+                // the magnetic field radius.
+                if (mEnableDismissDragToEdge) {
+                    showDismissTargetMaybe();
+                }
+            }
+
+            @Override
+            public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
+                    @NonNull MagnetizedObject<?> draggedObject,
+                    float velX, float velY, boolean wasFlungOut) {
+                if (wasFlungOut) {
+                    mMotionHelper.flingToSnapTarget(velX, velY, null /* endAction */);
+                    hideDismissTargetMaybe();
+                } else {
+                    mMotionHelper.setSpringingToTouch(true);
+                }
+            }
+
+            @Override
+            public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target,
+                    @NonNull MagnetizedObject<?> draggedObject) {
+                if (mEnableDismissDragToEdge) {
+                    mMainExecutor.executeDelayed(() -> {
+                        mMotionHelper.notifyDismissalPending();
+                        mMotionHelper.animateDismiss();
+                        hideDismissTargetMaybe();
+
+                        mPipUiEventLogger.log(
+                                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE);
+                    }, 0);
+                }
+            }
+        });
+
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
+        mHasDismissTargetSurface = true;
+        updateDismissTargetLayer();
+        return true;
+    }
+
+    /**
+     * Potentially start consuming future motion events if PiP is currently near the magnetized
+     * object.
+     */
+    public boolean maybeConsumeMotionEvent(MotionEvent ev) {
+        return mMagnetizedPip.maybeConsumeMotionEvent(ev);
+    }
+
+    /**
+     * Update the magnet size.
+     */
+    public void updateMagneticTargetSize() {
+        if (mTargetView == null) {
+            return;
+        }
+        if (mTargetViewContainer != null) {
+            mTargetViewContainer.updateResources();
+        }
+
+        final Resources res = mContext.getResources();
+        mTargetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
+        mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
+
+        // Set the magnetic field radius equal to the target size from the center of the target
+        setMagneticFieldRadiusPercent(mMagneticFieldRadiusPercent);
+    }
+
+    /**
+     * Increase or decrease the field radius of the magnet object, e.g. with larger percent,
+     * PiP will magnetize to the field sooner.
+     */
+    public void setMagneticFieldRadiusPercent(float percent) {
+        mMagneticFieldRadiusPercent = percent;
+        mMagneticTarget.setMagneticFieldRadiusPx((int) (mMagneticFieldRadiusPercent * mTargetSize
+                        * MAGNETIC_FIELD_RADIUS_MULTIPLIER));
+    }
+
+    public void setTaskLeash(SurfaceControl taskLeash) {
+        mTaskLeash = taskLeash;
+    }
+
+    private void updateDismissTargetLayer() {
+        if (!mHasDismissTargetSurface || mTaskLeash == null) {
+            // No dismiss target surface, can just return
+            return;
+        }
+
+        final SurfaceControl targetViewLeash =
+                mTargetViewContainer.getViewRootImpl().getSurfaceControl();
+        if (!targetViewLeash.isValid()) {
+            // The surface of mTargetViewContainer is somehow not ready, bail early
+            return;
+        }
+
+        // Put the dismiss target behind the task
+        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        t.setRelativeLayer(targetViewLeash, mTaskLeash, -1);
+        t.apply();
+    }
+
+    /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
+    public void createOrUpdateDismissTarget() {
+        if (mTargetViewContainer.getParent() == null) {
+            mTargetViewContainer.cancelAnimators();
+
+            mTargetViewContainer.setVisibility(View.INVISIBLE);
+            mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
+            mHasDismissTargetSurface = false;
+
+            mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
+        } else {
+            mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
+        }
+    }
+
+    /** Returns layout params for the dismiss target, using the latest display metrics. */
+    private WindowManager.LayoutParams getDismissTargetLayoutParams() {
+        final Point windowSize = new Point();
+        mWindowManager.getDefaultDisplay().getRealSize(windowSize);
+        int height = Math.min(windowSize.y, mDismissAreaHeight);
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.MATCH_PARENT,
+                height,
+                0, windowSize.y - height,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.TRANSLUCENT);
+
+        lp.setTitle("pip-dismiss-overlay");
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        lp.setFitInsetsTypes(0 /* types */);
+
+        return lp;
+    }
+
+    /** Makes the dismiss target visible and animates it in, if it isn't already visible. */
+    public void showDismissTargetMaybe() {
+        if (!mEnableDismissDragToEdge) {
+            return;
+        }
+
+        createOrUpdateDismissTarget();
+
+        if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
+            mTargetViewContainer.getViewTreeObserver().addOnPreDrawListener(this);
+        }
+        // always invoke show, since the target might still be VISIBLE while playing hide animation,
+        // so we want to ensure it will show back again
+        mTargetViewContainer.show();
+    }
+
+    /** Animates the magnetic dismiss target out and then sets it to GONE. */
+    public void hideDismissTargetMaybe() {
+        if (!mEnableDismissDragToEdge) {
+            return;
+        }
+        mTargetViewContainer.hide();
+    }
+
+    /**
+     * Removes the dismiss target and cancels any pending callbacks to show it.
+     */
+    public void cleanUpDismissTarget() {
+        if (mTargetViewContainer.getParent() != null) {
+            mWindowManager.removeViewImmediate(mTargetViewContainer);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
new file mode 100644
index 0000000..619bed4
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
@@ -0,0 +1,719 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2.phone;
+
+import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_NO_BOUNCY;
+import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW;
+import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
+
+import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_LEFT;
+import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_NONE;
+import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_RIGHT;
+import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_DISMISS;
+import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_NONE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Debug;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.FloatProperties;
+import com.android.wm.shell.common.FloatingContentCoordinator;
+import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
+import com.android.wm.shell.common.pip.PipAppOpsListener;
+import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipPerfHintController;
+import com.android.wm.shell.common.pip.PipSnapAlgorithm;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.shared.animation.PhysicsAnimator;
+
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+
+import java.util.Optional;
+import java.util.function.Consumer;
+
+/**
+ * A helper to animate and manipulate the PiP.
+ */
+public class PipMotionHelper implements PipAppOpsListener.Callback,
+        FloatingContentCoordinator.FloatingContent {
+    private static final String TAG = "PipMotionHelper";
+    private static final boolean DEBUG = false;
+
+    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
+    private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
+    private static final int UNSTASH_DURATION = 250;
+    private static final int LEAVE_PIP_DURATION = 300;
+    private static final int SHIFT_DURATION = 300;
+
+    /** Friction to use for PIP when it moves via physics fling animations. */
+    private static final float DEFAULT_FRICTION = 1.9f;
+    /** How much of the dismiss circle size to use when scaling down PIP. **/
+    private static final float DISMISS_CIRCLE_PERCENT = 0.85f;
+
+    private final Context mContext;
+    private @NonNull PipBoundsState mPipBoundsState;
+
+    private PhonePipMenuController mMenuController;
+    private PipSnapAlgorithm mSnapAlgorithm;
+
+    /** The region that all of PIP must stay within. */
+    private final Rect mFloatingAllowedArea = new Rect();
+
+    /** Coordinator instance for resolving conflicts with other floating content. */
+    private FloatingContentCoordinator mFloatingContentCoordinator;
+
+    @Nullable private final PipPerfHintController mPipPerfHintController;
+    @Nullable private PipPerfHintController.PipHighPerfSession mPipHighPerfSession;
+
+    /**
+     * PhysicsAnimator instance for animating {@link PipBoundsState#getMotionBoundsState()}
+     * using physics animations.
+     */
+    private PhysicsAnimator<Rect> mTemporaryBoundsPhysicsAnimator;
+
+    private MagnetizedObject<Rect> mMagnetizedPip;
+
+    /**
+     * Update listener that resizes the PIP to {@link PipBoundsState#getMotionBoundsState()}.
+     */
+    private final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener;
+
+    /** FlingConfig instances provided to PhysicsAnimator for fling gestures. */
+    private PhysicsAnimator.FlingConfig mFlingConfigX;
+    private PhysicsAnimator.FlingConfig mFlingConfigY;
+    /** FlingConfig instances provided to PhysicsAnimator for stashing. */
+    private PhysicsAnimator.FlingConfig mStashConfigX;
+
+    /** SpringConfig to use for fling-then-spring animations. */
+    private final PhysicsAnimator.SpringConfig mSpringConfig =
+            new PhysicsAnimator.SpringConfig(700f, DAMPING_RATIO_NO_BOUNCY);
+
+    /** SpringConfig used for animating into the dismiss region, matches the one in
+     * {@link MagnetizedObject}. */
+    private final PhysicsAnimator.SpringConfig mAnimateToDismissSpringConfig =
+            new PhysicsAnimator.SpringConfig(STIFFNESS_MEDIUM, DAMPING_RATIO_NO_BOUNCY);
+
+    /** SpringConfig used for animating the pip to catch up to the finger once it leaves the dismiss
+     * drag region. */
+    private final PhysicsAnimator.SpringConfig mCatchUpSpringConfig =
+            new PhysicsAnimator.SpringConfig(5000f, DAMPING_RATIO_NO_BOUNCY);
+
+    /** SpringConfig to use for springing PIP away from conflicting floating content. */
+    private final PhysicsAnimator.SpringConfig mConflictResolutionSpringConfig =
+            new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_NO_BOUNCY);
+
+    private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> {
+        if (mPipBoundsState.getBounds().equals(newBounds)) {
+            return;
+        }
+
+        mMenuController.updateMenuLayout(newBounds);
+        mPipBoundsState.setBounds(newBounds);
+    };
+
+    /**
+     * Whether we're springing to the touch event location (vs. moving it to that position
+     * instantly). We spring-to-touch after PIP is dragged out of the magnetic target, since it was
+     * 'stuck' in the target and needs to catch up to the touch location.
+     */
+    private boolean mSpringingToTouch = false;
+
+    /**
+     * Whether PIP was released in the dismiss target, and will be animated out and dismissed
+     * shortly.
+     */
+    private boolean mDismissalPending = false;
+
+    /**
+     * Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is
+     * used to show menu activity when the expand animation is completed.
+     */
+    private Runnable mPostPipTransitionCallback;
+
+    public PipMotionHelper(Context context, @NonNull PipBoundsState pipBoundsState,
+            PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm,
+            FloatingContentCoordinator floatingContentCoordinator,
+            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
+        mContext = context;
+        mPipBoundsState = pipBoundsState;
+        mMenuController = menuController;
+        mSnapAlgorithm = snapAlgorithm;
+        mFloatingContentCoordinator = floatingContentCoordinator;
+        mPipPerfHintController = pipPerfHintControllerOptional.orElse(null);
+        mResizePipUpdateListener = (target, values) -> {
+            if (mPipBoundsState.getMotionBoundsState().isInMotion()) {
+                /*
+                mPipTaskOrganizer.scheduleUserResizePip(getBounds(),
+                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion(), null);
+                 */
+            }
+        };
+    }
+
+    void init() {
+        mTemporaryBoundsPhysicsAnimator = PhysicsAnimator.getInstance(
+                mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
+    }
+
+    @NonNull
+    @Override
+    public Rect getFloatingBoundsOnScreen() {
+        return !mPipBoundsState.getMotionBoundsState().getAnimatingToBounds().isEmpty()
+                ? mPipBoundsState.getMotionBoundsState().getAnimatingToBounds() : getBounds();
+    }
+
+    @NonNull
+    @Override
+    public Rect getAllowedFloatingBoundsRegion() {
+        return mFloatingAllowedArea;
+    }
+
+    @Override
+    public void moveToBounds(@NonNull Rect bounds) {
+        animateToBounds(bounds, mConflictResolutionSpringConfig);
+    }
+
+    /**
+     * Synchronizes the current bounds with the pinned stack, cancelling any ongoing animations.
+     */
+    void synchronizePinnedStackBounds() {
+        cancelPhysicsAnimation();
+        mPipBoundsState.getMotionBoundsState().onAllAnimationsEnded();
+
+        /*
+        if (mPipTaskOrganizer.isInPip()) {
+            mFloatingContentCoordinator.onContentMoved(this);
+        }
+         */
+    }
+
+    /**
+     * Tries to move the pinned stack to the given {@param bounds}.
+     */
+    void movePip(Rect toBounds) {
+        movePip(toBounds, false /* isDragging */);
+    }
+
+    /**
+     * Tries to move the pinned stack to the given {@param bounds}.
+     *
+     * @param isDragging Whether this movement is the result of a drag touch gesture. If so, we
+     *                   won't notify the floating content coordinator of this move, since that will
+     *                   happen when the gesture ends.
+     */
+    void movePip(Rect toBounds, boolean isDragging) {
+        if (!isDragging) {
+            mFloatingContentCoordinator.onContentMoved(this);
+        }
+
+        if (!mSpringingToTouch) {
+            // If we are moving PIP directly to the touch event locations, cancel any animations and
+            // move PIP to the given bounds.
+            cancelPhysicsAnimation();
+
+            if (!isDragging) {
+                resizePipUnchecked(toBounds);
+                mPipBoundsState.setBounds(toBounds);
+            } else {
+                mPipBoundsState.getMotionBoundsState().setBoundsInMotion(toBounds);
+                /*
+                mPipTaskOrganizer.scheduleUserResizePip(getBounds(), toBounds,
+                        (Rect newBounds) -> {
+                                mMenuController.updateMenuLayout(newBounds);
+                        });
+                 */
+            }
+        } else {
+            // If PIP is 'catching up' after being stuck in the dismiss target, update the animation
+            // to spring towards the new touch location.
+            mTemporaryBoundsPhysicsAnimator
+                    .spring(FloatProperties.RECT_WIDTH, getBounds().width(), mCatchUpSpringConfig)
+                    .spring(FloatProperties.RECT_HEIGHT, getBounds().height(), mCatchUpSpringConfig)
+                    .spring(FloatProperties.RECT_X, toBounds.left, mCatchUpSpringConfig)
+                    .spring(FloatProperties.RECT_Y, toBounds.top, mCatchUpSpringConfig);
+
+            startBoundsAnimator(toBounds.left /* toX */, toBounds.top /* toY */);
+        }
+    }
+
+    /** Animates the PIP into the dismiss target, scaling it down. */
+    void animateIntoDismissTarget(
+            MagnetizedObject.MagneticTarget target,
+            float velX, float velY,
+            boolean flung, Function0<Unit> after) {
+        final PointF targetCenter = target.getCenterOnScreen();
+
+        // PIP should fit in the circle
+        final float dismissCircleSize = mContext.getResources().getDimensionPixelSize(
+                R.dimen.dismiss_circle_size);
+
+        final float width = getBounds().width();
+        final float height = getBounds().height();
+        final float ratio = width / height;
+
+        // Width should be a little smaller than the circle size.
+        final float desiredWidth = dismissCircleSize * DISMISS_CIRCLE_PERCENT;
+        final float desiredHeight = desiredWidth / ratio;
+        final float destinationX = targetCenter.x - (desiredWidth / 2f);
+        final float destinationY = targetCenter.y - (desiredHeight / 2f);
+
+        // If we're already in the dismiss target area, then there won't be a move to set the
+        // temporary bounds, so just initialize it to the current bounds.
+        if (!mPipBoundsState.getMotionBoundsState().isInMotion()) {
+            mPipBoundsState.getMotionBoundsState().setBoundsInMotion(getBounds());
+        }
+        mTemporaryBoundsPhysicsAnimator
+                .spring(FloatProperties.RECT_X, destinationX, velX, mAnimateToDismissSpringConfig)
+                .spring(FloatProperties.RECT_Y, destinationY, velY, mAnimateToDismissSpringConfig)
+                .spring(FloatProperties.RECT_WIDTH, desiredWidth, mAnimateToDismissSpringConfig)
+                .spring(FloatProperties.RECT_HEIGHT, desiredHeight, mAnimateToDismissSpringConfig)
+                .withEndActions(after);
+
+        startBoundsAnimator(destinationX, destinationY);
+    }
+
+    /** Set whether we're springing-to-touch to catch up after being stuck in the dismiss target. */
+    void setSpringingToTouch(boolean springingToTouch) {
+        mSpringingToTouch = springingToTouch;
+    }
+
+    /**
+     * Resizes the pinned stack back to unknown windowing mode, which could be freeform or
+     *      * fullscreen depending on the display area's windowing mode.
+     */
+    void expandLeavePip(boolean skipAnimation) {
+        expandLeavePip(skipAnimation, false /* enterSplit */);
+    }
+
+    /**
+     * Resizes the pinned task to split-screen mode.
+     */
+    void expandIntoSplit() {
+        expandLeavePip(false, true /* enterSplit */);
+    }
+
+    /**
+     * Resizes the pinned stack back to unknown windowing mode, which could be freeform or
+     * fullscreen depending on the display area's windowing mode.
+     */
+    private void expandLeavePip(boolean skipAnimation, boolean enterSplit) {
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: exitPip: skipAnimation=%s"
+                            + " callers=\n%s", TAG, skipAnimation, Debug.getCallers(5, "    "));
+        }
+        cancelPhysicsAnimation();
+        mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */);
+        // mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION, enterSplit);
+    }
+
+    /**
+     * Dismisses the pinned stack.
+     */
+    @Override
+    public void dismissPip() {
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: removePip: callers=\n%s", TAG, Debug.getCallers(5, "    "));
+        }
+        cancelPhysicsAnimation();
+        mMenuController.hideMenu(ANIM_TYPE_DISMISS, false /* resize */);
+        // mPipTaskOrganizer.removePip();
+    }
+
+    /** Sets the movement bounds to use to constrain PIP position animations. */
+    void onMovementBoundsChanged() {
+        rebuildFlingConfigs();
+
+        // The movement bounds represent the area within which we can move PIP's top-left position.
+        // The allowed area for all of PIP is those bounds plus PIP's width and height.
+        mFloatingAllowedArea.set(mPipBoundsState.getMovementBounds());
+        mFloatingAllowedArea.right += getBounds().width();
+        mFloatingAllowedArea.bottom += getBounds().height();
+    }
+
+    /**
+     * @return the PiP bounds.
+     */
+    private Rect getBounds() {
+        return mPipBoundsState.getBounds();
+    }
+
+    /**
+     * Flings the PiP to the closest snap target.
+     */
+    void flingToSnapTarget(
+            float velocityX, float velocityY, @Nullable Runnable postBoundsUpdateCallback) {
+        movetoTarget(velocityX, velocityY, postBoundsUpdateCallback, false /* isStash */);
+    }
+
+    /**
+     * Stash PiP to the closest edge. We set velocityY to 0 to limit pure horizontal motion.
+     */
+    void stashToEdge(float velX, float velY, @Nullable Runnable postBoundsUpdateCallback) {
+        velY = mPipBoundsState.getStashedState() == STASH_TYPE_NONE ? 0 : velY;
+        movetoTarget(velX, velY, postBoundsUpdateCallback, true /* isStash */);
+    }
+
+    private void onHighPerfSessionTimeout(PipPerfHintController.PipHighPerfSession session) {}
+
+    private void cleanUpHighPerfSessionMaybe() {
+        if (mPipHighPerfSession != null) {
+            // Close the high perf session once pointer interactions are over;
+            mPipHighPerfSession.close();
+            mPipHighPerfSession = null;
+        }
+    }
+
+    private void movetoTarget(
+            float velocityX,
+            float velocityY,
+            @Nullable Runnable postBoundsUpdateCallback,
+            boolean isStash) {
+        // If we're flinging to a snap target now, we're not springing to catch up to the touch
+        // location now.
+        mSpringingToTouch = false;
+
+        mTemporaryBoundsPhysicsAnimator
+                .spring(FloatProperties.RECT_WIDTH, getBounds().width(), mSpringConfig)
+                .spring(FloatProperties.RECT_HEIGHT, getBounds().height(), mSpringConfig)
+                .flingThenSpring(
+                        FloatProperties.RECT_X, velocityX,
+                        isStash ? mStashConfigX : mFlingConfigX,
+                        mSpringConfig, true /* flingMustReachMinOrMax */)
+                .flingThenSpring(
+                        FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig);
+
+        final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
+        final float leftEdge = isStash
+                ? mPipBoundsState.getStashOffset() - mPipBoundsState.getBounds().width()
+                + insetBounds.left
+                : mPipBoundsState.getMovementBounds().left;
+        final float rightEdge = isStash
+                ?  mPipBoundsState.getDisplayBounds().right - mPipBoundsState.getStashOffset()
+                - insetBounds.right
+                : mPipBoundsState.getMovementBounds().right;
+
+        final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
+
+        final int startValueY = mPipBoundsState.getMotionBoundsState().getBoundsInMotion().top;
+        final float estimatedFlingYEndValue =
+                PhysicsAnimator.estimateFlingEndValue(startValueY, velocityY, mFlingConfigY);
+
+        startBoundsAnimator(xEndValue /* toX */, estimatedFlingYEndValue /* toY */,
+                postBoundsUpdateCallback);
+    }
+
+    /**
+     * Animates PIP to the provided bounds, using physics animations and the given spring
+     * configuration
+     */
+    void animateToBounds(Rect bounds, PhysicsAnimator.SpringConfig springConfig) {
+        if (!mTemporaryBoundsPhysicsAnimator.isRunning()) {
+            // Animate from the current bounds if we're not already animating.
+            mPipBoundsState.getMotionBoundsState().setBoundsInMotion(getBounds());
+        }
+
+        mTemporaryBoundsPhysicsAnimator
+                .spring(FloatProperties.RECT_X, bounds.left, springConfig)
+                .spring(FloatProperties.RECT_Y, bounds.top, springConfig);
+        startBoundsAnimator(bounds.left /* toX */, bounds.top /* toY */);
+    }
+
+    /**
+     * Animates the dismissal of the PiP off the edge of the screen.
+     */
+    void animateDismiss() {
+        // Animate off the bottom of the screen, then dismiss PIP.
+        mTemporaryBoundsPhysicsAnimator
+                .spring(FloatProperties.RECT_Y,
+                        mPipBoundsState.getMovementBounds().bottom + getBounds().height() * 2,
+                        0,
+                        mSpringConfig)
+                .withEndActions(this::dismissPip);
+
+        startBoundsAnimator(
+                getBounds().left /* toX */, getBounds().bottom + getBounds().height() /* toY */);
+
+        mDismissalPending = false;
+    }
+
+    /**
+     * Animates the PiP to the expanded state to show the menu.
+     */
+    float animateToExpandedState(Rect expandedBounds, Rect movementBounds,
+            Rect expandedMovementBounds, Runnable callback) {
+        float savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(getBounds()),
+                movementBounds);
+        mSnapAlgorithm.applySnapFraction(expandedBounds, expandedMovementBounds, savedSnapFraction);
+        mPostPipTransitionCallback = callback;
+        resizeAndAnimatePipUnchecked(expandedBounds, EXPAND_STACK_TO_MENU_DURATION);
+        return savedSnapFraction;
+    }
+
+    /**
+     * Animates the PiP from the expanded state to the normal state after the menu is hidden.
+     */
+    void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction,
+            Rect normalMovementBounds, Rect currentMovementBounds, boolean immediate) {
+        if (savedSnapFraction < 0f) {
+            // If there are no saved snap fractions, then just use the current bounds
+            savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(getBounds()),
+                    currentMovementBounds, mPipBoundsState.getStashedState());
+        }
+
+        mSnapAlgorithm.applySnapFraction(normalBounds, normalMovementBounds, savedSnapFraction,
+                mPipBoundsState.getStashedState(), mPipBoundsState.getStashOffset(),
+                mPipBoundsState.getDisplayBounds(),
+                mPipBoundsState.getDisplayLayout().stableInsets());
+
+        if (immediate) {
+            movePip(normalBounds);
+        } else {
+            resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION);
+        }
+    }
+
+    /**
+     * Animates the PiP to the stashed state, choosing the closest edge.
+     */
+    void animateToStashedClosestEdge() {
+        Rect tmpBounds = new Rect();
+        final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
+        final int stashType =
+                mPipBoundsState.getBounds().left == mPipBoundsState.getMovementBounds().left
+                ? STASH_TYPE_LEFT : STASH_TYPE_RIGHT;
+        final float leftEdge = stashType == STASH_TYPE_LEFT
+                ? mPipBoundsState.getStashOffset()
+                - mPipBoundsState.getBounds().width() + insetBounds.left
+                : mPipBoundsState.getDisplayBounds().right
+                        - mPipBoundsState.getStashOffset() - insetBounds.right;
+        tmpBounds.set((int) leftEdge,
+                mPipBoundsState.getBounds().top,
+                (int) (leftEdge + mPipBoundsState.getBounds().width()),
+                mPipBoundsState.getBounds().bottom);
+        resizeAndAnimatePipUnchecked(tmpBounds, UNSTASH_DURATION);
+        mPipBoundsState.setStashed(stashType);
+    }
+
+    /**
+     * Animates the PiP from stashed state into un-stashed, popping it out from the edge.
+     */
+    void animateToUnStashedBounds(Rect unstashedBounds) {
+        resizeAndAnimatePipUnchecked(unstashedBounds, UNSTASH_DURATION);
+    }
+
+    /**
+     * Animates the PiP to offset it from the IME or shelf.
+     */
+    void animateToOffset(Rect originalBounds, int offset) {
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: animateToOffset: originalBounds=%s offset=%s"
+                            + " callers=\n%s", TAG, originalBounds, offset,
+                    Debug.getCallers(5, "    "));
+        }
+        cancelPhysicsAnimation();
+        /*
+        mPipTaskOrganizer.scheduleOffsetPip(originalBounds, offset, SHIFT_DURATION,
+                mUpdateBoundsCallback);
+         */
+    }
+
+    /**
+     * Cancels all existing animations.
+     */
+    private void cancelPhysicsAnimation() {
+        mTemporaryBoundsPhysicsAnimator.cancel();
+        mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
+        mSpringingToTouch = false;
+    }
+
+    /** Set new fling configs whose min/max values respect the given movement bounds. */
+    private void rebuildFlingConfigs() {
+        mFlingConfigX = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
+                mPipBoundsState.getMovementBounds().left,
+                mPipBoundsState.getMovementBounds().right);
+        mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
+                mPipBoundsState.getMovementBounds().top,
+                mPipBoundsState.getMovementBounds().bottom);
+        final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
+        mStashConfigX = new PhysicsAnimator.FlingConfig(
+                DEFAULT_FRICTION,
+                mPipBoundsState.getStashOffset() - mPipBoundsState.getBounds().width()
+                        + insetBounds.left,
+                mPipBoundsState.getDisplayBounds().right - mPipBoundsState.getStashOffset()
+                        - insetBounds.right);
+    }
+
+    private void startBoundsAnimator(float toX, float toY) {
+        startBoundsAnimator(toX, toY, null /* postBoundsUpdateCallback */);
+    }
+
+    /**
+     * Starts the physics animator which will update the animated PIP bounds using physics
+     * animations, as well as the TimeAnimator which will apply those bounds to PIP.
+     *
+     * This will also add end actions to the bounds animator that cancel the TimeAnimator and update
+     * the 'real' bounds to equal the final animated bounds.
+     *
+     * If one wishes to supply a callback after all the 'real' bounds update has happened,
+     * pass @param postBoundsUpdateCallback.
+     */
+    private void startBoundsAnimator(float toX, float toY, Runnable postBoundsUpdateCallback) {
+        if (!mSpringingToTouch) {
+            cancelPhysicsAnimation();
+        }
+
+        setAnimatingToBounds(new Rect(
+                (int) toX,
+                (int) toY,
+                (int) toX + getBounds().width(),
+                (int) toY + getBounds().height()));
+
+        if (!mTemporaryBoundsPhysicsAnimator.isRunning()) {
+            if (mPipPerfHintController != null) {
+                // Start a high perf session with a timeout callback.
+                mPipHighPerfSession = mPipPerfHintController.startSession(
+                        this::onHighPerfSessionTimeout, "startBoundsAnimator");
+            }
+            if (postBoundsUpdateCallback != null) {
+                mTemporaryBoundsPhysicsAnimator
+                        .addUpdateListener(mResizePipUpdateListener)
+                        .withEndActions(this::onBoundsPhysicsAnimationEnd,
+                                postBoundsUpdateCallback);
+            } else {
+                mTemporaryBoundsPhysicsAnimator
+                        .addUpdateListener(mResizePipUpdateListener)
+                        .withEndActions(this::onBoundsPhysicsAnimationEnd);
+            }
+        }
+
+        mTemporaryBoundsPhysicsAnimator.start();
+    }
+
+    /**
+     * Notify that PIP was released in the dismiss target and will be animated out and dismissed
+     * shortly.
+     */
+    void notifyDismissalPending() {
+        mDismissalPending = true;
+    }
+
+    private void onBoundsPhysicsAnimationEnd() {
+        // The physics animation ended, though we may not necessarily be done animating, such as
+        // when we're still dragging after moving out of the magnetic target.
+        if (!mDismissalPending
+                && !mSpringingToTouch
+                && !mMagnetizedPip.getObjectStuckToTarget()) {
+            // All motion operations have actually finished.
+            mPipBoundsState.setBounds(
+                    mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
+            mPipBoundsState.getMotionBoundsState().onAllAnimationsEnded();
+            if (!mDismissalPending) {
+                // do not schedule resize if PiP is dismissing, which may cause app re-open to
+                // mBounds instead of its normal bounds.
+                // mPipTaskOrganizer.scheduleFinishResizePip(getBounds());
+            }
+        }
+        mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
+        mSpringingToTouch = false;
+        mDismissalPending = false;
+        cleanUpHighPerfSessionMaybe();
+    }
+
+    /**
+     * Notifies the floating coordinator that we're moving, and sets the animating to bounds so
+     * we return these bounds from
+     * {@link FloatingContentCoordinator.FloatingContent#getFloatingBoundsOnScreen()}.
+     */
+    private void setAnimatingToBounds(Rect bounds) {
+        mPipBoundsState.getMotionBoundsState().setAnimatingToBounds(bounds);
+        mFloatingContentCoordinator.onContentMoved(this);
+    }
+
+    /**
+     * Directly resizes the PiP to the given {@param bounds}.
+     */
+    private void resizePipUnchecked(Rect toBounds) {
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: resizePipUnchecked: toBounds=%s"
+                            + " callers=\n%s", TAG, toBounds, Debug.getCallers(5, "    "));
+        }
+        if (!toBounds.equals(getBounds())) {
+            // mPipTaskOrganizer.scheduleResizePip(toBounds, mUpdateBoundsCallback);
+        }
+    }
+
+    /**
+     * Directly resizes the PiP to the given {@param bounds}.
+     */
+    private void resizeAndAnimatePipUnchecked(Rect toBounds, int duration) {
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: resizeAndAnimatePipUnchecked: toBounds=%s"
+                            + " duration=%s callers=\n%s", TAG, toBounds, duration,
+                    Debug.getCallers(5, "    "));
+        }
+
+        // Intentionally resize here even if the current bounds match the destination bounds.
+        // This is so all the proper callbacks are performed.
+
+        // mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration,
+        //         TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, null /* updateBoundsCallback */);
+        // setAnimatingToBounds(toBounds);
+    }
+
+    /**
+     * Returns a MagnetizedObject wrapper for PIP's animated bounds. This is provided to the
+     * magnetic dismiss target so it can calculate PIP's size and position.
+     */
+    MagnetizedObject<Rect> getMagnetizedPip() {
+        if (mMagnetizedPip == null) {
+            mMagnetizedPip = new MagnetizedObject<Rect>(
+                    mContext, mPipBoundsState.getMotionBoundsState().getBoundsInMotion(),
+                    FloatProperties.RECT_X, FloatProperties.RECT_Y) {
+                @Override
+                public float getWidth(@NonNull Rect animatedPipBounds) {
+                    return animatedPipBounds.width();
+                }
+
+                @Override
+                public float getHeight(@NonNull Rect animatedPipBounds) {
+                    return animatedPipBounds.height();
+                }
+
+                @Override
+                public void getLocationOnScreen(
+                        @NonNull Rect animatedPipBounds, @NonNull int[] loc) {
+                    loc[0] = animatedPipBounds.left;
+                    loc[1] = animatedPipBounds.top;
+                }
+            };
+            mMagnetizedPip.setFlingToTargetEnabled(false);
+        }
+
+        return mMagnetizedPip;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
new file mode 100644
index 0000000..472003c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2.phone;
+
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASH_MINIMUM_VELOCITY_THRESHOLD;
+import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_LEFT;
+import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_NONE;
+import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_RIGHT;
+import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
+import static com.android.wm.shell.pip2.phone.PhonePipMenuController.MENU_STATE_FULL;
+import static com.android.wm.shell.pip2.phone.PhonePipMenuController.MENU_STATE_NONE;
+import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_NONE;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.provider.DeviceConfig;
+import android.util.Size;
+import android.view.DisplayCutout;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.FloatingContentCoordinator;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
+import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipDoubleTapHelper;
+import com.android.wm.shell.common.pip.PipPerfHintController;
+import com.android.wm.shell.common.pip.PipUiEventLogger;
+import com.android.wm.shell.common.pip.PipUtils;
+import com.android.wm.shell.common.pip.SizeSpecSource;
+import com.android.wm.shell.pip.PipAnimationController;
+import com.android.wm.shell.pip.PipTransitionController;
+import com.android.wm.shell.sysui.ShellInit;
+
+import java.io.PrintWriter;
+import java.util.Optional;
+
+/**
+ * Manages all the touch handling for PIP on the Phone, including moving, dismissing and expanding
+ * the PIP.
+ */
+public class PipTouchHandler {
+
+    private static final String TAG = "PipTouchHandler";
+    private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f;
+
+    // Allow PIP to resize to a slightly bigger state upon touch
+    private boolean mEnableResize;
+    private final Context mContext;
+    private final PipBoundsAlgorithm mPipBoundsAlgorithm;
+    @NonNull private final PipBoundsState mPipBoundsState;
+    @NonNull private final SizeSpecSource mSizeSpecSource;
+    private final PipUiEventLogger mPipUiEventLogger;
+    private final PipDismissTargetHandler mPipDismissTargetHandler;
+    private final ShellExecutor mMainExecutor;
+    @Nullable private final PipPerfHintController mPipPerfHintController;
+
+    private PipResizeGestureHandler mPipResizeGestureHandler;
+
+    private final PhonePipMenuController mMenuController;
+    private final AccessibilityManager mAccessibilityManager;
+
+    /**
+     * Whether PIP stash is enabled or not. When enabled, if the user flings toward the edge of the
+     * screen, it will be shown in "stashed" mode, where PIP will only show partially.
+     */
+    private boolean mEnableStash = true;
+
+    private float mStashVelocityThreshold;
+
+    // The reference inset bounds, used to determine the dismiss fraction
+    private final Rect mInsetBounds = new Rect();
+
+    // Used to workaround an issue where the WM rotation happens before we are notified, allowing
+    // us to send stale bounds
+    private int mDeferResizeToNormalBoundsUntilRotation = -1;
+    private int mDisplayRotation;
+
+    // Behaviour states
+    private int mMenuState = MENU_STATE_NONE;
+    private boolean mIsImeShowing;
+    private int mImeHeight;
+    private int mImeOffset;
+    private boolean mIsShelfShowing;
+    private int mShelfHeight;
+    private int mMovementBoundsExtraOffsets;
+    private int mBottomOffsetBufferPx;
+    private float mSavedSnapFraction = -1f;
+    private boolean mSendingHoverAccessibilityEvents;
+    private boolean mMovementWithinDismiss;
+
+    // Touch state
+    private final PipTouchState mTouchState;
+    private final FloatingContentCoordinator mFloatingContentCoordinator;
+    private PipMotionHelper mMotionHelper;
+    private PipTouchGesture mGesture;
+
+    // Temp vars
+    private final Rect mTmpBounds = new Rect();
+
+    /**
+     * A listener for the PIP menu activity.
+     */
+    private class PipMenuListener implements PhonePipMenuController.Listener {
+        @Override
+        public void onPipMenuStateChangeStart(int menuState, boolean resize, Runnable callback) {
+            PipTouchHandler.this.onPipMenuStateChangeStart(menuState, resize, callback);
+        }
+
+        @Override
+        public void onPipMenuStateChangeFinish(int menuState) {
+            setMenuState(menuState);
+        }
+
+        @Override
+        public void onPipExpand() {
+            mMotionHelper.expandLeavePip(false /* skipAnimation */);
+        }
+
+        @Override
+        public void onPipDismiss() {
+            mTouchState.removeDoubleTapTimeoutCallback();
+            mMotionHelper.dismissPip();
+        }
+
+        @Override
+        public void onPipShowMenu() {
+            mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
+                    true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle());
+        }
+    }
+
+    @SuppressLint("InflateParams")
+    public PipTouchHandler(Context context,
+            ShellInit shellInit,
+            PhonePipMenuController menuController,
+            PipBoundsAlgorithm pipBoundsAlgorithm,
+            @NonNull PipBoundsState pipBoundsState,
+            @NonNull SizeSpecSource sizeSpecSource,
+            PipMotionHelper pipMotionHelper,
+            FloatingContentCoordinator floatingContentCoordinator,
+            PipUiEventLogger pipUiEventLogger,
+            ShellExecutor mainExecutor,
+            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
+        mContext = context;
+        mMainExecutor = mainExecutor;
+        mPipPerfHintController = pipPerfHintControllerOptional.orElse(null);
+        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+        mPipBoundsAlgorithm = pipBoundsAlgorithm;
+        mPipBoundsState = pipBoundsState;
+        mSizeSpecSource = sizeSpecSource;
+        mMenuController = menuController;
+        mPipUiEventLogger = pipUiEventLogger;
+        mFloatingContentCoordinator = floatingContentCoordinator;
+        mMenuController.addListener(new PipMenuListener());
+        mGesture = new DefaultPipTouchGesture();
+        mMotionHelper = pipMotionHelper;
+        mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
+                mMotionHelper, mainExecutor);
+        mTouchState = new PipTouchState(ViewConfiguration.get(context),
+                () -> {
+                    if (mPipBoundsState.isStashed()) {
+                        animateToUnStashedState();
+                        mPipUiEventLogger.log(
+                                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
+                        mPipBoundsState.setStashed(STASH_TYPE_NONE);
+                    } else {
+                        mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
+                                mPipBoundsState.getBounds(), true /* allowMenuTimeout */,
+                                willResizeMenu(),
+                                shouldShowResizeHandle());
+                    }
+                },
+                menuController::hideMenu,
+                mainExecutor);
+        mPipResizeGestureHandler =
+                new PipResizeGestureHandler(context, pipBoundsAlgorithm, pipBoundsState,
+                        mTouchState, this::updateMovementBounds, pipUiEventLogger,
+                        menuController, mainExecutor, mPipPerfHintController);
+        mPipBoundsState.addOnAspectRatioChangedCallback(this::updateMinMaxSize);
+
+        if (PipUtils.isPip2ExperimentEnabled()) {
+            shellInit.addInitCallback(this::onInit, this);
+        }
+    }
+
+    /**
+     * Called when the touch handler is initialized.
+     */
+    public void onInit() {
+        Resources res = mContext.getResources();
+        mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu);
+        reloadResources();
+
+        mMotionHelper.init();
+        mPipResizeGestureHandler.init();
+        mPipDismissTargetHandler.init();
+
+        mEnableStash = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                PIP_STASHING,
+                /* defaultValue = */ true);
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
+                mMainExecutor,
+                properties -> {
+                    if (properties.getKeyset().contains(PIP_STASHING)) {
+                        mEnableStash = properties.getBoolean(
+                                PIP_STASHING, /* defaultValue = */ true);
+                    }
+                });
+        mStashVelocityThreshold = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                PIP_STASH_MINIMUM_VELOCITY_THRESHOLD,
+                DEFAULT_STASH_VELOCITY_THRESHOLD);
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
+                mMainExecutor,
+                properties -> {
+                    if (properties.getKeyset().contains(PIP_STASH_MINIMUM_VELOCITY_THRESHOLD)) {
+                        mStashVelocityThreshold = properties.getFloat(
+                                PIP_STASH_MINIMUM_VELOCITY_THRESHOLD,
+                                DEFAULT_STASH_VELOCITY_THRESHOLD);
+                    }
+                });
+    }
+
+    public PipTransitionController getTransitionHandler() {
+        // return mPipTaskOrganizer.getTransitionController();
+        return null;
+    }
+
+    private void reloadResources() {
+        final Resources res = mContext.getResources();
+        mBottomOffsetBufferPx = res.getDimensionPixelSize(R.dimen.pip_bottom_offset_buffer);
+        mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
+        mPipDismissTargetHandler.updateMagneticTargetSize();
+    }
+
+    void onOverlayChanged() {
+        // onOverlayChanged is triggered upon theme change, update the dismiss target accordingly.
+        mPipDismissTargetHandler.init();
+    }
+
+    private boolean shouldShowResizeHandle() {
+        return false;
+    }
+
+    void setTouchGesture(PipTouchGesture gesture) {
+        mGesture = gesture;
+    }
+
+    void setTouchEnabled(boolean enabled) {
+        mTouchState.setAllowTouches(enabled);
+    }
+
+    void showPictureInPictureMenu() {
+        // Only show the menu if the user isn't currently interacting with the PiP
+        if (!mTouchState.isUserInteracting()) {
+            mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
+                    false /* allowMenuTimeout */, willResizeMenu(),
+                    shouldShowResizeHandle());
+        }
+    }
+
+    void onActivityPinned() {
+        mPipDismissTargetHandler.createOrUpdateDismissTarget();
+
+        mPipResizeGestureHandler.onActivityPinned();
+        mFloatingContentCoordinator.onContentAdded(mMotionHelper);
+    }
+
+    void onActivityUnpinned(ComponentName topPipActivity) {
+        if (topPipActivity == null) {
+            // Clean up state after the last PiP activity is removed
+            mPipDismissTargetHandler.cleanUpDismissTarget();
+
+            mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
+        }
+        mPipResizeGestureHandler.onActivityUnpinned();
+    }
+
+    void onPinnedStackAnimationEnded(
+            @PipAnimationController.TransitionDirection int direction) {
+        // Always synchronize the motion helper bounds once PiP animations finish
+        mMotionHelper.synchronizePinnedStackBounds();
+        updateMovementBounds();
+        if (direction == TRANSITION_DIRECTION_TO_PIP) {
+            // Set the initial bounds as the user resize bounds.
+            mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
+        }
+    }
+
+    void onConfigurationChanged() {
+        mPipResizeGestureHandler.onConfigurationChanged();
+        mMotionHelper.synchronizePinnedStackBounds();
+        reloadResources();
+
+        /*
+        if (mPipTaskOrganizer.isInPip()) {
+            // Recreate the dismiss target for the new orientation.
+            mPipDismissTargetHandler.createOrUpdateDismissTarget();
+        }
+         */
+    }
+
+    void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+        mIsImeShowing = imeVisible;
+        mImeHeight = imeHeight;
+    }
+
+    void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+        mIsShelfShowing = shelfVisible;
+        mShelfHeight = shelfHeight;
+    }
+
+    /**
+     * Called when SysUI state changed.
+     *
+     * @param isSysUiStateValid Is SysUI valid or not.
+     */
+    public void onSystemUiStateChanged(boolean isSysUiStateValid) {
+        mPipResizeGestureHandler.onSystemUiStateChanged(isSysUiStateValid);
+    }
+
+    void adjustBoundsForRotation(Rect outBounds, Rect curBounds, Rect insetBounds) {
+        final Rect toMovementBounds = new Rect();
+        mPipBoundsAlgorithm.getMovementBounds(outBounds, insetBounds, toMovementBounds, 0);
+        final int prevBottom = mPipBoundsState.getMovementBounds().bottom
+                - mMovementBoundsExtraOffsets;
+        if ((prevBottom - mBottomOffsetBufferPx) <= curBounds.top) {
+            outBounds.offsetTo(outBounds.left, toMovementBounds.bottom);
+        }
+    }
+
+    /**
+     * Responds to IPinnedStackListener on resetting aspect ratio for the pinned window.
+     */
+    public void onAspectRatioChanged() {
+        mPipResizeGestureHandler.invalidateUserResizeBounds();
+    }
+
+    void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect curBounds,
+            boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) {
+        // Set the user resized bounds equal to the new normal bounds in case they were
+        // invalidated (e.g. by an aspect ratio change).
+        if (mPipResizeGestureHandler.getUserResizeBounds().isEmpty()) {
+            mPipResizeGestureHandler.setUserResizeBounds(normalBounds);
+        }
+
+        final int bottomOffset = mIsImeShowing ? mImeHeight : 0;
+        final boolean fromDisplayRotationChanged = (mDisplayRotation != displayRotation);
+        if (fromDisplayRotationChanged) {
+            mTouchState.reset();
+        }
+
+        // Re-calculate the expanded bounds
+        Rect normalMovementBounds = new Rect();
+        mPipBoundsAlgorithm.getMovementBounds(normalBounds, insetBounds,
+                normalMovementBounds, bottomOffset);
+
+        if (mPipBoundsState.getMovementBounds().isEmpty()) {
+            // mMovementBounds is not initialized yet and a clean movement bounds without
+            // bottom offset shall be used later in this function.
+            mPipBoundsAlgorithm.getMovementBounds(curBounds, insetBounds,
+                    mPipBoundsState.getMovementBounds(), 0 /* bottomOffset */);
+        }
+
+        // Calculate the expanded size
+        float aspectRatio = (float) normalBounds.width() / normalBounds.height();
+        Size expandedSize = mSizeSpecSource.getDefaultSize(aspectRatio);
+        mPipBoundsState.setExpandedBounds(
+                new Rect(0, 0, expandedSize.getWidth(), expandedSize.getHeight()));
+        Rect expandedMovementBounds = new Rect();
+        mPipBoundsAlgorithm.getMovementBounds(
+                mPipBoundsState.getExpandedBounds(), insetBounds, expandedMovementBounds,
+                bottomOffset);
+
+        updatePipSizeConstraints(normalBounds, aspectRatio);
+
+        // The extra offset does not really affect the movement bounds, but are applied based on the
+        // current state (ime showing, or shelf offset) when we need to actually shift
+        int extraOffset = Math.max(
+                mIsImeShowing ? mImeOffset : 0,
+                !mIsImeShowing && mIsShelfShowing ? mShelfHeight : 0);
+
+        // Update the movement bounds after doing the calculations based on the old movement bounds
+        // above
+        mPipBoundsState.setNormalMovementBounds(normalMovementBounds);
+        mPipBoundsState.setExpandedMovementBounds(expandedMovementBounds);
+        mDisplayRotation = displayRotation;
+        mInsetBounds.set(insetBounds);
+        updateMovementBounds();
+        mMovementBoundsExtraOffsets = extraOffset;
+
+        // If we have a deferred resize, apply it now
+        if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
+            mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
+                    mPipBoundsState.getNormalMovementBounds(), mPipBoundsState.getMovementBounds(),
+                    true /* immediate */);
+            mSavedSnapFraction = -1f;
+            mDeferResizeToNormalBoundsUntilRotation = -1;
+        }
+    }
+
+    /**
+     * Update the values for min/max allowed size of picture in picture window based on the aspect
+     * ratio.
+     * @param aspectRatio aspect ratio to use for the calculation of min/max size
+     */
+    public void updateMinMaxSize(float aspectRatio) {
+        updatePipSizeConstraints(mPipBoundsState.getNormalBounds(),
+                aspectRatio);
+    }
+
+    private void updatePipSizeConstraints(Rect normalBounds,
+            float aspectRatio) {
+        if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
+            updatePinchResizeSizeConstraints(aspectRatio);
+        } else {
+            mPipResizeGestureHandler.updateMinSize(normalBounds.width(), normalBounds.height());
+            mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getExpandedBounds().width(),
+                    mPipBoundsState.getExpandedBounds().height());
+        }
+    }
+
+    private void updatePinchResizeSizeConstraints(float aspectRatio) {
+        mPipBoundsState.updateMinMaxSize(aspectRatio);
+        mPipResizeGestureHandler.updateMinSize(mPipBoundsState.getMinSize().x,
+                mPipBoundsState.getMinSize().y);
+        mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getMaxSize().x,
+                mPipBoundsState.getMaxSize().y);
+    }
+
+    /**
+     * TODO Add appropriate description
+     */
+    public void onRegistrationChanged(boolean isRegistered) {
+        if (isRegistered) {
+            // Register the accessibility connection.
+        } else {
+            mAccessibilityManager.setPictureInPictureActionReplacingConnection(null);
+        }
+        if (!isRegistered && mTouchState.isUserInteracting()) {
+            // If the input consumer is unregistered while the user is interacting, then we may not
+            // get the final TOUCH_UP event, so clean up the dismiss target as well
+            mPipDismissTargetHandler.cleanUpDismissTarget();
+        }
+    }
+
+    private void onAccessibilityShowMenu() {
+        mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
+                true /* allowMenuTimeout */, willResizeMenu(),
+                shouldShowResizeHandle());
+    }
+
+    /**
+     * TODO Add appropriate description
+     */
+    public boolean handleTouchEvent(InputEvent inputEvent) {
+        // Skip any non motion events
+        if (!(inputEvent instanceof MotionEvent)) {
+            return true;
+        }
+
+        // do not process input event if not allowed
+        if (!mTouchState.getAllowInputEvents()) {
+            return true;
+        }
+
+        MotionEvent ev = (MotionEvent) inputEvent;
+        if (!mPipBoundsState.isStashed() && mPipResizeGestureHandler.willStartResizeGesture(ev)) {
+            // Initialize the touch state for the gesture, but immediately reset to invalidate the
+            // gesture
+            mTouchState.onTouchEvent(ev);
+            mTouchState.reset();
+            return true;
+        }
+
+        if (mPipResizeGestureHandler.hasOngoingGesture()) {
+            mGesture.cleanUpHighPerfSessionMaybe();
+            mPipDismissTargetHandler.hideDismissTargetMaybe();
+            return true;
+        }
+
+        if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
+                && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
+            // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
+            // to the touch state. Touch state needs a DOWN event in order to later process MOVE
+            // events it'll receive if the object is dragged out of the magnetic field.
+            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                mTouchState.onTouchEvent(ev);
+            }
+
+            // Continue tracking velocity when the object is in the magnetic field, since we want to
+            // respect touch input velocity if the object is dragged out and then flung.
+            mTouchState.addMovementToVelocityTracker(ev);
+
+            return true;
+        }
+
+        if (!mTouchState.isUserInteracting()) {
+            ProtoLog.wtf(WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Waiting to start the entry animation, skip the motion event.", TAG);
+            return true;
+        }
+
+        // Update the touch state
+        mTouchState.onTouchEvent(ev);
+
+        boolean shouldDeliverToMenu = mMenuState != MENU_STATE_NONE;
+
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN: {
+                mGesture.onDown(mTouchState);
+                break;
+            }
+            case MotionEvent.ACTION_MOVE: {
+                if (mGesture.onMove(mTouchState)) {
+                    break;
+                }
+
+                shouldDeliverToMenu = !mTouchState.isDragging();
+                break;
+            }
+            case MotionEvent.ACTION_UP: {
+                // Update the movement bounds again if the state has changed since the user started
+                // dragging (ie. when the IME shows)
+                updateMovementBounds();
+
+                if (mGesture.onUp(mTouchState)) {
+                    break;
+                }
+            }
+            // Fall through to clean up
+            case MotionEvent.ACTION_CANCEL: {
+                shouldDeliverToMenu = !mTouchState.startedDragging() && !mTouchState.isDragging();
+                mTouchState.reset();
+                break;
+            }
+            case MotionEvent.ACTION_HOVER_ENTER: {
+                // If Touch Exploration is enabled, some a11y services (e.g. Talkback) is probably
+                // on and changing MotionEvents into HoverEvents.
+                // Let's not enable menu show/hide for a11y services.
+                if (!mAccessibilityManager.isTouchExplorationEnabled()) {
+                    mTouchState.removeHoverExitTimeoutCallback();
+                    mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
+                            false /* allowMenuTimeout */, false /* willResizeMenu */,
+                            shouldShowResizeHandle());
+                }
+            }
+            // Fall through
+            case MotionEvent.ACTION_HOVER_MOVE: {
+                if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) {
+                    sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
+                    mSendingHoverAccessibilityEvents = true;
+                }
+                break;
+            }
+            case MotionEvent.ACTION_HOVER_EXIT: {
+                // If Touch Exploration is enabled, some a11y services (e.g. Talkback) is probably
+                // on and changing MotionEvents into HoverEvents.
+                // Let's not enable menu show/hide for a11y services.
+                if (!mAccessibilityManager.isTouchExplorationEnabled()) {
+                    mTouchState.scheduleHoverExitTimeoutCallback();
+                }
+                if (!shouldDeliverToMenu && mSendingHoverAccessibilityEvents) {
+                    sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+                    mSendingHoverAccessibilityEvents = false;
+                }
+                break;
+            }
+        }
+
+        shouldDeliverToMenu &= !mPipBoundsState.isStashed();
+
+        // Deliver the event to PipMenuActivity to handle button click if the menu has shown.
+        if (shouldDeliverToMenu) {
+            final MotionEvent cloneEvent = MotionEvent.obtain(ev);
+            // Send the cancel event and cancel menu timeout if it starts to drag.
+            if (mTouchState.startedDragging()) {
+                cloneEvent.setAction(MotionEvent.ACTION_CANCEL);
+                mMenuController.pokeMenu();
+            }
+
+            mMenuController.handlePointerEvent(cloneEvent);
+            cloneEvent.recycle();
+        }
+
+        return true;
+    }
+
+    private void sendAccessibilityHoverEvent(int type) {
+        if (!mAccessibilityManager.isEnabled()) {
+            return;
+        }
+
+        AccessibilityEvent event = AccessibilityEvent.obtain(type);
+        event.setImportantForAccessibility(true);
+        event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
+        event.setWindowId(
+                AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+        mAccessibilityManager.sendAccessibilityEvent(event);
+    }
+
+    /**
+     * Called when the PiP menu state is in the process of animating/changing from one to another.
+     */
+    private void onPipMenuStateChangeStart(int menuState, boolean resize, Runnable callback) {
+        if (mMenuState == menuState && !resize) {
+            return;
+        }
+
+        if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
+            // Save the current snap fraction and if we do not drag or move the PiP, then
+            // we store back to this snap fraction.  Otherwise, we'll reset the snap
+            // fraction and snap to the closest edge.
+            if (resize) {
+                // PIP is too small to show the menu actions and thus needs to be resized to a
+                // size that can fit them all. Resize to the default size.
+                animateToNormalSize(callback);
+            }
+        } else if (menuState == MENU_STATE_NONE && mMenuState == MENU_STATE_FULL) {
+            // Try and restore the PiP to the closest edge, using the saved snap fraction
+            // if possible
+            if (resize && !mPipResizeGestureHandler.isResizing()) {
+                if (mDeferResizeToNormalBoundsUntilRotation == -1) {
+                    // This is a very special case: when the menu is expanded and visible,
+                    // navigating to another activity can trigger auto-enter PiP, and if the
+                    // revealed activity has a forced rotation set, then the controller will get
+                    // updated with the new rotation of the display. However, at the same time,
+                    // SystemUI will try to hide the menu by creating an animation to the normal
+                    // bounds which are now stale.  In such a case we defer the animation to the
+                    // normal bounds until after the next onMovementBoundsChanged() call to get the
+                    // bounds in the new orientation
+                    int displayRotation = mContext.getDisplay().getRotation();
+                    if (mDisplayRotation != displayRotation) {
+                        mDeferResizeToNormalBoundsUntilRotation = displayRotation;
+                    }
+                }
+
+                if (mDeferResizeToNormalBoundsUntilRotation == -1) {
+                    animateToUnexpandedState(getUserResizeBounds());
+                }
+            } else {
+                mSavedSnapFraction = -1f;
+            }
+        }
+    }
+
+    private void setMenuState(int menuState) {
+        mMenuState = menuState;
+        updateMovementBounds();
+        // If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
+        // as well, or it can't handle a11y focus and pip menu can't perform any action.
+        onRegistrationChanged(menuState == MENU_STATE_NONE);
+        if (menuState == MENU_STATE_NONE) {
+            mPipUiEventLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_HIDE_MENU);
+        } else if (menuState == MENU_STATE_FULL) {
+            mPipUiEventLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_SHOW_MENU);
+        }
+    }
+
+    private void animateToMaximizedState(Runnable callback) {
+        Rect maxMovementBounds = new Rect();
+        Rect maxBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x,
+                mPipBoundsState.getMaxSize().y);
+        mPipBoundsAlgorithm.getMovementBounds(maxBounds, mInsetBounds, maxMovementBounds,
+                mIsImeShowing ? mImeHeight : 0);
+        mSavedSnapFraction = mMotionHelper.animateToExpandedState(maxBounds,
+                mPipBoundsState.getMovementBounds(), maxMovementBounds,
+                callback);
+    }
+
+    private void animateToNormalSize(Runnable callback) {
+        // Save the current bounds as the user-resize bounds.
+        mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
+
+        final Size minMenuSize = mMenuController.getEstimatedMinMenuSize();
+        final Rect normalBounds = mPipBoundsState.getNormalBounds();
+        final Rect destBounds = mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds,
+                minMenuSize);
+        Rect restoredMovementBounds = new Rect();
+        mPipBoundsAlgorithm.getMovementBounds(destBounds,
+                mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0);
+        mSavedSnapFraction = mMotionHelper.animateToExpandedState(destBounds,
+                mPipBoundsState.getMovementBounds(), restoredMovementBounds, callback);
+    }
+
+    private void animateToUnexpandedState(Rect restoreBounds) {
+        Rect restoredMovementBounds = new Rect();
+        mPipBoundsAlgorithm.getMovementBounds(restoreBounds,
+                mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0);
+        mMotionHelper.animateToUnexpandedState(restoreBounds, mSavedSnapFraction,
+                restoredMovementBounds, mPipBoundsState.getMovementBounds(), false /* immediate */);
+        mSavedSnapFraction = -1f;
+    }
+
+    private void animateToUnStashedState() {
+        final Rect pipBounds = mPipBoundsState.getBounds();
+        final boolean onLeftEdge = pipBounds.left < mPipBoundsState.getDisplayBounds().left;
+        final Rect unStashedBounds = new Rect(0, pipBounds.top, 0, pipBounds.bottom);
+        unStashedBounds.left = onLeftEdge ? mInsetBounds.left
+                : mInsetBounds.right - pipBounds.width();
+        unStashedBounds.right = onLeftEdge ? mInsetBounds.left + pipBounds.width()
+                : mInsetBounds.right;
+        mMotionHelper.animateToUnStashedBounds(unStashedBounds);
+    }
+
+    /**
+     * @return the motion helper.
+     */
+    public PipMotionHelper getMotionHelper() {
+        return mMotionHelper;
+    }
+
+    @VisibleForTesting
+    public PipResizeGestureHandler getPipResizeGestureHandler() {
+        return mPipResizeGestureHandler;
+    }
+
+    @VisibleForTesting
+    public void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) {
+        mPipResizeGestureHandler = pipResizeGestureHandler;
+    }
+
+    @VisibleForTesting
+    public void setPipMotionHelper(PipMotionHelper pipMotionHelper) {
+        mMotionHelper = pipMotionHelper;
+    }
+
+    Rect getUserResizeBounds() {
+        return mPipResizeGestureHandler.getUserResizeBounds();
+    }
+
+    /**
+     * Sets the user resize bounds tracked by {@link PipResizeGestureHandler}
+     */
+    void setUserResizeBounds(Rect bounds) {
+        mPipResizeGestureHandler.setUserResizeBounds(bounds);
+    }
+
+    /**
+     * Gesture controlling normal movement of the PIP.
+     */
+    private class DefaultPipTouchGesture extends PipTouchGesture {
+        private final Point mStartPosition = new Point();
+        private final PointF mDelta = new PointF();
+        private boolean mShouldHideMenuAfterFling;
+
+        @Nullable private PipPerfHintController.PipHighPerfSession mPipHighPerfSession;
+
+        private void onHighPerfSessionTimeout(PipPerfHintController.PipHighPerfSession session) {}
+
+        @Override
+        public void cleanUpHighPerfSessionMaybe() {
+            if (mPipHighPerfSession != null) {
+                // Close the high perf session once pointer interactions are over;
+                mPipHighPerfSession.close();
+                mPipHighPerfSession = null;
+            }
+        }
+
+        @Override
+        public void onDown(PipTouchState touchState) {
+            if (!touchState.isUserInteracting()) {
+                return;
+            }
+
+            if (mPipPerfHintController != null) {
+                // Cache the PiP high perf session to close it upon touch up.
+                mPipHighPerfSession = mPipPerfHintController.startSession(
+                        this::onHighPerfSessionTimeout, "DefaultPipTouchGesture#onDown");
+            }
+
+            Rect bounds = getPossiblyMotionBounds();
+            mDelta.set(0f, 0f);
+            mStartPosition.set(bounds.left, bounds.top);
+            mMovementWithinDismiss = touchState.getDownTouchPosition().y
+                    >= mPipBoundsState.getMovementBounds().bottom;
+            mMotionHelper.setSpringingToTouch(false);
+            // mPipDismissTargetHandler.setTaskLeash(mPipTaskOrganizer.getSurfaceControl());
+
+            // If the menu is still visible then just poke the menu
+            // so that it will timeout after the user stops touching it
+            if (mMenuState != MENU_STATE_NONE && !mPipBoundsState.isStashed()) {
+                mMenuController.pokeMenu();
+            }
+        }
+
+        @Override
+        public boolean onMove(PipTouchState touchState) {
+            if (!touchState.isUserInteracting()) {
+                return false;
+            }
+
+            if (touchState.startedDragging()) {
+                mSavedSnapFraction = -1f;
+                mPipDismissTargetHandler.showDismissTargetMaybe();
+            }
+
+            if (touchState.isDragging()) {
+                mPipBoundsState.setHasUserMovedPip(true);
+
+                // Move the pinned stack freely
+                final PointF lastDelta = touchState.getLastTouchDelta();
+                float lastX = mStartPosition.x + mDelta.x;
+                float lastY = mStartPosition.y + mDelta.y;
+                float left = lastX + lastDelta.x;
+                float top = lastY + lastDelta.y;
+
+                // Add to the cumulative delta after bounding the position
+                mDelta.x += left - lastX;
+                mDelta.y += top - lastY;
+
+                mTmpBounds.set(getPossiblyMotionBounds());
+                mTmpBounds.offsetTo((int) left, (int) top);
+                mMotionHelper.movePip(mTmpBounds, true /* isDragging */);
+
+                final PointF curPos = touchState.getLastTouchPosition();
+                if (mMovementWithinDismiss) {
+                    // Track if movement remains near the bottom edge to identify swipe to dismiss
+                    mMovementWithinDismiss = curPos.y >= mPipBoundsState.getMovementBounds().bottom;
+                }
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public boolean onUp(PipTouchState touchState) {
+            mPipDismissTargetHandler.hideDismissTargetMaybe();
+            mPipDismissTargetHandler.setTaskLeash(null);
+
+            if (!touchState.isUserInteracting()) {
+                return false;
+            }
+
+            final PointF vel = touchState.getVelocity();
+
+            if (touchState.isDragging()) {
+                if (mMenuState != MENU_STATE_NONE) {
+                    // If the menu is still visible, then just poke the menu so that
+                    // it will timeout after the user stops touching it
+                    mMenuController.showMenu(mMenuState, mPipBoundsState.getBounds(),
+                            true /* allowMenuTimeout */, willResizeMenu(),
+                            shouldShowResizeHandle());
+                }
+                mShouldHideMenuAfterFling = mMenuState == MENU_STATE_NONE;
+
+                // Reset the touch state on up before the fling settles
+                mTouchState.reset();
+                if (mEnableStash && shouldStash(vel, getPossiblyMotionBounds())) {
+                    mMotionHelper.stashToEdge(vel.x, vel.y, this::stashEndAction /* endAction */);
+                } else {
+                    if (mPipBoundsState.isStashed()) {
+                        // Reset stashed state if previously stashed
+                        mPipUiEventLogger.log(
+                                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
+                        mPipBoundsState.setStashed(STASH_TYPE_NONE);
+                    }
+                    mMotionHelper.flingToSnapTarget(vel.x, vel.y,
+                            this::flingEndAction /* endAction */);
+                }
+            } else if (mTouchState.isDoubleTap() && !mPipBoundsState.isStashed()
+                    && mMenuState != MENU_STATE_FULL) {
+                // If using pinch to zoom, double-tap functions as resizing between max/min size
+                if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
+                    final boolean toExpand = mPipBoundsState.getBounds().width()
+                            < mPipBoundsState.getMaxSize().x
+                            && mPipBoundsState.getBounds().height()
+                            < mPipBoundsState.getMaxSize().y;
+                    if (mMenuController.isMenuVisible()) {
+                        mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */);
+                    }
+
+                    // the size to toggle to after a double tap
+                    int nextSize = PipDoubleTapHelper
+                            .nextSizeSpec(mPipBoundsState, getUserResizeBounds());
+
+                    // actually toggle to the size chosen
+                    if (nextSize == PipDoubleTapHelper.SIZE_SPEC_MAX) {
+                        mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
+                        animateToMaximizedState(null);
+                    } else if (nextSize == PipDoubleTapHelper.SIZE_SPEC_DEFAULT) {
+                        mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
+                        animateToNormalSize(null);
+                    } else {
+                        animateToUnexpandedState(getUserResizeBounds());
+                    }
+                } else {
+                    // Expand to fullscreen if this is a double tap
+                    // the PiP should be frozen until the transition ends
+                    setTouchEnabled(false);
+                    mMotionHelper.expandLeavePip(false /* skipAnimation */);
+                }
+            } else if (mMenuState != MENU_STATE_FULL) {
+                if (mPipBoundsState.isStashed()) {
+                    // Unstash immediately if stashed, and don't wait for the double tap timeout
+                    animateToUnStashedState();
+                    mPipUiEventLogger.log(
+                            PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
+                    mPipBoundsState.setStashed(STASH_TYPE_NONE);
+                    mTouchState.removeDoubleTapTimeoutCallback();
+                } else if (!mTouchState.isWaitingForDoubleTap()) {
+                    // User has stalled long enough for this not to be a drag or a double tap,
+                    // just expand the menu
+                    mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
+                            true /* allowMenuTimeout */, willResizeMenu(),
+                            shouldShowResizeHandle());
+                } else {
+                    // Next touch event _may_ be the second tap for the double-tap, schedule a
+                    // fallback runnable to trigger the menu if no touch event occurs before the
+                    // next tap
+                    mTouchState.scheduleDoubleTapTimeoutCallback();
+                }
+            }
+            cleanUpHighPerfSessionMaybe();
+            return true;
+        }
+
+        private void stashEndAction() {
+            if (mPipBoundsState.getBounds().left < 0
+                    && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT) {
+                mPipUiEventLogger.log(
+                        PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_LEFT);
+                mPipBoundsState.setStashed(STASH_TYPE_LEFT);
+            } else if (mPipBoundsState.getBounds().left >= 0
+                    && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) {
+                mPipUiEventLogger.log(
+                        PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_RIGHT);
+                mPipBoundsState.setStashed(STASH_TYPE_RIGHT);
+            }
+            mMenuController.hideMenu();
+        }
+
+        private void flingEndAction() {
+            if (mShouldHideMenuAfterFling) {
+                // If the menu is not visible, then we can still be showing the activity for the
+                // dismiss overlay, so just finish it after the animation completes
+                mMenuController.hideMenu();
+            }
+        }
+
+        private boolean shouldStash(PointF vel, Rect motionBounds) {
+            final boolean flingToLeft = vel.x < -mStashVelocityThreshold;
+            final boolean flingToRight = vel.x > mStashVelocityThreshold;
+            final int offset = motionBounds.width() / 2;
+            final boolean droppingOnLeft =
+                    motionBounds.left < mPipBoundsState.getDisplayBounds().left - offset;
+            final boolean droppingOnRight =
+                    motionBounds.right > mPipBoundsState.getDisplayBounds().right + offset;
+
+            // Do not allow stash if the destination edge contains display cutout. We only
+            // compare the left and right edges since we do not allow stash on top / bottom.
+            final DisplayCutout displayCutout =
+                    mPipBoundsState.getDisplayLayout().getDisplayCutout();
+            if (displayCutout != null) {
+                if ((flingToLeft || droppingOnLeft)
+                        && !displayCutout.getBoundingRectLeft().isEmpty()) {
+                    return false;
+                } else if ((flingToRight || droppingOnRight)
+                        && !displayCutout.getBoundingRectRight().isEmpty()) {
+                    return false;
+                }
+            }
+
+            // If user flings the PIP window above the minimum velocity, stash PIP.
+            // Only allow stashing to the edge if PIP wasn't previously stashed on the opposite
+            // edge.
+            final boolean stashFromFlingToEdge =
+                    (flingToLeft && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT)
+                    || (flingToRight && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT);
+
+            // If User releases the PIP window while it's out of the display bounds, put
+            // PIP into stashed mode.
+            final boolean stashFromDroppingOnEdge = droppingOnLeft || droppingOnRight;
+
+            return stashFromFlingToEdge || stashFromDroppingOnEdge;
+        }
+    }
+
+    /**
+     * Updates the current movement bounds based on whether the menu is currently visible and
+     * resized.
+     */
+    private void updateMovementBounds() {
+        mPipBoundsAlgorithm.getMovementBounds(mPipBoundsState.getBounds(),
+                mInsetBounds, mPipBoundsState.getMovementBounds(), mIsImeShowing ? mImeHeight : 0);
+        mMotionHelper.onMovementBoundsChanged();
+    }
+
+    private Rect getMovementBounds(Rect curBounds) {
+        Rect movementBounds = new Rect();
+        mPipBoundsAlgorithm.getMovementBounds(curBounds, mInsetBounds,
+                movementBounds, mIsImeShowing ? mImeHeight : 0);
+        return movementBounds;
+    }
+
+    /**
+     * @return {@code true} if the menu should be resized on tap because app explicitly specifies
+     * PiP window size that is too small to hold all the actions.
+     */
+    private boolean willResizeMenu() {
+        if (!mEnableResize) {
+            return false;
+        }
+        final Size estimatedMinMenuSize = mMenuController.getEstimatedMinMenuSize();
+        if (estimatedMinMenuSize == null) {
+            ProtoLog.wtf(WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Failed to get estimated menu size", TAG);
+            return false;
+        }
+        final Rect currentBounds = mPipBoundsState.getBounds();
+        return currentBounds.width() < estimatedMinMenuSize.getWidth()
+                || currentBounds.height() < estimatedMinMenuSize.getHeight();
+    }
+
+    /**
+     * Returns the PIP bounds if we're not in the middle of a motion operation, or the current,
+     * temporary motion bounds otherwise.
+     */
+    Rect getPossiblyMotionBounds() {
+        return mPipBoundsState.getMotionBoundsState().isInMotion()
+                ? mPipBoundsState.getMotionBoundsState().getBoundsInMotion()
+                : mPipBoundsState.getBounds();
+    }
+
+    void setOhmOffset(int offset) {
+        mPipResizeGestureHandler.setOhmOffset(offset);
+    }
+
+    /**
+     * Dumps the {@link PipTouchHandler} state.
+     */
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + "mMenuState=" + mMenuState);
+        pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
+        pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
+        pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
+        pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
+        pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
+        pw.println(innerPrefix + "mMovementBoundsExtraOffsets=" + mMovementBoundsExtraOffsets);
+        mPipBoundsAlgorithm.dump(pw, innerPrefix);
+        mTouchState.dump(pw, innerPrefix);
+        if (mPipResizeGestureHandler != null) {
+            mPipResizeGestureHandler.dump(pw, innerPrefix);
+        }
+    }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index b179b5b..e829d4e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -17,8 +17,10 @@
 package com.android.wm.shell.pip2.phone;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_PIP;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
@@ -159,7 +161,7 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        if (transition == mEnterTransition) {
+        if (transition == mEnterTransition || info.getType() == TRANSIT_PIP) {
             mEnterTransition = null;
             if (mPipScheduler.isInSwipePipToHomeTransition()) {
                 // If this is the second transition as a part of swipe PiP to home cuj,
@@ -182,6 +184,10 @@
             mResizeTransition = null;
             return startResizeAnimation(info, startTransaction, finishTransaction, finishCallback);
         }
+
+        if (isRemovePipTransition(info)) {
+            return removePipImmediately(info, startTransaction, finishTransaction, finishCallback);
+        }
         return false;
     }
 
@@ -291,6 +297,10 @@
         startOverlayFadeoutAnimation();
     }
 
+    //
+    // Subroutines setting up and starting transitions' animations.
+    //
+
     private void startOverlayFadeoutAnimation() {
         ValueAnimator animator = ValueAnimator.ofFloat(1f, 0f);
         animator.setDuration(CONTENT_OVERLAY_FADE_OUT_DELAY_MS);
@@ -326,6 +336,7 @@
         mPipScheduler.setPipTaskToken(mPipTaskToken);
 
         startTransaction.apply();
+        // TODO: b/275910498 Use a new implementation of the PiP animator here.
         finishCallback.onTransitionFinished(null);
         return true;
     }
@@ -353,11 +364,26 @@
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
         startTransaction.apply();
+        // TODO: b/275910498 Use a new implementation of the PiP animator here.
         finishCallback.onTransitionFinished(null);
         onExitPip();
         return true;
     }
 
+    private boolean removePipImmediately(@NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        startTransaction.apply();
+        finishCallback.onTransitionFinished(null);
+        onExitPip();
+        return true;
+    }
+
+    //
+    // Utility methods for checking PiP-related transition info and requests.
+    //
+
     @Nullable
     private TransitionInfo.Change getPipChange(TransitionInfo info) {
         for (TransitionInfo.Change change : info.getChanges()) {
@@ -415,6 +441,25 @@
                 && info.getChanges().size() == 1;
     }
 
+    private boolean isRemovePipTransition(@NonNull TransitionInfo info) {
+        if (mPipTaskToken == null) {
+            // PiP removal makes sense if enter-PiP has cached a valid pinned task token.
+            return false;
+        }
+        TransitionInfo.Change pipChange = info.getChange(mPipTaskToken);
+        if (pipChange == null) {
+            // Search for the PiP change by token since the windowing mode might be FULLSCREEN now.
+            return false;
+        }
+
+        boolean isPipMovedToBack = info.getType() == TRANSIT_TO_BACK
+                && pipChange.getMode() == TRANSIT_TO_BACK;
+        boolean isPipClosed = info.getType() == TRANSIT_CLOSE
+                && pipChange.getMode() == TRANSIT_CLOSE;
+        // PiP is being removed if the pinned task is either moved to back or closed.
+        return isPipMovedToBack || isPipClosed;
+    }
+
     /**
      * TODO: b/275910498 Use a new implementation of the PiP animator here.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl
index e8f58fe..62d195e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl
@@ -37,4 +37,9 @@
      * Called when a running task vanishes.
      */
     void onRunningTaskVanished(in RunningTaskInfo taskInfo);
+
+    /**
+     * Called when a running task changes.
+     */
+    void onRunningTaskChanged(in RunningTaskInfo taskInfo);
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java
index eebd133..77b8663 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasks.java
@@ -16,6 +16,9 @@
 
 package com.android.wm.shell.recents;
 
+import android.annotation.Nullable;
+import android.graphics.Color;
+
 import com.android.wm.shell.shared.annotations.ExternalThread;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
 
@@ -40,4 +43,12 @@
      */
     default void addAnimationStateListener(Executor listenerExecutor, Consumer<Boolean> listener) {
     }
+
+    /**
+     * Sets a background color on the transition root layered behind the outgoing task. {@code null}
+     * may be used to clear any previously set colors to avoid showing a background at all. The
+     * color is always shown at full opacity.
+     */
+    default void setTransitionBackgroundColor(@Nullable Color color) {
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index f9fcfac..e7d9812 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.content.pm.PackageManager.FEATURE_PC;
 
+import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS;
 
@@ -26,10 +27,10 @@
 import android.app.ActivityTaskManager;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
-import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -86,7 +87,7 @@
     private final ActivityTaskManager mActivityTaskManager;
     private RecentsTransitionHandler mTransitionHandler = null;
     private IRecentTasksListener mListener;
-    private final boolean mIsDesktopMode;
+    private final boolean mPcFeatureEnabled;
 
     // Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a
     // pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1)
@@ -133,7 +134,7 @@
         mShellController = shellController;
         mShellCommandHandler = shellCommandHandler;
         mActivityTaskManager = activityTaskManager;
-        mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
+        mPcFeatureEnabled = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
         mTaskStackListener = taskStackListener;
         mDesktopModeTaskRepository = desktopModeTaskRepository;
         mMainExecutor = mainExecutor;
@@ -252,8 +253,10 @@
         notifyRunningTaskVanished(taskInfo);
     }
 
-    public void onTaskWindowingModeChanged(TaskInfo taskInfo) {
+    /** Notify listeners that the windowing mode of the given Task was updated. */
+    public void onTaskWindowingModeChanged(ActivityManager.RunningTaskInfo taskInfo) {
         notifyRecentTasksChanged();
+        notifyRunningTaskChanged(taskInfo);
     }
 
     @Override
@@ -278,7 +281,9 @@
      * Notify the running task listener that a task appeared on desktop environment.
      */
     private void notifyRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
-        if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) {
+        if (mListener == null
+                || !shouldEnableRunningTasksForDesktopMode()
+                || taskInfo.realActivity == null) {
             return;
         }
         try {
@@ -292,7 +297,9 @@
      * Notify the running task listener that a task was removed on desktop environment.
      */
     private void notifyRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
-        if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) {
+        if (mListener == null
+                || !shouldEnableRunningTasksForDesktopMode()
+                || taskInfo.realActivity == null) {
             return;
         }
         try {
@@ -302,6 +309,27 @@
         }
     }
 
+    /**
+     * Notify the running task listener that a task was changed on desktop environment.
+     */
+    private void notifyRunningTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        if (mListener == null
+                || !shouldEnableRunningTasksForDesktopMode()
+                || taskInfo.realActivity == null) {
+            return;
+        }
+        try {
+            mListener.onRunningTaskChanged(taskInfo);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Failed call onRunningTaskChanged", e);
+        }
+    }
+
+    private boolean shouldEnableRunningTasksForDesktopMode() {
+        return mPcFeatureEnabled
+                || (DesktopModeStatus.isEnabled() && enableDesktopWindowingTaskbarRunningApps());
+    }
+
     @VisibleForTesting
     void registerRecentTasksListener(IRecentTasksListener listener) {
         mListener = listener;
@@ -449,6 +477,16 @@
                 });
             });
         }
+
+        @Override
+        public void setTransitionBackgroundColor(@Nullable Color color) {
+            mMainExecutor.execute(() -> {
+                if (mTransitionHandler == null) {
+                    return;
+                }
+                mTransitionHandler.setTransitionBackgroundColor(color);
+            });
+        }
     }
 
 
@@ -476,6 +514,11 @@
             public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
                 mListener.call(l -> l.onRunningTaskVanished(taskInfo));
             }
+
+            @Override
+            public void onRunningTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+                mListener.call(l -> l.onRunningTaskChanged(taskInfo));
+            }
         };
 
         public IRecentTasksImpl(RecentTasksController controller) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 3b4fb9f..c625b69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
+import static android.view.WindowManager.TRANSIT_PIP;
 import static android.view.WindowManager.TRANSIT_SLEEP;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
@@ -35,6 +36,7 @@
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
 import android.content.Intent;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -55,10 +57,13 @@
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.pip.PipUtils;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.shared.TransitionUtil;
 import com.android.wm.shell.sysui.ShellInit;
@@ -90,6 +95,7 @@
     private final ArrayList<RecentsMixedHandler> mMixers = new ArrayList<>();
 
     private final HomeTransitionObserver mHomeTransitionObserver;
+    private @Nullable Color mBackgroundColor;
 
     public RecentsTransitionHandler(ShellInit shellInit, Transitions transitions,
             @Nullable RecentTasksController recentTasksController,
@@ -121,6 +127,15 @@
         mStateListeners.add(listener);
     }
 
+    /**
+     * Sets a background color on the transition root layered behind the outgoing task. {@code null}
+     * may be used to clear any previously set colors to avoid showing a background at all. The
+     * color is always shown at full opacity.
+     */
+    public void setTransitionBackgroundColor(@Nullable Color color) {
+        mBackgroundColor = color;
+    }
+
     @VisibleForTesting
     public IBinder startRecentsTransition(PendingIntent intent, Intent fillIn, Bundle options,
             IApplicationThread appThread, IRecentsAnimationRunner listener) {
@@ -467,6 +482,16 @@
             final int belowLayers = info.getChanges().size();
             final int middleLayers = info.getChanges().size() * 2;
             final int aboveLayers = info.getChanges().size() * 3;
+
+            // Add a background color to each transition root in this transition.
+            if (mBackgroundColor != null) {
+                info.getChanges().stream()
+                        .mapToInt((change) -> TransitionUtil.rootIndexFor(change, info))
+                        .distinct()
+                        .mapToObj((rootIndex) -> info.getRoot(rootIndex).getLeash())
+                        .forEach((root) -> createBackgroundSurface(t, root, middleLayers));
+            }
+
             for (int i = 0; i < info.getChanges().size(); ++i) {
                 final TransitionInfo.Change change = info.getChanges().get(i);
                 final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
@@ -1023,13 +1048,16 @@
                 }
                 if (mPipTransaction != null && sendUserLeaveHint) {
                     SurfaceControl pipLeash = null;
+                    TransitionInfo.Change pipChange = null;
                     if (mPipTask != null) {
-                        pipLeash = mInfo.getChange(mPipTask).getLeash();
+                        pipChange = mInfo.getChange(mPipTask);
+                        pipLeash = pipChange.getLeash();
                     } else if (mPipTaskId != -1) {
                         // find a task with taskId from #setFinishTaskTransaction()
                         for (TransitionInfo.Change change : mInfo.getChanges()) {
                             if (change.getTaskInfo() != null
                                     && change.getTaskInfo().taskId == mPipTaskId) {
+                                pipChange = change;
                                 pipLeash = change.getLeash();
                                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                         "RecentsController.finishInner:"
@@ -1048,6 +1076,28 @@
                         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                 "RecentsController.finishInner: PiP transaction %s merged",
                                 mPipTransaction);
+                        if (PipUtils.isPip2ExperimentEnabled()) {
+                            // If this path is triggered, we are in auto-enter PiP flow in gesture
+                            // navigation mode, which means "Recents" transition should be followed
+                            // by a TRANSIT_PIP. Hence, we take the WCT was about to be sent
+                            // to Core to be applied during finishTransition(), we modify it to
+                            // factor in PiP changes, and we send it as a direct startWCT for
+                            // a new TRANSIT_PIP type transition. Recents still sends
+                            // finishTransition() to update visibilities, but with finishWCT=null.
+                            TransitionRequestInfo requestInfo = new TransitionRequestInfo(
+                                    TRANSIT_PIP, null /* triggerTask */, pipChange.getTaskInfo(),
+                                    null /* remote */, null /* displayChange */, 0 /* flags */);
+                            // Use mTransition IBinder token temporarily just to get PipTransition
+                            // to return from its handleRequest(). The actual TRANSIT_PIP will have
+                            // anew token once it arrives into PipTransition#startAnimation().
+                            Pair<Transitions.TransitionHandler, WindowContainerTransaction>
+                                    requestRes = mTransitions.dispatchRequest(mTransition,
+                                            requestInfo, null /* skip */);
+                            wct.merge(requestRes.second, true);
+                            mTransitions.startTransition(TRANSIT_PIP, wct, null /* handler */);
+                            // We need to clear the WCT to send finishWCT=null for Recents.
+                            wct.clear();
+                        }
                     }
                     mPipTaskId = -1;
                     mPipTask = null;
@@ -1080,6 +1130,29 @@
             return true;
         }
 
+        private void createBackgroundSurface(SurfaceControl.Transaction transaction,
+                SurfaceControl parent, int layer) {
+            if (mBackgroundColor == null) {
+                return;
+            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                    "  adding background color to layer=%d", layer);
+            final SurfaceControl background = new SurfaceControl.Builder()
+                    .setName("recents_background")
+                    .setColorLayer()
+                    .setOpaque(true)
+                    .setParent(parent)
+                    .build();
+            transaction.setColor(background, colorToFloatArray(mBackgroundColor));
+            transaction.setLayer(background, layer);
+            transaction.setAlpha(background, 1F);
+            transaction.show(background);
+        }
+
+        private static float[] colorToFloatArray(@NonNull Color color) {
+            return new float[]{color.red(), color.green(), color.blue()};
+        }
+
         private void cleanUpPausingOrClosingTask(TaskState task, WindowContainerTransaction wct,
                 SurfaceControl.Transaction finishTransaction, boolean sendUserLeaveHint) {
             if (!sendUserLeaveHint && task.isLeaf()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 5762197..6aad4e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -18,9 +18,14 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.graphics.Rect;
+import android.os.Bundle;
+import android.window.RemoteTransition;
 
+import com.android.internal.logging.InstanceId;
+import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
 import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
 import com.android.wm.shell.shared.annotations.ExternalThread;
 
@@ -72,6 +77,12 @@
         }
     }
 
+    /** Launches a pair of tasks into splitscreen */
+    void startTasks(int taskId1, @Nullable Bundle options1, int taskId2,
+            @Nullable Bundle options2, @SplitPosition int splitPosition,
+            @PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
+            InstanceId instanceId);
+
     /** Registers listener that gets split screen callback. */
     void registerSplitScreenListener(@NonNull SplitScreenListener listener,
             @NonNull Executor executor);
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 088bb48..547457b 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
@@ -506,6 +506,15 @@
         return mStageCoordinator.getActivateSplitPosition(taskInfo);
     }
 
+    /** Start two tasks in parallel as a splitscreen pair. */
+    public void startTasks(int taskId1, @Nullable Bundle options1, int taskId2,
+            @Nullable Bundle options2, @SplitPosition int splitPosition,
+            @PersistentSnapPosition int snapPosition,
+            @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
+        mStageCoordinator.startTasks(taskId1, options1, taskId2, options2, splitPosition,
+                snapPosition, remoteTransition, instanceId);
+    }
+
     /**
      * Move a task to split select
      * @param taskInfo the task being moved to split select
@@ -1120,6 +1129,15 @@
         };
 
         @Override
+        public void startTasks(int taskId1, @Nullable Bundle options1, int taskId2,
+                @Nullable Bundle options2, int splitPosition, int snapPosition,
+                @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
+            mMainExecutor.execute(() -> SplitScreenController.this.startTasks(
+                    taskId1, options1, taskId2, options2, splitPosition, snapPosition,
+                    remoteTransition, instanceId));
+        }
+
+        @Override
         public void registerSplitScreenListener(SplitScreenListener listener, Executor executor) {
             if (mExecutors.containsKey(listener)) return;
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
index 35a1fa0..a85188a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
@@ -30,7 +30,6 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Handler;
-import android.os.Looper;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
@@ -121,6 +120,11 @@
 
     @Override
     public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
+        if (mTaskViewTaskController.isUsingShellTransitions()) {
+            // No need for additional work as it is already taken care of during
+            // prepareOpenAnimation().
+            return;
+        }
         onLocationChanged();
         if (taskInfo.taskDescription != null) {
             final int bgColor = taskInfo.taskDescription.getBackgroundColor();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index 196e04e..11aa402 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -17,6 +17,7 @@
 package com.android.wm.shell.taskview;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -48,6 +49,23 @@
  * TaskView} to {@link TaskViewTaskController} interactions are done via direct method calls.
  *
  * The reverse communication is done via the {@link TaskViewBase} interface.
+ *
+ * <ul>
+ *     <li>The entry point for an activity based task view is {@link
+ *     TaskViewTaskController#startActivity(PendingIntent, Intent, ActivityOptions, Rect)}</li>
+ *
+ *     <li>The entry point for an activity (represented by {@link ShortcutInfo}) based task view
+ *     is {@link TaskViewTaskController#startShortcutActivity(ShortcutInfo, ActivityOptions, Rect)}
+ *     </li>
+ *
+ *     <li>The entry point for a root-task based task view is {@link
+ *     TaskViewTaskController#startRootTask(ActivityManager.RunningTaskInfo, SurfaceControl,
+ *     WindowContainerTransaction)}.
+ *     This method is special as it doesn't create a root task and instead expects that the
+ *     launch root task is already created and started. This method just attaches the taskInfo to
+ *     the TaskView.
+ *     </li>
+ * </ul>
  */
 public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
 
@@ -155,8 +173,8 @@
      * <p>The owner of this container must be allowed to access the shortcut information,
      * as defined in {@link LauncherApps#hasShortcutHostPermission()} to use this method.
      *
-     * @param shortcut the shortcut used to launch the activity.
-     * @param options options for the activity.
+     * @param shortcut     the shortcut used to launch the activity.
+     * @param options      options for the activity.
      * @param launchBounds the bounds (window size and position) that the activity should be
      *                     launched in, in pixels and in screen coordinates.
      */
@@ -183,10 +201,10 @@
      * Launch a new activity.
      *
      * @param pendingIntent Intent used to launch an activity.
-     * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
-     * @param options options for the activity.
-     * @param launchBounds the bounds (window size and position) that the activity should be
-     *                     launched in, in pixels and in screen coordinates.
+     * @param fillInIntent  Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
+     * @param options       options for the activity.
+     * @param launchBounds  the bounds (window size and position) that the activity should be
+     *                      launched in, in pixels and in screen coordinates.
      */
     public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
             @NonNull ActivityOptions options, @Nullable Rect launchBounds) {
@@ -208,6 +226,35 @@
         }
     }
 
+
+    /**
+     * Attaches the given root task {@code taskInfo} in the task view.
+     *
+     * <p> Since {@link ShellTaskOrganizer#createRootTask(int, int,
+     * ShellTaskOrganizer.TaskListener)} does not use the shell transitions flow, this method is
+     * used as an entry point for an already-created root-task in the task view.
+     *
+     * @param taskInfo the task info of the root task.
+     * @param leash    the {@link android.content.pm.ShortcutInfo.Surface} of the root task
+     * @param wct      The Window container work that should happen as part of this set up.
+     */
+    public void startRootTask(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
+            @Nullable WindowContainerTransaction wct) {
+        if (wct == null) {
+            wct = new WindowContainerTransaction();
+        }
+        // This method skips the regular flow where an activity task is launched as part of a new
+        // transition in taskview and then transition is intercepted using the launchcookie.
+        // The task here is already created and running, it just needs to be reparented, resized
+        // and tracked correctly inside taskview. Which is done by calling
+        // prepareOpenAnimationInternal() and then manually enqueuing the resulting window container
+        // transaction.
+        prepareOpenAnimationInternal(true /* newTask */, mTransaction /* startTransaction */,
+                null /* finishTransaction */, taskInfo, leash, wct);
+        mTransaction.apply();
+        mTaskViewTransitions.startInstantTransition(TRANSIT_CHANGE, wct);
+    }
+
     private void prepareActivityOptions(ActivityOptions options, Rect launchBounds) {
         final Binder launchCookie = new Binder();
         mShellExecutor.execute(() -> {
@@ -342,7 +389,6 @@
         final SurfaceControl taskLeash = mTaskLeash;
         handleAndNotifyTaskRemoval(mTaskInfo);
 
-        // Unparent the task when this surface is destroyed
         mTransaction.reparent(taskLeash, null).apply();
         resetTaskInfo();
     }
@@ -597,6 +643,15 @@
             @NonNull SurfaceControl.Transaction finishTransaction,
             ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
             WindowContainerTransaction wct) {
+        prepareOpenAnimationInternal(newTask, startTransaction, finishTransaction, taskInfo, leash,
+                wct);
+    }
+
+    private void prepareOpenAnimationInternal(final boolean newTask,
+            SurfaceControl.Transaction startTransaction,
+            SurfaceControl.Transaction finishTransaction,
+            ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
+            WindowContainerTransaction wct) {
         mPendingInfo = null;
         mTaskInfo = taskInfo;
         mTaskToken = mTaskInfo.token;
@@ -608,10 +663,12 @@
             // Also reparent on finishTransaction since the finishTransaction will reparent back
             // to its "original" parent by default.
             Rect boundsOnScreen = mTaskViewBase.getCurrentBoundsOnScreen();
-            finishTransaction.reparent(mTaskLeash, mSurfaceControl)
-                    .setPosition(mTaskLeash, 0, 0)
-                    // TODO: maybe once b/280900002 is fixed this will be unnecessary
-                    .setWindowCrop(mTaskLeash, boundsOnScreen.width(), boundsOnScreen.height());
+            if (finishTransaction != null) {
+                finishTransaction.reparent(mTaskLeash, mSurfaceControl)
+                        .setPosition(mTaskLeash, 0, 0)
+                        // TODO: maybe once b/280900002 is fixed this will be unnecessary
+                        .setWindowCrop(mTaskLeash, boundsOnScreen.width(), boundsOnScreen.height());
+            }
             mTaskViewTransitions.updateBoundsState(this, boundsOnScreen);
             mTaskViewTransitions.updateVisibilityState(this, true /* visible */);
             wct.setBounds(mTaskToken, boundsOnScreen);
@@ -632,6 +689,7 @@
             mTaskViewBase.setResizeBgColor(startTransaction, backgroundColor);
         }
 
+        mTaskViewBase.onTaskAppeared(mTaskInfo, mTaskLeash);
         if (mListener != null) {
             final int taskId = mTaskInfo.taskId;
             final ComponentName baseActivity = mTaskInfo.baseActivity;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index 198ec82..e6d1b45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -53,7 +53,7 @@
             new ArrayMap<>();
     private final ArrayList<PendingTransition> mPending = new ArrayList<>();
     private final Transitions mTransitions;
-    private final boolean[] mRegistered = new boolean[]{ false };
+    private final boolean[] mRegistered = new boolean[]{false};
 
     /**
      * TaskView makes heavy use of startTransition. Only one shell-initiated transition can be
@@ -122,6 +122,7 @@
     /**
      * Looks through the pending transitions for a closing transaction that matches the provided
      * `taskView`.
+     *
      * @param taskView the pending transition should be for this.
      */
     private PendingTransition findPendingCloseTransition(TaskViewTaskController taskView) {
@@ -135,8 +136,17 @@
     }
 
     /**
+     * Starts a transition outside of the handler associated with {@link TaskViewTransitions}.
+     */
+    public void startInstantTransition(@WindowManager.TransitionType int type,
+            WindowContainerTransaction wct) {
+        mTransitions.startTransition(type, wct, null);
+    }
+
+    /**
      * Looks through the pending transitions for a opening transaction that matches the provided
      * `taskView`.
+     *
      * @param taskView the pending transition should be for this.
      */
     @VisibleForTesting
@@ -152,8 +162,9 @@
 
     /**
      * Looks through the pending transitions for one matching `taskView`.
+     *
      * @param taskView the pending transition should be for this.
-     * @param type the type of transition it's looking for
+     * @param type     the type of transition it's looking for
      */
     PendingTransition findPending(TaskViewTaskController taskView, int type) {
         for (int i = mPending.size() - 1; i >= 0; --i) {
@@ -220,7 +231,24 @@
         startNextTransition();
     }
 
-    void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
+    /** Starts a new transition to make the given {@code taskView} visible. */
+    public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
+        setTaskViewVisible(taskView, visible, false /* reorder */);
+    }
+
+    /**
+     * Starts a new transition to make the given {@code taskView} visible and optionally change
+     * the task order.
+     *
+     * @param taskView the task view which the visibility is being changed for
+     * @param visible  the new visibility of the task view
+     * @param reorder  whether to reorder the task or not. If this is {@code true}, the task will be
+     *                 reordered as per the given {@code visible}. For {@code visible = true}, task
+     *                 will be reordered to top. For {@code visible = false}, task will be reordered
+     *                 to the bottom
+     */
+    public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible,
+            boolean reorder) {
         if (mTaskViews.get(taskView) == null) return;
         if (mTaskViews.get(taskView).mVisible == visible) return;
         if (taskView.getTaskInfo() == null) {
@@ -231,6 +259,9 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
         wct.setBounds(taskView.getTaskInfo().token, mTaskViews.get(taskView).mBounds);
+        if (reorder) {
+            wct.reorder(taskView.getTaskInfo().token, visible /* onTop */);
+        }
         PendingTransition pending = new PendingTransition(
                 visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
         mPending.add(pending);
@@ -238,6 +269,22 @@
         // visibility is reported in transition.
     }
 
+    /** Starts a new transition to reorder the given {@code taskView}'s task. */
+    public void reorderTaskViewTask(TaskViewTaskController taskView, boolean onTop) {
+        if (mTaskViews.get(taskView) == null) return;
+        if (taskView.getTaskInfo() == null) {
+            // Nothing to update, task is not yet available
+            return;
+        }
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.reorder(taskView.getTaskInfo().token, onTop /* onTop */);
+        PendingTransition pending = new PendingTransition(
+                onTop ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
+        mPending.add(pending);
+        startNextTransition();
+        // visibility is reported in transition.
+    }
+
     void updateBoundsState(TaskViewTaskController taskView, Rect boundsOnScreen) {
         TaskViewRequestedState state = mTaskViews.get(taskView);
         if (state == null) return;
@@ -380,7 +427,7 @@
                 }
                 startTransaction.reparent(chg.getLeash(), tv.getSurfaceControl());
                 finishTransaction.reparent(chg.getLeash(), tv.getSurfaceControl())
-                    .setPosition(chg.getLeash(), 0, 0);
+                        .setPosition(chg.getLeash(), 0, 0);
                 changesHandled++;
             }
         }
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 8746b8c..4bc0dc0 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
@@ -61,9 +61,10 @@
 
 /**
  * A handler for dealing with transitions involving multiple other handlers. For example: an
- * activity in split-screen going into PiP.
+ * activity in split-screen going into PiP. Note this is provided as a handset-specific
+ * implementation of {@code MixedTransitionHandler}.
  */
-public class DefaultMixedHandler implements Transitions.TransitionHandler,
+public class DefaultMixedHandler implements MixedTransitionHandler,
         RecentsTransitionHandler.RecentsMixedHandler {
 
     private final Transitions mPlayer;
@@ -116,7 +117,7 @@
         final IBinder mTransition;
 
         protected final Transitions mPlayer;
-        protected final DefaultMixedHandler mMixedHandler;
+        protected final MixedTransitionHandler mMixedHandler;
         protected final PipTransitionController mPipHandler;
         protected final StageCoordinator mSplitHandler;
         protected final KeyguardTransitionHandler mKeyguardHandler;
@@ -142,7 +143,7 @@
         int mInFlightSubAnimations = 0;
 
         MixedTransition(int type, IBinder transition, Transitions player,
-                DefaultMixedHandler mixedHandler, PipTransitionController pipHandler,
+                MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
                 StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler) {
             mType = type;
             mTransition = transition;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java
index e9cd73b..b028bd6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java
@@ -41,7 +41,7 @@
     private final ActivityEmbeddingController mActivityEmbeddingController;
 
     DefaultMixedTransition(int type, IBinder transition, Transitions player,
-            DefaultMixedHandler mixedHandler, PipTransitionController pipHandler,
+            MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
             StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler,
             UnfoldTransitionHandler unfoldHandler,
             ActivityEmbeddingController activityEmbeddingController) {
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 74e85f8..2d6ba6e 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
@@ -507,6 +507,15 @@
                 final Point animRelOffset = new Point(
                         change.getEndAbsBounds().left - animRoot.getOffset().x,
                         change.getEndAbsBounds().top - animRoot.getOffset().y);
+
+                if (change.getActivityComponent() != null) {
+                    // For appcompat letterbox: we intentionally report the task-bounds so that we
+                    // can animate as-if letterboxes are "part of" the activity. This means we can't
+                    // always rely solely on endAbsBounds and need to also max with endRelOffset.
+                    animRelOffset.x = Math.max(animRelOffset.x, change.getEndRelOffset().x);
+                    animRelOffset.y = Math.max(animRelOffset.y, change.getEndRelOffset().y);
+                }
+
                 if (change.getActivityComponent() != null && !isActivityLevel) {
                     // At this point, this is an independent activity change in a non-activity
                     // transition. This means that an activity transition got erroneously combined
@@ -585,7 +594,6 @@
                     .setName("animation-background")
                     .setCallsite("DefaultTransitionHandler")
                     .setColorLayer();
-            final SurfaceControl backgroundSurface = colorLayerBuilder.build();
 
             // Attaching the background surface to the transition root could unexpectedly make it
             // cover one of the split root tasks. To avoid this, put the background surface just
@@ -596,8 +604,10 @@
             if (isSplitTaskInvolved) {
                 mRootTDAOrganizer.attachToDisplayArea(displayId, colorLayerBuilder);
             } else {
-                startTransaction.reparent(backgroundSurface, info.getRootLeash());
+                colorLayerBuilder.setParent(info.getRootLeash());
             }
+
+            final SurfaceControl backgroundSurface = colorLayerBuilder.build();
             startTransaction.setColor(backgroundSurface, colorArray)
                     .setLayer(backgroundSurface, -1)
                     .show(backgroundSurface);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
index c9185ae..b1a1e59 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -20,6 +20,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
 
+import static com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
 import static com.android.wm.shell.transition.Transitions.TransitionObserver;
 
 import android.annotation.NonNull;
@@ -60,7 +61,8 @@
             @NonNull SurfaceControl.Transaction finishTransaction) {
         for (TransitionInfo.Change change : info.getChanges()) {
             final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
-            if (taskInfo == null
+            if (info.getType() == TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
+                    || taskInfo == null
                     || taskInfo.displayId != DEFAULT_DISPLAY
                     || taskInfo.taskId == -1
                     || !taskInfo.isRunning) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHandler.java
new file mode 100644
index 0000000..ff429fb
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+/**
+ * Interface for a {@link Transitions.TransitionHandler} that can take the subset of transitions
+ * that it handles and further decompose those transitions into sub-transitions which can be
+ * independently delegated to separate handlers.
+ */
+public interface MixedTransitionHandler extends Transitions.TransitionHandler {
+
+    // TODO(b/335685449) this currently exists purely as a marker interface for use in form-factor
+    // specific/sysui dagger modules. Going forward, we should define this in a meaningful
+    // way so as to provide a clear basis for expectations/behaviours associated with mixed
+    // transitions and their default handlers.
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
index 0974cd1..ffc0b76 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
@@ -44,7 +44,7 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback,
-            @NonNull Transitions player, @NonNull DefaultMixedHandler mixedHandler,
+            @NonNull Transitions player, @NonNull MixedTransitionHandler mixedHandler,
             @NonNull PipTransitionController pipHandler, @NonNull StageCoordinator splitHandler) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animating a mixed transition for "
                 + "entering PIP while Split-Screen is foreground.");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
index 5b402a5..d6e64cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
@@ -43,7 +43,7 @@
     private final DesktopTasksController mDesktopTasksController;
 
     RecentsMixedTransition(int type, IBinder transition, Transitions player,
-            DefaultMixedHandler mixedHandler, PipTransitionController pipHandler,
+            MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
             StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler,
             RecentsTransitionHandler recentsHandler,
             DesktopTasksController desktopTasksController) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
index fa331af..ed4ae05 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
@@ -16,7 +16,10 @@
 
 package com.android.wm.shell.transition.tracing;
 
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellHandlerMapping;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellHandlerMappings;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellTransition;
+import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.tracing.perfetto.DataSourceParams;
@@ -72,11 +75,11 @@
             final int handlerId = getHandlerId(handler);
 
             final ProtoOutputStream os = ctx.newTracePacket();
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, transitionId);
-            os.write(PerfettoTrace.ShellTransition.DISPATCH_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, transitionId);
+            os.write(ShellTransition.DISPATCH_TIME_NS,
                     SystemClock.elapsedRealtimeNanos());
-            os.write(PerfettoTrace.ShellTransition.HANDLER, handlerId);
+            os.write(ShellTransition.HANDLER, handlerId);
             os.end(token);
         });
     }
@@ -117,11 +120,11 @@
     private void doLogMergeRequested(int mergeRequestedTransitionId, int playingTransitionId) {
         mDataSource.trace(ctx -> {
             final ProtoOutputStream os = ctx.newTracePacket();
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, mergeRequestedTransitionId);
-            os.write(PerfettoTrace.ShellTransition.MERGE_REQUEST_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, mergeRequestedTransitionId);
+            os.write(ShellTransition.MERGE_REQUEST_TIME_NS,
                     SystemClock.elapsedRealtimeNanos());
-            os.write(PerfettoTrace.ShellTransition.MERGE_TARGET, playingTransitionId);
+            os.write(ShellTransition.MERGE_TARGET, playingTransitionId);
             os.end(token);
         });
     }
@@ -149,11 +152,11 @@
     private void doLogMerged(int mergeRequestedTransitionId, int playingTransitionId) {
         mDataSource.trace(ctx -> {
             final ProtoOutputStream os = ctx.newTracePacket();
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, mergeRequestedTransitionId);
-            os.write(PerfettoTrace.ShellTransition.MERGE_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, mergeRequestedTransitionId);
+            os.write(ShellTransition.MERGE_TIME_NS,
                     SystemClock.elapsedRealtimeNanos());
-            os.write(PerfettoTrace.ShellTransition.MERGE_TARGET, playingTransitionId);
+            os.write(ShellTransition.MERGE_TARGET, playingTransitionId);
             os.end(token);
         });
     }
@@ -180,9 +183,9 @@
     private void doLogAborted(int transitionId) {
         mDataSource.trace(ctx -> {
             final ProtoOutputStream os = ctx.newTracePacket();
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, transitionId);
-            os.write(PerfettoTrace.ShellTransition.SHELL_ABORT_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, transitionId);
+            os.write(ShellTransition.SHELL_ABORT_TIME_NS,
                     SystemClock.elapsedRealtimeNanos());
             os.end(token);
         });
@@ -196,14 +199,14 @@
         mDataSource.trace(ctx -> {
             final ProtoOutputStream os = ctx.newTracePacket();
 
-            final long mappingsToken = os.start(PerfettoTrace.TracePacket.SHELL_HANDLER_MAPPINGS);
+            final long mappingsToken = os.start(TracePacket.SHELL_HANDLER_MAPPINGS);
             for (Map.Entry<String, Integer> entry : mHandlerMapping.entrySet()) {
                 final String handler = entry.getKey();
                 final int handlerId = entry.getValue();
 
-                final long mappingEntryToken = os.start(PerfettoTrace.ShellHandlerMappings.MAPPING);
-                os.write(PerfettoTrace.ShellHandlerMapping.ID, handlerId);
-                os.write(PerfettoTrace.ShellHandlerMapping.NAME, handler);
+                final long mappingEntryToken = os.start(ShellHandlerMappings.MAPPING);
+                os.write(ShellHandlerMapping.ID, handlerId);
+                os.write(ShellHandlerMapping.NAME, handler);
                 os.end(mappingEntryToken);
 
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
index c26604a..7c2ba45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
@@ -293,7 +293,13 @@
     @Override
     public void onFoldStateChanged(boolean isFolded) {
         if (isFolded) {
+            // Reset unfold animation finished flag on folding, so it could be used next time
+            // when we unfold the device as an indication that animation hasn't finished yet
             mAnimationFinished = false;
+
+            // If we are currently animating unfold animation we should finish it because
+            // the animation might not start and finish as the device was folded
+            finishTransitionIfNeeded();
         }
     }
 
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 c59a1b4..87dc391 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
@@ -19,23 +19,30 @@
 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.content.pm.PackageManager.FEATURE_PC;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 
 import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.provider.Settings;
 import android.util.SparseArray;
 import android.view.Choreographer;
+import android.view.Display;
 import android.view.MotionEvent;
 import android.view.SurfaceControl;
 import android.view.View;
+import android.window.DisplayAreaInfo;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.Nullable;
 
 import com.android.wm.shell.R;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.SyncTransactionQueue;
@@ -53,6 +60,7 @@
     private final Handler mMainHandler;
     private final Choreographer mMainChoreographer;
     private final DisplayController mDisplayController;
+    private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
     private final SyncTransactionQueue mSyncQueue;
     private final Transitions mTransitions;
     private TaskOperations mTaskOperations;
@@ -65,6 +73,7 @@
             Choreographer mainChoreographer,
             ShellTaskOrganizer taskOrganizer,
             DisplayController displayController,
+            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
             SyncTransactionQueue syncQueue,
             Transitions transitions) {
         mContext = context;
@@ -72,6 +81,7 @@
         mMainChoreographer = mainChoreographer;
         mTaskOrganizer = taskOrganizer;
         mDisplayController = displayController;
+        mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
         mSyncQueue = syncQueue;
         mTransitions = transitions;
         if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -158,10 +168,33 @@
     }
 
     private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
-        return taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
-                || (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
-                && taskInfo.configuration.windowConfiguration.getDisplayWindowingMode()
-                == WINDOWING_MODE_FREEFORM);
+        if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+            return true;
+        }
+        if (taskInfo.getActivityType() != ACTIVITY_TYPE_STANDARD) {
+            return false;
+        }
+        final DisplayAreaInfo rootDisplayAreaInfo =
+                mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(taskInfo.displayId);
+        if (rootDisplayAreaInfo != null) {
+            return rootDisplayAreaInfo.configuration.windowConfiguration.getWindowingMode()
+                    == WINDOWING_MODE_FREEFORM;
+        }
+
+        // It is possible that the rootDisplayAreaInfo is null when a task appears soon enough after
+        // a new display shows up, because TDA may appear after task appears in WM shell. Instead of
+        // fixing the synchronization issues, let's use other signals to "guess" the answer. It is
+        // OK in this context because no other captions other than the legacy developer option
+        // freeform and Kingyo/CF PC may use this class. WM shell should have full control over the
+        // condition where captions should show up in all new cases such as desktop mode, for which
+        // we should use different window decor view models. Ultimately Kingyo/CF PC may need to
+        // spin up their own window decor view model when they start to care about multiple
+        // displays.
+        if (isPc()) {
+            return true;
+        }
+        return taskInfo.displayId != Display.DEFAULT_DISPLAY
+                && forcesDesktopModeOnExternalDisplays();
     }
 
     private void createWindowDecoration(
@@ -231,7 +264,10 @@
                 mTaskOperations.minimizeTask(mTaskToken);
             } else if (id == R.id.maximize_window) {
                 RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
-                mTaskOperations.maximizeTask(taskInfo);
+                final DisplayAreaInfo rootDisplayAreaInfo =
+                        mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(taskInfo.displayId);
+                mTaskOperations.maximizeTask(taskInfo,
+                        rootDisplayAreaInfo.configuration.windowConfiguration.getWindowingMode());
             }
         }
 
@@ -305,4 +341,17 @@
             return true;
         }
     }
+
+    /**
+     * Returns if this device is a PC.
+     */
+    private boolean isPc() {
+        return mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
+    }
+
+    private boolean forcesDesktopModeOnExternalDisplays() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        return Settings.Global.getInt(resolver,
+                DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
+    }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index beead6a..43fd32b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -16,17 +16,23 @@
 
 package com.android.wm.shell.windowdecor;
 
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize;
+
 import android.annotation.NonNull;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration;
 import android.app.WindowConfiguration.WindowingMode;
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.VectorDrawable;
 import android.os.Handler;
+import android.util.Size;
 import android.view.Choreographer;
 import android.view.SurfaceControl;
 import android.view.View;
@@ -222,7 +228,6 @@
                     mHandler,
                     mChoreographer,
                     mDisplay.getDisplayId(),
-                    0 /* taskCornerRadius */,
                     mDecorationContainerSurface,
                     mDragPositioningCallback,
                     mSurfaceControlBuilderSupplier,
@@ -234,12 +239,10 @@
                 .getScaledTouchSlop();
         mDragDetector.setTouchSlop(touchSlop);
 
-        final int resize_handle = mResult.mRootView.getResources()
-                .getDimensionPixelSize(R.dimen.freeform_resize_handle);
-        final int resize_corner = mResult.mRootView.getResources()
-                .getDimensionPixelSize(R.dimen.freeform_resize_corner);
-        mDragResizeListener.setGeometry(
-                mResult.mWidth, mResult.mHeight, resize_handle, resize_corner, touchSlop);
+        final Resources res = mResult.mRootView.getResources();
+        mDragResizeListener.setGeometry(new DragResizeWindowGeometry(0 /* taskCornerRadius */,
+                new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(res),
+                getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop);
     }
 
     /**
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 a0f9c6b..6a9d17f 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
@@ -84,6 +84,7 @@
 import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
+import com.android.wm.shell.desktopmode.DesktopWallpaperActivity;
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
 import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.splitscreen.SplitScreen.StageType;
@@ -407,7 +408,9 @@
                     mSplitScreenController.moveTaskToFullscreen(getOtherSplitTask(mTaskId).taskId,
                             SplitScreenController.EXIT_REASON_DESKTOP_MODE);
                 } else {
-                    mTaskOperations.closeTask(mTaskToken);
+                    WindowContainerTransaction wct = new WindowContainerTransaction();
+                    mDesktopTasksController.onDesktopWindowClose(wct, mTaskId);
+                    mTaskOperations.closeTask(mTaskToken, wct);
                 }
             } else if (id == R.id.back_button) {
                 mTaskOperations.injectBackKey();
@@ -858,10 +861,7 @@
                         // as it likely will change.
                         relevantDecor.updateHoverAndPressStatus(ev);
                         mDesktopTasksController.onDragPositioningEndThroughStatusBar(
-                                new PointF(ev.getRawX(), ev.getRawY()),
-                                relevantDecor.mTaskInfo,
-                                calculateFreeformBounds(ev.getDisplayId(),
-                                        DesktopTasksController.DESKTOP_MODE_INITIAL_BOUNDS_SCALE));
+                                new PointF(ev.getRawX(), ev.getRawY()), relevantDecor.mTaskInfo);
                         mMoveToDesktopAnimator = null;
                         return;
                     } else {
@@ -913,23 +913,6 @@
         }
     }
 
-    /**
-     * Gets bounds of a scaled window centered relative to the screen bounds
-     * @param scale the amount to scale to relative to the Screen Bounds
-     */
-    private Rect calculateFreeformBounds(int displayId, float scale) {
-        // TODO(b/319819547): Account for app constraints so apps do not become letterboxed
-        final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId);
-        final int screenWidth = displayLayout.width();
-        final int screenHeight = displayLayout.height();
-
-        final float adjustmentPercentage = (1f - scale) / 2;
-        return new Rect((int) (screenWidth * adjustmentPercentage),
-                (int) (screenHeight * adjustmentPercentage),
-                (int) (screenWidth * (adjustmentPercentage + scale)),
-                (int) (screenHeight * (adjustmentPercentage + scale)));
-    }
-
     @Nullable
     private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
         final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
@@ -1025,6 +1008,7 @@
             return false;
         }
         return DesktopModeStatus.isEnabled()
+                && !DesktopWallpaperActivity.isWallpaperTask(taskInfo)
                 && taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED
                 && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
                 && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop()
@@ -1198,7 +1182,9 @@
                 final boolean inImmersiveMode = !source.isVisible();
                 // Calls WindowDecoration#relayout if decoration visibility needs to be updated
                 if (inImmersiveMode != mInImmersiveMode) {
-                    decor.relayout(decor.mTaskInfo);
+                    if (Flags.enableDesktopWindowingImmersiveHandleHiding()) {
+                        decor.relayout(decor.mTaskInfo);
+                    }
                     mInImmersiveMode = inImmersiveMode;
                 }
 
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 f790d2a..da1699cd 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
@@ -19,15 +19,20 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.windowingModeToString;
+import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
 
 import static com.android.launcher3.icons.BaseIconFactory.MODE_DEFAULT;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.WindowConfiguration.WindowingMode;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
@@ -39,6 +44,8 @@
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.util.Log;
+import android.util.Size;
 import android.view.Choreographer;
 import android.view.MotionEvent;
 import android.view.SurfaceControl;
@@ -273,7 +280,6 @@
                     mHandler,
                     mChoreographer,
                     mDisplay.getDisplayId(),
-                    mRelayoutParams.mCornerRadius,
                     mDecorationContainerSurface,
                     mDragPositioningCallback,
                     mSurfaceControlBuilderSupplier,
@@ -285,15 +291,13 @@
                 .getScaledTouchSlop();
         mDragDetector.setTouchSlop(touchSlop);
 
-        final int resize_handle = mResult.mRootView.getResources()
-                .getDimensionPixelSize(R.dimen.freeform_resize_handle);
-        final int resize_corner = mResult.mRootView.getResources()
-                .getDimensionPixelSize(R.dimen.freeform_resize_corner);
-
         // If either task geometry or position have changed, update this task's
         // exclusion region listener
+        final Resources res = mResult.mRootView.getResources();
         if (mDragResizeListener.setGeometry(
-                mResult.mWidth, mResult.mHeight, resize_handle, resize_corner, touchSlop)
+                new DragResizeWindowGeometry(mRelayoutParams.mCornerRadius,
+                        new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(res),
+                        getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop)
                 || !mTaskInfo.positionInParent.equals(mPositionInParent)) {
             updateExclusionRegion();
         }
@@ -424,8 +428,8 @@
         return mHandleMenu != null;
     }
 
-    boolean shouldResizeListenerHandleEvent(MotionEvent e, Point offset) {
-        return mDragResizeListener.shouldHandleEvent(e, offset);
+    boolean shouldResizeListenerHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) {
+        return mDragResizeListener != null && mDragResizeListener.shouldHandleEvent(e, offset);
     }
 
     boolean isHandlingDragResize() {
@@ -433,15 +437,20 @@
     }
 
     private void loadAppInfo() {
+        final ActivityInfo activityInfo = mTaskInfo.topActivityInfo;
+        if (activityInfo == null) {
+            Log.e(TAG, "Top activity info not found in task");
+            return;
+        }
         PackageManager pm = mContext.getApplicationContext().getPackageManager();
         final IconProvider provider = new IconProvider(mContext);
-        mAppIconDrawable = provider.getIcon(mTaskInfo.topActivityInfo);
+        mAppIconDrawable = provider.getIcon(activityInfo);
         final Resources resources = mContext.getResources();
         final BaseIconFactory factory = new BaseIconFactory(mContext,
                 resources.getDisplayMetrics().densityDpi,
                 resources.getDimensionPixelSize(R.dimen.desktop_mode_caption_icon_radius));
         mAppIconBitmap = factory.createScaledBitmap(mAppIconDrawable, MODE_DEFAULT);
-        final ApplicationInfo applicationInfo = mTaskInfo.topActivityInfo.applicationInfo;
+        final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
         mAppName = pm.getApplicationLabel(applicationInfo);
     }
 
@@ -458,8 +467,8 @@
      * until a resize event calls showResizeVeil below.
      */
     void createResizeVeil() {
-        mResizeVeil = new ResizeVeil(mContext, mAppIconDrawable, mTaskInfo, mTaskSurface,
-                mSurfaceControlBuilderSupplier, mDisplay, mSurfaceControlTransactionSupplier);
+        mResizeVeil = new ResizeVeil(mContext, mDisplayController, mAppIconDrawable, mTaskInfo,
+                mTaskSurface, mSurfaceControlTransactionSupplier);
     }
 
     /**
@@ -752,7 +761,9 @@
         final int action = ev.getActionMasked();
         // The comparison against ACTION_UP is needed for the cancel drag to desktop case.
         handle.setHovered(inHandle && action != ACTION_UP);
-        handle.setPressed(inHandle && action == ACTION_DOWN);
+        // We want handle to remain pressed if the pointer moves outside of it during a drag.
+        handle.setPressed((inHandle && action == ACTION_DOWN)
+                || (handle.isPressed() && action != ACTION_UP && action != ACTION_CANCEL));
         if (isHandleMenuActive()) {
             mHandleMenu.checkMotionEvent(ev);
         }
@@ -795,7 +806,7 @@
      */
     private Region getGlobalExclusionRegion() {
         Region exclusionRegion;
-        if (mTaskInfo.isResizeable) {
+        if (mDragResizeListener != null && mTaskInfo.isResizeable) {
             exclusionRegion = mDragResizeListener.getCornersRegion();
         } else {
             exclusionRegion = new Region();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
index 8ce2d6d..421ffd9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
@@ -23,6 +23,9 @@
  * Callback called when receiving drag-resize or drag-move related input events.
  */
 public interface DragPositioningCallback {
+    /**
+     * Indicates the direction of resizing. May be combined together to indicate a diagonal drag.
+     */
     @IntDef(flag = true, value = {
             CTRL_TYPE_UNDEFINED, CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT, CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM
     })
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 97eb4a4..9624d46 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -30,6 +30,7 @@
 import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
 import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -39,6 +40,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.Size;
 import android.view.Choreographer;
 import android.view.IWindowSession;
 import android.view.InputChannel;
@@ -55,6 +57,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 /**
@@ -66,40 +69,20 @@
 class DragResizeInputListener implements AutoCloseable {
     private static final String TAG = "DragResizeInputListener";
     private final IWindowSession mWindowSession = WindowManagerGlobal.getWindowSession();
-    private final Context mContext;
-    private final Handler mHandler;
-    private final Choreographer mChoreographer;
-    private final InputManager mInputManager;
     private final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier;
 
     private final int mDisplayId;
 
     private final IBinder mClientToken;
 
-    private final InputTransferToken mInputTransferToken;
     private final SurfaceControl mDecorationSurface;
     private final InputChannel mInputChannel;
     private final TaskResizeInputEventReceiver mInputEventReceiver;
-    private final DragPositioningCallback mCallback;
 
     private final SurfaceControl mInputSinkSurface;
     private final IBinder mSinkClientToken;
     private final InputChannel mSinkInputChannel;
     private final DisplayController mDisplayController;
-
-    private int mTaskWidth;
-    private int mTaskHeight;
-    private int mResizeHandleThickness;
-    private int mCornerSize;
-    private int mTaskCornerRadius;
-
-    private Rect mLeftTopCornerBounds;
-    private Rect mRightTopCornerBounds;
-    private Rect mLeftBottomCornerBounds;
-    private Rect mRightBottomCornerBounds;
-
-    private int mDragPointerId = -1;
-    private DragDetector mDragDetector;
     private final Region mTouchRegion = new Region();
 
     DragResizeInputListener(
@@ -107,23 +90,17 @@
             Handler handler,
             Choreographer choreographer,
             int displayId,
-            int taskCornerRadius,
             SurfaceControl decorationSurface,
             DragPositioningCallback callback,
             Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
             DisplayController displayController) {
-        mInputManager = context.getSystemService(InputManager.class);
-        mContext = context;
-        mHandler = handler;
-        mChoreographer = choreographer;
         mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
         mDisplayId = displayId;
-        mTaskCornerRadius = taskCornerRadius;
         mDecorationSurface = decorationSurface;
         mDisplayController = displayController;
         mClientToken = new Binder();
-        mInputTransferToken = new InputTransferToken();
+        final InputTransferToken inputTransferToken = new InputTransferToken();
         mInputChannel = new InputChannel();
         try {
             mWindowSession.grantInputChannel(
@@ -136,18 +113,19 @@
                     INPUT_FEATURE_SPY,
                     TYPE_APPLICATION,
                     null /* windowToken */,
-                    mInputTransferToken,
+                    inputTransferToken,
                     TAG + " of " + decorationSurface.toString(),
                     mInputChannel);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
 
-        mInputEventReceiver = new TaskResizeInputEventReceiver(
-                mInputChannel, mHandler, mChoreographer);
-        mCallback = callback;
-        mDragDetector = new DragDetector(mInputEventReceiver);
-        mDragDetector.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
+        mInputEventReceiver = new TaskResizeInputEventReceiver(context, mInputChannel, callback,
+                handler, choreographer, () -> {
+            final DisplayLayout layout = mDisplayController.getDisplayLayout(mDisplayId);
+            return new Size(layout.width(), layout.height());
+        }, this::updateSinkInputChannel);
+        mInputEventReceiver.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
 
         mInputSinkSurface = surfaceControlBuilderSupplier.get()
                 .setName("TaskInputSink of " + decorationSurface)
@@ -171,7 +149,7 @@
                     INPUT_FEATURE_NO_INPUT_CHANNEL,
                     TYPE_INPUT_CONSUMER,
                     null /* windowToken */,
-                    mInputTransferToken,
+                    inputTransferToken,
                     "TaskInputSink of " + decorationSurface,
                     mSinkInputChannel);
         } catch (RemoteException e) {
@@ -182,86 +160,26 @@
     /**
      * Updates the geometry (the touch region) of this drag resize handler.
      *
-     * @param taskWidth The width of the task.
-     * @param taskHeight The height of the task.
-     * @param resizeHandleThickness The thickness of the resize handle in pixels.
-     * @param cornerSize The size of the resize handle centered in each corner.
-     * @param touchSlop The distance in pixels user has to drag with touch for it to register as
-     *                  a resize action.
+     * @param incomingGeometry The geometry update to apply for this task's drag resize regions.
+     * @param touchSlop        The distance in pixels user has to drag with touch for it to register
+     *                         as a resize action.
      * @return whether the geometry has changed or not
      */
-    boolean setGeometry(int taskWidth, int taskHeight, int resizeHandleThickness, int cornerSize,
-            int touchSlop) {
-        if (mTaskWidth == taskWidth && mTaskHeight == taskHeight
-                && mResizeHandleThickness == resizeHandleThickness
-                && mCornerSize == cornerSize) {
+    boolean setGeometry(@NonNull DragResizeWindowGeometry incomingGeometry, int touchSlop) {
+        DragResizeWindowGeometry geometry = mInputEventReceiver.getGeometry();
+        if (incomingGeometry.equals(geometry)) {
+            // Geometry hasn't changed size so skip all updates.
             return false;
+        } else {
+            geometry = incomingGeometry;
         }
-
-        mTaskWidth = taskWidth;
-        mTaskHeight = taskHeight;
-        mResizeHandleThickness = resizeHandleThickness;
-        mCornerSize = cornerSize;
-        mDragDetector.setTouchSlop(touchSlop);
+        mInputEventReceiver.setTouchSlop(touchSlop);
 
         mTouchRegion.setEmpty();
-        final Rect topInputBounds = new Rect(
-                -mResizeHandleThickness,
-                -mResizeHandleThickness,
-                mTaskWidth + mResizeHandleThickness,
-                0);
-        mTouchRegion.union(topInputBounds);
-
-        final Rect leftInputBounds = new Rect(
-                -mResizeHandleThickness,
-                0,
-                0,
-                mTaskHeight);
-        mTouchRegion.union(leftInputBounds);
-
-        final Rect rightInputBounds = new Rect(
-                mTaskWidth,
-                0,
-                mTaskWidth + mResizeHandleThickness,
-                mTaskHeight);
-        mTouchRegion.union(rightInputBounds);
-
-        final Rect bottomInputBounds = new Rect(
-                -mResizeHandleThickness,
-                mTaskHeight,
-                mTaskWidth + mResizeHandleThickness,
-                mTaskHeight + mResizeHandleThickness);
-        mTouchRegion.union(bottomInputBounds);
-
-        // Set up touch areas in each corner.
-        int cornerRadius = mCornerSize / 2;
-        mLeftTopCornerBounds = new Rect(
-                -cornerRadius,
-                -cornerRadius,
-                cornerRadius,
-                cornerRadius);
-        mTouchRegion.union(mLeftTopCornerBounds);
-
-        mRightTopCornerBounds = new Rect(
-                mTaskWidth - cornerRadius,
-                -cornerRadius,
-                mTaskWidth + cornerRadius,
-                cornerRadius);
-        mTouchRegion.union(mRightTopCornerBounds);
-
-        mLeftBottomCornerBounds = new Rect(
-                -cornerRadius,
-                mTaskHeight - cornerRadius,
-                cornerRadius,
-                mTaskHeight + cornerRadius);
-        mTouchRegion.union(mLeftBottomCornerBounds);
-
-        mRightBottomCornerBounds = new Rect(
-                mTaskWidth - cornerRadius,
-                mTaskHeight - cornerRadius,
-                mTaskWidth + cornerRadius,
-                mTaskHeight + cornerRadius);
-        mTouchRegion.union(mRightBottomCornerBounds);
+        // Apply the geometry to the touch region.
+        geometry.union(mTouchRegion);
+        mInputEventReceiver.setGeometry(geometry);
+        mInputEventReceiver.setTouchRegion(mTouchRegion);
 
         try {
             mWindowSession.updateInputChannel(
@@ -276,8 +194,9 @@
             e.rethrowFromSystemServer();
         }
 
+        final Size taskSize = geometry.getTaskSize();
         mSurfaceControlTransactionSupplier.get()
-                .setWindowCrop(mInputSinkSurface, mTaskWidth, mTaskHeight)
+                .setWindowCrop(mInputSinkSurface, taskSize.getWidth(), taskSize.getHeight())
                 .apply();
         // The touch region of the TaskInputSink should be the touch region of this
         // DragResizeInputHandler minus the task bounds. Pilfering events isn't enough to prevent
@@ -290,21 +209,16 @@
         // issue. However, were there touchscreen-only a region out of the task bounds, mouse
         // gestures will become no-op in that region, even though the mouse gestures may appear to
         // be performed on the input window behind the resize handle.
-        mTouchRegion.op(0, 0, mTaskWidth, mTaskHeight, Region.Op.DIFFERENCE);
+        mTouchRegion.op(0, 0, taskSize.getWidth(), taskSize.getHeight(), Region.Op.DIFFERENCE);
         updateSinkInputChannel(mTouchRegion);
         return true;
     }
 
     /**
-     * Generate a Region that encapsulates all 4 corner handles
+     * Generate a Region that encapsulates all 4 corner handles and window edges.
      */
-    Region getCornersRegion() {
-        Region region = new Region();
-        region.union(mLeftTopCornerBounds);
-        region.union(mLeftBottomCornerBounds);
-        region.union(mRightTopCornerBounds);
-        region.union(mRightBottomCornerBounds);
-        return region;
+    @NonNull Region getCornersRegion() {
+        return mInputEventReceiver.getCornersRegion();
     }
 
     private void updateSinkInputChannel(Region region) {
@@ -322,7 +236,7 @@
         }
     }
 
-    boolean shouldHandleEvent(MotionEvent e, Point offset) {
+    boolean shouldHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) {
         return mInputEventReceiver.shouldHandleEvent(e, offset);
     }
 
@@ -351,19 +265,37 @@
                 .apply();
     }
 
-    private class TaskResizeInputEventReceiver extends InputEventReceiver
-            implements DragDetector.MotionEventHandler {
-        private final Choreographer mChoreographer;
-        private final Runnable mConsumeBatchEventRunnable;
+    private static class TaskResizeInputEventReceiver extends InputEventReceiver implements
+            DragDetector.MotionEventHandler {
+        @NonNull private final Context mContext;
+        private final InputManager mInputManager;
+        @NonNull private final InputChannel mInputChannel;
+        @NonNull private final DragPositioningCallback mCallback;
+        @NonNull private final Choreographer mChoreographer;
+        @NonNull private final Runnable mConsumeBatchEventRunnable;
+        @NonNull private final DragDetector mDragDetector;
+        @NonNull private final Supplier<Size> mDisplayLayoutSizeSupplier;
+        @NonNull private final Consumer<Region> mTouchRegionConsumer;
+        private final Rect mTmpRect = new Rect();
         private boolean mConsumeBatchEventScheduled;
+        private DragResizeWindowGeometry mDragResizeWindowGeometry;
+        private Region mTouchRegion;
         private boolean mShouldHandleEvents;
         private int mLastCursorType = PointerIcon.TYPE_DEFAULT;
         private Rect mDragStartTaskBounds;
-        private final Rect mTmpRect = new Rect();
+        private int mDragPointerId = -1;
 
-        private TaskResizeInputEventReceiver(
-                InputChannel inputChannel, Handler handler, Choreographer choreographer) {
+        private TaskResizeInputEventReceiver(@NonNull Context context,
+                @NonNull InputChannel inputChannel,
+                @NonNull DragPositioningCallback callback, @NonNull Handler handler,
+                @NonNull Choreographer choreographer,
+                @NonNull Supplier<Size> displayLayoutSizeSupplier,
+                @NonNull Consumer<Region> touchRegionConsumer) {
             super(inputChannel, handler.getLooper());
+            mContext = context;
+            mInputManager = context.getSystemService(InputManager.class);
+            mInputChannel = inputChannel;
+            mCallback = callback;
             mChoreographer = choreographer;
 
             mConsumeBatchEventRunnable = () -> {
@@ -376,6 +308,48 @@
                     scheduleConsumeBatchEvent();
                 }
             };
+
+            mDragDetector = new DragDetector(this);
+            mDisplayLayoutSizeSupplier = displayLayoutSizeSupplier;
+            mTouchRegionConsumer = touchRegionConsumer;
+        }
+
+        /**
+         * Returns the geometry of the areas to drag resize.
+         */
+        DragResizeWindowGeometry getGeometry() {
+            return mDragResizeWindowGeometry;
+        }
+
+        /**
+         * Updates the geometry of the areas to drag resize.
+         */
+        void setGeometry(@NonNull DragResizeWindowGeometry dragResizeWindowGeometry) {
+            mDragResizeWindowGeometry = dragResizeWindowGeometry;
+        }
+
+        /**
+         * Sets how much slop to allow for touches.
+         */
+        void setTouchSlop(int touchSlop) {
+            mDragDetector.setTouchSlop(touchSlop);
+        }
+
+        /**
+         * Updates the region accepting input for drag resizing the task.
+         */
+        void setTouchRegion(@NonNull Region touchRegion) {
+            mTouchRegion = touchRegion;
+        }
+
+        /**
+         * Returns the union of all regions that can be touched for drag resizing; the corners and
+         * window edges.
+         */
+        @NonNull Region getCornersRegion() {
+            Region region = new Region();
+            mDragResizeWindowGeometry.union(region);
+            return region;
         }
 
         @Override
@@ -416,14 +390,15 @@
             boolean isTouch = isTouchEvent(e);
             switch (e.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN: {
-                    mShouldHandleEvents = shouldHandleEvent(e, isTouch, new Point() /* offset */);
+                    mShouldHandleEvents = mDragResizeWindowGeometry.shouldHandleEvent(e, isTouch,
+                            new Point() /* offset */);
                     if (mShouldHandleEvents) {
                         mDragPointerId = e.getPointerId(0);
                         float x = e.getX(0);
                         float y = e.getY(0);
                         float rawX = e.getRawX(0);
                         float rawY = e.getRawY(0);
-                        int ctrlType = calculateCtrlType(isTouch, x, y);
+                        int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(isTouch, x, y);
                         mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
                                 rawX, rawY);
                         // Increase the input sink region to cover the whole screen; this is to
@@ -455,7 +430,7 @@
                         // If taskBounds has changed, setGeometry will be called and update the
                         // sink region. Otherwise, we should revert it here.
                         if (taskBounds.equals(mDragStartTaskBounds)) {
-                            updateSinkInputChannel(mTouchRegion);
+                            mTouchRegionConsumer.accept(mTouchRegion);
                         }
                     }
                     mShouldHandleEvents = false;
@@ -480,125 +455,20 @@
 
         private void updateInputSinkRegionForDrag(Rect taskBounds) {
             mTmpRect.set(taskBounds);
-            final DisplayLayout layout = mDisplayController.getDisplayLayout(mDisplayId);
-            final Region dragTouchRegion = new Region(-taskBounds.left,
-                    -taskBounds.top,
-                    -taskBounds.left + layout.width(),
-                    -taskBounds.top + layout.height());
+            final Size displayLayoutSize = mDisplayLayoutSizeSupplier.get();
+            final Region dragTouchRegion = new Region(-taskBounds.left, -taskBounds.top,
+                    -taskBounds.left + displayLayoutSize.getWidth(),
+                    -taskBounds.top + displayLayoutSize.getHeight());
             // Remove the localized task bounds from the touch region.
             mTmpRect.offsetTo(0, 0);
             dragTouchRegion.op(mTmpRect, Region.Op.DIFFERENCE);
-            updateSinkInputChannel(dragTouchRegion);
-        }
-
-        private boolean isInCornerBounds(float xf, float yf) {
-            return calculateCornersCtrlType(xf, yf) != 0;
-        }
-
-        private boolean isInResizeHandleBounds(float x, float y) {
-            return calculateResizeHandlesCtrlType(x, y) != 0;
-        }
-
-        @DragPositioningCallback.CtrlType
-        private int calculateCtrlType(boolean isTouch, float x, float y) {
-            if (isTouch) {
-                return calculateCornersCtrlType(x, y);
-            }
-            return calculateResizeHandlesCtrlType(x, y);
-        }
-
-        @DragPositioningCallback.CtrlType
-        private int calculateResizeHandlesCtrlType(float x, float y) {
-            int ctrlType = 0;
-            // mTaskCornerRadius is only used in comparing with corner regions. Comparisons with
-            // sides will use the bounds specified in setGeometry and not go into task bounds.
-            if (x < mTaskCornerRadius) {
-                ctrlType |= CTRL_TYPE_LEFT;
-            }
-            if (x > mTaskWidth - mTaskCornerRadius) {
-                ctrlType |= CTRL_TYPE_RIGHT;
-            }
-            if (y < mTaskCornerRadius) {
-                ctrlType |= CTRL_TYPE_TOP;
-            }
-            if (y > mTaskHeight - mTaskCornerRadius) {
-                ctrlType |= CTRL_TYPE_BOTTOM;
-            }
-            // Check distances from the center if it's in one of four corners.
-            if ((ctrlType & (CTRL_TYPE_LEFT | CTRL_TYPE_RIGHT)) != 0
-                    && (ctrlType & (CTRL_TYPE_TOP | CTRL_TYPE_BOTTOM)) != 0) {
-                return checkDistanceFromCenter(ctrlType, x, y);
-            }
-            // Otherwise, we should make sure we don't resize tasks inside task bounds.
-            return (x < 0 || y < 0 || x >= mTaskWidth || y >= mTaskHeight) ? ctrlType : 0;
-        }
-
-        // If corner input is not within appropriate distance of corner radius, do not use it.
-        // If input is not on a corner or is within valid distance, return ctrlType.
-        @DragPositioningCallback.CtrlType
-        private int checkDistanceFromCenter(@DragPositioningCallback.CtrlType int ctrlType,
-                float x, float y) {
-            int centerX;
-            int centerY;
-
-            // Determine center of rounded corner circle; this is simply the corner if radius is 0.
-            switch (ctrlType) {
-                case CTRL_TYPE_LEFT | CTRL_TYPE_TOP: {
-                    centerX = mTaskCornerRadius;
-                    centerY = mTaskCornerRadius;
-                    break;
-                }
-                case CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM: {
-                    centerX = mTaskCornerRadius;
-                    centerY = mTaskHeight - mTaskCornerRadius;
-                    break;
-                }
-                case CTRL_TYPE_RIGHT | CTRL_TYPE_TOP: {
-                    centerX = mTaskWidth - mTaskCornerRadius;
-                    centerY = mTaskCornerRadius;
-                    break;
-                }
-                case CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM: {
-                    centerX = mTaskWidth - mTaskCornerRadius;
-                    centerY = mTaskHeight - mTaskCornerRadius;
-                    break;
-                }
-                default: {
-                    throw new IllegalArgumentException("ctrlType should be complex, but it's 0x"
-                            + Integer.toHexString(ctrlType));
-                }
-            }
-            double distanceFromCenter = Math.hypot(x - centerX, y - centerY);
-
-            if (distanceFromCenter < mTaskCornerRadius + mResizeHandleThickness
-                    && distanceFromCenter >= mTaskCornerRadius) {
-                return ctrlType;
-            }
-            return 0;
-        }
-
-        @DragPositioningCallback.CtrlType
-        private int calculateCornersCtrlType(float x, float y) {
-            int xi = (int) x;
-            int yi = (int) y;
-            if (mLeftTopCornerBounds.contains(xi, yi)) {
-                return CTRL_TYPE_LEFT | CTRL_TYPE_TOP;
-            }
-            if (mLeftBottomCornerBounds.contains(xi, yi)) {
-                return CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM;
-            }
-            if (mRightTopCornerBounds.contains(xi, yi)) {
-                return CTRL_TYPE_RIGHT | CTRL_TYPE_TOP;
-            }
-            if (mRightBottomCornerBounds.contains(xi, yi)) {
-                return CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM;
-            }
-            return 0;
+            mTouchRegionConsumer.accept(dragTouchRegion);
         }
 
         private void updateCursorType(int displayId, int deviceId, int pointerId, float x,
                 float y) {
-            @DragPositioningCallback.CtrlType int ctrlType = calculateResizeHandlesCtrlType(x, y);
+            @DragPositioningCallback.CtrlType int ctrlType =
+                    mDragResizeWindowGeometry.calculateCtrlType(/* isTouch= */ false, x, y);
 
             int cursorType = PointerIcon.TYPE_DEFAULT;
             switch (ctrlType) {
@@ -640,19 +510,7 @@
         }
 
         private boolean shouldHandleEvent(MotionEvent e, Point offset) {
-            return shouldHandleEvent(e, isTouchEvent(e), offset);
-        }
-
-        private boolean shouldHandleEvent(MotionEvent e, boolean isTouch, Point offset) {
-            boolean result;
-            final float x = e.getX(0) + offset.x;
-            final float y = e.getY(0) + offset.y;
-            if (isTouch) {
-                result = isInCornerBounds(x, y);
-            } else {
-                result = isInResizeHandleBounds(x, y);
-            }
-            return result;
+            return mDragResizeWindowGeometry.shouldHandleEvent(e, offset);
         }
 
         private boolean isTouchEvent(MotionEvent e) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
new file mode 100644
index 0000000..eafb569
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+
+import static com.android.window.flags.Flags.enableWindowingEdgeDragResize;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED;
+
+import android.annotation.NonNull;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.Size;
+import android.view.MotionEvent;
+
+import com.android.wm.shell.R;
+
+import java.util.Objects;
+
+/**
+ * Geometry for a drag resize region for a particular window.
+ */
+final class DragResizeWindowGeometry {
+    private final int mTaskCornerRadius;
+    private final Size mTaskSize;
+    // The size of the handle applied to the edges of the window, for the user to drag resize.
+    private final int mResizeHandleThickness;
+    // The task corners to permit drag resizing with a course input, such as touch.
+
+    private final @NonNull TaskCorners mLargeTaskCorners;
+    // The task corners to permit drag resizing with a fine input, such as stylus or cursor.
+    private final @NonNull TaskCorners mFineTaskCorners;
+    // The bounds for each edge drag region, which can resize the task in one direction.
+    private final @NonNull Rect mTopEdgeBounds;
+    private final @NonNull Rect mLeftEdgeBounds;
+    private final @NonNull Rect mRightEdgeBounds;
+    private final @NonNull Rect mBottomEdgeBounds;
+
+    DragResizeWindowGeometry(int taskCornerRadius, @NonNull Size taskSize,
+            int resizeHandleThickness, int fineCornerSize, int largeCornerSize) {
+        mTaskCornerRadius = taskCornerRadius;
+        mTaskSize = taskSize;
+        mResizeHandleThickness = resizeHandleThickness;
+
+        mLargeTaskCorners = new TaskCorners(mTaskSize, largeCornerSize);
+        mFineTaskCorners = new TaskCorners(mTaskSize, fineCornerSize);
+
+        // Save touch areas for each edge.
+        mTopEdgeBounds = new Rect(
+                -mResizeHandleThickness,
+                -mResizeHandleThickness,
+                mTaskSize.getWidth() + mResizeHandleThickness,
+                0);
+        mLeftEdgeBounds = new Rect(
+                -mResizeHandleThickness,
+                0,
+                0,
+                mTaskSize.getHeight());
+        mRightEdgeBounds = new Rect(
+                mTaskSize.getWidth(),
+                0,
+                mTaskSize.getWidth() + mResizeHandleThickness,
+                mTaskSize.getHeight());
+        mBottomEdgeBounds = new Rect(
+                -mResizeHandleThickness,
+                mTaskSize.getHeight(),
+                mTaskSize.getWidth() + mResizeHandleThickness,
+                mTaskSize.getHeight() + mResizeHandleThickness);
+    }
+
+    /**
+     * Returns the resource value to use for the resize handle on the edge of the window.
+     */
+    static int getResizeEdgeHandleSize(@NonNull Resources res) {
+        return enableWindowingEdgeDragResize()
+                ? res.getDimensionPixelSize(R.dimen.desktop_mode_edge_handle)
+                : res.getDimensionPixelSize(R.dimen.freeform_resize_handle);
+    }
+
+    /**
+     * Returns the resource value to use for course input, such as touch, that benefits from a large
+     * square on each of the window's corners.
+     */
+    static int getLargeResizeCornerSize(@NonNull Resources res) {
+        return res.getDimensionPixelSize(R.dimen.desktop_mode_corner_resize_large);
+    }
+
+    /**
+     * Returns the resource value to use for fine input, such as stylus, that can use a smaller
+     * square on each of the window's corners.
+     */
+    static int getFineResizeCornerSize(@NonNull Resources res) {
+        return res.getDimensionPixelSize(R.dimen.freeform_resize_corner);
+    }
+
+    /**
+     * Returns the size of the task this geometry is calculated for.
+     */
+    @NonNull Size getTaskSize() {
+        // Safe to return directly since size is immutable.
+        return mTaskSize;
+    }
+
+    /**
+     * Returns the union of all regions that can be touched for drag resizing; the corners window
+     * and window edges.
+     */
+    void union(@NonNull Region region) {
+        // Apply the edge resize regions.
+        region.union(mTopEdgeBounds);
+        region.union(mLeftEdgeBounds);
+        region.union(mRightEdgeBounds);
+        region.union(mBottomEdgeBounds);
+
+        if (enableWindowingEdgeDragResize()) {
+            // Apply the corners as well for the larger corners, to ensure we capture all possible
+            // touches.
+            mLargeTaskCorners.union(region);
+        } else {
+            // Only apply fine corners for the legacy approach.
+            mFineTaskCorners.union(region);
+        }
+    }
+
+    /**
+     * Returns if this MotionEvent should be handled, based on its source and position.
+     */
+    boolean shouldHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) {
+        return shouldHandleEvent(e, isTouchEvent(e), offset);
+    }
+
+    /**
+     * Returns if this MotionEvent should be handled, based on its source and position.
+     */
+    boolean shouldHandleEvent(@NonNull MotionEvent e, boolean isTouch, @NonNull Point offset) {
+        final float x = e.getX(0) + offset.x;
+        final float y = e.getY(0) + offset.y;
+
+        if (enableWindowingEdgeDragResize()) {
+            // First check if touch falls within a corner.
+            // Large corner bounds are used for course input like touch, otherwise fine bounds.
+            boolean result = isTouch
+                    ? isInCornerBounds(mLargeTaskCorners, x, y)
+                    : isInCornerBounds(mFineTaskCorners, x, y);
+            // Check if touch falls within the edge resize handle, since edge resizing can apply
+            // for any input source.
+            if (!result) {
+                result = isInEdgeResizeBounds(x, y);
+            }
+            return result;
+        } else {
+            // Legacy uses only fine corners for touch, and edges only for non-touch input.
+            return isTouch
+                    ? isInCornerBounds(mFineTaskCorners, x, y)
+                    : isInEdgeResizeBounds(x, y);
+        }
+    }
+
+    private boolean isTouchEvent(@NonNull MotionEvent e) {
+        return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
+    }
+
+    private boolean isInCornerBounds(TaskCorners corners, float xf, float yf) {
+        return corners.calculateCornersCtrlType(xf, yf) != 0;
+    }
+
+    private boolean isInEdgeResizeBounds(float x, float y) {
+        return calculateEdgeResizeCtrlType(x, y) != 0;
+    }
+
+    /**
+     * Returns the control type for the drag-resize, based on the touch regions and this
+     * MotionEvent's coordinates.
+     */
+    @DragPositioningCallback.CtrlType
+    int calculateCtrlType(boolean isTouch, float x, float y) {
+        if (enableWindowingEdgeDragResize()) {
+            // First check if touch falls within a corner.
+            // Large corner bounds are used for course input like touch, otherwise fine bounds.
+            int ctrlType = isTouch
+                    ? mLargeTaskCorners.calculateCornersCtrlType(x, y)
+                    : mFineTaskCorners.calculateCornersCtrlType(x, y);
+            // Check if touch falls within the edge resize handle, since edge resizing can apply
+            // for any input source.
+            if (ctrlType == CTRL_TYPE_UNDEFINED) {
+                ctrlType = calculateEdgeResizeCtrlType(x, y);
+            }
+            return ctrlType;
+        } else {
+            // Legacy uses only fine corners for touch, and edges only for non-touch input.
+            return isTouch
+                    ? mFineTaskCorners.calculateCornersCtrlType(x, y)
+                    : calculateEdgeResizeCtrlType(x, y);
+        }
+    }
+
+    @DragPositioningCallback.CtrlType
+    private int calculateEdgeResizeCtrlType(float x, float y) {
+        int ctrlType = CTRL_TYPE_UNDEFINED;
+        // mTaskCornerRadius is only used in comparing with corner regions. Comparisons with
+        // sides will use the bounds specified in setGeometry and not go into task bounds.
+        if (x < mTaskCornerRadius) {
+            ctrlType |= CTRL_TYPE_LEFT;
+        }
+        if (x > mTaskSize.getWidth() - mTaskCornerRadius) {
+            ctrlType |= CTRL_TYPE_RIGHT;
+        }
+        if (y < mTaskCornerRadius) {
+            ctrlType |= CTRL_TYPE_TOP;
+        }
+        if (y > mTaskSize.getHeight() - mTaskCornerRadius) {
+            ctrlType |= CTRL_TYPE_BOTTOM;
+        }
+        // If the touch is within one of the four corners, check if it is within the bounds of the
+        // // handle.
+        if ((ctrlType & (CTRL_TYPE_LEFT | CTRL_TYPE_RIGHT)) != 0
+                && (ctrlType & (CTRL_TYPE_TOP | CTRL_TYPE_BOTTOM)) != 0) {
+            return checkDistanceFromCenter(ctrlType, x, y);
+        }
+        // Otherwise, we should make sure we don't resize tasks inside task bounds.
+        return (x < 0 || y < 0 || x >= mTaskSize.getWidth() || y >= mTaskSize.getHeight())
+                ? ctrlType : CTRL_TYPE_UNDEFINED;
+    }
+
+    /**
+     * Return {@code ctrlType} if the corner input is outside the (potentially rounded) corner of
+     * the task, and within the thickness of the resize handle. Otherwise, return 0.
+     */
+    @DragPositioningCallback.CtrlType
+    private int checkDistanceFromCenter(@DragPositioningCallback.CtrlType int ctrlType, float x,
+            float y) {
+        final Point cornerRadiusCenter = calculateCenterForCornerRadius(ctrlType);
+        double distanceFromCenter = Math.hypot(x - cornerRadiusCenter.x, y - cornerRadiusCenter.y);
+
+        if (distanceFromCenter < mTaskCornerRadius + mResizeHandleThickness
+                && distanceFromCenter >= mTaskCornerRadius) {
+            return ctrlType;
+        }
+        return CTRL_TYPE_UNDEFINED;
+    }
+
+    /**
+     * Returns center of rounded corner circle; this is simply the corner if radius is 0.
+     */
+    private Point calculateCenterForCornerRadius(@DragPositioningCallback.CtrlType int ctrlType) {
+        int centerX;
+        int centerY;
+
+        switch (ctrlType) {
+            case CTRL_TYPE_LEFT | CTRL_TYPE_TOP: {
+                centerX = mTaskCornerRadius;
+                centerY = mTaskCornerRadius;
+                break;
+            }
+            case CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM: {
+                centerX = mTaskCornerRadius;
+                centerY = mTaskSize.getHeight() - mTaskCornerRadius;
+                break;
+            }
+            case CTRL_TYPE_RIGHT | CTRL_TYPE_TOP: {
+                centerX = mTaskSize.getWidth() - mTaskCornerRadius;
+                centerY = mTaskCornerRadius;
+                break;
+            }
+            case CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM: {
+                centerX = mTaskSize.getWidth() - mTaskCornerRadius;
+                centerY = mTaskSize.getHeight() - mTaskCornerRadius;
+                break;
+            }
+            default: {
+                throw new IllegalArgumentException(
+                        "ctrlType should be complex, but it's 0x" + Integer.toHexString(ctrlType));
+            }
+        }
+        return new Point(centerX, centerY);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) return false;
+        if (this == obj) return true;
+        if (!(obj instanceof DragResizeWindowGeometry other)) return false;
+
+        return this.mTaskCornerRadius == other.mTaskCornerRadius
+                && this.mTaskSize.equals(other.mTaskSize)
+                && this.mResizeHandleThickness == other.mResizeHandleThickness
+                && this.mFineTaskCorners.equals(other.mFineTaskCorners)
+                && this.mLargeTaskCorners.equals(other.mLargeTaskCorners)
+                && this.mTopEdgeBounds.equals(other.mTopEdgeBounds)
+                && this.mLeftEdgeBounds.equals(other.mLeftEdgeBounds)
+                && this.mRightEdgeBounds.equals(other.mRightEdgeBounds)
+                && this.mBottomEdgeBounds.equals(other.mBottomEdgeBounds);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mTaskCornerRadius,
+                mTaskSize,
+                mResizeHandleThickness,
+                mFineTaskCorners,
+                mLargeTaskCorners,
+                mTopEdgeBounds,
+                mLeftEdgeBounds,
+                mRightEdgeBounds,
+                mBottomEdgeBounds);
+    }
+
+    /**
+     * Representation of the drag resize regions at the corner of the window.
+     */
+    private static class TaskCorners {
+        // The size of the square applied to the corners of the window, for the user to drag
+        // resize.
+        private final int mCornerSize;
+        // The square for each corner.
+        private final @NonNull Rect mLeftTopCornerBounds;
+        private final @NonNull Rect mRightTopCornerBounds;
+        private final @NonNull Rect mLeftBottomCornerBounds;
+        private final @NonNull Rect mRightBottomCornerBounds;
+
+        TaskCorners(@NonNull Size taskSize, int cornerSize) {
+            mCornerSize = cornerSize;
+            final int cornerRadius = cornerSize / 2;
+            mLeftTopCornerBounds = new Rect(
+                    -cornerRadius,
+                    -cornerRadius,
+                    cornerRadius,
+                    cornerRadius);
+
+            mRightTopCornerBounds = new Rect(
+                    taskSize.getWidth() - cornerRadius,
+                    -cornerRadius,
+                    taskSize.getWidth() + cornerRadius,
+                    cornerRadius);
+
+            mLeftBottomCornerBounds = new Rect(
+                    -cornerRadius,
+                    taskSize.getHeight() - cornerRadius,
+                    cornerRadius,
+                    taskSize.getHeight() + cornerRadius);
+
+            mRightBottomCornerBounds = new Rect(
+                    taskSize.getWidth() - cornerRadius,
+                    taskSize.getHeight() - cornerRadius,
+                    taskSize.getWidth() + cornerRadius,
+                    taskSize.getHeight() + cornerRadius);
+        }
+
+        /**
+         * Updates the region to include all four corners.
+         */
+        void union(Region region) {
+            region.union(mLeftTopCornerBounds);
+            region.union(mRightTopCornerBounds);
+            region.union(mLeftBottomCornerBounds);
+            region.union(mRightBottomCornerBounds);
+        }
+
+        /**
+         * Returns the control type based on the position of the {@code MotionEvent}'s coordinates.
+         */
+        @DragPositioningCallback.CtrlType
+        int calculateCornersCtrlType(float x, float y) {
+            int xi = (int) x;
+            int yi = (int) y;
+            if (mLeftTopCornerBounds.contains(xi, yi)) {
+                return CTRL_TYPE_LEFT | CTRL_TYPE_TOP;
+            }
+            if (mLeftBottomCornerBounds.contains(xi, yi)) {
+                return CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM;
+            }
+            if (mRightTopCornerBounds.contains(xi, yi)) {
+                return CTRL_TYPE_RIGHT | CTRL_TYPE_TOP;
+            }
+            if (mRightBottomCornerBounds.contains(xi, yi)) {
+                return CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return "TaskCorners of size " + mCornerSize + " for the"
+                    + " top left " + mLeftTopCornerBounds
+                    + " top right " + mRightTopCornerBounds
+                    + " bottom left " + mLeftBottomCornerBounds
+                    + " bottom right " + mRightBottomCornerBounds;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) return false;
+            if (this == obj) return true;
+            if (!(obj instanceof TaskCorners other)) return false;
+
+            return this.mCornerSize == other.mCornerSize
+                    && this.mLeftTopCornerBounds.equals(other.mLeftTopCornerBounds)
+                    && this.mRightTopCornerBounds.equals(other.mRightTopCornerBounds)
+                    && this.mLeftBottomCornerBounds.equals(other.mLeftBottomCornerBounds)
+                    && this.mRightBottomCornerBounds.equals(other.mRightBottomCornerBounds);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(
+                    mCornerSize,
+                    mLeftTopCornerBounds,
+                    mRightTopCornerBounds,
+                    mLeftBottomCornerBounds,
+                    mRightBottomCornerBounds);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt
new file mode 100644
index 0000000..b21c3f5
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor
+
+import android.animation.ValueAnimator
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.ImageButton
+
+/**
+ * [ImageButton] for the handle at the top of fullscreen apps. Has custom hover
+ * and press handling to grow the handle on hover enter and shrink the handle on
+ * hover exit and press.
+ */
+class HandleImageButton (context: Context?, attrs: AttributeSet?) :
+    ImageButton(context, attrs) {
+    private val handleAnimator = ValueAnimator()
+
+    override fun onHoverChanged(hovered: Boolean) {
+        super.onHoverChanged(hovered)
+        if (hovered) {
+            animateHandle(HANDLE_HOVER_ANIM_DURATION, HANDLE_HOVER_ENTER_SCALE)
+        } else {
+            if (!isPressed) {
+                animateHandle(HANDLE_HOVER_ANIM_DURATION, HANDLE_DEFAULT_SCALE)
+            }
+        }
+    }
+
+    override fun setPressed(pressed: Boolean) {
+        if (isPressed != pressed) {
+            super.setPressed(pressed)
+            if (pressed) {
+                animateHandle(HANDLE_PRESS_ANIM_DURATION, HANDLE_PRESS_DOWN_SCALE)
+            } else {
+                animateHandle(HANDLE_PRESS_ANIM_DURATION, HANDLE_DEFAULT_SCALE)
+            }
+        }
+    }
+
+    private fun animateHandle(duration: Long, endScale: Float) {
+        if (handleAnimator.isRunning) {
+            handleAnimator.cancel()
+        }
+        handleAnimator.duration = duration
+        handleAnimator.setFloatValues(scaleX, endScale)
+        handleAnimator.addUpdateListener { animator ->
+            scaleX = animator.animatedValue as Float
+        }
+        handleAnimator.start()
+    }
+
+    companion object {
+        /** The duration of animations related to hover state. **/
+        private const val HANDLE_HOVER_ANIM_DURATION = 300L
+        /** The duration of animations related to pressed state. **/
+        private const val HANDLE_PRESS_ANIM_DURATION = 200L
+        /** Ending scale for hover enter. **/
+        private const val HANDLE_HOVER_ENTER_SCALE = 1.2f
+        /** Ending scale for press down. **/
+        private const val HANDLE_PRESS_DOWN_SCALE = 0.85f
+        /** Default scale for handle. **/
+        private const val HANDLE_DEFAULT_SCALE = 1f
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuImageButton.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuImageButton.kt
index 2fda3ea..7898567 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuImageButton.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuImageButton.kt
@@ -21,7 +21,7 @@
 import android.widget.ImageButton
 
 /**
- * A custom [ImageButton] that intentionally does not handle hover events.
+ * A custom [ImageButton] for buttons inside handle menu that intentionally doesn't handle hovers.
  * This is due to the hover events being handled by [DesktopModeWindowDecorViewModel]
  * in order to take the status bar layer into account. Handling it in both classes results in a
  * flicker when the hover moves from outside to inside status bar layer.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt
index 987aadf..74499c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt
@@ -33,6 +33,7 @@
         get() = dragToDesktopAnimator.animatedValue as Float * startBounds.width()
     val scale: Float
         get() = dragToDesktopAnimator.animatedValue as Float
+    private val mostRecentInput = PointF()
     private val dragToDesktopAnimator: ValueAnimator = ValueAnimator.ofFloat(1f,
             DRAG_FREEFORM_SCALE)
             .setDuration(ANIMATION_DURATION.toLong())
@@ -40,9 +41,13 @@
                 val t = SurfaceControl.Transaction()
                 val cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
                 addUpdateListener {
+                    setTaskPosition(mostRecentInput.x, mostRecentInput.y)
                     t.setScale(taskSurface, scale, scale)
-                            .setCornerRadius(taskSurface, cornerRadius)
-                            .apply()
+                        .setCornerRadius(taskSurface, cornerRadius)
+                        .setScale(taskSurface, scale, scale)
+                        .setCornerRadius(taskSurface, cornerRadius)
+                        .setPosition(taskSurface, position.x, position.y)
+                        .apply()
                 }
             }
 
@@ -78,19 +83,28 @@
         // allow dragging beyond its stage across any region of the display. Because of that, the
         // rawX/Y are more true to where the gesture is on screen and where the surface should be
         // positioned.
-        position.x = ev.rawX - animatedTaskWidth / 2
-        position.y = ev.rawY
+        mostRecentInput.set(ev.rawX, ev.rawY)
 
-        if (!allowSurfaceChangesOnMove) {
+        // If animator is running, allow it to set scale and position at the same time.
+        if (!allowSurfaceChangesOnMove || dragToDesktopAnimator.isRunning) {
             return
         }
-
+        setTaskPosition(ev.rawX, ev.rawY)
         val t = transactionFactory()
         t.setPosition(taskSurface, position.x, position.y)
         t.apply()
     }
 
     /**
+     * Calculates the top left corner of task from input coordinates.
+     * Top left will be needed for the resulting surface control transaction.
+     */
+    private fun setTaskPosition(x: Float, y: Float) {
+        position.x = x - animatedTaskWidth / 2
+        position.y = y
+    }
+
+    /**
      * Cancels the animation, intended to be used when another animator will take over.
      */
     fun cancelAnimator() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
index d072f8c..2c4092a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.ColorRes;
+import android.annotation.NonNull;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -40,7 +41,7 @@
 import android.window.TaskConstants;
 
 import com.android.wm.shell.R;
-import com.android.wm.shell.common.SurfaceUtils;
+import com.android.wm.shell.common.DisplayController;
 
 import java.util.function.Supplier;
 
@@ -48,6 +49,7 @@
  * Creates and updates a veil that covers task contents on resize.
  */
 public class ResizeVeil {
+    private static final String TAG = "ResizeVeil";
     private static final int RESIZE_ALPHA_DURATION = 100;
 
     private static final int VEIL_CONTAINER_LAYER = TaskConstants.TASK_CHILD_LAYER_RESIZE_VEIL;
@@ -57,8 +59,10 @@
     private static final int VEIL_ICON_LAYER = 1;
 
     private final Context mContext;
-    private final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
+    private final DisplayController mDisplayController;
     private final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier;
+    private final SurfaceControlBuilderFactory mSurfaceControlBuilderFactory;
+    private final WindowDecoration.SurfaceControlViewHostFactory mSurfaceControlViewHostFactory;
     private final SurfaceSession mSurfaceSession = new SurfaceSession();
     private final Drawable mAppIcon;
     private ImageView mIconView;
@@ -74,41 +78,82 @@
 
     private final RunningTaskInfo mTaskInfo;
     private SurfaceControlViewHost mViewHost;
-    private final Display mDisplay;
+    private Display mDisplay;
     private ValueAnimator mVeilAnimator;
 
-    public ResizeVeil(Context context, Drawable appIcon, RunningTaskInfo taskInfo,
+    private boolean mIsShowing = false;
+
+    private final DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
+            new DisplayController.OnDisplaysChangedListener() {
+                @Override
+                public void onDisplayAdded(int displayId) {
+                    if (mTaskInfo.displayId != displayId) {
+                        return;
+                    }
+                    mDisplayController.removeDisplayWindowListener(this);
+                    setupResizeVeil();
+                }
+            };
+
+    public ResizeVeil(Context context,
+            @NonNull DisplayController displayController,
+            Drawable appIcon, RunningTaskInfo taskInfo,
             SurfaceControl taskSurface,
-            Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier, Display display,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier) {
+        this(context,
+                displayController,
+                appIcon,
+                taskInfo,
+                taskSurface,
+                surfaceControlTransactionSupplier,
+                new SurfaceControlBuilderFactory() {},
+                new WindowDecoration.SurfaceControlViewHostFactory() {});
+    }
+
+    public ResizeVeil(Context context,
+            @NonNull DisplayController displayController,
+            Drawable appIcon, RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
+            SurfaceControlBuilderFactory surfaceControlBuilderFactory,
+            WindowDecoration.SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
         mContext = context;
+        mDisplayController = displayController;
         mAppIcon = appIcon;
-        mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
         mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
         mTaskInfo = taskInfo;
         mParentSurface = taskSurface;
-        mDisplay = display;
+        mSurfaceControlBuilderFactory = surfaceControlBuilderFactory;
+        mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;
         setupResizeVeil();
     }
-
     /**
      * Create the veil in its default invisible state.
      */
     private void setupResizeVeil() {
-        mVeilSurface = mSurfaceControlBuilderSupplier.get()
+        if (!obtainDisplayOrRegisterListener()) {
+            // Display may not be available yet, skip this until then.
+            return;
+        }
+        mVeilSurface = mSurfaceControlBuilderFactory
+                .create("Resize veil of Task=" + mTaskInfo.taskId)
                 .setContainerLayer()
-                .setName("Resize veil of Task=" + mTaskInfo.taskId)
                 .setHidden(true)
                 .setParent(mParentSurface)
                 .setCallsite("ResizeVeil#setupResizeVeil")
                 .build();
-        mBackgroundSurface = SurfaceUtils.makeColorLayer(mVeilSurface,
-                "Resize veil background of Task=" + mTaskInfo.taskId, mSurfaceSession);
-        mIconSurface = mSurfaceControlBuilderSupplier.get()
-                .setName("Resize veil icon of Task= " + mTaskInfo.taskId)
-                .setContainerLayer()
-                .setParent(mVeilSurface)
+        mBackgroundSurface = mSurfaceControlBuilderFactory
+                .create("Resize veil background of Task=" + mTaskInfo.taskId, mSurfaceSession)
+                .setColorLayer()
                 .setHidden(true)
+                .setParent(mVeilSurface)
+                .setCallsite("ResizeVeil#setupResizeVeil")
+                .build();
+        mIconSurface = mSurfaceControlBuilderFactory
+                .create("Resize veil icon of Task=" + mTaskInfo.taskId)
+                .setContainerLayer()
+                .setHidden(true)
+                .setParent(mVeilSurface)
                 .setCallsite("ResizeVeil#setupResizeVeil")
                 .build();
 
@@ -131,10 +176,20 @@
 
         final WindowlessWindowManager wwm = new WindowlessWindowManager(mTaskInfo.configuration,
                 mIconSurface, null /* hostInputToken */);
-        mViewHost = new SurfaceControlViewHost(mContext, mDisplay, wwm, "ResizeVeil");
+
+        mViewHost = mSurfaceControlViewHostFactory.create(mContext, mDisplay, wwm, "ResizeVeil");
         mViewHost.setView(root, lp);
     }
 
+    private boolean obtainDisplayOrRegisterListener() {
+        mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
+        if (mDisplay == null) {
+            mDisplayController.addDisplayWindowListener(mOnDisplaysChangedListener);
+            return false;
+        }
+        return true;
+    }
+
     /**
      * Shows the veil surface/view.
      *
@@ -146,6 +201,12 @@
      */
     public void showVeil(SurfaceControl.Transaction t, SurfaceControl parentSurface,
             Rect taskBounds, boolean fadeIn) {
+        if (!isReady() || isVisible()) {
+            t.apply();
+            return;
+        }
+        mIsShowing = true;
+
         // Parent surface can change, ensure it is up to date.
         if (!parentSurface.equals(mParentSurface)) {
             t.reparent(mVeilSurface, parentSurface);
@@ -226,6 +287,9 @@
      * Animate veil's alpha to 1, fading it in.
      */
     public void showVeil(SurfaceControl parentSurface, Rect taskBounds) {
+        if (!isReady() || isVisible()) {
+            return;
+        }
         SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
         showVeil(t, parentSurface, taskBounds, true /* fadeIn */);
     }
@@ -247,6 +311,9 @@
      * @param newBounds bounds to update veil to.
      */
     public void updateResizeVeil(Rect newBounds) {
+        if (!isVisible()) {
+            return;
+        }
         SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
         updateResizeVeil(t, newBounds);
     }
@@ -260,6 +327,10 @@
      * @param newBounds bounds to update veil to.
      */
     public void updateResizeVeil(SurfaceControl.Transaction t, Rect newBounds) {
+        if (!isVisible()) {
+            t.apply();
+            return;
+        }
         if (mVeilAnimator != null && mVeilAnimator.isStarted()) {
             mVeilAnimator.removeAllUpdateListeners();
             mVeilAnimator.end();
@@ -272,6 +343,9 @@
      * Animate veil's alpha to 0, fading it out.
      */
     public void hideVeil() {
+        if (!isVisible()) {
+            return;
+        }
         cancelAnimation();
         mVeilAnimator = new ValueAnimator();
         mVeilAnimator.setFloatValues(1, 0);
@@ -292,6 +366,7 @@
             }
         });
         mVeilAnimator.start();
+        mIsShowing = false;
     }
 
     @ColorRes
@@ -318,10 +393,26 @@
     }
 
     /**
+     * Whether the resize veil is currently visible.
+     *
+     * Note: when animating a {@link ResizeVeil#hideVeil()}, the veil is considered visible as soon
+     * as the animation starts.
+     */
+    private boolean isVisible() {
+        return mIsShowing;
+    }
+
+    /** Whether the resize veil is ready to be shown. */
+    private boolean isReady() {
+        return mViewHost != null;
+    }
+
+    /**
      * Dispose of veil when it is no longer needed, likely on close of its container decor.
      */
     void dispose() {
         cancelAnimation();
+        mIsShowing = false;
         mVeilAnimator = null;
 
         if (mViewHost != null) {
@@ -342,5 +433,16 @@
             mVeilSurface = null;
         }
         t.apply();
+        mDisplayController.removeDisplayWindowListener(mOnDisplaysChangedListener);
+    }
+
+    interface SurfaceControlBuilderFactory {
+        default SurfaceControl.Builder create(@NonNull String name) {
+            return new SurfaceControl.Builder().setName(name);
+        }
+        default SurfaceControl.Builder create(@NonNull String name,
+                @NonNull SurfaceSession surfaceSession) {
+            return new SurfaceControl.Builder(surfaceSession).setName(name);
+        }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
index d0fcd86..53d4e27 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
@@ -72,7 +72,10 @@
     }
 
     void closeTask(WindowContainerToken taskToken) {
-        WindowContainerTransaction wct = new WindowContainerTransaction();
+        closeTask(taskToken, new WindowContainerTransaction());
+    }
+
+    void closeTask(WindowContainerToken taskToken, WindowContainerTransaction wct) {
         wct.removeTask(taskToken);
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             mTransitionStarter.startRemoveTransition(wct);
@@ -91,14 +94,12 @@
         }
     }
 
-    void maximizeTask(RunningTaskInfo taskInfo) {
+    void maximizeTask(RunningTaskInfo taskInfo, int containerWindowingMode) {
         WindowContainerTransaction wct = new WindowContainerTransaction();
         int targetWindowingMode = taskInfo.getWindowingMode() != WINDOWING_MODE_FULLSCREEN
                 ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_FREEFORM;
-        int displayWindowingMode =
-                taskInfo.configuration.windowConfiguration.getDisplayWindowingMode();
         wct.setWindowingMode(taskInfo.token,
-                targetWindowingMode == displayWindowingMode
+                targetWindowingMode == containerWindowingMode
                         ? WINDOWING_MODE_UNDEFINED : targetWindowingMode);
         if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) {
             wct.setBounds(taskInfo.token, null);
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 32c2d1e..36da1ac 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
@@ -40,7 +40,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
 import android.view.View;
-import android.view.ViewRootImpl;
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
@@ -293,60 +292,56 @@
                 .setLayer(mCaptionContainerSurface, CAPTION_LAYER_Z_ORDER)
                 .show(mCaptionContainerSurface);
 
-        if (ViewRootImpl.CAPTION_ON_SHELL) {
-            outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
+        outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
 
-            // Caption insets
-            if (mIsCaptionVisible) {
-                // Caption inset is the full width of the task with the |captionHeight| and
-                // positioned at the top of the task bounds, also in absolute coordinates.
-                // So just reuse the task bounds and adjust the bottom coordinate.
-                mCaptionInsetsRect.set(taskBounds);
-                mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + outResult.mCaptionHeight;
+        // Caption insets
+        if (mIsCaptionVisible) {
+            // Caption inset is the full width of the task with the |captionHeight| and
+            // positioned at the top of the task bounds, also in absolute coordinates.
+            // So just reuse the task bounds and adjust the bottom coordinate.
+            mCaptionInsetsRect.set(taskBounds);
+            mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + outResult.mCaptionHeight;
 
-                // Caption bounding rectangles: these are optional, and are used to present finer
-                // insets than traditional |Insets| to apps about where their content is occluded.
-                // These are also in absolute coordinates.
-                final Rect[] boundingRects;
-                final int numOfElements = params.mOccludingCaptionElements.size();
-                if (numOfElements == 0) {
-                    boundingRects = null;
-                } else {
-                    // The customizable region can at most be equal to the caption bar.
+            // Caption bounding rectangles: these are optional, and are used to present finer
+            // insets than traditional |Insets| to apps about where their content is occluded.
+            // These are also in absolute coordinates.
+            final Rect[] boundingRects;
+            final int numOfElements = params.mOccludingCaptionElements.size();
+            if (numOfElements == 0) {
+                boundingRects = null;
+            } else {
+                // The customizable region can at most be equal to the caption bar.
+                if (params.mAllowCaptionInputFallthrough) {
+                    outResult.mCustomizableCaptionRegion.set(mCaptionInsetsRect);
+                }
+                boundingRects = new Rect[numOfElements];
+                for (int i = 0; i < numOfElements; i++) {
+                    final OccludingCaptionElement element =
+                            params.mOccludingCaptionElements.get(i);
+                    final int elementWidthPx =
+                            resources.getDimensionPixelSize(element.mWidthResId);
+                    boundingRects[i] =
+                            calculateBoundingRect(element, elementWidthPx, mCaptionInsetsRect);
+                    // Subtract the regions used by the caption elements, the rest is
+                    // customizable.
                     if (params.mAllowCaptionInputFallthrough) {
-                        outResult.mCustomizableCaptionRegion.set(mCaptionInsetsRect);
-                    }
-                    boundingRects = new Rect[numOfElements];
-                    for (int i = 0; i < numOfElements; i++) {
-                        final OccludingCaptionElement element =
-                                params.mOccludingCaptionElements.get(i);
-                        final int elementWidthPx =
-                                resources.getDimensionPixelSize(element.mWidthResId);
-                        boundingRects[i] =
-                                calculateBoundingRect(element, elementWidthPx, mCaptionInsetsRect);
-                        // Subtract the regions used by the caption elements, the rest is
-                        // customizable.
-                        if (params.mAllowCaptionInputFallthrough) {
-                            outResult.mCustomizableCaptionRegion.op(boundingRects[i],
-                                    Region.Op.DIFFERENCE);
-                        }
+                        outResult.mCustomizableCaptionRegion.op(boundingRects[i],
+                                Region.Op.DIFFERENCE);
                     }
                 }
-                // Add this caption as an inset source.
-                wct.addInsetsSource(mTaskInfo.token,
-                        mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect,
-                        boundingRects);
-                wct.addInsetsSource(mTaskInfo.token,
-                        mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures(),
-                        mCaptionInsetsRect, null /* boundingRects */);
-            } else {
-                wct.removeInsetsSource(mTaskInfo.token, mOwner, 0 /* index */,
-                        WindowInsets.Type.captionBar());
-                wct.removeInsetsSource(mTaskInfo.token, mOwner, 0 /* index */,
-                        WindowInsets.Type.mandatorySystemGestures());
             }
+            // Add this caption as an inset source.
+            wct.addInsetsSource(mTaskInfo.token,
+                    mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect,
+                    boundingRects);
+            wct.addInsetsSource(mTaskInfo.token,
+                    mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures(),
+                    mCaptionInsetsRect, null /* boundingRects */);
         } else {
-            startT.hide(mCaptionContainerSurface);
+            wct.removeInsetsSource(mTaskInfo.token, mOwner, 0 /* index */,
+                    WindowInsets.Type.captionBar());
+            wct.removeInsetsSource(mTaskInfo.token, mOwner, 0 /* index */,
+                    WindowInsets.Type.mandatorySystemGestures());
         }
 
         // Task surface itself
@@ -594,8 +589,7 @@
      */
     public void addCaptionInset(WindowContainerTransaction wct) {
         final int captionHeightId = getCaptionHeightId(mTaskInfo.getWindowingMode());
-        if (!ViewRootImpl.CAPTION_ON_SHELL || captionHeightId == Resources.ID_NULL
-                || !mIsCaptionVisible) {
+        if (captionHeightId == Resources.ID_NULL || !mIsCaptionVisible) {
             return;
         }
 
@@ -674,6 +668,10 @@
         default SurfaceControlViewHost create(Context c, Display d, WindowlessWindowManager wmm) {
             return new SurfaceControlViewHost(c, d, wmm, "WindowDecoration");
         }
+        default SurfaceControlViewHost create(Context c, Display d,
+                WindowlessWindowManager wmm, String callsite) {
+            return new SurfaceControlViewHost(c, d, wmm, callsite);
+        }
     }
 
     /**
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
index 3380adac..e9eabb4 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.appcompat
 
 import android.content.Context
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.FlickerTestData
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.helpers.LetterboxAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.wm.shell.flicker.BaseTest
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
index f08eba5..16c2d47 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.Postsubmit
 import android.tools.flicker.assertions.FlickerTest
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt
index 826fc54..d85b771 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt
@@ -19,11 +19,11 @@
 import android.platform.test.annotations.Postsubmit
 import android.tools.Rotation
 import android.tools.flicker.assertions.FlickerTest
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt
index 26e78bf..164534c 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt
@@ -16,17 +16,17 @@
 
 package com.android.wm.shell.flicker.appcompat
 
+import android.graphics.Rect
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.RequiresDevice
 import android.tools.NavBar
 import android.tools.Rotation
-import android.tools.datatypes.Rect
 import android.tools.flicker.assertions.FlickerTest
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -260,7 +260,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt
index 2aa84b4..034d54b 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt
@@ -53,7 +53,7 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 class RepositionFixedPortraitAppTest(flicker: LegacyFlickerTest) : BaseAppCompat(flicker) {
 
-    val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation).bounds
+    val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation)
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
         get() = {
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt
index 7ffa233..22543aa 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt
@@ -16,19 +16,19 @@
 
 package com.android.wm.shell.flicker.appcompat
 
+import android.graphics.Rect
 import android.os.Build
 import android.platform.test.annotations.Postsubmit
 import android.system.helpers.CommandsHelper
 import android.tools.NavBar
 import android.tools.Rotation
-import android.tools.datatypes.Rect
 import android.tools.flicker.assertions.FlickerTest
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
 import android.tools.helpers.FIND_TIMEOUT
+import android.tools.traces.component.ComponentNameMatcher
 import android.tools.traces.parsers.toFlickerComponent
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.UiDevice
@@ -167,7 +167,7 @@
     }
 
     companion object {
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
         const val LAUNCHER_PACKAGE = "com.google.android.apps.nexuslauncher"
 
         /**
diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
index 521c0d0..2a9b107 100644
--- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
@@ -19,11 +19,11 @@
 import android.content.Context
 import android.graphics.Point
 import android.platform.test.annotations.Presubmit
-import android.tools.flicker.subject.layers.LayersTraceSubject
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.flicker.subject.layers.LayersTraceSubject
+import android.tools.traces.component.ComponentNameMatcher
 import android.util.DisplayMetrics
 import android.view.WindowManager
 import androidx.test.uiautomator.By
diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
index e059ac7..9ef49c1 100644
--- a/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/bubble/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.bubble
 
 import android.platform.test.annotations.Postsubmit
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import android.view.WindowInsets
 import android.view.WindowManager
 import androidx.test.filters.FlakyTest
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index d64bfed..b85d793 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -33,7 +33,7 @@
 /**
  * Test entering pip from an app via auto-enter property when navigating to home.
  *
- * To run this test: `atest WMShellFlickerTests:AutoEnterPipOnGoToHomeTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:AutoEnterPipOnGoToHomeTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt
index a0edcfb..d059211 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -30,7 +30,7 @@
 /**
  * Test auto entering pip using a source rect hint.
  *
- * To run this test: `atest AutoEnterPipWithSourceRectHintTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:AutoEnterPipWithSourceRectHintTest`
  *
  * Actions:
  * ```
@@ -66,9 +66,7 @@
     @Test
     fun pipOverlayNotShown() {
         val overlay = ComponentNameMatcher.PIP_CONTENT_OVERLAY
-        flicker.assertLayers {
-            this.notContains(overlay)
-        }
+        flicker.assertLayers { this.notContains(overlay) }
     }
     @Presubmit
     @Test
@@ -83,4 +81,4 @@
         // auto enter and sourceRectHint that causes the app to move outside of the display
         // bounds during the transition.
     }
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 031acf4..a5e0550 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.wm.shell.flicker.pip.common.ClosePipTransition
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -31,7 +31,7 @@
 /**
  * Test closing a pip window by swiping it to the bottom-center of the screen
  *
- * To run this test: `atest WMShellFlickerTests:ExitPipWithSwipeDownTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:ClosePipBySwipingDownTest`
  *
  * Actions:
  * ```
@@ -69,7 +69,8 @@
                 wmHelper.currentState.layerState
                     .getLayerWithBuffer(barComponent)
                     ?.visibleRegion
-                    ?.height
+                    ?.bounds
+                    ?.height()
                     ?: error("Couldn't find Nav or Task bar layer")
             // The dismiss button doesn't appear at the complete bottom of the screen,
             // it appears above the hot seat but `hotseatBarSize` is not available outside
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
index 860307f..d177624 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
@@ -30,7 +30,7 @@
 /**
  * Test closing a pip window via the dismiss button
  *
- * To run this test: `atest WMShellFlickerTests:ExitPipWithDismissButtonTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:ClosePipWithDismissButtonTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index c554161..a86803d 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -31,7 +31,7 @@
 /**
  * Test entering pip from an app via [onUserLeaveHint] and by navigating to home.
  *
- * To run this test: `atest WMShellFlickerTests:EnterPipOnUserLeaveHintTest`
+ * To run this test: `atest WMShellFlickerTestsPip2:EnterPipOnUserLeaveHintTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index 9a1bd26..a0a61fe2 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -21,12 +21,12 @@
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
 import android.tools.flicker.assertions.FlickerTest
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
 import android.tools.helpers.WindowUtils
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.FlakyTest
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
@@ -46,7 +46,7 @@
 /**
  * Test entering pip while changing orientation (from app in landscape to pip window in portrait)
  *
- * To run this test: `atest WMShellFlickerTests:EnterPipToOtherOrientationTest`
+ * To run this test: `atest WMShellFlickerTestsPip2:EnterPipToOtherOrientation`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
index f97d8d1..d92f55a 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
@@ -28,7 +28,7 @@
 /**
  * Test entering pip from an app by interacting with the app UI
  *
- * To run this test: `atest WMShellFlickerTests:EnterPipTest`
+ * To run this test: `atest WMShellFlickerTestsPip2:EnterPipViaAppUiButtonTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
index 47bf418..8c0817d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
@@ -28,7 +28,7 @@
 /**
  * Test expanding a pip window back to full screen via the expand button
  *
- * To run this test: `atest WMShellFlickerTests:ExitPipViaExpandButtonClickTest`
+ * To run this test: `atest WMShellFlickerTestsPip2:ExitPipToAppViaExpandButtonTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
index a356e68..90a9623 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
@@ -28,7 +28,7 @@
 /**
  * Test expanding a pip window back to full screen via an intent
  *
- * To run this test: `atest WMShellFlickerTests:ExitPipViaIntentTest`
+ * To run this test: `atest WMShellFlickerTestsPip2:ExitPipToAppViaIntentTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 25614ef..9306c77 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.wm.shell.flicker.pip.common.PipTransition
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -33,7 +33,7 @@
 /**
  * Test expanding a pip window by double-clicking it
  *
- * To run this test: `atest WMShellFlickerTests:ExpandPipOnDoubleClickTest`
+ * To run this test: `atest WMShellFlickerTestsPip2:ExpandPipOnDoubleClickTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt
index b94989d..cb8ee27 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt
@@ -24,6 +24,7 @@
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
 import android.tools.helpers.WindowUtils
 import android.tools.traces.parsers.toFlickerComponent
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.testapp.ActivityOptions
@@ -38,7 +39,7 @@
 /**
  * Test entering pip from an app via auto-enter property when navigating to home from split screen.
  *
- * To run this test: `atest WMShellFlickerTests:AutoEnterPipOnGoToHomeTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:FromSplitScreenAutoEnterPipOnGoToHomeTest`
  *
  * Actions:
  * ```
@@ -143,6 +144,10 @@
         }
     }
 
+    @FlakyTest(bugId = 293133362)
+    @Test
+    override fun entireScreenCovered() = super.entireScreenCovered()
+
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt
index 5f25d70..f2f10ae 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt
@@ -40,7 +40,7 @@
 /**
  * Test entering pip from an app via auto-enter property when navigating to home from split screen.
  *
- * To run this test: `atest WMShellFlickerTests:AutoEnterPipOnGoToHomeTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:FromSplitScreenEnterPipOnUserLeaveHintTest`
  *
  * Actions:
  * ```
@@ -191,8 +191,9 @@
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
-        fun getParams() = LegacyFlickerTestFactory.nonRotationTests(
-            supportedRotations = listOf(Rotation.ROTATION_0)
-        )
+        fun getParams() =
+            LegacyFlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(Rotation.ROTATION_0)
+            )
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
index 9b74622..265eb44 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
@@ -32,7 +32,7 @@
 /**
  * Test Pip movement with Launcher shelf height change (increase).
  *
- * To run this test: `atest WMShellFlickerTests:MovePipUpShelfHeightChangeTest`
+ * To run this test: `atest WMShellFlickerTestsPip3:MovePipDownOnShelfHeightChange`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index e184cf0..04fedf4 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -19,12 +19,12 @@
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
 import android.tools.flicker.assertions.FlickerTest
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
 import android.tools.helpers.WindowUtils
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.helpers.ImeAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.wm.shell.flicker.pip.common.PipTransition
@@ -34,7 +34,10 @@
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
 
-/** Test Pip launch. To run this test: `atest WMShellFlickerTests:PipKeyboardTest` */
+/**
+ * Test Pip launch. To run this test:
+ * `atest WMShellFlickerTestsPip3:MovePipOnImeVisibilityChangeTest`
+ */
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
index 490ebd1..8d6be64 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
@@ -32,7 +32,7 @@
 /**
  * Test Pip movement with Launcher shelf height change (decrease).
  *
- * To run this test: `atest WMShellFlickerTests:MovePipDownShelfHeightChangeTest`
+ * To run this test: `atest WMShellFlickerTestsPip3:MovePipUpOnShelfHeightChangeTest`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
index 6841706..16d08e5 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.flicker.subject.exceptions.IncorrectRegionException
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.flicker.subject.exceptions.IncorrectRegionException
 import androidx.test.filters.RequiresDevice
 import com.android.wm.shell.flicker.pip.common.PipTransition
 import org.junit.FixMethodOrder
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
index 9a6dacb..ed2a0a7 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
@@ -41,8 +41,8 @@
 import org.junit.runners.Parameterized
 
 /**
- * Test exiting Pip with orientation changes. To run this test: `atest
- * WMShellFlickerTests:SetRequestedOrientationWhilePinnedTest`
+ * Test exiting Pip with orientation changes. To run this test:
+ * `atest WMShellFlickerTestsPip1:SetRequestedOrientationWhilePinned`
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
index d2f803e..9109eaf 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
@@ -35,7 +35,7 @@
 /**
  * Test Pip Stack in bounds after rotations.
  *
- * To run this test: `atest WMShellFlickerTests:PipRotationTest`
+ * To run this test: `atest WMShellFlickerTestsPip1:ShowPipAndRotateDisplay`
  *
  * Actions:
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt
index c9f4a6c..65b60ce 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt
@@ -18,12 +18,12 @@
 
 import android.platform.test.annotations.Postsubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.device.apphelpers.StandardAppHelper
 import android.tools.flicker.junit.FlickerBuilderProvider
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.wm.shell.flicker.pip.common.EnterPipTransition
 import org.junit.Test
 import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt
index 8865010..1fc9d99 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt
@@ -65,8 +65,8 @@
 open class MapsEnterPipTest(flicker: LegacyFlickerTest) : AppsEnterPipTransition(flicker) {
     override val standardAppHelper: MapsAppHelper = MapsAppHelper(instrumentation)
 
-    override val permissions: Array<String> = arrayOf(Manifest.permission.POST_NOTIFICATIONS,
-        Manifest.permission.ACCESS_FINE_LOCATION)
+    override val permissions: Array<String> =
+        arrayOf(Manifest.permission.POST_NOTIFICATIONS, Manifest.permission.ACCESS_FINE_LOCATION)
 
     val locationManager: LocationManager =
         instrumentation.context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt
index e85da30..3a0eeb6 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt
@@ -19,13 +19,13 @@
 import android.Manifest
 import android.platform.test.annotations.Postsubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.device.apphelpers.NetflixAppHelper
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
 import android.tools.helpers.WindowUtils
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
 import org.junit.Assume
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt
index 3ae5937..35ed8de 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt
@@ -18,11 +18,11 @@
 
 import android.Manifest
 import android.platform.test.annotations.Postsubmit
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.device.apphelpers.YouTubeAppHelper
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import org.junit.Assume
 import org.junit.FixMethodOrder
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt
index de8e7c3..879034f 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt
@@ -19,13 +19,13 @@
 import android.Manifest
 import android.platform.test.annotations.Postsubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.device.apphelpers.YouTubeAppHelper
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
 import android.tools.helpers.WindowUtils
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
 import org.junit.Assume
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt
index dc12259..8cb81b4 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ClosePipTransition.kt
@@ -18,10 +18,10 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher.Companion.LAUNCHER
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher.Companion.LAUNCHER
 import com.android.server.wm.flicker.helpers.setRotation
 import org.junit.Test
 import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt
index 3d9eae6..6dd3a17 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/EnterPipTransition.kt
@@ -18,10 +18,10 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import org.junit.Test
 import org.junit.runners.Parameterized
 
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt
index 7b6839d..0742cf9 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/ExitPipToAppTransition.kt
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import org.junit.Test
 import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt
index f4baf5f..c4881e7 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/MovePipShelfHeightTransition.kt
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.flicker.subject.region.RegionSubject
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.flicker.subject.region.RegionSubject
 import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
 import com.android.wm.shell.flicker.utils.Direction
 import org.junit.Test
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt
index fd467e3..99c1ad2 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt
@@ -20,11 +20,11 @@
 import android.content.Intent
 import android.platform.test.annotations.Presubmit
 import android.tools.Rotation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
 import android.tools.helpers.WindowUtils
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.helpers.PipAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/OWNERS b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/OWNERS
new file mode 100644
index 0000000..73a5a23
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/OWNERS
@@ -0,0 +1,5 @@
+# Android > Android OS & Apps > Framework (Java + Native) > Window Manager > WM Shell > Freeform
+# Bug component: 929241
+
[email protected]
[email protected]
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitLandscape.kt
new file mode 100644
index 0000000..5563bb9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitLandscape.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_APP
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_LAST_APP
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class CloseAllAppWithAppHeaderExitLandscape : CloseAllAppsWithAppHeaderExit(Rotation.ROTATION_90) {
+    @ExpectedScenarios(["CLOSE_APP", "CLOSE_LAST_APP"])
+    @Test
+    override fun closeAllAppsInDesktop() = super.closeAllAppsInDesktop()
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig()
+                .use(FlickerServiceConfig.DEFAULT)
+                .use(CLOSE_APP)
+                .use(CLOSE_LAST_APP)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitPortrait.kt
new file mode 100644
index 0000000..3d16d2219
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitPortrait.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_APP
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_LAST_APP
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class CloseAllAppWithAppHeaderExitPortrait : CloseAllAppsWithAppHeaderExit(Rotation.ROTATION_0) {
+    @ExpectedScenarios(["CLOSE_APP", "CLOSE_LAST_APP"])
+    @Test
+    override fun closeAllAppsInDesktop() = super.closeAllAppsInDesktop()
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig()
+                .use(FlickerServiceConfig.DEFAULT)
+                .use(CLOSE_APP)
+                .use(CLOSE_LAST_APP)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
new file mode 100644
index 0000000..75dfeba
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.flicker.AssertionInvocationGroup
+import android.tools.flicker.assertors.assertions.AppLayerIsInvisibleAtEnd
+import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAlways
+import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAtStart
+import android.tools.flicker.assertors.assertions.AppWindowHasDesktopModeInitialBoundsAtTheEnd
+import android.tools.flicker.assertors.assertions.AppWindowOnTopAtEnd
+import android.tools.flicker.assertors.assertions.AppWindowOnTopAtStart
+import android.tools.flicker.assertors.assertions.LauncherWindowMovesToTop
+import android.tools.flicker.config.AssertionTemplates
+import android.tools.flicker.config.FlickerConfigEntry
+import android.tools.flicker.config.ScenarioId
+import android.tools.flicker.config.desktopmode.Components
+import android.tools.flicker.extractors.ITransitionMatcher
+import android.tools.flicker.extractors.ShellTransitionScenarioExtractor
+import android.tools.traces.wm.Transition
+import android.tools.traces.wm.TransitionType
+
+class DesktopModeFlickerScenarios {
+    companion object {
+        val END_DRAG_TO_DESKTOP =
+            FlickerConfigEntry(
+                scenarioId = ScenarioId("END_DRAG_TO_DESKTOP"),
+                extractor =
+                    ShellTransitionScenarioExtractor(
+                        transitionMatcher =
+                            object : ITransitionMatcher {
+                                override fun findAll(
+                                    transitions: Collection<Transition>
+                                ): Collection<Transition> {
+                                    return transitions.filter {
+                                        it.type == TransitionType.DESKTOP_MODE_END_DRAG_TO_DESKTOP
+                                    }
+                                }
+                            }
+                    ),
+                assertions =
+                    AssertionTemplates.COMMON_ASSERTIONS +
+                        listOf(
+                                AppLayerIsVisibleAlways(Components.DESKTOP_MODE_APP),
+                                AppWindowOnTopAtEnd(Components.DESKTOP_MODE_APP),
+                                AppWindowHasDesktopModeInitialBoundsAtTheEnd(
+                                    Components.DESKTOP_MODE_APP
+                                )
+                            )
+                            .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+            )
+
+        val CLOSE_APP =
+            FlickerConfigEntry(
+                scenarioId = ScenarioId("CLOSE_APP"),
+                extractor =
+                    ShellTransitionScenarioExtractor(
+                        transitionMatcher =
+                            object : ITransitionMatcher {
+                                override fun findAll(
+                                    transitions: Collection<Transition>
+                                ): Collection<Transition> {
+                                    return transitions.filter { it.type == TransitionType.CLOSE }
+                                }
+                            }
+                    ),
+                assertions =
+                    AssertionTemplates.COMMON_ASSERTIONS +
+                        listOf(
+                                AppWindowOnTopAtStart(Components.DESKTOP_MODE_APP),
+                                AppLayerIsVisibleAtStart(Components.DESKTOP_MODE_APP),
+                                AppLayerIsInvisibleAtEnd(Components.DESKTOP_MODE_APP),
+                            )
+                            .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+            )
+
+        val CLOSE_LAST_APP =
+            FlickerConfigEntry(
+                scenarioId = ScenarioId("CLOSE_LAST_APP"),
+                extractor =
+                    ShellTransitionScenarioExtractor(
+                        transitionMatcher =
+                            object : ITransitionMatcher {
+                                override fun findAll(
+                                    transitions: Collection<Transition>
+                                ): Collection<Transition> {
+                                    val lastTransition =
+                                        transitions.findLast { it.type == TransitionType.CLOSE }
+                                    return if (lastTransition != null) listOf(lastTransition)
+                                    else emptyList()
+                                }
+                            }
+                    ),
+                assertions =
+                    AssertionTemplates.COMMON_ASSERTIONS +
+                        listOf(
+                                AppWindowOnTopAtStart(Components.DESKTOP_MODE_APP),
+                                AppLayerIsVisibleAtStart(Components.DESKTOP_MODE_APP),
+                                AppLayerIsInvisibleAtEnd(Components.DESKTOP_MODE_APP),
+                                LauncherWindowMovesToTop()
+                            )
+                            .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+            )
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt
new file mode 100644
index 0000000..9dfafe9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.END_DRAG_TO_DESKTOP
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.EnterDesktopWithDrag
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class EnterDesktopWithDragLandscape : EnterDesktopWithDrag(Rotation.ROTATION_90) {
+    @ExpectedScenarios(["END_DRAG_TO_DESKTOP"])
+    @Test
+    override fun enterDesktopWithDrag() = super.enterDesktopWithDrag()
+
+    companion object {
+
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(END_DRAG_TO_DESKTOP)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt
new file mode 100644
index 0000000..1c7d623
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.END_DRAG_TO_DESKTOP
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.EnterDesktopWithDrag
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class EnterDesktopWithDragPortrait : EnterDesktopWithDrag(Rotation.ROTATION_0) {
+    @ExpectedScenarios(["END_DRAG_TO_DESKTOP"])
+    @Test
+    override fun enterDesktopWithDrag() = super.enterDesktopWithDrag()
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(END_DRAG_TO_DESKTOP)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
new file mode 100644
index 0000000..0c2b501
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.flicker.service.common.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+@Ignore("Base Test Class")
+abstract class CloseAllAppsWithAppHeaderExit
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0) {
+
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+    private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+    private val nonResizeableApp = DesktopModeAppHelper(NonResizeableAppHelper(instrumentation))
+
+
+
+    @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+        tapl.setEnableRotation(true)
+        tapl.setExpectedRotation(rotation.value)
+        testApp.enterDesktopWithDrag(wmHelper, device)
+        mailApp.launchViaIntent(wmHelper)
+        nonResizeableApp.launchViaIntent(wmHelper)
+    }
+
+    @Test
+    open fun closeAllAppsInDesktop() {
+        nonResizeableApp.closeDesktopApp(wmHelper, device)
+        mailApp.closeDesktopApp(wmHelper, device)
+        testApp.closeDesktopApp(wmHelper, device)
+    }
+
+    @After
+    fun teardown() {
+        testApp.exit(wmHelper)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
new file mode 100644
index 0000000..9e9998e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.service.desktopmode.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.flicker.service.common.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+
+@Ignore("Base Test Class")
+abstract class EnterDesktopWithDrag
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0) {
+
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+
+    @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+        tapl.setEnableRotation(true)
+        tapl.setExpectedRotation(rotation.value)
+    }
+
+    @Test
+    open fun enterDesktopWithDrag() {
+        testApp.enterDesktopWithDrag(wmHelper, device)
+    }
+
+    @After
+    fun teardown() {
+        testApp.exit(wmHelper)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt
index 9e6a686..bcd0f12 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt
@@ -24,6 +24,7 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.UiDevice
 import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.MultiWindowUtils
 import com.android.wm.shell.flicker.service.common.Utils
 import com.android.wm.shell.flicker.utils.SplitScreenUtils
 import org.junit.After
@@ -51,6 +52,10 @@
     fun setup() {
         Assume.assumeTrue(tapl.isTablet)
 
+        MultiWindowUtils.executeShellCommand(
+                instrumentation,
+                "settings put system notification_cooldown_enabled 0"
+        )
         // Send a notification
         sendNotificationApp.launchViaIntent(wmHelper)
         sendNotificationApp.postNotification(wmHelper)
@@ -74,5 +79,10 @@
         primaryApp.exit(wmHelper)
         secondaryApp.exit(wmHelper)
         sendNotificationApp.exit(wmHelper)
+
+        MultiWindowUtils.executeShellCommand(
+                instrumentation,
+                "settings reset system notification_cooldown_enabled"
+        )
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt
index 9312c0a..db962e7 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt
@@ -141,7 +141,7 @@
 
     private fun isLandscape(rotation: Rotation): Boolean {
         val displayBounds = WindowUtils.getDisplayBounds(rotation)
-        return displayBounds.width > displayBounds.height
+        return displayBounds.width() > displayBounds.height()
     }
 
     private fun isTablet(): Boolean {
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index d74c59e..7f48499 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -17,12 +17,12 @@
 package com.android.wm.shell.flicker.splitscreen
 
 import android.platform.test.annotations.Presubmit
-import android.tools.traces.component.ComponentNameMatcher
-import android.tools.traces.component.EdgeExtensionComponentMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
+import android.tools.traces.component.EdgeExtensionComponentMatcher
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.wm.shell.flicker.splitscreen.benchmark.CopyContentInSplitBenchmark
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt
index 8724346..a72b3d1 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairsNoPip.kt
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.Presubmit
 import android.tools.NavBar
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.helpers.PipAppHelper
 import com.android.wm.shell.flicker.splitscreen.benchmark.SplitScreenBase
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt
index 16d7331..9045364 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/UnlockKeyguardToSplitScreen.kt
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.tools.NavBar
-import android.tools.flicker.subject.layers.LayersTraceSubject
-import android.tools.flicker.subject.region.RegionSubject
-import android.tools.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.flicker.subject.layers.LayersTraceSubject
+import android.tools.flicker.subject.region.RegionSubject
+import android.tools.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.wm.shell.flicker.splitscreen.benchmark.UnlockKeyguardToSplitScreenBenchmark
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt
index 9c5a3fe..7e8e508 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt
@@ -16,11 +16,11 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.filters.RequiresDevice
 import com.android.wm.shell.flicker.utils.SplitScreenUtils
 import org.junit.FixMethodOrder
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt
index 38206c3..6a6aa1a 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt
@@ -128,7 +128,7 @@
 
     private fun isLandscape(rotation: Rotation): Boolean {
         val displayBounds = WindowUtils.getDisplayBounds(rotation)
-        return displayBounds.width > displayBounds.height
+        return displayBounds.width() > displayBounds.height()
     }
 
     companion object {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index a19d232..90d2635 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -17,8 +17,8 @@
 package com.android.wm.shell.flicker
 
 import android.app.Instrumentation
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.launcher3.tapl.LauncherInstrumentation
 import com.android.wm.shell.flicker.utils.ICommonAssertions
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt
index 3df0954..509f4f2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/CommonAssertions.kt
@@ -18,13 +18,13 @@
 
 package com.android.wm.shell.flicker.utils
 
+import android.graphics.Region
 import android.tools.Rotation
-import android.tools.datatypes.Region
+import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.flicker.subject.layers.LayerTraceEntrySubject
 import android.tools.flicker.subject.layers.LayersTraceSubject
-import android.tools.traces.component.IComponentMatcher
-import android.tools.flicker.legacy.LegacyFlickerTest
 import android.tools.helpers.WindowUtils
+import android.tools.traces.component.IComponentMatcher
 
 fun LegacyFlickerTest.appPairsDividerIsVisibleAtEnd() {
     assertLayersEnd { this.isVisible(APP_PAIR_SPLIT_DIVIDER_COMPONENT) }
@@ -263,41 +263,41 @@
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return invoke {
         val dividerRegion =
-            layer(SPLIT_SCREEN_DIVIDER_COMPONENT)?.visibleRegion?.region
+            layer(SPLIT_SCREEN_DIVIDER_COMPONENT)?.visibleRegion?.region?.bounds
                 ?: error("$SPLIT_SCREEN_DIVIDER_COMPONENT component not found")
         visibleRegion(component).isNotEmpty()
         visibleRegion(component)
             .coversAtMost(
-                if (displayBounds.width > displayBounds.height) {
+                if (displayBounds.width() > displayBounds.height()) {
                     if (landscapePosLeft) {
-                        Region.from(
+                        Region(
                             0,
                             0,
-                            (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
-                            displayBounds.bounds.bottom
+                            (dividerRegion.left + dividerRegion.right) / 2,
+                            displayBounds.bottom
                         )
                     } else {
-                        Region.from(
-                            (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
+                        Region(
+                            (dividerRegion.left + dividerRegion.right) / 2,
                             0,
-                            displayBounds.bounds.right,
-                            displayBounds.bounds.bottom
+                            displayBounds.right,
+                            displayBounds.bottom
                         )
                     }
                 } else {
                     if (portraitPosTop) {
-                        Region.from(
+                        Region(
                             0,
                             0,
-                            displayBounds.bounds.right,
-                            (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2
+                            displayBounds.right,
+                            (dividerRegion.top + dividerRegion.bottom) / 2
                         )
                     } else {
-                        Region.from(
+                        Region(
                             0,
-                            (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2,
-                            displayBounds.bounds.right,
-                            displayBounds.bounds.bottom
+                            (dividerRegion.top + dividerRegion.bottom) / 2,
+                            displayBounds.right,
+                            displayBounds.bottom
                         )
                     }
                 }
@@ -420,17 +420,17 @@
 fun getPrimaryRegion(dividerRegion: Region, rotation: Rotation): Region {
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return if (rotation.isRotated()) {
-        Region.from(
+        Region(
             0,
             0,
             dividerRegion.bounds.left + WindowUtils.dockedStackDividerInset,
-            displayBounds.bounds.bottom
+            displayBounds.bottom
         )
     } else {
-        Region.from(
+        Region(
             0,
             0,
-            displayBounds.bounds.right,
+            displayBounds.right,
             dividerRegion.bounds.top + WindowUtils.dockedStackDividerInset
         )
     }
@@ -439,18 +439,18 @@
 fun getSecondaryRegion(dividerRegion: Region, rotation: Rotation): Region {
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return if (rotation.isRotated()) {
-        Region.from(
+        Region(
             dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset,
             0,
-            displayBounds.bounds.right,
-            displayBounds.bounds.bottom
+            displayBounds.right,
+            displayBounds.bottom
         )
     } else {
-        Region.from(
+        Region(
             0,
             dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
-            displayBounds.bounds.right,
-            displayBounds.bounds.bottom
+            displayBounds.right,
+            displayBounds.bottom
         )
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt
index 50c0435..4465a16 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/ICommonAssertions.kt
@@ -17,8 +17,8 @@
 package com.android.wm.shell.flicker.utils
 
 import android.platform.test.annotations.Presubmit
-import android.tools.traces.component.ComponentNameMatcher
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
 import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt
index 9cc3a98..c4954f9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt
@@ -20,11 +20,11 @@
 import android.graphics.Point
 import android.os.SystemClock
 import android.tools.Rotation
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.flicker.rules.ChangeDisplayOrientationRule
 import android.tools.traces.component.ComponentNameMatcher
 import android.tools.traces.component.IComponentMatcher
 import android.tools.traces.component.IComponentNameMatcher
-import android.tools.device.apphelpers.StandardAppHelper
-import android.tools.flicker.rules.ChangeDisplayOrientationRule
 import android.tools.traces.parsers.WindowManagerStateHelper
 import android.tools.traces.parsers.toFlickerComponent
 import android.view.InputDevice
@@ -182,13 +182,7 @@
         val swipeXCoordinate = displayBounds.centerX() / 2
 
         // Pull down the notifications
-        device.swipe(
-            swipeXCoordinate,
-            5,
-            swipeXCoordinate,
-            displayBounds.bottom,
-            50 /* steps */
-        )
+        device.swipe(swipeXCoordinate, 5, swipeXCoordinate, displayBounds.bottom, 50 /* steps */)
         SystemClock.sleep(TIMEOUT_MS)
 
         // Find the target notification
@@ -211,7 +205,7 @@
         // Drag to split
         val dragStart = notificationContent.visibleCenter
         val dragMiddle = Point(dragStart.x + 50, dragStart.y)
-        val dragEnd = Point(displayBounds.width / 4, displayBounds.width / 4)
+        val dragEnd = Point(displayBounds.width() / 4, displayBounds.width() / 4)
         val downTime = SystemClock.uptimeMillis()
 
         touch(instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime, TIMEOUT_MS, dragStart)
@@ -318,7 +312,7 @@
             wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
                 ?: error("Display not found")
         val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
-        dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3), 200)
+        dividerBar.drag(Point(displayBounds.width() * 1 / 3, displayBounds.height() * 2 / 3), 200)
 
         wmHelper
             .StateSyncBuilder()
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 32c0703..13f95cc 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -39,7 +39,7 @@
     static_libs: [
         "WindowManager-Shell",
         "junit",
-        "flag-junit-base",
+        "flag-junit",
         "androidx.test.runner",
         "androidx.test.rules",
         "androidx.test.ext.junit",
@@ -55,6 +55,9 @@
         "platform-test-annotations",
         "servicestests-utils",
         "com_android_wm_shell_flags_lib",
+        "guava-android-testlib",
+        "com.android.window.flags.window-aconfig-java",
+        "platform-test-annotations",
     ],
 
     libs: [
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 9c1a88e..82c070c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -16,10 +16,10 @@
 
 package com.android.wm.shell;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -435,7 +435,8 @@
     public void testOnCameraCompatActivityChanged() {
         final RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN);
         taskInfo1.displayId = DEFAULT_DISPLAY;
-        taskInfo1.appCompatTaskInfo.cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
+        taskInfo1.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
+                CAMERA_COMPAT_CONTROL_HIDDEN;
         final TrackingTaskListener taskListener = new TrackingTaskListener();
         mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
         mOrganizer.onTaskAppeared(taskInfo1, null);
@@ -449,7 +450,7 @@
         final RunningTaskInfo taskInfo2 =
                 createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
         taskInfo2.displayId = taskInfo1.displayId;
-        taskInfo2.appCompatTaskInfo.cameraCompatControlState =
+        taskInfo2.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
                 CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
         taskInfo2.isVisible = true;
         mOrganizer.onTaskInfoChanged(taskInfo2);
@@ -461,7 +462,7 @@
         final RunningTaskInfo taskInfo3 =
                 createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
         taskInfo3.displayId = taskInfo1.displayId;
-        taskInfo3.appCompatTaskInfo.cameraCompatControlState =
+        taskInfo3.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
                 CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
         taskInfo3.isVisible = true;
         mOrganizer.onTaskInfoChanged(taskInfo3);
@@ -474,7 +475,7 @@
                 createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
         taskInfo4.displayId = taskInfo1.displayId;
         taskInfo4.appCompatTaskInfo.topActivityInSizeCompat = true;
-        taskInfo4.appCompatTaskInfo.cameraCompatControlState =
+        taskInfo4.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
                 CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
         taskInfo4.isVisible = true;
         mOrganizer.onTaskInfoChanged(taskInfo4);
@@ -485,7 +486,7 @@
         final RunningTaskInfo taskInfo5 =
                 createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
         taskInfo5.displayId = taskInfo1.displayId;
-        taskInfo5.appCompatTaskInfo.cameraCompatControlState =
+        taskInfo5.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
                 CAMERA_COMPAT_CONTROL_DISMISSED;
         taskInfo5.isVisible = true;
         mOrganizer.onTaskInfoChanged(taskInfo5);
@@ -496,7 +497,7 @@
         final RunningTaskInfo taskInfo6 =
                 createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
         taskInfo6.displayId = taskInfo1.displayId;
-        taskInfo6.appCompatTaskInfo.cameraCompatControlState =
+        taskInfo6.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
                 CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
         taskInfo6.isVisible = false;
         mOrganizer.onTaskInfoChanged(taskInfo6);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
index 3672ae3..24f4d92 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
@@ -23,8 +23,10 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.WindowConfiguration;
+import android.content.Intent;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.IBinder;
@@ -38,6 +40,7 @@
 
     private WindowContainerToken mToken = createMockWCToken();
     private int mParentTaskId = INVALID_TASK_ID;
+    private Intent mBaseIntent = new Intent();
     private @WindowConfiguration.ActivityType int mActivityType = ACTIVITY_TYPE_STANDARD;
     private @WindowConfiguration.WindowingMode int mWindowingMode = WINDOWING_MODE_UNDEFINED;
     private int mDisplayId = Display.DEFAULT_DISPLAY;
@@ -68,6 +71,15 @@
         return this;
     }
 
+    /**
+     * Set {@link ActivityManager.RunningTaskInfo#baseIntent} for the task info, by default
+     * an empty intent is assigned
+     */
+    public TestRunningTaskInfoBuilder setBaseIntent(@NonNull Intent intent) {
+        mBaseIntent = intent;
+        return this;
+    }
+
     public TestRunningTaskInfoBuilder setActivityType(
             @WindowConfiguration.ActivityType int activityType) {
         mActivityType = activityType;
@@ -109,6 +121,7 @@
     public ActivityManager.RunningTaskInfo build() {
         final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
         info.taskId = sNextTaskId++;
+        info.baseIntent = mBaseIntent;
         info.parentTaskId = mParentTaskId;
         info.displayId = mDisplayId;
         info.configuration.windowConfiguration.setBounds(mBounds);
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 2ff1ddd..65169e3 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
@@ -16,7 +16,7 @@
 
 package com.android.wm.shell.back;
 
-import static android.window.BackNavigationInfo.KEY_TRIGGER_BACK;
+import static android.window.BackNavigationInfo.KEY_NAVIGATION_FINISHED;
 
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -120,6 +120,8 @@
     private TestableContentResolver mContentResolver;
     private TestableLooper mTestableLooper;
 
+    private CrossActivityBackAnimation mCrossActivityBackAnimation;
+    private CrossTaskBackAnimation mCrossTaskBackAnimation;
     private ShellBackAnimationRegistry mShellBackAnimationRegistry;
 
     @Before
@@ -133,11 +135,11 @@
                 ANIMATION_ENABLED);
         mTestableLooper = TestableLooper.get(this);
         mShellInit = spy(new ShellInit(mShellExecutor));
+        mCrossActivityBackAnimation = new CrossActivityBackAnimation(mContext, mAnimationBackground,
+                mRootTaskDisplayAreaOrganizer);
+        mCrossTaskBackAnimation = new CrossTaskBackAnimation(mContext, mAnimationBackground);
         mShellBackAnimationRegistry =
-                new ShellBackAnimationRegistry(
-                        new CrossActivityBackAnimation(
-                                mContext, mAnimationBackground, mRootTaskDisplayAreaOrganizer),
-                        new CrossTaskBackAnimation(mContext, mAnimationBackground),
+                new ShellBackAnimationRegistry(mCrossActivityBackAnimation, mCrossTaskBackAnimation,
                         /* dialogCloseAnimation= */ null,
                         new CustomizeActivityAnimation(mContext, mAnimationBackground),
                         /* defaultBackToHomeAnimation= */ null);
@@ -576,16 +578,14 @@
 
     @Test
     public void testBackToActivity() throws RemoteException {
-        final CrossActivityBackAnimation animation = new CrossActivityBackAnimation(
-                mContext, mAnimationBackground, mRootTaskDisplayAreaOrganizer);
-        verifySystemBackBehavior(BackNavigationInfo.TYPE_CROSS_ACTIVITY, animation.getRunner());
+        verifySystemBackBehavior(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
+                mCrossActivityBackAnimation.getRunner());
     }
 
     @Test
     public void testBackToTask() throws RemoteException {
-        final CrossTaskBackAnimation animation = new CrossTaskBackAnimation(mContext,
-                mAnimationBackground);
-        verifySystemBackBehavior(BackNavigationInfo.TYPE_CROSS_TASK, animation.getRunner());
+        verifySystemBackBehavior(BackNavigationInfo.TYPE_CROSS_TASK,
+                mCrossTaskBackAnimation.getRunner());
     }
 
     private void verifySystemBackBehavior(int type, BackAnimationRunner animation)
@@ -596,6 +596,7 @@
 
         // Set up the monitoring objects.
         doNothing().when(runner).onAnimationStart(anyInt(), any(), any(), any(), any());
+        doReturn(false).when(animationRunner).shouldMonitorCUJ(any());
         doReturn(runner).when(animationRunner).getRunner();
         doReturn(callback).when(animationRunner).getCallback();
 
@@ -677,7 +678,7 @@
         @Override
         public void onResult(@Nullable Bundle result) {
             mBackNavigationDone = true;
-            mTriggerBack = result.getBoolean(KEY_TRIGGER_BACK);
+            mTriggerBack = result.getBoolean(KEY_NAVIGATION_FINISHED);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index 48e396a..6be411d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -1222,6 +1222,19 @@
         assertThat(update.bubbleBarLocation).isEqualTo(BubbleBarLocation.LEFT);
     }
 
+    @Test
+    public void setSelectedBubbleAndExpandStack() {
+        sendUpdatedEntryAtTime(mEntryA1, 1000);
+        sendUpdatedEntryAtTime(mEntryA2, 2000);
+        mBubbleData.setListener(mListener);
+
+        mBubbleData.setSelectedBubbleAndExpandStack(mBubbleA1);
+
+        verifyUpdateReceived();
+        assertSelectionChangedTo(mBubbleA1);
+        assertExpandedChangedTo(true);
+    }
+
     private void verifyUpdateReceived() {
         verify(mListener).applyUpdate(mUpdateCaptor.capture());
         reset(mListener);
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 fef81af..afae653 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
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.compatui;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
 import static android.view.WindowInsets.Type.navigationBars;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -34,7 +34,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager.RunningTaskInfo;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.TaskInfo;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -689,7 +689,8 @@
         taskInfo.taskId = taskId;
         taskInfo.displayId = displayId;
         taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
-        taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState;
+        taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
+                cameraCompatControlState;
         taskInfo.isVisible = isVisible;
         taskInfo.isFocused = isFocused;
         taskInfo.isTopActivityTransparent = isTopActivityTransparent;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java
index dd358e7..cd3e8cb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java
@@ -16,10 +16,10 @@
 
 package com.android.wm.shell.compatui;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
@@ -28,7 +28,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.TaskInfo;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
@@ -222,7 +222,8 @@
         ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.taskId = TASK_ID;
         taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
-        taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState;
+        taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
+                cameraCompatControlState;
         taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = 1000;
         taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = 1000;
         taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 0, 2000, 2000));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
index 4f261cd..5209d0e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
@@ -16,10 +16,10 @@
 
 package com.android.wm.shell.compatui;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
 import static android.view.WindowInsets.Type.navigationBars;
 
@@ -37,7 +37,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
-import android.app.AppCompatTaskInfo;
+import android.app.CameraCompatTaskInfo;
 import android.app.TaskInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -521,11 +521,12 @@
     }
 
     private static TaskInfo createTaskInfo(boolean hasSizeCompat,
-            @AppCompatTaskInfo.CameraCompatControlState int cameraCompatControlState) {
+            @CameraCompatTaskInfo.CameraCompatControlState int cameraCompatControlState) {
         ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.taskId = TASK_ID;
         taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
-        taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState;
+        taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
+                cameraCompatControlState;
         taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK;
         // Letterboxed activity that takes half the screen should show size compat restart button
         taskInfo.configuration.windowConfiguration.setBounds(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java
index 38d6ea1..0231612 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayoutTest.java
@@ -16,7 +16,7 @@
 
 package com.android.wm.shell.compatui;
 
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
@@ -25,7 +25,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.testing.AndroidTestingRunner;
@@ -148,7 +148,8 @@
         ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.taskId = TASK_ID;
         taskInfo.appCompatTaskInfo.topActivityInSizeCompat = hasSizeCompat;
-        taskInfo.appCompatTaskInfo.cameraCompatControlState = cameraCompatControlState;
+        taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState =
+                cameraCompatControlState;
         taskInfo.realActivity = new ComponentName("com.mypackage.test", "TestActivity");
         return taskInfo;
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java
index 81ba4b3..94e168e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java
@@ -292,6 +292,24 @@
     }
 
     @Test
+    public void testUserFullscreenOverrideEnabled_buttonAlwaysShown() {
+        TaskInfo taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
+                true, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
+
+        final Rect stableBounds = mWindowManager.getTaskStableBounds();
+
+        // Letterboxed activity that has user fullscreen override should always show button,
+        // layout should be inflated
+        taskInfo.appCompatTaskInfo.topActivityLetterboxHeight = stableBounds.height();
+        taskInfo.appCompatTaskInfo.topActivityLetterboxWidth = stableBounds.width();
+        taskInfo.appCompatTaskInfo.isUserFullscreenOverrideEnabled = true;
+
+        mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true);
+
+        verify(mWindowManager).inflateLayout();
+    }
+
+    @Test
     public void testUpdateDisplayLayout() {
         final DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.logicalWidth = 1000;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
index 0c45d52..dca7be1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
@@ -119,6 +119,57 @@
     }
 
     @Test
+    fun isOnlyActiveTask_noActiveTasks() {
+        // Not an active task
+        assertThat(repo.isOnlyActiveTask(1)).isFalse()
+    }
+
+    @Test
+    fun isOnlyActiveTask_singleActiveTask() {
+        repo.addActiveTask(DEFAULT_DISPLAY, 1)
+        // The only active task
+        assertThat(repo.isActiveTask(1)).isTrue()
+        assertThat(repo.isOnlyActiveTask(1)).isTrue()
+        // Not an active task
+        assertThat(repo.isActiveTask(99)).isFalse()
+        assertThat(repo.isOnlyActiveTask(99)).isFalse()
+    }
+
+    @Test
+    fun isOnlyActiveTask_multipleActiveTasks() {
+        repo.addActiveTask(DEFAULT_DISPLAY, 1)
+        repo.addActiveTask(DEFAULT_DISPLAY, 2)
+        // Not the only task
+        assertThat(repo.isActiveTask(1)).isTrue()
+        assertThat(repo.isOnlyActiveTask(1)).isFalse()
+        // Not the only task
+        assertThat(repo.isActiveTask(2)).isTrue()
+        assertThat(repo.isOnlyActiveTask(2)).isFalse()
+        // Not an active task
+        assertThat(repo.isActiveTask(99)).isFalse()
+        assertThat(repo.isOnlyActiveTask(99)).isFalse()
+    }
+
+    @Test
+    fun isOnlyActiveTask_multipleDisplays() {
+        repo.addActiveTask(DEFAULT_DISPLAY, 1)
+        repo.addActiveTask(DEFAULT_DISPLAY, 2)
+        repo.addActiveTask(SECOND_DISPLAY, 3)
+        // Not the only task on DEFAULT_DISPLAY
+        assertThat(repo.isActiveTask(1)).isTrue()
+        assertThat(repo.isOnlyActiveTask(1)).isFalse()
+        // Not the only task on DEFAULT_DISPLAY
+        assertThat(repo.isActiveTask(2)).isTrue()
+        assertThat(repo.isOnlyActiveTask(2)).isFalse()
+        // The only active task on SECOND_DISPLAY
+        assertThat(repo.isActiveTask(3)).isTrue()
+        assertThat(repo.isOnlyActiveTask(3)).isTrue()
+        // Not an active task
+        assertThat(repo.isActiveTask(99)).isFalse()
+        assertThat(repo.isOnlyActiveTask(99)).isFalse()
+    }
+
+    @Test
     fun addListener_notifiesVisibleFreeformTask() {
         repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
         val listener = TestVisibilityListener()
@@ -432,6 +483,102 @@
         assertThat(repo.removeBoundsBeforeMaximize(taskId)).isNull()
     }
 
+    @Test
+    fun minimizeTaskNotCalled_noTasksMinimized() {
+        assertThat(repo.isMinimizedTask(taskId = 0)).isFalse()
+        assertThat(repo.isMinimizedTask(taskId = 1)).isFalse()
+    }
+
+    @Test
+    fun minimizeTask_onlyThatTaskIsMinimized() {
+        repo.minimizeTask(displayId = 0, taskId = 0)
+
+        assertThat(repo.isMinimizedTask(taskId = 0)).isTrue()
+        assertThat(repo.isMinimizedTask(taskId = 1)).isFalse()
+        assertThat(repo.isMinimizedTask(taskId = 2)).isFalse()
+    }
+
+    @Test
+    fun unminimizeTask_taskNoLongerMinimized() {
+        repo.minimizeTask(displayId = 0, taskId = 0)
+        repo.unminimizeTask(displayId = 0, taskId = 0)
+
+        assertThat(repo.isMinimizedTask(taskId = 0)).isFalse()
+        assertThat(repo.isMinimizedTask(taskId = 1)).isFalse()
+        assertThat(repo.isMinimizedTask(taskId = 2)).isFalse()
+    }
+
+    @Test
+    fun unminimizeTask_nonExistentTask_doesntCrash() {
+        repo.unminimizeTask(displayId = 0, taskId = 0)
+
+        assertThat(repo.isMinimizedTask(taskId = 0)).isFalse()
+        assertThat(repo.isMinimizedTask(taskId = 1)).isFalse()
+        assertThat(repo.isMinimizedTask(taskId = 2)).isFalse()
+    }
+
+
+    @Test
+    fun updateVisibleFreeformTasks_toVisible_taskIsUnminimized() {
+        repo.minimizeTask(displayId = 10, taskId = 2)
+
+        repo.updateVisibleFreeformTasks(displayId = 10, taskId = 2, visible = true)
+
+        assertThat(repo.isMinimizedTask(taskId = 2)).isFalse()
+    }
+
+    @Test
+    fun isDesktopModeShowing_noActiveTasks_returnsFalse() {
+        assertThat(repo.isDesktopModeShowing(displayId = 0)).isFalse()
+    }
+
+    @Test
+    fun isDesktopModeShowing_noTasksVisible_returnsFalse() {
+        repo.addActiveTask(displayId = 0, taskId = 1)
+        repo.addActiveTask(displayId = 0, taskId = 2)
+
+        assertThat(repo.isDesktopModeShowing(displayId = 0)).isFalse()
+    }
+
+    @Test
+    fun isDesktopModeShowing_tasksActiveAndVisible_returnsTrue() {
+        repo.addActiveTask(displayId = 0, taskId = 1)
+        repo.addActiveTask(displayId = 0, taskId = 2)
+        repo.updateVisibleFreeformTasks(displayId = 0, taskId = 1, visible = true)
+
+        assertThat(repo.isDesktopModeShowing(displayId = 0)).isTrue()
+    }
+
+    @Test
+    fun getActiveNonMinimizedTasksOrderedFrontToBack_returnsFreeformTasksInCorrectOrder() {
+        repo.addActiveTask(displayId = 0, taskId = 1)
+        repo.addActiveTask(displayId = 0, taskId = 2)
+        repo.addActiveTask(displayId = 0, taskId = 3)
+        // The front-most task will be the one added last through addOrMoveFreeformTaskToTop
+        repo.addOrMoveFreeformTaskToTop(taskId = 3)
+        repo.addOrMoveFreeformTaskToTop(taskId = 2)
+        repo.addOrMoveFreeformTaskToTop(taskId = 1)
+
+        assertThat(repo.getActiveNonMinimizedTasksOrderedFrontToBack(displayId = 0)).isEqualTo(
+                listOf(1, 2, 3))
+    }
+
+    @Test
+    fun getActiveNonMinimizedTasksOrderedFrontToBack_minimizedTaskNotIncluded() {
+        repo.addActiveTask(displayId = 0, taskId = 1)
+        repo.addActiveTask(displayId = 0, taskId = 2)
+        repo.addActiveTask(displayId = 0, taskId = 3)
+        // The front-most task will be the one added last through addOrMoveFreeformTaskToTop
+        repo.addOrMoveFreeformTaskToTop(taskId = 3)
+        repo.addOrMoveFreeformTaskToTop(taskId = 2)
+        repo.addOrMoveFreeformTaskToTop(taskId = 1)
+        repo.minimizeTask(displayId = 0, taskId = 2)
+
+        assertThat(repo.getActiveNonMinimizedTasksOrderedFrontToBack(displayId = 0)).isEqualTo(
+                listOf(1, 3))
+    }
+
+
     class TestListener : DesktopModeTaskRepository.ActiveTasksListener {
         var activeChangesOnDefaultDisplay = 0
         var activeChangesOnSecondaryDisplay = 0
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 93a967e..ad4b720 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -23,10 +23,13 @@
 import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
 import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
 import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
+import android.content.Intent
 import android.graphics.Point
 import android.graphics.PointF
 import android.graphics.Rect
 import android.os.Binder
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.platform.test.flag.junit.SetFlagsRule
 import android.testing.AndroidTestingRunner
 import android.view.Display.DEFAULT_DISPLAY
@@ -34,11 +37,15 @@
 import android.view.WindowManager
 import android.view.WindowManager.TRANSIT_CHANGE
 import android.view.WindowManager.TRANSIT_OPEN
+import android.view.WindowManager.TRANSIT_TO_BACK
 import android.view.WindowManager.TRANSIT_TO_FRONT
 import android.window.DisplayAreaInfo
 import android.window.RemoteTransition
 import android.window.TransitionRequestInfo
+import android.window.WindowContainerToken
 import android.window.WindowContainerTransaction
+import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT
+import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK
 import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
 import androidx.test.filters.SmallTest
 import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
@@ -98,6 +105,7 @@
 import org.mockito.kotlin.atLeastOnce
 import org.mockito.kotlin.capture
 import org.mockito.quality.Strictness
+import java.util.Optional
 import org.mockito.Mockito.`when` as whenever
 
 /**
@@ -138,6 +146,7 @@
     private lateinit var controller: DesktopTasksController
     private lateinit var shellInit: ShellInit
     private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
+    private lateinit var desktopTasksLimiter: DesktopTasksLimiter
     private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
 
     private val shellExecutor = TestShellExecutor()
@@ -153,14 +162,21 @@
 
         shellInit = Mockito.spy(ShellInit(testExecutor))
         desktopModeTaskRepository = DesktopModeTaskRepository()
+        desktopTasksLimiter =
+                DesktopTasksLimiter(transitions, desktopModeTaskRepository, shellTaskOrganizer)
 
         whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks }
         whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() }
+        whenever(enterDesktopTransitionHandler.moveToDesktop(any())).thenAnswer { Binder() }
         whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
         whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
                 (i.arguments.first() as Rect).set(STABLE_BOUNDS)
             }
 
+        val tda = DisplayAreaInfo(MockToken().token(), DEFAULT_DISPLAY, 0)
+        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
+        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(tda)
+
         controller = createController()
         controller.setSplitScreenController(splitScreenController)
 
@@ -192,7 +208,8 @@
             launchAdjacentController,
             recentsTransitionHandler,
             multiInstanceHelper,
-            shellExecutor
+            shellExecutor,
+            Optional.of(desktopTasksLimiter),
         )
     }
 
@@ -219,7 +236,8 @@
     }
 
     @Test
-    fun showDesktopApps_allAppsInvisible_bringsToFront() {
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_allAppsInvisible_bringsToFront_desktopWallpaperDisabled() {
         val homeTask = setUpHomeTask()
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
@@ -238,7 +256,27 @@
     }
 
     @Test
-    fun showDesktopApps_appsAlreadyVisible_bringsToFront() {
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_allAppsInvisible_bringsToFront_desktopWallpaperEnabled() {
+        val task1 = setUpFreeformTask()
+        val task2 = setUpFreeformTask()
+        markTaskHidden(task1)
+        markTaskHidden(task2)
+
+        controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
+
+        val wct =
+            getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
+        assertThat(wct.hierarchyOps).hasSize(3)
+        // Expect order to be from bottom: wallpaper intent, task1, task2
+        wct.assertPendingIntentAt(index = 0, desktopWallpaperIntent)
+        wct.assertReorderAt(index = 1, task1)
+        wct.assertReorderAt(index = 2, task2)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_appsAlreadyVisible_bringsToFront_desktopWallpaperDisabled() {
         val homeTask = setUpHomeTask()
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
@@ -257,7 +295,27 @@
     }
 
     @Test
-    fun showDesktopApps_someAppsInvisible_reordersAll() {
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_appsAlreadyVisible_bringsToFront_desktopWallpaperEnabled() {
+        val task1 = setUpFreeformTask()
+        val task2 = setUpFreeformTask()
+        markTaskVisible(task1)
+        markTaskVisible(task2)
+
+        controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
+
+        val wct =
+            getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
+        assertThat(wct.hierarchyOps).hasSize(3)
+        // Expect order to be from bottom: wallpaper intent, task1, task2
+        wct.assertPendingIntentAt(index = 0, desktopWallpaperIntent)
+        wct.assertReorderAt(index = 1, task1)
+        wct.assertReorderAt(index = 2, task2)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_someAppsInvisible_reordersAll_desktopWallpaperDisabled() {
         val homeTask = setUpHomeTask()
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
@@ -276,7 +334,27 @@
     }
 
     @Test
-    fun showDesktopApps_noActiveTasks_reorderHomeToTop() {
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_someAppsInvisible_reordersAll_desktopWallpaperEnabled() {
+        val task1 = setUpFreeformTask()
+        val task2 = setUpFreeformTask()
+        markTaskHidden(task1)
+        markTaskVisible(task2)
+
+        controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
+
+        val wct =
+            getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
+        assertThat(wct.hierarchyOps).hasSize(3)
+        // Expect order to be from bottom: wallpaper intent, task1, task2
+        wct.assertPendingIntentAt(index = 0, desktopWallpaperIntent)
+        wct.assertReorderAt(index = 1, task1)
+        wct.assertReorderAt(index = 2, task2)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_noActiveTasks_reorderHomeToTop_desktopWallpaperDisabled() {
         val homeTask = setUpHomeTask()
 
         controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
@@ -288,7 +366,18 @@
     }
 
     @Test
-    fun showDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay() {
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_noActiveTasks_addDesktopWallpaper_desktopWallpaperEnabled() {
+        controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
+
+        val wct =
+            getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
+        wct.assertPendingIntentAt(index = 0, desktopWallpaperIntent)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay_desktopWallpaperDisabled() {
         val homeTaskDefaultDisplay = setUpHomeTask(DEFAULT_DISPLAY)
         val taskDefaultDisplay = setUpFreeformTask(DEFAULT_DISPLAY)
         setUpHomeTask(SECOND_DISPLAY)
@@ -307,6 +396,44 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun showDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay_desktopWallpaperEnabled() {
+        val taskDefaultDisplay = setUpFreeformTask(DEFAULT_DISPLAY)
+        setUpHomeTask(SECOND_DISPLAY)
+        val taskSecondDisplay = setUpFreeformTask(SECOND_DISPLAY)
+        markTaskHidden(taskDefaultDisplay)
+        markTaskHidden(taskSecondDisplay)
+
+        controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
+
+        val wct =
+            getLatestWct(type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
+        assertThat(wct.hierarchyOps).hasSize(2)
+        // Expect order to be from bottom: wallpaper intent, task
+        wct.assertPendingIntentAt(index = 0, desktopWallpaperIntent)
+        wct.assertReorderAt(index = 1, taskDefaultDisplay)
+    }
+
+    @Test
+    fun showDesktopApps_dontReorderMinimizedTask() {
+        val homeTask = setUpHomeTask()
+        val freeformTask = setUpFreeformTask()
+        val minimizedTask = setUpFreeformTask()
+        markTaskHidden(freeformTask)
+        markTaskHidden(minimizedTask)
+        desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, minimizedTask.taskId)
+
+        controller.showDesktopApps(DEFAULT_DISPLAY, RemoteTransition(TestRemoteTransition()))
+
+        val wct = getLatestWct(
+                type = TRANSIT_TO_FRONT, handlerClass = OneShotRemoteHandler::class.java)
+        assertThat(wct.hierarchyOps).hasSize(2)
+        // Reorder home and freeform task to top, don't reorder the minimized task
+        wct.assertReorderAt(index = 0, homeTask, toTop = true)
+        wct.assertReorderAt(index = 1, freeformTask, toTop = true)
+    }
+
+    @Test
     fun getVisibleTaskCount_noTasks_returnsZero() {
         assertThat(controller.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
     }
@@ -336,9 +463,10 @@
     }
 
     @Test
-    fun moveToDesktop_displayFullscreen_windowingModeSetToFreeform() {
+    fun moveToDesktop_tdaFullscreen_windowingModeSetToFreeform() {
         val task = setUpFullscreenTask()
-        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FULLSCREEN
+        val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
+        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
         controller.moveToDesktop(task)
         val wct = getLatestMoveToDesktopWct()
         assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -346,9 +474,10 @@
     }
 
     @Test
-    fun moveToDesktop_displayFreeform_windowingModeSetToUndefined() {
+    fun moveToDesktop_tdaFreeform_windowingModeSetToUndefined() {
         val task = setUpFullscreenTask()
-        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FREEFORM
+        val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
+        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
         controller.moveToDesktop(task)
         val wct = getLatestMoveToDesktopWct()
         assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -413,7 +542,8 @@
     }
 
     @Test
-    fun moveToDesktop_otherFreeformTasksBroughtToFront() {
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun moveToDesktop_otherFreeformTasksBroughtToFront_desktopWallpaperDisabled() {
         val homeTask = setUpHomeTask()
         val freeformTask = setUpFreeformTask()
         val fullscreenTask = setUpFullscreenTask()
@@ -431,6 +561,26 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun moveToDesktop_otherFreeformTasksBroughtToFront_desktopWallpaperEnabled() {
+        val freeformTask = setUpFreeformTask()
+        val fullscreenTask = setUpFullscreenTask()
+        markTaskHidden(freeformTask)
+
+        controller.moveToDesktop(fullscreenTask)
+
+        with(getLatestMoveToDesktopWct()) {
+            // Operations should include wallpaper intent, freeform task, fullscreen task
+            assertThat(hierarchyOps).hasSize(3)
+            assertPendingIntentAt(index = 0, desktopWallpaperIntent)
+            assertReorderAt(index = 1, freeformTask)
+            assertReorderAt(index = 2, fullscreenTask)
+            assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode)
+                .isEqualTo(WINDOWING_MODE_FREEFORM)
+        }
+    }
+
+    @Test
     fun moveToDesktop_onlyFreeformTasksFromCurrentDisplayBroughtToFront() {
         setUpHomeTask(displayId = DEFAULT_DISPLAY)
         val freeformTaskDefault = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
@@ -481,9 +631,28 @@
     }
 
     @Test
-    fun moveToFullscreen_displayFullscreen_windowingModeSetToUndefined() {
+    fun moveToDesktop_bringsTasksOverLimit_dontShowBackTask() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val homeTask = setUpHomeTask()
+        val freeformTasks = (1..taskLimit).map { _ -> setUpFreeformTask() }
+        val newTask = setUpFullscreenTask()
+
+        controller.moveToDesktop(newTask)
+
+        val wct = getLatestMoveToDesktopWct()
+        assertThat(wct.hierarchyOps.size).isEqualTo(taskLimit + 1) // visible tasks + home
+        wct.assertReorderAt(0, homeTask)
+        for (i in 1..<taskLimit) { // Skipping freeformTasks[0]
+            wct.assertReorderAt(index = i, task = freeformTasks[i])
+        }
+        wct.assertReorderAt(taskLimit, newTask)
+    }
+
+    @Test
+    fun moveToFullscreen_tdaFullscreen_windowingModeSetToUndefined() {
         val task = setUpFreeformTask()
-        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FULLSCREEN
+        val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
+        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
         controller.moveToFullscreen(task.taskId)
         val wct = getLatestExitDesktopWct()
         assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -491,9 +660,10 @@
     }
 
     @Test
-    fun moveToFullscreen_displayFreeform_windowingModeSetToFullscreen() {
+    fun moveToFullscreen_tdaFreeform_windowingModeSetToFullscreen() {
         val task = setUpFreeformTask()
-        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FREEFORM
+        val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
+        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
         controller.moveToFullscreen(task.taskId)
         val wct = getLatestExitDesktopWct()
         assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -532,6 +702,20 @@
     }
 
     @Test
+    fun moveTaskToFront_bringsTasksOverLimit_minimizesBackTask() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        setUpHomeTask()
+        val freeformTasks = (1..taskLimit + 1).map { _ -> setUpFreeformTask() }
+
+        controller.moveTaskToFront(freeformTasks[0])
+
+        val wct = getLatestWct(type = TRANSIT_TO_FRONT)
+        assertThat(wct.hierarchyOps.size).isEqualTo(2) // move-to-front + minimize
+        wct.assertReorderAt(0, freeformTasks[0], toTop = true)
+        wct.assertReorderAt(1, freeformTasks[1], toTop = false)
+    }
+
+    @Test
     fun moveToNextDisplay_noOtherDisplays() {
         whenever(rootTaskDisplayAreaOrganizer.displayIds).thenReturn(intArrayOf(DEFAULT_DISPLAY))
         val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
@@ -595,6 +779,48 @@
     }
 
     @Test
+    fun onDesktopWindowClose_noActiveTasks() {
+        val wct = WindowContainerTransaction()
+        controller.onDesktopWindowClose(wct, 1 /* taskId */)
+        // Doesn't modify transaction
+        assertThat(wct.hierarchyOps).isEmpty()
+    }
+
+    @Test
+    fun onDesktopWindowClose_singleActiveTask_noWallpaperActivityToken() {
+        val task = setUpFreeformTask()
+        val wct = WindowContainerTransaction()
+        controller.onDesktopWindowClose(wct, task.taskId)
+        // Doesn't modify transaction
+        assertThat(wct.hierarchyOps).isEmpty()
+    }
+
+    @Test
+    fun onDesktopWindowClose_singleActiveTask_hasWallpaperActivityToken() {
+        val task = setUpFreeformTask()
+        val wallpaperToken = MockToken().token()
+        desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+
+        val wct = WindowContainerTransaction()
+        controller.onDesktopWindowClose(wct, task.taskId)
+        // Adds remove wallpaper operation
+        wct.assertRemoveAt(index = 0, wallpaperToken)
+    }
+
+    @Test
+    fun onDesktopWindowClose_multipleActiveTasks() {
+        val task1 = setUpFreeformTask()
+        setUpFreeformTask()
+        val wallpaperToken = MockToken().token()
+        desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+
+        val wct = WindowContainerTransaction()
+        controller.onDesktopWindowClose(wct, task1.taskId)
+        // Doesn't modify transaction
+        assertThat(wct.hierarchyOps).isEmpty()
+    }
+
+    @Test
     fun handleRequest_fullscreenTask_freeformVisible_returnSwitchToFreeformWCT() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
 
@@ -608,6 +834,38 @@
     }
 
     @Test
+    fun handleRequest_fullscreenTaskToFreeform_underTaskLimit_dontMinimize() {
+        assumeTrue(ENABLE_SHELL_TRANSITIONS)
+
+        val freeformTask = setUpFreeformTask()
+        markTaskVisible(freeformTask)
+        val fullscreenTask = createFullscreenTask()
+
+        val wct = controller.handleRequest(Binder(), createTransition(fullscreenTask))
+
+        // Make sure we only reorder the new task to top (we don't reorder the old task to bottom)
+        assertThat(wct?.hierarchyOps?.size).isEqualTo(1)
+        wct!!.assertReorderAt(0, fullscreenTask, toTop = true)
+    }
+
+    @Test
+    fun handleRequest_fullscreenTaskToFreeform_bringsTasksOverLimit_otherTaskIsMinimized() {
+        assumeTrue(ENABLE_SHELL_TRANSITIONS)
+
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val freeformTasks = (1..taskLimit).map { _ -> setUpFreeformTask() }
+        freeformTasks.forEach { markTaskVisible(it) }
+        val fullscreenTask = createFullscreenTask()
+
+        val wct = controller.handleRequest(Binder(), createTransition(fullscreenTask))
+
+        // Make sure we reorder the new task to top, and the back task to the bottom
+        assertThat(wct!!.hierarchyOps.size).isEqualTo(2)
+        wct!!.assertReorderAt(0, fullscreenTask, toTop = true)
+        wct!!.assertReorderAt(1, freeformTasks[0], toTop = false)
+    }
+
+    @Test
     fun handleRequest_fullscreenTask_freeformNotVisible_returnNull() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
 
@@ -638,6 +896,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
     fun handleRequest_fullscreenTask_desktopStashed_returnWCTWithAllAppsBroughtToFront() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
         whenever(DesktopModeStatus.isStashingEnabled()).thenReturn(true)
@@ -671,6 +930,22 @@
     }
 
     @Test
+    fun handleRequest_freeformTask_freeformVisible_aboveTaskLimit_minimize() {
+        assumeTrue(ENABLE_SHELL_TRANSITIONS)
+
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val freeformTasks = (1..taskLimit).map { _ -> setUpFreeformTask() }
+        freeformTasks.forEach { markTaskVisible(it) }
+        val newFreeformTask = createFreeformTask()
+
+        val wct =
+                controller.handleRequest(Binder(), createTransition(newFreeformTask, TRANSIT_OPEN))
+
+        assertThat(wct?.hierarchyOps?.size).isEqualTo(1)
+        wct!!.assertReorderAt(0, freeformTasks[0], toTop = false) // Reorder to the bottom
+    }
+
+    @Test
     fun handleRequest_freeformTask_freeformNotVisible_returnSwitchToFullscreenWCT() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
 
@@ -684,7 +959,7 @@
                 createTransition(freeformTask2, type = TRANSIT_TO_FRONT)
             )
         assertThat(result?.changes?.get(freeformTask2.token.asBinder())?.windowingMode)
-            .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+            .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
     }
 
     @Test
@@ -694,7 +969,7 @@
         val task = createFreeformTask()
         val result = controller.handleRequest(Binder(), createTransition(task))
         assertThat(result?.changes?.get(task.token.asBinder())?.windowingMode)
-            .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+            .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
     }
 
     @Test
@@ -706,10 +981,11 @@
 
         val result = controller.handleRequest(Binder(), createTransition(taskDefaultDisplay))
         assertThat(result?.changes?.get(taskDefaultDisplay.token.asBinder())?.windowingMode)
-            .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+            .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
     fun handleRequest_freeformTask_desktopStashed_returnWCTWithAllAppsBroughtToFront() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
         whenever(DesktopModeStatus.isStashingEnabled()).thenReturn(true)
@@ -792,7 +1068,56 @@
 
         val result = controller.handleRequest(Binder(), createTransition(task))
         assertThat(result?.changes?.get(task.token.asBinder())?.windowingMode)
-                .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+                .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun handleRequest_backTransition_singleActiveTask_noToken() {
+        val task = setUpFreeformTask()
+        val result =
+            controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
+        // Doesn't handle request
+        assertThat(result).isNull()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun handleRequest_backTransition_singleActiveTask_hasToken_desktopWallpaperDisabled() {
+        desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+
+        val task = setUpFreeformTask()
+        val result =
+            controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
+        // Doesn't handle request
+        assertThat(result).isNull()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun handleRequest_backTransition_singleActiveTask_hasToken_desktopWallpaperEnabled() {
+        val wallpaperToken = MockToken().token()
+        desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+
+        val task = setUpFreeformTask()
+        val result =
+            controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
+        assertThat(result).isNotNull()
+        // Creates remove wallpaper transaction
+        result!!.assertRemoveAt(index = 0, wallpaperToken)
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    fun handleRequest_backTransition_multipleActiveTasks() {
+        desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+
+        val task1 = setUpFreeformTask()
+        setUpFreeformTask()
+        val result =
+            controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
+        // Doesn't handle request
+        assertThat(result).isNull()
     }
 
     @Test
@@ -895,7 +1220,7 @@
 
         val wct = getLatestExitDesktopWct()
         assertThat(wct.changes[task2.token.asBinder()]?.windowingMode)
-                .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+                .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
     }
 
     @Test
@@ -998,6 +1323,9 @@
         assertThat(desktopModeTaskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull()
     }
 
+    private val desktopWallpaperIntent: Intent
+        get() = Intent(context, DesktopWallpaperActivity::class.java)
+
     private fun setUpFreeformTask(
             displayId: Int = DEFAULT_DISPLAY,
             bounds: Rect? = null
@@ -1123,13 +1451,22 @@
     }
 }
 
-private fun WindowContainerTransaction.assertReorderAt(index: Int, task: RunningTaskInfo) {
+private fun WindowContainerTransaction.assertIndexInBounds(index: Int) {
     assertWithMessage("WCT does not have a hierarchy operation at index $index")
         .that(hierarchyOps.size)
         .isGreaterThan(index)
+}
+
+private fun WindowContainerTransaction.assertReorderAt(
+        index: Int,
+        task: RunningTaskInfo,
+        toTop: Boolean? = null
+) {
+    assertIndexInBounds(index)
     val op = hierarchyOps[index]
     assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REORDER)
     assertThat(op.container).isEqualTo(task.token.asBinder())
+    toTop?.let { assertThat(op.toTop).isEqualTo(it) }
 }
 
 private fun WindowContainerTransaction.assertReorderSequence(vararg tasks: RunningTaskInfo) {
@@ -1137,3 +1474,17 @@
         assertReorderAt(i, tasks[i])
     }
 }
+
+private fun WindowContainerTransaction.assertRemoveAt(index: Int, token: WindowContainerToken) {
+    assertIndexInBounds(index)
+    val op = hierarchyOps[index]
+    assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REMOVE_TASK)
+    assertThat(op.container).isEqualTo(token.asBinder())
+}
+
+private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent: Intent) {
+    assertIndexInBounds(index)
+    val op = hierarchyOps[index]
+    assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_PENDING_INTENT)
+    assertThat(op.pendingIntent?.intent?.component).isEqualTo(intent.component)
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
new file mode 100644
index 0000000..38ea034
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.os.Binder
+import android.platform.test.flag.junit.SetFlagsRule
+import android.testing.AndroidTestingRunner
+import android.view.Display.DEFAULT_DISPLAY
+import android.view.WindowManager.TRANSIT_OPEN
+import android.view.WindowManager.TRANSIT_TO_BACK
+import android.window.WindowContainerTransaction
+import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
+import com.android.wm.shell.transition.TransitionInfoBuilder
+import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.util.StubTransaction
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.quality.Strictness
+
+
+/**
+ * Test class for {@link DesktopTasksLimiter}
+ *
+ * Usage: atest WMShellUnitTests:DesktopTasksLimiterTest
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class DesktopTasksLimiterTest : ShellTestCase() {
+
+    @JvmField
+    @Rule
+    val setFlagsRule = SetFlagsRule()
+
+    @Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer
+    @Mock lateinit var transitions: Transitions
+
+    private lateinit var mockitoSession: StaticMockitoSession
+    private lateinit var desktopTasksLimiter: DesktopTasksLimiter
+    private lateinit var desktopTaskRepo: DesktopModeTaskRepository
+
+    @Before
+    fun setUp() {
+        mockitoSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
+                .spyStatic(DesktopModeStatus::class.java).startMocking()
+        `when`(DesktopModeStatus.isEnabled()).thenReturn(true)
+
+        desktopTaskRepo = DesktopModeTaskRepository()
+
+        desktopTasksLimiter = DesktopTasksLimiter(
+                transitions, desktopTaskRepo, shellTaskOrganizer)
+    }
+
+    @After
+    fun tearDown() {
+        mockitoSession.finishMocking()
+    }
+
+    // Currently, the task limit can be overridden through an adb flag. This test ensures the limit
+    // hasn't been overridden.
+    @Test
+    fun getMaxTaskLimit_isSameAsConstant() {
+        assertThat(desktopTasksLimiter.getMaxTaskLimit()).isEqualTo(
+            DesktopModeStatus.DEFAULT_MAX_TASK_LIMIT)
+    }
+
+    @Test
+    fun addPendingMinimizeTransition_taskIsNotMinimized() {
+        val task = setUpFreeformTask()
+        markTaskHidden(task)
+
+        desktopTasksLimiter.addPendingMinimizeChange(Binder(), displayId = 1, taskId = task.taskId)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isFalse()
+    }
+
+    @Test
+    fun onTransitionReady_noPendingTransition_taskIsNotMinimized() {
+        val task = setUpFreeformTask()
+        markTaskHidden(task)
+
+        desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+                Binder() /* transition */,
+                TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
+                StubTransaction() /* startTransaction */,
+                StubTransaction() /* finishTransaction */)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isFalse()
+    }
+
+    @Test
+    fun onTransitionReady_differentPendingTransition_taskIsNotMinimized() {
+        val pendingTransition = Binder()
+        val taskTransition = Binder()
+        val task = setUpFreeformTask()
+        markTaskHidden(task)
+        desktopTasksLimiter.addPendingMinimizeChange(
+            pendingTransition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+        desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+            taskTransition /* transition */,
+            TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
+            StubTransaction() /* startTransaction */,
+            StubTransaction() /* finishTransaction */)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isFalse()
+    }
+
+    @Test
+    fun onTransitionReady_pendingTransition_noTaskChange_taskVisible_taskIsNotMinimized() {
+        val transition = Binder()
+        val task = setUpFreeformTask()
+        markTaskVisible(task)
+        desktopTasksLimiter.addPendingMinimizeChange(
+                transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+        desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+                transition,
+                TransitionInfoBuilder(TRANSIT_OPEN).build(),
+                StubTransaction() /* startTransaction */,
+                StubTransaction() /* finishTransaction */)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isFalse()
+    }
+
+    @Test
+    fun onTransitionReady_pendingTransition_noTaskChange_taskInvisible_taskIsMinimized() {
+        val transition = Binder()
+        val task = setUpFreeformTask()
+        markTaskHidden(task)
+        desktopTasksLimiter.addPendingMinimizeChange(
+                transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+        desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+                transition,
+                TransitionInfoBuilder(TRANSIT_OPEN).build(),
+                StubTransaction() /* startTransaction */,
+                StubTransaction() /* finishTransaction */)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isTrue()
+    }
+
+    @Test
+    fun onTransitionReady_pendingTransition_changeTaskToBack_taskIsMinimized() {
+        val transition = Binder()
+        val task = setUpFreeformTask()
+        desktopTasksLimiter.addPendingMinimizeChange(
+                transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+
+        desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+                transition,
+                TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
+                StubTransaction() /* startTransaction */,
+                StubTransaction() /* finishTransaction */)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isTrue()
+    }
+
+    @Test
+    fun onTransitionReady_transitionMergedFromPending_taskIsMinimized() {
+        val mergedTransition = Binder()
+        val newTransition = Binder()
+        val task = setUpFreeformTask()
+        desktopTasksLimiter.addPendingMinimizeChange(
+            mergedTransition, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+        desktopTasksLimiter.getTransitionObserver().onTransitionMerged(
+            mergedTransition, newTransition)
+
+        desktopTasksLimiter.getTransitionObserver().onTransitionReady(
+            newTransition,
+            TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
+            StubTransaction() /* startTransaction */,
+            StubTransaction() /* finishTransaction */)
+
+        assertThat(desktopTaskRepo.isMinimizedTask(taskId = task.taskId)).isTrue()
+    }
+
+    @Test
+    fun addAndGetMinimizeTaskChangesIfNeeded_tasksWithinLimit_noTaskMinimized() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        (1..<taskLimit).forEach { _ -> setUpFreeformTask() }
+
+        val wct = WindowContainerTransaction()
+        val minimizedTaskId =
+                desktopTasksLimiter.addAndGetMinimizeTaskChangesIfNeeded(
+                        displayId = DEFAULT_DISPLAY,
+                        wct = wct,
+                        newFrontTaskInfo = setUpFreeformTask())
+
+        assertThat(minimizedTaskId).isNull()
+        assertThat(wct.hierarchyOps).isEmpty() // No reordering operations added
+    }
+
+    @Test
+    fun addAndGetMinimizeTaskChangesIfNeeded_tasksAboveLimit_backTaskMinimized() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        // The following list will be ordered bottom -> top, as the last task is moved to top last.
+        val tasks = (1..taskLimit).map { setUpFreeformTask() }
+
+        val wct = WindowContainerTransaction()
+        val minimizedTaskId =
+                desktopTasksLimiter.addAndGetMinimizeTaskChangesIfNeeded(
+                        displayId = DEFAULT_DISPLAY,
+                        wct = wct,
+                        newFrontTaskInfo = setUpFreeformTask())
+
+        assertThat(minimizedTaskId).isEqualTo(tasks.first())
+        assertThat(wct.hierarchyOps.size).isEqualTo(1)
+        assertThat(wct.hierarchyOps[0].type).isEqualTo(HIERARCHY_OP_TYPE_REORDER)
+        assertThat(wct.hierarchyOps[0].toTop).isFalse() // Reorder to bottom
+    }
+
+    @Test
+    fun addAndGetMinimizeTaskChangesIfNeeded_nonMinimizedTasksWithinLimit_noTaskMinimized() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val tasks = (1..taskLimit).map { setUpFreeformTask() }
+        desktopTaskRepo.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = tasks[0].taskId)
+
+        val wct = WindowContainerTransaction()
+        val minimizedTaskId =
+                desktopTasksLimiter.addAndGetMinimizeTaskChangesIfNeeded(
+                        displayId = 0,
+                        wct = wct,
+                        newFrontTaskInfo = setUpFreeformTask())
+
+        assertThat(minimizedTaskId).isNull()
+        assertThat(wct.hierarchyOps).isEmpty() // No reordering operations added
+    }
+
+    @Test
+    fun getTaskToMinimizeIfNeeded_tasksWithinLimit_returnsNull() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val tasks = (1..taskLimit).map { setUpFreeformTask() }
+
+        val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded(
+                visibleFreeformTaskIdsOrderedFrontToBack = tasks.map { it.taskId })
+
+        assertThat(minimizedTask).isNull()
+    }
+
+    @Test
+    fun getTaskToMinimizeIfNeeded_tasksAboveLimit_returnsBackTask() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val tasks = (1..taskLimit + 1).map { setUpFreeformTask() }
+
+        val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded(
+                visibleFreeformTaskIdsOrderedFrontToBack = tasks.map { it.taskId })
+
+        // first == front, last == back
+        assertThat(minimizedTask).isEqualTo(tasks.last())
+    }
+
+    @Test
+    fun getTaskToMinimizeIfNeeded_withNewTask_tasksAboveLimit_returnsBackTask() {
+        val taskLimit = desktopTasksLimiter.getMaxTaskLimit()
+        val tasks = (1..taskLimit).map { setUpFreeformTask() }
+
+        val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded(
+                visibleFreeformTaskIdsOrderedFrontToBack = tasks.map { it.taskId },
+                newTaskIdInFront = setUpFreeformTask().taskId)
+
+        // first == front, last == back
+        assertThat(minimizedTask).isEqualTo(tasks.last())
+    }
+
+    private fun setUpFreeformTask(
+            displayId: Int = DEFAULT_DISPLAY,
+    ): RunningTaskInfo {
+        val task = createFreeformTask(displayId)
+        `when`(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
+        desktopTaskRepo.addActiveTask(displayId, task.taskId)
+        desktopTaskRepo.addOrMoveFreeformTaskToTop(task.taskId)
+        return task
+    }
+
+    private fun markTaskVisible(task: RunningTaskInfo) {
+        desktopTaskRepo.updateVisibleFreeformTasks(
+                task.displayId,
+                task.taskId,
+                visible = true
+        )
+    }
+
+    private fun markTaskHidden(task: RunningTaskInfo) {
+        desktopTaskRepo.updateVisibleFreeformTasks(
+                task.displayId,
+                task.taskId,
+                visible = false
+        )
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java
index 3d5cd69..85f1da5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java
@@ -16,33 +16,26 @@
 
 package com.android.wm.shell.pip.phone;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.os.SystemProperties;
 import android.testing.AndroidTestingRunner;
 import android.util.Size;
 import android.view.DisplayInfo;
 
-import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.pip.PhoneSizeSpecSource;
 import com.android.wm.shell.common.pip.PipDisplayLayoutState;
 import com.android.wm.shell.common.pip.SizeSpecSource;
 
-import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -63,15 +56,24 @@
     private static final float DEFAULT_PERCENT = 0.6f;
     /** Minimum sizing percentage */
     private static final float MIN_PERCENT = 0.5f;
+    /** Threshold to determine if a Display is square-ish. */
+    private static final float SQUARE_DISPLAY_THRESHOLD = 0.95f;
+    /** Default sizing percentage for square-ish Display. */
+    private static final float SQUARE_DISPLAY_DEFAULT_PERCENT = 0.5f;
+    /** Minimum sizing percentage for square-ish Display. */
+    private static final float SQUARE_DISPLAY_MIN_PERCENT = 0.4f;
     /** Aspect ratio that the new PIP size spec logic optimizes for. */
     private static final float OPTIMIZED_ASPECT_RATIO = 9f / 16;
 
-    /** A map of aspect ratios to be tested to expected sizes */
-    private static Map<Float, Size> sExpectedMaxSizes;
-    private static Map<Float, Size> sExpectedDefaultSizes;
-    private static Map<Float, Size> sExpectedMinSizes;
-    /** A static mockito session object to mock {@link SystemProperties} */
-    private static StaticMockitoSession sStaticMockitoSession;
+    /** Maps of aspect ratios to be tested to expected sizes on non-square Display. */
+    private static Map<Float, Size> sNonSquareDisplayExpectedMaxSizes;
+    private static Map<Float, Size> sNonSquareDisplayExpectedDefaultSizes;
+    private static Map<Float, Size> sNonSquareDisplayExpectedMinSizes;
+
+    /** Maps of aspect ratios to be tested to expected sizes on square Display. */
+    private static Map<Float, Size> sSquareDisplayExpectedMaxSizes;
+    private static Map<Float, Size> sSquareDisplayExpectedDefaultSizes;
+    private static Map<Float, Size> sSquareDisplayExpectedMinSizes;
 
     @Mock private Context mContext;
     @Mock private Resources mResources;
@@ -80,49 +82,55 @@
     private SizeSpecSource mSizeSpecSource;
 
     /**
-     * Sets up static Mockito session for SystemProperties and mocks necessary static methods.
+     * Initializes the map with the aspect ratios to be tested and corresponding expected max sizes.
+     * This is to initialize the expectations on non-square Display only.
      */
-    private static void setUpStaticSystemPropertiesSession() {
-        sStaticMockitoSession = mockitoSession()
-                .mockStatic(SystemProperties.class).startMocking();
-        when(SystemProperties.get(anyString(), anyString())).thenAnswer(invocation -> {
-            String property = invocation.getArgument(0);
-            if (property.equals("com.android.wm.shell.pip.phone.def_percentage")) {
-                return Float.toString(DEFAULT_PERCENT);
-            } else if (property.equals("com.android.wm.shell.pip.phone.min_percentage")) {
-                return Float.toString(MIN_PERCENT);
-            }
+    private static void initNonSquareDisplayExpectedSizes() {
+        sNonSquareDisplayExpectedMaxSizes = new HashMap<>();
+        sNonSquareDisplayExpectedDefaultSizes = new HashMap<>();
+        sNonSquareDisplayExpectedMinSizes = new HashMap<>();
 
-            // throw an exception if illegal arguments are used for these tests
-            throw new InvalidUseOfMatchersException(
-                String.format("Argument %s does not match", property)
-            );
-        });
+        sNonSquareDisplayExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
+        sNonSquareDisplayExpectedDefaultSizes.put(16f / 9, new Size(600, 338));
+        sNonSquareDisplayExpectedMinSizes.put(16f / 9, new Size(501, 282));
+
+        sNonSquareDisplayExpectedMaxSizes.put(4f / 3, new Size(893, 670));
+        sNonSquareDisplayExpectedDefaultSizes.put(4f / 3, new Size(536, 402));
+        sNonSquareDisplayExpectedMinSizes.put(4f / 3, new Size(447, 335));
+
+        sNonSquareDisplayExpectedMaxSizes.put(3f / 4, new Size(670, 893));
+        sNonSquareDisplayExpectedDefaultSizes.put(3f / 4, new Size(402, 536));
+        sNonSquareDisplayExpectedMinSizes.put(3f / 4, new Size(335, 447));
+
+        sNonSquareDisplayExpectedMaxSizes.put(9f / 16, new Size(563, 1001));
+        sNonSquareDisplayExpectedDefaultSizes.put(9f / 16, new Size(338, 601));
+        sNonSquareDisplayExpectedMinSizes.put(9f / 16, new Size(282, 501));
     }
 
     /**
      * Initializes the map with the aspect ratios to be tested and corresponding expected max sizes.
+     * This is to initialize the expectations on square Display only.
      */
-    private static void initExpectedSizes() {
-        sExpectedMaxSizes = new HashMap<>();
-        sExpectedDefaultSizes = new HashMap<>();
-        sExpectedMinSizes = new HashMap<>();
+    private static void initSquareDisplayExpectedSizes() {
+        sSquareDisplayExpectedMaxSizes = new HashMap<>();
+        sSquareDisplayExpectedDefaultSizes = new HashMap<>();
+        sSquareDisplayExpectedMinSizes = new HashMap<>();
 
-        sExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
-        sExpectedDefaultSizes.put(16f / 9, new Size(600, 338));
-        sExpectedMinSizes.put(16f / 9, new Size(501, 282));
+        sSquareDisplayExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
+        sSquareDisplayExpectedDefaultSizes.put(16f / 9, new Size(500, 281));
+        sSquareDisplayExpectedMinSizes.put(16f / 9, new Size(400, 225));
 
-        sExpectedMaxSizes.put(4f / 3, new Size(893, 670));
-        sExpectedDefaultSizes.put(4f / 3, new Size(536, 402));
-        sExpectedMinSizes.put(4f / 3, new Size(447, 335));
+        sSquareDisplayExpectedMaxSizes.put(4f / 3, new Size(893, 670));
+        sSquareDisplayExpectedDefaultSizes.put(4f / 3, new Size(447, 335));
+        sSquareDisplayExpectedMinSizes.put(4f / 3, new Size(357, 268));
 
-        sExpectedMaxSizes.put(3f / 4, new Size(670, 893));
-        sExpectedDefaultSizes.put(3f / 4, new Size(402, 536));
-        sExpectedMinSizes.put(3f / 4, new Size(335, 447));
+        sSquareDisplayExpectedMaxSizes.put(3f / 4, new Size(670, 893));
+        sSquareDisplayExpectedDefaultSizes.put(3f / 4, new Size(335, 447));
+        sSquareDisplayExpectedMinSizes.put(3f / 4, new Size(268, 357));
 
-        sExpectedMaxSizes.put(9f / 16, new Size(563, 1001));
-        sExpectedDefaultSizes.put(9f / 16, new Size(338, 601));
-        sExpectedMinSizes.put(9f / 16, new Size(282, 501));
+        sSquareDisplayExpectedMaxSizes.put(9f / 16, new Size(563, 1001));
+        sSquareDisplayExpectedDefaultSizes.put(9f / 16, new Size(282, 501));
+        sSquareDisplayExpectedMinSizes.put(9f / 16, new Size(225, 400));
     }
 
     private void forEveryTestCaseCheck(Map<Float, Size> expectedSizes,
@@ -137,20 +145,38 @@
 
     @Before
     public void setUp() {
-        initExpectedSizes();
+        initNonSquareDisplayExpectedSizes();
+        initSquareDisplayExpectedSizes();
 
-        when(mResources.getDimensionPixelSize(anyInt())).thenReturn(DEFAULT_MIN_EDGE_SIZE);
-        when(mResources.getFloat(anyInt())).thenReturn(OPTIMIZED_ASPECT_RATIO);
-        when(mResources.getString(anyInt())).thenReturn("0x0");
+        when(mResources.getFloat(R.dimen.config_pipSystemPreferredDefaultSizePercent))
+                .thenReturn(DEFAULT_PERCENT);
+        when(mResources.getFloat(R.dimen.config_pipSystemPreferredMinimumSizePercent))
+                .thenReturn(MIN_PERCENT);
+        when(mResources.getDimensionPixelSize(R.dimen.default_minimal_size_pip_resizable_task))
+                .thenReturn(DEFAULT_MIN_EDGE_SIZE);
+        when(mResources.getFloat(R.dimen.config_pipLargeScreenOptimizedAspectRatio))
+                .thenReturn(OPTIMIZED_ASPECT_RATIO);
+        when(mResources.getString(R.string.config_defaultPictureInPictureScreenEdgeInsets))
+                .thenReturn("0x0");
         when(mResources.getDisplayMetrics())
                 .thenReturn(getContext().getResources().getDisplayMetrics());
+        when(mResources.getFloat(R.dimen.config_pipSquareDisplayThresholdForSystemPreferredSize))
+                .thenReturn(SQUARE_DISPLAY_THRESHOLD);
+        when(mResources.getFloat(
+                R.dimen.config_pipSystemPreferredDefaultSizePercentForSquareDisplay))
+                .thenReturn(SQUARE_DISPLAY_DEFAULT_PERCENT);
+        when(mResources.getFloat(
+                R.dimen.config_pipSystemPreferredMinimumSizePercentForSquareDisplay))
+                .thenReturn(SQUARE_DISPLAY_MIN_PERCENT);
 
         // set up the mock context for spec handler specifically
         when(mContext.getResources()).thenReturn(mResources);
+    }
 
+    private void setupSizeSpecWithDisplayDimension(int width, int height) {
         DisplayInfo displayInfo = new DisplayInfo();
-        displayInfo.logicalWidth = DISPLAY_EDGE_SIZE;
-        displayInfo.logicalHeight = DISPLAY_EDGE_SIZE;
+        displayInfo.logicalWidth = width;
+        displayInfo.logicalHeight = height;
 
         // use the parent context (not the mocked one) to obtain the display layout
         // this is done to avoid unnecessary mocking while allowing for custom display dimensions
@@ -159,38 +185,57 @@
         mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
         mPipDisplayLayoutState.setDisplayLayout(displayLayout);
 
-        setUpStaticSystemPropertiesSession();
         mSizeSpecSource = new PhoneSizeSpecSource(mContext, mPipDisplayLayoutState);
 
         // no overridden min edge size by default
         mSizeSpecSource.setOverrideMinSize(null);
     }
 
-    @After
-    public void cleanUp() {
-        sStaticMockitoSession.finishMocking();
-    }
-
     @Test
-    public void testGetMaxSize() {
-        forEveryTestCaseCheck(sExpectedMaxSizes,
+    public void testGetMaxSize_nonSquareDisplay() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
+        forEveryTestCaseCheck(sNonSquareDisplayExpectedMaxSizes,
                 (aspectRatio) -> mSizeSpecSource.getMaxSize(aspectRatio));
     }
 
     @Test
-    public void testGetDefaultSize() {
-        forEveryTestCaseCheck(sExpectedDefaultSizes,
+    public void testGetDefaultSize_nonSquareDisplay() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
+        forEveryTestCaseCheck(sNonSquareDisplayExpectedDefaultSizes,
                 (aspectRatio) -> mSizeSpecSource.getDefaultSize(aspectRatio));
     }
 
     @Test
-    public void testGetMinSize() {
-        forEveryTestCaseCheck(sExpectedMinSizes,
+    public void testGetMinSize_nonSquareDisplay() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
+        forEveryTestCaseCheck(sNonSquareDisplayExpectedMinSizes,
+                (aspectRatio) -> mSizeSpecSource.getMinSize(aspectRatio));
+    }
+
+    @Test
+    public void testGetMaxSize_squareDisplay() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE, DISPLAY_EDGE_SIZE);
+        forEveryTestCaseCheck(sSquareDisplayExpectedMaxSizes,
+                (aspectRatio) -> mSizeSpecSource.getMaxSize(aspectRatio));
+    }
+
+    @Test
+    public void testGetDefaultSize_squareDisplay() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE, DISPLAY_EDGE_SIZE);
+        forEveryTestCaseCheck(sSquareDisplayExpectedDefaultSizes,
+                (aspectRatio) -> mSizeSpecSource.getDefaultSize(aspectRatio));
+    }
+
+    @Test
+    public void testGetMinSize_squareDisplay() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE, DISPLAY_EDGE_SIZE);
+        forEveryTestCaseCheck(sSquareDisplayExpectedMinSizes,
                 (aspectRatio) -> mSizeSpecSource.getMinSize(aspectRatio));
     }
 
     @Test
     public void testGetSizeForAspectRatio_noOverrideMinSize() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
         // an initial size with 16:9 aspect ratio
         Size initSize = new Size(600, 337);
 
@@ -202,6 +247,7 @@
 
     @Test
     public void testGetSizeForAspectRatio_withOverrideMinSize() {
+        setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
         // an initial size with a 1:1 aspect ratio
         Size initSize = new Size(OVERRIDE_MIN_EDGE_SIZE, OVERRIDE_MIN_EDGE_SIZE);
         mSizeSpecSource.setOverrideMinSize(initSize);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index d38e97f..40b59c1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.ArgumentMatchers.isA;
 import static org.mockito.Mockito.doReturn;
 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;
@@ -45,16 +46,21 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.window.flags.Flags;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestShellExecutor;
@@ -70,6 +76,7 @@
 import com.android.wm.shell.util.SplitBounds;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -99,6 +106,11 @@
     private ActivityTaskManager mActivityTaskManager;
     @Mock
     private DisplayInsetsController mDisplayInsetsController;
+    @Mock
+    private IRecentTasksListener mRecentTasksListener;
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private ShellTaskOrganizer mShellTaskOrganizer;
     private RecentTasksController mRecentTasksController;
@@ -426,6 +438,85 @@
     }
 
     @Test
+    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+            Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS})
+    public void onTaskAdded_desktopModeRunningAppsEnabled_triggersOnRunningTaskAppeared()
+            throws Exception {
+        mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener);
+        ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10);
+
+        mRecentTasksControllerReal.onTaskAdded(taskInfo);
+
+        verify(mRecentTasksListener).onRunningTaskAppeared(taskInfo);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS)
+    public void onTaskAdded_desktopModeRunningAppsDisabled_doesNotTriggerOnRunningTaskAppeared()
+            throws Exception {
+        mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener);
+        ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10);
+
+        mRecentTasksControllerReal.onTaskAdded(taskInfo);
+
+        verify(mRecentTasksListener, never()).onRunningTaskAppeared(any());
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+            Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS})
+    public void taskWindowingModeChanged_desktopRunningAppsEnabled_triggersOnRunningTaskChanged()
+            throws Exception {
+        mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener);
+        ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10);
+
+        mRecentTasksControllerReal.onTaskWindowingModeChanged(taskInfo);
+
+        verify(mRecentTasksListener).onRunningTaskChanged(taskInfo);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS)
+    public void
+            taskWindowingModeChanged_desktopRunningAppsDisabled_doesNotTriggerOnRunningTaskChanged()
+            throws Exception {
+        mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener);
+        ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10);
+
+        mRecentTasksControllerReal.onTaskWindowingModeChanged(taskInfo);
+
+        verify(mRecentTasksListener, never()).onRunningTaskChanged(any());
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+            Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS})
+    public void onTaskRemoved_desktopModeRunningAppsEnabled_triggersOnRunningTaskVanished()
+            throws Exception {
+        mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener);
+        ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10);
+
+        mRecentTasksControllerReal.onTaskRemoved(taskInfo);
+
+        verify(mRecentTasksListener).onRunningTaskVanished(taskInfo);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS)
+    public void onTaskRemoved_desktopModeRunningAppsDisabled_doesNotTriggerOnRunningTaskVanished()
+            throws Exception {
+        mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener);
+        ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10);
+
+        mRecentTasksControllerReal.onTaskRemoved(taskInfo);
+
+        verify(mRecentTasksListener, never()).onRunningTaskVanished(any());
+    }
+
+    @Test
     public void getNullSplitBoundsNonSplitTask() {
         SplitBounds sb = mRecentTasksController.getSplitBoundsForTaskId(3);
         assertNull("splitBounds should be null for non-split task", sb);
@@ -471,6 +562,7 @@
     private ActivityManager.RunningTaskInfo makeRunningTaskInfo(int taskId) {
         ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
         info.taskId = taskId;
+        info.realActivity = new ComponentName("testPackage", "testClass");
         return info;
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index d7c4610..0434742 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -44,7 +44,6 @@
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.os.Handler;
 import android.os.Looper;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -498,6 +497,31 @@
     }
 
     @Test
+    public void testStartRootTask_setsBoundsAndVisibility() {
+        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+        TaskViewBase taskViewBase = mock(TaskViewBase.class);
+        Rect bounds = new Rect(0, 0, 100, 100);
+        when(taskViewBase.getCurrentBoundsOnScreen()).thenReturn(bounds);
+        mTaskViewTaskController.setTaskViewBase(taskViewBase);
+
+        // Surface created, but task not available so bounds / visibility isn't set
+        mTaskView.surfaceCreated(mock(SurfaceHolder.class));
+        verify(mTaskViewTransitions, never()).updateVisibilityState(
+                eq(mTaskViewTaskController), eq(true));
+
+        // Make the task available
+        WindowContainerTransaction wct = mock(WindowContainerTransaction.class);
+        mTaskViewTaskController.startRootTask(mTaskInfo, mLeash, wct);
+
+        // Bounds got set
+        verify(wct).setBounds(any(WindowContainerToken.class), eq(bounds));
+        // Visibility & bounds state got set
+        verify(mTaskViewTransitions).updateVisibilityState(eq(mTaskViewTaskController), eq(true));
+        verify(mTaskViewTransitions).updateBoundsState(eq(mTaskViewTaskController), eq(bounds));
+    }
+
+    @Test
     public void testTaskViewPrepareOpenAnimationSetsBoundsAndVisibility() {
         assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
index fbc0db9..d3e40f2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
@@ -18,6 +18,7 @@
 
 import static android.view.WindowManager.TRANSIT_CHANGE;
 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 com.google.common.truth.Truth.assertThat;
@@ -208,6 +209,48 @@
     }
 
     @Test
+    public void testReorderTask_movedToFrontTransaction() {
+        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+        mTaskViewTransitions.reorderTaskViewTask(mTaskViewTaskController, true);
+        // Consume the pending transaction from order change
+        TaskViewTransitions.PendingTransition pending =
+                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
+        assertThat(pending).isNotNull();
+        mTaskViewTransitions.startAnimation(pending.mClaimed,
+                mock(TransitionInfo.class),
+                new SurfaceControl.Transaction(),
+                new SurfaceControl.Transaction(),
+                mock(Transitions.TransitionFinishCallback.class));
+
+        // Verify it was consumed
+        TaskViewTransitions.PendingTransition pending2 =
+                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
+        assertThat(pending2).isNull();
+    }
+
+    @Test
+    public void testReorderTask_movedToBackTransaction() {
+        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+        mTaskViewTransitions.reorderTaskViewTask(mTaskViewTaskController, false);
+        // Consume the pending transaction from order change
+        TaskViewTransitions.PendingTransition pending =
+                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
+        assertThat(pending).isNotNull();
+        mTaskViewTransitions.startAnimation(pending.mClaimed,
+                mock(TransitionInfo.class),
+                new SurfaceControl.Transaction(),
+                new SurfaceControl.Transaction(),
+                mock(Transitions.TransitionFinishCallback.class));
+
+        // Verify it was consumed
+        TaskViewTransitions.PendingTransition pending2 =
+                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
+        assertThat(pending2).isNull();
+    }
+
+    @Test
     public void test_startAnimation_setsTaskNotFound() {
         assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index e7d37ad..0db10ef 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -24,6 +24,7 @@
 import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.mock;
@@ -167,6 +168,25 @@
     }
 
     @Test
+    public void testStartDragToDesktopDoesNotTriggerCallback() throws RemoteException {
+        TransitionInfo info = mock(TransitionInfo.class);
+        TransitionInfo.Change change = mock(TransitionInfo.Change.class);
+        ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
+        when(change.getTaskInfo()).thenReturn(taskInfo);
+        when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
+        when(info.getType()).thenReturn(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP);
+
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
+
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
+                info,
+                mock(SurfaceControl.Transaction.class),
+                mock(SurfaceControl.Transaction.class));
+
+        verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean());
+    }
+
+    @Test
     public void testHomeActivityWithBackGestureNotifiesHomeIsVisible() throws RemoteException {
         TransitionInfo info = mock(TransitionInfo.class);
         TransitionInfo.Change change = mock(TransitionInfo.Change.class);
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 e9da258..2366917 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
@@ -83,6 +83,7 @@
 import android.window.IRemoteTransitionFinishedCallback;
 import android.window.IWindowContainerToken;
 import android.window.RemoteTransition;
+import android.window.RemoteTransitionStub;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
@@ -280,7 +281,7 @@
 
         final boolean[] remoteCalled = new boolean[]{false};
         final WindowContainerTransaction remoteFinishWCT = new WindowContainerTransaction();
-        IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+        IRemoteTransition testRemote = new RemoteTransitionStub() {
             @Override
             public void startAnimation(IBinder token, TransitionInfo info,
                     SurfaceControl.Transaction t,
@@ -288,16 +289,6 @@
                 remoteCalled[0] = true;
                 finishCallback.onTransitionFinished(remoteFinishWCT, null /* sct */);
             }
-
-            @Override
-            public void mergeAnimation(IBinder token, TransitionInfo info,
-                    SurfaceControl.Transaction t, IBinder mergeTarget,
-                    IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
-            }
-
-            @Override
-            public void onTransitionConsumed(IBinder iBinder, boolean b) throws RemoteException {
-            }
         };
         IBinder transitToken = new Binder();
         transitions.requestStartTransition(transitToken,
@@ -450,7 +441,7 @@
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
-        IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+        IRemoteTransition testRemote = new RemoteTransitionStub() {
             @Override
             public void startAnimation(IBinder token, TransitionInfo info,
                     SurfaceControl.Transaction t,
@@ -458,16 +449,6 @@
                 remoteCalled[0] = true;
                 finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
             }
-
-            @Override
-            public void mergeAnimation(IBinder token, TransitionInfo info,
-                    SurfaceControl.Transaction t, IBinder mergeTarget,
-                    IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
-            }
-
-            @Override
-            public void onTransitionConsumed(IBinder iBinder, boolean b) throws RemoteException {
-            }
         };
 
         TransitionFilter filter = new TransitionFilter();
@@ -500,7 +481,7 @@
 
         final boolean[] remoteCalled = new boolean[]{false};
         final WindowContainerTransaction remoteFinishWCT = new WindowContainerTransaction();
-        IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+        IRemoteTransition testRemote = new RemoteTransitionStub() {
             @Override
             public void startAnimation(IBinder token, TransitionInfo info,
                     SurfaceControl.Transaction t,
@@ -508,16 +489,6 @@
                 remoteCalled[0] = true;
                 finishCallback.onTransitionFinished(remoteFinishWCT, null /* sct */);
             }
-
-            @Override
-            public void mergeAnimation(IBinder token, TransitionInfo info,
-                    SurfaceControl.Transaction t, IBinder mergeTarget,
-                    IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
-            }
-
-            @Override
-            public void onTransitionConsumed(IBinder iBinder, boolean b) throws RemoteException {
-            }
         };
 
         final int transitType = TRANSIT_FIRST_CUSTOM + 1;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TestRemoteTransition.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TestRemoteTransition.java
index 87330d2..184e895 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TestRemoteTransition.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TestRemoteTransition.java
@@ -20,6 +20,7 @@
 import android.view.SurfaceControl;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransitionStub;
 import android.window.TransitionInfo;
 import android.window.WindowContainerTransaction;
 
@@ -29,7 +30,7 @@
  * {@link #startAnimation(IBinder, TransitionInfo, SurfaceControl.Transaction,
  * IRemoteTransitionFinishedCallback)} being called.
  */
-public class TestRemoteTransition extends IRemoteTransition.Stub {
+public class TestRemoteTransition extends RemoteTransitionStub {
     private boolean mCalled = false;
     private boolean mConsumed = false;
     final WindowContainerTransaction mRemoteFinishWCT = new WindowContainerTransaction();
@@ -44,12 +45,6 @@
     }
 
     @Override
-    public void mergeAnimation(IBinder transition, TransitionInfo info,
-            SurfaceControl.Transaction t, IBinder mergeTarget,
-            IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
-    }
-
-    @Override
     public void onTransitionConsumed(IBinder iBinder, boolean b) throws RemoteException {
         mConsumed = true;
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java
index c5e229f..acc0bce 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java
@@ -298,6 +298,32 @@
     }
 
     @Test
+    public void fold_animationInProgress_finishesTransition() {
+        TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo();
+        TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class);
+
+        // Unfold
+        mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ false);
+        mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo);
+        mUnfoldTransitionHandler.startAnimation(
+                mTransition,
+                mock(TransitionInfo.class),
+                mock(SurfaceControl.Transaction.class),
+                mock(SurfaceControl.Transaction.class),
+                finishCallback
+        );
+
+        // Start animation but don't finish it
+        mShellUnfoldProgressProvider.onStateChangeStarted();
+        mShellUnfoldProgressProvider.onStateChangeProgress(0.5f);
+
+        // Fold
+        mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ true);
+
+        verify(finishCallback).onTransitionFinished(any());
+    }
+
+    @Test
     public void mergeAnimation_eatsDisplayOnlyTransitions() {
         TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo();
         mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 8e9619d..7d19f3c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -28,6 +28,9 @@
 import android.hardware.display.VirtualDisplay
 import android.os.Handler
 import android.platform.test.annotations.EnableFlags
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
 import android.platform.test.flag.junit.SetFlagsRule
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
@@ -97,6 +100,10 @@
     @Rule
     val setFlagsRule = SetFlagsRule()
 
+    @JvmField
+    @Rule
+    val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
     @Mock private lateinit var mockDesktopModeWindowDecorFactory:
             DesktopModeWindowDecoration.Factory
     @Mock private lateinit var mockMainHandler: Handler
@@ -306,6 +313,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_IMMERSIVE_HANDLE_HIDING)
     fun testRelayoutRunsWhenStatusBarsInsetsSourceVisibilityChanges() {
         val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM, focused = true)
         val decoration = setUpMockDecorationForTask(task)
@@ -326,6 +334,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_IMMERSIVE_HANDLE_HIDING)
     fun testRelayoutDoesNotRunWhenNonStatusBarsInsetsSourceVisibilityChanges() {
         val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM, focused = true)
         val decoration = setUpMockDecorationForTask(task)
@@ -346,6 +355,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_IMMERSIVE_HANDLE_HIDING)
     fun testRelayoutDoesNotRunWhenNonStatusBarsInsetSourceVisibilityDoesNotChange() {
         val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM, focused = true)
         val decoration = setUpMockDecorationForTask(task)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
new file mode 100644
index 0000000..82e5a1c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.annotation.NonNull;
+import android.graphics.Point;
+import android.graphics.Region;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.testing.AndroidTestingRunner;
+import android.util.Size;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.window.flags.Flags;
+
+import com.google.common.testing.EqualsTester;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link DragResizeWindowGeometry}.
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:DragResizeWindowGeometryTests
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class DragResizeWindowGeometryTests {
+    private static final Size TASK_SIZE = new Size(500, 1000);
+    private static final int TASK_CORNER_RADIUS = 10;
+    private static final int EDGE_RESIZE_THICKNESS = 15;
+    private static final int FINE_CORNER_SIZE = EDGE_RESIZE_THICKNESS * 2 + 10;
+    private static final int LARGE_CORNER_SIZE = FINE_CORNER_SIZE + 10;
+    private static final DragResizeWindowGeometry GEOMETRY = new DragResizeWindowGeometry(
+            TASK_CORNER_RADIUS, TASK_SIZE, EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE,
+            LARGE_CORNER_SIZE);
+    // Points in the edge resize handle. Note that coordinates start from the top left.
+    private static final Point TOP_EDGE_POINT = new Point(TASK_SIZE.getWidth() / 2,
+            -EDGE_RESIZE_THICKNESS / 2);
+    private static final Point LEFT_EDGE_POINT = new Point(-EDGE_RESIZE_THICKNESS / 2,
+            TASK_SIZE.getHeight() / 2);
+    private static final Point RIGHT_EDGE_POINT = new Point(
+            TASK_SIZE.getWidth() + EDGE_RESIZE_THICKNESS / 2, TASK_SIZE.getHeight() / 2);
+    private static final Point BOTTOM_EDGE_POINT = new Point(TASK_SIZE.getWidth() / 2,
+            TASK_SIZE.getHeight() + EDGE_RESIZE_THICKNESS / 2);
+
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+    /**
+     * Check that both groups of objects satisfy equals/hashcode within each group, and that each
+     * group is distinct from the next.
+     */
+    @Test
+    public void testEqualsAndHash() {
+        new EqualsTester()
+                .addEqualityGroup(
+                        GEOMETRY,
+                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
+                                EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE, LARGE_CORNER_SIZE))
+                .addEqualityGroup(
+                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
+                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE),
+                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
+                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE))
+                .addEqualityGroup(
+                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
+                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE,
+                                LARGE_CORNER_SIZE + 5),
+                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
+                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE,
+                                LARGE_CORNER_SIZE + 5))
+                .testEquals();
+    }
+
+    @Test
+    public void testGetTaskSize() {
+        assertThat(GEOMETRY.getTaskSize()).isEqualTo(TASK_SIZE);
+    }
+
+    @Test
+    public void testRegionUnionContainsEdges() {
+        Region region = new Region();
+        GEOMETRY.union(region);
+        assertThat(region.isComplex()).isTrue();
+        // Region excludes task area. Note that coordinates start from top left.
+        assertThat(region.contains(TASK_SIZE.getWidth() / 2, TASK_SIZE.getHeight() / 2)).isFalse();
+        // Region includes edges outside the task window.
+        verifyVerticalEdge(region, LEFT_EDGE_POINT);
+        verifyHorizontalEdge(region, TOP_EDGE_POINT);
+        verifyVerticalEdge(region, RIGHT_EDGE_POINT);
+        verifyHorizontalEdge(region, BOTTOM_EDGE_POINT);
+    }
+
+    private static void verifyHorizontalEdge(@NonNull Region region, @NonNull Point point) {
+        assertThat(region.contains(point.x, point.y)).isTrue();
+        // Horizontally along the edge is still contained.
+        assertThat(region.contains(point.x + EDGE_RESIZE_THICKNESS, point.y)).isTrue();
+        assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isTrue();
+        // Vertically along the edge is not contained.
+        assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isFalse();
+        assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isFalse();
+    }
+
+    private static void verifyVerticalEdge(@NonNull Region region, @NonNull Point point) {
+        assertThat(region.contains(point.x, point.y)).isTrue();
+        // Horizontally along the edge is not contained.
+        assertThat(region.contains(point.x + EDGE_RESIZE_THICKNESS, point.y)).isFalse();
+        assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isFalse();
+        // Vertically along the edge is contained.
+        assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isTrue();
+        assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isTrue();
+    }
+
+    /**
+     * Validate that with the flag enabled, the corner resize regions are the largest size, to
+     * capture all eligible input regardless of source (touch or cursor).
+     */
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
+    public void testRegionUnion_edgeDragResizeEnabled_containsLargeCorners() {
+        Region region = new Region();
+        GEOMETRY.union(region);
+        final int cornerRadius = LARGE_CORNER_SIZE / 2;
+
+        new TestPoints(TASK_SIZE, cornerRadius).validateRegion(region);
+    }
+
+    /**
+     * Validate that with the flag disabled, the corner resize regions are the original smaller
+     * size.
+     */
+    @Test
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
+    public void testRegionUnion_edgeDragResizeDisabled_containsFineCorners() {
+        Region region = new Region();
+        GEOMETRY.union(region);
+        final int cornerRadius = FINE_CORNER_SIZE / 2;
+
+        new TestPoints(TASK_SIZE, cornerRadius).validateRegion(region);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
+    public void testCalculateControlType_edgeDragResizeEnabled_edges() {
+        // The input source (touch or cursor) shouldn't impact the edge resize size.
+        validateCtrlTypeForEdges(/* isTouch= */ false);
+        validateCtrlTypeForEdges(/* isTouch= */ true);
+    }
+
+    @Test
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
+    public void testCalculateControlType_edgeDragResizeDisabled_edges() {
+        // Edge resizing is not supported when the flag is disabled.
+        validateCtrlTypeForEdges(/* isTouch= */ false);
+        validateCtrlTypeForEdges(/* isTouch= */ false);
+    }
+
+    private void validateCtrlTypeForEdges(boolean isTouch) {
+        assertThat(GEOMETRY.calculateCtrlType(isTouch, LEFT_EDGE_POINT.x,
+                LEFT_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_LEFT);
+        assertThat(GEOMETRY.calculateCtrlType(isTouch, TOP_EDGE_POINT.x,
+                TOP_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_TOP);
+        assertThat(GEOMETRY.calculateCtrlType(isTouch, RIGHT_EDGE_POINT.x,
+                RIGHT_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_RIGHT);
+        assertThat(GEOMETRY.calculateCtrlType(isTouch, BOTTOM_EDGE_POINT.x,
+                BOTTOM_EDGE_POINT.y)).isEqualTo(CTRL_TYPE_BOTTOM);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
+    public void testCalculateControlType_edgeDragResizeEnabled_corners() {
+        final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2);
+        final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2);
+
+        // When the flag is enabled, points within fine corners should pass regardless of touch or
+        // not. Points outside fine corners should not pass when using a course input (non-touch).
+        fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true);
+        fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, true);
+        fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, true);
+        fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false);
+
+        // When the flag is enabled, points near the large corners should only pass when the point
+        // is within the corner for large touch inputs.
+        largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true);
+        largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true,
+                false);
+        largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false);
+        largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false,
+                false);
+    }
+
+    @Test
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_WINDOWING_EDGE_DRAG_RESIZE)
+    public void testCalculateControlType_edgeDragResizeDisabled_corners() {
+        final TestPoints fineTestPoints = new TestPoints(TASK_SIZE, FINE_CORNER_SIZE / 2);
+        final TestPoints largeCornerTestPoints = new TestPoints(TASK_SIZE, LARGE_CORNER_SIZE / 2);
+
+        // When the flag is disabled, points within fine corners should pass only when touch.
+        fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, true);
+        fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true, false);
+        fineTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false);
+        fineTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false, false);
+
+        // When the flag is disabled, points near the large corners should never pass.
+        largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ true, false);
+        largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ true,
+                false);
+        largeCornerTestPoints.validateCtrlTypeForInnerPoints(GEOMETRY, /* isTouch= */ false, false);
+        largeCornerTestPoints.validateCtrlTypeForOutsidePoints(GEOMETRY, /* isTouch= */ false,
+                false);
+    }
+
+    /**
+     * Class for creating points for testing the drag resize corners.
+     *
+     * <p>Creates points that are both just within the bounds of each corner, and just outside.
+     */
+    private static final class TestPoints {
+        private final Point mTopLeftPoint;
+        private final Point mTopLeftPointOutside;
+        private final Point mTopRightPoint;
+        private final Point mTopRightPointOutside;
+        private final Point mBottomLeftPoint;
+        private final Point mBottomLeftPointOutside;
+        private final Point mBottomRightPoint;
+        private final Point mBottomRightPointOutside;
+
+        TestPoints(@NonNull Size taskSize, int cornerRadius) {
+            // Point just inside corner square is included.
+            mTopLeftPoint = new Point(-cornerRadius + 1, -cornerRadius + 1);
+            // Point just outside corner square is excluded.
+            mTopLeftPointOutside = new Point(mTopLeftPoint.x - 5, mTopLeftPoint.y - 5);
+
+            mTopRightPoint = new Point(taskSize.getWidth() + cornerRadius - 1, -cornerRadius + 1);
+            mTopRightPointOutside = new Point(mTopRightPoint.x + 5, mTopRightPoint.y - 5);
+
+            mBottomLeftPoint = new Point(-cornerRadius + 1,
+                    taskSize.getHeight() + cornerRadius - 1);
+            mBottomLeftPointOutside = new Point(mBottomLeftPoint.x - 5, mBottomLeftPoint.y + 5);
+
+            mBottomRightPoint = new Point(taskSize.getWidth() + cornerRadius - 1,
+                    taskSize.getHeight() + cornerRadius - 1);
+            mBottomRightPointOutside = new Point(mBottomRightPoint.x + 5, mBottomRightPoint.y + 5);
+        }
+
+        /**
+         * Validates that all test points are either within or without the given region.
+         */
+        public void validateRegion(@NonNull Region region) {
+            // Point just inside corner square is included.
+            assertThat(region.contains(mTopLeftPoint.x, mTopLeftPoint.y)).isTrue();
+            // Point just outside corner square is excluded.
+            assertThat(region.contains(mTopLeftPointOutside.x, mTopLeftPointOutside.y)).isFalse();
+
+            assertThat(region.contains(mTopRightPoint.x, mTopRightPoint.y)).isTrue();
+            assertThat(
+                    region.contains(mTopRightPointOutside.x, mTopRightPointOutside.y)).isFalse();
+
+            assertThat(region.contains(mBottomLeftPoint.x, mBottomLeftPoint.y)).isTrue();
+            assertThat(region.contains(mBottomLeftPointOutside.x,
+                    mBottomLeftPointOutside.y)).isFalse();
+
+            assertThat(region.contains(mBottomRightPoint.x, mBottomRightPoint.y)).isTrue();
+            assertThat(region.contains(mBottomRightPointOutside.x,
+                    mBottomRightPointOutside.y)).isFalse();
+        }
+
+        /**
+         * Validates that all test points within this drag corner size give the correct
+         * {@code @DragPositioningCallback.CtrlType}.
+         */
+        public void validateCtrlTypeForInnerPoints(@NonNull DragResizeWindowGeometry geometry,
+                boolean isTouch, boolean expectedWithinGeometry) {
+            assertThat(geometry.calculateCtrlType(isTouch, mTopLeftPoint.x,
+                    mTopLeftPoint.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
+            assertThat(geometry.calculateCtrlType(isTouch, mTopRightPoint.x,
+                    mTopRightPoint.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
+            assertThat(geometry.calculateCtrlType(isTouch, mBottomLeftPoint.x,
+                    mBottomLeftPoint.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM
+                            : CTRL_TYPE_UNDEFINED);
+            assertThat(geometry.calculateCtrlType(isTouch, mBottomRightPoint.x,
+                    mBottomRightPoint.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM
+                            : CTRL_TYPE_UNDEFINED);
+        }
+
+        /**
+         * Validates that all test points outside this drag corner size give the correct
+         * {@code @DragPositioningCallback.CtrlType}.
+         */
+        public void validateCtrlTypeForOutsidePoints(@NonNull DragResizeWindowGeometry geometry,
+                boolean isTouch, boolean expectedWithinGeometry) {
+            assertThat(geometry.calculateCtrlType(isTouch, mTopLeftPointOutside.x,
+                    mTopLeftPointOutside.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
+            assertThat(geometry.calculateCtrlType(isTouch, mTopRightPointOutside.x,
+                    mTopRightPointOutside.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED);
+            assertThat(geometry.calculateCtrlType(isTouch, mBottomLeftPointOutside.x,
+                    mBottomLeftPointOutside.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM
+                            : CTRL_TYPE_UNDEFINED);
+            assertThat(geometry.calculateCtrlType(isTouch, mBottomRightPointOutside.x,
+                    mBottomRightPointOutside.y)).isEqualTo(
+                    expectedWithinGeometry ? CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM
+                            : CTRL_TYPE_UNDEFINED);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
new file mode 100644
index 0000000..847c2dd
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.windowdecor
+
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.Display
+import android.view.SurfaceControl
+import android.view.SurfaceControlViewHost
+import android.view.WindowlessWindowManager
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestRunningTaskInfoBuilder
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayController.OnDisplaysChangedListener
+import com.android.wm.shell.windowdecor.WindowDecoration.SurfaceControlViewHostFactory
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Spy
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.whenever
+
+
+/**
+ * Tests for [ResizeVeil].
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:ResizeVeilTest
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected]
+class ResizeVeilTest : ShellTestCase() {
+
+    @Mock
+    private lateinit var mockDisplayController: DisplayController
+    @Mock
+    private lateinit var mockAppIcon: Drawable
+    @Mock
+    private lateinit var mockDisplay: Display
+    @Mock
+    private lateinit var mockSurfaceControlViewHost: SurfaceControlViewHost
+    @Mock
+    private lateinit var mockSurfaceControlBuilderFactory: ResizeVeil.SurfaceControlBuilderFactory
+    @Mock
+    private lateinit var mockSurfaceControlViewHostFactory: SurfaceControlViewHostFactory
+    @Spy
+    private val spyResizeVeilSurfaceBuilder = SurfaceControl.Builder()
+    @Mock
+    private lateinit var mockResizeVeilSurface: SurfaceControl
+    @Spy
+    private val spyBackgroundSurfaceBuilder = SurfaceControl.Builder()
+    @Mock
+    private lateinit var mockBackgroundSurface: SurfaceControl
+    @Spy
+    private val spyIconSurfaceBuilder = SurfaceControl.Builder()
+    @Mock
+    private lateinit var mockIconSurface: SurfaceControl
+    @Mock
+    private lateinit var mockTransaction: SurfaceControl.Transaction
+
+    private val taskInfo = TestRunningTaskInfoBuilder().build()
+
+    @Before
+    fun setUp() {
+        whenever(mockSurfaceControlViewHostFactory.create(any(), any(), any(), any()))
+                .thenReturn(mockSurfaceControlViewHost)
+        whenever(mockSurfaceControlBuilderFactory
+            .create("Resize veil of Task=" + taskInfo.taskId))
+            .thenReturn(spyResizeVeilSurfaceBuilder)
+        doReturn(mockResizeVeilSurface).whenever(spyResizeVeilSurfaceBuilder).build()
+        whenever(mockSurfaceControlBuilderFactory
+            .create(eq("Resize veil background of Task=" + taskInfo.taskId), any()))
+            .thenReturn(spyBackgroundSurfaceBuilder)
+        doReturn(mockBackgroundSurface).whenever(spyBackgroundSurfaceBuilder).build()
+        whenever(mockSurfaceControlBuilderFactory
+            .create("Resize veil icon of Task=" + taskInfo.taskId))
+            .thenReturn(spyIconSurfaceBuilder)
+        doReturn(mockIconSurface).whenever(spyIconSurfaceBuilder).build()
+    }
+
+    @Test
+    fun init_displayAvailable_viewHostCreated() {
+        createResizeVeil(withDisplayAvailable = true)
+
+        verify(mockSurfaceControlViewHostFactory)
+            .create(any(), eq(mockDisplay), any(), eq("ResizeVeil"))
+    }
+
+    @Test
+    fun init_displayUnavailable_viewHostNotCreatedUntilDisplayAppears() {
+        createResizeVeil(withDisplayAvailable = false)
+
+        verify(mockSurfaceControlViewHostFactory, never())
+            .create(any(), eq(mockDisplay), any<WindowlessWindowManager>(), eq("ResizeVeil"))
+        val captor = ArgumentCaptor.forClass(OnDisplaysChangedListener::class.java)
+        verify(mockDisplayController).addDisplayWindowListener(captor.capture())
+
+        whenever(mockDisplayController.getDisplay(taskInfo.displayId)).thenReturn(mockDisplay)
+        captor.value.onDisplayAdded(taskInfo.displayId)
+
+        verify(mockSurfaceControlViewHostFactory)
+            .create(any(), eq(mockDisplay), any(), eq("ResizeVeil"))
+        verify(mockDisplayController).removeDisplayWindowListener(any())
+    }
+
+    @Test
+    fun dispose_removesDisplayWindowListener() {
+        createResizeVeil().dispose()
+
+        verify(mockDisplayController).removeDisplayWindowListener(any())
+    }
+
+    @Test
+    fun showVeil() {
+        val veil = createResizeVeil()
+        val tx = mock<SurfaceControl.Transaction>()
+
+        veil.showVeil(tx, mock(), Rect(0, 0, 100, 100), false /* fadeIn */)
+
+        verify(tx).show(mockResizeVeilSurface)
+        verify(tx).show(mockBackgroundSurface)
+        verify(tx).show(mockIconSurface)
+        verify(tx).apply()
+    }
+
+    @Test
+    fun showVeil_displayUnavailable_doesNotShow() {
+        val veil = createResizeVeil(withDisplayAvailable = false)
+        val tx = mock<SurfaceControl.Transaction>()
+
+        veil.showVeil(tx, mock(), Rect(0, 0, 100, 100), false /* fadeIn */)
+
+        verify(tx, never()).show(mockResizeVeilSurface)
+        verify(tx, never()).show(mockBackgroundSurface)
+        verify(tx, never()).show(mockIconSurface)
+        verify(tx).apply()
+    }
+
+    @Test
+    fun showVeil_alreadyVisible_doesNotShowAgain() {
+        val veil = createResizeVeil()
+        val tx = mock<SurfaceControl.Transaction>()
+
+        veil.showVeil(tx, mock(), Rect(0, 0, 100, 100), false /* fadeIn */)
+        veil.showVeil(tx, mock(), Rect(0, 0, 100, 100), false /* fadeIn */)
+
+        verify(tx, times(1)).show(mockResizeVeilSurface)
+        verify(tx, times(1)).show(mockBackgroundSurface)
+        verify(tx, times(1)).show(mockIconSurface)
+        verify(tx, times(2)).apply()
+    }
+
+    @Test
+    fun showVeil_reparentsVeilToNewParent() {
+        val veil = createResizeVeil(parent = mock())
+        val tx = mock<SurfaceControl.Transaction>()
+
+        val newParent = mock<SurfaceControl>()
+        veil.showVeil(tx, newParent, Rect(0, 0, 100, 100), false /* fadeIn */)
+
+        verify(tx).reparent(mockResizeVeilSurface, newParent)
+    }
+
+    @Test
+    fun hideVeil_alreadyHidden_doesNothing() {
+        val veil = createResizeVeil()
+
+        veil.hideVeil()
+
+        verifyZeroInteractions(mockTransaction)
+    }
+
+    private fun createResizeVeil(
+        withDisplayAvailable: Boolean = true,
+        parent: SurfaceControl = mock()
+    ): ResizeVeil {
+        whenever(mockDisplayController.getDisplay(taskInfo.displayId))
+            .thenReturn(if (withDisplayAvailable) mockDisplay else null)
+        return ResizeVeil(
+            context,
+            mockDisplayController,
+            mockAppIcon,
+            taskInfo,
+            parent,
+            { mockTransaction },
+            mockSurfaceControlBuilderFactory,
+            mockSurfaceControlViewHostFactory
+        )
+    }
+}
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 228b25c..5464937 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
@@ -61,7 +61,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
 import android.view.View;
-import android.view.ViewRootImpl;
 import android.view.WindowInsets;
 import android.view.WindowManager.LayoutParams;
 import android.window.SurfaceSyncGroup;
@@ -252,16 +251,14 @@
                         argThat(lp -> lp.height == 64
                                 && lp.width == 300
                                 && (lp.flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0));
-        if (ViewRootImpl.CAPTION_ON_SHELL) {
-            verify(mMockView).setTaskFocusState(true);
-            verify(mMockWindowContainerTransaction).addInsetsSource(
-                    eq(taskInfo.token),
-                    any(),
-                    eq(0 /* index */),
-                    eq(WindowInsets.Type.captionBar()),
-                    eq(new Rect(100, 300, 400, 364)),
-                    any());
-        }
+        verify(mMockView).setTaskFocusState(true);
+        verify(mMockWindowContainerTransaction).addInsetsSource(
+                eq(taskInfo.token),
+                any(),
+                eq(0 /* index */),
+                eq(WindowInsets.Type.captionBar()),
+                eq(new Rect(100, 300, 400, 364)),
+                any());
 
         verify(mMockSurfaceControlStartT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
         verify(mMockSurfaceControlFinishT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
index 9d4b426..839c7b6 100644
--- a/libs/androidfw/ZipFileRO.cpp
+++ b/libs/androidfw/ZipFileRO.cpp
@@ -119,30 +119,41 @@
  * appear to be bogus.
  */
 bool ZipFileRO::getEntryInfo(ZipEntryRO entry, uint16_t* pMethod,
+ uint32_t* pUncompLen, uint32_t* pCompLen, off64_t* pOffset,
+ uint32_t* pModWhen, uint32_t* pCrc32) const
+{
+     return getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset, pModWhen,
+      pCrc32, nullptr);
+}
+
+bool ZipFileRO::getEntryInfo(ZipEntryRO entry, uint16_t* pMethod,
     uint32_t* pUncompLen, uint32_t* pCompLen, off64_t* pOffset,
-    uint32_t* pModWhen, uint32_t* pCrc32) const
+    uint32_t* pModWhen, uint32_t* pCrc32, uint16_t* pExtraFieldSize) const
 {
     const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
     const ZipEntry& ze = zipEntry->entry;
 
-    if (pMethod != NULL) {
+    if (pMethod != nullptr) {
         *pMethod = ze.method;
     }
-    if (pUncompLen != NULL) {
+    if (pUncompLen != nullptr) {
         *pUncompLen = ze.uncompressed_length;
     }
-    if (pCompLen != NULL) {
+    if (pCompLen != nullptr) {
         *pCompLen = ze.compressed_length;
     }
-    if (pOffset != NULL) {
+    if (pOffset != nullptr) {
         *pOffset = ze.offset;
     }
-    if (pModWhen != NULL) {
+    if (pModWhen != nullptr) {
         *pModWhen = ze.mod_time;
     }
-    if (pCrc32 != NULL) {
+    if (pCrc32 != nullptr) {
         *pCrc32 = ze.crc32;
     }
+    if (pExtraFieldSize != nullptr) {
+        *pExtraFieldSize = ze.extra_field_size;
+    }
 
     return true;
 }
@@ -310,3 +321,7 @@
 
     return true;
 }
+
+const char* ZipFileRO::getZipFileName() {
+    return mFileName;
+}
diff --git a/libs/androidfw/include/androidfw/ZipFileRO.h b/libs/androidfw/include/androidfw/ZipFileRO.h
index be1f98f..f7c5007 100644
--- a/libs/androidfw/include/androidfw/ZipFileRO.h
+++ b/libs/androidfw/include/androidfw/ZipFileRO.h
@@ -151,6 +151,10 @@
         uint32_t* pCompLen, off64_t* pOffset, uint32_t* pModWhen,
         uint32_t* pCrc32) const;
 
+    bool getEntryInfo(ZipEntryRO entry, uint16_t* pMethod,
+        uint32_t* pUncompLen, uint32_t* pCompLen, off64_t* pOffset,
+        uint32_t* pModWhen, uint32_t* pCrc32, uint16_t* pExtraFieldSize) const;
+
     /*
      * Create a new FileMap object that maps a subset of the archive. For
      * an uncompressed entry this effectively provides a pointer to the
@@ -187,6 +191,8 @@
      */
     bool uncompressEntry(ZipEntryRO entry, int fd) const;
 
+    const char* getZipFileName();
+
     ~ZipFileRO();
 
 private:
diff --git a/libs/hostgraphics/ANativeWindow.cpp b/libs/hostgraphics/ANativeWindow.cpp
new file mode 100644
index 0000000..fcfaf02
--- /dev/null
+++ b/libs/hostgraphics/ANativeWindow.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <system/window.h>
+
+static int32_t query(ANativeWindow* window, int what) {
+    int value;
+    int res = window->query(window, what, &value);
+    return res < 0 ? res : value;
+}
+
+static int64_t query64(ANativeWindow* window, int what) {
+    int64_t value;
+    int res = window->perform(window, what, &value);
+    return res < 0 ? res : value;
+}
+
+int ANativeWindow_setCancelBufferInterceptor(ANativeWindow* window,
+                                             ANativeWindow_cancelBufferInterceptor interceptor,
+                                             void* data) {
+    return window->perform(window, NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR, interceptor, data);
+}
+
+int ANativeWindow_setDequeueBufferInterceptor(ANativeWindow* window,
+                                              ANativeWindow_dequeueBufferInterceptor interceptor,
+                                              void* data) {
+    return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR, interceptor, data);
+}
+
+int ANativeWindow_setQueueBufferInterceptor(ANativeWindow* window,
+                                            ANativeWindow_queueBufferInterceptor interceptor,
+                                            void* data) {
+    return window->perform(window, NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR, interceptor, data);
+}
+
+int ANativeWindow_setPerformInterceptor(ANativeWindow* window,
+                                        ANativeWindow_performInterceptor interceptor, void* data) {
+    return window->perform(window, NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR, interceptor, data);
+}
+
+int ANativeWindow_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
+    return window->dequeueBuffer(window, buffer, fenceFd);
+}
+
+int ANativeWindow_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
+    return window->cancelBuffer(window, buffer, fenceFd);
+}
+
+int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) {
+    return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, timeout);
+}
+
+// extern "C", so that it can be used outside libhostgraphics (in host hwui/.../CanvasContext.cpp)
+extern "C" void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) {
+    if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) {
+        return;
+    }
+    window->perform(window, NATIVE_WINDOW_ALLOCATE_BUFFERS);
+}
+
+int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) {
+    return query64(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_START);
+}
+
+int64_t ANativeWindow_getLastDequeueDuration(ANativeWindow* window) {
+    return query64(window, NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION);
+}
+
+int64_t ANativeWindow_getLastQueueDuration(ANativeWindow* window) {
+    return query64(window, NATIVE_WINDOW_GET_LAST_QUEUE_DURATION);
+}
+
+int32_t ANativeWindow_getWidth(ANativeWindow* window) {
+    return query(window, NATIVE_WINDOW_WIDTH);
+}
+
+int32_t ANativeWindow_getHeight(ANativeWindow* window) {
+    return query(window, NATIVE_WINDOW_HEIGHT);
+}
+
+int32_t ANativeWindow_getFormat(ANativeWindow* window) {
+    return query(window, NATIVE_WINDOW_FORMAT);
+}
+
+void ANativeWindow_acquire(ANativeWindow* window) {
+    // incStrong/decStrong token must be the same, doesn't matter what it is
+    window->incStrong((void*)ANativeWindow_acquire);
+}
+
+void ANativeWindow_release(ANativeWindow* window) {
+    // incStrong/decStrong token must be the same, doesn't matter what it is
+    window->decStrong((void*)ANativeWindow_acquire);
+}
diff --git a/libs/hostgraphics/Android.bp b/libs/hostgraphics/Android.bp
index 4407af6..09232b6 100644
--- a/libs/hostgraphics/Android.bp
+++ b/libs/hostgraphics/Android.bp
@@ -17,26 +17,18 @@
     static_libs: [
         "libbase",
         "libmath",
+        "libui-types",
         "libutils",
     ],
 
     srcs: [
-        ":libui_host_common",
         "ADisplay.cpp",
+        "ANativeWindow.cpp",
         "Fence.cpp",
         "HostBufferQueue.cpp",
         "PublicFormat.cpp",
     ],
 
-    include_dirs: [
-        // Here we override all the headers automatically included with frameworks/native/include.
-        // When frameworks/native/include will be removed from the list of automatic includes.
-        // We will have to copy necessary headers with a pre-build step (generated headers).
-        ".",
-        "frameworks/native/libs/arect/include",
-        "frameworks/native/libs/ui/include_private",
-    ],
-
     header_libs: [
         "libnativebase_headers",
         "libnativedisplay_headers",
diff --git a/libs/hostgraphics/HostBufferQueue.cpp b/libs/hostgraphics/HostBufferQueue.cpp
index ec30437..b4fd5d9 100644
--- a/libs/hostgraphics/HostBufferQueue.cpp
+++ b/libs/hostgraphics/HostBufferQueue.cpp
@@ -16,12 +16,15 @@
 
 #include <gui/BufferQueue.h>
 
+#include <system/window.h>
+
 namespace android {
 
 class HostBufferQueue : public IGraphicBufferProducer, public IGraphicBufferConsumer {
 public:
     HostBufferQueue() : mWidth(0), mHeight(0) { }
 
+// Consumer
     virtual status_t setConsumerIsProtected(bool isProtected) { return OK; }
 
     virtual status_t detachBuffer(int slot) { return OK; }
@@ -51,6 +54,28 @@
     virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) { return OK; }
 
     virtual status_t setConsumerUsageBits(uint64_t usage) { return OK; }
+
+// Producer
+    virtual int query(int what, int* value) {
+        switch(what) {
+            case NATIVE_WINDOW_WIDTH:
+                *value = mWidth;
+                break;
+            case NATIVE_WINDOW_HEIGHT:
+                *value = mHeight;
+                break;
+            default:
+                *value = 0;
+                break;
+        }
+        return OK;
+    }
+
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+        *buf = mBuffer;
+        return OK;
+    }
+
 private:
     sp<GraphicBuffer> mBuffer;
     uint32_t mWidth;
diff --git a/libs/hostgraphics/gui/IGraphicBufferProducer.h b/libs/hostgraphics/gui/IGraphicBufferProducer.h
index a1efd0b..1447a4f 100644
--- a/libs/hostgraphics/gui/IGraphicBufferProducer.h
+++ b/libs/hostgraphics/gui/IGraphicBufferProducer.h
@@ -31,6 +31,10 @@
         // Disconnect any API originally connected from the process calling disconnect.
         AllLocal
     };
+
+    virtual int query(int what, int* value) = 0;
+
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
 };
 
 } // namespace android
diff --git a/libs/hostgraphics/gui/Surface.h b/libs/hostgraphics/gui/Surface.h
index 2573931..0d81037 100644
--- a/libs/hostgraphics/gui/Surface.h
+++ b/libs/hostgraphics/gui/Surface.h
@@ -17,18 +17,21 @@
 #ifndef ANDROID_GUI_SURFACE_H
 #define ANDROID_GUI_SURFACE_H
 
-#include <gui/IGraphicBufferProducer.h>
+#include <system/window.h>
 #include <ui/ANativeObjectBase.h>
 #include <utils/RefBase.h>
-#include <system/window.h>
+
+#include "gui/IGraphicBufferProducer.h"
 
 namespace android {
 
 class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase> {
 public:
-    explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer,
-                     bool controlledByApp = false) {
+    explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false)
+            : mBufferProducer(bufferProducer) {
         ANativeWindow::perform = hook_perform;
+        ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
+        ANativeWindow::query = hook_query;
     }
     static bool isValid(const sp<Surface>& surface) { return surface != nullptr; }
     void allocateBuffers() {}
@@ -48,19 +51,57 @@
         return 0;
     }
     virtual int unlockAndPost() { return 0; }
-    virtual int query(int what, int* value) const { return 0; }
+    virtual int query(int what, int* value) const { return mBufferProducer->query(what, value); }
+
+    status_t setDequeueTimeout(nsecs_t timeout) { return OK; }
+
+    nsecs_t getLastDequeueStartTime() const { return 0; }
 
     virtual void destroy() {}
 
+    int getBuffersDataSpace() { return 0; }
+
 protected:
     virtual ~Surface() {}
 
-    static int hook_perform(ANativeWindow* window, int operation, ...) { return 0; }
+    static int hook_perform(ANativeWindow* window, int operation, ...) {
+        va_list args;
+        va_start(args, operation);
+        Surface* c = getSelf(window);
+        int result = c->perform(operation, args);
+        va_end(args);
+        return result;
+    }
+
+    static int hook_query(const ANativeWindow* window, int what, int* value) {
+        const Surface* c = getSelf(window);
+        return c->query(what, value);
+    }
+
+    static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
+                                  int* fenceFd) {
+        Surface* c = getSelf(window);
+        return c->dequeueBuffer(buffer, fenceFd);
+    }
+
+    virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) {
+        mBufferProducer->requestBuffer(0, &mBuffer);
+        *buffer = mBuffer.get();
+        return OK;
+    }
+    virtual int cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd) { return 0; }
+    virtual int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) { return 0; }
+    virtual int perform(int operation, va_list args) { return 0; }
+    virtual int setSwapInterval(int interval) { return 0; }
+    virtual int setBufferCount(int bufferCount) { return 0; }
 
 private:
     // can't be copied
     Surface& operator=(const Surface& rhs);
     Surface(const Surface& rhs);
+
+    const sp<IGraphicBufferProducer> mBufferProducer;
+    sp<GraphicBuffer> mBuffer;
 };
 
 } // namespace android
diff --git a/libs/hostgraphics/ui/GraphicBuffer.h b/libs/hostgraphics/ui/GraphicBuffer.h
index ac88e44..eec9b23 100644
--- a/libs/hostgraphics/ui/GraphicBuffer.h
+++ b/libs/hostgraphics/ui/GraphicBuffer.h
@@ -22,24 +22,27 @@
 
 #include <vector>
 
+#include <ui/ANativeObjectBase.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
-
 #include <utils/RefBase.h>
 
 namespace android {
 
-class GraphicBuffer : virtual public RefBase {
+class GraphicBuffer : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase> {
 public:
-    GraphicBuffer(uint32_t w, uint32_t h):width(w),height(h) {
+    GraphicBuffer(uint32_t w, uint32_t h) {
         data.resize(w*h);
+        reserved[0] = data.data();
+        width = w;
+        height = h;
     }
     uint32_t getWidth() const           { return static_cast<uint32_t>(width); }
     uint32_t getHeight() const          { return static_cast<uint32_t>(height); }
     uint32_t getStride() const          { return static_cast<uint32_t>(width); }
     uint64_t getUsage() const           { return 0; }
     PixelFormat getPixelFormat() const  { return PIXEL_FORMAT_RGBA_8888; }
-    //uint32_t getLayerCount() const      { return static_cast<uint32_t>(layerCount); }
+
     Rect getBounds() const              { return Rect(width, height); }
 
     status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
@@ -54,8 +57,6 @@
     status_t unlockAsync(int *fenceFd) { return OK; }
 
 private:
-    uint32_t width;
-    uint32_t height;
     std::vector<uint32_t> data;
 };
 
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 341c3e8c..753a699 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_android_core_graphics_stack",
     default_applicable_licenses: ["frameworks_base_libs_hwui_license"],
 }
 
@@ -31,6 +32,7 @@
 aconfig_declarations {
     name: "hwui_flags",
     package: "com.android.graphics.hwui.flags",
+    container: "system",
     srcs: [
         "aconfig/hwui_flags.aconfig",
     ],
@@ -78,13 +80,13 @@
     include_dirs: [
         "external/skia/include/private",
         "external/skia/src/core",
+        "external/skia/src/utils",
     ],
 
     target: {
         android: {
             include_dirs: [
                 "external/skia/src/image",
-                "external/skia/src/utils",
                 "external/skia/src/gpu",
                 "external/skia/src/shaders",
             ],
@@ -92,9 +94,11 @@
         host: {
             include_dirs: [
                 "external/vulkan-headers/include",
+                "frameworks/av/media/ndk/include",
             ],
             cflags: [
                 "-Wno-unused-variable",
+                "-D__INTRODUCED_IN(n)=",
             ],
         },
     },
@@ -140,7 +144,6 @@
                 "libsync",
                 "libui",
                 "aconfig_text_flags_c_lib",
-                "server_configurable_flags",
             ],
             static_libs: [
                 "libEGL_blobCache",
@@ -265,6 +268,7 @@
     cppflags: ["-Wno-conversion-null"],
 
     srcs: [
+        "apex/android_canvas.cpp",
         "apex/android_matrix.cpp",
         "apex/android_paint.cpp",
         "apex/android_region.cpp",
@@ -277,7 +281,6 @@
         android: {
             srcs: [ // sources that depend on android only libraries
                 "apex/android_bitmap.cpp",
-                "apex/android_canvas.cpp",
                 "apex/jni_runtime.cpp",
             ],
         },
@@ -336,6 +339,8 @@
         "jni/android_graphics_ColorSpace.cpp",
         "jni/android_graphics_drawable_AnimatedVectorDrawable.cpp",
         "jni/android_graphics_drawable_VectorDrawable.cpp",
+        "jni/android_graphics_HardwareRenderer.cpp",
+        "jni/android_graphics_HardwareBufferRenderer.cpp",
         "jni/android_graphics_HardwareRendererObserver.cpp",
         "jni/android_graphics_Matrix.cpp",
         "jni/android_graphics_Picture.cpp",
@@ -420,8 +425,6 @@
         android: {
             srcs: [ // sources that depend on android only libraries
                 "jni/android_graphics_TextureLayer.cpp",
-                "jni/android_graphics_HardwareRenderer.cpp",
-                "jni/android_graphics_HardwareBufferRenderer.cpp",
                 "jni/GIFMovie.cpp",
                 "jni/GraphicsStatsService.cpp",
                 "jni/Movie.cpp",
@@ -446,6 +449,12 @@
                 "libstatssocket_lazy",
             ],
         },
+        linux: {
+            srcs: ["platform/linux/utils/SharedLib.cpp"],
+        },
+        darwin: {
+            srcs: ["platform/darwin/utils/SharedLib.cpp"],
+        },
         host: {
             cflags: [
                 "-Wno-unused-const-variable",
@@ -529,13 +538,20 @@
         "effects/GainmapRenderer.cpp",
         "pipeline/skia/BackdropFilterDrawable.cpp",
         "pipeline/skia/HolePunch.cpp",
+        "pipeline/skia/SkiaCpuPipeline.cpp",
         "pipeline/skia/SkiaDisplayList.cpp",
+        "pipeline/skia/SkiaPipeline.cpp",
         "pipeline/skia/SkiaRecordingCanvas.cpp",
         "pipeline/skia/StretchMask.cpp",
         "pipeline/skia/RenderNodeDrawable.cpp",
         "pipeline/skia/ReorderBarrierDrawables.cpp",
         "pipeline/skia/TransformCanvas.cpp",
+        "renderstate/RenderState.cpp",
+        "renderthread/CanvasContext.cpp",
+        "renderthread/DrawFrameTask.cpp",
         "renderthread/Frame.cpp",
+        "renderthread/RenderEffectCapabilityQuery.cpp",
+        "renderthread/RenderProxy.cpp",
         "renderthread/RenderTask.cpp",
         "renderthread/TimeLord.cpp",
         "hwui/AnimatedImageDrawable.cpp",
@@ -568,6 +584,8 @@
         "HWUIProperties.sysprop",
         "Interpolator.cpp",
         "JankTracker.cpp",
+        "Layer.cpp",
+        "LayerUpdateQueue.cpp",
         "LightingInfo.cpp",
         "Matrix.cpp",
         "Mesh.cpp",
@@ -584,6 +602,7 @@
         "SkiaCanvas.cpp",
         "SkiaInterpolator.cpp",
         "Tonemapper.cpp",
+        "TreeInfo.cpp",
         "VectorDrawable.cpp",
     ],
 
@@ -604,23 +623,18 @@
                 "pipeline/skia/GLFunctorDrawable.cpp",
                 "pipeline/skia/LayerDrawable.cpp",
                 "pipeline/skia/ShaderCache.cpp",
+                "pipeline/skia/SkiaGpuPipeline.cpp",
                 "pipeline/skia/SkiaMemoryTracer.cpp",
                 "pipeline/skia/SkiaOpenGLPipeline.cpp",
-                "pipeline/skia/SkiaPipeline.cpp",
                 "pipeline/skia/SkiaProfileRenderer.cpp",
                 "pipeline/skia/SkiaVulkanPipeline.cpp",
                 "pipeline/skia/VkFunctorDrawable.cpp",
                 "pipeline/skia/VkInteropFunctorDrawable.cpp",
-                "renderstate/RenderState.cpp",
                 "renderthread/CacheManager.cpp",
-                "renderthread/CanvasContext.cpp",
-                "renderthread/DrawFrameTask.cpp",
                 "renderthread/EglManager.cpp",
                 "renderthread/ReliableSurface.cpp",
-                "renderthread/RenderEffectCapabilityQuery.cpp",
                 "renderthread/VulkanManager.cpp",
                 "renderthread/VulkanSurface.cpp",
-                "renderthread/RenderProxy.cpp",
                 "renderthread/RenderThread.cpp",
                 "renderthread/HintSessionWrapper.cpp",
                 "service/GraphicsStatsService.cpp",
@@ -629,11 +643,8 @@
                 "AutoBackendTextureRelease.cpp",
                 "DeferredLayerUpdater.cpp",
                 "HardwareBitmapUploader.cpp",
-                "Layer.cpp",
-                "LayerUpdateQueue.cpp",
                 "ProfileDataContainer.cpp",
                 "Readback.cpp",
-                "TreeInfo.cpp",
                 "WebViewFunctorManager.cpp",
                 "protos/graphicsstats.proto",
             ],
@@ -651,6 +662,8 @@
 
             srcs: [
                 "platform/host/renderthread/CacheManager.cpp",
+                "platform/host/renderthread/HintSessionWrapper.cpp",
+                "platform/host/renderthread/ReliableSurface.cpp",
                 "platform/host/renderthread/RenderThread.cpp",
                 "platform/host/ProfileDataContainer.cpp",
                 "platform/host/Readback.cpp",
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index ec53070..c1510d9 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -242,7 +242,7 @@
 
 enum class OverdrawColorSet { Default = 0, Deuteranomaly };
 
-enum class RenderPipelineType { SkiaGL, SkiaVulkan, NotInitialized = 128 };
+enum class RenderPipelineType { SkiaGL, SkiaVulkan, SkiaCpu, NotInitialized = 128 };
 
 enum class StretchEffectBehavior {
     ShaderHWUI,   // Stretch shader in HWUI only, matrix scale in SF
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index f526a28..589abb4 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -16,18 +16,6 @@
 
 #include "RenderNode.h"
 
-#include "DamageAccumulator.h"
-#include "Debug.h"
-#include "Properties.h"
-#include "TreeInfo.h"
-#include "VectorDrawable.h"
-#include "private/hwui/WebViewFunctor.h"
-#ifdef __ANDROID__
-#include "renderthread/CanvasContext.h"
-#else
-#include "DamageAccumulator.h"
-#include "pipeline/skia/SkiaDisplayList.h"
-#endif
 #include <SkPathOps.h>
 #include <gui/TraceUtils.h>
 #include <ui/FatVector.h>
@@ -37,6 +25,14 @@
 #include <sstream>
 #include <string>
 
+#include "DamageAccumulator.h"
+#include "Debug.h"
+#include "Properties.h"
+#include "TreeInfo.h"
+#include "VectorDrawable.h"
+#include "private/hwui/WebViewFunctor.h"
+#include "renderthread/CanvasContext.h"
+
 #ifdef __ANDROID__
 #include "include/gpu/ganesh/SkImageGanesh.h"
 #endif
@@ -186,7 +182,6 @@
 }
 
 void RenderNode::pushLayerUpdate(TreeInfo& info) {
-#ifdef __ANDROID__ // Layoutlib does not support CanvasContext and Layers
     LayerType layerType = properties().effectiveLayerType();
     // If we are not a layer OR we cannot be rendered (eg, view was detached)
     // we need to destroy any Layers we may have had previously
@@ -218,7 +213,6 @@
     // That might be us, so tell CanvasContext that this layer is in the
     // tree and should not be destroyed.
     info.canvasContext.markLayerInUse(this);
-#endif
 }
 
 /**
diff --git a/libs/hwui/RootRenderNode.cpp b/libs/hwui/RootRenderNode.cpp
index ddbbf58..5174e27 100644
--- a/libs/hwui/RootRenderNode.cpp
+++ b/libs/hwui/RootRenderNode.cpp
@@ -18,11 +18,12 @@
 
 #ifdef __ANDROID__ // Layoutlib does not support Looper (windows)
 #include <utils/Looper.h>
+#else
+#include "utils/MessageHandler.h"
 #endif
 
 namespace android::uirenderer {
 
-#ifdef __ANDROID__ // Layoutlib does not support Looper
 class FinishAndInvokeListener : public MessageHandler {
 public:
     explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim) : mAnimator(anim) {
@@ -237,9 +238,13 @@
         // user events, in which case the already posted listener's id will become stale, and
         // the onFinished callback will then be ignored.
         sp<FinishAndInvokeListener> message = new FinishAndInvokeListener(anim);
+#ifdef __ANDROID__  // Layoutlib does not support Looper
         auto looper = Looper::getForThread();
         LOG_ALWAYS_FATAL_IF(looper == nullptr, "Not on a looper thread?");
         looper->sendMessageDelayed(ms2ns(remainingTimeInMs), message, 0);
+#else
+        message->handleMessage(0);
+#endif
         anim->clearOneShotListener();
     }
 }
@@ -285,22 +290,5 @@
 AnimationContext* ContextFactoryImpl::createAnimationContext(renderthread::TimeLord& clock) {
     return new AnimationContextBridge(clock, mRootNode);
 }
-#else
-
-void RootRenderNode::prepareTree(TreeInfo& info) {
-    info.errorHandler = mErrorHandler.get();
-    info.updateWindowPositions = true;
-    RenderNode::prepareTree(info);
-    info.updateWindowPositions = false;
-    info.errorHandler = nullptr;
-}
-
-void RootRenderNode::attachAnimatingNode(RenderNode* animatingNode) { }
-
-void RootRenderNode::destroy() { }
-
-void RootRenderNode::addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { }
-
-#endif
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/RootRenderNode.h b/libs/hwui/RootRenderNode.h
index 1d3f5a8..7a5cda7 100644
--- a/libs/hwui/RootRenderNode.h
+++ b/libs/hwui/RootRenderNode.h
@@ -74,7 +74,6 @@
     void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim);
 };
 
-#ifdef __ANDROID__ // Layoutlib does not support Animations
 class ContextFactoryImpl : public IContextFactory {
 public:
     explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
@@ -84,6 +83,5 @@
 private:
     RootRenderNode* mRootNode;
 };
-#endif
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/SkiaInterpolator.cpp b/libs/hwui/SkiaInterpolator.cpp
index c67b135..5a45ad9 100644
--- a/libs/hwui/SkiaInterpolator.cpp
+++ b/libs/hwui/SkiaInterpolator.cpp
@@ -20,6 +20,7 @@
 #include "include/core/SkTypes.h"
 
 #include <cstdlib>
+#include <cstring>
 #include <log/log.h>
 
 typedef int Dot14;
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index efa9b11..9d16ee86 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -87,7 +87,7 @@
     WebViewFunctorManager::instance().releaseFunctor(functor);
 }
 
-void WebViewFunctor_reportRenderingThreads(int functor, const int32_t* thread_ids, size_t size) {
+void WebViewFunctor_reportRenderingThreads(int functor, const pid_t* thread_ids, size_t size) {
     WebViewFunctorManager::instance().reportRenderingThreads(functor, thread_ids, size);
 }
 
@@ -265,8 +265,8 @@
     funcs.transactionDeleteFunc(transaction);
 }
 
-void WebViewFunctor::reportRenderingThreads(const int32_t* thread_ids, size_t size) {
-    mRenderingThreads = std::vector<int32_t>(thread_ids, thread_ids + size);
+void WebViewFunctor::reportRenderingThreads(const pid_t* thread_ids, size_t size) {
+    mRenderingThreads = std::vector<pid_t>(thread_ids, thread_ids + size);
 }
 
 WebViewFunctorManager& WebViewFunctorManager::instance() {
@@ -355,7 +355,7 @@
     }
 }
 
-void WebViewFunctorManager::reportRenderingThreads(int functor, const int32_t* thread_ids,
+void WebViewFunctorManager::reportRenderingThreads(int functor, const pid_t* thread_ids,
                                                    size_t size) {
     std::lock_guard _lock{mLock};
     for (auto& iter : mFunctors) {
@@ -366,8 +366,8 @@
     }
 }
 
-std::vector<int32_t> WebViewFunctorManager::getRenderingThreadsForActiveFunctors() {
-    std::vector<int32_t> renderingThreads;
+std::vector<pid_t> WebViewFunctorManager::getRenderingThreadsForActiveFunctors() {
+    std::vector<pid_t> renderingThreads;
     std::lock_guard _lock{mLock};
     for (const auto& iter : mActiveFunctors) {
         const auto& functorThreads = iter->getRenderingThreads();
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index 2d77dd8..ec17640 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -17,13 +17,11 @@
 #pragma once
 
 #include <private/hwui/WebViewFunctor.h>
-#ifdef __ANDROID__ // Layoutlib does not support render thread
 #include <renderthread/RenderProxy.h>
-#endif
-
 #include <utils/LightRefBase.h>
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
+
 #include <mutex>
 #include <vector>
 
@@ -38,11 +36,7 @@
 
     class Handle : public LightRefBase<Handle> {
     public:
-        ~Handle() {
-#ifdef __ANDROID__ // Layoutlib does not support render thread
-            renderthread::RenderProxy::destroyFunctor(id());
-#endif
-        }
+        ~Handle() { renderthread::RenderProxy::destroyFunctor(id()); }
 
         int id() const { return mReference.id(); }
 
@@ -60,7 +54,7 @@
 
         void onRemovedFromTree() { mReference.onRemovedFromTree(); }
 
-        const std::vector<int32_t>& getRenderingThreads() const {
+        const std::vector<pid_t>& getRenderingThreads() const {
             return mReference.getRenderingThreads();
         }
 
@@ -85,8 +79,8 @@
     ASurfaceControl* getSurfaceControl();
     void mergeTransaction(ASurfaceTransaction* transaction);
 
-    void reportRenderingThreads(const int32_t* thread_ids, size_t size);
-    const std::vector<int32_t>& getRenderingThreads() const { return mRenderingThreads; }
+    void reportRenderingThreads(const pid_t* thread_ids, size_t size);
+    const std::vector<pid_t>& getRenderingThreads() const { return mRenderingThreads; }
 
     sp<Handle> createHandle() {
         LOG_ALWAYS_FATAL_IF(mCreatedHandle);
@@ -107,7 +101,7 @@
     bool mCreatedHandle = false;
     int32_t mParentSurfaceControlGenerationId = 0;
     ASurfaceControl* mSurfaceControl = nullptr;
-    std::vector<int32_t> mRenderingThreads;
+    std::vector<pid_t> mRenderingThreads;
 };
 
 class WebViewFunctorManager {
@@ -118,8 +112,8 @@
     void releaseFunctor(int functor);
     void onContextDestroyed();
     void destroyFunctor(int functor);
-    void reportRenderingThreads(int functor, const int32_t* thread_ids, size_t size);
-    std::vector<int32_t> getRenderingThreadsForActiveFunctors();
+    void reportRenderingThreads(int functor, const pid_t* thread_ids, size_t size);
+    std::vector<pid_t> getRenderingThreadsForActiveFunctors();
 
     sp<WebViewFunctor::Handle> handleFor(int functor);
 
diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig
index 659bcdc..50f8b39 100644
--- a/libs/hwui/aconfig/hwui_flags.aconfig
+++ b/libs/hwui/aconfig/hwui_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.graphics.hwui.flags"
+container: "system"
 
 flag {
   name: "clip_shader"
diff --git a/libs/hwui/apex/LayoutlibLoader.cpp b/libs/hwui/apex/LayoutlibLoader.cpp
index 770822a..fd9915a 100644
--- a/libs/hwui/apex/LayoutlibLoader.cpp
+++ b/libs/hwui/apex/LayoutlibLoader.cpp
@@ -164,8 +164,10 @@
 } // namespace android
 
 using namespace android;
+using namespace android::uirenderer;
 
 void init_android_graphics() {
+    Properties::overrideRenderPipelineType(RenderPipelineType::SkiaCpu);
     SkGraphics::Init();
 }
 
diff --git a/libs/hwui/effects/GainmapRenderer.cpp b/libs/hwui/effects/GainmapRenderer.cpp
index 3ebf7d1..0a30c6c 100644
--- a/libs/hwui/effects/GainmapRenderer.cpp
+++ b/libs/hwui/effects/GainmapRenderer.cpp
@@ -32,6 +32,8 @@
 #include "src/core/SkColorFilterPriv.h"
 #include "src/core/SkImageInfoPriv.h"
 #include "src/core/SkRuntimeEffectPriv.h"
+
+#include <cmath>
 #endif
 
 namespace android::uirenderer {
@@ -206,12 +208,12 @@
 
     void setupGenericUniforms(const sk_sp<const SkImage>& gainmapImage,
                               const SkGainmapInfo& gainmapInfo) {
-        const SkColor4f logRatioMin({sk_float_log(gainmapInfo.fGainmapRatioMin.fR),
-                                     sk_float_log(gainmapInfo.fGainmapRatioMin.fG),
-                                     sk_float_log(gainmapInfo.fGainmapRatioMin.fB), 1.f});
-        const SkColor4f logRatioMax({sk_float_log(gainmapInfo.fGainmapRatioMax.fR),
-                                     sk_float_log(gainmapInfo.fGainmapRatioMax.fG),
-                                     sk_float_log(gainmapInfo.fGainmapRatioMax.fB), 1.f});
+        const SkColor4f logRatioMin({std::log(gainmapInfo.fGainmapRatioMin.fR),
+                                     std::log(gainmapInfo.fGainmapRatioMin.fG),
+                                     std::log(gainmapInfo.fGainmapRatioMin.fB), 1.f});
+        const SkColor4f logRatioMax({std::log(gainmapInfo.fGainmapRatioMax.fR),
+                                     std::log(gainmapInfo.fGainmapRatioMax.fG),
+                                     std::log(gainmapInfo.fGainmapRatioMax.fB), 1.f});
         const int noGamma = gainmapInfo.fGainmapGamma.fR == 1.f &&
                             gainmapInfo.fGainmapGamma.fG == 1.f &&
                             gainmapInfo.fGainmapGamma.fB == 1.f;
@@ -248,10 +250,10 @@
             float W = 0.f;
             if (targetHdrSdrRatio > mGainmapInfo.fDisplayRatioSdr) {
                 if (targetHdrSdrRatio < mGainmapInfo.fDisplayRatioHdr) {
-                    W = (sk_float_log(targetHdrSdrRatio) -
-                         sk_float_log(mGainmapInfo.fDisplayRatioSdr)) /
-                        (sk_float_log(mGainmapInfo.fDisplayRatioHdr) -
-                         sk_float_log(mGainmapInfo.fDisplayRatioSdr));
+                    W = (std::log(targetHdrSdrRatio) -
+                         std::log(mGainmapInfo.fDisplayRatioSdr)) /
+                        (std::log(mGainmapInfo.fDisplayRatioHdr) -
+                         std::log(mGainmapInfo.fDisplayRatioSdr));
                 } else {
                     W = 1.f;
                 }
diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp
index 0f80c55..b01e38d 100644
--- a/libs/hwui/jni/AnimatedImageDrawable.cpp
+++ b/libs/hwui/jni/AnimatedImageDrawable.cpp
@@ -27,6 +27,8 @@
 #include <hwui/ImageDecoder.h>
 #ifdef __ANDROID__
 #include <utils/Looper.h>
+#else
+#include "utils/MessageHandler.h"
 #endif
 
 #include "ColorFilter.h"
@@ -182,23 +184,6 @@
     drawable->setRepetitionCount(loopCount);
 }
 
-#ifndef __ANDROID__
-struct Message {
-    Message(int w) {}
-};
-
-class MessageHandler : public virtual RefBase {
-protected:
-    virtual ~MessageHandler() override {}
-
-public:
-    /**
-     * Handles a message.
-     */
-    virtual void handleMessage(const Message& message) = 0;
-};
-#endif
-
 class InvokeListener : public MessageHandler {
 public:
     InvokeListener(JNIEnv* env, jobject javaObject) {
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index 9e21f86..d415700 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -1,8 +1,14 @@
 // #define LOG_NDEBUG 0
 #include "Bitmap.h"
 
+#include <android-base/unique_fd.h>
 #include <hwui/Bitmap.h>
 #include <hwui/Paint.h>
+#include <inttypes.h>
+#include <renderthread/RenderProxy.h>
+#include <string.h>
+
+#include <memory>
 
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "Gainmap.h"
@@ -24,16 +30,6 @@
 #include "SkTypes.h"
 #include "android_nio_utils.h"
 
-#ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread
-#include <android-base/unique_fd.h>
-#include <renderthread/RenderProxy.h>
-#endif
-
-#include <inttypes.h>
-#include <string.h>
-
-#include <memory>
-
 #define DEBUG_PARCEL 0
 
 static jclass   gBitmap_class;
@@ -1105,11 +1101,9 @@
 }
 
 static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
-#ifdef __ANDROID__ // Layoutlib does not support render thread
     LocalScopedBitmap bitmapHandle(bitmapPtr);
     if (!bitmapHandle.valid()) return;
     android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
-#endif
 }
 
 static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
diff --git a/libs/hwui/jni/HardwareBufferHelpers.cpp b/libs/hwui/jni/HardwareBufferHelpers.cpp
index 7e3f771..d3b48d3 100644
--- a/libs/hwui/jni/HardwareBufferHelpers.cpp
+++ b/libs/hwui/jni/HardwareBufferHelpers.cpp
@@ -16,7 +16,9 @@
 
 #include "HardwareBufferHelpers.h"
 
+#ifdef __ANDROID__
 #include <dlfcn.h>
+#endif
 #include <log/log.h>
 
 #ifdef __ANDROID__
diff --git a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
index 426644e..948362c 100644
--- a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
+++ b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
@@ -16,22 +16,19 @@
 
 #include "GraphicsJNI.h"
 
-#ifdef __ANDROID__ // Layoutlib does not support Looper and device properties
+#ifdef __ANDROID__  // Layoutlib does not support Looper
 #include <utils/Looper.h>
 #endif
 
-#include <SkRegion.h>
-#include <SkRuntimeEffect.h>
-
+#include <CanvasProperty.h>
 #include <Rect.h>
 #include <RenderNode.h>
-#include <CanvasProperty.h>
+#include <SkRegion.h>
+#include <SkRuntimeEffect.h>
 #include <hwui/Canvas.h>
 #include <hwui/Paint.h>
 #include <minikin/Layout.h>
-#ifdef __ANDROID__ // Layoutlib does not support RenderThread
 #include <renderthread/RenderProxy.h>
-#endif
 
 namespace android {
 
@@ -85,11 +82,7 @@
 }
 
 static jint android_view_DisplayListCanvas_getMaxTextureSize(JNIEnv*, jobject) {
-#ifdef __ANDROID__ // Layoutlib does not support RenderProxy (RenderThread)
     return android::uirenderer::renderthread::RenderProxy::maxTextureSize();
-#else
-    return 4096;
-#endif
 }
 
 static void android_view_DisplayListCanvas_enableZ(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr,
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index d9e2c8c..df9f830 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -25,13 +25,16 @@
 #include <SkColorSpace.h>
 #include <SkData.h>
 #include <SkImage.h>
+#ifdef __ANDROID__
 #include <SkImageAndroid.h>
+#else
+#include <SkImagePriv.h>
+#endif
 #include <SkPicture.h>
 #include <SkPixmap.h>
 #include <SkSerialProcs.h>
 #include <SkStream.h>
 #include <SkTypeface.h>
-#include <dlfcn.h>
 #include <gui/TraceUtils.h>
 #include <include/encode/SkPngEncoder.h>
 #include <inttypes.h>
@@ -39,8 +42,10 @@
 #include <media/NdkImage.h>
 #include <media/NdkImageReader.h>
 #include <nativehelper/JNIPlatformHelp.h>
+#ifdef __ANDROID__
 #include <pipeline/skia/ShaderCache.h>
 #include <private/EGL/cache.h>
+#endif
 #include <renderthread/CanvasContext.h>
 #include <renderthread/RenderProxy.h>
 #include <renderthread/RenderTask.h>
@@ -59,6 +64,7 @@
 #include "JvmErrorReporter.h"
 #include "android_graphics_HardwareRendererObserver.h"
 #include "utils/ForceDark.h"
+#include "utils/SharedLib.h"
 
 namespace android {
 
@@ -498,7 +504,11 @@
                 return sk_ref_sp(img);
             }
             bm.setImmutable();
+#ifdef __ANDROID__
             return SkImages::PinnableRasterFromBitmap(bm);
+#else
+            return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
+#endif
         }
         return sk_ref_sp(img);
     }
@@ -713,6 +723,7 @@
 
 static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
+#ifdef __ANDROID__
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     if (jwidth <= 0 || jheight <= 0) {
         ALOGW("Invalid width %d or height %d", jwidth, jheight);
@@ -796,6 +807,9 @@
     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, cs);
     return bitmap::createBitmap(env, bitmap.release(),
             android::bitmap::kBitmapCreateFlag_Premultiplied);
+#else
+    return nullptr;
+#endif
 }
 
 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
@@ -909,6 +923,7 @@
 
 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
         jstring diskCachePath, jstring skiaDiskCachePath) {
+#ifdef __ANDROID__
     const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
     android::egl_set_cache_filename(cacheArray);
     env->ReleaseStringUTFChars(diskCachePath, cacheArray);
@@ -916,6 +931,7 @@
     const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL);
     uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray);
     env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
+#endif
 }
 
 static jboolean android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv* env, jobject clazz) {
@@ -1092,8 +1108,12 @@
     gCopyRequest.getDestinationBitmap =
             GetMethodIDOrDie(env, copyRequest, "getDestinationBitmap", "(II)J");
 
-    void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
-    fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
+#ifdef __ANDROID__
+    void* handle_ = SharedLib::openSharedLib("libandroid");
+#else
+    void* handle_ = SharedLib::openSharedLib("libandroid_runtime");
+#endif
+    fromSurface = (ANW_fromSurface)SharedLib::getSymbol(handle_, "ANativeWindow_fromSurface");
     LOG_ALWAYS_FATAL_IF(fromSurface == nullptr,
                         "Failed to find required symbol ANativeWindow_fromSurface!");
 
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index a7d6423..6e03bbd 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -15,19 +15,17 @@
  */
 
 #define ATRACE_TAG ATRACE_TAG_VIEW
-#include "GraphicsJNI.h"
-
 #include <Animator.h>
 #include <DamageAccumulator.h>
 #include <Matrix.h>
 #include <RenderNode.h>
-#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
-#include <renderthread/CanvasContext.h>
-#endif
 #include <TreeInfo.h>
 #include <effects/StretchEffect.h>
 #include <gui/TraceUtils.h>
 #include <hwui/Paint.h>
+#include <renderthread/CanvasContext.h>
+
+#include "GraphicsJNI.h"
 
 namespace android {
 
@@ -640,7 +638,6 @@
 
             ATRACE_NAME("Update SurfaceView position");
 
-#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
             JNIEnv* env = jnienv();
             // Update the new position synchronously. We cannot defer this to
             // a worker pool to process asynchronously because the UI thread
@@ -669,7 +666,6 @@
                 env->DeleteGlobalRef(mListener);
                 mListener = nullptr;
             }
-#endif
         }
 
         virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
@@ -682,7 +678,6 @@
 
             ATRACE_NAME("SurfaceView position lost");
             JNIEnv* env = jnienv();
-#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
             // Update the lost position synchronously. We cannot defer this to
             // a worker pool to process asynchronously because the UI thread
             // may be unblocked by the time a worker thread can process this,
@@ -698,7 +693,6 @@
                 env->DeleteGlobalRef(mListener);
                 mListener = nullptr;
             }
-#endif
         }
 
     private:
@@ -750,7 +744,6 @@
                 StretchEffectBehavior::Shader) {
                 JNIEnv* env = jnienv();
 
-#ifdef __ANDROID__  // Layoutlib does not support CanvasContext
                 SkVector stretchDirection = effect->getStretchDirection();
                 jboolean keepListening = env->CallStaticBooleanMethod(
                         gPositionListener.clazz, gPositionListener.callApplyStretch, mListener,
@@ -762,7 +755,6 @@
                     env->DeleteGlobalRef(mListener);
                     mListener = nullptr;
                 }
-#endif
             }
         }
 
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index b870023..8e07a2f 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -15,14 +15,18 @@
  */
 
 #include "ShaderCache.h"
+
 #include <GrDirectContext.h>
 #include <SkData.h>
 #include <gui/TraceUtils.h>
 #include <log/log.h>
 #include <openssl/sha.h>
+
 #include <algorithm>
 #include <array>
+#include <mutex>
 #include <thread>
+
 #include "FileBlobCache.h"
 #include "Properties.h"
 
diff --git a/libs/hwui/pipeline/skia/SkiaCpuPipeline.cpp b/libs/hwui/pipeline/skia/SkiaCpuPipeline.cpp
new file mode 100644
index 0000000..5bbbc10
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaCpuPipeline.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pipeline/skia/SkiaCpuPipeline.h"
+
+#include <system/window.h>
+
+#include "DeviceInfo.h"
+#include "LightingInfo.h"
+#include "renderthread/Frame.h"
+#include "utils/Color.h"
+
+using namespace android::uirenderer::renderthread;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+void SkiaCpuPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
+    // Render all layers that need to be updated, in order.
+    for (size_t i = 0; i < layers.entries().size(); i++) {
+        RenderNode* layerNode = layers.entries()[i].renderNode.get();
+        // only schedule repaint if node still on layer - possible it may have been
+        // removed during a dropped frame, but layers may still remain scheduled so
+        // as not to lose info on what portion is damaged
+        if (CC_UNLIKELY(layerNode->getLayerSurface() == nullptr)) {
+            continue;
+        }
+        bool rendered = renderLayerImpl(layerNode, layers.entries()[i].damage);
+        if (!rendered) {
+            return;
+        }
+    }
+}
+
+// If the given node didn't have a layer surface, or had one of the wrong size, this method
+// creates a new one and returns true. Otherwise does nothing and returns false.
+bool SkiaCpuPipeline::createOrUpdateLayer(RenderNode* node,
+                                          const DamageAccumulator& damageAccumulator,
+                                          ErrorHandler* errorHandler) {
+    // compute the size of the surface (i.e. texture) to be allocated for this layer
+    const int surfaceWidth = ceilf(node->getWidth() / float(LAYER_SIZE)) * LAYER_SIZE;
+    const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;
+
+    SkSurface* layer = node->getLayerSurface();
+    if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
+        SkImageInfo info;
+        info = SkImageInfo::Make(surfaceWidth, surfaceHeight, getSurfaceColorType(),
+                                 kPremul_SkAlphaType, getSurfaceColorSpace());
+        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
+        node->setLayerSurface(SkSurfaces::Raster(info, &props));
+        if (node->getLayerSurface()) {
+            // update the transform in window of the layer to reset its origin wrt light source
+            // position
+            Matrix4 windowTransform;
+            damageAccumulator.computeCurrentTransform(&windowTransform);
+            node->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
+        } else {
+            String8 cachesOutput;
+            mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
+                                                         &mRenderThread.renderState());
+            ALOGE("%s", cachesOutput.c_str());
+            if (errorHandler) {
+                std::ostringstream err;
+                err << "Unable to create layer for " << node->getName();
+                const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
+                err << ", size " << info.width() << "x" << info.height() << " max size "
+                    << maxTextureSize << " color type " << (int)info.colorType() << " has context "
+                    << (int)(mRenderThread.getGrContext() != nullptr);
+                errorHandler->onError(err.str());
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+MakeCurrentResult SkiaCpuPipeline::makeCurrent() {
+    return MakeCurrentResult::AlreadyCurrent;
+}
+
+Frame SkiaCpuPipeline::getFrame() {
+    return Frame(mSurface->width(), mSurface->height(), 0);
+}
+
+IRenderPipeline::DrawResult SkiaCpuPipeline::draw(
+        const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+        const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+        const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+        const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
+        const HardwareBufferRenderParams& bufferParams, std::mutex& profilerLock) {
+    LightingInfo::updateLighting(lightGeometry, lightInfo);
+    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, mSurface,
+                SkMatrix::I());
+    return {true, IRenderPipeline::DrawResult::kUnknownTime, android::base::unique_fd{}};
+}
+
+bool SkiaCpuPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior) {
+    if (surface) {
+        ANativeWindowBuffer* buffer;
+        surface->dequeueBuffer(surface, &buffer, nullptr);
+        int width, height;
+        surface->query(surface, NATIVE_WINDOW_WIDTH, &width);
+        surface->query(surface, NATIVE_WINDOW_HEIGHT, &height);
+        SkImageInfo imageInfo =
+                SkImageInfo::Make(width, height, mSurfaceColorType,
+                                  SkAlphaType::kPremul_SkAlphaType, mSurfaceColorSpace);
+        size_t widthBytes = width * imageInfo.bytesPerPixel();
+        void* pixels = buffer->reserved[0];
+        mSurface = SkSurfaces::WrapPixels(imageInfo, pixels, widthBytes);
+    } else {
+        mSurface = sk_sp<SkSurface>();
+    }
+    return true;
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaCpuPipeline.h b/libs/hwui/pipeline/skia/SkiaCpuPipeline.h
new file mode 100644
index 0000000..5a1014c
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaCpuPipeline.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "pipeline/skia/SkiaPipeline.h"
+
+namespace android {
+
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaCpuPipeline : public SkiaPipeline {
+public:
+    SkiaCpuPipeline(renderthread::RenderThread& thread) : SkiaPipeline(thread) {}
+    ~SkiaCpuPipeline() {}
+
+    bool pinImages(std::vector<SkImage*>& mutableImages) override { return false; }
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
+    void unpinImages() override {}
+
+    // If the given node didn't have a layer surface, or had one of the wrong size, this method
+    // creates a new one and returns true. Otherwise does nothing and returns false.
+    bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+                             ErrorHandler* errorHandler) override;
+    void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) override;
+    void setHardwareBuffer(AHardwareBuffer* hardwareBuffer) override {}
+    bool hasHardwareBuffer() override { return false; }
+
+    renderthread::MakeCurrentResult makeCurrent() override;
+    renderthread::Frame getFrame() override;
+    renderthread::IRenderPipeline::DrawResult draw(
+            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+            const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
+            const renderthread::HardwareBufferRenderParams& bufferParams,
+            std::mutex& profilerLock) override;
+    bool swapBuffers(const renderthread::Frame& frame, IRenderPipeline::DrawResult& drawResult,
+                     const SkRect& screenDirty, FrameInfo* currentFrameInfo,
+                     bool* requireSwap) override {
+        return false;
+    }
+    DeferredLayerUpdater* createTextureLayer() override { return nullptr; }
+    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
+    [[nodiscard]] android::base::unique_fd flush() override {
+        return android::base::unique_fd(-1);
+    };
+    void onStop() override {}
+    bool isSurfaceReady() override { return mSurface.get() != nullptr; }
+    bool isContextReady() override { return true; }
+
+    const SkM44& getPixelSnapMatrix() const override {
+        static const SkM44 sSnapMatrix = SkM44();
+        return sSnapMatrix;
+    }
+
+private:
+    sk_sp<SkSurface> mSurface;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index e0216b6..36dc933 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -15,23 +15,19 @@
  */
 
 #include "SkiaDisplayList.h"
-#include "FunctorDrawable.h"
-
-#include "DumpOpsCanvas.h"
-#ifdef __ANDROID__ // Layoutlib does not support SkiaPipeline
-#include "SkiaPipeline.h"
-#else
-#include "DamageAccumulator.h"
-#endif
-#include "TreeInfo.h"
-#include "VectorDrawable.h"
-#ifdef __ANDROID__
-#include "renderthread/CanvasContext.h"
-#endif
 
 #include <SkImagePriv.h>
 #include <SkPathOps.h>
 
+// clang-format off
+#include "FunctorDrawable.h" // Must be included before DumpOpsCanvas.h
+#include "DumpOpsCanvas.h"
+// clang-format on
+#include "SkiaPipeline.h"
+#include "TreeInfo.h"
+#include "VectorDrawable.h"
+#include "renderthread/CanvasContext.h"
+
 namespace android {
 namespace uirenderer {
 namespace skiapipeline {
@@ -101,7 +97,6 @@
     // If the prepare tree is triggered by the UI thread and no previous call to
     // pinImages has failed then we must pin all mutable images in the GPU cache
     // until the next UI thread draw.
-#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
     if (info.prepareTextures && !info.canvasContext.pinImages(mMutableImages)) {
         // In the event that pinning failed we prevent future pinImage calls for the
         // remainder of this tree traversal and also unpin any currently pinned images
@@ -110,11 +105,11 @@
         info.canvasContext.unpinImages();
     }
 
+#ifdef __ANDROID__
     auto grContext = info.canvasContext.getGrContext();
     for (const auto& bufferData : mMeshBufferData) {
         bufferData->updateBuffers(grContext);
     }
-
 #endif
 
     bool hasBackwardProjectedNodesHere = false;
diff --git a/libs/hwui/pipeline/skia/SkiaGpuPipeline.cpp b/libs/hwui/pipeline/skia/SkiaGpuPipeline.cpp
new file mode 100644
index 0000000..7bfbfdc
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaGpuPipeline.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pipeline/skia/SkiaGpuPipeline.h"
+
+#include <SkImageAndroid.h>
+#include <gui/TraceUtils.h>
+#include <include/android/SkSurfaceAndroid.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+
+using namespace android::uirenderer::renderthread;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+SkiaGpuPipeline::SkiaGpuPipeline(RenderThread& thread) : SkiaPipeline(thread) {}
+
+SkiaGpuPipeline::~SkiaGpuPipeline() {
+    unpinImages();
+}
+
+void SkiaGpuPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
+    sk_sp<GrDirectContext> cachedContext;
+
+    // Render all layers that need to be updated, in order.
+    for (size_t i = 0; i < layers.entries().size(); i++) {
+        RenderNode* layerNode = layers.entries()[i].renderNode.get();
+        // only schedule repaint if node still on layer - possible it may have been
+        // removed during a dropped frame, but layers may still remain scheduled so
+        // as not to lose info on what portion is damaged
+        if (CC_UNLIKELY(layerNode->getLayerSurface() == nullptr)) {
+            continue;
+        }
+        bool rendered = renderLayerImpl(layerNode, layers.entries()[i].damage);
+        if (!rendered) {
+            return;
+        }
+        // cache the current context so that we can defer flushing it until
+        // either all the layers have been rendered or the context changes
+        GrDirectContext* currentContext =
+                GrAsDirectContext(layerNode->getLayerSurface()->getCanvas()->recordingContext());
+        if (cachedContext.get() != currentContext) {
+            if (cachedContext.get()) {
+                ATRACE_NAME("flush layers (context changed)");
+                cachedContext->flushAndSubmit();
+            }
+            cachedContext.reset(SkSafeRef(currentContext));
+        }
+    }
+    if (cachedContext.get()) {
+        ATRACE_NAME("flush layers");
+        cachedContext->flushAndSubmit();
+    }
+}
+
+// If the given node didn't have a layer surface, or had one of the wrong size, this method
+// creates a new one and returns true. Otherwise does nothing and returns false.
+bool SkiaGpuPipeline::createOrUpdateLayer(RenderNode* node,
+                                          const DamageAccumulator& damageAccumulator,
+                                          ErrorHandler* errorHandler) {
+    // compute the size of the surface (i.e. texture) to be allocated for this layer
+    const int surfaceWidth = ceilf(node->getWidth() / float(LAYER_SIZE)) * LAYER_SIZE;
+    const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;
+
+    SkSurface* layer = node->getLayerSurface();
+    if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
+        SkImageInfo info;
+        info = SkImageInfo::Make(surfaceWidth, surfaceHeight, getSurfaceColorType(),
+                                 kPremul_SkAlphaType, getSurfaceColorSpace());
+        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
+        SkASSERT(mRenderThread.getGrContext() != nullptr);
+        node->setLayerSurface(SkSurfaces::RenderTarget(mRenderThread.getGrContext(),
+                                                       skgpu::Budgeted::kYes, info, 0,
+                                                       this->getSurfaceOrigin(), &props));
+        if (node->getLayerSurface()) {
+            // update the transform in window of the layer to reset its origin wrt light source
+            // position
+            Matrix4 windowTransform;
+            damageAccumulator.computeCurrentTransform(&windowTransform);
+            node->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
+        } else {
+            String8 cachesOutput;
+            mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
+                                                         &mRenderThread.renderState());
+            ALOGE("%s", cachesOutput.c_str());
+            if (errorHandler) {
+                std::ostringstream err;
+                err << "Unable to create layer for " << node->getName();
+                const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
+                err << ", size " << info.width() << "x" << info.height() << " max size "
+                    << maxTextureSize << " color type " << (int)info.colorType() << " has context "
+                    << (int)(mRenderThread.getGrContext() != nullptr);
+                errorHandler->onError(err.str());
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+bool SkiaGpuPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
+    if (!mRenderThread.getGrContext()) {
+        ALOGD("Trying to pin an image with an invalid GrContext");
+        return false;
+    }
+    for (SkImage* image : mutableImages) {
+        if (skgpu::ganesh::PinAsTexture(mRenderThread.getGrContext(), image)) {
+            mPinnedImages.emplace_back(sk_ref_sp(image));
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+void SkiaGpuPipeline::unpinImages() {
+    for (auto& image : mPinnedImages) {
+        skgpu::ganesh::UnpinTexture(mRenderThread.getGrContext(), image.get());
+    }
+    mPinnedImages.clear();
+}
+
+void SkiaGpuPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
+    GrDirectContext* context = thread.getGrContext();
+    if (context && !bitmap->isHardware()) {
+        ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
+        auto image = bitmap->makeImage();
+        if (image.get()) {
+            skgpu::ganesh::PinAsTexture(context, image.get());
+            skgpu::ganesh::UnpinTexture(context, image.get());
+            // A submit is necessary as there may not be a frame coming soon, so without a call
+            // to submit these texture uploads can just sit in the queue building up until
+            // we run out of RAM
+            context->flushAndSubmit();
+        }
+    }
+}
+
+sk_sp<SkSurface> SkiaGpuPipeline::getBufferSkSurface(
+        const renderthread::HardwareBufferRenderParams& bufferParams) {
+    auto bufferColorSpace = bufferParams.getColorSpace();
+    if (mBufferSurface == nullptr || mBufferColorSpace == nullptr ||
+        !SkColorSpace::Equals(mBufferColorSpace.get(), bufferColorSpace.get())) {
+        mBufferSurface = SkSurfaces::WrapAndroidHardwareBuffer(
+                mRenderThread.getGrContext(), mHardwareBuffer, kTopLeft_GrSurfaceOrigin,
+                bufferColorSpace, nullptr, true);
+        mBufferColorSpace = bufferColorSpace;
+    }
+    return mBufferSurface;
+}
+
+void SkiaGpuPipeline::dumpResourceCacheUsage() const {
+    int resources;
+    size_t bytes;
+    mRenderThread.getGrContext()->getResourceCacheUsage(&resources, &bytes);
+    size_t maxBytes = mRenderThread.getGrContext()->getResourceCacheLimit();
+
+    SkString log("Resource Cache Usage:\n");
+    log.appendf("%8d items\n", resources);
+    log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n", bytes,
+                bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
+
+    ALOGD("%s", log.c_str());
+}
+
+void SkiaGpuPipeline::setHardwareBuffer(AHardwareBuffer* buffer) {
+    if (mHardwareBuffer) {
+        AHardwareBuffer_release(mHardwareBuffer);
+        mHardwareBuffer = nullptr;
+    }
+
+    if (buffer) {
+        AHardwareBuffer_acquire(buffer);
+        mHardwareBuffer = buffer;
+    }
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index c8d5987..e4b1f916 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -14,25 +14,25 @@
  * limitations under the License.
  */
 
-#include "SkiaOpenGLPipeline.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
 
-#include <include/gpu/ganesh/SkSurfaceGanesh.h>
-#include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
-#include <include/gpu/gl/GrGLTypes.h>
 #include <GrBackendSurface.h>
 #include <SkBlendMode.h>
 #include <SkImageInfo.h>
 #include <cutils/properties.h>
 #include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
+#include <include/gpu/gl/GrGLTypes.h>
 #include <strings.h>
 
 #include "DeferredLayerUpdater.h"
 #include "FrameInfo.h"
-#include "LayerDrawable.h"
 #include "LightingInfo.h"
-#include "SkiaPipeline.h"
-#include "SkiaProfileRenderer.h"
 #include "hwui/Bitmap.h"
+#include "pipeline/skia/LayerDrawable.h"
+#include "pipeline/skia/SkiaGpuPipeline.h"
+#include "pipeline/skia/SkiaProfileRenderer.h"
 #include "private/hwui/DrawGlInfo.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/EglManager.h"
@@ -47,7 +47,7 @@
 namespace skiapipeline {
 
 SkiaOpenGLPipeline::SkiaOpenGLPipeline(RenderThread& thread)
-        : SkiaPipeline(thread), mEglManager(thread.eglManager()) {
+        : SkiaGpuPipeline(thread), mEglManager(thread.eglManager()) {
     thread.renderState().registerContextCallback(this);
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
deleted file mode 100644
index ebe8b6e..0000000
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <EGL/egl.h>
-#include <system/window.h>
-
-#include "SkiaPipeline.h"
-#include "renderstate/RenderState.h"
-#include "renderthread/HardwareBufferRenderParams.h"
-
-namespace android {
-
-class Bitmap;
-
-namespace uirenderer {
-namespace skiapipeline {
-
-class SkiaOpenGLPipeline : public SkiaPipeline, public IGpuContextCallback {
-public:
-    SkiaOpenGLPipeline(renderthread::RenderThread& thread);
-    virtual ~SkiaOpenGLPipeline();
-
-    renderthread::MakeCurrentResult makeCurrent() override;
-    renderthread::Frame getFrame() override;
-    renderthread::IRenderPipeline::DrawResult draw(
-            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
-            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
-            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
-            const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
-            const renderthread::HardwareBufferRenderParams& bufferParams,
-            std::mutex& profilerLock) override;
-    GrSurfaceOrigin getSurfaceOrigin() override { return kBottomLeft_GrSurfaceOrigin; }
-    bool swapBuffers(const renderthread::Frame& frame, IRenderPipeline::DrawResult& drawResult,
-                     const SkRect& screenDirty, FrameInfo* currentFrameInfo,
-                     bool* requireSwap) override;
-    DeferredLayerUpdater* createTextureLayer() override;
-    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
-    [[nodiscard]] android::base::unique_fd flush() override;
-    void onStop() override;
-    bool isSurfaceReady() override;
-    bool isContextReady() override;
-
-    const SkM44& getPixelSnapMatrix() const override {
-        // Small (~1/16th) nudge to ensure that pixel-aligned non-AA'd draws fill the
-        // desired fragment
-        static const SkScalar kOffset = 0.063f;
-        static const SkM44 sSnapMatrix = SkM44::Translate(kOffset, kOffset);
-        return sSnapMatrix;
-    }
-
-    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
-
-protected:
-    void onContextDestroyed() override;
-
-private:
-    renderthread::EglManager& mEglManager;
-    EGLSurface mEglSurface = EGL_NO_SURFACE;
-    sp<ANativeWindow> mNativeWindow;
-    renderthread::SwapBehavior mSwapBehavior = renderthread::SwapBehavior::kSwap_discardBuffer;
-};
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 99469d1..dc669a5 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -14,11 +14,8 @@
  * limitations under the License.
  */
 
-#include "SkiaPipeline.h"
+#include "pipeline/skia/SkiaPipeline.h"
 
-#include <include/android/SkSurfaceAndroid.h>
-#include <include/gpu/ganesh/SkSurfaceGanesh.h>
-#include <include/encode/SkPngEncoder.h>
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkColorSpace.h>
@@ -27,7 +24,6 @@
 #include <SkImageAndroid.h>
 #include <SkImageInfo.h>
 #include <SkMatrix.h>
-#include <SkMultiPictureDocument.h>
 #include <SkOverdrawCanvas.h>
 #include <SkOverdrawColorFilter.h>
 #include <SkPicture.h>
@@ -40,6 +36,10 @@
 #include <SkTypeface.h>
 #include <android-base/properties.h>
 #include <gui/TraceUtils.h>
+#include <include/android/SkSurfaceAndroid.h>
+#include <include/docs/SkMultiPictureDocument.h>
+#include <include/encode/SkPngEncoder.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <unistd.h>
 
 #include <sstream>
@@ -62,37 +62,13 @@
     setSurfaceColorProperties(mColorMode);
 }
 
-SkiaPipeline::~SkiaPipeline() {
-    unpinImages();
-}
+SkiaPipeline::~SkiaPipeline() {}
 
 void SkiaPipeline::onDestroyHardwareResources() {
     unpinImages();
     mRenderThread.cacheManager().trimStaleResources();
 }
 
-bool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
-    if (!mRenderThread.getGrContext()) {
-        ALOGD("Trying to pin an image with an invalid GrContext");
-        return false;
-    }
-    for (SkImage* image : mutableImages) {
-        if (skgpu::ganesh::PinAsTexture(mRenderThread.getGrContext(), image)) {
-            mPinnedImages.emplace_back(sk_ref_sp(image));
-        } else {
-            return false;
-        }
-    }
-    return true;
-}
-
-void SkiaPipeline::unpinImages() {
-    for (auto& image : mPinnedImages) {
-        skgpu::ganesh::UnpinTexture(mRenderThread.getGrContext(), image.get());
-    }
-    mPinnedImages.clear();
-}
-
 void SkiaPipeline::renderLayers(const LightGeometry& lightGeometry,
                                 LayerUpdateQueue* layerUpdateQueue, bool opaque,
                                 const LightInfo& lightInfo) {
@@ -102,136 +78,48 @@
     layerUpdateQueue->clear();
 }
 
-void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
-    sk_sp<GrDirectContext> cachedContext;
-
-    // Render all layers that need to be updated, in order.
-    for (size_t i = 0; i < layers.entries().size(); i++) {
-        RenderNode* layerNode = layers.entries()[i].renderNode.get();
-        // only schedule repaint if node still on layer - possible it may have been
-        // removed during a dropped frame, but layers may still remain scheduled so
-        // as not to lose info on what portion is damaged
-        if (CC_UNLIKELY(layerNode->getLayerSurface() == nullptr)) {
-            continue;
-        }
-        SkASSERT(layerNode->getLayerSurface());
-        SkiaDisplayList* displayList = layerNode->getDisplayList().asSkiaDl();
-        if (!displayList || displayList->isEmpty()) {
-            ALOGE("%p drawLayers(%s) : missing drawable", layerNode, layerNode->getName());
-            return;
-        }
-
-        const Rect& layerDamage = layers.entries()[i].damage;
-
-        SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
-
-        int saveCount = layerCanvas->save();
-        SkASSERT(saveCount == 1);
-
-        layerCanvas->androidFramework_setDeviceClipRestriction(layerDamage.toSkIRect());
-
-        // TODO: put localized light center calculation and storage to a drawable related code.
-        // It does not seem right to store something localized in a global state
-        // fix here and in recordLayers
-        const Vector3 savedLightCenter(LightingInfo::getLightCenterRaw());
-        Vector3 transformedLightCenter(savedLightCenter);
-        // map current light center into RenderNode's coordinate space
-        layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(transformedLightCenter);
-        LightingInfo::setLightCenterRaw(transformedLightCenter);
-
-        const RenderProperties& properties = layerNode->properties();
-        const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
-        if (properties.getClipToBounds() && layerCanvas->quickReject(bounds)) {
-            return;
-        }
-
-        ATRACE_FORMAT("drawLayer [%s] %.1f x %.1f", layerNode->getName(), bounds.width(),
-                      bounds.height());
-
-        layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
-        layerCanvas->clear(SK_ColorTRANSPARENT);
-
-        RenderNodeDrawable root(layerNode, layerCanvas, false);
-        root.forceDraw(layerCanvas);
-        layerCanvas->restoreToCount(saveCount);
-
-        LightingInfo::setLightCenterRaw(savedLightCenter);
-
-        // cache the current context so that we can defer flushing it until
-        // either all the layers have been rendered or the context changes
-        GrDirectContext* currentContext =
-            GrAsDirectContext(layerNode->getLayerSurface()->getCanvas()->recordingContext());
-        if (cachedContext.get() != currentContext) {
-            if (cachedContext.get()) {
-                ATRACE_NAME("flush layers (context changed)");
-                cachedContext->flushAndSubmit();
-            }
-            cachedContext.reset(SkSafeRef(currentContext));
-        }
+bool SkiaPipeline::renderLayerImpl(RenderNode* layerNode, const Rect& layerDamage) {
+    SkASSERT(layerNode->getLayerSurface());
+    SkiaDisplayList* displayList = layerNode->getDisplayList().asSkiaDl();
+    if (!displayList || displayList->isEmpty()) {
+        ALOGE("%p drawLayers(%s) : missing drawable", layerNode, layerNode->getName());
+        return false;
     }
 
-    if (cachedContext.get()) {
-        ATRACE_NAME("flush layers");
-        cachedContext->flushAndSubmit();
-    }
-}
+    SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
 
-bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
-                                       ErrorHandler* errorHandler) {
-    // compute the size of the surface (i.e. texture) to be allocated for this layer
-    const int surfaceWidth = ceilf(node->getWidth() / float(LAYER_SIZE)) * LAYER_SIZE;
-    const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;
+    int saveCount = layerCanvas->save();
+    SkASSERT(saveCount == 1);
 
-    SkSurface* layer = node->getLayerSurface();
-    if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
-        SkImageInfo info;
-        info = SkImageInfo::Make(surfaceWidth, surfaceHeight, getSurfaceColorType(),
-                                 kPremul_SkAlphaType, getSurfaceColorSpace());
-        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
-        SkASSERT(mRenderThread.getGrContext() != nullptr);
-        node->setLayerSurface(SkSurfaces::RenderTarget(mRenderThread.getGrContext(),
-                                                       skgpu::Budgeted::kYes, info, 0,
-                                                       this->getSurfaceOrigin(), &props));
-        if (node->getLayerSurface()) {
-            // update the transform in window of the layer to reset its origin wrt light source
-            // position
-            Matrix4 windowTransform;
-            damageAccumulator.computeCurrentTransform(&windowTransform);
-            node->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
-        } else {
-            String8 cachesOutput;
-            mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
-                                                         &mRenderThread.renderState());
-            ALOGE("%s", cachesOutput.c_str());
-            if (errorHandler) {
-                std::ostringstream err;
-                err << "Unable to create layer for " << node->getName();
-                const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
-                err << ", size " << info.width() << "x" << info.height() << " max size "
-                    << maxTextureSize << " color type " << (int)info.colorType() << " has context "
-                    << (int)(mRenderThread.getGrContext() != nullptr);
-                errorHandler->onError(err.str());
-            }
-        }
-        return true;
-    }
-    return false;
-}
+    layerCanvas->androidFramework_setDeviceClipRestriction(layerDamage.toSkIRect());
 
-void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
-    GrDirectContext* context = thread.getGrContext();
-    if (context && !bitmap->isHardware()) {
-        ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
-        auto image = bitmap->makeImage();
-        if (image.get()) {
-            skgpu::ganesh::PinAsTexture(context, image.get());
-            skgpu::ganesh::UnpinTexture(context, image.get());
-            // A submit is necessary as there may not be a frame coming soon, so without a call
-            // to submit these texture uploads can just sit in the queue building up until
-            // we run out of RAM
-            context->flushAndSubmit();
-        }
+    // TODO: put localized light center calculation and storage to a drawable related code.
+    // It does not seem right to store something localized in a global state
+    // fix here and in recordLayers
+    const Vector3 savedLightCenter(LightingInfo::getLightCenterRaw());
+    Vector3 transformedLightCenter(savedLightCenter);
+    // map current light center into RenderNode's coordinate space
+    layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(transformedLightCenter);
+    LightingInfo::setLightCenterRaw(transformedLightCenter);
+
+    const RenderProperties& properties = layerNode->properties();
+    const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
+    if (properties.getClipToBounds() && layerCanvas->quickReject(bounds)) {
+        return false;
     }
+
+    ATRACE_FORMAT("drawLayer [%s] %.1f x %.1f", layerNode->getName(), bounds.width(),
+                  bounds.height());
+
+    layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
+    layerCanvas->clear(SK_ColorTRANSPARENT);
+
+    RenderNodeDrawable root(layerNode, layerCanvas, false);
+    root.forceDraw(layerCanvas);
+    layerCanvas->restoreToCount(saveCount);
+
+    LightingInfo::setLightCenterRaw(savedLightCenter);
+    return true;
 }
 
 static void savePictureAsync(const sk_sp<SkData>& data, const std::string& filename) {
@@ -297,7 +185,7 @@
         // we need to keep it until after mMultiPic.close()
         // procs is passed as a pointer, but just as a method of having an optional default.
         // procs doesn't need to outlive this Make call.
-        mMultiPic = SkMakeMultiPictureDocument(mOpenMultiPicStream.get(), &procs,
+        mMultiPic = SkMultiPictureDocument::Make(mOpenMultiPicStream.get(), &procs,
             [sharingCtx = mSerialContext.get()](const SkPicture* pic) {
                     SkSharingSerialContext::collectNonTextureImagesFromPicture(pic, sharingCtx);
             });
@@ -599,45 +487,6 @@
     }
 }
 
-void SkiaPipeline::dumpResourceCacheUsage() const {
-    int resources;
-    size_t bytes;
-    mRenderThread.getGrContext()->getResourceCacheUsage(&resources, &bytes);
-    size_t maxBytes = mRenderThread.getGrContext()->getResourceCacheLimit();
-
-    SkString log("Resource Cache Usage:\n");
-    log.appendf("%8d items\n", resources);
-    log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n", bytes,
-                bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
-
-    ALOGD("%s", log.c_str());
-}
-
-void SkiaPipeline::setHardwareBuffer(AHardwareBuffer* buffer) {
-    if (mHardwareBuffer) {
-        AHardwareBuffer_release(mHardwareBuffer);
-        mHardwareBuffer = nullptr;
-    }
-
-    if (buffer) {
-        AHardwareBuffer_acquire(buffer);
-        mHardwareBuffer = buffer;
-    }
-}
-
-sk_sp<SkSurface> SkiaPipeline::getBufferSkSurface(
-        const renderthread::HardwareBufferRenderParams& bufferParams) {
-    auto bufferColorSpace = bufferParams.getColorSpace();
-    if (mBufferSurface == nullptr || mBufferColorSpace == nullptr ||
-        !SkColorSpace::Equals(mBufferColorSpace.get(), bufferColorSpace.get())) {
-        mBufferSurface = SkSurfaces::WrapAndroidHardwareBuffer(
-                mRenderThread.getGrContext(), mHardwareBuffer, kTopLeft_GrSurfaceOrigin,
-                bufferColorSpace, nullptr, true);
-        mBufferColorSpace = bufferColorSpace;
-    }
-    return mBufferSurface;
-}
-
 void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
     mColorMode = colorMode;
     switch (colorMode) {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index befee89..823b209 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -18,7 +18,6 @@
 
 #include <SkColorSpace.h>
 #include <SkDocument.h>
-#include <SkMultiPictureDocument.h>
 #include <SkSurface.h>
 
 #include "Lighting.h"
@@ -42,18 +41,9 @@
 
     void onDestroyHardwareResources() override;
 
-    bool pinImages(std::vector<SkImage*>& mutableImages) override;
-    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
-    void unpinImages() override;
-
     void renderLayers(const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
                       bool opaque, const LightInfo& lightInfo) override;
 
-    // If the given node didn't have a layer surface, or had one of the wrong size, this method
-    // creates a new one and returns true. Otherwise does nothing and returns false.
-    bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
-                             ErrorHandler* errorHandler) override;
-
     void setSurfaceColorProperties(ColorMode colorMode) override;
     SkColorType getSurfaceColorType() const override { return mSurfaceColorType; }
     sk_sp<SkColorSpace> getSurfaceColorSpace() override { return mSurfaceColorSpace; }
@@ -63,9 +53,8 @@
                      const Rect& contentDrawBounds, sk_sp<SkSurface> surface,
                      const SkMatrix& preTransform);
 
-    static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
-
-    void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque);
+    bool renderLayerImpl(RenderNode* layerNode, const Rect& layerDamage);
+    virtual void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) = 0;
 
     // Sets the recording callback to the provided function and the recording mode
     // to CallbackAPI
@@ -75,19 +64,11 @@
         mCaptureMode = callback ? CaptureMode::CallbackAPI : CaptureMode::None;
     }
 
-    virtual void setHardwareBuffer(AHardwareBuffer* buffer) override;
-    bool hasHardwareBuffer() override { return mHardwareBuffer != nullptr; }
-
     void setTargetSdrHdrRatio(float ratio) override;
 
 protected:
-    sk_sp<SkSurface> getBufferSkSurface(
-            const renderthread::HardwareBufferRenderParams& bufferParams);
-    void dumpResourceCacheUsage() const;
-
     renderthread::RenderThread& mRenderThread;
 
-    AHardwareBuffer* mHardwareBuffer = nullptr;
     sk_sp<SkSurface> mBufferSurface = nullptr;
     sk_sp<SkColorSpace> mBufferColorSpace = nullptr;
 
@@ -125,8 +106,6 @@
     // Set up a multi frame capture.
     bool setupMultiFrameCapture();
 
-    std::vector<sk_sp<SkImage>> mPinnedImages;
-
     // Block of properties used only for debugging to record a SkPicture and save it in a file.
     // There are three possible ways of recording drawing commands.
     enum class CaptureMode {
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index fd0a8e0..d06dba0 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "SkiaVulkanPipeline.h"
+#include "pipeline/skia/SkiaVulkanPipeline.h"
 
 #include <GrDirectContext.h>
 #include <GrTypes.h>
@@ -28,10 +28,10 @@
 #include "DeferredLayerUpdater.h"
 #include "LightingInfo.h"
 #include "Readback.h"
-#include "ShaderCache.h"
-#include "SkiaPipeline.h"
-#include "SkiaProfileRenderer.h"
-#include "VkInteropFunctorDrawable.h"
+#include "pipeline/skia/ShaderCache.h"
+#include "pipeline/skia/SkiaGpuPipeline.h"
+#include "pipeline/skia/SkiaProfileRenderer.h"
+#include "pipeline/skia/VkInteropFunctorDrawable.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
 #include "renderthread/IRenderPipeline.h"
@@ -42,7 +42,8 @@
 namespace uirenderer {
 namespace skiapipeline {
 
-SkiaVulkanPipeline::SkiaVulkanPipeline(renderthread::RenderThread& thread) : SkiaPipeline(thread) {
+SkiaVulkanPipeline::SkiaVulkanPipeline(renderthread::RenderThread& thread)
+        : SkiaGpuPipeline(thread) {
     thread.renderState().registerContextCallback(this);
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
deleted file mode 100644
index 624eaa5..0000000
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "SkRefCnt.h"
-#include "SkiaPipeline.h"
-#include "renderstate/RenderState.h"
-#include "renderthread/HardwareBufferRenderParams.h"
-#include "renderthread/VulkanManager.h"
-#include "renderthread/VulkanSurface.h"
-
-class SkBitmap;
-struct SkRect;
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-class SkiaVulkanPipeline : public SkiaPipeline, public IGpuContextCallback {
-public:
-    explicit SkiaVulkanPipeline(renderthread::RenderThread& thread);
-    virtual ~SkiaVulkanPipeline();
-
-    renderthread::MakeCurrentResult makeCurrent() override;
-    renderthread::Frame getFrame() override;
-    renderthread::IRenderPipeline::DrawResult draw(
-            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
-            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
-            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
-            const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
-            const renderthread::HardwareBufferRenderParams& bufferParams,
-            std::mutex& profilerLock) override;
-    GrSurfaceOrigin getSurfaceOrigin() override { return kTopLeft_GrSurfaceOrigin; }
-    bool swapBuffers(const renderthread::Frame& frame, IRenderPipeline::DrawResult& drawResult,
-                     const SkRect& screenDirty, FrameInfo* currentFrameInfo,
-                     bool* requireSwap) override;
-    DeferredLayerUpdater* createTextureLayer() override;
-    [[nodiscard]] android::base::unique_fd flush() override;
-
-    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
-    void onStop() override;
-    bool isSurfaceReady() override;
-    bool isContextReady() override;
-    void setTargetSdrHdrRatio(float ratio) override;
-    const SkM44& getPixelSnapMatrix() const override;
-
-    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
-    static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
-                                                SkBitmap& skBitmap);
-
-protected:
-    void onContextDestroyed() override;
-
-private:
-    renderthread::VulkanManager& vulkanManager();
-    renderthread::VulkanSurface* mVkSurface = nullptr;
-    sp<ANativeWindow> mNativeWindow;
-};
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index b62711f..21fe6ff 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -16,10 +16,10 @@
 
 #include "VkFunctorDrawable.h"
 
-#include <GrBackendDrawableInfo.h>
 #include <SkAndroidFrameworkUtils.h>
 #include <SkImage.h>
 #include <SkM44.h>
+#include <include/gpu/ganesh/vk/GrBackendDrawableInfo.h>
 #include <gui/TraceUtils.h>
 #include <private/hwui/DrawVkInfo.h>
 #include <utils/Color.h>
diff --git a/libs/hwui/platform/android/pipeline/skia/SkiaGpuPipeline.h b/libs/hwui/platform/android/pipeline/skia/SkiaGpuPipeline.h
new file mode 100644
index 0000000..9159eae
--- /dev/null
+++ b/libs/hwui/platform/android/pipeline/skia/SkiaGpuPipeline.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "pipeline/skia/SkiaPipeline.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaGpuPipeline : public SkiaPipeline {
+public:
+    SkiaGpuPipeline(renderthread::RenderThread& thread);
+    virtual ~SkiaGpuPipeline();
+
+    virtual GrSurfaceOrigin getSurfaceOrigin() = 0;
+
+    // If the given node didn't have a layer surface, or had one of the wrong size, this method
+    // creates a new one and returns true. Otherwise does nothing and returns false.
+    bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+                             ErrorHandler* errorHandler) override;
+
+    bool pinImages(std::vector<SkImage*>& mutableImages) override;
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
+    void unpinImages() override;
+    void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) override;
+    void setHardwareBuffer(AHardwareBuffer* hardwareBuffer) override;
+    bool hasHardwareBuffer() override { return mHardwareBuffer != nullptr; }
+
+    static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
+
+protected:
+    sk_sp<SkSurface> getBufferSkSurface(
+            const renderthread::HardwareBufferRenderParams& bufferParams);
+    void dumpResourceCacheUsage() const;
+
+    AHardwareBuffer* mHardwareBuffer = nullptr;
+
+private:
+    std::vector<sk_sp<SkImage>> mPinnedImages;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/android/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/platform/android/pipeline/skia/SkiaOpenGLPipeline.h
new file mode 100644
index 0000000..6e74782
--- /dev/null
+++ b/libs/hwui/platform/android/pipeline/skia/SkiaOpenGLPipeline.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <EGL/egl.h>
+#include <system/window.h>
+
+#include "pipeline/skia/SkiaGpuPipeline.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/HardwareBufferRenderParams.h"
+
+namespace android {
+
+class Bitmap;
+
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaOpenGLPipeline : public SkiaGpuPipeline, public IGpuContextCallback {
+public:
+    SkiaOpenGLPipeline(renderthread::RenderThread& thread);
+    virtual ~SkiaOpenGLPipeline();
+
+    renderthread::MakeCurrentResult makeCurrent() override;
+    renderthread::Frame getFrame() override;
+    renderthread::IRenderPipeline::DrawResult draw(
+            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+            const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
+            const renderthread::HardwareBufferRenderParams& bufferParams,
+            std::mutex& profilerLock) override;
+    GrSurfaceOrigin getSurfaceOrigin() override { return kBottomLeft_GrSurfaceOrigin; }
+    bool swapBuffers(const renderthread::Frame& frame, IRenderPipeline::DrawResult& drawResult,
+                     const SkRect& screenDirty, FrameInfo* currentFrameInfo,
+                     bool* requireSwap) override;
+    DeferredLayerUpdater* createTextureLayer() override;
+    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
+    [[nodiscard]] android::base::unique_fd flush() override;
+    void onStop() override;
+    bool isSurfaceReady() override;
+    bool isContextReady() override;
+
+    const SkM44& getPixelSnapMatrix() const override {
+        // Small (~1/16th) nudge to ensure that pixel-aligned non-AA'd draws fill the
+        // desired fragment
+        static const SkScalar kOffset = 0.063f;
+        static const SkM44 sSnapMatrix = SkM44::Translate(kOffset, kOffset);
+        return sSnapMatrix;
+    }
+
+    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+
+protected:
+    void onContextDestroyed() override;
+
+private:
+    renderthread::EglManager& mEglManager;
+    EGLSurface mEglSurface = EGL_NO_SURFACE;
+    sp<ANativeWindow> mNativeWindow;
+    renderthread::SwapBehavior mSwapBehavior = renderthread::SwapBehavior::kSwap_discardBuffer;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/android/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/platform/android/pipeline/skia/SkiaVulkanPipeline.h
new file mode 100644
index 0000000..0d30df4
--- /dev/null
+++ b/libs/hwui/platform/android/pipeline/skia/SkiaVulkanPipeline.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "SkRefCnt.h"
+#include "pipeline/skia/SkiaGpuPipeline.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/HardwareBufferRenderParams.h"
+#include "renderthread/VulkanManager.h"
+#include "renderthread/VulkanSurface.h"
+
+class SkBitmap;
+struct SkRect;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaVulkanPipeline : public SkiaGpuPipeline, public IGpuContextCallback {
+public:
+    explicit SkiaVulkanPipeline(renderthread::RenderThread& thread);
+    virtual ~SkiaVulkanPipeline();
+
+    renderthread::MakeCurrentResult makeCurrent() override;
+    renderthread::Frame getFrame() override;
+    renderthread::IRenderPipeline::DrawResult draw(
+            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+            const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
+            const renderthread::HardwareBufferRenderParams& bufferParams,
+            std::mutex& profilerLock) override;
+    GrSurfaceOrigin getSurfaceOrigin() override { return kTopLeft_GrSurfaceOrigin; }
+    bool swapBuffers(const renderthread::Frame& frame, IRenderPipeline::DrawResult& drawResult,
+                     const SkRect& screenDirty, FrameInfo* currentFrameInfo,
+                     bool* requireSwap) override;
+    DeferredLayerUpdater* createTextureLayer() override;
+    [[nodiscard]] android::base::unique_fd flush() override;
+
+    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
+    void onStop() override;
+    bool isSurfaceReady() override;
+    bool isContextReady() override;
+    void setTargetSdrHdrRatio(float ratio) override;
+    const SkM44& getPixelSnapMatrix() const override;
+
+    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+    static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
+                                                SkBitmap& skBitmap);
+
+protected:
+    void onContextDestroyed() override;
+
+private:
+    renderthread::VulkanManager& vulkanManager();
+    renderthread::VulkanSurface* mVkSurface = nullptr;
+    sp<ANativeWindow> mNativeWindow;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/darwin/utils/SharedLib.cpp b/libs/hwui/platform/darwin/utils/SharedLib.cpp
new file mode 100644
index 0000000..6e9f0b4
--- /dev/null
+++ b/libs/hwui/platform/darwin/utils/SharedLib.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/SharedLib.h"
+
+#include <dlfcn.h>
+
+namespace android {
+namespace uirenderer {
+
+void* SharedLib::openSharedLib(std::string filename) {
+    return dlopen((filename + ".dylib").c_str(), RTLD_NOW | RTLD_NODELETE);
+}
+
+void* SharedLib::getSymbol(void* library, const char* symbol) {
+    return dlsym(library, symbol);
+}
+
+}  // namespace uirenderer
+}  // namespace android
diff --git a/libs/hwui/platform/host/WebViewFunctorManager.cpp b/libs/hwui/platform/host/WebViewFunctorManager.cpp
index 1d16655..4ba206b 100644
--- a/libs/hwui/platform/host/WebViewFunctorManager.cpp
+++ b/libs/hwui/platform/host/WebViewFunctorManager.cpp
@@ -50,6 +50,8 @@
 
 void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) {}
 
+void WebViewFunctor::reportRenderingThreads(const pid_t* thread_ids, size_t size) {}
+
 void WebViewFunctor::reparentSurfaceControl(ASurfaceControl* parent) {}
 
 WebViewFunctorManager& WebViewFunctorManager::instance() {
@@ -68,6 +70,13 @@
 
 void WebViewFunctorManager::destroyFunctor(int functor) {}
 
+void WebViewFunctorManager::reportRenderingThreads(int functor, const pid_t* thread_ids,
+                                                   size_t size) {}
+
+std::vector<pid_t> WebViewFunctorManager::getRenderingThreadsForActiveFunctors() {
+    return {};
+}
+
 sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) {
     return nullptr;
 }
diff --git a/libs/hwui/platform/host/android/api-level.h b/libs/hwui/platform/host/android/api-level.h
new file mode 120000
index 0000000..4fb4784
--- /dev/null
+++ b/libs/hwui/platform/host/android/api-level.h
@@ -0,0 +1 @@
+../../../../../../../bionic/libc/include/android/api-level.h
\ No newline at end of file
diff --git a/libs/hwui/platform/host/pipeline/skia/SkiaGpuPipeline.h b/libs/hwui/platform/host/pipeline/skia/SkiaGpuPipeline.h
new file mode 100644
index 0000000..a717265
--- /dev/null
+++ b/libs/hwui/platform/host/pipeline/skia/SkiaGpuPipeline.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "pipeline/skia/SkiaPipeline.h"
+#include "renderthread/Frame.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaGpuPipeline : public SkiaPipeline {
+public:
+    SkiaGpuPipeline(renderthread::RenderThread& thread) : SkiaPipeline(thread) {}
+    ~SkiaGpuPipeline() {}
+
+    bool pinImages(std::vector<SkImage*>& mutableImages) override { return false; }
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
+    void unpinImages() override {}
+
+    // If the given node didn't have a layer surface, or had one of the wrong size, this method
+    // creates a new one and returns true. Otherwise does nothing and returns false.
+    bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
+                             ErrorHandler* errorHandler) override {
+        return false;
+    }
+    void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) override {}
+    void setHardwareBuffer(AHardwareBuffer* hardwareBuffer) override {}
+    bool hasHardwareBuffer() override { return false; }
+
+    renderthread::MakeCurrentResult makeCurrent() override {
+        return renderthread::MakeCurrentResult::Failed;
+    }
+    renderthread::Frame getFrame() override { return renderthread::Frame(0, 0, 0); }
+    renderthread::IRenderPipeline::DrawResult draw(
+            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+            const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
+            const renderthread::HardwareBufferRenderParams& bufferParams,
+            std::mutex& profilerLock) override {
+        return {false, IRenderPipeline::DrawResult::kUnknownTime, android::base::unique_fd(-1)};
+    }
+    bool swapBuffers(const renderthread::Frame& frame, IRenderPipeline::DrawResult& drawResult,
+                     const SkRect& screenDirty, FrameInfo* currentFrameInfo,
+                     bool* requireSwap) override {
+        return false;
+    }
+    DeferredLayerUpdater* createTextureLayer() override { return nullptr; }
+    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override {
+        return false;
+    }
+    [[nodiscard]] android::base::unique_fd flush() override {
+        return android::base::unique_fd(-1);
+    };
+    void onStop() override {}
+    bool isSurfaceReady() override { return false; }
+    bool isContextReady() override { return false; }
+
+    const SkM44& getPixelSnapMatrix() const override {
+        static const SkM44 sSnapMatrix = SkM44();
+        return sSnapMatrix;
+    }
+    static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap) {}
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/host/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/platform/host/pipeline/skia/SkiaOpenGLPipeline.h
new file mode 100644
index 0000000..4fafbcc
--- /dev/null
+++ b/libs/hwui/platform/host/pipeline/skia/SkiaOpenGLPipeline.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "pipeline/skia/SkiaGpuPipeline.h"
+
+namespace android {
+
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaOpenGLPipeline : public SkiaGpuPipeline {
+public:
+    SkiaOpenGLPipeline(renderthread::RenderThread& thread) : SkiaGpuPipeline(thread) {}
+
+    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor) {}
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/host/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/platform/host/pipeline/skia/SkiaVulkanPipeline.h
new file mode 100644
index 0000000..d54caef
--- /dev/null
+++ b/libs/hwui/platform/host/pipeline/skia/SkiaVulkanPipeline.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "pipeline/skia/SkiaGpuPipeline.h"
+
+namespace android {
+
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaVulkanPipeline : public SkiaGpuPipeline {
+public:
+    SkiaVulkanPipeline(renderthread::RenderThread& thread) : SkiaGpuPipeline(thread) {}
+
+    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor) {}
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/host/renderthread/HintSessionWrapper.cpp b/libs/hwui/platform/host/renderthread/HintSessionWrapper.cpp
new file mode 100644
index 0000000..b1b1d58
--- /dev/null
+++ b/libs/hwui/platform/host/renderthread/HintSessionWrapper.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "renderthread/HintSessionWrapper.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+void HintSessionWrapper::HintSessionBinding::init() {}
+
+HintSessionWrapper::HintSessionWrapper(pid_t uiThreadId, pid_t renderThreadId)
+        : mUiThreadId(uiThreadId)
+        , mRenderThreadId(renderThreadId)
+        , mBinding(std::make_shared<HintSessionBinding>()) {}
+
+HintSessionWrapper::~HintSessionWrapper() {}
+
+void HintSessionWrapper::destroy() {}
+
+bool HintSessionWrapper::init() {
+    return false;
+}
+
+void HintSessionWrapper::updateTargetWorkDuration(long targetWorkDurationNanos) {}
+
+void HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {}
+
+void HintSessionWrapper::sendLoadResetHint() {}
+
+void HintSessionWrapper::sendLoadIncreaseHint() {}
+
+bool HintSessionWrapper::alive() {
+    return false;
+}
+
+nsecs_t HintSessionWrapper::getLastUpdate() {
+    return -1;
+}
+
+void HintSessionWrapper::delayedDestroy(RenderThread& rt, nsecs_t delay,
+                                        std::shared_ptr<HintSessionWrapper> wrapperPtr) {}
+
+void HintSessionWrapper::setActiveFunctorThreads(std::vector<pid_t> threadIds) {}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/platform/host/renderthread/ReliableSurface.cpp b/libs/hwui/platform/host/renderthread/ReliableSurface.cpp
new file mode 100644
index 0000000..2deaaf3
--- /dev/null
+++ b/libs/hwui/platform/host/renderthread/ReliableSurface.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "renderthread/ReliableSurface.h"
+
+#include <log/log_main.h>
+#include <system/window.h>
+
+namespace android::uirenderer::renderthread {
+
+ReliableSurface::ReliableSurface(ANativeWindow* window) : mWindow(window) {
+    LOG_ALWAYS_FATAL_IF(!mWindow, "Error, unable to wrap a nullptr");
+    ANativeWindow_acquire(mWindow);
+}
+
+ReliableSurface::~ReliableSurface() {
+    ANativeWindow_release(mWindow);
+}
+
+void ReliableSurface::init() {}
+
+int ReliableSurface::reserveNext() {
+    return OK;
+}
+
+};  // namespace android::uirenderer::renderthread
diff --git a/libs/hwui/platform/host/renderthread/RenderThread.cpp b/libs/hwui/platform/host/renderthread/RenderThread.cpp
index 6f08b59..f9d0f47 100644
--- a/libs/hwui/platform/host/renderthread/RenderThread.cpp
+++ b/libs/hwui/platform/host/renderthread/RenderThread.cpp
@@ -17,6 +17,7 @@
 #include "renderthread/RenderThread.h"
 
 #include "Readback.h"
+#include "renderstate/RenderState.h"
 #include "renderthread/VulkanManager.h"
 
 namespace android {
@@ -66,6 +67,7 @@
 RenderThread::~RenderThread() {}
 
 void RenderThread::initThreadLocals() {
+    mRenderState = new RenderState(*this);
     mCacheManager = new CacheManager(*this);
 }
 
diff --git a/libs/hwui/platform/host/utils/MessageHandler.h b/libs/hwui/platform/host/utils/MessageHandler.h
new file mode 100644
index 0000000..51ee48e
--- /dev/null
+++ b/libs/hwui/platform/host/utils/MessageHandler.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/RefBase.h>
+
+struct Message {
+    Message(int w) {}
+};
+
+class MessageHandler : public virtual android::RefBase {
+protected:
+    virtual ~MessageHandler() override {}
+
+public:
+    /**
+     * Handles a message.
+     */
+    virtual void handleMessage(const Message& message) = 0;
+};
diff --git a/libs/hwui/platform/linux/utils/SharedLib.cpp b/libs/hwui/platform/linux/utils/SharedLib.cpp
new file mode 100644
index 0000000..a9acf37
--- /dev/null
+++ b/libs/hwui/platform/linux/utils/SharedLib.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/SharedLib.h"
+
+#include <dlfcn.h>
+
+namespace android {
+namespace uirenderer {
+
+void* SharedLib::openSharedLib(std::string filename) {
+    return dlopen((filename + ".so").c_str(), RTLD_NOW | RTLD_NODELETE);
+}
+
+void* SharedLib::getSymbol(void* library, const char* symbol) {
+    return dlsym(library, symbol);
+}
+
+}  // namespace uirenderer
+}  // namespace android
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index e08d32a..60657cf 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -16,11 +16,13 @@
 #ifndef RENDERSTATE_H
 #define RENDERSTATE_H
 
-#include "utils/Macros.h"
-
+#include <pthread.h>
 #include <utils/RefBase.h>
+
 #include <set>
 
+#include "utils/Macros.h"
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1fbd580..8bb11ba 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -35,8 +35,9 @@
 #include "Properties.h"
 #include "RenderThread.h"
 #include "hwui/Canvas.h"
+#include "pipeline/skia/SkiaCpuPipeline.h"
+#include "pipeline/skia/SkiaGpuPipeline.h"
 #include "pipeline/skia/SkiaOpenGLPipeline.h"
-#include "pipeline/skia/SkiaPipeline.h"
 #include "pipeline/skia/SkiaVulkanPipeline.h"
 #include "thread/CommonPool.h"
 #include "utils/GLUtils.h"
@@ -72,7 +73,7 @@
 
 CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
                                      RenderNode* rootRenderNode, IContextFactory* contextFactory,
-                                     int32_t uiThreadId, int32_t renderThreadId) {
+                                     pid_t uiThreadId, pid_t renderThreadId) {
     auto renderType = Properties::getRenderPipelineType();
 
     switch (renderType) {
@@ -84,6 +85,12 @@
             return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                      std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread),
                                      uiThreadId, renderThreadId);
+#ifndef __ANDROID__
+        case RenderPipelineType::SkiaCpu:
+            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
+                                     std::make_unique<skiapipeline::SkiaCpuPipeline>(thread),
+                                     uiThreadId, renderThreadId);
+#endif
         default:
             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
             break;
@@ -108,7 +115,7 @@
 }
 
 void CanvasContext::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
-    skiapipeline::SkiaPipeline::prepareToDraw(thread, bitmap);
+    skiapipeline::SkiaGpuPipeline::prepareToDraw(thread, bitmap);
 }
 
 CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
@@ -182,6 +189,7 @@
 }
 
 void CanvasContext::setHardwareBuffer(AHardwareBuffer* buffer) {
+#ifdef __ANDROID__
     if (mHardwareBuffer) {
         AHardwareBuffer_release(mHardwareBuffer);
         mHardwareBuffer = nullptr;
@@ -192,6 +200,7 @@
         mHardwareBuffer = buffer;
     }
     mRenderPipeline->setHardwareBuffer(mHardwareBuffer);
+#endif
 }
 
 void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
@@ -561,6 +570,7 @@
 }
 
 void CanvasContext::draw(bool solelyTextureViewUpdates) {
+#ifdef __ANDROID__
     if (auto grContext = getGrContext()) {
         if (grContext->abandoned()) {
             if (grContext->isDeviceLost()) {
@@ -571,6 +581,7 @@
             return;
         }
     }
+#endif
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
 
@@ -594,11 +605,13 @@
     if (skippedFrameReason) {
         mCurrentFrameInfo->setSkippedFrameReason(*skippedFrameReason);
 
+#ifdef __ANDROID__
         if (auto grContext = getGrContext()) {
             // Submit to ensure that any texture uploads complete and Skia can
             // free its staging buffers.
             grContext->flushAndSubmit();
         }
+#endif
 
         // Notify the callbacks, even if there's nothing to draw so they aren't waiting
         // indefinitely
@@ -997,7 +1010,15 @@
 }
 
 void CanvasContext::onContextDestroyed() {
-    destroyHardwareResources();
+    // We don't want to destroyHardwareResources as that will invalidate display lists which
+    // the client may not be expecting. Instead just purge all scratch resources
+    if (mRenderPipeline->isContextReady()) {
+        freePrefetchedLayers();
+        for (const sp<RenderNode>& node : mRenderNodes) {
+            node->destroyLayers();
+        }
+        mRenderPipeline->onDestroyHardwareResources();
+    }
 }
 
 DeferredLayerUpdater* CanvasContext::createTextureLayer() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1b333bf..826d00e 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -140,12 +140,14 @@
     if (CC_LIKELY(canDrawThisFrame)) {
         context->draw(solelyTextureViewUpdates);
     } else {
+#ifdef __ANDROID__
         // Do a flush in case syncFrameState performed any texture uploads. Since we skipped
         // the draw() call, those uploads (or deletes) will end up sitting in the queue.
         // Do them now
         if (GrDirectContext* grContext = mRenderThread->getGrContext()) {
             grContext->flushAndSubmit();
         }
+#endif
         // wait on fences so tasks don't overlap next frame
         context->waitOnFences();
     }
@@ -176,11 +178,13 @@
     bool canDraw = mContext->makeCurrent();
     mContext->unpinImages();
 
+#ifdef __ANDROID__
     for (size_t i = 0; i < mLayers.size(); i++) {
         if (mLayers[i]) {
             mLayers[i]->apply();
         }
     }
+#endif
 
     mLayers.clear();
     mContext->setContentDrawBounds(mContentDrawBounds);
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 2904dfe..708b011 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -442,14 +442,17 @@
         }
 
         // TODO: maybe we want to get rid of the WCG check if overlay properties just works?
-        const bool canUseFp16 = DeviceInfo::get()->isSupportFp16ForHdr() ||
-                                DeviceInfo::get()->getWideColorType() == kRGBA_F16_SkColorType;
+        bool canUseFp16 = DeviceInfo::get()->isSupportFp16ForHdr() ||
+                DeviceInfo::get()->getWideColorType() == kRGBA_F16_SkColorType;
 
-        if (canUseFp16) {
-            if (mEglConfigF16 == EGL_NO_CONFIG_KHR) {
-                colorMode = ColorMode::Default;
-            } else {
-                config = mEglConfigF16;
+        if (colorMode == ColorMode::Hdr) {
+            if (canUseFp16 && !DeviceInfo::get()->isSupportRgba10101010ForHdr()) {
+                if (mEglConfigF16 == EGL_NO_CONFIG_KHR) {
+                    // If the driver doesn't support fp16 then fallback to 8-bit
+                    canUseFp16 = false;
+                } else {
+                    config = mEglConfigF16;
+                }
             }
         }
 
diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp
index 6993d52..7a155c5 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.cpp
+++ b/libs/hwui/renderthread/HintSessionWrapper.cpp
@@ -45,7 +45,7 @@
     LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
 
     BIND_APH_METHOD(getManager);
-    BIND_APH_METHOD(createSession);
+    BIND_APH_METHOD(createSessionInternal);
     BIND_APH_METHOD(closeSession);
     BIND_APH_METHOD(updateTargetWorkDuration);
     BIND_APH_METHOD(reportActualWorkDuration);
@@ -122,7 +122,8 @@
     int64_t targetDurationNanos =
             mLastTargetWorkDuration == 0 ? kDefaultTargetDuration : mLastTargetWorkDuration;
     mHintSessionFuture = CommonPool::async([=, this, tids = mPermanentSessionTids] {
-        return mBinding->createSession(manager, tids.data(), tids.size(), targetDurationNanos);
+        return mBinding->createSessionInternal(manager, tids.data(), tids.size(),
+                                               targetDurationNanos, SessionTag::HWUI);
     });
     return false;
 }
diff --git a/libs/hwui/renderthread/HintSessionWrapper.h b/libs/hwui/renderthread/HintSessionWrapper.h
index 14e7a53..859cc57 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.h
+++ b/libs/hwui/renderthread/HintSessionWrapper.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <android/performance_hint.h>
+#include <private/performance_hint_private.h>
 
 #include <future>
 #include <optional>
@@ -80,9 +81,10 @@
         virtual ~HintSessionBinding() = default;
         virtual void init();
         APerformanceHintManager* (*getManager)();
-        APerformanceHintSession* (*createSession)(APerformanceHintManager* manager,
-                                                  const int32_t* tids, size_t tidCount,
-                                                  int64_t defaultTarget) = nullptr;
+        APerformanceHintSession* (*createSessionInternal)(APerformanceHintManager* manager,
+                                                          const int32_t* tids, size_t tidCount,
+                                                          int64_t defaultTarget,
+                                                          SessionTag tag) = nullptr;
         void (*closeSession)(APerformanceHintSession* session) = nullptr;
         void (*updateTargetWorkDuration)(APerformanceHintSession* session,
                                          int64_t targetDuration) = nullptr;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index b8c3a4d..ee1d1f8 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -30,8 +30,6 @@
 #include "SwapBehavior.h"
 #include "hwui/Bitmap.h"
 
-class GrDirectContext;
-
 struct ANativeWindow;
 
 namespace android {
@@ -94,7 +92,6 @@
     virtual void setSurfaceColorProperties(ColorMode colorMode) = 0;
     virtual SkColorType getSurfaceColorType() const = 0;
     virtual sk_sp<SkColorSpace> getSurfaceColorSpace() = 0;
-    virtual GrSurfaceOrigin getSurfaceOrigin() = 0;
     virtual void setPictureCapturedCallback(
             const std::function<void(sk_sp<SkPicture>&&)>& callback) = 0;
 
diff --git a/libs/hwui/renderthread/ReliableSurface.h b/libs/hwui/renderthread/ReliableSurface.h
index 5959647..d6a4d50 100644
--- a/libs/hwui/renderthread/ReliableSurface.h
+++ b/libs/hwui/renderthread/ReliableSurface.h
@@ -21,7 +21,9 @@
 #include <apex/window.h>
 #include <utils/Errors.h>
 #include <utils/Macros.h>
+#ifdef __ANDROID__
 #include <utils/NdkUtils.h>
+#endif
 #include <utils/StrongPointer.h>
 
 #include <memory>
@@ -62,9 +64,11 @@
     mutable std::mutex mMutex;
 
     uint64_t mUsage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
+#ifdef __ANDROID__
     AHardwareBuffer_Format mFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
     UniqueAHardwareBuffer mScratchBuffer;
     ANativeWindowBuffer* mReservedBuffer = nullptr;
+#endif
     base::unique_fd mReservedFenceFd;
     bool mHasDequeuedBuffer = false;
     int mBufferQueueState = OK;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index eab3605..715153b 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -42,7 +42,11 @@
 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
                          IContextFactory* contextFactory)
         : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
+#ifdef __ANDROID__
     pid_t uiThreadId = pthread_gettid_np(pthread_self());
+#else
+    pid_t uiThreadId = 0;
+#endif
     pid_t renderThreadId = getRenderThreadTid();
     mContext = mRenderThread.queue().runSync([=, this]() -> CanvasContext* {
         CanvasContext* context = CanvasContext::create(mRenderThread, translucent, rootRenderNode,
@@ -90,6 +94,7 @@
 }
 
 void RenderProxy::setHardwareBuffer(AHardwareBuffer* buffer) {
+#ifdef __ANDROID__
     if (buffer) {
         AHardwareBuffer_acquire(buffer);
     }
@@ -99,6 +104,7 @@
             AHardwareBuffer_release(hardwareBuffer);
         }
     });
+#endif
 }
 
 void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
@@ -216,7 +222,9 @@
 }
 
 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
+#ifdef __ANDROID__
     return mRenderThread.queue().runSync([&]() { layer->detachSurfaceTexture(); });
+#endif
 }
 
 void RenderProxy::destroyHardwareResources() {
@@ -324,11 +332,13 @@
             }
         });
     }
+#ifdef __ANDROID__
     if (!Properties::isolatedProcess) {
         std::string grallocInfo;
         GraphicBufferAllocator::getInstance().dump(grallocInfo);
         dprintf(fd, "%s\n", grallocInfo.c_str());
     }
+#endif
 }
 
 void RenderProxy::getMemoryUsage(size_t* cpuUsage, size_t* gpuUsage) {
@@ -352,7 +362,11 @@
 }
 
 int RenderProxy::getRenderThreadTid() {
+#ifdef __ANDROID__
     return mRenderThread.getTid();
+#else
+    return 0;
+#endif
 }
 
 void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
@@ -461,7 +475,7 @@
 int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
     ATRACE_NAME("HardwareBitmap readback");
     RenderThread& thread = RenderThread::getInstance();
-    if (gettid() == thread.getTid()) {
+    if (RenderThread::isCurrent()) {
         // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
         return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap);
     } else {
@@ -472,7 +486,7 @@
 
 int RenderProxy::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) {
     RenderThread& thread = RenderThread::getInstance();
-    if (gettid() == thread.getTid()) {
+    if (RenderThread::isCurrent()) {
         // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
         return (int)thread.readback().copyImageInto(image, bitmap);
     } else {
diff --git a/libs/hwui/tests/unit/HintSessionWrapperTests.cpp b/libs/hwui/tests/unit/HintSessionWrapperTests.cpp
index c16602c..a8db0f4a 100644
--- a/libs/hwui/tests/unit/HintSessionWrapperTests.cpp
+++ b/libs/hwui/tests/unit/HintSessionWrapperTests.cpp
@@ -52,8 +52,8 @@
         void init() override;
 
         MOCK_METHOD(APerformanceHintManager*, fakeGetManager, ());
-        MOCK_METHOD(APerformanceHintSession*, fakeCreateSession,
-                    (APerformanceHintManager*, const int32_t*, size_t, int64_t));
+        MOCK_METHOD(APerformanceHintSession*, fakeCreateSessionInternal,
+                    (APerformanceHintManager*, const int32_t*, size_t, int64_t, SessionTag));
         MOCK_METHOD(void, fakeCloseSession, (APerformanceHintSession*));
         MOCK_METHOD(void, fakeUpdateTargetWorkDuration, (APerformanceHintSession*, int64_t));
         MOCK_METHOD(void, fakeReportActualWorkDuration, (APerformanceHintSession*, int64_t));
@@ -72,22 +72,28 @@
 
     // Must be static so we can point to them as normal fn pointers with HintSessionBinding
     static APerformanceHintManager* stubGetManager() { return sMockBinding->fakeGetManager(); };
-    static APerformanceHintSession* stubCreateSession(APerformanceHintManager* manager,
-                                                      const int32_t* ids, size_t idsSize,
-                                                      int64_t initialTarget) {
-        return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
+    static APerformanceHintSession* stubCreateSessionInternal(APerformanceHintManager* manager,
+                                                              const int32_t* ids, size_t idsSize,
+                                                              int64_t initialTarget,
+                                                              SessionTag tag) {
+        return sMockBinding->fakeCreateSessionInternal(manager, ids, idsSize, initialTarget,
+                                                       SessionTag::HWUI);
     }
-    static APerformanceHintSession* stubManagedCreateSession(APerformanceHintManager* manager,
-                                                             const int32_t* ids, size_t idsSize,
-                                                             int64_t initialTarget) {
+    static APerformanceHintSession* stubManagedCreateSessionInternal(
+            APerformanceHintManager* manager, const int32_t* ids, size_t idsSize,
+            int64_t initialTarget, SessionTag tag) {
         sMockBinding->allowCreationToFinish.get_future().wait();
-        return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
+        return sMockBinding->fakeCreateSessionInternal(manager, ids, idsSize, initialTarget,
+                                                       SessionTag::HWUI);
     }
-    static APerformanceHintSession* stubSlowCreateSession(APerformanceHintManager* manager,
-                                                          const int32_t* ids, size_t idsSize,
-                                                          int64_t initialTarget) {
+    static APerformanceHintSession* stubSlowCreateSessionInternal(APerformanceHintManager* manager,
+                                                                  const int32_t* ids,
+                                                                  size_t idsSize,
+                                                                  int64_t initialTarget,
+                                                                  SessionTag tag) {
         std::this_thread::sleep_for(50ms);
-        return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
+        return sMockBinding->fakeCreateSessionInternal(manager, ids, idsSize, initialTarget,
+                                                       SessionTag::HWUI);
     }
     static void stubCloseSession(APerformanceHintSession* session) {
         sMockBinding->fakeCloseSession(session);
@@ -139,14 +145,14 @@
     mWrapper = std::make_shared<HintSessionWrapper>(uiThreadId, renderThreadId);
     mWrapper->mBinding = sMockBinding;
     EXPECT_CALL(*sMockBinding, fakeGetManager).WillOnce(Return(managerPtr));
-    ON_CALL(*sMockBinding, fakeCreateSession).WillByDefault(Return(sessionPtr));
+    ON_CALL(*sMockBinding, fakeCreateSessionInternal).WillByDefault(Return(sessionPtr));
     ON_CALL(*sMockBinding, fakeSetThreads).WillByDefault(Return(0));
 }
 
 void HintSessionWrapperTests::MockHintSessionBinding::init() {
     sMockBinding->getManager = &stubGetManager;
-    if (sMockBinding->createSession == nullptr) {
-        sMockBinding->createSession = &stubCreateSession;
+    if (sMockBinding->createSessionInternal == nullptr) {
+        sMockBinding->createSessionInternal = &stubCreateSessionInternal;
     }
     sMockBinding->closeSession = &stubCloseSession;
     sMockBinding->updateTargetWorkDuration = &stubUpdateTargetWorkDuration;
@@ -163,14 +169,14 @@
 
 TEST_F(HintSessionWrapperTests, destructorClosesBackgroundSession) {
     EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
-    sMockBinding->createSession = stubSlowCreateSession;
+    sMockBinding->createSessionInternal = stubSlowCreateSessionInternal;
     mWrapper->init();
     mWrapper = nullptr;
     Mock::VerifyAndClearExpectations(sMockBinding.get());
 }
 
 TEST_F(HintSessionWrapperTests, sessionInitializesCorrectly) {
-    EXPECT_CALL(*sMockBinding, fakeCreateSession(managerPtr, _, Gt(1), _)).Times(1);
+    EXPECT_CALL(*sMockBinding, fakeCreateSessionInternal(managerPtr, _, Gt(1), _, _)).Times(1);
     mWrapper->init();
     waitForWrapperReady();
 }
@@ -219,7 +225,7 @@
     // Here we test whether queueing delayedDestroy works while creation is still happening, if
     // creation happens after
     EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
-    sMockBinding->createSession = &stubManagedCreateSession;
+    sMockBinding->createSessionInternal = &stubManagedCreateSessionInternal;
 
     // Start creating the session and destroying it at the same time
     mWrapper->init();
@@ -246,7 +252,7 @@
     // Here we test whether queueing delayedDestroy works while creation is still happening, if
     // creation happens before
     EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
-    sMockBinding->createSession = &stubManagedCreateSession;
+    sMockBinding->createSessionInternal = &stubManagedCreateSessionInternal;
 
     // Start creating the session and destroying it at the same time
     mWrapper->init();
@@ -352,7 +358,7 @@
 }
 
 TEST_F(HintSessionWrapperTests, setThreadsUpdatesSessionThreads) {
-    EXPECT_CALL(*sMockBinding, fakeCreateSession(managerPtr, _, Gt(1), _)).Times(1);
+    EXPECT_CALL(*sMockBinding, fakeCreateSessionInternal(managerPtr, _, Gt(1), _, _)).Times(1);
     EXPECT_CALL(*sMockBinding, fakeSetThreads(sessionPtr, testing::IsSupersetOf({11, 22})))
             .Times(1);
     mWrapper->init();
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index f6c5792..6a560b3 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -403,7 +403,7 @@
 }
 
 static skcms_TransferFunction trfn_apply_gain(const skcms_TransferFunction trfn, float gain) {
-    float pow_gain_ginv = sk_float_pow(gain, 1 / trfn.g);
+    float pow_gain_ginv = std::pow(gain, 1 / trfn.g);
     skcms_TransferFunction result;
     result.g = trfn.g;
     result.a = trfn.a * pow_gain_ginv;
diff --git a/libs/hwui/utils/SharedLib.h b/libs/hwui/utils/SharedLib.h
new file mode 100644
index 0000000..f4dcf0f
--- /dev/null
+++ b/libs/hwui/utils/SharedLib.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SHAREDLIB_H
+#define SHAREDLIB_H
+
+#include <string>
+
+namespace android {
+namespace uirenderer {
+
+class SharedLib {
+public:
+    static void* openSharedLib(std::string filename);
+    static void* getSymbol(void* library, const char* symbol);
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif  // SHAREDLIB_H
diff --git a/location/Android.bp b/location/Android.bp
index eb7cd01..5ba35ac 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -26,6 +26,7 @@
         "com.android.internal.location",
     ],
     libs: [
+        "android.location.flags-aconfig-java",
         "app-compat-annotations",
         "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
     ],
diff --git a/location/TEST_MAPPING b/location/TEST_MAPPING
index f5deb2b..10da632 100644
--- a/location/TEST_MAPPING
+++ b/location/TEST_MAPPING
@@ -2,12 +2,7 @@
   "presubmit": [
     {
       "name": "CtsLocationFineTestCases",
-      "options": [
-          {
-             // TODO: Wait for test to deflake - b/293934372
-             "exclude-filter":"android.location.cts.fine.ScanningSettingsTest"
-          }
-      ]
+      "options": []
     },
     {
       "name": "CtsLocationCoarseTestCases"
diff --git a/location/api/current.txt b/location/api/current.txt
index 85e9f65..61afd26 100644
--- a/location/api/current.txt
+++ b/location/api/current.txt
@@ -412,8 +412,8 @@
     field public static final int TYPE_GPS_L1CA = 257; // 0x101
     field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
     field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
-    field @FlaggedApi(Flags.FLAG_GNSS_API_NAVIC_L1) public static final int TYPE_IRN_L1 = 1795; // 0x703
-    field @FlaggedApi(Flags.FLAG_GNSS_API_NAVIC_L1) public static final int TYPE_IRN_L5 = 1794; // 0x702
+    field @FlaggedApi("android.location.flags.gnss_api_navic_l1") public static final int TYPE_IRN_L1 = 1795; // 0x703
+    field @FlaggedApi("android.location.flags.gnss_api_navic_l1") public static final int TYPE_IRN_L5 = 1794; // 0x702
     field public static final int TYPE_IRN_L5CA = 1793; // 0x701
     field public static final int TYPE_QZS_L1CA = 1025; // 0x401
     field public static final int TYPE_SBS = 513; // 0x201
@@ -682,7 +682,7 @@
   public final class AltitudeConverter {
     ctor public AltitudeConverter();
     method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
-    method @FlaggedApi(Flags.FLAG_GEOID_HEIGHTS_VIA_ALTITUDE_HAL) public boolean tryAddMslAltitudeToLocation(@NonNull android.location.Location);
+    method @FlaggedApi("android.location.flags.geoid_heights_via_altitude_hal") public boolean tryAddMslAltitudeToLocation(@NonNull android.location.Location);
   }
 
 }
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index 254d74aa..f6e76a2 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -113,13 +113,13 @@
   }
 
   public final class GnssMeasurementRequest implements android.os.Parcelable {
-    method @FlaggedApi(Flags.FLAG_GNSS_API_MEASUREMENT_REQUEST_WORK_SOURCE) @NonNull public android.os.WorkSource getWorkSource();
+    method @FlaggedApi("android.location.flags.gnss_api_measurement_request_work_source") @NonNull public android.os.WorkSource getWorkSource();
     method public boolean isCorrelationVectorOutputsEnabled();
   }
 
   public static final class GnssMeasurementRequest.Builder {
     method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
-    method @FlaggedApi(Flags.FLAG_GNSS_API_MEASUREMENT_REQUEST_WORK_SOURCE) @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+    method @FlaggedApi("android.location.flags.gnss_api_measurement_request_work_source") @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
   }
 
   public final class GnssReflectingPlane implements android.os.Parcelable {
@@ -591,7 +591,7 @@
 
 package android.location.provider {
 
-  @FlaggedApi(Flags.FLAG_NEW_GEOCODER) public final class ForwardGeocodeRequest implements android.os.Parcelable {
+  @FlaggedApi("android.location.flags.new_geocoder") public final class ForwardGeocodeRequest implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public String getCallingAttributionTag();
     method @NonNull public String getCallingPackage();
@@ -613,7 +613,7 @@
     method @NonNull public android.location.provider.ForwardGeocodeRequest.Builder setCallingAttributionTag(@NonNull String);
   }
 
-  @FlaggedApi(Flags.FLAG_NEW_GEOCODER) public abstract class GeocodeProviderBase {
+  @FlaggedApi("android.location.flags.new_geocoder") public abstract class GeocodeProviderBase {
     ctor public GeocodeProviderBase(@NonNull android.content.Context, @NonNull String);
     method @NonNull public final android.os.IBinder getBinder();
     method public abstract void onForwardGeocode(@NonNull android.location.provider.ForwardGeocodeRequest, @NonNull android.os.OutcomeReceiver<java.util.List<android.location.Address>,java.lang.Throwable>);
@@ -672,7 +672,7 @@
     method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
   }
 
-  @FlaggedApi(Flags.FLAG_NEW_GEOCODER) public final class ReverseGeocodeRequest implements android.os.Parcelable {
+  @FlaggedApi("android.location.flags.new_geocoder") public final class ReverseGeocodeRequest implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public String getCallingAttributionTag();
     method @NonNull public String getCallingPackage();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 3619d3a..d921730 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -432,6 +432,20 @@
     public static final String METADATA_SETTINGS_FOOTER_STRING =
             "com.android.settings.location.FOOTER_STRING";
 
+    /**
+     * Metadata name for {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast
+     * receivers to specify a string resource id as location settings footer HTML snippet. This is
+     * for use only by apps that are included in the system image. If HTML snippet is provided,
+     * plain text footer text specified with {@link #METADATA_SETTINGS_FOOTER_STRING} will be
+     * ignored.
+     *
+     * <p>See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use.
+     *
+     * @hide
+     */
+    public static final String METADATA_SETTINGS_FOOTER_HTML =
+            "com.android.settings.location.FOOTER_HTML";
+
     private static final long MAX_SINGLE_LOCATION_TIMEOUT_MS = 30 * 1000;
 
     private static final String CACHE_KEY_LOCATION_ENABLED_PROPERTY =
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index b8b03b6..4981029 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -80,6 +80,13 @@
 }
 
 flag {
+    name: "subscriptions_listener_thread"
+    namespace: "location"
+    description: "Flag for running onSubscriptionsChangeListener on FgThread"
+    bug: "332451908"
+}
+
+flag {
     name: "gnss_configuration_from_resource"
     namespace: "location"
     description: "Flag for GNSS configuration from resource"
diff --git a/media/java/android/media/FadeManagerConfiguration.java b/media/java/android/media/FadeManagerConfiguration.java
index eaafa59..6d84e70 100644
--- a/media/java/android/media/FadeManagerConfiguration.java
+++ b/media/java/android/media/FadeManagerConfiguration.java
@@ -836,7 +836,7 @@
          */
         public Builder(@NonNull FadeManagerConfiguration fmc) {
             mFadeState = fmc.mFadeState;
-            mUsageToFadeWrapperMap = fmc.mUsageToFadeWrapperMap.clone();
+            copyUsageToFadeWrapperMapInternal(fmc.mUsageToFadeWrapperMap);
             mAttrToFadeWrapperMap = new ArrayMap<AudioAttributes, FadeVolumeShaperConfigsWrapper>(
                     fmc.mAttrToFadeWrapperMap);
             mFadeableUsages = fmc.mFadeableUsages.clone();
@@ -1459,6 +1459,14 @@
             }
         }
 
+        private  void copyUsageToFadeWrapperMapInternal(
+                SparseArray<FadeVolumeShaperConfigsWrapper> usageToFadeWrapperMap) {
+            for (int index = 0; index < usageToFadeWrapperMap.size(); index++) {
+                mUsageToFadeWrapperMap.put(usageToFadeWrapperMap.keyAt(index),
+                        new FadeVolumeShaperConfigsWrapper(usageToFadeWrapperMap.valueAt(index)));
+            }
+        }
+
         private void validateFadeState(int state) {
             switch(state) {
                 case FADE_STATE_DISABLED:
@@ -1551,6 +1559,12 @@
 
         FadeVolumeShaperConfigsWrapper() {}
 
+        FadeVolumeShaperConfigsWrapper(@NonNull FadeVolumeShaperConfigsWrapper wrapper) {
+            Objects.requireNonNull(wrapper, "Fade volume shaper configs wrapper cannot be null");
+            this.mFadeOutVolShaperConfig = wrapper.mFadeOutVolShaperConfig;
+            this.mFadeInVolShaperConfig = wrapper.mFadeInVolShaperConfig;
+        }
+
         public void setFadeOutVolShaperConfig(@Nullable VolumeShaper.Configuration fadeOutConfig) {
             mFadeOutVolShaperConfig = fadeOutConfig;
         }
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index ce7474c..3ba0d59 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -5232,6 +5232,13 @@
         setParameters(keys, values);
     }
 
+    private void logAndRun(String message, Runnable r) {
+        final String TAG = "MediaCodec";
+        android.util.Log.d(TAG, "enter: " + message);
+        r.run();
+        android.util.Log.d(TAG, "exit : " + message);
+    }
+
     /**
      * Sets an asynchronous callback for actionable MediaCodec events.
      *
@@ -5261,14 +5268,40 @@
                 // even if we were to extend this to be callable dynamically, it must
                 // be called when codec is flushed, so no messages are pending.
                 if (newHandler != mCallbackHandler) {
-                    mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
-                    mCallbackHandler.removeMessages(EVENT_CALLBACK);
+                    if (android.media.codec.Flags.setCallbackStall()) {
+                        logAndRun(
+                                "[new handler] removeMessages(SET_CALLBACK)",
+                                () -> {
+                                    mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
+                                });
+                        logAndRun(
+                                "[new handler] removeMessages(CALLBACK)",
+                                () -> {
+                                    mCallbackHandler.removeMessages(EVENT_CALLBACK);
+                                });
+                    } else {
+                        mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
+                        mCallbackHandler.removeMessages(EVENT_CALLBACK);
+                    }
                     mCallbackHandler = newHandler;
                 }
             }
         } else if (mCallbackHandler != null) {
-            mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
-            mCallbackHandler.removeMessages(EVENT_CALLBACK);
+            if (android.media.codec.Flags.setCallbackStall()) {
+                logAndRun(
+                        "[null handler] removeMessages(SET_CALLBACK)",
+                        () -> {
+                            mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
+                        });
+                logAndRun(
+                        "[null handler] removeMessages(CALLBACK)",
+                        () -> {
+                            mCallbackHandler.removeMessages(EVENT_CALLBACK);
+                        });
+            } else {
+                mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
+                mCallbackHandler.removeMessages(EVENT_CALLBACK);
+            }
         }
 
         if (mCallbackHandler != null) {
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 5331046..6593533 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -205,6 +205,10 @@
      * media container format specified by mimeType at the requested
      * security level.
      *
+     * Calling this method while the application is running on the physical Android device or a
+     * {@link android.companion.virtual.VirtualDevice} may lead to different results, based on
+     * the different DRM capabilities of the devices.
+     *
      * @param uuid The UUID of the crypto scheme.
      * @param mimeType The MIME type of the media container, e.g. "video/mp4"
      *   or "video/webm"
@@ -1400,6 +1404,10 @@
      * Open a new session with the MediaDrm object. A session ID is returned.
      * By default, sessions are opened at the native security level of the device.
      *
+     * If the application is currently running on a {@link android.companion.virtual.VirtualDevice}
+     * the security level will be adjusted accordingly to the maximum supported level for the
+     * display.
+     *
      * @throws NotProvisionedException if provisioning is needed
      * @throws ResourceBusyException if required resources are in use
      */
@@ -1422,6 +1430,10 @@
      * can be queried using {@link #getSecurityLevel}. A session
      * ID is returned.
      *
+     * If the application is currently running on a {@link android.companion.virtual.VirtualDevice}
+     * the security level will be adjusted accordingly to the maximum supported level for the
+     * display.
+     *
      * @param level the new security level
      * @throws NotProvisionedException if provisioning is needed
      * @throws ResourceBusyException if required resources are in use
@@ -2180,6 +2192,11 @@
      * Returns a value that may be passed as a parameter to {@link #openSession(int)}
      * requesting that the session be opened at the maximum security level of
      * the device.
+     *
+     * This security level is only valid for the application running on the physical Android
+     * device (e.g. {@link android.content.Context#DEVICE_ID_DEFAULT}). While running on a
+     * {@link android.companion.virtual.VirtualDevice} the maximum supported security level
+     * might be different.
      */
     public static final int getMaxSecurityLevel() {
         return SECURITY_LEVEL_MAX;
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 3f9440b..ffd6e16 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -545,16 +545,17 @@
                                     ? SCANNING_STATE_SCANNING_FULL
                                     : SCANNING_STATE_WHILE_INTERACTIVE);
 
-                    if (scanRequest.isScreenOffScan()) {
-                        mScreenOffScanRequestCount++;
-                    } else {
-                        mScreenOnScanRequestCount++;
-                    }
                 } catch (RemoteException ex) {
                     throw ex.rethrowFromSystemServer();
                 }
             }
 
+            if (scanRequest.isScreenOffScan()) {
+                mScreenOffScanRequestCount++;
+            } else {
+                mScreenOnScanRequestCount++;
+            }
+
             mScanRequestsMap.put(token.mId, scanRequest);
             return token;
         }
@@ -580,27 +581,29 @@
             }
 
             boolean shouldUpdate =
-                    mScreenOffScanRequestCount == 1
-                            && (request.isScreenOffScan() || mScreenOnScanRequestCount == 1);
+                    request.isScreenOffScan()
+                            ? mScreenOffScanRequestCount == 1
+                            : mScreenOnScanRequestCount == 1 && mScreenOffScanRequestCount == 0;
 
             if (shouldUpdate) {
                 try {
-                    if (request.isScreenOffScan() && mScreenOnScanRequestCount == 0) {
+                    if (!request.isScreenOffScan() || mScreenOnScanRequestCount == 0) {
                         mImpl.updateScanningState(SCANNING_STATE_NOT_SCANNING);
                     } else {
                         mImpl.updateScanningState(SCANNING_STATE_WHILE_INTERACTIVE);
                     }
 
-                    if (request.isScreenOffScan()) {
-                        mScreenOffScanRequestCount--;
-                    } else {
-                        mScreenOnScanRequestCount--;
-                    }
                 } catch (RemoteException ex) {
                     ex.rethrowFromSystemServer();
                 }
             }
 
+            if (request.isScreenOffScan()) {
+                mScreenOffScanRequestCount--;
+            } else {
+                mScreenOnScanRequestCount--;
+            }
+
             mScanRequestsMap.remove(token.mId);
         }
     }
@@ -1309,18 +1312,24 @@
             return;
         }
 
-        RoutingController newController;
-        if (sessionInfo.isSystemSession()) {
-            newController = getSystemController();
-            newController.setRoutingSessionInfo(sessionInfo);
+        RoutingController newController = addRoutingController(sessionInfo);
+        notifyTransfer(oldController, newController);
+    }
+
+    @NonNull
+    private RoutingController addRoutingController(@NonNull RoutingSessionInfo session) {
+        RoutingController controller;
+        if (session.isSystemSession()) {
+            // mSystemController is never released, so we only need to update its status.
+            mSystemController.setRoutingSessionInfo(session);
+            controller = mSystemController;
         } else {
-            newController = new RoutingController(sessionInfo);
+            controller = new RoutingController(session);
             synchronized (mLock) {
-                mNonSystemRoutingControllers.put(newController.getId(), newController);
+                mNonSystemRoutingControllers.put(controller.getId(), controller);
             }
         }
-
-        notifyTransfer(oldController, newController);
+        return controller;
     }
 
     void updateControllerOnHandler(RoutingSessionInfo sessionInfo) {
@@ -1329,40 +1338,12 @@
             return;
         }
 
-        if (sessionInfo.isSystemSession()) {
-            // The session info is sent from SystemMediaRoute2Provider.
-            RoutingController systemController = getSystemController();
-            systemController.setRoutingSessionInfo(sessionInfo);
-            notifyControllerUpdated(systemController);
-            return;
+        RoutingController controller =
+                getMatchingController(sessionInfo, /* logPrefix */ "updateControllerOnHandler");
+        if (controller != null) {
+            controller.setRoutingSessionInfo(sessionInfo);
+            notifyControllerUpdated(controller);
         }
-
-        RoutingController matchingController;
-        synchronized (mLock) {
-            matchingController = mNonSystemRoutingControllers.get(sessionInfo.getId());
-        }
-
-        if (matchingController == null) {
-            Log.w(
-                    TAG,
-                    "updateControllerOnHandler: Matching controller not found. uniqueSessionId="
-                            + sessionInfo.getId());
-            return;
-        }
-
-        RoutingSessionInfo oldInfo = matchingController.getRoutingSessionInfo();
-        if (!TextUtils.equals(oldInfo.getProviderId(), sessionInfo.getProviderId())) {
-            Log.w(
-                    TAG,
-                    "updateControllerOnHandler: Provider IDs are not matched. old="
-                            + oldInfo.getProviderId()
-                            + ", new="
-                            + sessionInfo.getProviderId());
-            return;
-        }
-
-        matchingController.setRoutingSessionInfo(sessionInfo);
-        notifyControllerUpdated(matchingController);
     }
 
     void releaseControllerOnHandler(RoutingSessionInfo sessionInfo) {
@@ -1371,34 +1352,47 @@
             return;
         }
 
-        RoutingController matchingController;
-        synchronized (mLock) {
-            matchingController = mNonSystemRoutingControllers.get(sessionInfo.getId());
-        }
+        RoutingController matchingController =
+                getMatchingController(sessionInfo, /* logPrefix */ "releaseControllerOnHandler");
 
-        if (matchingController == null) {
-            if (DEBUG) {
-                Log.d(
-                        TAG,
-                        "releaseControllerOnHandler: Matching controller not found. "
-                                + "uniqueSessionId="
-                                + sessionInfo.getId());
+        if (matchingController != null) {
+            matchingController.releaseInternal(/* shouldReleaseSession= */ false);
+        }
+    }
+
+    @Nullable
+    private RoutingController getMatchingController(
+            RoutingSessionInfo sessionInfo, String logPrefix) {
+        if (sessionInfo.isSystemSession()) {
+            return getSystemController();
+        } else {
+            RoutingController controller;
+            synchronized (mLock) {
+                controller = mNonSystemRoutingControllers.get(sessionInfo.getId());
             }
-            return;
-        }
 
-        RoutingSessionInfo oldInfo = matchingController.getRoutingSessionInfo();
-        if (!TextUtils.equals(oldInfo.getProviderId(), sessionInfo.getProviderId())) {
-            Log.w(
-                    TAG,
-                    "releaseControllerOnHandler: Provider IDs are not matched. old="
-                            + oldInfo.getProviderId()
-                            + ", new="
-                            + sessionInfo.getProviderId());
-            return;
-        }
+            if (controller == null) {
+                Log.w(
+                        TAG,
+                        logPrefix
+                                + ": Matching controller not found. uniqueSessionId="
+                                + sessionInfo.getId());
+                return null;
+            }
 
-        matchingController.releaseInternal(/* shouldReleaseSession= */ false);
+            RoutingSessionInfo oldInfo = controller.getRoutingSessionInfo();
+            if (!TextUtils.equals(oldInfo.getProviderId(), sessionInfo.getProviderId())) {
+                Log.w(
+                        TAG,
+                        logPrefix
+                                + ": Provider IDs are not matched. old="
+                                + oldInfo.getProviderId()
+                                + ", new="
+                                + sessionInfo.getProviderId());
+                return null;
+            }
+            return controller;
+        }
     }
 
     void onRequestCreateControllerByManagerOnHandler(
@@ -2722,7 +2716,7 @@
 
             List<RoutingSessionInfo> sessionInfos = getRoutingSessions();
             RoutingSessionInfo targetSession = sessionInfos.get(sessionInfos.size() - 1);
-            transfer(targetSession, route, Process.myUserHandle(), mContext.getPackageName());
+            transfer(targetSession, route, mClientUser, mContext.getPackageName());
         }
 
         @Override
@@ -3129,20 +3123,8 @@
 
         private void onTransferred(
                 @NonNull RoutingSessionInfo oldSession, @NonNull RoutingSessionInfo newSession) {
-            if (!oldSession.isSystemSession()
-                    && !TextUtils.equals(
-                            getClientPackageName(), oldSession.getClientPackageName())) {
-                return;
-            }
-
-            if (!newSession.isSystemSession()
-                    && !TextUtils.equals(
-                            getClientPackageName(), newSession.getClientPackageName())) {
-                return;
-            }
-
-            // For successful in-session transfer, onControllerUpdated() handles it.
-            if (TextUtils.equals(oldSession.getId(), newSession.getId())) {
+            if (!isSessionRelatedToTargetPackageName(oldSession)
+                    || !isSessionRelatedToTargetPackageName(newSession)) {
                 return;
             }
 
@@ -3169,16 +3151,14 @@
 
         private void onTransferFailed(
                 @NonNull RoutingSessionInfo session, @NonNull MediaRoute2Info route) {
-            if (!session.isSystemSession()
-                    && !TextUtils.equals(getClientPackageName(), session.getClientPackageName())) {
+            if (!isSessionRelatedToTargetPackageName(session)) {
                 return;
             }
             notifyTransferFailure(route);
         }
 
         private void onSessionUpdated(@NonNull RoutingSessionInfo session) {
-            if (!session.isSystemSession()
-                    && !TextUtils.equals(getClientPackageName(), session.getClientPackageName())) {
+            if (!isSessionRelatedToTargetPackageName(session)) {
                 return;
             }
 
@@ -3193,6 +3173,15 @@
             notifyControllerUpdated(controller);
         }
 
+        /**
+         * Returns {@code true} if the session is a system session or if its client package name
+         * matches the proxy router's target package name.
+         */
+        private boolean isSessionRelatedToTargetPackageName(@NonNull RoutingSessionInfo session) {
+            return session.isSystemSession()
+                    || TextUtils.equals(getClientPackageName(), session.getClientPackageName());
+        }
+
         private void onSessionCreatedOnHandler(
                 int requestId, @NonNull RoutingSessionInfo sessionInfo) {
             MediaRouter2Manager.TransferRequest matchingRequest = null;
@@ -3237,19 +3226,19 @@
             }
         }
 
-        private void onSessionUpdatedOnHandler(@NonNull RoutingSessionInfo sessionInfo) {
+        private void onSessionUpdatedOnHandler(@NonNull RoutingSessionInfo updatedSession) {
             for (MediaRouter2Manager.TransferRequest request : mTransferRequests) {
                 String sessionId = request.mOldSessionInfo.getId();
-                if (!TextUtils.equals(sessionId, sessionInfo.getId())) {
+                if (!TextUtils.equals(sessionId, updatedSession.getId())) {
                     continue;
                 }
-                if (sessionInfo.getSelectedRoutes().contains(request.mTargetRoute.getId())) {
+
+                if (updatedSession.getSelectedRoutes().contains(request.mTargetRoute.getId())) {
                     mTransferRequests.remove(request);
-                    this.onTransferred(request.mOldSessionInfo, sessionInfo);
                     break;
                 }
             }
-            this.onSessionUpdated(sessionInfo);
+            this.onSessionUpdated(updatedSession);
         }
 
         private void onSessionReleasedOnHandler(@NonNull RoutingSessionInfo session) {
diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java
index 2202766..a3c8b68 100644
--- a/media/java/android/media/RoutingSessionInfo.java
+++ b/media/java/android/media/RoutingSessionInfo.java
@@ -84,7 +84,6 @@
      *
      * @hide
      */
-    @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
     @IntDef(value = {TRANSFER_REASON_FALLBACK, TRANSFER_REASON_SYSTEM_REQUEST, TRANSFER_REASON_APP})
     @Retention(RetentionPolicy.SOURCE)
     public @interface TransferReason {}
@@ -382,14 +381,12 @@
     }
 
     /** @hide */
-    @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
     @Nullable
     public UserHandle getTransferInitiatorUserHandle() {
         return mTransferInitiatorUserHandle;
     }
 
     /** @hide */
-    @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
     @Nullable
     public String getTransferInitiatorPackageName() {
         return mTransferInitiatorPackageName;
diff --git a/media/java/android/media/flags/media_better_together.aconfig b/media/java/android/media/flags/media_better_together.aconfig
index c1be6b5..91c4f11 100644
--- a/media/java/android/media/flags/media_better_together.aconfig
+++ b/media/java/android/media/flags/media_better_together.aconfig
@@ -25,13 +25,6 @@
 }
 
 flag {
-    name: "disable_screen_off_broadcast_receiver"
-    namespace: "media_solutions"
-    description: "Disables the broadcast receiver that prevents scanning when the screen is off."
-    bug: "304234628"
-}
-
-flag {
     name: "fallback_to_default_handling_when_media_session_has_fixed_volume_handling"
     namespace: "media_solutions"
     description: "Fallbacks to the default handling for volume adjustment when media session has fixed volume handling and its app is in the foreground and setting a media controller."
@@ -108,6 +101,16 @@
 }
 
 flag {
+    name: "enable_mr2_service_non_main_bg_thread"
+    namespace: "media_solutions"
+    description: "Enables the use of a background thread in the media routing framework, instead of using the main thread."
+    bug: "310145678"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "enable_screen_off_scanning"
     is_exported: true
     namespace: "media_solutions"
@@ -121,3 +124,13 @@
     description: "Enables apps owning a MediaBrowserService to disconnect all connected browsers."
     bug: "185136506"
 }
+
+flag {
+    name: "enable_prevention_of_manager_scans_when_no_apps_scan"
+    namespace: "media_solutions"
+    description: "Prevents waking up route providers when no apps are scanning, even if SysUI or Settings are scanning."
+    bug: "319604673"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/media/java/android/media/flags/performance.aconfig b/media/java/android/media/flags/performance.aconfig
index 9e9197e..464efea 100644
--- a/media/java/android/media/flags/performance.aconfig
+++ b/media/java/android/media/flags/performance.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.media.performance.flags"
+container: "system"
 
 flag {
     name: "media_description_ashmem_bitmap"
diff --git a/media/java/android/media/midi/package.html b/media/java/android/media/midi/package.html
index 45b4370..988b5cf 100644
--- a/media/java/android/media/midi/package.html
+++ b/media/java/android/media/midi/package.html
@@ -332,7 +332,8 @@
 
 <pre class=prettyprint>
 &lt;service android:name="<strong>MySynthDeviceService</strong>"
-  android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE">
+  android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE"
+  android:exported="true">
   &lt;intent-filter>
     &lt;action android:name="android.media.midi.MidiDeviceService" />
   &lt;/intent-filter>
@@ -474,7 +475,8 @@
 
 <pre class=prettyprint>
 &lt;service android:name="<strong>MidiEchoDeviceService</strong>"
-  android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE">
+  android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE"
+  android:exported="true">
   &lt;intent-filter>
     &lt;action android:name="android.media.midi.MidiUmpDeviceService" />
   &lt;/intent-filter>
@@ -509,6 +511,11 @@
 import android.media.midi.MidiReceiver;
 import android.media.midi.MidiUmpDeviceService;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 public class MidiEchoDeviceService extends MidiUmpDeviceService {
     private static final String TAG = "MidiEchoDeviceService";
     // Other apps will write to this port.
@@ -528,8 +535,8 @@
 
     &#64;Override
     // Declare the receivers associated with your input ports.
-    public List<MidiReceiver> onGetInputPortReceivers() {
-        return new ArrayList<MidiReceiver>(Collections.singletonList(mInputReceiver));
+    public List&lt;MidiReceiver> onGetInputPortReceivers() {
+        return new ArrayList&lt;MidiReceiver>(Collections.singletonList(mInputReceiver));
     }
 
     /**
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index 2a0648d..7ed67dc 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -23,6 +23,9 @@
 import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.ActivityOptions.LaunchCookie;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.Overridable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -66,6 +69,18 @@
     private static final String TAG = "MediaProjectionManager";
 
     /**
+     * This change id ensures that users are presented with a choice of capturing a single app
+     * or the entire screen when initiating a MediaProjection session, overriding the usage of
+     * MediaProjectionConfig#createConfigForDefaultDisplay.
+     *
+     * @hide
+     */
+    @ChangeId
+    @Overridable
+    @Disabled
+    public static final long OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION = 316897322L;
+
+    /**
      * Intent extra to customize the permission dialog based on the host app's preferences.
      * @hide
      */
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 207ccbe..871e9ab 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -80,4 +80,7 @@
     boolean hasCustomMediaSessionPolicyProvider(String componentName);
     int getSessionPolicies(in MediaSession.Token token);
     void setSessionPolicies(in MediaSession.Token token, int policies);
+
+    // For testing of temporarily engaged sessions.
+    void expireTempEngagedSessions();
 }
diff --git a/media/java/android/media/session/ParcelableListBinder.java b/media/java/android/media/session/ParcelableListBinder.java
index bbf1e08..d788284 100644
--- a/media/java/android/media/session/ParcelableListBinder.java
+++ b/media/java/android/media/session/ParcelableListBinder.java
@@ -45,6 +45,7 @@
     private static final int END_OF_PARCEL = 0;
     private static final int ITEM_CONTINUED = 1;
 
+    private final Class<T> mListElementsClass;
     private final Consumer<List<T>> mConsumer;
 
     private final Object mLock = new Object();
@@ -61,9 +62,11 @@
     /**
      * Creates an instance.
      *
+     * @param listElementsClass the class of the list elements.
      * @param consumer a consumer that consumes the list received
      */
-    public ParcelableListBinder(@NonNull Consumer<List<T>> consumer) {
+    public ParcelableListBinder(Class<T> listElementsClass, @NonNull Consumer<List<T>> consumer) {
+        mListElementsClass = listElementsClass;
         mConsumer = consumer;
     }
 
@@ -83,7 +86,13 @@
                 mCount = data.readInt();
             }
             while (i < mCount && data.readInt() != END_OF_PARCEL) {
-                mList.add(data.readParcelable(null));
+                Object object = data.readParcelable(null);
+                if (mListElementsClass.isAssignableFrom(object.getClass())) {
+                    // Checking list items are of compaitible types to validate against malicious
+                    // apps calling it directly via reflection with non compilable items.
+                    // See b/317048338 for more details
+                    mList.add((T) object);
+                }
                 i++;
             }
             if (i >= mCount) {
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 94fce79..8609c4d 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -82,6 +82,7 @@
         "libhidlbase",
         "libsonivox",
         "server_configurable_flags",
+        "android.companion.virtual.virtualdevice_aidl-cpp",
         "[email protected]",
         "[email protected]",
         "[email protected]",
@@ -100,6 +101,7 @@
     static_libs: [
         "libgrallocusage",
         "libmedia_midiiowrapper",
+        "android.companion.virtualdevice.flags-aconfig-cc",
         "android.media.playback.flags-aconfig-cc",
     ],
 
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 82561f9..4492c85 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2088,26 +2088,27 @@
             }
             return BAD_VALUE;
         }
-        size_t offset = static_cast<size_t>(env->GetIntField(param, gFields.bufferInfoOffset));
-        size_t size = static_cast<size_t>(env->GetIntField(param, gFields.bufferInfoSize));
+        ssize_t offset = static_cast<ssize_t>(env->GetIntField(param, gFields.bufferInfoOffset));
+        ssize_t size = static_cast<ssize_t>(env->GetIntField(param, gFields.bufferInfoSize));
         uint32_t flags = static_cast<uint32_t>(env->GetIntField(param, gFields.bufferInfoFlags));
-        if (flags == 0 && size == 0) {
-            if (errorDetailMsg) {
-                *errorDetailMsg = "Error: Queuing an empty BufferInfo";
-            }
-            return BAD_VALUE;
-        }
         if (i == 0) {
             *initialOffset = offset;
         }
-        if (CC_UNLIKELY((offset >  UINT32_MAX)
-                || ((long)(offset + size) > UINT32_MAX)
-                || ((offset - *initialOffset) != *totalSize))) {
+        if (CC_UNLIKELY((offset < 0)
+                || (size < 0)
+                || ((INT32_MAX - offset) < size)
+                || ((offset - (*initialOffset)) != *totalSize))) {
             if (errorDetailMsg) {
                 *errorDetailMsg = "Error: offset/size in BufferInfo";
             }
             return BAD_VALUE;
         }
+        if (flags == 0 && size == 0) {
+            if (errorDetailMsg) {
+                *errorDetailMsg = "Error: Queuing an empty BufferInfo";
+            }
+            return BAD_VALUE;
+        }
         infos->emplace_back(
                 flags,
                 size,
@@ -2886,6 +2887,10 @@
         jint offset,
         jint size,
         sp<hardware::HidlMemory> *memory) {
+    if ((offset + size) > context->capacity()) {
+        ALOGW("extractMemoryFromContext: offset + size provided exceed capacity");
+        return;
+    }
     *memory = context->toHidlMemory();
     if (*memory == nullptr) {
         if (!context->mBlock) {
@@ -2893,23 +2898,26 @@
             return;
         }
         ALOGD("extractMemoryFromContext: realloc & copying from C2Block to IMemory (cap=%zu)",
-              context->capacity());
+                context->capacity());
         if (!obtain(context, context->capacity(),
                     context->mCodecNames, true /* secure */)) {
             ALOGW("extractMemoryFromContext: failed to obtain secure block");
             return;
         }
-        C2WriteView view = context->mBlock->map().get();
-        if (view.error() != C2_OK) {
-            ALOGW("extractMemoryFromContext: failed to map C2Block (%d)", view.error());
-            return;
-        }
-        uint8_t *memoryPtr = static_cast<uint8_t *>(context->mMemory->unsecurePointer());
-        memcpy(memoryPtr + offset, view.base() + offset, size);
-        context->mBlock.reset();
-        context->mReadWriteMapping.reset();
         *memory = context->toHidlMemory();
     }
+    if (context->mBlock == nullptr || context->mReadWriteMapping == nullptr) {
+        ALOGW("extractMemoryFromContext: Cannot extract memory as C2Block is not created/mapped");
+        return;
+    }
+    if (context->mReadWriteMapping->error() != C2_OK) {
+        ALOGW("extractMemoryFromContext: failed to map C2Block (%d)",
+                context->mReadWriteMapping->error());
+        return;
+    }
+    // We are proceeding to extract memory from C2Block
+    uint8_t *memoryPtr = static_cast<uint8_t *>(context->mMemory->unsecurePointer());
+    memcpy(memoryPtr + offset, context->mReadWriteMapping->base() + offset, size);
 }
 
 static void extractBufferFromContext(
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 1c25080..48cd53d 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -27,6 +27,8 @@
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 
+#include <android_companion_virtualdevice_flags.h>
+#include <android/companion/virtualnative/IVirtualDeviceManagerNative.h>
 #include <android/hardware/drm/1.3/IDrmFactory.h>
 #include <binder/Parcel.h>
 #include <binder/PersistableBundle.h>
@@ -41,8 +43,10 @@
 #include <map>
 #include <string>
 
+using ::android::companion::virtualnative::IVirtualDeviceManagerNative;
 using ::android::os::PersistableBundle;
 namespace drm = ::android::hardware::drm;
+namespace virtualdevice_flags = android::companion::virtualdevice::flags;
 
 namespace android {
 
@@ -1045,6 +1049,26 @@
     return level;
 }
 
+std::vector<int> getVirtualDeviceIds() {
+    if (!virtualdevice_flags::device_aware_drm()) {
+        ALOGW("Device-aware DRM flag disabled.");
+        return std::vector<int>();
+    }
+
+    sp<IBinder> binder =
+            defaultServiceManager()->checkService(String16("virtualdevice_native"));
+    if (binder != nullptr) {
+        auto vdm = interface_cast<IVirtualDeviceManagerNative>(binder);
+        std::vector<int> deviceIds;
+        const uid_t uid = IPCThreadState::self()->getCallingUid();
+        vdm->getDeviceIdsForUid(uid, &deviceIds);
+        return deviceIds;
+    } else {
+        ALOGW("Cannot get virtualdevice_native service");
+        return std::vector<int>();
+    }
+}
+
 static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
     sp<IDrm> drm = android::DrmUtils::MakeDrm();
     if (drm == NULL) return env->NewByteArray(0);
@@ -1081,6 +1105,15 @@
     }
     DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
 
+    if (getVirtualDeviceIds().size() > 0) {
+        // Cap security level at max SECURITY_LEVEL_SW_SECURE_CRYPTO because at
+        // higher security levels decode output cannot be captured and
+        // streamed to virtual devices rendered on virtual displays.
+        if (securityLevel > DrmPlugin::kSecurityLevelSwSecureCrypto) {
+            return false;
+        }
+    }
+
     bool isSupported;
     status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
             securityLevel, &isSupported);
@@ -1106,6 +1139,16 @@
         return NULL;
     }
 
+    if (getVirtualDeviceIds().size() > 0) {
+        // Cap security level at max SECURITY_LEVEL_SW_SECURE_CRYPTO because at
+        // higher security levels decode output cannot be captured and
+        // streamed to virtual devices rendered on virtual displays.
+        if (level == DrmPlugin::kSecurityLevelMax ||
+            level > DrmPlugin::kSecurityLevelSwSecureCrypto) {
+            level = DrmPlugin::kSecurityLevelSwSecureCrypto;
+        }
+    }
+
     DrmStatus err = drm->openSession(level, sessionId);
 
     if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index a64e3f2..36cba2d 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -19,6 +19,8 @@
 
 #include "jni.h"
 
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <mediadrm/IDrm.h>
 #include <mediadrm/IDrmClient.h>
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java
index c48a956..74b5afe 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/FadeManagerConfigurationUnitTest.java
@@ -196,8 +196,7 @@
         FadeManagerConfiguration fmcObj = new FadeManagerConfiguration
                 .Builder(TEST_FADE_OUT_DURATION_MS, TEST_FADE_IN_DURATION_MS).build();
 
-        FadeManagerConfiguration fmc = new FadeManagerConfiguration
-                .Builder(fmcObj).build();
+        FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder(fmcObj).build();
 
         expect.withMessage("Fade state for copy builder").that(fmc.getFadeState())
                 .isEqualTo(fmcObj.getFadeState());
@@ -249,6 +248,45 @@
     }
 
     @Test
+    public void build_withCopyConstructor_doesnotChangeOriginal() {
+        FadeManagerConfiguration copyConstructedFmc = new FadeManagerConfiguration.Builder(mFmc)
+                .setFadeOutDurationForUsage(AudioAttributes.USAGE_MEDIA, TEST_FADE_OUT_DURATION_MS)
+                .setFadeInDurationForUsage(AudioAttributes.USAGE_MEDIA, TEST_FADE_IN_DURATION_MS)
+                .build();
+
+        expect.withMessage("Fade out duration for media usage of default constructor")
+                .that(mFmc.getFadeOutDurationForUsage(AudioAttributes.USAGE_MEDIA))
+                .isEqualTo(DEFAULT_FADE_OUT_DURATION_MS);
+        expect.withMessage("Fade out duration for media usage of default constructor")
+                .that(mFmc.getFadeInDurationForUsage(AudioAttributes.USAGE_MEDIA))
+                .isEqualTo(DEFAULT_FADE_IN_DURATION_MS);
+        expect.withMessage("Fade out duration for media usage of copy constructor")
+                .that(copyConstructedFmc.getFadeOutDurationForUsage(AudioAttributes.USAGE_MEDIA))
+                .isEqualTo(TEST_FADE_OUT_DURATION_MS);
+        expect.withMessage("Fade out duration for media usage of copy constructor")
+                .that(copyConstructedFmc.getFadeInDurationForUsage(AudioAttributes.USAGE_MEDIA))
+                .isEqualTo(TEST_FADE_IN_DURATION_MS);
+    }
+
+    @Test
+    public void build_withCopyConstructor_equals() {
+        FadeManagerConfiguration fmc = new FadeManagerConfiguration.Builder()
+                .setFadeableUsages(List.of(AudioAttributes.USAGE_MEDIA,
+                        AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+                        AudioAttributes.USAGE_ASSISTANT,
+                        AudioAttributes.USAGE_EMERGENCY))
+                .setFadeOutDurationForUsage(AudioAttributes.USAGE_MEDIA, TEST_FADE_OUT_DURATION_MS)
+                .setFadeInDurationForUsage(AudioAttributes.USAGE_MEDIA, TEST_FADE_IN_DURATION_MS)
+                .build();
+
+        FadeManagerConfiguration copyConstructedFmc =
+                new FadeManagerConfiguration.Builder(fmc).build();
+
+        expect.withMessage("Fade manager config constructed using copy constructor").that(fmc)
+                .isEqualTo(copyConstructedFmc);
+    }
+
+    @Test
     public void testGetDefaultFadeOutDuration() {
         expect.withMessage("Default fade out duration")
                 .that(FadeManagerConfiguration.getDefaultFadeOutDurationMillis())
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index c836df3..520b76e 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -361,6 +361,7 @@
      * Tests if MR2.SessionCallback.onSessionCreated is called
      * when a route is selected from MR2Manager.
      */
+    @Ignore // Ignored due to flakiness. No plans to fix though, in favor of removal (b/334970551).
     @Test
     public void testRouterOnSessionCreated() throws Exception {
         Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
@@ -512,6 +513,7 @@
     /**
      * Tests select, transfer, release of routes of a provider
      */
+    @Ignore // Ignored due to flakiness. No plans to fix though, in favor of removal (b/334970551).
     @Test
     public void testSelectAndTransferAndRelease() throws Exception {
         Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
@@ -908,6 +910,7 @@
      * Tests if getSelectableRoutes and getDeselectableRoutes filter routes based on
      * selected routes
      */
+    @Ignore // Ignored due to flakiness. No plans to fix though, in favor of removal (b/334970551).
     @Test
     public void testGetSelectableRoutes_notReturnsSelectedRoutes() throws Exception {
         Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 1c203e3..346c87d 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -366,6 +366,7 @@
     APerformanceHint_setIHintManagerForTesting;
     APerformanceHint_sendHint;
     APerformanceHint_getThreadIds;
+    APerformanceHint_createSessionInternal;
     extern "C++" {
         ASurfaceControl_registerSurfaceStatsListener*;
         ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 8227bdb..83056b2 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -41,16 +41,15 @@
 
 using namespace std::chrono_literals;
 
-using HalSessionHint = aidl::android::hardware::power::SessionHint;
-using HalSessionMode = aidl::android::hardware::power::SessionMode;
-using HalWorkDuration = aidl::android::hardware::power::WorkDuration;
+// Namespace for AIDL types coming from the PowerHAL
+namespace hal = aidl::android::hardware::power;
 
 using android::base::StringPrintf;
 
 struct APerformanceHintSession;
 
 constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count();
-struct AWorkDuration : public HalWorkDuration {};
+struct AWorkDuration : public hal::WorkDuration {};
 
 struct APerformanceHintManager {
 public:
@@ -60,7 +59,8 @@
     ~APerformanceHintManager() = default;
 
     APerformanceHintSession* createSession(const int32_t* threadIds, size_t size,
-                                           int64_t initialTargetWorkDurationNanos);
+                                           int64_t initialTargetWorkDurationNanos,
+                                           hal::SessionTag tag = hal::SessionTag::OTHER);
     int64_t getPreferredRateNanos() const;
 
 private:
@@ -85,7 +85,8 @@
 public:
     APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
                             std::shared_ptr<IHintSession> session, int64_t preferredRateNanos,
-                            int64_t targetDurationNanos);
+                            int64_t targetDurationNanos,
+                            std::optional<hal::SessionConfig> sessionConfig);
     APerformanceHintSession() = delete;
     ~APerformanceHintSession();
 
@@ -115,11 +116,12 @@
     // Last hint reported from sendHint indexed by hint value
     std::vector<int64_t> mLastHintSentTimestamp;
     // Cached samples
-    std::vector<HalWorkDuration> mActualWorkDurations;
+    std::vector<hal::WorkDuration> mActualWorkDurations;
     std::string mSessionName;
-    static int32_t sIDCounter;
+    static int64_t sIDCounter;
     // The most recent set of thread IDs
     std::vector<int32_t> mLastThreadIDs;
+    std::optional<hal::SessionConfig> mSessionConfig;
     // Tracing helpers
     void traceThreads(std::vector<int32_t>& tids);
     void tracePowerEfficient(bool powerEfficient);
@@ -130,7 +132,8 @@
 
 static std::shared_ptr<IHintManager>* gIHintManagerForTesting = nullptr;
 static APerformanceHintManager* gHintManagerForTesting = nullptr;
-int32_t APerformanceHintSession::sIDCounter = 0;
+// Start above the int32 range so we don't collide with config sessions
+int64_t APerformanceHintSession::sIDCounter = INT32_MAX;
 
 // ===================================== APerformanceHintManager implementation
 APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager> manager,
@@ -175,16 +178,20 @@
 }
 
 APerformanceHintSession* APerformanceHintManager::createSession(
-        const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
+        const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos,
+        hal::SessionTag tag) {
     std::vector<int32_t> tids(threadIds, threadIds + size);
     std::shared_ptr<IHintSession> session;
-    ndk::ScopedAStatus ret =
-            mHintManager->createHintSession(mToken, tids, initialTargetWorkDurationNanos, &session);
+    ndk::ScopedAStatus ret;
+    std::optional<hal::SessionConfig> sessionConfig;
+    ret = mHintManager->createHintSessionWithConfig(mToken, tids, initialTargetWorkDurationNanos,
+                                                    tag, &sessionConfig, &session);
+
     if (!ret.isOk() || !session) {
         return nullptr;
     }
     auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos,
-                                           initialTargetWorkDurationNanos);
+                                           initialTargetWorkDurationNanos, sessionConfig);
     out->traceThreads(tids);
     out->traceTargetDuration(initialTargetWorkDurationNanos);
     out->tracePowerEfficient(false);
@@ -200,18 +207,23 @@
 APerformanceHintSession::APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
                                                  std::shared_ptr<IHintSession> session,
                                                  int64_t preferredRateNanos,
-                                                 int64_t targetDurationNanos)
+                                                 int64_t targetDurationNanos,
+                                                 std::optional<hal::SessionConfig> sessionConfig)
       : mHintManager(hintManager),
         mHintSession(std::move(session)),
         mPreferredRateNanos(preferredRateNanos),
         mTargetDurationNanos(targetDurationNanos),
         mFirstTargetMetTimestamp(0),
-        mLastTargetMetTimestamp(0) {
-    const std::vector<HalSessionHint> sessionHintRange{ndk::enum_range<HalSessionHint>().begin(),
-                                                       ndk::enum_range<HalSessionHint>().end()};
-
-    mLastHintSentTimestamp = std::vector<int64_t>(sessionHintRange.size(), 0);
-    mSessionName = android::base::StringPrintf("ADPF Session %" PRId32, ++sIDCounter);
+        mLastTargetMetTimestamp(0),
+        mSessionConfig(sessionConfig) {
+    if (sessionConfig->id > INT32_MAX) {
+        ALOGE("Session ID too large, must fit 32-bit integer");
+    }
+    constexpr int numEnums =
+            ndk::enum_range<hal::SessionHint>().end() - ndk::enum_range<hal::SessionHint>().begin();
+    mLastHintSentTimestamp = std::vector<int64_t>(numEnums, 0);
+    int64_t traceId = sessionConfig.has_value() ? sessionConfig->id : ++sIDCounter;
+    mSessionName = android::base::StringPrintf("ADPF Session %" PRId64, traceId);
 }
 
 APerformanceHintSession::~APerformanceHintSession() {
@@ -246,10 +258,10 @@
 }
 
 int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) {
-    HalWorkDuration workDuration{.durationNanos = actualDurationNanos,
-                                 .workPeriodStartTimestampNanos = 0,
-                                 .cpuDurationNanos = actualDurationNanos,
-                                 .gpuDurationNanos = 0};
+    hal::WorkDuration workDuration{.durationNanos = actualDurationNanos,
+                                   .workPeriodStartTimestampNanos = 0,
+                                   .cpuDurationNanos = actualDurationNanos,
+                                   .gpuDurationNanos = 0};
 
     return reportActualWorkDurationInternal(static_cast<AWorkDuration*>(&workDuration));
 }
@@ -323,7 +335,8 @@
 
 int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) {
     ndk::ScopedAStatus ret =
-            mHintSession->setMode(static_cast<int32_t>(HalSessionMode::POWER_EFFICIENCY), enabled);
+            mHintSession->setMode(static_cast<int32_t>(hal::SessionMode::POWER_EFFICIENCY),
+                                  enabled);
 
     if (!ret.isOk()) {
         ALOGE("%s: HintSession setPreferPowerEfficiency failed: %s", __FUNCTION__,
@@ -450,6 +463,15 @@
     return manager->createSession(threadIds, size, initialTargetWorkDurationNanos);
 }
 
+APerformanceHintSession* APerformanceHint_createSessionInternal(
+        APerformanceHintManager* manager, const int32_t* threadIds, size_t size,
+        int64_t initialTargetWorkDurationNanos, SessionTag tag) {
+    VALIDATE_PTR(manager)
+    VALIDATE_PTR(threadIds)
+    return manager->createSession(threadIds, size, initialTargetWorkDurationNanos,
+                                  static_cast<hal::SessionTag>(tag));
+}
+
 int64_t APerformanceHint_getPreferredUpdateRateNanos(APerformanceHintManager* manager) {
     VALIDATE_PTR(manager)
     return manager->getPreferredRateNanos();
@@ -473,9 +495,9 @@
     delete session;
 }
 
-int APerformanceHint_sendHint(void* session, SessionHint hint) {
+int APerformanceHint_sendHint(APerformanceHintSession* session, SessionHint hint) {
     VALIDATE_PTR(session)
-    return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint);
+    return session->sendHint(hint);
 }
 
 int APerformanceHint_setThreads(APerformanceHintSession* session, const pid_t* threadIds,
@@ -485,11 +507,10 @@
     return session->setThreads(threadIds, size);
 }
 
-int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const threadIds,
+int APerformanceHint_getThreadIds(APerformanceHintSession* session, int32_t* const threadIds,
                                   size_t* const size) {
-    VALIDATE_PTR(aPerformanceHintSession)
-    return static_cast<APerformanceHintSession*>(aPerformanceHintSession)
-            ->getThreadIds(threadIds, size);
+    VALIDATE_PTR(session)
+    return session->getThreadIds(threadIds, size);
 }
 
 int APerformanceHint_setPreferPowerEfficiency(APerformanceHintSession* session, bool enabled) {
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 9b1330f..6ce83cd 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -367,7 +367,7 @@
 
 void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction,
                                        ASurfaceControl* aSurfaceControl,
-                                       int8_t visibility) {
+                                       ASurfaceTransactionVisibility visibility) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
 
@@ -496,7 +496,7 @@
 
 void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction,
                                                ASurfaceControl* aSurfaceControl,
-                                               int8_t transparency) {
+                                               ASurfaceTransactionTransparency transparency) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
 
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index bfbe34e..58f56b8 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "PerformanceHintNativeTest"
 
+#include <aidl/android/hardware/power/SessionConfig.h>
+#include <aidl/android/hardware/power/SessionTag.h>
 #include <aidl/android/hardware/power/WorkDuration.h>
 #include <aidl/android/os/IHintManager.h>
 #include <android/binder_manager.h>
@@ -28,7 +30,7 @@
 #include <memory>
 #include <vector>
 
-using aidl::android::hardware::power::WorkDuration;
+namespace hal = aidl::android::hardware::power;
 using aidl::android::os::IHintManager;
 using aidl::android::os::IHintSession;
 using ndk::ScopedAStatus;
@@ -39,8 +41,9 @@
 
 class MockIHintManager : public IHintManager {
 public:
-    MOCK_METHOD(ScopedAStatus, createHintSession,
+    MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig,
                 (const SpAIBinder& token, const ::std::vector<int32_t>& tids, int64_t durationNanos,
+                 hal::SessionTag tag, std::optional<hal::SessionConfig>* config,
                  std::shared_ptr<IHintSession>* _aidl_return),
                 (override));
     MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
@@ -66,7 +69,7 @@
     MOCK_METHOD(ScopedAStatus, setMode, (int32_t mode, bool enabled), (override));
     MOCK_METHOD(ScopedAStatus, close, (), (override));
     MOCK_METHOD(ScopedAStatus, reportActualWorkDuration2,
-                (const ::std::vector<WorkDuration>& workDurations), (override));
+                (const ::std::vector<hal::WorkDuration>& workDurations), (override));
     MOCK_METHOD(SpAIBinder, asBinder, (), (override));
     MOCK_METHOD(bool, isRemote, (), (override));
 };
@@ -90,16 +93,20 @@
         return APerformanceHint_getManager();
     }
     APerformanceHintSession* createSession(APerformanceHintManager* manager,
-                                           int64_t targetDuration = 56789L) {
+                                           int64_t targetDuration = 56789L, bool isHwui = false) {
         mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
-
+        int64_t sessionId = 123;
         std::vector<int32_t> tids;
         tids.push_back(1);
         tids.push_back(2);
 
-        ON_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
-                .WillByDefault(DoAll(SetArgPointee<3>(std::shared_ptr<IHintSession>(mMockSession)),
+        ON_CALL(*mMockIHintManager,
+                createHintSessionWithConfig(_, Eq(tids), Eq(targetDuration), _, _, _))
+                .WillByDefault(DoAll(SetArgPointee<4>(std::make_optional<hal::SessionConfig>(
+                                             {.id = sessionId})),
+                                     SetArgPointee<5>(std::shared_ptr<IHintSession>(mMockSession)),
                                      [] { return ScopedAStatus::ok(); }));
+
         ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] {
             return ScopedAStatus::ok();
         });
@@ -115,7 +122,10 @@
         ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
             return ScopedAStatus::ok();
         });
-
+        if (isHwui) {
+            return APerformanceHint_createSessionInternal(manager, tids.data(), tids.size(),
+                                                          targetDuration, SessionTag::HWUI);
+        }
         return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
     }
 
@@ -123,7 +133,7 @@
     std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
 };
 
-bool equalsWithoutTimestamp(WorkDuration lhs, WorkDuration rhs) {
+bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) {
     return lhs.workPeriodStartTimestampNanos == rhs.workPeriodStartTimestampNanos &&
             lhs.cpuDurationNanos == rhs.cpuDurationNanos &&
             lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
@@ -178,6 +188,24 @@
     APerformanceHint_closeSession(session);
 }
 
+TEST_F(PerformanceHintTest, TestUpdatedSessionCreation) {
+    EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _, _)).Times(1);
+    APerformanceHintManager* manager = createManager();
+    APerformanceHintSession* session = createSession(manager);
+    ASSERT_TRUE(session);
+    APerformanceHint_closeSession(session);
+}
+
+TEST_F(PerformanceHintTest, TestHwuiSessionCreation) {
+    EXPECT_CALL(*mMockIHintManager,
+                createHintSessionWithConfig(_, _, _, hal::SessionTag::HWUI, _, _))
+            .Times(1);
+    APerformanceHintManager* manager = createManager();
+    APerformanceHintSession* session = createSession(manager, 56789L, true);
+    ASSERT_TRUE(session);
+    APerformanceHint_closeSession(session);
+}
+
 TEST_F(PerformanceHintTest, SetThreads) {
     APerformanceHintManager* manager = createManager();
 
@@ -233,8 +261,8 @@
         return false;
     }
     for (int i = 0; i < expected.size(); ++i) {
-        WorkDuration expectedWorkDuration = expected[i];
-        WorkDuration actualWorkDuration = arg[i];
+        hal::WorkDuration expectedWorkDuration = expected[i];
+        hal::WorkDuration actualWorkDuration = arg[i];
         if (!equalsWithoutTimestamp(expectedWorkDuration, actualWorkDuration)) {
             *result_listener << "WorkDuration at [" << i << "] is different: "
                              << "Expected: " << expectedWorkDuration.toString()
@@ -257,7 +285,7 @@
 
     usleep(2); // Sleep for longer than preferredUpdateRateNanos.
     struct TestPair {
-        WorkDuration duration;
+        hal::WorkDuration duration;
         int expectedResult;
     };
     std::vector<TestPair> testPairs{
@@ -266,7 +294,7 @@
             {{1, -20, 1, 13, -8}, EINVAL},
     };
     for (auto&& pair : testPairs) {
-        std::vector<WorkDuration> actualWorkDurations;
+        std::vector<hal::WorkDuration> actualWorkDurations;
         actualWorkDurations.push_back(pair.duration);
 
         EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
diff --git a/nfc/Android.bp b/nfc/Android.bp
index c186804..13ac231 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -66,6 +66,7 @@
     ],
     impl_library_visibility: [
         "//frameworks/base:__subpackages__",
+        "//cts/hostsidetests/multidevices/nfc:__subpackages__",
         "//cts/tests/tests/nfc",
         "//packages/apps/Nfc:__subpackages__",
     ],
diff --git a/nfc/TEST_MAPPING b/nfc/TEST_MAPPING
index 5b5ea37..49c778d2 100644
--- a/nfc/TEST_MAPPING
+++ b/nfc/TEST_MAPPING
@@ -5,6 +5,9 @@
     },
     {
       "name": "CtsNfcTestCases"
+    },
+    {
+      "name": "CtsNdefTestCases"
     }
   ]
 }
diff --git a/nfc/java/android/nfc/Constants.java b/nfc/java/android/nfc/Constants.java
index f768330..9b11e2d 100644
--- a/nfc/java/android/nfc/Constants.java
+++ b/nfc/java/android/nfc/Constants.java
@@ -16,6 +16,8 @@
 
 package android.nfc;
 
+import android.provider.Settings;
+
 /**
  * @hide
  * TODO(b/303286040): Holds @hide API constants. Formalize these APIs.
@@ -26,4 +28,15 @@
     public static final String SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND = "nfc_payment_foreground";
     public static final String SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
     public static final String FEATURE_NFC_ANY = "android.hardware.nfc.any";
+
+    /**
+     * @hide constant copied from {@link Settings.Global}
+     * TODO(b/274636414): Migrate to official API in Android V.
+     */
+    public static final String SETTINGS_SATELLITE_MODE_RADIOS = "satellite_mode_radios";
+    /**
+     * @hide constant copied from {@link Settings.Global}
+     * TODO(b/274636414): Migrate to official API in Android V.
+     */
+    public static final String SETTINGS_SATELLITE_MODE_ENABLED = "satellite_mode_enabled";
 }
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
index b57d548..7cd7e7ab 100644
--- a/nfc/java/android/nfc/INfcAdapter.aidl
+++ b/nfc/java/android/nfc/INfcAdapter.aidl
@@ -35,6 +35,7 @@
 import android.nfc.INfcWlcStateListener;
 import android.nfc.NfcAntennaInfo;
 import android.nfc.WlcListenerDeviceInfo;
+import android.nfc.cardemulation.PollingFrame;
 import android.os.Bundle;
 
 /**
@@ -101,7 +102,7 @@
 
     void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags);
 
-    void notifyPollingLoop(in Bundle frame);
+    void notifyPollingLoop(in PollingFrame frame);
     void notifyHceDeactivated();
     int sendVendorNciMessage(int mt, int gid, int oid, in byte[] payload);
     void registerVendorExtensionCallback(in INfcVendorNciCallback callbacks);
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index b44a71b..29867d9 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -2803,12 +2803,11 @@
     @TestApi
     @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
     public void notifyPollingLoop(@NonNull PollingFrame pollingFrame) {
-        Bundle frame = pollingFrame.toBundle();
         try {
             if (sService == null) {
                 attemptDeadServiceRecovery(null);
             }
-            sService.notifyPollingLoop(frame);
+            sService.notifyPollingLoop(pollingFrame);
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
             // Try one more time
@@ -2817,7 +2816,7 @@
                 return;
             }
             try {
-                sService.notifyPollingLoop(frame);
+                sService.notifyPollingLoop(pollingFrame);
             } catch (RemoteException ee) {
                 Log.e(TAG, "Failed to recover NFC Service.");
             }
diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
index 572e20d..a470f93 100644
--- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -410,7 +410,12 @@
                     boolean autoTransact = a.getBoolean(
                             com.android.internal.R.styleable.PollingLoopFilter_autoTransact,
                             false);
-                    mAutoTransact.put(plf, autoTransact);
+                    if (!mOnHost && !autoTransact) {
+                        Log.e(TAG, "Ignoring polling-loop-filter " + plf
+                                + " for offhost service that isn't autoTranact");
+                    } else {
+                        mAutoTransact.put(plf, autoTransact);
+                    }
                     a.recycle();
                 } else if (eventType == XmlPullParser.START_TAG
                         && "polling-loop-pattern-filter".equals(tagName) && currentGroup == null) {
@@ -422,7 +427,12 @@
                     boolean autoTransact = a.getBoolean(
                             com.android.internal.R.styleable.PollingLoopFilter_autoTransact,
                             false);
-                    mAutoTransactPatterns.put(Pattern.compile(plf), autoTransact);
+                    if (!mOnHost && !autoTransact) {
+                        Log.e(TAG, "Ignoring polling-loop-filter " + plf
+                                + " for offhost service that isn't autoTranact");
+                    } else {
+                        mAutoTransactPatterns.put(Pattern.compile(plf), autoTransact);
+                    }
                     a.recycle();
                 }
             }
@@ -729,8 +739,10 @@
     @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
     public void addPollingLoopFilter(@NonNull String pollingLoopFilter,
             boolean autoTransact) {
+        if (!mOnHost && !autoTransact) {
+            return;
+        }
         mAutoTransact.put(pollingLoopFilter, autoTransact);
-
     }
 
     /**
@@ -755,8 +767,10 @@
     @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
     public void addPollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter,
             boolean autoTransact) {
+        if (!mOnHost && !autoTransact) {
+            return;
+        }
         mAutoTransactPatterns.put(Pattern.compile(pollingLoopPatternFilter), autoTransact);
-
     }
 
     /**
diff --git a/nfc/java/android/nfc/cardemulation/HostApduService.java b/nfc/java/android/nfc/cardemulation/HostApduService.java
index 61037a2..f674b06a 100644
--- a/nfc/java/android/nfc/cardemulation/HostApduService.java
+++ b/nfc/java/android/nfc/cardemulation/HostApduService.java
@@ -325,15 +325,12 @@
                 }
                 break;
                 case MSG_POLLING_LOOP:
-                    ArrayList<Bundle> frames =
-                            msg.getData().getParcelableArrayList(KEY_POLLING_LOOP_FRAMES_BUNDLE,
-                            Bundle.class);
-                    ArrayList<PollingFrame> pollingFrames =
-                            new ArrayList<PollingFrame>(frames.size());
-                    for (Bundle frame : frames) {
-                        pollingFrames.add(new PollingFrame(frame));
+                    if (android.nfc.Flags.nfcReadPollingLoop()) {
+                        ArrayList<PollingFrame> pollingFrames =
+                                msg.getData().getParcelableArrayList(
+                                    KEY_POLLING_LOOP_FRAMES_BUNDLE, PollingFrame.class);
+                        processPollingFrames(pollingFrames);
                     }
-                    processPollingFrames(pollingFrames);
                     break;
             default:
                 super.handleMessage(msg);
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.aidl b/nfc/java/android/nfc/cardemulation/PollingFrame.aidl
new file mode 100644
index 0000000..8e09f8b
--- /dev/null
+++ b/nfc/java/android/nfc/cardemulation/PollingFrame.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.cardemulation;
+
+parcelable PollingFrame;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.java b/nfc/java/android/nfc/cardemulation/PollingFrame.java
index c6861bf..b52faba 100644
--- a/nfc/java/android/nfc/cardemulation/PollingFrame.java
+++ b/nfc/java/android/nfc/cardemulation/PollingFrame.java
@@ -101,47 +101,37 @@
     /**
      * KEY_POLLING_LOOP_TYPE is the Bundle key for the type of
      * polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-     *
-     * @hide
      */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final String KEY_POLLING_LOOP_TYPE = "android.nfc.cardemulation.TYPE";
+    private static final String KEY_POLLING_LOOP_TYPE = "android.nfc.cardemulation.TYPE";
 
     /**
      * KEY_POLLING_LOOP_DATA is the Bundle key for the raw data of captured from
      * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-     *
-     * @hide
      */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final String KEY_POLLING_LOOP_DATA = "android.nfc.cardemulation.DATA";
+    private static final String KEY_POLLING_LOOP_DATA = "android.nfc.cardemulation.DATA";
 
     /**
      * KEY_POLLING_LOOP_GAIN is the Bundle key for the field strength of
      * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-     *
-     * @hide
-     */
+    */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final String KEY_POLLING_LOOP_GAIN = "android.nfc.cardemulation.GAIN";
+    private static final String KEY_POLLING_LOOP_GAIN = "android.nfc.cardemulation.GAIN";
 
     /**
      * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for the timestamp of
      * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-     *
-     * @hide
-     */
+    */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
+    private static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
 
     /**
      * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for whether this polling frame triggered
      * autoTransact in the Bundle included in MSG_POLLING_LOOP.
-     *
-     * @hide
-     */
+    */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final String KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT =
+    private static final String KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT =
             "android.nfc.cardemulation.TRIGGERED_AUTOTRANSACT";
 
 
@@ -151,7 +141,7 @@
     private final int mGain;
     @DurationMillisLong
     private final long mTimestamp;
-    private final boolean mTriggeredAutoTransact;
+    private boolean mTriggeredAutoTransact;
 
     public static final @NonNull Parcelable.Creator<PollingFrame> CREATOR =
             new Parcelable.Creator<>() {
@@ -166,7 +156,7 @@
                 }
             };
 
-    PollingFrame(Bundle frame) {
+    private PollingFrame(Bundle frame) {
         mType = frame.getInt(KEY_POLLING_LOOP_TYPE);
         byte[] data = frame.getByteArray(KEY_POLLING_LOOP_DATA);
         mData = (data == null) ? new byte[0] : data;
@@ -239,6 +229,13 @@
     }
 
     /**
+     * @hide
+     */
+    public void setTriggeredAutoTransact(boolean triggeredAutoTransact) {
+        mTriggeredAutoTransact = triggeredAutoTransact;
+    }
+
+    /**
      * Returns whether this frame triggered the device to automatically disable observe mode and
      * allow one transaction.
      */
@@ -257,11 +254,9 @@
     }
 
     /**
-     *
-     * @hide
      * @return a Bundle representing this frame
      */
-    public Bundle toBundle() {
+    private Bundle toBundle() {
         Bundle frame = new Bundle();
         frame.putInt(KEY_POLLING_LOOP_TYPE, getType());
         if (getVendorSpecificGain() != -1) {
diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml
index e67b3be..44aa1b1 100644
--- a/packages/BackupRestoreConfirmation/AndroidManifest.xml
+++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml
@@ -26,7 +26,8 @@
                  android:allowBackup="false"
                  android:permission="android.permission.CONFIRM_FULL_BACKUP" >
 
-        <activity android:name=".BackupRestoreConfirmation" 
+        <activity android:name=".BackupRestoreConfirmation"
+                  android:theme="@style/OptOutEdgeToEdgeEnforcement"
                   android:title=""
                   android:windowSoftInputMode="stateAlwaysHidden"
                   android:excludeFromRecents="true"
diff --git a/packages/BackupRestoreConfirmation/res/values/styles.xml b/packages/BackupRestoreConfirmation/res/values/styles.xml
new file mode 100644
index 0000000..ce54568
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <!--
+        TODO(b/309578419): Make activities handle insets properly and then remove this.
+    -->
+    <style name="OptOutEdgeToEdgeEnforcement">
+        <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+    </style>
+</resources>
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 97dfba1..8fe771c 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -41,7 +41,7 @@
         android:supportsRtl="true">
 
         <activity
-            android:name=".CompanionDeviceActivity"
+            android:name=".CompanionAssociationActivity"
             android:exported="true"
             android:launchMode="singleInstance"
             android:excludeFromRecents="true"
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 183965e..d2df0e4 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -27,10 +27,10 @@
     <string name="summary_glasses" msgid="2872254734959842579">"سيتم السماح لهذا التطبيق بالوصول إلى هذه الأذونات على \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"‏هل تريد منح &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; إذنًا لبث التطبيقات المُثبَّتة على هاتفك؟"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"‏سيتمكّن \"%1$s\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على الهاتف، بما في ذلك الملفات الصوتية والصور وكلمات المرور والرسائل.&lt;br/&gt;&lt;br/&gt;سيتمكّن \"%1$s\" من بث التطبيقات إلى أنّ توقف إمكانية استخدام هذا الإذن."</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"‏سيتمكّن %1$s من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على الهاتف، بما في ذلك الملفات الصوتية والصور وكلمات المرور والرسائل.&lt;br/&gt;&lt;br/&gt;سيتمكّن %1$s من بث التطبيقات إلى أن توقف إمكانية استخدام هذا الإذن."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"يطلب تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" لبثّ محتوى التطبيقات بين أجهزتك."</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" لعرض التطبيقات وبثها بين أجهزتك"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"تطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> لعرض التطبيقات وبثها بين أجهزتك"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى هذه المعلومات من هاتفك"</string>
@@ -39,7 +39,7 @@
     <string name="helper_summary_computer" msgid="8774832742608187072">"يطلب تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" للوصول إلى الصور والوسائط والإشعارات في هاتفك."</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"‏هل تريد السماح للتطبيق &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; باتّخاذ هذا الإجراء؟"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"‏هل تريد منح &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; إذنًا لبث التطبيقات والوصول إلى ميزات النظام على هاتفك؟"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"‏سيتمكّن \"%1$s\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على هاتفك، بما في ذلك الملفات الصوتية والصور ومعلومات الدفع وكلمات المرور والرسائل.&lt;br/&gt;&lt;br/&gt;سيتمكّن \"%1$s\" من بث التطبيقات والوصول إلى ميزات النظام إلى أنّ توقف إمكانية استخدام هذا الإذن."</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"‏سيتمكّن %1$s من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على هاتفك، بما في ذلك الملفات الصوتية والصور ومعلومات الدفع وكلمات المرور والرسائل.&lt;br/&gt;&lt;br/&gt;سيتمكّن %1$s من بث التطبيقات والوصول إلى ميزات النظام إلى أن توقف إمكانية استخدام هذا الإذن."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" لبثّ التطبيقات وميزات النظام الأخرى إلى أجهزتك المجاورة."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
     <string name="summary_generic" msgid="1761976003668044801">"سيتمكّن هذا التطبيق من مزامنة المعلومات، مثل اسم المتصل، بين هاتفك والجهاز المحدّد."</string>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 4fb9ceed..2316baa 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s ще има достъп до всичко, което се показва или възпроизвежда на телефона, включително аудиосъдържание, снимки, пароли и съобщения.&lt;br/&gt;&lt;br/&gt;%1$s ще може да предава поточно приложения, докато не премахнете това разрешение."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> да показва и да предава поточно приложения между устройствата ви"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ иска разрешение от името на <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> да показва и да предава поточно приложения между устройствата ви"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"Разрешете на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до тази информация от телефона ви"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index 231d395..247d017 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -26,7 +26,7 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Aplikaciji će biti dozvoljen pristup ovim odobrenjima na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Dozvoliti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da prenosi aplikacije telefona?"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Dozvoliti uređaju &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da prenosi aplikacije telefona?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s će imati pristup svemu što je vidljivo ili se reproducira na telefonu, uključujući zvuk, fotografije, lozinke i poruke.&lt;br/&gt;&lt;br/&gt;%1$s će moći prenositi aplikacije dok ne uklonite pristup ovom odobrenju."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string>
@@ -59,7 +59,7 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Zapisnici poziva"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
-    <string name="permission_media_routing_control" msgid="5498639511586715253">"Promijeni izlaz med. sadržaja"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Promjena medijskog izlaza"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
     <string name="permission_notifications" msgid="4099418516590632909">"Obavještenja"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index 94510e3..3acd179 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -27,7 +27,7 @@
     <string name="summary_glasses" msgid="2872254734959842579">"Tato aplikace bude mít ve vašem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> povolený přístup k těmto oprávněním"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Povolit zařízení &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovat aplikace telefonu?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"Aplikace %1$s bude mít přístup ke všemu, co zobrazíte nebo přehrajete na telefonu, včetně zvuku, fotek, hesel a zpráv.&lt;br/&gt;&lt;br/&gt;%1$s bude moci streamovat aplikace, dokud přístup k tomuto oprávnění neodeberete."</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s bude mít přístup ke všemu, co na telefonu zobrazíte nebo přehrajete, včetně zvuku, fotek, hesel a zpráv.&lt;br/&gt;&lt;br/&gt;%1$s bude moci streamovat aplikace, dokud přístup k tomuto oprávnění neodeberete."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> oprávnění ke streamování aplikací mezi zařízeními"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> oprávnění k zobrazení a streamování obsahu mezi zařízeními"</string>
@@ -39,7 +39,7 @@
     <string name="helper_summary_computer" msgid="8774832742608187072">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DISPLAY_NAME">%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="7269956847378799794">"Povolit zařízení &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; podniknout tuto akci?"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Povolit zařízení &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovat aplikace a systémové funkce telefonu?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"Aplikace %1$s bude mít přístup ke všemu, co zobrazíte nebo přehrajete na telefonu, včetně zvuku, fotek, platebních údajů, hesel a zpráv.&lt;br/&gt;&lt;br/&gt;%1$s bude moci streamovat aplikace a systémové funkce, dokud přístup k tomuto oprávnění neodeberete."</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s bude mít přístup ke všemu, co na telefonu zobrazíte nebo přehrajete, včetně zvuku, fotek, platebních údajů, hesel a zpráv.&lt;br/&gt;&lt;br/&gt;%1$s bude moci streamovat aplikace a systémové funkce, dokud přístup k tomuto oprávnění neodeberete."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> žádá jménem vašeho zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o oprávnění streamovat aplikace a další systémové funkce do zařízení v okolí"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a vybraným zařízením"</string>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index 6b38bff..9d0846c 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -28,7 +28,7 @@
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Vil du give &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilladelse til at streame din telefons apps?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s har adgang til alt, der er synligt eller afspilles på telefonen, herunder lyd, billeder, adgangskoder og beskeder.&lt;br/&gt;&lt;br/&gt;%1$s kan streame apps, indtil du fjerner adgangen til denne tilladelse."</string>
-    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
+    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester til flere enheder"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> til at streame apps mellem dine enheder"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> til at vise og streame apps mellem dine enheder"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index 65e923c..3f730fc 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -26,11 +26,11 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"Gerät"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Diese App darf dann auf diese Berechtigungen auf deinem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zugreifen:"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; erlauben, die Apps auf deinem Smartphone zu streamen?"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Zulassen, dass &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; die Apps auf deinem Smartphone streamt?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s hat dann Zugriff auf alle Inhalte, die auf deinem Smartphone sichtbar sind oder abgespielt werden, einschließlich Audio, Fotos, Passwörter und Nachrichten.&lt;br/&gt;&lt;br/&gt;%1$s kann so lange Apps streamen, bis du diese Berechtigung entfernst."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung zum Anzeigen und Streamen von Apps zwischen deinen Geräten"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> um die Berechtigung, gegenseitig das Anzeigen und Streamen von Apps zu erlauben"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"&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>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-Dienste"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen deines <xliff:g id="DISPLAY_NAME">%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="7269956847378799794">"Darf das Gerät &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; diese Aktion ausführen?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; erlauben, die Apps und Systemfunktionen auf deinem Smartphone zu streamen?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s hat dann Zugriff auf alle Inhalte, die auf deinem Smartphone sichtbar sind oder abgespielt werden, einschließlich Audio, Fotos, Zahlungsinformationen, Passwörter und Nachrichten.&lt;br/&gt;&lt;br/&gt;%1$s kann so lange Apps und Systemfunktionen streamen, bis du diese Berechtigung entfernst."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Zulassen, dass &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; die Apps und Systemfunktionen auf deinem Smartphone streamt?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s hat dann Zugriff auf alle Inhalte, die auf deinem Smartphone sichtbar sind oder abgespielt werden, einschließlich Audio, Fotos, Zahlungsinformationen, Passwörter und Nachrichten.&lt;br/&gt;&lt;br/&gt;%1$s kann so lange Apps und System­funktionen streamen, bis du diese Berechtigung entfernst."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein Gerät (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) um die Berechtigung, Apps und andere Systemfunktionen auf Geräte in der Nähe zu streamen"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index c0d1888..15d97af 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -59,7 +59,7 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registros de llamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
-    <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambia la salida multimedia"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambiar la salida multimedia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string>
     <string name="permission_notifications" msgid="4099418516590632909">"Notificaciones"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index b7a9ff6..e02cb04 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -26,21 +26,21 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"seade"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Sellele rakendusele antakse need load teie seadmes <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Kas lubate rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; oma telefoni rakendusi voogesitada?"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Kas lubate seadmel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; oma telefoni rakendusi voogesitada?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s saab juurdepääsu kõigele, mis on telefonis nähtaval või esitatav, sh helile, fotodele, paroolidele ja sõnumitele.&lt;br/&gt;&lt;br/&gt;%1$s saab rakendusi voogesitada kuni eemaldate juurdepääsu sellele loale."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string>
-    <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi kuvada ja voogesitada"</string>
+    <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi kuvada ja voogesitada"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"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="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play teenused"</string>
-    <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba pääseda juurde telefoni fotodele, meediale ja märguannetele"</string>
+    <string name="helper_summary_computer" msgid="8774832742608187072">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nimel luba pääseda juurde telefoni fotodele, meediale ja märguannetele"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Kas lubada seadmel &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; teha seda toimingut?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Kas lubate rakendusel &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; oma telefoni rakenduste ja süsteemifunktsioonidel voogesitada?"</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Kas lubate seadmel &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; oma telefoni rakendusi ja süsteemifunktsioone voogesitada?"</string>
     <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s saab juurdepääsu kõigele, mis on teie telefonis nähtav või esitatav, sh heli, fotod, makseteave, paroolid ja sõnumid.&lt;br/&gt;&lt;br/&gt;%1$s saab voogesitada rakendusi ja süsteemifunktsioone, kuni eemaldate juurdepääsu sellele loale."</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba voogesitada rakendusi ja muid süsteemi funktsioone läheduses olevatesse seadmetesse"</string>
+    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba voogesitada rakendusi ja muid süsteemi funktsioone läheduses olevatesse seadmetesse"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
     <string name="summary_generic" msgid="1761976003668044801">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja valitud seadme vahel"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Luba"</string>
@@ -59,7 +59,7 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Kõnelogid"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Läheduses olevad seadmed"</string>
-    <string name="permission_media_routing_control" msgid="5498639511586715253">"Muutke meediaväljundit"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Meediaväljundi muutmine"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string>
     <string name="permission_notifications" msgid="4099418516590632909">"Märguanded"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Rakendused"</string>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index d0dee9b..ca84970 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -26,8 +26,8 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"gailua"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Baimen hauek erabili ahalko ditu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>n aplikazioak:"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari zure telefonoko aplikazioak zuzenean igortzeko baimena eman nahi diozu?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s aplikazioak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, pasahitzak eta mezuak barne.&lt;br/&gt;&lt;br/&gt;%1$s aplikazioak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; gailuari zure telefonoko aplikazioak zuzenean igortzeko baimena eman nahi diozu?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s gailuak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, pasahitzak eta mezuak barne.&lt;br/&gt;&lt;br/&gt;%1$s aplikazioak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailuarteko zerbitzuak"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Gailu batetik bestera aplikazioak igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> gailuaren izenean"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikazioak gailuen artean bistaratzeko eta zuzenean igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> gailuaren izenean"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"Telefonoko argazkiak, multimedia-edukia eta jakinarazpenak erabiltzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> gailuaren izenean"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Ekintza hau gauzatzeko baimena eman nahi diozu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari zure telefonoko aplikazioak eta sistemaren eginbideak zuzenean igortzeko baimena eman nahi diozu?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s aplikazioak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, ordainketa-informazioa, pasahitzak eta mezuak barne.&lt;br/&gt;&lt;br/&gt;%1$s aplikazioak eta sistemaren eginbideak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; gailuari zure telefonoko aplikazioak eta sistemaren eginbideak zuzenean igortzeko baimena eman nahi diozu?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s gailuak telefonoan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, ordainketa-informazioa, pasahitzak eta mezuak barne.&lt;br/&gt;&lt;br/&gt;%1$s aplikazioak eta sistemaren eginbideak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikazioak eta sistemaren beste eginbide batzuk inguruko gailuetara igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 9b55669..92d94f3 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -27,10 +27,10 @@
     <string name="summary_glasses" msgid="2872254734959842579">"यह ऐप्लिकेशन, आपके <xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर इन अनुमतियों को ऐक्सेस कर पाएगा"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को आपके फ़ोन के ऐप्लिकेशन स्ट्रीम करने की अनुमति देनी है?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चलाया गया हो. जैसे, ऑडियो, फ़ोटो, पासवर्ड, और मैसेज.&lt;br/&gt;&lt;br/&gt;%1$s तब तक ऐप्लिकेशन स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string>
-    <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चल रहा हो. जैसे, ऑडियो, फ़ोटो, पासवर्ड, और मैसेज.&lt;br/&gt;&lt;br/&gt;%1$s तब तक ऐप्लिकेशन स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string>
+    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन स्ट्रीम करने की अनुमति मांग रहा है"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन दिखाने और स्ट्रीम करने की अनुमति मांग रहा है"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, एक डिवाइस के ऐप्लिकेशन, दूसरे डिवाइस पर दिखाने और स्ट्रीम करने की अनुमति मांग रहा है"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string>
@@ -39,7 +39,7 @@
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> की ओर से, आपने फ़ोन में मौजूद फ़ोटो, मीडिया, और सूचनाओं को ऐक्सेस करने की अनुमति मांग रहा है"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"क्या &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; को यह कार्रवाई करने की अनुमति देनी है?"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; को आपके फ़ोन के ऐप्लिकेशन और सिस्टम की सुविधाएं स्ट्रीम करने की अनुमति देनी है?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चलाया गया हो. जैसे, ऑडियो, फ़ोटो, पेमेंट से जुड़ी जानकारी, पासवर्ड, और मैसेज.&lt;br/&gt;&lt;br/&gt;%1$s तब तक ऐप्लिकेशन और सिस्टम की सुविधाओं को स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s के पास ऐसे कॉन्टेंट का ऐक्सेस होगा जो फ़ोन पर दिख रहा हो या चल रहा हो. जैसे, ऑडियो, फ़ोटो, पेमेंट की जानकारी, पासवर्ड, और मैसेज.&lt;br/&gt;&lt;br/&gt;%1$s तब तक ऐप्लिकेशन और सिस्टम की सुविधाओं को स्ट्रीम करेगा, जब तक आप इस अनुमति को हटा न दें."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से, ऐप्लिकेशन और दूसरे सिस्टम की सुविधाओं को आस-पास मौजूद डिवाइसों पर स्ट्रीम करने की अनुमति मांग रहा है"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
     <string name="summary_generic" msgid="1761976003668044801">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक करेगा. जैसे, कॉल करने वाले व्यक्ति का नाम"</string>
@@ -59,7 +59,7 @@
     <string name="permission_microphone" msgid="2152206421428732949">"माइक्रोफ़ोन"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"कॉल लॉग"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"आस-पास मौजूद डिवाइस"</string>
-    <string name="permission_media_routing_control" msgid="5498639511586715253">"मीडिया आउटपुट बदलें"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"मीडिया आउटपुट में बदलाव करे"</string>
     <string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string>
     <string name="permission_notifications" msgid="4099418516590632909">"सूचनाएं"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ऐप्लिकेशन"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 1c9c218..4985ae3c 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -59,7 +59,7 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Hívásnaplók"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Közeli eszközök"</string>
-    <string name="permission_media_routing_control" msgid="5498639511586715253">"Médiakiment módosítása"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Médiakimenet módosítása"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string>
     <string name="permission_notifications" msgid="4099418516590632909">"Értesítések"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Alkalmazások"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index c4de3cd..a655a3ec 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -26,8 +26,8 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"սարք"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Այս հավելվածը կստանա հետևյալ թույլտվությունները ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ում"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին հեռարձակել ձեր հեռախոսի հավելվածները"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s հավելվածին հասանելի կլինի հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, գաղտնաբառերը և հաղորդագրությունները։&lt;br/&gt;&lt;br/&gt;%1$s հավելվածը կկարողանա հավելվածներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-ին հեռարձակել ձեր հեռախոսի հավելվածները"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s-ին հասանելի կլինի հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, գաղտնաբառերը և հաղորդագրությունները։&lt;br/&gt;&lt;br/&gt;%1$s-ը կկարողանա հավելվածներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ծառայություններ"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր հեռախոսի լուսանկարները, մեդիաֆայլերն ու ծանուցումները տեսնելու համար"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին կատարել այս գործողությունը"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; սարքին հեռարձակել ձեր հեռախոսի հավելվածները և համակարգի գործառույթները"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s սարքին հասանելի կլինի ձեր հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, վճարային տեղեկությունները, գաղտնաբառերը և հաղորդագրությունները։&lt;br/&gt;&lt;br/&gt;%1$s սարքը կկարողանա հավելվածներ և համակարգի գործառույթներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt;-ին հեռարձակել ձեր հեռախոսի հավելվածները և համակարգի գործառույթները"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s-ին հասանելի կլինի ձեր հեռախոսում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, վճարային տեղեկությունները, գաղտնաբառերը և հաղորդագրությունները։&lt;br/&gt;&lt;br/&gt;%1$s-ը կկարողանա հավելվածներ և համակարգի գործառույթներ հեռարձակել, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ մոտակա սարքերին հավելվածներ և համակարգի այլ գործառույթներ հեռարձակելու համար"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և ընտրված սարքի տվյալները, օր․՝ զանգողի անունը"</string>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index b1c4f5b..1481ca1 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -26,11 +26,11 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"perangkat"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Aplikasi ini akan diizinkan mengakses izin ini di <xliff:g id="DEVICE_NAME">%1$s</xliff:g> Anda"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan streaming aplikasi di ponsel Anda?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s akan memiliki akses ke konten apa pun yang ditampilkan atau dimainkan di ponsel, termasuk audio, foto, sandi, dan pesan.&lt;br/&gt;&lt;br/&gt;%1$s akan dapat melakukan streaming aplikasi hingga Anda menghapus izin ini."</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; menstreaming aplikasi di ponsel Anda?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s akan memiliki akses ke apa pun yang ditampilkan atau diputar di ponsel, termasuk audio, foto, sandi, dan pesan.&lt;br/&gt;&lt;br/&gt;%1$s akan dapat menstreaming aplikasi hingga Anda menghapus izin ini."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggantikan <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> meminta izin untuk menampilkan dan melakukan streaming aplikasi di antara perangkat Anda"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> untuk menampilkan dan menstreaming aplikasi di antara perangkat Anda"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses informasi ini dari ponsel Anda"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Layanan Google Play"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> untuk mengakses foto, media, dan notifikasi ponsel Anda"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Izinkan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan tindakan ini?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Izinkan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan streaming aplikasi dan mengakses fitur sistem di ponsel Anda?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s akan memiliki akses ke konten apa pun yang ditampilkan atau dimainkan di ponsel Anda, termasuk audio, foto, info pembayaran, sandi, dan pesan.&lt;br/&gt;&lt;br/&gt;%1$s akan dapat melakukan streaming aplikasi dan mengakses fitur sistem hingga Anda menghapus izin ini."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Izinkan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; menstreaming aplikasi dan fitur sistem di ponsel Anda?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s akan memiliki akses ke apa pun yang ditampilkan atau diputar di ponsel Anda, termasuk audio, foto, info pembayaran, sandi, dan pesan.&lt;br/&gt;&lt;br/&gt;%1$s akan dapat menstreaming aplikasi dan fitur sistem hingga Anda menghapus izin ini."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menstreaming aplikasi dan fitur sistem lainnya ke perangkat di sekitar"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih"</string>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index f1eb5347..ce8feb5 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"‏ל-%1$s תהיה גישה לכל מה שרואים או מפעילים בטלפון, כולל אודיו, תמונות, סיסמאות והודעות.&lt;br/&gt;&lt;br/&gt;‎‏ל-%1$s תהיה אפשרות לשדר אפליקציות עד שהגישה להרשאה הזו תוסר."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור המכשיר <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> כדי לשדר אפליקציות בין המכשירים שלך"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה למכשיר <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> כדי להציג ולשדר אפליקציות בין המכשירים שלך"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"האפליקציה \'<xliff:g id="APP_NAME">%1$s</xliff:g>\' מבקשת הרשאה למכשיר <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> כדי להציג ולשדר אפליקציות בין המכשירים שלך"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"‏מתן אישור לאפליקציה &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; לגשת למידע הזה מהטלפון שלך"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 7aace82..7dbcef0 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"ಆಡಿಯೋ, ಫೋಟೋಗಳು, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಸಂದೇಶಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ಕಂಟೆಂಟ್‌ಗೆ %1$s ಆ್ಯಕ್ಸೆಸ್ ಹೊಂದಿರುತ್ತದೆ.&lt;br/&gt;&lt;br/&gt;ನೀವು ಈ ಅನುಮತಿಗೆ ಇರುವ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ತೆಗೆದುಹಾಕುವವರೆಗೆ %1$s ಗೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಮತ್ತು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಮತ್ತು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿವೆ"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಿ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 86679ac..925f21b 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s에서 오디오, 사진, 비밀번호, 메시지 등 휴대전화에 표시되거나 휴대전화에서 재생되는 모든 항목에 액세스할 수 있습니다.&lt;br/&gt;&lt;br/&gt;이 권한에 대한 액세스를 삭제할 때까지 %1$s에서 앱을 스트리밍할 수 있습니다."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 기기 간 앱을 표시하고 스트리밍할 권한을 요청하고 있습니다."</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 연결된 기기의 앱을 표시하고 스트리밍할 권한을 요청하고 있습니다."</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;이 휴대전화에서 이 정보에 액세스하도록 허용"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 932b5c5..1b72477 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -26,8 +26,8 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"түзмөк"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Бул колдонмого <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздө төмөнкүлөрдү аткарууга уруксат берилет"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна телефонуңуздагы колдонмолорду алып ойнотууга уруксат бересизби?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s телефондо көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, сырсөздөр жана билдирүүлөргө кире алат. Бул уруксатты алып салмайынча, &lt;br/&gt;&lt;br/&gt;%1$s колдонмолорду алып ойното алат."</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна телефонуңуздагы колдонмолорду өткөрүүгө уруксат бересизби?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s телефондо көрүнгөн же ойнотулган аудиофайлдар, сүрөттөр, сырсөздөр жана билдирүүлөр сыяктуу нерселерди көрө алат. Бул уруксатты алып салмайынча, &lt;br/&gt;&lt;br/&gt;%1$s колдонмолорду өткөрө берет."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду алып ойнотууга уруксат сурап жатат"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрдүн ортосунда колдонмолорду көрсөтүү жана алып ойнотуу үчүн уруксат сурап жатат"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play кызматтары"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан телефондогу сүрөттөрдү, медиа файлдарды жана билдирмелерди колдонууга уруксат сурап жатат"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; түзмөгүнө бул аракетти аткарууга уруксат бересизби?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна телефонуңуздагы колдонмолорду жана тутумдун функцияларын алып ойнотууга уруксат бересизби?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s телефонуңузда көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, төлөм маалыматы, сырсөздөр жана билдирүүлөргө кире алат. Бул уруксатты алып салмайынча, &lt;br/&gt;&lt;br/&gt;%1$s колдонмолорду жана тутум функцияларын алып ойното алат."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна телефонуңуздагы колдонмолорду жана системалык функцияларды өткөргөнгө уруксат бересизби?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s телефонуңузда көрүнгөн же ойнотулган аудиофайлдар, сүрөттөр, төлөм маалыматы, сырсөздөр жана билдирүүлөр сыяктуу нерселерди көрө алат. Бул уруксатты алып салмайынча, &lt;br/&gt;&lt;br/&gt;%1$s колдонмолорду жана системдик функцияларды өткөрө алат."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан жакын жердеги түзмөктөрдө колдонмолорду жана системанын башка функцияларын алып ойнотууга уруксат сурап жатат"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана тандалган түзмөк менен шайкештирет"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index fe6e4cc..0c4bfcb 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -27,7 +27,7 @@
     <string name="summary_glasses" msgid="2872254734959842579">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-н эдгээр зөвшөөрөлд хандах эрхтэй байх болно"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Таны утасны аппуудыг дамжуулахыг &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-д&lt;/strong&gt; зөвшөөрөх үү?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s аудио, зураг, нууц үг болон мессежүүдийг оруулаад утсан дээр харагдсан эсвэх тоглуулсан аливаа зүйлд хандах эрхтэй болно.&lt;br/&gt;&lt;br/&gt;%1$s таныг энэ зөвшөөрлийг хасах хүртэл аппуудыг дамжуулах боломжтой байх болно."</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s аудио, зураг, нууц үг болон мессежүүдийг зэрэг утсан дээр харагдсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй болно.&lt;br/&gt;&lt;br/&gt;%1$s таныг энэ зөвшөөрлийг хасах хүртэл аппуудыг дамжуулах боломжтой байх болно."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Таны төхөөрөмжүүд хооронд апп дамжуулахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>-н өмнөөс таны төхөөрөмжүүдийн хооронд аппууд үзүүлж, дамжуулах зөвшөөрлийг хүсэж байна"</string>
@@ -39,7 +39,7 @@
     <string name="helper_summary_computer" msgid="8774832742608187072">"Таны утасны зураг, медиа болон мэдэгдэлд хандахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt;-д энэ үйлдлийг хийхийг зөвшөөрөх үү?"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Таны утасны апп болон системийн онцлогуудыг дамжуулахыг &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-д&lt;/strong&gt; зөвшөөрөх үү?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s аудио, зураг, төлбөрийн мэдээлэл, нууц үг болон мессежүүдийг оруулаад утсан дээр харагдсан эсвэх тоглуулсан аливаа зүйлд хандах эрхтэй болно.&lt;br/&gt;&lt;br/&gt;%1$s таныг энэ зөвшөөрлийг хасах хүртэл апп болон системийн онцлогуудыг дамжуулах боломжтой байх болно."</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s аудио, зураг, төлбөрийн мэдээлэл, нууц үг болон мессеж зэрэг утсан дээр харагдсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй болно.&lt;br/&gt;&lt;br/&gt;%1$s таныг энэ зөвшөөрлийг хасах хүртэл апп болон системийн онцлогуудыг дамжуулах боломжтой байх болно."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс аппууд болон системийн бусад онцлогийг ойролцоох төхөөрөмжүүд рүү дамжуулах зөвшөөрөл хүсэж байна"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index d817df2..4605c18 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -24,7 +24,7 @@
     <string name="summary_watch" msgid="7962014927042971830">"Denne appen får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og har disse tillatelsene på <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vil du la &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; administrere &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_glasses" msgid="3506504967216601277">"enheten"</string>
-    <string name="summary_glasses" msgid="2872254734959842579">"Denne appen får disse tillatelsene på <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Denne appen får disse tillatelsene på enheten din (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Vil du tillate at &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; strømmer appene på telefonen?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s får tilgang til alt som er synlig eller spilles av på telefonen, inkludert lyd, bilder, passord og meldinger.&lt;br/&gt;&lt;br/&gt;%1$s kan strømme apper til du fjerner denne tillatelsen."</string>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 8394a82..448362f 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -27,7 +27,7 @@
     <string name="summary_glasses" msgid="2872254734959842579">"ਇਸ ਐਪ ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> \'ਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"ਕੀ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।&lt;br/&gt;&lt;br/&gt;%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗੀ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।&lt;br/&gt;&lt;br/&gt;%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗਾ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਦਿਖਾਉਣ ਅਤੇ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
@@ -39,7 +39,7 @@
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"ਕੀ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਇਹ ਕਾਰਵਾਈ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"ਕੀ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।&lt;br/&gt;&lt;br/&gt;%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕੇਗੀ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।&lt;br/&gt;&lt;br/&gt;%1$s ਐਪਾਂ ਨੂੰ ਉਦੋਂ ਤੱਕ ਸਟ੍ਰੀਮ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕੇਗਾ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹਟਾ ਦਿੰਦੇ।"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ \'ਤੇ ਐਪਾਂ ਅਤੇ ਹੋਰ ਸਿਸਟਮ ਸੰਬੰਧੀ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index 945f849..7579678 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s będzie mieć dostęp do wszystkiego, co jest widoczne i odtwarzane na telefonie, w tym do dźwięku, zdjęć, haseł i wiadomości.&lt;br/&gt;&lt;br/&gt;%1$s będzie w stanie strumieniować aplikacje, dopóki nie usuniesz dostępu do tego uprawnienia."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> o pozwolenie na wyświetlanie i strumieniowanie aplikacji między Twoimi urządzeniami"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> o pozwolenie na wyświetlanie i strumieniowanie aplikacji między Twoimi urządzeniami"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"Zezwól aplikacji &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>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 289d6e0..eb7b533 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, senhas e mensagens. O app &lt;br/&gt;&lt;br/&gt;%1$s poderá fazer o streaming de apps até que você remova o acesso a essa permissão."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"Autorizar que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone"</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="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming dos apps e recursos do sistema do smartphone?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. O app &lt;br/&gt;&lt;br/&gt;%1$s poderá fazer o streaming de apps e recursos do sistema até que você remova o acesso a essa permissão."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming de apps e recursos do sistema do smartphone?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. &lt;br/&gt;&lt;br/&gt;O %1$s poderá acessar e transferir informações de apps e recursos do sistema até que você remova essa permissão."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de apps e de outros recursos do sistema para dispositivos por perto"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 9d94de7..c951334 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -26,8 +26,8 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Esta app vai poder aceder a estas autorizações no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Permitir que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça stream das apps do telemóvel?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, palavras-passe e mensagens.&lt;br/&gt;&lt;br/&gt;%1$s vai poder fazer stream de apps até remover o acesso a esta autorização."</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça stream das apps do telemóvel?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"O dispositivo %1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, palavras-passe e mensagens.&lt;br/&gt;&lt;br/&gt;O %1$s vai poder fazer stream de apps até remover o acesso a esta autorização."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para fazer stream de apps entre os seus dispositivos"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para apresentar e fazer stream de apps entre os seus dispositivos"</string>
@@ -39,7 +39,7 @@
     <string name="helper_summary_computer" msgid="8774832742608187072">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%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="7269956847378799794">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; faça esta ação?"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; faça stream das apps e das funcionalidades do sistema do telemóvel?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, informações de pagamento, palavras-passe e mensagens.&lt;br/&gt;&lt;br/&gt;%1$s vai poder fazer stream de apps e funcionalidades do sistema até remover o acesso a esta autorização."</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O dispositivo %1$s vai ter acesso a tudo o que seja visível ou reproduzido no telemóvel, incluindo áudio, fotos, informações de pagamento, palavras-passe e mensagens.&lt;br/&gt;&lt;br/&gt;O %1$s vai poder fazer stream de apps e funcionalidades do sistema até remover o acesso a esta autorizaçã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" msgid="1761976003668044801">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo escolhido"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 289d6e0..eb7b533 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -30,7 +30,7 @@
     <string name="summary_app_streaming" msgid="295548145144086753">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, senhas e mensagens. O app &lt;br/&gt;&lt;br/&gt;%1$s poderá fazer o streaming de apps até que você remova o acesso a essa permissão."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"Autorizar que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone"</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="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming dos apps e recursos do sistema do smartphone?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O app %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. O app &lt;br/&gt;&lt;br/&gt;%1$s poderá fazer o streaming de apps e recursos do sistema até que você remova o acesso a essa permissão."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Permitir que &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming de apps e recursos do sistema do smartphone?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"O %1$s terá acesso a tudo o que estiver visível ou for aberto no smartphone, incluindo áudios, fotos, informações de pagamento, senhas e mensagens. &lt;br/&gt;&lt;br/&gt;O %1$s poderá acessar e transferir informações de apps e recursos do sistema até que você remova essa permissão."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de apps e de outros recursos do sistema para dispositivos por perto"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index ce65c70..15456aa 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -26,11 +26,11 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"устройстве"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Это приложение получит указанные разрешения на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Разрешить приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; транслировать приложения с вашего телефона?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"Приложение \"%1$s\" получит доступ ко всему, что показывается или воспроизводится на телефоне, включая аудиофайлы, фотографии, пароли и сообщения.&lt;br/&gt;&lt;br/&gt;Приложение \"%1$s\" сможет транслировать приложения, пока вы не отзовете это разрешение."</string>
-    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Разрешить устройству &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; транслировать приложения с вашего телефона?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"У устройства \"%1$s\" будет доступ ко всему, что показывается или воспроизводится на телефоне, включая аудиофайлы, фотографии, пароли и сообщения.<br/>&lt;br/&gt;&lt;br/&gt;Устройство \"%1$s\" сможет транслировать приложения, пока вы не отзовете это разрешение."</string>
+    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы для нескольких устройств"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>, чтобы транслировать приложения между устройствами."</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>, чтобы транслировать приложения между устройствами."</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>\" запрашивает разрешение на трансляцию приложений между устройствами."</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"Разрешите приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; получать эту информацию с вашего телефона"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Сервисы Google Play"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>, чтобы получить доступ к фотографиям, медиаконтенту и уведомлениям на телефоне."</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Разрешить приложению &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; выполнять это действие?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Разрешить приложению &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; транслировать приложения и системные функции с вашего телефона?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"Приложение \"%1$s\" получит доступ ко всему, что показывается или воспроизводится на вашем телефоне, включая аудиофайлы, фотографии, платежные данные, пароли и сообщения.&lt;br/&gt;&lt;br/&gt;Приложение \"%1$s\" сможет транслировать приложения и системные функции, пока вы не отзовете это разрешение."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Разрешить устройству &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; транслировать приложения и системные функции с вашего телефона?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"У устройства \"%1$s\" будет доступ ко всему, что показывается или воспроизводится на вашем телефоне, включая аудиофайлы, фотографии, платежные данные, пароли и сообщения.&lt;br/&gt;&lt;br/&gt;Устройство \"%1$s\" сможет транслировать приложения и системные функции, пока вы не отзовете это разрешение."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение транслировать приложения и системные функции на устройства поблизости."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Приложение сможет синхронизировать информацию между телефоном и выбранным устройством, например данные из журнала звонков."</string>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index bbee596..c0d27f1 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -26,11 +26,11 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"zariadenie"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Táto aplikácia bude mať prístup k týmto povoleniam v zariadení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Chcete povoliť aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovať aplikácie vo svojom telefóne?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s bude mať prístup k všetkému obsahu viditeľnému alebo prehrávanému v telefóne vrátane zvuku, fotiek, hesiel a správ.&lt;br/&gt;&lt;br/&gt;%1$s bude môcť streamovať aplikácie, kým prístup k tomuto povoleniu neodstránite."</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Chcete povoliť zariadeniu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovať aplikácie telefónu?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s bude mať prístup k všetkému, čo v telefóne zobrazíte alebo prehrajete, vrátane zvuku, fotiek, hesiel a správ.&lt;br/&gt;&lt;br/&gt;%1$s bude môcť streamovať aplikácie, kým toto povolenie neodstránite."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie streamovať aplikácie medzi vašimi zariadeniami."</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie zobrazovať a streamovať aplikácie medzi zariadeniami"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje v mene zariadenia <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie zobrazovať a streamovať aplikácie medzi zariadeniami"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"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>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> povolenie na prístup k fotkám, médiám a upozorneniam vášho telefónu"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Chcete povoliť zariadeniu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; vykonať túto akciu?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Chcete povoliť aplikácii &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovať aplikácie a systémové funkcie vo svojom telefóne?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s bude mať prístup k všetkému obsahu viditeľnému alebo prehrávanému v telefóne vrátane zvuku, fotiek, platobných údajov, hesiel a správ.&lt;br/&gt;&lt;br/&gt;%1$s bude môcť streamovať aplikácie, kým prístup k tomuto povoleniu neodstránite."</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Chcete povoliť zariadeniu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovať aplikácie a systémové funkcie telefónu?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s bude mať prístup k všetkému, čo v telefóne zobrazíte alebo prehrajete, vrátane zvuku, fotiek, platobných údajov, hesiel a správ.&lt;br/&gt;&lt;br/&gt;%1$s bude môcť streamovať aplikácie a systémové funkcie, kým toto povolenie neodstránite."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie streamovať aplikácie a ďalšie systémové funkcie do zariadení v okolí"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a vybraným zariadením"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 346fbae..a895c25 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -28,7 +28,7 @@
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Ali aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovolite, da pretočno predvaja aplikacije telefona?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"Aplikacija %1$s bo imela dostop do vsega, kar je prikazano ali se predvaja v telefonu, vključno z zvokom, fotografijami, gesli in sporočili.&lt;br/&gt;&lt;br/&gt;Aplikacija %1$s bo lahko pretočno predvajala aplikacije, dokler ne odstranite dostopa do tega dovoljenja."</string>
-    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
+    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve v več napravah"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>« zahteva dovoljenje za prikaz in pretočno predvajanje aplikacij v vaših napravah."</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 76f623a..63e8cb6 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -27,20 +27,20 @@
     <string name="summary_glasses" msgid="2872254734959842579">"Këtij aplikacioni do t\'i lejohet qasja te këto leje në <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"Të lejohet që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të transmetojë aplikacionet e telefonit tënd?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose luhet në telefon, duke përfshirë audion, fotografitë, fjalëkalimet dhe mesazhet.&lt;br/&gt;&lt;br/&gt;%1$s do të mund të transmetojë aplikacionet derisa ta heqësh qasjen për këtë leje."</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose që luhet në telefon, duke përfshirë audion, fotografitë, fjalëkalimet dhe mesazhet.&lt;br/&gt;&lt;br/&gt;%1$s do të mund t\'i transmetojë aplikacionet derisa ta heqësh qasjen për këtë leje."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string>
-    <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të shfaqur dhe transmetuar aplikacionet mes pajisjeve të tua"</string>
+    <string name="helper_summary_app_streaming" msgid="2396773196949578425">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të shfaqur dhe transmetuar aplikacionet mes pajisjeve të tua"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"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="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Shërbimet e Google Play"</string>
-    <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> për të marrë qasje te fotografitë, media dhe njoftimet e telefonit tënd"</string>
+    <string name="helper_summary_computer" msgid="8774832742608187072">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të <xliff:g id="DISPLAY_NAME">%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="7269956847378799794">"Të lejohet që &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; të ndërmarrë këtë veprim?"</string>
     <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"Të lejohet që &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; të transmetojë aplikacionet dhe veçoritë e sistemit të telefonit tënd?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose luhet në telefon, duke përfshirë audion, fotografitë, informacionet për pagesën, fjalëkalimet dhe mesazhet.&lt;br/&gt;&lt;br/&gt;%1$s do të mund të transmetojë aplikacionet dhe veçoritë e sistemit derisa ta heqësh qasjen për këtë leje."</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) tënde për të transmetuar aplikacione dhe veçori të tjera të sistemit te pajisjet në afërsi"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s do të ketë qasje te çdo gjë që është e dukshme ose që luhet në telefon, duke përfshirë audion, fotografitë, informacionet për pagesën, fjalëkalimet dhe mesazhet.&lt;br/&gt;&lt;br/&gt;%1$s do të mund t\'i transmetojë aplikacionet dhe veçoritë e sistemit derisa ta heqësh qasjen për këtë leje."</string>
+    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" po kërkon leje në emër të (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) tënde për të transmetuar aplikacione dhe veçori të tjera të sistemit te pajisjet në afërsi"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emrin e dikujt që po telefonon, mes telefonit tënd dhe pajisjes së zgjedhur."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Lejo"</string>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index ede266e..2643b2d4 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -28,7 +28,7 @@
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"మీ ఫోన్ యాప్‌లను స్ట్రీమ్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ను అనుమతించాలా?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"ఆడియో, ఫోటోలు, పాస్‌వర్డ్‌లు, మెసేజ్‌లతో సహా ఫోన్‌లో కనిపించే లేదా ప్లే అయ్యే దేనికైనా %1$sకు యాక్సెస్ ఉంటుంది.&lt;br/&gt;&lt;br/&gt;మీరు ఈ అనుమతికి యాక్సెస్‌ను తీసివేసే వరకు %1$s యాప్‌లను స్ట్రీమ్ చేయగలదు."</string>
-    <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
+    <string name="helper_title_app_streaming" msgid="4151687003439969765">"క్రాస్-డివైజ్ సర్వీసులు"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"మీ పరికరాల మధ్య యాప్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"మీ పరికరాలలో యాప్‌లను డిస్‌ప్లే చేయడానికి, స్ట్రీమ్ చేయడానికి <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> తరఫున <xliff:g id="APP_NAME">%1$s</xliff:g> అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 3efc2992..5852657 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -26,7 +26,7 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"Cihaz"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"Bu uygulamanın <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızda şu izinlere erişmesine izin verilecek:"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adlı uygulamanın telefonunuzdaki uygulamaları aktarmasına izin verilsin mi?"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adlı cihazın telefonunuzdaki uygulamaları aktarmasına izin verilsin mi?"</string>
     <string name="summary_app_streaming" msgid="295548145144086753">"%1$s; ses, fotoğraflar, şifreler ve mesajlar da dahil olmak üzere telefonda görünen veya oynatılan her şeye erişebilecek.&lt;br/&gt;&lt;br/&gt;%1$s siz bu iznin erişimini kaldırana kadar uygulamaları aktarabilecek."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
@@ -38,7 +38,7 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Hizmetleri"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g>, telefonunuzdaki fotoğraf, medya ve bildirimlere erişmek için <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; cihazının bu işlemi yapmasına izin verilsin mi?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; adlı uygulamanın telefonunuzdaki uygulamaları ve sistem özelliklerini aktarmasına izin verilsin mi?"</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; adlı cihazın telefonunuzdaki uygulamaları ve sistem özelliklerini aktarmasına izin verilsin mi?"</string>
     <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s; ses, fotoğraflar, ödeme bilgileri, şifreler ve mesajlar da dahil olmak üzere telefonunuzda görünen veya oynatılan her şeye erişebilecek.&lt;br/&gt;&lt;br/&gt;%1$s siz bu iznin erişimini kaldırana kadar uygulamaları ve diğer sistem özelliklerini aktarabilecek."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması <xliff:g id="DEVICE_NAME">%2$s</xliff:g> cihazınız adına uygulamaları ve diğer sistem özelliklerini yakındaki cihazlara aktarmak için izin istiyor"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 109a011..d92a2e0 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -27,7 +27,7 @@
     <string name="summary_glasses" msgid="2872254734959842579">"اس ایپ کو آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> پر ان اجازتوں تک رسائی کی اجازت ہوگی"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"‏اجازت دیں&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اپنے فون کی ایپس کو سلسلہ بندی کرنے کے لیے؟"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"‏%1$s کو فون پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، پاس ورڈز اور پیغامات۔&lt;br/&gt;&lt;br/&gt;%1$s اس وقت تک ایپس کو اسٹریم کر سکے گید جب تک آپ اس اجازت تک رسائی کو ہٹا دیتے ہیں۔"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"‏%1$s کو فون پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، پاس ورڈز اور پیغامات۔&lt;br/&gt;&lt;br/&gt;اس وقت تک %1$s ایپس کو اسٹریم کر سکے گا جب تک آپ اس اجازت تک رسائی کو ہٹا نہیں دیتے۔"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس ڈیوائس سروسز"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
     <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"<xliff:g id="APP_NAME">%1$s</xliff:g> آپ کے <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کو ڈسپلے اور اسٹریم کرنے کے لیے اجازت کی درخواست کر رہی ہے"</string>
@@ -38,7 +38,7 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"‏Google Play سروسز"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> کی جانب سے آپ کے فون کی تصاویر، میڈیا اور اطلاعات تک رسائی کی اجازت کی درخواست کر رہی ہے"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"‏&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; کو یہ کارروائی انجام دینے کی اجازت دیں؟"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"‏اجازت دیں &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; اپنے فون کی ایپس اور سسٹم کی خصوصیات کو سلسلہ بندی کرنے کے لیے؟"</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"‏آپ کے فون کی ایپس اور سسٹم کی خصوصیات کو سلسلہ بندی کرنے کی &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; کو اجازت دیں؟"</string>
     <!-- String.format failed for translation -->
     <!-- no translation found for summary_nearby_device_streaming (4039565463149145573) -->
     <skip />
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index 750ff0d..6daf4ff 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -26,11 +26,11 @@
     <string name="profile_name_glasses" msgid="3506504967216601277">"设备"</string>
     <string name="summary_glasses" msgid="2872254734959842579">"该应用将可以获得您<xliff:g id="DEVICE_NAME">%1$s</xliff:g>上的以下权限"</string>
     <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="title_app_streaming_with_mirroring" msgid="3364582597581570658">"允许 &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 流式传输手机的应用?"</string>
-    <string name="summary_app_streaming" msgid="295548145144086753">"“%1$s”将能够访问手机上可见或播放的任何内容,包括音频、照片、密码和消息。&lt;br/&gt;&lt;br/&gt;“%1$s”将能够流式传输应用,除非您撤消此访问权限。"</string>
+    <string name="title_app_streaming_with_mirroring" msgid="3364582597581570658">"要允许 &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 流式传输手机的应用吗?"</string>
+    <string name="summary_app_streaming" msgid="295548145144086753">"%1$s 将能够访问手机上可见或播放的任何内容,包括音频、照片、密码和消息。&lt;br/&gt;&lt;br/&gt;%1$s 将能够流式传输应用,除非您撤消此访问权限。"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>请求在您的设备之间流式传输应用内容"</string>
-    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>请求在设备之间显示和流式传输应用"</string>
+    <string name="helper_summary_app_streaming_with_mirroring" msgid="6138581029144467467">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 请求在设备之间显示和流式传输应用"</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
     <string name="title_computer" msgid="4693714143506569253">"允许 &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 访问您手机中的这项信息"</string>
@@ -38,8 +38,8 @@
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服务"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>请求访问您手机上的照片、媒体内容和通知"</string>
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"允许&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt;进行此操作?"</string>
-    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"允许 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; 流式传输手机的应用和系统功能?"</string>
-    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"“%1$s”将能够访问手机上可见或播放的任何内容,包括音频、照片、付款信息、密码和消息。&lt;br/&gt;&lt;br/&gt;“%1$s”将能够流式传输应用和系统功能,除非您撤消此访问权限。"</string>
+    <string name="title_nearby_device_streaming_with_mirroring" msgid="242855799919611657">"要允许 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; 流式传输手机的应用和系统功能吗?"</string>
+    <string name="summary_nearby_device_streaming" msgid="4039565463149145573">"%1$s 将能够访问手机上可见或播放的任何内容,包括音频、照片、付款信息、密码和消息。&lt;br/&gt;&lt;br/&gt;%1$s 将能够流式传输应用和系统功能,除非您撤消此访问权限。"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_NAME">%2$s</xliff:g>请求将应用和其他系统功能流式传输到附近的设备"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
     <string name="summary_generic" msgid="1761976003668044801">"此应用将能在您的手机和所选设备之间同步信息,例如来电者的姓名"</string>
diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml
index 0af1080..e8e24f4 100644
--- a/packages/CompanionDeviceManager/res/values/styles.xml
+++ b/packages/CompanionDeviceManager/res/values/styles.xml
@@ -40,6 +40,7 @@
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:gravity">center</item>
+        <item name="android:textDirection">locale</item>
         <item name="android:layout_marginLeft">14dp</item>
         <item name="android:layout_marginRight">14dp</item>
         <item name="android:textSize">20sp</item>
@@ -53,6 +54,7 @@
         <item name="android:layout_marginTop">18dp</item>
         <item name="android:layout_marginLeft">18dp</item>
         <item name="android:layout_marginRight">18dp</item>
+        <item name="android:textDirection">locale</item>
         <item name="android:textSize">14sp</item>
         <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
new file mode 100644
index 0000000..bf81d3f
--- /dev/null
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
@@ -0,0 +1,762 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.companiondevicemanager;
+
+import static android.companion.CompanionDeviceManager.REASON_CANCELED;
+import static android.companion.CompanionDeviceManager.REASON_DISCOVERY_TIMEOUT;
+import static android.companion.CompanionDeviceManager.REASON_INTERNAL_ERROR;
+import static android.companion.CompanionDeviceManager.REASON_USER_REJECTED;
+import static android.companion.CompanionDeviceManager.RESULT_DISCOVERY_TIMEOUT;
+import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR;
+import static android.companion.CompanionDeviceManager.RESULT_USER_REJECTED;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
+import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICONS;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_NAMES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_PERMISSIONS;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_SUMMARIES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_TITLES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_PROFILES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_SELF_MANAGED_PROFILES;
+import static com.android.companiondevicemanager.Utils.getApplicationLabel;
+import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
+import static com.android.companiondevicemanager.Utils.getIcon;
+import static com.android.companiondevicemanager.Utils.getImageColor;
+import static com.android.companiondevicemanager.Utils.getVendorHeaderIcon;
+import static com.android.companiondevicemanager.Utils.getVendorHeaderName;
+import static com.android.companiondevicemanager.Utils.hasVendorIcon;
+import static com.android.companiondevicemanager.Utils.prepareResultReceiverForIpc;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.companion.AssociatedDevice;
+import android.companion.AssociationInfo;
+import android.companion.AssociationRequest;
+import android.companion.CompanionDeviceManager;
+import android.companion.IAssociationRequestCallback;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.BlendMode;
+import android.graphics.BlendModeColorFilter;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.net.MacAddress;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.text.Spanned;
+import android.util.Slog;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *  A CompanionDevice activity response for showing the available
+ *  nearby devices to be associated with.
+ */
+@SuppressLint("LongLogTag")
+public class CompanionAssociationActivity extends FragmentActivity implements
+        CompanionVendorHelperDialogFragment.CompanionVendorHelperDialogListener {
+    private static final String TAG = "CDM_CompanionDeviceActivity";
+
+    // Keep the following constants in sync with
+    // frameworks/base/services/companion/java/
+    // com/android/server/companion/AssociationRequestsProcessor.java
+
+    // AssociationRequestsProcessor <-> UI
+    private static final String EXTRA_APPLICATION_CALLBACK = "application_callback";
+    private static final String EXTRA_ASSOCIATION_REQUEST = "association_request";
+    private static final String EXTRA_RESULT_RECEIVER = "result_receiver";
+    private static final String EXTRA_FORCE_CANCEL_CONFIRMATION = "cancel_confirmation";
+
+    private static final String FRAGMENT_DIALOG_TAG = "fragment_dialog";
+
+    // AssociationRequestsProcessor -> UI
+    private static final int RESULT_CODE_ASSOCIATION_CREATED = 0;
+    private static final String EXTRA_ASSOCIATION = "association";
+
+    // UI -> AssociationRequestsProcessor
+    private static final int RESULT_CODE_ASSOCIATION_APPROVED = 0;
+    private static final String EXTRA_MAC_ADDRESS = "mac_address";
+
+    private AssociationRequest mRequest;
+    private IAssociationRequestCallback mAppCallback;
+    private ResultReceiver mCdmServiceReceiver;
+
+    // Present for application's name.
+    private CharSequence mAppLabel;
+
+    // Always present widgets.
+    private TextView mTitle;
+    private TextView mSummary;
+
+    // Present for single device and multiple device only.
+    private ImageView mProfileIcon;
+
+    // Only present for selfManaged devices.
+    private ImageView mVendorHeaderImage;
+    private TextView mVendorHeaderName;
+    private ImageButton mVendorHeaderButton;
+
+    // Progress indicator is only shown while we are looking for the first suitable device for a
+    // multiple device association.
+    private ProgressBar mMultipleDeviceSpinner;
+    // Progress indicator is only shown while we are looking for the first suitable device for a
+    // single device association.
+    private ProgressBar mSingleDeviceSpinner;
+
+    // Present for self-managed association requests and "single-device" regular association
+    // regular.
+    private Button mButtonAllow;
+    private Button mButtonNotAllow;
+    // Present for multiple devices' association requests only.
+    private Button mButtonNotAllowMultipleDevices;
+
+    // Present for top and bottom borders for permissions list and device list.
+    private View mBorderTop;
+    private View mBorderBottom;
+
+    private LinearLayout mAssociationConfirmationDialog;
+    // Contains device list, permission list and top/bottom borders.
+    private ConstraintLayout mConstraintList;
+    // Only present for self-managed association requests.
+    private RelativeLayout mVendorHeader;
+    // A linearLayout for mButtonNotAllowMultipleDevices, user will press this layout instead
+    // of the button for accessibility.
+    private LinearLayout mNotAllowMultipleDevicesLayout;
+
+    // The recycler view is only shown for multiple-device regular association request, after
+    // at least one matching device is found.
+    private @Nullable RecyclerView mDeviceListRecyclerView;
+    private @Nullable DeviceListAdapter mDeviceAdapter;
+
+    // The recycler view is shown for non-null profile association request.
+    private @Nullable RecyclerView mPermissionListRecyclerView;
+    private @Nullable PermissionListAdapter mPermissionListAdapter;
+
+    // The flag used to prevent double taps, that may lead to sending several requests for creating
+    // an association to CDM.
+    private boolean mApproved;
+    private boolean mCancelled;
+    // A reference to the device selected by the user, to be sent back to the application via
+    // onActivityResult() after the association is created.
+    private @Nullable DeviceFilterPair<?> mSelectedDevice;
+
+    private final LinearLayoutManager mPermissionsLayoutManager = new LinearLayoutManager(this);
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        boolean forceCancelDialog = getIntent().getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION,
+                false);
+        // Must handle the force cancel request in onNewIntent.
+        if (forceCancelDialog) {
+            Slog.i(TAG, "The confirmation does not exist, skipping the cancel request");
+            finish();
+        }
+
+        super.onCreate(savedInstanceState);
+        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        final Intent intent = getIntent();
+        mRequest = intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST, AssociationRequest.class);
+        mAppCallback = IAssociationRequestCallback.Stub.asInterface(
+                intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK));
+        mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER,
+                ResultReceiver.class);
+
+        requireNonNull(mRequest);
+        requireNonNull(mAppCallback);
+        requireNonNull(mCdmServiceReceiver);
+
+        // Start discovery services if needed.
+        if (!mRequest.isSelfManaged()) {
+            CompanionDeviceDiscoveryService.startForRequest(this, mRequest);
+            // TODO(b/217749191): Create the ViewModel for the LiveData
+            CompanionDeviceDiscoveryService.getDiscoveryState().observe(
+                    /* LifeCycleOwner */ this, this::onDiscoveryStateChanged);
+        }
+        // Init UI.
+        initUI();
+    }
+
+    @Override
+    protected void onNewIntent(@NonNull Intent intent) {
+        super.onNewIntent(intent);
+
+        // Force cancels the CDM dialog if this activity receives another intent with
+        // EXTRA_FORCE_CANCEL_CONFIRMATION.
+        boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false);
+        if (forCancelDialog) {
+            Slog.i(TAG, "Cancelling the user confirmation");
+            cancel(/* discoveryTimeOut */ false, /* userRejected */ false,
+                    /* internalError */ false);
+            return;
+        }
+
+        // Handle another incoming request (while we are not done with the original - mRequest -
+        // yet). We can only "process" one request at a time.
+        final IAssociationRequestCallback appCallback = IAssociationRequestCallback.Stub
+                .asInterface(intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK));
+        try {
+            requireNonNull(appCallback).onFailure("Busy.");
+        } catch (RemoteException ignore) {
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+
+        // TODO: handle config changes without cancelling.
+        if (!isDone()) {
+            cancel(/* discoveryTimeOut */ false,
+                    /* userRejected */ false, /* internalError */ false); // will finish()
+        }
+    }
+
+    private void initUI() {
+        Slog.d(TAG, "initUI(), request=" + mRequest);
+
+        final String packageName = mRequest.getPackageName();
+        final int userId = mRequest.getUserId();
+        final CharSequence appLabel;
+
+        try {
+            appLabel = getApplicationLabel(this, packageName, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.w(TAG, "Package u" + userId + "/" + packageName + " not found.");
+
+            CompanionDeviceDiscoveryService.stop(this);
+            setResultAndFinish(null, RESULT_INTERNAL_ERROR);
+            return;
+        }
+
+        setContentView(R.layout.activity_confirmation);
+
+        mAppLabel = appLabel;
+
+        mConstraintList = findViewById(R.id.constraint_list);
+        mAssociationConfirmationDialog = findViewById(R.id.association_confirmation);
+        mVendorHeader = findViewById(R.id.vendor_header);
+
+        mBorderTop = findViewById(R.id.border_top);
+        mBorderBottom = findViewById(R.id.border_bottom);
+
+        mTitle = findViewById(R.id.title);
+        mSummary = findViewById(R.id.summary);
+
+        mProfileIcon = findViewById(R.id.profile_icon);
+
+        mVendorHeaderImage = findViewById(R.id.vendor_header_image);
+        mVendorHeaderName = findViewById(R.id.vendor_header_name);
+        mVendorHeaderButton = findViewById(R.id.vendor_header_button);
+
+        mDeviceListRecyclerView = findViewById(R.id.device_list);
+
+        mMultipleDeviceSpinner = findViewById(R.id.spinner_multiple_device);
+        mSingleDeviceSpinner = findViewById(R.id.spinner_single_device);
+
+        mPermissionListRecyclerView = findViewById(R.id.permission_list);
+        mPermissionListAdapter = new PermissionListAdapter(this);
+
+        mButtonAllow = findViewById(R.id.btn_positive);
+        mButtonNotAllow = findViewById(R.id.btn_negative);
+        mButtonNotAllowMultipleDevices = findViewById(R.id.btn_negative_multiple_devices);
+        mNotAllowMultipleDevicesLayout = findViewById(R.id.negative_multiple_devices_layout);
+
+        mButtonAllow.setOnClickListener(this::onPositiveButtonClick);
+        mButtonNotAllow.setOnClickListener(this::onNegativeButtonClick);
+        mNotAllowMultipleDevicesLayout.setOnClickListener(this::onNegativeButtonClick);
+
+        mVendorHeaderButton.setOnClickListener(this::onShowHelperDialog);
+
+        if (mRequest.isSelfManaged()) {
+            initUiForSelfManagedAssociation();
+        } else if (mRequest.isSingleDevice()) {
+            initUiForSingleDevice();
+        } else {
+            initUiForMultipleDevices();
+        }
+    }
+
+    private void onDiscoveryStateChanged(DiscoveryState newState) {
+        if (newState == FINISHED_TIMEOUT
+                && CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) {
+            cancel(/* discoveryTimeOut */ true,
+                    /* userRejected */ false, /* internalError */ false);
+        }
+    }
+
+    private void onUserSelectedDevice(@NonNull DeviceFilterPair<?> selectedDevice) {
+        final MacAddress macAddress = selectedDevice.getMacAddress();
+        mRequest.setDisplayName(selectedDevice.getDisplayName());
+        mRequest.setAssociatedDevice(new AssociatedDevice(selectedDevice.getDevice()));
+        onAssociationApproved(macAddress);
+    }
+
+    private void onAssociationApproved(@Nullable MacAddress macAddress) {
+        if (isDone()) {
+            Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled"));
+            return;
+        }
+        mApproved = true;
+
+        Slog.i(TAG, "onAssociationApproved() macAddress=" + macAddress);
+
+        if (!mRequest.isSelfManaged()) {
+            requireNonNull(macAddress);
+            CompanionDeviceDiscoveryService.stop(this);
+        }
+
+        final Bundle data = new Bundle();
+        data.putParcelable(EXTRA_ASSOCIATION_REQUEST, mRequest);
+        data.putBinder(EXTRA_APPLICATION_CALLBACK, mAppCallback.asBinder());
+        if (macAddress != null) {
+            data.putParcelable(EXTRA_MAC_ADDRESS, macAddress);
+        }
+
+        data.putParcelable(EXTRA_RESULT_RECEIVER,
+                prepareResultReceiverForIpc(mOnAssociationCreatedReceiver));
+
+        mCdmServiceReceiver.send(RESULT_CODE_ASSOCIATION_APPROVED, data);
+    }
+
+    private void cancel(boolean discoveryTimeout, boolean userRejected, boolean internalError) {
+        if (isDone()) {
+            Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled"));
+            return;
+        }
+        mCancelled = true;
+
+        // Stop discovery service if it was used.
+        if (!mRequest.isSelfManaged() || discoveryTimeout) {
+            CompanionDeviceDiscoveryService.stop(this);
+        }
+
+        final String cancelReason;
+        final int resultCode;
+        if (userRejected) {
+            cancelReason = REASON_USER_REJECTED;
+            resultCode = RESULT_USER_REJECTED;
+        } else if (discoveryTimeout) {
+            cancelReason = REASON_DISCOVERY_TIMEOUT;
+            resultCode = RESULT_DISCOVERY_TIMEOUT;
+        } else if (internalError) {
+            cancelReason = REASON_INTERNAL_ERROR;
+            resultCode = RESULT_INTERNAL_ERROR;
+        } else {
+            cancelReason = REASON_CANCELED;
+            resultCode = CompanionDeviceManager.RESULT_CANCELED;
+        }
+
+        // First send callback to the app directly...
+        try {
+            Slog.i(TAG, "Sending onFailure to app due to reason=" + cancelReason);
+            mAppCallback.onFailure(cancelReason);
+        } catch (RemoteException ignore) {
+        }
+
+        // ... then set result and finish ("sending" onActivityResult()).
+        setResultAndFinish(null, resultCode);
+    }
+
+    private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) {
+        Slog.i(TAG, "setResultAndFinish(), association="
+                + (association == null ? "null" : association)
+                + "resultCode=" + resultCode);
+
+        final Intent data = new Intent();
+        if (association != null) {
+            data.putExtra(CompanionDeviceManager.EXTRA_ASSOCIATION, association);
+            if (!association.isSelfManaged()) {
+                data.putExtra(CompanionDeviceManager.EXTRA_DEVICE, mSelectedDevice.getDevice());
+            }
+        }
+        setResult(resultCode, data);
+
+        finish();
+    }
+
+    private void initUiForSelfManagedAssociation() {
+        Slog.d(TAG, "initUiForSelfManagedAssociation()");
+
+        final CharSequence deviceName = mRequest.getDisplayName();
+        final String deviceProfile = mRequest.getDeviceProfile();
+        final String packageName = mRequest.getPackageName();
+        final int userId = mRequest.getUserId();
+        final Drawable vendorIcon;
+        final CharSequence vendorName;
+        final Spanned title;
+
+        if (!SUPPORTED_SELF_MANAGED_PROFILES.contains(deviceProfile)) {
+            throw new RuntimeException("Unsupported profile " + deviceProfile);
+        }
+
+        try {
+            vendorIcon = getVendorHeaderIcon(this, packageName, userId);
+            vendorName = getVendorHeaderName(this, packageName, userId);
+            mVendorHeaderImage.setImageDrawable(vendorIcon);
+            if (hasVendorIcon(this, packageName, userId)) {
+                int color = getImageColor(this);
+                mVendorHeaderImage.setColorFilter(getResources().getColor(color, /* Theme= */null));
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.e(TAG, "Package u" + userId + "/" + packageName + " not found.");
+            cancel(/* discoveryTimeout */ false,
+                    /* userRejected */ false, /* internalError */ true);
+            return;
+        }
+
+        title = getHtmlFromResources(this, PROFILE_TITLES.get(deviceProfile), deviceName);
+
+        if (PROFILE_SUMMARIES.containsKey(deviceProfile)) {
+            final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile);
+            final Spanned summary = getHtmlFromResources(this, summaryResourceId,
+                    deviceName);
+            mSummary.setText(summary);
+        } else {
+            mSummary.setVisibility(View.GONE);
+        }
+
+        setupPermissionList(deviceProfile);
+
+        mTitle.setText(title);
+        mVendorHeaderName.setText(vendorName);
+        mVendorHeader.setVisibility(View.VISIBLE);
+        mProfileIcon.setVisibility(View.GONE);
+        mDeviceListRecyclerView.setVisibility(View.GONE);
+        // Top and bottom borders should be gone for selfManaged dialog.
+        mBorderTop.setVisibility(View.GONE);
+        mBorderBottom.setVisibility(View.GONE);
+    }
+
+    private void initUiForSingleDevice() {
+        Slog.d(TAG, "initUiForSingleDevice()");
+
+        final String deviceProfile = mRequest.getDeviceProfile();
+
+        if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
+            throw new RuntimeException("Unsupported profile " + deviceProfile);
+        }
+
+        final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile));
+        mProfileIcon.setImageDrawable(profileIcon);
+
+        CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> {
+            if (deviceFilterPairs.isEmpty()) {
+                return;
+            }
+            mSelectedDevice = requireNonNull(deviceFilterPairs.get(0));
+            updateSingleDeviceUi();
+        });
+
+        mSingleDeviceSpinner.setVisibility(View.VISIBLE);
+        // Hide permission list and confirmation dialog first before the
+        // first matched device is found.
+        mPermissionListRecyclerView.setVisibility(View.GONE);
+        mDeviceListRecyclerView.setVisibility(View.GONE);
+        mAssociationConfirmationDialog.setVisibility(View.GONE);
+    }
+
+    private void initUiForMultipleDevices() {
+        Slog.d(TAG, "initUiForMultipleDevices()");
+
+        final Drawable profileIcon;
+        final Spanned title;
+        final String deviceProfile = mRequest.getDeviceProfile();
+
+        if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
+            throw new RuntimeException("Unsupported profile " + deviceProfile);
+        }
+
+        profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile));
+
+        if (deviceProfile == null) {
+            title = getHtmlFromResources(this, R.string.chooser_title_non_profile, mAppLabel);
+            mButtonNotAllowMultipleDevices.setText(R.string.consent_no);
+        } else {
+            title = getHtmlFromResources(this,
+                    R.string.chooser_title, getString(PROFILE_NAMES.get(deviceProfile)));
+        }
+
+        mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked);
+
+        mTitle.setText(title);
+        mProfileIcon.setImageDrawable(profileIcon);
+
+        mDeviceListRecyclerView.setAdapter(mDeviceAdapter);
+        mDeviceListRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+
+        CompanionDeviceDiscoveryService.getScanResult().observe(this,
+                deviceFilterPairs -> {
+                    // Dismiss the progress bar once there's one device found for multiple devices.
+                    if (deviceFilterPairs.size() >= 1) {
+                        mMultipleDeviceSpinner.setVisibility(View.GONE);
+                    }
+
+                    mDeviceAdapter.setDevices(deviceFilterPairs);
+                });
+
+        mSummary.setVisibility(View.GONE);
+        // "Remove" consent button: users would need to click on the list item.
+        mButtonAllow.setVisibility(View.GONE);
+        mButtonNotAllow.setVisibility(View.GONE);
+        mDeviceListRecyclerView.setVisibility(View.VISIBLE);
+        mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE);
+        mNotAllowMultipleDevicesLayout.setVisibility(View.VISIBLE);
+        mConstraintList.setVisibility(View.VISIBLE);
+        mMultipleDeviceSpinner.setVisibility(View.VISIBLE);
+    }
+
+    private void onDeviceClicked(int position) {
+        final DeviceFilterPair<?> selectedDevice = mDeviceAdapter.getItem(position);
+        // To prevent double tap on the selected device.
+        if (mSelectedDevice != null) {
+            Slog.w(TAG, "Already selected.");
+            return;
+        }
+        // Notify the adapter to highlight the selected item.
+        mDeviceAdapter.setSelectedPosition(position);
+
+        mSelectedDevice = requireNonNull(selectedDevice);
+
+        Slog.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString());
+
+        updateSingleDeviceUi();
+
+        mSummary.setVisibility(View.VISIBLE);
+        mButtonAllow.setVisibility(View.VISIBLE);
+        mButtonNotAllow.setVisibility(View.VISIBLE);
+        mDeviceListRecyclerView.setVisibility(View.GONE);
+        mNotAllowMultipleDevicesLayout.setVisibility(View.GONE);
+    }
+
+    private void updateSingleDeviceUi() {
+        // No need to show permission consent dialog if it is a isSkipPrompt(true)
+        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
+        if (mRequest.isSkipPrompt()) {
+            Slog.d(TAG, "Skipping the permission consent dialog.");
+            onUserSelectedDevice(mSelectedDevice);
+            return;
+        }
+
+        mSingleDeviceSpinner.setVisibility(View.GONE);
+        mAssociationConfirmationDialog.setVisibility(View.VISIBLE);
+
+        final String deviceProfile = mRequest.getDeviceProfile();
+        final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile);
+        final String remoteDeviceName = mSelectedDevice.getDisplayName();
+        final Spanned title = getHtmlFromResources(
+                this, PROFILE_TITLES.get(deviceProfile), mAppLabel, remoteDeviceName);
+        final Spanned summary;
+
+        if (deviceProfile == null && mRequest.isSingleDevice()) {
+            summary = getHtmlFromResources(this, summaryResourceId, remoteDeviceName);
+            mConstraintList.setVisibility(View.GONE);
+        } else if (deviceProfile == null) {
+            onUserSelectedDevice(mSelectedDevice);
+            return;
+        } else {
+            summary = getHtmlFromResources(
+                    this, summaryResourceId, getString(R.string.device_type));
+            setupPermissionList(deviceProfile);
+        }
+
+        mTitle.setText(title);
+        mSummary.setText(summary);
+    }
+
+    private void onPositiveButtonClick(View v) {
+        Slog.d(TAG, "onPositiveButtonClick()");
+
+        // Disable the button, to prevent more clicks.
+        v.setEnabled(false);
+
+        if (mRequest.isSelfManaged()) {
+            onAssociationApproved(null);
+        } else {
+            onUserSelectedDevice(mSelectedDevice);
+        }
+    }
+
+    private void onNegativeButtonClick(View v) {
+        Slog.d(TAG, "onNegativeButtonClick()");
+
+        // Disable the button, to prevent more clicks.
+        v.setEnabled(false);
+
+        cancel(/* discoveryTimeout */ false, /* userRejected */ true, /* internalError */ false);
+    }
+
+    private void onShowHelperDialog(View view) {
+        FragmentManager fragmentManager = getSupportFragmentManager();
+        CompanionVendorHelperDialogFragment fragmentDialog =
+                CompanionVendorHelperDialogFragment.newInstance(mRequest);
+
+        mAssociationConfirmationDialog.setVisibility(View.INVISIBLE);
+
+        fragmentDialog.show(fragmentManager, /* Tag */ FRAGMENT_DIALOG_TAG);
+    }
+
+    private boolean isDone() {
+        return mApproved || mCancelled;
+    }
+
+    // Set up the mPermissionListRecyclerView, including set up the adapter,
+    // initiate the layoutManager for the recyclerview, add listeners for monitoring the scrolling
+    // and when mPermissionListRecyclerView is fully populated.
+    // Lastly, disable the Allow and Don't allow buttons.
+    private void setupPermissionList(String deviceProfile) {
+        final List<Integer> permissionTypes = new ArrayList<>(
+                PROFILE_PERMISSIONS.get(deviceProfile));
+        if (permissionTypes.isEmpty()) {
+            // Nothing to do if there are no permission types.
+            return;
+        }
+
+        mPermissionListAdapter.setPermissionType(permissionTypes);
+        mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
+        mPermissionListRecyclerView.setLayoutManager(mPermissionsLayoutManager);
+
+        disableButtons();
+
+        LinearLayoutManager permissionListLayoutManager =
+                (LinearLayoutManager) mPermissionListRecyclerView
+                        .getLayoutManager();
+
+        // Enable buttons once users scroll down to the bottom of the permission list.
+        mPermissionListRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+                enableAllowButtonIfNeeded(permissionListLayoutManager);
+            }
+        });
+        // Enable buttons if last item in the permission list is visible to the users when
+        // mPermissionListRecyclerView is fully populated.
+        mPermissionListRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        enableAllowButtonIfNeeded(permissionListLayoutManager);
+                        mPermissionListRecyclerView.getViewTreeObserver()
+                                .removeOnGlobalLayoutListener(this);
+                    }
+                });
+
+        // Set accessibility for the recyclerView that to be able scroll up/down for voice access.
+        mPermissionListRecyclerView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN);
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
+            }
+        });
+
+        mConstraintList.setVisibility(View.VISIBLE);
+        mPermissionListRecyclerView.setVisibility(View.VISIBLE);
+    }
+
+    // Enable the Allow button if the last element in the PermissionListRecyclerView is reached.
+    private void enableAllowButtonIfNeeded(LinearLayoutManager layoutManager) {
+        int lastVisibleItemPosition =
+                layoutManager.findLastCompletelyVisibleItemPosition();
+        int numItems = mPermissionListRecyclerView.getAdapter().getItemCount();
+
+        if (lastVisibleItemPosition >= numItems - 1) {
+            enableButtons();
+        }
+    }
+
+    // Disable and grey out the Allow and Don't allow buttons if the last permission in the
+    // permission list is not visible to the users.
+    private void disableButtons() {
+        mButtonAllow.setEnabled(false);
+        mButtonNotAllow.setEnabled(false);
+        mButtonAllow.setTextColor(
+                getResources().getColor(android.R.color.system_neutral1_400, null));
+        mButtonNotAllow.setTextColor(
+                getResources().getColor(android.R.color.system_neutral1_400, null));
+        mButtonAllow.getBackground().setColorFilter(
+                (new BlendModeColorFilter(Color.LTGRAY,  BlendMode.DARKEN)));
+        mButtonNotAllow.getBackground().setColorFilter(
+                (new BlendModeColorFilter(Color.LTGRAY,  BlendMode.DARKEN)));
+    }
+    // Enable and restore the color for the Allow and Don't allow buttons if the last permission in
+    // the permission list is visible to the users.
+    private void enableButtons() {
+        mButtonAllow.setEnabled(true);
+        mButtonNotAllow.setEnabled(true);
+        mButtonAllow.getBackground().setColorFilter(null);
+        mButtonNotAllow.getBackground().setColorFilter(null);
+        mButtonAllow.setTextColor(
+                getResources().getColor(android.R.color.system_neutral1_900, null));
+        mButtonNotAllow.setTextColor(
+                getResources().getColor(android.R.color.system_neutral1_900, null));
+    }
+
+    private final ResultReceiver mOnAssociationCreatedReceiver =
+            new ResultReceiver(Handler.getMain()) {
+                @Override
+                protected void onReceiveResult(int resultCode, Bundle data) {
+                    if (resultCode == RESULT_CODE_ASSOCIATION_CREATED) {
+                        final AssociationInfo association = data.getParcelable(
+                                EXTRA_ASSOCIATION, AssociationInfo.class);
+                        requireNonNull(association);
+                        setResultAndFinish(association, CompanionDeviceManager.RESULT_OK);
+                    } else {
+                        setResultAndFinish(null, resultCode);
+                    }
+                }
+            };
+
+    @Override
+    public void onShowHelperDialogFailed() {
+        cancel(/* discoveryTimeout */ false, /* userRejected */ false, /* internalError */ true);
+    }
+
+    @Override
+    public void onHelperDialogDismissed() {
+        mAssociationConfirmationDialog.setVisibility(View.VISIBLE);
+    }
+}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
deleted file mode 100644
index 1231b63..0000000
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.companiondevicemanager;
-
-import static android.companion.CompanionDeviceManager.REASON_CANCELED;
-import static android.companion.CompanionDeviceManager.REASON_DISCOVERY_TIMEOUT;
-import static android.companion.CompanionDeviceManager.REASON_INTERNAL_ERROR;
-import static android.companion.CompanionDeviceManager.REASON_USER_REJECTED;
-import static android.companion.CompanionDeviceManager.RESULT_DISCOVERY_TIMEOUT;
-import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR;
-import static android.companion.CompanionDeviceManager.RESULT_USER_REJECTED;
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
-import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
-import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICONS;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_NAMES;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_PERMISSIONS;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_SUMMARIES;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_TITLES;
-import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_PROFILES;
-import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_SELF_MANAGED_PROFILES;
-import static com.android.companiondevicemanager.Utils.getApplicationLabel;
-import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
-import static com.android.companiondevicemanager.Utils.getIcon;
-import static com.android.companiondevicemanager.Utils.getImageColor;
-import static com.android.companiondevicemanager.Utils.getVendorHeaderIcon;
-import static com.android.companiondevicemanager.Utils.getVendorHeaderName;
-import static com.android.companiondevicemanager.Utils.hasVendorIcon;
-import static com.android.companiondevicemanager.Utils.prepareResultReceiverForIpc;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.companion.AssociatedDevice;
-import android.companion.AssociationInfo;
-import android.companion.AssociationRequest;
-import android.companion.CompanionDeviceManager;
-import android.companion.IAssociationRequestCallback;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.BlendMode;
-import android.graphics.BlendModeColorFilter;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.net.MacAddress;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.text.Spanned;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import androidx.constraintlayout.widget.ConstraintLayout;
-import androidx.fragment.app.FragmentActivity;
-import androidx.fragment.app.FragmentManager;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- *  A CompanionDevice activity response for showing the available
- *  nearby devices to be associated with.
- */
-@SuppressLint("LongLogTag")
-public class CompanionDeviceActivity extends FragmentActivity implements
-        CompanionVendorHelperDialogFragment.CompanionVendorHelperDialogListener {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "CDM_CompanionDeviceActivity";
-
-    // Keep the following constants in sync with
-    // frameworks/base/services/companion/java/
-    // com/android/server/companion/AssociationRequestsProcessor.java
-
-    // AssociationRequestsProcessor <-> UI
-    private static final String EXTRA_APPLICATION_CALLBACK = "application_callback";
-    private static final String EXTRA_ASSOCIATION_REQUEST = "association_request";
-    private static final String EXTRA_RESULT_RECEIVER = "result_receiver";
-    private static final String EXTRA_FORCE_CANCEL_CONFIRMATION = "cancel_confirmation";
-
-    private static final String FRAGMENT_DIALOG_TAG = "fragment_dialog";
-
-    // AssociationRequestsProcessor -> UI
-    private static final int RESULT_CODE_ASSOCIATION_CREATED = 0;
-    private static final String EXTRA_ASSOCIATION = "association";
-
-    // UI -> AssociationRequestsProcessor
-    private static final int RESULT_CODE_ASSOCIATION_APPROVED = 0;
-    private static final String EXTRA_MAC_ADDRESS = "mac_address";
-
-    private AssociationRequest mRequest;
-    private IAssociationRequestCallback mAppCallback;
-    private ResultReceiver mCdmServiceReceiver;
-
-    // Present for application's name.
-    private CharSequence mAppLabel;
-
-    // Always present widgets.
-    private TextView mTitle;
-    private TextView mSummary;
-
-    // Present for single device and multiple device only.
-    private ImageView mProfileIcon;
-
-    // Only present for selfManaged devices.
-    private ImageView mVendorHeaderImage;
-    private TextView mVendorHeaderName;
-    private ImageButton mVendorHeaderButton;
-
-    // Progress indicator is only shown while we are looking for the first suitable device for a
-    // multiple device association.
-    private ProgressBar mMultipleDeviceSpinner;
-    // Progress indicator is only shown while we are looking for the first suitable device for a
-    // single device association.
-    private ProgressBar mSingleDeviceSpinner;
-
-    // Present for self-managed association requests and "single-device" regular association
-    // regular.
-    private Button mButtonAllow;
-    private Button mButtonNotAllow;
-    // Present for multiple devices' association requests only.
-    private Button mButtonNotAllowMultipleDevices;
-
-    // Present for top and bottom borders for permissions list and device list.
-    private View mBorderTop;
-    private View mBorderBottom;
-
-    private LinearLayout mAssociationConfirmationDialog;
-    // Contains device list, permission list and top/bottom borders.
-    private ConstraintLayout mConstraintList;
-    // Only present for self-managed association requests.
-    private RelativeLayout mVendorHeader;
-    // A linearLayout for mButtonNotAllowMultipleDevices, user will press this layout instead
-    // of the button for accessibility.
-    private LinearLayout mNotAllowMultipleDevicesLayout;
-
-    // The recycler view is only shown for multiple-device regular association request, after
-    // at least one matching device is found.
-    private @Nullable RecyclerView mDeviceListRecyclerView;
-    private @Nullable DeviceListAdapter mDeviceAdapter;
-
-    // The recycler view is shown for non-null profile association request.
-    private @Nullable RecyclerView mPermissionListRecyclerView;
-    private @Nullable PermissionListAdapter mPermissionListAdapter;
-
-    // The flag used to prevent double taps, that may lead to sending several requests for creating
-    // an association to CDM.
-    private boolean mApproved;
-    private boolean mCancelled;
-    // A reference to the device selected by the user, to be sent back to the application via
-    // onActivityResult() after the association is created.
-    private @Nullable DeviceFilterPair<?> mSelectedDevice;
-
-    private final LinearLayoutManager mPermissionsLayoutManager = new LinearLayoutManager(this);
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        if (DEBUG) Log.d(TAG, "onCreate()");
-        boolean forceCancelDialog = getIntent().getBooleanExtra("cancel_confirmation", false);
-        // Must handle the force cancel request in onNewIntent.
-        if (forceCancelDialog) {
-            Log.i(TAG, "The confirmation does not exist, skipping the cancel request");
-            finish();
-        }
-
-        super.onCreate(savedInstanceState);
-        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        if (DEBUG) Log.d(TAG, "onStart()");
-
-        final Intent intent = getIntent();
-        mRequest = intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST);
-        mAppCallback = IAssociationRequestCallback.Stub.asInterface(
-                intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK));
-        mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER);
-
-        requireNonNull(mRequest);
-        requireNonNull(mAppCallback);
-        requireNonNull(mCdmServiceReceiver);
-
-        // Start discovery services if needed.
-        if (!mRequest.isSelfManaged()) {
-            CompanionDeviceDiscoveryService.startForRequest(this, mRequest);
-            // TODO(b/217749191): Create the ViewModel for the LiveData
-            CompanionDeviceDiscoveryService.getDiscoveryState().observe(
-                    /* LifeCycleOwner */ this, this::onDiscoveryStateChanged);
-        }
-        // Init UI.
-        initUI();
-    }
-
-    @SuppressWarnings("MissingSuperCall") // TODO: Fix me
-    @Override
-    protected void onNewIntent(Intent intent) {
-        // Force cancels the CDM dialog if this activity receives another intent with
-        // EXTRA_FORCE_CANCEL_CONFIRMATION.
-        boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false);
-
-        if (forCancelDialog) {
-            Log.i(TAG, "Cancelling the user confirmation");
-
-            cancel(/* discoveryTimeOut */ false,
-                    /* userRejected */ false, /* internalError */ false);
-            return;
-        }
-
-        // Handle another incoming request (while we are not done with the original - mRequest -
-        // yet).
-        final AssociationRequest request = requireNonNull(
-                intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST));
-
-        if (DEBUG) Log.d(TAG, "onNewIntent(), request=" + request);
-
-        // We can only "process" one request at a time.
-        final IAssociationRequestCallback appCallback = IAssociationRequestCallback.Stub
-                .asInterface(intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK));
-        try {
-            requireNonNull(appCallback).onFailure("Busy.");
-        } catch (RemoteException ignore) {
-        }
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        if (DEBUG) Log.d(TAG, "onStop(), finishing=" + isFinishing());
-
-        // TODO: handle config changes without cancelling.
-        if (!isDone()) {
-            cancel(/* discoveryTimeOut */ false,
-                    /* userRejected */ false, /* internalError */ false); // will finish()
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        if (DEBUG) Log.d(TAG, "onDestroy()");
-    }
-
-    @Override
-    public void onBackPressed() {
-        if (DEBUG) Log.d(TAG, "onBackPressed()");
-        super.onBackPressed();
-    }
-
-    @Override
-    public void finish() {
-        if (DEBUG) Log.d(TAG, "finish()", new Exception("Stack Trace Dump"));
-        super.finish();
-    }
-
-    private void initUI() {
-        if (DEBUG) Log.d(TAG, "initUI(), request=" + mRequest);
-
-        final String packageName = mRequest.getPackageName();
-        final int userId = mRequest.getUserId();
-        final CharSequence appLabel;
-
-        try {
-            appLabel = getApplicationLabel(this, packageName, userId);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Package u" + userId + "/" + packageName + " not found.");
-
-            CompanionDeviceDiscoveryService.stop(this);
-            setResultAndFinish(null, RESULT_INTERNAL_ERROR);
-            return;
-        }
-
-        setContentView(R.layout.activity_confirmation);
-
-        mAppLabel = appLabel;
-
-        mConstraintList = findViewById(R.id.constraint_list);
-        mAssociationConfirmationDialog = findViewById(R.id.association_confirmation);
-        mVendorHeader = findViewById(R.id.vendor_header);
-
-        mBorderTop = findViewById(R.id.border_top);
-        mBorderBottom = findViewById(R.id.border_bottom);
-
-        mTitle = findViewById(R.id.title);
-        mSummary = findViewById(R.id.summary);
-
-        mProfileIcon = findViewById(R.id.profile_icon);
-
-        mVendorHeaderImage = findViewById(R.id.vendor_header_image);
-        mVendorHeaderName = findViewById(R.id.vendor_header_name);
-        mVendorHeaderButton = findViewById(R.id.vendor_header_button);
-
-        mDeviceListRecyclerView = findViewById(R.id.device_list);
-
-        mMultipleDeviceSpinner = findViewById(R.id.spinner_multiple_device);
-        mSingleDeviceSpinner = findViewById(R.id.spinner_single_device);
-
-        mPermissionListRecyclerView = findViewById(R.id.permission_list);
-        mPermissionListAdapter = new PermissionListAdapter(this);
-
-        mButtonAllow = findViewById(R.id.btn_positive);
-        mButtonNotAllow = findViewById(R.id.btn_negative);
-        mButtonNotAllowMultipleDevices = findViewById(R.id.btn_negative_multiple_devices);
-        mNotAllowMultipleDevicesLayout = findViewById(R.id.negative_multiple_devices_layout);
-
-        mButtonAllow.setOnClickListener(this::onPositiveButtonClick);
-        mButtonNotAllow.setOnClickListener(this::onNegativeButtonClick);
-        mNotAllowMultipleDevicesLayout.setOnClickListener(this::onNegativeButtonClick);
-
-        mVendorHeaderButton.setOnClickListener(this::onShowHelperDialog);
-
-        if (mRequest.isSelfManaged()) {
-            initUiForSelfManagedAssociation();
-        } else if (mRequest.isSingleDevice()) {
-            initUiForSingleDevice(appLabel);
-        } else {
-            initUiForMultipleDevices(appLabel);
-        }
-    }
-
-    private void onDiscoveryStateChanged(DiscoveryState newState) {
-        if (newState == FINISHED_TIMEOUT
-                && CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) {
-            cancel(/* discoveryTimeOut */ true,
-                    /* userRejected */ false, /* internalError */ false);
-        }
-    }
-
-    private void onUserSelectedDevice(@NonNull DeviceFilterPair<?> selectedDevice) {
-        final MacAddress macAddress = selectedDevice.getMacAddress();
-        mRequest.setDisplayName(selectedDevice.getDisplayName());
-        mRequest.setAssociatedDevice(new AssociatedDevice(selectedDevice.getDevice()));
-        onAssociationApproved(macAddress);
-    }
-
-    private void onAssociationApproved(@Nullable MacAddress macAddress) {
-        if (isDone()) {
-            if (DEBUG) Log.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled"));
-            return;
-        }
-        mApproved = true;
-
-        if (DEBUG) Log.i(TAG, "onAssociationApproved() macAddress=" + macAddress);
-
-        if (!mRequest.isSelfManaged()) {
-            requireNonNull(macAddress);
-            CompanionDeviceDiscoveryService.stop(this);
-        }
-
-        final Bundle data = new Bundle();
-        data.putParcelable(EXTRA_ASSOCIATION_REQUEST, mRequest);
-        data.putBinder(EXTRA_APPLICATION_CALLBACK, mAppCallback.asBinder());
-        if (macAddress != null) {
-            data.putParcelable(EXTRA_MAC_ADDRESS, macAddress);
-        }
-
-        data.putParcelable(EXTRA_RESULT_RECEIVER,
-                prepareResultReceiverForIpc(mOnAssociationCreatedReceiver));
-
-        mCdmServiceReceiver.send(RESULT_CODE_ASSOCIATION_APPROVED, data);
-    }
-
-    private void cancel(boolean discoveryTimeout, boolean userRejected, boolean internalError) {
-        if (DEBUG) {
-            Log.i(TAG, "cancel(), discoveryTimeout="
-                    + discoveryTimeout
-                    + ", userRejected="
-                    + userRejected
-                    + ", internalError="
-                    + internalError, new Exception("Stack Trace Dump"));
-        }
-
-        if (isDone()) {
-            if (DEBUG) Log.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled"));
-            return;
-        }
-        mCancelled = true;
-
-        // Stop discovery service if it was used.
-        if (!mRequest.isSelfManaged() || discoveryTimeout) {
-            CompanionDeviceDiscoveryService.stop(this);
-        }
-
-        final String cancelReason;
-        final int resultCode;
-        if (userRejected) {
-            cancelReason = REASON_USER_REJECTED;
-            resultCode = RESULT_USER_REJECTED;
-        } else if (discoveryTimeout) {
-            cancelReason = REASON_DISCOVERY_TIMEOUT;
-            resultCode = RESULT_DISCOVERY_TIMEOUT;
-        } else if (internalError) {
-            cancelReason = REASON_INTERNAL_ERROR;
-            resultCode = RESULT_INTERNAL_ERROR;
-        } else {
-            cancelReason = REASON_CANCELED;
-            resultCode = CompanionDeviceManager.RESULT_CANCELED;
-        }
-
-        // First send callback to the app directly...
-        try {
-            mAppCallback.onFailure(cancelReason);
-        } catch (RemoteException ignore) {
-        }
-
-        // ... then set result and finish ("sending" onActivityResult()).
-        setResultAndFinish(null, resultCode);
-    }
-
-    private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) {
-        Log.i(TAG, "setResultAndFinish(), association="
-                + (association == null ? "null" : association)
-                + "resultCode=" + resultCode);
-
-        final Intent data = new Intent();
-        if (association != null) {
-            data.putExtra(CompanionDeviceManager.EXTRA_ASSOCIATION, association);
-            if (!association.isSelfManaged()) {
-                data.putExtra(CompanionDeviceManager.EXTRA_DEVICE, mSelectedDevice.getDevice());
-            }
-        }
-        setResult(resultCode, data);
-
-        finish();
-    }
-
-    private void initUiForSelfManagedAssociation() {
-        if (DEBUG) Log.i(TAG, "initUiFor_SelfManaged_Association()");
-
-        final CharSequence deviceName = mRequest.getDisplayName();
-        final String deviceProfile = mRequest.getDeviceProfile();
-        final String packageName = mRequest.getPackageName();
-        final int userId = mRequest.getUserId();
-        final Drawable vendorIcon;
-        final CharSequence vendorName;
-        final Spanned title;
-
-        if (!SUPPORTED_SELF_MANAGED_PROFILES.contains(deviceProfile)) {
-            throw new RuntimeException("Unsupported profile " + deviceProfile);
-        }
-
-        try {
-            vendorIcon = getVendorHeaderIcon(this, packageName, userId);
-            vendorName = getVendorHeaderName(this, packageName, userId);
-            mVendorHeaderImage.setImageDrawable(vendorIcon);
-            if (hasVendorIcon(this, packageName, userId)) {
-                int color = getImageColor(this);
-                mVendorHeaderImage.setColorFilter(getResources().getColor(color, /* Theme= */null));
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Package u" + userId + "/" + packageName + " not found.");
-            cancel(/* discoveryTimeout */ false,
-                    /* userRejected */ false, /* internalError */ true);
-            return;
-        }
-
-        title = getHtmlFromResources(this, PROFILE_TITLES.get(deviceProfile), deviceName);
-
-        if (PROFILE_SUMMARIES.containsKey(deviceProfile)) {
-            final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile);
-            final Spanned summary = getHtmlFromResources(this, summaryResourceId,
-                    deviceName);
-            mSummary.setText(summary);
-        } else {
-            mSummary.setVisibility(View.GONE);
-        }
-
-        setupPermissionList(deviceProfile);
-
-        mTitle.setText(title);
-        mVendorHeaderName.setText(vendorName);
-        mVendorHeader.setVisibility(View.VISIBLE);
-        mProfileIcon.setVisibility(View.GONE);
-        mDeviceListRecyclerView.setVisibility(View.GONE);
-        // Top and bottom borders should be gone for selfManaged dialog.
-        mBorderTop.setVisibility(View.GONE);
-        mBorderBottom.setVisibility(View.GONE);
-    }
-
-    private void initUiForSingleDevice(CharSequence appLabel) {
-        if (DEBUG) Log.i(TAG, "initUiFor_SingleDevice()");
-
-        final String deviceProfile = mRequest.getDeviceProfile();
-
-        if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
-            throw new RuntimeException("Unsupported profile " + deviceProfile);
-        }
-
-        CompanionDeviceDiscoveryService.getScanResult().observe(this,
-                deviceFilterPairs -> updateSingleDeviceUi(
-                        deviceFilterPairs, deviceProfile, appLabel));
-
-        mSingleDeviceSpinner.setVisibility(View.VISIBLE);
-        // Hide permission list and confirmation dialog first before the
-        // first matched device is found.
-        mPermissionListRecyclerView.setVisibility(View.GONE);
-        mDeviceListRecyclerView.setVisibility(View.GONE);
-        mAssociationConfirmationDialog.setVisibility(View.GONE);
-    }
-
-    private void updateSingleDeviceUi(List<DeviceFilterPair<?>> deviceFilterPairs,
-            String deviceProfile, CharSequence appLabel) {
-        // Ignore "empty" scan reports.
-        if (deviceFilterPairs.isEmpty()) return;
-
-        mSelectedDevice = requireNonNull(deviceFilterPairs.get(0));
-
-        final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile));
-
-        // No need to show permission consent dialog if it is a isSkipPrompt(true)
-        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
-        if (mRequest.isSkipPrompt()) {
-            Log.d(TAG, "Skipping the permission consent dialog.");
-            mSingleDeviceSpinner.setVisibility(View.GONE);
-            onUserSelectedDevice(mSelectedDevice);
-            return;
-        }
-
-        updatePermissionUi();
-
-        mProfileIcon.setImageDrawable(profileIcon);
-        mAssociationConfirmationDialog.setVisibility(View.VISIBLE);
-        mSingleDeviceSpinner.setVisibility(View.GONE);
-    }
-
-    private void initUiForMultipleDevices(CharSequence appLabel) {
-        if (DEBUG) Log.i(TAG, "initUiFor_MultipleDevices()");
-
-        final Drawable profileIcon;
-        final Spanned title;
-        final String deviceProfile = mRequest.getDeviceProfile();
-
-        if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
-            throw new RuntimeException("Unsupported profile " + deviceProfile);
-        }
-
-        profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile));
-
-        if (deviceProfile == null) {
-            title = getHtmlFromResources(this, R.string.chooser_title_non_profile, appLabel);
-            mButtonNotAllowMultipleDevices.setText(R.string.consent_no);
-        } else {
-            title = getHtmlFromResources(this,
-                    R.string.chooser_title, getString(PROFILE_NAMES.get(deviceProfile)));
-        }
-
-        mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked);
-
-        mTitle.setText(title);
-        mProfileIcon.setImageDrawable(profileIcon);
-
-        mDeviceListRecyclerView.setAdapter(mDeviceAdapter);
-        mDeviceListRecyclerView.setLayoutManager(new LinearLayoutManager(this));
-
-        CompanionDeviceDiscoveryService.getScanResult().observe(this,
-                deviceFilterPairs -> {
-                    // Dismiss the progress bar once there's one device found for multiple devices.
-                    if (deviceFilterPairs.size() >= 1) {
-                        mMultipleDeviceSpinner.setVisibility(View.GONE);
-                    }
-
-                    mDeviceAdapter.setDevices(deviceFilterPairs);
-                });
-
-        mSummary.setVisibility(View.GONE);
-        // "Remove" consent button: users would need to click on the list item.
-        mButtonAllow.setVisibility(View.GONE);
-        mButtonNotAllow.setVisibility(View.GONE);
-        mDeviceListRecyclerView.setVisibility(View.VISIBLE);
-        mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE);
-        mNotAllowMultipleDevicesLayout.setVisibility(View.VISIBLE);
-        mConstraintList.setVisibility(View.VISIBLE);
-        mMultipleDeviceSpinner.setVisibility(View.VISIBLE);
-    }
-
-    private void onDeviceClicked(int position) {
-        final DeviceFilterPair<?> selectedDevice = mDeviceAdapter.getItem(position);
-        // To prevent double tap on the selected device.
-        if (mSelectedDevice != null) {
-            if (DEBUG) Log.w(TAG, "Already selected.");
-            return;
-        }
-        // Notify the adapter to highlight the selected item.
-        mDeviceAdapter.setSelectedPosition(position);
-
-        mSelectedDevice = requireNonNull(selectedDevice);
-
-        Log.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString());
-
-        // No need to show permission consent dialog if it is a isSkipPrompt(true)
-        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
-        if (mRequest.isSkipPrompt()) {
-            Log.d(TAG, "Skipping the permission consent dialog.");
-            onUserSelectedDevice(mSelectedDevice);
-            return;
-        }
-
-        updatePermissionUi();
-
-        mSummary.setVisibility(View.VISIBLE);
-        mButtonAllow.setVisibility(View.VISIBLE);
-        mButtonNotAllow.setVisibility(View.VISIBLE);
-        mDeviceListRecyclerView.setVisibility(View.GONE);
-        mNotAllowMultipleDevicesLayout.setVisibility(View.GONE);
-    }
-
-    private void updatePermissionUi() {
-        final String deviceProfile = mRequest.getDeviceProfile();
-        final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile);
-        final String remoteDeviceName = mSelectedDevice.getDisplayName();
-        final Spanned title = getHtmlFromResources(
-                this, PROFILE_TITLES.get(deviceProfile), mAppLabel, remoteDeviceName);
-        final Spanned summary;
-
-        if (deviceProfile == null && mRequest.isSingleDevice()) {
-            summary = getHtmlFromResources(this, summaryResourceId, remoteDeviceName);
-            mConstraintList.setVisibility(View.GONE);
-        } else if (deviceProfile == null) {
-            onUserSelectedDevice(mSelectedDevice);
-            return;
-        } else {
-            summary = getHtmlFromResources(
-                    this, summaryResourceId, getString(R.string.device_type));
-            setupPermissionList(deviceProfile);
-        }
-
-        mTitle.setText(title);
-        mSummary.setText(summary);
-    }
-
-    private void onPositiveButtonClick(View v) {
-        if (DEBUG) Log.d(TAG, "on_Positive_ButtonClick()");
-
-        // Disable the button, to prevent more clicks.
-        v.setEnabled(false);
-
-        if (mRequest.isSelfManaged()) {
-            onAssociationApproved(null);
-        } else {
-            onUserSelectedDevice(mSelectedDevice);
-        }
-    }
-
-    private void onNegativeButtonClick(View v) {
-        if (DEBUG) Log.d(TAG, "on_Negative_ButtonClick()");
-
-        // Disable the button, to prevent more clicks.
-        v.setEnabled(false);
-
-        cancel(/* discoveryTimeout */ false, /* userRejected */ true, /* internalError */ false);
-    }
-
-    private void onShowHelperDialog(View view) {
-        FragmentManager fragmentManager = getSupportFragmentManager();
-        CompanionVendorHelperDialogFragment fragmentDialog =
-                CompanionVendorHelperDialogFragment.newInstance(mRequest);
-
-        mAssociationConfirmationDialog.setVisibility(View.INVISIBLE);
-
-        fragmentDialog.show(fragmentManager, /* Tag */ FRAGMENT_DIALOG_TAG);
-    }
-
-    private boolean isDone() {
-        return mApproved || mCancelled;
-    }
-
-    // Set up the mPermissionListRecyclerView, including set up the adapter,
-    // initiate the layoutManager for the recyclerview, add listeners for monitoring the scrolling
-    // and when mPermissionListRecyclerView is fully populated.
-    // Lastly, disable the Allow and Don't allow buttons.
-    private void setupPermissionList(String deviceProfile) {
-        final List<Integer> permissionTypes = new ArrayList<>(
-                PROFILE_PERMISSIONS.get(deviceProfile));
-        if (permissionTypes.isEmpty()) {
-            // Nothing to do if there are no permission types.
-            return;
-        }
-
-        mPermissionListAdapter.setPermissionType(permissionTypes);
-        mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
-        mPermissionListRecyclerView.setLayoutManager(mPermissionsLayoutManager);
-
-        disableButtons();
-
-        LinearLayoutManager permissionListLayoutManager =
-                (LinearLayoutManager) mPermissionListRecyclerView
-                        .getLayoutManager();
-
-        // Enable buttons once users scroll down to the bottom of the permission list.
-        mPermissionListRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
-            @Override
-            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
-                enableAllowButtonIfNeeded(permissionListLayoutManager);
-            }
-        });
-        // Enable buttons if last item in the permission list is visible to the users when
-        // mPermissionListRecyclerView is fully populated.
-        mPermissionListRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
-                new ViewTreeObserver.OnGlobalLayoutListener() {
-                    @Override
-                    public void onGlobalLayout() {
-                        enableAllowButtonIfNeeded(permissionListLayoutManager);
-                        mPermissionListRecyclerView.getViewTreeObserver()
-                                .removeOnGlobalLayoutListener(this);
-                    }
-                });
-
-        // Set accessibility for the recyclerView that to be able scroll up/down for voice access.
-        mPermissionListRecyclerView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
-            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
-                super.onInitializeAccessibilityNodeInfo(host, info);
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN);
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
-            }
-        });
-
-        mConstraintList.setVisibility(View.VISIBLE);
-        mPermissionListRecyclerView.setVisibility(View.VISIBLE);
-    }
-
-    // Enable the Allow button if the last element in the PermissionListRecyclerView is reached.
-    private void enableAllowButtonIfNeeded(LinearLayoutManager layoutManager) {
-        int lastVisibleItemPosition =
-                layoutManager.findLastCompletelyVisibleItemPosition();
-        int numItems = mPermissionListRecyclerView.getAdapter().getItemCount();
-
-        if (lastVisibleItemPosition >= numItems - 1) {
-            enableButtons();
-        }
-    }
-
-    // Disable and grey out the Allow and Don't allow buttons if the last permission in the
-    // permission list is not visible to the users.
-    private void disableButtons() {
-        mButtonAllow.setEnabled(false);
-        mButtonNotAllow.setEnabled(false);
-        mButtonAllow.setTextColor(
-                getResources().getColor(android.R.color.system_neutral1_400, null));
-        mButtonNotAllow.setTextColor(
-                getResources().getColor(android.R.color.system_neutral1_400, null));
-        mButtonAllow.getBackground().setColorFilter(
-                (new BlendModeColorFilter(Color.LTGRAY,  BlendMode.DARKEN)));
-        mButtonNotAllow.getBackground().setColorFilter(
-                (new BlendModeColorFilter(Color.LTGRAY,  BlendMode.DARKEN)));
-    }
-    // Enable and restore the color for the Allow and Don't allow buttons if the last permission in
-    // the permission list is visible to the users.
-    private void enableButtons() {
-        mButtonAllow.setEnabled(true);
-        mButtonNotAllow.setEnabled(true);
-        mButtonAllow.getBackground().setColorFilter(null);
-        mButtonNotAllow.getBackground().setColorFilter(null);
-        mButtonAllow.setTextColor(
-                getResources().getColor(android.R.color.system_neutral1_900, null));
-        mButtonNotAllow.setTextColor(
-                getResources().getColor(android.R.color.system_neutral1_900, null));
-    }
-
-    private final ResultReceiver mOnAssociationCreatedReceiver =
-            new ResultReceiver(Handler.getMain()) {
-                @Override
-                protected void onReceiveResult(int resultCode, Bundle data) {
-                    if (resultCode == RESULT_CODE_ASSOCIATION_CREATED) {
-                        final AssociationInfo association = data.getParcelable(
-                                EXTRA_ASSOCIATION, AssociationInfo.class);
-                        requireNonNull(association);
-                        setResultAndFinish(association, CompanionDeviceManager.RESULT_OK);
-                    } else {
-                        setResultAndFinish(null, resultCode);
-                    }
-                }
-            };
-
-    @Override
-    public void onShowHelperDialogFailed() {
-        cancel(/* discoveryTimeout */ false, /* userRejected */ false, /* internalError */ true);
-    }
-
-    @Override
-    public void onHelperDialogDismissed() {
-        mAssociationConfirmationDialog.setVisibility(View.VISIBLE);
-    }
-}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 65bbb6fc..a5bb34f 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -55,7 +55,7 @@
 import android.os.Parcelable;
 import android.os.SystemProperties;
 import android.text.TextUtils;
-import android.util.Log;
+import android.util.Slog;
 
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
@@ -71,7 +71,6 @@
  */
 @SuppressLint("LongLogTag")
 public class CompanionDeviceDiscoveryService extends Service {
-    private static final boolean DEBUG = false;
     private static final String TAG = "CDM_CompanionDeviceDiscoveryService";
 
     private static final String SYS_PROP_DEBUG_TIMEOUT = "debug.cdm.discovery_timeout";
@@ -147,7 +146,6 @@
     @Override
     public void onCreate() {
         super.onCreate();
-        if (DEBUG) Log.d(TAG, "onCreate()");
 
         mBtManager = getSystemService(BluetoothManager.class);
         mBtAdapter = mBtManager.getAdapter();
@@ -158,7 +156,6 @@
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         final String action = intent.getAction();
-        if (DEBUG) Log.d(TAG, "onStartCommand() action=" + action);
 
         switch (action) {
             case ACTION_START_DISCOVERY:
@@ -174,15 +171,9 @@
         return START_NOT_STICKY;
     }
 
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        if (DEBUG) Log.d(TAG, "onDestroy()");
-    }
-
     @MainThread
     private void startDiscovery(@NonNull AssociationRequest request) {
-        if (DEBUG) Log.i(TAG, "startDiscovery() request=" + request);
+        Slog.d(TAG, "startDiscovery() request=" + request);
         requireNonNull(request);
 
         if (mDiscoveryStarted) throw new RuntimeException("Discovery in progress.");
@@ -197,7 +188,12 @@
                 filter(allFilters, BluetoothLeDeviceFilter.class);
         final List<WifiDeviceFilter> wifiFilters = filter(allFilters, WifiDeviceFilter.class);
 
-        checkBoundDevicesIfNeeded(request, btFilters);
+        // No need to startDiscovery if the device is already bound or connected for
+        // singleDevice dialog.
+        if (checkBoundDevicesIfNeeded(request, btFilters)) {
+            stopSelf();
+            return;
+        }
 
         // If no filters are specified: look for everything.
         final boolean forceStartScanningAll = isEmpty(allFilters);
@@ -213,7 +209,7 @@
 
     @MainThread
     private void stopDiscoveryAndFinish(boolean timeout) {
-        if (DEBUG) Log.i(TAG, "stopDiscovery()");
+        Slog.d(TAG, "stopDiscoveryAndFinish(" + timeout + ")");
 
         if (!mDiscoveryStarted) {
             stopSelf();
@@ -257,42 +253,45 @@
         stopSelf();
     }
 
-    private void checkBoundDevicesIfNeeded(@NonNull AssociationRequest request,
+    private boolean checkBoundDevicesIfNeeded(@NonNull AssociationRequest request,
             @NonNull List<BluetoothDeviceFilter> btFilters) {
         // If filtering to get single device by mac address, also search in the set of already
         // bonded devices to allow linking those directly
-        if (btFilters.isEmpty() || !request.isSingleDevice()) return;
+        if (btFilters.isEmpty() || !request.isSingleDevice()) return false;
 
         final BluetoothDeviceFilter singleMacAddressFilter =
                 find(btFilters, filter -> !TextUtils.isEmpty(filter.getAddress()));
 
-        if (singleMacAddressFilter == null) return;
+        if (singleMacAddressFilter == null) return false;
 
-        findAndReportMatches(mBtAdapter.getBondedDevices(), btFilters);
-        findAndReportMatches(mBtManager.getConnectedDevices(BluetoothProfile.GATT), btFilters);
-        findAndReportMatches(
-                mBtManager.getConnectedDevices(BluetoothProfile.GATT_SERVER), btFilters);
+        return findAndReportMatches(mBtAdapter.getBondedDevices(), btFilters)
+                || findAndReportMatches(mBtManager.getConnectedDevices(
+                        BluetoothProfile.GATT), btFilters)
+                || findAndReportMatches(mBtManager.getConnectedDevices(
+                        BluetoothProfile.GATT_SERVER), btFilters);
     }
 
-    private void findAndReportMatches(@Nullable Collection<BluetoothDevice> devices,
+    private boolean findAndReportMatches(@Nullable Collection<BluetoothDevice> devices,
             @NonNull List<BluetoothDeviceFilter> filters) {
-        if (devices == null) return;
+        if (devices == null) return false;
 
         for (BluetoothDevice device : devices) {
             final DeviceFilterPair<BluetoothDevice> match = findMatch(device, filters);
             if (match != null) {
                 onDeviceFound(match);
+                return true;
             }
         }
+
+        return false;
     }
 
     private BluetoothBroadcastReceiver startBtScanningIfNeeded(
             List<BluetoothDeviceFilter> filters, boolean force) {
         if (isEmpty(filters) && !force) return null;
-        if (DEBUG) Log.d(TAG, "registerReceiver(BluetoothDevice.ACTION_FOUND)");
+        Slog.d(TAG, "registerReceiver(BluetoothDevice.ACTION_FOUND)");
 
         final BluetoothBroadcastReceiver receiver = new BluetoothBroadcastReceiver(filters);
-
         final IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
         registerReceiver(receiver, intentFilter);
 
@@ -304,7 +303,7 @@
     private WifiBroadcastReceiver startWifiScanningIfNeeded(
             List<WifiDeviceFilter> filters, boolean force) {
         if (isEmpty(filters) && !force) return null;
-        if (DEBUG) Log.d(TAG, "registerReceiver(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)");
+        Slog.d(TAG, "registerReceiver(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)");
 
         final WifiBroadcastReceiver receiver = new WifiBroadcastReceiver(filters);
 
@@ -320,10 +319,10 @@
     private ScanCallback startBleScanningIfNeeded(
             List<BluetoothLeDeviceFilter> filters, boolean force) {
         if (isEmpty(filters) && !force) return null;
-        if (DEBUG) Log.d(TAG, "BLEScanner.startScan");
+        Slog.d(TAG, "BLEScanner.startScan");
 
         if (mBleScanner == null) {
-            Log.w(TAG, "BLE Scanner is not available.");
+            Slog.w(TAG, "BLE Scanner is not available.");
             return null;
         }
 
@@ -341,18 +340,13 @@
 
     private void onDeviceFound(@NonNull DeviceFilterPair<?> device) {
         runOnMainThread(() -> {
-            if (DEBUG) Log.v(TAG, "onDeviceFound() " + device);
             if (mDiscoveryStopped) return;
             if (mDevicesFound.contains(device)) {
                 // TODO: update the device instead of ignoring (new found device may contain
                 //  additional/updated info, eg. name of the device).
-                if (DEBUG) {
-                    Log.d(TAG, "onDeviceFound() " + device.toShortString()
-                            + " - Already seen: ignore.");
-                }
                 return;
             }
-            Log.i(TAG, "onDeviceFound() " + device.toShortString() + " - New device.");
+            Slog.i(TAG, "onDeviceFound() " + device.toShortString() + " - New device.");
 
             // First: make change.
             mDevicesFound.add(device);
@@ -367,7 +361,7 @@
 
     private void onDeviceLost(@NonNull DeviceFilterPair<?> device) {
         runOnMainThread(() -> {
-            Log.i(TAG, "onDeviceLost(), device=" + device.toShortString());
+            Slog.i(TAG, "onDeviceLost(), device=" + device.toShortString());
 
             // First: make change.
             mDevicesFound.remove(device);
@@ -386,13 +380,10 @@
             timeout = max(timeout, TIMEOUT_MIN); // should be >= 1 sec (TIMEOUT_MIN)
         }
 
-        if (DEBUG) Log.d(TAG, "scheduleTimeout(), timeout=" + timeout);
-
         Handler.getMain().postDelayed(mTimeoutRunnable, timeout);
     }
 
     private void timeout() {
-        if (DEBUG) Log.i(TAG, "timeout()");
         stopDiscoveryAndFinish(/* timeout */ true);
     }
 
@@ -410,10 +401,6 @@
 
         @Override
         public void onScanResult(int callbackType, ScanResult result) {
-            if (DEBUG) {
-                Log.v(TAG, "BLE.onScanResult() callback=" + callbackType + ", result=" + result);
-            }
-
             final DeviceFilterPair<ScanResult> match = findMatch(result, mFilters);
             if (match == null) return;
 
@@ -438,8 +425,6 @@
             final String action = intent.getAction();
             final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 
-            if (DEBUG) Log.v(TAG, action + ", device=" + device);
-
             if (action == null) return;
 
             final DeviceFilterPair<BluetoothDevice> match = findMatch(device, mFilters);
@@ -468,10 +453,6 @@
             }
 
             final List<android.net.wifi.ScanResult> scanResults = mWifiManager.getScanResults();
-            if (DEBUG) {
-                Log.v(TAG, "WifiManager.SCAN_RESULTS_AVAILABLE_ACTION, results:\n  "
-                        + TextUtils.join("\n  ", scanResults));
-            }
 
             for (int i = 0; i < scanResults.size(); i++) {
                 final android.net.wifi.ScanResult scanResult = scanResults.get(i);
@@ -496,9 +477,7 @@
 
         DeviceFilterPair<T> result = matchingFilter != null
                 ? new DeviceFilterPair<>(dev, matchingFilter) : null;
-        if (DEBUG) {
-            Log.v(TAG, "findMatch(dev=" + dev + ", filters=" + filters + ") -> " + result);
-        }
+
         return result;
     }
 }
diff --git a/packages/CrashRecovery/aconfig/flags.aconfig b/packages/CrashRecovery/aconfig/flags.aconfig
index 35d7393..8cdef38 100644
--- a/packages/CrashRecovery/aconfig/flags.aconfig
+++ b/packages/CrashRecovery/aconfig/flags.aconfig
@@ -3,7 +3,7 @@
 
 flag {
     name: "recoverability_detection"
-    namespace: "package_watchdog"
+    namespace: "package_manager_service"
     description: "Feature flag for recoverability detection"
     bug: "310236690"
     is_fixed_read_only: true
@@ -16,3 +16,11 @@
     description: "Enables various dependencies of crashrecovery module"
     bug: "289203818"
 }
+
+flag {
+    name: "allow_rescue_party_flag_resets"
+    namespace: "crashrecovery"
+    description: "Enables rescue party flag resets"
+    bug: "287618292"
+    is_fixed_read_only: true
+}
diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
deleted file mode 100644
index a8d8f9a..0000000
--- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
+++ /dev/null
@@ -1,1985 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static android.service.watchdog.ExplicitHealthCheckService.PackageConfig;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.annotation.IntDef;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.VersionedPackage;
-import android.crashrecovery.flags.Flags;
-import android.net.ConnectivityModuleConnector;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Process;
-import android.os.SystemProperties;
-import android.provider.DeviceConfig;
-import android.sysprop.CrashRecoveryProperties;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.AtomicFile;
-import android.util.Slog;
-import android.util.Xml;
-import android.utils.BackgroundThread;
-import android.utils.LongArrayQueue;
-import android.utils.XmlUtils;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.modules.utils.TypedXmlPullParser;
-import com.android.modules.utils.TypedXmlSerializer;
-
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Monitors the health of packages on the system and notifies interested observers when packages
- * fail. On failure, the registered observer with the least user impacting mitigation will
- * be notified.
- */
-public class PackageWatchdog {
-    private static final String TAG = "PackageWatchdog";
-
-    static final String PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS =
-            "watchdog_trigger_failure_duration_millis";
-    static final String PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT =
-            "watchdog_trigger_failure_count";
-    static final String PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED =
-            "watchdog_explicit_health_check_enabled";
-
-    // TODO: make the following values configurable via DeviceConfig
-    private static final long NATIVE_CRASH_POLLING_INTERVAL_MILLIS =
-            TimeUnit.SECONDS.toMillis(30);
-    private static final long NUMBER_OF_NATIVE_CRASH_POLLS = 10;
-
-
-    public static final int FAILURE_REASON_UNKNOWN = 0;
-    public static final int FAILURE_REASON_NATIVE_CRASH = 1;
-    public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
-    public static final int FAILURE_REASON_APP_CRASH = 3;
-    public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
-    public static final int FAILURE_REASON_BOOT_LOOP = 5;
-
-    @IntDef(prefix = { "FAILURE_REASON_" }, value = {
-            FAILURE_REASON_UNKNOWN,
-            FAILURE_REASON_NATIVE_CRASH,
-            FAILURE_REASON_EXPLICIT_HEALTH_CHECK,
-            FAILURE_REASON_APP_CRASH,
-            FAILURE_REASON_APP_NOT_RESPONDING,
-            FAILURE_REASON_BOOT_LOOP
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface FailureReasons {}
-
-    // Duration to count package failures before it resets to 0
-    @VisibleForTesting
-    static final int DEFAULT_TRIGGER_FAILURE_DURATION_MS =
-            (int) TimeUnit.MINUTES.toMillis(1);
-    // Number of package failures within the duration above before we notify observers
-    @VisibleForTesting
-    static final int DEFAULT_TRIGGER_FAILURE_COUNT = 5;
-    @VisibleForTesting
-    static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2);
-    // Sliding window for tracking how many mitigation calls were made for a package.
-    @VisibleForTesting
-    static final long DEFAULT_DEESCALATION_WINDOW_MS = TimeUnit.HOURS.toMillis(1);
-    // Whether explicit health checks are enabled or not
-    private static final boolean DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED = true;
-
-    @VisibleForTesting
-    static final int DEFAULT_BOOT_LOOP_TRIGGER_COUNT = 5;
-
-    static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10);
-    // Boot loop at which packageWatchdog starts first mitigation
-    private static final String BOOT_LOOP_THRESHOLD =
-            "persist.device_config.configuration.boot_loop_threshold";
-    @VisibleForTesting
-    static final int DEFAULT_BOOT_LOOP_THRESHOLD = 15;
-    // Once boot_loop_threshold is surpassed next mitigation would be triggered after
-    // specified number of reboots.
-    private static final String BOOT_LOOP_MITIGATION_INCREMENT =
-            "persist.device_config.configuration..boot_loop_mitigation_increment";
-    @VisibleForTesting
-    static final int DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT = 2;
-
-    // Threshold level at which or above user might experience significant disruption.
-    private static final String MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
-            "persist.device_config.configuration.major_user_impact_level_threshold";
-    private static final int DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
-            PackageHealthObserverImpact.USER_IMPACT_LEVEL_71;
-
-    private long mNumberOfNativeCrashPollsRemaining;
-
-    private static final int DB_VERSION = 1;
-    private static final String TAG_PACKAGE_WATCHDOG = "package-watchdog";
-    private static final String TAG_PACKAGE = "package";
-    private static final String TAG_OBSERVER = "observer";
-    private static final String ATTR_VERSION = "version";
-    private static final String ATTR_NAME = "name";
-    private static final String ATTR_DURATION = "duration";
-    private static final String ATTR_EXPLICIT_HEALTH_CHECK_DURATION = "health-check-duration";
-    private static final String ATTR_PASSED_HEALTH_CHECK = "passed-health-check";
-    private static final String ATTR_MITIGATION_CALLS = "mitigation-calls";
-    private static final String ATTR_MITIGATION_COUNT = "mitigation-count";
-
-    // A file containing information about the current mitigation count in the case of a boot loop.
-    // This allows boot loop information to persist in the case of an fs-checkpoint being
-    // aborted.
-    private static final String METADATA_FILE = "/metadata/watchdog/mitigation_count.txt";
-
-    @GuardedBy("PackageWatchdog.class")
-    private static PackageWatchdog sPackageWatchdog;
-
-    private final Object mLock = new Object();
-    // System server context
-    private final Context mContext;
-    // Handler to run short running tasks
-    private final Handler mShortTaskHandler;
-    // Handler for processing IO and long running tasks
-    private final Handler mLongTaskHandler;
-    // Contains (observer-name -> observer-handle) that have ever been registered from
-    // previous boots. Observers with all packages expired are periodically pruned.
-    // It is saved to disk on system shutdown and repouplated on startup so it survives reboots.
-    @GuardedBy("mLock")
-    private final ArrayMap<String, ObserverInternal> mAllObservers = new ArrayMap<>();
-    // File containing the XML data of monitored packages /data/system/package-watchdog.xml
-    private final AtomicFile mPolicyFile;
-    private final ExplicitHealthCheckController mHealthCheckController;
-    private final ConnectivityModuleConnector mConnectivityModuleConnector;
-    private final Runnable mSyncRequests = this::syncRequests;
-    private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason;
-    private final Runnable mSaveToFile = this::saveToFile;
-    private final SystemClock mSystemClock;
-    private final BootThreshold mBootThreshold;
-    private final DeviceConfig.OnPropertiesChangedListener
-            mOnPropertyChangedListener = this::onPropertyChanged;
-
-    // The set of packages that have been synced with the ExplicitHealthCheckController
-    @GuardedBy("mLock")
-    private Set<String> mRequestedHealthCheckPackages = new ArraySet<>();
-    @GuardedBy("mLock")
-    private boolean mIsPackagesReady;
-    // Flag to control whether explicit health checks are supported or not
-    @GuardedBy("mLock")
-    private boolean mIsHealthCheckEnabled = DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED;
-    @GuardedBy("mLock")
-    private int mTriggerFailureDurationMs = DEFAULT_TRIGGER_FAILURE_DURATION_MS;
-    @GuardedBy("mLock")
-    private int mTriggerFailureCount = DEFAULT_TRIGGER_FAILURE_COUNT;
-    // SystemClock#uptimeMillis when we last executed #syncState
-    // 0 if no prune is scheduled.
-    @GuardedBy("mLock")
-    private long mUptimeAtLastStateSync;
-    // If true, sync explicit health check packages with the ExplicitHealthCheckController.
-    @GuardedBy("mLock")
-    private boolean mSyncRequired = false;
-
-    @FunctionalInterface
-    @VisibleForTesting
-    interface SystemClock {
-        long uptimeMillis();
-    }
-
-    private PackageWatchdog(Context context) {
-        // Needs to be constructed inline
-        this(context, new AtomicFile(
-                        new File(new File(Environment.getDataDirectory(), "system"),
-                                "package-watchdog.xml")),
-                new Handler(Looper.myLooper()), BackgroundThread.getHandler(),
-                new ExplicitHealthCheckController(context),
-                ConnectivityModuleConnector.getInstance(),
-                android.os.SystemClock::uptimeMillis);
-    }
-
-    /**
-     * Creates a PackageWatchdog that allows injecting dependencies.
-     */
-    @VisibleForTesting
-    PackageWatchdog(Context context, AtomicFile policyFile, Handler shortTaskHandler,
-            Handler longTaskHandler, ExplicitHealthCheckController controller,
-            ConnectivityModuleConnector connectivityModuleConnector, SystemClock clock) {
-        mContext = context;
-        mPolicyFile = policyFile;
-        mShortTaskHandler = shortTaskHandler;
-        mLongTaskHandler = longTaskHandler;
-        mHealthCheckController = controller;
-        mConnectivityModuleConnector = connectivityModuleConnector;
-        mSystemClock = clock;
-        mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
-        if (Flags.recoverabilityDetection()) {
-            mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    SystemProperties.getInt(BOOT_LOOP_MITIGATION_INCREMENT,
-                            DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-        } else {
-            mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS);
-        }
-
-        loadFromFile();
-        sPackageWatchdog = this;
-    }
-
-    /** Creates or gets singleton instance of PackageWatchdog. */
-    public static PackageWatchdog getInstance(Context context) {
-        synchronized (PackageWatchdog.class) {
-            if (sPackageWatchdog == null) {
-                new PackageWatchdog(context);
-            }
-            return sPackageWatchdog;
-        }
-    }
-
-    /**
-     * Called during boot to notify when packages are ready on the device so we can start
-     * binding.
-     */
-    public void onPackagesReady() {
-        synchronized (mLock) {
-            mIsPackagesReady = true;
-            mHealthCheckController.setCallbacks(packageName -> onHealthCheckPassed(packageName),
-                    packages -> onSupportedPackages(packages),
-                    this::onSyncRequestNotified);
-            setPropertyChangedListenerLocked();
-            updateConfigs();
-            registerConnectivityModuleHealthListener();
-        }
-    }
-
-    /**
-     * Registers {@code observer} to listen for package failures. Add a new ObserverInternal for
-     * this observer if it does not already exist.
-     *
-     * <p>Observers are expected to call this on boot. It does not specify any packages but
-     * it will resume observing any packages requested from a previous boot.
-     */
-    public void registerHealthObserver(PackageHealthObserver observer) {
-        synchronized (mLock) {
-            ObserverInternal internalObserver = mAllObservers.get(observer.getName());
-            if (internalObserver != null) {
-                internalObserver.registeredObserver = observer;
-            } else {
-                internalObserver = new ObserverInternal(observer.getName(), new ArrayList<>());
-                internalObserver.registeredObserver = observer;
-                mAllObservers.put(observer.getName(), internalObserver);
-                syncState("added new observer");
-            }
-        }
-    }
-
-    /**
-     * Starts observing the health of the {@code packages} for {@code observer} and notifies
-     * {@code observer} of any package failures within the monitoring duration.
-     *
-     * <p>If monitoring a package supporting explicit health check, at the end of the monitoring
-     * duration if {@link #onHealthCheckPassed} was never called,
-     * {@link PackageHealthObserver#execute} will be called as if the package failed.
-     *
-     * <p>If {@code observer} is already monitoring a package in {@code packageNames},
-     * the monitoring window of that package will be reset to {@code durationMs} and the health
-     * check state will be reset to a default depending on if the package is contained in
-     * {@link mPackagesWithExplicitHealthCheckEnabled}.
-     *
-     * <p>If {@code packageNames} is empty, this will be a no-op.
-     *
-     * <p>If {@code durationMs} is less than 1, a default monitoring duration
-     * {@link #DEFAULT_OBSERVING_DURATION_MS} will be used.
-     */
-    public void startObservingHealth(PackageHealthObserver observer, List<String> packageNames,
-            long durationMs) {
-        if (packageNames.isEmpty()) {
-            Slog.wtf(TAG, "No packages to observe, " + observer.getName());
-            return;
-        }
-        if (durationMs < 1) {
-            Slog.wtf(TAG, "Invalid duration " + durationMs + "ms for observer "
-                    + observer.getName() + ". Not observing packages " + packageNames);
-            durationMs = DEFAULT_OBSERVING_DURATION_MS;
-        }
-
-        List<MonitoredPackage> packages = new ArrayList<>();
-        for (int i = 0; i < packageNames.size(); i++) {
-            // Health checks not available yet so health check state will start INACTIVE
-            MonitoredPackage pkg = newMonitoredPackage(packageNames.get(i), durationMs, false);
-            if (pkg != null) {
-                packages.add(pkg);
-            } else {
-                Slog.w(TAG, "Failed to create MonitoredPackage for pkg=" + packageNames.get(i));
-            }
-        }
-
-        if (packages.isEmpty()) {
-            return;
-        }
-
-        // Sync before we add the new packages to the observers. This will #pruneObservers,
-        // causing any elapsed time to be deducted from all existing packages before we add new
-        // packages. This maintains the invariant that the elapsed time for ALL (new and existing)
-        // packages is the same.
-        mLongTaskHandler.post(() -> {
-            syncState("observing new packages");
-
-            synchronized (mLock) {
-                ObserverInternal oldObserver = mAllObservers.get(observer.getName());
-                if (oldObserver == null) {
-                    Slog.d(TAG, observer.getName() + " started monitoring health "
-                            + "of packages " + packageNames);
-                    mAllObservers.put(observer.getName(),
-                            new ObserverInternal(observer.getName(), packages));
-                } else {
-                    Slog.d(TAG, observer.getName() + " added the following "
-                            + "packages to monitor " + packageNames);
-                    oldObserver.updatePackagesLocked(packages);
-                }
-            }
-
-            // Register observer in case not already registered
-            registerHealthObserver(observer);
-
-            // Sync after we add the new packages to the observers. We may have received packges
-            // requiring an earlier schedule than we are currently scheduled for.
-            syncState("updated observers");
-        });
-
-    }
-
-    /**
-     * Unregisters {@code observer} from listening to package failure.
-     * Additionally, this stops observing any packages that may have previously been observed
-     * even from a previous boot.
-     */
-    public void unregisterHealthObserver(PackageHealthObserver observer) {
-        mLongTaskHandler.post(() -> {
-            synchronized (mLock) {
-                mAllObservers.remove(observer.getName());
-            }
-            syncState("unregistering observer: " + observer.getName());
-        });
-    }
-
-    /**
-     * Called when a process fails due to a crash, ANR or explicit health check.
-     *
-     * <p>For each package contained in the process, one registered observer with the least user
-     * impact will be notified for mitigation.
-     *
-     * <p>This method could be called frequently if there is a severe problem on the device.
-     */
-    public void onPackageFailure(List<VersionedPackage> packages,
-            @FailureReasons int failureReason) {
-        if (packages == null) {
-            Slog.w(TAG, "Could not resolve a list of failing packages");
-            return;
-        }
-        mLongTaskHandler.post(() -> {
-            synchronized (mLock) {
-                if (mAllObservers.isEmpty()) {
-                    return;
-                }
-                boolean requiresImmediateAction = (failureReason == FAILURE_REASON_NATIVE_CRASH
-                        || failureReason == FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
-                if (requiresImmediateAction) {
-                    handleFailureImmediately(packages, failureReason);
-                } else {
-                    for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
-                        VersionedPackage versionedPackage = packages.get(pIndex);
-                        // Observer that will receive failure for versionedPackage
-                        PackageHealthObserver currentObserverToNotify = null;
-                        int currentObserverImpact = Integer.MAX_VALUE;
-                        MonitoredPackage currentMonitoredPackage = null;
-
-                        // Find observer with least user impact
-                        for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
-                            ObserverInternal observer = mAllObservers.valueAt(oIndex);
-                            PackageHealthObserver registeredObserver = observer.registeredObserver;
-                            if (registeredObserver != null
-                                    && observer.onPackageFailureLocked(
-                                    versionedPackage.getPackageName())) {
-                                MonitoredPackage p = observer.getMonitoredPackage(
-                                        versionedPackage.getPackageName());
-                                int mitigationCount = 1;
-                                if (p != null) {
-                                    mitigationCount = p.getMitigationCountLocked() + 1;
-                                }
-                                int impact = registeredObserver.onHealthCheckFailed(
-                                        versionedPackage, failureReason, mitigationCount);
-                                if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
-                                        && impact < currentObserverImpact) {
-                                    currentObserverToNotify = registeredObserver;
-                                    currentObserverImpact = impact;
-                                    currentMonitoredPackage = p;
-                                }
-                            }
-                        }
-
-                        // Execute action with least user impact
-                        if (currentObserverToNotify != null) {
-                            int mitigationCount = 1;
-                            if (currentMonitoredPackage != null) {
-                                currentMonitoredPackage.noteMitigationCallLocked();
-                                mitigationCount =
-                                        currentMonitoredPackage.getMitigationCountLocked();
-                            }
-                            if (Flags.recoverabilityDetection()) {
-                                maybeExecute(currentObserverToNotify, versionedPackage,
-                                        failureReason, currentObserverImpact, mitigationCount);
-                            } else {
-                                currentObserverToNotify.execute(versionedPackage,
-                                        failureReason, mitigationCount);
-                            }
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * For native crashes or explicit health check failures, call directly into each observer to
-     * mitigate the error without going through failure threshold logic.
-     */
-    private void handleFailureImmediately(List<VersionedPackage> packages,
-            @FailureReasons int failureReason) {
-        VersionedPackage failingPackage = packages.size() > 0 ? packages.get(0) : null;
-        PackageHealthObserver currentObserverToNotify = null;
-        int currentObserverImpact = Integer.MAX_VALUE;
-        for (ObserverInternal observer: mAllObservers.values()) {
-            PackageHealthObserver registeredObserver = observer.registeredObserver;
-            if (registeredObserver != null) {
-                int impact = registeredObserver.onHealthCheckFailed(
-                        failingPackage, failureReason, 1);
-                if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
-                        && impact < currentObserverImpact) {
-                    currentObserverToNotify = registeredObserver;
-                    currentObserverImpact = impact;
-                }
-            }
-        }
-        if (currentObserverToNotify != null) {
-            if (Flags.recoverabilityDetection()) {
-                maybeExecute(currentObserverToNotify, failingPackage, failureReason,
-                        currentObserverImpact, /*mitigationCount=*/ 1);
-            } else {
-                currentObserverToNotify.execute(failingPackage,  failureReason, 1);
-            }
-        }
-    }
-
-    private void maybeExecute(PackageHealthObserver currentObserverToNotify,
-                              VersionedPackage versionedPackage,
-                              @FailureReasons int failureReason,
-                              int currentObserverImpact,
-                              int mitigationCount) {
-        if (currentObserverImpact < getUserImpactLevelLimit()) {
-            currentObserverToNotify.execute(versionedPackage, failureReason, mitigationCount);
-        }
-    }
-
-
-    /**
-     * Called when the system server boots. If the system server is detected to be in a boot loop,
-     * query each observer and perform the mitigation action with the lowest user impact.
-     */
-    @SuppressWarnings("GuardedBy")
-    public void noteBoot() {
-        synchronized (mLock) {
-            boolean mitigate = mBootThreshold.incrementAndTest();
-            if (mitigate) {
-                if (!Flags.recoverabilityDetection()) {
-                    mBootThreshold.reset();
-                }
-                int mitigationCount = mBootThreshold.getMitigationCount() + 1;
-                PackageHealthObserver currentObserverToNotify = null;
-                ObserverInternal currentObserverInternal = null;
-                int currentObserverImpact = Integer.MAX_VALUE;
-                for (int i = 0; i < mAllObservers.size(); i++) {
-                    final ObserverInternal observer = mAllObservers.valueAt(i);
-                    PackageHealthObserver registeredObserver = observer.registeredObserver;
-                    if (registeredObserver != null) {
-                        int impact = Flags.recoverabilityDetection()
-                                ? registeredObserver.onBootLoop(
-                                        observer.getBootMitigationCount() + 1)
-                                : registeredObserver.onBootLoop(mitigationCount);
-                        if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
-                                && impact < currentObserverImpact) {
-                            currentObserverToNotify = registeredObserver;
-                            currentObserverInternal = observer;
-                            currentObserverImpact = impact;
-                        }
-                    }
-                }
-                if (currentObserverToNotify != null) {
-                    if (Flags.recoverabilityDetection()) {
-                        if (currentObserverImpact < getUserImpactLevelLimit()
-                                || (currentObserverImpact >= getUserImpactLevelLimit()
-                                        && mBootThreshold.getCount() >= getBootLoopThreshold())) {
-                            int currentObserverMitigationCount =
-                                    currentObserverInternal.getBootMitigationCount() + 1;
-                            currentObserverInternal.setBootMitigationCount(
-                                    currentObserverMitigationCount);
-                            saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
-                            currentObserverToNotify.executeBootLoopMitigation(
-                                    currentObserverMitigationCount);
-                        }
-                    } else {
-                        mBootThreshold.setMitigationCount(mitigationCount);
-                        mBootThreshold.saveMitigationCountToMetadata();
-                        currentObserverToNotify.executeBootLoopMitigation(mitigationCount);
-                    }
-                }
-            }
-        }
-    }
-
-    // TODO(b/120598832): Optimize write? Maybe only write a separate smaller file? Also
-    // avoid holding lock?
-    // This currently adds about 7ms extra to shutdown thread
-    /** Writes the package information to file during shutdown. */
-    public void writeNow() {
-        synchronized (mLock) {
-            // Must only run synchronous tasks as this runs on the ShutdownThread and no other
-            // thread is guaranteed to run during shutdown.
-            if (!mAllObservers.isEmpty()) {
-                mLongTaskHandler.removeCallbacks(mSaveToFile);
-                pruneObserversLocked();
-                saveToFile();
-                Slog.i(TAG, "Last write to update package durations");
-            }
-        }
-    }
-
-    /**
-     * Enables or disables explicit health checks.
-     * <p> If explicit health checks are enabled, the health check service is started.
-     * <p> If explicit health checks are disabled, pending explicit health check requests are
-     * passed and the health check service is stopped.
-     */
-    private void setExplicitHealthCheckEnabled(boolean enabled) {
-        synchronized (mLock) {
-            mIsHealthCheckEnabled = enabled;
-            mHealthCheckController.setEnabled(enabled);
-            mSyncRequired = true;
-            // Prune to update internal state whenever health check is enabled/disabled
-            syncState("health check state " + (enabled ? "enabled" : "disabled"));
-        }
-    }
-
-    /**
-     * This method should be only called on mShortTaskHandler, since it modifies
-     * {@link #mNumberOfNativeCrashPollsRemaining}.
-     */
-    private void checkAndMitigateNativeCrashes() {
-        mNumberOfNativeCrashPollsRemaining--;
-        // Check if native watchdog reported a crash
-        if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
-            // We rollback all available low impact rollbacks when crash is unattributable
-            onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH);
-            // we stop polling after an attempt to execute rollback, regardless of whether the
-            // attempt succeeds or not
-        } else {
-            if (mNumberOfNativeCrashPollsRemaining > 0) {
-                mShortTaskHandler.postDelayed(() -> checkAndMitigateNativeCrashes(),
-                        NATIVE_CRASH_POLLING_INTERVAL_MILLIS);
-            }
-        }
-    }
-
-    /**
-     * Since this method can eventually trigger a rollback, it should be called
-     * only once boot has completed {@code onBootCompleted} and not earlier, because the install
-     * session must be entirely completed before we try to rollback.
-     */
-    public void scheduleCheckAndMitigateNativeCrashes() {
-        Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check "
-                + "and mitigate native crashes");
-        mShortTaskHandler.post(()->checkAndMitigateNativeCrashes());
-    }
-
-    private int getUserImpactLevelLimit() {
-        return SystemProperties.getInt(MAJOR_USER_IMPACT_LEVEL_THRESHOLD,
-                DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD);
-    }
-
-    private int getBootLoopThreshold() {
-        return SystemProperties.getInt(BOOT_LOOP_THRESHOLD,
-                DEFAULT_BOOT_LOOP_THRESHOLD);
-    }
-
-    /** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */
-    @Retention(SOURCE)
-    @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_10,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_20,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_30,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_50,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_71,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_75,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_80,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_90,
-                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_100})
-    public @interface PackageHealthObserverImpact {
-        /** No action to take. */
-        int USER_IMPACT_LEVEL_0 = 0;
-        /* Action has low user impact, user of a device will barely notice. */
-        int USER_IMPACT_LEVEL_10 = 10;
-        /* Actions having medium user impact, user of a device will likely notice. */
-        int USER_IMPACT_LEVEL_20 = 20;
-        int USER_IMPACT_LEVEL_30 = 30;
-        int USER_IMPACT_LEVEL_50 = 50;
-        int USER_IMPACT_LEVEL_70 = 70;
-        /* Action has high user impact, a last resort, user of a device will be very frustrated. */
-        int USER_IMPACT_LEVEL_71 = 71;
-        int USER_IMPACT_LEVEL_75 = 75;
-        int USER_IMPACT_LEVEL_80 = 80;
-        int USER_IMPACT_LEVEL_90 = 90;
-        int USER_IMPACT_LEVEL_100 = 100;
-    }
-
-    /** Register instances of this interface to receive notifications on package failure. */
-    public interface PackageHealthObserver {
-        /**
-         * Called when health check fails for the {@code versionedPackage}.
-         *
-         * @param versionedPackage the package that is failing. This may be null if a native
-         *                          service is crashing.
-         * @param failureReason   the type of failure that is occurring.
-         * @param mitigationCount the number of times mitigation has been called for this package
-         *                        (including this time).
-         *
-         *
-         * @return any one of {@link PackageHealthObserverImpact} to express the impact
-         * to the user on {@link #execute}
-         */
-        @PackageHealthObserverImpact int onHealthCheckFailed(
-                @Nullable VersionedPackage versionedPackage,
-                @FailureReasons int failureReason,
-                int mitigationCount);
-
-        /**
-         * Executes mitigation for {@link #onHealthCheckFailed}.
-         *
-         * @param versionedPackage the package that is failing. This may be null if a native
-         *                          service is crashing.
-         * @param failureReason   the type of failure that is occurring.
-         * @param mitigationCount the number of times mitigation has been called for this package
-         *                        (including this time).
-         * @return {@code true} if action was executed successfully, {@code false} otherwise
-         */
-        boolean execute(@Nullable VersionedPackage versionedPackage,
-                @FailureReasons int failureReason, int mitigationCount);
-
-
-        /**
-         * Called when the system server has booted several times within a window of time, defined
-         * by {@link #mBootThreshold}
-         *
-         * @param mitigationCount the number of times mitigation has been attempted for this
-         *                        boot loop (including this time).
-         */
-        default @PackageHealthObserverImpact int onBootLoop(int mitigationCount) {
-            return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
-        }
-
-        /**
-         * Executes mitigation for {@link #onBootLoop}
-         * @param mitigationCount the number of times mitigation has been attempted for this
-         *                        boot loop (including this time).
-         */
-        default boolean executeBootLoopMitigation(int mitigationCount) {
-            return false;
-        }
-
-        // TODO(b/120598832): Ensure uniqueness?
-        /**
-         * Identifier for the observer, should not change across device updates otherwise the
-         * watchdog may drop observing packages with the old name.
-         */
-        String getName();
-
-        /**
-         * An observer will not be pruned if this is set, even if the observer is not explicitly
-         * monitoring any packages.
-         */
-        default boolean isPersistent() {
-            return false;
-        }
-
-        /**
-         * Returns {@code true} if this observer wishes to observe the given package, {@code false}
-         * otherwise
-         *
-         * <p> A persistent observer may choose to start observing certain failing packages, even if
-         * it has not explicitly asked to watch the package with {@link #startObservingHealth}.
-         */
-        default boolean mayObservePackage(String packageName) {
-            return false;
-        }
-    }
-
-    @VisibleForTesting
-    long getTriggerFailureCount() {
-        synchronized (mLock) {
-            return mTriggerFailureCount;
-        }
-    }
-
-    @VisibleForTesting
-    long getTriggerFailureDurationMs() {
-        synchronized (mLock) {
-            return mTriggerFailureDurationMs;
-        }
-    }
-
-    /**
-     * Serializes and syncs health check requests with the {@link ExplicitHealthCheckController}.
-     */
-    private void syncRequestsAsync() {
-        mShortTaskHandler.removeCallbacks(mSyncRequests);
-        mShortTaskHandler.post(mSyncRequests);
-    }
-
-    /**
-     * Syncs health check requests with the {@link ExplicitHealthCheckController}.
-     * Calls to this must be serialized.
-     *
-     * @see #syncRequestsAsync
-     */
-    private void syncRequests() {
-        boolean syncRequired = false;
-        synchronized (mLock) {
-            if (mIsPackagesReady) {
-                Set<String> packages = getPackagesPendingHealthChecksLocked();
-                if (mSyncRequired || !packages.equals(mRequestedHealthCheckPackages)
-                        || packages.isEmpty()) {
-                    syncRequired = true;
-                    mRequestedHealthCheckPackages = packages;
-                }
-            } // else, we will sync requests when packages become ready
-        }
-
-        // Call outside lock to avoid holding lock when calling into the controller.
-        if (syncRequired) {
-            Slog.i(TAG, "Syncing health check requests for packages: "
-                    + mRequestedHealthCheckPackages);
-            mHealthCheckController.syncRequests(mRequestedHealthCheckPackages);
-            mSyncRequired = false;
-        }
-    }
-
-    /**
-     * Updates the observers monitoring {@code packageName} that explicit health check has passed.
-     *
-     * <p> This update is strictly for registered observers at the time of the call
-     * Observers that register after this signal will have no knowledge of prior signals and will
-     * effectively behave as if the explicit health check hasn't passed for {@code packageName}.
-     *
-     * <p> {@code packageName} can still be considered failed if reported by
-     * {@link #onPackageFailureLocked} before the package expires.
-     *
-     * <p> Triggered by components outside the system server when they are fully functional after an
-     * update.
-     */
-    private void onHealthCheckPassed(String packageName) {
-        Slog.i(TAG, "Health check passed for package: " + packageName);
-        boolean isStateChanged = false;
-
-        synchronized (mLock) {
-            for (int observerIdx = 0; observerIdx < mAllObservers.size(); observerIdx++) {
-                ObserverInternal observer = mAllObservers.valueAt(observerIdx);
-                MonitoredPackage monitoredPackage = observer.getMonitoredPackage(packageName);
-
-                if (monitoredPackage != null) {
-                    int oldState = monitoredPackage.getHealthCheckStateLocked();
-                    int newState = monitoredPackage.tryPassHealthCheckLocked();
-                    isStateChanged |= oldState != newState;
-                }
-            }
-        }
-
-        if (isStateChanged) {
-            syncState("health check passed for " + packageName);
-        }
-    }
-
-    private void onSupportedPackages(List<PackageConfig> supportedPackages) {
-        boolean isStateChanged = false;
-
-        Map<String, Long> supportedPackageTimeouts = new ArrayMap<>();
-        Iterator<PackageConfig> it = supportedPackages.iterator();
-        while (it.hasNext()) {
-            PackageConfig info = it.next();
-            supportedPackageTimeouts.put(info.getPackageName(), info.getHealthCheckTimeoutMillis());
-        }
-
-        synchronized (mLock) {
-            Slog.d(TAG, "Received supported packages " + supportedPackages);
-            Iterator<ObserverInternal> oit = mAllObservers.values().iterator();
-            while (oit.hasNext()) {
-                Iterator<MonitoredPackage> pit = oit.next().getMonitoredPackages()
-                        .values().iterator();
-                while (pit.hasNext()) {
-                    MonitoredPackage monitoredPackage = pit.next();
-                    String packageName = monitoredPackage.getName();
-                    int oldState = monitoredPackage.getHealthCheckStateLocked();
-                    int newState;
-
-                    if (supportedPackageTimeouts.containsKey(packageName)) {
-                        // Supported packages become ACTIVE if currently INACTIVE
-                        newState = monitoredPackage.setHealthCheckActiveLocked(
-                                supportedPackageTimeouts.get(packageName));
-                    } else {
-                        // Unsupported packages are marked as PASSED unless already FAILED
-                        newState = monitoredPackage.tryPassHealthCheckLocked();
-                    }
-                    isStateChanged |= oldState != newState;
-                }
-            }
-        }
-
-        if (isStateChanged) {
-            syncState("updated health check supported packages " + supportedPackages);
-        }
-    }
-
-    private void onSyncRequestNotified() {
-        synchronized (mLock) {
-            mSyncRequired = true;
-            syncRequestsAsync();
-        }
-    }
-
-    @GuardedBy("mLock")
-    private Set<String> getPackagesPendingHealthChecksLocked() {
-        Set<String> packages = new ArraySet<>();
-        Iterator<ObserverInternal> oit = mAllObservers.values().iterator();
-        while (oit.hasNext()) {
-            ObserverInternal observer = oit.next();
-            Iterator<MonitoredPackage> pit =
-                    observer.getMonitoredPackages().values().iterator();
-            while (pit.hasNext()) {
-                MonitoredPackage monitoredPackage = pit.next();
-                String packageName = monitoredPackage.getName();
-                if (monitoredPackage.isPendingHealthChecksLocked()) {
-                    packages.add(packageName);
-                }
-            }
-        }
-        return packages;
-    }
-
-    /**
-     * Syncs the state of the observers.
-     *
-     * <p> Prunes all observers, saves new state to disk, syncs health check requests with the
-     * health check service and schedules the next state sync.
-     */
-    private void syncState(String reason) {
-        synchronized (mLock) {
-            Slog.i(TAG, "Syncing state, reason: " + reason);
-            pruneObserversLocked();
-
-            saveToFileAsync();
-            syncRequestsAsync();
-
-            // Done syncing state, schedule the next state sync
-            scheduleNextSyncStateLocked();
-        }
-    }
-
-    private void syncStateWithScheduledReason() {
-        syncState("scheduled");
-    }
-
-    @GuardedBy("mLock")
-    private void scheduleNextSyncStateLocked() {
-        long durationMs = getNextStateSyncMillisLocked();
-        mShortTaskHandler.removeCallbacks(mSyncStateWithScheduledReason);
-        if (durationMs == Long.MAX_VALUE) {
-            Slog.i(TAG, "Cancelling state sync, nothing to sync");
-            mUptimeAtLastStateSync = 0;
-        } else {
-            mUptimeAtLastStateSync = mSystemClock.uptimeMillis();
-            mShortTaskHandler.postDelayed(mSyncStateWithScheduledReason, durationMs);
-        }
-    }
-
-    /**
-     * Returns the next duration in millis to sync the watchdog state.
-     *
-     * @returns Long#MAX_VALUE if there are no observed packages.
-     */
-    @GuardedBy("mLock")
-    private long getNextStateSyncMillisLocked() {
-        long shortestDurationMs = Long.MAX_VALUE;
-        for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
-            ArrayMap<String, MonitoredPackage> packages = mAllObservers.valueAt(oIndex)
-                    .getMonitoredPackages();
-            for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
-                MonitoredPackage mp = packages.valueAt(pIndex);
-                long duration = mp.getShortestScheduleDurationMsLocked();
-                if (duration < shortestDurationMs) {
-                    shortestDurationMs = duration;
-                }
-            }
-        }
-        return shortestDurationMs;
-    }
-
-    /**
-     * Removes {@code elapsedMs} milliseconds from all durations on monitored packages
-     * and updates other internal state.
-     */
-    @GuardedBy("mLock")
-    private void pruneObserversLocked() {
-        long elapsedMs = mUptimeAtLastStateSync == 0
-                ? 0 : mSystemClock.uptimeMillis() - mUptimeAtLastStateSync;
-        if (elapsedMs <= 0) {
-            Slog.i(TAG, "Not pruning observers, elapsed time: " + elapsedMs + "ms");
-            return;
-        }
-
-        Iterator<ObserverInternal> it = mAllObservers.values().iterator();
-        while (it.hasNext()) {
-            ObserverInternal observer = it.next();
-            Set<MonitoredPackage> failedPackages =
-                    observer.prunePackagesLocked(elapsedMs);
-            if (!failedPackages.isEmpty()) {
-                onHealthCheckFailed(observer, failedPackages);
-            }
-            if (observer.getMonitoredPackages().isEmpty() && (observer.registeredObserver == null
-                    || !observer.registeredObserver.isPersistent())) {
-                Slog.i(TAG, "Discarding observer " + observer.name + ". All packages expired");
-                it.remove();
-            }
-        }
-    }
-
-    private void onHealthCheckFailed(ObserverInternal observer,
-            Set<MonitoredPackage> failedPackages) {
-        mLongTaskHandler.post(() -> {
-            synchronized (mLock) {
-                PackageHealthObserver registeredObserver = observer.registeredObserver;
-                if (registeredObserver != null) {
-                    Iterator<MonitoredPackage> it = failedPackages.iterator();
-                    while (it.hasNext()) {
-                        VersionedPackage versionedPkg = getVersionedPackage(it.next().getName());
-                        if (versionedPkg != null) {
-                            Slog.i(TAG,
-                                    "Explicit health check failed for package " + versionedPkg);
-                            registeredObserver.execute(versionedPkg,
-                                    PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK, 1);
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * Gets PackageInfo for the given package. Matches any user and apex.
-     *
-     * @throws PackageManager.NameNotFoundException if no such package is installed.
-     */
-    private PackageInfo getPackageInfo(String packageName)
-            throws PackageManager.NameNotFoundException {
-        PackageManager pm = mContext.getPackageManager();
-        try {
-            // The MATCH_ANY_USER flag doesn't mix well with the MATCH_APEX
-            // flag, so make two separate attempts to get the package info.
-            // We don't need both flags at the same time because we assume
-            // apex files are always installed for all users.
-            return pm.getPackageInfo(packageName, PackageManager.MATCH_ANY_USER);
-        } catch (PackageManager.NameNotFoundException e) {
-            return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
-        }
-    }
-
-    @Nullable
-    private VersionedPackage getVersionedPackage(String packageName) {
-        final PackageManager pm = mContext.getPackageManager();
-        if (pm == null || TextUtils.isEmpty(packageName)) {
-            return null;
-        }
-        try {
-            final long versionCode = getPackageInfo(packageName).getLongVersionCode();
-            return new VersionedPackage(packageName, versionCode);
-        } catch (PackageManager.NameNotFoundException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Loads mAllObservers from file.
-     *
-     * <p>Note that this is <b>not</b> thread safe and should only called be called
-     * from the constructor.
-     */
-    private void loadFromFile() {
-        InputStream infile = null;
-        mAllObservers.clear();
-        try {
-            infile = mPolicyFile.openRead();
-            final TypedXmlPullParser parser = Xml.resolvePullParser(infile);
-            XmlUtils.beginDocument(parser, TAG_PACKAGE_WATCHDOG);
-            int outerDepth = parser.getDepth();
-            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
-                ObserverInternal observer = ObserverInternal.read(parser, this);
-                if (observer != null) {
-                    mAllObservers.put(observer.name, observer);
-                }
-            }
-        } catch (FileNotFoundException e) {
-            // Nothing to monitor
-        } catch (IOException | NumberFormatException | XmlPullParserException e) {
-            Slog.wtf(TAG, "Unable to read monitored packages, deleting file", e);
-            mPolicyFile.delete();
-        } finally {
-            IoUtils.closeQuietly(infile);
-        }
-    }
-
-    private void onPropertyChanged(DeviceConfig.Properties properties) {
-        try {
-            updateConfigs();
-        } catch (Exception ignore) {
-            Slog.w(TAG, "Failed to reload device config changes");
-        }
-    }
-
-    /** Adds a {@link DeviceConfig#OnPropertiesChangedListener}. */
-    private void setPropertyChangedListenerLocked() {
-        DeviceConfig.addOnPropertiesChangedListener(
-                DeviceConfig.NAMESPACE_ROLLBACK,
-                mContext.getMainExecutor(),
-                mOnPropertyChangedListener);
-    }
-
-    @VisibleForTesting
-    void removePropertyChangedListener() {
-        DeviceConfig.removeOnPropertiesChangedListener(mOnPropertyChangedListener);
-    }
-
-    /**
-     * Health check is enabled or disabled after reading the flags
-     * from DeviceConfig.
-     */
-    @VisibleForTesting
-    void updateConfigs() {
-        synchronized (mLock) {
-            mTriggerFailureCount = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
-                    DEFAULT_TRIGGER_FAILURE_COUNT);
-            if (mTriggerFailureCount <= 0) {
-                mTriggerFailureCount = DEFAULT_TRIGGER_FAILURE_COUNT;
-            }
-
-            mTriggerFailureDurationMs = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS,
-                    DEFAULT_TRIGGER_FAILURE_DURATION_MS);
-            if (mTriggerFailureDurationMs <= 0) {
-                mTriggerFailureDurationMs = DEFAULT_TRIGGER_FAILURE_DURATION_MS;
-            }
-
-            setExplicitHealthCheckEnabled(DeviceConfig.getBoolean(
-                    DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED,
-                    DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED));
-        }
-    }
-
-    private void registerConnectivityModuleHealthListener() {
-        // TODO: have an internal method to trigger a rollback by reporting high severity errors,
-        // and rely on ActivityManager to inform the watchdog of severe network stack crashes
-        // instead of having this listener in parallel.
-        mConnectivityModuleConnector.registerHealthListener(
-                packageName -> {
-                    final VersionedPackage pkg = getVersionedPackage(packageName);
-                    if (pkg == null) {
-                        Slog.wtf(TAG, "NetworkStack failed but could not find its package");
-                        return;
-                    }
-                    final List<VersionedPackage> pkgList = Collections.singletonList(pkg);
-                    onPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
-                });
-    }
-
-    /**
-     * Persists mAllObservers to file. Threshold information is ignored.
-     */
-    private boolean saveToFile() {
-        Slog.i(TAG, "Saving observer state to file");
-        synchronized (mLock) {
-            FileOutputStream stream;
-            try {
-                stream = mPolicyFile.startWrite();
-            } catch (IOException e) {
-                Slog.w(TAG, "Cannot update monitored packages", e);
-                return false;
-            }
-
-            try {
-                TypedXmlSerializer out = Xml.resolveSerializer(stream);
-                out.startDocument(null, true);
-                out.startTag(null, TAG_PACKAGE_WATCHDOG);
-                out.attributeInt(null, ATTR_VERSION, DB_VERSION);
-                for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
-                    mAllObservers.valueAt(oIndex).writeLocked(out);
-                }
-                out.endTag(null, TAG_PACKAGE_WATCHDOG);
-                out.endDocument();
-                mPolicyFile.finishWrite(stream);
-                return true;
-            } catch (IOException e) {
-                Slog.w(TAG, "Failed to save monitored packages, restoring backup", e);
-                mPolicyFile.failWrite(stream);
-                return false;
-            } finally {
-                IoUtils.closeQuietly(stream);
-            }
-        }
-    }
-
-    private void saveToFileAsync() {
-        if (!mLongTaskHandler.hasCallbacks(mSaveToFile)) {
-            mLongTaskHandler.post(mSaveToFile);
-        }
-    }
-
-    /** Convert a {@code LongArrayQueue} to a String of comma-separated values. */
-    public static String longArrayQueueToString(LongArrayQueue queue) {
-        if (queue.size() > 0) {
-            StringBuilder sb = new StringBuilder();
-            sb.append(queue.get(0));
-            for (int i = 1; i < queue.size(); i++) {
-                sb.append(",");
-                sb.append(queue.get(i));
-            }
-            return sb.toString();
-        }
-        return "";
-    }
-
-    /** Parse a comma-separated String of longs into a LongArrayQueue. */
-    public static LongArrayQueue parseLongArrayQueue(String commaSeparatedValues) {
-        LongArrayQueue result = new LongArrayQueue();
-        if (!TextUtils.isEmpty(commaSeparatedValues)) {
-            String[] values = commaSeparatedValues.split(",");
-            for (String value : values) {
-                result.addLast(Long.parseLong(value));
-            }
-        }
-        return result;
-    }
-
-
-    /** Dump status of every observer in mAllObservers. */
-    public void dump(IndentingPrintWriter pw) {
-        pw.println("Package Watchdog status");
-        pw.increaseIndent();
-        synchronized (mLock) {
-            for (String observerName : mAllObservers.keySet()) {
-                pw.println("Observer name: " + observerName);
-                pw.increaseIndent();
-                ObserverInternal observerInternal = mAllObservers.get(observerName);
-                observerInternal.dump(pw);
-                pw.decreaseIndent();
-            }
-        }
-    }
-
-    @VisibleForTesting
-    @GuardedBy("mLock")
-    void registerObserverInternal(ObserverInternal observerInternal) {
-        mAllObservers.put(observerInternal.name, observerInternal);
-    }
-
-    /**
-     * Represents an observer monitoring a set of packages along with the failure thresholds for
-     * each package.
-     *
-     * <p> Note, the PackageWatchdog#mLock must always be held when reading or writing
-     * instances of this class.
-     */
-    static class ObserverInternal {
-        public final String name;
-        @GuardedBy("mLock")
-        private final ArrayMap<String, MonitoredPackage> mPackages = new ArrayMap<>();
-        @Nullable
-        @GuardedBy("mLock")
-        public PackageHealthObserver registeredObserver;
-        private int mMitigationCount;
-
-        ObserverInternal(String name, List<MonitoredPackage> packages) {
-            this(name, packages, /*mitigationCount=*/ 0);
-        }
-
-        ObserverInternal(String name, List<MonitoredPackage> packages, int mitigationCount) {
-            this.name = name;
-            updatePackagesLocked(packages);
-            this.mMitigationCount = mitigationCount;
-        }
-
-        /**
-         * Writes important {@link MonitoredPackage} details for this observer to file.
-         * Does not persist any package failure thresholds.
-         */
-        @GuardedBy("mLock")
-        public boolean writeLocked(TypedXmlSerializer out) {
-            try {
-                out.startTag(null, TAG_OBSERVER);
-                out.attribute(null, ATTR_NAME, name);
-                if (Flags.recoverabilityDetection()) {
-                    out.attributeInt(null, ATTR_MITIGATION_COUNT, mMitigationCount);
-                }
-                for (int i = 0; i < mPackages.size(); i++) {
-                    MonitoredPackage p = mPackages.valueAt(i);
-                    p.writeLocked(out);
-                }
-                out.endTag(null, TAG_OBSERVER);
-                return true;
-            } catch (IOException e) {
-                Slog.w(TAG, "Cannot save observer", e);
-                return false;
-            }
-        }
-
-        public int getBootMitigationCount() {
-            return mMitigationCount;
-        }
-
-        public void setBootMitigationCount(int mitigationCount) {
-            mMitigationCount = mitigationCount;
-        }
-
-        @GuardedBy("mLock")
-        public void updatePackagesLocked(List<MonitoredPackage> packages) {
-            for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
-                MonitoredPackage p = packages.get(pIndex);
-                MonitoredPackage existingPackage = getMonitoredPackage(p.getName());
-                if (existingPackage != null) {
-                    existingPackage.updateHealthCheckDuration(p.mDurationMs);
-                } else {
-                    putMonitoredPackage(p);
-                }
-            }
-        }
-
-        /**
-         * Reduces the monitoring durations of all packages observed by this observer by
-         * {@code elapsedMs}. If any duration is less than 0, the package is removed from
-         * observation. If any health check duration is less than 0, the health check result
-         * is evaluated.
-         *
-         * @return a {@link Set} of packages that were removed from the observer without explicit
-         * health check passing, or an empty list if no package expired for which an explicit health
-         * check was still pending
-         */
-        @GuardedBy("mLock")
-        private Set<MonitoredPackage> prunePackagesLocked(long elapsedMs) {
-            Set<MonitoredPackage> failedPackages = new ArraySet<>();
-            Iterator<MonitoredPackage> it = mPackages.values().iterator();
-            while (it.hasNext()) {
-                MonitoredPackage p = it.next();
-                int oldState = p.getHealthCheckStateLocked();
-                int newState = p.handleElapsedTimeLocked(elapsedMs);
-                if (oldState != HealthCheckState.FAILED
-                        && newState == HealthCheckState.FAILED) {
-                    Slog.i(TAG, "Package " + p.getName() + " failed health check");
-                    failedPackages.add(p);
-                }
-                if (p.isExpiredLocked()) {
-                    it.remove();
-                }
-            }
-            return failedPackages;
-        }
-
-        /**
-         * Increments failure counts of {@code packageName}.
-         * @returns {@code true} if failure threshold is exceeded, {@code false} otherwise
-         */
-        @GuardedBy("mLock")
-        public boolean onPackageFailureLocked(String packageName) {
-            if (getMonitoredPackage(packageName) == null && registeredObserver.isPersistent()
-                    && registeredObserver.mayObservePackage(packageName)) {
-                putMonitoredPackage(sPackageWatchdog.newMonitoredPackage(
-                        packageName, DEFAULT_OBSERVING_DURATION_MS, false));
-            }
-            MonitoredPackage p = getMonitoredPackage(packageName);
-            if (p != null) {
-                return p.onFailureLocked();
-            }
-            return false;
-        }
-
-        /**
-         * Returns the map of packages monitored by this observer.
-         *
-         * @return a mapping of package names to {@link MonitoredPackage} objects.
-         */
-        @GuardedBy("mLock")
-        public ArrayMap<String, MonitoredPackage> getMonitoredPackages() {
-            return mPackages;
-        }
-
-        /**
-         * Returns the {@link MonitoredPackage} associated with a given package name if the
-         * package is being monitored by this observer.
-         *
-         * @param packageName: the name of the package.
-         * @return the {@link MonitoredPackage} object associated with the package name if one
-         *         exists, {@code null} otherwise.
-         */
-        @GuardedBy("mLock")
-        @Nullable
-        public MonitoredPackage getMonitoredPackage(String packageName) {
-            return mPackages.get(packageName);
-        }
-
-        /**
-         * Associates a {@link MonitoredPackage} with the observer.
-         *
-         * @param p: the {@link MonitoredPackage} to store.
-         */
-        @GuardedBy("mLock")
-        public void putMonitoredPackage(MonitoredPackage p) {
-            mPackages.put(p.getName(), p);
-        }
-
-        /**
-         * Returns one ObserverInternal from the {@code parser} and advances its state.
-         *
-         * <p>Note that this method is <b>not</b> thread safe. It should only be called from
-         * #loadFromFile which in turn is only called on construction of the
-         * singleton PackageWatchdog.
-         **/
-        public static ObserverInternal read(TypedXmlPullParser parser, PackageWatchdog watchdog) {
-            String observerName = null;
-            int observerMitigationCount = 0;
-            if (TAG_OBSERVER.equals(parser.getName())) {
-                observerName = parser.getAttributeValue(null, ATTR_NAME);
-                if (TextUtils.isEmpty(observerName)) {
-                    Slog.wtf(TAG, "Unable to read observer name");
-                    return null;
-                }
-            }
-            List<MonitoredPackage> packages = new ArrayList<>();
-            int innerDepth = parser.getDepth();
-            try {
-                if (Flags.recoverabilityDetection()) {
-                    observerMitigationCount = parser.getAttributeInt(null, ATTR_MITIGATION_COUNT);
-                }
-                while (XmlUtils.nextElementWithin(parser, innerDepth)) {
-                    if (TAG_PACKAGE.equals(parser.getName())) {
-                        try {
-                            MonitoredPackage pkg = watchdog.parseMonitoredPackage(parser);
-                            if (pkg != null) {
-                                packages.add(pkg);
-                            }
-                        } catch (NumberFormatException e) {
-                            Slog.wtf(TAG, "Skipping package for observer " + observerName, e);
-                            continue;
-                        }
-                    }
-                }
-            } catch (XmlPullParserException | IOException e) {
-                Slog.wtf(TAG, "Unable to read observer " + observerName, e);
-                return null;
-            }
-            if (packages.isEmpty()) {
-                return null;
-            }
-            return new ObserverInternal(observerName, packages, observerMitigationCount);
-        }
-
-        /** Dumps information about this observer and the packages it watches. */
-        public void dump(IndentingPrintWriter pw) {
-            boolean isPersistent = registeredObserver != null && registeredObserver.isPersistent();
-            pw.println("Persistent: " + isPersistent);
-            for (String packageName : mPackages.keySet()) {
-                MonitoredPackage p = getMonitoredPackage(packageName);
-                pw.println(packageName +  ": ");
-                pw.increaseIndent();
-                pw.println("# Failures: " + p.mFailureHistory.size());
-                pw.println("Monitoring duration remaining: " + p.mDurationMs + "ms");
-                pw.println("Explicit health check duration: " + p.mHealthCheckDurationMs + "ms");
-                pw.println("Health check state: " + p.toString(p.mHealthCheckState));
-                pw.decreaseIndent();
-            }
-        }
-    }
-
-    @Retention(SOURCE)
-    @IntDef(value = {
-            HealthCheckState.ACTIVE,
-            HealthCheckState.INACTIVE,
-            HealthCheckState.PASSED,
-            HealthCheckState.FAILED})
-    public @interface HealthCheckState {
-        // The package has not passed health check but has requested a health check
-        int ACTIVE = 0;
-        // The package has not passed health check and has not requested a health check
-        int INACTIVE = 1;
-        // The package has passed health check
-        int PASSED = 2;
-        // The package has failed health check
-        int FAILED = 3;
-    }
-
-    MonitoredPackage newMonitoredPackage(
-            String name, long durationMs, boolean hasPassedHealthCheck) {
-        return newMonitoredPackage(name, durationMs, Long.MAX_VALUE, hasPassedHealthCheck,
-                new LongArrayQueue());
-    }
-
-    MonitoredPackage newMonitoredPackage(String name, long durationMs, long healthCheckDurationMs,
-            boolean hasPassedHealthCheck, LongArrayQueue mitigationCalls) {
-        return new MonitoredPackage(name, durationMs, healthCheckDurationMs,
-                hasPassedHealthCheck, mitigationCalls);
-    }
-
-    MonitoredPackage parseMonitoredPackage(TypedXmlPullParser parser)
-            throws XmlPullParserException {
-        String packageName = parser.getAttributeValue(null, ATTR_NAME);
-        long duration = parser.getAttributeLong(null, ATTR_DURATION);
-        long healthCheckDuration = parser.getAttributeLong(null,
-                        ATTR_EXPLICIT_HEALTH_CHECK_DURATION);
-        boolean hasPassedHealthCheck = parser.getAttributeBoolean(null, ATTR_PASSED_HEALTH_CHECK);
-        LongArrayQueue mitigationCalls = parseLongArrayQueue(
-                parser.getAttributeValue(null, ATTR_MITIGATION_CALLS));
-        return newMonitoredPackage(packageName,
-                duration, healthCheckDuration, hasPassedHealthCheck, mitigationCalls);
-    }
-
-    /**
-     * Represents a package and its health check state along with the time
-     * it should be monitored for.
-     *
-     * <p> Note, the PackageWatchdog#mLock must always be held when reading or writing
-     * instances of this class.
-     */
-    class MonitoredPackage {
-        private final String mPackageName;
-        // Times when package failures happen sorted in ascending order
-        @GuardedBy("mLock")
-        private final LongArrayQueue mFailureHistory = new LongArrayQueue();
-        // Times when an observer was called to mitigate this package's failure. Sorted in
-        // ascending order.
-        @GuardedBy("mLock")
-        private final LongArrayQueue mMitigationCalls;
-        // One of STATE_[ACTIVE|INACTIVE|PASSED|FAILED]. Updated on construction and after
-        // methods that could change the health check state: handleElapsedTimeLocked and
-        // tryPassHealthCheckLocked
-        private int mHealthCheckState = HealthCheckState.INACTIVE;
-        // Whether an explicit health check has passed.
-        // This value in addition with mHealthCheckDurationMs determines the health check state
-        // of the package, see #getHealthCheckStateLocked
-        @GuardedBy("mLock")
-        private boolean mHasPassedHealthCheck;
-        // System uptime duration to monitor package.
-        @GuardedBy("mLock")
-        private long mDurationMs;
-        // System uptime duration to check the result of an explicit health check
-        // Initially, MAX_VALUE until we get a value from the health check service
-        // and request health checks.
-        // This value in addition with mHasPassedHealthCheck determines the health check state
-        // of the package, see #getHealthCheckStateLocked
-        @GuardedBy("mLock")
-        private long mHealthCheckDurationMs = Long.MAX_VALUE;
-
-        MonitoredPackage(String packageName, long durationMs,
-                long healthCheckDurationMs, boolean hasPassedHealthCheck,
-                LongArrayQueue mitigationCalls) {
-            mPackageName = packageName;
-            mDurationMs = durationMs;
-            mHealthCheckDurationMs = healthCheckDurationMs;
-            mHasPassedHealthCheck = hasPassedHealthCheck;
-            mMitigationCalls = mitigationCalls;
-            updateHealthCheckStateLocked();
-        }
-
-        /** Writes the salient fields to disk using {@code out}. */
-        @GuardedBy("mLock")
-        public void writeLocked(TypedXmlSerializer out) throws IOException {
-            out.startTag(null, TAG_PACKAGE);
-            out.attribute(null, ATTR_NAME, getName());
-            out.attributeLong(null, ATTR_DURATION, mDurationMs);
-            out.attributeLong(null, ATTR_EXPLICIT_HEALTH_CHECK_DURATION, mHealthCheckDurationMs);
-            out.attributeBoolean(null, ATTR_PASSED_HEALTH_CHECK, mHasPassedHealthCheck);
-            LongArrayQueue normalizedCalls = normalizeMitigationCalls();
-            out.attribute(null, ATTR_MITIGATION_CALLS, longArrayQueueToString(normalizedCalls));
-            out.endTag(null, TAG_PACKAGE);
-        }
-
-        /**
-         * Increment package failures or resets failure count depending on the last package failure.
-         *
-         * @return {@code true} if failure count exceeds a threshold, {@code false} otherwise
-         */
-        @GuardedBy("mLock")
-        public boolean onFailureLocked() {
-            // Sliding window algorithm: find out if there exists a window containing failures >=
-            // mTriggerFailureCount.
-            final long now = mSystemClock.uptimeMillis();
-            mFailureHistory.addLast(now);
-            while (now - mFailureHistory.peekFirst() > mTriggerFailureDurationMs) {
-                // Prune values falling out of the window
-                mFailureHistory.removeFirst();
-            }
-            boolean failed = mFailureHistory.size() >= mTriggerFailureCount;
-            if (failed) {
-                mFailureHistory.clear();
-            }
-            return failed;
-        }
-
-        /**
-         * Notes the timestamp of a mitigation call into the observer.
-         */
-        @GuardedBy("mLock")
-        public void noteMitigationCallLocked() {
-            mMitigationCalls.addLast(mSystemClock.uptimeMillis());
-        }
-
-        /**
-         * Prunes any mitigation calls outside of the de-escalation window, and returns the
-         * number of calls that are in the window afterwards.
-         *
-         * @return the number of mitigation calls made in the de-escalation window.
-         */
-        @GuardedBy("mLock")
-        public int getMitigationCountLocked() {
-            try {
-                final long now = mSystemClock.uptimeMillis();
-                while (now - mMitigationCalls.peekFirst() > DEFAULT_DEESCALATION_WINDOW_MS) {
-                    mMitigationCalls.removeFirst();
-                }
-            } catch (NoSuchElementException ignore) {
-            }
-
-            return mMitigationCalls.size();
-        }
-
-        /**
-         * Before writing to disk, make the mitigation call timestamps relative to the current
-         * system uptime. This is because they need to be relative to the uptime which will reset
-         * at the next boot.
-         *
-         * @return a LongArrayQueue of the mitigation calls relative to the current system uptime.
-         */
-        @GuardedBy("mLock")
-        public LongArrayQueue normalizeMitigationCalls() {
-            LongArrayQueue normalized = new LongArrayQueue();
-            final long now = mSystemClock.uptimeMillis();
-            for (int i = 0; i < mMitigationCalls.size(); i++) {
-                normalized.addLast(mMitigationCalls.get(i) - now);
-            }
-            return normalized;
-        }
-
-        /**
-         * Sets the initial health check duration.
-         *
-         * @return the new health check state
-         */
-        @GuardedBy("mLock")
-        public int setHealthCheckActiveLocked(long initialHealthCheckDurationMs) {
-            if (initialHealthCheckDurationMs <= 0) {
-                Slog.wtf(TAG, "Cannot set non-positive health check duration "
-                        + initialHealthCheckDurationMs + "ms for package " + getName()
-                        + ". Using total duration " + mDurationMs + "ms instead");
-                initialHealthCheckDurationMs = mDurationMs;
-            }
-            if (mHealthCheckState == HealthCheckState.INACTIVE) {
-                // Transitions to ACTIVE
-                mHealthCheckDurationMs = initialHealthCheckDurationMs;
-            }
-            return updateHealthCheckStateLocked();
-        }
-
-        /**
-         * Updates the monitoring durations of the package.
-         *
-         * @return the new health check state
-         */
-        @GuardedBy("mLock")
-        public int handleElapsedTimeLocked(long elapsedMs) {
-            if (elapsedMs <= 0) {
-                Slog.w(TAG, "Cannot handle non-positive elapsed time for package " + getName());
-                return mHealthCheckState;
-            }
-            // Transitions to FAILED if now <= 0 and health check not passed
-            mDurationMs -= elapsedMs;
-            if (mHealthCheckState == HealthCheckState.ACTIVE) {
-                // We only update health check durations if we have #setHealthCheckActiveLocked
-                // This ensures we don't leave the INACTIVE state for an unexpected elapsed time
-                // Transitions to FAILED if now <= 0 and health check not passed
-                mHealthCheckDurationMs -= elapsedMs;
-            }
-            return updateHealthCheckStateLocked();
-        }
-
-        /** Explicitly update the monitoring duration of the package. */
-        @GuardedBy("mLock")
-        public void updateHealthCheckDuration(long newDurationMs) {
-            mDurationMs = newDurationMs;
-        }
-
-        /**
-         * Marks the health check as passed and transitions to {@link HealthCheckState.PASSED}
-         * if not yet {@link HealthCheckState.FAILED}.
-         *
-         * @return the new {@link HealthCheckState health check state}
-         */
-        @GuardedBy("mLock")
-        @HealthCheckState
-        public int tryPassHealthCheckLocked() {
-            if (mHealthCheckState != HealthCheckState.FAILED) {
-                // FAILED is a final state so only pass if we haven't failed
-                // Transition to PASSED
-                mHasPassedHealthCheck = true;
-            }
-            return updateHealthCheckStateLocked();
-        }
-
-        /** Returns the monitored package name. */
-        private String getName() {
-            return mPackageName;
-        }
-
-        /**
-         * Returns the current {@link HealthCheckState health check state}.
-         */
-        @GuardedBy("mLock")
-        @HealthCheckState
-        public int getHealthCheckStateLocked() {
-            return mHealthCheckState;
-        }
-
-        /**
-         * Returns the shortest duration before the package should be scheduled for a prune.
-         *
-         * @return the duration or {@link Long#MAX_VALUE} if the package should not be scheduled
-         */
-        @GuardedBy("mLock")
-        public long getShortestScheduleDurationMsLocked() {
-            // Consider health check duration only if #isPendingHealthChecksLocked is true
-            return Math.min(toPositive(mDurationMs),
-                    isPendingHealthChecksLocked()
-                    ? toPositive(mHealthCheckDurationMs) : Long.MAX_VALUE);
-        }
-
-        /**
-         * Returns {@code true} if the total duration left to monitor the package is less than or
-         * equal to 0 {@code false} otherwise.
-         */
-        @GuardedBy("mLock")
-        public boolean isExpiredLocked() {
-            return mDurationMs <= 0;
-        }
-
-        /**
-         * Returns {@code true} if the package, {@link #getName} is expecting health check results
-         * {@code false} otherwise.
-         */
-        @GuardedBy("mLock")
-        public boolean isPendingHealthChecksLocked() {
-            return mHealthCheckState == HealthCheckState.ACTIVE
-                    || mHealthCheckState == HealthCheckState.INACTIVE;
-        }
-
-        /**
-         * Updates the health check state based on {@link #mHasPassedHealthCheck}
-         * and {@link #mHealthCheckDurationMs}.
-         *
-         * @return the new {@link HealthCheckState health check state}
-         */
-        @GuardedBy("mLock")
-        @HealthCheckState
-        private int updateHealthCheckStateLocked() {
-            int oldState = mHealthCheckState;
-            if (mHasPassedHealthCheck) {
-                // Set final state first to avoid ambiguity
-                mHealthCheckState = HealthCheckState.PASSED;
-            } else if (mHealthCheckDurationMs <= 0 || mDurationMs <= 0) {
-                // Set final state first to avoid ambiguity
-                mHealthCheckState = HealthCheckState.FAILED;
-            } else if (mHealthCheckDurationMs == Long.MAX_VALUE) {
-                mHealthCheckState = HealthCheckState.INACTIVE;
-            } else {
-                mHealthCheckState = HealthCheckState.ACTIVE;
-            }
-
-            if (oldState != mHealthCheckState) {
-                Slog.i(TAG, "Updated health check state for package " + getName() + ": "
-                        + toString(oldState) + " -> " + toString(mHealthCheckState));
-            }
-            return mHealthCheckState;
-        }
-
-        /** Returns a {@link String} representation of the current health check state. */
-        private String toString(@HealthCheckState int state) {
-            switch (state) {
-                case HealthCheckState.ACTIVE:
-                    return "ACTIVE";
-                case HealthCheckState.INACTIVE:
-                    return "INACTIVE";
-                case HealthCheckState.PASSED:
-                    return "PASSED";
-                case HealthCheckState.FAILED:
-                    return "FAILED";
-                default:
-                    return "UNKNOWN";
-            }
-        }
-
-        /** Returns {@code value} if it is greater than 0 or {@link Long#MAX_VALUE} otherwise. */
-        private long toPositive(long value) {
-            return value > 0 ? value : Long.MAX_VALUE;
-        }
-
-        /** Compares the equality of this object with another {@link MonitoredPackage}. */
-        @VisibleForTesting
-        boolean isEqualTo(MonitoredPackage pkg) {
-            return (getName().equals(pkg.getName()))
-                    && mDurationMs == pkg.mDurationMs
-                    && mHasPassedHealthCheck == pkg.mHasPassedHealthCheck
-                    && mHealthCheckDurationMs == pkg.mHealthCheckDurationMs
-                    && (mMitigationCalls.toString()).equals(pkg.mMitigationCalls.toString());
-        }
-    }
-
-    @GuardedBy("mLock")
-    @SuppressWarnings("GuardedBy")
-    void saveAllObserversBootMitigationCountToMetadata(String filePath) {
-        HashMap<String, Integer> bootMitigationCounts = new HashMap<>();
-        for (int i = 0; i < mAllObservers.size(); i++) {
-            final ObserverInternal observer = mAllObservers.valueAt(i);
-            bootMitigationCounts.put(observer.name, observer.getBootMitigationCount());
-        }
-
-        try {
-            FileOutputStream fileStream = new FileOutputStream(new File(filePath));
-            ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
-            objectStream.writeObject(bootMitigationCounts);
-            objectStream.flush();
-            objectStream.close();
-            fileStream.close();
-        } catch (Exception e) {
-            Slog.i(TAG, "Could not save observers metadata to file: " + e);
-        }
-    }
-
-    /**
-     * Handles the thresholding logic for system server boots.
-     */
-    class BootThreshold {
-
-        private final int mBootTriggerCount;
-        private final long mTriggerWindow;
-        private final int mBootMitigationIncrement;
-
-        BootThreshold(int bootTriggerCount, long triggerWindow) {
-            this(bootTriggerCount, triggerWindow, /*bootMitigationIncrement=*/ 1);
-        }
-
-        BootThreshold(int bootTriggerCount, long triggerWindow, int bootMitigationIncrement) {
-            this.mBootTriggerCount = bootTriggerCount;
-            this.mTriggerWindow = triggerWindow;
-            this.mBootMitigationIncrement = bootMitigationIncrement;
-        }
-
-        public void reset() {
-            setStart(0);
-            setCount(0);
-        }
-
-        protected int getCount() {
-            return CrashRecoveryProperties.rescueBootCount().orElse(0);
-        }
-
-        protected void setCount(int count) {
-            CrashRecoveryProperties.rescueBootCount(count);
-        }
-
-        public long getStart() {
-            return CrashRecoveryProperties.rescueBootStart().orElse(0L);
-        }
-
-        public int getMitigationCount() {
-            return CrashRecoveryProperties.bootMitigationCount().orElse(0);
-        }
-
-        public void setStart(long start) {
-            CrashRecoveryProperties.rescueBootStart(getStartTime(start));
-        }
-
-        public void setMitigationStart(long start) {
-            CrashRecoveryProperties.bootMitigationStart(getStartTime(start));
-        }
-
-        public long getMitigationStart() {
-            return CrashRecoveryProperties.bootMitigationStart().orElse(0L);
-        }
-
-        public void setMitigationCount(int count) {
-            CrashRecoveryProperties.bootMitigationCount(count);
-        }
-
-        private static long constrain(long amount, long low, long high) {
-            return amount < low ? low : (amount > high ? high : amount);
-        }
-
-        public long getStartTime(long start) {
-            final long now = mSystemClock.uptimeMillis();
-            return constrain(start, 0, now);
-        }
-
-        public void saveMitigationCountToMetadata() {
-            try (BufferedWriter writer = new BufferedWriter(new FileWriter(METADATA_FILE))) {
-                writer.write(String.valueOf(getMitigationCount()));
-            } catch (Exception e) {
-                Slog.e(TAG, "Could not save metadata to file: " + e);
-            }
-        }
-
-        public void readMitigationCountFromMetadataIfNecessary() {
-            File bootPropsFile = new File(METADATA_FILE);
-            if (bootPropsFile.exists()) {
-                try (BufferedReader reader = new BufferedReader(new FileReader(METADATA_FILE))) {
-                    String mitigationCount = reader.readLine();
-                    setMitigationCount(Integer.parseInt(mitigationCount));
-                    bootPropsFile.delete();
-                } catch (Exception e) {
-                    Slog.i(TAG, "Could not read metadata file: " + e);
-                }
-            }
-        }
-
-
-        /** Increments the boot counter, and returns whether the device is bootlooping. */
-        @GuardedBy("mLock")
-        public boolean incrementAndTest() {
-            if (Flags.recoverabilityDetection()) {
-                readAllObserversBootMitigationCountIfNecessary(METADATA_FILE);
-            } else {
-                readMitigationCountFromMetadataIfNecessary();
-            }
-            final long now = mSystemClock.uptimeMillis();
-            if (now - getStart() < 0) {
-                Slog.e(TAG, "Window was less than zero. Resetting start to current time.");
-                setStart(now);
-                setMitigationStart(now);
-            }
-            if (now - getMitigationStart() > DEFAULT_DEESCALATION_WINDOW_MS) {
-                setMitigationStart(now);
-                if (Flags.recoverabilityDetection()) {
-                    resetAllObserversBootMitigationCount();
-                } else {
-                    setMitigationCount(0);
-                }
-            }
-            final long window = now - getStart();
-            if (window >= mTriggerWindow) {
-                setCount(1);
-                setStart(now);
-                return false;
-            } else {
-                int count = getCount() + 1;
-                setCount(count);
-                EventLogTags.writeRescueNote(Process.ROOT_UID, count, window);
-                if (Flags.recoverabilityDetection()) {
-                    boolean mitigate = (count >= mBootTriggerCount)
-                            && (count - mBootTriggerCount) % mBootMitigationIncrement == 0;
-                    return mitigate;
-                }
-                return count >= mBootTriggerCount;
-            }
-        }
-
-        @GuardedBy("mLock")
-        private void resetAllObserversBootMitigationCount() {
-            for (int i = 0; i < mAllObservers.size(); i++) {
-                final ObserverInternal observer = mAllObservers.valueAt(i);
-                observer.setBootMitigationCount(0);
-            }
-        }
-
-        @GuardedBy("mLock")
-        @SuppressWarnings("GuardedBy")
-        void readAllObserversBootMitigationCountIfNecessary(String filePath) {
-            File metadataFile = new File(filePath);
-            if (metadataFile.exists()) {
-                try {
-                    FileInputStream fileStream = new FileInputStream(metadataFile);
-                    ObjectInputStream objectStream = new ObjectInputStream(fileStream);
-                    HashMap<String, Integer> bootMitigationCounts =
-                            (HashMap<String, Integer>) objectStream.readObject();
-                    objectStream.close();
-                    fileStream.close();
-
-                    for (int i = 0; i < mAllObservers.size(); i++) {
-                        final ObserverInternal observer = mAllObservers.valueAt(i);
-                        if (bootMitigationCounts.containsKey(observer.name)) {
-                            observer.setBootMitigationCount(
-                                    bootMitigationCounts.get(observer.name));
-                        }
-                    }
-                } catch (Exception e) {
-                    Slog.i(TAG, "Could not read observer metadata file: " + e);
-                }
-            }
-        }
-
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
deleted file mode 100644
index 7093ba4..0000000
--- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static android.provider.DeviceConfig.Properties;
-
-import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.VersionedPackage;
-import android.crashrecovery.flags.Flags;
-import android.os.Build;
-import android.os.Environment;
-import android.os.PowerManager;
-import android.os.RecoverySystem;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.DeviceConfig;
-import android.provider.Settings;
-import android.sysprop.CrashRecoveryProperties;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.Slog;
-import android.utils.ArrayUtils;
-import android.utils.FileUtils;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.PackageWatchdog.FailureReasons;
-import com.android.server.PackageWatchdog.PackageHealthObserver;
-import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
-import com.android.server.am.SettingsToPropertiesMapper;
-import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
-
-import java.io.File;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Utilities to help rescue the system from crash loops. Callers are expected to
- * report boot events and persistent app crashes, and if they happen frequently
- * enough this class will slowly escalate through several rescue operations
- * before finally rebooting and prompting the user if they want to wipe data as
- * a last resort.
- *
- * @hide
- */
-public class RescueParty {
-    @VisibleForTesting
-    static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
-    @VisibleForTesting
-    static final int LEVEL_NONE = 0;
-    @VisibleForTesting
-    static final int LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 1;
-    @VisibleForTesting
-    static final int LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 2;
-    @VisibleForTesting
-    static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
-    @VisibleForTesting
-    static final int LEVEL_WARM_REBOOT = 4;
-    @VisibleForTesting
-    static final int LEVEL_FACTORY_RESET = 5;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_NONE = 0;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET = 1;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET = 2;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_WARM_REBOOT = 3;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 4;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 5;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 6;
-    @VisibleForTesting
-    static final int RESCUE_LEVEL_FACTORY_RESET = 7;
-
-    @IntDef(prefix = { "RESCUE_LEVEL_" }, value = {
-        RESCUE_LEVEL_NONE,
-        RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET,
-        RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET,
-        RESCUE_LEVEL_WARM_REBOOT,
-        RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
-        RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
-        RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
-        RESCUE_LEVEL_FACTORY_RESET
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    @interface RescueLevels {}
-
-    @VisibleForTesting
-    static final String RESCUE_NON_REBOOT_LEVEL_LIMIT = "persist.sys.rescue_non_reboot_level_limit";
-    @VisibleForTesting
-    static final int DEFAULT_RESCUE_NON_REBOOT_LEVEL_LIMIT = RESCUE_LEVEL_WARM_REBOOT - 1;
-    @VisibleForTesting
-    static final String TAG = "RescueParty";
-    @VisibleForTesting
-    static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2);
-    @VisibleForTesting
-    static final int DEVICE_CONFIG_RESET_MODE = Settings.RESET_MODE_TRUSTED_DEFAULTS;
-    // The DeviceConfig namespace containing all RescueParty switches.
-    @VisibleForTesting
-    static final String NAMESPACE_CONFIGURATION = "configuration";
-    @VisibleForTesting
-    static final String NAMESPACE_TO_PACKAGE_MAPPING_FLAG =
-            "namespace_to_package_mapping";
-    @VisibleForTesting
-    static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 10;
-
-    private static final String NAME = "rescue-party-observer";
-
-    private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
-    private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device";
-    private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
-            "persist.device_config.configuration.disable_rescue_party";
-    private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
-            "persist.device_config.configuration.disable_rescue_party_factory_reset";
-    private static final String PROP_THROTTLE_DURATION_MIN_FLAG =
-            "persist.device_config.configuration.rescue_party_throttle_duration_min";
-
-    private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
-            | ApplicationInfo.FLAG_SYSTEM;
-
-    /** Register the Rescue Party observer as a Package Watchdog health observer */
-    public static void registerHealthObserver(Context context) {
-        PackageWatchdog.getInstance(context).registerHealthObserver(
-                RescuePartyObserver.getInstance(context));
-    }
-
-    private static boolean isDisabled() {
-        // Check if we're explicitly enabled for testing
-        if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, false)) {
-            return false;
-        }
-
-        // We're disabled if the DeviceConfig disable flag is set to true.
-        // This is in case that an emergency rollback of the feature is needed.
-        if (SystemProperties.getBoolean(PROP_DEVICE_CONFIG_DISABLE_FLAG, false)) {
-            Slog.v(TAG, "Disabled because of DeviceConfig flag");
-            return true;
-        }
-
-        // We're disabled on all engineering devices
-        if (Build.TYPE.equals("eng")) {
-            Slog.v(TAG, "Disabled because of eng build");
-            return true;
-        }
-
-        // We're disabled on userdebug devices connected over USB, since that's
-        // a decent signal that someone is actively trying to debug the device,
-        // or that it's in a lab environment.
-        if (Build.TYPE.equals("userdebug") && isUsbActive()) {
-            Slog.v(TAG, "Disabled because of active USB connection");
-            return true;
-        }
-
-        // One last-ditch check
-        if (SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false)) {
-            Slog.v(TAG, "Disabled because of manual property");
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Check if we're currently attempting to reboot for a factory reset. This method must
-     * return true if RescueParty tries to reboot early during a boot loop, since the device
-     * will not be fully booted at this time.
-     */
-    public static boolean isRecoveryTriggeredReboot() {
-        return isFactoryResetPropertySet() || isRebootPropertySet();
-    }
-
-    static boolean isFactoryResetPropertySet() {
-        return CrashRecoveryProperties.attemptingFactoryReset().orElse(false);
-    }
-
-    static boolean isRebootPropertySet() {
-        return CrashRecoveryProperties.attemptingReboot().orElse(false);
-    }
-
-    protected static long getLastFactoryResetTimeMs() {
-        return CrashRecoveryProperties.lastFactoryResetTimeMs().orElse(0L);
-    }
-
-    protected static int getMaxRescueLevelAttempted() {
-        return CrashRecoveryProperties.maxRescueLevelAttempted().orElse(LEVEL_NONE);
-    }
-
-    protected static void setFactoryResetProperty(boolean value) {
-        CrashRecoveryProperties.attemptingFactoryReset(value);
-    }
-    protected static void setRebootProperty(boolean value) {
-        CrashRecoveryProperties.attemptingReboot(value);
-    }
-
-    protected static void setLastFactoryResetTimeMs(long value) {
-        CrashRecoveryProperties.lastFactoryResetTimeMs(value);
-    }
-
-    protected static void setMaxRescueLevelAttempted(int level) {
-        CrashRecoveryProperties.maxRescueLevelAttempted(level);
-    }
-
-    /**
-     * Called when {@code SettingsProvider} has been published, which is a good
-     * opportunity to reset any settings depending on our rescue level.
-     */
-    public static void onSettingsProviderPublished(Context context) {
-        handleNativeRescuePartyResets();
-        ContentResolver contentResolver = context.getContentResolver();
-        DeviceConfig.setMonitorCallback(
-                contentResolver,
-                Executors.newSingleThreadExecutor(),
-                new RescuePartyMonitorCallback(context));
-    }
-
-
-    /**
-     * Called when {@code RollbackManager} performs Mainline module rollbacks,
-     * to avoid rolled back modules consuming flag values only expected to work
-     * on modules of newer versions.
-     */
-    public static void resetDeviceConfigForPackages(List<String> packageNames) {
-        if (packageNames == null) {
-            return;
-        }
-        Set<String> namespacesToReset = new ArraySet<String>();
-        Iterator<String> it = packageNames.iterator();
-        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated();
-        // Get runtime package to namespace mapping if created.
-        if (rescuePartyObserver != null) {
-            while (it.hasNext()) {
-                String packageName = it.next();
-                Set<String> runtimeAffectedNamespaces =
-                        rescuePartyObserver.getAffectedNamespaceSet(packageName);
-                if (runtimeAffectedNamespaces != null) {
-                    namespacesToReset.addAll(runtimeAffectedNamespaces);
-                }
-            }
-        }
-        // Get preset package to namespace mapping if created.
-        Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages(
-                packageNames);
-        if (presetAffectedNamespaces != null) {
-            namespacesToReset.addAll(presetAffectedNamespaces);
-        }
-
-        // Clear flags under the namespaces mapped to these packages.
-        // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set.
-        Iterator<String> namespaceIt = namespacesToReset.iterator();
-        while (namespaceIt.hasNext()) {
-            String namespaceToReset = namespaceIt.next();
-            Properties properties = new Properties.Builder(namespaceToReset).build();
-            try {
-                if (!DeviceConfig.setProperties(properties)) {
-                    logCriticalInfo(Log.ERROR, "Failed to clear properties under "
-                            + namespaceToReset
-                            + ". Running `device_config get_sync_disabled_for_tests` will confirm"
-                            + " if config-bulk-update is enabled.");
-                }
-            } catch (DeviceConfig.BadConfigException exception) {
-                logCriticalInfo(Log.WARN, "namespace " + namespaceToReset
-                        + " is already banned, skip reset.");
-            }
-        }
-    }
-
-    private static Set<String> getPresetNamespacesForPackages(List<String> packageNames) {
-        Set<String> resultSet = new ArraySet<String>();
-        try {
-            String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION,
-                    NAMESPACE_TO_PACKAGE_MAPPING_FLAG, "");
-            String[] mappingEntries = flagVal.split(",");
-            for (int i = 0; i < mappingEntries.length; i++) {
-                if (TextUtils.isEmpty(mappingEntries[i])) {
-                    continue;
-                }
-                String[] splittedEntry = mappingEntries[i].split(":");
-                if (splittedEntry.length != 2) {
-                    throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]);
-                }
-                String namespace = splittedEntry[0];
-                String packageName = splittedEntry[1];
-
-                if (packageNames.contains(packageName)) {
-                    resultSet.add(namespace);
-                }
-            }
-        } catch (Exception e) {
-            resultSet.clear();
-            Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e);
-        } finally {
-            return resultSet;
-        }
-    }
-
-    @VisibleForTesting
-    static long getElapsedRealtime() {
-        return SystemClock.elapsedRealtime();
-    }
-
-    private static class RescuePartyMonitorCallback implements DeviceConfig.MonitorCallback {
-        Context mContext;
-
-        RescuePartyMonitorCallback(Context context) {
-            this.mContext = context;
-        }
-
-        public void onNamespaceUpdate(@NonNull String updatedNamespace) {
-            startObservingPackages(mContext, updatedNamespace);
-        }
-
-        public void onDeviceConfigAccess(@NonNull String callingPackage,
-                @NonNull String namespace) {
-            RescuePartyObserver.getInstance(mContext).recordDeviceConfigAccess(
-                            callingPackage,
-                            namespace);
-        }
-    }
-
-    private static void startObservingPackages(Context context, @NonNull String updatedNamespace) {
-        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
-        Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet(updatedNamespace);
-        if (callingPackages == null) {
-            return;
-        }
-        List<String> callingPackageList = new ArrayList<>();
-        callingPackageList.addAll(callingPackages);
-        Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
-                + updatedNamespace);
-        PackageWatchdog.getInstance(context).startObservingHealth(
-                rescuePartyObserver,
-                callingPackageList,
-                DEFAULT_OBSERVING_DURATION_MS);
-    }
-
-    private static void handleNativeRescuePartyResets() {
-        if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
-            String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories();
-            for (int i = 0; i < resetNativeCategories.length; i++) {
-                // Don't let RescueParty reset the namespace for RescueParty switches.
-                if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) {
-                    continue;
-                }
-                DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE,
-                        resetNativeCategories[i]);
-            }
-        }
-    }
-
-    private static int getMaxRescueLevel(boolean mayPerformReboot) {
-        if (Flags.recoverabilityDetection()) {
-            if (!mayPerformReboot
-                    || SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
-                return SystemProperties.getInt(RESCUE_NON_REBOOT_LEVEL_LIMIT,
-                        DEFAULT_RESCUE_NON_REBOOT_LEVEL_LIMIT);
-            }
-            return RESCUE_LEVEL_FACTORY_RESET;
-        } else {
-            if (!mayPerformReboot
-                    || SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
-                return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
-            }
-            return LEVEL_FACTORY_RESET;
-        }
-    }
-
-    /**
-     * Get the rescue level to perform if this is the n-th attempt at mitigating failure.
-     *
-     * @param mitigationCount: the mitigation attempt number (1 = first attempt etc.)
-     * @param mayPerformReboot: whether or not a reboot and factory reset may be performed
-     *                          for the given failure.
-     * @return the rescue level for the n-th mitigation attempt.
-     */
-    private static int getRescueLevel(int mitigationCount, boolean mayPerformReboot) {
-        if (mitigationCount == 1) {
-            return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
-        } else if (mitigationCount == 2) {
-            return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES;
-        } else if (mitigationCount == 3) {
-            return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
-        } else if (mitigationCount == 4) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT);
-        } else if (mitigationCount >= 5) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET);
-        } else {
-            Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
-            return LEVEL_NONE;
-        }
-    }
-
-    /**
-     * Get the rescue level to perform if this is the n-th attempt at mitigating failure.
-     * When failedPackage is null then 1st and 2nd mitigation counts are redundant (scoped and
-     * all device config reset). Behaves as if one mitigation attempt was already done.
-     *
-     * @param mitigationCount the mitigation attempt number (1 = first attempt etc.).
-     * @param mayPerformReboot whether or not a reboot and factory reset may be performed
-     * for the given failure.
-     * @param failedPackage in case of bootloop this is null.
-     * @return the rescue level for the n-th mitigation attempt.
-     */
-    private static @RescueLevels int getRescueLevel(int mitigationCount, boolean mayPerformReboot,
-            @Nullable VersionedPackage failedPackage) {
-        // Skipping RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET since it's not defined without a failed
-        // package.
-        if (failedPackage == null && mitigationCount > 0) {
-            mitigationCount += 1;
-        }
-        if (mitigationCount == 1) {
-            return RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET;
-        } else if (mitigationCount == 2) {
-            return RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET;
-        } else if (mitigationCount == 3) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_WARM_REBOOT);
-        } else if (mitigationCount == 4) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot),
-                                RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS);
-        } else if (mitigationCount == 5) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot),
-                                RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES);
-        } else if (mitigationCount == 6) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot),
-                                RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS);
-        } else if (mitigationCount >= 7) {
-            return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_FACTORY_RESET);
-        } else {
-            return RESCUE_LEVEL_NONE;
-        }
-    }
-
-    private static void executeRescueLevel(Context context, @Nullable String failedPackage,
-            int level) {
-        Slog.w(TAG, "Attempting rescue level " + levelToString(level));
-        try {
-            executeRescueLevelInternal(context, level, failedPackage);
-            EventLogTags.writeRescueSuccess(level);
-            String successMsg = "Finished rescue level " + levelToString(level);
-            if (!TextUtils.isEmpty(failedPackage)) {
-                successMsg += " for package " + failedPackage;
-            }
-            logCriticalInfo(Log.DEBUG, successMsg);
-        } catch (Throwable t) {
-            logRescueException(level, failedPackage, t);
-        }
-    }
-
-    private static void executeRescueLevelInternal(Context context, int level, @Nullable
-            String failedPackage) throws Exception {
-        if (Flags.recoverabilityDetection()) {
-            executeRescueLevelInternalNew(context, level, failedPackage);
-        } else {
-            executeRescueLevelInternalOld(context, level, failedPackage);
-        }
-    }
-
-    private static void executeRescueLevelInternalOld(Context context, int level, @Nullable
-            String failedPackage) throws Exception {
-
-        if (level <= LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS) {
-            // Disabling flag resets on master branch for trunk stable launch.
-            // TODO(b/287618292): Re-enable them after the trunk stable is launched and we
-            // figured out a way to reset flags without interfering with trunk development.
-            return;
-        }
-
-        CrashRecoveryStatsLog.write(CrashRecoveryStatsLog.RESCUE_PARTY_RESET_REPORTED,
-                level, levelToString(level));
-        // Try our best to reset all settings possible, and once finished
-        // rethrow any exception that we encountered
-        Exception res = null;
-        switch (level) {
-            case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                try {
-                    resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS,
-                            level);
-                } catch (Exception e) {
-                    res = e;
-                }
-                try {
-                    resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
-                } catch (Exception e) {
-                    res = e;
-                }
-                break;
-            case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                try {
-                    resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES,
-                            level);
-                } catch (Exception e) {
-                    res = e;
-                }
-                try {
-                    resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
-                } catch (Exception e) {
-                    res = e;
-                }
-                break;
-            case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                try {
-                    resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS,
-                            level);
-                } catch (Exception e) {
-                    res = e;
-                }
-                try {
-                    resetDeviceConfig(context, /*isScoped=*/false, failedPackage);
-                } catch (Exception e) {
-                    res = e;
-                }
-                break;
-            case LEVEL_WARM_REBOOT:
-                executeWarmReboot(context, level, failedPackage);
-                break;
-            case LEVEL_FACTORY_RESET:
-                // Before the completion of Reboot, if any crash happens then PackageWatchdog
-                // escalates to next level i.e. factory reset, as they happen in separate threads.
-                // Adding a check to prevent factory reset to execute before above reboot completes.
-                // Note: this reboot property is not persistent resets after reboot is completed.
-                if (isRebootPropertySet()) {
-                    return;
-                }
-                executeFactoryReset(context, level, failedPackage);
-                break;
-        }
-
-        if (res != null) {
-            throw res;
-        }
-    }
-
-    private static void executeRescueLevelInternalNew(Context context, @RescueLevels int level,
-            @Nullable String failedPackage) throws Exception {
-        CrashRecoveryStatsLog.write(CrashRecoveryStatsLog.RESCUE_PARTY_RESET_REPORTED,
-                level, levelToString(level));
-        switch (level) {
-            case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
-                // Temporary disable deviceConfig reset
-                // resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
-                break;
-            case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
-                // Temporary disable deviceConfig reset
-                // resetDeviceConfig(context, /*isScoped=*/false, failedPackage);
-                break;
-            case RESCUE_LEVEL_WARM_REBOOT:
-                executeWarmReboot(context, level, failedPackage);
-                break;
-            case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS, level);
-                break;
-            case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES, level);
-                break;
-            case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, level);
-                break;
-            case RESCUE_LEVEL_FACTORY_RESET:
-                // Before the completion of Reboot, if any crash happens then PackageWatchdog
-                // escalates to next level i.e. factory reset, as they happen in separate threads.
-                // Adding a check to prevent factory reset to execute before above reboot completes.
-                // Note: this reboot property is not persistent resets after reboot is completed.
-                if (isRebootPropertySet()) {
-                    return;
-                }
-                executeFactoryReset(context, level, failedPackage);
-                break;
-        }
-    }
-
-    private static void executeWarmReboot(Context context, int level,
-            @Nullable String failedPackage) {
-        // Request the reboot from a separate thread to avoid deadlock on PackageWatchdog
-        // when device shutting down.
-        setRebootProperty(true);
-        Runnable runnable = () -> {
-            try {
-                PowerManager pm = context.getSystemService(PowerManager.class);
-                if (pm != null) {
-                    pm.reboot(TAG);
-                }
-            } catch (Throwable t) {
-                logRescueException(level, failedPackage, t);
-            }
-        };
-        Thread thread = new Thread(runnable);
-        thread.start();
-    }
-
-    private static void executeFactoryReset(Context context, int level,
-            @Nullable String failedPackage) {
-        setFactoryResetProperty(true);
-        long now = System.currentTimeMillis();
-        setLastFactoryResetTimeMs(now);
-        Runnable runnable = new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    RecoverySystem.rebootPromptAndWipeUserData(context, TAG);
-                } catch (Throwable t) {
-                    logRescueException(level, failedPackage, t);
-                }
-            }
-        };
-        Thread thread = new Thread(runnable);
-        thread.start();
-    }
-
-
-    private static String getCompleteMessage(Throwable t) {
-        final StringBuilder builder = new StringBuilder();
-        builder.append(t.getMessage());
-        while ((t = t.getCause()) != null) {
-            builder.append(": ").append(t.getMessage());
-        }
-        return builder.toString();
-    }
-
-    private static void logRescueException(int level, @Nullable String failedPackageName,
-            Throwable t) {
-        final String msg = getCompleteMessage(t);
-        EventLogTags.writeRescueFailure(level, msg);
-        String failureMsg = "Failed rescue level " + levelToString(level);
-        if (!TextUtils.isEmpty(failedPackageName)) {
-            failureMsg += " for package " + failedPackageName;
-        }
-        logCriticalInfo(Log.ERROR, failureMsg + ": " + msg);
-    }
-
-    private static int mapRescueLevelToUserImpact(int rescueLevel) {
-        if (Flags.recoverabilityDetection()) {
-            switch (rescueLevel) {
-                case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_10;
-                case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_20;
-                case RESCUE_LEVEL_WARM_REBOOT:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_50;
-                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_71;
-                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_75;
-                case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_80;
-                case RESCUE_LEVEL_FACTORY_RESET:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
-                default:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
-            }
-        } else {
-            switch (rescueLevel) {
-                case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_10;
-                case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                case LEVEL_WARM_REBOOT:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_50;
-                case LEVEL_FACTORY_RESET:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
-                default:
-                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
-            }
-        }
-    }
-
-    private static void resetAllSettingsIfNecessary(Context context, int mode,
-            int level) throws Exception {
-        // No need to reset Settings again if they are already reset in the current level once.
-        if (getMaxRescueLevelAttempted() >= level) {
-            return;
-        }
-        setMaxRescueLevelAttempted(level);
-        // Try our best to reset all settings possible, and once finished
-        // rethrow any exception that we encountered
-        Exception res = null;
-        final ContentResolver resolver = context.getContentResolver();
-        try {
-            Settings.Global.resetToDefaultsAsUser(resolver, null, mode,
-                    UserHandle.SYSTEM.getIdentifier());
-        } catch (Exception e) {
-            res = new RuntimeException("Failed to reset global settings", e);
-        }
-        for (int userId : getAllUserIds()) {
-            try {
-                Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
-            } catch (Exception e) {
-                res = new RuntimeException("Failed to reset secure settings for " + userId, e);
-            }
-        }
-        if (res != null) {
-            throw res;
-        }
-    }
-
-    private static void resetDeviceConfig(Context context, boolean isScoped,
-            @Nullable String failedPackage) throws Exception {
-        final ContentResolver resolver = context.getContentResolver();
-        try {
-            if (!isScoped || failedPackage == null) {
-                resetAllAffectedNamespaces(context);
-            } else {
-                performScopedReset(context, failedPackage);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to reset config settings", e);
-        }
-    }
-
-    private static void resetAllAffectedNamespaces(Context context) {
-        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
-        Set<String> allAffectedNamespaces = rescuePartyObserver.getAllAffectedNamespaceSet();
-
-        Slog.w(TAG,
-                "Performing reset for all affected namespaces: "
-                        + Arrays.toString(allAffectedNamespaces.toArray()));
-        Iterator<String> it = allAffectedNamespaces.iterator();
-        while (it.hasNext()) {
-            String namespace = it.next();
-            // Don't let RescueParty reset the namespace for RescueParty switches.
-            if (NAMESPACE_CONFIGURATION.equals(namespace)) {
-                continue;
-            }
-            DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE, namespace);
-        }
-    }
-
-    private static void performScopedReset(Context context, @NonNull String failedPackage) {
-        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
-        Set<String> affectedNamespaces = rescuePartyObserver.getAffectedNamespaceSet(
-                failedPackage);
-        // If we can't find namespaces affected for current package,
-        // skip this round of reset.
-        if (affectedNamespaces != null) {
-            Slog.w(TAG,
-                    "Performing scoped reset for package: " + failedPackage
-                            + ", affected namespaces: "
-                            + Arrays.toString(affectedNamespaces.toArray()));
-            Iterator<String> it = affectedNamespaces.iterator();
-            while (it.hasNext()) {
-                String namespace = it.next();
-                // Don't let RescueParty reset the namespace for RescueParty switches.
-                if (NAMESPACE_CONFIGURATION.equals(namespace)) {
-                    continue;
-                }
-                DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE, namespace);
-            }
-        }
-    }
-
-    /**
-     * Handle mitigation action for package failures. This observer will be register to Package
-     * Watchdog and will receive calls about package failures. This observer is persistent so it
-     * may choose to mitigate failures for packages it has not explicitly asked to observe.
-     */
-    public static class RescuePartyObserver implements PackageHealthObserver {
-
-        private final Context mContext;
-        private final Map<String, Set<String>> mCallingPackageNamespaceSetMap = new HashMap<>();
-        private final Map<String, Set<String>> mNamespaceCallingPackageSetMap = new HashMap<>();
-
-        @GuardedBy("RescuePartyObserver.class")
-        static RescuePartyObserver sRescuePartyObserver;
-
-        private RescuePartyObserver(Context context) {
-            mContext = context;
-        }
-
-        /** Creates or gets singleton instance of RescueParty. */
-        public static RescuePartyObserver getInstance(Context context) {
-            synchronized (RescuePartyObserver.class) {
-                if (sRescuePartyObserver == null) {
-                    sRescuePartyObserver = new RescuePartyObserver(context);
-                }
-                return sRescuePartyObserver;
-            }
-        }
-
-        /** Gets singleton instance. It returns null if the instance is not created yet.*/
-        @Nullable
-        public static RescuePartyObserver getInstanceIfCreated() {
-            synchronized (RescuePartyObserver.class) {
-                return sRescuePartyObserver;
-            }
-        }
-
-        @VisibleForTesting
-        static void reset() {
-            synchronized (RescuePartyObserver.class) {
-                sRescuePartyObserver = null;
-            }
-        }
-
-        @Override
-        public int onHealthCheckFailed(@Nullable VersionedPackage failedPackage,
-                @FailureReasons int failureReason, int mitigationCount) {
-            if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
-                    || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) {
-                if (Flags.recoverabilityDetection()) {
-                    return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
-                            mayPerformReboot(failedPackage), failedPackage));
-                } else {
-                    return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
-                        mayPerformReboot(failedPackage)));
-                }
-            } else {
-                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
-            }
-        }
-
-        @Override
-        public boolean execute(@Nullable VersionedPackage failedPackage,
-                @FailureReasons int failureReason, int mitigationCount) {
-            if (isDisabled()) {
-                return false;
-            }
-            if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
-                    || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
-                final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount,
-                        mayPerformReboot(failedPackage), failedPackage)
-                        : getRescueLevel(mitigationCount,
-                                mayPerformReboot(failedPackage));
-                executeRescueLevel(mContext,
-                        failedPackage == null ? null : failedPackage.getPackageName(), level);
-                return true;
-            } else {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean isPersistent() {
-            return true;
-        }
-
-        @Override
-        public boolean mayObservePackage(String packageName) {
-            PackageManager pm = mContext.getPackageManager();
-            try {
-                // A package is a module if this is non-null
-                if (pm.getModuleInfo(packageName, 0) != null) {
-                    return true;
-                }
-            } catch (PackageManager.NameNotFoundException | IllegalStateException ignore) {
-            }
-
-            return isPersistentSystemApp(packageName);
-        }
-
-        @Override
-        public int onBootLoop(int mitigationCount) {
-            if (isDisabled()) {
-                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
-            }
-            if (Flags.recoverabilityDetection()) {
-                return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
-                        true, /*failedPackage=*/ null));
-            } else {
-                return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true));
-            }
-        }
-
-        @Override
-        public boolean executeBootLoopMitigation(int mitigationCount) {
-            if (isDisabled()) {
-                return false;
-            }
-            boolean mayPerformReboot = !shouldThrottleReboot();
-            final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount,
-                        mayPerformReboot, /*failedPackage=*/ null)
-                        : getRescueLevel(mitigationCount, mayPerformReboot);
-            executeRescueLevel(mContext, /*failedPackage=*/ null, level);
-            return true;
-        }
-
-        @Override
-        public String getName() {
-            return NAME;
-        }
-
-        /**
-         * Returns {@code true} if the failing package is non-null and performing a reboot or
-         * prompting a factory reset is an acceptable mitigation strategy for the package's
-         * failure, {@code false} otherwise.
-         */
-        private boolean mayPerformReboot(@Nullable VersionedPackage failingPackage) {
-            if (failingPackage == null) {
-                return false;
-            }
-            if (shouldThrottleReboot())  {
-                return false;
-            }
-
-            return isPersistentSystemApp(failingPackage.getPackageName());
-        }
-
-        /**
-         * Returns {@code true} if Rescue Party is allowed to attempt a reboot or factory reset.
-         * Will return {@code false} if a factory reset was already offered recently.
-         */
-        private boolean shouldThrottleReboot() {
-            Long lastResetTime = getLastFactoryResetTimeMs();
-            long now = System.currentTimeMillis();
-            long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG,
-                    DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN);
-            return now < lastResetTime + TimeUnit.MINUTES.toMillis(throttleDurationMin);
-        }
-
-        private boolean isPersistentSystemApp(@NonNull String packageName) {
-            PackageManager pm = mContext.getPackageManager();
-            try {
-                ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
-                return (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK;
-            } catch (PackageManager.NameNotFoundException e) {
-                return false;
-            }
-        }
-
-        private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage,
-                @NonNull String namespace) {
-            // Record it in calling packages to namespace map
-            Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage);
-            if (namespaceSet == null) {
-                namespaceSet = new ArraySet<>();
-                mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet);
-            }
-            namespaceSet.add(namespace);
-            // Record it in namespace to calling packages map
-            Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace);
-            if (callingPackageSet == null) {
-                callingPackageSet = new ArraySet<>();
-            }
-            callingPackageSet.add(callingPackage);
-            mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet);
-        }
-
-        private synchronized Set<String> getAffectedNamespaceSet(String failedPackage) {
-            return mCallingPackageNamespaceSetMap.get(failedPackage);
-        }
-
-        private synchronized Set<String> getAllAffectedNamespaceSet() {
-            return new HashSet<String>(mNamespaceCallingPackageSetMap.keySet());
-        }
-
-        private synchronized Set<String> getCallingPackagesSet(String namespace) {
-            return mNamespaceCallingPackageSetMap.get(namespace);
-        }
-    }
-
-    private static int[] getAllUserIds() {
-        int systemUserId = UserHandle.SYSTEM.getIdentifier();
-        int[] userIds = { systemUserId };
-        try {
-            for (File file : FileUtils.listFilesOrEmpty(Environment.getDataSystemDeDirectory())) {
-                try {
-                    final int userId = Integer.parseInt(file.getName());
-                    if (userId != systemUserId) {
-                        userIds = ArrayUtils.appendInt(userIds, userId);
-                    }
-                } catch (NumberFormatException ignored) {
-                }
-            }
-        } catch (Throwable t) {
-            Slog.w(TAG, "Trouble discovering users", t);
-        }
-        return userIds;
-    }
-
-    /**
-     * Hacky test to check if the device has an active USB connection, which is
-     * a good proxy for someone doing local development work.
-     */
-    private static boolean isUsbActive() {
-        if (SystemProperties.getBoolean(PROP_VIRTUAL_DEVICE, false)) {
-            Slog.v(TAG, "Assuming virtual device is connected over USB");
-            return true;
-        }
-        try {
-            final String state = FileUtils
-                    .readTextFile(new File("/sys/class/android_usb/android0/state"), 128, "");
-            return "CONFIGURED".equals(state.trim());
-        } catch (Throwable t) {
-            Slog.w(TAG, "Failed to determine if device was on USB", t);
-            return false;
-        }
-    }
-
-    private static String levelToString(int level) {
-        if (Flags.recoverabilityDetection()) {
-            switch (level) {
-                case RESCUE_LEVEL_NONE:
-                    return "NONE";
-                case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
-                    return "SCOPED_DEVICE_CONFIG_RESET";
-                case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
-                    return "ALL_DEVICE_CONFIG_RESET";
-                case RESCUE_LEVEL_WARM_REBOOT:
-                    return "WARM_REBOOT";
-                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                    return "RESET_SETTINGS_UNTRUSTED_DEFAULTS";
-                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                    return "RESET_SETTINGS_UNTRUSTED_CHANGES";
-                case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                    return "RESET_SETTINGS_TRUSTED_DEFAULTS";
-                case RESCUE_LEVEL_FACTORY_RESET:
-                    return "FACTORY_RESET";
-                default:
-                    return Integer.toString(level);
-            }
-        } else {
-            switch (level) {
-                case LEVEL_NONE:
-                    return "NONE";
-                case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                    return "RESET_SETTINGS_UNTRUSTED_DEFAULTS";
-                case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                    return "RESET_SETTINGS_UNTRUSTED_CHANGES";
-                case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                    return "RESET_SETTINGS_TRUSTED_DEFAULTS";
-                case LEVEL_WARM_REBOOT:
-                    return "WARM_REBOOT";
-                case LEVEL_FACTORY_RESET:
-                    return "FACTORY_RESET";
-                default:
-                    return Integer.toString(level);
-            }
-        }
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java b/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java
deleted file mode 100644
index fa4d6af..0000000
--- a/packages/CrashRecovery/services/java/com/android/utils/ArrayUtils.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.File;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Copied over from frameworks/base/core/java/com/android/internal/util/ArrayUtils.java
- *
- * @hide
- */
-public class ArrayUtils {
-    private ArrayUtils() { /* cannot be instantiated */ }
-    public static final File[] EMPTY_FILE = new File[0];
-
-
-    /**
-     * Return first index of {@code value} in {@code array}, or {@code -1} if
-     * not found.
-     */
-    public static <T> int indexOf(@Nullable T[] array, T value) {
-        if (array == null) return -1;
-        for (int i = 0; i < array.length; i++) {
-            if (Objects.equals(array[i], value)) return i;
-        }
-        return -1;
-    }
-
-    /** @hide */
-    public static @NonNull File[] defeatNullable(@Nullable File[] val) {
-        return (val != null) ? val : EMPTY_FILE;
-    }
-
-    /**
-     * Checks if given array is null or has zero elements.
-     */
-    public static boolean isEmpty(@Nullable int[] array) {
-        return array == null || array.length == 0;
-    }
-
-    /**
-     * True if the byte array is null or has length 0.
-     */
-    public static boolean isEmpty(@Nullable byte[] array) {
-        return array == null || array.length == 0;
-    }
-
-    /**
-     * Converts from List of bytes to byte array
-     * @param list
-     * @return byte[]
-     */
-    public static byte[] toPrimitive(List<byte[]> list) {
-        if (list.size() == 0) {
-            return new byte[0];
-        }
-        int byteLen = list.get(0).length;
-        byte[] array = new byte[list.size() * byteLen];
-        for (int i = 0; i < list.size(); i++) {
-            for (int j = 0; j < list.get(i).length; j++) {
-                array[i * byteLen + j] = list.get(i)[j];
-            }
-        }
-        return array;
-    }
-
-    /**
-     * Adds value to given array if not already present, providing set-like
-     * behavior.
-     */
-    public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
-        return appendInt(cur, val, false);
-    }
-
-    /**
-     * Adds value to given array.
-     */
-    public static @NonNull int[] appendInt(@Nullable int[] cur, int val,
-            boolean allowDuplicates) {
-        if (cur == null) {
-            return new int[] { val };
-        }
-        final int n = cur.length;
-        if (!allowDuplicates) {
-            for (int i = 0; i < n; i++) {
-                if (cur[i] == val) {
-                    return cur;
-                }
-            }
-        }
-        int[] ret = new int[n + 1];
-        System.arraycopy(cur, 0, ret, 0, n);
-        ret[n] = val;
-        return ret;
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java b/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java
deleted file mode 100644
index afcf689..0000000
--- a/packages/CrashRecovery/services/java/com/android/utils/BackgroundThread.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *  * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.os.Handler;
-import android.os.HandlerThread;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.concurrent.Executor;
-
-/**
- * Thread for asynchronous event processing. This thread is configured as
- * {@link android.os.Process#THREAD_PRIORITY_BACKGROUND}, which means fewer CPU
- * resources will be dedicated to it, and it will "have less chance of impacting
- * the responsiveness of the user interface."
- * <p>
- * This thread is best suited for tasks that the user is not actively waiting
- * for, or for tasks that the user expects to be executed eventually.
- *
- * @see com.android.internal.os.BackgroundThread
- *
- * TODO: b/326916057 depend on modules-utils-backgroundthread instead
- * @hide
- */
-public final class BackgroundThread extends HandlerThread {
-    private static final Object sLock = new Object();
-
-    @GuardedBy("sLock")
-    private static BackgroundThread sInstance;
-    @GuardedBy("sLock")
-    private static Handler sHandler;
-    @GuardedBy("sLock")
-    private static HandlerExecutor sHandlerExecutor;
-
-    private BackgroundThread() {
-        super(BackgroundThread.class.getName(), android.os.Process.THREAD_PRIORITY_BACKGROUND);
-    }
-
-    @GuardedBy("sLock")
-    private static void ensureThreadLocked() {
-        if (sInstance == null) {
-            sInstance = new BackgroundThread();
-            sInstance.start();
-            sHandler = new Handler(sInstance.getLooper());
-            sHandlerExecutor = new HandlerExecutor(sHandler);
-        }
-    }
-
-    /**
-     * Get the singleton instance of this class.
-     *
-     * @return the singleton instance of this class
-     */
-    @NonNull
-    public static BackgroundThread get() {
-        synchronized (sLock) {
-            ensureThreadLocked();
-            return sInstance;
-        }
-    }
-
-    /**
-     * Get the singleton {@link Handler} for this class.
-     *
-     * @return the singleton {@link Handler} for this class.
-     */
-    @NonNull
-    public static Handler getHandler() {
-        synchronized (sLock) {
-            ensureThreadLocked();
-            return sHandler;
-        }
-    }
-
-    /**
-     * Get the singleton {@link Executor} for this class.
-     *
-     * @return the singleton {@link Executor} for this class.
-     */
-    @NonNull
-    public static Executor getExecutor() {
-        synchronized (sLock) {
-            ensureThreadLocked();
-            return sHandlerExecutor;
-        }
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java b/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java
deleted file mode 100644
index e4923bf..0000000
--- a/packages/CrashRecovery/services/java/com/android/utils/FileUtils.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Bits and pieces copied from hidden API of android.os.FileUtils.
- *
- * @hide
- */
-public class FileUtils {
-    /**
-     * Read a text file into a String, optionally limiting the length.
-     *
-     * @param file     to read (will not seek, so things like /proc files are OK)
-     * @param max      length (positive for head, negative of tail, 0 for no limit)
-     * @param ellipsis to add of the file was truncated (can be null)
-     * @return the contents of the file, possibly truncated
-     * @throws IOException if something goes wrong reading the file
-     * @hide
-     */
-    public static @Nullable String readTextFile(@Nullable File file, @Nullable int max,
-            @Nullable String ellipsis) throws IOException {
-        InputStream input = new FileInputStream(file);
-        // wrapping a BufferedInputStream around it because when reading /proc with unbuffered
-        // input stream, bytes read not equal to buffer size is not necessarily the correct
-        // indication for EOF; but it is true for BufferedInputStream due to its implementation.
-        BufferedInputStream bis = new BufferedInputStream(input);
-        try {
-            long size = file.length();
-            if (max > 0 || (size > 0 && max == 0)) {  // "head" mode: read the first N bytes
-                if (size > 0 && (max == 0 || size < max)) max = (int) size;
-                byte[] data = new byte[max + 1];
-                int length = bis.read(data);
-                if (length <= 0) return "";
-                if (length <= max) return new String(data, 0, length);
-                if (ellipsis == null) return new String(data, 0, max);
-                return new String(data, 0, max) + ellipsis;
-            } else if (max < 0) {  // "tail" mode: keep the last N
-                int len;
-                boolean rolled = false;
-                byte[] last = null;
-                byte[] data = null;
-                do {
-                    if (last != null) rolled = true;
-                    byte[] tmp = last;
-                    last = data;
-                    data = tmp;
-                    if (data == null) data = new byte[-max];
-                    len = bis.read(data);
-                } while (len == data.length);
-
-                if (last == null && len <= 0) return "";
-                if (last == null) return new String(data, 0, len);
-                if (len > 0) {
-                    rolled = true;
-                    System.arraycopy(last, len, last, 0, last.length - len);
-                    System.arraycopy(data, 0, last, last.length - len, len);
-                }
-                if (ellipsis == null || !rolled) return new String(last);
-                return ellipsis + new String(last);
-            } else {  // "cat" mode: size unknown, read it all in streaming fashion
-                ByteArrayOutputStream contents = new ByteArrayOutputStream();
-                int len;
-                byte[] data = new byte[1024];
-                do {
-                    len = bis.read(data);
-                    if (len > 0) contents.write(data, 0, len);
-                } while (len == data.length);
-                return contents.toString();
-            }
-        } finally {
-            bis.close();
-            input.close();
-        }
-    }
-
-    /**
-     * Perform an fsync on the given FileOutputStream. The stream at this
-     * point must be flushed but not yet closed.
-     *
-     * @hide
-     */
-    public static boolean sync(FileOutputStream stream) {
-        try {
-            if (stream != null) {
-                stream.getFD().sync();
-            }
-            return true;
-        } catch (IOException e) {
-        }
-        return false;
-    }
-
-    /**
-     * List the files in the directory or return empty file.
-     *
-     * @hide
-     */
-    public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {
-        return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles())
-            : ArrayUtils.EMPTY_FILE;
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java b/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java
deleted file mode 100644
index fdb15e2..0000000
--- a/packages/CrashRecovery/services/java/com/android/utils/HandlerExecutor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.os.Handler;
-
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
-
-/**
- * An adapter {@link Executor} that posts all executed tasks onto the given
- * {@link Handler}.
- *
- * TODO: b/326916057 depend on modules-utils-backgroundthread instead
- * @hide
- */
-public class HandlerExecutor implements Executor {
-    private final Handler mHandler;
-
-    public HandlerExecutor(@NonNull Handler handler) {
-        mHandler = Objects.requireNonNull(handler);
-    }
-
-    @Override
-    public void execute(Runnable command) {
-        if (!mHandler.post(command)) {
-            throw new RejectedExecutionException(mHandler + " is shutting down");
-        }
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java b/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java
deleted file mode 100644
index 5cdc253..0000000
--- a/packages/CrashRecovery/services/java/com/android/utils/LongArrayQueue.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.utils;
-
-import libcore.util.EmptyArray;
-
-import java.util.NoSuchElementException;
-
-/**
- * Copied from frameworks/base/core/java/android/util/LongArrayQueue.java
- *
- * @hide
- */
-public class LongArrayQueue {
-
-    private long[] mValues;
-    private int mSize;
-    private int mHead;
-    private int mTail;
-
-    private long[] newUnpaddedLongArray(int num) {
-        return new long[num];
-    }
-    /**
-     * Initializes a queue with the given starting capacity.
-     *
-     * @param initialCapacity the capacity.
-     */
-    public LongArrayQueue(int initialCapacity) {
-        if (initialCapacity == 0) {
-            mValues = EmptyArray.LONG;
-        } else {
-            mValues = newUnpaddedLongArray(initialCapacity);
-        }
-        mSize = 0;
-        mHead = mTail = 0;
-    }
-
-    /**
-     * Initializes a queue with default starting capacity.
-     */
-    public LongArrayQueue() {
-        this(16);
-    }
-
-    /** @hide */
-    public static int growSize(int currentSize) {
-        return currentSize <= 4 ? 8 : currentSize * 2;
-    }
-
-    private void grow() {
-        if (mSize < mValues.length) {
-            throw new IllegalStateException("Queue not full yet!");
-        }
-        final int newSize = growSize(mSize);
-        final long[] newArray = newUnpaddedLongArray(newSize);
-        final int r = mValues.length - mHead; // Number of elements on and to the right of head.
-        System.arraycopy(mValues, mHead, newArray, 0, r);
-        System.arraycopy(mValues, 0, newArray, r, mHead);
-        mValues = newArray;
-        mHead = 0;
-        mTail = mSize;
-    }
-
-    /**
-     * Returns the number of elements in the queue.
-     */
-    public int size() {
-        return mSize;
-    }
-
-    /**
-     * Removes all elements from this queue.
-     */
-    public void clear() {
-        mSize = 0;
-        mHead = mTail = 0;
-    }
-
-    /**
-     * Adds a value to the tail of the queue.
-     *
-     * @param value the value to be added.
-     */
-    public void addLast(long value) {
-        if (mSize == mValues.length) {
-            grow();
-        }
-        mValues[mTail] = value;
-        mTail = (mTail + 1) % mValues.length;
-        mSize++;
-    }
-
-    /**
-     * Removes an element from the head of the queue.
-     *
-     * @return the element at the head of the queue.
-     * @throws NoSuchElementException if the queue is empty.
-     */
-    public long removeFirst() {
-        if (mSize == 0) {
-            throw new NoSuchElementException("Queue is empty!");
-        }
-        final long ret = mValues[mHead];
-        mHead = (mHead + 1) % mValues.length;
-        mSize--;
-        return ret;
-    }
-
-    /**
-     * Returns the element at the given position from the head of the queue, where 0 represents the
-     * head of the queue.
-     *
-     * @param position the position from the head of the queue.
-     * @return the element found at the given position.
-     * @throws IndexOutOfBoundsException if {@code position} < {@code 0} or
-     *                                   {@code position} >= {@link #size()}
-     */
-    public long get(int position) {
-        if (position < 0 || position >= mSize) {
-            throw new IndexOutOfBoundsException("Index " + position
-                + " not valid for a queue of size " + mSize);
-        }
-        final int index = (mHead + position) % mValues.length;
-        return mValues[index];
-    }
-
-    /**
-     * Returns the element at the head of the queue, without removing it.
-     *
-     * @return the element at the head of the queue.
-     * @throws NoSuchElementException if the queue is empty
-     */
-    public long peekFirst() {
-        if (mSize == 0) {
-            throw new NoSuchElementException("Queue is empty!");
-        }
-        return mValues[mHead];
-    }
-
-    /**
-     * Returns the element at the tail of the queue.
-     *
-     * @return the element at the tail of the queue.
-     * @throws NoSuchElementException if the queue is empty.
-     */
-    public long peekLast() {
-        if (mSize == 0) {
-            throw new NoSuchElementException("Queue is empty!");
-        }
-        final int index = (mTail == 0) ? mValues.length - 1 : mTail - 1;
-        return mValues[index];
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        if (mSize <= 0) {
-            return "{}";
-        }
-
-        final StringBuilder buffer = new StringBuilder(mSize * 64);
-        buffer.append('{');
-        buffer.append(get(0));
-        for (int i = 1; i < mSize; i++) {
-            buffer.append(", ");
-            buffer.append(get(i));
-        }
-        buffer.append('}');
-        return buffer.toString();
-    }
-}
diff --git a/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java b/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java
deleted file mode 100644
index dbbef61..0000000
--- a/packages/CrashRecovery/services/java/com/android/utils/XmlUtils.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.utils;
-
-import android.annotation.NonNull;
-import android.system.ErrnoException;
-import android.system.Os;
-
-import com.android.modules.utils.TypedXmlPullParser;
-
-import libcore.util.XmlObjectFactory;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Copied over partly from frameworks/base/core/java/com/android/internal/util/XmlUtils.java
- *
- * @hide
- */
-public class XmlUtils {
-
-    private static final String STRING_ARRAY_SEPARATOR = ":";
-
-    /** @hide */
-    public static final void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        int type;
-        while ((type = parser.next()) != parser.START_TAG
-            && type != parser.END_DOCUMENT) {
-            // Do nothing
-        }
-
-        if (type != parser.START_TAG) {
-            throw new XmlPullParserException("No start tag found");
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
-                + ", expected " + firstElementName);
-        }
-    }
-
-    /** @hide */
-    public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
-            throws IOException, XmlPullParserException {
-        for (;;) {
-            int type = parser.next();
-            if (type == XmlPullParser.END_DOCUMENT
-                    || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
-                return false;
-            }
-            if (type == XmlPullParser.START_TAG
-                    && parser.getDepth() == outerDepth + 1) {
-                return true;
-            }
-        }
-    }
-
-    private static XmlPullParser newPullParser() {
-        try {
-            XmlPullParser parser = XmlObjectFactory.newXmlPullParser();
-            parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true);
-            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
-            return parser;
-        } catch (XmlPullParserException e) {
-            throw new AssertionError();
-        }
-    }
-
-    /** @hide */
-    public static @NonNull TypedXmlPullParser resolvePullParser(@NonNull InputStream in)
-            throws IOException {
-        final byte[] magic = new byte[4];
-        if (in instanceof FileInputStream) {
-            try {
-                Os.pread(((FileInputStream) in).getFD(), magic, 0, magic.length, 0);
-            } catch (ErrnoException e) {
-                throw e.rethrowAsIOException();
-            }
-        } else {
-            if (!in.markSupported()) {
-                in = new BufferedInputStream(in);
-            }
-            in.mark(8);
-            in.read(magic);
-            in.reset();
-        }
-
-        final TypedXmlPullParser xml;
-        xml = (TypedXmlPullParser) newPullParser();
-        try {
-            xml.setInput(in, "UTF_8");
-        } catch (XmlPullParserException e) {
-            throw new IOException(e);
-        }
-        return xml;
-    }
-}
diff --git a/packages/CredentialManager/profile.txt.prof b/packages/CredentialManager/profile.txt.prof
index afe066b..9cfeb9a 100644
--- a/packages/CredentialManager/profile.txt.prof
+++ b/packages/CredentialManager/profile.txt.prof
@@ -1,13865 +1 @@
-HPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->get(I)Z
-HPLandroidx/emoji2/text/MetadataRepo;->constructIndex(Landroidx/emoji2/text/flatbuffer/MetadataList;)V
-HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda0;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda1;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda3;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$$ExternalSyntheticLambda3;->onContextAvailable(Landroid/content/Context;)V
-HSPLandroidx/activity/ComponentActivity$1;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$2;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$3;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$3;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/activity/ComponentActivity$4;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$4;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/activity/ComponentActivity$5;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$5;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/activity/ComponentActivity$Api19Impl;->cancelPendingInputEvents(Landroid/view/View;)V
-HSPLandroidx/activity/ComponentActivity$Api33Impl;->getOnBackInvokedDispatcher(Landroid/app/Activity;)Landroid/window/OnBackInvokedDispatcher;
-HSPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorApi16Impl;-><init>(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorApi16Impl;->onDraw()V
-HSPLandroidx/activity/ComponentActivity$ReportFullyDrawnExecutorApi16Impl;->viewCreated(Landroid/view/View;)V
-HSPLandroidx/activity/ComponentActivity;->$r8$lambda$h2i_RK2mddCIbAsGubaI4eL8_cU(Landroidx/activity/ComponentActivity;Landroid/content/Context;)V
-HSPLandroidx/activity/ComponentActivity;-><init>()V
-HSPLandroidx/activity/ComponentActivity;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
-HSPLandroidx/activity/ComponentActivity;->createFullyDrawnExecutor()Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutor;
-HSPLandroidx/activity/ComponentActivity;->ensureViewModelStore()V
-HSPLandroidx/activity/ComponentActivity;->getActivityResultRegistry()Landroidx/activity/result/ActivityResultRegistry;
-HSPLandroidx/activity/ComponentActivity;->getDefaultViewModelCreationExtras()Landroidx/lifecycle/viewmodel/CreationExtras;
-HSPLandroidx/activity/ComponentActivity;->getLifecycle()Landroidx/lifecycle/Lifecycle;
-HSPLandroidx/activity/ComponentActivity;->getOnBackPressedDispatcher()Landroidx/activity/OnBackPressedDispatcher;
-HSPLandroidx/activity/ComponentActivity;->getSavedStateRegistry()Landroidx/savedstate/SavedStateRegistry;
-HSPLandroidx/activity/ComponentActivity;->getViewModelStore()Landroidx/lifecycle/ViewModelStore;
-HSPLandroidx/activity/ComponentActivity;->initViewTreeOwners()V
-HSPLandroidx/activity/ComponentActivity;->lambda$new$2(Landroid/content/Context;)V
-HSPLandroidx/activity/ComponentActivity;->onCreate(Landroid/os/Bundle;)V
-HSPLandroidx/activity/ComponentActivity;->setContentView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V
-HSPLandroidx/activity/FullyDrawnReporter$$ExternalSyntheticLambda0;-><init>(Landroidx/activity/FullyDrawnReporter;)V
-HSPLandroidx/activity/FullyDrawnReporter;-><init>(Ljava/util/concurrent/Executor;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/activity/OnBackPressedCallback;-><init>(Z)V
-HSPLandroidx/activity/OnBackPressedCallback;->addCancellable(Landroidx/activity/Cancellable;)V
-HSPLandroidx/activity/OnBackPressedCallback;->isEnabled()Z
-HSPLandroidx/activity/OnBackPressedCallback;->removeCancellable(Landroidx/activity/Cancellable;)V
-HSPLandroidx/activity/OnBackPressedCallback;->setEnabledChangedCallback$activity_release(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$1;-><init>(Landroidx/activity/OnBackPressedDispatcher;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$2;-><init>(Landroidx/activity/OnBackPressedDispatcher;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl$$ExternalSyntheticLambda0;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;-><clinit>()V
-HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;-><init>()V
-HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;->createOnBackInvokedCallback(Lkotlin/jvm/functions/Function0;)Landroid/window/OnBackInvokedCallback;
-HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;->registerOnBackInvokedCallback(Ljava/lang/Object;ILjava/lang/Object;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$Api33Impl;->unregisterOnBackInvokedCallback(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;-><init>(Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/Lifecycle;Landroidx/activity/OnBackPressedCallback;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;->cancel()V
-HSPLandroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;-><init>(Landroidx/activity/OnBackPressedDispatcher;Landroidx/activity/OnBackPressedCallback;)V
-HSPLandroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;->cancel()V
-HSPLandroidx/activity/OnBackPressedDispatcher;-><init>(Ljava/lang/Runnable;)V
-HSPLandroidx/activity/OnBackPressedDispatcher;->access$getOnBackPressedCallbacks$p(Landroidx/activity/OnBackPressedDispatcher;)Lkotlin/collections/ArrayDeque;
-HSPLandroidx/activity/OnBackPressedDispatcher;->addCallback(Landroidx/lifecycle/LifecycleOwner;Landroidx/activity/OnBackPressedCallback;)V
-HSPLandroidx/activity/OnBackPressedDispatcher;->addCancellableCallback$activity_release(Landroidx/activity/OnBackPressedCallback;)Landroidx/activity/Cancellable;
-HSPLandroidx/activity/OnBackPressedDispatcher;->hasEnabledCallbacks()Z
-HSPLandroidx/activity/OnBackPressedDispatcher;->setOnBackInvokedDispatcher(Landroid/window/OnBackInvokedDispatcher;)V
-HSPLandroidx/activity/OnBackPressedDispatcher;->updateBackInvokedCallbackState$activity_release()V
-HSPLandroidx/activity/ViewTreeFullyDrawnReporterOwner;->set(Landroid/view/View;Landroidx/activity/FullyDrawnReporterOwner;)V
-HSPLandroidx/activity/ViewTreeOnBackPressedDispatcherOwner;->set(Landroid/view/View;Landroidx/activity/OnBackPressedDispatcherOwner;)V
-HSPLandroidx/activity/compose/ActivityResultLauncherHolder;-><init>()V
-HSPLandroidx/activity/compose/ActivityResultLauncherHolder;->setLauncher(Landroidx/activity/result/ActivityResultLauncher;)V
-HSPLandroidx/activity/compose/ActivityResultLauncherHolder;->unregister()V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1$1;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/activity/compose/ActivityResultLauncherHolder;)V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1;-><init>(Landroidx/activity/compose/ActivityResultLauncherHolder;Landroidx/activity/result/ActivityResultRegistry;Ljava/lang/String;Landroidx/activity/result/contract/ActivityResultContract;Landroidx/compose/runtime/State;)V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$key$1;-><clinit>()V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$key$1;-><init>()V
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$key$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$key$1;->invoke()Ljava/lang/String;
-HSPLandroidx/activity/compose/ActivityResultRegistryKt;->rememberLauncherForActivityResult(Landroidx/activity/result/contract/ActivityResultContract;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)Landroidx/activity/compose/ManagedActivityResultLauncher;
-HSPLandroidx/activity/compose/ComponentActivityKt;-><clinit>()V
-HSPLandroidx/activity/compose/ComponentActivityKt;->setContent$default(Landroidx/activity/ComponentActivity;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
-HSPLandroidx/activity/compose/ComponentActivityKt;->setContent(Landroidx/activity/ComponentActivity;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/activity/compose/ComponentActivityKt;->setOwners(Landroidx/activity/ComponentActivity;)V
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner$LocalComposition$1;-><clinit>()V
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner$LocalComposition$1;-><init>()V
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner$LocalComposition$1;->invoke()Landroidx/activity/result/ActivityResultRegistryOwner;
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner$LocalComposition$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner;-><clinit>()V
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner;-><init>()V
-HSPLandroidx/activity/compose/LocalActivityResultRegistryOwner;->getCurrent(Landroidx/compose/runtime/Composer;I)Landroidx/activity/result/ActivityResultRegistryOwner;
-HSPLandroidx/activity/compose/ManagedActivityResultLauncher;-><clinit>()V
-HSPLandroidx/activity/compose/ManagedActivityResultLauncher;-><init>(Landroidx/activity/compose/ActivityResultLauncherHolder;Landroidx/compose/runtime/State;)V
-HSPLandroidx/activity/contextaware/ContextAwareHelper;-><init>()V
-HSPLandroidx/activity/contextaware/ContextAwareHelper;->addOnContextAvailableListener(Landroidx/activity/contextaware/OnContextAvailableListener;)V
-HSPLandroidx/activity/contextaware/ContextAwareHelper;->clearAvailableContext()V
-HSPLandroidx/activity/contextaware/ContextAwareHelper;->dispatchOnContextAvailable(Landroid/content/Context;)V
-HSPLandroidx/activity/result/ActivityResultLauncher;-><init>()V
-HSPLandroidx/activity/result/ActivityResultRegistry$$ExternalSyntheticThrowCCEIfNotNull0;->m(Ljava/lang/Object;)V
-HSPLandroidx/activity/result/ActivityResultRegistry$3;-><init>(Landroidx/activity/result/ActivityResultRegistry;Ljava/lang/String;Landroidx/activity/result/contract/ActivityResultContract;)V
-HSPLandroidx/activity/result/ActivityResultRegistry$3;->unregister()V
-HSPLandroidx/activity/result/ActivityResultRegistry$CallbackAndContract;-><init>(Landroidx/activity/result/ActivityResultCallback;Landroidx/activity/result/contract/ActivityResultContract;)V
-HSPLandroidx/activity/result/ActivityResultRegistry;-><init>()V
-HSPLandroidx/activity/result/ActivityResultRegistry;->bindRcKey(ILjava/lang/String;)V
-HSPLandroidx/activity/result/ActivityResultRegistry;->generateRandomNumber()I
-HSPLandroidx/activity/result/ActivityResultRegistry;->register(Ljava/lang/String;Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;
-HSPLandroidx/activity/result/ActivityResultRegistry;->registerKey(Ljava/lang/String;)V
-HSPLandroidx/activity/result/ActivityResultRegistry;->unregister(Ljava/lang/String;)V
-HSPLandroidx/activity/result/contract/ActivityResultContract;-><init>()V
-HSPLandroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda0;-><init>()V
-HSPLandroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda1;-><init>()V
-HSPLandroidx/arch/core/executor/ArchTaskExecutor;-><clinit>()V
-HSPLandroidx/arch/core/executor/ArchTaskExecutor;-><init>()V
-HSPLandroidx/arch/core/executor/ArchTaskExecutor;->getInstance()Landroidx/arch/core/executor/ArchTaskExecutor;
-HSPLandroidx/arch/core/executor/ArchTaskExecutor;->isMainThread()Z
-HSPLandroidx/arch/core/executor/DefaultTaskExecutor$1;-><init>(Landroidx/arch/core/executor/DefaultTaskExecutor;)V
-HSPLandroidx/arch/core/executor/DefaultTaskExecutor;-><init>()V
-HSPLandroidx/arch/core/executor/DefaultTaskExecutor;->isMainThread()Z
-HSPLandroidx/arch/core/executor/TaskExecutor;-><init>()V
-HSPLandroidx/arch/core/internal/FastSafeIterableMap;-><init>()V
-HSPLandroidx/arch/core/internal/FastSafeIterableMap;->ceil(Ljava/lang/Object;)Ljava/util/Map$Entry;
-HSPLandroidx/arch/core/internal/FastSafeIterableMap;->contains(Ljava/lang/Object;)Z
-HSPLandroidx/arch/core/internal/FastSafeIterableMap;->get(Ljava/lang/Object;)Landroidx/arch/core/internal/SafeIterableMap$Entry;
-HSPLandroidx/arch/core/internal/FastSafeIterableMap;->putIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/FastSafeIterableMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap$AscendingIterator;-><init>(Landroidx/arch/core/internal/SafeIterableMap$Entry;Landroidx/arch/core/internal/SafeIterableMap$Entry;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$DescendingIterator;-><init>(Landroidx/arch/core/internal/SafeIterableMap$Entry;Landroidx/arch/core/internal/SafeIterableMap$Entry;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$DescendingIterator;->forward(Landroidx/arch/core/internal/SafeIterableMap$Entry;)Landroidx/arch/core/internal/SafeIterableMap$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap$Entry;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$Entry;->getKey()Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap$Entry;->getValue()Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;-><init>(Landroidx/arch/core/internal/SafeIterableMap;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;->hasNext()Z
-HSPLandroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;->next()Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;->next()Ljava/util/Map$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;->supportRemove(Landroidx/arch/core/internal/SafeIterableMap$Entry;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$ListIterator;-><init>(Landroidx/arch/core/internal/SafeIterableMap$Entry;Landroidx/arch/core/internal/SafeIterableMap$Entry;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$ListIterator;->hasNext()Z
-HSPLandroidx/arch/core/internal/SafeIterableMap$ListIterator;->next()Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap$ListIterator;->next()Ljava/util/Map$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap$ListIterator;->nextNode()Landroidx/arch/core/internal/SafeIterableMap$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap$ListIterator;->supportRemove(Landroidx/arch/core/internal/SafeIterableMap$Entry;)V
-HSPLandroidx/arch/core/internal/SafeIterableMap$SupportRemove;-><init>()V
-HSPLandroidx/arch/core/internal/SafeIterableMap;-><init>()V
-HSPLandroidx/arch/core/internal/SafeIterableMap;->descendingIterator()Ljava/util/Iterator;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->eldest()Ljava/util/Map$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->get(Ljava/lang/Object;)Landroidx/arch/core/internal/SafeIterableMap$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->iterator()Ljava/util/Iterator;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->iteratorWithAdditions()Landroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->newest()Ljava/util/Map$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Landroidx/arch/core/internal/SafeIterableMap$Entry;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->putIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->remove(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/arch/core/internal/SafeIterableMap;->size()I
-HSPLandroidx/collection/ArraySet$Companion;-><init>()V
-HSPLandroidx/collection/ArraySet$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/collection/ArraySet;-><clinit>()V
-HSPLandroidx/collection/ArraySet;-><init>()V
-HSPLandroidx/collection/ArraySet;-><init>(I)V
-HSPLandroidx/collection/ArraySet;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/collection/ArraySet;->add(Ljava/lang/Object;)Z
-HSPLandroidx/collection/ArraySet;->allocArrays(I)V
-HSPLandroidx/collection/ArraySet;->clear()V
-HSPLandroidx/collection/ArraySet;->indexOf(Ljava/lang/Object;I)I
-HSPLandroidx/collection/ArraySet;->toArray()[Ljava/lang/Object;
-HSPLandroidx/collection/LruCache;-><init>(I)V
-HSPLandroidx/collection/SimpleArrayMap;-><init>()V
-HSPLandroidx/collection/SimpleArrayMap;-><init>(I)V
-HSPLandroidx/collection/SimpleArrayMap;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/collection/SparseArrayCompat;-><init>()V
-HSPLandroidx/collection/SparseArrayCompat;-><init>(I)V
-HSPLandroidx/collection/SparseArrayCompat;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/collection/internal/ContainerHelpersKt;-><clinit>()V
-HSPLandroidx/collection/internal/ContainerHelpersKt;->idealByteArraySize(I)I
-HSPLandroidx/collection/internal/ContainerHelpersKt;->idealIntArraySize(I)I
-HSPLandroidx/collection/internal/Lock;-><init>()V
-HSPLandroidx/collection/internal/LruHashMap;-><init>(IF)V
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;-><clinit>()V
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;-><init>()V
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;->invoke-8_81llA(J)Landroidx/compose/animation/core/AnimationVector4D;
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$2;-><init>(Landroidx/compose/ui/graphics/colorspace/ColorSpace;)V
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;-><init>()V
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;->invoke(Landroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/ColorVectorConverterKt;-><clinit>()V
-HSPLandroidx/compose/animation/ColorVectorConverterKt;->access$getM1$p()[F
-HSPLandroidx/compose/animation/ColorVectorConverterKt;->access$multiplyColumn(IFFF[F)F
-HSPLandroidx/compose/animation/ColorVectorConverterKt;->getVectorConverter(Landroidx/compose/ui/graphics/Color$Companion;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/animation/ColorVectorConverterKt;->multiplyColumn(IFFF[F)F
-HSPLandroidx/compose/animation/FlingCalculator;-><init>(FLandroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/animation/FlingCalculator;->computeDeceleration(Landroidx/compose/ui/unit/Density;)F
-HSPLandroidx/compose/animation/FlingCalculatorKt;-><clinit>()V
-HSPLandroidx/compose/animation/FlingCalculatorKt;->access$computeDeceleration(FF)F
-HSPLandroidx/compose/animation/FlingCalculatorKt;->computeDeceleration(FF)F
-HSPLandroidx/compose/animation/SingleValueAnimationKt;-><clinit>()V
-HSPLandroidx/compose/animation/SingleValueAnimationKt;->animateColorAsState-KTwxG1Y(JLandroidx/compose/animation/core/AnimationSpec;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/animation/SingleValueAnimationKt;->animateColorAsState-euL9pac(JLandroidx/compose/animation/core/AnimationSpec;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/animation/SplineBasedFloatDecayAnimationSpec;-><clinit>()V
-HSPLandroidx/compose/animation/SplineBasedFloatDecayAnimationSpec;-><init>(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/animation/SplineBasedFloatDecayAnimationSpec_androidKt;-><clinit>()V
-HSPLandroidx/compose/animation/SplineBasedFloatDecayAnimationSpec_androidKt;->getPlatformFlingScrollFriction()F
-HSPLandroidx/compose/animation/SplineBasedFloatDecayAnimationSpec_androidKt;->rememberSplineBasedDecay(Landroidx/compose/runtime/Composer;I)Landroidx/compose/animation/core/DecayAnimationSpec;
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2$1;-><init>(Landroidx/compose/animation/core/Animatable;Landroidx/compose/animation/core/AnimationState;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/Ref$BooleanRef;)V
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2$1;->invoke(Landroidx/compose/animation/core/AnimationScope;)V
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2;-><init>(Landroidx/compose/animation/core/Animatable;Ljava/lang/Object;Landroidx/compose/animation/core/Animation;JLkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable$runAnimation$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;-><clinit>()V
-HSPLandroidx/compose/animation/core/Animatable;-><init>(Ljava/lang/Object;Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Ljava/lang/String;)V
-HSPLandroidx/compose/animation/core/Animatable;-><init>(Ljava/lang/Object;Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/animation/core/Animatable;->access$clampToBounds(Landroidx/compose/animation/core/Animatable;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->access$endAnimation(Landroidx/compose/animation/core/Animatable;)V
-HSPLandroidx/compose/animation/core/Animatable;->access$setRunning(Landroidx/compose/animation/core/Animatable;Z)V
-HSPLandroidx/compose/animation/core/Animatable;->access$setTargetValue(Landroidx/compose/animation/core/Animatable;Ljava/lang/Object;)V
-HSPLandroidx/compose/animation/core/Animatable;->animateTo$default(Landroidx/compose/animation/core/Animatable;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationSpec;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->animateTo(Ljava/lang/Object;Landroidx/compose/animation/core/AnimationSpec;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->asState()Landroidx/compose/runtime/State;
-HSPLandroidx/compose/animation/core/Animatable;->clampToBounds(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->createVector(Ljava/lang/Object;F)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/Animatable;->endAnimation()V
-HSPLandroidx/compose/animation/core/Animatable;->getInternalState$animation_core_release()Landroidx/compose/animation/core/AnimationState;
-HSPLandroidx/compose/animation/core/Animatable;->getTargetValue()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->getTypeConverter()Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/Animatable;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->getVelocity()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->getVelocityVector()Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/Animatable;->runAnimation(Landroidx/compose/animation/core/Animation;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/Animatable;->setRunning(Z)V
-HSPLandroidx/compose/animation/core/Animatable;->setTargetValue(Ljava/lang/Object;)V
-HSPLandroidx/compose/animation/core/AnimatableKt;->Animatable$default(FFILjava/lang/Object;)Landroidx/compose/animation/core/Animatable;
-HSPLandroidx/compose/animation/core/AnimatableKt;->Animatable(FF)Landroidx/compose/animation/core/Animatable;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$2;-><init>(Lkotlinx/coroutines/channels/Channel;Ljava/lang/Object;)V
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$2;->invoke()V
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3$1;-><init>(Ljava/lang/Object;Landroidx/compose/animation/core/Animatable;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3;-><init>(Lkotlinx/coroutines/channels/Channel;Landroidx/compose/animation/core/Animatable;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;->access$animateValueAsState$lambda$4(Landroidx/compose/runtime/State;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;->access$animateValueAsState$lambda$6(Landroidx/compose/runtime/State;)Landroidx/compose/animation/core/AnimationSpec;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;->animateFloatAsState(FLandroidx/compose/animation/core/AnimationSpec;FLjava/lang/String;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;->animateValueAsState$lambda$4(Landroidx/compose/runtime/State;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;->animateValueAsState$lambda$6(Landroidx/compose/runtime/State;)Landroidx/compose/animation/core/AnimationSpec;
-HSPLandroidx/compose/animation/core/AnimateAsStateKt;->animateValueAsState(Ljava/lang/Object;Landroidx/compose/animation/core/TwoWayConverter;Landroidx/compose/animation/core/AnimationSpec;Ljava/lang/Object;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/animation/core/Animation;->isFinishedFromNanos(J)Z
-HSPLandroidx/compose/animation/core/AnimationEndReason;->$values()[Landroidx/compose/animation/core/AnimationEndReason;
-HSPLandroidx/compose/animation/core/AnimationEndReason;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationEndReason;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/animation/core/AnimationKt;->TargetBasedAnimation(Landroidx/compose/animation/core/AnimationSpec;Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Landroidx/compose/animation/core/TargetBasedAnimation;
-HSPLandroidx/compose/animation/core/AnimationResult;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationResult;-><init>(Landroidx/compose/animation/core/AnimationState;Landroidx/compose/animation/core/AnimationEndReason;)V
-HSPLandroidx/compose/animation/core/AnimationScope;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationScope;-><init>(Ljava/lang/Object;Landroidx/compose/animation/core/TwoWayConverter;Landroidx/compose/animation/core/AnimationVector;JLjava/lang/Object;JZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/animation/core/AnimationScope;->getFinishedTimeNanos()J
-HSPLandroidx/compose/animation/core/AnimationScope;->getLastFrameTimeNanos()J
-HSPLandroidx/compose/animation/core/AnimationScope;->getStartTimeNanos()J
-HSPLandroidx/compose/animation/core/AnimationScope;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/AnimationScope;->getVelocityVector()Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationScope;->isRunning()Z
-HSPLandroidx/compose/animation/core/AnimationScope;->setFinishedTimeNanos$animation_core_release(J)V
-HSPLandroidx/compose/animation/core/AnimationScope;->setLastFrameTimeNanos$animation_core_release(J)V
-HSPLandroidx/compose/animation/core/AnimationScope;->setRunning$animation_core_release(Z)V
-HSPLandroidx/compose/animation/core/AnimationScope;->setValue$animation_core_release(Ljava/lang/Object;)V
-HSPLandroidx/compose/animation/core/AnimationScope;->setVelocityVector$animation_core_release(Landroidx/compose/animation/core/AnimationVector;)V
-HSPLandroidx/compose/animation/core/AnimationSpecKt;->access$convert(Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationSpecKt;->convert(Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationSpecKt;->spring$default(FFLjava/lang/Object;ILjava/lang/Object;)Landroidx/compose/animation/core/SpringSpec;
-HSPLandroidx/compose/animation/core/AnimationSpecKt;->spring(FFLjava/lang/Object;)Landroidx/compose/animation/core/SpringSpec;
-HSPLandroidx/compose/animation/core/AnimationState;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationState;-><init>(Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationVector;JJZ)V
-HSPLandroidx/compose/animation/core/AnimationState;-><init>(Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationVector;JJZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/animation/core/AnimationState;->getLastFrameTimeNanos()J
-HSPLandroidx/compose/animation/core/AnimationState;->getTypeConverter()Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/AnimationState;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/AnimationState;->getVelocityVector()Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationState;->isRunning()Z
-HSPLandroidx/compose/animation/core/AnimationState;->setFinishedTimeNanos$animation_core_release(J)V
-HSPLandroidx/compose/animation/core/AnimationState;->setLastFrameTimeNanos$animation_core_release(J)V
-HSPLandroidx/compose/animation/core/AnimationState;->setRunning$animation_core_release(Z)V
-HSPLandroidx/compose/animation/core/AnimationState;->setValue$animation_core_release(Ljava/lang/Object;)V
-HSPLandroidx/compose/animation/core/AnimationState;->setVelocityVector$animation_core_release(Landroidx/compose/animation/core/AnimationVector;)V
-HSPLandroidx/compose/animation/core/AnimationStateKt;->copy$default(Landroidx/compose/animation/core/AnimationState;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationVector;JJZILjava/lang/Object;)Landroidx/compose/animation/core/AnimationState;
-HSPLandroidx/compose/animation/core/AnimationStateKt;->copy(Landroidx/compose/animation/core/AnimationState;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationVector;JJZ)Landroidx/compose/animation/core/AnimationState;
-HSPLandroidx/compose/animation/core/AnimationStateKt;->createZeroVectorFrom(Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationVector1D;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationVector1D;-><init>(F)V
-HSPLandroidx/compose/animation/core/AnimationVector1D;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/animation/core/AnimationVector1D;->get$animation_core_release(I)F
-HSPLandroidx/compose/animation/core/AnimationVector1D;->getSize$animation_core_release()I
-HSPLandroidx/compose/animation/core/AnimationVector1D;->getValue()F
-HSPLandroidx/compose/animation/core/AnimationVector1D;->newVector$animation_core_release()Landroidx/compose/animation/core/AnimationVector1D;
-HSPLandroidx/compose/animation/core/AnimationVector1D;->newVector$animation_core_release()Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationVector1D;->reset$animation_core_release()V
-HSPLandroidx/compose/animation/core/AnimationVector1D;->set$animation_core_release(IF)V
-HSPLandroidx/compose/animation/core/AnimationVector4D;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationVector4D;-><init>(FFFF)V
-HSPLandroidx/compose/animation/core/AnimationVector4D;->getSize$animation_core_release()I
-HSPLandroidx/compose/animation/core/AnimationVector4D;->newVector$animation_core_release()Landroidx/compose/animation/core/AnimationVector4D;
-HSPLandroidx/compose/animation/core/AnimationVector4D;->newVector$animation_core_release()Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationVector4D;->set$animation_core_release(IF)V
-HSPLandroidx/compose/animation/core/AnimationVector;-><clinit>()V
-HSPLandroidx/compose/animation/core/AnimationVector;-><init>()V
-HSPLandroidx/compose/animation/core/AnimationVector;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/animation/core/AnimationVectorsKt;->copy(Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/AnimationVectorsKt;->copyFrom(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)V
-HSPLandroidx/compose/animation/core/AnimationVectorsKt;->newInstance(Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/ComplexDouble;-><init>(DD)V
-HSPLandroidx/compose/animation/core/ComplexDouble;->access$get_imaginary$p(Landroidx/compose/animation/core/ComplexDouble;)D
-HSPLandroidx/compose/animation/core/ComplexDouble;->access$get_real$p(Landroidx/compose/animation/core/ComplexDouble;)D
-HSPLandroidx/compose/animation/core/ComplexDouble;->access$set_imaginary$p(Landroidx/compose/animation/core/ComplexDouble;D)V
-HSPLandroidx/compose/animation/core/ComplexDouble;->access$set_real$p(Landroidx/compose/animation/core/ComplexDouble;D)V
-HSPLandroidx/compose/animation/core/ComplexDouble;->getReal()D
-HSPLandroidx/compose/animation/core/ComplexDoubleKt;->complexQuadraticFormula(DDD)Lkotlin/Pair;
-HSPLandroidx/compose/animation/core/ComplexDoubleKt;->complexSqrt(D)Landroidx/compose/animation/core/ComplexDouble;
-HSPLandroidx/compose/animation/core/CubicBezierEasing;-><clinit>()V
-HSPLandroidx/compose/animation/core/CubicBezierEasing;-><init>(FFFF)V
-HSPLandroidx/compose/animation/core/CubicBezierEasing;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/animation/core/CubicBezierEasing;->evaluateCubic(FFF)F
-HSPLandroidx/compose/animation/core/CubicBezierEasing;->transform(F)F
-HSPLandroidx/compose/animation/core/DecayAnimationSpecImpl;-><init>(Landroidx/compose/animation/core/FloatDecayAnimationSpec;)V
-HSPLandroidx/compose/animation/core/DecayAnimationSpecKt;->generateDecayAnimationSpec(Landroidx/compose/animation/core/FloatDecayAnimationSpec;)Landroidx/compose/animation/core/DecayAnimationSpec;
-HSPLandroidx/compose/animation/core/EasingKt$LinearEasing$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/EasingKt$LinearEasing$1;-><init>()V
-HSPLandroidx/compose/animation/core/EasingKt;-><clinit>()V
-HSPLandroidx/compose/animation/core/EasingKt;->getFastOutLinearInEasing()Landroidx/compose/animation/core/Easing;
-HSPLandroidx/compose/animation/core/EasingKt;->getFastOutSlowInEasing()Landroidx/compose/animation/core/Easing;
-HSPLandroidx/compose/animation/core/EasingKt;->getLinearEasing()Landroidx/compose/animation/core/Easing;
-HSPLandroidx/compose/animation/core/FloatSpringSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/FloatSpringSpec;-><init>(FFF)V
-HSPLandroidx/compose/animation/core/FloatSpringSpec;-><init>(FFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/animation/core/FloatSpringSpec;->getDurationNanos(FFF)J
-HSPLandroidx/compose/animation/core/FloatSpringSpec;->getEndVelocity(FFF)F
-HSPLandroidx/compose/animation/core/FloatSpringSpec;->getValueFromNanos(JFFF)F
-HSPLandroidx/compose/animation/core/FloatSpringSpec;->getVelocityFromNanos(JFFF)F
-HSPLandroidx/compose/animation/core/FloatTweenSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/FloatTweenSpec;-><init>(IILandroidx/compose/animation/core/Easing;)V
-HSPLandroidx/compose/animation/core/FloatTweenSpec;->clampPlayTime(J)J
-HSPLandroidx/compose/animation/core/FloatTweenSpec;->getValueFromNanos(JFFF)F
-HSPLandroidx/compose/animation/core/FloatTweenSpec;->getVelocityFromNanos(JFFF)F
-HSPLandroidx/compose/animation/core/Motion;->constructor-impl(J)J
-HSPLandroidx/compose/animation/core/Motion;->getValue-impl(J)F
-HSPLandroidx/compose/animation/core/Motion;->getVelocity-impl(J)F
-HSPLandroidx/compose/animation/core/MutatePriority;->$values()[Landroidx/compose/animation/core/MutatePriority;
-HSPLandroidx/compose/animation/core/MutatePriority;-><clinit>()V
-HSPLandroidx/compose/animation/core/MutatePriority;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/animation/core/MutatorMutex$Mutator;-><init>(Landroidx/compose/animation/core/MutatePriority;Lkotlinx/coroutines/Job;)V
-HSPLandroidx/compose/animation/core/MutatorMutex$mutate$2;-><init>(Landroidx/compose/animation/core/MutatePriority;Landroidx/compose/animation/core/MutatorMutex;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/animation/core/MutatorMutex$mutate$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/animation/core/MutatorMutex$mutate$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/MutatorMutex$mutate$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/MutatorMutex$mutate$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/MutatorMutex;-><init>()V
-HSPLandroidx/compose/animation/core/MutatorMutex;->access$getCurrentMutator$p(Landroidx/compose/animation/core/MutatorMutex;)Ljava/util/concurrent/atomic/AtomicReference;
-HSPLandroidx/compose/animation/core/MutatorMutex;->access$getMutex$p(Landroidx/compose/animation/core/MutatorMutex;)Lkotlinx/coroutines/sync/Mutex;
-HSPLandroidx/compose/animation/core/MutatorMutex;->access$tryMutateOrCancel(Landroidx/compose/animation/core/MutatorMutex;Landroidx/compose/animation/core/MutatorMutex$Mutator;)V
-HSPLandroidx/compose/animation/core/MutatorMutex;->mutate$default(Landroidx/compose/animation/core/MutatorMutex;Landroidx/compose/animation/core/MutatePriority;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/MutatorMutex;->mutate(Landroidx/compose/animation/core/MutatePriority;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/MutatorMutex;->tryMutateOrCancel(Landroidx/compose/animation/core/MutatorMutex$Mutator;)V
-HSPLandroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fn$1;-><init>(DDDD)V
-HSPLandroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fn$1;->invoke(D)Ljava/lang/Double;
-HSPLandroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fn$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fnPrime$1;-><init>(DDD)V
-HSPLandroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fnPrime$1;->invoke(D)Ljava/lang/Double;
-HSPLandroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fnPrime$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SpringEstimationKt;->estimateAnimationDurationMillis(DDDDD)J
-HSPLandroidx/compose/animation/core/SpringEstimationKt;->estimateAnimationDurationMillis(FFFFF)J
-HSPLandroidx/compose/animation/core/SpringEstimationKt;->estimateCriticallyDamped$t2Iterate(DD)D
-HSPLandroidx/compose/animation/core/SpringEstimationKt;->estimateCriticallyDamped(Lkotlin/Pair;DDD)D
-HSPLandroidx/compose/animation/core/SpringEstimationKt;->estimateDurationInternal(Lkotlin/Pair;DDDD)J
-HSPLandroidx/compose/animation/core/SpringSimulation;-><init>(F)V
-HSPLandroidx/compose/animation/core/SpringSimulation;->getDampingRatio()F
-HSPLandroidx/compose/animation/core/SpringSimulation;->getStiffness()F
-HSPLandroidx/compose/animation/core/SpringSimulation;->init()V
-HSPLandroidx/compose/animation/core/SpringSimulation;->setDampingRatio(F)V
-HSPLandroidx/compose/animation/core/SpringSimulation;->setFinalPosition(F)V
-HSPLandroidx/compose/animation/core/SpringSimulation;->setStiffness(F)V
-HSPLandroidx/compose/animation/core/SpringSimulation;->updateValues-IJZedt4$animation_core_release(FFJ)J
-HSPLandroidx/compose/animation/core/SpringSimulationKt;-><clinit>()V
-HSPLandroidx/compose/animation/core/SpringSimulationKt;->Motion(FF)J
-HSPLandroidx/compose/animation/core/SpringSimulationKt;->getUNSET()F
-HSPLandroidx/compose/animation/core/SpringSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/SpringSpec;-><init>(FFLjava/lang/Object;)V
-HSPLandroidx/compose/animation/core/SpringSpec;-><init>(FFLjava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/animation/core/SpringSpec;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/animation/core/SpringSpec;->vectorize(Landroidx/compose/animation/core/TwoWayConverter;)Landroidx/compose/animation/core/VectorizedAnimationSpec;
-HSPLandroidx/compose/animation/core/SpringSpec;->vectorize(Landroidx/compose/animation/core/TwoWayConverter;)Landroidx/compose/animation/core/VectorizedSpringSpec;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$4;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$4;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$6$1;-><init>(Landroidx/compose/animation/core/AnimationState;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$6;-><init>(Lkotlin/jvm/internal/Ref$ObjectRef;Ljava/lang/Object;Landroidx/compose/animation/core/Animation;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationState;FLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$6;->invoke(J)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$6;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$9;-><init>(Lkotlin/jvm/internal/Ref$ObjectRef;FLandroidx/compose/animation/core/Animation;Landroidx/compose/animation/core/AnimationState;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$9;->invoke(J)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$animate$9;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$callWithFrameNanos$2;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$callWithFrameNanos$2;->invoke(J)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt$callWithFrameNanos$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->access$doAnimationFrameWithScale(Landroidx/compose/animation/core/AnimationScope;JFLandroidx/compose/animation/core/Animation;Landroidx/compose/animation/core/AnimationState;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->animate(Landroidx/compose/animation/core/AnimationState;Landroidx/compose/animation/core/Animation;JLkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->callWithFrameNanos(Landroidx/compose/animation/core/Animation;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->doAnimationFrame(Landroidx/compose/animation/core/AnimationScope;JJLandroidx/compose/animation/core/Animation;Landroidx/compose/animation/core/AnimationState;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->doAnimationFrameWithScale(Landroidx/compose/animation/core/AnimationScope;JFLandroidx/compose/animation/core/Animation;Landroidx/compose/animation/core/AnimationState;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->getDurationScale(Lkotlin/coroutines/CoroutineContext;)F
-HSPLandroidx/compose/animation/core/SuspendAnimationKt;->updateState(Landroidx/compose/animation/core/AnimationScope;Landroidx/compose/animation/core/AnimationState;)V
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;-><clinit>()V
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;-><init>(Landroidx/compose/animation/core/AnimationSpec;Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationVector;)V
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;-><init>(Landroidx/compose/animation/core/VectorizedAnimationSpec;Landroidx/compose/animation/core/TwoWayConverter;Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationVector;)V
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;->getDurationNanos()J
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;->getTargetValue()Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;->getTypeConverter()Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;->getValueFromNanos(J)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;->getVelocityVectorFromNanos(J)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/TargetBasedAnimation;->isInfinite()Z
-HSPLandroidx/compose/animation/core/TweenSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/TweenSpec;-><init>(IILandroidx/compose/animation/core/Easing;)V
-HSPLandroidx/compose/animation/core/TweenSpec;-><init>(IILandroidx/compose/animation/core/Easing;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/animation/core/TweenSpec;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/animation/core/TweenSpec;->vectorize(Landroidx/compose/animation/core/TwoWayConverter;)Landroidx/compose/animation/core/VectorizedAnimationSpec;
-HSPLandroidx/compose/animation/core/TweenSpec;->vectorize(Landroidx/compose/animation/core/TwoWayConverter;)Landroidx/compose/animation/core/VectorizedTweenSpec;
-HSPLandroidx/compose/animation/core/TwoWayConverterImpl;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/animation/core/TwoWayConverterImpl;->getConvertFromVector()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/animation/core/TwoWayConverterImpl;->getConvertToVector()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpOffsetToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpOffsetToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpOffsetToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpOffsetToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$1;->invoke-0680j_4(F)Landroidx/compose/animation/core/AnimationVector1D;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$DpToVector$2;->invoke-u2uoSUM(Landroidx/compose/animation/core/AnimationVector1D;)F
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$1;->invoke(F)Landroidx/compose/animation/core/AnimationVector1D;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$2;->invoke(Landroidx/compose/animation/core/AnimationVector1D;)Ljava/lang/Float;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$FloatToVector$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntOffsetToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntOffsetToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntOffsetToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntOffsetToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntSizeToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntSizeToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntSizeToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntSizeToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$IntToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$OffsetToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$OffsetToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$OffsetToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$OffsetToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$RectToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$RectToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$RectToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$RectToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$SizeToVector$1;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$SizeToVector$1;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$SizeToVector$2;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt$SizeToVector$2;-><init>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->TwoWayConverter(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/geometry/Offset$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/geometry/Rect$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/geometry/Size$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/unit/Dp$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/unit/DpOffset$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/unit/IntOffset$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Landroidx/compose/ui/unit/IntSize$Companion;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Lkotlin/jvm/internal/FloatCompanionObject;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->getVectorConverter(Lkotlin/jvm/internal/IntCompanionObject;)Landroidx/compose/animation/core/TwoWayConverter;
-HSPLandroidx/compose/animation/core/VectorConvertersKt;->lerp(FFF)F
-HSPLandroidx/compose/animation/core/VectorizedAnimationSpec;->getEndVelocity(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedAnimationSpecKt$createSpringAnimations$2;-><init>(FF)V
-HSPLandroidx/compose/animation/core/VectorizedAnimationSpecKt$createSpringAnimations$2;->get(I)Landroidx/compose/animation/core/FloatAnimationSpec;
-HSPLandroidx/compose/animation/core/VectorizedAnimationSpecKt$createSpringAnimations$2;->get(I)Landroidx/compose/animation/core/FloatSpringSpec;
-HSPLandroidx/compose/animation/core/VectorizedAnimationSpecKt;->access$createSpringAnimations(Landroidx/compose/animation/core/AnimationVector;FF)Landroidx/compose/animation/core/Animations;
-HSPLandroidx/compose/animation/core/VectorizedAnimationSpecKt;->createSpringAnimations(Landroidx/compose/animation/core/AnimationVector;FF)Landroidx/compose/animation/core/Animations;
-HSPLandroidx/compose/animation/core/VectorizedDurationBasedAnimationSpec;->getDurationNanos(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)J
-HSPLandroidx/compose/animation/core/VectorizedFiniteAnimationSpec;->isInfinite()Z
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec$1;-><init>(Landroidx/compose/animation/core/FloatAnimationSpec;)V
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec$1;->get(I)Landroidx/compose/animation/core/FloatAnimationSpec;
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;-><init>(Landroidx/compose/animation/core/Animations;)V
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;-><init>(Landroidx/compose/animation/core/FloatAnimationSpec;)V
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;->getDurationNanos(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)J
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;->getEndVelocity(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;->getValueFromNanos(JLandroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedFloatAnimationSpec;->getVelocityFromNanos(JLandroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;-><init>(FFLandroidx/compose/animation/core/AnimationVector;)V
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;-><init>(FFLandroidx/compose/animation/core/Animations;)V
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;->getDurationNanos(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)J
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;->getEndVelocity(Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;->getValueFromNanos(JLandroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;->getVelocityFromNanos(JLandroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedSpringSpec;->isInfinite()Z
-HSPLandroidx/compose/animation/core/VectorizedTweenSpec;-><clinit>()V
-HSPLandroidx/compose/animation/core/VectorizedTweenSpec;-><init>(IILandroidx/compose/animation/core/Easing;)V
-HSPLandroidx/compose/animation/core/VectorizedTweenSpec;->getDelayMillis()I
-HSPLandroidx/compose/animation/core/VectorizedTweenSpec;->getDurationMillis()I
-HSPLandroidx/compose/animation/core/VectorizedTweenSpec;->getValueFromNanos(JLandroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VectorizedTweenSpec;->getVelocityFromNanos(JLandroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;Landroidx/compose/animation/core/AnimationVector;)Landroidx/compose/animation/core/AnimationVector;
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;-><clinit>()V
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Landroidx/compose/ui/geometry/Offset$Companion;)J
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Landroidx/compose/ui/geometry/Rect$Companion;)Landroidx/compose/ui/geometry/Rect;
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Landroidx/compose/ui/geometry/Size$Companion;)J
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Landroidx/compose/ui/unit/Dp$Companion;)F
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Landroidx/compose/ui/unit/IntOffset$Companion;)J
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Landroidx/compose/ui/unit/IntSize$Companion;)J
-HSPLandroidx/compose/animation/core/VisibilityThresholdsKt;->getVisibilityThreshold(Lkotlin/jvm/internal/IntCompanionObject;)I
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1$1;-><init>(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1$1;->invoke(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1;-><init>(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$onNewSize$1;-><init>(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$onNewSize$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$onNewSize$1;->invoke-ozmzZPI(J)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;-><init>(Landroid/content/Context;Landroidx/compose/foundation/OverscrollConfiguration;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$animateToRelease(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getBottomEffect$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getBottomEffectNegation$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getContainerSize$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)J
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getLeftEffect$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getLeftEffectNegation$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getRightEffect$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getRightEffectNegation$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getTopEffect$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$getTopEffectNegation$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$invalidateOverscroll(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->access$setContainerSize$p(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;J)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->animateToRelease()V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->drawOverscroll(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->getEffectModifier()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;->invalidateOverscroll()V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1$1;-><init>(Landroidx/compose/ui/layout/Placeable;I)V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1;-><clinit>()V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1;-><init>()V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1;->invoke-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2$1;-><init>(Landroidx/compose/ui/layout/Placeable;I)V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2;-><clinit>()V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2;-><init>()V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2;->invoke-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt;-><clinit>()V
-HSPLandroidx/compose/foundation/AndroidOverscrollKt;->access$getStretchOverscrollNonClippingLayer$p()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/AndroidOverscrollKt;->rememberOverscrollEffect(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/OverscrollEffect;
-HSPLandroidx/compose/foundation/Api31Impl;-><clinit>()V
-HSPLandroidx/compose/foundation/Api31Impl;-><init>()V
-HSPLandroidx/compose/foundation/Api31Impl;->create(Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/Api31Impl;->getDistance(Landroid/widget/EdgeEffect;)F
-HSPLandroidx/compose/foundation/Background;-><init>(Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Shape;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/Background;-><init>(Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Shape;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/Background;-><init>(Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Shape;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/Background;->draw(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/foundation/Background;->drawOutline(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/foundation/Background;->drawRect(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/foundation/Background;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/BackgroundKt;->background-bw27NRU$default(Landroidx/compose/ui/Modifier;JLandroidx/compose/ui/graphics/Shape;ILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/BackgroundKt;->background-bw27NRU(Landroidx/compose/ui/Modifier;JLandroidx/compose/ui/graphics/Shape;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/CanvasKt;->Canvas(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/CheckScrollableContainerConstraintsKt;->checkScrollableContainerConstraints-K40F9xA(JLandroidx/compose/foundation/gestures/Orientation;)V
-HSPLandroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/MutableState;Ljava/util/Map;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1;-><init>(Landroidx/compose/runtime/MutableState;Ljava/util/Map;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$1$1;-><init>(Landroidx/compose/runtime/MutableState;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$1$1;->onModifierLocalsUpdated(Landroidx/compose/ui/modifier/ModifierLocalReadScope;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$delayPressInteraction$1$1;-><init>(Landroidx/compose/runtime/MutableState;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$delayPressInteraction$1$1;->invoke()Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$delayPressInteraction$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$1;-><init>(ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$1;->invoke-d-4ec7I(Landroidx/compose/foundation/gestures/PressGestureScope;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$2;-><init>(ZLandroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$2;->invoke-k-4lQ0M(J)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1;-><init>(Landroidx/compose/runtime/MutableState;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4;-><init>(Lkotlin/jvm/functions/Function0;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/Indication;Ljava/lang/String;Landroidx/compose/ui/semantics/Role;)V
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClickableKt$clickable$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$clickSemantics$1$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$clickSemantics$1;-><init>(Landroidx/compose/ui/semantics/Role;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$clickSemantics$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$clickSemantics$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$detectPressAndClickFromKey$1;-><init>(ZLjava/util/Map;Landroidx/compose/runtime/State;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2$delayJob$1;-><init>(Landroidx/compose/runtime/State;JLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2$delayJob$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2$delayJob$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2;-><init>(Landroidx/compose/foundation/gestures/PressGestureScope;JLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt$handlePressInteraction$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ClickableKt;->PressedInteractionSourceDisposableEffect(Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Ljava/util/Map;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/ClickableKt;->clickable-O2vRcR0$default(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/Indication;ZLjava/lang/String;Landroidx/compose/ui/semantics/Role;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClickableKt;->clickable-O2vRcR0(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/Indication;ZLjava/lang/String;Landroidx/compose/ui/semantics/Role;Lkotlin/jvm/functions/Function0;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClickableKt;->genericClickableWithoutGesture-bdNGguI(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/Indication;Lkotlinx/coroutines/CoroutineScope;Ljava/util/Map;Landroidx/compose/runtime/State;ZLjava/lang/String;Landroidx/compose/ui/semantics/Role;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClickableKt;->genericClickableWithoutGesture_bdNGguI$clickSemantics(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/semantics/Role;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function0;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClickableKt;->genericClickableWithoutGesture_bdNGguI$detectPressAndClickFromKey(Landroidx/compose/ui/Modifier;ZLjava/util/Map;Landroidx/compose/runtime/State;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/foundation/interaction/MutableInteractionSource;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClickableKt;->handlePressInteraction-EPk0efs(Landroidx/compose/foundation/gestures/PressGestureScope;JLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/Clickable_androidKt$isComposeRootInScrollableContainer$1;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/foundation/Clickable_androidKt$isComposeRootInScrollableContainer$1;->invoke()Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/Clickable_androidKt$isComposeRootInScrollableContainer$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/Clickable_androidKt;-><clinit>()V
-HSPLandroidx/compose/foundation/Clickable_androidKt;->access$isInScrollableViewGroup(Landroid/view/View;)Z
-HSPLandroidx/compose/foundation/Clickable_androidKt;->isComposeRootInScrollableContainer(Landroidx/compose/runtime/Composer;I)Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/foundation/Clickable_androidKt;->isInScrollableViewGroup(Landroid/view/View;)Z
-HSPLandroidx/compose/foundation/ClipScrollableContainerKt$HorizontalScrollableClipModifier$1;-><init>()V
-HSPLandroidx/compose/foundation/ClipScrollableContainerKt$VerticalScrollableClipModifier$1;-><init>()V
-HSPLandroidx/compose/foundation/ClipScrollableContainerKt$VerticalScrollableClipModifier$1;->createOutline-Pq9zytI(JLandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;)Landroidx/compose/ui/graphics/Outline;
-HSPLandroidx/compose/foundation/ClipScrollableContainerKt;-><clinit>()V
-HSPLandroidx/compose/foundation/ClipScrollableContainerKt;->clipScrollableContainer(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/gestures/Orientation;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ClipScrollableContainerKt;->getMaxSupportedElevation()F
-HSPLandroidx/compose/foundation/DarkThemeKt;->isSystemInDarkTheme(Landroidx/compose/runtime/Composer;I)Z
-HSPLandroidx/compose/foundation/DarkTheme_androidKt;->_isSystemInDarkTheme(Landroidx/compose/runtime/Composer;I)Z
-HSPLandroidx/compose/foundation/DrawOverscrollModifier;-><init>(Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/DrawOverscrollModifier;->draw(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/foundation/DrawOverscrollModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/EdgeEffectCompat;-><clinit>()V
-HSPLandroidx/compose/foundation/EdgeEffectCompat;-><init>()V
-HSPLandroidx/compose/foundation/EdgeEffectCompat;->create(Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/widget/EdgeEffect;
-HSPLandroidx/compose/foundation/EdgeEffectCompat;->getDistanceCompat(Landroid/widget/EdgeEffect;)F
-HSPLandroidx/compose/foundation/FocusableKt$focusGroup$1;-><clinit>()V
-HSPLandroidx/compose/foundation/FocusableKt$focusGroup$1;-><init>()V
-HSPLandroidx/compose/foundation/FocusableKt$focusGroup$1;->invoke(Landroidx/compose/ui/focus/FocusProperties;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusGroup$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$1$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$1$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$1$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$1$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$2$invoke$$inlined$onDispose$1;-><init>()V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$2$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$2;-><init>(ZLkotlinx/coroutines/CoroutineScope;Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$2;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$3$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/MutableState;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$3$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$3$1;-><init>(Landroidx/compose/ui/layout/PinnableContainer;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/MutableState;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$3$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$3$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$4$1$1;-><init>(Landroidx/compose/ui/focus/FocusRequester;Landroidx/compose/runtime/MutableState;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$4$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/ui/focus/FocusRequester;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$4$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$4$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$5$2;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$5$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$5$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$5;-><init>(Landroidx/compose/ui/layout/PinnableContainer;Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/relocation/BringIntoViewRequester;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$5;->invoke(Landroidx/compose/ui/focus/FocusState;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2$5;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;-><init>(Landroidx/compose/foundation/interaction/MutableInteractionSource;Z)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->access$invoke$lambda$10(Landroidx/compose/runtime/MutableState;Landroidx/compose/ui/layout/PinnableContainer$PinnedHandle;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->access$invoke$lambda$2(Landroidx/compose/runtime/MutableState;)Z
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->access$invoke$lambda$3(Landroidx/compose/runtime/MutableState;Z)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->access$invoke$lambda$9(Landroidx/compose/runtime/MutableState;)Landroidx/compose/ui/layout/PinnableContainer$PinnedHandle;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->invoke$lambda$10(Landroidx/compose/runtime/MutableState;Landroidx/compose/ui/layout/PinnableContainer$PinnedHandle;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->invoke$lambda$2(Landroidx/compose/runtime/MutableState;)Z
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->invoke$lambda$3(Landroidx/compose/runtime/MutableState;Z)V
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->invoke$lambda$9(Landroidx/compose/runtime/MutableState;)Landroidx/compose/ui/layout/PinnableContainer$PinnedHandle;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusableKt$focusable$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2$1;-><init>(Landroidx/compose/ui/input/InputModeManager;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2$1;->invoke(Landroidx/compose/ui/focus/FocusProperties;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2;-><init>(ZLandroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusableKt;-><clinit>()V
-HSPLandroidx/compose/foundation/FocusableKt;->focusGroup(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusableKt;->focusable(Landroidx/compose/ui/Modifier;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusableKt;->focusableInNonTouchMode(Landroidx/compose/ui/Modifier;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusedBoundsKt$ModifierLocalFocusedBoundsObserver$1;-><clinit>()V
-HSPLandroidx/compose/foundation/FocusedBoundsKt$ModifierLocalFocusedBoundsObserver$1;-><init>()V
-HSPLandroidx/compose/foundation/FocusedBoundsKt$ModifierLocalFocusedBoundsObserver$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusedBoundsKt$ModifierLocalFocusedBoundsObserver$1;->invoke()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/foundation/FocusedBoundsKt$onFocusedBoundsChanged$2;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/FocusedBoundsKt$onFocusedBoundsChanged$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusedBoundsKt$onFocusedBoundsChanged$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/FocusedBoundsKt;-><clinit>()V
-HSPLandroidx/compose/foundation/FocusedBoundsKt;->getModifierLocalFocusedBoundsObserver()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/FocusedBoundsKt;->onFocusedBoundsChanged(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/FocusedBoundsObserverModifier;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/FocusedBoundsObserverModifier;->getKey()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/FocusedBoundsObserverModifier;->onModifierLocalsUpdated(Landroidx/compose/ui/modifier/ModifierLocalReadScope;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$1$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$1$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$1$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$1$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$2$1;-><init>(ZLandroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3$1;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3;-><init>(Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/MutableState;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2;-><init>(Landroidx/compose/foundation/interaction/MutableInteractionSource;Z)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2;->access$invoke$tryEmitExit(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2;->invoke$lambda$1(Landroidx/compose/runtime/MutableState;)Landroidx/compose/foundation/interaction/HoverInteraction$Enter;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2;->invoke$tryEmitExit(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/HoverableKt$hoverable$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/HoverableKt;->hoverable(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;Z)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/ImageKt$Image$2$measure$1;-><clinit>()V
-HSPLandroidx/compose/foundation/ImageKt$Image$2$measure$1;-><init>()V
-HSPLandroidx/compose/foundation/ImageKt$Image$2$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/ImageKt$Image$2$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/ImageKt$Image$2;-><clinit>()V
-HSPLandroidx/compose/foundation/ImageKt$Image$2;-><init>()V
-HSPLandroidx/compose/foundation/ImageKt$Image$2;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/ImageKt;->Image(Landroidx/compose/ui/graphics/painter/Painter;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;FLandroidx/compose/ui/graphics/ColorFilter;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/foundation/ImageKt;->Image-5h-nEew(Landroidx/compose/ui/graphics/ImageBitmap;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;FLandroidx/compose/ui/graphics/ColorFilter;ILandroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/foundation/IndicationKt$LocalIndication$1;-><clinit>()V
-HSPLandroidx/compose/foundation/IndicationKt$LocalIndication$1;-><init>()V
-HSPLandroidx/compose/foundation/IndicationKt$indication$2;-><init>(Landroidx/compose/foundation/Indication;Landroidx/compose/foundation/interaction/InteractionSource;)V
-HSPLandroidx/compose/foundation/IndicationKt$indication$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/IndicationKt$indication$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/IndicationKt;-><clinit>()V
-HSPLandroidx/compose/foundation/IndicationKt;->getLocalIndication()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/foundation/IndicationKt;->indication(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/foundation/Indication;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/IndicationModifier;-><init>(Landroidx/compose/foundation/IndicationInstance;)V
-HSPLandroidx/compose/foundation/IndicationModifier;->draw(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/foundation/MutatePriority;->$values()[Landroidx/compose/foundation/MutatePriority;
-HSPLandroidx/compose/foundation/MutatePriority;-><clinit>()V
-HSPLandroidx/compose/foundation/MutatePriority;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/foundation/MutatorMutex$Mutator;-><init>(Landroidx/compose/foundation/MutatePriority;Lkotlinx/coroutines/Job;)V
-HSPLandroidx/compose/foundation/MutatorMutex$mutateWith$2;-><init>(Landroidx/compose/foundation/MutatePriority;Landroidx/compose/foundation/MutatorMutex;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/MutatorMutex$mutateWith$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/MutatorMutex$mutateWith$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/MutatorMutex$mutateWith$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/MutatorMutex$mutateWith$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/MutatorMutex;-><clinit>()V
-HSPLandroidx/compose/foundation/MutatorMutex;-><init>()V
-HSPLandroidx/compose/foundation/MutatorMutex;->access$getCurrentMutator$p(Landroidx/compose/foundation/MutatorMutex;)Ljava/util/concurrent/atomic/AtomicReference;
-HSPLandroidx/compose/foundation/MutatorMutex;->access$getMutex$p(Landroidx/compose/foundation/MutatorMutex;)Lkotlinx/coroutines/sync/Mutex;
-HSPLandroidx/compose/foundation/MutatorMutex;->access$tryMutateOrCancel(Landroidx/compose/foundation/MutatorMutex;Landroidx/compose/foundation/MutatorMutex$Mutator;)V
-HSPLandroidx/compose/foundation/MutatorMutex;->mutateWith(Ljava/lang/Object;Landroidx/compose/foundation/MutatePriority;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/MutatorMutex;->tryMutateOrCancel(Landroidx/compose/foundation/MutatorMutex$Mutator;)V
-HSPLandroidx/compose/foundation/OverscrollConfiguration;-><clinit>()V
-HSPLandroidx/compose/foundation/OverscrollConfiguration;-><init>(JLandroidx/compose/foundation/layout/PaddingValues;)V
-HSPLandroidx/compose/foundation/OverscrollConfiguration;-><init>(JLandroidx/compose/foundation/layout/PaddingValues;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/OverscrollConfiguration;-><init>(JLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/OverscrollConfiguration;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/OverscrollConfiguration;->getGlowColor-0d7_KjU()J
-HSPLandroidx/compose/foundation/OverscrollConfigurationKt$LocalOverscrollConfiguration$1;-><clinit>()V
-HSPLandroidx/compose/foundation/OverscrollConfigurationKt$LocalOverscrollConfiguration$1;-><init>()V
-HSPLandroidx/compose/foundation/OverscrollConfigurationKt$LocalOverscrollConfiguration$1;->invoke()Landroidx/compose/foundation/OverscrollConfiguration;
-HSPLandroidx/compose/foundation/OverscrollConfigurationKt$LocalOverscrollConfiguration$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/OverscrollConfigurationKt;-><clinit>()V
-HSPLandroidx/compose/foundation/OverscrollConfigurationKt;->getLocalOverscrollConfiguration()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/foundation/OverscrollKt;->overscroll(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/OverscrollEffect;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/AndroidConfig;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/AndroidConfig;-><init>()V
-HSPLandroidx/compose/foundation/gestures/AndroidScrollable_androidKt;->platformScrollConfig(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/gestures/ScrollConfig;
-HSPLandroidx/compose/foundation/gestures/BringIntoViewRequestPriorityQueue;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier$modifier$1;-><init>(Landroidx/compose/foundation/gestures/ContentInViewModifier;)V
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier;-><init>(Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/foundation/gestures/Orientation;Landroidx/compose/foundation/gestures/ScrollableState;Z)V
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier;->compareTo-TemP2vQ(JJ)I
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier;->getModifier()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier;->onPlaced(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/foundation/gestures/ContentInViewModifier;->onRemeasured-ozmzZPI(J)V
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$drag$2;-><init>(Landroidx/compose/foundation/gestures/DefaultDraggableState;Landroidx/compose/foundation/MutatePriority;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$drag$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$drag$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$drag$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$drag$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$dragScope$1;-><init>(Landroidx/compose/foundation/gestures/DefaultDraggableState;)V
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState$dragScope$1;->dragBy(F)V
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState;->access$getDragScope$p(Landroidx/compose/foundation/gestures/DefaultDraggableState;)Landroidx/compose/foundation/gestures/DragScope;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState;->access$getScrollMutex$p(Landroidx/compose/foundation/gestures/DefaultDraggableState;)Landroidx/compose/foundation/MutatorMutex;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState;->drag(Landroidx/compose/foundation/MutatePriority;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DefaultDraggableState;->getOnDelta()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/foundation/gestures/DefaultFlingBehavior;-><init>(Landroidx/compose/animation/core/DecayAnimationSpec;Landroidx/compose/ui/MotionDurationScale;)V
-HSPLandroidx/compose/foundation/gestures/DefaultFlingBehavior;-><init>(Landroidx/compose/animation/core/DecayAnimationSpec;Landroidx/compose/ui/MotionDurationScale;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/gestures/DefaultScrollableState$scrollScope$1;-><init>(Landroidx/compose/foundation/gestures/DefaultScrollableState;)V
-HSPLandroidx/compose/foundation/gestures/DefaultScrollableState;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt$HorizontalPointerDirectionConfig$1;-><init>()V
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt$VerticalPointerDirectionConfig$1;-><init>()V
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt;->access$isPointerUp-DmW0f2w(Landroidx/compose/ui/input/pointer/PointerEvent;J)Z
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt;->isPointerUp-DmW0f2w(Landroidx/compose/ui/input/pointer/PointerEvent;J)Z
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt;->pointerSlop-E8SPZFQ(Landroidx/compose/ui/platform/ViewConfiguration;I)F
-HSPLandroidx/compose/foundation/gestures/DragGestureDetectorKt;->toPointerDirectionConfig(Landroidx/compose/foundation/gestures/Orientation;)Landroidx/compose/foundation/gestures/PointerDirectionConfig;
-HSPLandroidx/compose/foundation/gestures/DragLogic;-><init>(Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$awaitDownAndSlop$1;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$awaitDownAndSlop$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$awaitDownAndSlop$postPointerSlop$1;-><init>(Landroidx/compose/ui/input/pointer/util/VelocityTracker;Lkotlin/jvm/internal/Ref$LongRef;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$1;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$3;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$3;-><init>()V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$3;->invoke(Landroidx/compose/ui/input/pointer/PointerInputChange;)Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$3;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$4;-><init>(Z)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$4;->invoke()Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$4;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$5;-><init>(Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/gestures/Orientation;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$6;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/interaction/MutableInteractionSource;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$2;-><init>(Lkotlinx/coroutines/channels/Channel;Landroidx/compose/foundation/gestures/DraggableState;Landroidx/compose/runtime/State;Landroidx/compose/foundation/gestures/Orientation;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1$1;-><init>(Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/foundation/gestures/Orientation;Lkotlinx/coroutines/channels/Channel;ZLkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1;-><init>(Landroidx/compose/ui/input/pointer/PointerInputScope;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/foundation/gestures/Orientation;Lkotlinx/coroutines/channels/Channel;ZLkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3;-><init>(ZLandroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/foundation/gestures/Orientation;Lkotlinx/coroutines/channels/Channel;ZLkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9;-><init>(Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/gestures/DraggableState;Landroidx/compose/foundation/gestures/Orientation;ZZ)V
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/DraggableKt$draggable$9;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->DraggableState(Lkotlin/jvm/functions/Function1;)Landroidx/compose/foundation/gestures/DraggableState;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->access$awaitDownAndSlop(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/ui/input/pointer/util/VelocityTracker;Landroidx/compose/foundation/gestures/Orientation;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->awaitDownAndSlop(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/ui/input/pointer/util/VelocityTracker;Landroidx/compose/foundation/gestures/Orientation;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->draggable$default(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/gestures/DraggableState;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->draggable$default(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/gestures/DraggableState;Lkotlin/jvm/functions/Function1;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->draggable(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/gestures/DraggableState;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Z)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/DraggableKt;->draggable(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/gestures/DraggableState;Lkotlin/jvm/functions/Function1;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Z)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/DraggableState;->drag$default(Landroidx/compose/foundation/gestures/DraggableState;Landroidx/compose/foundation/MutatePriority;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt$awaitAllPointersUp$3;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt$awaitEachGesture$2;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt$awaitEachGesture$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt$awaitEachGesture$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt;->allPointersUp(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;)Z
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt;->awaitAllPointersUp(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ForEachGestureKt;->awaitEachGesture(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ModifierLocalScrollableContainerProvider;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/ModifierLocalScrollableContainerProvider;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ModifierLocalScrollableContainerProvider;->getKey()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/gestures/ModifierLocalScrollableContainerProvider;->getValue()Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/gestures/ModifierLocalScrollableContainerProvider;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/Orientation;->$values()[Landroidx/compose/foundation/gestures/Orientation;
-HSPLandroidx/compose/foundation/gestures/Orientation;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/Orientation;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/foundation/gestures/Orientation;->values()[Landroidx/compose/foundation/gestures/Orientation;
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl$reset$1;-><init>(Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl$reset$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl$tryAwaitRelease$1;-><init>(Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl$tryAwaitRelease$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl;-><init>(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl;->release()V
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl;->reset(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/PressGestureScopeImpl;->tryAwaitRelease(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollDraggableState;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/gestures/ScrollableDefaults;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableDefaults;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableDefaults;->flingBehavior(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/gestures/FlingBehavior;
-HSPLandroidx/compose/foundation/gestures/ScrollableDefaults;->overscrollEffect(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/OverscrollEffect;
-HSPLandroidx/compose/foundation/gestures/ScrollableDefaults;->reverseDirection(Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/foundation/gestures/Orientation;Z)Z
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$DefaultScrollMotionDurationScale$1;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$ModifierLocalScrollableContainer$1;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$ModifierLocalScrollableContainer$1;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$ModifierLocalScrollableContainer$1;->invoke()Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$ModifierLocalScrollableContainer$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$NoOpScrollScope$1;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$awaitScrollEvent$1;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$awaitScrollEvent$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1$1;-><init>(Landroidx/compose/foundation/gestures/ScrollConfig;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1;-><init>(Landroidx/compose/foundation/gestures/ScrollConfig;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$1;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$1;-><init>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$2$1;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$3$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/runtime/State;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$scrollable$2;-><init>(Landroidx/compose/foundation/gestures/Orientation;Landroidx/compose/foundation/gestures/ScrollableState;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/gestures/FlingBehavior;Landroidx/compose/foundation/OverscrollEffect;Z)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$scrollable$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$scrollable$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt$scrollableNestedScrollConnection$1;-><init>(Landroidx/compose/runtime/State;Z)V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->access$awaitScrollEvent(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->access$getNoOpScrollScope$p()Landroidx/compose/foundation/gestures/ScrollScope;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->access$pointerScrollable(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/gestures/ScrollableState;Landroidx/compose/foundation/gestures/FlingBehavior;Landroidx/compose/foundation/OverscrollEffect;ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->access$scrollableNestedScrollConnection(Landroidx/compose/runtime/State;Z)Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->awaitScrollEvent(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->getDefaultScrollMotionDurationScale()Landroidx/compose/ui/MotionDurationScale;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->getModifierLocalScrollableContainer()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->mouseWheelScroll(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/State;Landroidx/compose/foundation/gestures/ScrollConfig;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->pointerScrollable(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/gestures/ScrollableState;Landroidx/compose/foundation/gestures/FlingBehavior;Landroidx/compose/foundation/OverscrollEffect;ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->scrollable(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/gestures/ScrollableState;Landroidx/compose/foundation/gestures/Orientation;Landroidx/compose/foundation/OverscrollEffect;ZZLandroidx/compose/foundation/gestures/FlingBehavior;Landroidx/compose/foundation/interaction/MutableInteractionSource;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/gestures/ScrollableKt;->scrollableNestedScrollConnection(Landroidx/compose/runtime/State;Z)Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;
-HSPLandroidx/compose/foundation/gestures/ScrollableStateKt;->ScrollableState(Lkotlin/jvm/functions/Function1;)Landroidx/compose/foundation/gestures/ScrollableState;
-HSPLandroidx/compose/foundation/gestures/ScrollingLogic;-><init>(Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/runtime/State;Landroidx/compose/foundation/gestures/ScrollableState;Landroidx/compose/foundation/gestures/FlingBehavior;Landroidx/compose/foundation/OverscrollEffect;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$NoPressGesture$1;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$awaitFirstDown$2;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$awaitFirstDown$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$1;-><init>(Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$2;-><init>(Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Landroidx/compose/ui/input/pointer/PointerInputChange;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$4;-><init>(Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$4;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$4;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1;-><init>(Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1;->invoke(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2;-><init>(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1;-><init>(Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1;->invoke(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2;-><init>(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$waitForUpOrCancellation$2;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt$waitForUpOrCancellation$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->access$getNoPressGesture$p()Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->awaitFirstDown$default(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;ZLandroidx/compose/ui/input/pointer/PointerEventPass;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->awaitFirstDown(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;ZLandroidx/compose/ui/input/pointer/PointerEventPass;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->detectTapAndPress(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->detectTapGestures$default(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->detectTapGestures(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->waitForUpOrCancellation$default(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Landroidx/compose/ui/input/pointer/PointerEventPass;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/TapGestureDetectorKt;->waitForUpOrCancellation(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Landroidx/compose/ui/input/pointer/PointerEventPass;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/gestures/UpdatableAnimationState$Companion;-><init>()V
-HSPLandroidx/compose/foundation/gestures/UpdatableAnimationState$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/gestures/UpdatableAnimationState;-><clinit>()V
-HSPLandroidx/compose/foundation/gestures/UpdatableAnimationState;-><init>()V
-HSPLandroidx/compose/foundation/interaction/InteractionSourceKt;->MutableInteractionSource()Landroidx/compose/foundation/interaction/MutableInteractionSource;
-HSPLandroidx/compose/foundation/interaction/MutableInteractionSourceImpl;-><init>()V
-HSPLandroidx/compose/foundation/interaction/MutableInteractionSourceImpl;->emit(Landroidx/compose/foundation/interaction/Interaction;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/interaction/MutableInteractionSourceImpl;->getInteractions()Lkotlinx/coroutines/flow/Flow;
-HSPLandroidx/compose/foundation/interaction/MutableInteractionSourceImpl;->getInteractions()Lkotlinx/coroutines/flow/MutableSharedFlow;
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Press;-><clinit>()V
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Press;-><init>(J)V
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Press;-><init>(JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Press;->getPressPosition-F1C5BW0()J
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Release;-><clinit>()V
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Release;-><init>(Landroidx/compose/foundation/interaction/PressInteraction$Press;)V
-HSPLandroidx/compose/foundation/interaction/PressInteraction$Release;->getPress()Landroidx/compose/foundation/interaction/PressInteraction$Press;
-HSPLandroidx/compose/foundation/layout/AndroidWindowInsets;-><init>(ILjava/lang/String;)V
-HSPLandroidx/compose/foundation/layout/AndroidWindowInsets;->getInsets$foundation_layout_release()Landroidx/core/graphics/Insets;
-HSPLandroidx/compose/foundation/layout/AndroidWindowInsets;->getLeft(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/AndroidWindowInsets;->getRight(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/AndroidWindowInsets;->getTop(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/Arrangement$Bottom$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$Center$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$Center$1;->arrange(Landroidx/compose/ui/unit/Density;I[ILandroidx/compose/ui/unit/LayoutDirection;[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$Center$1;->getSpacing-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/Arrangement$End$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$End$1;->arrange(Landroidx/compose/ui/unit/Density;I[ILandroidx/compose/ui/unit/LayoutDirection;[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$Horizontal;->getSpacing-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/Arrangement$SpaceAround$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpaceBetween$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpaceBetween$1;->arrange(Landroidx/compose/ui/unit/Density;I[ILandroidx/compose/ui/unit/LayoutDirection;[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpaceBetween$1;->getSpacing-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/Arrangement$SpaceEvenly$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpacedAligned;-><init>(FZLkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpacedAligned;-><init>(FZLkotlin/jvm/functions/Function2;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpacedAligned;->arrange(Landroidx/compose/ui/unit/Density;I[ILandroidx/compose/ui/unit/LayoutDirection;[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpacedAligned;->arrange(Landroidx/compose/ui/unit/Density;I[I[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$SpacedAligned;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/Arrangement$SpacedAligned;->getSpacing-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/Arrangement$Start$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$Start$1;->arrange(Landroidx/compose/ui/unit/Density;I[ILandroidx/compose/ui/unit/LayoutDirection;[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$Top$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$Top$1;->arrange(Landroidx/compose/ui/unit/Density;I[I[I)V
-HSPLandroidx/compose/foundation/layout/Arrangement$Vertical;->getSpacing-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/Arrangement$spacedBy$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/Arrangement$spacedBy$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/Arrangement;-><init>()V
-HSPLandroidx/compose/foundation/layout/Arrangement;->getCenter()Landroidx/compose/foundation/layout/Arrangement$HorizontalOrVertical;
-HSPLandroidx/compose/foundation/layout/Arrangement;->getEnd()Landroidx/compose/foundation/layout/Arrangement$Horizontal;
-HSPLandroidx/compose/foundation/layout/Arrangement;->getSpaceBetween()Landroidx/compose/foundation/layout/Arrangement$HorizontalOrVertical;
-HSPLandroidx/compose/foundation/layout/Arrangement;->getStart()Landroidx/compose/foundation/layout/Arrangement$Horizontal;
-HSPLandroidx/compose/foundation/layout/Arrangement;->getTop()Landroidx/compose/foundation/layout/Arrangement$Vertical;
-HSPLandroidx/compose/foundation/layout/Arrangement;->placeCenter$foundation_layout_release(I[I[IZ)V
-HSPLandroidx/compose/foundation/layout/Arrangement;->placeLeftOrTop$foundation_layout_release([I[IZ)V
-HSPLandroidx/compose/foundation/layout/Arrangement;->placeRightOrBottom$foundation_layout_release(I[I[IZ)V
-HSPLandroidx/compose/foundation/layout/Arrangement;->placeSpaceBetween$foundation_layout_release(I[I[IZ)V
-HSPLandroidx/compose/foundation/layout/Arrangement;->spacedBy-0680j_4(F)Landroidx/compose/foundation/layout/Arrangement$HorizontalOrVertical;
-HSPLandroidx/compose/foundation/layout/BoxChildData;-><init>(Landroidx/compose/ui/Alignment;ZLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/BoxChildData;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/BoxChildData;->getAlignment()Landroidx/compose/ui/Alignment;
-HSPLandroidx/compose/foundation/layout/BoxChildData;->getMatchParentSize()Z
-HSPLandroidx/compose/foundation/layout/BoxChildData;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Landroidx/compose/foundation/layout/BoxChildData;
-HSPLandroidx/compose/foundation/layout/BoxChildData;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1$measure$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1$measure$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$2;-><init>(Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/layout/Measurable;Landroidx/compose/ui/layout/MeasureScope;IILandroidx/compose/ui/Alignment;)V
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$2;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$5;-><init>([Landroidx/compose/ui/layout/Placeable;Ljava/util/List;Landroidx/compose/ui/layout/MeasureScope;Lkotlin/jvm/internal/Ref$IntRef;Lkotlin/jvm/internal/Ref$IntRef;Landroidx/compose/ui/Alignment;)V
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$5;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$5;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1;-><init>(ZLandroidx/compose/ui/Alignment;)V
-HSPLandroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/BoxKt;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/BoxKt;->Box(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/layout/BoxKt;->access$getMatchesParentSize(Landroidx/compose/ui/layout/Measurable;)Z
-HSPLandroidx/compose/foundation/layout/BoxKt;->access$placeInBox(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/layout/Measurable;Landroidx/compose/ui/unit/LayoutDirection;IILandroidx/compose/ui/Alignment;)V
-HSPLandroidx/compose/foundation/layout/BoxKt;->boxMeasurePolicy(Landroidx/compose/ui/Alignment;Z)Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/foundation/layout/BoxKt;->getBoxChildData(Landroidx/compose/ui/layout/Measurable;)Landroidx/compose/foundation/layout/BoxChildData;
-HSPLandroidx/compose/foundation/layout/BoxKt;->getMatchesParentSize(Landroidx/compose/ui/layout/Measurable;)Z
-HSPLandroidx/compose/foundation/layout/BoxKt;->placeInBox(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/layout/Measurable;Landroidx/compose/ui/unit/LayoutDirection;IILandroidx/compose/ui/Alignment;)V
-HSPLandroidx/compose/foundation/layout/BoxKt;->rememberBoxMeasurePolicy(Landroidx/compose/ui/Alignment;ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/foundation/layout/BoxScopeInstance;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/BoxScopeInstance;-><init>()V
-HSPLandroidx/compose/foundation/layout/BoxScopeInstance;->align(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1;-><init>(Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;I)V
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1;-><init>(Landroidx/compose/ui/layout/MeasurePolicy;Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1;->invoke-0kLqBqw(Landroidx/compose/ui/layout/SubcomposeMeasureScope;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsKt;->BoxWithConstraints(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;ZLkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;-><init>(Landroidx/compose/ui/unit/Density;J)V
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;-><init>(Landroidx/compose/ui/unit/Density;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;->align(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;->getConstraints-msEJaDk()J
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;->getMaxHeight-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;->getMaxWidth-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/ColumnKt$DefaultColumnMeasurePolicy$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/ColumnKt$DefaultColumnMeasurePolicy$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/ColumnKt$DefaultColumnMeasurePolicy$1;->invoke(I[ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;[I)V
-HSPLandroidx/compose/foundation/layout/ColumnKt$DefaultColumnMeasurePolicy$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/ColumnKt$columnMeasurePolicy$1$1;-><init>(Landroidx/compose/foundation/layout/Arrangement$Vertical;)V
-HSPLandroidx/compose/foundation/layout/ColumnKt$columnMeasurePolicy$1$1;->invoke(I[ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;[I)V
-HSPLandroidx/compose/foundation/layout/ColumnKt$columnMeasurePolicy$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/ColumnKt;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/ColumnKt;->columnMeasurePolicy(Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/foundation/layout/ColumnScopeInstance;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/ColumnScopeInstance;-><init>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$CenterCrossAxisAlignment;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$CenterCrossAxisAlignment;-><init>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$Companion;-><init>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$Companion;->horizontal$foundation_layout_release(Landroidx/compose/ui/Alignment$Horizontal;)Landroidx/compose/foundation/layout/CrossAxisAlignment;
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$Companion;->vertical$foundation_layout_release(Landroidx/compose/ui/Alignment$Vertical;)Landroidx/compose/foundation/layout/CrossAxisAlignment;
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$EndCrossAxisAlignment;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$EndCrossAxisAlignment;-><init>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$HorizontalCrossAxisAlignment;-><init>(Landroidx/compose/ui/Alignment$Horizontal;)V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$HorizontalCrossAxisAlignment;->align$foundation_layout_release(ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/layout/Placeable;I)I
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$StartCrossAxisAlignment;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$StartCrossAxisAlignment;-><init>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$VerticalCrossAxisAlignment;-><init>(Landroidx/compose/ui/Alignment$Vertical;)V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment$VerticalCrossAxisAlignment;->align$foundation_layout_release(ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/layout/Placeable;I)I
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment;-><init>()V
-HSPLandroidx/compose/foundation/layout/CrossAxisAlignment;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/Direction;->$values()[Landroidx/compose/foundation/layout/Direction;
-HSPLandroidx/compose/foundation/layout/Direction;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/Direction;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/foundation/layout/ExcludeInsets;-><init>(Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/foundation/layout/WindowInsets;)V
-HSPLandroidx/compose/foundation/layout/ExcludeInsets;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/ExcludeInsets;->getBottom(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/ExcludeInsets;->getLeft(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/ExcludeInsets;->getRight(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/ExcludeInsets;->getTop(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/FillModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/foundation/layout/FillModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/FillModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/FillModifier;-><init>(Landroidx/compose/foundation/layout/Direction;FLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/FillModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/FillModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/FixedIntInsets;-><init>(IIII)V
-HSPLandroidx/compose/foundation/layout/FixedIntInsets;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/FixedIntInsets;->getBottom(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/FixedIntInsets;->getLeft(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/FixedIntInsets;->getRight(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/FixedIntInsets;->getTop(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/InsetsListener;-><init>(Landroidx/compose/foundation/layout/WindowInsetsHolder;)V
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;II)V
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;-><init>(Landroidx/compose/foundation/layout/WindowInsets;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;->getKey()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;->getUnconsumedInsets()Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;->onModifierLocalsUpdated(Landroidx/compose/ui/modifier/ModifierLocalReadScope;)V
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;->setConsumedInsets(Landroidx/compose/foundation/layout/WindowInsets;)V
-HSPLandroidx/compose/foundation/layout/InsetsPaddingModifier;->setUnconsumedInsets(Landroidx/compose/foundation/layout/WindowInsets;)V
-HSPLandroidx/compose/foundation/layout/InsetsValues;-><init>(IIII)V
-HSPLandroidx/compose/foundation/layout/LayoutOrientation;->$values()[Landroidx/compose/foundation/layout/LayoutOrientation;
-HSPLandroidx/compose/foundation/layout/LayoutOrientation;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/LayoutOrientation;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/foundation/layout/LayoutWeightImpl;-><init>(FZLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/LayoutWeightImpl;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Landroidx/compose/foundation/layout/RowColumnParentData;
-HSPLandroidx/compose/foundation/layout/LayoutWeightImpl;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/LimitInsets;-><init>(Landroidx/compose/foundation/layout/WindowInsets;I)V
-HSPLandroidx/compose/foundation/layout/LimitInsets;-><init>(Landroidx/compose/foundation/layout/WindowInsets;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/LimitInsets;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/LimitInsets;->getBottom(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/LimitInsets;->getLeft(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/LimitInsets;->getRight(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/foundation/layout/LimitInsets;->getTop(Landroidx/compose/ui/unit/Density;)I
-HSPLandroidx/compose/foundation/layout/OffsetKt;->offset(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier$measure$1;-><init>(Landroidx/compose/foundation/layout/OffsetPxModifier;Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier;-><init>(Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier;->getOffset()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier;->getRtlAware()Z
-HSPLandroidx/compose/foundation/layout/OffsetPxModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;-><init>(IIII)V
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;-><init>(JLandroidx/compose/foundation/layout/LayoutOrientation;)V
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;-><init>(JLandroidx/compose/foundation/layout/LayoutOrientation;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->copy$default(Landroidx/compose/foundation/layout/OrientationIndependentConstraints;IIIIILjava/lang/Object;)Landroidx/compose/foundation/layout/OrientationIndependentConstraints;
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->copy(IIII)Landroidx/compose/foundation/layout/OrientationIndependentConstraints;
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->getCrossAxisMax()I
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->getCrossAxisMin()I
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->getMainAxisMax()I
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->getMainAxisMin()I
-HSPLandroidx/compose/foundation/layout/OrientationIndependentConstraints;->toBoxConstraints-OenEA2s(Landroidx/compose/foundation/layout/LayoutOrientation;)J
-HSPLandroidx/compose/foundation/layout/PaddingKt;->PaddingValues-0680j_4(F)Landroidx/compose/foundation/layout/PaddingValues;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->PaddingValues-YgX7TsA$default(FFILjava/lang/Object;)Landroidx/compose/foundation/layout/PaddingValues;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->PaddingValues-YgX7TsA(FF)Landroidx/compose/foundation/layout/PaddingValues;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->PaddingValues-a9UjIt4(FFFF)Landroidx/compose/foundation/layout/PaddingValues;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->padding(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->padding-VpY3zN4$default(Landroidx/compose/ui/Modifier;FFILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->padding-VpY3zN4(Landroidx/compose/ui/Modifier;FF)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->padding-qDBjuR0$default(Landroidx/compose/ui/Modifier;FFFFILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/PaddingKt;->padding-qDBjuR0(Landroidx/compose/ui/Modifier;FFFF)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/PaddingModifier$measure$1;-><init>(Landroidx/compose/foundation/layout/PaddingModifier;Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/layout/MeasureScope;)V
-HSPLandroidx/compose/foundation/layout/PaddingModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/PaddingModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/PaddingModifier;-><init>(FFFFZLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/PaddingModifier;-><init>(FFFFZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/PaddingModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/PaddingModifier;->getRtlAware()Z
-HSPLandroidx/compose/foundation/layout/PaddingModifier;->getStart-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/PaddingModifier;->getTop-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/PaddingModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;-><init>(FFFF)V
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;-><init>(FFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;->calculateBottomPadding-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;->calculateLeftPadding-u2uoSUM(Landroidx/compose/ui/unit/LayoutDirection;)F
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;->calculateRightPadding-u2uoSUM(Landroidx/compose/ui/unit/LayoutDirection;)F
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;->calculateTopPadding-D9Ej5fM()F
-HSPLandroidx/compose/foundation/layout/PaddingValuesImpl;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier$measure$2;-><init>(Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/foundation/layout/PaddingValuesModifier;)V
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier$measure$2;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier$measure$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier;-><init>(Landroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier;->getPaddingValues()Landroidx/compose/foundation/layout/PaddingValues;
-HSPLandroidx/compose/foundation/layout/PaddingValuesModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1$measure$1;-><init>(Landroidx/compose/foundation/layout/RowColumnMeasurementHelper;Landroidx/compose/foundation/layout/RowColumnMeasureHelperResult;Landroidx/compose/ui/layout/MeasureScope;)V
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1;-><init>(Landroidx/compose/foundation/layout/LayoutOrientation;Lkotlin/jvm/functions/Function5;FLandroidx/compose/foundation/layout/SizeMode;Landroidx/compose/foundation/layout/CrossAxisAlignment;)V
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt;->getCrossAxisAlignment(Landroidx/compose/foundation/layout/RowColumnParentData;)Landroidx/compose/foundation/layout/CrossAxisAlignment;
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt;->getFill(Landroidx/compose/foundation/layout/RowColumnParentData;)Z
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt;->getRowColumnParentData(Landroidx/compose/ui/layout/IntrinsicMeasurable;)Landroidx/compose/foundation/layout/RowColumnParentData;
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt;->getWeight(Landroidx/compose/foundation/layout/RowColumnParentData;)F
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt;->isRelative(Landroidx/compose/foundation/layout/RowColumnParentData;)Z
-HSPLandroidx/compose/foundation/layout/RowColumnImplKt;->rowColumnMeasurePolicy-TDGSqEk(Landroidx/compose/foundation/layout/LayoutOrientation;Lkotlin/jvm/functions/Function5;FLandroidx/compose/foundation/layout/SizeMode;Landroidx/compose/foundation/layout/CrossAxisAlignment;)Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;-><init>(IIIII[I)V
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;->getBeforeCrossAxisAlignmentLine()I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;->getCrossAxisSize()I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;->getEndIndex()I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;->getMainAxisPositions()[I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;->getMainAxisSize()I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasureHelperResult;->getStartIndex()I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;-><init>(Landroidx/compose/foundation/layout/LayoutOrientation;Lkotlin/jvm/functions/Function5;FLandroidx/compose/foundation/layout/SizeMode;Landroidx/compose/foundation/layout/CrossAxisAlignment;Ljava/util/List;[Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;-><init>(Landroidx/compose/foundation/layout/LayoutOrientation;Lkotlin/jvm/functions/Function5;FLandroidx/compose/foundation/layout/SizeMode;Landroidx/compose/foundation/layout/CrossAxisAlignment;Ljava/util/List;[Landroidx/compose/ui/layout/Placeable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;->crossAxisSize(Landroidx/compose/ui/layout/Placeable;)I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;->getCrossAxisPosition(Landroidx/compose/ui/layout/Placeable;Landroidx/compose/foundation/layout/RowColumnParentData;ILandroidx/compose/ui/unit/LayoutDirection;I)I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;->mainAxisPositions(I[I[ILandroidx/compose/ui/layout/MeasureScope;)[I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;->mainAxisSize(Landroidx/compose/ui/layout/Placeable;)I
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;->measureWithoutPlacing-_EkL_-Y(Landroidx/compose/ui/layout/MeasureScope;JII)Landroidx/compose/foundation/layout/RowColumnMeasureHelperResult;
-HSPLandroidx/compose/foundation/layout/RowColumnMeasurementHelper;->placeHelper(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/foundation/layout/RowColumnMeasureHelperResult;ILandroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;-><init>(FZLandroidx/compose/foundation/layout/CrossAxisAlignment;)V
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;-><init>(FZLandroidx/compose/foundation/layout/CrossAxisAlignment;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;->getCrossAxisAlignment()Landroidx/compose/foundation/layout/CrossAxisAlignment;
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;->getFill()Z
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;->getWeight()F
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;->setFill(Z)V
-HSPLandroidx/compose/foundation/layout/RowColumnParentData;->setWeight(F)V
-HSPLandroidx/compose/foundation/layout/RowKt$DefaultRowMeasurePolicy$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/RowKt$DefaultRowMeasurePolicy$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/RowKt$DefaultRowMeasurePolicy$1;->invoke(I[ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;[I)V
-HSPLandroidx/compose/foundation/layout/RowKt$DefaultRowMeasurePolicy$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/RowKt$rowMeasurePolicy$1$1;-><init>(Landroidx/compose/foundation/layout/Arrangement$Horizontal;)V
-HSPLandroidx/compose/foundation/layout/RowKt$rowMeasurePolicy$1$1;->invoke(I[ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;[I)V
-HSPLandroidx/compose/foundation/layout/RowKt$rowMeasurePolicy$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/RowKt;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/RowKt;->rowMeasurePolicy(Landroidx/compose/foundation/layout/Arrangement$Horizontal;Landroidx/compose/ui/Alignment$Vertical;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/foundation/layout/RowScope;->weight$default(Landroidx/compose/foundation/layout/RowScope;Landroidx/compose/ui/Modifier;FZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/RowScopeInstance;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/RowScopeInstance;-><init>()V
-HSPLandroidx/compose/foundation/layout/RowScopeInstance;->weight(Landroidx/compose/ui/Modifier;FZ)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt$createFillHeightModifier$1;-><init>(F)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createFillSizeModifier$1;-><init>(F)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createFillWidthModifier$1;-><init>(F)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentHeightModifier$1;-><init>(Landroidx/compose/ui/Alignment$Vertical;)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentHeightModifier$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentHeightModifier$1;->invoke-5SAbXVA(JLandroidx/compose/ui/unit/LayoutDirection;)J
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentHeightModifier$2;-><init>(Landroidx/compose/ui/Alignment$Vertical;Z)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentSizeModifier$1;-><init>(Landroidx/compose/ui/Alignment;)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentSizeModifier$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentSizeModifier$1;->invoke-5SAbXVA(JLandroidx/compose/ui/unit/LayoutDirection;)J
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentSizeModifier$2;-><init>(Landroidx/compose/ui/Alignment;Z)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentWidthModifier$1;-><init>(Landroidx/compose/ui/Alignment$Horizontal;)V
-HSPLandroidx/compose/foundation/layout/SizeKt$createWrapContentWidthModifier$2;-><init>(Landroidx/compose/ui/Alignment$Horizontal;Z)V
-HSPLandroidx/compose/foundation/layout/SizeKt;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/SizeKt;->createFillHeightModifier(F)Landroidx/compose/foundation/layout/FillModifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->createFillSizeModifier(F)Landroidx/compose/foundation/layout/FillModifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->createFillWidthModifier(F)Landroidx/compose/foundation/layout/FillModifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->createWrapContentHeightModifier(Landroidx/compose/ui/Alignment$Vertical;Z)Landroidx/compose/foundation/layout/WrapContentModifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->createWrapContentSizeModifier(Landroidx/compose/ui/Alignment;Z)Landroidx/compose/foundation/layout/WrapContentModifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->createWrapContentWidthModifier(Landroidx/compose/ui/Alignment$Horizontal;Z)Landroidx/compose/foundation/layout/WrapContentModifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->defaultMinSize-VpY3zN4$default(Landroidx/compose/ui/Modifier;FFILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->defaultMinSize-VpY3zN4(Landroidx/compose/ui/Modifier;FF)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->fillMaxSize$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->fillMaxSize(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->fillMaxWidth$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->fillMaxWidth(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->heightIn-VpY3zN4$default(Landroidx/compose/ui/Modifier;FFILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->heightIn-VpY3zN4(Landroidx/compose/ui/Modifier;FF)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->size-3ABfNKs(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->sizeIn-qDBjuR0$default(Landroidx/compose/ui/Modifier;FFFFILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->sizeIn-qDBjuR0(Landroidx/compose/ui/Modifier;FFFF)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->width-3ABfNKs(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->wrapContentHeight$default(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment$Vertical;ZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->wrapContentHeight(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment$Vertical;Z)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->wrapContentSize$default(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;ZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeKt;->wrapContentSize(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Alignment;Z)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/SizeMode;->$values()[Landroidx/compose/foundation/layout/SizeMode;
-HSPLandroidx/compose/foundation/layout/SizeMode;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/SizeMode;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/foundation/layout/SizeModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/foundation/layout/SizeModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/SizeModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/SizeModifier;-><init>(FFFFZLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/SizeModifier;-><init>(FFFFZLkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/SizeModifier;-><init>(FFFFZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/SizeModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/SizeModifier;->getTargetConstraints-OenEA2s(Landroidx/compose/ui/unit/Density;)J
-HSPLandroidx/compose/foundation/layout/SizeModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/SpacerKt;->Spacer(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy$measure$1$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy$measure$1$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy$measure$1$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy$measure$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy;-><init>()V
-HSPLandroidx/compose/foundation/layout/SpacerMeasurePolicy;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/UnionInsets;-><init>(Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/foundation/layout/WindowInsets;)V
-HSPLandroidx/compose/foundation/layout/UnionInsets;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier;-><init>(FFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier;-><init>(FFLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/UnspecifiedConstraintsModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/layout/ValueInsets;-><init>(Landroidx/compose/foundation/layout/InsetsValues;Ljava/lang/String;)V
-HSPLandroidx/compose/foundation/layout/WindowInsets$Companion;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/WindowInsets$Companion;-><init>()V
-HSPLandroidx/compose/foundation/layout/WindowInsets;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/foundation/layout/WindowInsetsHolder;Landroid/view/View;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1;-><init>(Landroidx/compose/foundation/layout/WindowInsetsHolder;Landroid/view/View;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;-><init>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;->access$systemInsets(Landroidx/compose/foundation/layout/WindowInsetsHolder$Companion;Landroidx/core/view/WindowInsetsCompat;ILjava/lang/String;)Landroidx/compose/foundation/layout/AndroidWindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;->access$valueInsetsIgnoringVisibility(Landroidx/compose/foundation/layout/WindowInsetsHolder$Companion;Landroidx/core/view/WindowInsetsCompat;ILjava/lang/String;)Landroidx/compose/foundation/layout/ValueInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;->current(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/layout/WindowInsetsHolder;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;->getOrCreateFor(Landroid/view/View;)Landroidx/compose/foundation/layout/WindowInsetsHolder;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;->systemInsets(Landroidx/core/view/WindowInsetsCompat;ILjava/lang/String;)Landroidx/compose/foundation/layout/AndroidWindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder$Companion;->valueInsetsIgnoringVisibility(Landroidx/core/view/WindowInsetsCompat;ILjava/lang/String;)Landroidx/compose/foundation/layout/ValueInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;-><init>(Landroidx/core/view/WindowInsetsCompat;Landroid/view/View;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;-><init>(Landroidx/core/view/WindowInsetsCompat;Landroid/view/View;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;->access$getViewMap$cp()Ljava/util/WeakHashMap;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;->decrementAccessors(Landroid/view/View;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;->getConsumes()Z
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;->getSystemBars()Landroidx/compose/foundation/layout/AndroidWindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsHolder;->incrementAccessors(Landroid/view/View;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsKt;->WindowInsets(IIII)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsKt;->exclude(Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/foundation/layout/WindowInsets;)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsKt;->only-bOOhFvg(Landroidx/compose/foundation/layout/WindowInsets;I)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsKt;->union(Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/foundation/layout/WindowInsets;)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt$ModifierLocalConsumedWindowInsets$1;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt$ModifierLocalConsumedWindowInsets$1;-><init>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt$ModifierLocalConsumedWindowInsets$1;->invoke()Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt$ModifierLocalConsumedWindowInsets$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt;->getModifierLocalConsumedWindowInsets()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/layout/WindowInsetsPaddingKt;->windowInsetsPadding(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/WindowInsets;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;-><init>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;->getAllowLeftInLtr-JoeWqyM$foundation_layout_release()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;->getAllowRightInLtr-JoeWqyM$foundation_layout_release()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;->getBottom-JoeWqyM()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;->getHorizontal-JoeWqyM()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides$Companion;->getTop-JoeWqyM()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;-><clinit>()V
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->access$getAllowLeftInLtr$cp()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->access$getAllowRightInLtr$cp()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->access$getBottom$cp()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->access$getHorizontal$cp()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->access$getTop$cp()I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->constructor-impl(I)I
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->hasAny-bkgdKaI$foundation_layout_release(II)Z
-HSPLandroidx/compose/foundation/layout/WindowInsetsSides;->plus-gK_yJZ4(II)I
-HSPLandroidx/compose/foundation/layout/WindowInsets_androidKt;->ValueInsets(Landroidx/core/graphics/Insets;Ljava/lang/String;)Landroidx/compose/foundation/layout/ValueInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsets_androidKt;->getSystemBars(Landroidx/compose/foundation/layout/WindowInsets$Companion;Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/foundation/layout/WindowInsets_androidKt;->toInsetsValues(Landroidx/core/graphics/Insets;)Landroidx/compose/foundation/layout/InsetsValues;
-HSPLandroidx/compose/foundation/layout/WrapContentModifier$measure$1;-><init>(Landroidx/compose/foundation/layout/WrapContentModifier;ILandroidx/compose/ui/layout/Placeable;ILandroidx/compose/ui/layout/MeasureScope;)V
-HSPLandroidx/compose/foundation/layout/WrapContentModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/layout/WrapContentModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/layout/WrapContentModifier;-><init>(Landroidx/compose/foundation/layout/Direction;ZLkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/layout/WrapContentModifier;->access$getAlignmentCallback$p(Landroidx/compose/foundation/layout/WrapContentModifier;)Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/foundation/layout/WrapContentModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/layout/WrapContentModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/lazy/AwaitFirstLayoutModifier;-><init>()V
-HSPLandroidx/compose/foundation/lazy/AwaitFirstLayoutModifier;->onGloballyPositioned(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/foundation/lazy/DataIndex;-><init>(I)V
-HSPLandroidx/compose/foundation/lazy/DataIndex;->box-impl(I)Landroidx/compose/foundation/lazy/DataIndex;
-HSPLandroidx/compose/foundation/lazy/DataIndex;->constructor-impl(I)I
-HSPLandroidx/compose/foundation/lazy/DataIndex;->equals-impl0(II)Z
-HSPLandroidx/compose/foundation/lazy/DataIndex;->unbox-impl()I
-HSPLandroidx/compose/foundation/lazy/EmptyLazyListLayoutInfo;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/EmptyLazyListLayoutInfo;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyBeyondBoundsModifierKt;->lazyListBeyondBoundsModifier(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;ZLandroidx/compose/foundation/gestures/Orientation;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/lazy/LazyDslKt;->LazyColumn(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/layout/PaddingValues;ZLandroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/foundation/gestures/FlingBehavior;ZLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/foundation/lazy/LazyItemScopeImpl;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyItemScopeImpl;->setMaxSize(II)V
-HSPLandroidx/compose/foundation/lazy/LazyListAnimateScrollScope;-><init>(Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;->hasIntervals()Z
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal$Companion$emptyBeyondBoundsScope$1;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal$Companion;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal;-><init>(Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;ZLandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/foundation/gestures/Orientation;)V
-HSPLandroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal;->getKey()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/lazy/LazyListIntervalContent;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)V
-HSPLandroidx/compose/foundation/lazy/LazyListIntervalContent;->getItem()Lkotlin/jvm/functions/Function4;
-HSPLandroidx/compose/foundation/lazy/LazyListIntervalContent;->getKey()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/foundation/lazy/LazyListIntervalContent;->getType()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;-><init>(Lkotlinx/coroutines/CoroutineScope;Z)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;->onMeasured(IIILjava/util/List;Landroidx/compose/foundation/lazy/LazyMeasuredItemProvider;)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;->reset()V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl$1$1;-><init>(Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;Landroidx/compose/foundation/lazy/LazyItemScopeImpl;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl$1;-><init>(Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/LazyItemScopeImpl;)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl$1;->invoke(Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;ILandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;-><init>(Landroidx/compose/foundation/lazy/layout/IntervalList;Lkotlin/ranges/IntRange;Ljava/util/List;Landroidx/compose/foundation/lazy/LazyItemScopeImpl;Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->Item(ILandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->getContentType(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->getHeaderIndexes()Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->getItemCount()I
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->getItemScope()Landroidx/compose/foundation/lazy/LazyItemScopeImpl;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->getKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderImpl;->getKeyToIndexMap()Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->Item(ILandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->getContentType(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->getHeaderIndexes()Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->getItemCount()I
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->getItemScope()Landroidx/compose/foundation/lazy/LazyItemScopeImpl;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->getKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;->getKeyToIndexMap()Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$itemProviderState$1;-><init>(Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/foundation/lazy/LazyItemScopeImpl;Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$itemProviderState$1;->invoke()Landroidx/compose/foundation/lazy/LazyListItemProviderImpl;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$itemProviderState$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$1$1;-><init>(Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$1$1;->invoke()Ljava/lang/Integer;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$2;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$2;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$2;->invoke()Ljava/lang/Integer;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$3;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$3;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$3;->invoke()Ljava/lang/Integer;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$3;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListItemProviderKt;->rememberLazyListItemProvider(Landroidx/compose/foundation/lazy/LazyListState;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/lazy/LazyListItemProvider;
-HSPLandroidx/compose/foundation/lazy/LazyListKt$ScrollPositionUpdater$1;-><init>(Landroidx/compose/foundation/lazy/LazyListItemProvider;Landroidx/compose/foundation/lazy/LazyListState;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$2;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope;JII)V
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$2;->invoke(IILkotlin/jvm/functions/Function1;)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$measuredItemProvider$1;-><init>(IILandroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope;ZLandroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Vertical;ZIILandroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;J)V
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$measuredItemProvider$1;->createItem-HK0c1C0(ILjava/lang/Object;Ljava/util/List;)Landroidx/compose/foundation/lazy/LazyMeasuredItem;
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1;-><init>(ZLandroidx/compose/foundation/layout/PaddingValues;ZLandroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/LazyListItemProvider;Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;ILandroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Vertical;)V
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1;->invoke-0kLqBqw(Landroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope;J)Landroidx/compose/foundation/lazy/LazyListMeasureResult;
-HSPLandroidx/compose/foundation/lazy/LazyListKt;->LazyList(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/layout/PaddingValues;ZZLandroidx/compose/foundation/gestures/FlingBehavior;ZILandroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/ui/Alignment$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;III)V
-HSPLandroidx/compose/foundation/lazy/LazyListKt;->ScrollPositionUpdater(Landroidx/compose/foundation/lazy/LazyListItemProvider;Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListKt;->rememberLazyListMeasurePolicy(Landroidx/compose/foundation/lazy/LazyListItemProvider;Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;Landroidx/compose/foundation/layout/PaddingValues;ZZILandroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;Landroidx/compose/runtime/Composer;III)Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt$measureLazyList$5;-><init>(Ljava/util/List;Landroidx/compose/foundation/lazy/LazyListPositionedItem;)V
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt$measureLazyList$5;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt$measureLazyList$5;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt;->calculateItemsOffsets(Ljava/util/List;Ljava/util/List;Ljava/util/List;IIIIIZLandroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;ZLandroidx/compose/ui/unit/Density;)Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt;->createItemsAfterList(Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;Ljava/util/List;Landroidx/compose/foundation/lazy/LazyMeasuredItemProvider;IILandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;)Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt;->createItemsBeforeList-_ok666U(Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;ILandroidx/compose/foundation/lazy/LazyMeasuredItemProvider;IILandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;)Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureKt;->measureLazyList-QaF8Ofo(ILandroidx/compose/foundation/lazy/LazyMeasuredItemProvider;IIIIIIFJZLjava/util/List;Landroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;ZLandroidx/compose/ui/unit/Density;Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;ILandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;Lkotlin/jvm/functions/Function3;)Landroidx/compose/foundation/lazy/LazyListMeasureResult;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;-><init>(Landroidx/compose/foundation/lazy/LazyMeasuredItem;IZFLandroidx/compose/ui/layout/MeasureResult;Ljava/util/List;IIIZLandroidx/compose/foundation/gestures/Orientation;II)V
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getAlignmentLines()Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getCanScrollForward()Z
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getConsumedScroll()F
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getFirstVisibleItem()Landroidx/compose/foundation/lazy/LazyMeasuredItem;
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getFirstVisibleItemScrollOffset()I
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getHeight()I
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getTotalItemsCount()I
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->getWidth()I
-HSPLandroidx/compose/foundation/lazy/LazyListMeasureResult;->placeChildren()V
-HSPLandroidx/compose/foundation/lazy/LazyListPlaceableWrapper;-><init>(JLandroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/foundation/lazy/LazyListPlaceableWrapper;-><init>(JLandroidx/compose/ui/layout/Placeable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/LazyListPlaceableWrapper;->getOffset-nOcc-ac()J
-HSPLandroidx/compose/foundation/lazy/LazyListPlaceableWrapper;->getPlaceable()Landroidx/compose/ui/layout/Placeable;
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;-><init>(IILjava/lang/Object;IIIZLjava/util/List;Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;JZI)V
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;-><init>(IILjava/lang/Object;IIIZLjava/util/List;Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;JZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;->getAnimationSpec(I)Landroidx/compose/animation/core/FiniteAnimationSpec;
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;->getHasAnimations()Z
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;->getMainAxisSize(Landroidx/compose/ui/layout/Placeable;)I
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;->getOffset-Bjo55l4(I)J
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;->getPlaceablesCount()I
-HSPLandroidx/compose/foundation/lazy/LazyListPositionedItem;->place(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScope;->item$default(Landroidx/compose/foundation/lazy/LazyListScope;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl$item$2;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl$item$2;->invoke(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl$item$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl$item$3;-><init>(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl$item$3;->invoke(Landroidx/compose/foundation/lazy/LazyItemScope;ILandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl$item$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl;->getHeaderIndexes()Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl;->getIntervals()Landroidx/compose/foundation/lazy/layout/IntervalList;
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl;->item(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScopeImpl;->items(ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScrollPosition;-><init>(II)V
-HSPLandroidx/compose/foundation/lazy/LazyListScrollPosition;->getIndex-jQJCoq8()I
-HSPLandroidx/compose/foundation/lazy/LazyListScrollPosition;->getScrollOffset()I
-HSPLandroidx/compose/foundation/lazy/LazyListScrollPosition;->update-AhXoVpI(II)V
-HSPLandroidx/compose/foundation/lazy/LazyListScrollPosition;->updateFromMeasureResult(Landroidx/compose/foundation/lazy/LazyListMeasureResult;)V
-HSPLandroidx/compose/foundation/lazy/LazyListScrollPosition;->updateScrollPositionIfTheFirstItemWasMoved(Landroidx/compose/foundation/lazy/LazyListItemProvider;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion$Saver$1;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion$Saver$1;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion$Saver$1;->invoke(Landroidx/compose/runtime/saveable/SaverScope;Landroidx/compose/foundation/lazy/LazyListState;)Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion$Saver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion$Saver$2;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion$Saver$2;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion;-><init>()V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState$Companion;->getSaver()Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/foundation/lazy/LazyListState$remeasurementModifier$1;-><init>(Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState$remeasurementModifier$1;->onRemeasurementAvailable(Landroidx/compose/ui/layout/Remeasurement;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState$scrollableState$1;-><init>(Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/LazyListState;-><init>(II)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->access$getSaver$cp()Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/foundation/lazy/LazyListState;->access$setRemeasurement(Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/ui/layout/Remeasurement;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->applyMeasureResult$foundation_release(Landroidx/compose/foundation/lazy/LazyListMeasureResult;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->cancelPrefetchIfVisibleItemsChanged(Landroidx/compose/foundation/lazy/LazyListLayoutInfo;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getAwaitLayoutModifier$foundation_release()Landroidx/compose/foundation/lazy/AwaitFirstLayoutModifier;
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getFirstVisibleItemIndex()I
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getFirstVisibleItemScrollOffset()I
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getInternalInteractionSource$foundation_release()Landroidx/compose/foundation/interaction/MutableInteractionSource;
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getPinnedItems$foundation_release()Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getPrefetchState$foundation_release()Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getRemeasurementModifier$foundation_release()Landroidx/compose/ui/layout/RemeasurementModifier;
-HSPLandroidx/compose/foundation/lazy/LazyListState;->getScrollToBeConsumed$foundation_release()F
-HSPLandroidx/compose/foundation/lazy/LazyListState;->setCanScrollBackward(Z)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->setCanScrollForward(Z)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->setDensity$foundation_release(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->setPlacementAnimator$foundation_release(Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->setPremeasureConstraints-BRTryo0$foundation_release(J)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->setRemeasurement(Landroidx/compose/ui/layout/Remeasurement;)V
-HSPLandroidx/compose/foundation/lazy/LazyListState;->updateScrollPositionIfTheFirstItemWasMoved$foundation_release(Landroidx/compose/foundation/lazy/LazyListItemProvider;)V
-HSPLandroidx/compose/foundation/lazy/LazyListStateKt$rememberLazyListState$1$1;-><init>(II)V
-HSPLandroidx/compose/foundation/lazy/LazyListStateKt$rememberLazyListState$1$1;->invoke()Landroidx/compose/foundation/lazy/LazyListState;
-HSPLandroidx/compose/foundation/lazy/LazyListStateKt$rememberLazyListState$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyListStateKt;->rememberLazyListState(IILandroidx/compose/runtime/Composer;II)Landroidx/compose/foundation/lazy/LazyListState;
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;-><init>(ILjava/util/List;ZLandroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Vertical;Landroidx/compose/ui/unit/LayoutDirection;ZIILandroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;IJLjava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;-><init>(ILjava/util/List;ZLandroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Vertical;Landroidx/compose/ui/unit/LayoutDirection;ZIILandroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;IJLjava/lang/Object;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;->getCrossAxisSize()I
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;->getIndex()I
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;->getKey()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;->getSizeWithSpacings()I
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItem;->position(III)Landroidx/compose/foundation/lazy/LazyListPositionedItem;
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItemProvider;-><init>(JZLandroidx/compose/foundation/lazy/LazyListItemProvider;Landroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope;Landroidx/compose/foundation/lazy/MeasuredItemFactory;)V
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItemProvider;-><init>(JZLandroidx/compose/foundation/lazy/LazyListItemProvider;Landroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope;Landroidx/compose/foundation/lazy/MeasuredItemFactory;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItemProvider;->getAndMeasure-ZjPyQlc(I)Landroidx/compose/foundation/lazy/LazyMeasuredItem;
-HSPLandroidx/compose/foundation/lazy/LazyMeasuredItemProvider;->getChildConstraints-msEJaDk()J
-HSPLandroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1$scrollAxisRange$1;-><init>(Landroidx/compose/foundation/lazy/LazyListState;)V
-HSPLandroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1$scrollAxisRange$2;-><init>(Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;)V
-HSPLandroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1;-><init>(ZLandroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;Z)V
-HSPLandroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1;->collectionInfo()Landroidx/compose/ui/semantics/CollectionInfo;
-HSPLandroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1;->scrollAxisRange()Landroidx/compose/ui/semantics/ScrollAxisRange;
-HSPLandroidx/compose/foundation/lazy/LazySemanticsKt;->rememberLazyListSemanticState(Landroidx/compose/foundation/lazy/LazyListState;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;ZZLandroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticState;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider$Item$1;-><init>(Landroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;II)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;->Item(ILandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;->getContentType(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;->getItemCount()I
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;->getKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;->getKeyToIndexMap()Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey$Companion$CREATOR$1;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey$Companion;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey;-><init>(I)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyKey;->hashCode()I
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider$generateKeyToIndexMap$1$1;-><init>(IILjava/util/HashMap;)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider$generateKeyToIndexMap$1$1;->invoke(Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider$generateKeyToIndexMap$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;-><init>(Lkotlin/jvm/functions/Function4;Landroidx/compose/foundation/lazy/layout/IntervalList;Lkotlin/ranges/IntRange;)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;->Item(ILandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;->generateKeyToIndexMap(Lkotlin/ranges/IntRange;Landroidx/compose/foundation/lazy/layout/IntervalList;)Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;->getContentType(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;->getItemCount()I
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;->getKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;->getKeyToIndexMap()Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/layout/IntervalList$Interval;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/IntervalList$Interval;-><init>(IILjava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/layout/IntervalList$Interval;->getSize()I
-HSPLandroidx/compose/foundation/lazy/layout/IntervalList$Interval;->getStartIndex()I
-HSPLandroidx/compose/foundation/lazy/layout/IntervalList$Interval;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/IntervalListKt;->access$binarySearch(Landroidx/compose/runtime/collection/MutableVector;I)I
-HSPLandroidx/compose/foundation/lazy/layout/IntervalListKt;->binarySearch(Landroidx/compose/runtime/collection/MutableVector;I)I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;ILjava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;->access$set_content$p(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;->createContentLambda()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;->getContent()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;->getKey()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;->getLastKnownIndex()I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;->getType()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;-><init>(Landroidx/compose/runtime/saveable/SaveableStateHolder;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;->access$getSaveableStateHolder$p(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;)Landroidx/compose/runtime/saveable/SaveableStateHolder;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;->getContent(ILjava/lang/Object;)Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;->getItemProvider()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemProviderKt;->DelegatingLazyLayoutItemProvider(Landroidx/compose/runtime/State;)Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemProviderKt;->LazyLayoutItemProvider(Landroidx/compose/foundation/lazy/layout/IntervalList;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function4;)Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemProviderKt;->findIndexByKey(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;Ljava/lang/Object;I)I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutItemReusePolicy;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$2$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$2$1;->invoke-0kLqBqw(Landroidx/compose/ui/layout/SubcomposeMeasureScope;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$itemContentFactory$1$1;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$itemContentFactory$1$1;->invoke()Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$itemContentFactory$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;ILandroidx/compose/runtime/State;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1;->invoke(Landroidx/compose/runtime/saveable/SaveableStateHolder;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutKt;->LazyLayout(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScopeImpl;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;Landroidx/compose/ui/layout/SubcomposeMeasureScope;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScopeImpl;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScopeImpl;->layout(IILjava/util/Map;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScopeImpl;->measure-0kLqBqw(IJ)Ljava/util/List;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScopeImpl;->roundToPx-0680j_4(F)I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;->getPinsCount()I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;->get_parentPinnableContainer()Landroidx/compose/ui/layout/PinnableContainer;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;->onDisposed()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;->setIndex(I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;->setParentPinnableContainer(Landroidx/compose/ui/layout/PinnableContainer;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt;->LazyLayoutPinnableItem(ILandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;-><init>(Ljava/util/List;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;->getSize()I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;->size()I
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;->setPrefetcher$foundation_release(Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState$Prefetcher;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$Companion;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$Companion;->access$calculateFrameIntervalIfNeeded(Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$Companion;Landroid/view/View;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$Companion;->calculateFrameIntervalIfNeeded(Landroid/view/View;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;Landroidx/compose/ui/layout/SubcomposeLayoutState;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;Landroid/view/View;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;->access$getFrameIntervalNs$cp()J
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;->access$setFrameIntervalNs$cp(J)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;->onForgotten()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;->onRemembered()V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher_androidKt;->LazyLayoutPrefetcher(Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;Landroidx/compose/ui/layout/SubcomposeLayoutState;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$1;-><init>(Lkotlin/jvm/functions/Function1;ZLandroidx/compose/ui/semantics/ScrollAxisRange;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/semantics/CollectionInfo;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$indexForKeyMapping$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$scrollByAction$1;-><init>(ZLkotlinx/coroutines/CoroutineScope;Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticState;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$scrollToIndexAction$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticState;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt;->lazyLayoutSemantics(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticState;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$1;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$1;->invoke()Lkotlin/ranges/IntRange;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$2;-><init>(Landroidx/compose/runtime/MutableState;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$2;->emit(Lkotlin/ranges/IntRange;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/MutableState;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt;->access$calculateNearestItemsRange(III)Lkotlin/ranges/IntRange;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt;->calculateNearestItemsRange(III)Lkotlin/ranges/IntRange;
-HSPLandroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt;->rememberLazyNearestItemsRangeState(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$1;->invoke(Ljava/lang/Object;)Ljava/lang/Boolean;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$1;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$1;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$1;->invoke(Landroidx/compose/runtime/saveable/SaverScope;Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;)Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$2;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion;->saver(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;Ljava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;Ljava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$2;-><init>(Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;Ljava/util/Map;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->SaveableStateProvider(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->access$getPreviouslyComposedKeys$p(Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;)Ljava/util/Set;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->canBeSaved(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->consumeRestored(Ljava/lang/String;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->getWrappedHolder()Landroidx/compose/runtime/saveable/SaveableStateHolder;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->performSave()Ljava/util/Map;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->registerProvider(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/saveable/SaveableStateRegistry$Entry;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;->setWrappedHolder(Landroidx/compose/runtime/saveable/SaveableStateHolder;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$1;-><init>(Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$holder$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$holder$1;->invoke()Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$holder$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt;->LazySaveableStateHolderProvider(Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/foundation/lazy/layout/Lazy_androidKt;->getDefaultLazyLayoutKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;-><clinit>()V
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;-><init>()V
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->addInterval(ILjava/lang/Object;)V
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->checkIndexBounds(I)V
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->contains(Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;I)Z
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->forEach(IILkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->get(I)Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->getIntervalForIndex(I)Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;
-HSPLandroidx/compose/foundation/lazy/layout/MutableIntervalList;->getSize()I
-HSPLandroidx/compose/foundation/relocation/AndroidBringIntoViewParent;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewChildModifier;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewParent;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewChildModifier;->onModifierLocalsUpdated(Landroidx/compose/ui/modifier/ModifierLocalReadScope;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewChildModifier;->onPlaced(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewKt$ModifierLocalBringIntoViewParent$1;-><clinit>()V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewKt$ModifierLocalBringIntoViewParent$1;-><init>()V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewKt$ModifierLocalBringIntoViewParent$1;->invoke()Landroidx/compose/foundation/relocation/BringIntoViewParent;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewKt$ModifierLocalBringIntoViewParent$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewKt;-><clinit>()V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewKt;->getModifierLocalBringIntoViewParent()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterImpl;-><init>()V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterImpl;->getModifiers()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewRequester;Landroidx/compose/foundation/relocation/BringIntoViewRequesterModifier;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewRequester;Landroidx/compose/foundation/relocation/BringIntoViewRequesterModifier;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewRequester;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt;->BringIntoViewRequester()Landroidx/compose/foundation/relocation/BringIntoViewRequester;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterKt;->bringIntoViewRequester(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/relocation/BringIntoViewRequester;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewRequesterModifier;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewParent;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderKt$bringIntoViewResponder$2;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewResponder;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderKt$bringIntoViewResponder$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderKt$bringIntoViewResponder$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderKt;->bringIntoViewResponder(Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/relocation/BringIntoViewResponder;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderModifier;-><init>(Landroidx/compose/foundation/relocation/BringIntoViewParent;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderModifier;->getKey()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderModifier;->getValue()Landroidx/compose/foundation/relocation/BringIntoViewParent;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderModifier;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponderModifier;->setResponder(Landroidx/compose/foundation/relocation/BringIntoViewResponder;)V
-HSPLandroidx/compose/foundation/relocation/BringIntoViewResponder_androidKt;->rememberDefaultBringIntoViewParent(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/relocation/BringIntoViewParent;
-HSPLandroidx/compose/foundation/shape/CornerBasedShape;-><clinit>()V
-HSPLandroidx/compose/foundation/shape/CornerBasedShape;-><init>(Landroidx/compose/foundation/shape/CornerSize;Landroidx/compose/foundation/shape/CornerSize;Landroidx/compose/foundation/shape/CornerSize;Landroidx/compose/foundation/shape/CornerSize;)V
-HSPLandroidx/compose/foundation/shape/CornerBasedShape;->createOutline-Pq9zytI(JLandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;)Landroidx/compose/ui/graphics/Outline;
-HSPLandroidx/compose/foundation/shape/CornerBasedShape;->getBottomEnd()Landroidx/compose/foundation/shape/CornerSize;
-HSPLandroidx/compose/foundation/shape/CornerBasedShape;->getTopEnd()Landroidx/compose/foundation/shape/CornerSize;
-HSPLandroidx/compose/foundation/shape/CornerBasedShape;->getTopStart()Landroidx/compose/foundation/shape/CornerSize;
-HSPLandroidx/compose/foundation/shape/CornerSizeKt$ZeroCornerSize$1;-><init>()V
-HSPLandroidx/compose/foundation/shape/CornerSizeKt;-><clinit>()V
-HSPLandroidx/compose/foundation/shape/CornerSizeKt;->CornerSize(I)Landroidx/compose/foundation/shape/CornerSize;
-HSPLandroidx/compose/foundation/shape/CornerSizeKt;->CornerSize-0680j_4(F)Landroidx/compose/foundation/shape/CornerSize;
-HSPLandroidx/compose/foundation/shape/DpCornerSize;-><init>(F)V
-HSPLandroidx/compose/foundation/shape/DpCornerSize;-><init>(FLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/shape/DpCornerSize;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/shape/DpCornerSize;->toPx-TmRCtEA(JLandroidx/compose/ui/unit/Density;)F
-HSPLandroidx/compose/foundation/shape/PercentCornerSize;-><init>(F)V
-HSPLandroidx/compose/foundation/shape/PercentCornerSize;->toPx-TmRCtEA(JLandroidx/compose/ui/unit/Density;)F
-HSPLandroidx/compose/foundation/shape/RoundedCornerShape;-><clinit>()V
-HSPLandroidx/compose/foundation/shape/RoundedCornerShape;-><init>(Landroidx/compose/foundation/shape/CornerSize;Landroidx/compose/foundation/shape/CornerSize;Landroidx/compose/foundation/shape/CornerSize;Landroidx/compose/foundation/shape/CornerSize;)V
-HSPLandroidx/compose/foundation/shape/RoundedCornerShape;->createOutline-LjSzlW0(JFFFFLandroidx/compose/ui/unit/LayoutDirection;)Landroidx/compose/ui/graphics/Outline;
-HSPLandroidx/compose/foundation/shape/RoundedCornerShape;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/shape/RoundedCornerShapeKt;-><clinit>()V
-HSPLandroidx/compose/foundation/shape/RoundedCornerShapeKt;->RoundedCornerShape(I)Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/foundation/shape/RoundedCornerShapeKt;->RoundedCornerShape(Landroidx/compose/foundation/shape/CornerSize;)Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/foundation/shape/RoundedCornerShapeKt;->RoundedCornerShape-0680j_4(F)Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/foundation/shape/RoundedCornerShapeKt;->RoundedCornerShape-a9UjIt4(FFFF)Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/foundation/shape/RoundedCornerShapeKt;->getCircleShape()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/foundation/text/BasicTextKt$BasicText-4YKlhWE$$inlined$Layout$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/foundation/text/BasicTextKt$BasicText-4YKlhWE$$inlined$Layout$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/BasicTextKt;->BasicText-4YKlhWE(Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/text/TextStyle;Lkotlin/jvm/functions/Function1;IZIILandroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/foundation/text/CoreTextKt;-><clinit>()V
-HSPLandroidx/compose/foundation/text/CoreTextKt;->updateTextDelegate-x_uQXYA(Landroidx/compose/foundation/text/TextDelegate;Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;ZIII)Landroidx/compose/foundation/text/TextDelegate;
-HSPLandroidx/compose/foundation/text/HeightInLinesModifierKt$heightInLines$2;-><init>(IILandroidx/compose/ui/text/TextStyle;)V
-HSPLandroidx/compose/foundation/text/HeightInLinesModifierKt$heightInLines$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/text/HeightInLinesModifierKt$heightInLines$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/HeightInLinesModifierKt;->heightInLines$default(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/text/TextStyle;IIILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/text/HeightInLinesModifierKt;->heightInLines(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/text/TextStyle;II)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/text/HeightInLinesModifierKt;->validateMinMaxLines(II)V
-HSPLandroidx/compose/foundation/text/TextController$coreModifiers$1;-><init>(Landroidx/compose/foundation/text/TextController;)V
-HSPLandroidx/compose/foundation/text/TextController$coreModifiers$1;->invoke(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/foundation/text/TextController$coreModifiers$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/TextController$createSemanticsModifierFor$1$1;-><init>(Landroidx/compose/foundation/text/TextController;)V
-HSPLandroidx/compose/foundation/text/TextController$createSemanticsModifierFor$1;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/foundation/text/TextController;)V
-HSPLandroidx/compose/foundation/text/TextController$createSemanticsModifierFor$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/foundation/text/TextController$createSemanticsModifierFor$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/TextController$drawTextAndSelectionBehind$1;-><init>(Landroidx/compose/foundation/text/TextController;)V
-HSPLandroidx/compose/foundation/text/TextController$drawTextAndSelectionBehind$1;->invoke(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/foundation/text/TextController$drawTextAndSelectionBehind$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/TextController$measurePolicy$1$measure$2;-><init>(Ljava/util/List;)V
-HSPLandroidx/compose/foundation/text/TextController$measurePolicy$1$measure$2;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/foundation/text/TextController$measurePolicy$1$measure$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/TextController$measurePolicy$1;-><init>(Landroidx/compose/foundation/text/TextController;)V
-HSPLandroidx/compose/foundation/text/TextController$measurePolicy$1;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/foundation/text/TextController;-><init>(Landroidx/compose/foundation/text/TextState;)V
-HSPLandroidx/compose/foundation/text/TextController;->access$getSelectionRegistrar$p(Landroidx/compose/foundation/text/TextController;)Landroidx/compose/foundation/text/selection/SelectionRegistrar;
-HSPLandroidx/compose/foundation/text/TextController;->createSemanticsModifierFor(Landroidx/compose/ui/text/AnnotatedString;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/text/TextController;->drawTextAndSelectionBehind(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/text/TextController;->getMeasurePolicy()Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/foundation/text/TextController;->getModifiers()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/foundation/text/TextController;->getState()Landroidx/compose/foundation/text/TextState;
-HSPLandroidx/compose/foundation/text/TextController;->onForgotten()V
-HSPLandroidx/compose/foundation/text/TextController;->onRemembered()V
-HSPLandroidx/compose/foundation/text/TextController;->setTextDelegate(Landroidx/compose/foundation/text/TextDelegate;)V
-HSPLandroidx/compose/foundation/text/TextController;->update(Landroidx/compose/foundation/text/selection/SelectionRegistrar;)V
-HSPLandroidx/compose/foundation/text/TextDelegate$Companion;-><init>()V
-HSPLandroidx/compose/foundation/text/TextDelegate$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/text/TextDelegate$Companion;->paint(Landroidx/compose/ui/graphics/Canvas;Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLandroidx/compose/foundation/text/TextDelegate;-><clinit>()V
-HSPLandroidx/compose/foundation/text/TextDelegate;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;IIZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;Ljava/util/List;)V
-HSPLandroidx/compose/foundation/text/TextDelegate;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;IIZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/text/TextDelegate;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;IIZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/text/TextDelegate;->getDensity()Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/foundation/text/TextDelegate;->getFontFamilyResolver()Landroidx/compose/ui/text/font/FontFamily$Resolver;
-HSPLandroidx/compose/foundation/text/TextDelegate;->getMaxIntrinsicWidth()I
-HSPLandroidx/compose/foundation/text/TextDelegate;->getMaxLines()I
-HSPLandroidx/compose/foundation/text/TextDelegate;->getMinLines()I
-HSPLandroidx/compose/foundation/text/TextDelegate;->getNonNullIntrinsics()Landroidx/compose/ui/text/MultiParagraphIntrinsics;
-HSPLandroidx/compose/foundation/text/TextDelegate;->getOverflow-gIe3tQ8()I
-HSPLandroidx/compose/foundation/text/TextDelegate;->getSoftWrap()Z
-HSPLandroidx/compose/foundation/text/TextDelegate;->getStyle()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/foundation/text/TextDelegate;->getText()Landroidx/compose/ui/text/AnnotatedString;
-HSPLandroidx/compose/foundation/text/TextDelegate;->layout-NN6Ew-U(JLandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/TextLayoutResult;)Landroidx/compose/ui/text/TextLayoutResult;
-HSPLandroidx/compose/foundation/text/TextDelegate;->layoutIntrinsics(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/foundation/text/TextDelegate;->layoutText-K40F9xA(JLandroidx/compose/ui/unit/LayoutDirection;)Landroidx/compose/ui/text/MultiParagraph;
-HSPLandroidx/compose/foundation/text/TextDelegateKt;->ceilToIntPx(F)I
-HSPLandroidx/compose/foundation/text/TextLayoutHelperKt;->canReuse-7_7YC6M(Landroidx/compose/ui/text/TextLayoutResult;Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;IZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/font/FontFamily$Resolver;J)Z
-HSPLandroidx/compose/foundation/text/TextState$onTextLayout$1;-><clinit>()V
-HSPLandroidx/compose/foundation/text/TextState$onTextLayout$1;-><init>()V
-HSPLandroidx/compose/foundation/text/TextState;-><init>(Landroidx/compose/foundation/text/TextDelegate;J)V
-HSPLandroidx/compose/foundation/text/TextState;->getDrawScopeInvalidation()Lkotlin/Unit;
-HSPLandroidx/compose/foundation/text/TextState;->getLayoutInvalidation()Lkotlin/Unit;
-HSPLandroidx/compose/foundation/text/TextState;->getLayoutResult()Landroidx/compose/ui/text/TextLayoutResult;
-HSPLandroidx/compose/foundation/text/TextState;->getOnTextLayout()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/foundation/text/TextState;->getSelectable()Landroidx/compose/foundation/text/selection/Selectable;
-HSPLandroidx/compose/foundation/text/TextState;->getSelectableId()J
-HSPLandroidx/compose/foundation/text/TextState;->getTextDelegate()Landroidx/compose/foundation/text/TextDelegate;
-HSPLandroidx/compose/foundation/text/TextState;->setDrawScopeInvalidation(Lkotlin/Unit;)V
-HSPLandroidx/compose/foundation/text/TextState;->setLayoutCoordinates(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/foundation/text/TextState;->setLayoutResult(Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLandroidx/compose/foundation/text/TextState;->setOnTextLayout(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt$LocalSelectionRegistrar$1;-><clinit>()V
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt$LocalSelectionRegistrar$1;-><init>()V
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt$LocalSelectionRegistrar$1;->invoke()Landroidx/compose/foundation/text/selection/SelectionRegistrar;
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt$LocalSelectionRegistrar$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt;-><clinit>()V
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt;->getLocalSelectionRegistrar()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/foundation/text/selection/SelectionRegistrarKt;->hasSelection(Landroidx/compose/foundation/text/selection/SelectionRegistrar;J)Z
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColors;-><clinit>()V
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColors;-><init>(JJ)V
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColors;-><init>(JJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColors;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColorsKt$LocalTextSelectionColors$1;-><clinit>()V
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColorsKt$LocalTextSelectionColors$1;-><init>()V
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColorsKt;-><clinit>()V
-HSPLandroidx/compose/foundation/text/selection/TextSelectionColorsKt;->getLocalTextSelectionColors()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material/icons/Icons$Filled;-><clinit>()V
-HSPLandroidx/compose/material/icons/Icons$Filled;-><init>()V
-HSPLandroidx/compose/material/icons/Icons$Outlined;-><clinit>()V
-HSPLandroidx/compose/material/icons/Icons$Outlined;-><init>()V
-HSPLandroidx/compose/material/icons/filled/ArrowBackKt;-><clinit>()V
-HSPLandroidx/compose/material/icons/filled/ArrowBackKt;->getArrowBack(Landroidx/compose/material/icons/Icons$Filled;)Landroidx/compose/ui/graphics/vector/ImageVector;
-HSPLandroidx/compose/material/icons/filled/CloseKt;-><clinit>()V
-HSPLandroidx/compose/material/icons/filled/CloseKt;->getClose(Landroidx/compose/material/icons/Icons$Filled;)Landroidx/compose/ui/graphics/vector/ImageVector;
-HSPLandroidx/compose/material/icons/outlined/QrCodeScannerKt;-><clinit>()V
-HSPLandroidx/compose/material/icons/outlined/QrCodeScannerKt;->getQrCodeScanner(Landroidx/compose/material/icons/Icons$Outlined;)Landroidx/compose/ui/graphics/vector/ImageVector;
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance$onInvalidateRipple$1;-><init>(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance$onInvalidateRipple$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance$onInvalidateRipple$1;->invoke()V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;-><init>(ZFLandroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/material/ripple/RippleContainer;)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;-><init>(ZFLandroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/material/ripple/RippleContainer;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->access$getInvalidateTick(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;)Z
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->access$setInvalidateTick(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;Z)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->addRipple(Landroidx/compose/foundation/interaction/PressInteraction$Press;Lkotlinx/coroutines/CoroutineScope;)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->dispose()V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->drawIndication(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->getInvalidateTick()Z
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->getRippleHostView()Landroidx/compose/material/ripple/RippleHostView;
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->onForgotten()V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->onRemembered()V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->removeRipple(Landroidx/compose/foundation/interaction/PressInteraction$Press;)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->resetHostView()V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->setInvalidateTick(Z)V
-HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->setRippleHostView(Landroidx/compose/material/ripple/RippleHostView;)V
-HSPLandroidx/compose/material/ripple/PlatformRipple;-><init>(ZFLandroidx/compose/runtime/State;)V
-HSPLandroidx/compose/material/ripple/PlatformRipple;-><init>(ZFLandroidx/compose/runtime/State;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material/ripple/PlatformRipple;->findNearestViewGroup(Landroidx/compose/runtime/Composer;I)Landroid/view/ViewGroup;
-HSPLandroidx/compose/material/ripple/PlatformRipple;->rememberUpdatedRippleInstance-942rkJo(Landroidx/compose/foundation/interaction/InteractionSource;ZFLandroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/runtime/Composer;I)Landroidx/compose/material/ripple/RippleIndicationInstance;
-HSPLandroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1$1;-><init>(Landroidx/compose/material/ripple/RippleIndicationInstance;Lkotlinx/coroutines/CoroutineScope;)V
-HSPLandroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1$1;->emit(Landroidx/compose/foundation/interaction/Interaction;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1$1;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1;-><init>(Landroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/material/ripple/RippleIndicationInstance;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material/ripple/Ripple;-><init>(ZFLandroidx/compose/runtime/State;)V
-HSPLandroidx/compose/material/ripple/Ripple;-><init>(ZFLandroidx/compose/runtime/State;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material/ripple/Ripple;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material/ripple/Ripple;->rememberUpdatedInstance(Landroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/IndicationInstance;
-HSPLandroidx/compose/material/ripple/RippleAlpha;-><clinit>()V
-HSPLandroidx/compose/material/ripple/RippleAlpha;-><init>(FFFF)V
-HSPLandroidx/compose/material/ripple/RippleAlpha;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material/ripple/RippleAlpha;->getPressedAlpha()F
-HSPLandroidx/compose/material/ripple/RippleAnimationKt;-><clinit>()V
-HSPLandroidx/compose/material/ripple/RippleAnimationKt;->getRippleEndRadius-cSwnlzA(Landroidx/compose/ui/unit/Density;ZJ)F
-HSPLandroidx/compose/material/ripple/RippleContainer;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/material/ripple/RippleContainer;->disposeRippleIfNeeded(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;)V
-HSPLandroidx/compose/material/ripple/RippleContainer;->getRippleHostView(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;)Landroidx/compose/material/ripple/RippleHostView;
-HSPLandroidx/compose/material/ripple/RippleHostMap;-><init>()V
-HSPLandroidx/compose/material/ripple/RippleHostMap;->get(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;)Landroidx/compose/material/ripple/RippleHostView;
-HSPLandroidx/compose/material/ripple/RippleHostMap;->remove(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;)V
-HSPLandroidx/compose/material/ripple/RippleHostMap;->set(Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;Landroidx/compose/material/ripple/RippleHostView;)V
-HSPLandroidx/compose/material/ripple/RippleHostView$Companion;-><init>()V
-HSPLandroidx/compose/material/ripple/RippleHostView$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material/ripple/RippleHostView;-><clinit>()V
-HSPLandroidx/compose/material/ripple/RippleHostView;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/material/ripple/RippleHostView;->addRipple-KOepWvA(Landroidx/compose/foundation/interaction/PressInteraction$Press;ZJIJFLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/material/ripple/RippleHostView;->createRipple(Z)V
-HSPLandroidx/compose/material/ripple/RippleHostView;->disposeRipple()V
-HSPLandroidx/compose/material/ripple/RippleHostView;->invalidateDrawable(Landroid/graphics/drawable/Drawable;)V
-HSPLandroidx/compose/material/ripple/RippleHostView;->refreshDrawableState()V
-HSPLandroidx/compose/material/ripple/RippleHostView;->removeRipple()V
-HSPLandroidx/compose/material/ripple/RippleHostView;->setRippleState(Z)V
-HSPLandroidx/compose/material/ripple/RippleHostView;->updateRippleProperties-biQXAtU(JIJF)V
-HSPLandroidx/compose/material/ripple/RippleIndicationInstance;-><init>(ZLandroidx/compose/runtime/State;)V
-HSPLandroidx/compose/material/ripple/RippleIndicationInstance;->drawStateLayer-H2RKhps(Landroidx/compose/ui/graphics/drawscope/DrawScope;FJ)V
-HSPLandroidx/compose/material/ripple/RippleKt;-><clinit>()V
-HSPLandroidx/compose/material/ripple/RippleKt;->rememberRipple-9IZ8Weo(ZFJLandroidx/compose/runtime/Composer;II)Landroidx/compose/foundation/Indication;
-HSPLandroidx/compose/material/ripple/RippleThemeKt$LocalRippleTheme$1;-><clinit>()V
-HSPLandroidx/compose/material/ripple/RippleThemeKt$LocalRippleTheme$1;-><init>()V
-HSPLandroidx/compose/material/ripple/RippleThemeKt;-><clinit>()V
-HSPLandroidx/compose/material/ripple/RippleThemeKt;->getLocalRippleTheme()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material/ripple/StateLayer;-><init>(ZLandroidx/compose/runtime/State;)V
-HSPLandroidx/compose/material/ripple/StateLayer;->drawStateLayer-H2RKhps(Landroidx/compose/ui/graphics/drawscope/DrawScope;FJ)V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple$Companion;-><init>()V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple$MRadiusHelper;-><clinit>()V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple$MRadiusHelper;-><init>()V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple$MRadiusHelper;->setRadius(Landroid/graphics/drawable/RippleDrawable;I)V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;-><clinit>()V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;-><init>(Z)V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;->calculateRippleColor-5vOe2sY(JF)J
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;->getDirtyBounds()Landroid/graphics/Rect;
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;->isProjected()Z
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;->setColor-DxMtmZc(JF)V
-HSPLandroidx/compose/material/ripple/UnprojectedRipple;->trySetRadius(I)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$1$1;-><init>(Landroidx/compose/material3/TopAppBarScrollBehavior;F)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$1$1;->invoke()V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$2;-><init>(Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/material3/TopAppBarColors;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;ILandroidx/compose/material3/TopAppBarScrollBehavior;)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$2;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$3;-><init>(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/material3/TopAppBarColors;Landroidx/compose/material3/TopAppBarScrollBehavior;II)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$actionsRow$1;-><init>(Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$actionsRow$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/AppBarKt$SingleRowTopAppBar$actionsRow$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$1$3$1;-><init>(JLkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$1$3$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$1$3$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$2$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;ILandroidx/compose/ui/layout/Placeable;Landroidx/compose/foundation/layout/Arrangement$Horizontal;JLandroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/foundation/layout/Arrangement$Vertical;II)V
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$2$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$2$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$2;-><init>(FLandroidx/compose/foundation/layout/Arrangement$Horizontal;Landroidx/compose/foundation/layout/Arrangement$Vertical;I)V
-HSPLandroidx/compose/material3/AppBarKt$TopAppBarLayout$2;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/material3/AppBarKt;-><clinit>()V
-HSPLandroidx/compose/material3/AppBarKt;->SingleRowTopAppBar$lambda$3(Landroidx/compose/runtime/State;)J
-HSPLandroidx/compose/material3/AppBarKt;->SingleRowTopAppBar(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/material3/TopAppBarColors;Landroidx/compose/material3/TopAppBarScrollBehavior;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/AppBarKt;->TopAppBar(Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/foundation/layout/WindowInsets;Landroidx/compose/material3/TopAppBarColors;Landroidx/compose/material3/TopAppBarScrollBehavior;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/AppBarKt;->TopAppBarLayout-kXwM9vE(Landroidx/compose/ui/Modifier;FJJJLkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;FLandroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;IZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/AppBarKt;->access$TopAppBarLayout-kXwM9vE(Landroidx/compose/ui/Modifier;FJJJLkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;FLandroidx/compose/foundation/layout/Arrangement$Vertical;Landroidx/compose/foundation/layout/Arrangement$Horizontal;IZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/AppBarKt;->access$getTopAppBarTitleInset$p()F
-HSPLandroidx/compose/material3/ButtonColors;-><clinit>()V
-HSPLandroidx/compose/material3/ButtonColors;-><init>(JJJJ)V
-HSPLandroidx/compose/material3/ButtonColors;-><init>(JJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/ButtonColors;->containerColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ButtonColors;->contentColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ButtonColors;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/ButtonDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/ButtonDefaults;-><init>()V
-HSPLandroidx/compose/material3/ButtonDefaults;->getMinHeight-D9Ej5fM()F
-HSPLandroidx/compose/material3/ButtonDefaults;->getMinWidth-D9Ej5fM()F
-HSPLandroidx/compose/material3/ButtonDefaults;->getTextShape(Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/material3/ButtonDefaults;->textButtonColors-ro_MJ88(JJJJLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/ButtonColors;
-HSPLandroidx/compose/material3/ButtonKt$Button$2$1$1;-><init>(Landroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/material3/ButtonKt$Button$2$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ButtonKt$Button$2$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ButtonKt$Button$2$1;-><init>(Landroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/material3/ButtonKt$Button$2$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ButtonKt$Button$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ButtonKt$Button$2;-><init>(JLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/material3/ButtonKt$Button$2;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ButtonKt$Button$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ButtonKt$Button$3;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ButtonColors;Landroidx/compose/material3/ButtonElevation;Landroidx/compose/foundation/BorderStroke;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function3;II)V
-HSPLandroidx/compose/material3/ButtonKt$TextButton$2;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ButtonColors;Landroidx/compose/material3/ButtonElevation;Landroidx/compose/foundation/BorderStroke;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function3;II)V
-HSPLandroidx/compose/material3/ButtonKt;->Button(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ButtonColors;Landroidx/compose/material3/ButtonElevation;Landroidx/compose/foundation/BorderStroke;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/ButtonKt;->TextButton(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ButtonColors;Landroidx/compose/material3/ButtonElevation;Landroidx/compose/foundation/BorderStroke;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/CardColors;-><clinit>()V
-HSPLandroidx/compose/material3/CardColors;-><init>(JJJJ)V
-HSPLandroidx/compose/material3/CardColors;-><init>(JJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/CardColors;->containerColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/CardColors;->contentColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/CardColors;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/CardDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/CardDefaults;-><init>()V
-HSPLandroidx/compose/material3/CardDefaults;->cardColors-ro_MJ88(JJJJLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/CardColors;
-HSPLandroidx/compose/material3/CardDefaults;->cardElevation-aqJV_2Y(FFFFFFLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/CardElevation;
-HSPLandroidx/compose/material3/CardDefaults;->getShape(Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/material3/CardElevation;-><clinit>()V
-HSPLandroidx/compose/material3/CardElevation;-><init>(FFFFFF)V
-HSPLandroidx/compose/material3/CardElevation;-><init>(FFFFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/CardElevation;->access$getDefaultElevation$p(Landroidx/compose/material3/CardElevation;)F
-HSPLandroidx/compose/material3/CardElevation;->shadowElevation$material3_release(ZLandroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/CardElevation;->tonalElevation$material3_release(ZLandroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/CardKt$Card$1;-><init>(Lkotlin/jvm/functions/Function3;I)V
-HSPLandroidx/compose/material3/CardKt$Card$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/CardKt$Card$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/CardKt$Card$2;-><init>(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/CardColors;Landroidx/compose/material3/CardElevation;Landroidx/compose/foundation/BorderStroke;Lkotlin/jvm/functions/Function3;II)V
-HSPLandroidx/compose/material3/CardKt;->Card(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/CardColors;Landroidx/compose/material3/CardElevation;Landroidx/compose/foundation/BorderStroke;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/ChipColors;-><clinit>()V
-HSPLandroidx/compose/material3/ChipColors;-><init>(JJJJJJJJ)V
-HSPLandroidx/compose/material3/ChipColors;-><init>(JJJJJJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/ChipColors;->containerColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipColors;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/ChipColors;->labelColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipColors;->leadingIconContentColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipColors;->trailingIconContentColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$1$1$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateList;)V
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$1$1;-><init>(Landroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/snapshots/SnapshotStateList;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$3;-><init>(Landroidx/compose/animation/core/Animatable;Landroidx/compose/material3/ChipElevation;FLandroidx/compose/foundation/interaction/Interaction;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/material3/ChipElevation$animateElevation$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ChipElevation;-><clinit>()V
-HSPLandroidx/compose/material3/ChipElevation;-><init>(FFFFFF)V
-HSPLandroidx/compose/material3/ChipElevation;-><init>(FFFFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/ChipElevation;->access$getPressedElevation$p(Landroidx/compose/material3/ChipElevation;)F
-HSPLandroidx/compose/material3/ChipElevation;->animateElevation(ZLandroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipElevation;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/ChipElevation;->shadowElevation$material3_release(ZLandroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipElevation;->tonalElevation$material3_release(ZLandroidx/compose/foundation/interaction/InteractionSource;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/ChipKt$Chip$1;-><init>(Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;JLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/material3/ChipColors;ZIFLandroidx/compose/foundation/layout/PaddingValues;I)V
-HSPLandroidx/compose/material3/ChipKt$Chip$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ChipKt$Chip$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ChipKt$Chip$2;-><init>(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;JLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ChipColors;Landroidx/compose/material3/ChipElevation;Landroidx/compose/foundation/BorderStroke;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;II)V
-HSPLandroidx/compose/material3/ChipKt$ChipContent$1;-><init>(FLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;J)V
-HSPLandroidx/compose/material3/ChipKt$ChipContent$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ChipKt$ChipContent$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ChipKt$SuggestionChip$2;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ChipColors;Landroidx/compose/material3/ChipElevation;Landroidx/compose/material3/ChipBorder;Landroidx/compose/foundation/interaction/MutableInteractionSource;II)V
-HSPLandroidx/compose/material3/ChipKt;-><clinit>()V
-HSPLandroidx/compose/material3/ChipKt;->Chip-nkUnTEs(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;JLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ChipColors;Landroidx/compose/material3/ChipElevation;Landroidx/compose/foundation/BorderStroke;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/ChipKt;->ChipContent-fe0OD_I(Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;JLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;JJFLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ChipKt;->SuggestionChip(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/material3/ChipColors;Landroidx/compose/material3/ChipElevation;Landroidx/compose/material3/ChipBorder;Landroidx/compose/foundation/interaction/MutableInteractionSource;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/ChipKt;->access$ChipContent-fe0OD_I(Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/text/TextStyle;JLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;JJFLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ChipKt;->access$getHorizontalElementsPadding$p()F
-HSPLandroidx/compose/material3/ColorResourceHelper;-><clinit>()V
-HSPLandroidx/compose/material3/ColorResourceHelper;-><init>()V
-HSPLandroidx/compose/material3/ColorResourceHelper;->getColor-WaAFU9c(Landroid/content/Context;I)J
-HSPLandroidx/compose/material3/ColorScheme;-><clinit>()V
-HSPLandroidx/compose/material3/ColorScheme;-><init>(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJ)V
-HSPLandroidx/compose/material3/ColorScheme;-><init>(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/ColorScheme;->copy-G1PFc-w$default(Landroidx/compose/material3/ColorScheme;JJJJJJJJJJJJJJJJJJJJJJJJJJJJJILjava/lang/Object;)Landroidx/compose/material3/ColorScheme;
-HSPLandroidx/compose/material3/ColorScheme;->copy-G1PFc-w(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJ)Landroidx/compose/material3/ColorScheme;
-HSPLandroidx/compose/material3/ColorScheme;->getBackground-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getError-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getErrorContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getInverseOnSurface-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getInversePrimary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getInverseSurface-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnBackground-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnError-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnErrorContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnPrimary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnPrimaryContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnSecondary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnSecondaryContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnSurface-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnSurfaceVariant-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnTertiary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOnTertiaryContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOutline-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getOutlineVariant-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getPrimary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getPrimaryContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getScrim-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getSecondary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getSecondaryContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getSurface-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getSurfaceTint-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getSurfaceVariant-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getTertiary-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->getTertiaryContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/ColorScheme;->setBackground-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setError-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setErrorContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setInverseOnSurface-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setInversePrimary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setInverseSurface-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnBackground-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnError-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnErrorContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnPrimary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnPrimaryContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnSecondary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnSecondaryContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnSurface-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnSurfaceVariant-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnTertiary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOnTertiaryContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOutline-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setOutlineVariant-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setPrimary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setPrimaryContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setScrim-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setSecondary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setSecondaryContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setSurface-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setSurfaceTint-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setSurfaceVariant-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setTertiary-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorScheme;->setTertiaryContainer-8_81llA$material3_release(J)V
-HSPLandroidx/compose/material3/ColorSchemeKt$LocalColorScheme$1;-><clinit>()V
-HSPLandroidx/compose/material3/ColorSchemeKt$LocalColorScheme$1;-><init>()V
-HSPLandroidx/compose/material3/ColorSchemeKt$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/material3/ColorSchemeKt;-><clinit>()V
-HSPLandroidx/compose/material3/ColorSchemeKt;->applyTonalElevation-Hht5A8o(Landroidx/compose/material3/ColorScheme;JF)J
-HSPLandroidx/compose/material3/ColorSchemeKt;->contentColorFor-4WTKRHQ(Landroidx/compose/material3/ColorScheme;J)J
-HSPLandroidx/compose/material3/ColorSchemeKt;->contentColorFor-ek8zF_U(JLandroidx/compose/runtime/Composer;I)J
-HSPLandroidx/compose/material3/ColorSchemeKt;->darkColorScheme-G1PFc-w$default(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJILjava/lang/Object;)Landroidx/compose/material3/ColorScheme;
-HSPLandroidx/compose/material3/ColorSchemeKt;->darkColorScheme-G1PFc-w(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJ)Landroidx/compose/material3/ColorScheme;
-HSPLandroidx/compose/material3/ColorSchemeKt;->fromToken(Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;)J
-HSPLandroidx/compose/material3/ColorSchemeKt;->getLocalColorScheme()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material3/ColorSchemeKt;->surfaceColorAtElevation-3ABfNKs(Landroidx/compose/material3/ColorScheme;F)J
-HSPLandroidx/compose/material3/ColorSchemeKt;->toColor(Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;Landroidx/compose/runtime/Composer;I)J
-HSPLandroidx/compose/material3/ColorSchemeKt;->updateColorSchemeFrom(Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/ColorScheme;)V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-1$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-1$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-10$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-10$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-11$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-11$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-12$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-12$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-2$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-2$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-2$1;->invoke(Landroidx/compose/foundation/layout/RowScope;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-3$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-3$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-4$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-4$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-5$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-5$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-6$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-6$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-7$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-7$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-8$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-8$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-9$1;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-9$1;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt;-><clinit>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt;-><init>()V
-HSPLandroidx/compose/material3/ComposableSingletons$AppBarKt;->getLambda-2$material3_release()Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/material3/ContentColorKt$LocalContentColor$1;-><clinit>()V
-HSPLandroidx/compose/material3/ContentColorKt$LocalContentColor$1;-><init>()V
-HSPLandroidx/compose/material3/ContentColorKt$LocalContentColor$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material3/ContentColorKt$LocalContentColor$1;->invoke-0d7_KjU()J
-HSPLandroidx/compose/material3/ContentColorKt;-><clinit>()V
-HSPLandroidx/compose/material3/ContentColorKt;->getLocalContentColor()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material3/DynamicTonalPaletteKt;->dynamicDarkColorScheme(Landroid/content/Context;)Landroidx/compose/material3/ColorScheme;
-HSPLandroidx/compose/material3/DynamicTonalPaletteKt;->dynamicTonalPalette(Landroid/content/Context;)Landroidx/compose/material3/TonalPalette;
-HSPLandroidx/compose/material3/ElevationDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/ElevationDefaults;-><init>()V
-HSPLandroidx/compose/material3/ElevationDefaults;->outgoingAnimationSpecForInteraction(Landroidx/compose/foundation/interaction/Interaction;)Landroidx/compose/animation/core/AnimationSpec;
-HSPLandroidx/compose/material3/ElevationKt;-><clinit>()V
-HSPLandroidx/compose/material3/ElevationKt;->access$getDefaultOutgoingSpec$p()Landroidx/compose/animation/core/TweenSpec;
-HSPLandroidx/compose/material3/ElevationKt;->animateElevation-rAjV9yQ(Landroidx/compose/animation/core/Animatable;FLandroidx/compose/foundation/interaction/Interaction;Landroidx/compose/foundation/interaction/Interaction;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/IconButtonColors;-><clinit>()V
-HSPLandroidx/compose/material3/IconButtonColors;-><init>(JJJJ)V
-HSPLandroidx/compose/material3/IconButtonColors;-><init>(JJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/IconButtonColors;->containerColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/IconButtonColors;->contentColor$material3_release(ZLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/material3/IconButtonDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/IconButtonDefaults;-><init>()V
-HSPLandroidx/compose/material3/IconButtonDefaults;->iconButtonColors-ro_MJ88(JJJJLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/IconButtonColors;
-HSPLandroidx/compose/material3/IconButtonKt$IconButton$3;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/material3/IconButtonColors;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;II)V
-HSPLandroidx/compose/material3/IconButtonKt;->IconButton(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/material3/IconButtonColors;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/IconKt$Icon$3;-><init>(Landroidx/compose/ui/graphics/painter/Painter;Ljava/lang/String;Landroidx/compose/ui/Modifier;JII)V
-HSPLandroidx/compose/material3/IconKt$Icon$semantics$1$1;-><init>(Ljava/lang/String;)V
-HSPLandroidx/compose/material3/IconKt$Icon$semantics$1$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/material3/IconKt$Icon$semantics$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/IconKt;-><clinit>()V
-HSPLandroidx/compose/material3/IconKt;->Icon-ww6aTOc(Landroidx/compose/ui/graphics/painter/Painter;Ljava/lang/String;Landroidx/compose/ui/Modifier;JLandroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/IconKt;->Icon-ww6aTOc(Landroidx/compose/ui/graphics/vector/ImageVector;Ljava/lang/String;Landroidx/compose/ui/Modifier;JLandroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/IconKt;->defaultSizeFor(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/painter/Painter;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/material3/IconKt;->isInfinite-uvyYCjk(J)Z
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$LocalMinimumInteractiveComponentEnforcement$1;-><clinit>()V
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$LocalMinimumInteractiveComponentEnforcement$1;-><init>()V
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$LocalMinimumInteractiveComponentEnforcement$1;->invoke()Ljava/lang/Boolean;
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$LocalMinimumInteractiveComponentEnforcement$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$minimumInteractiveComponentSize$2;-><clinit>()V
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$minimumInteractiveComponentSize$2;-><init>()V
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$minimumInteractiveComponentSize$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt$minimumInteractiveComponentSize$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt;-><clinit>()V
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt;->access$getMinimumInteractiveComponentSize$p()J
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt;->getLocalMinimumInteractiveComponentEnforcement()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material3/InteractiveComponentSizeKt;->minimumInteractiveComponentSize(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/material3/MaterialRippleTheme;-><clinit>()V
-HSPLandroidx/compose/material3/MaterialRippleTheme;-><init>()V
-HSPLandroidx/compose/material3/MaterialRippleTheme;->defaultColor-WaAFU9c(Landroidx/compose/runtime/Composer;I)J
-HSPLandroidx/compose/material3/MaterialRippleTheme;->rippleAlpha(Landroidx/compose/runtime/Composer;I)Landroidx/compose/material/ripple/RippleAlpha;
-HSPLandroidx/compose/material3/MaterialTheme;-><clinit>()V
-HSPLandroidx/compose/material3/MaterialTheme;-><init>()V
-HSPLandroidx/compose/material3/MaterialTheme;->getColorScheme(Landroidx/compose/runtime/Composer;I)Landroidx/compose/material3/ColorScheme;
-HSPLandroidx/compose/material3/MaterialTheme;->getShapes(Landroidx/compose/runtime/Composer;I)Landroidx/compose/material3/Shapes;
-HSPLandroidx/compose/material3/MaterialTheme;->getTypography(Landroidx/compose/runtime/Composer;I)Landroidx/compose/material3/Typography;
-HSPLandroidx/compose/material3/MaterialThemeKt$MaterialTheme$1;-><init>(Landroidx/compose/material3/Typography;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/material3/MaterialThemeKt$MaterialTheme$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/MaterialThemeKt$MaterialTheme$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/MaterialThemeKt$MaterialTheme$2;-><init>(Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/Shapes;Landroidx/compose/material3/Typography;Lkotlin/jvm/functions/Function2;II)V
-HSPLandroidx/compose/material3/MaterialThemeKt;-><clinit>()V
-HSPLandroidx/compose/material3/MaterialThemeKt;->MaterialTheme(Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/Shapes;Landroidx/compose/material3/Typography;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/MaterialThemeKt;->access$getDefaultRippleAlpha$p()Landroidx/compose/material/ripple/RippleAlpha;
-HSPLandroidx/compose/material3/MaterialThemeKt;->rememberTextSelectionColors(Landroidx/compose/material3/ColorScheme;Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/text/selection/TextSelectionColors;
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier$measure$1;-><init>(ILandroidx/compose/ui/layout/Placeable;I)V
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier;-><init>(J)V
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier;-><init>(JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/MinimumInteractiveComponentSizeModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/material3/ShapeDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/ShapeDefaults;-><init>()V
-HSPLandroidx/compose/material3/ShapeDefaults;->getExtraLarge()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/ShapeDefaults;->getExtraSmall()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/ShapeDefaults;->getLarge()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/ShapeDefaults;->getMedium()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/ShapeDefaults;->getSmall()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/Shapes;-><clinit>()V
-HSPLandroidx/compose/material3/Shapes;-><init>(Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;)V
-HSPLandroidx/compose/material3/Shapes;-><init>(Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;Landroidx/compose/foundation/shape/CornerBasedShape;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/Shapes;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/Shapes;->getLarge()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/Shapes;->getMedium()Landroidx/compose/foundation/shape/CornerBasedShape;
-HSPLandroidx/compose/material3/ShapesKt$LocalShapes$1;-><clinit>()V
-HSPLandroidx/compose/material3/ShapesKt$LocalShapes$1;-><init>()V
-HSPLandroidx/compose/material3/ShapesKt$LocalShapes$1;->invoke()Landroidx/compose/material3/Shapes;
-HSPLandroidx/compose/material3/ShapesKt$LocalShapes$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material3/ShapesKt$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/material3/ShapesKt;-><clinit>()V
-HSPLandroidx/compose/material3/ShapesKt;->fromToken(Landroidx/compose/material3/Shapes;Landroidx/compose/material3/tokens/ShapeKeyTokens;)Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/material3/ShapesKt;->getLocalShapes()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material3/ShapesKt;->toShape(Landroidx/compose/material3/tokens/ShapeKeyTokens;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/material3/SuggestionChipDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/SuggestionChipDefaults;-><init>()V
-HSPLandroidx/compose/material3/SuggestionChipDefaults;->getHeight-D9Ej5fM()F
-HSPLandroidx/compose/material3/SuggestionChipDefaults;->suggestionChipColors-5tl4gsc(JJJJJJLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/ChipColors;
-HSPLandroidx/compose/material3/SuggestionChipDefaults;->suggestionChipElevation-aqJV_2Y(FFFFFFLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/ChipElevation;
-HSPLandroidx/compose/material3/SurfaceKt$LocalAbsoluteTonalElevation$1;-><clinit>()V
-HSPLandroidx/compose/material3/SurfaceKt$LocalAbsoluteTonalElevation$1;-><init>()V
-HSPLandroidx/compose/material3/SurfaceKt$LocalAbsoluteTonalElevation$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt$LocalAbsoluteTonalElevation$1;->invoke-D9Ej5fM()F
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$1;-><clinit>()V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$1;-><init>()V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$2;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$2;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1;-><init>(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;JFILandroidx/compose/foundation/BorderStroke;FLkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt$Surface$3;-><init>(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;JFILandroidx/compose/foundation/BorderStroke;FLandroidx/compose/foundation/interaction/MutableInteractionSource;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$3;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/SurfaceKt$Surface$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/SurfaceKt;-><clinit>()V
-HSPLandroidx/compose/material3/SurfaceKt;->Surface-T9BRK9s(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;JJFFLandroidx/compose/foundation/BorderStroke;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/material3/SurfaceKt;->Surface-o_FOJdg(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZLandroidx/compose/ui/graphics/Shape;JJFFLandroidx/compose/foundation/BorderStroke;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;III)V
-HSPLandroidx/compose/material3/SurfaceKt;->access$surface-8ww4TTg(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;JLandroidx/compose/foundation/BorderStroke;F)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/material3/SurfaceKt;->access$surfaceColorAtElevation-CLU3JFs(JFLandroidx/compose/runtime/Composer;I)J
-HSPLandroidx/compose/material3/SurfaceKt;->surface-8ww4TTg(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;JLandroidx/compose/foundation/BorderStroke;F)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/material3/SurfaceKt;->surfaceColorAtElevation-CLU3JFs(JFLandroidx/compose/runtime/Composer;I)J
-HSPLandroidx/compose/material3/SystemBarsDefaultInsets_androidKt;->getSystemBarsForVisualComponents(Landroidx/compose/foundation/layout/WindowInsets$Companion;Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/material3/TextKt$LocalTextStyle$1;-><clinit>()V
-HSPLandroidx/compose/material3/TextKt$LocalTextStyle$1;-><init>()V
-HSPLandroidx/compose/material3/TextKt$LocalTextStyle$1;->invoke()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/TextKt$LocalTextStyle$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/material3/TextKt$ProvideTextStyle$1;-><init>(Landroidx/compose/ui/text/TextStyle;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/material3/TextKt$Text$1;-><clinit>()V
-HSPLandroidx/compose/material3/TextKt$Text$1;-><init>()V
-HSPLandroidx/compose/material3/TextKt$Text$1;->invoke(Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLandroidx/compose/material3/TextKt$Text$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/material3/TextKt;-><clinit>()V
-HSPLandroidx/compose/material3/TextKt;->ProvideTextStyle(Landroidx/compose/ui/text/TextStyle;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/material3/TextKt;->Text--4IGK_g(Ljava/lang/String;Landroidx/compose/ui/Modifier;JJLandroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontFamily;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/text/style/TextAlign;JIZIILkotlin/jvm/functions/Function1;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/runtime/Composer;III)V
-HSPLandroidx/compose/material3/TextKt;->getLocalTextStyle()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material3/TonalPalette;-><init>(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ)V
-HSPLandroidx/compose/material3/TonalPalette;-><init>(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/TonalPalette;->getNeutral10-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getNeutral20-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getNeutral90-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getNeutralVariant30-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getNeutralVariant60-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getNeutralVariant80-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getPrimary20-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getPrimary30-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getPrimary40-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getPrimary80-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getPrimary90-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getSecondary20-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getSecondary30-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getSecondary80-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getSecondary90-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getTertiary20-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getTertiary30-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getTertiary80-0d7_KjU()J
-HSPLandroidx/compose/material3/TonalPalette;->getTertiary90-0d7_KjU()J
-HSPLandroidx/compose/material3/TopAppBarColors;-><clinit>()V
-HSPLandroidx/compose/material3/TopAppBarColors;-><init>(JJJJJ)V
-HSPLandroidx/compose/material3/TopAppBarColors;-><init>(JJJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/material3/TopAppBarColors;->containerColor-XeAY9LY$material3_release(FLandroidx/compose/runtime/Composer;I)J
-HSPLandroidx/compose/material3/TopAppBarColors;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/TopAppBarColors;->getActionIconContentColor-0d7_KjU$material3_release()J
-HSPLandroidx/compose/material3/TopAppBarColors;->getNavigationIconContentColor-0d7_KjU$material3_release()J
-HSPLandroidx/compose/material3/TopAppBarColors;->getTitleContentColor-0d7_KjU$material3_release()J
-HSPLandroidx/compose/material3/TopAppBarDefaults;-><clinit>()V
-HSPLandroidx/compose/material3/TopAppBarDefaults;-><init>()V
-HSPLandroidx/compose/material3/TopAppBarDefaults;->getWindowInsets(Landroidx/compose/runtime/Composer;I)Landroidx/compose/foundation/layout/WindowInsets;
-HSPLandroidx/compose/material3/TopAppBarDefaults;->topAppBarColors-zjMxDiM(JJJJJLandroidx/compose/runtime/Composer;II)Landroidx/compose/material3/TopAppBarColors;
-HSPLandroidx/compose/material3/Typography;-><clinit>()V
-HSPLandroidx/compose/material3/Typography;-><init>(Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;)V
-HSPLandroidx/compose/material3/Typography;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/material3/Typography;->getBodyLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/Typography;->getBodyMedium()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/Typography;->getBodySmall()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/Typography;->getLabelLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/Typography;->getTitleLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/Typography;->getTitleSmall()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/TypographyKt$LocalTypography$1;-><clinit>()V
-HSPLandroidx/compose/material3/TypographyKt$LocalTypography$1;-><init>()V
-HSPLandroidx/compose/material3/TypographyKt$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/material3/TypographyKt;-><clinit>()V
-HSPLandroidx/compose/material3/TypographyKt;->fromToken(Landroidx/compose/material3/Typography;Landroidx/compose/material3/tokens/TypographyKeyTokens;)Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/material3/TypographyKt;->getLocalTypography()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;->getError-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;->getErrorContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;->getOnError-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;->getOnErrorContainer-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;->getOutlineVariant-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ColorDarkTokens;->getScrim-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ColorSchemeKeyTokens;->$values()[Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/ColorSchemeKeyTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/ColorSchemeKeyTokens;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/material3/tokens/ColorSchemeKeyTokens;->values()[Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/ElevationTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/ElevationTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/ElevationTokens;->getLevel0-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/ElevationTokens;->getLevel1-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/ElevationTokens;->getLevel2-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/ElevationTokens;->getLevel3-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/ElevationTokens;->getLevel4-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledButtonTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/FilledButtonTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/FilledButtonTokens;->getIconSize-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getContainerShape()Landroidx/compose/material3/tokens/ShapeKeyTokens;
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getDisabledContainerColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getDisabledContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getDraggedContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getFocusContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getHoverContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/FilledCardTokens;->getPressedContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/IconButtonTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/IconButtonTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/IconButtonTokens;->getIconSize-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/IconButtonTokens;->getStateLayerShape()Landroidx/compose/material3/tokens/ShapeKeyTokens;
-HSPLandroidx/compose/material3/tokens/IconButtonTokens;->getStateLayerSize-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/PaletteTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/PaletteTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getError20-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getError30-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getError80-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getError90-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutral0-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutral10-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutral20-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutral90-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutralVariant30-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutralVariant60-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getNeutralVariant80-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getPrimary20-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getPrimary30-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getPrimary40-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getPrimary80-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getPrimary90-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getSecondary20-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getSecondary30-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getSecondary80-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getSecondary90-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getTertiary20-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getTertiary30-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getTertiary80-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/PaletteTokens;->getTertiary90-0d7_KjU()J
-HSPLandroidx/compose/material3/tokens/ShapeKeyTokens;->$values()[Landroidx/compose/material3/tokens/ShapeKeyTokens;
-HSPLandroidx/compose/material3/tokens/ShapeKeyTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/ShapeKeyTokens;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/material3/tokens/ShapeKeyTokens;->values()[Landroidx/compose/material3/tokens/ShapeKeyTokens;
-HSPLandroidx/compose/material3/tokens/ShapeTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/ShapeTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/ShapeTokens;->getCornerExtraLarge()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/material3/tokens/ShapeTokens;->getCornerExtraSmall()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/material3/tokens/ShapeTokens;->getCornerLarge()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/material3/tokens/ShapeTokens;->getCornerMedium()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/material3/tokens/ShapeTokens;->getCornerSmall()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getContainerHeight-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getDisabledLabelTextColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getDisabledLeadingIconColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getDraggedContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getFlatContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getLabelTextColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getLabelTextFont()Landroidx/compose/material3/tokens/TypographyKeyTokens;
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getLeadingIconColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/SuggestionChipTokens;->getLeadingIconSize-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/TextButtonTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/TextButtonTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/TextButtonTokens;->getContainerShape()Landroidx/compose/material3/tokens/ShapeKeyTokens;
-HSPLandroidx/compose/material3/tokens/TextButtonTokens;->getDisabledLabelTextColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/TextButtonTokens;->getLabelTextColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;-><init>()V
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;->getContainerHeight-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;->getHeadlineColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;->getHeadlineFont()Landroidx/compose/material3/tokens/TypographyKeyTokens;
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;->getLeadingIconColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;->getOnScrollContainerElevation-D9Ej5fM()F
-HSPLandroidx/compose/material3/tokens/TopAppBarSmallTokens;->getTrailingIconColor()Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-HSPLandroidx/compose/material3/tokens/TypographyKeyTokens;->$values()[Landroidx/compose/material3/tokens/TypographyKeyTokens;
-HSPLandroidx/compose/material3/tokens/TypographyKeyTokens;-><clinit>()V
-HSPLandroidx/compose/material3/tokens/TypographyKeyTokens;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/material3/tokens/TypographyKeyTokens;->values()[Landroidx/compose/material3/tokens/TypographyKeyTokens;
-HSPLandroidx/compose/runtime/AbstractApplier;-><clinit>()V
-HSPLandroidx/compose/runtime/AbstractApplier;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/AbstractApplier;->clear()V
-HSPLandroidx/compose/runtime/AbstractApplier;->down(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/AbstractApplier;->getCurrent()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/AbstractApplier;->getRoot()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/AbstractApplier;->setCurrent(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/AbstractApplier;->up()V
-HSPLandroidx/compose/runtime/ActualAndroid_androidKt$DefaultMonotonicFrameClock$2;-><clinit>()V
-HSPLandroidx/compose/runtime/ActualAndroid_androidKt$DefaultMonotonicFrameClock$2;-><init>()V
-HSPLandroidx/compose/runtime/ActualAndroid_androidKt;-><clinit>()V
-HSPLandroidx/compose/runtime/ActualAndroid_androidKt;->createSnapshotMutableState(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;)Landroidx/compose/runtime/snapshots/SnapshotMutableState;
-HSPLandroidx/compose/runtime/ActualJvm_jvmKt;->identityHashCode(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/ActualJvm_jvmKt;->invokeComposable(Landroidx/compose/runtime/Composer;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/ActualJvm_jvmKt;->invokeComposableForResult(Landroidx/compose/runtime/Composer;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Anchor;-><init>(I)V
-HSPLandroidx/compose/runtime/Anchor;->getLocation$runtime_release()I
-HSPLandroidx/compose/runtime/Anchor;->getValid()Z
-HSPLandroidx/compose/runtime/Anchor;->setLocation$runtime_release(I)V
-HSPLandroidx/compose/runtime/Anchor;->toIndexFor(Landroidx/compose/runtime/SlotTable;)I
-HSPLandroidx/compose/runtime/Anchor;->toIndexFor(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/Applier;->onBeginChanges()V
-HSPLandroidx/compose/runtime/Applier;->onEndChanges()V
-HSPLandroidx/compose/runtime/BroadcastFrameClock$FrameAwaiter;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/BroadcastFrameClock$FrameAwaiter;->resume(J)V
-HSPLandroidx/compose/runtime/BroadcastFrameClock$withFrameNanos$2$1;-><init>(Landroidx/compose/runtime/BroadcastFrameClock;Lkotlin/jvm/internal/Ref$ObjectRef;)V
-HSPLandroidx/compose/runtime/BroadcastFrameClock;-><clinit>()V
-HSPLandroidx/compose/runtime/BroadcastFrameClock;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->access$getAwaiters$p(Landroidx/compose/runtime/BroadcastFrameClock;)Ljava/util/List;
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->access$getFailureCause$p(Landroidx/compose/runtime/BroadcastFrameClock;)Ljava/lang/Throwable;
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->access$getLock$p(Landroidx/compose/runtime/BroadcastFrameClock;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->access$getOnNewAwaiters$p(Landroidx/compose/runtime/BroadcastFrameClock;)Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->getHasAwaiters()Z
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->sendFrame(J)V
-HSPLandroidx/compose/runtime/BroadcastFrameClock;->withFrameNanos(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt$lambda-1$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt$lambda-1$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt$lambda-2$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt$lambda-2$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt;-><init>()V
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt;->getLambda-1$runtime_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/runtime/ComposableSingletons$CompositionKt;->getLambda-2$runtime_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/runtime/ComposablesKt;->getCurrentCompositeKeyHash(Landroidx/compose/runtime/Composer;I)I
-HSPLandroidx/compose/runtime/ComposablesKt;->rememberCompositionContext(Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/runtime/Composer$Companion$Empty$1;-><init>()V
-HSPLandroidx/compose/runtime/Composer$Companion;-><clinit>()V
-HSPLandroidx/compose/runtime/Composer$Companion;-><init>()V
-HSPLandroidx/compose/runtime/Composer$Companion;->getEmpty()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Composer;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextHolder;-><init>(Landroidx/compose/runtime/ComposerImpl$CompositionContextImpl;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextHolder;->getRef()Landroidx/compose/runtime/ComposerImpl$CompositionContextImpl;
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextHolder;->onForgotten()V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextHolder;->onRemembered()V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;-><init>(Landroidx/compose/runtime/ComposerImpl;IZ)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->composeInitial$runtime_release(Landroidx/compose/runtime/ControlledComposition;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->dispose()V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->doneComposing$runtime_release()V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->getCollectingParameterInformation$runtime_release()Z
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->getComposers()Ljava/util/Set;
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->getCompositionLocalScope$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->getCompositionLocalScope()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->getCompoundHashKey$runtime_release()I
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->getEffectCoroutineContext$runtime_release()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->invalidate$runtime_release(Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->registerComposer$runtime_release(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->setCompositionLocalScope(Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->startComposing$runtime_release()V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->unregisterComposer$runtime_release(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->unregisterComposition$runtime_release(Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/ComposerImpl$CompositionContextImpl;->updateCompositionLocalScope(Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;)V
-HSPLandroidx/compose/runtime/ComposerImpl$apply$operation$1;-><init>(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl$apply$operation$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$apply$operation$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$createNode$2;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Anchor;I)V
-HSPLandroidx/compose/runtime/ComposerImpl$createNode$2;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$createNode$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$createNode$3;-><init>(Landroidx/compose/runtime/Anchor;I)V
-HSPLandroidx/compose/runtime/ComposerImpl$createNode$3;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$createNode$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$3;-><init>(Landroidx/compose/runtime/ComposerImpl;)V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$3;->invoke(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$3;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$4;-><init>(Landroidx/compose/runtime/ComposerImpl;)V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$4;->invoke(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$4;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$5;-><init>(Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/ComposerImpl;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$5;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$2$5;->invoke()V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$lambda$37$$inlined$sortBy$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposerImpl$doCompose$lambda$37$$inlined$sortBy$1;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/ComposerImpl$endRestartGroup$1$1;-><init>(Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/ComposerImpl;)V
-HSPLandroidx/compose/runtime/ComposerImpl$endRestartGroup$1$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$endRestartGroup$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$realizeDowns$1;-><init>([Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeDowns$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeDowns$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$realizeMovement$1;-><init>(II)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeMovement$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeMovement$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$realizeOperationLocation$2;-><init>(I)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeOperationLocation$2;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeOperationLocation$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$realizeUps$1;-><init>(I)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeUps$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$realizeUps$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$recordInsert$1;-><init>(Landroidx/compose/runtime/SlotTable;Landroidx/compose/runtime/Anchor;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordInsert$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordInsert$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$recordInsert$2;-><init>(Landroidx/compose/runtime/SlotTable;Landroidx/compose/runtime/Anchor;Ljava/util/List;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordInsert$2;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordInsert$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$recordSideEffect$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordSideEffect$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordSideEffect$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$recordSlotEditing$1;-><init>(Landroidx/compose/runtime/Anchor;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordSlotEditing$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$recordSlotEditing$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$start$2;-><init>(I)V
-HSPLandroidx/compose/runtime/ComposerImpl$start$2;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$start$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$startProviders$currentProviders$1;-><init>([Landroidx/compose/runtime/ProvidedValue;Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;)V
-HSPLandroidx/compose/runtime/ComposerImpl$startProviders$currentProviders$1;->invoke(Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerImpl$startProviders$currentProviders$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$startReaderGroup$1;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl$startReaderGroup$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$startReaderGroup$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$updateValue$1;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl$updateValue$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$updateValue$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl$updateValue$2;-><init>(Ljava/lang/Object;I)V
-HSPLandroidx/compose/runtime/ComposerImpl$updateValue$2;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerImpl$updateValue$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;-><init>(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/CompositionContext;Landroidx/compose/runtime/SlotTable;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->access$endGroup(Landroidx/compose/runtime/ComposerImpl;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->access$getChanges$p(Landroidx/compose/runtime/ComposerImpl;)Ljava/util/List;
-HSPLandroidx/compose/runtime/ComposerImpl;->access$getChildrenComposing$p(Landroidx/compose/runtime/ComposerImpl;)I
-HSPLandroidx/compose/runtime/ComposerImpl;->access$getForciblyRecompose$p(Landroidx/compose/runtime/ComposerImpl;)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->access$getParentContext$p(Landroidx/compose/runtime/ComposerImpl;)Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/runtime/ComposerImpl;->access$getProvidersInvalid$p(Landroidx/compose/runtime/ComposerImpl;)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->access$setChanges$p(Landroidx/compose/runtime/ComposerImpl;Ljava/util/List;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->access$setChildrenComposing$p(Landroidx/compose/runtime/ComposerImpl;I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->access$startGroup(Landroidx/compose/runtime/ComposerImpl;ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->addRecomposeScope()V
-HSPLandroidx/compose/runtime/ComposerImpl;->apply(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->buildContext()Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/runtime/ComposerImpl;->changed(F)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->changed(I)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->changed(J)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->changed(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->changed(Z)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->changedInstance(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->changesApplied$runtime_release()V
-HSPLandroidx/compose/runtime/ComposerImpl;->cleanUpCompose()V
-HSPLandroidx/compose/runtime/ComposerImpl;->clearUpdatedNodeCounts()V
-HSPLandroidx/compose/runtime/ComposerImpl;->composeContent$runtime_release(Landroidx/compose/runtime/collection/IdentityArrayMap;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->compoundKeyOf(III)I
-HSPLandroidx/compose/runtime/ComposerImpl;->consume(Landroidx/compose/runtime/CompositionLocal;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;->createNode(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->currentCompositionLocalScope()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerImpl;->currentCompositionLocalScope(I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerImpl;->disableReusing()V
-HSPLandroidx/compose/runtime/ComposerImpl;->dispose$runtime_release()V
-HSPLandroidx/compose/runtime/ComposerImpl;->doCompose(Landroidx/compose/runtime/collection/IdentityArrayMap;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->doRecordDownsFor(II)V
-HSPLandroidx/compose/runtime/ComposerImpl;->enableReusing()V
-HSPLandroidx/compose/runtime/ComposerImpl;->end(Z)V
-HSPLandroidx/compose/runtime/ComposerImpl;->endDefaults()V
-HSPLandroidx/compose/runtime/ComposerImpl;->endGroup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->endNode()V
-HSPLandroidx/compose/runtime/ComposerImpl;->endProviders()V
-HSPLandroidx/compose/runtime/ComposerImpl;->endReplaceableGroup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->endRestartGroup()Landroidx/compose/runtime/ScopeUpdateScope;
-HSPLandroidx/compose/runtime/ComposerImpl;->endReusableGroup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->endRoot()V
-HSPLandroidx/compose/runtime/ComposerImpl;->ensureWriter()V
-HSPLandroidx/compose/runtime/ComposerImpl;->enterGroup(ZLandroidx/compose/runtime/Pending;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->exitGroup(IZ)V
-HSPLandroidx/compose/runtime/ComposerImpl;->finalizeCompose()V
-HSPLandroidx/compose/runtime/ComposerImpl;->getApplier()Landroidx/compose/runtime/Applier;
-HSPLandroidx/compose/runtime/ComposerImpl;->getApplyCoroutineContext()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/runtime/ComposerImpl;->getAreChildrenComposing$runtime_release()Z
-HSPLandroidx/compose/runtime/ComposerImpl;->getComposition()Landroidx/compose/runtime/ControlledComposition;
-HSPLandroidx/compose/runtime/ComposerImpl;->getCompoundKeyHash()I
-HSPLandroidx/compose/runtime/ComposerImpl;->getCurrentRecomposeScope$runtime_release()Landroidx/compose/runtime/RecomposeScopeImpl;
-HSPLandroidx/compose/runtime/ComposerImpl;->getDefaultsInvalid()Z
-HSPLandroidx/compose/runtime/ComposerImpl;->getDeferredChanges$runtime_release()Ljava/util/List;
-HSPLandroidx/compose/runtime/ComposerImpl;->getInserting()Z
-HSPLandroidx/compose/runtime/ComposerImpl;->getNode(Landroidx/compose/runtime/SlotReader;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;->getRecomposeScope()Landroidx/compose/runtime/RecomposeScope;
-HSPLandroidx/compose/runtime/ComposerImpl;->getSkipping()Z
-HSPLandroidx/compose/runtime/ComposerImpl;->groupCompoundKeyPart(Landroidx/compose/runtime/SlotReader;I)I
-HSPLandroidx/compose/runtime/ComposerImpl;->insertedGroupVirtualIndex(I)I
-HSPLandroidx/compose/runtime/ComposerImpl;->isComposing$runtime_release()Z
-HSPLandroidx/compose/runtime/ComposerImpl;->nextSlot()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;->nodeAt(Landroidx/compose/runtime/SlotReader;I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;->nodeIndexOf(IIII)I
-HSPLandroidx/compose/runtime/ComposerImpl;->prepareCompose$runtime_release(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->realizeDowns()V
-HSPLandroidx/compose/runtime/ComposerImpl;->realizeDowns([Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->realizeMovement()V
-HSPLandroidx/compose/runtime/ComposerImpl;->realizeOperationLocation$default(Landroidx/compose/runtime/ComposerImpl;ZILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->realizeOperationLocation(Z)V
-HSPLandroidx/compose/runtime/ComposerImpl;->realizeUps()V
-HSPLandroidx/compose/runtime/ComposerImpl;->recompose$runtime_release(Landroidx/compose/runtime/collection/IdentityArrayMap;)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->recomposeToGroupEnd()V
-HSPLandroidx/compose/runtime/ComposerImpl;->record(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordApplierOperation(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordDelete()V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordDown(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordEndGroup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordEndRoot()V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordFixup(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordInsert(Landroidx/compose/runtime/Anchor;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordInsertUpFixup(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordReaderMoving(I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordRemoveNode(II)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordSideEffect(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordSlotEditing()V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordSlotEditingOperation(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordSlotTableOperation$default(Landroidx/compose/runtime/ComposerImpl;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordSlotTableOperation(ZLkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordUp()V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordUpsAndDowns(III)V
-HSPLandroidx/compose/runtime/ComposerImpl;->recordUsed(Landroidx/compose/runtime/RecomposeScope;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->registerInsertUpFixup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->rememberedValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;->reportAllMovableContent()V
-HSPLandroidx/compose/runtime/ComposerImpl;->reportFreeMovableContent$reportGroup(Landroidx/compose/runtime/ComposerImpl;IZI)I
-HSPLandroidx/compose/runtime/ComposerImpl;->reportFreeMovableContent(I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->resolveCompositionLocal(Landroidx/compose/runtime/CompositionLocal;Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerImpl;->skipCurrentGroup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->skipGroup()V
-HSPLandroidx/compose/runtime/ComposerImpl;->skipReaderToGroupEnd()V
-HSPLandroidx/compose/runtime/ComposerImpl;->skipToGroupEnd()V
-HSPLandroidx/compose/runtime/ComposerImpl;->start-BaiHCIY(ILjava/lang/Object;ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startDefaults()V
-HSPLandroidx/compose/runtime/ComposerImpl;->startGroup(I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startGroup(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startNode()V
-HSPLandroidx/compose/runtime/ComposerImpl;->startProviders([Landroidx/compose/runtime/ProvidedValue;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startReaderGroup(ZLjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startReplaceableGroup(I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startRestartGroup(I)Landroidx/compose/runtime/Composer;
-HSPLandroidx/compose/runtime/ComposerImpl;->startReusableGroup(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->startReusableNode()V
-HSPLandroidx/compose/runtime/ComposerImpl;->startRoot()V
-HSPLandroidx/compose/runtime/ComposerImpl;->tryImminentInvalidation$runtime_release(Landroidx/compose/runtime/RecomposeScopeImpl;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/ComposerImpl;->updateCompoundKeyWhenWeEnterGroup(ILjava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateCompoundKeyWhenWeEnterGroupKeyHash(I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateCompoundKeyWhenWeExitGroup(ILjava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateCompoundKeyWhenWeExitGroupKeyHash(I)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateNodeCount(II)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateNodeCountOverrides(II)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateProviderMapGroup(Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerImpl;->updateRememberedValue(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
-HSPLandroidx/compose/runtime/ComposerImpl;->useNode()V
-HSPLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
-HSPLandroidx/compose/runtime/ComposerImpl;->validateNodeNotExpected()V
-HSPLandroidx/compose/runtime/ComposerKt$endGroupInstance$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerKt$endGroupInstance$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposerKt$endGroupInstance$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerKt$endGroupInstance$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt$removeCurrentGroupInstance$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerKt$removeCurrentGroupInstance$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposerKt$removeCurrentGroupInstance$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerKt$removeCurrentGroupInstance$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt$resetSlotsInstance$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerKt$resetSlotsInstance$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposerKt$skipToGroupEndInstance$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerKt$skipToGroupEndInstance$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposerKt$startRootGroup$1;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerKt$startRootGroup$1;-><init>()V
-HSPLandroidx/compose/runtime/ComposerKt$startRootGroup$1;->invoke(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerKt$startRootGroup$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;-><clinit>()V
-HSPLandroidx/compose/runtime/ComposerKt;->access$asBool(I)Z
-HSPLandroidx/compose/runtime/ComposerKt;->access$asInt(Z)I
-HSPLandroidx/compose/runtime/ComposerKt;->access$compositionLocalMapOf([Landroidx/compose/runtime/ProvidedValue;Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerKt;->access$firstInRange(Ljava/util/List;II)Landroidx/compose/runtime/Invalidation;
-HSPLandroidx/compose/runtime/ComposerKt;->access$getEndGroupInstance$p()Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/runtime/ComposerKt;->access$getJoinedKey(Landroidx/compose/runtime/KeyInfo;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->access$getRemoveCurrentGroupInstance$p()Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/runtime/ComposerKt;->access$getStartRootGroup$p()Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/runtime/ComposerKt;->access$insertIfMissing(Ljava/util/List;ILandroidx/compose/runtime/RecomposeScopeImpl;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerKt;->access$multiMap()Ljava/util/HashMap;
-HSPLandroidx/compose/runtime/ComposerKt;->access$nearestCommonRootOf(Landroidx/compose/runtime/SlotReader;III)I
-HSPLandroidx/compose/runtime/ComposerKt;->access$pop(Ljava/util/HashMap;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->access$put(Ljava/util/HashMap;Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/ComposerKt;->access$removeLocation(Ljava/util/List;I)Landroidx/compose/runtime/Invalidation;
-HSPLandroidx/compose/runtime/ComposerKt;->access$removeRange(Ljava/util/List;II)V
-HSPLandroidx/compose/runtime/ComposerKt;->asBool(I)Z
-HSPLandroidx/compose/runtime/ComposerKt;->asInt(Z)I
-HSPLandroidx/compose/runtime/ComposerKt;->compositionLocalMapOf([Landroidx/compose/runtime/ProvidedValue;Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/ComposerKt;->contains(Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;Landroidx/compose/runtime/CompositionLocal;)Z
-HSPLandroidx/compose/runtime/ComposerKt;->distanceFrom(Landroidx/compose/runtime/SlotReader;II)I
-HSPLandroidx/compose/runtime/ComposerKt;->findInsertLocation(Ljava/util/List;I)I
-HSPLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
-HSPLandroidx/compose/runtime/ComposerKt;->firstInRange(Ljava/util/List;II)Landroidx/compose/runtime/Invalidation;
-HSPLandroidx/compose/runtime/ComposerKt;->getCompositionLocalMap()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getInvocation()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getJoinedKey(Landroidx/compose/runtime/KeyInfo;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getProvider()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getProviderMaps()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getProviderValues()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getReference()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->getValueOf(Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;Landroidx/compose/runtime/CompositionLocal;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->insertIfMissing(Ljava/util/List;ILandroidx/compose/runtime/RecomposeScopeImpl;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/ComposerKt;->isTraceInProgress()Z
-HSPLandroidx/compose/runtime/ComposerKt;->multiMap()Ljava/util/HashMap;
-HSPLandroidx/compose/runtime/ComposerKt;->nearestCommonRootOf(Landroidx/compose/runtime/SlotReader;III)I
-HSPLandroidx/compose/runtime/ComposerKt;->pop(Ljava/util/HashMap;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/ComposerKt;->put(Ljava/util/HashMap;Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/ComposerKt;->remove(Ljava/util/HashMap;Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Unit;
-HSPLandroidx/compose/runtime/ComposerKt;->removeCurrentGroup(Landroidx/compose/runtime/SlotWriter;Landroidx/compose/runtime/RememberManager;)V
-HSPLandroidx/compose/runtime/ComposerKt;->removeLocation(Ljava/util/List;I)Landroidx/compose/runtime/Invalidation;
-HSPLandroidx/compose/runtime/ComposerKt;->removeRange(Ljava/util/List;II)V
-HSPLandroidx/compose/runtime/ComposerKt;->runtimeCheck(Z)V
-HSPLandroidx/compose/runtime/CompositionContext;-><clinit>()V
-HSPLandroidx/compose/runtime/CompositionContext;-><init>()V
-HSPLandroidx/compose/runtime/CompositionContext;->doneComposing$runtime_release()V
-HSPLandroidx/compose/runtime/CompositionContext;->getCompositionLocalScope$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/CompositionContext;->registerComposer$runtime_release(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/CompositionContext;->startComposing$runtime_release()V
-HSPLandroidx/compose/runtime/CompositionContext;->unregisterComposer$runtime_release(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/CompositionContextKt;-><clinit>()V
-HSPLandroidx/compose/runtime/CompositionContextKt;->access$getEmptyCompositionLocalMap$p()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;-><init>(Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->dispatchAbandons()V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->dispatchNodeCallbacks()V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->dispatchRememberObservers()V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->dispatchSideEffects()V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->forgetting(Landroidx/compose/runtime/RememberObserver;)V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->remembering(Landroidx/compose/runtime/RememberObserver;)V
-HSPLandroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;->sideEffect(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/CompositionImpl;-><init>(Landroidx/compose/runtime/CompositionContext;Landroidx/compose/runtime/Applier;Lkotlin/coroutines/CoroutineContext;)V
-HSPLandroidx/compose/runtime/CompositionImpl;-><init>(Landroidx/compose/runtime/CompositionContext;Landroidx/compose/runtime/Applier;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->addPendingInvalidationsLocked$invalidate(Landroidx/compose/runtime/CompositionImpl;ZLkotlin/jvm/internal/Ref$ObjectRef;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->addPendingInvalidationsLocked(Ljava/util/Set;Z)V
-HSPLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
-HSPLandroidx/compose/runtime/CompositionImpl;->applyChangesInLocked(Ljava/util/List;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->applyLateChanges()V
-HSPLandroidx/compose/runtime/CompositionImpl;->changesApplied()V
-HSPLandroidx/compose/runtime/CompositionImpl;->cleanUpDerivedStateObservations()V
-HSPLandroidx/compose/runtime/CompositionImpl;->composeContent(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->dispose()V
-HSPLandroidx/compose/runtime/CompositionImpl;->drainPendingModificationsForCompositionLocked()V
-HSPLandroidx/compose/runtime/CompositionImpl;->drainPendingModificationsLocked()V
-HSPLandroidx/compose/runtime/CompositionImpl;->getAreChildrenComposing()Z
-HSPLandroidx/compose/runtime/CompositionImpl;->getHasInvalidations()Z
-HSPLandroidx/compose/runtime/CompositionImpl;->invalidate(Landroidx/compose/runtime/RecomposeScopeImpl;Ljava/lang/Object;)Landroidx/compose/runtime/InvalidationResult;
-HSPLandroidx/compose/runtime/CompositionImpl;->invalidateChecked(Landroidx/compose/runtime/RecomposeScopeImpl;Landroidx/compose/runtime/Anchor;Ljava/lang/Object;)Landroidx/compose/runtime/InvalidationResult;
-HSPLandroidx/compose/runtime/CompositionImpl;->invalidateScopeOfLocked(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->isComposing()Z
-HSPLandroidx/compose/runtime/CompositionImpl;->isDisposed()Z
-HSPLandroidx/compose/runtime/CompositionImpl;->observesAnyOf(Ljava/util/Set;)Z
-HSPLandroidx/compose/runtime/CompositionImpl;->prepareCompose(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->recompose()Z
-HSPLandroidx/compose/runtime/CompositionImpl;->recordModificationsOf(Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->recordReadOf(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->recordWriteOf(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->removeObservation$runtime_release(Ljava/lang/Object;Landroidx/compose/runtime/RecomposeScopeImpl;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->setContent(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/CompositionImpl;->setPendingInvalidScopes$runtime_release(Z)V
-HSPLandroidx/compose/runtime/CompositionImpl;->takeInvalidations()Landroidx/compose/runtime/collection/IdentityArrayMap;
-HSPLandroidx/compose/runtime/CompositionKt;-><clinit>()V
-HSPLandroidx/compose/runtime/CompositionKt;->Composition(Landroidx/compose/runtime/Applier;Landroidx/compose/runtime/CompositionContext;)Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/runtime/CompositionKt;->access$addValue(Landroidx/compose/runtime/collection/IdentityArrayMap;Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/CompositionKt;->access$getPendingApplyNoModifications$p()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/CompositionKt;->addValue(Landroidx/compose/runtime/collection/IdentityArrayMap;Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/CompositionLocal;-><clinit>()V
-HSPLandroidx/compose/runtime/CompositionLocal;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/CompositionLocal;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/CompositionLocal;->getDefaultValueHolder$runtime_release()Landroidx/compose/runtime/LazyValueHolder;
-HSPLandroidx/compose/runtime/CompositionLocalKt;->CompositionLocalProvider([Landroidx/compose/runtime/ProvidedValue;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/CompositionLocalKt;->compositionLocalOf$default(Landroidx/compose/runtime/SnapshotMutationPolicy;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/runtime/CompositionLocalKt;->compositionLocalOf(Landroidx/compose/runtime/SnapshotMutationPolicy;Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/runtime/CompositionLocalKt;->staticCompositionLocalOf(Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/runtime/CompositionScopedCoroutineScopeCanceller;-><init>(Lkotlinx/coroutines/CoroutineScope;)V
-HSPLandroidx/compose/runtime/CompositionScopedCoroutineScopeCanceller;->getCoroutineScope()Lkotlinx/coroutines/CoroutineScope;
-HSPLandroidx/compose/runtime/CompositionScopedCoroutineScopeCanceller;->onForgotten()V
-HSPLandroidx/compose/runtime/CompositionScopedCoroutineScopeCanceller;->onRemembered()V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord$Companion;-><init>()V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord$Companion;->getUnset()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;-><clinit>()V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;-><init>()V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->access$getUnset$cp()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->assign(Landroidx/compose/runtime/snapshots/StateRecord;)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->create()Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->getDependencies()Landroidx/compose/runtime/collection/IdentityArrayMap;
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->getResult()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->isValid(Landroidx/compose/runtime/DerivedState;Landroidx/compose/runtime/snapshots/Snapshot;)Z
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->readableHash(Landroidx/compose/runtime/DerivedState;Landroidx/compose/runtime/snapshots/Snapshot;)I
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->setDependencies(Landroidx/compose/runtime/collection/IdentityArrayMap;)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->setResult(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$ResultRecord;->setResultHash(I)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$currentRecord$result$1$result$1;-><init>(Landroidx/compose/runtime/DerivedSnapshotState;Landroidx/compose/runtime/collection/IdentityArrayMap;I)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState$currentRecord$result$1$result$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState$currentRecord$result$1$result$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/SnapshotMutationPolicy;)V
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->currentRecord(Landroidx/compose/runtime/DerivedSnapshotState$ResultRecord;Landroidx/compose/runtime/snapshots/Snapshot;ZLkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/DerivedSnapshotState$ResultRecord;
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->getCurrentValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->getDependencies()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->getFirstStateRecord()Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->getPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/DerivedSnapshotState;->prependStateRecord(Landroidx/compose/runtime/snapshots/StateRecord;)V
-HSPLandroidx/compose/runtime/DisposableEffectImpl;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/DisposableEffectImpl;->onForgotten()V
-HSPLandroidx/compose/runtime/DisposableEffectImpl;->onRemembered()V
-HSPLandroidx/compose/runtime/DisposableEffectScope;-><clinit>()V
-HSPLandroidx/compose/runtime/DisposableEffectScope;-><init>()V
-HSPLandroidx/compose/runtime/DynamicProvidableCompositionLocal;-><init>(Landroidx/compose/runtime/SnapshotMutationPolicy;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/DynamicProvidableCompositionLocal;->access$getPolicy$p(Landroidx/compose/runtime/DynamicProvidableCompositionLocal;)Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/DynamicProvidableCompositionLocal;->provided$runtime_release(Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/runtime/EffectsKt;-><clinit>()V
-HSPLandroidx/compose/runtime/EffectsKt;->DisposableEffect(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->DisposableEffect(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->DisposableEffect(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->LaunchedEffect(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->LaunchedEffect(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->LaunchedEffect(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->LaunchedEffect([Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->SideEffect(Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/EffectsKt;->access$getInternalDisposableEffectScope$p()Landroidx/compose/runtime/DisposableEffectScope;
-HSPLandroidx/compose/runtime/EffectsKt;->createCompositionCoroutineScope(Lkotlin/coroutines/CoroutineContext;Landroidx/compose/runtime/Composer;)Lkotlinx/coroutines/CoroutineScope;
-HSPLandroidx/compose/runtime/GroupInfo;-><init>(III)V
-HSPLandroidx/compose/runtime/GroupInfo;->getNodeCount()I
-HSPLandroidx/compose/runtime/GroupInfo;->getNodeIndex()I
-HSPLandroidx/compose/runtime/GroupInfo;->getSlotIndex()I
-HSPLandroidx/compose/runtime/GroupInfo;->setNodeCount(I)V
-HSPLandroidx/compose/runtime/GroupInfo;->setNodeIndex(I)V
-HSPLandroidx/compose/runtime/GroupInfo;->setSlotIndex(I)V
-HSPLandroidx/compose/runtime/GroupKind$Companion;-><init>()V
-HSPLandroidx/compose/runtime/GroupKind$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/GroupKind$Companion;->getGroup-ULZAiWs()I
-HSPLandroidx/compose/runtime/GroupKind$Companion;->getNode-ULZAiWs()I
-HSPLandroidx/compose/runtime/GroupKind$Companion;->getReusableNode-ULZAiWs()I
-HSPLandroidx/compose/runtime/GroupKind;-><clinit>()V
-HSPLandroidx/compose/runtime/GroupKind;->access$getGroup$cp()I
-HSPLandroidx/compose/runtime/GroupKind;->access$getNode$cp()I
-HSPLandroidx/compose/runtime/GroupKind;->access$getReusableNode$cp()I
-HSPLandroidx/compose/runtime/GroupKind;->constructor-impl(I)I
-HSPLandroidx/compose/runtime/IntStack;-><init>()V
-HSPLandroidx/compose/runtime/IntStack;->clear()V
-HSPLandroidx/compose/runtime/IntStack;->getSize()I
-HSPLandroidx/compose/runtime/IntStack;->isEmpty()Z
-HSPLandroidx/compose/runtime/IntStack;->peek()I
-HSPLandroidx/compose/runtime/IntStack;->peekOr(I)I
-HSPLandroidx/compose/runtime/IntStack;->pop()I
-HSPLandroidx/compose/runtime/IntStack;->push(I)V
-HSPLandroidx/compose/runtime/Invalidation;-><init>(Landroidx/compose/runtime/RecomposeScopeImpl;ILandroidx/compose/runtime/collection/IdentityArraySet;)V
-HSPLandroidx/compose/runtime/Invalidation;->getLocation()I
-HSPLandroidx/compose/runtime/Invalidation;->getScope()Landroidx/compose/runtime/RecomposeScopeImpl;
-HSPLandroidx/compose/runtime/Invalidation;->isInvalid()Z
-HSPLandroidx/compose/runtime/InvalidationResult;->$values()[Landroidx/compose/runtime/InvalidationResult;
-HSPLandroidx/compose/runtime/InvalidationResult;-><clinit>()V
-HSPLandroidx/compose/runtime/InvalidationResult;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/runtime/KeyInfo;-><init>(ILjava/lang/Object;III)V
-HSPLandroidx/compose/runtime/KeyInfo;->getKey()I
-HSPLandroidx/compose/runtime/KeyInfo;->getLocation()I
-HSPLandroidx/compose/runtime/KeyInfo;->getNodes()I
-HSPLandroidx/compose/runtime/KeyInfo;->getObjectKey()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Latch;-><init>()V
-HSPLandroidx/compose/runtime/Latch;->await(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Latch;->closeLatch()V
-HSPLandroidx/compose/runtime/Latch;->isOpen()Z
-HSPLandroidx/compose/runtime/Latch;->openLatch()V
-HSPLandroidx/compose/runtime/LaunchedEffectImpl;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/LaunchedEffectImpl;->onForgotten()V
-HSPLandroidx/compose/runtime/LaunchedEffectImpl;->onRemembered()V
-HSPLandroidx/compose/runtime/LazyValueHolder;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/LazyValueHolder;->getCurrent()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/LazyValueHolder;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/MonotonicFrameClock$DefaultImpls;->fold(Landroidx/compose/runtime/MonotonicFrameClock;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/MonotonicFrameClock$DefaultImpls;->get(Landroidx/compose/runtime/MonotonicFrameClock;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLandroidx/compose/runtime/MonotonicFrameClock$DefaultImpls;->minusKey(Landroidx/compose/runtime/MonotonicFrameClock;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/runtime/MonotonicFrameClock$Key;-><clinit>()V
-HSPLandroidx/compose/runtime/MonotonicFrameClock$Key;-><init>()V
-HSPLandroidx/compose/runtime/MonotonicFrameClock;-><clinit>()V
-HSPLandroidx/compose/runtime/MonotonicFrameClock;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
-HSPLandroidx/compose/runtime/MonotonicFrameClockKt;->getMonotonicFrameClock(Lkotlin/coroutines/CoroutineContext;)Landroidx/compose/runtime/MonotonicFrameClock;
-HSPLandroidx/compose/runtime/MonotonicFrameClockKt;->withFrameNanos(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/NeverEqualPolicy;-><clinit>()V
-HSPLandroidx/compose/runtime/NeverEqualPolicy;-><init>()V
-HSPLandroidx/compose/runtime/NeverEqualPolicy;->equivalent(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/OpaqueKey;-><init>(Ljava/lang/String;)V
-HSPLandroidx/compose/runtime/OpaqueKey;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/OpaqueKey;->hashCode()I
-HSPLandroidx/compose/runtime/ParcelableSnapshotMutableState$Companion$CREATOR$1;-><init>()V
-HSPLandroidx/compose/runtime/ParcelableSnapshotMutableState$Companion;-><init>()V
-HSPLandroidx/compose/runtime/ParcelableSnapshotMutableState$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/ParcelableSnapshotMutableState;-><clinit>()V
-HSPLandroidx/compose/runtime/ParcelableSnapshotMutableState;-><init>(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;)V
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock$withFrameNanos$1;-><init>(Landroidx/compose/runtime/PausableMonotonicFrameClock;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock$withFrameNanos$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;-><clinit>()V
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;-><init>(Landroidx/compose/runtime/MonotonicFrameClock;)V
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->pause()V
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->resume()V
-HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->withFrameNanos(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Pending$keyMap$2;-><init>(Landroidx/compose/runtime/Pending;)V
-HSPLandroidx/compose/runtime/Pending$keyMap$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Pending$keyMap$2;->invoke()Ljava/util/HashMap;
-HSPLandroidx/compose/runtime/Pending;-><init>(Ljava/util/List;I)V
-HSPLandroidx/compose/runtime/Pending;->getGroupIndex()I
-HSPLandroidx/compose/runtime/Pending;->getKeyInfos()Ljava/util/List;
-HSPLandroidx/compose/runtime/Pending;->getKeyMap()Ljava/util/HashMap;
-HSPLandroidx/compose/runtime/Pending;->getNext(ILjava/lang/Object;)Landroidx/compose/runtime/KeyInfo;
-HSPLandroidx/compose/runtime/Pending;->getStartIndex()I
-HSPLandroidx/compose/runtime/Pending;->getUsed()Ljava/util/List;
-HSPLandroidx/compose/runtime/Pending;->nodePositionOf(Landroidx/compose/runtime/KeyInfo;)I
-HSPLandroidx/compose/runtime/Pending;->recordUsed(Landroidx/compose/runtime/KeyInfo;)Z
-HSPLandroidx/compose/runtime/Pending;->registerInsert(Landroidx/compose/runtime/KeyInfo;I)V
-HSPLandroidx/compose/runtime/Pending;->registerMoveSlot(II)V
-HSPLandroidx/compose/runtime/Pending;->setGroupIndex(I)V
-HSPLandroidx/compose/runtime/Pending;->slotPositionOf(Landroidx/compose/runtime/KeyInfo;)I
-HSPLandroidx/compose/runtime/Pending;->updateNodeCount(II)Z
-HSPLandroidx/compose/runtime/Pending;->updatedNodeCountOf(Landroidx/compose/runtime/KeyInfo;)I
-HSPLandroidx/compose/runtime/PrioritySet;-><init>(Ljava/util/List;)V
-HSPLandroidx/compose/runtime/PrioritySet;-><init>(Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/PrioritySet;->add(I)V
-HSPLandroidx/compose/runtime/PrioritySet;->isNotEmpty()Z
-HSPLandroidx/compose/runtime/PrioritySet;->peek()I
-HSPLandroidx/compose/runtime/PrioritySet;->takeMax()I
-HSPLandroidx/compose/runtime/ProvidableCompositionLocal;-><clinit>()V
-HSPLandroidx/compose/runtime/ProvidableCompositionLocal;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/ProvidableCompositionLocal;->provides(Ljava/lang/Object;)Landroidx/compose/runtime/ProvidedValue;
-HSPLandroidx/compose/runtime/ProvidableCompositionLocal;->providesDefault(Ljava/lang/Object;)Landroidx/compose/runtime/ProvidedValue;
-HSPLandroidx/compose/runtime/ProvidedValue;-><clinit>()V
-HSPLandroidx/compose/runtime/ProvidedValue;-><init>(Landroidx/compose/runtime/CompositionLocal;Ljava/lang/Object;Z)V
-HSPLandroidx/compose/runtime/ProvidedValue;->getCanOverride()Z
-HSPLandroidx/compose/runtime/ProvidedValue;->getCompositionLocal()Landroidx/compose/runtime/CompositionLocal;
-HSPLandroidx/compose/runtime/ProvidedValue;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl$end$1$2;-><init>(Landroidx/compose/runtime/RecomposeScopeImpl;ILandroidx/compose/runtime/collection/IdentityArrayIntMap;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl$end$1$2;->invoke(Landroidx/compose/runtime/Composition;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl$end$1$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;-><init>(Landroidx/compose/runtime/CompositionImpl;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->access$getCurrentToken$p(Landroidx/compose/runtime/RecomposeScopeImpl;)I
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->access$getTrackedInstances$p(Landroidx/compose/runtime/RecomposeScopeImpl;)Landroidx/compose/runtime/collection/IdentityArrayIntMap;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->access$setTrackedInstances$p(Landroidx/compose/runtime/RecomposeScopeImpl;Landroidx/compose/runtime/collection/IdentityArrayIntMap;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->compose(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->end(I)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getAnchor()Landroidx/compose/runtime/Anchor;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getCanRecompose()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getComposition()Landroidx/compose/runtime/CompositionImpl;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getDefaultsInScope()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getDefaultsInvalid()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getRequiresRecompose()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getRereading()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getSkipped$runtime_release()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getUsed()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->getValid()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->invalidate()V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->invalidateForResult(Ljava/lang/Object;)Landroidx/compose/runtime/InvalidationResult;
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->isConditional()Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->isInvalidFor(Landroidx/compose/runtime/collection/IdentityArraySet;)Z
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->recordRead(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->release()V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->scopeSkipped()V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->setAnchor(Landroidx/compose/runtime/Anchor;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->setDefaultsInScope(Z)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->setDefaultsInvalid(Z)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->setRequiresRecompose(Z)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->setSkipped(Z)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->setUsed(Z)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->start(I)V
-HSPLandroidx/compose/runtime/RecomposeScopeImpl;->updateScope(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/RecomposeScopeImplKt;->updateChangedFlags(I)I
-HSPLandroidx/compose/runtime/Recomposer$Companion;-><init>()V
-HSPLandroidx/compose/runtime/Recomposer$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/Recomposer$Companion;->access$addRunning(Landroidx/compose/runtime/Recomposer$Companion;Landroidx/compose/runtime/Recomposer$RecomposerInfoImpl;)V
-HSPLandroidx/compose/runtime/Recomposer$Companion;->access$removeRunning(Landroidx/compose/runtime/Recomposer$Companion;Landroidx/compose/runtime/Recomposer$RecomposerInfoImpl;)V
-HSPLandroidx/compose/runtime/Recomposer$Companion;->addRunning(Landroidx/compose/runtime/Recomposer$RecomposerInfoImpl;)V
-HSPLandroidx/compose/runtime/Recomposer$Companion;->removeRunning(Landroidx/compose/runtime/Recomposer$RecomposerInfoImpl;)V
-HSPLandroidx/compose/runtime/Recomposer$RecomposerInfoImpl;-><init>(Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer$State;->$values()[Landroidx/compose/runtime/Recomposer$State;
-HSPLandroidx/compose/runtime/Recomposer$State;-><clinit>()V
-HSPLandroidx/compose/runtime/Recomposer$State;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/runtime/Recomposer$broadcastFrameClock$1;-><init>(Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer$broadcastFrameClock$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$broadcastFrameClock$1;->invoke()V
-HSPLandroidx/compose/runtime/Recomposer$effectJob$1$1$1$1;-><init>(Landroidx/compose/runtime/Recomposer;Ljava/lang/Throwable;)V
-HSPLandroidx/compose/runtime/Recomposer$effectJob$1$1$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$effectJob$1$1$1$1;->invoke(Ljava/lang/Throwable;)V
-HSPLandroidx/compose/runtime/Recomposer$effectJob$1$1;-><init>(Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer$effectJob$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$effectJob$1$1;->invoke(Ljava/lang/Throwable;)V
-HSPLandroidx/compose/runtime/Recomposer$join$2;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/Recomposer$join$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/runtime/Recomposer$join$2;->invoke(Landroidx/compose/runtime/Recomposer$State;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$join$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$join$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$performRecompose$1$1;-><init>(Landroidx/compose/runtime/collection/IdentityArraySet;Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/Recomposer$performRecompose$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$performRecompose$1$1;->invoke()V
-HSPLandroidx/compose/runtime/Recomposer$readObserverOf$1;-><init>(Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/Recomposer$readObserverOf$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$readObserverOf$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$2;-><init>(Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/MonotonicFrameClock;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$unregisterApplyObserver$1;-><init>(Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$unregisterApplyObserver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2$unregisterApplyObserver$1;->invoke(Ljava/util/Set;Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2;-><init>(Landroidx/compose/runtime/Recomposer;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/MonotonicFrameClock;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$recompositionRunner$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2$2;-><init>(Landroidx/compose/runtime/Recomposer;Ljava/util/List;Ljava/util/List;Ljava/util/Set;Ljava/util/List;Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2$2;->invoke(J)V
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;-><init>(Landroidx/compose/runtime/Recomposer;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;->access$invokeSuspend$fillToInsert(Ljava/util/List;Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/runtime/MonotonicFrameClock;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;->invokeSuspend$fillToInsert(Ljava/util/List;Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$writeObserverOf$1;-><init>(Landroidx/compose/runtime/ControlledComposition;Landroidx/compose/runtime/collection/IdentityArraySet;)V
-HSPLandroidx/compose/runtime/Recomposer$writeObserverOf$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer$writeObserverOf$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/Recomposer;-><clinit>()V
-HSPLandroidx/compose/runtime/Recomposer;-><init>(Lkotlin/coroutines/CoroutineContext;)V
-HSPLandroidx/compose/runtime/Recomposer;->access$awaitWorkAvailable(Landroidx/compose/runtime/Recomposer;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer;->access$deriveStateLocked(Landroidx/compose/runtime/Recomposer;)Lkotlinx/coroutines/CancellableContinuation;
-HSPLandroidx/compose/runtime/Recomposer;->access$discardUnusedValues(Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer;->access$getBroadcastFrameClock$p(Landroidx/compose/runtime/Recomposer;)Landroidx/compose/runtime/BroadcastFrameClock;
-HSPLandroidx/compose/runtime/Recomposer;->access$getCompositionInvalidations$p(Landroidx/compose/runtime/Recomposer;)Ljava/util/List;
-HSPLandroidx/compose/runtime/Recomposer;->access$getCompositionValuesAwaitingInsert$p(Landroidx/compose/runtime/Recomposer;)Ljava/util/List;
-HSPLandroidx/compose/runtime/Recomposer;->access$getHasFrameWorkLocked(Landroidx/compose/runtime/Recomposer;)Z
-HSPLandroidx/compose/runtime/Recomposer;->access$getHasSchedulingWork(Landroidx/compose/runtime/Recomposer;)Z
-HSPLandroidx/compose/runtime/Recomposer;->access$getKnownCompositions$p(Landroidx/compose/runtime/Recomposer;)Ljava/util/List;
-HSPLandroidx/compose/runtime/Recomposer;->access$getRecomposerInfo$p(Landroidx/compose/runtime/Recomposer;)Landroidx/compose/runtime/Recomposer$RecomposerInfoImpl;
-HSPLandroidx/compose/runtime/Recomposer;->access$getRunnerJob$p(Landroidx/compose/runtime/Recomposer;)Lkotlinx/coroutines/Job;
-HSPLandroidx/compose/runtime/Recomposer;->access$getShouldKeepRecomposing(Landroidx/compose/runtime/Recomposer;)Z
-HSPLandroidx/compose/runtime/Recomposer;->access$getSnapshotInvalidations$p(Landroidx/compose/runtime/Recomposer;)Ljava/util/Set;
-HSPLandroidx/compose/runtime/Recomposer;->access$getStateLock$p(Landroidx/compose/runtime/Recomposer;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer;->access$get_runningRecomposers$cp()Lkotlinx/coroutines/flow/MutableStateFlow;
-HSPLandroidx/compose/runtime/Recomposer;->access$get_state$p(Landroidx/compose/runtime/Recomposer;)Lkotlinx/coroutines/flow/MutableStateFlow;
-HSPLandroidx/compose/runtime/Recomposer;->access$isClosed$p(Landroidx/compose/runtime/Recomposer;)Z
-HSPLandroidx/compose/runtime/Recomposer;->access$performRecompose(Landroidx/compose/runtime/Recomposer;Landroidx/compose/runtime/ControlledComposition;Landroidx/compose/runtime/collection/IdentityArraySet;)Landroidx/compose/runtime/ControlledComposition;
-HSPLandroidx/compose/runtime/Recomposer;->access$recordComposerModificationsLocked(Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/runtime/Recomposer;->access$registerRunnerJob(Landroidx/compose/runtime/Recomposer;Lkotlinx/coroutines/Job;)V
-HSPLandroidx/compose/runtime/Recomposer;->access$setChangeCount$p(Landroidx/compose/runtime/Recomposer;J)V
-HSPLandroidx/compose/runtime/Recomposer;->access$setCloseCause$p(Landroidx/compose/runtime/Recomposer;Ljava/lang/Throwable;)V
-HSPLandroidx/compose/runtime/Recomposer;->access$setRunnerJob$p(Landroidx/compose/runtime/Recomposer;Lkotlinx/coroutines/Job;)V
-HSPLandroidx/compose/runtime/Recomposer;->access$setWorkContinuation$p(Landroidx/compose/runtime/Recomposer;Lkotlinx/coroutines/CancellableContinuation;)V
-HSPLandroidx/compose/runtime/Recomposer;->applyAndCheck(Landroidx/compose/runtime/snapshots/MutableSnapshot;)V
-HSPLandroidx/compose/runtime/Recomposer;->awaitWorkAvailable(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer;->cancel()V
-HSPLandroidx/compose/runtime/Recomposer;->composeInitial$runtime_release(Landroidx/compose/runtime/ControlledComposition;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/Recomposer;->deriveStateLocked()Lkotlinx/coroutines/CancellableContinuation;
-HSPLandroidx/compose/runtime/Recomposer;->discardUnusedValues()V
-HSPLandroidx/compose/runtime/Recomposer;->getChangeCount()J
-HSPLandroidx/compose/runtime/Recomposer;->getCollectingParameterInformation$runtime_release()Z
-HSPLandroidx/compose/runtime/Recomposer;->getCompoundHashKey$runtime_release()I
-HSPLandroidx/compose/runtime/Recomposer;->getCurrentState()Lkotlinx/coroutines/flow/StateFlow;
-HSPLandroidx/compose/runtime/Recomposer;->getEffectCoroutineContext$runtime_release()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/runtime/Recomposer;->getHasFrameWorkLocked()Z
-HSPLandroidx/compose/runtime/Recomposer;->getHasSchedulingWork()Z
-HSPLandroidx/compose/runtime/Recomposer;->getShouldKeepRecomposing()Z
-HSPLandroidx/compose/runtime/Recomposer;->invalidate$runtime_release(Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/Recomposer;->join(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer;->performInitialMovableContentInserts(Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/Recomposer;->performRecompose(Landroidx/compose/runtime/ControlledComposition;Landroidx/compose/runtime/collection/IdentityArraySet;)Landroidx/compose/runtime/ControlledComposition;
-HSPLandroidx/compose/runtime/Recomposer;->readObserverOf(Landroidx/compose/runtime/ControlledComposition;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/Recomposer;->recompositionRunner(Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer;->recordComposerModificationsLocked()V
-HSPLandroidx/compose/runtime/Recomposer;->registerRunnerJob(Lkotlinx/coroutines/Job;)V
-HSPLandroidx/compose/runtime/Recomposer;->runRecomposeAndApplyChanges(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Recomposer;->unregisterComposition$runtime_release(Landroidx/compose/runtime/ControlledComposition;)V
-HSPLandroidx/compose/runtime/Recomposer;->writeObserverOf(Landroidx/compose/runtime/ControlledComposition;Landroidx/compose/runtime/collection/IdentityArraySet;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/ReferentialEqualityPolicy;-><clinit>()V
-HSPLandroidx/compose/runtime/ReferentialEqualityPolicy;-><init>()V
-HSPLandroidx/compose/runtime/SkippableUpdater;-><init>(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/SkippableUpdater;->box-impl(Landroidx/compose/runtime/Composer;)Landroidx/compose/runtime/SkippableUpdater;
-HSPLandroidx/compose/runtime/SkippableUpdater;->constructor-impl(Landroidx/compose/runtime/Composer;)Landroidx/compose/runtime/Composer;
-HSPLandroidx/compose/runtime/SkippableUpdater;->unbox-impl()Landroidx/compose/runtime/Composer;
-HSPLandroidx/compose/runtime/SlotReader;-><init>(Landroidx/compose/runtime/SlotTable;)V
-HSPLandroidx/compose/runtime/SlotReader;->anchor(I)Landroidx/compose/runtime/Anchor;
-HSPLandroidx/compose/runtime/SlotReader;->aux([II)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->beginEmpty()V
-HSPLandroidx/compose/runtime/SlotReader;->close()V
-HSPLandroidx/compose/runtime/SlotReader;->containsMark(I)Z
-HSPLandroidx/compose/runtime/SlotReader;->endEmpty()V
-HSPLandroidx/compose/runtime/SlotReader;->endGroup()V
-HSPLandroidx/compose/runtime/SlotReader;->extractKeys()Ljava/util/List;
-HSPLandroidx/compose/runtime/SlotReader;->getCurrentGroup()I
-HSPLandroidx/compose/runtime/SlotReader;->getGroupAux()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->getGroupEnd()I
-HSPLandroidx/compose/runtime/SlotReader;->getGroupKey()I
-HSPLandroidx/compose/runtime/SlotReader;->getGroupObjectKey()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->getGroupSize()I
-HSPLandroidx/compose/runtime/SlotReader;->getGroupSlotIndex()I
-HSPLandroidx/compose/runtime/SlotReader;->getInEmpty()Z
-HSPLandroidx/compose/runtime/SlotReader;->getParent()I
-HSPLandroidx/compose/runtime/SlotReader;->getParentNodes()I
-HSPLandroidx/compose/runtime/SlotReader;->getSize()I
-HSPLandroidx/compose/runtime/SlotReader;->getTable$runtime_release()Landroidx/compose/runtime/SlotTable;
-HSPLandroidx/compose/runtime/SlotReader;->groupAux(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->groupGet(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->groupGet(II)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->groupKey(I)I
-HSPLandroidx/compose/runtime/SlotReader;->groupObjectKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->groupSize(I)I
-HSPLandroidx/compose/runtime/SlotReader;->hasMark(I)Z
-HSPLandroidx/compose/runtime/SlotReader;->hasObjectKey(I)Z
-HSPLandroidx/compose/runtime/SlotReader;->isGroupEnd()Z
-HSPLandroidx/compose/runtime/SlotReader;->isNode()Z
-HSPLandroidx/compose/runtime/SlotReader;->isNode(I)Z
-HSPLandroidx/compose/runtime/SlotReader;->next()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->node(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->node([II)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->nodeCount(I)I
-HSPLandroidx/compose/runtime/SlotReader;->objectKey([II)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotReader;->parent(I)I
-HSPLandroidx/compose/runtime/SlotReader;->reposition(I)V
-HSPLandroidx/compose/runtime/SlotReader;->restoreParent(I)V
-HSPLandroidx/compose/runtime/SlotReader;->skipGroup()I
-HSPLandroidx/compose/runtime/SlotReader;->skipToGroupEnd()V
-HSPLandroidx/compose/runtime/SlotReader;->startGroup()V
-HSPLandroidx/compose/runtime/SlotReader;->startNode()V
-HSPLandroidx/compose/runtime/SlotTable;-><init>()V
-HSPLandroidx/compose/runtime/SlotTable;->anchorIndex(Landroidx/compose/runtime/Anchor;)I
-HSPLandroidx/compose/runtime/SlotTable;->close$runtime_release(Landroidx/compose/runtime/SlotReader;)V
-HSPLandroidx/compose/runtime/SlotTable;->close$runtime_release(Landroidx/compose/runtime/SlotWriter;[II[Ljava/lang/Object;ILjava/util/ArrayList;)V
-HSPLandroidx/compose/runtime/SlotTable;->containsMark()Z
-HSPLandroidx/compose/runtime/SlotTable;->getAnchors$runtime_release()Ljava/util/ArrayList;
-HSPLandroidx/compose/runtime/SlotTable;->getGroups()[I
-HSPLandroidx/compose/runtime/SlotTable;->getGroupsSize()I
-HSPLandroidx/compose/runtime/SlotTable;->getSlots()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotTable;->getSlotsSize()I
-HSPLandroidx/compose/runtime/SlotTable;->isEmpty()Z
-HSPLandroidx/compose/runtime/SlotTable;->openReader()Landroidx/compose/runtime/SlotReader;
-HSPLandroidx/compose/runtime/SlotTable;->openWriter()Landroidx/compose/runtime/SlotWriter;
-HSPLandroidx/compose/runtime/SlotTable;->ownsAnchor(Landroidx/compose/runtime/Anchor;)Z
-HSPLandroidx/compose/runtime/SlotTable;->setTo$runtime_release([II[Ljava/lang/Object;ILjava/util/ArrayList;)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$auxIndex([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$containsAnyMark([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->access$containsMark([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->access$countOneBits(I)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$dataAnchor([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$groupInfo([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$groupSize([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$hasAux([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->access$hasMark([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->access$hasObjectKey([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->access$initGroup([IIIZZZII)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$isNode([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->access$key([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$locationOf(Ljava/util/ArrayList;II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$nodeCount([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$nodeIndex([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$objectKeyIndex([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$parentAnchor([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$search(Ljava/util/ArrayList;II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$slotAnchor([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->access$updateContainsMark([IIZ)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$updateDataAnchor([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$updateGroupSize([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$updateMark([IIZ)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$updateNodeCount([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->access$updateParentAnchor([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->auxIndex([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->containsAnyMark([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->containsMark([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->countOneBits(I)I
-HSPLandroidx/compose/runtime/SlotTableKt;->dataAnchor([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->groupInfo([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->groupSize([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->hasAux([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->hasMark([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->hasObjectKey([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->initGroup([IIIZZZII)V
-HSPLandroidx/compose/runtime/SlotTableKt;->isNode([II)Z
-HSPLandroidx/compose/runtime/SlotTableKt;->key([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->locationOf(Ljava/util/ArrayList;II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->nodeCount([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->nodeIndex([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->objectKeyIndex([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->parentAnchor([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->search(Ljava/util/ArrayList;II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->slotAnchor([II)I
-HSPLandroidx/compose/runtime/SlotTableKt;->updateContainsMark([IIZ)V
-HSPLandroidx/compose/runtime/SlotTableKt;->updateDataAnchor([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->updateGroupSize([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->updateMark([IIZ)V
-HSPLandroidx/compose/runtime/SlotTableKt;->updateNodeCount([III)V
-HSPLandroidx/compose/runtime/SlotTableKt;->updateParentAnchor([III)V
-HSPLandroidx/compose/runtime/SlotWriter$Companion;-><init>()V
-HSPLandroidx/compose/runtime/SlotWriter$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/SlotWriter$Companion;->access$moveGroup(Landroidx/compose/runtime/SlotWriter$Companion;Landroidx/compose/runtime/SlotWriter;ILandroidx/compose/runtime/SlotWriter;ZZ)Ljava/util/List;
-HSPLandroidx/compose/runtime/SlotWriter$Companion;->moveGroup(Landroidx/compose/runtime/SlotWriter;ILandroidx/compose/runtime/SlotWriter;ZZ)Ljava/util/List;
-HSPLandroidx/compose/runtime/SlotWriter$groupSlots$1;-><init>(IILandroidx/compose/runtime/SlotWriter;)V
-HSPLandroidx/compose/runtime/SlotWriter$groupSlots$1;->hasNext()Z
-HSPLandroidx/compose/runtime/SlotWriter$groupSlots$1;->next()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;-><clinit>()V
-HSPLandroidx/compose/runtime/SlotWriter;-><init>(Landroidx/compose/runtime/SlotTable;)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$containsAnyGroupMarks(Landroidx/compose/runtime/SlotWriter;I)Z
-HSPLandroidx/compose/runtime/SlotWriter;->access$dataIndex(Landroidx/compose/runtime/SlotWriter;I)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$dataIndex(Landroidx/compose/runtime/SlotWriter;[II)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$dataIndexToDataAddress(Landroidx/compose/runtime/SlotWriter;I)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$dataIndexToDataAnchor(Landroidx/compose/runtime/SlotWriter;IIII)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getAnchors$p(Landroidx/compose/runtime/SlotWriter;)Ljava/util/ArrayList;
-HSPLandroidx/compose/runtime/SlotWriter;->access$getCurrentSlot$p(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getGroupGapStart$p(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getGroups$p(Landroidx/compose/runtime/SlotWriter;)[I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getNodeCount$p(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getSlots$p(Landroidx/compose/runtime/SlotWriter;)[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->access$getSlotsGapLen$p(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getSlotsGapOwner$p(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$getSlotsGapStart$p(Landroidx/compose/runtime/SlotWriter;)I
-HSPLandroidx/compose/runtime/SlotWriter;->access$insertGroups(Landroidx/compose/runtime/SlotWriter;I)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$insertSlots(Landroidx/compose/runtime/SlotWriter;II)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$setCurrentGroup$p(Landroidx/compose/runtime/SlotWriter;I)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$setCurrentSlot$p(Landroidx/compose/runtime/SlotWriter;I)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$setNodeCount$p(Landroidx/compose/runtime/SlotWriter;I)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$setSlotsGapOwner$p(Landroidx/compose/runtime/SlotWriter;I)V
-HSPLandroidx/compose/runtime/SlotWriter;->access$updateContainsMark(Landroidx/compose/runtime/SlotWriter;I)V
-HSPLandroidx/compose/runtime/SlotWriter;->advanceBy(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->anchor(I)Landroidx/compose/runtime/Anchor;
-HSPLandroidx/compose/runtime/SlotWriter;->anchorIndex(Landroidx/compose/runtime/Anchor;)I
-HSPLandroidx/compose/runtime/SlotWriter;->auxIndex([II)I
-HSPLandroidx/compose/runtime/SlotWriter;->beginInsert()V
-HSPLandroidx/compose/runtime/SlotWriter;->childContainsAnyMarks(I)Z
-HSPLandroidx/compose/runtime/SlotWriter;->close()V
-HSPLandroidx/compose/runtime/SlotWriter;->containsAnyGroupMarks(I)Z
-HSPLandroidx/compose/runtime/SlotWriter;->containsGroupMark(I)Z
-HSPLandroidx/compose/runtime/SlotWriter;->dataAnchorToDataIndex(III)I
-HSPLandroidx/compose/runtime/SlotWriter;->dataIndex(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->dataIndex([II)I
-HSPLandroidx/compose/runtime/SlotWriter;->dataIndexToDataAddress(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->dataIndexToDataAnchor(IIII)I
-HSPLandroidx/compose/runtime/SlotWriter;->endGroup()I
-HSPLandroidx/compose/runtime/SlotWriter;->endInsert()V
-HSPLandroidx/compose/runtime/SlotWriter;->ensureStarted(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->ensureStarted(Landroidx/compose/runtime/Anchor;)V
-HSPLandroidx/compose/runtime/SlotWriter;->fixParentAnchorsFor(III)V
-HSPLandroidx/compose/runtime/SlotWriter;->getCapacity()I
-HSPLandroidx/compose/runtime/SlotWriter;->getClosed()Z
-HSPLandroidx/compose/runtime/SlotWriter;->getCurrentGroup()I
-HSPLandroidx/compose/runtime/SlotWriter;->getParent()I
-HSPLandroidx/compose/runtime/SlotWriter;->getSize$runtime_release()I
-HSPLandroidx/compose/runtime/SlotWriter;->getTable$runtime_release()Landroidx/compose/runtime/SlotTable;
-HSPLandroidx/compose/runtime/SlotWriter;->groupAux(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->groupIndexToAddress(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->groupKey(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->groupObjectKey(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->groupSize(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->groupSlots()Ljava/util/Iterator;
-HSPLandroidx/compose/runtime/SlotWriter;->insertGroups(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->insertSlots(II)V
-HSPLandroidx/compose/runtime/SlotWriter;->markGroup$default(Landroidx/compose/runtime/SlotWriter;IILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->markGroup(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->moveAnchors(III)V
-HSPLandroidx/compose/runtime/SlotWriter;->moveFrom(Landroidx/compose/runtime/SlotTable;I)Ljava/util/List;
-HSPLandroidx/compose/runtime/SlotWriter;->moveGroup(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->moveGroupGapTo(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->moveSlotGapTo(II)V
-HSPLandroidx/compose/runtime/SlotWriter;->node(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->node(Landroidx/compose/runtime/Anchor;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->nodeIndex([II)I
-HSPLandroidx/compose/runtime/SlotWriter;->parent(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->parent([II)I
-HSPLandroidx/compose/runtime/SlotWriter;->parentAnchorToIndex(I)I
-HSPLandroidx/compose/runtime/SlotWriter;->parentIndexToAnchor(II)I
-HSPLandroidx/compose/runtime/SlotWriter;->recalculateMarks()V
-HSPLandroidx/compose/runtime/SlotWriter;->removeAnchors(II)Z
-HSPLandroidx/compose/runtime/SlotWriter;->removeGroup()Z
-HSPLandroidx/compose/runtime/SlotWriter;->removeGroups(II)Z
-HSPLandroidx/compose/runtime/SlotWriter;->removeSlots(III)V
-HSPLandroidx/compose/runtime/SlotWriter;->restoreCurrentGroupEnd()I
-HSPLandroidx/compose/runtime/SlotWriter;->saveCurrentGroupEnd()V
-HSPLandroidx/compose/runtime/SlotWriter;->set(ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->set(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->skip()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->skipGroup()I
-HSPLandroidx/compose/runtime/SlotWriter;->skipToGroupEnd()V
-HSPLandroidx/compose/runtime/SlotWriter;->slotIndex([II)I
-HSPLandroidx/compose/runtime/SlotWriter;->startData(ILjava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->startGroup()V
-HSPLandroidx/compose/runtime/SlotWriter;->startGroup(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->startGroup(ILjava/lang/Object;ZLjava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->startNode(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->update(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SlotWriter;->updateAnchors(II)V
-HSPLandroidx/compose/runtime/SlotWriter;->updateAux(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->updateContainsMark(I)V
-HSPLandroidx/compose/runtime/SlotWriter;->updateContainsMarkNow(ILandroidx/compose/runtime/PrioritySet;)V
-HSPLandroidx/compose/runtime/SlotWriter;->updateDataIndex([III)V
-HSPLandroidx/compose/runtime/SlotWriter;->updateNode(Landroidx/compose/runtime/Anchor;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SlotWriter;->updateNodeOfGroup(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl$StateStateRecord;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl$StateStateRecord;->assign(Landroidx/compose/runtime/snapshots/StateRecord;)V
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl$StateStateRecord;->create()Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl$StateStateRecord;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl$StateStateRecord;->setValue(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl;-><init>(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;)V
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl;->getFirstStateRecord()Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl;->getPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl;->prependStateRecord(Landroidx/compose/runtime/snapshots/StateRecord;)V
-HSPLandroidx/compose/runtime/SnapshotMutableStateImpl;->setValue(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt;->derivedStateOf(Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->mutableStateListOf()Landroidx/compose/runtime/snapshots/SnapshotStateList;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->mutableStateOf(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;)Landroidx/compose/runtime/MutableState;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->neverEqualPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->observeDerivedStateRecalculations(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt;->referentialEqualityPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->rememberUpdatedState(Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->snapshotFlow(Lkotlin/jvm/functions/Function0;)Lkotlinx/coroutines/flow/Flow;
-HSPLandroidx/compose/runtime/SnapshotStateKt;->structuralEqualityPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotStateKt__DerivedStateKt;-><clinit>()V
-HSPLandroidx/compose/runtime/SnapshotStateKt__DerivedStateKt;->access$getCalculationBlockNestedLevel$p()Landroidx/compose/runtime/SnapshotThreadLocal;
-HSPLandroidx/compose/runtime/SnapshotStateKt__DerivedStateKt;->access$getDerivedStateObservers$p()Landroidx/compose/runtime/SnapshotThreadLocal;
-HSPLandroidx/compose/runtime/SnapshotStateKt__DerivedStateKt;->derivedStateOf(Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/runtime/SnapshotStateKt__DerivedStateKt;->observeDerivedStateRecalculations(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$readObserver$1;-><init>(Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$readObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$readObserver$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$unregisterApplyObserver$1;-><init>(Lkotlinx/coroutines/channels/Channel;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$unregisterApplyObserver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$unregisterApplyObserver$1;->invoke(Ljava/util/Set;Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt;->access$intersects(Ljava/util/Set;Ljava/util/Set;)Z
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt;->intersects$SnapshotStateKt__SnapshotFlowKt(Ljava/util/Set;Ljava/util/Set;)Z
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt;->snapshotFlow(Lkotlin/jvm/functions/Function0;)Lkotlinx/coroutines/flow/Flow;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotMutationPolicyKt;->neverEqualPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotMutationPolicyKt;->referentialEqualityPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotMutationPolicyKt;->structuralEqualityPolicy()Landroidx/compose/runtime/SnapshotMutationPolicy;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotStateKt;->mutableStateListOf()Landroidx/compose/runtime/snapshots/SnapshotStateList;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotStateKt;->mutableStateOf(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;)Landroidx/compose/runtime/MutableState;
-HSPLandroidx/compose/runtime/SnapshotStateKt__SnapshotStateKt;->rememberUpdatedState(Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/runtime/SnapshotThreadLocal;-><init>()V
-HSPLandroidx/compose/runtime/SnapshotThreadLocal;->get()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/SnapshotThreadLocal;->set(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/Stack;-><init>()V
-HSPLandroidx/compose/runtime/Stack;->clear()V
-HSPLandroidx/compose/runtime/Stack;->getSize()I
-HSPLandroidx/compose/runtime/Stack;->isEmpty()Z
-HSPLandroidx/compose/runtime/Stack;->isNotEmpty()Z
-HSPLandroidx/compose/runtime/Stack;->peek()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Stack;->peek(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Stack;->pop()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Stack;->push(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/Stack;->toArray()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/StaticProvidableCompositionLocal;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/StaticProvidableCompositionLocal;->provided$runtime_release(Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/runtime/StaticValueHolder;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/StaticValueHolder;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/StaticValueHolder;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/StructuralEqualityPolicy;-><clinit>()V
-HSPLandroidx/compose/runtime/StructuralEqualityPolicy;-><init>()V
-HSPLandroidx/compose/runtime/StructuralEqualityPolicy;->equivalent(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/Trace;-><clinit>()V
-HSPLandroidx/compose/runtime/Trace;-><init>()V
-HSPLandroidx/compose/runtime/Trace;->beginSection(Ljava/lang/String;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/Trace;->endSection(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/Updater;->constructor-impl(Landroidx/compose/runtime/Composer;)Landroidx/compose/runtime/Composer;
-HSPLandroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;-><init>()V
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;->add(Ljava/lang/Object;I)I
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;->find(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;->getKeys()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;->getSize()I
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;->getValues()[I
-HSPLandroidx/compose/runtime/collection/IdentityArrayIntMap;->setSize(I)V
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;-><init>(I)V
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->clear()V
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->contains(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->find(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->getKeys$runtime_release()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->getSize$runtime_release()I
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->getValues$runtime_release()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->isNotEmpty()Z
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->set(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/collection/IdentityArrayMap;->setSize$runtime_release(I)V
-HSPLandroidx/compose/runtime/collection/IdentityArraySet$iterator$1;-><init>(Landroidx/compose/runtime/collection/IdentityArraySet;)V
-HSPLandroidx/compose/runtime/collection/IdentityArraySet$iterator$1;->hasNext()Z
-HSPLandroidx/compose/runtime/collection/IdentityArraySet$iterator$1;->next()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;-><init>()V
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->add(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->checkIndexBounds(I)V
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->clear()V
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->contains(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->find(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->get(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->getSize()I
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->getValues()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->isEmpty()Z
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->isNotEmpty()Z
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->iterator()Ljava/util/Iterator;
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->remove(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->setSize(I)V
-HSPLandroidx/compose/runtime/collection/IdentityArraySet;->size()I
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;-><init>()V
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->access$find(Landroidx/compose/runtime/collection/IdentityScopeMap;Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->access$scopeSetAt(Landroidx/compose/runtime/collection/IdentityScopeMap;I)Landroidx/compose/runtime/collection/IdentityArraySet;
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->add(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->clear()V
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->contains(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->find(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->getOrCreateIdentitySet(Ljava/lang/Object;)Landroidx/compose/runtime/collection/IdentityArraySet;
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->getScopeSets()[Landroidx/compose/runtime/collection/IdentityArraySet;
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->getSize()I
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->getValueOrder()[I
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->getValues()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->remove(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->removeScope(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->scopeSetAt(I)Landroidx/compose/runtime/collection/IdentityArraySet;
-HSPLandroidx/compose/runtime/collection/IdentityScopeMap;->setSize(I)V
-HSPLandroidx/compose/runtime/collection/IntMap;-><init>(I)V
-HSPLandroidx/compose/runtime/collection/IntMap;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/collection/IntMap;-><init>(Landroid/util/SparseArray;)V
-HSPLandroidx/compose/runtime/collection/IntMap;->clear()V
-HSPLandroidx/compose/runtime/collection/IntMap;->get(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/IntMap;->set(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;-><init>(Landroidx/compose/runtime/collection/MutableVector;)V
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;->get(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;->getSize()I
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;->indexOf(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;->isEmpty()Z
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;->iterator()Ljava/util/Iterator;
-HSPLandroidx/compose/runtime/collection/MutableVector$MutableVectorList;->size()I
-HSPLandroidx/compose/runtime/collection/MutableVector$VectorListIterator;-><init>(Ljava/util/List;I)V
-HSPLandroidx/compose/runtime/collection/MutableVector$VectorListIterator;->hasNext()Z
-HSPLandroidx/compose/runtime/collection/MutableVector$VectorListIterator;->next()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/MutableVector;-><clinit>()V
-HSPLandroidx/compose/runtime/collection/MutableVector;-><init>([Ljava/lang/Object;I)V
-HSPLandroidx/compose/runtime/collection/MutableVector;->add(ILjava/lang/Object;)V
-HSPLandroidx/compose/runtime/collection/MutableVector;->add(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/MutableVector;->addAll(ILandroidx/compose/runtime/collection/MutableVector;)Z
-HSPLandroidx/compose/runtime/collection/MutableVector;->asMutableList()Ljava/util/List;
-HSPLandroidx/compose/runtime/collection/MutableVector;->clear()V
-HSPLandroidx/compose/runtime/collection/MutableVector;->contains(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/MutableVector;->ensureCapacity(I)V
-HSPLandroidx/compose/runtime/collection/MutableVector;->getContent()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/MutableVector;->getSize()I
-HSPLandroidx/compose/runtime/collection/MutableVector;->indexOf(Ljava/lang/Object;)I
-HSPLandroidx/compose/runtime/collection/MutableVector;->isEmpty()Z
-HSPLandroidx/compose/runtime/collection/MutableVector;->isNotEmpty()Z
-HSPLandroidx/compose/runtime/collection/MutableVector;->remove(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/collection/MutableVector;->removeAt(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/MutableVector;->removeRange(II)V
-HSPLandroidx/compose/runtime/collection/MutableVector;->set(ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/collection/MutableVector;->sortWith(Ljava/util/Comparator;)V
-HSPLandroidx/compose/runtime/collection/MutableVectorKt;->access$checkIndex(Ljava/util/List;I)V
-HSPLandroidx/compose/runtime/collection/MutableVectorKt;->checkIndex(Ljava/util/List;I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;->persistentHashMapOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;->persistentListOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;->persistentSetOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/AbstractPersistentList;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;->getEMPTY()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;-><clinit>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;-><init>([Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->getSize()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/UtilsKt;->persistentVectorOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;->getKey()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;->emptyOf$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;-><clinit>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->builder()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap$Builder;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->builder()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->containsKey(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->createEntries()Landroidx/compose/runtime/external/kotlinx/collections/immutable/ImmutableSet;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->getEntries()Ljava/util/Set;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->getNode$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->getSize()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->remove(Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;[Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->checkHasNext()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->ensureNextEntryIsReady()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->hasNext()Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->moveToNextNodeWithData(I)I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->next()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->build()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->build()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->getModCount$runtime_release()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->getOwnership$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->getSize()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->putAll(Ljava/util/Map;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->setModCount$runtime_release(I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->setOperationResult$runtime_release(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->setSize(I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;->getSize()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;->iterator()Ljava/util/Iterator;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntriesIterator;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;->getEMPTY$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;->getNode()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;->getSizeDelta()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;-><clinit>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;-><init>(II[Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;-><init>(II[Ljava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->asInsertResult()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->bufferMoveEntryToNode(IIILjava/lang/Object;Ljava/lang/Object;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->containsKey(ILjava/lang/Object;I)Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->elementsIdentityEquals(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;)Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->entryCount$runtime_release()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->entryKeyIndex$runtime_release(I)I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->get(ILjava/lang/Object;I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->getBuffer$runtime_release()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->hasEntryAt$runtime_release(I)Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->hasNodeAt(I)Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->insertEntryAt(ILjava/lang/Object;Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->keyAtIndex(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->makeNode(ILjava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutableInsertEntryAt(ILjava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutableMoveEntryToNode(IIILjava/lang/Object;Ljava/lang/Object;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutablePut(ILjava/lang/Object;Ljava/lang/Object;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutablePutAll(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutablePutAllFromOtherNodeCell(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;IILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutableUpdateValueAtIndex(ILjava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->nodeAtIndex$runtime_release(I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->nodeIndex$runtime_release(I)I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->put(ILjava/lang/Object;Ljava/lang/Object;I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->remove(ILjava/lang/Object;I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->removeEntryAtIndex(II)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->valueAtKeyIndex(I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->currentNode()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->getBuffer()[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->getIndex()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->hasNextKey()Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->hasNextNode()Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->moveToNextNode()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->reset([Ljava/lang/Object;I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->reset([Ljava/lang/Object;II)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->setIndex(I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;->next()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;->next()Ljava/util/Map$Entry;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->access$insertEntryAtIndex([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->access$replaceEntryWithNode([Ljava/lang/Object;IILandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;)[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->indexSegment(II)I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->insertEntryAtIndex([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->replaceEntryWithNode([Ljava/lang/Object;IILandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;)[Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;->getHasNext()Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;->getHasPrevious()Z
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;->getNext()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;->getPrevious()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;->emptyOf$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;-><clinit>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;-><init>(Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->add(Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->getSize()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->remove(Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/CommonFunctionsKt;->assert(Z)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;-><init>(I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;->getCount()I
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;->setCount(I)V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/EndOfChain;-><clinit>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/EndOfChain;-><init>()V
-HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;-><init>()V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl$invoke$1;-><init>(Landroidx/compose/runtime/internal/ComposableLambdaImpl;Ljava/lang/Object;I)V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl$invoke$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl$invoke$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl$invoke$2;-><init>(Landroidx/compose/runtime/internal/ComposableLambdaImpl;Ljava/lang/Object;Ljava/lang/Object;I)V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;-><init>(IZ)V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->invoke(Landroidx/compose/runtime/Composer;I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->invoke(Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->invoke(Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->trackRead(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->trackWrite()V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl;->update(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->bitsForSlot(II)I
-HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->composableLambda(Landroidx/compose/runtime/Composer;IZLjava/lang/Object;)Landroidx/compose/runtime/internal/ComposableLambda;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->composableLambdaInstance(IZLjava/lang/Object;)Landroidx/compose/runtime/internal/ComposableLambda;
-HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->differentBits(I)I
-HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->replacableWith(Landroidx/compose/runtime/RecomposeScope;Landroidx/compose/runtime/RecomposeScope;)Z
-HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->sameBits(I)I
-HSPLandroidx/compose/runtime/internal/ThreadMap;-><init>(I[J[Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/internal/ThreadMap;->find(J)I
-HSPLandroidx/compose/runtime/internal/ThreadMap;->get(J)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/internal/ThreadMap;->newWith(JLjava/lang/Object;)Landroidx/compose/runtime/internal/ThreadMap;
-HSPLandroidx/compose/runtime/internal/ThreadMap;->trySet(JLjava/lang/Object;)Z
-HSPLandroidx/compose/runtime/internal/ThreadMapKt;-><clinit>()V
-HSPLandroidx/compose/runtime/internal/ThreadMapKt;->getEmptyThreadMap()Landroidx/compose/runtime/internal/ThreadMap;
-HSPLandroidx/compose/runtime/saveable/ListSaverKt$listSaver$1;-><init>(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/saveable/ListSaverKt$listSaver$1;->invoke(Landroidx/compose/runtime/saveable/SaverScope;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/ListSaverKt$listSaver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/ListSaverKt;->listSaver(Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry$Entry;)V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$valueProvider$1$1$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$valueProvider$1$1$1;->canBeSaved(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$valueProvider$1;-><init>(Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$valueProvider$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;Ljava/lang/String;Landroidx/compose/runtime/State;Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt;->access$requireCanBeSaved(Landroidx/compose/runtime/saveable/SaveableStateRegistry;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt;->rememberSaveable([Ljava/lang/Object;Landroidx/compose/runtime/saveable/Saver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;II)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/RememberSaveableKt;->requireCanBeSaved(Landroidx/compose/runtime/saveable/SaveableStateRegistry;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$1;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$1;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$1;->invoke(Landroidx/compose/runtime/saveable/SaverScope;Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$2;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$2;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion;->getSaver()Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder$registry$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder;-><init>(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder;->getRegistry()Landroidx/compose/runtime/saveable/SaveableStateRegistry;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder;->saveTo(Ljava/util/Map;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder;Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;Ljava/lang/Object;Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;-><init>(Ljava/util/Map;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;-><init>(Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->SaveableStateProvider(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->access$getRegistryHolders$p(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->access$getSavedStates$p(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->access$getSaver$cp()Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->access$saveAll(Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->getParentSaveableStateRegistry()Landroidx/compose/runtime/saveable/SaveableStateRegistry;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->saveAll()Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl;->setParentSaveableStateRegistry(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderKt$rememberSaveableStateHolder$1;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderKt$rememberSaveableStateHolder$1;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderKt$rememberSaveableStateHolder$1;->invoke()Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderKt$rememberSaveableStateHolder$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaveableStateHolderKt;->rememberSaveableStateHolder(Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/saveable/SaveableStateHolder;
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl$registerProvider$3;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistryImpl;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl$registerProvider$3;->unregister()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;-><init>(Ljava/util/Map;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;->access$getValueProviders$p(Landroidx/compose/runtime/saveable/SaveableStateRegistryImpl;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;->canBeSaved(Ljava/lang/Object;)Z
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;->consumeRestored(Ljava/lang/String;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;->performSave()Ljava/util/Map;
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;->registerProvider(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/saveable/SaveableStateRegistry$Entry;
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryKt$LocalSaveableStateRegistry$1;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryKt$LocalSaveableStateRegistry$1;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryKt;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryKt;->SaveableStateRegistry(Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/saveable/SaveableStateRegistry;
-HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryKt;->getLocalSaveableStateRegistry()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/runtime/saveable/SaverKt$AutoSaver$1;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaverKt$AutoSaver$1;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaverKt$AutoSaver$1;->invoke(Landroidx/compose/runtime/saveable/SaverScope;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaverKt$AutoSaver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaverKt$AutoSaver$2;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaverKt$AutoSaver$2;-><init>()V
-HSPLandroidx/compose/runtime/saveable/SaverKt$Saver$1;-><init>(Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/saveable/SaverKt$Saver$1;->save(Landroidx/compose/runtime/saveable/SaverScope;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/saveable/SaverKt;-><clinit>()V
-HSPLandroidx/compose/runtime/saveable/SaverKt;->Saver(Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/runtime/saveable/SaverKt;->autoSaver()Landroidx/compose/runtime/saveable/Saver;
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedMutableSnapshot$1;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedMutableSnapshot$1;->invoke(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/MutableSnapshot;
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedMutableSnapshot$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedSnapshot$1;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedSnapshot$1;->invoke(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/ReadonlySnapshot;
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedSnapshot$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot;-><init>(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot;->notifyObjectsInitialized$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot;->takeNestedMutableSnapshot(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/MutableSnapshot;
-HSPLandroidx/compose/runtime/snapshots/GlobalSnapshot;->takeNestedSnapshot(Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/ListUtilsKt;->fastToSet(Ljava/util/List;)Ljava/util/Set;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;-><init>(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->advance$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->apply()Landroidx/compose/runtime/snapshots/SnapshotApplyResult;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->closeLocked$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getApplied$runtime_release()Z
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getModified$runtime_release()Ljava/util/Set;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getPreviousIds$runtime_release()Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getPreviousPinnedSnapshots$runtime_release()[I
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getReadObserver$runtime_release()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getReadOnly()Z
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->getWriteObserver$runtime_release()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->innerApplyLocked$runtime_release(ILjava/util/Map;Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/SnapshotApplyResult;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->nestedActivated$runtime_release(Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->nestedDeactivated$runtime_release(Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->notifyObjectsInitialized$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->recordModified$runtime_release(Landroidx/compose/runtime/snapshots/StateObject;)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->recordPrevious$runtime_release(I)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->recordPreviousList$runtime_release(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->recordPreviousPinnedSnapshot$runtime_release(I)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->recordPreviousPinnedSnapshots$runtime_release([I)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->releasePinnedSnapshotsForCloseLocked$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->releasePreviouslyPinnedSnapshotsLocked$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->setApplied$runtime_release(Z)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->setModified(Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->takeNestedMutableSnapshot(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/MutableSnapshot;
-HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->validateNotAppliedOrPinned$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/NestedMutableSnapshot;-><init>(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/snapshots/MutableSnapshot;)V
-HSPLandroidx/compose/runtime/snapshots/NestedMutableSnapshot;->apply()Landroidx/compose/runtime/snapshots/SnapshotApplyResult;
-HSPLandroidx/compose/runtime/snapshots/NestedMutableSnapshot;->deactivate()V
-HSPLandroidx/compose/runtime/snapshots/NestedMutableSnapshot;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/ReadonlySnapshot;-><init>(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/ReadonlySnapshot;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/ReadonlySnapshot;->getReadObserver$runtime_release()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/ReadonlySnapshot;->nestedDeactivated$runtime_release(Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion$registerApplyObserver$2;-><init>(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion$registerApplyObserver$2;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion$registerGlobalWriteObserver$2;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->createNonObservableSnapshot()Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->getCurrent()Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->notifyObjectsInitialized()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->observe(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->registerApplyObserver(Lkotlin/jvm/functions/Function2;)Landroidx/compose/runtime/snapshots/ObserverHandle;
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->registerGlobalWriteObserver(Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/ObserverHandle;
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->sendApplyNotifications()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->takeMutableSnapshot(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/MutableSnapshot;
-HSPLandroidx/compose/runtime/snapshots/Snapshot$Companion;->takeSnapshot(Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/Snapshot;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;-><init>(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;-><init>(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->closeAndReleasePinning$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->closeLocked$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->getDisposed$runtime_release()Z
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->getId()I
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->getInvalid$runtime_release()Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->makeCurrent()Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->releasePinnedSnapshotLocked$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->releasePinnedSnapshotsForCloseLocked$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->restoreCurrent(Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->setDisposed$runtime_release(Z)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->setId$runtime_release(I)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->setInvalid$runtime_release(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->takeoverPinnedSnapshot$runtime_release()I
-HSPLandroidx/compose/runtime/snapshots/Snapshot;->validateNotDisposed$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotApplyResult$Success;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotApplyResult$Success;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotApplyResult;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotApplyResult;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotApplyResult;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->add(I)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->allocateHandle()I
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->ensure(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->freeHandle(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->lowestOrDefault(I)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->remove(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->shiftDown(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->shiftUp(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;->swap(II)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet$Companion;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet$Companion;->getEMPTY()Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;-><init>(JJI[I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->access$getEMPTY$cp()Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->andNot(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->clear(I)Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->lowest(I)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->or(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet;->set(I)Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSetKt;->access$lowestBitOf(J)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotIdSetKt;->lowestBitOf(J)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$advanceGlobalSnapshot$3;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$advanceGlobalSnapshot$3;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$advanceGlobalSnapshot$3;->invoke(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$advanceGlobalSnapshot$3;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$emptyLambda$1;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$emptyLambda$1;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$emptyLambda$1;->invoke(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$emptyLambda$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$mergedReadObserver$1;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$mergedReadObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$mergedReadObserver$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$mergedWriteObserver$1;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$mergedWriteObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$mergedWriteObserver$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$takeNewSnapshot$1;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$takeNewSnapshot$1;->invoke(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt$takeNewSnapshot$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$advanceGlobalSnapshot()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$advanceGlobalSnapshot(Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getApplyObservers$p()Ljava/util/List;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getCurrentGlobalSnapshot$p()Ljava/util/concurrent/atomic/AtomicReference;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getEmptyLambda$p()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getGlobalWriteObservers$p()Ljava/util/List;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getNextSnapshotId$p()I
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getOpenSnapshots$p()Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$getThreadSnapshot$p()Landroidx/compose/runtime/SnapshotThreadLocal;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$mergedReadObserver(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Z)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$mergedWriteObserver(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$optimisticMerges(Landroidx/compose/runtime/snapshots/MutableSnapshot;Landroidx/compose/runtime/snapshots/MutableSnapshot;Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$overwriteUnusedRecordsLocked(Landroidx/compose/runtime/snapshots/StateObject;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$readable(Landroidx/compose/runtime/snapshots/StateRecord;ILandroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$setNextSnapshotId$p(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$setOpenSnapshots$p(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$takeNewGlobalSnapshot(Landroidx/compose/runtime/snapshots/Snapshot;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$takeNewSnapshot(Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->access$validateOpen(Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->addRange(Landroidx/compose/runtime/snapshots/SnapshotIdSet;II)Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->advanceGlobalSnapshot()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->advanceGlobalSnapshot(Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->createTransparentSnapshotWithNoParentReadObserver$default(Landroidx/compose/runtime/snapshots/Snapshot;Lkotlin/jvm/functions/Function1;ZILjava/lang/Object;)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->createTransparentSnapshotWithNoParentReadObserver(Landroidx/compose/runtime/snapshots/Snapshot;Lkotlin/jvm/functions/Function1;Z)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->current(Landroidx/compose/runtime/snapshots/StateRecord;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->current(Landroidx/compose/runtime/snapshots/StateRecord;Landroidx/compose/runtime/snapshots/Snapshot;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->currentSnapshot()Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->getLock()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->getSnapshotInitializer()Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->mergedReadObserver$default(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZILjava/lang/Object;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->mergedReadObserver(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Z)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->mergedWriteObserver(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->newOverwritableRecordLocked(Landroidx/compose/runtime/snapshots/StateRecord;Landroidx/compose/runtime/snapshots/StateObject;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->newWritableRecord(Landroidx/compose/runtime/snapshots/StateRecord;Landroidx/compose/runtime/snapshots/StateObject;Landroidx/compose/runtime/snapshots/Snapshot;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->newWritableRecordLocked(Landroidx/compose/runtime/snapshots/StateRecord;Landroidx/compose/runtime/snapshots/StateObject;Landroidx/compose/runtime/snapshots/Snapshot;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->notifyWrite(Landroidx/compose/runtime/snapshots/Snapshot;Landroidx/compose/runtime/snapshots/StateObject;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->optimisticMerges(Landroidx/compose/runtime/snapshots/MutableSnapshot;Landroidx/compose/runtime/snapshots/MutableSnapshot;Landroidx/compose/runtime/snapshots/SnapshotIdSet;)Ljava/util/Map;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->overwritableRecord(Landroidx/compose/runtime/snapshots/StateRecord;Landroidx/compose/runtime/snapshots/StateObject;Landroidx/compose/runtime/snapshots/Snapshot;Landroidx/compose/runtime/snapshots/StateRecord;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->overwriteUnusedRecordsLocked(Landroidx/compose/runtime/snapshots/StateObject;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->readable(Landroidx/compose/runtime/snapshots/StateRecord;ILandroidx/compose/runtime/snapshots/SnapshotIdSet;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->readable(Landroidx/compose/runtime/snapshots/StateRecord;Landroidx/compose/runtime/snapshots/StateObject;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->releasePinningLocked(I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->takeNewGlobalSnapshot(Landroidx/compose/runtime/snapshots/Snapshot;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->takeNewSnapshot(Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/Snapshot;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->trackPinning(ILandroidx/compose/runtime/snapshots/SnapshotIdSet;)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->usedLocked(Landroidx/compose/runtime/snapshots/StateObject;)Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->valid(IILandroidx/compose/runtime/snapshots/SnapshotIdSet;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->valid(Landroidx/compose/runtime/snapshots/StateRecord;ILandroidx/compose/runtime/snapshots/SnapshotIdSet;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotKt;->validateOpen(Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList$StateListStateRecord;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList$StateListStateRecord;->getList$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;->getFirstStateRecord()Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;->getReadable$runtime_release()Landroidx/compose/runtime/snapshots/SnapshotStateList$StateListStateRecord;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;->getSize()I
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;->isEmpty()Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateList;->size()I
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateEnterObserver$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateEnterObserver$1;->invoke(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateEnterObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateExitObserver$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateExitObserver$1;->invoke(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateExitObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$clearObsoleteStateReads(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$getCurrentScope$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$getCurrentScopeReads$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)Landroidx/compose/runtime/collection/IdentityArrayIntMap;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$getCurrentToken$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$getDeriveStateScopeCount$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)I
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$getScopeToValues$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;)Landroidx/compose/runtime/collection/IdentityArrayMap;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$setCurrentScope$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$setCurrentScopeReads$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;Landroidx/compose/runtime/collection/IdentityArrayIntMap;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$setCurrentToken$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->access$setDeriveStateScopeCount$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;I)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->clear()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->clearObsoleteStateReads(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->getDerivedStateEnterObserver()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->getDerivedStateExitObserver()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->getOnChanged()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->notifyInvalidatedScopes()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->recordInvalidation(Ljava/util/Set;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->recordRead(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->removeObservation(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;->removeScopeIf(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$applyObserver$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$applyObserver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$applyObserver$1;->invoke(Ljava/util/Set;Landroidx/compose/runtime/snapshots/Snapshot;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$observeReads$1$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$observeReads$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$observeReads$1$1;->invoke()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$readObserver$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$readObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$readObserver$1;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$sendNotifications$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$sendNotifications$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver$sendNotifications$1;->invoke()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$addChanges(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$drainChanges(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$getCurrentMap$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$getObservedScopeMaps$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$getReadObserver$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$getSendingNotifications$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$isPaused$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$sendNotifications(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->access$setSendingNotifications$p(Landroidx/compose/runtime/snapshots/SnapshotStateObserver;Z)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->addChanges(Ljava/util/Set;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->clear()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->clearIf(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->drainChanges()Z
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->ensureMap(Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->observeReads(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->removeChanges()Ljava/util/Set;
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->sendNotifications()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->start()V
-HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver;->stop()V
-HSPLandroidx/compose/runtime/snapshots/StateRecord;-><clinit>()V
-HSPLandroidx/compose/runtime/snapshots/StateRecord;-><init>()V
-HSPLandroidx/compose/runtime/snapshots/StateRecord;->getNext$runtime_release()Landroidx/compose/runtime/snapshots/StateRecord;
-HSPLandroidx/compose/runtime/snapshots/StateRecord;->getSnapshotId$runtime_release()I
-HSPLandroidx/compose/runtime/snapshots/StateRecord;->setNext$runtime_release(Landroidx/compose/runtime/snapshots/StateRecord;)V
-HSPLandroidx/compose/runtime/snapshots/StateRecord;->setSnapshotId$runtime_release(I)V
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;-><init>(Landroidx/compose/runtime/snapshots/MutableSnapshot;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZZ)V
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->apply()Landroidx/compose/runtime/snapshots/SnapshotApplyResult;
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->dispose()V
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->getCurrentSnapshot()Landroidx/compose/runtime/snapshots/MutableSnapshot;
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->getId()I
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->getInvalid$runtime_release()Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->getReadOnly()Z
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->notifyObjectsInitialized$runtime_release()V
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->recordModified$runtime_release(Landroidx/compose/runtime/snapshots/StateObject;)V
-HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->takeNestedMutableSnapshot(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/snapshots/MutableSnapshot;
-HSPLandroidx/compose/runtime/tooling/InspectionTablesKt$LocalInspectionTables$1;-><clinit>()V
-HSPLandroidx/compose/runtime/tooling/InspectionTablesKt$LocalInspectionTables$1;-><init>()V
-HSPLandroidx/compose/runtime/tooling/InspectionTablesKt$LocalInspectionTables$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/runtime/tooling/InspectionTablesKt$LocalInspectionTables$1;->invoke()Ljava/util/Set;
-HSPLandroidx/compose/runtime/tooling/InspectionTablesKt;-><clinit>()V
-HSPLandroidx/compose/runtime/tooling/InspectionTablesKt;->getLocalInspectionTables()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/ActualKt;->areObjectsOfSameType(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/Alignment$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/Alignment$Companion;-><init>()V
-HSPLandroidx/compose/ui/Alignment$Companion;->getBottomCenter()Landroidx/compose/ui/Alignment;
-HSPLandroidx/compose/ui/Alignment$Companion;->getCenter()Landroidx/compose/ui/Alignment;
-HSPLandroidx/compose/ui/Alignment$Companion;->getCenterHorizontally()Landroidx/compose/ui/Alignment$Horizontal;
-HSPLandroidx/compose/ui/Alignment$Companion;->getCenterVertically()Landroidx/compose/ui/Alignment$Vertical;
-HSPLandroidx/compose/ui/Alignment$Companion;->getStart()Landroidx/compose/ui/Alignment$Horizontal;
-HSPLandroidx/compose/ui/Alignment$Companion;->getTop()Landroidx/compose/ui/Alignment$Vertical;
-HSPLandroidx/compose/ui/Alignment$Companion;->getTopCenter()Landroidx/compose/ui/Alignment;
-HSPLandroidx/compose/ui/Alignment$Companion;->getTopStart()Landroidx/compose/ui/Alignment;
-HSPLandroidx/compose/ui/Alignment;-><clinit>()V
-HSPLandroidx/compose/ui/BiasAlignment$Horizontal;-><clinit>()V
-HSPLandroidx/compose/ui/BiasAlignment$Horizontal;-><init>(F)V
-HSPLandroidx/compose/ui/BiasAlignment$Horizontal;->align(IILandroidx/compose/ui/unit/LayoutDirection;)I
-HSPLandroidx/compose/ui/BiasAlignment$Horizontal;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/BiasAlignment$Vertical;-><clinit>()V
-HSPLandroidx/compose/ui/BiasAlignment$Vertical;-><init>(F)V
-HSPLandroidx/compose/ui/BiasAlignment$Vertical;->align(II)I
-HSPLandroidx/compose/ui/BiasAlignment$Vertical;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/BiasAlignment;-><clinit>()V
-HSPLandroidx/compose/ui/BiasAlignment;-><init>(FF)V
-HSPLandroidx/compose/ui/BiasAlignment;->align-KFBX0sM(JJLandroidx/compose/ui/unit/LayoutDirection;)J
-HSPLandroidx/compose/ui/BiasAlignment;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/CombinedModifier;-><clinit>()V
-HSPLandroidx/compose/ui/CombinedModifier;-><init>(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier;)V
-HSPLandroidx/compose/ui/CombinedModifier;->all(Lkotlin/jvm/functions/Function1;)Z
-HSPLandroidx/compose/ui/CombinedModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/CombinedModifier;->foldIn(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/CombinedModifier;->getInner$ui_release()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/CombinedModifier;->getOuter$ui_release()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/ComposedModifier;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/ui/ComposedModifier;->getFactory()Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$1;-><clinit>()V
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$1;-><init>()V
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$1;->invoke(Landroidx/compose/ui/Modifier$Element;)Ljava/lang/Boolean;
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$result$1;-><init>(Landroidx/compose/runtime/Composer;)V
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$result$1;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/Modifier$Element;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/ComposedModifierKt$materialize$result$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/ComposedModifierKt;->composed$default(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/ComposedModifierKt;->composed(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/ComposedModifierKt;->materialize(Landroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/Modifier$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/Modifier$Companion;-><init>()V
-HSPLandroidx/compose/ui/Modifier$Companion;->all(Lkotlin/jvm/functions/Function1;)Z
-HSPLandroidx/compose/ui/Modifier$Companion;->then(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/Modifier$Element;->all(Lkotlin/jvm/functions/Function1;)Z
-HSPLandroidx/compose/ui/Modifier$Element;->foldIn(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/Modifier$Node;-><clinit>()V
-HSPLandroidx/compose/ui/Modifier$Node;-><init>()V
-HSPLandroidx/compose/ui/Modifier$Node;->attach$ui_release()V
-HSPLandroidx/compose/ui/Modifier$Node;->detach$ui_release()V
-HSPLandroidx/compose/ui/Modifier$Node;->getAggregateChildKindSet$ui_release()I
-HSPLandroidx/compose/ui/Modifier$Node;->getChild$ui_release()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/Modifier$Node;->getCoordinator$ui_release()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/Modifier$Node;->getKindSet$ui_release()I
-HSPLandroidx/compose/ui/Modifier$Node;->getNode()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/Modifier$Node;->getParent$ui_release()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/Modifier$Node;->isAttached()Z
-HSPLandroidx/compose/ui/Modifier$Node;->onAttach()V
-HSPLandroidx/compose/ui/Modifier$Node;->onDetach()V
-HSPLandroidx/compose/ui/Modifier$Node;->setAggregateChildKindSet$ui_release(I)V
-HSPLandroidx/compose/ui/Modifier$Node;->setChild$ui_release(Landroidx/compose/ui/Modifier$Node;)V
-HSPLandroidx/compose/ui/Modifier$Node;->setKindSet$ui_release(I)V
-HSPLandroidx/compose/ui/Modifier$Node;->setParent$ui_release(Landroidx/compose/ui/Modifier$Node;)V
-HSPLandroidx/compose/ui/Modifier$Node;->updateCoordinator$ui_release(Landroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/Modifier;-><clinit>()V
-HSPLandroidx/compose/ui/Modifier;->then(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/MotionDurationScale$DefaultImpls;->fold(Landroidx/compose/ui/MotionDurationScale;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/MotionDurationScale$DefaultImpls;->get(Landroidx/compose/ui/MotionDurationScale;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLandroidx/compose/ui/MotionDurationScale$DefaultImpls;->minusKey(Landroidx/compose/ui/MotionDurationScale;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/MotionDurationScale$Key;-><clinit>()V
-HSPLandroidx/compose/ui/MotionDurationScale$Key;-><init>()V
-HSPLandroidx/compose/ui/MotionDurationScale;-><clinit>()V
-HSPLandroidx/compose/ui/MotionDurationScale;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
-HSPLandroidx/compose/ui/autofill/AndroidAutofill;-><init>(Landroid/view/View;Landroidx/compose/ui/autofill/AutofillTree;)V
-HSPLandroidx/compose/ui/autofill/AndroidAutofill;->getAutofillManager()Landroid/view/autofill/AutofillManager;
-HSPLandroidx/compose/ui/autofill/AutofillCallback;-><clinit>()V
-HSPLandroidx/compose/ui/autofill/AutofillCallback;-><init>()V
-HSPLandroidx/compose/ui/autofill/AutofillCallback;->register(Landroidx/compose/ui/autofill/AndroidAutofill;)V
-HSPLandroidx/compose/ui/autofill/AutofillCallback;->unregister(Landroidx/compose/ui/autofill/AndroidAutofill;)V
-HSPLandroidx/compose/ui/autofill/AutofillTree;-><clinit>()V
-HSPLandroidx/compose/ui/autofill/AutofillTree;-><init>()V
-HSPLandroidx/compose/ui/draw/ClipKt;->clip(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/draw/ClipKt;->clipToBounds(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/draw/DrawBackgroundModifier;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/draw/DrawBackgroundModifier;->draw(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/ui/draw/DrawModifierKt$drawBehind$$inlined$modifierElementOf$1;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/draw/DrawModifierKt$drawBehind$$inlined$modifierElementOf$1;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/draw/DrawModifierKt;->drawBehind(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/draw/PainterModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/ui/draw/PainterModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/ui/draw/PainterModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/draw/PainterModifier;-><init>(Landroidx/compose/ui/graphics/painter/Painter;ZLandroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;FLandroidx/compose/ui/graphics/ColorFilter;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/draw/PainterModifier;->calculateScaledSize-E7KxVPU(J)J
-HSPLandroidx/compose/ui/draw/PainterModifier;->draw(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/ui/draw/PainterModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/draw/PainterModifier;->getUseIntrinsicSize()Z
-HSPLandroidx/compose/ui/draw/PainterModifier;->hasSpecifiedAndFiniteHeight-uvyYCjk(J)Z
-HSPLandroidx/compose/ui/draw/PainterModifier;->hasSpecifiedAndFiniteWidth-uvyYCjk(J)Z
-HSPLandroidx/compose/ui/draw/PainterModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/draw/PainterModifier;->modifyConstraints-ZezNO4M(J)J
-HSPLandroidx/compose/ui/draw/PainterModifierKt;->paint$default(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/painter/Painter;ZLandroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;FLandroidx/compose/ui/graphics/ColorFilter;ILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/draw/PainterModifierKt;->paint(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/painter/Painter;ZLandroidx/compose/ui/Alignment;Landroidx/compose/ui/layout/ContentScale;FLandroidx/compose/ui/graphics/ColorFilter;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/draw/ShadowKt$shadow$2$1;-><init>(FLandroidx/compose/ui/graphics/Shape;ZJJ)V
-HSPLandroidx/compose/ui/draw/ShadowKt$shadow$2$1;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)V
-HSPLandroidx/compose/ui/draw/ShadowKt$shadow$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/draw/ShadowKt;->shadow-s4CzXII$default(Landroidx/compose/ui/Modifier;FLandroidx/compose/ui/graphics/Shape;ZJJILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/draw/ShadowKt;->shadow-s4CzXII(Landroidx/compose/ui/Modifier;FLandroidx/compose/ui/graphics/Shape;ZJJ)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusChangedModifierKt$onFocusChanged$$inlined$modifierElementOf$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusChangedModifierKt$onFocusChanged$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusChangedModifierKt$onFocusChanged$$inlined$modifierElementOf$2;->update(Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusChangedModifierKt;->onFocusChanged(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusChangedModifierNode;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusChangedModifierNode;->onFocusEvent(Landroidx/compose/ui/focus/FocusState;)V
-HSPLandroidx/compose/ui/focus/FocusChangedModifierNode;->setOnFocusChanged(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusEventModifierNodeKt$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/focus/FocusEventModifierNodeKt;->getFocusState(Landroidx/compose/ui/focus/FocusEventModifierNode;)Landroidx/compose/ui/focus/FocusState;
-HSPLandroidx/compose/ui/focus/FocusEventModifierNodeKt;->refreshFocusEventNodes(Landroidx/compose/ui/focus/FocusTargetModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager$invalidateNodes$1;-><init>(Landroidx/compose/ui/focus/FocusInvalidationManager;)V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager$invalidateNodes$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager$invalidateNodes$1;->invoke()V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->access$getFocusEventNodes$p(Landroidx/compose/ui/focus/FocusInvalidationManager;)Ljava/util/Set;
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->access$getFocusPropertiesNodes$p(Landroidx/compose/ui/focus/FocusInvalidationManager;)Ljava/util/Set;
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->access$getFocusTargetNodes$p(Landroidx/compose/ui/focus/FocusInvalidationManager;)Ljava/util/Set;
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->scheduleInvalidation(Landroidx/compose/ui/focus/FocusEventModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->scheduleInvalidation(Landroidx/compose/ui/focus/FocusPropertiesModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->scheduleInvalidation(Landroidx/compose/ui/focus/FocusTargetModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusInvalidationManager;->scheduleInvalidation(Ljava/util/Set;Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/focus/FocusModifierKt;->focusTarget(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl$special$$inlined$modifierElementOf$2;-><init>(Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/focus/FocusOwnerImpl;)V
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl$special$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;->getModifier()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;->getRootFocusNode$ui_release()Landroidx/compose/ui/focus/FocusTargetModifierNode;
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;->scheduleInvalidation(Landroidx/compose/ui/focus/FocusEventModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;->scheduleInvalidation(Landroidx/compose/ui/focus/FocusPropertiesModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;->scheduleInvalidation(Landroidx/compose/ui/focus/FocusTargetModifierNode;)V
-HSPLandroidx/compose/ui/focus/FocusOwnerImpl;->setLayoutDirection(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/focus/FocusPropertiesKt$focusProperties$$inlined$modifierElementOf$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusPropertiesKt$focusProperties$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusPropertiesKt$focusProperties$$inlined$modifierElementOf$2;->update(Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusPropertiesKt;->focusProperties(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusPropertiesModifierNodeImpl;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusPropertiesModifierNodeImpl;->modifyFocusProperties(Landroidx/compose/ui/focus/FocusProperties;)V
-HSPLandroidx/compose/ui/focus/FocusPropertiesModifierNodeImpl;->setFocusPropertiesScope(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusRequester$Companion;-><init>()V
-HSPLandroidx/compose/ui/focus/FocusRequester$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/focus/FocusRequester;-><clinit>()V
-HSPLandroidx/compose/ui/focus/FocusRequester;-><init>()V
-HSPLandroidx/compose/ui/focus/FocusRequester;->getFocusRequesterNodes$ui_release()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/focus/FocusRequesterModifierKt$focusRequester$$inlined$modifierElementOf$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/focus/FocusRequester;Landroidx/compose/ui/focus/FocusRequester;)V
-HSPLandroidx/compose/ui/focus/FocusRequesterModifierKt$focusRequester$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusRequesterModifierKt;->focusRequester(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/focus/FocusRequester;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusRequesterModifierNodeImpl;-><init>(Landroidx/compose/ui/focus/FocusRequester;)V
-HSPLandroidx/compose/ui/focus/FocusRequesterModifierNodeImpl;->onAttach()V
-HSPLandroidx/compose/ui/focus/FocusRequesterModifierNodeImpl;->onDetach()V
-HSPLandroidx/compose/ui/focus/FocusStateImpl$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/focus/FocusStateImpl;->$values()[Landroidx/compose/ui/focus/FocusStateImpl;
-HSPLandroidx/compose/ui/focus/FocusStateImpl;-><clinit>()V
-HSPLandroidx/compose/ui/focus/FocusStateImpl;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/focus/FocusStateImpl;->isFocused()Z
-HSPLandroidx/compose/ui/focus/FocusStateImpl;->values()[Landroidx/compose/ui/focus/FocusStateImpl;
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode$Companion;-><init>()V
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode$Companion;->getFocusTargetModifierElement$ui_release()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode$special$$inlined$modifierElementOf$2;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode$special$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode;-><clinit>()V
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode;-><init>()V
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode;->access$getFocusTargetModifierElement$cp()Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode;->getFocusState()Landroidx/compose/ui/focus/FocusState;
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode;->getFocusStateImpl$ui_release()Landroidx/compose/ui/focus/FocusStateImpl;
-HSPLandroidx/compose/ui/focus/FocusTargetModifierNode;->invalidateFocus$ui_release()V
-HSPLandroidx/compose/ui/geometry/CornerRadius$Companion;-><init>()V
-HSPLandroidx/compose/ui/geometry/CornerRadius$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/geometry/CornerRadius$Companion;->getZero-kKHJgLs()J
-HSPLandroidx/compose/ui/geometry/CornerRadius;-><clinit>()V
-HSPLandroidx/compose/ui/geometry/CornerRadius;->access$getZero$cp()J
-HSPLandroidx/compose/ui/geometry/CornerRadius;->constructor-impl(J)J
-HSPLandroidx/compose/ui/geometry/CornerRadius;->getX-impl(J)F
-HSPLandroidx/compose/ui/geometry/CornerRadius;->getY-impl(J)F
-HSPLandroidx/compose/ui/geometry/CornerRadiusKt;->CornerRadius$default(FFILjava/lang/Object;)J
-HSPLandroidx/compose/ui/geometry/CornerRadiusKt;->CornerRadius(FF)J
-HSPLandroidx/compose/ui/geometry/Offset$Companion;-><init>()V
-HSPLandroidx/compose/ui/geometry/Offset$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/geometry/Offset$Companion;->getInfinite-F1C5BW0()J
-HSPLandroidx/compose/ui/geometry/Offset$Companion;->getUnspecified-F1C5BW0()J
-HSPLandroidx/compose/ui/geometry/Offset$Companion;->getZero-F1C5BW0()J
-HSPLandroidx/compose/ui/geometry/Offset;-><clinit>()V
-HSPLandroidx/compose/ui/geometry/Offset;-><init>(J)V
-HSPLandroidx/compose/ui/geometry/Offset;->access$getInfinite$cp()J
-HSPLandroidx/compose/ui/geometry/Offset;->access$getUnspecified$cp()J
-HSPLandroidx/compose/ui/geometry/Offset;->access$getZero$cp()J
-HSPLandroidx/compose/ui/geometry/Offset;->box-impl(J)Landroidx/compose/ui/geometry/Offset;
-HSPLandroidx/compose/ui/geometry/Offset;->constructor-impl(J)J
-HSPLandroidx/compose/ui/geometry/Offset;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/geometry/Offset;->equals-impl(JLjava/lang/Object;)Z
-HSPLandroidx/compose/ui/geometry/Offset;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/geometry/Offset;->getDistance-impl(J)F
-HSPLandroidx/compose/ui/geometry/Offset;->getX-impl(J)F
-HSPLandroidx/compose/ui/geometry/Offset;->getY-impl(J)F
-HSPLandroidx/compose/ui/geometry/Offset;->minus-MK-Hz9U(JJ)J
-HSPLandroidx/compose/ui/geometry/Offset;->plus-MK-Hz9U(JJ)J
-HSPLandroidx/compose/ui/geometry/Offset;->unbox-impl()J
-HSPLandroidx/compose/ui/geometry/OffsetKt;->Offset(FF)J
-HSPLandroidx/compose/ui/geometry/OffsetKt;->isFinite-k-4lQ0M(J)Z
-HSPLandroidx/compose/ui/geometry/Rect$Companion;-><init>()V
-HSPLandroidx/compose/ui/geometry/Rect$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/geometry/Rect$Companion;->getZero()Landroidx/compose/ui/geometry/Rect;
-HSPLandroidx/compose/ui/geometry/Rect;-><clinit>()V
-HSPLandroidx/compose/ui/geometry/Rect;-><init>(FFFF)V
-HSPLandroidx/compose/ui/geometry/Rect;->access$getZero$cp()Landroidx/compose/ui/geometry/Rect;
-HSPLandroidx/compose/ui/geometry/Rect;->getBottom()F
-HSPLandroidx/compose/ui/geometry/Rect;->getHeight()F
-HSPLandroidx/compose/ui/geometry/Rect;->getLeft()F
-HSPLandroidx/compose/ui/geometry/Rect;->getRight()F
-HSPLandroidx/compose/ui/geometry/Rect;->getTop()F
-HSPLandroidx/compose/ui/geometry/Rect;->getWidth()F
-HSPLandroidx/compose/ui/geometry/RectKt;->Rect-tz77jQw(JJ)Landroidx/compose/ui/geometry/Rect;
-HSPLandroidx/compose/ui/geometry/RoundRect$Companion;-><init>()V
-HSPLandroidx/compose/ui/geometry/RoundRect$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/geometry/RoundRect;-><clinit>()V
-HSPLandroidx/compose/ui/geometry/RoundRect;-><init>(FFFFJJJJ)V
-HSPLandroidx/compose/ui/geometry/RoundRect;-><init>(FFFFJJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/geometry/RoundRect;->getBottom()F
-HSPLandroidx/compose/ui/geometry/RoundRect;->getBottomLeftCornerRadius-kKHJgLs()J
-HSPLandroidx/compose/ui/geometry/RoundRect;->getBottomRightCornerRadius-kKHJgLs()J
-HSPLandroidx/compose/ui/geometry/RoundRect;->getHeight()F
-HSPLandroidx/compose/ui/geometry/RoundRect;->getLeft()F
-HSPLandroidx/compose/ui/geometry/RoundRect;->getRight()F
-HSPLandroidx/compose/ui/geometry/RoundRect;->getTop()F
-HSPLandroidx/compose/ui/geometry/RoundRect;->getTopLeftCornerRadius-kKHJgLs()J
-HSPLandroidx/compose/ui/geometry/RoundRect;->getTopRightCornerRadius-kKHJgLs()J
-HSPLandroidx/compose/ui/geometry/RoundRect;->getWidth()F
-HSPLandroidx/compose/ui/geometry/RoundRectKt;->RoundRect(FFFFFF)Landroidx/compose/ui/geometry/RoundRect;
-HSPLandroidx/compose/ui/geometry/RoundRectKt;->RoundRect-ZAM2FJo(Landroidx/compose/ui/geometry/Rect;JJJJ)Landroidx/compose/ui/geometry/RoundRect;
-HSPLandroidx/compose/ui/geometry/RoundRectKt;->RoundRect-gG7oq9Y(FFFFJ)Landroidx/compose/ui/geometry/RoundRect;
-HSPLandroidx/compose/ui/geometry/RoundRectKt;->isSimple(Landroidx/compose/ui/geometry/RoundRect;)Z
-HSPLandroidx/compose/ui/geometry/Size$Companion;-><init>()V
-HSPLandroidx/compose/ui/geometry/Size$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/geometry/Size$Companion;->getUnspecified-NH-jbRc()J
-HSPLandroidx/compose/ui/geometry/Size$Companion;->getZero-NH-jbRc()J
-HSPLandroidx/compose/ui/geometry/Size;-><clinit>()V
-HSPLandroidx/compose/ui/geometry/Size;-><init>(J)V
-HSPLandroidx/compose/ui/geometry/Size;->access$getUnspecified$cp()J
-HSPLandroidx/compose/ui/geometry/Size;->access$getZero$cp()J
-HSPLandroidx/compose/ui/geometry/Size;->box-impl(J)Landroidx/compose/ui/geometry/Size;
-HSPLandroidx/compose/ui/geometry/Size;->constructor-impl(J)J
-HSPLandroidx/compose/ui/geometry/Size;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/geometry/Size;->equals-impl(JLjava/lang/Object;)Z
-HSPLandroidx/compose/ui/geometry/Size;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/geometry/Size;->getHeight-impl(J)F
-HSPLandroidx/compose/ui/geometry/Size;->getMinDimension-impl(J)F
-HSPLandroidx/compose/ui/geometry/Size;->getWidth-impl(J)F
-HSPLandroidx/compose/ui/geometry/Size;->isEmpty-impl(J)Z
-HSPLandroidx/compose/ui/geometry/Size;->unbox-impl()J
-HSPLandroidx/compose/ui/geometry/SizeKt;->Size(FF)J
-HSPLandroidx/compose/ui/geometry/SizeKt;->toRect-uvyYCjk(J)Landroidx/compose/ui/geometry/Rect;
-HSPLandroidx/compose/ui/graphics/AndroidBlendMode_androidKt;->toAndroidBlendMode-s9anfk8(I)Landroid/graphics/BlendMode;
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;-><init>()V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->concat-58bKbWc([F)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->disableZ()V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->drawImageRect-HPBpro0(Landroidx/compose/ui/graphics/ImageBitmap;JJJJLandroidx/compose/ui/graphics/Paint;)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->drawPath(Landroidx/compose/ui/graphics/Path;Landroidx/compose/ui/graphics/Paint;)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->drawRect(FFFFLandroidx/compose/ui/graphics/Paint;)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->drawRoundRect(FFFFFFLandroidx/compose/ui/graphics/Paint;)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->enableZ()V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->getInternalCanvas()Landroid/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->restore()V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->save()V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->setInternalCanvas(Landroid/graphics/Canvas;)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas;->translate(FF)V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/AndroidCanvas_androidKt;->ActualCanvas(Landroidx/compose/ui/graphics/ImageBitmap;)Landroidx/compose/ui/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/AndroidCanvas_androidKt;->access$getEmptyCanvas$p()Landroid/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/AndroidCanvas_androidKt;->getNativeCanvas(Landroidx/compose/ui/graphics/Canvas;)Landroid/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/AndroidColorFilter_androidKt;->actualTintColorFilter-xETnrds(JI)Landroidx/compose/ui/graphics/ColorFilter;
-HSPLandroidx/compose/ui/graphics/AndroidColorFilter_androidKt;->asAndroidColorFilter(Landroidx/compose/ui/graphics/ColorFilter;)Landroid/graphics/ColorFilter;
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap;-><init>(Landroid/graphics/Bitmap;)V
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap;->getBitmap$ui_graphics_release()Landroid/graphics/Bitmap;
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap;->getHeight()I
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap;->getWidth()I
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap;->prepareToDraw()V
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap_androidKt;->ActualImageBitmap-x__-hDU(IIIZLandroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroidx/compose/ui/graphics/ImageBitmap;
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap_androidKt;->asAndroidBitmap(Landroidx/compose/ui/graphics/ImageBitmap;)Landroid/graphics/Bitmap;
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap_androidKt;->asImageBitmap(Landroid/graphics/Bitmap;)Landroidx/compose/ui/graphics/ImageBitmap;
-HSPLandroidx/compose/ui/graphics/AndroidImageBitmap_androidKt;->toBitmapConfig-1JJdX4A(I)Landroid/graphics/Bitmap$Config;
-HSPLandroidx/compose/ui/graphics/AndroidMatrixConversions_androidKt;->setFrom-EL8BTi8(Landroid/graphics/Matrix;[F)V
-HSPLandroidx/compose/ui/graphics/AndroidMatrixConversions_androidKt;->setFrom-tU-YjHk([FLandroid/graphics/Matrix;)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;-><init>()V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;-><init>(Landroid/graphics/Paint;)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->asFrameworkPaint()Landroid/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->getAlpha()F
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->getBlendMode-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->getColor-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->getColorFilter()Landroidx/compose/ui/graphics/ColorFilter;
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->getFilterQuality-f-v9h1I()I
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->getShader()Landroid/graphics/Shader;
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setAlpha(F)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setBlendMode-s9anfk8(I)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setColor-8_81llA(J)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setColorFilter(Landroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setShader(Landroid/graphics/Shader;)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setStrokeWidth(F)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint;->setStyle-k9PVt8s(I)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->Paint()Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->getNativeAlpha(Landroid/graphics/Paint;)F
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->getNativeColor(Landroid/graphics/Paint;)J
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->getNativeFilterQuality(Landroid/graphics/Paint;)I
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->makeNativePaint()Landroid/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeAlpha(Landroid/graphics/Paint;F)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeBlendMode-GB0RdKg(Landroid/graphics/Paint;I)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeColor-4WTKRHQ(Landroid/graphics/Paint;J)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeColorFilter(Landroid/graphics/Paint;Landroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeShader(Landroid/graphics/Paint;Landroid/graphics/Shader;)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeStrokeWidth(Landroid/graphics/Paint;F)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->setNativeStyle--5YerkU(Landroid/graphics/Paint;I)V
-HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->toComposePaint(Landroid/graphics/Paint;)Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/AndroidPath;-><init>(Landroid/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;-><init>(Landroid/graphics/Path;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->addPath-Uv8p0NA(Landroidx/compose/ui/graphics/Path;J)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->addRoundRect(Landroidx/compose/ui/geometry/RoundRect;)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->close()V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->getInternalPath()Landroid/graphics/Path;
-HSPLandroidx/compose/ui/graphics/AndroidPath;->lineTo(FF)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->moveTo(FF)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->relativeLineTo(FF)V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->reset()V
-HSPLandroidx/compose/ui/graphics/AndroidPath;->setFillType-oQ8Xj4U(I)V
-HSPLandroidx/compose/ui/graphics/AndroidPath_androidKt;->Path()Landroidx/compose/ui/graphics/Path;
-HSPLandroidx/compose/ui/graphics/Api26Bitmap;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Api26Bitmap;-><init>()V
-HSPLandroidx/compose/ui/graphics/Api26Bitmap;->createBitmap-x__-hDU$ui_graphics_release(IIIZLandroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroid/graphics/Bitmap;
-HSPLandroidx/compose/ui/graphics/Api26Bitmap;->toFrameworkColorSpace$ui_graphics_release(Landroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroid/graphics/ColorSpace;
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;->getClear-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;->getDst-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;->getDstOver-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;->getSrc-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;->getSrcIn-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/BlendMode$Companion;->getSrcOver-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/BlendMode;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/BlendMode;-><init>(I)V
-HSPLandroidx/compose/ui/graphics/BlendMode;->access$getClear$cp()I
-HSPLandroidx/compose/ui/graphics/BlendMode;->access$getDst$cp()I
-HSPLandroidx/compose/ui/graphics/BlendMode;->access$getDstOver$cp()I
-HSPLandroidx/compose/ui/graphics/BlendMode;->access$getSrc$cp()I
-HSPLandroidx/compose/ui/graphics/BlendMode;->access$getSrcIn$cp()I
-HSPLandroidx/compose/ui/graphics/BlendMode;->access$getSrcOver$cp()I
-HSPLandroidx/compose/ui/graphics/BlendMode;->box-impl(I)Landroidx/compose/ui/graphics/BlendMode;
-HSPLandroidx/compose/ui/graphics/BlendMode;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/BlendMode;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/BlendMode;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/BlendMode;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/BlendMode;->unbox-impl()I
-HSPLandroidx/compose/ui/graphics/BlendModeColorFilterHelper;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/BlendModeColorFilterHelper;-><init>()V
-HSPLandroidx/compose/ui/graphics/BlendModeColorFilterHelper;->BlendModeColorFilter-xETnrds(JI)Landroid/graphics/BlendModeColorFilter;
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/graphics/BlockGraphicsLayerModifier;)V
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier;->getLayerBlock()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier;->setLayerBlock(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/graphics/Brush$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/Brush$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Brush;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Brush;-><init>()V
-HSPLandroidx/compose/ui/graphics/Brush;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/CanvasHolder;-><init>()V
-HSPLandroidx/compose/ui/graphics/CanvasHolder;->getAndroidCanvas()Landroidx/compose/ui/graphics/AndroidCanvas;
-HSPLandroidx/compose/ui/graphics/CanvasKt;->Canvas(Landroidx/compose/ui/graphics/ImageBitmap;)Landroidx/compose/ui/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/CanvasUtils;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/CanvasUtils;-><init>()V
-HSPLandroidx/compose/ui/graphics/CanvasUtils;->enableZ(Landroid/graphics/Canvas;Z)V
-HSPLandroidx/compose/ui/graphics/CanvasZHelper;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/CanvasZHelper;-><init>()V
-HSPLandroidx/compose/ui/graphics/CanvasZHelper;->enableZ(Landroid/graphics/Canvas;Z)V
-HSPLandroidx/compose/ui/graphics/Color$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/Color$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Color$Companion;->getBlack-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/Color$Companion;->getBlue-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/Color$Companion;->getRed-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/Color$Companion;->getTransparent-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/Color$Companion;->getUnspecified-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/Color;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Color;-><init>(J)V
-HSPLandroidx/compose/ui/graphics/Color;->access$getBlack$cp()J
-HSPLandroidx/compose/ui/graphics/Color;->access$getBlue$cp()J
-HSPLandroidx/compose/ui/graphics/Color;->access$getRed$cp()J
-HSPLandroidx/compose/ui/graphics/Color;->access$getTransparent$cp()J
-HSPLandroidx/compose/ui/graphics/Color;->access$getUnspecified$cp()J
-HSPLandroidx/compose/ui/graphics/Color;->box-impl(J)Landroidx/compose/ui/graphics/Color;
-HSPLandroidx/compose/ui/graphics/Color;->constructor-impl(J)J
-HSPLandroidx/compose/ui/graphics/Color;->convert-vNxB06k(JLandroidx/compose/ui/graphics/colorspace/ColorSpace;)J
-HSPLandroidx/compose/ui/graphics/Color;->copy-wmQWz5c$default(JFFFFILjava/lang/Object;)J
-HSPLandroidx/compose/ui/graphics/Color;->copy-wmQWz5c(JFFFF)J
-HSPLandroidx/compose/ui/graphics/Color;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/Color;->equals-impl(JLjava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/Color;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/graphics/Color;->getAlpha-impl(J)F
-HSPLandroidx/compose/ui/graphics/Color;->getBlue-impl(J)F
-HSPLandroidx/compose/ui/graphics/Color;->getColorSpace-impl(J)Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-HSPLandroidx/compose/ui/graphics/Color;->getGreen-impl(J)F
-HSPLandroidx/compose/ui/graphics/Color;->getRed-impl(J)F
-HSPLandroidx/compose/ui/graphics/Color;->unbox-impl()J
-HSPLandroidx/compose/ui/graphics/ColorFilter$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/ColorFilter$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/ColorFilter$Companion;->tint-xETnrds$default(Landroidx/compose/ui/graphics/ColorFilter$Companion;JIILjava/lang/Object;)Landroidx/compose/ui/graphics/ColorFilter;
-HSPLandroidx/compose/ui/graphics/ColorFilter$Companion;->tint-xETnrds(JI)Landroidx/compose/ui/graphics/ColorFilter;
-HSPLandroidx/compose/ui/graphics/ColorFilter;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/ColorFilter;-><init>(Landroid/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/ColorFilter;->getNativeColorFilter$ui_graphics_release()Landroid/graphics/ColorFilter;
-HSPLandroidx/compose/ui/graphics/ColorKt;->Color$default(FFFFLandroidx/compose/ui/graphics/colorspace/ColorSpace;ILjava/lang/Object;)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->Color$default(IIIIILjava/lang/Object;)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->Color(FFFFLandroidx/compose/ui/graphics/colorspace/ColorSpace;)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->Color(I)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->Color(IIII)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->Color(J)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->compositeOver--OWjLjI(JJ)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->lerp-jxsXWHM(JJF)J
-HSPLandroidx/compose/ui/graphics/ColorKt;->toArgb-8_81llA(J)I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/CompositingStrategy$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/CompositingStrategy$Companion;->getAuto--NrFUSI()I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy$Companion;->getModulateAlpha--NrFUSI()I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy$Companion;->getOffscreen--NrFUSI()I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/CompositingStrategy;->access$getAuto$cp()I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy;->access$getModulateAlpha$cp()I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy;->access$getOffscreen$cp()I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/CompositingStrategy;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/FilterQuality$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/FilterQuality$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/FilterQuality$Companion;->getLow-f-v9h1I()I
-HSPLandroidx/compose/ui/graphics/FilterQuality;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/FilterQuality;->access$getLow$cp()I
-HSPLandroidx/compose/ui/graphics/FilterQuality;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/FilterQuality;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/Float16$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/Float16$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Float16$Companion;->access$floatToHalf(Landroidx/compose/ui/graphics/Float16$Companion;F)S
-HSPLandroidx/compose/ui/graphics/Float16$Companion;->floatToHalf(F)S
-HSPLandroidx/compose/ui/graphics/Float16;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Float16;->constructor-impl(F)S
-HSPLandroidx/compose/ui/graphics/Float16;->constructor-impl(S)S
-HSPLandroidx/compose/ui/graphics/Float16;->toFloat-impl(S)F
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt$graphicsLayer$$inlined$modifierElementOf$1;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt$graphicsLayer$$inlined$modifierElementOf$1;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt$graphicsLayer$$inlined$modifierElementOf$1;->update(Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt;->graphicsLayer(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt;->graphicsLayer-Ap8cVGQ$default(Landroidx/compose/ui/Modifier;FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJIILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt;->graphicsLayer-Ap8cVGQ(Landroidx/compose/ui/Modifier;FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJI)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt;->toolingGraphicsLayer(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierNodeElement;-><init>(FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJI)V
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierNodeElement;-><init>(FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierNodeElement;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierNodeElement;->create()Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;
-HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierNodeElement;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/GraphicsLayerScopeKt;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/GraphicsLayerScopeKt;->getDefaultShadowColor()J
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig$Companion;->getArgb8888-_sVssgQ()I
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig;->access$getArgb8888$cp()I
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/ImageBitmapConfig;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/ImageBitmapKt;->ImageBitmap-x__-hDU$default(IIIZLandroidx/compose/ui/graphics/colorspace/ColorSpace;ILjava/lang/Object;)Landroidx/compose/ui/graphics/ImageBitmap;
-HSPLandroidx/compose/ui/graphics/ImageBitmapKt;->ImageBitmap-x__-hDU(IIIZLandroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroidx/compose/ui/graphics/ImageBitmap;
-HSPLandroidx/compose/ui/graphics/Matrix$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/Matrix$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Matrix;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Matrix;-><init>([F)V
-HSPLandroidx/compose/ui/graphics/Matrix;->box-impl([F)Landroidx/compose/ui/graphics/Matrix;
-HSPLandroidx/compose/ui/graphics/Matrix;->constructor-impl$default([FILkotlin/jvm/internal/DefaultConstructorMarker;)[F
-HSPLandroidx/compose/ui/graphics/Matrix;->constructor-impl([F)[F
-HSPLandroidx/compose/ui/graphics/Matrix;->map-MK-Hz9U([FJ)J
-HSPLandroidx/compose/ui/graphics/Matrix;->reset-impl([F)V
-HSPLandroidx/compose/ui/graphics/Matrix;->rotateZ-impl([FF)V
-HSPLandroidx/compose/ui/graphics/Matrix;->scale-impl([FFFF)V
-HSPLandroidx/compose/ui/graphics/Matrix;->translate-impl$default([FFFFILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/Matrix;->translate-impl([FFFF)V
-HSPLandroidx/compose/ui/graphics/Matrix;->unbox-impl()[F
-HSPLandroidx/compose/ui/graphics/MatrixKt;->isIdentity-58bKbWc([F)Z
-HSPLandroidx/compose/ui/graphics/Outline$Rectangle;-><init>(Landroidx/compose/ui/geometry/Rect;)V
-HSPLandroidx/compose/ui/graphics/Outline$Rectangle;->getRect()Landroidx/compose/ui/geometry/Rect;
-HSPLandroidx/compose/ui/graphics/Outline$Rounded;-><init>(Landroidx/compose/ui/geometry/RoundRect;)V
-HSPLandroidx/compose/ui/graphics/Outline$Rounded;->getRoundRect()Landroidx/compose/ui/geometry/RoundRect;
-HSPLandroidx/compose/ui/graphics/Outline$Rounded;->getRoundRectPath$ui_graphics_release()Landroidx/compose/ui/graphics/Path;
-HSPLandroidx/compose/ui/graphics/Outline;-><init>()V
-HSPLandroidx/compose/ui/graphics/Outline;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/OutlineKt;->access$hasSameCornerRadius(Landroidx/compose/ui/geometry/RoundRect;)Z
-HSPLandroidx/compose/ui/graphics/OutlineKt;->drawOutline-wDX37Ww$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/graphics/Outline;JFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;IILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/OutlineKt;->drawOutline-wDX37Ww(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/graphics/Outline;JFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/graphics/OutlineKt;->hasSameCornerRadius(Landroidx/compose/ui/geometry/RoundRect;)Z
-HSPLandroidx/compose/ui/graphics/OutlineKt;->size(Landroidx/compose/ui/geometry/Rect;)J
-HSPLandroidx/compose/ui/graphics/OutlineKt;->size(Landroidx/compose/ui/geometry/RoundRect;)J
-HSPLandroidx/compose/ui/graphics/OutlineKt;->topLeft(Landroidx/compose/ui/geometry/Rect;)J
-HSPLandroidx/compose/ui/graphics/OutlineKt;->topLeft(Landroidx/compose/ui/geometry/RoundRect;)J
-HSPLandroidx/compose/ui/graphics/PaintingStyle$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/PaintingStyle$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/PaintingStyle$Companion;->getFill-TiuSbCo()I
-HSPLandroidx/compose/ui/graphics/PaintingStyle$Companion;->getStroke-TiuSbCo()I
-HSPLandroidx/compose/ui/graphics/PaintingStyle;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/PaintingStyle;->access$getFill$cp()I
-HSPLandroidx/compose/ui/graphics/PaintingStyle;->access$getStroke$cp()I
-HSPLandroidx/compose/ui/graphics/PaintingStyle;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/PaintingStyle;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/Path$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Path$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/Path;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Path;->addPath-Uv8p0NA$default(Landroidx/compose/ui/graphics/Path;Landroidx/compose/ui/graphics/Path;JILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/PathFillType$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/PathFillType$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/PathFillType$Companion;->getEvenOdd-Rg-k1Os()I
-HSPLandroidx/compose/ui/graphics/PathFillType$Companion;->getNonZero-Rg-k1Os()I
-HSPLandroidx/compose/ui/graphics/PathFillType;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/PathFillType;-><init>(I)V
-HSPLandroidx/compose/ui/graphics/PathFillType;->access$getEvenOdd$cp()I
-HSPLandroidx/compose/ui/graphics/PathFillType;->access$getNonZero$cp()I
-HSPLandroidx/compose/ui/graphics/PathFillType;->box-impl(I)Landroidx/compose/ui/graphics/PathFillType;
-HSPLandroidx/compose/ui/graphics/PathFillType;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/PathFillType;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/PathFillType;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/PathFillType;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/PathFillType;->unbox-impl()I
-HSPLandroidx/compose/ui/graphics/RectangleShapeKt$RectangleShape$1;-><init>()V
-HSPLandroidx/compose/ui/graphics/RectangleShapeKt;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/RectangleShapeKt;->getRectangleShape()Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;-><init>()V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getAlpha()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getAmbientShadowColor-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getCameraDistance()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getClip()Z
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getCompositingStrategy--NrFUSI()I
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getDensity()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getRenderEffect()Landroidx/compose/ui/graphics/RenderEffect;
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getRotationX()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getRotationY()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getRotationZ()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getScaleX()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getScaleY()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getShadowElevation()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getShape()Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getSpotShadowColor-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getTransformOrigin-SzJe1aQ()J
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getTranslationX()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->getTranslationY()F
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->reset()V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setAlpha(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setAmbientShadowColor-8_81llA(J)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setCameraDistance(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setClip(Z)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setCompositingStrategy-aDBOjCE(I)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setGraphicsDensity$ui_release(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setRenderEffect(Landroidx/compose/ui/graphics/RenderEffect;)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setRotationX(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setRotationY(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setRotationZ(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setScaleX(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setScaleY(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setShadowElevation(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setShape(Landroidx/compose/ui/graphics/Shape;)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setSize-uvyYCjk(J)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setSpotShadowColor-8_81llA(J)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setTransformOrigin-__ExYCQ(J)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setTranslationX(F)V
-HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->setTranslationY(F)V
-HSPLandroidx/compose/ui/graphics/Shadow$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/Shadow$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Shadow$Companion;->getNone()Landroidx/compose/ui/graphics/Shadow;
-HSPLandroidx/compose/ui/graphics/Shadow;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/Shadow;-><init>(JJF)V
-HSPLandroidx/compose/ui/graphics/Shadow;-><init>(JJFILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Shadow;-><init>(JJFLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/Shadow;->access$getNone$cp()Landroidx/compose/ui/graphics/Shadow;
-HSPLandroidx/compose/ui/graphics/Shadow;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$layerBlock$1;-><init>(Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;)V
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$layerBlock$1;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)V
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$layerBlock$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$measure$1;-><init>(Landroidx/compose/ui/layout/Placeable;Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;)V
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$measure$1;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$measure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;-><init>(FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJI)V
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;-><init>(FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->access$getLayerBlock$p(Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getAlpha()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getAmbientShadowColor-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getCameraDistance()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getClip()Z
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getCompositingStrategy--NrFUSI()I
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getRenderEffect()Landroidx/compose/ui/graphics/RenderEffect;
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getRotationX()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getRotationY()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getRotationZ()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getScaleX()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getScaleY()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getShadowElevation()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getShape()Landroidx/compose/ui/graphics/Shape;
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getSpotShadowColor-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getTransformOrigin-SzJe1aQ()J
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getTranslationX()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->getTranslationY()F
-HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/graphics/SolidColor;-><init>(J)V
-HSPLandroidx/compose/ui/graphics/SolidColor;-><init>(JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/SolidColor;->applyTo-Pq9zytI(JLandroidx/compose/ui/graphics/Paint;F)V
-HSPLandroidx/compose/ui/graphics/SolidColor;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/StrokeCap$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/StrokeCap$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/StrokeCap$Companion;->getButt-KaPHkGw()I
-HSPLandroidx/compose/ui/graphics/StrokeCap;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/StrokeCap;-><init>(I)V
-HSPLandroidx/compose/ui/graphics/StrokeCap;->access$getButt$cp()I
-HSPLandroidx/compose/ui/graphics/StrokeCap;->box-impl(I)Landroidx/compose/ui/graphics/StrokeCap;
-HSPLandroidx/compose/ui/graphics/StrokeCap;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/StrokeCap;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/StrokeCap;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/StrokeCap;->unbox-impl()I
-HSPLandroidx/compose/ui/graphics/StrokeJoin$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/StrokeJoin$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/StrokeJoin$Companion;->getBevel-LxFBmk8()I
-HSPLandroidx/compose/ui/graphics/StrokeJoin$Companion;->getMiter-LxFBmk8()I
-HSPLandroidx/compose/ui/graphics/StrokeJoin;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/StrokeJoin;-><init>(I)V
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->access$getBevel$cp()I
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->access$getMiter$cp()I
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->box-impl(I)Landroidx/compose/ui/graphics/StrokeJoin;
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/StrokeJoin;->unbox-impl()I
-HSPLandroidx/compose/ui/graphics/TransformOrigin$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/TransformOrigin$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/TransformOrigin$Companion;->getCenter-SzJe1aQ()J
-HSPLandroidx/compose/ui/graphics/TransformOrigin;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/TransformOrigin;->access$getCenter$cp()J
-HSPLandroidx/compose/ui/graphics/TransformOrigin;->constructor-impl(J)J
-HSPLandroidx/compose/ui/graphics/TransformOrigin;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/graphics/TransformOrigin;->getPivotFractionX-impl(J)F
-HSPLandroidx/compose/ui/graphics/TransformOrigin;->getPivotFractionY-impl(J)F
-HSPLandroidx/compose/ui/graphics/TransformOriginKt;->TransformOrigin(FF)J
-HSPLandroidx/compose/ui/graphics/WrapperVerificationHelperMethods;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/WrapperVerificationHelperMethods;-><init>()V
-HSPLandroidx/compose/ui/graphics/WrapperVerificationHelperMethods;->setBlendMode-GB0RdKg(Landroid/graphics/Paint;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation$Companion$Bradford$1;-><init>([F)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation$Companion$Ciecat02$1;-><init>([F)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation$Companion$VonKries$1;-><init>([F)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation$Companion;->getBradford()Landroidx/compose/ui/graphics/colorspace/Adaptation;
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation;-><init>([F)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation;-><init>([FLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation;->access$getBradford$cp()Landroidx/compose/ui/graphics/colorspace/Adaptation;
-HSPLandroidx/compose/ui/graphics/colorspace/Adaptation;->getTransform$ui_graphics_release()[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel$Companion;->getLab-xdoWZVw()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel$Companion;->getRgb-xdoWZVw()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel$Companion;->getXyz-xdoWZVw()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;->access$getLab$cp()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;->access$getRgb$cp()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;->access$getXyz$cp()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;->constructor-impl(J)J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/graphics/colorspace/ColorModel;->getComponentCount-impl(J)I
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;-><init>(Ljava/lang/String;JI)V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;-><init>(Ljava/lang/String;JILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;->getComponentCount()I
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;->getId$ui_graphics_release()I
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;->getModel-xdoWZVw()J
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;->getName()Ljava/lang/String;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpace;->isSrgb()Z
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->adapt$default(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/WhitePoint;Landroidx/compose/ui/graphics/colorspace/Adaptation;ILjava/lang/Object;)Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->adapt(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/WhitePoint;Landroidx/compose/ui/graphics/colorspace/Adaptation;)Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->chromaticAdaptation([F[F[F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->compare(Landroidx/compose/ui/graphics/colorspace/WhitePoint;Landroidx/compose/ui/graphics/colorspace/WhitePoint;)Z
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->compare([F[F)Z
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->connect-YBCOT_4$default(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;IILjava/lang/Object;)Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->connect-YBCOT_4(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;I)Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->inverse3x3([F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->mul3x3([F[F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->mul3x3Diag([F[F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->mul3x3Float3([F[F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->mul3x3Float3_0([FFFF)F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->mul3x3Float3_1([FFFF)F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->mul3x3Float3_2([FFFF)F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->rcpResponse(DDDDDD)D
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaceKt;->response(DDDDDD)D
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces$$ExternalSyntheticLambda0;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces$$ExternalSyntheticLambda1;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getCieXyz()Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getColorSpacesArray$ui_graphics_release()[Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getNtsc1953Primaries$ui_graphics_release()[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getOklab()Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getSrgb()Landroidx/compose/ui/graphics/colorspace/Rgb;
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getSrgbPrimaries$ui_graphics_release()[F
-HSPLandroidx/compose/ui/graphics/colorspace/ColorSpaces;->getUnspecified$ui_graphics_release()Landroidx/compose/ui/graphics/colorspace/Rgb;
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion$identity$1;-><init>(Landroidx/compose/ui/graphics/colorspace/ColorSpace;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;->access$computeTransform-YBCOT_4(Landroidx/compose/ui/graphics/colorspace/Connector$Companion;Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;I)[F
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;->computeTransform-YBCOT_4(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;I)[F
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;->getOklabToSrgbPerceptual$ui_graphics_release()Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;->getSrgbToOklabPerceptual$ui_graphics_release()Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/Connector$Companion;->identity$ui_graphics_release(Landroidx/compose/ui/graphics/colorspace/ColorSpace;)Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;-><init>(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;-><init>(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;-><init>(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;I[F)V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;-><init>(Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;Landroidx/compose/ui/graphics/colorspace/ColorSpace;I[FLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;->access$getOklabToSrgbPerceptual$cp()Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;->access$getSrgbToOklabPerceptual$cp()Landroidx/compose/ui/graphics/colorspace/Connector;
-HSPLandroidx/compose/ui/graphics/colorspace/Connector;->transformToColor-wmQWz5c$ui_graphics_release(FFFF)J
-HSPLandroidx/compose/ui/graphics/colorspace/Illuminant;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Illuminant;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Illuminant;->getC()Landroidx/compose/ui/graphics/colorspace/WhitePoint;
-HSPLandroidx/compose/ui/graphics/colorspace/Illuminant;->getD50()Landroidx/compose/ui/graphics/colorspace/WhitePoint;
-HSPLandroidx/compose/ui/graphics/colorspace/Illuminant;->getD60()Landroidx/compose/ui/graphics/colorspace/WhitePoint;
-HSPLandroidx/compose/ui/graphics/colorspace/Illuminant;->getD65()Landroidx/compose/ui/graphics/colorspace/WhitePoint;
-HSPLandroidx/compose/ui/graphics/colorspace/Lab$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Lab$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Lab;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Lab;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;->getMaxValue(I)F
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;->getMinValue(I)F
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;->toXy$ui_graphics_release(FFF)J
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;->toZ$ui_graphics_release(FFF)F
-HSPLandroidx/compose/ui/graphics/colorspace/Oklab;->xyzaToColor-JlNiLsg$ui_graphics_release(FFFFLandroidx/compose/ui/graphics/colorspace/ColorSpace;)J
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent$Companion;->getAbsolute-uksYyKA()I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent$Companion;->getPerceptual-uksYyKA()I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent$Companion;->getRelative-uksYyKA()I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent;->access$getAbsolute$cp()I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent;->access$getPerceptual$cp()I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent;->access$getRelative$cp()I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent;->constructor-impl(I)I
-HSPLandroidx/compose/ui/graphics/colorspace/RenderIntent;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda0;-><init>(Landroidx/compose/ui/graphics/colorspace/Rgb;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda0;->invoke(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda1;-><init>(Landroidx/compose/ui/graphics/colorspace/Rgb;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda1;->invoke(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda2;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda2;->invoke(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda3;-><init>(Landroidx/compose/ui/graphics/colorspace/TransferParameters;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda3;->invoke(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda5;-><init>(Landroidx/compose/ui/graphics/colorspace/TransferParameters;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda5;->invoke(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda7;-><init>(D)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda8;-><init>(D)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->access$computeXYZMatrix(Landroidx/compose/ui/graphics/colorspace/Rgb$Companion;[FLandroidx/compose/ui/graphics/colorspace/WhitePoint;)[F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->access$isSrgb(Landroidx/compose/ui/graphics/colorspace/Rgb$Companion;[FLandroidx/compose/ui/graphics/colorspace/WhitePoint;Landroidx/compose/ui/graphics/colorspace/DoubleFunction;Landroidx/compose/ui/graphics/colorspace/DoubleFunction;FFI)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->access$isWideGamut(Landroidx/compose/ui/graphics/colorspace/Rgb$Companion;[FFF)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->access$xyPrimaries(Landroidx/compose/ui/graphics/colorspace/Rgb$Companion;[F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->area([F)F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->compare(DLandroidx/compose/ui/graphics/colorspace/DoubleFunction;Landroidx/compose/ui/graphics/colorspace/DoubleFunction;)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->computeXYZMatrix([FLandroidx/compose/ui/graphics/colorspace/WhitePoint;)[F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->contains([F[F)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->cross(FFFF)F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->isSrgb([FLandroidx/compose/ui/graphics/colorspace/WhitePoint;Landroidx/compose/ui/graphics/colorspace/DoubleFunction;Landroidx/compose/ui/graphics/colorspace/DoubleFunction;FFI)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->isWideGamut([FFF)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$Companion;->xyPrimaries([F)[F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$eotf$1;-><init>(Landroidx/compose/ui/graphics/colorspace/Rgb;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb$oetf$1;-><init>(Landroidx/compose/ui/graphics/colorspace/Rgb;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->$r8$lambda$FANKyyW7TMwi4gnihl1LqxbkU6k(Landroidx/compose/ui/graphics/colorspace/Rgb;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->$r8$lambda$G8Pyx7Z9bMrnDjgEiQ7pXGTZEzg(Landroidx/compose/ui/graphics/colorspace/TransferParameters;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->$r8$lambda$OfmTeMXzL_nayJmS5mO6N4G4DlI(Landroidx/compose/ui/graphics/colorspace/Rgb;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->$r8$lambda$ahWovdYS5NpJ-IThda37cTda4qg(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->$r8$lambda$q_AtDSzDu9yw5JwgrVWJo3kmlB0(Landroidx/compose/ui/graphics/colorspace/TransferParameters;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;-><init>(Landroidx/compose/ui/graphics/colorspace/Rgb;[FLandroidx/compose/ui/graphics/colorspace/WhitePoint;)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;-><init>(Ljava/lang/String;[FLandroidx/compose/ui/graphics/colorspace/WhitePoint;DFFI)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;-><init>(Ljava/lang/String;[FLandroidx/compose/ui/graphics/colorspace/WhitePoint;Landroidx/compose/ui/graphics/colorspace/TransferParameters;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;-><init>(Ljava/lang/String;[FLandroidx/compose/ui/graphics/colorspace/WhitePoint;[FLandroidx/compose/ui/graphics/colorspace/DoubleFunction;Landroidx/compose/ui/graphics/colorspace/DoubleFunction;FFLandroidx/compose/ui/graphics/colorspace/TransferParameters;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->DoubleIdentity$lambda$12(D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->_init_$lambda$6(Landroidx/compose/ui/graphics/colorspace/TransferParameters;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->_init_$lambda$8(Landroidx/compose/ui/graphics/colorspace/TransferParameters;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->eotfFunc$lambda$1(Landroidx/compose/ui/graphics/colorspace/Rgb;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->getEotfOrig$ui_graphics_release()Landroidx/compose/ui/graphics/colorspace/DoubleFunction;
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->getMaxValue(I)F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->getMinValue(I)F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->getOetfOrig$ui_graphics_release()Landroidx/compose/ui/graphics/colorspace/DoubleFunction;
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->getTransform$ui_graphics_release()[F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->getWhitePoint()Landroidx/compose/ui/graphics/colorspace/WhitePoint;
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->isSrgb()Z
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->oetfFunc$lambda$0(Landroidx/compose/ui/graphics/colorspace/Rgb;D)D
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->toXy$ui_graphics_release(FFF)J
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->toZ$ui_graphics_release(FFF)F
-HSPLandroidx/compose/ui/graphics/colorspace/Rgb;->xyzaToColor-JlNiLsg$ui_graphics_release(FFFFLandroidx/compose/ui/graphics/colorspace/ColorSpace;)J
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;-><init>(DDDDDDD)V
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;-><init>(DDDDDDDILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getA()D
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getB()D
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getC()D
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getD()D
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getE()D
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getF()D
-HSPLandroidx/compose/ui/graphics/colorspace/TransferParameters;->getGamma()D
-HSPLandroidx/compose/ui/graphics/colorspace/WhitePoint;-><init>(FF)V
-HSPLandroidx/compose/ui/graphics/colorspace/WhitePoint;->getX()F
-HSPLandroidx/compose/ui/graphics/colorspace/WhitePoint;->getY()F
-HSPLandroidx/compose/ui/graphics/colorspace/WhitePoint;->toXyz$ui_graphics_release()[F
-HSPLandroidx/compose/ui/graphics/colorspace/Xyz;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/graphics/colorspace/Xyz;->clamp(F)F
-HSPLandroidx/compose/ui/graphics/colorspace/Xyz;->getMaxValue(I)F
-HSPLandroidx/compose/ui/graphics/colorspace/Xyz;->getMinValue(I)F
-HSPLandroidx/compose/ui/graphics/colorspace/Xyz;->xyzaToColor-JlNiLsg$ui_graphics_release(FFFFLandroidx/compose/ui/graphics/colorspace/ColorSpace;)J
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;-><init>(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/graphics/Canvas;J)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;-><init>(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/graphics/Canvas;JILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;-><init>(Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/graphics/Canvas;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->component1()Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->component2()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->component3()Landroidx/compose/ui/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->component4-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->getCanvas()Landroidx/compose/ui/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->getDensity()Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->getSize-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->setCanvas(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->setDensity(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->setLayoutDirection(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;->setSize-uvyYCjk(J)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$drawContext$1;-><init>(Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$drawContext$1;->getCanvas()Landroidx/compose/ui/graphics/Canvas;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$drawContext$1;->getSize-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$drawContext$1;->getTransform()Landroidx/compose/ui/graphics/drawscope/DrawTransform;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope$drawContext$1;->setSize-uvyYCjk(J)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;-><init>()V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->configurePaint-2qPWKa0$default(Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope;JLandroidx/compose/ui/graphics/drawscope/DrawStyle;FLandroidx/compose/ui/graphics/ColorFilter;IIILjava/lang/Object;)Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->configurePaint-2qPWKa0(JLandroidx/compose/ui/graphics/drawscope/DrawStyle;FLandroidx/compose/ui/graphics/ColorFilter;II)Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->configurePaint-swdJneE$default(Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope;Landroidx/compose/ui/graphics/Brush;Landroidx/compose/ui/graphics/drawscope/DrawStyle;FLandroidx/compose/ui/graphics/ColorFilter;IIILjava/lang/Object;)Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->configurePaint-swdJneE(Landroidx/compose/ui/graphics/Brush;Landroidx/compose/ui/graphics/drawscope/DrawStyle;FLandroidx/compose/ui/graphics/ColorFilter;II)Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->drawImage-AZ2fEMs(Landroidx/compose/ui/graphics/ImageBitmap;JJJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;II)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->drawPath-GBMwjPU(Landroidx/compose/ui/graphics/Path;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->drawPath-LG529CI(Landroidx/compose/ui/graphics/Path;JFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->drawRect-n-J9OG0(JJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->drawRoundRect-u-Aw5IA(JJJJLandroidx/compose/ui/graphics/drawscope/DrawStyle;FLandroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->getDensity()F
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->getDrawContext()Landroidx/compose/ui/graphics/drawscope/DrawContext;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->getDrawParams()Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->modulate-5vOe2sY(JF)J
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->obtainFillPaint()Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScope;->selectPaint(Landroidx/compose/ui/graphics/drawscope/DrawStyle;)Landroidx/compose/ui/graphics/Paint;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt$asDrawTransform$1;-><init>(Landroidx/compose/ui/graphics/drawscope/DrawContext;)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt$asDrawTransform$1;->getSize-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt$asDrawTransform$1;->inset(FFFF)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt$asDrawTransform$1;->transform-58bKbWc([F)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt$asDrawTransform$1;->translate(FF)V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt;->access$asDrawTransform(Landroidx/compose/ui/graphics/drawscope/DrawContext;)Landroidx/compose/ui/graphics/drawscope/DrawTransform;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt;->access$getDefaultDensity$p()Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt;->asDrawTransform(Landroidx/compose/ui/graphics/drawscope/DrawContext;)Landroidx/compose/ui/graphics/drawscope/DrawTransform;
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope$Companion;->getDefaultBlendMode-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope$Companion;->getDefaultFilterQuality-f-v9h1I()I
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope;->drawImage-AZ2fEMs$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/graphics/ImageBitmap;JJJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;IIILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope;->drawPath-GBMwjPU$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/graphics/Path;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;IILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope;->drawRect-n-J9OG0$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;JJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;IILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope;->getSize-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/drawscope/DrawScope;->offsetSize-PENXr5M(JJ)J
-HSPLandroidx/compose/ui/graphics/drawscope/DrawStyle;-><init>()V
-HSPLandroidx/compose/ui/graphics/drawscope/DrawStyle;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/drawscope/EmptyCanvas;-><init>()V
-HSPLandroidx/compose/ui/graphics/drawscope/Fill;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/drawscope/Fill;-><init>()V
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;-><init>(Landroidx/compose/ui/graphics/ImageBitmap;JJ)V
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;-><init>(Landroidx/compose/ui/graphics/ImageBitmap;JJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;->getIntrinsicSize-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;->onDraw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;->setFilterQuality-vDHp3xo$ui_graphics_release(I)V
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;->validateSize-N5eqBDc(JJ)J
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainterKt;->BitmapPainter-QZhYCtY$default(Landroidx/compose/ui/graphics/ImageBitmap;JJIILjava/lang/Object;)Landroidx/compose/ui/graphics/painter/BitmapPainter;
-HSPLandroidx/compose/ui/graphics/painter/BitmapPainterKt;->BitmapPainter-QZhYCtY(Landroidx/compose/ui/graphics/ImageBitmap;JJI)Landroidx/compose/ui/graphics/painter/BitmapPainter;
-HSPLandroidx/compose/ui/graphics/painter/Painter$drawLambda$1;-><init>(Landroidx/compose/ui/graphics/painter/Painter;)V
-HSPLandroidx/compose/ui/graphics/painter/Painter;-><init>()V
-HSPLandroidx/compose/ui/graphics/painter/Painter;->configureAlpha(F)V
-HSPLandroidx/compose/ui/graphics/painter/Painter;->configureColorFilter(Landroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/painter/Painter;->configureLayoutDirection(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/graphics/painter/Painter;->draw-x_KDEd0(Landroidx/compose/ui/graphics/drawscope/DrawScope;JFLandroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/vector/DrawCache;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/DrawCache;->clear(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/ui/graphics/vector/DrawCache;->drawCachedImage-CJJAR-o(JLandroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/graphics/vector/DrawCache;->drawInto(Landroidx/compose/ui/graphics/drawscope/DrawScope;FLandroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->draw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->getInvalidateListener$ui_release()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->getNumChildren()I
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->getWillClipPath()Z
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->insertAt(ILandroidx/compose/ui/graphics/vector/VNode;)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->remove(II)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->setInvalidateListener$ui_release(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->setName(Ljava/lang/String;)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->setPivotX(F)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->setPivotY(F)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->setScaleX(F)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->setScaleY(F)V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->updateClipPath()V
-HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->updateMatrix()V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;-><init>(Ljava/lang/String;FFFFFFFLjava/util/List;Ljava/util/List;)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;-><init>(Ljava/lang/String;FFFFFFFLjava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getChildren()Ljava/util/List;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getClipPathData()Ljava/util/List;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getName()Ljava/lang/String;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getPivotX()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getPivotY()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getRotate()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getScaleX()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getScaleY()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getTranslationX()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;->getTranslationY()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;-><init>(Ljava/lang/String;FFFFJIZ)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;-><init>(Ljava/lang/String;FFFFJIZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;-><init>(Ljava/lang/String;FFFFJIZLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;->addPath-oIyEayM$default(Landroidx/compose/ui/graphics/vector/ImageVector$Builder;Ljava/util/List;ILjava/lang/String;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Brush;FFIIFFFFILjava/lang/Object;)Landroidx/compose/ui/graphics/vector/ImageVector$Builder;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;->addPath-oIyEayM(Ljava/util/List;ILjava/lang/String;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Brush;FFIIFFFF)Landroidx/compose/ui/graphics/vector/ImageVector$Builder;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;->asVectorGroup(Landroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;)Landroidx/compose/ui/graphics/vector/VectorGroup;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;->build()Landroidx/compose/ui/graphics/vector/ImageVector;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;->ensureNotConsumed()V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Builder;->getCurrentGroup()Landroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Companion;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;-><init>(Ljava/lang/String;FFFFLandroidx/compose/ui/graphics/vector/VectorGroup;JIZ)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;-><init>(Ljava/lang/String;FFFFLandroidx/compose/ui/graphics/vector/VectorGroup;JIZLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getAutoMirror()Z
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getDefaultHeight-D9Ej5fM()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getDefaultWidth-D9Ej5fM()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getName()Ljava/lang/String;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getRoot()Landroidx/compose/ui/graphics/vector/VectorGroup;
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getTintBlendMode-0nO6VwU()I
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getTintColor-0d7_KjU()J
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getViewportHeight()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVector;->getViewportWidth()F
-HSPLandroidx/compose/ui/graphics/vector/ImageVectorKt;->access$peek(Ljava/util/ArrayList;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/ImageVectorKt;->access$push(Ljava/util/ArrayList;Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/vector/ImageVectorKt;->peek(Ljava/util/ArrayList;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/ImageVectorKt;->push(Ljava/util/ArrayList;Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->addNode(Landroidx/compose/ui/graphics/vector/PathNode;)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->close()Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->getNodes()Ljava/util/List;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->horizontalLineTo(F)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->horizontalLineToRelative(F)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->lineTo(FF)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->lineToRelative(FF)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->moveTo(FF)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->verticalLineTo(F)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->verticalLineToRelative(F)Landroidx/compose/ui/graphics/vector/PathBuilder;
-HSPLandroidx/compose/ui/graphics/vector/PathComponent$pathMeasure$2;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent$pathMeasure$2;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->draw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setFill(Landroidx/compose/ui/graphics/Brush;)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setFillAlpha(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setName(Ljava/lang/String;)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setPathData(Ljava/util/List;)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setPathFillType-oQ8Xj4U(I)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setStroke(Landroidx/compose/ui/graphics/Brush;)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setStrokeAlpha(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setStrokeLineCap-BeK7IIE(I)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setStrokeLineJoin-Ww9F2mQ(I)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setStrokeLineMiter(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setStrokeLineWidth(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setTrimPathEnd(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setTrimPathOffset(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->setTrimPathStart(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->updatePath()V
-HSPLandroidx/compose/ui/graphics/vector/PathComponent;->updateRenderPath()V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$Close;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$Close;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$HorizontalTo;-><init>(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$HorizontalTo;->getX()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$LineTo;-><init>(FF)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$LineTo;->getX()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$LineTo;->getY()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$MoveTo;-><init>(FF)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$MoveTo;->getX()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$MoveTo;->getY()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeHorizontalTo;-><init>(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeHorizontalTo;->getDx()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeLineTo;-><init>(FF)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeLineTo;->getDx()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeLineTo;->getDy()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeVerticalTo;-><init>(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$RelativeVerticalTo;->getDy()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode$VerticalTo;-><init>(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode$VerticalTo;->getY()F
-HSPLandroidx/compose/ui/graphics/vector/PathNode;-><init>(ZZ)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode;-><init>(ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/PathNode;-><init>(ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;-><init>(FF)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;-><init>(FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;->getX()F
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;->getY()F
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;->reset()V
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;->setX(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser$PathPoint;->setY(F)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->addPathNodes(Ljava/util/List;)Landroidx/compose/ui/graphics/vector/PathParser;
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->clear()V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->close(Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->horizontalTo(Landroidx/compose/ui/graphics/vector/PathNode$HorizontalTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->lineTo(Landroidx/compose/ui/graphics/vector/PathNode$LineTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->moveTo(Landroidx/compose/ui/graphics/vector/PathNode$MoveTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->relativeHorizontalTo(Landroidx/compose/ui/graphics/vector/PathNode$RelativeHorizontalTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->relativeLineTo(Landroidx/compose/ui/graphics/vector/PathNode$RelativeLineTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->relativeVerticalTo(Landroidx/compose/ui/graphics/vector/PathNode$RelativeVerticalTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->toPath(Landroidx/compose/ui/graphics/Path;)Landroidx/compose/ui/graphics/Path;
-HSPLandroidx/compose/ui/graphics/vector/PathParser;->verticalTo(Landroidx/compose/ui/graphics/vector/PathNode$VerticalTo;Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/graphics/vector/VNode;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VNode;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VNode;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/VNode;->getInvalidateListener$ui_release()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/graphics/vector/VNode;->invalidate()V
-HSPLandroidx/compose/ui/graphics/vector/VNode;->setInvalidateListener$ui_release(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;-><init>(Landroidx/compose/ui/graphics/vector/VNode;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->asGroup(Landroidx/compose/ui/graphics/vector/VNode;)Landroidx/compose/ui/graphics/vector/GroupComponent;
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->insertBottomUp(ILandroidx/compose/ui/graphics/vector/VNode;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->insertBottomUp(ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->insertTopDown(ILandroidx/compose/ui/graphics/vector/VNode;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->insertTopDown(ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->onClear()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$drawVectorBlock$1;-><init>(Landroidx/compose/ui/graphics/vector/VectorComponent;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$drawVectorBlock$1;->invoke(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$drawVectorBlock$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$invalidateCallback$1;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$invalidateCallback$1;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$root$1$1;-><init>(Landroidx/compose/ui/graphics/vector/VectorComponent;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$root$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent$root$1$1;->invoke()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->access$doInvalidate(Landroidx/compose/ui/graphics/vector/VectorComponent;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->doInvalidate()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->draw(Landroidx/compose/ui/graphics/drawscope/DrawScope;FLandroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->getRoot()Landroidx/compose/ui/graphics/vector/GroupComponent;
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->getViewportHeight()F
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->getViewportWidth()F
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->setIntrinsicColorFilter$ui_release(Landroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->setInvalidateCallback$ui_release(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->setName(Ljava/lang/String;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->setViewportHeight(F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->setViewportWidth(F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$1;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$1;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$1;->invoke()Landroidx/compose/ui/graphics/vector/PathComponent;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$10;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$10;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$10;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$10;->invoke-CSYIeUk(Landroidx/compose/ui/graphics/vector/PathComponent;I)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$11;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$11;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$11;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$11;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$12;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$12;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$12;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$12;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$13;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$13;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$13;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$13;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$14;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$14;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$14;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$14;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$1;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$1;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$1;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;Ljava/lang/String;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$2;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$2;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$2;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;Ljava/util/List;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$3;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$3;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$3;->invoke-pweu1eQ(Landroidx/compose/ui/graphics/vector/PathComponent;I)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$4;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$4;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$4;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;Landroidx/compose/ui/graphics/Brush;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$5;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$5;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$5;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$5;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$6;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$6;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$6;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;Landroidx/compose/ui/graphics/Brush;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$6;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$7;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$7;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$7;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$7;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$8;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$8;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$8;->invoke(Landroidx/compose/ui/graphics/vector/PathComponent;F)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$8;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$9;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$9;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$9;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$9;->invoke-kLtJ_vA(Landroidx/compose/ui/graphics/vector/PathComponent;I)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path-9cdaXJ4$$inlined$ComposeNode$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt$Path-9cdaXJ4$$inlined$ComposeNode$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt;->Path-9cdaXJ4(Ljava/util/List;ILjava/lang/String;Landroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Brush;FFIIFFFFLandroidx/compose/runtime/Composer;III)V
-HSPLandroidx/compose/ui/graphics/vector/VectorConfig;->getOrDefault(Landroidx/compose/ui/graphics/vector/VectorProperty;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup$iterator$1;-><init>(Landroidx/compose/ui/graphics/vector/VectorGroup;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup$iterator$1;->hasNext()Z
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup$iterator$1;->next()Landroidx/compose/ui/graphics/vector/VectorNode;
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup$iterator$1;->next()Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup;-><init>(Ljava/lang/String;FFFFFFFLjava/util/List;Ljava/util/List;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup;->access$getChildren$p(Landroidx/compose/ui/graphics/vector/VectorGroup;)Ljava/util/List;
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/graphics/vector/VectorGroup;->iterator()Ljava/util/Iterator;
-HSPLandroidx/compose/ui/graphics/vector/VectorKt;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorKt;->getDefaultFillType()I
-HSPLandroidx/compose/ui/graphics/vector/VectorKt;->getDefaultStrokeLineCap()I
-HSPLandroidx/compose/ui/graphics/vector/VectorKt;->getDefaultStrokeLineJoin()I
-HSPLandroidx/compose/ui/graphics/vector/VectorKt;->getEmptyPath()Ljava/util/List;
-HSPLandroidx/compose/ui/graphics/vector/VectorNode;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorNode;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorNode;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/Composition;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2;-><init>(Landroidx/compose/runtime/Composition;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$composeVector$1;-><init>(Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/graphics/vector/VectorPainter;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$composeVector$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$composeVector$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$vector$1$1;-><init>(Landroidx/compose/ui/graphics/vector/VectorPainter;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$vector$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter$vector$1$1;->invoke()V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->RenderVector$ui_release(Ljava/lang/String;FFLkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->access$getVector$p(Landroidx/compose/ui/graphics/vector/VectorPainter;)Landroidx/compose/ui/graphics/vector/VectorComponent;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->access$setDirty(Landroidx/compose/ui/graphics/vector/VectorPainter;Z)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->applyColorFilter(Landroidx/compose/ui/graphics/ColorFilter;)Z
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->composeVector(Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function4;)Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->getAutoMirror$ui_release()Z
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->getIntrinsicSize-NH-jbRc()J
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->getSize-NH-jbRc$ui_release()J
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->isDirty()Z
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->onDraw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->setAutoMirror$ui_release(Z)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->setDirty(Z)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->setIntrinsicColorFilter$ui_release(Landroidx/compose/ui/graphics/ColorFilter;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainter;->setSize-uvyYCjk$ui_release(J)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt$RenderVectorGroup$config$1;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt$rememberVectorPainter$3;-><init>(Landroidx/compose/ui/graphics/vector/ImageVector;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt$rememberVectorPainter$3;->invoke(FFLandroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt$rememberVectorPainter$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt;->RenderVectorGroup(Landroidx/compose/ui/graphics/vector/VectorGroup;Ljava/util/Map;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt;->rememberVectorPainter(Landroidx/compose/ui/graphics/vector/ImageVector;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/vector/VectorPainter;
-HSPLandroidx/compose/ui/graphics/vector/VectorPainterKt;->rememberVectorPainter-vIP8VLU(FFFFLjava/lang/String;JIZLkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)Landroidx/compose/ui/graphics/vector/VectorPainter;
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;-><init>(Ljava/lang/String;Ljava/util/List;ILandroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Brush;FFIIFFFF)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;-><init>(Ljava/lang/String;Ljava/util/List;ILandroidx/compose/ui/graphics/Brush;FLandroidx/compose/ui/graphics/Brush;FFIIFFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getFill()Landroidx/compose/ui/graphics/Brush;
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getFillAlpha()F
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getName()Ljava/lang/String;
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getPathData()Ljava/util/List;
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getPathFillType-Rg-k1Os()I
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getStroke()Landroidx/compose/ui/graphics/Brush;
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getStrokeAlpha()F
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getStrokeLineCap-KaPHkGw()I
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getStrokeLineJoin-LxFBmk8()I
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getStrokeLineMiter()F
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getStrokeLineWidth()F
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getTrimPathEnd()F
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getTrimPathOffset()F
-HSPLandroidx/compose/ui/graphics/vector/VectorPath;->getTrimPathStart()F
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$Fill;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$Fill;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$FillAlpha;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$FillAlpha;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$PathData;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$PathData;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$Stroke;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$Stroke;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$StrokeAlpha;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$StrokeAlpha;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$StrokeLineWidth;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$StrokeLineWidth;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$TrimPathEnd;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$TrimPathEnd;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$TrimPathOffset;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$TrimPathOffset;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$TrimPathStart;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty$TrimPathStart;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty;-><clinit>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty;-><init>()V
-HSPLandroidx/compose/ui/graphics/vector/VectorProperty;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/hapticfeedback/PlatformHapticFeedback;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/ui/input/InputMode$Companion;-><init>()V
-HSPLandroidx/compose/ui/input/InputMode$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/InputMode$Companion;->getTouch-aOaMEAU()I
-HSPLandroidx/compose/ui/input/InputMode;-><clinit>()V
-HSPLandroidx/compose/ui/input/InputMode;-><init>(I)V
-HSPLandroidx/compose/ui/input/InputMode;->access$getTouch$cp()I
-HSPLandroidx/compose/ui/input/InputMode;->box-impl(I)Landroidx/compose/ui/input/InputMode;
-HSPLandroidx/compose/ui/input/InputMode;->constructor-impl(I)I
-HSPLandroidx/compose/ui/input/InputMode;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/input/InputMode;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/input/InputMode;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/input/InputMode;->unbox-impl()I
-HSPLandroidx/compose/ui/input/InputModeManagerImpl;-><init>(ILkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/input/InputModeManagerImpl;-><init>(ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/InputModeManagerImpl;->getInputMode-aOaMEAU()I
-HSPLandroidx/compose/ui/input/InputModeManagerImpl;->setInputMode-iuPiT84(I)V
-HSPLandroidx/compose/ui/input/key/KeyInputInputModifierNodeImpl;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/input/key/KeyInputInputModifierNodeImpl;->setOnEvent(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/input/key/KeyInputModifierKt$onKeyEvent$$inlined$modifierElementOf$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/input/key/KeyInputModifierKt$onKeyEvent$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/input/key/KeyInputModifierKt$onKeyEvent$$inlined$modifierElementOf$2;->update(Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/input/key/KeyInputModifierKt;->onKeyEvent(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher$calculateNestedScrollScope$1;-><init>(Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;-><clinit>()V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;-><init>()V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;->setCalculateNestedScrollScope$ui_release(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;->setOriginNestedScrollScope$ui_release(Lkotlinx/coroutines/CoroutineScope;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;->setParent$ui_release(Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt$nestedScroll$2;-><init>(Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt$nestedScroll$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt$nestedScroll$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt;->nestedScroll$default(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;ILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt;->nestedScroll(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal$1;-><init>(Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;-><init>(Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;->getKey()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;->getParent()Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;->getValue()Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;->onModifierLocalsUpdated(Landroidx/compose/ui/modifier/ModifierLocalReadScope;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;->setParent(Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;)V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt$ModifierLocalNestedScroll$1;-><clinit>()V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt$ModifierLocalNestedScroll$1;-><init>()V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt$ModifierLocalNestedScroll$1;->invoke()Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt$ModifierLocalNestedScroll$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt;-><clinit>()V
-HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt;->getModifierLocalNestedScroll()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/ui/input/pointer/AwaitPointerEventScope;->awaitPointerEvent$default(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Landroidx/compose/ui/input/pointer/PointerEventPass;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/ConsumedData;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/ConsumedData;-><init>(ZZ)V
-HSPLandroidx/compose/ui/input/pointer/ConsumedData;->getDownChange()Z
-HSPLandroidx/compose/ui/input/pointer/ConsumedData;->getPositionChange()Z
-HSPLandroidx/compose/ui/input/pointer/ConsumedData;->setDownChange(Z)V
-HSPLandroidx/compose/ui/input/pointer/ConsumedData;->setPositionChange(Z)V
-HSPLandroidx/compose/ui/input/pointer/HitPathTracker;-><init>(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/ui/input/pointer/HitPathTracker;->addHitPath-KNwqfcY(JLjava/util/List;)V
-HSPLandroidx/compose/ui/input/pointer/HitPathTracker;->dispatchChanges(Landroidx/compose/ui/input/pointer/InternalPointerEvent;Z)Z
-HSPLandroidx/compose/ui/input/pointer/HitPathTracker;->removeDetachedPointerInputFilters()V
-HSPLandroidx/compose/ui/input/pointer/InternalPointerEvent;-><init>(Ljava/util/Map;Landroidx/compose/ui/input/pointer/PointerInputEvent;)V
-HSPLandroidx/compose/ui/input/pointer/InternalPointerEvent;->getChanges()Ljava/util/Map;
-HSPLandroidx/compose/ui/input/pointer/InternalPointerEvent;->getMotionEvent()Landroid/view/MotionEvent;
-HSPLandroidx/compose/ui/input/pointer/InternalPointerEvent;->getSuppressMovementConsumption()Z
-HSPLandroidx/compose/ui/input/pointer/InternalPointerEvent;->issuesEnterExitEvent-0FcD4WY(J)Z
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->addFreshIds(Landroid/view/MotionEvent;)V
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->clearOnDeviceChange(Landroid/view/MotionEvent;)V
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->convertToPointerInputEvent$ui_release(Landroid/view/MotionEvent;Landroidx/compose/ui/input/pointer/PositionCalculator;)Landroidx/compose/ui/input/pointer/PointerInputEvent;
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->createPointerInputEventData(Landroidx/compose/ui/input/pointer/PositionCalculator;Landroid/view/MotionEvent;IZ)Landroidx/compose/ui/input/pointer/PointerInputEventData;
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->getComposePointerId-_I2yYro(I)J
-HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->removeStaleIds(Landroid/view/MotionEvent;)V
-HSPLandroidx/compose/ui/input/pointer/Node;-><init>(Landroidx/compose/ui/node/PointerInputModifierNode;)V
-HSPLandroidx/compose/ui/input/pointer/Node;->buildCache(Ljava/util/Map;Landroidx/compose/ui/layout/LayoutCoordinates;Landroidx/compose/ui/input/pointer/InternalPointerEvent;Z)Z
-HSPLandroidx/compose/ui/input/pointer/Node;->cleanUpHits(Landroidx/compose/ui/input/pointer/InternalPointerEvent;)V
-HSPLandroidx/compose/ui/input/pointer/Node;->clearCache()V
-HSPLandroidx/compose/ui/input/pointer/Node;->dispatchFinalEventPass(Landroidx/compose/ui/input/pointer/InternalPointerEvent;)Z
-HSPLandroidx/compose/ui/input/pointer/Node;->dispatchMainEventPass(Ljava/util/Map;Landroidx/compose/ui/layout/LayoutCoordinates;Landroidx/compose/ui/input/pointer/InternalPointerEvent;Z)Z
-HSPLandroidx/compose/ui/input/pointer/Node;->getPointerIds()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/input/pointer/Node;->getPointerInputNode()Landroidx/compose/ui/node/PointerInputModifierNode;
-HSPLandroidx/compose/ui/input/pointer/NodeParent;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/NodeParent;->buildCache(Ljava/util/Map;Landroidx/compose/ui/layout/LayoutCoordinates;Landroidx/compose/ui/input/pointer/InternalPointerEvent;Z)Z
-HSPLandroidx/compose/ui/input/pointer/NodeParent;->cleanUpHits(Landroidx/compose/ui/input/pointer/InternalPointerEvent;)V
-HSPLandroidx/compose/ui/input/pointer/NodeParent;->dispatchFinalEventPass(Landroidx/compose/ui/input/pointer/InternalPointerEvent;)Z
-HSPLandroidx/compose/ui/input/pointer/NodeParent;->dispatchMainEventPass(Ljava/util/Map;Landroidx/compose/ui/layout/LayoutCoordinates;Landroidx/compose/ui/input/pointer/InternalPointerEvent;Z)Z
-HSPLandroidx/compose/ui/input/pointer/NodeParent;->getChildren()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/input/pointer/NodeParent;->removeDetachedPointerInputFilters()V
-HSPLandroidx/compose/ui/input/pointer/PointerButtons;->constructor-impl(I)I
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;-><init>(Ljava/util/List;)V
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;-><init>(Ljava/util/List;Landroidx/compose/ui/input/pointer/InternalPointerEvent;)V
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;->calculatePointerEventType-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;->getChanges()Ljava/util/List;
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;->getMotionEvent$ui_release()Landroid/view/MotionEvent;
-HSPLandroidx/compose/ui/input/pointer/PointerEvent;->getType-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->changedToDown(Landroidx/compose/ui/input/pointer/PointerInputChange;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->changedToDownIgnoreConsumed(Landroidx/compose/ui/input/pointer/PointerInputChange;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->changedToUp(Landroidx/compose/ui/input/pointer/PointerInputChange;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->changedToUpIgnoreConsumed(Landroidx/compose/ui/input/pointer/PointerInputChange;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->positionChangeInternal(Landroidx/compose/ui/input/pointer/PointerInputChange;Z)J
-HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->positionChangedIgnoreConsumed(Landroidx/compose/ui/input/pointer/PointerInputChange;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerEventPass;->$values()[Landroidx/compose/ui/input/pointer/PointerEventPass;
-HSPLandroidx/compose/ui/input/pointer/PointerEventPass;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/PointerEventPass;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/input/pointer/PointerEventPass;->values()[Landroidx/compose/ui/input/pointer/PointerEventPass;
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;->getEnter-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;->getExit-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;->getMove-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;->getPress-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType$Companion;->getRelease-7fucELk()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->access$getEnter$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->access$getExit$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->access$getMove$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->access$getPress$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->access$getRelease$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->constructor-impl(I)I
-HSPLandroidx/compose/ui/input/pointer/PointerEventType;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/input/pointer/PointerEvent_androidKt;->EmptyPointerKeyboardModifiers()I
-HSPLandroidx/compose/ui/input/pointer/PointerId;-><init>(J)V
-HSPLandroidx/compose/ui/input/pointer/PointerId;->box-impl(J)Landroidx/compose/ui/input/pointer/PointerId;
-HSPLandroidx/compose/ui/input/pointer/PointerId;->constructor-impl(J)J
-HSPLandroidx/compose/ui/input/pointer/PointerId;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerId;->equals-impl(JLjava/lang/Object;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerId;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/input/pointer/PointerId;->hashCode()I
-HSPLandroidx/compose/ui/input/pointer/PointerId;->hashCode-impl(J)I
-HSPLandroidx/compose/ui/input/pointer/PointerId;->unbox-impl()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><init>(JJJZFJJZZIJ)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><init>(JJJZFJJZZIJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><init>(JJJZFJJZZILjava/util/List;J)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><init>(JJJZFJJZZILjava/util/List;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><init>(JJJZJJZZIJ)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;-><init>(JJJZJJZZIJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->consume()V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->copy-OHpmEuE$default(Landroidx/compose/ui/input/pointer/PointerInputChange;JJJZJJZILjava/util/List;JILjava/lang/Object;)Landroidx/compose/ui/input/pointer/PointerInputChange;
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->copy-OHpmEuE(JJJZJJZILjava/util/List;J)Landroidx/compose/ui/input/pointer/PointerInputChange;
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getHistorical()Ljava/util/List;
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getId-J3iCeTQ()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getPosition-F1C5BW0()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getPressed()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getPressure()F
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getPreviousPosition-F1C5BW0()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getPreviousPressed()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getType-T8wyACA()I
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->getUptimeMillis()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->isConsumed()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer$PointerInputData;-><init>(JJZI)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer$PointerInputData;-><init>(JJZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer$PointerInputData;->getDown()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer$PointerInputData;->getPositionOnScreen-F1C5BW0()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer$PointerInputData;->getUptime()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer;->produce(Landroidx/compose/ui/input/pointer/PointerInputEvent;Landroidx/compose/ui/input/pointer/PositionCalculator;)Landroidx/compose/ui/input/pointer/InternalPointerEvent;
-HSPLandroidx/compose/ui/input/pointer/PointerInputEvent;-><init>(JLjava/util/List;Landroid/view/MotionEvent;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputEvent;->getMotionEvent()Landroid/view/MotionEvent;
-HSPLandroidx/compose/ui/input/pointer/PointerInputEvent;->getPointers()Ljava/util/List;
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;-><init>(JJJJZFIZLjava/util/List;J)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;-><init>(JJJJZFIZLjava/util/List;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getDown()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getHistorical()Ljava/util/List;
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getId-J3iCeTQ()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getIssuesEnterExit()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getPosition-F1C5BW0()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getPositionOnScreen-F1C5BW0()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getPressure()F
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getScrollDelta-F1C5BW0()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getType-T8wyACA()I
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->getUptime()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventProcessor;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventProcessor;->process-BIzXfog(Landroidx/compose/ui/input/pointer/PointerInputEvent;Landroidx/compose/ui/input/pointer/PositionCalculator;Z)I
-HSPLandroidx/compose/ui/input/pointer/PointerInputEventProcessorKt;->ProcessResult(ZZ)I
-HSPLandroidx/compose/ui/input/pointer/PointerInputFilter;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/PointerInputFilter;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/PointerInputFilter;->getShareWithSiblings()Z
-HSPLandroidx/compose/ui/input/pointer/PointerInputFilter;->getSize-YbymL2g()J
-HSPLandroidx/compose/ui/input/pointer/PointerInputFilter;->setLayoutCoordinates$ui_release(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/ui/input/pointer/PointerKeyboardModifiers;-><init>(I)V
-HSPLandroidx/compose/ui/input/pointer/PointerKeyboardModifiers;->box-impl(I)Landroidx/compose/ui/input/pointer/PointerKeyboardModifiers;
-HSPLandroidx/compose/ui/input/pointer/PointerKeyboardModifiers;->constructor-impl(I)I
-HSPLandroidx/compose/ui/input/pointer/PointerKeyboardModifiers;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerKeyboardModifiers;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/input/pointer/PointerKeyboardModifiers;->unbox-impl()I
-HSPLandroidx/compose/ui/input/pointer/PointerType$Companion;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/PointerType$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/PointerType$Companion;->getMouse-T8wyACA()I
-HSPLandroidx/compose/ui/input/pointer/PointerType$Companion;->getTouch-T8wyACA()I
-HSPLandroidx/compose/ui/input/pointer/PointerType;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/PointerType;->access$getMouse$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerType;->access$getTouch$cp()I
-HSPLandroidx/compose/ui/input/pointer/PointerType;->constructor-impl(I)I
-HSPLandroidx/compose/ui/input/pointer/PointerType;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/input/pointer/ProcessResult;->constructor-impl(I)I
-HSPLandroidx/compose/ui/input/pointer/ProcessResult;->getAnyMovementConsumed-impl(I)Z
-HSPLandroidx/compose/ui/input/pointer/ProcessResult;->getDispatchedToAPointerInputModifier-impl(I)Z
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;-><init>(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->access$setAwaitPass$p(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;Landroidx/compose/ui/input/pointer/PointerEventPass;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->access$setPointerAwaiter$p(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;Lkotlinx/coroutines/CancellableContinuation;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->awaitPointerEvent(Landroidx/compose/ui/input/pointer/PointerEventPass;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->cancel(Ljava/lang/Throwable;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->getCurrentEvent()Landroidx/compose/ui/input/pointer/PointerEvent;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->getViewConfiguration()Landroidx/compose/ui/platform/ViewConfiguration;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->offerPointerEvent(Landroidx/compose/ui/input/pointer/PointerEvent;Landroidx/compose/ui/input/pointer/PointerEventPass;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->resumeWith(Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$awaitPointerEventScope$2$2;-><init>(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$awaitPointerEventScope$2$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$awaitPointerEventScope$2$2;->invoke(Ljava/lang/Throwable;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;-><init>(Landroidx/compose/ui/platform/ViewConfiguration;Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->access$getCurrentEvent$p(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;)Landroidx/compose/ui/input/pointer/PointerEvent;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->access$getPointerHandlers$p(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;)Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->awaitPointerEventScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->dispatchPointerEvent(Landroidx/compose/ui/input/pointer/PointerEvent;Landroidx/compose/ui/input/pointer/PointerEventPass;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->getPointerInputFilter()Landroidx/compose/ui/input/pointer/PointerInputFilter;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->getViewConfiguration()Landroidx/compose/ui/platform/ViewConfiguration;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->onPointerEvent-H0pRuoY(Landroidx/compose/ui/input/pointer/PointerEvent;Landroidx/compose/ui/input/pointer/PointerEventPass;J)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->setCoroutineScope(Lkotlinx/coroutines/CoroutineScope;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2$2$1;-><init>(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4$2$1;-><init>(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4;-><init>(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6$2$1;-><init>(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6;-><init>([Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;->access$getEmptyPointerEvent$p()Landroidx/compose/ui/input/pointer/PointerEvent;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;->pointerInput(Landroidx/compose/ui/Modifier;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;->pointerInput(Landroidx/compose/ui/Modifier;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;->pointerInput(Landroidx/compose/ui/Modifier;[Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/pointer/util/DataPointAtTime;-><init>(JF)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;->$values()[Landroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;->values()[Landroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D;-><init>(ZLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D;-><init>(ZLandroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D;->addDataPoint(JF)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker1D;->resetTracking()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;-><clinit>()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;-><init>()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;->addPosition-Uv8p0NA(JJ)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;->getCurrentPointerPositionAccumulator-F1C5BW0$ui_release()J
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;->resetTracking()V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;->setCurrentPointerPositionAccumulator-k-4lQ0M$ui_release(J)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTrackerKt;->access$set([Landroidx/compose/ui/input/pointer/util/DataPointAtTime;IJF)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTrackerKt;->addPointerInputChange(Landroidx/compose/ui/input/pointer/util/VelocityTracker;Landroidx/compose/ui/input/pointer/PointerInputChange;)V
-HSPLandroidx/compose/ui/input/pointer/util/VelocityTrackerKt;->set([Landroidx/compose/ui/input/pointer/util/DataPointAtTime;IJF)V
-HSPLandroidx/compose/ui/input/rotary/RotaryInputModifierKt$onRotaryScrollEvent$$inlined$modifierElementOf$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/input/rotary/RotaryInputModifierKt$onRotaryScrollEvent$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/input/rotary/RotaryInputModifierKt;->onRotaryScrollEvent(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/input/rotary/RotaryInputModifierNodeImpl;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/AlignmentLine$Companion;-><init>()V
-HSPLandroidx/compose/ui/layout/AlignmentLine$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/layout/AlignmentLine;-><clinit>()V
-HSPLandroidx/compose/ui/layout/AlignmentLine;-><init>(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/layout/AlignmentLine;-><init>(Lkotlin/jvm/functions/Function2;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/layout/AlignmentLineKt$FirstBaseline$1;-><clinit>()V
-HSPLandroidx/compose/ui/layout/AlignmentLineKt$FirstBaseline$1;-><init>()V
-HSPLandroidx/compose/ui/layout/AlignmentLineKt$LastBaseline$1;-><clinit>()V
-HSPLandroidx/compose/ui/layout/AlignmentLineKt$LastBaseline$1;-><init>()V
-HSPLandroidx/compose/ui/layout/AlignmentLineKt;-><clinit>()V
-HSPLandroidx/compose/ui/layout/AlignmentLineKt;->getFirstBaseline()Landroidx/compose/ui/layout/HorizontalAlignmentLine;
-HSPLandroidx/compose/ui/layout/AlignmentLineKt;->getLastBaseline()Landroidx/compose/ui/layout/HorizontalAlignmentLine;
-HSPLandroidx/compose/ui/layout/BeyondBoundsLayoutKt$ModifierLocalBeyondBoundsLayout$1;-><clinit>()V
-HSPLandroidx/compose/ui/layout/BeyondBoundsLayoutKt$ModifierLocalBeyondBoundsLayout$1;-><init>()V
-HSPLandroidx/compose/ui/layout/BeyondBoundsLayoutKt;-><clinit>()V
-HSPLandroidx/compose/ui/layout/BeyondBoundsLayoutKt;->getModifierLocalBeyondBoundsLayout()Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt$lambda-1$1;-><clinit>()V
-HSPLandroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt$lambda-1$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt;-><clinit>()V
-HSPLandroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt;-><init>()V
-HSPLandroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt;->getLambda-1$ui_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$Crop$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$FillBounds$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$FillHeight$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$FillWidth$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$Fit$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$Fit$1;->computeScaleFactor-H7hwNQA(JJ)J
-HSPLandroidx/compose/ui/layout/ContentScale$Companion$Inside$1;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion;-><init>()V
-HSPLandroidx/compose/ui/layout/ContentScale$Companion;->getFit()Landroidx/compose/ui/layout/ContentScale;
-HSPLandroidx/compose/ui/layout/ContentScale;-><clinit>()V
-HSPLandroidx/compose/ui/layout/ContentScaleKt;->access$computeFillMinDimension-iLBOSCw(JJ)F
-HSPLandroidx/compose/ui/layout/ContentScaleKt;->computeFillHeight-iLBOSCw(JJ)F
-HSPLandroidx/compose/ui/layout/ContentScaleKt;->computeFillMinDimension-iLBOSCw(JJ)F
-HSPLandroidx/compose/ui/layout/ContentScaleKt;->computeFillWidth-iLBOSCw(JJ)F
-HSPLandroidx/compose/ui/layout/FixedScale;-><clinit>()V
-HSPLandroidx/compose/ui/layout/FixedScale;-><init>(F)V
-HSPLandroidx/compose/ui/layout/HorizontalAlignmentLine;-><clinit>()V
-HSPLandroidx/compose/ui/layout/HorizontalAlignmentLine;-><init>(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/layout/LayoutId;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/LayoutId;->getLayoutId()Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/LayoutId;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/LayoutIdKt;->getLayoutId(Landroidx/compose/ui/layout/Measurable;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/LayoutIdKt;->layoutId(Landroidx/compose/ui/Modifier;Ljava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/layout/LayoutKt$materializerOf$1;-><init>(Landroidx/compose/ui/Modifier;)V
-HSPLandroidx/compose/ui/layout/LayoutKt$materializerOf$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/LayoutKt$materializerOf$1;->invoke-Deg8D_g(Landroidx/compose/runtime/Composer;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/layout/LayoutKt;->materializerOf(Landroidx/compose/ui/Modifier;)Lkotlin/jvm/functions/Function3;
-HSPLandroidx/compose/ui/layout/LayoutModifierImpl;-><init>(Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/ui/layout/LayoutModifierImpl;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/layout/LayoutModifierKt$layout$$inlined$modifierElementOf$2;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/ui/layout/LayoutModifierKt$layout$$inlined$modifierElementOf$2;->create()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/layout/LayoutModifierKt;->layout(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function3;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composition;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;-><init>(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composition;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->getActive()Z
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->getComposition()Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->getContent()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->getForceRecompose()Z
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->setComposition(Landroidx/compose/runtime/Composition;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->setContent(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;->setForceRecompose(Z)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;-><init>(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;->getDensity()F
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;->setDensity(F)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;->setFontScale(F)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;->setLayoutDirection(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;->subcompose(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1;-><init>(Landroidx/compose/ui/layout/MeasureResult;Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;I)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1;->getAlignmentLines()Ljava/util/Map;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1;->getHeight()I
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1;->getWidth()I
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1;->placeChildren()V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1;-><init>(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;Lkotlin/jvm/functions/Function2;Ljava/lang/String;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$subcompose$3$1$1;-><init>(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$subcompose$3$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState$subcompose$3$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;-><init>(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/layout/SubcomposeSlotReusePolicy;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->access$getCurrentIndex$p(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;)I
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->access$getScope$p(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;)Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->access$setCurrentIndex$p(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;I)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->createMeasurePolicy(Lkotlin/jvm/functions/Function2;)Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->createNodeAt(I)Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->disposeCurrentNodes()V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->disposeOrReuseStartingFromIndex(I)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->forceRecomposeChildren()V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->makeSureStateIsConsistent()V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->setCompositionContext(Landroidx/compose/runtime/CompositionContext;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->setSlotReusePolicy(Landroidx/compose/ui/layout/SubcomposeSlotReusePolicy;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->subcompose(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->subcompose(Landroidx/compose/ui/node/LayoutNode;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->subcompose(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->subcomposeInto(Landroidx/compose/runtime/Composition;Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;)Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/layout/LayoutNodeSubcompositionsState;->takeNodeFromReusables(Ljava/lang/Object;)Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/layout/MeasureScope$layout$1;-><init>(IILjava/util/Map;Landroidx/compose/ui/layout/MeasureScope;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/MeasureScope$layout$1;->getAlignmentLines()Ljava/util/Map;
-HSPLandroidx/compose/ui/layout/MeasureScope$layout$1;->getHeight()I
-HSPLandroidx/compose/ui/layout/MeasureScope$layout$1;->getWidth()I
-HSPLandroidx/compose/ui/layout/MeasureScope$layout$1;->placeChildren()V
-HSPLandroidx/compose/ui/layout/MeasureScope;->layout$default(Landroidx/compose/ui/layout/MeasureScope;IILjava/util/Map;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/layout/MeasureScope;->layout(IILjava/util/Map;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/layout/NoOpSubcomposeSlotReusePolicy;-><clinit>()V
-HSPLandroidx/compose/ui/layout/NoOpSubcomposeSlotReusePolicy;-><init>()V
-HSPLandroidx/compose/ui/layout/OnGloballyPositionedModifierImpl;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/OnGloballyPositionedModifierImpl;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/layout/OnGloballyPositionedModifierImpl;->onGloballyPositioned(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/ui/layout/OnGloballyPositionedModifierKt;->onGloballyPositioned(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/layout/OnRemeasuredModifierKt;->onSizeChanged(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/layout/OnSizeChangedModifier;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/OnSizeChangedModifier;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/layout/OnSizeChangedModifier;->onRemeasured-ozmzZPI(J)V
-HSPLandroidx/compose/ui/layout/PinnableContainerKt$LocalPinnableContainer$1;-><clinit>()V
-HSPLandroidx/compose/ui/layout/PinnableContainerKt$LocalPinnableContainer$1;-><init>()V
-HSPLandroidx/compose/ui/layout/PinnableContainerKt$LocalPinnableContainer$1;->invoke()Landroidx/compose/ui/layout/PinnableContainer;
-HSPLandroidx/compose/ui/layout/PinnableContainerKt$LocalPinnableContainer$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/PinnableContainerKt;-><clinit>()V
-HSPLandroidx/compose/ui/layout/PinnableContainerKt;->getLocalPinnableContainer()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;-><init>()V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;->access$configureForPlacingForAlignment(Landroidx/compose/ui/layout/Placeable$PlacementScope$Companion;Landroidx/compose/ui/node/LookaheadCapablePlaceable;)Z
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;->access$getParentLayoutDirection(Landroidx/compose/ui/layout/Placeable$PlacementScope$Companion;)Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;->access$getParentWidth(Landroidx/compose/ui/layout/Placeable$PlacementScope$Companion;)I
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;->configureForPlacingForAlignment(Landroidx/compose/ui/node/LookaheadCapablePlaceable;)Z
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;->getParentLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope$Companion;->getParentWidth()I
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;-><clinit>()V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;-><init>()V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$getLayoutDelegate$cp()Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$getParentLayoutDirection$cp()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$getParentLayoutDirection(Landroidx/compose/ui/layout/Placeable$PlacementScope;)Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$getParentWidth$cp()I
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$get_coordinates$cp()Landroidx/compose/ui/layout/LayoutCoordinates;
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$setLayoutDelegate$cp(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$setParentLayoutDirection$cp(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$setParentWidth$cp(I)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->access$set_coordinates$cp(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->place$default(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;IIFILjava/lang/Object;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->place(Landroidx/compose/ui/layout/Placeable;IIF)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->place-70tqf50$default(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;JFILjava/lang/Object;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->place-70tqf50(Landroidx/compose/ui/layout/Placeable;JF)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeRelative$default(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;IIFILjava/lang/Object;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeRelative(Landroidx/compose/ui/layout/Placeable;IIF)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeRelativeWithLayer$default(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;IIFLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeRelativeWithLayer(Landroidx/compose/ui/layout/Placeable;IIFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeWithLayer$default(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;IIFLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeWithLayer(Landroidx/compose/ui/layout/Placeable;IIFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeWithLayer-aW-9-wM$default(Landroidx/compose/ui/layout/Placeable$PlacementScope;Landroidx/compose/ui/layout/Placeable;JFLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/layout/Placeable$PlacementScope;->placeWithLayer-aW-9-wM(Landroidx/compose/ui/layout/Placeable;JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/Placeable;-><clinit>()V
-HSPLandroidx/compose/ui/layout/Placeable;-><init>()V
-HSPLandroidx/compose/ui/layout/Placeable;->access$getApparentToRealOffset-nOcc-ac(Landroidx/compose/ui/layout/Placeable;)J
-HSPLandroidx/compose/ui/layout/Placeable;->access$placeAt-f8xVGno(Landroidx/compose/ui/layout/Placeable;JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/layout/Placeable;->getApparentToRealOffset-nOcc-ac()J
-HSPLandroidx/compose/ui/layout/Placeable;->getHeight()I
-HSPLandroidx/compose/ui/layout/Placeable;->getMeasuredHeight()I
-HSPLandroidx/compose/ui/layout/Placeable;->getMeasuredSize-YbymL2g()J
-HSPLandroidx/compose/ui/layout/Placeable;->getMeasuredWidth()I
-HSPLandroidx/compose/ui/layout/Placeable;->getMeasurementConstraints-msEJaDk()J
-HSPLandroidx/compose/ui/layout/Placeable;->getWidth()I
-HSPLandroidx/compose/ui/layout/Placeable;->recalculateWidthAndHeight()V
-HSPLandroidx/compose/ui/layout/Placeable;->setMeasuredSize-ozmzZPI(J)V
-HSPLandroidx/compose/ui/layout/Placeable;->setMeasurementConstraints-BRTryo0(J)V
-HSPLandroidx/compose/ui/layout/PlaceableKt$DefaultLayerBlock$1;-><clinit>()V
-HSPLandroidx/compose/ui/layout/PlaceableKt$DefaultLayerBlock$1;-><init>()V
-HSPLandroidx/compose/ui/layout/PlaceableKt$DefaultLayerBlock$1;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)V
-HSPLandroidx/compose/ui/layout/PlaceableKt$DefaultLayerBlock$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/PlaceableKt;-><clinit>()V
-HSPLandroidx/compose/ui/layout/PlaceableKt;->access$getDefaultConstraints$p()J
-HSPLandroidx/compose/ui/layout/PlaceableKt;->access$getDefaultLayerBlock$p()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/layout/RootMeasurePolicy$measure$2;-><init>(Landroidx/compose/ui/layout/Placeable;)V
-HSPLandroidx/compose/ui/layout/RootMeasurePolicy$measure$2;->invoke(Landroidx/compose/ui/layout/Placeable$PlacementScope;)V
-HSPLandroidx/compose/ui/layout/RootMeasurePolicy$measure$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/RootMeasurePolicy;-><clinit>()V
-HSPLandroidx/compose/ui/layout/RootMeasurePolicy;-><init>()V
-HSPLandroidx/compose/ui/layout/RootMeasurePolicy;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/layout/ScaleFactor$Companion;-><init>()V
-HSPLandroidx/compose/ui/layout/ScaleFactor$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/layout/ScaleFactor;-><clinit>()V
-HSPLandroidx/compose/ui/layout/ScaleFactor;->constructor-impl(J)J
-HSPLandroidx/compose/ui/layout/ScaleFactor;->getScaleX-impl(J)F
-HSPLandroidx/compose/ui/layout/ScaleFactor;->getScaleY-impl(J)F
-HSPLandroidx/compose/ui/layout/ScaleFactorKt;->ScaleFactor(FF)J
-HSPLandroidx/compose/ui/layout/ScaleFactorKt;->times-UQTWf7w(JJ)J
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$$inlined$ComposeNode$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$$inlined$ComposeNode$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$4;-><init>(Landroidx/compose/ui/layout/SubcomposeLayoutState;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$4;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$4;->invoke()V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1;-><init>(Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$6;-><init>(Landroidx/compose/ui/layout/SubcomposeLayoutState;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;II)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt;->SubcomposeLayout(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutKt;->SubcomposeLayout(Landroidx/compose/ui/layout/SubcomposeLayoutState;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setCompositionContext$1;-><init>(Landroidx/compose/ui/layout/SubcomposeLayoutState;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setCompositionContext$1;->invoke(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/runtime/CompositionContext;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setCompositionContext$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setMeasurePolicy$1;-><init>(Landroidx/compose/ui/layout/SubcomposeLayoutState;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setMeasurePolicy$1;->invoke(Landroidx/compose/ui/node/LayoutNode;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setMeasurePolicy$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setRoot$1;-><init>(Landroidx/compose/ui/layout/SubcomposeLayoutState;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setRoot$1;->invoke(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/layout/SubcomposeLayoutState;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState$setRoot$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;-><clinit>()V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;-><init>()V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;-><init>(Landroidx/compose/ui/layout/SubcomposeSlotReusePolicy;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->access$getSlotReusePolicy$p(Landroidx/compose/ui/layout/SubcomposeLayoutState;)Landroidx/compose/ui/layout/SubcomposeSlotReusePolicy;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->access$getState(Landroidx/compose/ui/layout/SubcomposeLayoutState;)Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->access$set_state$p(Landroidx/compose/ui/layout/SubcomposeLayoutState;Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;)V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->disposeCurrentNodes$ui_release()V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->forceRecomposeChildren$ui_release()V
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->getSetCompositionContext$ui_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->getSetMeasurePolicy$ui_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->getSetRoot$ui_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/layout/SubcomposeLayoutState;->getState()Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;
-HSPLandroidx/compose/ui/layout/SubcomposeSlotReusePolicy$SlotIdsSet;-><clinit>()V
-HSPLandroidx/compose/ui/layout/SubcomposeSlotReusePolicy$SlotIdsSet;-><init>(Ljava/util/Set;)V
-HSPLandroidx/compose/ui/layout/SubcomposeSlotReusePolicy$SlotIdsSet;-><init>(Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/modifier/BackwardsCompatLocalMap;-><init>(Landroidx/compose/ui/modifier/ModifierLocalProvider;)V
-HSPLandroidx/compose/ui/modifier/BackwardsCompatLocalMap;->contains$ui_release(Landroidx/compose/ui/modifier/ModifierLocal;)Z
-HSPLandroidx/compose/ui/modifier/BackwardsCompatLocalMap;->get$ui_release(Landroidx/compose/ui/modifier/ModifierLocal;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/modifier/EmptyMap;-><clinit>()V
-HSPLandroidx/compose/ui/modifier/EmptyMap;-><init>()V
-HSPLandroidx/compose/ui/modifier/EmptyMap;->contains$ui_release(Landroidx/compose/ui/modifier/ModifierLocal;)Z
-HSPLandroidx/compose/ui/modifier/ModifierLocal;-><clinit>()V
-HSPLandroidx/compose/ui/modifier/ModifierLocal;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/modifier/ModifierLocal;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/modifier/ModifierLocal;->getDefaultFactory$ui_release()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/modifier/ModifierLocalKt;->modifierLocalOf(Lkotlin/jvm/functions/Function0;)Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager$invalidate$1;-><init>(Landroidx/compose/ui/modifier/ModifierLocalManager;)V
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager$invalidate$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager$invalidate$1;->invoke()V
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager;-><init>(Landroidx/compose/ui/node/Owner;)V
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager;->invalidate()V
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager;->removedProvider(Landroidx/compose/ui/node/BackwardsCompatNode;Landroidx/compose/ui/modifier/ModifierLocal;)V
-HSPLandroidx/compose/ui/modifier/ModifierLocalManager;->triggerUpdates()V
-HSPLandroidx/compose/ui/modifier/ModifierLocalMap;-><clinit>()V
-HSPLandroidx/compose/ui/modifier/ModifierLocalMap;-><init>()V
-HSPLandroidx/compose/ui/modifier/ModifierLocalMap;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/modifier/ModifierLocalNode;->getProvidedValues()Landroidx/compose/ui/modifier/ModifierLocalMap;
-HSPLandroidx/compose/ui/modifier/ModifierLocalNodeKt;->modifierLocalMapOf()Landroidx/compose/ui/modifier/ModifierLocalMap;
-HSPLandroidx/compose/ui/modifier/ProvidableModifierLocal;-><clinit>()V
-HSPLandroidx/compose/ui/modifier/ProvidableModifierLocal;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/AlignmentLines$recalculate$1;-><init>(Landroidx/compose/ui/node/AlignmentLines;)V
-HSPLandroidx/compose/ui/node/AlignmentLines$recalculate$1;->invoke(Landroidx/compose/ui/node/AlignmentLinesOwner;)V
-HSPLandroidx/compose/ui/node/AlignmentLines$recalculate$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/AlignmentLines;-><init>(Landroidx/compose/ui/node/AlignmentLinesOwner;)V
-HSPLandroidx/compose/ui/node/AlignmentLines;-><init>(Landroidx/compose/ui/node/AlignmentLinesOwner;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/AlignmentLines;->access$addAlignmentLine(Landroidx/compose/ui/node/AlignmentLines;Landroidx/compose/ui/layout/AlignmentLine;ILandroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/AlignmentLines;->access$getAlignmentLineMap$p(Landroidx/compose/ui/node/AlignmentLines;)Ljava/util/Map;
-HSPLandroidx/compose/ui/node/AlignmentLines;->addAlignmentLine(Landroidx/compose/ui/layout/AlignmentLine;ILandroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/AlignmentLines;->getAlignmentLinesOwner()Landroidx/compose/ui/node/AlignmentLinesOwner;
-HSPLandroidx/compose/ui/node/AlignmentLines;->getDirty$ui_release()Z
-HSPLandroidx/compose/ui/node/AlignmentLines;->getLastCalculation()Ljava/util/Map;
-HSPLandroidx/compose/ui/node/AlignmentLines;->getQueried$ui_release()Z
-HSPLandroidx/compose/ui/node/AlignmentLines;->getRequired$ui_release()Z
-HSPLandroidx/compose/ui/node/AlignmentLines;->getUsedDuringParentLayout$ui_release()Z
-HSPLandroidx/compose/ui/node/AlignmentLines;->onAlignmentsChanged()V
-HSPLandroidx/compose/ui/node/AlignmentLines;->recalculate()V
-HSPLandroidx/compose/ui/node/AlignmentLines;->recalculateQueryOwner()V
-HSPLandroidx/compose/ui/node/AlignmentLines;->reset$ui_release()V
-HSPLandroidx/compose/ui/node/AlignmentLines;->setPreviousUsedDuringParentLayout$ui_release(Z)V
-HSPLandroidx/compose/ui/node/AlignmentLines;->setUsedByModifierLayout$ui_release(Z)V
-HSPLandroidx/compose/ui/node/AlignmentLines;->setUsedByModifierMeasurement$ui_release(Z)V
-HSPLandroidx/compose/ui/node/AlignmentLines;->setUsedDuringParentMeasurement$ui_release(Z)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode$updateModifierLocalConsumer$1;-><init>(Landroidx/compose/ui/node/BackwardsCompatNode;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode$updateModifierLocalConsumer$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode$updateModifierLocalConsumer$1;->invoke()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;-><init>(Landroidx/compose/ui/Modifier$Element;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->draw(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->getCurrent(Landroidx/compose/ui/modifier/ModifierLocal;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->getElement()Landroidx/compose/ui/Modifier$Element;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->getProvidedValues()Landroidx/compose/ui/modifier/ModifierLocalMap;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->getSemanticsConfiguration()Landroidx/compose/ui/semantics/SemanticsConfiguration;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->initializeModifier(Z)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->isValidOwnerScope()Z
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->measure-3p2s80s(Landroidx/compose/ui/layout/MeasureScope;Landroidx/compose/ui/layout/Measurable;J)Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->modifyParentData(Landroidx/compose/ui/unit/Density;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onAttach()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onDetach()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onGloballyPositioned(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onMeasureResultChanged()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onPlaced(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onPointerEvent-H0pRuoY(Landroidx/compose/ui/input/pointer/PointerEvent;Landroidx/compose/ui/input/pointer/PointerEventPass;J)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->onRemeasured-ozmzZPI(J)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->setElement(Landroidx/compose/ui/Modifier$Element;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->sharePointerInputWithSiblings()Z
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->unInitializeModifier()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->updateModifierLocalConsumer()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNode;->updateModifierLocalProvider(Landroidx/compose/ui/modifier/ModifierLocalProvider;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$DetachedModifierLocalReadScope$1;-><init>()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$DetachedModifierLocalReadScope$1;->getCurrent(Landroidx/compose/ui/modifier/ModifierLocal;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$onDrawCacheReadsChanged$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$onDrawCacheReadsChanged$1;-><init>()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$updateModifierLocalConsumer$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$updateModifierLocalConsumer$1;-><init>()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$updateModifierLocalConsumer$1;->invoke(Landroidx/compose/ui/node/BackwardsCompatNode;)V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt$updateModifierLocalConsumer$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt;-><clinit>()V
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt;->access$getDetachedModifierLocalReadScope$p()Landroidx/compose/ui/node/BackwardsCompatNodeKt$DetachedModifierLocalReadScope$1;
-HSPLandroidx/compose/ui/node/BackwardsCompatNodeKt;->access$getUpdateModifierLocalConsumer$p()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/node/CanFocusChecker;-><clinit>()V
-HSPLandroidx/compose/ui/node/CanFocusChecker;-><init>()V
-HSPLandroidx/compose/ui/node/CanFocusChecker;->isCanFocusSet()Z
-HSPLandroidx/compose/ui/node/CanFocusChecker;->reset()V
-HSPLandroidx/compose/ui/node/CanFocusChecker;->setCanFocus(Z)V
-HSPLandroidx/compose/ui/node/CenteredArray;->constructor-impl([I)[I
-HSPLandroidx/compose/ui/node/CenteredArray;->get-impl([II)I
-HSPLandroidx/compose/ui/node/CenteredArray;->getMid-impl([I)I
-HSPLandroidx/compose/ui/node/CenteredArray;->set-impl([III)V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetDensity$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetDensity$1;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetDensity$1;->invoke(Landroidx/compose/ui/node/ComposeUiNode;Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetDensity$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetLayoutDirection$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetLayoutDirection$1;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetLayoutDirection$1;->invoke(Landroidx/compose/ui/node/ComposeUiNode;Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetLayoutDirection$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetMeasurePolicy$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetMeasurePolicy$1;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetMeasurePolicy$1;->invoke(Landroidx/compose/ui/node/ComposeUiNode;Landroidx/compose/ui/layout/MeasurePolicy;)V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetMeasurePolicy$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetModifier$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetModifier$1;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetModifier$1;->invoke(Landroidx/compose/ui/node/ComposeUiNode;Landroidx/compose/ui/Modifier;)V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetModifier$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetViewConfiguration$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetViewConfiguration$1;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetViewConfiguration$1;->invoke(Landroidx/compose/ui/node/ComposeUiNode;Landroidx/compose/ui/platform/ViewConfiguration;)V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$SetViewConfiguration$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$VirtualConstructor$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion$VirtualConstructor$1;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;->getConstructor()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;->getSetDensity()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;->getSetLayoutDirection()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;->getSetMeasurePolicy()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;->getSetModifier()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/node/ComposeUiNode$Companion;->getSetViewConfiguration()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/node/ComposeUiNode;-><clinit>()V
-HSPLandroidx/compose/ui/node/DelegatableNodeKt;->has-64DMado(Landroidx/compose/ui/node/DelegatableNode;I)Z
-HSPLandroidx/compose/ui/node/DelegatableNodeKt;->localChild(Landroidx/compose/ui/node/DelegatableNode;I)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/DelegatableNodeKt;->requireCoordinator-64DMado(Landroidx/compose/ui/node/DelegatableNode;I)Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/DelegatableNodeKt;->requireLayoutNode(Landroidx/compose/ui/node/DelegatableNode;)Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/DelegatableNodeKt;->requireOwner(Landroidx/compose/ui/node/DelegatableNode;)Landroidx/compose/ui/node/Owner;
-HSPLandroidx/compose/ui/node/DepthSortedSet$DepthComparator$1;-><init>()V
-HSPLandroidx/compose/ui/node/DepthSortedSet$DepthComparator$1;->compare(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/node/LayoutNode;)I
-HSPLandroidx/compose/ui/node/DepthSortedSet$DepthComparator$1;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/node/DepthSortedSet$mapOfOriginalDepth$2;-><clinit>()V
-HSPLandroidx/compose/ui/node/DepthSortedSet$mapOfOriginalDepth$2;-><init>()V
-HSPLandroidx/compose/ui/node/DepthSortedSet;-><init>(Z)V
-HSPLandroidx/compose/ui/node/DepthSortedSet;->add(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/DepthSortedSet;->isEmpty()Z
-HSPLandroidx/compose/ui/node/DepthSortedSet;->pop()Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/DepthSortedSet;->remove(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/DistanceAndInLayer;->compareTo-S_HNhKs(JJ)I
-HSPLandroidx/compose/ui/node/DistanceAndInLayer;->constructor-impl(J)J
-HSPLandroidx/compose/ui/node/DistanceAndInLayer;->getDistance-impl(J)F
-HSPLandroidx/compose/ui/node/DistanceAndInLayer;->isInLayer-impl(J)Z
-HSPLandroidx/compose/ui/node/DrawModifierNode;->onMeasureResultChanged()V
-HSPLandroidx/compose/ui/node/DrawModifierNodeKt;->invalidateDraw(Landroidx/compose/ui/node/DrawModifierNode;)V
-HSPLandroidx/compose/ui/node/HitTestResult;-><init>()V
-HSPLandroidx/compose/ui/node/HitTestResult;->access$getHitDepth$p(Landroidx/compose/ui/node/HitTestResult;)I
-HSPLandroidx/compose/ui/node/HitTestResult;->access$setHitDepth$p(Landroidx/compose/ui/node/HitTestResult;I)V
-HSPLandroidx/compose/ui/node/HitTestResult;->clear()V
-HSPLandroidx/compose/ui/node/HitTestResult;->ensureContainerSize()V
-HSPLandroidx/compose/ui/node/HitTestResult;->findBestHitDistance-ptXAw2c()J
-HSPLandroidx/compose/ui/node/HitTestResult;->get(I)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/HitTestResult;->getSize()I
-HSPLandroidx/compose/ui/node/HitTestResult;->hasHit()Z
-HSPLandroidx/compose/ui/node/HitTestResult;->hit(Ljava/lang/Object;ZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/HitTestResult;->hitInMinimumTouchTarget(Ljava/lang/Object;FZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/HitTestResult;->isEmpty()Z
-HSPLandroidx/compose/ui/node/HitTestResult;->resizeToHitDepth()V
-HSPLandroidx/compose/ui/node/HitTestResult;->size()I
-HSPLandroidx/compose/ui/node/HitTestResultKt;->DistanceAndInLayer(FZ)J
-HSPLandroidx/compose/ui/node/HitTestResultKt;->access$DistanceAndInLayer(FZ)J
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator$tail$1;-><init>()V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;-><clinit>()V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;->calculateAlignmentLine(Landroidx/compose/ui/layout/AlignmentLine;)I
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;->getTail()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;->hitTestChild-YqVAtuI(Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;->measure-BRTryo0(J)Landroidx/compose/ui/layout/Placeable;
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;->performDraw(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/InnerNodeCoordinator;->placeAt-f8xVGno(JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/IntStack;-><init>(I)V
-HSPLandroidx/compose/ui/node/IntStack;->compareDiagonal(II)Z
-HSPLandroidx/compose/ui/node/IntStack;->isNotEmpty()Z
-HSPLandroidx/compose/ui/node/IntStack;->partition(III)I
-HSPLandroidx/compose/ui/node/IntStack;->pop()I
-HSPLandroidx/compose/ui/node/IntStack;->pushDiagonal(III)V
-HSPLandroidx/compose/ui/node/IntStack;->pushRange(IIII)V
-HSPLandroidx/compose/ui/node/IntStack;->quickSort(III)V
-HSPLandroidx/compose/ui/node/IntStack;->sortDiagonals()V
-HSPLandroidx/compose/ui/node/IntStack;->swapDiagonal(II)V
-HSPLandroidx/compose/ui/node/IntrinsicsPolicy$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/IntrinsicsPolicy$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/IntrinsicsPolicy;-><clinit>()V
-HSPLandroidx/compose/ui/node/IntrinsicsPolicy;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/IntrinsicsPolicy;->setMeasurePolicyState(Landroidx/compose/ui/layout/MeasurePolicy;)V
-HSPLandroidx/compose/ui/node/IntrinsicsPolicy;->updateFrom(Landroidx/compose/ui/layout/MeasurePolicy;)V
-HSPLandroidx/compose/ui/node/LayerPositionalProperties;-><init>()V
-HSPLandroidx/compose/ui/node/LayerPositionalProperties;->copyFrom(Landroidx/compose/ui/graphics/GraphicsLayerScope;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;-><init>(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/node/LayoutModifierNode;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->calculateAlignmentLine(Landroidx/compose/ui/layout/AlignmentLine;)I
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->getLayoutModifierNode()Landroidx/compose/ui/node/LayoutModifierNode;
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->getTail()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->getWrappedNonNull()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->measure-BRTryo0(J)Landroidx/compose/ui/layout/Placeable;
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->onLayoutModifierNodeChanged()V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->performDraw(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->placeAt-f8xVGno(JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinator;->setLayoutModifierNode$ui_release(Landroidx/compose/ui/node/LayoutModifierNode;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinatorKt;->access$calculateAlignmentAndPlaceChildAsNeeded(Landroidx/compose/ui/node/LookaheadCapablePlaceable;Landroidx/compose/ui/layout/AlignmentLine;)I
-HSPLandroidx/compose/ui/node/LayoutModifierNodeCoordinatorKt;->calculateAlignmentAndPlaceChildAsNeeded(Landroidx/compose/ui/node/LookaheadCapablePlaceable;Landroidx/compose/ui/layout/AlignmentLine;)I
-HSPLandroidx/compose/ui/node/LayoutModifierNodeKt;->invalidateLayer(Landroidx/compose/ui/node/LayoutModifierNode;)V
-HSPLandroidx/compose/ui/node/LayoutModifierNodeKt;->invalidateMeasurements(Landroidx/compose/ui/node/LayoutModifierNode;)V
-HSPLandroidx/compose/ui/node/LayoutNode$$ExternalSyntheticLambda0;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNode$$ExternalSyntheticLambda0;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/node/LayoutNode$Companion$Constructor$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNode$Companion$Constructor$1;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNode$Companion$Constructor$1;->invoke()Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/LayoutNode$Companion$Constructor$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNode$Companion$DummyViewConfiguration$1;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNode$Companion$ErrorMeasurePolicy$1;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNode$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNode$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/LayoutNode$Companion;->getConstructor$ui_release()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/node/LayoutNode$LayoutState;->$values()[Landroidx/compose/ui/node/LayoutNode$LayoutState;
-HSPLandroidx/compose/ui/node/LayoutNode$LayoutState;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNode$LayoutState;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/node/LayoutNode$LayoutState;->values()[Landroidx/compose/ui/node/LayoutNode$LayoutState;
-HSPLandroidx/compose/ui/node/LayoutNode$NoIntrinsicsMeasurePolicy;-><init>(Ljava/lang/String;)V
-HSPLandroidx/compose/ui/node/LayoutNode$UsageByParent;->$values()[Landroidx/compose/ui/node/LayoutNode$UsageByParent;
-HSPLandroidx/compose/ui/node/LayoutNode$UsageByParent;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNode$UsageByParent;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/node/LayoutNode$UsageByParent;->values()[Landroidx/compose/ui/node/LayoutNode$UsageByParent;
-HSPLandroidx/compose/ui/node/LayoutNode$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNode$_foldedChildren$1;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNode$_foldedChildren$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNode$_foldedChildren$1;->invoke()V
-HSPLandroidx/compose/ui/node/LayoutNode;->$r8$lambda$5YfhreyhdVOEmOIPT3j1kScR2gs(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/node/LayoutNode;)I
-HSPLandroidx/compose/ui/node/LayoutNode;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNode;-><init>(ZI)V
-HSPLandroidx/compose/ui/node/LayoutNode;-><init>(ZIILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->ZComparator$lambda$41(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/node/LayoutNode;)I
-HSPLandroidx/compose/ui/node/LayoutNode;->access$getConstructor$cp()Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/node/LayoutNode;->access$setIgnoreRemeasureRequests$p(Landroidx/compose/ui/node/LayoutNode;Z)V
-HSPLandroidx/compose/ui/node/LayoutNode;->attach$ui_release(Landroidx/compose/ui/node/Owner;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->checkChildrenPlaceOrderForUpdates$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->clearPlaceOrder$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->clearSubtreeIntrinsicsUsage$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->clearSubtreePlacementIntrinsicsUsage()V
-HSPLandroidx/compose/ui/node/LayoutNode;->detach$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->dispatchOnPositionedCallbacks$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->draw$ui_release(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->getCanMultiMeasure$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getChildMeasurables$ui_release()Ljava/util/List;
-HSPLandroidx/compose/ui/node/LayoutNode;->getChildren$ui_release()Ljava/util/List;
-HSPLandroidx/compose/ui/node/LayoutNode;->getCoordinates()Landroidx/compose/ui/layout/LayoutCoordinates;
-HSPLandroidx/compose/ui/node/LayoutNode;->getDensity()Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/node/LayoutNode;->getDepth$ui_release()I
-HSPLandroidx/compose/ui/node/LayoutNode;->getFoldedChildren$ui_release()Ljava/util/List;
-HSPLandroidx/compose/ui/node/LayoutNode;->getHasFixedInnerContentConstraints$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getHeight()I
-HSPLandroidx/compose/ui/node/LayoutNode;->getInnerCoordinator$ui_release()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/LayoutNode;->getInnerLayerCoordinator()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/LayoutNode;->getIntrinsicsUsageByParent$ui_release()Landroidx/compose/ui/node/LayoutNode$UsageByParent;
-HSPLandroidx/compose/ui/node/LayoutNode;->getLayoutDelegate$ui_release()Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;
-HSPLandroidx/compose/ui/node/LayoutNode;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/node/LayoutNode;->getLayoutPending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getLayoutState$ui_release()Landroidx/compose/ui/node/LayoutNode$LayoutState;
-HSPLandroidx/compose/ui/node/LayoutNode;->getLookaheadLayoutPending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getLookaheadMeasurePending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getMDrawScope$ui_release()Landroidx/compose/ui/node/LayoutNodeDrawScope;
-HSPLandroidx/compose/ui/node/LayoutNode;->getMLookaheadScope$ui_release()Landroidx/compose/ui/layout/LookaheadScope;
-HSPLandroidx/compose/ui/node/LayoutNode;->getMeasurePassDelegate()Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;
-HSPLandroidx/compose/ui/node/LayoutNode;->getMeasurePending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getMeasurePolicy()Landroidx/compose/ui/layout/MeasurePolicy;
-HSPLandroidx/compose/ui/node/LayoutNode;->getMeasuredByParent$ui_release()Landroidx/compose/ui/node/LayoutNode$UsageByParent;
-HSPLandroidx/compose/ui/node/LayoutNode;->getNeedsOnPositionedDispatch$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->getNodes$ui_release()Landroidx/compose/ui/node/NodeChain;
-HSPLandroidx/compose/ui/node/LayoutNode;->getOuterCoordinator$ui_release()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/LayoutNode;->getOwner$ui_release()Landroidx/compose/ui/node/Owner;
-HSPLandroidx/compose/ui/node/LayoutNode;->getParent$ui_release()Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/LayoutNode;->getSemanticsId()I
-HSPLandroidx/compose/ui/node/LayoutNode;->getSubcompositionsState$ui_release()Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;
-HSPLandroidx/compose/ui/node/LayoutNode;->getViewConfiguration()Landroidx/compose/ui/platform/ViewConfiguration;
-HSPLandroidx/compose/ui/node/LayoutNode;->getWidth()I
-HSPLandroidx/compose/ui/node/LayoutNode;->getZSortedChildren()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/node/LayoutNode;->get_children$ui_release()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/node/LayoutNode;->hitTest-M_7yMNQ$ui_release$default(Landroidx/compose/ui/node/LayoutNode;JLandroidx/compose/ui/node/HitTestResult;ZZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->hitTest-M_7yMNQ$ui_release(JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/LayoutNode;->insertAt$ui_release(ILandroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->invalidateFocusOnAttach()V
-HSPLandroidx/compose/ui/node/LayoutNode;->invalidateFocusOnDetach()V
-HSPLandroidx/compose/ui/node/LayoutNode;->invalidateLayer$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->invalidateLayers$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->invalidateMeasurements$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->invalidateUnfoldedVirtualChildren()V
-HSPLandroidx/compose/ui/node/LayoutNode;->isAttached()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->isPlaced()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->isValidOwnerScope()Z
-HSPLandroidx/compose/ui/node/LayoutNode;->markLayoutPending$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->markMeasurePending$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->markNodeAndSubtreeAsPlaced()V
-HSPLandroidx/compose/ui/node/LayoutNode;->onChildRemoved(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->onDensityOrLayoutDirectionChanged()V
-HSPLandroidx/compose/ui/node/LayoutNode;->onNodePlaced$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->onZSortedChildrenInvalidated$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->place$ui_release(II)V
-HSPLandroidx/compose/ui/node/LayoutNode;->recreateUnfoldedChildrenIfDirty()V
-HSPLandroidx/compose/ui/node/LayoutNode;->remeasure-_Sx5XlM$ui_release$default(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/unit/Constraints;ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/node/LayoutNode;->remeasure-_Sx5XlM$ui_release(Landroidx/compose/ui/unit/Constraints;)Z
-HSPLandroidx/compose/ui/node/LayoutNode;->removeAll$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->removeAt$ui_release(II)V
-HSPLandroidx/compose/ui/node/LayoutNode;->replace$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->requestRelayout$ui_release$default(Landroidx/compose/ui/node/LayoutNode;ZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->requestRelayout$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LayoutNode;->requestRemeasure$ui_release$default(Landroidx/compose/ui/node/LayoutNode;ZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->requestRemeasure$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LayoutNode;->rescheduleRemeasureOrRelayout$ui_release(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->resetSubtreeIntrinsicsUsage$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNode;->setCanMultiMeasure$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setDensity(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setInnerLayerCoordinatorIsDirty$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setLayoutDirection(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setMLookaheadScope(Landroidx/compose/ui/layout/LookaheadScope;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setMeasurePolicy(Landroidx/compose/ui/layout/MeasurePolicy;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setMeasuredByParent$ui_release(Landroidx/compose/ui/node/LayoutNode$UsageByParent;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setModifier(Landroidx/compose/ui/Modifier;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setNeedsOnPositionedDispatch$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setSubcompositionsState$ui_release(Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->setViewConfiguration(Landroidx/compose/ui/platform/ViewConfiguration;)V
-HSPLandroidx/compose/ui/node/LayoutNode;->updateChildrenIfDirty$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNodeAlignmentLines;-><init>(Landroidx/compose/ui/node/AlignmentLinesOwner;)V
-HSPLandroidx/compose/ui/node/LayoutNodeAlignmentLines;->calculatePositionInParent-R5De75A(Landroidx/compose/ui/node/NodeCoordinator;J)J
-HSPLandroidx/compose/ui/node/LayoutNodeAlignmentLines;->getAlignmentLinesMap(Landroidx/compose/ui/node/NodeCoordinator;)Ljava/util/Map;
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;-><init>(Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope;)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;-><init>(Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->draw-x_KDEd0$ui_release(Landroidx/compose/ui/graphics/Canvas;JLandroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/node/DrawModifierNode;)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->drawContent()V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->drawImage-AZ2fEMs(Landroidx/compose/ui/graphics/ImageBitmap;JJJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;II)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->drawPath-LG529CI(Landroidx/compose/ui/graphics/Path;JFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->drawRect-n-J9OG0(JJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->drawRoundRect-u-Aw5IA(JJJJLandroidx/compose/ui/graphics/drawscope/DrawStyle;FLandroidx/compose/ui/graphics/ColorFilter;I)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->getDrawContext()Landroidx/compose/ui/graphics/drawscope/DrawContext;
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->getSize-NH-jbRc()J
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->performDraw(Landroidx/compose/ui/node/DrawModifierNode;Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->roundToPx-0680j_4(F)I
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScope;->toPx-0680j_4(F)F
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScopeKt;->access$nextDrawNode(Landroidx/compose/ui/node/DelegatableNode;)Landroidx/compose/ui/node/DrawModifierNode;
-HSPLandroidx/compose/ui/node/LayoutNodeDrawScopeKt;->nextDrawNode(Landroidx/compose/ui/node/DelegatableNode;)Landroidx/compose/ui/node/DrawModifierNode;
-HSPLandroidx/compose/ui/node/LayoutNodeKt;->requireOwner(Landroidx/compose/ui/node/LayoutNode;)Landroidx/compose/ui/node/Owner;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$childMeasurables$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$childMeasurables$1;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$childMeasurables$1;->invoke(Landroidx/compose/ui/node/LayoutNode;)Landroidx/compose/ui/layout/Measurable;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$childMeasurables$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$1;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$1;->invoke(Landroidx/compose/ui/node/AlignmentLinesOwner;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$2;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$2;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$2;->invoke(Landroidx/compose/ui/node/AlignmentLinesOwner;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1;-><init>(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1;->invoke()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1;-><init>(Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;JF)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1;->invoke()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$remeasure$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$remeasure$1;-><init>()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$remeasure$1;->invoke(Landroidx/compose/ui/node/AlignmentLinesOwner;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$remeasure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;-><init>(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->calculateAlignmentLines()Ljava/util/Map;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->forEachChildAlignmentLinesOwner(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->get(Landroidx/compose/ui/layout/AlignmentLine;)I
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getAlignmentLines()Landroidx/compose/ui/node/AlignmentLines;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getChildMeasurables$ui_release()Ljava/util/List;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getInnerCoordinator()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getLastConstraints-DWUhwKw()Landroidx/compose/ui/unit/Constraints;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getMeasuredWidth()I
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getParentAlignmentLinesOwner()Landroidx/compose/ui/node/AlignmentLinesOwner;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->getParentData()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->invalidateIntrinsicsParent(Z)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->isPlaced()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->layoutChildren()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->measure-BRTryo0(J)Landroidx/compose/ui/layout/Placeable;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->notifyChildrenUsingCoordinatesWhilePlacing()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->onBeforeLayoutChildren()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->placeAt-f8xVGno(JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->placeOuterCoordinator-f8xVGno(JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->remeasure-BRTryo0(J)Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->replace()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->requestMeasure()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->setChildMeasurablesDirty$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->trackMeasurementByParent(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;->updateParentData()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$performMeasure$2;-><init>(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;J)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$performMeasure$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate$performMeasure$2;->invoke()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$getLayoutNode$p(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;)Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$getLayoutPendingForAlignment$p(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;)Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$isOutMostLookaheadRoot(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$performMeasure-BRTryo0(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;J)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$setLayoutPending$p(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;Z)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$setLayoutPendingForAlignment$p(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;Z)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->access$setLayoutState$p(Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;Landroidx/compose/ui/node/LayoutNode$LayoutState;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getAlignmentLinesOwner$ui_release()Landroidx/compose/ui/node/AlignmentLinesOwner;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getChildrenAccessingCoordinatesDuringPlacement()I
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getCoordinatesAccessedDuringPlacement()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getHeight$ui_release()I
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getLastConstraints-DWUhwKw()Landroidx/compose/ui/unit/Constraints;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getLayoutPending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getLayoutState$ui_release()Landroidx/compose/ui/node/LayoutNode$LayoutState;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getLookaheadLayoutPending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getLookaheadMeasurePending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getMeasurePassDelegate$ui_release()Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getMeasurePending$ui_release()Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getOuterCoordinator()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->getWidth$ui_release()I
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->isOutMostLookaheadRoot(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->markChildrenDirty()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->markLayoutPending$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->markMeasurePending$ui_release()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->performMeasure-BRTryo0(J)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->resetAlignmentLines()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->setCoordinatesAccessedDuringPlacement(Z)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegate;->updateParentData()V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegateKt;->access$updateChildMeasurables(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/runtime/collection/MutableVector;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/LayoutNodeLayoutDelegateKt;->updateChildMeasurables(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/runtime/collection/MutableVector;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;-><init>()V
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;->get(Landroidx/compose/ui/layout/AlignmentLine;)I
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;->invalidateAlignmentLinesFromPositionChange(Landroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;->isPlacingForAlignment$ui_release()Z
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;->isShallowPlacing$ui_release()Z
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;->setPlacingForAlignment$ui_release(Z)V
-HSPLandroidx/compose/ui/node/LookaheadCapablePlaceable;->setShallowPlacing$ui_release(Z)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->access$getRoot$p(Landroidx/compose/ui/node/MeasureAndLayoutDelegate;)Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->access$remeasureAndRelayoutIfNeeded(Landroidx/compose/ui/node/MeasureAndLayoutDelegate;Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->callOnLayoutCompletedListeners()V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->dispatchOnPositionedCallbacks$default(Landroidx/compose/ui/node/MeasureAndLayoutDelegate;ZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->dispatchOnPositionedCallbacks(Z)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->doRemeasure-sdFAvZA(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/unit/Constraints;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->forceMeasureTheSubtree(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->getCanAffectParent(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->getMeasureAffectsParent(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->measureAndLayout(Lkotlin/jvm/functions/Function0;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->measureOnly()V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->onNodeDetached(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->recurseRemeasure(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->remeasureAndRelayoutIfNeeded(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->remeasureOnly(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->requestRelayout(Landroidx/compose/ui/node/LayoutNode;Z)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->requestRemeasure$default(Landroidx/compose/ui/node/MeasureAndLayoutDelegate;Landroidx/compose/ui/node/LayoutNode;ZILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->requestRemeasure(Landroidx/compose/ui/node/LayoutNode;Z)Z
-HSPLandroidx/compose/ui/node/MeasureAndLayoutDelegate;->updateRootConstraints-BRTryo0(J)V
-HSPLandroidx/compose/ui/node/ModifierNodeElement;-><clinit>()V
-HSPLandroidx/compose/ui/node/ModifierNodeElement;-><init>(Ljava/lang/Object;ZLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/ModifierNodeElement;-><init>(Ljava/lang/Object;ZLkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/ModifierNodeElement;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/node/ModifierNodeElement;->getAutoInvalidate$ui_release()Z
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;-><init>(Landroidx/compose/runtime/collection/MutableVector;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->add(ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->asList()Ljava/util/List;
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->clear()V
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->get(I)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->getSize()I
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->getVector()Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/node/MutableVectorWithMutationTracking;->removeAt(I)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/MyersDiffKt;->access$swap([III)V
-HSPLandroidx/compose/ui/node/MyersDiffKt;->applyDiff(IILandroidx/compose/ui/node/IntStack;Landroidx/compose/ui/node/DiffCallback;)V
-HSPLandroidx/compose/ui/node/MyersDiffKt;->backward-4l5_RBY(IIIILandroidx/compose/ui/node/DiffCallback;[I[II[I)Z
-HSPLandroidx/compose/ui/node/MyersDiffKt;->calculateDiff(IILandroidx/compose/ui/node/DiffCallback;)Landroidx/compose/ui/node/IntStack;
-HSPLandroidx/compose/ui/node/MyersDiffKt;->executeDiff(IILandroidx/compose/ui/node/DiffCallback;)V
-HSPLandroidx/compose/ui/node/MyersDiffKt;->fillSnake(IIIIZ[I)V
-HSPLandroidx/compose/ui/node/MyersDiffKt;->forward-4l5_RBY(IIIILandroidx/compose/ui/node/DiffCallback;[I[II[I)Z
-HSPLandroidx/compose/ui/node/MyersDiffKt;->midPoint-q5eDKzI(IIIILandroidx/compose/ui/node/DiffCallback;[I[I[I)Z
-HSPLandroidx/compose/ui/node/MyersDiffKt;->swap([III)V
-HSPLandroidx/compose/ui/node/NodeChain$Differ;-><init>(Landroidx/compose/ui/node/NodeChain;Landroidx/compose/ui/Modifier$Node;ILandroidx/compose/runtime/collection/MutableVector;Landroidx/compose/runtime/collection/MutableVector;)V
-HSPLandroidx/compose/ui/node/NodeChain$Differ;->areItemsTheSame(II)Z
-HSPLandroidx/compose/ui/node/NodeChain$Differ;->insert(II)V
-HSPLandroidx/compose/ui/node/NodeChain$Differ;->same(II)V
-HSPLandroidx/compose/ui/node/NodeChain;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/NodeChain;->access$createAndInsertNodeAsParent(Landroidx/compose/ui/node/NodeChain;Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChain;->access$getAggregateChildKindSet(Landroidx/compose/ui/node/NodeChain;)I
-HSPLandroidx/compose/ui/node/NodeChain;->access$getLogger$p(Landroidx/compose/ui/node/NodeChain;)Landroidx/compose/ui/node/NodeChain$Logger;
-HSPLandroidx/compose/ui/node/NodeChain;->access$updateNodeAndReplaceIfNeeded(Landroidx/compose/ui/node/NodeChain;Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChain;->attach(Z)V
-HSPLandroidx/compose/ui/node/NodeChain;->createAndInsertNodeAsParent(Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChain;->detach$ui_release()V
-HSPLandroidx/compose/ui/node/NodeChain;->getAggregateChildKindSet()I
-HSPLandroidx/compose/ui/node/NodeChain;->getDiffer(Landroidx/compose/ui/Modifier$Node;Landroidx/compose/runtime/collection/MutableVector;Landroidx/compose/runtime/collection/MutableVector;)Landroidx/compose/ui/node/NodeChain$Differ;
-HSPLandroidx/compose/ui/node/NodeChain;->getHead$ui_release()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChain;->getInnerCoordinator$ui_release()Landroidx/compose/ui/node/InnerNodeCoordinator;
-HSPLandroidx/compose/ui/node/NodeChain;->getOuterCoordinator$ui_release()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/NodeChain;->getTail$ui_release()Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChain;->has$ui_release(I)Z
-HSPLandroidx/compose/ui/node/NodeChain;->has-H91voCI$ui_release(I)Z
-HSPLandroidx/compose/ui/node/NodeChain;->insertParent(Landroidx/compose/ui/Modifier$Node;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChain;->padChain()V
-HSPLandroidx/compose/ui/node/NodeChain;->structuralUpdate(Landroidx/compose/runtime/collection/MutableVector;ILandroidx/compose/runtime/collection/MutableVector;ILandroidx/compose/ui/Modifier$Node;)V
-HSPLandroidx/compose/ui/node/NodeChain;->syncCoordinators()V
-HSPLandroidx/compose/ui/node/NodeChain;->trimChain()V
-HSPLandroidx/compose/ui/node/NodeChain;->updateFrom$ui_release(Landroidx/compose/ui/Modifier;)V
-HSPLandroidx/compose/ui/node/NodeChain;->updateNodeAndReplaceIfNeeded(Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChainKt$SentinelHead$1;-><init>()V
-HSPLandroidx/compose/ui/node/NodeChainKt;-><clinit>()V
-HSPLandroidx/compose/ui/node/NodeChainKt;->access$fillVector(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/collection/MutableVector;)Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/node/NodeChainKt;->access$getSentinelHead$p()Landroidx/compose/ui/node/NodeChainKt$SentinelHead$1;
-HSPLandroidx/compose/ui/node/NodeChainKt;->access$updateUnsafe(Landroidx/compose/ui/node/ModifierNodeElement;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeChainKt;->fillVector(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/collection/MutableVector;)Landroidx/compose/runtime/collection/MutableVector;
-HSPLandroidx/compose/ui/node/NodeChainKt;->reuseActionForModifiers(Landroidx/compose/ui/Modifier$Element;Landroidx/compose/ui/Modifier$Element;)I
-HSPLandroidx/compose/ui/node/NodeChainKt;->updateUnsafe(Landroidx/compose/ui/node/ModifierNodeElement;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;-><init>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;->childHitTest-YqVAtuI(Landroidx/compose/ui/node/LayoutNode;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;->entityType-OLwlOKw()I
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;->shouldHitTestChildren(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$SemanticsSource$1;-><init>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayer$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayer$1;-><init>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayer$1;->invoke(Landroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayer$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayerParams$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayerParams$1;-><init>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$Companion;->getPointerInputSource()Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;
-HSPLandroidx/compose/ui/node/NodeCoordinator$hit$1;-><init>(Landroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$hit$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator$hit$1;->invoke()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$invalidateParentLayer$1;-><init>(Landroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$invalidateParentLayer$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator$invalidateParentLayer$1;->invoke()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$invoke$1;-><init>(Landroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$invoke$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator$invoke$1;->invoke()V
-HSPLandroidx/compose/ui/node/NodeCoordinator$updateLayerParameters$1;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator$updateLayerParameters$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator$updateLayerParameters$1;->invoke()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;-><clinit>()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$drawContainedDrawModifiers(Landroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$getGraphicsLayerScope$cp()Landroidx/compose/ui/graphics/ReusableGraphicsLayerScope;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$getMeasuredSize-YbymL2g(Landroidx/compose/ui/node/NodeCoordinator;)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$getPointerInputSource$cp()Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$headNode(Landroidx/compose/ui/node/NodeCoordinator;Z)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$hit-1hIXUjU(Landroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->access$setMeasurementConstraints-BRTryo0(Landroidx/compose/ui/node/NodeCoordinator;J)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->ancestorToLocal-R5De75A(Landroidx/compose/ui/node/NodeCoordinator;J)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->attach()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->calculateMinimumTouchTargetPadding-E7KxVPU(J)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->detach()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->distanceInMinimumTouchTarget-tz77jQw(JJ)F
-HSPLandroidx/compose/ui/node/NodeCoordinator;->draw(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->drawContainedDrawModifiers(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->findCommonAncestor$ui_release(Landroidx/compose/ui/node/NodeCoordinator;)Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->fromParentPosition-MK-Hz9U(J)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getAlignmentLinesOwner()Landroidx/compose/ui/node/AlignmentLinesOwner;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getChild()Landroidx/compose/ui/node/LookaheadCapablePlaceable;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getCoordinates()Landroidx/compose/ui/layout/LayoutCoordinates;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getDensity()F
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getFontScale()F
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getHasMeasureResult()Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getLastLayerDrawingWasSkipped$ui_release()Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getLastMeasurementConstraints-msEJaDk$ui_release()J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getLayer()Landroidx/compose/ui/node/OwnedLayer;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getLayoutNode()Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getLookaheadDelegate$ui_release()Landroidx/compose/ui/node/LookaheadDelegate;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getMeasureResult$ui_release()Landroidx/compose/ui/layout/MeasureResult;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getMinimumTouchTargetSize-NH-jbRc()J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getParent()Landroidx/compose/ui/node/LookaheadCapablePlaceable;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getParentData()Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getPosition-nOcc-ac()J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getSize-YbymL2g()J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getSnapshotObserver()Landroidx/compose/ui/node/OwnerSnapshotObserver;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getWrapped$ui_release()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getWrappedBy$ui_release()Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->getZIndex()F
-HSPLandroidx/compose/ui/node/NodeCoordinator;->hasNode-H91voCI(I)Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->headNode(Z)Landroidx/compose/ui/Modifier$Node;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->headUnchecked-H91voCI(I)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->hit-1hIXUjU(Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->hitTest-YqVAtuI(Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->hitTestChild-YqVAtuI(Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZ)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->invalidateLayer()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->invoke(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->isAttached()Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->isPointerInBounds-k-4lQ0M(J)Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->isValidOwnerScope()Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->localPositionOf-R5De75A(Landroidx/compose/ui/layout/LayoutCoordinates;J)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->offsetFromEdge-MK-Hz9U(J)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->onLayerBlockUpdated$default(Landroidx/compose/ui/node/NodeCoordinator;Lkotlin/jvm/functions/Function1;ZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->onLayerBlockUpdated(Lkotlin/jvm/functions/Function1;Z)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->onLayoutModifierNodeChanged()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->onMeasureResultChanged(II)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->onMeasured()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->onPlaced()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->placeAt-f8xVGno(JFLkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->replace$ui_release()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->setMeasureResult$ui_release(Landroidx/compose/ui/layout/MeasureResult;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->setPosition--gyyYBs(J)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->setWrapped$ui_release(Landroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->setWrappedBy$ui_release(Landroidx/compose/ui/node/NodeCoordinator;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->shouldSharePointerInputWithSiblings()Z
-HSPLandroidx/compose/ui/node/NodeCoordinator;->toCoordinator(Landroidx/compose/ui/layout/LayoutCoordinates;)Landroidx/compose/ui/node/NodeCoordinator;
-HSPLandroidx/compose/ui/node/NodeCoordinator;->toParentPosition-MK-Hz9U(J)J
-HSPLandroidx/compose/ui/node/NodeCoordinator;->updateLayerParameters()V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->updateLookaheadScope$ui_release(Landroidx/compose/ui/layout/LookaheadScope;)V
-HSPLandroidx/compose/ui/node/NodeCoordinator;->withinLayerBounds-k-4lQ0M(J)Z
-HSPLandroidx/compose/ui/node/NodeCoordinatorKt;->access$nextUncheckedUntil-hw7D004(Landroidx/compose/ui/node/DelegatableNode;II)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeCoordinatorKt;->nextUncheckedUntil-hw7D004(Landroidx/compose/ui/node/DelegatableNode;II)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/NodeKind;->constructor-impl(I)I
-HSPLandroidx/compose/ui/node/NodeKindKt;->autoInvalidateInsertedNode(Landroidx/compose/ui/Modifier$Node;)V
-HSPLandroidx/compose/ui/node/NodeKindKt;->autoInvalidateNode(Landroidx/compose/ui/Modifier$Node;I)V
-HSPLandroidx/compose/ui/node/NodeKindKt;->autoInvalidateUpdatedNode(Landroidx/compose/ui/Modifier$Node;)V
-HSPLandroidx/compose/ui/node/NodeKindKt;->calculateNodeKindSetFrom(Landroidx/compose/ui/Modifier$Element;)I
-HSPLandroidx/compose/ui/node/NodeKindKt;->calculateNodeKindSetFrom(Landroidx/compose/ui/Modifier$Node;)I
-HSPLandroidx/compose/ui/node/NodeKindKt;->getIncludeSelfInTraversal-H91voCI(I)Z
-HSPLandroidx/compose/ui/node/NodeKindKt;->specifiesCanFocusProperty(Landroidx/compose/ui/focus/FocusPropertiesModifierNode;)Z
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher$Companion$DepthComparator;-><clinit>()V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher$Companion$DepthComparator;-><init>()V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher$Companion$DepthComparator;->compare(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/ui/node/LayoutNode;)I
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher$Companion$DepthComparator;->compare(Ljava/lang/Object;Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher;-><clinit>()V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher;-><init>()V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher;->dispatch()V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher;->dispatchHierarchy(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/OnPositionedDispatcher;->onNodePositioned(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/Owner$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/node/Owner$Companion;-><init>()V
-HSPLandroidx/compose/ui/node/Owner$Companion;->getEnableExtraAssertions()Z
-HSPLandroidx/compose/ui/node/Owner;-><clinit>()V
-HSPLandroidx/compose/ui/node/Owner;->measureAndLayout$default(Landroidx/compose/ui/node/Owner;ZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/Owner;->onRequestMeasure$default(Landroidx/compose/ui/node/Owner;Landroidx/compose/ui/node/LayoutNode;ZZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/Owner;->onRequestRelayout$default(Landroidx/compose/ui/node/Owner;Landroidx/compose/ui/node/LayoutNode;ZZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$clearInvalidObservations$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$clearInvalidObservations$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$clearInvalidObservations$1;->invoke(Ljava/lang/Object;)Ljava/lang/Boolean;
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$clearInvalidObservations$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayout$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayout$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifier$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifier$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifier$1;->invoke(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifier$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifierInLookahead$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifierInLookahead$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLookaheadLayout$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLookaheadLayout$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLookaheadMeasure$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLookaheadMeasure$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingMeasure$1;-><clinit>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingMeasure$1;-><init>()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingMeasure$1;->invoke(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingMeasure$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->clearInvalidObservations$ui_release()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->observeLayoutModifierSnapshotReads$ui_release(Landroidx/compose/ui/node/LayoutNode;ZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->observeLayoutSnapshotReads$ui_release(Landroidx/compose/ui/node/LayoutNode;ZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->observeMeasureSnapshotReads$ui_release(Landroidx/compose/ui/node/LayoutNode;ZLkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->observeReads$ui_release(Landroidx/compose/ui/node/OwnerScope;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->startObserving$ui_release()V
-HSPLandroidx/compose/ui/node/OwnerSnapshotObserver;->stopObserving$ui_release()V
-HSPLandroidx/compose/ui/node/PointerInputModifierNodeKt;->getLayoutCoordinates(Landroidx/compose/ui/node/PointerInputModifierNode;)Landroidx/compose/ui/layout/LayoutCoordinates;
-HSPLandroidx/compose/ui/node/PointerInputModifierNodeKt;->isAttached(Landroidx/compose/ui/node/PointerInputModifierNode;)Z
-HSPLandroidx/compose/ui/node/SemanticsModifierNodeKt;->collapsedSemanticsConfiguration(Landroidx/compose/ui/node/SemanticsModifierNode;)Landroidx/compose/ui/semantics/SemanticsConfiguration;
-HSPLandroidx/compose/ui/node/SemanticsModifierNodeKt;->invalidateSemantics(Landroidx/compose/ui/node/SemanticsModifierNode;)V
-HSPLandroidx/compose/ui/node/Snake;->addDiagonalToStack-impl([ILandroidx/compose/ui/node/IntStack;)V
-HSPLandroidx/compose/ui/node/Snake;->constructor-impl([I)[I
-HSPLandroidx/compose/ui/node/Snake;->getDiagonalSize-impl([I)I
-HSPLandroidx/compose/ui/node/Snake;->getEndX-impl([I)I
-HSPLandroidx/compose/ui/node/Snake;->getEndY-impl([I)I
-HSPLandroidx/compose/ui/node/Snake;->getHasAdditionOrRemoval-impl([I)Z
-HSPLandroidx/compose/ui/node/Snake;->getReverse-impl([I)Z
-HSPLandroidx/compose/ui/node/Snake;->getStartX-impl([I)I
-HSPLandroidx/compose/ui/node/Snake;->getStartY-impl([I)I
-HSPLandroidx/compose/ui/node/Snake;->isAddition-impl([I)Z
-HSPLandroidx/compose/ui/node/TreeSet;-><init>(Ljava/util/Comparator;)V
-HSPLandroidx/compose/ui/node/UiApplier;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/UiApplier;->insertBottomUp(ILandroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/UiApplier;->insertBottomUp(ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/UiApplier;->insertTopDown(ILandroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/node/UiApplier;->insertTopDown(ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/node/UiApplier;->onClear()V
-HSPLandroidx/compose/ui/node/UiApplier;->onEndChanges()V
-HSPLandroidx/compose/ui/node/UiApplier;->remove(II)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView$ensureCompositionCreated$1;-><init>(Landroidx/compose/ui/platform/AbstractComposeView;)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView$ensureCompositionCreated$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView$ensureCompositionCreated$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AbstractComposeView;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;I)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->addView(Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->addView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->cacheIfAlive(Landroidx/compose/runtime/CompositionContext;)Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->checkAddView()V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->disposeComposition()V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->ensureCompositionCreated()V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->internalOnLayout$ui_release(ZIIII)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->internalOnMeasure$ui_release(II)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->isAlive(Landroidx/compose/runtime/CompositionContext;)Z
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->onAttachedToWindow()V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->onLayout(ZIIII)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->onMeasure(II)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->onRtlPropertiesChanged(I)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->resolveParentCompositionContext()Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->setParentCompositionContext(Landroidx/compose/runtime/CompositionContext;)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->setParentContext(Landroidx/compose/runtime/CompositionContext;)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->setPreviousAttachedWindowToken(Landroid/os/IBinder;)V
-HSPLandroidx/compose/ui/platform/AbstractComposeView;->shouldDelayChildPressedState()Z
-HSPLandroidx/compose/ui/platform/AndroidAccessibilityManager$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidAccessibilityManager$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/AndroidAccessibilityManager;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidAccessibilityManager;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/ui/platform/AndroidClipboardManager;-><init>(Landroid/content/ClipboardManager;)V
-HSPLandroidx/compose/ui/platform/AndroidClipboardManager;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda0;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda0;->onGlobalLayout()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda2;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda2;->onTouchModeChanged(Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda3;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$Companion;->access$getIsShowingLayoutBounds(Landroidx/compose/ui/platform/AndroidComposeView$Companion;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView$Companion;->getIsShowingLayoutBounds()Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;-><init>(Landroidx/lifecycle/LifecycleOwner;Landroidx/savedstate/SavedStateRegistryOwner;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;->getLifecycleOwner()Landroidx/lifecycle/LifecycleOwner;
-HSPLandroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;->getSavedStateRegistryOwner()Landroidx/savedstate/SavedStateRegistryOwner;
-HSPLandroidx/compose/ui/platform/AndroidComposeView$_inputModeManager$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$configurationChangeObserver$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$configurationChangeObserver$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$focusOwner$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$focusOwner$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView$focusOwner$1;->invoke(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$keyInputModifier$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$pointerIconService$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$resendMotionEventOnLayout$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$resendMotionEventOnLayout$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView$resendMotionEventOnLayout$1;->invoke()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$resendMotionEventRunnable$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$rotaryInputModifier$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$rotaryInputModifier$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$semanticsModifier$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$semanticsModifier$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$semanticsModifier$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$semanticsModifier$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView$snapshotObserver$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView$snapshotObserver$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView$snapshotObserver$1;->invoke(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->$r8$lambda$6rnsioIDxAVR319ScBkOteeoeiE(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->$r8$lambda$TvhWqMihl4JwF42Odovn0ewO6fk(Landroidx/compose/ui/platform/AndroidComposeView;Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->access$getGetBooleanMethod$cp()Ljava/lang/reflect/Method;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->access$getPreviousMotionEvent$p(Landroidx/compose/ui/platform/AndroidComposeView;)Landroid/view/MotionEvent;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->access$getSystemPropertiesClass$cp()Ljava/lang/Class;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->access$setGetBooleanMethod$cp(Ljava/lang/reflect/Method;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->access$setSystemPropertiesClass$cp(Ljava/lang/Class;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->autofillSupported()Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->boundsUpdatesEventLoop(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->childSizeCanAffectParentSize(Landroidx/compose/ui/node/LayoutNode;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->convertMeasureSpec(I)Lkotlin/Pair;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->createLayer(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Landroidx/compose/ui/node/OwnedLayer;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->dispatchDraw(Landroid/graphics/Canvas;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->dispatchTouchEvent(Landroid/view/MotionEvent;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->forceMeasureTheSubtree(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getAccessibilityManager()Landroidx/compose/ui/platform/AccessibilityManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getAccessibilityManager()Landroidx/compose/ui/platform/AndroidAccessibilityManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getAutofill()Landroidx/compose/ui/autofill/Autofill;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getAutofillTree()Landroidx/compose/ui/autofill/AutofillTree;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getClipboardManager()Landroidx/compose/ui/platform/AndroidClipboardManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getClipboardManager()Landroidx/compose/ui/platform/ClipboardManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getDensity()Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getFocusOwner()Landroidx/compose/ui/focus/FocusOwner;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getFontFamilyResolver()Landroidx/compose/ui/text/font/FontFamily$Resolver;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getFontLoader()Landroidx/compose/ui/text/font/Font$ResourceLoader;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getFontWeightAdjustmentCompat(Landroid/content/res/Configuration;)I
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getHapticFeedBack()Landroidx/compose/ui/hapticfeedback/HapticFeedback;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getInputModeManager()Landroidx/compose/ui/input/InputModeManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getLayoutDirection()Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getModifierLocalManager()Landroidx/compose/ui/modifier/ModifierLocalManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getPointerIconService()Landroidx/compose/ui/input/pointer/PointerIconService;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getRoot()Landroidx/compose/ui/node/LayoutNode;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getSemanticsOwner()Landroidx/compose/ui/semantics/SemanticsOwner;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getSharedDrawScope()Landroidx/compose/ui/node/LayoutNodeDrawScope;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getShowLayoutBounds()Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getSnapshotObserver()Landroidx/compose/ui/node/OwnerSnapshotObserver;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getTextInputService()Landroidx/compose/ui/text/input/TextInputService;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getTextToolbar()Landroidx/compose/ui/platform/TextToolbar;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getView()Landroid/view/View;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getViewConfiguration()Landroidx/compose/ui/platform/ViewConfiguration;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getViewTreeOwners()Landroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->getWindowInfo()Landroidx/compose/ui/platform/WindowInfo;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->globalLayoutListener$lambda$1(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->handleMotionEvent-8iAsVTc(Landroid/view/MotionEvent;)I
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->hasChangedDevices(Landroid/view/MotionEvent;Landroid/view/MotionEvent;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->invalidateLayers(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->invalidateLayoutNodeMeasurement(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->isBadMotionEvent(Landroid/view/MotionEvent;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->isInBounds(Landroid/view/MotionEvent;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->isPositionChanged(Landroid/view/MotionEvent;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->keyboardVisibilityEventLoop(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->measureAndLayout(Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->notifyLayerIsDirty$ui_release(Landroidx/compose/ui/node/OwnedLayer;Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onAttach(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onAttachedToWindow()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onCheckIsTextEditor()Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onDetach(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onDetachedFromWindow()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onDraw(Landroid/graphics/Canvas;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onEndApplyChanges()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onLayout(ZIIII)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onLayoutChange(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onMeasure(II)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onRequestMeasure(Landroidx/compose/ui/node/LayoutNode;ZZ)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onRequestRelayout(Landroidx/compose/ui/node/LayoutNode;ZZ)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onResume(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onRtlPropertiesChanged(I)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onSemanticsChange()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->onWindowFocusChanged(Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->recalculateWindowPosition()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->recalculateWindowPosition(Landroid/view/MotionEvent;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->recalculateWindowViewTransforms()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->recycle$ui_release(Landroidx/compose/ui/node/OwnedLayer;)Z
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->registerOnEndApplyChangesListener(Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->requestClearInvalidObservations()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->scheduleMeasureAndLayout$default(Landroidx/compose/ui/platform/AndroidComposeView;Landroidx/compose/ui/node/LayoutNode;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->scheduleMeasureAndLayout(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->screenToLocal-MK-Hz9U(J)J
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->sendMotionEvent-8iAsVTc(Landroid/view/MotionEvent;)I
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->setConfigurationChangeObserver(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->setLayoutDirection(Landroidx/compose/ui/unit/LayoutDirection;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->setOnViewTreeOwnersAvailable(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->setShowLayoutBounds(Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->setViewTreeOwners(Landroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->touchModeChangeListener$lambda$3(Landroidx/compose/ui/platform/AndroidComposeView;Z)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView;->updatePositionCacheAndDispatch()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$$ExternalSyntheticLambda0;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$$ExternalSyntheticLambda1;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$$ExternalSyntheticLambda2;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$1;->onViewAttachedToWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$1;->onViewDetachedFromWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$MyNodeProvider;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$SemanticsNodeCopy;-><init>(Landroidx/compose/ui/semantics/SemanticsNode;Ljava/util/Map;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$boundsUpdatesEventLoop$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$boundsUpdatesEventLoop$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$sendScrollEventIfNeededLambda$1;-><init>(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->access$getHandler$p(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)Landroid/os/Handler;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->access$getSemanticsChangeChecker$p(Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;)Ljava/lang/Runnable;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->boundsUpdatesEventLoop(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->getAccessibilityManager$ui_release()Landroid/view/accessibility/AccessibilityManager;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->getEnabledStateListener$ui_release()Landroid/view/accessibility/AccessibilityManager$AccessibilityStateChangeListener;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->getTouchExplorationStateListener$ui_release()Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener;
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->isEnabled$ui_release()Z
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->onLayoutChange$ui_release(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;->onSemanticsChange$ui_release()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewForceDarkModeQ;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewForceDarkModeQ;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewForceDarkModeQ;->disallowForceDark(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsN;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsN;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsN;->setPointerIcon(Landroid/view/View;Landroidx/compose/ui/input/pointer/PointerIcon;)V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsO;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsO;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsO;->focusable(Landroid/view/View;IZ)V
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt$textInputServiceFactory$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt$textInputServiceFactory$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt$textInputServiceFactory$1;->invoke(Landroidx/compose/ui/text/input/PlatformTextInputService;)Landroidx/compose/ui/text/input/TextInputService;
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt$textInputServiceFactory$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt;->access$layoutDirectionFromInt(I)Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt;->getLocaleLayoutDirection(Landroid/content/res/Configuration;)Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt;->getTextInputServiceFactory()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt;->layoutDirectionFromInt(I)Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalConfiguration$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalConfiguration$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalContext$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalContext$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalImageVectorCache$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalImageVectorCache$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalLifecycleOwner$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalLifecycleOwner$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalSavedStateRegistryOwner$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalSavedStateRegistryOwner$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalView$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalView$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$1$1;-><init>(Landroidx/compose/runtime/MutableState;)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2$invoke$$inlined$onDispose$1;-><init>(Landroidx/compose/ui/platform/DisposableSaveableStateRegistry;)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2;-><init>(Landroidx/compose/ui/platform/DisposableSaveableStateRegistry;)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;Landroidx/compose/ui/platform/AndroidUriHandler;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$4;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$4;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1$invoke$$inlined$onDispose$1;-><init>(Landroid/content/Context;Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$callbacks$1$1;)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1$invoke$$inlined$onDispose$1;->dispose()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1;-><init>(Landroid/content/Context;Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$callbacks$1$1;)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1;->invoke(Landroidx/compose/runtime/DisposableEffectScope;)Landroidx/compose/runtime/DisposableEffectResult;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$callbacks$1$1;-><init>(Landroid/content/res/Configuration;Landroidx/compose/ui/res/ImageVectorCache;)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;->ProvideAndroidCompositionLocals$lambda$1(Landroidx/compose/runtime/MutableState;)Landroid/content/res/Configuration;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;->ProvideAndroidCompositionLocals(Landroidx/compose/ui/platform/AndroidComposeView;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;->getLocalConfiguration()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;->getLocalContext()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;->getLocalView()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;->obtainImageVectorCache(Landroid/content/Context;Landroid/content/res/Configuration;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/res/ImageVectorCache;
-HSPLandroidx/compose/ui/platform/AndroidFontResourceLoader;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/ui/platform/AndroidTextToolbar$textActionModeCallback$1;-><init>(Landroidx/compose/ui/platform/AndroidTextToolbar;)V
-HSPLandroidx/compose/ui/platform/AndroidTextToolbar;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion$Main$2;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion$Main$2;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion$Main$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion$Main$2;->invoke()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion$currentThread$1;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion;->getCurrentThread()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$Companion;->getMain()Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$dispatchCallback$1;-><init>(Landroidx/compose/ui/platform/AndroidUiDispatcher;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$dispatchCallback$1;->doFrame(J)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher$dispatchCallback$1;->run()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;-><init>(Landroid/view/Choreographer;Landroid/os/Handler;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;-><init>(Landroid/view/Choreographer;Landroid/os/Handler;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$getHandler$p(Landroidx/compose/ui/platform/AndroidUiDispatcher;)Landroid/os/Handler;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$getLock$p(Landroidx/compose/ui/platform/AndroidUiDispatcher;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$getMain$delegate$cp()Lkotlin/Lazy;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$getToRunOnFrame$p(Landroidx/compose/ui/platform/AndroidUiDispatcher;)Ljava/util/List;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$performFrameDispatch(Landroidx/compose/ui/platform/AndroidUiDispatcher;J)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$performTrampolineDispatch(Landroidx/compose/ui/platform/AndroidUiDispatcher;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->access$setScheduledFrameDispatch$p(Landroidx/compose/ui/platform/AndroidUiDispatcher;Z)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->dispatch(Lkotlin/coroutines/CoroutineContext;Ljava/lang/Runnable;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->getChoreographer()Landroid/view/Choreographer;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->getFrameClock()Landroidx/compose/runtime/MonotonicFrameClock;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->nextTask()Ljava/lang/Runnable;
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->performFrameDispatch(J)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->performTrampolineDispatch()V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher;->postFrameCallback$ui_release(Landroid/view/Choreographer$FrameCallback;)V
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher_androidKt;->access$isMainThread()Z
-HSPLandroidx/compose/ui/platform/AndroidUiDispatcher_androidKt;->isMainThread()Z
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock$withFrameNanos$2$1;-><init>(Landroidx/compose/ui/platform/AndroidUiDispatcher;Landroid/view/Choreographer$FrameCallback;)V
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock$withFrameNanos$2$callback$1;-><init>(Lkotlinx/coroutines/CancellableContinuation;Landroidx/compose/ui/platform/AndroidUiFrameClock;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock$withFrameNanos$2$callback$1;->doFrame(J)V
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;-><init>(Landroid/view/Choreographer;)V
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;->getChoreographer()Landroid/view/Choreographer;
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/platform/AndroidUiFrameClock;->withFrameNanos(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/AndroidUriHandler;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidUriHandler;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/ui/platform/AndroidViewConfiguration;-><clinit>()V
-HSPLandroidx/compose/ui/platform/AndroidViewConfiguration;-><init>(Landroid/view/ViewConfiguration;)V
-HSPLandroidx/compose/ui/platform/AndroidViewConfiguration;->getTouchSlop()F
-HSPLandroidx/compose/ui/platform/CalculateMatrixToWindowApi29;-><init>()V
-HSPLandroidx/compose/ui/platform/CalculateMatrixToWindowApi29;->calculateMatrixToWindow-EL8BTi8(Landroid/view/View;[F)V
-HSPLandroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt$lambda-1$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt$lambda-1$1;-><init>()V
-HSPLandroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt;-><init>()V
-HSPLandroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt;->getLambda-1$ui_release()Lkotlin/jvm/functions/Function2;
-HSPLandroidx/compose/ui/platform/ComposeView$Content$1;-><init>(Landroidx/compose/ui/platform/ComposeView;I)V
-HSPLandroidx/compose/ui/platform/ComposeView;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ComposeView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;I)V
-HSPLandroidx/compose/ui/platform/ComposeView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/ComposeView;->Content(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/ComposeView;->getShouldCreateCompositionOnAttachedToWindow()Z
-HSPLandroidx/compose/ui/platform/ComposeView;->setContent(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalAccessibilityManager$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalAccessibilityManager$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalAutofill$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalAutofill$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalAutofillTree$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalAutofillTree$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalClipboardManager$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalClipboardManager$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalDensity$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalDensity$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalFocusManager$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalFocusManager$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalFontFamilyResolver$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalFontFamilyResolver$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalFontLoader$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalFontLoader$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalHapticFeedback$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalHapticFeedback$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalInputModeManager$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalInputModeManager$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalLayoutDirection$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalLayoutDirection$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalPointerIconService$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalPointerIconService$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalTextInputService$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalTextInputService$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalTextToolbar$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalTextToolbar$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalUriHandler$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalUriHandler$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalViewConfiguration$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalViewConfiguration$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalWindowInfo$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$LocalWindowInfo$1;-><init>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt$ProvideCommonCompositionLocals$1;-><init>(Landroidx/compose/ui/node/Owner;Landroidx/compose/ui/platform/UriHandler;Lkotlin/jvm/functions/Function2;I)V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->ProvideCommonCompositionLocals(Landroidx/compose/ui/node/Owner;Landroidx/compose/ui/platform/UriHandler;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->getLocalAccessibilityManager()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->getLocalDensity()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->getLocalFontFamilyResolver()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->getLocalInputModeManager()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->getLocalLayoutDirection()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/CompositionLocalsKt;->getLocalViewConfiguration()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry;->canBeSaved(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry;->consumeRestored(Ljava/lang/String;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry;->dispose()V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry;->registerProvider(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Landroidx/compose/runtime/saveable/SaveableStateRegistry$Entry;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$1;-><init>(ZLandroidx/savedstate/SavedStateRegistry;Ljava/lang/String;)V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$1;->invoke()V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$registered$1;-><init>(Landroidx/compose/runtime/saveable/SaveableStateRegistry;)V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$saveableStateRegistry$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$saveableStateRegistry$1;-><init>()V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$saveableStateRegistry$1;->invoke(Ljava/lang/Object;)Ljava/lang/Boolean;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$saveableStateRegistry$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt;->DisposableSaveableStateRegistry(Landroid/view/View;Landroidx/savedstate/SavedStateRegistryOwner;)Landroidx/compose/ui/platform/DisposableSaveableStateRegistry;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt;->DisposableSaveableStateRegistry(Ljava/lang/String;Landroidx/savedstate/SavedStateRegistryOwner;)Landroidx/compose/ui/platform/DisposableSaveableStateRegistry;
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt;->access$canBeSavedToBundle(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt;->canBeSavedToBundle(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$1;-><init>(Lkotlinx/coroutines/channels/Channel;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$2;-><init>(Lkotlinx/coroutines/channels/Channel;)V
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$2;->invoke(Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager;-><clinit>()V
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager;-><init>()V
-HSPLandroidx/compose/ui/platform/GlobalSnapshotManager;->ensureStarted()V
-HSPLandroidx/compose/ui/platform/InspectableModifier$End;-><init>(Landroidx/compose/ui/platform/InspectableModifier;)V
-HSPLandroidx/compose/ui/platform/InspectableModifier;-><clinit>()V
-HSPLandroidx/compose/ui/platform/InspectableModifier;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/platform/InspectableModifier;->getEnd()Landroidx/compose/ui/platform/InspectableModifier$End;
-HSPLandroidx/compose/ui/platform/InspectableValueKt$NoInspectorInfo$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/InspectableValueKt$NoInspectorInfo$1;-><init>()V
-HSPLandroidx/compose/ui/platform/InspectableValueKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/InspectableValueKt;->getNoInspectorInfo()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/platform/InspectableValueKt;->inspectableWrapper(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/platform/InspectableValueKt;->isDebugInspectorInfoEnabled()Z
-HSPLandroidx/compose/ui/platform/InspectorValueInfo;-><clinit>()V
-HSPLandroidx/compose/ui/platform/InspectorValueInfo;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/platform/InvertMatrixKt;->invertTo-JiSxe2E([F[F)Z
-HSPLandroidx/compose/ui/platform/LayerMatrixCache;-><init>(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/LayerMatrixCache;->calculateInverseMatrix-bWbORWo(Ljava/lang/Object;)[F
-HSPLandroidx/compose/ui/platform/LayerMatrixCache;->calculateMatrix-GrdbGEg(Ljava/lang/Object;)[F
-HSPLandroidx/compose/ui/platform/LayerMatrixCache;->invalidate()V
-HSPLandroidx/compose/ui/platform/MotionDurationScaleImpl;-><init>()V
-HSPLandroidx/compose/ui/platform/MotionDurationScaleImpl;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/MotionDurationScaleImpl;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLandroidx/compose/ui/platform/MotionDurationScaleImpl;->getScaleFactor()F
-HSPLandroidx/compose/ui/platform/MotionDurationScaleImpl;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLandroidx/compose/ui/platform/MotionDurationScaleImpl;->setScaleFactor(F)V
-HSPLandroidx/compose/ui/platform/OutlineResolver;-><init>(Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/platform/OutlineResolver;->getOutline()Landroid/graphics/Outline;
-HSPLandroidx/compose/ui/platform/OutlineResolver;->getOutlineClipSupported()Z
-HSPLandroidx/compose/ui/platform/OutlineResolver;->isInOutline-k-4lQ0M(J)Z
-HSPLandroidx/compose/ui/platform/OutlineResolver;->update(Landroidx/compose/ui/graphics/Shape;FZFLandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;)Z
-HSPLandroidx/compose/ui/platform/OutlineResolver;->update-uvyYCjk(J)V
-HSPLandroidx/compose/ui/platform/OutlineResolver;->updateCache()V
-HSPLandroidx/compose/ui/platform/OutlineResolver;->updateCacheWithPath(Landroidx/compose/ui/graphics/Path;)V
-HSPLandroidx/compose/ui/platform/OutlineResolver;->updateCacheWithRect(Landroidx/compose/ui/geometry/Rect;)V
-HSPLandroidx/compose/ui/platform/OutlineResolver;->updateCacheWithRoundRect(Landroidx/compose/ui/geometry/RoundRect;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->discardDisplayList()V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->drawInto(Landroid/graphics/Canvas;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getAlpha()F
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getClipToBounds()Z
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getClipToOutline()Z
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getElevation()F
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getHasDisplayList()Z
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getHeight()I
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getLeft()I
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getMatrix(Landroid/graphics/Matrix;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getTop()I
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->getWidth()I
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->offsetLeftAndRight(I)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->offsetTopAndBottom(I)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->record(Landroidx/compose/ui/graphics/CanvasHolder;Landroidx/compose/ui/graphics/Path;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setAlpha(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setAmbientShadowColor(I)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setCameraDistance(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setClipToBounds(Z)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setClipToOutline(Z)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setCompositingStrategy-aDBOjCE(I)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setElevation(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setHasOverlappingRendering(Z)Z
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setOutline(Landroid/graphics/Outline;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setPivotX(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setPivotY(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setPosition(IIII)Z
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setRenderEffect(Landroidx/compose/ui/graphics/RenderEffect;)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setRotationX(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setRotationY(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setRotationZ(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setScaleX(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setScaleY(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setSpotShadowColor(I)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setTranslationX(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29;->setTranslationY(F)V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29VerificationHelper;-><clinit>()V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29VerificationHelper;-><init>()V
-HSPLandroidx/compose/ui/platform/RenderNodeApi29VerificationHelper;->setRenderEffect(Landroid/graphics/RenderNode;Landroidx/compose/ui/graphics/RenderEffect;)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer$Companion$getMatrix$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer$Companion$getMatrix$1;-><init>()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer$Companion$getMatrix$1;->invoke(Landroidx/compose/ui/platform/DeviceRenderNode;Landroid/graphics/Matrix;)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer$Companion$getMatrix$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/RenderNodeLayer$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;-><clinit>()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->destroy()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->drawLayer(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->invalidate()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->isInLayer-k-4lQ0M(J)Z
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->mapOffset-8S9VItk(JZ)J
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->move--gyyYBs(J)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->resize-ozmzZPI(J)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->reuseLayer(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->setDirty(Z)V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->triggerRepaint()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->updateDisplayList()V
-HSPLandroidx/compose/ui/platform/RenderNodeLayer;->updateLayerProperties-dDxr-wY(FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/platform/ShapeContainingUtilKt;->cornersFit(Landroidx/compose/ui/geometry/RoundRect;)Z
-HSPLandroidx/compose/ui/platform/ShapeContainingUtilKt;->isInOutline(Landroidx/compose/ui/graphics/Outline;FFLandroidx/compose/ui/graphics/Path;Landroidx/compose/ui/graphics/Path;)Z
-HSPLandroidx/compose/ui/platform/ShapeContainingUtilKt;->isInRectangle(Landroidx/compose/ui/geometry/Rect;FF)Z
-HSPLandroidx/compose/ui/platform/ShapeContainingUtilKt;->isInRoundedRect(Landroidx/compose/ui/graphics/Outline$Rounded;FFLandroidx/compose/ui/graphics/Path;Landroidx/compose/ui/graphics/Path;)Z
-HSPLandroidx/compose/ui/platform/ShapeContainingUtilKt;->isWithinEllipse-VE1yxkc(FFJFF)Z
-HSPLandroidx/compose/ui/platform/TextToolbarStatus;->$values()[Landroidx/compose/ui/platform/TextToolbarStatus;
-HSPLandroidx/compose/ui/platform/TextToolbarStatus;-><clinit>()V
-HSPLandroidx/compose/ui/platform/TextToolbarStatus;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$Companion;->getDefault()Landroidx/compose/ui/platform/ViewCompositionStrategy;
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$1;-><init>(Landroidx/compose/ui/platform/AbstractComposeView;Landroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$listener$1;Landroidx/customview/poolingcontainer/PoolingContainerListener;)V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$listener$1;-><init>(Landroidx/compose/ui/platform/AbstractComposeView;)V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$listener$1;->onViewAttachedToWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$listener$1;->onViewDetachedFromWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$poolingContainerListener$1;-><init>(Landroidx/compose/ui/platform/AbstractComposeView;)V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool;-><init>()V
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool;->installFor(Landroidx/compose/ui/platform/AbstractComposeView;)Lkotlin/jvm/functions/Function0;
-HSPLandroidx/compose/ui/platform/ViewCompositionStrategy;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ViewConfiguration;->getMinimumTouchTargetSize-MYxV2XQ()J
-HSPLandroidx/compose/ui/platform/ViewLayer$Companion$OutlineProvider$1;-><init>()V
-HSPLandroidx/compose/ui/platform/ViewLayer$Companion$getMatrix$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ViewLayer$Companion$getMatrix$1;-><init>()V
-HSPLandroidx/compose/ui/platform/ViewLayer$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/ViewLayer$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/ViewLayer$Companion;->getShouldUseDispatchDraw()Z
-HSPLandroidx/compose/ui/platform/ViewLayer;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ViewLayer;->access$getShouldUseDispatchDraw$cp()Z
-HSPLandroidx/compose/ui/platform/ViewRootForTest$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/platform/ViewRootForTest$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/ViewRootForTest$Companion;->getOnViewCreatedCallback()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/platform/ViewRootForTest;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WeakCache;-><init>()V
-HSPLandroidx/compose/ui/platform/WeakCache;->clearWeakReferences()V
-HSPLandroidx/compose/ui/platform/WeakCache;->pop()Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WeakCache;->push(Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/platform/WindowInfoImpl$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/WindowInfoImpl$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/platform/WindowInfoImpl;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowInfoImpl;-><init>()V
-HSPLandroidx/compose/ui/platform/WindowInfoImpl;->setKeyboardModifiers-5xRPYO0(I)V
-HSPLandroidx/compose/ui/platform/WindowInfoImpl;->setWindowFocused(Z)V
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory$Companion$LifecycleAware$1;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory$Companion$LifecycleAware$1;-><init>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory$Companion$LifecycleAware$1;->createRecomposer(Landroid/view/View;)Landroidx/compose/runtime/Recomposer;
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory$Companion;-><init>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory$Companion;->getLifecycleAware()Landroidx/compose/ui/platform/WindowRecomposerFactory;
-HSPLandroidx/compose/ui/platform/WindowRecomposerFactory;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$1;-><init>(Lkotlinx/coroutines/Job;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$1;->onViewAttachedToWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$1;->onViewDetachedFromWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$unsetJob$1;-><init>(Landroidx/compose/runtime/Recomposer;Landroid/view/View;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$unsetJob$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$unsetJob$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy;-><init>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy;->createAndInstallWindowRecomposer$ui_release(Landroid/view/View;)Landroidx/compose/runtime/Recomposer;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$1;-><init>(Landroid/view/View;Landroidx/compose/runtime/Recomposer;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$1;->onViewAttachedToWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$1;->onViewDetachedFromWindow(Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1$1;-><init>(Landroidx/compose/ui/platform/MotionDurationScaleImpl;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1$1;->emit(FLkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1$1;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1;-><init>(Lkotlinx/coroutines/flow/StateFlow;Landroidx/compose/ui/platform/MotionDurationScaleImpl;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1;-><init>(Lkotlin/jvm/internal/Ref$ObjectRef;Landroidx/compose/runtime/Recomposer;Landroidx/lifecycle/LifecycleOwner;Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2;Landroid/view/View;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2;-><init>(Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/runtime/PausableMonotonicFrameClock;Landroidx/compose/runtime/Recomposer;Lkotlin/jvm/internal/Ref$ObjectRef;Landroid/view/View;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$1;-><init>(Landroid/content/ContentResolver;Landroid/net/Uri;Landroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$contentObserver$1;Lkotlinx/coroutines/channels/Channel;Landroid/content/Context;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$contentObserver$1;-><init>(Lkotlinx/coroutines/channels/Channel;Landroid/os/Handler;)V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->access$getAnimationScaleFlowFor(Landroid/content/Context;)Lkotlinx/coroutines/flow/StateFlow;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->createLifecycleAwareWindowRecomposer$default(Landroid/view/View;Lkotlin/coroutines/CoroutineContext;Landroidx/lifecycle/Lifecycle;ILjava/lang/Object;)Landroidx/compose/runtime/Recomposer;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->createLifecycleAwareWindowRecomposer(Landroid/view/View;Lkotlin/coroutines/CoroutineContext;Landroidx/lifecycle/Lifecycle;)Landroidx/compose/runtime/Recomposer;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->findViewTreeCompositionContext(Landroid/view/View;)Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->getAnimationScaleFlowFor(Landroid/content/Context;)Lkotlinx/coroutines/flow/StateFlow;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->getCompositionContext(Landroid/view/View;)Landroidx/compose/runtime/CompositionContext;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->getContentChild(Landroid/view/View;)Landroid/view/View;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->getWindowRecomposer(Landroid/view/View;)Landroidx/compose/runtime/Recomposer;
-HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt;->setCompositionContext(Landroid/view/View;Landroidx/compose/runtime/CompositionContext;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$1;-><init>(Landroidx/compose/ui/platform/WrappedComposition;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$2;-><init>(Landroidx/compose/ui/platform/WrappedComposition;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$3;-><init>(Landroidx/compose/ui/platform/WrappedComposition;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$3;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1;-><init>(Landroidx/compose/ui/platform/WrappedComposition;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1;-><init>(Landroidx/compose/ui/platform/WrappedComposition;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1;->invoke(Landroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition$setContent$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/platform/WrappedComposition;-><init>(Landroidx/compose/ui/platform/AndroidComposeView;Landroidx/compose/runtime/Composition;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition;->access$getAddedToLifecycle$p(Landroidx/compose/ui/platform/WrappedComposition;)Landroidx/lifecycle/Lifecycle;
-HSPLandroidx/compose/ui/platform/WrappedComposition;->access$getDisposed$p(Landroidx/compose/ui/platform/WrappedComposition;)Z
-HSPLandroidx/compose/ui/platform/WrappedComposition;->access$setAddedToLifecycle$p(Landroidx/compose/ui/platform/WrappedComposition;Landroidx/lifecycle/Lifecycle;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition;->access$setLastContent$p(Landroidx/compose/ui/platform/WrappedComposition;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition;->dispose()V
-HSPLandroidx/compose/ui/platform/WrappedComposition;->getOriginal()Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/platform/WrappedComposition;->getOwner()Landroidx/compose/ui/platform/AndroidComposeView;
-HSPLandroidx/compose/ui/platform/WrappedComposition;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/compose/ui/platform/WrappedComposition;->setContent(Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/platform/WrapperRenderNodeLayerHelperMethods;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WrapperRenderNodeLayerHelperMethods;-><init>()V
-HSPLandroidx/compose/ui/platform/WrapperRenderNodeLayerHelperMethods;->onDescendantInvalidated(Landroidx/compose/ui/platform/AndroidComposeView;)V
-HSPLandroidx/compose/ui/platform/WrapperVerificationHelperMethods;-><clinit>()V
-HSPLandroidx/compose/ui/platform/WrapperVerificationHelperMethods;-><init>()V
-HSPLandroidx/compose/ui/platform/WrapperVerificationHelperMethods;->attributeSourceResourceMap(Landroid/view/View;)Ljava/util/Map;
-HSPLandroidx/compose/ui/platform/Wrapper_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/platform/Wrapper_androidKt;->createSubcomposition(Landroidx/compose/ui/node/LayoutNode;Landroidx/compose/runtime/CompositionContext;)Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/platform/Wrapper_androidKt;->doSetContent(Landroidx/compose/ui/platform/AndroidComposeView;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;)Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/platform/Wrapper_androidKt;->inspectionWanted(Landroidx/compose/ui/platform/AndroidComposeView;)Z
-HSPLandroidx/compose/ui/platform/Wrapper_androidKt;->setContent(Landroidx/compose/ui/platform/AbstractComposeView;Landroidx/compose/runtime/CompositionContext;Lkotlin/jvm/functions/Function2;)Landroidx/compose/runtime/Composition;
-HSPLandroidx/compose/ui/platform/actionmodecallback/TextActionModeCallback;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/geometry/Rect;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/platform/actionmodecallback/TextActionModeCallback;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/geometry/Rect;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/res/ImageVectorCache;-><init>()V
-HSPLandroidx/compose/ui/res/Resources_androidKt;->resources(Landroidx/compose/runtime/Composer;I)Landroid/content/res/Resources;
-HSPLandroidx/compose/ui/res/StringResources_androidKt;->stringResource(ILandroidx/compose/runtime/Composer;I)Ljava/lang/String;
-HSPLandroidx/compose/ui/semantics/AccessibilityAction;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/AccessibilityAction;-><init>(Ljava/lang/String;Lkotlin/Function;)V
-HSPLandroidx/compose/ui/semantics/AccessibilityAction;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/semantics/CollectionInfo;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/CollectionInfo;-><init>(II)V
-HSPLandroidx/compose/ui/semantics/Role$Companion;-><init>()V
-HSPLandroidx/compose/ui/semantics/Role$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/semantics/Role$Companion;->getButton-o7Vup1c()I
-HSPLandroidx/compose/ui/semantics/Role$Companion;->getImage-o7Vup1c()I
-HSPLandroidx/compose/ui/semantics/Role;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/Role;-><init>(I)V
-HSPLandroidx/compose/ui/semantics/Role;->access$getButton$cp()I
-HSPLandroidx/compose/ui/semantics/Role;->access$getImage$cp()I
-HSPLandroidx/compose/ui/semantics/Role;->box-impl(I)Landroidx/compose/ui/semantics/Role;
-HSPLandroidx/compose/ui/semantics/Role;->constructor-impl(I)I
-HSPLandroidx/compose/ui/semantics/Role;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/semantics/Role;->equals-impl(ILjava/lang/Object;)Z
-HSPLandroidx/compose/ui/semantics/Role;->unbox-impl()I
-HSPLandroidx/compose/ui/semantics/ScrollAxisRange;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/ScrollAxisRange;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Z)V
-HSPLandroidx/compose/ui/semantics/SemanticsActions;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsActions;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getCustomActions()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getDismiss()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getGetTextLayoutResult()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getOnClick()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getRequestFocus()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getScrollBy()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsActions;->getScrollToIndex()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->contains(Landroidx/compose/ui/semantics/SemanticsPropertyKey;)Z
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->getOrElseNullable(Landroidx/compose/ui/semantics/SemanticsPropertyKey;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->isClearingSemantics()Z
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->set(Landroidx/compose/ui/semantics/SemanticsPropertyKey;Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->setClearingSemantics(Z)V
-HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->setMergingSemanticsOfDescendants(Z)V
-HSPLandroidx/compose/ui/semantics/SemanticsConfigurationKt$getOrNull$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsConfigurationKt$getOrNull$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsConfigurationKt$getOrNull$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/semantics/SemanticsConfigurationKt;->getOrNull(Landroidx/compose/ui/semantics/SemanticsConfiguration;Landroidx/compose/ui/semantics/SemanticsPropertyKey;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore$Companion;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore$Companion;->generateSemanticsId()I
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;-><init>(ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;-><init>(ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;->access$getLastIdentifier$cp()Ljava/util/concurrent/atomic/AtomicInteger;
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;->getSemanticsConfiguration()Landroidx/compose/ui/semantics/SemanticsConfiguration;
-HSPLandroidx/compose/ui/semantics/SemanticsModifierKt;->semantics$default(Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/semantics/SemanticsModifierKt;->semantics(Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier;
-HSPLandroidx/compose/ui/semantics/SemanticsNode;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsNode;-><init>(Landroidx/compose/ui/node/SemanticsModifierNode;ZLandroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/semantics/SemanticsNode;-><init>(Landroidx/compose/ui/node/SemanticsModifierNode;ZLandroidx/compose/ui/node/LayoutNode;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/semantics/SemanticsNode;->emitFakeNodes(Ljava/util/List;)V
-HSPLandroidx/compose/ui/semantics/SemanticsNode;->getChildren(ZZZ)Ljava/util/List;
-HSPLandroidx/compose/ui/semantics/SemanticsNode;->getReplacedChildren$ui_release()Ljava/util/List;
-HSPLandroidx/compose/ui/semantics/SemanticsNode;->getUnmergedConfig$ui_release()Landroidx/compose/ui/semantics/SemanticsConfiguration;
-HSPLandroidx/compose/ui/semantics/SemanticsNode;->isMergingSemanticsOfDescendants()Z
-HSPLandroidx/compose/ui/semantics/SemanticsNode;->unmergedChildren$ui_release(ZZ)Ljava/util/List;
-HSPLandroidx/compose/ui/semantics/SemanticsNodeKt;->access$getRole(Landroidx/compose/ui/semantics/SemanticsNode;)Landroidx/compose/ui/semantics/Role;
-HSPLandroidx/compose/ui/semantics/SemanticsNodeKt;->findOneLayerOfSemanticsWrappers$default(Landroidx/compose/ui/node/LayoutNode;Ljava/util/List;ILjava/lang/Object;)Ljava/util/List;
-HSPLandroidx/compose/ui/semantics/SemanticsNodeKt;->findOneLayerOfSemanticsWrappers(Landroidx/compose/ui/node/LayoutNode;Ljava/util/List;)Ljava/util/List;
-HSPLandroidx/compose/ui/semantics/SemanticsNodeKt;->getOuterSemantics(Landroidx/compose/ui/node/LayoutNode;)Landroidx/compose/ui/node/SemanticsModifierNode;
-HSPLandroidx/compose/ui/semantics/SemanticsNodeKt;->getRole(Landroidx/compose/ui/semantics/SemanticsNode;)Landroidx/compose/ui/semantics/Role;
-HSPLandroidx/compose/ui/semantics/SemanticsOwner;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsOwner;-><init>(Landroidx/compose/ui/node/LayoutNode;)V
-HSPLandroidx/compose/ui/semantics/SemanticsOwner;->getUnmergedRootSemanticsNode()Landroidx/compose/ui/semantics/SemanticsNode;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$ContentDescription$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$ContentDescription$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$InvisibleToUser$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$InvisibleToUser$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$IsDialog$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$IsDialog$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$IsPopup$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$IsPopup$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$PaneTitle$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$PaneTitle$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$Role$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$Role$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$TestTag$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$TestTag$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$Text$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties$Text$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getCollectionInfo()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getCollectionItemInfo()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getContentDescription()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getEditableText()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getFocused()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getHorizontalScrollAxisRange()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getImeAction()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getIndexForKey()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getIsContainer()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getLiveRegion()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getPaneTitle()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getProgressBarRangeInfo()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getRole()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getSelected()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getStateDescription()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getTestTag()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getText()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getTextSelectionRange()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getToggleableState()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsProperties;->getVerticalScrollAxisRange()Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt$ActionPropertyKey$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt$ActionPropertyKey$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->dismiss$default(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->dismiss(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->getTextLayoutResult$default(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->getTextLayoutResult(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->indexForKey(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->onClick$default(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->onClick(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->requestFocus$default(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->requestFocus(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->scrollBy$default(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->scrollBy(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->scrollToIndex$default(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->scrollToIndex(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setCollectionInfo(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Landroidx/compose/ui/semantics/CollectionInfo;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setContainer(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Z)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setContentDescription(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setFocused(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Z)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setRole-kuIjeqM(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;I)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setText(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Landroidx/compose/ui/text/AnnotatedString;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt;->setVerticalScrollAxisRange(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Landroidx/compose/ui/semantics/ScrollAxisRange;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertyKey$1;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertyKey$1;-><init>()V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertyKey;-><clinit>()V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertyKey;-><init>(Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertyKey;-><init>(Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/semantics/SemanticsPropertyKey;->setValue(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/text/AndroidParagraph$wordBoundary$2;-><init>(Landroidx/compose/ui/text/AndroidParagraph;)V
-HSPLandroidx/compose/ui/text/AndroidParagraph;-><init>(Landroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;IZJ)V
-HSPLandroidx/compose/ui/text/AndroidParagraph;-><init>(Landroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;IZJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/AndroidParagraph;->constructTextLayout(IILandroid/text/TextUtils$TruncateAt;IIIII)Landroidx/compose/ui/text/android/TextLayout;
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getDidExceedMaxLines()Z
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getFirstBaseline()F
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getHeight()F
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getLastBaseline()F
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getLineBaseline$ui_text_release(I)F
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getLineCount()I
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getPlaceholderRects()Ljava/util/List;
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getShaderBrushSpans(Landroidx/compose/ui/text/android/TextLayout;)[Landroidx/compose/ui/text/platform/style/ShaderBrushSpan;
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getTextPaint$ui_text_release()Landroidx/compose/ui/text/platform/AndroidTextPaint;
-HSPLandroidx/compose/ui/text/AndroidParagraph;->getWidth()F
-HSPLandroidx/compose/ui/text/AndroidParagraph;->paint(Landroidx/compose/ui/graphics/Canvas;)V
-HSPLandroidx/compose/ui/text/AndroidParagraph;->paint-iJQMabo(Landroidx/compose/ui/graphics/Canvas;JLandroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/drawscope/DrawStyle;)V
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->access$shouldAttachIndentationFixSpan(Landroidx/compose/ui/text/TextStyle;Z)Z
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->access$toLayoutAlign-AMY3VfE(Landroidx/compose/ui/text/style/TextAlign;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->access$toLayoutBreakStrategy-u6PBz3U(Landroidx/compose/ui/text/style/LineBreak$Strategy;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->access$toLayoutHyphenationFrequency-0_XeFpE(Landroidx/compose/ui/text/style/Hyphens;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->access$toLayoutLineBreakStyle-4a2g8L8(Landroidx/compose/ui/text/style/LineBreak$Strictness;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->access$toLayoutLineBreakWordStyle-gvcdTPQ(Landroidx/compose/ui/text/style/LineBreak$WordBreak;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->shouldAttachIndentationFixSpan(Landroidx/compose/ui/text/TextStyle;Z)Z
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->toLayoutAlign-AMY3VfE(Landroidx/compose/ui/text/style/TextAlign;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->toLayoutBreakStrategy-u6PBz3U(Landroidx/compose/ui/text/style/LineBreak$Strategy;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->toLayoutHyphenationFrequency-0_XeFpE(Landroidx/compose/ui/text/style/Hyphens;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->toLayoutLineBreakStyle-4a2g8L8(Landroidx/compose/ui/text/style/LineBreak$Strictness;)I
-HSPLandroidx/compose/ui/text/AndroidParagraph_androidKt;->toLayoutLineBreakWordStyle-gvcdTPQ(Landroidx/compose/ui/text/style/LineBreak$WordBreak;)I
-HSPLandroidx/compose/ui/text/AnnotatedString$Range;-><clinit>()V
-HSPLandroidx/compose/ui/text/AnnotatedString$Range;-><init>(Ljava/lang/Object;II)V
-HSPLandroidx/compose/ui/text/AnnotatedString$Range;-><init>(Ljava/lang/Object;IILjava/lang/String;)V
-HSPLandroidx/compose/ui/text/AnnotatedString$Range;->getEnd()I
-HSPLandroidx/compose/ui/text/AnnotatedString$Range;->getItem()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/AnnotatedString$Range;->getStart()I
-HSPLandroidx/compose/ui/text/AnnotatedString;-><clinit>()V
-HSPLandroidx/compose/ui/text/AnnotatedString;-><init>(Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
-HSPLandroidx/compose/ui/text/AnnotatedString;-><init>(Ljava/lang/String;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/AnnotatedString;-><init>(Ljava/lang/String;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V
-HSPLandroidx/compose/ui/text/AnnotatedString;-><init>(Ljava/lang/String;Ljava/util/List;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/AnnotatedString;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/AnnotatedString;->getParagraphStylesOrNull$ui_text_release()Ljava/util/List;
-HSPLandroidx/compose/ui/text/AnnotatedString;->getSpanStyles()Ljava/util/List;
-HSPLandroidx/compose/ui/text/AnnotatedString;->getSpanStylesOrNull$ui_text_release()Ljava/util/List;
-HSPLandroidx/compose/ui/text/AnnotatedString;->getText()Ljava/lang/String;
-HSPLandroidx/compose/ui/text/AnnotatedStringKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/AnnotatedStringKt;->access$substringWithoutParagraphStyles(Landroidx/compose/ui/text/AnnotatedString;II)Landroidx/compose/ui/text/AnnotatedString;
-HSPLandroidx/compose/ui/text/AnnotatedStringKt;->getLocalSpanStyles(Landroidx/compose/ui/text/AnnotatedString;II)Ljava/util/List;
-HSPLandroidx/compose/ui/text/AnnotatedStringKt;->normalizedParagraphStyles(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/ParagraphStyle;)Ljava/util/List;
-HSPLandroidx/compose/ui/text/AnnotatedStringKt;->substringWithoutParagraphStyles(Landroidx/compose/ui/text/AnnotatedString;II)Landroidx/compose/ui/text/AnnotatedString;
-HSPLandroidx/compose/ui/text/EmojiSupportMatch$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/EmojiSupportMatch$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/EmojiSupportMatch$Companion;->getNone-_3YsG6Y()I
-HSPLandroidx/compose/ui/text/EmojiSupportMatch;-><clinit>()V
-HSPLandroidx/compose/ui/text/EmojiSupportMatch;->access$getNone$cp()I
-HSPLandroidx/compose/ui/text/EmojiSupportMatch;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/MultiParagraph;-><clinit>()V
-HSPLandroidx/compose/ui/text/MultiParagraph;-><init>(Landroidx/compose/ui/text/MultiParagraphIntrinsics;JIZ)V
-HSPLandroidx/compose/ui/text/MultiParagraph;-><init>(Landroidx/compose/ui/text/MultiParagraphIntrinsics;JIZLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/MultiParagraph;->getDidExceedMaxLines()Z
-HSPLandroidx/compose/ui/text/MultiParagraph;->getFirstBaseline()F
-HSPLandroidx/compose/ui/text/MultiParagraph;->getHeight()F
-HSPLandroidx/compose/ui/text/MultiParagraph;->getIntrinsics()Landroidx/compose/ui/text/MultiParagraphIntrinsics;
-HSPLandroidx/compose/ui/text/MultiParagraph;->getLastBaseline()F
-HSPLandroidx/compose/ui/text/MultiParagraph;->getPlaceholderRects()Ljava/util/List;
-HSPLandroidx/compose/ui/text/MultiParagraph;->getWidth()F
-HSPLandroidx/compose/ui/text/MultiParagraph;->paint-iJQMabo(Landroidx/compose/ui/graphics/Canvas;JLandroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/drawscope/DrawStyle;)V
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics$maxIntrinsicWidth$2;-><init>(Landroidx/compose/ui/text/MultiParagraphIntrinsics;)V
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics$maxIntrinsicWidth$2;->invoke()Ljava/lang/Float;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics$maxIntrinsicWidth$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics$minIntrinsicWidth$2;-><init>(Landroidx/compose/ui/text/MultiParagraphIntrinsics;)V
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;-><clinit>()V
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;)V
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;->access$resolveTextDirection(Landroidx/compose/ui/text/MultiParagraphIntrinsics;Landroidx/compose/ui/text/ParagraphStyle;Landroidx/compose/ui/text/ParagraphStyle;)Landroidx/compose/ui/text/ParagraphStyle;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;->getHasStaleResolvedFonts()Z
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;->getInfoList$ui_text_release()Ljava/util/List;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;->getMaxIntrinsicWidth()F
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;->getPlaceholders()Ljava/util/List;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics;->resolveTextDirection(Landroidx/compose/ui/text/ParagraphStyle;Landroidx/compose/ui/text/ParagraphStyle;)Landroidx/compose/ui/text/ParagraphStyle;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsicsKt;->access$getLocalPlaceholders(Ljava/util/List;II)Ljava/util/List;
-HSPLandroidx/compose/ui/text/MultiParagraphIntrinsicsKt;->getLocalPlaceholders(Ljava/util/List;II)Ljava/util/List;
-HSPLandroidx/compose/ui/text/ParagraphInfo;-><init>(Landroidx/compose/ui/text/Paragraph;IIIIFF)V
-HSPLandroidx/compose/ui/text/ParagraphInfo;->getParagraph()Landroidx/compose/ui/text/Paragraph;
-HSPLandroidx/compose/ui/text/ParagraphInfo;->toGlobalYPosition(F)F
-HSPLandroidx/compose/ui/text/ParagraphIntrinsicInfo;-><init>(Landroidx/compose/ui/text/ParagraphIntrinsics;II)V
-HSPLandroidx/compose/ui/text/ParagraphIntrinsicInfo;->getEndIndex()I
-HSPLandroidx/compose/ui/text/ParagraphIntrinsicInfo;->getIntrinsics()Landroidx/compose/ui/text/ParagraphIntrinsics;
-HSPLandroidx/compose/ui/text/ParagraphIntrinsicInfo;->getStartIndex()I
-HSPLandroidx/compose/ui/text/ParagraphIntrinsicsKt;->ParagraphIntrinsics(Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;)Landroidx/compose/ui/text/ParagraphIntrinsics;
-HSPLandroidx/compose/ui/text/ParagraphKt;->Paragraph-_EkL_-Y(Landroidx/compose/ui/text/ParagraphIntrinsics;JIZ)Landroidx/compose/ui/text/Paragraph;
-HSPLandroidx/compose/ui/text/ParagraphKt;->ceilToInt(F)I
-HSPLandroidx/compose/ui/text/ParagraphStyle;-><clinit>()V
-HSPLandroidx/compose/ui/text/ParagraphStyle;-><init>(Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformParagraphStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;)V
-HSPLandroidx/compose/ui/text/ParagraphStyle;-><init>(Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformParagraphStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;Landroidx/compose/ui/text/style/TextMotion;)V
-HSPLandroidx/compose/ui/text/ParagraphStyle;-><init>(Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformParagraphStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;Landroidx/compose/ui/text/style/TextMotion;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/ParagraphStyle;-><init>(Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformParagraphStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/ParagraphStyle;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getHyphens-EaSxIns()Landroidx/compose/ui/text/style/Hyphens;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getLineBreak-LgCVezo()Landroidx/compose/ui/text/style/LineBreak;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getLineHeight-XSAIIZE()J
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getLineHeightStyle()Landroidx/compose/ui/text/style/LineHeightStyle;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getPlatformStyle()Landroidx/compose/ui/text/PlatformParagraphStyle;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getTextAlign-buA522U()Landroidx/compose/ui/text/style/TextAlign;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getTextDirection-mmuk1to()Landroidx/compose/ui/text/style/TextDirection;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getTextIndent()Landroidx/compose/ui/text/style/TextIndent;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->getTextMotion()Landroidx/compose/ui/text/style/TextMotion;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->merge(Landroidx/compose/ui/text/ParagraphStyle;)Landroidx/compose/ui/text/ParagraphStyle;
-HSPLandroidx/compose/ui/text/ParagraphStyle;->mergePlatformStyle(Landroidx/compose/ui/text/PlatformParagraphStyle;)Landroidx/compose/ui/text/PlatformParagraphStyle;
-HSPLandroidx/compose/ui/text/ParagraphStyleKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/ParagraphStyleKt;->resolveParagraphStyleDefaults(Landroidx/compose/ui/text/ParagraphStyle;Landroidx/compose/ui/unit/LayoutDirection;)Landroidx/compose/ui/text/ParagraphStyle;
-HSPLandroidx/compose/ui/text/SpanStyle;-><clinit>()V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/PlatformSpanStyle;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/PlatformSpanStyle;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(Landroidx/compose/ui/text/style/TextForegroundStyle;JLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/PlatformSpanStyle;Landroidx/compose/ui/graphics/drawscope/DrawStyle;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(Landroidx/compose/ui/text/style/TextForegroundStyle;JLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/PlatformSpanStyle;Landroidx/compose/ui/graphics/drawscope/DrawStyle;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/SpanStyle;-><init>(Landroidx/compose/ui/text/style/TextForegroundStyle;JLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/PlatformSpanStyle;Landroidx/compose/ui/graphics/drawscope/DrawStyle;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/SpanStyle;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/SpanStyle;->getAlpha()F
-HSPLandroidx/compose/ui/text/SpanStyle;->getBackground-0d7_KjU()J
-HSPLandroidx/compose/ui/text/SpanStyle;->getBaselineShift-5SSeXJ0()Landroidx/compose/ui/text/style/BaselineShift;
-HSPLandroidx/compose/ui/text/SpanStyle;->getBrush()Landroidx/compose/ui/graphics/Brush;
-HSPLandroidx/compose/ui/text/SpanStyle;->getColor-0d7_KjU()J
-HSPLandroidx/compose/ui/text/SpanStyle;->getDrawStyle()Landroidx/compose/ui/graphics/drawscope/DrawStyle;
-HSPLandroidx/compose/ui/text/SpanStyle;->getFontFamily()Landroidx/compose/ui/text/font/FontFamily;
-HSPLandroidx/compose/ui/text/SpanStyle;->getFontFeatureSettings()Ljava/lang/String;
-HSPLandroidx/compose/ui/text/SpanStyle;->getFontSize-XSAIIZE()J
-HSPLandroidx/compose/ui/text/SpanStyle;->getFontStyle-4Lr2A7w()Landroidx/compose/ui/text/font/FontStyle;
-HSPLandroidx/compose/ui/text/SpanStyle;->getFontSynthesis-ZQGJjVo()Landroidx/compose/ui/text/font/FontSynthesis;
-HSPLandroidx/compose/ui/text/SpanStyle;->getFontWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/SpanStyle;->getLetterSpacing-XSAIIZE()J
-HSPLandroidx/compose/ui/text/SpanStyle;->getLocaleList()Landroidx/compose/ui/text/intl/LocaleList;
-HSPLandroidx/compose/ui/text/SpanStyle;->getPlatformStyle()Landroidx/compose/ui/text/PlatformSpanStyle;
-HSPLandroidx/compose/ui/text/SpanStyle;->getShadow()Landroidx/compose/ui/graphics/Shadow;
-HSPLandroidx/compose/ui/text/SpanStyle;->getTextDecoration()Landroidx/compose/ui/text/style/TextDecoration;
-HSPLandroidx/compose/ui/text/SpanStyle;->getTextForegroundStyle$ui_text_release()Landroidx/compose/ui/text/style/TextForegroundStyle;
-HSPLandroidx/compose/ui/text/SpanStyle;->getTextGeometricTransform()Landroidx/compose/ui/text/style/TextGeometricTransform;
-HSPLandroidx/compose/ui/text/SpanStyle;->hasSameLayoutAffectingAttributes$ui_text_release(Landroidx/compose/ui/text/SpanStyle;)Z
-HSPLandroidx/compose/ui/text/SpanStyle;->hasSameNonLayoutAttributes(Landroidx/compose/ui/text/SpanStyle;)Z
-HSPLandroidx/compose/ui/text/SpanStyle;->merge(Landroidx/compose/ui/text/SpanStyle;)Landroidx/compose/ui/text/SpanStyle;
-HSPLandroidx/compose/ui/text/SpanStyle;->mergePlatformStyle(Landroidx/compose/ui/text/PlatformSpanStyle;)Landroidx/compose/ui/text/PlatformSpanStyle;
-HSPLandroidx/compose/ui/text/SpanStyleKt$resolveSpanStyleDefaults$1;-><clinit>()V
-HSPLandroidx/compose/ui/text/SpanStyleKt$resolveSpanStyleDefaults$1;-><init>()V
-HSPLandroidx/compose/ui/text/SpanStyleKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/SpanStyleKt;->resolveSpanStyleDefaults(Landroidx/compose/ui/text/SpanStyle;)Landroidx/compose/ui/text/SpanStyle;
-HSPLandroidx/compose/ui/text/TextLayoutInput;-><clinit>()V
-HSPLandroidx/compose/ui/text/TextLayoutInput;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;IZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/font/Font$ResourceLoader;Landroidx/compose/ui/text/font/FontFamily$Resolver;J)V
-HSPLandroidx/compose/ui/text/TextLayoutInput;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;IZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/font/FontFamily$Resolver;J)V
-HSPLandroidx/compose/ui/text/TextLayoutInput;-><init>(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;IZILandroidx/compose/ui/unit/Density;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/font/FontFamily$Resolver;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/TextLayoutInput;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/TextLayoutInput;->getStyle()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/TextLayoutInput;->getText()Landroidx/compose/ui/text/AnnotatedString;
-HSPLandroidx/compose/ui/text/TextLayoutResult;-><clinit>()V
-HSPLandroidx/compose/ui/text/TextLayoutResult;-><init>(Landroidx/compose/ui/text/TextLayoutInput;Landroidx/compose/ui/text/MultiParagraph;J)V
-HSPLandroidx/compose/ui/text/TextLayoutResult;-><init>(Landroidx/compose/ui/text/TextLayoutInput;Landroidx/compose/ui/text/MultiParagraph;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/TextLayoutResult;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getDidOverflowHeight()Z
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getDidOverflowWidth()Z
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getFirstBaseline()F
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getHasVisualOverflow()Z
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getLastBaseline()F
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getLayoutInput()Landroidx/compose/ui/text/TextLayoutInput;
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getMultiParagraph()Landroidx/compose/ui/text/MultiParagraph;
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getPlaceholderRects()Ljava/util/List;
-HSPLandroidx/compose/ui/text/TextLayoutResult;->getSize-YbymL2g()J
-HSPLandroidx/compose/ui/text/TextPainter;-><clinit>()V
-HSPLandroidx/compose/ui/text/TextPainter;-><init>()V
-HSPLandroidx/compose/ui/text/TextPainter;->paint(Landroidx/compose/ui/graphics/Canvas;Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLandroidx/compose/ui/text/TextRange$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/TextRange$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/TextRange$Companion;->getZero-d9O1mEE()J
-HSPLandroidx/compose/ui/text/TextRange;-><clinit>()V
-HSPLandroidx/compose/ui/text/TextRange;->access$getZero$cp()J
-HSPLandroidx/compose/ui/text/TextRange;->constructor-impl(J)J
-HSPLandroidx/compose/ui/text/TextRange;->getEnd-impl(J)I
-HSPLandroidx/compose/ui/text/TextRange;->getStart-impl(J)I
-HSPLandroidx/compose/ui/text/TextRangeKt;->TextRange(I)J
-HSPLandroidx/compose/ui/text/TextRangeKt;->TextRange(II)J
-HSPLandroidx/compose/ui/text/TextRangeKt;->constrain-8ffj60Q(JII)J
-HSPLandroidx/compose/ui/text/TextRangeKt;->packWithCheck(II)J
-HSPLandroidx/compose/ui/text/TextStyle$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/TextStyle$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/TextStyle$Companion;->getDefault()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/TextStyle;-><clinit>()V
-HSPLandroidx/compose/ui/text/TextStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformTextStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;)V
-HSPLandroidx/compose/ui/text/TextStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformTextStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/TextStyle;-><init>(JJLandroidx/compose/ui/text/font/FontWeight;Landroidx/compose/ui/text/font/FontStyle;Landroidx/compose/ui/text/font/FontSynthesis;Landroidx/compose/ui/text/font/FontFamily;Ljava/lang/String;JLandroidx/compose/ui/text/style/BaselineShift;Landroidx/compose/ui/text/style/TextGeometricTransform;Landroidx/compose/ui/text/intl/LocaleList;JLandroidx/compose/ui/text/style/TextDecoration;Landroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/style/TextAlign;Landroidx/compose/ui/text/style/TextDirection;JLandroidx/compose/ui/text/style/TextIndent;Landroidx/compose/ui/text/PlatformTextStyle;Landroidx/compose/ui/text/style/LineHeightStyle;Landroidx/compose/ui/text/style/LineBreak;Landroidx/compose/ui/text/style/Hyphens;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/TextStyle;-><init>(Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/ParagraphStyle;)V
-HSPLandroidx/compose/ui/text/TextStyle;-><init>(Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/ParagraphStyle;Landroidx/compose/ui/text/PlatformTextStyle;)V
-HSPLandroidx/compose/ui/text/TextStyle;->access$getDefault$cp()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/TextStyle;->getAlpha()F
-HSPLandroidx/compose/ui/text/TextStyle;->getBrush()Landroidx/compose/ui/graphics/Brush;
-HSPLandroidx/compose/ui/text/TextStyle;->getFontFamily()Landroidx/compose/ui/text/font/FontFamily;
-HSPLandroidx/compose/ui/text/TextStyle;->getFontStyle-4Lr2A7w()Landroidx/compose/ui/text/font/FontStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->getFontSynthesis-ZQGJjVo()Landroidx/compose/ui/text/font/FontSynthesis;
-HSPLandroidx/compose/ui/text/TextStyle;->getFontWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/TextStyle;->getLetterSpacing-XSAIIZE()J
-HSPLandroidx/compose/ui/text/TextStyle;->getLineBreak-LgCVezo()Landroidx/compose/ui/text/style/LineBreak;
-HSPLandroidx/compose/ui/text/TextStyle;->getLineHeight-XSAIIZE()J
-HSPLandroidx/compose/ui/text/TextStyle;->getLineHeightStyle()Landroidx/compose/ui/text/style/LineHeightStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->getLocaleList()Landroidx/compose/ui/text/intl/LocaleList;
-HSPLandroidx/compose/ui/text/TextStyle;->getParagraphStyle$ui_text_release()Landroidx/compose/ui/text/ParagraphStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->getPlatformStyle()Landroidx/compose/ui/text/PlatformTextStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->getSpanStyle$ui_text_release()Landroidx/compose/ui/text/SpanStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->getTextAlign-buA522U()Landroidx/compose/ui/text/style/TextAlign;
-HSPLandroidx/compose/ui/text/TextStyle;->getTextDecoration()Landroidx/compose/ui/text/style/TextDecoration;
-HSPLandroidx/compose/ui/text/TextStyle;->getTextDirection-mmuk1to()Landroidx/compose/ui/text/style/TextDirection;
-HSPLandroidx/compose/ui/text/TextStyle;->getTextIndent()Landroidx/compose/ui/text/style/TextIndent;
-HSPLandroidx/compose/ui/text/TextStyle;->getTextMotion()Landroidx/compose/ui/text/style/TextMotion;
-HSPLandroidx/compose/ui/text/TextStyle;->merge(Landroidx/compose/ui/text/ParagraphStyle;)Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->merge(Landroidx/compose/ui/text/TextStyle;)Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->toParagraphStyle()Landroidx/compose/ui/text/ParagraphStyle;
-HSPLandroidx/compose/ui/text/TextStyle;->toSpanStyle()Landroidx/compose/ui/text/SpanStyle;
-HSPLandroidx/compose/ui/text/TextStyleKt$WhenMappings;-><clinit>()V
-HSPLandroidx/compose/ui/text/TextStyleKt;->access$createPlatformTextStyleInternal(Landroidx/compose/ui/text/PlatformSpanStyle;Landroidx/compose/ui/text/PlatformParagraphStyle;)Landroidx/compose/ui/text/PlatformTextStyle;
-HSPLandroidx/compose/ui/text/TextStyleKt;->createPlatformTextStyleInternal(Landroidx/compose/ui/text/PlatformSpanStyle;Landroidx/compose/ui/text/PlatformParagraphStyle;)Landroidx/compose/ui/text/PlatformTextStyle;
-HSPLandroidx/compose/ui/text/TextStyleKt;->resolveDefaults(Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/unit/LayoutDirection;)Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/TextStyleKt;->resolveTextDirection-Yj3eThk(Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/style/TextDirection;)I
-HSPLandroidx/compose/ui/text/android/BoringLayoutFactory33;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/BoringLayoutFactory33;-><init>()V
-HSPLandroidx/compose/ui/text/android/BoringLayoutFactory33;->isBoring(Ljava/lang/CharSequence;Landroid/text/TextPaint;Landroid/text/TextDirectionHeuristic;)Landroid/text/BoringLayout$Metrics;
-HSPLandroidx/compose/ui/text/android/BoringLayoutFactory;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/BoringLayoutFactory;-><init>()V
-HSPLandroidx/compose/ui/text/android/BoringLayoutFactory;->measure(Ljava/lang/CharSequence;Landroid/text/TextPaint;Landroid/text/TextDirectionHeuristic;)Landroid/text/BoringLayout$Metrics;
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$boringMetrics$2;-><init>(ILjava/lang/CharSequence;Landroid/text/TextPaint;)V
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$boringMetrics$2;->invoke()Landroid/text/BoringLayout$Metrics;
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$boringMetrics$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$maxIntrinsicWidth$2;-><init>(Landroidx/compose/ui/text/android/LayoutIntrinsics;Ljava/lang/CharSequence;Landroid/text/TextPaint;)V
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$maxIntrinsicWidth$2;->invoke()Ljava/lang/Float;
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$maxIntrinsicWidth$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics$minIntrinsicWidth$2;-><init>(Ljava/lang/CharSequence;Landroid/text/TextPaint;)V
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics;-><init>(Ljava/lang/CharSequence;Landroid/text/TextPaint;I)V
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics;->getBoringMetrics()Landroid/text/BoringLayout$Metrics;
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsics;->getMaxIntrinsicWidth()F
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsicsKt;->access$shouldIncreaseMaxIntrinsic(FLjava/lang/CharSequence;Landroid/text/TextPaint;)Z
-HSPLandroidx/compose/ui/text/android/LayoutIntrinsicsKt;->shouldIncreaseMaxIntrinsic(FLjava/lang/CharSequence;Landroid/text/TextPaint;)Z
-HSPLandroidx/compose/ui/text/android/SpannedExtensionsKt;->hasSpan(Landroid/text/Spanned;Ljava/lang/Class;)Z
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory23;-><init>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory23;->create(Landroidx/compose/ui/text/android/StaticLayoutParams;)Landroid/text/StaticLayout;
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory26;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory26;-><init>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory26;->setJustificationMode(Landroid/text/StaticLayout$Builder;I)V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory28;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory28;-><init>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory28;->setUseLineSpacingFromFallbacks(Landroid/text/StaticLayout$Builder;Z)V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory33;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory33;-><init>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory33;->setLineBreakConfig(Landroid/text/StaticLayout$Builder;II)V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory;-><init>()V
-HSPLandroidx/compose/ui/text/android/StaticLayoutFactory;->create(Ljava/lang/CharSequence;IILandroid/text/TextPaint;ILandroid/text/TextDirectionHeuristic;Landroid/text/Layout$Alignment;ILandroid/text/TextUtils$TruncateAt;IFFIZZIIII[I[I)Landroid/text/StaticLayout;
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;-><init>(Ljava/lang/CharSequence;IILandroid/text/TextPaint;ILandroid/text/TextDirectionHeuristic;Landroid/text/Layout$Alignment;ILandroid/text/TextUtils$TruncateAt;IFFIZZIIII[I[I)V
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getAlignment()Landroid/text/Layout$Alignment;
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getBreakStrategy()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getEllipsize()Landroid/text/TextUtils$TruncateAt;
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getEllipsizedWidth()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getEnd()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getHyphenationFrequency()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getIncludePadding()Z
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getJustificationMode()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getLeftIndents()[I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getLineBreakStyle()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getLineBreakWordStyle()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getLineSpacingExtra()F
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getLineSpacingMultiplier()F
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getMaxLines()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getPaint()Landroid/text/TextPaint;
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getRightIndents()[I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getStart()I
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getText()Ljava/lang/CharSequence;
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getTextDir()Landroid/text/TextDirectionHeuristic;
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getUseFallbackLineSpacing()Z
-HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->getWidth()I
-HSPLandroidx/compose/ui/text/android/TextAlignmentAdapter;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/TextAlignmentAdapter;-><init>()V
-HSPLandroidx/compose/ui/text/android/TextAlignmentAdapter;->get(I)Landroid/text/Layout$Alignment;
-HSPLandroidx/compose/ui/text/android/TextAndroidCanvas;-><init>()V
-HSPLandroidx/compose/ui/text/android/TextAndroidCanvas;->drawTextRun(Ljava/lang/CharSequence;IIIIFFZLandroid/graphics/Paint;)V
-HSPLandroidx/compose/ui/text/android/TextAndroidCanvas;->getClipBounds(Landroid/graphics/Rect;)Z
-HSPLandroidx/compose/ui/text/android/TextAndroidCanvas;->setCanvas(Landroid/graphics/Canvas;)V
-HSPLandroidx/compose/ui/text/android/TextLayout$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/android/TextLayout$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/android/TextLayout$layoutHelper$2;-><init>(Landroidx/compose/ui/text/android/TextLayout;)V
-HSPLandroidx/compose/ui/text/android/TextLayout;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/TextLayout;-><init>(Ljava/lang/CharSequence;FLandroid/text/TextPaint;ILandroid/text/TextUtils$TruncateAt;IFFZZIIIIII[I[ILandroidx/compose/ui/text/android/LayoutIntrinsics;)V
-HSPLandroidx/compose/ui/text/android/TextLayout;-><init>(Ljava/lang/CharSequence;FLandroid/text/TextPaint;ILandroid/text/TextUtils$TruncateAt;IFFZZIIIIII[I[ILandroidx/compose/ui/text/android/LayoutIntrinsics;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/android/TextLayout;->getDidExceedMaxLines()Z
-HSPLandroidx/compose/ui/text/android/TextLayout;->getHeight()I
-HSPLandroidx/compose/ui/text/android/TextLayout;->getIncludePadding()Z
-HSPLandroidx/compose/ui/text/android/TextLayout;->getLayout()Landroid/text/Layout;
-HSPLandroidx/compose/ui/text/android/TextLayout;->getLineBaseline(I)F
-HSPLandroidx/compose/ui/text/android/TextLayout;->getLineCount()I
-HSPLandroidx/compose/ui/text/android/TextLayout;->getText()Ljava/lang/CharSequence;
-HSPLandroidx/compose/ui/text/android/TextLayout;->paint(Landroid/graphics/Canvas;)V
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->access$getLastLineMetrics(Landroidx/compose/ui/text/android/TextLayout;Landroid/text/TextPaint;Landroid/text/TextDirectionHeuristic;[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->access$getLineHeightPaddings(Landroidx/compose/ui/text/android/TextLayout;[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->access$getLineHeightSpans(Landroidx/compose/ui/text/android/TextLayout;)[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->access$getVerticalPaddings(Landroidx/compose/ui/text/android/TextLayout;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->getLastLineMetrics(Landroidx/compose/ui/text/android/TextLayout;Landroid/text/TextPaint;Landroid/text/TextDirectionHeuristic;[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->getLineHeightPaddings(Landroidx/compose/ui/text/android/TextLayout;[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->getLineHeightSpans(Landroidx/compose/ui/text/android/TextLayout;)[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->getTextDirectionHeuristic(I)Landroid/text/TextDirectionHeuristic;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->getVerticalPaddings(Landroidx/compose/ui/text/android/TextLayout;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/android/TextLayoutKt;->isLineEllipsized(Landroid/text/Layout;I)Z
-HSPLandroidx/compose/ui/text/android/style/IndentationFixSpanKt;->getEllipsizedLeftPadding$default(Landroid/text/Layout;ILandroid/graphics/Paint;ILjava/lang/Object;)F
-HSPLandroidx/compose/ui/text/android/style/IndentationFixSpanKt;->getEllipsizedLeftPadding(Landroid/text/Layout;ILandroid/graphics/Paint;)F
-HSPLandroidx/compose/ui/text/android/style/IndentationFixSpanKt;->getEllipsizedRightPadding$default(Landroid/text/Layout;ILandroid/graphics/Paint;ILjava/lang/Object;)F
-HSPLandroidx/compose/ui/text/android/style/IndentationFixSpanKt;->getEllipsizedRightPadding(Landroid/text/Layout;ILandroid/graphics/Paint;)F
-HSPLandroidx/compose/ui/text/android/style/LineHeightSpan;-><clinit>()V
-HSPLandroidx/compose/ui/text/android/style/LineHeightSpan;-><init>(F)V
-HSPLandroidx/compose/ui/text/android/style/LineHeightSpan;->chooseHeight(Ljava/lang/CharSequence;IIIILandroid/graphics/Paint$FontMetricsInt;)V
-HSPLandroidx/compose/ui/text/android/style/LineHeightStyleSpanKt;->lineHeight(Landroid/graphics/Paint$FontMetricsInt;)I
-HSPLandroidx/compose/ui/text/caches/ContainerHelpersKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/caches/LruCache;-><init>(I)V
-HSPLandroidx/compose/ui/text/caches/LruCache;->access$getMonitor$p(Landroidx/compose/ui/text/caches/LruCache;)Landroidx/compose/ui/text/platform/SynchronizedObject;
-HSPLandroidx/compose/ui/text/caches/LruCache;->create(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/caches/LruCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/caches/LruCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/caches/LruCache;->safeSizeOf(Ljava/lang/Object;Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/text/caches/LruCache;->size()I
-HSPLandroidx/compose/ui/text/caches/LruCache;->sizeOf(Ljava/lang/Object;Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/text/caches/LruCache;->trimToSize(I)V
-HSPLandroidx/compose/ui/text/caches/SimpleArrayMap;-><init>(I)V
-HSPLandroidx/compose/ui/text/caches/SimpleArrayMap;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/caches/SimpleArrayMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/caches/SimpleArrayMap;->indexOf(Ljava/lang/Object;I)I
-HSPLandroidx/compose/ui/text/caches/SimpleArrayMap;->indexOfKey(Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/text/font/AndroidFont;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/AndroidFont;-><init>(ILandroidx/compose/ui/text/font/AndroidFont$TypefaceLoader;Landroidx/compose/ui/text/font/FontVariation$Settings;)V
-HSPLandroidx/compose/ui/text/font/AndroidFont;-><init>(ILandroidx/compose/ui/text/font/AndroidFont$TypefaceLoader;Landroidx/compose/ui/text/font/FontVariation$Settings;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/AndroidFont;->getLoadingStrategy-PKNRLFQ()I
-HSPLandroidx/compose/ui/text/font/AndroidFont;->getTypefaceLoader()Landroidx/compose/ui/text/font/AndroidFont$TypefaceLoader;
-HSPLandroidx/compose/ui/text/font/AndroidFont;->getVariationSettings()Landroidx/compose/ui/text/font/FontVariation$Settings;
-HSPLandroidx/compose/ui/text/font/AndroidFontLoader;-><init>(Landroid/content/Context;)V
-HSPLandroidx/compose/ui/text/font/AndroidFontLoader;->getCacheKey()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/font/AndroidFontLoader;->loadBlocking(Landroidx/compose/ui/text/font/Font;)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/AndroidFontLoader;->loadBlocking(Landroidx/compose/ui/text/font/Font;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/font/AndroidFontResolveInterceptor;-><init>(I)V
-HSPLandroidx/compose/ui/text/font/AndroidFontResolveInterceptor;->interceptFontWeight(Landroidx/compose/ui/text/font/FontWeight;)Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/AndroidFontResolveInterceptor_androidKt;->AndroidFontResolveInterceptor(Landroid/content/Context;)Landroidx/compose/ui/text/font/AndroidFontResolveInterceptor;
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache$AsyncTypefaceResult;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache$AsyncTypefaceResult;->box-impl(Ljava/lang/Object;)Landroidx/compose/ui/text/font/AsyncTypefaceCache$AsyncTypefaceResult;
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache$AsyncTypefaceResult;->constructor-impl(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache$Key;-><init>(Landroidx/compose/ui/text/font/Font;Ljava/lang/Object;)V
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache$Key;->hashCode()I
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache;-><init>()V
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache;->access$getCacheLock$p(Landroidx/compose/ui/text/font/AsyncTypefaceCache;)Landroidx/compose/ui/text/platform/SynchronizedObject;
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache;->access$getPermanentCache$p(Landroidx/compose/ui/text/font/AsyncTypefaceCache;)Landroidx/compose/ui/text/caches/SimpleArrayMap;
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache;->access$getResultCache$p(Landroidx/compose/ui/text/font/AsyncTypefaceCache;)Landroidx/compose/ui/text/caches/LruCache;
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache;->put$default(Landroidx/compose/ui/text/font/AsyncTypefaceCache;Landroidx/compose/ui/text/font/Font;Landroidx/compose/ui/text/font/PlatformFontLoader;Ljava/lang/Object;ZILjava/lang/Object;)V
-HSPLandroidx/compose/ui/text/font/AsyncTypefaceCache;->put(Landroidx/compose/ui/text/font/Font;Landroidx/compose/ui/text/font/PlatformFontLoader;Ljava/lang/Object;Z)V
-HSPLandroidx/compose/ui/text/font/DefaultFontFamily;-><init>()V
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyName;->constructor-impl(Ljava/lang/String;)Ljava/lang/String;
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyName;->hashCode-impl(Ljava/lang/String;)I
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;-><init>(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/ui/text/font/FontVariation$Settings;)V
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;-><init>(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/ui/text/font/FontVariation$Settings;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;->getStyle-_-LCdwA()I
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;->getWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;->hashCode()I
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;->loadCached(Landroid/content/Context;)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFontKt;->Font-vxs03AY$default(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/ui/text/font/FontVariation$Settings;ILjava/lang/Object;)Landroidx/compose/ui/text/font/Font;
-HSPLandroidx/compose/ui/text/font/DeviceFontFamilyNameFontKt;->Font-vxs03AY(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/ui/text/font/FontVariation$Settings;)Landroidx/compose/ui/text/font/Font;
-HSPLandroidx/compose/ui/text/font/FileBasedFontFamily;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FileBasedFontFamily;-><init>()V
-HSPLandroidx/compose/ui/text/font/FileBasedFontFamily;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontFamily$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontFamily$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontFamily$Companion;->getCursive()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily$Companion;->getMonospace()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily$Companion;->getSansSerif()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily$Companion;->getSerif()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontFamily;-><init>(Z)V
-HSPLandroidx/compose/ui/text/font/FontFamily;-><init>(ZLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontFamily;->access$getCursive$cp()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily;->access$getMonospace$cp()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily;->access$getSansSerif$cp()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamily;->access$getSerif$cp()Landroidx/compose/ui/text/font/GenericFontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamilyKt;->FontFamily([Landroidx/compose/ui/text/font/Font;)Landroidx/compose/ui/text/font/FontFamily;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl$createDefaultTypeface$1;-><init>(Landroidx/compose/ui/text/font/FontFamilyResolverImpl;)V
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl$resolve$result$1;-><init>(Landroidx/compose/ui/text/font/FontFamilyResolverImpl;Landroidx/compose/ui/text/font/TypefaceRequest;)V
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl$resolve$result$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl$resolve$result$1;->invoke(Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/text/font/TypefaceResult;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;-><init>(Landroidx/compose/ui/text/font/PlatformFontLoader;Landroidx/compose/ui/text/font/PlatformResolveInterceptor;Landroidx/compose/ui/text/font/TypefaceRequestCache;Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;Landroidx/compose/ui/text/font/PlatformFontFamilyTypefaceAdapter;)V
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;-><init>(Landroidx/compose/ui/text/font/PlatformFontLoader;Landroidx/compose/ui/text/font/PlatformResolveInterceptor;Landroidx/compose/ui/text/font/TypefaceRequestCache;Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;Landroidx/compose/ui/text/font/PlatformFontFamilyTypefaceAdapter;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;->access$getCreateDefaultTypeface$p(Landroidx/compose/ui/text/font/FontFamilyResolverImpl;)Lkotlin/jvm/functions/Function1;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;->access$getFontListFontFamilyTypefaceAdapter$p(Landroidx/compose/ui/text/font/FontFamilyResolverImpl;)Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;->getPlatformFontLoader$ui_text_release()Landroidx/compose/ui/text/font/PlatformFontLoader;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;->resolve(Landroidx/compose/ui/text/font/TypefaceRequest;)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverImpl;->resolve-DPcqOEQ(Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;II)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverKt;->getGlobalAsyncTypefaceCache()Landroidx/compose/ui/text/font/AsyncTypefaceCache;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolverKt;->getGlobalTypefaceRequestCache()Landroidx/compose/ui/text/font/TypefaceRequestCache;
-HSPLandroidx/compose/ui/text/font/FontFamilyResolver_androidKt;->createFontFamilyResolver(Landroid/content/Context;)Landroidx/compose/ui/text/font/FontFamily$Resolver;
-HSPLandroidx/compose/ui/text/font/FontListFontFamily;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontListFontFamily;-><init>(Ljava/util/List;)V
-HSPLandroidx/compose/ui/text/font/FontListFontFamily;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/font/FontListFontFamily;->getFonts()Ljava/util/List;
-HSPLandroidx/compose/ui/text/font/FontListFontFamily;->hashCode()I
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter$special$$inlined$CoroutineExceptionHandler$1;-><init>(Lkotlinx/coroutines/CoroutineExceptionHandler$Key;)V
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;-><init>(Landroidx/compose/ui/text/font/AsyncTypefaceCache;Lkotlin/coroutines/CoroutineContext;)V
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;-><init>(Landroidx/compose/ui/text/font/AsyncTypefaceCache;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;->resolve(Landroidx/compose/ui/text/font/TypefaceRequest;Landroidx/compose/ui/text/font/PlatformFontLoader;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Landroidx/compose/ui/text/font/TypefaceResult;
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterKt;->access$firstImmediatelyAvailable(Ljava/util/List;Landroidx/compose/ui/text/font/TypefaceRequest;Landroidx/compose/ui/text/font/AsyncTypefaceCache;Landroidx/compose/ui/text/font/PlatformFontLoader;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterKt;->firstImmediatelyAvailable(Ljava/util/List;Landroidx/compose/ui/text/font/TypefaceRequest;Landroidx/compose/ui/text/font/AsyncTypefaceCache;Landroidx/compose/ui/text/font/PlatformFontLoader;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair;
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy$Companion;->getBlocking-PKNRLFQ()I
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy$Companion;->getOptionalLocal-PKNRLFQ()I
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy;->access$getBlocking$cp()I
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy;->access$getOptionalLocal$cp()I
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/font/FontLoadingStrategy;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/font/FontMatcher;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontMatcher;->matchFont-RetOiIg(Ljava/util/List;Landroidx/compose/ui/text/font/FontWeight;I)Ljava/util/List;
-HSPLandroidx/compose/ui/text/font/FontStyle$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontStyle$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontStyle$Companion;->getItalic-_-LCdwA()I
-HSPLandroidx/compose/ui/text/font/FontStyle$Companion;->getNormal-_-LCdwA()I
-HSPLandroidx/compose/ui/text/font/FontStyle;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontStyle;-><init>(I)V
-HSPLandroidx/compose/ui/text/font/FontStyle;->access$getItalic$cp()I
-HSPLandroidx/compose/ui/text/font/FontStyle;->access$getNormal$cp()I
-HSPLandroidx/compose/ui/text/font/FontStyle;->box-impl(I)Landroidx/compose/ui/text/font/FontStyle;
-HSPLandroidx/compose/ui/text/font/FontStyle;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/font/FontStyle;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/font/FontStyle;->hashCode-impl(I)I
-HSPLandroidx/compose/ui/text/font/FontStyle;->unbox-impl()I
-HSPLandroidx/compose/ui/text/font/FontSynthesis$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontSynthesis$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontSynthesis$Companion;->getAll-GVVA2EU()I
-HSPLandroidx/compose/ui/text/font/FontSynthesis;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontSynthesis;-><init>(I)V
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->access$getAll$cp()I
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->box-impl(I)Landroidx/compose/ui/text/font/FontSynthesis;
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->hashCode-impl(I)I
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->isStyleOn-impl$ui_text_release(I)Z
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->isWeightOn-impl$ui_text_release(I)Z
-HSPLandroidx/compose/ui/text/font/FontSynthesis;->unbox-impl()I
-HSPLandroidx/compose/ui/text/font/FontSynthesis_androidKt;->synthesizeTypeface-FxwP2eA(ILjava/lang/Object;Landroidx/compose/ui/text/font/Font;Landroidx/compose/ui/text/font/FontWeight;I)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/font/FontVariation$Settings;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontVariation$Settings;-><init>([Landroidx/compose/ui/text/font/FontVariation$Setting;)V
-HSPLandroidx/compose/ui/text/font/FontVariation$Settings;->getSettings()Ljava/util/List;
-HSPLandroidx/compose/ui/text/font/FontVariation$Settings;->hashCode()I
-HSPLandroidx/compose/ui/text/font/FontWeight$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/FontWeight$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/FontWeight$Companion;->getMedium()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/FontWeight$Companion;->getNormal()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/FontWeight;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/FontWeight;-><init>(I)V
-HSPLandroidx/compose/ui/text/font/FontWeight;->access$getMedium$cp()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/FontWeight;->access$getNormal$cp()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/FontWeight;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/font/FontWeight;->getWeight()I
-HSPLandroidx/compose/ui/text/font/FontWeight;->hashCode()I
-HSPLandroidx/compose/ui/text/font/GenericFontFamily;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/GenericFontFamily;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-HSPLandroidx/compose/ui/text/font/GenericFontFamily;->getName()Ljava/lang/String;
-HSPLandroidx/compose/ui/text/font/NamedFontLoader;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/NamedFontLoader;-><init>()V
-HSPLandroidx/compose/ui/text/font/NamedFontLoader;->loadBlocking(Landroid/content/Context;Landroidx/compose/ui/text/font/AndroidFont;)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/PlatformFontFamilyTypefaceAdapter;-><init>()V
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor$Companion$Default$1;-><init>()V
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor;->interceptFontFamily(Landroidx/compose/ui/text/font/FontFamily;)Landroidx/compose/ui/text/font/FontFamily;
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor;->interceptFontStyle-T2F_aPo(I)I
-HSPLandroidx/compose/ui/text/font/PlatformResolveInterceptor;->interceptFontSynthesis-Mscr08Y(I)I
-HSPLandroidx/compose/ui/text/font/PlatformTypefacesApi28;-><init>()V
-HSPLandroidx/compose/ui/text/font/PlatformTypefacesApi28;->createAndroidTypefaceApi28-RetOiIg(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;I)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/PlatformTypefacesApi28;->loadNamedFromTypefaceCacheOrNull-RetOiIg(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;I)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/PlatformTypefacesApi28;->optionalOnDeviceFontFamilyByName-78DK7lM(Ljava/lang/String;Landroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/ui/text/font/FontVariation$Settings;Landroid/content/Context;)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/PlatformTypefacesKt;->PlatformTypefaces()Landroidx/compose/ui/text/font/PlatformTypefaces;
-HSPLandroidx/compose/ui/text/font/PlatformTypefacesKt;->setFontVariationSettings(Landroid/graphics/Typeface;Landroidx/compose/ui/text/font/FontVariation$Settings;Landroid/content/Context;)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/SystemFontFamily;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/SystemFontFamily;-><init>()V
-HSPLandroidx/compose/ui/text/font/SystemFontFamily;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/TypefaceCompatApi26;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/TypefaceCompatApi26;-><init>()V
-HSPLandroidx/compose/ui/text/font/TypefaceCompatApi26;->setFontVariationSettings(Landroid/graphics/Typeface;Landroidx/compose/ui/text/font/FontVariation$Settings;Landroid/content/Context;)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/TypefaceHelperMethodsApi28;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/TypefaceHelperMethodsApi28;-><init>()V
-HSPLandroidx/compose/ui/text/font/TypefaceHelperMethodsApi28;->create(Landroid/graphics/Typeface;IZ)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;-><init>(Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;IILjava/lang/Object;)V
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;-><init>(Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;IILjava/lang/Object;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;->getFontFamily()Landroidx/compose/ui/text/font/FontFamily;
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;->getFontStyle-_-LCdwA()I
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;->getFontSynthesis-GVVA2EU()I
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;->getFontWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLandroidx/compose/ui/text/font/TypefaceRequest;->hashCode()I
-HSPLandroidx/compose/ui/text/font/TypefaceRequestCache$runCached$currentTypefaceResult$1;-><init>(Landroidx/compose/ui/text/font/TypefaceRequestCache;Landroidx/compose/ui/text/font/TypefaceRequest;)V
-HSPLandroidx/compose/ui/text/font/TypefaceRequestCache;-><init>()V
-HSPLandroidx/compose/ui/text/font/TypefaceRequestCache;->runCached(Landroidx/compose/ui/text/font/TypefaceRequest;Lkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/State;
-HSPLandroidx/compose/ui/text/font/TypefaceResult$Immutable;-><clinit>()V
-HSPLandroidx/compose/ui/text/font/TypefaceResult$Immutable;-><init>(Ljava/lang/Object;Z)V
-HSPLandroidx/compose/ui/text/font/TypefaceResult$Immutable;-><init>(Ljava/lang/Object;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/font/TypefaceResult$Immutable;->getCacheable()Z
-HSPLandroidx/compose/ui/text/font/TypefaceResult$Immutable;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/input/ImeAction$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/input/ImeAction$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/ImeAction$Companion;->getDefault-eUduSuo()I
-HSPLandroidx/compose/ui/text/input/ImeAction;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/ImeAction;->access$getDefault$cp()I
-HSPLandroidx/compose/ui/text/input/ImeAction;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/input/ImeOptions$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/input/ImeOptions$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/ImeOptions$Companion;->getDefault()Landroidx/compose/ui/text/input/ImeOptions;
-HSPLandroidx/compose/ui/text/input/ImeOptions;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/ImeOptions;-><init>(ZIZII)V
-HSPLandroidx/compose/ui/text/input/ImeOptions;-><init>(ZIZIIILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/ImeOptions;-><init>(ZIZIILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/ImeOptions;->access$getDefault$cp()Landroidx/compose/ui/text/input/ImeOptions;
-HSPLandroidx/compose/ui/text/input/ImmHelper30;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/ui/text/input/InputMethodManagerImpl$imm$2;-><init>(Landroidx/compose/ui/text/input/InputMethodManagerImpl;)V
-HSPLandroidx/compose/ui/text/input/InputMethodManagerImpl;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/ui/text/input/KeyboardCapitalization$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/input/KeyboardCapitalization$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/KeyboardCapitalization$Companion;->getNone-IUNYP9k()I
-HSPLandroidx/compose/ui/text/input/KeyboardCapitalization;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/KeyboardCapitalization;->access$getNone$cp()I
-HSPLandroidx/compose/ui/text/input/KeyboardCapitalization;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/input/KeyboardType$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/input/KeyboardType$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/KeyboardType$Companion;->getText-PjHm6EE()I
-HSPLandroidx/compose/ui/text/input/KeyboardType;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/KeyboardType;->access$getText$cp()I
-HSPLandroidx/compose/ui/text/input/KeyboardType;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/input/TextFieldValue$Companion$Saver$1;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/TextFieldValue$Companion$Saver$1;-><init>()V
-HSPLandroidx/compose/ui/text/input/TextFieldValue$Companion$Saver$2;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/TextFieldValue$Companion$Saver$2;-><init>()V
-HSPLandroidx/compose/ui/text/input/TextFieldValue$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/input/TextFieldValue$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;-><init>(Landroidx/compose/ui/text/AnnotatedString;JLandroidx/compose/ui/text/TextRange;)V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;-><init>(Landroidx/compose/ui/text/AnnotatedString;JLandroidx/compose/ui/text/TextRange;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;-><init>(Ljava/lang/String;JLandroidx/compose/ui/text/TextRange;)V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;-><init>(Ljava/lang/String;JLandroidx/compose/ui/text/TextRange;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;-><init>(Ljava/lang/String;JLandroidx/compose/ui/text/TextRange;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/input/TextFieldValue;->getText()Ljava/lang/String;
-HSPLandroidx/compose/ui/text/input/TextInputService;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/TextInputService;-><init>(Landroidx/compose/ui/text/input/PlatformTextInputService;)V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$baseInputConnection$2;-><init>(Landroidx/compose/ui/text/input/TextInputServiceAndroid;)V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$onEditCommand$1;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$onEditCommand$1;-><init>()V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$onImeActionPerformed$1;-><clinit>()V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$onImeActionPerformed$1;-><init>()V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$textInputCommandEventLoop$1;-><init>(Landroidx/compose/ui/text/input/TextInputServiceAndroid;Lkotlin/coroutines/Continuation;)V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid$textInputCommandEventLoop$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid;-><init>(Landroid/view/View;)V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid;-><init>(Landroid/view/View;Landroidx/compose/ui/text/input/InputMethodManager;)V
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid;->isEditorFocused()Z
-HSPLandroidx/compose/ui/text/input/TextInputServiceAndroid;->textInputCommandEventLoop(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/intl/AndroidLocale;-><init>(Ljava/util/Locale;)V
-HSPLandroidx/compose/ui/text/intl/AndroidLocaleDelegateAPI24;-><init>()V
-HSPLandroidx/compose/ui/text/intl/AndroidLocaleDelegateAPI24;->getCurrent()Landroidx/compose/ui/text/intl/LocaleList;
-HSPLandroidx/compose/ui/text/intl/AndroidPlatformLocale_androidKt;->createPlatformLocaleDelegate()Landroidx/compose/ui/text/intl/PlatformLocaleDelegate;
-HSPLandroidx/compose/ui/text/intl/Locale$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/intl/Locale$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/intl/Locale;-><clinit>()V
-HSPLandroidx/compose/ui/text/intl/Locale;-><init>(Landroidx/compose/ui/text/intl/PlatformLocale;)V
-HSPLandroidx/compose/ui/text/intl/LocaleList$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/intl/LocaleList$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/intl/LocaleList$Companion;->getCurrent()Landroidx/compose/ui/text/intl/LocaleList;
-HSPLandroidx/compose/ui/text/intl/LocaleList;-><clinit>()V
-HSPLandroidx/compose/ui/text/intl/LocaleList;-><init>(Ljava/util/List;)V
-HSPLandroidx/compose/ui/text/intl/LocaleList;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/intl/PlatformLocaleKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/intl/PlatformLocaleKt;->getPlatformLocaleDelegate()Landroidx/compose/ui/text/intl/PlatformLocaleDelegate;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphHelper_androidKt$NoopSpan$1;-><init>()V
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphHelper_androidKt;-><clinit>()V
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphHelper_androidKt;->createCharSequence(Ljava/lang/String;FLandroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/unit/Density;Lkotlin/jvm/functions/Function4;Z)Ljava/lang/CharSequence;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphHelper_androidKt;->isIncludeFontPaddingEnabled(Landroidx/compose/ui/text/TextStyle;)Z
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics$resolveTypeface$1;-><init>(Landroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;)V
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics$resolveTypeface$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics$resolveTypeface$1;->invoke-DPcqOEQ(Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;II)Landroid/graphics/Typeface;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;-><init>(Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/text/font/FontFamily$Resolver;Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getCharSequence$ui_text_release()Ljava/lang/CharSequence;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getFontFamilyResolver()Landroidx/compose/ui/text/font/FontFamily$Resolver;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getHasStaleResolvedFonts()Z
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getLayoutIntrinsics$ui_text_release()Landroidx/compose/ui/text/android/LayoutIntrinsics;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getMaxIntrinsicWidth()F
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getStyle()Landroidx/compose/ui/text/TextStyle;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getTextDirectionHeuristic$ui_text_release()I
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->getTextPaint$ui_text_release()Landroidx/compose/ui/text/platform/AndroidTextPaint;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics_androidKt;->ActualParagraphIntrinsics(Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/FontFamily$Resolver;)Landroidx/compose/ui/text/ParagraphIntrinsics;
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics_androidKt;->access$getHasEmojiCompat(Landroidx/compose/ui/text/TextStyle;)Z
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics_androidKt;->getHasEmojiCompat(Landroidx/compose/ui/text/TextStyle;)Z
-HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics_androidKt;->resolveTextDirectionHeuristics-9GRLPo0(Landroidx/compose/ui/text/style/TextDirection;Landroidx/compose/ui/text/intl/LocaleList;)I
-HSPLandroidx/compose/ui/text/platform/AndroidParagraph_androidKt;->ActualParagraph--hBUhpc(Landroidx/compose/ui/text/ParagraphIntrinsics;IZJ)Landroidx/compose/ui/text/Paragraph;
-HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;-><init>(IF)V
-HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;->setBrush-12SF9DM(Landroidx/compose/ui/graphics/Brush;JF)V
-HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;->setColor-8_81llA(J)V
-HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;->setDrawStyle(Landroidx/compose/ui/graphics/drawscope/DrawStyle;)V
-HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;->setShadow(Landroidx/compose/ui/graphics/Shadow;)V
-HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;->setTextDecoration(Landroidx/compose/ui/text/style/TextDecoration;)V
-HSPLandroidx/compose/ui/text/platform/DefaultImpl$getFontLoadState$initCallback$1;-><init>(Landroidx/compose/runtime/MutableState;Landroidx/compose/ui/text/platform/DefaultImpl;)V
-HSPLandroidx/compose/ui/text/platform/DefaultImpl$getFontLoadState$initCallback$1;->onInitialized()V
-HSPLandroidx/compose/ui/text/platform/DefaultImpl;-><init>()V
-HSPLandroidx/compose/ui/text/platform/DefaultImpl;->access$setLoadState$p(Landroidx/compose/ui/text/platform/DefaultImpl;Landroidx/compose/runtime/State;)V
-HSPLandroidx/compose/ui/text/platform/DefaultImpl;->getFontLoadState()Landroidx/compose/runtime/State;
-HSPLandroidx/compose/ui/text/platform/DefaultImpl;->getFontLoaded()Landroidx/compose/runtime/State;
-HSPLandroidx/compose/ui/text/platform/EmojiCompatStatus;-><clinit>()V
-HSPLandroidx/compose/ui/text/platform/EmojiCompatStatus;-><init>()V
-HSPLandroidx/compose/ui/text/platform/EmojiCompatStatus;->getFontLoaded()Landroidx/compose/runtime/State;
-HSPLandroidx/compose/ui/text/platform/ImmutableBool;-><init>(Z)V
-HSPLandroidx/compose/ui/text/platform/ImmutableBool;->getValue()Ljava/lang/Boolean;
-HSPLandroidx/compose/ui/text/platform/ImmutableBool;->getValue()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/platform/Synchronization_jvmKt;->createSynchronizedObject()Landroidx/compose/ui/text/platform/SynchronizedObject;
-HSPLandroidx/compose/ui/text/platform/SynchronizedObject;-><init>()V
-HSPLandroidx/compose/ui/text/platform/extensions/PlaceholderExtensions_androidKt;->setPlaceholders(Landroid/text/Spannable;Ljava/util/List;Landroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt$setFontAttributes$1;-><init>(Landroid/text/Spannable;Lkotlin/jvm/functions/Function4;)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->flattenFontStylesAndApply(Landroidx/compose/ui/text/SpanStyle;Ljava/util/List;Lkotlin/jvm/functions/Function3;)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->hasFontAttributes(Landroidx/compose/ui/text/TextStyle;)Z
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->resolveLineHeightInPx-o2QH7mI(JFLandroidx/compose/ui/unit/Density;)F
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->setFontAttributes(Landroid/text/Spannable;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Lkotlin/jvm/functions/Function4;)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->setLineHeight-r9BaKPg(Landroid/text/Spannable;JFLandroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->setSpan(Landroid/text/Spannable;Ljava/lang/Object;II)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->setSpanStyles(Landroid/text/Spannable;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Landroidx/compose/ui/unit/Density;Lkotlin/jvm/functions/Function4;)V
-HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->setTextIndent(Landroid/text/Spannable;Landroidx/compose/ui/text/style/TextIndent;FLandroidx/compose/ui/unit/Density;)V
-HSPLandroidx/compose/ui/text/platform/extensions/TextPaintExtensions_androidKt;->applySpanStyle(Landroidx/compose/ui/text/platform/AndroidTextPaint;Landroidx/compose/ui/text/SpanStyle;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/unit/Density;Z)Landroidx/compose/ui/text/SpanStyle;
-HSPLandroidx/compose/ui/text/platform/extensions/TextPaintExtensions_androidKt;->generateFallbackSpanStyle-62GTOB8(JZJLandroidx/compose/ui/text/style/BaselineShift;)Landroidx/compose/ui/text/SpanStyle;
-HSPLandroidx/compose/ui/text/platform/extensions/TextPaintExtensions_androidKt;->hasFontAttributes(Landroidx/compose/ui/text/SpanStyle;)Z
-HSPLandroidx/compose/ui/text/platform/extensions/TextPaintExtensions_androidKt;->setTextMotion(Landroidx/compose/ui/text/platform/AndroidTextPaint;Landroidx/compose/ui/text/style/TextMotion;)V
-HSPLandroidx/compose/ui/text/style/BaselineShift$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/BaselineShift$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/BaselineShift$Companion;->getNone-y9eOQZs()F
-HSPLandroidx/compose/ui/text/style/BaselineShift;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/BaselineShift;-><init>(F)V
-HSPLandroidx/compose/ui/text/style/BaselineShift;->access$getNone$cp()F
-HSPLandroidx/compose/ui/text/style/BaselineShift;->box-impl(F)Landroidx/compose/ui/text/style/BaselineShift;
-HSPLandroidx/compose/ui/text/style/BaselineShift;->constructor-impl(F)F
-HSPLandroidx/compose/ui/text/style/BaselineShift;->equals-impl0(FF)Z
-HSPLandroidx/compose/ui/text/style/BaselineShift;->unbox-impl()F
-HSPLandroidx/compose/ui/text/style/ColorStyle;-><init>(J)V
-HSPLandroidx/compose/ui/text/style/ColorStyle;-><init>(JLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/ColorStyle;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/style/ColorStyle;->getAlpha()F
-HSPLandroidx/compose/ui/text/style/ColorStyle;->getBrush()Landroidx/compose/ui/graphics/Brush;
-HSPLandroidx/compose/ui/text/style/ColorStyle;->getColor-0d7_KjU()J
-HSPLandroidx/compose/ui/text/style/Hyphens$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/Hyphens$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/Hyphens$Companion;->getAuto-vmbZdU8()I
-HSPLandroidx/compose/ui/text/style/Hyphens$Companion;->getNone-vmbZdU8()I
-HSPLandroidx/compose/ui/text/style/Hyphens;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/Hyphens;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/Hyphens;->access$getAuto$cp()I
-HSPLandroidx/compose/ui/text/style/Hyphens;->access$getNone$cp()I
-HSPLandroidx/compose/ui/text/style/Hyphens;->box-impl(I)Landroidx/compose/ui/text/style/Hyphens;
-HSPLandroidx/compose/ui/text/style/Hyphens;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/Hyphens;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/Hyphens;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/LineBreak$Companion;->getSimple-rAG3T2k()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy$Companion;->getBalanced-fcGXIks()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy$Companion;->getHighQuality-fcGXIks()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy$Companion;->getSimple-fcGXIks()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->access$getBalanced$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->access$getHighQuality$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->access$getSimple$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->box-impl(I)Landroidx/compose/ui/text/style/LineBreak$Strategy;
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/LineBreak$Strategy;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness$Companion;->getDefault-usljTpc()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness$Companion;->getLoose-usljTpc()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness$Companion;->getNormal-usljTpc()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness$Companion;->getStrict-usljTpc()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->access$getDefault$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->access$getLoose$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->access$getNormal$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->access$getStrict$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->box-impl(I)Landroidx/compose/ui/text/style/LineBreak$Strictness;
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/LineBreak$Strictness;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak$Companion;->getDefault-jp8hJ3c()I
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak$Companion;->getPhrase-jp8hJ3c()I
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;->access$getDefault$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;->access$getPhrase$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;->box-impl(I)Landroidx/compose/ui/text/style/LineBreak$WordBreak;
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/LineBreak$WordBreak;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/LineBreak;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/LineBreak;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/LineBreak;->access$getSimple$cp()I
-HSPLandroidx/compose/ui/text/style/LineBreak;->box-impl(I)Landroidx/compose/ui/text/style/LineBreak;
-HSPLandroidx/compose/ui/text/style/LineBreak;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak;->constructor-impl(III)I
-HSPLandroidx/compose/ui/text/style/LineBreak;->getStrategy-fcGXIks(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak;->getStrictness-usljTpc(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak;->getWordBreak-jp8hJ3c(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->access$packBytes(III)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->access$unpackByte1(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->access$unpackByte2(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->access$unpackByte3(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->packBytes(III)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->unpackByte1(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->unpackByte2(I)I
-HSPLandroidx/compose/ui/text/style/LineBreak_androidKt;->unpackByte3(I)I
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;->getCenter-e0LSkKk()I
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;->getJustify-e0LSkKk()I
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;->getLeft-e0LSkKk()I
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;->getRight-e0LSkKk()I
-HSPLandroidx/compose/ui/text/style/TextAlign$Companion;->getStart-e0LSkKk()I
-HSPLandroidx/compose/ui/text/style/TextAlign;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextAlign;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/TextAlign;->access$getCenter$cp()I
-HSPLandroidx/compose/ui/text/style/TextAlign;->access$getJustify$cp()I
-HSPLandroidx/compose/ui/text/style/TextAlign;->access$getLeft$cp()I
-HSPLandroidx/compose/ui/text/style/TextAlign;->access$getRight$cp()I
-HSPLandroidx/compose/ui/text/style/TextAlign;->access$getStart$cp()I
-HSPLandroidx/compose/ui/text/style/TextAlign;->box-impl(I)Landroidx/compose/ui/text/style/TextAlign;
-HSPLandroidx/compose/ui/text/style/TextAlign;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/TextAlign;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/TextAlign;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/TextDecoration$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextDecoration$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextDecoration$Companion;->getNone()Landroidx/compose/ui/text/style/TextDecoration;
-HSPLandroidx/compose/ui/text/style/TextDecoration$Companion;->getUnderline()Landroidx/compose/ui/text/style/TextDecoration;
-HSPLandroidx/compose/ui/text/style/TextDecoration;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextDecoration;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/TextDecoration;->access$getNone$cp()Landroidx/compose/ui/text/style/TextDecoration;
-HSPLandroidx/compose/ui/text/style/TextDecoration;->access$getUnderline$cp()Landroidx/compose/ui/text/style/TextDecoration;
-HSPLandroidx/compose/ui/text/style/TextDecoration;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/style/TextDirection$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextDirection$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextDirection$Companion;->getContent-s_7X-co()I
-HSPLandroidx/compose/ui/text/style/TextDirection$Companion;->getContentOrLtr-s_7X-co()I
-HSPLandroidx/compose/ui/text/style/TextDirection$Companion;->getContentOrRtl-s_7X-co()I
-HSPLandroidx/compose/ui/text/style/TextDirection$Companion;->getLtr-s_7X-co()I
-HSPLandroidx/compose/ui/text/style/TextDirection;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextDirection;-><init>(I)V
-HSPLandroidx/compose/ui/text/style/TextDirection;->access$getContent$cp()I
-HSPLandroidx/compose/ui/text/style/TextDirection;->access$getContentOrLtr$cp()I
-HSPLandroidx/compose/ui/text/style/TextDirection;->access$getContentOrRtl$cp()I
-HSPLandroidx/compose/ui/text/style/TextDirection;->access$getLtr$cp()I
-HSPLandroidx/compose/ui/text/style/TextDirection;->box-impl(I)Landroidx/compose/ui/text/style/TextDirection;
-HSPLandroidx/compose/ui/text/style/TextDirection;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/TextDirection;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/TextDirection;->unbox-impl()I
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$Companion;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$Companion;->from-8_81llA(J)Landroidx/compose/ui/text/style/TextForegroundStyle;
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$Unspecified;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$Unspecified;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$merge$2;-><init>(Landroidx/compose/ui/text/style/TextForegroundStyle;)V
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$merge$2;->invoke()Landroidx/compose/ui/text/style/TextForegroundStyle;
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle$merge$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle;->merge(Landroidx/compose/ui/text/style/TextForegroundStyle;)Landroidx/compose/ui/text/style/TextForegroundStyle;
-HSPLandroidx/compose/ui/text/style/TextForegroundStyle;->takeOrElse(Lkotlin/jvm/functions/Function0;)Landroidx/compose/ui/text/style/TextForegroundStyle;
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform$Companion;->getNone$ui_text_release()Landroidx/compose/ui/text/style/TextGeometricTransform;
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform;-><init>(FF)V
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform;->access$getNone$cp()Landroidx/compose/ui/text/style/TextGeometricTransform;
-HSPLandroidx/compose/ui/text/style/TextGeometricTransform;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/style/TextIndent$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextIndent$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextIndent$Companion;->getNone()Landroidx/compose/ui/text/style/TextIndent;
-HSPLandroidx/compose/ui/text/style/TextIndent;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextIndent;-><init>(JJ)V
-HSPLandroidx/compose/ui/text/style/TextIndent;-><init>(JJILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextIndent;-><init>(JJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextIndent;->access$getNone$cp()Landroidx/compose/ui/text/style/TextIndent;
-HSPLandroidx/compose/ui/text/style/TextIndent;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/text/style/TextIndent;->getFirstLine-XSAIIZE()J
-HSPLandroidx/compose/ui/text/style/TextIndent;->getRestLine-XSAIIZE()J
-HSPLandroidx/compose/ui/text/style/TextMotion$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextMotion$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextMotion$Companion;->getStatic()Landroidx/compose/ui/text/style/TextMotion;
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity$Companion;->getFontHinting-4e0Vf04()I
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity$Companion;->getLinear-4e0Vf04()I
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity;->access$getFontHinting$cp()I
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity;->access$getLinear$cp()I
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/TextMotion$Linearity;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/text/style/TextMotion;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextMotion;-><init>(IZ)V
-HSPLandroidx/compose/ui/text/style/TextMotion;-><init>(IZLkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextMotion;->access$getStatic$cp()Landroidx/compose/ui/text/style/TextMotion;
-HSPLandroidx/compose/ui/text/style/TextMotion;->getLinearity-4e0Vf04$ui_text_release()I
-HSPLandroidx/compose/ui/text/style/TextMotion;->getSubpixelTextPositioning$ui_text_release()Z
-HSPLandroidx/compose/ui/text/style/TextOverflow$Companion;-><init>()V
-HSPLandroidx/compose/ui/text/style/TextOverflow$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/text/style/TextOverflow$Companion;->getClip-gIe3tQ8()I
-HSPLandroidx/compose/ui/text/style/TextOverflow$Companion;->getEllipsis-gIe3tQ8()I
-HSPLandroidx/compose/ui/text/style/TextOverflow;-><clinit>()V
-HSPLandroidx/compose/ui/text/style/TextOverflow;->access$getClip$cp()I
-HSPLandroidx/compose/ui/text/style/TextOverflow;->access$getEllipsis$cp()I
-HSPLandroidx/compose/ui/text/style/TextOverflow;->constructor-impl(I)I
-HSPLandroidx/compose/ui/text/style/TextOverflow;->equals-impl0(II)Z
-HSPLandroidx/compose/ui/unit/AndroidDensity_androidKt;->Density(Landroid/content/Context;)Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/unit/Constraints$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/Constraints$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/Constraints$Companion;->bitsNeedForSize(I)I
-HSPLandroidx/compose/ui/unit/Constraints$Companion;->createConstraints-Zbe2FdA$ui_unit_release(IIII)J
-HSPLandroidx/compose/ui/unit/Constraints;-><clinit>()V
-HSPLandroidx/compose/ui/unit/Constraints;-><init>(J)V
-HSPLandroidx/compose/ui/unit/Constraints;->access$getMinHeightOffsets$cp()[I
-HSPLandroidx/compose/ui/unit/Constraints;->box-impl(J)Landroidx/compose/ui/unit/Constraints;
-HSPLandroidx/compose/ui/unit/Constraints;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/Constraints;->copy-Zbe2FdA$default(JIIIIILjava/lang/Object;)J
-HSPLandroidx/compose/ui/unit/Constraints;->copy-Zbe2FdA(JIIII)J
-HSPLandroidx/compose/ui/unit/Constraints;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/unit/Constraints;->equals-impl(JLjava/lang/Object;)Z
-HSPLandroidx/compose/ui/unit/Constraints;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/unit/Constraints;->getFocusIndex-impl(J)I
-HSPLandroidx/compose/ui/unit/Constraints;->getHasBoundedHeight-impl(J)Z
-HSPLandroidx/compose/ui/unit/Constraints;->getHasBoundedWidth-impl(J)Z
-HSPLandroidx/compose/ui/unit/Constraints;->getHasFixedHeight-impl(J)Z
-HSPLandroidx/compose/ui/unit/Constraints;->getHasFixedWidth-impl(J)Z
-HSPLandroidx/compose/ui/unit/Constraints;->getMaxHeight-impl(J)I
-HSPLandroidx/compose/ui/unit/Constraints;->getMaxWidth-impl(J)I
-HSPLandroidx/compose/ui/unit/Constraints;->getMinHeight-impl(J)I
-HSPLandroidx/compose/ui/unit/Constraints;->getMinWidth-impl(J)I
-HSPLandroidx/compose/ui/unit/Constraints;->unbox-impl()J
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->Constraints$default(IIIIILjava/lang/Object;)J
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->Constraints(IIII)J
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->addMaxWithMinimum(II)I
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->constrain-4WqzIAM(JJ)J
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->constrain-N9IONVI(JJ)J
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->constrainHeight-K40F9xA(JI)I
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->constrainWidth-K40F9xA(JI)I
-HSPLandroidx/compose/ui/unit/ConstraintsKt;->offset-NN6Ew-U(JII)J
-HSPLandroidx/compose/ui/unit/Density;->roundToPx-0680j_4(F)I
-HSPLandroidx/compose/ui/unit/Density;->toDp-u2uoSUM(I)F
-HSPLandroidx/compose/ui/unit/Density;->toPx--R2X_6o(J)F
-HSPLandroidx/compose/ui/unit/Density;->toPx-0680j_4(F)F
-HSPLandroidx/compose/ui/unit/Density;->toSize-XkaWNTQ(J)J
-HSPLandroidx/compose/ui/unit/DensityImpl;-><init>(FF)V
-HSPLandroidx/compose/ui/unit/DensityImpl;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/unit/DensityImpl;->getDensity()F
-HSPLandroidx/compose/ui/unit/DensityImpl;->getFontScale()F
-HSPLandroidx/compose/ui/unit/DensityKt;->Density$default(FFILjava/lang/Object;)Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/unit/DensityKt;->Density(FF)Landroidx/compose/ui/unit/Density;
-HSPLandroidx/compose/ui/unit/Dp$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/Dp$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/Dp$Companion;->getUnspecified-D9Ej5fM()F
-HSPLandroidx/compose/ui/unit/Dp;-><clinit>()V
-HSPLandroidx/compose/ui/unit/Dp;-><init>(F)V
-HSPLandroidx/compose/ui/unit/Dp;->access$getUnspecified$cp()F
-HSPLandroidx/compose/ui/unit/Dp;->box-impl(F)Landroidx/compose/ui/unit/Dp;
-HSPLandroidx/compose/ui/unit/Dp;->compareTo(Ljava/lang/Object;)I
-HSPLandroidx/compose/ui/unit/Dp;->compareTo-0680j_4(F)I
-HSPLandroidx/compose/ui/unit/Dp;->compareTo-0680j_4(FF)I
-HSPLandroidx/compose/ui/unit/Dp;->constructor-impl(F)F
-HSPLandroidx/compose/ui/unit/Dp;->equals(Ljava/lang/Object;)Z
-HSPLandroidx/compose/ui/unit/Dp;->equals-impl(FLjava/lang/Object;)Z
-HSPLandroidx/compose/ui/unit/Dp;->equals-impl0(FF)Z
-HSPLandroidx/compose/ui/unit/Dp;->unbox-impl()F
-HSPLandroidx/compose/ui/unit/DpKt;->DpOffset-YgX7TsA(FF)J
-HSPLandroidx/compose/ui/unit/DpKt;->DpSize-YgX7TsA(FF)J
-HSPLandroidx/compose/ui/unit/DpOffset$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/DpOffset$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/DpOffset;-><clinit>()V
-HSPLandroidx/compose/ui/unit/DpOffset;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/DpSize$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/DpSize$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/DpSize$Companion;->getUnspecified-MYxV2XQ()J
-HSPLandroidx/compose/ui/unit/DpSize;-><clinit>()V
-HSPLandroidx/compose/ui/unit/DpSize;->access$getUnspecified$cp()J
-HSPLandroidx/compose/ui/unit/DpSize;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/DpSize;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/unit/DpSize;->getHeight-D9Ej5fM(J)F
-HSPLandroidx/compose/ui/unit/DpSize;->getWidth-D9Ej5fM(J)F
-HSPLandroidx/compose/ui/unit/IntOffset$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/IntOffset$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/IntOffset$Companion;->getZero-nOcc-ac()J
-HSPLandroidx/compose/ui/unit/IntOffset;-><clinit>()V
-HSPLandroidx/compose/ui/unit/IntOffset;-><init>(J)V
-HSPLandroidx/compose/ui/unit/IntOffset;->access$getZero$cp()J
-HSPLandroidx/compose/ui/unit/IntOffset;->box-impl(J)Landroidx/compose/ui/unit/IntOffset;
-HSPLandroidx/compose/ui/unit/IntOffset;->component1-impl(J)I
-HSPLandroidx/compose/ui/unit/IntOffset;->component2-impl(J)I
-HSPLandroidx/compose/ui/unit/IntOffset;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/IntOffset;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/unit/IntOffset;->getX-impl(J)I
-HSPLandroidx/compose/ui/unit/IntOffset;->getY-impl(J)I
-HSPLandroidx/compose/ui/unit/IntOffset;->unbox-impl()J
-HSPLandroidx/compose/ui/unit/IntOffsetKt;->IntOffset(II)J
-HSPLandroidx/compose/ui/unit/IntOffsetKt;->minus-Nv-tHpc(JJ)J
-HSPLandroidx/compose/ui/unit/IntOffsetKt;->plus-Nv-tHpc(JJ)J
-HSPLandroidx/compose/ui/unit/IntSize$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/IntSize$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/IntSize$Companion;->getZero-YbymL2g()J
-HSPLandroidx/compose/ui/unit/IntSize;-><clinit>()V
-HSPLandroidx/compose/ui/unit/IntSize;-><init>(J)V
-HSPLandroidx/compose/ui/unit/IntSize;->access$getZero$cp()J
-HSPLandroidx/compose/ui/unit/IntSize;->box-impl(J)Landroidx/compose/ui/unit/IntSize;
-HSPLandroidx/compose/ui/unit/IntSize;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/IntSize;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/unit/IntSize;->getHeight-impl(J)I
-HSPLandroidx/compose/ui/unit/IntSize;->getWidth-impl(J)I
-HSPLandroidx/compose/ui/unit/IntSize;->unbox-impl()J
-HSPLandroidx/compose/ui/unit/IntSizeKt;->IntSize(II)J
-HSPLandroidx/compose/ui/unit/IntSizeKt;->getCenter-ozmzZPI(J)J
-HSPLandroidx/compose/ui/unit/IntSizeKt;->toSize-ozmzZPI(J)J
-HSPLandroidx/compose/ui/unit/LayoutDirection;->$values()[Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/unit/LayoutDirection;-><clinit>()V
-HSPLandroidx/compose/ui/unit/LayoutDirection;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/compose/ui/unit/LayoutDirection;->values()[Landroidx/compose/ui/unit/LayoutDirection;
-HSPLandroidx/compose/ui/unit/TextUnit$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/TextUnit$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/TextUnit$Companion;->getUnspecified-XSAIIZE()J
-HSPLandroidx/compose/ui/unit/TextUnit;-><clinit>()V
-HSPLandroidx/compose/ui/unit/TextUnit;->access$getUnspecified$cp()J
-HSPLandroidx/compose/ui/unit/TextUnit;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/TextUnit;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/unit/TextUnit;->getRawType-impl(J)J
-HSPLandroidx/compose/ui/unit/TextUnit;->getType-UIouoOA(J)J
-HSPLandroidx/compose/ui/unit/TextUnit;->getValue-impl(J)F
-HSPLandroidx/compose/ui/unit/TextUnitKt;->getSp(D)J
-HSPLandroidx/compose/ui/unit/TextUnitKt;->getSp(I)J
-HSPLandroidx/compose/ui/unit/TextUnitKt;->isUnspecified--R2X_6o(J)Z
-HSPLandroidx/compose/ui/unit/TextUnitKt;->pack(JF)J
-HSPLandroidx/compose/ui/unit/TextUnitType$Companion;-><init>()V
-HSPLandroidx/compose/ui/unit/TextUnitType$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/compose/ui/unit/TextUnitType$Companion;->getEm-UIouoOA()J
-HSPLandroidx/compose/ui/unit/TextUnitType$Companion;->getSp-UIouoOA()J
-HSPLandroidx/compose/ui/unit/TextUnitType$Companion;->getUnspecified-UIouoOA()J
-HSPLandroidx/compose/ui/unit/TextUnitType;-><clinit>()V
-HSPLandroidx/compose/ui/unit/TextUnitType;-><init>(J)V
-HSPLandroidx/compose/ui/unit/TextUnitType;->access$getEm$cp()J
-HSPLandroidx/compose/ui/unit/TextUnitType;->access$getSp$cp()J
-HSPLandroidx/compose/ui/unit/TextUnitType;->access$getUnspecified$cp()J
-HSPLandroidx/compose/ui/unit/TextUnitType;->box-impl(J)Landroidx/compose/ui/unit/TextUnitType;
-HSPLandroidx/compose/ui/unit/TextUnitType;->constructor-impl(J)J
-HSPLandroidx/compose/ui/unit/TextUnitType;->equals-impl0(JJ)Z
-HSPLandroidx/compose/ui/unit/TextUnitType;->unbox-impl()J
-HSPLandroidx/compose/ui/util/MathHelpersKt;->lerp(FFF)F
-HSPLandroidx/core/app/ComponentActivity;-><init>()V
-HSPLandroidx/core/app/ComponentActivity;->onCreate(Landroid/os/Bundle;)V
-HSPLandroidx/core/app/CoreComponentFactory;-><init>()V
-HSPLandroidx/core/app/CoreComponentFactory;->checkCompatWrapper(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/core/app/CoreComponentFactory;->instantiateActivity(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/app/Activity;
-HSPLandroidx/core/app/CoreComponentFactory;->instantiateApplication(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/app/Application;
-HSPLandroidx/core/app/CoreComponentFactory;->instantiateProvider(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/content/ContentProvider;
-HSPLandroidx/core/graphics/Insets;-><clinit>()V
-HSPLandroidx/core/graphics/Insets;-><init>(IIII)V
-HSPLandroidx/core/graphics/TypefaceCompat;-><clinit>()V
-HSPLandroidx/core/graphics/TypefaceCompat;->createFromFontInfo(Landroid/content/Context;Landroid/os/CancellationSignal;[Landroidx/core/provider/FontsContractCompat$FontInfo;I)Landroid/graphics/Typeface;
-HSPLandroidx/core/graphics/TypefaceCompatApi29Impl;-><init>()V
-HSPLandroidx/core/graphics/TypefaceCompatApi29Impl;->createFromFontInfo(Landroid/content/Context;Landroid/os/CancellationSignal;[Landroidx/core/provider/FontsContractCompat$FontInfo;I)Landroid/graphics/Typeface;
-HSPLandroidx/core/graphics/TypefaceCompatApi29Impl;->findBaseFont(Landroid/graphics/fonts/FontFamily;I)Landroid/graphics/fonts/Font;
-HSPLandroidx/core/graphics/TypefaceCompatApi29Impl;->getMatchScore(Landroid/graphics/fonts/FontStyle;Landroid/graphics/fonts/FontStyle;)I
-HSPLandroidx/core/graphics/TypefaceCompatBaseImpl;-><init>()V
-HSPLandroidx/core/graphics/TypefaceCompatUtil$Api19Impl;->openFileDescriptor(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Landroid/os/CancellationSignal;)Landroid/os/ParcelFileDescriptor;
-HSPLandroidx/core/graphics/TypefaceCompatUtil;->mmap(Landroid/content/Context;Landroid/os/CancellationSignal;Landroid/net/Uri;)Ljava/nio/ByteBuffer;
-HSPLandroidx/core/graphics/drawable/DrawableKt;->toBitmap$default(Landroid/graphics/drawable/Drawable;IILandroid/graphics/Bitmap$Config;ILjava/lang/Object;)Landroid/graphics/Bitmap;
-HSPLandroidx/core/graphics/drawable/DrawableKt;->toBitmap(Landroid/graphics/drawable/Drawable;IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;
-HSPLandroidx/core/os/BuildCompat$Extensions30Impl;-><clinit>()V
-HSPLandroidx/core/os/BuildCompat;-><clinit>()V
-HSPLandroidx/core/os/BuildCompat;->isAtLeastT()Z
-HSPLandroidx/core/os/HandlerCompat$Api28Impl;->createAsync(Landroid/os/Looper;)Landroid/os/Handler;
-HSPLandroidx/core/os/HandlerCompat;->createAsync(Landroid/os/Looper;)Landroid/os/Handler;
-HSPLandroidx/core/os/TraceCompat$Api18Impl;->beginSection(Ljava/lang/String;)V
-HSPLandroidx/core/os/TraceCompat$Api18Impl;->endSection()V
-HSPLandroidx/core/os/TraceCompat;-><clinit>()V
-HSPLandroidx/core/os/TraceCompat;->beginSection(Ljava/lang/String;)V
-HSPLandroidx/core/os/TraceCompat;->endSection()V
-HSPLandroidx/core/provider/FontProvider$$ExternalSyntheticLambda0;-><init>()V
-HSPLandroidx/core/provider/FontProvider$Api16Impl;->query(Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)Landroid/database/Cursor;
-HSPLandroidx/core/provider/FontProvider;-><clinit>()V
-HSPLandroidx/core/provider/FontProvider;->convertToByteArrayList([Landroid/content/pm/Signature;)Ljava/util/List;
-HSPLandroidx/core/provider/FontProvider;->equalsByteArrayList(Ljava/util/List;Ljava/util/List;)Z
-HSPLandroidx/core/provider/FontProvider;->getCertificates(Landroidx/core/provider/FontRequest;Landroid/content/res/Resources;)Ljava/util/List;
-HSPLandroidx/core/provider/FontProvider;->getFontFamilyResult(Landroid/content/Context;Landroidx/core/provider/FontRequest;Landroid/os/CancellationSignal;)Landroidx/core/provider/FontsContractCompat$FontFamilyResult;
-HSPLandroidx/core/provider/FontProvider;->getProvider(Landroid/content/pm/PackageManager;Landroidx/core/provider/FontRequest;Landroid/content/res/Resources;)Landroid/content/pm/ProviderInfo;
-HSPLandroidx/core/provider/FontProvider;->query(Landroid/content/Context;Landroidx/core/provider/FontRequest;Ljava/lang/String;Landroid/os/CancellationSignal;)[Landroidx/core/provider/FontsContractCompat$FontInfo;
-HSPLandroidx/core/provider/FontRequest;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V
-HSPLandroidx/core/provider/FontRequest;->createIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-HSPLandroidx/core/provider/FontRequest;->getCertificates()Ljava/util/List;
-HSPLandroidx/core/provider/FontRequest;->getProviderAuthority()Ljava/lang/String;
-HSPLandroidx/core/provider/FontRequest;->getProviderPackage()Ljava/lang/String;
-HSPLandroidx/core/provider/FontRequest;->getQuery()Ljava/lang/String;
-HSPLandroidx/core/provider/FontsContractCompat$FontFamilyResult;-><init>(I[Landroidx/core/provider/FontsContractCompat$FontInfo;)V
-HSPLandroidx/core/provider/FontsContractCompat$FontFamilyResult;->create(I[Landroidx/core/provider/FontsContractCompat$FontInfo;)Landroidx/core/provider/FontsContractCompat$FontFamilyResult;
-HSPLandroidx/core/provider/FontsContractCompat$FontFamilyResult;->getFonts()[Landroidx/core/provider/FontsContractCompat$FontInfo;
-HSPLandroidx/core/provider/FontsContractCompat$FontFamilyResult;->getStatusCode()I
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;-><init>(Landroid/net/Uri;IIZI)V
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;->create(Landroid/net/Uri;IIZI)Landroidx/core/provider/FontsContractCompat$FontInfo;
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;->getResultCode()I
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;->getTtcIndex()I
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;->getUri()Landroid/net/Uri;
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;->getWeight()I
-HSPLandroidx/core/provider/FontsContractCompat$FontInfo;->isItalic()Z
-HSPLandroidx/core/provider/FontsContractCompat;->buildTypeface(Landroid/content/Context;Landroid/os/CancellationSignal;[Landroidx/core/provider/FontsContractCompat$FontInfo;)Landroid/graphics/Typeface;
-HSPLandroidx/core/provider/FontsContractCompat;->fetchFonts(Landroid/content/Context;Landroid/os/CancellationSignal;Landroidx/core/provider/FontRequest;)Landroidx/core/provider/FontsContractCompat$FontFamilyResult;
-HSPLandroidx/core/util/Preconditions;->checkArgument(ZLjava/lang/Object;)V
-HSPLandroidx/core/util/Preconditions;->checkArgumentNonnegative(ILjava/lang/String;)I
-HSPLandroidx/core/util/Preconditions;->checkNotNull(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/core/util/Preconditions;->checkNotNull(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/core/util/Preconditions;->checkState(ZLjava/lang/String;)V
-HSPLandroidx/core/view/AccessibilityDelegateCompat$AccessibilityDelegateAdapter;-><init>(Landroidx/core/view/AccessibilityDelegateCompat;)V
-HSPLandroidx/core/view/AccessibilityDelegateCompat;-><clinit>()V
-HSPLandroidx/core/view/AccessibilityDelegateCompat;-><init>()V
-HSPLandroidx/core/view/AccessibilityDelegateCompat;-><init>(Landroid/view/View$AccessibilityDelegate;)V
-HSPLandroidx/core/view/AccessibilityDelegateCompat;->getBridge()Landroid/view/View$AccessibilityDelegate;
-HSPLandroidx/core/view/MenuHostHelper;-><init>(Ljava/lang/Runnable;)V
-HSPLandroidx/core/view/ViewCompat$$ExternalSyntheticLambda0;-><init>()V
-HSPLandroidx/core/view/ViewCompat$AccessibilityPaneVisibilityManager;-><init>()V
-HSPLandroidx/core/view/ViewCompat$Api21Impl$1;-><init>(Landroid/view/View;Landroidx/core/view/OnApplyWindowInsetsListener;)V
-HSPLandroidx/core/view/ViewCompat$Api21Impl;->setOnApplyWindowInsetsListener(Landroid/view/View;Landroidx/core/view/OnApplyWindowInsetsListener;)V
-HSPLandroidx/core/view/ViewCompat;-><clinit>()V
-HSPLandroidx/core/view/ViewCompat;->setAccessibilityDelegate(Landroid/view/View;Landroidx/core/view/AccessibilityDelegateCompat;)V
-HSPLandroidx/core/view/ViewCompat;->setOnApplyWindowInsetsListener(Landroid/view/View;Landroidx/core/view/OnApplyWindowInsetsListener;)V
-HSPLandroidx/core/view/ViewCompat;->setWindowInsetsAnimationCallback(Landroid/view/View;Landroidx/core/view/WindowInsetsAnimationCompat$Callback;)V
-HSPLandroidx/core/view/ViewKt$ancestors$1;-><clinit>()V
-HSPLandroidx/core/view/ViewKt$ancestors$1;-><init>()V
-HSPLandroidx/core/view/ViewKt$ancestors$1;->invoke(Landroid/view/ViewParent;)Landroid/view/ViewParent;
-HSPLandroidx/core/view/ViewKt$ancestors$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/core/view/ViewKt;->getAncestors(Landroid/view/View;)Lkotlin/sequences/Sequence;
-HSPLandroidx/core/view/WindowCompat;->getInsetsController(Landroid/view/Window;Landroid/view/View;)Landroidx/core/view/WindowInsetsControllerCompat;
-HSPLandroidx/core/view/WindowInsetsAnimationCompat$Callback;-><init>(I)V
-HSPLandroidx/core/view/WindowInsetsAnimationCompat$Callback;->getDispatchMode()I
-HSPLandroidx/core/view/WindowInsetsAnimationCompat$Impl30$ProxyCallback;-><init>(Landroidx/core/view/WindowInsetsAnimationCompat$Callback;)V
-HSPLandroidx/core/view/WindowInsetsAnimationCompat$Impl30;->setCallback(Landroid/view/View;Landroidx/core/view/WindowInsetsAnimationCompat$Callback;)V
-HSPLandroidx/core/view/WindowInsetsAnimationCompat;->setCallback(Landroid/view/View;Landroidx/core/view/WindowInsetsAnimationCompat$Callback;)V
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->captionBar()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->displayCutout()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->ime()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->mandatorySystemGestures()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->navigationBars()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->statusBars()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->systemBars()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->systemGestures()I
-HSPLandroidx/core/view/WindowInsetsCompat$Type;->tappableElement()I
-HSPLandroidx/core/view/WindowInsetsControllerCompat$Impl30;-><init>(Landroid/view/Window;Landroidx/core/view/WindowInsetsControllerCompat;)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat$Impl30;-><init>(Landroid/view/WindowInsetsController;Landroidx/core/view/WindowInsetsControllerCompat;)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat$Impl30;->setAppearanceLightNavigationBars(Z)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat$Impl30;->setAppearanceLightStatusBars(Z)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat$Impl30;->unsetSystemUiFlag(I)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat$Impl;-><init>()V
-HSPLandroidx/core/view/WindowInsetsControllerCompat;-><init>(Landroid/view/Window;Landroid/view/View;)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat;->setAppearanceLightNavigationBars(Z)V
-HSPLandroidx/core/view/WindowInsetsControllerCompat;->setAppearanceLightStatusBars(Z)V
-HSPLandroidx/core/view/accessibility/AccessibilityNodeProviderCompat;-><init>(Ljava/lang/Object;)V
-HSPLandroidx/credentials/provider/Action$Companion;-><init>()V
-HSPLandroidx/credentials/provider/Action$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/credentials/provider/Action$Companion;->fromSlice(Landroid/app/slice/Slice;)Landroidx/credentials/provider/Action;
-HSPLandroidx/credentials/provider/Action;-><clinit>()V
-HSPLandroidx/credentials/provider/Action;-><init>(Ljava/lang/CharSequence;Landroid/app/PendingIntent;Ljava/lang/CharSequence;)V
-HSPLandroidx/credentials/provider/Action;->getPendingIntent()Landroid/app/PendingIntent;
-HSPLandroidx/credentials/provider/Action;->getSubtitle()Ljava/lang/CharSequence;
-HSPLandroidx/credentials/provider/Action;->getTitle()Ljava/lang/CharSequence;
-HSPLandroidx/credentials/provider/RemoteEntry$Companion;-><init>()V
-HSPLandroidx/credentials/provider/RemoteEntry$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/credentials/provider/RemoteEntry$Companion;->fromSlice(Landroid/app/slice/Slice;)Landroidx/credentials/provider/RemoteEntry;
-HSPLandroidx/credentials/provider/RemoteEntry;-><clinit>()V
-HSPLandroidx/credentials/provider/RemoteEntry;-><init>(Landroid/app/PendingIntent;)V
-HSPLandroidx/credentials/provider/RemoteEntry;->getPendingIntent()Landroid/app/PendingIntent;
-HSPLandroidx/customview/poolingcontainer/PoolingContainer;-><clinit>()V
-HSPLandroidx/customview/poolingcontainer/PoolingContainer;->addPoolingContainerListener(Landroid/view/View;Landroidx/customview/poolingcontainer/PoolingContainerListener;)V
-HSPLandroidx/customview/poolingcontainer/PoolingContainer;->getPoolingContainerListenerHolder(Landroid/view/View;)Landroidx/customview/poolingcontainer/PoolingContainerListenerHolder;
-HSPLandroidx/customview/poolingcontainer/PoolingContainer;->isPoolingContainer(Landroid/view/View;)Z
-HSPLandroidx/customview/poolingcontainer/PoolingContainer;->isWithinPoolingContainer(Landroid/view/View;)Z
-HSPLandroidx/customview/poolingcontainer/PoolingContainerListenerHolder;-><init>()V
-HSPLandroidx/customview/poolingcontainer/PoolingContainerListenerHolder;->addListener(Landroidx/customview/poolingcontainer/PoolingContainerListener;)V
-HSPLandroidx/emoji2/text/ConcurrencyHelpers$$ExternalSyntheticLambda0;-><init>(Ljava/lang/String;)V
-HSPLandroidx/emoji2/text/ConcurrencyHelpers$$ExternalSyntheticLambda0;->newThread(Ljava/lang/Runnable;)Ljava/lang/Thread;
-HSPLandroidx/emoji2/text/ConcurrencyHelpers$Handler28Impl;->createAsync(Landroid/os/Looper;)Landroid/os/Handler;
-HSPLandroidx/emoji2/text/ConcurrencyHelpers;->$r8$lambda$rm7NN8F9tEuy2Vr8i0fl8_hnx_A(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Thread;
-HSPLandroidx/emoji2/text/ConcurrencyHelpers;->createBackgroundPriorityExecutor(Ljava/lang/String;)Ljava/util/concurrent/ThreadPoolExecutor;
-HSPLandroidx/emoji2/text/ConcurrencyHelpers;->lambda$createBackgroundPriorityExecutor$0(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Thread;
-HSPLandroidx/emoji2/text/ConcurrencyHelpers;->mainHandlerAsync()Landroid/os/Handler;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;-><init>(Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;)V
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->configOrNull(Landroid/content/Context;Landroidx/core/provider/FontRequest;)Landroidx/emoji2/text/EmojiCompat$Config;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->convertToByteArray([Landroid/content/pm/Signature;)Ljava/util/List;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->create(Landroid/content/Context;)Landroidx/emoji2/text/EmojiCompat$Config;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->generateFontRequestFrom(Landroid/content/pm/ProviderInfo;Landroid/content/pm/PackageManager;)Landroidx/core/provider/FontRequest;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->getHelperForApi()Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->hasFlagSystem(Landroid/content/pm/ProviderInfo;)Z
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->queryDefaultInstalledContentProvider(Landroid/content/pm/PackageManager;)Landroid/content/pm/ProviderInfo;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;->queryForDefaultFontRequest(Landroid/content/Context;)Landroidx/core/provider/FontRequest;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;-><init>()V
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19;-><init>()V
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19;->getProviderInfo(Landroid/content/pm/ResolveInfo;)Landroid/content/pm/ProviderInfo;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19;->queryIntentContentProviders(Landroid/content/pm/PackageManager;Landroid/content/Intent;I)Ljava/util/List;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28;-><init>()V
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28;->getSigningSignatures(Landroid/content/pm/PackageManager;Ljava/lang/String;)[Landroid/content/pm/Signature;
-HSPLandroidx/emoji2/text/DefaultEmojiCompatConfig;->create(Landroid/content/Context;)Landroidx/emoji2/text/FontRequestEmojiCompatConfig;
-HSPLandroidx/emoji2/text/DefaultGlyphChecker;-><clinit>()V
-HSPLandroidx/emoji2/text/DefaultGlyphChecker;-><init>()V
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal19$1;-><init>(Landroidx/emoji2/text/EmojiCompat$CompatInternal19;)V
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal19$1;->onLoaded(Landroidx/emoji2/text/MetadataRepo;)V
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal19;-><init>(Landroidx/emoji2/text/EmojiCompat;)V
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal19;->loadMetadata()V
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal19;->onMetadataLoadSuccess(Landroidx/emoji2/text/MetadataRepo;)V
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal19;->process(Ljava/lang/CharSequence;IIIZ)Ljava/lang/CharSequence;
-HSPLandroidx/emoji2/text/EmojiCompat$CompatInternal;-><init>(Landroidx/emoji2/text/EmojiCompat;)V
-HSPLandroidx/emoji2/text/EmojiCompat$Config;-><init>(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;)V
-HSPLandroidx/emoji2/text/EmojiCompat$Config;->getMetadataRepoLoader()Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;
-HSPLandroidx/emoji2/text/EmojiCompat$Config;->setMetadataLoadStrategy(I)Landroidx/emoji2/text/EmojiCompat$Config;
-HSPLandroidx/emoji2/text/EmojiCompat$DefaultSpanFactory;-><init>()V
-HSPLandroidx/emoji2/text/EmojiCompat$InitCallback;-><init>()V
-HSPLandroidx/emoji2/text/EmojiCompat$ListenerDispatcher;-><init>(Ljava/util/Collection;I)V
-HSPLandroidx/emoji2/text/EmojiCompat$ListenerDispatcher;-><init>(Ljava/util/Collection;ILjava/lang/Throwable;)V
-HSPLandroidx/emoji2/text/EmojiCompat$ListenerDispatcher;->run()V
-HSPLandroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;-><init>()V
-HSPLandroidx/emoji2/text/EmojiCompat;-><clinit>()V
-HSPLandroidx/emoji2/text/EmojiCompat;-><init>(Landroidx/emoji2/text/EmojiCompat$Config;)V
-HSPLandroidx/emoji2/text/EmojiCompat;->access$000(Landroidx/emoji2/text/EmojiCompat;)Landroidx/emoji2/text/EmojiCompat$SpanFactory;
-HSPLandroidx/emoji2/text/EmojiCompat;->access$100(Landroidx/emoji2/text/EmojiCompat;)Landroidx/emoji2/text/EmojiCompat$GlyphChecker;
-HSPLandroidx/emoji2/text/EmojiCompat;->get()Landroidx/emoji2/text/EmojiCompat;
-HSPLandroidx/emoji2/text/EmojiCompat;->getLoadState()I
-HSPLandroidx/emoji2/text/EmojiCompat;->init(Landroidx/emoji2/text/EmojiCompat$Config;)Landroidx/emoji2/text/EmojiCompat;
-HSPLandroidx/emoji2/text/EmojiCompat;->isConfigured()Z
-HSPLandroidx/emoji2/text/EmojiCompat;->isInitialized()Z
-HSPLandroidx/emoji2/text/EmojiCompat;->load()V
-HSPLandroidx/emoji2/text/EmojiCompat;->loadMetadata()V
-HSPLandroidx/emoji2/text/EmojiCompat;->onMetadataLoadSuccess()V
-HSPLandroidx/emoji2/text/EmojiCompat;->process(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
-HSPLandroidx/emoji2/text/EmojiCompat;->process(Ljava/lang/CharSequence;II)Ljava/lang/CharSequence;
-HSPLandroidx/emoji2/text/EmojiCompat;->process(Ljava/lang/CharSequence;III)Ljava/lang/CharSequence;
-HSPLandroidx/emoji2/text/EmojiCompat;->process(Ljava/lang/CharSequence;IIII)Ljava/lang/CharSequence;
-HSPLandroidx/emoji2/text/EmojiCompat;->registerInitCallback(Landroidx/emoji2/text/EmojiCompat$InitCallback;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$1;-><init>(Landroidx/emoji2/text/EmojiCompatInitializer;Landroidx/lifecycle/Lifecycle;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$1;->onResume(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultConfig;-><init>(Landroid/content/Context;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader$$ExternalSyntheticLambda0;-><init>(Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;Ljava/util/concurrent/ThreadPoolExecutor;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader$$ExternalSyntheticLambda0;->run()V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader$1;-><init>(Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;Ljava/util/concurrent/ThreadPoolExecutor;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader$1;->onLoaded(Landroidx/emoji2/text/MetadataRepo;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;->$r8$lambda$2V1iWTiAwNxOBlVvz73bbuEdzIw(Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;Ljava/util/concurrent/ThreadPoolExecutor;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;-><init>(Landroid/content/Context;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;->doLoad(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;Ljava/util/concurrent/ThreadPoolExecutor;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;->lambda$load$0(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;Ljava/util/concurrent/ThreadPoolExecutor;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;->load(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$LoadEmojiCompatRunnable;-><init>()V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer$LoadEmojiCompatRunnable;->run()V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer;-><init>()V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer;->create(Landroid/content/Context;)Ljava/lang/Boolean;
-HSPLandroidx/emoji2/text/EmojiCompatInitializer;->create(Landroid/content/Context;)Ljava/lang/Object;
-HSPLandroidx/emoji2/text/EmojiCompatInitializer;->delayUntilFirstResume(Landroid/content/Context;)V
-HSPLandroidx/emoji2/text/EmojiCompatInitializer;->dependencies()Ljava/util/List;
-HSPLandroidx/emoji2/text/EmojiCompatInitializer;->loadEmojiCompatAfterDelay()V
-HSPLandroidx/emoji2/text/EmojiExclusions$EmojiExclusions_Api34;->getExclusions()Ljava/util/Set;
-HSPLandroidx/emoji2/text/EmojiExclusions$EmojiExclusions_Reflections;->getExclusions()Ljava/util/Set;
-HSPLandroidx/emoji2/text/EmojiExclusions;->getEmojiExclusions()Ljava/util/Set;
-HSPLandroidx/emoji2/text/EmojiProcessor$EmojiProcessAddSpanCallback;-><init>(Landroidx/emoji2/text/UnprecomputeTextOnModificationSpannable;Landroidx/emoji2/text/EmojiCompat$SpanFactory;)V
-HSPLandroidx/emoji2/text/EmojiProcessor$EmojiProcessAddSpanCallback;->getResult()Landroidx/emoji2/text/UnprecomputeTextOnModificationSpannable;
-HSPLandroidx/emoji2/text/EmojiProcessor$EmojiProcessAddSpanCallback;->getResult()Ljava/lang/Object;
-HSPLandroidx/emoji2/text/EmojiProcessor$ProcessorSm;-><init>(Landroidx/emoji2/text/MetadataRepo$Node;Z[I)V
-HSPLandroidx/emoji2/text/EmojiProcessor$ProcessorSm;->check(I)I
-HSPLandroidx/emoji2/text/EmojiProcessor$ProcessorSm;->isInFlushableState()Z
-HSPLandroidx/emoji2/text/EmojiProcessor$ProcessorSm;->reset()I
-HSPLandroidx/emoji2/text/EmojiProcessor;-><init>(Landroidx/emoji2/text/MetadataRepo;Landroidx/emoji2/text/EmojiCompat$SpanFactory;Landroidx/emoji2/text/EmojiCompat$GlyphChecker;Z[ILjava/util/Set;)V
-HSPLandroidx/emoji2/text/EmojiProcessor;->initExclusions(Ljava/util/Set;)V
-HSPLandroidx/emoji2/text/EmojiProcessor;->process(Ljava/lang/CharSequence;IIIZ)Ljava/lang/CharSequence;
-HSPLandroidx/emoji2/text/EmojiProcessor;->process(Ljava/lang/CharSequence;IIIZLandroidx/emoji2/text/EmojiProcessor$EmojiProcessCallback;)Ljava/lang/Object;
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontProviderHelper;-><init>()V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontProviderHelper;->buildTypeface(Landroid/content/Context;Landroidx/core/provider/FontsContractCompat$FontInfo;)Landroid/graphics/Typeface;
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontProviderHelper;->fetchFonts(Landroid/content/Context;Landroidx/core/provider/FontRequest;)Landroidx/core/provider/FontsContractCompat$FontFamilyResult;
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader$$ExternalSyntheticLambda0;-><init>(Landroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;)V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader$$ExternalSyntheticLambda0;->run()V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;-><init>(Landroid/content/Context;Landroidx/core/provider/FontRequest;Landroidx/emoji2/text/FontRequestEmojiCompatConfig$FontProviderHelper;)V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;->cleanUp()V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;->createMetadata()V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;->load(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;)V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;->loadInternal()V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;->retrieveFontInfo()Landroidx/core/provider/FontsContractCompat$FontInfo;
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;->setExecutor(Ljava/util/concurrent/Executor;)V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig;-><clinit>()V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig;-><init>(Landroid/content/Context;Landroidx/core/provider/FontRequest;)V
-HSPLandroidx/emoji2/text/FontRequestEmojiCompatConfig;->setLoadingExecutor(Ljava/util/concurrent/Executor;)Landroidx/emoji2/text/FontRequestEmojiCompatConfig;
-HSPLandroidx/emoji2/text/MetadataListReader$ByteBufferReader;-><init>(Ljava/nio/ByteBuffer;)V
-HSPLandroidx/emoji2/text/MetadataListReader$ByteBufferReader;->getPosition()J
-HSPLandroidx/emoji2/text/MetadataListReader$ByteBufferReader;->readTag()I
-HSPLandroidx/emoji2/text/MetadataListReader$ByteBufferReader;->readUnsignedInt()J
-HSPLandroidx/emoji2/text/MetadataListReader$ByteBufferReader;->readUnsignedShort()I
-HSPLandroidx/emoji2/text/MetadataListReader$ByteBufferReader;->skip(I)V
-HSPLandroidx/emoji2/text/MetadataListReader$OffsetInfo;-><init>(JJ)V
-HSPLandroidx/emoji2/text/MetadataListReader$OffsetInfo;->getStartOffset()J
-HSPLandroidx/emoji2/text/MetadataListReader;->findOffsetInfo(Landroidx/emoji2/text/MetadataListReader$OpenTypeReader;)Landroidx/emoji2/text/MetadataListReader$OffsetInfo;
-HSPLandroidx/emoji2/text/MetadataListReader;->read(Ljava/nio/ByteBuffer;)Landroidx/emoji2/text/flatbuffer/MetadataList;
-HSPLandroidx/emoji2/text/MetadataListReader;->toUnsignedInt(I)J
-HSPLandroidx/emoji2/text/MetadataListReader;->toUnsignedShort(S)I
-HSPLandroidx/emoji2/text/MetadataRepo$Node;-><init>()V
-HSPLandroidx/emoji2/text/MetadataRepo$Node;-><init>(I)V
-HSPLandroidx/emoji2/text/MetadataRepo$Node;->get(I)Landroidx/emoji2/text/MetadataRepo$Node;
-HSPLandroidx/emoji2/text/MetadataRepo$Node;->put(Landroidx/emoji2/text/TypefaceEmojiRasterizer;II)V
-HSPLandroidx/emoji2/text/MetadataRepo;-><init>(Landroid/graphics/Typeface;Landroidx/emoji2/text/flatbuffer/MetadataList;)V
-HSPLandroidx/emoji2/text/MetadataRepo;->create(Landroid/graphics/Typeface;Ljava/nio/ByteBuffer;)Landroidx/emoji2/text/MetadataRepo;
-HSPLandroidx/emoji2/text/MetadataRepo;->getMetadataList()Landroidx/emoji2/text/flatbuffer/MetadataList;
-HSPLandroidx/emoji2/text/MetadataRepo;->getRootNode()Landroidx/emoji2/text/MetadataRepo$Node;
-HSPLandroidx/emoji2/text/MetadataRepo;->put(Landroidx/emoji2/text/TypefaceEmojiRasterizer;)V
-HSPLandroidx/emoji2/text/TypefaceEmojiRasterizer;-><clinit>()V
-HSPLandroidx/emoji2/text/TypefaceEmojiRasterizer;-><init>(Landroidx/emoji2/text/MetadataRepo;I)V
-HSPLandroidx/emoji2/text/TypefaceEmojiRasterizer;->getCodepointAt(I)I+]Landroidx/emoji2/text/flatbuffer/MetadataItem;Landroidx/emoji2/text/flatbuffer/MetadataItem;
-HSPLandroidx/emoji2/text/TypefaceEmojiRasterizer;->getCodepointsLength()I+]Landroidx/emoji2/text/flatbuffer/MetadataItem;Landroidx/emoji2/text/flatbuffer/MetadataItem;
-HSPLandroidx/emoji2/text/TypefaceEmojiRasterizer;->getId()I
-HSPLandroidx/emoji2/text/TypefaceEmojiRasterizer;->getMetadataItem()Landroidx/emoji2/text/flatbuffer/MetadataItem;+]Landroidx/emoji2/text/flatbuffer/MetadataList;Landroidx/emoji2/text/flatbuffer/MetadataList;]Landroidx/emoji2/text/MetadataRepo;Landroidx/emoji2/text/MetadataRepo;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataItem;-><init>()V
-HSPLandroidx/emoji2/text/flatbuffer/MetadataItem;->__assign(ILjava/nio/ByteBuffer;)Landroidx/emoji2/text/flatbuffer/MetadataItem;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataItem;->__init(ILjava/nio/ByteBuffer;)V
-HSPLandroidx/emoji2/text/flatbuffer/MetadataItem;->codepoints(I)I+]Landroidx/emoji2/text/flatbuffer/Table;Landroidx/emoji2/text/flatbuffer/MetadataItem;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataItem;->codepointsLength()I+]Landroidx/emoji2/text/flatbuffer/Table;Landroidx/emoji2/text/flatbuffer/MetadataItem;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataItem;->id()I
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;-><init>()V
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;->__assign(ILjava/nio/ByteBuffer;)Landroidx/emoji2/text/flatbuffer/MetadataList;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;->__init(ILjava/nio/ByteBuffer;)V
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;->getRootAsMetadataList(Ljava/nio/ByteBuffer;)Landroidx/emoji2/text/flatbuffer/MetadataList;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;->getRootAsMetadataList(Ljava/nio/ByteBuffer;Landroidx/emoji2/text/flatbuffer/MetadataList;)Landroidx/emoji2/text/flatbuffer/MetadataList;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;->list(Landroidx/emoji2/text/flatbuffer/MetadataItem;I)Landroidx/emoji2/text/flatbuffer/MetadataItem;+]Landroidx/emoji2/text/flatbuffer/MetadataItem;Landroidx/emoji2/text/flatbuffer/MetadataItem;]Landroidx/emoji2/text/flatbuffer/Table;Landroidx/emoji2/text/flatbuffer/MetadataList;
-HSPLandroidx/emoji2/text/flatbuffer/MetadataList;->listLength()I
-HSPLandroidx/emoji2/text/flatbuffer/Table;-><init>()V
-HSPLandroidx/emoji2/text/flatbuffer/Table;->__indirect(I)I
-HSPLandroidx/emoji2/text/flatbuffer/Table;->__offset(I)I
-HSPLandroidx/emoji2/text/flatbuffer/Table;->__reset(ILjava/nio/ByteBuffer;)V
-HSPLandroidx/emoji2/text/flatbuffer/Table;->__vector(I)I
-HSPLandroidx/emoji2/text/flatbuffer/Table;->__vector_len(I)I
-HSPLandroidx/emoji2/text/flatbuffer/Utf8;-><init>()V
-HSPLandroidx/emoji2/text/flatbuffer/Utf8;->getDefault()Landroidx/emoji2/text/flatbuffer/Utf8;
-HSPLandroidx/emoji2/text/flatbuffer/Utf8Safe;-><init>()V
-HSPLandroidx/lifecycle/DefaultLifecycleObserver;->onCreate(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/DefaultLifecycleObserver;->onDestroy(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/DefaultLifecycleObserver;->onPause(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/DefaultLifecycleObserver;->onStart(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/DefaultLifecycleObserver;->onStop(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;-><init>()V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;->onActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;->onActivityDestroyed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;->onActivityPaused(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;->onActivityResumed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;->onActivityStarted(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/EmptyActivityLifecycleCallbacks;->onActivityStopped(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/FullLifecycleObserverAdapter$1;-><clinit>()V
-HSPLandroidx/lifecycle/FullLifecycleObserverAdapter;-><init>(Landroidx/lifecycle/FullLifecycleObserver;Landroidx/lifecycle/LifecycleEventObserver;)V
-HSPLandroidx/lifecycle/FullLifecycleObserverAdapter;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/lifecycle/Lifecycle$1;-><clinit>()V
-HSPLandroidx/lifecycle/Lifecycle$Event;->$values()[Landroidx/lifecycle/Lifecycle$Event;
-HSPLandroidx/lifecycle/Lifecycle$Event;-><clinit>()V
-HSPLandroidx/lifecycle/Lifecycle$Event;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/lifecycle/Lifecycle$Event;->downFrom(Landroidx/lifecycle/Lifecycle$State;)Landroidx/lifecycle/Lifecycle$Event;
-HSPLandroidx/lifecycle/Lifecycle$Event;->getTargetState()Landroidx/lifecycle/Lifecycle$State;
-HSPLandroidx/lifecycle/Lifecycle$Event;->upFrom(Landroidx/lifecycle/Lifecycle$State;)Landroidx/lifecycle/Lifecycle$Event;
-HSPLandroidx/lifecycle/Lifecycle$Event;->values()[Landroidx/lifecycle/Lifecycle$Event;
-HSPLandroidx/lifecycle/Lifecycle$State;->$values()[Landroidx/lifecycle/Lifecycle$State;
-HSPLandroidx/lifecycle/Lifecycle$State;-><clinit>()V
-HSPLandroidx/lifecycle/Lifecycle$State;-><init>(Ljava/lang/String;I)V
-HSPLandroidx/lifecycle/Lifecycle$State;->isAtLeast(Landroidx/lifecycle/Lifecycle$State;)Z
-HSPLandroidx/lifecycle/Lifecycle$State;->values()[Landroidx/lifecycle/Lifecycle$State;
-HSPLandroidx/lifecycle/Lifecycle;-><init>()V
-HSPLandroidx/lifecycle/LifecycleDispatcher$DispatcherActivityCallback;-><init>()V
-HSPLandroidx/lifecycle/LifecycleDispatcher$DispatcherActivityCallback;->onActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/LifecycleDispatcher$DispatcherActivityCallback;->onActivityStopped(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/LifecycleDispatcher;-><clinit>()V
-HSPLandroidx/lifecycle/LifecycleDispatcher;->init(Landroid/content/Context;)V
-HSPLandroidx/lifecycle/LifecycleRegistry$ObserverWithState;-><init>(Landroidx/lifecycle/LifecycleObserver;Landroidx/lifecycle/Lifecycle$State;)V
-HSPLandroidx/lifecycle/LifecycleRegistry$ObserverWithState;->dispatchEvent(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;-><init>(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;-><init>(Landroidx/lifecycle/LifecycleOwner;Z)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->addObserver(Landroidx/lifecycle/LifecycleObserver;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->backwardPass(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->calculateTargetState(Landroidx/lifecycle/LifecycleObserver;)Landroidx/lifecycle/Lifecycle$State;
-HSPLandroidx/lifecycle/LifecycleRegistry;->enforceMainThreadIfNeeded(Ljava/lang/String;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->forwardPass(Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->getCurrentState()Landroidx/lifecycle/Lifecycle$State;
-HSPLandroidx/lifecycle/LifecycleRegistry;->handleLifecycleEvent(Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->isSynced()Z
-HSPLandroidx/lifecycle/LifecycleRegistry;->min(Landroidx/lifecycle/Lifecycle$State;Landroidx/lifecycle/Lifecycle$State;)Landroidx/lifecycle/Lifecycle$State;
-HSPLandroidx/lifecycle/LifecycleRegistry;->moveToState(Landroidx/lifecycle/Lifecycle$State;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->popParentState()V
-HSPLandroidx/lifecycle/LifecycleRegistry;->pushParentState(Landroidx/lifecycle/Lifecycle$State;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->removeObserver(Landroidx/lifecycle/LifecycleObserver;)V
-HSPLandroidx/lifecycle/LifecycleRegistry;->sync()V
-HSPLandroidx/lifecycle/Lifecycling;-><clinit>()V
-HSPLandroidx/lifecycle/Lifecycling;->lifecycleEventObserver(Ljava/lang/Object;)Landroidx/lifecycle/LifecycleEventObserver;
-HSPLandroidx/lifecycle/ProcessLifecycleInitializer;-><init>()V
-HSPLandroidx/lifecycle/ProcessLifecycleInitializer;->create(Landroid/content/Context;)Landroidx/lifecycle/LifecycleOwner;
-HSPLandroidx/lifecycle/ProcessLifecycleInitializer;->create(Landroid/content/Context;)Ljava/lang/Object;
-HSPLandroidx/lifecycle/ProcessLifecycleInitializer;->dependencies()Ljava/util/List;
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$1;-><init>(Landroidx/lifecycle/ProcessLifecycleOwner;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$1;->run()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$2;-><init>(Landroidx/lifecycle/ProcessLifecycleOwner;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3$1;-><init>(Landroidx/lifecycle/ProcessLifecycleOwner$3;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3$1;->onActivityPostResumed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3$1;->onActivityPostStarted(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3;-><init>(Landroidx/lifecycle/ProcessLifecycleOwner;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3;->onActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3;->onActivityPaused(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3;->onActivityPreCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$3;->onActivityStopped(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner$Api29Impl;->registerActivityLifecycleCallbacks(Landroid/app/Activity;Landroid/app/Application$ActivityLifecycleCallbacks;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;-><clinit>()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;-><init>()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->activityPaused()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->activityResumed()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->activityStarted()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->activityStopped()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->attach(Landroid/content/Context;)V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->dispatchPauseIfNeeded()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->dispatchStopIfNeeded()V
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->get()Landroidx/lifecycle/LifecycleOwner;
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->getLifecycle()Landroidx/lifecycle/Lifecycle;
-HSPLandroidx/lifecycle/ProcessLifecycleOwner;->init(Landroid/content/Context;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;-><init>()V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityDestroyed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPaused(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPostCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPostResumed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPostStarted(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPreDestroyed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPrePaused(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityPreStopped(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityResumed(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityStarted(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->onActivityStopped(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment$LifecycleCallbacks;->registerIn(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment;-><init>()V
-HSPLandroidx/lifecycle/ReportFragment;->dispatch(Landroid/app/Activity;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/lifecycle/ReportFragment;->dispatch(Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/lifecycle/ReportFragment;->dispatchCreate(Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;)V
-HSPLandroidx/lifecycle/ReportFragment;->dispatchResume(Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;)V
-HSPLandroidx/lifecycle/ReportFragment;->dispatchStart(Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;)V
-HSPLandroidx/lifecycle/ReportFragment;->injectIfNeededIn(Landroid/app/Activity;)V
-HSPLandroidx/lifecycle/ReportFragment;->onActivityCreated(Landroid/os/Bundle;)V
-HSPLandroidx/lifecycle/ReportFragment;->onDestroy()V
-HSPLandroidx/lifecycle/ReportFragment;->onPause()V
-HSPLandroidx/lifecycle/ReportFragment;->onResume()V
-HSPLandroidx/lifecycle/ReportFragment;->onStart()V
-HSPLandroidx/lifecycle/ReportFragment;->onStop()V
-HSPLandroidx/lifecycle/SavedStateHandleAttacher;-><init>(Landroidx/lifecycle/SavedStateHandlesProvider;)V
-HSPLandroidx/lifecycle/SavedStateHandleAttacher;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/lifecycle/SavedStateHandleSupport$DEFAULT_ARGS_KEY$1;-><init>()V
-HSPLandroidx/lifecycle/SavedStateHandleSupport$SAVED_STATE_REGISTRY_OWNER_KEY$1;-><init>()V
-HSPLandroidx/lifecycle/SavedStateHandleSupport$VIEW_MODEL_STORE_OWNER_KEY$1;-><init>()V
-HSPLandroidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1;-><clinit>()V
-HSPLandroidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1;-><init>()V
-HSPLandroidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1;->invoke(Landroidx/lifecycle/viewmodel/CreationExtras;)Landroidx/lifecycle/SavedStateHandlesVM;
-HSPLandroidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/lifecycle/SavedStateHandleSupport;-><clinit>()V
-HSPLandroidx/lifecycle/SavedStateHandleSupport;->enableSavedStateHandles(Landroidx/savedstate/SavedStateRegistryOwner;)V
-HSPLandroidx/lifecycle/SavedStateHandleSupport;->getSavedStateHandlesVM(Landroidx/lifecycle/ViewModelStoreOwner;)Landroidx/lifecycle/SavedStateHandlesVM;
-HSPLandroidx/lifecycle/SavedStateHandlesProvider$viewModel$2;-><init>(Landroidx/lifecycle/ViewModelStoreOwner;)V
-HSPLandroidx/lifecycle/SavedStateHandlesProvider$viewModel$2;->invoke()Landroidx/lifecycle/SavedStateHandlesVM;
-HSPLandroidx/lifecycle/SavedStateHandlesProvider$viewModel$2;->invoke()Ljava/lang/Object;
-HSPLandroidx/lifecycle/SavedStateHandlesProvider;-><init>(Landroidx/savedstate/SavedStateRegistry;Landroidx/lifecycle/ViewModelStoreOwner;)V
-HSPLandroidx/lifecycle/SavedStateHandlesProvider;->getViewModel()Landroidx/lifecycle/SavedStateHandlesVM;
-HSPLandroidx/lifecycle/SavedStateHandlesProvider;->performRestore()V
-HSPLandroidx/lifecycle/SavedStateHandlesVM;-><init>()V
-HSPLandroidx/lifecycle/ViewModel;-><init>()V
-HSPLandroidx/lifecycle/ViewModel;->clear()V
-HSPLandroidx/lifecycle/ViewModel;->onCleared()V
-HSPLandroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory$Companion$ApplicationKeyImpl;-><clinit>()V
-HSPLandroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory$Companion$ApplicationKeyImpl;-><init>()V
-HSPLandroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory$Companion;-><init>()V
-HSPLandroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory;-><clinit>()V
-HSPLandroidx/lifecycle/ViewModelProvider$Factory$Companion;-><clinit>()V
-HSPLandroidx/lifecycle/ViewModelProvider$Factory$Companion;-><init>()V
-HSPLandroidx/lifecycle/ViewModelProvider$Factory;-><clinit>()V
-HSPLandroidx/lifecycle/ViewModelProvider$NewInstanceFactory$Companion$ViewModelKeyImpl;-><clinit>()V
-HSPLandroidx/lifecycle/ViewModelProvider$NewInstanceFactory$Companion$ViewModelKeyImpl;-><init>()V
-HSPLandroidx/lifecycle/ViewModelProvider$NewInstanceFactory$Companion;-><init>()V
-HSPLandroidx/lifecycle/ViewModelProvider$NewInstanceFactory$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/lifecycle/ViewModelProvider$NewInstanceFactory;-><clinit>()V
-HSPLandroidx/lifecycle/ViewModelProvider;-><init>(Landroidx/lifecycle/ViewModelStore;Landroidx/lifecycle/ViewModelProvider$Factory;Landroidx/lifecycle/viewmodel/CreationExtras;)V
-HSPLandroidx/lifecycle/ViewModelProvider;-><init>(Landroidx/lifecycle/ViewModelStoreOwner;Landroidx/lifecycle/ViewModelProvider$Factory;)V
-HSPLandroidx/lifecycle/ViewModelProvider;->get(Ljava/lang/Class;)Landroidx/lifecycle/ViewModel;
-HSPLandroidx/lifecycle/ViewModelProvider;->get(Ljava/lang/String;Ljava/lang/Class;)Landroidx/lifecycle/ViewModel;
-HSPLandroidx/lifecycle/ViewModelProviderGetKt;->defaultCreationExtras(Landroidx/lifecycle/ViewModelStoreOwner;)Landroidx/lifecycle/viewmodel/CreationExtras;
-HSPLandroidx/lifecycle/ViewModelStore;-><init>()V
-HSPLandroidx/lifecycle/ViewModelStore;->clear()V
-HSPLandroidx/lifecycle/ViewModelStore;->get(Ljava/lang/String;)Landroidx/lifecycle/ViewModel;
-HSPLandroidx/lifecycle/ViewModelStore;->put(Ljava/lang/String;Landroidx/lifecycle/ViewModel;)V
-HSPLandroidx/lifecycle/ViewTreeLifecycleOwner;->get(Landroid/view/View;)Landroidx/lifecycle/LifecycleOwner;
-HSPLandroidx/lifecycle/ViewTreeLifecycleOwner;->set(Landroid/view/View;Landroidx/lifecycle/LifecycleOwner;)V
-HSPLandroidx/lifecycle/ViewTreeViewModelStoreOwner;->get(Landroid/view/View;)Landroidx/lifecycle/ViewModelStoreOwner;
-HSPLandroidx/lifecycle/ViewTreeViewModelStoreOwner;->set(Landroid/view/View;Landroidx/lifecycle/ViewModelStoreOwner;)V
-HSPLandroidx/lifecycle/viewmodel/CreationExtras$Empty;-><clinit>()V
-HSPLandroidx/lifecycle/viewmodel/CreationExtras$Empty;-><init>()V
-HSPLandroidx/lifecycle/viewmodel/CreationExtras;-><init>()V
-HSPLandroidx/lifecycle/viewmodel/CreationExtras;->getMap$lifecycle_viewmodel_release()Ljava/util/Map;
-HSPLandroidx/lifecycle/viewmodel/InitializerViewModelFactory;-><init>([Landroidx/lifecycle/viewmodel/ViewModelInitializer;)V
-HSPLandroidx/lifecycle/viewmodel/InitializerViewModelFactory;->create(Ljava/lang/Class;Landroidx/lifecycle/viewmodel/CreationExtras;)Landroidx/lifecycle/ViewModel;
-HSPLandroidx/lifecycle/viewmodel/InitializerViewModelFactoryBuilder;-><init>()V
-HSPLandroidx/lifecycle/viewmodel/InitializerViewModelFactoryBuilder;->addInitializer(Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/lifecycle/viewmodel/InitializerViewModelFactoryBuilder;->build()Landroidx/lifecycle/ViewModelProvider$Factory;
-HSPLandroidx/lifecycle/viewmodel/MutableCreationExtras;-><init>()V
-HSPLandroidx/lifecycle/viewmodel/MutableCreationExtras;-><init>(Landroidx/lifecycle/viewmodel/CreationExtras;)V
-HSPLandroidx/lifecycle/viewmodel/MutableCreationExtras;-><init>(Landroidx/lifecycle/viewmodel/CreationExtras;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/lifecycle/viewmodel/MutableCreationExtras;->set(Landroidx/lifecycle/viewmodel/CreationExtras$Key;Ljava/lang/Object;)V
-HSPLandroidx/lifecycle/viewmodel/ViewModelInitializer;-><init>(Ljava/lang/Class;Lkotlin/jvm/functions/Function1;)V
-HSPLandroidx/lifecycle/viewmodel/ViewModelInitializer;->getClazz$lifecycle_viewmodel_release()Ljava/lang/Class;
-HSPLandroidx/lifecycle/viewmodel/ViewModelInitializer;->getInitializer$lifecycle_viewmodel_release()Lkotlin/jvm/functions/Function1;
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner$LocalViewModelStoreOwner$1;-><clinit>()V
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner$LocalViewModelStoreOwner$1;-><init>()V
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner$LocalViewModelStoreOwner$1;->invoke()Landroidx/lifecycle/ViewModelStoreOwner;
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner$LocalViewModelStoreOwner$1;->invoke()Ljava/lang/Object;
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner;-><clinit>()V
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner;-><init>()V
-HSPLandroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner;->getCurrent(Landroidx/compose/runtime/Composer;I)Landroidx/lifecycle/ViewModelStoreOwner;
-HSPLandroidx/lifecycle/viewmodel/compose/ViewModelKt;->get(Landroidx/lifecycle/ViewModelStoreOwner;Ljava/lang/Class;Ljava/lang/String;Landroidx/lifecycle/ViewModelProvider$Factory;Landroidx/lifecycle/viewmodel/CreationExtras;)Landroidx/lifecycle/ViewModel;
-HSPLandroidx/lifecycle/viewmodel/compose/ViewModelKt;->viewModel(Ljava/lang/Class;Landroidx/lifecycle/ViewModelStoreOwner;Ljava/lang/String;Landroidx/lifecycle/ViewModelProvider$Factory;Landroidx/lifecycle/viewmodel/CreationExtras;Landroidx/compose/runtime/Composer;II)Landroidx/lifecycle/ViewModel;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;-><init>(Landroidx/profileinstaller/ProfileInstallerInitializer;Landroid/content/Context;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;->run()V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;-><init>(Landroid/content/Context;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda0;-><init>(Ljava/lang/Runnable;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda0;->doFrame(J)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;->$r8$lambda$DSwPKNQiVu4DdgIKQZrSpqkWM-A(Ljava/lang/Runnable;J)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;->lambda$postFrameCallback$0(Ljava/lang/Runnable;J)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;->postFrameCallback(Ljava/lang/Runnable;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Handler28Impl;->createAsync(Landroid/os/Looper;)Landroid/os/Handler;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer$Result;-><init>()V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->$r8$lambda$QGpANLTF0YGY0pXfe2eje4OKwkc(Landroidx/profileinstaller/ProfileInstallerInitializer;Landroid/content/Context;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;-><init>()V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->create(Landroid/content/Context;)Landroidx/profileinstaller/ProfileInstallerInitializer$Result;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->create(Landroid/content/Context;)Ljava/lang/Object;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->delayAfterFirstFrame(Landroid/content/Context;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->dependencies()Ljava/util/List;
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->installAfterDelay(Landroid/content/Context;)V
-HSPLandroidx/profileinstaller/ProfileInstallerInitializer;->lambda$delayAfterFirstFrame$0(Landroid/content/Context;)V
-HSPLandroidx/savedstate/Recreator$Companion;-><init>()V
-HSPLandroidx/savedstate/Recreator$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/savedstate/Recreator;-><clinit>()V
-HSPLandroidx/savedstate/Recreator;-><init>(Landroidx/savedstate/SavedStateRegistryOwner;)V
-HSPLandroidx/savedstate/Recreator;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/savedstate/SavedStateRegistry$$ExternalSyntheticLambda0;-><init>(Landroidx/savedstate/SavedStateRegistry;)V
-HSPLandroidx/savedstate/SavedStateRegistry$$ExternalSyntheticLambda0;->onStateChanged(Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/savedstate/SavedStateRegistry$Companion;-><init>()V
-HSPLandroidx/savedstate/SavedStateRegistry$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/savedstate/SavedStateRegistry;->$r8$lambda$AUDDdpkzZrJMhBj0r-_9pI-j6hA(Landroidx/savedstate/SavedStateRegistry;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/savedstate/SavedStateRegistry;-><clinit>()V
-HSPLandroidx/savedstate/SavedStateRegistry;-><init>()V
-HSPLandroidx/savedstate/SavedStateRegistry;->consumeRestoredStateForKey(Ljava/lang/String;)Landroid/os/Bundle;
-HSPLandroidx/savedstate/SavedStateRegistry;->getSavedStateProvider(Ljava/lang/String;)Landroidx/savedstate/SavedStateRegistry$SavedStateProvider;
-HSPLandroidx/savedstate/SavedStateRegistry;->performAttach$lambda$4(Landroidx/savedstate/SavedStateRegistry;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$Event;)V
-HSPLandroidx/savedstate/SavedStateRegistry;->performAttach$savedstate_release(Landroidx/lifecycle/Lifecycle;)V
-HSPLandroidx/savedstate/SavedStateRegistry;->performRestore$savedstate_release(Landroid/os/Bundle;)V
-HSPLandroidx/savedstate/SavedStateRegistry;->registerSavedStateProvider(Ljava/lang/String;Landroidx/savedstate/SavedStateRegistry$SavedStateProvider;)V
-HSPLandroidx/savedstate/SavedStateRegistry;->unregisterSavedStateProvider(Ljava/lang/String;)V
-HSPLandroidx/savedstate/SavedStateRegistryController$Companion;-><init>()V
-HSPLandroidx/savedstate/SavedStateRegistryController$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/savedstate/SavedStateRegistryController$Companion;->create(Landroidx/savedstate/SavedStateRegistryOwner;)Landroidx/savedstate/SavedStateRegistryController;
-HSPLandroidx/savedstate/SavedStateRegistryController;-><clinit>()V
-HSPLandroidx/savedstate/SavedStateRegistryController;-><init>(Landroidx/savedstate/SavedStateRegistryOwner;)V
-HSPLandroidx/savedstate/SavedStateRegistryController;-><init>(Landroidx/savedstate/SavedStateRegistryOwner;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLandroidx/savedstate/SavedStateRegistryController;->create(Landroidx/savedstate/SavedStateRegistryOwner;)Landroidx/savedstate/SavedStateRegistryController;
-HSPLandroidx/savedstate/SavedStateRegistryController;->getSavedStateRegistry()Landroidx/savedstate/SavedStateRegistry;
-HSPLandroidx/savedstate/SavedStateRegistryController;->performAttach()V
-HSPLandroidx/savedstate/SavedStateRegistryController;->performRestore(Landroid/os/Bundle;)V
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1;-><clinit>()V
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1;-><init>()V
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1;->invoke(Landroid/view/View;)Landroid/view/View;
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2;-><clinit>()V
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2;-><init>()V
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2;->invoke(Landroid/view/View;)Landroidx/savedstate/SavedStateRegistryOwner;
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner;->get(Landroid/view/View;)Landroidx/savedstate/SavedStateRegistryOwner;
-HSPLandroidx/savedstate/ViewTreeSavedStateRegistryOwner;->set(Landroid/view/View;Landroidx/savedstate/SavedStateRegistryOwner;)V
-HSPLandroidx/startup/AppInitializer;-><clinit>()V
-HSPLandroidx/startup/AppInitializer;-><init>(Landroid/content/Context;)V
-HSPLandroidx/startup/AppInitializer;->discoverAndInitialize(Landroid/os/Bundle;)V
-HSPLandroidx/startup/AppInitializer;->discoverAndInitialize(Ljava/lang/Class;)V
-HSPLandroidx/startup/AppInitializer;->doInitialize(Ljava/lang/Class;)Ljava/lang/Object;
-HSPLandroidx/startup/AppInitializer;->doInitialize(Ljava/lang/Class;Ljava/util/Set;)Ljava/lang/Object;
-HSPLandroidx/startup/AppInitializer;->getInstance(Landroid/content/Context;)Landroidx/startup/AppInitializer;
-HSPLandroidx/startup/AppInitializer;->initializeComponent(Ljava/lang/Class;)Ljava/lang/Object;
-HSPLandroidx/startup/AppInitializer;->isEagerlyInitialized(Ljava/lang/Class;)Z
-HSPLandroidx/startup/InitializationProvider;-><init>()V
-HSPLandroidx/startup/InitializationProvider;->onCreate()Z
-HSPLandroidx/tracing/Trace;->beginSection(Ljava/lang/String;)V
-HSPLandroidx/tracing/Trace;->endSection()V
-HSPLandroidx/tracing/Trace;->isEnabled()Z
-HSPLandroidx/tracing/TraceApi18Impl;->beginSection(Ljava/lang/String;)V
-HSPLandroidx/tracing/TraceApi18Impl;->endSection()V
-HSPLandroidx/tracing/TraceApi29Impl;->isEnabled()Z
-HSPLcom/android/compose/AndroidSystemUiController;-><init>(Landroid/view/View;Landroid/view/Window;)V
-HSPLcom/android/compose/AndroidSystemUiController;->setNavigationBarColor-Iv8Zu3U(JZZLkotlin/jvm/functions/Function1;)V
-HSPLcom/android/compose/AndroidSystemUiController;->setNavigationBarContrastEnforced(Z)V
-HSPLcom/android/compose/AndroidSystemUiController;->setNavigationBarDarkContentEnabled(Z)V
-HSPLcom/android/compose/AndroidSystemUiController;->setStatusBarColor-ek8zF_U(JZLkotlin/jvm/functions/Function1;)V
-HSPLcom/android/compose/AndroidSystemUiController;->setStatusBarDarkContentEnabled(Z)V
-HSPLcom/android/compose/SystemUiController;->setNavigationBarColor-Iv8Zu3U$default(Lcom/android/compose/SystemUiController;JZZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLcom/android/compose/SystemUiController;->setStatusBarColor-ek8zF_U$default(Lcom/android/compose/SystemUiController;JZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLcom/android/compose/SystemUiController;->setSystemBarsColor-Iv8Zu3U$default(Lcom/android/compose/SystemUiController;JZZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLcom/android/compose/SystemUiController;->setSystemBarsColor-Iv8Zu3U(JZZLkotlin/jvm/functions/Function1;)V
-HSPLcom/android/compose/SystemUiControllerKt$BlackScrimmed$1;-><clinit>()V
-HSPLcom/android/compose/SystemUiControllerKt$BlackScrimmed$1;-><init>()V
-HSPLcom/android/compose/SystemUiControllerKt;-><clinit>()V
-HSPLcom/android/compose/SystemUiControllerKt;->access$getBlackScrimmed$p()Lkotlin/jvm/functions/Function1;
-HSPLcom/android/compose/SystemUiControllerKt;->findWindow(Landroid/content/Context;)Landroid/view/Window;
-HSPLcom/android/compose/SystemUiControllerKt;->findWindow(Landroidx/compose/runtime/Composer;I)Landroid/view/Window;
-HSPLcom/android/compose/SystemUiControllerKt;->rememberSystemUiController(Landroid/view/Window;Landroidx/compose/runtime/Composer;II)Lcom/android/compose/SystemUiController;
-HSPLcom/android/credentialmanager/CredentialManagerRepo$Companion;-><init>()V
-HSPLcom/android/credentialmanager/CredentialManagerRepo$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/CredentialManagerRepo$Companion;->getCancelUiRequest(Landroid/content/Intent;)Landroid/credentials/ui/CancelUiRequest;
-HSPLcom/android/credentialmanager/CredentialManagerRepo$Companion;->sendCancellationCode(ILandroid/os/IBinder;Landroid/os/ResultReceiver;)V
-HSPLcom/android/credentialmanager/CredentialManagerRepo;-><clinit>()V
-HSPLcom/android/credentialmanager/CredentialManagerRepo;-><init>(Landroid/content/Context;Landroid/content/Intent;Lcom/android/credentialmanager/UserConfigRepo;Z)V
-HSPLcom/android/credentialmanager/CredentialManagerRepo;->getCredentialInitialUiState(Ljava/lang/String;)Lcom/android/credentialmanager/getflow/GetCredentialUiState;
-HSPLcom/android/credentialmanager/CredentialManagerRepo;->getRequestInfo()Landroid/credentials/ui/RequestInfo;
-HSPLcom/android/credentialmanager/CredentialManagerRepo;->initState()Lcom/android/credentialmanager/UiState;
-HSPLcom/android/credentialmanager/CredentialManagerRepo;->onCancel(I)V
-HSPLcom/android/credentialmanager/CredentialManagerRepo;->onUserCancel()V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$Companion;-><init>()V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$1;-><init>(Lcom/android/credentialmanager/CredentialSelectorActivity;Lcom/android/credentialmanager/CredentialSelectorViewModel;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$3;-><init>(Lcom/android/credentialmanager/CredentialSelectorActivity;Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$3;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$launcher$1;-><init>(Lcom/android/credentialmanager/CredentialSelectorViewModel;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$viewModel$1;-><init>(Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$viewModel$1;->invoke(Landroidx/lifecycle/viewmodel/CreationExtras;)Lcom/android/credentialmanager/CredentialSelectorViewModel;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$viewModel$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1$1;-><init>(Lcom/android/credentialmanager/CredentialSelectorActivity;Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1;-><init>(Lcom/android/credentialmanager/CredentialSelectorActivity;Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity$onCreate$backPressedCallback$1;-><init>(Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/CredentialSelectorActivity;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;-><clinit>()V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;-><init>()V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->CredentialManagerBottomSheet(Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->access$CredentialManagerBottomSheet(Lcom/android/credentialmanager/CredentialSelectorActivity;Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->access$handleDialogState(Lcom/android/credentialmanager/CredentialSelectorActivity;Lcom/android/credentialmanager/common/DialogState;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->handleDialogState(Lcom/android/credentialmanager/common/DialogState;)V
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->maybeCancelUIUponRequest$default(Lcom/android/credentialmanager/CredentialSelectorActivity;Landroid/content/Intent;Lcom/android/credentialmanager/CredentialSelectorViewModel;ILjava/lang/Object;)Lkotlin/Triple;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->maybeCancelUIUponRequest(Landroid/content/Intent;Lcom/android/credentialmanager/CredentialSelectorViewModel;)Lkotlin/Triple;
-HSPLcom/android/credentialmanager/CredentialSelectorActivity;->onCreate(Landroid/os/Bundle;)V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;-><clinit>()V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;-><init>(Lcom/android/credentialmanager/CredentialManagerRepo;Lcom/android/credentialmanager/UserConfigRepo;)V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->getFlowOnBackToHybridSnackBarScreen()V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->getFlowOnMoreOptionOnSnackBarSelected(Z)V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->getUiMetrics()Lcom/android/credentialmanager/logging/UIMetrics;
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->getUiState()Lcom/android/credentialmanager/UiState;
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->logUiEvent(Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->onInitialRenderComplete()V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->onUserCancel()V
-HSPLcom/android/credentialmanager/CredentialSelectorViewModel;->setUiState(Lcom/android/credentialmanager/UiState;)V
-HSPLcom/android/credentialmanager/DataConverterKt;->access$getServiceLabelAndIcon(Landroid/content/pm/PackageManager;Ljava/lang/String;)Lkotlin/Pair;
-HSPLcom/android/credentialmanager/DataConverterKt;->getAppLabel(Landroid/content/pm/PackageManager;Ljava/lang/String;)Ljava/lang/String;
-HSPLcom/android/credentialmanager/DataConverterKt;->getServiceLabelAndIcon(Landroid/content/pm/PackageManager;Ljava/lang/String;)Lkotlin/Pair;
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;-><init>()V
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;->getActionEntryList(Ljava/lang/String;Ljava/util/List;Landroid/graphics/drawable/Drawable;)Ljava/util/List;
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;->getAuthenticationEntryList(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/drawable/Drawable;Ljava/util/List;)Ljava/util/List;
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;->getCredentialOptionInfoList(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Landroid/content/Context;)Ljava/util/List;
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;->getRemoteEntry(Ljava/lang/String;Landroid/credentials/ui/Entry;)Lcom/android/credentialmanager/getflow/RemoteEntryInfo;
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;->toProviderList(Ljava/util/List;Landroid/content/Context;)Ljava/util/List;
-HSPLcom/android/credentialmanager/GetFlowUtils$Companion;->toRequestDisplayInfo(Landroid/credentials/ui/RequestInfo;Landroid/content/Context;Ljava/lang/String;)Lcom/android/credentialmanager/getflow/RequestDisplayInfo;
-HSPLcom/android/credentialmanager/GetFlowUtils;-><clinit>()V
-HSPLcom/android/credentialmanager/UiState;-><clinit>()V
-HSPLcom/android/credentialmanager/UiState;-><init>(Lcom/android/credentialmanager/createflow/CreateCredentialUiState;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Lcom/android/credentialmanager/common/BaseEntry;Lcom/android/credentialmanager/common/ProviderActivityState;Lcom/android/credentialmanager/common/DialogState;ZLcom/android/credentialmanager/CancelUiRequestState;Z)V
-HSPLcom/android/credentialmanager/UiState;-><init>(Lcom/android/credentialmanager/createflow/CreateCredentialUiState;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Lcom/android/credentialmanager/common/BaseEntry;Lcom/android/credentialmanager/common/ProviderActivityState;Lcom/android/credentialmanager/common/DialogState;ZLcom/android/credentialmanager/CancelUiRequestState;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/UiState;->copy$default(Lcom/android/credentialmanager/UiState;Lcom/android/credentialmanager/createflow/CreateCredentialUiState;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Lcom/android/credentialmanager/common/BaseEntry;Lcom/android/credentialmanager/common/ProviderActivityState;Lcom/android/credentialmanager/common/DialogState;ZLcom/android/credentialmanager/CancelUiRequestState;ZILjava/lang/Object;)Lcom/android/credentialmanager/UiState;
-HSPLcom/android/credentialmanager/UiState;->copy(Lcom/android/credentialmanager/createflow/CreateCredentialUiState;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Lcom/android/credentialmanager/common/BaseEntry;Lcom/android/credentialmanager/common/ProviderActivityState;Lcom/android/credentialmanager/common/DialogState;ZLcom/android/credentialmanager/CancelUiRequestState;Z)Lcom/android/credentialmanager/UiState;
-HSPLcom/android/credentialmanager/UiState;->equals(Ljava/lang/Object;)Z
-HSPLcom/android/credentialmanager/UiState;->getCancelRequestState()Lcom/android/credentialmanager/CancelUiRequestState;
-HSPLcom/android/credentialmanager/UiState;->getCreateCredentialUiState()Lcom/android/credentialmanager/createflow/CreateCredentialUiState;
-HSPLcom/android/credentialmanager/UiState;->getDialogState()Lcom/android/credentialmanager/common/DialogState;
-HSPLcom/android/credentialmanager/UiState;->getGetCredentialUiState()Lcom/android/credentialmanager/getflow/GetCredentialUiState;
-HSPLcom/android/credentialmanager/UiState;->getProviderActivityState()Lcom/android/credentialmanager/common/ProviderActivityState;
-HSPLcom/android/credentialmanager/UiState;->isAutoSelectFlow()Z
-HSPLcom/android/credentialmanager/UiState;->isInitialRender()Z
-HSPLcom/android/credentialmanager/UserConfigRepo$Companion;-><init>()V
-HSPLcom/android/credentialmanager/UserConfigRepo$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/UserConfigRepo;-><clinit>()V
-HSPLcom/android/credentialmanager/UserConfigRepo;-><init>(Landroid/content/Context;)V
-HSPLcom/android/credentialmanager/common/BaseEntry;-><clinit>()V
-HSPLcom/android/credentialmanager/common/BaseEntry;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/content/Intent;Z)V
-HSPLcom/android/credentialmanager/common/DialogState;->$values()[Lcom/android/credentialmanager/common/DialogState;
-HSPLcom/android/credentialmanager/common/DialogState;-><clinit>()V
-HSPLcom/android/credentialmanager/common/DialogState;-><init>(Ljava/lang/String;I)V
-HSPLcom/android/credentialmanager/common/ProviderActivityState;->$values()[Lcom/android/credentialmanager/common/ProviderActivityState;
-HSPLcom/android/credentialmanager/common/ProviderActivityState;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ProviderActivityState;-><init>(Ljava/lang/String;I)V
-HSPLcom/android/credentialmanager/common/ProviderActivityState;->values()[Lcom/android/credentialmanager/common/ProviderActivityState;
-HSPLcom/android/credentialmanager/common/StartBalIntentSenderForResultContract;-><clinit>()V
-HSPLcom/android/credentialmanager/common/StartBalIntentSenderForResultContract;-><init>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;-><init>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;->getElevation-D9Ej5fM()F
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;->getMaxCompactWidth-D9Ej5fM()F
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;->getMaxSheetWidth-D9Ej5fM()F
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;->getMinScrimHeight-D9Ej5fM()F
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;->getScrimColor(Landroidx/compose/runtime/Composer;I)J
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Lkotlinx/coroutines/CoroutineScope;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$1$1;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;F)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$1$1;->invoke-Bjo55l4(Landroidx/compose/ui/unit/Density;)J
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$2$1;-><init>(Landroidx/compose/runtime/MutableState;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$2$1;->invoke(Landroidx/compose/ui/layout/LayoutCoordinates;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$3$1;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Lkotlinx/coroutines/CoroutineScope;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$3;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Lkotlinx/coroutines/CoroutineScope;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$3;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$3;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$4;-><init>(Lkotlin/jvm/functions/Function3;I)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$4;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1;-><init>(Lkotlin/jvm/functions/Function2;ILcom/android/credentialmanager/common/material/ModalBottomSheetState;Lkotlinx/coroutines/CoroutineScope;Landroidx/compose/ui/graphics/Shape;JJFLkotlin/jvm/functions/Function3;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1;->invoke(Landroidx/compose/foundation/layout/BoxWithConstraintsScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$2;-><init>(Lkotlin/jvm/functions/Function3;Landroidx/compose/ui/Modifier;Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Landroidx/compose/ui/graphics/Shape;FJJLkotlin/jvm/functions/Function2;II)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$1$1;-><init>(JLandroidx/compose/runtime/State;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$1$1;->invoke(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$2;-><init>(JLkotlin/jvm/functions/Function0;ZI)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1;->invoke(Landroidx/compose/ui/input/pointer/PointerInputScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$2$1$1;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$2$1;-><init>(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$2$1;->invoke(Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$1;-><init>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$2;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;Landroidx/compose/animation/core/AnimationSpec;ZLkotlin/jvm/functions/Function1;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$2;->invoke()Lcom/android/credentialmanager/common/material/ModalBottomSheetState;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$2;->invoke()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->ModalBottomSheetLayout-XBZIF-8(Lkotlin/jvm/functions/Function3;Landroidx/compose/ui/Modifier;Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Landroidx/compose/ui/graphics/Shape;FJJLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->Scrim-3J-VO9M(JLkotlin/jvm/functions/Function0;ZLandroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->Scrim_3J_VO9M$lambda$0(Landroidx/compose/runtime/State;)F
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->access$Scrim_3J_VO9M$lambda$0(Landroidx/compose/runtime/State;)F
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->access$bottomSheetSwipeable(Landroidx/compose/ui/Modifier;Lcom/android/credentialmanager/common/material/ModalBottomSheetState;FLandroidx/compose/runtime/State;)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->bottomSheetSwipeable(Landroidx/compose/ui/Modifier;Lcom/android/credentialmanager/common/material/ModalBottomSheetState;FLandroidx/compose/runtime/State;)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetKt;->rememberModalBottomSheetState(Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;Landroidx/compose/animation/core/AnimationSpec;ZLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)Lcom/android/credentialmanager/common/material/ModalBottomSheetState;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$1;-><init>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$1;->invoke(Landroidx/compose/runtime/saveable/SaverScope;Lcom/android/credentialmanager/common/material/ModalBottomSheetState;)Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$2;-><init>(Landroidx/compose/animation/core/AnimationSpec;ZLkotlin/jvm/functions/Function1;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion;-><init>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion;->Saver(Landroidx/compose/animation/core/AnimationSpec;ZLkotlin/jvm/functions/Function1;)Landroidx/compose/runtime/saveable/Saver;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;Landroidx/compose/animation/core/AnimationSpec;ZLkotlin/jvm/functions/Function1;)V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState;->getHasHalfExpandedState$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Z
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState;->getNestedScrollConnection$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState;->isVisible()Z
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetState;->show(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetValue;->$values()[Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetValue;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/ModalBottomSheetValue;-><init>(Ljava/lang/String;I)V
-HSPLcom/android/credentialmanager/common/material/SwipeableDefaults;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableDefaults;-><init>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableDefaults;->getAnimationSpec()Landroidx/compose/animation/core/SpringSpec;
-HSPLcom/android/credentialmanager/common/material/SwipeableDefaults;->getDefaultDurationMillis()I
-HSPLcom/android/credentialmanager/common/material/SwipeableDefaults;->getVelocityThreshold-D9Ej5fM()F
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$PreUpPostDownNestedScrollConnection$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$1;-><init>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$3$1;-><init>(Ljava/util/Map;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/unit/Density;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$3;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;Ljava/util/Map;Lcom/android/credentialmanager/common/material/ResistanceConfig;Landroidx/compose/ui/unit/Density;Lkotlin/jvm/functions/Function2;FLkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$4$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3;-><init>(Ljava/util/Map;Lcom/android/credentialmanager/common/material/SwipeableState;Landroidx/compose/foundation/gestures/Orientation;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;ZLcom/android/credentialmanager/common/material/ResistanceConfig;Lkotlin/jvm/functions/Function2;F)V
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->access$computeTarget(FFLjava/util/Set;Lkotlin/jvm/functions/Function2;FF)F
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->access$getOffset(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Float;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->computeTarget(FFLjava/util/Set;Lkotlin/jvm/functions/Function2;FF)F
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->findBounds(FLjava/util/Set;)Ljava/util/List;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->getOffset(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Float;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->getPreUpPostDownNestedScrollConnection(Lcom/android/credentialmanager/common/material/SwipeableState;)Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->swipeable-pPrIpRY$default(Landroidx/compose/ui/Modifier;Lcom/android/credentialmanager/common/material/SwipeableState;Ljava/util/Map;Landroidx/compose/foundation/gestures/Orientation;ZZLandroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;Lcom/android/credentialmanager/common/material/ResistanceConfig;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/material/SwipeableKt;->swipeable-pPrIpRY(Landroidx/compose/ui/Modifier;Lcom/android/credentialmanager/common/material/SwipeableState;Ljava/util/Map;Landroidx/compose/foundation/gestures/Orientation;ZZLandroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;Lcom/android/credentialmanager/common/material/ResistanceConfig;F)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$Companion;-><init>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2$1;-><init>(Landroidx/compose/foundation/gestures/DragScope;Lkotlin/jvm/internal/Ref$FloatRef;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2$1;->invoke(Landroidx/compose/animation/core/Animatable;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;FLandroidx/compose/animation/core/AnimationSpec;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2;->invoke(Landroidx/compose/foundation/gestures/DragScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateTo$2$emit$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState$animateTo$2;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateTo$2$emit$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateTo$2;-><init>(Ljava/lang/Object;Lcom/android/credentialmanager/common/material/SwipeableState;Landroidx/compose/animation/core/AnimationSpec;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateTo$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$animateTo$2;->emit(Ljava/util/Map;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$draggableState$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$draggableState$1;->invoke(F)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$draggableState$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$latestNonEmptyAnchorsFlow$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$latestNonEmptyAnchorsFlow$1;->invoke()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$latestNonEmptyAnchorsFlow$1;->invoke()Ljava/util/Map;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$processNewAnchors$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$snapInternalToOffset$2;-><init>(FLcom/android/credentialmanager/common/material/SwipeableState;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$snapInternalToOffset$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$snapInternalToOffset$2;->invoke(Landroidx/compose/foundation/gestures/DragScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$snapInternalToOffset$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$snapInternalToOffset$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2$1;-><init>(Lcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2;-><init>(Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1;-><init>(Lkotlinx/coroutines/flow/Flow;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState$thresholds$2;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableState$thresholds$2;-><init>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;-><clinit>()V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;-><init>(Ljava/lang/Object;Landroidx/compose/animation/core/AnimationSpec;Lkotlin/jvm/functions/Function1;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$animateInternalToOffset(Lcom/android/credentialmanager/common/material/SwipeableState;FLandroidx/compose/animation/core/AnimationSpec;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$getAbsoluteOffset$p(Lcom/android/credentialmanager/common/material/SwipeableState;)Landroidx/compose/runtime/MutableState;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$getAnimationTarget$p(Lcom/android/credentialmanager/common/material/SwipeableState;)Landroidx/compose/runtime/MutableState;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$getOffsetState$p(Lcom/android/credentialmanager/common/material/SwipeableState;)Landroidx/compose/runtime/MutableState;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$getOverflowState$p(Lcom/android/credentialmanager/common/material/SwipeableState;)Landroidx/compose/runtime/MutableState;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$setAnimationRunning(Lcom/android/credentialmanager/common/material/SwipeableState;Z)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->access$setCurrentValue(Lcom/android/credentialmanager/common/material/SwipeableState;Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->animateInternalToOffset(FLandroidx/compose/animation/core/AnimationSpec;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->animateTo$default(Lcom/android/credentialmanager/common/material/SwipeableState;Ljava/lang/Object;Landroidx/compose/animation/core/AnimationSpec;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->animateTo(Ljava/lang/Object;Landroidx/compose/animation/core/AnimationSpec;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->ensureInit$frameworks__base__packages__CredentialManager__android_common__CredentialManager(Ljava/util/Map;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getAnchors$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Ljava/util/Map;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getCurrentValue()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getDraggableState$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Landroidx/compose/foundation/gestures/DraggableState;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getMaxBound$frameworks__base__packages__CredentialManager__android_common__CredentialManager()F
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getMinBound$frameworks__base__packages__CredentialManager__android_common__CredentialManager()F
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getOffset()Landroidx/compose/runtime/State;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getResistance$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lcom/android/credentialmanager/common/material/ResistanceConfig;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getTargetValue()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->getThresholds$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lkotlin/jvm/functions/Function2;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->isAnimationRunning()Z
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->processNewAnchors$frameworks__base__packages__CredentialManager__android_common__CredentialManager(Ljava/util/Map;Ljava/util/Map;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->setAnchors$frameworks__base__packages__CredentialManager__android_common__CredentialManager(Ljava/util/Map;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->setAnimationRunning(Z)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->setCurrentValue(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->setResistance$frameworks__base__packages__CredentialManager__android_common__CredentialManager(Lcom/android/credentialmanager/common/material/ResistanceConfig;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->setThresholds$frameworks__base__packages__CredentialManager__android_common__CredentialManager(Lkotlin/jvm/functions/Function2;)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->setVelocityThreshold$frameworks__base__packages__CredentialManager__android_common__CredentialManager(F)V
-HSPLcom/android/credentialmanager/common/material/SwipeableState;->snapInternalToOffset(FLkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1$1;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;ZLkotlin/jvm/functions/Function0;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$2;-><init>(Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function0;ZI)V
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$2;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/BottomSheetKt;->ModalBottomSheet(Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function0;ZLandroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/CardsKt$CredentialContainerCard$1;-><init>(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function3;II)V
-HSPLcom/android/credentialmanager/common/ui/CardsKt$SheetContainerCard$1;-><init>(Lkotlin/jvm/functions/Function2;ILandroidx/compose/foundation/layout/Arrangement$Vertical;Lkotlin/jvm/functions/Function1;)V
-HSPLcom/android/credentialmanager/common/ui/CardsKt$SheetContainerCard$1;->invoke(Landroidx/compose/foundation/layout/ColumnScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/CardsKt$SheetContainerCard$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/CardsKt$SheetContainerCard$2;-><init>(Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/Arrangement$Vertical;Lkotlin/jvm/functions/Function1;II)V
-HSPLcom/android/credentialmanager/common/ui/CardsKt;->CredentialContainerCard(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/CardsKt;->SheetContainerCard(Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/Arrangement$Vertical;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt$lambda-1$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt$lambda-1$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt$lambda-1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt$lambda-1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt;->getLambda-1$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lkotlin/jvm/functions/Function2;
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt$lambda-1$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt$lambda-1$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt$lambda-1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt$lambda-1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt;->getLambda-1$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lkotlin/jvm/functions/Function2;
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt$lambda-1$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt$lambda-1$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt$lambda-1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt$lambda-1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt;->getLambda-1$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lkotlin/jvm/functions/Function2;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$1;-><init>(Ljava/lang/String;ILjava/lang/String;)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$2;-><init>(Landroidx/compose/ui/graphics/ImageBitmap;)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$2;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$3;-><init>(Lkotlin/jvm/functions/Function0;Ljava/lang/String;Ljava/lang/String;Landroidx/compose/ui/graphics/ImageBitmap;II)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$1;->invoke(Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$4;-><init>(Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/vector/ImageVector;Landroidx/compose/ui/Modifier;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$4;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$6;-><init>(ZLjava/lang/String;ZLkotlin/jvm/functions/Function1;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$6;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$6;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$Entry$7;-><init>(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroidx/compose/ui/graphics/ImageBitmap;ZLandroidx/compose/ui/graphics/vector/ImageVector;Landroidx/compose/ui/graphics/painter/Painter;Ljava/lang/String;ZZLkotlin/jvm/functions/Function1;III)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$1;-><init>(Ljava/lang/String;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$2;-><init>(Lkotlin/jvm/functions/Function0;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$2;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$3;-><init>(Ljava/lang/String;Lkotlin/jvm/functions/Function0;FI)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1$WhenMappings;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1;->invoke(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/EntryKt;->ActionEntry(Lkotlin/jvm/functions/Function0;Ljava/lang/String;Ljava/lang/String;Landroidx/compose/ui/graphics/ImageBitmap;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt;->Entry(Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroidx/compose/ui/graphics/ImageBitmap;ZLandroidx/compose/ui/graphics/vector/ImageVector;Landroidx/compose/ui/graphics/painter/Painter;Ljava/lang/String;ZZLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;III)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt;->MoreOptionTopAppBar-TDGSqEk(Ljava/lang/String;Lkotlin/jvm/functions/Function0;FLandroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/EntryKt;->access$autoMirrored(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/ui/EntryKt;->autoMirrored(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
-HSPLcom/android/credentialmanager/common/ui/SectionHeaderKt;->CredentialListSectionHeader(Ljava/lang/String;ZLandroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/SectionHeaderKt;->InternalSectionHeader-3IgeMak(Ljava/lang/String;JZLandroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1$2$1;-><init>(Ljava/lang/String;ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;)V
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1$2$1;->invoke(Landroidx/compose/foundation/layout/ColumnScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1;-><init>(Lkotlin/jvm/functions/Function0;ILjava/lang/String;Lkotlin/jvm/functions/Function2;)V
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1;->invoke(Landroidx/compose/foundation/layout/BoxWithConstraintsScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$2;-><init>(ZLandroidx/compose/ui/platform/AccessibilityManager;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/SnackBarKt;->Snackbar(Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;ZLandroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/SystemUiControllerUtilsKt$setBottomSheetSystemBarsColor$1;-><init>(Lcom/android/compose/SystemUiController;I)V
-HSPLcom/android/credentialmanager/common/ui/SystemUiControllerUtilsKt;->setBottomSheetSystemBarsColor(Lcom/android/compose/SystemUiController;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/SystemUiControllerUtilsKt;->setTransparentSystemBarsColor(Lcom/android/compose/SystemUiController;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$BodySmallText$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$BodySmallText$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$BodySmallText$1;->invoke(Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$BodySmallText$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/TextsKt$SmallTitleText$1;-><clinit>()V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$SmallTitleText$1;-><init>()V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$SmallTitleText$1;->invoke(Landroidx/compose/ui/text/TextLayoutResult;)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$SmallTitleText$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/common/ui/TextsKt$SnackbarActionText$1;-><init>(Ljava/lang/String;Landroidx/compose/ui/Modifier;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt$SnackbarContentText$1;-><init>(Ljava/lang/String;Landroidx/compose/ui/Modifier;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt;->BodySmallText(Ljava/lang/String;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt;->LargeTitleText(Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt;->SectionHeaderText-FNF3uiM(Ljava/lang/String;Landroidx/compose/ui/Modifier;JLandroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt;->SmallTitleText(Ljava/lang/String;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt;->SnackbarActionText(Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/common/ui/TextsKt;->SnackbarContentText(Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/getflow/ActionEntryInfo;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ActionEntryInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/content/Intent;Ljava/lang/String;Landroid/graphics/drawable/Drawable;Ljava/lang/String;)V
-HSPLcom/android/credentialmanager/getflow/ActionEntryInfo;->getIcon()Landroid/graphics/drawable/Drawable;
-HSPLcom/android/credentialmanager/getflow/ActionEntryInfo;->getSubTitle()Ljava/lang/String;
-HSPLcom/android/credentialmanager/getflow/ActionEntryInfo;->getTitle()Ljava/lang/String;
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-1$1;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-1$1;-><init>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-2$1;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-2$1;-><init>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-3$1;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-3$1;-><init>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-3$1;->invoke(Landroidx/compose/foundation/layout/RowScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-3$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt;-><init>()V
-HSPLcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt;->getLambda-3$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lkotlin/jvm/functions/Function3;
-HSPLcom/android/credentialmanager/getflow/CredentialEntryInfoComparatorByTypeThenTimestamp;-><init>()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionChips$2;-><init>(Ljava/util/List;Lkotlin/jvm/functions/Function1;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionChips$2;->invoke(Landroidx/compose/foundation/layout/ColumnScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionChips$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionChips$3;-><init>(Ljava/util/List;Lkotlin/jvm/functions/Function1;ZI)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionEntryRow$1;-><init>(Lkotlin/jvm/functions/Function1;Lcom/android/credentialmanager/getflow/ActionEntryInfo;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$1;-><init>(Lkotlin/jvm/functions/Function0;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$3;-><init>(Lcom/android/credentialmanager/getflow/RemoteEntryInfo;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/Ref$BooleanRef;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$3;->invoke(Landroidx/compose/foundation/lazy/LazyItemScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$4;-><init>(Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/Ref$BooleanRef;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$4;->invoke(Landroidx/compose/foundation/lazy/LazyItemScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$4;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$1;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$1;-><init>()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$3;-><init>(Lkotlin/jvm/functions/Function1;Ljava/util/List;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$4;-><init>(Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/Ref$BooleanRef;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2;-><init>(Ljava/util/List;Ljava/util/List;Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;Lkotlin/jvm/functions/Function1;ILjava/util/List;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2;->invoke(Landroidx/compose/foundation/lazy/LazyListScope;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$10;-><init>(Lcom/android/credentialmanager/CredentialSelectorViewModel;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Landroidx/activity/compose/ManagedActivityResultLauncher;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$1;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$1;->invoke(Z)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$2;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$2;->invoke()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$2;->invoke()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$3;-><init>(Lcom/android/credentialmanager/CredentialSelectorViewModel;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$3;->invoke(Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$7;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$8;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$8;->invoke()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$8;->invoke()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$5;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$6;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$6;->invoke()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$6;->invoke()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$8;-><init>(Ljava/lang/Object;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$9;-><init>(Lcom/android/credentialmanager/CredentialSelectorViewModel;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$9;->invoke(Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$9;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$WhenMappings;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9;-><init>(Lcom/android/credentialmanager/CredentialSelectorViewModel;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Landroidx/activity/compose/ManagedActivityResultLauncher;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9;->invoke(Landroidx/compose/foundation/layout/ColumnScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1$1$1;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1$1$1;->invoke()Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1$1$1;->invoke()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1;-><init>(Lkotlin/jvm/functions/Function1;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$2;-><init>(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$1$1$1$1;-><init>(Lkotlin/jvm/functions/Function1;Lcom/android/credentialmanager/getflow/RemoteEntryInfo;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$1;-><init>(Lkotlin/jvm/functions/Function1;Lcom/android/credentialmanager/getflow/RemoteEntryInfo;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$1;->invoke(Landroidx/compose/foundation/layout/ColumnScope;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$2;-><init>(Lcom/android/credentialmanager/getflow/RemoteEntryInfo;Lkotlin/jvm/functions/Function1;ZI)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt;->ActionChips(Ljava/util/List;Lkotlin/jvm/functions/Function1;ZLandroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt;->ActionEntryRow(Lcom/android/credentialmanager/getflow/ActionEntryInfo;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt;->AllSignInOptionCard(Ljava/util/List;Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt;->GetCredentialScreen(Lcom/android/credentialmanager/CredentialSelectorViewModel;Lcom/android/credentialmanager/getflow/GetCredentialUiState;Landroidx/activity/compose/ManagedActivityResultLauncher;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt;->RemoteCredentialSnackBarScreen(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialComponentsKt;->RemoteEntryCard(Lcom/android/credentialmanager/getflow/RemoteEntryInfo;Lkotlin/jvm/functions/Function1;ZLandroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;-><init>(Ljava/util/List;Lcom/android/credentialmanager/getflow/RequestDisplayInfo;Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;Lcom/android/credentialmanager/getflow/GetScreenState;Lcom/android/credentialmanager/common/BaseEntry;Z)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;-><init>(Ljava/util/List;Lcom/android/credentialmanager/getflow/RequestDisplayInfo;Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;Lcom/android/credentialmanager/getflow/GetScreenState;Lcom/android/credentialmanager/common/BaseEntry;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->copy$default(Lcom/android/credentialmanager/getflow/GetCredentialUiState;Ljava/util/List;Lcom/android/credentialmanager/getflow/RequestDisplayInfo;Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;Lcom/android/credentialmanager/getflow/GetScreenState;Lcom/android/credentialmanager/common/BaseEntry;ZILjava/lang/Object;)Lcom/android/credentialmanager/getflow/GetCredentialUiState;
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->copy(Ljava/util/List;Lcom/android/credentialmanager/getflow/RequestDisplayInfo;Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;Lcom/android/credentialmanager/getflow/GetScreenState;Lcom/android/credentialmanager/common/BaseEntry;Z)Lcom/android/credentialmanager/getflow/GetCredentialUiState;
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->equals(Ljava/lang/Object;)Z
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->getCurrentScreenState()Lcom/android/credentialmanager/getflow/GetScreenState;
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->getProviderDisplayInfo()Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->getProviderInfoList()Ljava/util/List;
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->getRequestDisplayInfo()Lcom/android/credentialmanager/getflow/RequestDisplayInfo;
-HSPLcom/android/credentialmanager/getflow/GetCredentialUiState;->isNoAccount()Z
-HSPLcom/android/credentialmanager/getflow/GetModelKt$toProviderDisplayInfo$$inlined$compareByDescending$1;-><init>()V
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->access$toActiveEntry(Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;)Lcom/android/credentialmanager/common/BaseEntry;
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->access$toGetScreenState(Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;)Lcom/android/credentialmanager/getflow/GetScreenState;
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->access$toProviderDisplayInfo(Ljava/util/List;)Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->findAutoSelectEntry(Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;)Lcom/android/credentialmanager/getflow/CredentialEntryInfo;
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->hasContentToDisplay(Lcom/android/credentialmanager/getflow/GetCredentialUiState;)Z
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->toActiveEntry(Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;)Lcom/android/credentialmanager/common/BaseEntry;
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->toGetScreenState(Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;)Lcom/android/credentialmanager/getflow/GetScreenState;
-HSPLcom/android/credentialmanager/getflow/GetModelKt;->toProviderDisplayInfo(Ljava/util/List;)Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;
-HSPLcom/android/credentialmanager/getflow/GetScreenState;->$values()[Lcom/android/credentialmanager/getflow/GetScreenState;
-HSPLcom/android/credentialmanager/getflow/GetScreenState;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/GetScreenState;-><init>(Ljava/lang/String;I)V
-HSPLcom/android/credentialmanager/getflow/ProviderDisplayInfo;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ProviderDisplayInfo;-><init>(Ljava/util/List;Ljava/util/List;Lcom/android/credentialmanager/getflow/RemoteEntryInfo;)V
-HSPLcom/android/credentialmanager/getflow/ProviderDisplayInfo;->equals(Ljava/lang/Object;)Z
-HSPLcom/android/credentialmanager/getflow/ProviderDisplayInfo;->getAuthenticationEntryList()Ljava/util/List;
-HSPLcom/android/credentialmanager/getflow/ProviderDisplayInfo;->getRemoteEntry()Lcom/android/credentialmanager/getflow/RemoteEntryInfo;
-HSPLcom/android/credentialmanager/getflow/ProviderDisplayInfo;->getSortedUserNameToCredentialEntryList()Ljava/util/List;
-HSPLcom/android/credentialmanager/getflow/ProviderInfo;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/ProviderInfo;-><init>(Ljava/lang/String;Landroid/graphics/drawable/Drawable;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Lcom/android/credentialmanager/getflow/RemoteEntryInfo;Ljava/util/List;)V
-HSPLcom/android/credentialmanager/getflow/ProviderInfo;->getActionEntryList()Ljava/util/List;
-HSPLcom/android/credentialmanager/getflow/ProviderInfo;->getAuthenticationEntryList()Ljava/util/List;
-HSPLcom/android/credentialmanager/getflow/ProviderInfo;->getCredentialEntryList()Ljava/util/List;
-HSPLcom/android/credentialmanager/getflow/ProviderInfo;->getRemoteEntry()Lcom/android/credentialmanager/getflow/RemoteEntryInfo;
-HSPLcom/android/credentialmanager/getflow/RemoteEntryInfo;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/RemoteEntryInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/content/Intent;)V
-HSPLcom/android/credentialmanager/getflow/RequestDisplayInfo;-><clinit>()V
-HSPLcom/android/credentialmanager/getflow/RequestDisplayInfo;-><init>(Ljava/lang/String;ZZLcom/android/credentialmanager/getflow/TopBrandingContent;)V
-HSPLcom/android/credentialmanager/getflow/RequestDisplayInfo;->equals(Ljava/lang/Object;)Z
-HSPLcom/android/credentialmanager/getflow/RequestDisplayInfo;->getPreferImmediatelyAvailableCredentials()Z
-HSPLcom/android/credentialmanager/logging/GetCredentialEvent;->$values()[Lcom/android/credentialmanager/logging/GetCredentialEvent;
-HSPLcom/android/credentialmanager/logging/GetCredentialEvent;-><clinit>()V
-HSPLcom/android/credentialmanager/logging/GetCredentialEvent;-><init>(Ljava/lang/String;II)V
-HSPLcom/android/credentialmanager/logging/GetCredentialEvent;->getId()I
-HSPLcom/android/credentialmanager/logging/LifecycleEvent;->$values()[Lcom/android/credentialmanager/logging/LifecycleEvent;
-HSPLcom/android/credentialmanager/logging/LifecycleEvent;-><clinit>()V
-HSPLcom/android/credentialmanager/logging/LifecycleEvent;-><init>(Ljava/lang/String;II)V
-HSPLcom/android/credentialmanager/logging/LifecycleEvent;->getId()I
-HSPLcom/android/credentialmanager/logging/UIMetrics$log$1;-><init>(Lcom/android/credentialmanager/logging/UIMetrics;Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Lcom/android/internal/logging/InstanceId;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/logging/UIMetrics$log$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/logging/UIMetrics$log$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/logging/UIMetrics$log$3;-><init>(Lcom/android/credentialmanager/logging/UIMetrics;Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Ljava/lang/String;Lcom/android/internal/logging/InstanceId;Lkotlin/coroutines/Continuation;)V
-HSPLcom/android/credentialmanager/logging/UIMetrics$log$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLcom/android/credentialmanager/logging/UIMetrics$log$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/logging/UIMetrics;-><clinit>()V
-HSPLcom/android/credentialmanager/logging/UIMetrics;-><init>()V
-HSPLcom/android/credentialmanager/logging/UIMetrics;->access$getMUiEventLogger$p(Lcom/android/credentialmanager/logging/UIMetrics;)Lcom/android/internal/logging/UiEventLogger;
-HSPLcom/android/credentialmanager/logging/UIMetrics;->log(Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/logging/UIMetrics;->log(Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Ljava/lang/String;Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/logging/UIMetrics;->logNormal(Lcom/android/internal/logging/UiEventLogger$UiEventEnum;Ljava/lang/String;)V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme$Companion;-><init>()V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme$Companion;->getColor-WaAFU9c(Landroid/content/Context;I)J
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme;-><init>(Landroid/content/Context;)V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme;->getColorOnSurface-0d7_KjU()J
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme;->getColorOnSurfaceVariant-0d7_KjU()J
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme;->getColorSurfaceBright-0d7_KjU()J
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorScheme;->getColorSurfaceContainerHigh-0d7_KjU()J
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorSchemeKt$LocalAndroidColorScheme$1;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorSchemeKt$LocalAndroidColorScheme$1;-><init>()V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorSchemeKt;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/AndroidColorSchemeKt;->getLocalAndroidColorScheme()Landroidx/compose/runtime/ProvidableCompositionLocal;
-HSPLcom/android/credentialmanager/ui/theme/EntryShape;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/EntryShape;-><init>()V
-HSPLcom/android/credentialmanager/ui/theme/EntryShape;->getFullSmallRoundedCorner()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLcom/android/credentialmanager/ui/theme/EntryShape;->getTopRoundedCorner()Landroidx/compose/foundation/shape/RoundedCornerShape;
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1$1;-><init>(Lkotlin/jvm/functions/Function2;I)V
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1;-><init>(Lcom/android/credentialmanager/ui/theme/AndroidColorScheme;Lkotlin/jvm/functions/Function2;I)V
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$2;-><init>(ZLkotlin/jvm/functions/Function2;II)V
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$2;->invoke(Landroidx/compose/runtime/Composer;I)V
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLcom/android/credentialmanager/ui/theme/PlatformThemeKt;->PlatformTheme(ZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
-HSPLcom/android/credentialmanager/ui/theme/ShapeKt;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/ShapeKt;->getShapes()Landroidx/compose/material3/Shapes;
-HSPLcom/android/credentialmanager/ui/theme/typography/PlatformTypographyKt;->platformTypography(Lcom/android/credentialmanager/ui/theme/typography/TypographyTokens;)Landroidx/compose/material3/Typography;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;-><init>(Lcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyLargeFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyLargeLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyLargeSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyLargeTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyLargeWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyMediumFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyMediumLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyMediumSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyMediumTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodyMediumWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodySmallFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodySmallLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodySmallSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodySmallTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getBodySmallWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayLargeFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayLargeLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayLargeSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayLargeTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayLargeWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayMediumFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayMediumLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayMediumSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayMediumTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplayMediumWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplaySmallFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplaySmallLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplaySmallSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplaySmallTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getDisplaySmallWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineLargeFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineLargeLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineLargeSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineLargeTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineLargeWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineMediumFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineMediumLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineMediumSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineMediumTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineMediumWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineSmallFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineSmallLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineSmallSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineSmallTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getHeadlineSmallWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelLargeFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelLargeLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelLargeSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelLargeTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelLargeWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelMediumFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelMediumLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelMediumSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelMediumTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelMediumWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelSmallFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelSmallLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelSmallSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelSmallTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getLabelSmallWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleLargeFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleLargeLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleLargeSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleLargeTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleLargeWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleMediumFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleMediumLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleMediumSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleMediumTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleMediumWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleSmallFont()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleSmallLineHeight-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleSmallSize-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleSmallTracking-XSAIIZE()J
-HSPLcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;->getTitleSmallWeight()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Companion;-><init>()V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Companion;->get(Landroid/content/Context;)Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Companion;->getTypefaceName(Landroid/content/Context;Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;)Ljava/lang/String;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;->$values()[Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;-><init>(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;->getConfigName()Ljava/lang/String;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames;-><init>(Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames;->equals(Ljava/lang/Object;)Z
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames;->getBrand()Ljava/lang/String;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceNames;->getPlain()Ljava/lang/String;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens$Companion;-><init>()V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens$Companion;->getWeightMedium()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens$Companion;->getWeightRegular()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;-><clinit>()V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;-><init>(Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;->access$getWeightMedium$cp()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;->access$getWeightRegular$cp()Landroidx/compose/ui/text/font/FontWeight;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;->getBrand()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;->getPlain()Landroidx/compose/ui/text/font/FontFamily;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;-><init>(Lcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;)V
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getBodyLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getBodyMedium()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getBodySmall()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getDisplayLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getDisplayMedium()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getDisplaySmall()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getHeadlineLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getHeadlineMedium()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getHeadlineSmall()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getLabelLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getLabelMedium()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getLabelSmall()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getTitleLarge()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getTitleMedium()Landroidx/compose/ui/text/TextStyle;
-HSPLcom/android/credentialmanager/ui/theme/typography/TypographyTokens;->getTitleSmall()Landroidx/compose/ui/text/TextStyle;
-HSPLkotlin/LazyKt;->lazy(Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;
-HSPLkotlin/LazyKt;->lazy(Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;
-HSPLkotlin/LazyKt__LazyJVMKt$WhenMappings;-><clinit>()V
-HSPLkotlin/LazyKt__LazyJVMKt;->lazy(Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;
-HSPLkotlin/LazyKt__LazyJVMKt;->lazy(Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;
-HSPLkotlin/LazyThreadSafetyMode;->$values()[Lkotlin/LazyThreadSafetyMode;
-HSPLkotlin/LazyThreadSafetyMode;-><clinit>()V
-HSPLkotlin/LazyThreadSafetyMode;-><init>(Ljava/lang/String;I)V
-HSPLkotlin/LazyThreadSafetyMode;->values()[Lkotlin/LazyThreadSafetyMode;
-HSPLkotlin/Pair;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLkotlin/Pair;->component1()Ljava/lang/Object;
-HSPLkotlin/Pair;->component2()Ljava/lang/Object;
-HSPLkotlin/Pair;->getFirst()Ljava/lang/Object;
-HSPLkotlin/Pair;->getSecond()Ljava/lang/Object;
-HSPLkotlin/Result$Companion;-><init>()V
-HSPLkotlin/Result$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/Result$Failure;-><init>(Ljava/lang/Throwable;)V
-HSPLkotlin/Result;-><clinit>()V
-HSPLkotlin/Result;->constructor-impl(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlin/Result;->exceptionOrNull-impl(Ljava/lang/Object;)Ljava/lang/Throwable;
-HSPLkotlin/Result;->isFailure-impl(Ljava/lang/Object;)Z
-HSPLkotlin/ResultKt;->createFailure(Ljava/lang/Throwable;)Ljava/lang/Object;
-HSPLkotlin/ResultKt;->throwOnFailure(Ljava/lang/Object;)V
-HSPLkotlin/SynchronizedLazyImpl;-><init>(Lkotlin/jvm/functions/Function0;Ljava/lang/Object;)V
-HSPLkotlin/SynchronizedLazyImpl;-><init>(Lkotlin/jvm/functions/Function0;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/SynchronizedLazyImpl;->getValue()Ljava/lang/Object;
-HSPLkotlin/Triple;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLkotlin/Triple;->component1()Ljava/lang/Object;
-HSPLkotlin/Triple;->component2()Ljava/lang/Object;
-HSPLkotlin/TuplesKt;->to(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
-HSPLkotlin/ULong$Companion;-><init>()V
-HSPLkotlin/ULong$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/ULong;-><clinit>()V
-HSPLkotlin/ULong;->constructor-impl(J)J
-HSPLkotlin/UNINITIALIZED_VALUE;-><clinit>()V
-HSPLkotlin/UNINITIALIZED_VALUE;-><init>()V
-HSPLkotlin/Unit;-><clinit>()V
-HSPLkotlin/Unit;-><init>()V
-HSPLkotlin/UnsafeLazyImpl;-><init>(Lkotlin/jvm/functions/Function0;)V
-HSPLkotlin/UnsafeLazyImpl;->getValue()Ljava/lang/Object;
-HSPLkotlin/UnsignedKt;->ulongToDouble(J)D
-HSPLkotlin/collections/AbstractCollection;-><init>()V
-HSPLkotlin/collections/AbstractCollection;->isEmpty()Z
-HSPLkotlin/collections/AbstractCollection;->size()I
-HSPLkotlin/collections/AbstractList$Companion;-><init>()V
-HSPLkotlin/collections/AbstractList$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/collections/AbstractList$Companion;->checkElementIndex$kotlin_stdlib(II)V
-HSPLkotlin/collections/AbstractList;-><clinit>()V
-HSPLkotlin/collections/AbstractList;-><init>()V
-HSPLkotlin/collections/AbstractMap$Companion;-><init>()V
-HSPLkotlin/collections/AbstractMap$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/collections/AbstractMap;-><clinit>()V
-HSPLkotlin/collections/AbstractMap;-><init>()V
-HSPLkotlin/collections/AbstractMap;->containsEntry$kotlin_stdlib(Ljava/util/Map$Entry;)Z
-HSPLkotlin/collections/AbstractMap;->entrySet()Ljava/util/Set;
-HSPLkotlin/collections/AbstractMap;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/collections/AbstractMap;->size()I
-HSPLkotlin/collections/AbstractMutableList;-><init>()V
-HSPLkotlin/collections/AbstractMutableList;->remove(I)Ljava/lang/Object;
-HSPLkotlin/collections/AbstractMutableList;->size()I
-HSPLkotlin/collections/AbstractMutableMap;-><init>()V
-HSPLkotlin/collections/AbstractMutableMap;->size()I
-HSPLkotlin/collections/AbstractSet$Companion;-><init>()V
-HSPLkotlin/collections/AbstractSet$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/collections/AbstractSet$Companion;->setEquals$kotlin_stdlib(Ljava/util/Set;Ljava/util/Set;)Z
-HSPLkotlin/collections/AbstractSet;-><clinit>()V
-HSPLkotlin/collections/AbstractSet;-><init>()V
-HSPLkotlin/collections/AbstractSet;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/collections/ArrayDeque$Companion;-><init>()V
-HSPLkotlin/collections/ArrayDeque$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/collections/ArrayDeque$Companion;->newCapacity$kotlin_stdlib(II)I
-HSPLkotlin/collections/ArrayDeque;-><clinit>()V
-HSPLkotlin/collections/ArrayDeque;-><init>()V
-HSPLkotlin/collections/ArrayDeque;->add(Ljava/lang/Object;)Z
-HSPLkotlin/collections/ArrayDeque;->addLast(Ljava/lang/Object;)V
-HSPLkotlin/collections/ArrayDeque;->copyElements(I)V
-HSPLkotlin/collections/ArrayDeque;->ensureCapacity(I)V
-HSPLkotlin/collections/ArrayDeque;->get(I)Ljava/lang/Object;
-HSPLkotlin/collections/ArrayDeque;->getSize()I
-HSPLkotlin/collections/ArrayDeque;->incremented(I)I
-HSPLkotlin/collections/ArrayDeque;->indexOf(Ljava/lang/Object;)I
-HSPLkotlin/collections/ArrayDeque;->isEmpty()Z
-HSPLkotlin/collections/ArrayDeque;->positiveMod(I)I
-HSPLkotlin/collections/ArrayDeque;->remove(Ljava/lang/Object;)Z
-HSPLkotlin/collections/ArrayDeque;->removeAt(I)Ljava/lang/Object;
-HSPLkotlin/collections/ArrayDeque;->removeFirst()Ljava/lang/Object;
-HSPLkotlin/collections/ArrayDeque;->removeFirstOrNull()Ljava/lang/Object;
-HSPLkotlin/collections/ArrayDeque;->removeLast()Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt;->asList([Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/ArraysKt;->copyInto$default([F[FIIIILjava/lang/Object;)[F
-HSPLkotlin/collections/ArraysKt;->copyInto$default([I[IIIIILjava/lang/Object;)[I
-HSPLkotlin/collections/ArraysKt;->copyInto$default([Ljava/lang/Object;[Ljava/lang/Object;IIIILjava/lang/Object;)[Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt;->copyInto([F[FIII)[F
-HSPLkotlin/collections/ArraysKt;->copyInto([I[IIII)[I
-HSPLkotlin/collections/ArraysKt;->copyInto([Ljava/lang/Object;[Ljava/lang/Object;III)[Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt;->copyOfRange([Ljava/lang/Object;II)[Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt;->fill$default([IIIIILjava/lang/Object;)V
-HSPLkotlin/collections/ArraysKt;->fill$default([Ljava/lang/Object;Ljava/lang/Object;IIILjava/lang/Object;)V
-HSPLkotlin/collections/ArraysKt;->fill([IIII)V
-HSPLkotlin/collections/ArraysKt;->fill([Ljava/lang/Object;Ljava/lang/Object;II)V
-HSPLkotlin/collections/ArraysKt;->getLastIndex([Ljava/lang/Object;)I
-HSPLkotlin/collections/ArraysKt;->sortWith([Ljava/lang/Object;Ljava/util/Comparator;II)V
-HSPLkotlin/collections/ArraysKt__ArraysJVMKt;->copyOfRangeToIndexCheck(II)V
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->asList([Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto$default([F[FIIIILjava/lang/Object;)[F
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto$default([I[IIIIILjava/lang/Object;)[I
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto$default([Ljava/lang/Object;[Ljava/lang/Object;IIIILjava/lang/Object;)[Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto([F[FIII)[F
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto([I[IIII)[I
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto([Ljava/lang/Object;[Ljava/lang/Object;III)[Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyOfRange([Ljava/lang/Object;II)[Ljava/lang/Object;
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill$default([IIIIILjava/lang/Object;)V
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill$default([Ljava/lang/Object;Ljava/lang/Object;IIILjava/lang/Object;)V
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill([IIII)V
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill([Ljava/lang/Object;Ljava/lang/Object;II)V
-HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->sortWith([Ljava/lang/Object;Ljava/util/Comparator;II)V
-HSPLkotlin/collections/ArraysKt___ArraysKt;->getLastIndex([Ljava/lang/Object;)I
-HSPLkotlin/collections/ArraysUtilJVM;->asList([Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->addAll(Ljava/util/Collection;Ljava/lang/Iterable;)Z
-HSPLkotlin/collections/CollectionsKt;->collectionSizeOrDefault(Ljava/lang/Iterable;I)I
-HSPLkotlin/collections/CollectionsKt;->distinct(Ljava/lang/Iterable;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->emptyList()Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->first(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->firstOrNull(Ljava/lang/Iterable;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->getLastIndex(Ljava/util/List;)I
-HSPLkotlin/collections/CollectionsKt;->getOrNull(Ljava/util/List;I)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->last(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->lastOrNull(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->listOf(Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->listOf([Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->listOfNotNull(Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->maxOrNull(Ljava/lang/Iterable;)Ljava/lang/Float;
-HSPLkotlin/collections/CollectionsKt;->minOrNull(Ljava/lang/Iterable;)Ljava/lang/Float;
-HSPLkotlin/collections/CollectionsKt;->optimizeReadOnlyList(Ljava/util/List;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->removeFirstOrNull(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->singleOrNull(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt;->sortWith(Ljava/util/List;Ljava/util/Comparator;)V
-HSPLkotlin/collections/CollectionsKt;->sortedWith(Ljava/lang/Iterable;Ljava/util/Comparator;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->toList(Ljava/lang/Iterable;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt;->toMutableList(Ljava/util/Collection;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt__CollectionsJVMKt;->listOf(Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt__CollectionsKt;->emptyList()Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt__CollectionsKt;->getLastIndex(Ljava/util/List;)I
-HSPLkotlin/collections/CollectionsKt__CollectionsKt;->listOf([Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt__CollectionsKt;->listOfNotNull(Ljava/lang/Object;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt__CollectionsKt;->optimizeReadOnlyList(Ljava/util/List;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt__IterablesKt;->collectionSizeOrDefault(Ljava/lang/Iterable;I)I
-HSPLkotlin/collections/CollectionsKt__MutableCollectionsJVMKt;->sortWith(Ljava/util/List;Ljava/util/Comparator;)V
-HSPLkotlin/collections/CollectionsKt__MutableCollectionsKt;->addAll(Ljava/util/Collection;Ljava/lang/Iterable;)Z
-HSPLkotlin/collections/CollectionsKt__MutableCollectionsKt;->removeFirstOrNull(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->distinct(Ljava/lang/Iterable;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->first(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->firstOrNull(Ljava/lang/Iterable;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->getOrNull(Ljava/util/List;I)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->last(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->lastOrNull(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->maxOrNull(Ljava/lang/Iterable;)Ljava/lang/Float;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->minOrNull(Ljava/lang/Iterable;)Ljava/lang/Float;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->singleOrNull(Ljava/util/List;)Ljava/lang/Object;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->sortedWith(Ljava/lang/Iterable;Ljava/util/Comparator;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toList(Ljava/lang/Iterable;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toMutableList(Ljava/util/Collection;)Ljava/util/List;
-HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toMutableSet(Ljava/lang/Iterable;)Ljava/util/Set;
-HSPLkotlin/collections/EmptyIterator;-><clinit>()V
-HSPLkotlin/collections/EmptyIterator;-><init>()V
-HSPLkotlin/collections/EmptyIterator;->hasNext()Z
-HSPLkotlin/collections/EmptyList;-><clinit>()V
-HSPLkotlin/collections/EmptyList;-><init>()V
-HSPLkotlin/collections/EmptyList;->contains(Ljava/lang/Object;)Z
-HSPLkotlin/collections/EmptyList;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/collections/EmptyList;->getSize()I
-HSPLkotlin/collections/EmptyList;->isEmpty()Z
-HSPLkotlin/collections/EmptyList;->size()I
-HSPLkotlin/collections/EmptyMap;-><clinit>()V
-HSPLkotlin/collections/EmptyMap;-><init>()V
-HSPLkotlin/collections/EmptyMap;->containsKey(Ljava/lang/Object;)Z
-HSPLkotlin/collections/EmptyMap;->entrySet()Ljava/util/Set;
-HSPLkotlin/collections/EmptyMap;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/collections/EmptyMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlin/collections/EmptyMap;->get(Ljava/lang/Object;)Ljava/lang/Void;
-HSPLkotlin/collections/EmptyMap;->getEntries()Ljava/util/Set;
-HSPLkotlin/collections/EmptyMap;->getKeys()Ljava/util/Set;
-HSPLkotlin/collections/EmptyMap;->getSize()I
-HSPLkotlin/collections/EmptyMap;->getValues()Ljava/util/Collection;
-HSPLkotlin/collections/EmptyMap;->isEmpty()Z
-HSPLkotlin/collections/EmptyMap;->keySet()Ljava/util/Set;
-HSPLkotlin/collections/EmptyMap;->size()I
-HSPLkotlin/collections/EmptyMap;->values()Ljava/util/Collection;
-HSPLkotlin/collections/EmptySet;-><clinit>()V
-HSPLkotlin/collections/EmptySet;-><init>()V
-HSPLkotlin/collections/EmptySet;->iterator()Ljava/util/Iterator;
-HSPLkotlin/collections/IntIterator;-><init>()V
-HSPLkotlin/collections/MapsKt;->emptyMap()Ljava/util/Map;
-HSPLkotlin/collections/MapsKt;->mapCapacity(I)I
-HSPLkotlin/collections/MapsKt;->mapOf([Lkotlin/Pair;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt;->toMap(Ljava/lang/Iterable;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt;->toMutableMap(Ljava/util/Map;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt__MapsJVMKt;->mapCapacity(I)I
-HSPLkotlin/collections/MapsKt__MapsKt;->emptyMap()Ljava/util/Map;
-HSPLkotlin/collections/MapsKt__MapsKt;->mapOf([Lkotlin/Pair;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt__MapsKt;->putAll(Ljava/util/Map;Ljava/lang/Iterable;)V
-HSPLkotlin/collections/MapsKt__MapsKt;->putAll(Ljava/util/Map;[Lkotlin/Pair;)V
-HSPLkotlin/collections/MapsKt__MapsKt;->toMap(Ljava/lang/Iterable;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt__MapsKt;->toMap(Ljava/lang/Iterable;Ljava/util/Map;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt__MapsKt;->toMap([Lkotlin/Pair;Ljava/util/Map;)Ljava/util/Map;
-HSPLkotlin/collections/MapsKt__MapsKt;->toMutableMap(Ljava/util/Map;)Ljava/util/Map;
-HSPLkotlin/comparisons/ComparisonsKt;->compareValues(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
-HSPLkotlin/comparisons/ComparisonsKt__ComparisonsKt;->compareValues(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
-HSPLkotlin/coroutines/AbstractCoroutineContextElement;-><init>(Lkotlin/coroutines/CoroutineContext$Key;)V
-HSPLkotlin/coroutines/AbstractCoroutineContextElement;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlin/coroutines/AbstractCoroutineContextElement;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlin/coroutines/AbstractCoroutineContextElement;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
-HSPLkotlin/coroutines/AbstractCoroutineContextElement;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/AbstractCoroutineContextElement;->plus(Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/AbstractCoroutineContextKey;-><init>(Lkotlin/coroutines/CoroutineContext$Key;Lkotlin/jvm/functions/Function1;)V
-HSPLkotlin/coroutines/CombinedContext;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext$Element;)V
-HSPLkotlin/coroutines/CombinedContext;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlin/coroutines/CombinedContext;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlin/coroutines/CombinedContext;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/CombinedContext;->plus(Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/ContinuationInterceptor$DefaultImpls;->get(Lkotlin/coroutines/ContinuationInterceptor;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlin/coroutines/ContinuationInterceptor$DefaultImpls;->minusKey(Lkotlin/coroutines/ContinuationInterceptor;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/ContinuationInterceptor$Key;-><clinit>()V
-HSPLkotlin/coroutines/ContinuationInterceptor$Key;-><init>()V
-HSPLkotlin/coroutines/ContinuationInterceptor;-><clinit>()V
-HSPLkotlin/coroutines/ContinuationKt;->createCoroutine(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/ContinuationKt;->startCoroutine(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/CoroutineContext$DefaultImpls;->plus(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/CoroutineContext$Element$DefaultImpls;->fold(Lkotlin/coroutines/CoroutineContext$Element;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlin/coroutines/CoroutineContext$Element$DefaultImpls;->get(Lkotlin/coroutines/CoroutineContext$Element;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlin/coroutines/CoroutineContext$Element$DefaultImpls;->minusKey(Lkotlin/coroutines/CoroutineContext$Element;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/CoroutineContext$Element$DefaultImpls;->plus(Lkotlin/coroutines/CoroutineContext$Element;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/CoroutineContext$plus$1;-><clinit>()V
-HSPLkotlin/coroutines/CoroutineContext$plus$1;-><init>()V
-HSPLkotlin/coroutines/CoroutineContext$plus$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlin/coroutines/CoroutineContext$plus$1;->invoke(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext$Element;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/EmptyCoroutineContext;-><clinit>()V
-HSPLkotlin/coroutines/EmptyCoroutineContext;-><init>()V
-HSPLkotlin/coroutines/EmptyCoroutineContext;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlin/coroutines/EmptyCoroutineContext;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlin/coroutines/EmptyCoroutineContext;->plus(Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/SafeContinuation$Companion;-><init>()V
-HSPLkotlin/coroutines/SafeContinuation$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/coroutines/SafeContinuation;-><clinit>()V
-HSPLkotlin/coroutines/SafeContinuation;-><init>(Lkotlin/coroutines/Continuation;Ljava/lang/Object;)V
-HSPLkotlin/coroutines/SafeContinuation;->resumeWith(Ljava/lang/Object;)V
-HSPLkotlin/coroutines/intrinsics/CoroutineSingletons;->$values()[Lkotlin/coroutines/intrinsics/CoroutineSingletons;
-HSPLkotlin/coroutines/intrinsics/CoroutineSingletons;-><clinit>()V
-HSPLkotlin/coroutines/intrinsics/CoroutineSingletons;-><init>(Ljava/lang/String;I)V
-HSPLkotlin/coroutines/intrinsics/IntrinsicsKt;->createCoroutineUnintercepted(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/intrinsics/IntrinsicsKt;->getCOROUTINE_SUSPENDED()Ljava/lang/Object;
-HSPLkotlin/coroutines/intrinsics/IntrinsicsKt;->intercepted(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/intrinsics/IntrinsicsKt__IntrinsicsJvmKt;->createCoroutineUnintercepted(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/intrinsics/IntrinsicsKt__IntrinsicsJvmKt;->intercepted(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/intrinsics/IntrinsicsKt__IntrinsicsKt;->getCOROUTINE_SUSPENDED()Ljava/lang/Object;
-HSPLkotlin/coroutines/jvm/internal/BaseContinuationImpl;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/BaseContinuationImpl;->releaseIntercepted()V
-HSPLkotlin/coroutines/jvm/internal/BaseContinuationImpl;->resumeWith(Ljava/lang/Object;)V
-HSPLkotlin/coroutines/jvm/internal/Boxing;->boxBoolean(Z)Ljava/lang/Boolean;
-HSPLkotlin/coroutines/jvm/internal/Boxing;->boxFloat(F)Ljava/lang/Float;
-HSPLkotlin/coroutines/jvm/internal/CompletedContinuation;-><clinit>()V
-HSPLkotlin/coroutines/jvm/internal/CompletedContinuation;-><init>()V
-HSPLkotlin/coroutines/jvm/internal/ContinuationImpl;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/ContinuationImpl;-><init>(Lkotlin/coroutines/Continuation;Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlin/coroutines/jvm/internal/ContinuationImpl;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/jvm/internal/ContinuationImpl;->intercepted()Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/jvm/internal/ContinuationImpl;->releaseIntercepted()V
-HSPLkotlin/coroutines/jvm/internal/DebugProbesKt;->probeCoroutineCreated(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlin/coroutines/jvm/internal/DebugProbesKt;->probeCoroutineResumed(Lkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/DebugProbesKt;->probeCoroutineSuspended(Lkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/RestrictedContinuationImpl;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/RestrictedContinuationImpl;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlin/coroutines/jvm/internal/RestrictedSuspendLambda;-><init>(ILkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/SuspendLambda;-><init>(ILkotlin/coroutines/Continuation;)V
-HSPLkotlin/coroutines/jvm/internal/SuspendLambda;->getArity()I
-HSPLkotlin/internal/ProgressionUtilKt;->differenceModulo(III)I
-HSPLkotlin/internal/ProgressionUtilKt;->getProgressionLastElement(III)I
-HSPLkotlin/internal/ProgressionUtilKt;->mod(II)I
-HSPLkotlin/jvm/JvmClassMappingKt;->getJavaClass(Lkotlin/reflect/KClass;)Ljava/lang/Class;
-HSPLkotlin/jvm/JvmClassMappingKt;->getJavaObjectType(Lkotlin/reflect/KClass;)Ljava/lang/Class;
-HSPLkotlin/jvm/internal/CallableReference$NoReceiver;-><clinit>()V
-HSPLkotlin/jvm/internal/CallableReference$NoReceiver;-><init>()V
-HSPLkotlin/jvm/internal/CallableReference$NoReceiver;->access$000()Lkotlin/jvm/internal/CallableReference$NoReceiver;
-HSPLkotlin/jvm/internal/CallableReference;-><clinit>()V
-HSPLkotlin/jvm/internal/CallableReference;-><init>(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V
-HSPLkotlin/jvm/internal/CallableReference;->getBoundReceiver()Ljava/lang/Object;
-HSPLkotlin/jvm/internal/CallableReference;->getName()Ljava/lang/String;
-HSPLkotlin/jvm/internal/CallableReference;->getOwner()Lkotlin/reflect/KDeclarationContainer;
-HSPLkotlin/jvm/internal/CallableReference;->getSignature()Ljava/lang/String;
-HSPLkotlin/jvm/internal/ClassReference$Companion;-><init>()V
-HSPLkotlin/jvm/internal/ClassReference$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/jvm/internal/ClassReference;-><clinit>()V
-HSPLkotlin/jvm/internal/ClassReference;-><init>(Ljava/lang/Class;)V
-HSPLkotlin/jvm/internal/ClassReference;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/jvm/internal/ClassReference;->getJClass()Ljava/lang/Class;
-HSPLkotlin/jvm/internal/FloatCompanionObject;-><clinit>()V
-HSPLkotlin/jvm/internal/FloatCompanionObject;-><init>()V
-HSPLkotlin/jvm/internal/FunctionReference;-><init>(ILjava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/FunctionReference;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/jvm/internal/FunctionReference;->getArity()I
-HSPLkotlin/jvm/internal/FunctionReferenceImpl;-><init>(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/FunctionReferenceImpl;-><init>(ILjava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/InlineMarker;->mark(I)V
-HSPLkotlin/jvm/internal/IntCompanionObject;-><clinit>()V
-HSPLkotlin/jvm/internal/IntCompanionObject;-><init>()V
-HSPLkotlin/jvm/internal/Intrinsics;->areEqual(Ljava/lang/Float;F)Z
-HSPLkotlin/jvm/internal/Intrinsics;->areEqual(Ljava/lang/Float;Ljava/lang/Float;)Z
-HSPLkotlin/jvm/internal/Intrinsics;->areEqual(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLkotlin/jvm/internal/Intrinsics;->checkNotNull(Ljava/lang/Object;)V
-HSPLkotlin/jvm/internal/Intrinsics;->checkNotNull(Ljava/lang/Object;Ljava/lang/String;)V
-HSPLkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V
-HSPLkotlin/jvm/internal/Intrinsics;->checkNotNullParameter(Ljava/lang/Object;Ljava/lang/String;)V
-HSPLkotlin/jvm/internal/Intrinsics;->compare(II)I
-HSPLkotlin/jvm/internal/Lambda;-><init>(I)V
-HSPLkotlin/jvm/internal/Lambda;->getArity()I
-HSPLkotlin/jvm/internal/MutablePropertyReference1;-><init>(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/MutablePropertyReference1Impl;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/MutablePropertyReference;-><init>(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/PropertyReference;-><init>(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
-HSPLkotlin/jvm/internal/Ref$BooleanRef;-><init>()V
-HSPLkotlin/jvm/internal/Ref$FloatRef;-><init>()V
-HSPLkotlin/jvm/internal/Ref$IntRef;-><init>()V
-HSPLkotlin/jvm/internal/Ref$LongRef;-><init>()V
-HSPLkotlin/jvm/internal/Ref$ObjectRef;-><init>()V
-HSPLkotlin/jvm/internal/Reflection;-><clinit>()V
-HSPLkotlin/jvm/internal/Reflection;->getOrCreateKotlinClass(Ljava/lang/Class;)Lkotlin/reflect/KClass;
-HSPLkotlin/jvm/internal/Reflection;->mutableProperty1(Lkotlin/jvm/internal/MutablePropertyReference1;)Lkotlin/reflect/KMutableProperty1;
-HSPLkotlin/jvm/internal/ReflectionFactory;-><init>()V
-HSPLkotlin/jvm/internal/ReflectionFactory;->getOrCreateKotlinClass(Ljava/lang/Class;)Lkotlin/reflect/KClass;
-HSPLkotlin/jvm/internal/ReflectionFactory;->mutableProperty1(Lkotlin/jvm/internal/MutablePropertyReference1;)Lkotlin/reflect/KMutableProperty1;
-HSPLkotlin/jvm/internal/SpreadBuilder;-><init>(I)V
-HSPLkotlin/jvm/internal/SpreadBuilder;->add(Ljava/lang/Object;)V
-HSPLkotlin/jvm/internal/SpreadBuilder;->addSpread(Ljava/lang/Object;)V
-HSPLkotlin/jvm/internal/SpreadBuilder;->size()I
-HSPLkotlin/jvm/internal/SpreadBuilder;->toArray([Ljava/lang/Object;)[Ljava/lang/Object;
-HSPLkotlin/jvm/internal/TypeIntrinsics;->asMutableCollection(Ljava/lang/Object;)Ljava/util/Collection;
-HSPLkotlin/jvm/internal/TypeIntrinsics;->beforeCheckcastToFunctionOfArity(Ljava/lang/Object;I)Ljava/lang/Object;
-HSPLkotlin/jvm/internal/TypeIntrinsics;->castToCollection(Ljava/lang/Object;)Ljava/util/Collection;
-HSPLkotlin/jvm/internal/TypeIntrinsics;->getFunctionArity(Ljava/lang/Object;)I
-HSPLkotlin/jvm/internal/TypeIntrinsics;->isFunctionOfArity(Ljava/lang/Object;I)Z
-HSPLkotlin/jvm/internal/TypeIntrinsics;->isMutableSet(Ljava/lang/Object;)Z
-HSPLkotlin/math/MathKt;->getSign(I)I
-HSPLkotlin/math/MathKt;->roundToInt(F)I
-HSPLkotlin/math/MathKt__MathJVMKt;->getSign(I)I
-HSPLkotlin/math/MathKt__MathJVMKt;->roundToInt(F)I
-HSPLkotlin/ranges/IntProgression$Companion;-><init>()V
-HSPLkotlin/ranges/IntProgression$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/ranges/IntProgression;-><clinit>()V
-HSPLkotlin/ranges/IntProgression;-><init>(III)V
-HSPLkotlin/ranges/IntProgression;->getFirst()I
-HSPLkotlin/ranges/IntProgression;->getLast()I
-HSPLkotlin/ranges/IntProgression;->iterator()Ljava/util/Iterator;
-HSPLkotlin/ranges/IntProgression;->iterator()Lkotlin/collections/IntIterator;
-HSPLkotlin/ranges/IntProgressionIterator;-><init>(III)V
-HSPLkotlin/ranges/IntProgressionIterator;->hasNext()Z
-HSPLkotlin/ranges/IntProgressionIterator;->nextInt()I
-HSPLkotlin/ranges/IntRange$Companion;-><init>()V
-HSPLkotlin/ranges/IntRange$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlin/ranges/IntRange;-><clinit>()V
-HSPLkotlin/ranges/IntRange;-><init>(II)V
-HSPLkotlin/ranges/IntRange;->contains(I)Z
-HSPLkotlin/ranges/IntRange;->equals(Ljava/lang/Object;)Z
-HSPLkotlin/ranges/IntRange;->isEmpty()Z
-HSPLkotlin/ranges/RangesKt;->coerceAtLeast(II)I
-HSPLkotlin/ranges/RangesKt;->coerceAtLeast(Ljava/lang/Comparable;Ljava/lang/Comparable;)Ljava/lang/Comparable;
-HSPLkotlin/ranges/RangesKt;->coerceAtMost(FF)F
-HSPLkotlin/ranges/RangesKt;->coerceAtMost(II)I
-HSPLkotlin/ranges/RangesKt;->coerceIn(DDD)D
-HSPLkotlin/ranges/RangesKt;->coerceIn(FFF)F
-HSPLkotlin/ranges/RangesKt;->coerceIn(III)I
-HSPLkotlin/ranges/RangesKt;->coerceIn(JJJ)J
-HSPLkotlin/ranges/RangesKt;->until(II)Lkotlin/ranges/IntRange;
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtLeast(II)I
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtLeast(Ljava/lang/Comparable;Ljava/lang/Comparable;)Ljava/lang/Comparable;
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtMost(FF)F
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtMost(II)I
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(DDD)D
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(FFF)F
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(III)I
-HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(JJJ)J
-HSPLkotlin/ranges/RangesKt___RangesKt;->until(II)Lkotlin/ranges/IntRange;
-HSPLkotlin/sequences/ConstrainedOnceSequence;-><init>(Lkotlin/sequences/Sequence;)V
-HSPLkotlin/sequences/ConstrainedOnceSequence;->iterator()Ljava/util/Iterator;
-HSPLkotlin/sequences/FilteringSequence$iterator$1;-><init>(Lkotlin/sequences/FilteringSequence;)V
-HSPLkotlin/sequences/FilteringSequence$iterator$1;->calcNext()V
-HSPLkotlin/sequences/FilteringSequence$iterator$1;->hasNext()Z
-HSPLkotlin/sequences/FilteringSequence$iterator$1;->next()Ljava/lang/Object;
-HSPLkotlin/sequences/FilteringSequence;-><init>(Lkotlin/sequences/Sequence;ZLkotlin/jvm/functions/Function1;)V
-HSPLkotlin/sequences/FilteringSequence;->access$getPredicate$p(Lkotlin/sequences/FilteringSequence;)Lkotlin/jvm/functions/Function1;
-HSPLkotlin/sequences/FilteringSequence;->access$getSendWhen$p(Lkotlin/sequences/FilteringSequence;)Z
-HSPLkotlin/sequences/FilteringSequence;->access$getSequence$p(Lkotlin/sequences/FilteringSequence;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/FilteringSequence;->iterator()Ljava/util/Iterator;
-HSPLkotlin/sequences/GeneratorSequence$iterator$1;-><init>(Lkotlin/sequences/GeneratorSequence;)V
-HSPLkotlin/sequences/GeneratorSequence$iterator$1;->calcNext()V
-HSPLkotlin/sequences/GeneratorSequence$iterator$1;->hasNext()Z
-HSPLkotlin/sequences/GeneratorSequence$iterator$1;->next()Ljava/lang/Object;
-HSPLkotlin/sequences/GeneratorSequence;-><init>(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)V
-HSPLkotlin/sequences/GeneratorSequence;->access$getGetInitialValue$p(Lkotlin/sequences/GeneratorSequence;)Lkotlin/jvm/functions/Function0;
-HSPLkotlin/sequences/GeneratorSequence;->access$getGetNextValue$p(Lkotlin/sequences/GeneratorSequence;)Lkotlin/jvm/functions/Function1;
-HSPLkotlin/sequences/GeneratorSequence;->iterator()Ljava/util/Iterator;
-HSPLkotlin/sequences/SequencesKt;->asSequence(Ljava/util/Iterator;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt;->firstOrNull(Lkotlin/sequences/Sequence;)Ljava/lang/Object;
-HSPLkotlin/sequences/SequencesKt;->generateSequence(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt;->mapNotNull(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt;->toList(Lkotlin/sequences/Sequence;)Ljava/util/List;
-HSPLkotlin/sequences/SequencesKt__SequencesKt$asSequence$$inlined$Sequence$1;-><init>(Ljava/util/Iterator;)V
-HSPLkotlin/sequences/SequencesKt__SequencesKt$asSequence$$inlined$Sequence$1;->iterator()Ljava/util/Iterator;
-HSPLkotlin/sequences/SequencesKt__SequencesKt$generateSequence$2;-><init>(Ljava/lang/Object;)V
-HSPLkotlin/sequences/SequencesKt__SequencesKt$generateSequence$2;->invoke()Ljava/lang/Object;
-HSPLkotlin/sequences/SequencesKt__SequencesKt;->asSequence(Ljava/util/Iterator;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt__SequencesKt;->constrainOnce(Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt__SequencesKt;->generateSequence(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt___SequencesKt$filterNotNull$1;-><clinit>()V
-HSPLkotlin/sequences/SequencesKt___SequencesKt$filterNotNull$1;-><init>()V
-HSPLkotlin/sequences/SequencesKt___SequencesKt$filterNotNull$1;->invoke(Ljava/lang/Object;)Ljava/lang/Boolean;
-HSPLkotlin/sequences/SequencesKt___SequencesKt$filterNotNull$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->filterNot(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->filterNotNull(Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->firstOrNull(Lkotlin/sequences/Sequence;)Ljava/lang/Object;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->mapNotNull(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->toCollection(Lkotlin/sequences/Sequence;Ljava/util/Collection;)Ljava/util/Collection;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->toList(Lkotlin/sequences/Sequence;)Ljava/util/List;
-HSPLkotlin/sequences/SequencesKt___SequencesKt;->toMutableList(Lkotlin/sequences/Sequence;)Ljava/util/List;
-HSPLkotlin/sequences/TransformingSequence$iterator$1;-><init>(Lkotlin/sequences/TransformingSequence;)V
-HSPLkotlin/sequences/TransformingSequence$iterator$1;->hasNext()Z
-HSPLkotlin/sequences/TransformingSequence$iterator$1;->next()Ljava/lang/Object;
-HSPLkotlin/sequences/TransformingSequence;-><init>(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)V
-HSPLkotlin/sequences/TransformingSequence;->access$getSequence$p(Lkotlin/sequences/TransformingSequence;)Lkotlin/sequences/Sequence;
-HSPLkotlin/sequences/TransformingSequence;->access$getTransformer$p(Lkotlin/sequences/TransformingSequence;)Lkotlin/jvm/functions/Function1;
-HSPLkotlin/sequences/TransformingSequence;->iterator()Ljava/util/Iterator;
-HSPLkotlin/text/CharsKt;->checkRadix(I)I
-HSPLkotlin/text/CharsKt__CharJVMKt;->checkRadix(I)I
-HSPLkotlin/text/CharsKt__CharJVMKt;->isWhitespace(C)Z
-HSPLkotlin/text/StringsKt;->isBlank(Ljava/lang/CharSequence;)Z
-HSPLkotlin/text/StringsKt;->substringAfterLast$default(Ljava/lang/String;CLjava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
-HSPLkotlin/text/StringsKt__StringsJVMKt;->isBlank(Ljava/lang/CharSequence;)Z
-HSPLkotlin/text/StringsKt__StringsKt;->getIndices(Ljava/lang/CharSequence;)Lkotlin/ranges/IntRange;
-HSPLkotlin/text/StringsKt__StringsKt;->getLastIndex(Ljava/lang/CharSequence;)I
-HSPLkotlin/text/StringsKt__StringsKt;->lastIndexOf$default(Ljava/lang/CharSequence;CIZILjava/lang/Object;)I
-HSPLkotlin/text/StringsKt__StringsKt;->lastIndexOf(Ljava/lang/CharSequence;CIZ)I
-HSPLkotlin/text/StringsKt__StringsKt;->substringAfterLast$default(Ljava/lang/String;CLjava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
-HSPLkotlin/text/StringsKt__StringsKt;->substringAfterLast(Ljava/lang/String;CLjava/lang/String;)Ljava/lang/String;
-HSPLkotlinx/atomicfu/AtomicArray;-><init>(I)V
-HSPLkotlinx/atomicfu/AtomicBoolean$Companion;-><init>()V
-HSPLkotlinx/atomicfu/AtomicBoolean$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/atomicfu/AtomicBoolean;-><clinit>()V
-HSPLkotlinx/atomicfu/AtomicBoolean;-><init>(ZLkotlinx/atomicfu/TraceBase;)V
-HSPLkotlinx/atomicfu/AtomicBoolean;->compareAndSet(ZZ)Z
-HSPLkotlinx/atomicfu/AtomicBoolean;->getValue()Z
-HSPLkotlinx/atomicfu/AtomicBoolean;->setValue(Z)V
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(I)Lkotlinx/atomicfu/AtomicInt;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(ILkotlinx/atomicfu/TraceBase;)Lkotlinx/atomicfu/AtomicInt;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(J)Lkotlinx/atomicfu/AtomicLong;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(JLkotlinx/atomicfu/TraceBase;)Lkotlinx/atomicfu/AtomicLong;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(Ljava/lang/Object;)Lkotlinx/atomicfu/AtomicRef;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(Ljava/lang/Object;Lkotlinx/atomicfu/TraceBase;)Lkotlinx/atomicfu/AtomicRef;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(Z)Lkotlinx/atomicfu/AtomicBoolean;
-HSPLkotlinx/atomicfu/AtomicFU;->atomic(ZLkotlinx/atomicfu/TraceBase;)Lkotlinx/atomicfu/AtomicBoolean;
-HSPLkotlinx/atomicfu/AtomicFU_commonKt;->atomicArrayOfNulls(I)Lkotlinx/atomicfu/AtomicArray;
-HSPLkotlinx/atomicfu/AtomicInt$Companion;-><init>()V
-HSPLkotlinx/atomicfu/AtomicInt$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/atomicfu/AtomicInt;-><clinit>()V
-HSPLkotlinx/atomicfu/AtomicInt;-><init>(ILkotlinx/atomicfu/TraceBase;)V
-HSPLkotlinx/atomicfu/AtomicInt;->compareAndSet(II)Z
-HSPLkotlinx/atomicfu/AtomicInt;->getValue()I
-HSPLkotlinx/atomicfu/AtomicInt;->setValue(I)V
-HSPLkotlinx/atomicfu/AtomicLong$Companion;-><init>()V
-HSPLkotlinx/atomicfu/AtomicLong$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/atomicfu/AtomicLong;-><clinit>()V
-HSPLkotlinx/atomicfu/AtomicLong;-><init>(JLkotlinx/atomicfu/TraceBase;)V
-HSPLkotlinx/atomicfu/AtomicRef$Companion;-><init>()V
-HSPLkotlinx/atomicfu/AtomicRef$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/atomicfu/AtomicRef;-><clinit>()V
-HSPLkotlinx/atomicfu/AtomicRef;-><init>(Ljava/lang/Object;Lkotlinx/atomicfu/TraceBase;)V
-HSPLkotlinx/atomicfu/AtomicRef;->compareAndSet(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLkotlinx/atomicfu/AtomicRef;->getAndSet(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/atomicfu/AtomicRef;->getValue()Ljava/lang/Object;
-HSPLkotlinx/atomicfu/AtomicRef;->lazySet(Ljava/lang/Object;)V
-HSPLkotlinx/atomicfu/AtomicRef;->setValue(Ljava/lang/Object;)V
-HSPLkotlinx/atomicfu/TraceBase$None;-><clinit>()V
-HSPLkotlinx/atomicfu/TraceBase$None;-><init>()V
-HSPLkotlinx/atomicfu/TraceBase;-><init>()V
-HSPLkotlinx/coroutines/AbstractCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;ZZ)V
-HSPLkotlinx/coroutines/AbstractCoroutine;->afterResume(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/AbstractCoroutine;->cancellationExceptionMessage()Ljava/lang/String;
-HSPLkotlinx/coroutines/AbstractCoroutine;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/AbstractCoroutine;->getCoroutineContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/AbstractCoroutine;->isActive()Z
-HSPLkotlinx/coroutines/AbstractCoroutine;->onCancelled(Ljava/lang/Throwable;Z)V
-HSPLkotlinx/coroutines/AbstractCoroutine;->onCompleted(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/AbstractCoroutine;->onCompletionInternal(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/AbstractCoroutine;->resumeWith(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/AbstractCoroutine;->start(Lkotlinx/coroutines/CoroutineStart;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
-HSPLkotlinx/coroutines/Active;-><clinit>()V
-HSPLkotlinx/coroutines/Active;-><init>()V
-HSPLkotlinx/coroutines/BeforeResumeCancelHandler;-><init>()V
-HSPLkotlinx/coroutines/BlockingEventLoop;-><init>(Ljava/lang/Thread;)V
-HSPLkotlinx/coroutines/BuildersKt;->launch$default(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/BuildersKt;->launch(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/BuildersKt;->withContext(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/BuildersKt__Builders_commonKt;->launch$default(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/BuildersKt__Builders_commonKt;->launch(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/BuildersKt__Builders_commonKt;->withContext(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancelHandler;-><init>()V
-HSPLkotlinx/coroutines/CancelHandlerBase;-><init>()V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;-><init>(Lkotlin/coroutines/Continuation;I)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->callCancelHandler(Lkotlinx/coroutines/CancelHandler;Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->cancel(Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->cancelCompletedResult$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->cancelLater(Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->completeResume(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->detachChild$external__kotlinx_coroutines__android_common__kotlinx_coroutines()V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->detachChildIfNonResuable()V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->dispatchResume(I)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getContinuationCancellationCause(Lkotlinx/coroutines/Job;)Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getDelegate$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getExceptionalResult$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;)Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getResult()Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getState$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->getSuccessfulResult$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->initCancellability()V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->installParentHandle()Lkotlinx/coroutines/DisposableHandle;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->invokeOnCancellation(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->isCompleted()Z
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->isReusable()Z
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->makeCancelHandler(Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/CancelHandler;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->parentCancelled$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->releaseClaimedReusableContinuation()V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->resetStateReusable()Z
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeImpl$default(Lkotlinx/coroutines/CancellableContinuationImpl;Ljava/lang/Object;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeImpl(Ljava/lang/Object;ILkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeWith(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumedState(Lkotlinx/coroutines/NotCompleted;Ljava/lang/Object;ILkotlin/jvm/functions/Function1;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->takeState$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->tryResume()Z
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->tryResume(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->tryResumeImpl(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/CancellableContinuationImpl;->trySuspend()Z
-HSPLkotlinx/coroutines/CancellableContinuationImplKt;-><clinit>()V
-HSPLkotlinx/coroutines/CancellableContinuationKt;->disposeOnCancellation(Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/DisposableHandle;)V
-HSPLkotlinx/coroutines/CancellableContinuationKt;->getOrCreateCancellableContinuation(Lkotlin/coroutines/Continuation;)Lkotlinx/coroutines/CancellableContinuationImpl;
-HSPLkotlinx/coroutines/CancellableContinuationKt;->removeOnCancellation(Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/CancelledContinuation;-><init>(Lkotlin/coroutines/Continuation;Ljava/lang/Throwable;Z)V
-HSPLkotlinx/coroutines/CancelledContinuation;->makeResumed()Z
-HSPLkotlinx/coroutines/ChildContinuation;-><init>(Lkotlinx/coroutines/CancellableContinuationImpl;)V
-HSPLkotlinx/coroutines/ChildContinuation;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/ChildHandleNode;-><init>(Lkotlinx/coroutines/ChildJob;)V
-HSPLkotlinx/coroutines/ChildHandleNode;->childCancelled(Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/ChildHandleNode;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/CompletedContinuation;-><init>(Ljava/lang/Object;Lkotlinx/coroutines/CancelHandler;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/CompletedContinuation;-><init>(Ljava/lang/Object;Lkotlinx/coroutines/CancelHandler;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/CompletedExceptionally;-><init>(Ljava/lang/Throwable;Z)V
-HSPLkotlinx/coroutines/CompletedExceptionally;-><init>(Ljava/lang/Throwable;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/CompletedExceptionally;->getHandled()Z
-HSPLkotlinx/coroutines/CompletedExceptionally;->makeHandled()Z
-HSPLkotlinx/coroutines/CompletionHandlerBase;-><init>()V
-HSPLkotlinx/coroutines/CompletionStateKt;->recoverResult(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CompletionStateKt;->toState$default(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CompletionStateKt;->toState(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CompletionStateKt;->toState(Ljava/lang/Object;Lkotlinx/coroutines/CancellableContinuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CoroutineContextKt$hasCopyableElements$1;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineContextKt$hasCopyableElements$1;-><init>()V
-HSPLkotlinx/coroutines/CoroutineContextKt$hasCopyableElements$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CoroutineContextKt$hasCopyableElements$1;->invoke(ZLkotlin/coroutines/CoroutineContext$Element;)Ljava/lang/Boolean;
-HSPLkotlinx/coroutines/CoroutineContextKt;->foldCopies(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext;Z)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/CoroutineContextKt;->hasCopyableElements(Lkotlin/coroutines/CoroutineContext;)Z
-HSPLkotlinx/coroutines/CoroutineContextKt;->newCoroutineContext(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/CoroutineContextKt;->newCoroutineContext(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/CoroutineDispatcher$Key$1;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineDispatcher$Key$1;-><init>()V
-HSPLkotlinx/coroutines/CoroutineDispatcher$Key;-><init>()V
-HSPLkotlinx/coroutines/CoroutineDispatcher$Key;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/CoroutineDispatcher;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineDispatcher;-><init>()V
-HSPLkotlinx/coroutines/CoroutineDispatcher;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlinx/coroutines/CoroutineDispatcher;->interceptContinuation(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/CoroutineDispatcher;->isDispatchNeeded(Lkotlin/coroutines/CoroutineContext;)Z
-HSPLkotlinx/coroutines/CoroutineDispatcher;->limitedParallelism(I)Lkotlinx/coroutines/CoroutineDispatcher;
-HSPLkotlinx/coroutines/CoroutineDispatcher;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/CoroutineDispatcher;->releaseInterceptedContinuation(Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/CoroutineExceptionHandler$Key;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineExceptionHandler$Key;-><init>()V
-HSPLkotlinx/coroutines/CoroutineExceptionHandler;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineScopeKt;->CoroutineScope(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/CoroutineScope;
-HSPLkotlinx/coroutines/CoroutineScopeKt;->MainScope()Lkotlinx/coroutines/CoroutineScope;
-HSPLkotlinx/coroutines/CoroutineScopeKt;->cancel$default(Lkotlinx/coroutines/CoroutineScope;Ljava/util/concurrent/CancellationException;ILjava/lang/Object;)V
-HSPLkotlinx/coroutines/CoroutineScopeKt;->cancel(Lkotlinx/coroutines/CoroutineScope;Ljava/util/concurrent/CancellationException;)V
-HSPLkotlinx/coroutines/CoroutineScopeKt;->coroutineScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/CoroutineScopeKt;->isActive(Lkotlinx/coroutines/CoroutineScope;)Z
-HSPLkotlinx/coroutines/CoroutineStart$WhenMappings;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineStart;->$values()[Lkotlinx/coroutines/CoroutineStart;
-HSPLkotlinx/coroutines/CoroutineStart;-><clinit>()V
-HSPLkotlinx/coroutines/CoroutineStart;-><init>(Ljava/lang/String;I)V
-HSPLkotlinx/coroutines/CoroutineStart;->invoke(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/CoroutineStart;->isLazy()Z
-HSPLkotlinx/coroutines/CoroutineStart;->values()[Lkotlinx/coroutines/CoroutineStart;
-HSPLkotlinx/coroutines/DebugStringsKt;->getClassSimpleName(Ljava/lang/Object;)Ljava/lang/String;
-HSPLkotlinx/coroutines/DefaultExecutor;-><clinit>()V
-HSPLkotlinx/coroutines/DefaultExecutor;-><init>()V
-HSPLkotlinx/coroutines/DefaultExecutorKt;-><clinit>()V
-HSPLkotlinx/coroutines/DefaultExecutorKt;->getDefaultDelay()Lkotlinx/coroutines/Delay;
-HSPLkotlinx/coroutines/DefaultExecutorKt;->initializeDefaultDelay()Lkotlinx/coroutines/Delay;
-HSPLkotlinx/coroutines/DelayKt;->delay(JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/DispatchedTask;-><init>(I)V
-HSPLkotlinx/coroutines/DispatchedTask;->getExceptionalResult$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;)Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/DispatchedTask;->getSuccessfulResult$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/DispatchedTask;->handleFatalException(Ljava/lang/Throwable;Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/DispatchedTask;->run()V
-HSPLkotlinx/coroutines/DispatchedTaskKt;->dispatch(Lkotlinx/coroutines/DispatchedTask;I)V
-HSPLkotlinx/coroutines/DispatchedTaskKt;->isCancellableMode(I)Z
-HSPLkotlinx/coroutines/DispatchedTaskKt;->isReusableMode(I)Z
-HSPLkotlinx/coroutines/DispatchedTaskKt;->resume(Lkotlinx/coroutines/DispatchedTask;Lkotlin/coroutines/Continuation;Z)V
-HSPLkotlinx/coroutines/DispatchedTaskKt;->resumeUnconfined(Lkotlinx/coroutines/DispatchedTask;)V
-HSPLkotlinx/coroutines/Dispatchers;-><clinit>()V
-HSPLkotlinx/coroutines/Dispatchers;-><init>()V
-HSPLkotlinx/coroutines/Dispatchers;->getDefault()Lkotlinx/coroutines/CoroutineDispatcher;
-HSPLkotlinx/coroutines/Dispatchers;->getMain()Lkotlinx/coroutines/MainCoroutineDispatcher;
-HSPLkotlinx/coroutines/DisposeOnCancel;-><init>(Lkotlinx/coroutines/DisposableHandle;)V
-HSPLkotlinx/coroutines/Empty;-><init>(Z)V
-HSPLkotlinx/coroutines/Empty;->getList()Lkotlinx/coroutines/NodeList;
-HSPLkotlinx/coroutines/Empty;->isActive()Z
-HSPLkotlinx/coroutines/EventLoop;-><init>()V
-HSPLkotlinx/coroutines/EventLoop;->decrementUseCount(Z)V
-HSPLkotlinx/coroutines/EventLoop;->delta(Z)J
-HSPLkotlinx/coroutines/EventLoop;->incrementUseCount$default(Lkotlinx/coroutines/EventLoop;ZILjava/lang/Object;)V
-HSPLkotlinx/coroutines/EventLoop;->incrementUseCount(Z)V
-HSPLkotlinx/coroutines/EventLoop;->isUnconfinedLoopActive()Z
-HSPLkotlinx/coroutines/EventLoop;->processUnconfinedEvent()Z
-HSPLkotlinx/coroutines/EventLoopImplBase;-><init>()V
-HSPLkotlinx/coroutines/EventLoopImplPlatform;-><init>()V
-HSPLkotlinx/coroutines/EventLoopKt;->createEventLoop()Lkotlinx/coroutines/EventLoop;
-HSPLkotlinx/coroutines/ExceptionsKt;->CancellationException(Ljava/lang/String;Ljava/lang/Throwable;)Ljava/util/concurrent/CancellationException;
-HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key$1;-><clinit>()V
-HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key$1;-><init>()V
-HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key;-><init>()V
-HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher;-><clinit>()V
-HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher;-><init>()V
-HSPLkotlinx/coroutines/GlobalScope;-><clinit>()V
-HSPLkotlinx/coroutines/GlobalScope;-><init>()V
-HSPLkotlinx/coroutines/GlobalScope;->getCoroutineContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/InvokeOnCancel;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/InvokeOnCancel;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/InvokeOnCompletion;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/InvokeOnCompletion;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/Job$DefaultImpls;->cancel$default(Lkotlinx/coroutines/Job;Ljava/util/concurrent/CancellationException;ILjava/lang/Object;)V
-HSPLkotlinx/coroutines/Job$DefaultImpls;->fold(Lkotlinx/coroutines/Job;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/Job$DefaultImpls;->get(Lkotlinx/coroutines/Job;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlinx/coroutines/Job$DefaultImpls;->invokeOnCompletion$default(Lkotlinx/coroutines/Job;ZZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/DisposableHandle;
-HSPLkotlinx/coroutines/Job$DefaultImpls;->minusKey(Lkotlinx/coroutines/Job;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/Job$DefaultImpls;->plus(Lkotlinx/coroutines/Job;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/Job$Key;-><clinit>()V
-HSPLkotlinx/coroutines/Job$Key;-><init>()V
-HSPLkotlinx/coroutines/Job;-><clinit>()V
-HSPLkotlinx/coroutines/JobCancellationException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/JobCancellationException;->equals(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/JobCancellationException;->fillInStackTrace()Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/JobCancellingNode;-><init>()V
-HSPLkotlinx/coroutines/JobImpl;-><init>(Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/JobImpl;->getHandlesException$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Z
-HSPLkotlinx/coroutines/JobImpl;->getOnCancelComplete$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Z
-HSPLkotlinx/coroutines/JobImpl;->handlesException()Z
-HSPLkotlinx/coroutines/JobKt;->Job$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
-HSPLkotlinx/coroutines/JobKt;->Job(Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
-HSPLkotlinx/coroutines/JobKt;->ensureActive(Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/JobKt;->ensureActive(Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/JobKt;->getJob(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/JobKt;->isActive(Lkotlin/coroutines/CoroutineContext;)Z
-HSPLkotlinx/coroutines/JobKt__JobKt;->Job$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
-HSPLkotlinx/coroutines/JobKt__JobKt;->Job(Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
-HSPLkotlinx/coroutines/JobKt__JobKt;->ensureActive(Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/JobKt__JobKt;->ensureActive(Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/JobKt__JobKt;->getJob(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/JobKt__JobKt;->isActive(Lkotlin/coroutines/CoroutineContext;)Z
-HSPLkotlinx/coroutines/JobNode;-><init>()V
-HSPLkotlinx/coroutines/JobNode;->dispose()V
-HSPLkotlinx/coroutines/JobNode;->getJob()Lkotlinx/coroutines/JobSupport;
-HSPLkotlinx/coroutines/JobNode;->getList()Lkotlinx/coroutines/NodeList;
-HSPLkotlinx/coroutines/JobNode;->isActive()Z
-HSPLkotlinx/coroutines/JobNode;->setJob(Lkotlinx/coroutines/JobSupport;)V
-HSPLkotlinx/coroutines/JobSupport$ChildCompletion;-><init>(Lkotlinx/coroutines/JobSupport;Lkotlinx/coroutines/JobSupport$Finishing;Lkotlinx/coroutines/ChildHandleNode;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport$ChildCompletion;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport$Finishing;-><init>(Lkotlinx/coroutines/NodeList;ZLjava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport$Finishing;->addExceptionLocked(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport$Finishing;->allocateList()Ljava/util/ArrayList;
-HSPLkotlinx/coroutines/JobSupport$Finishing;->getExceptionsHolder()Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport$Finishing;->getList()Lkotlinx/coroutines/NodeList;
-HSPLkotlinx/coroutines/JobSupport$Finishing;->getRootCause()Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/JobSupport$Finishing;->isActive()Z
-HSPLkotlinx/coroutines/JobSupport$Finishing;->isCancelling()Z
-HSPLkotlinx/coroutines/JobSupport$Finishing;->isCompleting()Z
-HSPLkotlinx/coroutines/JobSupport$Finishing;->isSealed()Z
-HSPLkotlinx/coroutines/JobSupport$Finishing;->sealLocked(Ljava/lang/Throwable;)Ljava/util/List;
-HSPLkotlinx/coroutines/JobSupport$Finishing;->setCompleting(Z)V
-HSPLkotlinx/coroutines/JobSupport$Finishing;->setExceptionsHolder(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport$Finishing;->setRootCause(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/JobSupport;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;->prepare(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;->prepare(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;-><init>(Z)V
-HSPLkotlinx/coroutines/JobSupport;->access$cancellationExceptionMessage(Lkotlinx/coroutines/JobSupport;)Ljava/lang/String;
-HSPLkotlinx/coroutines/JobSupport;->access$continueCompleting(Lkotlinx/coroutines/JobSupport;Lkotlinx/coroutines/JobSupport$Finishing;Lkotlinx/coroutines/ChildHandleNode;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport;->addLastAtomic(Ljava/lang/Object;Lkotlinx/coroutines/NodeList;Lkotlinx/coroutines/JobNode;)Z
-HSPLkotlinx/coroutines/JobSupport;->addSuppressedExceptions(Ljava/lang/Throwable;Ljava/util/List;)V
-HSPLkotlinx/coroutines/JobSupport;->afterCompletion(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport;->attachChild(Lkotlinx/coroutines/ChildJob;)Lkotlinx/coroutines/ChildHandle;
-HSPLkotlinx/coroutines/JobSupport;->cancel(Ljava/util/concurrent/CancellationException;)V
-HSPLkotlinx/coroutines/JobSupport;->cancelImpl$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/JobSupport;->cancelInternal(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport;->cancelMakeCompleting(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->cancelParent(Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/JobSupport;->cancellationExceptionMessage()Ljava/lang/String;
-HSPLkotlinx/coroutines/JobSupport;->childCancelled(Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/JobSupport;->completeStateFinalization(Lkotlinx/coroutines/Incomplete;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport;->continueCompleting(Lkotlinx/coroutines/JobSupport$Finishing;Lkotlinx/coroutines/ChildHandleNode;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport;->createCauseException(Ljava/lang/Object;)Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/JobSupport;->finalizeFinishingState(Lkotlinx/coroutines/JobSupport$Finishing;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->firstChild(Lkotlinx/coroutines/Incomplete;)Lkotlinx/coroutines/ChildHandleNode;
-HSPLkotlinx/coroutines/JobSupport;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlinx/coroutines/JobSupport;->getCancellationException()Ljava/util/concurrent/CancellationException;
-HSPLkotlinx/coroutines/JobSupport;->getChildJobCancellationCause()Ljava/util/concurrent/CancellationException;
-HSPLkotlinx/coroutines/JobSupport;->getFinalRootCause(Lkotlinx/coroutines/JobSupport$Finishing;Ljava/util/List;)Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/JobSupport;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
-HSPLkotlinx/coroutines/JobSupport;->getOnCancelComplete$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Z
-HSPLkotlinx/coroutines/JobSupport;->getOrPromoteCancellingList(Lkotlinx/coroutines/Incomplete;)Lkotlinx/coroutines/NodeList;
-HSPLkotlinx/coroutines/JobSupport;->getParentHandle$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Lkotlinx/coroutines/ChildHandle;
-HSPLkotlinx/coroutines/JobSupport;->getState$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->initParentJob(Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/JobSupport;->invokeOnCompletion(Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/DisposableHandle;
-HSPLkotlinx/coroutines/JobSupport;->invokeOnCompletion(ZZLkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/DisposableHandle;
-HSPLkotlinx/coroutines/JobSupport;->isActive()Z
-HSPLkotlinx/coroutines/JobSupport;->isCompleted()Z
-HSPLkotlinx/coroutines/JobSupport;->isScopedCoroutine()Z
-HSPLkotlinx/coroutines/JobSupport;->join(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->joinInternal()Z
-HSPLkotlinx/coroutines/JobSupport;->joinSuspend(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->makeCancelling(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->makeCompletingOnce$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->makeNode(Lkotlin/jvm/functions/Function1;Z)Lkotlinx/coroutines/JobNode;
-HSPLkotlinx/coroutines/JobSupport;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/JobSupport;->nextChild(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Lkotlinx/coroutines/ChildHandleNode;
-HSPLkotlinx/coroutines/JobSupport;->notifyCancelling(Lkotlinx/coroutines/NodeList;Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport;->notifyCompletion(Lkotlinx/coroutines/NodeList;Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport;->onCancelling(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/JobSupport;->onCompletionInternal(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/JobSupport;->parentCancelled(Lkotlinx/coroutines/ParentJob;)V
-HSPLkotlinx/coroutines/JobSupport;->plus(Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/JobSupport;->promoteSingleToNodeList(Lkotlinx/coroutines/JobNode;)V
-HSPLkotlinx/coroutines/JobSupport;->removeNode$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Lkotlinx/coroutines/JobNode;)V
-HSPLkotlinx/coroutines/JobSupport;->setParentHandle$external__kotlinx_coroutines__android_common__kotlinx_coroutines(Lkotlinx/coroutines/ChildHandle;)V
-HSPLkotlinx/coroutines/JobSupport;->start()Z
-HSPLkotlinx/coroutines/JobSupport;->startInternal(Ljava/lang/Object;)I
-HSPLkotlinx/coroutines/JobSupport;->toCancellationException(Ljava/lang/Throwable;Ljava/lang/String;)Ljava/util/concurrent/CancellationException;
-HSPLkotlinx/coroutines/JobSupport;->tryFinalizeSimpleState(Lkotlinx/coroutines/Incomplete;Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/JobSupport;->tryMakeCancelling(Lkotlinx/coroutines/Incomplete;Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/JobSupport;->tryMakeCompleting(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->tryMakeCompletingSlowPath(Lkotlinx/coroutines/Incomplete;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupport;->tryWaitForChild(Lkotlinx/coroutines/JobSupport$Finishing;Lkotlinx/coroutines/ChildHandleNode;Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/JobSupportKt;-><clinit>()V
-HSPLkotlinx/coroutines/JobSupportKt;->access$getCOMPLETING_ALREADY$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/JobSupportKt;->access$getCOMPLETING_RETRY$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/JobSupportKt;->access$getEMPTY_ACTIVE$p()Lkotlinx/coroutines/Empty;
-HSPLkotlinx/coroutines/JobSupportKt;->access$getSEALED$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/JobSupportKt;->access$getTOO_LATE_TO_CANCEL$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/JobSupportKt;->boxIncomplete(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/JobSupportKt;->unboxState(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/MainCoroutineDispatcher;-><init>()V
-HSPLkotlinx/coroutines/NodeList;-><init>()V
-HSPLkotlinx/coroutines/NodeList;->getList()Lkotlinx/coroutines/NodeList;
-HSPLkotlinx/coroutines/NodeList;->isActive()Z
-HSPLkotlinx/coroutines/NonDisposableHandle;-><clinit>()V
-HSPLkotlinx/coroutines/NonDisposableHandle;-><init>()V
-HSPLkotlinx/coroutines/NonDisposableHandle;->dispose()V
-HSPLkotlinx/coroutines/RemoveOnCancel;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/ResumeOnCompletion;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/ResumeOnCompletion;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/StandaloneCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Z)V
-HSPLkotlinx/coroutines/SupervisorJobImpl;-><init>(Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/SupervisorKt;->SupervisorJob$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
-HSPLkotlinx/coroutines/SupervisorKt;->SupervisorJob(Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
-HSPLkotlinx/coroutines/ThreadLocalEventLoop;-><clinit>()V
-HSPLkotlinx/coroutines/ThreadLocalEventLoop;-><init>()V
-HSPLkotlinx/coroutines/ThreadLocalEventLoop;->getEventLoop$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Lkotlinx/coroutines/EventLoop;
-HSPLkotlinx/coroutines/Unconfined;-><clinit>()V
-HSPLkotlinx/coroutines/Unconfined;-><init>()V
-HSPLkotlinx/coroutines/UndispatchedCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/UndispatchedCoroutine;->afterResume(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/UndispatchedMarker;-><clinit>()V
-HSPLkotlinx/coroutines/UndispatchedMarker;-><init>()V
-HSPLkotlinx/coroutines/UndispatchedMarker;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/UndispatchedMarker;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
-HSPLkotlinx/coroutines/UndispatchedMarker;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
-HSPLkotlinx/coroutines/android/AndroidDispatcherFactory;-><init>()V
-HSPLkotlinx/coroutines/android/AndroidDispatcherFactory;->createDispatcher(Ljava/util/List;)Lkotlinx/coroutines/MainCoroutineDispatcher;
-HSPLkotlinx/coroutines/android/HandlerContext;-><init>(Landroid/os/Handler;Ljava/lang/String;)V
-HSPLkotlinx/coroutines/android/HandlerContext;-><init>(Landroid/os/Handler;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/android/HandlerContext;-><init>(Landroid/os/Handler;Ljava/lang/String;Z)V
-HSPLkotlinx/coroutines/android/HandlerContext;->dispatch(Lkotlin/coroutines/CoroutineContext;Ljava/lang/Runnable;)V
-HSPLkotlinx/coroutines/android/HandlerContext;->getImmediate()Lkotlinx/coroutines/android/HandlerContext;
-HSPLkotlinx/coroutines/android/HandlerContext;->getImmediate()Lkotlinx/coroutines/android/HandlerDispatcher;
-HSPLkotlinx/coroutines/android/HandlerContext;->isDispatchNeeded(Lkotlin/coroutines/CoroutineContext;)Z
-HSPLkotlinx/coroutines/android/HandlerDispatcher;-><init>()V
-HSPLkotlinx/coroutines/android/HandlerDispatcher;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/android/HandlerDispatcherKt;-><clinit>()V
-HSPLkotlinx/coroutines/android/HandlerDispatcherKt;->asHandler(Landroid/os/Looper;Z)Landroid/os/Handler;
-HSPLkotlinx/coroutines/android/HandlerDispatcherKt;->from(Landroid/os/Handler;Ljava/lang/String;)Lkotlinx/coroutines/android/HandlerDispatcher;
-HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;-><init>(Lkotlinx/coroutines/channels/AbstractChannel;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->hasNext(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->hasNextResult(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->hasNextSuspend(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->next()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->setResult(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;-><init>(Lkotlinx/coroutines/CancellableContinuation;I)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;->completeResumeReceive(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;->resumeValue(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;->tryResumeReceive(Ljava/lang/Object;Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;-><init>(Lkotlinx/coroutines/channels/AbstractChannel$Itr;Lkotlinx/coroutines/CancellableContinuation;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;->completeResumeReceive(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;->resumeOnCancellationFun(Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
-HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;->tryResumeReceive(Ljava/lang/Object;Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/channels/AbstractChannel$RemoveReceiveOnCancel;-><init>(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlinx/coroutines/channels/Receive;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$RemoveReceiveOnCancel;->invoke(Ljava/lang/Throwable;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/channels/AbstractChannel;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;->prepare(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;->prepare(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel$receiveCatching$1;-><init>(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel$receiveCatching$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel;->access$enqueueReceive(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlinx/coroutines/channels/Receive;)Z
-HSPLkotlinx/coroutines/channels/AbstractChannel;->access$removeReceiveOnCancel(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/channels/Receive;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel;->enqueueReceive(Lkotlinx/coroutines/channels/Receive;)Z
-HSPLkotlinx/coroutines/channels/AbstractChannel;->enqueueReceiveInternal(Lkotlinx/coroutines/channels/Receive;)Z
-HSPLkotlinx/coroutines/channels/AbstractChannel;->iterator()Lkotlinx/coroutines/channels/ChannelIterator;
-HSPLkotlinx/coroutines/channels/AbstractChannel;->onReceiveDequeued()V
-HSPLkotlinx/coroutines/channels/AbstractChannel;->onReceiveEnqueued()V
-HSPLkotlinx/coroutines/channels/AbstractChannel;->pollInternal()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel;->receive(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel;->receiveCatching-JP2dKIU(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel;->receiveSuspend(ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannel;->removeReceiveOnCancel(Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/channels/Receive;)V
-HSPLkotlinx/coroutines/channels/AbstractChannel;->takeFirstReceiveOrPeekClosed()Lkotlinx/coroutines/channels/ReceiveOrClosed;
-HSPLkotlinx/coroutines/channels/AbstractChannel;->tryReceive-PtdJZtk()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractChannelKt;-><clinit>()V
-HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;-><init>(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;->completeResumeSend()V
-HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;->getPollResult()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;->tryResumeSend(Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->getClosedForSend()Lkotlinx/coroutines/channels/Closed;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->getQueue()Lkotlinx/coroutines/internal/LockFreeLinkedListHead;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->send(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->sendBuffered(Ljava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveOrClosed;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->takeFirstReceiveOrPeekClosed()Lkotlinx/coroutines/channels/ReceiveOrClosed;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->takeFirstSendOrPeekClosed()Lkotlinx/coroutines/channels/Send;
-HSPLkotlinx/coroutines/channels/AbstractSendChannel;->trySend-JP2dKIU(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ArrayChannel;-><init>(ILkotlinx/coroutines/channels/BufferOverflow;Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/channels/ArrayChannel;->enqueueReceiveInternal(Lkotlinx/coroutines/channels/Receive;)Z
-HSPLkotlinx/coroutines/channels/ArrayChannel;->isBufferAlwaysEmpty()Z
-HSPLkotlinx/coroutines/channels/ArrayChannel;->isBufferEmpty()Z
-HSPLkotlinx/coroutines/channels/ArrayChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ArrayChannel;->pollInternal()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ArrayChannel;->updateBufferSize(I)Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/channels/BufferOverflow;->$values()[Lkotlinx/coroutines/channels/BufferOverflow;
-HSPLkotlinx/coroutines/channels/BufferOverflow;-><clinit>()V
-HSPLkotlinx/coroutines/channels/BufferOverflow;-><init>(Ljava/lang/String;I)V
-HSPLkotlinx/coroutines/channels/Channel$Factory;-><clinit>()V
-HSPLkotlinx/coroutines/channels/Channel$Factory;-><init>()V
-HSPLkotlinx/coroutines/channels/Channel$Factory;->getCHANNEL_DEFAULT_CAPACITY$external__kotlinx_coroutines__android_common__kotlinx_coroutines()I
-HSPLkotlinx/coroutines/channels/Channel;-><clinit>()V
-HSPLkotlinx/coroutines/channels/ChannelCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/channels/Channel;ZZ)V
-HSPLkotlinx/coroutines/channels/ChannelCoroutine;->receiveCatching-JP2dKIU(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelCoroutine;->send(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelKt;->Channel$default(ILkotlinx/coroutines/channels/BufferOverflow;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/channels/Channel;
-HSPLkotlinx/coroutines/channels/ChannelKt;->Channel(ILkotlinx/coroutines/channels/BufferOverflow;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/channels/Channel;
-HSPLkotlinx/coroutines/channels/ChannelResult$Companion;-><init>()V
-HSPLkotlinx/coroutines/channels/ChannelResult$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/channels/ChannelResult$Companion;->failure-PtdJZtk()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelResult$Companion;->success-JP2dKIU(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelResult$Failed;-><init>()V
-HSPLkotlinx/coroutines/channels/ChannelResult;-><clinit>()V
-HSPLkotlinx/coroutines/channels/ChannelResult;-><init>(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/channels/ChannelResult;->access$getFailed$cp()Lkotlinx/coroutines/channels/ChannelResult$Failed;
-HSPLkotlinx/coroutines/channels/ChannelResult;->box-impl(Ljava/lang/Object;)Lkotlinx/coroutines/channels/ChannelResult;
-HSPLkotlinx/coroutines/channels/ChannelResult;->constructor-impl(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelResult;->getOrNull-impl(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelResult;->getOrThrow-impl(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ChannelResult;->isClosed-impl(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/channels/ChannelResult;->unbox-impl()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ConflatedChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/channels/ConflatedChannel;->enqueueReceiveInternal(Lkotlinx/coroutines/channels/Receive;)Z
-HSPLkotlinx/coroutines/channels/ConflatedChannel;->isBufferAlwaysEmpty()Z
-HSPLkotlinx/coroutines/channels/ConflatedChannel;->isBufferEmpty()Z
-HSPLkotlinx/coroutines/channels/ConflatedChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ConflatedChannel;->pollInternal()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ConflatedChannel;->updateValueLocked(Ljava/lang/Object;)Lkotlinx/coroutines/internal/UndeliveredElementException;
-HSPLkotlinx/coroutines/channels/LinkedListChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/channels/LinkedListChannel;->isBufferAlwaysEmpty()Z
-HSPLkotlinx/coroutines/channels/LinkedListChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/ProduceKt;->produce$default(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel;
-HSPLkotlinx/coroutines/channels/ProduceKt;->produce(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/channels/ReceiveChannel;
-HSPLkotlinx/coroutines/channels/ProducerCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/channels/Channel;)V
-HSPLkotlinx/coroutines/channels/Receive;-><init>()V
-HSPLkotlinx/coroutines/channels/Receive;->getOfferResult()Ljava/lang/Object;
-HSPLkotlinx/coroutines/channels/Receive;->getOfferResult()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/channels/Receive;->resumeOnCancellationFun(Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
-HSPLkotlinx/coroutines/channels/RendezvousChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/channels/RendezvousChannel;->isBufferAlwaysEmpty()Z
-HSPLkotlinx/coroutines/channels/Send;-><init>()V
-HSPLkotlinx/coroutines/flow/AbstractFlow$collect$1;-><init>(Lkotlinx/coroutines/flow/AbstractFlow;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/AbstractFlow$collect$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/AbstractFlow;-><init>()V
-HSPLkotlinx/coroutines/flow/AbstractFlow;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/DistinctFlowImpl$collect$2$emit$1;-><init>(Lkotlinx/coroutines/flow/DistinctFlowImpl$collect$2;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/DistinctFlowImpl$collect$2$emit$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/DistinctFlowImpl$collect$2;-><init>(Lkotlinx/coroutines/flow/DistinctFlowImpl;Lkotlin/jvm/internal/Ref$ObjectRef;Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/DistinctFlowImpl$collect$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/DistinctFlowImpl;-><init>(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)V
-HSPLkotlinx/coroutines/flow/DistinctFlowImpl;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt;->buffer$default(Lkotlinx/coroutines/flow/Flow;ILkotlinx/coroutines/channels/BufferOverflow;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->buffer(Lkotlinx/coroutines/flow/Flow;ILkotlinx/coroutines/channels/BufferOverflow;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->collect(Lkotlinx/coroutines/flow/Flow;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt;->collectLatest(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt;->distinctUntilChanged(Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->dropWhile(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->emitAll(Lkotlinx/coroutines/flow/FlowCollector;Lkotlinx/coroutines/channels/ReceiveChannel;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt;->ensureActive(Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/FlowKt;->first(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt;->flow(Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->mapLatest(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->stateIn(Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;Ljava/lang/Object;)Lkotlinx/coroutines/flow/StateFlow;
-HSPLkotlinx/coroutines/flow/FlowKt;->take(Lkotlinx/coroutines/flow/Flow;I)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt;->transformLatest(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__BuildersKt;->flow(Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__ChannelsKt$emitAllImpl$1;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__ChannelsKt$emitAllImpl$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ChannelsKt;->access$emitAllImpl$FlowKt__ChannelsKt(Lkotlinx/coroutines/flow/FlowCollector;Lkotlinx/coroutines/channels/ReceiveChannel;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ChannelsKt;->emitAll(Lkotlinx/coroutines/flow/FlowCollector;Lkotlinx/coroutines/channels/ReceiveChannel;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ChannelsKt;->emitAllImpl$FlowKt__ChannelsKt(Lkotlinx/coroutines/flow/FlowCollector;Lkotlinx/coroutines/channels/ReceiveChannel;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__CollectKt;->collect(Lkotlinx/coroutines/flow/Flow;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__CollectKt;->collectLatest(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ContextKt;->buffer$default(Lkotlinx/coroutines/flow/Flow;ILkotlinx/coroutines/channels/BufferOverflow;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__ContextKt;->buffer(Lkotlinx/coroutines/flow/Flow;ILkotlinx/coroutines/channels/BufferOverflow;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultAreEquivalent$1;-><clinit>()V
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultAreEquivalent$1;-><init>()V
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultAreEquivalent$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Boolean;
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultAreEquivalent$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultKeySelector$1;-><clinit>()V
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultKeySelector$1;-><init>()V
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultKeySelector$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt;->distinctUntilChanged(Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__DistinctKt;->distinctUntilChangedBy$FlowKt__DistinctKt(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__EmittersKt;->ensureActive(Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$$inlined$unsafeFlow$1;-><init>(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$$inlined$unsafeFlow$1;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1$emit$1;-><init>(Lkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1$emit$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1;-><init>(Lkotlin/jvm/internal/Ref$BooleanRef;Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/jvm/functions/Function2;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$emitAbort$1;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$emitAbort$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1$1;-><init>(Lkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1;-><init>(Lkotlinx/coroutines/flow/Flow;I)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1$emit$1;-><init>(Lkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1$emit$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1;-><init>(Lkotlin/jvm/internal/Ref$IntRef;ILkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt;->access$emitAbort$FlowKt__LimitKt(Lkotlinx/coroutines/flow/FlowCollector;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt;->dropWhile(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt;->emitAbort$FlowKt__LimitKt(Lkotlinx/coroutines/flow/FlowCollector;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__LimitKt;->take(Lkotlinx/coroutines/flow/Flow;I)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt$mapLatest$1;-><init>(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt$mapLatest$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt$mapLatest$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt$mapLatest$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt;->mapLatest(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__MergeKt;->transformLatest(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2$1;-><init>(Lkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;-><init>(Lkotlin/jvm/functions/Function2;Lkotlin/jvm/internal/Ref$ObjectRef;)V
-HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$3;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt;->first(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2$WhenMappings;-><clinit>()V
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2;-><init>(Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/flow/MutableSharedFlow;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2;->invoke(Lkotlinx/coroutines/flow/SharingCommand;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1;-><init>(Lkotlinx/coroutines/flow/SharingStarted;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/flow/MutableSharedFlow;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt;->configureSharing$FlowKt__ShareKt(Lkotlinx/coroutines/flow/Flow;I)Lkotlinx/coroutines/flow/SharingConfig;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt;->launchSharing$FlowKt__ShareKt(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/flow/MutableSharedFlow;Lkotlinx/coroutines/flow/SharingStarted;Ljava/lang/Object;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/flow/FlowKt__ShareKt;->stateIn(Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;Ljava/lang/Object;)Lkotlinx/coroutines/flow/StateFlow;
-HSPLkotlinx/coroutines/flow/ReadonlyStateFlow;-><init>(Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/Job;)V
-HSPLkotlinx/coroutines/flow/ReadonlyStateFlow;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/ReadonlyStateFlow;->getValue()Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SafeFlow;-><init>(Lkotlin/jvm/functions/Function2;)V
-HSPLkotlinx/coroutines/flow/SafeFlow;->collectSafely(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl$collect$1;-><init>(Lkotlinx/coroutines/flow/SharedFlowImpl;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/SharedFlowImpl$collect$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;-><init>(IILkotlinx/coroutines/channels/BufferOverflow;)V
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->access$tryPeekLocked(Lkotlinx/coroutines/flow/SharedFlowImpl;Lkotlinx/coroutines/flow/SharedFlowSlot;)J
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->awaitValue(Lkotlinx/coroutines/flow/SharedFlowSlot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->cleanupTailLocked()V
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->collect$suspendImpl(Lkotlinx/coroutines/flow/SharedFlowImpl;Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlot()Lkotlinx/coroutines/flow/SharedFlowSlot;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlot()Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/SharedFlowSlot;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->dropOldestLocked()V
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->emit$suspendImpl(Lkotlinx/coroutines/flow/SharedFlowImpl;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->enqueueLocked(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->findSlotsToResumeLocked([Lkotlin/coroutines/Continuation;)[Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getBufferEndIndex()J
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getHead()J
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getLastReplayedLocked()Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getPeekedValueLockedAt(J)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getQueueEndIndex()J
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getReplaySize()I
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getTotalSize()I
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->growBuffer([Ljava/lang/Object;II)[Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryEmit(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryEmitLocked(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryEmitNoCollectorsLocked(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryPeekLocked(Lkotlinx/coroutines/flow/SharedFlowSlot;)J
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryTakeValue(Lkotlinx/coroutines/flow/SharedFlowSlot;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->updateBufferLocked(JJJJ)V
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->updateCollectorIndexLocked$external__kotlinx_coroutines__android_common__kotlinx_coroutines(J)[Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/SharedFlowImpl;->updateNewCollectorIndexLocked$external__kotlinx_coroutines__android_common__kotlinx_coroutines()J
-HSPLkotlinx/coroutines/flow/SharedFlowKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/SharedFlowKt;->MutableSharedFlow$default(IILkotlinx/coroutines/channels/BufferOverflow;ILjava/lang/Object;)Lkotlinx/coroutines/flow/MutableSharedFlow;
-HSPLkotlinx/coroutines/flow/SharedFlowKt;->MutableSharedFlow(IILkotlinx/coroutines/channels/BufferOverflow;)Lkotlinx/coroutines/flow/MutableSharedFlow;
-HSPLkotlinx/coroutines/flow/SharedFlowKt;->access$getBufferAt([Ljava/lang/Object;J)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowKt;->access$setBufferAt([Ljava/lang/Object;JLjava/lang/Object;)V
-HSPLkotlinx/coroutines/flow/SharedFlowKt;->getBufferAt([Ljava/lang/Object;J)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/SharedFlowKt;->setBufferAt([Ljava/lang/Object;JLjava/lang/Object;)V
-HSPLkotlinx/coroutines/flow/SharedFlowSlot;-><init>()V
-HSPLkotlinx/coroutines/flow/SharedFlowSlot;->allocateLocked(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/SharedFlowSlot;->allocateLocked(Lkotlinx/coroutines/flow/SharedFlowImpl;)Z
-HSPLkotlinx/coroutines/flow/SharedFlowSlot;->freeLocked(Ljava/lang/Object;)[Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/SharedFlowSlot;->freeLocked(Lkotlinx/coroutines/flow/SharedFlowImpl;)[Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/SharingCommand;->$values()[Lkotlinx/coroutines/flow/SharingCommand;
-HSPLkotlinx/coroutines/flow/SharingCommand;-><clinit>()V
-HSPLkotlinx/coroutines/flow/SharingCommand;-><init>(Ljava/lang/String;I)V
-HSPLkotlinx/coroutines/flow/SharingCommand;->values()[Lkotlinx/coroutines/flow/SharingCommand;
-HSPLkotlinx/coroutines/flow/SharingConfig;-><init>(Lkotlinx/coroutines/flow/Flow;ILkotlinx/coroutines/channels/BufferOverflow;Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/flow/SharingStarted$Companion;-><clinit>()V
-HSPLkotlinx/coroutines/flow/SharingStarted$Companion;-><init>()V
-HSPLkotlinx/coroutines/flow/SharingStarted$Companion;->WhileSubscribed$default(Lkotlinx/coroutines/flow/SharingStarted$Companion;JJILjava/lang/Object;)Lkotlinx/coroutines/flow/SharingStarted;
-HSPLkotlinx/coroutines/flow/SharingStarted$Companion;->WhileSubscribed(JJ)Lkotlinx/coroutines/flow/SharingStarted;
-HSPLkotlinx/coroutines/flow/SharingStarted$Companion;->getEagerly()Lkotlinx/coroutines/flow/SharingStarted;
-HSPLkotlinx/coroutines/flow/SharingStarted$Companion;->getLazily()Lkotlinx/coroutines/flow/SharingStarted;
-HSPLkotlinx/coroutines/flow/SharingStarted;-><clinit>()V
-HSPLkotlinx/coroutines/flow/StartedEagerly;-><init>()V
-HSPLkotlinx/coroutines/flow/StartedLazily;-><init>()V
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$1;-><init>(Lkotlinx/coroutines/flow/StartedWhileSubscribed;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$2;-><init>(Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$2;->invoke(Lkotlinx/coroutines/flow/SharingCommand;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed$command$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed;-><init>(JJ)V
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed;->access$getReplayExpiration$p(Lkotlinx/coroutines/flow/StartedWhileSubscribed;)J
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed;->access$getStopTimeout$p(Lkotlinx/coroutines/flow/StartedWhileSubscribed;)J
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed;->command(Lkotlinx/coroutines/flow/StateFlow;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/StartedWhileSubscribed;->equals(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/StateFlowImpl$collect$1;-><init>(Lkotlinx/coroutines/flow/StateFlowImpl;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/StateFlowImpl$collect$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;-><init>(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->compareAndSet(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlot()Lkotlinx/coroutines/flow/StateFlowSlot;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlot()Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/StateFlowSlot;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->getValue()Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->setValue(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/flow/StateFlowImpl;->updateState(Ljava/lang/Object;Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/StateFlowKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/StateFlowKt;->MutableStateFlow(Ljava/lang/Object;)Lkotlinx/coroutines/flow/MutableStateFlow;
-HSPLkotlinx/coroutines/flow/StateFlowKt;->access$getNONE$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/flow/StateFlowKt;->access$getPENDING$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/flow/StateFlowSlot;-><init>()V
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->access$get_state$p(Lkotlinx/coroutines/flow/StateFlowSlot;)Lkotlinx/atomicfu/AtomicRef;
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->allocateLocked(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->allocateLocked(Lkotlinx/coroutines/flow/StateFlowImpl;)Z
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->awaitPending(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->freeLocked(Ljava/lang/Object;)[Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->freeLocked(Lkotlinx/coroutines/flow/StateFlowImpl;)[Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->makePending()V
-HSPLkotlinx/coroutines/flow/StateFlowSlot;->takePending()Z
-HSPLkotlinx/coroutines/flow/internal/AbortFlowException;-><init>(Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/internal/AbortFlowException;->fillInStackTrace()Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->access$getNCollectors(Lkotlinx/coroutines/flow/internal/AbstractSharedFlow;)I
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->access$getSlots(Lkotlinx/coroutines/flow/internal/AbstractSharedFlow;)[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->allocateSlot()Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->freeSlot(Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;)V
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->getNCollectors()I
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->getSlots()[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->getSubscriptionCount()Lkotlinx/coroutines/flow/StateFlow;
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlowKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collect$2;-><init>(Lkotlinx/coroutines/flow/FlowCollector;Lkotlinx/coroutines/flow/internal/ChannelFlow;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collect$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collect$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collect$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collect$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collectToFun$1;-><init>(Lkotlinx/coroutines/flow/internal/ChannelFlow;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collectToFun$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow$collectToFun$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;-><init>(Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;->collect$suspendImpl(Lkotlinx/coroutines/flow/internal/ChannelFlow;Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;->fuse(Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;->getCollectToFun$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Lkotlin/jvm/functions/Function2;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;->getProduceCapacity$external__kotlinx_coroutines__android_common__kotlinx_coroutines()I
-HSPLkotlinx/coroutines/flow/internal/ChannelFlow;->produceImpl(Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/channels/ReceiveChannel;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowOperator;-><init>(Lkotlinx/coroutines/flow/Flow;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowOperator;->collect$suspendImpl(Lkotlinx/coroutines/flow/internal/ChannelFlowOperator;Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowOperator;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowOperator;->collectTo$suspendImpl(Lkotlinx/coroutines/flow/internal/ChannelFlowOperator;Lkotlinx/coroutines/channels/ProducerScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowOperator;->collectTo(Lkotlinx/coroutines/channels/ProducerScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$2;-><init>(Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;Lkotlinx/coroutines/flow/FlowCollector;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$emit$1;-><init>(Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$emit$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1;-><init>(Lkotlin/jvm/internal/Ref$ObjectRef;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3;-><init>(Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;-><init>(Lkotlin/jvm/functions/Function3;Lkotlinx/coroutines/flow/Flow;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;-><init>(Lkotlin/jvm/functions/Function3;Lkotlinx/coroutines/flow/Flow;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;->access$getTransform$p(Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;)Lkotlin/jvm/functions/Function3;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;->create(Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;)Lkotlinx/coroutines/flow/internal/ChannelFlow;
-HSPLkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;->flowCollect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/ChildCancelledException;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/ChildCancelledException;->fillInStackTrace()Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/flow/internal/DownstreamExceptionContext;-><init>(Ljava/lang/Throwable;Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/flow/internal/FlowExceptions_commonKt;->checkOwnership(Lkotlinx/coroutines/flow/internal/AbortFlowException;Lkotlinx/coroutines/flow/FlowCollector;)V
-HSPLkotlinx/coroutines/flow/internal/FusibleFlow$DefaultImpls;->fuse$default(Lkotlinx/coroutines/flow/internal/FusibleFlow;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/channels/BufferOverflow;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
-HSPLkotlinx/coroutines/flow/internal/NoOpContinuation;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/NoOpContinuation;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/NopCollector;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/NopCollector;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/NopCollector;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/NullSurrogateKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector$collectContextSize$1;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector$collectContextSize$1;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector$collectContextSize$1;->invoke(ILkotlin/coroutines/CoroutineContext$Element;)Ljava/lang/Integer;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector$collectContextSize$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;-><init>(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;->checkContext(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;->emit(Lkotlin/coroutines/Continuation;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector;->releaseIntercepted()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollectorKt$emitFun$1;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollectorKt$emitFun$1;-><init>()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollectorKt$emitFun$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollectorKt$emitFun$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollectorKt;-><clinit>()V
-HSPLkotlinx/coroutines/flow/internal/SafeCollectorKt;->access$getEmitFun$p()Lkotlin/jvm/functions/Function3;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector_commonKt$checkContext$result$1;-><init>(Lkotlinx/coroutines/flow/internal/SafeCollector;)V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector_commonKt$checkContext$result$1;->invoke(ILkotlin/coroutines/CoroutineContext$Element;)Ljava/lang/Integer;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector_commonKt$checkContext$result$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SafeCollector_commonKt;->checkContext(Lkotlinx/coroutines/flow/internal/SafeCollector;Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/flow/internal/SafeCollector_commonKt;->transitiveCoroutineParent(Lkotlinx/coroutines/Job;Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
-HSPLkotlinx/coroutines/flow/internal/SendingCollector;-><init>(Lkotlinx/coroutines/channels/SendChannel;)V
-HSPLkotlinx/coroutines/flow/internal/SendingCollector;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/flow/internal/SubscriptionCountStateFlow;-><init>(I)V
-HSPLkotlinx/coroutines/flow/internal/SubscriptionCountStateFlow;->increment(I)Z
-HSPLkotlinx/coroutines/internal/AtomicKt;-><clinit>()V
-HSPLkotlinx/coroutines/internal/AtomicOp;-><init>()V
-HSPLkotlinx/coroutines/internal/AtomicOp;->decide(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/AtomicOp;->perform(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/ContextScope;-><init>(Lkotlin/coroutines/CoroutineContext;)V
-HSPLkotlinx/coroutines/internal/ContextScope;->getCoroutineContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;-><init>(Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->awaitReusability()V
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->claimReusableCancellableContinuation()Lkotlinx/coroutines/CancellableContinuationImpl;
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->getContext()Lkotlin/coroutines/CoroutineContext;
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->getDelegate$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Lkotlin/coroutines/Continuation;
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->getReusableCancellableContinuation()Lkotlinx/coroutines/CancellableContinuationImpl;
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->isReusable()Z
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->postponeCancellation(Ljava/lang/Throwable;)Z
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->release()V
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->resumeWith(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->takeState$external__kotlinx_coroutines__android_common__kotlinx_coroutines()Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/DispatchedContinuation;->tryReleaseClaimedContinuation(Lkotlinx/coroutines/CancellableContinuation;)Ljava/lang/Throwable;
-HSPLkotlinx/coroutines/internal/DispatchedContinuationKt;-><clinit>()V
-HSPLkotlinx/coroutines/internal/DispatchedContinuationKt;->access$getUNDEFINED$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/internal/DispatchedContinuationKt;->resumeCancellableWith(Lkotlin/coroutines/Continuation;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/internal/LimitedDispatcher;-><init>(Lkotlinx/coroutines/CoroutineDispatcher;I)V
-HSPLkotlinx/coroutines/internal/LimitedDispatcherKt;->checkParallelism(I)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListHead;-><init>()V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListHead;->isRemoved()Z
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListKt;-><clinit>()V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListKt;->unwrap(Ljava/lang/Object;)Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;->complete(Ljava/lang/Object;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;->complete(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;-><init>()V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->access$finishAdd(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->access$get_next$p(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Lkotlinx/atomicfu/AtomicRef;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->addLast(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->addNext(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Z
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->addOneIfEmpty(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Z
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->correctPrev(Lkotlinx/coroutines/internal/OpDescriptor;)Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->findPrevNonRemoved(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->finishAdd(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->getNext()Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->getNextNode()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->getPrevNode()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->isRemoved()Z
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->remove()Z
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->removeFirstOrNull()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->removeOrNext()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->removed()Lkotlinx/coroutines/internal/Removed;
-HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->tryCondAddNext(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;)I
-HSPLkotlinx/coroutines/internal/LockFreeTaskQueue;-><init>(Z)V
-HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore$Companion;-><init>()V
-HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore;-><clinit>()V
-HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore;-><init>(IZ)V
-HSPLkotlinx/coroutines/internal/MainDispatcherLoader;-><clinit>()V
-HSPLkotlinx/coroutines/internal/MainDispatcherLoader;-><init>()V
-HSPLkotlinx/coroutines/internal/MainDispatcherLoader;->loadMainDispatcher()Lkotlinx/coroutines/MainCoroutineDispatcher;
-HSPLkotlinx/coroutines/internal/MainDispatchersKt;-><clinit>()V
-HSPLkotlinx/coroutines/internal/MainDispatchersKt;->tryCreateDispatcher(Lkotlinx/coroutines/internal/MainDispatcherFactory;Ljava/util/List;)Lkotlinx/coroutines/MainCoroutineDispatcher;
-HSPLkotlinx/coroutines/internal/OpDescriptor;-><init>()V
-HSPLkotlinx/coroutines/internal/Removed;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
-HSPLkotlinx/coroutines/internal/ResizableAtomicArray;-><init>(I)V
-HSPLkotlinx/coroutines/internal/ScopeCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/internal/ScopeCoroutine;->afterResume(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/internal/ScopeCoroutine;->isScopedCoroutine()Z
-HSPLkotlinx/coroutines/internal/Symbol;-><init>(Ljava/lang/String;)V
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->getAVAILABLE_PROCESSORS()I
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp$default(Ljava/lang/String;IIIILjava/lang/Object;)I
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp$default(Ljava/lang/String;JJJILjava/lang/Object;)J
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;)Ljava/lang/String;
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;III)I
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;JJJ)J
-HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;Z)Z
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemPropsKt;-><clinit>()V
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemPropsKt;->getAVAILABLE_PROCESSORS()I
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemPropsKt;->systemProp(Ljava/lang/String;)Ljava/lang/String;
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp$default(Ljava/lang/String;IIIILjava/lang/Object;)I
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp$default(Ljava/lang/String;JJJILjava/lang/Object;)J
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp(Ljava/lang/String;III)I
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp(Ljava/lang/String;JJJ)J
-HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp(Ljava/lang/String;Z)Z
-HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;-><clinit>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;-><init>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;->invoke(Ljava/lang/Object;Lkotlin/coroutines/CoroutineContext$Element;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/ThreadContextKt$findOne$1;-><clinit>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt$findOne$1;-><init>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt$updateState$1;-><clinit>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt$updateState$1;-><init>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt;-><clinit>()V
-HSPLkotlinx/coroutines/internal/ThreadContextKt;->restoreThreadContext(Lkotlin/coroutines/CoroutineContext;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/internal/ThreadContextKt;->threadContextElements(Lkotlin/coroutines/CoroutineContext;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/internal/ThreadContextKt;->updateThreadContext(Lkotlin/coroutines/CoroutineContext;Ljava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/intrinsics/CancellableKt;->startCoroutineCancellable$default(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
-HSPLkotlinx/coroutines/intrinsics/CancellableKt;->startCoroutineCancellable(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;Lkotlin/jvm/functions/Function1;)V
-HSPLkotlinx/coroutines/intrinsics/UndispatchedKt;->startCoroutineUndispatched(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
-HSPLkotlinx/coroutines/intrinsics/UndispatchedKt;->startUndispatchedOrReturn(Lkotlinx/coroutines/internal/ScopeCoroutine;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/scheduling/CoroutineScheduler$Companion;-><init>()V
-HSPLkotlinx/coroutines/scheduling/CoroutineScheduler$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
-HSPLkotlinx/coroutines/scheduling/CoroutineScheduler;-><clinit>()V
-HSPLkotlinx/coroutines/scheduling/CoroutineScheduler;-><init>(IIJLjava/lang/String;)V
-HSPLkotlinx/coroutines/scheduling/DefaultIoScheduler;-><clinit>()V
-HSPLkotlinx/coroutines/scheduling/DefaultIoScheduler;-><init>()V
-HSPLkotlinx/coroutines/scheduling/DefaultScheduler;-><clinit>()V
-HSPLkotlinx/coroutines/scheduling/DefaultScheduler;-><init>()V
-HSPLkotlinx/coroutines/scheduling/GlobalQueue;-><init>()V
-HSPLkotlinx/coroutines/scheduling/NanoTimeSource;-><clinit>()V
-HSPLkotlinx/coroutines/scheduling/NanoTimeSource;-><init>()V
-HSPLkotlinx/coroutines/scheduling/SchedulerCoroutineDispatcher;-><init>(IIJLjava/lang/String;)V
-HSPLkotlinx/coroutines/scheduling/SchedulerCoroutineDispatcher;->createScheduler()Lkotlinx/coroutines/scheduling/CoroutineScheduler;
-HSPLkotlinx/coroutines/scheduling/SchedulerTimeSource;-><init>()V
-HSPLkotlinx/coroutines/scheduling/Task;-><init>()V
-HSPLkotlinx/coroutines/scheduling/Task;-><init>(JLkotlinx/coroutines/scheduling/TaskContext;)V
-HSPLkotlinx/coroutines/scheduling/TaskContextImpl;-><init>(I)V
-HSPLkotlinx/coroutines/scheduling/TaskContextImpl;->afterTask()V
-HSPLkotlinx/coroutines/scheduling/TasksKt;-><clinit>()V
-HSPLkotlinx/coroutines/scheduling/UnlimitedIoScheduler;-><clinit>()V
-HSPLkotlinx/coroutines/scheduling/UnlimitedIoScheduler;-><init>()V
-HSPLkotlinx/coroutines/sync/Empty;-><init>(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/sync/Mutex$DefaultImpls;->lock$default(Lkotlinx/coroutines/sync/Mutex;Ljava/lang/Object;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/sync/Mutex$DefaultImpls;->unlock$default(Lkotlinx/coroutines/sync/Mutex;Ljava/lang/Object;ILjava/lang/Object;)V
-HSPLkotlinx/coroutines/sync/MutexImpl$LockCont$tryResumeLockWaiter$1;-><init>(Lkotlinx/coroutines/sync/MutexImpl;Lkotlinx/coroutines/sync/MutexImpl$LockCont;)V
-HSPLkotlinx/coroutines/sync/MutexImpl$LockCont;-><init>(Lkotlinx/coroutines/sync/MutexImpl;Ljava/lang/Object;Lkotlinx/coroutines/CancellableContinuation;)V
-HSPLkotlinx/coroutines/sync/MutexImpl$LockCont;->completeResumeLockWaiter()V
-HSPLkotlinx/coroutines/sync/MutexImpl$LockCont;->tryResumeLockWaiter()Z
-HSPLkotlinx/coroutines/sync/MutexImpl$LockWaiter;-><init>(Lkotlinx/coroutines/sync/MutexImpl;Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/sync/MutexImpl$LockWaiter;->take()Z
-HSPLkotlinx/coroutines/sync/MutexImpl$LockedQueue;-><init>(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/sync/MutexImpl;-><init>(Z)V
-HSPLkotlinx/coroutines/sync/MutexImpl;->access$get_state$p(Lkotlinx/coroutines/sync/MutexImpl;)Lkotlinx/atomicfu/AtomicRef;
-HSPLkotlinx/coroutines/sync/MutexImpl;->lock(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/sync/MutexImpl;->lockSuspend(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-HSPLkotlinx/coroutines/sync/MutexImpl;->tryLock(Ljava/lang/Object;)Z
-HSPLkotlinx/coroutines/sync/MutexImpl;->unlock(Ljava/lang/Object;)V
-HSPLkotlinx/coroutines/sync/MutexKt;-><clinit>()V
-HSPLkotlinx/coroutines/sync/MutexKt;->Mutex$default(ZILjava/lang/Object;)Lkotlinx/coroutines/sync/Mutex;
-HSPLkotlinx/coroutines/sync/MutexKt;->Mutex(Z)Lkotlinx/coroutines/sync/Mutex;
-HSPLkotlinx/coroutines/sync/MutexKt;->access$getEMPTY_LOCKED$p()Lkotlinx/coroutines/sync/Empty;
-HSPLkotlinx/coroutines/sync/MutexKt;->access$getEMPTY_UNLOCKED$p()Lkotlinx/coroutines/sync/Empty;
-HSPLkotlinx/coroutines/sync/MutexKt;->access$getLOCKED$p()Lkotlinx/coroutines/internal/Symbol;
-HSPLkotlinx/coroutines/sync/MutexKt;->access$getUNLOCKED$p()Lkotlinx/coroutines/internal/Symbol;
-Landroidx/activity/Cancellable;
-Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda0;
-Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda1;
-Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda2;
-Landroidx/activity/ComponentActivity$$ExternalSyntheticLambda3;
-Landroidx/activity/ComponentActivity$1;
-Landroidx/activity/ComponentActivity$2;
-Landroidx/activity/ComponentActivity$3;
-Landroidx/activity/ComponentActivity$4;
-Landroidx/activity/ComponentActivity$5;
-Landroidx/activity/ComponentActivity$Api19Impl;
-Landroidx/activity/ComponentActivity$Api33Impl;
-Landroidx/activity/ComponentActivity$NonConfigurationInstances;
-Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutor;
-Landroidx/activity/ComponentActivity$ReportFullyDrawnExecutorApi16Impl;
-Landroidx/activity/ComponentActivity;
-Landroidx/activity/FullyDrawnReporter$$ExternalSyntheticLambda0;
-Landroidx/activity/FullyDrawnReporter;
-Landroidx/activity/FullyDrawnReporterOwner;
-Landroidx/activity/OnBackPressedCallback;
-Landroidx/activity/OnBackPressedDispatcher$1;
-Landroidx/activity/OnBackPressedDispatcher$2;
-Landroidx/activity/OnBackPressedDispatcher$Api33Impl$$ExternalSyntheticLambda0;
-Landroidx/activity/OnBackPressedDispatcher$Api33Impl;
-Landroidx/activity/OnBackPressedDispatcher$LifecycleOnBackPressedCancellable;
-Landroidx/activity/OnBackPressedDispatcher$OnBackPressedCancellable;
-Landroidx/activity/OnBackPressedDispatcher;
-Landroidx/activity/OnBackPressedDispatcherOwner;
-Landroidx/activity/R$id;
-Landroidx/activity/ViewTreeFullyDrawnReporterOwner;
-Landroidx/activity/ViewTreeOnBackPressedDispatcherOwner;
-Landroidx/activity/compose/ActivityResultLauncherHolder;
-Landroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1$1;
-Landroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1$invoke$$inlined$onDispose$1;
-Landroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$1;
-Landroidx/activity/compose/ActivityResultRegistryKt$rememberLauncherForActivityResult$key$1;
-Landroidx/activity/compose/ActivityResultRegistryKt;
-Landroidx/activity/compose/ComponentActivityKt;
-Landroidx/activity/compose/LocalActivityResultRegistryOwner$LocalComposition$1;
-Landroidx/activity/compose/LocalActivityResultRegistryOwner;
-Landroidx/activity/compose/ManagedActivityResultLauncher;
-Landroidx/activity/contextaware/ContextAwareHelper;
-Landroidx/activity/contextaware/OnContextAvailableListener;
-Landroidx/activity/result/ActivityResult;
-Landroidx/activity/result/ActivityResultCallback;
-Landroidx/activity/result/ActivityResultLauncher;
-Landroidx/activity/result/ActivityResultRegistry$$ExternalSyntheticThrowCCEIfNotNull0;
-Landroidx/activity/result/ActivityResultRegistry$3;
-Landroidx/activity/result/ActivityResultRegistry$CallbackAndContract;
-Landroidx/activity/result/ActivityResultRegistry;
-Landroidx/activity/result/ActivityResultRegistryOwner;
-Landroidx/activity/result/contract/ActivityResultContract;
-Landroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda0;
-Landroidx/arch/core/executor/ArchTaskExecutor$$ExternalSyntheticLambda1;
-Landroidx/arch/core/executor/ArchTaskExecutor;
-Landroidx/arch/core/executor/DefaultTaskExecutor$1;
-Landroidx/arch/core/executor/DefaultTaskExecutor;
-Landroidx/arch/core/executor/TaskExecutor;
-Landroidx/arch/core/internal/FastSafeIterableMap;
-Landroidx/arch/core/internal/SafeIterableMap$AscendingIterator;
-Landroidx/arch/core/internal/SafeIterableMap$DescendingIterator;
-Landroidx/arch/core/internal/SafeIterableMap$Entry;
-Landroidx/arch/core/internal/SafeIterableMap$IteratorWithAdditions;
-Landroidx/arch/core/internal/SafeIterableMap$ListIterator;
-Landroidx/arch/core/internal/SafeIterableMap$SupportRemove;
-Landroidx/arch/core/internal/SafeIterableMap;
-Landroidx/collection/ArraySet$Companion;
-Landroidx/collection/ArraySet;
-Landroidx/collection/LruCache;
-Landroidx/collection/SimpleArrayMap;
-Landroidx/collection/SparseArrayCompat;
-Landroidx/collection/internal/ContainerHelpersKt;
-Landroidx/collection/internal/Lock;
-Landroidx/collection/internal/LruHashMap;
-Landroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$1;
-Landroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1$2;
-Landroidx/compose/animation/ColorVectorConverterKt$ColorToVector$1;
-Landroidx/compose/animation/ColorVectorConverterKt;
-Landroidx/compose/animation/FlingCalculator;
-Landroidx/compose/animation/FlingCalculatorKt;
-Landroidx/compose/animation/SingleValueAnimationKt;
-Landroidx/compose/animation/SplineBasedFloatDecayAnimationSpec;
-Landroidx/compose/animation/SplineBasedFloatDecayAnimationSpec_androidKt;
-Landroidx/compose/animation/core/Animatable$runAnimation$2$1;
-Landroidx/compose/animation/core/Animatable$runAnimation$2;
-Landroidx/compose/animation/core/Animatable;
-Landroidx/compose/animation/core/AnimatableKt;
-Landroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$2;
-Landroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3$1;
-Landroidx/compose/animation/core/AnimateAsStateKt$animateValueAsState$3;
-Landroidx/compose/animation/core/AnimateAsStateKt;
-Landroidx/compose/animation/core/Animation;
-Landroidx/compose/animation/core/AnimationEndReason;
-Landroidx/compose/animation/core/AnimationKt;
-Landroidx/compose/animation/core/AnimationResult;
-Landroidx/compose/animation/core/AnimationScope;
-Landroidx/compose/animation/core/AnimationSpec;
-Landroidx/compose/animation/core/AnimationSpecKt;
-Landroidx/compose/animation/core/AnimationState;
-Landroidx/compose/animation/core/AnimationStateKt;
-Landroidx/compose/animation/core/AnimationVector1D;
-Landroidx/compose/animation/core/AnimationVector4D;
-Landroidx/compose/animation/core/AnimationVector;
-Landroidx/compose/animation/core/AnimationVectorsKt;
-Landroidx/compose/animation/core/Animations;
-Landroidx/compose/animation/core/ComplexDouble;
-Landroidx/compose/animation/core/ComplexDoubleKt;
-Landroidx/compose/animation/core/CubicBezierEasing;
-Landroidx/compose/animation/core/DecayAnimationSpec;
-Landroidx/compose/animation/core/DecayAnimationSpecImpl;
-Landroidx/compose/animation/core/DecayAnimationSpecKt;
-Landroidx/compose/animation/core/Easing;
-Landroidx/compose/animation/core/EasingKt$LinearEasing$1;
-Landroidx/compose/animation/core/EasingKt;
-Landroidx/compose/animation/core/FiniteAnimationSpec;
-Landroidx/compose/animation/core/FloatAnimationSpec;
-Landroidx/compose/animation/core/FloatDecayAnimationSpec;
-Landroidx/compose/animation/core/FloatSpringSpec;
-Landroidx/compose/animation/core/FloatTweenSpec;
-Landroidx/compose/animation/core/Motion;
-Landroidx/compose/animation/core/MutatePriority;
-Landroidx/compose/animation/core/MutatorMutex$Mutator;
-Landroidx/compose/animation/core/MutatorMutex$mutate$2;
-Landroidx/compose/animation/core/MutatorMutex;
-Landroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fn$1;
-Landroidx/compose/animation/core/SpringEstimationKt$estimateCriticallyDamped$fnPrime$1;
-Landroidx/compose/animation/core/SpringEstimationKt;
-Landroidx/compose/animation/core/SpringSimulation;
-Landroidx/compose/animation/core/SpringSimulationKt;
-Landroidx/compose/animation/core/SpringSpec;
-Landroidx/compose/animation/core/SuspendAnimationKt$animate$4;
-Landroidx/compose/animation/core/SuspendAnimationKt$animate$6$1;
-Landroidx/compose/animation/core/SuspendAnimationKt$animate$6;
-Landroidx/compose/animation/core/SuspendAnimationKt$animate$7;
-Landroidx/compose/animation/core/SuspendAnimationKt$animate$9;
-Landroidx/compose/animation/core/SuspendAnimationKt$callWithFrameNanos$2;
-Landroidx/compose/animation/core/SuspendAnimationKt;
-Landroidx/compose/animation/core/TargetBasedAnimation;
-Landroidx/compose/animation/core/TweenSpec;
-Landroidx/compose/animation/core/TwoWayConverter;
-Landroidx/compose/animation/core/TwoWayConverterImpl;
-Landroidx/compose/animation/core/VectorConvertersKt$DpOffsetToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$DpOffsetToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$DpToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$DpToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$FloatToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$FloatToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$IntOffsetToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$IntOffsetToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$IntSizeToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$IntSizeToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$IntToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$IntToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$OffsetToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$OffsetToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$RectToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$RectToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt$SizeToVector$1;
-Landroidx/compose/animation/core/VectorConvertersKt$SizeToVector$2;
-Landroidx/compose/animation/core/VectorConvertersKt;
-Landroidx/compose/animation/core/VectorizedAnimationSpec;
-Landroidx/compose/animation/core/VectorizedAnimationSpecKt$createSpringAnimations$2;
-Landroidx/compose/animation/core/VectorizedAnimationSpecKt;
-Landroidx/compose/animation/core/VectorizedDurationBasedAnimationSpec;
-Landroidx/compose/animation/core/VectorizedFiniteAnimationSpec;
-Landroidx/compose/animation/core/VectorizedFloatAnimationSpec$1;
-Landroidx/compose/animation/core/VectorizedFloatAnimationSpec;
-Landroidx/compose/animation/core/VectorizedSpringSpec;
-Landroidx/compose/animation/core/VectorizedTweenSpec;
-Landroidx/compose/animation/core/VisibilityThresholdsKt;
-Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1$1;
-Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$effectModifier$1;
-Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect$onNewSize$1;
-Landroidx/compose/foundation/AndroidEdgeEffectOverscrollEffect;
-Landroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1$1;
-Landroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1;
-Landroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2$1;
-Landroidx/compose/foundation/AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2;
-Landroidx/compose/foundation/AndroidOverscrollKt;
-Landroidx/compose/foundation/Api31Impl;
-Landroidx/compose/foundation/Background;
-Landroidx/compose/foundation/BackgroundKt;
-Landroidx/compose/foundation/BorderStroke;
-Landroidx/compose/foundation/CanvasKt;
-Landroidx/compose/foundation/CheckScrollableContainerConstraintsKt;
-Landroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/ClickableKt$PressedInteractionSourceDisposableEffect$1;
-Landroidx/compose/foundation/ClickableKt$clickable$4$1$1;
-Landroidx/compose/foundation/ClickableKt$clickable$4$delayPressInteraction$1$1;
-Landroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$1;
-Landroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1$2;
-Landroidx/compose/foundation/ClickableKt$clickable$4$gesture$1$1;
-Landroidx/compose/foundation/ClickableKt$clickable$4;
-Landroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$clickSemantics$1$1;
-Landroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$clickSemantics$1;
-Landroidx/compose/foundation/ClickableKt$genericClickableWithoutGesture$detectPressAndClickFromKey$1;
-Landroidx/compose/foundation/ClickableKt$handlePressInteraction$2$delayJob$1;
-Landroidx/compose/foundation/ClickableKt$handlePressInteraction$2;
-Landroidx/compose/foundation/ClickableKt;
-Landroidx/compose/foundation/Clickable_androidKt$isComposeRootInScrollableContainer$1;
-Landroidx/compose/foundation/Clickable_androidKt;
-Landroidx/compose/foundation/ClipScrollableContainerKt$HorizontalScrollableClipModifier$1;
-Landroidx/compose/foundation/ClipScrollableContainerKt$VerticalScrollableClipModifier$1;
-Landroidx/compose/foundation/ClipScrollableContainerKt;
-Landroidx/compose/foundation/DarkThemeKt;
-Landroidx/compose/foundation/DarkTheme_androidKt;
-Landroidx/compose/foundation/DrawOverscrollModifier;
-Landroidx/compose/foundation/EdgeEffectCompat;
-Landroidx/compose/foundation/FocusableKt$focusGroup$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$1$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$1$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$2$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$2;
-Landroidx/compose/foundation/FocusableKt$focusable$2$3$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$3$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$4$1$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$4$1;
-Landroidx/compose/foundation/FocusableKt$focusable$2$5$2;
-Landroidx/compose/foundation/FocusableKt$focusable$2$5;
-Landroidx/compose/foundation/FocusableKt$focusable$2;
-Landroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2$1;
-Landroidx/compose/foundation/FocusableKt$focusableInNonTouchMode$2;
-Landroidx/compose/foundation/FocusableKt;
-Landroidx/compose/foundation/FocusedBoundsKt$ModifierLocalFocusedBoundsObserver$1;
-Landroidx/compose/foundation/FocusedBoundsKt$onFocusedBoundsChanged$2;
-Landroidx/compose/foundation/FocusedBoundsKt;
-Landroidx/compose/foundation/FocusedBoundsObserverModifier;
-Landroidx/compose/foundation/HoverableKt$hoverable$2$1$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/HoverableKt$hoverable$2$1$1;
-Landroidx/compose/foundation/HoverableKt$hoverable$2$2$1;
-Landroidx/compose/foundation/HoverableKt$hoverable$2$3$1;
-Landroidx/compose/foundation/HoverableKt$hoverable$2$3;
-Landroidx/compose/foundation/HoverableKt$hoverable$2;
-Landroidx/compose/foundation/HoverableKt;
-Landroidx/compose/foundation/ImageKt$Image$2$measure$1;
-Landroidx/compose/foundation/ImageKt$Image$2;
-Landroidx/compose/foundation/ImageKt;
-Landroidx/compose/foundation/Indication;
-Landroidx/compose/foundation/IndicationInstance;
-Landroidx/compose/foundation/IndicationKt$LocalIndication$1;
-Landroidx/compose/foundation/IndicationKt$indication$2;
-Landroidx/compose/foundation/IndicationKt;
-Landroidx/compose/foundation/IndicationModifier;
-Landroidx/compose/foundation/MutatePriority;
-Landroidx/compose/foundation/MutatorMutex$Mutator;
-Landroidx/compose/foundation/MutatorMutex$mutateWith$2;
-Landroidx/compose/foundation/MutatorMutex;
-Landroidx/compose/foundation/OverscrollConfiguration;
-Landroidx/compose/foundation/OverscrollConfigurationKt$LocalOverscrollConfiguration$1;
-Landroidx/compose/foundation/OverscrollConfigurationKt;
-Landroidx/compose/foundation/OverscrollEffect;
-Landroidx/compose/foundation/OverscrollKt;
-Landroidx/compose/foundation/gestures/AndroidConfig;
-Landroidx/compose/foundation/gestures/AndroidScrollable_androidKt;
-Landroidx/compose/foundation/gestures/BringIntoViewRequestPriorityQueue;
-Landroidx/compose/foundation/gestures/ContentInViewModifier$Request;
-Landroidx/compose/foundation/gestures/ContentInViewModifier$WhenMappings;
-Landroidx/compose/foundation/gestures/ContentInViewModifier$modifier$1;
-Landroidx/compose/foundation/gestures/ContentInViewModifier;
-Landroidx/compose/foundation/gestures/DefaultDraggableState$drag$2;
-Landroidx/compose/foundation/gestures/DefaultDraggableState$dragScope$1;
-Landroidx/compose/foundation/gestures/DefaultDraggableState;
-Landroidx/compose/foundation/gestures/DefaultFlingBehavior;
-Landroidx/compose/foundation/gestures/DefaultScrollableState$scrollScope$1;
-Landroidx/compose/foundation/gestures/DefaultScrollableState;
-Landroidx/compose/foundation/gestures/DragGestureDetectorKt$HorizontalPointerDirectionConfig$1;
-Landroidx/compose/foundation/gestures/DragGestureDetectorKt$VerticalPointerDirectionConfig$1;
-Landroidx/compose/foundation/gestures/DragGestureDetectorKt;
-Landroidx/compose/foundation/gestures/DragLogic;
-Landroidx/compose/foundation/gestures/DragScope;
-Landroidx/compose/foundation/gestures/DraggableKt$awaitDownAndSlop$1;
-Landroidx/compose/foundation/gestures/DraggableKt$awaitDownAndSlop$postPointerSlop$1;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$1;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$3;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$4;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$5;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$6;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9$1$1;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9$2;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1$1;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9$3$1;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9$3;
-Landroidx/compose/foundation/gestures/DraggableKt$draggable$9;
-Landroidx/compose/foundation/gestures/DraggableKt;
-Landroidx/compose/foundation/gestures/DraggableState;
-Landroidx/compose/foundation/gestures/FlingBehavior;
-Landroidx/compose/foundation/gestures/ForEachGestureKt$awaitAllPointersUp$3;
-Landroidx/compose/foundation/gestures/ForEachGestureKt$awaitEachGesture$2;
-Landroidx/compose/foundation/gestures/ForEachGestureKt;
-Landroidx/compose/foundation/gestures/ModifierLocalScrollableContainerProvider;
-Landroidx/compose/foundation/gestures/Orientation;
-Landroidx/compose/foundation/gestures/PointerDirectionConfig;
-Landroidx/compose/foundation/gestures/PressGestureScope;
-Landroidx/compose/foundation/gestures/PressGestureScopeImpl$reset$1;
-Landroidx/compose/foundation/gestures/PressGestureScopeImpl$tryAwaitRelease$1;
-Landroidx/compose/foundation/gestures/PressGestureScopeImpl;
-Landroidx/compose/foundation/gestures/ScrollConfig;
-Landroidx/compose/foundation/gestures/ScrollDraggableState;
-Landroidx/compose/foundation/gestures/ScrollScope;
-Landroidx/compose/foundation/gestures/ScrollableDefaults;
-Landroidx/compose/foundation/gestures/ScrollableKt$DefaultScrollMotionDurationScale$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$ModifierLocalScrollableContainer$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$NoOpScrollScope$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$awaitScrollEvent$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$mouseWheelScroll$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$2$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$pointerScrollable$3$1;
-Landroidx/compose/foundation/gestures/ScrollableKt$scrollable$2;
-Landroidx/compose/foundation/gestures/ScrollableKt$scrollableNestedScrollConnection$1;
-Landroidx/compose/foundation/gestures/ScrollableKt;
-Landroidx/compose/foundation/gestures/ScrollableState;
-Landroidx/compose/foundation/gestures/ScrollableStateKt;
-Landroidx/compose/foundation/gestures/ScrollingLogic;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$NoPressGesture$1;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$awaitFirstDown$2;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$1;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$2;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1$4;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2$1;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapAndPress$2;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$1;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$3;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$5;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt$waitForUpOrCancellation$2;
-Landroidx/compose/foundation/gestures/TapGestureDetectorKt;
-Landroidx/compose/foundation/gestures/UpdatableAnimationState$Companion;
-Landroidx/compose/foundation/gestures/UpdatableAnimationState;
-Landroidx/compose/foundation/interaction/DragInteraction$Start;
-Landroidx/compose/foundation/interaction/FocusInteraction$Focus;
-Landroidx/compose/foundation/interaction/HoverInteraction$Enter;
-Landroidx/compose/foundation/interaction/Interaction;
-Landroidx/compose/foundation/interaction/InteractionSource;
-Landroidx/compose/foundation/interaction/InteractionSourceKt;
-Landroidx/compose/foundation/interaction/MutableInteractionSource;
-Landroidx/compose/foundation/interaction/MutableInteractionSourceImpl;
-Landroidx/compose/foundation/interaction/PressInteraction$Press;
-Landroidx/compose/foundation/interaction/PressInteraction$Release;
-Landroidx/compose/foundation/layout/AndroidWindowInsets;
-Landroidx/compose/foundation/layout/Arrangement$Bottom$1;
-Landroidx/compose/foundation/layout/Arrangement$Center$1;
-Landroidx/compose/foundation/layout/Arrangement$End$1;
-Landroidx/compose/foundation/layout/Arrangement$Horizontal;
-Landroidx/compose/foundation/layout/Arrangement$HorizontalOrVertical;
-Landroidx/compose/foundation/layout/Arrangement$SpaceAround$1;
-Landroidx/compose/foundation/layout/Arrangement$SpaceBetween$1;
-Landroidx/compose/foundation/layout/Arrangement$SpaceEvenly$1;
-Landroidx/compose/foundation/layout/Arrangement$SpacedAligned;
-Landroidx/compose/foundation/layout/Arrangement$Start$1;
-Landroidx/compose/foundation/layout/Arrangement$Top$1;
-Landroidx/compose/foundation/layout/Arrangement$Vertical;
-Landroidx/compose/foundation/layout/Arrangement$spacedBy$1;
-Landroidx/compose/foundation/layout/Arrangement;
-Landroidx/compose/foundation/layout/BoxChildData;
-Landroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1$measure$1;
-Landroidx/compose/foundation/layout/BoxKt$EmptyBoxMeasurePolicy$1;
-Landroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$2;
-Landroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1$measure$5;
-Landroidx/compose/foundation/layout/BoxKt$boxMeasurePolicy$1;
-Landroidx/compose/foundation/layout/BoxKt;
-Landroidx/compose/foundation/layout/BoxScope;
-Landroidx/compose/foundation/layout/BoxScopeInstance;
-Landroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1;
-Landroidx/compose/foundation/layout/BoxWithConstraintsKt$BoxWithConstraints$1$1;
-Landroidx/compose/foundation/layout/BoxWithConstraintsKt;
-Landroidx/compose/foundation/layout/BoxWithConstraintsScope;
-Landroidx/compose/foundation/layout/BoxWithConstraintsScopeImpl;
-Landroidx/compose/foundation/layout/ColumnKt$DefaultColumnMeasurePolicy$1;
-Landroidx/compose/foundation/layout/ColumnKt$columnMeasurePolicy$1$1;
-Landroidx/compose/foundation/layout/ColumnKt;
-Landroidx/compose/foundation/layout/ColumnScope;
-Landroidx/compose/foundation/layout/ColumnScopeInstance;
-Landroidx/compose/foundation/layout/CrossAxisAlignment$CenterCrossAxisAlignment;
-Landroidx/compose/foundation/layout/CrossAxisAlignment$Companion;
-Landroidx/compose/foundation/layout/CrossAxisAlignment$EndCrossAxisAlignment;
-Landroidx/compose/foundation/layout/CrossAxisAlignment$HorizontalCrossAxisAlignment;
-Landroidx/compose/foundation/layout/CrossAxisAlignment$StartCrossAxisAlignment;
-Landroidx/compose/foundation/layout/CrossAxisAlignment$VerticalCrossAxisAlignment;
-Landroidx/compose/foundation/layout/CrossAxisAlignment;
-Landroidx/compose/foundation/layout/Direction;
-Landroidx/compose/foundation/layout/ExcludeInsets;
-Landroidx/compose/foundation/layout/FillModifier$measure$1;
-Landroidx/compose/foundation/layout/FillModifier;
-Landroidx/compose/foundation/layout/FixedIntInsets;
-Landroidx/compose/foundation/layout/InsetsListener;
-Landroidx/compose/foundation/layout/InsetsPaddingModifier$measure$1;
-Landroidx/compose/foundation/layout/InsetsPaddingModifier;
-Landroidx/compose/foundation/layout/InsetsValues;
-Landroidx/compose/foundation/layout/LayoutOrientation;
-Landroidx/compose/foundation/layout/LayoutWeightImpl;
-Landroidx/compose/foundation/layout/LimitInsets;
-Landroidx/compose/foundation/layout/OffsetKt;
-Landroidx/compose/foundation/layout/OffsetPxModifier$measure$1;
-Landroidx/compose/foundation/layout/OffsetPxModifier;
-Landroidx/compose/foundation/layout/OrientationIndependentConstraints;
-Landroidx/compose/foundation/layout/PaddingKt;
-Landroidx/compose/foundation/layout/PaddingModifier$measure$1;
-Landroidx/compose/foundation/layout/PaddingModifier;
-Landroidx/compose/foundation/layout/PaddingValues;
-Landroidx/compose/foundation/layout/PaddingValuesImpl;
-Landroidx/compose/foundation/layout/PaddingValuesModifier$measure$2;
-Landroidx/compose/foundation/layout/PaddingValuesModifier;
-Landroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1$measure$1;
-Landroidx/compose/foundation/layout/RowColumnImplKt$rowColumnMeasurePolicy$1;
-Landroidx/compose/foundation/layout/RowColumnImplKt;
-Landroidx/compose/foundation/layout/RowColumnMeasureHelperResult;
-Landroidx/compose/foundation/layout/RowColumnMeasurementHelper;
-Landroidx/compose/foundation/layout/RowColumnParentData;
-Landroidx/compose/foundation/layout/RowKt$DefaultRowMeasurePolicy$1;
-Landroidx/compose/foundation/layout/RowKt$rowMeasurePolicy$1$1;
-Landroidx/compose/foundation/layout/RowKt;
-Landroidx/compose/foundation/layout/RowScope;
-Landroidx/compose/foundation/layout/RowScopeInstance;
-Landroidx/compose/foundation/layout/SizeKt$createFillHeightModifier$1;
-Landroidx/compose/foundation/layout/SizeKt$createFillSizeModifier$1;
-Landroidx/compose/foundation/layout/SizeKt$createFillWidthModifier$1;
-Landroidx/compose/foundation/layout/SizeKt$createWrapContentHeightModifier$1;
-Landroidx/compose/foundation/layout/SizeKt$createWrapContentHeightModifier$2;
-Landroidx/compose/foundation/layout/SizeKt$createWrapContentSizeModifier$1;
-Landroidx/compose/foundation/layout/SizeKt$createWrapContentSizeModifier$2;
-Landroidx/compose/foundation/layout/SizeKt$createWrapContentWidthModifier$1;
-Landroidx/compose/foundation/layout/SizeKt$createWrapContentWidthModifier$2;
-Landroidx/compose/foundation/layout/SizeKt;
-Landroidx/compose/foundation/layout/SizeMode;
-Landroidx/compose/foundation/layout/SizeModifier$measure$1;
-Landroidx/compose/foundation/layout/SizeModifier;
-Landroidx/compose/foundation/layout/SpacerKt;
-Landroidx/compose/foundation/layout/SpacerMeasurePolicy$measure$1$1;
-Landroidx/compose/foundation/layout/SpacerMeasurePolicy;
-Landroidx/compose/foundation/layout/UnionInsets;
-Landroidx/compose/foundation/layout/UnspecifiedConstraintsModifier$measure$1;
-Landroidx/compose/foundation/layout/UnspecifiedConstraintsModifier;
-Landroidx/compose/foundation/layout/ValueInsets;
-Landroidx/compose/foundation/layout/WindowInsets$Companion;
-Landroidx/compose/foundation/layout/WindowInsets;
-Landroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/layout/WindowInsetsHolder$Companion$current$1;
-Landroidx/compose/foundation/layout/WindowInsetsHolder$Companion;
-Landroidx/compose/foundation/layout/WindowInsetsHolder;
-Landroidx/compose/foundation/layout/WindowInsetsKt;
-Landroidx/compose/foundation/layout/WindowInsetsPaddingKt$ModifierLocalConsumedWindowInsets$1;
-Landroidx/compose/foundation/layout/WindowInsetsPaddingKt;
-Landroidx/compose/foundation/layout/WindowInsetsSides$Companion;
-Landroidx/compose/foundation/layout/WindowInsetsSides;
-Landroidx/compose/foundation/layout/WindowInsets_androidKt;
-Landroidx/compose/foundation/layout/WrapContentModifier$measure$1;
-Landroidx/compose/foundation/layout/WrapContentModifier;
-Landroidx/compose/foundation/lazy/AwaitFirstLayoutModifier;
-Landroidx/compose/foundation/lazy/DataIndex;
-Landroidx/compose/foundation/lazy/EmptyLazyListLayoutInfo;
-Landroidx/compose/foundation/lazy/LazyBeyondBoundsModifierKt;
-Landroidx/compose/foundation/lazy/LazyDslKt;
-Landroidx/compose/foundation/lazy/LazyItemScope;
-Landroidx/compose/foundation/lazy/LazyItemScopeImpl;
-Landroidx/compose/foundation/lazy/LazyListAnimateScrollScope;
-Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo$Interval;
-Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo;
-Landroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal$Companion$emptyBeyondBoundsScope$1;
-Landroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal$Companion;
-Landroidx/compose/foundation/lazy/LazyListBeyondBoundsModifierLocal;
-Landroidx/compose/foundation/lazy/LazyListIntervalContent;
-Landroidx/compose/foundation/lazy/LazyListItemInfo;
-Landroidx/compose/foundation/lazy/LazyListItemPlacementAnimator;
-Landroidx/compose/foundation/lazy/LazyListItemProvider;
-Landroidx/compose/foundation/lazy/LazyListItemProviderImpl$1$1;
-Landroidx/compose/foundation/lazy/LazyListItemProviderImpl$1;
-Landroidx/compose/foundation/lazy/LazyListItemProviderImpl;
-Landroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$1;
-Landroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$1$itemProviderState$1;
-Landroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$1$1;
-Landroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$2;
-Landroidx/compose/foundation/lazy/LazyListItemProviderKt$rememberLazyListItemProvider$nearestItemsRangeState$3;
-Landroidx/compose/foundation/lazy/LazyListItemProviderKt;
-Landroidx/compose/foundation/lazy/LazyListKt$ScrollPositionUpdater$1;
-Landroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$2;
-Landroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1$measuredItemProvider$1;
-Landroidx/compose/foundation/lazy/LazyListKt$rememberLazyListMeasurePolicy$1$1;
-Landroidx/compose/foundation/lazy/LazyListKt;
-Landroidx/compose/foundation/lazy/LazyListLayoutInfo;
-Landroidx/compose/foundation/lazy/LazyListMeasureKt$measureLazyList$5;
-Landroidx/compose/foundation/lazy/LazyListMeasureKt;
-Landroidx/compose/foundation/lazy/LazyListMeasureResult;
-Landroidx/compose/foundation/lazy/LazyListPlaceableWrapper;
-Landroidx/compose/foundation/lazy/LazyListPositionedItem;
-Landroidx/compose/foundation/lazy/LazyListScope;
-Landroidx/compose/foundation/lazy/LazyListScopeImpl$item$2;
-Landroidx/compose/foundation/lazy/LazyListScopeImpl$item$3;
-Landroidx/compose/foundation/lazy/LazyListScopeImpl;
-Landroidx/compose/foundation/lazy/LazyListScrollPosition;
-Landroidx/compose/foundation/lazy/LazyListState$Companion$Saver$1;
-Landroidx/compose/foundation/lazy/LazyListState$Companion$Saver$2;
-Landroidx/compose/foundation/lazy/LazyListState$Companion;
-Landroidx/compose/foundation/lazy/LazyListState$remeasurementModifier$1;
-Landroidx/compose/foundation/lazy/LazyListState$scrollableState$1;
-Landroidx/compose/foundation/lazy/LazyListState;
-Landroidx/compose/foundation/lazy/LazyListStateKt$rememberLazyListState$1$1;
-Landroidx/compose/foundation/lazy/LazyListStateKt;
-Landroidx/compose/foundation/lazy/LazyMeasuredItem;
-Landroidx/compose/foundation/lazy/LazyMeasuredItemProvider;
-Landroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1$scrollAxisRange$1;
-Landroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1$scrollAxisRange$2;
-Landroidx/compose/foundation/lazy/LazySemanticsKt$rememberLazyListSemanticState$1$1;
-Landroidx/compose/foundation/lazy/LazySemanticsKt;
-Landroidx/compose/foundation/lazy/MeasuredItemFactory;
-Landroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider$Item$1;
-Landroidx/compose/foundation/lazy/layout/DefaultDelegatingLazyLayoutItemProvider;
-Landroidx/compose/foundation/lazy/layout/DefaultLazyKey$Companion$CREATOR$1;
-Landroidx/compose/foundation/lazy/layout/DefaultLazyKey$Companion;
-Landroidx/compose/foundation/lazy/layout/DefaultLazyKey;
-Landroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider$generateKeyToIndexMap$1$1;
-Landroidx/compose/foundation/lazy/layout/DefaultLazyLayoutItemsProvider;
-Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;
-Landroidx/compose/foundation/lazy/layout/IntervalList;
-Landroidx/compose/foundation/lazy/layout/IntervalListKt;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutIntervalContent;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1$2;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent$createContentLambda$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory$CachedItemContent;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemContentFactory;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProvider;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemProviderKt;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutItemReusePolicy;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$2$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1$itemContentFactory$1$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutKt$LazyLayout$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutKt;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScope;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutMeasureScopeImpl;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItem;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt$LazyLayoutPinnableItem$1$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnableItemKt;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList$PinnedItem;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPinnedItemList;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState$PrefetchHandle;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState$Prefetcher;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetchState;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$Companion;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$PrefetchRequest;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher_androidKt;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticState;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$indexForKeyMapping$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$scrollByAction$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt$lazyLayoutSemantics$1$scrollToIndexAction$1;
-Landroidx/compose/foundation/lazy/layout/LazyLayoutSemanticsKt;
-Landroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$1;
-Landroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1$2;
-Landroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt$rememberLazyNearestItemsRangeState$1$1;
-Landroidx/compose/foundation/lazy/layout/LazyNearestItemsRangeKt;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$1;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$1;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion$saver$2;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$Companion;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$1;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder$SaveableStateProvider$2;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolder;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$1;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt$LazySaveableStateHolderProvider$holder$1;
-Landroidx/compose/foundation/lazy/layout/LazySaveableStateHolderKt;
-Landroidx/compose/foundation/lazy/layout/Lazy_androidKt;
-Landroidx/compose/foundation/lazy/layout/MutableIntervalList;
-Landroidx/compose/foundation/relocation/AndroidBringIntoViewParent;
-Landroidx/compose/foundation/relocation/BringIntoViewChildModifier;
-Landroidx/compose/foundation/relocation/BringIntoViewKt$ModifierLocalBringIntoViewParent$1;
-Landroidx/compose/foundation/relocation/BringIntoViewKt;
-Landroidx/compose/foundation/relocation/BringIntoViewParent;
-Landroidx/compose/foundation/relocation/BringIntoViewRequester;
-Landroidx/compose/foundation/relocation/BringIntoViewRequesterImpl;
-Landroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2$1;
-Landroidx/compose/foundation/relocation/BringIntoViewRequesterKt$bringIntoViewRequester$2;
-Landroidx/compose/foundation/relocation/BringIntoViewRequesterKt;
-Landroidx/compose/foundation/relocation/BringIntoViewRequesterModifier;
-Landroidx/compose/foundation/relocation/BringIntoViewResponder;
-Landroidx/compose/foundation/relocation/BringIntoViewResponderKt$bringIntoViewResponder$2;
-Landroidx/compose/foundation/relocation/BringIntoViewResponderKt;
-Landroidx/compose/foundation/relocation/BringIntoViewResponderModifier;
-Landroidx/compose/foundation/relocation/BringIntoViewResponder_androidKt;
-Landroidx/compose/foundation/shape/CornerBasedShape;
-Landroidx/compose/foundation/shape/CornerSize;
-Landroidx/compose/foundation/shape/CornerSizeKt$ZeroCornerSize$1;
-Landroidx/compose/foundation/shape/CornerSizeKt;
-Landroidx/compose/foundation/shape/DpCornerSize;
-Landroidx/compose/foundation/shape/PercentCornerSize;
-Landroidx/compose/foundation/shape/RoundedCornerShape;
-Landroidx/compose/foundation/shape/RoundedCornerShapeKt;
-Landroidx/compose/foundation/text/BasicTextKt$BasicText-4YKlhWE$$inlined$Layout$1;
-Landroidx/compose/foundation/text/BasicTextKt;
-Landroidx/compose/foundation/text/CoreTextKt;
-Landroidx/compose/foundation/text/HeightInLinesModifierKt$heightInLines$2;
-Landroidx/compose/foundation/text/HeightInLinesModifierKt;
-Landroidx/compose/foundation/text/TextController$coreModifiers$1;
-Landroidx/compose/foundation/text/TextController$createSemanticsModifierFor$1$1;
-Landroidx/compose/foundation/text/TextController$createSemanticsModifierFor$1;
-Landroidx/compose/foundation/text/TextController$drawTextAndSelectionBehind$1;
-Landroidx/compose/foundation/text/TextController$measurePolicy$1$measure$2;
-Landroidx/compose/foundation/text/TextController$measurePolicy$1;
-Landroidx/compose/foundation/text/TextController;
-Landroidx/compose/foundation/text/TextDelegate$Companion;
-Landroidx/compose/foundation/text/TextDelegate;
-Landroidx/compose/foundation/text/TextDelegateKt;
-Landroidx/compose/foundation/text/TextLayoutHelperKt;
-Landroidx/compose/foundation/text/TextState$onTextLayout$1;
-Landroidx/compose/foundation/text/TextState;
-Landroidx/compose/foundation/text/selection/SelectionRegistrarKt$LocalSelectionRegistrar$1;
-Landroidx/compose/foundation/text/selection/SelectionRegistrarKt;
-Landroidx/compose/foundation/text/selection/TextSelectionColors;
-Landroidx/compose/foundation/text/selection/TextSelectionColorsKt$LocalTextSelectionColors$1;
-Landroidx/compose/foundation/text/selection/TextSelectionColorsKt;
-Landroidx/compose/material/icons/Icons$Filled;
-Landroidx/compose/material/icons/Icons$Outlined;
-Landroidx/compose/material/icons/filled/ArrowBackKt;
-Landroidx/compose/material/icons/filled/CloseKt;
-Landroidx/compose/material/icons/outlined/LockKt;
-Landroidx/compose/material/icons/outlined/QrCodeScannerKt;
-Landroidx/compose/material/ripple/AndroidRippleIndicationInstance$onInvalidateRipple$1;
-Landroidx/compose/material/ripple/AndroidRippleIndicationInstance;
-Landroidx/compose/material/ripple/PlatformRipple;
-Landroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1$1;
-Landroidx/compose/material/ripple/Ripple$rememberUpdatedInstance$1;
-Landroidx/compose/material/ripple/Ripple;
-Landroidx/compose/material/ripple/RippleAlpha;
-Landroidx/compose/material/ripple/RippleAnimationKt;
-Landroidx/compose/material/ripple/RippleContainer;
-Landroidx/compose/material/ripple/RippleHostMap;
-Landroidx/compose/material/ripple/RippleHostView$$ExternalSyntheticLambda0;
-Landroidx/compose/material/ripple/RippleHostView$Companion;
-Landroidx/compose/material/ripple/RippleHostView;
-Landroidx/compose/material/ripple/RippleIndicationInstance;
-Landroidx/compose/material/ripple/RippleKt;
-Landroidx/compose/material/ripple/RippleTheme;
-Landroidx/compose/material/ripple/RippleThemeKt$LocalRippleTheme$1;
-Landroidx/compose/material/ripple/RippleThemeKt;
-Landroidx/compose/material/ripple/StateLayer;
-Landroidx/compose/material/ripple/UnprojectedRipple$Companion;
-Landroidx/compose/material/ripple/UnprojectedRipple$MRadiusHelper;
-Landroidx/compose/material/ripple/UnprojectedRipple;
-Landroidx/compose/material3/AppBarKt$SingleRowTopAppBar$1$1;
-Landroidx/compose/material3/AppBarKt$SingleRowTopAppBar$2;
-Landroidx/compose/material3/AppBarKt$SingleRowTopAppBar$3;
-Landroidx/compose/material3/AppBarKt$SingleRowTopAppBar$actionsRow$1;
-Landroidx/compose/material3/AppBarKt$TopAppBarLayout$1$3$1;
-Landroidx/compose/material3/AppBarKt$TopAppBarLayout$2$measure$1;
-Landroidx/compose/material3/AppBarKt$TopAppBarLayout$2;
-Landroidx/compose/material3/AppBarKt;
-Landroidx/compose/material3/ButtonColors;
-Landroidx/compose/material3/ButtonDefaults;
-Landroidx/compose/material3/ButtonElevation$animateElevation$1$1$1;
-Landroidx/compose/material3/ButtonElevation$animateElevation$1$1;
-Landroidx/compose/material3/ButtonElevation$animateElevation$3;
-Landroidx/compose/material3/ButtonElevation;
-Landroidx/compose/material3/ButtonKt$Button$2$1$1;
-Landroidx/compose/material3/ButtonKt$Button$2$1;
-Landroidx/compose/material3/ButtonKt$Button$2;
-Landroidx/compose/material3/ButtonKt$Button$3;
-Landroidx/compose/material3/ButtonKt$TextButton$2;
-Landroidx/compose/material3/ButtonKt;
-Landroidx/compose/material3/CardColors;
-Landroidx/compose/material3/CardDefaults;
-Landroidx/compose/material3/CardElevation;
-Landroidx/compose/material3/CardKt$Card$1;
-Landroidx/compose/material3/CardKt$Card$2;
-Landroidx/compose/material3/CardKt;
-Landroidx/compose/material3/ChipBorder;
-Landroidx/compose/material3/ChipColors;
-Landroidx/compose/material3/ChipElevation$animateElevation$1$1$1;
-Landroidx/compose/material3/ChipElevation$animateElevation$1$1;
-Landroidx/compose/material3/ChipElevation$animateElevation$3;
-Landroidx/compose/material3/ChipElevation;
-Landroidx/compose/material3/ChipKt$Chip$1;
-Landroidx/compose/material3/ChipKt$Chip$2;
-Landroidx/compose/material3/ChipKt$ChipContent$1;
-Landroidx/compose/material3/ChipKt$SuggestionChip$2;
-Landroidx/compose/material3/ChipKt;
-Landroidx/compose/material3/ColorResourceHelper;
-Landroidx/compose/material3/ColorScheme;
-Landroidx/compose/material3/ColorSchemeKt$LocalColorScheme$1;
-Landroidx/compose/material3/ColorSchemeKt$WhenMappings;
-Landroidx/compose/material3/ColorSchemeKt;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-1$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-10$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-11$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-12$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-2$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-3$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-4$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-5$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-6$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-7$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-8$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt$lambda-9$1;
-Landroidx/compose/material3/ComposableSingletons$AppBarKt;
-Landroidx/compose/material3/ContentColorKt$LocalContentColor$1;
-Landroidx/compose/material3/ContentColorKt;
-Landroidx/compose/material3/DividerKt;
-Landroidx/compose/material3/DynamicTonalPaletteKt;
-Landroidx/compose/material3/ElevationDefaults;
-Landroidx/compose/material3/ElevationKt;
-Landroidx/compose/material3/IconButtonColors;
-Landroidx/compose/material3/IconButtonDefaults;
-Landroidx/compose/material3/IconButtonKt$IconButton$3;
-Landroidx/compose/material3/IconButtonKt;
-Landroidx/compose/material3/IconKt$Icon$3;
-Landroidx/compose/material3/IconKt$Icon$semantics$1$1;
-Landroidx/compose/material3/IconKt;
-Landroidx/compose/material3/InteractiveComponentSizeKt$LocalMinimumInteractiveComponentEnforcement$1;
-Landroidx/compose/material3/InteractiveComponentSizeKt$minimumInteractiveComponentSize$2;
-Landroidx/compose/material3/InteractiveComponentSizeKt;
-Landroidx/compose/material3/MaterialRippleTheme;
-Landroidx/compose/material3/MaterialTheme;
-Landroidx/compose/material3/MaterialThemeKt$MaterialTheme$1;
-Landroidx/compose/material3/MaterialThemeKt$MaterialTheme$2;
-Landroidx/compose/material3/MaterialThemeKt;
-Landroidx/compose/material3/MinimumInteractiveComponentSizeModifier$measure$1;
-Landroidx/compose/material3/MinimumInteractiveComponentSizeModifier;
-Landroidx/compose/material3/ShapeDefaults;
-Landroidx/compose/material3/Shapes;
-Landroidx/compose/material3/ShapesKt$LocalShapes$1;
-Landroidx/compose/material3/ShapesKt$WhenMappings;
-Landroidx/compose/material3/ShapesKt;
-Landroidx/compose/material3/SuggestionChipDefaults;
-Landroidx/compose/material3/SurfaceKt$LocalAbsoluteTonalElevation$1;
-Landroidx/compose/material3/SurfaceKt$Surface$1$1;
-Landroidx/compose/material3/SurfaceKt$Surface$1$2;
-Landroidx/compose/material3/SurfaceKt$Surface$1;
-Landroidx/compose/material3/SurfaceKt$Surface$3;
-Landroidx/compose/material3/SurfaceKt;
-Landroidx/compose/material3/SystemBarsDefaultInsets_androidKt;
-Landroidx/compose/material3/TextKt$LocalTextStyle$1;
-Landroidx/compose/material3/TextKt$ProvideTextStyle$1;
-Landroidx/compose/material3/TextKt$Text$1;
-Landroidx/compose/material3/TextKt$Text$2;
-Landroidx/compose/material3/TextKt;
-Landroidx/compose/material3/TonalPalette;
-Landroidx/compose/material3/TopAppBarColors;
-Landroidx/compose/material3/TopAppBarDefaults;
-Landroidx/compose/material3/Typography;
-Landroidx/compose/material3/TypographyKt$LocalTypography$1;
-Landroidx/compose/material3/TypographyKt$WhenMappings;
-Landroidx/compose/material3/TypographyKt;
-Landroidx/compose/material3/tokens/ColorDarkTokens;
-Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-Landroidx/compose/material3/tokens/ElevationTokens;
-Landroidx/compose/material3/tokens/FilledButtonTokens;
-Landroidx/compose/material3/tokens/FilledCardTokens;
-Landroidx/compose/material3/tokens/FilledTonalButtonTokens;
-Landroidx/compose/material3/tokens/IconButtonTokens;
-Landroidx/compose/material3/tokens/PaletteTokens;
-Landroidx/compose/material3/tokens/ShapeKeyTokens;
-Landroidx/compose/material3/tokens/ShapeTokens;
-Landroidx/compose/material3/tokens/SuggestionChipTokens;
-Landroidx/compose/material3/tokens/TextButtonTokens;
-Landroidx/compose/material3/tokens/TopAppBarSmallTokens;
-Landroidx/compose/material3/tokens/TypographyKeyTokens;
-Landroidx/compose/runtime/AbstractApplier;
-Landroidx/compose/runtime/ActualAndroid_androidKt$DefaultMonotonicFrameClock$2;
-Landroidx/compose/runtime/ActualAndroid_androidKt;
-Landroidx/compose/runtime/ActualJvm_jvmKt;
-Landroidx/compose/runtime/Anchor;
-Landroidx/compose/runtime/Applier;
-Landroidx/compose/runtime/BroadcastFrameClock$FrameAwaiter;
-Landroidx/compose/runtime/BroadcastFrameClock$withFrameNanos$2$1;
-Landroidx/compose/runtime/BroadcastFrameClock;
-Landroidx/compose/runtime/ComposableSingletons$CompositionKt$lambda-1$1;
-Landroidx/compose/runtime/ComposableSingletons$CompositionKt$lambda-2$1;
-Landroidx/compose/runtime/ComposableSingletons$CompositionKt;
-Landroidx/compose/runtime/ComposablesKt;
-Landroidx/compose/runtime/Composer$Companion$Empty$1;
-Landroidx/compose/runtime/Composer$Companion;
-Landroidx/compose/runtime/Composer;
-Landroidx/compose/runtime/ComposerImpl$CompositionContextHolder;
-Landroidx/compose/runtime/ComposerImpl$CompositionContextImpl;
-Landroidx/compose/runtime/ComposerImpl$apply$operation$1;
-Landroidx/compose/runtime/ComposerImpl$createNode$2;
-Landroidx/compose/runtime/ComposerImpl$createNode$3;
-Landroidx/compose/runtime/ComposerImpl$doCompose$2$3;
-Landroidx/compose/runtime/ComposerImpl$doCompose$2$4;
-Landroidx/compose/runtime/ComposerImpl$doCompose$2$5;
-Landroidx/compose/runtime/ComposerImpl$doCompose$lambda$37$$inlined$sortBy$1;
-Landroidx/compose/runtime/ComposerImpl$endRestartGroup$1$1;
-Landroidx/compose/runtime/ComposerImpl$realizeDowns$1;
-Landroidx/compose/runtime/ComposerImpl$realizeMovement$1;
-Landroidx/compose/runtime/ComposerImpl$realizeOperationLocation$2;
-Landroidx/compose/runtime/ComposerImpl$realizeUps$1;
-Landroidx/compose/runtime/ComposerImpl$recordInsert$1;
-Landroidx/compose/runtime/ComposerImpl$recordInsert$2;
-Landroidx/compose/runtime/ComposerImpl$recordSideEffect$1;
-Landroidx/compose/runtime/ComposerImpl$recordSlotEditing$1;
-Landroidx/compose/runtime/ComposerImpl$start$2;
-Landroidx/compose/runtime/ComposerImpl$startProviders$currentProviders$1;
-Landroidx/compose/runtime/ComposerImpl$startReaderGroup$1;
-Landroidx/compose/runtime/ComposerImpl$updateValue$1;
-Landroidx/compose/runtime/ComposerImpl$updateValue$2;
-Landroidx/compose/runtime/ComposerImpl;
-Landroidx/compose/runtime/ComposerKt$endGroupInstance$1;
-Landroidx/compose/runtime/ComposerKt$removeCurrentGroupInstance$1;
-Landroidx/compose/runtime/ComposerKt$resetSlotsInstance$1;
-Landroidx/compose/runtime/ComposerKt$skipToGroupEndInstance$1;
-Landroidx/compose/runtime/ComposerKt$startRootGroup$1;
-Landroidx/compose/runtime/ComposerKt;
-Landroidx/compose/runtime/Composition;
-Landroidx/compose/runtime/CompositionContext;
-Landroidx/compose/runtime/CompositionContextKt;
-Landroidx/compose/runtime/CompositionImpl$RememberEventDispatcher;
-Landroidx/compose/runtime/CompositionImpl;
-Landroidx/compose/runtime/CompositionKt;
-Landroidx/compose/runtime/CompositionLocal;
-Landroidx/compose/runtime/CompositionLocalKt;
-Landroidx/compose/runtime/CompositionScopedCoroutineScopeCanceller;
-Landroidx/compose/runtime/ControlledComposition;
-Landroidx/compose/runtime/DerivedSnapshotState$ResultRecord$Companion;
-Landroidx/compose/runtime/DerivedSnapshotState$ResultRecord;
-Landroidx/compose/runtime/DerivedSnapshotState$currentRecord$result$1$result$1;
-Landroidx/compose/runtime/DerivedSnapshotState;
-Landroidx/compose/runtime/DerivedState;
-Landroidx/compose/runtime/DisposableEffectImpl;
-Landroidx/compose/runtime/DisposableEffectResult;
-Landroidx/compose/runtime/DisposableEffectScope;
-Landroidx/compose/runtime/DynamicProvidableCompositionLocal;
-Landroidx/compose/runtime/EffectsKt;
-Landroidx/compose/runtime/GroupInfo;
-Landroidx/compose/runtime/GroupKind$Companion;
-Landroidx/compose/runtime/GroupKind;
-Landroidx/compose/runtime/IntStack;
-Landroidx/compose/runtime/Invalidation;
-Landroidx/compose/runtime/InvalidationResult;
-Landroidx/compose/runtime/KeyInfo;
-Landroidx/compose/runtime/Latch;
-Landroidx/compose/runtime/LaunchedEffectImpl;
-Landroidx/compose/runtime/LazyValueHolder;
-Landroidx/compose/runtime/MonotonicFrameClock$DefaultImpls;
-Landroidx/compose/runtime/MonotonicFrameClock$Key;
-Landroidx/compose/runtime/MonotonicFrameClock;
-Landroidx/compose/runtime/MonotonicFrameClockKt;
-Landroidx/compose/runtime/MutableState;
-Landroidx/compose/runtime/NeverEqualPolicy;
-Landroidx/compose/runtime/OpaqueKey;
-Landroidx/compose/runtime/ParcelableSnapshotMutableState$Companion$CREATOR$1;
-Landroidx/compose/runtime/ParcelableSnapshotMutableState$Companion;
-Landroidx/compose/runtime/ParcelableSnapshotMutableState;
-Landroidx/compose/runtime/PausableMonotonicFrameClock$withFrameNanos$1;
-Landroidx/compose/runtime/PausableMonotonicFrameClock;
-Landroidx/compose/runtime/Pending$keyMap$2;
-Landroidx/compose/runtime/Pending;
-Landroidx/compose/runtime/PrioritySet;
-Landroidx/compose/runtime/ProvidableCompositionLocal;
-Landroidx/compose/runtime/ProvidedValue;
-Landroidx/compose/runtime/RecomposeScope;
-Landroidx/compose/runtime/RecomposeScopeImpl$end$1$2;
-Landroidx/compose/runtime/RecomposeScopeImpl;
-Landroidx/compose/runtime/RecomposeScopeImplKt;
-Landroidx/compose/runtime/Recomposer$Companion;
-Landroidx/compose/runtime/Recomposer$RecomposerErrorState;
-Landroidx/compose/runtime/Recomposer$RecomposerInfoImpl;
-Landroidx/compose/runtime/Recomposer$State;
-Landroidx/compose/runtime/Recomposer$broadcastFrameClock$1;
-Landroidx/compose/runtime/Recomposer$effectJob$1$1$1$1;
-Landroidx/compose/runtime/Recomposer$effectJob$1$1;
-Landroidx/compose/runtime/Recomposer$join$2;
-Landroidx/compose/runtime/Recomposer$performRecompose$1$1;
-Landroidx/compose/runtime/Recomposer$readObserverOf$1;
-Landroidx/compose/runtime/Recomposer$recompositionRunner$2$2;
-Landroidx/compose/runtime/Recomposer$recompositionRunner$2$unregisterApplyObserver$1;
-Landroidx/compose/runtime/Recomposer$recompositionRunner$2;
-Landroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2$2;
-Landroidx/compose/runtime/Recomposer$runRecomposeAndApplyChanges$2;
-Landroidx/compose/runtime/Recomposer$writeObserverOf$1;
-Landroidx/compose/runtime/Recomposer;
-Landroidx/compose/runtime/ReferentialEqualityPolicy;
-Landroidx/compose/runtime/RememberManager;
-Landroidx/compose/runtime/RememberObserver;
-Landroidx/compose/runtime/ScopeUpdateScope;
-Landroidx/compose/runtime/SkippableUpdater;
-Landroidx/compose/runtime/SlotReader;
-Landroidx/compose/runtime/SlotTable;
-Landroidx/compose/runtime/SlotTableKt;
-Landroidx/compose/runtime/SlotWriter$Companion;
-Landroidx/compose/runtime/SlotWriter$groupSlots$1;
-Landroidx/compose/runtime/SlotWriter;
-Landroidx/compose/runtime/SnapshotMutableStateImpl$StateStateRecord;
-Landroidx/compose/runtime/SnapshotMutableStateImpl;
-Landroidx/compose/runtime/SnapshotMutationPolicy;
-Landroidx/compose/runtime/SnapshotStateKt;
-Landroidx/compose/runtime/SnapshotStateKt__DerivedStateKt;
-Landroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$readObserver$1;
-Landroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1$unregisterApplyObserver$1;
-Landroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1;
-Landroidx/compose/runtime/SnapshotStateKt__SnapshotFlowKt;
-Landroidx/compose/runtime/SnapshotStateKt__SnapshotMutationPolicyKt;
-Landroidx/compose/runtime/SnapshotStateKt__SnapshotStateKt;
-Landroidx/compose/runtime/SnapshotThreadLocal;
-Landroidx/compose/runtime/Stack;
-Landroidx/compose/runtime/State;
-Landroidx/compose/runtime/StaticProvidableCompositionLocal;
-Landroidx/compose/runtime/StaticValueHolder;
-Landroidx/compose/runtime/StructuralEqualityPolicy;
-Landroidx/compose/runtime/Trace;
-Landroidx/compose/runtime/Updater;
-Landroidx/compose/runtime/collection/IdentityArrayIntMap;
-Landroidx/compose/runtime/collection/IdentityArrayMap;
-Landroidx/compose/runtime/collection/IdentityArraySet$iterator$1;
-Landroidx/compose/runtime/collection/IdentityArraySet;
-Landroidx/compose/runtime/collection/IdentityScopeMap;
-Landroidx/compose/runtime/collection/IntMap;
-Landroidx/compose/runtime/collection/MutableVector$MutableVectorList;
-Landroidx/compose/runtime/collection/MutableVector$VectorListIterator;
-Landroidx/compose/runtime/collection/MutableVector;
-Landroidx/compose/runtime/collection/MutableVectorKt;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/ImmutableCollection;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/ImmutableList;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/ImmutableSet;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap$Builder;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/AbstractPersistentList;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/UtilsKt;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntriesIterator;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/CommonFunctionsKt;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/EndOfChain;
-Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;
-Landroidx/compose/runtime/internal/ComposableLambda;
-Landroidx/compose/runtime/internal/ComposableLambdaImpl$invoke$1;
-Landroidx/compose/runtime/internal/ComposableLambdaImpl$invoke$2;
-Landroidx/compose/runtime/internal/ComposableLambdaImpl;
-Landroidx/compose/runtime/internal/ComposableLambdaKt;
-Landroidx/compose/runtime/internal/ThreadMap;
-Landroidx/compose/runtime/internal/ThreadMapKt;
-Landroidx/compose/runtime/saveable/ListSaverKt$listSaver$1;
-Landroidx/compose/runtime/saveable/ListSaverKt;
-Landroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$valueProvider$1$1$1;
-Landroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1$valueProvider$1;
-Landroidx/compose/runtime/saveable/RememberSaveableKt$rememberSaveable$1;
-Landroidx/compose/runtime/saveable/RememberSaveableKt;
-Landroidx/compose/runtime/saveable/SaveableStateHolder;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$1;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion$Saver$2;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$Companion;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder$registry$1;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$RegistryHolder;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl$SaveableStateProvider$1$1;
-Landroidx/compose/runtime/saveable/SaveableStateHolderImpl;
-Landroidx/compose/runtime/saveable/SaveableStateHolderKt$rememberSaveableStateHolder$1;
-Landroidx/compose/runtime/saveable/SaveableStateHolderKt;
-Landroidx/compose/runtime/saveable/SaveableStateRegistry$Entry;
-Landroidx/compose/runtime/saveable/SaveableStateRegistry;
-Landroidx/compose/runtime/saveable/SaveableStateRegistryImpl$registerProvider$3;
-Landroidx/compose/runtime/saveable/SaveableStateRegistryImpl;
-Landroidx/compose/runtime/saveable/SaveableStateRegistryKt$LocalSaveableStateRegistry$1;
-Landroidx/compose/runtime/saveable/SaveableStateRegistryKt;
-Landroidx/compose/runtime/saveable/Saver;
-Landroidx/compose/runtime/saveable/SaverKt$AutoSaver$1;
-Landroidx/compose/runtime/saveable/SaverKt$AutoSaver$2;
-Landroidx/compose/runtime/saveable/SaverKt$Saver$1;
-Landroidx/compose/runtime/saveable/SaverKt;
-Landroidx/compose/runtime/saveable/SaverScope;
-Landroidx/compose/runtime/snapshots/GlobalSnapshot$1$1$1;
-Landroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedMutableSnapshot$1;
-Landroidx/compose/runtime/snapshots/GlobalSnapshot$takeNestedSnapshot$1;
-Landroidx/compose/runtime/snapshots/GlobalSnapshot;
-Landroidx/compose/runtime/snapshots/ListUtilsKt;
-Landroidx/compose/runtime/snapshots/MutableSnapshot;
-Landroidx/compose/runtime/snapshots/NestedMutableSnapshot;
-Landroidx/compose/runtime/snapshots/ObserverHandle;
-Landroidx/compose/runtime/snapshots/ReadonlySnapshot;
-Landroidx/compose/runtime/snapshots/Snapshot$Companion$registerApplyObserver$2;
-Landroidx/compose/runtime/snapshots/Snapshot$Companion$registerGlobalWriteObserver$2;
-Landroidx/compose/runtime/snapshots/Snapshot$Companion;
-Landroidx/compose/runtime/snapshots/Snapshot;
-Landroidx/compose/runtime/snapshots/SnapshotApplyResult$Failure;
-Landroidx/compose/runtime/snapshots/SnapshotApplyResult$Success;
-Landroidx/compose/runtime/snapshots/SnapshotApplyResult;
-Landroidx/compose/runtime/snapshots/SnapshotDoubleIndexHeap;
-Landroidx/compose/runtime/snapshots/SnapshotIdSet$Companion;
-Landroidx/compose/runtime/snapshots/SnapshotIdSet$iterator$1;
-Landroidx/compose/runtime/snapshots/SnapshotIdSet;
-Landroidx/compose/runtime/snapshots/SnapshotIdSetKt;
-Landroidx/compose/runtime/snapshots/SnapshotKt$advanceGlobalSnapshot$3;
-Landroidx/compose/runtime/snapshots/SnapshotKt$emptyLambda$1;
-Landroidx/compose/runtime/snapshots/SnapshotKt$mergedReadObserver$1;
-Landroidx/compose/runtime/snapshots/SnapshotKt$mergedWriteObserver$1;
-Landroidx/compose/runtime/snapshots/SnapshotKt$takeNewSnapshot$1;
-Landroidx/compose/runtime/snapshots/SnapshotKt;
-Landroidx/compose/runtime/snapshots/SnapshotMutableState;
-Landroidx/compose/runtime/snapshots/SnapshotStateList$StateListStateRecord;
-Landroidx/compose/runtime/snapshots/SnapshotStateList;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateEnterObserver$1;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap$derivedStateExitObserver$1;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$applyObserver$1;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$observeReads$1$1;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$readObserver$1;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver$sendNotifications$1;
-Landroidx/compose/runtime/snapshots/SnapshotStateObserver;
-Landroidx/compose/runtime/snapshots/StateObject;
-Landroidx/compose/runtime/snapshots/StateRecord;
-Landroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;
-Landroidx/compose/runtime/tooling/CompositionData;
-Landroidx/compose/runtime/tooling/InspectionTablesKt$LocalInspectionTables$1;
-Landroidx/compose/runtime/tooling/InspectionTablesKt;
-Landroidx/compose/ui/ActualKt;
-Landroidx/compose/ui/Alignment$Companion;
-Landroidx/compose/ui/Alignment$Horizontal;
-Landroidx/compose/ui/Alignment$Vertical;
-Landroidx/compose/ui/Alignment;
-Landroidx/compose/ui/BiasAlignment$Horizontal;
-Landroidx/compose/ui/BiasAlignment$Vertical;
-Landroidx/compose/ui/BiasAlignment;
-Landroidx/compose/ui/CombinedModifier;
-Landroidx/compose/ui/ComposedModifier;
-Landroidx/compose/ui/ComposedModifierKt$materialize$1;
-Landroidx/compose/ui/ComposedModifierKt$materialize$result$1;
-Landroidx/compose/ui/ComposedModifierKt;
-Landroidx/compose/ui/Modifier$Companion;
-Landroidx/compose/ui/Modifier$Element;
-Landroidx/compose/ui/Modifier$Node;
-Landroidx/compose/ui/Modifier;
-Landroidx/compose/ui/MotionDurationScale$DefaultImpls;
-Landroidx/compose/ui/MotionDurationScale$Key;
-Landroidx/compose/ui/MotionDurationScale;
-Landroidx/compose/ui/R$id;
-Landroidx/compose/ui/autofill/AndroidAutofill;
-Landroidx/compose/ui/autofill/Autofill;
-Landroidx/compose/ui/autofill/AutofillCallback;
-Landroidx/compose/ui/autofill/AutofillTree;
-Landroidx/compose/ui/draw/BuildDrawCacheParams;
-Landroidx/compose/ui/draw/ClipKt;
-Landroidx/compose/ui/draw/DrawBackgroundModifier;
-Landroidx/compose/ui/draw/DrawCacheModifier;
-Landroidx/compose/ui/draw/DrawModifier;
-Landroidx/compose/ui/draw/DrawModifierKt$drawBehind$$inlined$modifierElementOf$1;
-Landroidx/compose/ui/draw/DrawModifierKt;
-Landroidx/compose/ui/draw/PainterModifier$measure$1;
-Landroidx/compose/ui/draw/PainterModifier;
-Landroidx/compose/ui/draw/PainterModifierKt;
-Landroidx/compose/ui/draw/ShadowKt$shadow$2$1;
-Landroidx/compose/ui/draw/ShadowKt;
-Landroidx/compose/ui/focus/FocusChangedModifierKt$onFocusChanged$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/focus/FocusChangedModifierKt;
-Landroidx/compose/ui/focus/FocusChangedModifierNode;
-Landroidx/compose/ui/focus/FocusEventModifierNode;
-Landroidx/compose/ui/focus/FocusEventModifierNodeKt$WhenMappings;
-Landroidx/compose/ui/focus/FocusEventModifierNodeKt;
-Landroidx/compose/ui/focus/FocusInvalidationManager$invalidateNodes$1;
-Landroidx/compose/ui/focus/FocusInvalidationManager;
-Landroidx/compose/ui/focus/FocusManager;
-Landroidx/compose/ui/focus/FocusModifierKt;
-Landroidx/compose/ui/focus/FocusOwner;
-Landroidx/compose/ui/focus/FocusOwnerImpl$special$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/focus/FocusOwnerImpl;
-Landroidx/compose/ui/focus/FocusProperties;
-Landroidx/compose/ui/focus/FocusPropertiesKt$focusProperties$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/focus/FocusPropertiesKt;
-Landroidx/compose/ui/focus/FocusPropertiesModifierNode;
-Landroidx/compose/ui/focus/FocusPropertiesModifierNodeImpl;
-Landroidx/compose/ui/focus/FocusRequester$Companion;
-Landroidx/compose/ui/focus/FocusRequester;
-Landroidx/compose/ui/focus/FocusRequesterModifierKt$focusRequester$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/focus/FocusRequesterModifierKt;
-Landroidx/compose/ui/focus/FocusRequesterModifierNode;
-Landroidx/compose/ui/focus/FocusRequesterModifierNodeImpl;
-Landroidx/compose/ui/focus/FocusState;
-Landroidx/compose/ui/focus/FocusStateImpl$WhenMappings;
-Landroidx/compose/ui/focus/FocusStateImpl;
-Landroidx/compose/ui/focus/FocusTargetModifierNode$Companion;
-Landroidx/compose/ui/focus/FocusTargetModifierNode$special$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/focus/FocusTargetModifierNode;
-Landroidx/compose/ui/geometry/CornerRadius$Companion;
-Landroidx/compose/ui/geometry/CornerRadius;
-Landroidx/compose/ui/geometry/CornerRadiusKt;
-Landroidx/compose/ui/geometry/Offset$Companion;
-Landroidx/compose/ui/geometry/Offset;
-Landroidx/compose/ui/geometry/OffsetKt;
-Landroidx/compose/ui/geometry/Rect$Companion;
-Landroidx/compose/ui/geometry/Rect;
-Landroidx/compose/ui/geometry/RectKt;
-Landroidx/compose/ui/geometry/RoundRect$Companion;
-Landroidx/compose/ui/geometry/RoundRect;
-Landroidx/compose/ui/geometry/RoundRectKt;
-Landroidx/compose/ui/geometry/Size$Companion;
-Landroidx/compose/ui/geometry/Size;
-Landroidx/compose/ui/geometry/SizeKt;
-Landroidx/compose/ui/graphics/AndroidBlendMode_androidKt;
-Landroidx/compose/ui/graphics/AndroidCanvas;
-Landroidx/compose/ui/graphics/AndroidCanvas_androidKt;
-Landroidx/compose/ui/graphics/AndroidColorFilter_androidKt;
-Landroidx/compose/ui/graphics/AndroidImageBitmap;
-Landroidx/compose/ui/graphics/AndroidImageBitmap_androidKt;
-Landroidx/compose/ui/graphics/AndroidMatrixConversions_androidKt;
-Landroidx/compose/ui/graphics/AndroidPaint;
-Landroidx/compose/ui/graphics/AndroidPaint_androidKt;
-Landroidx/compose/ui/graphics/AndroidPath;
-Landroidx/compose/ui/graphics/AndroidPath_androidKt;
-Landroidx/compose/ui/graphics/Api26Bitmap;
-Landroidx/compose/ui/graphics/BlendMode$Companion;
-Landroidx/compose/ui/graphics/BlendMode;
-Landroidx/compose/ui/graphics/BlendModeColorFilterHelper;
-Landroidx/compose/ui/graphics/BlockGraphicsLayerModifier$measure$1;
-Landroidx/compose/ui/graphics/BlockGraphicsLayerModifier;
-Landroidx/compose/ui/graphics/Brush$Companion;
-Landroidx/compose/ui/graphics/Brush;
-Landroidx/compose/ui/graphics/Canvas;
-Landroidx/compose/ui/graphics/CanvasHolder;
-Landroidx/compose/ui/graphics/CanvasKt;
-Landroidx/compose/ui/graphics/CanvasUtils;
-Landroidx/compose/ui/graphics/CanvasZHelper;
-Landroidx/compose/ui/graphics/Color$Companion;
-Landroidx/compose/ui/graphics/Color;
-Landroidx/compose/ui/graphics/ColorFilter$Companion;
-Landroidx/compose/ui/graphics/ColorFilter;
-Landroidx/compose/ui/graphics/ColorKt;
-Landroidx/compose/ui/graphics/CompositingStrategy$Companion;
-Landroidx/compose/ui/graphics/CompositingStrategy;
-Landroidx/compose/ui/graphics/FilterQuality$Companion;
-Landroidx/compose/ui/graphics/FilterQuality;
-Landroidx/compose/ui/graphics/Float16$Companion;
-Landroidx/compose/ui/graphics/Float16;
-Landroidx/compose/ui/graphics/GraphicsLayerModifierKt$graphicsLayer$$inlined$modifierElementOf$1;
-Landroidx/compose/ui/graphics/GraphicsLayerModifierKt;
-Landroidx/compose/ui/graphics/GraphicsLayerModifierNodeElement;
-Landroidx/compose/ui/graphics/GraphicsLayerScope;
-Landroidx/compose/ui/graphics/GraphicsLayerScopeKt;
-Landroidx/compose/ui/graphics/ImageBitmap;
-Landroidx/compose/ui/graphics/ImageBitmapConfig$Companion;
-Landroidx/compose/ui/graphics/ImageBitmapConfig;
-Landroidx/compose/ui/graphics/ImageBitmapKt;
-Landroidx/compose/ui/graphics/Matrix$Companion;
-Landroidx/compose/ui/graphics/Matrix;
-Landroidx/compose/ui/graphics/MatrixKt;
-Landroidx/compose/ui/graphics/Outline$Rectangle;
-Landroidx/compose/ui/graphics/Outline$Rounded;
-Landroidx/compose/ui/graphics/Outline;
-Landroidx/compose/ui/graphics/OutlineKt;
-Landroidx/compose/ui/graphics/Paint;
-Landroidx/compose/ui/graphics/PaintingStyle$Companion;
-Landroidx/compose/ui/graphics/PaintingStyle;
-Landroidx/compose/ui/graphics/Path$Companion;
-Landroidx/compose/ui/graphics/Path;
-Landroidx/compose/ui/graphics/PathFillType$Companion;
-Landroidx/compose/ui/graphics/PathFillType;
-Landroidx/compose/ui/graphics/RectangleShapeKt$RectangleShape$1;
-Landroidx/compose/ui/graphics/RectangleShapeKt;
-Landroidx/compose/ui/graphics/ReusableGraphicsLayerScope;
-Landroidx/compose/ui/graphics/ShaderBrush;
-Landroidx/compose/ui/graphics/Shadow$Companion;
-Landroidx/compose/ui/graphics/Shadow;
-Landroidx/compose/ui/graphics/Shape;
-Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$layerBlock$1;
-Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier$measure$1;
-Landroidx/compose/ui/graphics/SimpleGraphicsLayerModifier;
-Landroidx/compose/ui/graphics/SolidColor;
-Landroidx/compose/ui/graphics/StrokeCap$Companion;
-Landroidx/compose/ui/graphics/StrokeCap;
-Landroidx/compose/ui/graphics/StrokeJoin$Companion;
-Landroidx/compose/ui/graphics/StrokeJoin;
-Landroidx/compose/ui/graphics/TransformOrigin$Companion;
-Landroidx/compose/ui/graphics/TransformOrigin;
-Landroidx/compose/ui/graphics/TransformOriginKt;
-Landroidx/compose/ui/graphics/WrapperVerificationHelperMethods;
-Landroidx/compose/ui/graphics/colorspace/Adaptation$Companion$Bradford$1;
-Landroidx/compose/ui/graphics/colorspace/Adaptation$Companion$Ciecat02$1;
-Landroidx/compose/ui/graphics/colorspace/Adaptation$Companion$VonKries$1;
-Landroidx/compose/ui/graphics/colorspace/Adaptation$Companion;
-Landroidx/compose/ui/graphics/colorspace/Adaptation;
-Landroidx/compose/ui/graphics/colorspace/ColorModel$Companion;
-Landroidx/compose/ui/graphics/colorspace/ColorModel;
-Landroidx/compose/ui/graphics/colorspace/ColorSpace$Companion;
-Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-Landroidx/compose/ui/graphics/colorspace/ColorSpaceKt;
-Landroidx/compose/ui/graphics/colorspace/ColorSpaces$$ExternalSyntheticLambda0;
-Landroidx/compose/ui/graphics/colorspace/ColorSpaces$$ExternalSyntheticLambda1;
-Landroidx/compose/ui/graphics/colorspace/ColorSpaces;
-Landroidx/compose/ui/graphics/colorspace/Connector$Companion$identity$1;
-Landroidx/compose/ui/graphics/colorspace/Connector$Companion;
-Landroidx/compose/ui/graphics/colorspace/Connector;
-Landroidx/compose/ui/graphics/colorspace/DoubleFunction;
-Landroidx/compose/ui/graphics/colorspace/Illuminant;
-Landroidx/compose/ui/graphics/colorspace/Lab$Companion;
-Landroidx/compose/ui/graphics/colorspace/Lab;
-Landroidx/compose/ui/graphics/colorspace/Oklab$Companion;
-Landroidx/compose/ui/graphics/colorspace/Oklab;
-Landroidx/compose/ui/graphics/colorspace/RenderIntent$Companion;
-Landroidx/compose/ui/graphics/colorspace/RenderIntent;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda0;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda1;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda2;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda3;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda5;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda7;
-Landroidx/compose/ui/graphics/colorspace/Rgb$$ExternalSyntheticLambda8;
-Landroidx/compose/ui/graphics/colorspace/Rgb$Companion;
-Landroidx/compose/ui/graphics/colorspace/Rgb$eotf$1;
-Landroidx/compose/ui/graphics/colorspace/Rgb$oetf$1;
-Landroidx/compose/ui/graphics/colorspace/Rgb;
-Landroidx/compose/ui/graphics/colorspace/TransferParameters;
-Landroidx/compose/ui/graphics/colorspace/WhitePoint;
-Landroidx/compose/ui/graphics/colorspace/Xyz;
-Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope$DrawParams;
-Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope$drawContext$1;
-Landroidx/compose/ui/graphics/drawscope/CanvasDrawScope;
-Landroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt$asDrawTransform$1;
-Landroidx/compose/ui/graphics/drawscope/CanvasDrawScopeKt;
-Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;
-Landroidx/compose/ui/graphics/drawscope/DrawContext;
-Landroidx/compose/ui/graphics/drawscope/DrawScope$Companion;
-Landroidx/compose/ui/graphics/drawscope/DrawScope;
-Landroidx/compose/ui/graphics/drawscope/DrawStyle;
-Landroidx/compose/ui/graphics/drawscope/DrawTransform;
-Landroidx/compose/ui/graphics/drawscope/EmptyCanvas;
-Landroidx/compose/ui/graphics/drawscope/Fill;
-Landroidx/compose/ui/graphics/painter/BitmapPainter;
-Landroidx/compose/ui/graphics/painter/BitmapPainterKt;
-Landroidx/compose/ui/graphics/painter/Painter$drawLambda$1;
-Landroidx/compose/ui/graphics/painter/Painter;
-Landroidx/compose/ui/graphics/vector/DrawCache;
-Landroidx/compose/ui/graphics/vector/GroupComponent;
-Landroidx/compose/ui/graphics/vector/ImageVector$Builder$GroupParams;
-Landroidx/compose/ui/graphics/vector/ImageVector$Builder;
-Landroidx/compose/ui/graphics/vector/ImageVector$Companion;
-Landroidx/compose/ui/graphics/vector/ImageVector;
-Landroidx/compose/ui/graphics/vector/ImageVectorKt;
-Landroidx/compose/ui/graphics/vector/PathBuilder;
-Landroidx/compose/ui/graphics/vector/PathComponent$pathMeasure$2;
-Landroidx/compose/ui/graphics/vector/PathComponent;
-Landroidx/compose/ui/graphics/vector/PathNode$Close;
-Landroidx/compose/ui/graphics/vector/PathNode$CurveTo;
-Landroidx/compose/ui/graphics/vector/PathNode$HorizontalTo;
-Landroidx/compose/ui/graphics/vector/PathNode$LineTo;
-Landroidx/compose/ui/graphics/vector/PathNode$MoveTo;
-Landroidx/compose/ui/graphics/vector/PathNode$ReflectiveCurveTo;
-Landroidx/compose/ui/graphics/vector/PathNode$RelativeCurveTo;
-Landroidx/compose/ui/graphics/vector/PathNode$RelativeHorizontalTo;
-Landroidx/compose/ui/graphics/vector/PathNode$RelativeLineTo;
-Landroidx/compose/ui/graphics/vector/PathNode$RelativeMoveTo;
-Landroidx/compose/ui/graphics/vector/PathNode$RelativeReflectiveCurveTo;
-Landroidx/compose/ui/graphics/vector/PathNode$RelativeVerticalTo;
-Landroidx/compose/ui/graphics/vector/PathNode$VerticalTo;
-Landroidx/compose/ui/graphics/vector/PathNode;
-Landroidx/compose/ui/graphics/vector/PathParser$PathPoint;
-Landroidx/compose/ui/graphics/vector/PathParser;
-Landroidx/compose/ui/graphics/vector/VNode;
-Landroidx/compose/ui/graphics/vector/VectorApplier;
-Landroidx/compose/ui/graphics/vector/VectorComponent$drawVectorBlock$1;
-Landroidx/compose/ui/graphics/vector/VectorComponent$invalidateCallback$1;
-Landroidx/compose/ui/graphics/vector/VectorComponent$root$1$1;
-Landroidx/compose/ui/graphics/vector/VectorComponent;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$1;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$10;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$11;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$12;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$13;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$14;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$1;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$2;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$3;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$4;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$5;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$6;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$7;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$8;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path$2$9;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt$Path-9cdaXJ4$$inlined$ComposeNode$1;
-Landroidx/compose/ui/graphics/vector/VectorComposeKt;
-Landroidx/compose/ui/graphics/vector/VectorConfig;
-Landroidx/compose/ui/graphics/vector/VectorGroup$iterator$1;
-Landroidx/compose/ui/graphics/vector/VectorGroup;
-Landroidx/compose/ui/graphics/vector/VectorKt;
-Landroidx/compose/ui/graphics/vector/VectorNode;
-Landroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2$invoke$$inlined$onDispose$1;
-Landroidx/compose/ui/graphics/vector/VectorPainter$RenderVector$2;
-Landroidx/compose/ui/graphics/vector/VectorPainter$composeVector$1;
-Landroidx/compose/ui/graphics/vector/VectorPainter$vector$1$1;
-Landroidx/compose/ui/graphics/vector/VectorPainter;
-Landroidx/compose/ui/graphics/vector/VectorPainterKt$RenderVectorGroup$config$1;
-Landroidx/compose/ui/graphics/vector/VectorPainterKt$rememberVectorPainter$3;
-Landroidx/compose/ui/graphics/vector/VectorPainterKt;
-Landroidx/compose/ui/graphics/vector/VectorPath;
-Landroidx/compose/ui/graphics/vector/VectorProperty$Fill;
-Landroidx/compose/ui/graphics/vector/VectorProperty$FillAlpha;
-Landroidx/compose/ui/graphics/vector/VectorProperty$PathData;
-Landroidx/compose/ui/graphics/vector/VectorProperty$Stroke;
-Landroidx/compose/ui/graphics/vector/VectorProperty$StrokeAlpha;
-Landroidx/compose/ui/graphics/vector/VectorProperty$StrokeLineWidth;
-Landroidx/compose/ui/graphics/vector/VectorProperty$TrimPathEnd;
-Landroidx/compose/ui/graphics/vector/VectorProperty$TrimPathOffset;
-Landroidx/compose/ui/graphics/vector/VectorProperty$TrimPathStart;
-Landroidx/compose/ui/graphics/vector/VectorProperty;
-Landroidx/compose/ui/hapticfeedback/HapticFeedback;
-Landroidx/compose/ui/hapticfeedback/PlatformHapticFeedback;
-Landroidx/compose/ui/input/InputMode$Companion;
-Landroidx/compose/ui/input/InputMode;
-Landroidx/compose/ui/input/InputModeManager;
-Landroidx/compose/ui/input/InputModeManagerImpl;
-Landroidx/compose/ui/input/key/KeyInputInputModifierNodeImpl;
-Landroidx/compose/ui/input/key/KeyInputModifierKt$onKeyEvent$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/input/key/KeyInputModifierKt;
-Landroidx/compose/ui/input/key/KeyInputModifierNode;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher$calculateNestedScrollScope$1;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt$nestedScroll$2;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierKt;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal$1;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocal;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt$ModifierLocalNestedScroll$1;
-Landroidx/compose/ui/input/nestedscroll/NestedScrollModifierLocalKt;
-Landroidx/compose/ui/input/pointer/AndroidPointerIconType;
-Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;
-Landroidx/compose/ui/input/pointer/ConsumedData;
-Landroidx/compose/ui/input/pointer/HistoricalChange;
-Landroidx/compose/ui/input/pointer/HitPathTracker;
-Landroidx/compose/ui/input/pointer/InternalPointerEvent;
-Landroidx/compose/ui/input/pointer/MotionEventAdapter;
-Landroidx/compose/ui/input/pointer/Node;
-Landroidx/compose/ui/input/pointer/NodeParent;
-Landroidx/compose/ui/input/pointer/PointerButtons;
-Landroidx/compose/ui/input/pointer/PointerEvent;
-Landroidx/compose/ui/input/pointer/PointerEventKt;
-Landroidx/compose/ui/input/pointer/PointerEventPass;
-Landroidx/compose/ui/input/pointer/PointerEventTimeoutCancellationException;
-Landroidx/compose/ui/input/pointer/PointerEventType$Companion;
-Landroidx/compose/ui/input/pointer/PointerEventType;
-Landroidx/compose/ui/input/pointer/PointerEvent_androidKt;
-Landroidx/compose/ui/input/pointer/PointerIcon;
-Landroidx/compose/ui/input/pointer/PointerIconService;
-Landroidx/compose/ui/input/pointer/PointerId;
-Landroidx/compose/ui/input/pointer/PointerInputChange;
-Landroidx/compose/ui/input/pointer/PointerInputChangeEventProducer$PointerInputData;
-Landroidx/compose/ui/input/pointer/PointerInputChangeEventProducer;
-Landroidx/compose/ui/input/pointer/PointerInputEvent;
-Landroidx/compose/ui/input/pointer/PointerInputEventData;
-Landroidx/compose/ui/input/pointer/PointerInputEventProcessor;
-Landroidx/compose/ui/input/pointer/PointerInputEventProcessorKt;
-Landroidx/compose/ui/input/pointer/PointerInputFilter;
-Landroidx/compose/ui/input/pointer/PointerInputModifier;
-Landroidx/compose/ui/input/pointer/PointerInputScope;
-Landroidx/compose/ui/input/pointer/PointerKeyboardModifiers;
-Landroidx/compose/ui/input/pointer/PointerType$Companion;
-Landroidx/compose/ui/input/pointer/PointerType;
-Landroidx/compose/ui/input/pointer/PositionCalculator;
-Landroidx/compose/ui/input/pointer/ProcessResult;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$1;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$job$1;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$WhenMappings;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$awaitPointerEventScope$2$2;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2$2$1;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$2;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4$2$1;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$4;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6$2$1;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt$pointerInput$6;
-Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;
-Landroidx/compose/ui/input/pointer/util/DataPointAtTime;
-Landroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;
-Landroidx/compose/ui/input/pointer/util/VelocityTracker1D$WhenMappings;
-Landroidx/compose/ui/input/pointer/util/VelocityTracker1D;
-Landroidx/compose/ui/input/pointer/util/VelocityTracker;
-Landroidx/compose/ui/input/pointer/util/VelocityTrackerKt;
-Landroidx/compose/ui/input/rotary/RotaryInputModifierKt$onRotaryScrollEvent$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/input/rotary/RotaryInputModifierKt;
-Landroidx/compose/ui/input/rotary/RotaryInputModifierNode;
-Landroidx/compose/ui/input/rotary/RotaryInputModifierNodeImpl;
-Landroidx/compose/ui/layout/AlignmentLine$Companion;
-Landroidx/compose/ui/layout/AlignmentLine;
-Landroidx/compose/ui/layout/AlignmentLineKt$FirstBaseline$1;
-Landroidx/compose/ui/layout/AlignmentLineKt$LastBaseline$1;
-Landroidx/compose/ui/layout/AlignmentLineKt;
-Landroidx/compose/ui/layout/BeyondBoundsLayout$BeyondBoundsScope;
-Landroidx/compose/ui/layout/BeyondBoundsLayout;
-Landroidx/compose/ui/layout/BeyondBoundsLayoutKt$ModifierLocalBeyondBoundsLayout$1;
-Landroidx/compose/ui/layout/BeyondBoundsLayoutKt;
-Landroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt$lambda-1$1;
-Landroidx/compose/ui/layout/ComposableSingletons$SubcomposeLayoutKt;
-Landroidx/compose/ui/layout/ContentScale$Companion$Crop$1;
-Landroidx/compose/ui/layout/ContentScale$Companion$FillBounds$1;
-Landroidx/compose/ui/layout/ContentScale$Companion$FillHeight$1;
-Landroidx/compose/ui/layout/ContentScale$Companion$FillWidth$1;
-Landroidx/compose/ui/layout/ContentScale$Companion$Fit$1;
-Landroidx/compose/ui/layout/ContentScale$Companion$Inside$1;
-Landroidx/compose/ui/layout/ContentScale$Companion;
-Landroidx/compose/ui/layout/ContentScale;
-Landroidx/compose/ui/layout/ContentScaleKt;
-Landroidx/compose/ui/layout/FixedScale;
-Landroidx/compose/ui/layout/HorizontalAlignmentLine;
-Landroidx/compose/ui/layout/IntrinsicMeasurable;
-Landroidx/compose/ui/layout/IntrinsicMeasureScope;
-Landroidx/compose/ui/layout/LayoutCoordinates;
-Landroidx/compose/ui/layout/LayoutId;
-Landroidx/compose/ui/layout/LayoutIdKt;
-Landroidx/compose/ui/layout/LayoutIdParentData;
-Landroidx/compose/ui/layout/LayoutInfo;
-Landroidx/compose/ui/layout/LayoutKt$materializerOf$1;
-Landroidx/compose/ui/layout/LayoutKt;
-Landroidx/compose/ui/layout/LayoutModifier;
-Landroidx/compose/ui/layout/LayoutModifierImpl;
-Landroidx/compose/ui/layout/LayoutModifierKt$layout$$inlined$modifierElementOf$2;
-Landroidx/compose/ui/layout/LayoutModifierKt;
-Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$NodeState;
-Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$Scope;
-Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1;
-Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$createMeasurePolicy$1;
-Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState$subcompose$3$1$1;
-Landroidx/compose/ui/layout/LayoutNodeSubcompositionsState;
-Landroidx/compose/ui/layout/LookaheadLayoutCoordinates;
-Landroidx/compose/ui/layout/LookaheadLayoutCoordinatesImpl;
-Landroidx/compose/ui/layout/Measurable;
-Landroidx/compose/ui/layout/MeasurePolicy;
-Landroidx/compose/ui/layout/MeasureResult;
-Landroidx/compose/ui/layout/MeasureScope$layout$1;
-Landroidx/compose/ui/layout/MeasureScope;
-Landroidx/compose/ui/layout/Measured;
-Landroidx/compose/ui/layout/NoOpSubcomposeSlotReusePolicy;
-Landroidx/compose/ui/layout/OnGloballyPositionedModifier;
-Landroidx/compose/ui/layout/OnGloballyPositionedModifierImpl;
-Landroidx/compose/ui/layout/OnGloballyPositionedModifierKt;
-Landroidx/compose/ui/layout/OnPlacedModifier;
-Landroidx/compose/ui/layout/OnRemeasuredModifier;
-Landroidx/compose/ui/layout/OnRemeasuredModifierKt;
-Landroidx/compose/ui/layout/OnSizeChangedModifier;
-Landroidx/compose/ui/layout/ParentDataModifier;
-Landroidx/compose/ui/layout/PinnableContainer$PinnedHandle;
-Landroidx/compose/ui/layout/PinnableContainer;
-Landroidx/compose/ui/layout/PinnableContainerKt$LocalPinnableContainer$1;
-Landroidx/compose/ui/layout/PinnableContainerKt;
-Landroidx/compose/ui/layout/Placeable$PlacementScope$Companion;
-Landroidx/compose/ui/layout/Placeable$PlacementScope;
-Landroidx/compose/ui/layout/Placeable;
-Landroidx/compose/ui/layout/PlaceableKt$DefaultLayerBlock$1;
-Landroidx/compose/ui/layout/PlaceableKt;
-Landroidx/compose/ui/layout/Remeasurement;
-Landroidx/compose/ui/layout/RemeasurementModifier;
-Landroidx/compose/ui/layout/RootMeasurePolicy$measure$2;
-Landroidx/compose/ui/layout/RootMeasurePolicy;
-Landroidx/compose/ui/layout/ScaleFactor$Companion;
-Landroidx/compose/ui/layout/ScaleFactor;
-Landroidx/compose/ui/layout/ScaleFactorKt;
-Landroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$$inlined$ComposeNode$1;
-Landroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$4;
-Landroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$5$1;
-Landroidx/compose/ui/layout/SubcomposeLayoutKt$SubcomposeLayout$6;
-Landroidx/compose/ui/layout/SubcomposeLayoutKt;
-Landroidx/compose/ui/layout/SubcomposeLayoutState$setCompositionContext$1;
-Landroidx/compose/ui/layout/SubcomposeLayoutState$setMeasurePolicy$1;
-Landroidx/compose/ui/layout/SubcomposeLayoutState$setRoot$1;
-Landroidx/compose/ui/layout/SubcomposeLayoutState;
-Landroidx/compose/ui/layout/SubcomposeMeasureScope;
-Landroidx/compose/ui/layout/SubcomposeSlotReusePolicy$SlotIdsSet;
-Landroidx/compose/ui/layout/SubcomposeSlotReusePolicy;
-Landroidx/compose/ui/modifier/BackwardsCompatLocalMap;
-Landroidx/compose/ui/modifier/EmptyMap;
-Landroidx/compose/ui/modifier/ModifierLocal;
-Landroidx/compose/ui/modifier/ModifierLocalConsumer;
-Landroidx/compose/ui/modifier/ModifierLocalKt;
-Landroidx/compose/ui/modifier/ModifierLocalManager$invalidate$1;
-Landroidx/compose/ui/modifier/ModifierLocalManager;
-Landroidx/compose/ui/modifier/ModifierLocalMap;
-Landroidx/compose/ui/modifier/ModifierLocalNode;
-Landroidx/compose/ui/modifier/ModifierLocalNodeKt;
-Landroidx/compose/ui/modifier/ModifierLocalProvider;
-Landroidx/compose/ui/modifier/ModifierLocalReadScope;
-Landroidx/compose/ui/modifier/ProvidableModifierLocal;
-Landroidx/compose/ui/node/AlignmentLines$recalculate$1;
-Landroidx/compose/ui/node/AlignmentLines;
-Landroidx/compose/ui/node/AlignmentLinesOwner;
-Landroidx/compose/ui/node/BackwardsCompatNode$updateModifierLocalConsumer$1;
-Landroidx/compose/ui/node/BackwardsCompatNode;
-Landroidx/compose/ui/node/BackwardsCompatNodeKt$DetachedModifierLocalReadScope$1;
-Landroidx/compose/ui/node/BackwardsCompatNodeKt$onDrawCacheReadsChanged$1;
-Landroidx/compose/ui/node/BackwardsCompatNodeKt$updateModifierLocalConsumer$1;
-Landroidx/compose/ui/node/BackwardsCompatNodeKt;
-Landroidx/compose/ui/node/CanFocusChecker;
-Landroidx/compose/ui/node/CenteredArray;
-Landroidx/compose/ui/node/ComposeUiNode$Companion$SetDensity$1;
-Landroidx/compose/ui/node/ComposeUiNode$Companion$SetLayoutDirection$1;
-Landroidx/compose/ui/node/ComposeUiNode$Companion$SetMeasurePolicy$1;
-Landroidx/compose/ui/node/ComposeUiNode$Companion$SetModifier$1;
-Landroidx/compose/ui/node/ComposeUiNode$Companion$SetViewConfiguration$1;
-Landroidx/compose/ui/node/ComposeUiNode$Companion$VirtualConstructor$1;
-Landroidx/compose/ui/node/ComposeUiNode$Companion;
-Landroidx/compose/ui/node/ComposeUiNode;
-Landroidx/compose/ui/node/DelegatableNode;
-Landroidx/compose/ui/node/DelegatableNodeKt;
-Landroidx/compose/ui/node/DepthSortedSet$DepthComparator$1;
-Landroidx/compose/ui/node/DepthSortedSet$mapOfOriginalDepth$2;
-Landroidx/compose/ui/node/DepthSortedSet;
-Landroidx/compose/ui/node/DiffCallback;
-Landroidx/compose/ui/node/DistanceAndInLayer;
-Landroidx/compose/ui/node/DrawModifierNode;
-Landroidx/compose/ui/node/DrawModifierNodeKt;
-Landroidx/compose/ui/node/GlobalPositionAwareModifierNode;
-Landroidx/compose/ui/node/HitTestResult;
-Landroidx/compose/ui/node/HitTestResultKt;
-Landroidx/compose/ui/node/InnerNodeCoordinator$Companion;
-Landroidx/compose/ui/node/InnerNodeCoordinator$tail$1;
-Landroidx/compose/ui/node/InnerNodeCoordinator;
-Landroidx/compose/ui/node/IntStack;
-Landroidx/compose/ui/node/IntermediateLayoutModifierNode;
-Landroidx/compose/ui/node/IntrinsicsPolicy$Companion;
-Landroidx/compose/ui/node/IntrinsicsPolicy;
-Landroidx/compose/ui/node/LayerPositionalProperties;
-Landroidx/compose/ui/node/LayoutAwareModifierNode;
-Landroidx/compose/ui/node/LayoutModifierNode;
-Landroidx/compose/ui/node/LayoutModifierNodeCoordinator$Companion;
-Landroidx/compose/ui/node/LayoutModifierNodeCoordinator;
-Landroidx/compose/ui/node/LayoutModifierNodeCoordinatorKt;
-Landroidx/compose/ui/node/LayoutModifierNodeKt;
-Landroidx/compose/ui/node/LayoutNode$$ExternalSyntheticLambda0;
-Landroidx/compose/ui/node/LayoutNode$Companion$Constructor$1;
-Landroidx/compose/ui/node/LayoutNode$Companion$DummyViewConfiguration$1;
-Landroidx/compose/ui/node/LayoutNode$Companion$ErrorMeasurePolicy$1;
-Landroidx/compose/ui/node/LayoutNode$Companion;
-Landroidx/compose/ui/node/LayoutNode$LayoutState;
-Landroidx/compose/ui/node/LayoutNode$NoIntrinsicsMeasurePolicy;
-Landroidx/compose/ui/node/LayoutNode$UsageByParent;
-Landroidx/compose/ui/node/LayoutNode$WhenMappings;
-Landroidx/compose/ui/node/LayoutNode$_foldedChildren$1;
-Landroidx/compose/ui/node/LayoutNode;
-Landroidx/compose/ui/node/LayoutNodeAlignmentLines;
-Landroidx/compose/ui/node/LayoutNodeDrawScope;
-Landroidx/compose/ui/node/LayoutNodeDrawScopeKt;
-Landroidx/compose/ui/node/LayoutNodeKt;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$WhenMappings;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$childMeasurables$1;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$1;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1$2;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate$remeasure$1;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$MeasurePassDelegate;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate$performMeasure$2;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegate;
-Landroidx/compose/ui/node/LayoutNodeLayoutDelegateKt;
-Landroidx/compose/ui/node/LayoutTreeConsistencyChecker;
-Landroidx/compose/ui/node/LookaheadCapablePlaceable;
-Landroidx/compose/ui/node/LookaheadDelegate;
-Landroidx/compose/ui/node/MeasureAndLayoutDelegate$PostponedRequest;
-Landroidx/compose/ui/node/MeasureAndLayoutDelegate$WhenMappings;
-Landroidx/compose/ui/node/MeasureAndLayoutDelegate;
-Landroidx/compose/ui/node/ModifierNodeElement;
-Landroidx/compose/ui/node/MutableVectorWithMutationTracking;
-Landroidx/compose/ui/node/MyersDiffKt;
-Landroidx/compose/ui/node/NodeChain$Differ;
-Landroidx/compose/ui/node/NodeChain;
-Landroidx/compose/ui/node/NodeChainKt$SentinelHead$1;
-Landroidx/compose/ui/node/NodeChainKt;
-Landroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;
-Landroidx/compose/ui/node/NodeCoordinator$Companion$SemanticsSource$1;
-Landroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayer$1;
-Landroidx/compose/ui/node/NodeCoordinator$Companion$onCommitAffectingLayerParams$1;
-Landroidx/compose/ui/node/NodeCoordinator$Companion;
-Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;
-Landroidx/compose/ui/node/NodeCoordinator$hit$1;
-Landroidx/compose/ui/node/NodeCoordinator$invalidateParentLayer$1;
-Landroidx/compose/ui/node/NodeCoordinator$invoke$1;
-Landroidx/compose/ui/node/NodeCoordinator$updateLayerParameters$1;
-Landroidx/compose/ui/node/NodeCoordinator;
-Landroidx/compose/ui/node/NodeCoordinatorKt;
-Landroidx/compose/ui/node/NodeKind;
-Landroidx/compose/ui/node/NodeKindKt;
-Landroidx/compose/ui/node/ObserverNode;
-Landroidx/compose/ui/node/OnPositionedDispatcher$Companion$DepthComparator;
-Landroidx/compose/ui/node/OnPositionedDispatcher$Companion;
-Landroidx/compose/ui/node/OnPositionedDispatcher;
-Landroidx/compose/ui/node/OwnedLayer;
-Landroidx/compose/ui/node/Owner$Companion;
-Landroidx/compose/ui/node/Owner$OnLayoutCompletedListener;
-Landroidx/compose/ui/node/Owner;
-Landroidx/compose/ui/node/OwnerScope;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$clearInvalidObservations$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayout$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifier$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLayoutModifierInLookahead$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLookaheadLayout$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingLookaheadMeasure$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver$onCommitAffectingMeasure$1;
-Landroidx/compose/ui/node/OwnerSnapshotObserver;
-Landroidx/compose/ui/node/ParentDataModifierNode;
-Landroidx/compose/ui/node/PointerInputModifierNode;
-Landroidx/compose/ui/node/PointerInputModifierNodeKt;
-Landroidx/compose/ui/node/RootForTest;
-Landroidx/compose/ui/node/SemanticsModifierNode;
-Landroidx/compose/ui/node/SemanticsModifierNodeKt;
-Landroidx/compose/ui/node/Snake;
-Landroidx/compose/ui/node/TreeSet;
-Landroidx/compose/ui/node/UiApplier;
-Landroidx/compose/ui/platform/AbstractComposeView$ensureCompositionCreated$1;
-Landroidx/compose/ui/platform/AbstractComposeView;
-Landroidx/compose/ui/platform/AccessibilityManager;
-Landroidx/compose/ui/platform/AndroidAccessibilityManager$Companion;
-Landroidx/compose/ui/platform/AndroidAccessibilityManager;
-Landroidx/compose/ui/platform/AndroidClipboardManager;
-Landroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda0;
-Landroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda1;
-Landroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda2;
-Landroidx/compose/ui/platform/AndroidComposeView$$ExternalSyntheticLambda3;
-Landroidx/compose/ui/platform/AndroidComposeView$Companion;
-Landroidx/compose/ui/platform/AndroidComposeView$ViewTreeOwners;
-Landroidx/compose/ui/platform/AndroidComposeView$_inputModeManager$1;
-Landroidx/compose/ui/platform/AndroidComposeView$configurationChangeObserver$1;
-Landroidx/compose/ui/platform/AndroidComposeView$focusOwner$1;
-Landroidx/compose/ui/platform/AndroidComposeView$keyInputModifier$1;
-Landroidx/compose/ui/platform/AndroidComposeView$pointerIconService$1;
-Landroidx/compose/ui/platform/AndroidComposeView$resendMotionEventOnLayout$1;
-Landroidx/compose/ui/platform/AndroidComposeView$resendMotionEventRunnable$1;
-Landroidx/compose/ui/platform/AndroidComposeView$rotaryInputModifier$1;
-Landroidx/compose/ui/platform/AndroidComposeView$semanticsModifier$1;
-Landroidx/compose/ui/platform/AndroidComposeView$snapshotObserver$1;
-Landroidx/compose/ui/platform/AndroidComposeView;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$$ExternalSyntheticLambda0;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$$ExternalSyntheticLambda1;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$$ExternalSyntheticLambda2;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$1;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$Companion;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$MyNodeProvider;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$SemanticsNodeCopy;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$boundsUpdatesEventLoop$1;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat$sendScrollEventIfNeededLambda$1;
-Landroidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat;
-Landroidx/compose/ui/platform/AndroidComposeViewForceDarkModeQ;
-Landroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsN;
-Landroidx/compose/ui/platform/AndroidComposeViewVerificationHelperMethodsO;
-Landroidx/compose/ui/platform/AndroidComposeView_androidKt$textInputServiceFactory$1;
-Landroidx/compose/ui/platform/AndroidComposeView_androidKt;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalConfiguration$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalContext$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalImageVectorCache$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalLifecycleOwner$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalSavedStateRegistryOwner$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$LocalView$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$1$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2$invoke$$inlined$onDispose$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$2;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$4;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1$invoke$$inlined$onDispose$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$callbacks$1$1;
-Landroidx/compose/ui/platform/AndroidCompositionLocals_androidKt;
-Landroidx/compose/ui/platform/AndroidFontResourceLoader;
-Landroidx/compose/ui/platform/AndroidTextToolbar$textActionModeCallback$1;
-Landroidx/compose/ui/platform/AndroidTextToolbar;
-Landroidx/compose/ui/platform/AndroidUiDispatcher$Companion$Main$2;
-Landroidx/compose/ui/platform/AndroidUiDispatcher$Companion$currentThread$1;
-Landroidx/compose/ui/platform/AndroidUiDispatcher$Companion;
-Landroidx/compose/ui/platform/AndroidUiDispatcher$dispatchCallback$1;
-Landroidx/compose/ui/platform/AndroidUiDispatcher;
-Landroidx/compose/ui/platform/AndroidUiDispatcher_androidKt;
-Landroidx/compose/ui/platform/AndroidUiFrameClock$withFrameNanos$2$1;
-Landroidx/compose/ui/platform/AndroidUiFrameClock$withFrameNanos$2$callback$1;
-Landroidx/compose/ui/platform/AndroidUiFrameClock;
-Landroidx/compose/ui/platform/AndroidUriHandler;
-Landroidx/compose/ui/platform/AndroidViewConfiguration;
-Landroidx/compose/ui/platform/CalculateMatrixToWindow;
-Landroidx/compose/ui/platform/CalculateMatrixToWindowApi29;
-Landroidx/compose/ui/platform/ClipboardManager;
-Landroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt$lambda-1$1;
-Landroidx/compose/ui/platform/ComposableSingletons$Wrapper_androidKt;
-Landroidx/compose/ui/platform/ComposeView$Content$1;
-Landroidx/compose/ui/platform/ComposeView;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalAccessibilityManager$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalAutofill$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalAutofillTree$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalClipboardManager$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalDensity$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalFocusManager$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalFontFamilyResolver$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalFontLoader$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalHapticFeedback$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalInputModeManager$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalLayoutDirection$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalPointerIconService$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalTextInputService$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalTextToolbar$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalUriHandler$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalViewConfiguration$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$LocalWindowInfo$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt$ProvideCommonCompositionLocals$1;
-Landroidx/compose/ui/platform/CompositionLocalsKt;
-Landroidx/compose/ui/platform/DeviceRenderNode;
-Landroidx/compose/ui/platform/DisposableSaveableStateRegistry;
-Landroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$1;
-Landroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$registered$1;
-Landroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt$DisposableSaveableStateRegistry$saveableStateRegistry$1;
-Landroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt;
-Landroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$1;
-Landroidx/compose/ui/platform/GlobalSnapshotManager$ensureStarted$2;
-Landroidx/compose/ui/platform/GlobalSnapshotManager;
-Landroidx/compose/ui/platform/InspectableModifier$End;
-Landroidx/compose/ui/platform/InspectableModifier;
-Landroidx/compose/ui/platform/InspectableValueKt$NoInspectorInfo$1;
-Landroidx/compose/ui/platform/InspectableValueKt;
-Landroidx/compose/ui/platform/InspectorValueInfo;
-Landroidx/compose/ui/platform/InvertMatrixKt;
-Landroidx/compose/ui/platform/LayerMatrixCache;
-Landroidx/compose/ui/platform/MotionDurationScaleImpl;
-Landroidx/compose/ui/platform/OutlineResolver;
-Landroidx/compose/ui/platform/RenderNodeApi29;
-Landroidx/compose/ui/platform/RenderNodeApi29VerificationHelper;
-Landroidx/compose/ui/platform/RenderNodeLayer$Companion$getMatrix$1;
-Landroidx/compose/ui/platform/RenderNodeLayer$Companion;
-Landroidx/compose/ui/platform/RenderNodeLayer;
-Landroidx/compose/ui/platform/ShapeContainingUtilKt;
-Landroidx/compose/ui/platform/TextToolbar;
-Landroidx/compose/ui/platform/TextToolbarStatus;
-Landroidx/compose/ui/platform/UriHandler;
-Landroidx/compose/ui/platform/ViewCompositionStrategy$Companion;
-Landroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$1;
-Landroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$listener$1;
-Landroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool$installFor$poolingContainerListener$1;
-Landroidx/compose/ui/platform/ViewCompositionStrategy$DisposeOnDetachedFromWindowOrReleasedFromPool;
-Landroidx/compose/ui/platform/ViewCompositionStrategy;
-Landroidx/compose/ui/platform/ViewConfiguration;
-Landroidx/compose/ui/platform/ViewLayer$Companion$OutlineProvider$1;
-Landroidx/compose/ui/platform/ViewLayer$Companion$getMatrix$1;
-Landroidx/compose/ui/platform/ViewLayer$Companion;
-Landroidx/compose/ui/platform/ViewLayer;
-Landroidx/compose/ui/platform/ViewRootForTest$Companion;
-Landroidx/compose/ui/platform/ViewRootForTest;
-Landroidx/compose/ui/platform/WeakCache;
-Landroidx/compose/ui/platform/WindowInfo;
-Landroidx/compose/ui/platform/WindowInfoImpl$Companion;
-Landroidx/compose/ui/platform/WindowInfoImpl;
-Landroidx/compose/ui/platform/WindowRecomposerFactory$Companion$LifecycleAware$1;
-Landroidx/compose/ui/platform/WindowRecomposerFactory$Companion;
-Landroidx/compose/ui/platform/WindowRecomposerFactory;
-Landroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$1;
-Landroidx/compose/ui/platform/WindowRecomposerPolicy$createAndInstallWindowRecomposer$unsetJob$1;
-Landroidx/compose/ui/platform/WindowRecomposerPolicy;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$1;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$WhenMappings;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1$1;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1$1$1;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2$onStateChanged$1;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$createLifecycleAwareWindowRecomposer$2;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$1;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt$getAnimationScaleFlowFor$1$1$contentObserver$1;
-Landroidx/compose/ui/platform/WindowRecomposer_androidKt;
-Landroidx/compose/ui/platform/WrappedComposition$setContent$1$1$1;
-Landroidx/compose/ui/platform/WrappedComposition$setContent$1$1$2;
-Landroidx/compose/ui/platform/WrappedComposition$setContent$1$1$3;
-Landroidx/compose/ui/platform/WrappedComposition$setContent$1$1;
-Landroidx/compose/ui/platform/WrappedComposition$setContent$1;
-Landroidx/compose/ui/platform/WrappedComposition;
-Landroidx/compose/ui/platform/WrapperRenderNodeLayerHelperMethods;
-Landroidx/compose/ui/platform/WrapperVerificationHelperMethods;
-Landroidx/compose/ui/platform/Wrapper_androidKt;
-Landroidx/compose/ui/platform/actionmodecallback/TextActionModeCallback;
-Landroidx/compose/ui/res/ImageVectorCache;
-Landroidx/compose/ui/res/Resources_androidKt;
-Landroidx/compose/ui/res/StringResources_androidKt;
-Landroidx/compose/ui/semantics/AccessibilityAction;
-Landroidx/compose/ui/semantics/CollectionInfo;
-Landroidx/compose/ui/semantics/Role$Companion;
-Landroidx/compose/ui/semantics/Role;
-Landroidx/compose/ui/semantics/ScrollAxisRange;
-Landroidx/compose/ui/semantics/SemanticsActions;
-Landroidx/compose/ui/semantics/SemanticsConfiguration;
-Landroidx/compose/ui/semantics/SemanticsConfigurationKt$getOrNull$1;
-Landroidx/compose/ui/semantics/SemanticsConfigurationKt;
-Landroidx/compose/ui/semantics/SemanticsModifier;
-Landroidx/compose/ui/semantics/SemanticsModifierCore$Companion;
-Landroidx/compose/ui/semantics/SemanticsModifierCore;
-Landroidx/compose/ui/semantics/SemanticsModifierKt;
-Landroidx/compose/ui/semantics/SemanticsNode;
-Landroidx/compose/ui/semantics/SemanticsNodeKt;
-Landroidx/compose/ui/semantics/SemanticsOwner;
-Landroidx/compose/ui/semantics/SemanticsProperties$ContentDescription$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$InvisibleToUser$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$IsDialog$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$IsPopup$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$PaneTitle$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$Role$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$TestTag$1;
-Landroidx/compose/ui/semantics/SemanticsProperties$Text$1;
-Landroidx/compose/ui/semantics/SemanticsProperties;
-Landroidx/compose/ui/semantics/SemanticsPropertiesKt$ActionPropertyKey$1;
-Landroidx/compose/ui/semantics/SemanticsPropertiesKt;
-Landroidx/compose/ui/semantics/SemanticsPropertyKey$1;
-Landroidx/compose/ui/semantics/SemanticsPropertyKey;
-Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;
-Landroidx/compose/ui/text/AndroidParagraph$wordBoundary$2;
-Landroidx/compose/ui/text/AndroidParagraph;
-Landroidx/compose/ui/text/AndroidParagraph_androidKt;
-Landroidx/compose/ui/text/AnnotatedString$Range;
-Landroidx/compose/ui/text/AnnotatedString;
-Landroidx/compose/ui/text/AnnotatedStringKt;
-Landroidx/compose/ui/text/EmojiSupportMatch$Companion;
-Landroidx/compose/ui/text/EmojiSupportMatch;
-Landroidx/compose/ui/text/MultiParagraph;
-Landroidx/compose/ui/text/MultiParagraphIntrinsics$maxIntrinsicWidth$2;
-Landroidx/compose/ui/text/MultiParagraphIntrinsics$minIntrinsicWidth$2;
-Landroidx/compose/ui/text/MultiParagraphIntrinsics;
-Landroidx/compose/ui/text/MultiParagraphIntrinsicsKt;
-Landroidx/compose/ui/text/Paragraph;
-Landroidx/compose/ui/text/ParagraphInfo;
-Landroidx/compose/ui/text/ParagraphIntrinsicInfo;
-Landroidx/compose/ui/text/ParagraphIntrinsics;
-Landroidx/compose/ui/text/ParagraphIntrinsicsKt;
-Landroidx/compose/ui/text/ParagraphKt;
-Landroidx/compose/ui/text/ParagraphStyle;
-Landroidx/compose/ui/text/ParagraphStyleKt;
-Landroidx/compose/ui/text/PlatformTextStyle;
-Landroidx/compose/ui/text/SpanStyle;
-Landroidx/compose/ui/text/SpanStyleKt$resolveSpanStyleDefaults$1;
-Landroidx/compose/ui/text/SpanStyleKt;
-Landroidx/compose/ui/text/TextLayoutInput;
-Landroidx/compose/ui/text/TextLayoutResult;
-Landroidx/compose/ui/text/TextPainter;
-Landroidx/compose/ui/text/TextRange$Companion;
-Landroidx/compose/ui/text/TextRange;
-Landroidx/compose/ui/text/TextRangeKt;
-Landroidx/compose/ui/text/TextStyle$Companion;
-Landroidx/compose/ui/text/TextStyle;
-Landroidx/compose/ui/text/TextStyleKt$WhenMappings;
-Landroidx/compose/ui/text/TextStyleKt;
-Landroidx/compose/ui/text/android/BoringLayoutFactory33;
-Landroidx/compose/ui/text/android/BoringLayoutFactory;
-Landroidx/compose/ui/text/android/LayoutIntrinsics$boringMetrics$2;
-Landroidx/compose/ui/text/android/LayoutIntrinsics$maxIntrinsicWidth$2;
-Landroidx/compose/ui/text/android/LayoutIntrinsics$minIntrinsicWidth$2;
-Landroidx/compose/ui/text/android/LayoutIntrinsics;
-Landroidx/compose/ui/text/android/LayoutIntrinsicsKt;
-Landroidx/compose/ui/text/android/SpannedExtensionsKt;
-Landroidx/compose/ui/text/android/StaticLayoutFactory23;
-Landroidx/compose/ui/text/android/StaticLayoutFactory26;
-Landroidx/compose/ui/text/android/StaticLayoutFactory28;
-Landroidx/compose/ui/text/android/StaticLayoutFactory33;
-Landroidx/compose/ui/text/android/StaticLayoutFactory;
-Landroidx/compose/ui/text/android/StaticLayoutFactoryImpl;
-Landroidx/compose/ui/text/android/StaticLayoutParams;
-Landroidx/compose/ui/text/android/TextAlignmentAdapter;
-Landroidx/compose/ui/text/android/TextAndroidCanvas;
-Landroidx/compose/ui/text/android/TextLayout$Companion;
-Landroidx/compose/ui/text/android/TextLayout$layoutHelper$2;
-Landroidx/compose/ui/text/android/TextLayout;
-Landroidx/compose/ui/text/android/TextLayoutKt;
-Landroidx/compose/ui/text/android/style/BaselineShiftSpan;
-Landroidx/compose/ui/text/android/style/IndentationFixSpanKt;
-Landroidx/compose/ui/text/android/style/LetterSpacingSpanEm;
-Landroidx/compose/ui/text/android/style/LetterSpacingSpanPx;
-Landroidx/compose/ui/text/android/style/LineHeightSpan;
-Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;
-Landroidx/compose/ui/text/android/style/LineHeightStyleSpanKt;
-Landroidx/compose/ui/text/android/style/PlaceholderSpan;
-Landroidx/compose/ui/text/caches/ContainerHelpersKt;
-Landroidx/compose/ui/text/caches/LruCache;
-Landroidx/compose/ui/text/caches/SimpleArrayMap;
-Landroidx/compose/ui/text/font/AndroidFont$TypefaceLoader;
-Landroidx/compose/ui/text/font/AndroidFont;
-Landroidx/compose/ui/text/font/AndroidFontLoader;
-Landroidx/compose/ui/text/font/AndroidFontResolveInterceptor;
-Landroidx/compose/ui/text/font/AndroidFontResolveInterceptor_androidKt;
-Landroidx/compose/ui/text/font/AsyncTypefaceCache$AsyncTypefaceResult;
-Landroidx/compose/ui/text/font/AsyncTypefaceCache$Key;
-Landroidx/compose/ui/text/font/AsyncTypefaceCache;
-Landroidx/compose/ui/text/font/DefaultFontFamily;
-Landroidx/compose/ui/text/font/DeviceFontFamilyName;
-Landroidx/compose/ui/text/font/DeviceFontFamilyNameFont;
-Landroidx/compose/ui/text/font/DeviceFontFamilyNameFontKt;
-Landroidx/compose/ui/text/font/FileBasedFontFamily;
-Landroidx/compose/ui/text/font/Font$ResourceLoader;
-Landroidx/compose/ui/text/font/Font;
-Landroidx/compose/ui/text/font/FontFamily$Companion;
-Landroidx/compose/ui/text/font/FontFamily$Resolver;
-Landroidx/compose/ui/text/font/FontFamily;
-Landroidx/compose/ui/text/font/FontFamilyKt;
-Landroidx/compose/ui/text/font/FontFamilyResolverImpl$createDefaultTypeface$1;
-Landroidx/compose/ui/text/font/FontFamilyResolverImpl$resolve$result$1;
-Landroidx/compose/ui/text/font/FontFamilyResolverImpl;
-Landroidx/compose/ui/text/font/FontFamilyResolverKt;
-Landroidx/compose/ui/text/font/FontFamilyResolver_androidKt;
-Landroidx/compose/ui/text/font/FontListFontFamily;
-Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter$Companion;
-Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter$special$$inlined$CoroutineExceptionHandler$1;
-Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapter;
-Landroidx/compose/ui/text/font/FontListFontFamilyTypefaceAdapterKt;
-Landroidx/compose/ui/text/font/FontLoadingStrategy$Companion;
-Landroidx/compose/ui/text/font/FontLoadingStrategy;
-Landroidx/compose/ui/text/font/FontMatcher;
-Landroidx/compose/ui/text/font/FontStyle$Companion;
-Landroidx/compose/ui/text/font/FontStyle;
-Landroidx/compose/ui/text/font/FontSynthesis$Companion;
-Landroidx/compose/ui/text/font/FontSynthesis;
-Landroidx/compose/ui/text/font/FontSynthesis_androidKt;
-Landroidx/compose/ui/text/font/FontVariation$Setting;
-Landroidx/compose/ui/text/font/FontVariation$Settings;
-Landroidx/compose/ui/text/font/FontWeight$Companion;
-Landroidx/compose/ui/text/font/FontWeight;
-Landroidx/compose/ui/text/font/GenericFontFamily;
-Landroidx/compose/ui/text/font/NamedFontLoader;
-Landroidx/compose/ui/text/font/PlatformFontFamilyTypefaceAdapter;
-Landroidx/compose/ui/text/font/PlatformFontLoader;
-Landroidx/compose/ui/text/font/PlatformResolveInterceptor$Companion$Default$1;
-Landroidx/compose/ui/text/font/PlatformResolveInterceptor$Companion;
-Landroidx/compose/ui/text/font/PlatformResolveInterceptor;
-Landroidx/compose/ui/text/font/PlatformTypefaces;
-Landroidx/compose/ui/text/font/PlatformTypefacesApi28;
-Landroidx/compose/ui/text/font/PlatformTypefacesKt;
-Landroidx/compose/ui/text/font/SystemFontFamily;
-Landroidx/compose/ui/text/font/TypefaceCompatApi26;
-Landroidx/compose/ui/text/font/TypefaceHelperMethodsApi28;
-Landroidx/compose/ui/text/font/TypefaceRequest;
-Landroidx/compose/ui/text/font/TypefaceRequestCache$runCached$currentTypefaceResult$1;
-Landroidx/compose/ui/text/font/TypefaceRequestCache;
-Landroidx/compose/ui/text/font/TypefaceResult$Immutable;
-Landroidx/compose/ui/text/font/TypefaceResult;
-Landroidx/compose/ui/text/input/ImeAction$Companion;
-Landroidx/compose/ui/text/input/ImeAction;
-Landroidx/compose/ui/text/input/ImeOptions$Companion;
-Landroidx/compose/ui/text/input/ImeOptions;
-Landroidx/compose/ui/text/input/ImmHelper30;
-Landroidx/compose/ui/text/input/ImmHelper;
-Landroidx/compose/ui/text/input/InputMethodManager;
-Landroidx/compose/ui/text/input/InputMethodManagerImpl$imm$2;
-Landroidx/compose/ui/text/input/InputMethodManagerImpl;
-Landroidx/compose/ui/text/input/KeyboardCapitalization$Companion;
-Landroidx/compose/ui/text/input/KeyboardCapitalization;
-Landroidx/compose/ui/text/input/KeyboardType$Companion;
-Landroidx/compose/ui/text/input/KeyboardType;
-Landroidx/compose/ui/text/input/PlatformTextInputService;
-Landroidx/compose/ui/text/input/TextFieldValue$Companion$Saver$1;
-Landroidx/compose/ui/text/input/TextFieldValue$Companion$Saver$2;
-Landroidx/compose/ui/text/input/TextFieldValue$Companion;
-Landroidx/compose/ui/text/input/TextFieldValue;
-Landroidx/compose/ui/text/input/TextInputService;
-Landroidx/compose/ui/text/input/TextInputServiceAndroid$baseInputConnection$2;
-Landroidx/compose/ui/text/input/TextInputServiceAndroid$onEditCommand$1;
-Landroidx/compose/ui/text/input/TextInputServiceAndroid$onImeActionPerformed$1;
-Landroidx/compose/ui/text/input/TextInputServiceAndroid$textInputCommandEventLoop$1;
-Landroidx/compose/ui/text/input/TextInputServiceAndroid;
-Landroidx/compose/ui/text/intl/AndroidLocale;
-Landroidx/compose/ui/text/intl/AndroidLocaleDelegateAPI24;
-Landroidx/compose/ui/text/intl/AndroidPlatformLocale_androidKt;
-Landroidx/compose/ui/text/intl/Locale$Companion;
-Landroidx/compose/ui/text/intl/Locale;
-Landroidx/compose/ui/text/intl/LocaleList$Companion;
-Landroidx/compose/ui/text/intl/LocaleList;
-Landroidx/compose/ui/text/intl/PlatformLocale;
-Landroidx/compose/ui/text/intl/PlatformLocaleDelegate;
-Landroidx/compose/ui/text/intl/PlatformLocaleKt;
-Landroidx/compose/ui/text/platform/AndroidParagraphHelper_androidKt$NoopSpan$1;
-Landroidx/compose/ui/text/platform/AndroidParagraphHelper_androidKt;
-Landroidx/compose/ui/text/platform/AndroidParagraphIntrinsics$resolveTypeface$1;
-Landroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;
-Landroidx/compose/ui/text/platform/AndroidParagraphIntrinsics_androidKt;
-Landroidx/compose/ui/text/platform/AndroidParagraph_androidKt;
-Landroidx/compose/ui/text/platform/AndroidTextPaint;
-Landroidx/compose/ui/text/platform/DefaultImpl$getFontLoadState$initCallback$1;
-Landroidx/compose/ui/text/platform/DefaultImpl;
-Landroidx/compose/ui/text/platform/EmojiCompatStatus;
-Landroidx/compose/ui/text/platform/EmojiCompatStatusDelegate;
-Landroidx/compose/ui/text/platform/ImmutableBool;
-Landroidx/compose/ui/text/platform/Synchronization_jvmKt;
-Landroidx/compose/ui/text/platform/SynchronizedObject;
-Landroidx/compose/ui/text/platform/extensions/PlaceholderExtensions_androidKt;
-Landroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt$setFontAttributes$1;
-Landroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;
-Landroidx/compose/ui/text/platform/extensions/TextPaintExtensions_androidKt;
-Landroidx/compose/ui/text/platform/style/ShaderBrushSpan;
-Landroidx/compose/ui/text/style/BaselineShift$Companion;
-Landroidx/compose/ui/text/style/BaselineShift;
-Landroidx/compose/ui/text/style/BrushStyle;
-Landroidx/compose/ui/text/style/ColorStyle;
-Landroidx/compose/ui/text/style/Hyphens$Companion;
-Landroidx/compose/ui/text/style/Hyphens;
-Landroidx/compose/ui/text/style/LineBreak$Companion;
-Landroidx/compose/ui/text/style/LineBreak$Strategy$Companion;
-Landroidx/compose/ui/text/style/LineBreak$Strategy;
-Landroidx/compose/ui/text/style/LineBreak$Strictness$Companion;
-Landroidx/compose/ui/text/style/LineBreak$Strictness;
-Landroidx/compose/ui/text/style/LineBreak$WordBreak$Companion;
-Landroidx/compose/ui/text/style/LineBreak$WordBreak;
-Landroidx/compose/ui/text/style/LineBreak;
-Landroidx/compose/ui/text/style/LineBreak_androidKt;
-Landroidx/compose/ui/text/style/LineHeightStyle;
-Landroidx/compose/ui/text/style/TextAlign$Companion;
-Landroidx/compose/ui/text/style/TextAlign;
-Landroidx/compose/ui/text/style/TextDecoration$Companion;
-Landroidx/compose/ui/text/style/TextDecoration;
-Landroidx/compose/ui/text/style/TextDirection$Companion;
-Landroidx/compose/ui/text/style/TextDirection;
-Landroidx/compose/ui/text/style/TextForegroundStyle$Companion;
-Landroidx/compose/ui/text/style/TextForegroundStyle$Unspecified;
-Landroidx/compose/ui/text/style/TextForegroundStyle$merge$2;
-Landroidx/compose/ui/text/style/TextForegroundStyle;
-Landroidx/compose/ui/text/style/TextGeometricTransform$Companion;
-Landroidx/compose/ui/text/style/TextGeometricTransform;
-Landroidx/compose/ui/text/style/TextIndent$Companion;
-Landroidx/compose/ui/text/style/TextIndent;
-Landroidx/compose/ui/text/style/TextMotion$Companion;
-Landroidx/compose/ui/text/style/TextMotion$Linearity$Companion;
-Landroidx/compose/ui/text/style/TextMotion$Linearity;
-Landroidx/compose/ui/text/style/TextMotion;
-Landroidx/compose/ui/text/style/TextOverflow$Companion;
-Landroidx/compose/ui/text/style/TextOverflow;
-Landroidx/compose/ui/unit/AndroidDensity_androidKt;
-Landroidx/compose/ui/unit/Constraints$Companion;
-Landroidx/compose/ui/unit/Constraints;
-Landroidx/compose/ui/unit/ConstraintsKt;
-Landroidx/compose/ui/unit/Density;
-Landroidx/compose/ui/unit/DensityImpl;
-Landroidx/compose/ui/unit/DensityKt;
-Landroidx/compose/ui/unit/Dp$Companion;
-Landroidx/compose/ui/unit/Dp;
-Landroidx/compose/ui/unit/DpKt;
-Landroidx/compose/ui/unit/DpOffset$Companion;
-Landroidx/compose/ui/unit/DpOffset;
-Landroidx/compose/ui/unit/DpSize$Companion;
-Landroidx/compose/ui/unit/DpSize;
-Landroidx/compose/ui/unit/IntOffset$Companion;
-Landroidx/compose/ui/unit/IntOffset;
-Landroidx/compose/ui/unit/IntOffsetKt;
-Landroidx/compose/ui/unit/IntSize$Companion;
-Landroidx/compose/ui/unit/IntSize;
-Landroidx/compose/ui/unit/IntSizeKt;
-Landroidx/compose/ui/unit/LayoutDirection;
-Landroidx/compose/ui/unit/TextUnit$Companion;
-Landroidx/compose/ui/unit/TextUnit;
-Landroidx/compose/ui/unit/TextUnitKt;
-Landroidx/compose/ui/unit/TextUnitType$Companion;
-Landroidx/compose/ui/unit/TextUnitType;
-Landroidx/compose/ui/util/MathHelpersKt;
-Landroidx/core/R$id;
-Landroidx/core/app/ComponentActivity;
-Landroidx/core/app/CoreComponentFactory;
-Landroidx/core/graphics/Insets;
-Landroidx/core/graphics/TypefaceCompat;
-Landroidx/core/graphics/TypefaceCompatApi29Impl;
-Landroidx/core/graphics/TypefaceCompatBaseImpl;
-Landroidx/core/graphics/TypefaceCompatUtil$Api19Impl;
-Landroidx/core/graphics/TypefaceCompatUtil;
-Landroidx/core/graphics/drawable/DrawableKt;
-Landroidx/core/os/BuildCompat$Extensions30Impl;
-Landroidx/core/os/BuildCompat;
-Landroidx/core/os/HandlerCompat$Api28Impl;
-Landroidx/core/os/HandlerCompat;
-Landroidx/core/os/TraceCompat$Api18Impl;
-Landroidx/core/os/TraceCompat;
-Landroidx/core/provider/FontProvider$$ExternalSyntheticLambda0;
-Landroidx/core/provider/FontProvider$Api16Impl;
-Landroidx/core/provider/FontProvider;
-Landroidx/core/provider/FontRequest;
-Landroidx/core/provider/FontsContractCompat$FontFamilyResult;
-Landroidx/core/provider/FontsContractCompat$FontInfo;
-Landroidx/core/provider/FontsContractCompat;
-Landroidx/core/util/Preconditions;
-Landroidx/core/view/AccessibilityDelegateCompat$AccessibilityDelegateAdapter;
-Landroidx/core/view/AccessibilityDelegateCompat;
-Landroidx/core/view/KeyEventDispatcher$Component;
-Landroidx/core/view/MenuHostHelper;
-Landroidx/core/view/OnApplyWindowInsetsListener;
-Landroidx/core/view/OnReceiveContentViewBehavior;
-Landroidx/core/view/ViewCompat$$ExternalSyntheticLambda0;
-Landroidx/core/view/ViewCompat$AccessibilityPaneVisibilityManager;
-Landroidx/core/view/ViewCompat$Api21Impl$1;
-Landroidx/core/view/ViewCompat$Api21Impl;
-Landroidx/core/view/ViewCompat;
-Landroidx/core/view/ViewKt$ancestors$1;
-Landroidx/core/view/ViewKt;
-Landroidx/core/view/WindowCompat;
-Landroidx/core/view/WindowInsetsAnimationCompat$Callback;
-Landroidx/core/view/WindowInsetsAnimationCompat$Impl30$ProxyCallback;
-Landroidx/core/view/WindowInsetsAnimationCompat$Impl30;
-Landroidx/core/view/WindowInsetsAnimationCompat$Impl;
-Landroidx/core/view/WindowInsetsAnimationCompat;
-Landroidx/core/view/WindowInsetsCompat$Type;
-Landroidx/core/view/WindowInsetsCompat;
-Landroidx/core/view/WindowInsetsControllerCompat$Impl30;
-Landroidx/core/view/WindowInsetsControllerCompat$Impl;
-Landroidx/core/view/WindowInsetsControllerCompat;
-Landroidx/core/view/accessibility/AccessibilityNodeProviderCompat;
-Landroidx/credentials/provider/Action$Companion;
-Landroidx/credentials/provider/Action;
-Landroidx/credentials/provider/AuthenticationAction$Companion;
-Landroidx/credentials/provider/AuthenticationAction;
-Landroidx/credentials/provider/RemoteEntry$Companion;
-Landroidx/credentials/provider/RemoteEntry;
-Landroidx/customview/poolingcontainer/PoolingContainer;
-Landroidx/customview/poolingcontainer/PoolingContainerListener;
-Landroidx/customview/poolingcontainer/PoolingContainerListenerHolder;
-Landroidx/customview/poolingcontainer/R$id;
-Landroidx/emoji2/text/ConcurrencyHelpers$$ExternalSyntheticLambda0;
-Landroidx/emoji2/text/ConcurrencyHelpers$Handler28Impl;
-Landroidx/emoji2/text/ConcurrencyHelpers;
-Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;
-Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;
-Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19;
-Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28;
-Landroidx/emoji2/text/DefaultEmojiCompatConfig;
-Landroidx/emoji2/text/DefaultGlyphChecker;
-Landroidx/emoji2/text/EmojiCompat$CompatInternal19$1;
-Landroidx/emoji2/text/EmojiCompat$CompatInternal19;
-Landroidx/emoji2/text/EmojiCompat$CompatInternal;
-Landroidx/emoji2/text/EmojiCompat$Config;
-Landroidx/emoji2/text/EmojiCompat$DefaultSpanFactory;
-Landroidx/emoji2/text/EmojiCompat$GlyphChecker;
-Landroidx/emoji2/text/EmojiCompat$InitCallback;
-Landroidx/emoji2/text/EmojiCompat$ListenerDispatcher;
-Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;
-Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;
-Landroidx/emoji2/text/EmojiCompat$SpanFactory;
-Landroidx/emoji2/text/EmojiCompat;
-Landroidx/emoji2/text/EmojiCompatInitializer$1;
-Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultConfig;
-Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader$$ExternalSyntheticLambda0;
-Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader$1;
-Landroidx/emoji2/text/EmojiCompatInitializer$BackgroundDefaultLoader;
-Landroidx/emoji2/text/EmojiCompatInitializer$LoadEmojiCompatRunnable;
-Landroidx/emoji2/text/EmojiCompatInitializer;
-Landroidx/emoji2/text/EmojiExclusions$EmojiExclusions_Api34;
-Landroidx/emoji2/text/EmojiExclusions$EmojiExclusions_Reflections;
-Landroidx/emoji2/text/EmojiExclusions;
-Landroidx/emoji2/text/EmojiProcessor$EmojiProcessAddSpanCallback;
-Landroidx/emoji2/text/EmojiProcessor$EmojiProcessCallback;
-Landroidx/emoji2/text/EmojiProcessor$ProcessorSm;
-Landroidx/emoji2/text/EmojiProcessor;
-Landroidx/emoji2/text/FontRequestEmojiCompatConfig$FontProviderHelper;
-Landroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader$$ExternalSyntheticLambda0;
-Landroidx/emoji2/text/FontRequestEmojiCompatConfig$FontRequestMetadataLoader;
-Landroidx/emoji2/text/FontRequestEmojiCompatConfig;
-Landroidx/emoji2/text/MetadataListReader$ByteBufferReader;
-Landroidx/emoji2/text/MetadataListReader$OffsetInfo;
-Landroidx/emoji2/text/MetadataListReader$OpenTypeReader;
-Landroidx/emoji2/text/MetadataListReader;
-Landroidx/emoji2/text/MetadataRepo$Node;
-Landroidx/emoji2/text/MetadataRepo;
-Landroidx/emoji2/text/SpannableBuilder;
-Landroidx/emoji2/text/TypefaceEmojiRasterizer;
-Landroidx/emoji2/text/UnprecomputeTextOnModificationSpannable;
-Landroidx/emoji2/text/flatbuffer/MetadataItem;
-Landroidx/emoji2/text/flatbuffer/MetadataList;
-Landroidx/emoji2/text/flatbuffer/Table;
-Landroidx/emoji2/text/flatbuffer/Utf8;
-Landroidx/emoji2/text/flatbuffer/Utf8Safe;
-Landroidx/lifecycle/DefaultLifecycleObserver;
-Landroidx/lifecycle/EmptyActivityLifecycleCallbacks;
-Landroidx/lifecycle/FullLifecycleObserver;
-Landroidx/lifecycle/FullLifecycleObserverAdapter$1;
-Landroidx/lifecycle/FullLifecycleObserverAdapter;
-Landroidx/lifecycle/HasDefaultViewModelProviderFactory;
-Landroidx/lifecycle/Lifecycle$1;
-Landroidx/lifecycle/Lifecycle$Event;
-Landroidx/lifecycle/Lifecycle$State;
-Landroidx/lifecycle/Lifecycle;
-Landroidx/lifecycle/LifecycleDispatcher$DispatcherActivityCallback;
-Landroidx/lifecycle/LifecycleDispatcher;
-Landroidx/lifecycle/LifecycleEventObserver;
-Landroidx/lifecycle/LifecycleObserver;
-Landroidx/lifecycle/LifecycleOwner;
-Landroidx/lifecycle/LifecycleRegistry$ObserverWithState;
-Landroidx/lifecycle/LifecycleRegistry;
-Landroidx/lifecycle/Lifecycling;
-Landroidx/lifecycle/ProcessLifecycleInitializer;
-Landroidx/lifecycle/ProcessLifecycleOwner$1;
-Landroidx/lifecycle/ProcessLifecycleOwner$2;
-Landroidx/lifecycle/ProcessLifecycleOwner$3$1;
-Landroidx/lifecycle/ProcessLifecycleOwner$3;
-Landroidx/lifecycle/ProcessLifecycleOwner$Api29Impl;
-Landroidx/lifecycle/ProcessLifecycleOwner;
-Landroidx/lifecycle/ReportFragment$ActivityInitializationListener;
-Landroidx/lifecycle/ReportFragment$LifecycleCallbacks;
-Landroidx/lifecycle/ReportFragment;
-Landroidx/lifecycle/SavedStateHandleAttacher;
-Landroidx/lifecycle/SavedStateHandleSupport$DEFAULT_ARGS_KEY$1;
-Landroidx/lifecycle/SavedStateHandleSupport$SAVED_STATE_REGISTRY_OWNER_KEY$1;
-Landroidx/lifecycle/SavedStateHandleSupport$VIEW_MODEL_STORE_OWNER_KEY$1;
-Landroidx/lifecycle/SavedStateHandleSupport$savedStateHandlesVM$1$1;
-Landroidx/lifecycle/SavedStateHandleSupport;
-Landroidx/lifecycle/SavedStateHandlesProvider$viewModel$2;
-Landroidx/lifecycle/SavedStateHandlesProvider;
-Landroidx/lifecycle/SavedStateHandlesVM;
-Landroidx/lifecycle/ViewModel;
-Landroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory$Companion$ApplicationKeyImpl;
-Landroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory$Companion;
-Landroidx/lifecycle/ViewModelProvider$AndroidViewModelFactory;
-Landroidx/lifecycle/ViewModelProvider$Factory$Companion;
-Landroidx/lifecycle/ViewModelProvider$Factory;
-Landroidx/lifecycle/ViewModelProvider$NewInstanceFactory$Companion$ViewModelKeyImpl;
-Landroidx/lifecycle/ViewModelProvider$NewInstanceFactory$Companion;
-Landroidx/lifecycle/ViewModelProvider$NewInstanceFactory;
-Landroidx/lifecycle/ViewModelProvider$OnRequeryFactory;
-Landroidx/lifecycle/ViewModelProvider;
-Landroidx/lifecycle/ViewModelProviderGetKt;
-Landroidx/lifecycle/ViewModelStore;
-Landroidx/lifecycle/ViewModelStoreOwner;
-Landroidx/lifecycle/ViewTreeLifecycleOwner;
-Landroidx/lifecycle/ViewTreeViewModelStoreOwner;
-Landroidx/lifecycle/runtime/R$id;
-Landroidx/lifecycle/viewmodel/CreationExtras$Empty;
-Landroidx/lifecycle/viewmodel/CreationExtras$Key;
-Landroidx/lifecycle/viewmodel/CreationExtras;
-Landroidx/lifecycle/viewmodel/InitializerViewModelFactory;
-Landroidx/lifecycle/viewmodel/InitializerViewModelFactoryBuilder;
-Landroidx/lifecycle/viewmodel/MutableCreationExtras;
-Landroidx/lifecycle/viewmodel/R$id;
-Landroidx/lifecycle/viewmodel/ViewModelInitializer;
-Landroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner$LocalViewModelStoreOwner$1;
-Landroidx/lifecycle/viewmodel/compose/LocalViewModelStoreOwner;
-Landroidx/lifecycle/viewmodel/compose/ViewModelKt;
-Landroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda0;
-Landroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;
-Landroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl$$ExternalSyntheticLambda0;
-Landroidx/profileinstaller/ProfileInstallerInitializer$Choreographer16Impl;
-Landroidx/profileinstaller/ProfileInstallerInitializer$Handler28Impl;
-Landroidx/profileinstaller/ProfileInstallerInitializer$Result;
-Landroidx/profileinstaller/ProfileInstallerInitializer;
-Landroidx/savedstate/R$id;
-Landroidx/savedstate/Recreator$Companion;
-Landroidx/savedstate/Recreator;
-Landroidx/savedstate/SavedStateRegistry$$ExternalSyntheticLambda0;
-Landroidx/savedstate/SavedStateRegistry$Companion;
-Landroidx/savedstate/SavedStateRegistry$SavedStateProvider;
-Landroidx/savedstate/SavedStateRegistry;
-Landroidx/savedstate/SavedStateRegistryController$Companion;
-Landroidx/savedstate/SavedStateRegistryController;
-Landroidx/savedstate/SavedStateRegistryOwner;
-Landroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$1;
-Landroidx/savedstate/ViewTreeSavedStateRegistryOwner$findViewTreeSavedStateRegistryOwner$2;
-Landroidx/savedstate/ViewTreeSavedStateRegistryOwner;
-Landroidx/startup/AppInitializer;
-Landroidx/startup/InitializationProvider;
-Landroidx/startup/Initializer;
-Landroidx/startup/R$string;
-Landroidx/tracing/Trace;
-Landroidx/tracing/TraceApi18Impl;
-Landroidx/tracing/TraceApi29Impl;
-Lcom/android/compose/AndroidSystemUiController;
-Lcom/android/compose/SystemUiController;
-Lcom/android/compose/SystemUiControllerKt$BlackScrimmed$1;
-Lcom/android/compose/SystemUiControllerKt;
-Lcom/android/credentialmanager/CancelUiRequestState;
-Lcom/android/credentialmanager/CredentialManagerRepo$Companion;
-Lcom/android/credentialmanager/CredentialManagerRepo;
-Lcom/android/credentialmanager/CredentialSelectorActivity$Companion;
-Lcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$1;
-Lcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$3;
-Lcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$launcher$1;
-Lcom/android/credentialmanager/CredentialSelectorActivity$CredentialManagerBottomSheet$viewModel$1;
-Lcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1$1;
-Lcom/android/credentialmanager/CredentialSelectorActivity$onCreate$1;
-Lcom/android/credentialmanager/CredentialSelectorActivity$onCreate$backPressedCallback$1;
-Lcom/android/credentialmanager/CredentialSelectorActivity;
-Lcom/android/credentialmanager/CredentialSelectorViewModel;
-Lcom/android/credentialmanager/DataConverterKt;
-Lcom/android/credentialmanager/GetFlowUtils$Companion;
-Lcom/android/credentialmanager/GetFlowUtils;
-Lcom/android/credentialmanager/UiState;
-Lcom/android/credentialmanager/UserConfigRepo$Companion;
-Lcom/android/credentialmanager/UserConfigRepo;
-Lcom/android/credentialmanager/common/BaseEntry;
-Lcom/android/credentialmanager/common/CredentialType;
-Lcom/android/credentialmanager/common/DialogState;
-Lcom/android/credentialmanager/common/ProviderActivityState;
-Lcom/android/credentialmanager/common/StartBalIntentSenderForResultContract;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetDefaults;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$2$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$3$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$3;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$2$4;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$2;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$2;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$2$1$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$2$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$2;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetKt;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$1;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion$Saver$2;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetState$Companion;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetState;
-Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;
-Lcom/android/credentialmanager/common/material/ResistanceConfig;
-Lcom/android/credentialmanager/common/material/SwipeableDefaults;
-Lcom/android/credentialmanager/common/material/SwipeableKt$PreUpPostDownNestedScrollConnection$1;
-Lcom/android/credentialmanager/common/material/SwipeableKt$swipeable$1;
-Lcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$3$1;
-Lcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$3;
-Lcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3$4$1;
-Lcom/android/credentialmanager/common/material/SwipeableKt$swipeable$3;
-Lcom/android/credentialmanager/common/material/SwipeableKt;
-Lcom/android/credentialmanager/common/material/SwipeableState$Companion;
-Lcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$animateInternalToOffset$2;
-Lcom/android/credentialmanager/common/material/SwipeableState$animateTo$2$emit$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$animateTo$2;
-Lcom/android/credentialmanager/common/material/SwipeableState$draggableState$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$latestNonEmptyAnchorsFlow$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$processNewAnchors$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$snapInternalToOffset$2;
-Lcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1$2;
-Lcom/android/credentialmanager/common/material/SwipeableState$special$$inlined$filter$1;
-Lcom/android/credentialmanager/common/material/SwipeableState$thresholds$2;
-Lcom/android/credentialmanager/common/material/SwipeableState;
-Lcom/android/credentialmanager/common/ui/ActionButtonKt$ActionButton$1;
-Lcom/android/credentialmanager/common/ui/ActionButtonKt$ActionButton$2;
-Lcom/android/credentialmanager/common/ui/ActionButtonKt;
-Lcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1$1;
-Lcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$1;
-Lcom/android/credentialmanager/common/ui/BottomSheetKt$ModalBottomSheet$2;
-Lcom/android/credentialmanager/common/ui/BottomSheetKt;
-Lcom/android/credentialmanager/common/ui/CardsKt$CredentialContainerCard$1;
-Lcom/android/credentialmanager/common/ui/CardsKt$SheetContainerCard$1;
-Lcom/android/credentialmanager/common/ui/CardsKt$SheetContainerCard$2;
-Lcom/android/credentialmanager/common/ui/CardsKt;
-Lcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt$lambda-1$1;
-Lcom/android/credentialmanager/common/ui/ComposableSingletons$BottomSheetKt;
-Lcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt$lambda-1$1;
-Lcom/android/credentialmanager/common/ui/ComposableSingletons$EntryKt;
-Lcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt$lambda-1$1;
-Lcom/android/credentialmanager/common/ui/ComposableSingletons$SnackBarKt;
-Lcom/android/credentialmanager/common/ui/ConfirmButtonKt$ConfirmButton$1;
-Lcom/android/credentialmanager/common/ui/ConfirmButtonKt$ConfirmButton$2;
-Lcom/android/credentialmanager/common/ui/ConfirmButtonKt;
-Lcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$1;
-Lcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$2;
-Lcom/android/credentialmanager/common/ui/EntryKt$ActionEntry$3;
-Lcom/android/credentialmanager/common/ui/EntryKt$Entry$1;
-Lcom/android/credentialmanager/common/ui/EntryKt$Entry$3;
-Lcom/android/credentialmanager/common/ui/EntryKt$Entry$4;
-Lcom/android/credentialmanager/common/ui/EntryKt$Entry$6;
-Lcom/android/credentialmanager/common/ui/EntryKt$Entry$7;
-Lcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$1;
-Lcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$2;
-Lcom/android/credentialmanager/common/ui/EntryKt$MoreOptionTopAppBar$3;
-Lcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1$WhenMappings;
-Lcom/android/credentialmanager/common/ui/EntryKt$autoMirrored$1;
-Lcom/android/credentialmanager/common/ui/EntryKt;
-Lcom/android/credentialmanager/common/ui/HeadlineIconKt;
-Lcom/android/credentialmanager/common/ui/SectionHeaderKt;
-Lcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1$2$1;
-Lcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$1;
-Lcom/android/credentialmanager/common/ui/SnackBarKt$Snackbar$2;
-Lcom/android/credentialmanager/common/ui/SnackBarKt;
-Lcom/android/credentialmanager/common/ui/SystemUiControllerUtilsKt$setBottomSheetSystemBarsColor$1;
-Lcom/android/credentialmanager/common/ui/SystemUiControllerUtilsKt;
-Lcom/android/credentialmanager/common/ui/TextsKt$BodySmallText$1;
-Lcom/android/credentialmanager/common/ui/TextsKt$SmallTitleText$1;
-Lcom/android/credentialmanager/common/ui/TextsKt$SnackbarActionText$1;
-Lcom/android/credentialmanager/common/ui/TextsKt$SnackbarContentText$1;
-Lcom/android/credentialmanager/common/ui/TextsKt;
-Lcom/android/credentialmanager/createflow/CreateCredentialUiState;
-Lcom/android/credentialmanager/getflow/ActionEntryInfo;
-Lcom/android/credentialmanager/getflow/AuthenticationEntryInfo;
-Lcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-1$1;
-Lcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-2$1;
-Lcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt$lambda-3$1;
-Lcom/android/credentialmanager/getflow/ComposableSingletons$GetCredentialComponentsKt;
-Lcom/android/credentialmanager/getflow/CredentialEntryInfoComparatorByTypeThenTimestamp;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionChips$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionChips$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$ActionEntryRow$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$4;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2$invoke$$inlined$items$default$4;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AllSignInOptionCard$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AuthenticationEntryRow$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$AuthenticationEntryRow$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$10;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$7;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$8;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$4;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$5;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$6;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$7;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$8;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$9;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9$WhenMappings;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$9;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$LockedCredentials$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$LockedCredentials$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$4$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$4;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$5$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$5$3;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1$5;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$PrimarySelectionCard$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1$1$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteCredentialSnackBarScreen$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$1$1$1$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$1;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt$RemoteEntryCard$2;
-Lcom/android/credentialmanager/getflow/GetCredentialComponentsKt;
-Lcom/android/credentialmanager/getflow/GetCredentialUiState;
-Lcom/android/credentialmanager/getflow/GetModelKt$toProviderDisplayInfo$$inlined$compareByDescending$1;
-Lcom/android/credentialmanager/getflow/GetModelKt;
-Lcom/android/credentialmanager/getflow/GetScreenState;
-Lcom/android/credentialmanager/getflow/PerUserNameCredentialEntryList;
-Lcom/android/credentialmanager/getflow/ProviderDisplayInfo;
-Lcom/android/credentialmanager/getflow/ProviderInfo;
-Lcom/android/credentialmanager/getflow/RemoteEntryInfo;
-Lcom/android/credentialmanager/getflow/RequestDisplayInfo;
-Lcom/android/credentialmanager/getflow/TopBrandingContent;
-Lcom/android/credentialmanager/logging/GetCredentialEvent;
-Lcom/android/credentialmanager/logging/LifecycleEvent;
-Lcom/android/credentialmanager/logging/UIMetrics$log$1;
-Lcom/android/credentialmanager/logging/UIMetrics$log$3;
-Lcom/android/credentialmanager/logging/UIMetrics;
-Lcom/android/credentialmanager/ui/theme/AndroidColorScheme$Companion;
-Lcom/android/credentialmanager/ui/theme/AndroidColorScheme;
-Lcom/android/credentialmanager/ui/theme/AndroidColorSchemeKt$LocalAndroidColorScheme$1;
-Lcom/android/credentialmanager/ui/theme/AndroidColorSchemeKt;
-Lcom/android/credentialmanager/ui/theme/EntryShape;
-Lcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1$1;
-Lcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$1;
-Lcom/android/credentialmanager/ui/theme/PlatformThemeKt$PlatformTheme$2;
-Lcom/android/credentialmanager/ui/theme/PlatformThemeKt;
-Lcom/android/credentialmanager/ui/theme/ShapeKt;
-Lcom/android/credentialmanager/ui/theme/typography/PlatformTypographyKt;
-Lcom/android/credentialmanager/ui/theme/typography/TypeScaleTokens;
-Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Companion;
-Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;
-Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames;
-Lcom/android/credentialmanager/ui/theme/typography/TypefaceTokens$Companion;
-Lcom/android/credentialmanager/ui/theme/typography/TypefaceTokens;
-Lcom/android/credentialmanager/ui/theme/typography/TypographyTokens;
-Lkotlin/Function;
-Lkotlin/KotlinNothingValueException;
-Lkotlin/Lazy;
-Lkotlin/LazyKt;
-Lkotlin/LazyKt__LazyJVMKt$WhenMappings;
-Lkotlin/LazyKt__LazyJVMKt;
-Lkotlin/LazyKt__LazyKt;
-Lkotlin/LazyThreadSafetyMode;
-Lkotlin/Pair;
-Lkotlin/Result$Companion;
-Lkotlin/Result$Failure;
-Lkotlin/Result;
-Lkotlin/ResultKt;
-Lkotlin/SynchronizedLazyImpl;
-Lkotlin/Triple;
-Lkotlin/TuplesKt;
-Lkotlin/ULong$Companion;
-Lkotlin/ULong;
-Lkotlin/UNINITIALIZED_VALUE;
-Lkotlin/Unit;
-Lkotlin/UnsafeLazyImpl;
-Lkotlin/UnsignedKt;
-Lkotlin/collections/AbstractCollection;
-Lkotlin/collections/AbstractList$Companion;
-Lkotlin/collections/AbstractList;
-Lkotlin/collections/AbstractMap$Companion;
-Lkotlin/collections/AbstractMap;
-Lkotlin/collections/AbstractMutableList;
-Lkotlin/collections/AbstractMutableMap;
-Lkotlin/collections/AbstractSet$Companion;
-Lkotlin/collections/AbstractSet;
-Lkotlin/collections/ArrayDeque$Companion;
-Lkotlin/collections/ArrayDeque;
-Lkotlin/collections/ArraysKt;
-Lkotlin/collections/ArraysKt__ArraysJVMKt;
-Lkotlin/collections/ArraysKt__ArraysKt;
-Lkotlin/collections/ArraysKt___ArraysJvmKt;
-Lkotlin/collections/ArraysKt___ArraysKt;
-Lkotlin/collections/ArraysUtilJVM;
-Lkotlin/collections/CollectionsKt;
-Lkotlin/collections/CollectionsKt__CollectionsJVMKt;
-Lkotlin/collections/CollectionsKt__CollectionsKt;
-Lkotlin/collections/CollectionsKt__IterablesKt;
-Lkotlin/collections/CollectionsKt__IteratorsJVMKt;
-Lkotlin/collections/CollectionsKt__IteratorsKt;
-Lkotlin/collections/CollectionsKt__MutableCollectionsJVMKt;
-Lkotlin/collections/CollectionsKt__MutableCollectionsKt;
-Lkotlin/collections/CollectionsKt__ReversedViewsKt;
-Lkotlin/collections/CollectionsKt___CollectionsJvmKt;
-Lkotlin/collections/CollectionsKt___CollectionsKt;
-Lkotlin/collections/EmptyIterator;
-Lkotlin/collections/EmptyList;
-Lkotlin/collections/EmptyMap;
-Lkotlin/collections/EmptySet;
-Lkotlin/collections/IntIterator;
-Lkotlin/collections/MapsKt;
-Lkotlin/collections/MapsKt__MapWithDefaultKt;
-Lkotlin/collections/MapsKt__MapsJVMKt;
-Lkotlin/collections/MapsKt__MapsKt;
-Lkotlin/collections/MapsKt___MapsJvmKt;
-Lkotlin/collections/MapsKt___MapsKt;
-Lkotlin/comparisons/ComparisonsKt;
-Lkotlin/comparisons/ComparisonsKt__ComparisonsKt;
-Lkotlin/comparisons/ComparisonsKt___ComparisonsJvmKt;
-Lkotlin/comparisons/ComparisonsKt___ComparisonsKt;
-Lkotlin/coroutines/AbstractCoroutineContextElement;
-Lkotlin/coroutines/AbstractCoroutineContextKey;
-Lkotlin/coroutines/CombinedContext;
-Lkotlin/coroutines/Continuation;
-Lkotlin/coroutines/ContinuationInterceptor$DefaultImpls;
-Lkotlin/coroutines/ContinuationInterceptor$Key;
-Lkotlin/coroutines/ContinuationInterceptor;
-Lkotlin/coroutines/ContinuationKt;
-Lkotlin/coroutines/CoroutineContext$DefaultImpls;
-Lkotlin/coroutines/CoroutineContext$Element$DefaultImpls;
-Lkotlin/coroutines/CoroutineContext$Element;
-Lkotlin/coroutines/CoroutineContext$Key;
-Lkotlin/coroutines/CoroutineContext$plus$1;
-Lkotlin/coroutines/CoroutineContext;
-Lkotlin/coroutines/EmptyCoroutineContext;
-Lkotlin/coroutines/SafeContinuation$Companion;
-Lkotlin/coroutines/SafeContinuation;
-Lkotlin/coroutines/intrinsics/CoroutineSingletons;
-Lkotlin/coroutines/intrinsics/IntrinsicsKt;
-Lkotlin/coroutines/intrinsics/IntrinsicsKt__IntrinsicsJvmKt;
-Lkotlin/coroutines/intrinsics/IntrinsicsKt__IntrinsicsKt;
-Lkotlin/coroutines/jvm/internal/BaseContinuationImpl;
-Lkotlin/coroutines/jvm/internal/Boxing;
-Lkotlin/coroutines/jvm/internal/CompletedContinuation;
-Lkotlin/coroutines/jvm/internal/ContinuationImpl;
-Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;
-Lkotlin/coroutines/jvm/internal/DebugProbesKt;
-Lkotlin/coroutines/jvm/internal/RestrictedContinuationImpl;
-Lkotlin/coroutines/jvm/internal/RestrictedSuspendLambda;
-Lkotlin/coroutines/jvm/internal/SuspendLambda;
-Lkotlin/internal/ProgressionUtilKt;
-Lkotlin/jvm/JvmClassMappingKt;
-Lkotlin/jvm/functions/Function0;
-Lkotlin/jvm/functions/Function10;
-Lkotlin/jvm/functions/Function11;
-Lkotlin/jvm/functions/Function12;
-Lkotlin/jvm/functions/Function13;
-Lkotlin/jvm/functions/Function14;
-Lkotlin/jvm/functions/Function15;
-Lkotlin/jvm/functions/Function16;
-Lkotlin/jvm/functions/Function17;
-Lkotlin/jvm/functions/Function18;
-Lkotlin/jvm/functions/Function19;
-Lkotlin/jvm/functions/Function1;
-Lkotlin/jvm/functions/Function20;
-Lkotlin/jvm/functions/Function21;
-Lkotlin/jvm/functions/Function22;
-Lkotlin/jvm/functions/Function2;
-Lkotlin/jvm/functions/Function3;
-Lkotlin/jvm/functions/Function4;
-Lkotlin/jvm/functions/Function5;
-Lkotlin/jvm/functions/Function6;
-Lkotlin/jvm/functions/Function7;
-Lkotlin/jvm/functions/Function8;
-Lkotlin/jvm/functions/Function9;
-Lkotlin/jvm/internal/CallableReference$NoReceiver;
-Lkotlin/jvm/internal/CallableReference;
-Lkotlin/jvm/internal/ClassBasedDeclarationContainer;
-Lkotlin/jvm/internal/ClassReference$Companion;
-Lkotlin/jvm/internal/ClassReference;
-Lkotlin/jvm/internal/FloatCompanionObject;
-Lkotlin/jvm/internal/FunctionBase;
-Lkotlin/jvm/internal/FunctionReference;
-Lkotlin/jvm/internal/FunctionReferenceImpl;
-Lkotlin/jvm/internal/InlineMarker;
-Lkotlin/jvm/internal/IntCompanionObject;
-Lkotlin/jvm/internal/Intrinsics;
-Lkotlin/jvm/internal/Lambda;
-Lkotlin/jvm/internal/MutablePropertyReference1;
-Lkotlin/jvm/internal/MutablePropertyReference1Impl;
-Lkotlin/jvm/internal/MutablePropertyReference;
-Lkotlin/jvm/internal/PropertyReference;
-Lkotlin/jvm/internal/Ref$BooleanRef;
-Lkotlin/jvm/internal/Ref$FloatRef;
-Lkotlin/jvm/internal/Ref$IntRef;
-Lkotlin/jvm/internal/Ref$LongRef;
-Lkotlin/jvm/internal/Ref$ObjectRef;
-Lkotlin/jvm/internal/Reflection;
-Lkotlin/jvm/internal/ReflectionFactory;
-Lkotlin/jvm/internal/SpreadBuilder;
-Lkotlin/jvm/internal/TypeIntrinsics;
-Lkotlin/jvm/internal/markers/KMappedMarker;
-Lkotlin/jvm/internal/markers/KMutableCollection;
-Lkotlin/jvm/internal/markers/KMutableIterable;
-Lkotlin/jvm/internal/markers/KMutableMap;
-Lkotlin/jvm/internal/markers/KMutableSet;
-Lkotlin/math/MathKt;
-Lkotlin/math/MathKt__MathHKt;
-Lkotlin/math/MathKt__MathJVMKt;
-Lkotlin/ranges/ClosedRange;
-Lkotlin/ranges/IntProgression$Companion;
-Lkotlin/ranges/IntProgression;
-Lkotlin/ranges/IntProgressionIterator;
-Lkotlin/ranges/IntRange$Companion;
-Lkotlin/ranges/IntRange;
-Lkotlin/ranges/RangesKt;
-Lkotlin/ranges/RangesKt__RangesKt;
-Lkotlin/ranges/RangesKt___RangesKt;
-Lkotlin/reflect/KCallable;
-Lkotlin/reflect/KClass;
-Lkotlin/reflect/KDeclarationContainer;
-Lkotlin/reflect/KFunction;
-Lkotlin/reflect/KMutableProperty1;
-Lkotlin/reflect/KProperty1;
-Lkotlin/reflect/KProperty;
-Lkotlin/sequences/ConstrainedOnceSequence;
-Lkotlin/sequences/FilteringSequence$iterator$1;
-Lkotlin/sequences/FilteringSequence;
-Lkotlin/sequences/GeneratorSequence$iterator$1;
-Lkotlin/sequences/GeneratorSequence;
-Lkotlin/sequences/Sequence;
-Lkotlin/sequences/SequenceBuilderIterator;
-Lkotlin/sequences/SequenceScope;
-Lkotlin/sequences/SequencesKt;
-Lkotlin/sequences/SequencesKt__SequenceBuilderKt$sequence$$inlined$Sequence$1;
-Lkotlin/sequences/SequencesKt__SequenceBuilderKt;
-Lkotlin/sequences/SequencesKt__SequencesJVMKt;
-Lkotlin/sequences/SequencesKt__SequencesKt$asSequence$$inlined$Sequence$1;
-Lkotlin/sequences/SequencesKt__SequencesKt$generateSequence$2;
-Lkotlin/sequences/SequencesKt__SequencesKt;
-Lkotlin/sequences/SequencesKt___SequencesJvmKt;
-Lkotlin/sequences/SequencesKt___SequencesKt$filterNotNull$1;
-Lkotlin/sequences/SequencesKt___SequencesKt;
-Lkotlin/sequences/TransformingSequence$iterator$1;
-Lkotlin/sequences/TransformingSequence;
-Lkotlin/text/CharsKt;
-Lkotlin/text/CharsKt__CharJVMKt;
-Lkotlin/text/CharsKt__CharKt;
-Lkotlin/text/StringsKt;
-Lkotlin/text/StringsKt__AppendableKt;
-Lkotlin/text/StringsKt__IndentKt;
-Lkotlin/text/StringsKt__RegexExtensionsJVMKt;
-Lkotlin/text/StringsKt__RegexExtensionsKt;
-Lkotlin/text/StringsKt__StringBuilderJVMKt;
-Lkotlin/text/StringsKt__StringBuilderKt;
-Lkotlin/text/StringsKt__StringNumberConversionsJVMKt;
-Lkotlin/text/StringsKt__StringNumberConversionsKt;
-Lkotlin/text/StringsKt__StringsJVMKt;
-Lkotlin/text/StringsKt__StringsKt;
-Lkotlin/text/StringsKt___StringsJvmKt;
-Lkotlin/text/StringsKt___StringsKt;
-Lkotlinx/atomicfu/AtomicArray;
-Lkotlinx/atomicfu/AtomicBoolean$Companion;
-Lkotlinx/atomicfu/AtomicBoolean;
-Lkotlinx/atomicfu/AtomicFU;
-Lkotlinx/atomicfu/AtomicFU_commonKt;
-Lkotlinx/atomicfu/AtomicInt$Companion;
-Lkotlinx/atomicfu/AtomicInt;
-Lkotlinx/atomicfu/AtomicLong$Companion;
-Lkotlinx/atomicfu/AtomicLong;
-Lkotlinx/atomicfu/AtomicRef$Companion;
-Lkotlinx/atomicfu/AtomicRef;
-Lkotlinx/atomicfu/TraceBase$None;
-Lkotlinx/atomicfu/TraceBase;
-Lkotlinx/coroutines/AbstractCoroutine;
-Lkotlinx/coroutines/AbstractTimeSourceKt;
-Lkotlinx/coroutines/Active;
-Lkotlinx/coroutines/BeforeResumeCancelHandler;
-Lkotlinx/coroutines/BlockingEventLoop;
-Lkotlinx/coroutines/BuildersKt;
-Lkotlinx/coroutines/BuildersKt__Builders_commonKt;
-Lkotlinx/coroutines/CancelHandler;
-Lkotlinx/coroutines/CancelHandlerBase;
-Lkotlinx/coroutines/CancellableContinuation$DefaultImpls;
-Lkotlinx/coroutines/CancellableContinuation;
-Lkotlinx/coroutines/CancellableContinuationImpl;
-Lkotlinx/coroutines/CancellableContinuationImplKt;
-Lkotlinx/coroutines/CancellableContinuationKt;
-Lkotlinx/coroutines/CancelledContinuation;
-Lkotlinx/coroutines/ChildContinuation;
-Lkotlinx/coroutines/ChildHandle;
-Lkotlinx/coroutines/ChildHandleNode;
-Lkotlinx/coroutines/ChildJob;
-Lkotlinx/coroutines/CompletableJob;
-Lkotlinx/coroutines/CompletedContinuation;
-Lkotlinx/coroutines/CompletedExceptionally;
-Lkotlinx/coroutines/CompletionHandlerBase;
-Lkotlinx/coroutines/CompletionStateKt;
-Lkotlinx/coroutines/CoroutineContextKt$hasCopyableElements$1;
-Lkotlinx/coroutines/CoroutineContextKt;
-Lkotlinx/coroutines/CoroutineDispatcher$Key$1;
-Lkotlinx/coroutines/CoroutineDispatcher$Key;
-Lkotlinx/coroutines/CoroutineDispatcher;
-Lkotlinx/coroutines/CoroutineExceptionHandler$Key;
-Lkotlinx/coroutines/CoroutineExceptionHandler;
-Lkotlinx/coroutines/CoroutineScope;
-Lkotlinx/coroutines/CoroutineScopeKt;
-Lkotlinx/coroutines/CoroutineStart$WhenMappings;
-Lkotlinx/coroutines/CoroutineStart;
-Lkotlinx/coroutines/DebugStringsKt;
-Lkotlinx/coroutines/DefaultExecutor;
-Lkotlinx/coroutines/DefaultExecutorKt;
-Lkotlinx/coroutines/Delay;
-Lkotlinx/coroutines/DelayKt;
-Lkotlinx/coroutines/DispatchedTask;
-Lkotlinx/coroutines/DispatchedTaskKt;
-Lkotlinx/coroutines/Dispatchers;
-Lkotlinx/coroutines/DisposableHandle;
-Lkotlinx/coroutines/DisposeOnCancel;
-Lkotlinx/coroutines/Empty;
-Lkotlinx/coroutines/EventLoop;
-Lkotlinx/coroutines/EventLoopImplBase$DelayedResumeTask;
-Lkotlinx/coroutines/EventLoopImplBase$DelayedTask;
-Lkotlinx/coroutines/EventLoopImplBase$DelayedTaskQueue;
-Lkotlinx/coroutines/EventLoopImplBase;
-Lkotlinx/coroutines/EventLoopImplPlatform;
-Lkotlinx/coroutines/EventLoopKt;
-Lkotlinx/coroutines/EventLoop_commonKt;
-Lkotlinx/coroutines/ExceptionsKt;
-Lkotlinx/coroutines/ExecutorCoroutineDispatcher$Key$1;
-Lkotlinx/coroutines/ExecutorCoroutineDispatcher$Key;
-Lkotlinx/coroutines/ExecutorCoroutineDispatcher;
-Lkotlinx/coroutines/GlobalScope;
-Lkotlinx/coroutines/InactiveNodeList;
-Lkotlinx/coroutines/Incomplete;
-Lkotlinx/coroutines/IncompleteStateBox;
-Lkotlinx/coroutines/InvokeOnCancel;
-Lkotlinx/coroutines/InvokeOnCompletion;
-Lkotlinx/coroutines/Job$DefaultImpls;
-Lkotlinx/coroutines/Job$Key;
-Lkotlinx/coroutines/Job;
-Lkotlinx/coroutines/JobCancellationException;
-Lkotlinx/coroutines/JobCancellingNode;
-Lkotlinx/coroutines/JobImpl;
-Lkotlinx/coroutines/JobKt;
-Lkotlinx/coroutines/JobKt__JobKt;
-Lkotlinx/coroutines/JobNode;
-Lkotlinx/coroutines/JobSupport$ChildCompletion;
-Lkotlinx/coroutines/JobSupport$Finishing;
-Lkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;
-Lkotlinx/coroutines/JobSupport;
-Lkotlinx/coroutines/JobSupportKt;
-Lkotlinx/coroutines/MainCoroutineDispatcher;
-Lkotlinx/coroutines/NodeList;
-Lkotlinx/coroutines/NonDisposableHandle;
-Lkotlinx/coroutines/NotCompleted;
-Lkotlinx/coroutines/ParentJob;
-Lkotlinx/coroutines/RemoveOnCancel;
-Lkotlinx/coroutines/ResumeOnCompletion;
-Lkotlinx/coroutines/StandaloneCoroutine;
-Lkotlinx/coroutines/SupervisorJobImpl;
-Lkotlinx/coroutines/SupervisorKt;
-Lkotlinx/coroutines/ThreadContextElement;
-Lkotlinx/coroutines/ThreadLocalEventLoop;
-Lkotlinx/coroutines/TimeoutCancellationException;
-Lkotlinx/coroutines/Unconfined;
-Lkotlinx/coroutines/UndispatchedCoroutine;
-Lkotlinx/coroutines/UndispatchedMarker;
-Lkotlinx/coroutines/android/AndroidDispatcherFactory;
-Lkotlinx/coroutines/android/HandlerContext;
-Lkotlinx/coroutines/android/HandlerDispatcher;
-Lkotlinx/coroutines/android/HandlerDispatcherKt;
-Lkotlinx/coroutines/channels/AbstractChannel$Itr;
-Lkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;
-Lkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;
-Lkotlinx/coroutines/channels/AbstractChannel$RemoveReceiveOnCancel;
-Lkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;
-Lkotlinx/coroutines/channels/AbstractChannel$receiveCatching$1;
-Lkotlinx/coroutines/channels/AbstractChannel;
-Lkotlinx/coroutines/channels/AbstractChannelKt;
-Lkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;
-Lkotlinx/coroutines/channels/AbstractSendChannel;
-Lkotlinx/coroutines/channels/ArrayChannel;
-Lkotlinx/coroutines/channels/BufferOverflow;
-Lkotlinx/coroutines/channels/Channel$Factory;
-Lkotlinx/coroutines/channels/Channel;
-Lkotlinx/coroutines/channels/ChannelCoroutine;
-Lkotlinx/coroutines/channels/ChannelIterator;
-Lkotlinx/coroutines/channels/ChannelKt;
-Lkotlinx/coroutines/channels/ChannelResult$Closed;
-Lkotlinx/coroutines/channels/ChannelResult$Companion;
-Lkotlinx/coroutines/channels/ChannelResult$Failed;
-Lkotlinx/coroutines/channels/ChannelResult;
-Lkotlinx/coroutines/channels/Closed;
-Lkotlinx/coroutines/channels/ConflatedChannel;
-Lkotlinx/coroutines/channels/LinkedListChannel;
-Lkotlinx/coroutines/channels/ProduceKt;
-Lkotlinx/coroutines/channels/ProducerCoroutine;
-Lkotlinx/coroutines/channels/ProducerScope;
-Lkotlinx/coroutines/channels/Receive;
-Lkotlinx/coroutines/channels/ReceiveChannel;
-Lkotlinx/coroutines/channels/ReceiveOrClosed;
-Lkotlinx/coroutines/channels/RendezvousChannel;
-Lkotlinx/coroutines/channels/Send;
-Lkotlinx/coroutines/channels/SendChannel;
-Lkotlinx/coroutines/flow/AbstractFlow$collect$1;
-Lkotlinx/coroutines/flow/AbstractFlow;
-Lkotlinx/coroutines/flow/DistinctFlowImpl$collect$2$emit$1;
-Lkotlinx/coroutines/flow/DistinctFlowImpl$collect$2;
-Lkotlinx/coroutines/flow/DistinctFlowImpl;
-Lkotlinx/coroutines/flow/Flow;
-Lkotlinx/coroutines/flow/FlowCollector;
-Lkotlinx/coroutines/flow/FlowKt;
-Lkotlinx/coroutines/flow/FlowKt__BuildersKt;
-Lkotlinx/coroutines/flow/FlowKt__ChannelsKt$emitAllImpl$1;
-Lkotlinx/coroutines/flow/FlowKt__ChannelsKt;
-Lkotlinx/coroutines/flow/FlowKt__CollectKt;
-Lkotlinx/coroutines/flow/FlowKt__ContextKt;
-Lkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultAreEquivalent$1;
-Lkotlinx/coroutines/flow/FlowKt__DistinctKt$defaultKeySelector$1;
-Lkotlinx/coroutines/flow/FlowKt__DistinctKt;
-Lkotlinx/coroutines/flow/FlowKt__EmittersKt;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$$inlined$unsafeFlow$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1$emit$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$dropWhile$1$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$emitAbort$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1$emit$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt$take$2$1;
-Lkotlinx/coroutines/flow/FlowKt__LimitKt;
-Lkotlinx/coroutines/flow/FlowKt__MergeKt$mapLatest$1;
-Lkotlinx/coroutines/flow/FlowKt__MergeKt;
-Lkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2$1;
-Lkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;
-Lkotlinx/coroutines/flow/FlowKt__ReduceKt$first$3;
-Lkotlinx/coroutines/flow/FlowKt__ReduceKt;
-Lkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2$WhenMappings;
-Lkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1$2;
-Lkotlinx/coroutines/flow/FlowKt__ShareKt$launchSharing$1;
-Lkotlinx/coroutines/flow/FlowKt__ShareKt;
-Lkotlinx/coroutines/flow/MutableSharedFlow;
-Lkotlinx/coroutines/flow/MutableStateFlow;
-Lkotlinx/coroutines/flow/ReadonlyStateFlow;
-Lkotlinx/coroutines/flow/SafeFlow;
-Lkotlinx/coroutines/flow/SharedFlow;
-Lkotlinx/coroutines/flow/SharedFlowImpl$Emitter;
-Lkotlinx/coroutines/flow/SharedFlowImpl$collect$1;
-Lkotlinx/coroutines/flow/SharedFlowImpl;
-Lkotlinx/coroutines/flow/SharedFlowKt;
-Lkotlinx/coroutines/flow/SharedFlowSlot;
-Lkotlinx/coroutines/flow/SharingCommand;
-Lkotlinx/coroutines/flow/SharingConfig;
-Lkotlinx/coroutines/flow/SharingStarted$Companion;
-Lkotlinx/coroutines/flow/SharingStarted;
-Lkotlinx/coroutines/flow/StartedEagerly;
-Lkotlinx/coroutines/flow/StartedLazily;
-Lkotlinx/coroutines/flow/StartedWhileSubscribed$command$1;
-Lkotlinx/coroutines/flow/StartedWhileSubscribed$command$2;
-Lkotlinx/coroutines/flow/StartedWhileSubscribed;
-Lkotlinx/coroutines/flow/StateFlow;
-Lkotlinx/coroutines/flow/StateFlowImpl$collect$1;
-Lkotlinx/coroutines/flow/StateFlowImpl;
-Lkotlinx/coroutines/flow/StateFlowKt;
-Lkotlinx/coroutines/flow/StateFlowSlot;
-Lkotlinx/coroutines/flow/internal/AbortFlowException;
-Lkotlinx/coroutines/flow/internal/AbstractSharedFlow;
-Lkotlinx/coroutines/flow/internal/AbstractSharedFlowKt;
-Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-Lkotlinx/coroutines/flow/internal/ChannelFlow$collect$2;
-Lkotlinx/coroutines/flow/internal/ChannelFlow$collectToFun$1;
-Lkotlinx/coroutines/flow/internal/ChannelFlow;
-Lkotlinx/coroutines/flow/internal/ChannelFlowOperator;
-Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$2;
-Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1$emit$1;
-Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3$1;
-Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest$flowCollect$3;
-Lkotlinx/coroutines/flow/internal/ChannelFlowTransformLatest;
-Lkotlinx/coroutines/flow/internal/ChildCancelledException;
-Lkotlinx/coroutines/flow/internal/DownstreamExceptionContext;
-Lkotlinx/coroutines/flow/internal/FlowExceptions_commonKt;
-Lkotlinx/coroutines/flow/internal/FusibleFlow$DefaultImpls;
-Lkotlinx/coroutines/flow/internal/FusibleFlow;
-Lkotlinx/coroutines/flow/internal/NoOpContinuation;
-Lkotlinx/coroutines/flow/internal/NopCollector;
-Lkotlinx/coroutines/flow/internal/NullSurrogateKt;
-Lkotlinx/coroutines/flow/internal/SafeCollector$collectContextSize$1;
-Lkotlinx/coroutines/flow/internal/SafeCollector;
-Lkotlinx/coroutines/flow/internal/SafeCollectorKt$emitFun$1;
-Lkotlinx/coroutines/flow/internal/SafeCollectorKt;
-Lkotlinx/coroutines/flow/internal/SafeCollector_commonKt$checkContext$result$1;
-Lkotlinx/coroutines/flow/internal/SafeCollector_commonKt;
-Lkotlinx/coroutines/flow/internal/SendingCollector;
-Lkotlinx/coroutines/flow/internal/SubscriptionCountStateFlow;
-Lkotlinx/coroutines/internal/AtomicKt;
-Lkotlinx/coroutines/internal/AtomicOp;
-Lkotlinx/coroutines/internal/ContextScope;
-Lkotlinx/coroutines/internal/DispatchedContinuation;
-Lkotlinx/coroutines/internal/DispatchedContinuationKt;
-Lkotlinx/coroutines/internal/LimitedDispatcher;
-Lkotlinx/coroutines/internal/LimitedDispatcherKt;
-Lkotlinx/coroutines/internal/LockFreeLinkedListHead;
-Lkotlinx/coroutines/internal/LockFreeLinkedListKt;
-Lkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;
-Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
-Lkotlinx/coroutines/internal/LockFreeTaskQueue;
-Lkotlinx/coroutines/internal/LockFreeTaskQueueCore$Companion;
-Lkotlinx/coroutines/internal/LockFreeTaskQueueCore;
-Lkotlinx/coroutines/internal/MainDispatcherFactory;
-Lkotlinx/coroutines/internal/MainDispatcherLoader;
-Lkotlinx/coroutines/internal/MainDispatchersKt;
-Lkotlinx/coroutines/internal/OpDescriptor;
-Lkotlinx/coroutines/internal/Removed;
-Lkotlinx/coroutines/internal/ResizableAtomicArray;
-Lkotlinx/coroutines/internal/ScopeCoroutine;
-Lkotlinx/coroutines/internal/Symbol;
-Lkotlinx/coroutines/internal/SystemPropsKt;
-Lkotlinx/coroutines/internal/SystemPropsKt__SystemPropsKt;
-Lkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;
-Lkotlinx/coroutines/internal/ThreadContextKt$countAll$1;
-Lkotlinx/coroutines/internal/ThreadContextKt$findOne$1;
-Lkotlinx/coroutines/internal/ThreadContextKt$updateState$1;
-Lkotlinx/coroutines/internal/ThreadContextKt;
-Lkotlinx/coroutines/internal/ThreadSafeHeap;
-Lkotlinx/coroutines/internal/ThreadSafeHeapNode;
-Lkotlinx/coroutines/internal/ThreadState;
-Lkotlinx/coroutines/intrinsics/CancellableKt;
-Lkotlinx/coroutines/intrinsics/UndispatchedKt;
-Lkotlinx/coroutines/scheduling/CoroutineScheduler$Companion;
-Lkotlinx/coroutines/scheduling/CoroutineScheduler;
-Lkotlinx/coroutines/scheduling/DefaultIoScheduler;
-Lkotlinx/coroutines/scheduling/DefaultScheduler;
-Lkotlinx/coroutines/scheduling/GlobalQueue;
-Lkotlinx/coroutines/scheduling/NanoTimeSource;
-Lkotlinx/coroutines/scheduling/SchedulerCoroutineDispatcher;
-Lkotlinx/coroutines/scheduling/SchedulerTimeSource;
-Lkotlinx/coroutines/scheduling/Task;
-Lkotlinx/coroutines/scheduling/TaskContext;
-Lkotlinx/coroutines/scheduling/TaskContextImpl;
-Lkotlinx/coroutines/scheduling/TasksKt;
-Lkotlinx/coroutines/scheduling/UnlimitedIoScheduler;
-Lkotlinx/coroutines/sync/Empty;
-Lkotlinx/coroutines/sync/Mutex$DefaultImpls;
-Lkotlinx/coroutines/sync/Mutex;
-Lkotlinx/coroutines/sync/MutexImpl$LockCont$tryResumeLockWaiter$1;
-Lkotlinx/coroutines/sync/MutexImpl$LockCont;
-Lkotlinx/coroutines/sync/MutexImpl$LockWaiter;
-Lkotlinx/coroutines/sync/MutexImpl$LockedQueue;
-Lkotlinx/coroutines/sync/MutexImpl;
-Lkotlinx/coroutines/sync/MutexKt;
-PLandroidx/compose/foundation/MutatorMutex$Mutator;->canInterrupt(Landroidx/compose/foundation/MutatorMutex$Mutator;)Z
-PLandroidx/compose/foundation/MutatorMutex$Mutator;->cancel()V
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$1;-><init>(Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$3;-><init>(Lkotlin/coroutines/Continuation;)V
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$3;->invoke(Landroidx/compose/ui/input/pointer/AwaitPointerEventScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$5;-><init>(Landroidx/compose/foundation/gestures/PressGestureScopeImpl;Lkotlin/coroutines/Continuation;)V
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$5;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-PLandroidx/compose/foundation/gestures/TapGestureDetectorKt$detectTapGestures$2$1$5;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/runtime/BroadcastFrameClock$withFrameNanos$2$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/runtime/BroadcastFrameClock$withFrameNanos$2$1;->invoke(Ljava/lang/Throwable;)V
-PLandroidx/compose/runtime/RecomposeScopeImpl;->rereadTrackedInstances()V
-PLandroidx/compose/runtime/RecomposeScopeImpl;->setRereading(Z)V
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet$iterator$1;-><init>(Landroidx/compose/runtime/snapshots/SnapshotIdSet;Lkotlin/coroutines/Continuation;)V
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet$iterator$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet$iterator$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet;->access$getBelowBound$p(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)[I
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet;->access$getLowerBound$p(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)I
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet;->access$getLowerSet$p(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)J
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet;->access$getUpperSet$p(Landroidx/compose/runtime/snapshots/SnapshotIdSet;)J
-PLandroidx/compose/runtime/snapshots/SnapshotIdSet;->iterator()Ljava/util/Iterator;
-PLandroidx/compose/ui/geometry/Offset;->getDistanceSquared-impl(J)F
-PLandroidx/compose/ui/input/pointer/HistoricalChange;-><clinit>()V
-PLandroidx/compose/ui/input/pointer/HistoricalChange;-><init>(JJ)V
-PLandroidx/compose/ui/input/pointer/HistoricalChange;-><init>(JJLkotlin/jvm/internal/DefaultConstructorMarker;)V
-PLandroidx/compose/ui/input/pointer/HistoricalChange;->getPosition-F1C5BW0()J
-PLandroidx/compose/ui/input/pointer/HistoricalChange;->getUptimeMillis()J
-PLandroidx/compose/ui/input/pointer/Node;->hasPositionChanged(Landroidx/compose/ui/input/pointer/PointerEvent;Landroidx/compose/ui/input/pointer/PointerEvent;)Z
-PLandroidx/compose/ui/input/pointer/PointerEventKt;->isOutOfBounds-jwHxaWs(Landroidx/compose/ui/input/pointer/PointerInputChange;JJ)Z
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$1;-><init>(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;Lkotlin/coroutines/Continuation;)V
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$job$1;-><init>(JLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;Lkotlin/coroutines/Continuation;)V
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$job$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine$withTimeout$job$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->getExtendedTouchPadding-NH-jbRc()J
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->getSize-YbymL2g()J
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;->withTimeout(JLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->access$getBoundsSize$p(Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;)J
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->getCoroutineScope()Lkotlinx/coroutines/CoroutineScope;
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->getExtendedTouchPadding-NH-jbRc()J
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->getInterceptOutOfBoundsChildEvents()Z
-PLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter;->toSize-XkaWNTQ(J)J
-PLandroidx/compose/ui/node/BackwardsCompatNode;->interceptOutOfBoundsChildEvents()Z
-PLandroidx/compose/ui/node/HitTestResult;->isHitInMinimumTouchTargetBetter(FZ)Z
-PLandroidx/compose/ui/node/NodeChain$Differ;->remove(I)V
-PLandroidx/compose/ui/node/NodeChain$Differ;->setAfter(Landroidx/compose/runtime/collection/MutableVector;)V
-PLandroidx/compose/ui/node/NodeChain$Differ;->setAggregateChildKindSet(I)V
-PLandroidx/compose/ui/node/NodeChain$Differ;->setBefore(Landroidx/compose/runtime/collection/MutableVector;)V
-PLandroidx/compose/ui/node/NodeChain$Differ;->setNode(Landroidx/compose/ui/Modifier$Node;)V
-PLandroidx/compose/ui/node/NodeChain;->access$disposeAndRemoveNode(Landroidx/compose/ui/node/NodeChain;Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-PLandroidx/compose/ui/node/NodeChain;->disposeAndRemoveNode(Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-PLandroidx/compose/ui/node/NodeChain;->removeNode(Landroidx/compose/ui/Modifier$Node;)Landroidx/compose/ui/Modifier$Node;
-PLandroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;->interceptOutOfBoundsChildEvents(Landroidx/compose/ui/node/DelegatableNode;)Z
-PLandroidx/compose/ui/node/NodeCoordinator$Companion$PointerInputSource$1;->interceptOutOfBoundsChildEvents(Landroidx/compose/ui/node/PointerInputModifierNode;)Z
-PLandroidx/compose/ui/node/NodeCoordinator$hitNear$1;-><init>(Landroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZF)V
-PLandroidx/compose/ui/node/NodeCoordinator$hitNear$1;->invoke()Ljava/lang/Object;
-PLandroidx/compose/ui/node/NodeCoordinator$hitNear$1;->invoke()V
-PLandroidx/compose/ui/node/NodeCoordinator;->access$hitNear-JHbHoSQ(Landroidx/compose/ui/node/NodeCoordinator;Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZF)V
-PLandroidx/compose/ui/node/NodeCoordinator;->hitNear-JHbHoSQ(Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZF)V
-PLandroidx/compose/ui/node/NodeCoordinator;->speculativeHit-JHbHoSQ(Landroidx/compose/ui/node/DelegatableNode;Landroidx/compose/ui/node/NodeCoordinator$HitTestSource;JLandroidx/compose/ui/node/HitTestResult;ZZF)V
-PLandroidx/compose/ui/node/NodeKindKt;->autoInvalidateRemovedNode(Landroidx/compose/ui/Modifier$Node;)V
-PLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt$obtainImageVectorCache$callbacks$1$1;->onTrimMemory(I)V
-PLandroidx/compose/ui/res/ImageVectorCache;->clear()V
-PLandroidx/compose/ui/text/font/DeviceFontFamilyName;->equals-impl0(Ljava/lang/String;Ljava/lang/String;)Z
-PLandroidx/compose/ui/text/font/DeviceFontFamilyNameFont;->equals(Ljava/lang/Object;)Z
-PLandroidx/compose/ui/text/font/FontVariation$Settings;->equals(Ljava/lang/Object;)Z
-PLandroidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper;-><init>()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$AtomicHelper;-><init>(Landroidx/concurrent/futures/AbstractResolvableFuture$1;)V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$Listener;-><clinit>()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$Listener;-><init>(Ljava/lang/Runnable;Ljava/util/concurrent/Executor;)V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;-><init>(Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;)V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casListeners(Landroidx/concurrent/futures/AbstractResolvableFuture;Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;)Z
-PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casValue(Landroidx/concurrent/futures/AbstractResolvableFuture;Ljava/lang/Object;Ljava/lang/Object;)Z
-PLandroidx/concurrent/futures/AbstractResolvableFuture$SafeAtomicHelper;->casWaiters(Landroidx/concurrent/futures/AbstractResolvableFuture;Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;Landroidx/concurrent/futures/AbstractResolvableFuture$Waiter;)Z
-PLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;-><clinit>()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture$Waiter;-><init>(Z)V
-PLandroidx/concurrent/futures/AbstractResolvableFuture;-><clinit>()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture;-><init>()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture;->afterDone()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture;->clearListeners(Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;)Landroidx/concurrent/futures/AbstractResolvableFuture$Listener;
-PLandroidx/concurrent/futures/AbstractResolvableFuture;->complete(Landroidx/concurrent/futures/AbstractResolvableFuture;)V
-PLandroidx/concurrent/futures/AbstractResolvableFuture;->releaseWaiters()V
-PLandroidx/concurrent/futures/AbstractResolvableFuture;->set(Ljava/lang/Object;)Z
-PLandroidx/concurrent/futures/ResolvableFuture;-><init>()V
-PLandroidx/concurrent/futures/ResolvableFuture;->create()Landroidx/concurrent/futures/ResolvableFuture;
-PLandroidx/concurrent/futures/ResolvableFuture;->set(Ljava/lang/Object;)Z
-PLandroidx/profileinstaller/DeviceProfileWriter$$ExternalSyntheticLambda0;-><init>(Landroidx/profileinstaller/DeviceProfileWriter;ILjava/lang/Object;)V
-PLandroidx/profileinstaller/DeviceProfileWriter$$ExternalSyntheticLambda0;->run()V
-PLandroidx/profileinstaller/DeviceProfileWriter;->$r8$lambda$ERhlvXCSfTRq-n5iULYjO-Ntn-w(Landroidx/profileinstaller/DeviceProfileWriter;ILjava/lang/Object;)V
-PLandroidx/profileinstaller/DeviceProfileWriter;-><init>(Landroid/content/res/AssetManager;Ljava/util/concurrent/Executor;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
-PLandroidx/profileinstaller/DeviceProfileWriter;->desiredVersion()[B
-PLandroidx/profileinstaller/DeviceProfileWriter;->deviceAllowsProfileInstallerAotWrites()Z
-PLandroidx/profileinstaller/DeviceProfileWriter;->lambda$result$0(ILjava/lang/Object;)V
-PLandroidx/profileinstaller/DeviceProfileWriter;->result(ILjava/lang/Object;)V
-PLandroidx/profileinstaller/ProfileInstallReceiver$$ExternalSyntheticLambda0;-><init>()V
-PLandroidx/profileinstaller/ProfileInstallReceiver$$ExternalSyntheticLambda0;->execute(Ljava/lang/Runnable;)V
-PLandroidx/profileinstaller/ProfileInstaller$1;-><init>()V
-PLandroidx/profileinstaller/ProfileInstaller$1;->onResultReceived(ILjava/lang/Object;)V
-PLandroidx/profileinstaller/ProfileInstaller$2;-><init>()V
-PLandroidx/profileinstaller/ProfileInstaller;-><clinit>()V
-PLandroidx/profileinstaller/ProfileInstaller;->hasAlreadyWrittenProfileForThisInstall(Landroid/content/pm/PackageInfo;Ljava/io/File;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;)Z
-PLandroidx/profileinstaller/ProfileInstaller;->transcodeAndWrite(Landroid/content/res/AssetManager;Ljava/lang/String;Landroid/content/pm/PackageInfo;Ljava/io/File;Ljava/lang/String;Ljava/util/concurrent/Executor;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;)Z
-PLandroidx/profileinstaller/ProfileInstaller;->writeProfile(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileInstaller;->writeProfile(Landroid/content/Context;Ljava/util/concurrent/Executor;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;)V
-PLandroidx/profileinstaller/ProfileInstaller;->writeProfile(Landroid/content/Context;Ljava/util/concurrent/Executor;Landroidx/profileinstaller/ProfileInstaller$DiagnosticsCallback;Z)V
-PLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda1;->run()V
-PLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda2;-><init>(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileInstallerInitializer$$ExternalSyntheticLambda2;->run()V
-PLandroidx/profileinstaller/ProfileInstallerInitializer;->$r8$lambda$nkOIpN4NfyreWbcXjHv0xCvwgTY(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileInstallerInitializer;->$r8$lambda$nvFqT5BztGB-MvszW9GUTUoI9rw(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileInstallerInitializer;->lambda$installAfterDelay$1(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileInstallerInitializer;->lambda$writeInBackground$2(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileInstallerInitializer;->writeInBackground(Landroid/content/Context;)V
-PLandroidx/profileinstaller/ProfileVerifier$Api33Impl;->getPackageInfo(Landroid/content/pm/PackageManager;Landroid/content/Context;)Landroid/content/pm/PackageInfo;
-PLandroidx/profileinstaller/ProfileVerifier$Cache;-><init>(IIJJ)V
-PLandroidx/profileinstaller/ProfileVerifier$Cache;->equals(Ljava/lang/Object;)Z
-PLandroidx/profileinstaller/ProfileVerifier$Cache;->readFromFile(Ljava/io/File;)Landroidx/profileinstaller/ProfileVerifier$Cache;
-PLandroidx/profileinstaller/ProfileVerifier$CompilationStatus;-><init>(IZZ)V
-PLandroidx/profileinstaller/ProfileVerifier;-><clinit>()V
-PLandroidx/profileinstaller/ProfileVerifier;->getPackageLastUpdateTime(Landroid/content/Context;)J
-PLandroidx/profileinstaller/ProfileVerifier;->setCompilationStatus(IZZ)Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;
-PLandroidx/profileinstaller/ProfileVerifier;->writeProfileVerification(Landroid/content/Context;Z)Landroidx/profileinstaller/ProfileVerifier$CompilationStatus;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1$1;-><init>(Lcom/android/credentialmanager/common/material/ModalBottomSheetState;Lkotlin/coroutines/Continuation;)V
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1;->invoke()Ljava/lang/Object;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$ModalBottomSheetLayout$1$1$1;->invoke()V
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$Scrim$dismissModifier$1$1$1;->invoke-k-4lQ0M(J)V
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$1;->invoke(Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;)Ljava/lang/Boolean;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetKt$rememberModalBottomSheetState$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
-PLcom/android/credentialmanager/common/material/ModalBottomSheetState;->hide(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-PLcom/android/credentialmanager/common/material/SwipeableState;->getConfirmStateChange$frameworks__base__packages__CredentialManager__android_common__CredentialManager()Lkotlin/jvm/functions/Function1;
-PLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$7;->invoke()Ljava/lang/Object;
-PLcom/android/credentialmanager/getflow/GetCredentialComponentsKt$GetCredentialScreen$7;->invoke()V
-PLkotlin/coroutines/jvm/internal/Boxing;->boxInt(I)Ljava/lang/Integer;
-PLkotlin/sequences/SequenceBuilderIterator;-><init>()V
-PLkotlin/sequences/SequenceBuilderIterator;->getContext()Lkotlin/coroutines/CoroutineContext;
-PLkotlin/sequences/SequenceBuilderIterator;->hasNext()Z
-PLkotlin/sequences/SequenceBuilderIterator;->next()Ljava/lang/Object;
-PLkotlin/sequences/SequenceBuilderIterator;->resumeWith(Ljava/lang/Object;)V
-PLkotlin/sequences/SequenceBuilderIterator;->setNextStep(Lkotlin/coroutines/Continuation;)V
-PLkotlin/sequences/SequenceBuilderIterator;->yield(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
-PLkotlin/sequences/SequenceScope;-><init>()V
-PLkotlin/sequences/SequencesKt;->sequence(Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence;
-PLkotlin/sequences/SequencesKt__SequenceBuilderKt$sequence$$inlined$Sequence$1;-><init>(Lkotlin/jvm/functions/Function2;)V
-PLkotlin/sequences/SequencesKt__SequenceBuilderKt$sequence$$inlined$Sequence$1;->iterator()Ljava/util/Iterator;
-PLkotlin/sequences/SequencesKt__SequenceBuilderKt;->iterator(Lkotlin/jvm/functions/Function2;)Ljava/util/Iterator;
-PLkotlin/sequences/SequencesKt__SequenceBuilderKt;->sequence(Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence;
-PLkotlinx/coroutines/DelayKt;->getDelay(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Delay;
-PLkotlinx/coroutines/EventLoopImplBase;->scheduleResumeAfterDelay(JLkotlinx/coroutines/CancellableContinuation;)V
-PLkotlinx/coroutines/EventLoop_commonKt;-><clinit>()V
-PLkotlinx/coroutines/EventLoop_commonKt;->delayToNanos(J)J
-PLkotlinx/coroutines/internal/LockFreeLinkedListHead;->isEmpty()Z
-PLkotlinx/coroutines/sync/MutexImpl$UnlockOp;-><init>(Lkotlinx/coroutines/sync/MutexImpl$LockedQueue;)V
-PLkotlinx/coroutines/sync/MutexImpl$UnlockOp;->complete(Ljava/lang/Object;Ljava/lang/Object;)V
-PLkotlinx/coroutines/sync/MutexImpl$UnlockOp;->complete(Lkotlinx/coroutines/sync/MutexImpl;Ljava/lang/Object;)V
-PLkotlinx/coroutines/sync/MutexImpl$UnlockOp;->prepare(Ljava/lang/Object;)Ljava/lang/Object;
-PLkotlinx/coroutines/sync/MutexImpl$UnlockOp;->prepare(Lkotlinx/coroutines/sync/MutexImpl;)Ljava/lang/Object;
-[Landroidx/compose/animation/core/AnimationEndReason;
-[Landroidx/compose/animation/core/MutatePriority;
-[Landroidx/compose/foundation/MutatePriority;
-[Landroidx/compose/foundation/gestures/ContentInViewModifier$Request;
-[Landroidx/compose/foundation/gestures/Orientation;
-[Landroidx/compose/foundation/layout/Direction;
-[Landroidx/compose/foundation/layout/LayoutOrientation;
-[Landroidx/compose/foundation/layout/RowColumnParentData;
-[Landroidx/compose/foundation/layout/SizeMode;
-[Landroidx/compose/foundation/lazy/LazyListBeyondBoundsInfo$Interval;
-[Landroidx/compose/foundation/lazy/layout/IntervalList$Interval;
-[Landroidx/compose/foundation/lazy/layout/LazyLayoutPrefetcher$PrefetchRequest;
-[Landroidx/compose/foundation/relocation/BringIntoViewRequesterModifier;
-[Landroidx/compose/material3/tokens/ColorSchemeKeyTokens;
-[Landroidx/compose/material3/tokens/ShapeKeyTokens;
-[Landroidx/compose/material3/tokens/TypographyKeyTokens;
-[Landroidx/compose/runtime/InvalidationResult;
-[Landroidx/compose/runtime/ProvidedValue;
-[Landroidx/compose/runtime/Recomposer$State;
-[Landroidx/compose/runtime/collection/IdentityArraySet;
-[Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;
-[Landroidx/compose/runtime/snapshots/SnapshotStateObserver$ObservedScopeMap;
-[Landroidx/compose/ui/Modifier$Element;
-[Landroidx/compose/ui/Modifier$Node;
-[Landroidx/compose/ui/Modifier;
-[Landroidx/compose/ui/focus/FocusRequesterModifierNode;
-[Landroidx/compose/ui/focus/FocusStateImpl;
-[Landroidx/compose/ui/graphics/colorspace/ColorSpace;
-[Landroidx/compose/ui/input/pointer/Node;
-[Landroidx/compose/ui/input/pointer/PointerEventPass;
-[Landroidx/compose/ui/input/pointer/PointerId;
-[Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilter$PointerEventHandlerCoroutine;
-[Landroidx/compose/ui/input/pointer/util/DataPointAtTime;
-[Landroidx/compose/ui/input/pointer/util/VelocityTracker1D$Strategy;
-[Landroidx/compose/ui/layout/Measurable;
-[Landroidx/compose/ui/layout/Placeable;
-[Landroidx/compose/ui/modifier/ModifierLocal;
-[Landroidx/compose/ui/node/BackwardsCompatNode;
-[Landroidx/compose/ui/node/LayoutNode$LayoutState;
-[Landroidx/compose/ui/node/LayoutNode$UsageByParent;
-[Landroidx/compose/ui/node/LayoutNode;
-[Landroidx/compose/ui/node/MeasureAndLayoutDelegate$PostponedRequest;
-[Landroidx/compose/ui/node/Owner$OnLayoutCompletedListener;
-[Landroidx/compose/ui/platform/TextToolbarStatus;
-[Landroidx/compose/ui/text/android/style/LineHeightStyleSpan;
-[Landroidx/compose/ui/text/android/style/PlaceholderSpan;
-[Landroidx/compose/ui/text/font/Font;
-[Landroidx/compose/ui/text/font/FontVariation$Setting;
-[Landroidx/compose/ui/text/font/FontWeight;
-[Landroidx/compose/ui/text/platform/style/ShaderBrushSpan;
-[Landroidx/compose/ui/unit/LayoutDirection;
-[Landroidx/compose/ui/unit/TextUnitType;
-[Landroidx/core/provider/FontsContractCompat$FontInfo;
-[Landroidx/lifecycle/Lifecycle$Event;
-[Landroidx/lifecycle/Lifecycle$State;
-[Landroidx/lifecycle/viewmodel/ViewModelInitializer;
-[Lcom/android/credentialmanager/common/CredentialType;
-[Lcom/android/credentialmanager/common/DialogState;
-[Lcom/android/credentialmanager/common/ProviderActivityState;
-[Lcom/android/credentialmanager/common/material/ModalBottomSheetValue;
-[Lcom/android/credentialmanager/getflow/GetScreenState;
-[Lcom/android/credentialmanager/logging/GetCredentialEvent;
-[Lcom/android/credentialmanager/logging/LifecycleEvent;
-[Lcom/android/credentialmanager/ui/theme/typography/TypefaceNames$Config;
-[Lkotlin/LazyThreadSafetyMode;
-[Lkotlin/Pair;
-[Lkotlin/coroutines/Continuation;
-[Lkotlin/coroutines/intrinsics/CoroutineSingletons;
-[Lkotlin/jvm/functions/Function0;
-[Lkotlin/reflect/KClass;
-[Lkotlin/reflect/KProperty;
-[Lkotlinx/atomicfu/AtomicRef;
-[Lkotlinx/coroutines/CoroutineStart;
-[Lkotlinx/coroutines/channels/BufferOverflow;
-[Lkotlinx/coroutines/flow/SharedFlowSlot;
-[Lkotlinx/coroutines/flow/SharingCommand;
-[Lkotlinx/coroutines/flow/StateFlowSlot;
-[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
-[Lkotlinx/coroutines/internal/ThreadSafeHeapNode;
\ No newline at end of file
+# TODO(b/335418838): Restore when build support for rewriting profiles lands.
diff --git a/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml b/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
index e998fe8..2aff2c3 100644
--- a/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
+++ b/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
@@ -34,7 +34,7 @@
                     android:layout_height="wrap_content"
                     android:layout_gravity="center"
                     android:layout_alignParentStart="true"
-                    android:paddingLeft="@dimen/autofill_view_left_padding"
+                    android:paddingStart="@dimen/autofill_view_left_padding"
                     app:tint="?androidprv:attr/materialColorOnSurface"
                     android:background="@null"/>
 
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index a24134b3..2c73eb7 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -68,15 +68,15 @@
     <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 toegangsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"Gebruik jou gestoorde wagwoord vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Gebruik jou skermslot om met <xliff:g id="USERNAME">%2$s</xliff:g> by <xliff:g id="APP_NAME">%1$s</xliff:g> aan te meld"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Gebruik jou aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Ontsluit aanmeldingopsies vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Gebruik jou gestoorde toegangsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Gebruik jou gestoorde wagwoord vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Gebruik jou rekening vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Gebruik jou skermslot om met <xliff:g id="USERNAME">%2$s</xliff:g> by <xliff:g id="APP_NAME">%1$s</xliff:g> aan te meld"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Ontsluit aanmeldingopsies vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Kies ’n gestoorde toegangsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Kies ’n gestoorde wagwoord vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Kies ’n gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Kies ’n aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Kies ’n rekening vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Kies ’n opsie vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Gebruik hierdie inligting op <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Meld op ’n ander manier aan"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 0554d81..cc6d07c 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠውን የይለፍ ቃልዎን ይጠቀሙ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"በ<xliff:g id="USERNAME">%2$s</xliff:g> ወደ <xliff:g id="APP_NAME">%1$s</xliff:g> ለመግባት የማያ ገጽ መቆለፊያዎን ይጠቀሙ"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> መግቢያዎ ጥቅም ላይ ይዋል?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የመግቢያ አማራጮች ይከፈቱ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"የተቀመጠ የይለፍ ቁልፍዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠውን የይለፍ ቃልዎ ይጠቀሙ"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"መለያዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"በ<xliff:g id="USERNAME">%2$s</xliff:g> ወደ <xliff:g id="APP_NAME">%1$s</xliff:g> ለመግባት የማያ ገጽ መቆለፊያዎን ይጠቀሙ"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የመግቢያ አማራጮችን ይከፈቱ"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠ የይለፍ ቁልፍ ይምረጡ"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠ የይለፍ ቃል ይምረጡ"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠ መግቢያ ይጠቀሙ"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> መግቢያ ይምረጡ"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> መለያን ይምረጡ"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> አማራጭ ይመረጥ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ይህን መረጃ በ<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-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index 5e089fe..4a632b7 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"هل تريد استخدام كلمة المرور المحفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"استخدِم قفل الشاشة لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" باستخدام <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"هل تريد استخدام معلومات تسجيل دخولك لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"هل تريد فتح القفل لاستعادة خيارات تسجيل الدخول لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"استخدام مفتاح المرور المحفوظ لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"استخدام كلمة المرور المحفوظة لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"استخدام حسابك لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"استخدِم قفل الشاشة لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" باستخدام <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"فتح القفل لاستعادة خيارات تسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"اختيار مفتاح مرور محفوظ لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"اختيار كلمة مرور محفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"اختيار بيانات اعتماد تسجيل دخول محفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"اختيار معلومات تسجيل الدخول لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"اختيار حساب لتسجيل الدخول إلى \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"هل تريد اختيار بيانات الاعتماد لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"هل تريد استخدام بيانات الاعتماد هذه في \"<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-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 95a0e1b..b106214 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ কৰি থোৱা পাছৱৰ্ড ব্যৱহাৰ কৰিবনে?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g>ৰ জৰিয়তে <xliff:g id="APP_NAME">%1$s</xliff:g>ত ছাইন ইন কৰিবলৈ আপোনাৰ স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছাইন ইন কৰিবলৈ আপোনাৰ ক্ৰিডেনশ্বিয়েল ব্যৱহাৰ কৰিবনে?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছাইন ইনৰ বিকল্পসমূহ আনলক কৰিবনে?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"আপুনি <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ কৰি থোৱা পাছকী ব্যৱহাৰ কৰক"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"আপুনি <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ কৰি থোৱা পাছৱৰ্ড ব্যৱহাৰ কৰক"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে থকা আপোনাৰ একাউণ্ট ব্যৱহাৰ কৰক"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> ব্যৱহাৰ কৰি <xliff:g id="APP_NAME">%1$s</xliff:g>ত ছাইন ইন কৰিবলৈ আপোনাৰ স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছাইন ইনৰ বিকল্পসমূহ আনলক কৰক"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা পাছকী বাছনি কৰক"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা পাছৱৰ্ড বাছনি কৰক"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা ছাইন ইন বাছনি কৰক"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছাইন ইন কৰিবলৈ এটা ক্ৰিডেনশ্বিয়েল বাছনি কৰক"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে এটা একাউণ্ট বাছনি কৰক"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে এটা বিকল্প বাছনি কৰিবনে?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index 00a6718..7c33676 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış parol istifadə edilsin?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə <xliff:g id="USERNAME">%2$s</xliff:g> ilə daxil olmaq üçün ekran kilidindən istifadə edin"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş istifadə edilsin?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş seçimləri kiliddən çıxarılsın?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanılmış giriş açarından istifadə edin"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanılmış paroldan istifadə edin"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün hesabınızdan istifadə edin"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə <xliff:g id="USERNAME">%2$s</xliff:g> ilə daxil olmaq üçün ekran kilidindən istifadə edin"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş seçimlərini kiliddən çıxarın"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış giriş açarı seçin"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış parol seçin"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış giriş seçin"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün giriş seçin"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün hesab seçin"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün seçim edilsin?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Məlumat <xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqində istifadə edilsin?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Başqa üsulla daxil olun"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index 390c774..5661868 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
     <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_password_for" msgid="625828023234318484">"Želite da koristite sačuvanu lozinku za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Koristite otključavanje ekrana da biste se prijavili u <xliff:g id="APP_NAME">%1$s</xliff:g> kao <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Želite li da koristite svoje podatke za prijavljivanje za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Želite da otključate opcije prijavljivanja za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Koristite sačuvani pristupni ključ za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Koristite sačuvanu lozinku za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Koristite nalog za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Koristite otključavanje ekrana da biste se prijavili u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> kao <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Otključajte opcije prijavljivanja za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Izaberite sačuvan pristupni ključ za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Izaberite sačuvanu lozinku za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Izaberite 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="3048870756117876514">"Odaberite podatke za prijavljivanje za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Odaberite nalog za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Želite da odaberete opciju za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Želite da koristite te podatke u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prijavite se na drugi način"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index 6922e70..2d98870e 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Выкарыстоўваць пароль, захаваны для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Выкарыстайце сродак разблакіроўкі экрана для ўваходу ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" як <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Скарыстаць ваш спосаб уваходу для праграмы <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Разблакіраваць варыянты ўваходу для праграмы\"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Выкарыстайце захаваны ключ доступу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Выкарыстайце захаваны пароль для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Выкарыстайце ўліковы запіс для ўваходу ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Выкарыстайце спосаб разблакіроўкі экрана, каб увайсці ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" як <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Разблакіруйце спосабы ўваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Выберыце захаваны ключ доступу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Выберыце захаваны пароль для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Выберыце захаваны спосаб уваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Выберыце спосаб уваходу для праграмы <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Выберыце ўліковы запіс для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Выберыце ўліковыя даныя для ўваходу ў праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Выкарыстоўваць гэтую інфармацыю на прыладзе <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-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index 3d33c8f..e97cc94 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Искате ли да използвате запазената си парола за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Използвайте опцията си за заключване на екрана, за да влизате в(ъв) <xliff:g id="APP_NAME">%1$s</xliff:g> с профила <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Да се използват ли вашите данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Искате ли да отключите опциите за влизане в профила за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Използване на запазения ви ключ за достъп за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Използване на запазената ви парола за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Използване на профила ви за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Използвайте опцията си за заключване на екрана, за да влизате в(ъв) <xliff:g id="APP_NAME">%1$s</xliff:g> с профила <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Искате ли да отключите опциите за влизане в профила за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Изберете запазен ключ за достъп за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Изберете запазена парола за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Изберете запазени данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Избиране на данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Изберете профил за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Искате ли да изберете опция за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Да се използва ли тази информация за <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-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index fe42ed6..8a8e5fa 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"আপনার সেভ করা পাসওয়ার্ড <xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য ব্যবহার করবেন?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"আপনার স্ক্রিন লক ব্যবহার করে <xliff:g id="USERNAME">%2$s</xliff:g>-এর মাধ্যমে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপে সাইন-ইন করুন"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সাইন-ইন ক্রেডেনশিয়াল ব্যবহার করবেন?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সাইন-ইন করার বিকল্প আনলক করতে চান?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা পাসকী ব্যবহার করুন"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা পাসওয়ার্ড ব্যবহার করুন"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার অ্যাকাউন্ট ব্যবহার করুন"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"আপনার \'স্ক্রিন লক\' ব্যবহার করে <xliff:g id="USERNAME">%2$s</xliff:g> আইডির মাধ্যমে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপে সাইন-ইন করুন"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সাইন-ইন করার বিকল্পগুলি আনলক করুন"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সেভ করা পাসকী বেছে নিন"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সেভ করা পাসকী বেছে নিন"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সেভ করা ক্রেডেনশিয়াল বেছে নিন"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সাইন-ইন ক্রেডেনশিয়াল বেছে নিন"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য একটি অ্যাকাউন্ট বেছে নিন"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য বিকল্প বেছে নেবেন?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index f6e6d811..c2d452db 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Povratak na prethodnu stranicu"</string>
     <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_password_for" msgid="625828023234318484">"Koristiti sačuvanu lozinku za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Koristite zaključavanje ekrana da se prijavite u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> s korisničkim imenom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Koristiti prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Otključati opcije prijave za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Koristite sačuvani pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Koristite sačuvanu lozinku za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Koristite račun za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Koristite zaključavanje ekrana da se prijavite u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> pomoću korisničkog imena <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Otključajte načine prijave za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Odaberite sačuvani pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Odaberite sačuvanu lozinku za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Odaberite 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="3048870756117876514">"Odaberite prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Odaberite račun za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Odabrati opciju za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Koristiti ove informacije u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prijavite se na drugi način"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 3809d92..32405a4 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna a la pàgina anterior"</string>
     <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_password_for" msgid="625828023234318484">"Vols utilitzar la contrasenya desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Utilitza el bloqueig de pantalla per iniciar sessió a <xliff:g id="APP_NAME">%1$s</xliff:g> amb <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Vols utilitzar el teu inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vols desbloquejar les opcions d\'inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Utilitza la clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Utilitza la contrasenya desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Utilitza el teu compte per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Utilitza el bloqueig de pantalla per iniciar la sessió a <xliff:g id="APP_NAME">%1$s</xliff:g> amb <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloqueja les opcions d\'inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Tria una clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Tria una clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Tria un 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="3048870756117876514">"Tria un inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Selecciona un compte per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vols triar una opció per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Vols utilitzar aquesta informació a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Inicia la sessió d\'una altra manera"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index 6e6857c..ca7bdde 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zpět na předchozí stránku"</string>
     <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_password_for" msgid="625828023234318484">"Použít pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> uložené heslo?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Přihlašovat se do aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> uživatelským jménem <xliff:g id="USERNAME">%2$s</xliff:g> pomocí zámku obrazovky"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Použít přihlášení pro <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Odemknout možnosti přihlášení pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Použijte pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> uložený přístupový klíč"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Použijte pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> uložené heslo"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Použijte pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> svůj účet"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Přihlašovat se do aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> uživatelským jménem <xliff:g id="USERNAME">%2$s</xliff:g> pomocí zámku obrazovky"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Odemkněte možnosti přihlášení pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Vyberte uložený přístupový klíč pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Vyberte uložené heslo pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Vyberte 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="3048870756117876514">"Vyberte přihlášení pro <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Vyberte účet pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vybrat možnost pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Použít tyto informace na <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Přihlásit se jinak"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index ae7c3cf..a2c0cba2 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbage til den forrige side"</string>
     <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_password_for" msgid="625828023234318484">"Vil du bruge din gemte adgangskode til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Brug din skærmlås til at logge ind på <xliff:g id="APP_NAME">%1$s</xliff:g> med <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Vil du bruge dine loginoplysninger til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vil du låse enheden op for at se loginmetoder for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Brug din gemte adgangsnøgle til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Brug din gemte adgangskode til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Brug din konto til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Brug din skærmlås til at logge ind på <xliff:g id="APP_NAME">%1$s</xliff:g> med <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Lås loginmetoder for <xliff:g id="APP_NAME">%1$s</xliff:g> op"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Vælg en gemt adgangsnøgle til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Vælg en gemt adgangskode til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Vælg en gemt loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Vælg loginoplysninger til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Vælg en konto til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vil du vælge en mulighed for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Vil du bruge disse oplysninger i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Log ind på en anden måde"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index 4fa669b..ccff535 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zurück zur vorherigen Seite"</string>
     <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_password_for" msgid="625828023234318484">"Soll dein gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> verwendet werden?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Du kannst die Displaysperre verwenden, um dich in <xliff:g id="APP_NAME">%1$s</xliff:g> als <xliff:g id="USERNAME">%2$s</xliff:g> anzumelden"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Anmeldeoptionen für <xliff:g id="APP_NAME">%1$s</xliff:g> freischalten?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Dein Konto für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Du kannst die Displaysperre verwenden, um dich in <xliff:g id="APP_NAME">%1$s</xliff:g> als <xliff:g id="USERNAME">%2$s</xliff:g> anzumelden"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Anmeldeoptionen für <xliff:g id="APP_NAME">%1$s</xliff:g> freischalten"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Einen gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Ein gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Konto für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Option für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Diese Infos für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Andere Anmeldeoption auswählen"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index b6b2728..2f3aa0b 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Χρήση του αποθηκευμένου κωδικού πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Χρησιμοποιήστε το κλείδωμα οθόνης για να συνδεθείτε στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> με το όνομα χρήστη <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Χρήση της σύνδεσής σας για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Ξεκλείδωμα των επιλογών σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Χρήση του αποθηκευμένου κλειδιού πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Χρήση του αποθηκευμένου κωδικού πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Χρήση του λογαριασμού για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Χρησιμοποιήστε το κλείδωμα οθόνης για να συνδεθείτε στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> με το όνομα χρήστη <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Ξεκλείδωμα των επιλογών σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Επιλογή αποθηκευμένου κλειδιού πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Επιλογή αποθηκευμένου κωδικού πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Επιλογή αποθηκευμένων στοιχείων σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Επιλέξτε μια σύνδεση για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Επιλογή ενός λογαριασμού για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Επιλογή ενέργειας για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Να χρησιμοποιηθούν αυτές οι πληροφορίες στην εφαρμογή <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-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index f177cf9..d94c6e1 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Use your sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Use your account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choose a saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choose a saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Choose a sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Choose an account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choose an option for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Use this info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Sign in another way"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index df4cd86..f5cb357 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Use your sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Use your account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choose a saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choose a saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Choose a sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Choose an account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choose an option for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Use this info on <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Sign in another way"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index f177cf9..d94c6e1 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Use your sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Use your account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choose a saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choose a saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Choose a sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Choose an account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choose an option for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Use this info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Sign in another way"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index f177cf9..d94c6e1 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Use your sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Use your saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Use your account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use your screen lock to sign in to <xliff:g id="APP_NAME">%1$s</xliff:g> with <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Unlock sign-in options for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choose a saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choose a saved password for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Choose a sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Choose an account for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choose an option for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Use this info for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Sign in another way"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 77ae53a..9841f19 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎Use your saved password for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎Use your screen lock to sign in to ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ with ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‎Use your sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎Unlock sign-in options for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‎Use your saved passkey for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎Use your saved password for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎Use your account for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎Use your screen lock to sign in to ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ with ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎Unlock sign-in options for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎Choose a saved passkey for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎Choose a saved password for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎Choose a saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎Choose a sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‎Choose an account for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎Choose an option for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎Use this info on ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎Sign in another way‎‏‎‎‏‎"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index 6ccfec3..ef27359 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"Credential Manager"</string>
     <string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"Guardar otra forma"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"Guardar de otra forma"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Más información"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Mostrar contraseña"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar contraseña"</string>
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
     <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_password_for" msgid="625828023234318484">"¿Quieres usar la contraseña guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Usar el bloqueo de pantalla para acceder a <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"¿Quieres usar tu acceso para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"¿Quieres desbloquear las opciones de acceso para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Usar la llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Usar la contraseña guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Usar tu cuenta para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Usar el bloqueo de pantalla para acceder a <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloquear las opciones para acceder para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Elige una llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Elige una contraseña guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Elige un acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Elige un acceso para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Elige una cuenta para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"¿Quieres una opción para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"¿Quieres usar esta información en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Acceder de otra forma"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index b2c1c6f..ce2c123 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
     <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_password_for" msgid="625828023234318484">"¿Usar la contraseña que tienes guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Usa tu bloqueo de pantalla para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g> con el usuario <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"¿Usar tu inicio de sesión en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"¿Desbloquear las opciones de inicio de sesión de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Usa la llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Usa la contraseña que tienes guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Usa tu cuenta para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Usa tu bloqueo de pantalla para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloquea las opciones de inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Elige una llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Elige una contraseña guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Elige un 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="3048870756117876514">"Elige un inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Elige la cuenta que usar en <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"¿Elegir una opción para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"¿Usar esta información en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Iniciar sesión de otra manera"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index 823a016..662390a 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -40,7 +40,7 @@
     <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="8762295821604276511">"Kas luua rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks pääsuvõti?"</string>
-    <string name="choose_create_option_password_title" msgid="4481366993598649224">"Kas salvestada rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks parool?"</string>
+    <string name="choose_create_option_password_title" msgid="4481366993598649224">"Kas salvestada parool rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks?"</string>
     <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Kas salvestada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks sisselogimisteave?"</string>
     <string name="passkey" msgid="632353688396759522">"pääsuvõti"</string>
     <string name="password" msgid="6738570945182936667">"parool"</string>
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Minge tagasi eelmisele lehele"</string>
     <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_password_for" msgid="625828023234318484">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> puhul salvestatud parooli?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Kasutage rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> kasutajanimega <xliff:g id="USERNAME">%2$s</xliff:g> sisselogimiseks ekraanilukku"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Kas soovite rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks kasutada oma mandaati?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Kas avada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks sisselogimisvalikud?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Kasutage rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud pääsuvõtit"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Kasutage rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud parooli"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Kasutage rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks kontot"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Kasutage rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> kasutajanimega <xliff:g id="USERNAME">%2$s</xliff:g> sisselogimiseks ekraanilukku"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Avage rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks sisselogimisviisid"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Valige rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud pääsuvõti"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Valige rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud parool"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Valige rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmed"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Valige rakendusse <xliff:g id="APP_NAME">%1$s</xliff:g> sisselogimiseks mandaat"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Valige rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks konto"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Kas teha valik rakendusele <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Kas soovite kasutada seda teavet rakenduses <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Logige sisse muul viisil"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index 8507b3f..6a4974d 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Itzuli aurreko orrira"</string>
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako pasahitza erabili nahi duzu?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Erabili pantailaren blokeoa <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan <xliff:g id="USERNAME">%2$s</xliff:g> kontuarekin saioa hasteko"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> zerbitzuan saioa hasteko kredentzialak erabili nahi dituzu?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan saioa hasteko aukerak desblokeatu nahi dituzu?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Erabili <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako sarbide-gakoa"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Erabili <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako pasahitza"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Erabili zure kontua <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Erabili pantailaren blokeoa <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan <xliff:g id="USERNAME">%2$s</xliff:g> kontuarekin saioa hasteko"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desblokeatu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan saioa hasteko aukerak"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako sarbide-gakoa"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako pasahitza"</string>
-    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako kredentzialak"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> zerbitzuan saioa hasteko kredentzialak"</string>
+    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gordetako saioa hasteko moduak"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan erabili nahi duzun kontua"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako aukera bat hautatu nahi duzu?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioan erabili nahi duzu informazio hori?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Hasi saioa beste modu batean"</string>
@@ -89,10 +89,10 @@
     <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>
     <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_manage_sign_ins" msgid="3522556476480676782">"Kudeatu saioa hasteko moduak"</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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"Utzi du bertan behera eskaera <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak"</string>
-    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Saioa hasteko aukerak"</string>
+    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Saioa hasteko moduak"</string>
     <string name="more_options_content_description" msgid="1323427365788198808">"Gehiago"</string>
 </resources>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index 656c789..6147ccc 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"از گذرواژه ذخیره‌شده‌تان برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"برای ورود به سیستم <xliff:g id="APP_NAME">%1$s</xliff:g> با <xliff:g id="USERNAME">%2$s</xliff:g> از قفل صفحه استفاده کنید"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"از روش ورود به سیستم شما برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"گزینه‌های ورود به سیستم برای <xliff:g id="APP_NAME">%1$s</xliff:g> باز شود؟"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"از گذرکلید ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده کنید"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"از گذرواژه ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده کنید"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"از حساب <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده کنید"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"برای ورود به سیستم <xliff:g id="APP_NAME">%1$s</xliff:g> با <xliff:g id="USERNAME">%2$s</xliff:g> از قفل صفحه استفاده کنید"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"قفل را ازطریق گزینه‌های ورود به سیستم <xliff:g id="APP_NAME">%1$s</xliff:g> باز کنید"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"گذرکلید ذخیره‌شده‌ای را برای <xliff:g id="APP_NAME">%1$s</xliff:g> انتخاب کنید"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"گذرواژه ذخیره‌شده‌ای را برای <xliff:g id="APP_NAME">%1$s</xliff:g> انتخاب کنید"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"اطلاعات ورود به سیستم ذخیره‌شده‌ای را برای <xliff:g id="APP_NAME">%1$s</xliff:g> انتخاب کنید"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"انتخاب روش ورود به سیستم برای <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"حسابی برای <xliff:g id="APP_NAME">%1$s</xliff:g> انتخاب کنید"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"گزینه‌ای را برای <xliff:g id="APP_NAME">%1$s</xliff:g> انتخاب کنید؟"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"از این اطلاعات در <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-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index f2f1bfb..7aa9cb1 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Takaisin edelliselle sivulle"</string>
     <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_password_for" msgid="625828023234318484">"Käytetäänkö tallennettua salasanaasi sovelluksessa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Kirjaudu sisään (<xliff:g id="APP_NAME">%1$s</xliff:g>) käyttämällä näytön lukitusta tilillä <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Käytetäänkö kirjautumistapaa: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Avataanko kirjautumisvaihtoehdot (<xliff:g id="APP_NAME">%1$s</xliff:g>)?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Käytä tallennettua avainkoodia: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Käytetä tallennettua salasanaa: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Käytä tiliä: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Kirjaudu sisään (<xliff:g id="APP_NAME">%1$s</xliff:g>) käyttämällä näytön lukituksen avaustapaa tilillä <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Avaa kirjautumisvaihtoehdot: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g>: valitse tallennettu avainkoodi"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g>: valitse tallennettu salasana"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g>: valitse tallennetut kirjautumistiedot"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Valitse kirjautumistapa: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Valitse tili: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Valitaanko vaihtoehto, jota <xliff:g id="APP_NAME">%1$s</xliff:g> käyttää?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Saako <xliff:g id="APP_NAME">%1$s</xliff:g> käyttää näitä tietoja?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Kirjaudu sisään toisella tavalla"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 891e987..7b8093e 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Retourner à la page précédente"</string>
     <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_password_for" msgid="625828023234318484">"Utiliser votre mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Utilisez votre verrouillage d\'écran pour vous connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> avec <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Utiliser votre identifiant de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Déverrouiller les options de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"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_password_for" msgid="688557784207167647">"Utiliser votre mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Utiliser votre compte pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Utilisez le verrouillage de l\'écran pour vous connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> avec <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Déverrouiller les options de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choisissez une clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choisissez un mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choisissez une connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Choisissez un identifiant de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Choisir un compte pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choisir une option pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Utiliser ces renseignements dans <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Se connecter d\'une autre manière"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index f2ca1fc..c406857 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revenir à la page précédente"</string>
     <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_password_for" msgid="625828023234318484">"Utiliser votre mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Utiliser le verrouillage de l\'écran pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> avec <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Utiliser vos infos de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Déverrouiller les options de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"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_password_for" msgid="688557784207167647">"Utiliser votre mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Utiliser votre compte pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Utiliser le verrouillage de l\'écran pour se connecter à <xliff:g id="APP_NAME">%1$s</xliff:g> avec <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Déverrouiller les options de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Choisir une clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Choisir un mot de passe enregistré pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choisir des 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="3048870756117876514">"Choisir des infos de connexion pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Choisissez les identifiants à utiliser pour la connexion à <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Sélectionnez un compte pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Choisir une option pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Utiliser ces informations dans <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Se connecter d\'une autre manière"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index 7117e1c..c959ade 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver á páxina anterior"</string>
     <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_password_for" msgid="625828023234318484">"Queres usar o contrasinal gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Usa o bloqueo de pantalla para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Queres usar o teu inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Queres desbloquear as opcións de inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Usa a clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Usa o contrasinal gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Usa a túa conta para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Usa o bloqueo de pantalla para iniciar sesión en <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloquea as opcións de inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Escolle unha clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Escolle un contrasinal gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Escolle un 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="3048870756117876514">"Escolle un inicio de sesión para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Escolle un 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="645728947702442421">"Escolle unha conta para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Queres escoller unha opción para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Queres usar esta información en <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Iniciar sesión doutra forma"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index 98b4686..65c3eff 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"શું <xliff:g id="APP_NAME">%1$s</xliff:g> માટે તમારા સાચવેલા પાસવર્ડનો ઉપયોગ કરીએ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> વડે <xliff:g id="APP_NAME">%1$s</xliff:g>માં સાઇન ઇન કરવા માટે તમારા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"શું <xliff:g id="APP_NAME">%1$s</xliff:g>માં સાઇન ઇન કરવા માટે તમારી આ લૉગ ઇન વિગતોનો ઉપયોગ કરીએ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સાઇન ઇન વિકલ્પો અનલૉક કરીએ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે તમારી સાચવેલી પાસકીનો ઉપયોગ કરો"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે તમારા સાચવેલા પાસવર્ડનો ઉપયોગ કરો"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે તમારા એકાઉન્ટનો ઉપયોગ કરો"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> વડે <xliff:g id="APP_NAME">%1$s</xliff:g>માં સાઇન ઇન કરવા માટે તમારા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સાઇન ઇન વિકલ્પો અનલૉક કરો"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ સાચવેલી પાસકી પસંદ કરો"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ સાચવેલો પાસવર્ડ પસંદ કરો"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ સાચવેલું સાઇન-ઇન પસંદ કરો"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g>માં સાઇન ઇન કરવાની કોઈ રીત પસંદ કરો"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ એકાઉન્ટ પસંદ કરો"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g>નો વિકલ્પ પસંદ કરીએ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index 9bc5feb..b40648c 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"CredentialManager"</string>
     <string name="string_cancel" msgid="6369133483981306063">"रद्द करें"</string>
     <string name="string_continue" msgid="1346732695941131882">"जारी रखें"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"दूसरा तरीका सेव करें"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"दूसरे तरीके से सेव करें"</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>
@@ -68,31 +68,31 @@
     <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_password_for" msgid="625828023234318484">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया हुआ पासवर्ड इस्तेमाल करना है?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> से <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए, स्क्रीन लॉक का इस्तेमाल करें"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> के लिए अपने साइन-इन क्रेडेंशियल का इस्तेमाल करना है?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के विकल्पों को अनलॉक करना है?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए, सेव की गई पासकी का इस्तेमाल करें"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए सेव किया हुआ पासवर्ड इस्तेमाल करें"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन करने के लिए अपने खाते का इस्तेमाल करें"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> से <xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए, स्क्रीन लॉक का इस्तेमाल करें"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए, विकल्पों को अनलॉक करें"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव की गई पासकी चुनें"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया गया पासवर्ड चुनें"</string>
-    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया गया साइन इन क्रेडेंशियल चुनें"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए साइन-इन क्रेडेंशियल चुनें"</string>
+    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सेव किया गया क्रेडेंशियल चुनें"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए कोई खाता चुनें"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> में साइन इन करने के लिए सेव किए गए विकल्पों में से किसी को चुनना है?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए, क्या इस जानकारी का इस्तेमाल करना है?"</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>
+    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन-इन करने के लिए विकल्प"</string>
     <string name="button_label_view_more" msgid="3429098227286495651">"ज़्यादा देखें"</string>
     <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> के लिए"</string>
     <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>
     <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_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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g> की ओर से अनुरोध रद्द किया गया"</string>
-    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन-इन करने के विकल्प"</string>
+    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन-इन करने के लिए विकल्प"</string>
     <string name="more_options_content_description" msgid="1323427365788198808">"ज़्यादा"</string>
 </resources>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 968a747..2d90646 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
     <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_password_for" msgid="625828023234318484">"Želite li upotrijebiti spremljenu zaporku za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Upotrijebite zaključavanje zaslona da biste se prijavili u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> korisničkim imenom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Želite li upotrijebiti prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Želite li otključati opcije za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Upotrijebite spremljeni pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Upotrijebite spremljenu zaporku za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Upotrijebite račun za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Upotrijebite zaključavanje zaslona da biste se prijavili u aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> korisničkim imenom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Otključajte opcije za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Odaberite spremljeni pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Odaberite spremljenu zaporku za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Odaberite 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="3048870756117876514">"Odaberite prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Odaberite račun za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Želite li odabrati opciju za <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Želite li koristiti te podatke u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prijavite se na neki drugi način"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index e601da6..41fe127 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vissza az előző oldalra"</string>
     <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_password_for" msgid="625828023234318484">"Szeretné az elmentett jelszavát használni a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"A képernyőzár használata a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásba való bejelentkezéshez a következő felhasználónévvel: <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Szeretné használni bejelentkezési adatait a következőhöz: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Feloldja a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> bejelentkezési lehetőségeit?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Mentett azonosítókulcs használata a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Mentett jelszó használata a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Fiók használata a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"A képernyőzár használata a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásba való bejelentkezéshez a következő felhasználónévvel: <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Feloldja a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> bejelentkezési lehetőségeit?"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Mentett azonosítókulcs kiválasztása a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Mentett jelszó kiválasztása a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
-    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Mentett bejelentkezési adatok kiválasztása a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Válasszon bejelentkezési adatokat – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Mentett bejelentkezési adatok kiválasztása – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Válasszon fiókot a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Kiválaszt egy lehetőséget a következőbe való bejelentkezéshez: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Használni szeretná ezt az információt a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásban?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Bejelentkezés más módon"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index 79a2624..d23874b 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -27,7 +27,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">"Անցաբառերը ձեզ թույլ են տալիս մուտք գործել առանց գաղտնաբառերի։ Ձեզ պարզապես հարկավոր է օգտագործել ձեր մատնահետքը, դիմաճանաչումը, PIN կոդը կամ նախշը՝ ձեր ինքնությունը հաստատելու և անցաբառ ստեղծելու համար։"</string>
@@ -53,7 +53,7 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Պահե՞լ գաղտնաբառն այլ սարքում"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Պահե՞լ մուտքի տվյալներն այլ սարքում"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Միշտ մուտք գործե՞լ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> հավելվածի միջոցով"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Այս գաղտնաբառերի կառավարչում <xliff:g id="USERNAME">%1$s</xliff:g> օգտատերը կկարողանա պահել իր գաղտնաբառերն ու անցաբառերը, որպեսզի հետագայում ավելի արագ մուտք գործի հաշիվ"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Այս գաղտնաբառերի կառավարչում <xliff:g id="USERNAME">%1$s</xliff:g> օգտատերը կկարողանա պահել իր գաղտնաբառերն ու մուտքի բանալիները, որպեսզի հետագայում ավելի արագ մուտք գործի հաշիվ"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Նշել որպես կանխադրված"</string>
     <string name="settings" msgid="6536394145760913145">"Կարգավորումներ"</string>
     <string name="use_once" msgid="9027366575315399714">"Օգտագործել մեկ անգամ"</string>
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Օգտագործե՞լ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար պահված ձեր գաղտնաբառը"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Օգտագործեք ձեր էկրանի կողպումը՝ <xliff:g id="USERNAME">%2$s</xliff:g> հաշվի միջոցով <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Օգտագործե՞լ այս տվյալները <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Ապակողպե՞լ մուտքի տարբերակներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Օգտագործեք <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար պահված ձեր մուտքի բանալին"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Օգտագործեք <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար պահված ձեր գաղտնաբառը"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Օգտագործեք ձեր հաշիվը՝ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Օգտագործեք ձեր էկրանի կողպումը՝ <xliff:g id="USERNAME">%2$s</xliff:g> հաշվի միջոցով <xliff:g id="APP_NAME">%1$s</xliff:g> հավելված մուտք գործելու համար"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Ապակողպեք մուտք գործելու տարբերակներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Ընտրեք պահված անցաբառ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Ընտրեք պահված գաղտնաբառ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Ընտրեք մուտքի պահված տվյալներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Ընտրեք, թե ինչպես եք ուզում մուտք գործել <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Ընտրեք հաշիվ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Ընտրե՞լ տարբերակ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Օգտագործե՞լ այս տեղեկությունները <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-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index e7556b0..9f74b8e 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -68,15 +68,15 @@
     <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">"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_password_for" msgid="625828023234318484">"Gunakan sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Gunakan kunci layar untuk login ke <xliff:g id="APP_NAME">%1$s</xliff:g> dengan <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Gunakan login Anda untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Autentikasi opsi login untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Gunakan kunci sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Gunakan sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Gunakan akun Anda untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Gunakan kunci layar untuk login ke <xliff:g id="APP_NAME">%1$s</xliff:g> dengan <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Autentikasi opsi login untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Pilih kunci sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Pilih sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Pilih info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Pilih login untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Pilih akun untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Pilih opsi untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Gunakan info ini di <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Login dengan cara lain"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index 970a2e6..e5462d1 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Fara aftur á fyrri síðu"</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_password_for" msgid="625828023234318484">"Nota vistaða aðgangsorðið þitt fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Notaðu skjálásinn þinn til að skrá þig inn á <xliff:g id="APP_NAME">%1$s</xliff:g> með <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Nota innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Opna fyrir innskráningarvalkosti fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Nota vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Nota vistað aðgangsorð fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Nota reikninginn þinn fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Notaðu skjálásinn þinn til að skrá þig inn á <xliff:g id="APP_NAME">%1$s</xliff:g> með <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Opna innskráningaraðferð fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Veldu vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Veldu vistað aðgangsorð fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Veldu 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="3048870756117876514">"Veldu innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Veldu reikning fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Velja valkost fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Nota þessar upplýsingar í <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>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index a04a840..54c1fc3 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -40,7 +40,7 @@
     <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="8762295821604276511">"Creare passkey per accedere all\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="choose_create_option_password_title" msgid="4481366993598649224">"Salvare password per accedere all\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="choose_create_option_password_title" msgid="4481366993598649224">"Salvare la password per accedere all\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"Vuoi salvare i dati di accesso di <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"passkey"</string>
     <string name="password" msgid="6738570945182936667">"password"</string>
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna alla pagina precedente"</string>
     <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_password_for" msgid="625828023234318484">"Vuoi usare la password salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Usa il blocco schermo per accedere a <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Vuoi usare il tuo accesso per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vuoi sbloccare le opzioni di accesso per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Usa la passkey salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Usa la password salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Usa il tuo account per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Usa il blocco schermo per accedere all\'app <xliff:g id="APP_NAME">%1$s</xliff:g> con <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Sblocca le opzioni di accesso per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Scegli una passkey salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Scegli una password salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Scegli un accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Scegli un accesso per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Scegli un account per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vuoi scegliere un\'opzione per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Vuoi usare questi dati su <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Accedi in un altro modo"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index 87dee5f..46ad865 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"להשתמש בסיסמה השמורה של <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"שימוש בשיטה לביטול נעילת המסך כדי להיכנס לחשבון של <xliff:g id="USERNAME">%2$s</xliff:g> ב-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"להשתמש בחשבון שלך כדי להיכנס אל <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"לבטל את הנעילה של אפשרויות הכניסה אל <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"שימוש במפתח הגישה השמור של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"שימוש בסיסמה השמורה של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"שימוש בחשבון של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"שימוש בשיטה לביטול נעילת המסך כדי להיכנס לחשבון של <xliff:g id="USERNAME">%2$s</xliff:g> ב-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"ביטול הנעילה של אמצעי הכניסה אל <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"בחירת מפתח גישה שמור ל-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"בחירת סיסמה שמורה ל-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"בחירת פרטי כניסה שמורים ל-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"בחירת חשבון לכניסה אל <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"צריך לבחור חשבון לכניסה אל <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"רוצה לבחור אפשרות עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"להשתמש במידע הזה בשביל <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-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index 71746dc..afe11361 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したパスワードを使用しますか?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"画面ロックを使用して <xliff:g id="USERNAME">%2$s</xliff:g> で <xliff:g id="APP_NAME">%1$s</xliff:g> にログインできます"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"この認証情報を使用して <xliff:g id="APP_NAME">%1$s</xliff:g> にログインしますか?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> がログイン方法を使用できるようにしますか?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"保存したパスキーを <xliff:g id="APP_NAME">%1$s</xliff:g> に使用する"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"保存したパスワードを <xliff:g id="APP_NAME">%1$s</xliff:g> に使用する"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"アカウントを <xliff:g id="APP_NAME">%1$s</xliff:g> に使用する"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"画面ロックを使用して <xliff:g id="USERNAME">%2$s</xliff:g> で <xliff:g id="APP_NAME">%1$s</xliff:g> にログインできます"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> がログイン方法を使用できるようにする"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> に使用するパスキーを選択してください"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> に使用するパスワードを選択してください"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> に使用するログイン情報を選択してください"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> のログインに使用する認証情報の選択"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> 用のアカウントを選択する"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> のオプションを選択しますか?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index 51f1332..4224da6 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"გამოიყენებთ შენახულ პაროლს <xliff:g id="APP_NAME">%1$s</xliff:g>-სთვის?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"გამოიყენეთ თქვენი ეკრანის დაბლოკვის ფუნქცია <xliff:g id="APP_NAME">%1$s</xliff:g>-ში <xliff:g id="USERNAME">%2$s</xliff:g>-ით შესასვლელად"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"გსურთ შესვლის <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის გამოყენება?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"გსურთ შესვლის ვარიანტების განბლოკვა <xliff:g id="APP_NAME">%1$s</xliff:g>-სთვის?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"თქვენი დამახსოვრებული წვდომის გასაღების გამოყენება <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"გამოიყენეთ შენახული პაროლი <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"გამოიყენეთ თქვენი ანგარიში <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"გამოიყენეთ თქვენი ეკრანის დაბლოკვის ფუნქცია <xliff:g id="APP_NAME">%1$s</xliff:g>-ში <xliff:g id="USERNAME">%2$s</xliff:g>-ით შესასვლელად"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"შესვლის ვარიანტების განბლოკვა <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"აირჩიეთ შენახული წვდომის გასაღები <xliff:g id="APP_NAME">%1$s</xliff:g>-სთვის"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"აირჩიეთ შენახული პაროლი <xliff:g id="APP_NAME">%1$s</xliff:g>-სთვის"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"აირჩიეთ სისტემაში შესვლის ინფორმაცია <xliff:g id="APP_NAME">%1$s</xliff:g>-სთვის"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"აირჩიეთ შესვლა <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"აირჩიეთ ანგარიში <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"გსურთ აირჩიოთ ვარიანტი <xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"გსურთ ამ ინფორმაციის გამოყენება <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-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 7393ca0..2fd31ee 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған құпия сөзіңізді пайдаланасыз ба?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына <xliff:g id="USERNAME">%2$s</xliff:g> аккаунтымен кіру үшін экран құлпын қолданыңыз."</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына кіру деректерін пайдаланасыз ба?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін кіру опциялары ашылсын ба?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілті пайдаланыңыз"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған құпия сөзді пайдаланыңыз"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін аккаунтыңызды пайдаланыңыз"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына <xliff:g id="USERNAME">%2$s</xliff:g> аккаунтымен кіру үшін экран құлпын қолданыңыз."</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін аккаунтқа кіру әдістерін ашыңыз"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілтін таңдаңыз"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған құпия сөзді таңдаңыз"</string>
-    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректерін таңдаңыз"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына кіру деректерін таңдаңыз"</string>
+    <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру деректерін таңдаңыз"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін аккаунт таңдаңыз"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін опция таңдайсыз ба?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Бұл ақпарат <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-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index ac0d427..64b0376 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"ប្រើពាក្យសម្ងាត់​ដែលអ្នកបាន​រក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"ប្រើមុខងារចាក់សោអេក្រង់របស់អ្នក ដើម្បីចូល <xliff:g id="APP_NAME">%1$s</xliff:g> ដោយប្រើ <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"ប្រើការចូលគណនីរបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"ដោះ​សោជម្រើសចូល​គណនីសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"ប្រើកូដសម្ងាត់ដែលអ្នកបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"ប្រើពាក្យសម្ងាត់​ដែលអ្នកបាន​រក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"ប្រើគណនីរបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"ប្រើមុខងារចាក់សោអេក្រង់របស់អ្នក ដើម្បីចូល <xliff:g id="APP_NAME">%1$s</xliff:g> ដោយប្រើ <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"ដោះ​សោជម្រើសចូល​គណនីសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"ជ្រើសរើសកូដសម្ងាត់ដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"ជ្រើសរើសពាក្យ​សម្ងាត់ដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"ជ្រើសរើសការចូលគណនីដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"ជ្រើសរើសការចូលគណនីសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"ជ្រើសរើសគណនី​សម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"ជ្រើសរើសជម្រើសសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ប្រើព័ត៌មាននេះ​នៅលើ <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-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index 031fa65..bfc31a1 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ನಿಮ್ಮ ಉಳಿಸಲಾದ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಬಳಸಬೇಕೇ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ <xliff:g id="USERNAME">%2$s</xliff:g> ಮೂಲಕ ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ನಿಮ್ಮ ಸೈನ್ ಇನ್ ಅನ್ನು ಬಳಸಬೇಕೇ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೈನ್-ಇನ್ ಆಯ್ಕೆಗಳನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಬೇಕೇ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೇವ್ ಮಾಡಿದ ನಿಮ್ಮ ಪಾಸ್‌ಕೀ ಅನ್ನು ಬಳಸಿ"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೇವ್ ಮಾಡಿದ ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಬಳಸಿ"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಬಳಸಿ"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ <xliff:g id="USERNAME">%2$s</xliff:g> ಮೂಲಕ ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೈನ್ ಇನ್ ಆಯ್ಕೆಗಳನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಪಾಸ್‌ಕೀ ಅನ್ನು ಆರಿಸಿ"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಆರಿಸಿ"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೈನ್ ಇನ್ ಅನ್ನು ಆರಿಸಿ"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಒಂದು ಖಾತೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಆಯ್ಕೆಯನ್ನು ಆರಿಸಬೇಕೆ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ಈ ಮಾಹಿತಿಯನ್ನು <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-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index e29ae68..468f4e7 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -20,7 +20,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="2763852250269945472">"다른 방법 저장하기"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"다른 방법으로 저장하기"</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>
@@ -39,7 +39,7 @@
     <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">"정보를 저장해서 다음에 더 빠르게 로그인하려면 비밀번호 관리자를 선택하세요."</string>
-    <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"패스키를 생성하여 <xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인하시겠습니까?"</string>
+    <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 패스키를 생성할까요?"</string>
     <string name="choose_create_option_password_title" msgid="4481366993598649224">"비밀번호를 저장하여 <xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인하시겠습니까?"</string>
     <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 로그인 정보를 저장하시겠습니까?"</string>
     <string name="passkey" msgid="632353688396759522">"패스키"</string>
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"저장된 비밀번호를 <xliff:g id="APP_NAME">%1$s</xliff:g>에 사용할까요?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"화면 잠금을 사용하여 <xliff:g id="USERNAME">%2$s</xliff:g> 계정으로 <xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인합니다."</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인을 사용하시겠습니까?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 대해 로그인 옵션을 잠금 해제하시겠습니까?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱에 대해 저장된 패스키를 사용하시겠습니까?"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱에 대해 저장된 비밀번호를 사용하시겠습니까?"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱에 계정을 사용하시겠습니까?"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"화면 잠금을 사용하여 <xliff:g id="USERNAME">%2$s</xliff:g> 계정으로 <xliff:g id="APP_NAME">%1$s</xliff:g>에 로그인합니다."</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱에 대해 로그인 옵션을 잠금 해제하시겠습니까?"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 대해 저장된 패스키 선택"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 대해 저장된 비밀번호 선택"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 대해 저장된 로그인 정보 선택"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g>에 사용할 로그인 선택"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱에 사용할 계정 선택"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱의 옵션을 선택하시겠습니까?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index 5e48ae5..4172b51 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган сырсөздү колдоносузбу?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна <xliff:g id="USERNAME">%2$s</xliff:g> аккаунту менен кирүү үчүн экрандын кулпусун колдонуңуз"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна төмөнкү аккаунт менен киресизби?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн кирүү параметрлеринин кулпусу ачылсынбы?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган киргизүүчү ачкычты колдонуңуз"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган сырсөздү колдонуңуз"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн аккаунтуңузду колдонуңуз"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна <xliff:g id="USERNAME">%2$s</xliff:g> аккаунту менен кирүү үчүн экрандын кулпусун колдонуңуз"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн кирүү параметрлеринин кулпусун ачыңыз"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган киргизүүчү ачкычты тандаңыз"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган сырсөздү тандаңыз"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн кирүү маалыматын тандаңыз"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна кайсы аккаунт менен киресиз:"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн аккаунт тандаңыз"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн параметр тандайсызбы?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Бул маалыматты <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-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index c3733a3..de5b810 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"ໃຊ້ລະຫັດຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"ໃຊ້ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອເຂົ້າສູ່ລະບົບ <xliff:g id="APP_NAME">%1$s</xliff:g> ດ້ວຍ <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"ເລືອກການເຂົ້າສູ່ລະບົບຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"ປົດລັອກຕົວເລືອກການເຂົ້າສູ່ລະບົບສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"ໃຊ້ກະແຈຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"ໃຊ້ລະຫັດຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"ໃຊ້ບັນຊີຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"ໃຊ້ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອເຂົ້າສູ່ລະບົບ <xliff:g id="APP_NAME">%1$s</xliff:g> ດ້ວຍ <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"ປົດລັອກຕົວເລືອກການເຂົ້າສູ່ລະບົບສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"ເລືອກກະແຈຜ່ານທີ່ບັນທຶກໄວ້ສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"ເລືອກລະຫັດຜ່ານທີ່ບັນທຶກໄວ້ສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"ເລືອກການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"ເລືອກການເຂົ້າສູ່ລະບົບສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"ເລືອກບັນຊີສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"ເລືອກຕົວເລືອກສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ໃຊ້ຂໍ້ມູນນີ້ຢູ່ <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-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index 453a0e0..e236e09 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Grįžti į ankstesnį puslapį"</string>
     <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_password_for" msgid="625828023234318484">"Naudoti išsaugotą slaptažodį programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Naudodami ekrano užraktą prisijunkite prie „<xliff:g id="APP_NAME">%1$s</xliff:g>“ kaip <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Naudoti prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Atrakinti prisijungimo prie „<xliff:g id="APP_NAME">%1$s</xliff:g>“ parinktis?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Naudokite išsaugotą prieigos raktą, skirtą programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Naudokite išsaugotą slaptažodį, skirtą programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Naudokite paskyrą, skirtą programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Naudodami ekrano užraktą prisijunkite prie „<xliff:g id="APP_NAME">%1$s</xliff:g>“ kaip <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Atrakinkite prisijungimo parinktis, skirtas programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Išsaugoto prieigos rakto, skirto „<xliff:g id="APP_NAME">%1$s</xliff:g>“, pasirinkimas"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Išsaugoto slaptažodžio, skirto „<xliff:g id="APP_NAME">%1$s</xliff:g>“, pasirinkimas"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Pasirinkite 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="3048870756117876514">"Pasirinkite prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Pasirinkite paskyrą, skirtą „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Pasirinkti parinktį programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Naudoti šią informaciją programoje „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prisijungti kitu būdu"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index 4da1051..258f1b9 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Atgriezties iepriekšējā lapā"</string>
     <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_password_for" msgid="625828023234318484">"Vai izmantot jūsu saglabāto paroli lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Izmantot ekrāna bloķēšanu, lai lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> pierakstītos ar kontu <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Vai izmantot jūsu pierakstīšanās informāciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vai vēlaties atbloķēt lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> pierakstīšanās opcijas?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Saglabātās piekļuves atslēgas izmantošana lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Saglabātās paroles izmantošana lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Sava konta izmantošana lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Izmantojiet ekrāna bloķēšanas opciju, lai lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> pierakstītos ar kontu <xliff:g id="USERNAME">%2$s</xliff:g>."</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> pierakstīšanās opciju atbloķēšana"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Saglabātas piekļuves atslēgas izvēle lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Saglabātas paroles izvēle lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Saglabātas pierakstīšanās informācijas izvēle lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Pierakstīšanās informācijas izvēle lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Konta izvēle izmantošanai lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vai izvēlēties opciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Vai izmantot šo informāciju lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Pierakstīties citā veidā"</string>
@@ -93,6 +93,6 @@
     <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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g> atcēla pieprasījumu"</string>
-    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Pierakstīšanās iespējas"</string>
+    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Pierakstīšanās opcijas"</string>
     <string name="more_options_content_description" msgid="1323427365788198808">"Vairāk"</string>
 </resources>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index 95554a2..62806f6 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Да се користат зачуваните лозинки за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Користете го заклучувањето екран за да се најавувате на <xliff:g id="APP_NAME">%1$s</xliff:g> со <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Да се користи вашето најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Да се отклучат опциите за најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Користете го зачуваниот криптографски клуч за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Користете ја зачуваната лозинка за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Користете ја вашата сметка за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Користете го заклучувањето екран за да се најавувате на <xliff:g id="APP_NAME">%1$s</xliff:g> со <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Отклучете ги опциите за најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Изберете зачуван криптографски клуч за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Изберете зачувана лозинка за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Изберете зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Изберете најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Изберете сметка за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Избери опција за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Да се користат овие информации на <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-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index eccfb51..598ccc0 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങളുടെ സംരക്ഷിച്ച പാസ്‌വേഡ് ഉപയോഗിക്കണോ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> എന്നയാളായി <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്യാൻ നിങ്ങളുടെ സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനുള്ള നിങ്ങളുടെ സൈൻ ഇൻ ക്രെഡൻഷ്യലുകൾ ഉപയോഗിക്കണോ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി സൈൻ ഇൻ ഓപ്‌ഷനുകൾ അൺലോക്ക് ചെയ്യണോ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനായി നിങ്ങളുടെ സംരക്ഷിച്ച പാസ്‌കീ ഉപയോഗിക്കുക"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനായി നിങ്ങളുടെ സംരക്ഷിച്ച പാസ്‌വേഡ് ഉപയോഗിക്കുക"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനായി നിങ്ങളുടെ അക്കൗണ്ട് ഉപയോഗിക്കുക"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> എന്നയാളായി <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്യാൻ നിങ്ങളുടെ സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനായി സൈൻ ഇൻ ചെയ്യൽ ഓപ്ഷനുകൾ അൺലോക്ക് ചെയ്യുക"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച പാസ്‌കീ തിരഞ്ഞെടുക്കുക"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച പാസ്‌വേഡ് തിരഞ്ഞെടുക്കുക"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച സൈൻ ഇൻ തിരഞ്ഞെടുക്കുക"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനുള്ള സൈൻ ഇൻ ക്രെഡൻഷ്യലുകൾ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിനായി ഒരു അക്കൗണ്ട് തിരഞ്ഞെടുക്കുക"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്ന ആപ്പിനായി ഒരു ഓപ്‌ഷൻ തിരഞ്ഞെടുക്കണോ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index 5b1cbe9..958233a 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -68,15 +68,15 @@
     <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>-д өөрийн хадгалсан passkey-г ашиглах уу?"</string>
-    <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нууц үгээ ашиглах уу?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д <xliff:g id="USERNAME">%2$s</xliff:g>-р нэвтрэхийн тулд дэлгэцийн түгжээгээ ашиглана уу"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н нэвтрэлтээ ашиглах уу?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д нэвтрэлтийн сонголтын түгжээг тайлах уу?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх түлхүүрээ ашиглана уу"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нууц үгээ ашиглана уу"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д нэвтрэх бүртгэлээ ашиглана уу"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д <xliff:g id="USERNAME">%2$s</xliff:g>-р нэвтрэхийн тулд дэлгэцийн түгжээгээ ашиглана уу"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д нэвтрэх сонголтын түгжээг тайлна уу"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх түлхүүр сонгоно уу"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нууц үг сонгоно уу"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх мэдээллийг сонгоно уу"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н нэвтрэлтийг сонгоно уу"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д нэвтрэх бүртгэл сонгоно уу"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д сонголт хийх үү?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Энэ мэдээллийг <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-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index a0a4a7d..7eebec5 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -68,21 +68,21 @@
     <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_password_for" msgid="625828023234318484">"तुमचा सेव्ह केलेला पासवर्ड <xliff:g id="APP_NAME">%1$s</xliff:g> साठी वापरायचा आहे का?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> सह <xliff:g id="APP_NAME">%1$s</xliff:g> मध्ये साइन इन करण्यासाठी तुमचे स्क्रीन लॉक वापरा"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचे साइन-इन वापरायचे आहे का?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी साइन-इन पर्याय अनलॉक करायचे आहेत का?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमची सेव्ह केलेली पासकी वापरा"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचा सेव्ह केलेला पासवर्ड वापरा"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचे खाते वापरा"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> वापरून <xliff:g id="APP_NAME">%1$s</xliff:g> मध्ये साइन इन करण्यासाठी तुमचे स्क्रीन लॉक वापरा"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी साइन-इन पर्याय अनलॉक करा"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सेव्ह केलेली पासकी निवडा"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सेव्ह केलेला पासवर्ड निवडा"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सेव्ह केलेले साइन-इन निवडा"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी साइन-इन निवडा"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी खाते निवडा"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी पर्याय निवडा?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ही माहिती <xliff:g id="APP_NAME">%1$s</xliff:g> वर वापरायची का?"</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>
+    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन-इन पर्याय"</string>
     <string name="button_label_view_more" msgid="3429098227286495651">"आणखी पहा"</string>
     <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> साठी"</string>
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक केलेले पासवर्ड व्यवस्थापक"</string>
@@ -93,6 +93,6 @@
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"दुसऱ्या डिव्हाइस वरून"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"वेगळे डिव्हाइस वापरा"</string>
     <string name="request_cancelled_by" msgid="3735222326886267820">"<xliff:g id="APP_NAME">%1$s</xliff:g> ने विनंती रद्द केली आहे"</string>
-    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन इन करण्याचे पर्याय"</string>
+    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"साइन-इन पर्याय"</string>
     <string name="more_options_content_description" msgid="1323427365788198808">"आणखी"</string>
 </resources>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index c866013..aa216c2 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Gunakan kata laluan anda yang disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Gunakan kunci skrin anda untuk log masuk ke <xliff:g id="APP_NAME">%1$s</xliff:g> dengan <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Gunakan log masuk anda untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Buka kunci pilihan log masuk untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Gunakan kunci laluan anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Gunakan kata laluan anda yang disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Gunakan akaun anda untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Gunakan kunci skrin anda untuk log masuk ke <xliff:g id="APP_NAME">%1$s</xliff:g> dengan <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Buka kunci pilihan log masuk untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Pilih kunci laluan yang disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Pilih kata laluan yang disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Pilih log masuk yang disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Pilih log masuk untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Pilih akaun untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Pilih satu pilihan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Gunakan maklumat ini pada <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Log masuk menggunakan cara lain"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index a66e7b6..2f6086a 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောစကားဝှက် သုံးမလား။"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> သို့ <xliff:g id="USERNAME">%2$s</xliff:g> ဖြင့် လက်မှတ်ထိုးဝင်ရန် သင့်ဖန်သားပြင်လော့ခ်ကို သုံးနိုင်သည်"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သင့်လက်မှတ်ထိုးဝင်မှုကို သုံးမလား။"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် လက်မှတ်ထိုးဝင်မှု ရွေးစရာကို ဖွင့်မလား။"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သင်သိမ်းထားသော လျှို့ဝှက်ကီးကို သုံးပါ"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သင်သိမ်းထားသော စကားဝှက်ကို သုံးပါ"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သင့်အကောင့်ကို သုံးပါ"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> သို့ <xliff:g id="USERNAME">%2$s</xliff:g> ဖြင့် လက်မှတ်ထိုးဝင်ရန် သင့်ဖန်သားပြင်လော့ခ်ကို သုံးနိုင်သည်"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် လက်မှတ်ထိုးဝင်မှု ရွေးစရာကို ဖွင့်ပါ"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသော လျှို့ဝှက်ကီး ရွေးပါ"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသော စကားဝှက် ရွေးပါ"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသော လက်မှတ်ထိုးဝင်မှုကို ရွေးပါ"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် လက်မှတ်ထိုးဝင်မှု ရွေးခြင်း"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် အကောင့်တစ်ခု ရွေးပါ"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် တစ်ခုကိုရွေးမလား။"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index 7f4fa6b..9739635 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbake til den forrige siden"</string>
     <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_password_for" msgid="625828023234318484">"Vil du bruke det lagrede passordet ditt for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Bruk skjermlåsen til å logge på <xliff:g id="APP_NAME">%1$s</xliff:g> med <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Vil du bruke påloggingen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vil du låse opp påloggingsalternativene for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Bruk den lagrede passnøkkelen din for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Bruk det lagrede passordet ditt for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Bruk kontoen din for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Bruk skjermlåsen til å logge på <xliff:g id="APP_NAME">%1$s</xliff:g> med <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Lås opp påloggingsalternativene for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Velg en lagret passnøkkel for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Velg et lagret passord for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Velg en lagret pålogging for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Velg pålogging for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Velg en konto for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vil du velge et alternativ for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Vil du bruke denne informasjonen i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Bruk en annen påloggingsmetode"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index 6e69476..07775e0 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -22,8 +22,8 @@
     <string name="string_continue" msgid="1346732695941131882">"जारी राख्नुहोस्"</string>
     <string name="string_more_options" msgid="2763852250269945472">"अर्को तरिकाले सेभ गर्नुहोस्"</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>
+    <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_body_password" msgid="8825872426579958200">"तपाईंले पासकी बनाउनुभयो भने तपाईंले जटिल पासवर्ड बनाउनु वा तिनलाई याद गरिराख्नु पर्दैन"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी भनेको तपाईंले आफ्नो फिंगरप्रिन्ट, अनुहार वा स्क्रिन लक प्रयोग गरेर बनाएको इन्क्रिप्ट गरिएको डिजिटल की हो"</string>
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न सेभ गरिएको पासवर्ड प्रयोग गर्ने हो?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न आफ्नो स्क्रिन लक प्रयोग गर्नुहोस्"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्नका लागि तपाईंका क्रिडेन्सियलहरू प्रयोग गर्ने हो?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> का साइन इनसम्बन्धी विकल्पहरू अनलक गर्ने हो?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> चलाउन सेभ गरिएको पासकी प्रयोग गर्नुहोस्"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> चलाउन सेभ गरिएको पासवर्ड प्रयोग गर्नुहोस्"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> चलाउन आफ्नो खाता प्रयोग गर्नुहोस्"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न आफ्नो स्क्रिन लक प्रयोग गर्नुहोस्"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> चलाउन साइन इनसम्बन्धी विकल्पहरू प्राप्त गर्नुहोस्"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न सेभ गरिएको पासकी छनौट गर्नुहोस्"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न सेभ गरिएको पासवर्ड छनौट गर्नुहोस्"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न सेभ गरिएका क्रिडेन्सियल छनौट गर्नुहोस्"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्न प्रयोग गरिने क्रिडेन्सियलहरू छनौट गर्नुहोस्"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> चलाउन कुनै खाता छनौट गर्नुहोस्"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन गर्न प्रयोग गरिने क्रिडेन्सियल छनौट गर्ने हो?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index 50eefc7..d7790c7 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -68,21 +68,21 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Ga terug naar de vorige pagina"</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_password_for" msgid="625828023234318484">"Je opgeslagen wachtwoord voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Gebruik je schermvergrendeling om in te loggen bij <xliff:g id="APP_NAME">%1$s</xliff:g> met <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Je login voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Inlogopties voor <xliff:g id="APP_NAME">%1$s</xliff:g> ontgrendelen?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Gebruik je opgeslagen toegangssleutel voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Gebruik je opgeslagen wachtwoord voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Gebruik je account voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Gebruik je schermvergrendeling om in te loggen bij <xliff:g id="APP_NAME">%1$s</xliff:g> met <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Ontgrendel inlogopties voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Opgeslagen toegangssleutel kiezen voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Opgeslagen wachtwoord kiezen voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Opgeslagen login kiezen voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Kies een login voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Kies een account voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Een optie kiezen voor <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Deze informatie gebruiken in <xliff:g id="APP_NAME">%1$s</xliff:g>?"</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>
+    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Inlogopties"</string>
     <string name="button_label_view_more" msgid="3429098227286495651">"Meer bekijken"</string>
     <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Voor <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vergrendelde wachtwoordmanagers"</string>
@@ -93,6 +93,6 @@
     <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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"Verzoek geannuleerd door <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Opties voor inloggen"</string>
+    <string name="dropdown_presentation_more_sign_in_options_text" msgid="1693727354272417902">"Inlogopties"</string>
     <string name="more_options_content_description" msgid="1323427365788198808">"Meer"</string>
 </resources>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 56e585d..336b29f 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଆପଣଙ୍କ ସେଭ କରାଯାଇଥିବା ପାସୱାର୍ଡକୁ ବ୍ୟବହାର କରିବେ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> ମାଧ୍ୟମରେ <xliff:g id="APP_NAME">%1$s</xliff:g>ରେ ସାଇନ ଇନ କରିବା ପାଇଁ ଆପଣଙ୍କ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଆପଣଙ୍କ ସାଇନ-ଇନ ବ୍ୟବହାର କରିବେ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସାଇନ-ଇନ ବିକଳ୍ପଗୁଡ଼ିକୁ ଅନଲକ କରିବେ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଆପଣଙ୍କ ସେଭ କରାଯାଇଥିବା ପାସକୀ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଆପଣଙ୍କ ସେଭ କରାଯାଇଥିବା ପାସୱାର୍ଡ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଆପଣଙ୍କ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> ମାଧ୍ୟମରେ <xliff:g id="APP_NAME">%1$s</xliff:g>ରେ ସାଇନ ଇନ କରିବା ପାଇଁ ଆପଣଙ୍କ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସାଇନ-ଇନ ବିକଳ୍ପକୁ ଅନଲକ କରନ୍ତୁ"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଏକ ପାସକୀ ବାଛନ୍ତୁ"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଏକ ପାସୱାର୍ଡ ବାଛନ୍ତୁ"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଏକ ସାଇନ-ଇନ ବାଛନ୍ତୁ"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଏକ ସାଇନ-ଇନ ବାଛନ୍ତୁ"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଏକ ଆକାଉଣ୍ଟ ବାଛନ୍ତୁ"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ଏକ ବିକଳ୍ପ ବାଛିବେ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index d23d209..517fd82 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਤੁਹਾਡਾ ਰੱਖਿਅਤ ਕੀਤਾ ਪਾਸਵਰਡ ਵਰਤਣਾ ਹੈ?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> ਨਾਲ <xliff:g id="APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਨ ਲਈ ਆਪਣੇ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣਾ ਸਾਈਨ-ਇਨ ਕਰਨ ਦਾ ਵਿਕਲਪ ਵਰਤਣਾ ਹੈ?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸਾਈਨ-ਇਨ ਵਿਕਲਪਾਂ ਨੂੰ ਅਣਲਾਕ ਕਰਨਾ ਹੈ?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਪਾਸਕੀ ਵਰਤੋ"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣਾ ਰੱਖਿਅਤ ਕੀਤਾ ਪਾਸਵਰਡ ਵਰਤੋ"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣਾ ਖਾਤਾ ਵਰਤੋ"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> ਨਾਲ <xliff:g id="APP_NAME">%1$s</xliff:g> ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਨ ਲਈ ਆਪਣੇ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸਾਈਨ-ਇਨ ਵਿਕਲਪਾਂ ਨੂੰ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਕੋਈ ਰੱਖਿਅਤ ਕੀਤੀ ਪਾਸਕੀ ਚੁਣੋ"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਕੋਈ ਰੱਖਿਅਤ ਕੀਤਾ ਪਾਸਵਰਡ ਚੁਣੋ"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਕੋਈ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਚੁਣੋ"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸਾਈਨ-ਇਨ ਕਰਨ ਦਾ ਵਿਕਲਪ ਚੁਣੋ"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਕੋਈ ਖਾਤਾ ਚੁਣੋ"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਕਿਸੇ ਵਿਕਲਪ ਦੀ ਚੋਣ ਕਰਨੀ ਹੈ?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ਕੀ <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-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index 5fa26b4..3857de4 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Wróć do poprzedniej strony"</string>
     <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_password_for" msgid="625828023234318484">"Użyć zapisanego hasła do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Używaj metody odblokowywania ekranu, aby logować się do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> za pomocą nazwy użytkownika <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Użyć tych danych logowania do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Odblokować opcje logowania do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Użyj zapisanego klucza dostępu do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Użyj zapisanego hasła do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Użyj swojego konta w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Używaj metody odblokowywania ekranu, aby logować się w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> za pomocą nazwy użytkownika <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Odblokuj opcje logowania w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Wybierz zapisany klucz dostępu do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Wybierz zapisane hasło do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Wybierz zapisane dane logowania do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Wybierz dane logowania do aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Wybierz konto dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Wybrać opcję dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Użyć tych informacji w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Zaloguj się w inny sposób"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 994bc55..bc8a969 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -68,15 +68,15 @@
     <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 o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"Usar a senha salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use o bloqueio de tela para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g> com a conta <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Usar seu login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Desbloquear opções de login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Usar sua chave de acesso salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Usar a senha salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Usar sua conta para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use o bloqueio de tela para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g> com a conta <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloquear opções de login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Escolha uma chave de acesso salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Escolha uma senha salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Escolha uma credencial de login salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Escolha uma opção de login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Escolha uma conta para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Escolher uma opção para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Usar estas informações no app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Fazer login de outra forma"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 26c6491..2204e02 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volte à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</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_password_for" msgid="625828023234318484">"Usar a sua palavra-passe guardada para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use o seu bloqueio de ecrã para iniciar sessão na app <xliff:g id="APP_NAME">%1$s</xliff:g> com <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Usar o seu início de sessão para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Desbloquear as opções de início de sessão para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Use a sua chave de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Use a sua palavra-passe guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Use sua conta na app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use o seu bloqueio de ecrã para iniciar sessão na app <xliff:g id="APP_NAME">%1$s</xliff:g> com <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloqueie as opções de início de sessão para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Escolha uma chave de acesso guardada para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Escolha uma palavra-passe guardada para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"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_title_choose_sign_in_for" msgid="3048870756117876514">"Escolha um início de sessão para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Escolha uma conta para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Escolher uma opção para a app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Usar estas informações na 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 994bc55..bc8a969 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -68,15 +68,15 @@
     <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 o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"Usar a senha salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Use o bloqueio de tela para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g> com a conta <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Usar seu login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Desbloquear opções de login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Usar sua chave de acesso salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Usar a senha salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Usar sua conta para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Use o bloqueio de tela para fazer login no app <xliff:g id="APP_NAME">%1$s</xliff:g> com a conta <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloquear opções de login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Escolha uma chave de acesso salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Escolha uma senha salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Escolha uma credencial de login salva para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Escolha uma opção de login para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Escolha uma conta para o app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Escolher uma opção para o app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Usar estas informações no app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Fazer login de outra forma"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index 342b6ab..9e42dbb 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revino la pagina precedentă"</string>
     <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_password_for" msgid="625828023234318484">"Folosești parola salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Folosește blocarea ecranului ca să te conectezi la <xliff:g id="APP_NAME">%1$s</xliff:g> cu <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Folosești datele de conectare pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Deblochezi opțiunile de conectare pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Folosește cheia de acces salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Folosește parola salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Folosește-ți contul pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Folosește blocarea ecranului ca să te conectezi la <xliff:g id="APP_NAME">%1$s</xliff:g> cu <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Deblochează opțiunile de conectare pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Alege o cheie de acces salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Alege o parolă salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Alege o conectare salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Alege un set de date conectare pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Alege un cont pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Alegi o opțiune pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Folosești aceste informații în <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Conectează-te altfel"</string>
@@ -89,7 +89,7 @@
     <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>
     <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_manage_sign_ins" msgid="3522556476480676782">"Gestionează conectă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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"Solicitare anulată de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index e472695..ec2a2d6 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Использовать сохраненный пароль для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Используйте способ разблокировки экрана для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" (<xliff:g id="USERNAME">%2$s</xliff:g>)."</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Войти в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" с этими данными?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Разблокировать варианты входа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Используйте сохраненный ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Используйте сохраненный пароль для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Используйте аккаунт для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Используйте способ разблокировки экрана для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" (<xliff:g id="USERNAME">%2$s</xliff:g>)."</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Разблокируйте способы входа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Выберите сохраненный ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Выберите сохраненный пароль для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Выберите сохраненные учетные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Как вы хотите войти в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Выберите аккаунт для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Выберите данные для входа в приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Использовать эту информацию для входа в приложение \"<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-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index ce0b9cd..dc0d846 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරපදය භාවිත කරන්න ද?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> සමඟින් <xliff:g id="APP_NAME">%1$s</xliff:g> වෙත පුරනය වීමට ඔබේ තිර අගුල භාවිත කරන්න"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ පුරනය වීම භාවිතා කරන්න ද?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා පුරන විකල්ප අගුලු හරින්න ද?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරයතුර භාවිතා කරන්න"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරපදය භාවිතා කරන්න"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ ගිණුම භාවිතා කරන්න"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> සමඟින් <xliff:g id="APP_NAME">%1$s</xliff:g> වෙත පුරනය වීමට ඔබේ තිර අගුල භාවිත කරන්න"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා පුරනය වීමේ විකල්ප අගුළු හරින්න"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා සුරකින ලද මුරයතුරක් තෝරන්න"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා සුරකින ලද මුරපදයක් තෝරන්න"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා සුරැකි පුරනයක් තෝරා ගන්න"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා පුරනය වීමක් තෝරා ගන්න"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ගිණුමක් තෝරා ගන්න"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා විකල්පයක් තෝරන්නද?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 62a2e69..8e6b32c 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Prejsť späť na predchádzajúcu stránku"</string>
     <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_password_for" msgid="625828023234318484">"Chcete použiť uložené heslo aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Pomocou zámky obrazovky sa prihláste do aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g> používateľským menom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Chcete použiť svoje prihlásenie pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Chcete odomknúť možnosti prihlásenia pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Použite svoj uložený prístupový kľúč pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Použite uložené heslo pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Použite svoj účet pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Pomocou zámky obrazovky sa prihláste do aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g> používateľským menom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Odomknite možnosti prihlásenia pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Vyberte uložený prístupový kľúč pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Vyberte uložené heslo pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Vyberte uložené prihlasovacie údaje pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Vyberte prihlásenie pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Vyberte účet pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> vybrať možnosť?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Chcete použiť tieto informácie v aplikácii <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prihlásiť sa inak"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index d2aaf68..437ced1 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -48,7 +48,7 @@
     <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 za: <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
     <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Želite ustvariti ključ za dostop v drugi napravi?"</string>
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Želite shraniti geslo v drugi napravi?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Želite shraniti prijavo v drugi napravi?"</string>
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Ali želite uporabiti shranjeno geslo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Uporabite zaklepanje zaslona za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g> z uporabniškim imenom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Želite uporabiti svojo prijavo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Želite odkleniti možnosti prijave za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Uporaba shranjenega ključa za dostop za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Uporaba shranjenega gesla za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Uporaba vašega računa za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Uporabite zaklepanje zaslona za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g> z uporabniškim imenom <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Odklepanje možnosti prijave za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Izberite shranjeni ključ za dostop za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Izberite shranjeno geslo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Izberite shranjene podatke za prijavo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Izberite prijavo za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Izbira računa za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Izberite možnost za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Želite te podatke uporabiti v aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prijava na drug način"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index f31d16a..8dc0fc2 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kthehu te faqja e mëparshme"</string>
     <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_password_for" msgid="625828023234318484">"Të përdoret fjalëkalimi i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Përdor kyçjen e ekranit për t\'u identifikuar në <xliff:g id="APP_NAME">%1$s</xliff:g> me <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Të përdoret identifikimi yt për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Të shkyçen opsionet e identifikimit për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Përdor fjalëkalimin tënd të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Përdor fjalëkalimin tënd të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Përdor llogarinë tënde për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Përdor kyçjen e ekranit për t\'u identifikuar në \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" me <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Shkyç opsionet e identifikimit për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Zgjidh një çelës kalimi të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Zgjidh një fjalëkalim të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Zgjidh një identifikim të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Zgjidh një identifikim për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Zgjidh një llogari për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Të zgjidhet një opsion për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Të përdoren këto informacione në <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Identifikohu me një mënyrë tjetër"</string>
@@ -89,7 +89,7 @@
     <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>
     <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_manage_sign_ins" msgid="3522556476480676782">"Menaxho identifikimet"</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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"Kërkesa u anulua nga <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index e68a20c..d28cefe 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Желите да користите сачувану лозинку за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Користите откључавање екрана да бисте се пријавили у <xliff:g id="APP_NAME">%1$s</xliff:g> као <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Желите ли да користите своје податке за пријављивање за апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Желите да откључате опције пријављивања за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Користите сачувани приступни кључ за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Користите сачувану лозинку за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Користите налог за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Користите откључавање екрана да бисте се пријавили у апликацију <xliff:g id="APP_NAME">%1$s</xliff:g> као <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Откључајте опције пријављивања за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Изаберите сачуван приступни кључ за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Изаберите сачувану лозинку за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Изаберите сачуване податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Одаберите податке за пријављивање за апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Одаберите налог за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Желите да одаберете опцију за апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Желите да користите те податке у апликацији <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-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index e18fea1..cab499a 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tillbaka till föregående sida"</string>
     <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_password_for" msgid="625828023234318484">"Vill du använda det sparade lösenordet för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Använd skärmlåset för att logga in i <xliff:g id="APP_NAME">%1$s</xliff:g> med <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Vill du använda din inloggning för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vill du låsa upp inloggningsalternativ för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Använd den sparade nyckeln för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Använd det sparade lösenordet för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Använd kontot för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Använd skärmlåset för att logga in i <xliff:g id="APP_NAME">%1$s</xliff:g> med <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Lås upp inloggningsalternativ för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Välj en sparad nyckel för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Välj ett sparat lösenord för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Välj en sparad inloggning för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Välj en inloggning för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Välj ett konto för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vill du välja ett alternativ för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Vill du använda den här informationen på <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Logga in på ett annat sätt"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 65672d5..3386373 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Rudi kwenye ukurasa uliotangulia"</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_password_for" msgid="625828023234318484">"Je, ungependa kutumia nenosiri lako lililohifadhiwa kuingia katika <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Tumia mbinu yako ya kufunga skrini kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g> ukitumia <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Ungependa kutumia kitambulisho chako cha kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Je, ungependa kuona chaguo za kuingia katika <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Tumia ufunguo wako wa siri uliohifadhi wa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Tumia nenosiri lako ulilohifadhi la <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Tumia akaunti yako ya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Tumia mbinu yako ya kufunga skrini kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g> ukitumia <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Fungua chaguo za kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Chagua ufunguo wa siri uliohifadhiwa ambao ungependa kutumia kuingia katika <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Chagua nenosiri lililohifadhiwa ambalo ungependa kutumia kuingia katika <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Chagua vitambulisho vilivyohifadhiwa ambavyo ungependa kutumia kuingia katika <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Chagua kitambulisho 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="645728947702442421">"Chagua akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Ungependa kuteua chaguo la <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Ungependa kutumia maelezo haya kwenye <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>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 49d1710..96d2676 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்குச் சேமித்த கடவுச்சொல்லைப் பயன்படுத்தவா?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> ஐப் பயன்படுத்தி <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸில் உள்நுழைய உங்கள் திரைப் பூட்டைப் பயன்படுத்துங்கள்"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு உங்கள் உள்நுழைவு விவரங்களைப் பயன்படுத்தவா?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான உள்நுழைவு விருப்பங்களை அன்லாக் செய்யவா?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான சேமிக்கப்பட்ட கடவுச்சாவியைப் பயன்படுத்துங்கள்"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான சேமிக்கப்பட்ட கடவுச்சொல்லைப் பயன்படுத்துங்கள்"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான உங்கள் கணக்கைப் பயன்படுத்துங்கள்"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> ஐப் பயன்படுத்தி <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸில் உள்நுழைய உங்கள் திரைப் பூட்டைப் பயன்படுத்துங்கள்"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான உள்நுழைவு விருப்பங்களை அன்லாக் செய்யுங்கள்"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான சேமிக்கப்பட்ட கடவுச்சாவியைத் தேர்ந்தெடுங்கள்"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான சேமிக்கப்பட்ட கடவுச்சொல்லைத் தேர்ந்தெடுங்கள்"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான சேமிக்கப்பட்ட உள்நுழைவுத் தகவல்களைத் தேர்ந்தெடுங்கள்"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான உள்நுழைவு விவரங்களைத் தேர்வுசெய்யுங்கள்"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான கணக்கைத் தேர்வுசெய்யுங்கள்"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கான விருப்பத்தைத் தேர்வுசெய்யவா?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 742a422..3b98438 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్‌వర్డ్‌ను ఉపయోగించాలా?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"మీ స్క్రీన్ లాక్‌ను ఉపయోగించి <xliff:g id="USERNAME">%2$s</xliff:g>‌తో <xliff:g id="APP_NAME">%1$s</xliff:g>‌కు సైన్ ఇన్ చేయండి"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సైన్ ఇన్ వివరాలను ఉపయోగించాలా?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సైన్ ఇన్ ఆప్షన్‌లను అన్‌లాక్ చేయాలా?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్-కీ వివరాలను ఉపయోగించండి"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్‌వర్డ్‌ను ఉపయోగించండి"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ ఖాతాను ఉపయోగించండి"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"మీ స్క్రీన్ లాక్‌ను ఉపయోగించి <xliff:g id="USERNAME">%2$s</xliff:g>‌తో <xliff:g id="APP_NAME">%1$s</xliff:g>‌కు సైన్ ఇన్ చేయండి"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సైన్ ఇన్ ఆప్షన్‌లను అన్‌లాక్ చేయండి"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన పాస్-కీని ఎంచుకోండి"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన పాస్‌వర్డ్‌ను ఎంచుకోండి"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఎంచుకోండి"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సైన్ ఇన్ వివరాలను ఎంచుకోండి"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం ఖాతాను ఎంచుకోండి"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం ఏదైనా ఆప్షన్‌ను ఎంచుకోవాలనుకుంటున్నారా?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ఈ సమాచారాన్ని <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 3f9de26..bb47574 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"ใช้รหัสผ่านที่บันทึกไว้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"ใช้การล็อกหน้าจอเพื่อลงชื่อเข้าใช้ <xliff:g id="APP_NAME">%1$s</xliff:g> ด้วย <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"ใช้การลงชื่อเข้าใช้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"ปลดล็อกตัวเลือกการลงชื่อเข้าใช้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"ใช้พาสคีย์ที่บันทึกไว้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"ใช้รหัสผ่านที่บันทึกไว้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"ใช้บัญชีสำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"ใช้การล็อกหน้าจอเพื่อลงชื่อเข้าใช้ <xliff:g id="APP_NAME">%1$s</xliff:g> ด้วย <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"ปลดล็อกตัวเลือกการลงชื่อเข้าใช้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"เลือกพาสคีย์ที่บันทึกไว้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"เลือกรหัสผ่านที่บันทึกไว้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"เลือกการลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"เลือกการลงชื่อเข้าใช้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"เลือกบัญชีสำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"ต้องการเลือกตัวเลือกสำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"ใช้ข้อมูลนี้กับ <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-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index 659c1ec..ebc2f4d 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Bumalik sa nakaraang page"</string>
     <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_password_for" msgid="625828023234318484">"Gamitin ang iyong naka-save na password para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Gamitin ang iyong lock ng screen para mag-sign in sa <xliff:g id="APP_NAME">%1$s</xliff:g> gamit ang <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Gamitin ang iyong sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"I-unlock ang mga opsyon sa pag-sign in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"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_password_for" msgid="688557784207167647">"Gamitin ang iyong naka-save na password para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Gamitin ang iyong account para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Gamitin ang iyong lock ng screen para mag-sign in sa <xliff:g id="APP_NAME">%1$s</xliff:g> gamit ang <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"I-unlock ang mga opsyon sa pag-sign in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Pumili ng naka-save na passkey para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Pumili ng naka-save na password para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Pumili ng 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="3048870756117876514">"Pumili ng sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Pumili ng account para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Pumili ng opsyon para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Gamitin ang impormasyong ito sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Mag-sign in sa ibang paraan"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 5139a67..3c9c3b7 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Önceki sayfaya geri dön"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Kapat"</string>
     <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Kapat"</string>
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı geçiş anahtarınız kullanılsın mı?"</string>
-    <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifreniz kullanılsın mı?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında <xliff:g id="USERNAME">%2$s</xliff:g> hesabıyla oturum açmak için ekran kilidinizi kullanın"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma bilgileriniz kullanılsın mı?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma seçeneklerine izin verilsin mi?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı geçiş anahtarınızı kullanın"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifrenizi kullanın"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> için hesabınızı kullanın"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında <xliff:g id="USERNAME">%2$s</xliff:g> hesabıyla oturum açmak için ekran kilidinizi kullanın"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma seçeneklerinin kilidini açın"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir geçiş anahtarı kullanın"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir şifre kullanın"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgilerini kullanın"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma bilgilerini seçin"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması için bir hesap seçin"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bir seçim yapmak ister misiniz?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Bu bilgiler <xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında kullanılsın mı?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Başka bir yöntemle oturum aç"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index 62eac9a..a3f79ca 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"Використати ваш збережений пароль для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Використовуйте свій спосіб розблокування екрана, щоб входити в додаток <xliff:g id="APP_NAME">%1$s</xliff:g> як користувач <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Використовувати ваші дані для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Розблокувати опції входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Використайте свій збережений ключ доступу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Використайте свій збережений пароль для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Використайте свій обліковий запис для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Використовуйте свій спосіб розблокування екрана, щоб входити в додаток <xliff:g id="APP_NAME">%1$s</xliff:g> як користувач <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Розблокуйте способи входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Виберіть збережений ключ доступу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Виберіть збережений пароль для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Виберіть збережені дані для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Виберіть дані для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Виберіть обліковий запис для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Вибрати варіант для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Використовувати ці дані в додатку <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-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index 9fad273..1a39abb 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے آپ کا محفوظ کردہ پاس ورڈ استعمال کریں؟"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="USERNAME">%2$s</xliff:g> کے ساتھ <xliff:g id="APP_NAME">%1$s</xliff:g> میں سائن ان کرنے کے لیے اپنا اسکرین لاک استعمال کریں"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے آپ کی سائن ان تفصیلات استعمال کریں؟"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے سائن ان کے اختیارات کو غیر مقفل کریں؟"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنی محفوظ کردہ پاس کی استعمال کریں"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے آپ کا محفوظ کردہ پاس ورڈ استعمال کریں"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنا اکاؤنٹ استعمال کریں"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="USERNAME">%2$s</xliff:g> کے ساتھ <xliff:g id="APP_NAME">%1$s</xliff:g> میں سائن ان کرنے کے لیے اپنا اسکرین لاک استعمال کریں"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے سائن ان کے اختیارات کو غیر مقفل کریں"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے ایک محفوظ کردہ پاس کی منتخب کریں"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے ایک محفوظ کردہ پاس ورڈ منتخب کریں"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے محفوظ کردہ سائن ان منتخب کریں"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے سائن ان منتخب کریں"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے ایک اکاؤنٹ منتخب کریں"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے ایک اختیار منتخب کریں؟"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"<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-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index a3d2025..db0c96b 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan parol ishlatilsinmi?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga <xliff:g id="USERNAME">%2$s</xliff:g> bilan kirish uchun ekran qulfini ishlating"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga bu maʼlumotlar bilan kirilsinmi?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun kirish usullari ochilsinmi?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga saqlangan kalit orqali kiring"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan parol orqali kiring"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga hisobingiz orqali kiring"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga <xliff:g id="USERNAME">%2$s</xliff:g> bilan kirish uchun ekran qulfini ishlating"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga kirish usulini tasdiqlang"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan kalitni tanlang"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan parolni tanlang"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun hisob maʼlumotlarini tanlang"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga qanday kirishni tanlang"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga kirish hisobini tanlang"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga kirish uchun maʼlumotlar tanlansinmi?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Bu axborotdan <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga kirish uchun foydalanilsinmi?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Boshqa usul orqali kirish"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index da04efd..91eecd8 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -68,21 +68,21 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Quay lại trang trước"</string>
     <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 khoá đăng nhập bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"Sử dụng mật khẩu bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Dùng phương thức khoá màn hình để đăng nhập vào <xliff:g id="APP_NAME">%1$s</xliff:g> bằng <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Dùng thông tin đăng nhập của bạn cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Mở khoá các tuỳ chọn đăng nhập cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Dùng khoá truy cập bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Dùng mật khẩu 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="4233553937542583226">"Dùng tài khoản của bạn cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Dùng phương thức khoá màn hình để đăng nhập vào <xliff:g id="APP_NAME">%1$s</xliff:g> bằng <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Mở khoá các phương thức đăng nhập cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Chọn khoá truy cập đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Chọn mật khẩu đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Chọn thông tin đăng nhập đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Chọn thông tin đăng nhập cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Chọn một tài khoản cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Chọn một lựa chọn cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Sử dụng thông tin này trên <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Đăng nhập bằng cách khác"</string>
     <string name="snackbar_action" msgid="37373514216505085">"Xem các lựa chọn"</string>
     <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Tiếp tục"</string>
-    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Tuỳ chọn đăng nhập"</string>
+    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Lựa chọn đăng nhập"</string>
     <string name="button_label_view_more" msgid="3429098227286495651">"Xem thêm"</string>
     <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Cho <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Trình quản lý mật khẩu đã khoá"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index 968e978..4d6a371 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"要使用已保存的密码登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”吗?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"使用您的屏锁以 <xliff:g id="USERNAME">%2$s</xliff:g> 的身份登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"是否使用您的<xliff:g id="APP_NAME">%1$s</xliff:g>登录凭据继续?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"要解锁“<xliff:g id="APP_NAME">%1$s</xliff:g>”的登录选项吗?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"使用已保存的通行密钥登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"使用已保存的密码登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"使用您的账号登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"使用您的屏锁以 <xliff:g id="USERNAME">%2$s</xliff:g> 的身份登录 <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"解锁“<xliff:g id="APP_NAME">%1$s</xliff:g>”的登录选项"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"选择一个已保存的通行密钥来登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"选择一个已保存的密码来登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"选择一种已保存的登录方式来登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"选择一种登录<xliff:g id="APP_NAME">%1$s</xliff:g>的方式"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"选择一个账号登录“<xliff:g id="APP_NAME">%1$s</xliff:g>”"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"要为“<xliff:g id="APP_NAME">%1$s</xliff:g>”选择一个选项吗?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"要将此信息用于“<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-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 7a375c9..44f5eaa 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼嗎?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"使用螢幕鎖定方式以 <xliff:g id="USERNAME">%2$s</xliff:g> 登入 <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"要以此登入方式使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」嗎?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"要解鎖「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入選項嗎?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"使用已儲存的 <xliff:g id="APP_NAME">%1$s</xliff:g> 密鑰"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"使用已儲存的 <xliff:g id="APP_NAME">%1$s</xliff:g> 密碼"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"透過你的帳戶使用 <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"使用螢幕鎖定方式以 <xliff:g id="USERNAME">%2$s</xliff:g> 登入 <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"解鎖 <xliff:g id="APP_NAME">%1$s</xliff:g> 的登入選項"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密鑰"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"選擇用於「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入方式"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"選擇使用 <xliff:g id="APP_NAME">%1$s</xliff:g> 的帳戶"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"要選擇適用於「<xliff:g id="APP_NAME">%1$s</xliff:g>」的項目嗎?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"要在「<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-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index 0299088..d5f3093 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -68,15 +68,15 @@
     <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_password_for" msgid="625828023234318484">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼嗎?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"用 <xliff:g id="USERNAME">%2$s</xliff:g> 登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」時使用螢幕鎖定功能進行驗證"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"要使用你的憑證登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」嗎?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"要解鎖「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入選項嗎?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼金鑰"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」的帳戶"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"用 <xliff:g id="USERNAME">%2$s</xliff:g> 登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」時使用螢幕鎖定功能進行驗證"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"解鎖「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入選項"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼金鑰"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"選擇用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的憑證"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"選擇要用於「<xliff:g id="APP_NAME">%1$s</xliff:g>」的帳戶"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"要選擇適用於「<xliff:g id="APP_NAME">%1$s</xliff:g>」的項目嗎?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"要在「<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-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index 4f888f4..db7c992 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -68,15 +68,15 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Buyela emuva ekhasini langaphambilini"</string>
     <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_password_for" msgid="625828023234318484">"Sebenzisa iphasiwedi yakho elondoloziwe ye-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_single_tap_for" msgid="2057945648748859483">"Sebenzisa ukukhiya kwakho kwesikrini ukuze ungene ngemvume ku-<xliff:g id="APP_NAME">%1$s</xliff:g> ngo-<xliff:g id="USERNAME">%2$s</xliff:g>"</string>
-    <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Sebenzisa ukungena kwakho ngemvume ku-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
-    <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Vula ukungena ngemvume okukhethwa kukho kwe-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="479261099705979148">"Sebenzisa ukhiye wakho wokungena olondoloziwe we-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_password_for" msgid="688557784207167647">"Sebenzisa iphasiwedi yakho elondoloziwe ye-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_use_sign_in_for" msgid="4233553937542583226">"Sebenzisa i-akhawunti yakho ye-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Sebenzisa ukukhiya kwakho isikrini ukuze ungene ngemvume ku-<xliff:g id="APP_NAME">%1$s</xliff:g> ngo-<xliff:g id="USERNAME">%2$s</xliff:g>"</string>
+    <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Vula ukungena ngemvume okukhethwa kukho kwe-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Khetha ukhiye wokudlula olondoloziwe we-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Khetha iphasiwedi elondoloziwe ye-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Khetha ukungena ngemvume okulondoloziwe kwe-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Khetha ukungenangemvume ku-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Khetha i-akhawunti ye-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Khetha ongakhetha kukho kwe-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_info_on" msgid="8863708099535435146">"Sebenzisa lolu lwazi ku-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Ngena ngemvume ngenye indlela"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index bc35a85..46a5138 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -68,7 +68,6 @@
   <string name="choose_create_option_password_title">Save password to sign in to <xliff:g id="app_name" example="Tribank">%1$s</xliff:g>?</string>
   <!-- This appears as the title of the modal bottom sheet for users to choose the create option inside a provider when the credential type is others. [CHAR LIMIT=200] -->
   <string name="choose_create_option_sign_in_title">Save sign-in info for <xliff:g id="app_name" example="Tribank">%1$s</xliff:g>?</string>
-  <!-- Types which are inserted as a placeholder as credentialTypes for other strings. [CHAR LIMIT=200] -->
   <string name="passkey">passkey</string>
   <string name="password">password</string>
   <string name="passkeys">passkeys</string>
@@ -119,15 +118,15 @@
 
   <!-- Strings for the get flow. -->
   <!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
-  <string name="get_dialog_title_use_passkey_for">Use your saved passkey for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
+  <string name="get_dialog_title_use_passkey_for">Use your saved passkey for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
   <!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved password to sign in to the app. [CHAR LIMIT=200] -->
-  <string name="get_dialog_title_use_password_for">Use your saved password for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
-  <!-- This appears as a description of the modal bottom sheet when the single tap sign in flow is used for the get flow. [CHAR LIMIT=200] -->
-  <string name="get_dialog_title_single_tap_for">Use your screen lock to sign in to <xliff:g id="app_name" example="Shrine">%1$s</xliff:g> with <xliff:g id="username" example="[email protected]">%2$s</xliff:g></string>
+  <string name="get_dialog_title_use_password_for">Use your saved password for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
   <!-- This appears as the title of the dialog asking for user confirmation to use the single user credential (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
-  <string name="get_dialog_title_use_sign_in_for">Use your sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
+  <string name="get_dialog_title_use_sign_in_for">Use your account for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
+  <!-- This appears as the description of the modal bottom sheet asking for user confirmation to use the biometric screen embedded within credential manager for passkey authentication. [CHAR LIMIT=200] -->
+  <string name="get_dialog_description_single_tap">Use your screen lock to sign in to <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> with <xliff:g id="username" example="[email protected]">%2$s</xliff:g></string>
   <!-- This appears as the title of the dialog asking for user confirmation to unlock / authenticate (e.g. via fingerprint, faceId, passcode etc.) so that we can retrieve their sign-in options. [CHAR LIMIT=200] -->
-  <string name="get_dialog_title_unlock_options_for">Unlock sign-in options for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
+  <string name="get_dialog_title_unlock_options_for">Unlock sign-in options for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
   <!-- This appears as the title of the dialog asking for user to make a choice from multiple previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
   <string name="get_dialog_title_choose_passkey_for">Choose a saved passkey for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
   <!-- This appears as the title of the dialog asking for user to make a choice from multiple previously saved passwords to sign in to the app. [CHAR LIMIT=200] -->
@@ -135,7 +134,7 @@
   <!-- This appears as the title of the dialog asking for user to make a choice from multiple previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
   <string name="get_dialog_title_choose_saved_sign_in_for">Choose a saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
   <!-- This appears as the title of the dialog asking for user to make a choice from various available user credentials (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
-  <string name="get_dialog_title_choose_sign_in_for">Choose a sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
+  <string name="get_dialog_title_choose_sign_in_for">Choose an account for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
   <!-- This appears as the title of the dialog asking for user to make a choice from options of available user information (e.g. driver's license, vaccination status) to pass to the app. [CHAR LIMIT=200] -->
   <string name="get_dialog_title_choose_option_for">Choose an option for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
   <!-- This appears as the title of the dialog asking user to send a piece of user information (e.g. driver's license, vaccination status) to the app. [CHAR LIMIT=200] -->
diff --git a/packages/CredentialManager/shared/project.config b/packages/CredentialManager/shared/project.config
new file mode 100644
index 0000000..f748d6c
--- /dev/null
+++ b/packages/CredentialManager/shared/project.config
@@ -0,0 +1,9 @@
+[notify "team"]
+	header = cc
+        email = [email protected]
+        email = [email protected]
+	email = [email protected]
+	email = [email protected]
+	email = [email protected]
+	type = new_changes
+	type = submitted_changes
\ No newline at end of file
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt
index ab70394..694e27a 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/client/impl/CredentialManagerClientImpl.kt
@@ -21,7 +21,6 @@
 import android.content.Intent
 import android.credentials.selection.BaseDialogResult
 import android.credentials.selection.BaseDialogResult.RESULT_CODE_DIALOG_USER_CANCELED
-import android.credentials.selection.Constants
 import android.credentials.selection.ProviderPendingIntentResponse
 import android.credentials.selection.UserSelectionDialogResult
 import android.os.Bundle
@@ -117,21 +116,17 @@
         sendCancellationCode(
             cancelCode = cancelCode,
             requestToken = token,
-            resultReceiver = resultReceiver,
-            finalResponseReceiver = finalResponseReceiver
+            resultReceiver = resultReceiver
         )
     }
 
     private fun sendCancellationCode(
         cancelCode: Int,
         requestToken: IBinder?,
-        resultReceiver: ResultReceiver?,
-        finalResponseReceiver: ResultReceiver?
+        resultReceiver: ResultReceiver?
     ) {
         if (requestToken != null && resultReceiver != null) {
-            val resultData = Bundle().apply {
-                putParcelable(Constants.EXTRA_FINAL_RESPONSE_RECEIVER, finalResponseReceiver)
-            }
+            val resultData = Bundle()
             BaseDialogResult.addToBundle(BaseDialogResult(requestToken), resultData)
             resultReceiver.send(cancelCode, resultData)
         }
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt
index f2c252e..9c8ec3b 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt
@@ -51,6 +51,8 @@
 import com.android.credentialmanager.model.BiometricRequestInfo
 import com.android.credentialmanager.model.EntryInfo
 
+const val CREDENTIAL_ENTRY_PREFIX = "androidx.credentials.provider.credentialEntry."
+
 fun EntryInfo.getIntentSenderRequest(
     isAutoSelected: Boolean = false
 ): IntentSenderRequest? {
@@ -140,7 +142,8 @@
                     isDefaultIconPreferredAsSingleProvider =
                             credentialEntry.isDefaultIconPreferredAsSingleProvider,
                     affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
-                    biometricRequest = predetermineAndValidateBiometricFlow(it),
+                    biometricRequest = retrieveEntryBiometricRequest(it,
+                        CREDENTIAL_ENTRY_PREFIX),
                 )
                 )
             }
@@ -169,7 +172,8 @@
                     isDefaultIconPreferredAsSingleProvider =
                             credentialEntry.isDefaultIconPreferredAsSingleProvider,
                     affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
-                    biometricRequest = predetermineAndValidateBiometricFlow(it),
+                    biometricRequest = retrieveEntryBiometricRequest(it,
+                        CREDENTIAL_ENTRY_PREFIX),
                 )
                 )
             }
@@ -197,7 +201,8 @@
                     isDefaultIconPreferredAsSingleProvider =
                             credentialEntry.isDefaultIconPreferredAsSingleProvider,
                     affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
-                    biometricRequest = predetermineAndValidateBiometricFlow(it),
+                    biometricRequest = retrieveEntryBiometricRequest(it,
+                        CREDENTIAL_ENTRY_PREFIX),
                 )
                 )
             }
@@ -211,27 +216,32 @@
 }
 
 /**
- * This validates if this is a biometric flow or not, and if it is, this returns the expected
+ * This validates if the entry calling this method contains biometric info, and if so, returns a
  * [BiometricRequestInfo]. Namely, the biometric flow must have at least the
  * ALLOWED_AUTHENTICATORS bit passed from Jetpack.
  * Note that the required values, such as the provider info's icon or display name, or the entries
  * credential type or userName, and finally the display info's app name, are non-null and must
  * exist to run through the flow.
+ *
+ * @param hintPrefix a string prefix indicating the type of entry being utilized, since both create
+ * and get flows utilize slice params; includes the final '.' before the name of the type (e.g.
+ * androidx.credentials.provider.credentialEntry.SLICE_HINT_ALLOWED_AUTHENTICATORS must have
+ * 'hintPrefix' up to "androidx.credentials.provider.credentialEntry.")
  * // TODO(b/326243754) : Presently, due to dependencies, the opId bit is parsed but is never
  * // expected to be used. When it is added, it should be lightly validated.
  */
-private fun predetermineAndValidateBiometricFlow(
-    it: Entry
+fun retrieveEntryBiometricRequest(
+    entry: Entry,
+    hintPrefix: String,
 ): BiometricRequestInfo? {
     // TODO(b/326243754) : When available, use the official jetpack structured type
-    val allowedAuthenticators: Int? = it.slice.items.firstOrNull {
-        it.hasHint("androidx.credentials." +
-                "provider.credentialEntry.SLICE_HINT_ALLOWED_AUTHENTICATORS")
+    val allowedAuthenticators: Int? = entry.slice.items.firstOrNull {
+        it.hasHint(hintPrefix + "SLICE_HINT_ALLOWED_AUTHENTICATORS")
     }?.int
 
     // This is optional and does not affect validating the biometric flow in any case
-    val opId: Int? = it.slice.items.firstOrNull {
-        it.hasHint("androidx.credentials.provider.credentialEntry.SLICE_HINT_CRYPTO_OP_ID")
+    val opId: Int? = entry.slice.items.firstOrNull {
+        it.hasHint(hintPrefix + "SLICE_HINT_CRYPTO_OP_ID")
     }?.int
     if (allowedAuthenticators != null) {
         return BiometricRequestInfo(opId = opId, allowedAuthenticators = allowedAuthenticators)
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt
index 786c441..9242141 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/IntentKtx.kt
@@ -54,9 +54,3 @@
         Constants.EXTRA_RESULT_RECEIVER,
         ResultReceiver::class.java
     )
-
-val Intent.finalResponseReceiver: ResultReceiver?
-    get() = this.getParcelableExtra(
-        Constants.EXTRA_FINAL_RESPONSE_RECEIVER,
-        ResultReceiver::class.java
-    )
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt
index 1683cc4..f1f1f7c 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestGetMapper.kt
@@ -20,7 +20,6 @@
 import android.content.Intent
 import com.android.credentialmanager.ktx.getCredentialProviderDataList
 import com.android.credentialmanager.ktx.requestInfo
-import com.android.credentialmanager.ktx.finalResponseReceiver
 import com.android.credentialmanager.ktx.resultReceiver
 import com.android.credentialmanager.ktx.toProviderList
 import com.android.credentialmanager.model.Request
@@ -29,7 +28,6 @@
     return Request.Get(
         token = requestInfo?.token,
         resultReceiver = resultReceiver,
-        finalResponseReceiver = finalResponseReceiver,
         providerInfos = getCredentialProviderDataList.toProviderList(context)
     )
 }
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt
index fd99275..cb335fc 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt
@@ -25,8 +25,7 @@
  */
 sealed class Request private constructor(
     open val token: IBinder?,
-    open val resultReceiver: ResultReceiver? = null,
-    open val finalResponseReceiver: ResultReceiver? = null,
+    open val resultReceiver: ResultReceiver? = null
 ) {
 
     /**
@@ -51,9 +50,8 @@
     data class Get(
         override val token: IBinder?,
         override val resultReceiver: ResultReceiver?,
-        override val finalResponseReceiver: ResultReceiver?,
         val providerInfos: List<ProviderInfo>,
-    ) : Request(token, resultReceiver, finalResponseReceiver)
+    ) : Request(token, resultReceiver)
     /**
      * Request to start the create credentials flow.
      */
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index b17a98b..3683235 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -58,7 +58,6 @@
     private val providerEnabledList: List<ProviderData>
     private val providerDisabledList: List<DisabledProviderData>?
     val resultReceiver: ResultReceiver?
-    val finalResponseReceiver: ResultReceiver?
 
     var initialUiState: UiState
 
@@ -105,12 +104,6 @@
             Constants.EXTRA_RESULT_RECEIVER,
             ResultReceiver::class.java
         )
-
-        finalResponseReceiver = intent.getParcelableExtra(
-                Constants.EXTRA_FINAL_RESPONSE_RECEIVER,
-                ResultReceiver::class.java
-        )
-
         isReqForAllOptions = requestInfo?.isShowAllOptionsRequested ?: false
 
         val cancellationRequest = getCancelUiRequest(intent)
@@ -206,7 +199,7 @@
     }
 
     fun onCancel(cancelCode: Int) {
-        sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver, finalResponseReceiver)
+        sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver)
     }
 
     fun onOptionSelected(
@@ -226,9 +219,6 @@
         val resultDataBundle = Bundle()
         UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultDataBundle)
 
-        resultDataBundle.putParcelable(Constants.EXTRA_FINAL_RESPONSE_RECEIVER,
-                finalResponseReceiver)
-
         resultReceiver?.send(
             BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
             resultDataBundle
@@ -296,13 +286,10 @@
         fun sendCancellationCode(
             cancelCode: Int,
             requestToken: IBinder?,
-            resultReceiver: ResultReceiver?,
-            finalResponseReceiver: ResultReceiver?
+            resultReceiver: ResultReceiver?
         ) {
             if (requestToken != null && resultReceiver != null) {
                 val resultData = Bundle()
-                resultData.putParcelable(Constants.EXTRA_FINAL_RESPONSE_RECEIVER,
-                        finalResponseReceiver)
 
                 BaseDialogResult.addToBundle(BaseDialogResult(requestToken), resultData)
                 resultReceiver.send(cancelCode, resultData)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index ec0da09..a2f55cd 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -208,18 +208,13 @@
             android.credentials.selection.Constants.EXTRA_RESULT_RECEIVER,
             ResultReceiver::class.java
         )
-        val finalResponseResultReceiver = intent.getParcelableExtra(
-                android.credentials.selection.Constants.EXTRA_FINAL_RESPONSE_RECEIVER,
-                ResultReceiver::class.java
-        )
-
         val requestInfo = intent.extras?.getParcelable(
             RequestInfo.EXTRA_REQUEST_INFO,
             RequestInfo::class.java
         )
         CredentialManagerRepo.sendCancellationCode(
             BaseDialogResult.RESULT_CODE_DATA_PARSING_FAILURE,
-            requestInfo?.token, resultReceiver, finalResponseResultReceiver
+            requestInfo?.token, resultReceiver
         )
         this.finish()
     }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index 28c40479..7bc3241 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -18,6 +18,7 @@
 
 import android.app.Activity
 import android.hardware.biometrics.BiometricPrompt
+import android.hardware.biometrics.BiometricPrompt.AuthenticationResult
 import android.os.IBinder
 import android.text.TextUtils
 import android.util.Log
@@ -29,6 +30,9 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.lifecycle.ViewModel
+import com.android.credentialmanager.common.BiometricError
+import com.android.credentialmanager.common.BiometricFlowType
+import com.android.credentialmanager.common.BiometricPromptState
 import com.android.credentialmanager.common.BiometricResult
 import com.android.credentialmanager.common.BiometricState
 import com.android.credentialmanager.model.EntryInfo
@@ -39,6 +43,7 @@
 import com.android.credentialmanager.createflow.ActiveEntry
 import com.android.credentialmanager.createflow.CreateCredentialUiState
 import com.android.credentialmanager.createflow.CreateScreenState
+import com.android.credentialmanager.createflow.isBiometricFlow
 import com.android.credentialmanager.getflow.GetCredentialUiState
 import com.android.credentialmanager.getflow.GetScreenState
 import com.android.credentialmanager.logging.LifecycleEvent
@@ -124,13 +129,22 @@
             uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING)
             val entryIntent = entry.fillInIntent
             entryIntent?.putExtra(Constants.IS_AUTO_SELECTED_KEY, uiState.isAutoSelectFlow)
-            if (biometricState.biometricResult != null) {
+            if (biometricState.biometricResult != null || biometricState.biometricError != null) {
                 if (uiState.isAutoSelectFlow) {
                     Log.w(Constants.LOG_TAG, "Unexpected biometric result exists when " +
                             "autoSelect is preferred.")
                 }
-                entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_TYPE,
-                    biometricState.biometricResult.biometricAuthenticationResult.authenticationType)
+                // TODO(b/333445754) : Decide whether to propagate info on prompt launch
+                if (biometricState.biometricResult != null) {
+                    entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_RESULT,
+                        biometricState.biometricResult.biometricAuthenticationResult
+                            .authenticationType)
+                } else if (biometricState.biometricError != null){
+                    entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_CODE,
+                        biometricState.biometricError.errorCode)
+                    entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_MESSAGE,
+                        biometricState.biometricError.errorMessage)
+                }
             }
             val intentSenderRequest = IntentSenderRequest.Builder(pendingIntent)
                 .setFillInIntent(entryIntent).build()
@@ -215,7 +229,8 @@
     /**************************************************************************/
     fun getFlowOnEntrySelected(
         entry: EntryInfo,
-        authResult: BiometricPrompt.AuthenticationResult? = null
+        authResult: BiometricPrompt.AuthenticationResult? = null,
+        authError: BiometricError? = null,
     ) {
         Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
             ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
@@ -223,10 +238,11 @@
             uiState.copy(
                 selectedEntry = entry,
                 providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
-                biometricState = if (authResult == null) uiState.biometricState else uiState
+                biometricState = if (authResult == null && authError == null)
+                    uiState.biometricState else if (authResult != null) uiState
                     .biometricState.copy(biometricResult = BiometricResult(
-                            biometricAuthenticationResult = authResult)
-                )
+                            biometricAuthenticationResult = authResult)) else uiState
+                    .biometricState.copy(biometricError = authError)
             )
         } else {
             credManRepo.onOptionSelected(entry.providerId, entry.entryKey, entry.entrySubkey)
@@ -254,6 +270,15 @@
         )
     }
 
+    fun getFlowOnMoreOptionOnlySelected() {
+        Log.d(Constants.LOG_TAG, "More Option Only selected")
+        uiState = uiState.copy(
+                getCredentialUiState = uiState.getCredentialUiState?.copy(
+                        currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY
+                )
+        )
+    }
+
     fun getFlowOnMoreOptionOnSnackBarSelected(isNoAccount: Boolean) {
         Log.d(Constants.LOG_TAG, "More Option on snackBar selected")
         uiState = uiState.copy(
@@ -292,6 +317,14 @@
         )
     }
 
+    fun createFlowOnMoreOptionsOnlySelectedOnCreationSelection() {
+        uiState = uiState.copy(
+                createCredentialUiState = uiState.createCredentialUiState?.copy(
+                        currentScreenState = CreateScreenState.MORE_OPTIONS_SELECTION_ONLY,
+                )
+        )
+    }
+
     fun createFlowOnBackCreationSelectionButtonSelected() {
         uiState = uiState.copy(
             createCredentialUiState = uiState.createCredentialUiState?.copy(
@@ -301,10 +334,24 @@
     }
 
     fun createFlowOnEntrySelectedFromMoreOptionScreen(activeEntry: ActiveEntry) {
+        val isBiometricFlow = isBiometricFlow(activeEntry = activeEntry, isAutoSelectFlow = false)
+        if (isBiometricFlow) {
+            // This atomically ensures that the only edge case that *restarts* the biometric flow
+            // doesn't risk a configuration change bug on the more options page during create.
+            // Namely, it's atomic in that it happens only on a tap, and it is not possible to
+            // reproduce a tap and a rotation at the same time. However, even if it were, it would
+            // just be an alternate way to jump back into the biometric selection flow after this
+            // reset, and thus, the state machine is maintained.
+            onBiometricPromptStateChange(BiometricPromptState.INACTIVE)
+        }
         uiState = uiState.copy(
             createCredentialUiState = uiState.createCredentialUiState?.copy(
                 currentScreenState =
-                if (uiState.createCredentialUiState?.requestDisplayInfo?.userSetDefaultProviderIds
+                // An autoselect flow never makes it to the more options screen
+                if (isBiometricFlow) {
+                    CreateScreenState.BIOMETRIC_SELECTION
+                } else if (
+                    uiState.createCredentialUiState?.requestDisplayInfo?.userSetDefaultProviderIds
                         ?.contains(activeEntry.activeProvider.id) ?: true ||
                     !(uiState.createCredentialUiState?.foundCandidateFromUserDefaultProvider
                     ?: false) ||
@@ -330,7 +377,11 @@
         )
     }
 
-    fun createFlowOnEntrySelected(selectedEntry: EntryInfo) {
+    fun createFlowOnEntrySelected(
+        selectedEntry: EntryInfo,
+        authResult: AuthenticationResult? = null,
+        authError: BiometricError? = null,
+    ) {
         val providerId = selectedEntry.providerId
         val entryKey = selectedEntry.entryKey
         val entrySubkey = selectedEntry.entrySubkey
@@ -341,6 +392,11 @@
             uiState = uiState.copy(
                 selectedEntry = selectedEntry,
                 providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
+                biometricState = if (authResult == null && authError == null)
+                    uiState.biometricState else if (authResult != null) uiState
+                    .biometricState.copy(biometricResult = BiometricResult(
+                        biometricAuthenticationResult = authResult)) else uiState
+                    .biometricState.copy(biometricError = authError)
             )
         } else {
             credManRepo.onOptionSelected(
@@ -363,13 +419,48 @@
         }
     }
 
+    /**************************************************************************/
+    /*****                     Biometric Flow Callbacks                   *****/
+    /**************************************************************************/
+
+    /**
+     * This allows falling back from the biometric prompt screen to the normal get flow by applying
+     * a reset to all necessary states involved in the fallback.
+     */
+    fun fallbackFromBiometricToNormalFlow(biometricFlowType: BiometricFlowType) {
+        onBiometricPromptStateChange(BiometricPromptState.INACTIVE)
+        when (biometricFlowType) {
+            BiometricFlowType.GET -> getFlowOnBackToPrimarySelectionScreen()
+            BiometricFlowType.CREATE -> createFlowOnUseOnceSelected()
+        }
+    }
+
+    /**
+     * This method can be used to change the [BiometricPromptState] according to the necessity.
+     * For example, if resetting, one might use [BiometricPromptState.INACTIVE], but if the flow
+     * has just launched, to avoid configuration errors, one can use
+     * [BiometricPromptState.PENDING].
+     */
+    fun onBiometricPromptStateChange(biometricPromptState: BiometricPromptState) {
+        uiState = uiState.copy(
+            biometricState = uiState.biometricState.copy(
+                biometricStatus = biometricPromptState
+            )
+        )
+    }
+
+    /**
+     * This returns the present biometric state.
+     */
+    fun getBiometricPromptState(): BiometricPromptState =
+        uiState.biometricState.biometricStatus
+
+    /**************************************************************************/
+    /*****                     Misc. Callbacks/Logs                       *****/
+    /**************************************************************************/
+
     @Composable
     fun logUiEvent(uiEventEnum: UiEventEnum) {
         this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo?.packageName)
     }
-
-    companion object {
-        // TODO(b/326243754) : Replace/remove once all failure flows added in
-        const val TEMPORARY_FAILURE_CODE = Integer.MIN_VALUE
-    }
 }
\ 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 fd6fc6a..c477f30 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -52,10 +52,12 @@
 import androidx.credentials.provider.RemoteEntry
 import org.json.JSONObject
 import android.credentials.flags.Flags
+import com.android.credentialmanager.createflow.isBiometricFlow
+import com.android.credentialmanager.createflow.isFlowAutoSelectable
 import com.android.credentialmanager.getflow.TopBrandingContent
+import com.android.credentialmanager.ktx.retrieveEntryBiometricRequest
 import java.time.Instant
 
-
 fun getAppLabel(
     pm: PackageManager,
     appPackageName: String
@@ -237,6 +239,9 @@
 
 class CreateFlowUtils {
     companion object {
+
+        private const val CREATE_ENTRY_PREFIX = "androidx.credentials.provider.createEntry."
+
         /**
          * Note: caller required handle empty list due to parsing error.
          */
@@ -417,12 +422,26 @@
                 }
             }
             val defaultProvider = defaultProviderPreferredByApp ?: defaultProviderSetByUser
+            val sortedCreateOptionsPairs = createOptionsPairs.sortedWith(
+                compareByDescending { it.first.lastUsedTime }
+            )
+            val activeEntry = toActiveEntry(
+                defaultProvider = defaultProvider,
+                sortedCreateOptionsPairs = sortedCreateOptionsPairs,
+                remoteEntry = remoteEntry,
+                remoteEntryProvider = remoteEntryProvider,
+            )
+            val isBiometricFlow = if (activeEntry == null) false else isBiometricFlow(activeEntry,
+                isFlowAutoSelectable(
+                    requestDisplayInfo = requestDisplayInfo,
+                    activeEntry = activeEntry,
+                    sortedCreateOptionsPairs = sortedCreateOptionsPairs
+                )
+            )
             val initialScreenState = toCreateScreenState(
                 createOptionSize = createOptionsPairs.size,
                 remoteEntry = remoteEntry,
-            )
-            val sortedCreateOptionsPairs = createOptionsPairs.sortedWith(
-                compareByDescending { it.first.lastUsedTime }
+                isBiometricFlow = isBiometricFlow
             )
             return CreateCredentialUiState(
                 enabledProviders = enabledProviders,
@@ -430,12 +449,7 @@
                 currentScreenState = initialScreenState,
                 requestDisplayInfo = requestDisplayInfo,
                 sortedCreateOptionsPairs = sortedCreateOptionsPairs,
-                activeEntry = toActiveEntry(
-                    defaultProvider = defaultProvider,
-                    sortedCreateOptionsPairs = sortedCreateOptionsPairs,
-                    remoteEntry = remoteEntry,
-                    remoteEntryProvider = remoteEntryProvider,
-                ),
+                activeEntry = activeEntry,
                 remoteEntry = remoteEntry,
                 foundCandidateFromUserDefaultProvider = defaultProviderSetByUser != null,
             )
@@ -444,9 +458,12 @@
         fun toCreateScreenState(
             createOptionSize: Int,
             remoteEntry: RemoteInfo?,
+            isBiometricFlow: Boolean,
         ): CreateScreenState {
             return if (createOptionSize == 0 && remoteEntry != null) {
                 CreateScreenState.EXTERNAL_ONLY_SELECTION
+            } else if (isBiometricFlow) {
+                CreateScreenState.BIOMETRIC_SELECTION
             } else {
                 CreateScreenState.CREATION_OPTION_SELECTION
             }
@@ -503,8 +520,8 @@
                         it.hasHint("androidx.credentials.provider.createEntry.SLICE_HINT_AUTO_" +
                             "SELECT_ALLOWED")
                     }?.text == "true",
-                    // TODO(b/326243754) : Handle this when the create flow is added; for now the
-                    // create flow does not support biometric values
+                    biometricRequest = retrieveEntryBiometricRequest(it,
+                        CREATE_ENTRY_PREFIX),
                 )
                 )
             }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index 1253ce3..50ebdd5 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -32,6 +32,7 @@
 import android.os.Bundle
 import android.os.CancellationSignal
 import android.os.OutcomeReceiver
+import android.os.ResultReceiver
 import android.service.autofill.AutofillService
 import android.service.autofill.Dataset
 import android.service.autofill.Field
@@ -46,9 +47,9 @@
 import android.service.credentials.CredentialProviderService
 import android.util.Log
 import android.content.Intent
+import android.os.IBinder
 import android.view.autofill.AutofillId
 import android.view.autofill.AutofillManager
-import android.view.autofill.IAutoFillManagerClient
 import android.widget.RemoteViews
 import android.widget.inline.InlinePresentationSpec
 import androidx.autofill.inline.v1.InlineSuggestionUi
@@ -94,7 +95,7 @@
             request: FillRequest,
             cancellationSignal: CancellationSignal,
             callback: FillCallback,
-            autofillCallback: IAutoFillManagerClient
+            autofillCallback: IBinder
     ) {
         val context = request.fillContexts
         val structure = context[context.size - 1].structure
@@ -109,17 +110,19 @@
         }
         val sessionId = clientState.getInt(SESSION_ID_KEY)
         val requestId = clientState.getInt(REQUEST_ID_KEY)
+        val resultReceiver = clientState.getParcelable(
+                CredentialManager.EXTRA_AUTOFILL_RESULT_RECEIVER, ResultReceiver::class.java)
         Log.i(TAG, "Autofill sessionId: $sessionId, autofill requestId: $requestId")
-        if (sessionId == 0 || requestId == 0) {
-            Log.i(TAG, "Session Id or request Id not found")
-            callback.onFailure("Session Id or request Id not found")
+        if (sessionId == 0 || requestId == 0 || resultReceiver == null) {
+            Log.i(TAG, "Session Id or request Id or resultReceiver not found")
+            callback.onFailure("Session Id or request Id or resultReceiver not found")
             return
         }
 
         val responseClientState = Bundle()
         responseClientState.putBoolean(WEBVIEW_REQUESTED_CREDENTIAL_KEY, false)
         val getCredRequest: GetCredentialRequest? = getCredManRequest(structure, sessionId,
-                requestId, responseClientState)
+                requestId, resultReceiver, responseClientState)
         // TODO(b/324635774): Use callback for validating. If the request is coming
         // directly from the view, there should be a corresponding callback, otherwise
         // we should fail fast,
@@ -157,7 +160,7 @@
                 CancellationSignal(),
                 Executors.newSingleThreadExecutor(),
                 outcome,
-                autofillCallback.asBinder()
+                autofillCallback
         )
     }
 
@@ -531,6 +534,7 @@
             structure: AssistStructure,
             sessionId: Int,
             requestId: Int,
+            resultReceiver: ResultReceiver,
             responseClientState: Bundle
     ): GetCredentialRequest? {
         val credentialOptions: MutableList<CredentialOption> = mutableListOf()
@@ -540,6 +544,9 @@
             val dataBundle = Bundle()
             dataBundle.putInt(SESSION_ID_KEY, sessionId)
             dataBundle.putInt(REQUEST_ID_KEY, requestId)
+            dataBundle.putParcelable(CredentialManager.EXTRA_AUTOFILL_RESULT_RECEIVER,
+                    resultReceiver)
+
             return GetCredentialRequest.Builder(dataBundle)
                     .setCredentialOptions(credentialOptions)
                     .build()
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricFlowType.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricFlowType.kt
new file mode 100644
index 0000000..263cfd5
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricFlowType.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.common
+
+enum class BiometricFlowType {
+    GET,
+    CREATE
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
index a30956e..0d19a45 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
@@ -17,20 +17,25 @@
 package com.android.credentialmanager.common
 
 import android.content.Context
+import android.content.DialogInterface
 import android.graphics.Bitmap
 import android.hardware.biometrics.BiometricManager
+import android.hardware.biometrics.BiometricManager.Authenticators
 import android.hardware.biometrics.BiometricPrompt
+import android.hardware.biometrics.PromptContentViewWithMoreOptionsButton
 import android.os.CancellationSignal
 import android.util.Log
 import androidx.core.content.ContextCompat.getMainExecutor
 import androidx.core.graphics.drawable.toBitmap
 import com.android.credentialmanager.R
 import com.android.credentialmanager.createflow.EnabledProviderInfo
+import com.android.credentialmanager.createflow.getCreateTitleResCode
 import com.android.credentialmanager.getflow.ProviderDisplayInfo
 import com.android.credentialmanager.getflow.RequestDisplayInfo
 import com.android.credentialmanager.getflow.generateDisplayTitleTextResCode
 import com.android.credentialmanager.model.BiometricRequestInfo
 import com.android.credentialmanager.model.EntryInfo
+import com.android.credentialmanager.model.creation.CreateOptionInfo
 import com.android.credentialmanager.model.get.CredentialEntryInfo
 import com.android.credentialmanager.model.get.ProviderInfo
 import java.lang.Exception
@@ -39,15 +44,36 @@
  * Aggregates common display information used for the Biometric Flow.
  * Namely, this adds the ability to encapsulate the [providerIcon], the providers icon, the
  * [providerName], which represents the name of the provider, the [displayTitleText] which is
- * the large text displaying the flow in progress, and the [descriptionAboveBiometricButton], which
- * describes details of where the credential is being saved, and how.
+ * the large text displaying the flow in progress, and the [descriptionForCredential], which
+ * describes details of where the credential is being saved, and how. [displaySubtitleText] is only expected
+ * to be used by the 'create' flow, optionally, and describes the saved name of the creating entity.
+ * (E.g. assume a hypothetical provider 'Any Provider' for *passkey* flows with [email protected] and
+ * name 'Your', and an rp called 'The App'):
+ *
+ * 'get' flow:
+ *     - [providerIcon] and [providerName] = 'Any Provider' (and it's icon)
+ *     - [displayTitleText] = "Use your saved passkey for The App?"
+ *     - [descriptionForCredential] = "Sign in to The App with your saved passkey for
+ *     [email protected]"
+ *
+ * 'create' flow:
+ *     - [providerIcon] and [providerName] = 'Any Provider' (and it's icon)
+ *     - [displayTitleText] = "Create passkey to sign in to Any Provider?"
+ *     - [subtitle] = "Your"
+ *     - [descriptionForCredential] = "You can use your passkey on other devices. It is saved to
+ *  *     Google Password Manager for [email protected]."
+ * ).
+ *
+ * The above are examples; the credential type can change depending on scenario.
+ * // TODO(b/333445112) : Finalize once all the strings and create flow is iterated to completion
  */
 data class BiometricDisplayInfo(
     val providerIcon: Bitmap,
     val providerName: String,
     val displayTitleText: String,
-    val descriptionAboveBiometricButton: String,
+    val descriptionForCredential: String?,
     val biometricRequestInfo: BiometricRequestInfo,
+    val displaySubtitleText: CharSequence? = null,
 )
 
 /**
@@ -58,8 +84,7 @@
 data class BiometricState(
     val biometricResult: BiometricResult? = null,
     val biometricError: BiometricError? = null,
-    val biometricHelp: BiometricHelp? = null,
-    val biometricAcquireInfo: Int? = null,
+    val biometricStatus: BiometricPromptState = BiometricPromptState.INACTIVE
 )
 
 /**
@@ -67,7 +92,7 @@
  * so that should this object exist, the result will be retrievable.
  */
 data class BiometricResult(
-    val biometricAuthenticationResult: BiometricPrompt.AuthenticationResult
+    val biometricAuthenticationResult: BiometricPrompt.AuthenticationResult,
 )
 
 /**
@@ -75,156 +100,262 @@
  */
 data class BiometricError(
     val errorCode: Int,
-    val errString: CharSequence? = null
+    val errorMessage: CharSequence? = null
 )
 
 /**
- * Encapsulates the help callback results to easily manage biometric help states in the flow.
- * To specify, this allows us to parse the onAuthenticationHelp method in the [BiometricPrompt].
+ * This is the entry point to start the integrated biometric prompt for 'get' flows. It captures
+ * information specific to the get flow, along with required shared callbacks and more general
+ * info across both flows, such as the tapped [EntryInfo] or [sendDataToProvider].
  */
-data class BiometricHelp(
-    val helpCode: Int,
-    var helpString: CharSequence? = null
-)
+fun runBiometricFlowForGet(
+    biometricEntry: EntryInfo,
+    context: Context,
+    openMoreOptionsPage: () -> Unit,
+    sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult?, BiometricError?) -> Unit,
+    onCancelFlowAndFinish: () -> Unit,
+    onIllegalStateAndFinish: (String) -> Unit,
+    getBiometricPromptState: () -> BiometricPromptState,
+    onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+    onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+    getRequestDisplayInfo: RequestDisplayInfo? = null,
+    getProviderInfoList: List<ProviderInfo>? = null,
+    getProviderDisplayInfo: ProviderDisplayInfo? = null,
+) {
+    if (getBiometricPromptState() != BiometricPromptState.INACTIVE) {
+        // Screen is already up, do not re-launch
+        return
+    }
+    onBiometricPromptStateChange(BiometricPromptState.PENDING)
+    val biometricDisplayInfo = validateAndRetrieveBiometricGetDisplayInfo(
+        getRequestDisplayInfo,
+        getProviderInfoList,
+        getProviderDisplayInfo,
+        context, biometricEntry
+    )
+
+    if (biometricDisplayInfo == null) {
+        onBiometricFailureFallback(BiometricFlowType.GET)
+        return
+    }
+
+    val callback: BiometricPrompt.AuthenticationCallback =
+        setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
+            onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange)
+
+    Log.d(TAG, "The BiometricPrompt API call begins.")
+    runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage,
+        onBiometricFailureFallback, BiometricFlowType.GET, onCancelFlowAndFinish)
+}
+
+/**
+ * This is the entry point to start the integrated biometric prompt for 'create' flows. It captures
+ * information specific to the create flow, along with required shared callbacks and more general
+ * info across both flows, such as the tapped [EntryInfo] or [sendDataToProvider].
+ */
+fun runBiometricFlowForCreate(
+    biometricEntry: EntryInfo,
+    context: Context,
+    openMoreOptionsPage: () -> Unit,
+    sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult?, BiometricError?) -> Unit,
+    onCancelFlowAndFinish: () -> Unit,
+    onIllegalStateAndFinish: (String) -> Unit,
+    getBiometricPromptState: () -> BiometricPromptState,
+    onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+    onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+    createRequestDisplayInfo: com.android.credentialmanager.createflow
+    .RequestDisplayInfo? = null,
+    createProviderInfo: EnabledProviderInfo? = null,
+) {
+    if (getBiometricPromptState() != BiometricPromptState.INACTIVE) {
+        // Screen is already up, do not re-launch
+        return
+    }
+    onBiometricPromptStateChange(BiometricPromptState.PENDING)
+    val biometricDisplayInfo = validateAndRetrieveBiometricCreateDisplayInfo(
+        createRequestDisplayInfo,
+        createProviderInfo,
+        context, biometricEntry
+    )
+
+    if (biometricDisplayInfo == null) {
+        onBiometricFailureFallback(BiometricFlowType.CREATE)
+        return
+    }
+
+    val callback: BiometricPrompt.AuthenticationCallback =
+        setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
+            onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange)
+
+    Log.d(TAG, "The BiometricPrompt API call begins.")
+    runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage,
+        onBiometricFailureFallback, BiometricFlowType.CREATE, onCancelFlowAndFinish)
+}
 
 /**
  * This will handle the logic for integrating credential manager with the biometric prompt for the
  * single account biometric experience. This simultaneously handles both the get and create flows,
  * by retrieving all the data from credential manager, and properly parsing that data into the
- * biometric prompt.
+ * biometric prompt. It will fallback in cases where the biometric api cannot be called, or when
+ * only device credentials are requested.
  */
-fun runBiometricFlow(
-    biometricEntry: EntryInfo,
+private fun runBiometricFlow(
     context: Context,
+    biometricDisplayInfo: BiometricDisplayInfo,
+    callback: BiometricPrompt.AuthenticationCallback,
     openMoreOptionsPage: () -> Unit,
-    sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult) -> Unit,
-    onCancelFlowAndFinish: () -> Unit,
-    onIllegalStateAndFinish: (String) -> Unit,
-    getRequestDisplayInfo: RequestDisplayInfo? = null,
-    getProviderInfoList: List<ProviderInfo>? = null,
-    getProviderDisplayInfo: ProviderDisplayInfo? = null,
-    onBiometricFailureFallback: () -> Unit,
-    createRequestDisplayInfo: com.android.credentialmanager.createflow
-    .RequestDisplayInfo? = null,
-    createProviderInfo: EnabledProviderInfo? = null,
+    onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+    biometricFlowType: BiometricFlowType,
+    onCancelFlowAndFinish: () -> Unit
 ) {
-    var biometricDisplayInfo: BiometricDisplayInfo? = null
-    if (getRequestDisplayInfo != null) {
-        biometricDisplayInfo = validateAndRetrieveBiometricGetDisplayInfo(getRequestDisplayInfo,
-            getProviderInfoList,
-            getProviderDisplayInfo,
-            context, biometricEntry)
-    } else if (createRequestDisplayInfo != null) {
-        // TODO(b/326243754) : Create Flow to be implemented in follow up
-        biometricDisplayInfo = validateBiometricCreateFlow(
-            createRequestDisplayInfo,
-            createProviderInfo
-        )
-    }
-
-    if (biometricDisplayInfo == null) {
-        onBiometricFailureFallback()
-        return
-    }
-
-    val biometricPrompt = setupBiometricPrompt(context, biometricDisplayInfo, openMoreOptionsPage,
-        biometricDisplayInfo.biometricRequestInfo.allowedAuthenticators)
-
-    val callback: BiometricPrompt.AuthenticationCallback =
-        setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
-            onCancelFlowAndFinish, onIllegalStateAndFinish)
-
-    val cancellationSignal = CancellationSignal()
-    cancellationSignal.setOnCancelListener {
-        Log.d(TAG, "Your cancellation signal was called.")
-        // TODO(b/326243754) : Migrate towards passing along the developer cancellation signal
-        // or validate the necessity for this
-    }
-
-    val executor = getMainExecutor(context)
-
     try {
-        biometricPrompt.authenticate(cancellationSignal, executor, callback)
+        if (!canCallBiometricPrompt(biometricDisplayInfo, context)) {
+            onBiometricFailureFallback(biometricFlowType)
+            return
+        }
+
+        val biometricPrompt = setupBiometricPrompt(context, biometricDisplayInfo,
+            openMoreOptionsPage, biometricDisplayInfo.biometricRequestInfo, onCancelFlowAndFinish)
+
+        val cancellationSignal = CancellationSignal()
+        cancellationSignal.setOnCancelListener {
+            Log.d(TAG, "Your cancellation signal was called.")
+            // TODO(b/333445112) : Migrate towards passing along the developer cancellation signal
+            // or validate the necessity for this
+        }
+
+        val executor = getMainExecutor(context)
+
+        val cryptoOpId = getCryptoOpId(biometricDisplayInfo)
+        if (cryptoOpId != null) {
+            biometricPrompt.authenticate(
+                BiometricPrompt.CryptoObject(cryptoOpId.toLong()),
+                cancellationSignal, executor, callback)
+        } else {
+            biometricPrompt.authenticate(cancellationSignal, executor, callback)
+        }
     } catch (e: IllegalArgumentException) {
         Log.w(TAG, "Calling the biometric prompt API failed with: /n${e.localizedMessage}\n")
-        onBiometricFailureFallback()
+        onBiometricFailureFallback(biometricFlowType)
     }
 }
 
+private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Int? {
+    return biometricDisplayInfo.biometricRequestInfo.opId
+}
+
+/**
+ * Determines if, given the allowed authenticators, the flow should fallback early. This has
+ * consistency because for biometrics to exist, **device credentials must exist**. Thus, fallbacks
+ * occur if *only* device credentials are available, to avoid going right into the PIN screen.
+ * Note that if device credential is the only available modality but not requested, or if none
+ * of the requested modalities are available, we fallback to the normal flow to ensure a selector
+ * shows up.
+ * // TODO(b/334197980) : While we already fallback in cases the selector doesn't show, confirm
+ * // final plan.
+ */
+private fun canCallBiometricPrompt(
+    biometricDisplayInfo: BiometricDisplayInfo,
+    context: Context
+): Boolean {
+    val allowedAuthenticators = biometricDisplayInfo.biometricRequestInfo.allowedAuthenticators
+    if (allowedAuthenticators == BiometricManager.Authenticators.DEVICE_CREDENTIAL) {
+        return false
+    }
+
+    val biometricManager = context.getSystemService(Context.BIOMETRIC_SERVICE) as BiometricManager
+
+    if (biometricManager.canAuthenticate(allowedAuthenticators) !=
+        BiometricManager.BIOMETRIC_SUCCESS) {
+        return false
+    }
+
+    if (ifOnlySupportsAtMostDeviceCredentials(biometricManager)) return false
+
+    return true
+}
+
+private fun ifOnlySupportsAtMostDeviceCredentials(biometricManager: BiometricManager): Boolean {
+    if (biometricManager.canAuthenticate(Authenticators.BIOMETRIC_WEAK) !=
+        BiometricManager.BIOMETRIC_SUCCESS &&
+        biometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG) !=
+        BiometricManager.BIOMETRIC_SUCCESS
+    ) {
+        return true
+    }
+    return false
+}
+
+private fun containsBiometricAuthenticatorWithDeviceCredentials(
+    allowedAuthenticators: Int
+): Boolean {
+    val allowedAuthContainsDeviceCredential = (allowedAuthenticators ==
+            Authenticators.BIOMETRIC_WEAK or Authenticators.DEVICE_CREDENTIAL) ||
+            (allowedAuthenticators ==
+                    Authenticators.BIOMETRIC_STRONG or Authenticators.DEVICE_CREDENTIAL)
+    return allowedAuthContainsDeviceCredential
+}
+
 /**
  * Sets up the biometric prompt with the UI specific bits.
- * // TODO(b/326243754) : Pass in opId once dependency is confirmed via CryptoObject
- * // TODO(b/326243754) : Given fallbacks aren't allowed, for now we validate that device creds
- * // are NOT allowed to be passed in to avoid throwing an error. Later, however, once target
- * // alignments occur, we should add the bit back properly.
+ * // TODO(b/333445112) : Pass in opId once dependency is confirmed via CryptoObject
  */
 private fun setupBiometricPrompt(
     context: Context,
     biometricDisplayInfo: BiometricDisplayInfo,
     openMoreOptionsPage: () -> Unit,
-    requestAllowedAuthenticators: Int,
+    biometricRequestInfo: BiometricRequestInfo,
+    onCancelFlowAndFinish: () -> Unit
 ): BiometricPrompt {
-    val finalAuthenticators = removeDeviceCredential(requestAllowedAuthenticators)
+    val listener =
+        DialogInterface.OnClickListener { _: DialogInterface?, _: Int -> openMoreOptionsPage() }
 
-    val biometricPrompt = BiometricPrompt.Builder(context)
+    val promptContentViewBuilder = PromptContentViewWithMoreOptionsButton.Builder()
+        .setMoreOptionsButtonListener(context.mainExecutor, listener)
+    biometricDisplayInfo.descriptionForCredential?.let {
+        promptContentViewBuilder.setDescription(it) }
+
+    val biometricPromptBuilder = BiometricPrompt.Builder(context)
         .setTitle(biometricDisplayInfo.displayTitleText)
-        // TODO(b/326243754) : Migrate to using new methods recently aligned upon
-        .setNegativeButton(context.getString(R.string
-                .dropdown_presentation_more_sign_in_options_text),
-            getMainExecutor(context)) { _, _ ->
-            openMoreOptionsPage()
-        }
-        .setAllowedAuthenticators(finalAuthenticators)
+        .setAllowedAuthenticators(biometricRequestInfo.allowedAuthenticators)
         .setConfirmationRequired(true)
         .setLogoBitmap(biometricDisplayInfo.providerIcon)
         .setLogoDescription(biometricDisplayInfo.providerName)
-        .setDescription(biometricDisplayInfo.descriptionAboveBiometricButton)
-        .build()
+        .setContentView(promptContentViewBuilder.build())
 
-    return biometricPrompt
-}
-
-// TODO(b/326243754) : Remove after larger level alignments made on fallback negative button
-// For the time being, we do not support the pin fallback until UX is decided.
-private fun removeDeviceCredential(requestAllowedAuthenticators: Int): Int {
-    var finalAuthenticators = requestAllowedAuthenticators
-
-    if (requestAllowedAuthenticators == (BiometricManager.Authenticators.DEVICE_CREDENTIAL or
-                BiometricManager.Authenticators.BIOMETRIC_WEAK)) {
-        finalAuthenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK
+    if (!containsBiometricAuthenticatorWithDeviceCredentials(biometricDisplayInfo
+            .biometricRequestInfo.allowedAuthenticators)) {
+        biometricPromptBuilder.setNegativeButton(context.getString(R.string.string_cancel),
+            getMainExecutor(context)
+        ) { _: DialogInterface?, _: Int -> onCancelFlowAndFinish() }
     }
 
-    if (requestAllowedAuthenticators == (BiometricManager.Authenticators.DEVICE_CREDENTIAL or
-                BiometricManager.Authenticators.BIOMETRIC_STRONG)) {
-        finalAuthenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK
-    }
+    biometricDisplayInfo.displaySubtitleText?.let { biometricPromptBuilder.setSubtitle(it) }
 
-    if (requestAllowedAuthenticators == (BiometricManager.Authenticators.DEVICE_CREDENTIAL)) {
-        finalAuthenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK
-    }
-
-    return finalAuthenticators
+    return biometricPromptBuilder.build()
 }
 
 /**
  * Sets up the biometric authentication callback.
  */
 private fun setupBiometricAuthenticationCallback(
-    sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult) -> Unit,
+    sendDataToProvider: (EntryInfo, BiometricPrompt.AuthenticationResult?, BiometricError?) -> Unit,
     selectedEntry: EntryInfo,
     onCancelFlowAndFinish: () -> Unit,
     onIllegalStateAndFinish: (String) -> Unit,
+    onBiometricPromptStateChange: (BiometricPromptState) -> Unit
 ): BiometricPrompt.AuthenticationCallback {
     val callback: BiometricPrompt.AuthenticationCallback =
         object : BiometricPrompt.AuthenticationCallback() {
-            // TODO(b/326243754) : Validate remaining callbacks
+            // TODO(b/333445772) : Validate remaining callbacks
             override fun onAuthenticationSucceeded(
                 authResult: BiometricPrompt.AuthenticationResult?
             ) {
                 super.onAuthenticationSucceeded(authResult)
                 try {
                     if (authResult != null) {
-                        sendDataToProvider(selectedEntry, authResult)
+                        onBiometricPromptStateChange(BiometricPromptState.COMPLETE)
+                        sendDataToProvider(selectedEntry, authResult, /*authError=*/null)
                     } else {
                         onIllegalStateAndFinish("The biometric flow succeeded but unexpectedly " +
                                 "returned a null value.")
@@ -238,26 +369,26 @@
             override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence?) {
                 super.onAuthenticationHelp(helpCode, helpString)
                 Log.d(TAG, "Authentication help discovered: $helpCode and $helpString")
-                // TODO(b/326243754) : Decide on strategy with provider (a simple log probably
-                // suffices here)
             }
 
             override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
                 super.onAuthenticationError(errorCode, errString)
                 Log.d(TAG, "Authentication error-ed out: $errorCode and $errString")
+                onBiometricPromptStateChange(BiometricPromptState.COMPLETE)
                 if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED) {
                     // Note that because the biometric prompt is imbued directly
                     // into the selector, parity applies to the selector's cancellation instead
                     // of the provider's biometric prompt cancellation.
                     onCancelFlowAndFinish()
+                } else {
+                    sendDataToProvider(selectedEntry, /*authResult=*/null, /*authError=*/
+                        BiometricError(errorCode, errString))
                 }
-                // TODO(b/326243754) : Propagate to provider
             }
 
             override fun onAuthenticationFailed() {
                 super.onAuthenticationFailed()
                 Log.d(TAG, "Authentication failed.")
-                // TODO(b/326243754) : Propagate to provider
             }
         }
     return callback
@@ -283,7 +414,7 @@
     if (getRequestDisplayInfo != null && getProviderInfoList != null &&
         getProviderDisplayInfo != null) {
         if (selectedEntry !is CredentialEntryInfo) { return null }
-        return getBiometricDisplayValues(getProviderInfoList,
+        return retrieveBiometricGetDisplayValues(getProviderInfoList,
             context, getRequestDisplayInfo, selectedEntry)
     }
     return null
@@ -292,16 +423,19 @@
 /**
  * Creates the [BiometricDisplayInfo] for create flows, and early handles conditional
  * checking between the two. The reason for this method matches the logic for the
- * [validateBiometricGetFlow] with the only difference being that this is for the create flow.
+ * [validateAndRetrieveBiometricGetDisplayInfo] with the only difference being that this is for
+ * the create flow.
  */
-private fun validateBiometricCreateFlow(
+private fun validateAndRetrieveBiometricCreateDisplayInfo(
     createRequestDisplayInfo: com.android.credentialmanager.createflow.RequestDisplayInfo?,
     createProviderInfo: EnabledProviderInfo?,
+    context: Context,
+    selectedEntry: EntryInfo,
 ): BiometricDisplayInfo? {
     if (createRequestDisplayInfo != null && createProviderInfo != null) {
-    } else if (createRequestDisplayInfo != null && createProviderInfo != null) {
-        // TODO(b/326243754) : Create Flow to be implemented in follow up
-        return createFlowDisplayValues()
+        if (selectedEntry !is CreateOptionInfo) { return null }
+        return retrieveBiometricCreateDisplayValues(createRequestDisplayInfo, createProviderInfo,
+            context, selectedEntry)
     }
     return null
 }
@@ -312,16 +446,16 @@
  * to the original selector. Note that these redundant checks are just failsafe; the original
  * flow should never reach here with invalid params.
  */
-private fun getBiometricDisplayValues(
+private fun retrieveBiometricGetDisplayValues(
     getProviderInfoList: List<ProviderInfo>,
     context: Context,
     getRequestDisplayInfo: RequestDisplayInfo,
     selectedEntry: CredentialEntryInfo,
 ): BiometricDisplayInfo? {
-    var icon: Bitmap? = null
-    var providerName: String? = null
-    var displayTitleText: String? = null
-    var descriptionText: String? = null
+    val icon: Bitmap?
+    val providerName: String?
+    val displayTitleText: String?
+    val descriptionText: String?
     val primaryAccountsProviderInfo = retrievePrimaryAccountProviderInfo(selectedEntry.providerId,
         getProviderInfoList)
     icon = primaryAccountsProviderInfo?.icon?.toBitmap()
@@ -336,27 +470,51 @@
     }
     val singleEntryType = selectedEntry.credentialType
     val username = selectedEntry.userName
+
+    // TODO(b/330396140) : Finalize localization and parsing for specific sign in option flows
+    //  (fingerprint, face, etc...))
     displayTitleText = context.getString(
         generateDisplayTitleTextResCode(singleEntryType),
         getRequestDisplayInfo.appName
     )
+
     descriptionText = context.getString(
-        R.string.get_dialog_title_single_tap_for,
+        R.string.get_dialog_description_single_tap,
         getRequestDisplayInfo.appName,
         username
     )
+
     return BiometricDisplayInfo(providerIcon = icon, providerName = providerName,
-        displayTitleText = displayTitleText, descriptionAboveBiometricButton = descriptionText,
+        displayTitleText = displayTitleText, descriptionForCredential = descriptionText,
         biometricRequestInfo = selectedEntry.biometricRequest as BiometricRequestInfo)
 }
 
 /**
- * Handles the biometric sign in via the 'create credentials' flow, or early validates this flow
- * needs to fallback.
+ * Handles the biometric sign in via the create credentials flow. Stricter in the get flow in that
+ * if this is called, a result is guaranteed. Specifically, this is guaranteed to return a non-null
+ * value unlike the get counterpart.
  */
-private fun createFlowDisplayValues(): BiometricDisplayInfo? {
-    // TODO(b/326243754) : Create Flow to be implemented in follow up
-    return null
+private fun retrieveBiometricCreateDisplayValues(
+    createRequestDisplayInfo: com.android.credentialmanager.createflow.RequestDisplayInfo,
+    createProviderInfo: EnabledProviderInfo,
+    context: Context,
+    selectedEntry: CreateOptionInfo,
+): BiometricDisplayInfo {
+    val icon: Bitmap?
+    val providerName: String?
+    val displayTitleText: String?
+    icon = createProviderInfo.icon.toBitmap()
+    providerName = createProviderInfo.displayName
+    displayTitleText = context.getString(
+        getCreateTitleResCode(createRequestDisplayInfo),
+        createRequestDisplayInfo.appName
+    )
+
+    // TODO(b/330396140) : If footerDescription is null, determine if we need to fallback
+    return BiometricDisplayInfo(providerIcon = icon, providerName = providerName,
+        displayTitleText = displayTitleText, descriptionForCredential = selectedEntry
+            .footerDescription, biometricRequestInfo = selectedEntry.biometricRequest
+                as BiometricRequestInfo, displaySubtitleText = createRequestDisplayInfo.title)
 }
 
 /**
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
new file mode 100644
index 0000000..e1aa041
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.common
+
+enum class BiometricPromptState {
+    /** The biometric prompt hasn't been activated. */
+    INACTIVE,
+    /** The biometric prompt is active but data hasn't been returned yet. */
+    PENDING,
+    /** The biometric prompt has closed and returned data we then send to the provider activity. */
+    COMPLETE
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
index 7e7a74f..3c80113 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
@@ -22,7 +22,9 @@
         const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS =
             "androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED"
         const val IS_AUTO_SELECTED_KEY = "IS_AUTO_SELECTED"
-        const val BIOMETRIC_AUTH_TYPE = "BIOMETRIC_AUTH_TYPE"
-        const val BIOMETRIC_AUTH_FAILURE = "BIOMETRIC_AUTH_FAILURE"
+        // TODO(b/333445772) : Qualify error codes fully for propagation
+        const val BIOMETRIC_AUTH_RESULT = "BIOMETRIC_AUTH_RESULT"
+        const val BIOMETRIC_AUTH_ERROR_CODE = "BIOMETRIC_AUTH_ERROR_CODE"
+        const val BIOMETRIC_AUTH_ERROR_MESSAGE = "BIOMETRIC_AUTH_ERROR_MESSAGE"
     }
 }
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 d13d86f..2c3c63b 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -28,7 +28,6 @@
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowBack
 import androidx.compose.material.icons.outlined.Lock
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -47,7 +46,6 @@
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.text.input.PasswordVisualTransformation
@@ -55,7 +53,6 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import com.android.compose.theme.LocalAndroidColorScheme
-import com.android.credentialmanager.R
 import com.android.credentialmanager.ui.theme.EntryShape
 import com.android.credentialmanager.ui.theme.Shapes
 
@@ -321,6 +318,8 @@
 fun MoreOptionTopAppBar(
     text: String,
     onNavigationIconClicked: () -> Unit,
+    navigationIcon: ImageVector,
+    navigationIconContentDescription: String,
     bottomPadding: Dp,
 ) {
     Row(
@@ -336,10 +335,8 @@
                     contentAlignment = Alignment.Center,
             ) {
                 Icon(
-                        imageVector = Icons.Filled.ArrowBack,
-                        contentDescription = stringResource(
-                                R.string.accessibility_back_arrow_button
-                        ),
+                        imageVector = navigationIcon,
+                        contentDescription = navigationIconContentDescription,
                         modifier = Modifier.size(24.dp).autoMirrored(),
                         tint = LocalAndroidColorScheme.current.onSurfaceVariant,
                 )
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index af78573..282a1b5 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -17,6 +17,7 @@
 package com.android.credentialmanager.createflow
 
 import android.credentials.flags.Flags.selectorUiImprovementsEnabled
+import android.hardware.biometrics.BiometricPrompt
 import android.text.TextUtils
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
@@ -26,18 +27,20 @@
 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.material3.Divider
 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.filled.ArrowBack
+import androidx.compose.material.icons.filled.Close
 import androidx.compose.material.icons.outlined.QrCodeScanner
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
@@ -45,10 +48,14 @@
 import com.android.compose.theme.LocalAndroidColorScheme
 import com.android.credentialmanager.CredentialSelectorViewModel
 import com.android.credentialmanager.R
+import com.android.credentialmanager.common.BiometricError
+import com.android.credentialmanager.common.BiometricFlowType
+import com.android.credentialmanager.common.BiometricPromptState
 import com.android.credentialmanager.model.EntryInfo
 import com.android.credentialmanager.model.CredentialType
 import com.android.credentialmanager.common.ProviderActivityState
 import com.android.credentialmanager.common.material.ModalBottomSheetDefaults
+import com.android.credentialmanager.common.runBiometricFlowForCreate
 import com.android.credentialmanager.common.ui.ActionButton
 import com.android.credentialmanager.common.ui.BodyMediumText
 import com.android.credentialmanager.common.ui.BodySmallText
@@ -95,6 +102,61 @@
                                 viewModel::createFlowOnMoreOptionsSelectedOnCreationSelection,
                                 onLog = { viewModel.logUiEvent(it) },
                         )
+                        CreateScreenState.BIOMETRIC_SELECTION ->
+                            BiometricSelectionPage(
+                                biometricEntry = createCredentialUiState
+                                    .activeEntry?.activeEntryInfo,
+                                onCancelFlowAndFinish = viewModel::onUserCancel,
+                                onIllegalScreenStateAndFinish = viewModel::onIllegalUiState,
+                                onMoreOptionSelected =
+                                viewModel::createFlowOnMoreOptionsOnlySelectedOnCreationSelection,
+                                requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                                enabledProviderInfo = createCredentialUiState
+                                        .activeEntry?.activeProvider!!,
+                                onBiometricEntrySelected =
+                                viewModel::createFlowOnEntrySelected,
+                                fallbackToOriginalFlow =
+                                viewModel::fallbackFromBiometricToNormalFlow,
+                                getBiometricPromptState =
+                                viewModel::getBiometricPromptState,
+                                onBiometricPromptStateChange =
+                                viewModel::onBiometricPromptStateChange
+                            )
+                        CreateScreenState.MORE_OPTIONS_SELECTION_ONLY -> MoreOptionsSelectionCard(
+                                requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                                enabledProviderList = createCredentialUiState.enabledProviders,
+                                disabledProviderList = createCredentialUiState.disabledProviders,
+                                sortedCreateOptionsPairs =
+                                createCredentialUiState.sortedCreateOptionsPairs,
+                                onBackCreationSelectionButtonSelected =
+                                viewModel::createFlowOnBackCreationSelectionButtonSelected,
+                                onOptionSelected =
+                                viewModel::createFlowOnEntrySelectedFromMoreOptionScreen,
+                                onDisabledProvidersSelected =
+                                viewModel::createFlowOnLaunchSettings,
+                                onRemoteEntrySelected = viewModel::createFlowOnEntrySelected,
+                                onLog = { viewModel.logUiEvent(it) },
+                                customTopAppBar = { MoreOptionTopAppBar(
+                                        text = stringResource(
+                                                R.string.save_credential_to_title,
+                                                when (createCredentialUiState.requestDisplayInfo
+                                                        .type) {
+                                                    CredentialType.PASSKEY ->
+                                                        stringResource(R.string.passkey)
+                                                    CredentialType.PASSWORD ->
+                                                        stringResource(R.string.password)
+                                                    CredentialType.UNKNOWN -> stringResource(
+                                                            R.string.sign_in_info)
+                                                }
+                                        ),
+                                        onNavigationIconClicked = viewModel::onUserCancel,
+                                        bottomPadding = 16.dp,
+                                        navigationIcon = Icons.Filled.Close,
+                                        navigationIconContentDescription = stringResource(
+                                                R.string.accessibility_close_button
+                                        )
+                                )}
+                        )
                         CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard(
                                 requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
                                 enabledProviderList = createCredentialUiState.enabledProviders,
@@ -182,22 +244,31 @@
     onDisabledProvidersSelected: () -> Unit,
     onRemoteEntrySelected: (EntryInfo) -> Unit,
     onLog: @Composable (UiEventEnum) -> Unit,
+    customTopAppBar: (@Composable() () -> Unit)? = null
 ) {
     SheetContainerCard(topAppBar = {
-        MoreOptionTopAppBar(
-            text = stringResource(
-                R.string.save_credential_to_title,
-                when (requestDisplayInfo.type) {
-                    CredentialType.PASSKEY ->
-                        stringResource(R.string.passkey)
-                    CredentialType.PASSWORD ->
-                        stringResource(R.string.password)
-                    CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
-                }
-            ),
-            onNavigationIconClicked = onBackCreationSelectionButtonSelected,
-            bottomPadding = 16.dp,
-        )
+        if (customTopAppBar != null) {
+            customTopAppBar()
+        } else {
+            MoreOptionTopAppBar(
+                    text = stringResource(
+                            R.string.save_credential_to_title,
+                            when (requestDisplayInfo.type) {
+                                CredentialType.PASSKEY ->
+                                    stringResource(R.string.passkey)
+                                CredentialType.PASSWORD ->
+                                    stringResource(R.string.password)
+                                CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
+                            }
+                    ),
+                    onNavigationIconClicked = onBackCreationSelectionButtonSelected,
+                    bottomPadding = 16.dp,
+                    navigationIcon = Icons.Filled.ArrowBack,
+                    navigationIconContentDescription = stringResource(
+                            R.string.accessibility_back_arrow_button
+                    )
+            )
+        }
     }) {
         // bottom padding already
         item {
@@ -313,20 +384,9 @@
         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
-                    )
-                }
+                text = stringResource(
+                    getCreateTitleResCode(requestDisplayInfo),
+                    requestDisplayInfo.appName)
             )
         }
         item { Divider(thickness = 24.dp, color = Color.Transparent) }
@@ -560,4 +620,40 @@
         iconImageVector = Icons.Outlined.QrCodeScanner,
         entryHeadlineText = stringResource(R.string.another_device),
     )
-}
\ No newline at end of file
+}
+
+@Composable
+internal fun BiometricSelectionPage(
+    biometricEntry: EntryInfo?,
+    onMoreOptionSelected: () -> Unit,
+    requestDisplayInfo: RequestDisplayInfo,
+    enabledProviderInfo: EnabledProviderInfo,
+    onBiometricEntrySelected: (
+        EntryInfo,
+        BiometricPrompt.AuthenticationResult?,
+        BiometricError?
+    ) -> Unit,
+    onCancelFlowAndFinish: () -> Unit,
+    onIllegalScreenStateAndFinish: (String) -> Unit,
+    fallbackToOriginalFlow: (BiometricFlowType) -> Unit,
+    getBiometricPromptState: () -> BiometricPromptState,
+    onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+) {
+    if (biometricEntry == null) {
+        fallbackToOriginalFlow(BiometricFlowType.CREATE)
+        return
+    }
+    runBiometricFlowForCreate(
+        biometricEntry = biometricEntry,
+        context = LocalContext.current,
+        openMoreOptionsPage = onMoreOptionSelected,
+        sendDataToProvider = onBiometricEntrySelected,
+        onCancelFlowAndFinish = onCancelFlowAndFinish,
+        getBiometricPromptState = getBiometricPromptState,
+        onBiometricPromptStateChange = onBiometricPromptStateChange,
+        createRequestDisplayInfo = requestDisplayInfo,
+        createProviderInfo = enabledProviderInfo,
+        onBiometricFailureFallback = fallbackToOriginalFlow,
+        onIllegalStateAndFinish = onIllegalScreenStateAndFinish,
+    )
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 617a981..130937c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -16,9 +16,11 @@
 
 package com.android.credentialmanager.createflow
 
+import android.credentials.flags.Flags.credmanBiometricApiEnabled
 import android.graphics.drawable.Drawable
-import com.android.credentialmanager.model.EntryInfo
+import com.android.credentialmanager.R
 import com.android.credentialmanager.model.CredentialType
+import com.android.credentialmanager.model.EntryInfo
 import com.android.credentialmanager.model.creation.CreateOptionInfo
 import com.android.credentialmanager.model.creation.RemoteInfo
 
@@ -33,14 +35,94 @@
     val foundCandidateFromUserDefaultProvider: Boolean,
 )
 
+/**
+ * Checks if this create flow is a biometric flow. Note that this flow differs slightly from the
+ * autoselect 'get' flow. Namely, given there can be multiple providers, rather than multiple
+ * accounts, the idea is that autoselect is ever only enabled for a single provider (or even, in
+ * that case, a single 'type' (family only, or work only) for a provider). However, for all other
+ * cases, the biometric screen should always show up if that entry contains the biometric bit.
+ */
+internal fun findBiometricFlowEntry(
+    activeEntry: ActiveEntry,
+    isAutoSelectFlow: Boolean,
+): CreateOptionInfo? {
+    if (!credmanBiometricApiEnabled()) {
+        return null
+    }
+    if (isAutoSelectFlow) {
+        // Since this is the create flow, auto select will only ever be true for a single provider.
+        // However, for all other cases, biometric should be used if that bit is opted into. If
+        // they clash, autoselect is always preferred, but that's only if there's a single provider.
+        return null
+    }
+    val biometricEntry = getCreateEntry(activeEntry)
+    return if (biometricEntry?.biometricRequest != null) biometricEntry else null
+}
+
+/**
+ * Retrieves the activeEntry by validating it is a [CreateOptionInfo]. This is done by ensuring
+ * that the [activeEntry] exists as a [CreateOptionInfo] to retrieve its [EntryInfo].
+ */
+internal fun getCreateEntry(
+    activeEntry: ActiveEntry?,
+): CreateOptionInfo? {
+    val entry = activeEntry?.activeEntryInfo
+    if (entry !is CreateOptionInfo) {
+        return null
+    }
+    return entry
+}
+
+/**
+* Determines if the flow is a biometric flow by taking into account autoselect criteria.
+*/
+internal fun isBiometricFlow(
+    activeEntry: ActiveEntry,
+    isAutoSelectFlow: Boolean,
+) = findBiometricFlowEntry(activeEntry, isAutoSelectFlow) != null
+
+/**
+ * This utility presents the correct resource string for the create flows title conditionally.
+ * Similar to generateDisplayTitleTextResCode in the 'get' flow, but for the create flow instead.
+ * This is for the title, and is a shared resource, unlike the specific unlock request text.
+ * E.g. this will look something like: "Create passkey to sign in to Tribank."
+ * // TODO(b/330396140) : Validate approach and add dynamic auth strings
+ */
+internal fun getCreateTitleResCode(createRequestDisplayInfo: RequestDisplayInfo): Int =
+    when (createRequestDisplayInfo.type) {
+        CredentialType.PASSKEY ->
+            R.string.choose_create_option_passkey_title
+
+        CredentialType.PASSWORD ->
+            R.string.choose_create_option_password_title
+
+        CredentialType.UNKNOWN ->
+            R.string.choose_create_option_sign_in_title
+    }
+
 internal fun isFlowAutoSelectable(
     uiState: CreateCredentialUiState
 ): Boolean {
-  return uiState.requestDisplayInfo.isAutoSelectRequest &&
-      uiState.sortedCreateOptionsPairs.size == 1 &&
-      uiState.activeEntry?.activeEntryInfo?.let {
-        it is CreateOptionInfo && it.allowAutoSelect
-      } ?: false
+    return isFlowAutoSelectable(uiState.requestDisplayInfo, uiState.activeEntry,
+        uiState.sortedCreateOptionsPairs)
+}
+
+/**
+ * When initializing, the [CreateCredentialUiState] is generated after the initial screen is set.
+ * This overloaded method allows identifying if the flow is auto selectable prior to the creation
+ * of the [CreateCredentialUiState].
+ */
+internal fun isFlowAutoSelectable(
+    requestDisplayInfo: RequestDisplayInfo,
+    activeEntry: ActiveEntry?,
+    sortedCreateOptionsPairs: List<Pair<CreateOptionInfo, EnabledProviderInfo>>
+): Boolean {
+    val isAutoSelectRequest = requestDisplayInfo.isAutoSelectRequest
+    if (sortedCreateOptionsPairs.size != 1) {
+        return false
+    }
+    val singleEntry = getCreateEntry(activeEntry)
+    return isAutoSelectRequest && singleEntry?.allowAutoSelect == true
 }
 
 internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
@@ -95,7 +177,9 @@
 /** The name of the current screen. */
 enum class CreateScreenState {
   CREATION_OPTION_SELECTION,
+  BIOMETRIC_SELECTION,
   MORE_OPTIONS_SELECTION,
   DEFAULT_PROVIDER_CONFIRMATION,
   EXTERNAL_ONLY_SELECTION,
+  MORE_OPTIONS_SELECTION_ONLY,
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 4d7272c..c98bb5e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -32,6 +32,8 @@
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.lazy.items
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material.icons.filled.Close
 import androidx.compose.material.icons.outlined.QrCodeScanner
 import androidx.compose.material3.Divider
 import androidx.compose.material3.TextButton
@@ -52,9 +54,12 @@
 import androidx.core.graphics.drawable.toBitmap
 import com.android.credentialmanager.CredentialSelectorViewModel
 import com.android.credentialmanager.R
+import com.android.credentialmanager.common.BiometricError
+import com.android.credentialmanager.common.BiometricFlowType
+import com.android.credentialmanager.common.BiometricPromptState
 import com.android.credentialmanager.common.ProviderActivityState
 import com.android.credentialmanager.common.material.ModalBottomSheetDefaults
-import com.android.credentialmanager.common.runBiometricFlow
+import com.android.credentialmanager.common.runBiometricFlowForGet
 import com.android.credentialmanager.common.ui.ActionButton
 import com.android.credentialmanager.common.ui.ActionEntry
 import com.android.credentialmanager.common.ui.ConfirmButton
@@ -144,10 +149,8 @@
                         } else if (credmanBiometricApiEnabled() && getCredentialUiState
                                 .currentScreenState == GetScreenState.BIOMETRIC_SELECTION) {
                             BiometricSelectionPage(
-                                // TODO(b/326243754) : Utilize expected entry for this flow, confirm
-                                // activeEntry will always be what represents the single tap flow
                                 biometricEntry = getCredentialUiState.activeEntry,
-                                onMoreOptionSelected = viewModel::getFlowOnMoreOptionSelected,
+                                onMoreOptionSelected = viewModel::getFlowOnMoreOptionOnlySelected,
                                 onCancelFlowAndFinish = viewModel::onUserCancel,
                                 onIllegalStateAndFinish = viewModel::onIllegalUiState,
                                 requestDisplayInfo = getCredentialUiState.requestDisplayInfo,
@@ -156,8 +159,34 @@
                                 onBiometricEntrySelected =
                                 viewModel::getFlowOnEntrySelected,
                                 fallbackToOriginalFlow =
-                                viewModel::getFlowOnBackToPrimarySelectionScreen,
+                                viewModel::fallbackFromBiometricToNormalFlow,
+                                getBiometricPromptState =
+                                viewModel::getBiometricPromptState,
+                                onBiometricPromptStateChange =
+                                viewModel::onBiometricPromptStateChange
                             )
+                        } else if (credmanBiometricApiEnabled() &&
+                                getCredentialUiState.currentScreenState
+                                == GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY) {
+                            AllSignInOptionCard(
+                                    providerInfoList = getCredentialUiState.providerInfoList,
+                                    providerDisplayInfo = getCredentialUiState.providerDisplayInfo,
+                                    onEntrySelected = viewModel::getFlowOnEntrySelected,
+                                    onBackButtonClicked = viewModel::onUserCancel,
+                                    onCancel = viewModel::onUserCancel,
+                                    onLog = { viewModel.logUiEvent(it) },
+                                    customTopBar = { MoreOptionTopAppBar(
+                                            text = stringResource(
+                                                    R.string.get_dialog_title_sign_in_options),
+                                            onNavigationIconClicked = viewModel::onUserCancel,
+                                            navigationIcon = Icons.Filled.Close,
+                                            navigationIconContentDescription =
+                                            stringResource(R.string.accessibility_close_button),
+                                            bottomPadding = 0.dp
+                                    ) }
+                            )
+                            viewModel.uiMetrics.log(GetCredentialEvent
+                                    .CREDMAN_GET_CRED_SCREEN_ALL_SIGN_IN_OPTIONS)
                         } else {
                             AllSignInOptionCard(
                                 providerInfoList = getCredentialUiState.providerInfoList,
@@ -219,20 +248,28 @@
     requestDisplayInfo: RequestDisplayInfo,
     providerInfoList: List<ProviderInfo>,
     providerDisplayInfo: ProviderDisplayInfo,
-    onBiometricEntrySelected: (EntryInfo, BiometricPrompt.AuthenticationResult?) -> Unit,
-    fallbackToOriginalFlow: () -> Unit,
+    onBiometricEntrySelected: (
+        EntryInfo,
+        BiometricPrompt.AuthenticationResult?,
+        BiometricError?
+    ) -> Unit,
+    fallbackToOriginalFlow: (BiometricFlowType) -> Unit,
+    getBiometricPromptState: () -> BiometricPromptState,
+    onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
 ) {
     if (biometricEntry == null) {
-        fallbackToOriginalFlow()
+        fallbackToOriginalFlow(BiometricFlowType.GET)
         return
     }
-    runBiometricFlow(
+    runBiometricFlowForGet(
         biometricEntry = biometricEntry,
         context = LocalContext.current,
         openMoreOptionsPage = onMoreOptionSelected,
         sendDataToProvider = onBiometricEntrySelected,
         onCancelFlowAndFinish = onCancelFlowAndFinish,
         onIllegalStateAndFinish = onIllegalStateAndFinish,
+        getBiometricPromptState = getBiometricPromptState,
+        onBiometricPromptStateChange = onBiometricPromptStateChange,
         getRequestDisplayInfo = requestDisplayInfo,
         getProviderInfoList = providerInfoList,
         getProviderDisplayInfo = providerDisplayInfo,
@@ -512,19 +549,8 @@
                                 R.string.get_dialog_title_choose_password_for
                             else if (areAllPasskeysOnPrimaryScreen)
                                 R.string.get_dialog_title_choose_passkey_for
-                            else if (primaryPageLockedEntryList.isNotEmpty() ||
-                                primaryPageCredentialEntryList.any {
-                                    it.sortedCredentialEntryList.first().credentialType !=
-                                            CredentialType.PASSWORD &&
-                                    it.sortedCredentialEntryList.first().credentialType !=
-                                            CredentialType.PASSKEY
-                                }
-                            ) // An unknown typed / locked entry exists, and we can't say it is
-                            // already saved, strictly speaking. Hence use a different title
-                            // without the mention of "saved".
+                            else
                                 R.string.get_dialog_title_choose_sign_in_for
-                            else // All entries on the primary screen are passkeys or passwords
-                                R.string.get_dialog_title_choose_saved_sign_in_for
                         },
                         requestDisplayInfo.appName
                     ),
@@ -629,7 +655,13 @@
     return providerId
 }
 
-/** Draws the secondary credential selection page, where all sign-in options are listed. */
+/**
+ * Draws the secondary credential selection page, where all sign-in options are listed.
+ *
+ * By default, this card has 'back' navigation whereby user can navigate back to invoke
+ * [onBackButtonClicked]. However if a different top bar with possibly a different navigation
+ * is required, then the caller of this Composable can set a [customTopBar].
+ */
 @Composable
 fun AllSignInOptionCard(
     providerInfoList: List<ProviderInfo>,
@@ -638,16 +670,24 @@
     onBackButtonClicked: () -> Unit,
     onCancel: () -> Unit,
     onLog: @Composable (UiEventEnum) -> Unit,
+    customTopBar: (@Composable() () -> Unit)? = null
 ) {
     val sortedUserNameToCredentialEntryList =
         providerDisplayInfo.sortedUserNameToCredentialEntryList
     val authenticationEntryList = providerDisplayInfo.authenticationEntryList
     SheetContainerCard(topAppBar = {
-        MoreOptionTopAppBar(
-            text = stringResource(R.string.get_dialog_title_sign_in_options),
-            onNavigationIconClicked = onBackButtonClicked,
-            bottomPadding = 0.dp,
-        )
+        if (customTopBar != null) {
+            customTopBar()
+        } else {
+            MoreOptionTopAppBar(
+                    text = stringResource(R.string.get_dialog_title_sign_in_options),
+                    onNavigationIconClicked = onBackButtonClicked,
+                    bottomPadding = 0.dp,
+                    navigationIcon = Icons.Filled.ArrowBack,
+                    navigationIconContentDescription = stringResource(
+                            R.string.accessibility_back_arrow_button
+            ))
+        }
     }) {
         var isFirstSection = true
         // For username
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index 6d5b52a..8e78861 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -163,7 +163,11 @@
     /** The single tap biometric selection page. */
     BIOMETRIC_SELECTION,
 
-    /** The secondary credential selection page, where all sign-in options are listed. */
+    /**
+     * The secondary credential selection page, where all sign-in options are listed.
+     *
+     * This state is expected to go back to PRIMARY_SELECTION on back navigation
+     */
     ALL_SIGN_IN_OPTIONS,
 
     /** The snackbar only page when there's no account but only a remoteEntry. */
@@ -171,6 +175,14 @@
 
     /** The snackbar when there are only auth entries and all of them turn out to be empty. */
     UNLOCKED_AUTH_ENTRIES_ONLY,
+
+    /**
+     * The secondary credential selection page, where all sign-in options are listed.
+     *
+     * This state has no option for the user to navigate back to PRIMARY_SELECTION, and
+     * instead can be terminated independently.
+     */
+    ALL_SIGN_IN_OPTIONS_ONLY,
 }
 
 
@@ -238,6 +250,7 @@
 /**
  * This generates the res code for the large display title text for the selector. For example, it
  * retrieves the resource for strings like: "Use your saved passkey for *rpName*".
+ * TODO(b/330396140) : Validate approach and add dynamic auth strings
  */
 internal fun generateDisplayTitleTextResCode(
     singleEntryType: CredentialType,
@@ -284,8 +297,8 @@
         providerDisplayInfo.remoteEntry != null)
         GetScreenState.REMOTE_ONLY
     else if (isRequestForAllOptions)
-        GetScreenState.ALL_SIGN_IN_OPTIONS
-    else if (isBiometricFlow(providerDisplayInfo))
+        GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY
+    else if (isBiometricFlow(providerDisplayInfo, isFlowAutoSelectable(providerDisplayInfo)))
         GetScreenState.BIOMETRIC_SELECTION
     else GetScreenState.PRIMARY_SELECTION
 }
@@ -293,9 +306,14 @@
 /**
  * Determines if the flow is a biometric flow by taking into account autoselect criteria.
  */
-internal fun isBiometricFlow(providerDisplayInfo: ProviderDisplayInfo) =
-    findBiometricFlowEntry(providerDisplayInfo,
-        findAutoSelectEntry(providerDisplayInfo) != null) != null
+internal fun isBiometricFlow(providerDisplayInfo: ProviderDisplayInfo, isAutoSelectFlow: Boolean) =
+    findBiometricFlowEntry(providerDisplayInfo, isAutoSelectFlow) != null
+
+/**
+ * Determines if the flow is an autoselect flow.
+ */
+internal fun isFlowAutoSelectable(providerDisplayInfo: ProviderDisplayInfo) =
+    findAutoSelectEntry(providerDisplayInfo) != null
 
 internal class CredentialEntryInfoComparatorByTypeThenTimestamp(
         val typePriorityMap: Map<String, Int>,
diff --git a/packages/CredentialManager/wear/res/drawable/passkey_icon.xml b/packages/CredentialManager/wear/res/drawable/passkey_icon.xml
deleted file mode 100644
index be366bf..0000000
--- a/packages/CredentialManager/wear/res/drawable/passkey_icon.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:pathData="M23,10.5H17V13.5H23V10.5Z"
-        android:fillColor="#188038"/>
-    <path
-        android:pathData="M6.5,17.5C3.5,17.5 1,15 1,12C1,9 3.5,6.5 6.5,6.5C9.5,6.5 12,9 12,12C12,15 9.5,17.5 6.5,17.5ZM6.5,9.5C5.1,9.5 4,10.6 4,12C4,13.4 5.1,14.5 6.5,14.5C7.9,14.5 9,13.4 9,12C9,10.6 7.9,9.5 6.5,9.5Z"
-        android:fillColor="#4285F4"/>
-    <path
-        android:pathData="M21,13.5H19H17V16.5H19V15.5C19,14.9 19.4,14.5 20,14.5C20.6,14.5 21,14.9 21,15.5V16.5H23V13.5H21Z"
-        android:fillColor="#34A853"/>
-    <path
-        android:pathData="M11.8,10.5H8.5C8.8,10.9 9,11.4 9,12C9,12.6 8.8,13.1 8.5,13.5H11.8C11.9,13 12,12.5 12,12C12,11.5 11.9,11 11.8,10.5Z"
-        android:fillColor="#EA4335"/>
-    <path
-        android:pathData="M17,10.5H11.8C11.9,11 12,11.5 12,12C12,12.5 11.9,13 11.8,13.5H17V10.5Z"
-        android:fillColor="#FBBC04"/>
-</vector>
diff --git a/packages/CredentialManager/wear/res/values-watch/donottranslate.xml b/packages/CredentialManager/wear/res/values-watch/donottranslate.xml
new file mode 100644
index 0000000..c3ab3cb
--- /dev/null
+++ b/packages/CredentialManager/wear/res/values-watch/donottranslate.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- font-family-device-default is expected to be preloaded in the font_customization.xml(/vendor/<OEM>/products/<PRODUCT>/fonts/fonts_customization.xml)-->
+    <!-- Falls back to system default when font-family-device-default doesn't exist    -->
+    <string name="wear_material_compose_display_1_font_family">font-family-device-default</string>
+    <string name="wear_material_compose_display_2_font_family">font-family-device-default</string>
+    <string name="wear_material_compose_display_3_font_family">font-family-device-default</string>
+    <string name="wear_material_compose_title_1_font_family">font-family-medium-device-default</string>
+    <string name="wear_material_compose_title_2_font_family">font-family-medium-device-default</string>
+    <string name="wear_material_compose_title_3_font_family">font-family-device-default</string>
+    <string name="wear_material_compose_body_1_font_family">font-family-text-device-default</string>
+    <string name="wear_material_compose_body_2_font_family">font-family-text-device-default</string>
+    <string name="wear_material_compose_button_font_family">font-family-text-medium-device-default</string>
+    <string name="wear_material_compose_caption_1_font_family">font-family-text-medium-device-default</string>
+    <string name="wear_material_compose_caption_2_font_family">font-family-text-medium-device-default</string>
+    <string name="wear_material_compose_caption_3_font_family">font-family-text-medium-device-default</string>
+</resources>
diff --git a/packages/CredentialManager/wear/res/values/overlayable.xml b/packages/CredentialManager/wear/res/values/overlayable.xml
new file mode 100644
index 0000000..5b9d372
--- /dev/null
+++ b/packages/CredentialManager/wear/res/values/overlayable.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <overlayable name="CredentialSelectorStyles">
+        <policy type="product|system|vendor|odm|oem">
+            <!--START WEAR SPECIFIC FONT STRINGS -->
+            <item type="string" name="wear_material_compose_display_1_font_family" />
+            <item type="string" name="wear_material_compose_display_2_font_family" />
+            <item type="string" name="wear_material_compose_display_3_font_family" />
+            <item type="string" name="wear_material_compose_title_1_font_family" />
+            <item type="string" name="wear_material_compose_title_2_font_family" />
+            <item type="string" name="wear_material_compose_title_3_font_family" />
+            <item type="string" name="wear_material_compose_body_1_font_family" />
+            <item type="string" name="wear_material_compose_body_2_font_family" />
+            <item type="string" name="wear_material_compose_button_font_family" />
+            <item type="string" name="wear_material_compose_caption_1_font_family" />
+            <item type="string" name="wear_material_compose_caption_2_font_family" />
+            <item type="string" name="wear_material_compose_caption_3_font_family" />
+            <!--END WEAR SPECIFIC FONT STRINGS -->
+
+        </policy>
+
+    </overlayable>
+
+</resources>
diff --git a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt
index 3422d3d..c6013e2 100644
--- a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt
+++ b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorUiStateGetMapperTest.kt
@@ -65,29 +65,29 @@
             isLastUnlocked = true
         )
 
-    val passkeyCredentialEntryInfo =
+    private val passkeyCredentialEntryInfo =
         createCredentialEntryInfo(credentialType = CredentialType.PASSKEY, userName = "userName")
 
-    val unknownCredentialEntryInfo =
+    private val unknownCredentialEntryInfo =
         createCredentialEntryInfo(credentialType = CredentialType.UNKNOWN, userName = "userName2")
 
-    val passwordCredentialEntryInfo =
+    private val passwordCredentialEntryInfo =
         createCredentialEntryInfo(credentialType = CredentialType.PASSWORD, userName = "userName")
 
-    val recentlyUsedPasskeyCredential =
+    private val recentlyUsedPasskeyCredential =
         createCredentialEntryInfo(credentialType =
     CredentialType.PASSKEY, lastUsedTimeMillis = 2L, userName = "userName")
 
-    val recentlyUsedPasswordCredential =
+    private val recentlyUsedPasswordCredential =
         createCredentialEntryInfo(credentialType =
     CredentialType.PASSWORD, lastUsedTimeMillis = 2L, userName = "userName")
 
-    val credentialList1 = listOf(
+    private val credentialList1 = listOf(
         passkeyCredentialEntryInfo,
         passwordCredentialEntryInfo
     )
 
-    val credentialList2 = listOf(
+    private val credentialList2 = listOf(
         passkeyCredentialEntryInfo,
         passwordCredentialEntryInfo,
         recentlyUsedPasskeyCredential,
@@ -100,7 +100,6 @@
         val getCredentialUiState = Request.Get(
             token = null,
             resultReceiver = null,
-            finalResponseReceiver = null,
             providerInfos = listOf(createProviderInfo(credentialList1))).toGet(isPrimary = true)
 
         assertThat(getCredentialUiState).isEqualTo(
@@ -113,16 +112,16 @@
         val getCredentialUiState = Request.Get(
             token = null,
             resultReceiver = null,
-            finalResponseReceiver = null,
             providerInfos = listOf(createProviderInfo(listOf(passkeyCredentialEntryInfo,
                 unknownCredentialEntryInfo)))).toGet(isPrimary = true)
 
         assertThat(getCredentialUiState).isEqualTo(
-            CredentialSelectorUiState.Get.SingleEntryPerAccount(
+            CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen(
                 sortedEntries = listOf(
                     passkeyCredentialEntryInfo, // userName
                     unknownCredentialEntryInfo // userName2
                 ),
+                icon = mDrawable,
                 authenticationEntryList = listOf(authenticationEntryInfo)
             )) // prefer passkey from account 1, then unknown from account 2
     }
@@ -132,7 +131,6 @@
         val getCredentialUiState = Request.Get(
             token = null,
             resultReceiver = null,
-            finalResponseReceiver = null,
             providerInfos = listOf(createProviderInfo(credentialList1))).toGet(isPrimary = false)
 
         assertThat(getCredentialUiState).isEqualTo(
@@ -151,7 +149,6 @@
         val getCredentialUiState = Request.Get(
             token = null,
             resultReceiver = null,
-            finalResponseReceiver = null,
             providerInfos = listOf(createProviderInfo(credentialList1),
                 createProviderInfo(credentialList2))).toGet(isPrimary = false)
 
diff --git a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt
index b79f34c..cf839f8 100644
--- a/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt
+++ b/packages/CredentialManager/wear/robotests/src/com/android/credentialmanager/CredentialSelectorViewModelTest.kt
@@ -121,7 +121,6 @@
         stateFlow.value = Request.Get(
             token = null,
             resultReceiver = null,
-            finalResponseReceiver = null,
             providerInfos = emptyList())
 
         mViewModel.back()
@@ -136,7 +135,6 @@
         stateFlow.value = Request.Get(
             token = null,
             resultReceiver = null,
-            finalResponseReceiver = null,
             providerInfos = emptyList())
 
         mViewModel.back()
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index 0fe35e6..652e62c 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -21,7 +21,7 @@
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.viewModels
-import androidx.wear.compose.material.MaterialTheme
+import com.android.credentialmanager.ui.theme.WearCredentialSelectorTheme
 import com.android.credentialmanager.ui.WearApp
 import com.google.android.horologist.annotations.ExperimentalHorologistApi
 import dagger.hilt.android.AndroidEntryPoint
@@ -36,7 +36,7 @@
         super.onCreate(savedInstanceState)
         setTheme(android.R.style.Theme_DeviceDefault)
         setContent {
-            MaterialTheme {
+            WearCredentialSelectorTheme {
                 WearApp(
                     flowEngine = viewModel,
                     onCloseApp = { finish() },
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index b7fa33e..3608568 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -86,7 +86,7 @@
         when (uiState.value) {
             is Get.MultipleEntry -> isPrimaryScreen.value = true
             is Create, Close, is Cancel, Idle -> shouldClose.value = true
-            is Get.SingleEntry, is Get.SingleEntryPerAccount -> cancel()
+            is Get.SingleEntry, is Get.MultipleEntryPrimaryScreen -> cancel()
         }
     }
 
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt
index c05fc93..b2f55c1 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/FlowEngine.kt
@@ -17,6 +17,7 @@
 package com.android.credentialmanager
 
 import android.content.Intent
+import android.graphics.drawable.Drawable
 import androidx.activity.result.IntentSenderRequest
 import androidx.compose.runtime.Composable
 import com.android.credentialmanager.model.EntryInfo
@@ -71,14 +72,14 @@
         /** Getting credential UI state when there is only one credential available. */
         data class SingleEntry(val entry: CredentialEntryInfo) : Get()
         /**
-         * Getting credential UI state when there is only one account while with multiple
-         * credentials, with different types(eg, passkey vs password) or providers.
+         * Getting credential UI state on primary screen when there is are multiple accounts.
          */
-        data class SingleEntryPerAccount(
+        data class MultipleEntryPrimaryScreen(
+            val icon: Drawable?,
             val sortedEntries: List<CredentialEntryInfo>,
             val authenticationEntryList: List<AuthenticationEntryInfo>,
             ) : Get()
-        /** Getting credential UI state when there are multiple accounts available. */
+        /** Getting credential UI state on secondary screen when there are multiple accounts available. */
         data class MultipleEntry(
             val accounts: List<PerUserNameEntries>,
             val actionEntryList: List<ActionEntryInfo>,
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
index 018db68..a75aeaf 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/WearApp.kt
@@ -29,7 +29,7 @@
 import androidx.wear.compose.navigation.rememberSwipeDismissableNavController
 import androidx.wear.compose.navigation.rememberSwipeDismissableNavHostState
 import com.android.credentialmanager.CredentialSelectorUiState
-import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntryPerAccount
+import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen
 import com.android.credentialmanager.CredentialSelectorUiState.Get.SingleEntry
 import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry
 import com.android.credentialmanager.FlowEngine
@@ -95,7 +95,7 @@
 
         scrollable(Screen.MultipleCredentialsScreenFold.route) {
             MultiCredentialsFoldScreen(
-                credentialSelectorUiState = (remember { uiState } as SingleEntryPerAccount),
+                credentialSelectorUiState = (remember { uiState } as MultipleEntryPrimaryScreen),
                 columnState = it.columnState,
                 flowEngine = flowEngine,
             )
@@ -124,7 +124,6 @@
                 handleGetNavigation(
                     navController = navController,
                     state = state,
-                    onCloseApp = onCloseApp,
                     selectEntry = selectEntry
                 )
             }
@@ -147,7 +146,6 @@
 private fun handleGetNavigation(
     navController: NavController,
     state: CredentialSelectorUiState.Get,
-    onCloseApp: () -> Unit,
     selectEntry: (entry: EntryInfo, isAutoSelected: Boolean) -> Unit,
 ) {
     when (state) {
@@ -169,7 +167,7 @@
             }
         }
 
-            is SingleEntryPerAccount -> {
+            is MultipleEntryPrimaryScreen -> {
                 navController.navigateToMultipleCredentialsFoldScreen()
             }
 
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt
index 8b19e1b..3088fed 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt
@@ -21,35 +21,25 @@
 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.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.material.MaterialTheme
-import androidx.wear.compose.material.Text
+import com.android.credentialmanager.common.ui.components.WearDisplayNameText
+import com.android.credentialmanager.common.ui.components.WearUsernameText
 import com.google.android.horologist.compose.tools.WearPreview
 
 @Composable
 fun AccountRow(
     primaryText: String,
     secondaryText: String? = null,
-    modifier: Modifier = Modifier,
 ) {
-    Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
-        Text(
+    Column(modifier = Modifier.padding(bottom = 12.dp),
+        horizontalAlignment = Alignment.CenterHorizontally) {
+        WearDisplayNameText(
             text = primaryText,
-            color = Color(0xFFE6FF7B),
-            overflow = TextOverflow.Ellipsis,
-            maxLines = 1,
-            style = MaterialTheme.typography.title2
         )
         if (secondaryText != null) {
-            Text(
+            WearUsernameText(
                 text = secondaryText,
-                modifier = Modifier.padding(top = 7.dp),
-                color = Color(0xFFCAC5BC),
-                overflow = TextOverflow.Ellipsis,
-                maxLines = 2,
-                style = MaterialTheme.typography.body1,
+                modifier = Modifier.padding(top = 8.dp)
             )
         }
     }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt
index 8e5a866..c641d7f 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/CredentialsScreenChip.kt
@@ -22,12 +22,9 @@
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clipToBounds
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.wear.compose.material.Chip
@@ -35,11 +32,12 @@
 import androidx.wear.compose.material.ChipColors
 import androidx.compose.ui.graphics.asImageBitmap
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.style.TextAlign
 import androidx.wear.compose.material.ChipDefaults
-import androidx.wear.compose.material.Text
 import com.android.credentialmanager.R
+import com.android.credentialmanager.common.ui.components.WearButtonText
+import com.android.credentialmanager.common.ui.components.WearSecondaryLabel
 import com.android.credentialmanager.model.get.AuthenticationEntryInfo
-import com.android.credentialmanager.ui.components.CredentialsScreenChip.TOPPADDING
 
 /* Used as credential suggestion or user action chip. */
 @Composable
@@ -49,36 +47,61 @@
     secondaryLabel: String? = null,
     icon: Drawable? = null,
     isAuthenticationEntryLocked: Boolean = false,
+    textAlign: TextAlign = TextAlign.Center,
     modifier: Modifier = Modifier,
-    colors: ChipColors = ChipDefaults.secondaryChipColors(),
+    colors: ChipColors = ChipDefaults.secondaryChipColors()
 ) {
+        return CredentialsScreenChip(
+                    onClick,
+                    text = {
+                        WearButtonText(
+                            text = label,
+                            textAlign = textAlign,
+                            maxLines = if (secondaryLabel != null) 1 else 2
+                        )
+                    },
+                    secondaryLabel,
+                    icon,
+                    isAuthenticationEntryLocked,
+                    modifier,
+                    colors
+        )
+}
+
+
+
+/* Used as credential suggestion or user action chip. */
+@Composable
+fun CredentialsScreenChip(
+    onClick: () -> Unit,
+    text: @Composable () -> Unit,
+    secondaryLabel: String? = null,
+    icon: Drawable? = null,
+    isAuthenticationEntryLocked: Boolean = false,
+    modifier: Modifier = Modifier,
+    colors: ChipColors = ChipDefaults.primaryChipColors(),
+    ) {
     val labelParam: (@Composable RowScope.() -> Unit) =
         {
-            Text(
-                text = label,
-                overflow = TextOverflow.Ellipsis,
-                maxLines = if (secondaryLabel != null) 1 else 2,
-            )
+            text()
         }
 
     val secondaryLabelParam: (@Composable RowScope.() -> Unit)? =
         secondaryLabel?.let {
             {
                 Row {
-                    Text(
+                    WearSecondaryLabel(
                         text = secondaryLabel,
-                        overflow = TextOverflow.Ellipsis,
-                        maxLines = 1,
                     )
 
                     if (isAuthenticationEntryLocked)
-                        // TODO(b/324465527) change this to lock icon and correct size once figma mocks are
-                        // updated
+                    // TODO(b/324465527) change this to lock icon and correct size once figma mocks are
+                    // updated
                         Icon(
                             bitmap = checkNotNull(icon?.toBitmap()?.asImageBitmap()),
                             // Decorative purpose only.
                             contentDescription = null,
-                            modifier = Modifier.size(20.dp),
+                            modifier = Modifier.size(10.dp),
                             tint = Color.Unspecified
                         )
                 }
@@ -92,7 +115,7 @@
                     bitmap = it,
                     // Decorative purpose only.
                     contentDescription = null,
-                    modifier = Modifier.size(32.dp),
+                    modifier = Modifier.size(24.dp),
                     tint = Color.Unspecified
                 )
             }
@@ -117,9 +140,6 @@
         onClick = { },
         secondaryLabel = "[email protected]",
         icon = null,
-        modifier = Modifier
-            .clipToBounds()
-            .padding(top = 2.dp)
     )
 }
 
@@ -127,9 +147,8 @@
 fun SignInOptionsChip(onClick: () -> Unit) {
     CredentialsScreenChip(
         label = stringResource(R.string.dialog_sign_in_options_button),
+        textAlign = TextAlign.Start,
         onClick = onClick,
-        modifier = Modifier
-            .padding(top = TOPPADDING)
     )
 }
 
@@ -142,10 +161,13 @@
 @Composable
 fun ContinueChip(onClick: () -> Unit) {
     CredentialsScreenChip(
-        label = stringResource(R.string.dialog_continue_button),
         onClick = onClick,
-        modifier = Modifier
-            .padding(top = TOPPADDING),
+        text = {
+            WearButtonText(
+                text = stringResource(R.string.dialog_continue_button),
+                textAlign = TextAlign.Center,
+            )
+        },
         colors = ChipDefaults.primaryChipColors(),
     )
 }
@@ -161,21 +183,8 @@
     CredentialsScreenChip(
         label = stringResource(R.string.dialog_dismiss_button),
         onClick = onClick,
-        modifier = Modifier
-            .padding(top = TOPPADDING),
     )
 }
-
-@Composable
-fun SignInOnPhoneChip(onClick: () -> Unit) {
-    CredentialsScreenChip(
-        label = stringResource(R.string.sign_in_on_phone_button),
-        onClick = onClick,
-        modifier = Modifier
-            .padding(top = TOPPADDING),
-    )
-}
-
 @Composable
 fun LockedProviderChip(
     authenticationEntryInfo: AuthenticationEntryInfo,
@@ -191,9 +200,9 @@
         label = authenticationEntryInfo.title,
         icon = authenticationEntryInfo.icon,
         secondaryLabel = secondaryLabel,
+        textAlign = TextAlign.Start,
         isAuthenticationEntryLocked = !authenticationEntryInfo.isUnlockedAndEmpty,
         onClick = onClick,
-        modifier = Modifier.padding(top = TOPPADDING),
     )
 }
 
@@ -203,7 +212,3 @@
     DismissChip({})
 }
 
-private object CredentialsScreenChip {
-    val TOPPADDING = 8.dp
-}
-
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt
index 97900b7..62e1c85 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt
@@ -21,33 +21,22 @@
 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.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.material.MaterialTheme
-import androidx.wear.compose.material.Text
+import com.android.credentialmanager.common.ui.components.WearDisplayNameText
+import com.android.credentialmanager.common.ui.components.WearUsernameText
 import com.google.android.horologist.compose.tools.WearPreview
 
 @Composable
 fun PasswordRow(
     email: String,
-    modifier: Modifier = Modifier,
 ) {
-    Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
-        Text(
+    Column(modifier = Modifier.padding(bottom = 12.dp),
+        horizontalAlignment = Alignment.CenterHorizontally) {
+        WearDisplayNameText(
             text = email,
-            color = Color(0xFFE6FF7B),
-            overflow = TextOverflow.Ellipsis,
-            maxLines = 2,
-            style = MaterialTheme.typography.title2
         )
-        Text(
-            text = "••••••••••••••",
-            modifier = Modifier.padding(top = 7.dp),
-            color = Color(0xFFCAC5BC),
-            overflow = TextOverflow.Ellipsis,
-            maxLines = 1,
-            style = MaterialTheme.typography.body1,
+        WearUsernameText(
+            text = "••••••••••••••"
         )
     }
 }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
index 423662c..0afef5e 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
@@ -18,49 +18,44 @@
 
 import android.graphics.drawable.Drawable
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Icon
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.asImageBitmap
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toBitmap
-import androidx.wear.compose.material.Text
-import androidx.compose.ui.graphics.Color
-import androidx.compose.material3.Icon
-import androidx.wear.compose.material.MaterialTheme as WearMaterialTheme
-import androidx.compose.ui.text.style.TextAlign
+import com.android.credentialmanager.common.ui.components.WearTitleText
 
 /* Used as header across Credential Selector screens. */
 @Composable
 fun SignInHeader(
     icon: Drawable?,
     title: String,
-    modifier: Modifier = Modifier,
 ) {
     Column(
-        modifier = modifier,
+        modifier = Modifier,
         horizontalAlignment = Alignment.CenterHorizontally
     ) {
         if (icon != null) {
             Icon(
                 bitmap = icon.toBitmap().asImageBitmap(),
-                modifier = Modifier.size(32.dp),
+                modifier = Modifier.size(24.dp),
                 // Decorative purpose only.
                 contentDescription = null,
                 tint = Color.Unspecified,
 
             )
         }
+        Spacer(modifier = Modifier.size(8.dp))
 
-        Text(
+        WearTitleText(
             text = title,
-            textAlign = TextAlign.Center,
-            modifier = Modifier
-                .padding(top = 6.dp)
-                .padding(horizontal = 10.dp),
-            style = WearMaterialTheme.typography.title3
         )
+
+        Spacer(modifier = Modifier.size(8.dp))
     }
 }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Spacers.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Spacers.kt
new file mode 100644
index 0000000..c87f176
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Spacers.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.ui.components
+
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+/**
+ * Space beneath all elements of screen
+ */
+@Composable
+fun BottomSpacer() {
+    Spacer(modifier = Modifier.size(40.dp))
+ }
+
+/**
+ * Usual space between Credential Screen Chips
+ */
+@Composable
+fun CredentialsScreenChipSpacer() {
+    Spacer(modifier = Modifier.size(4.dp))
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt
new file mode 100644
index 0000000..22f6bf0
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/Texts.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.common.ui.components
+
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentSize
+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.TextLayoutResult
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.MaterialTheme as WearMaterialTheme
+
+@Composable
+fun WearTitleText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = WearMaterialTheme.colors.onSurface,
+        textAlign = TextAlign.Center,
+        style = WearMaterialTheme.typography.title3,
+    )
+}
+
+@Composable
+fun WearDisplayNameText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = WearMaterialTheme.colors.onSurfaceVariant,
+        textAlign = TextAlign.Center,
+        overflow = TextOverflow.Ellipsis,
+        maxLines = 2,
+        style = WearMaterialTheme.typography.title2,
+    )
+}
+
+@Composable
+fun WearUsernameText(
+    text: String,
+    textAlign: TextAlign = TextAlign.Center,
+    modifier: Modifier = Modifier,
+    onTextLayout: (TextLayoutResult) -> Unit = {},
+) {
+    Text(
+        modifier = modifier.padding(start = 8.dp, end = 8.dp).wrapContentSize(),
+        text = text,
+        color = WearMaterialTheme.colors.onSurfaceVariant,
+        style = WearMaterialTheme.typography.caption1,
+        overflow = TextOverflow.Ellipsis,
+        textAlign = textAlign,
+        maxLines = 2,
+        onTextLayout = onTextLayout,
+    )
+}
+
+// used for primary label in button
+@Composable
+fun WearButtonText(
+    text: String,
+    textAlign: TextAlign,
+    maxLines: Int = 1,
+    modifier: Modifier = Modifier,
+    color: Color = WearMaterialTheme.colors.onSurface,
+    onTextLayout: (TextLayoutResult) -> Unit = {},
+) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = color,
+        style = WearMaterialTheme.typography.button,
+        overflow = TextOverflow.Ellipsis,
+        textAlign = textAlign,
+        maxLines = maxLines,
+        onTextLayout = onTextLayout,
+    )
+}
+
+@Composable
+fun WearSecondaryLabel(
+    text: String,
+    modifier: Modifier = Modifier,
+    onTextLayout: (TextLayoutResult) -> Unit = {},
+) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = WearMaterialTheme.colors.onSurfaceVariant,
+        style = WearMaterialTheme.typography.caption1,
+        overflow = TextOverflow.Ellipsis,
+        textAlign = TextAlign.Start,
+        maxLines = 1,
+        onTextLayout = onTextLayout,
+    )
+}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt
index 7a936b6..0417533 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mappers/CredentialSelectorUiStateGetMapper.kt
@@ -16,6 +16,7 @@
 
 package com.android.credentialmanager.ui.mappers
 
+import android.graphics.drawable.Drawable
 import com.android.credentialmanager.model.Request
 import com.android.credentialmanager.CredentialSelectorUiState
 import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerUserNameEntries
@@ -35,10 +36,19 @@
                 entry = accounts[0].value.minWith(comparator)
             )
         } else {
-            CredentialSelectorUiState.Get.SingleEntryPerAccount(
-                sortedEntries = accounts.map {
-                    it.value.minWith(comparator)
-                }.sortedWith(comparator),
+            val sortedEntries = accounts.map {
+                it.value.minWith(comparator)
+            }.sortedWith(comparator)
+
+            var icon: Drawable? = null
+            // provide icon if all entries have the same provider
+            if (sortedEntries.all {it.providerId == sortedEntries[0].providerId}) {
+                icon = providerInfos[0].icon
+            }
+
+            CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen(
+                sortedEntries = sortedEntries,
+                icon = icon,
                 authenticationEntryList = providerInfos.flatMap { it.authenticationEntryList }
             )
         }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt
index b3ab0c4..0b07643 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/LoadingScreen.kt
@@ -17,12 +17,9 @@
 package com.android.credentialmanager.ui.screens
 
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
 
 @Composable
-fun LoadingScreen(
-    modifier: Modifier = Modifier
-) {
+fun LoadingScreen() {
     // Don't display anything, assuming that there should be minimal latency
     // to parse the Credential Manager intent and define the state of the
     // app. If latency is big, then a "loading" screen should be displayed
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
index d54103c..fb81e73 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
@@ -15,20 +15,21 @@
  */
 package com.android.credentialmanager.ui.screens.multiple
 
+import com.android.credentialmanager.ui.components.CredentialsScreenChip
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
-import androidx.wear.compose.material.MaterialTheme
-import androidx.wear.compose.material.Text
-import com.android.credentialmanager.ui.components.SignInHeader
 import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry
 import com.android.credentialmanager.FlowEngine
 import com.android.credentialmanager.R
+import com.android.credentialmanager.common.ui.components.WearButtonText
+import com.android.credentialmanager.common.ui.components.WearSecondaryLabel
 import com.android.credentialmanager.model.get.CredentialEntryInfo
-import com.android.credentialmanager.ui.components.CredentialsScreenChip
+import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer
 import com.google.android.horologist.annotations.ExperimentalHorologistApi
 import com.google.android.horologist.compose.layout.ScalingLazyColumn
 import com.google.android.horologist.compose.layout.ScalingLazyColumnState
@@ -55,20 +56,17 @@
     ) {
         item {
             // make this credential specific if all credentials are same
-            SignInHeader(
-                icon = null,
-                title = stringResource(R.string.sign_in_options_title),
+            WearButtonText(
+                text = stringResource(R.string.sign_in_options_title),
+                textAlign = TextAlign.Start,
             )
         }
 
         credentialSelectorUiState.accounts.forEach { userNameEntries ->
             item {
-                Text(
+                WearSecondaryLabel(
                     text = userNameEntries.userName,
-                    modifier = Modifier
-                        .padding(top = 6.dp)
-                        .padding(horizontal = 10.dp),
-                    style = MaterialTheme.typography.title3
+                    modifier = Modifier.padding(top = 12.dp, bottom = 4.dp)
                 )
             }
 
@@ -79,21 +77,20 @@
                         onClick = { selectEntry(credential, false) },
                         secondaryLabel = credential.credentialTypeDisplayName,
                         icon = credential.icon,
+                        textAlign = TextAlign.Start
                     )
+
+                    CredentialsScreenChipSpacer()
                 }
             }
         }
         item {
-            Text(
+            WearSecondaryLabel(
                 text = stringResource(R.string.provider_list_title),
-                modifier = Modifier
-                    .padding(top = 6.dp)
-                    .padding(horizontal = 10.dp),
-                style = MaterialTheme.typography.title3
+                modifier = Modifier.padding(top = 12.dp, bottom = 4.dp)
             )
         }
-
-        credentialSelectorUiState.actionEntryList.forEach {actionEntry ->
+        credentialSelectorUiState.actionEntryList.forEach { actionEntry ->
             item {
                     CredentialsScreenChip(
                         label = actionEntry.title,
@@ -101,9 +98,8 @@
                         secondaryLabel = null,
                         icon = actionEntry.icon,
                     )
+                    CredentialsScreenChipSpacer()
             }
         }
     }
 }
-
-
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt
index 6f32c99..7addc74 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFoldScreen.kt
@@ -16,10 +16,11 @@
 
 package com.android.credentialmanager.ui.screens.multiple
 
+import androidx.compose.foundation.layout.Spacer
 import com.android.credentialmanager.R
 import androidx.compose.ui.res.stringResource
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
@@ -35,6 +36,8 @@
 import com.google.android.horologist.compose.layout.ScalingLazyColumn
 import com.google.android.horologist.compose.layout.ScalingLazyColumnState
 import com.android.credentialmanager.model.CredentialType
+import com.android.credentialmanager.ui.components.BottomSpacer
+import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer
 
 /**
  * Screen that shows multiple credentials to select from.
@@ -45,7 +48,7 @@
 @OptIn(ExperimentalHorologistApi::class)
 @Composable
 fun MultiCredentialsFoldScreen(
-    credentialSelectorUiState: CredentialSelectorUiState.Get.SingleEntryPerAccount,
+    credentialSelectorUiState: CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen,
     columnState: ScalingLazyColumnState,
     flowEngine: FlowEngine,
 ) {
@@ -58,42 +61,52 @@
         val credentials = credentialSelectorUiState.sortedEntries
         item {
             var title = stringResource(R.string.choose_sign_in_title)
-            if (credentials.all{ it.credentialType == CredentialType.PASSKEY }) {
+
+            if (credentials.isEmpty()) {
+                title = stringResource(R.string.choose_sign_in_title)
+            } else if (credentials.all{ it.credentialType == CredentialType.PASSKEY }) {
                 title = stringResource(R.string.choose_passkey_title)
             } else if (credentials.all { it.credentialType == CredentialType.PASSWORD }) {
                 title = stringResource(R.string.choose_password_title)
             }
 
             SignInHeader(
-                icon = null,
+                icon = credentialSelectorUiState.icon,
                 title = title,
-                modifier = Modifier
-                    .padding(top = 6.dp),
             )
         }
 
         credentials.forEach { credential: CredentialEntryInfo ->
-                item {
-                    CredentialsScreenChip(
-                        label = credential.userName,
-                        onClick = { selectEntry(credential, false) },
-                        secondaryLabel = credential.credentialTypeDisplayName,
-                        icon = credential.icon,
-                    )
-                }
+            item {
+                CredentialsScreenChip(
+                    label = credential.userName,
+                    onClick = { selectEntry(credential, false) },
+                    secondaryLabel = credential.credentialTypeDisplayName,
+                    icon = credential.icon,
+                )
+                CredentialsScreenChipSpacer()
             }
+        }
 
         credentialSelectorUiState.authenticationEntryList.forEach { authenticationEntryInfo ->
             item {
                 LockedProviderChip(authenticationEntryInfo) {
-                    selectEntry(authenticationEntryInfo, false) }
+                    selectEntry(authenticationEntryInfo, false)
+                }
+                CredentialsScreenChipSpacer()
             }
         }
+
+        item {
+            Spacer(modifier = Modifier.size(8.dp))
+        }
+
         item {
             SignInOptionsChip { flowEngine.openSecondaryScreen() }
         }
         item {
             DismissChip { flowEngine.cancel() }
+            BottomSpacer()
         }
     }
 }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt
index 56b1c2e..03608a4 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/passkey/SinglePasskeyScreen.kt
@@ -29,17 +29,19 @@
 import com.android.credentialmanager.R
 import com.android.credentialmanager.ui.components.AccountRow
 import com.android.credentialmanager.ui.components.ContinueChip
+import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer
 import com.android.credentialmanager.ui.components.DismissChip
 import com.android.credentialmanager.ui.components.SignInHeader
 import com.android.credentialmanager.ui.components.SignInOptionsChip
 import com.android.credentialmanager.ui.screens.single.SingleAccountScreen
 import com.google.android.horologist.annotations.ExperimentalHorologistApi
 import com.google.android.horologist.compose.layout.ScalingLazyColumnState
+import com.android.credentialmanager.ui.components.BottomSpacer
 
 /**
- * Screen that shows sign in with provider credential.
+ * Screen that shows single passkey credential.
  *
- * @param entry The password entry
+ * @param entry The passkey entry
  * @param columnState ScalingLazyColumn configuration to be be applied to SingleAccountScreen
  * @param modifier styling for composable
  * @param flowEngine [FlowEngine] that updates ui state for this screen
@@ -49,7 +51,6 @@
 fun SinglePasskeyScreen(
     entry: CredentialEntryInfo,
     columnState: ScalingLazyColumnState,
-    modifier: Modifier = Modifier,
     flowEngine: FlowEngine,
 ) {
     SingleAccountScreen(
@@ -60,21 +61,31 @@
             )
         },
         accountContent = {
-            AccountRow(
-                    primaryText = checkNotNull(entry.displayName),
-                    secondaryText = entry.userName,
-                    modifier = Modifier.padding(top = 10.dp),
+            val displayName = entry.displayName
+            if (displayName == null ||
+                entry.displayName.equals(entry.userName, ignoreCase = true)) {
+                AccountRow(
+                    primaryText = entry.userName,
                 )
+            } else {
+                AccountRow(
+                    primaryText = displayName,
+                    secondaryText = entry.userName,
+                )
+            }
         },
         columnState = columnState,
-        modifier = modifier.padding(horizontal = 10.dp)
+        modifier = Modifier.padding(horizontal = 10.dp)
     ) {
         item {
             val selectEntry = flowEngine.getEntrySelector()
             Column {
                 ContinueChip { selectEntry(entry, false) }
+                CredentialsScreenChipSpacer()
                 SignInOptionsChip{ flowEngine.openSecondaryScreen() }
+                CredentialsScreenChipSpacer()
                 DismissChip { flowEngine.cancel() }
+                BottomSpacer()
             }
         }
     }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
index 2ca8ef1..818723b 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
@@ -33,11 +33,13 @@
 import com.android.credentialmanager.ui.components.SignInOptionsChip
 import com.android.credentialmanager.ui.screens.single.SingleAccountScreen
 import com.android.credentialmanager.model.get.CredentialEntryInfo
+import com.android.credentialmanager.ui.components.BottomSpacer
+import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer
 import com.google.android.horologist.annotations.ExperimentalHorologistApi
 import com.google.android.horologist.compose.layout.ScalingLazyColumnState
 
 /**
- * Screen that shows sign in with provider credential.
+ * Screen that shows password credential.
  *
  * @param entry The password entry.
  * @param columnState ScalingLazyColumn configuration to be be applied to SingleAccountScreen
@@ -49,7 +51,6 @@
 fun SinglePasswordScreen(
     entry: CredentialEntryInfo,
     columnState: ScalingLazyColumnState,
-    modifier: Modifier = Modifier,
     flowEngine: FlowEngine,
 ) {
     val selectEntry = flowEngine.getEntrySelector()
@@ -63,17 +64,19 @@
         accountContent = {
             PasswordRow(
                 email = entry.userName,
-                modifier = Modifier.padding(top = 10.dp),
             )
         },
         columnState = columnState,
-        modifier = modifier.padding(horizontal = 10.dp)
+        modifier = Modifier.padding(horizontal = 10.dp)
     ) {
         item {
             Column {
                 ContinueChip { selectEntry(entry, false) }
+                CredentialsScreenChipSpacer()
                 SignInOptionsChip{ flowEngine.openSecondaryScreen() }
+                CredentialsScreenChipSpacer()
                 DismissChip { flowEngine.cancel() }
+                BottomSpacer()
             }
         }
     }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt
index 3a86feb..34d6e97 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/signInWithProvider/SignInWithProviderScreen.kt
@@ -24,7 +24,9 @@
 import com.android.credentialmanager.FlowEngine
 import com.android.credentialmanager.model.get.CredentialEntryInfo
 import com.android.credentialmanager.ui.components.AccountRow
+import com.android.credentialmanager.ui.components.BottomSpacer
 import com.android.credentialmanager.ui.components.ContinueChip
+import com.android.credentialmanager.ui.components.CredentialsScreenChipSpacer
 import com.android.credentialmanager.ui.components.DismissChip
 import com.android.credentialmanager.ui.components.SignInHeader
 import com.android.credentialmanager.ui.components.SignInOptionsChip
@@ -35,7 +37,7 @@
 /**
  * Screen that shows sign in with provider credential.
  *
- * @param entry The password entry.
+ * @param entry The custom credential entry.
  * @param columnState ScalingLazyColumn configuration to be be applied to SingleAccountScreen
  * @param modifier styling for composable
  * @param flowEngine [FlowEngine] that updates ui state for this screen
@@ -57,16 +59,15 @@
         },
         accountContent = {
             val displayName = entry.displayName
-            if (displayName != null) {
+            if (displayName == null ||
+                entry.displayName.equals(entry.userName, ignoreCase = true)) {
                 AccountRow(
-                    primaryText = displayName,
-                    secondaryText = entry.userName,
-                    modifier = Modifier.padding(top = 10.dp),
+                    primaryText = entry.userName,
                 )
             } else {
                 AccountRow(
-                    primaryText = entry.userName,
-                    modifier = Modifier.padding(top = 10.dp),
+                    primaryText = displayName,
+                    secondaryText = entry.userName,
                 )
             }
         },
@@ -77,8 +78,11 @@
             val selectEntry = flowEngine.getEntrySelector()
             Column {
                 ContinueChip { selectEntry(entry, false) }
+                CredentialsScreenChipSpacer()
                 SignInOptionsChip{ flowEngine.openSecondaryScreen() }
+                CredentialsScreenChipSpacer()
                 DismissChip { flowEngine.cancel() }
+                BottomSpacer()
             }
         }
     }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialSelectorTheme.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialSelectorTheme.kt
new file mode 100644
index 0000000..ee0ba7b
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialSelectorTheme.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.credentialmanager.ui.theme
+
+import android.content.Context
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.annotation.StringRes
+import androidx.wear.compose.material.Colors
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.font.DeviceFontFamilyName
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.font.FontFamily
+import androidx.wear.compose.material.Typography
+import androidx.wear.compose.material.MaterialTheme
+import com.android.credentialmanager.R
+import androidx.compose.ui.graphics.Color
+
+/** The Material 3 Theme Wrapper for Supporting RRO. */
+@Composable
+fun WearCredentialSelectorTheme(content: @Composable () -> Unit) {
+    val context = LocalContext.current
+    val colors =
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+            overlayColors(context)
+                .copy(error = MaterialTheme.colors.error, onError = MaterialTheme.colors.onError)
+        } else {
+            MaterialTheme.colors
+        }
+    MaterialTheme(colors = colors, typography = deviceDefaultTypography(context), content = content)
+}
+
+/**
+ * Creates a dynamic color maps that can be overlaid. 100 - Lightest shade; 0 - Darkest Shade; In
+ * wear we only support dark theme for the time being. Thus the fill colors and variants are dark
+ * and anything on top is light. We will use this custom redirection until wear compose material
+ * supports color scheming.
+ *
+ * The mapping is best case match on wear material color tokens from
+ * /android/clockwork/common/wearable/wearmaterial/color/res/values/color-tokens.xml
+ *
+ * @param context The context required to get system resource data.
+ */
+@RequiresApi(Build.VERSION_CODES.S)
+internal fun overlayColors(context: Context): Colors {
+    val tonalPalette = dynamicTonalPalette(context)
+    return Colors(
+        background = Color.Black,
+        onBackground = Color.White,
+        primary = tonalPalette.primary90,
+        primaryVariant = tonalPalette.primary80,
+        onPrimary = tonalPalette.primary10,
+        secondary = tonalPalette.tertiary90,
+        secondaryVariant = tonalPalette.tertiary60,
+        onSecondary = tonalPalette.tertiary10,
+        surface = tonalPalette.neutral20,
+        onSurface = tonalPalette.neutral95,
+        onSurfaceVariant = tonalPalette.neutralVariant80,
+    )
+}
+
+private fun fontFamily(context: Context, @StringRes id: Int): FontFamily {
+    val typefaceName = context.resources.getString(id)
+    val font = Font(familyName = DeviceFontFamilyName(typefaceName))
+    return FontFamily(font)
+}
+
+/*
+ Only customizes font family. The material 3 roles to 2.5 are mapped to the best case matching of
+ google3/java/com/google/android/wearable/libraries/compose/theme/GoogleMaterialTheme.kt
+*/
+internal fun deviceDefaultTypography(context: Context): Typography {
+    val defaultTypography = Typography()
+    return Typography(
+        display1 =
+        defaultTypography.display1.copy(
+            fontFamily =
+            fontFamily(context, R.string.wear_material_compose_display_1_font_family)
+        ),
+        display2 =
+        defaultTypography.display2.copy(
+            fontFamily =
+            fontFamily(context, R.string.wear_material_compose_display_2_font_family)
+        ),
+        display3 =
+        defaultTypography.display1.copy(
+            fontFamily =
+            fontFamily(context, R.string.wear_material_compose_display_3_font_family)
+        ),
+        title1 =
+        defaultTypography.title1.copy(
+            fontFamily = fontFamily(context, R.string.wear_material_compose_title_1_font_family)
+        ),
+        title2 =
+        defaultTypography.title2.copy(
+            fontFamily = fontFamily(context, R.string.wear_material_compose_title_2_font_family)
+        ),
+        title3 =
+        defaultTypography.title3.copy(
+            fontFamily = fontFamily(context, R.string.wear_material_compose_title_3_font_family)
+        ),
+        body1 =
+        defaultTypography.body1.copy(
+            fontFamily = fontFamily(context, R.string.wear_material_compose_body_1_font_family)
+        ),
+        body2 =
+        defaultTypography.body2.copy(
+            fontFamily = fontFamily(context, R.string.wear_material_compose_body_2_font_family)
+        ),
+        button =
+        defaultTypography.button.copy(
+            fontFamily = fontFamily(context, R.string.wear_material_compose_button_font_family)
+        ),
+        caption1 =
+        defaultTypography.caption1.copy(
+            fontFamily =
+            fontFamily(context, R.string.wear_material_compose_caption_1_font_family)
+        ),
+        caption2 =
+        defaultTypography.caption2.copy(
+            fontFamily =
+            fontFamily(context, R.string.wear_material_compose_caption_2_font_family)
+        ),
+        caption3 =
+        defaultTypography.caption3.copy(
+            fontFamily =
+            fontFamily(context, R.string.wear_material_compose_caption_3_font_family)
+        ),
+    )
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialTonalPalette.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialTonalPalette.kt
new file mode 100644
index 0000000..1d6ed33
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/theme/WearCredentialTonalPalette.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.credentialmanager.ui.theme
+
+import android.R
+import android.content.Context
+import android.os.Build
+import androidx.annotation.ColorRes
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
+
+import androidx.compose.ui.graphics.Color
+
+/**
+ * Tonal Palette structure in Material.
+ *
+ * A tonal palette is comprised of 5 tonal ranges. Each tonal range includes the 13 stops, or tonal
+ * swatches.
+ *
+ * Tonal range names are:
+ * - Neutral (N)
+ * - Neutral variant (NV)
+ * - Primary (P)
+ * - Secondary (S)
+ * - Tertiary (T)
+ */
+internal class WearCredentialSelectorTonalPalette(
+    // The neutral tonal range.
+    val neutral100: Color,
+    val neutral99: Color,
+    val neutral95: Color,
+    val neutral90: Color,
+    val neutral80: Color,
+    val neutral70: Color,
+    val neutral60: Color,
+    val neutral50: Color,
+    val neutral40: Color,
+    val neutral30: Color,
+    val neutral20: Color,
+    val neutral10: Color,
+    val neutral0: Color,
+
+    // The neutral variant tonal range, sometimes called "neutral 2"
+    val neutralVariant100: Color,
+    val neutralVariant99: Color,
+    val neutralVariant95: Color,
+    val neutralVariant90: Color,
+    val neutralVariant80: Color,
+    val neutralVariant70: Color,
+    val neutralVariant60: Color,
+    val neutralVariant50: Color,
+    val neutralVariant40: Color,
+    val neutralVariant30: Color,
+    val neutralVariant20: Color,
+    val neutralVariant10: Color,
+    val neutralVariant0: Color,
+
+    // The primary tonal range, also known as accent 1
+    val primary100: Color,
+    val primary99: Color,
+    val primary95: Color,
+    val primary90: Color,
+    val primary80: Color,
+    val primary70: Color,
+    val primary60: Color,
+    val primary50: Color,
+    val primary40: Color,
+    val primary30: Color,
+    val primary20: Color,
+    val primary10: Color,
+    val primary0: Color,
+
+    // The Secondary tonal range, also know as accent 2
+    val secondary100: Color,
+    val secondary99: Color,
+    val secondary95: Color,
+    val secondary90: Color,
+    val secondary80: Color,
+    val secondary70: Color,
+    val secondary60: Color,
+    val secondary50: Color,
+    val secondary40: Color,
+    val secondary30: Color,
+    val secondary20: Color,
+    val secondary10: Color,
+    val secondary0: Color,
+
+    // The tertiary tonal range, also known as accent 3
+    val tertiary100: Color,
+    val tertiary99: Color,
+    val tertiary95: Color,
+    val tertiary90: Color,
+    val tertiary80: Color,
+    val tertiary70: Color,
+    val tertiary60: Color,
+    val tertiary50: Color,
+    val tertiary40: Color,
+    val tertiary30: Color,
+    val tertiary20: Color,
+    val tertiary10: Color,
+    val tertiary0: Color,
+)
+/** Dynamic colors for wear compose material to support resource overlay. */
+@RequiresApi(Build.VERSION_CODES.S)
+// TODO: once we have proper support for this on Wear 6+, we will do something similar to
+// https://source.corp.google.com/h/android/platform/superproject/+/androidx-main:frameworks/support/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt;l=307-362?q=dynamicTonalPalette&sq=repo:android%2Fplatform%2Fsuperproject%20b:androidx-main
+// Tracking Bug: b/270720571
+internal fun dynamicTonalPalette(context: Context) =
+    WearCredentialSelectorTonalPalette(
+        // The neutral tonal range from the generated dynamic color palette.
+        neutral100 = ColorResourceHelper.getColor(context, R.color.system_neutral1_0),
+        neutral99 = ColorResourceHelper.getColor(context, R.color.system_neutral1_10),
+        neutral95 = ColorResourceHelper.getColor(context, R.color.system_neutral1_50),
+        neutral90 = ColorResourceHelper.getColor(context, R.color.system_neutral1_100),
+        neutral80 = ColorResourceHelper.getColor(context, R.color.system_neutral1_200),
+        neutral70 = ColorResourceHelper.getColor(context, R.color.system_neutral1_300),
+        neutral60 = ColorResourceHelper.getColor(context, R.color.system_neutral1_400),
+        neutral50 = ColorResourceHelper.getColor(context, R.color.system_neutral1_500),
+        neutral40 = ColorResourceHelper.getColor(context, R.color.system_neutral1_600),
+        neutral30 = ColorResourceHelper.getColor(context, R.color.system_neutral1_700),
+        neutral20 = ColorResourceHelper.getColor(context, R.color.system_neutral1_800),
+        neutral10 = ColorResourceHelper.getColor(context, R.color.system_neutral1_900),
+        neutral0 = ColorResourceHelper.getColor(context, R.color.system_neutral1_1000),
+
+        // The neutral variant tonal range, sometimes called "neutral 2",  from the
+        // generated dynamic color palette.
+        neutralVariant100 = ColorResourceHelper.getColor(context, R.color.system_neutral2_0),
+        neutralVariant99 = ColorResourceHelper.getColor(context, R.color.system_neutral2_10),
+        neutralVariant95 = ColorResourceHelper.getColor(context, R.color.system_neutral2_50),
+        neutralVariant90 = ColorResourceHelper.getColor(context, R.color.system_neutral2_100),
+        neutralVariant80 = ColorResourceHelper.getColor(context, R.color.system_neutral2_200),
+        neutralVariant70 = ColorResourceHelper.getColor(context, R.color.system_neutral2_300),
+        neutralVariant60 = ColorResourceHelper.getColor(context, R.color.system_neutral2_400),
+        neutralVariant50 = ColorResourceHelper.getColor(context, R.color.system_neutral2_500),
+        neutralVariant40 = ColorResourceHelper.getColor(context, R.color.system_neutral2_600),
+        neutralVariant30 = ColorResourceHelper.getColor(context, R.color.system_neutral2_700),
+        neutralVariant20 = ColorResourceHelper.getColor(context, R.color.system_neutral2_800),
+        neutralVariant10 = ColorResourceHelper.getColor(context, R.color.system_neutral2_900),
+        neutralVariant0 = ColorResourceHelper.getColor(context, R.color.system_neutral2_1000),
+
+        // The primary tonal range from the generated dynamic color palette.
+        primary100 = ColorResourceHelper.getColor(context, R.color.system_accent1_0),
+        primary99 = ColorResourceHelper.getColor(context, R.color.system_accent1_10),
+        primary95 = ColorResourceHelper.getColor(context, R.color.system_accent1_50),
+        primary90 = ColorResourceHelper.getColor(context, R.color.system_accent1_100),
+        primary80 = ColorResourceHelper.getColor(context, R.color.system_accent1_200),
+        primary70 = ColorResourceHelper.getColor(context, R.color.system_accent1_300),
+        primary60 = ColorResourceHelper.getColor(context, R.color.system_accent1_400),
+        primary50 = ColorResourceHelper.getColor(context, R.color.system_accent1_500),
+        primary40 = ColorResourceHelper.getColor(context, R.color.system_accent1_600),
+        primary30 = ColorResourceHelper.getColor(context, R.color.system_accent1_700),
+        primary20 = ColorResourceHelper.getColor(context, R.color.system_accent1_800),
+        primary10 = ColorResourceHelper.getColor(context, R.color.system_accent1_900),
+        primary0 = ColorResourceHelper.getColor(context, R.color.system_accent1_1000),
+
+        // The secondary tonal range from the generated dynamic color palette.
+        secondary100 = ColorResourceHelper.getColor(context, R.color.system_accent2_0),
+        secondary99 = ColorResourceHelper.getColor(context, R.color.system_accent2_10),
+        secondary95 = ColorResourceHelper.getColor(context, R.color.system_accent2_50),
+        secondary90 = ColorResourceHelper.getColor(context, R.color.system_accent2_100),
+        secondary80 = ColorResourceHelper.getColor(context, R.color.system_accent2_200),
+        secondary70 = ColorResourceHelper.getColor(context, R.color.system_accent2_300),
+        secondary60 = ColorResourceHelper.getColor(context, R.color.system_accent2_400),
+        secondary50 = ColorResourceHelper.getColor(context, R.color.system_accent2_500),
+        secondary40 = ColorResourceHelper.getColor(context, R.color.system_accent2_600),
+        secondary30 = ColorResourceHelper.getColor(context, R.color.system_accent2_700),
+        secondary20 = ColorResourceHelper.getColor(context, R.color.system_accent2_800),
+        secondary10 = ColorResourceHelper.getColor(context, R.color.system_accent2_900),
+        secondary0 = ColorResourceHelper.getColor(context, R.color.system_accent2_1000),
+
+        // The tertiary tonal range from the generated dynamic color palette.
+        tertiary100 = ColorResourceHelper.getColor(context, R.color.system_accent3_0),
+        tertiary99 = ColorResourceHelper.getColor(context, R.color.system_accent3_10),
+        tertiary95 = ColorResourceHelper.getColor(context, R.color.system_accent3_50),
+        tertiary90 = ColorResourceHelper.getColor(context, R.color.system_accent3_100),
+        tertiary80 = ColorResourceHelper.getColor(context, R.color.system_accent3_200),
+        tertiary70 = ColorResourceHelper.getColor(context, R.color.system_accent3_300),
+        tertiary60 = ColorResourceHelper.getColor(context, R.color.system_accent3_400),
+        tertiary50 = ColorResourceHelper.getColor(context, R.color.system_accent3_500),
+        tertiary40 = ColorResourceHelper.getColor(context, R.color.system_accent3_600),
+        tertiary30 = ColorResourceHelper.getColor(context, R.color.system_accent3_700),
+        tertiary20 = ColorResourceHelper.getColor(context, R.color.system_accent3_800),
+        tertiary10 = ColorResourceHelper.getColor(context, R.color.system_accent3_900),
+        tertiary0 = ColorResourceHelper.getColor(context, R.color.system_accent3_1000),
+    )
+
+private object ColorResourceHelper {
+    @DoNotInline
+    fun getColor(context: Context, @ColorRes id: Int): Color {
+        return Color(context.resources.getColor(id, context.theme))
+    }
+}
\ No newline at end of file
diff --git a/packages/EasterEgg/Android.bp b/packages/EasterEgg/Android.bp
index 6f4f9ca..ec1fe39 100644
--- a/packages/EasterEgg/Android.bp
+++ b/packages/EasterEgg/Android.bp
@@ -83,6 +83,7 @@
 aconfig_declarations {
     name: "easter_egg_flags",
     package: "com.android.egg.flags",
+    container: "system",
     srcs: [
         "easter_egg_flags.aconfig",
     ],
diff --git a/packages/EasterEgg/easter_egg_flags.aconfig b/packages/EasterEgg/easter_egg_flags.aconfig
index 3268a4f..7ddc238 100644
--- a/packages/EasterEgg/easter_egg_flags.aconfig
+++ b/packages/EasterEgg/easter_egg_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.egg.flags"
+container: "system"
 
 flag {
     name: "flag_flag"
diff --git a/packages/InputDevices/res/raw/keyboard_layout_french.kcm b/packages/InputDevices/res/raw/keyboard_layout_french.kcm
index 636f98d..4f4fb1b 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_french.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_french.kcm
@@ -35,85 +35,97 @@
 }
 
 key 1 {
-    label:                              '1'
+    label:                              '&'
     base:                               '&'
-    shift:                              '1'
+    shift, capslock:                    '1'
+    shift+capslock:                     '&'
 }
 
 key 2 {
-    label:                              '2'
+    label:                              '\u00e9'
     base:                               '\u00e9'
-    shift:                              '2'
+    shift, capslock:                    '2'
+    shift+capslock:                     '\u00e9'
     ralt:                               '\u0303'
 }
 
 key 3 {
-    label:                              '3'
+    label:                              '"'
     base:                               '"'
-    shift:                              '3'
+    shift, capslock:                    '3'
+    shift+capslock:                     '"'
     ralt:                               '#'
 }
 
 key 4 {
-    label:                              '4'
+    label:                              '\''
     base:                               '\''
-    shift:                              '4'
+    shift, capslock:                    '4'
+    shift+capslock:                     '\''
     ralt:                               '{'
 }
 
 key 5 {
-    label:                              '5'
+    label:                              '('
     base:                               '('
-    shift:                              '5'
+    shift, capslock:                    '5'
+    shift+capslock:                     '('
     ralt:                               '['
 }
 
 key 6 {
-    label:                              '6'
+    label:                              '-'
     base:                               '-'
-    shift:                              '6'
+    shift, capslock:                    '6'
+    shift+capslock:                     '-'
     ralt:                               '|'
 }
 
 key 7 {
-    label:                              '7'
+    label:                              '\u00e8'
     base:                               '\u00e8'
-    shift:                              '7'
+    shift, capslock:                    '7'
+    shift+capslock:                     '\u00e8'
     ralt:                               '\u0300'
 }
 
 key 8 {
-    label:                              '8'
+    label:                              '_'
     base:                               '_'
-    shift:                              '8'
+    shift, capslock:                    '8'
+    shift+capslock:                     '_'
     ralt:                               '\\'
 }
 
 key 9 {
-    label:                              '9'
+    label:                              '\u00e7'
     base:                               '\u00e7'
-    shift:                              '9'
+    shift, capslock:                    '9'
+    shift+capslock:                     '\u00e7'
     ralt:                               '^'
 }
 
 key 0 {
-    label:                              '0'
+    label:                              '\u00e0'
     base:                               '\u00e0'
-    shift:                              '0'
+    shift, capslock:                    '0'
+    shift+capslock:                     '\u00e0'
     ralt:                               '@'
 }
 
 key MINUS {
     label:                              ')'
     base:                               ')'
-    shift:                              '\u00b0'
+    shift, capslock:                    '\u00b0'
+    shift+capslock:                     ')'
     ralt:                               ']'
 }
 
 key EQUALS {
     label:                              '='
     base:                               '='
-    shift:                              '+'
+    shift, capslock:                    '+'
+    shift+capslock:                     '='
     ralt:                               '}'
 }
 
@@ -193,13 +205,15 @@
 key LEFT_BRACKET {
     label:                              '\u02c6'
     base:                               '\u0302'
-    shift:                              '\u0308'
+    shift, capslock:                    '\u0308'
+    shift+capslock:                     '\u0302'
 }
 
 key RIGHT_BRACKET {
     label:                              '$'
     base:                               '$'
-    shift:                              '\u00a3'
+    shift, capslock:                    '\u00a3'
+    shift+capslock:                     '$'
     ralt:                               '\u00a4'
 }
 
@@ -278,13 +292,15 @@
 key APOSTROPHE {
     label:                              '\u00f9'
     base:                               '\u00f9'
-    shift:                              '%'
+    shift, capslock:                    '%'
+    shift+capslock:                     '\u00f9'
 }
 
 key BACKSLASH {
     label:                              '*'
     base:                               '*'
-    shift:                              '\u00b5'
+    shift, capslock:                    '\u00b5'
+    shift+capslock:                     '*'
 }
 
 ### ROW 4
@@ -340,23 +356,27 @@
 key COMMA {
     label:                              ','
     base:                               ','
-    shift:                              '?'
+    shift, capslock:                    '?'
+    shift+capslock:                     ','
 }
 
 key SEMICOLON {
     label:                              ';'
     base:                               ';'
-    shift:                              '.'
+    shift, capslock:                    '.'
+    shift+capslock:                     ';'
 }
 
 key PERIOD {
     label:                              ':'
     base:                               ':'
-    shift:                              '/'
+    shift, capslock:                    '/'
+    shift+capslock:                     ':'
 }
 
 key SLASH {
     label:                              '!'
     base:                               '!'
-    shift:                              '\u00a7'
+    shift, capslock:                    '\u00a7'
+    shift+capslock:                     '!'
 }
diff --git a/packages/InputDevices/res/raw/keyboard_layout_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_german.kcm
index fbb9bb6..1fb0924 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_german.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_german.kcm
@@ -28,82 +28,93 @@
 
 key GRAVE {
     label:                              '^'
-    base:                               '^'
+    base:                               '\u0302'
     shift:                              '\u00b0'
 }
 
 key 1 {
     label:                              '1'
     base:                               '1'
-    shift:                              '!'
+    shift, capslock:                    '!'
+    shift+capslock:                     '1'
 }
 
 key 2 {
     label:                              '2'
     base:                               '2'
-    shift:                              '"'
+    shift, capslock:                    '"'
+    shift+capslock:                     '2'
     ralt:                               '\u00b2'
 }
 
 key 3 {
     label:                              '3'
     base:                               '3'
-    shift:                              '\u00a7'
+    shift, capslock:                    '\u00a7'
+    shift+capslock:                     '3'
     ralt:                               '\u00b3'
 }
 
 key 4 {
     label:                              '4'
     base:                               '4'
-    shift:                              '$'
+    shift, capslock:                    '$'
+    shift+capslock:                     '4'
 }
 
 key 5 {
     label:                              '5'
     base:                               '5'
-    shift:                              '%'
+    shift, capslock:                    '%'
+    shift+capslock:                     '5'
 }
 
 key 6 {
     label:                              '6'
     base:                               '6'
-    shift:                              '&'
+    shift, capslock:                    '&'
+    shift+capslock:                     '6'
 }
 
 key 7 {
     label:                              '7'
     base:                               '7'
-    shift:                              '/'
+    shift, capslock:                    '/'
+    shift+capslock:                     '7'
     ralt:                               '{'
 }
 
 key 8 {
     label:                              '8'
     base:                               '8'
-    shift:                              '('
+    shift, capslock:                    '('
+    shift+capslock:                     '8'
     ralt:                               '['
 }
 
 key 9 {
     label:                              '9'
     base:                               '9'
-    shift:                              ')'
+    shift, capslock:                    ')'
+    shift+capslock:                     '9'
     ralt:                               ']'
 }
 
 key 0 {
     label:                              '0'
     base:                               '0'
-    shift:                              '='
+    shift, capslock:                    '='
+    shift+capslock:                     '0'
     ralt:                               '}'
 }
 
 key SLASH {
     label:                              '\u00df'
     base:                               '\u00df'
-    capslock:                           '\u1e9e'
-    shift:                              '?'
+    shift, capslock:                    '?'
+    shift+capslock:                     '\u00df'
     ralt:                               '\\'
+    shift+ralt:                         '\u1e9e'
 }
 
 key EQUALS {
@@ -196,7 +207,8 @@
 key RIGHT_BRACKET {
     label:                              '+'
     base:                               '+'
-    shift:                              '*'
+    shift, capslock:                    '*'
+    shift+capslock:                     '+'
     ralt:                               '~'
 }
 
@@ -282,7 +294,8 @@
 key BACKSLASH {
     label:                              '#'
     base:                               '#'
-    shift:                              '\''
+    shift, capslock:                    '\''
+    shift+capslock:                     '#'
 }
 
 ### ROW 4
@@ -347,13 +360,15 @@
 key COMMA {
     label:                              ','
     base:                               ','
-    shift:                              ';'
+    shift, capslock:                    ';'
+    shift+capslock:                     ','
 }
 
 key PERIOD {
     label:                              '.'
     base:                               '.'
-    shift:                              ':'
+    shift, capslock:                    ':'
+    shift+capslock:                     '.'
 }
 
 key MINUS {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_thai_kedmanee.kcm b/packages/InputDevices/res/raw/keyboard_layout_thai_kedmanee.kcm
new file mode 100644
index 0000000..2283032
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_thai_kedmanee.kcm
@@ -0,0 +1,321 @@
+# Copyright 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Thai Kedmanee keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '_'
+    base:                               '_'
+    shift, capslock:                    '%'
+}
+
+key 1 {
+    label:                              '\u0e45'
+    base:                               '\u0e45'
+    shift, capslock:                    '+'
+}
+
+key 2 {
+    label:                              '/'
+    base:                               '/'
+    shift, capslock:                    '\u0e51'
+}
+
+key 3 {
+    label:                              '-'
+    base:                               '-'
+    shift, capslock:                    '\u0e52'
+}
+
+key 4 {
+    label:                              '\u0e20'
+    base:                               '\u0e20'
+    shift, capslock:                    '\u0e53'
+}
+
+key 5 {
+    label:                              '\u0e16'
+    base:                               '\u0e16'
+    shift, capslock:                    '\u0e54'
+}
+
+key 6 {
+    label:                              '\u0e38'
+    base:                               '\u0e38'
+    shift, capslock:                    '\u0e39'
+}
+
+key 7 {
+    label:                              '\u0e36'
+    base:                               '\u0e36'
+    shift, capslock:                    '\u0e3f'
+}
+
+key 8 {
+    label:                              '\u0e04'
+    base:                               '\u0e04'
+    shift, capslock:                    '\u0e55'
+}
+
+key 9 {
+    label:                              '\u0e15'
+    base:                               '\u0e15'
+    shift, capslock:                    '\u0e56'
+}
+
+key 0 {
+    label:                              '\u0e08'
+    base:                               '\u0e08'
+    shift, capslock:                    '\u0e57'
+}
+
+key MINUS {
+    label:                              '\u0e02'
+    base:                               '\u0e02'
+    shift, capslock:                    '\u0e58'
+}
+
+key EQUALS {
+    label:                              '\u0e0a'
+    base:                               '\u0e0a'
+    shift, capslock:                    '\u0e59'
+}
+
+### ROW 2
+
+key Q {
+    label:                              '\u0e46'
+    base:                               '\u0e46'
+    shift, capslock:                    '\u0e50'
+}
+
+key W {
+    label:                              '\u0e44'
+    base:                               '\u0e44'
+    shift, capslock:                    '\u0022'
+}
+
+key E {
+    label:                              '\u0e33'
+    base:                               '\u0e33'
+    shift, capslock:                    '\u0e0e'
+}
+
+key R {
+    label:                              '\u0e1e'
+    base:                               '\u0e1e'
+    shift, capslock:                    '\u0e11'
+}
+
+key T {
+    label:                              '\u0e30'
+    base:                               '\u0e30'
+    shift, capslock:                    '\u0e18'
+}
+
+key Y {
+    label:                              '\u0e31'
+    base:                               '\u0e31'
+    shift, capslock:                    '\u0e4d'
+}
+
+key U {
+    label:                              '\u0e35'
+    base:                               '\u0e35'
+    shift, capslock:                    '\u0e4a'
+}
+
+key I {
+    label:                              '\u0e23'
+    base:                               '\u0e23'
+    shift, capslock:                    '\u0e13'
+}
+
+key O {
+    label:                              '\u0e19'
+    base:                               '\u0e19'
+    shift, capslock:                    '\u0e2f'
+}
+
+key P {
+    label:                              '\u0e22'
+    base:                               '\u0e22'
+    shift, capslock:                    '\u0e0d'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u0e1a'
+    base:                               '\u0e1a'
+    shift, capslock:                    '\u0e10'
+    ctrl:                               '%'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u0e25'
+    base:                               '\u0e25'
+    shift, capslock:                    ','
+    ctrl:                               '\u0e51'
+}
+
+### ROW 3
+
+key A {
+    label:                              '\u0e1f'
+    base:                               '\u0e1f'
+    shift, capslock:                    '\u0e24'
+}
+
+key S {
+    label:                              '\u0e2b'
+    base:                               '\u0e2b'
+    shift, capslock:                    '\u0e06'
+}
+
+key D {
+    label:                              '\u0e01'
+    base:                               '\u0e01'
+    shift, capslock:                    '\u0e0f'
+}
+
+key F {
+    label:                              '\u0e14'
+    base:                               '\u0e14'
+    shift, capslock:                    '\u0e42'
+}
+
+key G {
+    label:                              '\u0e40'
+    base:                               '\u0e40'
+    shift, capslock:                    '\u0e0c'
+}
+
+key H {
+    label:                              '\u0e49'
+    base:                               '\u0e49'
+    shift, capslock:                    '\u0e47'
+}
+
+key J {
+    label:                              '\u0e48'
+    base:                               '\u0e48'
+    shift, capslock:                    '\u0e4b'
+}
+
+key K {
+    label:                              '\u0e32'
+    base:                               '\u0e32'
+    shift, capslock:                    '\u0e29'
+}
+
+key L {
+    label:                              '\u0e2a'
+    base:                               '\u0e2a'
+    shift, capslock:                    '\u0e28'
+}
+
+key SEMICOLON {
+    label:                              '\u0e27'
+    base:                               '\u0e27'
+    shift, capslock:                    '\u0e0b'
+}
+
+key APOSTROPHE {
+    label:                              '\u0e07'
+    base:                               '\u0e07'
+    shift, capslock:                    '.'
+}
+
+key BACKSLASH {
+    label:                              '\u0e03'
+    base:                               '\u0e03'
+    shift, capslock:                    '\u0e05'
+    ctrl:                               '+'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\u0e03'
+    base:                               '\u0e03'
+    shift, capslock:                    '\u0e05'
+    ctrl:                               '\u0e52'
+}
+
+key Z {
+    label:                              '\u0e1c'
+    base:                               '\u0e1c'
+    shift, capslock:                    '('
+}
+
+key X {
+    label:                              '\u0e1b'
+    base:                               '\u0e1b'
+    shift, capslock:                    ')'
+}
+
+key C {
+    label:                              '\u0e41'
+    base:                               '\u0e41'
+    shift, capslock:                    '\u0e09'
+}
+
+key V {
+    label:                              '\u0e2d'
+    base:                               '\u0e2d'
+    shift, capslock:                    '\u0e2e'
+}
+
+key B {
+    label:                              '\u0e34'
+    base:                               '\u0e34'
+    shift, capslock:                    '\u0e3a'
+}
+
+key N {
+    label:                              '\u0e37'
+    base:                               '\u0e37'
+    shift, capslock:                    '\u0e4c'
+}
+
+key M {
+    label:                              '\u0e17'
+    base:                               '\u0e17'
+    shift, capslock:                    '?'
+}
+
+key COMMA {
+    label:                              '\u0e21'
+    base:                               '\u0e21'
+    shift, capslock:                    '\u0e12'
+}
+
+key PERIOD {
+    label:                              '\u0e43'
+    base:                               '\u0e43'
+    shift, capslock:                    '\u0e2c'
+}
+
+key SLASH {
+    label:                              '\u0e1d'
+    base:                               '\u0e1d'
+    shift, capslock:                    '\u0e26'
+}
\ No newline at end of file
diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index 7208894..72bb640 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarussies"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgies"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index 1698150..0eea57b 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ቤላሩስኛ"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ሞንጎሊያኛ"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ጂዮርጂያኛ"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ታይላንድኛ (ኬድማኒ)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index 8ed1972..88be85a 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"البيلاروسية"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"المنغولية"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"الجورجية"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"‏التايلاندية (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
index 9744a7d..3cd707f 100644
--- a/packages/InputDevices/res/values-as/strings.xml
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"বেলাৰুছিয়ান"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"থাই (কেডমানি)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml
index ee3a337..332fd1c 100644
--- a/packages/InputDevices/res/values-az/strings.xml
+++ b/packages/InputDevices/res/values-az/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarus dili"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Monqol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcü"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tay (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-b+sr+Latn/strings.xml b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
index 1fc84f3..a7ede75 100644
--- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml
+++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"beloruski"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolska"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijska"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajski (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml
index 50c5910..011ad66 100644
--- a/packages/InputDevices/res/values-be/strings.xml
+++ b/packages/InputDevices/res/values-be/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Беларуская"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Мангольская"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузінская"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайская (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 1ee9565..68f120a 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"беларуски"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузински"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тайландски (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml
index a996538..74b2462 100644
--- a/packages/InputDevices/res/values-bn/strings.xml
+++ b/packages/InputDevices/res/values-bn/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"বেলারুশীয়"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"মঙ্গোলিয়ান"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"জর্জিয়ান"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"থাই (কেডমানি)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml
index c6cacbc..ea8d91e 100644
--- a/packages/InputDevices/res/values-bs/strings.xml
+++ b/packages/InputDevices/res/values-bs/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"bjeloruska"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzijski"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajlandski (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 761c248..573e325 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorús"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgià"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index 3f1b3d0..331da96 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"běloruština"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolština"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínština"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thajština (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index b160341..e399f2c 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Hviderussisk"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index 17d6e4a..75fb724 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarussisch"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisch"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailändisch (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index 1b9b42e..1510708 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Λευκορωσικά"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Μογγολικά"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Γεωργιανά"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Ταϊλανδικά (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml
index ab48729..6db501e 100644
--- a/packages/InputDevices/res/values-en-rAU/strings.xml
+++ b/packages/InputDevices/res/values-en-rAU/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml
index 1161783..ac8ad0a 100644
--- a/packages/InputDevices/res/values-en-rCA/strings.xml
+++ b/packages/InputDevices/res/values-en-rCA/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index ab48729..6db501e 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index ab48729..6db501e 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml
index 92c5a5c..159b0e0f 100644
--- a/packages/InputDevices/res/values-en-rXC/strings.xml
+++ b/packages/InputDevices/res/values-en-rXC/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‎‏‎‎‎Belarusian‎‏‎‎‏‎"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎Mongolian‎‏‎‎‏‎"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎Georgian‎‏‎‎‏‎"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎Thai (Kedmanee)‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index b9fe046..755491e 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -4,7 +4,7 @@
     <string name="app_label" msgid="8016145283189546017">"Dispositivos de entrada"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Teclado de Android"</string>
     <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Inglés (Reino Unido)"</string>
-    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglés (EE. UU.)"</string>
+    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglés (EE.UU.)"</string>
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglés (EE. UU.), internacional"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglés (EE. UU.), Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglés (EE. UU.), Dvorak"</string>
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorruso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index 216e79f..9387812 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorruso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml
index 87c486f..1543669 100644
--- a/packages/InputDevices/res/values-et/strings.xml
+++ b/packages/InputDevices/res/values-et/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"valgevene"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruusia"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 64628a82..098ed6f 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusiarra"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliarra"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiarra"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailandiarra (kedmanee-a)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index a086060..67bdfc8 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"بلاروسی"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"مغولی"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"گرجستانی"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"تایلندی (کدمانی)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index f3bef4d..567c416 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"valkovenäjä"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoli"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgia"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thai (kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index 63635824..c03fd6d 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Biélorusse"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thaï (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 37cde05..8c70b0d 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Biélorusse"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Géorgien"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thaï (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml
index 9995f79..897f7d2 100644
--- a/packages/InputDevices/res/values-gl/strings.xml
+++ b/packages/InputDevices/res/values-gl/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belaruso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Xeorxiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandés (kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml
index 9dfda76..3627c5c 100644
--- a/packages/InputDevices/res/values-gu/strings.xml
+++ b/packages/InputDevices/res/values-gu/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"બેલારુશિયન"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"મોંગોલિયન"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"જ્યોર્જિઅન"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"થાઇ (કેડમાની)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index 25628543..4fbcde0 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"बेलारूसी"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन कीबोर्ड का लेआउट"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमेनी)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index 6832437..c5f46c4 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"bjeloruski"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolski"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzijska"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajlandski (kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index f2ac8a2..a02f934 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"belarusz"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"grúz"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thai (kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index a6676fe..cf0a9c7 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"բելառուսերեն"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Մոնղոլերեն"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"վրացերեն"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"թայերեն (քեդմանի)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index 92bd24d..5ac0439 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusia"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolia"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgia"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml
index b761a7e..d25497c 100644
--- a/packages/InputDevices/res/values-is/strings.xml
+++ b/packages/InputDevices/res/values-is/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"hvítrússneska"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongólska"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgíska"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Taílenskt (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index a992b86..ae86156 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorusso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolo"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index de9b276..9eed7be 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"בלארוסית"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"מונגולית"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"גיאורגית"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"‏תאית (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 6be0b4c..297f351 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ベラルーシ語"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"モンゴル語"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ジョージア語"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"タイ語(Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml
index 92d9470..c471c44 100644
--- a/packages/InputDevices/res/values-ka/strings.xml
+++ b/packages/InputDevices/res/values-ka/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ბელორუსული"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"მონღოლური"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ქართული"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ტაილანდური (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml
index c8ab796..4c7779e 100644
--- a/packages/InputDevices/res/values-kk/strings.xml
+++ b/packages/InputDevices/res/values-kk/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Белорус"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Моңғол"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузин"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тай (кедмани)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml
index fd63ab33c..d43fe36 100644
--- a/packages/InputDevices/res/values-km/strings.xml
+++ b/packages/InputDevices/res/values-km/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"បេឡារុស"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"មុងហ្គោលី"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ហ្សក​ហ្ស៊ី"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ថៃ (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml
index 761b7cc..5fd766f 100644
--- a/packages/InputDevices/res/values-kn/strings.xml
+++ b/packages/InputDevices/res/values-kn/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ಬೆಲರೂಸಿಯನ್"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ಮಂಗೋಲಿಯನ್"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ಜಾರ್ಜಿಯನ್"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ಥಾಯ್ (ಕೆಡ್‍ಮನೀ)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index 2a1cbb0..6c06d2d 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"벨라루스어"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"몽골어"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"조지아어"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"태국어(Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml
index 70295e1..67047d3 100644
--- a/packages/InputDevices/res/values-ky/strings.xml
+++ b/packages/InputDevices/res/values-ky/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Беларусча"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монголчо"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинче"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайча (Kedmanee баскычтобу)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml
index 2b8946b..0ffa3ce 100644
--- a/packages/InputDevices/res/values-lo/strings.xml
+++ b/packages/InputDevices/res/values-lo/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ເບລາຣັສຊຽນ"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ມອງໂກລຽນ"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ຈໍຈຽນ"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ໄທ (ເກດມະນີ)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index 5fca46b..d6e20eb 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Baltarusių k."</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolų"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzinų"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tajų („Kedmanee“)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index d225329..254c70e 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Baltkrievu"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoļu"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzīnu"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Taju valoda (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml
index d98b58b..16df119 100644
--- a/packages/InputDevices/res/values-mk/strings.xml
+++ b/packages/InputDevices/res/values-mk/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"белоруски"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголски"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузиски"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тајландски (кедмани)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml
index f346881..59ee6e6 100644
--- a/packages/InputDevices/res/values-ml/strings.xml
+++ b/packages/InputDevices/res/values-ml/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ബെലാറുഷ്യൻ"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"മംഗോളിയൻ"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ജോര്‍ജ്ജിയൻ"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"തായ് (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml
index 1697097..f013532 100644
--- a/packages/InputDevices/res/values-mn/strings.xml
+++ b/packages/InputDevices/res/values-mn/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Беларусь хэл"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгол"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Гүрж"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тай (кедмани)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index 6382f6f..4dfdbf0 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"बेलारुशियन"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मंगोलियन"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"जॉर्जियन"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमानी)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml
index 9bff1713..6f8f171 100644
--- a/packages/InputDevices/res/values-ms/strings.xml
+++ b/packages/InputDevices/res/values-ms/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bahasa Belarus"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Bahasa Mongolia"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Bahasa Georgia"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml
index 01b5507..4d71a7b 100644
--- a/packages/InputDevices/res/values-my/strings.xml
+++ b/packages/InputDevices/res/values-my/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ဘီလာရုဇ်"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"မွန်ဂိုလီးယား"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ဂျော်ဂျီယာ"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ထိုင်း (ကတ်မနီး)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 40eb25a..8a1d653 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusisk"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml
index 6e98bf6..7a6cbe8 100644
--- a/packages/InputDevices/res/values-ne/strings.xml
+++ b/packages/InputDevices/res/values-ne/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"बेलारुसियाली"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"मङ्गोलियाली"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"जर्जियाली"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"थाई (केडमानी)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index f3a5814..bb8acd0 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Wit-Russisch"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongools"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisch"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
index 5b6aaea..d1c2ccc 100644
--- a/packages/InputDevices/res/values-or/strings.xml
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ବେଲାରୁସିଆନ୍"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ମଙ୍ଗୋଲିଆନ୍"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ଜର୍ଜିଆନ୍"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ଥାଇ (କେଡମାନି)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index 988b449..6725072f 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ਬੇਲਾਰੂਸੀ"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ਮੰਗੋਲੀਆਈ"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ਜਾਰਜੀਆਈ"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ਥਾਈ (ਕੇਦਮਨੀ)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 4d18215..31a3dac 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"białoruski"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolski"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruziński"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajski (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml
index e44f4ae..24db406 100644
--- a/packages/InputDevices/res/values-pt-rBR/strings.xml
+++ b/packages/InputDevices/res/values-pt-rBR/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 3ad3e63..2cc6a8c 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index e44f4ae..24db406 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusso"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiano"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tailandês (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 3867e1c..49cb306 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusă"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolă"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiană"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thailandeză (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 7c5c95a..d1fbfd6 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"белорусский"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монгольский"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузинский"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайский (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml
index f4147f3..e4e4791 100644
--- a/packages/InputDevices/res/values-si/strings.xml
+++ b/packages/InputDevices/res/values-si/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"බෙලරුසියානු"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"මොන්ගෝලියානු"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ජෝර්ජියානු"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"තායි (කෙඩ්මනී)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index 2a37552..ffe3c8d 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"bieloruské"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolské"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzínske"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"thajčina (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index 334326c..36f10c7 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"beloruščina"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongolščina"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"gruzinščina"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"tajščina (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml
index 0863138..51da8d7 100644
--- a/packages/InputDevices/res/values-sq/strings.xml
+++ b/packages/InputDevices/res/values-sq/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bjellorusisht"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolisht"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gjeorgjisht"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tajlandisht (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index 973b833..563fe4a 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"белоруски"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"монголска"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"грузијска"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"тајски (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index b1e5d75..878f1ed 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"vitryska"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"mongoliska"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"georgiska"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index 0f4c846..f8cf6c6 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Kibelarusi"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Kimongolia"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Kijojia"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Kithai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml
index d3535d4..e6edc61 100644
--- a/packages/InputDevices/res/values-ta/strings.xml
+++ b/packages/InputDevices/res/values-ta/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"பெலரூசியன்"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"மங்கோலியன்"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ஜார்ஜியன்"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"தாய் (கேட்மேனி)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml
index 5a10f6e..6ea08d3 100644
--- a/packages/InputDevices/res/values-te/strings.xml
+++ b/packages/InputDevices/res/values-te/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"బెలారష్యన్"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"మంగోలియన్"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"జార్జియన్"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"థాయ్ (కెడ్మనీ)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index 131c536..e3c4a7a 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"เบลารุส"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ภาษามองโกเลีย"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"ภาษาจอร์เจีย"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"ไทย (เกษมณี)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index c42adbc..c82a067 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index 1a84d0ac..74b77e7 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusça"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Moğolca"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gürcüce"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tayca (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index 71b3496..e78d826 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Білоруська"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Монгольська"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Грузинська"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Тайська (кедмані)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml
index 0cc9b61..644d364 100644
--- a/packages/InputDevices/res/values-ur/strings.xml
+++ b/packages/InputDevices/res/values-ur/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"بيلاروسی"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"منگؤلی"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"جارجیائی"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"تھائی (کیڈمینی)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml
index 52ecdfc..581dea5 100644
--- a/packages/InputDevices/res/values-uz/strings.xml
+++ b/packages/InputDevices/res/values-uz/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarus"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongol"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Gruzin"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tay (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index 0c638fa..d58ac65 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Tiếng Belarus"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Tiếng Mông Cổ"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Tiếng Georgia"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Tiếng Thái (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index b2497798..6a1a5b1 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"白俄罗斯语"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古语"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"格鲁吉亚语"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰语 (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index 60a52e9..4f761a4 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"白俄羅斯文"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"格魯吉亞文"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰文 (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index c3217e3..be56620 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"白俄羅斯文"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"蒙古文"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"喬治亞文"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"泰文 (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index 88d55f2..832ce1b 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -50,4 +50,5 @@
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusian"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"isi-Mongolian"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgian"</string>
+    <string name="keyboard_layout_thai_kedmanee" msgid="6637147314580760938">"Isi-Thai (Kedmanee)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 1e13940..33a1d76 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -146,4 +146,7 @@
 
     <!-- Georgian keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_georgian">Georgian</string>
+
+    <!-- Thai (Kedmanee variant) keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_thai_kedmanee">Thai (Kedmanee)</string>
 </resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index ee49b23..4b7ea90 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -318,4 +318,11 @@
         android:label="@string/keyboard_layout_georgian"
         android:keyboardLayout="@raw/keyboard_layout_georgian"
         android:keyboardLocale="ka-Geor" />
+
+    <keyboard-layout
+        android:name="keyboard_layout_thai_kedmanee"
+        android:label="@string/keyboard_layout_thai_kedmanee"
+        android:keyboardLayout="@raw/keyboard_layout_thai_kedmanee"
+        android:keyboardLocale="th-Thai"
+        android:keyboardLayoutType="extended" />
 </keyboard-layouts>
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index bf69d3b..4437475 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -23,6 +23,7 @@
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
+    <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
 
     <uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" />
 
diff --git a/packages/PackageInstaller/res/values-af/strings.xml b/packages/PackageInstaller/res/values-af/strings.xml
index 140fa36..13661e3 100644
--- a/packages/PackageInstaller/res/values-af/strings.xml
+++ b/packages/PackageInstaller/res/values-af/strings.xml
@@ -58,7 +58,7 @@
     <string name="uninstall_application_title" msgid="4045420072401428123">"Deïnstalleer program"</string>
     <string name="uninstall_update_title" msgid="824411791011583031">"Deïnstalleer opdatering"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is deel van die volgende program:"</string>
-    <string name="uninstall_application_text" msgid="3816830743706143980">"Wil jy hierdie program deïnstalleer?"</string>
+    <string name="uninstall_application_text" msgid="3816830743706143980">"Wil jy hierdie app deïnstalleer?"</string>
     <string name="archive_application_text" msgid="8482325710714386348">"Jou persoonlike data sal gestoor word"</string>
     <string name="archive_application_text_all_users" msgid="3151229641681672580">"Argiveer hierdie app vir alle gebruikers? Jou persoonlike data sal gestoor word"</string>
     <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Argiveer hierdie app op jou werkprofiel? Jou persoonlike data sal gestoor word"</string>
diff --git a/packages/PackageInstaller/res/values-gu/strings.xml b/packages/PackageInstaller/res/values-gu/strings.xml
index f642e145..82d5414 100644
--- a/packages/PackageInstaller/res/values-gu/strings.xml
+++ b/packages/PackageInstaller/res/values-gu/strings.xml
@@ -58,7 +58,7 @@
     <string name="uninstall_application_title" msgid="4045420072401428123">"ઍપ્લિકેશન અનઇન્સ્ટૉલ કરો"</string>
     <string name="uninstall_update_title" msgid="824411791011583031">"અપડેટ અનઇન્સ્ટૉલ કરો"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>, નીચેની ઍપ્લિકેશનનો ભાગ છે:"</string>
-    <string name="uninstall_application_text" msgid="3816830743706143980">"શું તમે આ ઍપને અનઇન્સ્ટૉલ કરવા માંગો છો?"</string>
+    <string name="uninstall_application_text" msgid="3816830743706143980">"શું તમે આ ઍપને અનઇન્સ્ટૉલ કરવા માગો છો?"</string>
     <string name="archive_application_text" msgid="8482325710714386348">"તમારો વ્યક્તિગત ડેટા સાચવવામાં આવશે"</string>
     <string name="archive_application_text_all_users" msgid="3151229641681672580">"શું આ ઍપને તમામ વપરાશકર્તાઓ માટે આર્કાઇવ કરીએ? તમારો વ્યક્તિગત ડેટા સાચવવામાં આવશે"</string>
     <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"શું આ ઍપને તમારી ઑફિસની પ્રોફાઇલ પર આર્કાઇવ કરીએ? તમારો વ્યક્તિગત ડેટા સાચવવામાં આવશે"</string>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
index f2bc41e..d9fb570 100644
--- a/packages/PackageInstaller/res/values-hy/strings.xml
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -58,7 +58,7 @@
     <string name="uninstall_application_title" msgid="4045420072401428123">"Հավելվածի ապատեղադրում"</string>
     <string name="uninstall_update_title" msgid="824411791011583031">"Ապատեղադրել թարմացումը"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> գործողությունը հետևյալ հավելվածի մասն է`"</string>
-    <string name="uninstall_application_text" msgid="3816830743706143980">"Ուզո՞ւմ եք ապատեղադրել այս հավելվածը։"</string>
+    <string name="uninstall_application_text" msgid="3816830743706143980">"Ուզում եք ապատեղադրե՞լ այս հավելվածը։"</string>
     <string name="archive_application_text" msgid="8482325710714386348">"Ձեր անձնական տվյալները կպահվեն"</string>
     <string name="archive_application_text_all_users" msgid="3151229641681672580">"Արխիվացնե՞լ այս հավելվածը բոլոր օգտատերերի համար։ Ձեր անձնական տվյալները կպահվեն"</string>
     <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Արխիվացնե՞լ այս հավելվածը ձեր աշխատանքային պրոֆիլում։ Ձեր անձնական տվյալները կպահվեն"</string>
diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml
index e788bf7..55f960d 100644
--- a/packages/PackageInstaller/res/values-ky/strings.xml
+++ b/packages/PackageInstaller/res/values-ky/strings.xml
@@ -63,7 +63,7 @@
     <string name="archive_application_text_all_users" msgid="3151229641681672580">"Бул колдонмо бардык колдонуучулар үчүн архивделсинби? Жеке маалыматыңыз сакталат"</string>
     <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Бул колдонмо жумуш профилиңизде архивделсинби? Жеке маалыматыңыз сакталат"</string>
     <string name="archive_application_text_user" msgid="2586558895535581451">"Бул колдонмо <xliff:g id="USERNAME">%1$s</xliff:g> үчүн архивделсинби? Жеке маалыматыңыз сакталат"</string>
-    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Бул колдонмо жеке чөйрөдөн архивделсинби? Жеке маалыматыңыз сакталат"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Бул колдонмо жеке мейкиндиктен архивделсинби? Жеке маалыматыңыз сакталат"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Бул колдонмо "<b>"бардык"</b>" колдонуучулардан алынып салынсынбы? Бул колдонмо жана анын дайындары бул түзмөктүн "<b>"бардык"</b>" колдонуучуларынан өчүрүлөт."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Бул колдонмону <xliff:g id="USERNAME">%1$s</xliff:g> үчүн чыгарып саласызбы?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Бул колдонмону жумуш профилиңизден чыгарып саласызбы?"</string>
@@ -72,7 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Колдонмонун <xliff:g id="SIZE">%1$s</xliff:g> дайындарын сактоо."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Бул колдонмону өчүрөсүзбү?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Бул колдонмону чыгарып саласызбы? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону да өчүрүлөт."</string>
-    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Бул колдонмону жеке чөйрөдөн чыгарып саласызбы?"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Бул колдонмону жеке мейкиндиктен чыгарып саласызбы?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Чыгарылып салынууда"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Чыгарылып салынбай калгандар"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Чыгарылып салынууда…"</string>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index 149783d..bd288e4 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -98,7 +98,7 @@
     <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"Uit veiligheidsoverwegingen heeft je tv momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string>
     <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"Uit veiligheidsoverwegingen heeft je smartwatch momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string>
     <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"Uit veiligheidsoverwegingen heeft je telefoon momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string>
-    <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Je telefoon en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je telefoon of gegevensverlies als gevolg van het gebruik van de app."</string>
+    <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Je telefoon en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Door deze app te installeren, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je telefoon of gegevensverlies als gevolg van het gebruik van de app."</string>
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Je tablet en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tablet of gegevensverlies als gevolg van het gebruik van de app."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Je tv en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tv of gegevensverlies als gevolg van het gebruik van de app."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon"</string>
diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml
index 7f37084..739d272 100644
--- a/packages/PackageInstaller/res/values-th/strings.xml
+++ b/packages/PackageInstaller/res/values-th/strings.xml
@@ -94,10 +94,10 @@
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"พบปัญหาในการแยกวิเคราะห์แพ็กเกจ"</string>
     <string name="message_staging" msgid="8032722385658438567">"กำลังปรับสภาพแวดล้อมของแอป…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ไม่ทราบ"</string>
-    <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในแท็บเล็ต คุณเปลี่ยนแปลงได้ในการตั้งค่า"</string>
-    <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในทีวี คุณเปลี่ยนแปลงได้ในการตั้งค่า"</string>
-    <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"ปัจจุบันนาฬิกาไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้เพื่อความปลอดภัยของคุณ คุณเปลี่ยนค่านี้ได้ในการตั้งค่า"</string>
-    <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในโทรศัพท์ ซึ่งคุณเปลี่ยนเป็นอนุญาตได้ในการตั้งค่า"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"เพื่อความปลอดภัย โทรศัพท์ของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"เพื่อความปลอดภัย โทรศัพท์ของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string>
+    <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"เพื่อความปลอดภัย นาฬิกาของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"เพื่อความปลอดภัย โทรศัพท์ของคุณไม่ได้รับอนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ คุณสามารถเปลี่ยนแปลงได้ที่ \"การตั้งค่า\""</string>
     <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"โทรศัพท์และข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับโทรศัพท์หรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"แท็บเล็ตและข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับแท็บเล็ตหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ทีวีและข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับทีวีหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
index 8f5d07c..407ab5f 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
@@ -245,8 +245,7 @@
     }
 
     private static boolean isArchivingEnabled() {
-        return android.content.pm.Flags.archiving()
-                || SystemProperties.getBoolean("pm.archiving.enabled", false);
+        return android.content.pm.Flags.archiving();
     }
 
     private boolean isCloneProfile(UserHandle userHandle) {
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 5298f8b..6ffad70 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -35,7 +35,7 @@
     <string name="install_for_print_preview" msgid="6366303997385509332">"Installer un lecteur PDF pour voir l\'aperçu"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"L\'application à l\'origine de l\'impression a planté"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"Génération tâche impression…"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"Enregistrer en format PDF"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"Enregistrer au format PDF"</string>
     <string name="all_printers" msgid="5018829726861876202">"Toutes les imprimantes…"</string>
     <string name="print_dialog" msgid="32628687461331979">"Boîte de dialogue d\'impression"</string>
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> sur <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-night/themes.xml b/packages/PrintSpooler/res/values-night/themes.xml
index 4428dbb..3cc64a6 100644
--- a/packages/PrintSpooler/res/values-night/themes.xml
+++ b/packages/PrintSpooler/res/values-night/themes.xml
@@ -30,6 +30,7 @@
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
+        <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
     </style>
 
 </resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 4dcad10..bd96025 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -31,6 +31,7 @@
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowLightStatusBar">true</item>
+        <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
     </style>
 
 </resources>
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v35/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v35/themes.xml
new file mode 100644
index 0000000..fadcf7b
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-night-v35/themes.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<resources>
+    <style name="Theme.CollapsingToolbar.Settings" parent="@style/Theme.MaterialComponents.DayNight">
+        <item name="elevationOverlayEnabled">true</item>
+        <item name="elevationOverlayColor">?attr/colorPrimary</item>
+        <item name="colorPrimary">@color/settingslib_materialColorOnSurfaceInverse</item>
+        <item name="colorAccent">@color/settingslib_materialColorPrimaryFixed</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles.xml
new file mode 100644
index 0000000..0c20287
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<resources>
+    <style name="CollapsingToolbarTitle.Collapsed" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+        <item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item>
+        <item name="android:textSize">20dp</item>
+        <item name="android:textColor">@color/settingslib_materialColorOnSurface</item>
+    </style>
+
+    <style name="CollapsingToolbarTitle.Expanded" parent="CollapsingToolbarTitle.Collapsed">
+        <item name="android:textSize">36dp</item>
+        <item name="android:textColor">@color/settingslib_materialColorOnSurface</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml
new file mode 100644
index 0000000..7c9d1a47
--- /dev/null
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<resources>
+    <style name="Theme.CollapsingToolbar.Settings" parent="@style/Theme.MaterialComponents.DayNight">
+        <item name="elevationOverlayEnabled">true</item>
+        <item name="elevationOverlayColor">?attr/colorPrimary</item>
+        <item name="colorPrimary">@color/settingslib_materialColorOnSurfaceInverse</item>
+        <item name="colorAccent">@color/settingslib_materialColorPrimary</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/DataStore/Android.bp b/packages/SettingsLib/DataStore/Android.bp
index 9fafcab..86c8f0da 100644
--- a/packages/SettingsLib/DataStore/Android.bp
+++ b/packages/SettingsLib/DataStore/Android.bp
@@ -2,12 +2,17 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
+filegroup {
+    name: "SettingsLibDataStore-srcs",
+    srcs: ["src/**/*"],
+}
+
 android_library {
     name: "SettingsLibDataStore",
     defaults: [
         "SettingsLintDefaults",
     ],
-    srcs: ["src/**/*"],
+    srcs: [":SettingsLibDataStore-srcs"],
     static_libs: [
         "androidx.annotation_annotation",
         "androidx.collection_collection-ktx",
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt
index 9d3fb66..7644bc9 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt
@@ -19,6 +19,7 @@
 import android.app.backup.BackupDataInputStream
 import android.content.Context
 import android.util.Log
+import androidx.annotation.VisibleForTesting
 import java.io.File
 import java.io.InputStream
 import java.io.OutputStream
@@ -33,11 +34,9 @@
  */
 internal class BackupRestoreFileArchiver(
     private val context: Context,
-    private val fileStorages: List<BackupRestoreFileStorage>,
+    @get:VisibleForTesting internal val fileStorages: List<BackupRestoreFileStorage>,
+    override val name: String,
 ) : BackupRestoreStorage() {
-    override val name: String
-        get() = "file_archiver"
-
     override fun createBackupRestoreEntities(): List<BackupRestoreEntity> =
         fileStorages.map { it.toBackupRestoreEntity() }
 
@@ -88,7 +87,8 @@
     }
 }
 
-private fun BackupRestoreFileStorage.toBackupRestoreEntity() =
+@VisibleForTesting
+internal fun BackupRestoreFileStorage.toBackupRestoreEntity() =
     object : BackupRestoreEntity {
         override val key: String
             get() = storageFilePath
@@ -107,7 +107,7 @@
                 Log.i(LOG_TAG, "[$name] $key not exist")
                 return EntityBackupResult.DELETE
             }
-            val codec = codec() ?: defaultCodec()
+            val codec = defaultCodec()
             // MUST close to flush the data
             wrapBackupOutputStream(codec, outputStream).use { stream ->
                 val bytesCopied = file.inputStream().use { it.copyTo(stream) }
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt
index c4c00cb..935f9cc 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt
@@ -22,6 +22,7 @@
 import android.app.backup.BackupHelper
 import android.os.ParcelFileDescriptor
 import android.util.Log
+import androidx.annotation.VisibleForTesting
 import androidx.collection.MutableScatterMap
 import com.google.common.io.ByteStreams
 import java.io.ByteArrayOutputStream
@@ -60,10 +61,11 @@
      *
      * Map key is the entity key, map value is the checksum of backup data.
      */
-    protected val entityStates = MutableScatterMap<String, Long>()
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    val entityStates = MutableScatterMap<String, Long>()
 
     /** Entities created by [createBackupRestoreEntities]. This field is for restore only. */
-    private var entities: List<BackupRestoreEntity>? = null
+    @VisibleForTesting internal var entities: List<BackupRestoreEntity>? = null
 
     /** Entities to back up and restore. */
     abstract fun createBackupRestoreEntities(): List<BackupRestoreEntity>
@@ -76,7 +78,7 @@
         data: BackupDataOutput,
         newState: ParcelFileDescriptor,
     ) {
-        oldState.readEntityStates(entityStates)
+        readEntityStates(oldState, entityStates)
         val backupContext = BackupContext(data)
         if (!enableBackup(backupContext)) {
             Log.i(LOG_TAG, "[$name] Backup disabled")
@@ -94,7 +96,10 @@
             val codec = entity.codec() ?: defaultCodec()
             val result =
                 try {
-                    entity.backup(backupContext, wrapBackupOutputStream(codec, checkedOutputStream))
+                    // MUST close to flush all data
+                    wrapBackupOutputStream(codec, checkedOutputStream).use {
+                        entity.backup(backupContext, it)
+                    }
                 } catch (exception: Exception) {
                     Log.e(LOG_TAG, "[$name] Fail to backup entity $key", exception)
                     continue
@@ -191,9 +196,13 @@
     /** Callbacks when restore finished. */
     open fun onRestoreFinished() {}
 
-    private fun ParcelFileDescriptor?.readEntityStates(state: MutableScatterMap<String, Long>) {
+    @VisibleForTesting
+    internal fun readEntityStates(
+        parcelFileDescriptor: ParcelFileDescriptor?,
+        state: MutableScatterMap<String, Long>,
+    ) {
         state.clear()
-        if (this == null) return
+        val fileDescriptor = parcelFileDescriptor?.fileDescriptor ?: return
         // do not close the streams
         val fileInputStream = FileInputStream(fileDescriptor)
         val dataInputStream = DataInputStream(fileInputStream)
@@ -233,6 +242,7 @@
                 dataOutputStream.writeUTF(key)
                 dataOutputStream.writeLong(value)
             }
+            dataOutputStream.flush()
         } catch (exception: Exception) {
             Log.e(LOG_TAG, "[$name] Fail to write state file", exception)
         }
@@ -241,7 +251,7 @@
     }
 
     companion object {
-        private const val STATE_VERSION: Byte = 0
+        internal const val STATE_VERSION: Byte = 0
 
         /** Checksum for entity backup data. */
         fun createChecksum(): Checksum = CRC32()
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt
index cfdcaff..8242347 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt
@@ -21,23 +21,32 @@
 import android.app.backup.BackupManager
 import android.content.Context
 import android.util.Log
+import androidx.annotation.VisibleForTesting
 import com.google.common.util.concurrent.MoreExecutors
 import java.util.concurrent.ConcurrentHashMap
 
 /** Manager of [BackupRestoreStorage]. */
 class BackupRestoreStorageManager private constructor(private val application: Application) {
-    private val storageWrappers = ConcurrentHashMap<String, StorageWrapper>()
+    @VisibleForTesting internal val storageWrappers = ConcurrentHashMap<String, StorageWrapper>()
 
     private val executor = MoreExecutors.directExecutor()
 
     /**
      * Adds all the registered [BackupRestoreStorage] as the helpers of given [BackupAgentHelper].
      *
-     * All [BackupRestoreFileStorage]s will be wrapped as a single [BackupRestoreFileArchiver].
+     * All [BackupRestoreFileStorage]s will be wrapped as a single [BackupRestoreFileArchiver],
+     * specify [fileArchiverName] to avoid key prefix conflict if needed.
      *
+     * @param backupAgentHelper backup agent helper to add helpers
+     * @param fileArchiverName key prefix of the [BackupRestoreFileArchiver], the value must not be
+     *   changed in future
      * @see BackupAgentHelper.addHelper
      */
-    fun addBackupAgentHelpers(backupAgentHelper: BackupAgentHelper) {
+    @JvmOverloads
+    fun addBackupAgentHelpers(
+        backupAgentHelper: BackupAgentHelper,
+        fileArchiverName: String = "file_archiver",
+    ) {
         val fileStorages = mutableListOf<BackupRestoreFileStorage>()
         for ((keyPrefix, storageWrapper) in storageWrappers) {
             val storage = storageWrapper.storage
@@ -48,7 +57,7 @@
             }
         }
         // Always add file archiver even fileStorages is empty to handle forward compatibility
-        val fileArchiver = BackupRestoreFileArchiver(application, fileStorages)
+        val fileArchiver = BackupRestoreFileArchiver(application, fileStorages, fileArchiverName)
         backupAgentHelper.addHelper(fileArchiver.name, fileArchiver)
     }
 
@@ -106,7 +115,8 @@
     /** Returns storage with given name, exception is raised if not found. */
     fun getOrThrow(name: String): BackupRestoreStorage = storageWrappers[name]!!.storage
 
-    private inner class StorageWrapper(val storage: BackupRestoreStorage) :
+    @VisibleForTesting
+    internal inner class StorageWrapper(val storage: BackupRestoreStorage) :
         Observer, KeyedObserver<Any?> {
         init {
             when (storage) {
@@ -139,7 +149,7 @@
                 LOG_TAG,
                 "Notify BackupManager dataChanged: storage=$name key=$key reason=$reason"
             )
-            BackupManager.dataChanged(application.packageName)
+            BackupManager(application).dataChanged()
         }
 
         fun removeObserver() {
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
index 0c1b417..9f9c0d8 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
@@ -20,9 +20,11 @@
 import android.content.SharedPreferences
 import android.os.Build
 import android.util.Log
-import androidx.core.content.ContextCompat
+import androidx.annotation.VisibleForTesting
 import java.io.File
 
+private fun defaultVerbose() = Build.TYPE == "eng"
+
 /**
  * [SharedPreferences] based storage.
  *
@@ -43,24 +45,35 @@
  * @param verbose Verbose logging on key/value pairs during backup/restore. Enable for dev only!
  * @param filter Filter of key/value pairs for backup and restore.
  */
-class SharedPreferencesStorage
+open class SharedPreferencesStorage
 @JvmOverloads
 constructor(
     context: Context,
     override val name: String,
-    mode: Int,
-    private val verbose: Boolean = (Build.TYPE == "eng"),
+    @get:VisibleForTesting internal val sharedPreferences: SharedPreferences,
+    private val codec: BackupCodec? = null,
+    private val verbose: Boolean = defaultVerbose(),
     private val filter: (String, Any?) -> Boolean = { _, _ -> true },
 ) :
     BackupRestoreFileStorage(context, context.getSharedPreferencesFilePath(name)),
     KeyedObservable<String> by KeyedDataObservable() {
 
-    private val sharedPreferences = context.getSharedPreferences(name, mode)
+    @JvmOverloads
+    constructor(
+        context: Context,
+        name: String,
+        mode: Int,
+        codec: BackupCodec? = null,
+        verbose: Boolean = defaultVerbose(),
+        filter: (String, Any?) -> Boolean = { _, _ -> true },
+    ) : this(context, name, context.getSharedPreferences(name, mode), codec, verbose, filter)
 
     /** Name of the intermediate SharedPreferences. */
-    private val intermediateName: String
+    @VisibleForTesting
+    internal val intermediateName: String
         get() = "_br_$name"
 
+    @Suppress("DEPRECATION")
     private val intermediateSharedPreferences: SharedPreferences
         get() {
             // use MODE_MULTI_PROCESS to ensure a reload
@@ -82,12 +95,15 @@
         sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
     }
 
+    override fun defaultCodec() = codec ?: super.defaultCodec()
+
     override val backupFile: File
         // use a different file to avoid multi-thread file write
         get() = context.getSharedPreferencesFile(intermediateName)
 
     override fun prepareBackup(file: File) {
-        val editor = intermediateSharedPreferences.merge(sharedPreferences.all, "Backup")
+        val editor =
+            mergeSharedPreferences(intermediateSharedPreferences, sharedPreferences.all, "Backup")
         // commit to ensure data is write to disk synchronously
         if (!editor.commit()) {
             Log.w(LOG_TAG, "[$name] fail to commit")
@@ -104,8 +120,8 @@
         // observers consistently once restore finished.
         sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener)
         val restored = intermediateSharedPreferences
-        val editor = sharedPreferences.merge(restored.all, "Restore")
-        editor.apply() // apply to avoid blocking
+        val editor = mergeSharedPreferences(sharedPreferences, restored.all, "Restore")
+        editor.commit() // commit to avoid race condition
         sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
         // clear the intermediate SharedPreferences
         restored.delete(intermediateName)
@@ -115,7 +131,7 @@
         if (deleteSharedPreferences(name)) {
             Log.i(LOG_TAG, "SharedPreferences $name deleted")
         } else {
-            edit().clear().apply()
+            edit().clear().commit() // commit to avoid potential race condition
         }
     }
 
@@ -126,11 +142,13 @@
             false
         }
 
-    private fun SharedPreferences.merge(
+    @VisibleForTesting
+    internal open fun mergeSharedPreferences(
+        sharedPreferences: SharedPreferences,
         entries: Map<String, Any?>,
-        operation: String
+        operation: String,
     ): SharedPreferences.Editor {
-        val editor = edit()
+        val editor = sharedPreferences.edit()
         for ((key, value) in entries) {
             if (!filter.invoke(key, value)) {
                 if (verbose) Log.v(LOG_TAG, "[$name] $operation skips $key=$value")
@@ -184,7 +202,7 @@
     companion object {
         private fun Context.getSharedPreferencesFilePath(name: String): String {
             val file = getSharedPreferencesFile(name)
-            return file.relativeTo(ContextCompat.getDataDir(this)!!).toString()
+            return file.relativeTo(dataDirCompat).toString()
         }
 
         /** Returns the absolute path of shared preferences file. */
diff --git a/packages/SettingsLib/DataStore/tests/Android.bp b/packages/SettingsLib/DataStore/tests/Android.bp
index 8770dfa..5d000eb 100644
--- a/packages/SettingsLib/DataStore/tests/Android.bp
+++ b/packages/SettingsLib/DataStore/tests/Android.bp
@@ -9,11 +9,16 @@
 
 android_robolectric_test {
     name: "SettingsLibDataStoreTest",
-    srcs: ["src/**/*"],
+    srcs: [
+        ":SettingsLibDataStore-srcs", // b/240432457
+        "src/**/*",
+    ],
     static_libs: [
-        "SettingsLibDataStore",
+        "androidx.collection_collection-ktx",
+        "androidx.core_core-ktx",
         "androidx.test.ext.junit",
         "guava",
+        "kotlin-test",
         "mockito-robolectric-prebuilt", // mockito deps order matters!
         "mockito-kotlin2",
     ],
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupCodecTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupCodecTest.kt
new file mode 100644
index 0000000..867831b
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupCodecTest.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import kotlin.random.Random
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Tests of [BackupCodec]. */
+@RunWith(AndroidJUnit4::class)
+class BackupCodecTest {
+    @Test
+    fun name() {
+        val names = mutableSetOf<String>()
+        for (codec in allCodecs()) {
+            assertThat(names).doesNotContain(codec.name)
+            names.add(codec.name)
+        }
+    }
+
+    @Test
+    fun fromId() {
+        for (codec in allCodecs()) {
+            assertThat(BackupCodec.fromId(codec.id)).isInstanceOf(codec::class.java)
+        }
+    }
+
+    @Test
+    fun fromId_unknownId() {
+        assertFailsWith(IllegalArgumentException::class) { BackupCodec.fromId(-1) }
+    }
+
+    @Test
+    fun encode_decode() {
+        val random = Random.Default
+        fun test(codec: BackupCodec, size: Int) {
+            val data = random.nextBytes(size)
+
+            // encode
+            val outputStream = ByteArrayOutputStream()
+            codec.encode(outputStream).use { it.write(data) }
+
+            // decode
+            val inputStream = ByteArrayInputStream(outputStream.toByteArray())
+            val result = codec.decode(inputStream).use { it.readBytes() }
+
+            assertWithMessage("$size bytes: $data").that(result).isEqualTo(data)
+        }
+
+        for (codec in allCodecs()) {
+            test(codec, 0)
+            repeat(10) { test(codec, random.nextInt(1, 1024)) }
+        }
+    }
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreContextTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreContextTest.kt
new file mode 100644
index 0000000..911665a
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreContextTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.backup.BackupDataOutput
+import android.os.Build
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+
+/** Tests of [BackupContext] and [RestoreContext]. */
+@RunWith(AndroidJUnit4::class)
+class BackupRestoreContextTest {
+    @Test
+    fun backupContext_quota() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
+        val data = mock<BackupDataOutput> { on { quota } doReturn 10L }
+        assertThat(BackupContext(data).quota).isEqualTo(10)
+    }
+
+    @Test
+    fun backupContext_transportFlags() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return
+        val data = mock<BackupDataOutput> { on { transportFlags } doReturn 5 }
+        assertThat(BackupContext(data).transportFlags).isEqualTo(5)
+    }
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreFileArchiverTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreFileArchiverTest.kt
new file mode 100644
index 0000000..6cce453
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreFileArchiverTest.kt
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.Application
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import kotlin.random.Random
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+/** Tests of [BackupRestoreFileArchiver]. */
+@RunWith(AndroidJUnit4::class)
+class BackupRestoreFileArchiverTest {
+    private val random = Random.Default
+    private val application: Application = getApplicationContext()
+    @get:Rule val temporaryFolder = TemporaryFolder(application.dataDirCompat)
+
+    @Test
+    fun createBackupRestoreEntities() {
+        val fileStorages = mutableListOf<BackupRestoreFileStorage>()
+        for (count in 0 until 3) {
+            val fileArchiver = BackupRestoreFileArchiver(application, fileStorages, "")
+            fileArchiver.createBackupRestoreEntities().apply {
+                assertThat(this).hasSize(fileStorages.size)
+                for (index in 0 until count) {
+                    assertThat(get(index).key).isEqualTo(fileStorages[index].storageFilePath)
+                }
+            }
+            fileStorages.add(FileStorage("storage", "path$count"))
+        }
+    }
+
+    @Test
+    fun wrapBackupOutputStream() {
+        val fileArchiver = BackupRestoreFileArchiver(application, listOf(), "")
+        val outputStream = ByteArrayOutputStream()
+        assertThat(fileArchiver.wrapBackupOutputStream(BackupZipCodec.BEST_SPEED, outputStream))
+            .isSameInstanceAs(outputStream)
+    }
+
+    @Test
+    fun wrapRestoreInputStream() {
+        val fileArchiver = BackupRestoreFileArchiver(application, listOf(), "")
+        val inputStream = ByteArrayInputStream(byteArrayOf())
+        assertThat(fileArchiver.wrapRestoreInputStream(BackupZipCodec.BEST_SPEED, inputStream))
+            .isSameInstanceAs(inputStream)
+    }
+
+    @Test
+    fun restoreEntity_disabled() {
+        val file = temporaryFolder.newFile()
+        val key = file.name
+        val fileStorage = FileStorage("fs", key, restoreEnabled = false)
+
+        BackupRestoreFileArchiver(application, listOf(fileStorage), "archiver").apply {
+            restoreEntity(newBackupDataInputStream(key, byteArrayOf()))
+            assertThat(entityStates.asMap()).isEmpty()
+        }
+    }
+
+    @Test
+    fun restoreEntity_raiseIOException() {
+        val key = "key"
+        val fileStorage = FileStorage("fs", key)
+        BackupRestoreFileArchiver(application, listOf(fileStorage), "archiver").apply {
+            restoreEntity(newBackupDataInputStream(key, byteArrayOf(), IOException()))
+            assertThat(entityStates.asMap()).isEmpty()
+        }
+    }
+
+    @Test
+    fun restoreEntity_onRestoreFinished_raiseException() {
+        val key = "key"
+        val fileStorage = FileStorage("fs", key, restoreException = IllegalStateException())
+        BackupRestoreFileArchiver(application, listOf(fileStorage), "archiver").apply {
+            val data = random.nextBytes(random.nextInt(10))
+            val outputStream = ByteArrayOutputStream()
+            fileStorage.wrapBackupOutputStream(fileStorage.defaultCodec(), outputStream).use {
+                it.write(data)
+            }
+            val payload = outputStream.toByteArray()
+            restoreEntity(newBackupDataInputStream(key, payload))
+            assertThat(entityStates.asMap()).isEmpty()
+        }
+    }
+
+    @Test
+    fun restoreEntity_forwardCompatibility() {
+        val key = "key"
+        val fileStorage = FileStorage("fs", key)
+        for (codec in allCodecs()) {
+            BackupRestoreFileArchiver(application, listOf(), "archiver").apply {
+                val data = random.nextBytes(random.nextInt(MAX_DATA_SIZE))
+                val outputStream = ByteArrayOutputStream()
+                fileStorage.wrapBackupOutputStream(codec, outputStream).use { it.write(data) }
+                val payload = outputStream.toByteArray()
+
+                restoreEntity(newBackupDataInputStream(key, payload))
+
+                assertThat(entityStates.asMap()).apply {
+                    hasSize(1)
+                    containsKey(key)
+                }
+                assertThat(fileStorage.restoreFile.readBytes()).isEqualTo(data)
+            }
+        }
+    }
+
+    @Test
+    fun restoreEntity() {
+        val folder = File(application.dataDirCompat, "backup")
+        val file = File(folder, "file")
+        val key = "${folder.name}${File.separator}${file.name}"
+        fun test(codec: BackupCodec, size: Int) {
+            val fileStorage = FileStorage("fs", key, if (size % 2 == 0) codec else null)
+            val data = random.nextBytes(size)
+            val outputStream = ByteArrayOutputStream()
+            fileStorage.wrapBackupOutputStream(codec, outputStream).use { it.write(data) }
+            val payload = outputStream.toByteArray()
+
+            val fileArchiver =
+                BackupRestoreFileArchiver(application, listOf(fileStorage), "archiver")
+            fileArchiver.restoreEntity(newBackupDataInputStream(key, payload))
+
+            assertThat(fileArchiver.entityStates.asMap()).apply {
+                hasSize(1)
+                containsKey(key)
+            }
+            assertThat(file.readBytes()).isEqualTo(data)
+        }
+
+        for (codec in allCodecs()) {
+            for (size in 0 until 100) test(codec, size)
+            repeat(10) { test(codec, random.nextInt(100, MAX_DATA_SIZE)) }
+        }
+    }
+
+    @Test
+    fun onRestoreFinished() {
+        val fileStorage = mock<BackupRestoreFileStorage>()
+        val fileArchiver = BackupRestoreFileArchiver(application, listOf(fileStorage), "")
+
+        fileArchiver.onRestoreFinished()
+
+        verify(fileStorage).onRestoreFinished()
+    }
+
+    @Test
+    fun toBackupRestoreEntity_backup_disabled() {
+        val context = BackupContext(mock())
+        val fileStorage =
+            mock<BackupRestoreFileStorage> { on { enableBackup(context) } doReturn false }
+
+        assertThat(fileStorage.toBackupRestoreEntity().backup(context, ByteArrayOutputStream()))
+            .isEqualTo(EntityBackupResult.INTACT)
+
+        verify(fileStorage, never()).prepareBackup(any())
+    }
+
+    @Test
+    fun toBackupRestoreEntity_backup_fileNotExist() {
+        val context = BackupContext(mock())
+        val file = File("NotExist")
+        val fileStorage =
+            mock<BackupRestoreFileStorage> {
+                on { enableBackup(context) } doReturn true
+                on { backupFile } doReturn file
+            }
+
+        assertThat(fileStorage.toBackupRestoreEntity().backup(context, ByteArrayOutputStream()))
+            .isEqualTo(EntityBackupResult.DELETE)
+
+        verify(fileStorage).prepareBackup(file)
+        verify(fileStorage, never()).defaultCodec()
+    }
+
+    @Test
+    fun toBackupRestoreEntity_backup() {
+        val context = BackupContext(mock())
+        val file = temporaryFolder.newFile()
+
+        fun test(codec: BackupCodec, size: Int) {
+            val data = random.nextBytes(size)
+            file.outputStream().use { it.write(data) }
+
+            val outputStream = ByteArrayOutputStream()
+            val fileStorage =
+                mock<BackupRestoreFileStorage> {
+                    on { enableBackup(context) } doReturn true
+                    on { backupFile } doReturn file
+                    on { defaultCodec() } doReturn codec
+                    on { wrapBackupOutputStream(any(), any()) }.thenCallRealMethod()
+                    on { wrapRestoreInputStream(any(), any()) }.thenCallRealMethod()
+                    on { prepareBackup(any()) }.thenCallRealMethod()
+                    on { onBackupFinished(any()) }.thenCallRealMethod()
+                }
+
+            assertThat(fileStorage.toBackupRestoreEntity().backup(context, outputStream))
+                .isEqualTo(EntityBackupResult.UPDATE)
+
+            verify(fileStorage).prepareBackup(file)
+            verify(fileStorage).onBackupFinished(file)
+
+            val decodedData =
+                fileStorage
+                    .wrapRestoreInputStream(codec, ByteArrayInputStream(outputStream.toByteArray()))
+                    .readBytes()
+            assertThat(decodedData).isEqualTo(data)
+        }
+
+        for (codec in allCodecs()) {
+            // test small data to ensure correctness
+            for (size in 0 until 100) test(codec, size)
+            repeat(10) { test(codec, random.nextInt(100, MAX_DATA_SIZE)) }
+        }
+    }
+
+    @Test
+    fun toBackupRestoreEntity_restore() {
+        val restoreContext = RestoreContext("storage")
+        val inputStream =
+            object : InputStream() {
+                override fun read() = throw IllegalStateException()
+
+                override fun read(b: ByteArray, off: Int, len: Int) = throw IllegalStateException()
+            }
+        FileStorage("storage", "path").toBackupRestoreEntity().restore(restoreContext, inputStream)
+    }
+
+    private open class FileStorage(
+        override val name: String,
+        filePath: String,
+        private val codec: BackupCodec? = null,
+        private val restoreEnabled: Boolean? = null,
+        private val restoreException: Exception? = null,
+    ) : BackupRestoreFileStorage(getApplicationContext(), filePath) {
+
+        override fun defaultCodec() = codec ?: super.defaultCodec()
+
+        override fun enableRestore() = restoreEnabled ?: super.enableRestore()
+
+        override fun onRestoreFinished(file: File) {
+            super.onRestoreFinished(file)
+            if (restoreException != null) throw restoreException
+        }
+    }
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreFileStorageTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreFileStorageTest.kt
new file mode 100644
index 0000000..422273d
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreFileStorageTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.Application
+import android.os.Build
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Tests of [BackupRestoreFileStorage]. */
+@RunWith(AndroidJUnit4::class)
+class BackupRestoreFileStorageTest {
+    private val application: Application = getApplicationContext()
+
+    @Test
+    fun dataDirCompat() {
+        val expected =
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                application.dataDir
+            } else {
+                File(application.applicationInfo.dataDir)
+            }
+        assertThat(application.dataDirCompat).isEqualTo(expected)
+    }
+
+    @Test
+    fun backupFile() {
+        assertThat(FileStorage("path").backupFile.toString())
+            .startsWith(application.dataDirCompat.toString())
+    }
+
+    @Test
+    fun restoreFile() {
+        FileStorage("path").apply { assertThat(restoreFile).isEqualTo(backupFile) }
+    }
+
+    @Test
+    fun checkFilePaths() {
+        FileStorage("path").checkFilePaths()
+    }
+
+    @Test
+    fun checkFilePaths_emptyFilePath() {
+        assertFailsWith(IllegalArgumentException::class) { FileStorage("").checkFilePaths() }
+    }
+
+    @Test
+    fun checkFilePaths_absoluteFilePath() {
+        assertFailsWith(IllegalArgumentException::class) {
+            FileStorage("${File.separatorChar}file").checkFilePaths()
+        }
+    }
+
+    @Test
+    fun checkFilePaths_backupFile() {
+        assertFailsWith(IllegalArgumentException::class) {
+            FileStorage("path", fileForBackup = File("path")).checkFilePaths()
+        }
+    }
+
+    @Test
+    fun checkFilePaths_restoreFile() {
+        assertFailsWith(IllegalArgumentException::class) {
+            FileStorage("path", fileForRestore = File("path")).checkFilePaths()
+        }
+    }
+
+    @Test
+    fun createBackupRestoreEntities() {
+        assertThat(FileStorage("path").createBackupRestoreEntities()).isEmpty()
+    }
+
+    private class FileStorage(
+        filePath: String,
+        val fileForBackup: File? = null,
+        val fileForRestore: File? = null,
+    ) : BackupRestoreFileStorage(getApplicationContext(), filePath) {
+        override val name = "storage"
+
+        override val backupFile: File
+            get() = fileForBackup ?: super.backupFile
+
+        override val restoreFile: File
+            get() = fileForRestore ?: super.restoreFile
+    }
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt
new file mode 100644
index 0000000..d8f5028
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageManagerTest.kt
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.Application
+import android.app.backup.BackupAgentHelper
+import android.app.backup.BackupHelper
+import android.app.backup.BackupManager
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors.directExecutor
+import kotlin.test.assertFailsWith
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.reset
+import org.mockito.kotlin.verify
+import org.robolectric.Shadows
+import org.robolectric.shadows.ShadowBackupManager
+
+/** Tests of [BackupRestoreStorageManager]. */
+@RunWith(AndroidJUnit4::class)
+class BackupRestoreStorageManagerTest {
+    private val application: Application = getApplicationContext()
+    private val manager = BackupRestoreStorageManager.getInstance(application)
+    private val fileStorage = FileStorage("fileStorage")
+    private val keyedStorage = KeyedStorage("keyedStorage")
+
+    private val storage1 = mock<ObservableBackupRestoreStorage> { on { name } doReturn "1" }
+    private val storage2 = mock<ObservableBackupRestoreStorage> { on { name } doReturn "1" }
+
+    @After
+    fun tearDown() {
+        manager.removeAll()
+        ShadowBackupManager.reset()
+    }
+
+    @Test
+    fun getInstance() {
+        assertThat(BackupRestoreStorageManager.getInstance(application)).isSameInstanceAs(manager)
+    }
+
+    @Test
+    fun addBackupAgentHelpers() {
+        val fs = FileStorage("fs")
+        manager.add(keyedStorage, fileStorage, storage1, fs)
+        val backupAgentHelper = DummyBackupAgentHelper()
+        manager.addBackupAgentHelpers(backupAgentHelper)
+        backupAgentHelper.backupHelpers.apply {
+            assertThat(size).isEqualTo(3)
+            assertThat(remove(keyedStorage.name)).isSameInstanceAs(keyedStorage)
+            assertThat(remove(storage1.name)).isSameInstanceAs(storage1)
+            val fileArchiver = entries.first().value as BackupRestoreFileArchiver
+            assertThat(fileArchiver.fileStorages.toSet()).containsExactly(fs, fileStorage)
+        }
+    }
+
+    @Test
+    fun addBackupAgentHelpers_withoutFileStorage() {
+        manager.add(keyedStorage, storage1)
+        val backupAgentHelper = DummyBackupAgentHelper()
+        manager.addBackupAgentHelpers(backupAgentHelper)
+        backupAgentHelper.backupHelpers.apply {
+            assertThat(size).isEqualTo(3)
+            assertThat(remove(keyedStorage.name)).isSameInstanceAs(keyedStorage)
+            assertThat(remove(storage1.name)).isSameInstanceAs(storage1)
+            val fileArchiver = entries.first().value as BackupRestoreFileArchiver
+            assertThat(fileArchiver.fileStorages).isEmpty()
+        }
+    }
+
+    @Test
+    fun add() {
+        manager.add(keyedStorage, fileStorage, storage1)
+        assertThat(manager.storageWrappers).apply {
+            hasSize(3)
+            containsKey(keyedStorage.name)
+            containsKey(fileStorage.name)
+            containsKey(storage1.name)
+        }
+    }
+
+    @Test
+    fun add_identicalName() {
+        manager.add(storage1)
+        assertFailsWith(IllegalStateException::class) { manager.add(storage1) }
+        assertFailsWith(IllegalStateException::class) { manager.add(storage2) }
+    }
+
+    @Test
+    fun add_nonObservable() {
+        assertFailsWith(IllegalArgumentException::class) {
+            manager.add(mock<BackupRestoreStorage>())
+        }
+    }
+
+    @Test
+    fun removeAll() {
+        add()
+        manager.removeAll()
+        assertThat(manager.storageWrappers).isEmpty()
+    }
+
+    @Test
+    fun remove() {
+        manager.add(keyedStorage, fileStorage)
+        assertThat(manager.remove(storage1.name)).isNull()
+        assertThat(manager.remove(keyedStorage.name)).isSameInstanceAs(keyedStorage)
+        assertThat(manager.remove(fileStorage.name)).isSameInstanceAs(fileStorage)
+    }
+
+    @Test
+    fun get() {
+        manager.add(keyedStorage, fileStorage)
+        assertThat(manager.get(storage1.name)).isNull()
+        assertThat(manager.get(keyedStorage.name)).isSameInstanceAs(keyedStorage)
+        assertThat(manager.get(fileStorage.name)).isSameInstanceAs(fileStorage)
+    }
+
+    @Test
+    fun getOrThrow() {
+        manager.add(keyedStorage, fileStorage)
+        assertFailsWith(NullPointerException::class) { manager.getOrThrow(storage1.name) }
+        assertThat(manager.getOrThrow(keyedStorage.name)).isSameInstanceAs(keyedStorage)
+        assertThat(manager.getOrThrow(fileStorage.name)).isSameInstanceAs(fileStorage)
+    }
+
+    @Test
+    fun notifyRestoreFinished() {
+        manager.add(keyedStorage, fileStorage)
+        val keyedObserver = mock<KeyedObserver<String>>()
+        val anyKeyObserver = mock<KeyedObserver<String?>>()
+        val observer = mock<Observer>()
+        val executor = directExecutor()
+        keyedStorage.addObserver("key", keyedObserver, executor)
+        keyedStorage.addObserver(anyKeyObserver, executor)
+        fileStorage.addObserver(observer, executor)
+
+        manager.onRestoreFinished()
+
+        verify(keyedObserver).onKeyChanged("key", ChangeReason.RESTORE)
+        verify(anyKeyObserver).onKeyChanged(null, ChangeReason.RESTORE)
+        verify(observer).onChanged(ChangeReason.RESTORE)
+        if (isRobolectric()) {
+            Shadows.shadowOf(BackupManager(application)).apply {
+                assertThat(isDataChanged).isFalse()
+                assertThat(dataChangedCount).isEqualTo(0)
+            }
+        }
+    }
+
+    @Test
+    fun notifyBackupManager() {
+        manager.add(keyedStorage, fileStorage)
+        val keyedObserver = mock<KeyedObserver<String>>()
+        val anyKeyObserver = mock<KeyedObserver<String?>>()
+        val observer = mock<Observer>()
+        val executor = directExecutor()
+        keyedStorage.addObserver("key", keyedObserver, executor)
+        keyedStorage.addObserver(anyKeyObserver, executor)
+        fileStorage.addObserver(observer, executor)
+
+        val backupManager =
+            if (isRobolectric()) Shadows.shadowOf(BackupManager(application)) else null
+        backupManager?.apply {
+            assertThat(isDataChanged).isFalse()
+            assertThat(dataChangedCount).isEqualTo(0)
+        }
+
+        fileStorage.notifyChange(ChangeReason.UPDATE)
+        verify(observer).onChanged(ChangeReason.UPDATE)
+        verify(keyedObserver, never()).onKeyChanged(any(), any())
+        verify(anyKeyObserver, never()).onKeyChanged(any(), any())
+        reset(observer)
+        backupManager?.apply {
+            assertThat(isDataChanged).isTrue()
+            assertThat(dataChangedCount).isEqualTo(1)
+        }
+
+        keyedStorage.notifyChange("key", ChangeReason.DELETE)
+        verify(observer, never()).onChanged(any())
+        verify(keyedObserver).onKeyChanged("key", ChangeReason.DELETE)
+        verify(anyKeyObserver).onKeyChanged("key", ChangeReason.DELETE)
+        backupManager?.apply {
+            assertThat(isDataChanged).isTrue()
+            assertThat(dataChangedCount).isEqualTo(2)
+        }
+        reset(keyedObserver)
+
+        // backup manager is not notified for restore event
+        fileStorage.notifyChange(ChangeReason.RESTORE)
+        keyedStorage.notifyChange("key", ChangeReason.RESTORE)
+        verify(observer).onChanged(ChangeReason.RESTORE)
+        verify(keyedObserver).onKeyChanged("key", ChangeReason.RESTORE)
+        verify(anyKeyObserver).onKeyChanged("key", ChangeReason.RESTORE)
+        backupManager?.apply {
+            assertThat(isDataChanged).isTrue()
+            assertThat(dataChangedCount).isEqualTo(2)
+        }
+    }
+
+    private class KeyedStorage(override val name: String) :
+        BackupRestoreStorage(), KeyedObservable<String> by KeyedDataObservable() {
+
+        override fun createBackupRestoreEntities(): List<BackupRestoreEntity> = listOf()
+    }
+
+    private class FileStorage(override val name: String) :
+        BackupRestoreFileStorage(getApplicationContext(), "file"), Observable by DataObservable()
+
+    private class DummyBackupAgentHelper : BackupAgentHelper() {
+        val backupHelpers = mutableMapOf<String, BackupHelper>()
+
+        override fun addHelper(keyPrefix: String, helper: BackupHelper) {
+            backupHelpers[keyPrefix] = helper
+        }
+    }
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageTest.kt
new file mode 100644
index 0000000..99998ff
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/BackupRestoreStorageTest.kt
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.backup.BackupAgentHelper
+import android.app.backup.BackupDataInput
+import android.app.backup.BackupDataInputStream
+import android.app.backup.BackupDataOutput
+import android.os.ParcelFileDescriptor
+import android.os.ParcelFileDescriptor.MODE_APPEND
+import android.os.ParcelFileDescriptor.MODE_READ_ONLY
+import android.os.ParcelFileDescriptor.MODE_WRITE_ONLY
+import androidx.collection.MutableScatterMap
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.io.DataOutputStream
+import java.io.File
+import java.io.FileDescriptor
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import kotlin.random.Random
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.doThrow
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.reset
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+
+/** Tests of [BackupRestoreStorage]. */
+@RunWith(AndroidJUnit4::class)
+class BackupRestoreStorageTest {
+    @get:Rule val temporaryFolder = TemporaryFolder()
+
+    private val entity1 = Entity("key1", "value1".toByteArray())
+    private val entity1NoOpCodec = Entity("key1", "value1".toByteArray(), BackupNoOpCodec())
+    private val entity2 = Entity("key2", "value2".toByteArray(), BackupZipCodec.BEST_SPEED)
+
+    @Test
+    fun performBackup_disabled() {
+        val storage = spy(TestStorage().apply { enabled = false })
+        val unused = performBackup { data, newState -> storage.performBackup(null, data, newState) }
+        verify(storage, never()).createBackupRestoreEntities()
+        assertThat(storage.entities).isNull()
+        assertThat(storage.entityStates.size).isEqualTo(0)
+    }
+
+    @Test
+    fun performBackup_enabled() {
+        val storage = spy(TestStorage())
+        val unused = performBackup { data, newState -> storage.performBackup(null, data, newState) }
+        verify(storage).createBackupRestoreEntities()
+        assertThat(storage.entities).isNull()
+        assertThat(storage.entityStates.size).isEqualTo(0)
+    }
+
+    @Test
+    fun performBackup_entityBackupWithException() {
+        val entity =
+            mock<BackupRestoreEntity> {
+                on { key } doReturn ""
+                on { backup(any(), any()) } doThrow IllegalStateException()
+            }
+        val storage = TestStorage(entity, entity1)
+
+        val (_, stateFile) =
+            performBackup { data, newState -> storage.performBackup(null, data, newState) }
+
+        assertThat(storage.readEntityStates(stateFile)).apply {
+            hasSize(1)
+            containsKey(entity1.key)
+        }
+    }
+
+    @Test
+    fun performBackup_update_unchanged() {
+        performBackupTest({}) { entityStates, newEntityStates ->
+            assertThat(entityStates).isEqualTo(newEntityStates)
+        }
+    }
+
+    @Test
+    fun performBackup_intact() {
+        performBackupTest({ entity1.backupResult = EntityBackupResult.INTACT }) {
+            entityStates,
+            newEntityStates ->
+            assertThat(entityStates).isEqualTo(newEntityStates)
+        }
+    }
+
+    @Test
+    fun performBackup_delete() {
+        performBackupTest({ entity1.backupResult = EntityBackupResult.DELETE }) { _, newEntityStates
+            ->
+            assertThat(newEntityStates.size).isEqualTo(1)
+            assertThat(newEntityStates).containsKey(entity2.key)
+        }
+    }
+
+    private fun performBackupTest(
+        update: () -> Unit,
+        verification: (Map<String, Long>, Map<String, Long>) -> Unit,
+    ) {
+        val storage = TestStorage(entity1, entity2)
+        val (_, stateFile) =
+            performBackup { data, newState -> storage.performBackup(null, data, newState) }
+
+        val entityStates = storage.readEntityStates(stateFile)
+        assertThat(entityStates).apply {
+            hasSize(2)
+            containsKey(entity1.key)
+            containsKey(entity2.key)
+        }
+
+        update.invoke()
+        val (_, newStateFile) =
+            performBackup { data, newState ->
+                stateFile.toParcelFileDescriptor(MODE_READ_ONLY).use {
+                    storage.performBackup(it, data, newState)
+                }
+            }
+        verification.invoke(entityStates, storage.readEntityStates(newStateFile))
+    }
+
+    @Test
+    fun restoreEntity_disabled() {
+        val storage = spy(TestStorage().apply { enabled = false })
+        temporaryFolder.newFile().toParcelFileDescriptor(MODE_READ_ONLY).use {
+            storage.restoreEntity(it.toBackupDataInputStream())
+        }
+        verify(storage, never()).createBackupRestoreEntities()
+        assertThat(storage.entities).isNull()
+        assertThat(storage.entityStates.size).isEqualTo(0)
+    }
+
+    @Test
+    fun restoreEntity_entityNotFound() {
+        val storage = TestStorage()
+        temporaryFolder.newFile().toParcelFileDescriptor(MODE_READ_ONLY).use {
+            val backupDataInputStream = it.toBackupDataInputStream()
+            backupDataInputStream.setKey("")
+            storage.restoreEntity(backupDataInputStream)
+        }
+    }
+
+    @Test
+    fun restoreEntity_exception() {
+        val storage = TestStorage(entity1)
+        temporaryFolder.newFile().toParcelFileDescriptor(MODE_READ_ONLY).use {
+            val backupDataInputStream = it.toBackupDataInputStream()
+            backupDataInputStream.setKey(entity1.key)
+            storage.restoreEntity(backupDataInputStream)
+        }
+    }
+
+    @Test
+    fun restoreEntity_codecChanged() {
+        assertThat(entity1.codec()).isNotEqualTo(entity1NoOpCodec.codec())
+        backupAndRestore(entity1) { _, data ->
+            TestStorage(entity1NoOpCodec).apply { restoreEntity(data) }
+        }
+        assertThat(entity1.data).isEqualTo(entity1NoOpCodec.restoredData)
+    }
+
+    @Test
+    fun restoreEntity() {
+        val random = Random.Default
+        fun test(codec: BackupCodec, size: Int) {
+            val entity = Entity("key", random.nextBytes(size), codec)
+            backupAndRestore(entity)
+            entity.verifyRestoredData()
+        }
+        for (codec in allCodecs()) {
+            // test small data to ensure correctness
+            for (size in 0 until 100) test(codec, size)
+            repeat(10) { test(codec, random.nextInt(100, MAX_DATA_SIZE)) }
+        }
+    }
+
+    @Test
+    fun readEntityStates_eof_exception() {
+        val storage = TestStorage()
+        val entityStates = MutableScatterMap<String, Long>()
+        entityStates.put("", 0) // add an item to verify that exiting elements are clear
+        temporaryFolder.newFile().toParcelFileDescriptor(MODE_READ_ONLY).use {
+            storage.readEntityStates(it, entityStates)
+        }
+        assertThat(entityStates.size).isEqualTo(0)
+    }
+
+    @Test
+    fun readEntityStates_other_exception() {
+        val storage = TestStorage()
+        val entityStates = MutableScatterMap<String, Long>()
+        entityStates.put("", 0) // add an item to verify that exiting elements are clear
+        temporaryFolder.newFile().toParcelFileDescriptor(MODE_READ_ONLY).apply {
+            close() // cause exception when read state file
+            storage.readEntityStates(this, entityStates)
+        }
+        assertThat(entityStates.size).isEqualTo(0)
+    }
+
+    @Test
+    fun readEntityStates_unknownVersion() {
+        val storage = TestStorage()
+        val stateFile = temporaryFolder.newFile()
+        stateFile.toParcelFileDescriptor(MODE_WRITE_ONLY or MODE_APPEND).use {
+            DataOutputStream(FileOutputStream(it.fileDescriptor))
+                .writeByte(BackupRestoreStorage.STATE_VERSION + 1)
+        }
+        val entityStates = MutableScatterMap<String, Long>()
+        entityStates.put("", 0) // add an item to verify that exiting elements are clear
+        stateFile.toParcelFileDescriptor(MODE_READ_ONLY).use {
+            storage.readEntityStates(it, entityStates)
+        }
+        assertThat(entityStates.size).isEqualTo(0)
+    }
+
+    @Test
+    fun writeNewStateDescription() {
+        val storage = spy(TestStorage())
+        // use read only mode to trigger exception when write state file
+        temporaryFolder.newFile().toParcelFileDescriptor(MODE_READ_ONLY).use {
+            storage.writeNewStateDescription(it)
+        }
+        verify(storage).onRestoreFinished()
+    }
+
+    @Test
+    fun backupAndRestore() {
+        val storage = spy(TestStorage(entity1, entity2))
+        val backupAgentHelper = BackupAgentHelper()
+        backupAgentHelper.addHelper(storage.name, storage)
+
+        // backup
+        val (dataFile, stateFile) =
+            performBackup { data, newState -> backupAgentHelper.onBackup(null, data, newState) }
+        storage.verifyFieldsArePurged()
+
+        // verify state
+        val entityStates = MutableScatterMap<String, Long>()
+        entityStates[""] = 1
+        storage.readEntityStates(null, entityStates)
+        assertThat(entityStates.size).isEqualTo(0)
+        stateFile.toParcelFileDescriptor(MODE_READ_ONLY).use {
+            storage.readEntityStates(it, entityStates)
+        }
+        assertThat(entityStates.asMap()).apply {
+            hasSize(2)
+            containsKey(entity1.key)
+            containsKey(entity2.key)
+        }
+        reset(storage)
+
+        // restore
+        val newStateFile = temporaryFolder.newFile()
+        dataFile.toParcelFileDescriptor(MODE_READ_ONLY).use { dataPfd ->
+            newStateFile.toParcelFileDescriptor(MODE_WRITE_ONLY or MODE_APPEND).use {
+                backupAgentHelper.onRestore(dataPfd.toBackupDataInput(), 0, it)
+            }
+        }
+        verify(storage).onRestoreFinished()
+        storage.verifyFieldsArePurged()
+
+        // ShadowBackupDataOutput does not write data to file, so restore is bypassed
+        if (!isRobolectric()) {
+            entity1.verifyRestoredData()
+            entity2.verifyRestoredData()
+            assertThat(entityStates.asMap()).isEqualTo(storage.readEntityStates(newStateFile))
+        }
+    }
+
+    private fun backupAndRestore(
+        entity: BackupRestoreEntity,
+        restoreEntity: (TestStorage, BackupDataInputStream) -> TestStorage = { storage, data ->
+            storage.restoreEntity(data)
+            storage
+        },
+    ) {
+        val storage = TestStorage(entity)
+        val entityKey = argumentCaptor<String>()
+        val entitySize = argumentCaptor<Int>()
+        val entityData = argumentCaptor<ByteArray>()
+        val data = mock<BackupDataOutput>()
+
+        val stateFile = temporaryFolder.newFile()
+        stateFile.toParcelFileDescriptor(MODE_WRITE_ONLY or MODE_APPEND).use {
+            storage.performBackup(null, data, it)
+        }
+        val entityStates = MutableScatterMap<String, Long>()
+        stateFile.toParcelFileDescriptor(MODE_READ_ONLY).use {
+            storage.readEntityStates(it, entityStates)
+        }
+        assertThat(entityStates.size).isEqualTo(1)
+
+        verify(data).writeEntityHeader(entityKey.capture(), entitySize.capture())
+        verify(data).writeEntityData(entityData.capture(), entitySize.capture())
+        assertThat(entityKey.allValues).isEqualTo(listOf(entity.key))
+        assertThat(entityData.allValues).hasSize(1)
+        val payload = entityData.firstValue
+        assertThat(entitySize.allValues).isEqualTo(listOf(payload.size, payload.size))
+
+        val dataFile = temporaryFolder.newFile()
+        dataFile.toParcelFileDescriptor(MODE_WRITE_ONLY or MODE_APPEND).use {
+            FileOutputStream(it.fileDescriptor).write(payload)
+        }
+
+        newBackupDataInputStream(entity.key, payload).apply {
+            restoreEntity.invoke(storage, this).also {
+                assertThat(it.entityStates).isEqualTo(entityStates)
+            }
+        }
+    }
+
+    fun performBackup(backup: (BackupDataOutput, ParcelFileDescriptor) -> Unit): Pair<File, File> {
+        val dataFile = temporaryFolder.newFile()
+        val stateFile = temporaryFolder.newFile()
+        dataFile.toParcelFileDescriptor(MODE_WRITE_ONLY or MODE_APPEND).use { dataPfd ->
+            stateFile.toParcelFileDescriptor(MODE_WRITE_ONLY or MODE_APPEND).use {
+                backup.invoke(dataPfd.toBackupDataOutput(), it)
+            }
+        }
+        return dataFile to stateFile
+    }
+
+    private fun BackupRestoreStorage.verifyFieldsArePurged() {
+        assertThat(entities).isNull()
+        assertThat(entityStates.size).isEqualTo(0)
+        assertThat(entityStates.capacity).isEqualTo(0)
+    }
+
+    private fun BackupRestoreStorage.readEntityStates(stateFile: File): Map<String, Long> {
+        val entityStates = MutableScatterMap<String, Long>()
+        stateFile.toParcelFileDescriptor(MODE_READ_ONLY).use { readEntityStates(it, entityStates) }
+        return entityStates.asMap()
+    }
+
+    private fun File.toParcelFileDescriptor(mode: Int) = ParcelFileDescriptor.open(this, mode)
+
+    private fun ParcelFileDescriptor.toBackupDataOutput() = fileDescriptor.toBackupDataOutput()
+
+    private fun ParcelFileDescriptor.toBackupDataInputStream(): BackupDataInputStream =
+        BackupDataInputStream::class.java.newInstance(toBackupDataInput())
+
+    private fun ParcelFileDescriptor.toBackupDataInput() = fileDescriptor.toBackupDataInput()
+
+    private fun FileDescriptor.toBackupDataOutput(): BackupDataOutput =
+        BackupDataOutput::class.java.newInstance(this)
+
+    private fun FileDescriptor.toBackupDataInput(): BackupDataInput =
+        BackupDataInput::class.java.newInstance(this)
+}
+
+private open class TestStorage(vararg val backupRestoreEntities: BackupRestoreEntity) :
+    ObservableBackupRestoreStorage() {
+    var enabled: Boolean? = null
+
+    override val name
+        get() = "TestBackup"
+
+    override fun createBackupRestoreEntities() = backupRestoreEntities.toList()
+
+    override fun enableBackup(backupContext: BackupContext) =
+        enabled ?: super.enableBackup(backupContext)
+
+    override fun enableRestore() = enabled ?: super.enableRestore()
+}
+
+private class Entity(
+    override val key: String,
+    val data: ByteArray,
+    private val codec: BackupCodec? = null,
+) : BackupRestoreEntity {
+    var restoredData: ByteArray? = null
+    var backupResult = EntityBackupResult.UPDATE
+
+    override fun codec() = codec ?: super.codec()
+
+    override fun backup(
+        backupContext: BackupContext,
+        outputStream: OutputStream,
+    ): EntityBackupResult {
+        outputStream.write(data)
+        return backupResult
+    }
+
+    override fun restore(restoreContext: RestoreContext, inputStream: InputStream) {
+        restoredData = inputStream.readBytes()
+        inputStream.close()
+    }
+
+    fun verifyRestoredData() = assertThat(restoredData).isEqualTo(data)
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
index b52586c..8638b2f 100644
--- a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
@@ -16,76 +16,58 @@
 
 package com.android.settingslib.datastore
 
+import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
-import com.google.common.util.concurrent.MoreExecutors.directExecutor
+import com.google.common.util.concurrent.MoreExecutors
 import java.util.concurrent.Executor
 import java.util.concurrent.atomic.AtomicInteger
 import org.junit.Assert
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
 import org.mockito.kotlin.never
 import org.mockito.kotlin.reset
 import org.mockito.kotlin.verify
-import org.robolectric.RobolectricTestRunner
 
-@RunWith(RobolectricTestRunner::class)
+@RunWith(AndroidJUnit4::class)
 class KeyedObserverTest {
-    @get:Rule
-    val mockitoRule: MockitoRule = MockitoJUnit.rule()
+    private val observer1 = mock<KeyedObserver<Any?>>()
+    private val observer2 = mock<KeyedObserver<Any?>>()
+    private val keyedObserver1 = mock<KeyedObserver<Any>>()
+    private val keyedObserver2 = mock<KeyedObserver<Any>>()
 
-    @Mock
-    private lateinit var observer1: KeyedObserver<Any?>
+    private val key1 = Object()
+    private val key2 = Object()
 
-    @Mock
-    private lateinit var observer2: KeyedObserver<Any?>
-
-    @Mock
-    private lateinit var keyedObserver1: KeyedObserver<Any>
-
-    @Mock
-    private lateinit var keyedObserver2: KeyedObserver<Any>
-
-    @Mock
-    private lateinit var key1: Any
-
-    @Mock
-    private lateinit var key2: Any
-
-    @Mock
-    private lateinit var executor: Executor
-
+    private val executor1: Executor = MoreExecutors.directExecutor()
+    private val executor2: Executor = MoreExecutors.newDirectExecutorService()
     private val keyedObservable = KeyedDataObservable<Any>()
 
     @Test
     fun addObserver_sameExecutor() {
-        keyedObservable.addObserver(observer1, executor)
-        keyedObservable.addObserver(observer1, executor)
+        keyedObservable.addObserver(observer1, executor1)
+        keyedObservable.addObserver(observer1, executor1)
     }
 
     @Test
     fun addObserver_keyedObserver_sameExecutor() {
-        keyedObservable.addObserver(key1, keyedObserver1, executor)
-        keyedObservable.addObserver(key1, keyedObserver1, executor)
+        keyedObservable.addObserver(key1, keyedObserver1, executor1)
+        keyedObservable.addObserver(key1, keyedObserver1, executor1)
     }
 
     @Test
     fun addObserver_differentExecutor() {
-        keyedObservable.addObserver(observer1, executor)
+        keyedObservable.addObserver(observer1, executor1)
         Assert.assertThrows(IllegalStateException::class.java) {
-            keyedObservable.addObserver(observer1, directExecutor())
+            keyedObservable.addObserver(observer1, executor2)
         }
     }
 
     @Test
     fun addObserver_keyedObserver_differentExecutor() {
-        keyedObservable.addObserver(key1, keyedObserver1, executor)
+        keyedObservable.addObserver(key1, keyedObserver1, executor1)
         Assert.assertThrows(IllegalStateException::class.java) {
-            keyedObservable.addObserver(key1, keyedObserver1, directExecutor())
+            keyedObservable.addObserver(key1, keyedObserver1, executor2)
         }
     }
 
@@ -93,7 +75,7 @@
     fun addObserver_weaklyReferenced() {
         val counter = AtomicInteger()
         var observer: KeyedObserver<Any?>? = KeyedObserver { _, _ -> counter.incrementAndGet() }
-        keyedObservable.addObserver(observer!!, directExecutor())
+        keyedObservable.addObserver(observer!!, executor1)
 
         keyedObservable.notifyChange(ChangeReason.UPDATE)
         assertThat(counter.get()).isEqualTo(1)
@@ -111,7 +93,7 @@
     fun addObserver_keyedObserver_weaklyReferenced() {
         val counter = AtomicInteger()
         var keyObserver: KeyedObserver<Any>? = KeyedObserver { _, _ -> counter.incrementAndGet() }
-        keyedObservable.addObserver(key1, keyObserver!!, directExecutor())
+        keyedObservable.addObserver(key1, keyObserver!!, executor1)
 
         keyedObservable.notifyChange(key1, ChangeReason.UPDATE)
         assertThat(counter.get()).isEqualTo(1)
@@ -127,45 +109,43 @@
 
     @Test
     fun addObserver_notifyObservers_removeObserver() {
-        keyedObservable.addObserver(observer1, directExecutor())
-        keyedObservable.addObserver(observer2, executor)
+        keyedObservable.addObserver(observer1, executor1)
+        keyedObservable.addObserver(observer2, executor2)
 
         keyedObservable.notifyChange(ChangeReason.UPDATE)
         verify(observer1).onKeyChanged(null, ChangeReason.UPDATE)
-        verify(observer2, never()).onKeyChanged(any(), any())
-        verify(executor).execute(any())
+        verify(observer2).onKeyChanged(null, ChangeReason.UPDATE)
 
-        reset(observer1, executor)
+        reset(observer1, observer2)
         keyedObservable.removeObserver(observer2)
 
         keyedObservable.notifyChange(ChangeReason.DELETE)
         verify(observer1).onKeyChanged(null, ChangeReason.DELETE)
-        verify(executor, never()).execute(any())
+        verify(observer2, never()).onKeyChanged(null, ChangeReason.DELETE)
     }
 
     @Test
     fun addObserver_keyedObserver_notifyObservers_removeObserver() {
-        keyedObservable.addObserver(key1, keyedObserver1, directExecutor())
-        keyedObservable.addObserver(key2, keyedObserver2, executor)
+        keyedObservable.addObserver(key1, keyedObserver1, executor1)
+        keyedObservable.addObserver(key2, keyedObserver2, executor2)
 
         keyedObservable.notifyChange(key1, ChangeReason.UPDATE)
         verify(keyedObserver1).onKeyChanged(key1, ChangeReason.UPDATE)
-        verify(keyedObserver2, never()).onKeyChanged(any(), any())
-        verify(executor, never()).execute(any())
+        verify(keyedObserver2, never()).onKeyChanged(key2, ChangeReason.UPDATE)
 
-        reset(keyedObserver1, executor)
-        keyedObservable.removeObserver(key2, keyedObserver2)
+        reset(keyedObserver1, keyedObserver2)
+        keyedObservable.removeObserver(key1, keyedObserver1)
 
         keyedObservable.notifyChange(key1, ChangeReason.DELETE)
-        verify(keyedObserver1).onKeyChanged(key1, ChangeReason.DELETE)
-        verify(executor, never()).execute(any())
+        verify(keyedObserver1, never()).onKeyChanged(key1, ChangeReason.DELETE)
+        verify(keyedObserver2, never()).onKeyChanged(key2, ChangeReason.DELETE)
     }
 
     @Test
     fun notifyChange_addMoreTypeObservers_checkOnKeyChanged() {
-        keyedObservable.addObserver(observer1, directExecutor())
-        keyedObservable.addObserver(key1, keyedObserver1, directExecutor())
-        keyedObservable.addObserver(key2, keyedObserver2, directExecutor())
+        keyedObservable.addObserver(observer1, executor1)
+        keyedObservable.addObserver(key1, keyedObserver1, executor1)
+        keyedObservable.addObserver(key2, keyedObserver2, executor1)
 
         keyedObservable.notifyChange(ChangeReason.UPDATE)
         verify(observer1).onKeyChanged(null, ChangeReason.UPDATE)
@@ -191,10 +171,10 @@
     fun notifyChange_addObserverWithinCallback() {
         // ConcurrentModificationException is raised if it is not implemented correctly
         val observer: KeyedObserver<Any?> = KeyedObserver { _, _ ->
-            keyedObservable.addObserver(observer1, executor)
+            keyedObservable.addObserver(observer1, executor1)
         }
 
-        keyedObservable.addObserver(observer, directExecutor())
+        keyedObservable.addObserver(observer, executor1)
 
         keyedObservable.notifyChange(ChangeReason.UPDATE)
         keyedObservable.removeObserver(observer)
@@ -204,12 +184,12 @@
     fun notifyChange_KeyedObserver_addObserverWithinCallback() {
         // ConcurrentModificationException is raised if it is not implemented correctly
         val keyObserver: KeyedObserver<Any?> = KeyedObserver { _, _ ->
-            keyedObservable.addObserver(key1, keyedObserver1, executor)
+            keyedObservable.addObserver(key1, keyedObserver1, executor1)
         }
 
-        keyedObservable.addObserver(key1, keyObserver, directExecutor())
+        keyedObservable.addObserver(key1, keyObserver, executor1)
 
         keyedObservable.notifyChange(key1, ChangeReason.UPDATE)
         keyedObservable.removeObserver(key1, keyObserver)
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt
index f065829..173c2b1 100644
--- a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/ObserverTest.kt
@@ -22,40 +22,33 @@
 import java.util.concurrent.Executor
 import java.util.concurrent.atomic.AtomicInteger
 import org.junit.Assert.assertThrows
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
 import org.mockito.kotlin.never
 import org.mockito.kotlin.reset
 import org.mockito.kotlin.verify
 
 @RunWith(AndroidJUnit4::class)
 class ObserverTest {
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+    private val observer1 = mock<Observer>()
+    private val observer2 = mock<Observer>()
 
-    @Mock private lateinit var observer1: Observer
-
-    @Mock private lateinit var observer2: Observer
-
-    @Mock private lateinit var executor: Executor
-
+    private val executor1: Executor = MoreExecutors.directExecutor()
+    private val executor2: Executor = MoreExecutors.newDirectExecutorService()
     private val observable = DataObservable()
 
     @Test
     fun addObserver_sameExecutor() {
-        observable.addObserver(observer1, executor)
-        observable.addObserver(observer1, executor)
+        observable.addObserver(observer1, executor1)
+        observable.addObserver(observer1, executor1)
     }
 
     @Test
     fun addObserver_differentExecutor() {
-        observable.addObserver(observer1, executor)
+        observable.addObserver(observer1, executor1)
         assertThrows(IllegalStateException::class.java) {
-            observable.addObserver(observer1, MoreExecutors.directExecutor())
+            observable.addObserver(observer1, executor2)
         }
     }
 
@@ -63,7 +56,7 @@
     fun addObserver_weaklyReferenced() {
         val counter = AtomicInteger()
         var observer: Observer? = Observer { counter.incrementAndGet() }
-        observable.addObserver(observer!!, MoreExecutors.directExecutor())
+        observable.addObserver(observer!!, executor1)
 
         observable.notifyChange(ChangeReason.UPDATE)
         assertThat(counter.get()).isEqualTo(1)
@@ -79,31 +72,27 @@
 
     @Test
     fun addObserver_notifyObservers_removeObserver() {
-        observable.addObserver(observer1, MoreExecutors.directExecutor())
-        observable.addObserver(observer2, executor)
+        observable.addObserver(observer1, executor1)
+        observable.addObserver(observer2, executor2)
 
         observable.notifyChange(ChangeReason.DELETE)
 
         verify(observer1).onChanged(ChangeReason.DELETE)
-        verify(observer2, never()).onChanged(any())
-        verify(executor).execute(any())
+        verify(observer2).onChanged(ChangeReason.DELETE)
 
-        reset(observer1, executor)
+        reset(observer1, observer2)
         observable.removeObserver(observer2)
 
         observable.notifyChange(ChangeReason.UPDATE)
         verify(observer1).onChanged(ChangeReason.UPDATE)
-        verify(executor, never()).execute(any())
+        verify(observer2, never()).onChanged(ChangeReason.UPDATE)
     }
 
     @Test
     fun notifyChange_addObserverWithinCallback() {
         // ConcurrentModificationException is raised if it is not implemented correctly
-        val observer = Observer { observable.addObserver(observer1, executor) }
-        observable.addObserver(
-            observer,
-            MoreExecutors.directExecutor()
-        )
+        val observer = Observer { observable.addObserver(observer1, executor1) }
+        observable.addObserver(observer, executor1)
         observable.notifyChange(ChangeReason.UPDATE)
         observable.removeObserver(observer)
     }
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/SharedPreferencesStorageTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/SharedPreferencesStorageTest.kt
new file mode 100644
index 0000000..fec7d75
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/SharedPreferencesStorageTest.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.Application
+import android.content.Context
+import android.content.SharedPreferences
+import android.os.Build
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.util.concurrent.Executor
+import kotlin.random.Random
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+
+/** Tests of [SharedPreferencesStorage]. */
+@RunWith(AndroidJUnit4::class)
+class SharedPreferencesStorageTest {
+    private val random = Random.Default
+    private val application: Application = ApplicationProvider.getApplicationContext()
+    private val map =
+        mapOf(
+            "boolean" to true,
+            "float" to random.nextFloat(),
+            "int" to random.nextInt(),
+            "long" to random.nextLong(),
+            "string" to "string",
+            "set" to setOf("string"),
+        )
+
+    @After
+    fun tearDown() {
+        application.getSharedPreferences(NAME, MODE).edit().clear().applySync()
+    }
+
+    @Test
+    fun constructors() {
+        val storage1 = SharedPreferencesStorage(application, NAME, MODE)
+        val storage2 =
+            SharedPreferencesStorage(
+                application,
+                NAME,
+                application.getSharedPreferences(NAME, MODE),
+            )
+        assertThat(storage1.sharedPreferences).isSameInstanceAs(storage2.sharedPreferences)
+    }
+
+    @Test
+    fun observer() {
+        val observer = mock<KeyedObserver<Any?>>()
+        val keyedObserver = mock<KeyedObserver<Any>>()
+        val storage = SharedPreferencesStorage(application, NAME, MODE)
+        val executor: Executor = MoreExecutors.directExecutor()
+        storage.addObserver(observer, executor)
+        storage.addObserver("key", keyedObserver, executor)
+
+        storage.sharedPreferences.edit().putString("key", "string").applySync()
+        verify(observer).onKeyChanged("key", ChangeReason.UPDATE)
+        verify(keyedObserver).onKeyChanged("key", ChangeReason.UPDATE)
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            storage.sharedPreferences.edit().clear().applySync()
+            verify(observer).onKeyChanged(null, ChangeReason.DELETE)
+            verify(keyedObserver).onKeyChanged("key", ChangeReason.DELETE)
+        }
+    }
+
+    @Test
+    fun prepareBackup_commitFailed() {
+        val editor = mock<SharedPreferences.Editor> { on { commit() } doReturn false }
+        val storage =
+            spy(SharedPreferencesStorage(application, NAME, MODE)) {
+                onGeneric { mergeSharedPreferences(any(), any(), any()) } doReturn editor
+            }
+        storage.prepareBackup(File(""))
+    }
+
+    @Test
+    fun backupAndRestore() {
+        fun test(codec: BackupCodec) {
+            val storage = SharedPreferencesStorage(application, NAME, MODE, codec)
+            storage.mergeSharedPreferences(storage.sharedPreferences, map, "op").commit()
+            assertThat(storage.sharedPreferences.all).isEqualTo(map)
+
+            val outputStream = ByteArrayOutputStream()
+            assertThat(storage.toBackupRestoreEntity().backup(BackupContext(mock()), outputStream))
+                .isEqualTo(EntityBackupResult.UPDATE)
+            val payload = outputStream.toByteArray()
+
+            storage.sharedPreferences.edit().clear().commit()
+            assertThat(storage.sharedPreferences.all).isEmpty()
+
+            BackupRestoreFileArchiver(application, listOf(storage), "archiver")
+                .restoreEntity(newBackupDataInputStream(storage.storageFilePath, payload))
+            assertThat(storage.sharedPreferences.all).isEqualTo(map)
+        }
+
+        for (codec in allCodecs()) test(codec)
+    }
+
+    @Test
+    fun mergeSharedPreferences_filter() {
+        val storage =
+            SharedPreferencesStorage(application, NAME, MODE) { key, value ->
+                key == "float" || value is String
+            }
+        storage.mergeSharedPreferences(storage.sharedPreferences, map, "op").apply()
+        assertThat(storage.sharedPreferences.all)
+            .containsExactly("float", map["float"], "string", map["string"])
+    }
+
+    @Test
+    fun mergeSharedPreferences_invalidSet() {
+        val storage = SharedPreferencesStorage(application, NAME, MODE, verbose = true)
+        storage
+            .mergeSharedPreferences(
+                storage.sharedPreferences,
+                mapOf<String, Any>("set" to setOf(Any())),
+                "op"
+            )
+            .apply()
+        assertThat(storage.sharedPreferences.all).isEmpty()
+    }
+
+    @Test
+    fun mergeSharedPreferences_unknownType() {
+        val storage = SharedPreferencesStorage(application, NAME, MODE)
+        storage
+            .mergeSharedPreferences(storage.sharedPreferences, map + ("key" to Any()), "op")
+            .apply()
+        assertThat(storage.sharedPreferences.all).isEqualTo(map)
+    }
+
+    @Test
+    fun mergeSharedPreferences() {
+        val storage = SharedPreferencesStorage(application, NAME, MODE, verbose = true)
+        storage.mergeSharedPreferences(storage.sharedPreferences, map, "op").apply()
+        assertThat(storage.sharedPreferences.all).isEqualTo(map)
+    }
+
+    private fun SharedPreferences.Editor.applySync() {
+        apply()
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+    }
+
+    companion object {
+        private const val NAME = "pref"
+        private const val MODE = Context.MODE_PRIVATE
+    }
+}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/TestUtils.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/TestUtils.kt
new file mode 100644
index 0000000..823d222
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/TestUtils.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.backup.BackupDataInput
+import android.app.backup.BackupDataInputStream
+import android.os.Build
+import java.io.ByteArrayInputStream
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.mock
+
+internal const val MAX_DATA_SIZE = 1 shl 12
+
+internal fun allCodecs() =
+    arrayOf<BackupCodec>(
+        BackupNoOpCodec(),
+    ) + zipCodecs()
+
+internal fun zipCodecs() =
+    arrayOf<BackupCodec>(
+        BackupZipCodec.DEFAULT_COMPRESSION,
+        BackupZipCodec.BEST_COMPRESSION,
+        BackupZipCodec.BEST_SPEED,
+    )
+
+internal fun <T : Any> Class<T>.newInstance(arg: Any, type: Class<*> = arg.javaClass): T =
+    getDeclaredConstructor(type).apply { isAccessible = true }.newInstance(arg)
+
+internal fun newBackupDataInputStream(
+    key: String,
+    data: ByteArray,
+    e: Exception? = null,
+): BackupDataInputStream {
+    // ShadowBackupDataOutput does not write data to file, so mock for reading data
+    val inputStream = ByteArrayInputStream(data)
+    val backupDataInput =
+        mock<BackupDataInput> {
+            on { readEntityData(any(), any(), any()) } doAnswer
+                {
+                    if (e != null) throw e
+                    val buf = it.arguments[0] as ByteArray
+                    val offset = it.arguments[1] as Int
+                    val size = it.arguments[2] as Int
+                    inputStream.read(buf, offset, size)
+                }
+        }
+    return BackupDataInputStream::class
+        .java
+        .newInstance(backupDataInput, BackupDataInput::class.java)
+        .apply {
+            setKey(key)
+            setDataSize(data.size)
+        }
+}
+
+internal fun BackupDataInputStream.setKey(value: Any) {
+    val field = javaClass.getDeclaredField("key")
+    field.isAccessible = true
+    field.set(this, value)
+}
+
+internal fun BackupDataInputStream.setDataSize(dataSize: Int) {
+    val field = javaClass.getDeclaredField("dataSize")
+    field.isAccessible = true
+    field.setInt(this, dataSize)
+}
+
+internal fun isRobolectric() = Build.FINGERPRINT.contains("robolectric")
diff --git a/packages/SettingsLib/FooterPreference/res/drawable-v35/settingslib_ic_info_outline_24.xml b/packages/SettingsLib/FooterPreference/res/drawable-v35/settingslib_ic_info_outline_24.xml
deleted file mode 100644
index c7fbb5f..0000000
--- a/packages/SettingsLib/FooterPreference/res/drawable-v35/settingslib_ic_info_outline_24.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2024 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/settingslib_materialColorOnSurfaceVariant"
-        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
-</vector>
diff --git a/packages/SettingsLib/FooterPreference/res/layout-v35/preference_footer.xml b/packages/SettingsLib/FooterPreference/res/layout-v35/preference_footer.xml
deleted file mode 100644
index a2b9648..0000000
--- a/packages/SettingsLib/FooterPreference/res/layout-v35/preference_footer.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2024 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:background="?android:attr/selectableItemBackground"
-    android:orientation="vertical"
-    android:clipToPadding="false">
-
-    <LinearLayout
-        android:id="@+id/icon_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minWidth="56dp"
-        android:gravity="start|top"
-        android:orientation="horizontal"
-        android:paddingEnd="12dp"
-        android:paddingTop="16dp"
-        android:paddingBottom="4dp">
-        <ImageView
-            android:id="@android:id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-        <TextView
-            android:id="@android:id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start"
-            android:textAlignment="viewStart"
-            android:paddingTop="16dp"
-            android:paddingBottom="8dp"
-            android:textColor="@color/settingslib_materialColorOnSurfaceVariant"
-            android:hyphenationFrequency="normalFast"
-            android:lineBreakWordStyle="phrase"
-            android:ellipsize="marquee" />
-
-        <com.android.settingslib.widget.LinkTextView
-            android:id="@+id/settingslib_learn_more"
-            android:text="@string/settingslib_learn_more_text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start"
-            android:textAlignment="viewStart"
-            android:paddingBottom="8dp"
-            android:clickable="true"
-            android:visibility="gone" />
-    </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/Graph/Android.bp b/packages/SettingsLib/Graph/Android.bp
new file mode 100644
index 0000000..e2ed1e4
--- /dev/null
+++ b/packages/SettingsLib/Graph/Android.bp
@@ -0,0 +1,21 @@
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "SettingsLibGraph-srcs",
+    srcs: ["src/**/*"],
+}
+
+android_library {
+    name: "SettingsLibGraph",
+    defaults: [
+        "SettingsLintDefaults",
+    ],
+    srcs: [":SettingsLibGraph-srcs"],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "androidx.preference_preference",
+    ],
+    kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SettingsLib/Graph/AndroidManifest.xml b/packages/SettingsLib/Graph/AndroidManifest.xml
new file mode 100644
index 0000000..93acb35
--- /dev/null
+++ b/packages/SettingsLib/Graph/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settingslib.graph">
+
+  <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceScreenManager.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceScreenManager.kt
new file mode 100644
index 0000000..9231f40
--- /dev/null
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceScreenManager.kt
@@ -0,0 +1,70 @@
+package com.android.settingslib.graph
+
+import androidx.annotation.StringRes
+import androidx.annotation.XmlRes
+import androidx.preference.Preference
+import androidx.preference.PreferenceManager
+import androidx.preference.PreferenceScreen
+
+/** Manager to create and initialize preference screen. */
+class PreferenceScreenManager(private val preferenceManager: PreferenceManager) {
+    private val context = preferenceManager.context
+    // the map will preserve order
+    private val updaters = mutableMapOf<String, PreferenceUpdater>()
+    private val screenUpdaters = mutableListOf<PreferenceScreenUpdater>()
+
+    /** Creates an empty [PreferenceScreen]. */
+    fun createPreferenceScreen(): PreferenceScreen =
+        preferenceManager.createPreferenceScreen(context)
+
+    /** Creates [PreferenceScreen] from resource. */
+    fun createPreferenceScreen(@XmlRes xmlRes: Int): PreferenceScreen =
+        preferenceManager.inflateFromResource(context, xmlRes, null)
+
+    /** Adds updater for given preference. */
+    fun addPreferenceUpdater(@StringRes key: Int, updater: PreferenceUpdater) =
+        addPreferenceUpdater(context.getString(key), updater)
+
+    /** Adds updater for given preference. */
+    fun addPreferenceUpdater(
+        key: String,
+        updater: PreferenceUpdater,
+    ): PreferenceScreenManager {
+        updaters.put(key, updater)?.let { if (it != updater) throw IllegalArgumentException() }
+        return this
+    }
+
+    /** Adds updater for preference screen. */
+    fun addPreferenceScreenUpdater(updater: PreferenceScreenUpdater): PreferenceScreenManager {
+        screenUpdaters.add(updater)
+        return this
+    }
+
+    /** Adds a list of updaters for preference screen. */
+    fun addPreferenceScreenUpdater(
+        vararg updaters: PreferenceScreenUpdater,
+    ): PreferenceScreenManager {
+        screenUpdaters.addAll(updaters)
+        return this
+    }
+
+    /** Updates preference screen with registered updaters. */
+    fun updatePreferenceScreen(preferenceScreen: PreferenceScreen) {
+        for ((key, updater) in updaters) {
+            preferenceScreen.findPreference<Preference>(key)?.let { updater.updatePreference(it) }
+        }
+        for (updater in screenUpdaters) {
+            updater.updatePreferenceScreen(preferenceScreen)
+        }
+    }
+}
+
+/** Updater of [Preference]. */
+interface PreferenceUpdater {
+    fun updatePreference(preference: Preference)
+}
+
+/** Updater of [PreferenceScreen]. */
+interface PreferenceScreenUpdater {
+    fun updatePreferenceScreen(preferenceScreen: PreferenceScreen)
+}
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceScreenProvider.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceScreenProvider.kt
new file mode 100644
index 0000000..9e4c1f6
--- /dev/null
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceScreenProvider.kt
@@ -0,0 +1,26 @@
+package com.android.settingslib.graph
+
+import android.content.Context
+import androidx.preference.PreferenceScreen
+
+/**
+ * Interface to provide [PreferenceScreen].
+ *
+ * It is expected to be implemented by Activity/Fragment and the implementation needs to use
+ * [Context] APIs (e.g. `getContext()`, `getActivity()`) with caution: preference screen creation
+ * could happen in background service, where the Activity/Fragment lifecycle callbacks (`onCreate`,
+ * `onDestroy`, etc.) are not invoked.
+ */
+interface PreferenceScreenProvider {
+
+    /**
+     * Creates [PreferenceScreen].
+     *
+     * Preference screen creation could happen in background service. The implementation MUST use
+     * given [context] instead of APIs like `getContext()`, `getActivity()`, etc.
+     */
+    fun createPreferenceScreen(
+        context: Context,
+        preferenceScreenManager: PreferenceScreenManager,
+    ): PreferenceScreen?
+}
diff --git a/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml
index 9095f8e..f0bee5e 100644
--- a/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="help_feedback_label" msgid="7106780063063027882">"Ajuda e comentários"</string>
+    <string name="help_feedback_label" msgid="7106780063063027882">"Ajuda e feedback"</string>
 </resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/color-night-v35/settingslib_main_switch_text_color.xml b/packages/SettingsLib/MainSwitchPreference/res/color-night-v35/settingslib_main_switch_text_color.xml
new file mode 100644
index 0000000..ea15a67
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/color-night-v35/settingslib_main_switch_text_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+          android:color="@color/settingslib_materialColorOnPrimaryContainer"
+          android:alpha="?android:attr/disabledAlpha" />
+    <item android:color="@color/settingslib_materialColorOnPrimaryContainer"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/MainSwitchPreference/res/color-v35/settingslib_main_switch_text_color.xml b/packages/SettingsLib/MainSwitchPreference/res/color-v35/settingslib_main_switch_text_color.xml
new file mode 100644
index 0000000..ea15a67
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/color-v35/settingslib_main_switch_text_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+          android:color="@color/settingslib_materialColorOnPrimaryContainer"
+          android:alpha="?android:attr/disabledAlpha" />
+    <item android:color="@color/settingslib_materialColorOnPrimaryContainer"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/ProfileSelector/res/color-night-v35/settingslib_tabs_indicator_color.xml b/packages/SettingsLib/ProfileSelector/res/color-night-v35/settingslib_tabs_indicator_color.xml
new file mode 100644
index 0000000..5192a9a
--- /dev/null
+++ b/packages/SettingsLib/ProfileSelector/res/color-night-v35/settingslib_tabs_indicator_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/settingslib_materialColorSecondaryFixed" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/ProfileSelector/res/color-v35/settingslib_tabs_indicator_color.xml b/packages/SettingsLib/ProfileSelector/res/color-v35/settingslib_tabs_indicator_color.xml
new file mode 100644
index 0000000..4b16832
--- /dev/null
+++ b/packages/SettingsLib/ProfileSelector/res/color-v35/settingslib_tabs_indicator_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/settingslib_materialColorPrimaryFixed" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml
index fa5df16..b5534b9 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-hi/strings.xml
@@ -18,5 +18,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="enabled_by_admin" msgid="6630472777476410137">"एडमिन की ओर से चालू किया गया"</string>
-    <string name="disabled_by_admin" msgid="4023569940620832713">"एडमिन की ओर से बंद किया गया"</string>
+    <string name="disabled_by_admin" msgid="4023569940620832713">"एडमिन ने यह सुविधा बंद की है"</string>
 </resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml b/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml
index 23f46bf..473231a 100644
--- a/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-bn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="search_menu" msgid="1914043873178389845">"সেটিংসে সার্চ করুন"</string>
+    <string name="search_menu" msgid="1914043873178389845">"সার্চ সেটিংস"</string>
 </resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml b/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml
index 0d3a4da..99a9b05 100644
--- a/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-ms/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="search_menu" msgid="1914043873178389845">"Tetapan carian"</string>
+    <string name="search_menu" msgid="1914043873178389845">"Cari tetapan"</string>
 </resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/color-night-v31/settingslib_switch_track_on.xml b/packages/SettingsLib/SettingsTheme/res/color-night-v31/settingslib_switch_track_on.xml
index 81ddf29..1429e3b 100644
--- a/packages/SettingsLib/SettingsTheme/res/color-night-v31/settingslib_switch_track_on.xml
+++ b/packages/SettingsLib/SettingsTheme/res/color-night-v31/settingslib_switch_track_on.xml
@@ -14,7 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
   -->
-
+<!--Deprecated. After sdk 35 don't use it.-->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:color="@android:color/system_accent2_500" android:lStar="51" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color-night-v35/settingslib_switch_track_outline_color.xml b/packages/SettingsLib/SettingsTheme/res/color-night-v35/settingslib_switch_track_outline_color.xml
new file mode 100644
index 0000000..eedc364
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color-night-v35/settingslib_switch_track_outline_color.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Disabled status of thumb -->
+    <item android:state_enabled="false"
+          android:color="@color/settingslib_materialColorOutline"
+          android:alpha="?android:attr/disabledAlpha" />
+    <!-- Toggle off status of thumb -->
+    <item android:state_checked="false"
+          android:color="@color/settingslib_materialColorOutline" />
+    <!-- Enabled or toggle on status of thumb -->
+    <item android:color="@color/settingslib_track_on_color" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml
index 037b80a..b46181e 100644
--- a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml
+++ b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml
@@ -13,6 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+<!--Deprecated. After sdk 35, don't use it, using materialColorOnSurfaceInverse in light theme	-->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:color="@android:color/system_neutral1_500" android:lStar="98" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_switch_track_off.xml b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_switch_track_off.xml
index 762bb31..f0bcf0a 100644
--- a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_switch_track_off.xml
+++ b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_switch_track_off.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
+<!--Deprecated. After sdk 35 don't use it.-->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:color="@android:color/system_neutral2_500" android:lStar="45" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_preference_bg_color.xml b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_preference_bg_color.xml
new file mode 100644
index 0000000..4ced9f2
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_preference_bg_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:color="@color/settingslib_materialColorSecondaryContainer"/>
+    <item android:state_selected="true" android:color="@color/settingslib_materialColorSecondaryContainer"/>
+    <item android:state_activated="true" android:color="@color/settingslib_materialColorSecondaryContainer"/>
+    <item android:color="@color/settingslib_materialColorSurfaceContainerHighest"/> <!-- not selected -->
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_switch_track_outline_color.xml b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_switch_track_outline_color.xml
new file mode 100644
index 0000000..eedc364
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_switch_track_outline_color.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Disabled status of thumb -->
+    <item android:state_enabled="false"
+          android:color="@color/settingslib_materialColorOutline"
+          android:alpha="?android:attr/disabledAlpha" />
+    <!-- Toggle off status of thumb -->
+    <item android:state_checked="false"
+          android:color="@color/settingslib_materialColorOutline" />
+    <!-- Enabled or toggle on status of thumb -->
+    <item android:color="@color/settingslib_track_on_color" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_primary.xml b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_primary.xml
new file mode 100644
index 0000000..230eb7d
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_primary.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:alpha="?android:attr/disabledAlpha"
+        android:color="@color/settingslib_materialColorOnSurface"/>
+    <item android:color="@color/settingslib_materialColorOnSurface"/>
+</selector>
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_secondary.xml b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_secondary.xml
new file mode 100644
index 0000000..5bd2a29
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color-v35/settingslib_text_color_secondary.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:alpha="?android:attr/disabledAlpha"
+        android:color="@color/settingslib_materialColorOnSurfaceVariant"/>
+    <item android:color="@color/settingslib_materialColorOnSurfaceVariant"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
index 77979f0..87552477 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
@@ -16,11 +16,12 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:viewportWidth="18"
-        android:viewportHeight="18"
-        android:width="24dp"
-        android:height="24dp">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="@color/settingslib_materialColorOnPrimaryContainer">
     <path
-        android:pathData="M7 10l5 5 5 -5z"
-        android:fillColor="@color/settingslib_materialColorOnPrimaryContainer"/>
+        android:fillColor="@android:color/white"
+        android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6 -1.41,-1.41z"/>
 </vector>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_progress_horizontal.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_progress_horizontal.xml
new file mode 100644
index 0000000..3cb3435
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_progress_horizontal.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<layer-list
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:id="@android:id/background">
+        <shape>
+            <corners android:radius="8dp" />
+            <solid android:color="@color/settingslib_materialColorSurfaceVariant" />
+        </shape>
+    </item>
+
+    <item
+        android:id="@android:id/progress">
+        <scale android:scaleWidth="100%" android:useIntrinsicSizeAsMinimum="true">
+            <shape>
+                <corners android:radius="8dp" />
+                <solid android:color="?android:attr/textColorPrimary" />
+                <size android:width="8dp"/>
+            </shape>
+        </scale>
+    </item>
+</layer-list>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background.xml
new file mode 100644
index 0000000..285ab73
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:left="?android:attr/listPreferredItemPaddingStart"
+        android:right="?android:attr/listPreferredItemPaddingEnd"
+        android:top="1dp">
+        <shape android:shape="rectangle">
+            <solid
+                android:color="@color/settingslib_preference_bg_color" />
+            <corners
+                android:radius="?android:attr/dialogCornerRadius" />
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom.xml
new file mode 100644
index 0000000..e417307
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_bottom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:left="?android:attr/listPreferredItemPaddingStart"
+        android:right="?android:attr/listPreferredItemPaddingEnd"
+        android:top="1dp">
+        <shape android:shape="rectangle">
+            <solid
+                android:color="@color/settingslib_preference_bg_color" />
+            <corners
+                android:topLeftRadius="0dp"
+                android:bottomLeftRadius="?android:attr/dialogCornerRadius"
+                android:topRightRadius="0dp"
+                android:bottomRightRadius="?android:attr/dialogCornerRadius" />
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center.xml
new file mode 100644
index 0000000..e964657
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_center.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:left="?android:attr/listPreferredItemPaddingStart"
+        android:right="?android:attr/listPreferredItemPaddingEnd"
+        android:top="1dp">
+        <shape android:shape="rectangle">
+            <solid
+                android:color="@color/settingslib_preference_bg_color" />
+            <corners
+                android:radius="1dp" />
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top.xml
new file mode 100644
index 0000000..a9d69c2
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_round_background_top.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:left="?android:attr/listPreferredItemPaddingStart"
+        android:right="?android:attr/listPreferredItemPaddingEnd"
+        android:top="1dp">
+        <shape android:shape="rectangle">
+            <solid
+                android:color="@color/settingslib_preference_bg_color" />
+            <corners
+                android:topLeftRadius="?android:attr/dialogCornerRadius"
+                android:bottomLeftRadius="0dp"
+                android:topRightRadius="?android:attr/dialogCornerRadius"
+                android:bottomRightRadius="0dp" />
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
index 5411591..0a36a4f 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
@@ -29,17 +29,20 @@
     <color name="settingslib_track_off_color">@android:color/system_neutral1_700</color>
 
     <!-- Dialog accent color -->
+    <!--Deprecated. After sdk 35 don't use it, using materialColorPrimary-->
     <color name="settingslib_dialog_accent">@android:color/system_accent1_100</color>
     <!-- Dialog background color. -->
     <color name="settingslib_dialog_background">@color/settingslib_surface_dark</color>
     <!-- Dialog error color. -->
     <color name="settingslib_dialog_colorError">#f28b82</color> <!-- Red 300 -->
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_colorSurfaceVariant">@android:color/system_neutral1_700</color>
 
     <color name="settingslib_colorSurfaceHeader">@android:color/system_neutral1_700</color>
 
     <!-- copy from accent_primary_variant_dark_device_default-->
+    <!-- TODO: deprecate it after moving into partner code-->
     <color name="settingslib_accent_primary_variant">@android:color/system_accent1_300</color>
 
     <color name="settingslib_text_color_primary_device_default">@android:color/system_neutral1_50</color>
@@ -48,7 +51,9 @@
 
     <color name="settingslib_text_color_preference_category_title">@android:color/system_accent1_100</color>
 
+    <!--Deprecated. After sdk 35, don't use it, using materialColorOnSurfaceInverse in dark theme	-->
     <color name="settingslib_surface_dark">@android:color/system_neutral1_800</color>
 
+    <!--Deprecated. After sdk 35, don't use it-->
     <color name="settingslib_colorSurface">@color/settingslib_surface_dark</color>
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v34/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v34/colors.xml
index beed90e..8cfe54f 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v34/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v34/colors.xml
@@ -38,7 +38,8 @@
     <color name="settingslib_track_off_color">@android:color/system_surface_container_highest_dark
     </color>
 
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurface-->
     <color name="settingslib_text_color_primary_device_default">@android:color/system_on_surface_dark</color>
-
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurfaceVariant-->
     <color name="settingslib_text_color_secondary_device_default">@android:color/system_on_surface_variant_dark</color>
 </resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
index 229d9e3..7c76ea1 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
@@ -16,6 +16,34 @@
 -->
 
 <resources>
+    <!-- Material next state on color-->
+    <color name="settingslib_state_on_color">@color/settingslib_materialColorPrimaryContainer</color>
+
+    <!-- Material next state off color-->
+    <color name="settingslib_state_off_color">@color/settingslib_materialColorPrimaryContainer</color>
+
+    <!-- Material next thumb disable color-->
+    <color name="settingslib_thumb_disabled_color">@color/settingslib_materialColorOutline</color>
+
+    <!-- Material next thumb off color-->
+    <color name="settingslib_thumb_on_color">@color/settingslib_materialColorOnPrimary</color>
+
+    <!-- Material next thumb off color-->
+    <color name="settingslib_thumb_off_color">@color/settingslib_materialColorOutline</color>
+
+    <!-- Material next track on color-->
+    <color name="settingslib_track_on_color">@color/settingslib_materialColorPrimary</color>
+
+    <!-- Material next track off color-->
+    <color name="settingslib_track_off_color">@color/settingslib_materialColorSurfaceContainerHighest</color>
+
+    <!-- Dialog background color. -->
+    <color name="settingslib_dialog_background">@color/settingslib_materialColorSurfaceInverse</color>
+
+    <color name="settingslib_colorSurfaceHeader">@color/settingslib_materialColorSurfaceVariant</color>
+
+    <color name="settingslib_text_color_preference_category_title">@color/settingslib_materialColorPrimary</color>
+
     <color name="settingslib_materialColorSurfaceContainerLowest">@android:color/system_surface_container_lowest_dark</color>
     <color name="settingslib_materialColorOnSecondaryContainer">@android:color/system_on_secondary_container_dark</color>
     <color name="settingslib_materialColorOnTertiaryContainer">@android:color/system_on_tertiary_container_dark</color>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
index fe47e85..7706e0e 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
@@ -35,49 +35,57 @@
     <color name="settingslib_track_off_color">@color/settingslib_switch_track_off</color>
 
     <!-- Dialog accent color -->
+    <!--Deprecated. After sdk 35 don't use it, using materialColorPrimary-->
     <color name="settingslib_dialog_accent">@android:color/system_accent1_600</color>
     <!-- Dialog background color -->
     <color name="settingslib_dialog_background">@color/settingslib_surface_light</color>
     <!-- Dialog error color. -->
     <color name="settingslib_dialog_colorError">#d93025</color> <!-- Red 600 -->
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_colorSurfaceVariant">@android:color/system_neutral2_100</color>
 
     <color name="settingslib_colorSurfaceHeader">@android:color/system_neutral1_100</color>
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_accent_device_default_dark">@android:color/system_accent1_100</color>
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_accent_device_default_light">@android:color/system_accent1_600</color>
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_primary_dark_device_default_settings">@android:color/system_neutral1_900</color>
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_primary_device_default_settings_light">@android:color/system_neutral1_50</color>
 
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_accent_primary_device_default">@android:color/system_accent1_100</color>
 
     <!-- copy from accent_primary_variant_light_device_default-->
+    <!-- TODO: deprecate it after moving into partner code-->
     <color name="settingslib_accent_primary_variant">@android:color/system_accent1_600</color>
-
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_accent_secondary_device_default">@android:color/system_accent2_100</color>
-
+    <!--Deprecated. After sdk 35 don't use it.using materialColorOnSurfaceInverse in dark theme-->
     <color name="settingslib_background_device_default_dark">@android:color/system_neutral1_900</color>
-
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurfaceInverse in light theme-->
     <color name="settingslib_background_device_default_light">@android:color/system_neutral1_50</color>
-
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurface-->
     <color name="settingslib_text_color_primary_device_default">@android:color/system_neutral1_900</color>
-
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurfaceVariant-->
     <color name="settingslib_text_color_secondary_device_default">@android:color/system_neutral2_700</color>
 
     <color name="settingslib_text_color_preference_category_title">@android:color/system_accent1_600</color>
 
     <color name="settingslib_ripple_color">?android:attr/colorControlHighlight</color>
 
-    <color name="settingslib_material_grey_900">#ff212121</color>
-
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_colorAccentPrimary">@color/settingslib_accent_primary_device_default</color>
-
+    <!--Deprecated. After sdk 35 don't use it.-->
     <color name="settingslib_colorAccentSecondary">@color/settingslib_accent_secondary_device_default</color>
 
+    <!--Deprecated. After sdk 35, don't use it-->
     <color name="settingslib_colorSurface">@color/settingslib_surface_light</color>
 
     <color name="settingslib_spinner_title_color">@android:color/system_neutral1_900</color>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
index e4befc29..a9534c3 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
@@ -17,6 +17,7 @@
 <resources>
     <style name="PreferenceTheme.SettingsLib" parent="@style/PreferenceThemeOverlay">
         <item name="preferenceCategoryTitleTextAppearance">@style/TextAppearance.CategoryTitle.SettingsLib</item>
+        <item name="preferenceCategoryTitleTextColor">@color/settingslib_text_color_preference_category_title</item>
         <item name="preferenceScreenStyle">@style/SettingsPreferenceScreen.SettingsLib</item>
         <item name="preferenceCategoryStyle">@style/SettingsCategoryPreference.SettingsLib</item>
         <item name="preferenceStyle">@style/SettingsPreference.SettingsLib</item>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml
index 24e3c46..fb637fb 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml
@@ -16,9 +16,11 @@
   -->
 
 <resources>
-    <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v31" >
+    <style name="Theme.SettingsBase_v33" parent="Theme.SettingsBase_v31" >
         <item name="android:spinnerStyle">@style/Spinner.SettingsLib</item>
         <item name="android:spinnerItemStyle">@style/SpinnerItem.SettingsLib</item>
         <item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItem.SettingsLib</item>
     </style>
+
+    <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v33" />
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v34/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v34/colors.xml
index 3709b5d..185ac3e 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v34/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v34/colors.xml
@@ -39,8 +39,8 @@
 
     <!-- Material next track outline color-->
     <color name="settingslib_track_online_color">@color/settingslib_switch_track_outline_color</color>
-
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurface-->
     <color name="settingslib_text_color_primary_device_default">@android:color/system_on_surface_light</color>
-
+    <!--Deprecated. After sdk 35 don't use it. using materialColorOnSurfaceVariant-->
     <color name="settingslib_text_color_secondary_device_default">@android:color/system_on_surface_variant_light</color>
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
index 2691344..2a6499a 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
@@ -16,12 +16,42 @@
 -->
 
 <resources>
+    <!-- Material next state on color-->
+    <color name="settingslib_state_on_color">@color/settingslib_materialColorPrimaryContainer</color>
+
+    <!-- Material next state off color-->
+    <color name="settingslib_state_off_color">@color/settingslib_materialColorPrimaryContainer</color>
+
+    <!-- Material next thumb disable color-->
+    <color name="settingslib_thumb_disabled_color">@color/settingslib_materialColorOutline</color>
+
+    <!-- Material next thumb off color-->
+    <color name="settingslib_thumb_on_color">@color/settingslib_materialColorOnPrimary</color>
+
+    <!-- Material next thumb off color-->
+    <color name="settingslib_thumb_off_color">@color/settingslib_materialColorOutline</color>
+
+    <!-- Material next track on color-->
+    <color name="settingslib_track_on_color">@color/settingslib_materialColorPrimary</color>
+
+    <!-- Material next track off color-->
+    <color name="settingslib_track_off_color">@color/settingslib_materialColorSurfaceContainerHighest</color>
+
+    <!-- Dialog background color. -->
+    <color name="settingslib_dialog_background">@color/settingslib_materialColorSurfaceInverse</color>
+
+    <!-- Material next track outline color-->
+    <color name="settingslib_track_online_color">@color/settingslib_switch_track_outline_color</color>
+
+    <color name="settingslib_colorSurfaceHeader">@color/settingslib_materialColorSurfaceVariant</color>
+
+    <color name="settingslib_text_color_preference_category_title">@color/settingslib_materialColorPrimary</color>
+
     <!-- The text color of spinner title -->
     <color name="settingslib_spinner_title_color">@color/settingslib_materialColorOnPrimaryContainer</color>
     <!-- The text color of dropdown item title -->
     <color name="settingslib_spinner_dropdown_color">@color/settingslib_materialColorOnPrimaryContainer</color>
 
-
     <color name="settingslib_materialColorOnSecondaryFixedVariant">@android:color/system_on_secondary_fixed_variant</color>
     <color name="settingslib_materialColorOnTertiaryFixedVariant">@android:color/system_on_tertiary_fixed_variant</color>
     <color name="settingslib_materialColorSurfaceContainerLowest">@android:color/system_surface_container_lowest_light</color>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v35/styles.xml
deleted file mode 100644
index fff41c3..0000000
--- a/packages/SettingsLib/SettingsTheme/res/values-v35/styles.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2024 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<resources>
-    <style name="TextAppearance.TopIntroText"
-        parent="@android:style/TextAppearance.DeviceDefault">
-        <item name="android:textSize">14sp</item>
-        <item name="android:textColor">@color/settingslib_materialColorOnSurfaceVariant</item>
-    </style>
-
-</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
index 01dfd7d..cdd5c25 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v35/themes.xml
@@ -1,31 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2024 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
+    Copyright (C) 2024 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
   -->
 
 <resources>
-    <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v31" >
-        <item name="android:spinnerStyle">@style/Spinner.SettingsLib</item>
-        <item name="android:spinnerItemStyle">@style/SpinnerItem.SettingsLib</item>
-        <item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItem.SettingsLib</item>
-
+    <style name="Theme.SettingsBase_v35" parent="Theme.SettingsBase_v33" >
         <item name="android:colorAccent">@color/settingslib_materialColorPrimary</item>
-        <!-- component module background -->
         <item name="android:colorBackground">@color/settingslib_materialColorSurfaceContainer</item>
         <item name="android:textColorPrimary">@color/settingslib_materialColorOnSurface</item>
         <item name="android:textColorSecondary">@color/settingslib_materialColorOnSurfaceVariant</item>
         <item name="android:textColorTertiary">@color/settingslib_materialColorOutline</item>
     </style>
+
+    <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v35" />
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
index 761bb79..91bd791 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
@@ -40,7 +40,7 @@
 import com.android.settingslib.spa.gallery.page.IllustrationPageProvider
 import com.android.settingslib.spa.gallery.page.LoadingBarPageProvider
 import com.android.settingslib.spa.gallery.page.ProgressBarPageProvider
-import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
+import com.android.settingslib.spa.gallery.scaffold.NonScrollablePagerPageProvider
 import com.android.settingslib.spa.gallery.page.SliderPageProvider
 import com.android.settingslib.spa.gallery.preference.ListPreferencePageProvider
 import com.android.settingslib.spa.gallery.preference.MainSwitchPreferencePageProvider
@@ -48,10 +48,12 @@
 import com.android.settingslib.spa.gallery.preference.PreferencePageProvider
 import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvider
 import com.android.settingslib.spa.gallery.preference.TwoTargetSwitchPreferencePageProvider
+import com.android.settingslib.spa.gallery.scaffold.PagerMainPageProvider
 import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider
 import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider
 import com.android.settingslib.spa.gallery.ui.CategoryPageProvider
 import com.android.settingslib.spa.gallery.ui.CopyablePageProvider
+import com.android.settingslib.spa.gallery.scaffold.ScrollablePagerPageProvider
 import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
 import com.android.settingslib.spa.slice.SpaSliceBroadcastReceiver
 
@@ -84,7 +86,9 @@
                 ArgumentPageProvider,
                 SliderPageProvider,
                 SpinnerPageProvider,
-                SettingsPagerPageProvider,
+                PagerMainPageProvider,
+                NonScrollablePagerPageProvider,
+                ScrollablePagerPageProvider,
                 FooterPageProvider,
                 IllustrationPageProvider,
                 CategoryPageProvider,
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
index 1f028d5..654719d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
@@ -39,9 +39,9 @@
 import com.android.settingslib.spa.gallery.page.IllustrationPageProvider
 import com.android.settingslib.spa.gallery.page.LoadingBarPageProvider
 import com.android.settingslib.spa.gallery.page.ProgressBarPageProvider
-import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
 import com.android.settingslib.spa.gallery.page.SliderPageProvider
 import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider
+import com.android.settingslib.spa.gallery.scaffold.PagerMainPageProvider
 import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider
 import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider
 import com.android.settingslib.spa.gallery.ui.CategoryPageProvider
@@ -63,7 +63,7 @@
             SuwScaffoldPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SliderPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SpinnerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
-            SettingsPagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+            PagerMainPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             FooterPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             IllustrationPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             CategoryPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
deleted file mode 100644
index dc45e6d..0000000
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
+++ /dev/null
@@ -1,73 +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.settingslib.spa.gallery.page
-
-import android.os.Bundle
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.padding
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
-import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPageProvider
-import com.android.settingslib.spa.framework.common.createSettingsPage
-import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.theme.SettingsTheme
-import com.android.settingslib.spa.widget.preference.Preference
-import com.android.settingslib.spa.widget.preference.PreferenceModel
-import com.android.settingslib.spa.widget.scaffold.SettingsPager
-import com.android.settingslib.spa.widget.scaffold.SettingsScaffold
-import com.android.settingslib.spa.widget.ui.PlaceholderTitle
-
-private const val TITLE = "Sample SettingsPager"
-
-object SettingsPagerPageProvider : SettingsPageProvider {
-    override val name = "SettingsPager"
-
-    fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = createSettingsPage())
-            .setUiLayoutFn {
-                Preference(object : PreferenceModel {
-                    override val title = TITLE
-                    override val onClick = navigator(name)
-                })
-            }
-    }
-
-    override fun getTitle(arguments: Bundle?): String {
-        return TITLE
-    }
-
-    @Composable
-    override fun Page(arguments: Bundle?) {
-        SettingsScaffold(title = getTitle(arguments)) { paddingValues ->
-            Box(Modifier.padding(paddingValues)) {
-                SettingsPager(listOf("Personal", "Work")) {
-                    PlaceholderTitle("Page $it")
-                }
-            }
-        }
-    }
-}
-
-@Preview(showBackground = true)
-@Composable
-private fun SettingsPagerPagePreview() {
-    SettingsTheme {
-        SettingsPagerPageProvider.Page(null)
-    }
-}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/NonScrollablePagerPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/NonScrollablePagerPageProvider.kt
new file mode 100644
index 0000000..029773f
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/NonScrollablePagerPageProvider.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.gallery.scaffold
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.SettingsPager
+import com.android.settingslib.spa.widget.scaffold.SettingsScaffold
+import com.android.settingslib.spa.widget.ui.PlaceholderTitle
+
+object NonScrollablePagerPageProvider : SettingsPageProvider {
+    override val name = "NonScrollablePager"
+    private const val TITLE = "Sample Non Scrollable SettingsPager"
+
+    fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = createSettingsPage())
+        .setUiLayoutFn {
+            Preference(object : PreferenceModel {
+                override val title = TITLE
+                override val onClick = navigator(name)
+            })
+        }
+
+    override fun getTitle(arguments: Bundle?) = TITLE
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        SettingsScaffold(title = getTitle(arguments)) { paddingValues ->
+            Box(Modifier.padding(paddingValues)) {
+                SettingsPager(listOf("Personal", "Work")) {
+                    PlaceholderTitle("Page $it")
+                }
+            }
+        }
+    }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun NonScrollablePagerPageProviderPreview() {
+    SettingsTheme {
+        NonScrollablePagerPageProvider.Page(null)
+    }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/PagerMainPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/PagerMainPageProvider.kt
new file mode 100644
index 0000000..66cc38f
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/PagerMainPageProvider.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.gallery.scaffold
+
+import android.os.Bundle
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+object PagerMainPageProvider : SettingsPageProvider {
+    override val name = "PagerMain"
+    private val owner = createSettingsPage()
+    private const val TITLE = "Category: Pager"
+
+    override fun buildEntry(arguments: Bundle?) = listOf(
+        NonScrollablePagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+        ScrollablePagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+    )
+
+    fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner)
+        .setUiLayoutFn {
+            Preference(object : PreferenceModel {
+                override val title = TITLE
+                override val onClick = navigator(name)
+            })
+        }
+
+    override fun getTitle(arguments: Bundle?) = TITLE
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/ScrollablePagerPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/ScrollablePagerPageProvider.kt
new file mode 100644
index 0000000..689a98a
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/ScrollablePagerPageProvider.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.gallery.scaffold
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.SettingsPager
+import com.android.settingslib.spa.widget.scaffold.SettingsScaffold
+
+object ScrollablePagerPageProvider : SettingsPageProvider {
+    override val name = "ScrollablePager"
+    private const val TITLE = "Sample Scrollable SettingsPager"
+
+    fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = createSettingsPage())
+        .setUiLayoutFn {
+            Preference(object : PreferenceModel {
+                override val title = TITLE
+                override val onClick = navigator(name)
+            })
+        }
+
+    override fun getTitle(arguments: Bundle?) = TITLE
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        SettingsScaffold(title = getTitle(arguments)) { paddingValues ->
+            Box(Modifier.padding(paddingValues)) {
+                SettingsPager(listOf("Personal", "Work")) {
+                    LazyColumn {
+                        items(30) {
+                            Preference(object : PreferenceModel {
+                                override val title = it.toString()
+                            })
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun ScrollablePagerPageProviderPreview() {
+    SettingsTheme {
+        ScrollablePagerPageProvider.Page(null)
+    }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt
index 6fc8de3..a0ab2ce 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt
@@ -22,6 +22,10 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.SignalCellularAlt
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -37,6 +41,8 @@
 import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
 import com.android.settingslib.spa.widget.scaffold.SuwScaffold
 import com.android.settingslib.spa.widget.ui.SettingsBody
+import com.android.settingslib.spa.widget.ui.Spinner
+import com.android.settingslib.spa.widget.ui.SpinnerOption
 
 private const val TITLE = "Sample SuwScaffold"
 
@@ -67,13 +73,12 @@
         actionButton = BottomAppBarButton("Next") {},
         dismissButton = BottomAppBarButton("Cancel") {},
     ) {
-        Column(Modifier.padding(SettingsDimension.itemPadding)) {
-            SettingsBody("To add another SIM, download a new eSIM.")
-        }
-        Illustration(object : IllustrationModel {
-            override val resId = R.drawable.accessibility_captioning_banner
-            override val resourceType = ResourceType.IMAGE
-        })
+        var selectedId by rememberSaveable { mutableIntStateOf(1) }
+        Spinner(
+            options = (1..3).map { SpinnerOption(id = it, text = "Option $it") },
+            selectedId = selectedId,
+            setId = { selectedId = it },
+        )
         Column(Modifier.padding(SettingsDimension.itemPadding)) {
             SettingsBody("To add another SIM, download a new eSIM.")
         }
diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml
index 0ee9d59..85ad160 100644
--- a/packages/SettingsLib/Spa/gradle/libs.versions.toml
+++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml
@@ -15,7 +15,7 @@
 #
 
 [versions]
-agp = "8.3.1"
+agp = "8.3.2"
 compose-compiler = "1.5.11"
 dexmaker-mockito = "2.28.3"
 jvm = "17"
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip
deleted file mode 100644
index 5c96347..0000000
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip
+++ /dev/null
Binary files differ
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.7-bin.zip b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.7-bin.zip
new file mode 100644
index 0000000..7a9ac5a
--- /dev/null
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.7-bin.zip
Binary files differ
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index 50ff9df..182095e 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -16,6 +16,6 @@
 
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=gradle-8.6-bin.zip
+distributionUrl=gradle-8.7-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png
index 3e016f7..75c8e6e 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_mainSwitchPreference.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_progressBar.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_progressBar.png
index 105d1a1..9d477c5 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_progressBar.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_progressBar.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png
index d156f95..06f0059 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_landscape_spinner.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png
index b8bb25f..b72c8db 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_mainSwitchPreference.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_progressBar.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_progressBar.png
index fc845a6..f2e6d2e 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_progressBar.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_progressBar.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png
index d156f95..06f0059 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_spinner.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png
index 9044208..e43f27d 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/phone/light_portrait_twoTargetSwitchPreference.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png
index 36cbadc..15c86dc 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_mainSwitchPreference.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_progressBar.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_progressBar.png
index 19c028e..d31f2c4 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_progressBar.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_progressBar.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png
index a279481..5be3a21 100644
--- a/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png
+++ b/packages/SettingsLib/Spa/screenshot/robotests/assets/tablet/dark_portrait_spinner.png
Binary files differ
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
index 2f2ac24..6344501 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -65,7 +65,7 @@
     api("androidx.lifecycle:lifecycle-runtime-compose")
     api("androidx.navigation:navigation-compose:2.8.0-alpha05")
     api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha")
-    api("com.google.android.material:material:1.7.0-alpha03")
+    api("com.google.android.material:material:1.11.0")
     debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion")
     implementation("com.airbnb.android:lottie-compose:5.2.0")
 
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt
index 46975f5..fb9e98e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt
@@ -47,7 +47,7 @@
         super.finish()
     }
 
-    abstract val dialogWindowType: Int?
+    abstract fun getDialogWindowType(): Int?
 
     @Composable
     abstract fun Content()
@@ -67,7 +67,7 @@
         }
 
         override fun onCreate(savedInstanceState: Bundle?) {
-            dialogWindowType?.let { window?.setType(it) }
+            getDialogWindowType()?.let { window?.setType(it) }
             super.onCreate(savedInstanceState)
         }
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt
new file mode 100644
index 0000000..e883a4a
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.framework.compose
+
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+
+/** Sets the content description of this node. */
+fun Modifier.contentDescription(contentDescription: String?) =
+    if (contentDescription != null) this.semantics {
+        this.contentDescription = contentDescription
+    } else this
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
index f5cbe8f..d08d97e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
@@ -48,10 +48,9 @@
 import androidx.compose.ui.graphics.takeOrElse
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.semantics.contentDescription
-import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.debug.UiModePreviews
+import com.android.settingslib.spa.framework.compose.contentDescription
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraLarge
 import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraSmall
@@ -191,8 +190,7 @@
 private fun Button(button: CardButton, color: Color) {
     TextButton(
         onClick = button.onClick,
-        modifier =
-            Modifier.semantics { button.contentDescription?.let { this.contentDescription = it } }
+        modifier = Modifier.contentDescription(button.contentDescription),
     ) {
         Text(text = button.text, color = color)
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt
index bdc6a68..bc5904c 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt
@@ -40,12 +40,14 @@
     singleLine: Boolean = true,
     enabled: Boolean = true,
     shape: Shape = OutlinedTextFieldDefaults.shape,
+    placeholder: @Composable (() -> Unit)? = null,
+    modifier: Modifier = Modifier
+        .fillMaxWidth()
+        .padding(SettingsDimension.textFieldPadding),
     onTextChange: (String) -> Unit
 ) {
     OutlinedTextField(
-        modifier = Modifier
-            .fillMaxWidth()
-            .padding(SettingsDimension.textFieldPadding),
+        modifier = modifier,
         value = value,
         onValueChange = onTextChange,
         label = {
@@ -59,6 +61,7 @@
                 Text(text = errorMessage)
             }
         },
+        placeholder = placeholder,
         shape = shape
     )
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
index 56d75d8..23a8e78 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
@@ -28,6 +28,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
@@ -41,7 +42,8 @@
     title: String,
     subTitle: @Composable () -> Unit,
     modifier: Modifier = Modifier,
-    icon: (@Composable () -> Unit)? = null,
+    titleContentDescription: String? = null,
+    icon: @Composable (() -> Unit)? = null,
     enabled: () -> Boolean = { true },
     paddingStart: Dp = SettingsDimension.itemPaddingStart,
     paddingEnd: Dp = SettingsDimension.itemPaddingEnd,
@@ -51,6 +53,7 @@
     Row(
         modifier = modifier
             .fillMaxWidth()
+            .semantics(mergeDescendants = true) {}
             .padding(end = paddingEnd),
         verticalAlignment = Alignment.CenterVertically,
     ) {
@@ -58,6 +61,7 @@
         BaseIcon(icon, alphaModifier, paddingStart)
         Titles(
             title = title,
+            titleContentDescription = titleContentDescription,
             subTitle = subTitle,
             modifier = alphaModifier
                 .weight(1f)
@@ -87,9 +91,14 @@
 
 // Extracts a scope to avoid frequent recompose outside scope.
 @Composable
-private fun Titles(title: String, subTitle: @Composable () -> Unit, modifier: Modifier) {
+private fun Titles(
+    title: String,
+    titleContentDescription: String?,
+    subTitle: @Composable () -> Unit,
+    modifier: Modifier,
+) {
     Column(modifier) {
-        SettingsTitle(title)
+        SettingsTitle(title, titleContentDescription)
         subTitle()
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
index 194ed81..e9b3ba2 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
@@ -32,6 +32,8 @@
     title: String,
     summary: () -> String,
     modifier: Modifier = Modifier,
+    titleContentDescription: String? = null,
+    summaryContentDescription: () -> String? = { null },
     singleLineSummary: Boolean = false,
     icon: @Composable (() -> Unit)? = null,
     enabled: () -> Boolean = { true },
@@ -42,9 +44,11 @@
 ) {
     BaseLayout(
         title = title,
+        titleContentDescription = titleContentDescription,
         subTitle = {
             SettingsBody(
                 body = summary(),
+                contentDescription = summaryContentDescription(),
                 maxLines = if (singleLineSummary) 1 else Int.MAX_VALUE,
             )
         },
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt
index 1a04bb8..73ee5d1 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt
@@ -22,8 +22,10 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.selection.selectable
 import androidx.compose.foundation.selection.selectableGroup
+import androidx.compose.foundation.verticalScroll
 import androidx.compose.material3.RadioButton
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.IntState
@@ -86,7 +88,7 @@
             title = model.title,
             onDismissRequest = { dialogOpened = false },
         ) {
-            Column(modifier = Modifier.selectableGroup()) {
+            Column(modifier = Modifier.selectableGroup().verticalScroll(rememberScrollState())) {
                 for (option in model.options) {
                     Radio(option, model.selectedId.intValue, model.enabled()) {
                         dialogOpened = false
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
index 3acf075..4ad4c14 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
@@ -64,12 +64,24 @@
     val title: String
 
     /**
+     * The content description of [title].
+     */
+    val titleContentDescription: String?
+        get() = null
+
+    /**
      * The summary of this [Preference].
      */
     val summary: () -> String
         get() = { "" }
 
     /**
+     * The content description of [summary].
+     */
+    val summaryContentDescription: () -> String?
+        get() = { null }
+
+    /**
      * The icon of this [Preference].
      *
      * Default is `null` which means no icon.
@@ -112,7 +124,9 @@
     EntryHighlight {
         BasePreference(
             title = model.title,
+            titleContentDescription = model.titleContentDescription,
             summary = model.summary,
+            summaryContentDescription = model.summaryContentDescription,
             singleLineSummary = singleLineSummary,
             modifier = modifier,
             icon = model.icon,
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
index 8b546b4..ef1a137 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
@@ -23,7 +23,6 @@
 @Composable
 fun TwoTargetSwitchPreference(
     model: SwitchPreferenceModel,
-    icon: @Composable (() -> Unit)? = null,
     primaryEnabled: () -> Boolean = { true },
     primaryOnClick: (() -> Unit)?,
 ) {
@@ -33,11 +32,12 @@
             summary = model.summary,
             primaryEnabled = primaryEnabled,
             primaryOnClick = primaryOnClick,
-            icon = icon,
+            icon = model.icon,
         ) {
             SettingsSwitch(
                 checked = model.checked(),
                 changeable = model.changeable,
+                contentDescription = model.title,
                 onCheckedChange = model.onCheckedChange,
             )
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
index f372a45..163766a 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
@@ -19,7 +19,6 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxWithConstraints
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.padding
@@ -33,6 +32,8 @@
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.movableContentOf
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import com.android.settingslib.spa.framework.theme.SettingsDimension
@@ -50,7 +51,7 @@
     title: String,
     actionButton: BottomAppBarButton? = null,
     dismissButton: BottomAppBarButton? = null,
-    content: @Composable ColumnScope.() -> Unit,
+    content: @Composable () -> Unit,
 ) {
     ActivityTitle(title)
     Scaffold { innerPadding ->
@@ -59,6 +60,7 @@
                 .padding(innerPadding)
                 .padding(top = SettingsDimension.itemPaddingAround)
         ) {
+            val movableContent = remember(content) { movableContentOf { content() } }
             // Use single column layout in portrait, two columns in landscape.
             val useSingleColumn = maxWidth < maxHeight
             if (useSingleColumn) {
@@ -69,7 +71,7 @@
                             .verticalScroll(rememberScrollState())
                     ) {
                         Header(imageVector, title)
-                        content()
+                        movableContent()
                     }
                     BottomBar(actionButton, dismissButton)
                 }
@@ -82,8 +84,9 @@
                         Column(
                             Modifier
                                 .weight(1f)
-                                .verticalScroll(rememberScrollState())) {
-                            content()
+                                .verticalScroll(rememberScrollState())
+                        ) {
+                            movableContent()
                         }
                     }
                     BottomBar(actionButton, dismissButton)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
index a0da241..2fac576 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
@@ -20,12 +20,15 @@
 import androidx.compose.material3.Switch
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import com.android.settingslib.spa.framework.compose.contentDescription
 import com.android.settingslib.spa.framework.util.wrapOnSwitchWithLog
 
 @Composable
 internal fun SettingsSwitch(
     checked: Boolean?,
     changeable: () -> Boolean,
+    contentDescription: String? = null,
     onCheckedChange: ((newChecked: Boolean) -> Unit)? = null,
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
 ) {
@@ -33,6 +36,7 @@
         Switch(
             checked = checked,
             onCheckedChange = wrapOnSwitchWithLog(onCheckedChange),
+            modifier = Modifier.contentDescription(contentDescription),
             enabled = changeable(),
             interactionSource = interactionSource,
         )
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
index a59b95a..d423d9f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt
@@ -30,16 +30,23 @@
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
+import com.android.settingslib.spa.framework.compose.contentDescription
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsOpacity.alphaForEnabled
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.theme.toMediumWeight
 
 @Composable
-fun SettingsTitle(title: String, useMediumWeight: Boolean = false) {
+fun SettingsTitle(
+    title: String,
+    contentDescription: String? = null,
+    useMediumWeight: Boolean = false,
+) {
     Text(
         text = title,
-        modifier = Modifier.padding(vertical = SettingsDimension.paddingTiny),
+        modifier = Modifier
+            .padding(vertical = SettingsDimension.paddingTiny)
+            .contentDescription(contentDescription),
         color = MaterialTheme.colorScheme.onSurface,
         style = MaterialTheme.typography.titleMedium.withWeight(useMediumWeight),
     )
@@ -81,11 +88,13 @@
 @Composable
 fun SettingsBody(
     body: String,
+    contentDescription: String? = null,
     maxLines: Int = Int.MAX_VALUE,
 ) {
     if (body.isNotEmpty()) {
         Text(
             text = body,
+            modifier = Modifier.contentDescription(contentDescription),
             color = MaterialTheme.colorScheme.onSurfaceVariant,
             style = MaterialTheme.typography.bodyMedium,
             overflow = TextOverflow.Ellipsis,
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
index 8c363db..5ef3329 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
@@ -29,6 +29,7 @@
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
 import androidx.compose.ui.test.performClick
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
@@ -93,11 +94,10 @@
             }
         }
 
-        val summaryNode = composeTestRule.onNodeWithText(LONG_SUMMARY)
         try {
             // There is no assertHeightIsAtMost, so use the assertHeightIsAtLeast and catch the
             // expected exception.
-            summaryNode.assertHeightIsAtLeast(lineHeightDp.times(2))
+            composeTestRule.onRoot().assertHeightIsAtLeast(lineHeightDp.times(5))
         } catch (e: AssertionError) {
             assertThat(e).hasMessageThat().contains("height")
             return
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
index 9a8e7dd..f259541f 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
@@ -20,8 +20,8 @@
     <string name="no_applications" msgid="5800789569715871963">"ليس هناك أي تطبيقات."</string>
     <string name="menu_show_system" msgid="906304605807554788">"إظهار عمليات النظام"</string>
     <string name="menu_hide_system" msgid="374571689914923020">"إخفاء عمليات النظام"</string>
-    <string name="app_permission_summary_allowed" msgid="6115213465364138103">"مسموح به"</string>
-    <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غير مسموح به"</string>
+    <string name="app_permission_summary_allowed" msgid="6115213465364138103">"تطبيق مسموح به"</string>
+    <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"تطبيق غير مسموح به"</string>
     <string name="version_text" msgid="4001669804596458577">"الإصدار <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
     <string name="cloned_app_info_label" msgid="1765651167024478391">"نسخة طبق الأصل من \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\""</string>
 </resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
index a2a4289c..b1d5721 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
@@ -17,7 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="no_applications" msgid="5800789569715871963">"Tidak ada aplikasi."</string>
+    <string name="no_applications" msgid="5800789569715871963">"Tidak ada aplikasi"</string>
     <string name="menu_show_system" msgid="906304605807554788">"Tampilkan sistem"</string>
     <string name="menu_hide_system" msgid="374571689914923020">"Sembunyikan sistem"</string>
     <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Diizinkan"</string>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
index 7f3a523..87d0762 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
@@ -18,8 +18,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="no_applications" msgid="5800789569715871963">"कुनै पनि एप छैन।"</string>
-    <string name="menu_show_system" msgid="906304605807554788">"सिस्टम देखाइयोस्"</string>
-    <string name="menu_hide_system" msgid="374571689914923020">"सिस्टम लुकाइयोस्"</string>
+    <string name="menu_show_system" msgid="906304605807554788">"सिस्टम देखाउनुहोस्"</string>
+    <string name="menu_hide_system" msgid="374571689914923020">"सिस्टम लुकाउनुहोस्"</string>
     <string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमति दिइएका एप"</string>
     <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमति नदिइएका एप"</string>
     <string name="version_text" msgid="4001669804596458577">"संस्करण <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
index 8f67354b7..7ea4b18 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
@@ -27,7 +27,7 @@
 import kotlinx.coroutines.flow.flowOn
 
 /** Content change flow for the given [uri]. */
-internal fun Context.contentChangeFlow(
+fun Context.contentChangeFlow(
     uri: Uri,
     sendInitial: Boolean = true,
 ): Flow<Unit> = callbackFlow {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
index a395266..e1e1ee5 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
@@ -151,7 +151,7 @@
     }
 
     private fun isArchivingEnabled(featureFlags: FeatureFlags) =
-            featureFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false)
+            featureFlags.archiving()
 
     override fun showSystemPredicate(
         userIdFlow: Flow<Int>,
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
index 5c2d770..1f7122e 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
@@ -33,11 +33,13 @@
         model = object : SwitchPreferenceModel {
             override val title = label
             override val summary = [email protected]
+            override val icon = @Composable {
+                AppIcon(record.app, SettingsDimension.appIconItemSize)
+            }
             override val checked = checked
             override val changeable = changeable
             override val onCheckedChange = onCheckedChange
         },
-        icon = { AppIcon(record.app, SettingsDimension.appIconItemSize) },
         primaryOnClick = onClick,
     )
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
index 87cd2b8..c9934ad 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
@@ -52,6 +52,8 @@
         checked = model.checked,
     )
 
+    override val icon = model.icon
+
     override val checked = when (restrictedMode) {
         null -> ({ null })
         is NoRestricted -> model.checked
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt
index e100773..1bed733 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt
@@ -29,14 +29,12 @@
 @Composable
 fun RestrictedTwoTargetSwitchPreference(
     model: SwitchPreferenceModel,
-    icon: @Composable (() -> Unit)? = null,
     restrictions: Restrictions,
     primaryEnabled: () -> Boolean = { true },
     primaryOnClick: (() -> Unit)?,
 ) {
     RestrictedTwoTargetSwitchPreference(
         model = model,
-        icon = icon,
         primaryEnabled = primaryEnabled,
         primaryOnClick = primaryOnClick,
         restrictions = restrictions,
@@ -48,21 +46,19 @@
 @Composable
 internal fun RestrictedTwoTargetSwitchPreference(
     model: SwitchPreferenceModel,
-    icon: @Composable (() -> Unit)? = null,
     primaryEnabled: () -> Boolean = { true },
     primaryOnClick: (() -> Unit)?,
     restrictions: Restrictions,
     restrictionsProviderFactory: RestrictionsProviderFactory,
 ) {
     if (restrictions.isEmpty()) {
-        TwoTargetSwitchPreference(model, icon, primaryEnabled, primaryOnClick)
+        TwoTargetSwitchPreference(model, primaryEnabled, primaryOnClick)
         return
     }
     val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value
     RestrictedSwitchWrapper(model, restrictedMode) { restrictedModel ->
         TwoTargetSwitchPreference(
             model = restrictedModel,
-            icon = icon,
             primaryEnabled = restrictedMode.restrictEnabled(primaryEnabled),
             primaryOnClick = restrictedMode.restrictOnClick(primaryOnClick),
         )
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
index a4089c0..7f4bebc 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
@@ -52,16 +52,12 @@
 import java.util.Comparator;
 import java.util.HashMap;
 
-/**
- * Description of a single dashboard tile that the user can select.
- */
+/** Description of a single dashboard tile that the user can select. */
 public abstract class Tile implements Parcelable {
 
     private static final String TAG = "Tile";
 
-    /**
-     * Optional list of user handles which the intent should be launched on.
-     */
+    /** Optional list of user handles which the intent should be launched on. */
     public ArrayList<UserHandle> userHandle = new ArrayList<>();
 
     public HashMap<UserHandle, PendingIntent> pendingIntentMap = new HashMap<>();
@@ -76,6 +72,7 @@
     private CharSequence mSummaryOverride;
     private Bundle mMetaData;
     private String mCategory;
+    private String mGroupKey;
 
     public Tile(ComponentInfo info, String category, Bundle metaData) {
         mComponentInfo = info;
@@ -83,6 +80,9 @@
         mComponentName = mComponentInfo.name;
         mCategory = category;
         mMetaData = metaData;
+        if (mMetaData != null) {
+            mGroupKey = metaData.getString(META_DATA_PREFERENCE_GROUP_KEY);
+        }
         mIntent = new Intent().setClassName(mComponentPackage, mComponentName);
         if (isNewTask()) {
             mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -102,6 +102,7 @@
         if (isNewTask()) {
             mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         }
+        mGroupKey = in.readString();
     }
 
     @Override
@@ -121,16 +122,13 @@
         }
         dest.writeString(mCategory);
         dest.writeBundle(mMetaData);
+        dest.writeString(mGroupKey);
     }
 
-    /**
-     * Unique ID of the tile
-     */
+    /** Unique ID of the tile */
     public abstract int getId();
 
-    /**
-     * Human-readable description of the tile
-     */
+    /** Human-readable description of the tile */
     public abstract String getDescription();
 
     protected abstract ComponentInfo getComponentInfo(Context context);
@@ -147,16 +145,12 @@
         return mComponentName;
     }
 
-    /**
-     * Intent to launch when the preference is selected.
-     */
+    /** Intent to launch when the preference is selected. */
     public Intent getIntent() {
         return mIntent;
     }
 
-    /**
-     * Category in which the tile should be placed.
-     */
+    /** Category in which the tile should be placed. */
     public String getCategory() {
         return mCategory;
     }
@@ -165,9 +159,7 @@
         mCategory = newCategoryKey;
     }
 
-    /**
-     * Priority of this tile, used for display ordering.
-     */
+    /** Priority of this tile, used for display ordering. */
     public int getOrder() {
         if (hasOrder()) {
             return mMetaData.getInt(META_DATA_KEY_ORDER);
@@ -176,32 +168,24 @@
         }
     }
 
-    /**
-     * Check whether tile has order.
-     */
+    /** Check whether tile has order. */
     public boolean hasOrder() {
         return mMetaData != null
                 && mMetaData.containsKey(META_DATA_KEY_ORDER)
                 && mMetaData.get(META_DATA_KEY_ORDER) instanceof Integer;
     }
 
-    /**
-     * Check whether tile has a switch.
-     */
+    /** Check whether tile has a switch. */
     public boolean hasSwitch() {
         return mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_SWITCH_URI);
     }
 
-    /**
-     * Check whether tile has a pending intent.
-     */
+    /** Check whether tile has a pending intent. */
     public boolean hasPendingIntent() {
         return !pendingIntentMap.isEmpty();
     }
 
-    /**
-     * Title of the tile that is shown to the user.
-     */
+    /** Title of the tile that is shown to the user. */
     public CharSequence getTitle(Context context) {
         CharSequence title = null;
         ensureMetadataNotStale(context);
@@ -238,9 +222,7 @@
         mSummaryOverride = summaryOverride;
     }
 
-    /**
-     * Optional summary describing what this tile controls.
-     */
+    /** Optional summary describing what this tile controls. */
     public CharSequence getSummary(Context context) {
         if (mSummaryOverride != null) {
             return mSummaryOverride;
@@ -275,16 +257,12 @@
         mMetaData = metaData;
     }
 
-    /**
-     * The metaData from the activity that defines this tile.
-     */
+    /** The metaData from the activity that defines this tile. */
     public Bundle getMetaData() {
         return mMetaData;
     }
 
-    /**
-     * Optional key to use for this tile.
-     */
+    /** Optional key to use for this tile. */
     public String getKey(Context context) {
         ensureMetadataNotStale(context);
         if (!hasKey()) {
@@ -297,9 +275,7 @@
         }
     }
 
-    /**
-     * Check whether title has key.
-     */
+    /** Check whether title has key. */
     public boolean hasKey() {
         return mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_KEYHINT);
     }
@@ -325,8 +301,9 @@
         if (iconResId != 0 && iconResId != android.R.color.transparent) {
             final Icon icon = Icon.createWithResource(componentInfo.packageName, iconResId);
             if (isIconTintable(context)) {
-                final TypedArray a = context.obtainStyledAttributes(new int[]{
-                        android.R.attr.colorControlNormal});
+                final TypedArray a =
+                        context.obtainStyledAttributes(
+                                new int[] {android.R.attr.colorControlNormal});
                 final int tintColor = a.getColor(0, 0);
                 a.recycle();
                 icon.setTint(tintColor);
@@ -349,26 +326,22 @@
         return false;
     }
 
-    /**
-     * Whether the {@link Activity} should be launched in a separate task.
-     */
+    /** Whether the {@link Activity} should be launched in a separate task. */
     public boolean isNewTask() {
-        if (mMetaData != null
-                && mMetaData.containsKey(META_DATA_NEW_TASK)) {
+        if (mMetaData != null && mMetaData.containsKey(META_DATA_NEW_TASK)) {
             return mMetaData.getBoolean(META_DATA_NEW_TASK);
         }
         return false;
     }
 
-    /**
-     * Ensures metadata is not stale for this tile.
-     */
+    /** Ensures metadata is not stale for this tile. */
     private void ensureMetadataNotStale(Context context) {
         final PackageManager pm = context.getApplicationContext().getPackageManager();
 
         try {
-            final long lastUpdateTime = pm.getPackageInfo(mComponentPackage,
-                    PackageManager.GET_META_DATA).lastUpdateTime;
+            final long lastUpdateTime =
+                    pm.getPackageInfo(mComponentPackage, PackageManager.GET_META_DATA)
+                            .lastUpdateTime;
             if (lastUpdateTime == mLastUpdateTime) {
                 // All good. Do nothing
                 return;
@@ -382,72 +355,60 @@
         }
     }
 
-    public static final Creator<Tile> CREATOR = new Creator<Tile>() {
-        public Tile createFromParcel(Parcel source) {
-            final boolean isProviderTile = source.readBoolean();
-            // reset the Parcel pointer before delegating to the real constructor.
-            source.setDataPosition(0);
-            return isProviderTile ? new ProviderTile(source) : new ActivityTile(source);
-        }
+    public static final Creator<Tile> CREATOR =
+            new Creator<Tile>() {
+                public Tile createFromParcel(Parcel source) {
+                    final boolean isProviderTile = source.readBoolean();
+                    // reset the Parcel pointer before delegating to the real constructor.
+                    source.setDataPosition(0);
+                    return isProviderTile ? new ProviderTile(source) : new ActivityTile(source);
+                }
 
-        public Tile[] newArray(int size) {
-            return new Tile[size];
-        }
-    };
+                public Tile[] newArray(int size) {
+                    return new Tile[size];
+                }
+            };
 
-    /**
-     * Check whether tile only has primary profile.
-     */
+    /** Check whether tile only has primary profile. */
     public boolean isPrimaryProfileOnly() {
         return isPrimaryProfileOnly(mMetaData);
     }
 
     static boolean isPrimaryProfileOnly(Bundle metaData) {
-        String profile = metaData != null
-                ? metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
+        String profile = metaData != null ? metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
         profile = (profile != null ? profile : PROFILE_ALL);
         return TextUtils.equals(profile, PROFILE_PRIMARY);
     }
 
-    /**
-     * Returns whether the tile belongs to another group / category.
-     */
+    /** Returns whether the tile belongs to another group / category. */
     public boolean hasGroupKey() {
-        return mMetaData != null
-                && !TextUtils.isEmpty(mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY));
+        return !TextUtils.isEmpty(mGroupKey);
     }
 
-    /**
-     * Returns the group / category key this tile belongs to.
-     */
+    /** Set the group / PreferenceCategory key this tile belongs to. */
+    public void setGroupKey(String groupKey) {
+        mGroupKey = groupKey;
+    }
+
+    /** Returns the group / category key this tile belongs to. */
     public String getGroupKey() {
-        return (mMetaData == null) ? null : mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY);
+        return mGroupKey;
     }
 
-    /**
-     * Returns if this is searchable.
-     */
+    /** Returns if this is searchable. */
     public boolean isSearchable() {
         return mMetaData == null || mMetaData.getBoolean(META_DATA_PREFERENCE_SEARCHABLE, true);
     }
 
-    /**
-     * The type of the tile.
-     */
+    /** The type of the tile. */
     public enum Type {
-        /**
-         * A preference that can be tapped on to open a new page.
-         */
+        /** A preference that can be tapped on to open a new page. */
         ACTION,
 
-        /**
-         * A preference that can be tapped on to open an external app.
-         */
+        /** A preference that can be tapped on to open an external app. */
         EXTERNAL_ACTION,
 
-        /**
-         * A preference that shows an on / off switch that can be toggled by the user.
-         */
+        /** A preference that shows an on / off switch that can be toggled by the user. */
         SWITCH,
 
         /**
@@ -460,7 +421,7 @@
          * A preference category with a title that can be used to group multiple preferences
          * together.
          */
-        GROUP;
+        GROUP
     }
 
     /**
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index d0929e1..b949cd5 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -77,9 +77,7 @@
      */
     public static final String IA_SETTINGS_ACTION = "com.android.settings.action.IA_SETTINGS";
 
-    /**
-     * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities.
-     */
+    /** Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities. */
     private static final String SETTINGS_ACTION = "com.android.settings.action.SETTINGS";
 
     private static final String OPERATOR_SETTINGS =
@@ -101,9 +99,7 @@
      */
     static final String EXTRA_CATEGORY_KEY = "com.android.settings.category";
 
-    /**
-     * The key used to get the package name of the icon resource for the preference.
-     */
+    /** The key used to get the package name of the icon resource for the preference. */
     static final String EXTRA_PREFERENCE_ICON_PACKAGE = "com.android.settings.icon_package";
 
     /**
@@ -145,18 +141,17 @@
             "com.android.settings.bg.argb";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify the content provider providing the icon that should be displayed for
-     * the preference.
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
+     * content provider providing the icon that should be displayed for the preference.
      *
-     * Icon provided by the content provider overrides any static icon.
+     * <p>Icon provided by the content provider overrides any static icon.
      */
     public static final String META_DATA_PREFERENCE_ICON_URI = "com.android.settings.icon_uri";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify whether the icon is tintable. This should be a boolean value {@code true} or
-     * {@code false}, set using {@code android:value}
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify whether
+     * the icon is tintable. This should be a boolean value {@code true} or {@code false}, set using
+     * {@code android:value}
      */
     public static final String META_DATA_PREFERENCE_ICON_TINTABLE =
             "com.android.settings.icon_tintable";
@@ -171,41 +166,36 @@
     public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify the content provider providing the title text that should be displayed for the
-     * preference.
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
+     * content provider providing the title text that should be displayed for the preference.
      *
-     * Title provided by the content provider overrides any static title.
+     * <p>Title provided by the content provider overrides any static title.
      */
-    public static final String META_DATA_PREFERENCE_TITLE_URI =
-            "com.android.settings.title_uri";
+    public static final String META_DATA_PREFERENCE_TITLE_URI = "com.android.settings.title_uri";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify the summary text that should be displayed for the preference.
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
+     * summary text that should be displayed for the preference.
      */
     public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify the content provider providing the summary text that should be displayed for the
-     * preference.
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
+     * content provider providing the summary text that should be displayed for the preference.
      *
-     * Summary provided by the content provider overrides any static summary.
+     * <p>Summary provided by the content provider overrides any static summary.
      */
     public static final String META_DATA_PREFERENCE_SUMMARY_URI =
             "com.android.settings.summary_uri";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify the content provider providing the switch that should be displayed for the
-     * preference.
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
+     * content provider providing the switch that should be displayed for the preference.
      *
-     * This works with {@link #META_DATA_PREFERENCE_KEYHINT} which should also be set in the
+     * <p>This works with {@link #META_DATA_PREFERENCE_KEYHINT} which should also be set in the
      * AndroidManifest.xml
      */
-    public static final String META_DATA_PREFERENCE_SWITCH_URI =
-            "com.android.settings.switch_uri";
+    public static final String META_DATA_PREFERENCE_SWITCH_URI = "com.android.settings.switch_uri";
 
     /**
      * Name of the meta-data item that can be set from the content provider providing the intent
@@ -215,8 +205,8 @@
             "com.android.settings.pending_intent";
 
     /**
-     * Value for {@link #META_DATA_KEY_PROFILE}. When the device has a managed profile,
-     * the app will always be run in the primary profile.
+     * Value for {@link #META_DATA_KEY_PROFILE}. When the device has a managed profile, the app will
+     * always be run in the primary profile.
      *
      * @see #META_DATA_KEY_PROFILE
      */
@@ -231,11 +221,11 @@
     public static final String PROFILE_ALL = "all_profiles";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify the profile in which the app should be run when the device has a managed profile.
-     * The default value is {@link #PROFILE_ALL} which means the user will be presented with a
-     * dialog to choose the profile. If set to {@link #PROFILE_PRIMARY} the app will always be
-     * run in the primary profile.
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
+     * profile in which the app should be run when the device has a managed profile. The default
+     * value is {@link #PROFILE_ALL} which means the user will be presented with a dialog to choose
+     * the profile. If set to {@link #PROFILE_PRIMARY} the app will always be run in the primary
+     * profile.
      *
      * @see #PROFILE_PRIMARY
      * @see #PROFILE_ALL
@@ -243,20 +233,16 @@
     public static final String META_DATA_KEY_PROFILE = "com.android.settings.profile";
 
     /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml
-     * to specify whether the {@link android.app.Activity} should be launched in a separate task.
-     * This should be a boolean value {@code true} or {@code false}, set using {@code android:value}
+     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify whether
+     * the {@link android.app.Activity} should be launched in a separate task. This should be a
+     * boolean value {@code true} or {@code false}, set using {@code android:value}
      */
     public static final String META_DATA_NEW_TASK = "com.android.settings.new_task";
 
-    /**
-     * If the entry should be shown in settings search results. Defaults to true.
-     */
+    /** If the entry should be shown in settings search results. Defaults to true. */
     public static final String META_DATA_PREFERENCE_SEARCHABLE = "com.android.settings.searchable";
 
-    /**
-     * Build a list of DashboardCategory.
-     */
+    /** Build a list of DashboardCategory. */
     public static List<DashboardCategory> getCategories(Context context,
             Map<Pair<String, String>, Tile> cache) {
         final long startTime = System.currentTimeMillis();
@@ -341,8 +327,8 @@
             UserHandle user, Map<Pair<String, String>, Tile> addedCache,
             String defaultCategory, List<Tile> outTiles, Intent intent) {
         final PackageManager pm = context.getPackageManager();
-        final List<ResolveInfo> results = pm.queryIntentContentProvidersAsUser(intent,
-                0 /* flags */, user.getIdentifier());
+        final List<ResolveInfo> results =
+                pm.queryIntentContentProvidersAsUser(intent, 0 /* flags */, user.getIdentifier());
         for (ResolveInfo resolved : results) {
             if (!resolved.system) {
                 // Do not allow any app to add to settings, only system ones.
@@ -403,6 +389,8 @@
             tile.setMetaData(metaData);
         }
 
+        tile.setGroupKey(metaData.getString(META_DATA_PREFERENCE_GROUP_KEY));
+
         if (!tile.userHandle.contains(user)) {
             tile.userHandle.add(user);
         }
@@ -448,15 +436,15 @@
     /**
      * Returns the complete uri from the meta data key of the tile.
      *
-     * A complete uri should contain at least one path segment and be one of the following types:
-     *      content://authority/method
-     *      content://authority/method/key
+     * <p>A complete uri should contain at least one path segment and be one of the following types:
+     * <br>content://authority/method
+     * <br>content://authority/method/key
      *
-     * If the uri from the tile is not complete, build a uri by the default method and the
+     * <p>If the uri from the tile is not complete, build a uri by the default method and the
      * preference key.
      *
-     * @param tile          Tile which contains meta data
-     * @param metaDataKey   Key mapping to the uri in meta data
+     * @param tile Tile which contains meta data
+     * @param metaDataKey Key mapping to the uri in meta data
      * @param defaultMethod Method to be attached to the uri by default if it has no path segment
      * @return Uri associated with the key
      */
@@ -501,9 +489,9 @@
     /**
      * Gets the icon package name and resource id from content provider.
      *
-     * @param context     context
+     * @param context context
      * @param packageName package name of the target activity
-     * @param uri         URI for the content provider
+     * @param uri URI for the content provider
      * @param providerMap Maps URI authorities to providers
      * @return package name and resource id of the icon specified
      */
@@ -532,10 +520,10 @@
     /**
      * Gets text associated with the input key from the content provider.
      *
-     * @param context     context
-     * @param uri         URI for the content provider
+     * @param context context
+     * @param uri URI for the content provider
      * @param providerMap Maps URI authorities to providers
-     * @param key         Key mapping to the text in bundle returned by the content provider
+     * @param key Key mapping to the text in bundle returned by the content provider
      * @return Text associated with the key, if returned by the content provider
      */
     public static String getTextFromUri(Context context, Uri uri,
@@ -547,10 +535,10 @@
     /**
      * Gets boolean associated with the input key from the content provider.
      *
-     * @param context     context
-     * @param uri         URI for the content provider
+     * @param context context
+     * @param uri URI for the content provider
      * @param providerMap Maps URI authorities to providers
-     * @param key         Key mapping to the text in bundle returned by the content provider
+     * @param key Key mapping to the text in bundle returned by the content provider
      * @return Boolean associated with the key, if returned by the content provider
      */
     public static boolean getBooleanFromUri(Context context, Uri uri,
@@ -562,11 +550,11 @@
     /**
      * Puts boolean associated with the input key to the content provider.
      *
-     * @param context     context
-     * @param uri         URI for the content provider
+     * @param context context
+     * @param uri URI for the content provider
      * @param providerMap Maps URI authorities to providers
-     * @param key         Key mapping to the text in bundle returned by the content provider
-     * @param value       Boolean associated with the key
+     * @param key Key mapping to the text in bundle returned by the content provider
+     * @param value Boolean associated with the key
      * @return Bundle associated with the action, if returned by the content provider
      */
     public static Bundle putBooleanToUriAndGetResult(Context context, Uri uri,
diff --git a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
index 712f6f0..ea3dbd9 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
+++ b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java
@@ -20,6 +20,7 @@
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
 import android.text.style.AbsoluteSizeSpan;
 import android.util.AttributeSet;
 import android.view.View;
@@ -174,6 +175,7 @@
             bottomSummary.setVisibility(View.GONE);
         } else {
             bottomSummary.setVisibility(View.VISIBLE);
+            bottomSummary.setMovementMethod(LinkMovementMethod.getInstance());
             bottomSummary.setText(mBottomSummary);
         }
 
diff --git a/packages/SettingsLib/aconfig/OWNERS b/packages/SettingsLib/aconfig/OWNERS
new file mode 100644
index 0000000..ba02d20
--- /dev/null
+++ b/packages/SettingsLib/aconfig/OWNERS
@@ -0,0 +1,2 @@
+# go/android-fwk-media-solutions for info on areas of ownership.
+per-file settingslib_media_flag_declarations.aconfig = file:platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index e09ab00..89f54d9 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -36,14 +36,14 @@
   name: "enable_le_audio_sharing"
   namespace: "pixel_cross_device_control"
   description: "Gates whether to enable LE audio sharing"
-  bug: "305620450"
+  bug: "323125723"
 }
 
 flag {
   name: "enable_le_audio_qr_code_private_broadcast_sharing"
   namespace: "pixel_cross_device_control"
   description: "Gates whether to enable LE audio private broadcast sharing via QR code"
-  bug: "308368124"
+  bug: "323125723"
 }
 
 flag {
@@ -52,3 +52,13 @@
   description: "Hide exclusively managed Bluetooth devices in BT settings menu."
   bug: "324475542"
 }
+
+flag {
+    name: "enable_set_preferred_transport_for_le_audio_device"
+    namespace: "bluetooth"
+    description: "Enable setting preferred transport for Le Audio device"
+    bug: "330581926"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig b/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig
index 4d70aec..7aae1a6 100644
--- a/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig
@@ -21,3 +21,13 @@
     description: "Enable Output Switcher when no media is playing."
     bug: "284227163"
 }
+
+flag {
+    name: "remove_unnecessary_route_scanning"
+    namespace: "media_solutions"
+    description: "Avoid active scan requests on UI components that only display route status information."
+    bug: "332515672"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml b/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml
index 89d6ac3..3ed1724 100644
--- a/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml
+++ b/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml
@@ -53,7 +53,7 @@
     <EditText
         android:id="@+id/user_name"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/user_name_height_in_user_info_dialog"
+        android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:minWidth="200dp"
         android:layout_marginStart="6dp"
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index eb3d4af..f9800b3 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Gekoppel (geen foon nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Gekoppel (geen media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Gekoppel (geen foon of media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktief, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterykrag"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktief, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batterykrag, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batterykrag"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterykrag"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batterykrag, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batterykrag"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Links <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Regs <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktief"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gestoor"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktief, net links"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktief, net regs"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktief, links en regs"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktief (net media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Steun oudiodeling"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktief (net media), net linkerkant"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktief (net media), net regterkant"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktief (net media), linker- en regterkant"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media-oudio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Foonoproepe"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Lêeroordrag"</string>
@@ -335,8 +341,8 @@
     <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Wanneer hierdie modus geaktiveer is, kan hierdie toestel se MAC-adres verander elke keer wanneer dit aan \'n netwerk koppel waarvoor MAC-verewekansiging geaktiveer is."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"Beperk"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Onbeperk"</string>
-    <string name="select_logd_size_title" msgid="1604578195914595173">"Loggerbuffer se groottes"</string>
-    <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Kies loggergroottes per logbuffer"</string>
+    <string name="select_logd_size_title" msgid="1604578195914595173">"Logskepperbuffer se groottes"</string>
+    <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Kies logskeppergroottes per logbuffer"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Maak logskrywer se aanhoudende berging skoon?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Wanneer ons nie meer monitering met die aanhoudende logskrywer uitvoer nie, word ons vereis om die logskrywerdata wat op jou toestel is, uit te vee."</string>
     <string name="select_logpersist_title" msgid="447071974007104196">"Berg logskrywerdata aanhoudend op toestel"</string>
@@ -411,7 +417,7 @@
     <string name="show_non_rect_clip" msgid="7499758654867881817">"Ontfout nie-reghoekige knipbedrywighede"</string>
     <string name="track_frame_time" msgid="522674651937771106">"Profiel-HWUI-lewering"</string>
     <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Aktiveer GPU-ontfoutlae"</string>
-    <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Laat laai van GPU-ontfoutlae vir ontfoutprogramme toe"</string>
+    <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Laat laai van GPU-ontfoutlae vir ontfoutapps toe"</string>
     <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Aktiveer woordryke verkoperloginskrywing"</string>
     <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Sluit bykomende toestelspesifieke verkoperloglêers by foutverslae in, wat privaat inligting kan bevat, meer batterykrag kan gebruik, en/of meer berging kan gebruik."</string>
     <string name="window_animation_scale_title" msgid="5236381298376812508">"Vensteranimasieskaal"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> oor tot vol"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses word geoptimeer"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laai tans"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Volgelaai teen <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Volgelaai teen <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Volgelaai teen <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Volgelaai teen <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string>
@@ -509,12 +519,14 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Gelaai"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Volgelaai"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Laai wag tans"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Laai tans"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Laai vinnig"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Beheer deur administrateur"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Beheer deur Beperkte Instellings"</string>
     <string name="disabled" msgid="8017887509554714950">"Gedeaktiveer"</string>
     <string name="external_source_trusted" msgid="1146522036773132905">"Toegelaat"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"Nie toegelaat nie"</string>
-    <string name="install_other_apps" msgid="3232595082023199454">"Installeer onbekende programme"</string>
+    <string name="install_other_apps" msgid="3232595082023199454">"Installeer onbekende apps"</string>
     <string name="home" msgid="973834627243661438">"Instellingstuisblad"</string>
   <string-array name="battery_labels">
     <item msgid="7878690469765357158">"0%"</item>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Foon, een staaf."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Foon, twee stawe."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Foon, drie stawe."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Foon vier strepies."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Foonsein is vol."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Geen data nie."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data, een staaf."</string>
@@ -709,7 +722,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Verstek"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Skakel skerm aan"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Laat toe dat die skerm aangeskakel word"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Laat ’n program toe om die skerm aan te skakel. As jy toestemming gee, kan die program die skerm enige tyd sonder jou uitdruklike bedoeling aanskakel."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Laat ’n app toe om die skerm aan te skakel. As jy toestemming gee, kan die app die skerm enige tyd sonder jou uitdruklike bedoeling aanskakel."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hou op om <xliff:g id="APP_NAME">%1$s</xliff:g> uit te saai?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"As jy <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitsaai of die uitvoer verander, sal jou huidige uitsending stop"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Saai <xliff:g id="SWITCHAPP">%1$s</xliff:g> uit"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index bda0277..729ac28 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ተገናኝቷል (ምንም ስልክ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ተገናኝቷል (ምንም ማህደረ መረጃ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ተገናኝቷል (ምንም ስልክ ወይም ማህደረ መረጃ የለም)፣ ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ንቁ፣ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ገቢር፣ ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ባትሪ፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ባትሪ፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ግራ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ቀኝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ንቁ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ተቀምጧል"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ገቢር፣ ግራ ብቻ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ገቢር፣ ቀኝ ብቻ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ገቢር፣ ግራ እና ቀኝ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ገቢር (ሚዲያ ብቻ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ድምፅ ማጋራትን ይደግፋል"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ገቢር (ሚዲያ ብቻ)፣ ግራ ብቻ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ገቢር (ሚዲያ ብቻ) ቀኝ ብቻ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ገቢር (ሚዲያ ብቻ)፣ ግራ እና ቀኝ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"የማህደረ መረጃ ኦዲዮ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"የስልክ ጥሪዎች"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ፋይል ማስተላለፍ"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት እንዲተባ ተደርጓል"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል በመሙላት ላይ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - እስከ <xliff:g id="TIME">%3$s</xliff:g> ድረስ ይሞላል"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስከ <xliff:g id="TIME">%2$s</xliff:g> ሙሉ ለሙሉ ይሞላል"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"እስከ <xliff:g id="TIME">%1$s</xliff:g> ድረስ ሙሉ ለሙሉ ይሞላል"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"እስከ <xliff:g id="TIME">%1$s</xliff:g> ድረስ ይሞላል"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ባትሪ ሞልቷል"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ሙሉ ለሙሉ ኃይል ተሞልቷል"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ኃይል መሙላት በይቆይ ላይ"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ኃይል በመሙላት ላይ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ፈጣን መሙያ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"በአስተዳዳሪ ቁጥጥር የተደረገበት"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"በተገደበ ቅንብር ቁጥጥር የሚደረግበት"</string>
     <string name="disabled" msgid="8017887509554714950">"ቦዝኗል"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"የስልክ አንድ አሞሌ"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"የስልክ ሁለት አሞሌ"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"የስልክ ሦስት አሞሌ"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ስልክ አራት መስመሮች።"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"የስልክ አመልካች ሙሉ ነው።"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ምንም ውሂብ የለም።"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"የውሂብ አንድ አሞሌ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index ba93f65..9f13551 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -94,44 +94,50 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"متّصل (بدون هاتف)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"متّصل (بدون وسائط)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"متّصل (بدون هاتف أو وسائط)، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"نشط، ومستوى البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"مفعّلة، مستوى البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، المعدّل: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"‏مستوى شحن البطارية: ‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"مستوى البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، المعدّل: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"‏مستوى شحن البطارية في سماعة الرأس اليسرى: ‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"‏مستوى شحن البطارية في سماعة الرأس اليمنى: ‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"نشط"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"السمّاعة الطبية اليسرى فقط مفعَّلة"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"السمّاعة الطبية اليمنى فقط مفعَّلة"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"السمّاعتان اليسرى واليمنى مفعَّلتان"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"البلوتوث مفعَّل (للوسائط فقط)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"تتوفّر ميزة \"مشاركة الصوت\""</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"السماعة اليسرى فقط مشغَّلة (للوسائط فقط)"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"السماعة اليمنى فقط مشغَّلة (للوسائط فقط)"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"السماعتان اليسرى واليمنى مشغَّلتان (للوسائط فقط)"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"الإعدادات الصوتية للوسائط"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"المكالمات الهاتفية"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"نقل الملف"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"جهاز الإرسال"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"جهاز إدخال بيانات"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"الوصول إلى الإنترنت"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"السماح بالوصول إلى جهات الاتصال وسجلّ المكالمات"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"سيتم استخدام المعلومات لإرسال إشعارات المكالمات وغيرها"</string>
@@ -202,8 +208,8 @@
     <string name="launch_defaults_some" msgid="3631650616557252926">"تم ضبط بعض الإعدادات التلقائية"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"لم يتم ضبط إعدادات تلقائية"</string>
     <string name="tts_settings" msgid="8130616705989351312">"إعدادات تحويل النص إلى كلام"</string>
-    <string name="tts_settings_title" msgid="7602210956640483039">"إخراج النص إلى كلام"</string>
-    <string name="tts_default_rate_title" msgid="3964187817364304022">"معدل سرعة الكلام"</string>
+    <string name="tts_settings_title" msgid="7602210956640483039">"الصوت عند تحويل النص إلى كلام"</string>
+    <string name="tts_default_rate_title" msgid="3964187817364304022">"سرعة الكلام"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعة قول الكلام"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"درجة الصوت"</string>
     <string name="tts_default_pitch_summary" msgid="9132719475281551884">"للتأثير في نبرة الكلام المُرَكَّب"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقّى <xliff:g id="TIME">%2$s</xliff:g> حتى اكتمال شحن البطارية."</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم تحسين الشحن"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"‫<xliff:g id="LEVEL">%1$s</xliff:g>: جارٍ الشحن"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"‏‫‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - سيكتمل الشحن بحلول <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"‏‫‎<xliff:g id="LEVEL">%1$s</xliff:g> - سيكتمل الشحن بحلول <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"سيكتمل الشحن بحلول <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"سيكتمل الشحن بحلول <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string>
@@ -509,11 +519,13 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"مشحونة"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"البطارية مشحونة بالكامل."</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"الشحن معلَّق"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"جارٍ الشحن"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"جارٍ الشحن السريع"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"إعدادات يتحكم فيها المشرف"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"يتحكّم فيه إعداد محظور"</string>
     <string name="disabled" msgid="8017887509554714950">"غير مفعّل"</string>
-    <string name="external_source_trusted" msgid="1146522036773132905">"مسموح به"</string>
-    <string name="external_source_untrusted" msgid="5037891688911672227">"غير مسموح به"</string>
+    <string name="external_source_trusted" msgid="1146522036773132905">"تطبيق مسموح به"</string>
+    <string name="external_source_untrusted" msgid="5037891688911672227">"تطبيق غير مسموح به"</string>
     <string name="install_other_apps" msgid="3232595082023199454">"تثبيت التطبيقات غير المعروفة"</string>
     <string name="home" msgid="973834627243661438">"الشاشة الرئيسية للإعدادات"</string>
   <string-array name="battery_labels">
@@ -555,7 +567,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>
@@ -668,7 +680,7 @@
     <string name="user_image_photo_selector" msgid="433658323306627093">"اختيار صورة"</string>
     <string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف بيانات هذا الجهاز."</string>
     <string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف حساب هذا المستخدم."</string>
-    <string name="failed_attempts_now_wiping_profile" msgid="7626589520888963129">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف الملف الشخصي للعمل وبياناته."</string>
+    <string name="failed_attempts_now_wiping_profile" msgid="7626589520888963129">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف ملف العمل وبياناته."</string>
     <string name="failed_attempts_now_wiping_dialog_dismiss" msgid="2749889771223578925">"إغلاق"</string>
     <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"الإعداد التلقائي للجهاز"</string>
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غير مفعّل"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"إشارة الهاتف تتكون من شريط واحد."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"إشارة الهاتف تتكون من شريطين."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"إشارة الهاتف تتكون من ثلاثة أشرطة."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"أربعة أشرطة في إشارة بيانات الهاتف"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"إشارة الهاتف كاملة."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"لا تتوفر بيانات."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"إشارة البيانات تتكون من شريط واحد."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ef53faf..62c1201 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"সংযোগ কৰা হ’ল (ফ\'ন নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"সংযোগ কৰা হ’ল (মিডিয়া নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"সংযোগ কৰা হ’ল (কোনো ফ\'ন বা মিডিয়া নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"সক্ৰিয়, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"সক্ৰিয়, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰী, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰী, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"বাওঁফালে <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"সোঁফালে <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"সক্ৰিয়"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ছেভ কৰা হৈছে"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"কেৱল বাঁওফালৰটো সক্ৰিয় হৈছে"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"কেৱল সোঁফালৰটো সক্ৰিয় হৈছে"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাওঁ আৰু সোঁ দুয়োফালৰ সক্ৰিয় হৈছে"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল বাওঁ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), কেৱল সোঁ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া), বাওঁ আৰু সোঁ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"মিডিয়াৰ অডিঅ’"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ফ\'ন কলসমূহ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তৰণ"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ চাৰ্জ হৈ আছে"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণ হ’ব"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণৰূপে চাৰ্জ হ’ব"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণৰূপে চাৰ্জ হ’ব"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>ৰ ভিতৰত সম্পূৰ্ণ হ’ব"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"চাৰ্জ হ’ল"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"সম্পূৰ্ণ চাৰ্জ হৈছে"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"চাৰ্জিং স্থগিত ৰখা হৈছে"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"চাৰ্জ হৈ আছে"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"দ্ৰুত চাৰ্জিং"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"এডমিনৰ দ্বাৰা নিয়ন্ত্ৰিত"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"প্ৰতিবন্ধিত ছেটিঙৰ দ্বাৰা নিয়ন্ত্ৰিত"</string>
     <string name="disabled" msgid="8017887509554714950">"নিষ্ক্ৰিয়"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ফ\'ন ছিগনেলৰ এডাল দণ্ড।"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ফ\'ন ছিগনেলৰ দুডাল দণ্ড।"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ফ\'নৰ ছিগনেলৰ তিনিডাল দণ্ড আছে।"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ফ’নত চাৰিডাল দণ্ড।"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ফ\'নৰ ছিগনেল পূৰা আছে৷"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"কোনো ডেটা নাই।"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ডেটা ছিগনেলৰ এডাল দণ্ড।"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 48c68f4..b1bbf34 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Qoşuludur (telefon yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Qoşuludur (media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Qoşuludur (telefon və ya media yoxdur), batareya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiv, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batareya, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batareya, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Sol <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Sağ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Yadda saxlandı"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, yalnız sol"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, yalnız sağ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, sol və sağ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (yalnız media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio paylaşma dəstəklənir"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (yalnız media), yalnız sol"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (yalnız media), yalnız sağ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (yalnız media), sol və sağ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefon zəngləri"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl transferi"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj edilənədək <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj optimallaşdırılıb"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj edilir"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> radələrinə qədər tam dolacaq"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> radələrinə qədər tam dolacaq"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> radələrinə qədər tam dolacaq"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> radələrinə qədər tam dolacaq"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Şarj edilib"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Tam şarj edilib"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Şarj gözlədilir"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Şarj"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Sürətli şarj"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Admin tərəfindən nəzarət olunur"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Məhdudlaşdırılmış Ayar ilə nəzarət edilir"</string>
     <string name="disabled" msgid="8017887509554714950">"Deaktiv"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Şəbəkə bir xətdir."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Şəbəkə iki xətdir."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Şəbəkə üç xətdir."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefonda dörd zolaq."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Tam şəbəkə."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Məlumat yoxdur."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data bir xətdir."</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 04c6d94..4af26f2 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (bez telefona), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (bez medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (bez telefona ili medija), nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktivan, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivno, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Leva <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Desna <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo s leve strane"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, s desne strane"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, s leve i desne strane"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivan (samo za medije)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava deljenje zvuka"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivan (samo za medije), samo levo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivan (samo za medije), samo desno"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivan (samo za medije), levo i desno"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk medija"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski pozivi"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizovano"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Punjenje"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Potpuno napunjeno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Napunjeno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Napunjeno do kraja"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Punjenje je na čekanju"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Punjenje"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Brzo punjenje"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontroliše administrator"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolišu ograničena podešavanja"</string>
     <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal telefona ima jednu crtu."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal telefona od dve crte."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal telefona od tri crte."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon ima četiri crte."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal telefona je pun."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal za podatke ima jednu crtu."</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f8c88e6..9998c9e 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў і аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Уключана, зарад <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Актыўна, Л: акумулятар: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, П: акумулятар: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: акумулятар: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, П: акумулятар: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Левы: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Правы: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Уключана"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Захавана"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Уключана, толькі для левага вуха"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Уключана, толькі для правага вуха"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Уключана, для левага і правага вуха"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Выкарыстоўваецца (толькі для мультымедыя)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Падтрымліваецца абагульванне аўдыя"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Выкарыстоўваецца (толькі для мультымедыя), толькі левы навушнік"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Выкарыстоўваецца (толькі для мультымедыя), толькі правы навушнік"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Выкарыстоўваецца (толькі для мультымедыя), левы і правы навушнікі"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Аўдыя медыяфайлаў"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Тэлефонныя выклікі"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Перадача файлаў"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – да поўнай зарадкі засталося: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарадка аптымізавана"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – зараджаецца"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Прылада зарадзіцца поўнасцю да <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Зараджаны"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Акумулятар поўнасцю зараджаны"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Зарадка прыпынена"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Ідзе зарадка"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Ідзе хуткая зарадка"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Кантралюецца адміністратарам"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Пад кіраваннем Абмежаванага наладжвання"</string>
     <string name="disabled" msgid="8017887509554714950">"Адключанае"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Адна планка на тэлефоне."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"2 планкі тэлефона."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"3 планкі тэлефона."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Магутнасць сігналу: чатыры палоскі."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Поўны сігнал тэлефона."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Няма дадзеных."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Адна планка дадзеных."</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 9388e66..31d24c1 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -188,7 +188,7 @@
     <item msgid="409235464399258501">"Изключено"</item>
     <item msgid="4195153527464162486">"Рег. буфер – 64 КБ"</item>
     <item msgid="7464037639415220106">"Рег. буфер – 256 КБ"</item>
-    <item msgid="8539423820514360724">"Рег. буфер – 1 МБ"</item>
+    <item msgid="8539423820514360724">"Рег. буфер – 1 млн."</item>
     <item msgid="1984761927103140651">"Рег. буфер – 4 МБ"</item>
     <item msgid="2983219471251787208">"Регистрационен буфер – 8 МБ"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 0457f10..03065c6 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -94,47 +94,53 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Свързано (без телефон), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Свързано (без мултимедия), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Свързано (без телефон или мултимедия), батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Активно. Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активно. Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерия. Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерия"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерия. Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерия"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Вляво: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Вдясно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Запазено"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно – само лявото"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно – само дясното"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно – лявото и дясното"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само за мултимедия)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддържа споделяне на звука"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само за мултимедия), само лявата"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (само за мултимедия), само дясната"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (само за мултимедия), лявата и дясната"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Мултимедийно аудио"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонни обаждания"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Прехвърляне на файл"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Входно устройство"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Достъп до интернет"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Разреш. на достъпа до контактите и историята на обажд."</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Информацията ще се ползва за съобщения чрез обаждания и др."</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Информацията ще се ползва за обявяване на обажданията и др."</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Споделяне на връзката с интернет"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстови съобщения"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Достъп до SIM картата"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оставащо време до пълно зареждане: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зареждането е оптимизирано"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарежда се"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – ще се зареди напълно до <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – ще се зареди напълно до <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Ще се зареди напълно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Ще се зареди напълно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Заредена"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Напълно заредено"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Зареждането е поставено на пауза"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Зарежда се"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Зарежда се бързо"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролира се от администратор"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Управлява се чрез ограничена настройка"</string>
     <string name="disabled" msgid="8017887509554714950">"Деактивирано"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефонът е с една чертичка."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефонът е с две чертички."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефонът е с три чертички."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Телефонът е с четири чертички."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигналът за телефона е пълен."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Няма данни."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Данните са с една чертичка."</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index e9367ff..b69a542 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া), ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"চালু আছে, চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"চালু, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ব্যাটারি, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ব্যাটারি, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"বাঁদিকের হেডসেটে <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বাকি আছে"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ডানদিকের হেডসেটে <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বাকি আছে"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"চালু আছে"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"সেভ করা আছে"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"শুধুমাত্র বাঁদিকের হিয়ারিং এড অ্যাক্টিভ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"শুধুমাত্র ডানদিকের হিয়ারিং এড অ্যাক্টিভ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাঁ ও ডানদিকের হিয়ারিং এড, অ্যাক্টিভ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"চালু আছে (শুধুমাত্র মিডিয়া)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"অডিও শেয়ারিংয়ে কাজ করে"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র বাঁদিক"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"চালু আছে (শুধুমাত্র মিডিয়া), শুধুমাত্র ডানদিক"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক ও ডানদিক"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"মিডিয়া অডিও"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ফোন কল"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তর"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং অপ্টিমাইজ করা হয়েছে"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জ করা হচ্ছে"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>-এর মধ্যে পুরো চার্জ হয়ে যাবে"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"চার্জ হয়েছে"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"সম্পূর্ণ চার্জ আছে"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"চার্জিং হোল্ডে আছে"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"চার্জ হচ্ছে"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ফাস্ট চার্জিং"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"প্রশাসকের দ্বারা নিয়ন্ত্রিত"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"এটি বিধিনিষেধ সেটিং থেকে নিয়ন্ত্রণ করা হয়"</string>
     <string name="disabled" msgid="8017887509554714950">"অক্ষম হয়েছে"</string>
@@ -537,7 +549,7 @@
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"সিস্টেমের ভাষাগুলি ব্যবহার করুন"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> জন্য সেটিংস খুলতে ব্যর্থ হয়েছে"</string>
     <string name="ime_security_warning" msgid="6547562217880551450">"এই ইনপুট পদ্ধতিটি হয়ত পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ আপনার টাইপ করা সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> অ্যাপ থেকে এসেছে। এই ইনপুট পদ্ধতিটি ব্যবহার করবেন?"</string>
-    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"দ্রষ্টব্য: পুনরায় চালু করার পরে, আপনি আপনার ফোন আনলক না করা পর্যন্ত এই অ্যাপটিকে চালু করতে পারবেন না"</string>
+    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"দ্রষ্টব্য: রিবুট করার পরে, আপনি আপনার ফোন আনলক না করা পর্যন্ত এই অ্যাপটিকে চালু করতে পারবেন না"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS রেজিস্ট্রেশনের স্থিতি"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"রেজিস্টার করা"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"রেজিস্টার করা নয়"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"এক দন্ড ফোনের সংকেত রয়েছে৷"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"দুই দন্ড ফোনের সংকেত রয়েছে৷"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"তিন দন্ড ফোনের সংকেত রয়েছে৷"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ফোনে চারটি বার দেখা যাচ্ছে।"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ফোনের সংকেত পূর্ণ রয়েছে৷"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"কোনো ডেটা নেই৷"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"এক দন্ড ডেটার সংকেত৷"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 7fb5225..2cc6dc5 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (bez telefona ili medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktivan, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivno, L: baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Lijeva <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Desna <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevi"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desni"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevi i desni"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo za medijski sadržaj)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava dijeljenje zvuka"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo za medijski sadržaj), samo lijevo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo za medijski sadržaj), samo desno"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo za medijski sadržaj), lijevo i desno"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk medija"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski pozivi"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenošenje fajla"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je optimizirano"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Napunjeno do <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Potpuno napunjeno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Napunjeno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Potpuno napunjeno"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Punjenje je na čekanju"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Punjenje"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Brzo punjenje"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Pod kontrolom administratora"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolira ograničena postavka"</string>
     <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonski signal na jednoj crtici."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonski signal na dvije crtice."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonski signal na tri crtice."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Četiri crtice na telefonu."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonski signal pun."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Prijenos podataka na jednoj crtici."</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 18da1be..5a4a923 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connectat (sense accés al telèfon ni al contingut multimèdia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Actiu, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Actiu, E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateria"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateria"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Esquerre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Dret: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actiu"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Desat"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actiu, només l\'esquerre"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actiu, només el dret"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actiu, esquerre i dret"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actiu (només contingut multimèdia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admet compartició d\'àudio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actiu (només contingut multimèdia), només esquerre"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actiu (només contingut multimèdia), només dret"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actiu (només contingut multimèdia), esquerre i dret"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Àudio multimèdia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Trucades telefòniques"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferència de fitxers"</string>
@@ -487,7 +493,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> segons l\'ús que en facis"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"És possible que la bateria s\'esgoti a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: càrrega optimitzada"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g>: s\'està carregant"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Càrrega completa a les <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Càrrega completa a les <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Càrrega completa a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Càrrega completa a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Càrrega ràpida"</string>
@@ -509,12 +519,14 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Totalment carregada"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Càrrega en espera"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Càrrega"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Càrrega ràpida"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlat per l\'administrador"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlat per l\'opció de configuració restringida"</string>
     <string name="disabled" msgid="8017887509554714950">"Desactivat"</string>
     <string name="external_source_trusted" msgid="1146522036773132905">"Amb permís"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"Sense permís"</string>
-    <string name="install_other_apps" msgid="3232595082023199454">"Instal·lar aplicacions desconegudes"</string>
+    <string name="install_other_apps" msgid="3232595082023199454">"Instal·la aplicacions desconegudes"</string>
     <string name="home" msgid="973834627243661438">"Pàgina d\'inici de configuració"</string>
   <string-array name="battery_labels">
     <item msgid="7878690469765357158">"0%"</item>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Senyal de telèfon: una barra"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Senyal de telèfon: dues barres."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Senyal de telèfon: tres barres."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telèfon amb quatre barres."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Senyal de telèfon: complet."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Senyal de dades: no n\'hi ha"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Senyal de dades: una barra."</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index f4bfe505c..9a3ba63 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefonu), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez médií), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Připojeno k zařízení <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefonu a médií), úroveň baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktivní, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivní, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterie, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterie"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterie, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterie"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Vlevo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Vpravo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivní"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Uloženo"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivní, pouze levé"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivní, pouze pravé"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivní, levé a pravé"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivní (pouze média)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje sdílení zvuku"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivní (pouze média), pouze levé"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivní (pouze média), pouze pravé"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivní (pouze média), levé a pravé"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk médií"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonní hovory"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Přenos souborů"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimalizované nabíjení"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Nabíjení"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Úplné nabití: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Úplné nabití: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Úplné nabití: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Úplné nabití: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Nabito"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Plně nabito"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Nabíjení pozastaveno"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Nabíjení"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Rychlé nabíjení"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Spravováno administrátorem"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Spravováno omezeným nastavením"</string>
     <string name="disabled" msgid="8017887509554714950">"Deaktivováno"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Jedna čárka signálu telefonní sítě."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dvě čárky signálu telefonní sítě."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tři čárky signálu telefonní sítě."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon čtyři čárky."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Plný signál telefonní sítě."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Žádné datové připojení."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Jedna čárka signálu datové sítě."</string>
@@ -709,7 +722,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Výchozí"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Zapínání obrazovky"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Povolit zapínání obrazovky"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Povolte aplikaci zapínat obrazovku. Pokud aplikace bude mít toto oprávnění, může kdykoli zapnout obrazovku bez požadavku uživatele."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Aplikaci můžete povolit zapínat obrazovku. Pokud bude mít toto oprávnění, může kdykoli zapnout obrazovku bez požadavku uživatele."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zastavit vysílání v aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Pokud budete vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g> nebo změníte výstup, aktuální vysílání se zastaví"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d51f8b9..c7f1c6e 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Forbundet med <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Forbundet med <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Forbundet med <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivt, V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri. Højre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Højre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gemt"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, kun venstre"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, kun højre"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og højre"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiveret (kun for medier)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Understøtter lyddeling"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiveret (kun for medier), kun venstre"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiveret (kun for medier), kun højre"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiveret (kun for medier), venstre og højre"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medielyd"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonopkald"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverførsel"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladning er optimeret"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – oplades"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Opladet senest kl. <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fuldt opladet senest kl. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fuldt opladet senest kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Opladet senest kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Opladet"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fuldt opladet"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Opladningen er blevet sat på pause"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Opladning"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Lynopladning"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolleret af administratoren"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Styres af en begrænset indstilling"</string>
     <string name="disabled" msgid="8017887509554714950">"Deaktiveret"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon en bjælke."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon to bjælker."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon tre bjælker."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefonen har fire bjælker."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignal fuldt."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ingen data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data en bjælke."</string>
@@ -709,7 +722,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standard"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Aktivér skærmen"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Tillad aktivering af skærmen"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Tillad, at en app aktiverer skærmen. Hvis du giver denne tilladelse, kan appen til enhver tid aktiverer skærmen, uden at du eksplicit har bedt om det."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Tillad, at en app aktiverer skærmen. Hvis du giver denne tilladelse, kan appen til enhver tid aktivere skærmen, uden at du eksplicit har bedt om det."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop udsendelsen <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Hvis du udsender <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller skifter output, stopper din aktuelle udsendelse"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Udsend <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 08ca14a..cc962b4 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Telefon-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (weder Telefon- noch Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiv, Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiv, Akkustand L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Akkustand L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Links – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Rechts – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gespeichert"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, nur links"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, nur rechts"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, links und rechts"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (nur Medien)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Unterstützt Audiofreigabe"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (nur Medien), nur links"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (nur Medien), nur rechts"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (nur Medien), links und rechts"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medien-Audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonanrufe"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dateiübertragung"</string>
@@ -472,7 +478,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Die Farbkorrektur kann nützlich sein, wenn du:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Farben noch genauer sehen möchtest&lt;/li&gt; &lt;li&gt;&amp;nbsp;bestimmte Farben entfernen möchtest, um dich besser zu konzentrieren&lt;/li&gt; &lt;/ol&gt;"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Die Farbkorrektur kann nützlich sein, wenn du:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Farben noch genauer sehen möchtest&lt;/li&gt; &lt;li&gt;&amp;nbsp;Bestimmte Farben entfernen möchtest, um dich besser zu konzentrieren&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladevorgang zum Schutz des Akkus angehalten"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laden wird optimiert"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Wird geladen"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Vollständig geladen in <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Vollständig geladen in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Vollständig geladen in <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Vollständig geladen in <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Aufgeladen"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Vollständig geladen"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ladevorgang angehalten"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Wird geladen"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Schnelles Laden"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Durch den Administrator verwaltet"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Gesteuert durch eingeschränkte Einstellung"</string>
     <string name="disabled" msgid="8017887509554714950">"Deaktiviert"</string>
@@ -593,7 +605,7 @@
     <string name="tv_media_transfer_default" msgid="5403053145185843843">"Standardeinstellung: Fernseher"</string>
     <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-Ausgang"</string>
     <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interne Lautsprecher"</string>
-    <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus &amp; und wieder ein."</string>
+    <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus und wieder ein."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
     <string name="help_label" msgid="3528360748637781274">"Hilfe und Feedback"</string>
     <string name="storage_category" msgid="2287342585424631813">"Speicher"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonsignal - ein Balken"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonsignal - zwei Balken"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonsignal - drei Balken"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Smartphone – vier Balken."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Volle Telefonsignalstärke"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Keine Daten"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datensignal - ein Balken"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index c38034a..2ea96a7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Σε σύνδεση (χωρίς τηλέφωνο), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Σε σύνδεση (χωρίς μέσα), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Σε σύνδεση (χωρίς τηλέφωνο ή μέσα), μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Ενεργό, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Ενεργό, Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> μπαταρία, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> μπαταρία, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Αριστερό <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Δεξί <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ενεργό"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Αποθηκεύτηκε"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ενεργό, μόνο το αριστερό"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ενεργό, μόνο το δεξί"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ενεργό, αριστερό και δεξί"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ενεργό (μόνο για μέσα)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Υποστηρίζει κοινή χρήση ήχου"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ενεργό (μόνο για μέσα), μόνο αριστερό"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ενεργό (μόνο για μέσα), μόνο δεξί"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ενεργό (μόνο για μέσα), αριστερό και δεξί"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Ήχος πολυμέσων"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Τηλεφωνικές κλήσεις"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Μεταφορά αρχείου"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένουν <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση βελτιστοποιήθηκε"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Φόρτιση"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Πλήρης φόρτιση στις <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Πλήρης φόρτιση στις <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Πλήρης φόρτιση στις <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Πλήρης φόρτιση στις <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Φορτισμένη"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Πλήρως φορτισμένο"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Η φόρτιση τέθηκε σε αναμονή"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Φόρτιση"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Γρήγορη φόρτιση"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ελέγχονται από το διαχειριστή"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Ελέγχεται από τη Ρύθμιση με περιορισμό"</string>
     <string name="disabled" msgid="8017887509554714950">"Απενεργοποιημένο"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Μία γραμμή τηλεφώνου."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Δύο γραμμές τηλεφώνου."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Τρεις γραμμές μπαταρίας."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Τέσσερις γραμμές στο τηλέφωνο."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Πλήρες σήμα τηλεφώνου."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Δεν υπάρχουν δεδομένα."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Μία γραμμή δεδομένων."</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index c787c63..d4f14f4 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Active, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Active, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fully charged by <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Full by <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Charging on hold"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Charging"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Fast charging"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string>
     <string name="disabled" msgid="8017887509554714950">"Disabled"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Phone four bars."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index e5d2e29..6b49bc9 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -94,24 +94,29 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Active, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Active, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
+    <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+    <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
-    <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"Active (media only), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
-    <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"Active (media only), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"Connected (supports audio sharing), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"Connected (supports audio sharing), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"Connected (supports audio sharing), left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"Connected (supports audio sharing), right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Connected (supports audio sharing). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Connected (supports audio sharing). Left: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Connected (supports audio sharing). Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Connected (supports audio sharing)"</string>
     <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
     <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
     <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
@@ -487,6 +492,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimized"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fully charged by <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Full by <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -498,6 +507,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully Charged"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Charging on hold"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Charging"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Fast charging"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by Restricted Setting"</string>
     <string name="disabled" msgid="8017887509554714950">"Disabled"</string>
@@ -684,6 +695,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Phone four bars."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index c787c63..d4f14f4 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Active, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Active, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fully charged by <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Full by <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Charging on hold"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Charging"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Fast charging"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string>
     <string name="disabled" msgid="8017887509554714950">"Disabled"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Phone four bars."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index c787c63..d4f14f4 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Active, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Active, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> battery, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Left <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Right <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Active (media only)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supports audio sharing"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Active (media only), left only"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Active (media only), right only"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Active (media only), left and right"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Phone calls"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging optimised"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – charging"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Full by <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fully charged by <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fully charged by <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Full by <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Charging on hold"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Charging"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Fast charging"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string>
     <string name="disabled" msgid="8017887509554714950">"Disabled"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Phone four bars."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 5e14648..c255633 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -94,24 +94,29 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎Connected (no phone), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎Connected (no media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎Connected (no phone or media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎Active, ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎Active, L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
+    <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‎‎Active. ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎Active. L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎Battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‏‎‎Left ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‎Right ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎Left: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎Right: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‎Active‎‏‎‎‏‎"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎Saved‎‏‎‎‏‎"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎Active, left only‎‏‎‎‏‎"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎Active, right only‎‏‎‎‏‎"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎Active, left and right‎‏‎‎‏‎"</string>
-    <string name="bluetooth_active_media_only_battery_level" msgid="1164678961213251365">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎Active (media only), ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
-    <string name="bluetooth_active_media_only_battery_level_untethered" msgid="1345174295097854560">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎Active (media only), L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_lea_support" msgid="8580950145907305436">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎Connected (supports audio sharing), ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_untethered_lea_support" msgid="8534816721698743015">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎Connected (supports audio sharing), L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="6605320955858788855">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎Connected (supports audio sharing), left ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="5717356160322149355">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎Connected (supports audio sharing), right ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎Active (media only). ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‎Active (media only). L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎Connected (supports audio sharing). ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎Connected (supports audio sharing). L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎Connected (supports audio sharing). Left: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎Connected (supports audio sharing). Right: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‏‎Connected (supports audio sharing)‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎‎Active (media only)‎‏‎‎‏‎"</string>
     <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎Supports audio sharing‎‏‎‎‏‎"</string>
     <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‎Active (media only), left only‎‏‎‎‏‎"</string>
@@ -487,6 +492,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left until full‎‏‎‎‏‎"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Charging optimized‎‏‎‎‏‎"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Charging‎‏‎‎‏‎"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="STATUS">%2$s</xliff:g>‎‏‎‎‏‏‏‎ - Full by ‎‏‎‎‏‏‎<xliff:g id="TIME">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Fully charged by ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎Fully charged by ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎Full by ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎Unknown‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎Charging‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎Charging rapidly‎‏‎‎‏‎"</string>
@@ -498,6 +507,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎Charged‎‏‎‎‏‎"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎Fully Charged‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‎Charging on hold‎‏‎‎‏‎"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎Charging‎‏‎‎‏‎"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎Fast charging‎‏‎‎‏‎"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎Controlled by admin‎‏‎‎‏‎"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎Controlled by Restricted Setting‎‏‎‎‏‎"</string>
     <string name="disabled" msgid="8017887509554714950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎Disabled‎‏‎‎‏‎"</string>
@@ -684,6 +695,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎Phone one bar.‎‏‎‎‏‎"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‎Phone two bars.‎‏‎‎‏‎"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎Phone three bars.‎‏‎‎‏‎"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎Phone four bars.‎‏‎‎‏‎"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎Phone signal full.‎‏‎‎‏‎"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎No data.‎‏‎‎‏‎"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎Data one bar.‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index be12572..4d4d7c9b 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -186,10 +186,10 @@
   </string-array>
   <string-array name="select_logd_size_summaries">
     <item msgid="409235464399258501">"Desactivado"</item>
-    <item msgid="4195153527464162486">"64 K/búfer registro"</item>
-    <item msgid="7464037639415220106">"256 K/búfer registro"</item>
-    <item msgid="8539423820514360724">"1 M/búfer registro"</item>
-    <item msgid="1984761927103140651">"4 M/búfer registro"</item>
+    <item msgid="4195153527464162486">"64 K/búfer de registro"</item>
+    <item msgid="7464037639415220106">"256 K/búfer de registro"</item>
+    <item msgid="8539423820514360724">"1 M/búfer de registro"</item>
+    <item msgid="1984761927103140651">"4 M/búfer de registro"</item>
     <item msgid="2983219471251787208">"8 M/búfer de registro"</item>
   </string-array>
   <string-array name="select_logpersist_titles">
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 1903c6b..6a40c42 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sin teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sin archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sin teléfono ni archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Activado (batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Activo, I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activado"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo; solo oído izquierdo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo; solo oído derecho"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo; oídos izquierdo y derecho"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo para contenido multimedia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Admite el uso compartido de audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo para contenido multimedia); solo izquierdo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (solo para contenido multimedia); solo derecho"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (solo para contenido multimedia); izquierdo y derecho"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimedia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Llamadas telefónicas"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string>
@@ -335,7 +341,7 @@
     <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Si este modo está habilitado, es posible que la dirección MAC del dispositivo cambie cada vez que se conecte a una red que tenga habilitada la aleatorización de MAC."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"De uso medido"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Sin tarifa plana"</string>
-    <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaños de búfer de Logger"</string>
+    <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaños de los búferes de registro"</string>
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Selecciona el tamaño del Logger por búfer"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"¿Borrar el almacenamiento persistente del registrador?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Cuando ya no usamos el registrador persistente para monitorear, debemos borrar los datos que almacena el registrador en tu dispositivo."</string>
@@ -411,7 +417,7 @@
     <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operaciones de recorte no rectangulares"</string>
     <string name="track_frame_time" msgid="522674651937771106">"Perfil procesamiento HWUI"</string>
     <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Habilitar depuración GPU"</string>
-    <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite capas de GPU para apps de depuración"</string>
+    <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite cargar capas de depuración de GPU para apps de depuración"</string>
     <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Habilitar registro detallado"</string>
     <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Incluye otros registros de proveedor específicos del dispositivo en los informes de errores, que podrían contener información privada, consumir más batería o usar más espacio de almacenamiento."</string>
     <string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animación de ventana"</string>
@@ -471,7 +477,7 @@
     <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteronomalía (rojo-verde)"</string>
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
-    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
+    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de colores"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La corrección de colores puede ser útil cuando quieres hacer lo siguiente:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Ver los colores con mayor precisión&lt;/li&gt; &lt;li&gt;&amp;nbsp;Quitar colores para concentrarte&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Cargando"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carga completa: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Se detuvo la carga"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Cargando"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Carga rápida"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada por el administrador"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Función controlada por configuración restringida"</string>
     <string name="disabled" msgid="8017887509554714950">"Inhabilitada"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Una barra de teléfono"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dos barras de teléfono"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de teléfono"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Teléfono con cuatro barras."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Señal de teléfono completa"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"No hay datos."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Una barra de datos"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 29b29b6..ab75219 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -94,47 +94,53 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sin audio de teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sin audio de teléfono ni multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Activo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Activo L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Izquierda <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Derecha <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo, solo oído izquierdo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo, solo oído derecho"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo, oídos izquierdo y derecho"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (solo multimedia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Permite compartir audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (solo multimedia), solo el izquierdo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (solo multimedia), solo el derecho"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (solo multimedia), izquierdo y derecho"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimedia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Llamadas de teléfono"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Acceso a contactos e historial de llamadas"</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"La información se utilizará para avisos de llamada y más"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"La información se usará para avisos de llamada y más"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartir conexión a Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensajes de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a tarjeta SIM"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hasta la carga completa"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga optimizada"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Cargar"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carga completa a las <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa a las <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Carga completa a las <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Carga completa a las <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carga pausada"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Cargando"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Carga rápida"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada por el administrador"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlado por ajustes restringidos"</string>
     <string name="disabled" msgid="8017887509554714950">"Inhabilitada"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Una barra de cobertura"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dos barras de cobertura"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de cobertura"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Teléfono con cuatro barras."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Cobertura al máximo"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Sin datos"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Una barra de datos"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 9f77bd9..c730457 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ühendatud (telefoni pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ühendatud (meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ühendatud (telefoni ega meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiivne, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiivne, V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> akut, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> akut"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akutase: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> akut, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> akut"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Vasakpoolne: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Parempoolne: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivne"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvestatud"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivne, ainult vasak"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivne, ainult parem"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivne, vasak ja parem"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivne (ainult meedia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Toetab heli jagamist"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivne (ainult meedia), ainult vasak"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiivne (ainult meedia), ainult parem"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiivne (ainult meedia), vasak ja parem"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Meediaheli"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonikõned"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failiedastus"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – täislaadimiseks kulub <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on optimeeritud"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – täis kell <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – aku saab täis kell <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Aku saab täis kell <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Täis kell <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string>
@@ -505,10 +515,12 @@
     <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Juhtmevaba laadimine"</string>
     <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laadimine"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei lae"</string>
-    <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Ühendatud, kuid ei laadita"</string>
+    <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Ühendatud, kuid ei laeta"</string>
     <string name="battery_info_status_full" msgid="1339002294876531312">"Laetud"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Täielikult laetud"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Laadimine on ootele pandud"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Laadimine"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Kiirlaadimine"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Juhib administraator"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Haldavad piiranguga seaded"</string>
     <string name="disabled" msgid="8017887509554714950">"Keelatud"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonisignaal: üks pulk."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonisignaal: kaks pulka."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonisignaal: kolm pulka."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefoni neli riba."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonisignaal on tugev."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Andmed puuduvad."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Andmesignaal: üks pulk."</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 05f3ac7..0668fb2 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -94,44 +94,50 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Konektatuta (telefonoaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Konektatuta (gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Konektatuta (telefonoaren edo gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktibo. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktibo. Ezk. gailuaren bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Esk- gailuaren bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Ezk. gailuaren bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Esk- gailuaren bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Ezkerrekoa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Eskuinekoa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gordeta"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerrekoa soilik"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuinekoa soilik"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, ezkerreko eta eskuineko audifonoak"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (multimedia-edukia soilik)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audioa partekatzeko eginbidea onartzen du"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (multimedia-edukia soilik); ezkerreko aldea soilik"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktibo (multimedia-edukia soilik); eskuineko aldea soilik"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktibo (multimedia-edukia soilik); ezkerreko eta eskuineko aldeak"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Euskarriaren audioa"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefono-deiak"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fitxategi-transferentzia"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sarrerako gailua"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sarrera-gailua"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneteko konexioa"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Eman kontaktuak eta deien historia erabiltzeko baimena"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Deiak iragartzeko eta abarrerako erabiliko da informazioa"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatzeko modu optimizatua"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Kargatzen"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Ordu honetan kargatuko da guztiz: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Kargatuta"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Erabat kargatuta"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Kargatze-prozesua zain dago"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Kargatzen ari da"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Kargatze bizkorra"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Administratzaileak kontrolatzen du"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Ezarpen mugatuak kontrolatzen du"</string>
     <string name="disabled" msgid="8017887509554714950">"Desgaituta"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefono-seinaleak barra bat du."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefono-seinaleak bi barra ditu."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefono-seinaleak hiru barra ditu."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefonoak lau barra ditu."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefono-seinale osoa."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ez dago daturik."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datu-seinaleak barra bat du."</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 658fb0f..3c7f1f8 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"متصل (بدون تلفن)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"متصل (بدون رسانه)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"متصل (بدون تلفن یا رسانه)، باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"فعال، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> شارژ باتری"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"فعال، چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> باتری، راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> باتری"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> شارژ باتری"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> باتری، راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> باتری"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"چپ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"راست <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ذخیره‌شده"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، فقط چپ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، فقط راست"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، چپ و راست"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (فقط رسانه)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"از اشتراک صدا پشتیبانی می‌کند"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (فقط رسانه)، فقط چپ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"فعال (فقط رسانه)، فقط راست"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"فعال (فقط رسانه)، چپ و راست"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"رسانه صوتی"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"تماس‌های تلفنی"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"انتقال فایل"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ بهینه شده است"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - درحال شارژ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"‫<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - تا <xliff:g id="TIME">%3$s</xliff:g> کامل می‌شود"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"‫<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ تا <xliff:g id="TIME">%2$s</xliff:g> کامل می‌شود"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"شارژ تا <xliff:g id="TIME">%1$s</xliff:g> کامل می‌شود"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"تا <xliff:g id="TIME">%1$s</xliff:g> کامل می‌شود"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"شارژ کامل شد"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"کاملاً شارژ شده است"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"شارژ موقتاً متوقف شده است"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"درحال شارژ شدن"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"درحال شارژ سریع"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"توسط سرپرست سیستم کنترل می‌شود"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"با تنظیم «حالت محدود» کنترل می‌شود"</string>
     <string name="disabled" msgid="8017887509554714950">"غیر فعال شد"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"یک نوار برای تلفن."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"دو نوار برای تلفن."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"سه نوار برای تلفن."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"سیگنال تلفن با چهار خط."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"قدرت امواج تلفن همراه کامل است."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"داده‌ای وجود ندارد."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"یک نوار برای داده."</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 14b1701e..da80499 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Yhdistetty (ei puhelimen ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Yhdistetty (ei median ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Yhdistetty (ei puhelimen tai median ääntä), akun varaustaso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiivinen, akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiivinen, V: akku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: akku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"V: akku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: akku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Vasen <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Oikea <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivinen"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Tallennettu"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivinen, vain vasen"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivinen, vain oikea"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivinen, vasen ja oikea"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiivinen (vain media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Tukee audionjakoa"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiivinen (vain media), vain vasen"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiivinen (vain media), vain oikea"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiivinen (vain media), vasen ja oikea"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Median ääni"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Puhelut"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Tiedostonsiirto"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus optimoitu"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladataan"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Täynnä klo <xliff:g id="TIME">%3$s</xliff:g> mennessä"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladattu täyteen klo <xliff:g id="TIME">%2$s</xliff:g> mennessä"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Ladattu täyteen klo <xliff:g id="TIME">%1$s</xliff:g> mennessä"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Täynnä klo <xliff:g id="TIME">%1$s</xliff:g> mennessä"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Ladattu"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Täyteen ladattu"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Lataus on pidossa"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Ladataan"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Nopea lataus"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Järjestelmänvalvoja hallinnoi tätä asetusta."</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Rajoitettujen asetusten mukaisesti"</string>
     <string name="disabled" msgid="8017887509554714950">"Pois päältä"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Puhelinverkkosignaali - yksi palkki."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Puhelinverkkosignaali - kaksi palkkia."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Puhelinverkkosignaali - kolme palkkia."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Puhelin neljä palkkia."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Vahva puhelinverkkosignaali."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ei datasignaalia."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datasignaali - yksi palkki."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index e4ae145..6988384 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connecté (aucun téléphone), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connecté (aucun média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connecté (aucun téléphone ni média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Actif, pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Actif, G : charge à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D : charge à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"G : charge à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D : charge à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Droite : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche seulement"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, droite seulement"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, gauche et droite"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actif (contenu multimédia uniquement)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Prise en charge du partage audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actif (contenu multimédia uniquement), côté gauche seulement"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actif (contenu multimédia uniquement), côté droit seulement"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actif (contenu multimédia uniquement), côtés gauche et droit"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Paramètres audio du support"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Appels téléphoniques"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichier"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la recharge complète)"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Recharge en cours…"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Recharge complète d\'ici <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Recharge complète d\'ici <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Recharge complète d\'ici <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Recharge complète d\'ici <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Complètement rechargée"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Recharge en pause"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Recharge"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Recharge rapide"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Contrôlé par l\'administrateur"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Contrôlé par les paramètres restreints"</string>
     <string name="disabled" msgid="8017887509554714950">"Désactivée"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal : faible"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal : moyen"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal : bon"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Téléphone : quatre barres"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal excellent"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Aucun signal"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal faible"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 09b40ac..709477b 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Connecté (aucun téléphone), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Connecté (aucun contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connecté (aucun téléphone ni contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Actif, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Actif, G : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de la batterie, D : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de la batterie"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterie (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"G : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de la batterie, D : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de la batterie"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Gauche (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Droit (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche uniquement"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actif, droit uniquement"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actifs, gauche et droit"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activé (multimédia uniquement)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible avec le partage audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activé (multimédia uniquement), gauche uniquement"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activé (multimédia uniquement), droit uniquement"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activé (multimédia uniquement), gauche et droit"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimédia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Appels téléphoniques"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichiers"</string>
@@ -339,7 +345,7 @@
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Tailles enreg. par tampon journal"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Effacer l\'espace de stockage persistant de l\'enregistreur ?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Lorsque nous n\'effectuons plus de suivi avec l\'enregistreur persistant, nous sommes tenus d\'effacer les données associées à ce dernier qui sont stockées sur votre appareil."</string>
-    <string name="select_logpersist_title" msgid="447071974007104196">"Stocker données enregistreur en permanence sur appareil"</string>
+    <string name="select_logpersist_title" msgid="447071974007104196">"Stocker données journaux sur appareil de manière persistante"</string>
     <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Sélectionner les mémoires tampon journal à stocker en permanence sur l\'appareil"</string>
     <string name="select_usb_configuration_title" msgid="6339801314922294586">"Sélectionner une configuration USB"</string>
     <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Sélectionner une configuration USB"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge optimisée"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - En charge"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Complètement chargé dans <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Complètement chargé dans <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Complètement chargé dans <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Complètement chargé dans <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Complètement chargée"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Recharge en pause"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Recharge"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Recharge rapide"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Contrôlé par l\'administrateur"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Contrôlé par les paramètres restreints"</string>
     <string name="disabled" msgid="8017887509554714950">"Désactivée"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal : faible"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal : moyen"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal : bon"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Quatre barres sur le téléphone."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal excellent"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Aucun signal"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal faible"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index db40500..e5c7f1e 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen teléfono), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen audio multimedia), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (sen teléfono nin audio multimedia), batería ao <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Dispositivo activo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Activado. E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Lado dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gardado"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo (só o esquerdo)"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo (só o dereito)"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activos (o esquerdo e o dereito)"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activo (só contido multimedia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Compatible con audio compartido"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activo (só contido multimedia), só esquerdo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activo (só contido multimedia), só dereito"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activo (só contido multimedia), esquerdo e dereito"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimedia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefónicas"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de ficheiros"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar a carga)"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> (carga optimizada)"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (cargando)"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Completa á/s <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga completa á/s <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Carga completa á/s <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Completa á/s <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carga en pausa"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Cargando"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Carga rápida"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Opción controlada polo administrador"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Baixo o control de opcións restrinxidas"</string>
     <string name="disabled" msgid="8017887509554714950">"Desactivada"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Unha barra de cobertura"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dúas barras de cobertura"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de cobertura"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Catro barras no teléfono."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Cobertura ao máximo"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Sen datos"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Unha barra de sinal de datos"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index c1eeca5..d520536 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન અથવા મીડિયા નથી), બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"સક્રિય, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"સક્રિય, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> બૅટરી, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> બૅટરી, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ડાબી બાજુ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"જમણી બાજુ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"સક્રિય"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"સાચવેલું"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"સક્રિય, માત્ર ડાબું"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"સક્રિય, માત્ર જમણું"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"સક્રિય, ડાબું અને જમણું બન્ને"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"સક્રિય છે (માત્ર મીડિયા માટે)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ઑડિયો શેરિંગને સપોર્ટ કરે છે"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર ડાબી બાજુ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"સક્રિય છે (માત્ર મીડિયા માટે), માત્ર જમણી બાજુ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"સક્રિય છે (માત્ર મીડિયા માટે), ડાબી અને જમણી બાજુ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"મીડિયા ઑડિયો"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ફોન કૉલ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ફાઇલ સ્થાનાંતરણ"</string>
@@ -335,7 +341,7 @@
     <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"આ મોડ ચાલુ કરેલો હોય ત્યારે MAC રેન્ડમાઇઝેશન ચાલુ કરેલું હોય તેવા નેટવર્ક સાથે આ ડિવાઇસ કનેક્ટ થશે, ત્યારે દર વખતે તેનું MAC ઍડ્રેસ બદલાય તેવું બની શકે છે."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"મીટર કરેલું"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"મીટર ન કરેલ"</string>
-    <string name="select_logd_size_title" msgid="1604578195914595173">"લોગર બફર કદ"</string>
+    <string name="select_logd_size_title" msgid="1604578195914595173">"લૉગર બફર કદ"</string>
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"લૉગર નિરંતર સ્ટોરેજ સાફ કરીએ?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"જ્યારે અમે હવે નિરંતર લૉગર સાથે મોનીટર કરતાં નથી, તો તમારા ઉપકરણ પર રહેલો લૉગર ડેટા કાઢી નાખવાની જરૂર છે."</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> સુધીમાં સંપૂર્ણ ચાર્જ થશે"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ચાર્જ થયું"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"સંપૂર્ણપણે ચાર્જ છે"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ચાર્જિંગ હોલ્ડ પર રાખવામાં આવ્યું"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ચાર્જ થઈ રહ્યું છે"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ઝડપી ચાર્જિંગ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"પ્રતિબંધિત સેટિંગ દ્વારા નિયંત્રિત"</string>
     <string name="disabled" msgid="8017887509554714950">"અક્ષમ કર્યો"</string>
@@ -553,7 +565,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>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ફોન એક બાર."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ફોન બે બાર."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ફોન ત્રણ બાર."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ફોનના સિગ્નલમાં ચાર બાર છે."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"પૂર્ણ ફોન સિગ્નલ."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"કોઈ ડેટા નથી."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ડેટા એક બાર."</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a5b3c88..a81daf7 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"जुड़ गया (फ़ोन के ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"जुड़ गया (मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"जुड़ गया (फ़ोन या मीडिया ऑडियो को छोड़कर), बैटरी का लेवल <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"चालू, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"चालू, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बैटरी, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बैटरी, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"बाएं ईयरबड में <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी बची है"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"दाएं ईयरबड में <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी बची है"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"चालू"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव किया गया"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"सिर्फ़ बाईं तरफ़ वाला चालू है"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सिर्फ़ दाईं तरफ़ वाला चालू है"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"बाईं और दाईं तरफ़ वाला चालू है"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"चालू है (सिर्फ़ मीडिया के लिए)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडियो शेयर करने की सुविधा काम करती है"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ बाएं कान की मशीन"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"चालू है (सिर्फ़ मीडिया के लिए), सिर्फ़ दाएं कान की मशीन"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"चालू है (सिर्फ़ मीडिया के लिए), बाएं और दाएं कान की मशीन"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मीडिया ऑडियो"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"फ़ोन कॉल"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फ़ाइल स्थानांतरण"</string>
@@ -203,7 +209,7 @@
     <string name="launch_defaults_none" msgid="8049374306261262709">"कोई डिफ़ॉल्‍ट सेट नहीं है"</string>
     <string name="tts_settings" msgid="8130616705989351312">"लेख से बोली सेटिंग"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"लिखे गए शब्दों को सुनने की सुविधा"</string>
-    <string name="tts_default_rate_title" msgid="3964187817364304022">"बोलने की दर"</string>
+    <string name="tts_default_rate_title" msgid="3964187817364304022">"बोलने की स्पीड"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"बोलने की गति तय करें"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"पिच"</string>
     <string name="tts_default_pitch_summary" msgid="9132719475281551884">"कृत्रिम बोली के लहजे को प्रभावित करता है"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज हो रही है"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - बैटरी <xliff:g id="TIME">%3$s</xliff:g> में पूरी चार्ज हो जाएगी"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - बैटरी <xliff:g id="TIME">%2$s</xliff:g> में पूरी चार्ज हो जाएगी"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"बैटरी <xliff:g id="TIME">%1$s</xliff:g> में पूरी चार्ज हो जाएगी"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"बैटरी <xliff:g id="TIME">%1$s</xliff:g> में पूरी चार्ज हो जाएगी"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string>
@@ -509,12 +519,14 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"बैटरी चार्ज हो गई"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"बैटरी पूरी चार्ज है"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"फ़ोन को चार्ज होने से रोक दिया गया है"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"चार्ज हो रही है"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"फ़ास्ट चार्जिंग"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"इसका नियंत्रण एडमिन के पास है"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"इसे पाबंदी मोड वाली सेटिंग से कंट्रोल किया जाता है"</string>
     <string name="disabled" msgid="8017887509554714950">"बंद किया गया"</string>
     <string name="external_source_trusted" msgid="1146522036773132905">"अनुमति है"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"अनुमति नहीं है"</string>
-    <string name="install_other_apps" msgid="3232595082023199454">"अज्ञात ऐप्लिकेशन इंस्टॉल करने की अनुमति देना"</string>
+    <string name="install_other_apps" msgid="3232595082023199454">"अनजान ऐप्लिकेशन इंस्टॉल करने की अनुमति"</string>
     <string name="home" msgid="973834627243661438">"सेटिंग का होम पेज"</string>
   <string-array name="battery_labels">
     <item msgid="7878690469765357158">"0%"</item>
@@ -537,7 +549,7 @@
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिस्टम की भाषाओं का इस्तेमाल करें"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> के लिए सेटिंग खोलने में विफल रहा"</string>
     <string name="ime_security_warning" msgid="6547562217880551450">"इनपुट का यह तरीका, आपके पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा के साथ-साथ उस सभी डेटा को इकट्ठा कर सकता है जिसे आप लिखते हैं. यह <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ऐप्लिकेशन से आता है. इनपुट के इस तरीके का इस्तेमाल करें?"</string>
-    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"नोट: पुनः बूट करने के बाद, यह ऐप्लिकेशन तब तक शुरू नहीं हो सकता है जब तक कि आप अपना फ़ोन अनलॉक ना कर लें"</string>
+    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ध्यान दें: डिवाइस को फिर से चालू करने पर, यह ऐप्लिकेशन तब तक शुरू नहीं होगा, जब तक आप अपना फ़ोन अनलॉक न कर लें"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS रजिस्ट्रेशन की स्थिति"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"रजिस्टर है"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"रजिस्टर नहीं है"</string>
@@ -616,7 +628,7 @@
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबंधित प्रोफ़ाइल"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"नया उपयोगकर्ता जोड़ें?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"नए उपयोगकर्ता जोड़कर इस डिवाइस को दूसरे लोगों के साथ शेयर किया जा सकता है. हर उपयोगकर्ता के पास अपनी जगह होती है, जिसमें वे ऐप्लिकेशन, वॉलपेपर, और दूसरी चीज़ों में मनमुताबिक बदलाव कर सकते हैं. उपयोगकर्ता, वाई-फ़ाई जैसी डिवाइस सेटिंग में भी बदलाव कर सकते हैं. इसका असर हर किसी पर पड़ता है.\n\nजब किसी नए उपयोगकर्ता को जोड़ा जाता है, तो उसे अपनी जगह सेट अप करनी होती है.\n\nकोई भी उपयोगकर्ता, दूसरे सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है. ऐसा भी हो सकता है कि सुलभता सेटिंग और सेवाएं नए उपयोगकर्ता को ट्रांसफ़र न हो पाएं."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"कोई नया उपयोगकर्ता जोड़ने पर, उसे अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string>
+    <string name="user_add_user_message_short" msgid="3295959985795716166">"जब किसी नए उपयोगकर्ता को जोड़ा जाता है, तो उस व्यक्ति को डिवाइस में अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"क्या इस व्यक्ति को एडमिन बनाना है?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"एडमिन के पास अन्य लोगों के मुकाबले खास अधिकार होते हैं. एडमिन के पास ये अधिकार होते हैं: सभी लोगों को मैनेज करना, इस डिवाइस को अपडेट या रीसेट करना, सेटिंग में बदलाव करना, इंस्टॉल किए गए सभी ऐप्लिकेशन देखना, और अन्य लोगों को एडमिन के खास अधिकार देना या उन्हें वापस लेना."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"एडमिन बनाएं"</string>
@@ -638,7 +650,7 @@
     <string name="add_user_failed" msgid="4809887794313944872">"नया उपयोगकर्ता जोड़ा नहीं जा सका"</string>
     <string name="add_guest_failed" msgid="8074548434469843443">"नया मेहमान खाता नहीं बनाया जा सका"</string>
     <string name="user_nickname" msgid="262624187455825083">"निकनेम"</string>
-    <string name="edit_user_info_message" msgid="6677556031419002895">"आपकी चुनी गई फ़ोटो और नाम, उन सभी लोगों को दिखेगा जो इस डिवाइस का इस्तेमाल करते हैं."</string>
+    <string name="edit_user_info_message" msgid="6677556031419002895">"आपका नाम और चुनी गई फ़ोटो, इस डिवाइस का इस्तेमाल करने वाले हर व्यक्ति को दिखेगी."</string>
     <string name="user_add_user" msgid="7876449291500212468">"उपयोगकर्ता जोड़ें"</string>
     <string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान को हटाएं"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फ़ोन एक बार."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फ़ोन दो बार."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तीन बार."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"फ़ोन के चार सिग्नल बार हैं."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फ़ोन सि‍ग्‍नल पूरा."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"कोई डेटा नहीं."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटा एक बार."</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index a504c9a0..362393e 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -33,7 +33,7 @@
     <string name="wifi_security_short_none_owe" msgid="8827409046261759703">"Ništa/OWE"</string>
     <string name="wifi_security_short_owe" msgid="5073524307942025369">"OWE"</string>
     <string name="wifi_security_short_eap_suiteb" msgid="4174071135081556115">"Suite-B-192"</string>
-    <string name="wifi_security_none" msgid="7392696451280611452">"Nema"</string>
+    <string name="wifi_security_none" msgid="7392696451280611452">"Ništa"</string>
     <string name="wifi_security_wep" msgid="1413627788581122366">"WEP"</string>
     <string name="wifi_security_wpa" msgid="1072450904799930636">"WPA-Personal"</string>
     <string name="wifi_security_wpa2" msgid="4038267581230425543">"WPA2-Personal"</string>
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (bez telefona i medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktivan, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivno, L: baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Lijevo <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Desno <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Spremljeno"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevo i desno"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo medijski sadržaji)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podržava zajedničko slušanje"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo medijski sadržaji), samo lijeva"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo medijski sadržaji), samo desna"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo medijski sadržaji), lijeva i desna"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk medija"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski pozivi"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prijenos datoteke"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje se optimizira"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – napunjeno do <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – potpuno napunjeno do <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Potpuno napunjeno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Napunjeno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Posve puna"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Punjenje na čekanju"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Punjenje"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Brzo punjenje"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolira administrator"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolira ograničena postavka"</string>
     <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonski signal jedan stupac."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonski signal dva stupca."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonski signal tri stupca."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Signal na telefonu ima četiri crtice."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonski signal pun."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Podatkovni signal jedan stupac."</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 3838d7d0..f251464 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Csatlakoztatva (telefonhang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Csatlakoztatva (médiahang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Csatlakoztatva (nincs telefon- és médiahang); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktív, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-os töltöttség"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktív, B: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>-os töltöttség, J: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>-os töltöttség"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"B: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>-os töltöttség, J: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>-os töltöttség"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Bal: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Jobb: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktív"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Mentve"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktív, csak bal"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktív, csak jobb"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktív, bal és jobb"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktív (csak médiatartalom lejátszása)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Támogatja a hang megosztását"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktív (csak médiatartalom lejátszása), csak a bal"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktív (csak médiatartalom lejátszása), csak a jobb"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktív (csak médiatartalom lejátszása), bal és jobb"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Médiahang"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonhívások"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fájlátvitel"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttségig"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizált töltés"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Töltés…"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Teljes feltöltés eddig: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Teljes feltöltés eddig: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Teljes feltöltés eddig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Teljes feltöltés eddig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Feltöltve"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Teljesen feltöltve"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"A töltés szünetel"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Töltés…"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Gyors töltés…"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Rendszergazda által irányítva"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Korlátozott beállítás vezérli"</string>
     <string name="disabled" msgid="8017887509554714950">"Letiltva"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon egy sáv."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon két sáv."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon három sáv."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon négy egységnyi térerővel."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonjel megtelt."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nincsenek adatok."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Adat egy sáv."</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 0069175..4b6d727 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Միացված է (հեռախոս չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Միացված է (մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Միացված է (հեռախոս կամ մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Ակտիվ է։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Ակտիվ է, Ա` Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Ձ՝ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Ա՝ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Ձ՝ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Ձախը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Աջը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ակտիվ է"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Պահված է"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ակտիվ, միայն ձախ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ակտիվ, միայն աջ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ակտիվ, ձախ և աջ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ակտիվ է (միայն մեդիա)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Աջակցում է աուդիոյի փոխանցում"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ակտիվ է (միայն մեդիա), միայն ձախ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ակտիվ է (միայն մեդիա), միայն աջ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ակտիվ է (միայն մեդիա), աջ և ձախ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Մեդիա աուդիո"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Հեռախոսազանգեր"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Ֆայլերի փոխանցում"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումն օպտիմալացված է"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> — Լիցքավորում"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Ամբողջովին կլիցքավորվի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Լիցքավորված է"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Լրիվ լիցքավորված է"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Լրցքավորումը դադարեցված է"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Լիցքավորում"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Արագ լիցքավորում"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Վերահսկվում է ադմինիստրատորի կողմից"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Կառավարվում է սահմանափակ ռեժիմի կարգավորումներով"</string>
     <string name="disabled" msgid="8017887509554714950">"Կասեցված է"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Հեռախոսի մեկ գիծ:"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Հեռախոսի երկու գիծ:"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Հեռախոսի երեք գիծ:"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Հեռախոսակապի ուժգնությունը՝ չորս գիծ։"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Հեռախոսի ազդանշանը լիքն է:"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Տվյալներ չկան:"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Տվյալների մեկ գիծ:"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 6254f7b..1594d11 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -94,44 +94,50 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Terhubung (tanpa ponsel), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Terhubung (tanpa media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Terhubung (tanpa ponsel atau media), baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktif, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktif, Kr: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterai, Kn: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterai"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Kr: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterai, Kn: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterai"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kiri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Kanan <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, hanya kiri"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, hanya kanan"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (hanya media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mendukung berbagi audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (hanya media), hanya kiri"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktif (hanya media), hanya kanan"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktif (hanya media), kiri dan kanan"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio media"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Panggilan telepon"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer file"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Perangkat masukan"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Perangkat input"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Izinkan akses ke kontak dan histori panggilan"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Info akan digunakan untuk pengumuman panggilan dan lain-lain"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sampai penuh"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dioptimalkan"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengisi daya"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Penuh dalam <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Baterai terisi penuh dalam <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Baterai terisi penuh dalam <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Penuh dalam <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Terisi"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Baterai Terisi Penuh"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Pengisian daya dihentikan sementara"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Pengisian daya"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Pengisian daya cepat"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Dikontrol oleh admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Dikontrol oleh Setelan Terbatas"</string>
     <string name="disabled" msgid="8017887509554714950">"Dinonaktifkan"</string>
@@ -555,7 +567,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm dan pengingat"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Izinkan menyetel alarm dan pengingat"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm &amp; pengingat"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Mengizinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadwal, alarm, pengingat, jam"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktifkan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktifkan mode Jangan Ganggu"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Ponsel satu batang."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Ponsel dua batang."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Ponsel tiga batang."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telepon empat batang."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinyal ponsel penuh."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Tidak ada data yang diterima."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data satu batang."</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 0f57670..b85f453 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Tengt (enginn sími), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Tengt (ekkert efni), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Tengt (enginn sími eða efni), staða rafhlöðu <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Tengt, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Virkt, V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> rafhlaða, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlaða"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Rafhlaða <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> rafhlaða, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlaða"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Vinstri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Hægri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Virkt"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Vistað"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Virkt, aðeins vinstra"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Virkt, aðeins hægra"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Virkt, vinstra og hægra"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Virkt (eingöngu margmiðlunarefni)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Styður hljóðdeilingu"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Virkt (eingöngu margmiðlunarefni), eingöngu vinstri"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Virkt (eingöngu margmiðlunarefni), eingöngu hægri"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Virkt (eingöngu margmiðlunarefni), vinstri og hægri"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Hljóð efnis"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Símtöl"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Skráaflutningur"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> fram að fullri hleðslu"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Hleðsla fínstillt"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Í hleðslu"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Fullt kl. <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Fullhlaðið kl. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fullhlaðið kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Fullt kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Fullhlaðin"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Full hleðsla"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Hleðsla í bið"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Í hleðslu"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Hraðhleðsla"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Stjórnað af kerfisstjóra"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Stýrt af takmarkaði stillingu"</string>
     <string name="disabled" msgid="8017887509554714950">"Óvirkt"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Styrkur símasambands er eitt strik."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Styrkur símasambands er tvö strik."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Styrkur símasambands er þrjú strik."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Sími fjórar stikur."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Fullur styrkur símasambands."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Engin gögn."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Sendistyrkur gagnatengingar er eitt strik."</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9502374..08a2397 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Attivo - Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Attivo, S: batteria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: batteria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"S: batteria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: batteria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Sinistra: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Destra: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Attivo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Dispositivo salvato"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Attiva, solo sinistra"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Attiva, solo destra"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Attivo, destra e sinistra"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Attivo (solo contenuti multimediali)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Supporta la condivisione audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Attivo (solo contenuti multimediali), solo sinistro"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Attivo (solo contenuti multimediali), solo destro"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Attivo (solo contenuti multimediali), sinistro e destro"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimediale"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonate"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Trasferimento file"</string>
@@ -167,7 +173,7 @@
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Annulla"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"L\'accoppiamento consente l\'accesso ai tuoi contatti e alla cronologia chiamate quando i dispositivi sono connessi."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Impossibile eseguire l\'accoppiamento con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Impossibile eseguire l\'accoppiamento con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. La password o il PIN sono errati."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Impossibile eseguire l\'accoppiamento con <xliff:g id="DEVICE_NAME">%1$s</xliff:g> perché la passkey o il PIN sono errati."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Impossibile comunicare con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Accoppiamento rifiutato da <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computer"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla ricarica completa"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica ottimizzata"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ In carica"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Ricarica completa entro <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria completamente carica entro <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Batteria completamente carica entro <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Ricarica completa entro <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Carica"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Batteria completamente carica"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ricarica in sospeso"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"In carica"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Ricarica rapida"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Gestita dall\'amministratore"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Gestita tramite impostazioni con restrizioni"</string>
     <string name="disabled" msgid="8017887509554714950">"Disattivato"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefono: una barra."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefono: due barre."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefono: tre barre."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefono con quattro barre."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Massimo segnale telefonico."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nessun dato."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dati: una barra."</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index dea8ca3..9ecf47b 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -94,47 +94,53 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"מחובר (ללא טלפון), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"מחובר (ללא מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"מחובר (ללא טלפון או מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"פעיל, טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"פעיל, שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> סוללה, ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> סוללה"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"סוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> סוללה, ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> סוללה"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> שמאלי"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ימני"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"פעיל"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"בוצעה שמירה"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"פועל: שמאל בלבד"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"פועל: ימין בלבד"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"פועל: ימין ושמאל"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"פעיל (מדיה בלבד)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"תמיכה בשיתוף אודיו"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"פעיל (מדיה בלבד), שמאל בלבד"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"פעיל (מדיה בלבד), ימין בלבד"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"פעיל (מדיה בלבד), שמאל וימין"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"אודיו של מדיה"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"שיחות טלפון"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"העברת קבצים"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"מכשיר קלט"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"התקן קלט"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"גישה לאינטרנט"</string>
-    <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"אישור גישה אל אנשי קשר והיסטוריית שיחות"</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"המידע ישמש להודעות על שיחות ועוד"</string>
+    <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"אישור גישה אל אנשי הקשר והיסטוריית השיחות"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"המידע הזה ישמש למשל כדי להשמיע התראות על שיחות נכנסות"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"שיתוף חיבור לאינטרנט"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"הודעות טקסט"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"‏גישה ל-SIM"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה עברה אופטימיזציה"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"‫<xliff:g id="LEVEL">%1$s</xliff:g> – בטעינה"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"‫<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – טעינה מלאה עד <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"‫<xliff:g id="LEVEL">%1$s</xliff:g> – טעינה מלאה עד <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"טעינה מלאה עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"טעינה מלאה עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"הסוללה טעונה"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"טעונה במלואה"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"הטעינה הושהתה"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"טעינה"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"טעינה מהירה"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"נמצא בשליטת מנהל מערכת"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"בשליטה של הגדרה מוגבלת"</string>
     <string name="disabled" msgid="8017887509554714950">"מושבת"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"פס אחד של טלפון."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"שני פסים של טלפון."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"שלושה פסים של טלפון."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ארבעה פסים בטלפון."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"אות הטלפון מלא."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"אין נתונים."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"פס אחד של נתונים."</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index c7f3c0a..a51ba39 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"接続済み(電話なし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"接続済み(メディアなし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"接続済み(電話、メディアなし)、バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"有効、バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"有効、L: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、R: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、R: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"左 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"右 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"有効"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"保存済み"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"有効、左のみ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"有効、右のみ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"有効、左と右"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"有効(メディアのみ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"音声の共有をサポートしています"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"有効(メディアのみ)、左のみ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"有効(メディアのみ)、右のみ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"有効(メディアのみ)、左右"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"メディアの音声"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"電話"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ファイル転送"</string>
@@ -279,7 +285,7 @@
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"デバイスをペア設定しています…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"デバイスをペア設定できませんでした。QR コードが間違っているか、デバイスが同じネットワークに接続されていません。"</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP アドレスとポート"</string>
-    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR コードのスキャン"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR コードをスキャン"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR コードをスキャンして Wi-Fi 経由でデバイスをペア設定します"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi ネットワークに接続してください"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, デバッグ, dev"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 完了まであと <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電が最適化されています"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電中"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>までに完了"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>までに充電完了"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>までに充電完了"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>までに完了"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"充電が完了しました"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"充電完了"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"充電を一時停止しています"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"充電中"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"急速充電中"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"管理者により管理されています"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"制限付き設定によって管理されています"</string>
     <string name="disabled" msgid="8017887509554714950">"無効"</string>
@@ -666,9 +678,9 @@
     <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"終了時にアクティビティを保存、削除できます"</string>
     <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"アクティビティは、リセットして今すぐ削除するか、終了時に保存または削除できます"</string>
     <string name="user_image_photo_selector" msgid="433658323306627093">"写真を選択"</string>
-    <string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"間違えた回数が上限を超えました。このデバイスのデータが削除されます。"</string>
-    <string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"間違えた回数が上限を超えました。このユーザーが削除されます。"</string>
-    <string name="failed_attempts_now_wiping_profile" msgid="7626589520888963129">"間違えた回数が上限を超えました。この仕事用プロファイルと関連データが削除されます。"</string>
+    <string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"試行回数が上限に達しました。このデバイスのデータが削除されます。"</string>
+    <string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"試行回数が上限に達しました。このユーザーが削除されます。"</string>
+    <string name="failed_attempts_now_wiping_profile" msgid="7626589520888963129">"試行回数が上限に達しました。この仕事用プロファイルと関連データが削除されます。"</string>
     <string name="failed_attempts_now_wiping_dialog_dismiss" msgid="2749889771223578925">"閉じる"</string>
     <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"デバイスのデフォルト"</string>
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"無効"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電波状態:レベル1"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電波状態:レベル2"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電波状態:レベル3"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"スマートフォンのアンテナは 4 本です。"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電波状態:フル"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"データ信号:なし"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"データ信号:レベル1"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index a94a401..ba1dae0 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"დაკავშირებულია (ტელეფონი არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"დაკავშირებულია (მედია არ არის). ბატარეა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"დაკავშირებულია (ტელეფონი ან მედია არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"აქტიურია, ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-ს შეადგენს"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"აქტიური, მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ბატარეა, მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ბატარეა"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ბატარეა, მარჯვენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ბატარეა"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"მარცხენა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"მარჯვენა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"აქტიური"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"შენახული"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"აქტიური, მხოლოდ მარცხნივ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"აქტიური, მხოლოდ მარჯვნივ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"აქტიური, მარცხნივ და მარჯვნივ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"აქტიური (მხოლოდ მედია)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"აუდიოს გაზიარება მხარდაჭერილია"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"აქტიური (მხოლოდ მედია), მხოლოდ მარცხენა"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"აქტიური (მხოლოდ მედია), მხოლოდ მარჯვენა"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"აქტიური (მხოლოდ მედია), მარცხენა და მარჯვენა"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"მედია აუდიო"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"სატელეფონო ზარები"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ფაილების გადაცემა"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ოპტიმიზირებულია"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – იტენება"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - სრულად დატენის დრო: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - სრულად დატენის დრო: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"სრულად დატენის დრო: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"სრულად დატენის დრო: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"დატენილია"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ბოლომდე დატენილი"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"დატენვა შეჩერებულია"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"იტენება"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"სწრაფი დატენა"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"იმართება ადმინისტრატორის მიერ"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"კონტროლდება შეზღუდული რეჟიმის პარამეტრით"</string>
     <string name="disabled" msgid="8017887509554714950">"გამორთული"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ტელეფონის სიგნალი სამ ზოლზეა."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ტელეფონის სიგნალი ოთხ ზოლზეა."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ტელეფონის სიგნალი სრულია."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"მონაცემები არ არის."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"თარიღი ზოლზე."</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 1c80ad4..b8f8fa3 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -94,44 +94,50 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Жалғанды (телефонсыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Жалғанды (аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Жалғанды (телефонсыз не аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Қосулы, батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Қосулы, С: батарея заряды – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, О: батарея заряды – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"С: батарея заряды – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, О: батарея заряды – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Сол: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Оң: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Қосулы"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сақталған"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Тек сол жағы қосулы"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Тек оң жағы қосулы"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Екеуі де қосулы"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Істеп тұр (тек мультимедиа)."</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио бөлісуге мүмкіндік береді."</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Тек сол жақ істеп тұр (мультимедиа ғана)."</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Тек оң жақ істеп тұр (мультимедиа ғана)."</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Сол және оң жақ істеп тұр (мультимедиа ғана)."</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Mультимeдиа дыбысы"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефон қоңыраулары"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл жіберу"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Кіріс құрылғысы"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Енгізу құрылғысы"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернетке қосылу"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Контакт пен қоңырау тарихына рұқсат беру"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Ақпарат қоңырау туралы хабарландыру, т.б. үшін қолданылады."</string>
@@ -208,7 +214,7 @@
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"Дауыс жиілігі"</string>
     <string name="tts_default_pitch_summary" msgid="9132719475281551884">"Синтезделген сөйлеу үніне әсер етеді"</string>
     <string name="tts_default_lang_title" msgid="4698933575028098940">"Тіл"</string>
-    <string name="tts_lang_use_system" msgid="6312945299804012406">"Жүйелік тілді пайдалану"</string>
+    <string name="tts_lang_use_system" msgid="6312945299804012406">"Жүйе тілін пайдалану"</string>
     <string name="tts_lang_not_selected" msgid="7927823081096056147">"Тіл таңдалған жоқ"</string>
     <string name="tts_default_lang_summary" msgid="9042620014800063470">"Сөйлеу мәтіні үшін тілге тән дауыс орнатады"</string>
     <string name="tts_play_example_title" msgid="1599468547216481684">"Үлгіні тыңдау"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: толық зарядталуға <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау оңтайландырылды"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Зарядталып жатыр"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Заряд толуына қалған уақыт: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Толық заряд алуға қалған уақыт: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Толық заряд алуға қалған уақыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Заряд толуына қалған уақыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядтау"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Зарядталды"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Толық зарядталды."</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Зарядтау кідіртілді."</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Зарядталып жатыр."</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Жылдам зарядтау"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Әкімші басқарады"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Шектелген параметрлер арқылы басқарылады."</string>
     <string name="disabled" msgid="8017887509554714950">"Өшірілген"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон бір баған."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон екі баған."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон үш баған."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Телефон байланысының төрт бағанасы."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Телефон сигналы толық."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Дерекқор жоқ."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Дерекқор бір баған."</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 23bd55c..d049fd4 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"បាន​ភ្ជាប់ (គ្មាន​ទូរសព្ទ​ទេ) ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"បាន​ភ្ជាប់ (គ្មាន​មេឌៀ​ទេ) ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"បាន​ភ្ជាប់ (គ្មាន​ទូរសព្ទ ឬ​មេឌៀ​ទេ) ហើយ​ថ្ម​មាន​កម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"សកម្ម ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"សកម្ម, L៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ឆ្វេង <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ស្ដាំ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"សកម្ម"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"បាន​រក្សាទុក"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្ម ខាងឆ្វេងតែប៉ុណ្ណោះ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"សកម្មខាងស្ដាំតែប៉ុណ្ណោះ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"សកម្មខាងឆ្វេង និងស្ដាំ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"អាចប្រើការស្ដាប់សំឡេងរួមគ្នា"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងឆ្វេងប៉ុណ្ណោះ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) តែខាងស្ដាំប៉ុណ្ណោះ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ) ឆ្វេង និងស្ដាំ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"សំឡេង​មេឌៀ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ការហៅ​ទូរសព្ទ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ផ្ទេរ​ឯកសារ"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបពេញ"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានបង្កើនប្រសិទ្ធភាពនៃការសាក"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងសាកថ្ម"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - ពេញនៅម៉ោង <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - សាកថ្មពេញនៅម៉ោង <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"សាកថ្មពេញនៅម៉ោង <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"ពេញនៅម៉ោង <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងសាក​ថ្ម"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"បាន​សាក​ថ្មពេញ"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"បានសាក​ថ្មពេញ"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"កំពុងផ្អាកការសាកថ្ម"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"កំពុងសាកថ្ម"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ការសាកថ្មរហ័ស"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"គ្រប់គ្រងដោយការកំណត់ដែលបានរឹតបន្តឹង"</string>
     <string name="disabled" msgid="8017887509554714950">"បិទ"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"សេវា​ទូរស័ព្ទ​មួយ​កាំ។"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"សេវា​ទូរស័ព្ទ​ពីរ​កាំ។"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"សេវា​ទូរស័ព្ទ​បី​កាំ​។"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"បួនកាំលើទូរសព្ទ។"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"សេវា​ទូរស័ព្ទ​ពេញ។"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"គ្មាន​ទិន្នន័យ​។"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ទិន្នន័យ​មួយ​​កាំ។"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index c636dd5..70257de 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಇಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಅಥವಾ ಮಾಧ್ಯಮವಿಲ್ಲ), ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ ಮಟ್ಟ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ಸಕ್ರಿಯ, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ಸಕ್ರಿಯ, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ಬ್ಯಾಟರಿ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಇದೆ"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ಬ್ಯಾಟರಿ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ಎಡ ಭಾಗದ ಬ್ಯಾಟರಿ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ಬಲ ಭಾಗದ ಬ್ಯಾಟರಿ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ಸಕ್ರಿಯ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ಎಡಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ಬಲಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ಎಡ ಮತ್ತು ಬಲಕಿವಿಯ ಸಾಧನಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಭಾಗದ ಮಾತ್ರ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಬಲ ಭಾಗದ ಮಾತ್ರ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ), ಎಡ ಮತ್ತು ಬಲ ಭಾಗದ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ಮಾಧ್ಯಮ ಆಡಿಯೋ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ಫೋನ್ ಕರೆಗಳು"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string>
@@ -162,7 +168,7 @@
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ಇನ್‌ಪುಟ್‌ಗಾಗಿ ಬಳಸು"</string>
     <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"ಶ್ರವಣ ಸಾಧನಗಳಿಗಾಗಿ ಬಳಸಿ"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO ಗೆ ಬಳಸಿ"</string>
-    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"ಜೋಡಿಸಿ"</string>
+    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"ಪೇರ್ ಮಾಡಿ"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ಜೋಡಿ ಮಾಡು"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"ರದ್ದುಮಾಡಿ"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"ಸಂಪರ್ಕಗೊಳಿಸಿದಾಗ, ಜೋಡಿಸುವಿಕೆಯು ನಿಮ್ಮ ಸಂಪರ್ಕಗಳು ಮತ್ತು ಕರೆ ಇತಿಹಾಸಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
@@ -333,7 +339,7 @@
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ಬ್ಯಾಟರಿ ಹೆಚ್ಚು ಬಾಳಿಕೆ ಬರುವಂತೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನೆಟ್‌ವರ್ಕ್‌ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ"</string>
     <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ಈ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, MAC ಯಾದೃಚ್ಛಿಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿದಾಗ ಈ ಸಾಧನದ MAC ವಿಳಾಸವು ಪ್ರತಿ ಬಾರಿಯೂ ಬದಲಾಗಬಹುದು."</string>
-    <string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ಡ್ ನೆಟ್‌ವರ್ಕ್"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"ಮೀಟರ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್‌ಗೆ ಲಾಗರ್ ಗಾತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
@@ -487,7 +493,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"ನಿಮ್ಮ ಬಳಕೆ ಆಧರಿಸಿ <xliff:g id="TIME">%1$s</xliff:g> ವರೆಗೆ ರನ್ ಆಗಲಿದೆ"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ಸಮಯದವರೆಗೆ ರನ್ ಆಗಲಿದೆ"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"<xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ರನ್ ಆಗಲಿದೆ"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> ರವರೆಗೆ"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> ವರೆಗೆ ಇರುತ್ತದೆ"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> ಗಳಲ್ಲಿ ಬ್ಯಾಟರಿ ಮುಕ್ತಾಯವಾಗಬಹುದು"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ವೇಳೆಗೆ ಭರ್ತಿಯಾಗುತ್ತದೆ"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೇಳೆಗೆ ಸಂಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> ವೇಳೆಗೆ ಸಂಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> ವೇಳೆಗೆ ಭರ್ತಿಯಾಗುತ್ತದೆ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಹೋಲ್ಡ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ಫಾಸ್ಟ್ ಚಾರ್ಜಿಂಗ್"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ನಿರ್ಬಂಧಿಸಲಾದ ಸೆಟ್ಟಿಂಗ್ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗುತ್ತದೆ"</string>
     <string name="disabled" msgid="8017887509554714950">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
@@ -537,7 +549,7 @@
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"ಸಿಸ್ಟಂ ಭಾಷೆಗಳನ್ನು ಬಳಸಿ"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ಗಾಗಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಲು ವಿಫಲವಾಗಿದೆ"</string>
     <string name="ime_security_warning" msgid="6547562217880551450">"ವೈಯಕ್ತಿಕ ಡೇಟಾಗಳಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನೀವು ಟೈಪ್ ಮಾಡುವ ಎಲ್ಲ ಪಠ್ಯವನ್ನು ಸಂಗ್ರಹಿಸಲು ಈ ಇನ್‌ಪುಟ್ ವಿಧಾನಕ್ಕೆ ಸಾಧ್ಯವಾಗಬಹುದು. ಇದು <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಬರುತ್ತದೆ. ಈ ಇನ್‌ಪುಟ್ ವಿಧಾನವನ್ನು ಬಳಸುವುದೇ?"</string>
-    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ಗಮನಿಸಿ: ರೀಬೂಟ್ ನಂತರ, ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಅನ್‌ಲಾಕ್ ಮಾಡುವ ತನಕ ಈ ಆಪ್ ಪ್ರಾರಂಭಗೊಳ್ಳುವುದಿಲ್ಲ"</string>
+    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"ಗಮನಿಸಿ: ರೀಬೂಟ್ ನಂತರ, ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಅನ್‌ಲಾಕ್ ಮಾಡುವ ತನಕ ಈ ಆ್ಯಪ್ ಪ್ರಾರಂಭಗೊಳ್ಳುವುದಿಲ್ಲ"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS ನೋಂದಣಿ ಸ್ಥಿತಿ"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"ನೋಂದಾಯಿಸಲಾಗಿದೆ"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"ನೋಂದಾಯಿಸಲಾಗಿಲ್ಲ"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ಪೋನ್ ಒಂದು ಪಟ್ಟಿ."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ಫೋನ್ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ಫೋನ್ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ಫೋನ್‌ನ ನಾಲ್ಕು ಬಾರ್‌ಗಳು."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ಫೋನ್ ಸಂಕೇತ ಪೂರ್ತಿ ಇದೆ."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ಯಾವುದೇ ಡೇಟಾ ಇಲ್ಲ."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ಡೇಟಾ ಒಂದು ಪಟ್ಟಿ."</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index f193fef..9ced8a0 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"연결됨(전화 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"연결됨(미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"연결됨(전화 또는 미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"활성, 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"활성, 왼쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"왼쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽: 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"활성"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"저장됨"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"활성, 왼쪽만"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"활성, 오른쪽만"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"활성, 왼쪽 및 오른쪽"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"사용 중(미디어 전용)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"오디오 공유 지원"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"사용 중(미디어 전용), 왼쪽만"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"사용 중(미디어 전용), 오른쪽만"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"사용 중(미디어 전용), 왼쪽 및 오른쪽"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"미디어 오디오"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"전화 통화"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"파일 전송"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 최적화됨"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ 충전 중"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>에 완전히 충전됨"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>에 완전히 충전됨"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>에 완전히 충전됨"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>에 완전히 충전됨"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"충전됨"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"완전히 충전됨"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"충전 일시중지"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"충전"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"급속 충전"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"관리자가 제어"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"제한된 설정으로 제어됨"</string>
     <string name="disabled" msgid="8017887509554714950">"사용 안함"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"휴대전화 신호 막대가 하나입니다."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"휴대전화 신호 막대가 두 개입니다."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"휴대전화 신호 막대가 세 개입니다."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"전화 막대가 네 개입니다."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"휴대전화의 신호가 강합니다."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"데이터가 없습니다."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"데이터 신호 막대가 하나입니다."</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 86426fa..7be7f38 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Туташып турат (телефониясыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Туташып турат (медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Туташып турат (телефониясыз же медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Иштеп жатат, батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активдүү, сол: Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, оң: Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батареянын кубаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Сол: Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, оң: Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Сол: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Оң: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Жигердүү"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сакталган"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Иштеп жатат, сол кулак гана"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Жигердүү, оң кулакчын гана"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Жигердүү, сол жана оң кулакчын"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активдүү (медиа үчүн гана)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Чогуу угуу колдоого алынат"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активдүү (медиа үчүн гана), сол кулакчын гана"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активдүү (медиа үчүн гана), оң кулакчын гана"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активдүү (медиа үчүн гана), сол жана оң кулакчын"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Аудио"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефон чалуулар"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл алмашуу"</string>
@@ -292,7 +298,7 @@
     <string name="oem_unlock_enable" msgid="5334869171871566731">"OEM бөгөттөн чыгаруу"</string>
     <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Кайра жүктөгүчтү бөгөттөн чыгарууга уруксат берүү"</string>
     <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM бөгөттөн чыгарууга уруксатпы?"</string>
-    <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ЭСКЕРТҮҮ: Бул жөндөө күйгүзүлүп турганда түзмөктү коргоо өзгөчөлүктөрү иштебейт."</string>
+    <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ЭСКЕРТҮҮ: Бул параметр күйгүзүлүп турганда түзмөктү коргоо өзгөчөлүктөрү иштебейт."</string>
     <string name="mock_location_app" msgid="6269380172542248304">"Жалган жайгашкан жерлерди көрсөткөн колдонмону тандоо"</string>
     <string name="mock_location_app_not_set" msgid="6972032787262831155">"Жалган жайгашкан жерлерди көрсөткөн колдонмо жок"</string>
     <string name="mock_location_app_set" msgid="4706722469342913843">"Жалган жайгашкан жерлерди көрсөткөн колдонмо: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -339,7 +345,7 @@
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Таржымалдын туруктуу диски тазалансынбы?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Туруктуу таржымалга көз салууну токтотсок, анын түзмөктө сакталган дайындарын жок кылууга аргасыз болобуз."</string>
-    <string name="select_logpersist_title" msgid="447071974007104196">"Журналдагы маалымат түзмөккө сакталсын"</string>
+    <string name="select_logpersist_title" msgid="447071974007104196">"Журналдагы нерселерди түзмөккө сактоо"</string>
     <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Түзмөккө туруктуу сактоо үчүн таржымал буферлерин тандаңыз"</string>
     <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB конфигурациясын тандоо"</string>
     <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB конфигурациясын тандоо"</string>
@@ -398,7 +404,7 @@
     <string name="simulate_color_space" msgid="1206503300335835151">"Аномалияга окшошуу"</string>
     <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL трейстерин иштетүү"</string>
     <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Аудиону өткөрүүнү өчүрүү (USB)"</string>
-    <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Тышкы USB аудио жабдыктарына авто өткөрүү өчрлт"</string>
+    <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Тышкы USB түзмөктөргө автоматтык түрдө өтпөйт"</string>
     <string name="debug_layout" msgid="1659216803043339741">"Элементтрдн чектрин көрст"</string>
     <string name="debug_layout_summary" msgid="8825829038287321978">"Кесилген нерсенин чектери жана жээктери көрүнөт"</string>
     <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Интерфейсти чагылдыруу"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — Кубаттоо жакшыртылды"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Кубатталууда"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Саат <xliff:g id="TIME">%3$s</xliff:g> кубатталып бүтөт"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> чейин толук кубатталат"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> чейин толук кубатталат"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Саат <xliff:g id="TIME">%1$s</xliff:g> кубатталып бүтөт"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Кубатталды"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Толук кубатталды"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Кубаттоо күтүү режиминде"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Кубатталууда"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Ыкчам кубаттоо"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Администратор тарабынан көзөмөлдөнөт"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Чектелген параметр аркылуу көзөмөлдөнөт"</string>
     <string name="disabled" msgid="8017887509554714950">"Өчүрүлгөн"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон сигналы бир таякча."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон сигналы эки таякча."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон сигналы үч таякча."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Телефон: төрт таякча."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Телефон сигналы толук."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Сигнал жок."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Мобилдик интернеттин сигналы бир таякча."</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index ad1529d..c6a5bd4 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ ຫຼື ມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ເປີດໃຊ້ຢູ່, ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ເປີດໃຊ້, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ແບັດເຕີຣີ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ແບັດເຕີຣີ"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ແບັດເຕີຣີ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ແບັດເຕີຣີ"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ຊ້າຍ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ຂວາ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ອອນລາຍ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ບັນທຶກແລ້ວ"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ນຳໃຊ້ຢູ່, ຊ້າຍເທົ່ານັ້ນ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ນຳໃຊ້ຢູ່, ຂວາເທົ່ານັ້ນ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ນຳໃຊ້ຢູ່, ຊ້າຍ ແລະ ຂວາ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ຮອງຮັບການແບ່ງປັນສຽງ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍເທົ່ານັ້ນ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຂວາເທົ່ານັ້ນ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ), ຊ້າຍ ແລະ ຂວາ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ສຽງ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ການໂທ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ການໂອນຍ້າຍໄຟລ໌"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"ຍັງເຫຼືອອີກ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກຖືກປັບໃຫ້ເໝາະສົມແລ້ວ"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງສາກໄຟ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - ຈະເຕັມພາຍໃນ <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈະສາກເຕັມພາຍໃນ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"ຈະສາກເຕັມພາຍໃນ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"ຈະເຕັມພາຍໃນ <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ສາກເຕັມແລ້ວ"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ສາກເຕັມແລ້ວ"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ຢຸດການສາກຊົ່ວຄາວ"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ກຳລັງສາກ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ກຳລັງສາກໄວ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ຄວບຄຸມໂດຍຜູ້ເບິ່ງແຍງ"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ຄວບຄຸມໂດຍການຕັ້ງຄ່າທີ່ຈຳກັດໄວ້"</string>
     <string name="disabled" msgid="8017887509554714950">"ປິດການນຳໃຊ້"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ສັນຍານນຶ່ງຂີດ."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ສັນຍານສອງຂີດ."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ສັນຍານສາມຂີດ."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ສັນຍານໂທລະສັບ 4 ຂີດ."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ສັນຍານເຕັມ."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ບໍ່ມີຂໍ້ມູນ."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ຂໍ້ມູນນຶ່ງຂີດ."</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 10ef2c4..94b8173 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Prisijungta (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), (telefono ar medijos nėra), akumuliatoriaus įkrovos lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktyvus, akumuliatoriaus įkrova: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktyvi, KAIRĖ: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, DEŠINĖ: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumuliatoriaus įkrova: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumuliatorius: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"KAIRĖ: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, DEŠINĖ: akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kairė: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Dešinė: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktyvus"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Išsaugota"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktyvus, tik kairysis"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktyvus, tik dešinysis"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktyvus, kairysis ir dešinysis"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktyvus (tik medija)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Palaikomas garso įrašų bendrinimas"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktyvus (tik medija), tik kairė"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktyvus (tik medija), tik dešinė"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktyvus (tik medija), kairė ir dešinė"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medijos garsas"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefono skambučiai"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failo perkėlimas"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <xliff:g id="TIME">%2$s</xliff:g>, kol bus visiškai įkrauta"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas optimizuotas"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkraunama"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – bus visiškai įkrauta <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – bus visiškai įkrauta <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Bus visiškai įkrauta <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Bus visiškai įkrauta <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Įkrauta"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Visiškai įkrautas"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Įkrovimas pristabdytas"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Įkraunama"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Spartusis įkrovimas"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Valdo administratorius"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Valdoma pagal apribotą nustatymą"</string>
     <string name="disabled" msgid="8017887509554714950">"Neleidžiama"</string>
@@ -555,7 +567,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signalai ir priminimai"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Leisti nustatyti signalus ir priminimus"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signalai ir priminimai"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leisti šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leiskite šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tvarkaraštis, signalas, priminimas, laikrodis"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Įjungti"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Netrukdymo režimo įjungimas"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Viena telefono juosta."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dvi telefono juostos."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Trys telefono juostos."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Keturios juosto telefone."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefono signalas stiprus."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Duomenų nėra."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Viena duomenų juosta."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index c52e9dd..ff1f3f3 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Savienojums izveidots <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (nav tālrunis), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Savienojums izveidots (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>) (nav multivide), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Savienojums izveidots (nav tālrunis vai multivide) (<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>), akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktīvs, akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktīvs, L: akumulatora uzlādes līmenis <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: akumulatora uzlādes līmenis <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: akumulatora uzlādes līmenis <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: akumulatora uzlādes līmenis <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kreisā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Labā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktīvs"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saglabāta"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ierīce aktīva, tikai kreisā auss"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ierīce aktīva, tikai labā auss"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ierīces aktīvas, kreisā un labā auss"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktīvs (tikai multividei)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Atbalsta audio kopīgošanu"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktīvs (tikai multivide), tikai kreisās puses aparāts"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktīvs (tikai multivide), tikai labās puses aparāts"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktīvs (tikai multivide), kreisās un labās puses aparāts"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Multivides audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Tālruņa zvani"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failu pārsūtīšana"</string>
@@ -162,7 +168,7 @@
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Izmantot ievadei"</string>
     <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Izmantot dzirdes aparātiem"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Izmantot LE_AUDIO profilam"</string>
-    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Izveidot pāri"</string>
+    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Savienot pārī"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SAVIENOT PĀRĪ"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Atcelt"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Veicot savienošanu pārī, šī ierīce savienojuma laikā varēs piekļūt jūsu kontaktpersonām un zvanu vēsturei."</string>
@@ -487,7 +493,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Ņemot vērā lietojumu, darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Iespējams, akumulators izlādēsies līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Atlicis: mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Atlicis: mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde optimizēta"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> — notiek uzlāde"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATUS">%2$s</xliff:g>. Tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> — tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Tiks pilnībā uzlādēts līdz plkst. <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string>
@@ -509,12 +519,14 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Uzlādēts"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Pilnībā uzlādēts"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Uzlāde apturēta"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Notiek uzlāde"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Ātrā uzlāde"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolē administrators"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolē ierobežots iestatījums"</string>
     <string name="disabled" msgid="8017887509554714950">"Atspējots"</string>
     <string name="external_source_trusted" msgid="1146522036773132905">"Atļauts"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"Nav atļauts"</string>
-    <string name="install_other_apps" msgid="3232595082023199454">"Instalēt nez. lietotnes"</string>
+    <string name="install_other_apps" msgid="3232595082023199454">"Nezināmu lietotņu instalēšana"</string>
     <string name="home" msgid="973834627243661438">"Iestatījumu sākumekrāns"</string>
   <string-array name="battery_labels">
     <item msgid="7878690469765357158">"0%"</item>
@@ -541,7 +553,7 @@
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS reģistrācijas statuss"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"Reģistrēts"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Nav reģistrēts"</string>
-    <string name="status_unavailable" msgid="5279036186589861608">"Nepieejams"</string>
+    <string name="status_unavailable" msgid="5279036186589861608">"Nepieejama"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"MAC ir atlasīts nejaušā secībā"</string>
     <string name="wifi_tether_connected_summary" msgid="5100712926640492336">"{count,plural, =1{Pievienota 1 ierīce.}zero{Pievienotas # ierīces.}one{Pievienota # ierīce.}other{Pievienotas # ierīces.}}"</string>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Vairāk laika."</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Tālrunis: viena josla."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Tālrunis: divas joslas."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tālrunis: trīs joslas."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Tālrunis (četras joslas)."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Pilna piekļuve tālruņa signālam"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nav datu."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dati: viena josla"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 554b92e..c5b4a5e 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Поврзан со <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без телефон и аудиовизуелни содржини), ниво на батеријата <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Активен, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активен, Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија"</string>
-    <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
+    <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Одлево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Оддесно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активен"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Зачувано"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само лево"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, само десно"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, лево и десно"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (само аудиовизуелни содржини)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддржува споделување аудио"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (само аудиовизуелни содржини), само лево"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (само аудиовизуелни содржини), само десно"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (само аудиовизуелни содржини), лево и десно"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Звук на аудио/видео"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонски повици"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос на датотека"</string>
@@ -201,7 +207,7 @@
     <string name="running_process_item_user_label" msgid="3988506293099805796">"Корисник: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"Поставени се некои стандардни вредности"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"Нема поставено стандардни вредности"</string>
-    <string name="tts_settings" msgid="8130616705989351312">"Поставки на текст-во-говор"</string>
+    <string name="tts_settings" msgid="8130616705989351312">"Поставки за „Од текст во говор“"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"Претворање текст во говор"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"Брзина на говорот"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"Брзина со која се кажува текстот"</string>
@@ -474,9 +480,9 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција на боите"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Корекцијата на боите може да биде корисна кога сакате:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;да ги гледате боите попрецизно&lt;/li&gt; &lt;li&gt;&amp;nbsp;да ги отстраните боите за полесно да се концентрирате&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
-    <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - полнењето е паузирано за да се заштити батеријата"</string>
-    <string name="power_incompatible_charging_settings_home_page" msgid="1322050766135126880">"<xliff:g id="LEVEL">%1$s</xliff:g> - Проверете го додатокот за полнење"</string>
+    <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
+    <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – полнењето е паузирано за да се заштити батеријата"</string>
+    <string name="power_incompatible_charging_settings_home_page" msgid="1322050766135126880">"<xliff:g id="LEVEL">%1$s</xliff:g> – Проверете го додатокот за полнење"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="1076561255466053220">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> според вашето користење"</string>
@@ -496,8 +502,12 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string>
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string>
-    <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е оптимизирано"</string>
-    <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ се полни"</string>
+    <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – полнењето е оптимизирано"</string>
+    <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – се полни"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Ќе се наполни целосно до <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ќе се наполни целосно до <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Ќе се наполни целосно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Ќе се наполни целосно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string>
@@ -509,12 +519,14 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Полна"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Целосно полна"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Полнењето е паузирано"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Се полни"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Се полни брзо"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролирано од администраторот"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Контролирано со ограничени поставки"</string>
     <string name="disabled" msgid="8017887509554714950">"Оневозможено"</string>
     <string name="external_source_trusted" msgid="1146522036773132905">"Со дозвола"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"Без дозвола"</string>
-    <string name="install_other_apps" msgid="3232595082023199454">"Непознати апликации"</string>
+    <string name="install_other_apps" msgid="3232595082023199454">"Инсталирање непознати апликации"</string>
     <string name="home" msgid="973834627243661438">"Почетна страница за поставки"</string>
   <string-array name="battery_labels">
     <item msgid="7878690469765357158">"0 %"</item>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон една цртичка.."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон две цртички."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон три цртички."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Телефон со четири цртички."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигналот за телефон е исполнет."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Нема податоци."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Податоци една цртичка."</string>
@@ -709,7 +722,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Стандардно"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Вклучување на екранот"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Дозволи вклучување на екранот"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Дозволува одредена апликација да го вклучува екранот. Ако е дозволено, апликацијата може да го вклучува екранот во секое време без ваша намера."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Дозволете одредена апликација да го вклучува екранот. Ако е дозволено, апликацијата ќе може да го вклучува екранот во секое време без ваша намера."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Да се прекине емитувањето на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ако емитувате на <xliff:g id="SWITCHAPP">%1$s</xliff:g> или го промените излезот, тековното емитување ќе запре"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Емитување на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 61bcc44..0ba9122 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"കണ‌ക്റ്റ് ചെയ്‌തു (ഫോൺ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"കണക്റ്റ് ചെയ്‌തു (മീഡിയ ഇല്ല), ബാറ്ററി <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"കണ‌ക്റ്റ് ചെയ്‌തു (ഫോണോ മീഡിയയോ ഇല്ല), ബാറ്ററി നില <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"സജീവം, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"സജീവം, ഇടത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ബാറ്ററി ചാർജ് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ആണ്"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"ഇടത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ഇടത് വശത്ത് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"വലത് വശത്ത് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"സജീവം"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"സംരക്ഷിച്ചു"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"സജീവമാണ്, ഇടത്തേത് മാത്രം"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"സജീവമാണ്, വലത്തേത് മാത്രം"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"സജീവമാണ്, ഇടത്തേതും വലത്തേതും"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"സജീവം (മീഡിയ മാത്രം)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്ത് മാത്രം"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"സജീവം (മീഡിയ മാത്രം), വലതുവശത്ത് മാത്രം"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"സജീവം (മീഡിയ മാത്രം), ഇടതുവശത്തെയും വലതുവശത്തെയും"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"മീഡിയ ഓഡിയോ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ഫോണ്‍‌ കോളുകൾ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ഫയൽ കൈമാറൽ"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമാകാൻ <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ ചാർജ് ചെയ്യുന്നു"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>-നകം പൂർണ്ണമാകും"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-നകം പൂർണ്ണമായി ചാർജ് ചെയ്യും"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>-നകം പൂർണ്ണമായി ചാർജ് ചെയ്യും"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>-നകം പൂർണ്ണമാകും"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ചാർജായി"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"പൂർണ്ണമായി ചാർജ് ചെയ്തു"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ചാർജിംഗ് ഹോൾഡിലാണ്"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ചാർജ് ചെയ്യുന്നു"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"അതിവേഗ ചാർജിംഗ്"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"അഡ്‌മിൻ നിയന്ത്രിക്കുന്നത്"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"നിയന്ത്രിത ക്രമീകരണം ഉപയോഗിച്ച് നിയന്ത്രിക്കുന്നത്"</string>
     <string name="disabled" msgid="8017887509554714950">"പ്രവർത്തനരഹിതമാക്കി"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ഫോണിൽ ഒരു ബാർ."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ഫോണിൽ രണ്ട് ബാർ."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ഫോണിൽ മൂന്ന് ബാർ."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ഫോണിൽ നാല് ബാറുകൾ."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ഫോൺ സിഗ്‌നൽ പൂർണ്ണമാണ്."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ഡാറ്റാ സിഗ്‌നൽ ഒന്നുമില്ല."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ഡാറ്റ ഒരു ബാർ."</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index c2c22e6..c431857 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Холбогдсон (утас байхгүй), батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Холбогдсон (медиа байхгүй), батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Холбогдсон (утас эсвэл медиа байхгүй), батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Идэвхтэй, батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Идэвхтэй, Зүүн: Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Баруун: Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Зүүн: Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Баруун: Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Зүүн тал <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Баруун тал <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Идэвхтэй"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Хадгалсан"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Идэвхтэй, зөвхөн зүүн тал"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Идэвхтэй, зөвхөн баруун тал"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Идэвхтэй, зүүн болон баруун тал"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Идэвхтэй (зөвхөн медиа)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Аудио хуваалцахыг дэмждэг"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Идэвхтэй (зөвхөн медиа), зөвхөн зүүн"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Идэвхтэй (зөвхөн медиа), зөвхөн баруун"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Идэвхтэй (зөвхөн медиа), зүүн болон баруун"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Медиа аудио"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Утасны дуудлага"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл дамжуулалт"</string>
@@ -472,7 +478,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулга"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Өнгө тохируулга нь таныг дараахыг хийхийг хүсэх үед хэрэгтэй байж болно:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Өнгөнүүдийг илүү нарийвчилж харах&lt;/li&gt; &lt;li&gt;&amp;nbsp;Төвлөрөхийн тулд өнгөнүүдийг хасах&lt;/li&gt; &lt;/ol&gt;"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Өнгө засах нь таныг дараахыг хийхийг хүсэх үед хэрэгтэй байж болно:&lt;br/&gt; &lt;ol&gt; &lt;li&gt; Өнгөнүүдийг илүү нарийвчилж харах&lt;/li&gt; &lt;li&gt; Төвлөрөхийн тулд өнгөнүүдийг хасах&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейг хамгаалахын тулд цэнэглэхийг хүлээлгэсэн"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - дүүрэх хүртэл <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэх явцыг оновчилсон"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэж байна"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> гэхэд дүүрнэ"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> гэхэд бүрэн цэнэглэгдэнэ"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> гэхэд бүрэн цэнэглэгдэнэ"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> гэхэд дүүрнэ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Цэнэглэсэн"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Бүрэн цэнэглэсэн"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Цэнэглэхийг хүлээлгэд оруулсан"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Цэнэглэж байна"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Шуурхай цэнэглэх"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Админ удирдсан"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Хязгаарлагдсан тохиргоогоор хянадаг"</string>
     <string name="disabled" msgid="8017887509554714950">"Идэвхгүйжүүлсэн"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Утас нэг баганатай."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Утас хоёр баганатай."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Утас гурван баганатай."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Утасны дөрвөн заалт."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Утасны дохио дүүрэн."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Дата байхгүй."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Дата нэг баганатай."</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 1e56118..a916a1c 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"कनेक्ट केले (फोन नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"कनेक्ट केले (मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"कनेक्ट केले (फोन किंवा मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"अ‍ॅक्टिव्ह, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"अ‍ॅक्टिव्ह, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"डावा <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"उजवा <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"अ‍ॅक्टिव्ह"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव्ह केली आहेत"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"फक्त डावे अ‍ॅक्टिव्ह आहे"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"फक्त उजवे अ‍ॅक्टिव्ह आहे"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"डावे आणि उजवे अ‍ॅक्टिव्ह आहे"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"अ‍ॅक्टिव्ह आहे (फक्त मीडिया)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ऑडिओ शेअरिंगला सपोर्ट करते"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"अ‍ॅक्टिव्ह आहे (फक्त मीडिया), फक्त डावे"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"अ‍ॅक्टिव्ह आहे (फक्त मीडिया), फक्त उजवे"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"अ‍ॅक्टिव्ह आहे (फक्त मीडिया), डावे आणि उजवे"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मीडिया ऑडिओ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"फोन कॉल"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानांतरण"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग ऑप्टिमाइझ केले"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ चार्ज होत आहे"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> पर्यंत पूर्ण होईल"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्णपणे चार्ज होईल"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्णपणे चार्ज होईल"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण होईल"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज झाली"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"पूर्ण चार्ज झाली"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"चार्जिंग थांबवले आहे"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"चार्ज होत आहे"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"फास्ट चार्जिंग"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"प्रशासकाने नियंत्रित केलेले"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"प्रतिबंधित केलेल्या सेटिंग द्वारे नियंत्रित"</string>
     <string name="disabled" msgid="8017887509554714950">"अक्षम"</string>
@@ -537,7 +549,7 @@
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिस्टम भाषा वापरा"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> साठी सेटिंग्ज उघडण्यात अयशस्वी"</string>
     <string name="ime_security_warning" msgid="6547562217880551450">"ही इनपुट पद्धत पासवर्ड आणि क्रेडिट कार्ड नंबर यासह, तुम्ही टाइप करता तो सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. ही <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ॲपवरून येते. ही इनपुट पद्धत वापरायची?"</string>
-    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"टीप: रीबूट केल्यानंतर, तुम्ही तुमचा फोन अनलॉक करे पर्यंत हे अ‍ॅप सुरू होऊ शकत नाही"</string>
+    <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"टीप: रीबूट केल्यानंतर, तुम्ही तुमचा फोन अनलॉक करेपर्यंत हे अ‍ॅप सुरू होऊ शकत नाही"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS नोंदणी स्थिती"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"नोंदवलेले"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"नोंदवलेले नाही"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फोन एक बार."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फोन दोन बार."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तीन बार."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"फोनचे चार बार."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फोन सिग्नल पूर्ण."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"कोणताही डेटा नाही."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटा एक बार."</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a93c459..f86206c 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Disambungkan (tiada telefon), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Disambungkan (tiada media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Disambungkan (tiada telefon atau media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktif, bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktif, Ki: bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Ka: bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Ki: bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Ka: bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kiri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Kanan <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, kiri sahaja"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, kanan sahaja"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktif (media sahaja)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Menyokong perkongsian audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktif (media sahaja), kiri sahaja"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktif (media sahaja), kanan sahaja"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktif (media sahaja), kiri dan kanan"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio media"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Panggilan telefon"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Pemindahan fail"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sebelum penuh"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dioptimumkan"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengecas"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Penuh pada <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Dicas sepenuhnya pada <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Dicas sepenuhnya pada <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Penuh pada <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas pantas"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Sudah dicas"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Dicas Penuh"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Pengecasan ditunda"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Pengecasan"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Pengecasan pantas"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Dikawal oleh pentadbir"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Dikawal oleh Tetapan Terhad"</string>
     <string name="disabled" msgid="8017887509554714950">"Dilumpuhkan"</string>
@@ -555,7 +567,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Penggera dan peringatan"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Benarkan penetapan penggera dan peringatan"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Penggera &amp; peringatan"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Hal ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadual, penggera, peringatan, jam"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Hidupkan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Hidupkan Jangan Ganggu"</string>
@@ -638,7 +650,7 @@
     <string name="add_user_failed" msgid="4809887794313944872">"Gagal membuat pengguna baharu"</string>
     <string name="add_guest_failed" msgid="8074548434469843443">"Gagal membuat tetamu baharu"</string>
     <string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
-    <string name="edit_user_info_message" msgid="6677556031419002895">"Nama dan gambar yang anda pilih akan dipaparkan kepada sesiapa sahaja yang menggunakan peranti ini."</string>
+    <string name="edit_user_info_message" msgid="6677556031419002895">"Nama dan gambar yang anda pilih dapat dilihat oleh sesiapa sahaja yang menggunakan peranti ini."</string>
     <string name="user_add_user" msgid="7876449291500212468">"Tambah pengguna"</string>
     <string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon satu bar."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon dua bar."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon tiga bar."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon empat bar."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Isyarat telefon penuh."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Tiada data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data satu bar."</string>
@@ -708,7 +721,7 @@
     <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Pilih susun atur papan kekunci"</string>
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Lalai"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Hidupkan skrin"</string>
-    <string name="allow_turn_screen_on" msgid="6194845766392742639">"Benarkan menghidupkan skrin"</string>
+    <string name="allow_turn_screen_on" msgid="6194845766392742639">"Benarkan apl menghidupkan skrin"</string>
     <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Benarkan apl menghidupkan skrin. Jika dibenarkan, apl boleh menghidupkan skrin pada bila-bila masa tanpa niat eksplisit anda."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jika anda siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau tukarkan output, siaran semasa anda akan berhenti"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 7880c37..2dde99f 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ချိတ်ဆက်ပြီးပြီ (ဖုန်းမရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ချိတ်ဆက်ပြီးပြီ (မီဒီယာ မရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ချိတ်ဆက်ပြီးပြီ (ဖုန်း (သို့) မီဒီယာ မရှိပါ)၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ဖွင့်ထားသည်၊ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"သုံးနေသည်၊ L− ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R− ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L− ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R− ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ဘယ် <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ညာ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ဖွင့်ထားသည်"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"သိမ်းထားသည်များ"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ဖွင့်ထားသည်၊ ဘယ်သီးသန့်"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ဖွင့်ထားသည်၊ ညာသီးသန့်"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ဖွင့်ထားသည်၊ ဘယ်နှင့် ညာ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"သုံးနေသည် (မီဒီယာသီးသန့်)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်သီးသန့်"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ညာသီးသန့်"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"သုံးနေသည် (မီဒီယာသီးသန့်)၊ ဘယ်နှင့် ညာ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"မီဒီယာ အသံ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ဖုန်းခေါ်ဆိုမှုများ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ဖိုင်လွဲပြောင်းခြင်း"</string>
@@ -272,7 +278,7 @@
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ချိတ်ဆက်ခြင်း မအောင်မြင်ပါ"</string>
     <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> သည် မှန်ကန်သည့် ကွန်ရက်သို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ"</string>
     <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"စက်ပစ္စည်းနှင့် အတူတွဲပါ"</string>
-    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi အတူတွဲချိတ်ရန် ကုဒ်"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi တွဲချိတ်ကုဒ်"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"တွဲချိတ်ခြင်း မအောင်မြင်ပါ"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"စက်ပစ္စည်းသည် ကွန်ရက်တစ်ခုတည်းသို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ။"</string>
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR ကုဒ် စကင်ဖတ်ခြင်းဖြင့် Wi-Fi ပေါ်တွင် စက်ပစ္စည်းကို အတူတွဲပါ"</string>
@@ -471,7 +477,7 @@
     <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteranomaly (အနီ-အစိမ်း)"</string>
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (အနီ-အစိမ်း)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (အပြာ-အဝါ)"</string>
-    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင်ပြင်ခြင်း"</string>
+    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင် အမှန်ပြင်ခြင်း"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"အရောင် အမှန်ပြင်ခြင်းသည် အောက်ပါတို့အတွက် အသုံးဝင်နိုင်သည်-&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;အရောင်များကို ပိုမိုမှန်ကန်စွာ ကြည့်ရှုခြင်း&lt;/li&gt; &lt;li&gt;&amp;nbsp;အာရုံစိုက်နိုင်ရန် အရောင်များ ဖယ်ရှားခြင်း&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> လိုသည်"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းနေသည်"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> တွင် အားပြည့်မည်"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> တွင် အားပြည့်မည်"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> တွင် အားပြည့်မည်"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> တွင် အားပြည့်မည်"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"အားသွင်းပြီးပါပြီ"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"အားအပြည့်သွင်းထားသည်"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"အားသွင်းခြင်းကို ခဏရပ်ထားသည်"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"အားသွင်းနေသည်"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"အမြန်အားသွင်းခြင်း"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"စီမံခန့်ခွဲသူမှ ထိန်းချုပ်ပါသည်"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ကန့်သတ်ဆက်တင်ဖြင့် ထိန်းချုပ်ထားသည်"</string>
     <string name="disabled" msgid="8017887509554714950">"ပိတ်ထားပြီး"</string>
@@ -555,7 +567,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>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ဖုန်းလိုင်းတစ်ဘား။"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ဖုန်းလိုင်းနှစ်ဘား။"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ဖုန်းလိုင်းသုံးဘား။"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ဖုန်း လေးဘားရှိသည်။"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ဖုန်းလိုင်းအပြည့်။"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ဒေတာမရှိပါ။"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ဒေတာတစ်ဘား။"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0eacc5e..d2021ba 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Koblet til (ingen telefon), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Koblet til (ingen medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Koblet til (ingen telefon eller medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiv, V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Venstre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Høyre: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Lagret"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bare venstre"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bare høyre"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og høyre"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (bare medieinnhold)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Støtter lyddeling"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (bare medieinnhold), bare venstre"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (bare medieinnhold), bare høyre"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (bare medieinnhold), høyre og venstre"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medielyd"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonsamtaler"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverføring"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladingen er optimalisert"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – lader"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Fulladet innen <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet innen <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fulladet innen <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Fulladet innen <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Ladet"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fulladet"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ladingen er satt på vent"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Lading"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Hurtiglading"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrollert av administratoren"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrollert av en begrenset innstilling"</string>
     <string name="disabled" msgid="8017887509554714950">"Slått av"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon – én stolpe."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon – to stolper."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon – tre stolper."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Fire streker for telefon."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignal er fullt."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ingen data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data – én stolpe"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 447cd80..d2c3729 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -55,7 +55,7 @@
   </string-array>
   <string-array name="hdcp_checking_summaries">
     <item msgid="4045840870658484038">"HDCP परीक्षण कहिल्यै प्रयोग नगर्नुहोस्"</item>
-    <item msgid="8254225038262324761">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गरियोस्"</item>
+    <item msgid="8254225038262324761">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item>
     <item msgid="6421717003037072581">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_entries">
@@ -97,7 +97,7 @@
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="2494959071796102843">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
     <item msgid="720249083677397051">"AAC"</item>
     <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
@@ -107,7 +107,7 @@
     <item msgid="506175145534048710">"Opus"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="8868109554557331312">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="9024885861221697796">"SBC"</item>
     <item msgid="4688890470703790013">"AAC"</item>
     <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
@@ -117,38 +117,38 @@
     <item msgid="7940970833006181407">"Opus"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
-    <item msgid="926809261293414607">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="926809261293414607">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="8003118270854840095">"४४.१ kHz"</item>
     <item msgid="3208896645474529394">"४८.० kHz"</item>
     <item msgid="8420261949134022577">"८८.२ kHz"</item>
     <item msgid="8887519571067543785">"९६.० kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
-    <item msgid="2284090879080331090">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="2284090879080331090">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="1872276250541651186">"४४.१ kHz"</item>
     <item msgid="8736780630001704004">"४८.० kHz"</item>
     <item msgid="7698585706868856888">"८८.२ kHz"</item>
     <item msgid="8946330945963372966">"९६.० kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
-    <item msgid="2574107108483219051">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="2574107108483219051">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="4671992321419011165">"१६ बिट/नमूना"</item>
     <item msgid="1933898806184763940">"२४ बिट/नमूना"</item>
     <item msgid="1212577207279552119">"३२ बिट/नमूना"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
-    <item msgid="9196208128729063711">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="9196208128729063711">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="1084497364516370912">"१६ बिट/नमूना"</item>
     <item msgid="2077889391457961734">"२४ बिट/नमूना"</item>
     <item msgid="3836844909491316925">"३२ बिट/नमूना"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
-    <item msgid="3014194562841654656">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="3014194562841654656">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="5982952342181788248">"मोनो"</item>
     <item msgid="927546067692441494">"स्टेरियो"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
-    <item msgid="1997302811102880485">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
+    <item msgid="1997302811102880485">"सिस्टमको छनौट प्रयोग गर्नुहोस् (डिफल्ट)"</item>
     <item msgid="8005696114958453588">"मोनो"</item>
     <item msgid="1333279807604675720">"स्टेरियो"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index e2236cc..d01fc16 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -94,53 +94,59 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"जडान गरियो (फोनबाहेेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"जडान गरियो (मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"जडान गरियो (फोन वा मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"सक्रिय, ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"सक्रिय, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ब्याट्री, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ब्याट्री, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"बायाँ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"दायाँ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"सक्रिय"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"सेभ गरिएको"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"बायाँ मात्र अन छ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सक्रिय, दायाँ मात्र"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"सक्रिय, बायाँ र दायाँ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"सक्रिय छ (मिडिया मात्र)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"अडियो सेयर गर्न मिल्छ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"सक्रिय छ (मिडिया मात्र), बायाँ मात्र"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"सक्रिय छ (मिडिया मात्र), दायाँ मात्र"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"सक्रिय छ (मिडिया मात्र), बायाँ र दायाँ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मिडिया अडियो"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"फोन कलहरू"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानान्तरण"</string>
-    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट उपकरण"</string>
+    <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट डिभाइस"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"इन्टरनेट एक्सेस"</string>
-    <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"कन्ट्याक्ट र कल हिस्ट्री एक्सेस गर्ने अनुमति दिइयोस्"</string>
+    <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"कन्ट्याक्ट र कल हिस्ट्री एक्सेस गर्ने अनुमति दिनुहोस्"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"यो जानकारीको प्रयोग कल आएको जानकारी दिने लगायतका कुराका लागि प्रयोग गरिने छ"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इन्टरनेट जडान साझेदारी गर्दै"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"टेक्स्ट म्यासेजहरू"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM एक्सेस"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD अडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD अडियो"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"श्रवण यन्त्रहरू"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"हियरिङ डिभाइसहरू"</string>
     <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE अडियो"</string>
     <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"श्रवण यन्त्रहरूमा जडान गरियो"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE अडियोमा कनेक्ट गरिएको छ"</string>
@@ -176,7 +182,7 @@
     <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"छवि सम्बन्धी"</string>
     <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"हेडफोन"</string>
     <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"इनपुट सम्बन्धी बाह्य यन्त्र"</string>
-    <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"श्रवण यन्त्रहरू"</string>
+    <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"हियरिङ डिभाइसहरू"</string>
     <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ब्लुटुथ"</string>
     <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi बन्द।"</string>
     <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi जडान विच्छेद भयो।"</string>
@@ -256,14 +262,14 @@
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB कनेक्ट गरिएको बेलामा डिबग मोड"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB डिबग गर्ने अधिकार फिर्ता लिइयोस्"</string>
     <string name="enable_adb_wireless" msgid="6973226350963971018">"वायरलेस डिबगिङ"</string>
-    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi मा कनेक्ट हुँदा डिबग मोड अन गरियोस्"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi मा कनेक्ट हुँदा डिबग मोड अन गर्नुहोस्"</string>
     <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 कोड प्रयोग गरी डिभाइस कनेक्ट गर्नुहोस्"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR कोड स्क्यानर प्रयोग गरी नयाँ डिभाइसहरूको जोडा बनाउनुहोस्"</string>
-    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"पेयरिङ कोड प्रयोग गरी कनेक्ट गरियोस्"</string>
-    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"छ अङ्कको कोड प्रयोग गरी नयाँ डिभाइसहरू कनेक्ट गरियोस्"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"पेयरिङ कोड प्रयोग गरी कनेक्ट गर्नुहोस्"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"छ अङ्कको कोड प्रयोग गरी नयाँ डिभाइसहरू कनेक्ट गर्नुहोस्"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"कनेक्ट गरिएका डिभाइस"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"हाल जोडिएको छ"</string>
     <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"डिभाइसको विवरण"</string>
@@ -284,7 +290,7 @@
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"कृपया कुनै Wi-Fi मा कनेक्ट गर्नुहोस्"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"बग रिपोर्टको सर्टकट"</string>
-    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट प्राप्त गर्न पावर मेनुमा बटन देखाइयोस्"</string>
+    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट प्राप्त गर्न पावर मेनुमा बटन देखाउनुहोस्"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"डिस्प्ले अफ नहोस्"</string>
     <string name="keep_screen_on_summary" msgid="1510731514101925829">"चार्ज गर्दा स्क्रिन कहिल्यै अफ हुँदैन।"</string>
     <string name="bt_hci_snoop_log" msgid="7291287955649081448">"ब्लुटुथ HCI snoop लग अन गर्नुहोस्"</string>
@@ -298,14 +304,14 @@
     <string name="mock_location_app_set" msgid="4706722469342913843">"नमूना स्थान एप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="debug_networking_category" msgid="6829757985772659599">"नेटवर्किङ"</string>
     <string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिस्प्ले प्रयोग गर्ने वा नगर्ने"</string>
-    <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi-Fi भर्बोज लग अन गरियोस्"</string>
+    <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi-Fi भर्बोज लग अन गर्नुहोस्"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi स्क्यान थ्रोटलिङ"</string>
     <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi-Fi नन-पर्सिस्टेन्ट MAC र्‍यान्डमाइजेसन"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"मोबाइल डेटा सधैँ अन होस्"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string>
-    <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नामकरण नगरिएका ब्लुटुथ डिभाइस देखाइयोस्"</string>
-    <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"निरपेक्ष भोल्युम अफ गरियोस्"</string>
-    <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche अन गरियोस्"</string>
+    <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नामकरण नगरिएका ब्लुटुथ डिभाइस देखाउनुहोस्"</string>
+    <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"निरपेक्ष भोल्युम अफ गर्नुहोस्"</string>
+    <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche अन गर्नुहोस्"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लुटुथको AVRCP संस्करण"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लुटुथको AVRCP संस्करण चयन गर्नुहोस्"</string>
     <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ब्लुटुथको MAP संस्करण"</string>
@@ -329,8 +335,8 @@
     <string name="private_dns_mode_provider" msgid="3619040641762557028">"निजी DNS प्रदायकको होस्टनेम"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"DNS प्रदायकको होस्टनेम हाल्नुहोस्"</string>
     <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"जडान गर्न सकिएन"</string>
-    <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्लेसम्बन्धी विकल्प देखाइयोस्"</string>
-    <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi-Fi लगिङ लेभल बढाइयोस्, Wi-Fi पि‍करमा प्रति SSID RSSI देखाइयोस्"</string>
+    <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्लेसम्बन्धी विकल्प देखाउनुहोस्"</string>
+    <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi-Fi लगिङ लेभल बढाउनुहोस्, Wi-Fi पि‍करमा प्रति SSID RSSI देखाउनुहोस्"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"यसले ब्याट्रीको खपत कम गर्छ र नेटवर्कको कार्यसम्पादनमा सुधार गर्दछ"</string>
     <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"यो मोड अन गरिएका बेला यो डिभाइस म्याक एड्रेस बदल्ने सुविधा अन गरिएको नेटवर्कमा जति पटक कनेक्ट हुन्छ त्यति नै पटक यस डिभाइसको म्याक एड्रेस पनि परिवर्तन हुन सक्छ।"</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"सशुल्क वाइफाइ"</string>
@@ -339,15 +345,15 @@
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"लगरको निरन्तर भण्डारणलाई खाली गर्ने हो?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"हामी अब निरन्तर लगर मार्फत अनुगमन गरिरहेका छैनौँ, त्यसैले हामीले तपाईँको डिभाइसमा रहेको लगर सम्बन्धी डेटा मेटाउन आवश्यक छ।"</string>
-    <string name="select_logpersist_title" msgid="447071974007104196">"लगरसम्बन्धी डेटा निरन्तर डिभाइसमा भण्डारण गरियोस्"</string>
+    <string name="select_logpersist_title" msgid="447071974007104196">"लगरसम्बन्धी डेटा निरन्तर डिभाइसमा भण्डारण गर्नुहोस्"</string>
     <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"डिभाइसमा निरन्तर भण्डारण गरिने लग सम्बन्धी बफरहरूलाई चयन गर्नुहोस्"</string>
     <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB विन्यास चयन गर्नुहोस्"</string>
     <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB विन्यास चयन गर्नुहोस्"</string>
     <string name="allow_mock_location" msgid="2102650981552527884">"नक्कली स्थानहरूलाई अनुमति दिनुहोस्"</string>
     <string name="allow_mock_location_summary" msgid="179780881081354579">"नक्कली स्थानहरूलाई अनुमति दिनुहोस्"</string>
-    <string name="debug_view_attributes" msgid="3539609843984208216">"भ्युको एट्रिब्युट हेर्ने सुविधा अन गरियोस्"</string>
+    <string name="debug_view_attributes" msgid="3539609843984208216">"भ्युको एट्रिब्युट हेर्ने सुविधा अन गर्नुहोस्"</string>
     <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Wi-Fi अन हुँदा पनि मोबाइल डेटा सधैँ अन होस् (द्रुत रूपमा नेटवर्क बदल्न)।"</string>
-    <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध हुँदा टेदरिङ हार्डवेयर एक्सलरेसन प्रयोग गरियोस्"</string>
+    <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध हुँदा टेदरिङ हार्डवेयर एक्सलरेसन प्रयोग गर्नुहोस्"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB डिबग गर्न लागि अनुमति दिने हो?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"युएसबी डिबगिङ विकास प्रयोजनका लागि मात्र निर्मित हुन्छ। यसलाई तपाईँको कम्प्युटर र तपाईँको उपकरणका बीच डेटा कपी गर्न, बिना सूचना तपाईँको उपकरणमा एपहरू इन्स्टल गर्न र लग डेटा पढ्नका लागि प्रयोग गर्नुहोस्।"</string>
     <string name="adbwifi_warning_title" msgid="727104571653031865">"वायरलेस डिबगिङ सेवा सक्षम पार्ने हो?"</string>
@@ -355,11 +361,11 @@
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"तपाईं पहिले नै अधिकृत गर्नुभएका सबै कम्प्यूटरबाट USB डिबग गर्नको लागि पहुँच रद्द गर्ने हो?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिङहरू अनुमति दिने हो?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र एपहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string>
-    <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB मा एपको पुष्टि गरियोस्"</string>
-    <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक व्यवहार पत्ता लगाउन ADB/ADT बाट इन्स्टल गरिएका एपको जाँच गरियोस्"</string>
+    <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB मा एपको पुष्टि गर्नुहोस्"</string>
+    <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक व्यवहार पत्ता लगाउन ADB/ADT बाट इन्स्टल गरिएका एपको जाँच गर्नुहोस्"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"नामकरण नगरिएका ब्लुटुथ डिभाइस (म्याक एड्रेस भएका मात्र) देखाइने छ"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"यसले रिमोट डिभाइसमा अत्यधिक ठूलो वा अनियन्त्रित भोल्युम बज्नेको जस्ता अवस्थामा ब्लुटुथको निरपेक्ष भोल्युम अफ गर्छ।"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लुटुथ Gabeldorsche सुविधाको स्ट्याक अन गरियोस्।"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लुटुथ Gabeldorsche सुविधाको स्ट्याक अन गर्नुहोस्।"</string>
     <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"यसले परिष्कृत जडानको सुविधा सक्षम पार्छ।"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"स्थानीय सेल पहुँच प्रदान गर्ने टर्मिनल एप सक्षम गर्नुहोस्"</string>
@@ -378,60 +384,60 @@
     <string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयरले बढाएको रेन्डरिङ"</string>
     <string name="media_category" msgid="8122076702526144053">"मिडिया"</string>
     <string name="debug_monitoring_category" msgid="1597387133765424994">"अनुगमन गरिँदै छ"</string>
-    <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड अन गरियोस्"</string>
-    <string name="strict_mode_summary" msgid="1838248687233554654">"एपले मुख्य थ्रेडमा लामा गतिविधि गर्दा स्क्रिन फ्ल्यास गरियोस्"</string>
+    <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड अन गर्नुहोस्"</string>
+    <string name="strict_mode_summary" msgid="1838248687233554654">"एपले मुख्य थ्रेडमा लामा गतिविधि गर्दा स्क्रिन फ्ल्यास गर्नुहोस्"</string>
     <string name="pointer_location" msgid="7516929526199520173">"पोइन्टरको स्थान"</string>
     <string name="pointer_location_summary" msgid="957120116989798464">"स्क्रिन ओभरलेले हालको टच डेटा देखाउँदै छ"</string>
-    <string name="show_touches" msgid="8437666942161289025">"ट्याप देखाइयोस्"</string>
-    <string name="show_touches_summary" msgid="3692861665994502193">"ट्यापका लागि भिजुअल प्रतिक्रिया देखाइयोस्"</string>
+    <string name="show_touches" msgid="8437666942161289025">"ट्याप देखाउनुहोस्"</string>
+    <string name="show_touches_summary" msgid="3692861665994502193">"ट्यापका लागि भिजुअल प्रतिक्रिया देखाउनुहोस्"</string>
     <string name="show_key_presses" msgid="6360141722735900214">"थिचिएका कीहरू देखाइयून्"</string>
-    <string name="show_key_presses_summary" msgid="725387457373015024">"थिचिएका भौतिक कीसम्बन्धी भिजुअल प्रतिक्रिया देखाइयोस्"</string>
-    <string name="show_screen_updates" msgid="2078782895825535494">"सर्फेस अपडेट देखाइयोस्"</string>
-    <string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट हुँदा विन्डोका पूरै सतहमा देखाइयोस्"</string>
-    <string name="show_hw_screen_updates" msgid="2021286231267747506">"GPU भ्युको अपडेट देखाइयोस्"</string>
-    <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"GPU ले बनाएको भ्यु विन्डोमा फ्ल्यास गरियोस्"</string>
-    <string name="show_hw_layers_updates" msgid="5268370750002509767">"हार्डवेयर लेयरको अपडेट देखाइयोस्"</string>
+    <string name="show_key_presses_summary" msgid="725387457373015024">"थिचिएका भौतिक कीसम्बन्धी भिजुअल प्रतिक्रिया देखाउनुहोस्"</string>
+    <string name="show_screen_updates" msgid="2078782895825535494">"सर्फेस अपडेट देखाउनुहोस्"</string>
+    <string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट हुँदा विन्डोका पूरै सतहमा देखाउनुहोस्"</string>
+    <string name="show_hw_screen_updates" msgid="2021286231267747506">"GPU भ्युको अपडेट देखाउनुहोस्"</string>
+    <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"GPU ले बनाएको भ्यु विन्डोमा फ्ल्यास गर्नुहोस्"</string>
+    <string name="show_hw_layers_updates" msgid="5268370750002509767">"हार्डवेयर लेयरको अपडेट देखाउनुहोस्"</string>
     <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"हार्डवेयर लेयर अपडेट हुँदा ती लेयर हरिया देखिऊन्"</string>
-    <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU overdraw डिबग गरियोस्"</string>
-    <string name="disable_overlays" msgid="4206590799671557143">"HW ओभरले अफ गरियोस्"</string>
-    <string name="disable_overlays_summary" msgid="1954852414363338166">"स्क्रिन कोम्पजिट गर्न लागि सधैँ GPU प्रयोग गरियोस्"</string>
-    <string name="simulate_color_space" msgid="1206503300335835151">"कलर स्पेसको नक्कल गरियोस्"</string>
+    <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU overdraw डिबग गर्नुहोस्"</string>
+    <string name="disable_overlays" msgid="4206590799671557143">"HW ओभरले अफ गर्नुहोस्"</string>
+    <string name="disable_overlays_summary" msgid="1954852414363338166">"स्क्रिन कोम्पजिट गर्न लागि सधैँ GPU प्रयोग गर्नुहोस्"</string>
+    <string name="simulate_color_space" msgid="1206503300335835151">"कलर स्पेसको नक्कल गर्नुहोस्"</string>
     <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ट्रेसहरू सक्षम गर्नुहोस्"</string>
-    <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB अडियो राउटिङ अफ गरियोस्"</string>
-    <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB अडियोमा स्वत: राउट नगरियोस्"</string>
-    <string name="debug_layout" msgid="1659216803043339741">"लेआउटका सीमाहरू देखाइयोस्"</string>
-    <string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमा, मार्जिन, इत्यादि देखाइयोस्।"</string>
-    <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL लेआउट बलपूर्वक प्रयोग गरियोस्"</string>
-    <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सबै लोकेलमा RTLमा स्क्रिन लेआउट बलपूर्वक प्रयोग गरियोस्"</string>
+    <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB अडियो राउटिङ अफ गर्नुहोस्"</string>
+    <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB अडियोमा स्वत: राउट नगर्नुहोस्"</string>
+    <string name="debug_layout" msgid="1659216803043339741">"लेआउटका सीमाहरू देखाउनुहोस्"</string>
+    <string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमा, मार्जिन, इत्यादि देखाउनुहोस्।"</string>
+    <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL लेआउट बलपूर्वक प्रयोग गर्नुहोस्"</string>
+    <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"सबै लोकेलमा RTLमा स्क्रिन लेआउट बलपूर्वक प्रयोग गर्नुहोस्"</string>
     <string name="transparent_navigation_bar" msgid="1933192171384678484">"पारदर्शी नेभिगेसन बार"</string>
     <string name="transparent_navigation_bar_summary" msgid="5454359021817330722">"नेभिगेसन बारको ब्याकग्राउन्डको रङ स्वतः पारदर्शी बनाउनुहोस्"</string>
-    <string name="window_blurs" msgid="6831008984828425106">"विन्डो ब्लर गरियोस्"</string>
-    <string name="force_msaa" msgid="4081288296137775550">"बलपूर्वक 4x MSAA प्रयोग गरियोस्"</string>
-    <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES २.० एपमा ४x MSAA अन गरियोस्"</string>
-    <string name="show_non_rect_clip" msgid="7499758654867881817">"गैर आयातकर क्लिप रहेका कार्यहरू डिबग गरियोस्"</string>
+    <string name="window_blurs" msgid="6831008984828425106">"विन्डो ब्लर गर्नुहोस्"</string>
+    <string name="force_msaa" msgid="4081288296137775550">"बलपूर्वक 4x MSAA प्रयोग गर्नुहोस्"</string>
+    <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES २.० एपमा ४x MSAA अन गर्नुहोस्"</string>
+    <string name="show_non_rect_clip" msgid="7499758654867881817">"गैर आयातकर क्लिप रहेका कार्यहरू डिबग गर्नुहोस्"</string>
     <string name="track_frame_time" msgid="522674651937771106">"प्रोफाइलको HWUI रेन्डरिङ"</string>
-    <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU का डिबग लेयर अन गरियोस्"</string>
-    <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"डिबग एपका लागि GPU का डिबग लेयर लोड गरियोस्"</string>
-    <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"भर्बोज भेन्डर लगिङ अन गरियोस्"</string>
-    <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"बग रिपोर्टहरूमा डिभाइस विशेषका विक्रेताका अतिरिक्त लगहरू समावेश गरियोस्। यी लगमा निजी जानकारी समावेश हुन सक्छन्, यिनले ब्याट्रीको खपत बढाउन र/वा थप भण्डारण प्रयोग गर्न सक्छन्।"</string>
+    <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU का डिबग लेयर अन गर्नुहोस्"</string>
+    <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"डिबग एपका लागि GPU का डिबग लेयर लोड गर्नुहोस्"</string>
+    <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"भर्बोज भेन्डर लगिङ अन गर्नुहोस्"</string>
+    <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"बग रिपोर्टहरूमा डिभाइस विशेषका विक्रेताका अतिरिक्त लगहरू समावेश गर्नुहोस्। यी लगमा निजी जानकारी समावेश हुन सक्छन्, यिनले ब्याट्रीको खपत बढाउन र/वा थप भण्डारण प्रयोग गर्न सक्छन्।"</string>
     <string name="window_animation_scale_title" msgid="5236381298376812508">"विन्डो एनिमेसन स्केल"</string>
     <string name="transition_animation_scale_title" msgid="1278477690695439337">"संक्रमण एनिमेसन स्केल"</string>
     <string name="animator_duration_scale_title" msgid="7082913931326085176">"एनिमेसनको अवधि मापन"</string>
-    <string name="overlay_display_devices_title" msgid="5411894622334469607">"सहायक डिस्प्लेको नक्कल गरियोस्"</string>
+    <string name="overlay_display_devices_title" msgid="5411894622334469607">"सहायक डिस्प्लेको नक्कल गर्नुहोस्"</string>
     <string name="debug_applications_category" msgid="5394089406638954196">"एपहरू"</string>
     <string name="immediately_destroy_activities" msgid="1826287490705167403">"गतिविधि नराखियोस्"</string>
-    <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"प्रयोगकर्ता कुनै गतिविधिबाट बाहिरिने बित्तिकै उक्त गतिविधि अन्त्य गरियोस्"</string>
+    <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"प्रयोगकर्ता कुनै गतिविधिबाट बाहिरिने बित्तिकै उक्त गतिविधि अन्त्य गर्नुहोस्"</string>
     <string name="app_process_limit_title" msgid="8361367869453043007">"ब्याकग्राउन्ड प्रक्रियाको सीमा"</string>
-    <string name="show_all_anrs" msgid="9160563836616468726">"ब्याकग्राउन्डमा ANR देखाइयोस्"</string>
-    <string name="show_all_anrs_summary" msgid="8562788834431971392">"ब्याकग्राउन्डका एपको हकमा \'नचलिरहेका एप\' सन्देश देखाइयोस्"</string>
-    <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना च्यानलसम्बन्धी चेतावनी देखाइयोस्"</string>
-    <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"एपले मान्य च्यानलबिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाइयोस्"</string>
+    <string name="show_all_anrs" msgid="9160563836616468726">"ब्याकग्राउन्डमा ANR देखाउनुहोस्"</string>
+    <string name="show_all_anrs_summary" msgid="8562788834431971392">"ब्याकग्राउन्डका एपको हकमा \'नचलिरहेका एप\' सन्देश देखाउनुहोस्"</string>
+    <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना च्यानलसम्बन्धी चेतावनी देखाउनुहोस्"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"एपले मान्य च्यानलबिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाउनुहोस्"</string>
     <string name="force_allow_on_external" msgid="9187902444231637880">"एपलाई बहिरी मेमोरीमा पनि चल्न दिइयोस्"</string>
-    <string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाइयोस्"</string>
-    <string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाइयोस्"</string>
-    <string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाइयोस्।"</string>
-    <string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गरियोस्"</string>
-    <string name="enable_freeform_support_summary" msgid="1822862728719276331">"प्रयोगात्मक फ्रिफर्म विन्डोहरू चल्ने बनाइयोस्"</string>
+    <string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाउनुहोस्"</string>
+    <string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाउनुहोस्"</string>
+    <string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाउनुहोस्।"</string>
+    <string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गर्नुहोस्"</string>
+    <string name="enable_freeform_support_summary" msgid="1822862728719276331">"प्रयोगात्मक फ्रिफर्म विन्डोहरू चल्ने बनाउनुहोस्"</string>
     <string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटप ब्याकअप पासवर्ड"</string>
     <string name="local_backup_password_summary_none" msgid="7646898032616361714">"हाल डेस्कटपका सबै ब्याकअप पासवर्ड सुरक्षित छैनन्"</string>
     <string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string>
@@ -457,7 +463,7 @@
     <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिङसम्बन्धी डिफल्ट सेटिङ परिवर्तन गर्नुहोस्"</string>
     <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिङ अन गर्नुहोस्"</string>
     <string name="transcode_default" msgid="3784803084573509491">"एपहरूमा आधुनिक फर्म्याट प्रयोग गर्न मिल्छ भनी मान्नुहोस्"</string>
-    <string name="transcode_notification" msgid="5560515979793436168">"ट्रान्सकोडिङसम्बन्धी सूचना देखाइयोस्"</string>
+    <string name="transcode_notification" msgid="5560515979793436168">"ट्रान्सकोडिङसम्बन्धी सूचना देखाउनुहोस्"</string>
     <string name="transcode_disable_cache" msgid="3160069309377467045">"ट्रान्सकोडिङको क्यास अफ गर्नुहोस्"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
@@ -472,7 +478,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ट्रिटानोमेली (निलो-पंहेलो)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"कलर करेक्सन"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"तपाईं रङ सच्याउने सुविधाका सहायताले निम्न कार्य गर्न सक्नुहुन्छ:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;अझ सटीक तरिकाले रङहरू हेर्न&lt;/li&gt; &lt;li&gt;&amp;nbsp;फोकस गर्नका लागि रङहरू हटाउन&lt;/li&gt; &lt;/ol&gt;"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"तपाईं कलर करेक्सनका सहायताले निम्न कार्य गर्न सक्नुहुन्छ:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;अझ सटीक तरिकाले रङहरू हेर्न&lt;/li&gt; &lt;li&gt;&amp;nbsp;फोकस गर्नका लागि रङहरू हटाउन&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - ब्याट्री जोगाउन चार्जिङ होल्ड गरिएको छ"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूरा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> लाग्ने छ"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गरिँदै छ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> बजेसम्ममा पूरा चार्ज हुने छ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै छ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै छ"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज भयो"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"पूर्ण रूपमा चार्ज भएको छ"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"चार्जिङ होल्ड गरिएको छ"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"चार्ज गरिँदै छ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"फास्ट चार्जिङ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"प्रशासकद्वारा नियन्त्रित"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"प्रतिबन्धित सेटिङले नियन्त्रण गरेको"</string>
     <string name="disabled" msgid="8017887509554714950">"असक्षम पारियो"</string>
@@ -534,7 +546,7 @@
     <string name="retail_demo_reset_next" msgid="3688129033843885362">"अर्को"</string>
     <string name="retail_demo_reset_title" msgid="1866911701095959800">"पासवर्ड आवश्यक छ"</string>
     <string name="active_input_method_subtypes" msgid="4232680535471633046">"आगत विधिहरू अन गर्नुहोस्"</string>
-    <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिष्टममा भएका भाषा प्रयोग गरियोस्"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"सिष्टममा भएका भाषा प्रयोग गर्नुहोस्"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>का लागि सेटिङहरू खोल्न विफल भयो।"</string>
     <string name="ime_security_warning" msgid="6547562217880551450">"यस इनपुट विधिले तपाईँले टाइप गर्नुहुने सम्पूर्ण पाठ बटु्ल्न सक्छ, व्यक्तिगत डेटा जस्तै पासवर्ड र क्रेडिट कार्ड नम्बर लगायतका। यो <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> अनुप्रयोगबाट आउँदछ। यो इनपुट विधि प्रयोग गर्ने हो?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"नोट: रिबुट गरेपछि तपाईंले आफ्नो फोन अनलक नगरेसम्म यो एप सुरु हुँदैन"</string>
@@ -567,7 +579,7 @@
     <string name="alarm_template" msgid="3346777418136233330">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
     <string name="alarm_template_far" msgid="6382760514842998629">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
     <string name="zen_mode_duration_settings_title" msgid="1553451650289651489">"अवधि"</string>
-    <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"प्रत्येक पटक सोधियोस्"</string>
+    <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"प्रत्येक पटक सोध्नुहोस्"</string>
     <string name="zen_mode_forever" msgid="3339224497605461291">"तपाईंले अफ नगरेसम्म"</string>
     <string name="time_unit_just_now" msgid="3006134267292728099">"अहिले भर्खरै"</string>
     <string name="media_transfer_this_device_name" msgid="2357329267148436433">"यो फोन"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फोन एउटा पट्टि।"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फोन दुई पट्टि।"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तिन पट्टिहरू।"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"फोनका चार वटा बार।"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फोन सङ्केत भरिएको।"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"डेटा छैन।"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटाको एउटा पट्टि।"</string>
@@ -708,8 +721,8 @@
     <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"किबोर्ड लेआउट छान्नुहोस्"</string>
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"डिफल्ट"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"स्क्रिन अन गर्नुहोस्"</string>
-    <string name="allow_turn_screen_on" msgid="6194845766392742639">"स्क्रिन अन गर्ने अनुमति दिइयोस्"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"कुनै एपलाई स्क्रिन अन गर्ने अनुमति दिइयोस्। यो अनुमति दिइएका खण्डमा तपाईंले अन गर्न नखोजेका बेलामा पनि एपले जुनसुकै बेला स्क्रिन अन गर्न सक्छ।"</string>
+    <string name="allow_turn_screen_on" msgid="6194845766392742639">"स्क्रिन अन गर्ने अनुमति दिनुहोस्"</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"कुनै एपलाई स्क्रिन अन गर्ने अनुमति दिनुहोस्। यो अनुमति दिइएका खण्डमा तपाईंले अन गर्न नखोजेका बेलामा पनि एपले जुनसुकै बेला स्क्रिन अन गर्न सक्छ।"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ब्रोडकास्ट गर्न छाड्ने हो?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"तपाईंले <xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुभयो वा आउटपुट परिवर्तन गर्नुभयो भने तपाईंको हालको ब्रोडकास्ट रोकिने छ"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 801c73f..6394cb6 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -94,47 +94,53 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon of media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Actief, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterij"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Actief, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batterij, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batterij"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batterij, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batterij"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Links <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Rechts <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actief"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Opgeslagen"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actief, alleen links"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actief, alleen rechts"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actief, links en rechts"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Actief (alleen media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ondersteunt audio delen"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Actief (alleen media), alleen links"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Actief (alleen media), alleen rechts"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Actief (alleen media), links en rechts"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Media-audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefoongesprekken"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Bestandsoverdracht"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Invoerapparaat"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internettoegang"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Toegang geven tot contacten en gespreksgeschiedenis"</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"De informatie wordt onder andere gebruikt voor gespreksaankondigingen"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Deze informatie wordt o.a. gebruikt voor gespreksaankondigingen"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetverbinding delen"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms-berichten"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Simtoegang"</string>
@@ -472,7 +478,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Kleurcorrectie kan handig zijn in de volgende situaties:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Je wilt kleuren nauwkeuriger zien.&lt;/li&gt; &lt;li&gt;&amp;nbsp;Je wilt kleuren verwijderen zodat je je beter kunt focussen.&lt;/li&gt; &lt;/ol&gt;"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Kleurcorrectie kan handig zijn in de volgende situaties:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Je wilt kleuren nauwkeuriger zien.&lt;/li&gt; &lt;li&gt;&amp;nbsp;Je wilt kleuren verwijderen zodat je je beter kunt concentreren.&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g>: opladen is in de wacht gezet om de batterij te beschermen"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - vol over <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen geoptimaliseerd"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Opladen"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Vol om <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Volledig opgeladen om <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Volledig opgeladen om <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Vol om <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Opgeladen"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Volledig opgeladen"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Opladen in de wacht"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Opladen"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Snel opladen"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ingesteld door beheerder"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Beheerd door beperkte instelling"</string>
     <string name="disabled" msgid="8017887509554714950">"Uitgezet"</string>
@@ -553,7 +565,7 @@
     <string name="okay" msgid="949938843324579502">"OK"</string>
     <string name="done" msgid="381184316122520313">"Klaar"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en herinneringen"</string>
-    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Wekkers en herinneringen laten instellen"</string>
+    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Instellen van wekkers en herinneringen toestaan"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en herinneringen"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Sta toe dat deze app wekkers zet en tijdgevoelige acties plant. De app kan hierdoor op de achtergrond worden uitgevoerd, waardoor je misschien meer batterijlading verbruikt.\n\nAls dit recht uitstaat, werken door deze app geplande bestaande wekkers en tijdgebaseerde afspraken niet."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plannen, schema, wekker, alarm, herinnering, klok"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefoon: één streepje."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefoon: twee streepjes."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefoon: drie streepjes."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefoonsignaal 4 streepjes."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefoonsignaal is op volle sterkte."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Geen gegevens."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Gegevens: één streepje."</string>
@@ -709,7 +722,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Standaard"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Scherm aanzetten"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Scherm aanzetten toestaan"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Toestaan dat een app het scherm aanzet. Indien toegestaan, kan de app het scherm op elk moment aanzetten zonder jouw expliciete intentie."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Sta toe dat een app het scherm aanzet. Indien toegestaan, kan de app het scherm op elk moment aanzetten zonder jouw expliciete intentie."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Uitzending van <xliff:g id="APP_NAME">%1$s</xliff:g> stopzetten?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Als je <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzendt of de uitvoer wijzigt, wordt je huidige uitzending gestopt"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzenden"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index c7c857b..28a8db6d 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -188,7 +188,7 @@
     <item msgid="409235464399258501">"ବନ୍ଦ"</item>
     <item msgid="4195153527464162486">"64K ପିଛା ଲଗ୍‌ ବଫର୍‌"</item>
     <item msgid="7464037639415220106">"256K ଲଗ୍‌ ପ୍ରତି ବଫର୍‌"</item>
-    <item msgid="8539423820514360724">"1M ପ୍ରତି ଲଗ୍‌ ବଫର୍‌"</item>
+    <item msgid="8539423820514360724">"ପ୍ରତି ଲଗ ବଫର ପାଇଁ 1M"</item>
     <item msgid="1984761927103140651">"ଲଗ୍‌ ବଫର୍‌ ପ୍ରତି 4M"</item>
     <item msgid="2983219471251787208">"ଲଗ୍ ବଫର୍ ପ୍ରତି 8M"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 3cbbc05..eb31f96 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ସଂଯୁକ୍ତ ନାହିଁ (ଫୋନ୍ ନୁହେଁ), ବ୍ୟାଟେରୀ<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ସଂଯୁକ୍ତ ହେଲା (ମିଡିଆ ନୁହେଁ), ବ୍ୟାଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ସଂଯୁକ୍ତ ହେଲା (ଫୋନ୍ କିମ୍ବା ମେଡିଆ ନୁହେଁ), ବ୍ୟାଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ସକ୍ରିୟ, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବ୍ୟାଟେରୀ"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ସକ୍ରିୟ, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ବ୍ୟାଟେରୀ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବ୍ୟାଟେରୀ"</string>
-    <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବ୍ୟାଟେରୀ"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
+    <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ବେଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ବ୍ୟାଟେରୀ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବ୍ୟାଟେରୀ"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ବାମ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ଡାହାଣ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ସକ୍ରିୟ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ସେଭ କରାଯାଇଛି"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ସକ୍ରିୟ, କେବଳ ବାମ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ସକ୍ରିୟ, କେବଳ ଡାହାଣ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ସକ୍ରିୟ, ବାମ ଏବଂ ଡାହାଣ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ଅଡିଓ ସେୟାରିଂକୁ ସମର୍ଥନ କରେ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ବାମ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), କେବଳ ଡାହାଣ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ), ବାମ ଏବଂ ଡାହାଣ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ମିଡିଆ ଅଡିଓ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ଫୋନ୍‌ କଲ୍‌‌ଗୁଡ଼ିକ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ ଚାର୍ଜିଂ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବ"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • <xliff:g id="TIME">%2$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଭାବେ ଚାର୍ଜ ହୋଇଯିବ"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଭାବେ ଚାର୍ଜ ହୋଇଯିବ"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> ସୁଦ୍ଧା ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ଚାର୍ଜ ହୋଇଯାଇଛି"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ସମ୍ପୂର୍ଣ୍ଣ ଭାବରେ ଚାର୍ଜ ହୋଇଛି"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ଚାର୍ଜିଂ ହୋଲ୍ଡରେ ଅଛି"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ଚାର୍ଜ ହେଉଛି"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ଫାଷ୍ଟ ଚାର୍ଜିଂ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ଆଡ୍‌ମିନ୍‌ ଦ୍ୱାରା ନିୟନ୍ତ୍ରିତ"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ପ୍ରତିବନ୍ଧିତ ସେଟିଂ ଦ୍ୱାରା ନିୟନ୍ତ୍ରଣ କରାଯାଇଛି"</string>
     <string name="disabled" msgid="8017887509554714950">"ଅକ୍ଷମ ହୋଇଛି"</string>
@@ -635,7 +647,7 @@
     <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>କୁ ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ନୂଆ ୟୁଜର ତିଆରି କରାଯାଉଛି…"</string>
     <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"ନୂଆ ଅତିଥି ତିଆରି କରାଯାଉଛି…"</string>
-    <string name="add_user_failed" msgid="4809887794313944872">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା ତିଆରି କରିବାକୁ ବିଫଳ ହେଲା"</string>
+    <string name="add_user_failed" msgid="4809887794313944872">"ନୂଆ ୟୁଜର ତିଆରି କରିବା ବିଫଳ ହୋଇଛି"</string>
     <string name="add_guest_failed" msgid="8074548434469843443">"ଜଣେ ନୂଆ ଅତିଥି ତିଆରି କରିବାରେ ବିଫଳ ହୋଇଛି"</string>
     <string name="user_nickname" msgid="262624187455825083">"ଡାକନାମ"</string>
     <string name="edit_user_info_message" msgid="6677556031419002895">"ଆପଣ ବାଛିଥିବା ନାମ ଏବଂ ଛବି ଏହି ଡିଭାଇସ ବ୍ୟବହାର କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କୁ ଦେଖାଯିବ।"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ଫୋନର ଗୋଟିଏ ବାର ଅଛି।"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ଫୋନର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ଫୋନ୍‍ରେ ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ଫୋନର ଚାରୋଟି ବାର।"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ଫୋନ୍ ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"କୌଣସି ଡାଟା ନାହିଁ।"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ଡାଟାର ଗୋଟିଏ ବାର ଅଛି।"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 2105852..64c4e96 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ਕਿਰਿਆਸ਼ੀਲ, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ਕਿਰਿਆਸ਼ੀਲ, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ਬੈਟਰੀ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ਬੈਟਰੀ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ਖੱਬੇ ਪਾਸੇ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ਸੱਜੇ ਪਾਸੇ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ਕਿਰਿਆਸ਼ੀਲ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਖੱਬਾ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਸੱਜਾ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ਕਿਰਿਆਸ਼ੀਲ, ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਖੱਬਾ"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਸਿਰਫ਼ ਸੱਜਾ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ), ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"ਮੀਡੀਆ  ਆਡੀਓ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ਫ਼ੋਨ ਕਾਲਾਂ"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> ਤੱਕ ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
@@ -506,9 +516,11 @@
     <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
     <string name="battery_info_status_not_charging" msgid="1103084691314264664">"ਕਨੈਕਟ ਹੋ ਗਿਆ, ਪਰ ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ ਹੈ"</string>
-    <string name="battery_info_status_full" msgid="1339002294876531312">"ਚਾਰਜ ਹੋ ਗਈ"</string>
+    <string name="battery_info_status_full" msgid="1339002294876531312">"ਬੈਟਰੀ ਚਾਰਜ ਹੋ ਗਈ"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ਪੂਰੀ ਚਾਰਜ ਹੋ ਗਈ ਹੈ"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ਤੇਜ਼ ਚਾਰਜਿੰਗ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ਪ੍ਰਤਿਬੰਧਿਤ ਸੈਟਿੰਗ ਰਾਹੀਂ ਕੰਟਰੋਲ ਕੀਤੀ ਜਾਂਦੀ ਹੈ"</string>
     <string name="disabled" msgid="8017887509554714950">"ਅਯੋਗ ਬਣਾਇਆ"</string>
@@ -555,7 +567,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>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ਫ਼ੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ਫ਼ੋਨ ਦੇ ਸਿਗਨਲ ਦੀਆਂ ਚਾਰ ਡੰਡੀਆਂ ਹਨ।"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ਫ਼ੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ਕੋਈ  ਡਾਟਾ  ਨਹੀਂ।"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">" ਡਾਟਾ  ਇੱਕ ਬਾਰ।"</string>
@@ -709,7 +722,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰੋ"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰਨ ਦਿਓ"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"ਐਪ ਨੂੰ ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰਨ ਦਿਓ। ਜੇ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਐਪ ਕਿਸੇ ਵੀ ਸਮੇਂ ਸਕ੍ਰੀਨ ਨੂੰ ਚਾਲੂ ਕਰ ਸਕਦੀ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਨੂੰ ਇਸਦੀ ਲੋੜ ਨਾ ਹੋਵੇ।"</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"ਐਪ ਨੂੰ ਸਕ੍ਰੀਨ ਚਾਲੂ ਕਰਨ ਦਿਓ। ਇਜਾਜ਼ਤ ਦਿੱਤੇ ਜਾਣ \'ਤੇ, ਇਹ ਐਪ ਤੁਹਾਡੇ ਇਰਾਦੇ ਦੇ ਬਿਨਾਂ ਕਿਸੇ ਵੇਲੇ ਵੀ ਸਕ੍ਰੀਨ ਨੂੰ ਚਾਲੂ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਦੇ ਪ੍ਰਸਾਰਨ ਨੂੰ ਰੋਕਣਾ ਹੈ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ਜੇ ਤੁਸੀਂ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰਦੇ ਹੋ ਜਾਂ ਆਊਟਪੁੱਟ ਬਦਲਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਪ੍ਰਸਾਰਨ ਰੁਕ ਜਾਵੇਗਾ"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 5358ed8..9c25aaa 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -186,10 +186,10 @@
   </string-array>
   <string-array name="select_logd_size_summaries">
     <item msgid="409235464399258501">"Wył."</item>
-    <item msgid="4195153527464162486">"64 KB/bufor dziennika"</item>
-    <item msgid="7464037639415220106">"256 KB/bufor dziennika"</item>
-    <item msgid="8539423820514360724">"1 MB/bufor dziennika"</item>
-    <item msgid="1984761927103140651">"4 MB/bufor dziennika"</item>
+    <item msgid="4195153527464162486">"64 KB / bufor dziennika"</item>
+    <item msgid="7464037639415220106">"256 KB / bufor dziennika"</item>
+    <item msgid="8539423820514360724">"1 MB / bufor dziennika"</item>
+    <item msgid="1984761927103140651">"4 MB / bufor dziennika"</item>
     <item msgid="2983219471251787208">"8 MB na bufor dziennika"</item>
   </string-array>
   <string-array name="select_logpersist_titles">
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 93e65af..d4d27e1 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -94,47 +94,53 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Połączono (bez telefonu), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Połączono (bez multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Połączono (bez telefonu i multimediów), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktywne, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterii"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktywna, L: bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Po lewej <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Po prawej <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Urządzenie aktywne"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Zapisano"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywne, tylko lewa strona"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywne, tylko prawa strona"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktywny, lewa i prawa strona"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktywne (tylko multimedia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Obsługa udostępniania dźwięku"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktywne (tylko multimedia), tylko lewa"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktywne (tylko multimedia), tylko prawa"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktywne (tylko multimedia), lewa i prawa"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Dźwięk multimediów"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Połączenia telefoniczne"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Przesyłanie pliku"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Urządzenie wejściowe"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Dostęp do internetu"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Zezwól na dostęp do kontaktów i historii połączeń"</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Informacje zostaną wykorzystane do powiadomień i nie tylko"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"Informacje zostaną wykorzystane m.in. do powiadomień o połączeniach"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Udostępnianie połączenia internetowego"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-y"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostęp do karty SIM"</string>
@@ -336,7 +342,7 @@
     <string name="wifi_metered_label" msgid="8737187690304098638">"Użycie danych jest mierzone"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Użycie danych nie jest mierzone"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"Rozmiary bufora rejestratora"</string>
-    <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Wybierz rozmiary Rejestratora/bufor dziennika"</string>
+    <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Wybierz rozmiary Rejestratora na bufor dziennika"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Wyczyścić pamięć trwałych dzienników?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Po zakończeniu monitorowania przy użyciu trwale zapisywanych dzienników musimy usunąć ich dane zapisane na urządzeniu."</string>
     <string name="select_logpersist_title" msgid="447071974007104196">"Zapisuj trwale dane dzienników na urządzeniu"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zoptymalizowane"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Bateria będzie pełna do <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pełne naładowanie do <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Pełne naładowanie do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Bateria będzie pełna do <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string>
@@ -505,10 +515,12 @@
     <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ładowanie bezprzewodowe"</string>
     <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ładowanie"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nie podłączony"</string>
-    <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Podłączono, ale nie ładuje się"</string>
+    <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Podłączono, brak ładowania"</string>
     <string name="battery_info_status_full" msgid="1339002294876531312">"Naładowana"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Bateria w pełni naładowana"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ładowanie wstrzymane"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Ładowanie"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Szybkie ładowanie"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolowane przez administratora"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Obowiązują ustawienia z ograniczonym dostępem"</string>
     <string name="disabled" msgid="8017887509554714950">"Wyłączone"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon: jeden pasek."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon: dwa paski."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon: trzy paski."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Cztery słupki w telefonie."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon: pełna moc sygnału."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Brak danych."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dane: jeden pasek."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 811c04a..38df760 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sem telefone), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sem mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sem telefone ou mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Ativo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Ativo, E: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"E: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas mídia), somente direito"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas mídia), esquerdo e direito"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Áudio da mídia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefônicas"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (carregando)"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carregado até <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Totalmente carregado até <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Totalmente carregado até <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Carregado até <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carregamento suspenso"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Carregamento"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Carregamento rápido"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada pelo admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlada pelas configurações restritas"</string>
     <string name="disabled" msgid="8017887509554714950">"Desativado"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de sinal do telefone."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de sinal do telefone."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de sinal do telefone."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Quatro barras do smartphone."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal do telefone cheio."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nenhum dado."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de sinal de dados."</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 4c88683..9e98623 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -94,47 +94,53 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ligado (sem telemóvel), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ligado (sem multimédia), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ligado (sem telemóvel nem multimédia), bateria a <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Ativo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Ativo, E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas esquerdo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas direito"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas para multimédia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Suporta partilha de áudio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas para multimédia), apenas esquerdo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas para multimédia), apenas direito"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas para multimédia), esquerdo e direito"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Áudio de multimédia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefónicas"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência do ficheiro"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à internet"</string>
     <string name="bluetooth_profile_pbap" msgid="2103406516858653017">"Acesso a contactos e histórico de chamadas"</string>
-    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"As informações são usadas para anúncios de chamadas e outros"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"As informações são usadas para anúncios por chamadas e outros"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partilha da ligação à internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao SIM"</string>
@@ -410,7 +416,7 @@
     <string name="force_msaa_summary" msgid="9070437493586769500">"Ativar o 4x MSAA em aplicações OpenGL ES 2.0"</string>
     <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de clipe não retangulares"</string>
     <string name="track_frame_time" msgid="522674651937771106">"Renderização HWUI do perfil"</string>
-    <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar cam. depuração GPU"</string>
+    <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar camadas de depuração GPU"</string>
     <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite carregamento de camadas de depuração de GPU para apps de depuração"</string>
     <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Ativ. registo do fornecedor"</string>
     <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclua registos adicionais de fornecedores específicos de dispositivos em relatórios de erros, que podem conter informações privadas, utilizar mais bateria e/ou utilizar mais armazenamento."</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até à carga máxima"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g>: carregamento otimizado"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – A carregar"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Completo à(s) <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Completamente carregado à(s) <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Completamente carregado à(s) <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Completo à(s) <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Totalmente carregada"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carregamento em espera"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Carregamento"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Carregamento rápido"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlado pelo gestor"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlado por uma definição restrita"</string>
     <string name="disabled" msgid="8017887509554714950">"Desativada"</string>
@@ -555,7 +567,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir 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">"Permita que esta app defina alarmes e agende outras ações com base no tempo. Esta ação permite que a app seja executada em segundo plano, o que pode utilizar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que a app defina alarmes e agende ações com um horário específico. Esta ação permite que a app seja executada em segundo plano, o que pode usar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, 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 modo Não incomodar"</string>
@@ -595,7 +607,7 @@
     <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Altifalantes internos"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string>
-    <string name="help_label" msgid="3528360748637781274">"Ajuda e comentários"</string>
+    <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
     <string name="storage_category" msgid="2287342585424631813">"Armazenamento"</string>
     <string name="shared_data_title" msgid="1017034836800864953">"Dados partilhados"</string>
     <string name="shared_data_summary" msgid="5516326713822885652">"Ver e modificar dados partilhados"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de telefone."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de telefone."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de telefone."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telemóvel com quatro barras."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal de telefone completo."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Sem dados."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de dados."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 811c04a..38df760 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectado (sem telefone), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectado (sem mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectado (sem telefone ou mídia), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Ativo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Ativo, E: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"E: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: Bateria do <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Ativo (apenas mídia)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Com suporte ao compartilhamento de áudio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Ativo (apenas mídia), apenas esquerdo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Ativo (apenas mídia), somente direito"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Ativo (apenas mídia), esquerdo e direito"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Áudio da mídia"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Chamadas telefônicas"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento otimizado"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> (carregando)"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Carregado até <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Totalmente carregado até <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Totalmente carregado até <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Carregado até <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carregamento suspenso"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Carregamento"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Carregamento rápido"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada pelo admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlada pelas configurações restritas"</string>
     <string name="disabled" msgid="8017887509554714950">"Desativado"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de sinal do telefone."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de sinal do telefone."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de sinal do telefone."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Quatro barras do smartphone."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal do telefone cheio."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nenhum dado."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de sinal de dados."</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1233afd..dddc116 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Conectat (fără telefon), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Conectat (fără conținut media), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Conectat (fără telefon sau conținut media), baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Activ, baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Activ, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterie, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterie"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterie, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterie"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvat"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activ, numai stânga"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activ, numai dreapta"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activ, stânga și dreapta"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Activ (numai pentru conținut media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Acceptă permiterea accesului la audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Activ (numai pentru conținut media), numai stânga"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Activ (numai pentru conținut media), numai dreapta"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Activ (numai pentru conținut media), stânga și dreapta"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Conținut media audio"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Apeluri telefonice"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer de fișiere"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la finalizare"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcare optimizată"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Se încarcă"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Timp rămas <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Complet încărcat în <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Complet încărcat în <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Timp rămas <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Încărcată"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Complet încărcată"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Încărcare întreruptă"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Încărcare"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Încărcare rapidă"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlată de administrator"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlată de setarea restricționată"</string>
     <string name="disabled" msgid="8017887509554714950">"Dezactivată"</string>
@@ -553,7 +565,7 @@
     <string name="okay" msgid="949938843324579502">"OK"</string>
     <string name="done" msgid="381184316122520313">"Gata"</string>
     <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_switch_title" msgid="4939393911531826222">"Permite setarea de 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ă 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>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Semnal pentru telefon: o bară."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Semnal pentru telefon: două bare."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Semnal pentru telefon: trei bare."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Patru bare pe telefon."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Semnal pentru telefon: complet."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nu există semnal pentru date."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Semnal pentru date: o bară."</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 43645f4..9a5a400 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Подключено (кроме звонков), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Подключено (кроме аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Подключено (кроме звонков и аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Активно. Заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активно. Л: батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; П: батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; П: батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Левый <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Правый <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сохранено"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активен, только левое ухо"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активен, только правое ухо"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активен, оба уха"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Используется (только для медиа)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Поддерживается отправка аудио"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Используется (только для медиа), левый наушник"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Используется (только для медиа), правый наушник"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Используется (только для медиа), левый и правый наушники"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Профиль A2DP"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Звонки"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Профиль OPP"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядка оптимизирована"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряжается"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g>. <xliff:g id="STATUS">%2$s</xliff:g> – завершится к <xliff:g id="TIME">%3$s</xliff:g>."</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – полностью зарядится к <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Полностью зарядится к <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Полностью зарядится к <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Батарея заряжена"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Батарея заряжена"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Зарядка приостановлена"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Зарядка"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Быстрая зарядка"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролируется администратором"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Контролируется настройками с ограниченным доступом"</string>
     <string name="disabled" msgid="8017887509554714950">"Отключено"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Сигнал телефонной сети: одно деление."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Сигнал телефонной сети: два деления."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Сигнал телефонной сети: три деления."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Сигнал телефонной сети: четыре деления."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Надежный телефонный сигнал."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Сигнал передачи данных отсутствует."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Сигнал передачи данных: одно деление."</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index d965b73..0fce42b 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"සම්බන්ධිතයි (දුරකථනය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"සම්බන්ධිතයි (මාධ්‍ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"සම්බන්ධිතයි (දුරකථනය හෝ මාධ්‍ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ක්‍රියාකාරී, බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ක්‍රියාත්මක, ව: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"ව: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"වම <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"දකුණ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ක්‍රියාකාරී"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"සුරැකිණි"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"සක්‍රිය, වම පමණි"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"සක්‍රිය, දකුණ පමණි"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"සක්‍රිය, වම සහ දකුණ"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"සක්‍රිය (මාධ්‍ය පමණි)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ශ්‍රව්‍ය බෙදා ගැනීම සහය දක්වයි"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"සක්‍රිය (මාධ්‍ය පමණි), වම පමණි"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"සක්‍රිය (මාධ්‍ය පමණි), දකුණ පමණි"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"සක්‍රිය (මාධ්‍ය පමණි), වම සහ දකුණ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"මාධ්‍ය ශ්‍රව්‍ය"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"දුරකථන ඇමතුම්"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ගොනු හුවමාරුව"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - සම්පූර්ණ වීමට <xliff:g id="TIME">%2$s</xliff:g>ක් ඉතිරියි"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය ප්‍රශස්ත කර ඇත"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වේ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> හට පෙර සම්පූර්ණයි"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> හට පෙර සම්පූර්ණයෙන් ආරෝපණ වෙයි"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> හට පෙර සම්පූර්ණයෙන් ආරෝපණ වෙයි"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> හට පෙර සම්පූර්ණයි"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්‍ර ආරෝපණය"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"අරෝපිතයි"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"සම්පූර්ණයෙන් ආරෝපණ වී ඇත"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ආරෝපණය රදවාගෙන ඇත"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ආරෝපණ කෙරේ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"වේගවත් ආරෝපණය"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"පරිපාලක විසින් පාලනය කරන ලදී"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"සීමා කළ සැකසීම මගින් පාලනය වේ"</string>
     <string name="disabled" msgid="8017887509554714950">"අබල කර ඇත"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"දුරකථනය තීරු එකයි."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"දුරකථනය තීරු දෙකයි."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"දුරකථනය තීරු තුනයි."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"දුරකථනය තීරු හතරක්."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"දුරකථනයේ සංඥාව පිරී ඇත."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"දත්ත නැත."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"දත්ත තීරු එකයි."</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 77c265e..74c9e1f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu), úroveň batérie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Pripojené k zariadeniu <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (bez telefónu a médií), úroveň batérie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktívne, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktívne, Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Ľavé: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Pravé: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktívne"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Uložené"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktívne, iba ľavá strana"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktívne, iba pravá strana"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktívne, ľavá aj pravá strana"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktívne (iba médiá)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podporuje zdieľanie zvuku"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktívne (iba médiá), iba ľavá strana"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktívne (iba médiá), iba pravá strana"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktívne (iba médiá), ľavá aj pravá strana"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvuk médií"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonické hovory"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos súborov"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je optimalizované"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – nabíja sa"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – čas do nabitia: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – čas do úplného nabitia: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Čas do nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Nabité"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Úplne nabitá"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Nabíjanie je pozastavené"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Nabíja sa"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Nabíja sa rýchlo"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ovládané správcom"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Ovládané obmedzeným nastavením"</string>
     <string name="disabled" msgid="8017887509554714950">"Deaktivované"</string>
@@ -555,7 +567,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciou nebudú fungovať."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Jeden stĺpec signálu telefónnej siete."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dve čiarky signálu telefónnej siete."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tri čiarky signálu telefónnej siete."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Signál v telefóne má štyri čiarky."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Plný signál telefónnej siete."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Žiadna dátová sieť."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Jedna čiarka signálu dátovej siete."</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index abca26f..a6d35c80 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Povezano (brez telefona), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Povezano (brez predstavnosti), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Povezano (brez telefona ali predstavnosti), raven napolnjenosti baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktivno, baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivno, L: napolnjenost baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: napolnjenost baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: napolnjenost baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: napolnjenost baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivna"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Shranjeno"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo levo"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, levo in desno"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktivno (samo predstavnost)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Podpira deljenje zvoka"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktivno (samo predstavnost), samo levo"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktivno (samo predstavnost), samo desno"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktivno (samo predstavnost), levo in desno"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Zvok predstavnosti"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonski klici"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje je optimizirano"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – polnjenje"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – popolnoma napolnjena do <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – popolnoma napolnjena do <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Popolnoma napolnjena do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Napolnjena do <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Napolnjeno"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Popolnoma napolnjena"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Polnjenje je na čakanju"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Polnjenje"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Hitro polnjenje"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Nadzira skrbnik"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Pod nadzorom omejene nastavitve"</string>
     <string name="disabled" msgid="8017887509554714950">"Onemogočeno"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon z eno črtico."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon z dvema črticama."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon s tremi črticami."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon štiri črtice."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal telefona je poln."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ni podatkov."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Podatkovni signal z eno črtico."</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 0f48e42c9..3f6e803 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"E lidhur (pa telefon), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"E lidhur (pa media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"E lidhur (pa telefon ose media), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiv, bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiv, L: Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> majtas"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> djathtas"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Të ruajtura"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktive, vetëm majtas"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktive, vetëm djathtas"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktive, majtas dhe djathtas"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (vetëm për media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Mbështet ndarjen e audios"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (vetëm për media), vetëm majtas"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (vetëm për media), vetëm djathtas"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (vetëm për media), majtas dhe djathtas"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audioja e medias"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonatat"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferimi i skedarëve"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi u optimizua"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Po karikohet"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Plot deri në <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikohet plotësisht deri në <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Karikohet plotësisht deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Plot deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Karikim i shpejtë"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Karikuar"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Karikuar plotësisht"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Karikimi në pritje"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Po karikohet"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Karikim i shpejtë"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolluar nga administratori"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrollohet nga \"Cilësimet e kufizuara\""</string>
     <string name="disabled" msgid="8017887509554714950">"Çaktivizuar"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefoni ka edhe një vijë."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefoni ka dy vija."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefoni ka tre vija."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefoni ka katër vija."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinjali i telefonit është i plotë."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Nuk ka të dhëna."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Sinjali është vetëm një vijë."</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index d309036c..135176b 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Повезано (без телефона), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Повезано (без медија), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Повезано (без телефона или медија), ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Активан, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активно, Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерије, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерије, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Лева <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Десна <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активан"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сачувано"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само с леве стране"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, с десне стране"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, с леве и десне стране"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активан (само за медије)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Подржава дељење звука"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активан (само за медије), само лево"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активан (само за медије), само десно"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активан (само за медије), лево и десно"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Звук медија"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонски позиви"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос датотеке"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до краја пуњења"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – пуњење је оптимизовано"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Пуњење"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Потпуно напуњено до <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Потпуно напуњено до <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Потпуно напуњено до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Напуњено до <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Напуњено"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Напуњено до краја"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Пуњење је на чекању"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Пуњење"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Брзо пуњење"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролише администратор"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Контролишу ограничена подешавања"</string>
     <string name="disabled" msgid="8017887509554714950">"Онемогућено"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Сигнал телефона има једну црту."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Сигнал телефона од две црте."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Сигнал телефона од три црте."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Телефон има четири црте."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигнал телефона је пун."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Нема података."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Сигнал за податке има једну црту."</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 363396a..7712203 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ansluten (ingen mobil), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ansluten (inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ansluten (ingen mobil och inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktiv, V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri. H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri. H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Vänster <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Höger <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Sparad"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bara vänster"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bara höger"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, vänster och höger"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktiv (endast media)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ljuddelning stöds"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktiv (endast media), endast vänster"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktiv (endast media), endast höger"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktiv (endast media), vänster och höger"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medialjud"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonsamtal"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filöverföring"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kvar tills fulladdat"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har optimerats"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – laddas"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – fulladdad till <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladdad till <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Fulladdad till <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Fulladdad till <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Laddat"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fulladdad"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Laddningen har pausats"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Laddning"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Snabbladdning"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Strys av administratören"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Styrs av spärrad inställning"</string>
     <string name="disabled" msgid="8017887509554714950">"Inaktiverad"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon: en stapel."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon: två staplar."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon: tre staplar."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon fyra staplar."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignalen är full."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Inga data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data: en stapel."</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index ebff38b..53d583a 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Imeunganishwa (hamna simu), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Imeunganishwa (hamna kifaa cha sauti), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Imeunganishwa (hamna simu au kifaa cha sauti), kiasi cha chaji ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Inatumika, betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Inatumika, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ya betri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ya betri"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ya betri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ya betri"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kushoto <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Kulia <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Kimeunganishwa"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Imeokoa"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Inatumika, kushoto pekee"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Inatumika, kulia pekee"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Inatumika, kushoto na kulia"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Inatumika (maudhui pekee)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Inaweza kutumia kipengele cha kusikiliza pamoja"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Inatumika (maudhui pekee), kushoto pekee"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Inatumika (maudhui pekee), kulia pekee"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Inatumika (maudhui pekee), kushoto na kulia"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Sauti ya maudhui"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Simu"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Uhamishaji wa faili"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> zimesalia ijae chaji"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hali ya kuchaji imeboreshwa"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inachaji"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Itajaa kufikia <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri itajaa chaji kufikia <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Betri itajaa chaji kufikia <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Itajaa kufikia <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Imechajiwa"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Imejaa Chaji"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Imesitisha kuchaji"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Inachaji"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Inachaji kwa kasi"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Imedhibitiwa na msimamizi"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Imedhibitiwa na Mpangilio wenye Mipaka"</string>
     <string name="disabled" msgid="8017887509554714950">"Imezimwa"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Mwambaa mmoja wa simu."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Miambaa miwili ya simu"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Miambaa mitatu ya simu."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Simu ina alama nne za ishara."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Ishara ya simu imejaa."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Hakuna data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Upapi mmoja wa habari"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 1648de0..db11263 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"இணைக்கப்பட்டது (மொபைல் இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"இணைக்கப்பட்டது (மீடியா இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"இணைக்கப்பட்டது (மொபைல் அல்லது மீடியா இல்லை), பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"செயலில் உள்ளது, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"செயலில் உள்ளது, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> பேட்டரி, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> பேட்டரி"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> பேட்டரி, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> பேட்டரி"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"இடதுபுறம்: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"வலதுபுறம்: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"செயலில் உள்ளது"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"சேமிக்கப்பட்டது"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"இடது பக்கம் மட்டும் செயலில் உள்ளது"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"வலது பக்கம் மட்டும் செயலில் உள்ளது"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"வலது மற்றும் இடது பக்கம் செயலில் உள்ளது"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"செயலிலுள்ளது (மீடியா மட்டும்)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ஆடியோ பகிர்வை ஆதரிக்கிறது"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மட்டும்"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"செயலிலுள்ளது (மீடியா மட்டும்), வலதுபுறம் மட்டும்"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"செயலிலுள்ளது (மீடியா மட்டும்), இடதுபுறம் மற்றும் வலதுபுறம்"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"மீடியா ஆடியோ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ஃபோன் அழைப்புகள்"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ஃபைல் இடமாற்றம்"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழுவதும் சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜிங் மேம்படுத்தப்பட்டது"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ சார்ஜாகிறது"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>க்கு முழுமையாகச் சார்ஜாகிவிடும்"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"சார்ஜாகிவிட்டது"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"முழுவதும் சார்ஜாகிவிட்டது"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"சார்ஜிங் இடைநிறுத்தப்பட்டுள்ளது"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"சார்ஜாகிறது"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"விரைவு சார்ஜிங்"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"வரையறுக்கப்பட்ட அமைப்பால் கட்டுப்படுத்தப்படுகிறது"</string>
     <string name="disabled" msgid="8017887509554714950">"முடக்கப்பட்டது"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"சிக்னல் இரண்டு கோட்டில் உள்ளது."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"நான்கு மொபைல் சிக்னல் கோடுகள்."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"சிக்னல் முழுமையாக உள்ளது."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"டேட்டா சிக்னல் இல்லை."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"தரவு சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 7ee57cf..c2faca9 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"కనెక్ట్ చేయబడింది (మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"యాక్టివ్‌గా ఉంది, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"యాక్టివ్, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ఎడమ వైపు <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"కుడి వైపు <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"యాక్టివ్‌గా ఉంది"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"సేవ్ చేయబడింది"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"యాక్టివ్‌గా ఉంది, ఎడమవైపు మాత్రమే యాక్టివ్‌గా ఉంది"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"యాక్టివ్‌గా ఉంది, కుడివైపు యాక్టివ్‌గా ఉంది"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"యాక్టివ్‌గా ఉంది, ఎడమవైపు, కుడివైపు యాక్టివ్‌గా ఉంది"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"యాక్టివ్ (మీడియా మాత్రమే)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"ఆడియో షేరింగ్‌కు సపోర్ట్ చేస్తుంది"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ వైపు మాత్రమే"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"యాక్టివ్ (మీడియా మాత్రమే), కుడివైపు మాత్రమే"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"యాక్టివ్ (మీడియా మాత్రమే), ఎడమ, కుడివైపు మాత్రమే"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"మీడియా ఆడియో"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ఫోన్ కాల్స్‌"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ఫైల్ బదిలీ"</string>
@@ -162,8 +168,8 @@
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ఇన్‌పుట్ కోసం ఉపయోగించండి"</string>
     <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"వినికిడి పరికరాల కోసం ఉపయోగించండి"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO కోసం ఉపయోగించండి"</string>
-    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"జత చేయి"</string>
-    <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"జత చేయి"</string>
+    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"పెయిర్ చేయండి"</string>
+    <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"పెయిర్ చేయండి"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"రద్దు చేయండి"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"పెయిర్ చేయడం వలన కనెక్ట్ చేయబడినప్పుడు మీ కాంటాక్ట్‌లకు అలాగే కాల్ హిస్టరీకి యాక్సెస్‌ను మంజూరు చేస్తుంది."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string>
@@ -201,7 +207,7 @@
     <string name="running_process_item_user_label" msgid="3988506293099805796">"యూజర్‌: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"కొన్ని ఆటోమేటిక్ సెట్టింగ్‌లు సెట్ చేయబడ్డాయి"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"ఆటోమేటిక్ ఆప్ష‌న్‌లు ఏవీ సెట్ చేయ‌‌లేదు"</string>
-    <string name="tts_settings" msgid="8130616705989351312">"వచనం నుండి ప్రసంగం సెట్టింగ్‌లు"</string>
+    <string name="tts_settings" msgid="8130616705989351312">"టెక్స్ట్-టు-స్పీచ్ సెట్టింగ్‌లు"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"టెక్స్ట్-టు-స్పీచ్ అవుట్‌పుట్"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"స్పీచ్ రేట్"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"వచనాన్ని చదివి వినిపించాల్సిన వేగం"</string>
@@ -339,7 +345,7 @@
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"లాగ్ బఫర్‌కి లాగర్ పరిమా. ఎంచుకోండి"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"లాగర్ నిరంతర నిల్వలోని డేటాను తీసివేయాలా?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"మేము నిరంతర లాగర్‌తో ఇక పర్యవేక్షించనప్పుడు, మీ పరికరంలోని లాగర్ డేటాను మేము తొలగించాల్సి ఉంటుంది."</string>
-    <string name="select_logpersist_title" msgid="447071974007104196">"పరికరంలో లాగర్ డేటా నిరంతరం స్టోర్ చేయి"</string>
+    <string name="select_logpersist_title" msgid="447071974007104196">"పరికరంలో లాగర్ డేటా నిరంతరం స్టోర్ చేయండి"</string>
     <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"పరికరంలో నిరంతరం స్టోరేజ్‌ చేయాల్సిన లాగ్ బఫర్‌లను ఎంచుకోండి"</string>
     <string name="select_usb_configuration_title" msgid="6339801314922294586">"USB కాన్ఫిగరేషన్‌ని ఎంచుకోండి"</string>
     <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB కాన్ఫిగరేషన్‌ని ఎంచుకోండి"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవుతోంది"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g>కు పూర్తవుతుంది"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>కు పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g>కు పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g>కు పూర్తవుతుంది"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ఛార్జ్ చేయబడింది"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"పూర్తి ఛార్జ్ అయింది"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ఛార్జింగ్ హోల్డ్‌లో ఉంది"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"ఛార్జ్ అవుతోంది"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ఫాస్ట్ ఛార్జింగ్"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"నిర్వాహకుని ద్వారా నియంత్రించబడింది"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"పరిమితం చేసిన సెట్టింగ్ ద్వారా నియంత్రించబడుతుంది"</string>
     <string name="disabled" msgid="8017887509554714950">"డిజేబుల్ చేయబడింది"</string>
@@ -555,7 +567,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">"అలారాలు &amp; రిమైండర్‌లు"</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>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ఫోన్ ఒక బారు."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ఫోన్ రెండు బార్లు."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ఫోన్ మూడు బార్లు."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"ఫోన్‌లో నాలుగు బార్‌లు."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ఫోన్ సిగ్నల్ పూర్తిగా ఉంది."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"డేటా లేదు."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"డేటా ఒక బారు."</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 55b57db..7b03f81 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"เชื่อมต่อแล้ว (ไม่รวมสื่อ) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"เชื่อมต่อแล้ว (ไม่รวมโทรศัพท์หรือสื่อ) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"ใช้งานอยู่ แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"ใช้งานอยู่ L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"ฝั่งซ้าย <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"ฝั่งขวา <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ใช้งานอยู่"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"บันทึกแล้ว"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ใช้งานอยู่ เฉพาะข้างซ้าย"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ใช้งานอยู่ เฉพาะข้างขวา"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ใช้งานอยู่ ข้างซ้ายและขวา"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"ใช้งานอยู่ (สื่อเท่านั้น)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"รองรับการแชร์เสียง"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายเท่านั้น"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"ใช้งานอยู่ (สื่อเท่านั้น), ขวาเท่านั้น"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"ใช้งานอยู่ (สื่อเท่านั้น), ซ้ายและขวา"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"เสียงของสื่อ"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"โทรศัพท์"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"การถ่ายโอนไฟล์"</string>
@@ -203,7 +209,7 @@
     <string name="launch_defaults_none" msgid="8049374306261262709">"ไม่ได้ตั้งค่าเริ่มต้น"</string>
     <string name="tts_settings" msgid="8130616705989351312">"การตั้งค่าการอ่านออกเสียงข้อความ"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"เอาต์พุตการอ่านออกเสียงข้อความ"</string>
-    <string name="tts_default_rate_title" msgid="3964187817364304022">"ความเร็วของคำพูด"</string>
+    <string name="tts_default_rate_title" msgid="3964187817364304022">"ความเร็วในการพูด"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"ความเร็วในการพูดข้อความ"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"ความสูง-ต่ำของเสียง"</string>
     <string name="tts_default_pitch_summary" msgid="9132719475281551884">"มีผลต่อโทนเสียงของข้อความสังเคราะห์"</string>
@@ -261,7 +267,7 @@
     <string name="adb_wireless_settings" msgid="2295017847215680229">"การแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"หากต้องการดูและใช้อุปกรณ์ที่มีอยู่ ให้เปิดการแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"จับคู่อุปกรณ์ด้วยคิวอาร์โค้ด"</string>
-    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"จับคู่อุปกรณ์เครื่องใหม่โดยใช้แอปสแกนคิวอาร์โค้ด"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"จับคู่อุปกรณ์เครื่องใหม่โดยใช้ตัวสแกนคิวอาร์โค้ด"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"จับคู่อุปกรณ์ด้วยรหัสการจับคู่"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"จับคู่อุปกรณ์เครื่องใหม่โดยใช้รหัสตัวเลข 6 หลัก"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"อุปกรณ์ที่จับคู่"</string>
@@ -487,7 +493,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> เมื่อดูจากการใช้งานของคุณ"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"จนถึง <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"จนถึง <xliff:g id="TIME">%1$s</xliff:g> น."</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"แบตเตอรี่อาจหมดภายใน <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"เหลือน้อยกว่า <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"เหลือน้อยกว่า <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - ปรับการชาร์จให้เหมาะสมแล้ว"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ กำลังชาร์จ"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - จะเต็มภายใน <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - จะชาร์จเต็มภายใน <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"จะชาร์จเต็มภายใน <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"จะเต็มภายใน <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"ชาร์จแล้ว"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ชาร์จเต็มแล้ว"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"หยุดการชาร์จชั่วคราว"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"กำลังชาร์จ"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"ชาร์จเร็ว"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ควบคุมโดยการตั้งค่าที่จำกัด"</string>
     <string name="disabled" msgid="8017887509554714950">"ปิดอยู่"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"สัญญาณโทรศัพท์หนึ่งขีด"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"สัญญาณโทรศัพท์สองขีด"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"สัญญาณโทรศัพท์สามขีด"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"สัญญาณโทรศัพท์ 4 ขีด"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"สัญญาณโทรศัพท์เต็ม"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"ไม่มีข้อมูล"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"สัญญาณข้อมูลหนึ่งขีด"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index c34588d..8eef17e 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Nakakonekta (walang telepono), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Nakakonekta (walang media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Nakakonekta (walang telepono o media), baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Aktibo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktibo, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterya, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterya, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kaliwa <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Kanan <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Na-save"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, kaliwa lang"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, kanan lang"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, kaliwa at kanan"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktibo (media lang)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Sinusuportahan ang pag-share ng audio"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktibo (media lang), kaliwa lang"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Aktibo (media lang), kanan lang"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Aktibo (media lang), kaliwa at kanan"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio ng media"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Mga tawag sa telepono"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Paglilipat ng file"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> na lang bago mapuno"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-optimize ang pag-charge"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nagcha-charge"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Mapupuno sa <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mafu-full charge sa <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Mafu-full charge sa <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Mapupuno sa <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Puno ang Baterya"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Naka-hold ang pag-charge"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Nagcha-charge"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Fast charging"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Pinapamahalaan ng admin"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kinokontrol ng Pinaghihigpitang Setting"</string>
     <string name="disabled" msgid="8017887509554714950">"Naka-disable"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telepono na isang bar."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telepono na dalawang bar."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telepono na tatlong bar."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Apat na bar ang telepono."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Puno ang signal ng telepono."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Walang data."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data na isang bar."</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 4315241..cf5bd2d 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (telefon yok), pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (medya yok), pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> cihazına bağlandı (telefon veya medya yok), pil seviyesi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Etkin, pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Etkin, Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pil, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pil, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Sol <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Sağ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Etkin"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Kaydedildi"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Yalnızca sol tarafta etkin"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Yalnızca sağ tarafta etkin"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Sol ve sağ tarafta etkin"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Etkin (yalnızca medya)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Ses paylaşımını destekler"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Etkin (yalnızca medya), yalnızca sol"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Etkin (yalnızca medya), yalnızca sağ"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Etkin (yalnızca medya), sol ve sağ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Medya sesi"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefon aramaları"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dosya aktarımı"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj işlemi optimize edildi"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Şarj ediliyor"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Tamamen dolacağı zaman: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olacağı zaman: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Tamamen şarj olacağı zaman: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Tamamen dolacağı zaman: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Şarj oldu"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Pilin Şarjı Tam"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Şarj işlemi beklemede"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Şarj"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Hızlı şarj"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Yönetici tarafından denetleniyor"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kısıtlanmış ayar tarafından kontrol ediliyor"</string>
     <string name="disabled" msgid="8017887509554714950">"Devre dışı"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon sinyali bir çubuk."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon sinyali iki çubuk."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon sinyali üç çubuk."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon sinyali dört çubuk."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon sinyali tam."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Veri yok."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Veri sinyali bir çubuk."</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index ac9edc5..4b40503 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без телефона), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без медіа), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> під’єднано (без телефона й медіа), заряд акумулятора – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Активовано, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Активний. Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> заряду акумулятора, П: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Заряд акумулятора: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> заряду акумулятора, П: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> заряду акумулятора"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Ліва частина: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Права частина: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активовано"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Збережено"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активовано, лише лівий"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активовано, лише правий"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активовано, лівий і правий"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Активно (лише для мультимедіа)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Підтримує надсилання аудіо"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Активно (лише для мультимедіа); лише лівий"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Активно (лише для мультимедіа); лише правий"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Активно (лише для мультимедіа); лівий і правий"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Звук медіафайлів"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Телефонні дзвінки"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Передавання файлів"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджання оптимізовано"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – заряджається"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Завершиться до <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Повністю зарядиться до <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Повністю зарядиться до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Завершиться до <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Заряджено"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Повністю заряджено"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Заряджання призупинено"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Заряджання"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Швидке заряджання"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Керується адміністратором"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Керується налаштуваннями з обмеженнями"</string>
     <string name="disabled" msgid="8017887509554714950">"Вимкнено"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Одна смужка сигналу телефону."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Дві смужки сигналу телефону."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Три смужки сигналу телефону."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Чотири смужки сигналу телефона."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Максимальний сигнал телефону."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Немає сигналу даних."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Одна смужка сигналу даних."</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index d2fc32a..a1b2198 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"منسلک ہے (فون کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"منسلک ہے (میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"منسلک ہے (فون یا میڈیا کے علاوہ)، بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"فعال، <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"فعال، بائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> بیٹری، دائیں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"بائيں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> بیٹری، دائیں: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> چھوڑ دیا"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"دائیں <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ ہے"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، صرف بائیں طرف"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، صرف دائیں طرف"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، صرف بائیں اور دائیں طرف"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"فعال (صرف میڈیا)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"آڈیو کے اشتراک کو سپورٹ کرتا ہے"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"فعال (صرف میڈیا)، صرف بائیں"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"فعال (صرف میڈیا)، صرف دائیں"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"فعال (صرف میڈیا)، بائیں اور دائیں"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"میڈيا آڈیو"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"فون کالز"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"فائل کی منتقلی"</string>
@@ -487,7 +493,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> تک"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"‫<xliff:g id="TIME">%1$s</xliff:g> تک"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"‫<xliff:g id="TIME">%1$s</xliff:g> تک بیٹری ختم ہو سکتی ہے"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"مکمل چارج ہونے میں <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ کو بہتر بنایا گیا"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارج ہو رہی ہے"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> تک مکمل ہو جائے گی"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تک مکمل چارج ہو جائے گی"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> تک مکمل چارج ہو جائے گی"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> تک مکمل ہو جائے گی"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"چارج ہو گئی"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"مکمل طور پر چارج ہو گئی"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"چارجنگ ہولڈ پر ہے"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"چارج ہو رہی ہے"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"فاسٹ چارجنگ"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"کنٹرول کردہ بذریعہ منتظم"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"محدود کردہ ترتیب کے زیر انتظام ہے"</string>
     <string name="disabled" msgid="8017887509554714950">"غیر فعال"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"فون کا ایک بار۔"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"فون کے دو بارز۔"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"فون کے تین بارز۔"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"فون کے سگنل میں چار بارز۔"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"فون سگنل پورا ہے۔"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"کوئی ڈیٹا نہیں ہے۔"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ڈیٹا کا ایک بار۔"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 3c8e249..82f4576 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefondan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefon yoki mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Faol, batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Faol, L: batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Chapda: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Oʻngda: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Faol"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saqlangan"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Faol, faqat chap"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Faol, faqat oʻng"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Faol, chap va oʻng"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Faol (faqat media uchun)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Audio yuborishi mumkin"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Faol (faqat media uchun), faqat chap"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Faol (faqat media uchun), faqat oʻng"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Faol (faqat media uchun), chap va oʻng"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"A2DP profili"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefon chaqiruvlari"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl uzatish"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Toʻlishiga <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash optimallashtirildi"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlanmoqda"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Toʻladi: <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - Toʻliq quvvatlanadi: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Toʻliq quvvatlanadi: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Toʻladi: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Quvvat oldi"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Toʻliq quvvatlandi"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Quvvatlash toʻxtatildi"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Quvvatlanmoqda"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Tezkor quvvatlash"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Administrator tomonidan boshqariladi"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Cheklangan sozlama tomonidan boshqariladi"</string>
     <string name="disabled" msgid="8017887509554714950">"Oʻchiq"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon bitta panelda."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon ikkita panelda."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon uchta panelda."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Telefon: toʻrtta ustun."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon signali to‘liq."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ma’lumotlar yo‘q."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Ma’lumotlar bitta panelda."</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index b3d70cc..9a1386e 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Đã kết nối (không có điện thoại), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Đã kết nối (không có phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Đã kết nối (không có điện thoại hoặc phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Đang hoạt động, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Đang hoạt động, Trái: Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Phải: Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Trái: Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Phải: Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Bên trái <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Bên phải <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Đang hoạt động"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Đã lưu"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Đang hoạt động, chỉ tai bên trái"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Đang hoạt động, chỉ tai phải"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Đang hoạt động, cả tai phải và tai trái"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Đang hoạt động (chỉ phát nội dung đa phương tiện)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Hỗ trợ tính năng chia sẻ âm thanh"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên trái"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Đang hoạt động (chỉ phát nội dung đa phương tiện), chỉ dùng tai nghe bên phải"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Đang hoạt động (chỉ phát nội dung đa phương tiện), đang dùng cả tai nghe bên trái và phải"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Âm thanh nội dung nghe nhìn"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Cuộc gọi điện thoại"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Chuyển tệp"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là pin đầy"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quá trình sạc được tối ưu hoá"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đang sạc"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATUS">%2$s</xliff:g> – Pin sẽ đầy vào <xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pin sẽ đầy vào <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Pin sẽ đầy vào <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Pin sẽ đầy vào <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Đã sạc"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Đã sạc đầy"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Đang tạm ngưng sạc"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Đang sạc"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Đang sạc nhanh"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Do quản trị viên kiểm soát"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Do chế độ Cài đặt hạn chế kiểm soát"</string>
     <string name="disabled" msgid="8017887509554714950">"Đã tắt"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Tín hiệu điện thoại một vạch."</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Tín hiệu điện thoại hai vạch."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tín hiệu điện thoại ba vạch."</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Tín hiệu điện thoại 4 vạch."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Tín hiệu điện thoại đầy đủ."</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Không có dữ liệu."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Tín hiệu dữ liệu một vạch."</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 6a9a18c..d3f8945 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"已连接(无手机信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"已连接(无媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"已连接(无手机或媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"使用中,电池电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"使用中,左:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 电量,右:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 电量"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 的电量"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"电池电量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"左:目前电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>;右:目前电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"左耳机电池电量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"右耳机电池电量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"已保存的设备"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,仅左耳助听器"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,仅右耳助听器"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳助听器"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"使用中(仅限媒体)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支持音频分享"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"使用中(仅限媒体),仅左侧"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"使用中(仅限媒体),仅右侧"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"使用中(仅限媒体),左侧和右侧"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"媒体音频"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"通话"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"文件传输"</string>
@@ -324,7 +330,7 @@
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"正在流式传输:<xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"专用 DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"选择专用 DNS 模式"</string>
-    <string name="private_dns_mode_off" msgid="7065962499349997041">"已关闭"</string>
+    <string name="private_dns_mode_off" msgid="7065962499349997041">"关闭"</string>
     <string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"自动"</string>
     <string name="private_dns_mode_provider" msgid="3619040641762557028">"专用 DNS 提供商主机名"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"输入 DNS 提供商的主机名"</string>
@@ -472,7 +478,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"“色彩校正”功能适用于以下情况:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;您想更准确地查看颜色&lt;/li&gt; &lt;li&gt;您想移除颜色以提高专注程度&lt;/li&gt; &lt;/ol&gt;"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"“色彩校正”功能适用于以下情况:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;您想更准确地查看颜色&lt;/li&gt; &lt;li&gt;您想移除颜色以提高专注度&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - 为保护电池,已暂停充电"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电方式已优化"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在充电"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> 前充满"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 前充满"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> 前充满"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> 前充满"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"已充满电"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"已充满电"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"充电已暂停"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"正在充电"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"正在快速充电"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"由管理员控制"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"由受限设置控制"</string>
     <string name="disabled" msgid="8017887509554714950">"已停用"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"手机信号强度为一格。"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"手机信号强度为两格。"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"手机信号强度为三格。"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"手机信号满格。"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"手机信号满格。"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"没有数据网络信号。"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"数据信号强度为一格。"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index ecdfa62..b5a1d51 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"已連接 (無手機音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"已連接 (無媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"已連接 (無手機或媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"使用中,電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"已啟用,左:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"左:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"左耳機:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"右耳機:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (只限媒體)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享功能"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (只限媒體)"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"右側啟用 (只限媒體)"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"右側同時啟用 (只限媒體)"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"媒體音效"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"通話"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充滿電"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已優化充電"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> ‑ 充電中"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - 在 <xliff:g id="TIME">%3$s</xliff:g>前充滿電"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • 在 <xliff:g id="TIME">%2$s</xliff:g>前充滿電"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"在 <xliff:g id="TIME">%1$s</xliff:g>前充滿電"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"在 <xliff:g id="TIME">%1$s</xliff:g>前充滿電"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"已充滿電"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"充電完成"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"目前暫停充電"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"充電中"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"快速充電"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"已由管理員停用"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"由「受限設定」控制"</string>
     <string name="disabled" msgid="8017887509554714950">"已停用"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電話訊號強度為一格。"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電話訊號強度為兩格。"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電話訊號強度為三格。"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"電話有四格。"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電話訊號滿格。"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"沒有數據網絡。"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"數據網絡訊號強度為一格。"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 99fe41e..a131c12 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"已連線 (無手機音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"已連線 (無媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"已連線 (無手機或媒體音訊),電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"使用中,電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"已啟用,左:目前電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右:目前電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"左:目前電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右:目前電量為 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"左耳機:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"右耳機:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"啟用 (僅限媒體)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"支援音訊分享"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"左側啟用 (僅限媒體)"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"右側啟用 (僅限媒體)"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"左右側同時啟用 (僅限媒體)"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"媒體音訊"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"通話"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電效能已最佳化"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電中"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - <xliff:g id="TIME">%3$s</xliff:g> 前充飽"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 前充飽"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"<xliff:g id="TIME">%1$s</xliff:g> 前充飽"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"<xliff:g id="TIME">%1$s</xliff:g> 前充飽"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"充電完成"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"充電完成"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"目前暫停充電"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"充電中"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"快速充電"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"已由管理員停用"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"由受限制的設定控管"</string>
     <string name="disabled" msgid="8017887509554714950">"已停用"</string>
@@ -555,7 +567,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>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電話訊號強度一格。"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電話訊號強度兩格。"</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電話訊號強度三格。"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"手機訊號滿格。"</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電話訊號滿格。"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"沒有數據網路。"</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"數據網路訊號強度一格。"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 6f06e1f..f9bdfbf 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -94,40 +94,46 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Ixhunyiwe (ayikho ifoni), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Ixhunyiwe (ayikho imidiya), ibhethri iku-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Ixhunyiwe (ayikho ifoni noma imidiya), ibhethri ngu-<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"Kuyasebenza, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Kuyasebenza, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ibhethri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri"</string>
+    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <skip />
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Ibhethri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ibhethri, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri"</string>
-    <string name="bluetooth_battery_level_untethered_left" msgid="2952823007648782646">"Kwesokunxele <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_battery_level_untethered_right" msgid="6525710737740083276">"Kwesokudla <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
+    <skip />
+    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
+    <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Iyasebenza"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Ilondoloziwe"</string>
     <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Iyasebenza, ngakwesokunxele kuphela"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Iyasebenza, ngakwesokudla kuphela"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Iyasebenza, ngakwesokunxele nakwesokudla"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (1164678961213251365) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (1345174295097854560) -->
+    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (8580950145907305436) -->
+    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (8534816721698743015) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (6605320955858788855) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (5717356160322149355) -->
+    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_no_battery_level (71106861912593126) -->
+    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
     <skip />
-    <!-- no translation found for bluetooth_saved_device_lea_support (7231323139968285768) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_active (1632152540901488645) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_right_active (3854140683042617230) -->
-    <skip />
-    <!-- no translation found for bluetooth_hearing_aid_media_only_left_and_right_active (1299913413062528417) -->
-    <skip />
+    <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Kuyasebenza (imidiya kuphela)"</string>
+    <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Isekela ukwabelana ngokuqoshiwe"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Iyasebenza (imidiya kuphela), ngakwesokunxele kuphela"</string>
+    <string name="bluetooth_hearing_aid_media_only_right_active" msgid="3854140683042617230">"Kuyasebenza (imidiya kuphela), ngakwesokudla kuphela"</string>
+    <string name="bluetooth_hearing_aid_media_only_left_and_right_active" msgid="1299913413062528417">"Kuyasebenza (imidiya kuphela), ngakwesokunxele nakwesokudla"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Umsindo wemidiya"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Amakholi efoni"</string>
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dlulisa ifayela"</string>
@@ -498,6 +504,10 @@
     <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string>
     <string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kuthuthukisiwe"</string>
     <string name="power_charging_future_paused" msgid="1809543660923642799">"Iku-<xliff:g id="LEVEL">%1$s</xliff:g> ‑ Iyashaja"</string>
+    <string name="power_fast_charging_duration_v2" msgid="3797735998640359490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATUS">%2$s</xliff:g> - Igcwala ngo-<xliff:g id="TIME">%3$s</xliff:g>"</string>
+    <string name="power_charging_duration_v2" msgid="2938998284074003248">"<xliff:g id="LEVEL">%1$s</xliff:g> • Ishajwe ngokugcwele ngo-<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only_v2" msgid="5358176435722950193">"Ishajwe ngokugcwele ngo-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_fast_charging_duration_only_v2" msgid="6270950195810579563">"Igcwala ngo-<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string>
@@ -509,6 +519,8 @@
     <string name="battery_info_status_full" msgid="1339002294876531312">"Kushajiwe"</string>
     <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Ishaje Ngokuphelele"</string>
     <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ukushaja kumisiwe"</string>
+    <string name="battery_info_status_charging_v2" msgid="6118522107222245505">"Iyashaja"</string>
+    <string name="battery_info_status_charging_fast_v2" msgid="1825439848151256589">"Ishaja ngokushesha"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kulawulwa umqondisi"</string>
     <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kulawulwe Isethingi Elikhawulelwe"</string>
     <string name="disabled" msgid="8017887509554714950">"Akusebenzi"</string>
@@ -695,6 +707,7 @@
     <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Ibha eyodwa yefoni"</string>
     <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Amabha amabilil efoni."</string>
     <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Amabha amathathu efoni"</string>
+    <string name="accessibility_phone_four_bars" msgid="4477202400261338403">"Amabha amane efoni."</string>
     <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Isiginali yefoni igcwele"</string>
     <string name="accessibility_no_data" msgid="4563181886936931008">"Ayikho idatha."</string>
     <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Idatha enye yebha"</string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 2bd4d02..ab04904 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -82,7 +82,6 @@
     <dimen name="add_a_photo_circled_padding">6dp</dimen>
     <dimen name="user_photo_size_in_user_info_dialog">112dp</dimen>
     <dimen name="add_a_photo_icon_size_in_user_info_dialog">32dp</dimen>
-    <dimen name="user_name_height_in_user_info_dialog">48sp</dimen>
 
     <!-- Minimum increment between density scales. -->
     <fraction name="display_density_min_scale_interval">9%</fraction>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 7e6b004..73c96d9 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -197,19 +197,23 @@
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level">Connected (no phone or media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string>
 
     <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_active_battery_level">Active, <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
+    <string name="bluetooth_active_battery_level">Active. <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level for untethered headset. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_active_battery_level_untethered">Active, L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
+    <string name="bluetooth_active_battery_level_untethered">Active. L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery.</string>
+    <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level for the left part of the untethered headset. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_active_battery_level_untethered_left">Active. L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
+    <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level  for the right part of the untethered headset. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_active_battery_level_untethered_right">Active. R: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_battery_level"><xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
     <!-- Connected devices settings. Message on TV when Bluetooth is connected but not in use, showing remote device battery level. [CHAR LIMIT=NONE] -->
     <string name="tv_bluetooth_battery_level">Battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for untethered headset. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_untethered">L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
+    <string name="bluetooth_battery_level_untethered">L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for the left part of the untethered headset. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_untethered_left">Left <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g></string>
+    <string name="bluetooth_battery_level_untethered_left">Left: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for the right part of the untethered headset. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_untethered_right">Right <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g></string>
+    <string name="bluetooth_battery_level_untethered_right">Right: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
     <!-- Connected devices settings. Message when Bluetooth is connected and active but no battery information, showing remote device status. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_active_no_battery_level">Active</string>
     <!-- Connected devices settings. Message shown when bluetooth device is disconnected but is a known, previously connected device [CHAR LIMIT=NONE] -->
@@ -223,17 +227,19 @@
     <string name="bluetooth_hearing_aid_left_and_right_active">Active, left and right</string>
 
     <!-- Connected devices settings. Message when Bluetooth is connected and active for media only, showing remote device status and battery level. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_active_media_only_battery_level">Active (media only), <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
+    <string name="bluetooth_active_media_only_battery_level">Active (media only). <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected and active for media only, showing remote device status and battery level for untethered headset. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_active_media_only_battery_level_untethered">Active (media only), L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
+    <string name="bluetooth_active_media_only_battery_level_untethered">Active (media only). L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level, supports audio sharing. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_lea_support">Connected (supports audio sharing), <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
+    <string name="bluetooth_battery_level_lea_support">Connected (supports audio sharing). <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for untethered headset, supports audio sharing. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_untethered_lea_support">Connected (supports audio sharing), L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
+    <string name="bluetooth_battery_level_untethered_lea_support">Connected (supports audio sharing). L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for the left part of the untethered headset, supports audio sharing. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_untethered_left_lea_support">Connected (supports audio sharing), left <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g></string>
+    <string name="bluetooth_battery_level_untethered_left_lea_support">Connected (supports audio sharing). Left: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery.</string>
     <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for the right part of the untethered headset, supports audio sharing. [CHAR LIMIT=NONE] -->
-    <string name="bluetooth_battery_level_untethered_right_lea_support">Connected (supports audio sharing), right <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g></string>
+    <string name="bluetooth_battery_level_untethered_right_lea_support">Connected (supports audio sharing). Right: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery.</string>
+    <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing no battery information, supports audio sharing. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_no_battery_level_lea_support">Connected (supports audio sharing)</string>
     <!-- Connected devices settings. Message when Bluetooth is connected and active for media only but no battery information, showing remote device status. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_active_media_only_no_battery_level">Active (media only)</string>
     <!-- Connected devices settings. Message shown when bluetooth device is disconnected but is a known, previously connected device, supports audio sharing [CHAR LIMIT=NONE] -->
@@ -1148,6 +1154,16 @@
     <!-- [CHAR_LIMIT=80] Label for battery charging future pause -->
     <string name="power_charging_future_paused"><xliff:g id="level">%1$s</xliff:g> - Charging</string>
 
+    <!-- [CHAR_LIMIT=40] Label for battery level when fast charging with duration. -->
+    <string name="power_fast_charging_duration_v2"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="status">%2$s</xliff:g> - Full by <xliff:g id="time">%3$s</xliff:g></string>
+    <!-- [CHAR_LIMIT=40] Label for battery level when non-fast charging with duration. -->
+    <string name="power_charging_duration_v2"><xliff:g id="level">%1$s</xliff:g> - Fully charged by <xliff:g id="time">%2$s</xliff:g></string>
+
+    <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging. -->
+    <string name="power_remaining_charging_duration_only_v2">Fully charged by <xliff:g id="time">%1$s</xliff:g></string>
+    <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging. -->
+    <string name="power_remaining_fast_charging_duration_only_v2">Full by <xliff:g id="time">%1$s</xliff:g></string>
+
     <!-- Battery Info screen. Value for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="battery_info_status_unknown">Unknown</string>
     <!-- [CHAR_LIMIT=20] Battery use screen.  Battery status shown in chart label when charging from an unknown source.  -->
@@ -1171,6 +1187,11 @@
     <!-- [CHAR_LIMIT=None] Battery Info screen. Value for a status item. A state which device charging on hold -->
     <string name="battery_info_status_charging_on_hold">Charging on hold</string>
 
+    <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging isn't fast. -->
+    <string name="battery_info_status_charging_v2">Charging</string>
+    <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging speed is fast. -->
+    <string name="battery_info_status_charging_fast_v2">Fast charging</string>
+
     <!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] -->
     <string name="disabled_by_admin_summary_text">Controlled by admin</string>
 
@@ -1658,6 +1679,8 @@
     <string name="accessibility_phone_two_bars">Phone two bars.</string>
     <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_phone_three_bars">Phone three bars.</string>
+    <!-- Content description of the phone signal when it is four bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_four_bars">Phone four bars.</string>
     <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_phone_signal_full">Phone signal full.</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
index ce466df..9073d28 100644
--- a/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
+++ b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
@@ -33,6 +33,59 @@
         R.string.accessibility_phone_signal_full
     };
 
+    /**
+     * @param level int in range [0-4] that describes the signal level
+     * @return the appropriate content description for that signal strength, or 0 if the param is
+     *         invalid
+     */
+    public static int getDescriptionForLevel(int level) {
+        if (level > 4 || level < 0) {
+            return 0;
+        }
+
+        return PHONE_SIGNAL_STRENGTH[level];
+    }
+
+    public static final int[] PHONE_SIGNAL_STRENGTH_INFLATED = {
+            PHONE_SIGNAL_STRENGTH_NONE,
+            R.string.accessibility_phone_one_bar,
+            R.string.accessibility_phone_two_bars,
+            R.string.accessibility_phone_three_bars,
+            R.string.accessibility_phone_four_bars,
+            R.string.accessibility_phone_signal_full
+    };
+
+    /**
+     * @param level int in range [0-5] that describes the inflated signal level
+     * @return the appropriate content description for that signal strength, or 0 if the param is
+     *         invalid
+     */
+    public static int getDescriptionForInflatedLevel(int level) {
+        if (level > 5 || level < 0) {
+            return 0;
+        }
+
+        return PHONE_SIGNAL_STRENGTH_INFLATED[level];
+    }
+
+    /**
+     * @param level int in range [0-5] that describes the inflated signal level
+     * @param numberOfLevels one of (4, 5) that describes the default number of levels, or the
+     *                       inflated number of levels. The level param should be relative to the
+     *                       number of levels. This won't do any inflation.
+     * @return the appropriate content description for that signal strength, or 0 if the param is
+     *         invalid
+     */
+    public static int getDescriptionForLevel(int level, int numberOfLevels) {
+        if (numberOfLevels == 5) {
+            return getDescriptionForLevel(level);
+        } else if (numberOfLevels == 6) {
+            return getDescriptionForInflatedLevel(level);
+        } else {
+            return 0;
+        }
+    }
+
     public static final int[] DATA_CONNECTION_STRENGTH = {
         R.string.accessibility_no_data,
         R.string.accessibility_data_one_bar,
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index e95a506..c2506d3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -65,6 +65,7 @@
 import com.android.launcher3.util.UserIconInfo;
 import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.settingslib.fuelgauge.BatteryUtils;
 import com.android.settingslib.utils.BuildCompatUtils;
 
 import java.util.List;
@@ -246,25 +247,23 @@
         } else {
             if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
                 if (compactStatus) {
-                    statusString = res.getString(R.string.battery_info_status_charging);
+                    statusString = getRegularChargingStatusString(res);
                 } else if (batteryStatus.isPluggedInWired()) {
                     switch (batteryStatus.getChargingSpeed(context)) {
                         case BatteryStatus.CHARGING_FAST:
-                            statusString =
-                                    res.getString(R.string.battery_info_status_charging_fast);
+                            statusString = getFastChargingStatusString(res);
                             break;
                         case BatteryStatus.CHARGING_SLOWLY:
-                            statusString =
-                                    res.getString(R.string.battery_info_status_charging_slow);
+                            statusString = getSlowChargingStatusString(res);
                             break;
                         default:
-                            statusString = res.getString(R.string.battery_info_status_charging);
+                            statusString = getRegularChargingStatusString(res);
                             break;
                     }
                 } else if (batteryStatus.isPluggedInDock()) {
-                    statusString = res.getString(R.string.battery_info_status_charging_dock);
+                    statusString = getDockChargingStatusString(res);
                 } else {
-                    statusString = res.getString(R.string.battery_info_status_charging_wireless);
+                    statusString = getWirelessChargingStatusString(res);
                 }
             } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
                 statusString = res.getString(R.string.battery_info_status_discharging);
@@ -276,6 +275,41 @@
         return statusString;
     }
 
+    private static String getFastChargingStatusString(Resources res) {
+        return res.getString(
+                BatteryUtils.isChargingStringV2Enabled()
+                        ? R.string.battery_info_status_charging_fast_v2
+                        : R.string.battery_info_status_charging_fast);
+    }
+
+    private static String getSlowChargingStatusString(Resources res) {
+        return res.getString(
+                BatteryUtils.isChargingStringV2Enabled()
+                        ? R.string.battery_info_status_charging_v2
+                        : R.string.battery_info_status_charging_slow);
+    }
+
+    private static String getRegularChargingStatusString(Resources res) {
+        return res.getString(
+                BatteryUtils.isChargingStringV2Enabled()
+                        ? R.string.battery_info_status_charging_v2
+                        : R.string.battery_info_status_charging);
+    }
+
+    private static String getWirelessChargingStatusString(Resources res) {
+        return res.getString(
+                BatteryUtils.isChargingStringV2Enabled()
+                        ? R.string.battery_info_status_charging_v2
+                        : R.string.battery_info_status_charging_wireless);
+    }
+
+    private static String getDockChargingStatusString(Resources res) {
+        return res.getString(
+                BatteryUtils.isChargingStringV2Enabled()
+                        ? R.string.battery_info_status_charging_v2
+                        : R.string.battery_info_status_charging_dock);
+    }
+
     public static ColorStateList getColorAccent(Context context) {
         return getColorAttr(context, android.R.attr.colorAccent);
     }
@@ -731,7 +765,11 @@
             return false;
         }
 
-        final List<UsbPort> usbPortList = context.getSystemService(UsbManager.class).getPorts();
+        final UsbManager usbManager = context.getSystemService(UsbManager.class);
+        if (usbManager == null) {
+            return false;
+        }
+        final List<UsbPort> usbPortList = usbManager.getPorts();
         if (usbPortList == null || usbPortList.isEmpty()) {
             return false;
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java b/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
index 4af9e3c..2f6d839 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
@@ -106,8 +106,7 @@
                 AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
                 Context authContext = context.createPackageContextAsUser(desc.packageName, 0,
                         mUserHandle);
-                icon = mContext.getPackageManager().getUserBadgedIcon(
-                        authContext.getDrawable(desc.iconId), mUserHandle);
+                icon = authContext.getDrawable(desc.iconId);
                 synchronized (mAccTypeIconCache) {
                     mAccTypeIconCache.put(accountType, icon);
                 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 56118da..06c41cb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -1993,6 +1993,40 @@
     };
 
     /**
+     * Displays a combined list with "downloaded" and "visible in launcher" apps which belong to a
+     * user which is either not in quiet mode or allows showing apps even when in quiet mode.
+     */
+    public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET = new AppFilter() {
+        @Override
+        public void init() {
+        }
+
+        @Override
+        public boolean filterApp(@NonNull AppEntry entry) {
+            if (entry.hideInQuietMode) {
+                return false;
+            }
+            if (AppUtils.isInstant(entry.info)) {
+                return false;
+            } else if (hasFlag(entry.info.flags, ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) {
+                return true;
+            } else if (!hasFlag(entry.info.flags, ApplicationInfo.FLAG_SYSTEM)) {
+                return true;
+            } else if (entry.hasLauncherEntry) {
+                return true;
+            } else if (hasFlag(entry.info.flags, ApplicationInfo.FLAG_SYSTEM) && entry.isHomeApp) {
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void refreshAppEntryOnRebuild(@NonNull AppEntry appEntry, boolean hideInQuietMode) {
+            appEntry.hideInQuietMode = hideInQuietMode;
+        }
+    };
+
+    /**
      * Displays a combined list with "downloaded" and "visible in launcher" apps only.
      */
     public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT = new AppFilter() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java b/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java
index f73081a..169c330 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/RecentAppOpsAccess.java
@@ -51,6 +51,7 @@
     };
     private static final int[] MICROPHONE_OPS = new int[]{
             AppOpsManager.OP_RECORD_AUDIO,
+            AppOpsManager.OP_PHONE_CALL_MICROPHONE,
     };
     private static final int[] CAMERA_OPS = new int[]{
             AppOpsManager.OP_CAMERA,
@@ -144,6 +145,11 @@
             if (!showSystemApps) {
                 for (int op : mOps) {
                     final String permission = AppOpsManager.opToPermission(op);
+                    if (permission == null) {
+                        // Some ops like OP_PHONE_CALL_MICROPHONE don't have corresponding
+                        // permissions. No need to check in this case.
+                        continue;
+                    }
                     final int permissionFlags = mPackageManager.getPermissionFlags(permission,
                             packageName,
                             user);
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
index 6b833cc..0282f03 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.applications;
 
+import android.annotation.NonNull;
 import android.app.usage.StorageStats;
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
@@ -25,6 +26,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import java.io.IOException;
+import java.util.UUID;
 
 /**
  * StorageStatsSource wraps the StorageStatsManager for testability purposes.
@@ -59,6 +61,10 @@
         return mStorageStatsManager.getCacheQuotaBytes(volumeUuid, uid);
     }
 
+    public long getTotalBytes(@NonNull UUID storageUuid) throws IOException {
+        return mStorageStatsManager.getTotalBytes(storageUuid);
+    }
+
     /**
      * Static class that provides methods for querying the amount of external storage available as
      * well as breaking it up into several media types.
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 0996d52..e926b16 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -57,6 +57,7 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final LocalBluetoothAdapter mLocalAdapter;
+    private final LocalBluetoothManager mBtManager;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter;
     private final Map<String, Handler> mHandlerMap;
@@ -80,10 +81,15 @@
      * userHandle passed in is {@code null}, we register event receiver for the
      * {@code context.getUser()} handle.
      */
-    BluetoothEventManager(LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager, Context context,
-            android.os.Handler handler, @Nullable UserHandle userHandle) {
+    BluetoothEventManager(
+            LocalBluetoothAdapter adapter,
+            LocalBluetoothManager btManager,
+            CachedBluetoothDeviceManager deviceManager,
+            Context context,
+            android.os.Handler handler,
+            @Nullable UserHandle userHandle) {
         mLocalAdapter = adapter;
+        mBtManager = btManager;
         mDeviceManager = deviceManager;
         mAdapterIntentFilter = new IntentFilter();
         mProfileIntentFilter = new IntentFilter();
@@ -210,11 +216,27 @@
         }
     }
 
-    void dispatchProfileConnectionStateChanged(@NonNull CachedBluetoothDevice device, int state,
-            int bluetoothProfile) {
+    void dispatchProfileConnectionStateChanged(
+            @NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) {
         for (BluetoothCallback callback : mCallbacks) {
             callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
         }
+
+        // Trigger updateFallbackActiveDeviceIfNeeded when ASSISTANT profile disconnected when
+        // audio sharing is enabled.
+        if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT
+                && state == BluetoothAdapter.STATE_DISCONNECTED
+                && BluetoothUtils.isAudioSharingEnabled()) {
+            LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+            if (profileManager != null
+                    && profileManager.getLeAudioBroadcastProfile() != null
+                    && profileManager.getLeAudioBroadcastProfile().isProfileReady()
+                    && profileManager.getLeAudioBroadcastAssistantProfile() != null
+                    && profileManager.getLeAudioBroadcastAssistantProfile().isProfileReady()) {
+                Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, ASSISTANT profile disconnected");
+                profileManager.getLeAudioBroadcastProfile().updateFallbackActiveDeviceIfNeeded();
+            }
+        }
     }
 
     private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
@@ -536,7 +558,6 @@
                 default:
                     Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
                     return;
-
             }
             dispatchAclStateChanged(activeDevice, state);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 57fcc74..3dffb27 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -3,10 +3,13 @@
 import static com.android.settingslib.widget.AdaptiveOutlineDrawable.ICON_TYPE_ADVANCED;
 
 import android.annotation.SuppressLint;
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -30,6 +33,7 @@
 import androidx.core.graphics.drawable.IconCompat;
 
 import com.android.settingslib.R;
+import com.android.settingslib.flags.Flags;
 import com.android.settingslib.widget.AdaptiveIcon;
 import com.android.settingslib.widget.AdaptiveOutlineDrawable;
 
@@ -46,14 +50,14 @@
     private static final String TAG = "BluetoothUtils";
 
     public static final boolean V = false; // verbose logging
-    public static final boolean D = true;  // regular logging
+    public static final boolean D = true; // regular logging
 
     public static final int META_INT_ERROR = -1;
     public static final String BT_ADVANCED_HEADER_ENABLED = "bt_advanced_header_enabled";
     private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
     private static final String KEY_HEARABLE_CONTROL_SLICE = "HEARABLE_CONTROL_SLICE_WITH_WIDTH";
-    private static final Set<String> EXCLUSIVE_MANAGERS = ImmutableSet.of(
-            "com.google.android.gms.dck");
+    private static final Set<String> EXCLUSIVE_MANAGERS =
+            ImmutableSet.of("com.google.android.gms.dck");
 
     private static ErrorListener sErrorListener;
 
@@ -89,23 +93,23 @@
     /**
      * @param context to access resources from
      * @param cachedDevice to get class from
-     * @return pair containing the drawable and the description of the Bluetooth class
-     *         of the device.
+     * @return pair containing the drawable and the description of the Bluetooth class of the
+     *     device.
      */
-    public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
-            CachedBluetoothDevice cachedDevice) {
+    public static Pair<Drawable, String> getBtClassDrawableWithDescription(
+            Context context, CachedBluetoothDevice cachedDevice) {
         BluetoothClass btClass = cachedDevice.getBtClass();
         if (btClass != null) {
             switch (btClass.getMajorDeviceClass()) {
                 case BluetoothClass.Device.Major.COMPUTER:
-                    return new Pair<>(getBluetoothDrawable(context,
-                            com.android.internal.R.drawable.ic_bt_laptop),
+                    return new Pair<>(
+                            getBluetoothDrawable(
+                                    context, com.android.internal.R.drawable.ic_bt_laptop),
                             context.getString(R.string.bluetooth_talkback_computer));
 
                 case BluetoothClass.Device.Major.PHONE:
                     return new Pair<>(
-                            getBluetoothDrawable(context,
-                                    com.android.internal.R.drawable.ic_phone),
+                            getBluetoothDrawable(context, com.android.internal.R.drawable.ic_phone),
                             context.getString(R.string.bluetooth_talkback_phone));
 
                 case BluetoothClass.Device.Major.PERIPHERAL:
@@ -115,8 +119,8 @@
 
                 case BluetoothClass.Device.Major.IMAGING:
                     return new Pair<>(
-                            getBluetoothDrawable(context,
-                                    com.android.internal.R.drawable.ic_settings_print),
+                            getBluetoothDrawable(
+                                    context, com.android.internal.R.drawable.ic_settings_print),
                             context.getString(R.string.bluetooth_talkback_imaging));
 
                 default:
@@ -125,8 +129,9 @@
         }
 
         if (cachedDevice.isHearingAidDevice()) {
-            return new Pair<>(getBluetoothDrawable(context,
-                    com.android.internal.R.drawable.ic_bt_hearing_aid),
+            return new Pair<>(
+                    getBluetoothDrawable(
+                            context, com.android.internal.R.drawable.ic_bt_hearing_aid),
                     context.getString(R.string.bluetooth_talkback_hearing_aids));
         }
 
@@ -138,7 +143,8 @@
                 // The device should show hearing aid icon if it contains any hearing aid related
                 // profiles
                 if (profile instanceof HearingAidProfile || profile instanceof HapClientProfile) {
-                    return new Pair<>(getBluetoothDrawable(context, profileResId),
+                    return new Pair<>(
+                            getBluetoothDrawable(context, profileResId),
                             context.getString(R.string.bluetooth_talkback_hearing_aids));
                 }
                 if (resId == 0) {
@@ -153,42 +159,40 @@
         if (btClass != null) {
             if (doesClassMatch(btClass, BluetoothClass.PROFILE_HEADSET)) {
                 return new Pair<>(
-                        getBluetoothDrawable(context,
-                                com.android.internal.R.drawable.ic_bt_headset_hfp),
+                        getBluetoothDrawable(
+                                context, com.android.internal.R.drawable.ic_bt_headset_hfp),
                         context.getString(R.string.bluetooth_talkback_headset));
             }
             if (doesClassMatch(btClass, BluetoothClass.PROFILE_A2DP)) {
                 return new Pair<>(
-                        getBluetoothDrawable(context,
-                                com.android.internal.R.drawable.ic_bt_headphones_a2dp),
+                        getBluetoothDrawable(
+                                context, com.android.internal.R.drawable.ic_bt_headphones_a2dp),
                         context.getString(R.string.bluetooth_talkback_headphone));
             }
         }
         return new Pair<>(
-                getBluetoothDrawable(context,
-                        com.android.internal.R.drawable.ic_settings_bluetooth).mutate(),
+                getBluetoothDrawable(context, com.android.internal.R.drawable.ic_settings_bluetooth)
+                        .mutate(),
                 context.getString(R.string.bluetooth_talkback_bluetooth));
     }
 
-    /**
-     * Get bluetooth drawable by {@code resId}
-     */
+    /** Get bluetooth drawable by {@code resId} */
     public static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId) {
         return context.getDrawable(resId);
     }
 
-    /**
-     * Get colorful bluetooth icon with description
-     */
-    public static Pair<Drawable, String> getBtRainbowDrawableWithDescription(Context context,
-            CachedBluetoothDevice cachedDevice) {
+    /** Get colorful bluetooth icon with description */
+    public static Pair<Drawable, String> getBtRainbowDrawableWithDescription(
+            Context context, CachedBluetoothDevice cachedDevice) {
         final Resources resources = context.getResources();
-        final Pair<Drawable, String> pair = BluetoothUtils.getBtDrawableWithDescription(context,
-                cachedDevice);
+        final Pair<Drawable, String> pair =
+                BluetoothUtils.getBtDrawableWithDescription(context, cachedDevice);
 
         if (pair.first instanceof BitmapDrawable) {
-            return new Pair<>(new AdaptiveOutlineDrawable(
-                    resources, ((BitmapDrawable) pair.first).getBitmap()), pair.second);
+            return new Pair<>(
+                    new AdaptiveOutlineDrawable(
+                            resources, ((BitmapDrawable) pair.first).getBitmap()),
+                    pair.second);
         }
 
         int hashCode;
@@ -198,15 +202,12 @@
             hashCode = cachedDevice.getAddress().hashCode();
         }
 
-        return new Pair<>(buildBtRainbowDrawable(context,
-                pair.first, hashCode), pair.second);
+        return new Pair<>(buildBtRainbowDrawable(context, pair.first, hashCode), pair.second);
     }
 
-    /**
-     * Build Bluetooth device icon with rainbow
-     */
-    private static Drawable buildBtRainbowDrawable(Context context, Drawable drawable,
-            int hashCode) {
+    /** Build Bluetooth device icon with rainbow */
+    private static Drawable buildBtRainbowDrawable(
+            Context context, Drawable drawable, int hashCode) {
         final Resources resources = context.getResources();
 
         // Deal with normal headset
@@ -222,38 +223,37 @@
         return adaptiveIcon;
     }
 
-    /**
-     * Get bluetooth icon with description
-     */
-    public static Pair<Drawable, String> getBtDrawableWithDescription(Context context,
-            CachedBluetoothDevice cachedDevice) {
-        final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
-                context, cachedDevice);
+    /** Get bluetooth icon with description */
+    public static Pair<Drawable, String> getBtDrawableWithDescription(
+            Context context, CachedBluetoothDevice cachedDevice) {
+        final Pair<Drawable, String> pair =
+                BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice);
         final BluetoothDevice bluetoothDevice = cachedDevice.getDevice();
-        final int iconSize = context.getResources().getDimensionPixelSize(
-                R.dimen.bt_nearby_icon_size);
+        final int iconSize =
+                context.getResources().getDimensionPixelSize(R.dimen.bt_nearby_icon_size);
         final Resources resources = context.getResources();
 
         // Deal with advanced device icon
         if (isAdvancedDetailsHeader(bluetoothDevice)) {
-            final Uri iconUri = getUriMetaData(bluetoothDevice,
-                    BluetoothDevice.METADATA_MAIN_ICON);
+            final Uri iconUri = getUriMetaData(bluetoothDevice, BluetoothDevice.METADATA_MAIN_ICON);
             if (iconUri != null) {
                 try {
-                    context.getContentResolver().takePersistableUriPermission(iconUri,
-                            Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                    context.getContentResolver()
+                            .takePersistableUriPermission(
+                                    iconUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 } catch (SecurityException e) {
                     Log.e(TAG, "Failed to take persistable permission for: " + iconUri, e);
                 }
                 try {
-                    final Bitmap bitmap = MediaStore.Images.Media.getBitmap(
-                            context.getContentResolver(), iconUri);
+                    final Bitmap bitmap =
+                            MediaStore.Images.Media.getBitmap(
+                                    context.getContentResolver(), iconUri);
                     if (bitmap != null) {
-                        final Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, iconSize,
-                                iconSize, false);
+                        final Bitmap resizedBitmap =
+                                Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, false);
                         bitmap.recycle();
-                        return new Pair<>(new BitmapDrawable(resources,
-                                resizedBitmap), pair.second);
+                        return new Pair<>(
+                                new BitmapDrawable(resources, resizedBitmap), pair.second);
                     }
                 } catch (IOException e) {
                     Log.e(TAG, "Failed to get drawable for: " + iconUri, e);
@@ -280,8 +280,8 @@
             return true;
         }
         // The metadata is for Android S
-        String deviceType = getStringMetaData(bluetoothDevice,
-                BluetoothDevice.METADATA_DEVICE_TYPE);
+        String deviceType =
+                getStringMetaData(bluetoothDevice, BluetoothDevice.METADATA_DEVICE_TYPE);
         if (TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET)
                 || TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_WATCH)
                 || TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_DEFAULT)
@@ -306,8 +306,8 @@
             return true;
         }
         // The metadata is for Android S
-        String deviceType = getStringMetaData(bluetoothDevice,
-                BluetoothDevice.METADATA_DEVICE_TYPE);
+        String deviceType =
+                getStringMetaData(bluetoothDevice, BluetoothDevice.METADATA_DEVICE_TYPE);
         if (TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET)) {
             Log.d(TAG, "isAdvancedUntetheredDevice: is untethered device ");
             return true;
@@ -321,15 +321,15 @@
      * @param device Must be one of the public constants in {@link BluetoothClass.Device}
      * @return true if device class matches, false otherwise.
      */
-    public static boolean isDeviceClassMatched(@NonNull BluetoothDevice bluetoothDevice,
-            int device) {
+    public static boolean isDeviceClassMatched(
+            @NonNull BluetoothDevice bluetoothDevice, int device) {
         final BluetoothClass bluetoothClass = bluetoothDevice.getBluetoothClass();
         return bluetoothClass != null && bluetoothClass.getDeviceClass() == device;
     }
 
     private static boolean isAdvancedHeaderEnabled() {
-        if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI, BT_ADVANCED_HEADER_ENABLED,
-                true)) {
+        if (!DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_SETTINGS_UI, BT_ADVANCED_HEADER_ENABLED, true)) {
             Log.d(TAG, "isAdvancedDetailsHeader: advancedEnabled is false");
             return false;
         }
@@ -345,9 +345,7 @@
         return false;
     }
 
-    /**
-     * Create an Icon pointing to a drawable.
-     */
+    /** Create an Icon pointing to a drawable. */
     public static IconCompat createIconWithDrawable(Drawable drawable) {
         Bitmap bitmap;
         if (drawable instanceof BitmapDrawable) {
@@ -355,19 +353,15 @@
         } else {
             final int width = drawable.getIntrinsicWidth();
             final int height = drawable.getIntrinsicHeight();
-            bitmap = createBitmap(drawable,
-                    width > 0 ? width : 1,
-                    height > 0 ? height : 1);
+            bitmap = createBitmap(drawable, width > 0 ? width : 1, height > 0 ? height : 1);
         }
         return IconCompat.createWithBitmap(bitmap);
     }
 
-    /**
-     * Build device icon with advanced outline
-     */
+    /** Build device icon with advanced outline */
     public static Drawable buildAdvancedDrawable(Context context, Drawable drawable) {
-        final int iconSize = context.getResources().getDimensionPixelSize(
-                R.dimen.advanced_icon_size);
+        final int iconSize =
+                context.getResources().getDimensionPixelSize(R.dimen.advanced_icon_size);
         final Resources resources = context.getResources();
 
         Bitmap bitmap = null;
@@ -376,14 +370,12 @@
         } else {
             final int width = drawable.getIntrinsicWidth();
             final int height = drawable.getIntrinsicHeight();
-            bitmap = createBitmap(drawable,
-                    width > 0 ? width : 1,
-                    height > 0 ? height : 1);
+            bitmap = createBitmap(drawable, width > 0 ? width : 1, height > 0 ? height : 1);
         }
 
         if (bitmap != null) {
-            final Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, iconSize,
-                    iconSize, false);
+            final Bitmap resizedBitmap =
+                    Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, false);
             bitmap.recycle();
             return new AdaptiveOutlineDrawable(resources, resizedBitmap, ICON_TYPE_ADVANCED);
         }
@@ -391,9 +383,7 @@
         return drawable;
     }
 
-    /**
-     * Creates a drawable with specified width and height.
-     */
+    /** Creates a drawable with specified width and height. */
     public static Bitmap createBitmap(Drawable drawable, int width, int height) {
         final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         final Canvas canvas = new Canvas(bitmap);
@@ -487,11 +477,8 @@
     }
 
     /**
-     * Check if the Bluetooth device is an AvailableMediaBluetoothDevice, which means:
-     * 1) currently connected
-     * 2) is Hearing Aid or LE Audio
-     *    OR
-     * 3) connected profile matches currentAudioProfile
+     * Check if the Bluetooth device is an AvailableMediaBluetoothDevice, which means: 1) currently
+     * connected 2) is Hearing Aid or LE Audio OR 3) connected profile matches currentAudioProfile
      *
      * @param cachedDevice the CachedBluetoothDevice
      * @param audioManager audio manager to get the current audio profile
@@ -519,8 +506,11 @@
             // It would show in Available Devices group.
             if (cachedDevice.isConnectedAshaHearingAidDevice()
                     || cachedDevice.isConnectedLeAudioDevice()) {
-                Log.d(TAG, "isFilterMatched() device : "
-                        + cachedDevice.getName() + ", the profile is connected.");
+                Log.d(
+                        TAG,
+                        "isFilterMatched() device : "
+                                + cachedDevice.getName()
+                                + ", the profile is connected.");
                 return true;
             }
             // According to the current audio profile type,
@@ -541,11 +531,84 @@
         return isFilterMatched;
     }
 
+    /** Returns if the le audio sharing is enabled. */
+    public static boolean isAudioSharingEnabled() {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        try {
+            return Flags.enableLeAudioSharing()
+                    && adapter.isLeAudioBroadcastSourceSupported()
+                            == BluetoothStatusCodes.FEATURE_SUPPORTED
+                    && adapter.isLeAudioBroadcastAssistantSupported()
+                            == BluetoothStatusCodes.FEATURE_SUPPORTED;
+        } catch (IllegalStateException e) {
+            Log.d(TAG, "LE state is on, but there is no bluetooth service.", e);
+            return false;
+        }
+    }
+
+    /** Returns if the broadcast is on-going. */
+    @WorkerThread
+    public static boolean isBroadcasting(@Nullable LocalBluetoothManager manager) {
+        if (manager == null) return false;
+        LocalBluetoothLeBroadcast broadcast =
+                manager.getProfileManager().getLeAudioBroadcastProfile();
+        return broadcast != null && broadcast.isEnabled(null);
+    }
+
     /**
-     * Checks if the Bluetooth device is an available hearing device, which means:
-     * 1) currently connected
-     * 2) is Hearing Aid
-     * 3) connected profile match hearing aid related profiles (e.g. ASHA, HAP)
+     * Check if {@link CachedBluetoothDevice} has connected to a broadcast source.
+     *
+     * @param cachedDevice The cached bluetooth device to check.
+     * @param localBtManager The BT manager to provide BT functions.
+     * @return Whether the device has connected to a broadcast source.
+     */
+    @WorkerThread
+    public static boolean hasConnectedBroadcastSource(
+            CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager) {
+        if (localBtManager == null) {
+            Log.d(TAG, "Skip check hasConnectedBroadcastSource due to bt manager is null");
+            return false;
+        }
+        LocalBluetoothLeBroadcastAssistant assistant =
+                localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+        if (assistant == null) {
+            Log.d(TAG, "Skip check hasConnectedBroadcastSource due to assistant profile is null");
+            return false;
+        }
+        List<BluetoothLeBroadcastReceiveState> sourceList =
+                assistant.getAllSources(cachedDevice.getDevice());
+        if (!sourceList.isEmpty() && sourceList.stream().anyMatch(BluetoothUtils::isConnected)) {
+            Log.d(
+                    TAG,
+                    "Lead device has connected broadcast source, device = "
+                            + cachedDevice.getDevice().getAnonymizedAddress());
+            return true;
+        }
+        // Return true if member device is in broadcast.
+        for (CachedBluetoothDevice device : cachedDevice.getMemberDevice()) {
+            List<BluetoothLeBroadcastReceiveState> list =
+                    assistant.getAllSources(device.getDevice());
+            if (!list.isEmpty() && list.stream().anyMatch(BluetoothUtils::isConnected)) {
+                Log.d(
+                        TAG,
+                        "Member device has connected broadcast source, device = "
+                                + device.getDevice().getAnonymizedAddress());
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Checks the connectivity status based on the provided broadcast receive state. */
+    @WorkerThread
+    public static boolean isConnected(BluetoothLeBroadcastReceiveState state) {
+        return state.getBisSyncState().stream().anyMatch(bitmap -> bitmap != 0);
+    }
+
+    /**
+     * Checks if the Bluetooth device is an available hearing device, which means: 1) currently
+     * connected 2) is Hearing Aid 3) connected profile match hearing aid related profiles (e.g.
+     * ASHA, HAP)
      *
      * @param cachedDevice the CachedBluetoothDevice
      * @return if the device is Available hearing device
@@ -553,19 +616,20 @@
     @WorkerThread
     public static boolean isAvailableHearingDevice(CachedBluetoothDevice cachedDevice) {
         if (isDeviceConnected(cachedDevice) && cachedDevice.isConnectedHearingAidDevice()) {
-            Log.d(TAG, "isFilterMatched() device : "
-                    + cachedDevice.getName() + ", the profile is connected.");
+            Log.d(
+                    TAG,
+                    "isFilterMatched() device : "
+                            + cachedDevice.getName()
+                            + ", the profile is connected.");
             return true;
         }
         return false;
     }
 
     /**
-     * Check if the Bluetooth device is a ConnectedBluetoothDevice, which means:
-     * 1) currently connected
-     * 2) is not Hearing Aid or LE Audio
-     *    AND
-     * 3) connected profile does not match currentAudioProfile
+     * Check if the Bluetooth device is a ConnectedBluetoothDevice, which means: 1) currently
+     * connected 2) is not Hearing Aid or LE Audio AND 3) connected profile does not match
+     * currentAudioProfile
      *
      * @param cachedDevice the CachedBluetoothDevice
      * @param audioManager audio manager to get the current audio profile
@@ -675,29 +739,28 @@
     }
 
     /**
-     * Returns the BluetoothDevice's exclusive manager
-     * ({@link BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata) if it exists and is in the
-     * given set, otherwise null.
+     * Returns the BluetoothDevice's exclusive manager ({@link
+     * BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata) if it exists and is in the given
+     * set, otherwise null.
      */
     @Nullable
     private static String getAllowedExclusiveManager(BluetoothDevice bluetoothDevice) {
-        byte[] exclusiveManagerNameBytes = bluetoothDevice.getMetadata(
-                BluetoothDevice.METADATA_EXCLUSIVE_MANAGER);
+        byte[] exclusiveManagerNameBytes =
+                bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER);
         if (exclusiveManagerNameBytes == null) {
-            Log.d(TAG, "Bluetooth device " + bluetoothDevice.getName()
-                    + " doesn't have exclusive manager");
+            Log.d(
+                    TAG,
+                    "Bluetooth device "
+                            + bluetoothDevice.getName()
+                            + " doesn't have exclusive manager");
             return null;
         }
         String exclusiveManagerName = new String(exclusiveManagerNameBytes);
-        return getExclusiveManagers().contains(exclusiveManagerName) ? exclusiveManagerName
-                : null;
+        return getExclusiveManagers().contains(exclusiveManagerName) ? exclusiveManagerName : null;
     }
 
-    /**
-     * Checks if given package is installed
-     */
-    private static boolean isPackageInstalled(Context context,
-            String packageName) {
+    /** Checks if given package is installed */
+    private static boolean isPackageInstalled(Context context, String packageName) {
         PackageManager packageManager = context.getPackageManager();
         try {
             packageManager.getPackageInfo(packageName, 0);
@@ -709,13 +772,12 @@
     }
 
     /**
-     * A BluetoothDevice is exclusively managed if
-     * 1) it has field {@link BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata.
-     * 2) the exclusive manager app name is in the allowlist.
-     * 3) the exclusive manager app is installed.
+     * A BluetoothDevice is exclusively managed if 1) it has field {@link
+     * BluetoothDevice.METADATA_EXCLUSIVE_MANAGER} in metadata. 2) the exclusive manager app name is
+     * in the allowlist. 3) the exclusive manager app is installed.
      */
-    public static boolean isExclusivelyManagedBluetoothDevice(@NonNull Context context,
-            @NonNull BluetoothDevice bluetoothDevice) {
+    public static boolean isExclusivelyManagedBluetoothDevice(
+            @NonNull Context context, @NonNull BluetoothDevice bluetoothDevice) {
         String exclusiveManagerName = getAllowedExclusiveManager(bluetoothDevice);
         if (exclusiveManagerName == null) {
             return false;
@@ -728,11 +790,32 @@
         }
     }
 
-    /**
-     * Return the allowlist for exclusive manager names.
-     */
+    /** Return the allowlist for exclusive manager names. */
     @NonNull
     public static Set<String> getExclusiveManagers() {
         return EXCLUSIVE_MANAGERS;
     }
+
+    /**
+     * Get CSIP group id for {@link CachedBluetoothDevice}.
+     *
+     * <p>If CachedBluetoothDevice#getGroupId is invalid, fetch group id from
+     * LeAudioProfile#getGroupId.
+     */
+    public static int getGroupId(@NonNull CachedBluetoothDevice cachedDevice) {
+        int groupId = cachedDevice.getGroupId();
+        String anonymizedAddress = cachedDevice.getDevice().getAnonymizedAddress();
+        if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+            Log.d(TAG, "getGroupId by CSIP profile for device: " + anonymizedAddress);
+            return groupId;
+        }
+        for (LocalBluetoothProfile profile : cachedDevice.getProfiles()) {
+            if (profile instanceof LeAudioProfile) {
+                Log.d(TAG, "getGroupId by LEA profile for device: " + anonymizedAddress);
+                return ((LeAudioProfile) profile).getGroupId(cachedDevice.getDevice());
+            }
+        }
+        Log.d(TAG, "getGroupId return invalid id for device: " + anonymizedAddress);
+        return BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 4777b0d..a7b7da5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -16,7 +16,10 @@
 
 package com.android.settingslib.bluetooth;
 
+import static com.android.settingslib.flags.Flags.enableSetPreferredTransportForLeAudioDevice;
+
 import android.annotation.CallbackExecutor;
+import android.annotation.StringRes;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCsipSetCoordinator;
@@ -35,6 +38,7 @@
 import android.os.Message;
 import android.os.ParcelUuid;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
@@ -43,6 +47,7 @@
 import android.util.Pair;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.util.ArrayUtils;
@@ -100,6 +105,7 @@
     private HearingAidInfo mHearingAidInfo;
     private int mGroupId;
     private Timestamp mBondTimestamp;
+    private LocalBluetoothManager mBluetoothManager;
 
     // Need this since there is no method for getting RSSI
     short mRssi;
@@ -288,6 +294,10 @@
                         mLocalNapRoleConnected = true;
                     }
                 }
+                if (enableSetPreferredTransportForLeAudioDevice()
+                        && profile instanceof HidProfile) {
+                    updatePreferredTransport();
+                }
             } else if (profile instanceof MapProfile
                     && newProfileState == BluetoothProfile.STATE_DISCONNECTED) {
                 profile.setEnabled(mDevice, false);
@@ -300,12 +310,34 @@
                 mLocalNapRoleConnected = false;
             }
 
+            if (enableSetPreferredTransportForLeAudioDevice()
+                    && profile instanceof LeAudioProfile) {
+                updatePreferredTransport();
+            }
+
             HearingAidStatsLogUtils.updateHistoryIfNeeded(mContext, this, profile, newProfileState);
         }
 
         fetchActiveDevices();
     }
 
+    private void updatePreferredTransport() {
+        if (mProfiles.stream().noneMatch(p -> p instanceof LeAudioProfile)
+                || mProfiles.stream().noneMatch(p -> p instanceof HidProfile)) {
+            return;
+        }
+        // Both LeAudioProfile and HidProfile are connectable.
+        if (!mProfileManager
+                .getHidProfile()
+                .setPreferredTransport(
+                        mDevice,
+                        mProfileManager.getLeAudioProfile().isEnabled(mDevice)
+                                ? BluetoothDevice.TRANSPORT_LE
+                                : BluetoothDevice.TRANSPORT_BREDR)) {
+            Log.w(TAG, "Fail to set preferred transport");
+        }
+    }
+
     @VisibleForTesting
     void setProfileConnectedStatus(int profileId, boolean isFailed) {
         switch (profileId) {
@@ -694,6 +726,25 @@
                 .orElse(BluetoothDevice.BATTERY_LEVEL_UNKNOWN);
     }
 
+    /**
+     * Get the lowest battery level from remote device and its member devices if it's greater than
+     * BluetoothDevice.BATTERY_LEVEL_UNKNOWN.
+     *
+     * <p>Android framework should only set mBatteryLevel to valid range [0-100],
+     * BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF, or BluetoothDevice.BATTERY_LEVEL_UNKNOWN, any
+     * other value should be a framework bug. Thus assume here that if value is greater than
+     * BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must be valid
+     *
+     * @return battery level in String [0-100] or Null if this lower than
+     *     BluetoothDevice.BATTERY_LEVEL_UNKNOWN
+     */
+    @Nullable
+    private String getValidMinBatteryLevelWithMemberDevices() {
+        final int batteryLevel = getMinBatteryLevelWithMemberDevices();
+        return batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN
+                ? com.android.settingslib.Utils.formatPercentage(batteryLevel)
+                : null;
+    }
 
     void refresh() {
         ListenableFuture<Void> future = ThreadUtils.getBackgroundExecutor().submit(() -> {
@@ -1166,22 +1217,148 @@
     }
 
     /**
-     * Return summary that describes connection state of this device. Summary depends on:
-     * 1. Whether device has battery info
-     * 2. Whether device is in active usage(or in phone call)
+     * Return summary that describes connection state of this device. Summary depends on: 1. Whether
+     * device has battery info 2. Whether device is in active usage(or in phone call) 3. Whether
+     * device is in audio sharing process
      *
      * @param shortSummary {@code true} if need to return short version summary
      */
     public String getConnectionSummary(boolean shortSummary) {
-        CharSequence summary = getConnectionSummary(shortSummary, false /* isTvSummary */,
-                SUMMARY_NO_COLOR_FOR_LOW_BATTERY);
-        if (summary != null) {
-            return summary.toString();
+        CharSequence summary = null;
+        if (BluetoothUtils.isAudioSharingEnabled()) {
+            if (mBluetoothManager == null) {
+                mBluetoothManager = LocalBluetoothManager.getInstance(mContext, null);
+            }
+            if (BluetoothUtils.isBroadcasting(mBluetoothManager)) {
+                summary = getBroadcastConnectionSummary(shortSummary);
+            }
+        }
+        if (summary == null) {
+            summary =
+                    getConnectionSummary(
+                            shortSummary,
+                            false /* isTvSummary */,
+                            SUMMARY_NO_COLOR_FOR_LOW_BATTERY);
+        }
+        return summary != null ? summary.toString() : null;
+    }
+
+    /**
+     * Returns the connection summary of this device during le audio sharing.
+     *
+     * @param shortSummary {@code true} if need to return short version summary
+     */
+    @Nullable
+    private String getBroadcastConnectionSummary(boolean shortSummary) {
+        if (isProfileConnectedFail() && isConnected()) {
+            return mContext.getString(R.string.profile_connect_timeout_subtext);
+        }
+
+        synchronized (mProfileLock) {
+            for (LocalBluetoothProfile profile : getProfiles()) {
+                int connectionStatus = getProfileConnectionState(profile);
+                if (connectionStatus == BluetoothProfile.STATE_CONNECTING
+                        || connectionStatus == BluetoothProfile.STATE_DISCONNECTING) {
+                    return mContext.getString(
+                            BluetoothUtils.getConnectionStateSummary(connectionStatus));
+                }
+            }
+        }
+
+        int leftBattery =
+                BluetoothUtils.getIntMetaData(
+                        mDevice, BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY);
+        int rightBattery =
+                BluetoothUtils.getIntMetaData(
+                        mDevice, BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY);
+        String batteryLevelPercentageString = getValidMinBatteryLevelWithMemberDevices();
+
+        if (mBluetoothManager == null) {
+            mBluetoothManager = LocalBluetoothManager.getInstance(mContext, null);
+        }
+        if (BluetoothUtils.hasConnectedBroadcastSource(this, mBluetoothManager)) {
+            // Gets summary for the buds which are in the audio sharing.
+            int groupId = BluetoothUtils.getGroupId(this);
+            if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
+                    && groupId
+                            == Settings.Secure.getInt(
+                                    mContext.getContentResolver(),
+                                    "bluetooth_le_broadcast_fallback_active_group_id",
+                                    BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) {
+                // The buds are primary buds
+                return getSummaryWithBatteryInfo(
+                        R.string.bluetooth_active_battery_level_untethered,
+                        R.string.bluetooth_active_battery_level,
+                        R.string.bluetooth_active_no_battery_level,
+                        leftBattery,
+                        rightBattery,
+                        batteryLevelPercentageString,
+                        shortSummary);
+            } else {
+                // The buds are not primary buds
+                return getSummaryWithBatteryInfo(
+                        R.string.bluetooth_active_media_only_battery_level_untethered,
+                        R.string.bluetooth_active_media_only_battery_level,
+                        R.string.bluetooth_active_media_only_no_battery_level,
+                        leftBattery,
+                        rightBattery,
+                        batteryLevelPercentageString,
+                        shortSummary);
+            }
+        } else {
+            // Gets summary for the buds which are not in the audio sharing.
+            if (getProfiles().stream()
+                    .anyMatch(
+                            profile ->
+                                    profile instanceof LeAudioProfile
+                                            && profile.isEnabled(getDevice()))) {
+                // The buds support le audio.
+                if (isConnected()) {
+                    return getSummaryWithBatteryInfo(
+                            R.string.bluetooth_battery_level_untethered_lea_support,
+                            R.string.bluetooth_battery_level_lea_support,
+                            R.string.bluetooth_no_battery_level_lea_support,
+                            leftBattery,
+                            rightBattery,
+                            batteryLevelPercentageString,
+                            shortSummary);
+                } else {
+                    return mContext.getString(R.string.bluetooth_saved_device_lea_support);
+                }
+            }
         }
         return null;
     }
 
     /**
+     * Returns the summary with correct format depending the battery info.
+     *
+     * @param untetheredBatteryResId resource id for untethered device with battery info
+     * @param batteryResId resource id for device with single battery info
+     * @param noBatteryResId resource id for device with no battery info
+     * @param shortSummary {@code true} if need to return short version summary
+     */
+    private String getSummaryWithBatteryInfo(
+            @StringRes int untetheredBatteryResId,
+            @StringRes int batteryResId,
+            @StringRes int noBatteryResId,
+            int leftBattery,
+            int rightBattery,
+            String batteryLevelPercentageString,
+            boolean shortSummary) {
+        if (isTwsBatteryAvailable(leftBattery, rightBattery) && !shortSummary) {
+            return mContext.getString(
+                    untetheredBatteryResId,
+                    Utils.formatPercentage(leftBattery),
+                    Utils.formatPercentage(rightBattery));
+        } else if (batteryLevelPercentageString != null && !shortSummary) {
+            return mContext.getString(batteryResId, batteryLevelPercentageString);
+        } else {
+            return mContext.getString(noBatteryResId);
+        }
+    }
+
+    /**
      * Returns android tv string that describes the connection state of this device.
      */
     public CharSequence getTvConnectionSummary() {
@@ -1258,18 +1435,7 @@
             }
         }
 
-        String batteryLevelPercentageString = null;
-        // Android framework should only set mBatteryLevel to valid range [0-100],
-        // BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF, or BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
-        // any other value should be a framework bug. Thus assume here that if value is greater
-        // than BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must be valid
-        final int batteryLevel = getMinBatteryLevelWithMemberDevices();
-        if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
-            // TODO: name com.android.settingslib.bluetooth.Utils something different
-            batteryLevelPercentageString =
-                    com.android.settingslib.Utils.formatPercentage(batteryLevel);
-        }
-
+        String batteryLevelPercentageString = getValidMinBatteryLevelWithMemberDevices();
         int stringRes = R.string.bluetooth_pairing;
         //when profile is connected, information would be available
         if (profileConnected) {
@@ -1310,30 +1476,13 @@
                     }
                 }
 
-                // Try to show left/right information if can not get it from battery for hearing
+                // Try to show left/right information for hearing
                 // aids specifically.
                 boolean isActiveAshaHearingAid = mIsActiveDeviceHearingAid;
                 boolean isActiveLeAudioHearingAid = mIsActiveDeviceLeAudio
                         && isConnectedHapClientDevice();
                 if (isActiveAshaHearingAid || isActiveLeAudioHearingAid) {
-                    final Set<CachedBluetoothDevice> memberDevices = getMemberDevice();
-                    final CachedBluetoothDevice subDevice = getSubDevice();
-                    if (memberDevices.stream().anyMatch(m -> m.isConnected())) {
-                        stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
-                    } else if (subDevice != null && subDevice.isConnected()) {
-                        stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
-                    } else {
-                        int deviceSide = getDeviceSide();
-                        if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT_AND_RIGHT) {
-                            stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
-                        } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT) {
-                            stringRes = R.string.bluetooth_hearing_aid_left_active;
-                        } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_RIGHT) {
-                            stringRes = R.string.bluetooth_hearing_aid_right_active;
-                        } else {
-                            stringRes = R.string.bluetooth_active_no_battery_level;
-                        }
-                    }
+                    return getHearingDeviceSummary(leftBattery, rightBattery, shortSummary);
                 }
             }
         }
@@ -1348,7 +1497,11 @@
                 || stringRes == R.string.bluetooth_active_battery_level_untethered
                 || stringRes == R.string.bluetooth_battery_level_untethered;
         if (isTvSummary && summaryIncludesBatteryLevel && Flags.enableTvMediaOutputDialog()) {
-            return getTvBatterySummary(batteryLevel, leftBattery, rightBattery, lowBatteryColorRes);
+            return getTvBatterySummary(
+                    getMinBatteryLevelWithMemberDevices(),
+                    leftBattery,
+                    rightBattery,
+                    lowBatteryColorRes);
         }
 
         if (isTwsBatteryAvailable(leftBattery, rightBattery)) {
@@ -1397,6 +1550,62 @@
         return spannableBuilder;
     }
 
+    private CharSequence getHearingDeviceSummary(int leftBattery, int rightBattery,
+            boolean shortSummary) {
+
+        CachedBluetoothDevice memberDevice = getMemberDevice().stream().filter(
+                CachedBluetoothDevice::isConnected).findFirst().orElse(null);
+        if (memberDevice == null && mSubDevice != null && mSubDevice.isConnected()) {
+            memberDevice = mSubDevice;
+        }
+
+        CachedBluetoothDevice leftDevice = null;
+        CachedBluetoothDevice rightDevice = null;
+        final int deviceSide = getDeviceSide();
+        if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT) {
+            leftDevice = this;
+            rightDevice = memberDevice;
+        } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_RIGHT) {
+            leftDevice = memberDevice;
+            rightDevice = this;
+        } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT_AND_RIGHT) {
+            leftDevice = this;
+            rightDevice = this;
+        }
+
+        if (leftBattery < 0 && leftDevice != null) {
+            leftBattery = leftDevice.getBatteryLevel();
+        }
+        if (rightBattery < 0 && rightDevice != null) {
+            rightBattery = rightDevice.getBatteryLevel();
+        }
+
+        if (leftDevice != null && rightDevice != null) {
+            if (leftBattery >= 0 && rightBattery >= 0 && !shortSummary) {
+                return mContext.getString(R.string.bluetooth_active_battery_level_untethered,
+                        Utils.formatPercentage(leftBattery), Utils.formatPercentage(rightBattery));
+            } else {
+                return mContext.getString(R.string.bluetooth_hearing_aid_left_and_right_active);
+            }
+        } else if (leftDevice != null) {
+            if (leftBattery >= 0 && !shortSummary) {
+                return mContext.getString(R.string.bluetooth_active_battery_level_untethered_left,
+                        Utils.formatPercentage(leftBattery));
+            } else {
+                return mContext.getString(R.string.bluetooth_hearing_aid_left_active);
+            }
+        } else if (rightDevice != null) {
+            if (rightBattery >= 0 && !shortSummary) {
+                return mContext.getString(R.string.bluetooth_active_battery_level_untethered_right,
+                        Utils.formatPercentage(rightBattery));
+            } else {
+                return mContext.getString(R.string.bluetooth_hearing_aid_right_active);
+            }
+        }
+
+        return mContext.getString(R.string.bluetooth_active_no_battery_level);
+    }
+
     private void addBatterySpan(SpannableStringBuilder builder,
             String batteryString, boolean lowBattery, int lowBatteryColorRes) {
         if (lowBattery && lowBatteryColorRes != SUMMARY_NO_COLOR_FOR_LOW_BATTERY) {
@@ -1765,4 +1974,9 @@
     boolean getUnpairing() {
         return mUnpairing;
     }
+
+    @VisibleForTesting
+    void setLocalBluetoothManager(LocalBluetoothManager bluetoothManager) {
+        mBluetoothManager = bluetoothManager;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 5b91ac9..b849d44 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -27,6 +27,8 @@
 import android.content.Context;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import com.android.settingslib.R;
 
 import java.util.List;
@@ -187,6 +189,14 @@
         }
     }
 
+    /** Set preferred transport for the device */
+    public boolean setPreferredTransport(@NonNull BluetoothDevice device, int transport) {
+        if (mService != null) {
+            mService.setPreferredTransport(device, transport);
+        }
+        return false;
+    }
+
     protected void finalize() {
         Log.d(TAG, "finalize()");
         if (mService != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
index 64cf5c64..a6b1dd3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
@@ -42,6 +42,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -78,6 +79,7 @@
     public static final String ACTION_LE_AUDIO_SHARING_STATE_CHANGE =
             "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_STATE_CHANGE";
     public static final String EXTRA_LE_AUDIO_SHARING_STATE = "BLUETOOTH_LE_AUDIO_SHARING_STATE";
+    public static final String EXTRA_BLUETOOTH_DEVICE = "BLUETOOTH_DEVICE";
     public static final int BROADCAST_STATE_UNKNOWN = 0;
     public static final int BROADCAST_STATE_ON = 1;
     public static final int BROADCAST_STATE_OFF = 2;
@@ -290,7 +292,6 @@
                                         + ", sourceId = "
                                         + sourceId);
                     }
-                    updateFallbackActiveDeviceIfNeeded();
                 }
 
                 @Override
@@ -312,7 +313,18 @@
                 public void onSourceAddFailed(
                         @NonNull BluetoothDevice sink,
                         @NonNull BluetoothLeBroadcastMetadata source,
-                        int reason) {}
+                        int reason) {
+                    if (DEBUG) {
+                        Log.d(
+                                TAG,
+                                "onSourceAddFailed(), sink = "
+                                        + sink
+                                        + ", reason = "
+                                        + reason
+                                        + ", source = "
+                                        + source);
+                    }
+                }
 
                 @Override
                 public void onSourceModified(
@@ -335,7 +347,6 @@
                                         + ", sourceId = "
                                         + sourceId);
                     }
-                    updateFallbackActiveDeviceIfNeeded();
                 }
 
                 @Override
@@ -368,6 +379,9 @@
                                         + ", state = "
                                         + state);
                     }
+                    if (BluetoothUtils.isConnected(state)) {
+                        updateFallbackActiveDeviceIfNeeded();
+                    }
                 }
             };
 
@@ -467,6 +481,15 @@
         mServiceBroadcast.startBroadcast(settings);
     }
 
+    /** Checks if the broadcast is playing. */
+    public boolean isPlaying(int broadcastId) {
+        if (mServiceBroadcast == null) {
+            Log.d(TAG, "check isPlaying failed, the BluetoothLeBroadcast is null.");
+            return false;
+        }
+        return mServiceBroadcast.isPlaying(broadcastId);
+    }
+
     private BluetoothLeBroadcastSettings buildBroadcastSettings(
             boolean isPublic,
             @Nullable String broadcastName,
@@ -1024,6 +1047,16 @@
 
     /** Update fallback active device if needed. */
     public void updateFallbackActiveDeviceIfNeeded() {
+        if (mServiceBroadcast == null) {
+            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to broadcast profile is null");
+            return;
+        }
+        List<BluetoothLeBroadcastMetadata> sources = mServiceBroadcast.getAllBroadcastMetadata();
+        if (sources.stream()
+                .noneMatch(source -> mServiceBroadcast.isPlaying(source.getBroadcastId()))) {
+            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to no broadcast ongoing");
+            return;
+        }
         if (mServiceBroadcastAssistant == null) {
             Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to assistant profile is null");
             return;
@@ -1036,7 +1069,9 @@
                                     List<BluetoothLeBroadcastReceiveState> sourceList =
                                             mServiceBroadcastAssistant.getAllSources(
                                                     bluetoothDevice);
-                                    return !sourceList.isEmpty();
+                                    return !sourceList.isEmpty()
+                                            && sourceList.stream()
+                                                    .anyMatch(BluetoothUtils::isConnected);
                                 })
                         .collect(Collectors.toList());
         if (devicesInSharing.isEmpty()) {
@@ -1071,7 +1106,8 @@
             return;
         }
         int fallbackActiveGroupId = getFallbackActiveGroupId();
-        if (getGroupId(targetCachedDevice) == fallbackActiveGroupId) {
+        if (fallbackActiveGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
+                && getGroupId(targetCachedDevice) == fallbackActiveGroupId) {
             Log.d(
                     TAG,
                     "Skip updateFallbackActiveDeviceIfNeeded, already is fallback: "
@@ -1081,12 +1117,6 @@
         targetCachedDevice.setActive();
     }
 
-    private boolean isDecryptedSource(BluetoothLeBroadcastReceiveState state) {
-        return state.getPaSyncState() == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED
-                && state.getBigEncryptionState()
-                        == BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING;
-    }
-
     private int getFallbackActiveGroupId() {
         return Settings.Secure.getInt(
                 mContext.getContentResolver(),
@@ -1116,10 +1146,19 @@
             Log.d(TAG, "Skip notifyBroadcastStateChange, not triggered by Settings.");
             return;
         }
+        if (isWorkProfile(mContext)) {
+            Log.d(TAG, "Skip notifyBroadcastStateChange, not triggered for work profile.");
+            return;
+        }
         Intent intent = new Intent(ACTION_LE_AUDIO_SHARING_STATE_CHANGE);
         intent.putExtra(EXTRA_LE_AUDIO_SHARING_STATE, state);
         intent.setPackage(mContext.getPackageName());
         Log.e(TAG, "notifyBroadcastStateChange for state = " + state);
         mContext.sendBroadcast(intent);
     }
+
+    private boolean isWorkProfile(Context context) {
+        UserManager userManager = context.getSystemService(UserManager.class);
+        return userManager != null && userManager.isManagedProfile();
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java
index 34c60a1..9faebe2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java
@@ -381,6 +381,14 @@
                 });
     }
 
+    /** Gets devices with matched connection states. */
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[] states) {
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
+        return mService.getDevicesMatchingConnectionStates(states);
+    }
+
     public boolean isEnabled(BluetoothDevice device) {
         if (mService == null || device == null) {
             return false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
index 53c6075..c4300d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
@@ -21,11 +21,11 @@
 import android.os.UserHandle;
 import android.util.Log;
 
-import java.lang.ref.WeakReference;
-
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresPermission;
 
+import java.lang.ref.WeakReference;
+
 /**
  * LocalBluetoothManager provides a simplified interface on top of a subset of
  * the Bluetooth API. Note that {@link #getInstance} will return null
@@ -111,10 +111,17 @@
         mContext = context.getApplicationContext();
         mLocalAdapter = adapter;
         mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, this);
-        mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext,
-                handler, userHandle);
-        mProfileManager = new LocalBluetoothProfileManager(mContext,
-                mLocalAdapter, mCachedDeviceManager, mEventManager);
+        mEventManager =
+                new BluetoothEventManager(
+                        mLocalAdapter,
+                        this,
+                        mCachedDeviceManager,
+                        mContext,
+                        handler,
+                        userHandle);
+        mProfileManager =
+                new LocalBluetoothProfileManager(
+                        mContext, mLocalAdapter, mCachedDeviceManager, mEventManager);
 
         mProfileManager.updateLocalProfiles();
         mEventManager.readPairedDevices();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 79e4c37..4055986 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -572,8 +572,7 @@
         return mSapProfile;
     }
 
-    @VisibleForTesting
-    HidProfile getHidProfile() {
+    public HidProfile getHidProfile() {
         return mHidProfile;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
index 92db508..327e470 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
@@ -21,11 +21,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.provider.Settings;
+import android.os.SystemProperties;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.ArraySet;
 import android.view.accessibility.AccessibilityManager;
 
+import androidx.annotation.VisibleForTesting;
+
 import java.util.List;
 
 public final class BatteryUtils {
@@ -33,6 +36,9 @@
     /** The key to get the time to full from Settings.Global */
     public static final String GLOBAL_TIME_TO_FULL_MILLIS = "time_to_full_millis";
 
+    /** The system property key to check whether the charging string v2 is enabled or not. */
+    public static final String PROPERTY_CHARGING_STRING_V2_KEY = "charging_string.apply_v2";
+
     /** Gets the latest sticky battery intent from the Android system. */
     public static Intent getBatteryIntent(Context context) {
         return context.registerReceiver(
@@ -75,4 +81,25 @@
         final UserManager userManager = context.getSystemService(UserManager.class);
         return userManager.isManagedProfile() && !userManager.isSystemUser();
     }
+
+    private static Boolean sChargingStringV2Enabled = null;
+
+    /** Returns {@code true} if the charging string v2 is enabled. */
+    public static boolean isChargingStringV2Enabled() {
+        if (sChargingStringV2Enabled == null) {
+            sChargingStringV2Enabled =
+                    SystemProperties.getBoolean(PROPERTY_CHARGING_STRING_V2_KEY, false);
+        }
+        return sChargingStringV2Enabled;
+    }
+
+
+    /** Used to override the system property to enable or reset for charging string V2. */
+    @VisibleForTesting
+    public static void setChargingStringV2Enabled(Boolean enabled) {
+        SystemProperties.set(
+                BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY,
+                enabled == null ? "" : String.valueOf(enabled));
+        BatteryUtils.sChargingStringV2Enabled = enabled;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerAllowlistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerAllowlistBackend.java
index 8fd4e91..822a6088 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerAllowlistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerAllowlistBackend.java
@@ -18,14 +18,18 @@
 
 import static android.provider.DeviceConfig.NAMESPACE_ACTIVITY_MANAGER;
 
+import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.IDeviceIdleController;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.telecom.DefaultDialerManager;
 import android.text.TextUtils;
@@ -121,6 +125,14 @@
             return true;
         }
 
+        if (android.app.admin.flags.Flags.disallowUserControlBgUsageFix()) {
+            // App is subject to DevicePolicyManager.setUserControlDisabledPackages() policy.
+            final int userId = UserHandle.getUserId(uid);
+            if (mAppContext.getPackageManager().isPackageStateProtected(pkg, userId)) {
+                return true;
+            }
+        }
+
         return false;
     }
 
@@ -163,27 +175,77 @@
 
     /**
      * Add app into power save allow list.
-     * @param pkg packageName
+     * @param pkg packageName of the app
      */
+    // TODO: Fix all callers to pass in UID
     public void addApp(String pkg) {
+        addApp(pkg, Process.INVALID_UID);
+    }
+
+    /**
+     * Add app into power save allow list.
+     * @param pkg packageName of the app
+     * @param uid uid of the app
+     */
+    public void addApp(String pkg, int uid) {
         try {
+            if (android.app.Flags.appRestrictionsApi()) {
+                if (uid == Process.INVALID_UID) {
+                    uid = mAppContext.getSystemService(PackageManager.class).getPackageUid(pkg, 0);
+                }
+                final boolean wasInList = isAllowlisted(pkg, uid);
+
+                if (!wasInList) {
+                    mAppContext.getSystemService(ActivityManager.class).noteAppRestrictionEnabled(
+                            pkg, uid, ActivityManager.RESTRICTION_LEVEL_EXEMPTED,
+                            true, ActivityManager.RESTRICTION_REASON_USER,
+                            "settings", 0);
+                }
+            }
+
             mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
             mAllowlistedApps.add(pkg);
         } catch (RemoteException e) {
             Log.w(TAG, "Unable to reach IDeviceIdleController", e);
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Unable to find package", e);
         }
     }
 
     /**
      * Remove package from power save allow list.
-     * @param pkg
+     * @param pkg packageName of the app
      */
     public void removeApp(String pkg) {
+        removeApp(pkg, Process.INVALID_UID);
+    }
+
+    /**
+     * Remove package from power save allow list.
+     * @param pkg packageName of the app
+     * @param uid uid of the app
+     */
+    public void removeApp(String pkg, int uid) {
         try {
+            if (android.app.Flags.appRestrictionsApi()) {
+                if (uid == Process.INVALID_UID) {
+                    uid = mAppContext.getSystemService(PackageManager.class).getPackageUid(pkg, 0);
+                }
+                final boolean wasInList = isAllowlisted(pkg, uid);
+                if (wasInList) {
+                    mAppContext.getSystemService(ActivityManager.class).noteAppRestrictionEnabled(
+                            pkg, uid, ActivityManager.RESTRICTION_LEVEL_EXEMPTED,
+                            false, ActivityManager.RESTRICTION_REASON_USER,
+                            "settings", 0);
+                }
+            }
+
             mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
             mAllowlistedApps.remove(pkg);
         } catch (RemoteException e) {
             Log.w(TAG, "Unable to reach IDeviceIdleController", e);
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Unable to find package", e);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
index 6fb0179..e91c0bc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
@@ -168,17 +168,16 @@
     /**
      * Gets a list of preferences that other apps have injected.
      *
-     * @param profileId Identifier of the user/profile to obtain the injected settings for or
-     *                  UserHandle.USER_CURRENT for all profiles associated with current user.
+     * @param profiles UserHandles of the users/profiles for which to obtain the injected settings.
      */
     public Map<Integer, List<Preference>> getInjectedSettings(Context prefContext,
-            final int profileId) {
+            final Set<UserHandle> profiles) {
         final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        final List<UserHandle> profiles = um.getUserProfiles();
+        final List<UserHandle> allProfilesForUser = um.getUserProfiles();
         final ArrayMap<Integer, List<Preference>> result = new ArrayMap<>();
         mSettings.clear();
-        for (UserHandle userHandle : profiles) {
-            if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) {
+        for (UserHandle userHandle : allProfilesForUser) {
+            if (profiles.contains(userHandle)) {
                 final List<Preference> prefs = new ArrayList<>();
                 Iterable<InjectedSetting> settings = getSettings(userHandle);
                 for (InjectedSetting setting : settings) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 4e6d3cb..eae58ad 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -52,6 +52,7 @@
 import android.media.RouteListingPreference;
 import android.media.RoutingSessionInfo;
 import android.os.Build;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -131,6 +132,7 @@
     protected final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
     @NonNull protected final Context mContext;
     @NonNull protected final String mPackageName;
+    @NonNull protected final UserHandle mUserHandle;
     private final Collection<MediaDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
     private MediaDevice mCurrentConnectedDevice;
     private final LocalBluetoothManager mBluetoothManager;
@@ -140,16 +142,28 @@
     /* package */ InfoMediaManager(
             @NonNull Context context,
             @NonNull String packageName,
+            @NonNull UserHandle userHandle,
             @NonNull LocalBluetoothManager localBluetoothManager) {
         mContext = context;
         mBluetoothManager = localBluetoothManager;
         mPackageName = packageName;
+        mUserHandle = userHandle;
     }
 
-    /** Creates an instance of InfoMediaManager. */
+    /**
+     * Creates an instance of InfoMediaManager.
+     *
+     * @param context The {@link Context}.
+     * @param packageName The package name of the app for which to control routing, or null if the
+     *     caller is interested in system-level routing only (for example, headsets, built-in
+     *     speakers, as opposed to app-specific routing (for example, casting to another device).
+     * @param userHandle The {@link UserHandle} of the user on which the app to control is running,
+     *     or null if the caller does not need app-specific routing (see {@code packageName}).
+     */
     public static InfoMediaManager createInstance(
             Context context,
             @Nullable String packageName,
+            @Nullable UserHandle userHandle,
             LocalBluetoothManager localBluetoothManager) {
 
         // The caller is only interested in system routes (headsets, built-in speakers, etc), and is
@@ -159,25 +173,28 @@
             packageName = context.getPackageName();
         }
 
+        if (userHandle == null) {
+            userHandle = android.os.Process.myUserHandle();
+        }
+
         if (Flags.useMediaRouter2ForInfoMediaManager()) {
             try {
-                return new RouterInfoMediaManager(context, packageName, localBluetoothManager);
+                return new RouterInfoMediaManager(
+                        context, packageName, userHandle, localBluetoothManager);
             } catch (PackageNotAvailableException ex) {
                 // TODO: b/293578081 - Propagate this exception to callers for proper handling.
                 Log.w(TAG, "Returning a no-op InfoMediaManager for package " + packageName);
-                return new NoOpInfoMediaManager(context, packageName, localBluetoothManager);
+                return new NoOpInfoMediaManager(
+                        context, packageName, userHandle, localBluetoothManager);
             }
         } else {
-            return new ManagerInfoMediaManager(context, packageName, localBluetoothManager);
+            return new ManagerInfoMediaManager(
+                    context, packageName, userHandle, localBluetoothManager);
         }
     }
 
     public void startScan() {
-        mMediaDevices.clear();
-        registerRouter();
         startScanOnRouter();
-        updateRouteListingPreference();
-        refreshDevices();
     }
 
     private void updateRouteListingPreference() {
@@ -191,7 +208,6 @@
 
     public final void stopScan() {
         stopScanOnRouter();
-        unregisterRouter();
     }
 
     protected abstract void stopScanOnRouter();
@@ -254,8 +270,6 @@
     protected abstract List<MediaRoute2Info> getTransferableRoutes(@NonNull String packageName);
 
     protected final void rebuildDeviceList() {
-        mMediaDevices.clear();
-        mCurrentConnectedDevice = null;
         buildAvailableRoutes();
     }
 
@@ -280,14 +294,37 @@
         return null;
     }
 
-    protected final void registerCallback(MediaDeviceCallback callback) {
+    /**
+     * Registers the specified {@code callback} to receive state updates about routing information.
+     *
+     * <p>As long as there is a registered {@link MediaDeviceCallback}, {@link InfoMediaManager}
+     * will receive state updates from the platform.
+     *
+     * <p>Call {@link #unregisterCallback(MediaDeviceCallback)} once you no longer need platform
+     * updates.
+     */
+    public final void registerCallback(@NonNull MediaDeviceCallback callback) {
+        boolean wasEmpty = mCallbacks.isEmpty();
         if (!mCallbacks.contains(callback)) {
             mCallbacks.add(callback);
+            if (wasEmpty) {
+                mMediaDevices.clear();
+                registerRouter();
+                updateRouteListingPreference();
+                refreshDevices();
+            }
         }
     }
 
-    protected final void unregisterCallback(MediaDeviceCallback callback) {
-        mCallbacks.remove(callback);
+    /**
+     * Unregisters the specified {@code callback}.
+     *
+     * @see #registerCallback(MediaDeviceCallback)
+     */
+    public final void unregisterCallback(@NonNull MediaDeviceCallback callback) {
+        if (mCallbacks.remove(callback) && mCallbacks.isEmpty()) {
+            unregisterRouter();
+        }
     }
 
     private void dispatchDeviceListAdded(@NonNull List<MediaDevice> devices) {
@@ -524,6 +561,7 @@
     // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
     @SuppressWarnings("NewApi")
     private synchronized void buildAvailableRoutes() {
+        mMediaDevices.clear();
         RoutingSessionInfo activeSession = getActiveRoutingSession();
 
         for (MediaRoute2Info route : getAvailableRoutes(activeSession)) {
@@ -533,6 +571,12 @@
             }
             addMediaDevice(route, activeSession);
         }
+
+        // In practice, mMediaDevices should always have at least one route.
+        if (!mMediaDevices.isEmpty()) {
+            // First device on the list is always the first selected route.
+            mCurrentConnectedDevice = mMediaDevices.get(0);
+        }
     }
 
     private synchronized List<MediaRoute2Info> getAvailableRoutes(
@@ -643,9 +687,6 @@
         if (mediaDevice != null) {
             if (activeSession.getSelectedRoutes().contains(route.getId())) {
                 mediaDevice.setState(STATE_SELECTED);
-                if (mCurrentConnectedDevice == null) {
-                    mCurrentConnectedDevice = mediaDevice;
-                }
             }
             mMediaDevices.add(mediaDevice);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 63056b6..473c627 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -17,7 +17,6 @@
 
 import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
 
-import android.app.Notification;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
@@ -106,14 +105,23 @@
      * Register to start receiving callbacks for MediaDevice events.
      */
     public void registerCallback(DeviceCallback callback) {
-        mCallbacks.add(callback);
+        boolean wasEmpty = mCallbacks.isEmpty();
+        if (!mCallbacks.contains(callback)) {
+            mCallbacks.add(callback);
+            if (wasEmpty) {
+                mInfoMediaManager.registerCallback(mMediaDeviceCallback);
+            }
+        }
     }
 
     /**
      * Unregister to stop receiving callbacks for MediaDevice events
      */
     public void unregisterCallback(DeviceCallback callback) {
-        mCallbacks.remove(callback);
+        if (mCallbacks.remove(callback) && mCallbacks.isEmpty()) {
+            mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
+            unRegisterDeviceAttributeChangeCallback();
+        }
     }
 
     /**
@@ -125,7 +133,7 @@
      *
      * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter.
      */
-    public LocalMediaManager(Context context, String packageName, Notification notification) {
+    public LocalMediaManager(Context context, String packageName) {
         mContext = context;
         mPackageName = packageName;
         mLocalBluetoothManager =
@@ -138,7 +146,10 @@
         }
 
         mInfoMediaManager =
-                InfoMediaManager.createInstance(context, packageName, mLocalBluetoothManager);
+                // TODO: b/321969740 - Take the userHandle as a parameter and pass it through. The
+                // package name is not sufficient to unambiguously identify an app.
+                InfoMediaManager.createInstance(
+                        context, packageName, /* userHandle */ null, mLocalBluetoothManager);
     }
 
     /**
@@ -225,10 +236,6 @@
      * Start scan connected MediaDevice
      */
     public void startScan() {
-        synchronized (mMediaDevicesLock) {
-            mMediaDevices.clear();
-        }
-        mInfoMediaManager.registerCallback(mMediaDeviceCallback);
         mInfoMediaManager.startScan();
     }
 
@@ -278,9 +285,7 @@
      * Stop scan MediaDevice
      */
     public void stopScan() {
-        mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
         mInfoMediaManager.stopScan();
-        unRegisterDeviceAttributeChangeCallback();
     }
 
     /**
@@ -551,7 +556,6 @@
         private MediaDevice getMutingExpectedDevice() {
             if (mBluetoothAdapter == null
                     || mAudioManager.getMutingExpectedDevice() == null) {
-                Log.w(TAG, "BluetoothAdapter is null or muting expected device not exist");
                 return null;
             }
             final List<BluetoothDevice> bluetoothDevices =
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java
index 23063da..d621751 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java
@@ -21,6 +21,7 @@
 import android.media.MediaRouter2Manager;
 import android.media.RouteListingPreference;
 import android.media.RoutingSessionInfo;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -53,8 +54,9 @@
     /* package */ ManagerInfoMediaManager(
             Context context,
             @NonNull String packageName,
+            @NonNull UserHandle userHandle,
             LocalBluetoothManager localBluetoothManager) {
-        super(context, packageName, localBluetoothManager);
+        super(context, packageName, userHandle, localBluetoothManager);
 
         mRouterManager = MediaRouter2Manager.getInstance(context);
     }
@@ -87,8 +89,7 @@
 
     @Override
     protected void transferToRoute(@NonNull MediaRoute2Info route) {
-        // TODO: b/279555229 - provide real user handle of a caller.
-        mRouterManager.transfer(mPackageName, route, android.os.Process.myUserHandle());
+        mRouterManager.transfer(mPackageName, route, mUserHandle);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java
index cf11c6d..d2b018c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java
@@ -20,6 +20,7 @@
 import android.media.MediaRoute2Info;
 import android.media.RouteListingPreference;
 import android.media.RoutingSessionInfo;
+import android.os.UserHandle;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -58,8 +59,9 @@
     NoOpInfoMediaManager(
             Context context,
             @NonNull String packageName,
+            @NonNull UserHandle userHandle,
             LocalBluetoothManager localBluetoothManager) {
-        super(context, packageName, localBluetoothManager);
+        super(context, packageName, userHandle, localBluetoothManager);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java
index 0dceeba..045c60d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java
@@ -25,7 +25,7 @@
 import android.media.RouteDiscoveryPreference;
 import android.media.RouteListingPreference;
 import android.media.RoutingSessionInfo;
-import android.os.Process;
+import android.os.UserHandle;
 import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
@@ -70,15 +70,16 @@
     /* package */ RouterInfoMediaManager(
             Context context,
             @NonNull String packageName,
+            @NonNull UserHandle userHandle,
             LocalBluetoothManager localBluetoothManager)
             throws PackageNotAvailableException {
-        super(context, packageName, localBluetoothManager);
+        super(context, packageName, userHandle, localBluetoothManager);
 
         MediaRouter2 router = null;
 
         if (Flags.enableCrossUserRoutingInMediaRouter2()) {
             try {
-                router = MediaRouter2.getInstance(context, packageName, Process.myUserHandle());
+                router = MediaRouter2.getInstance(context, packageName, userHandle);
             } catch (IllegalArgumentException ex) {
                 // Do nothing
             }
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
index b015b2b..46f2290 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
@@ -184,7 +184,7 @@
         dialogHelper
                 .setTitle(R.string.user_info_settings_title)
                 .addCustomView(content)
-                .setPositiveButton(android.R.string.ok, view -> {
+                .setPositiveButton(R.string.okay, view -> {
                     Drawable newUserIcon = mEditUserPhotoController != null
                             ? mEditUserPhotoController.getNewUserPhotoDrawable()
                             : null;
@@ -201,7 +201,7 @@
                     }
                     dialogHelper.getDialog().dismiss();
                 })
-                .setBackButton(android.R.string.cancel, view -> {
+                .setBackButton(R.string.cancel, view -> {
                     clear();
                     if (cancelCallback != null) {
                         cancelCallback.run();
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index 2272654..2da6221 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.utils;
 
+import static java.lang.Math.abs;
+
 import android.content.Context;
 import android.icu.text.DateFormat;
 import android.icu.text.MeasureFormat;
@@ -33,7 +35,7 @@
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
-/** Utility class for keeping power related strings consistent**/
+/** Utility class for keeping power related strings consistent. **/
 public class PowerUtil {
 
     private static final long SEVEN_MINUTES_MILLIS = TimeUnit.MINUTES.toMillis(7);
@@ -212,8 +214,8 @@
      * @return The rounded value as a long
      */
     public static long roundTimeToNearestThreshold(long drainTime, long threshold) {
-        long time = Math.abs(drainTime);
-        long multiple = Math.abs(threshold);
+        long time = abs(drainTime);
+        long multiple = abs(threshold);
         final long remainder = time % multiple;
         if (remainder < multiple / 2) {
             return time - remainder;
@@ -221,4 +223,25 @@
             return time - remainder + multiple;
         }
     }
+
+    /** Gets the target time string in a short format. */
+    public static String getTargetTimeShortString(
+            Context context, long targetTimeOffsetMs, long currentTimeMs) {
+        long targetTimeMs = currentTimeMs + targetTimeOffsetMs;
+        if (targetTimeOffsetMs >= FIFTEEN_MINUTES_MILLIS) {
+            targetTimeMs = roundUpTimeToNextThreshold(targetTimeMs, FIFTEEN_MINUTES_MILLIS);
+        }
+
+        // convert the time to a properly formatted string.
+        String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+        DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+        Date date = Date.from(Instant.ofEpochMilli(targetTimeMs));
+        return fmt.format(date);
+    }
+
+    private static long roundUpTimeToNextThreshold(long timeMs, long threshold) {
+        var time = abs(timeMs);
+        var multiple = abs(threshold);
+        return ((time + multiple - 1) / multiple) * multiple;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt
index 724dd51..869fb7f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt
@@ -17,6 +17,7 @@
 
 import com.android.settingslib.media.LocalMediaManager
 import com.android.settingslib.media.MediaDevice
+import com.android.settingslib.media.flags.Flags
 import com.android.settingslib.volume.shared.AudioManagerEventsReceiver
 import com.android.settingslib.volume.shared.model.AudioManagerEvent
 import kotlinx.coroutines.CoroutineScope
@@ -69,10 +70,14 @@
                         }
                     }
                 localMediaManager.registerCallback(callback)
-                localMediaManager.startScan()
+                if (!Flags.removeUnnecessaryRouteScanning()) {
+                    localMediaManager.startScan()
+                }
 
                 awaitClose {
-                    localMediaManager.stopScan()
+                    if (!Flags.removeUnnecessaryRouteScanning()) {
+                        localMediaManager.stopScan()
+                    }
                     localMediaManager.unregisterCallback(callback)
                 }
             }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
index d5444cf..727c61c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
@@ -28,19 +28,21 @@
 import android.os.Bundle
 import android.os.SystemClock
 import android.util.Log
+import android.view.WindowManager
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import com.android.settingslib.R
 import com.android.settingslib.flags.Flags.newStatusBarIcons
-import java.util.Locale
-import kotlin.coroutines.resume
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.asExecutor
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withContext
-
+import java.util.Locale
+import kotlin.coroutines.resume
 
 open class WifiUtils {
     /**
@@ -473,9 +475,28 @@
             context: Context,
             lifecycleOwner: LifecycleOwner,
             ssid: String,
-            onAllowed: () -> Unit,
+            onAllowed: () -> Unit
         ) {
-            lifecycleOwner.lifecycleScope.launch {
+            checkWepAllowed(
+                context,
+                lifecycleOwner.lifecycleScope,
+                ssid,
+                WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW,
+                { intent -> context.startActivity(intent) },
+                onAllowed
+            )
+        }
+
+        @JvmStatic
+        fun checkWepAllowed(
+            context: Context,
+            coroutineScope: CoroutineScope,
+            ssid: String,
+            dialogWindowType: Int,
+            onStartActivity: (intent: Intent) -> Unit,
+            onAllowed: () -> Unit,
+        ): Job =
+            coroutineScope.launch {
                 val wifiManager = context.getSystemService(WifiManager::class.java) ?: return@launch
                 if (wifiManager.queryWepAllowed()) {
                     onAllowed()
@@ -485,12 +506,12 @@
                             "com.android.settings",
                             "com.android.settings.network.WepNetworkDialogActivity"
                         )
+                        putExtra(DIALOG_WINDOW_TYPE, dialogWindowType)
                         putExtra(SSID, ssid)
-                    }
-                    context.startActivity(intent)
+                    }.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                    onStartActivity(intent)
                 }
             }
-        }
 
         private suspend fun WifiManager.queryWepAllowed(): Boolean =
             withContext(Dispatchers.Default) {
@@ -502,5 +523,6 @@
             }
 
         const val SSID = "ssid"
+        const val DIALOG_WINDOW_TYPE = "dialog_window_type"
     }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index b974888..fef0561 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -240,6 +240,56 @@
     }
 
     @Test
+    public void testDownloadAndLauncherNotInQuietAcceptsCorrectApps() {
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = false;
+
+        // should include updated system apps
+        when(mEntry.info.isInstantApp()).thenReturn(false);
+        mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isTrue();
+
+        // should not include system apps other than the home app
+        mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = false;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isFalse();
+
+        // should include the home app
+        mEntry.isHomeApp = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isTrue();
+
+        // should include any System app with a launcher entry
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isTrue();
+
+        // should not include updated system apps when in quiet mode
+        when(mEntry.info.isInstantApp()).thenReturn(false);
+        mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+        mEntry.hideInQuietMode = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isFalse();
+
+        // should not include the home app when in quiet mode
+        mEntry.isHomeApp = true;
+        mEntry.hideInQuietMode = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isFalse();
+
+        // should not include any System app with a launcher entry when in quiet mode
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = true;
+        mEntry.hideInQuietMode = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_NOT_QUIET.filterApp(mEntry))
+                .isFalse();
+    }
+
+    @Test
     public void testOtherAppsRejectsLegacyGame() {
         mEntry.info.flags = ApplicationInfo.FLAG_IS_GAME;
 
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
index 50f5b9d..69f6305 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
@@ -20,6 +20,8 @@
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -37,13 +39,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static java.util.concurrent.TimeUnit.SECONDS;
-
 import java.util.concurrent.CountDownLatch;
 
 /**
- * Test that verifies that BluetoothEventManager can receive broadcasts for non-current
- * users for all bluetooth events.
+ * Test that verifies that BluetoothEventManager can receive broadcasts for non-current users for
+ * all bluetooth events.
  *
  * <p>Creation and deletion of users takes a long time, so marking this as a LargeTest.
  */
@@ -64,9 +64,14 @@
         mContext = InstrumentationRegistry.getTargetContext();
         mUserManager = UserManager.get(mContext);
 
-        mBluetoothEventManager = new BluetoothEventManager(
-                mock(LocalBluetoothAdapter.class), mock(CachedBluetoothDeviceManager.class),
-                mContext, /* handler= */ null, UserHandle.ALL);
+        mBluetoothEventManager =
+                new BluetoothEventManager(
+                        mock(LocalBluetoothAdapter.class),
+                        mock(LocalBluetoothManager.class),
+                        mock(CachedBluetoothDeviceManager.class),
+                        mContext,
+                        /* handler= */ null,
+                        UserHandle.ALL);
 
         // Create and start another user in the background.
         mOtherUser = mUserManager.createUser("TestUser", /* flags= */ 0);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java
index f0185b9..3bd37a2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java
@@ -64,21 +64,23 @@
     @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER)
     public void createInstance_withMR2FlagOn_returnsRouterInfoMediaManager() {
         InfoMediaManager manager =
-                InfoMediaManager.createInstance(mContext, mContext.getPackageName(), null);
+                InfoMediaManager.createInstance(
+                        mContext, mContext.getPackageName(), mContext.getUser(), null);
         assertThat(manager).isInstanceOf(RouterInfoMediaManager.class);
     }
 
     @Test
     @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER)
     public void createInstance_withMR2FlagOn_withFakePackage_returnsNoOpInfoMediaManager() {
-        InfoMediaManager manager = InfoMediaManager.createInstance(mContext, FAKE_PACKAGE, null);
+        InfoMediaManager manager =
+                InfoMediaManager.createInstance(mContext, FAKE_PACKAGE, null, null);
         assertThat(manager).isInstanceOf(NoOpInfoMediaManager.class);
     }
 
     @Test
     @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER)
     public void createInstance_withMR2FlagOn_withNullPackage_returnsRouterInfoMediaManager() {
-        InfoMediaManager manager = InfoMediaManager.createInstance(mContext, null, null);
+        InfoMediaManager manager = InfoMediaManager.createInstance(mContext, null, null, null);
         assertThat(manager).isInstanceOf(RouterInfoMediaManager.class);
     }
 
@@ -86,7 +88,8 @@
     @RequiresFlagsDisabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER)
     public void createInstance_withMR2FlagOff_returnsManagerInfoMediaManager() {
         InfoMediaManager manager =
-                InfoMediaManager.createInstance(mContext, mContext.getPackageName(), null);
+                InfoMediaManager.createInstance(
+                        mContext, mContext.getPackageName(), mContext.getUser(), null);
         assertThat(manager).isInstanceOf(ManagerInfoMediaManager.class);
     }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/OWNERS b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/OWNERS
new file mode 100644
index 0000000..384fd9b
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/OWNERS
@@ -0,0 +1,3 @@
+#Android Media Better Together
[email protected]
[email protected]
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index 48bbf4e..b1489be 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -22,6 +22,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -29,35 +30,47 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothStatusCodes;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.telephony.TelephonyManager;
 
 import com.android.settingslib.R;
+import com.android.settingslib.flags.Flags;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
 public class BluetoothEventManagerTest {
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private static final String DEVICE_NAME = "test_device_name";
 
     @Mock
     private LocalBluetoothAdapter mLocalAdapter;
     @Mock
+    private LocalBluetoothManager mBtManager;
+    @Mock
     private CachedBluetoothDeviceManager mCachedDeviceManager;
     @Mock
     private BluetoothCallback mBluetoothCallback;
@@ -96,8 +109,15 @@
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
 
-        mBluetoothEventManager = new BluetoothEventManager(mLocalAdapter,
-                mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null);
+        mBluetoothEventManager =
+                new BluetoothEventManager(
+                        mLocalAdapter,
+                        mBtManager,
+                        mCachedDeviceManager,
+                        mContext,
+                        /* handler= */ null,
+                        /* userHandle= */ null);
+        when(mBtManager.getProfileManager()).thenReturn(mLocalProfileManager);
         when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
         when(mHfpProfile.isProfileReady()).thenReturn(true);
         when(mA2dpProfile.isProfileReady()).thenReturn(true);
@@ -113,8 +133,13 @@
     public void ifUserHandleIsNull_registerReceiverIsCalled() {
         Context mockContext = mock(Context.class);
         BluetoothEventManager eventManager =
-                new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext,
-                        /* handler= */ null, /* userHandle= */ null);
+                new BluetoothEventManager(
+                        mLocalAdapter,
+                        mBtManager,
+                        mCachedDeviceManager,
+                        mockContext,
+                        /* handler= */ null,
+                        /* userHandle= */ null);
 
         verify(mockContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
                 eq(null), eq(null), eq(Context.RECEIVER_EXPORTED));
@@ -124,8 +149,13 @@
     public void ifUserHandleSpecified_registerReceiverAsUserIsCalled() {
         Context mockContext = mock(Context.class);
         BluetoothEventManager eventManager =
-                new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext,
-                        /* handler= */ null, UserHandle.ALL);
+                new BluetoothEventManager(
+                        mLocalAdapter,
+                        mBtManager,
+                        mCachedDeviceManager,
+                        mockContext,
+                        /* handler= */ null,
+                        UserHandle.ALL);
 
         verify(mockContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq(UserHandle.ALL),
                 any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED));
@@ -172,6 +202,160 @@
                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
     }
 
+    /**
+     * dispatchProfileConnectionStateChanged should not call {@link
+     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing flag is off.
+     */
+    @Test
+    public void dispatchProfileConnectionStateChanged_flagOff_noUpdateFallbackDevice() {
+        ShadowBluetoothAdapter shadowBluetoothAdapter =
+                Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class);
+        when(broadcast.isProfileReady()).thenReturn(true);
+        LocalBluetoothLeBroadcastAssistant assistant =
+                mock(LocalBluetoothLeBroadcastAssistant.class);
+        when(assistant.isProfileReady()).thenReturn(true);
+        LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class);
+        when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast);
+        when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant);
+        when(mBtManager.getProfileManager()).thenReturn(profileManager);
+        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
+                mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED,
+                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+
+        verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded();
+    }
+
+    /**
+     * dispatchProfileConnectionStateChanged should not call {@link
+     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when the device does not
+     * support audio sharing.
+     */
+    @Test
+    public void dispatchProfileConnectionStateChanged_notSupport_noUpdateFallbackDevice() {
+        ShadowBluetoothAdapter shadowBluetoothAdapter =
+                Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
+        shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class);
+        when(broadcast.isProfileReady()).thenReturn(true);
+        LocalBluetoothLeBroadcastAssistant assistant =
+                mock(LocalBluetoothLeBroadcastAssistant.class);
+        when(assistant.isProfileReady()).thenReturn(true);
+        LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class);
+        when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast);
+        when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant);
+        when(mBtManager.getProfileManager()).thenReturn(profileManager);
+        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
+                mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED,
+                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+
+        verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded();
+    }
+
+    /**
+     * dispatchProfileConnectionStateChanged should not call {@link
+     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing profile is
+     * not ready.
+     */
+    @Test
+    public void dispatchProfileConnectionStateChanged_profileNotReady_noUpdateFallbackDevice() {
+        ShadowBluetoothAdapter shadowBluetoothAdapter =
+                Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class);
+        when(broadcast.isProfileReady()).thenReturn(false);
+        LocalBluetoothLeBroadcastAssistant assistant =
+                mock(LocalBluetoothLeBroadcastAssistant.class);
+        when(assistant.isProfileReady()).thenReturn(true);
+        LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class);
+        when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast);
+        when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant);
+        when(mBtManager.getProfileManager()).thenReturn(profileManager);
+        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
+                mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED,
+                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+
+        verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded();
+    }
+
+    /**
+     * dispatchProfileConnectionStateChanged should not call {@link
+     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when triggered for profile
+     * other than LE_AUDIO_BROADCAST_ASSISTANT or state other than STATE_DISCONNECTED.
+     */
+    @Test
+    public void dispatchProfileConnectionStateChanged_notAssistantProfile_noUpdateFallbackDevice() {
+        ShadowBluetoothAdapter shadowBluetoothAdapter =
+                Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class);
+        when(broadcast.isProfileReady()).thenReturn(true);
+        LocalBluetoothLeBroadcastAssistant assistant =
+                mock(LocalBluetoothLeBroadcastAssistant.class);
+        when(assistant.isProfileReady()).thenReturn(true);
+        LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class);
+        when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast);
+        when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant);
+        when(mBtManager.getProfileManager()).thenReturn(profileManager);
+        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
+                mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED,
+                BluetoothProfile.LE_AUDIO);
+
+        verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded();
+    }
+
+    /**
+     * dispatchProfileConnectionStateChanged should call {@link
+     * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when assistant profile is
+     * disconnected and audio sharing is enabled.
+     */
+    @Test
+    public void dispatchProfileConnectionStateChanged_audioSharing_updateFallbackDevice() {
+        ShadowBluetoothAdapter shadowBluetoothAdapter =
+                Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class);
+        when(broadcast.isProfileReady()).thenReturn(true);
+        LocalBluetoothLeBroadcastAssistant assistant =
+                mock(LocalBluetoothLeBroadcastAssistant.class);
+        when(assistant.isProfileReady()).thenReturn(true);
+        LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class);
+        when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast);
+        when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant);
+        when(mBtManager.getProfileManager()).thenReturn(profileManager);
+        mBluetoothEventManager.dispatchProfileConnectionStateChanged(
+                mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED,
+                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+
+        verify(broadcast).updateFallbackActiveDeviceIfNeeded();
+    }
+
     @Test
     public void dispatchAclConnectionStateChanged_aclDisconnected_shouldDispatchCallback() {
         mBluetoothEventManager.registerCallback(mBluetoothCallback);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 1246fd8..f197f9e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -17,6 +17,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.spy;
@@ -25,6 +26,7 @@
 
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -44,6 +46,9 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class BluetoothUtilsTest {
 
@@ -55,6 +60,16 @@
     private AudioManager mAudioManager;
     @Mock
     private PackageManager mPackageManager;
+    @Mock
+    private LocalBluetoothLeBroadcast mBroadcast;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private LocalBluetoothManager mLocalBluetoothManager;
+    @Mock
+    private LocalBluetoothLeBroadcastAssistant mAssistant;
+    @Mock
+    private BluetoothLeBroadcastReceiveState mLeBroadcastReceiveState;
 
     private Context mContext;
     private static final String STRING_METADATA = "string_metadata";
@@ -72,6 +87,9 @@
         MockitoAnnotations.initMocks(this);
 
         mContext = spy(RuntimeEnvironment.application);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
+        when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
+        when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
     }
 
     @Test
@@ -432,6 +450,30 @@
     }
 
     @Test
+    public void testIsBroadcasting_broadcastEnabled_returnTrue() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        assertThat(BluetoothUtils.isBroadcasting(mLocalBluetoothManager)).isEqualTo(true);
+    }
+
+    @Test
+    public void testHasConnectedBroadcastSource_deviceConnectedToBroadcastSource() {
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+
+        List<Long> bisSyncState = new ArrayList<>();
+        bisSyncState.add(1L);
+        when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+
+        List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+        sourceList.add(mLeBroadcastReceiveState);
+        when(mAssistant.getAllSources(any())).thenReturn(sourceList);
+
+        assertThat(
+                BluetoothUtils.hasConnectedBroadcastSource(
+                        mCachedBluetoothDevice, mLocalBluetoothManager))
+                .isEqualTo(true);
+    }
+
+    @Test
     public void isAvailableHearingDevice_isConnectedHearingAid_returnTure() {
         when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
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 5996dbb..c13c493 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
@@ -15,6 +15,9 @@
  */
 package com.android.settingslib.bluetooth;
 
+import static com.android.settingslib.flags.Flags.FLAG_ENABLE_LE_AUDIO_SHARING;
+import static com.android.settingslib.flags.Flags.FLAG_ENABLE_SET_PREFERRED_TRANSPORT_FOR_LE_AUDIO_DEVICE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -28,14 +31,17 @@
 import static org.mockito.Mockito.when;
 
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
 import android.graphics.drawable.BitmapDrawable;
 import android.media.AudioManager;
 import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
 import android.text.Spannable;
 import android.text.style.ForegroundColorSpan;
 import android.util.LruCache;
@@ -45,6 +51,8 @@
 import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settingslib.widget.AdaptiveOutlineDrawable;
 
+import com.google.common.collect.ImmutableList;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -56,6 +64,9 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowBluetoothAdapter.class})
 public class CachedBluetoothDeviceTest {
@@ -86,10 +97,21 @@
     private HapClientProfile mHapClientProfile;
     @Mock
     private LeAudioProfile mLeAudioProfile;
+
+    @Mock
+    private HidProfile mHidProfile;
     @Mock
     private BluetoothDevice mDevice;
     @Mock
     private BluetoothDevice mSubDevice;
+    @Mock
+    private LocalBluetoothLeBroadcast mBroadcast;
+    @Mock
+    private LocalBluetoothManager mLocalBluetoothManager;
+    @Mock
+    private LocalBluetoothLeBroadcastAssistant mAssistant;
+    @Mock
+    private BluetoothLeBroadcastReceiveState mLeBroadcastReceiveState;
     private CachedBluetoothDevice mCachedDevice;
     private CachedBluetoothDevice mSubCachedDevice;
     private AudioManager mAudioManager;
@@ -104,9 +126,15 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TV_MEDIA_OUTPUT_DIALOG);
+        mSetFlagsRule.enableFlags(FLAG_ENABLE_SET_PREFERRED_TRANSPORT_FOR_LE_AUDIO_DEVICE);
+        mSetFlagsRule.enableFlags(FLAG_ENABLE_LE_AUDIO_SHARING);
         mContext = RuntimeEnvironment.application;
         mAudioManager = mContext.getSystemService(AudioManager.class);
         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
+        mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
+                BluetoothStatusCodes.FEATURE_SUPPORTED);
         when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
         when(mHfpProfile.isProfileReady()).thenReturn(true);
         when(mHfpProfile.getProfileId()).thenReturn(BluetoothProfile.HEADSET);
@@ -118,7 +146,14 @@
         when(mHearingAidProfile.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID);
         when(mLeAudioProfile.isProfileReady()).thenReturn(true);
         when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
+        when(mHidProfile.isProfileReady()).thenReturn(true);
+        when(mHidProfile.getProfileId()).thenReturn(BluetoothProfile.HID_HOST);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
+        when(mBroadcast.isEnabled(any())).thenReturn(false);
+        when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
+        when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
         mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice));
+        mCachedDevice.setLocalBluetoothManager(mLocalBluetoothManager);
         mSubCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mSubDevice));
         doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
         doAnswer((invocation) -> mBatteryLevel).when(mSubCachedDevice).getBatteryLevel();
@@ -338,12 +373,13 @@
 
         // Set device as Active for A2DP and test connection state summary
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
 
         // Test with battery level
         mBatteryLevel = 10;
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
-                "Active, 10% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_battery_level, "10%"));
 
         // Set A2DP profile to be disconnected and test connection state summary
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -354,7 +390,8 @@
         // Set A2DP profile to be connected, Active and test connection state summary
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
 
         // Set A2DP profile to be disconnected and test connection state summary
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -509,11 +546,13 @@
         mCachedDevice.onAudioModeChanged();
         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
 
         // Test with battery level
         mBatteryLevel = 10;
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 10% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_battery_level, "10%"));
 
         // Set HFP profile to be disconnected and test connection state summary
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -524,7 +563,8 @@
         // Set HFP profile to be connected, Active and test connection state summary
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
 
         // Set HFP profile to be disconnected and test connection state summary
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -896,7 +936,8 @@
         mCachedDevice.addMemberDevice(mSubCachedDevice);
         doAnswer((invocation) -> lowerBatteryLevel).when(mSubCachedDevice).getBatteryLevel();
 
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 30% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_battery_level, "30%"));
     }
 
     @Test
@@ -927,7 +968,8 @@
         doAnswer((invocation) -> BluetoothDevice.BATTERY_LEVEL_UNKNOWN).when(
                 mSubCachedDevice).getBatteryLevel();
 
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 70% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_battery_level, "70%"));
     }
 
     @Test
@@ -984,26 +1026,27 @@
         // Set device as Active for A2DP and HFP and test connection state summary
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
 
         // Test with battery level
         mBatteryLevel = 10;
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
-                "Active, 10% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_battery_level, "10%"));
 
         // Disconnect A2DP only and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
-                "10% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_battery_level, "10%"));
 
         // Disconnect HFP only and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
-                "Active, 10% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_battery_level, "10%"));
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
@@ -1012,7 +1055,8 @@
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
 
         // Set A2DP and HFP profiles to be disconnected and test connection state summary
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
@@ -1150,8 +1194,10 @@
         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
                 TWS_BATTERY_RIGHT.getBytes());
 
-        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
-                "L: 15% battery, R: 25% battery");
+        assertThat(mCachedDevice.getConnectionSummary())
+                .isEqualTo(
+                        mContext.getString(
+                                R.string.bluetooth_battery_level_untethered, "15%", "25%"));
     }
 
     @Test
@@ -1167,8 +1213,12 @@
         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
                 TWS_BATTERY_RIGHT.getBytes());
 
-        assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
-                "Left 15% Right 25%");
+        assertThat(mCachedDevice.getTvConnectionSummary().toString())
+                .isEqualTo(
+                        mContext.getString(R.string.bluetooth_battery_level_untethered_left, "15%")
+                                + " "
+                                + mContext.getString(
+                                        R.string.bluetooth_battery_level_untethered_right, "25%"));
     }
 
     @Test
@@ -1177,19 +1227,23 @@
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
         when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
-        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
-                "true".getBytes());
-        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
-                TWS_BATTERY_LEFT.getBytes());
-        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
-                TWS_BATTERY_RIGHT.getBytes());
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+                .thenReturn("true".getBytes());
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY))
+                .thenReturn(TWS_BATTERY_LEFT.getBytes());
+        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY))
+                .thenReturn(TWS_BATTERY_RIGHT.getBytes());
 
         int lowBatteryColor = mContext.getColor(LOW_BATTERY_COLOR);
+        String leftBattery =
+                mContext.getString(R.string.bluetooth_battery_level_untethered_left, "15%");
+        String rightBattery =
+                mContext.getString(R.string.bluetooth_battery_level_untethered_right, "25%");
 
         // Default low battery threshold, only left battery is low
         CharSequence summary = mCachedDevice.getTvConnectionSummary(LOW_BATTERY_COLOR);
-        assertForegroundColorSpan(summary, 0, 0, 8, lowBatteryColor);
-        assertThat(summary.toString()).isEqualTo("Left 15% Right 25%");
+        assertForegroundColorSpan(summary, 0, 0, leftBattery.length(), lowBatteryColor);
+        assertThat(summary.toString()).isEqualTo(leftBattery + " " + rightBattery);
 
         // Lower threshold, neither battery should be low
         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD))
@@ -1198,8 +1252,7 @@
                 .thenReturn(TWS_LOW_BATTERY_THRESHOLD_LOW.getBytes());
         summary = mCachedDevice.getTvConnectionSummary(LOW_BATTERY_COLOR);
         assertNoForegroundColorSpans(summary);
-        assertThat(summary.toString()).isEqualTo("Left 15% Right 25%");
-
+        assertThat(summary.toString()).isEqualTo(leftBattery + " " + rightBattery);
 
         // Higher Threshold, both batteries are low
         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD))
@@ -1207,9 +1260,14 @@
         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD))
                 .thenReturn(TWS_LOW_BATTERY_THRESHOLD_HIGH.getBytes());
         summary = mCachedDevice.getTvConnectionSummary(LOW_BATTERY_COLOR);
-        assertForegroundColorSpan(summary, 0, 0, 8, lowBatteryColor);
-        assertForegroundColorSpan(summary, 1, 9, 18, lowBatteryColor);
-        assertThat(summary.toString()).isEqualTo("Left 15% Right 25%");
+        assertForegroundColorSpan(summary, 0, 0, leftBattery.length(), lowBatteryColor);
+        assertForegroundColorSpan(
+                summary,
+                1,
+                leftBattery.length() + 1,
+                leftBattery.length() + rightBattery.length() + 1,
+                lowBatteryColor);
+        assertThat(summary.toString()).isEqualTo(leftBattery + " " + rightBattery);
     }
 
     private void assertNoForegroundColorSpans(CharSequence charSequence) {
@@ -1237,32 +1295,39 @@
         // Test without battery level
         // Set PAN profile to be connected and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_connected, ""));
 
         // Set PAN profile to be disconnected and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Disconnected");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_disconnected, ""));
 
         // Test with battery level
         mBatteryLevel = 10;
         // Set PAN profile to be connected and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(
+                        mContext.getString(R.string.bluetooth_connected_battery_level, "10%", ""));
 
         // Set PAN profile to be disconnected and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Disconnected");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_disconnected, ""));
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
 
         // Set PAN profile to be connected and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_connected, ""));
 
         // Set PAN profile to be disconnected and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Disconnected");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_disconnected, ""));
     }
 
     @Test
@@ -1273,27 +1338,38 @@
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(
+                        mContext.getString(R.string.bluetooth_connected_battery_level, "10%", ""));
 
         // Disconnect HFP only and test connection state summary
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
-                "Connected (no phone), battery 10%");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(
+                        mContext.getString(
+                                R.string.bluetooth_connected_no_headset_battery_level, "10%", ""));
 
         // Disconnect A2DP only and test connection state summary
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
-                "Connected (no media), battery 10%");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(
+                        mContext.getString(
+                                R.string.bluetooth_connected_no_a2dp_battery_level, "10%", ""));
 
         // Disconnect both HFP and A2DP and test connection state summary
         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
-                "Connected (no phone or media), battery 10%");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(
+                        mContext.getString(
+                                R.string.bluetooth_connected_no_headset_no_a2dp_battery_level,
+                                "10%",
+                                ""));
 
         // Disconnect all profiles and test connection state summary
         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
-        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Disconnected");
+        assertThat(mCachedDevice.getCarConnectionSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_disconnected));
     }
 
     @Test
@@ -1819,6 +1895,117 @@
         assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
     }
 
+    @Test
+    public void leAudioHidDevice_leAudioEnabled_setPreferredTransportToLE() {
+
+        when(mProfileManager.getHidProfile()).thenReturn(mHidProfile);
+        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
+        when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(true);
+
+        updateProfileStatus(mHidProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);
+
+        verify(mHidProfile).setPreferredTransport(mDevice, BluetoothDevice.TRANSPORT_LE);
+    }
+
+    @Test
+    public void leAudioHidDevice_leAudioDisabled_setPreferredTransportToBredr() {
+        when(mProfileManager.getHidProfile()).thenReturn(mHidProfile);
+        when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
+        when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(false);
+
+        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHidProfile, BluetoothProfile.STATE_CONNECTED);
+
+        verify(mHidProfile).setPreferredTransport(mDevice, BluetoothDevice.TRANSPORT_BREDR);
+    }
+
+    @Test
+    public void getConnectionSummary_isBroadcastPrimary_returnActive() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        when(mCachedDevice.getDevice()).thenReturn(mDevice);
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                "bluetooth_le_broadcast_fallback_active_group_id",
+                1);
+
+        List<Long> bisSyncState = new ArrayList<>();
+        bisSyncState.add(1L);
+        when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+        List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+        sourceList.add(mLeBroadcastReceiveState);
+        when(mAssistant.getAllSources(any())).thenReturn(sourceList);
+
+        when(mCachedDevice.getGroupId())
+                .thenReturn(
+                        Settings.Secure.getInt(
+                                mContext.getContentResolver(),
+                                "bluetooth_le_broadcast_fallback_active_group_id",
+                                BluetoothCsipSetCoordinator.GROUP_ID_INVALID));
+
+        assertThat(mCachedDevice.getConnectionSummary(false))
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
+    }
+
+    @Test
+    public void getConnectionSummary_isBroadcastNotPrimary_returnActiveMedia() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        when(mCachedDevice.getDevice()).thenReturn(mDevice);
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                "bluetooth_le_broadcast_fallback_active_group_id",
+                1);
+
+        List<Long> bisSyncState = new ArrayList<>();
+        bisSyncState.add(1L);
+        when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState);
+        List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>();
+        sourceList.add(mLeBroadcastReceiveState);
+        when(mAssistant.getAllSources(any())).thenReturn(sourceList);
+
+        when(mCachedDevice.getGroupId()).thenReturn(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+
+        assertThat(mCachedDevice.getConnectionSummary(false))
+                .isEqualTo(
+                        mContext.getString(R.string.bluetooth_active_media_only_no_battery_level));
+    }
+
+    @Test
+    public void getConnectionSummary_supportBroadcastConnected_returnConnectedSupportLe() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        when(mCachedDevice.getDevice()).thenReturn(mDevice);
+        when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(true);
+
+        when(mCachedDevice.getProfiles()).thenReturn(ImmutableList.of(mLeAudioProfile));
+        when(mCachedDevice.isConnected()).thenReturn(true);
+
+        assertThat(mCachedDevice.getConnectionSummary(false))
+                .isEqualTo(mContext.getString(R.string.bluetooth_no_battery_level_lea_support));
+    }
+
+    @Test
+    public void getConnectionSummary_supportBroadcastNotConnected_returnSupportLe() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        when(mCachedDevice.getDevice()).thenReturn(mDevice);
+        when(mLeAudioProfile.isEnabled(mDevice)).thenReturn(true);
+
+        when(mCachedDevice.getProfiles()).thenReturn(ImmutableList.of(mLeAudioProfile));
+        when(mCachedDevice.isConnected()).thenReturn(false);
+
+        assertThat(mCachedDevice.getConnectionSummary(false))
+                .isEqualTo(mContext.getString(R.string.bluetooth_saved_device_lea_support));
+    }
+
+    @Test
+    public void getConnectionSummary_doNotSupportBroadcast_returnNull() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+
+        when(mCachedDevice.getProfiles()).thenReturn(ImmutableList.of());
+
+        assertThat(mCachedDevice.getConnectionSummary(false)).isNull();
+    }
+
     private HearingAidInfo getLeftAshaHearingAidInfo() {
         return new HearingAidInfo.Builder()
                 .setAshaDeviceSide(HearingAidProfile.DeviceSide.SIDE_LEFT)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index 4f8fa2f..cef0835 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -56,7 +56,8 @@
 @Config(shadows = {ShadowBluetoothAdapter.class})
 public class LocalBluetoothProfileManagerTest {
     private final static long HISYNCID = 10;
-
+    @Mock
+    private LocalBluetoothManager mBtManager;
     @Mock
     private CachedBluetoothDeviceManager mDeviceManager;
     @Mock
@@ -77,13 +78,21 @@
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
         mLocalBluetoothAdapter = LocalBluetoothAdapter.getInstance();
-        mEventManager = spy(new BluetoothEventManager(mLocalBluetoothAdapter, mDeviceManager,
-                mContext, /* handler= */ null, /* userHandle= */ null));
+        mEventManager =
+                spy(
+                        new BluetoothEventManager(
+                                mLocalBluetoothAdapter,
+                                mBtManager,
+                                mDeviceManager,
+                                mContext,
+                                /* handler= */ null,
+                                /* userHandle= */ null));
         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
         when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice);
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mDevice);
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager =
+                new LocalBluetoothProfileManager(
+                        mContext, mLocalBluetoothAdapter, mDeviceManager, mEventManager);
     }
 
     /**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java
index b656253..0d318c3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java
@@ -96,7 +96,7 @@
         assertThat(mPowerAllowlistBackend.isAllowlisted(new String[] {PACKAGE_ONE}, UID)).isTrue();
         assertThat(mPowerAllowlistBackend.isAllowlisted(new String[] {PACKAGE_TWO}, UID)).isFalse();
 
-        mPowerAllowlistBackend.addApp(PACKAGE_TWO);
+        mPowerAllowlistBackend.addApp(PACKAGE_TWO, UID);
 
         verify(mDeviceIdleService, atLeastOnce()).addPowerSaveWhitelistApp(PACKAGE_TWO);
         assertThat(mPowerAllowlistBackend.isAllowlisted(PACKAGE_ONE, UID)).isTrue();
@@ -104,7 +104,7 @@
         assertThat(mPowerAllowlistBackend.isAllowlisted(
                 new String[] {PACKAGE_ONE, PACKAGE_TWO}, UID)).isTrue();
 
-        mPowerAllowlistBackend.removeApp(PACKAGE_TWO);
+        mPowerAllowlistBackend.removeApp(PACKAGE_TWO, UID);
 
         verify(mDeviceIdleService, atLeastOnce()).removePowerSaveWhitelistApp(PACKAGE_TWO);
         assertThat(mPowerAllowlistBackend.isAllowlisted(PACKAGE_ONE, UID)).isTrue();
@@ -112,7 +112,7 @@
         assertThat(mPowerAllowlistBackend.isAllowlisted(new String[] {PACKAGE_ONE}, UID)).isTrue();
         assertThat(mPowerAllowlistBackend.isAllowlisted(new String[] {PACKAGE_TWO}, UID)).isFalse();
 
-        mPowerAllowlistBackend.removeApp(PACKAGE_ONE);
+        mPowerAllowlistBackend.removeApp(PACKAGE_ONE, UID);
 
         verify(mDeviceIdleService, atLeastOnce()).removePowerSaveWhitelistApp(PACKAGE_ONE);
         assertThat(mPowerAllowlistBackend.isAllowlisted(PACKAGE_ONE, UID)).isFalse();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index f8dcec7..69faddf 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -110,6 +111,17 @@
                     .setAddress("00:00:00:00:00:00")
                     .build();
 
+    private static final RoutingSessionInfo TEST_REMOTE_ROUTING_SESSION =
+            new RoutingSessionInfo.Builder("FAKE_REMOTE_ROUTING_SESSION_ID", TEST_PACKAGE_NAME)
+                    .addSelectedRoute(TEST_ID_1)
+                    .build();
+
+    private static final MediaRoute2Info TEST_REMOTE_ROUTE =
+            new MediaRoute2Info.Builder(TEST_ID_1, "REMOTE_ROUTE")
+                    .setSystemRoute(true)
+                    .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
+                    .build();
+
     @Mock
     private MediaRouter2Manager mRouterManager;
     @Mock
@@ -133,7 +145,8 @@
         doReturn(mMediaSessionManager).when(mContext).getSystemService(
                 Context.MEDIA_SESSION_SERVICE);
         mInfoMediaManager =
-                new ManagerInfoMediaManager(mContext, TEST_PACKAGE_NAME, mLocalBluetoothManager);
+                new ManagerInfoMediaManager(
+                        mContext, TEST_PACKAGE_NAME, mContext.getUser(), mLocalBluetoothManager);
         mShadowRouter2Manager = ShadowRouter2Manager.getShadow();
         mInfoMediaManager.mRouterManager = MediaRouter2Manager.getInstance(mContext);
     }
@@ -151,7 +164,10 @@
         RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
         mInfoMediaManager.mRouterManager = mRouterManager;
         // Since test is running in Robolectric, return a fake session to avoid NPE.
-        when(mRouterManager.getRoutingSessions(anyString())).thenReturn(List.of(sessionInfo));
+        when(mRouterManager.getRoutingSessions(anyString()))
+                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
+        when(mRouterManager.getSelectedRoutes(any()))
+                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));
 
         mInfoMediaManager.startScan();
         mInfoMediaManager.stopScan();
@@ -191,52 +207,27 @@
 
     @Test
     public void onSessionReleased_shouldUpdateConnectedDevice() {
-        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
-        final RoutingSessionInfo sessionInfo1 = mock(RoutingSessionInfo.class);
-        routingSessionInfos.add(sessionInfo1);
-        final RoutingSessionInfo sessionInfo2 = mock(RoutingSessionInfo.class);
-        routingSessionInfos.add(sessionInfo2);
+        mInfoMediaManager.mRouterManager = mRouterManager;
 
-        final List<String> selectedRoutesSession1 = new ArrayList<>();
-        selectedRoutesSession1.add(TEST_ID_1);
-        when(sessionInfo1.getSelectedRoutes()).thenReturn(selectedRoutesSession1);
-
-        final List<String> selectedRoutesSession2 = new ArrayList<>();
-        selectedRoutesSession2.add(TEST_ID_2);
-        when(sessionInfo2.getSelectedRoutes()).thenReturn(selectedRoutesSession2);
-
-        mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
-
-        final MediaRoute2Info info1 = mock(MediaRoute2Info.class);
-        when(info1.getId()).thenReturn(TEST_ID_1);
-        when(info1.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
-
-        final MediaRoute2Info info2 = mock(MediaRoute2Info.class);
-        when(info2.getId()).thenReturn(TEST_ID_2);
-        when(info2.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
-
-        final List<MediaRoute2Info> routes = new ArrayList<>();
-        routes.add(info1);
-        routes.add(info2);
-        mShadowRouter2Manager.setAllRoutes(routes);
-        mShadowRouter2Manager.setTransferableRoutes(routes);
-
-        final MediaDevice mediaDevice1 = mInfoMediaManager.findMediaDevice(TEST_ID_1);
-        assertThat(mediaDevice1).isNull();
-        final MediaDevice mediaDevice2 = mInfoMediaManager.findMediaDevice(TEST_ID_2);
-        assertThat(mediaDevice2).isNull();
+        // Active routing session is last one in list.
+        when(mRouterManager.getRoutingSessions(anyString()))
+                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION));
+        when(mRouterManager.getSelectedRoutes(TEST_SYSTEM_ROUTING_SESSION))
+                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));
+        when(mRouterManager.getSelectedRoutes(TEST_REMOTE_ROUTING_SESSION))
+                .thenReturn(List.of(TEST_REMOTE_ROUTE));
 
         mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
-        final MediaDevice infoDevice1 = mInfoMediaManager.mMediaDevices.get(0);
-        assertThat(infoDevice1.getId()).isEqualTo(TEST_ID_1);
-        final MediaDevice infoDevice2 = mInfoMediaManager.mMediaDevices.get(1);
-        assertThat(infoDevice2.getId()).isEqualTo(TEST_ID_2);
-        // The active routing session is the last one in the list, which maps to infoDevice2.
-        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice2);
+        MediaDevice remoteDevice = mInfoMediaManager.findMediaDevice(TEST_REMOTE_ROUTE.getId());
+        assertThat(remoteDevice).isNotNull();
+        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(remoteDevice);
 
-        routingSessionInfos.remove(sessionInfo2);
-        mInfoMediaManager.mMediaRouterCallback.onSessionReleased(sessionInfo2);
-        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice1);
+        when(mRouterManager.getRoutingSessions(anyString()))
+                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
+        mInfoMediaManager.mMediaRouterCallback.onSessionReleased(TEST_REMOTE_ROUTING_SESSION);
+        MediaDevice systemRoute = mInfoMediaManager.findMediaDevice(TEST_SYSTEM_ROUTE_ID);
+        assertThat(systemRoute).isNotNull();
+        assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(systemRoute);
     }
 
     @Test
@@ -761,53 +752,48 @@
 
     @Test
     public void onTransferred_getAvailableRoutes_shouldAddMediaDevice() {
-        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
-        final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
-        routingSessionInfos.add(sessionInfo);
-        final List<String> selectedRoutes = new ArrayList<>();
-        selectedRoutes.add(TEST_ID);
-        when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes);
-        mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+        mInfoMediaManager.mRouterManager = mRouterManager;
+        // Since test is running in Robolectric, return a fake session to avoid NPE.
+        when(mRouterManager.getRoutingSessions(anyString()))
+                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
+        when(mRouterManager.getSelectedRoutes(any()))
+                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));
 
-        final MediaRoute2Info info = mock(MediaRoute2Info.class);
         mInfoMediaManager.registerCallback(mCallback);
 
-        when(info.getDeduplicationIds()).thenReturn(Set.of());
-        when(info.getId()).thenReturn(TEST_ID);
-        when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        MediaDevice mediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
+        assertThat(mediaDevice).isNotNull();
+        assertThat(mediaDevice.getId()).isEqualTo(TEST_SYSTEM_ROUTE_ID);
 
-        final List<MediaRoute2Info> routes = new ArrayList<>();
-        routes.add(info);
-        mShadowRouter2Manager.setTransferableRoutes(routes);
+        when(mRouterManager.getRoutingSessions(anyString()))
+                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION));
+        when(mRouterManager.getSelectedRoutes(any())).thenReturn(List.of(TEST_REMOTE_ROUTE));
 
-        final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
-        assertThat(mediaDevice).isNull();
-
-        mInfoMediaManager.mMediaRouterCallback.onTransferred(sessionInfo, sessionInfo);
+        mInfoMediaManager.mMediaRouterCallback.onTransferred(
+                TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION);
 
         final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0);
-        assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
+        assertThat(infoDevice).isNotNull();
+        assertThat(infoDevice.getId()).isEqualTo(TEST_REMOTE_ROUTE.getId());
         assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice);
-        assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size());
-        verify(mCallback).onConnectedDeviceChanged(TEST_ID);
+        verify(mCallback).onConnectedDeviceChanged(TEST_REMOTE_ROUTE.getId());
     }
 
     @Test
     public void onSessionUpdated_shouldDispatchDeviceListAdded() {
-        final MediaRoute2Info info = mock(MediaRoute2Info.class);
-        when(info.getId()).thenReturn(TEST_ID);
-        when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
-        when(info.isSystemRoute()).thenReturn(true);
-
-        final List<MediaRoute2Info> routes = new ArrayList<>();
-        routes.add(info);
-        mShadowRouter2Manager.setAllRoutes(routes);
+        mInfoMediaManager.mRouterManager = mRouterManager;
+        // Since test is running in Robolectric, return a fake session to avoid NPE.
+        when(mRouterManager.getRoutingSessions(anyString()))
+                .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION));
+        when(mRouterManager.getSelectedRoutes(any()))
+                .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE));
 
         mInfoMediaManager.registerCallback(mCallback);
 
-        mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(mock(RoutingSessionInfo.class));
+        mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(TEST_SYSTEM_ROUTING_SESSION);
 
-        verify(mCallback).onDeviceListAdded(any());
+        // Expecting 1st call after registerCallback() and 2nd call after onSessionUpdated().
+        verify(mCallback, times(2)).onDeviceListAdded(any());
     }
 
     @Test
@@ -871,7 +857,7 @@
     }
 
     @Test
-    public void addMediaDevice_deviceIncludedInSelectedDevices_shouldSetAsCurrentConnected() {
+    public void onRoutesUpdated_setsFirstSelectedRouteAsCurrentConnectedDevice() {
         final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
                 mock(CachedBluetoothDeviceManager.class);
 
@@ -886,14 +872,14 @@
 
         when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME))
                 .thenReturn(List.of(selectedBtSession));
+        when(mRouterManager.getSelectedRoutes(any())).thenReturn(List.of(TEST_BLUETOOTH_ROUTE));
         when(mLocalBluetoothManager.getCachedDeviceManager())
                 .thenReturn(cachedBluetoothDeviceManager);
         when(cachedBluetoothDeviceManager.findDevice(any(BluetoothDevice.class)))
                 .thenReturn(cachedDevice);
         mInfoMediaManager.mRouterManager = mRouterManager;
 
-        mInfoMediaManager.mMediaDevices.clear();
-        mInfoMediaManager.addMediaDevice(TEST_BLUETOOTH_ROUTE, selectedBtSession);
+        mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
 
         MediaDevice device = mInfoMediaManager.mMediaDevices.get(0);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 693b7d0..ddb5419 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -21,6 +21,8 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -58,6 +60,7 @@
 import org.robolectric.shadow.api.Shadow;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
@@ -117,6 +120,13 @@
         mInfoMediaManager = mock(
                 InfoMediaManager.class,
                 withSettings().useConstructor(mContext, TEST_PACKAGE_NAME, mLocalBluetoothManager));
+        doReturn(
+                        List.of(
+                                new RoutingSessionInfo.Builder(TEST_SESSION_ID, TEST_PACKAGE_NAME)
+                                        .addSelectedRoute(TEST_DEVICE_ID_1)
+                                        .build()))
+                .when(mInfoMediaManager)
+                .getRoutingSessionsForPackage();
 
         mInfoMediaDevice1 = spy(new InfoMediaDevice(mContext, mRouteInfo1));
         mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2);
@@ -124,15 +134,16 @@
                 new LocalMediaManager(
                         mContext, mLocalBluetoothManager, mInfoMediaManager, TEST_PACKAGE_NAME);
         mLocalMediaManager.mAudioManager = mAudioManager;
+        mLocalMediaManager.registerCallback(mCallback);
+        clearInvocations(mCallback);
     }
 
     @Test
-    public void startScan_mediaDevicesListShouldBeClear() {
+    public void onDeviceListAdded_shouldClearDeviceList() {
         final MediaDevice device = mock(MediaDevice.class);
         mLocalMediaManager.mMediaDevices.add(device);
-
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(1);
-        mLocalMediaManager.startScan();
+        mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(Collections.emptyList());
         assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
     }
 
@@ -147,7 +158,6 @@
         when(device.getId()).thenReturn(TEST_DEVICE_ID_1);
         when(currentDevice.getId()).thenReturn(TEST_CURRENT_DEVICE_ID);
 
-        mLocalMediaManager.registerCallback(mCallback);
         assertThat(mLocalMediaManager.connectDevice(device)).isTrue();
         verify(mInfoMediaManager).connectToDevice(device);
     }
@@ -158,7 +168,6 @@
         mLocalMediaManager.mMediaDevices.add(mInfoMediaDevice2);
         mLocalMediaManager.mCurrentConnectedDevice = mInfoMediaDevice1;
 
-        mLocalMediaManager.registerCallback(mCallback);
         assertThat(mLocalMediaManager.connectDevice(mInfoMediaDevice2)).isTrue();
 
         assertThat(mInfoMediaDevice2.getState()).isEqualTo(LocalMediaManager.MediaDeviceState
@@ -171,7 +180,6 @@
         mLocalMediaManager.mMediaDevices.add(mInfoMediaDevice2);
         mLocalMediaManager.mCurrentConnectedDevice = mInfoMediaDevice1;
 
-        mLocalMediaManager.registerCallback(mCallback);
         assertThat(mLocalMediaManager.connectDevice(mInfoMediaDevice1)).isFalse();
 
         assertThat(mInfoMediaDevice1.getState()).isNotEqualTo(LocalMediaManager.MediaDeviceState
@@ -189,7 +197,6 @@
         when(cachedDevice.isConnected()).thenReturn(false);
         when(cachedDevice.isBusy()).thenReturn(false);
 
-        mLocalMediaManager.registerCallback(mCallback);
         assertThat(mLocalMediaManager.connectDevice(device)).isTrue();
 
         verify(cachedDevice).connect();
@@ -252,7 +259,6 @@
         when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
 
         assertThat(mLocalMediaManager.mMediaDevices).isEmpty();
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(devices);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
@@ -274,7 +280,6 @@
         when(device3.getId()).thenReturn(TEST_DEVICE_ID_3);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(1);
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(devices);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
@@ -292,7 +297,6 @@
         mLocalMediaManager.mMediaDevices.add(device2);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback
                 .onDeviceListRemoved(mLocalMediaManager.mMediaDevices);
 
@@ -302,19 +306,21 @@
 
     @Test
     public void onDeviceListRemoved_phoneDeviceNotLastDeviceAfterRemoveDeviceList_removeList() {
-        final List<MediaDevice> devices = new ArrayList<>();
         final MediaDevice device1 = mock(MediaDevice.class);
         final MediaDevice device2 = mock(MediaDevice.class);
         final MediaDevice device3 = mock(MediaDevice.class);
-        devices.add(device1);
-        devices.add(device3);
+
+        mLocalMediaManager.mMediaDevices.clear();
         mLocalMediaManager.mMediaDevices.add(device1);
         mLocalMediaManager.mMediaDevices.add(device2);
         mLocalMediaManager.mMediaDevices.add(device3);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(3);
-        mLocalMediaManager.registerCallback(mCallback);
-        mLocalMediaManager.mMediaDeviceCallback.onDeviceListRemoved(devices);
+
+        final List<MediaDevice> devicesToRemove = new ArrayList<>();
+        devicesToRemove.add(device1);
+        devicesToRemove.add(device3);
+        mLocalMediaManager.mMediaDeviceCallback.onDeviceListRemoved(devicesToRemove);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(1);
         verify(mCallback).onDeviceListUpdate(any());
@@ -332,7 +338,6 @@
         when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
         when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
 
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_2);
 
         assertThat(mLocalMediaManager.getCurrentConnectedDevice()).isEqualTo(device2);
@@ -352,7 +357,6 @@
         when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
         when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
 
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_1);
 
         verify(mCallback, never()).onDeviceAttributesChanged();
@@ -366,7 +370,6 @@
 
         assertThat(mInfoMediaDevice1.getState()).isEqualTo(LocalMediaManager.MediaDeviceState
                 .STATE_DISCONNECTED);
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_1);
 
         assertThat(mInfoMediaDevice1.getState()).isEqualTo(LocalMediaManager.MediaDeviceState
@@ -375,7 +378,6 @@
 
     @Test
     public void onConnectedDeviceChanged_nullConnectedDevice_noException() {
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_2);
     }
 
@@ -392,7 +394,6 @@
         when(cachedDevice.isConnected()).thenReturn(false);
         when(cachedDevice.isBusy()).thenReturn(false);
 
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.connectDevice(device);
 
         mLocalMediaManager.mDeviceAttributeChangeCallback.onDeviceAttributesChanged();
@@ -410,7 +411,6 @@
                 .STATE_CONNECTING);
         assertThat(mInfoMediaDevice2.getState()).isEqualTo(LocalMediaManager.MediaDeviceState
                 .STATE_CONNECTED);
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onRequestFailed(REASON_UNKNOWN_ERROR);
 
         assertThat(mInfoMediaDevice1.getState()).isEqualTo(LocalMediaManager.MediaDeviceState
@@ -421,8 +421,6 @@
 
     @Test
     public void onDeviceAttributesChanged_shouldBeCalled() {
-        mLocalMediaManager.registerCallback(mCallback);
-
         mLocalMediaManager.mDeviceAttributeChangeCallback.onDeviceAttributesChanged();
 
         verify(mCallback).onDeviceAttributesChanged();
@@ -475,7 +473,6 @@
         when(device1.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(0);
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(devices);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
@@ -497,7 +494,6 @@
         when(cachedDevice.isConnected()).thenReturn(false);
         when(cachedDevice.isBusy()).thenReturn(false);
 
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.connectDevice(device);
 
         verify(cachedDevice).connect();
@@ -512,8 +508,6 @@
 
     @Test
     public void onRequestFailed_shouldDispatchOnRequestFailed() {
-        mLocalMediaManager.registerCallback(mCallback);
-
         mLocalMediaManager.mMediaDeviceCallback.onRequestFailed(1);
 
         verify(mCallback).onRequestFailed(1);
@@ -532,7 +526,6 @@
         mShadowBluetoothAdapter = null;
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(1);
-        mLocalMediaManager.registerCallback(mCallback);
         mLocalMediaManager.mMediaDeviceCallback.onDeviceListAdded(devices);
 
         assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java
index d630301..908f50d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java
@@ -46,6 +46,7 @@
                 new NoOpInfoMediaManager(
                         mContext,
                         /* packageName */ "FAKE_PACKAGE_NAME",
+                        mContext.getUser(),
                         /* localBluetoothManager */ null);
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index 2e7905f..4f3b200 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -20,30 +20,24 @@
 
 import static org.mockito.Mockito.spy;
 
+import android.app.AlarmManager;
 import android.content.Context;
 
+import androidx.test.core.app.ApplicationProvider;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
 
 import java.time.Duration;
+import java.time.Instant;
+import java.util.Locale;
 import java.util.regex.Pattern;
 
 @RunWith(RobolectricTestRunner.class)
 public class PowerUtilTest {
-    private static final String TEST_BATTERY_LEVEL_10 = "10%";
-    private static final long TEN_SEC_MILLIS = Duration.ofSeconds(10).toMillis();
-    private static final long SEVENTEEN_MIN_MILLIS = Duration.ofMinutes(17).toMillis();
-    private static final long FIVE_MINUTES_MILLIS = Duration.ofMinutes(5).toMillis();
-    private static final long TEN_MINUTES_MILLIS = Duration.ofMinutes(10).toMillis();
-    private static final long THREE_DAYS_MILLIS = Duration.ofDays(3).toMillis();
-    private static final long TEN_HOURS_MILLIS = Duration.ofHours(10).toMillis();
-    private static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis();
-    private static final String NORMAL_CASE_EXPECTED_PREFIX = "Should last until about";
-    private static final String ENHANCED_SUFFIX = " based on your usage";
     private static final String BATTERY_RUN_OUT_PREFIX = "Battery may run out by";
     // matches a time (ex: '1:15 PM', '2 AM', '23:00')
     private static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* ((AM)*)|((PM)*)";
@@ -55,29 +49,31 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
+        mContext = spy(ApplicationProvider.getApplicationContext());
     }
 
     @Test
     public void getBatteryTipStringFormatted_moreThanOneDay_usesCorrectString() {
-        String info = PowerUtil.getBatteryTipStringFormatted(mContext,
-                THREE_DAYS_MILLIS);
+        var threeDayMillis = Duration.ofDays(3).toMillis();
 
-        assertThat(info).isEqualTo("More than 3 days left");
+        String batteryTipString = PowerUtil.getBatteryTipStringFormatted(mContext, threeDayMillis);
+
+        assertThat(batteryTipString).isEqualTo("More than 3 days left");
     }
 
     @Test
     public void getBatteryTipStringFormatted_lessThanOneDay_usesCorrectString() {
-        String info = PowerUtil.getBatteryTipStringFormatted(mContext,
-                SEVENTEEN_MIN_MILLIS);
+        var drainTimeMs = Duration.ofMinutes(17).toMillis();
+
+        String batteryTipString = PowerUtil.getBatteryTipStringFormatted(mContext, drainTimeMs);
 
         // ex: Battery may run out by 1:15 PM
-        assertThat(info).containsMatch(Pattern.compile(
-                BATTERY_RUN_OUT_PREFIX + TIME_OF_DAY_REGEX));
+        assertThat(batteryTipString)
+                .containsMatch(Pattern.compile(BATTERY_RUN_OUT_PREFIX + TIME_OF_DAY_REGEX));
     }
 
     @Test
-    public void testRoundToNearestThreshold_roundsCorrectly() {
+    public void roundTimeToNearestThreshold_roundsCorrectly() {
         // test some pretty normal values
         assertThat(PowerUtil.roundTimeToNearestThreshold(1200, 1000)).isEqualTo(1000);
         assertThat(PowerUtil.roundTimeToNearestThreshold(800, 1000)).isEqualTo(1000);
@@ -89,4 +85,33 @@
         assertThat(PowerUtil.roundTimeToNearestThreshold(-120, 100)).isEqualTo(100);
         assertThat(PowerUtil.roundTimeToNearestThreshold(-200, -75)).isEqualTo(225);
     }
+
+    @Test
+    public void getTargetTimeShortString_lessThan15Minutes_returnsTimeShortStringWithoutRounded() {
+        mContext.getSystemService(AlarmManager.class).setTimeZone("UTC");
+        mContext.getResources().getConfiguration().setLocale(Locale.US);
+        var currentTimeMs = Instant.parse("2024-06-06T15:00:00Z").toEpochMilli();
+        var remainingTimeMs = Duration.ofMinutes(15).toMillis() - 1;
+
+        var actualTimeString =
+                PowerUtil.getTargetTimeShortString(mContext, remainingTimeMs, currentTimeMs);
+
+        // due to timezone issue in test case, focus on rounded minutes, remove hours part.
+        assertThat(actualTimeString).endsWith("14 PM");
+    }
+
+    @Test
+    public void getTargetTimeShortString_moreThan15Minutes_returnsTimeShortStringWithRounded() {
+        mContext.getSystemService(AlarmManager.class).setTimeZone("UTC");
+        mContext.getResources().getConfiguration().setLocale(Locale.US);
+        var currentTimeMs = Instant.parse("2024-06-06T15:00:00Z").toEpochMilli();
+        var remainingTimeMs = Duration.ofMinutes(15).toMillis() + 1;
+
+        var actualTimeString =
+                PowerUtil.getTargetTimeShortString(mContext, remainingTimeMs, currentTimeMs);
+
+        // due to timezone issue in test case, focus on rounded minutes, remove hours part.
+        assertThat(actualTimeString).endsWith("30 PM");
+
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
index c7e96bc..00e4772 100644
--- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
@@ -38,6 +38,8 @@
     private List<BluetoothDevice> mMostRecentlyConnectedDevices;
     private BluetoothProfile.ServiceListener mServiceListener;
     private ParcelUuid[] mParcelUuids;
+    private int mIsLeAudioBroadcastSourceSupported;
+    private int mIsLeAudioBroadcastAssistantSupported;
 
     @Implementation
     protected boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
@@ -97,4 +99,22 @@
     public void setUuids(ParcelUuid[] uuids) {
         mParcelUuids = uuids;
     }
+
+    @Implementation
+    protected int isLeAudioBroadcastSourceSupported() {
+        return mIsLeAudioBroadcastSourceSupported;
+    }
+
+    public void setIsLeAudioBroadcastSourceSupported(int isSupported) {
+        mIsLeAudioBroadcastSourceSupported = isSupported;
+    }
+
+    @Implementation
+    protected int isLeAudioBroadcastAssistantSupported() {
+        return mIsLeAudioBroadcastAssistantSupported;
+    }
+
+    public void setIsLeAudioBroadcastAssistantSupported(int isSupported) {
+        mIsLeAudioBroadcastAssistantSupported = isSupported;
+    }
 }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 17d9f1b..097840e 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -338,4 +338,7 @@
 
     <!-- Value to use as default scale for fonts -->
     <item name="def_device_font_scale" format="float" type="dimen">1.0</item>
+
+    <!-- The default ringer mode. See `AudioManager` for list of valid values. -->
+    <integer name="def_ringer_mode">2</integer>
 </resources>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index a33c160..75c0cec 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -272,6 +272,7 @@
         Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
         Settings.Secure.AUDIO_DEVICE_INVENTORY,
         Settings.Secure.SCREEN_RESOLUTION_MODE,
-        Settings.Secure.ACCESSIBILITY_FLOATING_MENU_TARGETS
+        Settings.Secure.ACCESSIBILITY_FLOATING_MENU_TARGETS,
+        Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_SATURATION_LEVEL
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 1bff592..8faf917 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -430,5 +430,7 @@
         VALIDATORS.put(Secure.AUDIO_DEVICE_INVENTORY, ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.SCREEN_RESOLUTION_MODE, new InclusiveIntegerRangeValidator(
                 Secure.RESOLUTION_MODE_UNKNOWN, Secure.RESOLUTION_MODE_FULL));
+        VALIDATORS.put(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_SATURATION_LEVEL,
+                new InclusiveIntegerRangeValidator(0, 10));
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index ad3eb92..e77cf2f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -531,13 +531,22 @@
             pw.println("  put NAMESPACE KEY VALUE [default]");
             pw.println("      Change the contents of KEY to VALUE for the given NAMESPACE.");
             pw.println("      {default} to set as the default value.");
+            pw.println("  override NAMESPACE KEY VALUE");
+            pw.println("      Set flag NAMESPACE/KEY to the given VALUE, and ignores "
+                    + "server-updates for");
+            pw.println("      this flag. This can still be called even if there is no underlying "
+                    + "value set.");
             pw.println("  delete NAMESPACE KEY");
             pw.println("      Delete the entry for KEY for the given NAMESPACE.");
+            pw.println("  clear_override NAMESPACE KEY");
+            pw.println("      Clear local sticky flag override for KEY in the given NAMESPACE.");
             pw.println("  list_namespaces [--public]");
             pw.println("      Prints the name of all (or just the public) namespaces.");
             pw.println("  list [NAMESPACE]");
             pw.println("      Print all keys and values defined, optionally for the given "
                     + "NAMESPACE.");
+            pw.println("  list_local_overrides");
+            pw.println("      Print all flags that have been overridden.");
             pw.println("  reset RESET_MODE [NAMESPACE]");
             pw.println("      Reset all flag values, optionally for a NAMESPACE, according to "
                     + "RESET_MODE.");
@@ -547,8 +556,9 @@
                     + "flags are reset");
             pw.println("  set_sync_disabled_for_tests SYNC_DISABLED_MODE");
             pw.println("      Modifies bulk property setting behavior for tests. When in one of the"
-                    + " disabled modes this ensures that config isn't overwritten.");
-            pw.println("      SYNC_DISABLED_MODE is one of:");
+                    + " disabled modes");
+            pw.println("      this ensures that config isn't overwritten. SYNC_DISABLED_MODE is "
+                    + "one of:");
             pw.println("        none: Sync is not disabled. A reboot may be required to restart"
                     + " syncing.");
             pw.println("        persistent: Sync is disabled, this state will survive a reboot.");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 46cee6b..fa9b279 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1760,6 +1760,9 @@
                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
                 SecureSettingsProto.Accessibility.DISPLAY_DALTONIZER);
         dumpSetting(s, p,
+                Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_SATURATION_LEVEL,
+                SecureSettingsProto.Accessibility.DISPLAY_DALTONIZER_SATURATION_LEVEL);
+        dumpSetting(s, p,
                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
                 SecureSettingsProto.Accessibility.DISPLAY_INVERSION_ENABLED);
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1ead14a..096cccc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3943,8 +3943,10 @@
                         globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
                                 Integer.toString(Settings.Global.ZEN_MODE_OFF), null,
                                 true, SettingsState.SYSTEM_PACKAGE_NAME);
+                        final int defaultRingerMode =
+                                getContext().getResources().getInteger(R.integer.def_ringer_mode);
                         globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER,
-                                Integer.toString(AudioManager.RINGER_MODE_NORMAL), null,
+                                Integer.toString(defaultRingerMode), null,
                                 true, SettingsState.SYSTEM_PACKAGE_NAME);
                     }
                     currentVersion = 119;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index e2b61b4..68bc96d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -1127,7 +1127,7 @@
                     Slog.i(LOG_TAG, "[PERSIST END]");
                 }
             } catch (Throwable t) {
-                Slog.wtf(LOG_TAG, "Failed to write settings, restoring old file", t);
+                Slog.e(LOG_TAG, "Failed to write settings, restoring old file", t);
                 if (t instanceof IOException) {
                     if (t.getMessage().contains("Couldn't create directory")) {
                         if (DEBUG) {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index f42efe2..c891dfc 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -840,6 +840,8 @@
                         Settings.Secure.BIOMETRIC_APP_ENABLED,
                         Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED,
                         Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED,
+                        Settings.Secure.BIOMETRIC_FINGERPRINT_VIRTUAL_ENABLED,
+                        Settings.Secure.BIOMETRIC_FACE_VIRTUAL_ENABLED,
                         Settings.Secure.BLUETOOTH_ADDR_VALID,
                         Settings.Secure.BLUETOOTH_ADDRESS,
                         Settings.Secure.BLUETOOTH_NAME,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index b94e224..46bf494 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -934,6 +934,9 @@
     <!-- Permission required for Cts test - CtsSettingsTestCases -->
     <uses-permission android:name="android.permission.PREPARE_FACTORY_RESET" />
 
+    <!-- Permission required for CTS test - FileIntegrityManagerTest -->
+    <uses-permission android:name="android.permission.SETUP_FSVERITY" />
+
     <application
         android:label="@string/app_label"
         android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index b52a83c..90f0962 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -35,7 +35,7 @@
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Kon nie foutverslagbesonderhede by ZIP-lêer voeg nie"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"naamloos"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"Besonderhede"</string>
-    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skermkiekie"</string>
+    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skermskoot"</string>
     <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Skermkiekie is suksesvol geneem."</string>
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kon nie skermkiekie neem nie."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Foutverslag <xliff:g id="ID">#%d</xliff:g> se besonderhede"</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 42952de..5ac0e44 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -50,7 +50,6 @@
 import android.os.Binder;
 import android.os.BugreportManager;
 import android.os.BugreportManager.BugreportCallback;
-import android.os.BugreportManager.BugreportCallback.BugreportErrorCode;
 import android.os.BugreportParams;
 import android.os.Bundle;
 import android.os.FileUtils;
@@ -169,6 +168,8 @@
     static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION";
     static final String EXTRA_ORIGINAL_INTENT = "android.intent.extra.ORIGINAL_INTENT";
     static final String EXTRA_INFO = "android.intent.extra.INFO";
+    static final String EXTRA_EXTRA_ATTACHMENT_URI =
+            "android.intent.extra.EXTRA_ATTACHMENT_URI";
 
     private static final int MSG_SERVICE_COMMAND = 1;
     private static final int MSG_DELAYED_SCREENSHOT = 2;
@@ -634,9 +635,10 @@
         long nonce = intent.getLongExtra(EXTRA_BUGREPORT_NONCE, 0);
         String baseName = getBugreportBaseName(bugreportType);
         String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
+        Uri extraAttachment = intent.getParcelableExtra(EXTRA_EXTRA_ATTACHMENT_URI, Uri.class);
 
-        BugreportInfo info = new BugreportInfo(mContext, baseName, name,
-                shareTitle, shareDescription, bugreportType, mBugreportsDir, nonce);
+        BugreportInfo info = new BugreportInfo(mContext, baseName, name, shareTitle,
+                shareDescription, bugreportType, mBugreportsDir, nonce, extraAttachment);
         synchronized (mLock) {
             if (info.bugreportFile.exists()) {
                 Log.e(TAG, "Failed to start bugreport generation, the requested bugreport file "
@@ -1184,6 +1186,10 @@
             clipData.addItem(new ClipData.Item(null, null, null, screenshotUri));
             attachments.add(screenshotUri);
         }
+        if (info.extraAttachment != null) {
+            clipData.addItem(new ClipData.Item(null, null, null, info.extraAttachment));
+            attachments.add(info.extraAttachment);
+        }
         intent.setClipData(clipData);
         intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);
 
@@ -2042,6 +2048,9 @@
          */
         final long nonce;
 
+        @Nullable
+        public Uri extraAttachment = null;
+
         private final Object mLock = new Object();
 
         /**
@@ -2049,7 +2058,8 @@
          */
         BugreportInfo(Context context, String baseName, String name,
                 @Nullable String shareTitle, @Nullable String shareDescription,
-                @BugreportParams.BugreportMode int type, File bugreportsDir, long nonce) {
+                @BugreportParams.BugreportMode int type, File bugreportsDir, long nonce,
+                @Nullable Uri extraAttachment) {
             this.context = context;
             this.name = this.initialName = name;
             this.shareTitle = shareTitle == null ? "" : shareTitle;
@@ -2058,6 +2068,7 @@
             this.nonce = nonce;
             this.baseName = baseName;
             this.bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
+            this.extraAttachment = extraAttachment;
         }
 
         void createBugreportFile() {
diff --git a/packages/SimAppDialog/res/values-pt-rBR/strings.xml b/packages/SimAppDialog/res/values-pt-rBR/strings.xml
index abf8dbd..fe31aa0 100644
--- a/packages/SimAppDialog/res/values-pt-rBR/strings.xml
+++ b/packages/SimAppDialog/res/values-pt-rBR/strings.xml
@@ -22,5 +22,5 @@
     <string name="install_carrier_app_description" msgid="4014303558674923797">"Para que o novo chip funcione corretamente, instale o app <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Para que o novo chip funcione corretamente, instale o app da operadora"</string>
     <string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Agora não"</string>
-    <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Fazer o download do app"</string>
+    <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Baixar o app"</string>
 </resources>
diff --git a/packages/SimAppDialog/res/values-pt/strings.xml b/packages/SimAppDialog/res/values-pt/strings.xml
index abf8dbd..fe31aa0 100644
--- a/packages/SimAppDialog/res/values-pt/strings.xml
+++ b/packages/SimAppDialog/res/values-pt/strings.xml
@@ -22,5 +22,5 @@
     <string name="install_carrier_app_description" msgid="4014303558674923797">"Para que o novo chip funcione corretamente, instale o app <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Para que o novo chip funcione corretamente, instale o app da operadora"</string>
     <string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Agora não"</string>
-    <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Fazer o download do app"</string>
+    <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Baixar o app"</string>
 </resources>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 40db52e..e2af631 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -117,6 +117,7 @@
         "SystemUILogLib",
         "SystemUIPluginLib",
         "SystemUISharedLib",
+        "SystemUI-shared-utils",
         "SystemUI-statsd",
         "SettingsLib",
         "com_android_systemui_flags_lib",
@@ -190,6 +191,7 @@
     lint: {
         extra_check_modules: ["SystemUILintChecker"],
         warning_checks: ["MissingApacheLicenseDetector"],
+        baseline_filename: "lint-baseline.xml",
     },
 }
 
@@ -263,6 +265,7 @@
         "SystemUISharedLib",
         "SystemUICustomizationLib",
         "SystemUICustomizationTestUtils",
+        "SystemUI-shared-utils",
         "SystemUI-statsd",
         "SettingsLib",
         "com_android_systemui_flags_lib",
@@ -361,6 +364,7 @@
         "SystemUICustomizationTestUtils",
         "androidx.compose.runtime_runtime",
         "kosmos",
+        "androidx.test.rules",
     ],
     libs: [
         "android.test.runner",
@@ -422,6 +426,7 @@
     kotlincflags: ["-Xjvm-default=all"],
     optimize: {
         shrink_resources: false,
+        optimized_shrink_resources: false,
         proguard_flags_files: ["proguard.flags"],
     },
 
@@ -511,6 +516,7 @@
                 optimize: true,
                 shrink: true,
                 shrink_resources: true,
+                optimized_shrink_resources: true,
                 ignore_warnings: false,
                 proguard_compatibility: false,
             },
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index bbc9fe4..5cc3caf 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -367,6 +367,9 @@
 
     <uses-permission android:name="android.permission.MONITOR_STICKY_MODIFIER_STATE" />
 
+    <!-- To follow the grammatical gender preference -->
+    <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
+
     <!-- Listen to (dis-)connection of external displays and enable / disable them. -->
     <uses-permission android:name="android.permission.MANAGE_DISPLAYS" />
 
@@ -1033,6 +1036,7 @@
 
         <receiver
             android:name=".statusbar.KeyboardShortcutsReceiver"
+            android:visibleToInstantApps="true"
             android:exported="true">
             <intent-filter>
                 <action android:name="com.android.intent.action.DISMISS_KEYBOARD_SHORTCUTS" />
@@ -1113,5 +1117,11 @@
                 android:name="android.service.dream"
                 android:resource="@xml/home_controls_dream_metadata" />
         </service>
+
+        <activity android:name="com.android.systemui.keyboard.shortcut.ShortcutHelperActivity"
+            android:exported="false"
+            android:theme="@style/ShortcutHelperTheme"
+            android:excludeFromRecents="true"
+            android:finishOnCloseSystemDialogs="true" />
     </application>
 </manifest>
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 78cacec..796e391 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -60,7 +60,6 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
 [email protected]
 [email protected]
 [email protected]
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
index 648cc3b..a98625f 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
@@ -40,7 +40,7 @@
             android:exported="true"
             android:label="@string/accessibility_menu_settings_name"
             android:launchMode="singleTop"
-            android:theme="@style/Theme.SettingsBase">
+            android:theme="@style/SettingsTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
 
@@ -59,4 +59,4 @@
             <action android:name="android.intent.action.VOICE_COMMAND" />
         </intent>
     </queries>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/Android.bp
index f74e59a..0ff856e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/Android.bp
@@ -5,6 +5,7 @@
 aconfig_declarations {
     name: "com_android_a11y_menu_flags",
     package: "com.android.systemui.accessibility.accessibilitymenu",
+    container: "system",
     srcs: [
         "accessibility.aconfig",
     ],
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
index f5db6a4..d868d5c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui.accessibility.accessibilitymenu"
+container: "system"
 
 # NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
 
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml
index cbb5ad7..56fd06c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-af/strings.xml
@@ -12,7 +12,7 @@
     <string name="lockscreen_label" msgid="648347953557887087">"Sluitskerm"</string>
     <string name="quick_settings_label" msgid="2999117381487601865">"Kitsinstellings"</string>
     <string name="notifications_label" msgid="6829741046963013567">"Kennisgewings"</string>
-    <string name="screenshot_label" msgid="863978141223970162">"Skermkiekie"</string>
+    <string name="screenshot_label" msgid="863978141223970162">"Skermskoot"</string>
     <string name="screenshot_utterance" msgid="1430760563401895074">"Neem skermkiekie"</string>
     <string name="volume_up_label" msgid="8592766918780362870">"Volume harder"</string>
     <string name="volume_down_label" msgid="8574981863656447346">"Volume sagter"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml
index e5dd693..15eb928 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-cs/strings.xml
@@ -21,7 +21,7 @@
     <string name="previous_button_content_description" msgid="840869171117765966">"Zpět na předchozí obrazovku"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Přejít na další obrazovku"</string>
     <string name="accessibility_menu_description" msgid="4458354794093858297">"Nabídka usnadnění přístupu zobrazuje na obrazovce velkou nabídku k ovládání zařízení. Můžete zamknout zařízení, upravit hlasitost a jas, pořídit snímek obrazovky apod."</string>
-    <string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládat zařízení pomocí velké nabídky"</string>
+    <string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládání zařízení pomocí velké nabídky"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Nastavení nabídky usnadnění přístupu"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Velká tlačítka"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Zvětšit tlačítka v nabídce přístupnosti"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml
index 5e31739..8f2abac 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fi/strings.xml
@@ -21,7 +21,7 @@
     <string name="previous_button_content_description" msgid="840869171117765966">"Siirry edelliselle näytöllä"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Siirry seuraavalle näytölle"</string>
     <string name="accessibility_menu_description" msgid="4458354794093858297">"Saavutettavuusvalikko on suuri näyttövalikko, josta voit ohjata laitettasi. Voit esimerkiksi lukita laitteen, säätää äänenvoimakkuutta ja kirkkautta sekä ottaa kuvakaappauksia."</string>
-    <string name="accessibility_menu_summary" msgid="340071398148208130">"Ohjaa laitetta suurella valikolla"</string>
+    <string name="accessibility_menu_summary" msgid="340071398148208130">"Ohjaa laitetta suuren valikon avulla"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Saavutettavuusvalikon asetukset"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Suuret painikkeet"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Suurenna saavutettavuusvalikon painikkeita"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml
index 1cb9b5e..3d59c0b 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hi/strings.xml
@@ -2,7 +2,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="accessibility_menu_service_name" msgid="730136711554740131">"सुलभता मेन्यू"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"सुलभता मेन्यू, स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इसकी मदद से, अपने डिवाइस को कंट्रोल किया जा सकता है. इस मेन्यू में जाकर, अपना डिवाइस लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ कंट्रोल करने जैसे कई दूसरे काम किए जा सकते हैं."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"सुलभता मेन्यू, डिवाइस की स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इस मेन्यू में जाकर, डिवाइस को लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ को कंट्रोल करने जैसे कई काम किए जा सकते हैं."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"सुलभता सेटिंग"</string>
@@ -20,7 +20,7 @@
     <string name="brightness_down_label" msgid="7115662941913272072">"स्क्रीन की रोशनी कम करें"</string>
     <string name="previous_button_content_description" msgid="840869171117765966">"पिछली स्क्रीन पर जाएं"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"अगली स्क्रीन पर जाएं"</string>
-    <string name="accessibility_menu_description" msgid="4458354794093858297">"सुलभता मेन्यू, स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इसकी मदद से, अपने डिवाइस को कंट्रोल किया जा सकता है. इस मेन्यू में जाकर, अपना डिवाइस लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ कंट्रोल करने जैसे कई दूसरे काम किए जा सकते हैं."</string>
+    <string name="accessibility_menu_description" msgid="4458354794093858297">"सुलभता मेन्यू, डिवाइस की स्क्रीन पर दिखने वाला एक बड़ा मेन्यू होता है. इस मेन्यू में जाकर, डिवाइस को लॉक करने, स्क्रीनशॉट लेने, स्क्रीन की रोशनी और आवाज़ को कंट्रोल करने जैसे कई काम किए जा सकते हैं."</string>
     <string name="accessibility_menu_summary" msgid="340071398148208130">"बड़े मेन्यू की मदद से डिवाइस को कंट्रोल करें"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"सुलभता मेन्यू सेटिंग"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"बड़े बटन"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hu/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hu/strings.xml
index 978deaa..13f8c09 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hu/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hu/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="accessibility_menu_service_name" msgid="730136711554740131">"Kisegítő lehetőségek menüje"</string>
+    <string name="accessibility_menu_service_name" msgid="730136711554740131">"Kisegítő lehetőségek menü"</string>
     <string name="accessibility_menu_intro" msgid="3164193281544042394">"A Kisegítő lehetőségek menüje az eszköz vezérlésére szolgáló nagyméretű, képernyőn megjelenő menü. Lezárhatja vele az eszközt, szabályozhatja a hang- és a fényerőt, képernyőképeket készíthet, és egyebekre is használhatja."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Segéd"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Segéd"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml
index fa8b587..98c91ed 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ky/strings.xml
@@ -21,7 +21,7 @@
     <string name="previous_button_content_description" msgid="840869171117765966">"Мурунку экранга өтүү"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Кийинки экранга өтүү"</string>
     <string name="accessibility_menu_description" msgid="4458354794093858297">"Атайын мүмкүнчүлүктөр менюсу — бул түзмөгүңүздү көзөмөлдөөнү жеңилдетүүгө ылайыкташтырылган экрандагы чоң меню. Түзмөгүңүздү кулпулап, үнүнүн катуулугун жана экрандын жарыктыгын көзөмөлдөп, скриншотторду тартып жана башка аракеттерди аткара аласыз."</string>
-    <string name="accessibility_menu_summary" msgid="340071398148208130">"Түзмөктү чоң менюдан башкаруу"</string>
+    <string name="accessibility_menu_summary" msgid="340071398148208130">"Түзмөктү чоң менюдан башкарасыз"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Атайын мүмкүнчүлүктөр менюсунун параметрлери"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Чоң баскычтар"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Атайын мүмкүнчүлүктөр менюсундагы баскычтардын өлчөмүн чоңойтот"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml
index 9c1ea75d..fd34732 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ms/strings.xml
@@ -2,14 +2,14 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menu Kebolehaksesan"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Menu Kebolehaksesan menyediakan menu pada skrin yang besar untuk mengawal peranti anda. Anda boleh mengunci peranti anda, mengawal kelantangan dan kecerahan, mengambil tangkapan skrin dan banyak lagi."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Menu Kebolehaksesan menyediakan menu yang besar pada skrin untuk mengawal peranti anda. Anda boleh mengunci peranti, mengawal kelantangan dan kecerahan, mengambil tangkapan skrin dan banyak lagi."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"Tetapan Kebolehaksesan"</string>
     <string name="power_label" msgid="7699720321491287839">"Kuasa"</string>
     <string name="power_utterance" msgid="7444296686402104807">"Pilihan kuasa"</string>
     <string name="recent_apps_label" msgid="6583276995616385847">"Apl terbaharu"</string>
-    <string name="lockscreen_label" msgid="648347953557887087">"Kunci skrin"</string>
+    <string name="lockscreen_label" msgid="648347953557887087">"Skrin kunci"</string>
     <string name="quick_settings_label" msgid="2999117381487601865">"Tetapan Pantas"</string>
     <string name="notifications_label" msgid="6829741046963013567">"Pemberitahuan"</string>
     <string name="screenshot_label" msgid="863978141223970162">"Tangkapan skrin"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml
index a8d6a0b..3f72d95 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml
@@ -2,7 +2,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="accessibility_menu_service_name" msgid="730136711554740131">"Toegankelijkheids­menu"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid beheren en screenshots maken."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid aanpassen en screenshots maken."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistent"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistent"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"Instellingen voor toegankelijkheid"</string>
@@ -21,7 +21,7 @@
     <string name="previous_button_content_description" msgid="840869171117765966">"Ga naar vorig scherm"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Ga naar volgend scherm"</string>
     <string name="accessibility_menu_description" msgid="4458354794093858297">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid aanpassen en screenshots maken."</string>
-    <string name="accessibility_menu_summary" msgid="340071398148208130">"Bedien apparaat via groot menu"</string>
+    <string name="accessibility_menu_summary" msgid="340071398148208130">"Bedien het apparaat via een groot menu"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Instellingen toegankelijkheidsmenu"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Grote knoppen"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Vergroot knoppen in het toegankelijkheidsmenu"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-or/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-or/strings.xml
index 3a40b9f2..0310c86 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-or/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-or/strings.xml
@@ -10,7 +10,7 @@
     <string name="power_utterance" msgid="7444296686402104807">"ପାୱର୍ ବିକଳ୍ପ"</string>
     <string name="recent_apps_label" msgid="6583276995616385847">"ବର୍ତ୍ତମାନର ଆପ୍‌"</string>
     <string name="lockscreen_label" msgid="648347953557887087">"ସ୍କ୍ରୀନ୍‌ ଲକ୍ କରନ୍ତୁ"</string>
-    <string name="quick_settings_label" msgid="2999117381487601865">"କ୍ୱିକ ସେଟିଂସ"</string>
+    <string name="quick_settings_label" msgid="2999117381487601865">"କୁଇକ ସେଟିଂସ"</string>
     <string name="notifications_label" msgid="6829741046963013567">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="screenshot_label" msgid="863978141223970162">"ସ୍କ୍ରିନସଟ"</string>
     <string name="screenshot_utterance" msgid="1430760563401895074">"ସ୍କ୍ରୀନଶଟ୍‌ ନିଅନ୍ତୁ"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml
index 44aff75..ff8b632 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rPT/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menu Acessibilidade"</string>
+    <string name="accessibility_menu_service_name" msgid="730136711554740131">"menu Acessibilidade"</string>
     <string name="accessibility_menu_intro" msgid="3164193281544042394">"O menu Acessibilidade disponibiliza um menu grande no ecrã para controlar o dispositivo. Pode bloquear o dispositivo, controlar o volume e o brilho, fazer capturas de ecrã e muito mais."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistente"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistente"</string>
@@ -21,7 +21,7 @@
     <string name="previous_button_content_description" msgid="840869171117765966">"Ir para o ecrã anterior"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Ir para o ecrã seguinte"</string>
     <string name="accessibility_menu_description" msgid="4458354794093858297">"O menu Acessibilidade disponibiliza um menu grande no ecrã para controlar o dispositivo. Pode bloquear o dispositivo, controlar o volume e o brilho, fazer capturas de ecrã e muito mais."</string>
-    <string name="accessibility_menu_summary" msgid="340071398148208130">"Controle o dispositivo através do menu grande"</string>
+    <string name="accessibility_menu_summary" msgid="340071398148208130">"Controlar dispositivo através do menu grande"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Definições do menu Acessibilidade"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Botões grandes"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Aumentar o tamanho dos botões do menu Acessibilidade"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml
index 2647498..62f63a8 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-sk/strings.xml
@@ -2,7 +2,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="accessibility_menu_service_name" msgid="730136711554740131">"Ponuka Dostupnosť"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Ponukou dostupnosti sa rozumie veľká ponuka na obrazovke, pomocou ktorej môžete ovládať zariadenie. Môžete ho uzamknúť, ovládať hlasitosť a jas, vytvárať snímky obrazovky a mnoho ďalšieho."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Ponukou Dostupnosť sa rozumie veľká ponuka na obrazovke, pomocou ktorej môžete ovládať zariadenie. Môžete ho uzamknúť, ovládať hlasitosť a jas, vytvárať snímky obrazovky a mnoho ďalšieho."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Asistent"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Asistent"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"Nastavenia dostupnosti"</string>
@@ -21,7 +21,7 @@
     <string name="previous_button_content_description" msgid="840869171117765966">"Prejsť na predchádzajúcu obrazovku"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Prejsť na ďalšiu obrazovku"</string>
     <string name="accessibility_menu_description" msgid="4458354794093858297">"Ponuka dostupnosti spustí na obrazovke telefónu veľkú ponuku, pomocou ktorej môžete ovládať svoje zariadenie. Môžete ho uzamknúť, ovládať hlasitosť a jas, vytvárať snímky obrazovky a mnoho ďalšieho."</string>
-    <string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládať zariadenie pomocou veľkej ponuky"</string>
+    <string name="accessibility_menu_summary" msgid="340071398148208130">"Ovládanie zariadenia pomocou veľkej ponuky"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Nastavenia ponuky dostupnosti"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Veľké tlačidlá"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Zväčšiť tlačidlá ponuky dostupnosti"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml
index 4169155..a138fa9 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml
@@ -21,6 +21,11 @@
     <item name="android:colorControlNormal">@color/colorControlNormal</item>
   </style>
 
+  <style name="SettingsTheme" parent="Theme.SettingsBase">
+    <!-- Quick fix so that the preference page doesn't render under its parent header. -->
+    <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+  </style>
+
   <!--The basic theme for service and test case only-->
   <style name="A11yMenuBaseTheme" parent="android:Theme.DeviceDefault.Light">
     <item name="android:windowActionBar">false</item>
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
index 5f3d1ea..0ab99fa 100644
--- 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
@@ -30,8 +30,6 @@
 import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_TOGGLE_MENU;
 import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.PACKAGE_NAME;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Instrumentation;
 import android.app.KeyguardManager;
@@ -449,7 +447,10 @@
         closeScreen();
         wakeUpScreen();
 
-        assertThat(isMenuVisible()).isFalse();
+        TestUtils.waitUntil("Menu did not close.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> !isMenuVisible()
+        );
     }
 
     @Test
diff --git a/packages/SystemUI/aconfig/Android.bp b/packages/SystemUI/aconfig/Android.bp
index 15c2c17..1858c80 100644
--- a/packages/SystemUI/aconfig/Android.bp
+++ b/packages/SystemUI/aconfig/Android.bp
@@ -36,6 +36,7 @@
 aconfig_declarations {
     name: "com_android_systemui_flags",
     package: "com.android.systemui",
+    container: "system",
     srcs: [
         "*.aconfig",
     ],
@@ -44,4 +45,5 @@
 java_aconfig_library {
     name: "com_android_systemui_flags_lib",
     aconfig_declarations: "com_android_systemui_flags",
+    sdk_version: "system_current",
 }
diff --git a/packages/SystemUI/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig
index 866aa89..14ebc39 100644
--- a/packages/SystemUI/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/aconfig/accessibility.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui"
+container: "system"
 
 # NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
 
@@ -31,6 +32,16 @@
 }
 
 flag {
+    name: "floating_menu_narrow_target_content_observer"
+    namespace: "accessibility"
+    description: "stops the FAB from monitoring enabled services to trigger target content changes."
+    bug: "331740049"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "floating_menu_overlaps_nav_bars_flag"
     namespace: "accessibility"
     description: "Adjusts bounds to allow the floating menu to render on top of navigation bars."
diff --git a/packages/SystemUI/aconfig/biometrics_framework.aconfig b/packages/SystemUI/aconfig/biometrics_framework.aconfig
index 7cc0c83..bd1a442 100644
--- a/packages/SystemUI/aconfig/biometrics_framework.aconfig
+++ b/packages/SystemUI/aconfig/biometrics_framework.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui"
+container: "system"
 
 # NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
 
@@ -14,4 +15,4 @@
     namespace: "biometrics_framework"
     description: "Refactors Biometric Prompt to use a ConstraintLayout"
     bug: "288175072"
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/aconfig/communal.aconfig b/packages/SystemUI/aconfig/communal.aconfig
index 2c6ff97..2e9af7e 100644
--- a/packages/SystemUI/aconfig/communal.aconfig
+++ b/packages/SystemUI/aconfig/communal.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui"
+container: "system"
 
 flag {
     name: "communal_hub"
diff --git a/packages/SystemUI/aconfig/cross_device_control.aconfig b/packages/SystemUI/aconfig/cross_device_control.aconfig
index d3f14c1..5f9a4f4 100644
--- a/packages/SystemUI/aconfig/cross_device_control.aconfig
+++ b/packages/SystemUI/aconfig/cross_device_control.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui"
+container: "system"
 
 flag {
     name: "legacy_le_audio_sharing"
diff --git a/packages/SystemUI/aconfig/predictive_back.aconfig b/packages/SystemUI/aconfig/predictive_back.aconfig
index 7bbe82c..46eb9e1 100644
--- a/packages/SystemUI/aconfig/predictive_back.aconfig
+++ b/packages/SystemUI/aconfig/predictive_back.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui"
+container: "system"
 
 flag {
     name: "predictive_back_sysui"
@@ -26,4 +27,4 @@
     namespace: "systemui"
     description: "Enable Predictive Back Animation for SysUI dialogs"
     bug: "327721544"
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 4bfc629..fadef1e 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.systemui"
+container: "system"
 
 flag {
     name: "example_flag"
@@ -25,6 +26,14 @@
 }
 
 flag {
+   name: "refactor_keyguard_dismiss_intent"
+   namespace: "systemui"
+   description: "Update how keyguard dismiss intents are stored."
+   bug: "275069969"
+}
+
+flag {
+
     name: "notification_heads_up_cycling"
     namespace: "systemui"
     description: "Heads-up notification cycling animation for the Notification Avalanche feature."
@@ -52,6 +61,16 @@
 }
 
 flag {
+   name: "notification_over_expansion_clipping_fix"
+   namespace: "systemui"
+   description: "fix NSSL clipping when over-expanding; fixes split shade bug."
+   bug: "288553572"
+   metadata {
+        purpose: PURPOSE_BUGFIX
+   }
+}
+
+flag {
     name: "notification_async_group_header_inflation"
     namespace: "systemui"
     description: "Inflates the notification group summary header views from the background thread."
@@ -139,6 +158,16 @@
 }
 
 flag {
+   name: "pss_app_selector_recents_split_screen"
+   namespace: "systemui"
+   description: "Allows recent apps selected for partial screenshare to be launched in split screen mode"
+   bug: "320449039"
+   metadata {
+        purpose: PURPOSE_BUGFIX
+   }
+}
+
+flag {
     name: "notifications_background_icons"
     namespace: "systemui"
     description: "Moves part of the notification icon updates to the background."
@@ -319,6 +348,16 @@
 }
 
 flag {
+    name: "status_bar_monochrome_icons_fix"
+    namespace: "systemui"
+    description: "Fixes the status bar icon size when drawing InsetDrawables (ie. monochrome icons)"
+    bug: "329091967"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "compose_bouncer"
     namespace: "systemui"
     description: "Use the new compose bouncer in SystemUI"
@@ -448,14 +487,17 @@
 }
 
 flag {
-    name: "screenshot_private_profile"
+    name: "screenshot_private_profile_behavior_fix"
     namespace: "systemui"
     description: "Private profile support for screenshots"
     bug: "327613051"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
 }
 
 flag {
-    name: "screenshot_shelf_ui"
+    name: "screenshot_shelf_ui2"
     namespace: "systemui"
     description: "Use new shelf UI flow for screenshots"
     bug: "329659738"
@@ -715,3 +757,74 @@
       " Compose for the UI."
     bug: "325099249"
 }
+
+flag {
+  name: "remove_dream_overlay_hide_on_touch"
+  namespace: "systemui"
+  description: "Removes logic to hide the dream overlay on user interaction, as it conflicts with various transitions"
+  bug: "329091030"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+    name: "keyboard_docking_indicator"
+    namespace: "systemui"
+    description: "Glow bar indicator reveals upon keyboard docking."
+    bug: "324600132"
+}
+
+flag {
+    name: "keyboard_shortcut_helper_rewrite"
+    namespace: "systemui"
+    description: "A new implementation of the keyboards shortcuts helper sheet."
+    bug: "327364197"
+}
+
+flag {
+  name: "dream_overlay_bouncer_swipe_direction_filtering"
+  namespace: "systemui"
+  description: "do not initiate bouncer swipe when the direction is opposite of the expansion"
+  bug: "333632464"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+    name: "dream_input_session_pilfer_once"
+    namespace: "systemui"
+    description: "Pilfer at most once per input session"
+    bug: "324600132"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    name: "slice_broadcast_relay_in_background"
+    namespace: "systemui"
+    description: "Move handling of slice broadcast relay broadcasts to background threads"
+    bug: "334767208"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    name: "register_battery_controller_receivers_in_corestartable"
+    namespace: "systemui"
+    description: "Decide whether to register the receivers in battery controller impl in the BatteryControllerStartable corestartable."
+    bug: "307517093"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    name: "enforce_brightness_base_user_restriction"
+    namespace: "systemui"
+    description: "Enforce BaseUserRestriction for DISALLOW_CONFIG_BRIGHTNESS."
+    bug: "329205638"
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
index 9ce30fd..1e60b98 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
@@ -599,6 +599,12 @@
             )
         }
 
+        init {
+            // We do this check here to cover all entry points, including Launcher which doesn't
+            // call startIntentWithAnimation()
+            if (!controller.isLaunching) TransitionAnimator.checkReturnAnimationFrameworkFlag()
+        }
+
         @UiThread
         internal fun postTimeouts() {
             if (timeoutHandler != null) {
@@ -637,7 +643,28 @@
                 return
             }
 
-            startAnimation(apps, nonApps, callback)
+            val window = findRootTaskIfPossible(apps)
+            if (window == null) {
+                Log.i(TAG, "Aborting the animation as no window is opening")
+                callback?.invoke()
+
+                if (DEBUG_TRANSITION_ANIMATION) {
+                    Log.d(
+                        TAG,
+                        "Calling controller.onTransitionAnimationCancelled() [no window opening]"
+                    )
+                }
+                controller.onTransitionAnimationCancelled()
+                listener?.onTransitionAnimationCancelled()
+                return
+            }
+
+            val navigationBar =
+                nonApps?.firstOrNull {
+                    it.windowType == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+                }
+
+            startAnimation(window, navigationBar, callback)
         }
 
         private fun findRootTaskIfPossible(
@@ -646,9 +673,17 @@
             if (apps == null) {
                 return null
             }
+
+            val targetMode =
+                if (controller.isLaunching) {
+                    RemoteAnimationTarget.MODE_OPENING
+                } else {
+                    RemoteAnimationTarget.MODE_CLOSING
+                }
             var candidate: RemoteAnimationTarget? = null
+
             for (it in apps) {
-                if (it.mode == RemoteAnimationTarget.MODE_OPENING) {
+                if (it.mode == targetMode) {
                     if (activityTransitionUseLargestWindow()) {
                         if (
                             candidate == null ||
@@ -673,47 +708,31 @@
                     }
                 }
             }
+
             return candidate
         }
 
         private fun startAnimation(
-            apps: Array<out RemoteAnimationTarget>?,
-            nonApps: Array<out RemoteAnimationTarget>?,
+            window: RemoteAnimationTarget,
+            navigationBar: RemoteAnimationTarget?,
             iCallback: IRemoteAnimationFinishedCallback?
         ) {
             if (TransitionAnimator.DEBUG) {
                 Log.d(TAG, "Remote animation started")
             }
 
-            val window = findRootTaskIfPossible(apps)
-            if (window == null) {
-                Log.i(TAG, "Aborting the animation as no window is opening")
-                iCallback?.invoke()
-
-                if (DEBUG_TRANSITION_ANIMATION) {
-                    Log.d(
-                        TAG,
-                        "Calling controller.onTransitionAnimationCancelled() [no window opening]"
-                    )
-                }
-                controller.onTransitionAnimationCancelled()
-                listener?.onTransitionAnimationCancelled()
-                return
-            }
-
-            val navigationBar =
-                nonApps?.firstOrNull {
-                    it.windowType == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
-                }
-
             val windowBounds = window.screenSpaceBounds
             val endState =
-                TransitionAnimator.State(
-                    top = windowBounds.top,
-                    bottom = windowBounds.bottom,
-                    left = windowBounds.left,
-                    right = windowBounds.right
-                )
+                if (controller.isLaunching) {
+                    TransitionAnimator.State(
+                        top = windowBounds.top,
+                        bottom = windowBounds.bottom,
+                        left = windowBounds.left,
+                        right = windowBounds.right
+                    )
+                } else {
+                    controller.createAnimatorState()
+                }
             val windowBackgroundColor =
                 window.taskInfo?.let { callback.getBackgroundColor(it) } ?: window.backgroundColor
 
@@ -721,24 +740,29 @@
             // instead of recomputing isExpandingFullyAbove here.
             val isExpandingFullyAbove =
                 transitionAnimator.isExpandingFullyAbove(controller.transitionContainer, endState)
-            val endRadius =
-                if (isExpandingFullyAbove) {
-                    // Most of the time, expanding fully above the root view means expanding in full
-                    // screen.
-                    ScreenDecorationsUtils.getWindowCornerRadius(context)
-                } else {
-                    // This usually means we are in split screen mode, so 2 out of 4 corners will
-                    // have
-                    // a radius of 0.
-                    0f
-                }
-            endState.topCornerRadius = endRadius
-            endState.bottomCornerRadius = endRadius
+            if (controller.isLaunching) {
+                val endRadius = getWindowRadius(isExpandingFullyAbove)
+                endState.topCornerRadius = endRadius
+                endState.bottomCornerRadius = endRadius
+            }
 
             // We animate the opening window and delegate the view expansion to [this.controller].
             val delegate = this.controller
             val controller =
                 object : Controller by delegate {
+                    override fun createAnimatorState(): TransitionAnimator.State {
+                        if (isLaunching) return delegate.createAnimatorState()
+                        val windowRadius = getWindowRadius(isExpandingFullyAbove)
+                        return TransitionAnimator.State(
+                            top = windowBounds.top,
+                            bottom = windowBounds.bottom,
+                            left = windowBounds.left,
+                            right = windowBounds.right,
+                            topCornerRadius = windowRadius,
+                            bottomCornerRadius = windowRadius
+                        )
+                    }
+
                     override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
                         listener?.onTransitionAnimationStart()
 
@@ -795,6 +819,18 @@
                 )
         }
 
+        private fun getWindowRadius(isExpandingFullyAbove: Boolean): Float {
+            return if (isExpandingFullyAbove) {
+                // Most of the time, expanding fully above the root view means
+                // expanding in full screen.
+                ScreenDecorationsUtils.getWindowCornerRadius(context)
+            } else {
+                // This usually means we are in split screen mode, so 2 out of 4
+                // corners will have a radius of 0.
+                0f
+            }
+        }
+
         private fun applyStateToWindow(
             window: RemoteAnimationTarget,
             state: TransitionAnimator.State,
@@ -842,20 +878,41 @@
                 windowCropF.bottom.roundToInt()
             )
 
+            val windowAnimationDelay =
+                if (controller.isLaunching) {
+                    TIMINGS.contentAfterFadeInDelay
+                } else {
+                    TIMINGS.contentBeforeFadeOutDelay
+                }
+            val windowAnimationDuration =
+                if (controller.isLaunching) {
+                    TIMINGS.contentAfterFadeInDuration
+                } else {
+                    TIMINGS.contentBeforeFadeOutDuration
+                }
+            val windowProgress =
+                TransitionAnimator.getProgress(
+                    TIMINGS,
+                    linearProgress,
+                    windowAnimationDelay,
+                    windowAnimationDuration
+                )
+
             // The alpha of the opening window. If it opens above the expandable, then it should
             // fade in progressively. Otherwise, it should be fully opaque and will be progressively
             // revealed as the window background color layer above the window fades out.
             val alpha =
                 if (controller.isBelowAnimatingWindow) {
-                    val windowProgress =
-                        TransitionAnimator.getProgress(
-                            TIMINGS,
-                            linearProgress,
-                            TIMINGS.contentAfterFadeInDelay,
-                            TIMINGS.contentAfterFadeInDuration
+                    if (controller.isLaunching) {
+                        INTERPOLATORS.contentAfterFadeInInterpolator.getInterpolation(
+                            windowProgress
                         )
-
-                    INTERPOLATORS.contentAfterFadeInInterpolator.getInterpolation(windowProgress)
+                    } else {
+                        1 -
+                            INTERPOLATORS.contentBeforeFadeOutInterpolator.getInterpolation(
+                                windowProgress
+                            )
+                    }
                 } else {
                     1f
                 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java
index e20425d..94f8846 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java
@@ -36,6 +36,7 @@
 import android.view.WindowManager.TransitionOldType;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransitionStub;
 import android.window.TransitionInfo;
 
 import com.android.wm.shell.shared.CounterRotator;
@@ -69,8 +70,8 @@
     }
 
     /** Wraps a remote animation runner in a remote-transition. */
-    public static IRemoteTransition.Stub wrap(IRemoteAnimationRunner runner) {
-        return new IRemoteTransition.Stub() {
+    public static RemoteTransitionStub wrap(IRemoteAnimationRunner runner) {
+        return new RemoteTransitionStub() {
             final ArrayMap<IBinder, Runnable> mFinishRunnables = new ArrayMap<>();
 
             @Override
@@ -233,11 +234,6 @@
                 runner.onAnimationCancelled();
                 finishRunnable.run();
             }
-
-            @Override
-            public void onTransitionConsumed(IBinder iBinder, boolean aborted)
-                    throws RemoteException {
-            }
         };
     }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
index 9bf6b34..679c969 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
@@ -59,6 +59,13 @@
                 1.0f
             )
         }
+
+        internal fun checkReturnAnimationFrameworkFlag() {
+            check(returnAnimationFrameworkLibrary()) {
+                "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag is " +
+                    "disabled"
+            }
+        }
     }
 
     private val transitionContainerLocation = IntArray(2)
@@ -558,10 +565,4 @@
             }
         }
     }
-
-    private fun checkReturnAnimationFrameworkFlag() {
-        check(returnAnimationFrameworkLibrary()) {
-            "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag is disabled"
-        }
-    }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt
index 4d327e1..6c982a0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt
@@ -41,9 +41,9 @@
     maxMarginXdp: Float,
     maxMarginYdp: Float,
     minScale: Float,
-    translateXEasing: Interpolator = Interpolators.STANDARD_DECELERATE,
+    translateXEasing: Interpolator = Interpolators.BACK_GESTURE,
     translateYEasing: Interpolator = Interpolators.LINEAR,
-    scaleEasing: Interpolator = Interpolators.STANDARD_DECELERATE,
+    scaleEasing: Interpolator = Interpolators.BACK_GESTURE,
 ): BackAnimationSpec {
     return BackAnimationSpec { backEvent, progressY, result ->
         val displayMetrics = displayMetricsProvider()
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt
new file mode 100644
index 0000000..d50979c
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects
+
+import android.graphics.Paint
+import android.graphics.RenderEffect
+
+/**
+ * A callback with a [Paint] object that contains shader info, which is triggered every frame while
+ * animation is playing. Note that the [Paint] object here is always the same instance.
+ *
+ * This approach is more performant than other ones because [RenderEffect] forces an intermediate
+ * render pass of the View to a texture to feed into it.
+ *
+ * The usage of this callback is as follows:
+ * <pre>{@code
+ *     private var paint: Paint? = null
+ *     // Override [View.onDraw].
+ *     override fun onDraw(canvas: Canvas) {
+ *         // RuntimeShader requires hardwareAcceleration.
+ *         if (!canvas.isHardwareAccelerated) return
+ *
+ *         paint?.let { canvas.drawPaint(it) }
+ *     }
+ *
+ *     // Given that this is called [PaintDrawCallback.onDraw]
+ *     fun draw(paint: Paint) {
+ *         this.paint = paint
+ *
+ *         // Must call invalidate to trigger View#onDraw
+ *         invalidate()
+ *     }
+ * }</pre>
+ *
+ * Please refer to [RenderEffectDrawCallback] for alternative approach.
+ */
+interface PaintDrawCallback {
+    fun onDraw(paint: Paint)
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt
new file mode 100644
index 0000000..db7ee58
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects
+
+import android.graphics.RenderEffect
+
+/**
+ * A callback with a [RenderEffect] object that contains shader info, which is triggered every frame
+ * while animation is playing. Note that the [RenderEffect] instance is different each time to
+ * update shader uniforms.
+ *
+ * The usage of this callback is as follows:
+ * <pre>{@code
+ *     private val xEffectDrawingCallback = RenderEffectDrawCallback() {
+ *         val myOtherRenderEffect = createOtherRenderEffect()
+ *         val chainEffect = RenderEffect.createChainEffect(renderEffect, myOtherRenderEffect)
+ *         myView.setRenderEffect(chainEffect)
+ *     }
+ *
+ *     private val xEffect = XEffect(config, xEffectDrawingCallback)
+ * }</pre>
+ */
+interface RenderEffectDrawCallback {
+    fun onDraw(renderEffect: RenderEffect)
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffect.kt
new file mode 100644
index 0000000..c08afd3
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffect.kt
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.gloweffect
+
+import android.animation.ValueAnimator
+import android.animation.ValueAnimator.INFINITE
+import android.graphics.RenderEffect
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
+import com.android.systemui.surfaceeffects.utils.MathUtils
+
+/** Renders rotating pie with glow on top, masked with a rounded box. */
+class GlowPieEffect(
+    config: GlowPieEffectConfig,
+    private val renderEffectDrawCallback: RenderEffectDrawCallback
+) {
+
+    private val glowPieShader = GlowPieShader().apply { applyConfig(config) }
+
+    @VisibleForTesting
+    val mainAnimator: ValueAnimator =
+        ValueAnimator.ofFloat(0f, 1f).apply {
+            // We want to loop the full cycle.
+            duration = DURATION_MS
+            repeatMode = ValueAnimator.RESTART
+            repeatCount = INFINITE
+        }
+
+    /** Plays glow pie until [finish] is called. */
+    fun play() {
+        if (mainAnimator.isRunning) return
+
+        baseGlow.resetProgress()
+        firstGlowPie.resetProgress()
+        secondGlowPie.resetProgress()
+
+        mainAnimator.addUpdateListener { updateListener ->
+            val time = updateListener.currentPlayTime.toFloat() % mainAnimator.duration
+
+            // Remap each glow pie progress.
+            baseGlow.updateProgress(time)
+            firstGlowPie.updateProgress(time)
+            secondGlowPie.updateProgress(time)
+
+            // TODO(b/335315940): Consider passing in 2D Matrix.
+            glowPieShader.setAngles(baseGlow.angle(), firstGlowPie.angle(), secondGlowPie.angle())
+            glowPieShader.setBottomAngleThresholds(
+                baseGlow.bottomThreshold(),
+                firstGlowPie.bottomThreshold(),
+                secondGlowPie.bottomThreshold()
+            )
+            glowPieShader.setTopAngleThresholds(
+                baseGlow.topThreshold(),
+                firstGlowPie.topThreshold(),
+                secondGlowPie.topThreshold()
+            )
+            glowPieShader.setAlphas(baseGlow.alpha(), firstGlowPie.alpha(), secondGlowPie.alpha())
+
+            // Finally trigger the draw callback.
+            renderEffectDrawCallback.onDraw(
+                RenderEffect.createRuntimeShaderEffect(
+                    glowPieShader,
+                    GlowPieShader.BACKGROUND_UNIFORM
+                )
+            )
+        }
+
+        mainAnimator.start()
+    }
+
+    fun finish() {
+        // TODO(b/335315940) Add alpha fade.
+        mainAnimator.cancel()
+    }
+
+    companion object {
+        @VisibleForTesting const val PI = Math.PI.toFloat()
+        @VisibleForTesting const val FEATHER = 0.3f
+        @VisibleForTesting const val DURATION_MS = 3000L
+
+        private val baseGlow = BaseGlow()
+        private val firstGlowPie = FirstGlowPie()
+        private val secondGlowPie = SecondGlowPie()
+    }
+
+    /** Contains animation parameters for each layer of glow pie. */
+    interface GlowPie {
+        /**
+         * The start & end timestamps of the animation. Must be smaller than or equal to the full
+         * [DURATION_MS].
+         */
+        val startMs: Float
+        val endMs: Float
+        /**
+         * Start & end angles in radian. This determines how many cycles you want to rotate. e.g.
+         * startAngle = 0f endAngle = 4f * PI, will give you the 2 cycles.
+         */
+        val startAngle: Float
+        val endAngle: Float
+        /**
+         * Start & end timestamps of the fade out duration. You may want to override [alpha] if you
+         * want to make it fade in. See [BaseGlow].
+         */
+        val alphaFadeStartMs: Float
+        val alphaFadeEndMs: Float
+
+        /** Below two values are expected to be updated through [updateProgress]. */
+        /** Normalized progress. */
+        var progress: Float
+        /** current time of the animation in ms. */
+        var time: Float
+
+        // Must be called before retrieving angle, bottom & top thresholds, and alpha.
+        // Otherwise the values would be stale.
+        fun updateProgress(time: Float) {
+            progress = MathUtils.constrainedMap(0f, 1f, startMs, endMs, time)
+            this.time = time
+        }
+
+        fun resetProgress() {
+            progress = 0f
+            time = 0f
+        }
+
+        fun angle(): Float {
+            // Negate the angle since we want clock-wise rotation.
+            val angle =
+                MathUtils.constrainedMap(startAngle, endAngle, 0f, 1f, progress) + progress * PI
+            return -angle
+        }
+
+        fun bottomThreshold(): Float {
+            return MathUtils.lerp(1f, -FEATHER, progress)
+        }
+
+        fun topThreshold(): Float {
+            return MathUtils.lerp(1f + FEATHER, 0f, progress)
+        }
+
+        // By default, it fades "out".
+        fun alpha(): Float {
+            // Remap timestamps (in MS) to alpha [0, 1].
+            return MathUtils.constrainedMap(1f, 0f, alphaFadeStartMs, alphaFadeEndMs, time)
+        }
+    }
+
+    data class BaseGlow(
+        override val startMs: Float = 0f,
+        override val endMs: Float = 0f,
+        override val startAngle: Float = 0f,
+        override val endAngle: Float = 0f,
+        override val alphaFadeStartMs: Float = 2250f,
+        override val alphaFadeEndMs: Float = 2950f,
+    ) : GlowPie {
+
+        override var progress: Float = 1f
+        override var time: Float = 0f
+        override fun updateProgress(time: Float) {}
+
+        override fun resetProgress() {}
+
+        override fun angle(): Float = 0f
+
+        override fun bottomThreshold(): Float = 0f
+
+        override fun topThreshold(): Float = 0f
+
+        // Base glow fade "in" (i.e. reveals).
+        override fun alpha(): Float {
+            return MathUtils.constrainedMap(0f, 1f, alphaFadeStartMs, alphaFadeEndMs, time)
+        }
+    }
+
+    data class FirstGlowPie(
+        override val startMs: Float = 250f,
+        override val endMs: Float = 2500f,
+        override val startAngle: Float = -PI / 2f,
+        override val endAngle: Float = 4f * PI,
+        override val alphaFadeStartMs: Float = 2500f,
+        override val alphaFadeEndMs: Float = 2750f,
+        override var progress: Float = 0f,
+        override var time: Float = 0f
+    ) : GlowPie
+
+    data class SecondGlowPie(
+        override val startMs: Float = 350f,
+        override val endMs: Float = 2600f,
+        override val startAngle: Float = -PI / 2f,
+        override val endAngle: Float = 3f * PI,
+        override val alphaFadeStartMs: Float = 2600f,
+        override val alphaFadeEndMs: Float = 2850f,
+        override var progress: Float = 0f,
+        override var time: Float = 0f
+    ) : GlowPie
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectConfig.kt
new file mode 100644
index 0000000..6c728c1
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectConfig.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.gloweffect
+
+/** Parameter values needed to draw [GlowPieEffect]. */
+data class GlowPieEffectConfig(
+    /** Center x position of the effect. */
+    val centerX: Float,
+    /** Center y position of the effect. */
+    val centerY: Float,
+    /** Width of the rounded box mask. */
+    val width: Float,
+    /** Height of the rounded box mask. */
+    val height: Float,
+    /** Corner radius of the rounded box mask. */
+    val cornerRadius: Float,
+    /**
+     * Colors of the effect. The number must match 3, which is defined in [GlowPieShader.NUM_PIE].
+     * Each color corresponds to baseColor (bottom), firstLayerColor, and secondLayerColor (top).
+     */
+    val colors: IntArray
+)
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieShader.kt
new file mode 100644
index 0000000..2dbc0b5
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieShader.kt
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.gloweffect
+
+import android.graphics.RuntimeShader
+import android.util.Log
+import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
+import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
+
+/** Draws two glowing pies rotating around the center of a rounded box on a base. */
+class GlowPieShader : RuntimeShader(GLOW_PIE_SHADER_COMP) {
+    // language=AGSL
+    companion object {
+        const val BACKGROUND_UNIFORM = "in_dst"
+        const val NUM_PIE = 3
+
+        private const val UNIFORMS =
+            """
+            uniform shader ${BACKGROUND_UNIFORM};
+            uniform vec2 in_center;
+            uniform vec2 in_size;
+            uniform half in_cornerRad;
+            uniform float[${NUM_PIE}] in_angles;
+            uniform float[${NUM_PIE}] in_alphas;
+            uniform float[${NUM_PIE}] in_bottomThresholds;
+            uniform float[${NUM_PIE}] in_topThresholds;
+            layout(color) uniform vec4 in_colors0;
+            layout(color) uniform vec4 in_colors1;
+            layout(color) uniform vec4 in_colors2;
+        """
+
+        private const val GLOW_PIE_MAIN =
+            """
+        vec4 main(vec2 p) {
+            vec4 pie = vec4(0.);
+            vec4 glow = vec4(0.);
+
+            vec2 c = p - in_center;
+            half box = sdRoundedBox(c, in_size, in_cornerRad);
+
+            // Base glow (drawn at the bottom)
+            pieGlow(
+                box,
+                c,
+                in_angles[0],
+                in_colors0.rgb,
+                /* pieAlpha= */ 1., // We always show the base color.
+                /* glowAlpha= */ in_alphas[0],
+                vec2(in_bottomThresholds[0], in_topThresholds[0]),
+                pie,
+                glow
+            );
+
+            // First pie
+            pieGlow(
+                box,
+                c,
+                in_angles[1],
+                in_colors1.rgb,
+                /* pieAlpha= */ in_alphas[1],
+                /* glowAlpha= */ in_alphas[1],
+                vec2(in_bottomThresholds[1], in_topThresholds[1]),
+                pie,
+                glow
+            );
+
+            // Second pie (drawn on top)
+            pieGlow(
+                box,
+                c,
+                in_angles[2],
+                in_colors2.rgb,
+                /* pieAlpha= */ in_alphas[2],
+                /* glowAlpha= */ in_alphas[2],
+                vec2(in_bottomThresholds[2], in_topThresholds[2]),
+                pie,
+                glow
+            );
+
+            return vec4(pie.rgb + glow.rgb * 0.3, pie.a);
+        }
+        """
+
+        private const val REMAP =
+            """
+            float remap(float in_start, float in_end, float out_start, float out_end, float x) {
+                x = (x - in_start) / (in_end - in_start);
+                x = clamp(x, 0., 1.);
+                return x * (out_end - out_start) + out_start;
+            }
+        """
+
+        /**
+         * This function draws a pie slice, an a glow on top. The glow also has the same pie shape
+         * but with more blur and additive blending.
+         */
+        private const val GLOW_PIE =
+            """
+            void pieGlow(
+                half box,
+                vec2 c,
+                half angle,
+                vec3 color,
+                half pieAlpha,
+                half glowAlpha,
+                vec2 angleThresholds,
+                inout vec4 inout_pie,
+                inout vec4 inout_glow) {
+
+                // Apply angular rotation.
+                half co = cos(angle), si = sin(angle);
+                mat2 rotM = mat2(co, -si, si, co); // 2D rotation matrix
+                c *= rotM;
+
+                // We rotate based on the cosine value, since we want to avoid using inverse
+                // trig function, which in this case is atan.
+
+                // Dot product with vec2(1., 0.) and bring the range to [0,1].
+                // Same as dot(normalize(c), vec2(1.,0) * 0.5 + 0.5
+                half d = normalize(c).x * 0.5 + 0.5;
+
+                // Those thresholds represents each end of the pie.
+                float bottomThreshold = angleThresholds[0];
+                float topThreshold = angleThresholds[1];
+                float angleMask = remap(bottomThreshold, topThreshold, 0., 1., d);
+
+                half boxMask = 1. - smoothstep(-0.02, 0.02, box);
+                vec4 pie = vec4(color, 1.0) * angleMask * boxMask * pieAlpha;
+
+                // We are drawing the same pie but with more blur.
+                half glowMask = 1. - smoothstep(0., 0.6, box);
+                // Glow outside only.
+                glowMask = min(glowMask, smoothstep(-0.02, 0.02, box));
+                // Apply some curve for the glow. (Can take out)
+                glowMask *= glowMask * glowMask;
+                // Glow mask should also be sliced with the angle mask.
+                glowMask *= angleMask;
+                vec4 glow = vec4(color, 1.0) * glowMask * glowAlpha;
+
+                inout_pie = pie + inout_pie * (1. - pie.a);
+                // Additive blending.
+                inout_glow += glow;
+            }
+            """
+
+        private const val GLOW_PIE_SHADER_COMP =
+            ShaderUtilLibrary.SHADER_LIB +
+                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
+                SdfShaderLibrary.ROUNDED_BOX_SDF +
+                UNIFORMS +
+                REMAP +
+                GLOW_PIE +
+                GLOW_PIE_MAIN
+
+        private val TAG = GlowPieShader::class.java.simpleName
+    }
+
+    fun applyConfig(config: GlowPieEffectConfig) {
+        setCenter(config.centerX, config.centerY)
+        setSize(config.width, config.height)
+        setCornerRadius(config.cornerRadius)
+        setColor(config.colors)
+    }
+
+    fun setCenter(centerX: Float, centerY: Float) {
+        setFloatUniform("in_center", centerX, centerY)
+    }
+
+    fun setSize(width: Float, height: Float) {
+        setFloatUniform("in_size", width, height)
+    }
+
+    fun setCornerRadius(cornerRadius: Float) {
+        setFloatUniform("in_cornerRad", cornerRadius)
+    }
+
+    /** Ignores alpha value, as fade in/out is handled within shader. */
+    fun setColor(colors: IntArray) {
+        if (colors.size != NUM_PIE) {
+            Log.wtf(TAG, "The number of colors must be $NUM_PIE")
+            return
+        }
+        setColorUniform("in_colors0", colors[0])
+        setColorUniform("in_colors1", colors[1])
+        setColorUniform("in_colors2", colors[2])
+    }
+
+    fun setAngles(vararg angles: Float) {
+        if (angles.size != NUM_PIE) {
+            Log.wtf(TAG, "The number of angles must be $NUM_PIE")
+            return
+        }
+        setFloatUniform("in_angles", angles)
+    }
+
+    fun setAlphas(vararg alphas: Float) {
+        if (alphas.size != NUM_PIE) {
+            Log.wtf(TAG, "The number of angles must be $NUM_PIE")
+            return
+        }
+        setFloatUniform("in_alphas", alphas)
+    }
+
+    fun setBottomAngleThresholds(vararg bottomThresholds: Float) {
+        if (bottomThresholds.size != NUM_PIE) {
+            Log.wtf(TAG, "The number of bottomThresholds must be $NUM_PIE")
+            return
+        }
+        setFloatUniform("in_bottomThresholds", bottomThresholds)
+    }
+
+    fun setTopAngleThresholds(vararg topThresholds: Float) {
+        if (topThresholds.size != NUM_PIE) {
+            Log.wtf(TAG, "The number of topThresholds must be $NUM_PIE")
+            return
+        }
+        setFloatUniform("in_topThresholds", topThresholds)
+    }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt
index 1c763e8..211b84f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt
@@ -22,6 +22,8 @@
 import android.graphics.Paint
 import android.graphics.RenderEffect
 import android.view.View
+import com.android.systemui.surfaceeffects.PaintDrawCallback
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader
 
@@ -334,52 +336,31 @@
         )
     }
 
-    companion object {
+    /**
+     * States of the loading effect animation.
+     *
+     * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN],
+     * [AnimationState.MAIN], [AnimationState.EASE_OUT]. Note that ease in and out don't necessarily
+     * mean the acceleration and deceleration in the animation curve. They simply mean each stage of
+     * the animation. (i.e. Intro, core, and rest)
+     */
+    enum class AnimationState {
+        EASE_IN,
+        MAIN,
+        EASE_OUT,
+        NOT_PLAYING
+    }
+
+    /** Optional callback that is triggered when the animation state changes. */
+    interface AnimationStateChangedCallback {
         /**
-         * States of the loading effect animation.
-         *
-         * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN],
-         * [AnimationState.MAIN], [AnimationState.EASE_OUT]. Note that ease in and out don't
-         * necessarily mean the acceleration and deceleration in the animation curve. They simply
-         * mean each stage of the animation. (i.e. Intro, core, and rest)
+         * A callback that's triggered when the [AnimationState] changes. Example usage is
+         * performing a cleanup when [AnimationState] becomes [NOT_PLAYING].
          */
-        enum class AnimationState {
-            EASE_IN,
-            MAIN,
-            EASE_OUT,
-            NOT_PLAYING
-        }
+        fun onStateChanged(oldState: AnimationState, newState: AnimationState) {}
+    }
 
-        /** Client must implement one of the draw callbacks. */
-        interface PaintDrawCallback {
-            /**
-             * A callback with a [Paint] object that contains shader info, which is triggered every
-             * frame while animation is playing. Note that the [Paint] object here is always the
-             * same instance.
-             */
-            fun onDraw(loadingPaint: Paint)
-        }
-
-        interface RenderEffectDrawCallback {
-            /**
-             * A callback with a [RenderEffect] object that contains shader info, which is triggered
-             * every frame while animation is playing. Note that the [RenderEffect] instance is
-             * different each time to update shader uniforms.
-             */
-            fun onDraw(loadingRenderEffect: RenderEffect)
-        }
-
-        /** Optional callback that is triggered when the animation state changes. */
-        interface AnimationStateChangedCallback {
-            /**
-             * A callback that's triggered when the [AnimationState] changes. Example usage is
-             * performing a cleanup when [AnimationState] becomes [NOT_PLAYING].
-             */
-            fun onStateChanged(oldState: AnimationState, newState: AnimationState) {}
-        }
-
+    private companion object {
         private const val MS_TO_SEC = 0.001f
-
-        private val TAG = LoadingEffect::class.java.simpleName
     }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt
new file mode 100644
index 0000000..ffa2b46
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.revealeffect
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ValueAnimator
+import android.graphics.RenderEffect
+import androidx.core.graphics.ColorUtils
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
+import com.android.systemui.surfaceeffects.utils.MathUtils
+import kotlin.math.max
+import kotlin.math.min
+
+/** Creates a reveal effect with a circular ripple sparkles on top. */
+class RippleRevealEffect(
+    private val config: RippleRevealEffectConfig,
+    private val renderEffectCallback: RenderEffectDrawCallback,
+    private val stateChangedCallback: AnimationStateChangedCallback? = null
+) {
+    private val rippleRevealShader = RippleRevealShader().apply { applyConfig(config) }
+    private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
+
+    fun play() {
+        if (animator.isRunning) {
+            return
+        }
+
+        animator.duration = config.duration.toLong()
+        animator.addUpdateListener { updateListener ->
+            val playTime = updateListener.currentPlayTime.toFloat()
+            rippleRevealShader.setTime(playTime * TIME_SCALE_FACTOR)
+
+            // Compute radius.
+            val progress = updateListener.animatedValue as Float
+            val innerRad = MathUtils.lerp(config.innerRadiusStart, config.innerRadiusEnd, progress)
+            val outerRad = MathUtils.lerp(config.outerRadiusStart, config.outerRadiusEnd, progress)
+            rippleRevealShader.setInnerRadius(innerRad)
+            rippleRevealShader.setOuterRadius(outerRad)
+
+            // Compute alphas.
+            val innerAlphaProgress =
+                MathUtils.constrainedMap(
+                    1f,
+                    0f,
+                    config.innerFadeOutStart,
+                    config.duration,
+                    playTime
+                )
+            val outerAlphaProgress =
+                MathUtils.constrainedMap(
+                    1f,
+                    0f,
+                    config.outerFadeOutStart,
+                    config.duration,
+                    playTime
+                )
+            val innerAlpha = MathUtils.lerp(0f, 255f, innerAlphaProgress)
+            val outerAlpha = MathUtils.lerp(0f, 255f, outerAlphaProgress)
+
+            val innerColor = ColorUtils.setAlphaComponent(config.innerColor, innerAlpha.toInt())
+            val outerColor = ColorUtils.setAlphaComponent(config.outerColor, outerAlpha.toInt())
+            rippleRevealShader.setInnerColor(innerColor)
+            rippleRevealShader.setOuterColor(outerColor)
+
+            // Pass in progresses since those functions take in normalized alpha values.
+            rippleRevealShader.setBackgroundAlpha(max(innerAlphaProgress, outerAlphaProgress))
+            rippleRevealShader.setSparkleAlpha(min(innerAlphaProgress, outerAlphaProgress))
+
+            // Trigger draw callback.
+            renderEffectCallback.onDraw(
+                RenderEffect.createRuntimeShaderEffect(
+                    rippleRevealShader,
+                    RippleRevealShader.BACKGROUND_UNIFORM
+                )
+            )
+        }
+        animator.addListener(
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationEnd(animation: Animator) {
+                    stateChangedCallback?.onAnimationEnd()
+                }
+            }
+        )
+        animator.start()
+        stateChangedCallback?.onAnimationStart()
+    }
+
+    interface AnimationStateChangedCallback {
+        fun onAnimationStart()
+        fun onAnimationEnd()
+    }
+
+    private companion object {
+        private const val TIME_SCALE_FACTOR = 0.00175f
+    }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt
new file mode 100644
index 0000000..9675f19
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.revealeffect
+
+import android.graphics.Color
+
+/** Defines parameters needed for [RippleRevealEffect]. */
+data class RippleRevealEffectConfig(
+    /** Total duration of the animation. */
+    val duration: Float = 0f,
+    /** Timestamp of when the inner mask starts fade out. (Linear fadeout) */
+    val innerFadeOutStart: Float = 0f,
+    /** Timestamp of when the outer mask starts fade out. (Linear fadeout) */
+    val outerFadeOutStart: Float = 0f,
+    /** Center x position of the effect. */
+    val centerX: Float = 0f,
+    /** Center y position of the effect. */
+    val centerY: Float = 0f,
+    /** Start radius of the inner circle. */
+    val innerRadiusStart: Float = 0f,
+    /** End radius of the inner circle. */
+    val innerRadiusEnd: Float = 0f,
+    /** Start radius of the outer circle. */
+    val outerRadiusStart: Float = 0f,
+    /** End radius of the outer circle. */
+    val outerRadiusEnd: Float = 0f,
+    /**
+     * Pixel density of the display. Do not pass a random value. The value must come from
+     * [context.resources.displayMetrics.density].
+     */
+    val pixelDensity: Float = 1f,
+    /**
+     * The amount the circle masks should be softened. Higher value will make the edge of the circle
+     * mask soft.
+     */
+    val blurAmount: Float = 0f,
+    /** Color of the inner circle mask. */
+    val innerColor: Int = Color.WHITE,
+    /** Color of the outer circle mask. */
+    val outerColor: Int = Color.WHITE,
+    /** Multiplier to make the sparkles visible. */
+    val sparkleStrength: Float = SPARKLE_STRENGTH,
+    /** Size of the sparkle. Expected range [0, 1]. */
+    val sparkleScale: Float = SPARKLE_SCALE
+) {
+    /** Default parameters. */
+    companion object {
+        const val SPARKLE_STRENGTH: Float = 0.3f
+        const val SPARKLE_SCALE: Float = 0.8f
+    }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt
new file mode 100644
index 0000000..a3f9795
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.revealeffect
+
+import android.graphics.RuntimeShader
+import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
+import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
+
+/** Circular reveal effect with sparkles. */
+class RippleRevealShader : RuntimeShader(SHADER) {
+    // language=AGSL
+    companion object {
+        const val BACKGROUND_UNIFORM = "in_dst"
+        private const val MAIN =
+            """
+            uniform shader ${BACKGROUND_UNIFORM};
+            uniform half in_dstAlpha;
+            uniform half in_time;
+            uniform vec2 in_center;
+            uniform half in_innerRadius;
+            uniform half in_outerRadius;
+            uniform half in_sparkleStrength;
+            uniform half in_blur;
+            uniform half in_pixelDensity;
+            uniform half in_sparkleScale;
+            uniform half in_sparkleAlpha;
+            layout(color) uniform vec4 in_innerColor;
+            layout(color) uniform vec4 in_outerColor;
+
+            vec4 main(vec2 p) {
+                half innerMask = soften(sdCircle(p - in_center, in_innerRadius), in_blur);
+                half outerMask = soften(sdCircle(p - in_center, in_outerRadius), in_blur);
+
+                // Flip it since we are interested in the circle.
+                innerMask = 1.-innerMask;
+                outerMask = 1.-outerMask;
+
+                // Color two circles using the mask.
+                vec4 inColor = vec4(in_innerColor.rgb, 1.) * in_innerColor.a;
+                vec4 outColor = vec4(in_outerColor.rgb, 1.) * in_outerColor.a;
+                vec4 blend = mix(inColor, outColor, innerMask);
+
+                vec4 dst = vec4(in_dst.eval(p).rgb, 1.);
+                dst *= in_dstAlpha;
+
+                blend *= blend.a;
+                // Do normal blend with the background.
+                blend = blend + dst * (1. - blend.a);
+
+                half sparkle =
+                    sparkles(p - mod(p, in_pixelDensity * in_sparkleScale), in_time);
+                // Add sparkles using additive blending.
+                blend += sparkle * in_sparkleStrength * in_sparkleAlpha;
+
+                // Mask everything at the end.
+                blend *= outerMask;
+
+                return blend;
+            }
+        """
+
+        private const val SHADER =
+            ShaderUtilLibrary.SHADER_LIB +
+                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
+                SdfShaderLibrary.CIRCLE_SDF +
+                MAIN
+    }
+
+    fun applyConfig(config: RippleRevealEffectConfig) {
+        setCenter(config.centerX, config.centerY)
+        setInnerRadius(config.innerRadiusStart)
+        setOuterRadius(config.outerRadiusStart)
+        setBlurAmount(config.blurAmount)
+        setPixelDensity(config.pixelDensity)
+        setSparkleScale(config.sparkleScale)
+        setSparkleStrength(config.sparkleStrength)
+        setInnerColor(config.innerColor)
+        setOuterColor(config.outerColor)
+    }
+
+    fun setTime(time: Float) {
+        setFloatUniform("in_time", time)
+    }
+
+    fun setCenter(centerX: Float, centerY: Float) {
+        setFloatUniform("in_center", centerX, centerY)
+    }
+
+    fun setInnerRadius(radius: Float) {
+        setFloatUniform("in_innerRadius", radius)
+    }
+
+    fun setOuterRadius(radius: Float) {
+        setFloatUniform("in_outerRadius", radius)
+    }
+
+    fun setBlurAmount(blurAmount: Float) {
+        setFloatUniform("in_blur", blurAmount)
+    }
+
+    fun setPixelDensity(density: Float) {
+        setFloatUniform("in_pixelDensity", density)
+    }
+
+    fun setSparkleScale(scale: Float) {
+        setFloatUniform("in_sparkleScale", scale)
+    }
+
+    fun setSparkleStrength(strength: Float) {
+        setFloatUniform("in_sparkleStrength", strength)
+    }
+
+    fun setInnerColor(color: Int) {
+        setColorUniform("in_innerColor", color)
+    }
+
+    fun setOuterColor(color: Int) {
+        setColorUniform("in_outerColor", color)
+    }
+
+    /** Sets the background alpha. Range [0,1]. */
+    fun setBackgroundAlpha(alpha: Float) {
+        setFloatUniform("in_dstAlpha", alpha)
+    }
+
+    /** Sets the sparkle alpha. Range [0,1]. */
+    fun setSparkleAlpha(alpha: Float) {
+        setFloatUniform("in_sparkleAlpha", alpha)
+    }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt
new file mode 100644
index 0000000..1411c32
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.utils
+
+/** Copied from android.utils.MathUtils */
+object MathUtils {
+    fun constrainedMap(
+        rangeMin: Float,
+        rangeMax: Float,
+        valueMin: Float,
+        valueMax: Float,
+        value: Float
+    ): Float {
+        return lerp(rangeMin, rangeMax, lerpInvSat(valueMin, valueMax, value))
+    }
+
+    fun lerp(start: Float, stop: Float, amount: Float): Float {
+        return start + (stop - start) * amount
+    }
+
+    fun lerpInv(a: Float, b: Float, value: Float): Float {
+        return if (a != b) (value - a) / (b - a) else 0.0f
+    }
+
+    fun saturate(value: Float): Float {
+        return constrain(value, 0.0f, 1.0f)
+    }
+
+    fun lerpInvSat(a: Float, b: Float, value: Float): Float {
+        return saturate(lerpInv(a, b, value))
+    }
+
+    fun constrain(amount: Float, low: Float, high: Float): Float {
+        return if (amount < low) low else if (amount > high) high else amount
+    }
+}
diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp
index 4cbc18c..1f502e3 100644
--- a/packages/SystemUI/checks/Android.bp
+++ b/packages/SystemUI/checks/Android.bp
@@ -24,10 +24,7 @@
 
 java_library_host {
     name: "SystemUILintChecker",
-    srcs: [
-        "src/**/*.kt",
-        "src/**/*.java",
-    ],
+    srcs: ["src/**/*.kt"],
     plugins: ["auto_service_plugin"],
     libs: [
         "auto_service_annotations",
@@ -38,35 +35,14 @@
 
 java_test_host {
     name: "SystemUILintCheckerTest",
-    srcs: [
-        "tests/**/*.kt",
-        "tests/**/*.java",
-    ],
+    defaults: ["AndroidLintCheckerTestDefaults"],
+    srcs: ["tests/**/*.kt"],
     data: [
         ":framework",
-        ":androidx.annotation_annotation",
+        ":androidx.annotation_annotation-nodeps",
+        ":kotlinx-coroutines-core",
     ],
     static_libs: [
         "SystemUILintChecker",
-        "junit",
-        "lint",
-        "lint_tests",
     ],
-    test_options: {
-        unit_test: true,
-        tradefed_options: [
-            {
-                // lint bundles in some classes that were built with older versions
-                // of libraries, and no longer load. Since tradefed tries to load
-                // all classes in the jar to look for tests, it crashes loading them.
-                // Exclude these classes from tradefed's search.
-                name: "exclude-paths",
-                value: "org/apache",
-            },
-            {
-                name: "exclude-paths",
-                value: "META-INF",
-            },
-        ],
-    },
 }
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
index 30e2a25..f9bf306 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
@@ -34,7 +34,6 @@
  * 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
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/FlowDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/FlowDetector.kt
new file mode 100644
index 0000000..5868200
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/FlowDetector.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.internal.systemui.lint
+
+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 com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.PsiParameter
+import org.jetbrains.kotlin.psi.psiUtil.isTopLevelKtOrJavaMember
+import org.jetbrains.uast.UCallExpression
+
+/** Detects bad usages of Kotlin Flows */
+class FlowDetector : Detector(), SourceCodeScanner {
+
+    override fun getApplicableMethodNames(): List<String> =
+        listOf(
+            FUN_MUTABLE_SHARED_FLOW,
+            FUN_SHARE_IN,
+        )
+
+    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+        if (
+            method.name == FUN_MUTABLE_SHARED_FLOW &&
+                method.parent.isTopLevelKtOrJavaMember() &&
+                context.evaluator.getPackage(method)?.qualifiedName == PACKAGE_FLOW
+        ) {
+            context.report(
+                issue = SHARED_FLOW_CREATION,
+                location = context.getNameLocation(node),
+                message =
+                    "`MutableSharedFlow()` creates a new shared flow, which has poor performance " +
+                        "characteristics"
+            )
+        }
+        if (
+            method.name == FUN_SHARE_IN &&
+                getTypeOfExtensionMethod(method)?.resolve()?.qualifiedName == CLASS_FLOW
+        ) {
+            context.report(
+                issue = SHARED_FLOW_CREATION,
+                location = context.getNameLocation(node),
+                message =
+                    "`shareIn()` creates a new shared flow, which has poor performance " +
+                        "characteristics"
+            )
+        }
+    }
+
+    companion object {
+        @JvmStatic
+        val SHARED_FLOW_CREATION =
+            Issue.create(
+                id = "SharedFlowCreation",
+                briefDescription = "Shared flow creation",
+                explanation =
+                    """
+                            Shared flows scale poorly with the number of collectors in use due to
+                            their internal buffering mechanism and reliance on thread
+                            synchronization. They can also cause memory leaks when used incorrectly.
+                            If possible, use `StateFlow` instead.
+                """,
+                moreInfo = "http://go//sysui-shared-flow",
+                category = Category.PERFORMANCE,
+                priority = 8,
+                severity = Severity.ERROR,
+                implementation =
+                    Implementation(
+                        FlowDetector::class.java,
+                        Scope.JAVA_FILE_SCOPE,
+                    ),
+            )
+
+        fun getTypeOfExtensionMethod(method: PsiMethod): PsiClassType? {
+            // If this is an extension method whose return type matches receiver
+            val parameterList = method.parameterList
+            if (parameterList.parametersCount > 0) {
+                val firstParameter = parameterList.getParameter(0)
+                if (firstParameter is PsiParameter && firstParameter.name.startsWith("\$this\$")) {
+                    return firstParameter.type as? PsiClassType
+                }
+            }
+            return null
+        }
+    }
+}
+
+private const val PACKAGE_FLOW = "kotlinx.coroutines.flow"
+private const val FUN_MUTABLE_SHARED_FLOW = "MutableSharedFlow"
+private const val FUN_SHARE_IN = "shareIn"
+private const val CLASS_FLOW = "$PACKAGE_FLOW.Flow"
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
index 46125be..a162897 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
@@ -25,7 +25,6 @@
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Location
 import com.android.tools.lint.detector.api.Scope
-import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
 import java.time.Year
 import org.jetbrains.uast.UComment
@@ -117,8 +116,13 @@
                         attached at the beginning.""",
                 category = Category.COMPLIANCE,
                 priority = 8,
-                // ignored by default and then explicitly overridden in SysUI's soong configuration
-                severity = Severity.IGNORE,
+                // This check is disabled by default so that it is not accidentally used by internal
+                // modules that have different silencing. This check can be enabled in Soong using
+                // the following configuration:
+                //   lint: {
+                //    warning_checks: ["MissingApacheLicenseDetector"],
+                //   }
+                enabledByDefault = false,
                 implementation =
                     Implementation(MissingApacheLicenseDetector::class.java, Scope.JAVA_FILE_SCOPE),
             )
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
index 5840e8f..024c394 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
@@ -59,7 +59,7 @@
                             `BroadcastDispatcher` instead, which registers the receiver on a \
                              background thread. `BroadcastDispatcher` also improves our visibility \
                              into ANRs.""",
-                            moreInfo = "go/identifying-broadcast-threads",
+                            moreInfo = "http://go/identifying-broadcast-threads",
                     category = Category.PERFORMANCE,
                     priority = 8,
                     severity = Severity.WARNING,
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 e09aa42..e93264c 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
@@ -33,6 +33,7 @@
                 BroadcastSentViaContextDetector.ISSUE,
                 CleanArchitectureDependencyViolationDetector.ISSUE,
                 DumpableNotRegisteredDetector.ISSUE,
+                FlowDetector.SHARED_FLOW_CREATION,
                 SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
                 SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
                 NonInjectedMainThreadDetector.ISSUE,
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
index 141dd05..edfd59a 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
@@ -16,33 +16,19 @@
 
 package com.android.internal.systemui.lint
 
-import com.android.annotations.NonNull
-import com.android.tools.lint.checks.infrastructure.LintDetectorTest.java
 import com.android.tools.lint.checks.infrastructure.TestFiles.LibraryReferenceTestFile
 import java.io.File
-import org.intellij.lang.annotations.Language
 
-@Suppress("UnstableApiUsage")
-@NonNull
-private fun indentedJava(@NonNull @Language("JAVA") source: String) = java(source).indented()
+internal val libraryNames =
+    arrayOf(
+        "framework.jar",
+        "androidx.annotation_annotation-nodeps.jar",
+        "kotlinx-coroutines-core.jar",
+    )
 
 /*
  * This file contains stubs of framework APIs and System UI classes for testing purposes only. The
  * stubs are not used in the lint detectors themselves.
  */
 internal val androidStubs =
-    arrayOf(
-        LibraryReferenceTestFile(File("framework.jar").canonicalFile),
-        LibraryReferenceTestFile(File("androidx.annotation_annotation.jar").canonicalFile),
-        indentedJava(
-            """
-package com.android.systemui.settings;
-import android.content.pm.UserInfo;
-
-public interface UserTracker {
-    int getUserId();
-    UserInfo getUserInfo();
-}
-"""
-        ),
-    )
+    libraryNames.map { LibraryReferenceTestFile(File(it).canonicalFile) }.toTypedArray()
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BindServiceOnMainThreadDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BindServiceOnMainThreadDetectorTest.kt
index 4c4185d..c9bc8b3 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BindServiceOnMainThreadDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BindServiceOnMainThreadDetectorTest.kt
@@ -19,17 +19,14 @@
 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.Ignore
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class BindServiceOnMainThreadDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = BindServiceOnMainThreadDetector()
 
     override fun getIssues(): List<Issue> = listOf(BindServiceOnMainThreadDetector.ISSUE)
 
-    @Ignore
     @Test
     fun testBindService() {
         lint()
@@ -37,7 +34,9 @@
                 TestFiles.java(
                         """
                     package test.pkg;
+
                     import android.content.Context;
+                    import android.content.Intent;
 
                     public class TestClass {
                         public void bind(Context context) {
@@ -48,13 +47,13 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BindServiceOnMainThreadDetector.ISSUE)
             .run()
             .expect(
                 """
-                src/test/pkg/TestClass.java:7: Warning: This method should be annotated with @WorkerThread because it calls bindService [BindServiceOnMainThread]
+                src/test/pkg/TestClass.java:9: Warning: This method should be annotated with @WorkerThread because it calls bindService [BindServiceOnMainThread]
                       context.bindService(intent, null, 0);
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                 0 errors, 1 warnings
@@ -62,7 +61,6 @@
             )
     }
 
-    @Ignore
     @Test
     fun testBindServiceAsUser() {
         lint()
@@ -70,7 +68,9 @@
                 TestFiles.java(
                         """
                     package test.pkg;
+
                     import android.content.Context;
+                    import android.content.Intent;
                     import android.os.UserHandle;
 
                     public class TestClass {
@@ -82,13 +82,13 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BindServiceOnMainThreadDetector.ISSUE)
             .run()
             .expect(
                 """
-                src/test/pkg/TestClass.java:8: Warning: This method should be annotated with @WorkerThread because it calls bindServiceAsUser [BindServiceOnMainThread]
+                src/test/pkg/TestClass.java:10: Warning: This method should be annotated with @WorkerThread because it calls bindServiceAsUser [BindServiceOnMainThread]
                       context.bindServiceAsUser(intent, null, 0, UserHandle.ALL);
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                 0 errors, 1 warnings
@@ -114,7 +114,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BindServiceOnMainThreadDetector.ISSUE)
             .run()
@@ -147,7 +147,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BindServiceOnMainThreadDetector.ISSUE)
             .run()
@@ -181,7 +181,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BindServiceOnMainThreadDetector.ISSUE)
             .run()
@@ -219,12 +219,10 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BindServiceOnMainThreadDetector.ISSUE)
             .run()
             .expectClean()
     }
-
-    private val stubs = androidStubs
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BroadcastSentViaContextDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BroadcastSentViaContextDetectorTest.kt
index 30b68f7..3788dda 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BroadcastSentViaContextDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/BroadcastSentViaContextDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class BroadcastSentViaContextDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = BroadcastSentViaContextDetector()
@@ -30,7 +29,6 @@
 
     @Test
     fun testSendBroadcast() {
-        println(stubs.size)
         lint()
             .files(
                 TestFiles.java(
@@ -47,7 +45,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BroadcastSentViaContextDetector.ISSUE)
             .run()
@@ -80,7 +78,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BroadcastSentViaContextDetector.ISSUE)
             .run()
@@ -114,7 +112,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BroadcastSentViaContextDetector.ISSUE)
             .run()
@@ -149,7 +147,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BroadcastSentViaContextDetector.ISSUE)
             .run()
@@ -176,7 +174,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BroadcastSentViaContextDetector.ISSUE)
             .run()
@@ -201,12 +199,10 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(BroadcastSentViaContextDetector.ISSUE)
             .run()
             .expectClean()
     }
-
-    private val stubs = androidStubs
 }
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 ff150c8c..2c20321 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
@@ -21,11 +21,8 @@
 import com.android.tools.lint.checks.infrastructure.TestMode
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Issue
-import org.junit.Ignore
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
-@Ignore("b/254533331")
 class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTest() {
     override fun getDetector(): Detector {
         return CleanArchitectureDependencyViolationDetector()
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
index ee6e0ce..0652e69 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
@@ -24,7 +24,6 @@
 import java.util.EnumSet
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class DemotingTestWithoutBugDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = DemotingTestWithoutBugDetector()
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
index 3d6cbc7..6c6c263 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class DumpableNotRegisteredDetectorTest : SystemUILintDetectorTest() {
     override fun getDetector(): Detector = DumpableNotRegisteredDetector()
 
@@ -37,7 +36,8 @@
 
                     class SomeClass() {
                     }
-                """.trimIndent()
+                """
+                        .trimIndent()
                 ),
                 *stubs,
             )
@@ -67,7 +67,8 @@
                             pw.println("testDump");
                         }
                     }
-                """.trimIndent()
+                """
+                        .trimIndent()
                 ),
                 *stubs,
             )
@@ -97,7 +98,8 @@
                             pw.println("testDump");
                         }
                     }
-                """.trimIndent()
+                """
+                        .trimIndent()
                 ),
                 *stubs,
             )
@@ -127,7 +129,8 @@
                             pw.println("testDump");
                         }
                     }
-                """.trimIndent()
+                """
+                        .trimIndent()
                 ),
                 *stubs,
             )
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/FlowDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/FlowDetectorTest.kt
new file mode 100644
index 0000000..4944529
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/FlowDetectorTest.kt
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *            http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.internal.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
+
+class FlowDetectorTest : SystemUILintDetectorTest() {
+    override fun getDetector(): Detector = FlowDetector()
+
+    override fun getIssues(): List<Issue> = listOf(FlowDetector.SHARED_FLOW_CREATION)
+
+    @Test
+    fun createSharedFlow_viaCallToMutableSharedFlow() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                        package test.pkg
+
+                        import kotlinx.coroutines.flow.MutableSharedFlow
+
+                        suspend fun doSomething() {
+                            val sharedFlow = MutableSharedFlow<Int>(replay = 2)
+                        }
+                    """
+                        .trimIndent()
+                ),
+                *androidStubs
+            )
+            .issues(FlowDetector.SHARED_FLOW_CREATION)
+            .run()
+            .expect(
+                """
+src/test/pkg/test.kt:6: Error: MutableSharedFlow() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+    val sharedFlow = MutableSharedFlow<Int>(replay = 2)
+                     ~~~~~~~~~~~~~~~~~
+1 errors, 0 warnings
+                """,
+            )
+    }
+
+    @Test
+    fun createSharedFlow_viaCallToShareIn_onFlow() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                        package test.pkg
+
+                        import kotlinx.coroutines.CoroutineScope
+                        import kotlinx.coroutines.flow.Flow
+                        import kotlinx.coroutines.flow.SharingStarted
+                        import kotlinx.coroutines.flow.shareIn
+
+                        suspend fun doSomething(scope: CoroutineScope, someFlow: Flow<Int>) {
+                            someFlow.shareIn(scope, SharingStarted.Eagerly)
+                        }
+                    """
+                        .trimIndent()
+                ),
+                *androidStubs
+            )
+            .issues(FlowDetector.SHARED_FLOW_CREATION)
+            .run()
+            .expect(
+                """
+src/test/pkg/test.kt:9: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+    someFlow.shareIn(scope, SharingStarted.Eagerly)
+             ~~~~~~~
+1 errors, 0 warnings
+                """,
+            )
+    }
+
+    @Test
+    fun createSharedFlow_viaCallToShareIn_afterOperationChain() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                        package test.pkg
+
+                        import kotlinx.coroutines.CoroutineScope
+                        import kotlinx.coroutines.flow.Flow
+                        import kotlinx.coroutines.flow.SharingStarted
+                        import kotlinx.coroutines.flow.shareIn
+                        import kotlinx.coroutines.flow.onStart
+                        import kotlinx.coroutines.flow.map
+                        import kotlinx.coroutines.flow.distinctUntilChanged
+
+                        suspend fun doSomething(scope: CoroutineScope, someFlow: Flow<Int>) {
+                            someFlow.onStart { emit(PackageChangeModel.Empty) }
+                                .map { reloadComponents(userId, packageManager) }
+                                .distinctUntilChanged()
+                                .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+                        }
+                    """
+                        .trimIndent()
+                ),
+                *androidStubs
+            )
+            .issues(FlowDetector.SHARED_FLOW_CREATION)
+            .run()
+            .expect(
+                """
+src/test/pkg/test.kt:15: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+        .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+         ~~~~~~~
+1 errors, 0 warnings
+                """,
+            )
+    }
+
+    @Test
+    fun createSharedFlow_viaCallToShareIn_onStateFlow() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                        package test.pkg
+
+                        import kotlinx.coroutines.CoroutineScope
+                        import kotlinx.coroutines.flow.Flow
+                        import kotlinx.coroutines.flow.StateFlow
+                        import kotlinx.coroutines.flow.SharingStarted
+                        import kotlinx.coroutines.flow.shareIn
+                        import kotlinx.coroutines.flow.onStart
+                        import kotlinx.coroutines.flow.map
+                        import kotlinx.coroutines.flow.distinctUntilChanged
+
+                        suspend fun doSomething(someScope: CoroutineScope, someFlow: StateFlow<Int>) {
+                            someFlow.onStart { emit(1) }
+                                .map { someOtherFunction() }
+                                .distinctUntilChanged()
+                                .shareIn(someScope, SharingStarted.WhileSubscribed())
+                            someFlow.shareIn(someScope, SharingStarted.Eagerly)
+                        }
+                    """
+                        .trimIndent()
+                ),
+                *androidStubs
+            )
+            .issues(FlowDetector.SHARED_FLOW_CREATION)
+            .run()
+            .expect(
+                """
+src/test/pkg/test.kt:16: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+        .shareIn(someScope, SharingStarted.WhileSubscribed())
+         ~~~~~~~
+src/test/pkg/test.kt:17: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+    someFlow.shareIn(someScope, SharingStarted.Eagerly)
+             ~~~~~~~
+2 errors, 0 warnings
+                """,
+            )
+    }
+
+    @Test
+    fun createSharedFlow_viaCallToShareIn_onSharedFlow() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                        package test.pkg
+
+                        import kotlinx.coroutines.CoroutineScope
+                        import kotlinx.coroutines.flow.Flow
+                        import kotlinx.coroutines.flow.SharedFlow
+                        import kotlinx.coroutines.flow.SharingStarted
+                        import kotlinx.coroutines.flow.shareIn
+                        import kotlinx.coroutines.flow.onStart
+                        import kotlinx.coroutines.flow.map
+                        import kotlinx.coroutines.flow.distinctUntilChanged
+
+                        suspend fun doSomething(someScope: CoroutineScope, someFlow: SharedFlow<Int>) {
+                            someFlow.onStart { emit(1) }
+                                .map { someOtherFunction() }
+                                .distinctUntilChanged()
+                                .shareIn(someScope, SharingStarted.WhileSubscribed())
+                            someFlow.shareIn(someScope, SharingStarted.Eagerly)
+                        }
+                    """
+                        .trimIndent()
+                ),
+                *androidStubs
+            )
+            .issues(FlowDetector.SHARED_FLOW_CREATION)
+            .run()
+            .expect(
+                """
+src/test/pkg/test.kt:16: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+        .shareIn(someScope, SharingStarted.WhileSubscribed())
+         ~~~~~~~
+src/test/pkg/test.kt:17: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+    someFlow.shareIn(someScope, SharingStarted.Eagerly)
+             ~~~~~~~
+2 errors, 0 warnings
+                """,
+            )
+    }
+}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
index 78e133f..80d9291 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
@@ -87,6 +87,31 @@
             .skipTestModes(TestMode.SUPPRESSIBLE)
             .issues(MissingApacheLicenseDetector.ISSUE)
             .run()
-            .expectContains("License header is missing")
+            .expect(
+                """
+                src/test/pkg/name/MyTest.kt:2: Warning: License header is missing
+                Please add the following copyright and license header to the beginning of the file:
+
+                /*
+                 * Copyright (C) ${Year.now().value} The Android Open Source Project
+                 *
+                 * Licensed under the Apache License, Version 2.0 (the "License");
+                 * you may not use this file except in compliance with the License.
+                 * You may obtain a copy of the License at
+                 *
+                 *     http://www.apache.org/licenses/LICENSE-2.0
+                 *
+                 * Unless required by applicable law or agreed to in writing, software
+                 * distributed under the License is distributed on an "AS IS" BASIS,
+                 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+                 * See the License for the specific language governing permissions and
+                 * limitations under the License.
+                 */ [MissingApacheLicenseDetector]
+
+                 ^
+                0 errors, 1 warnings
+            """
+                    .trimIndent()
+            )
     }
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedMainThreadDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedMainThreadDetectorTest.kt
index ed3d14a..bb34d91 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedMainThreadDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedMainThreadDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class NonInjectedMainThreadDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = NonInjectedMainThreadDetector()
@@ -46,7 +45,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedMainThreadDetector.ISSUE)
             .run()
@@ -79,7 +78,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedMainThreadDetector.ISSUE)
             .run()
@@ -104,7 +103,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedMainThreadDetector.ISSUE)
             .run()
@@ -136,7 +135,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedMainThreadDetector.ISSUE)
             .run()
@@ -149,6 +148,4 @@
                 """
             )
     }
-
-    private val stubs = androidStubs
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedServiceDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedServiceDetectorTest.kt
index 846129a..fe5b576 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedServiceDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/NonInjectedServiceDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class NonInjectedServiceDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = NonInjectedServiceDetector()
@@ -44,7 +43,7 @@
                         """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedServiceDetector.ISSUE)
             .run()
@@ -76,7 +75,7 @@
                         """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedServiceDetector.ISSUE)
             .run()
@@ -109,7 +108,7 @@
                         """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedServiceDetector.ISSUE)
             .run()
@@ -134,7 +133,7 @@
                         """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(NonInjectedServiceDetector.ISSUE)
             .run()
@@ -147,6 +146,4 @@
                 """
             )
     }
-
-    private val stubs = androidStubs
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/RegisterReceiverViaContextDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
index 0ac8f8e..3f12569dfc 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class RegisterReceiverViaContextDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = RegisterReceiverViaContextDetector()
@@ -35,9 +34,8 @@
                 TestFiles.java(
                         """
                     package test.pkg;
-                    import android.content.BroadcastReceiver;
+
                     import android.content.Context;
-                    import android.content.IntentFilter;
 
                     public class TestClass {
                         public void bind(Context context, BroadcastReceiver receiver,
@@ -48,13 +46,13 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(RegisterReceiverViaContextDetector.ISSUE)
             .run()
             .expect(
                 """
-                src/test/pkg/TestClass.java:9: Warning: Register BroadcastReceiver using BroadcastDispatcher instead of Context [RegisterReceiverViaContext]
+                src/test/pkg/TestClass.java:8: Warning: Register BroadcastReceiver using BroadcastDispatcher instead of Context [RegisterReceiverViaContext]
                       context.registerReceiver(receiver, filter, 0);
                               ~~~~~~~~~~~~~~~~
                 0 errors, 1 warnings
@@ -69,9 +67,8 @@
                 TestFiles.java(
                         """
                     package test.pkg;
-                    import android.content.BroadcastReceiver;
+
                     import android.content.Context;
-                    import android.content.IntentFilter;
 
                     @SuppressWarnings("RegisterReceiverViaContext")
                     public class TestClass {
@@ -83,7 +80,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(RegisterReceiverViaContextDetector.ISSUE)
             .run()
@@ -97,11 +94,8 @@
                 TestFiles.java(
                         """
                     package test.pkg;
-                    import android.content.BroadcastReceiver;
+
                     import android.content.Context;
-                    import android.content.IntentFilter;
-                    import android.os.Handler;
-                    import android.os.UserHandle;
 
                     public class TestClass {
                         public void bind(Context context, BroadcastReceiver receiver,
@@ -113,13 +107,13 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(RegisterReceiverViaContextDetector.ISSUE)
             .run()
             .expect(
                 """
-                src/test/pkg/TestClass.java:11: Warning: Register BroadcastReceiver using BroadcastDispatcher instead of Context [RegisterReceiverViaContext]
+                src/test/pkg/TestClass.java:8: Warning: Register BroadcastReceiver using BroadcastDispatcher instead of Context [RegisterReceiverViaContext]
                       context.registerReceiverAsUser(receiver, UserHandle.ALL, filter,
                               ~~~~~~~~~~~~~~~~~~~~~~
                 0 errors, 1 warnings
@@ -134,11 +128,8 @@
                 TestFiles.java(
                         """
                     package test.pkg;
-                    import android.content.BroadcastReceiver;
+
                     import android.content.Context;
-                    import android.content.IntentFilter;
-                    import android.os.Handler;
-                    import android.os.UserHandle;
 
                     public class TestClass {
                         public void bind(Context context, BroadcastReceiver receiver,
@@ -150,19 +141,17 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(RegisterReceiverViaContextDetector.ISSUE)
             .run()
             .expect(
                 """
-                src/test/pkg/TestClass.java:11: Warning: Register BroadcastReceiver using BroadcastDispatcher instead of Context [RegisterReceiverViaContext]
+                src/test/pkg/TestClass.java:8: Warning: Register BroadcastReceiver using BroadcastDispatcher instead of Context [RegisterReceiverViaContext]
                       context.registerReceiverForAllUsers(receiver, filter, "permission",
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
                 0 errors, 1 warnings
                 """
             )
     }
-
-    private val stubs = androidStubs
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SlowUserQueryDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SlowUserQueryDetectorTest.kt
index 34a4249..7944ce3 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SlowUserQueryDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SlowUserQueryDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class SlowUserQueryDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = SlowUserQueryDetector()
@@ -182,5 +181,19 @@
             .expectClean()
     }
 
-    private val stubs = androidStubs
+    private val stubs =
+        arrayOf(
+            *androidStubs,
+            java(
+                    """
+package com.android.systemui.settings;
+import android.content.pm.UserInfo;
+public interface UserTracker {
+    int getUserId();
+    UserInfo getUserInfo();
+}
+"""
+                )
+                .indented()
+        )
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt
index 34becc6..756751c 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class SoftwareBitmapDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = SoftwareBitmapDetector()
@@ -45,7 +44,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(SoftwareBitmapDetector.ISSUE)
             .run()
@@ -80,7 +79,7 @@
                 """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(SoftwareBitmapDetector.ISSUE)
             .run()
@@ -102,12 +101,10 @@
                     }
                 """
                 ),
-                *stubs
+                *androidStubs
             )
             .issues(SoftwareBitmapDetector.ISSUE)
             .run()
             .expectClean()
     }
-
-    private val stubs = androidStubs
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/StaticSettingsProviderDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/StaticSettingsProviderDetectorTest.kt
index efe4c90..fd00018 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/StaticSettingsProviderDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/StaticSettingsProviderDetectorTest.kt
@@ -21,7 +21,6 @@
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Test
 
-@Suppress("UnstableApiUsage")
 class StaticSettingsProviderDetectorTest : SystemUILintDetectorTest() {
 
     override fun getDetector(): Detector = StaticSettingsProviderDetector()
@@ -85,7 +84,7 @@
                         """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(StaticSettingsProviderDetector.ISSUE)
             .run()
@@ -226,12 +225,10 @@
                         """
                     )
                     .indented(),
-                *stubs
+                *androidStubs
             )
             .issues(StaticSettingsProviderDetector.ISSUE)
             .run()
             .expectClean()
     }
-
-    private val stubs = androidStubs
 }
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt
index 3f93f07..b7987f7 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt
@@ -10,15 +10,11 @@
 import org.junit.runners.JUnit4
 import org.junit.runners.model.Statement
 
-@Suppress("UnstableApiUsage")
 @RunWith(JUnit4::class)
 abstract class SystemUILintDetectorTest : LintDetectorTest() {
 
     companion object {
-        @ClassRule
-        @JvmField
-        val libraryChecker: LibraryExists =
-            LibraryExists("framework.jar", "androidx.annotation_annotation.jar")
+        @ClassRule @JvmField val libraryChecker: LibraryExists = LibraryExists(*libraryNames)
     }
 
     class LibraryExists(vararg val libraryNames: String) : TestRule {
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/TestFunctionNameViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/TestFunctionNameViolationDetectorTest.kt
index db73154..a4e82a7 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/TestFunctionNameViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/TestFunctionNameViolationDetectorTest.kt
@@ -18,28 +18,22 @@
 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
 
-@Suppress("UnstableApiUsage")
 class TestFunctionNameViolationDetectorTest : SystemUILintDetectorTest() {
-    override fun getDetector(): Detector {
-        return TestFunctionNameViolationDetector()
-    }
+    override fun getDetector(): Detector = TestFunctionNameViolationDetector()
 
-    override fun getIssues(): List<Issue> {
-        return listOf(
-            TestFunctionNameViolationDetector.ISSUE,
-        )
-    }
+    override fun getIssues(): List<Issue> = listOf(TestFunctionNameViolationDetector.ISSUE)
 
     @Test
     fun violations() {
         lint()
             .files(
-                kotlin(
-                    """
+                TestFiles.kotlin(
+                        """
                     package test.pkg.name
 
                     import org.junit.Test
@@ -64,13 +58,11 @@
                         }
                     }
                 """
-                        .trimIndent()
-                ),
-                testAnnotationStub,
+                    )
+                    .indented(),
+                testAnnotationStub
             )
-            .issues(
-                TestFunctionNameViolationDetector.ISSUE,
-            )
+            .issues(TestFunctionNameViolationDetector.ISSUE)
             .run()
             .expectWarningCount(0)
             .expect(
diff --git a/packages/SystemUI/compose/core/Android.bp b/packages/SystemUI/compose/core/Android.bp
index 4f7a43e..49ae821 100644
--- a/packages/SystemUI/compose/core/Android.bp
+++ b/packages/SystemUI/compose/core/Android.bp
@@ -38,6 +38,7 @@
         "androidx.compose.material3_material3-window-size-class",
         "androidx.savedstate_savedstate",
         "androidx.window_window",
+        "//frameworks/libs/systemui:tracinglib-platform",
     ],
 
     kotlincflags: ["-Xjvm-default=all"],
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt b/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt
index 4a89e31..36e6909 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/PlatformSlider.kt
@@ -25,7 +25,6 @@
 import androidx.compose.foundation.background
 import androidx.compose.foundation.interaction.DragInteraction
 import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
@@ -63,7 +62,6 @@
 import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
@@ -458,40 +456,19 @@
 
     @Composable
     fun defaultPlatformSliderColors(): PlatformSliderColors =
-        if (isSystemInDarkTheme()) darkThemePlatformSliderColors()
-        else lightThemePlatformSliderColors()
+        PlatformSliderColors(
+            trackColor = MaterialTheme.colorScheme.secondaryContainer,
+            indicatorColor = MaterialTheme.colorScheme.primary,
+            iconColor = MaterialTheme.colorScheme.onPrimary,
+            labelColorOnIndicator = MaterialTheme.colorScheme.onPrimary,
+            labelColorOnTrack = MaterialTheme.colorScheme.onSecondaryContainer,
+            disabledTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
+            disabledIndicatorColor = MaterialTheme.colorScheme.surfaceContainerHighest,
+            disabledIconColor = MaterialTheme.colorScheme.outline,
+            disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
+        )
 }
 
-/** [PlatformSliderColors] for the light theme */
-@Composable
-private fun lightThemePlatformSliderColors() =
-    PlatformSliderColors(
-        trackColor = colorResource(android.R.color.system_accent3_200),
-        indicatorColor = MaterialTheme.colorScheme.tertiary,
-        iconColor = MaterialTheme.colorScheme.onTertiary,
-        labelColorOnIndicator = MaterialTheme.colorScheme.onTertiary,
-        labelColorOnTrack = MaterialTheme.colorScheme.onTertiaryContainer,
-        disabledTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
-        disabledIndicatorColor = MaterialTheme.colorScheme.surfaceContainerHighest,
-        disabledIconColor = MaterialTheme.colorScheme.outline,
-        disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
-    )
-
-/** [PlatformSliderColors] for the dark theme */
-@Composable
-private fun darkThemePlatformSliderColors() =
-    PlatformSliderColors(
-        trackColor = colorResource(android.R.color.system_accent3_600),
-        indicatorColor = MaterialTheme.colorScheme.tertiary,
-        iconColor = MaterialTheme.colorScheme.onTertiary,
-        labelColorOnIndicator = MaterialTheme.colorScheme.onTertiary,
-        labelColorOnTrack = colorResource(android.R.color.system_accent3_900),
-        disabledTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
-        disabledIndicatorColor = MaterialTheme.colorScheme.surfaceContainerHighest,
-        disabledIconColor = MaterialTheme.colorScheme.outline,
-        disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
-    )
-
 private fun PlatformSliderColors.getTrackColor(isEnabled: Boolean): Color =
     if (isEnabled) trackColor else disabledTrackColor
 
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/modifiers/MeasureTracing.kt b/packages/SystemUI/compose/core/src/com/android/compose/modifiers/MeasureTracing.kt
new file mode 100644
index 0000000..9ce6cd1
--- /dev/null
+++ b/packages/SystemUI/compose/core/src/com/android/compose/modifiers/MeasureTracing.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.modifiers
+
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.layout
+import androidx.compose.ui.unit.IntOffset
+import com.android.app.tracing.traceSection
+
+/** Adds perfetto markers for the measure + layout stages. */
+inline fun Modifier.measureTracer(crossinline traceNameProducer: () -> String): Modifier {
+    return layout { measurable, constraints ->
+        traceSection(traceNameProducer) {
+            val placeable = measurable.measure(constraints)
+            layout(placeable.width, placeable.height) { placeable.placeRelative(IntOffset.Zero) }
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
index 0f3d3dc2..c22b50d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
@@ -21,6 +21,7 @@
 import android.app.AlertDialog
 import android.content.DialogInterface
 import androidx.compose.animation.Crossfade
+import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.animation.core.snap
 import androidx.compose.animation.core.tween
@@ -54,6 +55,7 @@
 import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -66,6 +68,7 @@
 import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.Dp
@@ -75,6 +78,7 @@
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.unit.times
 import com.android.compose.PlatformButton
+import com.android.compose.animation.Easings
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneScope
@@ -160,7 +164,9 @@
     FoldAware(
         modifier =
             modifier.padding(
+                start = 32.dp,
                 top = 92.dp,
+                end = 32.dp,
                 bottom = 48.dp,
             ),
         viewModel = viewModel,
@@ -663,10 +669,42 @@
     modifier: Modifier = Modifier,
 ) {
     val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState()
+    val appearFadeInAnimatable = remember { Animatable(0f) }
+    val appearMoveAnimatable = remember { Animatable(0f) }
+    val appearAnimationInitialOffset = with(LocalDensity.current) { 80.dp.toPx() }
 
     actionButton?.let { actionButtonViewModel ->
+        LaunchedEffect(Unit) {
+            appearFadeInAnimatable.animateTo(
+                targetValue = 1f,
+                animationSpec =
+                    tween(
+                        durationMillis = 450,
+                        delayMillis = 133,
+                        easing = Easings.LegacyDecelerate,
+                    )
+            )
+        }
+        LaunchedEffect(Unit) {
+            appearMoveAnimatable.animateTo(
+                targetValue = 1f,
+                animationSpec =
+                    tween(
+                        durationMillis = 450,
+                        delayMillis = 133,
+                        easing = Easings.StandardDecelerate,
+                    )
+            )
+        }
+
         Box(
-            modifier = modifier,
+            modifier =
+                modifier.graphicsLayer {
+                    // Translate the button up from an initially pushed-down position:
+                    translationY = (1 - appearMoveAnimatable.value) * appearAnimationInitialOffset
+                    // Fade the button in:
+                    alpha = appearFadeInAnimatable.value
+                },
         ) {
             Button(
                 onClick = actionButtonViewModel.onClick,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index 3ec5508..d59f1f5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -22,11 +22,8 @@
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import com.android.compose.animation.scene.Back
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.Swipe
-import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.bouncer.ui.BouncerDialogFactory
@@ -35,9 +32,7 @@
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.ComposableScene
 import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
 
 object Bouncer {
     object Elements {
@@ -57,13 +52,7 @@
     override val key = Scenes.Bouncer
 
     override val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
-        MutableStateFlow(
-                mapOf(
-                    Back to UserActionResult(Scenes.Lockscreen),
-                    Swipe(SwipeDirection.Down) to UserActionResult(Scenes.Lockscreen),
-                )
-            )
-            .asStateFlow()
+        viewModel.destinationScenes
 
     @Composable
     override fun SceneScope.Content(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index a78c2c0..19d6038 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -52,6 +52,7 @@
 import com.android.internal.R
 import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PatternDotViewModel
+import kotlin.math.max
 import kotlin.math.min
 import kotlin.math.pow
 import kotlin.math.sqrt
@@ -72,15 +73,17 @@
     centerDotsVertically: Boolean,
     modifier: Modifier = Modifier,
 ) {
+    val scope = rememberCoroutineScope()
+    val density = LocalDensity.current
     DisposableEffect(Unit) { onDispose { viewModel.onHidden() } }
 
     val colCount = viewModel.columnCount
     val rowCount = viewModel.rowCount
 
     val dotColor = MaterialTheme.colorScheme.secondary
-    val dotRadius = with(LocalDensity.current) { (DOT_DIAMETER_DP / 2).dp.toPx() }
+    val dotRadius = with(density) { (DOT_DIAMETER_DP / 2).dp.toPx() }
     val lineColor = MaterialTheme.colorScheme.primary
-    val lineStrokeWidth = with(LocalDensity.current) { LINE_STROKE_WIDTH_DP.dp.toPx() }
+    val lineStrokeWidth = with(density) { LINE_STROKE_WIDTH_DP.dp.toPx() }
 
     // All dots that should be rendered on the grid.
     val dots: List<PatternDotViewModel> by viewModel.dots.collectAsState()
@@ -101,7 +104,70 @@
         integerResource(R.integer.lock_pattern_line_fade_out_duration)
     val lineFadeOutAnimationDelayMs = integerResource(R.integer.lock_pattern_line_fade_out_delay)
 
-    val scope = rememberCoroutineScope()
+    val dotAppearFadeInAnimatables = remember(dots) { dots.associateWith { Animatable(0f) } }
+    val dotAppearMoveUpAnimatables = remember(dots) { dots.associateWith { Animatable(0f) } }
+    val dotAppearMaxOffsetPixels =
+        remember(dots) {
+            dots.associateWith { dot -> with(density) { (80 + (20 * dot.y)).dp.toPx() } }
+        }
+    val dotAppearScaleAnimatables = remember(dots) { dots.associateWith { Animatable(0f) } }
+    LaunchedEffect(Unit) {
+        dotAppearFadeInAnimatables.forEach { (dot, animatable) ->
+            scope.launch {
+                // Maps a dot at x and y to an ordinal number to denote the order in which all dots
+                // are visited by the fade-in animation.
+                //
+                // The order is basically starting from the top-left most dot (at 0,0) and ending at
+                // the bottom-right most dot (at 2,2). The visitation order happens
+                // diagonal-by-diagonal. Here's a visual representation of the expected output:
+                // [0][1][3]
+                // [2][4][6]
+                // [5][7][8]
+                //
+                // There's an assumption here that the grid is 3x3. If it's not, this formula needs
+                // to be revisited.
+                check(viewModel.columnCount == 3 && viewModel.rowCount == 3)
+                val staggerOrder = max(0, min(8, 2 * (dot.x + dot.y) + (dot.y - 1)))
+
+                animatable.animateTo(
+                    targetValue = 1f,
+                    animationSpec =
+                        tween(
+                            delayMillis = 33 * staggerOrder,
+                            durationMillis = 450,
+                            easing = Easings.LegacyDecelerate,
+                        )
+                )
+            }
+        }
+        dotAppearMoveUpAnimatables.forEach { (dot, animatable) ->
+            scope.launch {
+                animatable.animateTo(
+                    targetValue = 1f,
+                    animationSpec =
+                        tween(
+                            delayMillis = 0,
+                            durationMillis = 450 + (33 * dot.y),
+                            easing = Easings.StandardDecelerate,
+                        )
+                )
+            }
+        }
+        dotAppearScaleAnimatables.forEach { (dot, animatable) ->
+            scope.launch {
+                animatable.animateTo(
+                    targetValue = 1f,
+                    animationSpec =
+                        tween(
+                            delayMillis = 33 * dot.y,
+                            durationMillis = 450,
+                            easing = Easings.LegacyDecelerate,
+                        )
+                )
+            }
+        }
+    }
+
     val view = LocalView.current
 
     // When the current dot is changed, we need to update our animations.
@@ -322,10 +388,23 @@
 
             // Draw each dot on the grid.
             dots.forEach { dot ->
+                val initialOffset = checkNotNull(dotAppearMaxOffsetPixels[dot])
+                val appearOffset =
+                    (1 - checkNotNull(dotAppearMoveUpAnimatables[dot]).value) * initialOffset
                 drawCircle(
-                    center = pixelOffset(dot, spacing, horizontalOffset, verticalOffset),
-                    color = dotColor,
-                    radius = dotRadius * (dotScalingAnimatables[dot]?.value ?: 1f),
+                    center =
+                        pixelOffset(
+                            dot,
+                            spacing,
+                            horizontalOffset,
+                            verticalOffset + appearOffset,
+                        ),
+                    color =
+                        dotColor.copy(alpha = checkNotNull(dotAppearFadeInAnimatables[dot]).value),
+                    radius =
+                        dotRadius *
+                            checkNotNull(dotScalingAnimatables[dot]).value *
+                            checkNotNull(dotAppearScaleAnimatables[dot]).value,
                 )
             }
         }
@@ -432,12 +511,12 @@
     }
 }
 
-private const val DOT_DIAMETER_DP = 16
-private const val SELECTED_DOT_DIAMETER_DP = 24
+private const val DOT_DIAMETER_DP = 14
+private const val SELECTED_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 1.5).toInt()
 private const val SELECTED_DOT_REACTION_ANIMATION_DURATION_MS = 83
 private const val SELECTED_DOT_RETRACT_ANIMATION_DURATION_MS = 750
-private const val LINE_STROKE_WIDTH_DP = 16
-private const val FAILURE_ANIMATION_DOT_DIAMETER_DP = 13
+private const val LINE_STROKE_WIDTH_DP = DOT_DIAMETER_DP
+private const val FAILURE_ANIMATION_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 0.81f).toInt()
 private const val FAILURE_ANIMATION_DOT_SHRINK_ANIMATION_DURATION_MS = 50
 private const val FAILURE_ANIMATION_DOT_SHRINK_STAGGER_DELAY_MS = 33
 private const val FAILURE_ANIMATION_DOT_REVERT_ANIMATION_DURATION = 617
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt
index 76bd4ec..8144d15 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt
@@ -16,11 +16,16 @@
 
 package com.android.systemui.common.ui.compose.windowinsets
 
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.displayCutout
+import androidx.compose.foundation.layout.systemBars
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.dp
 import kotlinx.coroutines.flow.StateFlow
@@ -31,6 +36,9 @@
 /** The corner radius in px of the current display. */
 val LocalScreenCornerRadius = staticCompositionLocalOf { 0.dp }
 
+/** The screen height in px without accounting for any screen insets (cutouts, status/nav bars) */
+val LocalRawScreenHeight = staticCompositionLocalOf { 0f }
+
 @Composable
 fun ScreenDecorProvider(
     displayCutout: StateFlow<DisplayCutout>,
@@ -39,9 +47,23 @@
 ) {
     val cutout by displayCutout.collectAsState()
     val screenCornerRadiusDp = with(LocalDensity.current) { screenCornerRadius.toDp() }
+
+    val density = LocalDensity.current
+    val navBarHeight =
+        with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() }
+    val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
+    val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding()
+    val screenHeight =
+        with(density) {
+            (LocalConfiguration.current.screenHeightDp.dp +
+                    maxOf(statusBarHeight, displayCutoutHeight))
+                .toPx()
+        } + navBarHeight
+
     CompositionLocalProvider(
         LocalScreenCornerRadius provides screenCornerRadiusDp,
-        LocalDisplayCutout provides cutout
+        LocalDisplayCutout provides cutout,
+        LocalRawScreenHeight provides screenHeight,
     ) {
         content()
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index bdd888f..e07cd05 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -11,6 +11,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.res.dimensionResource
 import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.ElementKey
@@ -24,10 +25,10 @@
 import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.observableTransitionState
 import com.android.compose.animation.scene.transitions
-import com.android.compose.theme.LocalAndroidColorScheme
 import com.android.systemui.communal.shared.model.CommunalScenes
-import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
+import com.android.systemui.communal.shared.model.CommunalTransitionKeys
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
+import com.android.systemui.communal.util.CommunalColors
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
 import com.android.systemui.scene.ui.composable.SceneTransitionLayoutDataSource
@@ -41,6 +42,11 @@
 }
 
 val sceneTransitions = transitions {
+    to(CommunalScenes.Communal, key = CommunalTransitionKeys.SimpleFade) {
+        spec = tween(durationMillis = 250)
+        fade(Communal.Elements.Scrim)
+        fade(Communal.Elements.Content)
+    }
     to(CommunalScenes.Communal) {
         spec = tween(durationMillis = 1000)
         translate(Communal.Elements.Content, Edge.Right)
@@ -69,13 +75,14 @@
     viewModel: CommunalViewModel,
     dataSourceDelegator: SceneDataSourceDelegator,
     dialogFactory: SystemUIDialogFactory,
+    colors: CommunalColors,
 ) {
     val coroutineScope = rememberCoroutineScope()
     val currentSceneKey: SceneKey by viewModel.currentScene.collectAsState(CommunalScenes.Blank)
-    val touchesAllowed by viewModel.touchesAllowed.collectAsState(initial = false)
     val state: MutableSceneTransitionLayoutState = remember {
         MutableSceneTransitionLayoutState(
             initialScene = currentSceneKey,
+            canChangeScene = { _ -> viewModel.canChangeScene() },
             transitions = sceneTransitions,
             enableInterruptions = false,
         )
@@ -105,14 +112,9 @@
         scene(
             CommunalScenes.Blank,
             userActions =
-                if (touchesAllowed) {
-                    mapOf(
-                        Swipe(SwipeDirection.Left, fromSource = Edge.Right) to
-                            CommunalScenes.Communal
-                    )
-                } else {
-                    emptyMap()
-                }
+                mapOf(
+                    Swipe(SwipeDirection.Left, fromSource = Edge.Right) to CommunalScenes.Communal
+                )
         ) {
             // This scene shows nothing only allowing for transitions to the communal scene.
             Box(modifier = Modifier.fillMaxSize())
@@ -121,15 +123,9 @@
         scene(
             CommunalScenes.Communal,
             userActions =
-                if (touchesAllowed) {
-                    mapOf(
-                        Swipe(SwipeDirection.Right, fromSource = Edge.Left) to CommunalScenes.Blank
-                    )
-                } else {
-                    emptyMap()
-                },
+                mapOf(Swipe(SwipeDirection.Right, fromSource = Edge.Left) to CommunalScenes.Blank)
         ) {
-            CommunalScene(viewModel, dialogFactory, modifier = modifier)
+            CommunalScene(viewModel, colors, dialogFactory, modifier = modifier)
         }
     }
 }
@@ -137,15 +133,18 @@
 /** Scene containing the glanceable hub UI. */
 @Composable
 private fun SceneScope.CommunalScene(
-    viewModel: BaseCommunalViewModel,
+    viewModel: CommunalViewModel,
+    colors: CommunalColors,
     dialogFactory: SystemUIDialogFactory,
     modifier: Modifier = Modifier,
 ) {
+    val backgroundColor by colors.backgroundColor.collectAsState()
+
     Box(
         modifier =
             Modifier.element(Communal.Elements.Scrim)
                 .fillMaxSize()
-                .background(LocalAndroidColorScheme.current.outlineVariant),
+                .background(Color(backgroundColor.toArgb())),
     )
     Box(modifier.element(Communal.Elements.Content)) {
         CommunalHub(viewModel = viewModel, dialogFactory = dialogFactory)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index ed80277..89d4343 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -30,6 +30,7 @@
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
@@ -43,6 +44,7 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.lazy.grid.GridCells
 import androidx.compose.foundation.lazy.grid.GridItemSpan
 import androidx.compose.foundation.lazy.grid.LazyGridState
@@ -98,6 +100,9 @@
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.CustomAccessibilityAction
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.customActions
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.semantics.testTagsAsResourceId
 import androidx.compose.ui.text.style.TextAlign
@@ -118,6 +123,7 @@
 import com.android.internal.R.dimen.system_app_widget_background_radius
 import com.android.systemui.communal.domain.model.CommunalContentModel
 import com.android.systemui.communal.shared.model.CommunalContentSize
+import com.android.systemui.communal.shared.model.CommunalScenes
 import com.android.systemui.communal.ui.compose.Dimensions.CardOutlineWidth
 import com.android.systemui.communal.ui.compose.extensions.allowGestures
 import com.android.systemui.communal.ui.compose.extensions.detectLongPressGesture
@@ -222,32 +228,33 @@
                         .motionEventSpy { onMotionEvent(viewModel) }
                 },
     ) {
-        if (!viewModel.isEditMode && isEmptyState) {
-            EmptyStateCta(
-                contentPadding = contentPadding,
-                viewModel = viewModel,
-            )
-        } else {
-            CommunalHubLazyGrid(
-                communalContent = communalContent,
-                viewModel = viewModel,
-                contentPadding = contentPadding,
-                contentOffset = contentOffset,
-                setGridCoordinates = { gridCoordinates = it },
-                updateDragPositionForRemove = { offset ->
-                    isDraggingToRemove =
-                        isPointerWithinCoordinates(
-                            offset = gridCoordinates?.let { it.positionInWindow() + offset },
-                            containerToCheck = removeButtonCoordinates
-                        )
-                    isDraggingToRemove
-                },
-                onOpenWidgetPicker = onOpenWidgetPicker,
-                gridState = gridState,
-                contentListState = contentListState,
-                selectedKey = selectedKey,
-                widgetConfigurator = widgetConfigurator,
-            )
+        AccessibilityContainer(viewModel) {
+            if (!viewModel.isEditMode && isEmptyState) {
+                EmptyStateCta(
+                    contentPadding = contentPadding,
+                    viewModel = viewModel,
+                )
+            } else {
+                CommunalHubLazyGrid(
+                    communalContent = communalContent,
+                    viewModel = viewModel,
+                    contentPadding = contentPadding,
+                    contentOffset = contentOffset,
+                    setGridCoordinates = { gridCoordinates = it },
+                    updateDragPositionForRemove = { offset ->
+                        isDraggingToRemove =
+                            isPointerWithinCoordinates(
+                                offset = gridCoordinates?.let { it.positionInWindow() + offset },
+                                containerToCheck = removeButtonCoordinates
+                            )
+                        isDraggingToRemove
+                    },
+                    gridState = gridState,
+                    contentListState = contentListState,
+                    selectedKey = selectedKey,
+                    widgetConfigurator = widgetConfigurator,
+                )
+            }
         }
 
         // TODO(b/326060686): Remove this once keyguard indication area can persist over hub
@@ -384,7 +391,6 @@
     contentListState: ContentListState,
     setGridCoordinates: (coordinates: LayoutCoordinates) -> Unit,
     updateDragPositionForRemove: (offset: Offset) -> Boolean,
-    onOpenWidgetPicker: (() -> Unit)? = null,
     widgetConfigurator: WidgetConfigurator?,
 ) {
     var gridModifier =
@@ -452,7 +458,6 @@
                         model = list[index],
                         viewModel = viewModel,
                         size = size,
-                        onOpenWidgetPicker = onOpenWidgetPicker,
                         selected = selected && !isDragging,
                         widgetConfigurator = widgetConfigurator,
                     )
@@ -730,7 +735,6 @@
     size: SizeF,
     selected: Boolean,
     modifier: Modifier = Modifier,
-    onOpenWidgetPicker: (() -> Unit)? = null,
     widgetConfigurator: WidgetConfigurator? = null,
 ) {
     when (model) {
@@ -990,6 +994,45 @@
     )
 }
 
+/** Container of the glanceable hub grid to enable accessibility actions when focused. */
+@Composable
+fun AccessibilityContainer(viewModel: BaseCommunalViewModel, content: @Composable () -> Unit) {
+    val context = LocalContext.current
+    val isFocusable by viewModel.isFocusable.collectAsState(initial = false)
+    Box(
+        modifier =
+            Modifier.fillMaxWidth().wrapContentHeight().thenIf(
+                isFocusable && !viewModel.isEditMode
+            ) {
+                Modifier.focusable(isFocusable).semantics {
+                    contentDescription =
+                        context.getString(
+                            R.string.accessibility_content_description_for_communal_hub
+                        )
+                    customActions =
+                        listOf(
+                            CustomAccessibilityAction(
+                                context.getString(
+                                    R.string.accessibility_action_label_close_communal_hub
+                                )
+                            ) {
+                                viewModel.changeScene(CommunalScenes.Blank)
+                                true
+                            },
+                            CustomAccessibilityAction(
+                                context.getString(R.string.accessibility_action_label_edit_widgets)
+                            ) {
+                                viewModel.onOpenWidgetEditor()
+                                true
+                            }
+                        )
+                }
+            }
+    ) {
+        content()
+    }
+}
+
 /**
  * Returns the `contentPadding` of the grid. Use the vertical padding to push the grid content area
  * below the toolbar and let the grid take the max size. This ensures the item can be dragged
@@ -1066,7 +1109,7 @@
     val CardHeightHalf = 282.dp
     val CardHeightThird = 177.33.dp
     val CardOutlineWidth = 3.dp
-    val GridTopSpacing = 72.dp
+    val GridTopSpacing = 64.dp
     val GridHeight = CardHeightFull + GridTopSpacing
     val Spacing = 16.dp
 
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/DragAndDropTargetState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/DragAndDropTargetState.kt
index dee2559..37fe798 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/DragAndDropTargetState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/DragAndDropTargetState.kt
@@ -161,9 +161,9 @@
     private var isOnRemoveButton = false
 
     fun onStarted() {
-        // assume item will be added to the second to last position before CTA tile.
+        // assume item will be added to the end.
+        contentListState.list.add(placeHolder)
         placeHolderIndex = contentListState.list.size - 1
-        placeHolderIndex?.let { contentListState.list.add(it, placeHolder) }
     }
 
     fun onMoved(event: DragAndDropEvent) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt
index 55f7f69a..9afb4d5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenSceneBlueprintModule.kt
@@ -17,10 +17,7 @@
 package com.android.systemui.keyguard.ui.composable
 
 import com.android.systemui.keyguard.ui.composable.blueprint.CommunalBlueprintModule
-import com.android.systemui.keyguard.ui.composable.blueprint.DefaultBlueprintModule
 import com.android.systemui.keyguard.ui.composable.blueprint.ShortcutsBesideUdfpsBlueprintModule
-import com.android.systemui.keyguard.ui.composable.blueprint.SplitShadeWeatherClockBlueprintModule
-import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockBlueprintModule
 import com.android.systemui.keyguard.ui.composable.section.OptionalSectionModule
 import dagger.Module
 
@@ -28,11 +25,8 @@
     includes =
         [
             CommunalBlueprintModule::class,
-            DefaultBlueprintModule::class,
             OptionalSectionModule::class,
             ShortcutsBesideUdfpsBlueprintModule::class,
-            SplitShadeWeatherClockBlueprintModule::class,
-            WeatherClockBlueprintModule::class,
         ],
 )
 interface LockscreenSceneBlueprintModule
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/BurnInState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/BurnInState.kt
index 7a73c58..8129e41 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/BurnInState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/BurnInState.kt
@@ -71,7 +71,6 @@
 
     return remember(clock, topInset, topmostTop) {
         BurnInParameters(
-            clockControllerProvider = { clock },
             topInset = topInset,
             minViewY = topmostTop,
         )
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt
index acd9e3d..c6fe81a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt
@@ -25,6 +25,9 @@
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.largeClockElementKey
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.smallClockElementKey
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.smartspaceElementKey
+import com.android.systemui.keyguard.ui.composable.blueprint.ClockTransition.transitioningToLargeClock
+import com.android.systemui.keyguard.ui.composable.blueprint.ClockTransition.transitioningToSmallClock
+import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys.largeWeatherClockElementKeyList
 import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.ClockFaceInTransition.Companion.CLOCK_IN_MILLIS
 import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.ClockFaceInTransition.Companion.CLOCK_IN_START_DELAY_MILLIS
 import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.ClockFaceOutTransition.Companion.CLOCK_OUT_MILLIS
@@ -34,30 +37,45 @@
 object ClockTransition {
     val defaultClockTransitions = transitions {
         from(ClockScenes.smallClockScene, to = ClockScenes.largeClockScene) {
-            transitioningToLargeClock()
+            transitioningToLargeClock(largeClockElements = listOf(largeClockElementKey))
         }
         from(ClockScenes.largeClockScene, to = ClockScenes.smallClockScene) {
-            transitioningToSmallClock()
+            transitioningToSmallClock(largeClockElements = listOf(largeClockElementKey))
         }
         from(ClockScenes.splitShadeLargeClockScene, to = ClockScenes.largeClockScene) {
-            spec = tween(1000, easing = LinearEasing)
+            spec = tween(300, easing = LinearEasing)
+        }
+
+        from(WeatherClockScenes.largeClockScene, to = ClockScenes.smallClockScene) {
+            transitioningToSmallClock(largeClockElements = largeWeatherClockElementKeyList)
+        }
+
+        from(ClockScenes.smallClockScene, to = WeatherClockScenes.largeClockScene) {
+            transitioningToLargeClock(largeClockElements = largeWeatherClockElementKeyList)
+        }
+
+        from(
+            WeatherClockScenes.largeClockScene,
+            to = WeatherClockScenes.splitShadeLargeClockScene
+        ) {
+            spec = tween(300, easing = LinearEasing)
         }
     }
 
-    private fun TransitionBuilder.transitioningToLargeClock() {
+    private fun TransitionBuilder.transitioningToLargeClock(largeClockElements: List<ElementKey>) {
         spec = tween(durationMillis = STATUS_AREA_MOVE_UP_MILLIS.toInt())
         timestampRange(
             startMillis = CLOCK_IN_START_DELAY_MILLIS.toInt(),
             endMillis = (CLOCK_IN_START_DELAY_MILLIS + CLOCK_IN_MILLIS).toInt()
         ) {
-            fade(largeClockElementKey)
+            largeClockElements.forEach { fade(it) }
         }
 
         timestampRange(endMillis = CLOCK_OUT_MILLIS.toInt()) { fade(smallClockElementKey) }
         anchoredTranslate(smallClockElementKey, smartspaceElementKey)
     }
 
-    private fun TransitionBuilder.transitioningToSmallClock() {
+    private fun TransitionBuilder.transitioningToSmallClock(largeClockElements: List<ElementKey>) {
         spec = tween(durationMillis = STATUS_AREA_MOVE_DOWN_MILLIS.toInt())
         timestampRange(
             startMillis = CLOCK_IN_START_DELAY_MILLIS.toInt(),
@@ -66,7 +84,9 @@
             fade(smallClockElementKey)
         }
 
-        timestampRange(endMillis = CLOCK_OUT_MILLIS.toInt()) { fade(largeClockElementKey) }
+        timestampRange(endMillis = CLOCK_OUT_MILLIS.toInt()) {
+            largeClockElements.forEach { fade(it) }
+        }
         anchoredTranslate(smallClockElementKey, smartspaceElementKey)
     }
 }
@@ -81,14 +101,26 @@
 object ClockElementKeys {
     val largeClockElementKey = ElementKey("large-clock")
     val smallClockElementKey = ElementKey("small-clock")
-    val weatherSmallClockElementKey = ElementKey("weather-small-clock")
     val smartspaceElementKey = ElementKey("smart-space")
 }
 
+object WeatherClockScenes {
+    val largeClockScene = SceneKey("large-weather-clock-scene")
+    val splitShadeLargeClockScene = SceneKey("split-shade-large-weather-clock-scene")
+}
+
 object WeatherClockElementKeys {
     val timeElementKey = ElementKey("weather-large-clock-time")
     val dateElementKey = ElementKey("weather-large-clock-date")
     val weatherIconElementKey = ElementKey("weather-large-clock-weather-icon")
     val temperatureElementKey = ElementKey("weather-large-clock-temperature")
     val dndAlarmElementKey = ElementKey("weather-large-clock-dnd-alarm")
+    val largeWeatherClockElementKeyList =
+        listOf(
+            timeElementKey,
+            dateElementKey,
+            weatherIconElementKey,
+            temperatureElementKey,
+            dndAlarmElementKey
+        )
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
index c008a1a..3152535 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
@@ -26,9 +26,11 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.unit.IntRect
 import com.android.compose.animation.scene.SceneScope
+import com.android.compose.modifiers.padding
 import com.android.systemui.keyguard.ui.composable.LockscreenLongPress
 import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection
 import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection
@@ -38,11 +40,9 @@
 import com.android.systemui.keyguard.ui.composable.section.StatusBarSection
 import com.android.systemui.keyguard.ui.composable.section.TopAreaSection
 import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
-import dagger.Binds
-import dagger.Module
-import dagger.multibindings.IntoSet
 import java.util.Optional
 import javax.inject.Inject
+import kotlin.math.roundToInt
 
 /**
  * Renders the lockscreen scene when showing with the default layout (e.g. vertical phone form
@@ -68,6 +68,7 @@
         val isUdfpsVisible = viewModel.isUdfpsVisible
         val shouldUseSplitNotificationShade by
             viewModel.shouldUseSplitNotificationShade.collectAsState()
+        val unfoldTranslations by viewModel.unfoldTranslations.collectAsState()
 
         LockscreenLongPress(
             viewModel = viewModel.longPress,
@@ -79,23 +80,43 @@
                     Column(
                         modifier = Modifier.fillMaxSize(),
                     ) {
-                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
+                        with(statusBarSection) {
+                            StatusBar(
+                                modifier =
+                                    Modifier.fillMaxWidth()
+                                        .padding(
+                                            horizontal = { unfoldTranslations.start.roundToInt() },
+                                        )
+                            )
+                        }
 
                         Box {
-                            with(topAreaSection) { DefaultClockLayout() }
+                            with(topAreaSection) {
+                                DefaultClockLayout(
+                                    modifier =
+                                        Modifier.graphicsLayer {
+                                            translationX = unfoldTranslations.start
+                                        }
+                                )
+                            }
                             if (shouldUseSplitNotificationShade) {
                                 with(notificationSection) {
                                     Notifications(
-                                        Modifier.fillMaxWidth(0.5f)
-                                            .fillMaxHeight()
-                                            .align(alignment = Alignment.TopEnd)
+                                        burnInParams = null,
+                                        modifier =
+                                            Modifier.fillMaxWidth(0.5f)
+                                                .fillMaxHeight()
+                                                .align(alignment = Alignment.TopEnd)
                                     )
                                 }
                             }
                         }
                         if (!shouldUseSplitNotificationShade) {
                             with(notificationSection) {
-                                Notifications(Modifier.weight(weight = 1f))
+                                Notifications(
+                                    burnInParams = null,
+                                    modifier = Modifier.weight(weight = 1f)
+                                )
                             }
                         }
                         if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
@@ -122,8 +143,18 @@
 
                     // Aligned to bottom and NOT constrained by the lock icon.
                     with(bottomAreaSection) {
-                        Shortcut(isStart = true, applyPadding = true)
-                        Shortcut(isStart = false, applyPadding = true)
+                        Shortcut(
+                            isStart = true,
+                            applyPadding = true,
+                            modifier =
+                                Modifier.graphicsLayer { translationX = unfoldTranslations.start },
+                        )
+                        Shortcut(
+                            isStart = false,
+                            applyPadding = true,
+                            modifier =
+                                Modifier.graphicsLayer { translationX = unfoldTranslations.end },
+                        )
                     }
                     with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) }
                 },
@@ -196,8 +227,3 @@
         }
     }
 }
-
-@Module
-interface DefaultBlueprintModule {
-    @Binds @IntoSet fun blueprint(blueprint: DefaultBlueprint): ComposableLockscreenSceneBlueprint
-}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprintModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprintModule.kt
new file mode 100644
index 0000000..e0bb26e
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprintModule.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.composable.blueprint
+
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+@Module
+interface DefaultBlueprintModule {
+    @Binds @IntoSet fun blueprint(blueprint: DefaultBlueprint): ComposableLockscreenSceneBlueprint
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt
index 091a439..9d31955 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt
@@ -26,9 +26,11 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.unit.IntRect
 import com.android.compose.animation.scene.SceneScope
+import com.android.compose.modifiers.padding
 import com.android.systemui.keyguard.ui.composable.LockscreenLongPress
 import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection
 import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection
@@ -43,6 +45,7 @@
 import dagger.multibindings.IntoSet
 import java.util.Optional
 import javax.inject.Inject
+import kotlin.math.roundToInt
 
 /**
  * Renders the lockscreen scene when showing with the default layout (e.g. vertical phone form
@@ -68,6 +71,7 @@
         val isUdfpsVisible = viewModel.isUdfpsVisible
         val shouldUseSplitNotificationShade by
             viewModel.shouldUseSplitNotificationShade.collectAsState()
+        val unfoldTranslations by viewModel.unfoldTranslations.collectAsState()
 
         LockscreenLongPress(
             viewModel = viewModel.longPress,
@@ -79,23 +83,43 @@
                     Column(
                         modifier = Modifier.fillMaxSize(),
                     ) {
-                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
+                        with(statusBarSection) {
+                            StatusBar(
+                                modifier =
+                                    Modifier.fillMaxWidth()
+                                        .padding(
+                                            horizontal = { unfoldTranslations.start.roundToInt() },
+                                        )
+                            )
+                        }
 
                         Box {
-                            with(topAreaSection) { DefaultClockLayout() }
+                            with(topAreaSection) {
+                                DefaultClockLayout(
+                                    modifier =
+                                        Modifier.graphicsLayer {
+                                            translationX = unfoldTranslations.start
+                                        },
+                                )
+                            }
                             if (shouldUseSplitNotificationShade) {
                                 with(notificationSection) {
                                     Notifications(
-                                        Modifier.fillMaxWidth(0.5f)
-                                            .fillMaxHeight()
-                                            .align(alignment = Alignment.TopEnd)
+                                        burnInParams = null,
+                                        modifier =
+                                            Modifier.fillMaxWidth(0.5f)
+                                                .fillMaxHeight()
+                                                .align(alignment = Alignment.TopEnd)
                                     )
                                 }
                             }
                         }
                         if (!shouldUseSplitNotificationShade) {
                             with(notificationSection) {
-                                Notifications(Modifier.weight(weight = 1f))
+                                Notifications(
+                                    burnInParams = null,
+                                    modifier = Modifier.weight(weight = 1f)
+                                )
                             }
                         }
                         if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
@@ -106,12 +130,26 @@
                     }
 
                     // Constrained to the left of the lock icon (in left-to-right layouts).
-                    with(bottomAreaSection) { Shortcut(isStart = true, applyPadding = false) }
+                    with(bottomAreaSection) {
+                        Shortcut(
+                            isStart = true,
+                            applyPadding = false,
+                            modifier =
+                                Modifier.graphicsLayer { translationX = unfoldTranslations.start },
+                        )
+                    }
 
                     with(lockSection) { LockIcon() }
 
                     // Constrained to the right of the lock icon (in left-to-right layouts).
-                    with(bottomAreaSection) { Shortcut(isStart = false, applyPadding = false) }
+                    with(bottomAreaSection) {
+                        Shortcut(
+                            isStart = false,
+                            applyPadding = false,
+                            modifier =
+                                Modifier.graphicsLayer { translationX = unfoldTranslations.end },
+                        )
+                    }
 
                     // Aligned to bottom and constrained to below the lock icon.
                     Column(modifier = Modifier.fillMaxWidth()) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt
deleted file mode 100644
index 09d76a3..0000000
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/WeatherClockBlueprint.kt
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.ui.composable.blueprint
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.dimensionResource
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.IntRect
-import androidx.compose.ui.unit.dp
-import com.android.compose.animation.scene.SceneScope
-import com.android.compose.modifiers.padding
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.systemui.Flags
-import com.android.systemui.customization.R as customizationR
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID
-import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.ui.composable.LockscreenLongPress
-import com.android.systemui.keyguard.ui.composable.modifier.onTopPlacementChanged
-import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection
-import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection
-import com.android.systemui.keyguard.ui.composable.section.LockSection
-import com.android.systemui.keyguard.ui.composable.section.MediaCarouselSection
-import com.android.systemui.keyguard.ui.composable.section.NotificationSection
-import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection
-import com.android.systemui.keyguard.ui.composable.section.SmartSpaceSection
-import com.android.systemui.keyguard.ui.composable.section.StatusBarSection
-import com.android.systemui.keyguard.ui.composable.section.WeatherClockSection
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
-import com.android.systemui.res.R
-import com.android.systemui.shade.LargeScreenHeaderHelper
-import dagger.Binds
-import dagger.Module
-import dagger.multibindings.IntoSet
-import java.util.Optional
-import javax.inject.Inject
-
-class WeatherClockBlueprint
-@Inject
-constructor(
-    private val viewModel: LockscreenContentViewModel,
-    private val statusBarSection: StatusBarSection,
-    private val weatherClockSection: WeatherClockSection,
-    private val smartSpaceSection: SmartSpaceSection,
-    private val notificationSection: NotificationSection,
-    private val lockSection: LockSection,
-    private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>,
-    private val bottomAreaSection: BottomAreaSection,
-    private val settingsMenuSection: SettingsMenuSection,
-    private val clockInteractor: KeyguardClockInteractor,
-    private val mediaCarouselSection: MediaCarouselSection,
-    private val clockViewModel: KeyguardClockViewModel,
-) : ComposableLockscreenSceneBlueprint {
-
-    override val id: String = WEATHER_CLOCK_BLUEPRINT_ID
-    @Composable
-    override fun SceneScope.Content(modifier: Modifier) {
-        val isUdfpsVisible = viewModel.isUdfpsVisible
-        val burnIn = rememberBurnIn(clockInteractor)
-        val resources = LocalContext.current.resources
-        val currentClockState = clockViewModel.currentClock.collectAsState()
-        val areNotificationsVisible by viewModel.areNotificationsVisible.collectAsState()
-        LockscreenLongPress(
-            viewModel = viewModel.longPress,
-            modifier = modifier,
-        ) { onSettingsMenuPlaced ->
-            Layout(
-                content = {
-                    // Constrained to above the lock icon.
-                    Column(
-                        modifier = Modifier.fillMaxWidth(),
-                    ) {
-                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
-                        val currentClock = currentClockState.value
-                        val clockSize by clockViewModel.clockSize.collectAsState()
-                        with(weatherClockSection) {
-                            if (currentClock == null) {
-                                return@with
-                            }
-
-                            if (clockSize == LARGE) {
-                                Time(
-                                    clock = currentClock,
-                                    modifier =
-                                        Modifier.padding(
-                                            start =
-                                                dimensionResource(
-                                                    customizationR.dimen.clock_padding_start
-                                                )
-                                        )
-                                )
-                            } else {
-                                SmallClock(
-                                    burnInParams = burnIn.parameters,
-                                    modifier =
-                                        Modifier.align(Alignment.Start)
-                                            .onTopPlacementChanged(burnIn.onSmallClockTopChanged),
-                                    clock = currentClock
-                                )
-                            }
-                        }
-                        with(smartSpaceSection) {
-                            SmartSpace(
-                                burnInParams = burnIn.parameters,
-                                onTopChanged = burnIn.onSmartspaceTopChanged,
-                                modifier =
-                                    Modifier.fillMaxWidth()
-                                        .padding(
-                                            top = { viewModel.getSmartSpacePaddingTop(resources) },
-                                        )
-                                        .padding(
-                                            bottom =
-                                                dimensionResource(
-                                                    R.dimen.keyguard_status_view_bottom_margin
-                                                ),
-                                        ),
-                            )
-                        }
-
-                        with(mediaCarouselSection) { MediaCarousel() }
-
-                        if (areNotificationsVisible) {
-                            with(notificationSection) {
-                                Notifications(
-                                    modifier = Modifier.fillMaxWidth().weight(weight = 1f)
-                                )
-                            }
-                        }
-                        with(weatherClockSection) {
-                            if (currentClock == null || clockSize != LARGE) {
-                                return@with
-                            }
-                            LargeClockSectionBelowSmartspace(clock = currentClock)
-                        }
-
-                        if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
-                            with(ambientIndicationSectionOptional.get()) {
-                                AmbientIndication(modifier = Modifier.fillMaxWidth())
-                            }
-                        }
-                    }
-
-                    with(lockSection) { LockIcon() }
-
-                    // Aligned to bottom and constrained to below the lock icon.
-                    Column(modifier = Modifier.fillMaxWidth()) {
-                        if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
-                            with(ambientIndicationSectionOptional.get()) {
-                                AmbientIndication(modifier = Modifier.fillMaxWidth())
-                            }
-                        }
-
-                        with(bottomAreaSection) {
-                            IndicationArea(modifier = Modifier.fillMaxWidth())
-                        }
-                    }
-
-                    // Aligned to bottom and NOT constrained by the lock icon.
-                    with(bottomAreaSection) {
-                        Shortcut(isStart = true, applyPadding = true)
-                        Shortcut(isStart = false, applyPadding = true)
-                    }
-                    with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) }
-                },
-                modifier = Modifier.fillMaxSize(),
-            ) { measurables, constraints ->
-                check(measurables.size == 6)
-                val aboveLockIconMeasurable = measurables[0]
-                val lockIconMeasurable = measurables[1]
-                val belowLockIconMeasurable = measurables[2]
-                val startShortcutMeasurable = measurables[3]
-                val endShortcutMeasurable = measurables[4]
-                val settingsMenuMeasurable = measurables[5]
-
-                val noMinConstraints =
-                    constraints.copy(
-                        minWidth = 0,
-                        minHeight = 0,
-                    )
-                val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints)
-                val lockIconBounds =
-                    IntRect(
-                        left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left],
-                        top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top],
-                        right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right],
-                        bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom],
-                    )
-
-                val aboveLockIconPlaceable =
-                    aboveLockIconMeasurable.measure(
-                        noMinConstraints.copy(maxHeight = lockIconBounds.top)
-                    )
-                val belowLockIconPlaceable =
-                    belowLockIconMeasurable.measure(
-                        noMinConstraints.copy(
-                            maxHeight =
-                                (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0)
-                        )
-                    )
-                val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints)
-                val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints)
-                val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints)
-
-                layout(constraints.maxWidth, constraints.maxHeight) {
-                    aboveLockIconPlaceable.place(
-                        x = 0,
-                        y = 0,
-                    )
-                    lockIconPlaceable.place(
-                        x = lockIconBounds.left,
-                        y = lockIconBounds.top,
-                    )
-                    belowLockIconPlaceable.place(
-                        x = 0,
-                        y = constraints.maxHeight - belowLockIconPlaceable.height,
-                    )
-                    startShortcutPleaceable.place(
-                        x = 0,
-                        y = constraints.maxHeight - startShortcutPleaceable.height,
-                    )
-                    endShortcutPleaceable.place(
-                        x = constraints.maxWidth - endShortcutPleaceable.width,
-                        y = constraints.maxHeight - endShortcutPleaceable.height,
-                    )
-                    settingsMenuPlaceable.place(
-                        x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2,
-                        y = constraints.maxHeight - settingsMenuPlaceable.height,
-                    )
-                }
-            }
-        }
-    }
-}
-
-class SplitShadeWeatherClockBlueprint
-@Inject
-constructor(
-    private val viewModel: LockscreenContentViewModel,
-    private val statusBarSection: StatusBarSection,
-    private val smartSpaceSection: SmartSpaceSection,
-    private val notificationSection: NotificationSection,
-    private val lockSection: LockSection,
-    private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>,
-    private val bottomAreaSection: BottomAreaSection,
-    private val settingsMenuSection: SettingsMenuSection,
-    private val clockInteractor: KeyguardClockInteractor,
-    private val largeScreenHeaderHelper: LargeScreenHeaderHelper,
-    private val weatherClockSection: WeatherClockSection,
-    private val mediaCarouselSection: MediaCarouselSection,
-    private val clockViewModel: KeyguardClockViewModel,
-) : ComposableLockscreenSceneBlueprint {
-    override val id: String = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-
-    @Composable
-    override fun SceneScope.Content(modifier: Modifier) {
-        val isUdfpsVisible = viewModel.isUdfpsVisible
-        val burnIn = rememberBurnIn(clockInteractor)
-        val resources = LocalContext.current.resources
-        val currentClockState = clockViewModel.currentClock.collectAsState()
-        LockscreenLongPress(
-            viewModel = viewModel.longPress,
-            modifier = modifier,
-        ) { onSettingsMenuPlaced ->
-            Layout(
-                content = {
-                    // Constrained to above the lock icon.
-                    Column(
-                        modifier = Modifier.fillMaxSize(),
-                    ) {
-                        with(statusBarSection) { StatusBar(modifier = Modifier.fillMaxWidth()) }
-                        Row(
-                            modifier = Modifier.fillMaxSize(),
-                        ) {
-                            Column(
-                                modifier = Modifier.fillMaxHeight().weight(weight = 1f),
-                                horizontalAlignment = Alignment.CenterHorizontally,
-                            ) {
-                                val currentClock = currentClockState.value
-                                val clockSize by clockViewModel.clockSize.collectAsState()
-                                with(weatherClockSection) {
-                                    if (currentClock == null) {
-                                        return@with
-                                    }
-
-                                    if (clockSize == LARGE) {
-                                        Time(
-                                            clock = currentClock,
-                                            modifier =
-                                                Modifier.align(Alignment.Start)
-                                                    .padding(
-                                                        start =
-                                                            dimensionResource(
-                                                                customizationR.dimen
-                                                                    .clock_padding_start
-                                                            )
-                                                    )
-                                        )
-                                    } else {
-                                        SmallClock(
-                                            burnInParams = burnIn.parameters,
-                                            modifier =
-                                                Modifier.align(Alignment.Start)
-                                                    .onTopPlacementChanged(
-                                                        burnIn.onSmallClockTopChanged
-                                                    ),
-                                            clock = currentClock,
-                                        )
-                                    }
-                                }
-                                with(smartSpaceSection) {
-                                    SmartSpace(
-                                        burnInParams = burnIn.parameters,
-                                        onTopChanged = burnIn.onSmartspaceTopChanged,
-                                        modifier =
-                                            Modifier.fillMaxWidth()
-                                                .padding(
-                                                    top = {
-                                                        viewModel.getSmartSpacePaddingTop(resources)
-                                                    },
-                                                )
-                                                .padding(
-                                                    bottom =
-                                                        dimensionResource(
-                                                            R.dimen
-                                                                .keyguard_status_view_bottom_margin
-                                                        )
-                                                ),
-                                    )
-                                }
-
-                                with(mediaCarouselSection) { MediaCarousel() }
-
-                                with(weatherClockSection) {
-                                    if (currentClock == null || clockSize != LARGE) {
-                                        return@with
-                                    }
-
-                                    LargeClockSectionBelowSmartspace(currentClock)
-                                }
-                            }
-                            with(notificationSection) {
-                                val splitShadeTopMargin: Dp =
-                                    if (Flags.centralizedStatusBarHeightFix()) {
-                                        largeScreenHeaderHelper.getLargeScreenHeaderHeight().dp
-                                    } else {
-                                        dimensionResource(
-                                            id = R.dimen.large_screen_shade_header_height
-                                        )
-                                    }
-                                Notifications(
-                                    modifier =
-                                        Modifier.fillMaxHeight()
-                                            .weight(weight = 1f)
-                                            .padding(top = splitShadeTopMargin)
-                                )
-                            }
-                        }
-
-                        if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
-                            with(ambientIndicationSectionOptional.get()) {
-                                AmbientIndication(modifier = Modifier.fillMaxWidth())
-                            }
-                        }
-                    }
-
-                    with(lockSection) { LockIcon() }
-
-                    // Aligned to bottom and constrained to below the lock icon.
-                    Column(modifier = Modifier.fillMaxWidth()) {
-                        if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
-                            with(ambientIndicationSectionOptional.get()) {
-                                AmbientIndication(modifier = Modifier.fillMaxWidth())
-                            }
-                        }
-
-                        with(bottomAreaSection) {
-                            IndicationArea(modifier = Modifier.fillMaxWidth())
-                        }
-                    }
-
-                    // Aligned to bottom and NOT constrained by the lock icon.
-                    with(bottomAreaSection) {
-                        Shortcut(isStart = true, applyPadding = true)
-                        Shortcut(isStart = false, applyPadding = true)
-                    }
-                    with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) }
-                },
-                modifier = Modifier.fillMaxSize(),
-            ) { measurables, constraints ->
-                check(measurables.size == 6)
-                val aboveLockIconMeasurable = measurables[0]
-                val lockIconMeasurable = measurables[1]
-                val belowLockIconMeasurable = measurables[2]
-                val startShortcutMeasurable = measurables[3]
-                val endShortcutMeasurable = measurables[4]
-                val settingsMenuMeasurable = measurables[5]
-
-                val noMinConstraints =
-                    constraints.copy(
-                        minWidth = 0,
-                        minHeight = 0,
-                    )
-                val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints)
-                val lockIconBounds =
-                    IntRect(
-                        left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left],
-                        top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top],
-                        right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right],
-                        bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom],
-                    )
-
-                val aboveLockIconPlaceable =
-                    aboveLockIconMeasurable.measure(
-                        noMinConstraints.copy(maxHeight = lockIconBounds.top)
-                    )
-                val belowLockIconPlaceable =
-                    belowLockIconMeasurable.measure(
-                        noMinConstraints.copy(
-                            maxHeight =
-                                (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0)
-                        )
-                    )
-                val startShortcutPleaceable = startShortcutMeasurable.measure(noMinConstraints)
-                val endShortcutPleaceable = endShortcutMeasurable.measure(noMinConstraints)
-                val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints)
-
-                layout(constraints.maxWidth, constraints.maxHeight) {
-                    aboveLockIconPlaceable.place(
-                        x = 0,
-                        y = 0,
-                    )
-                    lockIconPlaceable.place(
-                        x = lockIconBounds.left,
-                        y = lockIconBounds.top,
-                    )
-                    belowLockIconPlaceable.place(
-                        x = 0,
-                        y = constraints.maxHeight - belowLockIconPlaceable.height,
-                    )
-                    startShortcutPleaceable.place(
-                        x = 0,
-                        y = constraints.maxHeight - startShortcutPleaceable.height,
-                    )
-                    endShortcutPleaceable.place(
-                        x = constraints.maxWidth - endShortcutPleaceable.width,
-                        y = constraints.maxHeight - endShortcutPleaceable.height,
-                    )
-                    settingsMenuPlaceable.place(
-                        x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2,
-                        y = constraints.maxHeight - settingsMenuPlaceable.height,
-                    )
-                }
-            }
-        }
-    }
-}
-
-@Module
-interface WeatherClockBlueprintModule {
-    @Binds
-    @IntoSet
-    fun blueprint(blueprint: WeatherClockBlueprint): ComposableLockscreenSceneBlueprint
-}
-
-@Module
-interface SplitShadeWeatherClockBlueprintModule {
-    @Binds
-    @IntoSet
-    fun blueprint(blueprint: SplitShadeWeatherClockBlueprint): ComposableLockscreenSceneBlueprint
-}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt
index 2a99039..238a230 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt
@@ -19,6 +19,8 @@
 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.ui.Modifier
 import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.layout.boundsInWindow
@@ -39,9 +41,12 @@
     params: BurnInParameters,
     isClock: Boolean = false,
 ): Modifier {
-    val burnIn = viewModel.movement(params)
+    val translationYState = remember { mutableStateOf(0F) }
+    val copiedParams = params.copy(translationY = { translationYState.value })
+    val burnIn = viewModel.movement(copiedParams)
     val translationX by burnIn.map { it.translationX.toFloat() }.collectAsState(initial = 0f)
     val translationY by burnIn.map { it.translationY.toFloat() }.collectAsState(initial = 0f)
+    translationYState.value = translationY
     val scaleViewModel by
         burnIn
             .map {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
index 467dbca..97d5b41 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
@@ -32,7 +32,6 @@
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.SceneScope
 import com.android.systemui.animation.view.LaunchableImageView
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
 import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea
@@ -44,7 +43,6 @@
 import com.android.systemui.statusbar.KeyguardIndicationController
 import com.android.systemui.statusbar.VibratorHelper
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.flow.Flow
 
@@ -56,7 +54,6 @@
     private val vibratorHelper: VibratorHelper,
     private val indicationController: KeyguardIndicationController,
     private val indicationAreaViewModel: KeyguardIndicationAreaViewModel,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
 ) {
     /**
      * Renders a single lockscreen shortcut.
@@ -164,7 +161,6 @@
                         transitionAlpha,
                         falsingManager,
                         vibratorHelper,
-                        mainImmediateDispatcher,
                     ) {
                         indicationController.showTransientIndication(it)
                     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
index 51a7e8e..7095875 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
@@ -60,6 +60,8 @@
         modifier: Modifier = Modifier,
     ) {
         val currentClock by viewModel.currentClock.collectAsState()
+        val smallTopMargin by
+            viewModel.smallClockTopMargin.collectAsState(viewModel.getSmallClockTopMargin())
         if (currentClock?.smallClock?.view == null) {
             return
         }
@@ -74,7 +76,8 @@
             modifier =
                 modifier
                     .height(dimensionResource(R.dimen.small_clock_height))
-                    .padding(top = { viewModel.getSmallClockTopMargin(context) })
+                    .padding(horizontal = dimensionResource(R.dimen.clock_padding_start))
+                    .padding(top = { smallTopMargin })
                     .onTopPlacementChanged(onTopChanged)
                     .burnInAware(
                         viewModel = aodBurnInViewModel,
@@ -106,13 +109,8 @@
                     1f
                 }
 
-            val distance =
-                if (transition.toScene == splitShadeLargeClockScene) {
-                        -getClockCenteringDistance()
-                    } else {
-                        getClockCenteringDistance()
-                    }
-                    .toFloat()
+            val dir = if (transition.toScene == splitShadeLargeClockScene) -1f else 1f
+            val distance = dir * getClockCenteringDistance()
             val largeClock = checkNotNull(currentClock).largeClock
             largeClock.animations.onPositionUpdated(
                 distance = distance,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
index 48684a0..9f02201 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
@@ -34,7 +34,6 @@
 import com.android.keyguard.LockIconViewController
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
@@ -51,14 +50,12 @@
 import com.android.systemui.statusbar.VibratorHelper
 import dagger.Lazy
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 
 class LockSection
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
     private val windowManager: WindowManager,
     private val authController: AuthController,
     private val featureFlags: FeatureFlagsClassic,
@@ -96,7 +93,6 @@
                                 deviceEntryBackgroundViewModel.get(),
                                 falsingManager.get(),
                                 vibratorHelper.get(),
-                                mainImmediateDispatcher,
                             )
                         }
                     } else {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
index fa0a1c4..f48fa88 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
@@ -32,8 +32,11 @@
 import com.android.systemui.Flags
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
+import com.android.systemui.keyguard.ui.composable.modifier.burnInAware
+import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
+import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
 import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
-import com.android.systemui.notifications.ui.composable.NotificationStack
+import com.android.systemui.notifications.ui.composable.ConstrainedNotificationStack
 import com.android.systemui.res.R
 import com.android.systemui.shade.LargeScreenHeaderHelper
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
@@ -48,6 +51,7 @@
 @Inject
 constructor(
     private val viewModel: NotificationsPlaceholderViewModel,
+    private val aodBurnInViewModel: AodBurnInViewModel,
     sharedNotificationContainer: SharedNotificationContainer,
     sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
     stackScrollLayout: NotificationStackScrollLayout,
@@ -77,8 +81,12 @@
         )
     }
 
+    /**
+     * @param burnInParams params to make this view adaptive to burn-in, `null` to disable burn-in
+     *   adjustment
+     */
     @Composable
-    fun SceneScope.Notifications(modifier: Modifier = Modifier) {
+    fun SceneScope.Notifications(burnInParams: BurnInParameters?, modifier: Modifier = Modifier) {
         val shouldUseSplitNotificationShade by
             lockscreenContentViewModel.shouldUseSplitNotificationShade.collectAsState()
         val areNotificationsVisible by
@@ -94,12 +102,24 @@
             return
         }
 
-        NotificationStack(
+        ConstrainedNotificationStack(
             viewModel = viewModel,
             modifier =
-                modifier.fillMaxWidth().thenIf(shouldUseSplitNotificationShade) {
-                    Modifier.padding(top = splitShadeTopMargin)
-                },
+                modifier
+                    .fillMaxWidth()
+                    .thenIf(shouldUseSplitNotificationShade) {
+                        Modifier.padding(top = splitShadeTopMargin)
+                    }
+                    .let {
+                        if (burnInParams == null) {
+                            it
+                        } else {
+                            it.burnInAware(
+                                viewModel = aodBurnInViewModel,
+                                params = burnInParams,
+                            )
+                        }
+                    },
         )
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
index f8e6341..0934b20 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
@@ -16,9 +16,11 @@
 
 package com.android.systemui.keyguard.ui.composable.section
 
+import android.content.Context
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.runtime.Composable
@@ -26,6 +28,10 @@
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
 import com.android.compose.animation.scene.SceneScope
 import com.android.compose.animation.scene.SceneTransitionLayout
@@ -36,6 +42,7 @@
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeLargeClockScene
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeSmallClockScene
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockTransition
+import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockScenes
 import com.android.systemui.keyguard.ui.composable.blueprint.rememberBurnIn
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
 import javax.inject.Inject
@@ -47,6 +54,7 @@
     private val smartSpaceSection: SmartSpaceSection,
     private val mediaCarouselSection: MediaCarouselSection,
     private val clockSection: DefaultClockSection,
+    private val weatherClockSection: WeatherClockSection,
     private val clockInteractor: KeyguardClockInteractor,
 ) {
     @Composable
@@ -64,6 +72,10 @@
                     splitShadeSmallClockScene
                 KeyguardClockViewModel.ClockLayout.LARGE_CLOCK -> largeClockScene
                 KeyguardClockViewModel.ClockLayout.SMALL_CLOCK -> smallClockScene
+                KeyguardClockViewModel.ClockLayout.WEATHER_LARGE_CLOCK ->
+                    WeatherClockScenes.largeClockScene
+                KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_WEATHER_LARGE_CLOCK ->
+                    WeatherClockScenes.splitShadeLargeClockScene
             }
 
         SceneTransitionLayout(
@@ -86,6 +98,12 @@
             scene(smallClockScene) { SmallClockWithSmartSpace() }
 
             scene(largeClockScene) { LargeClockWithSmartSpace() }
+
+            scene(WeatherClockScenes.largeClockScene) { WeatherLargeClockWithSmartSpace() }
+
+            scene(WeatherClockScenes.splitShadeLargeClockScene) {
+                WeatherLargeClockWithSmartSpace(modifier = Modifier.fillMaxWidth(0.5f))
+            }
         }
     }
 
@@ -146,4 +164,50 @@
             }
         }
     }
+
+    @Composable
+    private fun SceneScope.WeatherLargeClockWithSmartSpace(modifier: Modifier = Modifier) {
+        val burnIn = rememberBurnIn(clockInteractor)
+        val isLargeClockVisible by clockViewModel.isLargeClockVisible.collectAsState()
+        val currentClockState = clockViewModel.currentClock.collectAsState()
+
+        LaunchedEffect(isLargeClockVisible) {
+            if (isLargeClockVisible) {
+                burnIn.onSmallClockTopChanged(null)
+            }
+        }
+
+        Column(modifier = modifier) {
+            val currentClock = currentClockState.value ?: return@Column
+            with(weatherClockSection) { Time(clock = currentClock, modifier = Modifier) }
+            val density = LocalDensity.current
+            val context = LocalContext.current
+
+            with(smartSpaceSection) {
+                SmartSpace(
+                    burnInParams = burnIn.parameters,
+                    onTopChanged = burnIn.onSmartspaceTopChanged,
+                    modifier =
+                        Modifier.heightIn(
+                            min = getDimen(context, "enhanced_smartspace_height", density)
+                        )
+                )
+            }
+            with(weatherClockSection) { LargeClockSectionBelowSmartspace(clock = currentClock) }
+        }
+    }
+
+    /*
+     * Use this function to access dimen which cannot be access by R.dimen directly
+     * Currently use to access dimen from BcSmartspace
+     * @param name Name of resources
+     * @param density Density required to convert dimen from Int To Dp
+     */
+    private fun getDimen(context: Context, name: String, density: Density): Dp {
+        val res = context.packageManager.getResourcesForApplication(context.packageName)
+        val id = res.getIdentifier(name, "dimen", context.packageName)
+        var dimen: Dp
+        with(density) { dimen = (if (id == 0) 0 else res.getDimensionPixelSize(id)).toDp() }
+        return dimen
+    }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
index d358453..a7bb308ad 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.ui.composable.section
 
+import android.view.View
 import android.view.ViewGroup
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.IntrinsicSize
@@ -27,18 +28,14 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.viewinterop.AndroidView
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.SceneScope
 import com.android.compose.modifiers.padding
-import com.android.systemui.customization.R
-import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.weatherSmallClockElementKey
+import com.android.systemui.customization.R as customizationR
 import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys
-import com.android.systemui.keyguard.ui.composable.modifier.burnInAware
 import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
-import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
 import com.android.systemui.plugins.clocks.ClockController
 import javax.inject.Inject
@@ -55,12 +52,19 @@
         clock: ClockController,
         modifier: Modifier = Modifier,
     ) {
-        WeatherElement(
-            weatherClockElementViewId = R.id.weather_clock_time,
-            clock = clock,
-            elementKey = WeatherClockElementKeys.timeElementKey,
-            modifier = modifier.wrapContentSize(),
-        )
+        Row(
+            modifier =
+                Modifier.padding(
+                    horizontal = dimensionResource(customizationR.dimen.clock_padding_start)
+                )
+        ) {
+            WeatherElement(
+                weatherClockElementViewId = customizationR.id.weather_clock_time,
+                clock = clock,
+                elementKey = WeatherClockElementKeys.timeElementKey,
+                modifier = modifier,
+            )
+        }
     }
 
     @Composable
@@ -69,7 +73,7 @@
         modifier: Modifier = Modifier,
     ) {
         WeatherElement(
-            weatherClockElementViewId = R.id.weather_clock_date,
+            weatherClockElementViewId = customizationR.id.weather_clock_date,
             clock = clock,
             elementKey = WeatherClockElementKeys.dateElementKey,
             modifier = modifier,
@@ -82,7 +86,7 @@
         modifier: Modifier = Modifier,
     ) {
         WeatherElement(
-            weatherClockElementViewId = R.id.weather_clock_weather_icon,
+            weatherClockElementViewId = customizationR.id.weather_clock_weather_icon,
             clock = clock,
             elementKey = WeatherClockElementKeys.weatherIconElementKey,
             modifier = modifier.wrapContentSize(),
@@ -95,7 +99,7 @@
         modifier: Modifier = Modifier,
     ) {
         WeatherElement(
-            weatherClockElementViewId = R.id.weather_clock_alarm_dnd,
+            weatherClockElementViewId = customizationR.id.weather_clock_alarm_dnd,
             clock = clock,
             elementKey = WeatherClockElementKeys.dndAlarmElementKey,
             modifier = modifier.wrapContentSize(),
@@ -108,7 +112,7 @@
         modifier: Modifier = Modifier,
     ) {
         WeatherElement(
-            weatherClockElementViewId = R.id.weather_clock_temperature,
+            weatherClockElementViewId = customizationR.id.weather_clock_temperature,
             clock = clock,
             elementKey = WeatherClockElementKeys.temperatureElementKey,
             modifier = modifier.wrapContentSize(),
@@ -126,12 +130,16 @@
             content {
                 AndroidView(
                     factory = {
-                        val view =
-                            clock.largeClock.layout.views.first {
-                                it.id == weatherClockElementViewId
-                            }
-                        (view.parent as? ViewGroup)?.removeView(view)
-                        view
+                        try {
+                            val view =
+                                clock.largeClock.layout.views.first {
+                                    it.id == weatherClockElementViewId
+                                }
+                            (view.parent as? ViewGroup)?.removeView(view)
+                            view
+                        } catch (e: NoSuchElementException) {
+                            View(it)
+                        }
                     },
                     update = {},
                     modifier = modifier
@@ -147,46 +155,22 @@
         Row(
             modifier =
                 Modifier.height(IntrinsicSize.Max)
-                    .padding(horizontal = dimensionResource(R.dimen.clock_padding_start))
+                    .padding(
+                        horizontal = dimensionResource(customizationR.dimen.clock_padding_start)
+                    )
         ) {
             Date(clock = clock, modifier = Modifier.wrapContentSize())
-            Box(modifier = Modifier.fillMaxSize()) {
+            Box(
+                modifier =
+                    Modifier.fillMaxSize()
+                        .padding(
+                            start = dimensionResource(customizationR.dimen.clock_padding_start)
+                        )
+            ) {
                 Weather(clock = clock, modifier = Modifier.align(Alignment.TopStart))
                 Temperature(clock = clock, modifier = Modifier.align(Alignment.BottomEnd))
                 DndAlarmStatus(clock = clock, modifier = Modifier.align(Alignment.TopEnd))
             }
         }
     }
-
-    @Composable
-    fun SceneScope.SmallClock(
-        burnInParams: BurnInParameters,
-        modifier: Modifier = Modifier,
-        clock: ClockController,
-    ) {
-        val localContext = LocalContext.current
-        MovableElement(key = weatherSmallClockElementKey, modifier) {
-            content {
-                AndroidView(
-                    factory = {
-                        val view = clock.smallClock.view
-                        if (view.parent != null) {
-                            (view.parent as? ViewGroup)?.removeView(view)
-                        }
-                        view
-                    },
-                    modifier =
-                        modifier
-                            .height(dimensionResource(R.dimen.small_clock_height))
-                            .padding(start = dimensionResource(R.dimen.clock_padding_start))
-                            .padding(top = { viewModel.getSmallClockTopMargin(localContext) })
-                            .burnInAware(
-                                viewModel = aodBurnInViewModel,
-                                params = burnInParams,
-                            ),
-                    update = {},
-                )
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
index d3e4553..f0d356c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt
@@ -53,6 +53,11 @@
                 val mediaFrame = carouselController.mediaFrame
                 (mediaFrame.parent as? ViewGroup)?.removeView(mediaFrame)
                 addView(mediaFrame)
+                layoutParams =
+                    FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                    )
             }
         },
         update = {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index cda4347..985d3a1 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -24,7 +24,6 @@
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.WindowInsets
 import androidx.compose.foundation.layout.asPaddingValues
-import androidx.compose.foundation.layout.displayCutout
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.offset
@@ -36,12 +35,14 @@
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.draw.drawBehind
@@ -55,33 +56,34 @@
 import androidx.compose.ui.layout.onPlaced
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.layout.positionInWindow
-import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.res.dimensionResource
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.lerp
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.NestedScrollBehavior
 import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.SceneTransitionLayoutState
 import com.android.compose.modifiers.height
+import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight
 import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius
-import com.android.systemui.notifications.ui.composable.Notifications.Form
-import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS
-import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.ui.composable.ShadeHeader
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import kotlin.math.roundToInt
 
 object Notifications {
     object Elements {
         val NotificationScrim = ElementKey("NotificationScrim")
-        val NotificationPlaceholder = ElementKey("NotificationPlaceholder")
+        val NotificationStackPlaceholder = ElementKey("NotificationStackPlaceholder")
+        val HeadsUpNotificationPlaceholder = ElementKey("HeadsUpNotificationPlaceholder")
         val ShelfSpace = ElementKey("ShelfSpace")
     }
 
@@ -91,12 +93,6 @@
         const val EXPANSION_FOR_MAX_CORNER_RADIUS = 0.1f
         const val EXPANSION_FOR_MAX_SCRIM_ALPHA = 0.3f
     }
-
-    enum class Form {
-        HunFromTop,
-        Stack,
-        HunFromBottom,
-    }
 }
 
 /**
@@ -109,24 +105,48 @@
     modifier: Modifier = Modifier,
     isPeekFromBottom: Boolean = false,
 ) {
-    NotificationPlaceholder(
-        viewModel = viewModel,
-        form = if (isPeekFromBottom) Form.HunFromBottom else Form.HunFromTop,
-        modifier = modifier,
-    )
+    val headsUpHeight = viewModel.headsUpHeight.collectAsState()
+
+    Element(
+        Notifications.Elements.HeadsUpNotificationPlaceholder,
+        modifier =
+            modifier
+                .height { headsUpHeight.value.roundToInt() }
+                .fillMaxWidth()
+                .debugBackground(viewModel, DEBUG_HUN_COLOR)
+                .onGloballyPositioned { coordinates: LayoutCoordinates ->
+                    val boundsInWindow = coordinates.boundsInWindow()
+                    debugLog(viewModel) {
+                        "HUNS onGloballyPositioned:" +
+                            " size=${coordinates.size}" +
+                            " bounds=$boundsInWindow"
+                    }
+                    viewModel.onHeadsUpTopChanged(boundsInWindow.top)
+                }
+    ) {
+        content {}
+    }
 }
 
 /** Adds the space where notification stack should appear in the scene. */
 @Composable
-fun SceneScope.NotificationStack(
+fun SceneScope.ConstrainedNotificationStack(
     viewModel: NotificationsPlaceholderViewModel,
     modifier: Modifier = Modifier,
 ) {
-    NotificationPlaceholder(
-        viewModel = viewModel,
-        form = Form.Stack,
-        modifier = modifier,
-    )
+    Box(
+        modifier =
+            modifier.onSizeChanged { viewModel.onConstrainedAvailableSpaceChanged(it.height) }
+    ) {
+        NotificationPlaceholder(
+            viewModel = viewModel,
+            modifier = Modifier.fillMaxSize(),
+        )
+        HeadsUpNotificationSpace(
+            viewModel = viewModel,
+            modifier = Modifier.align(Alignment.TopCenter),
+        )
+    }
 }
 
 /**
@@ -148,14 +168,7 @@
 
     val navBarHeight =
         with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() }
-    val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
-    val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding()
-    val screenHeight =
-        with(density) {
-            (LocalConfiguration.current.screenHeightDp.dp +
-                    maxOf(statusBarHeight, displayCutoutHeight))
-                .toPx()
-        } + navBarHeight
+    val screenHeight = LocalRawScreenHeight.current
 
     val stackHeight = viewModel.stackHeight.collectAsState()
 
@@ -169,6 +182,9 @@
     // entire height of the scrim is visible on screen.
     val scrimOffset = remember { mutableStateOf(0f) }
 
+    // set the bounds to null when the scrim disappears
+    DisposableEffect(Unit) { onDispose { viewModel.onScrimBoundsChanged(null) } }
+
     val minScrimTop = with(density) { ShadeHeader.Dimensions.CollapsedHeight.toPx() }
 
     // The minimum offset for the scrim. The scrim is considered fully expanded when it
@@ -230,11 +246,27 @@
                                 scrimCornerRadius,
                                 screenCornerRadius,
                                 { expansionFraction },
-                                layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade)
+                                layoutState.isNotificationScrimTransitioning(),
                             )
                             .let { scrimRounding.value.toRoundedCornerShape(it) }
                     clip = true
                 }
+                .onGloballyPositioned { coordinates ->
+                    val boundsInWindow = coordinates.boundsInWindow()
+                    debugLog(viewModel) {
+                        "SCRIM onGloballyPositioned:" +
+                            " size=${coordinates.size}" +
+                            " bounds=$boundsInWindow"
+                    }
+                    viewModel.onScrimBoundsChanged(
+                        ShadeScrimBounds(
+                            left = boundsInWindow.left,
+                            top = boundsInWindow.top,
+                            right = boundsInWindow.right,
+                            bottom = boundsInWindow.bottom,
+                        )
+                    )
+                }
     ) {
         // Creates a cutout in the background scrim in the shape of the notifications scrim.
         // Only visible when notif scrim alpha < 1, during shade expansion.
@@ -249,16 +281,15 @@
                 Modifier.fillMaxSize()
                     .graphicsLayer {
                         alpha =
-                            if (layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade)) {
+                            if (layoutState.isNotificationScrimTransitioning()) {
                                 (expansionFraction / EXPANSION_FOR_MAX_SCRIM_ALPHA).coerceAtMost(1f)
                             } else 1f
                     }
                     .background(MaterialTheme.colorScheme.surface)
-                    .debugBackground(viewModel, Color(0.5f, 0.5f, 0f, 0.2f))
+                    .debugBackground(viewModel, DEBUG_BOX_COLOR)
         ) {
             NotificationPlaceholder(
                 viewModel = viewModel,
-                form = Form.Stack,
                 modifier =
                     Modifier.verticalNestedScrollToScene(
                             topBehavior = NestedScrollBehavior.EdgeWithPreview,
@@ -284,6 +315,7 @@
                         .height { (stackHeight.value + navBarHeight).roundToInt() },
             )
         }
+        HeadsUpNotificationSpace(viewModel = viewModel)
     }
 }
 
@@ -304,14 +336,10 @@
         modifier
             .element(key = Notifications.Elements.ShelfSpace)
             .fillMaxWidth()
-            .onSizeChanged { size: IntSize ->
-                debugLog(viewModel) { "SHELF onSizeChanged: size=$size" }
-            }
             .onPlaced { coordinates: LayoutCoordinates ->
                 debugLog(viewModel) {
                     ("SHELF onPlaced:" +
                         " size=${coordinates.size}" +
-                        " position=${coordinates.positionInWindow()}" +
                         " bounds=${coordinates.boundsInWindow()}")
                 }
             }
@@ -326,32 +354,26 @@
 @Composable
 private fun SceneScope.NotificationPlaceholder(
     viewModel: NotificationsPlaceholderViewModel,
-    form: Form,
     modifier: Modifier = Modifier,
 ) {
-    val elementKey = Notifications.Elements.NotificationPlaceholder
     Element(
-        elementKey,
+        Notifications.Elements.NotificationStackPlaceholder,
         modifier =
             modifier
-                .debugBackground(viewModel)
-                .onSizeChanged { size: IntSize ->
-                    debugLog(viewModel) { "STACK onSizeChanged: size=$size" }
-                }
+                .debugBackground(viewModel, DEBUG_STACK_COLOR)
+                .onSizeChanged { size -> debugLog(viewModel) { "STACK onSizeChanged: size=$size" } }
                 .onGloballyPositioned { coordinates: LayoutCoordinates ->
-                    viewModel.onContentTopChanged(coordinates.positionInWindow().y)
+                    val positionInWindow = coordinates.positionInWindow()
                     debugLog(viewModel) {
                         "STACK onGloballyPositioned:" +
                             " size=${coordinates.size}" +
-                            " position=${coordinates.positionInWindow()}" +
+                            " position=$positionInWindow" +
                             " bounds=${coordinates.boundsInWindow()}"
                     }
-                    val boundsInWindow = coordinates.boundsInWindow()
-                    viewModel.onBoundsChanged(
-                        left = boundsInWindow.left,
-                        top = boundsInWindow.top,
-                        right = boundsInWindow.right,
-                        bottom = boundsInWindow.bottom,
+                    // NOTE: positionInWindow.y scrolls off screen, but boundsInWindow.top will not
+                    viewModel.onStackBoundsChanged(
+                        top = positionInWindow.y,
+                        bottom = positionInWindow.y + coordinates.size.height,
                     )
                 }
     ) {
@@ -388,7 +410,7 @@
 
 private fun Modifier.debugBackground(
     viewModel: NotificationsPlaceholderViewModel,
-    color: Color = DEBUG_COLOR,
+    color: Color,
 ): Modifier =
     if (viewModel.isVisualDebuggingEnabled) {
         background(color)
@@ -396,9 +418,9 @@
         this
     }
 
-fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape {
-    val topRadius = if (roundTop) radius else 0.dp
-    val bottomRadius = if (roundBottom) radius else 0.dp
+private fun ShadeScrimRounding.toRoundedCornerShape(radius: Dp): RoundedCornerShape {
+    val topRadius = if (isTopRounded) radius else 0.dp
+    val bottomRadius = if (isBottomRounded) radius else 0.dp
     return RoundedCornerShape(
         topStart = topRadius,
         topEnd = topRadius,
@@ -407,5 +429,14 @@
     )
 }
 
+private fun SceneTransitionLayoutState.isNotificationScrimTransitioning(): Boolean {
+    return isTransitioningBetween(Scenes.Gone, Scenes.Shade) ||
+        isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade) ||
+        isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings) ||
+        isTransitioningBetween(Scenes.Lockscreen, Scenes.QuickSettings)
+}
+
 private const val TAG = "FlexiNotifs"
-private val DEBUG_COLOR = Color(1f, 0f, 0f, 0.2f)
+private val DEBUG_STACK_COLOR = Color(1f, 0f, 0f, 0.2f)
+private val DEBUG_HUN_COLOR = Color(0f, 0f, 1f, 0.2f)
+private val DEBUG_BOX_COLOR = Color(0f, 1f, 0f, 0.2f)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/BrightnessMirror.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/BrightnessMirror.kt
new file mode 100644
index 0000000..ca6b343
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/BrightnessMirror.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.ui.composable
+
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.offset
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.viewinterop.AndroidView
+import com.android.compose.modifiers.height
+import com.android.compose.modifiers.width
+import com.android.systemui.qs.ui.adapter.QSSceneAdapter
+import com.android.systemui.settings.brightness.ui.binder.BrightnessMirrorInflater
+import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
+
+@Composable
+fun BrightnessMirror(
+    viewModel: BrightnessMirrorViewModel,
+    qsSceneAdapter: QSSceneAdapter,
+    modifier: Modifier = Modifier,
+) {
+    val isShowing by viewModel.isShowing.collectAsState()
+    val mirrorAlpha by
+        animateFloatAsState(
+            targetValue = if (isShowing) 1f else 0f,
+            label = "alphaAnimationBrightnessMirrorShowing",
+        )
+    val mirrorOffsetAndSize by viewModel.locationAndSize.collectAsState()
+    val offset = IntOffset(0, mirrorOffsetAndSize.yOffset)
+
+    Box(modifier = modifier.fillMaxSize().graphicsLayer { alpha = mirrorAlpha }) {
+        QuickSettingsTheme {
+            // The assumption for using this AndroidView is that there will be only one in view at
+            // a given time (which is a reasonable assumption). Because `QSSceneAdapter` (actually
+            // `BrightnessSliderController` only supports a single mirror).
+            // The benefit of doing it like this is that if the configuration changes or QSImpl is
+            // re-inflated, it's not relevant to the composable, as we'll always get a new one.
+            AndroidView(
+                modifier =
+                    Modifier.align(Alignment.TopCenter)
+                        .offset { offset }
+                        .width { mirrorOffsetAndSize.width }
+                        .height { mirrorOffsetAndSize.height },
+                factory = { context ->
+                    val (view, controller) =
+                        BrightnessMirrorInflater.inflate(context, viewModel.sliderControllerFactory)
+                    viewModel.setToggleSlider(controller)
+                    view
+                },
+                update = { qsSceneAdapter.setBrightnessMirrorController(viewModel) },
+                onRelease = { qsSceneAdapter.setBrightnessMirrorController(null) }
+            )
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 5b9213a..fc32440 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -17,7 +17,9 @@
 package com.android.systemui.qs.ui.composable
 
 import android.view.ViewGroup
+import androidx.activity.compose.BackHandler
 import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.animation.core.tween
 import androidx.compose.animation.expandVertically
 import androidx.compose.animation.fadeIn
@@ -36,6 +38,7 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.navigationBars
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.rememberScrollState
@@ -48,18 +51,23 @@
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.CompositingStrategy
+import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLifecycleOwner
 import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.dp
 import com.android.compose.animation.scene.SceneScope
 import com.android.compose.animation.scene.TransitionState
 import com.android.compose.animation.scene.animateSceneFloatAsState
 import com.android.compose.windowsizeclass.LocalWindowSizeClass
 import com.android.systemui.battery.BatteryMeterViewController
+import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight
 import com.android.systemui.compose.modifiers.sysuiResTag
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.notifications.ui.composable.NotificationScrollingStack
 import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
 import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel
 import com.android.systemui.res.R
@@ -69,10 +77,12 @@
 import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
 import com.android.systemui.shade.ui.composable.Shade
 import com.android.systemui.shade.ui.composable.ShadeHeader
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import com.android.systemui.statusbar.phone.StatusBarIconController
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import javax.inject.Inject
+import kotlin.math.roundToInt
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.stateIn
@@ -84,6 +94,7 @@
 constructor(
     @Application private val applicationScope: CoroutineScope,
     private val viewModel: QuickSettingsSceneViewModel,
+    private val notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel,
     private val tintedIconManagerFactory: TintedIconManager.Factory,
     private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
     private val statusBarIconController: StatusBarIconController,
@@ -103,6 +114,7 @@
     ) {
         QuickSettingsScene(
             viewModel = viewModel,
+            notificationsPlaceholderViewModel = notificationsPlaceholderViewModel,
             createTintedIconManager = tintedIconManagerFactory::create,
             createBatteryMeterViewController = batteryMeterViewControllerFactory::create,
             statusBarIconController = statusBarIconController,
@@ -114,14 +126,43 @@
 @Composable
 private fun SceneScope.QuickSettingsScene(
     viewModel: QuickSettingsSceneViewModel,
+    notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel,
     createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager,
     createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController,
     statusBarIconController: StatusBarIconController,
     modifier: Modifier = Modifier,
 ) {
+    val brightnessMirrorShowing by viewModel.brightnessMirrorViewModel.isShowing.collectAsState()
+    val contentAlpha by
+        animateFloatAsState(
+            targetValue = if (brightnessMirrorShowing) 0f else 1f,
+            label = "alphaAnimationBrightnessMirrorContentHiding",
+        )
+
+    BrightnessMirror(
+        viewModel = viewModel.brightnessMirrorViewModel,
+        qsSceneAdapter = viewModel.qsSceneAdapter
+    )
+
     // TODO(b/280887232): implement the real UI.
-    Box(modifier = modifier.fillMaxSize()) {
+    Box(
+        modifier =
+            modifier.fillMaxSize().graphicsLayer {
+                // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this
+                // scene (and not the one under it) during a scene transition.
+                compositingStrategy = CompositingStrategy.Offscreen
+                alpha = contentAlpha
+            }
+    ) {
         val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState()
+        val screenHeight = LocalRawScreenHeight.current
+
+        BackHandler(
+            enabled = isCustomizing,
+        ) {
+            viewModel.qsSceneAdapter.requestCloseCustomizer()
+        }
+
         val collapsedHeaderHeight =
             with(LocalDensity.current) { ShadeHeader.Dimensions.CollapsedHeight.roundToPx() }
         val lifecycleOwner = LocalLifecycleOwner.current
@@ -251,5 +292,11 @@
                 modifier = Modifier.align(Alignment.CenterHorizontally),
             )
         }
+        NotificationScrollingStack(
+            viewModel = notificationsPlaceholderViewModel,
+            maxScrimTop = { screenHeight },
+            modifier =
+                Modifier.fillMaxWidth().offset { IntOffset(x = 0, y = screenHeight.roundToInt()) },
+        )
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index fe6701c..7af9b7b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -37,8 +37,6 @@
 import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneTransitionLayout
-import com.android.compose.animation.scene.UserAction
-import com.android.compose.animation.scene.UserActionResult
 import com.android.compose.animation.scene.observableTransitionState
 import com.android.systemui.ribbon.ui.composable.BottomRightCornerRibbon
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
@@ -71,9 +69,7 @@
 ) {
     val coroutineScope = rememberCoroutineScope()
     val currentSceneKey: SceneKey by viewModel.currentScene.collectAsState()
-    val currentScene = checkNotNull(sceneByKey[currentSceneKey])
-    val currentDestinations: Map<UserAction, UserActionResult> by
-        currentScene.destinationScenes.collectAsState()
+    val currentDestinations by viewModel.currentDestinationScenes(coroutineScope).collectAsState()
     val state: MutableSceneTransitionLayoutState = remember {
         MutableSceneTransitionLayoutState(
             initialScene = currentSceneKey,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt
index 5bd1583..851719d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt
@@ -1,12 +1,14 @@
 package com.android.systemui.scene.ui.composable.transitions
 
 import androidx.compose.animation.core.tween
-import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.TransitionBuilder
-import com.android.systemui.scene.shared.model.Scenes
+import kotlin.time.Duration.Companion.milliseconds
 
-fun TransitionBuilder.goneToQuickSettingsTransition() {
-    spec = tween(durationMillis = 500)
-
-    translate(Scenes.QuickSettings.rootElementKey, Edge.Top, true)
+fun TransitionBuilder.goneToQuickSettingsTransition(
+    durationScale: Double = 1.0,
+) {
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+    toQuickSettingsTransition()
 }
+
+private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt
index 9b59708..a0f410a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt
@@ -1,31 +1,14 @@
 package com.android.systemui.scene.ui.composable.transitions
 
 import androidx.compose.animation.core.tween
-import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.TransitionBuilder
-import com.android.systemui.notifications.ui.composable.Notifications
-import com.android.systemui.qs.ui.composable.QuickSettings
-import com.android.systemui.shade.ui.composable.ShadeHeader
 import kotlin.time.Duration.Companion.milliseconds
 
 fun TransitionBuilder.goneToShadeTransition(
     durationScale: Double = 1.0,
 ) {
-    spec = tween(durationMillis = DefaultDuration.times(durationScale).inWholeMilliseconds.toInt())
-
-    fractionRange(start = .58f) {
-        fade(ShadeHeader.Elements.Clock)
-        fade(ShadeHeader.Elements.CollapsedContentStart)
-        fade(ShadeHeader.Elements.CollapsedContentEnd)
-        fade(ShadeHeader.Elements.PrivacyChip)
-        fade(QuickSettings.Elements.SplitShadeQuickSettings)
-        fade(QuickSettings.Elements.FooterActions)
-    }
-    translate(
-        QuickSettings.Elements.QuickQuickSettings,
-        y = -ShadeHeader.Dimensions.CollapsedHeight * .66f
-    )
-    translate(Notifications.Elements.NotificationScrim, Edge.Top, false)
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+    toShadeTransition()
 }
 
 private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt
index 962d822..319438c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt
@@ -1,12 +1,14 @@
 package com.android.systemui.scene.ui.composable.transitions
 
 import androidx.compose.animation.core.tween
-import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.TransitionBuilder
-import com.android.systemui.scene.shared.model.Scenes
+import kotlin.time.Duration.Companion.milliseconds
 
-fun TransitionBuilder.lockscreenToQuickSettingsTransition() {
-    spec = tween(durationMillis = 500)
-
-    translate(Scenes.QuickSettings.rootElementKey, Edge.Top, true)
+fun TransitionBuilder.lockscreenToQuickSettingsTransition(
+    durationScale: Double = 1.0,
+) {
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+    toQuickSettingsTransition()
 }
+
+private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
index 48ab68a..f078b8c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
@@ -2,23 +2,13 @@
 
 import androidx.compose.animation.core.tween
 import com.android.compose.animation.scene.TransitionBuilder
-import com.android.systemui.notifications.ui.composable.Notifications
-import com.android.systemui.qs.ui.composable.QuickSettings
-import com.android.systemui.shade.ui.composable.Shade
-import com.android.systemui.shade.ui.composable.ShadeHeader
 import kotlin.time.Duration.Companion.milliseconds
 
 fun TransitionBuilder.lockscreenToShadeTransition(
     durationScale: Double = 1.0,
 ) {
-    spec = tween(durationMillis = DefaultDuration.times(durationScale).inWholeMilliseconds.toInt())
-
-    fractionRange(end = 0.5f) { fade(Shade.Elements.BackgroundScrim) }
-    translate(QuickSettings.Elements.Content, y = -ShadeHeader.Dimensions.CollapsedHeight * .66f)
-    fractionRange(start = 0.5f) {
-        fade(QuickSettings.Elements.Content)
-        fade(Notifications.Elements.NotificationScrim)
-    }
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+    toShadeTransition()
 }
 
 private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
index ffb6f31..a9e5be9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
@@ -6,9 +6,12 @@
 import com.android.systemui.notifications.ui.composable.Notifications
 import com.android.systemui.qs.ui.composable.QuickSettings
 import com.android.systemui.shade.ui.composable.ShadeHeader
+import kotlin.time.Duration.Companion.milliseconds
 
-fun TransitionBuilder.shadeToQuickSettingsTransition() {
-    spec = tween(durationMillis = 500)
+fun TransitionBuilder.shadeToQuickSettingsTransition(
+    durationScale: Double = 1.0,
+) {
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
 
     translate(Notifications.Elements.NotificationScrim, Edge.Bottom)
     timestampRange(endMillis = 83) { fade(QuickSettings.Elements.FooterActions) }
@@ -24,9 +27,15 @@
     )
     translate(ShadeHeader.Elements.ShadeCarrierGroup, y = -ShadeHeader.Dimensions.CollapsedHeight)
 
-    fractionRange(end = .14f) { fade(ShadeHeader.Elements.CollapsedContentStart) }
-    fractionRange(end = .14f) { fade(ShadeHeader.Elements.CollapsedContentEnd) }
+    fractionRange(end = .14f) {
+        fade(ShadeHeader.Elements.CollapsedContentStart)
+        fade(ShadeHeader.Elements.CollapsedContentEnd)
+    }
 
-    fractionRange(start = .58f) { fade(ShadeHeader.Elements.ExpandedContent) }
-    fractionRange(start = .58f) { fade(ShadeHeader.Elements.ShadeCarrierGroup) }
+    fractionRange(start = .58f) {
+        fade(ShadeHeader.Elements.ExpandedContent)
+        fade(ShadeHeader.Elements.ShadeCarrierGroup)
+    }
 }
+
+private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsTransition.kt
new file mode 100644
index 0000000..e0a6310
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsTransition.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.ui.composable.transitions
+
+import androidx.compose.animation.core.tween
+import com.android.compose.animation.scene.Edge
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.systemui.notifications.ui.composable.Notifications
+import com.android.systemui.qs.ui.composable.QuickSettings
+import com.android.systemui.shade.ui.composable.ShadeHeader
+import kotlin.time.Duration.Companion.milliseconds
+
+fun TransitionBuilder.toQuickSettingsTransition(
+    durationScale: Double = 1.0,
+) {
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+
+    translate(
+        ShadeHeader.Elements.ExpandedContent,
+        y = -(ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight)
+    )
+    translate(ShadeHeader.Elements.Clock, y = -ShadeHeader.Dimensions.CollapsedHeight)
+    translate(ShadeHeader.Elements.ShadeCarrierGroup, y = -ShadeHeader.Dimensions.CollapsedHeight)
+
+    fractionRange(start = .58f) {
+        fade(ShadeHeader.Elements.ExpandedContent)
+        fade(ShadeHeader.Elements.Clock)
+        fade(ShadeHeader.Elements.ShadeCarrierGroup)
+    }
+
+    translate(QuickSettings.Elements.Content, y = -ShadeHeader.Dimensions.ExpandedHeight * .66f)
+    translate(Notifications.Elements.NotificationScrim, Edge.Top, false)
+}
+
+private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
new file mode 100644
index 0000000..2f59217
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.ui.composable.transitions
+
+import androidx.compose.animation.core.tween
+import com.android.compose.animation.scene.Edge
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.systemui.notifications.ui.composable.Notifications
+import com.android.systemui.qs.ui.composable.QuickSettings
+import com.android.systemui.shade.ui.composable.ShadeHeader
+import kotlin.time.Duration.Companion.milliseconds
+
+fun TransitionBuilder.toShadeTransition(
+    durationScale: Double = 1.0,
+) {
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+
+    fractionRange(start = .58f) {
+        fade(ShadeHeader.Elements.Clock)
+        fade(ShadeHeader.Elements.CollapsedContentStart)
+        fade(ShadeHeader.Elements.CollapsedContentEnd)
+        fade(ShadeHeader.Elements.PrivacyChip)
+        fade(QuickSettings.Elements.SplitShadeQuickSettings)
+        fade(QuickSettings.Elements.FooterActions)
+    }
+    translate(
+        QuickSettings.Elements.QuickQuickSettings,
+        y = -ShadeHeader.Dimensions.CollapsedHeight * .66f
+    )
+    translate(Notifications.Elements.NotificationScrim, Edge.Top, false)
+}
+
+private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index fcd7760..516e140 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -54,9 +54,9 @@
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.LowestZIndexScenePicker
 import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.TransitionState
 import com.android.compose.animation.scene.ValueKey
 import com.android.compose.animation.scene.animateElementFloatAsState
-import com.android.compose.animation.scene.animateSceneFloatAsState
 import com.android.compose.windowsizeclass.LocalWindowSizeClass
 import com.android.settingslib.Utils
 import com.android.systemui.battery.BatteryMeterView
@@ -87,10 +87,6 @@
         val ShadeCarrierGroup = ElementKey("ShadeCarrierGroup")
     }
 
-    object Keys {
-        val transitionProgress = ValueKey("ShadeHeaderTransitionProgress")
-    }
-
     object Values {
         val ClockScale = ValueKey("ShadeHeaderClockScale")
     }
@@ -119,19 +115,17 @@
         return
     }
 
-    val formatProgress =
-        animateSceneFloatAsState(0f, ShadeHeader.Keys.transitionProgress)
-            .unsafeCompositionState(initialValue = 0f)
-
     val cutoutWidth = LocalDisplayCutout.current.width()
     val cutoutLocation = LocalDisplayCutout.current.location
 
     val useExpandedFormat by
-        remember(formatProgress) {
+        remember(cutoutLocation) {
             derivedStateOf {
-                cutoutLocation != CutoutLocation.CENTER || formatProgress.value > 0.5f
+                cutoutLocation != CutoutLocation.CENTER ||
+                    shouldUseExpandedFormat(layoutState.transitionState)
             }
         }
+
     val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsState()
 
     // This layout assumes it is globally positioned at (0, 0) and is the
@@ -207,7 +201,7 @@
 
         val screenWidth = constraints.maxWidth
         val cutoutWidthPx = cutoutWidth.roundToPx()
-        val height = ShadeHeader.Dimensions.CollapsedHeight.roundToPx()
+        val height = CollapsedHeight.roundToPx()
         val childConstraints = Constraints.fixed((screenWidth - cutoutWidthPx) / 2, height)
 
         val startMeasurable = measurables[0][0]
@@ -261,11 +255,10 @@
         return
     }
 
-    val formatProgress =
-        animateSceneFloatAsState(1f, ShadeHeader.Keys.transitionProgress)
-            .unsafeCompositionState(initialValue = 1f)
-    val useExpandedFormat by
-        remember(formatProgress) { derivedStateOf { formatProgress.value > 0.5f } }
+    val useExpandedFormat by remember {
+        derivedStateOf { shouldUseExpandedFormat(layoutState.transitionState) }
+    }
+
     val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsState()
 
     Box(modifier = modifier) {
@@ -414,15 +407,16 @@
             AndroidView(
                 factory = { context ->
                     ModernShadeCarrierGroupMobileView.constructAndBind(
-                        context = context,
-                        logger = viewModel.mobileIconsViewModel.logger,
-                        slot = "mobile_carrier_shade_group",
-                        viewModel =
-                            (viewModel.mobileIconsViewModel.viewModelForSub(
-                                subId,
-                                StatusBarLocation.SHADE_CARRIER_GROUP
-                            ) as ShadeCarrierGroupMobileIconViewModel),
-                    )
+                            context = context,
+                            logger = viewModel.mobileIconsViewModel.logger,
+                            slot = "mobile_carrier_shade_group",
+                            viewModel =
+                                (viewModel.mobileIconsViewModel.viewModelForSub(
+                                    subId,
+                                    StatusBarLocation.SHADE_CARRIER_GROUP
+                                ) as ShadeCarrierGroupMobileIconViewModel),
+                        )
+                        .also { it.setOnClickListener { viewModel.onShadeCarrierGroupClicked() } }
                 },
             )
         }
@@ -530,3 +524,21 @@
         modifier = modifier.element(ShadeHeader.Elements.PrivacyChip),
     )
 }
+
+private fun shouldUseExpandedFormat(state: TransitionState): Boolean {
+    return when (state) {
+        is TransitionState.Idle -> {
+            state.currentScene == Scenes.QuickSettings
+        }
+        is TransitionState.Transition -> {
+            ((state.isTransitioning(Scenes.Shade, Scenes.QuickSettings) ||
+                state.isTransitioning(Scenes.Gone, Scenes.QuickSettings) ||
+                state.isTransitioning(Scenes.Lockscreen, Scenes.QuickSettings)) &&
+                state.progress >= 0.5) ||
+                ((state.isTransitioning(Scenes.QuickSettings, Scenes.Shade) ||
+                    state.isTransitioning(Scenes.QuickSettings, Scenes.Gone) ||
+                    state.isTransitioning(Scenes.QuickSettings, Scenes.Lockscreen)) &&
+                    state.progress <= 0.5)
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 85798ac..944d6ef 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.shade.ui.composable
 
 import android.view.ViewGroup
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.clipScrollableContainer
@@ -33,6 +34,7 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.navigationBars
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.shape.RoundedCornerShape
@@ -45,6 +47,8 @@
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.CompositingStrategy
+import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.platform.LocalDensity
@@ -59,6 +63,7 @@
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.compose.animation.scene.animateSceneFloatAsState
+import com.android.compose.modifiers.padding
 import com.android.compose.modifiers.thenIf
 import com.android.systemui.battery.BatteryMeterViewController
 import com.android.systemui.dagger.SysUISingleton
@@ -70,6 +75,7 @@
 import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL
 import com.android.systemui.notifications.ui.composable.NotificationScrollingStack
 import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
+import com.android.systemui.qs.ui.composable.BrightnessMirror
 import com.android.systemui.qs.ui.composable.QuickSettings
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.model.Scenes
@@ -195,13 +201,15 @@
         animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness)
     val isClickable by viewModel.isClickable.collectAsState()
 
-    Box(
-        modifier =
-            modifier
-                .element(Shade.Elements.BackgroundScrim)
-                .background(colorResource(R.color.shade_scrim_background_dark)),
-    )
-    Box {
+    // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this scene
+    // (and not the one under it) during a scene transition.
+    Box(modifier = modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)) {
+        Box(
+            modifier =
+                Modifier.fillMaxSize()
+                    .element(Shade.Elements.BackgroundScrim)
+                    .background(colorResource(R.color.shade_scrim_background_dark)),
+        )
         Layout(
             contents =
                 listOf(
@@ -285,6 +293,18 @@
         remember(lifecycleOwner, viewModel) { viewModel.getFooterActionsViewModel(lifecycleOwner) }
     val tileSquishiness by
         animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness)
+    val unfoldTranslationXForStartSide by
+        viewModel
+            .unfoldTranslationX(
+                isOnStartSide = true,
+            )
+            .collectAsState(0f)
+    val unfoldTranslationXForEndSide by
+        viewModel
+            .unfoldTranslationX(
+                isOnStartSide = false,
+            )
+            .collectAsState(0f)
 
     val navBarBottomHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
     val density = LocalDensity.current
@@ -302,12 +322,25 @@
         }
     }
 
+    val brightnessMirrorShowing by viewModel.brightnessMirrorViewModel.isShowing.collectAsState()
+    val contentAlpha by
+        animateFloatAsState(
+            targetValue = if (brightnessMirrorShowing) 0f else 1f,
+            label = "alphaAnimationBrightnessMirrorContentHiding",
+        )
+
+    val brightnessMirrorShowingModifier = Modifier.graphicsLayer { alpha = contentAlpha }
+
     Box(
         modifier =
             modifier
                 .fillMaxSize()
                 .element(Shade.Elements.BackgroundScrim)
-                .background(colorResource(R.color.shade_scrim_background_dark))
+                // Cannot set the alpha of the whole element to 0, because the mirror should be
+                // in the QS column.
+                .background(
+                    colorResource(R.color.shade_scrim_background_dark).copy(alpha = contentAlpha)
+                )
     ) {
         Column(
             modifier = Modifier.fillMaxSize(),
@@ -317,61 +350,88 @@
                 createTintedIconManager = createTintedIconManager,
                 createBatteryMeterViewController = createBatteryMeterViewController,
                 statusBarIconController = statusBarIconController,
-                modifier = Modifier.padding(horizontal = Shade.Dimensions.HorizontalPadding)
+                modifier =
+                    Modifier.padding(horizontal = Shade.Dimensions.HorizontalPadding)
+                        .then(brightnessMirrorShowingModifier)
+                        .padding(
+                            horizontal = { unfoldTranslationXForStartSide.roundToInt() },
+                        )
             )
 
             Row(modifier = Modifier.fillMaxWidth().weight(1f)) {
-                Column(
-                    verticalArrangement = Arrangement.Top,
+                Box(
                     modifier =
-                        Modifier.weight(1f).fillMaxSize().thenIf(!isCustomizing) {
-                            Modifier.padding(bottom = navBarBottomHeight)
+                        Modifier.weight(1f).graphicsLayer {
+                            translationX = unfoldTranslationXForStartSide
                         },
                 ) {
+                    BrightnessMirror(
+                        viewModel = viewModel.brightnessMirrorViewModel,
+                        qsSceneAdapter = viewModel.qsSceneAdapter,
+                        // Need to remove the offset of the header height, as the mirror uses
+                        // the position of the Brightness slider in the window
+                        modifier = Modifier.offset(y = -ShadeHeader.Dimensions.CollapsedHeight)
+                    )
                     Column(
+                        verticalArrangement = Arrangement.Top,
                         modifier =
-                            Modifier.fillMaxSize().weight(1f).thenIf(!isCustomizing) {
-                                Modifier.verticalNestedScrollToScene()
-                                    .verticalScroll(
-                                        quickSettingsScrollState,
-                                        enabled = isScrollable
-                                    )
-                                    .clipScrollableContainer(Orientation.Horizontal)
-                            }
+                            Modifier.fillMaxSize().thenIf(!isCustomizing) {
+                                Modifier.padding(bottom = navBarBottomHeight)
+                            },
                     ) {
-                        Box(
+                        Column(
                             modifier =
-                                Modifier.element(QuickSettings.Elements.SplitShadeQuickSettings)
+                                Modifier.fillMaxSize()
+                                    .weight(1f)
+                                    .thenIf(!isCustomizing) {
+                                        Modifier.verticalNestedScrollToScene()
+                                            .verticalScroll(
+                                                quickSettingsScrollState,
+                                                enabled = isScrollable
+                                            )
+                                            .clipScrollableContainer(Orientation.Horizontal)
+                                    }
+                                    .then(brightnessMirrorShowingModifier)
                         ) {
-                            QuickSettings(
-                                qsSceneAdapter = viewModel.qsSceneAdapter,
-                                heightProvider = { viewModel.qsSceneAdapter.qsHeight },
-                                isSplitShade = true,
+                            Box(
+                                modifier =
+                                    Modifier.element(QuickSettings.Elements.SplitShadeQuickSettings)
+                            ) {
+                                QuickSettings(
+                                    qsSceneAdapter = viewModel.qsSceneAdapter,
+                                    heightProvider = { viewModel.qsSceneAdapter.qsHeight },
+                                    isSplitShade = true,
+                                    modifier = Modifier.fillMaxWidth(),
+                                    squishiness = tileSquishiness,
+                                )
+                            }
+
+                            MediaIfVisible(
+                                viewModel = viewModel,
+                                mediaCarouselController = mediaCarouselController,
+                                mediaHost = mediaHost,
                                 modifier = Modifier.fillMaxWidth(),
-                                squishiness = tileSquishiness,
                             )
                         }
-
-                        MediaIfVisible(
-                            viewModel = viewModel,
-                            mediaCarouselController = mediaCarouselController,
-                            mediaHost = mediaHost,
-                            modifier = Modifier.fillMaxWidth(),
+                        FooterActionsWithAnimatedVisibility(
+                            viewModel = footerActionsViewModel,
+                            isCustomizing = isCustomizing,
+                            lifecycleOwner = lifecycleOwner,
+                            modifier =
+                                Modifier.align(Alignment.CenterHorizontally)
+                                    .then(brightnessMirrorShowingModifier),
                         )
                     }
-                    FooterActionsWithAnimatedVisibility(
-                        viewModel = footerActionsViewModel,
-                        isCustomizing = isCustomizing,
-                        lifecycleOwner = lifecycleOwner,
-                        modifier = Modifier.align(Alignment.CenterHorizontally),
-                    )
                 }
 
                 NotificationScrollingStack(
                     viewModel = viewModel.notifications,
                     maxScrimTop = { 0f },
                     modifier =
-                        Modifier.weight(1f).fillMaxHeight().padding(bottom = navBarBottomHeight),
+                        Modifier.weight(1f)
+                            .fillMaxHeight()
+                            .padding(bottom = navBarBottomHeight)
+                            .then(brightnessMirrorShowingModifier)
                 )
             }
         }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt
index ccb5d36..fa052e8 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/AncModule.kt
@@ -17,15 +17,12 @@
 package com.android.systemui.volume.panel.component.anc
 
 import com.android.systemui.volume.panel.component.anc.domain.AncAvailabilityCriteria
-import com.android.systemui.volume.panel.component.anc.ui.composable.AncPopup
-import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel
-import com.android.systemui.volume.panel.component.button.ui.composable.ButtonComponent
+import com.android.systemui.volume.panel.component.anc.ui.composable.AncButtonComponent
 import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents
 import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
 import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent
 import dagger.Binds
 import dagger.Module
-import dagger.Provides
 import dagger.multibindings.IntoMap
 import dagger.multibindings.StringKey
 
@@ -40,14 +37,8 @@
         criteria: AncAvailabilityCriteria
     ): ComponentAvailabilityCriteria
 
-    companion object {
-
-        @Provides
-        @IntoMap
-        @StringKey(VolumePanelComponents.ANC)
-        fun provideVolumePanelUiComponent(
-            viewModel: AncViewModel,
-            popup: AncPopup,
-        ): VolumePanelUiComponent = ButtonComponent(viewModel.button, popup::show)
-    }
+    @Binds
+    @IntoMap
+    @StringKey(VolumePanelComponents.ANC)
+    fun bindVolumePanelUiComponent(component: AncButtonComponent): VolumePanelUiComponent
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt
new file mode 100644
index 0000000..00225fc
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncButtonComponent.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.anc.ui.composable
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.clearAndSetSemantics
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import com.android.systemui.res.R
+import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel
+import com.android.systemui.volume.panel.ui.composable.ComposeVolumePanelUiComponent
+import com.android.systemui.volume.panel.ui.composable.VolumePanelComposeScope
+import javax.inject.Inject
+
+class AncButtonComponent
+@Inject
+constructor(
+    private val viewModel: AncViewModel,
+    private val ancPopup: AncPopup,
+) : ComposeVolumePanelUiComponent {
+
+    @Composable
+    override fun VolumePanelComposeScope.Content(modifier: Modifier) {
+        val slice by viewModel.buttonSlice.collectAsState()
+        val label = stringResource(R.string.volume_panel_noise_control_title)
+        Column(
+            modifier = modifier,
+            verticalArrangement = Arrangement.spacedBy(12.dp),
+            horizontalAlignment = Alignment.CenterHorizontally,
+        ) {
+            SliceAndroidView(
+                modifier =
+                    Modifier.height(64.dp)
+                        .fillMaxWidth()
+                        .semantics {
+                            role = Role.Button
+                            contentDescription = label
+                        }
+                        .clip(RoundedCornerShape(28.dp)),
+                slice = slice,
+                onWidthChanged = viewModel::onButtonSliceWidthChanged,
+                onClick = { ancPopup.show(null) }
+            )
+            Text(
+                modifier = Modifier.clearAndSetSemantics {},
+                text = label,
+                style = MaterialTheme.typography.labelMedium,
+                maxLines = 1,
+                overflow = TextOverflow.Ellipsis,
+            )
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt
index b1fbe35..e1ee01e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/AncPopup.kt
@@ -16,9 +16,7 @@
 
 package com.android.systemui.volume.panel.component.anc.ui.composable
 
-import android.content.Context
-import android.view.ContextThemeWrapper
-import android.view.View
+import androidx.compose.foundation.basicMarquee
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
@@ -29,14 +27,14 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.viewinterop.AndroidView
 import androidx.slice.Slice
-import androidx.slice.widget.SliceView
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.animation.Expandable
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.volume.panel.component.anc.ui.viewmodel.AncViewModel
 import com.android.systemui.volume.panel.component.popup.ui.composable.VolumePanelPopup
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
 
 /** ANC popup up displaying ANC control [Slice]. */
@@ -45,16 +43,19 @@
 constructor(
     private val volumePanelPopup: VolumePanelPopup,
     private val viewModel: AncViewModel,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
     /** Shows a popup with the [expandable] animation. */
-    fun show(expandable: Expandable) {
+    fun show(expandable: Expandable?) {
+        uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_ANC_POPUP_SHOWN)
         volumePanelPopup.show(expandable, { Title() }, { Content(it) })
     }
 
     @Composable
     private fun Title() {
         Text(
+            modifier = Modifier.basicMarquee(),
             text = stringResource(R.string.volume_panel_noise_control_title),
             style = MaterialTheme.typography.titleMedium,
             textAlign = TextAlign.Center,
@@ -64,49 +65,18 @@
 
     @Composable
     private fun Content(dialog: SystemUIDialog) {
-        val slice: Slice? by viewModel.slice.collectAsState()
+        val isAvailable by viewModel.isAvailable.collectAsState(true)
 
-        if (slice == null) {
+        if (!isAvailable) {
             SideEffect { dialog.dismiss() }
             return
         }
 
-        AndroidView<SliceView>(
+        val slice by viewModel.popupSlice.collectAsState()
+        SliceAndroidView(
             modifier = Modifier.fillMaxWidth(),
-            factory = { context: Context ->
-                SliceView(ContextThemeWrapper(context, R.style.Widget_SliceView_VolumePanel))
-                    .apply {
-                        mode = SliceView.MODE_LARGE
-                        isScrollable = false
-                        importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
-                        setShowTitleItems(true)
-                        addOnLayoutChangeListener(
-                            OnWidthChangedLayoutListener(viewModel::changeSliceWidth)
-                        )
-                    }
-            },
-            update = { sliceView: SliceView -> sliceView.slice = slice }
+            slice = slice,
+            onWidthChanged = viewModel::onPopupSliceWidthChanged
         )
     }
-
-    private class OnWidthChangedLayoutListener(private val widthChanged: (Int) -> Unit) :
-        View.OnLayoutChangeListener {
-        override fun onLayoutChange(
-            v: View?,
-            left: Int,
-            top: Int,
-            right: Int,
-            bottom: Int,
-            oldLeft: Int,
-            oldTop: Int,
-            oldRight: Int,
-            oldBottom: Int
-        ) {
-            val newWidth = right - left
-            val oldWidth = oldRight - oldLeft
-            if (oldWidth != newWidth) {
-                widthChanged(newWidth)
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
new file mode 100644
index 0000000..f354b80
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/anc/ui/composable/SliceAndroidView.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.anc.ui.composable
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.ContextThemeWrapper
+import android.view.MotionEvent
+import android.view.View
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.slice.Slice
+import androidx.slice.widget.SliceView
+import com.android.systemui.res.R
+
+@Composable
+fun SliceAndroidView(
+    slice: Slice?,
+    modifier: Modifier = Modifier,
+    onWidthChanged: ((Int) -> Unit)? = null,
+    onClick: (() -> Unit)? = null,
+) {
+    AndroidView(
+        modifier = modifier,
+        factory = { context: Context ->
+            ClickableSliceView(
+                    ContextThemeWrapper(context, R.style.Widget_SliceView_VolumePanel),
+                    onClick,
+                )
+                .apply {
+                    mode = SliceView.MODE_LARGE
+                    isScrollable = false
+                    importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
+                    setShowTitleItems(true)
+                    if (onWidthChanged != null) {
+                        addOnLayoutChangeListener(OnWidthChangedLayoutListener(onWidthChanged))
+                    }
+                    if (onClick != null) {
+                        setOnClickListener { onClick() }
+                    }
+                }
+        },
+        update = { sliceView: SliceView -> sliceView.slice = slice }
+    )
+}
+
+class OnWidthChangedLayoutListener(private val widthChanged: (Int) -> Unit) :
+    View.OnLayoutChangeListener {
+
+    override fun onLayoutChange(
+        v: View?,
+        left: Int,
+        top: Int,
+        right: Int,
+        bottom: Int,
+        oldLeft: Int,
+        oldTop: Int,
+        oldRight: Int,
+        oldBottom: Int
+    ) {
+        val newWidth = right - left
+        val oldWidth = oldRight - oldLeft
+        if (oldWidth != newWidth) {
+            widthChanged(newWidth)
+        }
+    }
+}
+
+/**
+ * [SliceView] that prioritises [onClick] when its clicked instead of passing the event to the slice
+ * first.
+ */
+@SuppressLint("ViewConstructor") // only used in this class
+private class ClickableSliceView(
+    context: Context,
+    private val onClick: (() -> Unit)?,
+) : SliceView(context) {
+
+    init {
+        if (onClick != null) {
+            setOnClickListener {}
+        }
+    }
+
+    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
+        return onClick != null || super.onInterceptTouchEvent(ev)
+    }
+
+    override fun onClick(v: View?) {
+        onClick?.let { it() } ?: super.onClick(v)
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/BottomComponentButtonSurface.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/BottomComponentButtonSurface.kt
new file mode 100644
index 0000000..167eb65
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/BottomComponentButtonSurface.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.button.ui.composable
+
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+/**
+ * Container to create a rim around the button. Both `Expandable` and `OutlinedIconToggleButton`
+ * have antialiasing problem when used with [androidx.compose.foundation.BorderStroke] and some
+ * contrast container color.
+ */
+// TODO(b/331584069): Remove this once antialiasing bug is fixed
+@Composable
+fun BottomComponentButtonSurface(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
+    Surface(
+        modifier = modifier.height(64.dp),
+        shape = RoundedCornerShape(28.dp),
+        color = MaterialTheme.colorScheme.surface,
+        content = content,
+    )
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt
index b721e41..0893b9d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt
@@ -16,13 +16,12 @@
 
 package com.android.systemui.volume.panel.component.button.ui.composable
 
-import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.basicMarquee
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.MaterialTheme
@@ -37,7 +36,6 @@
 import androidx.compose.ui.semantics.contentDescription
 import androidx.compose.ui.semantics.role
 import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import com.android.compose.animation.Expandable
 import com.android.systemui.animation.Expandable
@@ -64,28 +62,38 @@
             verticalArrangement = Arrangement.spacedBy(12.dp),
             horizontalAlignment = Alignment.CenterHorizontally,
         ) {
-            Expandable(
-                modifier =
-                    Modifier.height(64.dp).fillMaxWidth().semantics {
-                        role = Role.Button
-                        contentDescription = label
-                    },
-                color = MaterialTheme.colorScheme.primaryContainer,
-                shape = RoundedCornerShape(28.dp),
-                contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
-                borderStroke = BorderStroke(8.dp, MaterialTheme.colorScheme.surface),
-                onClick = onClick,
-            ) {
-                Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
-                    Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+            BottomComponentButtonSurface {
+                Expandable(
+                    modifier =
+                        Modifier.fillMaxSize().padding(8.dp).semantics {
+                            role = Role.Button
+                            contentDescription = label
+                        },
+                    color =
+                        if (viewModel.isActive) {
+                            MaterialTheme.colorScheme.tertiaryContainer
+                        } else {
+                            MaterialTheme.colorScheme.surface
+                        },
+                    shape = RoundedCornerShape(28.dp),
+                    contentColor =
+                        if (viewModel.isActive) {
+                            MaterialTheme.colorScheme.onTertiaryContainer
+                        } else {
+                            MaterialTheme.colorScheme.onSurface
+                        },
+                    onClick = onClick,
+                ) {
+                    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                        Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+                    }
                 }
             }
             Text(
-                modifier = Modifier.clearAndSetSemantics {},
+                modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
                 text = label,
                 style = MaterialTheme.typography.labelMedium,
-                maxLines = 1,
-                overflow = TextOverflow.Ellipsis,
+                maxLines = 2,
             )
         }
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
index f6f07a5..4f3a6c8 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
@@ -16,38 +16,38 @@
 
 package com.android.systemui.volume.panel.component.button.ui.composable
 
-import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.basicMarquee
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.IconButtonDefaults
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.OutlinedIconToggleButton
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.semantics.contentDescription
 import androidx.compose.ui.semantics.role
 import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import com.android.systemui.common.ui.compose.Icon
-import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
 import com.android.systemui.volume.panel.ui.composable.ComposeVolumePanelUiComponent
 import com.android.systemui.volume.panel.ui.composable.VolumePanelComposeScope
 import kotlinx.coroutines.flow.StateFlow
 
 /** [ComposeVolumePanelUiComponent] implementing a toggleable button from a bottom row. */
 class ToggleButtonComponent(
-    private val viewModelFlow: StateFlow<ToggleButtonViewModel?>,
+    private val viewModelFlow: StateFlow<ButtonViewModel?>,
     private val onCheckedChange: (isChecked: Boolean) -> Unit
 ) : ComposeVolumePanelUiComponent {
 
@@ -62,32 +62,38 @@
             verticalArrangement = Arrangement.spacedBy(12.dp),
             horizontalAlignment = Alignment.CenterHorizontally,
         ) {
-            OutlinedIconToggleButton(
-                modifier =
-                    Modifier.height(64.dp).fillMaxWidth().semantics {
-                        role = Role.Switch
-                        contentDescription = label
-                    },
-                checked = viewModel.isChecked,
-                onCheckedChange = onCheckedChange,
-                shape = RoundedCornerShape(28.dp),
-                colors =
-                    IconButtonDefaults.outlinedIconToggleButtonColors(
-                        containerColor = MaterialTheme.colorScheme.surface,
-                        contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
-                        checkedContainerColor = MaterialTheme.colorScheme.primaryContainer,
-                        checkedContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
-                    ),
-                border = BorderStroke(8.dp, MaterialTheme.colorScheme.surface),
-            ) {
-                Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+            BottomComponentButtonSurface {
+                val colors =
+                    if (viewModel.isActive) {
+                        ButtonDefaults.buttonColors(
+                            containerColor = MaterialTheme.colorScheme.tertiaryContainer,
+                            contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
+                        )
+                    } else {
+                        ButtonDefaults.buttonColors(
+                            containerColor = Color.Transparent,
+                            contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
+                        )
+                    }
+                Button(
+                    modifier =
+                        Modifier.fillMaxSize().padding(8.dp).semantics {
+                            role = Role.Switch
+                            contentDescription = label
+                        },
+                    onClick = { onCheckedChange(!viewModel.isActive) },
+                    shape = RoundedCornerShape(28.dp),
+                    colors = colors
+                ) {
+                    Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+                }
             }
+
             Text(
-                modifier = Modifier.clearAndSetSemantics {},
+                modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
                 text = label,
                 style = MaterialTheme.typography.labelMedium,
-                maxLines = 1,
-                overflow = TextOverflow.Ellipsis,
+                maxLines = 2,
             )
         }
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt
index 26086d1..b489dfc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/popup/ui/composable/VolumePanelPopup.kt
@@ -33,6 +33,8 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.paneTitle
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.animation.Expandable
@@ -57,7 +59,7 @@
      * @param content is the popup body
      */
     fun show(
-        expandable: Expandable,
+        expandable: Expandable?,
         title: @Composable (SystemUIDialog) -> Unit,
         content: @Composable (SystemUIDialog) -> Unit,
     ) {
@@ -68,7 +70,7 @@
             ) {
                 PopupComposable(it, title, content)
             }
-        val controller = expandable.dialogTransitionController()
+        val controller = expandable?.dialogTransitionController()
         if (controller == null) {
             dialog.show()
         } else {
@@ -82,7 +84,8 @@
         title: @Composable (SystemUIDialog) -> Unit,
         content: @Composable (SystemUIDialog) -> Unit,
     ) {
-        Box(Modifier.fillMaxWidth()) {
+        val paneTitle = stringResource(R.string.accessibility_volume_settings)
+        Box(Modifier.fillMaxWidth().semantics(properties = { this.paneTitle = paneTitle })) {
             Column(
                 modifier = Modifier.fillMaxWidth().padding(vertical = 20.dp),
                 verticalArrangement = Arrangement.spacedBy(20.dp),
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
index b0b5a7d..51e2064 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
@@ -21,6 +21,7 @@
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.Spacer
@@ -29,9 +30,11 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.shape.CornerSize
 import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.LocalContentColor
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
@@ -45,6 +48,12 @@
 import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.clearAndSetSemantics
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.selected
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
@@ -111,10 +120,17 @@
                 horizontalArrangement = Arrangement.spacedBy(spacing)
             ) {
                 for (itemIndex in items.indices) {
+                    val item = items[itemIndex]
+                    val isSelected = itemIndex == scope.selectedIndex
                     Row(
                         modifier =
                             Modifier.height(48.dp)
                                 .weight(1f)
+                                .semantics {
+                                    item.contentDescription?.let { contentDescription = it }
+                                    role = Role.Switch
+                                    selected = isSelected
+                                }
                                 .clickable(
                                     interactionSource = null,
                                     indication = null,
@@ -123,9 +139,12 @@
                         horizontalArrangement = Arrangement.Center,
                         verticalAlignment = Alignment.CenterVertically,
                     ) {
-                        val item = items[itemIndex]
                         if (item.icon !== Empty) {
-                            with(items[itemIndex]) { icon() }
+                            CompositionLocalProvider(
+                                LocalContentColor provides colors.getIconColor(isSelected)
+                            ) {
+                                with(items[itemIndex]) { icon() }
+                            }
                         }
                     }
                 }
@@ -137,17 +156,24 @@
                             start = indicatorBackgroundPadding,
                             top = labelIndicatorBackgroundSpacing,
                             end = indicatorBackgroundPadding
-                        ),
+                        )
+                        .clearAndSetSemantics {},
                 horizontalArrangement = Arrangement.spacedBy(spacing),
             ) {
                 for (itemIndex in items.indices) {
+                    val cornersRadius = 4.dp
                     TextButton(
                         modifier = Modifier.weight(1f),
                         onClick = { items[itemIndex].onItemSelected() },
+                        shape = RoundedCornerShape(cornersRadius),
+                        contentPadding = PaddingValues(cornersRadius)
                     ) {
                         val item = items[itemIndex]
                         if (item.icon !== Empty) {
-                            with(items[itemIndex]) { label() }
+                            val textColor = colors.getLabelColor(itemIndex == scope.selectedIndex)
+                            CompositionLocalProvider(LocalContentColor provides textColor) {
+                                with(items[itemIndex]) { label() }
+                            }
                         }
                     }
                 }
@@ -249,8 +275,22 @@
     val indicatorColor: Color,
     /** Color of the indicator background. */
     val indicatorBackgroundColor: Color,
+    /** Color of the icon. */
+    val iconColor: Color,
+    /** Color of the icon when it's selected. */
+    val selectedIconColor: Color,
+    /** Color of the label. */
+    val labelColor: Color,
+    /** Color of the label when it's selected. */
+    val selectedLabelColor: Color,
 )
 
+private fun VolumePanelRadioButtonBarColors.getIconColor(selected: Boolean): Color =
+    if (selected) selectedIconColor else iconColor
+
+private fun VolumePanelRadioButtonBarColors.getLabelColor(selected: Boolean): Color =
+    if (selected) selectedLabelColor else labelColor
+
 object VolumePanelRadioButtonBarDefaults {
 
     val DefaultIndicatorBackgroundPadding = 8.dp
@@ -267,12 +307,20 @@
      */
     @Composable
     fun defaultColors(
-        indicatorColor: Color = MaterialTheme.colorScheme.primaryContainer,
+        indicatorColor: Color = MaterialTheme.colorScheme.tertiaryContainer,
         indicatorBackgroundColor: Color = MaterialTheme.colorScheme.surface,
+        iconColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
+        selectedIconColor: Color = MaterialTheme.colorScheme.onTertiaryContainer,
+        labelColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
+        selectedLabelColor: Color = MaterialTheme.colorScheme.onSurface,
     ): VolumePanelRadioButtonBarColors =
         VolumePanelRadioButtonBarColors(
             indicatorColor = indicatorColor,
             indicatorBackgroundColor = indicatorBackgroundColor,
+            iconColor = iconColor,
+            selectedIconColor = selectedIconColor,
+            labelColor = labelColor,
+            selectedLabelColor = selectedLabelColor,
         )
 }
 
@@ -292,6 +340,7 @@
         onItemSelected: () -> Unit,
         icon: @Composable RowScope.() -> Unit = Empty,
         label: @Composable RowScope.() -> Unit = Empty,
+        contentDescription: String? = null,
     )
 }
 
@@ -313,6 +362,7 @@
         onItemSelected: () -> Unit,
         icon: @Composable RowScope.() -> Unit,
         label: @Composable RowScope.() -> Unit,
+        contentDescription: String?,
     ) {
         require(!isSelected || !hasSelectedItem) { "Only one item should be selected at a time" }
         if (isSelected) {
@@ -323,6 +373,7 @@
                 onItemSelected = onItemSelected,
                 icon = icon,
                 label = label,
+                contentDescription = contentDescription,
             )
         )
     }
@@ -336,6 +387,7 @@
     val onItemSelected: () -> Unit,
     val icon: @Composable RowScope.() -> Unit,
     val label: @Composable RowScope.() -> Unit,
+    val contentDescription: String?,
 )
 
 private const val UNSET_OFFSET = -1
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
index 71b3e8a..12d2bc2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
@@ -16,22 +16,26 @@
 
 package com.android.systemui.volume.panel.component.spatialaudio.ui.composable
 
+import androidx.compose.foundation.basicMarquee
+import androidx.compose.material3.LocalContentColor
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextAlign
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.ui.compose.Icon
-import com.android.systemui.common.ui.compose.toColor
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.volume.panel.component.popup.ui.composable.VolumePanelPopup
 import com.android.systemui.volume.panel.component.selector.ui.composable.VolumePanelRadioButtonBar
 import com.android.systemui.volume.panel.component.spatial.ui.viewmodel.SpatialAudioViewModel
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
 
 class SpatialAudioPopup
@@ -39,16 +43,24 @@
 constructor(
     private val viewModel: SpatialAudioViewModel,
     private val volumePanelPopup: VolumePanelPopup,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
     /** Shows a popup with the [expandable] animation. */
     fun show(expandable: Expandable) {
+        uiEventLogger.logWithPosition(
+            VolumePanelUiEvent.VOLUME_PANEL_SPATIAL_AUDIO_POP_UP_SHOWN,
+            0,
+            null,
+            viewModel.spatialAudioButtons.value.indexOfFirst { it.button.isActive }
+        )
         volumePanelPopup.show(expandable, { Title() }, { Content(it) })
     }
 
     @Composable
     private fun Title() {
         Text(
+            modifier = Modifier.basicMarquee(),
             text = stringResource(R.string.volume_panel_spatial_audio_title),
             style = MaterialTheme.typography.titleMedium,
             textAlign = TextAlign.Center,
@@ -71,20 +83,20 @@
         }
         VolumePanelRadioButtonBar {
             for (buttonViewModel in enabledModelStates) {
+                val label = buttonViewModel.button.label.toString()
                 item(
-                    isSelected = buttonViewModel.button.isChecked,
+                    isSelected = buttonViewModel.button.isActive,
                     onItemSelected = { viewModel.setEnabled(buttonViewModel.model) },
-                    icon = {
-                        Icon(
-                            icon = buttonViewModel.button.icon,
-                            tint = buttonViewModel.iconColor.toColor(),
-                        )
-                    },
+                    contentDescription = label,
+                    icon = { Icon(icon = buttonViewModel.button.icon) },
                     label = {
                         Text(
-                            text = buttonViewModel.button.label.toString(),
+                            modifier = Modifier.basicMarquee(),
+                            text = label,
                             style = MaterialTheme.typography.labelMedium,
-                            color = buttonViewModel.labelColor.toColor(),
+                            color = LocalContentColor.current,
+                            textAlign = TextAlign.Center,
+                            maxLines = 2
                         )
                     }
                 )
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt
index f89669c..a3467f2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt
@@ -85,6 +85,7 @@
                 onValueChange = { newValue: Float ->
                     sliderViewModel.onValueChanged(sliderState, newValue)
                 },
+                onValueChangeFinished = { sliderViewModel.onValueChangeFinished() },
                 onIconTapped = { sliderViewModel.toggleMuted(sliderState) },
                 sliderColors = sliderColors,
             )
@@ -106,7 +107,7 @@
             }
         }
         transition.AnimatedVisibility(
-            visible = { it },
+            visible = { it || !isExpandable },
             enter =
                 expandVertically(animationSpec = tween(durationMillis = EXPAND_DURATION_MILLIS)),
             exit =
@@ -121,7 +122,7 @@
                         val sliderState by sliderViewModel.slider.collectAsState()
                         transition.AnimatedVisibility(
                             modifier = Modifier.padding(top = 16.dp),
-                            visible = { it },
+                            visible = { it || !isExpandable },
                             enter = enterTransition(index = index, totalCount = viewModels.size),
                             exit = exitTransition(index = index, totalCount = viewModels.size)
                         ) {
@@ -131,6 +132,7 @@
                                 onValueChange = { newValue: Float ->
                                     sliderViewModel.onValueChanged(sliderState, newValue)
                                 },
+                                onValueChangeFinished = { sliderViewModel.onValueChangeFinished() },
                                 onIconTapped = { sliderViewModel.toggleMuted(sliderState) },
                                 sliderColors = sliderColors,
                             )
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt
index b284c69..bb17499 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/GridVolumeSliders.kt
@@ -46,6 +46,7 @@
                 onValueChange = { newValue: Float ->
                     sliderViewModel.onValueChanged(sliderState, newValue)
                 },
+                onValueChangeFinished = { sliderViewModel.onValueChangeFinished() },
                 onIconTapped = { sliderViewModel.toggleMuted(sliderState) },
                 sliderColors = sliderColors,
             )
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
index d31064a..9f5ab3c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
@@ -16,13 +16,15 @@
 
 package com.android.systemui.volume.panel.component.volume.ui.composable
 
+import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.IconButtonColors
-import androidx.compose.material3.LocalContentColor
-import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.getValue
@@ -32,7 +34,6 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.semantics.ProgressBarRangeInfo
 import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.semantics.contentDescription
@@ -50,6 +51,7 @@
 fun VolumeSlider(
     state: SliderState,
     onValueChange: (newValue: Float) -> Unit,
+    onValueChangeFinished: (() -> Unit)? = null,
     onIconTapped: () -> Unit,
     modifier: Modifier = Modifier,
     sliderColors: PlatformSliderColors,
@@ -59,7 +61,8 @@
         modifier =
             modifier.clearAndSetSemantics {
                 if (!state.isEnabled) disabled()
-                contentDescription = state.label
+                contentDescription =
+                    state.disabledMessage?.let { "${state.label}, $it" } ?: state.label
 
                 // provide a not animated value to the a11y because it fails to announce the
                 // settled value when it changes rapidly.
@@ -84,28 +87,31 @@
         value = value,
         valueRange = state.valueRange,
         onValueChange = onValueChange,
+        onValueChangeFinished = onValueChangeFinished,
         enabled = state.isEnabled,
-        icon = { isDragging ->
-            if (isDragging) {
-                Text(text = state.valueText, color = LocalContentColor.current)
-            } else {
-                state.icon?.let {
-                    SliderIcon(
-                        icon = it,
-                        onIconTapped = onIconTapped,
-                        isTappable = state.isMutable,
-                    )
-                }
+        icon = {
+            state.icon?.let {
+                SliderIcon(
+                    icon = it,
+                    onIconTapped = onIconTapped,
+                    isTappable = state.isMutable,
+                )
             }
         },
         colors = sliderColors,
-        label = {
-            VolumeSliderContent(
-                modifier = Modifier,
-                label = state.label,
-                isEnabled = state.isEnabled,
-                disabledMessage = state.disabledMessage,
-            )
+        label = { isDragging ->
+            AnimatedVisibility(
+                visible = !isDragging,
+                enter = fadeIn(tween(150)),
+                exit = fadeOut(tween(150)),
+            ) {
+                VolumeSliderContent(
+                    modifier = Modifier,
+                    label = state.label,
+                    isEnabled = state.isEnabled,
+                    disabledMessage = state.disabledMessage,
+                )
+            }
         }
     )
 }
@@ -130,24 +136,20 @@
     isTappable: Boolean,
     modifier: Modifier = Modifier
 ) {
-    if (isTappable) {
-        IconButton(
-            modifier = modifier,
-            onClick = onIconTapped,
-            colors =
-                IconButtonColors(
-                    contentColor = LocalContentColor.current,
-                    containerColor = Color.Transparent,
-                    disabledContentColor = LocalContentColor.current,
-                    disabledContainerColor = Color.Transparent,
-                ),
-            content = { Icon(modifier = Modifier.size(24.dp), icon = icon) },
-        )
-    } else {
-        Box(
-            modifier = modifier,
-            contentAlignment = Alignment.Center,
-            content = { Icon(modifier = Modifier.size(24.dp), icon = icon) },
-        )
-    }
+    val boxModifier =
+        if (isTappable) {
+                modifier.clickable(
+                    onClick = onIconTapped,
+                    interactionSource = null,
+                    indication = null
+                )
+            } else {
+                modifier
+            }
+            .fillMaxSize()
+    Box(
+        modifier = boxModifier,
+        contentAlignment = Alignment.Center,
+        content = { Icon(modifier = Modifier.size(24.dp), icon = icon) },
+    )
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt
index dd76781..9ea20b9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VerticalVolumePanelContent.kt
@@ -20,6 +20,7 @@
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.rememberScrollState
@@ -27,6 +28,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastSumBy
 import com.android.systemui.volume.panel.ui.layout.ComponentsLayout
 
 @Composable
@@ -53,6 +55,14 @@
                 modifier = Modifier.fillMaxWidth().wrapContentHeight(),
                 horizontalArrangement = Arrangement.spacedBy(if (isLargeScreen) 28.dp else 20.dp),
             ) {
+                val visibleComponentsCount =
+                    layout.footerComponents.fastSumBy { if (it.isVisible) 1 else 0 }
+
+                // Center footer component if there is only one present
+                if (visibleComponentsCount == 1) {
+                    Spacer(modifier = Modifier.weight(0.5f))
+                }
+
                 for (component in layout.footerComponents) {
                     AnimatedVisibility(
                         visible = component.isVisible,
@@ -63,6 +73,10 @@
                         }
                     }
                 }
+
+                if (visibleComponentsCount == 1) {
+                    Spacer(modifier = Modifier.weight(0.5f))
+                }
             }
         }
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
index 910cd5e..1bf541a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/ui/composable/VolumePanelRoot.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.volume.panel.ui.composable
 
-import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -38,6 +38,7 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.dimensionResource
@@ -75,21 +76,13 @@
                 modifier =
                     modifier
                         .fillMaxSize()
-                        .clickable(onClick = onDismiss)
+                        .volumePanelClick(onDismiss)
                         .volumePanelPaddings(isPortrait = isPortrait),
                 contentAlignment = Alignment.BottomCenter,
             ) {
                 val radius = dimensionResource(R.dimen.volume_panel_corner_radius)
                 Surface(
-                    modifier =
-                        Modifier.clickable(
-                            interactionSource = null,
-                            indication = null,
-                            onClick = {
-                                // prevent windowCloseOnTouchOutside from dismissing when tapped
-                                // on the panel itself.
-                            },
-                        ),
+                    modifier = Modifier.volumePanelClick {},
                     shape = RoundedCornerShape(topStart = radius, topEnd = radius),
                     color = MaterialTheme.colorScheme.surfaceContainer,
                 ) {
@@ -185,3 +178,13 @@
         )
     }
 }
+
+/**
+ * For some reason adding clickable modifier onto the VolumePanel affects the traversal order:
+ * b/331155283.
+ *
+ * TODO(b/334870995) revert this to Modifier.clickable
+ */
+@Composable
+private fun Modifier.volumePanelClick(onClick: () -> Unit) =
+    pointerInput(onClick) { detectTapGestures { onClick() } }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 1b06275..32cebd1 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -280,7 +280,7 @@
             swipes.findUserActionResult(
                 fromScene = fromScene,
                 directionOffset = swipeTransition.dragOffset,
-                updateSwipesResults = isNewFromScene
+                updateSwipesResults = isNewFromScene,
             )
 
         if (result == null) {
@@ -288,13 +288,14 @@
             return
         }
 
-        swipeTransition.dragOffset += acceleratedOffset
-
         if (
             isNewFromScene ||
                 result.toScene != swipeTransition.toScene ||
                 result.transitionKey != swipeTransition.key
         ) {
+            // Make sure the current transition will finish to the right current scene.
+            swipeTransition._currentScene = fromScene
+
             val swipeTransition =
                 SwipeTransition(
                         layoutState = layoutState,
@@ -305,7 +306,7 @@
                         layoutImpl = draggableHandler.layoutImpl,
                         orientation = draggableHandler.orientation,
                     )
-                    .apply { dragOffset = swipeTransition.dragOffset }
+                    .apply { dragOffset = swipeTransition.dragOffset + acceleratedOffset }
 
             updateTransition(swipeTransition)
         }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index e7cb5a4..7d43ca8 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -43,6 +43,7 @@
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.round
 import androidx.compose.ui.util.fastCoerceIn
+import androidx.compose.ui.util.fastLastOrNull
 import androidx.compose.ui.util.lerp
 import com.android.compose.animation.scene.transformation.PropertyTransformation
 import com.android.compose.animation.scene.transformation.SharedElementTransformation
@@ -81,14 +82,12 @@
 }
 
 data class Scale(val scaleX: Float, val scaleY: Float, val pivot: Offset = Offset.Unspecified) {
-
     companion object {
         val Default = Scale(1f, 1f, Offset.Unspecified)
     }
 }
 
 /** The implementation of [SceneScope.element]. */
-@OptIn(ExperimentalComposeUiApi::class)
 @Stable
 internal fun Modifier.element(
     layoutImpl: SceneTransitionLayoutImpl,
@@ -187,7 +186,7 @@
     override fun isMeasurementApproachComplete(lookaheadSize: IntSize): Boolean {
         // TODO(b/324191441): Investigate whether making this check more complex (checking if this
         // element is shared or transformed) would lead to better performance.
-        return layoutImpl.state.currentTransition == null
+        return layoutImpl.state.currentTransitions.isEmpty()
     }
 
     override fun Placeable.PlacementScope.isPlacementApproachComplete(
@@ -195,7 +194,7 @@
     ): Boolean {
         // TODO(b/324191441): Investigate whether making this check more complex (checking if this
         // element is shared or transformed) would lead to better performance.
-        return layoutImpl.state.currentTransition == null
+        return layoutImpl.state.currentTransitions.isEmpty()
     }
 
     @ExperimentalComposeUiApi
@@ -203,25 +202,38 @@
         measurable: Measurable,
         constraints: Constraints,
     ): MeasureResult {
-        val overscrollScene = layoutImpl.state.currentTransition?.currentOverscrollSpec?.scene
-        if (overscrollScene != null && overscrollScene != scene.key) {
-            // There is an overscroll in progress on another scene
-            // By measuring composable elements, Compose can cache relevant information.
-            // This reduces the need for re-measure when users return from an overscroll animation.
+        val transitions = layoutImpl.state.currentTransitions
+        val transition = elementTransition(element, transitions)
+
+        // If this element is not supposed to be laid out now, either because it is not part of any
+        // ongoing transition or the other scene of its transition is overscrolling, then lay out
+        // the element normally and don't place it.
+        val overscrollScene = transition?.currentOverscrollSpec?.scene
+        val isOtherSceneOverscrolling = overscrollScene != null && overscrollScene != scene.key
+        val isNotPartOfAnyOngoingTransitions = transitions.isNotEmpty() && transition == null
+        if (isNotPartOfAnyOngoingTransitions || isOtherSceneOverscrolling) {
             val placeable = measurable.measure(constraints)
-            return layout(placeable.width, placeable.height) {
-                // We don't want to draw it, no need to place the element.
-            }
+            return layout(placeable.width, placeable.height) {}
         }
 
-        val placeable = measure(layoutImpl, scene, element, sceneState, measurable, constraints)
+        val placeable =
+            measure(layoutImpl, scene, element, transition, sceneState, measurable, constraints)
         return layout(placeable.width, placeable.height) {
-            place(layoutImpl, scene, element, sceneState, placeable, placementScope = this)
+            place(
+                layoutImpl,
+                scene,
+                element,
+                transition,
+                sceneState,
+                placeable,
+                placementScope = this,
+            )
         }
     }
 
     override fun ContentDrawScope.draw() {
-        val drawScale = getDrawScale(layoutImpl, element, scene)
+        val transition = elementTransition(element, layoutImpl.state.currentTransitions)
+        val drawScale = getDrawScale(layoutImpl, scene, element, transition)
         if (drawScale == Scale.Default) {
             drawContent()
         } else {
@@ -256,67 +268,91 @@
     }
 }
 
-private fun shouldDrawElement(
+/**
+ * The transition that we should consider for [element]. This is the last transition where one of
+ * its scenes contains the element.
+ */
+private fun elementTransition(
+    element: Element,
+    transitions: List<TransitionState.Transition>,
+): TransitionState.Transition? {
+    return transitions.fastLastOrNull { transition ->
+        transition.fromScene in element.sceneStates || transition.toScene in element.sceneStates
+    }
+}
+
+private fun shouldPlaceElement(
     layoutImpl: SceneTransitionLayoutImpl,
     scene: Scene,
     element: Element,
+    transition: TransitionState.Transition?,
 ): Boolean {
-    val transition = layoutImpl.state.currentTransition
+    // Always place the element if we are idle.
+    if (transition == null) {
+        return true
+    }
 
-    // Always draw the element if there is no ongoing transition or if the element is not shared or
-    // if the current scene is the one that is currently over scrolling with [OverscrollSpec].
+    // Don't place the element in this scene if this scene is not part of the current element
+    // transition.
+    if (scene.key != transition.fromScene && scene.key != transition.toScene) {
+        return false
+    }
+
+    // Place the element if it is not shared or if the current scene is the one that is currently
+    // overscrolling with [OverscrollSpec].
     if (
-        transition == null ||
-            transition.fromScene !in element.sceneStates ||
+        transition.fromScene !in element.sceneStates ||
             transition.toScene !in element.sceneStates ||
             transition.currentOverscrollSpec?.scene == scene.key
     ) {
         return true
     }
 
-    val sharedTransformation = sharedElementTransformation(transition, element.key)
+    val sharedTransformation = sharedElementTransformation(element.key, transition)
     if (sharedTransformation?.enabled == false) {
         return true
     }
 
     return shouldDrawOrComposeSharedElement(
         layoutImpl,
-        transition,
         scene.key,
         element.key,
+        transition,
     )
 }
 
 internal fun shouldDrawOrComposeSharedElement(
     layoutImpl: SceneTransitionLayoutImpl,
-    transition: TransitionState.Transition,
     scene: SceneKey,
     element: ElementKey,
+    transition: TransitionState.Transition,
 ): Boolean {
     val scenePicker = element.scenePicker
     val fromScene = transition.fromScene
     val toScene = transition.toScene
 
-    val chosenByPicker =
+    val pickedScene =
         scenePicker.sceneDuringTransition(
             element = element,
             transition = transition,
             fromSceneZIndex = layoutImpl.scenes.getValue(fromScene).zIndex,
             toSceneZIndex = layoutImpl.scenes.getValue(toScene).zIndex,
-        ) == scene
-    return chosenByPicker || transition.currentOverscrollSpec?.scene == scene
+        )
+            ?: return false
+
+    return pickedScene == scene || transition.currentOverscrollSpec?.scene == scene
 }
 
 private fun isSharedElementEnabled(
-    transition: TransitionState.Transition,
     element: ElementKey,
+    transition: TransitionState.Transition,
 ): Boolean {
-    return sharedElementTransformation(transition, element)?.enabled ?: true
+    return sharedElementTransformation(element, transition)?.enabled ?: true
 }
 
 internal fun sharedElementTransformation(
-    transition: TransitionState.Transition,
     element: ElementKey,
+    transition: TransitionState.Transition,
 ): SharedElementTransformation? {
     val transformationSpec = transition.transformationSpec
     val sharedInFromScene = transformationSpec.transformations(element, transition.fromScene).shared
@@ -341,11 +377,13 @@
  * placement and we don't want to read the transition progress in that phase.
  */
 private fun isElementOpaque(
-    layoutImpl: SceneTransitionLayoutImpl,
-    element: Element,
     scene: Scene,
+    element: Element,
+    transition: TransitionState.Transition?,
 ): Boolean {
-    val transition = layoutImpl.state.currentTransition ?: return true
+    if (transition == null) {
+        return true
+    }
 
     val fromScene = transition.fromScene
     val toScene = transition.toScene
@@ -353,11 +391,13 @@
     val toState = element.sceneStates[toScene]
 
     if (fromState == null && toState == null) {
-        error("This should not happen, element $element is neither in $fromScene or $toScene")
+        // TODO(b/311600838): Throw an exception instead once layers of disposed elements are not
+        // run anymore.
+        return true
     }
 
     val isSharedElement = fromState != null && toState != null
-    if (isSharedElement && isSharedElementEnabled(transition, element.key)) {
+    if (isSharedElement && isSharedElementEnabled(element.key, transition)) {
         return true
     }
 
@@ -374,13 +414,15 @@
  */
 private fun elementAlpha(
     layoutImpl: SceneTransitionLayoutImpl,
-    element: Element,
     scene: Scene,
+    element: Element,
+    transition: TransitionState.Transition?,
 ): Float {
     return computeValue(
             layoutImpl,
             scene,
             element,
+            transition,
             sceneValue = { 1f },
             transformation = { it.alpha },
             idleValue = 1f,
@@ -396,6 +438,7 @@
     layoutImpl: SceneTransitionLayoutImpl,
     scene: Scene,
     element: Element,
+    transition: TransitionState.Transition?,
     sceneState: Element.SceneState,
     measurable: Measurable,
     constraints: Constraints,
@@ -419,6 +462,7 @@
             layoutImpl,
             scene,
             element,
+            transition,
             sceneValue = { it.targetSize },
             transformation = { it.size },
             idleValue = lookaheadSize,
@@ -438,13 +482,15 @@
 
 private fun getDrawScale(
     layoutImpl: SceneTransitionLayoutImpl,
+    scene: Scene,
     element: Element,
-    scene: Scene
+    transition: TransitionState.Transition?,
 ): Scale {
     return computeValue(
         layoutImpl,
         scene,
         element,
+        transition,
         sceneValue = { Scale.Default },
         transformation = { it.drawScale },
         idleValue = Scale.Default,
@@ -459,6 +505,7 @@
     layoutImpl: SceneTransitionLayoutImpl,
     scene: Scene,
     element: Element,
+    transition: TransitionState.Transition?,
     sceneState: Element.SceneState,
     placeable: Placeable,
     placementScope: Placeable.PlacementScope,
@@ -476,7 +523,7 @@
         }
 
         // No need to place the element in this scene if we don't want to draw it anyways.
-        if (!shouldDrawElement(layoutImpl, scene, element)) {
+        if (!shouldPlaceElement(layoutImpl, scene, element, transition)) {
             return
         }
 
@@ -486,6 +533,7 @@
                 layoutImpl,
                 scene,
                 element,
+                transition,
                 sceneValue = { it.targetOffset },
                 transformation = { it.offset },
                 idleValue = targetOffsetInScene,
@@ -495,14 +543,14 @@
             )
 
         val offset = (targetOffset - currentOffset).round()
-        if (isElementOpaque(layoutImpl, element, scene)) {
+        if (isElementOpaque(scene, element, transition)) {
             // TODO(b/291071158): Call placeWithLayer() if offset != IntOffset.Zero and size is not
             // animated once b/305195729 is fixed. Test that drawing is not invalidated in that
             // case.
             placeable.place(offset)
         } else {
             placeable.placeWithLayer(offset) {
-                alpha = elementAlpha(layoutImpl, element, scene)
+                alpha = elementAlpha(layoutImpl, scene, element, transition)
                 compositingStrategy = CompositingStrategy.ModulateAlpha
             }
         }
@@ -533,6 +581,7 @@
     layoutImpl: SceneTransitionLayoutImpl,
     scene: Scene,
     element: Element,
+    transition: TransitionState.Transition?,
     sceneValue: (Element.SceneState) -> T,
     transformation: (ElementTransformations) -> PropertyTransformation<T>?,
     idleValue: T,
@@ -540,13 +589,13 @@
     isSpecified: (T) -> Boolean,
     lerp: (T, T, Float) -> T,
 ): T {
-    val transition =
-        layoutImpl.state.currentTransition
+    if (transition == null) {
         // There is no ongoing transition. Even if this element SceneTransitionLayout is not
         // animated, the layout itself might be animated (e.g. by another parent
         // SceneTransitionLayout), in which case this element still need to participate in the
         // layout phase.
-        ?: return currentValue()
+        return currentValue()
+    }
 
     val fromScene = transition.fromScene
     val toScene = transition.toScene
@@ -599,7 +648,7 @@
     // TODO(b/290184746): Support non linear shared paths as well as a way to make sure that shared
     // elements follow the finger direction.
     val isSharedElement = fromState != null && toState != null
-    if (isSharedElement && isSharedElementEnabled(transition, element.key)) {
+    if (isSharedElement && isSharedElementEnabled(element.key, transition)) {
         val start = sceneValue(fromState!!)
         val end = sceneValue(toState!!)
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index be066fd..4b20aca 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -26,6 +26,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.util.fastLastOrNull
 
 @Composable
 internal fun Element(
@@ -165,18 +166,33 @@
     scene: SceneKey,
     element: ElementKey,
 ): Boolean {
-    val transition =
-        layoutImpl.state.currentTransition
+    val transitions = layoutImpl.state.currentTransitions
+    if (transitions.isEmpty()) {
         // If we are idle, there is only one [scene] that is composed so we can compose our
-        // movable content here.
-        ?: return true
+        // movable content here. We still check that [scene] is equal to the current idle scene, to
+        // make sure we only compose it there.
+        return layoutImpl.state.transitionState.currentScene == scene
+    }
+
+    // The current transition for this element is the last transition in which either fromScene or
+    // toScene contains the element.
+    val transition =
+        transitions.fastLastOrNull { transition ->
+            element.scenePicker.sceneDuringTransition(
+                element = element,
+                transition = transition,
+                fromSceneZIndex = layoutImpl.scenes.getValue(transition.fromScene).zIndex,
+                toSceneZIndex = layoutImpl.scenes.getValue(transition.toScene).zIndex,
+            ) != null
+        }
+            ?: return false
 
     // Always compose movable elements in the scene picked by their scene picker.
     return shouldDrawOrComposeSharedElement(
         layoutImpl,
-        transition,
         scene,
         element,
+        transition,
     )
 }
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index dc3b612..7fb5a4d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -44,10 +44,30 @@
     internal val scope = SceneScopeImpl(layoutImpl, this)
 
     var content by mutableStateOf(content)
-    var userActions by mutableStateOf(actions)
+    private var _userActions by mutableStateOf(checkValid(actions))
     var zIndex by mutableFloatStateOf(zIndex)
     var targetSize by mutableStateOf(IntSize.Zero)
 
+    var userActions
+        get() = _userActions
+        set(value) {
+            _userActions = checkValid(value)
+        }
+
+    private fun checkValid(
+        userActions: Map<UserAction, UserActionResult>
+    ): Map<UserAction, UserActionResult> {
+        userActions.forEach { (action, result) ->
+            if (key == result.toScene) {
+                error(
+                    "Transition to the same scene is not supported. Scene $key, action $action," +
+                        " result $result"
+                )
+            }
+        }
+        return userActions
+    }
+
     @Composable
     @OptIn(ExperimentalComposeUiApi::class)
     fun Content(modifier: Modifier = Modifier) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index b1cfdcf..20dcc20 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -35,6 +35,7 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastForEachReversed
 import com.android.compose.ui.util.lerp
 import kotlinx.coroutines.CoroutineScope
 
@@ -191,37 +192,44 @@
                 .then(LayoutElement(layoutImpl = this))
         ) {
             LookaheadScope {
-                val scenesToCompose =
-                    when (val state = state.transitionState) {
-                        is TransitionState.Idle -> listOf(scene(state.currentScene))
-                        is TransitionState.Transition -> {
-                            if (state.toScene != state.fromScene) {
-                                listOf(scene(state.toScene), scene(state.fromScene))
-                            } else {
-                                listOf(scene(state.fromScene))
-                            }
-                        }
-                    }
+                BackHandler()
 
-                // Handle back events.
-                // TODO(b/290184746): Make sure that this works with SystemUI once we use
-                // SceneTransitionLayout in Flexiglass.
-                scene(state.transitionState.currentScene).userActions[Back]?.let { result ->
-                    // TODO(b/290184746): Handle predictive back and use result.distance if
-                    // specified.
-                    BackHandler {
-                        val targetScene = result.toScene
-                        if (state.canChangeScene(targetScene)) {
-                            with(state) { coroutineScope.onChangeScene(targetScene) }
-                        }
+                scenesToCompose().fastForEach { scene -> key(scene.key) { scene.Content() } }
+            }
+        }
+    }
+
+    @Composable
+    private fun BackHandler() {
+        val targetSceneForBackOrNull =
+            scene(state.transitionState.currentScene).userActions[Back]?.toScene
+        BackHandler(enabled = targetSceneForBackOrNull != null) {
+            targetSceneForBackOrNull?.let { targetSceneForBack ->
+                // TODO(b/290184746): Handle predictive back and use result.distance if specified.
+                if (state.canChangeScene(targetSceneForBack)) {
+                    with(state) { coroutineScope.onChangeScene(targetSceneForBack) }
+                }
+            }
+        }
+    }
+
+    private fun scenesToCompose(): List<Scene> {
+        val transitions = state.currentTransitions
+        return if (transitions.isEmpty()) {
+            listOf(scene(state.transitionState.currentScene))
+        } else {
+            buildList {
+                val visited = mutableSetOf<SceneKey>()
+                fun maybeAdd(sceneKey: SceneKey) {
+                    if (visited.add(sceneKey)) {
+                        add(scene(sceneKey))
                     }
                 }
 
-                Box {
-                    scenesToCompose.fastForEach { scene ->
-                        val key = scene.key
-                        key(key) { scene.Content() }
-                    }
+                // Compose the new scene we are going to first.
+                transitions.fastForEachReversed { transition ->
+                    maybeAdd(transition.toScene)
+                    maybeAdd(transition.fromScene)
                 }
             }
         }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index 2c109a3..6bc397e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -205,7 +205,9 @@
 interface ElementScenePicker {
     /**
      * Return the scene in which [element] should be drawn (when using `Modifier.element(key)`) or
-     * composed (when using `MovableElement(key)`) during the given [transition].
+     * composed (when using `MovableElement(key)`) during the given [transition]. If this element
+     * should not be drawn or composed in neither [transition.fromScene] nor [transition.toScene],
+     * return `null`.
      *
      * Important: For [MovableElements][SceneScope.MovableElement], this scene picker will *always*
      * be used during transitions to decide whether we should compose that element in a given scene
@@ -217,12 +219,13 @@
         transition: TransitionState.Transition,
         fromSceneZIndex: Float,
         toSceneZIndex: Float,
-    ): SceneKey
+    ): SceneKey?
 
     /**
      * Return [transition.fromScene] if it is in [scenes] and [transition.toScene] is not, or return
-     * [transition.toScene] if it is in [scenes] and [transition.fromScene] is not, otherwise throw
-     * an exception (i.e. if neither or both of fromScene and toScene are in [scenes]).
+     * [transition.toScene] if it is in [scenes] and [transition.fromScene] is not. If neither
+     * [transition.fromScene] and [transition.toScene] are in [scenes], return `null`. If both
+     * [transition.fromScene] and [transition.toScene] are in [scenes], throw an exception.
      *
      * This function can be useful when computing the scene in which a movable element should be
      * composed.
@@ -231,31 +234,22 @@
         scenes: Set<SceneKey>,
         transition: TransitionState.Transition,
         element: ElementKey,
-    ): SceneKey {
+    ): SceneKey? {
         val fromScene = transition.fromScene
         val toScene = transition.toScene
         val fromSceneInScenes = scenes.contains(fromScene)
         val toSceneInScenes = scenes.contains(toScene)
-        if (fromSceneInScenes && toSceneInScenes) {
-            error(
-                "Element $element can be in both $fromScene and $toScene. You should add a " +
-                    "special case for this transition before calling pickSingleSceneIn()."
-            )
-        }
 
-        if (!fromSceneInScenes && !toSceneInScenes) {
-            error(
-                "Element $element can be neither in $fromScene and $toScene. This either means " +
-                    "that you should add one of them in the scenes set passed to " +
-                    "pickSingleSceneIn(), or there is an internal error and this element was " +
-                    "composed when it shouldn't be."
-            )
-        }
-
-        return if (fromSceneInScenes) {
-            fromScene
-        } else {
-            toScene
+        return when {
+            fromSceneInScenes && toSceneInScenes -> {
+                error(
+                    "Element $element can be in both $fromScene and $toScene. You should add a " +
+                        "special case for this transition before calling pickSingleSceneIn()."
+                )
+            }
+            fromSceneInScenes -> fromScene
+            toSceneInScenes -> toScene
+            else -> null
         }
     }
 }
@@ -312,8 +306,12 @@
         transition: TransitionState.Transition,
         fromSceneZIndex: Float,
         toSceneZIndex: Float,
-    ): SceneKey {
-        return if (scenes.contains(transition.toScene)) transition.toScene else transition.fromScene
+    ): SceneKey? {
+        return when {
+            scenes.contains(transition.toScene) -> transition.toScene
+            scenes.contains(transition.fromScene) -> transition.fromScene
+            else -> null
+        }
     }
 }
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 2453e25..b7fc91c 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.compose.animation.scene
 
+import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.Spring
 import androidx.compose.animation.core.spring
 import androidx.compose.animation.core.tween
@@ -40,11 +41,14 @@
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
 import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.layout.intermediateLayout
 import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.test.assertIsNotDisplayed
+import androidx.compose.ui.test.assertPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
@@ -53,6 +57,9 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.TestScenes.SceneC
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
@@ -175,6 +182,64 @@
     }
 
     @Test
+    fun elementsNotInTransition_shouldNotBeDrawn() {
+        val nFrames = 20
+        val frameDuration = 16L
+        val tween = tween<Float>(nFrames * frameDuration.toInt())
+        val layoutSize = 100.dp
+        val elementSize = 50.dp
+        val elementOffset = 20.dp
+
+        lateinit var changeScene: (SceneKey) -> Unit
+
+        rule.testTransition(
+            from = SceneA,
+            to = SceneB,
+            transitionLayout = { currentScene, onChangeScene ->
+                changeScene = onChangeScene
+
+                SceneTransitionLayout(
+                    currentScene,
+                    onChangeScene,
+                    transitions {
+                        from(SceneA, to = SceneB) { spec = tween }
+                        from(SceneB, to = SceneC) { spec = tween }
+                    },
+
+                    // Disable interruptions so that the current transition is directly removed when
+                    // starting a new one.
+                    enableInterruptions = false,
+                ) {
+                    scene(SceneA) {
+                        Box(Modifier.size(layoutSize)) {
+                            // Transformed element
+                            Element(
+                                TestElements.Bar,
+                                elementSize,
+                                elementOffset,
+                            )
+                        }
+                    }
+                    scene(SceneB) { Box(Modifier.size(layoutSize)) }
+                    scene(SceneC) { Box(Modifier.size(layoutSize)) }
+                }
+            },
+        ) {
+            // Start transition from SceneA to SceneB
+            at(1 * frameDuration) {
+                onElement(TestElements.Bar).assertExists()
+
+                // Start transition from SceneB to SceneC
+                changeScene(SceneC)
+            }
+
+            at(2 * frameDuration) { onElement(TestElements.Bar).assertIsNotDisplayed() }
+
+            at(3 * frameDuration) { onElement(TestElements.Bar).assertDoesNotExist() }
+        }
+    }
+
+    @Test
     fun onlyMovingElements_noLayout_onlyPlacement() {
         val nFrames = 20
         val layoutSize = 100.dp
@@ -262,7 +327,7 @@
 
     @Test
     fun elementIsReusedBetweenScenes() {
-        var currentScene by mutableStateOf(TestScenes.SceneA)
+        var currentScene by mutableStateOf(SceneA)
         var sceneCState by mutableStateOf(0)
         val key = TestElements.Foo
         var nullableLayoutImpl: SceneTransitionLayoutImpl? = null
@@ -276,9 +341,9 @@
                     ),
                 onLayoutImpl = { nullableLayoutImpl = it },
             ) {
-                scene(TestScenes.SceneA) { /* Nothing */}
-                scene(TestScenes.SceneB) { Box(Modifier.element(key)) }
-                scene(TestScenes.SceneC) {
+                scene(SceneA) { /* Nothing */}
+                scene(SceneB) { Box(Modifier.element(key)) }
+                scene(SceneC) {
                     when (sceneCState) {
                         0 -> Row(Modifier.element(key)) {}
                         else -> {
@@ -297,21 +362,21 @@
         assertThat(layoutImpl.elements).isEmpty()
 
         // Scene B: element is in the map.
-        currentScene = TestScenes.SceneB
+        currentScene = SceneB
         rule.waitForIdle()
 
         assertThat(layoutImpl.elements.keys).containsExactly(key)
         val element = layoutImpl.elements.getValue(key)
-        assertThat(element.sceneStates.keys).containsExactly(TestScenes.SceneB)
+        assertThat(element.sceneStates.keys).containsExactly(SceneB)
 
         // Scene C, state 0: the same element is reused.
-        currentScene = TestScenes.SceneC
+        currentScene = SceneC
         sceneCState = 0
         rule.waitForIdle()
 
         assertThat(layoutImpl.elements.keys).containsExactly(key)
         assertThat(layoutImpl.elements.getValue(key)).isSameInstanceAs(element)
-        assertThat(element.sceneStates.keys).containsExactly(TestScenes.SceneC)
+        assertThat(element.sceneStates.keys).containsExactly(SceneC)
 
         // Scene C, state 1: the element is removed from the map.
         sceneCState = 1
@@ -399,14 +464,10 @@
 
         rule.setContent {
             SceneTransitionLayoutForTesting(
-                state =
-                    updateSceneTransitionLayoutState(
-                        currentScene = TestScenes.SceneA,
-                        onChangeScene = {}
-                    ),
+                state = updateSceneTransitionLayoutState(currentScene = SceneA, onChangeScene = {}),
                 onLayoutImpl = { nullableLayoutImpl = it },
             ) {
-                scene(TestScenes.SceneA) { Box(Modifier.element(key)) }
+                scene(SceneA) { Box(Modifier.element(key)) }
             }
         }
 
@@ -416,7 +477,7 @@
         // There is only Foo in the elements map.
         assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo)
         val fooElement = layoutImpl.elements.getValue(TestElements.Foo)
-        assertThat(fooElement.sceneStates.keys).containsExactly(TestScenes.SceneA)
+        assertThat(fooElement.sceneStates.keys).containsExactly(SceneA)
 
         key = TestElements.Bar
 
@@ -424,7 +485,7 @@
         rule.waitForIdle()
         assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Bar)
         val barElement = layoutImpl.elements.getValue(TestElements.Bar)
-        assertThat(barElement.sceneStates.keys).containsExactly(TestScenes.SceneA)
+        assertThat(barElement.sceneStates.keys).containsExactly(SceneA)
         assertThat(fooElement.sceneStates).isEmpty()
     }
 
@@ -452,14 +513,10 @@
             scrollScope = rememberCoroutineScope()
 
             SceneTransitionLayoutForTesting(
-                state =
-                    updateSceneTransitionLayoutState(
-                        currentScene = TestScenes.SceneA,
-                        onChangeScene = {}
-                    ),
+                state = updateSceneTransitionLayoutState(currentScene = SceneA, onChangeScene = {}),
                 onLayoutImpl = { nullableLayoutImpl = it },
             ) {
-                scene(TestScenes.SceneA) {
+                scene(SceneA) {
                     // The pages are full-size and beyondBoundsPageCount is 0, so at rest only one
                     // page should be composed.
                     HorizontalPager(
@@ -483,11 +540,11 @@
         assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo)
         val element = layoutImpl.elements.getValue(TestElements.Foo)
         val sceneValues = element.sceneStates
-        assertThat(sceneValues.keys).containsExactly(TestScenes.SceneA)
+        assertThat(sceneValues.keys).containsExactly(SceneA)
 
         // Get the ElementModifier node that should be reused later on when coming back to this
         // page.
-        val nodes = sceneValues.getValue(TestScenes.SceneA).nodes
+        val nodes = sceneValues.getValue(SceneA).nodes
         assertThat(nodes).hasSize(1)
         val node = nodes.single()
 
@@ -508,10 +565,10 @@
         val newSceneValues = newElement.sceneStates
         assertThat(newElement).isNotEqualTo(element)
         assertThat(newSceneValues).isNotEqualTo(sceneValues)
-        assertThat(newSceneValues.keys).containsExactly(TestScenes.SceneA)
+        assertThat(newSceneValues.keys).containsExactly(SceneA)
 
         // The ElementModifier node should be the same as before.
-        val newNodes = newSceneValues.getValue(TestScenes.SceneA).nodes
+        val newNodes = newSceneValues.getValue(SceneA).nodes
         assertThat(newNodes).hasSize(1)
         val newNode = newNodes.single()
         assertThat(newNode).isSameInstanceAs(node)
@@ -557,7 +614,7 @@
 
         val state =
             MutableSceneTransitionLayoutState(
-                initialScene = TestScenes.SceneA,
+                initialScene = SceneA,
                 transitions = transitions(sceneTransitions),
             )
                 as MutableSceneTransitionLayoutStateImpl
@@ -568,10 +625,7 @@
                 state = state,
                 modifier = Modifier.size(layoutWidth, layoutHeight)
             ) {
-                scene(
-                    key = TestScenes.SceneA,
-                    userActions = mapOf(Swipe.Down to TestScenes.SceneB)
-                ) {
+                scene(key = SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
                     animateSceneFloatAsState(
                         value = animatedFloatRange.start,
                         key = TestValues.Value1,
@@ -579,7 +633,7 @@
                     )
                     Spacer(Modifier.fillMaxSize())
                 }
-                scene(TestScenes.SceneB) {
+                scene(SceneB) {
                     val animatedFloat by
                         animateSceneFloatAsState(
                             value = animatedFloatRange.endInclusive,
@@ -619,7 +673,7 @@
                 layoutWidth = layoutWidth,
                 layoutHeight = layoutHeight,
                 sceneTransitions = {
-                    overscroll(TestScenes.SceneB, Orientation.Vertical) {
+                    overscroll(SceneB, Orientation.Vertical) {
                         // On overscroll 100% -> Foo should translate by overscrollTranslateY
                         translate(TestElements.Foo, y = overscrollTranslateY)
                     }
@@ -671,10 +725,10 @@
 
         val state =
             MutableSceneTransitionLayoutState(
-                initialScene = TestScenes.SceneB,
+                initialScene = SceneB,
                 transitions =
                     transitions {
-                        overscroll(TestScenes.SceneB, Orientation.Vertical) {
+                        overscroll(SceneB, Orientation.Vertical) {
                             translate(TestElements.Foo, y = overscrollTranslateY)
                         }
                     }
@@ -687,8 +741,8 @@
                 state = state,
                 modifier = Modifier.size(layoutWidth, layoutHeight)
             ) {
-                scene(TestScenes.SceneA) { Spacer(Modifier.fillMaxSize()) }
-                scene(TestScenes.SceneB, userActions = mapOf(Swipe.Up to TestScenes.SceneA)) {
+                scene(SceneA) { Spacer(Modifier.fillMaxSize()) }
+                scene(SceneB, userActions = mapOf(Swipe.Up to SceneA)) {
                     Box(
                         Modifier
                             // Unconsumed scroll gesture will be intercepted by STL
@@ -746,7 +800,7 @@
                 layoutWidth = layoutWidth,
                 layoutHeight = layoutHeight,
                 sceneTransitions = {
-                    overscroll(TestScenes.SceneB, Orientation.Vertical) {
+                    overscroll(SceneB, Orientation.Vertical) {
                         // On overscroll 100% -> Foo should translate by layoutHeight
                         translate(TestElements.Foo, y = { absoluteDistance })
                     }
@@ -803,7 +857,7 @@
                             stiffness = Spring.StiffnessLow,
                         )
 
-                    overscroll(TestScenes.SceneB, Orientation.Vertical) {
+                    overscroll(SceneB, Orientation.Vertical) {
                         // On overscroll 100% -> Foo should translate by layoutHeight
                         translate(TestElements.Foo, y = { absoluteDistance })
                     }
@@ -844,4 +898,125 @@
         assertThat(transition.bouncingScene).isEqualTo(transition.toScene)
         assertThat(animatedFloat).isEqualTo(100f)
     }
+
+    @Test
+    fun elementIsUsingLastTransition() {
+        // 4 frames of animation.
+        val duration = 4 * 16
+
+        val state =
+            MutableSceneTransitionLayoutState(
+                SceneA,
+                transitions {
+                    // Foo is at the top left corner of scene A. We make it disappear during A => B
+                    // to the right edge so it translates to the right.
+                    from(SceneA, to = SceneB) {
+                        spec = tween(duration, easing = LinearEasing)
+                        translate(
+                            TestElements.Foo,
+                            edge = Edge.Right,
+                            startsOutsideLayoutBounds = false,
+                        )
+                    }
+
+                    // Bar is at the top right corner of scene C. We make it appear during B => C
+                    // from the left edge so it translates to the right at same time as Foo.
+                    from(SceneB, to = SceneC) {
+                        spec = tween(duration, easing = LinearEasing)
+                        translate(
+                            TestElements.Bar,
+                            edge = Edge.Left,
+                            startsOutsideLayoutBounds = false,
+                        )
+                    }
+                }
+            )
+
+        val layoutSize = 150.dp
+        val elemSize = 50.dp
+        lateinit var coroutineScope: CoroutineScope
+        rule.setContent {
+            coroutineScope = rememberCoroutineScope()
+
+            SceneTransitionLayout(state) {
+                scene(SceneA) {
+                    Box(Modifier.size(layoutSize)) {
+                        Box(
+                            Modifier.align(Alignment.TopStart)
+                                .element(TestElements.Foo)
+                                .size(elemSize)
+                        )
+                    }
+                }
+                scene(SceneB) {
+                    // Empty scene.
+                    Box(Modifier.size(layoutSize))
+                }
+                scene(SceneC) {
+                    Box(Modifier.size(layoutSize)) {
+                        Box(
+                            Modifier.align(Alignment.BottomEnd)
+                                .element(TestElements.Bar)
+                                .size(elemSize)
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.mainClock.autoAdvance = false
+
+        // Trigger A => B then directly B => C so that Foo and Bar move together to the right edge.
+        rule.runOnUiThread {
+            state.setTargetScene(SceneB, coroutineScope)
+            state.setTargetScene(SceneC, coroutineScope)
+        }
+
+        val transitions = state.currentTransitions
+        assertThat(transitions).hasSize(2)
+        assertThat(transitions[0].fromScene).isEqualTo(SceneA)
+        assertThat(transitions[0].toScene).isEqualTo(SceneB)
+        assertThat(transitions[0].progress).isEqualTo(0f)
+
+        assertThat(transitions[1].fromScene).isEqualTo(SceneB)
+        assertThat(transitions[1].toScene).isEqualTo(SceneC)
+        assertThat(transitions[1].progress).isEqualTo(0f)
+
+        // First frame: both are at x = 0dp. For the whole transition, Foo is at y = 0dp and Bar is
+        // at y = layoutSize - elementSoze = 100dp.
+        rule.mainClock.advanceTimeByFrame()
+        rule.waitForIdle()
+        rule.onNode(isElement(TestElements.Foo)).assertPositionInRootIsEqualTo(0.dp, 0.dp)
+        rule.onNode(isElement(TestElements.Bar)).assertPositionInRootIsEqualTo(0.dp, 100.dp)
+
+        // Advance to the second frame (25% of the transition): they are both translating
+        // horizontally to the final target (x = layoutSize - elemSize = 100dp), so they should now
+        // be at x = 25dp.
+        rule.mainClock.advanceTimeByFrame()
+        rule.waitForIdle()
+        rule.onNode(isElement(TestElements.Foo)).assertPositionInRootIsEqualTo(25.dp, 0.dp)
+        rule.onNode(isElement(TestElements.Bar)).assertPositionInRootIsEqualTo(25.dp, 100.dp)
+
+        // Advance to the second frame (50% of the transition): they should now be at x = 50dp.
+        rule.mainClock.advanceTimeByFrame()
+        rule.waitForIdle()
+        rule.onNode(isElement(TestElements.Foo)).assertPositionInRootIsEqualTo(50.dp, 0.dp)
+        rule.onNode(isElement(TestElements.Bar)).assertPositionInRootIsEqualTo(50.dp, 100.dp)
+
+        // Advance to the third frame (75% of the transition): they should now be at x = 75dp.
+        rule.mainClock.advanceTimeByFrame()
+        rule.waitForIdle()
+        rule.onNode(isElement(TestElements.Foo)).assertPositionInRootIsEqualTo(75.dp, 0.dp)
+        rule.onNode(isElement(TestElements.Bar)).assertPositionInRootIsEqualTo(75.dp, 100.dp)
+
+        // Advance to the end of the animation. We can't really test the fourth frame because when
+        // pausing the clock, the layout/drawing code will still run (so elements will have their
+        // size/offset when there is no more transition running) but composition will not (so
+        // elements that should not be composed anymore will still be composed).
+        rule.mainClock.autoAdvance = true
+        rule.waitForIdle()
+        assertThat(state.currentTransitions).isEmpty()
+        rule.onNode(isElement(TestElements.Foo)).assertDoesNotExist()
+        rule.onNode(isElement(TestElements.Bar)).assertPositionInRootIsEqualTo(100.dp, 100.dp)
+    }
 }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt
index fb46a34..6745fbe 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementScenePickerTest.kt
@@ -38,8 +38,8 @@
     }
 
     @Test
-    fun toSceneNotInScenes() {
-        val picker = MovableElementScenePicker(scenes = emptySet())
+    fun fromSceneInScenes() {
+        val picker = MovableElementScenePicker(scenes = setOf(TestScenes.SceneA))
         assertThat(
                 picker.sceneDuringTransition(
                     TestElements.Foo,
@@ -50,4 +50,18 @@
             )
             .isEqualTo(TestScenes.SceneA)
     }
+
+    @Test
+    fun noneInScenes() {
+        val picker = MovableElementScenePicker(scenes = emptySet())
+        assertThat(
+                picker.sceneDuringTransition(
+                    TestElements.Foo,
+                    transition(from = TestScenes.SceneA, to = TestScenes.SceneB),
+                    fromSceneZIndex = 0f,
+                    toSceneZIndex = 1f,
+                )
+            )
+            .isEqualTo(null)
+    }
 }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 723a182..7836581 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -48,10 +48,14 @@
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.TestScenes.SceneC
 import com.android.compose.test.assertSizeIsEqualTo
 import com.android.compose.test.subjects.DpOffsetSubject
 import com.android.compose.test.subjects.assertThat
 import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -62,7 +66,7 @@
         private val LayoutSize = 300.dp
     }
 
-    private var currentScene by mutableStateOf(TestScenes.SceneA)
+    private var currentScene by mutableStateOf(SceneA)
     private lateinit var layoutState: SceneTransitionLayoutState
 
     // We use createAndroidComposeRule() here and not createComposeRule() because we need an
@@ -84,15 +88,15 @@
             modifier = Modifier.size(LayoutSize),
         ) {
             scene(
-                TestScenes.SceneA,
-                userActions = mapOf(Back to TestScenes.SceneB),
+                SceneA,
+                userActions = mapOf(Back to SceneB),
             ) {
                 Box(Modifier.fillMaxSize()) {
                     SharedFoo(size = 50.dp, childOffset = 0.dp, Modifier.align(Alignment.TopEnd))
                     Text("SceneA")
                 }
             }
-            scene(TestScenes.SceneB) {
+            scene(SceneB) {
                 Box(Modifier.fillMaxSize()) {
                     SharedFoo(
                         size = 100.dp,
@@ -102,7 +106,7 @@
                     Text("SceneB")
                 }
             }
-            scene(TestScenes.SceneC) {
+            scene(SceneC) {
                 Box(Modifier.fillMaxSize()) {
                     SharedFoo(
                         size = 150.dp,
@@ -144,42 +148,42 @@
         rule.onNodeWithText("SceneB").assertDoesNotExist()
         rule.onNodeWithText("SceneC").assertDoesNotExist()
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
 
         // Change to scene B. Only that scene is displayed.
-        currentScene = TestScenes.SceneB
+        currentScene = SceneB
         rule.onNodeWithText("SceneA").assertDoesNotExist()
         rule.onNodeWithText("SceneB").assertIsDisplayed()
         rule.onNodeWithText("SceneC").assertDoesNotExist()
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneB)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneB)
     }
 
     @Test
     fun testBack() {
         rule.setContent { TestContent() }
 
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
 
         rule.activity.onBackPressed()
         rule.waitForIdle()
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneB)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneB)
     }
 
     @Test
     fun testTransitionState() {
         rule.setContent { TestContent() }
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
 
         // We will advance the clock manually.
         rule.mainClock.autoAdvance = false
 
         // Change the current scene. Until composition is triggered, this won't change the layout
         // state.
-        currentScene = TestScenes.SceneB
+        currentScene = SceneB
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
 
         // On the next frame, we will recompose because currentScene changed, which will start the
         // transition (i.e. it will change the transitionState to be a Transition) in a
@@ -187,8 +191,8 @@
         rule.mainClock.advanceTimeByFrame()
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Transition::class.java)
         val transition = layoutState.transitionState as TransitionState.Transition
-        assertThat(transition.fromScene).isEqualTo(TestScenes.SceneA)
-        assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+        assertThat(transition.fromScene).isEqualTo(SceneA)
+        assertThat(transition.toScene).isEqualTo(SceneB)
         assertThat(transition.progress).isEqualTo(0f)
 
         // Then, on the next frame, the animator we started gets its initial value and clock
@@ -216,7 +220,7 @@
         // B.
         rule.mainClock.advanceTimeByFrame()
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneB)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneB)
     }
 
     @Test
@@ -242,7 +246,7 @@
         // Go to scene B and let the animation start. See [testLayoutState()] and
         // [androidx.compose.ui.test.MainTestClock] to understand why we need to advance the clock
         // by 2 frames to be at the start of the animation.
-        currentScene = TestScenes.SceneB
+        currentScene = SceneB
         rule.mainClock.advanceTimeByFrame()
         rule.mainClock.advanceTimeByFrame()
 
@@ -251,7 +255,7 @@
 
         // Foo is shared between Scene A and Scene B, and is therefore placed/drawn in Scene B given
         // that B has a higher zIndex than A.
-        sharedFoo = rule.onNode(isElement(TestElements.Foo, TestScenes.SceneB))
+        sharedFoo = rule.onNode(isElement(TestElements.Foo, SceneB))
 
         // In scene B, foo is at the top start (x = 0, y = 0) of the layout and has a size of
         // 100.dp. We pause at the middle of the transition, so it should now be 75.dp given that we
@@ -273,7 +277,7 @@
             .of(DpOffset(25.dp, 25.dp))
 
         // Animate to scene C, let the animation start then go to the middle of the transition.
-        currentScene = TestScenes.SceneC
+        currentScene = SceneC
         rule.mainClock.advanceTimeByFrame()
         rule.mainClock.advanceTimeByFrame()
         rule.mainClock.advanceTimeBy(TestTransitionDuration / 2)
@@ -285,7 +289,7 @@
         val expectedLeft = 0.dp
         val expectedSize = 100.dp + (150.dp - 100.dp) * interpolatedProgress
 
-        sharedFoo = rule.onNode(isElement(TestElements.Foo, TestScenes.SceneC))
+        sharedFoo = rule.onNode(isElement(TestElements.Foo, SceneC))
         assertThat((layoutState.transitionState as TransitionState.Transition).progress)
             .isEqualTo(interpolatedProgress)
         sharedFoo.assertWidthIsEqualTo(expectedSize)
@@ -302,15 +306,15 @@
         // Wait for the transition to C to finish.
         rule.mainClock.advanceTimeBy(TestTransitionDuration)
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneC)
 
         // Go back to scene A. This should happen instantly (once the animation started, i.e. after
         // 2 frames) given that we use a snap() animation spec.
-        currentScene = TestScenes.SceneA
+        currentScene = SceneA
         rule.mainClock.advanceTimeByFrame()
         rule.mainClock.advanceTimeByFrame()
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
-        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneA)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(SceneA)
     }
 
     @Test
@@ -333,6 +337,94 @@
         }
     }
 
+    @Test
+    fun multipleTransitionsWillComposeMultipleScenes() {
+        val duration = 10 * 16L
+
+        var currentScene: SceneKey by mutableStateOf(SceneA)
+        lateinit var state: SceneTransitionLayoutState
+        rule.setContent {
+            state =
+                updateSceneTransitionLayoutState(
+                    currentScene = currentScene,
+                    onChangeScene = { currentScene = it },
+                    transitions =
+                        transitions {
+                            from(SceneA, to = SceneB) {
+                                spec = tween(duration.toInt(), easing = LinearEasing)
+                            }
+                            from(SceneB, to = SceneC) {
+                                spec = tween(duration.toInt(), easing = LinearEasing)
+                            }
+                        }
+                )
+
+            SceneTransitionLayout(state) {
+                scene(SceneA) { Box(Modifier.testTag("aRoot").fillMaxSize()) }
+                scene(SceneB) { Box(Modifier.testTag("bRoot").fillMaxSize()) }
+                scene(SceneC) { Box(Modifier.testTag("cRoot").fillMaxSize()) }
+            }
+        }
+
+        // Initial state: only A is composed.
+        rule.onNodeWithTag("aRoot").assertExists()
+        rule.onNodeWithTag("bRoot").assertDoesNotExist()
+        rule.onNodeWithTag("cRoot").assertDoesNotExist()
+
+        // Pause the clock so we can manually advance it.
+        rule.waitForIdle()
+        rule.mainClock.autoAdvance = false
+
+        // Start A => B and go to the middle of the transition.
+        currentScene = SceneB
+
+        // We need to tick 2 frames after changing [currentScene] before the animation actually
+        // starts.
+        rule.mainClock.advanceTimeByFrame()
+        rule.mainClock.advanceTimeByFrame()
+        rule.mainClock.advanceTimeBy(duration / 2)
+        rule.waitForIdle()
+        assertThat(state.currentTransition?.progress).isEqualTo(0.5f)
+
+        // A and B are composed.
+        rule.onNodeWithTag("aRoot").assertExists()
+        rule.onNodeWithTag("bRoot").assertExists()
+        rule.onNodeWithTag("cRoot").assertDoesNotExist()
+
+        // Start B => C.
+        currentScene = SceneC
+        rule.mainClock.advanceTimeByFrame()
+        rule.mainClock.advanceTimeByFrame()
+        rule.waitForIdle()
+        assertThat(state.currentTransition?.progress).isEqualTo(0f)
+
+        // A, B and C are composed.
+        rule.onNodeWithTag("aRoot").assertExists()
+        rule.onNodeWithTag("bRoot").assertExists()
+        rule.onNodeWithTag("cRoot").assertExists()
+
+        // Let A => B finish.
+        rule.mainClock.advanceTimeBy(duration / 2L)
+        assertThat(state.currentTransition?.progress).isEqualTo(0.5f)
+        rule.waitForIdle()
+
+        // B and C are composed.
+        rule.onNodeWithTag("aRoot").assertDoesNotExist()
+        rule.onNodeWithTag("bRoot").assertExists()
+        rule.onNodeWithTag("cRoot").assertExists()
+
+        // Let B => C finish.
+        rule.mainClock.advanceTimeBy(duration / 2L)
+        rule.mainClock.advanceTimeByFrame()
+        assertThat(state.currentTransition).isNull()
+        rule.waitForIdle()
+
+        // Only C is composed.
+        rule.onNodeWithTag("aRoot").assertDoesNotExist()
+        rule.onNodeWithTag("bRoot").assertDoesNotExist()
+        rule.onNodeWithTag("cRoot").assertExists()
+    }
+
     private fun SemanticsNodeInteraction.offsetRelativeTo(
         other: SemanticsNodeInteraction,
     ): DpOffset {
@@ -346,4 +438,28 @@
             )
         }
     }
+
+    @Test
+    fun userActionFromSceneAToSceneA_throwsNotSupported() {
+        val exception: IllegalStateException =
+            assertThrows(IllegalStateException::class.java) {
+                rule.setContent {
+                    SceneTransitionLayout(
+                        state =
+                            updateSceneTransitionLayoutState(
+                                currentScene = currentScene,
+                                onChangeScene = { currentScene = it },
+                                transitions = EmptyTestTransitions
+                            ),
+                        modifier = Modifier.size(LayoutSize),
+                    ) {
+                        // from SceneA to SceneA
+                        scene(SceneA, userActions = mapOf(Back to SceneA), content = {})
+                    }
+                }
+            }
+
+        assertThat(exception).hasMessageThat().contains(Back.toString())
+        assertThat(exception).hasMessageThat().contains(SceneA.debugName)
+    }
 }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index 003c572..f539a23 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -28,8 +28,8 @@
 import android.util.AttributeSet
 import android.util.MathUtils.constrainedMap
 import android.util.TypedValue
-import android.view.View
 import android.view.View.MeasureSpec.EXACTLY
+import android.view.View
 import android.widget.TextView
 import com.android.app.animation.Interpolators
 import com.android.internal.annotations.VisibleForTesting
@@ -88,11 +88,17 @@
     private var textAnimator: TextAnimator? = null
     private var onTextAnimatorInitialized: Runnable? = null
 
+    private var translateForCenterAnimation = false
+    private val parentWidth: Int
+        get() = (parent as View).measuredWidth
+
     // last text size which is not constrained by view height
     private var lastUnconstrainedTextSize: Float = Float.MAX_VALUE
     @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator =
         { layout, invalidateCb ->
             TextAnimator(layout, NUM_CLOCK_FONT_ANIMATION_STEPS, invalidateCb) }
+
+    // Used by screenshot tests to provide stability
     @VisibleForTesting var isAnimationEnabled: Boolean = true
     @VisibleForTesting var timeOverrideInMillis: Long? = null
 
@@ -116,14 +122,14 @@
         try {
             dozingWeightInternal = animatableClockViewAttributes.getInt(
                 R.styleable.AnimatableClockView_dozeWeight,
-                100
+                /* default = */ 100
             )
             lockScreenWeightInternal = animatableClockViewAttributes.getInt(
                 R.styleable.AnimatableClockView_lockScreenWeight,
-                300
+                /* default = */ 300
             )
             chargeAnimationDelay = animatableClockViewAttributes.getInt(
-                R.styleable.AnimatableClockView_chargeAnimationDelay, 200
+                R.styleable.AnimatableClockView_chargeAnimationDelay, /* default = */ 200
             )
         } finally {
             animatableClockViewAttributes.recycle()
@@ -134,12 +140,12 @@
             defStyleAttr, defStyleRes
         )
 
-        isSingleLineInternal =
-            try {
-                textViewAttributes.getBoolean(android.R.styleable.TextView_singleLine, false)
-            } finally {
-                textViewAttributes.recycle()
-            }
+        try {
+            isSingleLineInternal = textViewAttributes.getBoolean(
+                android.R.styleable.TextView_singleLine, /* default = */ false)
+        } finally {
+            textViewAttributes.recycle()
+        }
 
         refreshFormat()
     }
@@ -206,6 +212,7 @@
             super.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                     min(lastUnconstrainedTextSize, MeasureSpec.getSize(heightMeasureSpec) / 2F))
         }
+
         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
         val animator = textAnimator
         if (animator == null) {
@@ -215,30 +222,31 @@
         } else {
             animator.updateLayout(layout)
         }
+
         if (migratedClocks && hasCustomPositionUpdatedAnimation) {
             // Expand width to avoid clock being clipped during stepping animation
-            setMeasuredDimension(measuredWidth +
-                    MeasureSpec.getSize(widthMeasureSpec) / 2, measuredHeight)
+            val targetWidth = measuredWidth + MeasureSpec.getSize(widthMeasureSpec) / 2
+
+            // This comparison is effectively a check if we're in splitshade or not
+            translateForCenterAnimation = parentWidth > targetWidth
+            if (translateForCenterAnimation) {
+                setMeasuredDimension(targetWidth, measuredHeight)
+            }
+        } else {
+            translateForCenterAnimation = false
         }
     }
 
     override fun onDraw(canvas: Canvas) {
-        if (migratedClocks && hasCustomPositionUpdatedAnimation) {
-            canvas.save()
-            canvas.translate((parent as View).measuredWidth / 4F, 0F)
+        canvas.save()
+        if (translateForCenterAnimation) {
+            canvas.translate(parentWidth / 4f, 0f)
         }
+
         logger.d({ "onDraw($str1)"}) { str1 = text.toString() }
-        // Use textAnimator to render text if animation is enabled.
-        // Otherwise default to using standard draw functions.
-        if (isAnimationEnabled) {
-            // intentionally doesn't call super.onDraw here or else the text will be rendered twice
-            textAnimator?.draw(canvas)
-        } else {
-            super.onDraw(canvas)
-        }
-        if (migratedClocks && hasCustomPositionUpdatedAnimation) {
-            canvas.restore()
-        }
+        // intentionally doesn't call super.onDraw here or else the text will be rendered twice
+        textAnimator?.draw(canvas)
+        canvas.restore()
     }
 
     override fun invalidate() {
@@ -305,7 +313,7 @@
             weight = lockScreenWeight,
             textSize = -1f,
             color = lockScreenColor,
-            animate = isAnimationEnabled,
+            animate = true,
             duration = APPEAR_ANIM_DURATION,
             interpolator = Interpolators.EMPHASIZED_DECELERATE,
             delay = 0,
@@ -314,7 +322,7 @@
     }
 
     fun animateFoldAppear(animate: Boolean = true) {
-        if (isAnimationEnabled && textAnimator == null) {
+        if (textAnimator == null) {
             return
         }
         logger.d("animateFoldAppear")
@@ -331,7 +339,7 @@
             weight = dozingWeightInternal,
             textSize = -1f,
             color = dozingColor,
-            animate = animate && isAnimationEnabled,
+            animate = animate,
             interpolator = Interpolators.EMPHASIZED_DECELERATE,
             duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(),
             delay = 0,
@@ -350,7 +358,7 @@
                 weight = if (isDozing()) dozingWeight else lockScreenWeight,
                 textSize = -1f,
                 color = null,
-                animate = isAnimationEnabled,
+                animate = true,
                 duration = CHARGE_ANIM_DURATION_PHASE_1,
                 delay = 0,
                 onAnimationEnd = null
@@ -360,7 +368,7 @@
             weight = if (isDozing()) lockScreenWeight else dozingWeight,
             textSize = -1f,
             color = null,
-            animate = isAnimationEnabled,
+            animate = true,
             duration = CHARGE_ANIM_DURATION_PHASE_0,
             delay = chargeAnimationDelay.toLong(),
             onAnimationEnd = startAnimPhase2
@@ -373,7 +381,7 @@
             weight = if (isDozing) dozingWeight else lockScreenWeight,
             textSize = -1f,
             color = if (isDozing) dozingColor else lockScreenColor,
-            animate = animate && isAnimationEnabled,
+            animate = animate,
             duration = DOZE_ANIM_DURATION,
             delay = 0,
             onAnimationEnd = null
@@ -432,9 +440,6 @@
                 onAnimationEnd = onAnimationEnd
             )
             textAnimator?.glyphFilter = glyphFilter
-            if (color != null && !isAnimationEnabled) {
-                setTextColor(color)
-            }
         } else {
             // when the text animator is set, update its start values
             onTextAnimatorInitialized = Runnable {
@@ -449,9 +454,6 @@
                     onAnimationEnd = onAnimationEnd
                 )
                 textAnimator?.glyphFilter = glyphFilter
-                if (color != null && !isAnimationEnabled) {
-                    setTextColor(color)
-                }
             }
         }
     }
@@ -469,7 +471,7 @@
             weight = weight,
             textSize = textSize,
             color = color,
-            animate = animate && isAnimationEnabled,
+            animate = animate,
             interpolator = null,
             duration = duration,
             delay = delay,
@@ -527,9 +529,9 @@
      *   means it finished moving.
      */
     fun offsetGlyphsForStepClockAnimation(
-            clockStartLeft: Int,
-            clockMoveDirection: Int,
-            moveFraction: Float
+        clockStartLeft: Int,
+        clockMoveDirection: Int,
+        moveFraction: Float
     ) {
         val isMovingToCenter = if (isLayoutRtl) clockMoveDirection < 0 else clockMoveDirection > 0
         val currentMoveAmount = left - clockStartLeft
diff --git a/packages/SystemUI/lint-baseline.xml b/packages/SystemUI/lint-baseline.xml
new file mode 100644
index 0000000..4def93f
--- /dev/null
+++ b/packages/SystemUI/lint-baseline.xml
@@ -0,0 +1,32215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08">
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        mSettingsObserver = new SettingsObserver(context.getMainThreadHandler());"
+        errorLine2="                                                         ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java"
+            line="142"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                mContext.getMainExecutor().execute(() -> {"
+        errorLine2="                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="845"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="            mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+        errorLine2="                                                                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java"
+            line="208"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+        errorLine2="                                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java"
+            line="515"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        return context.getMainExecutor();"
+        errorLine2="                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java"
+            line="94"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                    mContext.getMainExecutor().execute(() -> {"
+        errorLine2="                             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1088"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                    mContext.getMainExecutor().execute(() -> {"
+        errorLine2="                             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1132"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                    mContext.getMainExecutor().execute(() -> {"
+        errorLine2="                             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1191"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                    mContext.getMainExecutor().execute(() -> {"
+        errorLine2="                             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1230"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                mContext.getMainExecutor().execute(() -> {"
+        errorLine2="                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3115"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                context.getMainThreadHandler(), this);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+            line="191"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+        errorLine2="                                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+            line="807"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="            mContext.getMainExecutor().execute(() ->"
+        errorLine2="                     ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+            line="575"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                mContext.getMainExecutor());"
+        errorLine2="                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+            line="918"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+        errorLine2="                                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="188"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="            new Handler(mContext.getMainLooper())) {"
+        errorLine2="                                 ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java"
+            line="63"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="            mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+        errorLine2="                                                                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+            line="256"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                mSessionFuture.addListener(this::onStartComplete, mContext.getMainExecutor());"
+        errorLine2="                                                                           ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureController.java"
+            line="182"
+            column="76"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        }, mContext.getMainExecutor());"
+        errorLine2="                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureController.java"
+            line="354"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="        mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+        errorLine2="                                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java"
+            line="230"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="            wifiManager.registerTrafficStateCallback(context.getMainExecutor(),"
+        errorLine2="                                                             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java"
+            line="73"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                context.getMainThreadHandler(), this);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+            line="156"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                mContext.getMainThreadHandler()) {"
+        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+            line="159"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedMainThread"
+        message="Replace with injected `@Main Executor`."
+        errorLine1="                context.mainExecutor.execute { unoccludeAnimator?.cancel() }"
+        errorLine2="                        ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt"
+            line="245"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onBackPressed`"
+        errorLine1="    override fun onBackPressed() {"
+        errorLine2="                 ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt"
+            line="143"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onBackPressed`"
+        errorLine1="    override fun onBackPressed() {"
+        errorLine2="                 ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt"
+            line="133"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onBackPressed`"
+        errorLine1="    override fun onBackPressed() {"
+        errorLine2="                 ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+            line="118"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onBackPressed`"
+        errorLine1="    override fun onBackPressed() {"
+        errorLine2="                 ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt"
+            line="126"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onDetachedFromWindow`"
+        errorLine1="        public void onDetachedFromWindow() {"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+            line="474"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onDetachedFromWindow`"
+        errorLine1="        public void onDetachedFromWindow() {"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+            line="381"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="MissingSuperCall"
+        message="Overriding method should call `super.onBind`"
+        errorLine1="    override fun onBind(intent: Intent): IBinder? {"
+        errorLine2="                 ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt"
+            line="74"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="WrongViewCast"
+        message="Unexpected implicit cast to `NotificationExpandButton`: layout tag was `ImageView`"
+        errorLine1="        mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java"
+            line="145"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="WrongViewCast"
+        message="Unexpected implicit cast to `NotificationActionListLayout`: layout tag was `LinearLayout`"
+        errorLine1="        mActions = mView.findViewById(com.android.internal.R.id.actions);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java"
+            line="180"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.volume.panel.ui.VolumePanelUiEvent"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt"
+            line="23"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The shared layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.statusbar.pipeline.satellite.ui.DeviceBasedSatelliteBindableIcon"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/icons/shared/BindableIconsRegistry.kt"
+            line="21"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.volume.panel.ui.VolumePanelUiEvent"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt"
+            line="23"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.media.controls.domain.pipeline.MediaDataManager"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalMediaRepository.kt"
+            line="24"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt"
+            line="23"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt"
+            line="24"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt"
+            line="25"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.deviceentry.ui.binder.LiftToRunFaceAuthBinder"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt"
+            line="26"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+            line="26"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+            line="27"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+            line="50"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+            line="51"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.power.domain.interactor.PowerInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+            line="59"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt"
+            line="34"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.controls.ui.ControlsActivity"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt"
+            line="34"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.controls.ui.ControlsUiController"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt"
+            line="35"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.keyguard.domain.interactor.InWindowLauncherUnlockAnimationInteractor"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/InWindowLauncherUnlockAnimationRepository.kt"
+            line="20"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt"
+            line="40"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListener.kt"
+            line="20"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+            line="30"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+            line="31"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+            line="32"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+            line="33"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+            line="25"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+            line="26"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+            line="27"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the domain layer."
+        errorLine1="import com.android.systemui.bouncer.domain.interactor.BouncerMessageAuditLogger"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt"
+            line="24"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The data layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.keyguard.ui.binder.SideFpsProgressBarViewBinder"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt"
+            line="25"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt"
+            line="26"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.media.controls.ui.view.MediaViewHolder"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+            line="81"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.user.data.source.UserRecord"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt"
+            line="24"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.media.controls.ui.view.MediaViewHolder"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt"
+            line="84"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt"
+            line="36"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.people.data.model.PeopleTileModel"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt"
+            line="29"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.people.data.repository.PeopleTileRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt"
+            line="30"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.people.data.repository.PeopleWidgetRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt"
+            line="31"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The domain layer may not depend on the ui layer."
+        errorLine1="import com.android.systemui.bouncer.ui.BouncerView"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+            line="38"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The shared layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.qs.pipeline.data.model.RestoreData"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt"
+            line="24"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The shared layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.qs.pipeline.data.repository.UserTileSpecRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt"
+            line="25"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.keyboard.data.repository.KeyboardRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt"
+            line="20"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The ui layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.keyboard.stickykeys.data.repository.StickyKeysRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt"
+            line="21"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="CleanArchitectureDependencyViolation"
+        message="The shared layer may not depend on the data layer."
+        errorLine1="import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository"
+        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt"
+            line="25"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class ActionReceiver("
+        errorLine2="      ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt"
+            line="50"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class GroupCoalescer implements Dumpable, PipelineDumpable {"
+        errorLine2="             ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java"
+            line="70"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class KeyguardIndicationRotateTextViewController extends"
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java"
+            line="62"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class LightBarTransitionsController implements Dumpable {"
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java"
+            line="48"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class LockIconView extends FrameLayout implements Dumpable {"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/LockIconView.java"
+            line="47"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class NotificationBackgroundView extends View implements Dumpable {"
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java"
+            line="47"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class NotificationStackScrollLayout"
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java"
+            line="151"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class PendingRemovalStore @Inject constructor("
+        errorLine2="      ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt"
+            line="19"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class QSContainerImpl extends FrameLayout implements Dumpable {"
+        errorLine2="             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java"
+            line="47"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class QSTileViewModelAdapter"
+        errorLine2="      ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt"
+            line="47"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class QSTileViewModelImpl&lt;DATA_TYPE>("
+        errorLine2="      ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+            line="72"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class RoundedCornerResDelegateImpl("
+        errorLine2="      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt"
+            line="48"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class StatusBarModePerDisplayRepositoryImpl"
+        errorLine2="      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt"
+            line="108"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public final class StatusBarTouchableRegionManager implements Dumpable {"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java"
+            line="61"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class SwipeHelper implements Gefingerpoken, Dumpable {"
+        errorLine2="             ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SwipeHelper.java"
+            line="64"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class SysUiState implements Dumpable {"
+        errorLine2="             ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/model/SysUiState.java"
+            line="38"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="class TableLogBuffer("
+        errorLine2="      ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+            line="78"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="open class UserBroadcastDispatcher("
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+            line="48"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="DumpableNotRegistered"
+        message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+        errorLine1="public class ViewState implements Dumpable {"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java"
+            line="47"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="MissingClass"
+        message="Class referenced in the layout file, `com.android.systemui.multishade.ui.view.MultiShadeView`, was not found in the project or the libraries"
+        errorLine1="&lt;com.android.systemui.multishade.ui.view.MultiShadeView"
+        errorLine2="^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/multi_shade.xml"
+            line="19"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="MissingClass"
+        message="Class referenced in the layout file, `com.android.systemui.biometrics.UdfpsEnrollView`, was not found in the project or the libraries"
+        errorLine1="&lt;com.android.systemui.biometrics.UdfpsEnrollView"
+        errorLine2="^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/udfps_enroll_view.xml"
+            line="17"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java"
+            line="47"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);"
+        errorLine2="                                          ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java"
+            line="166"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWm = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java"
+            line="52"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+            line="409"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                                mContext.getSystemService(StatusBarManager.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+            line="459"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                                mContext.getSystemService(StatusBarManager.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+            line="475"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        final StatusBarManager statusBarManager = mContext.getSystemService(StatusBarManager.class);"
+        errorLine2="                                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+            line="485"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="343"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="808"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java"
+            line="68"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            val jobScheduler = context.getSystemService(JobScheduler::class.java)"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt"
+            line="183"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = context.getSystemService(WindowManager.class);"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/BiometricPromptLayout.java"
+            line="67"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!"
+        errorLine2="                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt"
+            line="91"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        val windowManager = requireNotNull(view.context.getSystemService(WindowManager::class.java))"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt"
+            line="76"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            requireNotNull(view.context.getSystemService(AccessibilityManager::class.java))"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt"
+            line="78"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="114"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        return applicationContext.getSystemService(Context.EUICC_SERVICE) as EuiccManager?"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorModule.kt"
+            line="54"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt"
+            line="167"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java"
+            line="74"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java"
+            line="77"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUiModeManager = mContext.getSystemService(UiModeManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="856"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);"
+        errorLine2="                                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="864"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService("
+        errorLine2="                                                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="875"
+            column="63"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="879"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="885"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="2913"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    it.context.getSystemService(InputMethodManager::class.java)"
+        errorLine2="                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt"
+            line="80"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        InputManager inputManager = mContext.getSystemService(InputManager.class);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java"
+            line="520"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java"
+            line="66"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mClipboardManager = context.getSystemService(ClipboardManager.class);"
+        errorLine2="                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java"
+            line="37"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            val am = context.getSystemService(ActivityManager::class.java)"
+        errorLine2="                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt"
+            line="48"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        context.getSystemService(AccessibilityManager::class.java)"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt"
+            line="26"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        val imeManager = view.context.getSystemService(InputMethodManager::class.java)!!"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt"
+            line="36"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                .getSystemService(android.telecom.TelecomManager::class.java)!!"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+            line="154"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                .getSystemService(WindowManager.class);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/display/DisplayHelper.java"
+            line="50"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        final PowerManager pm = getSystemService(PowerManager.class);"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeService.java"
+            line="119"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        context.getSystemService(Context.WINDOW_SERVICE) as WindowManager"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DragToInteractView.kt"
+            line="90"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        return mContext.getSystemService(InputManager.class)"
+        errorLine2="                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java"
+            line="1205"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mClipboardManager = requireNonNull(getSystemService(ClipboardManager.class));"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java"
+            line="61"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        InputMethodManager imm = getSystemService(InputMethodManager.class);"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java"
+            line="133"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    (AccessibilityManager) getContext().getSystemService("
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="2504"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mTetheringManager = context.getSystemService(TetheringManager.class);"
+        errorLine2="                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java"
+            line="105"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java"
+            line="106"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="77"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            mWallpaperManager = getDisplayContext().getSystemService(WallpaperManager.class);"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+            line="181"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            getDisplayContext().getSystemService(DisplayManager.class)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+            line="188"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                DisplayManager displayManager = context.getSystemService(DisplayManager.class);"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+            line="198"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    .getSystemService(WindowManager.class)"
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+            line="518"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mWindowContext.getSystemService(WindowManager.class);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+            line="508"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java"
+            line="46"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java"
+            line="109"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java"
+            line="148"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                        context.getSystemService(TelephonyManager.class).createForSubscriptionId("
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java"
+            line="963"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+            line="177"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            this.mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+            line="154"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+            line="858"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            this.mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="141"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        final InputManager inputManager = mContext.getSystemService(InputManager.class);"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="353"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService("
+        errorLine2="                                                            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="601"
+            column="61"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        InputManager im = context.getSystemService(InputManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java"
+            line="206"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        uiBgExecutor.execute(() -> mMediaRouter = mContext.getSystemService(MediaRouter.class));"
+        errorLine2="                                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java"
+            line="109"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mDisplayService = mContext.getSystemService(DisplayManager.class);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java"
+            line="110"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mEuiccManager = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java"
+            line="87"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java"
+            line="105"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                message = mContext.getSystemService(DevicePolicyManager.class).getResources()"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java"
+            line="765"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                message = mContext.getSystemService(DevicePolicyManager.class).getResources()"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java"
+            line="788"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);"
+        errorLine2="                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1528"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mContext.getSystemService(PowerManager.class).wakeUp(mSystemClock.uptimeMillis(),"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1715"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                final UserManager um = (UserManager) mContext.getSystemService("
+        errorLine2="                                                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="2684"
+            column="63"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="2736"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);"
+        errorLine2="                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3413"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                        getApplicationContext().getSystemService(LauncherApps.class);"
+        errorLine2="                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java"
+            line="163"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            NotificationManager notiMan = mContext.getSystemService(NotificationManager.class);"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java"
+            line="96"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        WindowManager windowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java"
+            line="435"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        context.getSystemService(Context.STATUS_BAR_SERVICE) as StatusBarManager"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+            line="237"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java"
+            line="192"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java"
+            line="206"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    windowContext.getSystemService(AccessibilityManager.class),"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java"
+            line="163"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    windowContext.getSystemService(WindowManager.class),"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java"
+            line="164"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java"
+            line="215"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+            line="111"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+            line="112"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                            .getSystemService(android.app.Service.STATUS_BAR_SERVICE);"
+        errorLine2="                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java"
+            line="81"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        context.getSystemService(Context.STATUS_BAR_SERVICE) as StatusBarManager"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt"
+            line="201"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="    val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt"
+            line="46"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        final UserManager um = mContext.getSystemService(UserManager.class);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java"
+            line="881"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt"
+            line="68"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt"
+            line="159"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mNotificationManager = context.getSystemService(NotificationManager.class);"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java"
+            line="253"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mStatusBarManager = context.getSystemService(StatusBarManager.class);"
+        errorLine2="                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java"
+            line="254"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);"
+        errorLine2="                                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java"
+            line="77"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mDisplayManager = mContext.getSystemService(DisplayManager.class);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java"
+            line="142"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        return context.getSystemService(WindowManager.class);"
+        errorLine2="                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java"
+            line="72"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            WindowManager wm = getContext().getSystemService(WindowManager.class);"
+        errorLine2="                                            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+            line="729"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        WindowManager wm = getContext().getSystemService(WindowManager.class);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+            line="830"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mManager = getHost().getUserContext().getSystemService(ColorDisplayManager.class);"
+        errorLine2="                                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java"
+            line="136"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        final NotificationManager nm = context.getSystemService(NotificationManager.class);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java"
+            line="57"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mContext.getSystemService(NotificationManager.class).deleteNotificationChannel(GENERAL);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java"
+            line="144"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                    (AudioManager) mCmd.context.getSystemService(Context.AUDIO_SERVICE);"
+        errorLine2="                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java"
+            line="93"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java"
+            line="508"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);"
+        errorLine2="                                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java"
+            line="285"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mKeyguardManager = context.getSystemService(KeyguardManager.class);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java"
+            line="286"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService("
+        errorLine2="                                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java"
+            line="316"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+            line="109"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService("
+        errorLine2="                                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+            line="110"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            mContext.getSystemService(InputMethodManager.class)"
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+            line="284"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+            line="145"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);"
+        errorLine2="                                            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleBackupFollowUpJob.java"
+            line="74"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mJobScheduler = mContext.getSystemService(JobScheduler.class);"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleBackupFollowUpJob.java"
+            line="92"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mPeopleManager = context.getSystemService(PeopleManager.class);"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+            line="204"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                JobScheduler jobScheduler = mContext.getSystemService(JobScheduler.class);"
+        errorLine2="                                                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+            line="1134"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java"
+            line="190"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mNoMan = mContext.getSystemService(NotificationManager.class);"
+        errorLine2="                          ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="200"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="201"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mKeyguard = mContext.getSystemService(KeyguardManager.class);"
+        errorLine2="                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="202"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mPowerManager = context.getSystemService(PowerManager::class.java)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt"
+            line="125"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                        mUserTracker.getUserContext().getSystemService(ClipboardManager.class);"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java"
+            line="77"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        WindowManager wm = this.mPanelView.getContext().getSystemService(WindowManager.class);"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java"
+            line="527"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mInputMethodManager = targetContext.getSystemService(InputMethodManager.class);"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java"
+            line="1111"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java"
+            line="484"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java"
+            line="144"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+            line="113"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mContext.getSystemService(Context.WINDOW_SERVICE);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+            line="115"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        NotificationManager notificationManager = context.getSystemService("
+        errorLine2="                                                          ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java"
+            line="36"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        DevicePolicyManager devicePolicyManager = context.getSystemService("
+        errorLine2="                                                          ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java"
+            line="38"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            final WindowManager wm = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java"
+            line="311"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                context.getSystemService(Context.DEVICE_POLICY_SERVICE);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+            line="140"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                context.getSystemService(Context.CONNECTIVITY_SERVICE);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+            line="142"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mVpnManager = context.getSystemService(VpnManager.class);"
+        errorLine2="                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+            line="143"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+            line="145"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LauncherApps apps = getContext().getSystemService(LauncherApps.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java"
+            line="61"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            getSystemService(SliceManager.class).grantPermissionFromUser(mUri, mCallingPkg,"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java"
+            line="108"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mKeyguardManager = context.getSystemService(KeyguardManager.class);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java"
+            line="159"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mKeyguardManager = context.getSystemService(KeyguardManager.class);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java"
+            line="110"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mA11yManager = (AccessibilityManager) mContext.getSystemService("
+        errorLine2="                                                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+            line="215"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mContext.getSystemService(InputManager.class)"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+            line="479"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mContext.getSystemService(PowerManager.class).goToSleep(SystemClock.uptimeMillis(),"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+            line="509"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                context.getSystemService(WallpaperManager.class),"
+        errorLine2="                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java"
+            line="62"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mDisplayManager = mContext.getSystemService(DisplayManager.class);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java"
+            line="176"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        return usercontext.getSystemService(UserManager.class).isPrivateProfile();"
+        errorLine2="                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java"
+            line="591"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TimeoutHandler.java"
+            line="96"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java"
+            line="104"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="            DisplayManager mDisplayManager = mContext.getSystemService(DisplayManager.class);"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java"
+            line="122"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        view.getContext().getSystemService(WindowManager.class)"
+        errorLine2="                          ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java"
+            line="48"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mView.getContext().getSystemService(WindowManager.class);"
+        errorLine2="                                            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java"
+            line="57"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUiModeManager = host.getUserContext().getSystemService(UiModeManager.class);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java"
+            line="88"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUsbPort = port.getUsbPort(getSystemService(UsbManager.class));"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java"
+            line="60"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        LayoutInflater inflater = getSystemService(LayoutInflater.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java"
+            line="102"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        return requireNotNull(context.getSystemService(serviceType))"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/utils/UserScopedService.kt"
+            line="64"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mCaptioningManager.set(userContext.getSystemService(CaptioningManager.class));"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+            line="343"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+            line="342"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+            line="343"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        return context.getSystemService(PowerManager.class)"
+        errorLine2="                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java"
+            line="93"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWm = context.getSystemService(WindowManager.class);"
+        errorLine2="                      ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="279"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                .getSystemService(AccessibilityManager.class);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="776"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+            line="140"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mWindowManager = mContext.getSystemService(WindowManager.class);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+            line="141"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="                mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);"
+        errorLine2="                                              ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java"
+            line="203"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java"
+            line="114"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="140"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="155"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NonInjectedService"
+        message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+        errorLine1="        mUserManager = context.getSystemService(UserManager.class);"
+        errorLine2="                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="158"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                = Settings.Global.getUriFor(Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS);"
+        errorLine2="                                  ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java"
+            line="148"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                final String value = Settings.Global.getString(mContext.getContentResolver(),"
+        errorLine2="                                                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java"
+            line="169"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                    Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),"
+        errorLine2="                                    ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/animation/data/repository/AnimationStatusRepository.kt"
+            line="62"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="                Settings.System.getUriFor(SHOW_BATTERY_PERCENT),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java"
+            line="215"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java"
+            line="223"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="        mHasPercentage = Settings.System.getInt(getContext().getContentResolver(),"
+        errorLine2="                                         ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java"
+            line="53"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="        Settings.System.putInt(getContext().getContentResolver(), SHOW_BATTERY_PERCENT, v ? 1 : 0);"
+        errorLine2="                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java"
+            line="89"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java"
+            line="73"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java"
+            line="668"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.putInt(mContext.getContentResolver(),"
+        errorLine2="                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="2917"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        return Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                               ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java"
+            line="152"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                                                 ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java"
+            line="167"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                &amp;&amp; Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java"
+            line="169"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            Settings.Secure.putInt(mContext.getContentResolver(),"
+        errorLine2="                            ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java"
+            line="173"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Settings.Secure.DOZE_QUICK_PICKUP_GESTURE);"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java"
+            line="475"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Settings.Secure.DOZE_PICK_UP_GESTURE);"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java"
+            line="477"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Settings.Secure.DOZE_ALWAYS_ON);"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java"
+            line="479"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BUBBLES);"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java"
+            line="80"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="424"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="                        Settings.System.getString("
+        errorLine2="                                        ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+            line="2328"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="                Settings.System.getUriFor(Settings.System.TIME_12_24),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+            line="2462"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        return Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                               ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+            line="3051"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+            line="3069"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);"
+        errorLine2="                                           ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1564"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);"
+        errorLine2="                                    ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1571"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        soundPath = Settings.Global.getString(cr, Settings.Global.TRUSTED_SOUND);"
+        errorLine2="                                    ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1578"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        Settings.Secure.getInt("
+        errorLine2="                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+            line="157"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getString(getContext().getContentResolver(),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java"
+            line="254"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="559"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),"
+        errorLine2="                                                                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java"
+            line="200"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        mContext.getContentResolver().registerContentObserver(Global.getUriFor("
+        errorLine2="                                                                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java"
+            line="202"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="                Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING), false,"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NaturalScrollingSettingObserver.kt"
+            line="55"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+            line="245"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+            line="248"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+            line="251"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+            line="254"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            Settings.Secure.putString(mCurrentUserContext.getContentResolver(),"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java"
+            line="139"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1048"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        if (&quot;1&quot;.equals(Settings.Global.getString(mContext.getContentResolver(),"
+        errorLine2="                                       ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java"
+            line="117"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        final String soundPath = Settings.Global.getString(context.getContentResolver(),"
+        errorLine2="                                                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java"
+            line="61"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            Settings.Secure.getUriFor(LOCK_SCREEN_SHOW_NOTIFICATIONS);"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+            line="108"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            Settings.Secure.getUriFor(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+            line="110"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        final int showDismissSetting =  Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+            line="298"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+            line="3664"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            final String config = Settings.Global.getString(getContext().getContentResolver(),"
+        errorLine2="                                                  ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java"
+            line="270"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,"
+        errorLine2="                                         ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="352"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                &amp;&amp; Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) > 0;"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="358"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                        Settings.Global.putInt("
+        errorLine2="                                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="674"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                        Settings.Global.putInt("
+        errorLine2="                                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="678"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        resolver.registerContentObserver(Settings.Global.getUriFor("
+        errorLine2="                                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="183"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="198"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="209"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        mEnableSkinTemperatureWarning = Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="556"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        mEnableUsbTemperatureAlarm = Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                                     ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="591"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            bootCount = Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="625"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        pw.println(Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="679"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED), false,"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java"
+            line="179"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        return (Settings.Global.getInt(cr, Settings.Global.DEVICE_PROVISIONED, 0) != 0) &amp;&amp;"
+        errorLine2="                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java"
+            line="131"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);"
+        errorLine2="                                 ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java"
+            line="132"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="                mOriginalShowTaps = Settings.System.getInt("
+        errorLine2="                                                    ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java"
+            line="163"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="        Settings.System.putInt(getContentResolver(), Settings.System.SHOW_TOUCHES, value);"
+        errorLine2="                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java"
+            line="472"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        return Settings.Secure.getInt(mContext.createContextAsUser(owner, 0)"
+        errorLine2="                               ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java"
+            line="959"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),"
+        errorLine2="                                                 ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureController.java"
+            line="179"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                    Settings.Secure.getUriFor(mKey), /* notifyForDescendants= */"
+        errorLine2="                                    ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java"
+            line="84"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        return Settings.Secure.getUriFor(name);"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java"
+            line="51"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        return Settings.Secure.putString(mContentResolver, name, value, overrideableByRestore);"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java"
+            line="62"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        return Settings.Secure.putString(mContentResolver, name, value, tag, makeDefault);"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java"
+            line="81"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="        return Settings.System.getUriFor(name);"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java"
+            line="51"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="        return Settings.System.putString(mContentResolver, name, value, overrideableByRestore);"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java"
+            line="62"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SystemSettings instead"
+        errorLine1="        mLessRows = ((Settings.System.getInt(context.getContentResolver(), &quot;qs_less_rows&quot;, 0) != 0)"
+        errorLine2="                                      ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java"
+            line="66"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        String current = Settings.Secure.getString(mContext.getContentResolver(),"
+        errorLine2="                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java"
+            line="100"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,"
+        errorLine2="                            ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java"
+            line="105"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                            Settings.Secure.putInt(getContext().getContentResolver(),"
+        errorLine2="                                            ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java"
+            line="163"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        Uri uri = Settings.Secure.getUriFor(key);"
+        errorLine2="                                  ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java"
+            line="217"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                    Secure.putInt(mContext.getContentResolver(),"
+        errorLine2="                           ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java"
+            line="321"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="            Settings.Secure.putString(getContext().getContentResolver(), key, value ? &quot;1&quot; : &quot;0&quot;);"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java"
+            line="57"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            return Settings.Global.getInt("
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt"
+            line="194"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),"
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt"
+            line="166"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            Settings.Global.getString("
+        errorLine2="                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt"
+            line="363"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            final int settingsFlag = Settings.Global.getInt(context.getContentResolver(),"
+        errorLine2="                                                     ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/Utils.java"
+            line="102"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        int flag = Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/Utils.java"
+            line="116"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="        final int zen = Settings.Global.getInt(mContext.getContentResolver(),"
+        errorLine2="                                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+            line="655"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.ZEN_MODE);"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+            line="1157"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG);"
+        errorLine2="                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+            line="1159"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        int ringerCount = Settings.Secure.getInt(cr, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, 0);"
+        errorLine2="                                          ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+            line="1397"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="        Settings.Secure.putInt(cr, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, ringerCount + 1);"
+        errorLine2="                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+            line="1398"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            return Global.getInt(mResolver, Global.DEVICE_PROVISIONED, 0) != 0;"
+        errorLine2="                          ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="372"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="                    Global.getUriFor(Global.DEVICE_PROVISIONED), false, this);"
+        errorLine2="                           ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="380"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                    Secure.getUriFor(Secure.USER_SETUP_COMPLETE), false, this, mUserId);"
+        errorLine2="                           ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="382"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a GlobalSettings instead"
+        errorLine1="            if (Global.getUriFor(Global.DEVICE_PROVISIONED).equals(uri)"
+        errorLine2="                       ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="389"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="StaticSettingsProvider"
+        message="`@Inject` a SecureSettings instead"
+        errorLine1="                    || Secure.getUriFor(Secure.USER_SETUP_COMPLETE).equals(uri)) {"
+        errorLine2="                              ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+            line="390"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="CanvasSize"
+        message="Calling `Canvas.getHeight()` is usually wrong; you should be calling `getHeight()` instead"
+        errorLine1="            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);"
+        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+            line="155"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="CanvasSize"
+        message="Calling `Canvas.getWidth()` is usually wrong; you should be calling `getWidth()` instead"
+        errorLine1="            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+            line="155"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="CustomViewStyleable"
+        message="By convention, the custom view (`KeyguardAffordanceView`) and the declare-styleable (`ImageView`) should have the same name (various editor features rely on this convention)"
+        errorLine1="        TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ImageView);"
+        errorLine2="                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java"
+            line="130"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="CustomViewStyleable"
+        message="By convention, the custom view (`PasswordTextView`) and the declare-styleable (`View`) should have the same name (various editor features rely on this convention)"
+        errorLine1="        TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.View);"
+        errorLine2="                                                             ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+            line="107"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="CustomViewStyleable"
+        message="By convention, the custom view (`ResizingSpace`) and the declare-styleable (`ViewGroup_Layout`) should have the same name (various editor features rely on this convention)"
+        errorLine1="        TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ViewGroup_Layout);"
+        errorLine2="                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/ResizingSpace.java"
+            line="35"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="CustomViewStyleable"
+        message="By convention, the custom view (`SeekBarWithIconButtonsView`) and the declare-styleable (`SeekBarWithIconButtonsView_Layout`) should have the same name (various editor features rely on this convention)"
+        errorLine1="                    R.styleable.SeekBarWithIconButtonsView_Layout,"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java"
+            line="87"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="CutPasteId"
+        message="The id `R.id.app_or_structure_spinner` has already been looked up in this method; possible cut &amp; paste error?"
+        errorLine1="        val anchor = parent.requireViewById&lt;View>(R.id.app_or_structure_spinner)"
+        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt"
+            line="611"
+            column="22"/>
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt"
+            line="601"
+            column="23"
+            message="First usage here"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="                    String.format(&quot;%dx%d&quot;, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="1839"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="            demoTime = String.format(&quot;%02d00&quot;, majorVersion % 24);"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="167"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="        mPredictionLog.log(String.format(&quot;Prediction [%d,%d,%d,%d,%f,%d]&quot;,"
+        errorLine2="                           ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java"
+            line="914"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="            (isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format("
+        errorLine2="                                                                                      ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java"
+            line="1034"
+            column="87"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="            cmd = args.get(1).toLowerCase();"
+        errorLine2="                              ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java"
+            line="75"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="                return String.format("
+        errorLine2="                       ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java"
+            line="65"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="                return String.format(&quot;{\&quot;type\&quot;:\&quot;tag\&quot;, \&quot;time\&quot;:%d, \&quot;tag\&quot;:\&quot;%s\&quot;, \&quot;info\&quot;:\&quot;%s\&quot;}&quot;,"
+        errorLine2="                       ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java"
+            line="85"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="            return String.format(FILENAME_PATTERN, time, fileExtension(format));"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java"
+            line="483"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="        return String.format(CONNECTED_DISPLAY_FILENAME_PATTERN, time, displayId,"
+        errorLine2="               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java"
+            line="485"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="                info.setContentDescription(mContentDescription.toLowerCase());"
+        errorLine2="                                                               ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="798"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="                    .setContentText(String.format("
+        errorLine2="                                    ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java"
+            line="107"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="        pw.println(String.format(&quot;      mCurrentView: id=%s (%dx%d) %s %f&quot;,"
+        errorLine2="                   ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+            line="1128"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="        pw.println(String.format(&quot;      disabled=0x%08x vertical=%s darkIntensity=%.2f&quot;,"
+        errorLine2="                   ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+            line="1134"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="            b.append(s.substring(1).toLowerCase());"
+        errorLine2="                                    ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+            line="139"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="            state.secondaryLabel = String.format(&quot;%d...&quot;, countdown);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java"
+            line="151"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="                    secondaryLabel = String.format(&quot;%d...&quot;, countDown)"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt"
+            line="64"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="                String colorString =  systemPalette.getPackageName().toLowerCase();"
+        errorLine2="                                                                     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java"
+            line="728"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="DuplicateDefinition"
+        message="`android:textSize` has already been defined in this `&lt;style>`"
+        errorLine1="        &lt;item name=&quot;android:textSize&quot;>@dimen/notification_importance_channel_text&lt;/item>"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="683"
+            column="15"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="680"
+            column="9"
+            message="Previously defined here"/>
+    </issue>
+
+    <issue
+        id="DuplicateDefinition"
+        message="`android:textSize` has already been defined in this `&lt;style>`"
+        errorLine1="        &lt;item name=&quot;android:textSize&quot;>@dimen/notification_importance_channel_group_text&lt;/item>"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="690"
+            column="15"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="687"
+            column="9"
+            message="Previously defined here"/>
+    </issue>
+
+    <issue
+        id="DuplicateDefinition"
+        message="`android:textSize` has already been defined in this `&lt;style>`"
+        errorLine1="        &lt;item name=&quot;android:textSize&quot;>@dimen/notification_importance_channel_group_text&lt;/item>"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="697"
+            column="15"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="694"
+            column="9"
+            message="Previously defined here"/>
+    </issue>
+
+    <issue
+        id="DuplicateIncludedIds"
+        message="Duplicate id @+id/wifi_combo, defined or included multiple times in layout/new_status_bar_wifi_group.xml: [layout/new_status_bar_wifi_group.xml defines @+id/wifi_combo, layout/new_status_bar_wifi_group.xml => layout/status_bar_wifi_group_inner.xml defines @+id/wifi_combo]"
+        errorLine1="    &lt;include layout=&quot;@layout/status_bar_wifi_group_inner&quot; />"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/new_status_bar_wifi_group.xml"
+            line="26"
+            column="5"
+            message="Duplicate id @+id/wifi_combo, defined or included multiple times in layout/new_status_bar_wifi_group.xml: [layout/new_status_bar_wifi_group.xml defines @+id/wifi_combo, layout/new_status_bar_wifi_group.xml => layout/status_bar_wifi_group_inner.xml defines @+id/wifi_combo]"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/new_status_bar_wifi_group.xml"
+            line="21"
+            column="5"
+            message="Defined here"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml"
+            line="52"
+            column="13"
+            message="Defined here, included via layout/new_status_bar_wifi_group.xml => layout/status_bar_wifi_group_inner.xml defines @+id/wifi_combo"/>
+    </issue>
+
+    <issue
+        id="ExactAlarm"
+        message="`USE_EXACT_ALARM` can only be used when targeting API level 33 or higher"
+        errorLine1="    &lt;uses-permission android:name=&quot;android.permission.USE_EXACT_ALARM&quot;/>"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="175"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;midGuideline&quot; in layout &quot;biometric_prompt_constraint_layout&quot; is missing from the following layout configurations: layout, layout-sw600dp (present in layout-land)"
+        errorLine1="        android:id=&quot;@+id/midGuideline&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml"
+            line="224"
+            column="9"
+            message="Occurrence in layout-land"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;volume_dialog_top_container&quot; in layout &quot;volume_dialog&quot; is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+        errorLine1="            android:id=&quot;@+id/volume_dialog_top_container&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+            line="41"
+            column="13"
+            message="Occurrence in layout"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+            line="42"
+            column="13"
+            message="Occurrence in layout-land"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;ringer&quot; in layout &quot;volume_dialog&quot; is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+        errorLine1="                android:id=&quot;@+id/ringer&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+            line="52"
+            column="17"
+            message="Occurrence in layout"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+            line="53"
+            column="17"
+            message="Occurrence in layout-land"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;ringer_icon&quot; in layout &quot;volume_dialog&quot; is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+        errorLine1="                    android:id=&quot;@+id/ringer_icon&quot;"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+            line="62"
+            column="21"
+            message="Occurrence in layout"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+            line="63"
+            column="21"
+            message="Occurrence in layout-land"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;settings_container&quot; in layout &quot;volume_dialog&quot; is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+        errorLine1="                    android:id=&quot;@+id/settings_container&quot;"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+            line="92"
+            column="21"
+            message="Occurrence in layout"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+            line="93"
+            column="21"
+            message="Occurrence in layout-land"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;settings&quot; in layout &quot;volume_dialog&quot; is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+        errorLine1="                        android:id=&quot;@+id/settings&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+            line="100"
+            column="25"
+            message="Occurrence in layout"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+            line="101"
+            column="25"
+            message="Occurrence in layout-land"/>
+    </issue>
+
+    <issue
+        id="InconsistentLayout"
+        message="The id &quot;volume_number&quot; in layout &quot;volume_dialog_row&quot; is missing from the following layout configurations: layout (present in layout-land-television)"
+        errorLine1="            android:id=&quot;@+id/volume_number&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml"
+            line="36"
+            column="13"
+            message="Occurrence in layout-land-television"/>
+    </issue>
+
+    <issue
+        id="KotlinNullnessAnnotation"
+        message="Do not use `@NonNull` in Kotlin; the nullability is already implied by the Kotlin type `PrintWriter` **not** ending with `?`"
+        errorLine1="    fun dump(@NonNull pw: PrintWriter, name: String) {"
+        errorLine2="             ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt"
+            line="112"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;notification_primary_text_color&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;notification_primary_text_color&quot;>@*android:color/notification_primary_text_color_dark&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="34"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;notification_section_header_label_color&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;notification_section_header_label_color&quot;>@color/GM2_grey_200&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="45"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;notification_channel_dialog_separator&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;notification_channel_dialog_separator&quot;>@color/GM2_grey_700&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="47"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;global_actions_text&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;global_actions_text&quot;>@color/GM2_grey_200&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="56"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;global_actions_alert_text&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;global_actions_alert_text&quot;>@color/GM2_red_300&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="59"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;media_divider&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;media_divider&quot;>#85ffffff&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="65"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;GM2_green_500&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;GM2_green_500&quot;>#FF41Af6A&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="81"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;GM2_blue_500&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;GM2_blue_500&quot;>#5195EA&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="82"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;GM2_yellow_500&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;GM2_yellow_500&quot;>#F5C518&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="84"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The color &quot;kg_user_switcher_selected_avatar_icon_color&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;color name=&quot;kg_user_switcher_selected_avatar_icon_color&quot;>#202124&lt;/color>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+            line="89"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The bool &quot;quick_settings_rssi_tile_capitalization&quot; in values-mcc262-mnc07 has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;bool name=&quot;quick_settings_rssi_tile_capitalization&quot;>false&lt;/bool>"
+        errorLine2="          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mcc262-mnc07/config.xml"
+            line="24"
+            column="11"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The bool &quot;quick_settings_rssi_tile_capitalization&quot; in values-mcc262-mnc08 has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;bool name=&quot;quick_settings_rssi_tile_capitalization&quot;>false&lt;/bool>"
+        errorLine2="          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mcc262-mnc08/config.xml"
+            line="24"
+            column="11"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The bool &quot;quick_settings_rssi_tile_capitalization&quot; in values-mcc262-mnc11 has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;bool name=&quot;quick_settings_rssi_tile_capitalization&quot;>false&lt;/bool>"
+        errorLine2="          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mcc262-mnc11/config.xml"
+            line="24"
+            column="11"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The integer &quot;quick_settings_user_time_settings_tile_span&quot; in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;integer name=&quot;quick_settings_user_time_settings_tile_span&quot;>2&lt;/integer>"
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/config.xml"
+            line="29"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The integer &quot;power_menu_max_columns&quot; in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;integer name=&quot;power_menu_max_columns&quot;>4&lt;/integer>"
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/config.xml"
+            line="35"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;ambient_indication_container_margin_top&quot; in values-h700dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;ambient_indication_container_margin_top&quot;>15dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-h700dp/dimens.xml"
+            line="19"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;ambient_indication_container_margin_top&quot; in values-h800dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;ambient_indication_container_margin_top&quot;>20dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-h800dp/dimens.xml"
+            line="19"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;volume_dialog_panel_height&quot; in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="  &lt;dimen name=&quot;volume_dialog_panel_height&quot;>190dp&lt;/dimen>"
+        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+            line="19"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;screenshot_bg_protection_height&quot; in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;screenshot_bg_protection_height&quot;>375dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-night/dimens.xml"
+            line="21"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;docked_divider_handle_width&quot; in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;docked_divider_handle_width&quot;>2dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+            line="22"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;docked_divider_handle_height&quot; in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;docked_divider_handle_height&quot;>16dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+            line="23"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;button_size&quot; in values-sw900dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;button_size&quot;>80dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw900dp/dimens.xml"
+            line="26"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;tv_volume_dialog_bubble_size&quot; in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="  &lt;dimen name=&quot;tv_volume_dialog_bubble_size&quot;>36dp&lt;/dimen>"
+        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+            line="28"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;tv_volume_dialog_row_padding&quot; in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="  &lt;dimen name=&quot;tv_volume_dialog_row_padding&quot;>6dp&lt;/dimen>"
+        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+            line="29"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;tv_volume_number_text_size&quot; in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="  &lt;dimen name=&quot;tv_volume_number_text_size&quot;>16sp&lt;/dimen>"
+        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+            line="30"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;tv_volume_seek_bar_thumb_diameter&quot; in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="  &lt;dimen name=&quot;tv_volume_seek_bar_thumb_diameter&quot;>16dp&lt;/dimen>"
+        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+            line="31"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;tv_volume_icons_size&quot; in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="  &lt;dimen name=&quot;tv_volume_icons_size&quot;>20dp&lt;/dimen>"
+        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+            line="32"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;volume_tool_tip_top_margin&quot; in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;volume_tool_tip_top_margin&quot;>12dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+            line="35"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;controls_activity_view_top_offset&quot; in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;controls_activity_view_top_offset&quot;>25dp&lt;/dimen>"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+            line="41"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingDefaultResource"
+        message="The dimen &quot;car_body2_size&quot; in values-h600dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+        errorLine1="    &lt;dimen name=&quot;car_body2_size&quot;>32sp&lt;/dimen> &lt;!-- B2 -->"
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-h600dp/dimens_car.xml"
+            line="19"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="MissingPrefix"
+        message="Attribute is missing the Android namespace prefix"
+        errorLine1="    &lt;item android:state_activated=&quot;true&quot; android_state_enabled=&quot;true&quot; android:color=&quot;@color/kg_user_switcher_activated_background_color&quot; />"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml"
+            line="20"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="SdCardPath"
+        message="Do not hardcode &quot;/sdcard/&quot;; use `Environment.getExternalStorageDirectory().getPath()` instead"
+        errorLine1="        ? new GestureRecorder(&quot;/sdcard/statusbar_gestures.dat&quot;)"
+        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="467"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="ShowToast"
+        message="Expected duration `Toast.LENGTH_SHORT` or `Toast.LENGTH_LONG`, a custom duration value is not supported"
+        errorLine1="                    500).show();"
+        errorLine2="                    ~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+            line="1894"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="    private static final SimpleDateFormat SSDF = new SimpleDateFormat(&quot;MM-dd HH:mm:ss.SSS&quot;);"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java"
+            line="52"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="            mContentDescriptionFormat = new SimpleDateFormat(format);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java"
+            line="452"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="            mClockFormat = new SimpleDateFormat(format);"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java"
+            line="483"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="    private static final SimpleDateFormat SSDF = new SimpleDateFormat(&quot;MM-dd HH:mm:ss.SSS&quot;);"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java"
+            line="60"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="    private static final SimpleDateFormat SSDF = new SimpleDateFormat(&quot;MM-dd HH:mm:ss.SSS&quot;);"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="119"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="        String today = new SimpleDateFormat(&quot;MM-dd&quot;).format(new Date());"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="503"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="        String fileName = new SimpleDateFormat(&quot;&apos;screen-&apos;yyyyMMdd-HHmmss&apos;.mp4&apos;&quot;)"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java"
+            line="329"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="Slices"
+        message="A slice should have a primary action set on one of its rows"
+        errorLine1="            ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java"
+            line="218"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="ValidFragment"
+        message="This fragment should provide a default constructor (a public constructor with no arguments) (`com.android.systemui.tuner.DemoModeFragment`)"
+        errorLine1="public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {"
+        errorLine2="             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="38"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ValidFragment"
+        message="This fragment should provide a default constructor (a public constructor with no arguments) (`com.android.systemui.qs.QSFragmentLegacy`)"
+        errorLine1="public class QSFragmentLegacy extends LifecycleFragment implements QS {"
+        errorLine2="             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java"
+            line="42"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ValidFragment"
+        message="Avoid non-default constructors in fragments: use a default constructor plus `Fragment#setArguments(Bundle)` instead"
+        errorLine1="    public QSFragmentLegacy("
+        errorLine2="           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java"
+            line="52"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="ValidFragment"
+        message="This fragment should provide a default constructor (a public constructor with no arguments) (`com.android.systemui.tuner.TunerFragment`)"
+        errorLine1="public class TunerFragment extends PreferenceFragment {"
+        errorLine2="             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java"
+            line="41"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="            animateAway(false /* sendReason */, 0 /* reason */);"
+        errorLine2="                                                ~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="778"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="        animateAway(false /* sendReason */, 0 /* reason */);"
+        errorLine2="                                            ~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="787"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="539"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_NEGATIVE,"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="544"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED,"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="549"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                        BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED,"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="555"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_ERROR,"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="560"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED,"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="565"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED,"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="570"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+        errorLine1="                        BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS,"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="576"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS, DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET, DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED, DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED, DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, DreamOverlayStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE"
+        errorLine1="        @DreamOverlayStatusBarView.StatusIconType int iconType = Resources.ID_NULL;"
+        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java"
+            line="287"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var desiredLocation: Int = -1"
+        errorLine2="                                                      ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="153"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation @VisibleForTesting var currentEndLocation: Int = -1"
+        errorLine2="                                                                    ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="159"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var currentStartLocation: Int = -1"
+        errorLine2="                                                           ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="165"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    if (location == desiredLocation) {"
+        errorLine2="                                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="542"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="543"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            startLocation != currentStartLocation ||"
+        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="974"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation = startLocation"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="979"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val startIsVisible = hostStates[currentStartLocation]?.visible ?: false"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="994"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            hostStates[currentStartLocation]?.showsOnlyActiveMedia ?: endShowsActive"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="1070"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            startLocation = currentStartLocation,"
+        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="1085"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            startLocation = currentStartLocation,"
+        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="1085"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                if (this.desiredLocation != desiredLocation) {"
+        errorLine2="                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="1111"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                this.desiredLocation = desiredLocation"
+        errorLine2="                     ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="1117"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            println(&quot;location: $desiredLocation&quot;)"
+        errorLine2="                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+            line="1325"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var crossFadeAnimationStartLocation = -1"
+        errorLine2="                                                                 ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="155"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var crossFadeAnimationEndLocation = -1"
+        errorLine2="                                                               ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="158"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var previousLocation = -1"
+        errorLine2="                                                  ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="226"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var desiredLocation = -1"
+        errorLine2="                                                 ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="228"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var currentAttachmentLocation = -1"
+        errorLine2="                                                           ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="235"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val startHost = getHost(previousLocation)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="337"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val startHost = getHost(previousLocation)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="337"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        if (mediaObject.location == desiredLocation) {"
+        errorLine2="                                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="618"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            desiredLocation = -1"
+        errorLine2="            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="621"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            desiredLocation = -1"
+        errorLine2="                              ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="621"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        if (mediaObject.location == currentAttachmentLocation) {"
+        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="623"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentAttachmentLocation = -1"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="624"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentAttachmentLocation = -1"
+        errorLine2="                                        ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="624"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                desiredLocation != this.desiredLocation || forceStateUpdate &amp;&amp; !blockLocationChanges"
+        errorLine2="                                        ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="671"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                if (this.desiredLocation >= 0 &amp;&amp; desiredLocation != this.desiredLocation) {"
+        errorLine2="                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="673"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                if (this.desiredLocation >= 0 &amp;&amp; desiredLocation != this.desiredLocation) {"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="673"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    previousLocation = this.desiredLocation"
+        errorLine2="                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="675"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    previousLocation = this.desiredLocation"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="675"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    previousLocation = this.desiredLocation"
+        errorLine2="                                            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="675"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                            previousLocation == LOCATION_LOCKSCREEN &amp;&amp;"
+        errorLine2="                            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="682"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        previousLocation = LOCATION_QQS"
+        errorLine2="                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="687"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                val isNewView = this.desiredLocation == -1"
+        errorLine2="                                     ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="690"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                this.desiredLocation = desiredLocation"
+        errorLine2="                     ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="691"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    !forceNoAnimation &amp;&amp; shouldAnimateTransition(desiredLocation, previousLocation)"
+        errorLine2="                                                                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="694"
+            column="83"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    !forceNoAnimation &amp;&amp; shouldAnimateTransition(desiredLocation, previousLocation)"
+        errorLine2="                                                                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="694"
+            column="83"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)"
+        errorLine2="                                                               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="695"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            if (previousLocation &lt; 0 || isNewView) {"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="715"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            val currentHost = getHost(desiredLocation)"
+        errorLine2="                                      ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="719"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            val currentHost = getHost(desiredLocation)"
+        errorLine2="                                      ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="719"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            val previousHost = getHost(previousLocation)"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="720"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            val previousHost = getHost(previousLocation)"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="720"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    currentAttachmentLocation != previousLocation ||"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="733"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    currentAttachmentLocation != previousLocation ||"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="733"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                var newCrossFadeStartLocation = previousLocation"
+        errorLine2="                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="751"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    if (currentAttachmentLocation == crossFadeAnimationEndLocation) {"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="753"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    if (currentAttachmentLocation == crossFadeAnimationEndLocation) {"
+        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="753"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        newCrossFadeStartLocation = crossFadeAnimationStartLocation"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="763"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        if (newCrossFadeStartLocation == desiredLocation) {"
+        errorLine2="                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="764"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                crossFadeAnimationStartLocation = newCrossFadeStartLocation"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="781"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                crossFadeAnimationStartLocation = newCrossFadeStartLocation"
+        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="781"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                crossFadeAnimationEndLocation = desiredLocation"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="782"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                crossFadeAnimationEndLocation = desiredLocation"
+        errorLine2="                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="782"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                crossFadeAnimationEndLocation = desiredLocation"
+        errorLine2="                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="782"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                adjustAnimatorForTransition(desiredLocation, previousLocation)"
+        errorLine2="                                            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="785"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                adjustAnimatorForTransition(desiredLocation, previousLocation)"
+        errorLine2="                                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="785"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                desiredLocation == LOCATION_QQS &amp;&amp;"
+        errorLine2="                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="812"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            desiredLocation == LOCATION_QS &amp;&amp;"
+        errorLine2="            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="830"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        var starthost = getHost(previousLocation)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="887"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        var starthost = getHost(previousLocation)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="887"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        var endHost = getHost(desiredLocation)"
+        errorLine2="                              ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="888"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        var endHost = getHost(desiredLocation)"
+        errorLine2="                              ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="888"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        return previousLocation != -1 &amp;&amp; desiredLocation != -1"
+        errorLine2="               ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="943"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        return previousLocation != -1 &amp;&amp; desiredLocation != -1"
+        errorLine2="                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="943"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            previousLocation == LOCATION_LOCKSCREEN &amp;&amp; desiredLocation == LOCATION_QS ||"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="957"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            previousLocation == LOCATION_LOCKSCREEN &amp;&amp; desiredLocation == LOCATION_QS ||"
+        errorLine2="                                                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="957"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                previousLocation == LOCATION_QS &amp;&amp; desiredLocation == LOCATION_LOCKSCREEN"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="958"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                previousLocation == LOCATION_QS &amp;&amp; desiredLocation == LOCATION_LOCKSCREEN"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="958"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        if (previousLocation == LOCATION_LOCKSCREEN &amp;&amp; desiredLocation == LOCATION_QQS) {"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="963"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        if (previousLocation == LOCATION_LOCKSCREEN &amp;&amp; desiredLocation == LOCATION_QQS) {"
+        errorLine2="                                                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="963"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        return getHost(previousLocation)?.visible == true &amp;&amp;"
+        errorLine2="                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="971"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        return getHost(previousLocation)?.visible == true &amp;&amp;"
+        errorLine2="                       ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="971"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            getHost(desiredLocation)?.visible == true"
+        errorLine2="                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="972"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            getHost(desiredLocation)?.visible == true"
+        errorLine2="                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="972"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val currentHost = getHost(desiredLocation)"
+        errorLine2="                                  ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="994"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val currentHost = getHost(desiredLocation)"
+        errorLine2="                                  ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="994"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val previousHost = getHost(previousLocation)"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="995"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        val previousHost = getHost(previousLocation)"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="995"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        getHost(desiredLocation)?.let {"
+        errorLine2="                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1015"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        getHost(desiredLocation)?.let {"
+        errorLine2="                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1015"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            val startLocation = if (onlyUseEndState) -1 else previousLocation"
+        errorLine2="                                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1032"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                startLocation,"
+        errorLine2="                ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1036"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                startLocation,"
+        errorLine2="                ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1036"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            if (currentAttachmentLocation == IN_OVERLAY) {"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1042"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                logger.logMediaHostAttachment(desiredLocation)"
+        errorLine2="                                              ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1060"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    desiredLocation = desiredLocation,"
+        errorLine2="                                      ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1062"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    desiredHostState = getHost(desiredLocation),"
+        errorLine2="                                               ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1063"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    desiredHostState = getHost(desiredLocation),"
+        errorLine2="                                               ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1063"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        newLocation != desiredLocation"
+        errorLine2="                                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1076"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            if (currentAttachmentLocation != newLocation) {"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1085"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                currentAttachmentLocation = newLocation"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1086"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                currentAttachmentLocation = newLocation"
+        errorLine2="                                            ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1086"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                    val targetHost = getHost(newLocation)!!.hostView"
+        errorLine2="                                             ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1095"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                logger.logMediaHostAttachment(currentAttachmentLocation)"
+        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1100"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        getHost(newLocation),"
+        errorLine2="                                ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1111"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            if (animationCrossFadeProgress > 0.5 || previousLocation == -1) {"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1127"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                return crossFadeAnimationEndLocation"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1128"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                return crossFadeAnimationStartLocation"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1130"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="        return desiredLocation"
+        errorLine2="               ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1133"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            return desiredLocation"
+        errorLine2="                   ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1146"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            return desiredLocation"
+        errorLine2="                   ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1146"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                mediaFlags.isSceneContainerEnabled() -> desiredLocation"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1152"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                desiredLocation == LOCATION_QS &amp;&amp;"
+        errorLine2="                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1179"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            location != LOCATION_LOCKSCREEN &amp;&amp; desiredLocation == LOCATION_LOCKSCREEN &amp;&amp; !fullyAwake"
+        errorLine2="                                               ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+            line="1186"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation var currentEndLocation: Int = -1"
+        errorLine2="                                                 ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="121"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="    @MediaLocation private var currentStartLocation: Int = -1"
+        errorLine2="                                                           ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="124"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                if (location == currentEndLocation || location == currentStartLocation) {"
+        errorLine2="                                                                  ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="287"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        currentStartLocation,"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="289"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                        currentStartLocation,"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="289"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation,"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="351"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation,"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="351"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation,"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="372"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation,"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="372"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation,"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="372"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation,"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="372"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            logger.logMediaLocation(&quot;attach $type&quot;, currentStartLocation, currentEndLocation)"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="640"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                startLocation = currentStartLocation,"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="648"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                startLocation = currentStartLocation,"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="648"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="            currentStartLocation = startLocation"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="854"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                currentStartLocation,"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="1076"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+        errorLine1="                currentStartLocation,"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+            line="1076"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one or more of: NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP, NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC, NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE, NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL"
+        errorLine1="                freeNotificationView(entry, row, curFlag);"
+        errorLine2="                                                 ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+            line="250"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one or more of: NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP, NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC, NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE, NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL"
+        errorLine1="            contentToUnbind &amp;= ~curFlag;"
+        errorLine2="                                ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+            line="252"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="    private @Action int mSelectedAction = -1;"
+        errorLine2="                                          ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="116"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        updateToggleActions(mSelectedAction, true);"
+        errorLine2="                            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="142"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        updateToggleActions(mSelectedAction, true);"
+        errorLine2="                            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="147"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        updateToggleActions(mSelectedAction, true);"
+        errorLine2="                            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="152"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        if (mSelectedAction == ACTION_FAVORITE &amp;&amp; getPriority() != mSelectedAction) {"
+        errorLine2="            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="160"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        if (mSelectedAction == ACTION_FAVORITE &amp;&amp; getPriority() != mSelectedAction) {"
+        errorLine2="                                                                   ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="160"
+            column="68"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        if (mSelectedAction == selectedAction) {"
+        errorLine2="            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="187"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        mSelectedAction = selectedAction;"
+        errorLine2="        ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="191"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        updateToggleActions(mSelectedAction == -1 ? getPriority() : mSelectedAction,"
+        errorLine2="                            ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="292"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        updateToggleActions(mSelectedAction == -1 ? getPriority() : mSelectedAction,"
+        errorLine2="                                                                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="292"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="                throw new IllegalArgumentException(&quot;Unrecognized behavior: &quot; + mSelectedAction);"
+        errorLine2="                                                                               ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="500"
+            column="80"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        return mSelectedAction;"
+        errorLine2="               ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="514"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="                        mAppUid, mSelectedAction, mNotificationChannel));"
+        errorLine2="                                 ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="532"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="                        mAppUid, mSelectedAction, mNotificationChannel));"
+        errorLine2="                                 ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="532"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        if (save &amp;&amp; mSelectedAction > -1) {"
+        errorLine2="                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="579"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        mSelectedAction = -1;"
+        errorLine2="        ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="585"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+        errorLine1="        mSelectedAction = -1;"
+        errorLine2="                          ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="585"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, Key.DEBUG_MODE_ENABLED, Key.HOTSPOT_TILE_LAST_USED, Key.COLOR_INVERSION_TILE_LAST_USED, Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, Key.QS_INVERT_COLORS_ADDED, Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, Key.ACCESSIBILITY_FLOATING_MENU_POSITION, Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM, Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM, Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT"
+        errorLine1="                mContext, QS_TILE_SPECS_REVEALED, Collections.EMPTY_SET);"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+            line="73"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, Key.DEBUG_MODE_ENABLED, Key.HOTSPOT_TILE_LAST_USED, Key.COLOR_INVERSION_TILE_LAST_USED, Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, Key.QS_INVERT_COLORS_ADDED, Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, Key.ACCESSIBILITY_FLOATING_MENU_POSITION, Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM, Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM, Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT"
+        errorLine1="                Prefs.getStringSet(mContext, QS_TILE_SPECS_REVEALED, Collections.EMPTY_SET));"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+            line="87"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="WrongConstant"
+        message="Must be one of: Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, Key.DEBUG_MODE_ENABLED, Key.HOTSPOT_TILE_LAST_USED, Key.COLOR_INVERSION_TILE_LAST_USED, Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, Key.QS_INVERT_COLORS_ADDED, Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, Key.ACCESSIBILITY_FLOATING_MENU_POSITION, Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM, Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM, Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT"
+        errorLine1="        Prefs.putStringSet(mContext, QS_TILE_SPECS_REVEALED, revealedTiles);"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+            line="89"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="WrongThread"
+        message="Method notifyContentChanged must be called from the UI thread, currently inferred thread is any thread"
+        errorLine1="        notifyContentChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ImageTileSet.java"
+            line="90"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="IncludeLayoutParam"
+        message="Layout parameter `layout_weight` ignored unless both `layout_width` and `layout_height` are also specified on `&lt;include>` tag"
+        errorLine1="        android:layout_weight=&quot;1&quot;/>"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/shade_carrier_group.xml"
+            line="44"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="IncludeLayoutParam"
+        message="Layout parameter `layout_weight` ignored unless both `layout_width` and `layout_height` are also specified on `&lt;include>` tag"
+        errorLine1="        android:layout_weight=&quot;1&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/shade_carrier_group.xml"
+            line="56"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="IncludeLayoutParam"
+        message="Layout parameter `layout_weight` ignored unless both `layout_width` and `layout_height` are also specified on `&lt;include>` tag"
+        errorLine1="        android:layout_weight=&quot;1&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/shade_carrier_group.xml"
+            line="70"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        mLayout = getLayoutInflater().inflate(R.layout.app_clips_screenshot, null);"
+        errorLine2="                                                                             ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java"
+            line="149"
+            column="78"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                    R.layout.biometric_prompt_layout, null, false);"
+        errorLine2="                                                      ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="451"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                        R.layout.auth_credential_pattern_view, null, false);"
+        errorLine2="                                                               ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="497"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                mCredentialView = factory.inflate(R.layout.auth_credential_pin_view, null, false);"
+        errorLine2="                                                                                     ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="500"
+            column="86"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                        R.layout.auth_credential_password_view, null, false);"
+        errorLine2="                                                                ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+            line="504"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.battery_percentage_view, null);"
+        errorLine2="                                                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java"
+            line="377"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="    return inflater.inflate(R.layout.biometric_prompt_content_row_layout, null) as LinearLayout"
+        errorLine2="                                                                          ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricCustomizedViewBinder.kt"
+            line="161"
+            column="75"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        inflater.inflate(R.layout.biometric_prompt_content_row_item_text_view, null) as TextView"
+        errorLine2="                                                                               ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricCustomizedViewBinder.kt"
+            line="219"
+            column="80"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null).apply {"
+        errorLine2="                                                                             ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt"
+            line="115"
+            column="78"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            (LayoutInflater.from(context).inflate(R.layout.brightness_mirror_container, null)"
+        errorLine2="                                                                                        ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflater.kt"
+            line="34"
+            column="89"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        View dialogView = dialog.getLayoutInflater().inflate(R.layout.broadcast_dialog, null);"
+        errorLine2="                                                                                        ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java"
+            line="201"
+            column="89"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            setView(LayoutInflater.from(context).inflate(R.layout.controls_dialog_pin, null))"
+        errorLine2="                                                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt"
+            line="87"
+            column="88"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow"
+        errorLine2="                                                                  ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt"
+            line="123"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.clipboard_overlay, null);"
+        errorLine2="                                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java"
+            line="61"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                                null),"
+        errorLine2="                                ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationHostViewModule.java"
+            line="65"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        dialogView = dialog.layoutInflater.inflate(R.layout.contrast_dialog, null)"
+        errorLine2="                                                                             ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt"
+            line="54"
+            column="78"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                            /* root = */ null,"
+        errorLine2="                                         ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt"
+            line="71"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                            null, false);"
+        errorLine2="                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java"
+            line="90"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            return (View) layoutInflater.inflate(R.layout.dream_overlay_media_entry_chip, null);"
+        errorLine2="                                                                                          ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamMediaEntryComplicationComponent.java"
+            line="78"
+            column="91"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                layoutInflater.inflate(R.layout.dream_overlay_container, null),"
+        errorLine2="                                                                         ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java"
+            line="61"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        dialog.setView(layoutInflater.inflate(R.layout.font_scaling_dialog, null))"
+        errorLine2="                                                                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogDelegate.kt"
+            line="85"
+            column="77"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                    .inflate(R.layout.fullscreen_magnification_border, null);"
+        errorLine2="                                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java"
+            line="181"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                com.android.systemui.res.R.layout.global_actions_power_dialog, null);"
+        errorLine2="                                                                               ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPowerDialog.java"
+            line="39"
+            column="80"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.hearing_devices_tile_dialog, null));"
+        errorLine2="                                                      ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java"
+            line="235"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.internet_connectivity_dialog, null);"
+        errorLine2="                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="231"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.keyboard_shortcuts_search_view, null);"
+        errorLine2="                                                         ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+            line="861"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.keyboard_shortcuts_key_view, null, false);"
+        errorLine2="                                                      ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="626"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        return inflater.inflate(R.layout.notification_icon_area, null);"
+        errorLine2="                                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java"
+            line="163"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        LayoutInflater.from(context).inflate(R.layout.screenshot, null) as ScreenshotView"
+        errorLine2="                                                                  ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt"
+            line="57"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.log_access_user_consent_dialog_permission, null /*root*/);"
+        errorLine2="                                                                    ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java"
+            line="208"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        mDialogView = LayoutInflater.from(mContext).inflate(R.layout.media_output_dialog, null);"
+        errorLine2="                                                                                          ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java"
+            line="246"
+            column="91"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                null);"
+        errorLine2="                ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSessionReleaseDialog.java"
+            line="67"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        return (NavigationBarFrame) layoutInflater.inflate(R.layout.navigation_bar_window, null);"
+        errorLine2="                                                                                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java"
+            line="47"
+            column="92"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.notification_snooze, null, false);"
+        errorLine2="                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java"
+            line="1592"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.notification_snooze, null, false);"
+        errorLine2="                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+            line="663"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                        R.layout.notification_conversation_info, null, false);"
+        errorLine2="                                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+            line="675"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                        R.layout.partial_conversation_info, null, false);"
+        errorLine2="                                                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+            line="685"
+            column="61"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.notification_info, null, false);"
+        errorLine2="                                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+            line="694"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.feedback_info, null, false);"
+        errorLine2="                                        ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+            line="701"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                    R.layout.keyguard_pin_shape_hinting_view, null);"
+        errorLine2="                                                              ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+            line="153"
+            column="63"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                    R.layout.keyguard_pin_shape_non_hinting_view, null);"
+        errorLine2="                                                                  ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+            line="156"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            .inflate(R.layout.people_space_activity, /* root= */ null) as ViewGroup"
+        errorLine2="                                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt"
+            line="66"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                inflater.inflate(R.layout.qs_panel, null) { view, _, _ ->"
+        errorLine2="                                                    ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt"
+            line="262"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.quick_settings_footer_dialog, null, false);"
+        errorLine2="                                                                ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java"
+            line="497"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);"
+        errorLine2="                                                                                  ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java"
+            line="585"
+            column="83"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            dialogView = inflater.inflate(R.layout.activity_rear_display_education, null);"
+        errorLine2="                                                                                    ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java"
+            line="145"
+            column="85"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                    R.layout.activity_rear_display_education_opened, null);"
+        errorLine2="                                                                     ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java"
+            line="148"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            setView(LayoutInflater.from(context).inflate(R.layout.record_issue_dialog, null))"
+        errorLine2="                                                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt"
+            line="84"
+            column="88"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.screen_decor_hwc_layer, null);"
+        errorLine2="                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java"
+            line="846"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.screen_record_dialog_audio_source, null, false);"
+        errorLine2="                                                                     ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java"
+            line="55"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.screen_record_dialog_audio_source_selected, null, false);"
+        errorLine2="                                                                              ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java"
+            line="71"
+            column="79"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        LayoutInflater.from(context).inflate(R.layout.screenshot_shelf, null) as ScreenshotShelfView"
+        errorLine2="                                                                        ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt"
+            line="63"
+            column="73"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)"
+        errorLine2="                                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt"
+            line="298"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        overlayView = layoutInflater.get().inflate(R.layout.sidefps_view, null, false)"
+        errorLine2="                                                                          ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt"
+            line="125"
+            column="75"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        final View view = layoutInflater.inflate(R.layout.magnifier_controllers, null);"
+        errorLine2="                                                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java"
+            line="68"
+            column="82"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            return LayoutInflater.from(context).inflate(R.layout.bindable_status_bar_icon, null)"
+        errorLine2="                                                                                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt"
+            line="69"
+            column="92"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                R.layout.smart_reply_view, null /* root */);"
+        errorLine2="                                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+            line="150"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                /* root= */null"
+        errorLine2="                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt"
+            line="27"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                /* root= */null"
+        errorLine2="                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt"
+            line="27"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.system_event_animation_window, null) as FrameLayout"
+        errorLine2="                                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt"
+            line="242"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                    com.android.systemui.res.R.layout.text_toast, null);"
+        errorLine2="                                                                  ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java"
+            line="173"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                        .inflate(R.layout.tile_service_request_dialog, null)"
+        errorLine2="                                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt"
+            line="51"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        LayoutInflater.from(context).inflate(R.layout.controls_onboarding, null) as ViewGroup"
+        errorLine2="                                                                           ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt"
+            line="64"
+            column="76"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                            R.layout.udfps_touch_overlay, null, false"
+        errorLine2="                                                          ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt"
+            line="212"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                            R.layout.udfps_view, null, false"
+        errorLine2="                                                 ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt"
+            line="238"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            LayoutInflater.from(this.context).inflate(R.layout.qs_user_dialog_content, null)"
+        errorLine2="                                                                                       ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitchDialog.kt"
+            line="59"
+            column="88"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                .inflate(R.layout.qs_user_dialog_content, null)"
+        errorLine2="                                                          ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt"
+            line="92"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="            LayoutInflater.from(this.context).inflate(R.layout.user_switcher_fullscreen, null)"
+        errorLine2="                                                                                         ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/UserSwitcherFullscreenDialog.kt"
+            line="49"
+            column="90"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                        /* parent= */ null"
+        errorLine2="                                      ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt"
+            line="231"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="                null);"
+        errorLine2="                ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java"
+            line="99"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);"
+        errorLine2="                                                                                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="692"
+            column="93"/>
+    </issue>
+
+    <issue
+        id="InflateParams"
+        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+        errorLine1="        mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);"
+        errorLine2="                                                                                            ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="742"
+            column="93"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/controls_management` does not contain a declaration with id `status_message`"
+        errorLine1="        statusText = requireViewById(R.id.status_message)"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+            line="261"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/controls_management` does not contain a declaration with id `structure_page_indicator`"
+        errorLine1="            R.id.structure_page_indicator).apply {"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+            line="275"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/controls_management` does not contain a declaration with id `structure_pager`"
+        errorLine1="        structurePager = requireViewById&lt;ViewPager2>(R.id.structure_pager)"
+        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+            line="291"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/controls_management` does not contain a declaration with id `list`"
+        errorLine1="        recyclerView = requireViewById(R.id.list)"
+        errorLine2="                                       ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt"
+            line="107"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/global_actions_grid_item_v2` does not contain a declaration with id `icon`"
+        errorLine1="            ImageView icon = (ImageView) v.findViewById(R.id.icon);"
+        errorLine2="                                                        ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="1899"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/global_actions_grid_item_v2` does not contain a declaration with id `message`"
+        errorLine1="            TextView messageView = (TextView) v.findViewById(R.id.message);"
+        errorLine2="                                                             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="1900"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="MissingInflatedId"
+        message="`@layout/quick_access_wallet` does not contain a declaration with id `action_bar`"
+        errorLine1="        Toolbar toolbar = findViewById(R.id.action_bar);"
+        errorLine2="                                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java"
+            line="120"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="UnspecifiedRegisterReceiverFlag"
+        message="`this` is missing `RECEIVER_EXPORTED` or `RECEIVER_NOT_EXPORTED` flag for unprotected broadcasts registered for android.intent.action.PROFILE_AVAILABLE, android.intent.action.PROFILE_UNAVAILABLE"
+        errorLine1="        context.registerReceiverForAllUsers(this, filter, null, backgroundHandler)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt"
+            line="148"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
+        errorLine1="    android:width=&quot;360dp&quot; >"
+        errorLine2="                   ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/indeterminate.xml"
+            line="20"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
+        errorLine1="        android:width=&quot;340dp&quot;"
+        errorLine2="                       ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml"
+            line="23"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ObjectAnimatorBinding"
+        message="Could not find property setter method `setLeft` on `java.lang.Object`"
+        errorLine1="            PropertyValuesHolder left = PropertyValuesHolder.ofInt(&quot;left&quot;, 0, 1);"
+        errorLine2="                                                                   ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java"
+            line="330"
+            column="68"/>
+    </issue>
+
+    <issue
+        id="ObjectAnimatorBinding"
+        message="Could not find property setter method `setRight` on `java.lang.Object`"
+        errorLine1="            PropertyValuesHolder right = PropertyValuesHolder.ofInt(&quot;right&quot;, 0, 1);"
+        errorLine2="                                                                    ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java"
+            line="331"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="UnsupportedChromeOsCameraSystemFeature"
+        message="You should look for any camera available on the device, not just the rear"
+        errorLine1="            mIsCameraAvailable = mContext.getPackageManager().hasSystemFeature("
+        errorLine2="                                 ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java"
+            line="239"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        BatteryController bC = new BatteryControllerImpl("
+        errorLine2="                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/AospPolicyModule.java"
+            line="51"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                getOrCreateInstanceId().id,"
+        errorLine2="                                        ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt"
+            line="83"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                getOrCreateInstanceId().id,"
+        errorLine2="                                        ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt"
+            line="83"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                + &quot; active[A2DP]=&quot; + device.isActiveDevice(BluetoothProfile.A2DP)"
+        errorLine2="                                            ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="164"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                + &quot; active[HEADSET]=&quot; + device.isActiveDevice(BluetoothProfile.HEADSET)"
+        errorLine2="                                               ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="165"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                + &quot; active[HEARING_AID]=&quot; + device.isActiveDevice(BluetoothProfile.HEARING_AID)"
+        errorLine2="                                                   ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="166"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                + &quot; active[LE_AUDIO]=&quot; + device.isActiveDevice(BluetoothProfile.LE_AUDIO);"
+        errorLine2="                                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="167"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="            isActive |= device.isActiveDevice(BluetoothProfile.HEADSET)"
+        errorLine2="                               ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="294"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                    || device.isActiveDevice(BluetoothProfile.A2DP)"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="295"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                    || device.isActiveDevice(BluetoothProfile.HEARING_AID)"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="296"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope"
+        errorLine1="                    || device.isActiveDevice(BluetoothProfile.LE_AUDIO);"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+            line="297"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="    return calculateLayoutInternal("
+        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt"
+            line="38"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mCentralSurfaces.updateScrimController();"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java"
+            line="378"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        instanceId = instanceIdSequence.newInstanceId().id"
+        errorLine2="                                                        ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt"
+            line="41"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        instanceId = instanceIdSequence.newInstanceId().id"
+        errorLine2="                                                        ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt"
+            line="41"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This class should only be accessed from tests or within private scope"
+        errorLine1="        controller: ControlsBindingControllerImpl"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt"
+            line="90"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mCentralSurfaces.updateScrimController();"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+            line="299"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mCentralSurfaces.updateScrimController();"
+        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+            line="306"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mCentralSurfaces.updateScrimController();"
+        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+            line="434"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mCentralSurfaces.updateScrimController();"
+        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+            line="441"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mDragController.startDragAndDrop(this);"
+        errorLine2="                            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+            line="2084"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            info.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+            line="2132"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        value = foldPostureInternal(layoutInfo)"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/FoldPosture.kt"
+            line="41"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)"
+        errorLine2="                                                                     ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt"
+            line="155"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        if (getCurrentRotation() == ROTATION_NONE) {"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsColumnLayout.java"
+            line="178"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        switch (getCurrentRotation()) {"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsColumnLayout.java"
+            line="186"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        int rotation = getCurrentRotation();"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+            line="135"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        if (getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+            line="141"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        switch (getCurrentRotation()) {"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+            line="157"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        if (getCurrentRotation() == ROTATION_NONE) {"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+            line="169"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId();"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="196"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE);"
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="276"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE);"
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="346"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            if (mInternetDialogController.isAirplaneModeEnabled()) {"
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="531"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                &amp;&amp; mInternetDialogController.isAirplaneModeEnabled();"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="833"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    &amp;&amp; msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher &amp; failed"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java"
+            line="1302"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mUiEventLogger.log(success ? BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="290"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId());"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="291"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This class should only be accessed from tests or within private scope"
+        errorLine1="        BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;"
+        errorLine2="        ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="869"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;"
+        errorLine2="                                                ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="869"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="877"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC;"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="881"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY;"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="887"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD;"
+        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="899"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="913"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        if (uiEvent != BouncerUiEvent.UNKNOWN) {"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="940"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                .getSecurityView(mCurrentSecurityMode, mKeyguardSecurityCallback,"
+        errorLine2="                 ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+            line="1185"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This class should only be accessed from tests or within private scope"
+        errorLine1="        @Nullable private ActivityTransitionAnimator.Runner mRunner;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3847"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mRunner.onAnimationCancelled();"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3856"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mRunner = mActivityTransitionAnimator.get().createRunner(mActivityLaunchController);"
+        errorLine2="                                                        ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3866"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mRunner.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);"
+        errorLine2="                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3867"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mKeyguardUpdateMonitor.onFaceAuthenticated(mSelectedUserInteractor.getSelectedUserId(),"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/LatencyTester.java"
+            line="90"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mKeyguardUpdateMonitor.onFingerprintAuthenticated("
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/LatencyTester.java"
+            line="93"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            return new LeakDetector("
+        errorLine2="                   ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java"
+            line="33"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            return new LeakDetector(null, null, null, dumpManager);"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java"
+            line="39"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        instanceId = InstanceId.fakeInstanceId(-1),"
+        errorLine2="                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+            line="132"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        instanceId = InstanceId.fakeInstanceId(-1),"
+        errorLine2="                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+            line="145"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="    val instanceId: InstanceId = InstanceId.fakeInstanceId(-1),"
+        errorLine2="                                            ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt"
+            line="92"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="    val instanceId: InstanceId = InstanceId.fakeInstanceId(-1),"
+        errorLine2="                                            ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt"
+            line="92"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;"
+        errorLine2="                                                ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="150"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    setUpContentDescriptionForView(mSeekBar, device);"
+        errorLine2="                                                   ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="251"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        setUpContentDescriptionForView(mSeekBar, device);"
+        errorLine2="                                                       ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="288"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        setUpContentDescriptionForView(mSeekBar, device);"
+        errorLine2="                                                       ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="297"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)"
+        errorLine2="                                                           ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="156"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="159"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter"
+        errorLine2="                                                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="159"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter"
+        errorLine2="                                                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="159"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="169"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="169"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="169"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+        errorLine2="                                                                     ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="169"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+        errorLine2="                                                                     ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="169"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mMultiProfilePagerAdapter.personalListAdapter.notifyDataSetChanged()"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="231"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="    private fun hasWorkProfile() = mMultiProfilePagerAdapter.count > 1"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="290"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        for (i in 0 until mMultiProfilePagerAdapter.count) {"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="373"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mMultiProfilePagerAdapter"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+            line="375"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                targetAppUserHandle = resolverListAdapter.userHandle,"
+        errorLine2="                                                          ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt"
+            line="42"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                targetAppUserHandle = resolverListAdapter.userHandle,"
+        errorLine2="                                                          ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt"
+            line="42"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            if (now.minus(it.second) &lt;= RESUME_MEDIA_TIMEOUT) {"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/resume/MediaResumeListener.kt"
+            line="220"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mUiEventLogger.log(KeyButtonView.NavBarButtonEvent.NAVBAR_IME_SWITCHER_BUTTON_TAP);"
+        errorLine2="                                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+            line="1500"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    mMobileSignalControllers.valueAt(i).mInflateSignalStrengths ="
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1367"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);"
+        errorLine2="                                   ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1376"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);"
+        errorLine2="                                   ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1379"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);"
+        errorLine2="                                   ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1382"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                        controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);"
+        errorLine2="                                   ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1385"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);"
+        errorLine2="                           ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="1389"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            ranking.populate("
+        errorLine2="                    ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java"
+            line="276"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    proto.instanceId = n.getInstanceId().getId();"
+        errorLine2="                                                         ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java"
+            line="104"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mQsController.setExpanded(mSplitShadeEnabled);"
+        errorLine2="                          ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+            line="1367"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        if (mQsController.isExpandImmediate() || mQsController.getExpanded()"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+            line="2613"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        if (!mQsController.getExpanded() || mQsController.isExpandImmediate()"
+        errorLine2="                                                          ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+            line="2648"
+            column="59"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    mView.setStatusBarState(mBarState);"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java"
+            line="383"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mView.updateFooter();"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java"
+            line="1559"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    getMessagingStyleMessages(notification);"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="197"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                getMessagingStyleMessages(notification);"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="258"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mPanelViewControllerLazy.get().cancelHeightAnimator();"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java"
+            line="951"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mPanelViewControllerLazy.get().notifyExpandingStarted();"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java"
+            line="1955"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            instanceId = sbn.instanceId?.id,"
+        errorLine2="                                         ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt"
+            line="138"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            instanceId = sbn.instanceId?.id,"
+        errorLine2="                                         ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt"
+            line="138"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        mContext.release();"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java"
+            line="530"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This class should only be accessed from tests or within private scope"
+        errorLine1="                (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.ACTION"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+            line="384"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.ACTION"
+        errorLine2="                                                              ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+            line="384"
+            column="63"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This class should only be accessed from tests or within private scope"
+        errorLine1="                (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.REPLY"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+            line="465"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.REPLY"
+        errorLine2="                                                              ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+            line="465"
+            column="63"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            ((TextView) view).nullLayouts();"
+        errorLine2="                              ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+            line="221"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="            mCentralSurfaces.updateScrimController();"
+        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java"
+            line="976"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                mCentralSurfaces.updateScrimController();"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java"
+            line="1195"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        final int sessionId = (sessionIdProvider != null) ? sessionIdProvider.getId() : -1;"
+        errorLine2="                                                                              ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java"
+            line="500"
+            column="79"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    udfpsController?.playStartHaptic()"
+        errorLine2="                                     ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt"
+            line="55"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="        udfpsController.mOverlayParams?.scaleFactor?.let { view.setScaleFactor(it) }"
+        errorLine2="                        ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt"
+            line="558"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    .createRunner(occludeAnimationController)"
+        errorLine2="                     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt"
+            line="128"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope"
+        errorLine1="                    .onAnimationStart("
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt"
+            line="129"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ExtraText"
+        message="Unexpected text found in layout file: &quot;>&quot;"
+        errorLine1="    >"
+        errorLine2="    ~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/ongoing_privacy_chip.xml"
+            line="28"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="ExtraText"
+        message="Unexpected text found in layout file: &quot;->&quot;"
+        errorLine1="&lt;merge xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>->"
+        errorLine2="                                                                  ~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_customize_panel_content.xml"
+            line="18"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="SpUsage"
+        message="Should use &quot;`sp`&quot; instead of &quot;`dp`&quot; for text sizes (`@dimen/dream_overlay_complication_clock_time_text_size` is defined as `86dp` in `values/dimens.xml`"
+        errorLine1="    android:textSize=&quot;@dimen/dream_overlay_complication_clock_time_text_size&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml"
+            line="30"
+            column="5"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1862"
+            column="67"
+            message="This dp dimension is used as a text size"/>
+    </issue>
+
+    <issue
+        id="SpUsage"
+        message="Should use &quot;`sp`&quot; instead of &quot;`dp`&quot; for text sizes"
+        errorLine1="        &lt;item name=&quot;android:textSize&quot;>36dp&lt;/item>"
+        errorLine2="                                      ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/styles.xml"
+            line="43"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="SpUsage"
+        message="Should use &quot;`sp`&quot; instead of &quot;`dp`&quot; for text sizes"
+        errorLine1="        &lt;item name=&quot;android:textSize&quot;>36dp&lt;/item>"
+        errorLine2="                                      ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+            line="255"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="SwitchIntDef"
+        message="Switch statement on an `int` with known associated constant missing case `BiometricUnlockController.MODE_DISMISS_BOUNCER`, `BiometricUnlockController.MODE_NONE`, `BiometricUnlockController.MODE_ONLY_WAKE`, `BiometricUnlockController.MODE_SHOW_BOUNCER`, `BiometricUnlockController.MODE_UNLOCK_COLLAPSING`"
+        errorLine1="                        switch (mode) {"
+        errorLine2="                        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="1522"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="SwitchIntDef"
+        message="Switch statement on an `int` with known associated constant missing case `ICON_NONE`"
+        errorLine1="        switch (icon) {"
+        errorLine2="        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/LockIconView.java"
+            line="214"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SwitchIntDef"
+        message="Switch statement on an `int` with known associated constant missing case `NotificationConversationInfo.ACTION_HOME`, `NotificationConversationInfo.ACTION_SETTINGS`, `NotificationConversationInfo.ACTION_SNOOZE`"
+        errorLine1="                switch (mAction) {"
+        errorLine2="                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+            line="630"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="SwitchIntDef"
+        message="Switch statement on an `int` with known associated constant missing case `NotificationPriorityBucketKt.BUCKET_UNKNOWN`"
+        errorLine1="        switch(bucket) {"
+        errorLine2="        ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java"
+            line="127"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="DiscouragedApi"
+        message="Should not restrict activity to fixed orientation. This may not be suitable for different form factors, causing the app to be letterboxed."
+        errorLine1="        &lt;activity android:name=&quot;.DessertCase&quot; android:exported=&quot;true&quot; android:label=&quot;@string/dessert_case&quot; android:theme=&quot;@android:style/Theme.Black.NoTitleBar.Fullscreen&quot; android:launchMode=&quot;singleInstance&quot; android:screenOrientation=&quot;locked&quot; android:process=&quot;:sweetsweetdesserts&quot; android:excludeFromRecents=&quot;true&quot;>"
+        errorLine2="                                                                                                                                                                                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="517"
+            column="209"/>
+    </issue>
+
+    <issue
+        id="DiscouragedApi"
+        message="Activity should not be non-resizable. With this setting, apps cannot be used in multi-window or free form mode."
+        errorLine1="        &lt;activity android:name=&quot;.notetask.shortcut.CreateNoteTaskShortcutActivity&quot; android:enabled=&quot;false&quot; android:exported=&quot;true&quot; android:excludeFromRecents=&quot;true&quot; android:resizeableActivity=&quot;false&quot; android:theme=&quot;@android:style/Theme.NoDisplay&quot; android:label=&quot;@string/note_task_button_label&quot; android:icon=&quot;@drawable/ic_note_task_shortcut_widget&quot;>"
+        errorLine2="                                                                                                                                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="631"
+            column="166"/>
+    </issue>
+
+    <issue
+        id="Orientation"
+        message="No orientation specified, and the default is horizontal. This is a common source of bugs when children are added dynamically."
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+            line="44"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;lock_icon_padding&quot;>48px&lt;/dimen>"
+        errorLine2="                                    ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="647"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;global_actions_top_padding&quot;>330px&lt;/dimen>"
+        errorLine2="                                             ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1007"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;udfps_burn_in_offset_x&quot;>7px&lt;/dimen>"
+        errorLine2="                                         ~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1061"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;udfps_burn_in_offset_y&quot;>20px&lt;/dimen>"
+        errorLine2="                                         ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1062"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;max_window_blur_radius&quot;>23px&lt;/dimen>"
+        errorLine2="                                         ~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1178"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;physical_power_button_center_screen_location_y&quot;>620px&lt;/dimen>"
+        errorLine2="                                                                 ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1671"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="PxUsage"
+        message="Avoid using `&quot;px&quot;` as units; use `&quot;dp&quot;` instead"
+        errorLine1="    &lt;dimen name=&quot;physical_fingerprint_sensor_center_screen_location_y&quot;>610px&lt;/dimen>"
+        errorLine2="                                                                       ~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+            line="1684"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="SupportAnnotationUsage"
+        message="Did you mean `@get:VisibleForTesting`? Without `get:` this annotates the constructor parameter itself instead of the associated getter."
+        errorLine1="    @VisibleForTesting private val dialogProvider: DialogProvider"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt"
+            line="74"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="SupportAnnotationUsage"
+        message="This annotation does not apply for type String; expected int. Should `@com.android.systemui.shade.PanelState` be annotated with `@StringDef` instead?"
+        errorLine1="@PanelState"
+        errorLine2="~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt"
+            line="162"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;BiometricUnlockController#onBiometricDetected&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java"
+            line="407"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;BiometricUnlockController#onBiometricUnlocked&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java"
+            line="418"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="            Trace.beginSection(&quot;$TAG#smallClock.animations.doze&quot;)"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt"
+            line="525"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="            Trace.beginSection(&quot;$TAG#largeClock.animations.doze&quot;)"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt"
+            line="528"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may throw an exception"
+        errorLine1="                Trace.traceBegin(Trace.TRACE_TAG_APP,"
+        errorLine2="                      ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java"
+            line="128"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin("
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java"
+            line="179"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;DumpManager#dump()&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt"
+            line="100"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="            Trace.beginSection(entry.name)"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt"
+            line="480"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;DumpsysTableLogger#printTableData&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dump/DumpsysTableLogger.kt"
+            line="87"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="            Trace.beginSection(&quot;ExpNotRow#onChildCountChanged (summary)&quot;);"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+            line="2761"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="            Trace.beginSection(&quot;HybridGroupManager#bindFromNotification&quot;);"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="102"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;ImageExporter_writeExif&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java"
+            line="436"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="            Trace.beginSection(&quot;WPMS.ImageWallpaper.CanvasEngine#loadWallpaper&quot;);"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+            line="339"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="                        Trace.beginSection(&quot;KeyguardBlueprintViewBinder#applyBlueprint&quot;)"
+        errorLine2="                              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt"
+            line="96"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="                        Trace.beginSection(&quot;KeyguardBlueprintViewBinder#refreshTransition&quot;)"
+        errorLine2="                              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt"
+            line="143"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+            line="955"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;KeyGuardUpdateMonitor#handlerFaceAuthenticated&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+            line="1208"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;KeyguardViewMediator#handleKeyguardDone&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="2654"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;KeyguardViewMediator#handleShow&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="2780"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;KeyguardViewMediator#handleStartKeyguardExitAnimation&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="3011"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin(Trace.TRACE_TAG_APP, &quot;MediaControlPanel#bindPlayer&lt;&quot; + key + &quot;>&quot;);"
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java"
+            line="543"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin(Trace.TRACE_TAG_APP,"
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java"
+            line="1435"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;NSSLC#updateResources&quot;);"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+            line="1331"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="                Trace.traceBegin(Trace.TRACE_TAG_APP, &quot;Pluggable&lt;&quot; + mName + &quot;>.invalidateList&quot;);"
+        errorLine2="                      ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java"
+            line="55"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="        Trace.beginSection(&quot;KeyguardBouncer#show&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+            line="184"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;KeyguardBouncer#hide&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+            line="215"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="        Trace.traceBegin(Trace.TRACE_TAG_APP, &quot;QSTileViewImpl#onMeasure&quot;)"
+        errorLine2="              ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt"
+            line="225"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="            Trace.beginSection(&quot;ResourceTrimmer#trimMemory&quot;)"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt"
+            line="132"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+        errorLine1="            Trace.beginSection(&quot;ScreenDecorations#onConfigurationChanged&quot;);"
+        errorLine2="                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java"
+            line="1071"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;ScreenOnCoordinator#onScreenTurningOn&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt"
+            line="57"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin("
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+            line="380"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin("
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+            line="406"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin("
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+            line="429"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="            Trace.traceBegin("
+        errorLine2="                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+            line="440"
+            column="19"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+        errorLine1="                Trace.traceBegin("
+        errorLine2="                      ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+            line="454"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;TableLogBuffer#logChange(string)&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+            line="199"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;TableLogBuffer#logChange(boolean)&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+            line="213"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;TableLogBuffer#logChange(int)&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+            line="227"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;TableLogBuffer#saveEvictedValue&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+            line="264"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;UdfpsDisplayMode.enable&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDisplayMode.kt"
+            line="54"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+        errorLine1="        Trace.beginSection(&quot;UdfpsDisplayMode.disable&quot;)"
+        errorLine2="              ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDisplayMode.kt"
+            line="83"
+            column="15"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may throw an exception"
+        errorLine1="                        Trace.traceBegin("
+        errorLine2="                              ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+            line="131"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="UnclosedTrace"
+        message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may throw an exception"
+        errorLine1="                            Trace.traceBegin("
+        errorLine2="                                  ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+            line="148"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="StringFormatInvalid"
+        message="Format string &apos;`high_temp_alarm_notify_message`&apos; is not a valid format string so it should not be passed to `String.format`"
+        errorLine1="        d.setMessage(mContext.getString(R.string.high_temp_alarm_notify_message, &quot;&quot;));"
+        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="554"
+            column="22"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="2344"
+            column="5"
+            message="This definition does not require arguments"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings.xml"
+            line="258"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                R.string.notification_group_overflow_indicator, number);"
+        errorLine2="                                                                ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+            line="151"
+            column="65"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="620"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+            line="1131"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings.xml"
+            line="1131"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+            line="1136"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="StringFormatMatches"
+        message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, &apos;o&apos; or `x`?)"
+        errorLine1="                    durationSinceLastInteraction.toDays());"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+            line="1315"
+            column="21"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="2997"
+            column="5"
+            message="Conflicting argument declaration here"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;theyre&quot; is a common misspelling; did you mean &quot;they&apos;re&quot;?"
+        errorLine1="    &lt;string name=&quot;fingerprint_re_enroll_dialog_content&quot; msgid=&quot;4866561176695984879&quot;>&quot;To set up Fingerprint Unlock again, your current fingerprint images and models will be deleted.\n\nAfter theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you.&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                                              ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="195"
+            column="191"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;theyre&quot; is a common misspelling; did you mean &quot;they&apos;re&quot;?"
+        errorLine1="    &lt;string name=&quot;fingerprint_re_enroll_dialog_content&quot; msgid=&quot;4866561176695984879&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎To set up Fingerprint Unlock again, your current fingerprint images and models will be deleted.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎After theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                                                                                                                                                                             ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+            line="195"
+            column="318"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;theyre&quot; is a common misspelling; did you mean &quot;they&apos;re&quot;?"
+        errorLine1="    &lt;string name=&quot;fingerprint_re_enroll_dialog_content_singular&quot; msgid=&quot;3083663339787381218&quot;>&quot;To set up Fingerprint Unlock again, your current fingerprint images and model will be deleted.\n\nAfter theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you.&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                                                      ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="196"
+            column="199"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;theyre&quot; is a common misspelling; did you mean &quot;they&apos;re&quot;?"
+        errorLine1="    &lt;string name=&quot;fingerprint_re_enroll_dialog_content_singular&quot; msgid=&quot;3083663339787381218&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎To set up Fingerprint Unlock again, your current fingerprint images and model will be deleted.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎After theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                                                                                                                                                                                    ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+            line="196"
+            column="325"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_management_named_vpn&quot; msgid=&quot;4137564460025113168&quot;>&quot;Denne enheten tilhører organisasjonen din og er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                          ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="520"
+            column="155"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_named_management_named_vpn&quot; msgid=&quot;2169227918166358741&quot;>&quot;Denne enheten tilhører &lt;xliff:g id=&quot;ORGANIZATION_NAME&quot;>%1$s&lt;/xliff:g> og er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%2$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                              ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="521"
+            column="175"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_management_vpns&quot; msgid=&quot;929181757984262902&quot;>&quot;Denne enheten tilhører organisasjonen din og er koblet til internett via VPN-er&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                    ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="524"
+            column="149"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_named_management_vpns&quot; msgid=&quot;3312645578322079185&quot;>&quot;Denne enheten tilhører &lt;xliff:g id=&quot;ORGANIZATION_NAME&quot;>%1$s&lt;/xliff:g> og er koblet til internett via VPN-er&quot;&lt;/string>"
+        errorLine2="                                                                                                                                                                         ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="525"
+            column="170"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_vpns&quot; msgid=&quot;3586175303518266301&quot;>&quot;Denne enheten er koblet til internett via VPN-er&quot;&lt;/string>"
+        errorLine2="                                                                                                           ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="530"
+            column="108"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_managed_profile_named_vpn&quot; msgid=&quot;153393105176944100&quot;>&quot;Jobbappene dine er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="                                                                                                                                 ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="531"
+            column="130"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_personal_profile_named_vpn&quot; msgid=&quot;451254750289172191&quot;>&quot;De personlige appene dine er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="                                                                                                                                            ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="532"
+            column="141"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;quick_settings_disclosure_named_vpn&quot; msgid=&quot;6191822916936028208&quot;>&quot;Denne enheten er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="                                                                                                                ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="533"
+            column="113"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;monitoring_description_named_vpn&quot; msgid=&quot;8220190039787149671&quot;>&quot;Denne enheten er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for VPN-leverandøren.&quot;&lt;/string>"
+        errorLine2="                                                                                                             ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="549"
+            column="110"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;monitoring_description_managed_device_named_vpn&quot; msgid=&quot;7693648349547785255&quot;>&quot;Denne enheten er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for IT-administratoren din.&quot;&lt;/string>"
+        errorLine2="                                                                                                                            ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="550"
+            column="125"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;monitoring_description_two_named_vpns&quot; msgid=&quot;6726394451199620634&quot;>&quot;Denne enheten er koblet til internett via &lt;xliff:g id=&quot;VPN_APP_0&quot;>%1$s&lt;/xliff:g> og &lt;xliff:g id=&quot;VPN_APP_1&quot;>%2$s&lt;/xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for IT-administratoren din.&quot;&lt;/string>"
+        errorLine2="                                                                                                                  ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="551"
+            column="115"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;monitoring_description_managed_profile_named_vpn&quot; msgid=&quot;7254359257263069766&quot;>&quot;Jobbappene dine er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>. Nettverksaktiviteten din i jobbapper, inkludert e-poster og nettlesingsdata, er synlige for IT-administratoren og VPN-leverandøren din.&quot;&lt;/string>"
+        errorLine2="                                                                                                                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="552"
+            column="128"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;monitoring_description_personal_profile_named_vpn&quot; msgid=&quot;5083909710727365452&quot;>&quot;De personlige appene dine er koblet til internett via &lt;xliff:g id=&quot;VPN_APP&quot;>%1$s&lt;/xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for VPN-leverandøren din.&quot;&lt;/string>"
+        errorLine2="                                                                                                                                          ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="553"
+            column="139"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="Did you mean &quot;Pos!&quot; instead of &quot;Pos1&quot;?"
+        errorLine1="    &lt;string name=&quot;keyboard_key_home&quot; msgid=&quot;3734400625170020657&quot;>&quot;Pos1&quot;&lt;/string>"
+        errorLine2="                                                                  ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+            line="718"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="Did you mean &quot;Pos!&quot; instead of &quot;Pos1&quot;?"
+        errorLine1="    &lt;string name=&quot;keyboard_key_move_home&quot; msgid=&quot;3496502501803911971&quot;>&quot;Pos1&quot;&lt;/string>"
+        errorLine2="                                                                       ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+            line="738"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="Typos"
+        message="&quot;internett&quot; is usually capitalized as &quot;Internett&quot;"
+        errorLine1="    &lt;string name=&quot;mobile_data_disable_message&quot; msgid=&quot;8604966027899770415&quot;>&quot;Du får ikke tilgang til data eller internett via &lt;xliff:g id=&quot;CARRIER&quot;>%s&lt;/xliff:g>. Internett er bare tilgjengelig via Wifi.&quot;&lt;/string>"
+        errorLine2="                                                                                                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+            line="925"
+            column="112"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;pip_settings_bounds&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string translatable=&quot;false&quot; name=&quot;pip_settings_bounds&quot;>&quot;778 756 1258 1026&quot;&lt;/string>"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ldrtl/config.xml"
+            line="20"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot;>Drag left to quickly switch apps&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ldrtl/strings.xml"
+            line="21"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Sleep links om programme vinnig te wissel&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;መተግበሪያዎችን በፍጥነት ለመቀየር ወደ ግራ ይጎትቱ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;اسحب لليمين للتبديل السريع بين التطبيقات.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;তাত্‍ক্ষণিকভাৱে আনটো এপ্ ব্যৱহাৰ কৰিবলৈ বাওঁফালে টানক&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Digər tətbiqə sürətlə keçmək üçün sola çəkin&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Prevucite ulevo da biste brzo promenili aplikacije&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Каб хутка пераключыцца паміж праграмамі, перацягніце ўлева&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Плъзнете наляво за бързо превключване между приложенията&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;একটি অ্যাপ ছেড়ে দ্রুত অন্য অ্যাপে যেতে বাঁ দিকে টেনে আনুন&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Prevucite ulijevo za brzo prebacivanje između aplikacija&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arrossega el dit cap a l\&apos;esquerra per canviar ràpidament d\&apos;aplicació&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Přetažením doleva rychle přepnete aplikace&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Træk til venstre for hurtigt at skifte app&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Zum schnellen Wechseln der Apps nach links ziehen&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Σύρετε αριστερά για γρήγορη εναλλαγή εφαρμογών&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Drag left to quickly switch apps&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Drag left to quickly switch apps&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Drag left to quickly switch apps&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Drag left to quickly switch apps&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‏‎Drag left to quickly switch apps‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arrastra el dedo hacia la izquierda para cambiar de aplicación rápidamente&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arrastra a la izquierda para cambiar de app rápidamente&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Rakenduste kiiresti vahetamiseks lohistage vasakule&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arrastatu ezkerrera aplikazioa azkar aldatzeko&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;برای سریع جابه‌جا شدن میان برنامه‌ها، به چپ بکشید&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Vaihda sovellusta nopeasti vetämällä vasemmalle&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Déplacer vers la gauche pour changer rapidement d\&apos;application&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Balayez l\&apos;écran vers la gauche pour changer rapidement d\&apos;application&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Para cambiar de aplicación, arrastra o dedo rapidamente á esquerda&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ઍપને ઝડપથી સ્વિચ કરવા માટે ડાબે ખેંચો&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ऐप्लिकेशन को तेज़ी से बदलने के लिए उसे बाईं ओर खींचें और छोड़ें&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Povucite ulijevo da biste brzo promijenili aplikaciju&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Húzza balra az ujját az alkalmazások közötti gyors váltáshoz&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Քաշեք ձախ՝ հավելվածների միջև անցնելու համար&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Tarik ke kiri untuk beralih ke aplikasi dengan cepat&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Dragðu til vinstri til að skipta hratt á milli forrita&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Trascina verso sinistra per cambiare velocemente app&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;יש לגרור שמאלה כדי לעבור במהירות בין אפליקציות&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;左にドラッグするとアプリを素早く切り替えることができます&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;აპების სწრაფად გადასართავად ჩავლებით გადაიტანეთ მარცხნივ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Қолданбалар арасында жылдам ауысу үшін солға қарай сүйреңіз&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;អូសទៅ​ឆ្វេង ដើម្បី​ប្ដូរកម្មវិធី​បានរហ័ស&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಿಸಲು ತ್ವರಿತವಾಗಿ ಎಡಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;앱을 빠르게 전환하려면 왼쪽으로 드래그&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Колдонмолорду тез которуштуруу үчүн, солго сүйрөңүз&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ລາກໄປຊ້າຍເພື່ອສະຫຼັບແອັບຢ່າງວ່ອງໄວ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Vilkite į kairę, kad greitai perjungtumėte programas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Lai ātri pārslēgtu lietotnes, velciet pa kreisi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Повлечете налево за брзо префрлање меѓу апликациите&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ആപ്പുകൾ പെട്ടെന്ന് മാറ്റാൻ ഇടത്തോട്ട് വലിച്ചിടുക&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Аппыг хурдан сэлгэхийн тулд зүүн тийш чирэх&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;अ‍ॅप्स त्वरित स्विच करण्यासाठी डावीकडे ड्रॅग करा&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Seret ke kiri untuk beralih apl dengan pantas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;အက်ပ်များ အမြန်ပြောင်းရန် ဘယ်ဘက်သို့ ဖိဆွဲပါ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Dra til venstre for å bytte app raskt&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;एपहरू द्रुत गतिमा बदल्न बायाँतिर ड्र्याग गर्नुहोस्&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Sleep naar links om snel tussen apps te schakelen&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ଆପ୍‌ ମଧ୍ୟରେ ଶୀଘ୍ର ବଦଳ କରିବା ପାଇଁ ବାମକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Przeciągnij w lewo, by szybko przełączyć aplikacje&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arraste para a esquerda para mudar rapidamente de app&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arraste para a esquerda para mudar rapidamente de app&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Arrastar para a esquerda para mudar rapidamente de app&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Trage spre stânga pentru a comuta rapid între aplicații&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Перетащите влево, чтобы быстро переключиться между приложениями&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ඉක්මනින් යෙදුම් මාරු කිරීමට වමට අදින්න&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Presunutím doľava rýchlo prepnete aplikácie&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Povlecite v levo za hiter preklop med aplikacijami&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Zvarrit majtas për të ndërruar aplikacionet me shpejtësi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Превуците улево да бисте брзо променили апликације&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Tryck och dra åt vänster för att snabbt byta mellan appar&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Buruta kushoto ili ubadili kati ya programu haraka&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ஆப்ஸை வேகமாக மாற்ற, இடப்புறம் இழுக்கவும்&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;యాప్‌లను శీఘ్రంగా స్విచ్ చేయడానికి ఎడమ వైపునకు లాగండి&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;ลากไปทางซ้ายเพื่อสลับแอปอย่างรวดเร็ว&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;I-drag pakaliwa para mabilisang magpalipat-lipat ng app.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Uygulamaları hızlıca değiştirmek için sola sürükleyin&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Потягніть уліво, щоб швидко переходити між додатками&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;تیزی سے ایپس کو سوئچ کرنے کے لیے بائيں طرف گھسیٹیں&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Ilovalarni tezkor almashtirish uchun chapga torting&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Kéo sang trái để chuyển nhanh giữa các ứng dụng&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;向左拖动可快速切换应用&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;向左拖曳即可快速切換應用程式&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;向左拖曳即可快速切換應用程式&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;recents_quick_scrub_onboarding&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;recents_quick_scrub_onboarding&quot; msgid=&quot;2452671841151577157&quot;>&quot;Hudulela ngakwesokunxele ukuze ushintshe ngokushesha izinhlelo zokusebenza&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu-ldrtl/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Vee alles uit&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;ሁሉንም  አጥራ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;محو الكل&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Выдаліць усё&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Изчистване&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Esborra-ho&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Smazat vše&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Ryd alt&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Löschen&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Εκκαθ. όλων&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Clear all&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Borrar todo&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Eliminar todas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Kust. kõik&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;پاک کردن همه موارد&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Tyhjennä kaikki&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Tout effacer&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;सभी साफ़ करें&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Obriši sve&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Össz.törl.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Hapus semua&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Cancella&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;נקה הכל&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;すべて消去&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;모두 지우기&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Išv. viską&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Notīr.visu&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Ksgkn smua&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Tøm alle&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Alles wissen&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Wyczyść&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Limpar tudo&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Limpar td&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Şterg. tot&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Очистить все&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Vymazať všetko&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Izbriši vse&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Обриши све&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Rensa alla&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Futa zote&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;ล้างทั้งหมด&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;I-clear&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Tümü temzl&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Очист. все&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Xóa tất cả&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;全部清除&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;全部清除&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;status_bar_clear_all_button&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;status_bar_clear_all_button&quot; msgid=&quot;4661583896803349732&quot;>&quot;Sula konke&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu-large/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Skerm is nou in landskapsoriëntering gesluit.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;አሁን ማያበወርድ ገፅ አቀማመጥ ተሸንጉሯል።&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;تم قفل الشاشة الآن في الاتجاه الأفقي&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;تم قفل الشاشة الآن في الاتجاه العمودي.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;স্ক্ৰীনখন এতিয়া লেণ্ডস্কে\&apos;প স্ক্ৰীনৰ দিশত লক কৰা অৱস্থাত আছে&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Hazırda ekran landşaft orientasiyasında kilidlənib.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekran je sada zaključan u vertikalnom položaju.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Цяпер экран заблакаваны ў альбомнай арыентацыі.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Екранът е заключен в хоризонтална ориентация.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Екранът е заключен във вертикална ориентация.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;এখন ল্যান্ডস্কেপ সজ্জাতে স্ক্রিন লক করা হয়েছে৷&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekran je sada zaključan u vodoravnom prikazu.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ara la pantalla està bloquejada en orientació horitzontal.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Ara la pantalla està bloquejada en orientació vertical.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Obrazovka je teď uzamčena v orientaci na šířku.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Skærmen er nu låst i liggende retning.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Bildschirm bleibt jetzt im Querformat.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ο προσανατολισμός της οθόνης κλειδώθηκε σε οριζόντια προβολή.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Screen is now locked in landscape orientation.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Screen is now locked in landscape orientation.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Screen is now locked in landscape orientation.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Screen is now locked in portrait orientation.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Screen is now locked in landscape orientation.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎Screen is now locked in landscape orientation.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;La pantalla está ahora bloqueada en orientación horizontal.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;La pantalla está bloqueada en orientación paisaje.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekraan on nüüd lukustatud horisontaalasendisse.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Pantaila horizontalki blokeatuta dago.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;صفحه اکنون در حالت افقی قفل است.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;صفحه اکنون در جهت عمودی قفل است.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ruutu on nyt lukittu vaakasuuntaan.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Ruutu on nyt lukittu pystysuuntaan.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;L\&apos;écran est désormais verrouillé en orientation paysage.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;L\&apos;écran est désormais verrouillé au format paysage.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Agora a pantalla está bloqueada en orientación horizontal.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;સ્ક્રીન હવે લેન્ડસ્કેપ ઓરિએન્ટેશનમાં લૉક કરેલ છે.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;स्क्रीन अभी लैंडस्केप दिशा में लॉक है.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Zaslona je sada zaključan u pejzažnoj orijentaciji.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Zaslona je sada zaključan u portretnoj orijentaciji.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;A képernyő zárolva van fekvő tájolásban.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;A képernyő zárolva van álló tájolásban.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Էկրանն այժմ կողպված է հորիզոնական դիրքավորման մեջ:&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Sekarang layar dikunci dalam orientasi lanskap.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Sekarang layar dikunci dalam orientasi potret.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Skjárinn er nú læstur á langsniði.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Lo schermo è bloccato in orientamento orizzontale.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;המסך נעול כעת לרוחב.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;המסך נעול כעת לאורך&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;画面を横向きにロックしました。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ეკრანი ამჟამად დაბლოკილია თარაზულ ორიენტაციაში&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Экран қазір ландшафт бағытына бекітілген.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ឥឡូវ​អេក្រង់​​ជាប់​សោ​ក្នុង​ទិស​ផ្ដេក។&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ಪರದೆಯು ಇದೀಗ ಲ್ಯಾಂಡ್‌ಸ್ಕೇಪ್ ಒರಿಯಂಟೇಶನ್‌ನಲ್ಲಿ ಲಾಕ್ ಆಗಿದೆ.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;화면이 현재 가로 방향으로 잠겨 있습니다.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Экран азыр туурасынан кулпуланган.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot;>Screen is now locked in landscape orientation.&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ໜ້າຈໍຕອນນີ້ຖືກລັອກໄວ້ໃນແບບລວງນອນ.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Dabar ekranas užrakintas horizontalioje pozicijoje.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Dabar ekranas užrakintas vertikalioje pozicijoje.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekrāns tagad ir bloķēts ainavas orientācijā.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Ekrāns tagad ir bloķēts portreta orientācijā.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Сега екранот е заклучен во ориентација на пејзаж.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ലാൻഡ്‌സ്‌കേപ്പ് ഓറിയന്റേഷനിൽ സ്ക്രീൻ ലോക്കുചെയ്‌തു.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Дэлгэц хэвтээ чиглэлд түгжигдсэн.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;स्‍क्रीन आता लॅंडस्केप ओरिएंटेशनमध्ये लॉक केली आहे.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Skrin kini dikunci dalam orientasi landskap.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ဖန်သားပြင် အနေအထားက အလျားလိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်။&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Skjermen er nå låst i liggende retning.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;स्क्रिन अहिले ल्यान्डस्केप अवस्थामा बन्द छ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Het scherm is nu vergrendeld in liggende stand.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ଲ୍ୟାଣ୍ଡସ୍କେପ୍ ଅବସ୍ଥାରେ ବର୍ତ୍ତମାନ ସ୍କ୍ରୀନ୍‌ଟି ଲକ୍ ଅଛି।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ਸਕ੍ਰੀਨ ਹੁਣ ਲੈਂਡਸਕੇਪ ਅਨੁਕੂਲਨ ਵਿੱਚ  ਲਾਕ  ਕੀਤੀ ਗਈ ਹੈ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekran jest teraz zablokowany w orientacji poziomej&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;A tela está bloqueada na orientação cenário.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;A tela está bloqueada na orientação cenário.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;O ecrã está agora bloqueado na orientação horizontal.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ecranul este acum blocat în orientarea de tip peisaj.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Ecranul este acum blocat în orientarea de tip portret.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Выбрана только альбомная ориентация экрана.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;තිරය දැන් තිරස් දිශානතිය අගුළු දමා ඇත.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Obrazovka je teraz uzamknutá v orientácii na šírku.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Obrazovka je teraz uzamknutá v orientácii na výšku.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Zaslon je zaklenjen v ležeči usmerjenosti.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Zaslon je zaklenjen v pokončni usmerjenosti.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekrani është kyçur tani në orientimin horizontal.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Екран је сада закључан у вертикалном положају.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Екран је сада закључан у хоризонталном положају.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Bildskärmens riktning är nu låst i liggande format.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Skrini imefungwa sasa katika uelekezo wa mandhari.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;தற்போது திரை நிலைபரப்பு திசையமைப்பில் பூட்டப்பட்டுள்ளது.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;స్క్రీన్ ఇప్పుడు ల్యాండ్‌స్కేప్ దృగ్విన్యాసంలో లాక్ చేయబడింది.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;ขณะนี้หน้าจอถูกล็อกในแนวนอน&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;ขณะนี้หน้าจอถูกล็อกการวางแนวในแนวตั้ง&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Naka-lock na ngayon ang screen at nasa pahigang oryentasyon.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Naka-lock na ngayon ang screen at nasa patayong orientation.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekran şimdi yatay yönde kilitlendi.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Екран зараз заблоковано в альбомній орієнтації.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Екран зараз заблоковано в книжковій орієнтації.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;اسکرین اب لینڈ اسکیپ سمت بندی میں مقفل ہے۔&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Ekran hozir albom joylashuvi bo‘yicha qulflanadi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Màn hình hiện bị khóa theo hướng ngang.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;1716565836190665743&quot;>&quot;Màn hình hiện bị khóa theo hướng dọc.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi-port/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;屏幕已锁定为横向浏览模式。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;螢幕現已鎖定為橫向模式&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;螢幕現已鎖定為橫向模式&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;toast_rotation_locked&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;toast_rotation_locked&quot; msgid=&quot;4914046305911646988&quot;>&quot;Isikrini okwamanje sivaliwe ekujikelezeni okumile.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu-land/strings.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Kennisgewings af&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;ማሳወቂያዎች ጠፍተዋል&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;إيقاف التنبيهات&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Паведамленні адключаныя&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Известията са изключени&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notificacions desactivades&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Oznámení jsou vypnuta&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Meddelelser: fra&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Benachrichtigungen aus&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Ειδοποιήσεις ανενεργές&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notifications off&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notificaciones desactivadas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notificaciones desactivadas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Teatised väljas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;اعلان ها خاموش&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Ilmoitukset pois käytöstä&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notifications désactivées&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;सूचनाएं बंद&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Obavijesti isključene&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Értesítések kikapcsolva&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Pemberitahuan mati&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notifiche disattivate&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;מצב התראות כבוי&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;通知OFF&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;알림 사용 안함&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Pranešimai išjungti&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Paziņojumi ir izslēgti.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Pemberitahuan dimatikan&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Varslinger er deaktivert&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Meldingen uit&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Powiadomienia wyłączone&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notificações desativadas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notificações desativadas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Notificările sunt dezactivate&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Уведомления отключены&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Upozornenia sú vypnuté&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Obvestila so izklopljena&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Обавештења су искључена&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Meddelanden inaktiverade&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Arifa imezimwa&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;การแจ้งเตือนปิดอยู่&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Naka-off ang mga notification&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Bildirimler kapalı&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Сповіщення вимкнено&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Tắt thông báo&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;通知功能已停用&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;關閉通知&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_title&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_title&quot; msgid=&quot;1860117696034775851&quot;>&quot;Izaziso zivaliwe&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu-large/strings.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tik hier om kennisgewings weer aan te skakel.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;ማሳወቂያን መልሶ ለማብራ እዚህ ሁለቴ ንካ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;انقر هنا لإعادة تشغيل التنبيهات.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Націсніце тут, каб зноў уключыць апавяшчэнні.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Докоснете тук, за да включите отново известията.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Pica aquí per tornar a activar les notificacions.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Chcete-li oznámení znovu zapnout, klepněte sem.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tryk her for at slå meddelelser til igen.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tippen Sie hier, um die Benachrichtigungen wieder zu aktivieren.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Πατήστε εδώ για να ενεργοποιήσετε ξανά τις ειδοποιήσεις.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tap here to turn notifications back on.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Toca aquí para volver a activar las notificaciones.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Toca aquí para volver a activar las notificaciones.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Teatiste uuesti sisselülitamiseks koputage siia.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;برای روشن کردن مجدد اعلان ها، اینجا را ضربه بزنید.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Ota ilmoitukset uudelleen käyttöön napauttamalla tätä.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Appuyez ici pour réactiver les notifications.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;सूचनाओं को पुन: चालू करने के लिए यहां टैप करें.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Dotaknite ovdje da biste ponovo uključili obavijesti.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Itt érintse meg az értesítések bekapcsolásához.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Ketuk di sini untuk menghidupkan pemberitahuan lagi.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tocca qui per riattivare le notifiche.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;הקש כאן כדי להפעיל מחדש את ההתראות.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;通知を再度ONにするにはここをタップします。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;알림을 다시 사용하려면 여기를 터치하세요.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Jei norite įjungti pranešimus, palieskite čia.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Pieskarieties šeit, lai atkal ieslēgtu paziņojumus.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Ketik di sini untuk menghidupkan kembali pemberitahuan.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Trykk her for å aktivere varslinger på nytt.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tik hier om meldingen weer in te schakelen.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Dotknij tutaj, aby z powrotem włączyć powiadomienia.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Toque aqui para ativar as notificações novamente.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Toque aqui para voltar a ativar as notificações.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Apăsaţi aici pentru a reactiva notificările.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Нажмите здесь, чтобы снова включить уведомления.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Klepnutím sem upozornenia znova povolíte.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Tapnite tukaj, da spet vklopite obvestila.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Додирните овде да бисте поново укључили обавештења.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Knacka lätt här om du vill aktivera meddelanden igen.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Gonga hapa ili kuwasha tena arifa.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Mag-tap dito upang i-on muli ang mga notification.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Bildirimleri tekrar açmak için buraya hafifçe vurun.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Торкніться тут, щоб знову ввімкнути сповіщення.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Chạm vào đây để bật lại thông báo.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;点按此处可重新启用通知功能。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;輕按這裡即可重新開啟通知。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;notifications_off_text&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;notifications_off_text&quot; msgid=&quot;1439152806320786912&quot;>&quot;Thepha lana ukuvula futhi izaziso.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu-large/strings.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;እንግዳ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ضيف&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;অতিথি&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Qonaq&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Госць&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Гост&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;অতিথি&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Convidat&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Host&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gæst&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gast&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Επισκέπτης&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎Guest‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Invitado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Invitado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Külaline&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gonbidatua&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;مهمان&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Vieras&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Invité&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Invité&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Convidado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;અતિથિ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;मेहमान&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Vendég&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Հյուր&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Tamu&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gestur&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Ospite&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;אורח&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ゲスト&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;სტუმარი&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Қонақ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ភ្ញៀវ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ಅತಿಥಿ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;게스트&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Конок&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ແຂກ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Svečias&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Viesis&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Гостин&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;അതിഥി&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Зочин&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;अतिथी&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Tetamu&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ဧည့်သည်&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gjest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;अतिथि&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gast&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ଅତିଥି&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ਮਹਿਮਾਨ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gość&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Visitante&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Convidado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Visitante&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Invitat&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Гость&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;අමුත්තා&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Hosť&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;I ftuar&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Гост&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Gäst&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Mgeni&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;விருந்தினர்&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;అతిథి&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;ผู้มาเยือน&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Bisita&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Misafir&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Гість&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;مہمان&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Mehmon&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Khách&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;访客&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;訪客&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;訪客&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_guest&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_guest&quot; msgid=&quot;3738772168718508650&quot;>&quot;Isivakashi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;እንግዳ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ضيف&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;অতিথি&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Qonaq&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Госць&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Гост&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;অতিথি&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Convidat&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Host&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gæst&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gast&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Επισκέπτης&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Guest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎Guest‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Invitado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Invitado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Külaline&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gonbidatua&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;مهمان&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Vieras&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Invité&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Invité&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Convidado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;અતિથિ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;मेहमान मोड&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Vendég&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Հյուր&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Tamu&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gestur&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Ospite&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;אורח&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ゲスト&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;სტუმარი&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Қонақ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ភ្ញៀវ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ಅತಿಥಿ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;게스트&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Конок&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ແຂກ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Svečias&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Viesis&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Гостин&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;അതിഥി&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Зочин&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;अतिथी&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Tetamu&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ဧည့်သည်&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gjest&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;अतिथि&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gast&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ଅତିଥି&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ਮਹਿਮਾਨ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gość&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Visitante&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Convidado&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Visitante&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Invitat&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Гость&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;අමුත්තා&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Hosť&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gost&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;I ftuar&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Гост&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Gäst&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Mgeni&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;விருந்தினர்&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;అతిథి&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;ผู้มาเยือน&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Bisita&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Misafir&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Гість&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;مہمان&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Mehmon&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Khách&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;访客&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;訪客&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;訪客&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;start_guest_session&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;start_guest_session&quot; msgid=&quot;7055742120180595689&quot;>&quot;Isivakashi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+            line="23"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Voeg gebruiker by&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ተጠቃሚ አክል&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;إضافة المستخدم&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ব্যৱহাৰকাৰী যোগ কৰক&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;İstifadəçi əlavə edin&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Dodaj korisnika&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Дадаць карыстальніка&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Добавяне на потребител&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ব্যবহারকারীকে যুক্ত করুন&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Dodaj korisnika&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Afegeix un usuari&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Přidat uživatele&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Tilføj bruger&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Nutzer hinzufügen&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Προσθήκη χρήστη&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Add User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Add User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Add User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Add User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‎Add User‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Agregar usuario&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Añadir usuario&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Kasutaja lisamine&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Gehitu erabiltzaile bat&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;افزودن کاربر&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Lisää käyttäjä&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Ajouter un utilisateur&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Ajouter un utilisateur&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Engadir usuario&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;વપરાશકર્તા ઉમેરો&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;उपयोगकर्ता जोड़ें&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Dodajte korisnika&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Felhasználó hozzáadása&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Ավելացնել օգտատեր&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Tambahkan Pengguna&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Bæta notanda við&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Aggiungi utente&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;הוספת משתמש&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ユーザーを追加&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;მომხმარებლის დამატება&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Пайдаланушыны енгізу&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;បញ្ចូល​អ្នក​ប្រើប្រាស់&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ಬಳಕೆದಾರ ಸೇರಿಸು&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;사용자 추가&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Колдонуучу кошуу&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ເພີ່ມຜູ້ໃຊ້&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Pridėti naudotoją&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Lietotāja pievienošana&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Додај корисник&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ഉപയോക്താവിനെ ചേര്‍ക്കുക&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Хэрэглэгч нэмэх&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;वापरकर्ता जोडा&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Tambah Pengguna&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;အသုံးပြုသူ ထည့်ရန်&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Legg til bruker&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;प्रयोगकर्ता थप्नुहोस्&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Gebruiker toevoegen&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ୟୁଜର୍‍ଙ୍କୁ ଯୋଡ଼ନ୍ତୁ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Dodaj użytkownika&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Adicionar usuário&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Adicionar utilizador&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Adicionar usuário&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Adăugați un utilizator&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Добавить пользователя&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;පරිශීලක එක් කරන්න&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Pridať používateľa&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Dodaj uporabnika&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Shto përdorues&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Додај корисника&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Lägg till användare&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Ongeza Mtumiaji&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;பயனரைச் சேர்க்கவும்&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;వినియోగదారును జోడించండి&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;เพิ่มผู้ใช้&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Magdagdag ng User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Kullanıcı Ekle&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Додати користувача&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;صارف شامل کریں&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Foydalanuvchi qo‘shish&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Thêm người dùng&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;添加用户&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;新增使用者&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;新增使用者&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_add_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_add_user&quot; msgid=&quot;5245196248349230898&quot;>&quot;Engeza umsebenzisi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+            line="24"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nuwe gebruiker&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;አዲስ ተጠቃሚ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;مستخدم جديد&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;নতুন ব্যৱহাৰকাৰী&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Yeni İstifadəçi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novi korisnik&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Новы карыстальнік&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Нов потребител&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;নতুন ব্যবহারকারী&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novi korisnik&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Usuari nou&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nový uživatel&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Ny bruger&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Neuer Nutzer&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Νέος χρήστης&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;New User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;New User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;New User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;New User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎New User‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nuevo usuario&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nuevo usuario&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Uus kasutaja&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Erabiltzaile berria&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;کاربر جدید&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Uusi käyttäjä&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nouvel utilisateur&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nouvel utilisateur&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novo usuario&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;નવા વપરાશકર્તા&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;नया उपयोगकर्ता&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novi korisnik&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Új felhasználó&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Նոր օգտատեր&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Pengguna Baru&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nýr notandi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nuovo utente&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;משתמש חדש&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;新しいユーザー&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;ახალი მომხმარებელი&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Жаңа пайдаланушы&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;អ្នក​ប្រើប្រាស់​ថ្មី&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;ಹೊಸ ಬಳಕೆದಾರ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;신규 사용자&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Жаңы колдонуучу&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;ຜູ້ໃຊ້ໃໝ່&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Naujas naudotojas&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Jauns lietotājs&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Нов корисник&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;പുതിയ ഉപയോക്താവ്&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Шинэ хэрэглэгч&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;नवीन वापरकर्ता&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Pengguna Baharu&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;အသုံးပြုသူ အသစ်&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Ny bruker&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;नयाँ प्रयोगकर्ता&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nieuwe gebruiker&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;ନୂଆ ୟୁଜର୍‍&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;ਨਵਾਂ ਵਰਤੋਂਕਾਰ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nowy użytkownik&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novo usuário&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novo utilizador&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Novo usuário&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Utilizator nou&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Новый пользователь&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;නව පරිශීලක&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nový používateľ&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Nov uporabnik&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Përdorues i ri&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Нови корисник&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Ny användare&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Mtumiaji Mpya&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;புதிய பயனர்&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;కొత్త వినియోగదారు&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;ผู้ใช้ใหม่&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Bagong User&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Yeni Kullanıcı&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Новий користувач&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;نیا صارف&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Yangi foydalanuvchi&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Người dùng mới&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;新用户&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;新使用者&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;新使用者&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;car_new_user&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;car_new_user&quot; msgid=&quot;8142927244990323906&quot;>&quot;Umsebenzisi omusha&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+            line="25"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Wanneer jy \&apos;n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሳቸውን ቦታ ማቀናበር አለባቸው።&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;عند إضافة مستخدم جديد، عليه إعداد مساحته.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;আপুনি কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰিলে তেখেতে নিজৰ বাবে খালী ঠাই ছেট আপ কৰিব লাগে।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Yeni istifadəçi əlavə etdiyinizdə həmin şəxs öz yerini təyin etməlidir.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Калі вы дадаяце новага карыстальніка, яму трэба наладзіць свой профіль.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Когато добавите нов потребител, той трябва да настрои работното си пространство.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;আপনি কোনও নতুন ব্যবহারকারীকে যোগ করলে তাকে তার স্পেস সেট-আপ করে নিতে হবে।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Quan s\&apos;afegeix un usuari nou, aquest usuari ha de configurar el seu espai.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Každý nově přidaný uživatel si musí nastavit vlastní prostor.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Når du tilføjer en ny bruger, skal vedkommende konfigurere sit område.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Όταν προσθέτετε έναν νέο χρήστη, αυτός ο χρήστης θα πρέπει να ρυθμίσει τον χώρο του.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;When you add a new user, that person needs to set up their space.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;When you add a new user, that person needs to set up their space.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;When you add a new user, that person needs to set up their space.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;When you add a new user, that person needs to set up their space.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎When you add a new user, that person needs to set up their space.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Cuando agregues un usuario nuevo, esa persona deberá configurar su espacio.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Al añadir un nuevo usuario, este debe configurar su espacio.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Erabiltzaile bat gehitzen duzunean, bere eremua konfiguratu beharko du.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;وقتی کاربر جدیدی اضافه می‌کنید، آن فرد باید فضای خود را تنظیم کند.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kun lisäät uuden käyttäjän, hänen on määritettävä oman tilansa asetukset.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Cando engadas un usuario novo, este deberá configurar o seu espazo.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિએ તેમની સ્પેસ સેટ કરવાની જરૂર રહે છે.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो, उस व्यक्ति को अपनी जगह सेट करनी होती है.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját felületét.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Երբ դուք նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Þegar þú bætir nýjum notanda við þarf viðkomandi að setja upp sitt eigið svæði.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Il nuovo utente, una volta aggiunto, dovrà configurare il proprio spazio.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;בעת הוספת משתמש חדש, על משתמש זה להגדיר את המרחב שלו.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Енгізілген жаңа пайдаланушы өз профилін реттеуі керек.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;នៅពេលដែល​អ្នក​បញ្ចូល​អ្នក​ប្រើប្រាស់​ថ្មី បុគ្គល​នោះ​ត្រូវតែ​រៀបចំ​ទំហំ​ផ្ទុក​របស់គេ។&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;ನೀವು ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Жаңы колдонуучу кошулганда, ал өзүнүн профилин жөндөп алышы керек.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ບຸກຄົນນັ້ນຈຳເປັນຕ້ອງຕັ້ງຄ່າພື້ນທີ່ຂອງເຂົາເຈົ້າ.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo vietą.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kad pievienosiet jaunu lietotāju, viņam būs jāizveido savs profils.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Кога додавате нов корисник, тоа лице треба да го постави својот простор.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;നിങ്ങളൊരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തി സ്വന്തം ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Таныг шинэ хэрэглэгч нэмэх үед тухайн хэрэглэгч хувийн орон зайгаа тохируулах шаардлагатай.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;तुम्ही नवीन वापरकर्त्याला जोडल्यावर, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Apabila anda menambahkan pengguna baharu, orang itu perlu menyediakan ruang mereka.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;အသုံးပြုသူအသစ် ထည့်သည့်အခါ ထိုသူသည် မိမိ၏ နေရာကို စီစဉ်သတ်မှတ်ရပါမည်။&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;तपाईंले नयाँ प्रयोगकर्ता थप्दा ती व्यक्तिले आफ्नो स्थान सेटअप गर्नु पर्छ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Wanneer je een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;ଯେତେବେଳେ ଆପଣ ଜଣେ ନୂଆ ୟୁଜର୍‍ଙ୍କୁ ଯୋଡ଼ିବେ, ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ନିଜ ପାଇଁ ସ୍ପେସ୍‍ ସେଟ‍ଅପ୍ କରିବାକୁ ପଡ଼ିବ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Когда вы добавите пользователя, ему потребуется настроить профиль.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;ඔබ අලුත් පරිශීලකයෙක් එක් කරන විට, එම පුද්ගලයාට තමන්ගේ ඉඩ සකසා ගැනීමට අවශ්‍ය වේ.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Ko dodate novega uporabnika, mora ta nastaviti svoj prostor.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Када додате новог корисника, та особа треба да подеси свој простор.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;När du lägger till en ny användare måste den personen konfigurera sitt utrymme.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Ukiongeza mtumiaji mpya, ni lazima aweke kikundi chake.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;మీరు కొత్త వినియోగదారును జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Yeni kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Коли ви додаєте нового користувача, він має налаштувати свій профіль.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے۔&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Yangi profil qo‘shilgach, uni sozlash lozim.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Khi bạn thêm một người dùng mới, người đó cần thiết lập không gian của họ.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;当您添加新用户时,该用户必须设置自己的空间。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;新增的使用者需要自行設定個人空間。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;新增的使用者需要自行設定個人空間。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_setup&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_setup&quot; msgid=&quot;1791011504259527329&quot;>&quot;Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha izikhala zakhe.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+            line="26"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Enige gebruiker kan programme vir al die ander gebruikers opdateer.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ማዘመን ይችላል።&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;يمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;সকলো ব্য়ৱহাৰকাৰীয়ে অইন ব্য়ৱহাৰকাৰীৰ বাবে এপসমূহ আপডেট কৰিব পাৰে।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;İstənilən istifadəçi digər bütün istifadəçilər üçün tətbiqləri güncəlləyə bilər.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Svaki korisnik može da ažurira aplikacije za sve ostale korisnike.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Кожны карыстальнік прылады можа абнаўляць праграмы для іншых уліковых запісаў.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Всеки потребител може да актуализира приложенията за всички останали потребители.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;যেকোনও ব্যবহারকারী বাকি সব ব্যবহারকারীর জন্য অ্যাপ আপডেট করতে পারবেন।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Svaki korisnik može ažurirati aplikacije za sve druge korisnike.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Qualsevol usuari pot actualitzar les aplicacions de la resta d\&apos;usuaris.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Každý uživatel může aktualizovat aplikace všech ostatních uživatelů.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Alle brugere kan opdatere apps for alle andre brugere.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Jeder Nutzer kann Apps für alle anderen Nutzer aktualisieren.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Οποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Any user can update apps for all other users.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Any user can update apps for all other users.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Any user can update apps for all other users.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Any user can update apps for all other users.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‎Any user can update apps for all other users.‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Cualquier usuario podrá actualizar las apps de otras personas.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Cualquier usuario puede actualizar las aplicaciones del resto de los usuarios.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Iga kasutaja saab rakendusi värskendada kõigi teiste kasutajate jaoks.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Edozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;هر کاربری می‌تواند برنامه‌ها را برای همه کاربران دیگر به‌روزرسانی کند.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Kaikki käyttäjät voivat päivittää muiden käyttäjien sovelluksia.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Tout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;N\&apos;importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Calquera usuario pode actualizar as aplicacións para o resto dos usuarios.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;કોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;कोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकते हैं.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Svaki korisnik može ažurirati aplikacije za ostale korisnike.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Bármely felhasználó frissítheti az alkalmazásokat az összes felhasználó számára.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Ցանկացած օգտատեր կարող է թարմացնել հավելվածները բոլոր մյուս հաշիվների համար:&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Setiap pengguna dapat mengupdate aplikasi untuk semua pengguna lain.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Allir notendur geta uppfært forrit fyrir alla aðra notendur.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Qualsiasi utente può aggiornare le app per tutti gli altri.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;כל משתמש יכול לעדכן אפליקציות לכל שאר המשתמשים.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;どのユーザーも他のすべてのユーザーに代わってアプリを更新できます。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Кез келген пайдаланушы қолданбаларды барлық басқа пайдаланушылар үшін жаңарта алады.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;អ្នកប្រើប្រាស់​ណាក៏​អាច​ដំឡើង​ជំនាន់កម្មវិធី​សម្រាប់​អ្នក​ប្រើប្រាស់​ទាំងអស់​ផ្សេង​ទៀត​បាន​ដែរ។&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬಹುದು.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;모든 사용자는 다른 사용자를 위해 앱을 업데이트할 수 있습니다.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Колдонмолорду бир колдонуучу калган бардык колдонуучулар үчүн да жаңырта алат.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ຜູ້ໃຊ້ຕ່າງໆສາມາດອັບເດດແອັບສຳລັບຜູ້ໃຊ້ອື່ນທັງໝົດໄດ້.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Bet kuris naudotojas gali atnaujinti visų kitų naudotojų programas.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Ikviens lietotājs var atjaunināt lietotnes citu lietotāju vietā.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Секој корисник може да ажурира апликации за сите други корисници.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ഏതൊരു ഉപയോക്താവിനും മറ്റെല്ലാ ഉപയോക്താക്കൾക്കുമായി ആപ്പുകൾ അപ്‌ഡേറ്റ് ചെയ്യാനാവും.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Бусад бүх хэрэглэгчийн аппыг дурын хэрэглэгч шинэчлэх боломжтой.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;कोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Mana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;အသုံးပြုသူအားလုံးအတွက် အက်ပ်များကို မည်သူမဆို အပ်ဒိတ်လုပ်နိုင်သည်။&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Alle brukere kan oppdatere apper for alle andre brukere.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;सबै प्रयोगकर्ताले अन्य प्रयोगकर्ताका अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Elke gebruiker kan apps updaten voor alle andere gebruikers.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ଯେକୌଣସି ୟୁଜର୍ ଅନ୍ୟ ସମସ୍ତ ୟୁଜରଙ୍କ ପାଇଁ ଆପ୍‍କୁ ଅପଡେଟ୍ କରିପାରିବେ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Każdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Qualquer usuário pode atualizar apps para os demais usuários&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Qualquer utilizador pode atualizar aplicações para todos os outros utilizadores.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Qualquer usuário pode atualizar apps para os demais usuários&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Orice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Любой пользователь устройства может обновлять приложения для всех аккаунтов.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;සියලුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යෙදුම් යාවත්කාලීන කළ හැක.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Akýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Vsak uporabnik lahko posodobi aplikacije za vse druge uporabnike.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Çdo përdorues mund t\&apos;i përditësojë aplikacionet për të gjithë përdoruesit e tjerë.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Сваки корисник може да ажурира апликације за све остале кориснике.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Alla användare kan uppdatera appar för andra användare.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Mtumiaji yeyote anaweza kusasisha programu za watumiaji wengine.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;எந்தவொரு பயனரும், மற்ற பயனர்களுக்காக ஆப்ஸைப் புதுப்பிக்கலாம்.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం యాప్‌లను అప్‌డేట్ చేయవచ్చు.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;ผู้ใช้ทุกคนจะอัปเดตแอปให้แก่ผู้ใช้คนอื่นๆ ได้&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Maaaring mag-update ng mga app ang sinumang user para sa lahat ng iba pang user.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Herhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Будь-який користувач може оновлювати додатки для решти людей.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;کوئی بھی صارف دیگر سبھی صارفین کیلئے ایپس کو اپ ڈیٹ کر سکتا ہے۔&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Qurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Bất kỳ người dùng nào cũng có thể cập nhật ứng dụng cho tất cả những người dùng khác.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;任何用户均可为所有其他用户更新应用。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;任何使用者都可以為所有其他使用者更新應用程式。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;任何使用者皆可為所有其他使用者更新應用程式。&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ExtraTranslation"
+        message="&quot;user_add_user_message_update&quot; is translated here but not found in default locale"
+        errorLine1="    &lt;string name=&quot;user_add_user_message_update&quot; msgid=&quot;3383320289232716179&quot;>&quot;Noma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza zabanye abasebenzisi.&quot;&lt;/string>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+            line="27"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_top_boundary_pct&quot; msgid=&quot;2520148599096479332&quot;>&quot;Top boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="95"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_top_boundary_pct&quot; msgid=&quot;2520148599096479332&quot;>&quot;Top boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="95"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_top_boundary_pct&quot; msgid=&quot;2520148599096479332&quot;>&quot;Top boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="95"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_top_boundary_pct&quot; msgid=&quot;2520148599096479332&quot;>&quot;Top boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> percent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="95"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_bottom_boundary_pct&quot; msgid=&quot;3880821519814946478&quot;>&quot;Bottom boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="96"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_bottom_boundary_pct&quot; msgid=&quot;3880821519814946478&quot;>&quot;Bottom boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="96"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_bottom_boundary_pct&quot; msgid=&quot;3880821519814946478&quot;>&quot;Bottom boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="96"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_bottom_boundary_pct&quot; msgid=&quot;3880821519814946478&quot;>&quot;Bottom boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> percent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="96"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_left_boundary_pct&quot; msgid=&quot;8502323556112287469&quot;>&quot;Left boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="97"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_left_boundary_pct&quot; msgid=&quot;8502323556112287469&quot;>&quot;Left boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="97"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_left_boundary_pct&quot; msgid=&quot;8502323556112287469&quot;>&quot;Left boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="97"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_left_boundary_pct&quot; msgid=&quot;8502323556112287469&quot;>&quot;Left boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> percent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="97"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_right_boundary_pct&quot; msgid=&quot;1201150713021779321&quot;>&quot;Right boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="98"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_right_boundary_pct&quot; msgid=&quot;1201150713021779321&quot;>&quot;Right boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="98"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_right_boundary_pct&quot; msgid=&quot;1201150713021779321&quot;>&quot;Right boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> per cent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="98"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_right_boundary_pct&quot; msgid=&quot;1201150713021779321&quot;>&quot;Right boundary &lt;xliff:g id=&quot;PERCENT&quot;>%1$d&lt;/xliff:g> percent&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="98"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;seconds&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;biometric_dialog_credential_too_many_attempts&quot; msgid=&quot;3083141271737748716&quot;>&quot;Too many incorrect attempts.\nTry again in &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> seconds.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="176"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;seconds&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;biometric_dialog_credential_too_many_attempts&quot; msgid=&quot;3083141271737748716&quot;>&quot;Too many incorrect attempts.\nTry again in &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> seconds.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="176"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;seconds&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;biometric_dialog_credential_too_many_attempts&quot; msgid=&quot;3083141271737748716&quot;>&quot;Too many incorrect attempts.\nTry again in &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> seconds.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="176"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;seconds&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;biometric_dialog_credential_too_many_attempts&quot; msgid=&quot;3083141271737748716&quot;>&quot;Too many incorrect attempts.\nTry again in &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> seconds.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="176"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level&quot; msgid=&quot;5143715405241138822&quot;>&quot;Battery &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> per cent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="224"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level&quot; msgid=&quot;5143715405241138822&quot;>&quot;Battery &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> per cent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="224"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level&quot; msgid=&quot;5143715405241138822&quot;>&quot;Battery &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> per cent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="224"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level&quot; msgid=&quot;5143715405241138822&quot;>&quot;Battery &lt;xliff:g id=&quot;NUMBER&quot;>%d&lt;/xliff:g> percent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="224"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_with_estimate&quot; msgid=&quot;6548654589315074529&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> per cent; &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="225"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_with_estimate&quot; msgid=&quot;6548654589315074529&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> per cent; &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="225"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_with_estimate&quot; msgid=&quot;6548654589315074529&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> per cent; &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="225"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_with_estimate&quot; msgid=&quot;6548654589315074529&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> percent, &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="225"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging&quot; msgid=&quot;8892191177774027364&quot;>&quot;Battery charging, &lt;xliff:g id=&quot;BATTERY_PERCENTAGE&quot;>%d&lt;/xliff:g> percent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="226"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging&quot; msgid=&quot;8892191177774027364&quot;>&quot;Battery charging, &lt;xliff:g id=&quot;BATTERY_PERCENTAGE&quot;>%d&lt;/xliff:g> percent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="226"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging&quot; msgid=&quot;8892191177774027364&quot;>&quot;Battery charging, &lt;xliff:g id=&quot;BATTERY_PERCENTAGE&quot;>%d&lt;/xliff:g> percent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="226"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging&quot; msgid=&quot;8892191177774027364&quot;>&quot;Battery charging, &lt;xliff:g id=&quot;BATTERY_PERCENTAGE&quot;>%d&lt;/xliff:g> percent.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="226"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused&quot; msgid=&quot;3560711496775146763&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%d&lt;/xliff:g> per cent; charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="227"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused&quot; msgid=&quot;3560711496775146763&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%d&lt;/xliff:g> per cent; charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="227"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused&quot; msgid=&quot;3560711496775146763&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%d&lt;/xliff:g> per cent; charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="227"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused&quot; msgid=&quot;3560711496775146763&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%d&lt;/xliff:g> percent, charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="227"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused_with_estimate&quot; msgid=&quot;2223541217743647858&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> per cent; &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>, charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="228"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused_with_estimate&quot; msgid=&quot;2223541217743647858&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> per cent; &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>, charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="228"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;per&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused_with_estimate&quot; msgid=&quot;2223541217743647858&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> per cent; &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>, charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="228"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused_with_estimate&quot; msgid=&quot;2223541217743647858&quot;>&quot;Battery &lt;xliff:g id=&quot;PERCENTAGE&quot;>%1$d&lt;/xliff:g> percent, &lt;xliff:g id=&quot;TIME&quot;>%2$s&lt;/xliff:g>, charging paused for battery protection.&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="228"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_top_boundary_pct&quot;>Top boundary &lt;xliff:g id=&quot;percent&quot; example=&quot;50&quot;>%1$d&lt;/xliff:g> percent&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="251"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_bottom_boundary_pct&quot;>Bottom boundary &lt;xliff:g id=&quot;percent&quot; example=&quot;50&quot;>%1$d&lt;/xliff:g> percent&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="253"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_left_boundary_pct&quot;>Left boundary &lt;xliff:g id=&quot;percent&quot; example=&quot;50&quot;>%1$d&lt;/xliff:g> percent&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="255"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;screenshot_right_boundary_pct&quot;>Right boundary &lt;xliff:g id=&quot;percent&quot; example=&quot;50&quot;>%1$d&lt;/xliff:g> percent&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="257"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;seconds&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;biometric_dialog_credential_too_many_attempts&quot;>Too many incorrect attempts.\nTry again in &lt;xliff:g id=&quot;number&quot;>%d&lt;/xliff:g> seconds.&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="429"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level&quot;>Battery &lt;xliff:g id=&quot;number&quot;>%d&lt;/xliff:g> percent.&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="535"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_with_estimate&quot;>Battery &lt;xliff:g id=&quot;percentage&quot; example=&quot;95%&quot;>%1$d&lt;/xliff:g> percent, &lt;xliff:g id=&quot;time&quot; example=&quot;Until 3:15pm&quot;>%2$s&lt;/xliff:g>&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="538"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging&quot;>Battery charging, &lt;xliff:g id=&quot;battery_percentage&quot;>%d&lt;/xliff:g> percent.&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="541"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused&quot;>Battery &lt;xliff:g id=&quot;percentage&quot; example=&quot;90%&quot;>%d&lt;/xliff:g> percent, charging paused for battery protection.&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="544"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;percent&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;accessibility_battery_level_charging_paused_with_estimate&quot;>Battery &lt;xliff:g id=&quot;percentage&quot; example=&quot;90%&quot;>%1$d&lt;/xliff:g> percent, &lt;xliff:g id=&quot;time&quot; example=&quot;Until 3:15pm&quot;>%2$s&lt;/xliff:g>, charging paused for battery protection.&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="547"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;tiles&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;drag_to_remove_disabled&quot; msgid=&quot;933046987838658850&quot;>&quot;You need at least &lt;xliff:g id=&quot;MIN_NUM_TILES&quot;>%1$d&lt;/xliff:g> tiles&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="835"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;tiles&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;drag_to_remove_disabled&quot; msgid=&quot;933046987838658850&quot;>&quot;You need at least &lt;xliff:g id=&quot;MIN_NUM_TILES&quot;>%1$d&lt;/xliff:g> tiles&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="840"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;tiles&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;drag_to_remove_disabled&quot; msgid=&quot;933046987838658850&quot;>&quot;You need at least &lt;xliff:g id=&quot;MIN_NUM_TILES&quot;>%1$d&lt;/xliff:g> tiles&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="840"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;tiles&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;drag_to_remove_disabled&quot; msgid=&quot;933046987838658850&quot;>&quot;You need at least &lt;xliff:g id=&quot;MIN_NUM_TILES&quot;>%1$d&lt;/xliff:g> tiles&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="840"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;devices&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_dialog_multiple_devices&quot; msgid=&quot;1093771040315422350&quot;>&quot;&lt;xliff:g id=&quot;COUNT&quot;>%1$d&lt;/xliff:g> devices selected&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="1096"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;devices&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_dialog_multiple_devices&quot; msgid=&quot;1093771040315422350&quot;>&quot;&lt;xliff:g id=&quot;COUNT&quot;>%1$d&lt;/xliff:g> devices selected&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="1101"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;devices&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_dialog_multiple_devices&quot; msgid=&quot;1093771040315422350&quot;>&quot;&lt;xliff:g id=&quot;COUNT&quot;>%1$d&lt;/xliff:g> devices selected&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="1101"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;devices&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_dialog_multiple_devices&quot; msgid=&quot;1093771040315422350&quot;>&quot;&lt;xliff:g id=&quot;COUNT&quot;>%1$d&lt;/xliff:g> devices selected&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="1101"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;characters&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_broadcast_edit_hint_no_more_than_max&quot; msgid=&quot;3923625800037673922&quot;>&quot;Use fewer than &lt;xliff:g id=&quot;LENGTH&quot;>%1$d&lt;/xliff:g> characters&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="1122"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;characters&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_broadcast_edit_hint_no_more_than_max&quot; msgid=&quot;3923625800037673922&quot;>&quot;Use fewer than &lt;xliff:g id=&quot;LENGTH&quot;>%1$d&lt;/xliff:g> characters&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="1127"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;characters&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_broadcast_edit_hint_no_more_than_max&quot; msgid=&quot;3923625800037673922&quot;>&quot;Use fewer than &lt;xliff:g id=&quot;LENGTH&quot;>%1$d&lt;/xliff:g> characters&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="1127"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;characters&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_broadcast_edit_hint_no_more_than_max&quot; msgid=&quot;3923625800037673922&quot;>&quot;Use fewer than &lt;xliff:g id=&quot;LENGTH&quot;>%1$d&lt;/xliff:g> characters&quot;&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="1127"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;tiles&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;drag_to_remove_disabled&quot;>You need at least &lt;xliff:g id=&quot;min_num_tiles&quot; example=&quot;6&quot;>%1$d&lt;/xliff:g> tiles&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="2211"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;devices&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_dialog_multiple_devices&quot;>&lt;xliff:g id=&quot;count&quot; example=&quot;2&quot;>%1$d&lt;/xliff:g> devices selected&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="2922"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="PluralsCandidate"
+        message="Formatting %d followed by words (&quot;characters&quot;): This should probably be a plural rather than a string"
+        errorLine1="    &lt;string name=&quot;media_output_broadcast_edit_hint_no_more_than_max&quot;>Use fewer than &lt;xliff:g id=&quot;length&quot; example=&quot;16&quot;>%1$d&lt;/xliff:g> characters&lt;/string>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="2977"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="UnsafeIntentLaunch"
+        message="This intent could be coming from an untrusted source. It is later launched by an unprotected component. You could either make the component protected; or sanitize this intent using androidx.core.content.IntentSanitizer."
+        errorLine1="                final IntentSender intentSender = intent.getParcelableExtra("
+        errorLine2="                                                  ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+            line="231"
+            column="51"/>
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+            line="239"
+            column="25"
+            message="The unsafe intent is launched here."/>
+    </issue>
+
+    <issue
+        id="ExportedContentProvider"
+        message="Exported content providers can provide access to potentially sensitive data"
+        errorLine1="        &lt;provider android:name=&quot;.keyguard.KeyguardSliceProvider&quot; android:authorities=&quot;com.android.systemui.keyguard&quot; android:grantUriPermissions=&quot;true&quot; android:exported=&quot;true&quot;>"
+        errorLine2="         ~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="678"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExportedReceiver"
+        message="Exported receiver does not require permission"
+        errorLine1="        &lt;receiver android:name=&quot;.statusbar.KeyboardShortcutsReceiver&quot; android:exported=&quot;true&quot;>"
+        errorLine2="         ~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="681"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExportedReceiver"
+        message="Exported receiver does not require permission"
+        errorLine1="        &lt;receiver android:name=&quot;.media.dialog.MediaOutputDialogReceiver&quot; android:exported=&quot;true&quot;>"
+        errorLine2="         ~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="688"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExportedService"
+        message="Exported service does not require permission"
+        errorLine1="        &lt;service android:name=&quot;SystemUIService&quot; android:exported=&quot;true&quot;/>"
+        errorLine2="         ~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="381"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExportedService"
+        message="Exported service does not require permission"
+        errorLine1="        &lt;service android:name=&quot;.wallet.controller.WalletContextualLocationsService&quot; android:exported=&quot;true&quot;/>"
+        errorLine2="         ~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="382"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExportedService"
+        message="Exported service does not require permission"
+        errorLine1="        &lt;service android:name=&quot;.keyguard.KeyguardService&quot; android:exported=&quot;true&quot;/>"
+        errorLine2="         ~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="557"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExportedService"
+        message="Exported service does not require permission"
+        errorLine1="        &lt;service android:name=&quot;.dreams.DreamOverlayService&quot; android:enabled=&quot;false&quot; android:exported=&quot;true&quot; android:singleUser=&quot;true&quot;/>"
+        errorLine2="         ~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="559"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ExpiredTargetSdkVersion"
+        message="Google Play requires that apps target API level 33 or higher."
+        errorLine1="    &lt;uses-sdk android:minSdkVersion=&quot;VanillaIceCream&quot; android:targetSdkVersion=&quot;16&quot;/>"
+        errorLine2="                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+            line="21"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/AdditionalStartable.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/BackupManagerProxy.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutSection.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatterySaverModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricOperationInfo.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=" * Copyright (C) 2022 The Android Open Source Project"
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=" * Copyright (C) 2022 The Android Open Source Project"
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/CarrierTextManagerLog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationComponent.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationComponent.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialHeaderViewModel.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractor.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPatternView.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPatternViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialStatus.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialView.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/DisplayRotation.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/EllipseOverlapDetectorParams.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ExpandableOutlineViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ExpandableOutlineViewModel.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ExpandableViewBinder.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ExpandableViewModel.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/FaceAuthLog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromBouncerToGoneTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToGoneTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardClockFrame.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardDisplayModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardLog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardStatusContainer.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/LargeScreenUtils.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=" * Copyright (C) 2022 The Android Open Source Project"
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaDataUtils.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/flags/NotOccludedCondition.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryMeter.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PlaceHolderDrawable.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/ProtoDumpable.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/dagger/QSComponent.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSDisableFlagsLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSRestoreLog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScopeModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QsBatteryModeController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QuickTileLayout.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/ReferenceExt.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/RemainingAttempts.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/model/RestoreData.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/rotationlock/RotationLockModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/SafeMarqueeTextView.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHideIconsForBouncerManager.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLogger.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverter.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/unfold/UnfoldKeyguardVisibilityListener.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepository.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/utils/UserRestrictionChecker.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitchDialog.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/VariableDayDate.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProvider.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/shared/model/WakefulnessModel.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualLocationsService.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */"
+        errorLine1=""
+        errorLine2=" ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProvider.kt"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="MissingApacheLicenseDetector"
+        message="License header is missing&#xA;Please add the following copyright and license header to the beginning of the file:&#xA;&#xA;/*&#xA; * Copyright (C) 2024 The Android Open Source Project&#xA; *&#xA; * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#xA; * you may not use this file except in compliance with the License.&#xA; * You may obtain a copy of the License at&#xA; *&#xA; *     http://www.apache.org/licenses/LICENSE-2.0&#xA; *&#xA; * Unless required by applicable law or agreed to in writing, software&#xA; * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#xA; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xA; * See the License for the specific language governing permissions and&#xA; * limitations under the License.&#xA; */">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java"
+            line="2"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        Paint pt = new Paint();"
+        errorLine2="                   ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/DessertCaseView.java"
+            line="491"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        final Rect check = new Rect();"
+        errorLine2="                           ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/DessertCaseView.java"
+            line="496"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        mOuterCircle = new Path();"
+        errorLine2="                       ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/MagnifierView.java"
+            line="114"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        mInnerCircle = new Path();"
+        errorLine2="                       ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/MagnifierView.java"
+            line="116"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        Rect scrimRect = new Rect(0, 0, getWidth(), getHeight() / 2);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/MagnifierView.java"
+            line="143"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw operations: Use `Canvas.getClipBounds(Rect)` instead of `Canvas.getClipBounds()` which allocates a temporary `Rect`"
+        errorLine1="        val bounds = canvas.clipBounds"
+        errorLine2="                     ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt"
+            line="63"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="            mBarTransitions.setBackgroundFrame(new Rect(0, frameHeight - height, w, h));"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+            line="1001"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        Paint paint = new Paint();"
+        errorLine2="                      ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java"
+            line="200"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="            Paint pt = new Paint();"
+        errorLine2="                       ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+            line="151"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        SmartSuggestionMeasures accumulatedMeasures = new SmartSuggestionMeasures("
+        errorLine2="                                                      ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+            line="240"
+            column="55"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        List&lt;View> smartSuggestions = new ArrayList&lt;>(smartActions);"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+            line="252"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        List&lt;View> coveredSuggestions = new ArrayList&lt;>();"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+            line="254"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="            Paint paint = new Paint();"
+        errorLine2="                          ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java"
+            line="141"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="DrawAllocation"
+        message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+        errorLine1="        animationViewController?.onSensorRectUpdated(RectF(sensorRect))"
+        errorLine2="                                                     ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt"
+            line="84"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="WakelockTimeout"
+        message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user&apos;s battery."
+        errorLine1="            mWakeLock.acquire();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java"
+            line="395"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WakelockTimeout"
+        message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user&apos;s battery."
+        errorLine1="            pmWakeLock.acquire()"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/wakelock/ClientTrackingWakeLock.kt"
+            line="41"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WakelockTimeout"
+        message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user&apos;s battery."
+        errorLine1="        mShowKeyguardWakeLock.acquire();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="2395"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="WakelockTimeout"
+        message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user&apos;s battery."
+        errorLine1="            mWakeLock.acquire();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java"
+            line="516"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="WakelockTimeout"
+        message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user&apos;s battery."
+        errorLine1="                    inner.acquire();"
+        errorLine2="                    ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java"
+            line="134"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls bindService"
+        errorLine1="            mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java"
+            line="179"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+        errorLine1="            mContext.unbindService(mConnection);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java"
+            line="208"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+        errorLine1="                        bound = context"
+        errorLine2="                                ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt"
+            line="175"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+        errorLine1="            context.unbindService(serviceConnection)"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt"
+            line="210"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+        errorLine1="            bindResult = mContext.bindServiceAsUser(mServiceIntent, this, mFlags,"
+        errorLine2="                         ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java"
+            line="159"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+        errorLine1="            mContext.unbindService(this);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java"
+            line="164"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+        errorLine1="        mContext.unbindService(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java"
+            line="234"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+        errorLine1="            mBound = mContext.bindServiceAsUser(mQuickStepIntent,"
+        errorLine2="                     ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+            line="828"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+        errorLine1="            mContext.unbindService(mOverviewServiceConnection);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+            line="887"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+        errorLine1="            return mContext.bindServiceAsUser(mIntent, this, flags, mUser);"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java"
+            line="254"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="BindServiceOnMainThread"
+        message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+        errorLine1="        return mContext.bindServiceAsUser(mIntent, this,"
+        errorLine2="               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java"
+            line="256"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+        errorLine1="        sendBroadcastAsUser(intent, UserHandle.SYSTEM, PERMISSION_SELF)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt"
+            line="103"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="                    context.sendBroadcast(mTestIntent);"
+        errorLine2="                            ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java"
+            line="315"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        getContext().sendBroadcast(intent);"
+        errorLine2="                     ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="171"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        getContext().sendBroadcast(intent);"
+        errorLine2="                     ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="180"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        getContext().sendBroadcast(intent);"
+        errorLine2="                     ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="184"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        getContext().sendBroadcast(intent);"
+        errorLine2="                     ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="189"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        getContext().sendBroadcast(intent);"
+        errorLine2="                     ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="195"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        getContext().sendBroadcast(intent);"
+        errorLine2="                     ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+            line="199"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+        errorLine1="        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="2207"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+        errorLine1="                        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT,"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="2688"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="            context.sendBroadcast(intent);"
+        errorLine2="                    ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleBackupHelper.java"
+            line="505"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="                getContext().sendBroadcast(intent);"
+        errorLine2="                             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+            line="199"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="            sendBroadcast(intent, PERMISSION_SELF);"
+        errorLine2="            ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java"
+            line="255"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+        errorLine1="                context.sendBroadcastAsUser(intent, mUserId);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java"
+            line="157"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="                        context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))"
+        errorLine2="                                ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt"
+            line="83"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="                    mContext.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));"
+        errorLine2="                             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java"
+            line="317"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="BroadcastSentViaContext"
+        message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+        errorLine1="        sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));"
+        errorLine2="        ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+            line="179"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged()"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt"
+            line="131"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java"
+            line="77"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="            notifyDataSetChanged();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java"
+            line="116"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="            mAdapter.notifyDataSetChanged();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+            line="840"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="            notifyDataSetChanged();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java"
+            line="299"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="69"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="            notifyDataSetChanged();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="475"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="            notifyDataSetChanged();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="488"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="            notifyDataSetChanged();"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+            line="224"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+            line="275"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+            line="484"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+            line="505"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+            line="513"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="        notifyDataSetChanged();"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumePanelSlicesAdapter.java"
+            line="89"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+        errorLine1="                notifyDataSetChanged();"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardCarousel.java"
+            line="433"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        registerReceiver(mBroadcastReceiver, mIntentFilter, PERMISSION_SELF, null,"
+        errorLine2="        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java"
+            line="136"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+            line="807"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="            Intent intent = mContext.registerReceiver("
+        errorLine2="                                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java"
+            line="160"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mBroadcastReceiver, intentFilter,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java"
+            line="177"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                Intent i = getContext().registerReceiver(null,"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java"
+            line="379"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="929"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver("
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt"
+            line="233"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver(mReceiver, filter,"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java"
+            line="132"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mReceiver, filter);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java"
+            line="125"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mReceiver, filter, null, null,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java"
+            line="146"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="            mContext.registerReceiver(mReceiver,"
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+            line="469"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_DISABLE_ESIM),"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java"
+            line="98"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,"
+        errorLine2="                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java"
+            line="401"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="            context.registerReceiver(new BroadcastReceiver() {"
+        errorLine2="                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java"
+            line="145"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mDelayedLockBroadcastReceiver, delayedActionFilter,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+            line="1524"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver(appChangeReceiver, uninstallFilter)"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+            line="349"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver(appChangeReceiver, uninstallFilter)"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt"
+            line="288"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        getContext().registerReceiver(mNotificationActionReceiver, intentFilter,"
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java"
+            line="631"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java"
+            line="119"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+            line="432"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mLauncherStateChangedReceiver, filter);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+            line="663"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/PackageObserver.java"
+            line="91"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                mContext.registerReceiver(mBaseBroadcastReceiver, perAppFilter);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+            line="243"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                mContext.registerReceiver(mBaseBroadcastReceiver, bootComplete);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+            line="247"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        getContext().registerReceiver(mReceiver, filter);"
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+            line="64"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        getContext().registerReceiver(mReceiver, filter);"
+        errorLine2="                     ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+            line="66"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="            mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,"
+        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+            line="827"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                Intent intent = mContext.registerReceiver("
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+            line="297"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                mContext.registerReceiver(mPermControllerChangeReceiver, PKG_CHANGE_INTENT_FILTER);"
+        errorLine2="                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SafetyController.java"
+            line="81"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver(mReceiver, filter,"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java"
+            line="66"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="            context.registerReceiver(this, filter,"
+        errorLine2="                    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java"
+            line="142"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null);"
+        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java"
+            line="78"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java"
+            line="103"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiverAsUser("
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt"
+            line="79"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiverForAllUsers("
+        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+            line="229"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        registerReceiver(mCloseSystemDialogs, new IntentFilter(ACTION_CLOSE_SYSTEM_DIALOGS),"
+        errorLine2="        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java"
+            line="130"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="            mContext.registerReceiverAsUser("
+        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java"
+            line="439"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiverAsUser(mUninstallReceiver, userTracker.getUserHandle(), filter,"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java"
+            line="100"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiver(mBroadcastReceiver, filter,"
+        errorLine2="                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java"
+            line="774"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        activity.registerReceiver(this, filter);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java"
+            line="40"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        activity.registerReceiver(this, filter);"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java"
+            line="48"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="                    context.registerReceiverAsUser("
+        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+            line="134"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,"
+        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java"
+            line="78"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        context.registerReceiverForAllUsers(this, filter, null, backgroundHandler)"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt"
+            line="148"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        registerReceiver(mWifiChangeReceiver, filter);"
+        errorLine2="        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+            line="177"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        registerReceiver(mWifiChangeReceiver, filter);"
+        errorLine2="        ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java"
+            line="98"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="RegisterReceiverViaContext"
+        message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+        errorLine1="        mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));"
+        errorLine2="                 ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+            line="402"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;Int>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/data/repository/AssistRepository.kt"
+            line="29"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val mutableIsExpanded = MutableSharedFlow&lt;Boolean>()"
+        errorLine2="                                    ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt"
+            line="78"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _onAuthenticationResult = MutableSharedFlow&lt;Boolean>()"
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt"
+            line="129"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow(extraBufferCapacity = 1)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt"
+            line="81"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow(extraBufferCapacity = 1)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt"
+            line="86"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _onIncorrectBouncerInput = MutableSharedFlow&lt;Unit>()"
+        errorLine2="                                           ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt"
+            line="64"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _onImeHiddenByUser = MutableSharedFlow&lt;Unit>()"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt"
+            line="84"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val resetToDefault = MutableSharedFlow&lt;Unit>(replay = 1)"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt"
+            line="107"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt"
+            line="48"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt"
+            line="93"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="                .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepository.kt"
+            line="69"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="                .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorInversionRepository.kt"
+            line="69"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _appWidgetIdToRemove = MutableSharedFlow&lt;Int>()"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt"
+            line="45"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn("
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt"
+            line="142"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt"
+            line="165"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn("
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt"
+            line="236"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope = applicationScope, started = SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt"
+            line="94"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/domain/interactor/ComponentsInteractor.kt"
+            line="67"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt"
+            line="157"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _validatedAttestation: MutableSharedFlow&lt;ByteArray?> = MutableSharedFlow()"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+            line="92"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(tileScope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt"
+            line="91"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;DefaultsRequest>("
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt"
+            line="77"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(applicationScope, SharingStarted.WhileSubscribed(), replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt"
+            line="93"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;Tile>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractor.kt"
+            line="55"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="                    .shareIn(tileScope, SharingStarted.WhileSubscribed())"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt"
+            line="71"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;TileWithUser>(onBufferOverflow = BufferOverflow.DROP_OLDEST, replay = 1)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt"
+            line="111"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        val mutableRefreshEvents = MutableSharedFlow&lt;Unit>()"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt"
+            line="183"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    val demoModeFinishedEvent = MutableSharedFlow&lt;Unit>(extraBufferCapacity = 1)"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt"
+            line="75"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    val mobileEvents = _mobileCommands.shareIn(scope, SharingStarted.WhileSubscribed())"
+        errorLine2="                                       ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt"
+            line="56"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    val wifiEvents = _wifiCommands.shareIn(scope, SharingStarted.WhileSubscribed())"
+        errorLine2="                                   ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt"
+            line="44"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt"
+            line="85"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val attemptEnterDeviceFromDeviceEntryIcon: MutableSharedFlow&lt;Unit> = MutableSharedFlow()"
+        errorLine2="                                                                                 ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt"
+            line="54"
+            column="82"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow(extraBufferCapacity = 1)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt"
+            line="62"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(bgApplicationScope, started = SharingStarted.WhileSubscribed(), replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt"
+            line="147"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(this, started = Lazily)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/HideNotificationsBinder.kt"
+            line="39"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;Long>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/domain/interactor/HomeControlsComponentInteractor.kt"
+            line="138"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="                    .shareIn(backgroundScope, SharingStarted.WhileSubscribed(), replay = 1)"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt"
+            line="84"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    val refreshTransition = MutableSharedFlow&lt;Config>(extraBufferCapacity = 1)"
+        errorLine2="                            ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+            line="59"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _keyguardAuthenticatedPrimaryAuth = MutableSharedFlow&lt;Int>()"
+        errorLine2="                                                    ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt"
+            line="178"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _userRequestedBouncerWhenAlreadyAuthenticated = MutableSharedFlow&lt;Int>()"
+        errorLine2="                                                                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt"
+            line="183"
+            column="65"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val unseenEntryAdded = MutableSharedFlow&lt;NotificationEntry>(extraBufferCapacity = 1)"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt"
+            line="96"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val unseenEntryRemoved = MutableSharedFlow&lt;NotificationEntry>(extraBufferCapacity = 1)"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt"
+            line="97"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _keyguardDone: MutableSharedFlow&lt;KeyguardDone> = MutableSharedFlow()"
+        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt"
+            line="298"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    override val keyguardDoneAnimationsFinished: MutableSharedFlow&lt;Unit> = MutableSharedFlow()"
+        errorLine2="                                                                           ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt"
+            line="304"
+            column="76"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            MutableSharedFlow&lt;Float>("
+        errorLine2="            ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+            line="81"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.Eagerly)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+            line="106"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            MutableSharedFlow&lt;TransitionStep>("
+        errorLine2="            ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+            line="149"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+            line="193"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+            line="207"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+            line="249"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;TransitionStep>("
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt"
+            line="117"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt"
+            line="130"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt"
+            line="63"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt"
+            line="93"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;PackageChangeModel>(replay = 0, extraBufferCapacity = BUFFER_CAPACITY)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/common/data/repository/PackageUpdateMonitor.kt"
+            line="67"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _accessibilityHint = MutableSharedFlow&lt;String>()"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt"
+            line="143"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;Int>("
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt"
+            line="179"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(scope, SharingStarted.Eagerly)"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt"
+            line="123"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val userInputs: MutableSharedFlow&lt;QSTileUserAction> = MutableSharedFlow()"
+        errorLine2="                                                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+            line="89"
+            column="67"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val forceUpdates: MutableSharedFlow&lt;Unit> = MutableSharedFlow()"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+            line="90"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn("
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+            line="104"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="                        .shareIn(tileScope, SharingStarted.WhileSubscribed())"
+        errorLine2="                         ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+            line="162"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn("
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+            line="172"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(applicationScope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt"
+            line="150"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(applicationScope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt"
+            line="156"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn(applicationScope, SharingStarted.WhileSubscribed())"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt"
+            line="169"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _notificationStackChanged = MutableSharedFlow&lt;Unit>(extraBufferCapacity = 1)"
+        errorLine2="                                            ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt"
+            line="57"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val _bouncerMessageChanged = MutableSharedFlow&lt;String?>()"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt"
+            line="75"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val changes = MutableSharedFlow&lt;Unit>()"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt"
+            line="54"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn("
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/UserA11yQsShortcutsRepository.kt"
+            line="56"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="    private val changeEvents = MutableSharedFlow&lt;ChangeAction>("
+        errorLine2="                               ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepository.kt"
+            line="47"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;ChangeAction>(extraBufferCapacity = CHANGES_BUFFER_SIZE)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt"
+            line="54"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="            .shareIn("
+        errorLine2="             ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt"
+            line="107"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="SharedFlowCreation"
+        message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+        errorLine1="        MutableSharedFlow&lt;Int>(extraBufferCapacity = QSSettingsRestoredRepository.BUFFER_CAPACITY)"
+        errorLine2="        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessor.kt"
+            line="49"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="        mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());"
+        errorLine2="                                                                     ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+            line="373"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="                startActivityAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));"
+        errorLine2="                                                                          ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java"
+            line="373"
+            column="75"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="        int startingUser = ActivityManager.getCurrentUser();"
+        errorLine2="                                           ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java"
+            line="70"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="                ? UserHandle.of(ActivityManager.getCurrentUser()) : notificationUser;"
+        errorLine2="                                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java"
+            line="611"
+            column="49"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="                ActivityManager.getCurrentUser());"
+        errorLine2="                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java"
+            line="91"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="                TextUtils.join(&quot;,&quot;, hideList), ActivityManager.getCurrentUser());"
+        errorLine2="                                                               ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java"
+            line="86"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="SlowUserIdQuery"
+        message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+        errorLine1="            ActivityManager.getCurrentUser(),"
+        errorLine2="                            ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt"
+            line="236"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="        getUserInfo("
+        errorLine2="        ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractor.kt"
+            line="173"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="                            manager.getUserInfo(lastSelectedNonGuestUserHandle)"
+        errorLine2="                                    ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt"
+            line="149"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="                mUserManager.getUserInfo(userId).isManagedProfile()"
+        errorLine2="                             ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java"
+            line="500"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="                        val userType = userManager.getUserInfo(userId).userType"
+        errorLine2="                                                   ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryImpl.kt"
+            line="45"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="                        userManager.getUserInfo(it.taskInfo1.userId).toUserType(),"
+        errorLine2="                                    ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt"
+            line="66"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="                            userManager.getUserInfo(it.taskInfo2!!.userId).toUserType(),"
+        errorLine2="                                        ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt"
+            line="75"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="        return mUserManager.getUserInfo(mCurrentUserId).isRestricted()"
+        errorLine2="                            ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+            line="312"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="SlowUserInfoQuery"
+        message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+        errorLine1="        final UserInfo newUserInfo = mUserManager.getUserInfo(newUserId);"
+        errorLine2="                                                  ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+            line="386"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="        Bitmap a = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ALPHA_8);"
+        errorLine2="                                                                                  ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/DessertCaseView.java"
+            line="196"
+            column="83"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="                        ?: Bitmap.Config.ARGB_8888"
+        errorLine2="                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt"
+            line="95"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="                        ?: Bitmap.Config.ARGB_8888"
+        errorLine2="                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt"
+            line="95"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                                             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayDotImageView.java"
+            line="120"
+            column="78"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java"
+            line="182"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java"
+            line="329"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java"
+            line="357"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="                                shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                                              ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="686"
+            column="79"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888"
+        errorLine2="                                                                                           ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java"
+            line="451"
+            column="92"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="                : Bitmap.Config.RGB_565;"
+        errorLine2="                                ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java"
+            line="452"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="355"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="SoftwareBitmap"
+        message="Replace software bitmap with `Config.HARDWARE`"
+        errorLine1="                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);"
+        errorLine2="                                                                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="359"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="Recycle"
+        message="This `TypedArray` should be recycled after use with `#recycle()`"
+        errorLine1="            TypedArray typedArray = context.obtainStyledAttributes("
+        errorLine2="                                            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java"
+            line="85"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="Recycle"
+        message="This `TypedArray` should be recycled after use with `#recycle()`"
+        errorLine1="        final TypedArray sa = mResources.obtainAttributes(mAttrs, R.styleable.Shortcut);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ShortcutParser.java"
+            line="103"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `FrameLayout`: `layout_weight`"
+        errorLine1="        android:layout_weight=&quot;0&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/contextual.xml"
+            line="31"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `FrameLayout`: `layout_weight`"
+        errorLine1="        android:layout_weight=&quot;0&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/contextual.xml"
+            line="54"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param &apos;`layout_weight`&apos; (included from within a `FrameLayout` in `layout/controls_dialog.xml`)"
+        errorLine1="    android:layout_weight=&quot;1&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_base_item.xml"
+            line="21"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="44"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+        errorLine1="            android:layout_alignParentStart=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="45"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="54"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+        errorLine1="            android:layout_alignEnd=&quot;@id/pkg_icon&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="56"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+        errorLine1="            android:layout_toEndOf=&quot;@id/pkg_icon&quot;>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="57"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param &apos;`layout_weight`&apos; (included from within a `FrameLayout` in `layout/contextual.xml`, included from within a `FrameLayout` in `layout/menu_ime.xml`)"
+        errorLine1="    android:layout_weight=&quot;0&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/ime_switcher.xml"
+            line="23"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;false&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="44"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+        errorLine1="            android:layout_alignParentStart=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="45"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="104"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+        errorLine1="            android:layout_alignEnd=&quot;@id/conversation_icon&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="106"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+        errorLine1="            android:layout_toEndOf=&quot;@id/conversation_icon&quot;>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="107"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                    android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="124"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="157"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="173"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentEnd`"
+        errorLine1="            android:layout_alignParentEnd=&quot;true&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="178"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+        errorLine1="                        android:layout_toEndOf=&quot;@id/silence_icon&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="353"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="43"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+        errorLine1="            android:layout_alignParentStart=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="44"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="53"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+        errorLine1="            android:layout_alignEnd=&quot;@id/pkg_icon&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="55"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+        errorLine1="            android:layout_toEndOf=&quot;@id/pkg_icon&quot;>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="56"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="82"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="100"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toStartOf`"
+        errorLine1="            android:layout_toStartOf=&quot;@id/info&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="105"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="111"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentEnd`"
+        errorLine1="            android:layout_alignParentEnd=&quot;true&quot; />"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="116"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+        errorLine1="                        android:layout_toEndOf=&quot;@id/silence_icon&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="301"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="42"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+        errorLine1="            android:layout_alignParentStart=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="43"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="52"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+        errorLine1="            android:layout_alignEnd=&quot;@id/conversation_icon&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="54"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+        errorLine1="            android:layout_toEndOf=&quot;@id/conversation_icon&quot;>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="55"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="67"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="            android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="83"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_alignParentEnd`"
+        errorLine1="            android:layout_alignParentEnd=&quot;true&quot;/>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="88"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                    android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="124"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                    android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="131"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_above`"
+        errorLine1="            android:layout_above=&quot;@id/got_it_button&quot;>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml"
+            line="75"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+            line="46"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                android:layout_centerVertical=&quot;true&quot;>"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+            line="55"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="ObsoleteLayoutParam"
+        message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+        errorLine1="                android:layout_centerVertical=&quot;true&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+            line="75"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="ObsoleteSdkInt"
+        message="Unnecessary; SDK_INT is always >= 34"
+        errorLine1="    @RequiresApi(34)"
+        errorLine2="    ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+            line="531"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields (static reference to `SystemUIDialog` which has field `mContext` pointing to `Context`); this is a memory leak"
+        errorLine1="        var dialog: SystemUIDialog? = null"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt"
+            line="40"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)"
+        errorLine1="        new AsyncTask&lt;Icon, Void, Drawable>() {"
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+            line="207"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields (static reference to `KeyboardShortcutListSearch` which has field `mSearchEditText` pointing to `EditText`); this is a memory leak"
+        errorLine1="    @VisibleForTesting static KeyboardShortcutListSearch sInstance;"
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+            line="100"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields (static reference to `KeyboardShortcuts` which has field `mContext` pointing to `Context`); this is a memory leak"
+        errorLine1="    @VisibleForTesting static KeyboardShortcuts sInstance;"
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+            line="83"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields (static reference to `MediaOutputDialog` which has field `mContext` pointing to `Context`); this is a memory leak"
+        errorLine1="        var mediaOutputDialog: MediaOutputDialog? = null"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt"
+            line="41"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)"
+        errorLine1="        new AsyncTask&lt;Void, Void, Void>() {"
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+            line="742"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="This field leaks a context object"
+        errorLine1="        private final Context mContext;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+            line="1053"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="This field leaks a context object"
+        errorLine1="        private ExpandableNotificationRow mRow;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+            line="1062"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="This field leaks a context object"
+        errorLine1="    private final Context mContext;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java"
+            line="62"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields (static reference to `SystemUIInitializer` which has field `mContext` pointing to `Context`); this is a memory leak"
+        errorLine1="        // Must be static due to http://b/141008541."
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt"
+            line="48"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)"
+        errorLine1="        mUserInfoTask = new AsyncTask&lt;Void, Void, UserInfoQueryResult>() {"
+        errorLine2="                        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java"
+            line="147"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_end_dialog.xml"
+            line="26"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="112"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
+        errorLine1="        &lt;LinearLayout"
+        errorLine2="         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_initial_layout.xml"
+            line="36"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+            line="95"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (922 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M36.3,25.5c-0.4,-0.3,-1,-0.5,-1.5,-0.5c-0.1,0,-0.3,0,-0.4,0c-0.3,0,-0.5,0,-0.7,0.1c-0.6,0.1,-1.1,0.4,-1.5,0.8   c-0.8,0.6,-1.2,1.6,-1.2,2.7v3.5h-1.2V14c0,-1.4,-0.6,-2.7,-1.6,-3.6c-0.4,-0.4,-0.9,-0.8,-1.5,-1c-0.4,-0.1,-0.7,-0.2,-1.1,-0.3   C25.2,9,24.9,9,24.7,9s-0.5,0,-0.8,0.1c-0.4,0.1,-0.8,0.2,-1.1,0.3c-0.6,0.2,-1.1,0.6,-1.5,1c-1,0.9,-1.6,2.2,-1.6,3.6v10.3h-2.4v-4.5   c0,-1.2,-0.6,-2.2,-1.5,-2.8c-0.4,-0.3,-1,-0.5,-1.5,-0.6c-0.2,0,-0.3,-0.1,-0.5,-0.1c-0.2,0,-0.4,0,-0.6,0.1c-0.6,0.1,-1.1,0.3,-1.5,0.7   c-0.8,0.6,-1.4,1.6,-1.4,2.7v8c0,1.1,0.5,2.1,1.4,2.7c0.4,0.3,0.9,0.6,1.5,0.7c0.2,0,0.4,0.1,0.6,0.1h0.5h1.5h3.8V48   c0,1.4,0.6,2.7,1.6,3.6c0.4,0.4,0.9,0.8,1.5,1c0.4,0.1,0.7,0.2,1.1,0.3c0.2,0,0.5,0.1,0.8,0.1s0.5,0,0.8,-0.1   c0.4,-0.1,0.8,-0.2,1.1,-0.3c0.6,-0.2,1.1,-0.6,1.5,-1c1,-0.9,1.6,-2.2,1.6,-3.6v-9.1h1.2h1.2h1.5h0.7c0.1,0,0.3,0,0.4,0   c0.6,-0.1,1.1,-0.2,1.5,-0.5c0.9,-0.6,1.6,-1.7,1.6,-2.9v-7C37.9,27.2,37.3,26.1,36.3,25.5z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-nodpi/cactus1.xml"
+            line="22"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (983 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M19.400000,10.000000c-0.700000,-3.400000 -3.700000,-6.000000 -7.400000,-6.000000c-1.500000,0.000000 -2.900000,0.400000 -4.000000,1.200000l1.500000,1.500000C10.200000,6.200000 11.100000,6.000000 12.000000,6.000000c3.000000,0.000000 5.500000,2.500000 5.500000,5.500000L17.500000,12.000000L19.000000,12.000000c1.700000,0.000000 3.000000,1.300000 3.000000,3.000000c0.000000,1.100000 -0.600000,2.100000 -1.600000,2.600000l1.500000,1.500000c1.300000,-0.900000 2.100000,-2.400000 2.100000,-4.100000C24.000000,12.400000 21.900000,10.200000 19.400000,10.000000zM3.000000,5.300000L5.800000,8.000000C2.600000,8.200000 0.000000,10.800000 0.000000,14.000000c0.000000,3.300000 2.700000,6.000000 6.000000,6.000000l11.700000,0.000000l2.000000,2.000000l1.300000,-1.300000L4.300000,4.000000L3.000000,5.300000zM7.700000,10.000000l8.000000,8.000000L6.000000,18.000000c-2.200000,0.000000 -4.000000,-1.800000 -4.000000,-4.000000c0.000000,-2.200000 1.800000,-4.000000 4.000000,-4.000000L7.700000,10.000000z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-nodpi/cloud_off.xml"
+            line="22"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (983 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M19.400000,10.000000c-0.700000,-3.400000 -3.700000,-6.000000 -7.400000,-6.000000c-1.500000,0.000000 -2.900000,0.400000 -4.000000,1.200000l1.500000,1.500000C10.200000,6.200000 11.100000,6.000000 12.000000,6.000000c3.000000,0.000000 5.500000,2.500000 5.500000,5.500000L17.500000,12.000000L19.000000,12.000000c1.700000,0.000000 3.000000,1.300000 3.000000,3.000000c0.000000,1.100000 -0.600000,2.100000 -1.600000,2.600000l1.500000,1.500000c1.300000,-0.900000 2.100000,-2.400000 2.100000,-4.100000C24.000000,12.400000 21.900000,10.200000 19.400000,10.000000zM3.000000,5.300000L5.800000,8.000000C2.600000,8.200000 0.000000,10.800000 0.000000,14.000000c0.000000,3.300000 2.700000,6.000000 6.000000,6.000000l11.700000,0.000000l2.000000,2.000000l1.300000,-1.300000L4.300000,4.000000L3.000000,5.300000zM7.700000,10.000000l8.000000,8.000000L6.000000,18.000000c-2.200000,0.000000 -4.000000,-1.800000 -4.000000,-4.000000c0.000000,-2.200000 1.800000,-4.000000 4.000000,-4.000000L7.700000,10.000000z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/cloud_off.xml"
+            line="22"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (925 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M34.4,43.95Q31.55,43.95 29.45,42.4Q27.35,40.85 26.35,38.3Q25.35,35.75 24.375,34.325Q23.4,32.9 20.7,30.75Q17.4,28.1 15.95,25.1Q14.5,22.1 14.5,17.8Q14.5,11.8 18.3,7.975Q22.1,4.15 28.1,4.15Q34,4.15 37.875,7.825Q41.75,11.5 42,17.2H39Q38.75,12.8 35.725,9.975Q32.7,7.15 28.1,7.15Q23.6,7.15 20.55,10.225Q17.5,13.3 17.5,17.8Q17.5,21.4 18.9,24.025Q20.3,26.65 23.55,29.1Q25.5,30.55 26.675,32.25Q27.85,33.95 28.9,36.45Q29.75,38.55 31.125,39.75Q32.5,40.95 34.4,40.95Q36.15,40.95 37.425,39.75Q38.7,38.55 38.95,36.8H41.95Q41.7,39.8 39.55,41.875Q37.4,43.95 34.4,43.95ZM11.95,32.9Q9.1,29.75 7.55,25.825Q6,21.9 6,17.6Q6,13.35 7.475,9.375Q8.95,5.4 11.95,2.35L14.2,4.35Q11.6,7 10.3,10.425Q9,13.85 9,17.6Q9,21.3 10.325,24.725Q11.65,28.15 14.2,30.85ZM28.1,22.45Q26.15,22.45 24.8,21.1Q23.45,19.75 23.45,17.8Q23.45,15.85 24.8,14.45Q26.15,13.05 28.1,13.05Q30.05,13.05 31.45,14.45Q32.85,15.85 32.85,17.8Q32.85,19.75 31.45,21.1Q30.05,22.45 28.1,22.45Z&quot;/>"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/hearing.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1848 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M6.000000,18.000000c0.000000,0.600000 0.400000,1.000000 1.000000,1.000000l1.000000,0.000000l0.000000,3.500000C8.000000,23.299999 8.700000,24.000000 9.500000,24.000000c0.800000,0.000000 1.500000,-0.700000 1.500000,-1.500000L11.000000,19.000000l2.000000,0.000000l0.000000,3.500000c0.000000,0.800000 0.700000,1.500000 1.500000,1.500000c0.800000,0.000000 1.500000,-0.700000 1.500000,-1.500000L16.000000,19.000000l1.000000,0.000000c0.600000,0.000000 1.000000,-0.400000 1.000000,-1.000000L18.000000,8.000000L6.000000,8.000000L6.000000,18.000000zM3.500000,8.000000C2.700000,8.000000 2.000000,8.700000 2.000000,9.500000l0.000000,7.000000C2.000000,17.299999 2.700000,18.000000 3.500000,18.000000C4.300000,18.000000 5.000000,17.299999 5.000000,16.500000l0.000000,-7.000000C5.000000,8.700000 4.300000,8.000000 3.500000,8.000000zM20.500000,8.000000C19.700001,8.000000 19.000000,8.700000 19.000000,9.500000l0.000000,7.000000c0.000000,0.800000 0.700000,1.500000 1.500000,1.500000c0.800000,0.000000 1.500000,-0.700000 1.500000,-1.500000l0.000000,-7.000000C22.000000,8.700000 21.299999,8.000000 20.500000,8.000000zM15.500000,2.200000l1.300000,-1.300000c0.200000,-0.200000 0.200000,-0.500000 0.000000,-0.700000c-0.200000,-0.200000 -0.500000,-0.200000 -0.700000,0.000000l-1.500000,1.500000C13.900000,1.200000 13.000000,1.000000 12.000000,1.000000c-1.000000,0.000000 -1.900000,0.200000 -2.700000,0.600000L7.900000,0.100000C7.700000,0.000000 7.300000,0.000000 7.100000,0.100000C7.000000,0.300000 7.000000,0.700000 7.100000,0.900000l1.300000,1.300000C7.000000,3.300000 6.000000,5.000000 6.000000,7.000000l12.000000,0.000000C18.000000,5.000000 17.000000,3.200000 15.500000,2.200000zM10.000000,5.000000L9.000000,5.000000L9.000000,4.000000l1.000000,0.000000L10.000000,5.000000zM15.000000,5.000000l-1.000000,0.000000L14.000000,4.000000l1.000000,0.000000L15.000000,5.000000z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_android.xml"
+            line="22"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1121 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M23.9998,10.667C16.6398,10.667 10.6665,16.6403 10.6665,24.0003C10.6665,31.3603 16.6398,37.3337 23.9998,37.3337C31.3598,37.3337 37.3332,31.3603 37.3332,24.0003C37.3332,16.6403 31.3598,10.667 23.9998,10.667ZM17.4265,32.3737C17.9998,31.1737 21.4932,30.0003 23.9998,30.0003C26.5065,30.0003 30.0132,31.1737 30.5732,32.3737C28.7598,33.8137 26.4798,34.667 23.9998,34.667C21.5198,34.667 19.2398,33.8137 17.4265,32.3737ZM23.9998,27.3337C25.9465,27.3337 30.5732,28.1203 32.4798,30.4403C33.8398,28.6537 34.6665,26.427 34.6665,24.0003C34.6665,18.1203 29.8798,13.3337 23.9998,13.3337C18.1198,13.3337 13.3332,18.1203 13.3332,24.0003C13.3332,26.427 14.1598,28.6537 15.5198,30.4403C17.4265,28.1203 22.0532,27.3337 23.9998,27.3337ZM23.9998,16.0003C21.4132,16.0003 19.3332,18.0803 19.3332,20.667C19.3332,23.2537 21.4132,25.3337 23.9998,25.3337C26.5865,25.3337 28.6665,23.2537 28.6665,20.667C28.6665,18.0803 26.5865,16.0003 23.9998,16.0003ZM21.9998,20.667C21.9998,21.7737 22.8932,22.667 23.9998,22.667C25.1065,22.667 25.9998,21.7737 25.9998,20.667C25.9998,19.5603 25.1065,18.667 23.9998,18.667C22.8932,18.667 21.9998,19.5603 21.9998,20.667Z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_avatar_guest_user.xml"
+            line="23"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1055 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="                    android:pathData=&quot; M66.67 -27.59 C66.67,-27.59 66.67,-66.67 66.67,-66.67 C66.67,-66.67 27.59,-66.67 27.59,-66.67 C27.59,-66.67 0,-94.25 0,-94.25 C0,-94.25 -27.58,-66.67 -27.58,-66.67 C-27.58,-66.67 -66.66,-66.67 -66.66,-66.67 C-66.66,-66.67 -66.66,-27.59 -66.66,-27.59 C-66.66,-27.59 -94.25,0 -94.25,0 C-94.25,0 -66.66,27.58 -66.66,27.58 C-66.66,27.58 -66.66,66.66 -66.66,66.66 C-66.66,66.66 -27.58,66.66 -27.58,66.66 C-27.58,66.66 0,94.25 0,94.25 C0,94.25 27.59,66.66 27.59,66.66 C27.59,66.66 66.67,66.66 66.67,66.66 C66.67,66.66 66.67,27.58 66.67,27.58 C66.67,27.58 94.25,0 94.25,0 C94.25,0 66.67,-27.59 66.67,-27.59c  M50 20.66 C50,20.66 50,50 50,50 C50,50 20.67,50 20.67,50 C20.67,50 0,70.66 0,70.66 C0,70.66 -20.66,50 -20.66,50 C-20.66,50 -50,50 -50,50 C-50,50 -50,20.66 -50,20.66 C-50,20.66 -70.66,0 -70.66,0 C-70.66,0 -50,-20.67 -50,-20.67 C-50,-20.67 -50,-50 -50,-50 C-50,-50 -20.66,-50 -20.66,-50 C-20.66,-50 0,-70.67 0,-70.67 C0,-70.67 20.67,-50 20.67,-50 C20.67,-50 50,-50 50,-50 C50,-50 50,-20.67 50,-20.67 C50,-20.67 70.67,0 70.67,0 C70.67,0 50,20.66 50,20.66c &quot; />"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_brightness_full.xml"
+            line="19"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1055 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="                    android:pathData=&quot; M66.67 -27.59 C66.67,-27.59 66.67,-66.67 66.67,-66.67 C66.67,-66.67 27.59,-66.67 27.59,-66.67 C27.59,-66.67 0,-94.25 0,-94.25 C0,-94.25 -27.58,-66.67 -27.58,-66.67 C-27.58,-66.67 -66.66,-66.67 -66.66,-66.67 C-66.66,-66.67 -66.66,-27.59 -66.66,-27.59 C-66.66,-27.59 -94.25,0 -94.25,0 C-94.25,0 -66.66,27.58 -66.66,27.58 C-66.66,27.58 -66.66,66.66 -66.66,66.66 C-66.66,66.66 -27.58,66.66 -27.58,66.66 C-27.58,66.66 0,94.25 0,94.25 C0,94.25 27.59,66.66 27.59,66.66 C27.59,66.66 66.67,66.66 66.67,66.66 C66.67,66.66 66.67,27.58 66.67,27.58 C66.67,27.58 94.25,0 94.25,0 C94.25,0 66.67,-27.59 66.67,-27.59c  M50 20.66 C50,20.66 50,50 50,50 C50,50 20.67,50 20.67,50 C20.67,50 0,70.66 0,70.66 C0,70.66 -20.66,50 -20.66,50 C-20.66,50 -50,50 -50,50 C-50,50 -50,20.66 -50,20.66 C-50,20.66 -70.66,0 -70.66,0 C-70.66,0 -50,-20.67 -50,-20.67 C-50,-20.67 -50,-50 -50,-50 C-50,-50 -20.66,-50 -20.66,-50 C-20.66,-50 0,-70.67 0,-70.67 C0,-70.67 20.67,-50 20.67,-50 C20.67,-50 50,-50 50,-50 C50,-50 50,-20.67 50,-20.67 C50,-20.67 70.67,0 70.67,0 C70.67,0 50,20.66 50,20.66c &quot; />"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_brightness_low.xml"
+            line="19"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1054 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="                    android:pathData=&quot;M66.67 -27.59 C66.67,-27.59 66.67,-66.67 66.67,-66.67 C66.67,-66.67 27.59,-66.67 27.59,-66.67 C27.59,-66.67 0,-94.25 0,-94.25 C0,-94.25 -27.58,-66.67 -27.58,-66.67 C-27.58,-66.67 -66.66,-66.67 -66.66,-66.67 C-66.66,-66.67 -66.66,-27.59 -66.66,-27.59 C-66.66,-27.59 -94.25,0 -94.25,0 C-94.25,0 -66.66,27.58 -66.66,27.58 C-66.66,27.58 -66.66,66.66 -66.66,66.66 C-66.66,66.66 -27.58,66.66 -27.58,66.66 C-27.58,66.66 0,94.25 0,94.25 C0,94.25 27.59,66.66 27.59,66.66 C27.59,66.66 66.67,66.66 66.67,66.66 C66.67,66.66 66.67,27.58 66.67,27.58 C66.67,27.58 94.25,0 94.25,0 C94.25,0 66.67,-27.59 66.67,-27.59c  M50 20.66 C50,20.66 50,50 50,50 C50,50 20.67,50 20.67,50 C20.67,50 0,70.66 0,70.66 C0,70.66 -20.66,50 -20.66,50 C-20.66,50 -50,50 -50,50 C-50,50 -50,20.66 -50,20.66 C-50,20.66 -70.66,0 -70.66,0 C-70.66,0 -50,-20.67 -50,-20.67 C-50,-20.67 -50,-50 -50,-50 C-50,-50 -20.66,-50 -20.66,-50 C-20.66,-50 0,-70.67 0,-70.67 C0,-70.67 20.67,-50 20.67,-50 C20.67,-50 50,-50 50,-50 C50,-50 50,-20.67 50,-20.67 C50,-20.67 70.67,0 70.67,0 C70.67,0 50,20.66 50,20.66c &quot; />"
+        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_brightness_medium.xml"
+            line="19"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (831 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M12,16Q13.875,16 15.188,14.688Q16.5,13.375 16.5,11.5Q16.5,9.625 15.188,8.312Q13.875,7 12,7Q10.125,7 8.812,8.312Q7.5,9.625 7.5,11.5Q7.5,13.375 8.812,14.688Q10.125,16 12,16ZM12,14.2Q10.875,14.2 10.088,13.412Q9.3,12.625 9.3,11.5Q9.3,10.375 10.088,9.587Q10.875,8.8 12,8.8Q13.125,8.8 13.913,9.587Q14.7,10.375 14.7,11.5Q14.7,12.625 13.913,13.412Q13.125,14.2 12,14.2ZM12,19Q8.35,19 5.35,16.962Q2.35,14.925 1,11.5Q2.35,8.075 5.35,6.037Q8.35,4 12,4Q15.65,4 18.65,6.037Q21.65,8.075 23,11.5Q21.65,14.925 18.65,16.962Q15.65,19 12,19ZM12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5ZM12,17Q14.825,17 17.188,15.512Q19.55,14.025 20.8,11.5Q19.55,8.975 17.188,7.487Q14.825,6 12,6Q9.175,6 6.812,7.487Q4.45,8.975 3.2,11.5Q4.45,14.025 6.812,15.512Q9.175,17 12,17Z&quot;/>"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_broadcast_code_eye.xml"
+            line="25"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1041 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M798,840Q673,840 551,785.5Q429,731 329,631Q229,531 174.5,409Q120,287 120,162Q120,144 132,132Q144,120 162,120L324,120Q338,120 349,129.5Q360,139 362,152L388,292Q390,308 387,319Q384,330 376,338L279,436Q299,473 326.5,507.5Q354,542 387,574Q418,605 452,631.5Q486,658 524,680L618,586Q627,577 641.5,572.5Q656,568 670,570L808,598Q822,602 831,612.5Q840,623 840,636L840,798Q840,816 828,828Q816,840 798,840ZM241,360L307,294Q307,294 307,294Q307,294 307,294L290,200Q290,200 290,200Q290,200 290,200L201,200Q201,200 201,200Q201,200 201,200Q206,241 215,281Q224,321 241,360ZM599,718Q638,735 678.5,745Q719,755 760,758Q760,758 760,758Q760,758 760,758L760,670Q760,670 760,670Q760,670 760,670L666,651Q666,651 666,651Q666,651 666,651L599,718ZM241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360ZM599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Z&quot;/>"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_call.xml"
+            line="25"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (902 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M15,9.683V7C15,6.7348 14.8946,6.4804 14.7071,6.2929C14.5196,6.1054 14.2652,6 14,6H10C9.7348,6 9.4804,6.1054 9.2929,6.2929C9.1053,6.4804 9,6.7348 9,7V9.683C7.855,10.2245 6.8787,11.067 6.1756,12.1205C5.4725,13.174 5.0689,14.3988 5.0081,15.6639C4.9473,16.929 5.2315,18.1868 5.8304,19.3029C6.4292,20.4189 7.3202,21.3512 8.408,22H15.592C16.6798,21.3512 17.5707,20.4189 18.1696,19.3029C18.7685,18.1868 19.0527,16.929 18.9919,15.6639C18.9311,14.3988 18.5275,13.174 17.8244,12.1205C17.1212,11.067 16.145,10.2245 15,9.683ZM14.989,20H9.011C8.3852,19.5381 7.877,18.9352 7.5276,18.2402C7.1783,17.5453 6.9975,16.7778 7,16C7.0041,15.0553 7.2746,14.131 7.7803,13.3331C8.286,12.5351 9.0065,11.896 9.859,11.489L11,10.946V8H13V10.946L14.141,11.489C14.9935,11.896 15.714,12.5351 16.2197,13.3331C16.7254,14.131 16.9959,15.0553 17,16C17.0025,16.7778 16.8217,17.5453 16.4723,18.2402C16.123,18.9352 15.6148,19.5381 14.989,20Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml"
+            line="41"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1852 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2335,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9905 4.1504,3.2335C4.0502,3.4766 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5234 4.1504,20.7665C4.2505,21.0096 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2335,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0096 19.8496,20.7665C19.9498,20.5234 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.7728 19.4151,2.5878C19.2291,2.4027 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0587 11.5556,5.1686C11.72,5.2785 11.8482,5.4346 11.9239,5.6173C11.9996,5.8 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5673 11.7071,6.7072C11.5673,6.847 11.3891,6.9423 11.1951,6.9809C11.0011,7.0194 10.8,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.72 10.1685,6.5556C10.0586,6.3911 10,6.1978 10,6C10,5.7348 10.1054,5.4804 10.2929,5.2929C10.4804,5.1053 10.7348,5 11,5ZM7,6C7,5.8022 7.0587,5.6089 7.1685,5.4445C7.2784,5.28 7.4346,5.1519 7.6173,5.0762C7.8,5.0005 8.0011,4.9806 8.1951,5.0192C8.3891,5.0578 8.5673,5.153 8.7071,5.2929C8.847,5.4327 8.9422,5.611 8.9808,5.8049C9.0194,5.9989 8.9996,6.2 8.9239,6.3827C8.8482,6.5654 8.72,6.7215 8.5556,6.8314C8.3911,6.9413 8.1978,7 8,7C7.7348,7 7.4804,6.8947 7.2929,6.7072C7.1054,6.5196 7,6.2652 7,6ZM12,18C11.0032,18.008 10.0441,17.6198 9.3335,16.9207C8.623,16.2216 8.2192,15.2688 8.211,14.272C8.2109,13.7806 8.3092,13.2941 8.5,12.8412C8.6908,12.3883 8.9703,11.9782 9.322,11.635L12,9L14.678,11.635C15.0297,11.9782 15.3092,12.3883 15.5,12.8412C15.6908,13.2941 15.7891,13.7806 15.789,14.272C15.7808,15.2688 15.377,16.2216 14.6665,16.9207C13.9559,17.6198 12.9968,18.008 12,18Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (878 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M12,15C11.6044,15 11.2177,15.1174 10.8889,15.3372C10.56,15.5569 10.3036,15.8692 10.1522,16.2346C10.0009,16.6001 9.9613,17.0022 10.0384,17.3901C10.1156,17.7781 10.3061,18.1346 10.5858,18.4143C10.8655,18.694 11.2219,18.8845 11.6098,18.9617C11.9978,19.0388 12.3999,18.999 12.7654,18.8477C13.1308,18.6963 13.4432,18.44 13.6629,18.1111C13.8827,17.7822 14,17.3956 14,17C14,16.4696 13.7893,15.9608 13.4142,15.5857C13.0391,15.2106 12.5304,15 12,15ZM12,18C11.8022,18 11.6089,17.9414 11.4444,17.8315C11.28,17.7217 11.1518,17.5653 11.0761,17.3826C11.0004,17.1998 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4328 11.2929,16.293C11.4327,16.1531 11.6109,16.0579 11.8049,16.0193C11.9989,15.9807 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.2799 12.8315,16.4443C12.9413,16.6088 13,16.8022 13,17C13,17.2652 12.8946,17.5195 12.7071,17.707C12.5196,17.8946 12.2652,18 12,18Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml"
+            line="26"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1266 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M17,2H7C6.4696,2 5.9609,2.2106 5.5858,2.5857C5.2107,2.9608 5,3.4696 5,4V20C5,20.5304 5.2107,21.0392 5.5858,21.4143C5.9609,21.7894 6.4696,22 7,22H17C17.5304,22 18.0391,21.7894 18.4142,21.4143C18.7893,21.0392 19,20.5304 19,20V4C19,3.4696 18.7893,2.9608 18.4142,2.5857C18.0391,2.2106 17.5304,2 17,2ZM12,19C11.6044,19 11.2178,18.8826 10.8889,18.6628C10.56,18.4431 10.3036,18.1308 10.1522,17.7654C10.0009,17.3999 9.9613,16.9978 10.0384,16.6099C10.1156,16.2219 10.3061,15.8654 10.5858,15.5857C10.8655,15.306 11.2219,15.1155 11.6098,15.0383C11.9978,14.9612 12.3999,15.001 12.7654,15.1523C13.1308,15.3037 13.4432,15.56 13.6629,15.8889C13.8827,16.2178 14,16.6044 14,17C14,17.5304 13.7893,18.0392 13.4142,18.4143C13.0391,18.7894 12.5304,19 12,19ZM11,12.5H13C13,12.7652 12.8946,13.0195 12.7071,13.207C12.5196,13.3946 12.2652,13.5 12,13.5C11.7348,13.5 11.4804,13.3946 11.2929,13.207C11.1054,13.0195 11,12.7652 11,12.5ZM16,12H8V11H9V8.6599C8.9488,7.9537 9.1455,7.2519 9.5562,6.675C9.9669,6.0982 10.5659,5.6827 11.25,5.5V5.25C11.25,5.0511 11.329,4.8604 11.4697,4.7197C11.6103,4.5791 11.8011,4.5 12,4.5C12.1989,4.5 12.3897,4.5791 12.5303,4.7197C12.671,4.8604 12.75,5.0511 12.75,5.25V5.5C13.4351,5.6809 14.0352,6.0961 14.4462,6.6733C14.8572,7.2506 15.0532,7.9533 15,8.6599V11H16V12Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml"
+            line="26"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (3845 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0458,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7793,13.342 12.3978,13.5001 12,13.5001ZM10.245,5.2161C10.6327,4.7742 11.1217,4.4328 11.6701,4.2211C12.2184,4.0093 12.8099,3.9335 13.394,4.0001C13.5259,3.9959 13.6555,4.0354 13.7627,4.1124C13.8699,4.1893 13.9487,4.2995 13.987,4.4258C14.0253,4.5521 14.0208,4.6875 13.9744,4.811C13.9279,4.9346 13.842,5.0393 13.73,5.1091C13.1418,5.5017 12.6392,6.0092 12.2521,6.601C11.8651,7.1929 11.6018,7.8568 11.478,8.553C11.2666,8.5847 11.0587,8.6362 10.857,8.707L10.181,6.8271C10.0515,6.576 9.9893,6.2955 10.0005,6.0131C10.0117,5.7308 10.0959,5.4561 10.245,5.2161ZM6.827,13.816C6.576,13.9458 6.2956,14.0083 6.0132,13.9973C5.7308,13.9862 5.4561,13.902 5.216,13.753C4.7745,13.3655 4.4332,12.8769 4.2215,12.3289C4.0098,11.7809 3.9338,11.1898 4,10.6061C3.9959,10.4742 4.0353,10.3446 4.1123,10.2374C4.1893,10.1302 4.2994,10.0513 4.4257,10.0131C4.552,9.9748 4.6874,9.9792 4.8109,10.0257C4.9345,10.0722 5.0392,10.1581 5.109,10.2701C5.5015,10.8581 6.0088,11.3607 6.6005,11.7477C7.1922,12.1347 7.8559,12.3981 8.552,12.522C8.5844,12.7334 8.6363,12.9413 8.707,13.1431L6.827,13.816ZM13.755,18.782C13.3675,19.2242 12.8786,19.566 12.3302,19.7781C11.7818,19.9902 11.1902,20.0664 10.606,20.0001C10.4741,20.0042 10.3445,19.9647 10.2373,19.8878C10.1301,19.8108 10.0512,19.7006 10.013,19.5743C9.9747,19.448 9.9791,19.3126 10.0256,19.1891C10.0721,19.0656 10.158,18.9608 10.27,18.8911C10.8581,18.4987 11.3606,17.9914 11.7475,17.3997C12.1343,16.808 12.3974,16.1441 12.521,15.4481C12.7327,15.4156 12.9409,15.3638 13.143,15.2931L13.818,17.173C13.9477,17.4241 14.0101,17.7045 13.999,17.9869C13.988,18.2692 13.9039,18.5439 13.755,18.7841V18.782ZM18.891,13.7281C18.4985,13.1399 17.991,12.6373 17.3992,12.2504C16.8073,11.8636 16.1432,11.6005 15.447,11.477C15.4154,11.2653 15.3639,11.057 15.293,10.855L17.173,10.1801C17.424,10.0503 17.7044,9.9879 17.9868,9.9989C18.2692,10.0099 18.5439,10.094 18.784,10.243C19.2261,10.631 19.5677,11.1202 19.7795,11.669C19.9912,12.2178 20.0669,12.8097 20,13.394C20.0041,13.5259 19.9647,13.6555 19.8877,13.7628C19.8107,13.87 19.7006,13.9488 19.5743,13.9871C19.448,14.0253 19.3126,14.0209 19.1891,13.9744C19.0655,13.928 18.9608,13.8421 18.891,13.73V13.7281Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_fan_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1740 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0457,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7794,13.342 12.3978,13.5001 12,13.5001Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_fan_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1072 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M18,8H17V6C17,4.6739 16.4732,3.402 15.5355,2.4644C14.5979,1.5267 13.3261,1 12,1C10.6739,1 9.4022,1.5267 8.4645,2.4644C7.5268,3.402 7,4.6739 7,6V8H6C5.47,8.0016 4.9623,8.2127 4.5875,8.5874C4.2128,8.9621 4.0016,9.47 4,10V20C4.0016,20.5299 4.2128,21.0379 4.5875,21.4126C4.9623,21.7873 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7873 19.4125,21.4126C19.7872,21.0379 19.9984,20.5299 20,20V10C19.9984,9.47 19.7872,8.9621 19.4125,8.5874C19.0377,8.2127 18.5299,8.0016 18,8ZM12,17C11.6044,17 11.2178,16.8828 10.8889,16.6631C10.56,16.4433 10.3036,16.1306 10.1522,15.7651C10.0009,15.3997 9.9613,14.9978 10.0384,14.6099C10.1156,14.2219 10.3061,13.8656 10.5858,13.5859C10.8655,13.3062 11.2219,13.1157 11.6098,13.0386C11.9978,12.9614 12.3999,13.001 12.7654,13.1523C13.1308,13.3037 13.4432,13.5598 13.6629,13.8887C13.8827,14.2176 14,14.6044 14,15C13.9984,15.5299 13.7872,16.0379 13.4125,16.4126C13.0377,16.7873 12.5299,16.9984 12,17ZM15,8H9V6C9,5.2043 9.3161,4.4415 9.8787,3.8789C10.4413,3.3163 11.2044,3 12,3C12.7956,3 13.5587,3.3163 14.1213,3.8789C14.6839,4.4415 15,5.2043 15,6V8Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_lock_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1585 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M20,4H4C3.4696,4 2.9609,4.2107 2.5858,4.5858C2.2107,4.9609 2,5.4696 2,6V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V6C22,5.4696 21.7893,4.9609 21.4142,4.5858C21.0391,4.2107 20.5304,4 20,4ZM15,17H5V7H15V17ZM18,17C17.8022,17 17.6089,16.9413 17.4444,16.8314C17.28,16.7215 17.1518,16.5654 17.0761,16.3827C17.0004,16.2 16.9806,15.9989 17.0192,15.8049C17.0578,15.611 17.153,15.4327 17.2929,15.2928C17.4327,15.153 17.6109,15.0578 17.8049,15.0192C17.9989,14.9806 18.2,15.0005 18.3827,15.0762C18.5654,15.1519 18.7216,15.28 18.8315,15.4445C18.9414,15.6089 19,15.8022 19,16C19,16.2652 18.8946,16.5196 18.7071,16.7072C18.5196,16.8947 18.2652,17 18,17ZM18,13C17.8022,13 17.6089,12.9413 17.4444,12.8314C17.28,12.7215 17.1518,12.5654 17.0761,12.3827C17.0004,12.2 16.9806,11.9989 17.0192,11.8049C17.0578,11.611 17.153,11.4327 17.2929,11.2928C17.4327,11.153 17.6109,11.0578 17.8049,11.0192C17.9989,10.9806 18.2,11.0005 18.3827,11.0762C18.5654,11.1519 18.7216,11.28 18.8315,11.4445C18.9414,11.6089 19,11.8022 19,12C19,12.2652 18.8946,12.5196 18.7071,12.7072C18.5196,12.8947 18.2652,13 18,13ZM18,9C17.8022,9 17.6089,8.9413 17.4444,8.8314C17.28,8.7215 17.1518,8.5654 17.0761,8.3827C17.0004,8.2 16.9806,7.9989 17.0192,7.8049C17.0578,7.6109 17.153,7.4327 17.2929,7.2929C17.4327,7.153 17.6109,7.0578 17.8049,7.0192C17.9989,6.9806 18.2,7.0005 18.3827,7.0762C18.5654,7.1519 18.7216,7.28 18.8315,7.4445C18.9414,7.6089 19,7.8022 19,8C19,8.2652 18.8946,8.5196 18.7071,8.7072C18.5196,8.8947 18.2652,9 18,9Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_microwave_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1375 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8786,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5884,22.6645 21.8277,22.4707 22.0149,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM11,4C11,3.7348 11.1053,3.4804 11.2929,3.2929C11.4804,3.1054 11.7348,3 12,3C12.2652,3 12.5195,3.1054 12.7071,3.2929C12.8946,3.4804 13,3.7348 13,4V11H11V4ZM5,13H19V15H5V13ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_mop_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1204 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8787,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5885,22.6645 21.8277,22.4707 22.0148,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_mop_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1592 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M17,12C17,12.5304 16.7893,13.0391 16.4142,13.4142C16.0391,13.7893 15.5304,14 15,14H9C8.4696,14 7.9609,13.7893 7.5858,13.4142C7.2107,13.0391 7,12.5304 7,12V10H3V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V10H17V12ZM8,18C7.8022,18 7.6089,17.9413 7.4444,17.8314C7.28,17.7215 7.1518,17.5654 7.0761,17.3827C7.0004,17.2 6.9806,16.9989 7.0192,16.8049C7.0578,16.611 7.153,16.4327 7.2929,16.2928C7.4328,16.153 7.6109,16.0578 7.8049,16.0192C7.9989,15.9806 8.2,16.0005 8.3827,16.0762C8.5654,16.1519 8.7216,16.28 8.8315,16.4445C8.9413,16.6089 9,16.8022 9,17C9,17.2652 8.8946,17.5196 8.7071,17.7072C8.5196,17.8947 8.2652,18 8,18ZM12,18C11.8022,18 11.6089,17.9413 11.4444,17.8314C11.28,17.7215 11.1518,17.5654 11.0761,17.3827C11.0004,17.2 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4327 11.2929,16.2928C11.4327,16.153 11.6109,16.0578 11.8049,16.0192C11.9989,15.9806 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.28 12.8315,16.4445C12.9414,16.6089 13,16.8022 13,17C13,17.2652 12.8946,17.5196 12.7071,17.7072C12.5196,17.8947 12.2652,18 12,18ZM16,18C15.8022,18 15.6089,17.9413 15.4444,17.8314C15.28,17.7215 15.1518,17.5654 15.0761,17.3827C15.0004,17.2 14.9806,16.9989 15.0192,16.8049C15.0578,16.611 15.153,16.4327 15.2929,16.2928C15.4327,16.153 15.6109,16.0578 15.8049,16.0192C15.9989,15.9806 16.2,16.0005 16.3827,16.0762C16.5654,16.1519 16.7216,16.28 16.8315,16.4445C16.9414,16.6089 17,16.8022 17,17C17,17.2652 16.8946,17.5196 16.7071,17.7072C16.5196,17.8947 16.2652,18 16,18Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (829 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M12,2C10.0222,2 8.0888,2.5865 6.4443,3.6853C4.7998,4.7841 3.5181,6.346 2.7612,8.1732C2.0043,10.0005 1.8063,12.0111 2.1922,13.9509C2.578,15.8907 3.5304,17.6725 4.9289,19.071C6.3275,20.4696 8.1093,21.422 10.0491,21.8079C11.9889,22.1937 13.9996,21.9956 15.8268,21.2388C17.6541,20.4819 19.2159,19.2002 20.3147,17.5557C21.4135,15.9112 22,13.9778 22,12C22,9.3478 20.9464,6.8043 19.0711,4.929C17.1957,3.0536 14.6522,2 12,2ZM12,20C10.4178,20 8.871,19.5308 7.5554,18.6517C6.2399,17.7727 5.2145,16.5233 4.609,15.0615C4.0035,13.5997 3.845,11.9912 4.1537,10.4393C4.4624,8.8875 5.2243,7.462 6.3432,6.3431C7.462,5.2243 8.8874,4.4624 10.4393,4.1537C11.9911,3.845 13.5997,4.0035 15.0615,4.609C16.5233,5.2145 17.7727,6.2398 18.6518,7.5554C19.5308,8.871 20,10.4177 20,12C20,14.1217 19.1572,16.1566 17.6569,17.6569C16.1566,19.1572 14.1217,20 12,20Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_outlet_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (814 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M12,10C12.5933,10 13.1734,9.824 13.6667,9.4944C14.1601,9.1648 14.5446,8.6963 14.7716,8.1481C14.9987,7.5999 15.0581,6.9966 14.9424,6.4147C14.8266,5.8327 14.5409,5.2982 14.1213,4.8787C13.7018,4.4591 13.1672,4.1734 12.5853,4.0576C12.0033,3.9419 11.4001,4.0013 10.8519,4.2284C10.3038,4.4555 9.8352,4.8399 9.5056,5.3333C9.1759,5.8266 9,6.4067 9,7C9,7.7957 9.3161,8.5587 9.8787,9.1214C10.4413,9.684 11.2044,10 12,10ZM12,6C12.1978,6 12.3911,6.0587 12.5556,6.1686C12.72,6.2785 12.8482,6.4346 12.9239,6.6173C12.9996,6.8 13.0194,7.0011 12.9808,7.1951C12.9422,7.3891 12.847,7.5673 12.7071,7.7072C12.5673,7.847 12.3891,7.9423 12.1951,7.9809C12.0011,8.0194 11.8,7.9995 11.6173,7.9238C11.4346,7.8481 11.2784,7.72 11.1685,7.5556C11.0587,7.3911 11,7.1978 11,7C11,6.7348 11.1054,6.4804 11.2929,6.2929C11.4804,6.1053 11.7348,6 12,6Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml"
+            line="26"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (3261 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M16,1H8C7.4696,1 6.9609,1.2107 6.5858,1.5858C6.2107,1.9609 6,2.4696 6,3V21C6,21.5304 6.2107,22.0391 6.5858,22.4142C6.9609,22.7893 7.4696,23 8,23H16C16.5304,23 17.0391,22.7893 17.4142,22.4142C17.7893,22.0391 18,21.5304 18,21V3C18,2.4696 17.7893,1.9609 17.4142,1.5858C17.0391,1.2107 16.5304,1 16,1ZM10,20C9.8022,20 9.6089,19.9413 9.4444,19.8314C9.28,19.7215 9.1518,19.5654 9.0761,19.3827C9.0004,19.2 8.9806,18.9989 9.0192,18.8049C9.0578,18.611 9.153,18.4327 9.2929,18.2928C9.4327,18.153 9.6109,18.0578 9.8049,18.0192C9.9989,17.9806 10.2,18.0005 10.3827,18.0762C10.5654,18.1519 10.7216,18.28 10.8315,18.4445C10.9414,18.6089 11,18.8022 11,19C11,19.2652 10.8946,19.5196 10.7071,19.7072C10.5196,19.8947 10.2652,20 10,20ZM10,17C9.8022,17 9.6089,16.9413 9.4444,16.8314C9.28,16.7215 9.1518,16.5654 9.0761,16.3827C9.0004,16.2 8.9806,15.9989 9.0192,15.8049C9.0578,15.611 9.153,15.4327 9.2929,15.2928C9.4327,15.153 9.6109,15.0578 9.8049,15.0192C9.9989,14.9806 10.2,15.0005 10.3827,15.0762C10.5654,15.1519 10.7216,15.28 10.8315,15.4445C10.9414,15.6089 11,15.8022 11,16C11,16.2652 10.8946,16.5196 10.7071,16.7072C10.5196,16.8947 10.2652,17 10,17ZM10,14C9.8022,14 9.6089,13.9413 9.4444,13.8314C9.28,13.7215 9.1518,13.5654 9.0761,13.3827C9.0004,13.2 8.9806,12.9989 9.0192,12.8049C9.0578,12.611 9.153,12.4327 9.2929,12.2928C9.4327,12.153 9.6109,12.0578 9.8049,12.0192C9.9989,11.9806 10.2,12.0005 10.3827,12.0762C10.5654,12.1519 10.7216,12.28 10.8315,12.4445C10.9414,12.6089 11,12.8022 11,13C11,13.2652 10.8946,13.5196 10.7071,13.7072C10.5196,13.8947 10.2652,14 10,14ZM14,20C13.8022,20 13.6089,19.9413 13.4444,19.8314C13.28,19.7215 13.1518,19.5654 13.0761,19.3827C13.0004,19.2 12.9806,18.9989 13.0192,18.8049C13.0578,18.611 13.153,18.4327 13.2929,18.2928C13.4327,18.153 13.6109,18.0578 13.8049,18.0192C13.9989,17.9806 14.2,18.0005 14.3827,18.0762C14.5654,18.1519 14.7216,18.28 14.8315,18.4445C14.9414,18.6089 15,18.8022 15,19C15,19.2652 14.8946,19.5196 14.7071,19.7072C14.5196,19.8947 14.2652,20 14,20ZM14,17C13.8022,17 13.6089,16.9413 13.4444,16.8314C13.28,16.7215 13.1518,16.5654 13.0761,16.3827C13.0004,16.2 12.9806,15.9989 13.0192,15.8049C13.0578,15.611 13.153,15.4327 13.2929,15.2928C13.4327,15.153 13.6109,15.0578 13.8049,15.0192C13.9989,14.9806 14.2,15.0005 14.3827,15.0762C14.5654,15.1519 14.7216,15.28 14.8315,15.4445C14.9414,15.6089 15,15.8022 15,16C15,16.2652 14.8946,16.5196 14.7071,16.7072C14.5196,16.8947 14.2652,17 14,17ZM14,14C13.8022,14 13.6089,13.9413 13.4444,13.8314C13.28,13.7215 13.1518,13.5654 13.0761,13.3827C13.0004,13.2 12.9806,12.9989 13.0192,12.8049C13.0578,12.611 13.153,12.4327 13.2929,12.2928C13.4327,12.153 13.6109,12.0578 13.8049,12.0192C13.9989,11.9806 14.2,12.0005 14.3827,12.0762C14.5654,12.1519 14.7216,12.28 14.8315,12.4445C14.9414,12.6089 15,12.8022 15,13C15,13.2652 14.8946,13.5196 14.7071,13.7072C14.5196,13.8947 14.2652,14 14,14ZM12,10C11.4067,10 10.8266,9.824 10.3333,9.4944C9.8399,9.1647 9.4554,8.6962 9.2284,8.1481C9.0013,7.5999 8.9419,6.9966 9.0576,6.4147C9.1734,5.8327 9.4591,5.2982 9.8787,4.8787C10.2982,4.4591 10.8328,4.1734 11.4147,4.0576C11.9967,3.9419 12.5999,4.0013 13.1481,4.2284C13.6962,4.4555 14.1648,4.8399 14.4944,5.3333C14.8241,5.8266 15,6.4067 15,7C15,7.7957 14.6839,8.5587 14.1213,9.1213C13.5587,9.684 12.7956,10 12,10Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml"
+            line="26"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (909 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M2,7V17H22V7H2ZM11,13H5V11H11V13ZM14,13C13.8022,13 13.6089,12.9414 13.4444,12.8315C13.28,12.7217 13.1518,12.5653 13.0761,12.3826C13.0004,12.1998 12.9806,11.9989 13.0192,11.8049C13.0578,11.611 13.153,11.4328 13.2929,11.293C13.4327,11.1531 13.6109,11.0579 13.8049,11.0193C13.9989,10.9807 14.2,11.0005 14.3827,11.0762C14.5654,11.1519 14.7216,11.2799 14.8315,11.4443C14.9414,11.6088 15,11.8022 15,12C15,12.2652 14.8946,12.5195 14.7071,12.707C14.5196,12.8946 14.2652,13 14,13ZM17,13C16.8022,13 16.6089,12.9414 16.4444,12.8315C16.28,12.7217 16.1518,12.5653 16.0761,12.3826C16.0004,12.1998 15.9806,11.9989 16.0192,11.8049C16.0578,11.611 16.153,11.4328 16.2929,11.293C16.4327,11.1531 16.6109,11.0579 16.8049,11.0193C16.9989,10.9807 17.2,11.0005 17.3827,11.0762C17.5654,11.1519 17.7216,11.2799 17.8315,11.4443C17.9414,11.6088 18,11.8022 18,12C18,12.2652 17.8946,12.5195 17.7071,12.707C17.5196,12.8946 17.2652,13 17,13Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_set_top_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1931 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM15,19.9999H9V14.9999H15V19.9999ZM18.58,13.9999H17V12.9999H7V13.9999H5.42C5.3642,13.9993 5.3091,13.9877 5.2577,13.9657C5.2064,13.9438 5.1599,13.9119 5.1209,13.872C5.0819,13.8321 5.0512,13.7846 5.0304,13.7328C5.0097,13.681 4.9993,13.6258 5,13.57C4.999,13.4889 5.0222,13.4094 5.0668,13.3417C5.1114,13.274 5.1752,13.221 5.25,13.1899L12,10.1899L18.75,13.1899C18.8245,13.2243 18.8876,13.2795 18.9319,13.3486C18.9761,13.4176 18.9998,13.4979 19,13.58C18.9995,13.6912 18.9551,13.7977 18.8764,13.8764C18.7978,13.955 18.6912,13.9994 18.58,13.9999Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_styler_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1908 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM18.58,14.0009H17V13.0009H7V14.0009H5.42C5.3642,14.0002 5.3091,13.9887 5.2577,13.9667C5.2064,13.9448 5.1599,13.9129 5.1209,13.873C5.0819,13.833 5.0512,13.7859 5.0304,13.7341C5.0097,13.6822 4.9993,13.6268 5,13.571C4.999,13.4899 5.0222,13.4104 5.0668,13.3427C5.1114,13.275 5.1752,13.222 5.25,13.1908L12,10.1908L18.75,13.1908C18.8245,13.2253 18.8876,13.2804 18.9319,13.3495C18.9761,13.4186 18.9998,13.4989 19,13.581C18.9992,13.692 18.9547,13.7982 18.8761,13.8766C18.7974,13.9551 18.6911,13.9994 18.58,13.9999V14.0009Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_styler_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1228 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M15,12V6C15,5.2043 14.6839,4.4413 14.1213,3.8787C13.5587,3.3161 12.7956,3 12,3C11.2044,3 10.4413,3.3161 9.8787,3.8787C9.3161,4.4413 9,5.2043 9,6V12C8.3795,12.4662 7.8759,13.0702 7.5288,13.7644C7.1817,14.4586 7.0007,15.2239 7,16C7.0021,17.0723 7.3531,18.1148 8,18.97V19H8.02C8.4815,19.6206 9.0818,20.1246 9.7729,20.4719C10.4639,20.8192 11.2266,21.0001 12,21.0001C12.7734,21.0001 13.5361,20.8192 14.2271,20.4719C14.9182,20.1246 15.5185,19.6206 15.98,19H16V18.97C16.6469,18.1148 16.9979,17.0723 17,16C16.9993,15.2239 16.8183,14.4586 16.4712,13.7644C16.1241,13.0702 15.6205,12.4662 15,12ZM14.4,17.773L14.367,17.819C14.0952,18.1807 13.744,18.4752 13.3405,18.6799C12.937,18.8846 12.4919,18.9941 12.0395,18.9998C11.5871,19.0055 11.1394,18.9073 10.7309,18.7128C10.3223,18.5184 9.9638,18.2327 9.683,17.878L9.604,17.778C9.2154,17.2664 9.0034,16.6425 9,16C9.0016,15.5346 9.1108,15.0758 9.3189,14.6595C9.5271,14.2432 9.8286,13.8805 10.2,13.6L11,13V6C11,5.7348 11.1054,5.4804 11.2929,5.2929C11.4804,5.1054 11.7348,5 12,5C12.2652,5 12.5196,5.1054 12.7071,5.2929C12.8946,5.4804 13,5.7348 13,6V13L13.8,13.6C14.1714,13.8805 14.4729,14.2432 14.6811,14.6595C14.8892,15.0758 14.9984,15.5346 15,16C14.9967,16.6403 14.7862,17.2623 14.4,17.773V17.773Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (941 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M8,6.5V11.76C8.8027,12.2963 9.4117,13.0766 9.7369,13.9856C10.0622,14.8946 10.0865,15.8841 9.8062,16.8079C9.526,17.7317 8.9561,18.541 8.1807,19.1161C7.4052,19.6912 6.4654,20.0017 5.5,20.0017C4.5346,20.0017 3.5948,19.6912 2.8193,19.1161C2.0439,18.541 1.474,17.7317 1.1938,16.8079C0.9135,15.8841 0.9378,14.8946 1.2631,13.9856C1.5883,13.0766 2.1973,12.2963 3,11.76V6.5C3,5.837 3.2634,5.2011 3.7322,4.7322C4.2011,4.2634 4.837,4 5.5,4C6.163,4 6.7989,4.2634 7.2678,4.7322C7.7366,5.2011 8,5.837 8,6.5ZM3.049,16H7.949C8.0467,15.5132 7.9978,15.0084 7.8084,14.5495C7.619,14.0905 7.2976,13.6981 6.885,13.422L5.998,12.828V6.5C5.998,6.3674 5.9453,6.2402 5.8516,6.1465C5.7578,6.0527 5.6306,6 5.498,6C5.3654,6 5.2382,6.0527 5.1445,6.1465C5.0507,6.2402 4.998,6.3674 4.998,6.5V12.828L4.111,13.422C3.7061,13.6922 3.3887,14.0746 3.1976,14.5223C3.0065,14.97 2.95,15.4637 3.035,15.943C3.0363,15.951 3.0389,15.959 3.0416,15.967C3.0453,15.978 3.049,15.989 3.049,16Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_unknown_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (924 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M8,6.5V11.76C8.8027,12.2963 9.4117,13.0766 9.7369,13.9856C10.0622,14.8946 10.0865,15.8841 9.8062,16.8079C9.526,17.7317 8.9561,18.541 8.1807,19.1161C7.4052,19.6912 6.4654,20.0017 5.5,20.0017C4.5346,20.0017 3.5948,19.6912 2.8193,19.1161C2.0439,18.541 1.474,17.7317 1.1938,16.8079C0.9135,15.8841 0.9378,14.8946 1.2631,13.9856C1.5883,13.0766 2.1973,12.2963 3,11.76V6.5C3,5.837 3.2634,5.2011 3.7322,4.7322C4.2011,4.2634 4.837,4 5.5,4C6.163,4 6.7989,4.2634 7.2678,4.7322C7.7366,5.2011 8,5.837 8,6.5ZM3.049,16H7.949C8.0469,15.5134 7.9983,15.0087 7.8093,14.5498C7.6202,14.0909 7.2992,13.6984 6.887,13.422L6,12.828V6.5C6,6.3674 5.9473,6.2402 5.8535,6.1465C5.7598,6.0527 5.6326,6 5.5,6C5.3674,6 5.2402,6.0527 5.1465,6.1465C5.0527,6.2402 5,6.3674 5,6.5V12.828L4.111,13.422C3.7061,13.6922 3.3887,14.0746 3.1976,14.5223C3.0065,14.97 2.95,15.4637 3.035,15.943C3.0363,15.951 3.0389,15.959 3.0416,15.967C3.0453,15.978 3.049,15.989 3.049,16Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_unknown_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1581 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7019 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9425C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2045 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1532 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5197 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001ZM23,20.0001V22.0001H16V20.0001H18.49L12.01,4.5901C11.7747,4.0366 11.3553,3.5814 10.823,3.3016C10.2906,3.0217 9.6779,2.9344 9.0885,3.0544C8.4991,3.1744 7.9693,3.4943 7.5888,3.96C7.2082,4.4257 7.0002,5.0086 7,5.6101V9.0001H9C10.0609,9.0001 11.0783,9.4215 11.8284,10.1717C12.5786,10.9218 13,11.9392 13,13.0001V22.0001H7.99C8.4398,21.4103 8.7508,20.7267 8.9,20.0001H11V13.0001C10.9984,12.4702 10.7872,11.9624 10.4125,11.5876C10.0377,11.2129 9.5299,11.0017 9,11.0001H4V14.0001C3.3113,13.9992 2.6301,14.1422 2,14.4201V9.0001H5V5.6101C5.0002,4.5458 5.3685,3.5144 6.0426,2.6908C6.7165,1.8672 7.6547,1.3021 8.6979,1.0913C9.741,0.8806 10.825,1.0372 11.7659,1.5345C12.7068,2.0319 13.4466,2.8394 13.86,3.8201L20.66,20.0001H23Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (867 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7018 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9424C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2044 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1531 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5196 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (2132 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M9.64,16.3601C10.2694,16.969 11.1129,17.3061 11.9886,17.2988C12.8643,17.2916 13.7021,16.9405 14.3213,16.3213C14.9406,15.7021 15.2916,14.8642 15.2989,13.9885C15.3061,13.1128 14.9689,12.2693 14.36,11.6399L9.64,16.3601ZM18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2336,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9906 4.1504,3.2336C4.0502,3.4767 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5233 4.1504,20.7664C4.2505,21.0094 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2336,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0094 19.8497,20.7664C19.9498,20.5233 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.773 19.4151,2.5879C19.2291,2.4028 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0586 11.5556,5.1685C11.72,5.2783 11.8482,5.4347 11.9239,5.6174C11.9996,5.8002 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5672 11.7071,6.707C11.5673,6.8469 11.3891,6.9421 11.1951,6.9807C11.0011,7.0193 10.8001,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.7201 10.1685,6.5557C10.0587,6.3912 10,6.1978 10,6C10,5.7348 10.1054,5.4805 10.2929,5.293C10.4804,5.1054 10.7348,5 11,5ZM8,5C8.1978,5 8.3911,5.0586 8.5556,5.1685C8.72,5.2783 8.8482,5.4347 8.9239,5.6174C8.9996,5.8002 9.0194,6.0011 8.9808,6.1951C8.9422,6.3891 8.847,6.5672 8.7071,6.707C8.5673,6.8469 8.3891,6.9421 8.1951,6.9807C8.0011,7.0193 7.8001,6.9995 7.6173,6.9238C7.4346,6.8481 7.2784,6.7201 7.1685,6.5557C7.0587,6.3912 7,6.1978 7,6C7,5.7348 7.1054,5.4805 7.2929,5.293C7.4804,5.1054 7.7348,5 8,5ZM12,19C11.0111,19 10.0444,18.7066 9.2222,18.1572C8.3999,17.6078 7.759,16.827 7.3806,15.9133C7.0022,14.9997 6.9032,13.9946 7.0961,13.0247C7.289,12.0548 7.7652,11.1636 8.4645,10.4644C9.1637,9.7651 10.0547,9.2891 11.0246,9.0962C11.9945,8.9033 12.9998,9.0022 13.9134,9.3806C14.8271,9.7591 15.608,10.3999 16.1574,11.2222C16.7068,12.0444 17,13.0111 17,14C17,15.3261 16.4732,16.598 15.5355,17.5357C14.5979,18.4733 13.3261,19 12,19Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_washer_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1783 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M13.553,8.0161C13.1979,7.6625 12.9486,7.2166 12.8333,6.729C12.7179,6.2413 12.741,5.7311 12.9,5.2558C12.9134,5.2214 12.9162,5.1839 12.9082,5.1479C12.9003,5.1119 12.8818,5.0792 12.8552,5.0537C12.8286,5.0281 12.795,5.0109 12.7586,5.0044C12.7223,4.9979 12.6849,5.0023 12.6511,5.0171C8.8941,6.6581 10.4031,10.6938 10.4031,10.7568C10.4028,10.8187 10.3848,10.8792 10.3511,10.9311C10.3174,10.9831 10.2695,11.0243 10.2131,11.0498C10.2031,11.0498 9.974,11.1708 9.769,10.8838C9.5395,10.5707 9.3759,10.2145 9.2879,9.8364C9.1999,9.4583 9.1894,9.0663 9.2571,8.6841C9.2647,8.6434 9.2587,8.6012 9.2398,8.5644C9.2209,8.5276 9.1902,8.4984 9.1527,8.4809C9.1152,8.4635 9.0729,8.459 9.0326,8.4682C8.9923,8.4775 8.9562,8.5001 8.93,8.5322C8.503,9.08 8.2253,9.7288 8.1241,10.416C8.023,11.1032 8.1018,11.805 8.3528,12.4526C8.6039,13.1003 9.0187,13.6719 9.5567,14.1113C10.0946,14.5507 10.7373,14.8431 11.4221,14.9599C15.6071,15.4939 17.1871,11.2899 14.7041,8.9599C14.3381,8.6159 13.909,8.3721 13.553,8.0161ZM13.3241,12.8691C13.0354,13.1235 12.6634,13.2626 12.2787,13.2607C11.8939,13.2589 11.5233,13.116 11.2371,12.8589C11.225,12.8488 11.2159,12.836 11.2107,12.8213C11.2054,12.8065 11.2042,12.7903 11.2072,12.7749C11.2101,12.7595 11.2172,12.7452 11.2275,12.7334C11.2379,12.7216 11.2512,12.7129 11.2661,12.708C11.5164,12.6335 11.7426,12.4939 11.9216,12.3037C12.1005,12.1135 12.226,11.8794 12.2851,11.625C12.3198,11.2109 12.2684,10.7941 12.1341,10.4009C12.067,10.0764 12.087,9.74 12.1921,9.4258C12.196,9.4132 12.2035,9.4023 12.2138,9.394C12.2241,9.3858 12.2366,9.3809 12.2497,9.3799C12.2628,9.3788 12.2759,9.3817 12.2874,9.3882C12.2989,9.3946 12.3081,9.4042 12.3141,9.416C12.6801,10.236 13.8361,10.6222 13.8361,11.6162C13.843,11.8492 13.801,12.081 13.7128,12.2969C13.6246,12.5127 13.4922,12.7076 13.3241,12.8691Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml"
+            line="26"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1632 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M16,2H8C6.9391,2 5.9217,2.4212 5.1716,3.1714C4.4214,3.9215 4,4.9391 4,6V20C4,20.5304 4.2107,21.039 4.5858,21.4141C4.9609,21.7891 5.4696,22 6,22H18C18.5304,22 19.0391,21.7891 19.4142,21.4141C19.7893,21.039 20,20.5304 20,20V6C20,4.9391 19.5786,3.9215 18.8284,3.1714C18.0783,2.4212 17.0609,2 16,2ZM8.93,8.5278C8.9561,8.4957 8.9922,8.4736 9.0325,8.4644C9.0729,8.4551 9.1151,8.4591 9.1526,8.4766C9.1902,8.494 9.2208,8.5237 9.2397,8.5605C9.2586,8.5974 9.2647,8.6395 9.257,8.6802C9.1893,9.0625 9.1998,9.4544 9.2878,9.8325C9.3758,10.2106 9.5395,10.5668 9.769,10.8799C9.969,11.1669 10.203,11.0499 10.213,11.0459C10.2694,11.0204 10.3173,10.9792 10.351,10.9272C10.3847,10.8753 10.4027,10.8148 10.403,10.7529C10.403,10.6899 8.894,6.6532 12.651,5.0132C12.6848,4.9985 12.7223,4.994 12.7586,5.0005C12.7949,5.007 12.8285,5.0238 12.8551,5.0493C12.8817,5.0749 12.9002,5.108 12.9082,5.144C12.9162,5.1801 12.9133,5.2175 12.9,5.2519C12.741,5.7272 12.7178,6.2374 12.8332,6.7251C12.9486,7.2127 13.1979,7.6586 13.553,8.0122C13.909,8.3682 14.338,8.6121 14.704,8.9541C17.187,11.2821 15.604,15.4861 11.422,14.9541C10.7376,14.8371 10.0952,14.5448 9.5576,14.1055C9.0199,13.6662 8.6053,13.0946 8.3543,12.4473C8.1033,11.7999 8.0244,11.0986 8.1252,10.4116C8.2261,9.7247 8.5034,9.0756 8.93,8.5278ZM18,20H6V16C6.7396,15.9897 7.4619,16.2246 8.054,16.668C8.3188,16.8888 8.6527,17.0098 8.9975,17.0098C9.3423,17.0098 9.6762,16.8888 9.941,16.668C10.5357,16.2281 11.2558,15.9907 11.9955,15.9907C12.7352,15.9907 13.4553,16.2281 14.05,16.668C14.3161,16.889 14.6511,17.0103 14.997,17.0103C15.3429,17.0103 15.6779,16.889 15.944,16.668C16.5368,16.2244 17.2597,15.9896 18,16V20Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml"
+            line="26"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (834 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="      android:pathData=&quot;M17.654,7.563L12,2L6.346,7.563C5.6036,8.2877 5.0136,9.1533 4.6108,10.1094C4.2079,11.0654 4.0002,12.0924 4,13.1299C4.0174,15.2343 4.87,17.2458 6.3703,18.7217C7.8705,20.1975 9.8956,21.017 12,21C14.1044,21.017 16.1295,20.1975 17.6297,18.7217C19.13,17.2458 19.9826,15.2343 20,13.1299C20,12.0924 19.7925,11.0654 19.3896,10.1094C18.9867,9.1533 18.3966,8.2875 17.654,7.563ZM12,18C11.7348,18 11.4804,17.8946 11.2929,17.707C11.1054,17.5195 11,17.2652 11,17C11,16.7348 11.1054,16.4805 11.2929,16.293C11.4804,16.1054 11.7348,16 12,16C12.7956,16 13.5587,15.6837 14.1213,15.1211C14.6839,14.5585 15,13.7956 15,13C15,12.7348 15.1054,12.4805 15.2929,12.293C15.4804,12.1054 15.7348,12 16,12C16.2652,12 16.5196,12.1054 16.7071,12.293C16.8946,12.4805 17,12.7348 17,13C16.9984,14.3256 16.4711,15.5964 15.5338,16.5337C14.5964,17.471 13.3256,17.9984 12,18Z&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_device_water_on.xml"
+            line="23"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1526 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M480,520Q414,520 367,473Q320,426 320,360Q320,294 367,247Q414,200 480,200Q546,200 593,247Q640,294 640,360Q640,426 593,473Q546,520 480,520ZM160,840L160,728Q160,695 177,666Q194,637 224,622Q275,596 339,578Q403,560 480,560Q557,560 621,578Q685,596 736,622Q766,637 783,666Q800,695 800,728L800,840L160,840ZM240,760L720,760L720,728Q720,717 714.5,708Q709,699 700,694Q664,676 607.5,658Q551,640 480,640Q409,640 352.5,658Q296,676 260,694Q251,699 245.5,708Q240,717 240,728L240,760ZM480,440Q513,440 536.5,416.5Q560,393 560,360Q560,327 536.5,303.5Q513,280 480,280Q447,280 423.5,303.5Q400,327 400,360Q400,393 423.5,416.5Q447,440 480,440ZM39,200L39,120Q56,120 70,113.5Q84,107 95,96Q106,85 112,71Q118,57 118,40L199,40Q199,73 186.5,102Q174,131 152,153Q130,175 101,187.5Q72,200 39,200ZM39,361L39,281Q90,281 133.5,262Q177,243 209,210Q241,177 260,133.5Q279,90 279,40L360,40Q360,106 335,164.5Q310,223 266,267Q222,311 164,336Q106,361 39,361ZM920,361Q854,361 795.5,336Q737,311 693,267Q649,223 624,164.5Q599,106 599,40L679,40Q679,90 698,133.5Q717,177 750,210Q783,243 826.5,262Q870,281 920,281L920,361ZM920,200Q887,200 858,187.5Q829,175 807,153Q785,131 772.5,102Q760,73 760,40L840,40Q840,57 846.5,71Q853,85 864,96Q875,107 889,113.5Q903,120 920,120L920,200ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360ZM480,760L480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760L480,760L480,760Z&quot; />"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_head_tracking.xml"
+            line="25"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1366 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-sw900dp/ic_ime_switcher_default.xml"
+            line="23"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1395 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M10,12Q8.35,12 7.175,10.825Q6,9.65 6,8Q6,6.35 7.175,5.175Q8.35,4 10,4Q11.65,4 12.825,5.175Q14,6.35 14,8Q14,9.65 12.825,10.825Q11.65,12 10,12ZM2,20V17.2Q2,16.375 2.425,15.65Q2.85,14.925 3.6,14.55Q4.875,13.9 6.475,13.45Q8.075,13 10,13Q10.2,13 10.35,13Q10.5,13 10.65,13.05Q10.45,13.5 10.312,13.988Q10.175,14.475 10.1,15H10Q8.225,15 6.812,15.45Q5.4,15.9 4.5,16.35Q4.275,16.475 4.138,16.7Q4,16.925 4,17.2V18H10.3Q10.45,18.525 10.7,19.038Q10.95,19.55 11.25,20ZM16,21L15.7,19.5Q15.4,19.375 15.137,19.238Q14.875,19.1 14.6,18.9L13.15,19.35L12.15,17.65L13.3,16.65Q13.25,16.3 13.25,16Q13.25,15.7 13.3,15.35L12.15,14.35L13.15,12.65L14.6,13.1Q14.875,12.9 15.137,12.762Q15.4,12.625 15.7,12.5L16,11H18L18.3,12.5Q18.6,12.625 18.863,12.775Q19.125,12.925 19.4,13.15L20.85,12.65L21.85,14.4L20.7,15.4Q20.75,15.7 20.75,16.025Q20.75,16.35 20.7,16.65L21.85,17.65L20.85,19.35L19.4,18.9Q19.125,19.1 18.863,19.238Q18.6,19.375 18.3,19.5L18,21ZM17,18Q17.825,18 18.413,17.413Q19,16.825 19,16Q19,15.175 18.413,14.587Q17.825,14 17,14Q16.175,14 15.588,14.587Q15,15.175 15,16Q15,16.825 15.588,17.413Q16.175,18 17,18ZM10,10Q10.825,10 11.413,9.412Q12,8.825 12,8Q12,7.175 11.413,6.588Q10.825,6 10,6Q9.175,6 8.588,6.588Q8,7.175 8,8Q8,8.825 8.588,9.412Q9.175,10 10,10ZM10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8ZM10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Z&quot;/>"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_manage_users.xml"
+            line="22"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (866 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M14.95,11.3l1.62,-1.61C16.84,10.41 17,11.18 17,12s-0.16,1.61 -0.44,2.33l-1.61,-1.61C14.56,12.33 14.56,11.69 14.95,11.3zM18.69,7.54c-0.26,0.26 -0.32,0.65 -0.17,0.98c0.47,1.07 0.72,2.24 0.72,3.47c0,1.24 -0.26,2.43 -0.73,3.49c-0.14,0.32 -0.09,0.69 0.16,0.94c0.4,0.4 1.09,0.29 1.34,-0.23c0.63,-1.3 0.98,-2.76 0.98,-4.3c-0.01,-1.46 -0.33,-2.86 -0.91,-4.12C19.84,7.23 19.12,7.11 18.69,7.54zM15.26,15.74c0.41,0.41 0.41,1.07 0,1.48l-4.51,4.51C10.57,21.89 10.32,22 10.04,22C9.47,22 9,21.53 9,20.96v-6.45l-4.05,4.05c-0.41,0.41 -1.06,0.41 -1.47,0s-0.41,-1.06 0,-1.47L8.57,12L3.48,6.9c-0.41,-0.41 -0.41,-1.06 0,-1.47s1.06,-0.41 1.47,0L9,9.49V3.04C9,2.47 9.47,2 10.04,2c0.28,0 0.53,0.11 0.72,0.29l4.5,4.5c0.41,0.41 0.41,1.07 0,1.48L11.51,12L15.26,15.74zM13.14,7.53l-2.15,-2.15v4.3C10.99,9.68 13.14,7.53 13.14,7.53zM13.14,16.47l-2.15,-2.15v4.3C10.99,18.62 13.14,16.47 13.14,16.47z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml"
+            line="23"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (836 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M2,12C2,6.48 6.47,2 11.99,2C17.52,2 22,6.48 22,12c0,0.34 -0.02,0.67 -0.05,1h-2.02c0.04,-0.33 0.07,-0.66 0.07,-1c0,-0.69 -0.1,-1.36 -0.26,-2h-3.38c0.08,0.66 0.14,1.32 0.14,2c0,0.34 -0.01,0.67 -0.04,1h-2.01c0.03,-0.33 0.05,-0.66 0.05,-1c0,-0.68 -0.07,-1.35 -0.16,-2H9.66c-0.09,0.65 -0.16,1.32 -0.16,2s0.07,1.34 0.16,2H13v2h-2.91c0.43,1.43 1.08,2.76 1.91,3.96V20h1v1.95C12.67,21.98 12.33,22 11.99,22C6.47,22 2,17.52 2,12zM15.97,8h2.95c-0.96,-1.65 -2.49,-2.93 -4.33,-3.56C15.19,5.55 15.65,6.75 15.97,8zM13.91,8C13.48,6.57 12.83,5.24 12,4.04c-0.83,1.2 -1.48,2.53 -1.91,3.96H13.91zM4,12c0,0.69 0.1,1.36 0.26,2h3.38c-0.08,-0.66 -0.14,-1.32 -0.14,-2s0.06,-1.34 0.14,-2H4.26C4.1,10.64 4,11.31 4,12zM8.03,16H5.08c0.96,1.66 2.49,2.93 4.33,3.56C8.81,18.45 8.35,17.25 8.03,16zM5.08,8h2.95c0.32,-1.25 0.78,-2.45 1.38,-3.56C7.57,5.07 6.04,6.34 5.08,8z&quot;"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_qs_no_internet_unavailable.xml"
+            line="23"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1847 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z&quot;/>"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_settings.xml"
+            line="22"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1847 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z&quot;/>"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_settings_24dp.xml"
+            line="25"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1227 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M920,401Q848,401 782,373.5Q716,346 665,295Q614,244 586.5,178Q559,112 559,40L639,40Q639,97 660,148Q681,199 721,239Q761,279 812,300.5Q863,322 920,322L920,401ZM920,242Q879,242 842.5,227Q806,212 777,183Q748,154 733,117.5Q718,81 718,40L797,40Q797,65 806.5,87.5Q816,110 833,127Q850,144 872.5,153Q895,162 920,162L920,242ZM400,520Q334,520 287,473Q240,426 240,360Q240,294 287,247Q334,200 400,200Q466,200 513,247Q560,294 560,360Q560,426 513,473Q466,520 400,520ZM80,840L80,728Q80,695 97,666Q114,637 144,622Q195,596 259,578Q323,560 400,560Q477,560 541,578Q605,596 656,622Q686,637 703,666Q720,695 720,728L720,840L80,840ZM160,760L640,760L640,728Q640,717 634.5,708Q629,699 620,694Q584,676 527.5,658Q471,640 400,640Q329,640 272.5,658Q216,676 180,694Q171,699 165.5,708Q160,717 160,728L160,760ZM400,440Q433,440 456.5,416.5Q480,393 480,360Q480,327 456.5,303.5Q433,280 400,280Q367,280 343.5,303.5Q320,327 320,360Q320,393 343.5,416.5Q367,440 400,440ZM400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360ZM400,760L400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760L400,760L400,760Z&quot; />"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_spatial_audio.xml"
+            line="25"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (1224 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M750,550L806,494Q766,454 743.5,402.5Q721,351 721,294Q721,237 743.5,186Q766,135 806,95L750,37Q699,88 670,155Q641,222 641,294Q641,366 670,432.5Q699,499 750,550ZM862,436L918,380Q901,363 891,341Q881,319 881,294Q881,269 891,247Q901,225 918,208L862,151Q833,180 817,216Q801,252 801,293Q801,334 817,371Q833,408 862,436ZM400,520Q334,520 287,473Q240,426 240,360Q240,294 287,247Q334,200 400,200Q466,200 513,247Q560,294 560,360Q560,426 513,473Q466,520 400,520ZM80,840L80,728Q80,695 97,666Q114,637 144,622Q195,596 259,578Q323,560 400,560Q477,560 541,578Q605,596 656,622Q686,637 703,666Q720,695 720,728L720,840L80,840ZM160,760L640,760L640,728Q640,717 634.5,708Q629,699 620,694Q584,676 527.5,658Q471,640 400,640Q329,640 272.5,658Q216,676 180,694Q171,699 165.5,708Q160,717 160,728L160,760ZM400,440Q433,440 456.5,416.5Q480,393 480,360Q480,327 456.5,303.5Q433,280 400,280Q367,280 343.5,303.5Q320,327 320,360Q320,393 343.5,416.5Q367,440 400,440ZM400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360ZM400,760L400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760L400,760L400,760Z&quot; />"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/ic_spatial_audio_off.xml"
+            line="25"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="VectorPath"
+        message="Very long vector path (921 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+        errorLine1="        android:pathData=&quot;M11.95,18Q12.475,18 12.838,17.637Q13.2,17.275 13.2,16.75Q13.2,16.225 12.838,15.863Q12.475,15.5 11.95,15.5Q11.425,15.5 11.062,15.863Q10.7,16.225 10.7,16.75Q10.7,17.275 11.062,17.637Q11.425,18 11.95,18ZM11.05,14.15H12.9Q12.9,13.325 13.088,12.85Q13.275,12.375 14.15,11.55Q14.8,10.9 15.175,10.312Q15.55,9.725 15.55,8.9Q15.55,7.5 14.525,6.75Q13.5,6 12.1,6Q10.675,6 9.788,6.75Q8.9,7.5 8.55,8.55L10.2,9.2Q10.325,8.75 10.763,8.225Q11.2,7.7 12.1,7.7Q12.9,7.7 13.3,8.137Q13.7,8.575 13.7,9.1Q13.7,9.6 13.4,10.037Q13.1,10.475 12.65,10.85Q11.55,11.825 11.3,12.325Q11.05,12.825 11.05,14.15ZM12,22Q9.925,22 8.1,21.212Q6.275,20.425 4.925,19.075Q3.575,17.725 2.788,15.9Q2,14.075 2,12Q2,9.925 2.788,8.1Q3.575,6.275 4.925,4.925Q6.275,3.575 8.1,2.787Q9.925,2 12,2Q14.075,2 15.9,2.787Q17.725,3.575 19.075,4.925Q20.425,6.275 21.212,8.1Q22,9.925 22,12Q22,14.075 21.212,15.9Q20.425,17.725 19.075,19.075Q17.725,20.425 15.9,21.212Q14.075,22 12,22Z&quot;/>"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/media_output_status_help.xml"
+            line="25"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="ViewHolder"
+        message="Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling"
+        errorLine1="                    layoutInflater.inflate("
+        errorLine2="                    ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt"
+            line="229"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="HandlerLeak"
+        message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)"
+        errorLine1="    private Handler mHandler = new Handler() {"
+        errorLine2="                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java"
+            line="144"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="HandlerLeak"
+        message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)"
+        errorLine1="    private Handler mHandler = new Handler() {"
+        errorLine2="                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="2165"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="HandlerLeak"
+        message="This `Handler` class should be static or leaks might occur (com.android.systemui.keyboard.KeyboardUI.KeyboardUIHandler)"
+        errorLine1="    private final class KeyboardUIHandler extends Handler {"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java"
+            line="430"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="HandlerLeak"
+        message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)"
+        errorLine1="    private Handler mHandler = new Handler() {"
+        errorLine2="                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java"
+            line="171"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="HandlerLeak"
+        message="This `Handler` class should be static or leaks might occur (com.android.systemui.shortcut.ShortcutKeyServiceProxy.H)"
+        errorLine1="    private final class H extends Handler {"
+        errorLine2="                        ~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java"
+            line="49"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="MergeRootFrame"
+        message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag"
+        errorLine1="&lt;FrameLayout"
+        errorLine2="^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_detail_dialog.xml"
+            line="18"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="MergeRootFrame"
+        message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag"
+        errorLine1="&lt;FrameLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+        errorLine2="^">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/rotate_suggestion.xml"
+            line="17"
+            column="1"/>
+    </issue>
+
+    <issue
+        id="UseValueOf"
+        message="Use `Long.valueOf(c2.getLastInteractionTimestamp())` instead"
+        errorLine1="                .sorted((c1, c2) -> new Long(c2.getLastInteractionTimestamp()).compareTo("
+        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="307"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="UseValueOf"
+        message="Use `Long.valueOf(c1.getLastInteractionTimestamp())` instead"
+        errorLine1="                        new Long(c1.getLastInteractionTimestamp())))"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+            line="308"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_app_item.xml"
+            line="22"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="                &lt;LinearLayout"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="93"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="                &lt;LinearLayout"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="199"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="                &lt;LinearLayout"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="250"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+            line="25"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="        &lt;LinearLayout"
+        errorLine2="         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_v2.xml"
+            line="63"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="DisableBaselineAlignment"
+        message="Set `android:baselineAligned=&quot;false&quot;` on this element for better performance"
+        errorLine1="&lt;LinearLayout"
+        errorLine2=" ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+            line="17"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                        android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="114"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                        android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="150"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                        android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="208"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                        android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="275"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="            android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+            line="48"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="        android:layout_height=&quot;wrap_content&quot;"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_dialog.xml"
+            line="109"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+            line="38"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                    android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+            line="129"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="            android:layout_height=&quot;wrap_content&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+            line="38"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_v2.xml"
+            line="73"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `match_parent` for better performance"
+        errorLine1=" android:layout_width=&quot;match_parent&quot;"
+        errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+            line="38"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="                android:layout_height=&quot;wrap_content&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/remote_input.xml"
+            line="79"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="InefficientWeight"
+        message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+        errorLine1="            android:layout_width=&quot;wrap_content&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar_notification_section_header.xml"
+            line="37"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NestedWeights"
+        message="Nested weights are bad for performance"
+        errorLine1="                android:layout_weight=&quot;1&quot;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_placeholder_layout.xml"
+            line="47"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:colorBackground` with a theme that also paints a background (inferred theme is `@android_style/Theme_Translucent_NoTitleBar_Fullscreen`)"
+        errorLine1="    android:background=&quot;?android:colorBackground&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/auth_biometric_background.xml"
+            line="20"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:attr/colorBackground` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="        android:background=&quot;?android:attr/colorBackground&quot;>"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="29"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:attr/dividerHorizontal` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?android:attr/dividerHorizontal&quot; />"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/keyboard_shortcuts_category_separator.xml"
+            line="25"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:attr/colorBackground` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?android:attr/colorBackground&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_projection_recent_tasks.xml"
+            line="22"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `@drawable/system_bar_background` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;@drawable/system_bar_background&quot;>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/navigation_bar.xml"
+            line="27"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?androidprv:attr/materialColorOnSurfaceVariant` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?androidprv:attr/materialColorOnSurfaceVariant&quot; />"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_children_divider.xml"
+            line="24"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?androidprv:attr/materialColorSurfaceContainerHigh` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?androidprv:attr/materialColorSurfaceContainerHigh&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_snooze.xml"
+            line="26"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:attr/colorAccent` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?android:attr/colorAccent&quot;>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="31"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:attr/colorAccent` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?android:attr/colorAccent&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="28"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `?android:attr/colorAccent` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;?android:attr/colorAccent&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="28"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `@drawable/status_bar_user_chip_bg` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+        errorLine1="    android:background=&quot;@drawable/status_bar_user_chip_bg&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar_user_chip_container.xml"
+            line="26"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="UselessLeaf"
+        message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/global_actions_grid.xml"
+            line="37"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="UselessLeaf"
+        message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/global_actions_grid.xml"
+            line="43"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="UselessLeaf"
+        message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout-land/global_actions_grid.xml"
+            line="49"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="UselessLeaf"
+        message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+        errorLine1="                &lt;LinearLayout"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid.xml"
+            line="73"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="UselessLeaf"
+        message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+        errorLine1="                &lt;LinearLayout"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid.xml"
+            line="79"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="UselessLeaf"
+        message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+        errorLine1="                &lt;LinearLayout"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid.xml"
+            line="85"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `ScrollView` layout or its `FrameLayout` parent is possibly unnecessary"
+        errorLine1="        &lt;ScrollView"
+        errorLine2="         ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/alert_dialog_systemui.xml"
+            line="39"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary"
+        errorLine1="        &lt;LinearLayout"
+        errorLine2="         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/combined_qs_header.xml"
+            line="128"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary"
+        errorLine1="  &lt;LinearLayout"
+        errorLine2="   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_detail_dialog.xml"
+            line="23"
+            column="4"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary"
+        errorLine1="            &lt;LinearLayout"
+        errorLine2="             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="58"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `RelativeLayout` layout or its `LinearLayout` parent is possibly unnecessary"
+        errorLine1="    &lt;RelativeLayout"
+        errorLine2="     ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_view.xml"
+            line="37"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `RelativeLayout` layout or its `FrameLayout` parent is unnecessary"
+        errorLine1="  &lt;RelativeLayout"
+        errorLine2="   ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/magnifier_controllers.xml"
+            line="25"
+            column="4"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `FrameLayout` layout or its `LinearLayout` parent is unnecessary"
+        errorLine1="    &lt;FrameLayout"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_list_item.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notif_half_shelf.xml"
+            line="28"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="        &lt;LinearLayout"
+        errorLine2="         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml"
+            line="69"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_initial_layout.xml"
+            line="23"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_placeholder_layout.xml"
+            line="23"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_tile_view.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="        &lt;LinearLayout"
+        errorLine2="         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_tile_view.xml"
+            line="32"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_empty.xml"
+            line="22"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `RelativeLayout` layout or its `LinearLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;RelativeLayout"
+        errorLine2="     ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+            line="28"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+            line="22"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small_horizontal.xml"
+            line="22"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `ScrollView` layout or its `LinearLayout` parent is unnecessary"
+        errorLine1="    &lt;ScrollView"
+        errorLine2="     ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `FrameLayout` layout or its `FrameLayout` parent is possibly unnecessary"
+        errorLine1="            &lt;FrameLayout"
+        errorLine2="             ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar.xml"
+            line="66"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary"
+        errorLine1="  &lt;LinearLayout"
+        errorLine2="   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/user_switcher_fullscreen_popup_item.xml"
+            line="24"
+            column="4"/>
+    </issue>
+
+    <issue
+        id="UselessParent"
+        message="This `LinearLayout` layout or its `FrameLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+        errorLine1="    &lt;LinearLayout"
+        errorLine2="     ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_dialog_row.xml"
+            line="29"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="RedundantNamespace"
+        message="This namespace declaration is redundant"
+        errorLine1="        &lt;shape xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>"
+        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable/rounded_ripple.xml"
+            line="19"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="UnusedNamespace"
+        message="Unused namespace `systemui`"
+        errorLine1="    xmlns:systemui=&quot;http://schemas.android.com/apk/res/com.android.systemui&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar.xml"
+            line="23"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Stoor tans skermkiekie...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-af/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;ቅጽበታዊ ገፅ ዕይታ በማስቀመጥ ላይ...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;جارٍ حفظ لقطة الشاشة...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Skrinşot yadda saxlanır...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Čuvanje snimka ekrana...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Захаванне скрыншота...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Екранната снимка се запазва...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;স্ক্রিনশট সেভ করা হচ্ছে...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Spašavanje snimka ekrana...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;S\&apos;està desant la captura de pantalla...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Ukládání snímku obrazovky...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Gemmer screenshot...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-da/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Screenshot wird gespeichert...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Αποθήκευση στιγμιότυπου οθόνης...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-el/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Guardando la captura de pantalla...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Guardando captura...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Kuvatõmmise salvestamine ...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Tallennetaan kuvakaappausta...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fi/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;स्क्रीनशॉट सहेजा जा रहा है...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Spremanje snimke zaslona...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Képernyőkép mentése...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hu/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Սքրինշոթը պահվում է...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Menyimpan screenshot...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;המערכת שומרת את צילום המסך...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;スクリーンショットを保存しています...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;កំពុង​រក្សាទុក​រូបថត​អេក្រង់...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;캡쳐화면 저장 중...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Скриншот сакталууда...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ky/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;ກຳລັງບັນທຶກພາບໜ້າຈໍ...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Išsaugoma ekrano kopija...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Notiek ekrānuzņēmuma saglabāšana...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lv/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Сликата на екранот се зачувува...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Menyimpan tangkapan skrin...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Screenshot opslaan...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-nl/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Zapisywanie zrzutu ekranu...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Salvando captura de tela...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;A guardar captura de ecrã...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Salvando captura de tela...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Se salvează captura de ecran...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Сохранение...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Prebieha ukladanie snímky obrazovky...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Shranjevanje posnetka zaslona ...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Чување снимка екрана...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Skärmbilden sparas ...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Inahifadhi picha ya skrini...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;กำลังบันทึกภาพหน้าจอ...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Ekran görüntüsü kaydediliyor...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Збереження знімка екрана...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-uk/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Đang lưu ảnh chụp màn hình...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;正在保存屏幕截图...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;正在儲存螢幕擷取畫面...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;screenshot_saving_title&quot; msgid=&quot;2298349784913287333&quot;>&quot;Ilondoloz umfanekiso weskrini...&quot;&lt;/string>"
+        errorLine2="                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+            line="77"
+            column="72"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;በማብራት ላይ...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Aktiv edilir...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Uključuje se...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Включва се...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;កំពុង​បើក...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;켜는 중...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;ກຳລັງເປີດ...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;A ativar...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Se activează...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Укључује се...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Inawasha...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;กำลังเปิด...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_bluetooth_secondary_label_transient&quot; msgid=&quot;3882884317600669650&quot;>&quot;Iyavula...&quot;&lt;/string>"
+        errorLine2="                                                                                                  ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+            line="292"
+            column="99"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;በማብራት ላይ...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Aktiv edilir...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Uključuje se...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Включва се...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;កំពុង​បើក...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;켜는 중...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;ກຳລັງເປີດ...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;A ativar...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Se activează...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Укључује се...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Inawasha...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;กำลังเปิด...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_wifi_secondary_label_transient&quot; msgid=&quot;7501659015509357887&quot;>&quot;Iyavula...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+            line="308"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Connecting...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+            line="318"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎Connecting...‎‏‎‎‏‎&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+            line="318"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Łączę...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pl/strings.xml"
+            line="318"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;በማገናኘት ላይ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;جارٍ الاتصال...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ar/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;সংযোগ কৰি থকা হৈছে...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-as/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Qoşulur...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Povezuje se...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Падлучэнне...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-be/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Установява се връзка...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;সংযুক্ত হচ্ছে...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Povezivanje...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bs/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;S\&apos;està connectant...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ca/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Připojování...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Connecting...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Connecting...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Connecting...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Conectando...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Ühenduse loomine ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-et/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;در حال اتصال...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fa/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Connexion en cours...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-fr/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Conectando...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gl/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;કનેક્ટ કરી રહ્યું છે...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-gu/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;कनेक्ट हो रहा है...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hi/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Povezivanje...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Միանում է...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-hy/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Menghubungkan...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-in/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Tengist...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-is/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Connessione in corso...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-it/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;מתבצע חיבור...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-iw/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;接続しています...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;დაკავშირება...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ka/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;កំពុង​តភ្ជាប់...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;연결 중...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;ກຳລັງເຊື່ອມຕໍ່...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Prisijungiama...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Се поврзува...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mk/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;കണക്റ്റുചെയ്യുന്നു...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ml/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Холбогдож байна...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mn/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;कनेक्ट करत आहे...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-mr/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Menyambung...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ms/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;ဆက်သွယ်နေ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-my/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;कनेक्ट गरिँदै छ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;ସଂଯୋଗ କରୁଛି...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-or/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pa/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Conectando...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;A ligar...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Conectando...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Se conectează...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Соединение...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;සම්බන්ධ වෙමින්...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-si/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Pripája sa...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sk/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Vzpostavljanje povezave ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Po lidhet...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sq/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Повезује се...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Ansluter ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Inaunganisha...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;இணைக்கிறது...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ta/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;కనెక్ట్ అవుతోంది...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-te/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;กำลังเชื่อมต่อ...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Kumokonekta...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tl/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Bağlanılıyor...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-tr/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Đang kết nối...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-vi/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;連線中...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot; msgid=&quot;2381969772953268809&quot;>&quot;Iyaxhuma...&quot;&lt;/string>"
+        errorLine2="                                                                         ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+            line="323"
+            column="74"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;በማብራት ላይ...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Aktiv edilir...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Uključuje se...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Включва се...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;កំពុង​បើក...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;켜는 중...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;ກຳລັງເປີດ...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;A ativar...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Se activează...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Укључује се...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Inawasha...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;กำลังเปิด...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_hotspot_secondary_label_transient&quot; msgid=&quot;7585604088079160564&quot;>&quot;Iyavula...&quot;&lt;/string>"
+        errorLine2="                                                                                                ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+            line="325"
+            column="97"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;media_output_label_title&quot; msgid=&quot;872824698593182505&quot;>&quot;&lt;xliff:g id=&quot;LABEL&quot;>%s&lt;/xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗು...&quot;&lt;/string>"
+        errorLine2="                                                                                             ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+            line="628"
+            column="94"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;quick_settings_connecting&quot;>Connecting...&lt;/string>"
+        errorLine2="                                             ~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+            line="793"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="TypographyEllipsis"
+        message="Replace &quot;...&quot; with ellipsis character (…, &amp;#8230;) ?"
+        errorLine1="    &lt;string name=&quot;shutdown_progress&quot; msgid=&quot;5464239146561542178&quot;>&quot;सट डाउन गरिँदै छ...&quot;&lt;/string>"
+        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/values-ne/strings.xml"
+            line="878"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="IconDipSize"
+        message="The image `ic_sysbar_lights_out_dot_small.png` varies significantly in its density-independent (dip) size across the various density versions: drawable-hdpi/ic_sysbar_lights_out_dot_small.png: 5x4 dp (7x6 px), drawable-mdpi/ic_sysbar_lights_out_dot_small.png: 8x9 dp (8x9 px), drawable-xhdpi/ic_sysbar_lights_out_dot_small.png: 6x7 dp (11x13 px), drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png: 4x4 dp (13x12 px)">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png"/>
+    </issue>
+
+    <issue
+        id="IconDipSize"
+        message="The image `ic_sysbar_lights_out_dot_small.png` varies significantly in its density-independent (dip) size across the various density versions: drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png: 6x5 dp (9x8 px), drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png: 7x10 dp (7x10 px), drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png: 7x8 dp (14x15 px), drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png: 5x5 dp (15x15 px)">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png"/>
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png"/>
+    </issue>
+
+    <issue
+        id="IconDensities"
+        message="Missing the following drawables in `drawable-hdpi`: dream_preview_back_arrow.png (found in drawable-mdpi, drawable-xhdpi, drawable-xxhdpi)">
+        <location
+            file="frameworks/base/packages/SystemUI/res/drawable-hdpi"/>
+    </issue>
+
+    <issue
+        id="ButtonOrder"
+        message="Cancel button should be on the left (was &quot;Cancel |  | Confirm | &quot;Try again&quot;&quot;, should be &quot;Cancel |  |  | Confirm | &quot;Try again&quot;&quot;)"
+        errorLine1="        &lt;Button android:id=&quot;@+id/button_cancel&quot;"
+        errorLine2="         ~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/biometric_prompt_layout.xml"
+            line="156"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="TextFields"
+        message="This text field does not specify an `inputType`"
+        errorLine1="        &lt;EditText"
+        errorLine2="         ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml"
+            line="46"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="TextFields"
+        message="This text field does not specify an `inputType`"
+        errorLine1="    &lt;EditText"
+        errorLine2="     ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_update_dialog.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`TouchHandler#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="    override fun onTouch(v: View, ev: MotionEvent): Boolean {"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt"
+            line="74"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`TouchHandler#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="        public boolean onTouch(View v, MotionEvent ev) {"
+        errorLine2="                       ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java"
+            line="71"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `CaptionsToggleImageButton` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java"
+            line="53"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NotificationShadeWindowView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        getNotificationShadeWindowView().setOnTouchListener(getStatusBarWindowTouchListener());"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="1158"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="        return (v, event) -> {"
+        errorLine2="               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+            line="1477"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ClipboardView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java"
+            line="53"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `CropView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/CropView.java"
+            line="165"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`SwipeDismissHandler#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="        public boolean onTouch(View view, MotionEvent event) {"
+        errorLine2="                       ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java"
+            line="232"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `EmergencyButton` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java"
+            line="75"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``EmergencyButton`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mEmergencyButton.setOnTouchListener(new OnTouchListener(){"
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java"
+            line="47"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="            public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                           ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java"
+            line="49"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ExpandableNotificationRow` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+            line="987"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="            mContainer.setOnTouchListener((v, event) -> {"
+        errorLine2="                                          ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+            line="2450"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ClingWindowView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="        public boolean onTouchEvent(MotionEvent motion) {"
+        errorLine2="                       ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+            line="479"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="            public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                           ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/Interaction.java"
+            line="29"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `KeyButtonView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+            line="267"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `KeyguardPatternView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java"
+            line="241"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``LockPatternView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mLockPatternView.setOnTouchListener((v, event) -> {"
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java"
+            line="229"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="        mLockPatternView.setOnTouchListener((v, event) -> {"
+        errorLine2="                                            ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java"
+            line="229"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``LockPatternView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mLockPatternView.setOnTouchListener(null);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java"
+            line="258"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="    private final OnTouchListener mActionButtonTouchListener = (v, event) -> {"
+        errorLine2="                                                               ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+            line="60"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NumPadKey`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            button.setOnTouchListener((v, event) -> {"
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+            line="97"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="            button.setOnTouchListener((v, event) -> {"
+        errorLine2="                                      ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+            line="97"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NumPadKey`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            button.setOnTouchListener(null);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+            line="175"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `KeyguardSecurityContainer` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java"
+            line="503"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `KeyguardSecurityViewFlipper` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java"
+            line="55"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``KeyguardUserSwitcherView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mView.setOnTouchListener((v, event) -> {"
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java"
+            line="190"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="        mView.setOnTouchListener((v, event) -> {"
+        errorLine2="                                 ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java"
+            line="190"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ListView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        listView.setOnTouchListener((v, ev) -> {"
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java"
+            line="77"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="        listView.setOnTouchListener((v, ev) -> {"
+        errorLine2="                                    ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java"
+            line="77"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mImageView.setOnTouchListener(this::onTouch);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+            line="117"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``MediaOutputSeekbar`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            mSeekBar.setOnTouchListener((v, event) -> true);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="509"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="            mSeekBar.setOnTouchListener((v, event) -> true);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="509"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``MediaOutputSeekbar`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            mSeekBar.setOnTouchListener((v, event) -> false);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="515"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="            mSeekBar.setOnTouchListener((v, event) -> false);"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="515"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``FrameLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="                    mIconAreaLayout.setOnTouchListener(((iconV, event) -> false));"
+        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="522"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="                    mIconAreaLayout.setOnTouchListener(((iconV, event) -> false));"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="522"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``FrameLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="                    mIconAreaLayout.setOnTouchListener(((iconV, event) -> {"
+        errorLine2="                    ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="528"
+            column="21"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="                    mIconAreaLayout.setOnTouchListener(((iconV, event) -> {"
+        errorLine2="                                                        ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+            line="528"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `MediaScrollView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    override fun onTouchEvent(ev: MotionEvent?): Boolean {"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaScrollView.kt"
+            line="106"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NavigationBarView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mView.setOnTouchListener(this::onNavigationTouch);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+            line="782"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NavigationBarView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+            line="383"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NearestTouchFrame` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java"
+            line="207"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NonInterceptingScrollView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java"
+            line="46"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``FrameLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        super.setOnTouchListener(touchHandler);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java"
+            line="111"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`TouchHandler#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="        public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                       ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+            line="5018"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NotificationShadeWindowView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+            line="133"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NotificationStackScrollLayout` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java"
+            line="3365"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NumPadButton` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadButton.java"
+            line="84"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NumPadKey` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+            line="164"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ObservableScrollView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java"
+            line="70"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `PhoneStatusBarView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java"
+            line="208"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`QSContainerImpl#performClick` should call `super#performClick`"
+        errorLine1="    public boolean performClick() {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java"
+            line="106"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="        public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                       ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+            line="52"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NonInterceptingScrollView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            mQSPanelContainer.setOnTouchListener(null);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+            line="84"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NonInterceptingScrollView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            mQSPanelContainer.setOnTouchListener(mContainerTouchHandler);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+            line="97"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``NonInterceptingScrollView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="            mQSPanelContainer.setOnTouchListener(null);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+            line="105"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="        public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                       ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java"
+            line="77"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``PagedTileLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        pagedTileLayout.setOnTouchListener(mTileLayoutTouchListener);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java"
+            line="143"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `QSScrollLayout` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java"
+            line="77"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `QuickStatusBarHeader` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java"
+            line="74"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `RemoteInputView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java"
+            line="409"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``SeekBar`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        bar.setOnTouchListener(SeekBarTouchListener(this, bar))"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt"
+            line="348"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`SeekBarTouchListener#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="        override fun onTouch(view: View, event: MotionEvent): Boolean {"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt"
+            line="456"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `SettingsButton` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java"
+            line="63"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`SimpleMirrorWindowControl#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="    public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                   ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java"
+            line="119"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ToggleSeekBar` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSeekBar.java"
+            line="43"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `WalletView` overrides `onTouchEvent` but not `performClick`"
+        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
+        errorLine2="                   ~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java"
+            line="138"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected"
+        errorLine1="        final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {"
+        errorLine2="                                                         ^">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+            line="106"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``Button`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+            line="121"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mDragView.setOnTouchListener(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1015"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mCloseView.setOnTouchListener(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1020"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mTopLeftCornerView.setOnTouchListener(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1021"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mTopRightCornerView.setOnTouchListener(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1022"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mBottomLeftCornerView.setOnTouchListener(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1023"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mBottomRightCornerView.setOnTouchListener(this);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1024"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`WindowMagnificationController#onTouch` should call `View#performClick` when a click is detected"
+        errorLine1="    public boolean onTouch(View v, MotionEvent event) {"
+        errorLine2="                   ~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+            line="1172"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``LinearLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+        errorLine1="        mSettingView.setOnTouchListener(this::onTouch);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+            line="516"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml"
+            line="38"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/auth_biometric_background.xml"
+            line="26"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/bindable_status_bar_icon.xml"
+            line="25"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/biometric_prompt_layout.xml"
+            line="23"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/bluetooth_device_item.xml"
+            line="28"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/bluetooth_device_item.xml"
+            line="85"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml"
+            line="170"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/broadcast_dialog.xml"
+            line="29"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/chipbar.xml"
+            line="65"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/chipbar.xml"
+            line="75"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+            line="27"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+            line="138"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+            line="143"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+            line="177"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/connected_device_signal.xml"
+            line="33"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/connected_display_chip.xml"
+            line="39"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/contrast_dialog.xml"
+            line="41"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/contrast_dialog.xml"
+            line="73"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/contrast_dialog.xml"
+            line="105"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_app_item.xml"
+            line="35"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_base_item.xml"
+            line="30"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_base_item.xml"
+            line="115"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="40"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="  &lt;ImageView"
+        errorLine2="   ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/fgs_manager_app_item.xml"
+            line="25"
+            column="4"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml"
+            line="25"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml"
+            line="32"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_power_item.xml"
+            line="25"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="      &lt;ImageView"
+        errorLine2="       ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/global_actions_view.xml"
+            line="43"
+            column="8"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/hybrid_conversation_notification.xml"
+            line="30"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/immersive_mode_cling.xml"
+            line="29"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/immersive_mode_cling.xml"
+            line="36"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/immersive_mode_cling.xml"
+            line="43"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                        &lt;ImageView"
+        errorLine2="                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="104"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                        &lt;ImageView"
+        errorLine2="                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="138"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                        &lt;ImageView"
+        errorLine2="                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="264"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                        &lt;ImageView"
+        errorLine2="                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="295"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="326"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+            line="369"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+            line="36"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+            line="67"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml"
+            line="27"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="&lt;ImageView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+        errorLine2=" ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml"
+            line="18"
+            column="2"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView android:id=&quot;@+id/multi_user_avatar&quot;"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/keyguard_status_bar.xml"
+            line="55"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/log_access_user_consent_dialog_permission.xml"
+            line="41"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/long_screenshot.xml"
+            line="74"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/long_screenshot.xml"
+            line="92"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/long_screenshot.xml"
+            line="156"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/magnifier_controllers.xml"
+            line="29"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+            line="34"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+            line="41"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+            line="80"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+            line="112"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+            line="130"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_list_item.xml"
+            line="54"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_recommendation_view.xml"
+            line="20"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="32"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="138"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="187"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="230"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="273"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="299"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="309"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="319"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="329"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageButton"
+        errorLine2="     ~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+            line="339"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/mobile_signal_group.xml"
+            line="31"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/mobile_signal_group.xml"
+            line="39"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/mobile_signal_group.xml"
+            line="48"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notif_half_shelf.xml"
+            line="53"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="69"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="77"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="85"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="232"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="283"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+            line="335"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="39"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="180"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="231"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="283"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_snooze.xml"
+            line="44"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/ongoing_call_chip.xml"
+            line="39"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/overlay_action_chip.xml"
+            line="34"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="38"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_initial_layout.xml"
+            line="43"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_placeholder_layout.xml"
+            line="50"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_space_tile_view.xml"
+            line="38"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+            line="21"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+            line="32"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+            line="36"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+            line="48"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+            line="52"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_empty_layout.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_empty.xml"
+            line="33"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_empty.xml"
+            line="59"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+            line="36"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+            line="42"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+            line="103"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+            line="124"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_empty.xml"
+            line="35"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_empty.xml"
+            line="39"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+            line="49"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+            line="55"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+            line="83"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+            line="147"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+            line="34"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+            line="42"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small_horizontal.xml"
+            line="34"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_small_horizontal.xml"
+            line="42"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_suppressed_layout.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_with_suppression_detail_content_horizontal.xml"
+            line="28"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_with_suppression_detail_content_vertical.xml"
+            line="33"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_with_suppression_detail_content_vertical.xml"
+            line="53"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_work_profile_quiet_layout.xml"
+            line="25"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView android:id=&quot;@+id/work_widget_badge_icon&quot;"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_work_profile_quiet_layout.xml"
+            line="32"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item.xml"
+            line="30"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item.xml"
+            line="53"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+            line="71"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1=" &lt;ImageView"
+        errorLine2="  ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+            line="26"
+            column="3"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1=" &lt;ImageView"
+        errorLine2="  ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+            line="56"
+            column="3"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_tile_side_icon.xml"
+            line="23"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/qs_user_detail_item.xml"
+            line="55"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/quick_settings_footer_dialog_parental_controls.xml"
+            line="30"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/remote_input.xml"
+            line="46"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/remote_input.xml"
+            line="54"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="48"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="55"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="65"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="91"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="98"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="108"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="134"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="141"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+            line="151"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="44"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="51"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="61"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="84"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="91"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="101"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="125"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="132"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+            line="142"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="44"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="52"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="63"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="87"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="95"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="106"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="130"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="138"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+            line="149"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+            line="43"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+            line="69"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                    &lt;ImageView"
+        errorLine2="                     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+            line="103"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot.xml"
+            line="31"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+            line="83"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+            line="102"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+            line="113"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+            line="23"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+            line="95"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+            line="114"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+            line="125"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml"
+            line="12"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml"
+            line="36"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml"
+            line="33"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml"
+            line="60"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/sensor_use_started_title.xml"
+            line="32"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/sensor_use_started_title.xml"
+            line="39"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/shelf_action_chip.xml"
+            line="28"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar.xml"
+            line="33"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView android:id=&quot;@+id/current_user_avatar&quot;"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar_user_chip_container.xml"
+            line="28"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml"
+            line="34"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="            &lt;ImageView"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml"
+            line="42"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/text_toast.xml"
+            line="33"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/tuner_shortcut_item.xml"
+            line="26"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/tuner_widget_settings_switch.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/udfps_enroll_view.xml"
+            line="32"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/udfps_enroll_view.xml"
+            line="38"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml"
+            line="27"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/user_switcher_fullscreen_item.xml"
+            line="23"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+            line="65"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+            line="83"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="                &lt;ImageView"
+        errorLine2="                 ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+            line="101"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+            line="125"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/window_magnifier_view.xml"
+            line="116"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="    &lt;ImageView"
+        errorLine2="     ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/window_magnifier_view.xml"
+            line="126"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="ContentDescription"
+        message="Missing `contentDescription` attribute on image"
+        errorLine1="        &lt;ImageView"
+        errorLine2="         ~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/wireless_charging_layout.xml"
+            line="44"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="LabelFor"
+        message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+        errorLine1="        &lt;EditText"
+        errorLine2="         ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml"
+            line="46"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="LabelFor"
+        message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+        errorLine1="  &lt;EditText"
+        errorLine2="   ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/controls_dialog_pin.xml"
+            line="24"
+            column="4"/>
+    </issue>
+
+    <issue
+        id="LabelFor"
+        message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+        errorLine1="    &lt;EditText"
+        errorLine2="     ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_update_dialog.xml"
+            line="24"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="SetTextI18n"
+        message="Number formatting does not take into account locale settings. Consider using `String.format` instead."
+        errorLine1="        mDigitText.setText(Integer.toString(mDigit));"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+            line="115"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="SetTextI18n"
+        message="Number formatting does not take into account locale settings. Consider using `String.format` instead."
+        errorLine1="        if (row.number != null) row.number.setText(Integer.toString(vlevel));"
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+            line="2026"
+            column="52"/>
+    </issue>
+
+    <issue
+        id="HardcodedText"
+        message="Hardcoded string &quot;Yes&quot;, should use `@string` resource"
+        errorLine1="            android:text=&quot;Yes&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="89"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="HardcodedText"
+        message="Hardcoded string &quot;No&quot;, should use `@string` resource"
+        errorLine1="            android:text=&quot;No&quot;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+            line="100"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/done` can overlap `@id/turn_off_notifications` if @string/inline_turn_off_notifications, @string/inline_ok_button grow due to localized text expansion"
+        errorLine1="            &lt;TextView"
+        errorLine2="             ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+            line="342"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/undo` can overlap `@id/expand_button` if @string/snooze_undo grows due to localized text expansion"
+        errorLine1="        &lt;TextView"
+        errorLine2="         ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/notification_snooze.xml"
+            line="54"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/done` can overlap `@id/turn_off_notifications` if @string/inline_turn_off_notifications, @string/inline_done_button grow due to localized text expansion"
+        errorLine1="            &lt;TextView"
+        errorLine2="             ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+            line="156"
+            column="14"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/punctuation3` can overlap `@id/punctuation4` if @id/punctuation4, @id/punctuation3 grow due to localized text expansion"
+        errorLine1="    &lt;TextView"
+        errorLine2="     ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+            line="53"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/punctuation5` can overlap `@id/punctuation1` if @id/punctuation1, @id/punctuation5 grow due to localized text expansion"
+        errorLine1="    &lt;TextView"
+        errorLine2="     ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+            line="81"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/punctuation5` can overlap `@id/punctuation2` if @id/punctuation2, @id/punctuation5 grow due to localized text expansion"
+        errorLine1="    &lt;TextView"
+        errorLine2="     ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+            line="81"
+            column="6"/>
+    </issue>
+
+    <issue
+        id="RelativeOverlap"
+        message="`@id/punctuation5` can overlap `@id/punctuation6` if @id/punctuation6, @id/punctuation5 grow due to localized text expansion"
+        errorLine1="    &lt;TextView"
+        errorLine2="     ~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+            line="81"
+            column="6"/>
+    </issue>
+
+</issues>
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 1120914..aa70c45 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -18,7 +18,6 @@
 package com.android.keyguard
 
 import android.content.res.Configuration
-import android.hardware.biometrics.BiometricRequestConstants
 import android.media.AudioManager
 import android.telephony.TelephonyManager
 import android.testing.TestableLooper.RunWithLooper
@@ -41,8 +40,6 @@
 import com.android.systemui.Flags as AConfigFlags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate
-import com.android.systemui.biometrics.SideFpsController
-import com.android.systemui.biometrics.SideFpsUiRequestSource
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.classifier.FalsingA11yDelegate
@@ -50,6 +47,7 @@
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
@@ -65,11 +63,10 @@
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.FakeSceneDataSource
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.DevicePostureController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -86,8 +83,6 @@
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.settings.GlobalSettings
 import com.google.common.truth.Truth
-import dagger.Lazy
-import java.util.Optional
 import junit.framework.Assert
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -143,7 +138,6 @@
     @Mock private lateinit var userSwitcherController: UserSwitcherController
     @Mock private lateinit var sessionTracker: SessionTracker
     @Mock private lateinit var keyguardViewController: KeyguardViewController
-    @Mock private lateinit var sideFpsController: SideFpsController
     @Mock private lateinit var keyguardPasswordViewControllerMock: KeyguardPasswordViewController
     @Mock private lateinit var falsingA11yDelegate: FalsingA11yDelegate
     @Mock private lateinit var telephonyManager: TelephonyManager
@@ -170,7 +164,7 @@
     private lateinit var sceneInteractor: SceneInteractor
     private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
     private lateinit var deviceEntryInteractor: DeviceEntryInteractor
-    @Mock private lateinit var primaryBouncerInteractor: Lazy<PrimaryBouncerInteractor>
+    @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
     private lateinit var sceneTransitionStateFlow: MutableStateFlow<ObservableTransitionState>
     private lateinit var fakeSceneDataSource: FakeSceneDataSource
 
@@ -209,16 +203,17 @@
 
         val keyguardKeyboardInteractor = KeyguardKeyboardInteractor(FakeKeyboardRepository())
         featureFlags = FakeFeatureFlags()
-        featureFlags.set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
         featureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
 
         mSetFlagsRule.enableFlags(
             AConfigFlags.FLAG_REVAMPED_BOUNCER_MESSAGES,
         )
-        mSetFlagsRule.disableFlags(
-            FLAG_SIDEFPS_CONTROLLER_REFACTOR,
-            AConfigFlags.FLAG_KEYGUARD_WM_STATE_REFACTOR
-        )
+        if (!SceneContainerFlag.isEnabled) {
+            mSetFlagsRule.disableFlags(
+                AConfigFlags.FLAG_KEYGUARD_WM_STATE_REFACTOR,
+                AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
+            )
+        }
 
         keyguardPasswordViewController =
             KeyguardPasswordViewController(
@@ -267,10 +262,8 @@
                 falsingManager,
                 userSwitcherController,
                 featureFlags,
-                kosmos.fakeSceneContainerFlags,
                 globalSettings,
                 sessionTracker,
-                Optional.of(sideFpsController),
                 falsingA11yDelegate,
                 telephonyManager,
                 viewMediatorCallback,
@@ -282,7 +275,7 @@
                 deviceProvisionedController,
                 faceAuthAccessibilityDelegate,
                 keyguardTransitionInteractor,
-                primaryBouncerInteractor,
+                { primaryBouncerInteractor },
             ) {
                 deviceEntryInteractor
             }
@@ -778,24 +771,6 @@
     }
 
     @Test
-    fun sideFpsControllerShow() {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        underTest.updateSideFpsVisibility(/* isVisible= */ true)
-        verify(sideFpsController)
-            .show(
-                SideFpsUiRequestSource.PRIMARY_BOUNCER,
-                BiometricRequestConstants.REASON_AUTH_KEYGUARD
-            )
-    }
-
-    @Test
-    fun sideFpsControllerHide() {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        underTest.updateSideFpsVisibility(/* isVisible= */ false)
-        verify(sideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER)
-    }
-
-    @Test
     fun setExpansion_setsAlpha() {
         underTest.setExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
         verify(view).alpha = 1f
@@ -803,17 +778,17 @@
     }
 
     @Test
+    @EnableSceneContainer
     fun dismissesKeyguard_whenSceneChangesToGone() =
         kosmos.testScope.runTest {
-            kosmos.fakeSceneContainerFlags.enabled = true
             // Upon init, we have never dismisses the keyguard.
             underTest.onInit()
             runCurrent()
-            verify(viewMediatorCallback, never()).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor, never())
+                .notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
 
             // Once the view is attached, we start listening but simply going to the bouncer scene
-            // is
-            // not enough to trigger a dismissal of the keyguard.
+            // is not enough to trigger a dismissal of the keyguard.
             underTest.onViewAttached()
             fakeSceneDataSource.pause()
             sceneInteractor.changeScene(Scenes.Bouncer, "reason")
@@ -829,7 +804,8 @@
             fakeSceneDataSource.unpause(expectedScene = Scenes.Bouncer)
             sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Bouncer)
             runCurrent()
-            verify(viewMediatorCallback, never()).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor, never())
+                .notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
 
             // While listening, going from the bouncer scene to the gone scene, does dismiss the
             // keyguard.
@@ -851,11 +827,11 @@
             fakeSceneDataSource.unpause(expectedScene = Scenes.Gone)
             sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
             runCurrent()
-            verify(viewMediatorCallback).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor).notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
 
             // While listening, moving back to the bouncer scene does not dismiss the keyguard
             // again.
-            clearInvocations(viewMediatorCallback)
+            clearInvocations(primaryBouncerInteractor)
             fakeSceneDataSource.pause()
             sceneInteractor.changeScene(Scenes.Bouncer, "reason")
             sceneTransitionStateFlow.value =
@@ -870,7 +846,8 @@
             fakeSceneDataSource.unpause(expectedScene = Scenes.Bouncer)
             sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Bouncer)
             runCurrent()
-            verify(viewMediatorCallback, never()).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor, never())
+                .notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
 
             // Detaching the view stops listening, so moving from the bouncer scene to the gone
             // scene
@@ -890,7 +867,8 @@
             fakeSceneDataSource.unpause(expectedScene = Scenes.Gone)
             sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
             runCurrent()
-            verify(viewMediatorCallback, never()).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor, never())
+                .notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
 
             // While not listening, moving to the lockscreen does not dismiss the keyguard.
             fakeSceneDataSource.pause()
@@ -907,7 +885,8 @@
             fakeSceneDataSource.unpause(expectedScene = Scenes.Lockscreen)
             sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Lockscreen)
             runCurrent()
-            verify(viewMediatorCallback, never()).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor, never())
+                .notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
 
             // Reattaching the view starts listening again so moving from the bouncer scene to the
             // gone scene now does dismiss the keyguard again, this time from lockscreen.
@@ -926,7 +905,7 @@
             fakeSceneDataSource.unpause(expectedScene = Scenes.Gone)
             sceneTransitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
             runCurrent()
-            verify(viewMediatorCallback).keyguardDone(anyInt())
+            verify(primaryBouncerInteractor).notifyKeyguardAuthenticatedPrimaryAuth(anyInt())
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
new file mode 100644
index 0000000..fefe5a0
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.pm.UserInfo;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Flags;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.ambient.touch.scrim.ScrimController;
+import com.android.systemui.ambient.touch.scrim.ScrimManager;
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.settings.FakeUserTracker;
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+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.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.Optional;
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
+    @Mock
+    CentralSurfaces mCentralSurfaces;
+
+    @Mock
+    ScrimManager mScrimManager;
+
+    @Mock
+    ScrimController mScrimController;
+
+    @Mock
+    NotificationShadeWindowController mNotificationShadeWindowController;
+
+    @Mock
+    FlingAnimationUtils mFlingAnimationUtils;
+
+    @Mock
+    FlingAnimationUtils mFlingAnimationUtilsClosing;
+
+    @Mock
+    TouchHandler.TouchSession mTouchSession;
+
+    BouncerSwipeTouchHandler mTouchHandler;
+
+    @Mock
+    BouncerSwipeTouchHandler.ValueAnimatorCreator mValueAnimatorCreator;
+
+    @Mock
+    ValueAnimator mValueAnimator;
+
+    @Mock
+    BouncerSwipeTouchHandler.VelocityTrackerFactory mVelocityTrackerFactory;
+
+    @Mock
+    VelocityTracker mVelocityTracker;
+
+    @Mock
+    UiEventLogger mUiEventLogger;
+
+    @Mock
+    LockPatternUtils mLockPatternUtils;
+
+    @Mock
+    Region mRegion;
+
+    @Captor
+    ArgumentCaptor<Rect> mRectCaptor;
+
+    FakeUserTracker mUserTracker;
+
+    private static final float TOUCH_REGION = .3f;
+    private static final int SCREEN_WIDTH_PX = 1024;
+    private static final int SCREEN_HEIGHT_PX = 100;
+    private static final float MIN_BOUNCER_HEIGHT = .05f;
+
+    private static final Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100);
+    private static final UserInfo CURRENT_USER_INFO = new UserInfo(
+            10,
+            /* name= */ "user10",
+            /* flags= */ 0
+    );
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mUserTracker = new FakeUserTracker();
+        mTouchHandler = new BouncerSwipeTouchHandler(
+                mScrimManager,
+                Optional.of(mCentralSurfaces),
+                mNotificationShadeWindowController,
+                mValueAnimatorCreator,
+                mVelocityTrackerFactory,
+                mLockPatternUtils,
+                mUserTracker,
+                mFlingAnimationUtils,
+                mFlingAnimationUtilsClosing,
+                TOUCH_REGION,
+                MIN_BOUNCER_HEIGHT,
+                mUiEventLogger);
+
+        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
+        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
+        when(mVelocityTrackerFactory.obtain()).thenReturn(mVelocityTracker);
+        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
+        when(mTouchSession.getBounds()).thenReturn(SCREEN_BOUNDS);
+        when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(true);
+
+        mUserTracker.set(Collections.singletonList(CURRENT_USER_INFO), 0);
+    }
+
+    /**
+     * Ensures expansion only happens when touch down happens in valid part of the screen.
+     */
+    @Test
+    public void testSessionStart() {
+        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, null);
+
+        verify(mRegion).union(mRectCaptor.capture());
+        final Rect bounds = mRectCaptor.getValue();
+
+        final Rect expected = new Rect();
+
+        expected.set(0, Math.round(SCREEN_HEIGHT_PX * (1 - TOUCH_REGION)), SCREEN_WIDTH_PX,
+                SCREEN_HEIGHT_PX);
+
+        assertThat(bounds).isEqualTo(expected);
+
+        mTouchHandler.onSessionStart(mTouchSession);
+        verify(mNotificationShadeWindowController).setForcePluginOpen(eq(true), any());
+        ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor =
+                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+        verify(mTouchSession).registerInputListener(eventListenerCaptor.capture());
+
+        // A touch within range at the bottom of the screen should trigger listening
+        assertThat(gestureListenerCaptor.getValue()
+                .onScroll(Mockito.mock(MotionEvent.class),
+                        Mockito.mock(MotionEvent.class),
+                        1,
+                        2)).isTrue();
+    }
+
+    @Test
+    public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() {
+        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
+                new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX));
+        verify(mRegion).union(mRectCaptor.capture());
+        final Rect bounds = mRectCaptor.getValue();
+
+        final Rect expected = new Rect();
+        final float minBouncerHeight =
+                SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT;
+        final int minAllowableBottom = SCREEN_HEIGHT_PX - Math.round(minBouncerHeight);
+
+        expected.set(0, minAllowableBottom, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
+
+        assertThat(bounds).isEqualTo(expected);
+
+        onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController);
+    }
+
+    @Test
+    public void testSwipeUp_exclusionRectAtTop_doesNotIntersectGestureArea() {
+        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
+                new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX / 4));
+        verify(mRegion).union(mRectCaptor.capture());
+        final Rect bounds = mRectCaptor.getValue();
+
+        final Rect expected = new Rect();
+        final int gestureAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION);
+        expected.set(0, gestureAreaTop, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
+
+        assertThat(bounds).isEqualTo(expected);
+        onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController);
+    }
+
+    @Test
+    public void testSwipeUp_exclusionRectBetweenNormalAndMinimumSwipeArea() {
+        final int normalSwipeAreaTop = SCREEN_HEIGHT_PX
+                - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION);
+        final int minimumSwipeAreaTop = SCREEN_HEIGHT_PX
+                - Math.round(SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT);
+
+        Rect exclusionRect = new Rect(0, 0, SCREEN_WIDTH_PX,
+                (normalSwipeAreaTop + minimumSwipeAreaTop) / 2);
+
+        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, exclusionRect);
+
+        verify(mRegion).union(mRectCaptor.capture());
+
+        final Rect bounds = mRectCaptor.getValue();
+        final Rect expected = new Rect();
+
+        final int expectedSwipeAreaBottom = exclusionRect.bottom;
+        expected.set(0, expectedSwipeAreaBottom, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
+
+        assertThat(bounds).isEqualTo(expected);
+
+        onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController);
+    }
+
+    private static void onSessionStartHelper(BouncerSwipeTouchHandler touchHandler,
+            TouchHandler.TouchSession touchSession,
+            NotificationShadeWindowController notificationShadeWindowController) {
+        touchHandler.onSessionStart(touchSession);
+        verify(notificationShadeWindowController).setForcePluginOpen(eq(true), any());
+        ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor =
+                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(touchSession).registerGestureListener(gestureListenerCaptor.capture());
+        verify(touchSession).registerInputListener(eventListenerCaptor.capture());
+
+        // A touch within range at the bottom of the screen should trigger listening
+        assertThat(gestureListenerCaptor.getValue()
+                .onScroll(Mockito.mock(MotionEvent.class),
+                        Mockito.mock(MotionEvent.class),
+                        1,
+                        2)).isTrue();
+    }
+
+    /**
+     * Makes sure swiping down doesn't change the expansion amount.
+     */
+    @Test
+    @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
+    public void testSwipeDown_doesNotSetExpansion() {
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+        final float percent = .15f;
+        final float distanceY = SCREEN_HEIGHT_PX * percent;
+
+        // Swiping down near the bottom of the screen where the touch initiation region is.
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX - distanceY, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX, 0);
+
+        assertThat(gestureListener.onScroll(event1, event2, 0, -distanceY)).isTrue();
+
+        verify(mScrimController, never()).expand(any());
+    }
+
+    /**
+     * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
+     */
+    @Test
+    @EnableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
+    public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion_directionFiltering() {
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+        final float percent = .15f;
+        final float distanceY = SCREEN_HEIGHT_PX * percent;
+
+        // Swiping down near the bottom of the screen where the touch initiation region is.
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX - distanceY, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX, 0);
+
+        assertThat(gestureListener.onScroll(event1, event2, 0, -distanceY)).isFalse();
+
+        verify(mScrimController, never()).expand(any());
+    }
+
+    /**
+     * Makes sure the expansion amount is proportional to (1 - scroll).
+     */
+    @Test
+    public void testSwipeUp_setsCorrectExpansionAmount() {
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+        verifyScroll(.3f, gestureListener);
+        verifyScroll(.7f, gestureListener);
+    }
+
+    /**
+     * Verifies that swiping up when the lock pattern is not secure dismissed dream and consumes
+     * the gesture.
+     */
+    @Test
+    public void testSwipeUp_keyguardNotSecure_doesNotExpand() {
+        when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(false);
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+        final float distanceY = SCREEN_HEIGHT_PX * 0.3f;
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX - distanceY, 0);
+
+        reset(mScrimController);
+
+        // Scroll gesture is consumed.
+        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
+                .isTrue();
+        // We should not expand since the keyguard is not secure
+        verify(mScrimController, never()).expand(any());
+        // Since we are swiping up, we should wake from dreams.
+        verify(mCentralSurfaces).awakenDreams();
+    }
+
+    /**
+     * Verifies that swiping down when the lock pattern is not secure does not dismiss the dream.
+     */
+    @Test
+    public void testSwipeDown_keyguardNotSecure_doesNotExpand() {
+        when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(false);
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+        final float distanceY = SCREEN_HEIGHT_PX * 0.3f;
+        // Swiping down near the bottom of the screen where the touch initiation region is.
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX - distanceY, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX, 0);
+
+        reset(mScrimController);
+
+        // Scroll gesture is not consumed.
+        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
+                .isTrue();
+        // We should not expand since the keyguard is not secure
+        verify(mScrimController, never()).expand(any());
+        // Since we are swiping down, we should not dismiss the dream.
+        verify(mCentralSurfaces, never()).awakenDreams();
+    }
+
+    private void verifyScroll(float percent,
+            OnGestureListener gestureListener) {
+        final float distanceY = SCREEN_HEIGHT_PX * percent;
+
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX - distanceY, 0);
+
+        reset(mScrimController);
+        assertThat(gestureListener.onScroll(event1, event2, 0,
+                distanceY))
+                .isTrue();
+
+        // Ensure only called once
+        verify(mScrimController).expand(any());
+
+        final float expansion = 1 - percent;
+
+        // Ensure correct expansion passed in.
+        ShadeExpansionChangeEvent event =
+                new ShadeExpansionChangeEvent(
+                        expansion, /* expanded= */ false, /* tracking= */ true);
+        verify(mScrimController).expand(event);
+    }
+
+    /**
+     * Tests that ending an upward swipe before the set threshold leads to bouncer collapsing down.
+     */
+    @Test
+    public void testSwipeUpPositionBelowThreshold_collapsesBouncer() {
+        final float swipeUpPercentage = .3f;
+        final float expansion = 1 - swipeUpPercentage;
+        // The upward velocity is ignored.
+        final float velocityY = -1;
+        swipeToPosition(swipeUpPercentage, velocityY);
+
+        verify(mValueAnimatorCreator).create(eq(expansion),
+                eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
+        verify(mValueAnimator, never()).addListener(any());
+
+        verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
+                eq(SCREEN_HEIGHT_PX * expansion),
+                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
+                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
+        verify(mValueAnimator).start();
+        verify(mUiEventLogger, never()).log(any());
+    }
+
+    /**
+     * Tests that ending an upward swipe above the set threshold will continue the expansion.
+     */
+    @Test
+    public void testSwipeUpPositionAboveThreshold_expandsBouncer() {
+        final float swipeUpPercentage = .7f;
+        final float expansion = 1 - swipeUpPercentage;
+        // The downward velocity is ignored.
+        final float velocityY = 1;
+        swipeToPosition(swipeUpPercentage, velocityY);
+
+        verify(mValueAnimatorCreator).create(eq(expansion),
+                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
+
+        ArgumentCaptor<AnimatorListenerAdapter> endAnimationListenerCaptor =
+                ArgumentCaptor.forClass(AnimatorListenerAdapter.class);
+        verify(mValueAnimator).addListener(endAnimationListenerCaptor.capture());
+        AnimatorListenerAdapter endAnimationListener = endAnimationListenerCaptor.getValue();
+
+        verify(mFlingAnimationUtils).apply(eq(mValueAnimator), eq(SCREEN_HEIGHT_PX * expansion),
+                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
+                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
+        verify(mValueAnimator).start();
+        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_SWIPED);
+
+        endAnimationListener.onAnimationEnd(mValueAnimator);
+        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
+    }
+
+    /**
+     * Tests that swiping up with a speed above the set threshold will continue the expansion.
+     */
+    @Test
+    public void testSwipeUpVelocityAboveMin_expandsBouncer() {
+        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);
+
+        // The ending position below the set threshold is ignored.
+        final float swipeUpPercentage = .3f;
+        final float expansion = 1 - swipeUpPercentage;
+        final float velocityY = -1;
+        swipeToPosition(swipeUpPercentage, velocityY);
+
+        verify(mValueAnimatorCreator).create(eq(expansion),
+                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
+
+        ArgumentCaptor<AnimatorListenerAdapter> endAnimationListenerCaptor =
+                ArgumentCaptor.forClass(AnimatorListenerAdapter.class);
+        verify(mValueAnimator).addListener(endAnimationListenerCaptor.capture());
+        AnimatorListenerAdapter endAnimationListener = endAnimationListenerCaptor.getValue();
+
+        verify(mFlingAnimationUtils).apply(eq(mValueAnimator), eq(SCREEN_HEIGHT_PX * expansion),
+                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
+                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
+        verify(mValueAnimator).start();
+        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_SWIPED);
+
+        endAnimationListener.onAnimationEnd(mValueAnimator);
+        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
+    }
+
+    @Test
+    public void testTouchSessionOnRemovedCalledTwice() {
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<TouchHandler.TouchSession.Callback> onRemovedCallbackCaptor =
+                ArgumentCaptor.forClass(TouchHandler.TouchSession.Callback.class);
+        verify(mTouchSession).registerCallback(onRemovedCallbackCaptor.capture());
+        onRemovedCallbackCaptor.getValue().onRemoved();
+        onRemovedCallbackCaptor.getValue().onRemoved();
+    }
+
+    private void swipeToPosition(float percent, float velocityY) {
+        Mockito.clearInvocations(mTouchSession);
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+        ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
+                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+        verify(mTouchSession).registerInputListener(inputEventListenerCaptor.capture());
+
+        when(mVelocityTracker.getYVelocity()).thenReturn(velocityY);
+
+        final float distanceY = SCREEN_HEIGHT_PX * percent;
+
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+                0, SCREEN_HEIGHT_PX - distanceY, 0);
+
+        assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0,
+                distanceY))
+                .isTrue();
+
+        final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
+                0, 0, 0);
+
+        inputEventListenerCaptor.getValue().onInputEvent(upEvent);
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java
new file mode 100644
index 0000000..11a4241
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.ambient.touch;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+
+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.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ShadeTouchHandlerTest extends SysuiTestCase {
+    @Mock
+    CentralSurfaces mCentralSurfaces;
+
+    @Mock
+    TouchHandler.TouchSession mTouchSession;
+
+    ShadeTouchHandler mTouchHandler;
+
+    @Captor
+    ArgumentCaptor<GestureDetector.OnGestureListener> mGestureListenerCaptor;
+    @Captor
+    ArgumentCaptor<InputChannelCompat.InputEventListener> mInputListenerCaptor;
+
+    private static final int TOUCH_HEIGHT = 20;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        mTouchHandler = new ShadeTouchHandler(Optional.of(mCentralSurfaces), TOUCH_HEIGHT);
+    }
+
+    // Verifies that a swipe down in the gesture region is captured by the shade touch handler.
+    @Test
+    public void testSwipeDown_captured() {
+        final boolean captured = swipe(Direction.DOWN);
+
+        assertThat(captured).isTrue();
+    }
+
+    // Verifies that a swipe in the upward direction is not catpured.
+    @Test
+    public void testSwipeUp_notCaptured() {
+        final boolean captured = swipe(Direction.UP);
+
+        // Motion events not captured as the swipe is going in the wrong direction.
+        assertThat(captured).isFalse();
+    }
+
+    // Verifies that a swipe down forwards captured touches to the shade window for handling.
+    @Test
+    public void testSwipeDown_sentToShadeWindow() {
+        swipe(Direction.DOWN);
+
+        // Both motion events are sent for the shade window to process.
+        verify(mCentralSurfaces, times(2)).handleExternalShadeWindowTouch(any());
+    }
+
+    // Verifies that a swipe down is not forwarded to the shade window.
+    @Test
+    public void testSwipeUp_touchesNotSent() {
+        swipe(Direction.UP);
+
+        // Motion events are not sent for the shade window to process as the swipe is going in the
+        // wrong direction.
+        verify(mCentralSurfaces, never()).handleExternalShadeWindowTouch(any());
+    }
+
+    /**
+     * Simulates a swipe in the given direction and returns true if the touch was intercepted by the
+     * touch handler's gesture listener.
+     * <p>
+     * Swipe down starts from a Y coordinate of 0 and goes downward. Swipe up starts from the edge
+     * of the gesture region, {@link #TOUCH_HEIGHT}, and goes upward to 0.
+     */
+    private boolean swipe(Direction direction) {
+        Mockito.clearInvocations(mTouchSession);
+        mTouchHandler.onSessionStart(mTouchSession);
+
+        verify(mTouchSession).registerGestureListener(mGestureListenerCaptor.capture());
+        verify(mTouchSession).registerInputListener(mInputListenerCaptor.capture());
+
+        final float startY = direction == Direction.UP ? TOUCH_HEIGHT : 0;
+        final float endY = direction == Direction.UP ? 0 : TOUCH_HEIGHT;
+
+        // Send touches to the input and gesture listener.
+        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, startY, 0);
+        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, endY, 0);
+        mInputListenerCaptor.getValue().onInputEvent(event1);
+        mInputListenerCaptor.getValue().onInputEvent(event2);
+        final boolean captured = mGestureListenerCaptor.getValue().onScroll(event1, event2, 0,
+                startY - endY);
+
+        return captured;
+    }
+
+    private enum Direction {
+        DOWN, UP,
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimControllerTest.java
new file mode 100644
index 0000000..099771c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimControllerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.os.PowerManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+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)
[email protected]
+public class BouncerlessScrimControllerTest extends SysuiTestCase {
+    @Mock
+    BouncerlessScrimController.Callback mCallback;
+
+    @Mock
+    PowerManager mPowerManager;
+
+    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testWakeupOnSwipeOpen() {
+        final BouncerlessScrimController scrimController =
+                new BouncerlessScrimController(mExecutor, mPowerManager);
+        scrimController.addCallback(mCallback);
+        scrimController.expand(new ShadeExpansionChangeEvent(.5f, true, false));
+        mExecutor.runAllReady();
+        verify(mPowerManager).wakeUp(anyLong(), eq(PowerManager.WAKE_REASON_GESTURE), any());
+        verify(mCallback).onWakeup();
+    }
+
+    @Test
+    public void testExpansionPropagation() {
+        final BouncerlessScrimController scrimController =
+                new BouncerlessScrimController(mExecutor, mPowerManager);
+        scrimController.addCallback(mCallback);
+        final ShadeExpansionChangeEvent expansionEvent =
+                new ShadeExpansionChangeEvent(0.5f, false, false);
+        scrimController.expand(expansionEvent);
+        mExecutor.runAllReady();
+        verify(mCallback).onExpansion(eq(expansionEvent));
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/ScrimManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/ScrimManagerTest.java
new file mode 100644
index 0000000..82de50c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/scrim/ScrimManagerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+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;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
[email protected]
+public class ScrimManagerTest extends SysuiTestCase {
+    @Mock
+    ScrimController mBouncerlessScrimController;
+
+    @Mock
+    ScrimController mBouncerScrimController;
+
+    @Mock
+    KeyguardStateController mKeyguardStateController;
+
+    @Mock
+    ScrimManager.Callback mCallback;
+
+    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testControllerSelection() {
+        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
+        ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
+                ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
+        final ScrimManager manager = new ScrimManager(mExecutor, mBouncerScrimController,
+                mBouncerlessScrimController, mKeyguardStateController);
+        verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
+
+        assertThat(manager.getCurrentController()).isEqualTo(mBouncerScrimController);
+        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
+        callbackCaptor.getValue().onKeyguardShowingChanged();
+        mExecutor.runAllReady();
+        assertThat(manager.getCurrentController()).isEqualTo(mBouncerlessScrimController);
+    }
+
+    @Test
+    public void testCallback() {
+        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
+        ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
+                ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
+        final ScrimManager manager = new ScrimManager(mExecutor, mBouncerScrimController,
+                mBouncerlessScrimController, mKeyguardStateController);
+        verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
+
+        manager.addCallback(mCallback);
+        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
+        callbackCaptor.getValue().onKeyguardShowingChanged();
+        mExecutor.runAllReady();
+        verify(mCallback).onScrimControllerChanged(eq(mBouncerlessScrimController));
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index caf9219..1cd9d76 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -32,7 +32,6 @@
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.testKosmos
@@ -86,7 +85,6 @@
             AuthenticationRepositoryImpl(
                 applicationScope = testScope.backgroundScope,
                 backgroundDispatcher = kosmos.testDispatcher,
-                flags = kosmos.sceneContainerFlags,
                 clock = clock,
                 getSecurityMode = getSecurityMode,
                 userRepository = userRepository,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index cb8cebf..81878aa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -179,10 +179,14 @@
                 setAutoConfirmFeatureEnabled(true)
             }
             assertThat(isAutoConfirmEnabled).isTrue()
-            val shorterPin =
-                FakeAuthenticationRepository.DEFAULT_PIN.toMutableList().apply { removeLast() }
+            val defaultPin = FakeAuthenticationRepository.DEFAULT_PIN.toMutableList()
 
-            assertSkipped(underTest.authenticate(shorterPin, tryAutoConfirm = true))
+            assertSkipped(
+                underTest.authenticate(
+                    defaultPin.subList(0, defaultPin.size - 1),
+                    tryAutoConfirm = true
+                )
+            )
             assertThat(underTest.lockoutEndTimestamp).isNull()
             assertThat(kosmos.fakeAuthenticationRepository.lockoutStartedReportCount).isEqualTo(0)
         }
@@ -201,7 +205,6 @@
 
             assertFailed(
                 underTest.authenticate(wrongPin, tryAutoConfirm = true),
-                assertNoResultEvents = true,
             )
         }
 
@@ -219,7 +222,6 @@
 
             assertFailed(
                 underTest.authenticate(longerPin, tryAutoConfirm = true),
-                assertNoResultEvents = true,
             )
         }
 
@@ -547,14 +549,9 @@
 
     private fun assertFailed(
         authenticationResult: AuthenticationResult,
-        assertNoResultEvents: Boolean = false,
     ) {
         assertThat(authenticationResult).isEqualTo(AuthenticationResult.FAILED)
-        if (assertNoResultEvents) {
-            assertThat(onAuthenticationResult).isNull()
-        } else {
-            assertThat(onAuthenticationResult).isFalse()
-        }
+        assertThat(onAuthenticationResult).isFalse()
     }
 
     private fun assertSkipped(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 289896e01..f4ad764 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -145,8 +145,6 @@
     @Mock
     private UdfpsController mUdfpsController;
     @Mock
-    private SideFpsController mSideFpsController;
-    @Mock
     private DisplayManager mDisplayManager;
     @Mock
     private WakefulnessLifecycle mWakefulnessLifecycle;
@@ -1064,14 +1062,12 @@
         TestableAuthController(Context context) {
             super(context, null /* applicationCoroutineScope */,
                     mExecution, mCommandQueue, mActivityTaskManager, mWindowManager,
-                    mFingerprintManager, mFaceManager, () -> mUdfpsController,
-                    () -> mSideFpsController, mDisplayManager, mWakefulnessLifecycle,
-                    mPanelInteractionDetector, mUserManager, mLockPatternUtils, () -> mUdfpsLogger,
-                    () -> mLogContextInteractor,
-                    () -> mBiometricPromptCredentialInteractor,
-                    () -> mPromptSelectionInteractor, () -> mCredentialViewModel,
-                    () -> mPromptViewModel, mInteractionJankMonitor, mHandler, mBackgroundExecutor,
-                    mUdfpsUtils, mVibratorHelper);
+                    mFingerprintManager, mFaceManager, () -> mUdfpsController, mDisplayManager,
+                    mWakefulnessLifecycle, mPanelInteractionDetector, mUserManager,
+                    mLockPatternUtils, () -> mUdfpsLogger, () -> mLogContextInteractor,
+                    () -> mBiometricPromptCredentialInteractor, () -> mPromptSelectionInteractor,
+                    () -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor,
+                    mHandler, mBackgroundExecutor, mUdfpsUtils, mVibratorHelper);
         }
 
         @Override
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
deleted file mode 100644
index 07e9815..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ /dev/null
@@ -1,898 +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.biometrics
-
-import android.animation.Animator
-import android.app.ActivityManager
-import android.app.ActivityTaskManager
-import android.content.ComponentName
-import android.graphics.Insets
-import android.graphics.Rect
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricRequestConstants.REASON_UNKNOWN
-import android.hardware.biometrics.SensorLocationInternal
-import android.hardware.biometrics.SensorProperties
-import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManagerGlobal
-import android.hardware.fingerprint.FingerprintManager
-import android.hardware.fingerprint.FingerprintSensorProperties
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
-import android.hardware.fingerprint.ISidefpsController
-import android.os.Handler
-import android.testing.TestableLooper
-import android.view.Display
-import android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS
-import android.view.DisplayInfo
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.View
-import android.view.ViewPropertyAnimator
-import android.view.WindowInsets
-import android.view.WindowManager
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
-import android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
-import android.view.WindowMetrics
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.airbnb.lottie.LottieAnimationView
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.SysuiTestableContext
-import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
-import com.android.systemui.display.data.repository.FakeDisplayRepository
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.res.R
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestCoroutineScope
-import kotlinx.coroutines.test.TestScope
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyFloat
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.anyLong
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenEver
-import org.mockito.junit.MockitoJUnit
-
-private const val DISPLAY_ID = 2
-private const val SENSOR_ID = 1
-
-private const val REAR_DISPLAY_MODE_DEVICE_STATE = 3
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
[email protected]
-class SideFpsControllerTest : SysuiTestCase() {
-
-    @JvmField @Rule var rule = MockitoJUnit.rule()
-
-    @Mock lateinit var layoutInflater: LayoutInflater
-    @Mock lateinit var fingerprintManager: FingerprintManager
-    @Mock lateinit var windowManager: WindowManager
-    @Mock lateinit var activityTaskManager: ActivityTaskManager
-    @Mock lateinit var sideFpsView: View
-    @Mock lateinit var displayManager: DisplayManager
-    @Mock lateinit var handler: Handler
-    @Mock lateinit var dumpManager: DumpManager
-    @Mock lateinit var fpsUnlockTracker: FpsUnlockTracker
-    @Captor lateinit var overlayCaptor: ArgumentCaptor<View>
-    @Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
-
-    private lateinit var displayRepository: FakeDisplayRepository
-    private lateinit var displayStateRepository: FakeDisplayStateRepository
-    private lateinit var keyguardBouncerRepository: FakeKeyguardBouncerRepository
-    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
-    private lateinit var displayStateInteractor: DisplayStateInteractor
-
-    private val executor = FakeExecutor(FakeSystemClock())
-    private val testScope = TestScope(StandardTestDispatcher())
-
-    private lateinit var overlayController: ISidefpsController
-    private lateinit var sideFpsController: SideFpsController
-
-    enum class DeviceConfig {
-        X_ALIGNED,
-        Y_ALIGNED,
-    }
-
-    private lateinit var deviceConfig: DeviceConfig
-    private lateinit var indicatorBounds: Rect
-    private lateinit var displayBounds: Rect
-    private lateinit var sensorLocation: SensorLocationInternal
-    private var displayWidth: Int = 0
-    private var displayHeight: Int = 0
-    private var boundsWidth: Int = 0
-    private var boundsHeight: Int = 0
-
-    @Before
-    fun setup() {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        displayRepository = FakeDisplayRepository()
-        displayStateRepository = FakeDisplayStateRepository()
-        keyguardBouncerRepository = FakeKeyguardBouncerRepository()
-        alternateBouncerInteractor =
-            AlternateBouncerInteractor(
-                mock(StatusBarStateController::class.java),
-                mock(KeyguardStateController::class.java),
-                keyguardBouncerRepository,
-                FakeFingerprintPropertyRepository(),
-                FakeBiometricSettingsRepository(),
-                FakeSystemClock(),
-                mock(KeyguardUpdateMonitor::class.java),
-                { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
-                { mock(KeyguardInteractor::class.java) },
-                { mock(KeyguardTransitionInteractor::class.java) },
-                testScope.backgroundScope,
-            )
-        displayStateInteractor =
-            DisplayStateInteractorImpl(
-                testScope.backgroundScope,
-                context,
-                executor,
-                displayStateRepository,
-                displayRepository,
-            )
-
-        context.addMockSystemService(DisplayManager::class.java, displayManager)
-        context.addMockSystemService(WindowManager::class.java, windowManager)
-
-        whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView)
-        whenEver(sideFpsView.requireViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
-            .thenReturn(mock(LottieAnimationView::class.java))
-        with(mock(ViewPropertyAnimator::class.java)) {
-            whenEver(sideFpsView.animate()).thenReturn(this)
-            whenEver(alpha(anyFloat())).thenReturn(this)
-            whenEver(setStartDelay(anyLong())).thenReturn(this)
-            whenEver(setDuration(anyLong())).thenReturn(this)
-            whenEver(setListener(any())).thenAnswer {
-                (it.arguments[0] as Animator.AnimatorListener).onAnimationEnd(
-                    mock(Animator::class.java)
-                )
-                this
-            }
-        }
-    }
-
-    private fun testWithDisplay(
-        deviceConfig: DeviceConfig = DeviceConfig.X_ALIGNED,
-        isReverseDefaultRotation: Boolean = false,
-        initInfo: DisplayInfo.() -> Unit = {},
-        windowInsets: WindowInsets = insetsForSmallNavbar(),
-        inRearDisplayMode: Boolean = false,
-        block: () -> Unit
-    ) {
-        this.deviceConfig = deviceConfig
-
-        when (deviceConfig) {
-            DeviceConfig.X_ALIGNED -> {
-                displayWidth = 3000
-                displayHeight = 1500
-                sensorLocation = SensorLocationInternal("", 2500, 0, 0)
-                boundsWidth = 200
-                boundsHeight = 100
-            }
-            DeviceConfig.Y_ALIGNED -> {
-                displayWidth = 2500
-                displayHeight = 2000
-                sensorLocation = SensorLocationInternal("", 0, 300, 0)
-                boundsWidth = 100
-                boundsHeight = 200
-            }
-        }
-
-        indicatorBounds = Rect(0, 0, boundsWidth, boundsHeight)
-        displayBounds = Rect(0, 0, displayWidth, displayHeight)
-        var locations = listOf(sensorLocation)
-
-        whenEver(fingerprintManager.sensorPropertiesInternal)
-            .thenReturn(
-                listOf(
-                    FingerprintSensorPropertiesInternal(
-                        SENSOR_ID,
-                        SensorProperties.STRENGTH_STRONG,
-                        5 /* maxEnrollmentsPerUser */,
-                        listOf() /* componentInfo */,
-                        FingerprintSensorProperties.TYPE_POWER_BUTTON,
-                        true /* halControlsIllumination */,
-                        true /* resetLockoutRequiresHardwareAuthToken */,
-                        locations
-                    )
-                )
-            )
-
-        val displayInfo = DisplayInfo()
-        displayInfo.initInfo()
-
-        val dmGlobal = mock(DisplayManagerGlobal::class.java)
-        val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS)
-
-        whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
-        whenEver(windowManager.defaultDisplay).thenReturn(display)
-        whenEver(windowManager.maximumWindowMetrics)
-            .thenReturn(WindowMetrics(displayBounds, WindowInsets.CONSUMED))
-        whenEver(windowManager.currentWindowMetrics)
-            .thenReturn(WindowMetrics(displayBounds, windowInsets))
-
-        val sideFpsControllerContext = context.createDisplayContext(display) as SysuiTestableContext
-        sideFpsControllerContext.orCreateTestableResources.addOverride(
-            com.android.internal.R.bool.config_reverseDefaultRotation,
-            isReverseDefaultRotation
-        )
-
-        val rearDisplayDeviceStates =
-            if (inRearDisplayMode) intArrayOf(REAR_DISPLAY_MODE_DEVICE_STATE) else intArrayOf()
-        sideFpsControllerContext.orCreateTestableResources.addOverride(
-            com.android.internal.R.array.config_rearDisplayDeviceStates,
-            rearDisplayDeviceStates
-        )
-
-        sideFpsController =
-            SideFpsController(
-                sideFpsControllerContext,
-                layoutInflater,
-                fingerprintManager,
-                windowManager,
-                activityTaskManager,
-                displayManager,
-                displayStateInteractor,
-                executor,
-                handler,
-                alternateBouncerInteractor,
-                TestCoroutineScope(),
-                dumpManager,
-                fpsUnlockTracker
-            )
-        displayStateRepository.setIsInRearDisplayMode(inRearDisplayMode)
-
-        overlayController =
-            ArgumentCaptor.forClass(ISidefpsController::class.java)
-                .apply { verify(fingerprintManager).setSidefpsController(capture()) }
-                .value
-
-        block()
-    }
-
-    @Test
-    fun testSubscribesToOrientationChangesWhenShowingOverlay() = testWithDisplay {
-        overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-        executor.runAllReady()
-
-        verify(displayManager).registerDisplayListener(any(), eq(handler), anyLong())
-
-        overlayController.hide(SENSOR_ID)
-        executor.runAllReady()
-        verify(displayManager).unregisterDisplayListener(any())
-    }
-
-    @Test
-    fun testShowOverlayReasonWhenDisplayChanged() = testWithDisplay {
-        sideFpsController.show(SideFpsUiRequestSource.AUTO_SHOW, REASON_AUTH_KEYGUARD)
-        executor.runAllReady()
-        sideFpsController.orientationListener.onDisplayChanged(1 /* displayId */)
-        executor.runAllReady()
-
-        assertThat(sideFpsController.orientationReasonListener.reason)
-            .isEqualTo(REASON_AUTH_KEYGUARD)
-    }
-
-    @Test
-    fun testShowsAndHides() = testWithDisplay {
-        overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-        executor.runAllReady()
-
-        verify(windowManager).addView(overlayCaptor.capture(), any())
-
-        reset(windowManager)
-        overlayController.hide(SENSOR_ID)
-        executor.runAllReady()
-
-        verify(windowManager, never()).addView(any(), any())
-        verify(windowManager).removeView(eq(overlayCaptor.value))
-    }
-
-    @Test
-    fun testShowsOnce() = testWithDisplay {
-        repeat(5) {
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-        }
-
-        verify(windowManager).addView(any(), any())
-        verify(windowManager, never()).removeView(any())
-    }
-
-    @Test
-    fun testHidesOnce() = testWithDisplay {
-        overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-        executor.runAllReady()
-
-        repeat(5) {
-            overlayController.hide(SENSOR_ID)
-            executor.runAllReady()
-        }
-
-        verify(windowManager).addView(any(), any())
-        verify(windowManager).removeView(any())
-    }
-
-    @Test fun testIgnoredForKeyguard() = testWithDisplay { testIgnoredFor(REASON_AUTH_KEYGUARD) }
-
-    @Test
-    fun testShowsForMostSettings() = testWithDisplay {
-        whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask()))
-        testIgnoredFor(REASON_AUTH_SETTINGS, ignored = false)
-    }
-
-    @Test
-    fun testIgnoredForVerySpecificSettings() = testWithDisplay {
-        whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask()))
-        testIgnoredFor(REASON_AUTH_SETTINGS)
-    }
-
-    private fun testIgnoredFor(reason: Int, ignored: Boolean = true) {
-        overlayController.show(SENSOR_ID, reason)
-        executor.runAllReady()
-
-        verify(windowManager, if (ignored) never() else times(1)).addView(any(), any())
-    }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_0 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_90 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_180 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_180 },
-            windowInsets = insetsForSmallNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_180 },
-            windowInsets = insetsForLargeNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_270 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_0 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_90 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_90 },
-            windowInsets = insetsForSmallNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_90 },
-            windowInsets = insetsForLargeNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_180 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_270 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_0 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_90 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_180 },
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_270 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_270 },
-            windowInsets = insetsForSmallNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_270 },
-            windowInsets = insetsForLargeNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_0 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_90 },
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_180 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_180 },
-            windowInsets = insetsForSmallNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_180 },
-            windowInsets = insetsForLargeNavbar()
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
-        }
-
-    @Test
-    fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_270 }
-        ) {
-            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
-        }
-
-    @Test
-    fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_0 },
-            inRearDisplayMode = true,
-        ) {
-            verifySfpsIndicator_notAdded_InRearDisplayMode()
-        }
-
-    @Test
-    fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_90() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_90 },
-            inRearDisplayMode = true,
-        ) {
-            verifySfpsIndicator_notAdded_InRearDisplayMode()
-        }
-
-    @Test
-    fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_180() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_180 },
-            inRearDisplayMode = true,
-        ) {
-            verifySfpsIndicator_notAdded_InRearDisplayMode()
-        }
-
-    @Test
-    fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_270 },
-            inRearDisplayMode = true,
-        ) {
-            verifySfpsIndicator_notAdded_InRearDisplayMode()
-        }
-
-    private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
-        sideFpsController.overlayOffsets = sensorLocation
-    }
-
-    private fun verifySfpsIndicator_notAdded_InRearDisplayMode() {
-        sideFpsController.overlayOffsets = sensorLocation
-        overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-        executor.runAllReady()
-
-        verify(windowManager, never()).addView(any(), any())
-    }
-
-    fun alternateBouncerVisibility_showAndHideSideFpsUI() = testWithDisplay {
-        // WHEN alternate bouncer is visible
-        keyguardBouncerRepository.setAlternateVisible(true)
-        executor.runAllReady()
-
-        // THEN side fps shows UI
-        verify(windowManager).addView(any(), any())
-        verify(windowManager, never()).removeView(any())
-
-        // WHEN alternate bouncer is no longer visible
-        keyguardBouncerRepository.setAlternateVisible(false)
-        executor.runAllReady()
-
-        // THEN side fps UI is hidden
-        verify(windowManager).removeView(any())
-    }
-
-    /**
-     * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
-     * and uses RotateUtils.rotateBounds to map to the correct indicator location given the device
-     * rotation. Assuming RotationUtils.rotateBounds works correctly, tests for indicator placement
-     * in other rotations have been omitted.
-     */
-    @Test
-    fun verifiesIndicatorPlacementForXAlignedSensor_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_0 }
-        ) {
-            sideFpsController.overlayOffsets = sensorLocation
-
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-            assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
-            assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
-        }
-
-    /**
-     * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
-     * in reverse default rotation. It then uses RotateUtils.rotateBounds to map to the correct
-     * indicator location given the device rotation. Assuming RotationUtils.rotateBounds works
-     * correctly, tests for indicator placement in other rotations have been omitted.
-     */
-    @Test
-    fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.X_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_270 }
-        ) {
-            sideFpsController.overlayOffsets = sensorLocation
-
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-            assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
-            assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
-        }
-
-    /**
-     * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
-     * and uses RotateUtils.rotateBounds to map to the correct indicator location given the device
-     * rotation. Assuming RotationUtils.rotateBounds works correctly, tests for indicator placement
-     * in other rotations have been omitted.
-     */
-    @Test
-    fun verifiesIndicatorPlacementForYAlignedSensor_0() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = false,
-            { rotation = Surface.ROTATION_0 }
-        ) {
-            sideFpsController.overlayOffsets = sensorLocation
-
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-            assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
-            assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
-        }
-
-    /**
-     * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
-     * in reverse default rotation. It then uses RotateUtils.rotateBounds to map to the correct
-     * indicator location given the device rotation. Assuming RotationUtils.rotateBounds works
-     * correctly, tests for indicator placement in other rotations have been omitted.
-     */
-    @Test
-    fun verifiesIndicatorPlacementForYAlignedSensor_InReverseDefaultRotation_270() =
-        testWithDisplay(
-            deviceConfig = DeviceConfig.Y_ALIGNED,
-            isReverseDefaultRotation = true,
-            { rotation = Surface.ROTATION_270 }
-        ) {
-            sideFpsController.overlayOffsets = sensorLocation
-
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-            assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
-            assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
-        }
-
-    @Test
-    fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay {
-        // By default all those tests assume the side fps sensor is available.
-        assertThat(fingerprintManager.hasSideFpsSensor()).isTrue()
-    }
-
-    @Test
-    fun hasSideFpsSensor_withoutSensorProps_returnsFalse() {
-        whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn(null)
-
-        assertThat(fingerprintManager.hasSideFpsSensor()).isFalse()
-    }
-
-    @Test
-    fun testLayoutParams_isKeyguardDialogType() =
-        testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
-            sideFpsController.overlayOffsets = sensorLocation
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
-            val lpType = overlayViewParamsCaptor.value.type
-
-            assertThat((lpType and TYPE_KEYGUARD_DIALOG) != 0).isTrue()
-        }
-
-    @Test
-    fun testLayoutParams_hasNoMoveAnimationWindowFlag() =
-        testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
-            sideFpsController.overlayOffsets = sensorLocation
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
-            val lpFlags = overlayViewParamsCaptor.value.privateFlags
-
-            assertThat((lpFlags and PRIVATE_FLAG_NO_MOVE_ANIMATION) != 0).isTrue()
-        }
-
-    @Test
-    fun testLayoutParams_hasTrustedOverlayWindowFlag() =
-        testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
-            sideFpsController.overlayOffsets = sensorLocation
-            sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-            overlayController.show(SENSOR_ID, REASON_UNKNOWN)
-            executor.runAllReady()
-
-            verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
-            val lpFlags = overlayViewParamsCaptor.value.privateFlags
-
-            assertThat((lpFlags and PRIVATE_FLAG_TRUSTED_OVERLAY) != 0).isTrue()
-        }
-
-    @Test
-    fun primaryBouncerRequestAnimatesAlphaIn() = testWithDisplay {
-        sideFpsController.show(SideFpsUiRequestSource.PRIMARY_BOUNCER, REASON_AUTH_KEYGUARD)
-        executor.runAllReady()
-        verify(sideFpsView).animate()
-    }
-
-    @Test
-    fun alternateBouncerRequestsDoesNotAnimateAlphaIn() = testWithDisplay {
-        sideFpsController.show(SideFpsUiRequestSource.ALTERNATE_BOUNCER, REASON_AUTH_KEYGUARD)
-        executor.runAllReady()
-        verify(sideFpsView, never()).animate()
-    }
-
-    @Test
-    fun autoShowRequestsDoesNotAnimateAlphaIn() = testWithDisplay {
-        sideFpsController.show(SideFpsUiRequestSource.AUTO_SHOW, REASON_AUTH_KEYGUARD)
-        executor.runAllReady()
-        verify(sideFpsView, never()).animate()
-    }
-}
-
-private fun insetsForSmallNavbar() = insetsWithBottom(60)
-
-private fun insetsForLargeNavbar() = insetsWithBottom(100)
-
-private fun insetsWithBottom(bottom: Int) =
-    WindowInsets.Builder()
-        .setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom))
-        .build()
-
-private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling")
-
-private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings")
-
-private fun settingsTask(cls: String) =
-    ActivityManager.RunningTaskInfo().apply {
-        topActivity = ComponentName.createRelative("com.android.settings", cls)
-    }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 4950b96..60b48f2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -537,4 +537,65 @@
                 assertThat(lp.height).isEqualTo(overlayParams.sensorBounds.height())
             }
         }
+
+    @Test
+    fun addViewPending_layoutIsNotUpdated() =
+        testScope.runTest {
+            withReasonSuspend(REASON_AUTH_KEYGUARD) {
+                mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE)
+                mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+
+                // GIVEN going to sleep
+                keyguardTransitionRepository.sendTransitionSteps(
+                    from = KeyguardState.OFF,
+                    to = KeyguardState.GONE,
+                    testScope = this,
+                )
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.STARTING_TO_SLEEP,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
+                )
+                runCurrent()
+
+                // WHEN a request comes to show the view
+                controllerOverlay.show(udfpsController, overlayParams)
+                runCurrent()
+
+                // THEN the view does not get added immediately
+                verify(windowManager, never()).addView(any(), any())
+
+                // WHEN updateOverlayParams gets called when the view is pending to be added
+                controllerOverlay.updateOverlayParams(overlayParams)
+
+                // THEN the view layout is never updated
+                verify(windowManager, never()).updateViewLayout(any(), any())
+
+                // CLEANUP we hide to end the job that listens for the finishedGoingToSleep signal
+                controllerOverlay.hide()
+            }
+        }
+
+    @Test
+    fun updateOverlayParams_viewLayoutUpdated() =
+        testScope.runTest {
+            withReasonSuspend(REASON_AUTH_KEYGUARD) {
+                mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE)
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.AWAKE,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
+                )
+                runCurrent()
+                controllerOverlay.show(udfpsController, overlayParams)
+                runCurrent()
+                verify(windowManager).addView(any(), any())
+
+                // WHEN updateOverlayParams gets called
+                controllerOverlay.updateOverlayParams(overlayParams)
+
+                // THEN the view layout is updated
+                verify(windowManager).updateViewLayout(any(), any())
+            }
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
index 741cde8..d850f17 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
@@ -29,10 +29,10 @@
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
@@ -56,6 +56,7 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class BouncerActionButtonInteractorTest : SysuiTestCase() {
 
     @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
@@ -75,7 +76,6 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        kosmos.fakeSceneContainerFlags.enabled = true
 
         mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index b0d03b1..361b078 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.uiEventLoggerFake
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
@@ -25,14 +26,15 @@
 import com.android.systemui.authentication.domain.interactor.authenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
+import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.data.repository.fakePowerRepository
 import com.android.systemui.res.R
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlin.time.Duration.Companion.seconds
@@ -48,11 +50,13 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class BouncerInteractorTest : SysuiTestCase() {
 
-    private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true }
+    private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val authenticationInteractor = kosmos.authenticationInteractor
+    private val uiEventLoggerFake = kosmos.uiEventLoggerFake
 
     private lateinit var underTest: BouncerInteractor
 
@@ -83,6 +87,7 @@
             // Thus, when auth method is sim, we expect to skip here.
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
+            assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0)
         }
 
     @Test
@@ -104,6 +109,8 @@
             // Wrong 6-digit pin
             assertThat(underTest.authenticate(listOf(1, 2, 3, 5, 5, 6), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.FAILED)
+            assertThat(uiEventLoggerFake[0].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_FAILURE.id)
 
             // Correct input.
             assertThat(
@@ -113,6 +120,9 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
+            assertThat(uiEventLoggerFake[1].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS.id)
+            assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2)
         }
 
     @Test
@@ -148,6 +158,8 @@
             // Wrong input.
             assertThat(underTest.authenticate("alohamora".toList()))
                 .isEqualTo(AuthenticationResult.FAILED)
+            assertThat(uiEventLoggerFake[0].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_FAILURE.id)
 
             // Too short input.
             assertThat(
@@ -165,6 +177,9 @@
             // Correct input.
             assertThat(underTest.authenticate("password".toList()))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
+            assertThat(uiEventLoggerFake[1].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS.id)
+            assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2)
         }
 
     @Test
@@ -187,6 +202,8 @@
             assertThat(wrongPattern.size)
                 .isAtLeast(kosmos.fakeAuthenticationRepository.minPatternLength)
             assertThat(underTest.authenticate(wrongPattern)).isEqualTo(AuthenticationResult.FAILED)
+            assertThat(uiEventLoggerFake[0].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_FAILURE.id)
 
             // Too short input.
             val tooShortPattern =
@@ -200,6 +217,9 @@
             // Correct input.
             assertThat(underTest.authenticate(FakeAuthenticationRepository.PATTERN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
+            assertThat(uiEventLoggerFake[1].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS.id)
+            assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2)
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
index c878e0b..004b1b4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
@@ -23,6 +23,7 @@
 import com.android.internal.widget.LockPatternUtils
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Pattern
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
@@ -88,7 +89,9 @@
         overrideResource(kg_trust_agent_disabled, "Trust agent is unavailable")
     }
 
-    suspend fun TestScope.init() {
+    suspend fun TestScope.init(
+        fingerprintAuthCurrentlyAllowed: Boolean = true,
+    ) {
         kosmos.fakeUserRepository.setSelectedUserInfo(PRIMARY_USER)
         mSetFlagsRule.enableFlags(Flags.FLAG_REVAMPED_BOUNCER_MESSAGES)
         underTest =
@@ -107,7 +110,9 @@
                 faceAuthRepository = kosmos.fakeDeviceEntryFaceAuthRepository,
                 securityModel = securityModel
             )
-        biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+        biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(
+            fingerprintAuthCurrentlyAllowed
+        )
         kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(false)
         kosmos.fakeFingerprintPropertyRepository.supportsSideFps()
         kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(true)
@@ -115,6 +120,29 @@
     }
 
     @Test
+    fun initialMessage_pin() =
+        testScope.runTest {
+            init(fingerprintAuthCurrentlyAllowed = false)
+            val bouncerMessage by collectLastValue(underTest.bouncerMessage)
+            kosmos.fakeKeyguardBouncerRepository.setLastShownSecurityMode(
+                KeyguardSecurityModel.SecurityMode.PIN
+            )
+            assertThat(bouncerMessage).isNotNull()
+            assertThat(primaryResMessage(bouncerMessage)).isEqualTo("Enter PIN")
+        }
+
+    @Test
+    fun onPrimaryAuthMethodChangeFromPinToPattern_initialMessageUpdates() =
+        testScope.runTest {
+            init(fingerprintAuthCurrentlyAllowed = false)
+            val bouncerMessage by collectLastValue(underTest.bouncerMessage)
+            whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(Pattern)
+            kosmos.fakeKeyguardBouncerRepository.setLastShownSecurityMode(Pattern)
+            assertThat(bouncerMessage).isNotNull()
+            assertThat(primaryResMessage(bouncerMessage)).isEqualTo("Draw pattern")
+        }
+
+    @Test
     fun onIncorrectSecurityInput_providesTheAppropriateValueForBouncerMessage() =
         testScope.runTest {
             init()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
index 63f6c20..546a6b7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -36,8 +36,6 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.data.repository.FakeTrustRepository
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.res.R
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.mockito.any
@@ -343,90 +341,6 @@
         assertThat(underTest.willDismissWithAction()).isFalse()
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun testSideFpsVisibility() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(true)
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun testSideFpsVisibility_notVisible() {
-        updateSideFpsVisibilityParameters(
-            isVisible = false,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun testSideFpsVisibility_sfpsNotEnabled() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = false,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun testSideFpsVisibility_fpsDetectionNotRunning() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = false,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = false,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun testSideFpsVisibility_AnimatingAway() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = true
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
     @Test
     fun delayBouncerWhenFaceAuthPossible() {
         mainHandler.setMode(FakeHandler.Mode.QUEUEING)
@@ -491,22 +405,4 @@
             verify(repository).setPrimaryShowingSoon(false)
         }
     }
-
-    private fun updateSideFpsVisibilityParameters(
-        isVisible: Boolean,
-        sfpsEnabled: Boolean,
-        fpsDetectionRunning: Boolean,
-        isUnlockingWithFpAllowed: Boolean,
-        isAnimatingAway: Boolean
-    ) {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        whenever(repository.primaryBouncerShow.value).thenReturn(isVisible)
-        resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
-        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
-            .thenReturn(fpsDetectionRunning)
-        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
-            .thenReturn(isUnlockingWithFpAllowed)
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value)
-            .thenReturn(if (isAnimatingAway) Runnable {} else null)
-    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index 3afca96..b83c0ce 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -18,6 +18,10 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.Back
+import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
+import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
@@ -30,11 +34,14 @@
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Sim
 import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.testKosmos
+import com.android.systemui.truth.containsEntriesExactly
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -53,6 +60,7 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class BouncerViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
@@ -63,7 +71,6 @@
 
     @Before
     fun setUp() {
-        kosmos.fakeSceneContainerFlags.enabled = true
         underTest = kosmos.bouncerViewModel
     }
 
@@ -193,6 +200,23 @@
             assertThat(isFoldSplitRequired).isTrue()
         }
 
+    @Test
+    fun destinationScenes() =
+        testScope.runTest {
+            val destinationScenes by collectLastValue(underTest.destinationScenes)
+            kosmos.fakeSceneDataSource.changeScene(Scenes.QuickSettings)
+            runCurrent()
+
+            kosmos.fakeSceneDataSource.changeScene(Scenes.Bouncer)
+            runCurrent()
+
+            assertThat(destinationScenes)
+                .containsEntriesExactly(
+                    Back to UserActionResult(Scenes.QuickSettings),
+                    Swipe(SwipeDirection.Down) to UserActionResult(Scenes.QuickSettings),
+                )
+        }
+
     private fun authMethodsToTest(): List<AuthenticationMethodModel> {
         return listOf(None, Pin, Password, Pattern, Sim)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index cddbd1f..1a43501 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -33,7 +33,6 @@
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.utils.os.FakeHandler
@@ -66,9 +65,7 @@
     @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
 
     lateinit var bouncerInteractor: PrimaryBouncerInteractor
-    private val mainHandler by lazy {
-        FakeHandler(Looper.getMainLooper())
-    }
+    private val mainHandler by lazy { FakeHandler(Looper.getMainLooper()) }
     val repository = FakeKeyguardBouncerRepository()
 
     lateinit var underTest: KeyguardBouncerViewModel
@@ -108,46 +105,6 @@
         job.cancel()
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun shouldUpdateSideFps_show() = runTest {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        var count = 0
-        val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
-        repository.setPrimaryShow(true)
-        // Run the tasks that are pending at this point of virtual time.
-        runCurrent()
-        assertThat(count).isEqualTo(1)
-        job.cancel()
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun shouldUpdateSideFps_hide() = runTest {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        repository.setPrimaryShow(true)
-        var count = 0
-        val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
-        repository.setPrimaryShow(false)
-        // Run the tasks that are pending at this point of virtual time.
-        runCurrent()
-        assertThat(count).isEqualTo(1)
-        job.cancel()
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Test
-    fun sideFpsShowing() = runTest {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        var sideFpsIsShowing = false
-        val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this)
-        repository.setSideFpsShowing(true)
-        // Run the tasks that are pending at this point of virtual time.
-        runCurrent()
-        assertThat(sideFpsIsShowing).isEqualTo(true)
-        job.cancel()
-    }
-
     @Test
     fun isShowing() = runTest {
         var isShowing: Boolean? = null
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index a0db482..256687b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -252,7 +252,14 @@
     @Test
     fun onAutoConfirm_whenCorrect() =
         testScope.runTest {
+            // TODO(b/332768183) remove this after the bug if fixed.
+            // Collect the flow so that it is hot, in the real application this is done by using a
+            // refreshingFlow that relies on the UI to make this flow hot.
+            val autoConfirmEnabled by
+                collectLastValue(authenticationInteractor.isAutoConfirmEnabled)
             kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true)
+
+            assertThat(autoConfirmEnabled).isTrue()
             val authResult by collectLastValue(authenticationInteractor.onAuthenticationResult)
             lockDeviceAndOpenPinBouncer()
 
@@ -264,9 +271,17 @@
     @Test
     fun onAutoConfirm_whenWrong() =
         testScope.runTest {
+            // TODO(b/332768183) remove this after the bug if fixed.
+            // Collect the flow so that it is hot, in the real application this is done by using a
+            // refreshingFlow that relies on the UI to make this flow hot.
+            val autoConfirmEnabled by
+                collectLastValue(authenticationInteractor.isAutoConfirmEnabled)
+
             val currentScene by collectLastValue(sceneInteractor.currentScene)
             val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
             kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true)
+
+            assertThat(autoConfirmEnabled).isTrue()
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit ->
@@ -374,6 +389,61 @@
             assertThat(isAnimationEnabled).isTrue()
         }
 
+    @Test
+    fun onPinButtonClicked_whenInputSameLengthAsHintedPin_ignoresClick() =
+        testScope.runTest {
+            val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
+            kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true)
+            val hintedPinLength by collectLastValue(underTest.hintedPinLength)
+            assertThat(hintedPinLength).isEqualTo(FakeAuthenticationRepository.HINTING_PIN_LENGTH)
+            lockDeviceAndOpenPinBouncer()
+
+            repeat(FakeAuthenticationRepository.HINTING_PIN_LENGTH - 1) { repetition ->
+                underTest.onPinButtonClicked(repetition + 1)
+                runCurrent()
+            }
+            kosmos.fakeAuthenticationRepository.pauseCredentialChecking()
+            // If credential checking were not paused, this would check the credentials and succeed.
+            underTest.onPinButtonClicked(FakeAuthenticationRepository.HINTING_PIN_LENGTH)
+            runCurrent()
+
+            // This one should be ignored because the user has already entered a number of digits
+            // that's equal to the length of the hinting PIN length. It should result in a PIN
+            // that's exactly the same length as the hinting PIN length.
+            underTest.onPinButtonClicked(FakeAuthenticationRepository.HINTING_PIN_LENGTH + 1)
+            runCurrent()
+
+            assertThat(pin)
+                .isEqualTo(
+                    buildList {
+                        repeat(FakeAuthenticationRepository.HINTING_PIN_LENGTH) { index ->
+                            add(index + 1)
+                        }
+                    }
+                )
+
+            kosmos.fakeAuthenticationRepository.unpauseCredentialChecking()
+            runCurrent()
+            assertThat(pin).isEmpty()
+        }
+
+    @Test
+    fun onPinButtonClicked_whenPinNotHinted_doesNotIgnoreClick() =
+        testScope.runTest {
+            val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
+            kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(false)
+            val hintedPinLength by collectLastValue(underTest.hintedPinLength)
+            assertThat(hintedPinLength).isNull()
+            lockDeviceAndOpenPinBouncer()
+
+            repeat(FakeAuthenticationRepository.HINTING_PIN_LENGTH + 1) { repetition ->
+                underTest.onPinButtonClicked(repetition + 1)
+                runCurrent()
+            }
+
+            assertThat(pin).hasSize(FakeAuthenticationRepository.HINTING_PIN_LENGTH + 1)
+        }
+
     private fun TestScope.switchToScene(toScene: SceneKey) {
         val currentScene by collectLastValue(sceneInteractor.currentScene)
         val bouncerHidden = currentScene == Scenes.Bouncer && toScene != Scenes.Bouncer
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalBackupRestoreStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalBackupRestoreStartableTest.kt
new file mode 100644
index 0000000..722eb2b
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalBackupRestoreStartableTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+import android.content.Intent
+import android.content.mockedContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.FakeBroadcastDispatcher
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.widgets.CommunalWidgetModule
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.log.logcatLogBuffer
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.kotlinArgumentCaptor
+import com.google.common.truth.Truth.assertThat
+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.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalBackupRestoreStartableTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    @Mock private lateinit var communalInteractor: CommunalInteractor
+
+    private val mapCaptor = kotlinArgumentCaptor<Map<Int, Int>>()
+
+    private lateinit var context: Context
+    private lateinit var broadcastDispatcher: FakeBroadcastDispatcher
+    private lateinit var underTest: CommunalBackupRestoreStartable
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+
+        context = kosmos.mockedContext
+        broadcastDispatcher = kosmos.broadcastDispatcher
+
+        underTest =
+            CommunalBackupRestoreStartable(
+                broadcastDispatcher,
+                communalInteractor,
+                logcatLogBuffer("CommunalBackupRestoreStartable"),
+            )
+    }
+
+    @Test
+    fun testRestoreWidgetsUponHostRestored() =
+        testScope.runTest {
+            underTest.start()
+
+            // Verify restore widgets not called
+            verify(communalInteractor, never()).restoreWidgets(any())
+
+            // Trigger app widget host restored
+            val intent =
+                Intent().apply {
+                    action = AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED
+                    putExtra(
+                        AppWidgetManager.EXTRA_HOST_ID,
+                        CommunalWidgetModule.APP_WIDGET_HOST_ID
+                    )
+                    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, intArrayOf(1, 2, 3))
+                    putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(7, 8, 9))
+                }
+            broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intent)
+
+            // Verify restore widgets called
+            verify(communalInteractor).restoreWidgets(mapCaptor.capture())
+            val oldToNewWidgetIdMap = mapCaptor.value
+            assertThat(oldToNewWidgetIdMap)
+                .containsExactlyEntriesIn(
+                    mapOf(
+                        Pair(1, 7),
+                        Pair(2, 8),
+                        Pair(3, 9),
+                    )
+                )
+        }
+
+    @Test
+    fun testDoNotRestoreWidgetsIfNotForCommunalWidgetHost() =
+        testScope.runTest {
+            underTest.start()
+
+            // Trigger app widget host restored, but for another host
+            val hostId = CommunalWidgetModule.APP_WIDGET_HOST_ID + 1
+            val intent =
+                Intent().apply {
+                    action = AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED
+                    putExtra(AppWidgetManager.EXTRA_HOST_ID, hostId)
+                    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, intArrayOf(1, 2, 3))
+                    putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(7, 8, 9))
+                }
+            broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intent)
+
+            // Verify restore widgets not called
+            verify(communalInteractor, never()).restoreWidgets(any())
+        }
+
+    @Test
+    fun testAbortRestoreWidgetsIfOldToNewIdsMappingInvalid() =
+        testScope.runTest {
+            underTest.start()
+
+            // Trigger app widget host restored, but new ids list is one too many for old ids
+            val oldIds = intArrayOf(1, 2, 3)
+            val newIds = intArrayOf(6, 7, 8, 9)
+            val intent =
+                Intent().apply {
+                    action = AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED
+                    putExtra(
+                        AppWidgetManager.EXTRA_HOST_ID,
+                        CommunalWidgetModule.APP_WIDGET_HOST_ID
+                    )
+                    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, oldIds)
+                    putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, newIds)
+                }
+            broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intent)
+
+            // Verify restore widgets aborted
+            verify(communalInteractor).abortRestoreWidgets()
+            verify(communalInteractor, never()).restoreWidgets(any())
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
index a944afb..b4b812d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
@@ -32,7 +32,9 @@
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.notificationShadeWindowController
 import com.android.systemui.testKosmos
 import com.android.systemui.util.settings.fakeSettings
 import com.google.common.truth.Truth.assertThat
@@ -68,8 +70,10 @@
                         keyguardTransitionInteractor = keyguardTransitionInteractor,
                         keyguardInteractor = keyguardInteractor,
                         systemSettings = fakeSettings,
+                        notificationShadeWindowController = notificationShadeWindowController,
                         applicationScope = applicationCoroutineScope,
                         bgScope = applicationCoroutineScope,
+                        mainDispatcher = testDispatcher,
                     )
                     .apply { start() }
 
@@ -120,19 +124,20 @@
         }
 
     @Test
-    fun exitingDream_forceCommunalScene() =
+    fun occluded_forceBlankScene() =
         with(kosmos) {
             testScope.runTest {
                 val scene by collectLastValue(communalInteractor.desiredScene)
-                assertThat(scene).isEqualTo(CommunalScenes.Blank)
+                communalInteractor.changeScene(CommunalScenes.Communal)
+                assertThat(scene).isEqualTo(CommunalScenes.Communal)
 
                 updateDocked(true)
                 fakeKeyguardTransitionRepository.sendTransitionSteps(
-                    from = KeyguardState.DREAMING,
-                    to = KeyguardState.LOCKSCREEN,
+                    from = KeyguardState.GLANCEABLE_HUB,
+                    to = KeyguardState.OCCLUDED,
                     testScope = this
                 )
-                assertThat(scene).isEqualTo(CommunalScenes.Communal)
+                assertThat(scene).isEqualTo(CommunalScenes.Blank)
             }
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
index f71121c..ce7b60e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
@@ -23,6 +23,7 @@
 import android.appwidget.AppWidgetProviderInfo
 import android.content.Intent
 import android.content.pm.UserInfo
+import android.os.UserManager.USER_TYPE_PROFILE_MANAGED
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.provider.Settings
@@ -59,6 +60,7 @@
         kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
         setKeyguardFeaturesDisabled(PRIMARY_USER, KEYGUARD_DISABLE_FEATURES_NONE)
         setKeyguardFeaturesDisabled(SECONDARY_USER, KEYGUARD_DISABLE_FEATURES_NONE)
+        setKeyguardFeaturesDisabled(WORK_PROFILE, KEYGUARD_DISABLE_FEATURES_NONE)
         underTest = kosmos.communalSettingsRepository
     }
 
@@ -133,6 +135,30 @@
 
     @EnableFlags(FLAG_COMMUNAL_HUB)
     @Test
+    fun widgetsAllowedForWorkProfile_isFalse_whenDisallowedByDevicePolicy() =
+        testScope.runTest {
+            val widgetsAllowedForWorkProfile by
+                collectLastValue(underTest.getAllowedByDevicePolicy(WORK_PROFILE))
+            assertThat(widgetsAllowedForWorkProfile).isTrue()
+
+            setKeyguardFeaturesDisabled(WORK_PROFILE, KEYGUARD_DISABLE_WIDGETS_ALL)
+            assertThat(widgetsAllowedForWorkProfile).isFalse()
+        }
+
+    @EnableFlags(FLAG_COMMUNAL_HUB)
+    @Test
+    fun hubIsEnabled_whenDisallowedByDevicePolicyForWorkProfile() =
+        testScope.runTest {
+            val enabledStateForPrimaryUser by
+                collectLastValue(underTest.getEnabledState(PRIMARY_USER))
+            assertThat(enabledStateForPrimaryUser?.enabled).isTrue()
+
+            setKeyguardFeaturesDisabled(WORK_PROFILE, KEYGUARD_DISABLE_WIDGETS_ALL)
+            assertThat(enabledStateForPrimaryUser?.enabled).isTrue()
+        }
+
+    @EnableFlags(FLAG_COMMUNAL_HUB)
+    @Test
     fun hubIsDisabledByUserAndDevicePolicy() =
         testScope.runTest {
             val enabledState by collectLastValue(underTest.getEnabledState(PRIMARY_USER))
@@ -189,5 +215,13 @@
         val PRIMARY_USER =
             UserInfo(/* id= */ 0, /* name= */ "primary user", /* flags= */ UserInfo.FLAG_MAIN)
         val SECONDARY_USER = UserInfo(/* id= */ 1, /* name= */ "secondary user", /* flags= */ 0)
+        val WORK_PROFILE =
+            UserInfo(
+                10,
+                "work",
+                /* iconPath= */ "",
+                /* flags= */ 0,
+                USER_TYPE_PROFILE_MANAGED,
+            )
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
index a4c7abd..fe4d32d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
@@ -16,18 +16,23 @@
 
 package com.android.systemui.communal.data.repository
 
+import android.app.backup.BackupManager
 import android.appwidget.AppWidgetManager
 import android.appwidget.AppWidgetProviderInfo
 import android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_CONFIGURATION_OPTIONAL
 import android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_RECONFIGURABLE
 import android.content.ComponentName
+import android.content.applicationContext
 import android.os.UserHandle
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
 import com.android.systemui.communal.data.db.CommunalItemRank
 import com.android.systemui.communal.data.db.CommunalWidgetDao
 import com.android.systemui.communal.data.db.CommunalWidgetItem
+import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.communal.proto.toByteArray
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.communal.widgets.CommunalAppWidgetHost
 import com.android.systemui.communal.widgets.CommunalWidgetHost
@@ -42,6 +47,7 @@
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -68,7 +74,9 @@
     @Mock private lateinit var providerInfoA: AppWidgetProviderInfo
     @Mock private lateinit var communalWidgetHost: CommunalWidgetHost
     @Mock private lateinit var communalWidgetDao: CommunalWidgetDao
+    @Mock private lateinit var backupManager: BackupManager
 
+    private lateinit var backupUtils: CommunalBackupUtils
     private lateinit var logBuffer: LogBuffer
     private lateinit var fakeWidgets: MutableStateFlow<Map<CommunalItemRank, CommunalWidgetItem>>
 
@@ -89,6 +97,7 @@
         MockitoAnnotations.initMocks(this)
         fakeWidgets = MutableStateFlow(emptyMap())
         logBuffer = logcatLogBuffer(name = "CommunalWidgetRepoImplTest")
+        backupUtils = CommunalBackupUtils(kosmos.applicationContext)
 
         setAppWidgetIds(emptyList())
 
@@ -106,6 +115,8 @@
                 communalWidgetHost,
                 communalWidgetDao,
                 logBuffer,
+                backupManager,
+                backupUtils,
             )
     }
 
@@ -129,6 +140,9 @@
                         priority = communalItemRankEntry.rank,
                     )
                 )
+
+            // Verify backup not requested
+            verify(backupManager, never()).dataChanged()
         }
 
     @Test
@@ -152,6 +166,9 @@
 
             verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
             verify(communalWidgetDao).addWidget(id, provider, priority)
+
+            // Verify backup requested
+            verify(backupManager).dataChanged()
         }
 
     @Test
@@ -176,6 +193,9 @@
             verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
             verify(communalWidgetDao, never()).addWidget(id, provider, priority)
             verify(appWidgetHost).deleteAppWidgetId(id)
+
+            // Verify backup not requested
+            verify(backupManager, never()).dataChanged()
         }
 
     @Test
@@ -202,6 +222,9 @@
             verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
             verify(communalWidgetDao, never()).addWidget(id, provider, priority)
             verify(appWidgetHost).deleteAppWidgetId(id)
+
+            // Verify backup not requested
+            verify(backupManager, never()).dataChanged()
         }
 
     @Test
@@ -225,10 +248,13 @@
 
             verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
             verify(communalWidgetDao).addWidget(id, provider, priority)
+
+            // Verify backup requested
+            verify(backupManager).dataChanged()
         }
 
     @Test
-    fun deleteWidget_deletefromDbTrue_alsoDeleteFromHost() =
+    fun deleteWidget_deleteFromDbTrue_alsoDeleteFromHost() =
         testScope.runTest {
             val id = 1
             whenever(communalWidgetDao.deleteWidgetById(eq(id))).thenReturn(true)
@@ -237,10 +263,13 @@
 
             verify(communalWidgetDao).deleteWidgetById(id)
             verify(appWidgetHost).deleteAppWidgetId(id)
+
+            // Verify backup requested
+            verify(backupManager).dataChanged()
         }
 
     @Test
-    fun deleteWidget_deletefromDbFalse_doesNotDeleteFromHost() =
+    fun deleteWidget_deleteFromDbFalse_doesNotDeleteFromHost() =
         testScope.runTest {
             val id = 1
             whenever(communalWidgetDao.deleteWidgetById(eq(id))).thenReturn(false)
@@ -249,6 +278,9 @@
 
             verify(communalWidgetDao).deleteWidgetById(id)
             verify(appWidgetHost, never()).deleteAppWidgetId(id)
+
+            // Verify backup not requested
+            verify(backupManager, never()).dataChanged()
         }
 
     @Test
@@ -259,6 +291,147 @@
             runCurrent()
 
             verify(communalWidgetDao).updateWidgetOrder(widgetIdToPriorityMap)
+
+            // Verify backup requested
+            verify(backupManager).dataChanged()
+        }
+
+    @Test
+    fun restoreWidgets_deleteStateFileIfRestoreFails() =
+        testScope.runTest {
+            // Write a state file that is invalid, and verify it is written
+            backupUtils.writeBytesToDisk(byteArrayOf(1, 2, 3, 4, 5, 6))
+            assertThat(backupUtils.fileExists()).isTrue()
+
+            // Try to restore widgets
+            underTest.restoreWidgets(emptyMap())
+            runCurrent()
+
+            // The restore should fail, and verify that the file is deleted
+            assertThat(backupUtils.fileExists()).isFalse()
+        }
+
+    @Test
+    fun restoreWidgets_deleteStateFileAfterWidgetsRestored() =
+        testScope.runTest {
+            // Write a state file, and verify it is written
+            backupUtils.writeBytesToDisk(fakeState.toByteArray())
+            assertThat(backupUtils.fileExists()).isTrue()
+
+            // Set up app widget host with widget ids
+            setAppWidgetIds(listOf(11, 12))
+
+            // Restore widgets
+            underTest.restoreWidgets(mapOf(Pair(1, 11), Pair(2, 12)))
+            runCurrent()
+
+            // Verify state restored
+            verify(communalWidgetDao).restoreCommunalHubState(any())
+
+            // Verify state file deleted
+            assertThat(backupUtils.fileExists()).isFalse()
+        }
+
+    @Test
+    fun restoreWidgets_restoredWidgetsNotRegisteredWithHostAreSkipped() =
+        testScope.runTest {
+            // Write fake state to file
+            backupUtils.writeBytesToDisk(fakeState.toByteArray())
+
+            // Set up app widget host with widget ids. Widget 12 (previously 2) is absent.
+            setAppWidgetIds(listOf(11))
+
+            // Restore widgets.
+            underTest.restoreWidgets(mapOf(Pair(1, 11), Pair(2, 12)))
+            runCurrent()
+
+            // Verify state restored, and widget 2 skipped
+            val restoredState =
+                withArgCaptor<CommunalHubState> {
+                    verify(communalWidgetDao).restoreCommunalHubState(capture())
+                }
+            val restoredWidgets = restoredState.widgets.toList()
+            assertThat(restoredWidgets).hasSize(1)
+
+            val restoredWidget = restoredWidgets.first()
+            val expectedWidget = fakeState.widgets.first()
+
+            // Verify widget id is updated, and the rest remain the same as expected
+            assertThat(restoredWidget.widgetId).isEqualTo(11)
+            assertThat(restoredWidget.componentName).isEqualTo(expectedWidget.componentName)
+            assertThat(restoredWidget.rank).isEqualTo(expectedWidget.rank)
+        }
+
+    @Test
+    fun restoreWidgets_registeredWidgetsNotRestoredAreRemoved() =
+        testScope.runTest {
+            // Write fake state to file
+            backupUtils.writeBytesToDisk(fakeState.toByteArray())
+
+            // Set up app widget host with widget ids. Widget 13 will not be restored.
+            setAppWidgetIds(listOf(11, 12, 13))
+
+            // Restore widgets.
+            underTest.restoreWidgets(mapOf(Pair(1, 11), Pair(2, 12)))
+            runCurrent()
+
+            // Verify widget 1 and 2 are restored, and are now 11 and 12.
+            val restoredState =
+                withArgCaptor<CommunalHubState> {
+                    verify(communalWidgetDao).restoreCommunalHubState(capture())
+                }
+            val restoredWidgets = restoredState.widgets.toList()
+            assertThat(restoredWidgets).hasSize(2)
+
+            val restoredWidget1 = restoredWidgets[0]
+            val expectedWidget1 = fakeState.widgets[0]
+            assertThat(restoredWidget1.widgetId).isEqualTo(11)
+            assertThat(restoredWidget1.componentName).isEqualTo(expectedWidget1.componentName)
+            assertThat(restoredWidget1.rank).isEqualTo(expectedWidget1.rank)
+
+            val restoredWidget2 = restoredWidgets[1]
+            val expectedWidget2 = fakeState.widgets[1]
+            assertThat(restoredWidget2.widgetId).isEqualTo(12)
+            assertThat(restoredWidget2.componentName).isEqualTo(expectedWidget2.componentName)
+            assertThat(restoredWidget2.rank).isEqualTo(expectedWidget2.rank)
+
+            // Verify widget 13 removed since it is not restored
+            verify(appWidgetHost).deleteAppWidgetId(13)
+        }
+
+    @Test
+    fun restoreWidgets_onlySomeWidgetsGotNewIds() =
+        testScope.runTest {
+            // Write fake state to file
+            backupUtils.writeBytesToDisk(fakeState.toByteArray())
+
+            // Set up app widget host with widget ids. Widget 2 gets a new id: 12, but widget 1 does
+            // not.
+            setAppWidgetIds(listOf(1, 12))
+
+            // Restore widgets.
+            underTest.restoreWidgets(mapOf(Pair(2, 12)))
+            runCurrent()
+
+            // Verify widget 1 and 2 are restored, and are now 1 and 12.
+            val restoredState =
+                withArgCaptor<CommunalHubState> {
+                    verify(communalWidgetDao).restoreCommunalHubState(capture())
+                }
+            val restoredWidgets = restoredState.widgets.toList()
+            assertThat(restoredWidgets).hasSize(2)
+
+            val restoredWidget1 = restoredWidgets[0]
+            val expectedWidget1 = fakeState.widgets[0]
+            assertThat(restoredWidget1.widgetId).isEqualTo(1)
+            assertThat(restoredWidget1.componentName).isEqualTo(expectedWidget1.componentName)
+            assertThat(restoredWidget1.rank).isEqualTo(expectedWidget1.rank)
+
+            val restoredWidget2 = restoredWidgets[1]
+            val expectedWidget2 = fakeState.widgets[1]
+            assertThat(restoredWidget2.widgetId).isEqualTo(12)
+            assertThat(restoredWidget2.componentName).isEqualTo(expectedWidget2.componentName)
+            assertThat(restoredWidget2.rank).isEqualTo(expectedWidget2.rank)
         }
 
     private fun installedProviders(providers: List<AppWidgetProviderInfo>) {
@@ -278,5 +451,22 @@
                 widgetFeatures =
                     WIDGET_FEATURE_CONFIGURATION_OPTIONAL or WIDGET_FEATURE_RECONFIGURABLE
             }
+        val fakeState =
+            CommunalHubState().apply {
+                widgets =
+                    listOf(
+                            CommunalHubState.CommunalWidgetItem().apply {
+                                widgetId = 1
+                                componentName = "pk_name/fake_widget_1"
+                                rank = 1
+                            },
+                            CommunalHubState.CommunalWidgetItem().apply {
+                                widgetId = 2
+                                componentName = "pk_name/fake_widget_2"
+                                rank = 2
+                            },
+                        )
+                        .toTypedArray()
+            }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index e7ccde2..497180b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -17,6 +17,8 @@
 
 package com.android.systemui.communal.domain.interactor
 
+import android.app.admin.DevicePolicyManager
+import android.app.admin.devicePolicyManager
 import android.app.smartspace.SmartspaceTarget
 import android.appwidget.AppWidgetProviderInfo
 import android.content.Intent
@@ -32,6 +34,7 @@
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.broadcastDispatcher
 import com.android.systemui.communal.data.repository.CommunalSettingsRepositoryImpl
 import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository
 import com.android.systemui.communal.data.repository.FakeCommunalPrefsRepository
@@ -49,6 +52,7 @@
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -58,7 +62,6 @@
 import com.android.systemui.plugins.activityStarter
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.settings.fakeUserTracker
@@ -71,6 +74,7 @@
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.settings.fakeSettings
 import com.google.common.truth.Truth.assertThat
@@ -694,10 +698,9 @@
         }
 
     @Test
+    @EnableSceneContainer
     fun isCommunalShowing_whenSceneContainerEnabled() =
         testScope.runTest {
-            kosmos.fakeSceneContainerFlags.enabled = true
-
             // Verify default is false
             val isCommunalShowing by collectLastValue(underTest.isCommunalShowing)
             runCurrent()
@@ -929,7 +932,6 @@
             keyguardRepository.setKeyguardShowing(true)
             keyguardRepository.setKeyguardOccluded(false)
             tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
-            userRepository.setSelectedUserInfo(mainUser)
 
             val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK)
             userRepository.setUserInfos(userInfos)
@@ -937,6 +939,7 @@
                 userInfos = userInfos,
                 selectedUserIndex = 0,
             )
+            userRepository.setSelectedUserInfo(MAIN_USER_INFO)
             runCurrent()
 
             // Widgets available.
@@ -955,7 +958,6 @@
                 AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD,
                 mainUser.id
             )
-            runCurrent()
 
             // Only the keyguard widget is enabled.
             assertThat(widgetContent).hasSize(3)
@@ -974,7 +976,6 @@
             keyguardRepository.setKeyguardShowing(true)
             keyguardRepository.setKeyguardOccluded(false)
             tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
-            userRepository.setSelectedUserInfo(mainUser)
 
             val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK)
             userRepository.setUserInfos(userInfos)
@@ -982,6 +983,7 @@
                 userInfos = userInfos,
                 selectedUserIndex = 0,
             )
+            userRepository.setSelectedUserInfo(MAIN_USER_INFO)
             runCurrent()
 
             // Widgets available.
@@ -1001,7 +1003,6 @@
                     AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
                 mainUser.id
             )
-            runCurrent()
 
             // All widgets are enabled.
             assertThat(widgetContent).hasSize(3)
@@ -1011,6 +1012,79 @@
             }
         }
 
+    @Test
+    fun filterWidgets_whenDisallowedByDevicePolicyForWorkProfile() =
+        testScope.runTest {
+            // Keyguard showing, and tutorial completed.
+            keyguardRepository.setKeyguardShowing(true)
+            keyguardRepository.setKeyguardOccluded(false)
+            tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
+
+            val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK)
+            userRepository.setUserInfos(userInfos)
+            userTracker.set(
+                userInfos = userInfos,
+                selectedUserIndex = 0,
+            )
+            userRepository.setSelectedUserInfo(MAIN_USER_INFO)
+            runCurrent()
+
+            val widgetContent by collectLastValue(underTest.widgetContent)
+            // Given three widgets, and one of them is associated with work profile.
+            val widget1 = createWidgetForUser(1, USER_INFO_WORK.id)
+            val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id)
+            val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id)
+            val widgets = listOf(widget1, widget2, widget3)
+            widgetRepository.setCommunalWidgets(widgets)
+
+            setKeyguardFeaturesDisabled(
+                USER_INFO_WORK,
+                DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL
+            )
+
+            // Widget under work profile is filtered out and the remaining two link to main user id.
+            assertThat(widgetContent).hasSize(2)
+            widgetContent!!.forEach { model ->
+                assertThat(model.providerInfo.profile?.identifier).isEqualTo(MAIN_USER_INFO.id)
+            }
+        }
+
+    @Test
+    fun filterWidgets_whenAllowedByDevicePolicyForWorkProfile() =
+        testScope.runTest {
+            // Keyguard showing, and tutorial completed.
+            keyguardRepository.setKeyguardShowing(true)
+            keyguardRepository.setKeyguardOccluded(false)
+            tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
+
+            val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK)
+            userRepository.setUserInfos(userInfos)
+            userTracker.set(
+                userInfos = userInfos,
+                selectedUserIndex = 0,
+            )
+            userRepository.setSelectedUserInfo(MAIN_USER_INFO)
+            runCurrent()
+
+            val widgetContent by collectLastValue(underTest.widgetContent)
+            // Given three widgets, and one of them is associated with work profile.
+            val widget1 = createWidgetForUser(1, USER_INFO_WORK.id)
+            val widget2 = createWidgetForUser(2, MAIN_USER_INFO.id)
+            val widget3 = createWidgetForUser(3, MAIN_USER_INFO.id)
+            val widgets = listOf(widget1, widget2, widget3)
+            widgetRepository.setCommunalWidgets(widgets)
+
+            setKeyguardFeaturesDisabled(
+                USER_INFO_WORK,
+                DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
+            )
+
+            // Widget under work profile is available.
+            assertThat(widgetContent).hasSize(3)
+            assertThat(widgetContent!![0].providerInfo.profile?.identifier)
+                .isEqualTo(USER_INFO_WORK.id)
+        }
+
     private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget {
         val timer = mock(SmartspaceTarget::class.java)
         whenever(timer.smartspaceTargetId).thenReturn(id)
@@ -1020,6 +1094,15 @@
         return timer
     }
 
+    private fun setKeyguardFeaturesDisabled(user: UserInfo, disabledFlags: Int) {
+        whenever(kosmos.devicePolicyManager.getKeyguardDisabledFeatures(nullable(), eq(user.id)))
+            .thenReturn(disabledFlags)
+        kosmos.broadcastDispatcher.sendIntentToMatchingReceiversOnly(
+            context,
+            Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+        )
+    }
+
     private fun createWidgetForUser(appWidgetId: Int, userId: Int): CommunalWidgetContentModel =
         mock<CommunalWidgetContentModel> {
             whenever(this.appWidgetId).thenReturn(appWidgetId)
@@ -1044,6 +1127,13 @@
 
     private companion object {
         val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
-        val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE)
+        val USER_INFO_WORK =
+            UserInfo(
+                10,
+                "work",
+                /* iconPath= */ "",
+                /* flags= */ 0,
+                UserManager.USER_TYPE_PROFILE_MANAGED,
+            )
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
index a496292..c56e919 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
@@ -31,7 +31,7 @@
     @Test
     fun addView() {
         val constraintLayout = ConstraintLayout(context, null)
-        blueprint.replaceViews(null, constraintLayout)
+        blueprint.replaceViews(constraintLayout)
         verify(hubSection).addViews(constraintLayout)
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 5be765d..779e79ed 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -44,11 +44,13 @@
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.log.logcatLogBuffer
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
 import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.shade.data.repository.fakeShadeRepository
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
 import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository
@@ -59,6 +61,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -266,6 +269,26 @@
             assertThat(isPopupOnDismissCtaShowing).isEqualTo(false)
         }
 
+    @Test
+    fun canChangeScene_shadeNotExpanded() =
+        testScope.runTest {
+            // On keyguard without any shade expansion.
+            kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+            kosmos.fakeShadeRepository.setLockscreenShadeExpansion(0f)
+            runCurrent()
+            assertThat(underTest.canChangeScene()).isTrue()
+        }
+
+    @Test
+    fun canChangeScene_shadeExpanded() =
+        testScope.runTest {
+            // On keyguard with shade fully expanded.
+            kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+            kosmos.fakeShadeRepository.setLockscreenShadeExpansion(1f)
+            runCurrent()
+            assertThat(underTest.canChangeScene()).isFalse()
+        }
+
     private suspend fun setIsMainUser(isMainUser: Boolean) {
         whenever(user.isMain).thenReturn(isMainUser)
         userRepository.setUserInfos(listOf(user))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 36919d0..6b2a1d5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -32,7 +32,6 @@
 import android.hardware.face.FaceSensorProperties
 import android.hardware.face.FaceSensorPropertiesInternal
 import android.os.CancellationSignal
-import android.view.Display
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.InstanceId.fakeInstanceId
@@ -54,7 +53,6 @@
 import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
 import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus
 import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
-import com.android.systemui.display.data.repository.display
 import com.android.systemui.display.data.repository.displayRepository
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FakeFeatureFlags
@@ -68,6 +66,7 @@
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.kosmos.testDispatcher
@@ -697,9 +696,7 @@
             )
             runCurrent()
 
-            displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_OFF)))
-            displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY)
-
+            displayRepository.setDefaultDisplayOff(true)
             runCurrent()
 
             assertThat(canFaceAuthRun()).isTrue()
@@ -717,10 +714,7 @@
                 )
                 runCurrent()
 
-                displayRepository.emit(
-                    setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_OFF))
-                )
-                displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY)
+                displayRepository.setDefaultDisplayOff(true)
             }
         }
 
@@ -827,21 +821,37 @@
         }
 
     @Test
-    fun isAuthenticatedIsResetToFalseWhenKeyguardDoneAnimationsFinished() =
+    fun isAuthenticatedIsResetToFalseWhenFinishedTransitioningToGoneAndStatusBarStateShade() =
         testScope.runTest {
             initCollectors()
             allPreconditionsToRunFaceAuthAreTrue()
 
             triggerFaceAuth(false)
 
+            keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
             authenticationCallback.value.onAuthenticationSucceeded(
                 mock(FaceManager.AuthenticationResult::class.java)
             )
 
             assertThat(authenticated()).isTrue()
 
-            keyguardRepository.keyguardDoneAnimationsFinished()
+            keyguardTransitionRepository.sendTransitionStep(
+                TransitionStep(
+                    transitionState = TransitionState.STARTED,
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.GONE,
+                )
+            )
+            keyguardTransitionRepository.sendTransitionStep(
+                TransitionStep(
+                    transitionState = TransitionState.FINISHED,
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.GONE,
+                )
+            )
+            assertThat(authenticated()).isTrue()
 
+            keyguardRepository.setStatusBarState(StatusBarState.SHADE)
             assertThat(authenticated()).isFalse()
         }
 
@@ -1161,8 +1171,7 @@
         faceLockoutResetCallback.value.onLockoutReset(0)
         bouncerRepository.setAlternateVisible(true)
         keyguardRepository.setKeyguardShowing(true)
-        displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_ON)))
-        displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY)
+        displayRepository.setDefaultDisplayOff(false)
         keyguardTransitionRepository.sendTransitionSteps(
             from = KeyguardState.AOD,
             to = KeyguardState.LOCKSCREEN,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
index 5caf35b..84c250c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.deviceentry.domain.interactor
 
+import android.testing.TestableLooper
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.SceneKey
@@ -25,6 +26,9 @@
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
 import com.android.systemui.authentication.domain.interactor.authenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository
+import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
@@ -38,16 +42,21 @@
 import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason.TrustAgentDisabled
 import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason.UnattendedUpdate
 import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReason.UserLockdown
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.fakeSystemPropertiesHelper
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.fakeTrustRepository
 import com.android.systemui.keyguard.shared.model.AuthenticationFlags
+import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -62,6 +71,8 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
[email protected]
 class DeviceEntryInteractorTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
@@ -74,7 +85,6 @@
 
     @Before
     fun setUp() {
-        kosmos.fakeSceneContainerFlags.enabled = true
         underTest = kosmos.deviceEntryInteractor
     }
 
@@ -371,6 +381,42 @@
         }
 
     @Test
+    fun showOrUnlockDevice_noAlternateBouncer_switchesToBouncerScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            switchToScene(Scenes.Lockscreen)
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+            kosmos.fakeFingerprintPropertyRepository.supportsRearFps() // altBouncer unsupported
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pin
+            )
+            runCurrent()
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+        }
+
+    @Test
+    fun showOrUnlockDevice_showsAlternateBouncer_staysOnLockscreenScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            switchToScene(Scenes.Lockscreen)
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pin
+            )
+            givenCanShowAlternateBouncer()
+            runCurrent()
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+        }
+
+    @Test
     fun isBypassEnabled_disabledInRepository_false() =
         testScope.runTest {
             kosmos.fakeDeviceEntryRepository.setBypassEnabled(false)
@@ -593,4 +639,20 @@
     private fun switchToScene(sceneKey: SceneKey) {
         sceneInteractor.changeScene(sceneKey, "reason")
     }
+
+    private suspend fun givenCanShowAlternateBouncer() {
+        val canShowAlternateBouncer by
+            testScope.collectLastValue(kosmos.alternateBouncerInteractor.canShowAlternateBouncer)
+        kosmos.fakeFingerprintPropertyRepository.supportsUdfps()
+        kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+            from = KeyguardState.GONE,
+            to = KeyguardState.LOCKSCREEN,
+            testScheduler = testScope.testScheduler,
+        )
+        kosmos.deviceEntryFingerprintAuthRepository.setLockedOut(false)
+        kosmos.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+        kosmos.fakeKeyguardRepository.setKeyguardDismissible(false)
+        kosmos.keyguardBouncerRepository.setPrimaryShow(false)
+        assertThat(canShowAlternateBouncer).isTrue()
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt
index e9e85c9..11cade2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/binder/LiftToRunFaceAuthBinderTest.kt
@@ -66,7 +66,7 @@
     @Captor private lateinit var triggerEventListenerCaptor: ArgumentCaptor<TriggerEventListener>
     @Mock private lateinit var mockSensor: Sensor
 
-    private val underTest = kosmos.liftToRunFaceAuthBinder
+    private val underTest by lazy { kosmos.liftToRunFaceAuthBinder }
 
     @Before
     fun setup() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java
deleted file mode 100644
index 3754062..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFake.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dock;
-
-/**
- * A rudimentary fake for DockManager.
- */
-public class DockManagerFake implements DockManager {
-    DockEventListener mCallback;
-    AlignmentStateListener mAlignmentListener;
-    private boolean mDocked;
-
-    @Override
-    public void addListener(DockEventListener callback) {
-        this.mCallback = callback;
-    }
-
-    @Override
-    public void removeListener(DockEventListener callback) {
-        this.mCallback = null;
-    }
-
-    @Override
-    public void addAlignmentStateListener(AlignmentStateListener listener) {
-        mAlignmentListener = listener;
-    }
-
-    @Override
-    public void removeAlignmentStateListener(AlignmentStateListener listener) {
-        mAlignmentListener = listener;
-    }
-
-    @Override
-    public boolean isDocked() {
-        return mDocked;
-    }
-
-    public void setIsDocked(boolean docked) {
-        mDocked = docked;
-    }
-
-    @Override
-    public boolean isHidden() {
-        return false;
-    }
-
-    public void setDockEvent(int event) {
-        mCallback.onEvent(event);
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 2af6566..e2e5169 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.dreams;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -28,6 +30,7 @@
 import android.content.res.Resources;
 import android.graphics.Region;
 import android.os.Handler;
+import android.testing.TestableLooper.RunWithLooper;
 import android.view.AttachedSurfaceControl;
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
@@ -39,10 +42,11 @@
 import com.android.dream.lowlight.LowLightTransitionCoordinator;
 import com.android.keyguard.BouncerPanelExpansionCalculator;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
 import com.android.systemui.complication.ComplicationHostViewController;
-import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.statusbar.BlurUtils;
 
 import org.junit.Before;
@@ -52,8 +56,11 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@RunWithLooper(setAsMainLooper = true)
 public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
     private static final int MAX_BURN_IN_OFFSET = 20;
     private static final long BURN_IN_PROTECTION_UPDATE_INTERVAL = 10;
@@ -87,6 +94,9 @@
     Handler mHandler;
 
     @Mock
+    CoroutineDispatcher mDispatcher;
+
+    @Mock
     BlurUtils mBlurUtils;
 
     @Mock
@@ -103,6 +113,8 @@
 
     @Mock
     DreamOverlayStateController mStateController;
+    @Mock
+    KeyguardTransitionInteractor mKeyguardTransitionInteractor;
 
     DreamOverlayContainerViewController mController;
 
@@ -115,6 +127,7 @@
         when(mDreamOverlayContainerView.getViewRootImpl()).thenReturn(mViewRoot);
         when(mDreamOverlayContainerView.getRootSurfaceControl())
                 .thenReturn(mAttachedSurfaceControl);
+        when(mKeyguardTransitionInteractor.isFinishedInStateWhere(any())).thenReturn(emptyFlow());
 
         mController = new DreamOverlayContainerViewController(
                 mDreamOverlayContainerView,
@@ -124,6 +137,7 @@
                 mLowLightTransitionCoordinator,
                 mBlurUtils,
                 mHandler,
+                mDispatcher,
                 mResources,
                 MAX_BURN_IN_OFFSET,
                 BURN_IN_PROTECTION_UPDATE_INTERVAL,
@@ -131,7 +145,8 @@
                 mPrimaryBouncerCallbackInteractor,
                 mAnimationsController,
                 mStateController,
-                mBouncerlessScrimController);
+                mBouncerlessScrimController,
+                mKeyguardTransitionInteractor);
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
deleted file mode 100644
index c143468..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ /dev/null
@@ -1,549 +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.dreams;
-
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
-
-import static com.google.common.truth.Truth.assertThat;
-
-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.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.service.dreams.IDreamOverlay;
-import android.service.dreams.IDreamOverlayCallback;
-import android.service.dreams.IDreamOverlayClient;
-import android.service.dreams.IDreamOverlayClientCallback;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
-
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.UiEventLogger;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.complication.ComplicationLayoutEngine;
-import com.android.systemui.dreams.complication.HideComplicationTouchHandler;
-import com.android.systemui.dreams.complication.dagger.ComplicationComponent;
-import com.android.systemui.dreams.dagger.DreamOverlayComponent;
-import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
-import com.android.systemui.touch.TouchInsetManager;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.utils.leaks.LeakCheckedTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class DreamOverlayServiceTest extends SysuiTestCase {
-    private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
-            "lowlight");
-
-    private static final ComponentName HOME_CONTROL_PANEL_DREAM_COMPONENT =
-            new ComponentName("package", "homeControlPanel");
-    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);
-
-    @Mock
-    DreamOverlayLifecycleOwner mLifecycleOwner;
-
-    @Mock
-    LifecycleRegistry mLifecycleRegistry;
-
-    @Rule
-    public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck();
-
-    WindowManager.LayoutParams mWindowParams;
-
-    @Mock
-    IDreamOverlayCallback mDreamOverlayCallback;
-
-    @Mock
-    WindowManagerImpl mWindowManager;
-
-    @Mock
-    com.android.systemui.complication.dagger.ComplicationComponent.Factory
-            mComplicationComponentFactory;
-
-    @Mock
-    com.android.systemui.complication.dagger.ComplicationComponent mComplicationComponent;
-
-    @Mock
-    ComplicationLayoutEngine mComplicationVisibilityController;
-
-    @Mock
-    ComplicationComponent.Factory mDreamComplicationComponentFactory;
-
-    @Mock
-    ComplicationComponent mDreamComplicationComponent;
-
-    @Mock
-    HideComplicationTouchHandler mHideComplicationTouchHandler;
-
-    @Mock
-    DreamOverlayComponent.Factory mDreamOverlayComponentFactory;
-
-    @Mock
-    DreamOverlayComponent mDreamOverlayComponent;
-
-    @Mock
-    DreamOverlayContainerView mDreamOverlayContainerView;
-
-    @Mock
-    DreamOverlayContainerViewController mDreamOverlayContainerViewController;
-
-    @Mock
-    KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
-    @Mock
-    DreamOverlayTouchMonitor mDreamOverlayTouchMonitor;
-
-    @Mock
-    DreamOverlayStateController mStateController;
-
-    @Mock
-    ViewGroup mDreamOverlayContainerViewParent;
-
-    @Mock
-    TouchInsetManager mTouchInsetManager;
-
-    @Mock
-    UiEventLogger mUiEventLogger;
-
-    @Mock
-    DreamOverlayCallbackController mDreamOverlayCallbackController;
-
-    @Captor
-    ArgumentCaptor<View> mViewCaptor;
-
-    DreamOverlayService mService;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mDreamOverlayComponent.getDreamOverlayContainerViewController())
-                .thenReturn(mDreamOverlayContainerViewController);
-        when(mLifecycleOwner.getRegistry())
-                .thenReturn(mLifecycleRegistry);
-        when(mDreamOverlayComponent.getDreamOverlayTouchMonitor())
-                .thenReturn(mDreamOverlayTouchMonitor);
-        when(mComplicationComponentFactory
-                .create(any(), any(), any(), any()))
-                .thenReturn(mComplicationComponent);
-        when(mComplicationComponent.getVisibilityController())
-                .thenReturn(mComplicationVisibilityController);
-        when(mDreamComplicationComponent.getHideComplicationTouchHandler())
-                .thenReturn(mHideComplicationTouchHandler);
-        when(mDreamComplicationComponentFactory
-                .create(any(), any()))
-                .thenReturn(mDreamComplicationComponent);
-        when(mDreamOverlayComponentFactory
-                .create(any(), any(), any(), any()))
-                .thenReturn(mDreamOverlayComponent);
-        when(mDreamOverlayContainerViewController.getContainerView())
-                .thenReturn(mDreamOverlayContainerView);
-
-        mWindowParams = new WindowManager.LayoutParams();
-        mService = new DreamOverlayService(
-                mContext,
-                mLifecycleOwner,
-                mMainExecutor,
-                mWindowManager,
-                mComplicationComponentFactory,
-                mDreamComplicationComponentFactory,
-                mDreamOverlayComponentFactory,
-                mStateController,
-                mKeyguardUpdateMonitor,
-                mUiEventLogger,
-                mTouchInsetManager,
-                LOW_LIGHT_COMPONENT,
-                HOME_CONTROL_PANEL_DREAM_COMPONENT,
-                mDreamOverlayCallbackController,
-                WINDOW_NAME);
-    }
-
-    public IDreamOverlayClient getClient() throws RemoteException {
-        final IBinder proxy = mService.onBind(new Intent());
-        final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
-        final IDreamOverlayClientCallback callback =
-                Mockito.mock(IDreamOverlayClientCallback.class);
-        overlay.getClient(callback);
-        final ArgumentCaptor<IDreamOverlayClient> clientCaptor =
-                ArgumentCaptor.forClass(IDreamOverlayClient.class);
-        verify(callback).onDreamOverlayClient(clientCaptor.capture());
-
-        return clientCaptor.getValue();
-    }
-
-    @Test
-    public void testOnStartMetricsLogged() throws Exception {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        verify(mUiEventLogger).log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
-        verify(mUiEventLogger).log(
-                DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
-    }
-
-    @Test
-    public void testOverlayContainerViewAddedToWindow() throws Exception {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        verify(mWindowManager).addView(any(), any());
-    }
-
-    // Validates that {@link DreamOverlayService} properly handles the case where the dream's
-    // window is no longer valid by the time start is called.
-    @Test
-    public void testInvalidWindowAddStart() throws Exception {
-        final IDreamOverlayClient client = getClient();
-
-        doThrow(new WindowManager.BadTokenException()).when(mWindowManager).addView(any(), any());
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        verify(mWindowManager).addView(any(), any());
-
-        verify(mStateController).setOverlayActive(false);
-        verify(mStateController).setLowLightActive(false);
-        verify(mStateController).setEntryAnimationsFinished(false);
-
-        verify(mStateController, never()).setOverlayActive(true);
-        verify(mUiEventLogger, never()).log(
-                DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
-
-        verify(mDreamOverlayCallbackController, never()).onStartDream();
-    }
-
-    @Test
-    public void testDreamOverlayContainerViewControllerInitialized() throws Exception {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        verify(mDreamOverlayContainerViewController).init();
-    }
-
-    @Test
-    public void testDreamOverlayContainerViewRemovedFromOldParentWhenInitialized()
-            throws Exception {
-        when(mDreamOverlayContainerView.getParent())
-                .thenReturn(mDreamOverlayContainerViewParent)
-                .thenReturn(null);
-
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        verify(mDreamOverlayContainerViewParent).removeView(mDreamOverlayContainerView);
-    }
-
-    @Test
-    public void testShouldShowComplicationsSetByStartDream() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                true /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        assertThat(mService.shouldShowComplications()).isTrue();
-    }
-
-    @Test
-    public void testLowLightSetByStartDream() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback,
-                LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        assertThat(mService.getDreamComponent()).isEqualTo(LOW_LIGHT_COMPONENT);
-        verify(mStateController).setLowLightActive(true);
-    }
-
-    @Test
-    public void testHomeControlPanelSetsByStartDream() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback,
-                HOME_CONTROL_PANEL_DREAM_COMPONENT.flattenToString(),
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-        assertThat(mService.getDreamComponent()).isEqualTo(HOME_CONTROL_PANEL_DREAM_COMPONENT);
-        verify(mStateController).setHomeControlPanelActive(true);
-    }
-
-    @Test
-    public void testOnEndDream() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback,
-                LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        // Verify view added.
-        verify(mWindowManager).addView(mViewCaptor.capture(), any());
-
-        // Service destroyed.
-        mService.onEndDream();
-        mMainExecutor.runAllReady();
-
-        // Verify view removed.
-        verify(mWindowManager).removeView(mViewCaptor.getValue());
-
-        // Verify state correctly set.
-        verify(mStateController).setOverlayActive(false);
-        verify(mStateController).setLowLightActive(false);
-        verify(mStateController).setEntryAnimationsFinished(false);
-    }
-
-    @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();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback,
-                LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        // Verify view added.
-        verify(mWindowManager).addView(mViewCaptor.capture(), any());
-
-        // Service destroyed.
-        mService.onDestroy();
-        mMainExecutor.runAllReady();
-
-        // Verify view removed.
-        verify(mWindowManager).removeView(mViewCaptor.getValue());
-
-        // Verify state correctly set.
-        verify(mKeyguardUpdateMonitor).removeCallback(any());
-        verify(mLifecycleRegistry).setCurrentState(Lifecycle.State.DESTROYED);
-        verify(mStateController).setOverlayActive(false);
-        verify(mStateController).setLowLightActive(false);
-        verify(mStateController).setEntryAnimationsFinished(false);
-    }
-
-    @Test
-    public void testDoNotRemoveViewOnDestroyIfOverlayNotStarted() {
-        // Service destroyed without ever starting dream.
-        mService.onDestroy();
-        mMainExecutor.runAllReady();
-
-        // Verify no view is removed.
-        verify(mWindowManager, never()).removeView(any());
-
-        // Verify state still correctly set.
-        verify(mKeyguardUpdateMonitor).removeCallback(any());
-        verify(mLifecycleRegistry).setCurrentState(Lifecycle.State.DESTROYED);
-        verify(mStateController).setOverlayActive(false);
-        verify(mStateController).setLowLightActive(false);
-    }
-
-    @Test
-    public void testDecorViewNotAddedToWindowAfterDestroy() throws Exception {
-        final IDreamOverlayClient client = getClient();
-
-        // Destroy the service.
-        mService.onDestroy();
-        mMainExecutor.runAllReady();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        verify(mWindowManager, never()).addView(any(), any());
-    }
-
-    @Test
-    public void testNeverRemoveDecorViewIfNotAdded() {
-        // Service destroyed before dream started.
-        mService.onDestroy();
-        mMainExecutor.runAllReady();
-
-        verify(mWindowManager, never()).removeView(any());
-    }
-
-    @Test
-    public void testResetCurrentOverlayWhenConnectedToNewDream() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting. Do not show dream complications.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        // Verify that a new window is added.
-        verify(mWindowManager).addView(mViewCaptor.capture(), any());
-        final View windowDecorView = mViewCaptor.getValue();
-
-        // Assert that the overlay is not showing complications.
-        assertThat(mService.shouldShowComplications()).isFalse();
-
-        clearInvocations(mDreamOverlayComponent);
-        clearInvocations(mWindowManager);
-
-        // New dream starting with dream complications showing. Note that when a new dream is
-        // binding to the dream overlay service, it receives the same instance of IBinder as the
-        // first one.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                true /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        // Assert that the overlay is showing complications.
-        assertThat(mService.shouldShowComplications()).isTrue();
-
-        // Verify that the old overlay window has been removed, and a new one created.
-        verify(mWindowManager).removeView(windowDecorView);
-        verify(mWindowManager).addView(any(), any());
-
-        // Verify that new instances of overlay container view controller and overlay touch monitor
-        // are created.
-        verify(mDreamOverlayComponent).getDreamOverlayContainerViewController();
-        verify(mDreamOverlayComponent).getDreamOverlayTouchMonitor();
-    }
-
-    @Test
-    public void testWakeUp() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                true /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        mService.onWakeUp();
-        verify(mDreamOverlayContainerViewController).wakeUp();
-        verify(mDreamOverlayCallbackController).onWakeUp();
-    }
-
-    @Test
-    public void testWakeUpBeforeStartDoesNothing() {
-        mService.onWakeUp();
-        verify(mDreamOverlayContainerViewController, never()).wakeUp();
-    }
-
-    @Test
-    public void testSystemFlagShowForAllUsersSetOnWindow() throws RemoteException {
-        final IDreamOverlayClient client = getClient();
-
-        // Inform the overlay service of dream starting. Do not show dream complications.
-        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
-                false /*shouldShowComplication*/);
-        mMainExecutor.runAllReady();
-
-        final ArgumentCaptor<WindowManager.LayoutParams> paramsCaptor =
-                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
-
-        // Verify that a new window is added.
-        verify(mWindowManager).addView(any(), paramsCaptor.capture());
-
-        assertThat((paramsCaptor.getValue().privateFlags & SYSTEM_FLAG_SHOW_FOR_ALL_USERS)
-                == SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isTrue();
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
new file mode 100644
index 0000000..bdb0c9a
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -0,0 +1,863 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.dreams
+
+import android.content.ComponentName
+import android.content.Intent
+import android.service.dreams.IDreamOverlay
+import android.service.dreams.IDreamOverlayCallback
+import android.service.dreams.IDreamOverlayClient
+import android.service.dreams.IDreamOverlayClientCallback
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import android.view.WindowManagerImpl
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.ambient.touch.TouchMonitor
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
+import com.android.systemui.ambient.touch.scrim.ScrimController
+import com.android.systemui.ambient.touch.scrim.ScrimManager
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
+import com.android.systemui.communal.data.repository.fakeCommunalRepository
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.complication.ComplicationHostViewController
+import com.android.systemui.complication.ComplicationLayoutEngine
+import com.android.systemui.complication.dagger.ComplicationComponent
+import com.android.systemui.dreams.complication.HideComplicationTouchHandler
+import com.android.systemui.dreams.dagger.DreamOverlayComponent
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.touch.TouchInsetManager
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.runCurrent
+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.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
[email protected](setAsMainLooper = true)
+@RunWith(AndroidJUnit4::class)
+class DreamOverlayServiceTest : SysuiTestCase() {
+    private val mFakeSystemClock = FakeSystemClock()
+    private val mMainExecutor = FakeExecutor(mFakeSystemClock)
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    @Mock lateinit var mLifecycleOwner: DreamOverlayLifecycleOwner
+
+    private lateinit var lifecycleRegistry: FakeLifecycleRegistry
+
+    private lateinit var mWindowParams: WindowManager.LayoutParams
+
+    @Mock lateinit var mDreamOverlayCallback: IDreamOverlayCallback
+
+    @Mock lateinit var mWindowManager: WindowManagerImpl
+
+    @Mock lateinit var mComplicationComponentFactory: ComplicationComponent.Factory
+
+    @Mock lateinit var mComplicationComponent: ComplicationComponent
+
+    @Mock lateinit var mComplicationHostViewController: ComplicationHostViewController
+
+    @Mock lateinit var mComplicationVisibilityController: ComplicationLayoutEngine
+
+    @Mock
+    lateinit var mDreamComplicationComponentFactory:
+        com.android.systemui.dreams.complication.dagger.ComplicationComponent.Factory
+
+    @Mock
+    lateinit var mDreamComplicationComponent:
+        com.android.systemui.dreams.complication.dagger.ComplicationComponent
+
+    @Mock lateinit var mHideComplicationTouchHandler: HideComplicationTouchHandler
+
+    @Mock lateinit var mDreamOverlayComponentFactory: DreamOverlayComponent.Factory
+
+    @Mock lateinit var mDreamOverlayComponent: DreamOverlayComponent
+
+    @Mock lateinit var mAmbientTouchComponentFactory: AmbientTouchComponent.Factory
+
+    @Mock lateinit var mAmbientTouchComponent: AmbientTouchComponent
+
+    @Mock lateinit var mDreamOverlayContainerView: DreamOverlayContainerView
+
+    @Mock lateinit var mDreamOverlayContainerViewController: DreamOverlayContainerViewController
+
+    @Mock lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor
+
+    @Mock lateinit var mTouchMonitor: TouchMonitor
+
+    @Mock lateinit var mStateController: DreamOverlayStateController
+
+    @Mock lateinit var mDreamOverlayContainerViewParent: ViewGroup
+
+    @Mock lateinit var mTouchInsetManager: TouchInsetManager
+
+    @Mock lateinit var mUiEventLogger: UiEventLogger
+
+    @Mock lateinit var mScrimManager: ScrimManager
+
+    @Mock lateinit var mScrimController: ScrimController
+
+    @Mock lateinit var mSystemDialogsCloser: SystemDialogsCloser
+
+    @Mock lateinit var mDreamOverlayCallbackController: DreamOverlayCallbackController
+
+    private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
+    private lateinit var communalRepository: FakeCommunalRepository
+
+    @Captor var mViewCaptor: ArgumentCaptor<View>? = null
+    private lateinit var mService: DreamOverlayService
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+
+        lifecycleRegistry = FakeLifecycleRegistry(mLifecycleOwner)
+        bouncerRepository = kosmos.fakeKeyguardBouncerRepository
+        communalRepository = kosmos.fakeCommunalRepository
+
+        whenever(mDreamOverlayComponent.getDreamOverlayContainerViewController())
+            .thenReturn(mDreamOverlayContainerViewController)
+        whenever(mComplicationComponent.getComplicationHostViewController())
+            .thenReturn(mComplicationHostViewController)
+        whenever(mLifecycleOwner.registry).thenReturn(lifecycleRegistry)
+        whenever(mComplicationComponentFactory.create(any(), any(), any(), any()))
+            .thenReturn(mComplicationComponent)
+        whenever(mComplicationComponent.getVisibilityController())
+            .thenReturn(mComplicationVisibilityController)
+        whenever(mDreamComplicationComponent.getHideComplicationTouchHandler())
+            .thenReturn(mHideComplicationTouchHandler)
+        whenever(mDreamComplicationComponentFactory.create(any(), any()))
+            .thenReturn(mDreamComplicationComponent)
+        whenever(mDreamOverlayComponentFactory.create(any(), any(), any()))
+            .thenReturn(mDreamOverlayComponent)
+        whenever(mAmbientTouchComponentFactory.create(any(), any()))
+            .thenReturn(mAmbientTouchComponent)
+        whenever(mAmbientTouchComponent.getTouchMonitor()).thenReturn(mTouchMonitor)
+        whenever(mDreamOverlayContainerViewController.containerView)
+            .thenReturn(mDreamOverlayContainerView)
+        whenever(mScrimManager.getCurrentController()).thenReturn(mScrimController)
+        mWindowParams = WindowManager.LayoutParams()
+        mService =
+            DreamOverlayService(
+                mContext,
+                mLifecycleOwner,
+                mMainExecutor,
+                mWindowManager,
+                mComplicationComponentFactory,
+                mDreamComplicationComponentFactory,
+                mDreamOverlayComponentFactory,
+                mAmbientTouchComponentFactory,
+                mStateController,
+                mKeyguardUpdateMonitor,
+                mScrimManager,
+                kosmos.communalInteractor,
+                mSystemDialogsCloser,
+                mUiEventLogger,
+                mTouchInsetManager,
+                LOW_LIGHT_COMPONENT,
+                HOME_CONTROL_PANEL_DREAM_COMPONENT,
+                mDreamOverlayCallbackController,
+                kosmos.keyguardInteractor,
+                WINDOW_NAME
+            )
+    }
+
+    private val client: IDreamOverlayClient
+        get() {
+            mService.onCreate()
+            TestableLooper.get(this).processAllMessages()
+
+            val proxy = mService.onBind(Intent())
+            val overlay = IDreamOverlay.Stub.asInterface(proxy)
+            val callback = Mockito.mock(IDreamOverlayClientCallback::class.java)
+            overlay.getClient(callback)
+            val clientCaptor = ArgumentCaptor.forClass(IDreamOverlayClient::class.java)
+            verify(callback).onDreamOverlayClient(clientCaptor.capture())
+            return clientCaptor.value
+        }
+
+    @Test
+    fun testOnStartMetricsLogged() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        verify(mUiEventLogger).log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_ENTER_START)
+        verify(mUiEventLogger)
+            .log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START)
+    }
+
+    @Test
+    fun testOverlayContainerViewAddedToWindow() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        verify(mWindowManager).addView(any(), any())
+    }
+
+    // Validates that {@link DreamOverlayService} properly handles the case where the dream's
+    // window is no longer valid by the time start is called.
+    @Test
+    fun testInvalidWindowAddStart() {
+        val client = client
+        Mockito.doThrow(WindowManager.BadTokenException())
+            .`when`(mWindowManager)
+            .addView(any(), any())
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        verify(mWindowManager).addView(any(), any())
+        verify(mStateController).setOverlayActive(false)
+        verify(mStateController).setLowLightActive(false)
+        verify(mStateController).setEntryAnimationsFinished(false)
+        verify(mStateController, Mockito.never()).setOverlayActive(true)
+        verify(mUiEventLogger, Mockito.never())
+            .log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START)
+        verify(mDreamOverlayCallbackController, Mockito.never()).onStartDream()
+    }
+
+    @Test
+    fun testDreamOverlayContainerViewControllerInitialized() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        verify(mDreamOverlayContainerViewController).init()
+    }
+
+    @Test
+    fun testDreamOverlayContainerViewRemovedFromOldParentWhenInitialized() {
+        whenever(mDreamOverlayContainerView.parent)
+            .thenReturn(mDreamOverlayContainerViewParent)
+            .thenReturn(null)
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        verify(mDreamOverlayContainerViewParent).removeView(mDreamOverlayContainerView)
+    }
+
+    @Test
+    fun testShouldShowComplicationsSetByStartDream() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            true /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(mService.shouldShowComplications()).isTrue()
+    }
+
+    @Test
+    fun testLowLightSetByStartDream() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            LOW_LIGHT_COMPONENT.flattenToString(),
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(mService.dreamComponent).isEqualTo(LOW_LIGHT_COMPONENT)
+        verify(mStateController).setLowLightActive(true)
+    }
+
+    @Test
+    fun testHomeControlPanelSetsByStartDream() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            HOME_CONTROL_PANEL_DREAM_COMPONENT.flattenToString(),
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(mService.dreamComponent).isEqualTo(HOME_CONTROL_PANEL_DREAM_COMPONENT)
+        verify(mStateController).setHomeControlPanelActive(true)
+    }
+
+    @Test
+    fun testOnEndDream() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            LOW_LIGHT_COMPONENT.flattenToString(),
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        // Verify view added.
+        verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+
+        // Service destroyed.
+        mService.onEndDream()
+        mMainExecutor.runAllReady()
+
+        // Verify view removed.
+        verify(mWindowManager).removeView(mViewCaptor!!.value)
+
+        // Verify state correctly set.
+        verify(mStateController).setOverlayActive(false)
+        verify(mStateController).setLowLightActive(false)
+        verify(mStateController).setEntryAnimationsFinished(false)
+    }
+
+    @Test
+    fun testImmediateEndDream() {
+        val client = client
+
+        // 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.
+        val inOrder = Mockito.inOrder(mWindowManager)
+        inOrder.verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+        inOrder.verify(mWindowManager).removeView(mViewCaptor!!.value)
+    }
+
+    @Test
+    fun testEndDreamDuringStartDream() {
+        val client = client
+
+        // Schedule the endDream call in the middle of the startDream implementation, as any
+        // ordering is possible.
+        Mockito.doAnswer {
+                client.endDream()
+                null
+            }
+            .`when`(mStateController)
+            .setOverlayActive(true)
+
+        // Start the dream.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        // The overlay starts then finishes.
+        val inOrder = Mockito.inOrder(mWindowManager)
+        inOrder.verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+        inOrder.verify(mWindowManager).removeView(mViewCaptor!!.value)
+    }
+
+    @Test
+    fun testDestroy() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            LOW_LIGHT_COMPONENT.flattenToString(),
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        // Verify view added.
+        verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+
+        // Service destroyed.
+        mService.onDestroy()
+        mMainExecutor.runAllReady()
+
+        // Verify view removed.
+        verify(mWindowManager).removeView(mViewCaptor!!.value)
+
+        // Verify state correctly set.
+        verify(mKeyguardUpdateMonitor).removeCallback(any())
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.DESTROYED)
+        verify(mStateController).setOverlayActive(false)
+        verify(mStateController).setLowLightActive(false)
+        verify(mStateController).setEntryAnimationsFinished(false)
+    }
+
+    @Test
+    fun testDoNotRemoveViewOnDestroyIfOverlayNotStarted() {
+        // Service destroyed without ever starting dream.
+        mService.onDestroy()
+        mMainExecutor.runAllReady()
+
+        // Verify no view is removed.
+        verify(mWindowManager, Mockito.never()).removeView(any())
+
+        // Verify state still correctly set.
+        verify(mKeyguardUpdateMonitor).removeCallback(any())
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.DESTROYED)
+        verify(mStateController).setOverlayActive(false)
+        verify(mStateController).setLowLightActive(false)
+    }
+
+    @Test
+    fun testDecorViewNotAddedToWindowAfterDestroy() {
+        val client = client
+
+        // Destroy the service.
+        mService.onDestroy()
+        mMainExecutor.runAllReady()
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        verify(mWindowManager, Mockito.never()).addView(any(), any())
+    }
+
+    @Test
+    fun testNeverRemoveDecorViewIfNotAdded() {
+        // Service destroyed before dream started.
+        mService.onDestroy()
+        mMainExecutor.runAllReady()
+        verify(mWindowManager, Mockito.never()).removeView(any())
+    }
+
+    @Test
+    fun testResetCurrentOverlayWhenConnectedToNewDream() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        // Verify that a new window is added.
+        verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+        val windowDecorView = mViewCaptor!!.value
+
+        // Assert that the overlay is not showing complications.
+        assertThat(mService.shouldShowComplications()).isFalse()
+        Mockito.clearInvocations(mDreamOverlayComponent)
+        Mockito.clearInvocations(mAmbientTouchComponent)
+        Mockito.clearInvocations(mWindowManager)
+
+        // New dream starting with dream complications showing. Note that when a new dream is
+        // binding to the dream overlay service, it receives the same instance of IBinder as the
+        // first one.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            true /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        // Assert that the overlay is showing complications.
+        assertThat(mService.shouldShowComplications()).isTrue()
+
+        // Verify that the old overlay window has been removed, and a new one created.
+        verify(mWindowManager).removeView(windowDecorView)
+        verify(mWindowManager).addView(any(), any())
+
+        // Verify that new instances of overlay container view controller and overlay touch monitor
+        // are created.
+        verify(mDreamOverlayComponent).getDreamOverlayContainerViewController()
+        verify(mAmbientTouchComponent).getTouchMonitor()
+    }
+
+    @Test
+    fun testWakeUp() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            true /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        mService.onWakeUp()
+        verify(mDreamOverlayContainerViewController).wakeUp()
+        verify(mDreamOverlayCallbackController).onWakeUp()
+    }
+
+    @Test
+    fun testWakeUpBeforeStartDoesNothing() {
+        mService.onWakeUp()
+        verify(mDreamOverlayContainerViewController, Mockito.never()).wakeUp()
+    }
+
+    @Test
+    fun testSystemFlagShowForAllUsersSetOnWindow() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        val paramsCaptor = ArgumentCaptor.forClass(WindowManager.LayoutParams::class.java)
+
+        // Verify that a new window is added.
+        verify(mWindowManager).addView(any(), paramsCaptor.capture())
+        assertThat(
+                paramsCaptor.value.privateFlags and
+                    WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS ==
+                    WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
+            )
+            .isTrue()
+    }
+
+    // Tests that the bouncer closes when DreamOverlayService is told that the dream is coming to
+    // the front.
+    @Test
+    fun testBouncerRetractedWhenDreamComesToFront() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            true /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        whenever(mDreamOverlayContainerViewController.isBouncerShowing()).thenReturn(true)
+        mService!!.onComeToFront()
+        verify(mScrimController).expand(any())
+    }
+
+    // Tests that glanceable hub is hidden when DreamOverlayService is told that the dream is
+    // coming to the front.
+    @Test
+    fun testGlanceableHubHiddenWhenDreamComesToFront() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            true /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        mService!!.onComeToFront()
+        assertThat(communalRepository.currentScene.value).isEqualTo(CommunalScenes.Blank)
+    }
+
+    // Tests that system dialogs (e.g. notification shade) closes when DreamOverlayService is told
+    // that the dream is coming to the front.
+    @Test
+    fun testSystemDialogsClosedWhenDreamComesToFront() {
+        val client = client
+
+        // Inform the overlay service of dream starting.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            true /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+
+        mService!!.onComeToFront()
+        verify(mSystemDialogsCloser).closeSystemDialogs()
+    }
+
+    @Test
+    fun testLifecycle_createdAfterConstruction() {
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.CREATED)
+    }
+
+    @Test
+    fun testLifecycle_resumedAfterDreamStarts() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.mLifecycles)
+            .containsExactly(
+                Lifecycle.State.CREATED,
+                Lifecycle.State.STARTED,
+                Lifecycle.State.RESUMED
+            )
+    }
+
+    @Test
+    fun testLifecycle_destroyedAfterOnDestroy() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        mService.onDestroy()
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.mLifecycles)
+            .containsExactly(
+                Lifecycle.State.CREATED,
+                Lifecycle.State.STARTED,
+                Lifecycle.State.RESUMED,
+                Lifecycle.State.DESTROYED
+            )
+    }
+
+    @Test
+    fun testNotificationShadeShown_setsLifecycleState() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+        val callbackCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+        verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture())
+
+        // Notification shade opens.
+        callbackCaptor.value.onShadeExpandedChanged(true)
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes from resumed back to started when the notification shade shows.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+        // Notification shade closes.
+        callbackCaptor.value.onShadeExpandedChanged(false)
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes back to RESUMED.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+    }
+
+    @Test
+    fun testBouncerShown_setsLifecycleState() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+
+        // Bouncer shows.
+        bouncerRepository.setPrimaryShow(true)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes from resumed back to started when the notification shade shows.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+        // Bouncer closes.
+        bouncerRepository.setPrimaryShow(false)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes back to RESUMED.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+    }
+
+    @Test
+    fun testCommunalVisible_setsLifecycleState() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+        val transitionState: MutableStateFlow<ObservableTransitionState> =
+            MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))
+        communalRepository.setTransitionState(transitionState)
+
+        // Communal becomes visible.
+        transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes from resumed back to started when the notification shade shows.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+        // Communal closes.
+        transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes back to RESUMED.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+    }
+
+    // Verifies the dream's lifecycle
+    @Test
+    fun testLifecycleStarted_whenAnyOcclusion() {
+        val client = client
+
+        // Inform the overlay service of dream starting. Do not show dream complications.
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+        val transitionState: MutableStateFlow<ObservableTransitionState> =
+            MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))
+        communalRepository.setTransitionState(transitionState)
+
+        // Communal becomes visible.
+        transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes from resumed back to started when the notification shade shows.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+        // Communal closes.
+        transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Lifecycle state goes back to RESUMED.
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+    }
+
+    internal class FakeLifecycleRegistry(provider: LifecycleOwner) : LifecycleRegistry(provider) {
+        val mLifecycles: MutableList<State> = ArrayList()
+
+        override var currentState: State
+            get() = mLifecycles[mLifecycles.size - 1]
+            set(state) {
+                mLifecycles.add(state)
+            }
+    }
+
+    companion object {
+        private val LOW_LIGHT_COMPONENT = ComponentName("package", "lowlight")
+        private val HOME_CONTROL_PANEL_DREAM_COMPONENT =
+            ComponentName("package", "homeControlPanel")
+        private const val DREAM_COMPONENT = "package/dream"
+        private const val WINDOW_NAME = "test"
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 39db2be..f561c53 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -36,11 +36,8 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.hardware.SensorPrivacyManager;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
 import android.provider.Settings;
+import android.testing.TestableLooper;
 import android.view.View;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -51,6 +48,7 @@
 import com.android.systemui.log.core.FakeLogBuffer;
 import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -72,6 +70,7 @@
 import java.util.concurrent.Executor;
 
 @SmallTest
[email protected](setAsMainLooper = true)
 @RunWith(AndroidJUnit4.class)
 public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
     private static final String NOTIFICATION_INDICATOR_FORMATTER_STRING =
@@ -80,12 +79,6 @@
     @Mock
     MockDreamOverlayStatusBarView mView;
     @Mock
-    ConnectivityManager mConnectivityManager;
-    @Mock
-    NetworkCapabilities mNetworkCapabilities;
-    @Mock
-    Network mNetwork;
-    @Mock
     TouchInsetManager.TouchInsetSession mTouchSession;
     @Mock
     Resources mResources;
@@ -121,6 +114,8 @@
 
     private final Executor mMainExecutor = Runnable::run;
 
+    private final FakeWifiRepository mWifiRepository = new FakeWifiRepository();
+
     DreamOverlayStatusBarViewController mController;
 
     @Before
@@ -137,7 +132,6 @@
                 mView,
                 mResources,
                 mMainExecutor,
-                mConnectivityManager,
                 mTouchSession,
                 mAlarmManager,
                 mNextAlarmController,
@@ -149,6 +143,7 @@
                 mDreamOverlayStatusBarItemsProvider,
                 mDreamOverlayStateController,
                 mUserTracker,
+                mWifiRepository,
                 mLogBuffer);
     }
 
@@ -164,42 +159,24 @@
     }
 
     @Test
-    public void testOnViewAttachedRegistersNetworkCallback() {
+    public void testWifiIconShownWhenWifiUnavailable() {
         mController.onViewAttached();
-        verify(mConnectivityManager)
-                .registerNetworkCallback(any(NetworkRequest.class), any(
-                        ConnectivityManager.NetworkCallback.class));
-    }
+        mController.updateWifiUnavailableStatusIcon(false);
 
-    @Test
-    public void testOnViewAttachedShowsWifiIconWhenWifiUnavailable() {
-        when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
-                .thenReturn(false);
-        when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
-        mController.onViewAttached();
         verify(mView).showIcon(
                 DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
     }
 
     @Test
-    public void testOnViewAttachedHidesWifiIconWhenWifiAvailable() {
-        when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
-                .thenReturn(true);
-        when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
+    public void testWifiIconHiddenWhenWifiAvailable() {
         mController.onViewAttached();
+        mController.updateWifiUnavailableStatusIcon(true);
+
         verify(mView).showIcon(
                 DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
     }
 
     @Test
-    public void testOnViewAttachedShowsWifiIconWhenNetworkCapabilitiesUnavailable() {
-        when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(null);
-        mController.onViewAttached();
-        verify(mView).showIcon(
-                DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
-    }
-
-    @Test
     public void testOnViewAttachedShowsAlarmIconWhenAlarmExists() {
         final AlarmManager.AlarmClockInfo alarmClockInfo =
                 new AlarmManager.AlarmClockInfo(1L, null);
@@ -282,7 +259,6 @@
                 mView,
                 mResources,
                 mMainExecutor,
-                mConnectivityManager,
                 mTouchSession,
                 mAlarmManager,
                 mNextAlarmController,
@@ -294,6 +270,7 @@
                 mDreamOverlayStatusBarItemsProvider,
                 mDreamOverlayStateController,
                 mUserTracker,
+                mWifiRepository,
                 mLogBuffer);
         controller.onViewAttached();
         verify(mView, never()).showIcon(
@@ -319,13 +296,6 @@
     }
 
     @Test
-    public void testOnViewDetachedUnregistersNetworkCallback() {
-        mController.onViewDetached();
-        verify(mConnectivityManager)
-                .unregisterNetworkCallback(any(ConnectivityManager.NetworkCallback.class));
-    }
-
-    @Test
     public void testOnViewDetachedRemovesCallbacks() {
         mController.onViewDetached();
         verify(mNextAlarmController).removeCallback(any());
@@ -343,61 +313,6 @@
     }
 
     @Test
-    public void testWifiIconHiddenWhenWifiBecomesAvailable() {
-        // Make sure wifi starts out unavailable when onViewAttached is called, and then returns
-        // true on the second query.
-        when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
-                .thenReturn(false).thenReturn(true);
-        when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
-        mController.onViewAttached();
-
-        final ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackCapture =
-                ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
-        verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
-        callbackCapture.getValue().onAvailable(mNetwork);
-
-        verify(mView).showIcon(
-                DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
-    }
-
-    @Test
-    public void testWifiIconShownWhenWifiBecomesUnavailable() {
-        // Make sure wifi starts out available when onViewAttached is called, then returns false
-        // on the second query.
-        when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
-                .thenReturn(true).thenReturn(false);
-        when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
-        mController.onViewAttached();
-
-        final ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackCapture =
-                ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
-        verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
-        callbackCapture.getValue().onLost(mNetwork);
-
-        verify(mView).showIcon(
-                DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
-    }
-
-    @Test
-    public void testWifiIconHiddenWhenCapabilitiesChange() {
-        // Make sure wifi starts out unavailable when onViewAttached is called.
-        when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
-                .thenReturn(false);
-        when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
-        mController.onViewAttached();
-
-        final ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackCapture =
-                ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
-        verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
-        when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
-                .thenReturn(true);
-        callbackCapture.getValue().onCapabilitiesChanged(mNetwork, mNetworkCapabilities);
-
-        verify(mView).showIcon(
-                DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
-    }
-
-    @Test
     public void testNotificationsIconShownWhenNotificationAdded() {
         mController.onViewAttached();
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
index 315a24b..8481586 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.dreams.complication;
 
+import static com.android.systemui.Flags.FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
@@ -23,6 +25,8 @@
 import static org.mockito.Mockito.when;
 
 import android.os.Handler;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.view.MotionEvent;
 import android.view.View;
 
@@ -31,9 +35,9 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.ambient.touch.TouchHandler;
 import com.android.systemui.complication.Complication;
 import com.android.systemui.dreams.DreamOverlayStateController;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
 import com.android.systemui.shared.system.InputChannelCompat;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.touch.TouchInsetManager;
@@ -70,7 +74,7 @@
     MotionEvent mMotionEvent;
 
     @Mock
-    DreamTouchHandler.TouchSession mSession;
+    TouchHandler.TouchSession mSession;
 
     @Mock
     DreamOverlayStateController mStateController;
@@ -90,6 +94,7 @@
      * Ensures no actions are taken when there multiple sessions.
      */
     @Test
+    @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH)
     public void testSessionEndOnMultipleSessions() {
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
@@ -122,6 +127,7 @@
      * Ensures no actions are taken when the bouncer is showing.
      */
     @Test
+    @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH)
     public void testSessionEndWhenBouncerShowing() {
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
@@ -154,6 +160,7 @@
      * Ensures no actions are taken when there multiple sessions.
      */
     @Test
+    @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH)
     public void testSessionEndWithTouchInInset() {
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
@@ -202,6 +209,7 @@
      * Make sure visibility changes are triggered from session events.
      */
     @Test
+    @DisableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH)
     public void testSessionLifecycle() {
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
@@ -259,4 +267,34 @@
         // Verify session ended.
         verify(mSession).pop();
     }
+
+    @Test
+    @EnableFlags(FLAG_REMOVE_DREAM_OVERLAY_HIDE_ON_TOUCH)
+    public void testNoActionWhenDisabledByFlag() {
+        final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
+                mVisibilityController,
+                RESTORE_TIMEOUT,
+                HIDE_DELAY,
+                mTouchInsetManager,
+                mStatusBarKeyguardViewManager,
+                mFakeExecutor,
+                mStateController);
+
+        // Report one session.
+        when(mSession.getActiveSessionCount()).thenReturn(1);
+
+        // Bouncer is showing.
+        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
+
+        // Start session.
+        touchHandler.onSessionStart(mSession);
+
+        // Verify session end.
+        verify(mSession).pop();
+
+        mClock.advanceTime(HIDE_DELAY);
+
+        // Verify no interaction with visibility controller.
+        verify(mVisibilityController, never()).setVisibility(anyInt());
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
deleted file mode 100644
index 0f8fc38..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ /dev/null
@@ -1,654 +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.dreams.touch;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyFloat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.pm.UserInfo;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.view.GestureDetector;
-import android.view.GestureDetector.OnGestureListener;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
-import com.android.systemui.dreams.touch.scrim.ScrimController;
-import com.android.systemui.dreams.touch.scrim.ScrimManager;
-import com.android.systemui.settings.FakeUserTracker;
-import com.android.systemui.shade.ShadeExpansionChangeEvent;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.wm.shell.animation.FlingAnimationUtils;
-
-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.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Collections;
-import java.util.Optional;
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
-    @Mock
-    CentralSurfaces mCentralSurfaces;
-
-    @Mock
-    ScrimManager mScrimManager;
-
-    @Mock
-    ScrimController mScrimController;
-
-    @Mock
-    NotificationShadeWindowController mNotificationShadeWindowController;
-
-    @Mock
-    FlingAnimationUtils mFlingAnimationUtils;
-
-    @Mock
-    FlingAnimationUtils mFlingAnimationUtilsClosing;
-
-    @Mock
-    DreamTouchHandler.TouchSession mTouchSession;
-
-    BouncerSwipeTouchHandler mTouchHandler;
-
-    @Mock
-    BouncerSwipeTouchHandler.ValueAnimatorCreator mValueAnimatorCreator;
-
-    @Mock
-    ValueAnimator mValueAnimator;
-
-    @Mock
-    BouncerSwipeTouchHandler.VelocityTrackerFactory mVelocityTrackerFactory;
-
-    @Mock
-    VelocityTracker mVelocityTracker;
-
-    @Mock
-    UiEventLogger mUiEventLogger;
-
-    @Mock
-    LockPatternUtils mLockPatternUtils;
-
-    @Mock
-    Region mRegion;
-
-    @Captor
-    ArgumentCaptor<Rect> mRectCaptor;
-
-    FakeUserTracker mUserTracker;
-
-    private static final float TOUCH_REGION = .3f;
-    private static final int SCREEN_WIDTH_PX = 1024;
-    private static final int SCREEN_HEIGHT_PX = 100;
-    private static final float MIN_BOUNCER_HEIGHT = .05f;
-
-    private static final Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100);
-    private static final UserInfo CURRENT_USER_INFO = new UserInfo(
-            10,
-            /* name= */ "user10",
-            /* flags= */ 0
-    );
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mUserTracker = new FakeUserTracker();
-        mTouchHandler = new BouncerSwipeTouchHandler(
-                mScrimManager,
-                Optional.of(mCentralSurfaces),
-                mNotificationShadeWindowController,
-                mValueAnimatorCreator,
-                mVelocityTrackerFactory,
-                mLockPatternUtils,
-                mUserTracker,
-                mFlingAnimationUtils,
-                mFlingAnimationUtilsClosing,
-                TOUCH_REGION,
-                MIN_BOUNCER_HEIGHT,
-                mUiEventLogger);
-
-        when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
-        when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
-        when(mVelocityTrackerFactory.obtain()).thenReturn(mVelocityTracker);
-        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
-        when(mTouchSession.getBounds()).thenReturn(SCREEN_BOUNDS);
-        when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(true);
-
-        mUserTracker.set(Collections.singletonList(CURRENT_USER_INFO), 0);
-    }
-
-    /**
-     * Ensures expansion only happens when touch down happens in valid part of the screen.
-     */
-    @Test
-    public void testSessionStart() {
-        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, null);
-
-        verify(mRegion).union(mRectCaptor.capture());
-        final Rect bounds = mRectCaptor.getValue();
-
-        final Rect expected = new Rect();
-
-        expected.set(0, Math.round(SCREEN_HEIGHT_PX * (1 - TOUCH_REGION)), SCREEN_WIDTH_PX,
-                SCREEN_HEIGHT_PX);
-
-        assertThat(bounds).isEqualTo(expected);
-
-        mTouchHandler.onSessionStart(mTouchSession);
-        verify(mNotificationShadeWindowController).setForcePluginOpen(eq(true), any());
-        ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor =
-                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-        verify(mTouchSession).registerInputListener(eventListenerCaptor.capture());
-
-        // A touch within range at the bottom of the screen should trigger listening
-        assertThat(gestureListenerCaptor.getValue()
-                .onScroll(Mockito.mock(MotionEvent.class),
-                        Mockito.mock(MotionEvent.class),
-                        1,
-                        2)).isTrue();
-    }
-
-    private enum Direction {
-        DOWN,
-        UP,
-    }
-
-    @Test
-    public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() {
-        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
-                new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX));
-        verify(mRegion).union(mRectCaptor.capture());
-        final Rect bounds = mRectCaptor.getValue();
-
-        final Rect expected = new Rect();
-        final float minBouncerHeight =
-                SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT;
-        final int minAllowableBottom = SCREEN_HEIGHT_PX - Math.round(minBouncerHeight);
-
-        expected.set(0, minAllowableBottom , SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
-
-        assertThat(bounds).isEqualTo(expected);
-
-        onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController);
-    }
-
-    @Test
-    public void testSwipeUp_exclusionRectAtTop_doesNotIntersectGestureArea() {
-        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
-                new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX / 4));
-        verify(mRegion).union(mRectCaptor.capture());
-        final Rect bounds = mRectCaptor.getValue();
-
-        final Rect expected = new Rect();
-        final int gestureAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION);
-        expected.set(0, gestureAreaTop, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
-
-        assertThat(bounds).isEqualTo(expected);
-        onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController);
-    }
-
-    @Test
-    public void testSwipeUp_exclusionRectBetweenNormalAndMinimumSwipeArea() {
-        final int normalSwipeAreaTop = SCREEN_HEIGHT_PX
-                - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION);
-        final int minimumSwipeAreaTop = SCREEN_HEIGHT_PX
-                - Math.round(SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT);
-
-        Rect exclusionRect = new Rect(0, 0, SCREEN_WIDTH_PX,
-                (normalSwipeAreaTop + minimumSwipeAreaTop) / 2);
-
-        mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, exclusionRect);
-
-        verify(mRegion).union(mRectCaptor.capture());
-
-        final Rect bounds = mRectCaptor.getValue();
-        final Rect expected = new Rect();
-
-        final int expectedSwipeAreaBottom = exclusionRect.bottom;
-        expected.set(0, expectedSwipeAreaBottom, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
-
-        assertThat(bounds).isEqualTo(expected);
-
-        onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController);
-    }
-
-    private static void onSessionStartHelper(BouncerSwipeTouchHandler touchHandler,
-            DreamTouchHandler.TouchSession touchSession,
-            NotificationShadeWindowController notificationShadeWindowController) {
-        touchHandler.onSessionStart(touchSession);
-        verify(notificationShadeWindowController).setForcePluginOpen(eq(true), any());
-        ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor =
-                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(touchSession).registerGestureListener(gestureListenerCaptor.capture());
-        verify(touchSession).registerInputListener(eventListenerCaptor.capture());
-
-        // A touch within range at the bottom of the screen should trigger listening
-        assertThat(gestureListenerCaptor.getValue()
-                .onScroll(Mockito.mock(MotionEvent.class),
-                        Mockito.mock(MotionEvent.class),
-                        1,
-                        2)).isTrue();
-    }
-
-    /**
-     * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount.
-     */
-    @Test
-    public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion() {
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
-        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
-        final float percent = .3f;
-        final float distanceY = SCREEN_HEIGHT_PX * percent;
-
-        // Swiping up near the top of the screen where the touch initiation region is.
-        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, distanceY, 0);
-        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, 0, 0);
-
-        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
-                .isTrue();
-
-        verify(mScrimController, never()).expand(any());
-    }
-
-    /**
-     * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
-     */
-    @Test
-    public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion() {
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
-        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
-        final float percent = .15f;
-        final float distanceY = SCREEN_HEIGHT_PX * percent;
-
-        // Swiping down near the bottom of the screen where the touch initiation region is.
-        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, SCREEN_HEIGHT_PX - distanceY, 0);
-        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, SCREEN_HEIGHT_PX, 0);
-
-        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
-                .isTrue();
-
-        verify(mScrimController, never()).expand(any());
-    }
-
-    /**
-     * Makes sure the expansion amount is proportional to (1 - scroll).
-     */
-    @Test
-    public void testSwipeUp_setsCorrectExpansionAmount() {
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
-        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
-        verifyScroll(.3f, Direction.UP, false, gestureListener);
-
-        // Ensure that subsequent gestures are treated as expanding even if the bouncer state
-        // changes.
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-        verifyScroll(.7f, Direction.UP, false, gestureListener);
-    }
-
-    /**
-     * Makes sure the expansion amount is proportional to scroll.
-     */
-    @Test
-    public void testSwipeDown_setsCorrectExpansionAmount() {
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
-        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
-        verifyScroll(.3f, Direction.DOWN, true, gestureListener);
-
-        // Ensure that subsequent gestures are treated as collapsing even if the bouncer state
-        // changes.
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
-        verifyScroll(.7f, Direction.DOWN, true, gestureListener);
-    }
-
-    /**
-     * Verifies that swiping up when the lock pattern is not secure dismissed dream and consumes
-     * the gesture.
-     */
-    @Test
-    public void testSwipeUp_keyguardNotSecure_doesNotExpand() {
-        when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(false);
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
-        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
-        final float distanceY = SCREEN_HEIGHT_PX * 0.3f;
-        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, SCREEN_HEIGHT_PX, 0);
-        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, SCREEN_HEIGHT_PX - distanceY, 0);
-
-        reset(mScrimController);
-
-        // Scroll gesture is consumed.
-        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
-                .isTrue();
-        // We should not expand since the keyguard is not secure
-        verify(mScrimController, never()).expand(any());
-        // Since we are swiping up, we should wake from dreams.
-        verify(mCentralSurfaces).awakenDreams();
-    }
-
-    /**
-     * Verifies that swiping down when the lock pattern is not secure does not dismiss the dream.
-     */
-    @Test
-    public void testSwipeDown_keyguardNotSecure_doesNotExpand() {
-        when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(false);
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
-        final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
-        final float distanceY = SCREEN_HEIGHT_PX * 0.3f;
-        // Swiping down near the bottom of the screen where the touch initiation region is.
-        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, SCREEN_HEIGHT_PX - distanceY, 0);
-        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, SCREEN_HEIGHT_PX, 0);
-
-        reset(mScrimController);
-
-        // Scroll gesture is not consumed.
-        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
-                .isTrue();
-        // We should not expand since the keyguard is not secure
-        verify(mScrimController, never()).expand(any());
-        // Since we are swiping down, we should not dismiss the dream.
-        verify(mCentralSurfaces, never()).awakenDreams();
-    }
-
-    private void verifyScroll(float percent, Direction direction,
-            boolean isBouncerInitiallyShowing, GestureDetector.OnGestureListener gestureListener) {
-        final float distanceY = SCREEN_HEIGHT_PX * percent;
-
-        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, direction == Direction.UP ? SCREEN_HEIGHT_PX : 0, 0);
-        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
-
-        reset(mScrimController);
-        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
-                .isTrue();
-
-        // Ensure only called once
-        verify(mScrimController).expand(any());
-
-        final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent;
-        final float dragDownAmount = event2.getY() - event1.getY();
-
-        // Ensure correct expansion passed in.
-        ShadeExpansionChangeEvent event =
-                new ShadeExpansionChangeEvent(
-                        expansion, /* expanded= */ false, /* tracking= */ true);
-        verify(mScrimController).expand(event);
-    }
-
-    /**
-     * Tests that ending an upward swipe before the set threshold leads to bouncer collapsing down.
-     */
-    @Test
-    public void testSwipeUpPositionBelowThreshold_collapsesBouncer() {
-        final float swipeUpPercentage = .3f;
-        final float expansion = 1 - swipeUpPercentage;
-        // The upward velocity is ignored.
-        final float velocityY = -1;
-        swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
-
-        verify(mValueAnimatorCreator).create(eq(expansion),
-                eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
-        verify(mValueAnimator, never()).addListener(any());
-
-        verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
-                eq(SCREEN_HEIGHT_PX * expansion),
-                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
-                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
-        verify(mValueAnimator).start();
-        verify(mUiEventLogger, never()).log(any());
-    }
-
-    /**
-     * Tests that ending an upward swipe above the set threshold will continue the expansion.
-     */
-    @Test
-    public void testSwipeUpPositionAboveThreshold_expandsBouncer() {
-        final float swipeUpPercentage = .7f;
-        final float expansion = 1 - swipeUpPercentage;
-        // The downward velocity is ignored.
-        final float velocityY = 1;
-        swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
-
-        verify(mValueAnimatorCreator).create(eq(expansion),
-                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
-
-        ArgumentCaptor<AnimatorListenerAdapter> endAnimationListenerCaptor =
-                ArgumentCaptor.forClass(AnimatorListenerAdapter.class);
-        verify(mValueAnimator).addListener(endAnimationListenerCaptor.capture());
-        AnimatorListenerAdapter endAnimationListener = endAnimationListenerCaptor.getValue();
-
-        verify(mFlingAnimationUtils).apply(eq(mValueAnimator), eq(SCREEN_HEIGHT_PX * expansion),
-                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
-                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
-        verify(mValueAnimator).start();
-        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_SWIPED);
-
-        endAnimationListener.onAnimationEnd(mValueAnimator);
-        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
-    }
-
-    /**
-     * Tests that ending a downward swipe above the set threshold will continue the expansion,
-     * but will not trigger logging of the DREAM_SWIPED event.
-     */
-    @Test
-    public void testSwipeDownPositionAboveThreshold_expandsBouncer_doesNotLog() {
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
-        final float swipeDownPercentage = .3f;
-        // The downward velocity is ignored.
-        final float velocityY = 1;
-        swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);
-
-        verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
-                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
-        verify(mValueAnimator, never()).addListener(any());
-
-        verify(mFlingAnimationUtils).apply(eq(mValueAnimator),
-                eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
-                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
-                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
-        verify(mValueAnimator).start();
-        verify(mUiEventLogger, never()).log(any());
-    }
-
-    /**
-     * Tests that swiping down with a speed above the set threshold leads to bouncer collapsing
-     * down.
-     */
-    @Test
-    public void testSwipeDownVelocityAboveMin_collapsesBouncer() {
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);
-
-        // The ending position above the set threshold is ignored.
-        final float swipeDownPercentage = .3f;
-        final float velocityY = 1;
-        swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);
-
-        verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
-                eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
-        verify(mValueAnimator, never()).addListener(any());
-
-        verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
-                eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
-                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
-                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
-        verify(mValueAnimator).start();
-        verify(mUiEventLogger, never()).log(any());
-    }
-
-    /**
-     * Tests that swiping up with a speed above the set threshold will continue the expansion.
-     */
-    @Test
-    public void testSwipeUpVelocityAboveMin_expandsBouncer() {
-        when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);
-
-        // The ending position below the set threshold is ignored.
-        final float swipeUpPercentage = .3f;
-        final float expansion = 1 - swipeUpPercentage;
-        final float velocityY = -1;
-        swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
-
-        verify(mValueAnimatorCreator).create(eq(expansion),
-                eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
-
-        ArgumentCaptor<AnimatorListenerAdapter> endAnimationListenerCaptor =
-                ArgumentCaptor.forClass(AnimatorListenerAdapter.class);
-        verify(mValueAnimator).addListener(endAnimationListenerCaptor.capture());
-        AnimatorListenerAdapter endAnimationListener = endAnimationListenerCaptor.getValue();
-
-        verify(mFlingAnimationUtils).apply(eq(mValueAnimator), eq(SCREEN_HEIGHT_PX * expansion),
-                eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
-                eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
-        verify(mValueAnimator).start();
-        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_SWIPED);
-
-        endAnimationListener.onAnimationEnd(mValueAnimator);
-        verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
-    }
-
-    /**
-     * Ensures {@link CentralSurfaces}
-     */
-    @Test
-    public void testInformBouncerShowingOnExpand() {
-        swipeToPosition(1f, Direction.UP, 0);
-    }
-
-    /**
-     * Ensures {@link CentralSurfaces}
-     */
-    @Test
-    public void testInformBouncerHidingOnCollapse() {
-        // Must swipe up to set initial state.
-        swipeToPosition(1f, Direction.UP, 0);
-        Mockito.clearInvocations(mCentralSurfaces);
-
-        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);
-        mTouchHandler.onSessionStart(mTouchSession);
-        ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-        verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-        ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
-                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
-        verify(mTouchSession).registerInputListener(inputEventListenerCaptor.capture());
-
-        when(mVelocityTracker.getYVelocity()).thenReturn(velocityY);
-
-        final float distanceY = SCREEN_HEIGHT_PX * percent;
-
-        final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, direction == Direction.UP ? SCREEN_HEIGHT_PX : 0, 0);
-        final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
-                0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
-
-        assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0, distanceY))
-                .isTrue();
-
-        final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
-                0, 0, 0);
-
-        inputEventListenerCaptor.getValue().onInputEvent(upEvent);
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
index 8dcf903..e3c6dee 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
@@ -31,6 +31,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.ambient.touch.TouchHandler;
 import com.android.systemui.kosmos.KosmosJavaAdapter;
 import com.android.systemui.shared.system.InputChannelCompat;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -54,7 +55,7 @@
     @Mock
     CentralSurfaces mCentralSurfaces;
     @Mock
-    DreamTouchHandler.TouchSession mTouchSession;
+    TouchHandler.TouchSession mTouchSession;
     CommunalTouchHandler mTouchHandler;
     @Mock
     Lifecycle mLifecycle;
@@ -107,7 +108,7 @@
         mTouchHandler.onSessionStart(mTouchSession);
         verify(mTouchSession).registerInputListener(inputEventListenerArgumentCaptor.capture());
         inputEventListenerArgumentCaptor.getValue().onInputEvent(motionEvent);
-        verify(mCentralSurfaces).handleDreamTouch(motionEvent);
+        verify(mCentralSurfaces).handleExternalShadeWindowTouch(motionEvent);
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
deleted file mode 100644
index 6aa821f..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.dreams.touch;
-
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.shade.ShadeViewController;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-
-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.Optional;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ShadeTouchHandlerTest extends SysuiTestCase {
-    @Mock
-    CentralSurfaces mCentralSurfaces;
-
-    @Mock
-    ShadeViewController mShadeViewController;
-
-    @Mock
-    DreamTouchHandler.TouchSession mTouchSession;
-
-    ShadeTouchHandler mTouchHandler;
-
-    private static final int TOUCH_HEIGHT = 20;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mTouchHandler = new ShadeTouchHandler(Optional.of(mCentralSurfaces), mShadeViewController,
-                TOUCH_HEIGHT);
-    }
-
-    /**
-     * Verify that touches aren't handled when the bouncer is showing.
-     */
-    @Test
-    public void testInactiveOnBouncer() {
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-        mTouchHandler.onSessionStart(mTouchSession);
-        verify(mTouchSession).pop();
-    }
-
-    /**
-     * Make sure {@link ShadeTouchHandler}
-     */
-    @Test
-    public void testTouchPilferingOnScroll() {
-        final MotionEvent motionEvent1 = Mockito.mock(MotionEvent.class);
-        final MotionEvent motionEvent2 = Mockito.mock(MotionEvent.class);
-
-        final ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerArgumentCaptor =
-                ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-
-        mTouchHandler.onSessionStart(mTouchSession);
-        verify(mTouchSession).registerGestureListener(gestureListenerArgumentCaptor.capture());
-
-        assertThat(gestureListenerArgumentCaptor.getValue()
-                .onScroll(motionEvent1, motionEvent2, 1, 1))
-                .isTrue();
-    }
-
-    /**
-     * Ensure touches are propagated to the {@link ShadeViewController}.
-     */
-    @Test
-    public void testEventPropagation() {
-        final MotionEvent motionEvent = Mockito.mock(MotionEvent.class);
-
-        final ArgumentCaptor<InputChannelCompat.InputEventListener>
-                inputEventListenerArgumentCaptor =
-                    ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
-
-        mTouchHandler.onSessionStart(mTouchSession);
-        verify(mTouchSession).registerInputListener(inputEventListenerArgumentCaptor.capture());
-        inputEventListenerArgumentCaptor.getValue().onInputEvent(motionEvent);
-        verify(mShadeViewController).handleExternalTouch(motionEvent);
-    }
-
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
deleted file mode 100644
index 7cdd478..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-
-import android.os.PowerManager;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.shade.ShadeExpansionChangeEvent;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
-
-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)
[email protected]
-public class BouncerlessScrimControllerTest extends SysuiTestCase {
-    @Mock
-    BouncerlessScrimController.Callback mCallback;
-
-    @Mock
-    PowerManager mPowerManager;
-
-    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void testWakeupOnSwipeOpen() {
-        final BouncerlessScrimController scrimController =
-                new BouncerlessScrimController(mExecutor, mPowerManager);
-        scrimController.addCallback(mCallback);
-        scrimController.expand(new ShadeExpansionChangeEvent(.5f, true, false));
-        mExecutor.runAllReady();
-        verify(mPowerManager).wakeUp(anyLong(), eq(PowerManager.WAKE_REASON_GESTURE), any());
-        verify(mCallback).onWakeup();
-    }
-
-    @Test
-    public void testExpansionPropagation() {
-        final BouncerlessScrimController scrimController =
-                new BouncerlessScrimController(mExecutor, mPowerManager);
-        scrimController.addCallback(mCallback);
-        final ShadeExpansionChangeEvent expansionEvent =
-                new ShadeExpansionChangeEvent(0.5f, false, false);
-        scrimController.expand(expansionEvent);
-        mExecutor.runAllReady();
-        verify(mCallback).onExpansion(eq(expansionEvent));
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
deleted file mode 100644
index ebbcf98..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
-
-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;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
[email protected]
-public class ScrimManagerTest extends SysuiTestCase {
-    @Mock
-    ScrimController mBouncerlessScrimController;
-
-    @Mock
-    ScrimController mBouncerScrimController;
-
-    @Mock
-    KeyguardStateController mKeyguardStateController;
-
-    @Mock
-    ScrimManager.Callback mCallback;
-
-    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void testControllerSelection() {
-        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
-        ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
-                ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
-        final ScrimManager manager = new ScrimManager(mExecutor, mBouncerScrimController,
-                mBouncerlessScrimController, mKeyguardStateController);
-        verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
-
-        assertThat(manager.getCurrentController()).isEqualTo(mBouncerScrimController);
-        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
-        callbackCaptor.getValue().onKeyguardShowingChanged();
-        mExecutor.runAllReady();
-        assertThat(manager.getCurrentController()).isEqualTo(mBouncerlessScrimController);
-    }
-
-    @Test
-    public void testCallback() {
-        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
-        ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
-                ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
-        final ScrimManager manager = new ScrimManager(mExecutor, mBouncerScrimController,
-                mBouncerlessScrimController, mKeyguardStateController);
-        verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
-
-        manager.addCallback(mCallback);
-        when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
-        callbackCaptor.getValue().onKeyguardShowingChanged();
-        mExecutor.runAllReady();
-        verify(mCallback).onScrimControllerChanged(eq(mBouncerlessScrimController));
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
index 8f03717..e332656 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
@@ -18,47 +18,35 @@
 
 import android.os.VibrationEffect
 import android.testing.TestableLooper.RunWithLooper
-import android.view.MotionEvent
-import android.view.View
-import androidx.test.core.view.MotionEventBuilder
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.AnimatorTestRule
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.testKosmos
-import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
 import org.mockito.junit.MockitoRule
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-@OptIn(ExperimentalCoroutinesApi::class)
 @RunWithLooper(setAsMainLooper = true)
 class QSLongPressEffectTest : SysuiTestCase() {
 
     @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
-    @Mock private lateinit var vibratorHelper: VibratorHelper
-    @Mock private lateinit var testView: View
     @get:Rule val animatorTestRule = AnimatorTestRule(this)
     private val kosmos = testKosmos()
+    private val vibratorHelper = kosmos.vibratorHelper
 
     private val effectDuration = 400
     private val lowTickDuration = 12
@@ -68,39 +56,90 @@
 
     @Before
     fun setup() {
-        whenever(
-                vibratorHelper.getPrimitiveDurations(
-                    VibrationEffect.Composition.PRIMITIVE_LOW_TICK,
-                    VibrationEffect.Composition.PRIMITIVE_SPIN,
-                )
-            )
-            .thenReturn(intArrayOf(lowTickDuration, spinDuration))
+        vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] =
+            lowTickDuration
+        vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_SPIN] = spinDuration
+
+        kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
 
         longPressEffect =
             QSLongPressEffect(
                 vibratorHelper,
-                effectDuration,
+                kosmos.keyguardInteractor,
             )
+        longPressEffect.initializeEffect(effectDuration)
+    }
+
+    @Test
+    fun onReset_whileIdle_resetsEffect() = testWithScope {
+        // GIVEN a call to reset
+        longPressEffect.resetEffect()
+
+        // THEN the effect remains idle and has not been initialized
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(longPressEffect.hasInitialized).isFalse()
+    }
+
+    @Test
+    fun onReset_whileRunning_resetsEffect() = testWhileRunning {
+        // GIVEN a call to reset
+        longPressEffect.resetEffect()
+
+        // THEN the effect remains idle and has not been initialized
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(longPressEffect.hasInitialized).isFalse()
+    }
+
+    @Test
+    fun onInitialize_withNegativeDuration_doesNotInitialize() = testWithScope {
+        // GIVEN an effect that has reset
+        longPressEffect.resetEffect()
+
+        // WHEN attempting to initialize with a negative duration
+        val couldInitialize = longPressEffect.initializeEffect(-1)
+
+        // THEN the effect can't initialized and remains reset
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(couldInitialize).isFalse()
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(longPressEffect.hasInitialized).isFalse()
+    }
+
+    @Test
+    fun onInitialize_withPositiveDuration_initializes() = testWithScope {
+        // GIVEN an effect that has reset
+        longPressEffect.resetEffect()
+
+        // WHEN attempting to initialize with a positive duration
+        val couldInitialize = longPressEffect.initializeEffect(effectDuration)
+
+        // THEN the effect is initialized
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(couldInitialize).isTrue()
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(longPressEffect.hasInitialized).isTrue()
     }
 
     @Test
     fun onActionDown_whileIdle_startsWait() = testWithScope {
         // GIVEN an action down event occurs
-        val downEvent = buildMotionEvent(MotionEvent.ACTION_DOWN)
-        longPressEffect.onTouch(testView, downEvent)
+        longPressEffect.handleActionDown()
 
         // THEN the effect moves to the TIMEOUT_WAIT state
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
     }
 
     @Test
     fun onActionCancel_whileWaiting_goesIdle() = testWhileWaiting {
         // GIVEN an action cancel occurs
-        val cancelEvent = buildMotionEvent(MotionEvent.ACTION_CANCEL)
-        longPressEffect.onTouch(testView, cancelEvent)
+        longPressEffect.handleActionCancel()
 
         // THEN the effect goes back to idle and does not start
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
         assertEffectDidNotStart()
     }
 
@@ -110,8 +149,7 @@
         val action by collectLastValue(longPressEffect.actionType)
 
         // GIVEN an action up occurs
-        val upEvent = buildMotionEvent(MotionEvent.ACTION_UP)
-        longPressEffect.onTouch(testView, upEvent)
+        longPressEffect.handleActionUp()
 
         // THEN the action to invoke is the click action and the effect does not start
         assertThat(action).isEqualTo(QSLongPressEffect.ActionType.CLICK)
@@ -121,7 +159,7 @@
     @Test
     fun onWaitComplete_whileWaiting_beginsEffect() = testWhileWaiting {
         // GIVEN the pressed timeout is complete
-        advanceTimeBy(QSLongPressEffect.PRESSED_TIMEOUT + 10L)
+        longPressEffect.handleTimeoutComplete()
 
         // THEN the effect starts
         assertEffectStarted()
@@ -133,8 +171,7 @@
         animatorTestRule.advanceTimeBy(effectDuration / 2L)
 
         // WHEN an action up occurs
-        val upEvent = buildMotionEvent(MotionEvent.ACTION_UP)
-        longPressEffect.onTouch(testView, upEvent)
+        longPressEffect.handleActionUp()
 
         // THEN the effect gets reversed at 50% progress
         assertEffectReverses(0.5f)
@@ -146,34 +183,44 @@
         animatorTestRule.advanceTimeBy(effectDuration / 2L)
 
         // WHEN an action cancel occurs
-        val cancelEvent = buildMotionEvent(MotionEvent.ACTION_CANCEL)
-        longPressEffect.onTouch(testView, cancelEvent)
+        longPressEffect.handleActionCancel()
 
         // THEN the effect gets reversed at 50% progress
         assertEffectReverses(0.5f)
     }
 
     @Test
-    fun onAnimationComplete_effectEnds() = testWhileRunning {
+    fun onAnimationComplete_keyguardDismissible_effectEndsWithLongPress() = testWhileRunning {
         // GIVEN that the animation completes
         animatorTestRule.advanceTimeBy(effectDuration + 10L)
 
-        // THEN the long-press effect completes
-        assertEffectCompleted()
+        // THEN the long-press effect completes with a LONG_PRESS
+        assertEffectCompleted(QSLongPressEffect.ActionType.LONG_PRESS)
     }
 
     @Test
+    fun onAnimationComplete_keyguardNotDismissible_effectEndsWithResetAndLongPress() =
+        testWhileRunning {
+            // GIVEN that the keyguard is not dismissible
+            kosmos.fakeKeyguardRepository.setKeyguardDismissible(false)
+
+            // GIVEN that the animation completes
+            animatorTestRule.advanceTimeBy(effectDuration + 10L)
+
+            // THEN the long-press effect completes with RESET_AND_LONG_PRESS
+            assertEffectCompleted(QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS)
+        }
+
+    @Test
     fun onActionDown_whileRunningBackwards_resets() = testWhileRunning {
         // GIVEN that the effect is at the middle of its completion (progress of 50%)
         animatorTestRule.advanceTimeBy(effectDuration / 2L)
 
         // GIVEN an action cancel occurs and the effect gets reversed
-        val cancelEvent = buildMotionEvent(MotionEvent.ACTION_CANCEL)
-        longPressEffect.onTouch(testView, cancelEvent)
+        longPressEffect.handleActionCancel()
 
         // GIVEN an action down occurs
-        val downEvent = buildMotionEvent(MotionEvent.ACTION_DOWN)
-        longPressEffect.onTouch(testView, downEvent)
+        longPressEffect.handleActionDown()
 
         // THEN the effect resets
         assertEffectResets()
@@ -185,40 +232,24 @@
         animatorTestRule.advanceTimeBy(effectDuration / 2L)
 
         // GIVEN an action cancel occurs and the effect gets reversed
-        val cancelEvent = buildMotionEvent(MotionEvent.ACTION_CANCEL)
-        longPressEffect.onTouch(testView, cancelEvent)
+        longPressEffect.handleActionCancel()
 
         // GIVEN that the animation completes after a sufficient amount of time
         animatorTestRule.advanceTimeBy(effectDuration.toLong())
 
         // THEN the state goes to [QSLongPressEffect.State.IDLE]
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
+        val state by collectLastValue(longPressEffect.state)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
     }
 
-    private fun buildMotionEvent(action: Int): MotionEvent =
-        MotionEventBuilder.newBuilder().setAction(action).build()
-
     private fun testWithScope(test: suspend TestScope.() -> Unit) =
-        with(kosmos) {
-            testScope.runTest {
-                // GIVEN an effect with a testing scope
-                longPressEffect.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler))
-
-                // THEN run the test
-                test()
-            }
-        }
+        with(kosmos) { testScope.runTest { test() } }
 
     private fun testWhileWaiting(test: suspend TestScope.() -> Unit) =
         with(kosmos) {
             testScope.runTest {
-                // GIVEN an effect with a testing scope
-                longPressEffect.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler))
-
                 // GIVEN the TIMEOUT_WAIT state is entered
-                val downEvent =
-                    MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_DOWN).build()
-                longPressEffect.onTouch(testView, downEvent)
+                longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT)
 
                 // THEN run the test
                 test()
@@ -228,16 +259,9 @@
     private fun testWhileRunning(test: suspend TestScope.() -> Unit) =
         with(kosmos) {
             testScope.runTest {
-                // GIVEN an effect with a testing scope
-                longPressEffect.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler))
-
-                // GIVEN the down event that enters the TIMEOUT_WAIT state
-                val downEvent =
-                    MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_DOWN).build()
-                longPressEffect.onTouch(testView, downEvent)
-
-                // GIVEN that the timeout completes and the effect starts
-                advanceTimeBy(QSLongPressEffect.PRESSED_TIMEOUT + 10L)
+                // GIVEN that the effect starts after the tap timeout is complete
+                longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT)
+                longPressEffect.handleTimeoutComplete()
 
                 // THEN run the test
                 test()
@@ -252,6 +276,7 @@
      */
     private fun TestScope.assertEffectStarted() {
         val effectProgress by collectLastValue(longPressEffect.effectProgress)
+        val state by collectLastValue(longPressEffect.state)
         val longPressHint =
             LongPressHapticBuilder.createLongPressHint(
                 lowTickDuration,
@@ -259,10 +284,10 @@
                 effectDuration,
             )
 
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
         assertThat(effectProgress).isEqualTo(0f)
         assertThat(longPressHint).isNotNull()
-        verify(vibratorHelper).vibrate(longPressHint!!)
+        assertThat(vibratorHelper.hasVibratedWithEffects(longPressHint!!)).isTrue()
     }
 
     /**
@@ -274,11 +299,12 @@
      */
     private fun TestScope.assertEffectDidNotStart() {
         val effectProgress by collectLastValue(longPressEffect.effectProgress)
+        val state by collectLastValue(longPressEffect.state)
 
-        assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
-        assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
+        assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
+        assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
         assertThat(effectProgress).isNull()
-        verify(vibratorHelper, never()).vibrate(any(/* type= */ VibrationEffect::class.java))
+        assertThat(vibratorHelper.totalVibrations).isEqualTo(0)
     }
 
     /**
@@ -286,18 +312,19 @@
      * 1. The progress is null
      * 2. The final snap haptics are played
      * 3. The internal state goes back to [QSLongPressEffect.State.IDLE]
-     * 4. The action to perform on the tile is the long-press action
+     * 4. The action to perform on the tile is the action given as a parameter
      */
-    private fun TestScope.assertEffectCompleted() {
+    private fun TestScope.assertEffectCompleted(expectedAction: QSLongPressEffect.ActionType) {
         val action by collectLastValue(longPressEffect.actionType)
         val effectProgress by collectLastValue(longPressEffect.effectProgress)
         val snapEffect = LongPressHapticBuilder.createSnapEffect()
+        val state by collectLastValue(longPressEffect.state)
 
         assertThat(effectProgress).isNull()
         assertThat(snapEffect).isNotNull()
-        verify(vibratorHelper).vibrate(snapEffect!!)
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
-        assertThat(action).isEqualTo(QSLongPressEffect.ActionType.LONG_PRESS)
+        assertThat(vibratorHelper.hasVibratedWithEffects(snapEffect!!)).isTrue()
+        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(action).isEqualTo(expectedAction)
     }
 
     /**
@@ -305,17 +332,18 @@
      * 1. The internal state is [QSLongPressEffect.State.RUNNING_BACKWARDS]
      * 2. The reverse haptics plays at the point where the animation was paused
      */
-    private fun assertEffectReverses(pausedProgress: Float) {
+    private fun TestScope.assertEffectReverses(pausedProgress: Float) {
         val reverseHaptics =
             LongPressHapticBuilder.createReversedEffect(
                 pausedProgress,
                 lowTickDuration,
                 effectDuration,
             )
+        val state by collectLastValue(longPressEffect.state)
 
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
+        assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
         assertThat(reverseHaptics).isNotNull()
-        verify(vibratorHelper).vibrate(reverseHaptics!!)
+        assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue()
     }
 
     /**
@@ -325,8 +353,9 @@
      */
     private fun TestScope.assertEffectResets() {
         val effectProgress by collectLastValue(longPressEffect.effectProgress)
-        assertThat(effectProgress).isEqualTo(0f)
+        val state by collectLastValue(longPressEffect.state)
 
-        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
+        assertThat(effectProgress).isNull()
+        assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt
deleted file mode 100644
index 805b4a8..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.haptics.slider
-
-import android.widget.SeekBar
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.fakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.advanceTimeBy
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@OptIn(ExperimentalCoroutinesApi::class)
-class SeekableSliderHapticPluginTest : SysuiTestCase() {
-
-    private val kosmos = Kosmos()
-
-    @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
-    @Mock private lateinit var vibratorHelper: VibratorHelper
-    private val seekBar = SeekBar(mContext)
-    private lateinit var plugin: SeekableSliderHapticPlugin
-
-    @Before
-    fun setup() {
-        whenever(vibratorHelper.getPrimitiveDurations(anyInt())).thenReturn(intArrayOf(0))
-    }
-
-    @Test
-    fun start_beginsTrackingSlider() = runOnStartedPlugin { assertThat(plugin.isTracking).isTrue() }
-
-    @Test
-    fun stop_stopsTrackingSlider() = runOnStartedPlugin {
-        // WHEN called to stop
-        plugin.stop()
-
-        // THEN stops tracking
-        assertThat(plugin.isTracking).isFalse()
-    }
-
-    @Test
-    fun start_afterStop_startsTheTrackingAgain() = runOnStartedPlugin {
-        // WHEN the plugin is restarted
-        plugin.stop()
-        plugin.startInScope(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // THEN the tracking begins again
-        assertThat(plugin.isTracking).isTrue()
-    }
-
-    @Test
-    fun onKeyDown_startsWaiting() = runOnStartedPlugin {
-        // WHEN a keyDown event is recorded
-        plugin.onKeyDown()
-
-        // THEN the timer starts waiting
-        assertThat(plugin.isKeyUpTimerWaiting).isTrue()
-    }
-
-    @Test
-    fun keyUpWaitComplete_triggersOnArrowUp() = runOnStartedPlugin {
-        // GIVEN an onKeyDown that starts the wait and a program progress change that advances the
-        // slider state to ARROW_HANDLE_MOVED_ONCE
-        plugin.onKeyDown()
-        plugin.onProgressChanged(seekBar, 50, false)
-        testScheduler.runCurrent()
-        assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
-
-        // WHEN the key-up wait completes after the timeout plus a small buffer
-        advanceTimeBy(KEY_UP_TIMEOUT + 10L)
-
-        // THEN the onArrowUp event is delivered causing the slider tracker to move to IDLE
-        assertThat(plugin.trackerState).isEqualTo(SliderState.IDLE)
-        assertThat(plugin.isKeyUpTimerWaiting).isFalse()
-    }
-
-    @Test
-    fun onKeyDown_whileWaiting_restartsWait() = runOnStartedPlugin {
-        // GIVEN an onKeyDown that starts the wait and a program progress change that advances the
-        // slider state to ARROW_HANDLE_MOVED_ONCE
-        plugin.onKeyDown()
-        plugin.onProgressChanged(seekBar, 50, false)
-        testScheduler.runCurrent()
-        assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
-
-        // WHEN half the timeout period has elapsed and a new keyDown event occurs
-        advanceTimeBy(KEY_UP_TIMEOUT / 2)
-        plugin.onKeyDown()
-
-        // AFTER advancing by a period of time that should have complete the original wait
-        advanceTimeBy(KEY_UP_TIMEOUT / 2 + 10L)
-
-        // THEN the timer is still waiting and the slider tracker remains on ARROW_HANDLE_MOVED_ONCE
-        assertThat(plugin.isKeyUpTimerWaiting).isTrue()
-        assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
-    }
-
-    private fun runOnStartedPlugin(test: suspend TestScope.() -> Unit) =
-        with(kosmos) {
-            testScope.runTest {
-                val pluginScope = CoroutineScope(UnconfinedTestDispatcher(testScheduler))
-                createPlugin()
-                // GIVEN that the plugin is started in a test scope
-                plugin.startInScope(pluginScope)
-
-                // THEN run the test
-                test()
-            }
-        }
-
-    private fun createPlugin() {
-        plugin =
-            SeekableSliderHapticPlugin(
-                vibratorHelper,
-                kosmos.fakeSystemClock,
-            )
-    }
-
-    companion object {
-        private const val KEY_UP_TIMEOUT = 100L
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
new file mode 100644
index 0000000..855b6d0
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.slider
+
+import android.widget.SeekBar
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.fakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class SeekbarHapticPluginTest : SysuiTestCase() {
+
+    private val kosmos = Kosmos()
+
+    @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
+    @Mock private lateinit var vibratorHelper: VibratorHelper
+    private val seekBar = SeekBar(mContext)
+    private lateinit var plugin: SeekbarHapticPlugin
+
+    @Before
+    fun setup() {
+        whenever(vibratorHelper.getPrimitiveDurations(anyInt())).thenReturn(intArrayOf(0))
+    }
+
+    @Test
+    fun start_beginsTrackingSlider() = runOnStartedPlugin { assertThat(plugin.isTracking).isTrue() }
+
+    @Test
+    fun stop_stopsTrackingSlider() = runOnStartedPlugin {
+        // WHEN called to stop
+        plugin.stop()
+
+        // THEN stops tracking
+        assertThat(plugin.isTracking).isFalse()
+    }
+
+    @Test
+    fun start_afterStop_startsTheTrackingAgain() = runOnStartedPlugin {
+        // WHEN the plugin is restarted
+        plugin.stop()
+        plugin.startInScope(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // THEN the tracking begins again
+        assertThat(plugin.isTracking).isTrue()
+    }
+
+    @Test
+    fun onKeyDown_startsWaiting() = runOnStartedPlugin {
+        // WHEN a keyDown event is recorded
+        plugin.onKeyDown()
+
+        // THEN the timer starts waiting
+        assertThat(plugin.isKeyUpTimerWaiting).isTrue()
+    }
+
+    @Test
+    fun keyUpWaitComplete_triggersOnArrowUp() = runOnStartedPlugin {
+        // GIVEN an onKeyDown that starts the wait and a program progress change that advances the
+        // slider state to ARROW_HANDLE_MOVED_ONCE
+        plugin.onKeyDown()
+        plugin.onProgressChanged(seekBar, 50, false)
+        testScheduler.runCurrent()
+        assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
+
+        // WHEN the key-up wait completes after the timeout plus a small buffer
+        advanceTimeBy(KEY_UP_TIMEOUT + 10L)
+
+        // THEN the onArrowUp event is delivered causing the slider tracker to move to IDLE
+        assertThat(plugin.trackerState).isEqualTo(SliderState.IDLE)
+        assertThat(plugin.isKeyUpTimerWaiting).isFalse()
+    }
+
+    @Test
+    fun onKeyDown_whileWaiting_restartsWait() = runOnStartedPlugin {
+        // GIVEN an onKeyDown that starts the wait and a program progress change that advances the
+        // slider state to ARROW_HANDLE_MOVED_ONCE
+        plugin.onKeyDown()
+        plugin.onProgressChanged(seekBar, 50, false)
+        testScheduler.runCurrent()
+        assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
+
+        // WHEN half the timeout period has elapsed and a new keyDown event occurs
+        advanceTimeBy(KEY_UP_TIMEOUT / 2)
+        plugin.onKeyDown()
+
+        // AFTER advancing by a period of time that should have complete the original wait
+        advanceTimeBy(KEY_UP_TIMEOUT / 2 + 10L)
+
+        // THEN the timer is still waiting and the slider tracker remains on ARROW_HANDLE_MOVED_ONCE
+        assertThat(plugin.isKeyUpTimerWaiting).isTrue()
+        assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
+    }
+
+    private fun runOnStartedPlugin(test: suspend TestScope.() -> Unit) =
+        with(kosmos) {
+            testScope.runTest {
+                val pluginScope = CoroutineScope(UnconfinedTestDispatcher(testScheduler))
+                createPlugin()
+                // GIVEN that the plugin is started in a test scope
+                plugin.startInScope(pluginScope)
+
+                // THEN run the test
+                test()
+            }
+        }
+
+    private fun createPlugin() {
+        plugin =
+            SeekbarHapticPlugin(
+                vibratorHelper,
+                kosmos.fakeSystemClock,
+            )
+    }
+
+    companion object {
+        private const val KEY_UP_TIMEOUT = 100L
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderStateProducerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderStateProducerTest.kt
new file mode 100644
index 0000000..88189db
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderStateProducerTest.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.slider
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SliderStateProducerTest : SysuiTestCase() {
+
+    private val eventProducer = SliderStateProducer()
+    private val eventFlow = eventProducer.produceEvents()
+
+    @Test
+    fun onStartTrackingTouch_noProgress_trackingTouchEventProduced() = runTest {
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onStartTracking(/*fromUser =*/ true)
+
+        assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0F), latest)
+    }
+
+    @Test
+    fun onStopTrackingTouch_noProgress_StoppedTrackingTouchEventProduced() = runTest {
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onStopTracking(/*fromUser =*/ true)
+
+        assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0F), latest)
+    }
+
+    @Test
+    fun onStartTrackingProgram_noProgress_trackingTouchEventProduced() = runTest {
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onStartTracking(/*fromUser =*/ false)
+
+        assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, 0F), latest)
+    }
+
+    @Test
+    fun onStopTrackingProgram_noProgress_StoppedTrackingTouchEventProduced() = runTest {
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onStopTracking(/*fromUser =*/ false)
+
+        assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, 0F), latest)
+    }
+
+    @Test
+    fun onProgressChangeByUser_changeByUserEventProduced() = runTest {
+        val progress = 0.5f
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onProgressChanged(/*fromUser =*/ true, progress)
+
+        assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress), latest)
+    }
+
+    @Test
+    fun onProgressChangeByProgram_changeByProgramEventProduced() = runTest {
+        val progress = 0.5f
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onProgressChanged(/*fromUser =*/ false, progress)
+
+        assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress), latest)
+    }
+
+    @Test
+    fun onStartTrackingTouch_afterProgress_trackingTouchEventProduced() = runTest {
+        val progress = 0.5f
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onProgressChanged(/*fromUser =*/ true, progress)
+        eventProducer.onStartTracking(/*fromUser =*/ true)
+
+        assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress), latest)
+    }
+
+    @Test
+    fun onStopTrackingTouch_afterProgress_stopTrackingTouchEventProduced() = runTest {
+        val progress = 0.5f
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onProgressChanged(/*fromUser =*/ true, progress)
+        eventProducer.onStopTracking(/*fromUser =*/ true)
+
+        assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, progress), latest)
+    }
+
+    @Test
+    fun onStartTrackingProgram_afterProgress_trackingProgramEventProduced() = runTest {
+        val progress = 0.5f
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onProgressChanged(/*fromUser =*/ false, progress)
+        eventProducer.onStartTracking(/*fromUser =*/ false)
+
+        assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress), latest)
+    }
+
+    @Test
+    fun onStopTrackingProgram_afterProgress_stopTrackingProgramEventProduced() = runTest {
+        val progress = 0.5f
+        val latest by collectLastValue(eventFlow)
+
+        eventProducer.onProgressChanged(/*fromUser =*/ false, progress)
+        eventProducer.onStopTracking(/*fromUser =*/ false)
+
+        assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, progress), latest)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
new file mode 100644
index 0000000..cfc6b33
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.Mockito.reset
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() {
+    private val kosmos =
+        testKosmos().apply {
+            this.fakeKeyguardTransitionRepository = Mockito.spy(FakeKeyguardTransitionRepository())
+        }
+    private val testScope = kosmos.testScope
+    private lateinit var underTest: FromAlternateBouncerTransitionInteractor
+    private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+
+    @Before
+    fun setup() {
+        transitionRepository = kosmos.fakeKeyguardTransitionRepository
+        underTest = kosmos.fromAlternateBouncerTransitionInteractor
+        underTest.start()
+    }
+
+    @Test
+    fun transitionToGone_keyguardOccluded_biometricAuthenticated() =
+        testScope.runTest {
+            transitionRepository.sendTransitionSteps(
+                from = KeyguardState.OCCLUDED,
+                to = KeyguardState.ALTERNATE_BOUNCER,
+                testScope
+            )
+            reset(transitionRepository)
+
+            kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
+            kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true)
+            runCurrent()
+            kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null)
+            runCurrent()
+
+            assertThat(transitionRepository)
+                .startedTransition(from = KeyguardState.ALTERNATE_BOUNCER, to = KeyguardState.GONE)
+        }
+
+    @Test
+    fun noTransition_keyguardNotOccluded_biometricAuthenticated() =
+        testScope.runTest {
+            transitionRepository.sendTransitionSteps(
+                from = KeyguardState.OCCLUDED,
+                to = KeyguardState.ALTERNATE_BOUNCER,
+                testScope
+            )
+            reset(transitionRepository)
+
+            kosmos.fakeKeyguardRepository.setKeyguardOccluded(false)
+            kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true)
+            runCurrent()
+            kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null)
+            runCurrent()
+
+            assertThat(transitionRepository).noTransitionsStarted()
+        }
+
+    @Test
+    fun transitionToOccluded() =
+        testScope.runTest {
+            kosmos.fakePowerRepository.updateWakefulness(
+                WakefulnessState.AWAKE,
+                WakeSleepReason.POWER_BUTTON,
+                WakeSleepReason.POWER_BUTTON,
+                false,
+            )
+            kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
+            kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(true)
+            runCurrent()
+
+            transitionRepository.sendTransitionSteps(
+                from = KeyguardState.OCCLUDED,
+                to = KeyguardState.ALTERNATE_BOUNCER,
+                testScope
+            )
+            reset(transitionRepository)
+
+            kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(false)
+            advanceTimeBy(200) // advance past delay
+
+            assertThat(transitionRepository)
+                .startedTransition(
+                    from = KeyguardState.ALTERNATE_BOUNCER,
+                    to = KeyguardState.OCCLUDED
+                )
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
new file mode 100644
index 0000000..26b56a1
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
+import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
+import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardClockInteractorTest : SysuiTestCase() {
+    private lateinit var kosmos: Kosmos
+    private lateinit var underTest: KeyguardClockInteractor
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setup() {
+        kosmos = testKosmos()
+        testScope = kosmos.testScope
+        underTest = kosmos.keyguardClockInteractor
+    }
+
+    @Test
+    @DisableSceneContainer
+    fun clockSize_sceneContainerFlagOff_basedOnRepository() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            kosmos.keyguardClockRepository.setClockSize(ClockSize.LARGE)
+            assertThat(value).isEqualTo(ClockSize.LARGE)
+
+            kosmos.keyguardClockRepository.setClockSize(ClockSize.SMALL)
+            assertThat(value).isEqualTo(ClockSize.SMALL)
+        }
+
+    @Test
+    @DisableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOff_basedOnRepository() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.keyguardInteractor.setClockShouldBeCentered(true)
+            assertThat(value).isEqualTo(true)
+
+            kosmos.keyguardInteractor.setClockShouldBeCentered(false)
+            assertThat(value).isEqualTo(false)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockSize_forceSmallClock_SMALL() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            kosmos.fakeKeyguardClockRepository.setShouldForceSmallClock(true)
+            kosmos.fakeFeatureFlagsClassic.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true)
+            transitionTo(KeyguardState.AOD, KeyguardState.LOCKSCREEN)
+            assertThat(value).isEqualTo(ClockSize.SMALL)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasNotifs_SMALL() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+            kosmos.activeNotificationListRepository.setActiveNotifs(1)
+            assertThat(value).isEqualTo(ClockSize.SMALL)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasMedia_SMALL() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+            val userMedia = MediaData().copy(active = true)
+            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            assertThat(value).isEqualTo(ClockSize.SMALL)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockSize_SceneContainerFlagOn_shadeModeSplit_isMediaVisible_SMALL() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            val userMedia = MediaData().copy(active = true)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            kosmos.keyguardRepository.setIsDozing(false)
+            assertThat(value).isEqualTo(ClockSize.SMALL)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockSize_SceneContainerFlagOn_shadeModeSplit_noMedia_LARGE() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.keyguardRepository.setIsDozing(false)
+            assertThat(value).isEqualTo(ClockSize.LARGE)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockSize_SceneContainerFlagOn_shadeModeSplit_isDozing_LARGE() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+            val userMedia = MediaData().copy(active = true)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            kosmos.keyguardRepository.setIsDozing(true)
+            assertThat(value).isEqualTo(ClockSize.LARGE)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOn_notSplitMode_true() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+            assertThat(value).isEqualTo(true)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_noActiveNotifications_true() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.activeNotificationListRepository.setActiveNotifs(0)
+            assertThat(value).isEqualTo(true)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_isActiveDreamLockscreenHosted_true() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.activeNotificationListRepository.setActiveNotifs(1)
+            kosmos.keyguardRepository.setIsActiveDreamLockscreenHosted(true)
+            assertThat(value).isEqualTo(true)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_hasPulsingNotifications_false() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.activeNotificationListRepository.setActiveNotifs(1)
+            kosmos.headsUpNotificationRepository.isHeadsUpAnimatingAway.value = true
+            kosmos.keyguardRepository.setIsDozing(true)
+            assertThat(value).isEqualTo(false)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_onAod_true() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.activeNotificationListRepository.setActiveNotifs(1)
+            transitionTo(KeyguardState.LOCKSCREEN, KeyguardState.AOD)
+            assertThat(value).isEqualTo(true)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_offAod_false() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockShouldBeCentered)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+            kosmos.activeNotificationListRepository.setActiveNotifs(1)
+            transitionTo(KeyguardState.AOD, KeyguardState.LOCKSCREEN)
+            assertThat(value).isEqualTo(false)
+        }
+
+    private suspend fun transitionTo(from: KeyguardState, to: KeyguardState) {
+        with(kosmos.fakeKeyguardTransitionRepository) {
+            sendTransitionStep(TransitionStep(from, to, 0f, TransitionState.STARTED))
+            sendTransitionStep(TransitionStep(from, to, 0.5f, TransitionState.RUNNING))
+            sendTransitionStep(TransitionStep(from, to, 1f, TransitionState.FINISHED))
+        }
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 6d7a0a9..12f8918 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.FakeCommandQueue
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -37,7 +38,6 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
@@ -75,7 +75,6 @@
             repository = repository,
             commandQueue = commandQueue,
             powerInteractor = PowerInteractorFactory.create().powerInteractor,
-            sceneContainerFlags = kosmos.fakeSceneContainerFlags,
             bouncerRepository = bouncerRepository,
             configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()),
             shadeRepository = shadeRepository,
@@ -248,9 +247,9 @@
         }
 
     @Test
+    @EnableSceneContainer
     fun animationDozingTransitions() =
         testScope.runTest {
-            kosmos.fakeSceneContainerFlags.enabled = true
             val isAnimate by collectLastValue(underTest.animateDozingTransitions)
 
             underTest.setAnimateDozingTransitions(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 0ebcf56..2d77f4f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -46,13 +46,17 @@
 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.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -60,8 +64,6 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -86,9 +88,11 @@
     @Mock private lateinit var shadeInteractor: ShadeInteractor
     @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: KeyguardQuickAffordanceInteractor
 
-    private lateinit var testScope: TestScope
+    private val testScope = kosmos.testScope
     private lateinit var repository: FakeKeyguardRepository
     private lateinit var homeControls: FakeKeyguardQuickAffordanceConfig
     private lateinit var quickAccessWallet: FakeKeyguardQuickAffordanceConfig
@@ -125,8 +129,6 @@
             )
         qrCodeScanner =
             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
-        val testDispatcher = StandardTestDispatcher()
-        testScope = TestScope(testDispatcher)
 
         dockManager = DockManagerFake()
         biometricSettingsRepository = FakeBiometricSettingsRepository()
@@ -165,7 +167,7 @@
                 legacySettingSyncer =
                     KeyguardQuickAffordanceLegacySettingSyncer(
                         scope = testScope.backgroundScope,
-                        backgroundDispatcher = testDispatcher,
+                        backgroundDispatcher = kosmos.testDispatcher,
                         secureSettings = FakeSettings(),
                         selectionsManager = localUserSelectionManager,
                     ),
@@ -195,8 +197,9 @@
                 devicePolicyManager = devicePolicyManager,
                 dockManager = dockManager,
                 biometricSettingsRepository = biometricSettingsRepository,
-                backgroundDispatcher = testDispatcher,
+                backgroundDispatcher = kosmos.testDispatcher,
                 appContext = context,
+                sceneInteractor = { kosmos.sceneInteractor },
             )
 
         whenever(shadeInteractor.anyExpansion).thenReturn(MutableStateFlow(0f))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index 15c9cf7..41229255 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -55,29 +55,30 @@
     val testScope = kosmos.testScope
 
     @Test
-    fun transitionCollectorsReceivesOnlyAppropriateEvents() = runTest {
-        val lockscreenToAodSteps by collectValues(underTest.lockscreenToAodTransition)
-        val aodToLockscreenSteps by collectValues(underTest.aodToLockscreenTransition)
+    fun transitionCollectorsReceivesOnlyAppropriateEvents() =
+        testScope.runTest {
+            val lockscreenToAodSteps by collectValues(underTest.transition(LOCKSCREEN, AOD))
+            val aodToLockscreenSteps by collectValues(underTest.transition(AOD, LOCKSCREEN))
 
-        val steps = mutableListOf<TransitionStep>()
-        steps.add(TransitionStep(AOD, GONE, 0f, STARTED))
-        steps.add(TransitionStep(AOD, GONE, 1f, FINISHED))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING))
+            val steps = mutableListOf<TransitionStep>()
+            steps.add(TransitionStep(AOD, GONE, 0f, STARTED))
+            steps.add(TransitionStep(AOD, GONE, 1f, FINISHED))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING))
 
-        steps.forEach {
-            repository.sendTransitionStep(it)
-            runCurrent()
+            steps.forEach {
+                repository.sendTransitionStep(it)
+                runCurrent()
+            }
+
+            assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5))
+            assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8))
         }
 
-        assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5))
-        assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8))
-    }
-
     @Test
     fun dozeAmountTransitionTest_AodToFromLockscreen() =
         testScope.runTest {
@@ -187,59 +188,60 @@
         }
 
     @Test
-    fun finishedKeyguardTransitionStepTests() = runTest {
-        val finishedSteps by collectValues(underTest.finishedKeyguardTransitionStep)
+    fun finishedKeyguardTransitionStepTests() =
+        testScope.runTest {
+            val finishedSteps by collectValues(underTest.finishedKeyguardTransitionStep)
+            val steps = mutableListOf<TransitionStep>()
 
-        val steps = mutableListOf<TransitionStep>()
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
+            steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
 
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
-        steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
+            steps.forEach {
+                repository.sendTransitionStep(it)
+                runCurrent()
+            }
 
-        steps.forEach {
-            repository.sendTransitionStep(it)
-            runCurrent()
+            // Ignore the default state.
+            assertThat(finishedSteps.subList(1, finishedSteps.size))
+                .isEqualTo(listOf(steps[2], steps[5]))
         }
 
-        // Ignore the default state.
-        assertThat(finishedSteps.subList(1, finishedSteps.size))
-            .isEqualTo(listOf(steps[2], steps[5]))
-    }
-
     @Test
-    fun startedKeyguardTransitionStepTests() = runTest {
-        val startedSteps by collectValues(underTest.startedKeyguardTransitionStep)
+    fun startedKeyguardTransitionStepTests() =
+        testScope.runTest {
+            val startedSteps by collectValues(underTest.startedKeyguardTransitionStep)
 
-        val steps = mutableListOf<TransitionStep>()
+            val steps = mutableListOf<TransitionStep>()
 
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
-        steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
-        steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
-        steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
+            steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
+            steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
+            steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
 
-        steps.forEach {
-            repository.sendTransitionStep(it)
-            runCurrent()
-        }
+            steps.forEach {
+                repository.sendTransitionStep(it)
+                runCurrent()
+            }
 
-        assertThat(startedSteps)
-            .isEqualTo(
-                listOf(
-                    // The initial transition will also get sent when collect started
-                    TransitionStep(OFF, LOCKSCREEN, 0f, STARTED),
-                    steps[0],
-                    steps[3],
-                    steps[6]
+            assertThat(startedSteps)
+                .isEqualTo(
+                    listOf(
+                        // The initial transition will also get sent when collect started
+                        TransitionStep(OFF, LOCKSCREEN, 0f, STARTED),
+                        steps[0],
+                        steps[3],
+                        steps[6]
+                    )
                 )
-            )
-    }
+        }
 
     @Test
     fun transitionValue() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
new file mode 100644
index 0000000..0ac7ff5
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    val testScope = kosmos.testScope
+    val animationFlow = kosmos.keyguardTransitionAnimationFlow
+    val repository = kosmos.fakeKeyguardTransitionRepository
+
+    private lateinit var underTest: KeyguardTransitionAnimationFlow.FlowBuilder
+
+    @Before
+    fun setUp() {
+        underTest =
+            animationFlow.setup(
+                duration = 1000.milliseconds,
+                from = GONE,
+                to = DREAMING,
+            )
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun zeroDurationThrowsException() =
+        testScope.runTest {
+            val flow = underTest.sharedFlow(duration = 0.milliseconds, onStep = { it })
+        }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun startTimePlusDurationGreaterThanTransitionDurationThrowsException() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    startTime = 300.milliseconds,
+                    duration = 800.milliseconds,
+                    onStep = { it }
+                )
+        }
+
+    @Test
+    fun onFinishRunsWhenSpecified() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    duration = 100.milliseconds,
+                    onStep = { it },
+                    onFinish = { 10f },
+                )
+            var animationValues = collectLastValue(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(1f, TransitionState.FINISHED), validateStep = false)
+            assertThat(animationValues()).isEqualTo(10f)
+        }
+
+    @Test
+    fun onCancelRunsWhenSpecified() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    duration = 100.milliseconds,
+                    onStep = { it },
+                    onCancel = { 100f },
+                )
+            var animationValues = collectLastValue(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
+            assertThat(animationValues()).isEqualTo(100f)
+        }
+
+    @Test
+    fun usesStartTime() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    startTime = 500.milliseconds,
+                    duration = 500.milliseconds,
+                    onStep = { it },
+                )
+            var animationValues = collectLastValue(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            assertThat(animationValues()).isEqualTo(0f)
+
+            // Should not emit a value
+            repository.sendTransitionStep(step(0.1f, TransitionState.RUNNING))
+
+            repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
+            assertFloat(animationValues(), 0f)
+            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+            assertFloat(animationValues(), 0.2f)
+            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+            assertFloat(animationValues(), 0.6f)
+            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+            assertFloat(animationValues(), 1f)
+        }
+
+    @Test
+    fun usesInterpolator() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    duration = 1000.milliseconds,
+                    interpolator = EMPHASIZED_ACCELERATE,
+                    onStep = { it },
+                )
+            var animationValues = collectLastValue(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0f))
+            repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
+            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.5f))
+            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.6f))
+            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.8f))
+            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(1f))
+        }
+
+    @Test
+    fun usesOnStepToDoubleValue() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    duration = 1000.milliseconds,
+                    onStep = { it * 2 },
+                )
+            val animationValues by collectLastValue(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            assertFloat(animationValues, 0f)
+            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+            assertFloat(animationValues, 0.6f)
+            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+            assertFloat(animationValues, 1.2f)
+            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+            assertFloat(animationValues, 1.6f)
+            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+            assertFloat(animationValues, 2f)
+        }
+
+    @Test
+    fun usesOnStepToDoubleValueWithState() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlowWithState(
+                    duration = 1000.milliseconds,
+                    onStep = { it * 2 },
+                )
+            val animationValues by collectLastValue(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            assertThat(animationValues)
+                .isEqualTo(
+                    StateToValue(
+                        from = GONE,
+                        to = DREAMING,
+                        transitionState = TransitionState.STARTED,
+                        value = 0f
+                    )
+                )
+            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+            assertThat(animationValues)
+                .isEqualTo(
+                    StateToValue(
+                        from = GONE,
+                        to = DREAMING,
+                        transitionState = TransitionState.RUNNING,
+                        value = 0.6f
+                    )
+                )
+            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+            assertThat(animationValues)
+                .isEqualTo(
+                    StateToValue(
+                        from = GONE,
+                        to = DREAMING,
+                        transitionState = TransitionState.RUNNING,
+                        value = 1.2f
+                    )
+                )
+            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+            assertThat(animationValues)
+                .isEqualTo(
+                    StateToValue(
+                        from = GONE,
+                        to = DREAMING,
+                        transitionState = TransitionState.RUNNING,
+                        value = 1.6f
+                    )
+                )
+            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+            assertThat(animationValues)
+                .isEqualTo(
+                    StateToValue(
+                        from = GONE,
+                        to = DREAMING,
+                        transitionState = TransitionState.RUNNING,
+                        value = 2f
+                    )
+                )
+            repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+            assertThat(animationValues)
+                .isEqualTo(
+                    StateToValue(
+                        from = GONE,
+                        to = DREAMING,
+                        transitionState = TransitionState.FINISHED,
+                        value = null
+                    )
+                )
+        }
+
+    @Test
+    fun sameFloatValueWithTheSameTransitionStateDoesNotEmitTwice() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    duration = 1000.milliseconds,
+                    onStep = { it },
+                )
+            val values by collectValues(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+
+            assertThat(values.size).isEqualTo(1)
+            assertThat(values[0]).isEqualTo(0.3f)
+        }
+
+    @Test
+    fun sameFloatValueWithADifferentTransitionStateDoesEmitTwice() =
+        testScope.runTest {
+            val flow =
+                underTest.sharedFlow(
+                    duration = 1000.milliseconds,
+                    onStep = { it },
+                )
+            val values by collectValues(flow)
+            runCurrent()
+
+            repository.sendTransitionStep(step(0.3f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+
+            assertThat(values.size).isEqualTo(2)
+            assertThat(values[0]).isEqualTo(0.3f)
+            assertThat(values[0]).isEqualTo(0.3f)
+        }
+
+    private fun assertFloat(actual: Float?, expected: Float) {
+        assertThat(actual!!).isWithin(0.01f).of(expected)
+    }
+
+    private fun step(
+        value: Float,
+        state: TransitionState = TransitionState.RUNNING
+    ): TransitionStep {
+        return TransitionStep(
+            from = GONE,
+            to = DREAMING,
+            value = value,
+            transitionState = state,
+            ownerName = "GoneToDreamingTransitionViewModelTest"
+        )
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelTest.kt
new file mode 100644
index 0000000..d0f434a
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+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.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AccessibilityActionsViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val keyguardRepository = kosmos.fakeKeyguardRepository
+    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+
+    private lateinit var underTest: AccessibilityActionsViewModel
+
+    @Before
+    fun setUp() {
+        underTest = kosmos.accessibilityActionsViewModelKosmos
+    }
+
+    @Test
+    fun isOnKeyguard_isFalse_whenTransitioningAwayFromLockscreen() =
+        testScope.runTest {
+            val isOnKeyguard by collectLastValue(underTest.isOnKeyguard)
+
+            // Shade not opened.
+            keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+            // Transitioning away from lock screen.
+            keyguardTransitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.PRIMARY_BOUNCER,
+                    transitionState = TransitionState.STARTED,
+                )
+            )
+
+            keyguardTransitionRepository.sendTransitionStep(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.PRIMARY_BOUNCER,
+                transitionState = TransitionState.RUNNING,
+                value = 0.5f,
+            )
+            assertThat(isOnKeyguard).isEqualTo(false)
+
+            // Transitioned to bouncer.
+            keyguardTransitionRepository.sendTransitionStep(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.PRIMARY_BOUNCER,
+                transitionState = TransitionState.FINISHED,
+                value = 1f,
+            )
+            assertThat(isOnKeyguard).isEqualTo(false)
+        }
+
+    @Test
+    fun isOnKeyguard_isFalse_whenTransitioningToLockscreenIsRunning() =
+        testScope.runTest {
+            val isOnKeyguard by collectLastValue(underTest.isOnKeyguard)
+
+            // Shade is not opened.
+            keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+            // Starts transitioning to lock screen.
+            keyguardTransitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.GLANCEABLE_HUB,
+                    to = KeyguardState.LOCKSCREEN,
+                    transitionState = TransitionState.STARTED,
+                )
+            )
+            assertThat(isOnKeyguard).isEqualTo(false)
+
+            keyguardTransitionRepository.sendTransitionStep(
+                from = KeyguardState.GLANCEABLE_HUB,
+                to = KeyguardState.LOCKSCREEN,
+                transitionState = TransitionState.RUNNING,
+                value = 0.5f,
+            )
+            assertThat(isOnKeyguard).isEqualTo(false)
+
+            // Transition has finished.
+            keyguardTransitionRepository.sendTransitionStep(
+                from = KeyguardState.GLANCEABLE_HUB,
+                to = KeyguardState.LOCKSCREEN,
+                transitionState = TransitionState.FINISHED,
+                value = 1f,
+            )
+            assertThat(isOnKeyguard).isEqualTo(true)
+        }
+
+    @Test
+    fun isOnKeyguard_isTrue_whenKeyguardStateIsLockscreen_andShadeIsNotOpened() =
+        testScope.runTest {
+            val isOnKeyguard by collectLastValue(underTest.isOnKeyguard)
+
+            keyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.GONE,
+                to = KeyguardState.LOCKSCREEN,
+                testScope = testScope,
+            )
+            keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+
+            assertThat(isOnKeyguard).isEqualTo(true)
+        }
+
+    @Test
+    fun isOnKeyguard_isFalse_whenKeyguardStateIsLockscreen_andShadeOpened() =
+        testScope.runTest {
+            val isOnKeyguard by collectLastValue(underTest.isOnKeyguard)
+
+            keyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.GONE,
+                to = KeyguardState.LOCKSCREEN,
+                testScope = testScope,
+            )
+            keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
+
+            assertThat(isOnKeyguard).isEqualTo(false)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt
index 78bdfb3..5bf0f4b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt
@@ -36,6 +36,7 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -45,16 +46,19 @@
 class AlternateBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
     val kosmos =
         testKosmos().apply {
-            fakeFeatureFlagsClassic.apply {
-                set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
-                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-            }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
+
     private val testScope = kosmos.testScope
     private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
     private val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController
     private val underTest by lazy { kosmos.alternateBouncerToGoneTransitionViewModel }
 
+    @Before
+    fun setup() {
+        mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
+    }
+
     @Test
     fun deviceEntryParentViewDisappear() =
         testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
index ff41ea2..854a478 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
@@ -32,6 +32,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -41,15 +42,17 @@
 class AlternateBouncerToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
     private val kosmos =
         testKosmos().apply {
-            fakeFeatureFlagsClassic.apply {
-                set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
-                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-            }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     private val testScope = kosmos.testScope
     private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
     private val underTest by lazy { kosmos.alternateBouncerToPrimaryBouncerTransitionViewModel }
 
+    @Before
+    fun setup() {
+        mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
+    }
+
     @Test
     fun deviceEntryParentViewDisappear() =
         testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
index f517cec..31337a6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.Flags as AConfigFlags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
 import com.android.systemui.keyguard.domain.interactor.burnInInteractor
@@ -60,10 +61,7 @@
     private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
     private lateinit var underTest: AodBurnInViewModel
 
-    private var burnInParameters =
-        BurnInParameters(
-            clockControllerProvider = { clockController },
-        )
+    private var burnInParameters = BurnInParameters()
     private val burnInFlow = MutableStateFlow(BurnInModel())
 
     @Before
@@ -76,6 +74,7 @@
         whenever(goneToAodTransitionViewModel.enterFromTopTranslationY(anyInt()))
             .thenReturn(emptyFlow())
         kosmos.goneToAodTransitionViewModel = goneToAodTransitionViewModel
+        kosmos.fakeKeyguardClockRepository.setCurrentClock(clockController)
 
         underTest = kosmos.aodBurnInViewModel
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
index e6b3017..ee217a6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
@@ -57,10 +57,7 @@
 
     private val kosmos =
         testKosmos().apply {
-            fakeFeatureFlagsClassic.apply {
-                set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
-                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-            }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     private val testScope = kosmos.testScope
     private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
@@ -72,6 +69,7 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
+        mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
         whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
         sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index fc604aa..e3eca67 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -30,11 +30,8 @@
 import com.android.systemui.communal.shared.model.CommunalScenes
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -60,13 +57,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class KeyguardRootViewModelTest : SysuiTestCase() {
-    private val kosmos =
-        testKosmos().apply {
-            fakeFeatureFlagsClassic.apply { set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false) }
-        }
+    private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
-    private val keyguardInteractor = kosmos.keyguardInteractor
     private val keyguardRepository = kosmos.fakeKeyguardRepository
     private val communalRepository = kosmos.communalRepository
     private val screenOffAnimationController = kosmos.screenOffAnimationController
@@ -82,7 +75,10 @@
     fun setUp() {
         mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
         mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION)
-        mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        mSetFlagsRule.disableFlags(
+            AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
+            AConfigFlags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
+        )
     }
 
     @Test
@@ -426,4 +422,23 @@
             shadeRepository.setQsExpansion(0.5f)
             assertThat(alpha).isEqualTo(0f)
         }
+
+    @Test
+    fun alpha_idleOnDream_isZero() =
+        testScope.runTest {
+            val alpha by collectLastValue(underTest.alpha(viewState))
+            assertThat(alpha).isEqualTo(1f)
+
+            // Go to GONE state
+            keyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.DREAMING,
+                testScope = testScope,
+            )
+            assertThat(alpha).isEqualTo(0f)
+
+            // Try pulling down shade and ensure the value doesn't change
+            shadeRepository.setQsExpansion(0.5f)
+            assertThat(alpha).isEqualTo(0f)
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index e9a8257..4907359 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -18,20 +18,24 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardClockSwitch
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.authController
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
+import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.testKosmos
+import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
+import java.util.Locale
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -58,7 +62,7 @@
     fun isUdfpsVisible_withUdfps_true() =
         with(kosmos) {
             testScope.runTest {
-                whenever(kosmos.authController.isUdfpsSupported).thenReturn(true)
+                whenever(authController.isUdfpsSupported).thenReturn(true)
                 assertThat(underTest.isUdfpsVisible).isTrue()
             }
         }
@@ -67,26 +71,28 @@
     fun isUdfpsVisible_withoutUdfps_false() =
         with(kosmos) {
             testScope.runTest {
-                whenever(kosmos.authController.isUdfpsSupported).thenReturn(false)
+                whenever(authController.isUdfpsSupported).thenReturn(false)
                 assertThat(underTest.isUdfpsVisible).isFalse()
             }
         }
 
     @Test
-    fun isLargeClockVisible_withLargeClock_true() =
+    fun clockSize_withLargeClock_true() =
         with(kosmos) {
             testScope.runTest {
-                kosmos.fakeKeyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-                assertThat(underTest.isLargeClockVisible).isTrue()
+                val clockSize by collectLastValue(underTest.clockSize)
+                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
+                assertThat(clockSize).isEqualTo(ClockSize.LARGE)
             }
         }
 
     @Test
-    fun isLargeClockVisible_withSmallClock_false() =
+    fun clockSize_withSmallClock_false() =
         with(kosmos) {
             testScope.runTest {
-                kosmos.fakeKeyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL)
-                assertThat(underTest.isLargeClockVisible).isFalse()
+                val clockSize by collectLastValue(underTest.clockSize)
+                fakeKeyguardClockRepository.setClockSize(ClockSize.SMALL)
+                assertThat(clockSize).isEqualTo(ClockSize.SMALL)
             }
         }
 
@@ -94,18 +100,21 @@
     fun areNotificationsVisible_splitShadeTrue_true() =
         with(kosmos) {
             testScope.runTest {
+                val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
                 shadeRepository.setShadeMode(ShadeMode.Split)
-                kosmos.fakeKeyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
+                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
 
-                assertThat(collectLastValue(underTest.areNotificationsVisible).invoke()).isTrue()
+                assertThat(areNotificationsVisible).isTrue()
             }
         }
+
     @Test
     fun areNotificationsVisible_withSmallClock_true() =
         with(kosmos) {
             testScope.runTest {
-                kosmos.fakeKeyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL)
-                assertThat(collectLastValue(underTest.areNotificationsVisible).invoke()).isTrue()
+                val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
+                fakeKeyguardClockRepository.setClockSize(ClockSize.SMALL)
+                assertThat(areNotificationsVisible).isTrue()
             }
         }
 
@@ -113,8 +122,9 @@
     fun areNotificationsVisible_withLargeClock_false() =
         with(kosmos) {
             testScope.runTest {
-                kosmos.fakeKeyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-                assertThat(collectLastValue(underTest.areNotificationsVisible).invoke()).isFalse()
+                val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
+                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
+                assertThat(areNotificationsVisible).isFalse()
             }
         }
 
@@ -122,9 +132,10 @@
     fun shouldUseSplitNotificationShade_withConfigTrue_true() =
         with(kosmos) {
             testScope.runTest {
+                val shouldUseSplitNotificationShade by
+                    collectLastValue(underTest.shouldUseSplitNotificationShade)
                 shadeRepository.setShadeMode(ShadeMode.Split)
-                assertThat(collectLastValue(underTest.shouldUseSplitNotificationShade).invoke())
-                    .isTrue()
+                assertThat(shouldUseSplitNotificationShade).isTrue()
             }
         }
 
@@ -132,9 +143,53 @@
     fun shouldUseSplitNotificationShade_withConfigFalse_false() =
         with(kosmos) {
             testScope.runTest {
+                val shouldUseSplitNotificationShade by
+                    collectLastValue(underTest.shouldUseSplitNotificationShade)
                 shadeRepository.setShadeMode(ShadeMode.Single)
-                assertThat(collectLastValue(underTest.shouldUseSplitNotificationShade).invoke())
-                    .isFalse()
+                assertThat(shouldUseSplitNotificationShade).isFalse()
             }
         }
+
+    @Test
+    fun unfoldTranslations() =
+        with(kosmos) {
+            testScope.runTest {
+                val maxTranslation = prepareConfiguration()
+                val translations by collectLastValue(underTest.unfoldTranslations)
+
+                val unfoldProvider = fakeUnfoldTransitionProgressProvider
+                unfoldProvider.onTransitionStarted()
+                assertThat(translations?.start).isEqualTo(0f)
+                assertThat(translations?.end).isEqualTo(-0f)
+
+                repeat(10) { repetition ->
+                    val transitionProgress = 0.1f * (repetition + 1)
+                    unfoldProvider.onTransitionProgress(transitionProgress)
+                    assertThat(translations?.start)
+                        .isEqualTo((1 - transitionProgress) * maxTranslation)
+                    assertThat(translations?.end)
+                        .isEqualTo(-(1 - transitionProgress) * maxTranslation)
+                }
+
+                unfoldProvider.onTransitionFinishing()
+                assertThat(translations?.start).isEqualTo(0f)
+                assertThat(translations?.end).isEqualTo(-0f)
+
+                unfoldProvider.onTransitionFinished()
+                assertThat(translations?.start).isEqualTo(0f)
+                assertThat(translations?.end).isEqualTo(-0f)
+            }
+        }
+
+    private fun prepareConfiguration(): Int {
+        val configuration = context.resources.configuration
+        configuration.setLayoutDirection(Locale.US)
+        kosmos.fakeConfigurationRepository.onConfigurationChange(configuration)
+        val maxTranslation = 10
+        kosmos.fakeConfigurationRepository.setDimensionPixelSize(
+            R.dimen.notification_side_paddings,
+            maxTranslation,
+        )
+        return maxTranslation
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 66f7e01..776f1a5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -34,6 +34,8 @@
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.shared.model.WakefulnessState
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.data.repository.shadeRepository
@@ -43,6 +45,7 @@
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
+import kotlin.math.pow
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
 import org.junit.BeforeClass
@@ -57,22 +60,26 @@
 class LockscreenSceneViewModelTest : SysuiTestCase() {
 
     companion object {
+        private const val parameterCount = 6
+
         @Parameters(
             name =
                 "canSwipeToEnter={0}, downWithTwoPointers={1}, downFromEdge={2}," +
-                    " isSingleShade={3}, isCommunalAvailable={4}"
+                    " isSingleShade={3}, isCommunalAvailable={4}, isShadeTouchable={5}"
         )
         @JvmStatic
         fun combinations() = buildList {
-            repeat(32) { combination ->
+            repeat(2f.pow(parameterCount).toInt()) { combination ->
                 add(
                     arrayOf(
-                        /* canSwipeToEnter= */ combination and 1 != 0,
-                        /* downWithTwoPointers= */ combination and 2 != 0,
-                        /* downFromEdge= */ combination and 4 != 0,
-                        /* isSingleShade= */ combination and 8 != 0,
-                        /* isCommunalAvailable= */ combination and 16 != 0,
-                    )
+                            /* canSwipeToEnter= */ combination and 1 != 0,
+                            /* downWithTwoPointers= */ combination and 2 != 0,
+                            /* downFromEdge= */ combination and 4 != 0,
+                            /* isSingleShade= */ combination and 8 != 0,
+                            /* isCommunalAvailable= */ combination and 16 != 0,
+                            /* isShadeTouchable= */ combination and 32 != 0,
+                        )
+                        .also { check(it.size == parameterCount) }
                 )
             }
         }
@@ -82,8 +89,15 @@
         fun setUp() {
             val combinationStrings =
                 combinations().map { array ->
-                    check(array.size == 5)
-                    "${array[4]},${array[3]},${array[2]},${array[1]},${array[0]}"
+                    check(array.size == parameterCount)
+                    buildString {
+                        ((parameterCount - 1) downTo 0).forEach { index ->
+                            append("${array[index]}")
+                            if (index > 0) {
+                                append(",")
+                            }
+                        }
+                    }
                 }
             val uniqueCombinations = combinationStrings.toSet()
             assertThat(combinationStrings).hasSize(uniqueCombinations.size)
@@ -92,8 +106,35 @@
         private fun expectedDownDestination(
             downFromEdge: Boolean,
             isSingleShade: Boolean,
-        ): SceneKey {
-            return if (downFromEdge && isSingleShade) Scenes.QuickSettings else Scenes.Shade
+            isShadeTouchable: Boolean,
+        ): SceneKey? {
+            return when {
+                !isShadeTouchable -> null
+                downFromEdge && isSingleShade -> Scenes.QuickSettings
+                else -> Scenes.Shade
+            }
+        }
+
+        private fun expectedUpDestination(
+            canSwipeToEnter: Boolean,
+            isShadeTouchable: Boolean,
+        ): SceneKey? {
+            return when {
+                !isShadeTouchable -> null
+                canSwipeToEnter -> Scenes.Gone
+                else -> Scenes.Bouncer
+            }
+        }
+
+        private fun expectedLeftDestination(
+            isCommunalAvailable: Boolean,
+            isShadeTouchable: Boolean,
+        ): SceneKey? {
+            return when {
+                !isShadeTouchable -> null
+                isCommunalAvailable -> Scenes.Communal
+                else -> null
+            }
         }
     }
 
@@ -106,6 +147,7 @@
     @JvmField @Parameter(2) var downFromEdge: Boolean = false
     @JvmField @Parameter(3) var isSingleShade: Boolean = true
     @JvmField @Parameter(4) var isCommunalAvailable: Boolean = false
+    @JvmField @Parameter(5) var isShadeTouchable: Boolean = false
 
     private val underTest by lazy { createLockscreenSceneViewModel() }
 
@@ -130,6 +172,14 @@
                 }
             )
             kosmos.setCommunalAvailable(isCommunalAvailable)
+            kosmos.fakePowerRepository.updateWakefulness(
+                rawState =
+                    if (isShadeTouchable) {
+                        WakefulnessState.AWAKE
+                    } else {
+                        WakefulnessState.ASLEEP
+                    },
+            )
 
             val destinationScenes by collectLastValue(underTest.destinationScenes)
 
@@ -148,14 +198,25 @@
                     expectedDownDestination(
                         downFromEdge = downFromEdge,
                         isSingleShade = isSingleShade,
+                        isShadeTouchable = isShadeTouchable,
                     )
                 )
 
             assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.toScene)
-                .isEqualTo(if (canSwipeToEnter) Scenes.Gone else Scenes.Bouncer)
+                .isEqualTo(
+                    expectedUpDestination(
+                        canSwipeToEnter = canSwipeToEnter,
+                        isShadeTouchable = isShadeTouchable,
+                    )
+                )
 
             assertThat(destinationScenes?.get(Swipe(SwipeDirection.Left))?.toScene)
-                .isEqualTo(Scenes.Communal.takeIf { isCommunalAvailable })
+                .isEqualTo(
+                    expectedLeftDestination(
+                        isCommunalAvailable = isCommunalAvailable,
+                        isShadeTouchable = isShadeTouchable,
+                    )
+                )
         }
 
     private fun createLockscreenSceneViewModel(): LockscreenSceneViewModel {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index dddf648..4c16a33 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -49,9 +49,7 @@
     val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
     val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
     val configurationRepository = kosmos.fakeConfigurationRepository
-    val underTest by lazy {
-        kosmos.occludedToLockscreenTransitionViewModel
-    }
+    val underTest by lazy { kosmos.occludedToLockscreenTransitionViewModel }
 
     @Test
     fun lockscreenFadeIn() =
@@ -164,25 +162,6 @@
             values.forEach { assertThat(it).isEqualTo(1f) }
         }
 
-    @Test
-    fun deviceEntryBackgroundView_noUdfpsEnrolled_noUpdates() =
-        testScope.runTest {
-            fingerprintPropertyRepository.supportsRearFps()
-            biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
-            val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
-
-            keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED))
-            keyguardTransitionRepository.sendTransitionStep(step(0.1f))
-            keyguardTransitionRepository.sendTransitionStep(step(0.3f))
-            keyguardTransitionRepository.sendTransitionStep(step(0.4f))
-            keyguardTransitionRepository.sendTransitionStep(step(0.5f))
-            keyguardTransitionRepository.sendTransitionStep(step(0.6f))
-            keyguardTransitionRepository.sendTransitionStep(step(0.8f))
-            keyguardTransitionRepository.sendTransitionStep(step(1f))
-
-            assertThat(values).isEmpty() // no updates
-        }
-
     private fun step(
         value: Float,
         state: TransitionState = TransitionState.RUNNING
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index db1d5d9..18e9009 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -44,10 +44,7 @@
 class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
     val kosmos =
         testKosmos().apply {
-            fakeFeatureFlagsClassic.apply {
-                set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
-                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-            }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     val testScope = kosmos.testScope
 
@@ -58,6 +55,7 @@
 
     @Before
     fun setUp() {
+        mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT)
         whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
         sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(false)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt
index f400cb1..0588b1c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt
@@ -59,6 +59,7 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -69,6 +70,7 @@
     private val kosmos = testKosmos()
     private lateinit var underTest: SideFpsProgressBarViewModel
     private val testScope = kosmos.testScope
+    private val dozeServiceHost = spy(kosmos.dozeServiceHost)
     private lateinit var mTestableLooper: TestableLooper
 
     @Before
@@ -175,7 +177,7 @@
 
             runCurrent()
 
-            verify(kosmos.dozeServiceHost).fireSideFpsAcquisitionStarted()
+            verify(dozeServiceHost).fireSideFpsAcquisitionStarted()
         }
 
     private fun createViewModel() =
@@ -184,7 +186,7 @@
             kosmos.biometricStatusInteractor,
             kosmos.deviceEntryFingerprintAuthInteractor,
             kosmos.sideFpsSensorInteractor,
-            kosmos.dozeServiceHost,
+            dozeServiceHost,
             kosmos.keyguardInteractor,
             kosmos.displayStateInteractor,
             kosmos.testDispatcher,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt
index 956ef66..1e5f314 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt
@@ -25,8 +25,11 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.media.controls.MediaTestHelper
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
 import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runTest
@@ -144,8 +147,176 @@
             assertThat(smartspaceMediaData?.isActive).isFalse()
         }
 
+    @Test
+    fun addMediaControlPlayingThenRemote() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(underTest.sortedMedia)
+            val playingInstanceId = InstanceId.fakeInstanceId(123)
+            val remoteInstanceId = InstanceId.fakeInstanceId(321)
+            val playingData = createMediaData("app1", true, LOCAL, false, playingInstanceId)
+            val remoteData = createMediaData("app2", true, REMOTE, false, remoteInstanceId)
+
+            underTest.addSelectedUserMediaEntry(playingData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId))
+            underTest.addSelectedUserMediaEntry(remoteData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(remoteInstanceId))
+
+            assertThat(sortedMedia?.size).isEqualTo(2)
+            assertThat(sortedMedia?.values)
+                .containsExactly(
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId)),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(remoteInstanceId))
+                )
+                .inOrder()
+        }
+
+    @Test
+    fun switchMediaControlsPlaying() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(underTest.sortedMedia)
+            val playingInstanceId1 = InstanceId.fakeInstanceId(123)
+            val playingInstanceId2 = InstanceId.fakeInstanceId(321)
+            var playingData1 = createMediaData("app1", true, LOCAL, false, playingInstanceId1)
+            var playingData2 = createMediaData("app2", false, LOCAL, false, playingInstanceId2)
+
+            underTest.addSelectedUserMediaEntry(playingData1)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId1))
+            underTest.addSelectedUserMediaEntry(playingData2)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId2))
+
+            assertThat(sortedMedia?.size).isEqualTo(2)
+            assertThat(sortedMedia?.values)
+                .containsExactly(
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId1)),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId2))
+                )
+                .inOrder()
+
+            playingData1 = createMediaData("app1", false, LOCAL, false, playingInstanceId1)
+            playingData2 = createMediaData("app2", true, LOCAL, false, playingInstanceId2)
+
+            underTest.addSelectedUserMediaEntry(playingData1)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId1))
+            underTest.addSelectedUserMediaEntry(playingData2)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId2))
+
+            assertThat(sortedMedia?.size).isEqualTo(2)
+            assertThat(sortedMedia?.values)
+                .containsExactly(
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId2)),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId1))
+                )
+                .inOrder()
+        }
+
+    @Test
+    fun fullOrderTest() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(underTest.sortedMedia)
+            val instanceId1 = InstanceId.fakeInstanceId(123)
+            val instanceId2 = InstanceId.fakeInstanceId(456)
+            val instanceId3 = InstanceId.fakeInstanceId(321)
+            val instanceId4 = InstanceId.fakeInstanceId(654)
+            val instanceId5 = InstanceId.fakeInstanceId(124)
+            val playingAndLocalData = createMediaData("app1", true, LOCAL, false, instanceId1)
+            val playingAndRemoteData = createMediaData("app2", true, REMOTE, false, instanceId2)
+            val stoppedAndLocalData = createMediaData("app3", false, LOCAL, false, instanceId3)
+            val stoppedAndRemoteData = createMediaData("app4", false, REMOTE, false, instanceId4)
+            val canResumeData = createMediaData("app5", false, LOCAL, true, instanceId5)
+
+            val icon = Icon.createWithResource(context, R.drawable.ic_media_play)
+            val mediaRecommendations =
+                SmartspaceMediaData(
+                    targetId = KEY_MEDIA_SMARTSPACE,
+                    isActive = true,
+                    recommendations = MediaTestHelper.getValidRecommendationList(icon),
+                )
+
+            underTest.addSelectedUserMediaEntry(stoppedAndLocalData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId3))
+
+            underTest.addSelectedUserMediaEntry(stoppedAndRemoteData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId4))
+
+            underTest.addSelectedUserMediaEntry(canResumeData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId5))
+
+            underTest.addSelectedUserMediaEntry(playingAndLocalData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId1))
+
+            underTest.addSelectedUserMediaEntry(playingAndRemoteData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId2))
+
+            underTest.setRecommendation(mediaRecommendations)
+            underTest.setRecommendationsLoadingState(
+                SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
+            )
+
+            assertThat(sortedMedia?.size).isEqualTo(6)
+            assertThat(sortedMedia?.values)
+                .containsExactly(
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId1)),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId2)),
+                    MediaCommonModel.MediaRecommendations(
+                        SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
+                    ),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId4)),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId3)),
+                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId5)),
+                )
+                .inOrder()
+        }
+
+    @Test
+    fun loadMediaFromRec() =
+        testScope.runTest {
+            val isMediaFromRec by collectLastValue(underTest.isMediaFromRec)
+            val instanceId1 = InstanceId.fakeInstanceId(123)
+            val instanceId2 = InstanceId.fakeInstanceId(456)
+            val data =
+                MediaData(
+                    active = true,
+                    instanceId = instanceId1,
+                    packageName = PACKAGE_NAME,
+                    isPlaying = true
+                )
+            val newData = MediaData(active = true, instanceId = instanceId2)
+
+            assertThat(isMediaFromRec).isFalse()
+
+            underTest.setMediaFromRecPackageName(PACKAGE_NAME)
+            underTest.addSelectedUserMediaEntry(data)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId1))
+
+            assertThat(isMediaFromRec).isTrue()
+
+            underTest.addSelectedUserMediaEntry(newData)
+            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId2))
+
+            assertThat(isMediaFromRec).isFalse()
+        }
+
+    private fun createMediaData(
+        app: String,
+        playing: Boolean,
+        playbackLocation: Int,
+        isResume: Boolean,
+        instanceId: InstanceId,
+    ): MediaData {
+        return MediaData(
+            playbackLocation = playbackLocation,
+            resumption = isResume,
+            notificationKey = "key: $app",
+            isPlaying = playing,
+            instanceId = instanceId
+        )
+    }
+
     companion object {
+        private const val LOCAL = MediaData.PLAYBACK_LOCAL
+        private const val REMOTE = MediaData.PLAYBACK_CAST_LOCAL
         private const val KEY = "KEY"
         private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
+        private const val PACKAGE_NAME = "com.android.example"
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
index d9d84f2..e44affc7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Icon
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
@@ -29,12 +30,18 @@
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
 import com.android.systemui.media.controls.data.repository.mediaFilterRepository
 import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaRecommendationsInteractor
 import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaRecommendationsInteractor
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
 import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runTest
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -46,8 +53,16 @@
     private val testScope = kosmos.testScope
 
     private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository
+    private val mediaRecommendationsInteractor: MediaRecommendationsInteractor =
+        kosmos.mediaRecommendationsInteractor
+
     private val underTest: MediaCarouselInteractor = kosmos.mediaCarouselInteractor
 
+    @Before
+    fun setUp() {
+        underTest.start()
+    }
+
     @Test
     fun addUserMediaEntry_activeThenInactivate() =
         testScope.runTest {
@@ -56,7 +71,7 @@
             val hasActiveMedia by collectLastValue(underTest.hasActiveMedia)
             val hasAnyMedia by collectLastValue(underTest.hasAnyMedia)
 
-            val userMedia = MediaData().copy(active = true)
+            val userMedia = MediaData(active = true)
 
             mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
 
@@ -79,10 +94,11 @@
             val hasActiveMedia by collectLastValue(underTest.hasActiveMedia)
             val hasAnyMedia by collectLastValue(underTest.hasAnyMedia)
 
-            val userMedia = MediaData().copy(active = false)
+            val userMedia = MediaData(active = false)
             val instanceId = userMedia.instanceId
 
             mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
 
             assertThat(hasActiveMediaOrRecommendation).isFalse()
             assertThat(hasActiveMedia).isFalse()
@@ -90,6 +106,9 @@
 
             assertThat(mediaFilterRepository.removeSelectedUserMediaEntry(instanceId, userMedia))
                 .isTrue()
+            mediaFilterRepository.addMediaDataLoadingState(
+                MediaDataLoadingModel.Removed(instanceId)
+            )
 
             assertThat(hasActiveMediaOrRecommendation).isFalse()
             assertThat(hasActiveMedia).isFalse()
@@ -103,6 +122,7 @@
                 collectLastValue(underTest.hasActiveMediaOrRecommendation)
             val hasAnyMediaOrRecommendation by
                 collectLastValue(underTest.hasAnyMediaOrRecommendation)
+            val sortedMedia by collectLastValue(underTest.sortedMedia)
             kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
 
             val icon = Icon.createWithResource(context, R.drawable.ic_media_play)
@@ -112,17 +132,29 @@
                     isActive = true,
                     recommendations = MediaTestHelper.getValidRecommendationList(icon),
                 )
-            val userMedia = MediaData().copy(active = false)
+            val userMedia = MediaData(active = false)
+            val recsLoadingModel = SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
+            val mediaLoadingModel = MediaDataLoadingModel.Loaded(userMedia.instanceId)
 
             mediaFilterRepository.setRecommendation(userMediaRecommendation)
+            mediaFilterRepository.setRecommendationsLoadingState(recsLoadingModel)
 
             assertThat(hasActiveMediaOrRecommendation).isTrue()
             assertThat(hasAnyMediaOrRecommendation).isTrue()
+            assertThat(sortedMedia)
+                .containsExactly(MediaCommonModel.MediaRecommendations(recsLoadingModel))
 
             mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            mediaFilterRepository.addMediaDataLoadingState(mediaLoadingModel)
 
             assertThat(hasActiveMediaOrRecommendation).isTrue()
             assertThat(hasAnyMediaOrRecommendation).isTrue()
+            assertThat(sortedMedia)
+                .containsExactly(
+                    MediaCommonModel.MediaRecommendations(recsLoadingModel),
+                    MediaCommonModel.MediaControl(mediaLoadingModel, true)
+                )
+                .inOrder()
         }
 
     @Test
@@ -199,7 +231,29 @@
     fun hasActiveMediaOrRecommendation_nothingSet_returnsFalse() =
         testScope.runTest { assertThat(underTest.hasActiveMediaOrRecommendation.value).isFalse() }
 
+    @Test
+    fun loadMediaFromRec() =
+        testScope.runTest {
+            val isMediaFromRec by collectLastValue(underTest.isMediaFromRec)
+            val instanceId = InstanceId.fakeInstanceId(123)
+            val data = MediaData(active = true, instanceId = instanceId, packageName = PACKAGE_NAME)
+
+            assertThat(isMediaFromRec).isFalse()
+
+            mediaRecommendationsInteractor.switchToMediaControl(PACKAGE_NAME)
+            mediaFilterRepository.addSelectedUserMediaEntry(data)
+            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+
+            assertThat(isMediaFromRec).isFalse()
+
+            mediaFilterRepository.addSelectedUserMediaEntry(data.copy(isPlaying = true))
+            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+
+            assertThat(isMediaFromRec).isTrue()
+        }
+
     companion object {
         private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
+        private const val PACKAGE_NAME = "com.android.example"
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt
index a1cee8a..d9224d7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaControlInteractorTest.kt
@@ -16,10 +16,17 @@
 
 package com.android.systemui.media.controls.domain.interactor
 
+import android.app.PendingIntent
+import android.os.Bundle
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.InstanceId
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.activityIntentHelper
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
+import com.android.systemui.bluetooth.mockBroadcastDialogController
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl
@@ -28,13 +35,22 @@
 import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.util.mediaInstanceId
+import com.android.systemui.media.mediaOutputDialogManager
+import com.android.systemui.mockActivityIntentHelper
+import com.android.systemui.plugins.activityStarter
 import com.android.systemui.statusbar.notificationLockscreenUserManager
+import com.android.systemui.statusbar.policy.keyguardStateController
 import com.android.systemui.testKosmos
+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.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
@@ -44,10 +60,16 @@
     private val testScope = kosmos.testScope
 
     private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter
+    private val activityStarter = kosmos.activityStarter
+    private val keyguardStateController = kosmos.keyguardStateController
     private val instanceId: InstanceId = kosmos.mediaInstanceId
     private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager
 
-    private val underTest: MediaControlInteractor = kosmos.mediaControlInteractor
+    private val underTest: MediaControlInteractor =
+        with(kosmos) {
+            activityIntentHelper = mockActivityIntentHelper
+            kosmos.mediaControlInteractor
+        }
 
     @Test
     fun onMediaDataUpdated() =
@@ -55,39 +77,146 @@
             whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
             whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
             val controlModel by collectLastValue(underTest.mediaControl)
-            var mediaData =
-                MediaData(userId = USER_ID, instanceId = instanceId, artist = SESSION_ARTIST)
+            var mediaData = MediaData(userId = USER_ID, instanceId = instanceId, artist = ARTIST)
 
             mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData)
 
             assertThat(controlModel?.instanceId).isEqualTo(instanceId)
-            assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST)
+            assertThat(controlModel?.artistName).isEqualTo(ARTIST)
 
-            mediaData =
-                MediaData(userId = USER_ID, instanceId = instanceId, artist = SESSION_ARTIST_2)
+            mediaData = MediaData(userId = USER_ID, instanceId = instanceId, artist = ARTIST_2)
 
             mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData)
 
             assertThat(controlModel?.instanceId).isEqualTo(instanceId)
-            assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST_2)
+            assertThat(controlModel?.artistName).isEqualTo(ARTIST_2)
 
             mediaData =
                 MediaData(
                     userId = USER_ID,
                     instanceId = InstanceId.fakeInstanceId(2),
-                    artist = SESSION_ARTIST
+                    artist = ARTIST
                 )
 
             mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData)
 
             assertThat(controlModel?.instanceId).isNotEqualTo(mediaData.instanceId)
-            assertThat(controlModel?.artistName).isEqualTo(SESSION_ARTIST_2)
+            assertThat(controlModel?.artistName).isEqualTo(ARTIST_2)
         }
 
+    @Test
+    fun startSettings() {
+        underTest.startSettings()
+
+        verify(activityStarter).startActivity(any(), eq(true))
+    }
+
+    @Test
+    fun startClickIntent_showOverLockscreen() {
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+        whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any()))
+            .thenReturn(true)
+
+        val clickIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) }
+        val expandable = mock<Expandable>()
+
+        underTest.startClickIntent(expandable, clickIntent)
+
+        verify(clickIntent).send(any<Bundle>())
+    }
+
+    @Test
+    fun startClickIntent_hideOverLockscreen() {
+        whenever(keyguardStateController.isShowing).thenReturn(false)
+
+        val clickIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) }
+        val expandable = mock<Expandable>()
+        val activityController = mock<ActivityTransitionAnimator.Controller>()
+        whenever(expandable.activityTransitionController(any())).thenReturn(activityController)
+
+        underTest.startClickIntent(expandable, clickIntent)
+
+        verify(activityStarter)
+            .postStartActivityDismissingKeyguard(eq(clickIntent), eq(activityController))
+    }
+
+    @Test
+    fun startDeviceIntent_showOverLockscreen() {
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+        whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any()))
+            .thenReturn(true)
+
+        val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) }
+
+        underTest.startDeviceIntent(deviceIntent)
+
+        verify(deviceIntent).send(any<Bundle>())
+    }
+
+    @Test
+    fun startDeviceIntent_intentNotActivity() {
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+        whenever(kosmos.activityIntentHelper.wouldPendingShowOverLockscreen(any(), any()))
+            .thenReturn(true)
+
+        val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(false) }
+
+        underTest.startDeviceIntent(deviceIntent)
+
+        verify(deviceIntent, never()).send(any<Bundle>())
+    }
+
+    @Test
+    fun startDeviceIntent_hideOverLockscreen() {
+        whenever(keyguardStateController.isShowing).thenReturn(false)
+
+        val deviceIntent = mock<PendingIntent> { whenever(isActivity).thenReturn(true) }
+
+        underTest.startDeviceIntent(deviceIntent)
+
+        verify(activityStarter).postStartActivityDismissingKeyguard(eq(deviceIntent))
+    }
+
+    @Test
+    fun startMediaOutputDialog() {
+        val expandable = mock<Expandable>()
+        val dialogTransitionController = mock<DialogTransitionAnimator.Controller>()
+        whenever(expandable.dialogTransitionController(any()))
+            .thenReturn(dialogTransitionController)
+
+        underTest.startMediaOutputDialog(expandable, PACKAGE_NAME)
+
+        verify(kosmos.mediaOutputDialogManager)
+            .createAndShowWithController(
+                eq(PACKAGE_NAME),
+                eq(true),
+                eq(dialogTransitionController),
+                eq(null)
+            )
+    }
+
+    @Test
+    fun startBroadcastDialog() {
+        val expandable = mock<Expandable>()
+        val dialogTransitionController = mock<DialogTransitionAnimator.Controller>()
+        whenever(expandable.dialogTransitionController()).thenReturn(dialogTransitionController)
+
+        underTest.startBroadcastDialog(expandable, APP_NAME, PACKAGE_NAME)
+
+        verify(kosmos.mockBroadcastDialogController)
+            .createBroadcastDialogWithController(
+                eq(APP_NAME),
+                eq(PACKAGE_NAME),
+                eq(dialogTransitionController)
+            )
+    }
+
     companion object {
         private const val USER_ID = 0
         private const val KEY = "key"
-        private const val SESSION_ARTIST = "artist"
-        private const val SESSION_ARTIST_2 = "artist2"
+        private const val PACKAGE_NAME = "com.example.app"
+        private const val APP_NAME = "app"
+        private const val ARTIST = "artist"
+        private const val ARTIST_2 = "artist2"
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt
new file mode 100644
index 0000000..71685a4
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.util
+
+import androidx.recyclerview.widget.DiffUtil
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.media.controls.ui.viewmodel.MediaCommonViewModel
+import com.android.systemui.media.controls.ui.viewmodel.mediaControlViewModel
+import com.android.systemui.media.controls.ui.viewmodel.mediaRecommendationsViewModel
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MediaDiffUtilTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+
+    @Test
+    fun newMediaControlAdded() {
+        val mediaControl = createMediaControl(InstanceId.fakeInstanceId(123), true)
+        val oldList = listOf<MediaCommonViewModel>()
+        val newList = listOf(mediaControl)
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> assertThat(commonViewModel).isEqualTo(mediaControl) },
+                { fail("Unexpected to update $it") },
+                { fail("Unexpected to remove $it") },
+                { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun newMediaRecommendationsAdded() {
+        val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE, true)
+        val oldList = listOf<MediaCommonViewModel>()
+        val newList = listOf(mediaRecs)
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
+                { fail("Unexpected to update $it") },
+                { fail("Unexpected to remove $it") },
+                { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun updateMediaControl_contentChanged() {
+        val mediaControl = createMediaControl(InstanceId.fakeInstanceId(123), true)
+        val oldList = listOf(mediaControl)
+        val newList = listOf(mediaControl.copy(immediatelyUpdateUi = false))
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
+                { commonViewModel -> assertThat(commonViewModel).isNotEqualTo(mediaControl) },
+                { fail("Unexpected to remove $it") },
+                { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun updateMediaRecommendations_contentChanged() {
+        val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE, true)
+        val oldList = listOf(mediaRecs)
+        val newList = listOf(mediaRecs.copy(key = KEY_MEDIA_SMARTSPACE_2))
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
+                { commonViewModel -> assertThat(commonViewModel).isNotEqualTo(mediaRecs) },
+                { fail("Unexpected to remove $it") },
+                { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun mediaControlMoved() {
+        val mediaControl1 = createMediaControl(InstanceId.fakeInstanceId(123), true)
+        val mediaControl2 = createMediaControl(InstanceId.fakeInstanceId(456), false)
+        val oldList = listOf(mediaControl1, mediaControl2)
+        val newList = listOf(mediaControl2, mediaControl1)
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
+                { fail("Unexpected to update $it") },
+                { fail("Unexpected to remove $it") },
+                { commonViewModel, _, _ -> assertThat(commonViewModel).isEqualTo(mediaControl1) },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun mediaRecommendationsMoved() {
+        val mediaControl1 = createMediaControl(InstanceId.fakeInstanceId(123), true)
+        val mediaControl2 = createMediaControl(InstanceId.fakeInstanceId(456), false)
+        val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE, true)
+        val oldList = listOf(mediaRecs, mediaControl1, mediaControl2)
+        val newList = listOf(mediaControl1, mediaControl2, mediaRecs)
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
+                { fail("Unexpected to update $it") },
+                { fail("Unexpected to remove $it") },
+                { commonViewModel, _, _ -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun mediaControlRemoved() {
+        val mediaControl = createMediaControl(InstanceId.fakeInstanceId(123), true)
+        val oldList = listOf(mediaControl)
+        val newList = listOf<MediaCommonViewModel>()
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
+                { fail("Unexpected to update $it") },
+                { commonViewModel -> assertThat(commonViewModel).isEqualTo(mediaControl) },
+                { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    @Test
+    fun mediaRecommendationsRemoved() {
+        val mediaRecs = createMediaRecommendations(KEY_MEDIA_SMARTSPACE_2, false)
+        val oldList = listOf(mediaRecs)
+        val newList = listOf<MediaCommonViewModel>()
+        val mediaLoadedCallback = MediaViewModelCallback(oldList, newList)
+        val mediaLoadedListUpdateCallback =
+            MediaViewModelListUpdateCallback(
+                oldList,
+                newList,
+                { commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
+                { fail("Unexpected to update $it") },
+                { commonViewModel -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
+                { commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
+            )
+
+        DiffUtil.calculateDiff(mediaLoadedCallback).dispatchUpdatesTo(mediaLoadedListUpdateCallback)
+    }
+
+    private fun createMediaControl(
+        instanceId: InstanceId,
+        immediatelyUpdateUi: Boolean,
+    ): MediaCommonViewModel.MediaControl {
+        return MediaCommonViewModel.MediaControl(
+            instanceId = instanceId,
+            immediatelyUpdateUi = immediatelyUpdateUi,
+            controlViewModel = kosmos.mediaControlViewModel,
+            onAdded = {},
+            onRemoved = {},
+            onUpdated = {}
+        )
+    }
+
+    private fun createMediaRecommendations(
+        key: String,
+        loadingEnabled: Boolean,
+    ): MediaCommonViewModel.MediaRecommendations {
+        return MediaCommonViewModel.MediaRecommendations(
+            key = key,
+            loadingEnabled = loadingEnabled,
+            recsViewModel = kosmos.mediaRecommendationsViewModel,
+            onAdded = {},
+            onRemoved = {},
+            onUpdated = {}
+        )
+    }
+
+    companion object {
+        private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
+        private const val KEY_MEDIA_SMARTSPACE_2 = "MEDIA_SMARTSPACE_ID_2"
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt
new file mode 100644
index 0000000..d1e475f
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.R
+import android.content.packageManager
+import android.content.pm.ApplicationInfo
+import android.graphics.drawable.Icon
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.media.controls.MediaTestHelper
+import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaRecommendationsInteractor
+import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter
+import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.statusbar.notification.collection.provider.visualStabilityProvider
+import com.android.systemui.statusbar.notificationLockscreenUserManager
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MediaCarouselViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter
+    private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager
+    private val packageManager = kosmos.packageManager
+    private val icon = Icon.createWithResource(context, R.drawable.ic_media_play)
+    private val drawable = context.getDrawable(R.drawable.ic_media_play)
+    private val smartspaceMediaData: SmartspaceMediaData =
+        SmartspaceMediaData(
+            targetId = KEY_MEDIA_SMARTSPACE,
+            isActive = true,
+            packageName = PACKAGE_NAME,
+            recommendations = MediaTestHelper.getValidRecommendationList(icon),
+        )
+
+    private val underTest: MediaCarouselViewModel = kosmos.mediaCarouselViewModel
+
+    @Before
+    fun setUp() {
+        kosmos.mediaCarouselInteractor.start()
+
+        whenever(packageManager.getApplicationIcon(Mockito.anyString())).thenReturn(drawable)
+        whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
+            .thenReturn(drawable)
+        whenever(packageManager.getApplicationInfo(eq(PACKAGE_NAME), ArgumentMatchers.anyInt()))
+            .thenReturn(ApplicationInfo())
+        whenever(packageManager.getApplicationLabel(any())).thenReturn(PACKAGE_NAME)
+
+        context.setMockPackageManager(packageManager)
+    }
+
+    @Test
+    fun loadMediaControls_mediaItemsAreUpdated() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(underTest.mediaItems)
+            val instanceId1 = InstanceId.fakeInstanceId(123)
+            val instanceId2 = InstanceId.fakeInstanceId(456)
+
+            loadMediaControl(KEY, instanceId1)
+            loadMediaControl(KEY_2, instanceId2)
+
+            val firstMediaControl = sortedMedia?.get(0) as MediaCommonViewModel.MediaControl
+            val secondMediaControl = sortedMedia?.get(1) as MediaCommonViewModel.MediaControl
+            assertThat(firstMediaControl.instanceId).isEqualTo(instanceId2)
+            assertThat(secondMediaControl.instanceId).isEqualTo(instanceId1)
+        }
+
+    @Test
+    fun loadMediaControlsAndRecommendations_mediaItemsAreUpdated() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(underTest.mediaItems)
+            kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
+            val instanceId1 = InstanceId.fakeInstanceId(123)
+            val instanceId2 = InstanceId.fakeInstanceId(456)
+
+            loadMediaControl(KEY, instanceId1)
+            loadMediaControl(KEY_2, instanceId2)
+            loadMediaRecommendations()
+
+            val firstMediaControl = sortedMedia?.get(0) as MediaCommonViewModel.MediaControl
+            val secondMediaControl = sortedMedia?.get(1) as MediaCommonViewModel.MediaControl
+            val recsCard = sortedMedia?.get(2) as MediaCommonViewModel.MediaRecommendations
+            assertThat(firstMediaControl.instanceId).isEqualTo(instanceId2)
+            assertThat(secondMediaControl.instanceId).isEqualTo(instanceId1)
+            assertThat(recsCard.key).isEqualTo(KEY_MEDIA_SMARTSPACE)
+        }
+
+    @Test
+    fun recommendationClicked_switchToPlayer() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(underTest.mediaItems)
+            kosmos.visualStabilityProvider.isReorderingAllowed = false
+            kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
+            val instanceId = InstanceId.fakeInstanceId(123)
+
+            loadMediaRecommendations()
+            kosmos.mediaRecommendationsInteractor.switchToMediaControl(PACKAGE_NAME)
+
+            var recsCard = sortedMedia?.get(0) as MediaCommonViewModel.MediaRecommendations
+            assertThat(sortedMedia).hasSize(1)
+            assertThat(recsCard.key).isEqualTo(KEY_MEDIA_SMARTSPACE)
+
+            loadMediaControl(KEY, instanceId, false)
+
+            recsCard = sortedMedia?.get(0) as MediaCommonViewModel.MediaRecommendations
+            assertThat(sortedMedia).hasSize(1)
+            assertThat(recsCard.key).isEqualTo(KEY_MEDIA_SMARTSPACE)
+
+            loadMediaControl(KEY, instanceId, true)
+
+            val mediaControl = sortedMedia?.get(0) as MediaCommonViewModel.MediaControl
+            assertThat(sortedMedia).hasSize(2)
+            assertThat(mediaControl.instanceId).isEqualTo(instanceId)
+        }
+
+    private fun loadMediaControl(key: String, instanceId: InstanceId, isPlaying: Boolean = true) {
+        whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+        whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+        val mediaData =
+            MediaData(
+                userId = USER_ID,
+                packageName = PACKAGE_NAME,
+                notificationKey = key,
+                instanceId = instanceId,
+                isPlaying = isPlaying,
+            )
+
+        mediaDataFilter.onMediaDataLoaded(key, key, mediaData)
+    }
+
+    private fun loadMediaRecommendations(key: String = KEY_MEDIA_SMARTSPACE) {
+        mediaDataFilter.onSmartspaceMediaDataLoaded(key, smartspaceMediaData)
+    }
+
+    companion object {
+        private const val USER_ID = 0
+        private const val KEY = "key"
+        private const val KEY_2 = "key2"
+        private const val PACKAGE_NAME = "com.example.app"
+        private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt
new file mode 100644
index 0000000..9558e5d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.R
+import android.content.packageManager
+import android.content.pm.ApplicationInfo
+import android.media.MediaMetadata
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl
+import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter
+import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.util.mediaInstanceId
+import com.android.systemui.statusbar.notificationLockscreenUserManager
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MediaControlViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter
+    private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager
+    private val packageManager = kosmos.packageManager
+    private val drawable = context.getDrawable(R.drawable.ic_media_play)
+    private val instanceId: InstanceId = kosmos.mediaInstanceId
+
+    private val underTest: MediaControlViewModel = kosmos.mediaControlViewModel
+
+    @Test
+    fun addMediaControl_mediaControlViewModelIsLoaded() =
+        testScope.runTest {
+            whenever(packageManager.getApplicationIcon(Mockito.anyString())).thenReturn(drawable)
+            whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
+                .thenReturn(drawable)
+            whenever(packageManager.getApplicationInfo(eq(PACKAGE_NAME), ArgumentMatchers.anyInt()))
+                .thenReturn(ApplicationInfo())
+            whenever(packageManager.getApplicationLabel(any())).thenReturn(PACKAGE_NAME)
+            whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+            whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+            val playerModel by collectLastValue(underTest.player)
+
+            context.setMockPackageManager(packageManager)
+
+            val mediaData = initMediaData()
+
+            mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData)
+
+            assertThat(playerModel).isNotNull()
+            assertThat(playerModel?.titleName).isEqualTo(TITLE)
+            assertThat(playerModel?.artistName).isEqualTo(ARTIST)
+            assertThat(playerModel?.gutsMenu).isNotNull()
+            assertThat(playerModel?.outputSwitcher).isNotNull()
+            assertThat(playerModel?.actionButtons).isNotNull()
+            assertThat(playerModel?.playTurbulenceNoise).isFalse()
+        }
+
+    private fun initMediaData(): MediaData {
+        val device = MediaDeviceData(true, null, DEVICE_NAME, null, showBroadcastButton = true)
+
+        // Create media session
+        val metadataBuilder =
+            MediaMetadata.Builder().apply {
+                putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
+                putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
+            }
+        val playbackBuilder =
+            PlaybackState.Builder().apply {
+                setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
+                setActions(PlaybackState.ACTION_PLAY)
+            }
+        val session =
+            MediaSession(context, SESSION_KEY).apply {
+                setMetadata(metadataBuilder.build())
+                setPlaybackState(playbackBuilder.build())
+            }
+        session.isActive = true
+
+        return MediaData(
+            userId = USER_ID,
+            artist = ARTIST,
+            song = TITLE,
+            packageName = PACKAGE,
+            token = session.sessionToken,
+            device = device,
+            instanceId = instanceId
+        )
+    }
+
+    companion object {
+        private const val USER_ID = 0
+        private const val KEY = "key"
+        private const val PACKAGE_NAME = "com.example.app"
+        private const val PACKAGE = "PKG"
+        private const val ARTIST = "ARTIST"
+        private const val TITLE = "TITLE"
+        private const val DEVICE_NAME = "DEVICE_NAME"
+        private const val SESSION_KEY = "SESSION_KEY"
+        private const val SESSION_ARTIST = "SESSION_ARTIST"
+        private const val SESSION_TITLE = "SESSION_TITLE"
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt
index 6d6fd75..d0699aa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt
@@ -16,7 +16,9 @@
 
 package com.android.systemui.qs.pipeline.domain.autoaddable
 
-import android.platform.test.annotations.EnabledOnRavenwood
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.view.accessibility.Flags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -44,7 +46,6 @@
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@EnabledOnRavenwood
 @RunWith(AndroidJUnit4::class)
 class ReduceBrightColorsAutoAddableTest : SysuiTestCase() {
 
@@ -67,12 +68,14 @@
         }
 
     @Test
+    @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
     fun available_strategyIfNotAdded() =
         testWithFeatureAvailability(available = true) {
             assertThat(underTest.autoAddTracking).isEqualTo(AutoAddTracking.IfNotAdded(SPEC))
         }
 
     @Test
+    @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
     fun activated_addSignal() = testWithFeatureAvailability {
         val signal by collectLastValue(underTest.autoAddSignal(0))
         runCurrent()
@@ -85,6 +88,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
     fun notActivated_noSignal() = testWithFeatureAvailability {
         val signal by collectLastValue(underTest.autoAddSignal(0))
         runCurrent()
@@ -96,6 +100,13 @@
         assertThat(signal).isNull()
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+    fun available_a11yQsShortcutFlagEnabled_strategyDisabled() =
+        testWithFeatureAvailability(available = true) {
+            assertThat(underTest.autoAddTracking).isEqualTo(AutoAddTracking.Disabled)
+        }
+
     private fun testWithFeatureAvailability(
         available: Boolean = true,
         body: suspend TestScope.() -> TestResult
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractorTest.kt
new file mode 100644
index 0000000..2e5fde8
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractorTest.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor
+
+import android.os.UserHandle
+import android.platform.test.annotations.EnabledOnRavenwood
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.accessibility.reduceBrightColorsController
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.toCollection
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@EnabledOnRavenwood
+@RunWith(AndroidJUnit4::class)
+class ReduceBrightColorsTileDataInteractorTest : SysuiTestCase() {
+
+    private val isAvailable = true
+    private val kosmos = Kosmos()
+    private val testScope = kosmos.testScope
+    private val reduceBrightColorsController = kosmos.reduceBrightColorsController
+    private val underTest: ReduceBrightColorsTileDataInteractor =
+        ReduceBrightColorsTileDataInteractor(
+            testScope.testScheduler,
+            isAvailable,
+            reduceBrightColorsController
+        )
+
+    @Test
+    fun alwaysAvailable() =
+        testScope.runTest {
+            val availability = underTest.availability(TEST_USER).toCollection(mutableListOf())
+
+            assertThat(availability).hasSize(1)
+            assertThat(availability.last()).isEqualTo(isAvailable)
+        }
+
+    @Test
+    fun dataMatchesTheRepository() =
+        testScope.runTest {
+            val dataList: List<ReduceBrightColorsTileModel> by
+                collectValues(
+                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+                )
+            runCurrent()
+
+            reduceBrightColorsController.isReduceBrightColorsActivated = true
+            runCurrent()
+
+            reduceBrightColorsController.isReduceBrightColorsActivated = false
+            runCurrent()
+
+            assertThat(dataList).hasSize(3)
+            assertThat(dataList.map { it.isEnabled }).isEqualTo(listOf(false, true, false))
+        }
+
+    private companion object {
+        val TEST_USER = UserHandle.of(1)!!
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractorTest.kt
new file mode 100644
index 0000000..6ea5e63
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractorTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor
+
+import android.platform.test.annotations.EnabledOnRavenwood
+import android.provider.Settings
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.accessibility.reduceBrightColorsController
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
+import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@EnabledOnRavenwood
+@RunWith(AndroidJUnit4::class)
+class ReduceBrightColorsTileUserActionInteractorTest : SysuiTestCase() {
+
+    private val kosmos = Kosmos()
+    private val inputHandler = FakeQSTileIntentUserInputHandler()
+    private val controller = kosmos.reduceBrightColorsController
+
+    private val underTest =
+        ReduceBrightColorsTileUserActionInteractor(
+            inputHandler,
+            controller,
+        )
+
+    @Test
+    fun handleClickWhenEnabled() = runTest {
+        val wasEnabled = true
+        controller.isReduceBrightColorsActivated = wasEnabled
+
+        underTest.handleInput(QSTileInputTestKtx.click(ReduceBrightColorsTileModel(wasEnabled)))
+
+        assertThat(controller.isReduceBrightColorsActivated).isEqualTo(!wasEnabled)
+    }
+
+    @Test
+    fun handleClickWhenDisabled() = runTest {
+        val wasEnabled = false
+        controller.isReduceBrightColorsActivated = wasEnabled
+
+        underTest.handleInput(QSTileInputTestKtx.click(ReduceBrightColorsTileModel(wasEnabled)))
+
+        assertThat(controller.isReduceBrightColorsActivated).isEqualTo(!wasEnabled)
+    }
+
+    @Test
+    fun handleLongClickWhenDisabled() = runTest {
+        val enabled = false
+
+        underTest.handleInput(QSTileInputTestKtx.longClick(ReduceBrightColorsTileModel(enabled)))
+
+        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
+            assertThat(it.intent.action).isEqualTo(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS)
+        }
+    }
+
+    @Test
+    fun handleLongClickWhenEnabled() = runTest {
+        val enabled = true
+
+        underTest.handleInput(QSTileInputTestKtx.longClick(ReduceBrightColorsTileModel(enabled)))
+
+        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
+            assertThat(it.intent.action).isEqualTo(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS)
+        }
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt
new file mode 100644
index 0000000..10e9bd6
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.ui
+
+import android.graphics.drawable.TestStubDrawable
+import android.service.quicksettings.Tile
+import android.widget.Switch
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.android.systemui.qs.tiles.impl.reducebrightness.qsReduceBrightColorsTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ReduceBrightColorsTileMapperTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val config = kosmos.qsReduceBrightColorsTileConfig
+
+    private lateinit var mapper: ReduceBrightColorsTileMapper
+
+    @Before
+    fun setup() {
+        mapper =
+            ReduceBrightColorsTileMapper(
+                context.orCreateTestableResources
+                    .apply {
+                        addOverride(R.drawable.qs_extra_dim_icon_on, TestStubDrawable())
+                        addOverride(R.drawable.qs_extra_dim_icon_off, TestStubDrawable())
+                    }
+                    .resources,
+                context.theme
+            )
+    }
+
+    @Test
+    fun disabledModel() {
+        val inputModel = ReduceBrightColorsTileModel(false)
+
+        val outputState = mapper.map(config, inputModel)
+
+        val expectedState =
+            createReduceBrightColorsTileState(
+                QSTileState.ActivationState.INACTIVE,
+            )
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    @Test
+    fun enabledModel() {
+        val inputModel = ReduceBrightColorsTileModel(true)
+
+        val outputState = mapper.map(config, inputModel)
+
+        val expectedState = createReduceBrightColorsTileState(QSTileState.ActivationState.ACTIVE)
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    private fun createReduceBrightColorsTileState(
+        activationState: QSTileState.ActivationState,
+    ): QSTileState {
+        val label =
+            context.getString(com.android.internal.R.string.reduce_bright_colors_feature_name)
+        return QSTileState(
+            {
+                Icon.Loaded(
+                    context.getDrawable(
+                        if (activationState == QSTileState.ActivationState.ACTIVE)
+                            R.drawable.qs_extra_dim_icon_on
+                        else R.drawable.qs_extra_dim_icon_off
+                    )!!,
+                    null
+                )
+            },
+            label,
+            activationState,
+            context.resources
+                .getStringArray(R.array.tile_states_reduce_brightness)[
+                    if (activationState == QSTileState.ActivationState.ACTIVE) Tile.STATE_ACTIVE
+                    else Tile.STATE_INACTIVE],
+            setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK),
+            label,
+            null,
+            QSTileState.SideViewIcon.None,
+            QSTileState.EnabledState.ENABLED,
+            Switch::class.qualifiedName
+        )
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileDataInteractorTest.kt
new file mode 100644
index 0000000..954f691
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileDataInteractorTest.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor
+
+import android.os.UserHandle
+import android.platform.test.annotations.EnabledOnRavenwood
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.screenrecord.RecordingController
+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 kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@EnabledOnRavenwood
+@RunWith(AndroidJUnit4::class)
+class ScreenRecordTileDataInteractorTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val testScope = kosmos.testScope
+    private val controller = mock<RecordingController>()
+    private val underTest: ScreenRecordTileDataInteractor =
+        ScreenRecordTileDataInteractor(testScope.testScheduler, controller)
+
+    private val isRecording = ScreenRecordTileModel.Recording
+    private val isDoingNothing = ScreenRecordTileModel.DoingNothing
+    private val isStarting0 = ScreenRecordTileModel.Starting(0)
+
+    @Test
+    fun isAvailable_returnsTrue() = runTest {
+        val availability by collectLastValue(underTest.availability(TEST_USER))
+
+        assertThat(availability).isTrue()
+    }
+
+    @Test
+    fun dataMatchesController() =
+        testScope.runTest {
+            whenever(controller.isRecording).thenReturn(false)
+            whenever(controller.isStarting).thenReturn(false)
+
+            val callbackCaptor = argumentCaptor<RecordingController.RecordingStateChangeCallback>()
+
+            val lastModel by
+                collectLastValue(
+                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+                )
+            runCurrent()
+
+            verify(controller).addCallback(callbackCaptor.capture())
+            val callback = callbackCaptor.value
+
+            assertThat(lastModel).isEqualTo(isDoingNothing)
+
+            val expectedModelStartingIn1 = ScreenRecordTileModel.Starting(1)
+            callback.onCountdown(1)
+            assertThat(lastModel).isEqualTo(expectedModelStartingIn1)
+
+            val expectedModelStartingIn0 = isStarting0
+            callback.onCountdown(0)
+            assertThat(lastModel).isEqualTo(expectedModelStartingIn0)
+
+            callback.onCountdownEnd()
+            assertThat(lastModel).isEqualTo(isDoingNothing)
+
+            callback.onRecordingStart()
+            assertThat(lastModel).isEqualTo(isRecording)
+
+            callback.onRecordingEnd()
+            assertThat(lastModel).isEqualTo(isDoingNothing)
+        }
+
+    @Test
+    fun data_whenRecording_matchesController() =
+        testScope.runTest {
+            whenever(controller.isRecording).thenReturn(true)
+            whenever(controller.isStarting).thenReturn(false)
+
+            val lastModel by
+                collectLastValue(
+                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+                )
+            runCurrent()
+
+            assertThat(lastModel).isEqualTo(isRecording)
+        }
+
+    @Test
+    fun data_whenStarting_matchesController() =
+        testScope.runTest {
+            whenever(controller.isRecording).thenReturn(false)
+            whenever(controller.isStarting).thenReturn(true)
+
+            val lastModel by
+                collectLastValue(
+                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+                )
+            runCurrent()
+
+            assertThat(lastModel).isEqualTo(isStarting0)
+        }
+
+    @Test
+    fun data_whenRecordingAndStarting_matchesControllerRecording() =
+        testScope.runTest {
+            whenever(controller.isRecording).thenReturn(true)
+            whenever(controller.isStarting).thenReturn(true)
+
+            val lastModel by
+                collectLastValue(
+                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
+                )
+            runCurrent()
+
+            assertThat(lastModel).isEqualTo(isRecording)
+        }
+
+    private companion object {
+        val TEST_USER = UserHandle.of(1)!!
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
new file mode 100644
index 0000000..b9321d5
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor
+
+import android.app.Dialog
+import android.os.UserHandle
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.dialogTransitionAnimator
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.screenrecord.RecordingController
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ScreenRecordTileUserActionInteractorTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val testScope = kosmos.testScope
+    private val keyguardInteractor = kosmos.keyguardInteractor
+    private val dialogTransitionAnimator = mock<DialogTransitionAnimator>()
+    private val featureFlags = kosmos.featureFlagsClassic
+    private val activityStarter = kosmos.activityStarter
+    private val keyguardDismissUtil = mock<KeyguardDismissUtil>()
+    private val panelInteractor = mock<PanelInteractor>()
+    private val dialog = mock<Dialog>()
+    private val recordingController =
+        mock<RecordingController> {
+            whenever(
+                    createScreenRecordDialog(
+                        eq(context),
+                        eq(featureFlags),
+                        eq(dialogTransitionAnimator),
+                        eq(activityStarter),
+                        any()
+                    )
+                )
+                .thenReturn(dialog)
+        }
+
+    private val underTest =
+        ScreenRecordTileUserActionInteractor(
+            context,
+            testScope.testScheduler,
+            testScope.testScheduler,
+            recordingController,
+            keyguardInteractor,
+            keyguardDismissUtil,
+            dialogTransitionAnimator,
+            panelInteractor,
+            mock<MediaProjectionMetricsLogger>(),
+            featureFlags,
+            activityStarter,
+        )
+
+    @Test
+    fun handleClick_whenStarting_cancelCountdown() = runTest {
+        val startingModel = ScreenRecordTileModel.Starting(0)
+
+        underTest.handleInput(QSTileInputTestKtx.click(startingModel))
+
+        verify(recordingController).cancelCountdown()
+    }
+
+    @Test
+    fun handleClick_whenRecording_stopRecording() = runTest {
+        val recordingModel = ScreenRecordTileModel.Recording
+
+        underTest.handleInput(QSTileInputTestKtx.click(recordingModel))
+
+        verify(recordingController).stopRecording()
+    }
+
+    @Test
+    fun handleClick_whenDoingNothing_createDialogDismissPanelShowDialog() = runTest {
+        val recordingModel = ScreenRecordTileModel.DoingNothing
+
+        underTest.handleInput(QSTileInputTestKtx.click(recordingModel))
+        val onStartRecordingClickedCaptor = argumentCaptor<Runnable>()
+        verify(recordingController)
+            .createScreenRecordDialog(
+                eq(context),
+                eq(featureFlags),
+                eq(dialogTransitionAnimator),
+                eq(activityStarter),
+                onStartRecordingClickedCaptor.capture()
+            )
+
+        val onDismissActionCaptor = argumentCaptor<OnDismissAction>()
+        verify(keyguardDismissUtil)
+            .executeWhenUnlocked(onDismissActionCaptor.capture(), eq(false), eq(true))
+        onDismissActionCaptor.value.onDismiss()
+        verify(dialog).show() // because the view was null
+
+        // When starting the recording, we collapse the shade and disable the dialog animation.
+        onStartRecordingClickedCaptor.value.run()
+        verify(dialogTransitionAnimator).disableAllCurrentDialogsExitAnimations()
+        verify(panelInteractor).collapsePanels()
+    }
+
+    /**
+     * When the input view is not null and keyguard is not showing, dialog should animate and show
+     */
+    @Test
+    fun handleClickFromView_whenDoingNothing_whenKeyguardNotShowing_showDialogFromView() = runTest {
+        val view = mock<View>()
+        kosmos.fakeKeyguardRepository.setKeyguardShowing(false)
+
+        val recordingModel = ScreenRecordTileModel.DoingNothing
+
+        underTest.handleInput(QSTileInputTestKtx.click(recordingModel, UserHandle.CURRENT, view))
+        val onStartRecordingClickedCaptor = argumentCaptor<Runnable>()
+        verify(recordingController)
+            .createScreenRecordDialog(
+                eq(context),
+                eq(featureFlags),
+                eq(dialogTransitionAnimator),
+                eq(activityStarter),
+                onStartRecordingClickedCaptor.capture()
+            )
+
+        val onDismissActionCaptor = argumentCaptor<OnDismissAction>()
+        verify(keyguardDismissUtil)
+            .executeWhenUnlocked(onDismissActionCaptor.capture(), eq(false), eq(true))
+        onDismissActionCaptor.value.onDismiss()
+        verify(dialogTransitionAnimator).showFromView(eq(dialog), eq(view), any(), eq(true))
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt
new file mode 100644
index 0000000..d7b7ab6
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.ui
+
+import android.graphics.drawable.TestStubDrawable
+import android.text.TextUtils
+import android.widget.Switch
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.ui.ScreenRecordTileMapper
+import com.android.systemui.qs.tiles.impl.screenrecord.qsScreenRecordTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ScreenRecordTileMapperTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val config = kosmos.qsScreenRecordTileConfig
+
+    private lateinit var mapper: ScreenRecordTileMapper
+
+    @Before
+    fun setup() {
+        mapper =
+            ScreenRecordTileMapper(
+                context.orCreateTestableResources
+                    .apply {
+                        addOverride(R.drawable.qs_screen_record_icon_on, TestStubDrawable())
+                        addOverride(R.drawable.qs_screen_record_icon_off, TestStubDrawable())
+                    }
+                    .resources,
+                context.theme
+            )
+    }
+
+    @Test
+    fun activeStateMatchesRecordingDataModel() {
+        val inputModel = ScreenRecordTileModel.Recording
+
+        val outputState = mapper.map(config, inputModel)
+
+        val expectedState =
+            createScreenRecordTileState(
+                QSTileState.ActivationState.ACTIVE,
+                R.drawable.qs_screen_record_icon_on,
+                context.getString(R.string.quick_settings_screen_record_stop),
+            )
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    @Test
+    fun activeStateMatchesStartingDataModel() {
+        val timeLeft = 0L
+        val inputModel = ScreenRecordTileModel.Starting(timeLeft)
+
+        val outputState = mapper.map(config, inputModel)
+
+        val expectedState =
+            createScreenRecordTileState(
+                QSTileState.ActivationState.ACTIVE,
+                R.drawable.qs_screen_record_icon_on,
+                String.format("%d...", timeLeft)
+            )
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    @Test
+    fun inactiveStateMatchesDisabledDataModel() {
+        val inputModel = ScreenRecordTileModel.DoingNothing
+
+        val outputState = mapper.map(config, inputModel)
+
+        val expectedState =
+            createScreenRecordTileState(
+                QSTileState.ActivationState.INACTIVE,
+                R.drawable.qs_screen_record_icon_off,
+                context.getString(R.string.quick_settings_screen_record_start),
+            )
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    private fun createScreenRecordTileState(
+        activationState: QSTileState.ActivationState,
+        iconRes: Int,
+        secondaryLabel: String,
+    ): QSTileState {
+        val label = context.getString(R.string.quick_settings_screen_record_label)
+
+        return QSTileState(
+            { Icon.Loaded(context.getDrawable(iconRes)!!, null) },
+            label,
+            activationState,
+            secondaryLabel,
+            setOf(QSTileState.UserAction.CLICK),
+            if (TextUtils.isEmpty(secondaryLabel)) label
+            else TextUtils.concat(label, ", ", secondaryLabel),
+            null,
+            if (activationState == QSTileState.ActivationState.INACTIVE)
+                QSTileState.SideViewIcon.Chevron
+            else QSTileState.SideViewIcon.None,
+            QSTileState.EnabledState.ENABLED,
+            Switch::class.qualifiedName
+        )
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
index 27c4ec1..f2eb7f4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.qs.QSImpl
 import com.android.systemui.qs.dagger.QSComponent
 import com.android.systemui.qs.dagger.QSSceneComponent
+import com.android.systemui.settings.brightness.MirrorController
 import com.android.systemui.shade.data.repository.fakeShadeRepository
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
@@ -496,4 +497,33 @@
             runCurrent()
             verify(qsImpl!!).setInSplitShade(true)
         }
+
+    @Test
+    fun requestCloseCustomizer() =
+        testScope.runTest {
+            val qsImpl by collectLastValue(underTest.qsImpl)
+
+            underTest.inflate(context)
+            runCurrent()
+
+            underTest.requestCloseCustomizer()
+            verify(qsImpl!!).closeCustomizer()
+        }
+
+    @Test
+    fun setBrightnessMirrorController() =
+        testScope.runTest {
+            val qsImpl by collectLastValue(underTest.qsImpl)
+
+            underTest.inflate(context)
+            runCurrent()
+
+            val mirrorController = mock<MirrorController>()
+            underTest.setBrightnessMirrorController(mirrorController)
+
+            verify(qsImpl!!).setBrightnessMirrorController(mirrorController)
+
+            underTest.setBrightnessMirrorController(null)
+            verify(qsImpl!!).setBrightnessMirrorController(null)
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index ef38567..719828c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -19,36 +19,36 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.Back
+import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.qs.FooterActionsController
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.domain.interactor.privacyChipInteractor
-import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
-import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
+import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
+import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModel
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel
-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.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
-import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 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.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -62,8 +62,6 @@
 
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
-    private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
-    private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
     private val qsFlexiglassAdapter = FakeQSSceneAdapter({ mock() })
     private val footerActionsViewModel = mock<FooterActionsViewModel>()
     private val footerActionsViewModelFactory =
@@ -72,110 +70,149 @@
         }
     private val footerActionsController = mock<FooterActionsController>()
 
-    private var mobileIconsViewModel: MobileIconsViewModel =
-        MobileIconsViewModel(
-            logger = mock(),
-            verboseLogger = mock(),
-            interactor = mobileIconsInteractor,
-            airplaneModeInteractor =
-                AirplaneModeInteractor(
-                    FakeAirplaneModeRepository(),
-                    FakeConnectivityRepository(),
-                    FakeMobileConnectionsRepository(),
-                ),
-            constants = mock(),
-            flags,
-            scope = testScope.backgroundScope,
-        )
-
-    private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel
+    private val sceneInteractor = kosmos.sceneInteractor
 
     private lateinit var underTest: QuickSettingsSceneViewModel
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     @Before
     fun setUp() {
-        shadeHeaderViewModel =
-            ShadeHeaderViewModel(
-                applicationScope = testScope.backgroundScope,
-                context = context,
-                shadeInteractor = kosmos.shadeInteractor,
-                mobileIconsInteractor = mobileIconsInteractor,
-                mobileIconsViewModel = mobileIconsViewModel,
-                privacyChipInteractor = kosmos.privacyChipInteractor,
-                clockInteractor = kosmos.shadeHeaderClockInteractor,
-                broadcastDispatcher = fakeBroadcastDispatcher,
-            )
+        kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false)
 
         underTest =
             QuickSettingsSceneViewModel(
-                shadeHeaderViewModel = shadeHeaderViewModel,
+                applicationScope = testScope.backgroundScope,
+                deviceEntryInteractor = kosmos.deviceEntryInteractor,
+                brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel,
+                shadeHeaderViewModel = kosmos.shadeHeaderViewModel,
                 qsSceneAdapter = qsFlexiglassAdapter,
                 notifications = kosmos.notificationsPlaceholderViewModel,
                 footerActionsViewModelFactory = footerActionsViewModelFactory,
                 footerActionsController = footerActionsController,
+                sceneInteractor = sceneInteractor,
             )
     }
 
     @Test
-    fun destinationsNotCustomizing() =
+    fun destinations_whenNotCustomizing_unlocked() =
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, false)
             val destinations by collectLastValue(underTest.destinationScenes)
             qsFlexiglassAdapter.setCustomizing(false)
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pin
+            )
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
 
             assertThat(destinations)
                 .isEqualTo(
                     mapOf(
                         Back to UserActionResult(Scenes.Shade),
                         Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Shade),
+                        Swipe(
+                            fromSource = Edge.Bottom,
+                            direction = SwipeDirection.Up,
+                        ) to UserActionResult(Scenes.Gone)
                     )
                 )
         }
 
     @Test
-    fun destinationsCustomizing() =
+    fun destinations_whenNotCustomizing_withPreviousSceneLockscreen() =
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, false)
+            qsFlexiglassAdapter.setCustomizing(false)
             val destinations by collectLastValue(underTest.destinationScenes)
-            qsFlexiglassAdapter.setCustomizing(true)
 
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            val previousScene by collectLastValue(sceneInteractor.previousScene())
+            sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+            sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
+            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+            assertThat(previousScene).isEqualTo(Scenes.Lockscreen)
             assertThat(destinations)
                 .isEqualTo(
                     mapOf(
-                        Back to UserActionResult(Scenes.QuickSettings),
+                        Back to UserActionResult(Scenes.Lockscreen),
+                        Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Lockscreen),
+                        Swipe(
+                            fromSource = Edge.Bottom,
+                            direction = SwipeDirection.Up,
+                        ) to UserActionResult(Scenes.Lockscreen)
                     )
                 )
         }
 
     @Test
-    fun destinations_whenNotCustomizing_inSplitShade() =
+    fun destinations_whenNotCustomizing_authMethodSwipe_lockscreenNotDismissed() =
         testScope.runTest {
-            overrideResource(R.bool.config_use_split_notification_shade, true)
+            overrideResource(R.bool.config_use_split_notification_shade, false)
             val destinations by collectLastValue(underTest.destinationScenes)
             qsFlexiglassAdapter.setCustomizing(false)
+            kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.None
+            )
 
             assertThat(destinations)
                 .isEqualTo(
                     mapOf(
                         Back to UserActionResult(Scenes.Shade),
                         Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Shade),
+                        Swipe(
+                            fromSource = Edge.Bottom,
+                            direction = SwipeDirection.Up,
+                        ) to UserActionResult(Scenes.Lockscreen)
                     )
                 )
         }
 
     @Test
-    fun destinations_whenCustomizing_inSplitShade() =
+    fun destinations_whenCustomizing_noDestinations() =
+        testScope.runTest {
+            overrideResource(R.bool.config_use_split_notification_shade, false)
+            val destinations by collectLastValue(underTest.destinationScenes)
+            qsFlexiglassAdapter.setCustomizing(true)
+
+            assertThat(destinations).isEmpty()
+        }
+
+    @Test
+    fun destinations_whenNotCustomizing_inSplitShade_unlocked() =
+        testScope.runTest {
+            overrideResource(R.bool.config_use_split_notification_shade, true)
+            val destinations by collectLastValue(underTest.destinationScenes)
+            qsFlexiglassAdapter.setCustomizing(false)
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pin
+            )
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
+
+            assertThat(destinations)
+                .isEqualTo(
+                    mapOf(
+                        Back to UserActionResult(Scenes.Shade),
+                        Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Shade),
+                        Swipe(
+                            fromSource = Edge.Bottom,
+                            direction = SwipeDirection.Up,
+                        ) to UserActionResult(Scenes.Gone),
+                    )
+                )
+        }
+
+    @Test
+    fun destinations_whenCustomizing_inSplitShade_noDestinations() =
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, true)
             val destinations by collectLastValue(underTest.destinationScenes)
             qsFlexiglassAdapter.setCustomizing(true)
 
-            assertThat(destinations)
-                .isEqualTo(
-                    mapOf(
-                        Back to UserActionResult(Scenes.QuickSettings),
-                    )
-                )
+            assertThat(destinations).isEmpty()
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 98cbda2..6643bcb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -36,62 +36,43 @@
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor
 import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor
-import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
-import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
 import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.bouncerViewModel
 import com.android.systemui.classifier.domain.interactor.falsingInteractor
-import com.android.systemui.classifier.falsingCollector
-import com.android.systemui.classifier.falsingManager
 import com.android.systemui.communal.domain.interactor.communalInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel
 import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
-import com.android.systemui.model.SysUiState
-import com.android.systemui.model.sceneContainerPlugin
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.qs.footerActionsController
 import com.android.systemui.qs.footerActionsViewModelFactory
 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
-import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
+import com.android.systemui.scene.domain.interactor.sceneContainerStartable
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.domain.startable.SceneContainerStartable
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
-import com.android.systemui.settings.FakeDisplayTracker
-import com.android.systemui.shade.domain.interactor.privacyChipInteractor
-import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
+import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
 import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
 import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel
-import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
+import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModel
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel
-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.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
-import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
-import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
 import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
 import com.android.systemui.testKosmos
+import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -135,9 +116,10 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 @RunWithLooper
+@EnableSceneContainer
 class SceneFrameworkIntegrationTest : SysuiTestCase() {
 
-    private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true }
+    private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
@@ -155,12 +137,11 @@
                 sceneInteractor = sceneInteractor,
                 falsingInteractor = kosmos.falsingInteractor,
                 powerInteractor = kosmos.powerInteractor,
+                scenes = kosmos.scenes,
             )
             .apply { setTransitionState(transitionState) }
     }
 
-    private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
-
     private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
     private lateinit var bouncerActionButtonInteractor: BouncerActionButtonInteractor
     private lateinit var bouncerViewModel: BouncerViewModel
@@ -179,28 +160,8 @@
         )
     }
 
-    private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
-
-    private var mobileIconsViewModel: MobileIconsViewModel =
-        MobileIconsViewModel(
-            logger = mock(),
-            verboseLogger = mock(),
-            interactor = mobileIconsInteractor,
-            airplaneModeInteractor =
-                AirplaneModeInteractor(
-                    FakeAirplaneModeRepository(),
-                    FakeConnectivityRepository(),
-                    FakeMobileConnectionsRepository(),
-                ),
-            constants = mock(),
-            flags = kosmos.fakeFeatureFlagsClassic,
-            scope = testScope.backgroundScope,
-        )
-
-    private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel
     private lateinit var shadeSceneViewModel: ShadeSceneViewModel
 
-    private val keyguardInteractor by lazy { kosmos.keyguardInteractor }
     private val powerInteractor by lazy { kosmos.powerInteractor }
 
     private var bouncerSceneJob: Job? = null
@@ -240,58 +201,23 @@
         bouncerActionButtonInteractor = kosmos.bouncerActionButtonInteractor
         bouncerViewModel = kosmos.bouncerViewModel
 
-        shadeHeaderViewModel =
-            ShadeHeaderViewModel(
-                applicationScope = testScope.backgroundScope,
-                context = context,
-                shadeInteractor = kosmos.shadeInteractor,
-                mobileIconsInteractor = mobileIconsInteractor,
-                mobileIconsViewModel = mobileIconsViewModel,
-                privacyChipInteractor = kosmos.privacyChipInteractor,
-                clockInteractor = kosmos.shadeHeaderClockInteractor,
-                broadcastDispatcher = fakeBroadcastDispatcher,
-            )
-
         shadeSceneViewModel =
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
                 deviceEntryInteractor = deviceEntryInteractor,
-                shadeHeaderViewModel = shadeHeaderViewModel,
+                shadeHeaderViewModel = kosmos.shadeHeaderViewModel,
                 qsSceneAdapter = qsFlexiglassAdapter,
                 notifications = kosmos.notificationsPlaceholderViewModel,
+                brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel,
                 mediaDataManager = mediaDataManager,
                 shadeInteractor = kosmos.shadeInteractor,
                 footerActionsController = kosmos.footerActionsController,
                 footerActionsViewModelFactory = kosmos.footerActionsViewModelFactory,
                 sceneInteractor = sceneInteractor,
+                unfoldTransitionInteractor = kosmos.unfoldTransitionInteractor,
             )
 
-        val displayTracker = FakeDisplayTracker(context)
-        val sysUiState = SysUiState(displayTracker, kosmos.sceneContainerPlugin)
-        val startable =
-            SceneContainerStartable(
-                applicationScope = testScope.backgroundScope,
-                sceneInteractor = sceneInteractor,
-                deviceEntryInteractor = deviceEntryInteractor,
-                keyguardInteractor = keyguardInteractor,
-                flags = kosmos.fakeSceneContainerFlags,
-                sysUiState = sysUiState,
-                displayId = displayTracker.defaultDisplayId,
-                sceneLogger = mock(),
-                falsingCollector = kosmos.falsingCollector,
-                falsingManager = kosmos.falsingManager,
-                powerInteractor = powerInteractor,
-                bouncerInteractor = bouncerInteractor,
-                simBouncerInteractor = dagger.Lazy { kosmos.simBouncerInteractor },
-                authenticationInteractor = dagger.Lazy { kosmos.authenticationInteractor },
-                windowController = mock(),
-                deviceProvisioningInteractor = kosmos.deviceProvisioningInteractor,
-                centralSurfaces = mock(),
-                headsUpInteractor = kosmos.headsUpNotificationInteractor,
-                occlusionInteractor = kosmos.sceneContainerOcclusionInteractor,
-                faceUnlockInteractor = kosmos.deviceEntryFaceAuthInteractor,
-                deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor,
-            )
+        val startable = kosmos.sceneContainerStartable
         startable.start()
 
         assertWithMessage("Initial scene key mismatch!")
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index 3d66192..8e2eea1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -23,10 +23,10 @@
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.sceneContainerConfig
 import com.android.systemui.scene.sceneKeys
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -39,10 +39,10 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
[email protected]
+@EnableSceneContainer
 class SceneContainerRepositoryTest : SysuiTestCase() {
 
-    private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true }
+    private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
 
     @Test
@@ -140,4 +140,23 @@
                     ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
                 )
         }
+
+    @Test
+    fun previousScene() =
+        testScope.runTest {
+            val underTest = kosmos.sceneContainerRepository
+            val currentScene by collectLastValue(underTest.currentScene)
+            val previousScene by collectLastValue(underTest.previousScene)
+
+            assertThat(previousScene).isNull()
+
+            val firstScene = currentScene
+            underTest.changeScene(Scenes.Shade)
+            assertThat(previousScene).isEqualTo(firstScene)
+            assertThat(currentScene).isEqualTo(Scenes.Shade)
+
+            underTest.changeScene(Scenes.QuickSettings)
+            assertThat(previousScene).isEqualTo(Scenes.Shade)
+            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 143c0f2..871ce6d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -23,13 +23,13 @@
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.data.repository.sceneContainerRepository
 import com.android.systemui.scene.sceneContainerConfig
 import com.android.systemui.scene.sceneKeys
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.testKosmos
@@ -45,6 +45,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class SceneInteractorTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
@@ -55,7 +56,6 @@
 
     @Before
     fun setUp() {
-        kosmos.fakeSceneContainerFlags.enabled = true
         underTest = kosmos.sceneInteractor
     }
 
@@ -291,4 +291,34 @@
 
             assertThat(isVisible).isFalse()
         }
+
+    @Test
+    fun previousScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(underTest.currentScene)
+            val previousScene by collectLastValue(underTest.previousScene())
+            assertThat(previousScene).isNull()
+
+            val firstScene = currentScene
+            underTest.changeScene(toScene = Scenes.Shade, "reason")
+            assertThat(previousScene).isEqualTo(firstScene)
+
+            underTest.changeScene(toScene = Scenes.QuickSettings, "reason")
+            assertThat(previousScene).isEqualTo(Scenes.Shade)
+        }
+
+    @Test
+    fun previousScene_withIgnoredScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(underTest.currentScene)
+            val previousScene by collectLastValue(underTest.previousScene(ignored = Scenes.Shade))
+            assertThat(previousScene).isNull()
+
+            val firstScene = currentScene
+            underTest.changeScene(toScene = Scenes.Shade, "reason")
+            assertThat(previousScene).isEqualTo(firstScene)
+
+            underTest.changeScene(toScene = Scenes.QuickSettings, "reason")
+            assertThat(previousScene).isNull()
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt
index d5e43f4..bfe5ef7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt
@@ -31,7 +31,6 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
 import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
 import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
@@ -82,7 +81,6 @@
                 headsUpManager,
                 powerInteractor,
                 activeNotificationsInteractor,
-                kosmos.sceneContainerFlags,
                 kosmos::sceneInteractor,
             )
             .apply { setUp(notificationPresenter, notificationsController) }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 3fd5306..2586ad541 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -20,53 +20,50 @@
 
 import android.app.StatusBarManager
 import android.os.PowerManager
-import android.platform.test.annotations.EnableFlags
 import android.view.Display
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
-import com.android.systemui.Flags as AconfigFlags
+import com.android.internal.logging.uiEventLoggerFake
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
-import com.android.systemui.authentication.domain.interactor.authenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
-import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
+import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
 import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.classifier.falsingCollector
 import com.android.systemui.classifier.falsingManager
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.data.repository.fakeTrustRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.model.sysUiState
+import com.android.systemui.power.data.repository.fakePowerRepository
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.scene.domain.interactor.sceneContainerStartable
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shared.system.QuickStepContract
-import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
 import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository
 import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRepository
 import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
-import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.notificationShadeWindowController
+import com.android.systemui.statusbar.phone.centralSurfaces
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
 import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
-import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -81,35 +78,30 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.never
-import org.mockito.Mockito.spy
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-@EnableFlags(AconfigFlags.FLAG_SCENE_CONTAINER)
+@EnableSceneContainer
 class SceneContainerStartableTest : SysuiTestCase() {
 
-    @Mock private lateinit var windowController: NotificationShadeWindowController
-    @Mock private lateinit var centralSurfaces: CentralSurfaces
-
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
-    private val sceneContainerFlags by lazy { kosmos.fakeSceneContainerFlags }
-    private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
     private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
     private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository }
-    private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor }
-    private val keyguardInteractor by lazy { kosmos.keyguardInteractor }
-    private val sysUiState = spy(kosmos.sysUiState)
-    private val falsingCollector: FalsingCollector = mock()
-    private val powerInteractor = PowerInteractorFactory.create().powerInteractor
+    private val sysUiState = kosmos.sysUiState
+    private val falsingCollector = mock<FalsingCollector>().also { kosmos.falsingCollector = it }
     private val fakeSceneDataSource = kosmos.fakeSceneDataSource
+    private val windowController = kosmos.notificationShadeWindowController
+    private val centralSurfaces = kosmos.centralSurfaces
+    private val powerInteractor = kosmos.powerInteractor
+    private val fakeTrustRepository = kosmos.fakeTrustRepository
+    private val uiEventLoggerFake = kosmos.uiEventLoggerFake
 
     private lateinit var underTest: SceneContainerStartable
 
@@ -117,30 +109,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        underTest =
-            SceneContainerStartable(
-                applicationScope = testScope.backgroundScope,
-                sceneInteractor = sceneInteractor,
-                deviceEntryInteractor = deviceEntryInteractor,
-                keyguardInteractor = keyguardInteractor,
-                flags = sceneContainerFlags,
-                sysUiState = sysUiState,
-                displayId = Display.DEFAULT_DISPLAY,
-                sceneLogger = mock(),
-                falsingCollector = falsingCollector,
-                falsingManager = kosmos.falsingManager,
-                powerInteractor = powerInteractor,
-                bouncerInteractor = bouncerInteractor,
-                simBouncerInteractor = { kosmos.simBouncerInteractor },
-                authenticationInteractor = { authenticationInteractor },
-                windowController = windowController,
-                deviceProvisioningInteractor = kosmos.deviceProvisioningInteractor,
-                centralSurfaces = centralSurfaces,
-                headsUpInteractor = kosmos.headsUpNotificationInteractor,
-                occlusionInteractor = kosmos.sceneContainerOcclusionInteractor,
-                faceUnlockInteractor = kosmos.deviceEntryFaceAuthInteractor,
-                deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor,
-            )
+        underTest = kosmos.sceneContainerStartable
     }
 
     @Test
@@ -287,6 +256,38 @@
         }
 
     @Test
+    fun switchFromBouncerToQuickSettingsWhenDeviceUnlocked() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+
+            val transitionState =
+                prepareState(
+                    authenticationMethod = AuthenticationMethodModel.Pin,
+                    isDeviceUnlocked = false,
+                    initialSceneKey = Scenes.Lockscreen,
+                )
+            assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+            underTest.start()
+            runCurrent()
+
+            sceneInteractor.changeScene(Scenes.QuickSettings, "switching to qs for test")
+            transitionState.value = ObservableTransitionState.Idle(Scenes.QuickSettings)
+            runCurrent()
+            assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
+
+            sceneInteractor.changeScene(Scenes.Bouncer, "switching to bouncer for test")
+            transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
+            runCurrent()
+            assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
+
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
+
+            assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
+        }
+
+    @Test
     fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -847,7 +848,7 @@
         }
 
     @Test
-    fun hydrateWindowFocus() =
+    fun hydrateWindowController_setNotificationShadeFocusable() =
         testScope.runTest {
             val currentDesiredSceneKey by collectLastValue(sceneInteractor.currentScene)
             val transitionStateFlow =
@@ -901,6 +902,89 @@
         }
 
     @Test
+    fun hydrateWindowController_setKeyguardShowing() =
+        testScope.runTest {
+            underTest.start()
+            val notificationShadeWindowController = kosmos.notificationShadeWindowController
+            val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            verify(notificationShadeWindowController).setKeyguardShowing(true)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
+            verify(notificationShadeWindowController, times(1)).setKeyguardShowing(true)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
+            verify(notificationShadeWindowController, times(1)).setKeyguardShowing(true)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Shade)
+            verify(notificationShadeWindowController, times(1)).setKeyguardShowing(true)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
+            verify(notificationShadeWindowController, times(1)).setKeyguardShowing(true)
+        }
+
+    @Test
+    fun hydrateWindowController_setBouncerShowing() =
+        testScope.runTest {
+            underTest.start()
+            val notificationShadeWindowController = kosmos.notificationShadeWindowController
+            val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            verify(notificationShadeWindowController, never()).setBouncerShowing(true)
+            verify(notificationShadeWindowController, times(1)).setBouncerShowing(false)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
+            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
+            verify(notificationShadeWindowController, times(1)).setBouncerShowing(false)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
+            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
+            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
+
+            kosmos.deviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
+            assertThat(currentScene).isEqualTo(Scenes.Gone)
+            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
+            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
+            verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
+            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
+
+            emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
+            verify(notificationShadeWindowController, times(2)).setBouncerShowing(true)
+            verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
+        }
+
+    @Test
+    fun hydrateWindowController_setKeyguardOccluded() =
+        testScope.runTest {
+            underTest.start()
+            val notificationShadeWindowController = kosmos.notificationShadeWindowController
+            prepareState(initialSceneKey = Scenes.Lockscreen)
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            verify(notificationShadeWindowController, never()).setKeyguardOccluded(true)
+            verify(notificationShadeWindowController, times(1)).setKeyguardOccluded(false)
+
+            kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
+                true,
+                mock()
+            )
+            runCurrent()
+            verify(notificationShadeWindowController, times(1)).setKeyguardOccluded(true)
+            verify(notificationShadeWindowController, times(1)).setKeyguardOccluded(false)
+
+            kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(false)
+            runCurrent()
+            verify(notificationShadeWindowController, times(1)).setKeyguardOccluded(true)
+            verify(notificationShadeWindowController, times(2)).setKeyguardOccluded(false)
+        }
+
+    @Test
     fun hydrateInteractionState_whileLocked() =
         testScope.runTest {
             val transitionStateFlow =
@@ -1127,6 +1211,52 @@
             assertThat(kosmos.fakeDeviceEntryFaceAuthRepository.isAuthRunning.value).isTrue()
         }
 
+    @Test
+    fun switchToLockscreen_whenShadeBecomesNotTouchable() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            val isShadeTouchable by collectLastValue(kosmos.shadeInteractor.isShadeTouchable)
+            val transitionStateFlow = prepareState()
+            underTest.start()
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            // Flung to bouncer, 90% of the way there:
+            transitionStateFlow.value =
+                ObservableTransitionState.Transition(
+                    fromScene = Scenes.Lockscreen,
+                    toScene = Scenes.Bouncer,
+                    progress = flowOf(0.9f),
+                    isInitiatedByUserInput = true,
+                    isUserInputOngoing = flowOf(false),
+                )
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+            kosmos.fakePowerRepository.updateWakefulness(WakefulnessState.ASLEEP)
+            runCurrent()
+            assertThat(isShadeTouchable).isFalse()
+
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+        }
+
+    @Test
+    fun switchToGone_extendUnlock() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            prepareState(
+                initialSceneKey = Scenes.Bouncer,
+                authenticationMethod = AuthenticationMethodModel.Pin,
+            )
+            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+
+            underTest.start()
+            fakeTrustRepository.setCurrentUserTrusted(true)
+
+            assertThat(currentScene).isEqualTo(Scenes.Gone)
+            assertThat(uiEventLoggerFake[0].eventId)
+                .isEqualTo(BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS.id)
+            assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
+        }
+
     private fun TestScope.emulateSceneTransition(
         transitionStateFlow: MutableStateFlow<ObservableTransitionState>,
         toScene: SceneKey,
@@ -1166,6 +1296,7 @@
         isLockscreenEnabled: Boolean = true,
         startsAwake: Boolean = true,
         isDeviceProvisioned: Boolean = true,
+        isInteractive: Boolean = true,
     ): MutableStateFlow<ObservableTransitionState> {
         if (authenticationMethod?.isSecure == true) {
             assert(isLockscreenEnabled) {
@@ -1182,7 +1313,6 @@
             "Cannot start on the Gone scene and have the device be locked at the same time."
         }
 
-        sceneContainerFlags.enabled = true
         kosmos.fakeDeviceEntryRepository.setBypassEnabled(isBypassEnabled)
         authenticationMethod?.let {
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(authenticationMethod)
@@ -1205,6 +1335,7 @@
         } else {
             powerInteractor.setAsleepForTest()
         }
+        kosmos.fakePowerRepository.setInteractive(isInteractive)
 
         kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(isDeviceProvisioned)
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt
new file mode 100644
index 0000000..4d69f0d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.shared.flag
+
+import android.platform.test.flag.junit.FlagsParameterization
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN
+import com.android.systemui.Flags.FLAG_EXAMPLE_FLAG
+import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.flags.parameterizeSceneContainerFlag
+import com.google.common.truth.Truth
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class SceneContainerFlagParameterizationTest : SysuiTestCase() {
+
+    @Test
+    fun emptyAndSceneContainer() {
+        val result = FlagsParameterization.allCombinationsOf().andSceneContainer()
+        Truth.assertThat(result).hasSize(2)
+        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
+    }
+
+    @Test
+    fun parameterizeSceneContainer() {
+        val result = parameterizeSceneContainerFlag()
+        Truth.assertThat(result).hasSize(2)
+        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
+    }
+
+    @Test
+    fun oneUnrelatedAndSceneContainer() {
+        val unrelatedFlag = FLAG_EXAMPLE_FLAG
+        val result = FlagsParameterization.allCombinationsOf(unrelatedFlag).andSceneContainer()
+        Truth.assertThat(result).hasSize(4)
+        Truth.assertThat(result[0].mOverrides[unrelatedFlag]).isFalse()
+        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+        Truth.assertThat(result[1].mOverrides[unrelatedFlag]).isFalse()
+        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
+        Truth.assertThat(result[2].mOverrides[unrelatedFlag]).isTrue()
+        Truth.assertThat(result[2].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+        Truth.assertThat(result[3].mOverrides[unrelatedFlag]).isTrue()
+        Truth.assertThat(result[3].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
+    }
+
+    @Test
+    fun oneDependencyAndSceneContainer() {
+        val dependentFlag = FLAG_COMPOSE_LOCKSCREEN
+        val result = FlagsParameterization.allCombinationsOf(dependentFlag).andSceneContainer()
+        Truth.assertThat(result).hasSize(3)
+        Truth.assertThat(result[0].mOverrides[dependentFlag]).isFalse()
+        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+        Truth.assertThat(result[1].mOverrides[dependentFlag]).isTrue()
+        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+        Truth.assertThat(result[2].mOverrides[dependentFlag]).isTrue()
+        Truth.assertThat(result[2].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
new file mode 100644
index 0000000..ae5bf07
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.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.scene.shared.flag
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.EnableSceneContainer
+import com.google.common.truth.Truth
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class SceneContainerFlagsTest : SysuiTestCase() {
+
+    @Test
+    @DisableSceneContainer
+    fun isNotEnabled_withoutAconfigFlags() {
+        Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(false)
+    }
+
+    @Test
+    @EnableSceneContainer
+    fun isEnabled_withAconfigFlags() {
+        Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(true)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index 7b0127e..5c30379 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -23,13 +23,15 @@
 import com.android.systemui.classifier.domain.interactor.falsingInteractor
 import com.android.systemui.classifier.fakeFalsingManager
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.data.repository.fakePowerRepository
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.fakeScenes
 import com.android.systemui.scene.sceneContainerConfig
 import com.android.systemui.scene.sceneKeys
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
+import com.android.systemui.scene.scenes
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.testKosmos
@@ -45,25 +47,26 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class SceneContainerViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
     private val testScope by lazy { kosmos.testScope }
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
-    private val fakeSceneDataSource = kosmos.fakeSceneDataSource
-    private val sceneContainerConfig = kosmos.sceneContainerConfig
-    private val falsingManager = kosmos.fakeFalsingManager
+    private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
+    private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
+    private val falsingManager by lazy { kosmos.fakeFalsingManager }
 
     private lateinit var underTest: SceneContainerViewModel
 
     @Before
     fun setUp() {
-        kosmos.fakeSceneContainerFlags.enabled = true
         underTest =
             SceneContainerViewModel(
                 sceneInteractor = sceneInteractor,
                 falsingInteractor = kosmos.falsingInteractor,
                 powerInteractor = kosmos.powerInteractor,
+                scenes = kosmos.scenes,
             )
     }
 
@@ -214,4 +217,23 @@
 
             assertThat(isVisible).isFalse()
         }
+
+    @Test
+    fun currentDestinationScenes_onlyTheCurrentSceneIsCollected() =
+        testScope.runTest {
+            val unused by collectLastValue(underTest.currentDestinationScenes(backgroundScope))
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            kosmos.fakeScenes.forEach { scene ->
+                fakeSceneDataSource.changeScene(toScene = scene.key)
+                runCurrent()
+                assertThat(currentScene).isEqualTo(scene.key)
+
+                assertThat(scene.isDestinationScenesBeingCollected).isTrue()
+                kosmos.fakeScenes
+                    .filter { it.key != scene.key }
+                    .forEach { otherScene ->
+                        assertThat(otherScene.isDestinationScenesBeingCollected).isFalse()
+                    }
+            }
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepositoryTest.kt
new file mode 100644
index 0000000..a1af70b
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepositoryTest.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.data.repository
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BrightnessMirrorShowingRepositoryTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+
+    private val underTest = BrightnessMirrorShowingRepository()
+
+    @Test
+    fun isShowing_setAndFlow() =
+        kosmos.testScope.runTest {
+            val isShowing by collectLastValue(underTest.isShowing)
+
+            assertThat(isShowing).isFalse()
+
+            underTest.setMirrorShowing(true)
+            assertThat(isShowing).isTrue()
+
+            underTest.setMirrorShowing(false)
+            assertThat(isShowing).isFalse()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractorTest.kt
new file mode 100644
index 0000000..31d6df2
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractorTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.settings.brightness.data.repository.brightnessMirrorShowingRepository
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BrightnessMirrorShowingInteractorTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+
+    private val underTest =
+        BrightnessMirrorShowingInteractor(kosmos.brightnessMirrorShowingRepository)
+
+    @Test
+    fun isShowing_setAndFlow() =
+        kosmos.testScope.runTest {
+            val isShowing by collectLastValue(underTest.isShowing)
+
+            assertThat(isShowing).isFalse()
+
+            underTest.setMirrorShowing(true)
+            assertThat(isShowing).isTrue()
+
+            underTest.setMirrorShowing(false)
+            assertThat(isShowing).isFalse()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflaterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflaterTest.kt
new file mode 100644
index 0000000..6de7f40
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflaterTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.ui.binder
+
+import android.content.applicationContext
+import android.view.ContextThemeWrapper
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
+import com.android.systemui.settings.brightnessSliderControllerFactory
+import com.android.systemui.testKosmos
+import com.android.systemui.util.Assert
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BrightnessMirrorInflaterTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
+    private val themedContext =
+        ContextThemeWrapper(kosmos.applicationContext, R.style.Theme_SystemUI_QuickSettings)
+
+    @Test
+    fun inflate_sliderViewAddedToFrame() {
+        Assert.setTestThread(Thread.currentThread())
+
+        val (frame, sliderController) =
+            BrightnessMirrorInflater.inflate(
+                themedContext,
+                kosmos.brightnessSliderControllerFactory
+            )
+
+        assertThat(sliderController.rootView.parent).isSameInstanceAs(frame)
+
+        Assert.setTestThread(null)
+    }
+
+    @Test
+    fun inflate_frameAndSliderViewVisible() {
+        Assert.setTestThread(Thread.currentThread())
+
+        val (frame, sliderController) =
+            BrightnessMirrorInflater.inflate(
+                themedContext,
+                kosmos.brightnessSliderControllerFactory,
+            )
+
+        assertThat(frame.visibility).isEqualTo(View.VISIBLE)
+        assertThat(sliderController.rootView.visibility).isEqualTo(View.VISIBLE)
+
+        Assert.setTestThread(null)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/ui/viewmodel/BrightnessMirrorViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/ui/viewmodel/BrightnessMirrorViewModelTest.kt
new file mode 100644
index 0000000..09fc6f9
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/ui/viewmodel/BrightnessMirrorViewModelTest.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.ui.viewmodel
+
+import android.content.applicationContext
+import android.content.res.mainResources
+import android.view.ContextThemeWrapper
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
+import com.android.systemui.settings.brightness.ui.binder.BrightnessMirrorInflater
+import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
+import com.android.systemui.settings.brightness.ui.viewModel.LocationAndSize
+import com.android.systemui.settings.brightnessSliderControllerFactory
+import com.android.systemui.testKosmos
+import com.android.systemui.util.Assert
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BrightnessMirrorViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+
+    private val themedContext =
+        ContextThemeWrapper(kosmos.applicationContext, R.style.Theme_SystemUI_QuickSettings)
+
+    private val underTest =
+        with(kosmos) {
+            BrightnessMirrorViewModel(
+                brightnessMirrorShowingInteractor,
+                mainResources,
+                brightnessSliderControllerFactory,
+            )
+        }
+
+    @Test
+    fun showHideMirror_isShowing() =
+        with(kosmos) {
+            testScope.runTest {
+                val showing by collectLastValue(underTest.isShowing)
+
+                assertThat(showing).isFalse()
+
+                underTest.showMirror()
+                assertThat(showing).isTrue()
+
+                underTest.hideMirror()
+                assertThat(showing).isFalse()
+            }
+        }
+
+    @Test
+    fun setLocationInWindow_correctLocationAndSize() =
+        with(kosmos) {
+            testScope.runTest {
+                val locationAndSize by collectLastValue(underTest.locationAndSize)
+
+                val x = 20
+                val y = 100
+                val height = 50
+                val width = 200
+                val padding =
+                    mainResources.getDimensionPixelSize(R.dimen.rounded_slider_background_padding)
+
+                val mockView =
+                    mock<View> {
+                        whenever(getLocationInWindow(any())).then {
+                            it.getArgument<IntArray>(0).apply {
+                                this[0] = x
+                                this[1] = y
+                            }
+                            Unit
+                        }
+
+                        whenever(measuredHeight).thenReturn(height)
+                        whenever(measuredWidth).thenReturn(width)
+                    }
+
+                underTest.setLocationAndSize(mockView)
+
+                assertThat(locationAndSize)
+                    .isEqualTo(
+                        // Adjust for padding around the view
+                        LocationAndSize(
+                            yOffset = y - padding,
+                            width = width + 2 * padding,
+                            height = height + 2 * padding,
+                        )
+                    )
+            }
+        }
+
+    @Test
+    fun setLocationInWindow_paddingSetToRootView() =
+        with(kosmos) {
+            Assert.setTestThread(Thread.currentThread())
+            val padding =
+                mainResources.getDimensionPixelSize(R.dimen.rounded_slider_background_padding)
+
+            val view = mock<View>()
+
+            val (_, sliderController) =
+                BrightnessMirrorInflater.inflate(
+                    themedContext,
+                    brightnessSliderControllerFactory,
+                )
+            underTest.setToggleSlider(sliderController)
+
+            underTest.setLocationAndSize(view)
+
+            with(sliderController.rootView) {
+                assertThat(paddingBottom).isEqualTo(padding)
+                assertThat(paddingTop).isEqualTo(padding)
+                assertThat(paddingLeft).isEqualTo(padding)
+                assertThat(paddingRight).isEqualTo(padding)
+            }
+
+            Assert.setTestThread(null)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
new file mode 100644
index 0000000..a8da116
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade;
+
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+
+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.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.app.IActivityManager;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.platform.test.flag.junit.FlagsParameterization;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
+import com.android.systemui.scene.FakeWindowRootViewComponent;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
+
+import com.google.common.util.concurrent.MoreExecutors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+@RunWith(ParameterizedAndroidJunit4.class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
+    @Mock private WindowManager mWindowManager;
+    @Mock private DozeParameters mDozeParameters;
+    @Spy private final NotificationShadeWindowView mNotificationShadeWindowView = spy(
+            new NotificationShadeWindowView(mContext, null));
+    @Mock private IActivityManager mActivityManager;
+    @Mock private ConfigurationController mConfigurationController;
+    @Mock private KeyguardViewMediator mKeyguardViewMediator;
+    @Mock private KeyguardBypassController mKeyguardBypassController;
+    @Mock private SysuiColorExtractor mColorExtractor;
+    @Mock private ColorExtractor.GradientColors mGradientColors;
+    @Mock private DumpManager mDumpManager;
+    @Mock private KeyguardStateController mKeyguardStateController;
+    @Mock private AuthController mAuthController;
+    @Mock private ShadeWindowLogger mShadeWindowLogger;
+    @Mock private SelectedUserInteractor mSelectedUserInteractor;
+    @Mock private UserTracker mUserTracker;
+    @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
+    @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
+
+    private final Executor mMainExecutor = MoreExecutors.directExecutor();
+    private final Executor mBackgroundExecutor = MoreExecutors.directExecutor();
+    private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
+
+    private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
+    private float mPreferredRefreshRate = -1;
+    private SysuiStatusBarStateController mStatusBarStateController;
+
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getParams() {
+        return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
+    }
+
+    public NotificationShadeWindowControllerImplTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        // Preferred refresh rate is equal to the first displayMode's refresh rate
+        mPreferredRefreshRate = mContext.getDisplay().getSupportedModes()[0].getRefreshRate();
+        overrideResource(
+                R.integer.config_keyguardRefreshRate,
+                (int) mPreferredRefreshRate
+        );
+
+        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
+        when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+
+        mStatusBarStateController = spy(mKosmos.getStatusBarStateController());
+
+        mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
+                mContext,
+                new FakeWindowRootViewComponent.Factory(mNotificationShadeWindowView),
+                mWindowManager,
+                mActivityManager,
+                mDozeParameters,
+                mStatusBarStateController,
+                mConfigurationController,
+                mKeyguardViewMediator,
+                mKeyguardBypassController,
+                mMainExecutor,
+                mBackgroundExecutor,
+                mColorExtractor,
+                mDumpManager,
+                mKeyguardStateController,
+                mKosmos.getScreenOffAnimationController(),
+                mAuthController,
+                mKosmos::getShadeInteractor,
+                mShadeWindowLogger,
+                () -> mSelectedUserInteractor,
+                mUserTracker,
+                mKosmos::getCommunalInteractor) {
+                    @Override
+                    protected boolean isDebuggable() {
+                        return false;
+                    }
+            };
+        mNotificationShadeWindowController.setScrimsVisibilityListener((visibility) -> {});
+        mNotificationShadeWindowController.fetchWindowRootView();
+
+        mNotificationShadeWindowController.attach();
+        verify(mWindowManager).addView(eq(mNotificationShadeWindowView), any());
+        verify(mStatusBarStateController).addCallback(mStateListener.capture(), anyInt());
+    }
+
+    @Test
+    public void testSetDozing_hidesSystemOverlays() {
+        mNotificationShadeWindowController.setDozing(true);
+        ArgumentCaptor<WindowManager.LayoutParams> captor =
+                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(any(), captor.capture());
+        int flag = captor.getValue().privateFlags
+                & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        assertThat(flag).isNotEqualTo(0);
+
+        reset(mWindowManager);
+        mNotificationShadeWindowController.setDozing(false);
+        verify(mWindowManager).updateViewLayout(any(), captor.capture());
+        flag = captor.getValue().privateFlags
+                & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        assertThat(flag).isEqualTo(0);
+    }
+
+    @Test
+    public void testOnThemeChanged_doesntCrash() {
+        mNotificationShadeWindowController.onThemeChanged();
+    }
+
+    @Test
+    public void testAdd_updatesVisibilityFlags() {
+        verify(mNotificationShadeWindowView).setSystemUiVisibility(anyInt());
+    }
+
+    @Test
+    public void testSetForcePluginOpen_beforeStatusBarInitialization() {
+        mNotificationShadeWindowController.setForcePluginOpen(true, this);
+    }
+
+    @Test
+    public void attach_visibleWithWallpaper() {
+        clearInvocations(mWindowManager);
+        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
+        mNotificationShadeWindowController.attach();
+
+        verify(mNotificationShadeWindowView).setVisibility(eq(View.VISIBLE));
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue();
+    }
+
+    @Test
+    public void attach_lightScrimHidesWallpaper() {
+        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
+        mNotificationShadeWindowController.attach();
+
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setLightRevealScrimOpaque(true);
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) == 0).isTrue();
+    }
+
+    @Test
+    public void attach_scrimDoesntHideWallpaper() {
+        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
+        mNotificationShadeWindowController.attach();
+
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setScrimsVisibility(ScrimController.OPAQUE);
+        // The scrim used to remove the wallpaper flag, but this causes a relayout.
+        // Instead, we're not relying on SurfaceControl#setOpaque on
+        // NotificationShadeDepthController.
+        verify(mWindowManager, never()).updateViewLayout(any(), mLayoutParameters.capture());
+    }
+
+    @Test
+    public void setScrimsVisibility_earlyReturn() {
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setScrimsVisibility(ScrimController.TRANSPARENT);
+        // Abort early if value didn't change
+        verify(mWindowManager, never()).updateViewLayout(any(), mLayoutParameters.capture());
+    }
+
+    @Test
+    public void attach_animatingKeyguardAndSurface_wallpaperVisible() {
+        clearInvocations(mWindowManager);
+        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
+        when(mKeyguardViewMediator
+                .isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe())
+                .thenReturn(true);
+        mNotificationShadeWindowController.attach();
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue();
+    }
+
+    @Test
+    public void setBackgroundBlurRadius_expandedWithBlurs() {
+        mNotificationShadeWindowController.setBackgroundBlurRadius(10);
+        verify(mNotificationShadeWindowView).setVisibility(eq(View.VISIBLE));
+
+        mNotificationShadeWindowController.setBackgroundBlurRadius(0);
+        verify(mNotificationShadeWindowView).setVisibility(eq(View.INVISIBLE));
+    }
+
+    @Test
+    public void setBouncerShowing_isFocusable_whenNeedsInput() {
+        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setBouncerShowing(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
+    }
+
+    @Test
+    public void setKeyguardShowing_focusable_notAltFocusable_whenNeedsInput() {
+        mNotificationShadeWindowController.setKeyguardShowing(true);
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
+    }
+
+    @Test
+    public void setPanelExpanded_notFocusable_altFocusable_whenPanelIsOpen() {
+        mNotificationShadeWindowController.onShadeOrQsExpanded(true);
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.onShadeOrQsExpanded(true);
+        verifyNoMoreInteractions(mWindowManager);
+        mNotificationShadeWindowController.setNotificationShadeFocusable(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) != 0).isTrue();
+    }
+
+    @Test
+    public void setCommunalVisible_userTimeout() {
+        setKeyguardShowing();
+        clearInvocations(mWindowManager);
+
+        mNotificationShadeWindowController.onCommunalVisibleChanged(true);
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().userActivityTimeout)
+                .isEqualTo(CommunalInteractor.AWAKE_INTERVAL_MS);
+        clearInvocations(mWindowManager);
+
+        // Bouncer showing over communal overrides communal value
+        mNotificationShadeWindowController.setBouncerShowing(true);
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().userActivityTimeout)
+                .isEqualTo(KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS);
+    }
+
+    @Test
+    public void setKeyguardShowing_notFocusable_byDefault() {
+        mNotificationShadeWindowController.setKeyguardShowing(false);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) != 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
+    }
+
+    @Test
+    public void setKeyguardShowing_enablesSecureFlag() {
+        mNotificationShadeWindowController.setBouncerShowing(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) != 0).isTrue();
+        assertThat(
+                (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_TRACING)
+                        != 0)
+                .isTrue();
+    }
+
+    @Test
+    public void setKeyguardNotShowing_disablesSecureFlag() {
+        mNotificationShadeWindowController.setBouncerShowing(false);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) == 0).isTrue();
+        assertThat(
+                (mLayoutParameters.getValue().inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_TRACING)
+                        == 0)
+                .isTrue();
+    }
+
+    @Test
+    public void rotationBecameAllowed_layoutParamsUpdated() {
+        mNotificationShadeWindowController.setKeyguardShowing(true);
+        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
+        mNotificationShadeWindowController.onConfigChanged(new Configuration());
+        clearInvocations(mWindowManager);
+
+        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true);
+        mNotificationShadeWindowController.onConfigChanged(new Configuration());
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().screenOrientation)
+                .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_USER);
+    }
+
+    @Test
+    public void rotationBecameNotAllowed_layoutParamsUpdated() {
+        mNotificationShadeWindowController.setKeyguardShowing(true);
+        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true);
+        mNotificationShadeWindowController.onConfigChanged(new Configuration());
+        clearInvocations(mWindowManager);
+
+        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
+        mNotificationShadeWindowController.onConfigChanged(new Configuration());
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().screenOrientation)
+                .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
+    }
+
+    @Test
+    public void batchApplyWindowLayoutParams_doesNotDispatchEvents() {
+        mNotificationShadeWindowController.setForceDozeBrightness(true);
+        verify(mWindowManager).updateViewLayout(any(), any());
+        mNotificationShadeWindowController.setForceDozeBrightness(true);
+        verifyNoMoreInteractions(mWindowManager);
+
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.batchApplyWindowLayoutParams(() -> {
+            mNotificationShadeWindowController.setForceDozeBrightness(false);
+            verify(mWindowManager, never()).updateViewLayout(any(), any());
+        });
+        verify(mWindowManager).updateViewLayout(any(), any());
+    }
+
+    @Test
+    public void bouncerShowing_OrientationNoSensor() {
+        mNotificationShadeWindowController.setKeyguardShowing(true);
+        mNotificationShadeWindowController.setKeyguardOccluded(true);
+        mNotificationShadeWindowController.setBouncerShowing(true);
+        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
+        mNotificationShadeWindowController.onConfigChanged(new Configuration());
+
+        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().screenOrientation)
+                .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
+    }
+
+    @Test
+    public void udfpsEnrolled_minAndMaxRefreshRateSetToPreferredRefreshRate() {
+        // GIVEN optical udfps is enrolled
+        when(mAuthController.isOpticalUdfpsEnrolled(anyInt())).thenReturn(true);
+
+        // WHEN keyguard is showing
+        setKeyguardShowing();
+
+        // THEN min and max refresh rate is set to the preferredRefreshRate
+        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+        final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
+        final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
+        assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(mPreferredRefreshRate);
+        assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(mPreferredRefreshRate);
+    }
+
+    @Test
+    public void opticalUdfpsNotEnrolled_refreshRateUnset() {
+        // GIVEN udfps is NOT enrolled
+        when(mAuthController.isOpticalUdfpsEnrolled(anyInt())).thenReturn(false);
+
+        // WHEN keyguard is showing
+        setKeyguardShowing();
+
+        // THEN min and max refresh rate aren't set (set to 0)
+        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+        final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
+        final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
+        assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(0);
+        assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0);
+    }
+
+    @Test
+    public void keyguardNotShowing_refreshRateUnset() {
+        // GIVEN optical UDFPS is enrolled
+        when(mAuthController.isOpticalUdfpsEnrolled(anyInt())).thenReturn(true);
+
+        // WHEN keyguard is NOT showing
+        mNotificationShadeWindowController.setKeyguardShowing(false);
+
+        // THEN min and max refresh rate aren't set (set to 0)
+        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+        final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
+        final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
+        assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(0);
+        assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0);
+    }
+
+    private void setKeyguardShowing() {
+        mNotificationShadeWindowController.setKeyguardShowing(true);
+        mNotificationShadeWindowController.setKeyguardGoingAway(false);
+        mNotificationShadeWindowController.setKeyguardFadingAway(false);
+        mStateListener.getValue().onStateChanged(StatusBarState.KEYGUARD);
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt
index cbbcce9..420418b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeControllerSceneImplTest.kt
@@ -22,6 +22,7 @@
 import com.android.compose.animation.scene.SceneKey
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
@@ -30,7 +31,6 @@
 import com.android.systemui.kosmos.testCase
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.domain.interactor.shadeInteractor
@@ -52,6 +52,7 @@
 @ExperimentalCoroutinesApi
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class ShadeControllerSceneImplTest : SysuiTestCase() {
     private val kosmos = Kosmos()
     private val testScope = kosmos.testScope
@@ -64,7 +65,6 @@
     @Before
     fun setup() {
         kosmos.testCase = this
-        kosmos.fakeSceneContainerFlags.enabled = true
         kosmos.fakeFeatureFlagsClassic.apply {
             set(Flags.FULL_SCREEN_USER_SWITCHER, false)
             set(Flags.NSSL_DEBUG_LINES, false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt
index e759b50..468c39d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt
@@ -22,85 +22,107 @@
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shared.recents.utilities.Utilities
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Assume
 import org.junit.Before
-import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-@Ignore("b/328827631")
+@EnableSceneContainer
 class ShadeBackActionInteractorImplTest : SysuiTestCase() {
-    val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true }
+    val kosmos = testKosmos()
     val testScope = kosmos.testScope
-    val sceneInteractor = kosmos.sceneInteractor
-    val underTest = kosmos.shadeBackActionInteractor
+    val sceneInteractor by lazy { kosmos.sceneInteractor }
+    val shadeInteractor by lazy { kosmos.shadeInteractor }
+    val fakeAuthenticationRepository by lazy { kosmos.fakeAuthenticationRepository }
+    val deviceEntryFingerprintAuthRepository by lazy { kosmos.deviceEntryFingerprintAuthRepository }
+
+    lateinit var underTest: ShadeBackActionInteractor
 
     @Before
-    fun ignoreSplitShade() {
+    fun ignoreSplitShadeAndSetup() {
         Assume.assumeFalse(Utilities.isLargeScreen(kosmos.applicationContext))
+        underTest = kosmos.shadeBackActionInteractor
     }
 
     @Test
     fun animateCollapseQs_notOnQs() =
         testScope.runTest {
+            val actual by collectLastValue(sceneInteractor.currentScene)
             setScene(Scenes.Shade)
             underTest.animateCollapseQs(true)
             runCurrent()
-            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Shade)
+            assertThat(actual).isEqualTo(Scenes.Shade)
         }
 
     @Test
     fun animateCollapseQs_fullyCollapse_entered() =
         testScope.runTest {
+            val actual by collectLastValue(sceneInteractor.currentScene)
             enterDevice()
             setScene(Scenes.QuickSettings)
             underTest.animateCollapseQs(true)
             runCurrent()
-            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Gone)
+            assertThat(actual).isEqualTo(Scenes.Gone)
         }
 
     @Test
     fun animateCollapseQs_fullyCollapse_locked() =
         testScope.runTest {
+            val actual by collectLastValue(sceneInteractor.currentScene)
             setScene(Scenes.QuickSettings)
             underTest.animateCollapseQs(true)
             runCurrent()
-            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
+            assertThat(actual).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
     fun animateCollapseQs_notFullyCollapse() =
         testScope.runTest {
+            val actual by collectLastValue(sceneInteractor.currentScene)
             setScene(Scenes.QuickSettings)
             underTest.animateCollapseQs(false)
             runCurrent()
-            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Shade)
+            assertThat(actual).isEqualTo(Scenes.Shade)
         }
 
-    private fun enterDevice() {
-        testScope.runCurrent()
+    private fun TestScope.enterDevice() {
+        // configure device unlocked state
+        fakeAuthenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+        runCurrent()
+        deviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+            SuccessFingerprintAuthenticationStatus(0, true)
+        )
+        runCurrent()
         setScene(Scenes.Gone)
     }
 
-    private fun setScene(key: SceneKey) {
+    private fun TestScope.setScene(key: SceneKey) {
+        val actual by collectLastValue(sceneInteractor.currentScene)
         sceneInteractor.changeScene(key, "test")
         sceneInteractor.setTransitionState(
             MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(key))
         )
-        testScope.runCurrent()
+        runCurrent()
+        assertThat(actual).isEqualTo(key)
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
index 757a6c9..aa0ca18 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
@@ -19,11 +19,12 @@
 import android.app.StatusBarManager.DISABLE2_NONE
 import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
 import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.parameterizeSceneContainerFlag
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.DozeStateModel
@@ -36,9 +37,7 @@
 import com.android.systemui.power.data.repository.fakePowerRepository
 import com.android.systemui.power.shared.model.WakeSleepReason
 import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.res.R
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
 import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
 import com.android.systemui.statusbar.phone.dozeParameters
@@ -52,28 +51,47 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@RunWith(AndroidJUnit4::class)
-class ShadeInteractorImplTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class ShadeInteractorImplTest(flags: FlagsParameterization?) : SysuiTestCase() {
     val kosmos = testKosmos()
     val testScope = kosmos.testScope
-    val configurationRepository = kosmos.fakeConfigurationRepository
-    val deviceProvisioningRepository = kosmos.fakeDeviceProvisioningRepository
-    val disableFlagsRepository = kosmos.fakeDisableFlagsRepository
-    val keyguardRepository = kosmos.fakeKeyguardRepository
-    val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
-    val powerRepository = kosmos.fakePowerRepository
-    val sceneInteractor = kosmos.sceneInteractor
-    val shadeRepository = kosmos.fakeShadeRepository
-    val userRepository = kosmos.fakeUserRepository
-    val userSetupRepository = kosmos.fakeUserSetupRepository
-    val dozeParameters = kosmos.dozeParameters
+    val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
+    val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
+    val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
+    val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+    val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
+    val powerRepository by lazy { kosmos.fakePowerRepository }
+    val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+    val userRepository by lazy { kosmos.fakeUserRepository }
+    val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
+    val dozeParameters by lazy { kosmos.dozeParameters }
 
-    val underTest = kosmos.shadeInteractorImpl
+    lateinit var underTest: ShadeInteractorImpl
+
+    companion object {
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return parameterizeSceneContainerFlag()
+        }
+    }
+
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
+    @Before
+    fun setup() {
+        underTest = kosmos.shadeInteractorImpl
+    }
 
     @Test
     fun isShadeEnabled_matchesDisableFlagsRepo() =
@@ -284,88 +302,13 @@
         }
 
     @Test
-    fun fullShadeExpansionWhenShadeLocked() =
-        testScope.runTest {
-            val actual by collectLastValue(underTest.shadeExpansion)
-
-            keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
-            shadeRepository.setLockscreenShadeExpansion(0.5f)
-
-            assertThat(actual).isEqualTo(1f)
-        }
-
-    @Test
-    fun fullShadeExpansionWhenStatusBarStateIsNotShadeLocked() =
-        testScope.runTest {
-            val actual by collectLastValue(underTest.shadeExpansion)
-
-            keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
-
-            shadeRepository.setLockscreenShadeExpansion(0.5f)
-            assertThat(actual).isEqualTo(0.5f)
-
-            shadeRepository.setLockscreenShadeExpansion(0.8f)
-            assertThat(actual).isEqualTo(0.8f)
-        }
-
-    @Test
-    fun shadeExpansionWhenInSplitShadeAndQsExpanded() =
-        testScope.runTest {
-            val actual by collectLastValue(underTest.shadeExpansion)
-
-            // WHEN split shade is enabled and QS is expanded
-            keyguardRepository.setStatusBarState(StatusBarState.SHADE)
-            overrideResource(R.bool.config_use_split_notification_shade, true)
-            configurationRepository.onAnyConfigurationChange()
-            shadeRepository.setQsExpansion(.5f)
-            shadeRepository.setLegacyShadeExpansion(.7f)
-            runCurrent()
-
-            // THEN legacy shade expansion is passed through
-            assertThat(actual).isEqualTo(.7f)
-        }
-
-    @Test
-    fun shadeExpansionWhenNotInSplitShadeAndQsPartiallyExpanded() =
-        testScope.runTest {
-            val actual by collectLastValue(underTest.shadeExpansion)
-
-            // WHEN split shade is not enabled and QS is expanded
-            keyguardRepository.setStatusBarState(StatusBarState.SHADE)
-            overrideResource(R.bool.config_use_split_notification_shade, false)
-            shadeRepository.setQsExpansion(.5f)
-            shadeRepository.setLegacyShadeExpansion(1f)
-            runCurrent()
-
-            // THEN shade expansion is zero
-            assertThat(actual).isEqualTo(.5f)
-        }
-
-    @Test
-    fun shadeExpansionWhenNotInSplitShadeAndQsFullyExpanded() =
-        testScope.runTest {
-            val actual by collectLastValue(underTest.shadeExpansion)
-
-            // WHEN split shade is not enabled and QS is expanded
-            keyguardRepository.setStatusBarState(StatusBarState.SHADE)
-            overrideResource(R.bool.config_use_split_notification_shade, false)
-            shadeRepository.setQsExpansion(1f)
-            shadeRepository.setLegacyShadeExpansion(1f)
-            runCurrent()
-
-            // THEN shade expansion is zero
-            assertThat(actual).isEqualTo(0f)
-        }
-
-    @Test
     fun shadeExpansionWhenNotInSplitShadeAndQsCollapsed() =
         testScope.runTest {
             val actual by collectLastValue(underTest.shadeExpansion)
 
             // WHEN split shade is not enabled and QS is expanded
             keyguardRepository.setStatusBarState(StatusBarState.SHADE)
-            shadeRepository.setQsExpansion(0f)
-            shadeRepository.setLegacyShadeExpansion(.6f)
+            shadeTestUtil.setShadeAndQsExpansion(.6f, 0f)
 
             // THEN shade expansion is zero
             assertThat(actual).isEqualTo(.6f)
@@ -375,8 +318,7 @@
     fun anyExpansion_shadeGreater() =
         testScope.runTest() {
             // WHEN shade is more expanded than QS
-            shadeRepository.setLegacyShadeExpansion(.5f)
-            shadeRepository.setQsExpansion(0f)
+            shadeTestUtil.setShadeAndQsExpansion(.5f, 0f)
             runCurrent()
 
             // THEN anyExpansion is .5f
@@ -387,8 +329,7 @@
     fun anyExpansion_qsGreater() =
         testScope.runTest() {
             // WHEN qs is more expanded than shade
-            shadeRepository.setLegacyShadeExpansion(0f)
-            shadeRepository.setQsExpansion(.5f)
+            shadeTestUtil.setShadeAndQsExpansion(0f, .5f)
             runCurrent()
 
             // THEN anyExpansion is .5f
@@ -396,229 +337,6 @@
         }
 
     @Test
-    fun userInteractingWithShade_shadeDraggedUpAndDown() =
-        testScope.runTest() {
-            val actual by collectLastValue(underTest.isUserInteractingWithShade)
-            // GIVEN shade collapsed and not tracking input
-            shadeRepository.setLegacyShadeExpansion(0f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-
-            // WHEN shade tracking starts
-            shadeRepository.setLegacyShadeTracking(true)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade dragged down halfway
-            shadeRepository.setLegacyShadeExpansion(.5f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade fully expanded but tracking is not stopped
-            shadeRepository.setLegacyShadeExpansion(1f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade fully collapsed but tracking is not stopped
-            shadeRepository.setLegacyShadeExpansion(0f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade dragged halfway and tracking is stopped
-            shadeRepository.setLegacyShadeExpansion(.6f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade completes expansion stopped
-            shadeRepository.setLegacyShadeExpansion(1f)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-        }
-
-    @Test
-    fun userInteractingWithShade_shadeExpanded() =
-        testScope.runTest() {
-            val actual by collectLastValue(underTest.isUserInteractingWithShade)
-            // GIVEN shade collapsed and not tracking input
-            shadeRepository.setLegacyShadeExpansion(0f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-
-            // WHEN shade tracking starts
-            shadeRepository.setLegacyShadeTracking(true)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade dragged down halfway
-            shadeRepository.setLegacyShadeExpansion(.5f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade fully expanded and tracking is stopped
-            shadeRepository.setLegacyShadeExpansion(1f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-        }
-
-    @Test
-    fun userInteractingWithShade_shadePartiallyExpanded() =
-        testScope.runTest() {
-            val actual by collectLastValue(underTest.isUserInteractingWithShade)
-            // GIVEN shade collapsed and not tracking input
-            shadeRepository.setLegacyShadeExpansion(0f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-
-            // WHEN shade tracking starts
-            shadeRepository.setLegacyShadeTracking(true)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade partially expanded
-            shadeRepository.setLegacyShadeExpansion(.4f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN tracking is stopped
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade goes back to collapsed
-            shadeRepository.setLegacyShadeExpansion(0f)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-        }
-
-    @Test
-    fun userInteractingWithShade_shadeCollapsed() =
-        testScope.runTest() {
-            val actual by collectLastValue(underTest.isUserInteractingWithShade)
-            // GIVEN shade expanded and not tracking input
-            shadeRepository.setLegacyShadeExpansion(1f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-
-            // WHEN shade tracking starts
-            shadeRepository.setLegacyShadeTracking(true)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade dragged up halfway
-            shadeRepository.setLegacyShadeExpansion(.5f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN shade fully collapsed and tracking is stopped
-            shadeRepository.setLegacyShadeExpansion(0f)
-            shadeRepository.setLegacyShadeTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-        }
-
-    @Test
-    fun userInteractingWithQs_qsDraggedUpAndDown() =
-        testScope.runTest() {
-            val actual by collectLastValue(underTest.isUserInteractingWithQs)
-            // GIVEN qs collapsed and not tracking input
-            shadeRepository.setQsExpansion(0f)
-            shadeRepository.setLegacyQsTracking(false)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-
-            // WHEN qs tracking starts
-            shadeRepository.setLegacyQsTracking(true)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN qs dragged down halfway
-            shadeRepository.setQsExpansion(.5f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN qs fully expanded but tracking is not stopped
-            shadeRepository.setQsExpansion(1f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN qs fully collapsed but tracking is not stopped
-            shadeRepository.setQsExpansion(0f)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN qs dragged halfway and tracking is stopped
-            shadeRepository.setQsExpansion(.6f)
-            shadeRepository.setLegacyQsTracking(false)
-            runCurrent()
-
-            // THEN user is interacting
-            assertThat(actual).isTrue()
-
-            // WHEN qs completes expansion stopped
-            shadeRepository.setQsExpansion(1f)
-            runCurrent()
-
-            // THEN user is not interacting
-            assertThat(actual).isFalse()
-        }
-
-    @Test
     fun isShadeTouchable_isFalse_whenDeviceAsleepAndNotPulsing() =
         testScope.runTest {
             powerRepository.updateWakefulness(
@@ -641,7 +359,6 @@
                 )
             )
             val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
-            runCurrent()
             assertThat(isShadeTouchable).isFalse()
         }
 
@@ -668,13 +385,17 @@
                 )
             )
             val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
-            runCurrent()
             assertThat(isShadeTouchable).isTrue()
         }
 
     @Test
     fun isShadeTouchable_isFalse_whenStartingToSleepAndNotControlScreenOff() =
         testScope.runTest {
+            whenever(dozeParameters.shouldControlScreenOff()).thenReturn(false)
+            val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+            // Assert the default condition is true
+            assertThat(isShadeTouchable).isTrue()
+
             powerRepository.updateWakefulness(
                 rawState = WakefulnessState.STARTING_TO_SLEEP,
                 lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -688,15 +409,17 @@
                     transitionState = TransitionState.STARTED,
                 )
             )
-            whenever(dozeParameters.shouldControlScreenOff()).thenReturn(false)
-            val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
-            runCurrent()
             assertThat(isShadeTouchable).isFalse()
         }
 
     @Test
     fun isShadeTouchable_isTrue_whenStartingToSleepAndControlScreenOff() =
         testScope.runTest {
+            whenever(dozeParameters.shouldControlScreenOff()).thenReturn(true)
+            val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+            // Assert the default condition is true
+            assertThat(isShadeTouchable).isTrue()
+
             powerRepository.updateWakefulness(
                 rawState = WakefulnessState.STARTING_TO_SLEEP,
                 lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -710,9 +433,6 @@
                     transitionState = TransitionState.STARTED,
                 )
             )
-            whenever(dozeParameters.shouldControlScreenOff()).thenReturn(true)
-            val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
-            runCurrent()
             assertThat(isShadeTouchable).isTrue()
         }
 
@@ -730,7 +450,6 @@
                 )
             )
             val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
-            runCurrent()
             assertThat(isShadeTouchable).isTrue()
         }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt
index 0ae95e7..109cd053 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.DisableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.StatusBarState
@@ -40,6 +41,7 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@DisableSceneContainer
 class ShadeInteractorLegacyImplTest : SysuiTestCase() {
     val kosmos = testKosmos()
     val testScope = kosmos.testScope
@@ -95,6 +97,22 @@
         }
 
     @Test
+    fun shadeExpansionWhenNotInSplitShadeAndQsPartiallyExpanded() =
+        testScope.runTest {
+            val actual by collectLastValue(underTest.shadeExpansion)
+
+            // WHEN split shade is not enabled and QS is expanded
+            keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+            overrideResource(R.bool.config_use_split_notification_shade, false)
+            shadeRepository.setQsExpansion(.5f)
+            shadeRepository.setLegacyShadeExpansion(1f)
+            runCurrent()
+
+            // THEN shade expansion is zero
+            assertThat(actual).isEqualTo(.5f)
+        }
+
+    @Test
     fun shadeExpansionWhenNotInSplitShadeAndQsFullyExpanded() =
         testScope.runTest {
             val actual by collectLastValue(underTest.shadeExpansion)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
index 8c9036a..e1908b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
@@ -23,7 +23,6 @@
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
@@ -32,7 +31,6 @@
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.testKosmos
-import com.android.systemui.user.data.repository.userRepository
 import com.google.common.truth.Truth
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -52,9 +50,7 @@
     private val testScope = kosmos.testScope
     private val configurationRepository = kosmos.fakeConfigurationRepository
     private val keyguardRepository = kosmos.fakeKeyguardRepository
-    private val keyguardTransitionRepository = kosmos.keyguardTransitionRepository
     private val sceneInteractor = kosmos.sceneInteractor
-    private val userRepository = kosmos.userRepository
     private val shadeRepository = kosmos.shadeRepository
 
     private val underTest = kosmos.shadeInteractorSceneContainerImpl
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
index 2ab934c..07c4b00 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.shade.domain.startable
 
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
@@ -25,9 +25,8 @@
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
 import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.flags.parameterizeSceneContainerFlag
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
@@ -50,24 +49,42 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@RunWith(AndroidJUnit4::class)
-class ShadeStartableTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class ShadeStartableTest(flags: FlagsParameterization?) : SysuiTestCase() {
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
-    private val shadeInteractor = kosmos.shadeInteractor
-    private val sceneInteractor = kosmos.sceneInteractor
-    private val shadeExpansionStateManager = kosmos.shadeExpansionStateManager
-    private val deviceEntryRepository = kosmos.fakeDeviceEntryRepository
-    private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
-    private val fakeConfigurationRepository = kosmos.fakeConfigurationRepository
-    private val fakeSceneDataSource = kosmos.fakeSceneDataSource
+    private val shadeInteractor by lazy { kosmos.shadeInteractor }
+    private val sceneInteractor by lazy { kosmos.sceneInteractor }
+    private val shadeExpansionStateManager by lazy { kosmos.shadeExpansionStateManager }
+    private val fakeConfigurationRepository by lazy { kosmos.fakeConfigurationRepository }
+    private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
 
-    private val underTest = kosmos.shadeStartable
+    private lateinit var underTest: ShadeStartable
+
+    companion object {
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return parameterizeSceneContainerFlag()
+        }
+    }
+
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
+    @Before
+    fun setup() {
+        underTest = kosmos.shadeStartable
+    }
 
     @Test
     fun hydrateShadeMode() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
index 4c573d3..f89f18a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
@@ -2,29 +2,18 @@
 
 import android.content.Intent
 import android.provider.AlarmClock
+import android.provider.Settings
 import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.activityStarter
-import com.android.systemui.shade.domain.interactor.privacyChipInteractor
-import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
-import com.android.systemui.shade.domain.interactor.shadeInteractor
-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.data.model.SubscriptionModel
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
-import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.argThat
-import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -40,43 +29,13 @@
 class ShadeHeaderViewModelTest : SysuiTestCase() {
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
+    private val mobileIconsInteractor = kosmos.fakeMobileIconsInteractor
 
-    private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
-    private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
-
-    private var mobileIconsViewModel: MobileIconsViewModel =
-        MobileIconsViewModel(
-            logger = mock(),
-            verboseLogger = mock(),
-            interactor = mobileIconsInteractor,
-            airplaneModeInteractor =
-                AirplaneModeInteractor(
-                    FakeAirplaneModeRepository(),
-                    FakeConnectivityRepository(),
-                    FakeMobileConnectionsRepository(),
-                ),
-            constants = mock(),
-            flags,
-            scope = testScope.backgroundScope,
-        )
-
-    private lateinit var underTest: ShadeHeaderViewModel
+    private val underTest: ShadeHeaderViewModel = kosmos.shadeHeaderViewModel
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-
-        underTest =
-            ShadeHeaderViewModel(
-                applicationScope = testScope.backgroundScope,
-                context = context,
-                shadeInteractor = kosmos.shadeInteractor,
-                mobileIconsInteractor = mobileIconsInteractor,
-                mobileIconsViewModel = mobileIconsViewModel,
-                privacyChipInteractor = kosmos.privacyChipInteractor,
-                clockInteractor = kosmos.shadeHeaderClockInteractor,
-                broadcastDispatcher = fakeBroadcastDispatcher,
-            )
     }
 
     @Test
@@ -105,6 +64,19 @@
                 )
         }
 
+    @Test
+    fun onShadeCarrierGroupClicked_launchesNetworkSettings() =
+        testScope.runTest {
+            val activityStarter = kosmos.activityStarter
+            underTest.onShadeCarrierGroupClicked()
+
+            verify(activityStarter)
+                .postStartActivityDismissingKeyguard(
+                    argThat(IntentMatcherAction(Settings.ACTION_WIRELESS_SETTINGS)),
+                    anyInt(),
+                )
+        }
+
     companion object {
         private val SUB_1 =
             SubscriptionModel(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 77109d6..5312ad80 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -24,11 +24,11 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
@@ -39,25 +39,21 @@
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
 import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.domain.interactor.privacyChipInteractor
-import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shade.domain.startable.shadeStartable
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel
-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.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
-import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.testKosmos
+import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor
+import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
+import java.util.Locale
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -70,6 +66,7 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 @TestableLooper.RunWithLooper
+@EnableSceneContainer
 class ShadeSceneViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
@@ -78,29 +75,8 @@
     private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor }
     private val shadeRepository by lazy { kosmos.shadeRepository }
 
-    private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
-    private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
-
-    private var mobileIconsViewModel: MobileIconsViewModel =
-        MobileIconsViewModel(
-            logger = mock(),
-            verboseLogger = mock(),
-            interactor = mobileIconsInteractor,
-            airplaneModeInteractor =
-                AirplaneModeInteractor(
-                    FakeAirplaneModeRepository(),
-                    FakeConnectivityRepository(),
-                    FakeMobileConnectionsRepository(),
-                ),
-            constants = mock(),
-            flags,
-            scope = testScope.backgroundScope,
-        )
-
     private val qsSceneAdapter = FakeQSSceneAdapter({ mock() })
 
-    private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel
-
     private lateinit var underTest: ShadeSceneViewModel
 
     @Mock private lateinit var mediaDataManager: MediaDataManager
@@ -108,30 +84,21 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        shadeHeaderViewModel =
-            ShadeHeaderViewModel(
-                applicationScope = testScope.backgroundScope,
-                context = context,
-                shadeInteractor = kosmos.shadeInteractor,
-                mobileIconsInteractor = mobileIconsInteractor,
-                mobileIconsViewModel = mobileIconsViewModel,
-                privacyChipInteractor = kosmos.privacyChipInteractor,
-                clockInteractor = kosmos.shadeHeaderClockInteractor,
-                broadcastDispatcher = fakeBroadcastDispatcher,
-            )
 
         underTest =
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
                 deviceEntryInteractor = deviceEntryInteractor,
-                shadeHeaderViewModel = shadeHeaderViewModel,
+                shadeHeaderViewModel = kosmos.shadeHeaderViewModel,
                 qsSceneAdapter = qsSceneAdapter,
                 notifications = kosmos.notificationsPlaceholderViewModel,
+                brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel,
                 mediaDataManager = mediaDataManager,
                 shadeInteractor = kosmos.shadeInteractor,
                 footerActionsViewModelFactory = kosmos.footerActionsViewModelFactory,
                 footerActionsController = kosmos.footerActionsController,
                 sceneInteractor = kosmos.sceneInteractor,
+                unfoldTransitionInteractor = kosmos.unfoldTransitionInteractor,
             )
     }
 
@@ -295,4 +262,59 @@
             shadeRepository.setShadeMode(ShadeMode.Split)
             assertThat(shadeMode).isEqualTo(ShadeMode.Split)
         }
+
+    @Test
+    fun unfoldTransitionProgress() =
+        testScope.runTest {
+            val maxTranslation = prepareConfiguration()
+            val translations by
+                collectLastValue(
+                    combine(
+                        underTest.unfoldTranslationX(isOnStartSide = true),
+                        underTest.unfoldTranslationX(isOnStartSide = false),
+                    ) { start, end ->
+                        Translations(
+                            start = start,
+                            end = end,
+                        )
+                    }
+                )
+
+            val unfoldProvider = kosmos.fakeUnfoldTransitionProgressProvider
+            unfoldProvider.onTransitionStarted()
+            assertThat(translations?.start).isEqualTo(0f)
+            assertThat(translations?.end).isEqualTo(-0f)
+
+            repeat(10) { repetition ->
+                val transitionProgress = 0.1f * (repetition + 1)
+                unfoldProvider.onTransitionProgress(transitionProgress)
+                assertThat(translations?.start).isEqualTo((1 - transitionProgress) * maxTranslation)
+                assertThat(translations?.end).isEqualTo(-(1 - transitionProgress) * maxTranslation)
+            }
+
+            unfoldProvider.onTransitionFinishing()
+            assertThat(translations?.start).isEqualTo(0f)
+            assertThat(translations?.end).isEqualTo(-0f)
+
+            unfoldProvider.onTransitionFinished()
+            assertThat(translations?.start).isEqualTo(0f)
+            assertThat(translations?.end).isEqualTo(-0f)
+        }
+
+    private fun prepareConfiguration(): Int {
+        val configuration = context.resources.configuration
+        configuration.setLayoutDirection(Locale.US)
+        kosmos.fakeConfigurationRepository.onConfigurationChange(configuration)
+        val maxTranslation = 10
+        kosmos.fakeConfigurationRepository.setDimensionPixelSize(
+            R.dimen.notification_side_paddings,
+            maxTranslation
+        )
+        return maxTranslation
+    }
+
+    private data class Translations(
+        val start: Float,
+        val end: Float,
+    )
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
new file mode 100644
index 0000000..d353a62
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar
+
+import android.animation.ObjectAnimator
+import android.platform.test.flag.junit.FlagsParameterization
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.flags.parameterizeSceneContainerFlag
+import com.android.systemui.jank.interactionJankMonitor
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.testKosmos
+import com.android.systemui.util.kotlin.JavaAdapter
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
+
+@SmallTest
+@RunWith(ParameterizedAndroidJunit4::class)
[email protected]
+class StatusBarStateControllerImplTest(flags: FlagsParameterization?) : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private val mockDarkAnimator = mock<ObjectAnimator>()
+
+    private lateinit var underTest: StatusBarStateControllerImpl
+    private lateinit var uiEventLogger: UiEventLoggerFake
+
+    companion object {
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return parameterizeSceneContainerFlag()
+        }
+    }
+
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        uiEventLogger = UiEventLoggerFake()
+        underTest =
+            object :
+                StatusBarStateControllerImpl(
+                    uiEventLogger,
+                    { kosmos.interactionJankMonitor },
+                    JavaAdapter(testScope.backgroundScope),
+                    { kosmos.shadeInteractor },
+                    { kosmos.deviceUnlockedInteractor },
+                    { kosmos.sceneInteractor },
+                    { kosmos.keyguardClockInteractor },
+                ) {
+                override fun createDarkAnimator(): ObjectAnimator {
+                    return mockDarkAnimator
+                }
+            }
+    }
+
+    @Test
+    @DisableSceneContainer
+    fun testChangeState_logged() {
+        TestableLooper.get(this).runWithLooper {
+            underTest.state = StatusBarState.KEYGUARD
+            underTest.state = StatusBarState.SHADE
+            underTest.state = StatusBarState.SHADE_LOCKED
+        }
+
+        val logs = uiEventLogger.logs
+        assertEquals(3, logs.size)
+        val ids = logs.map(UiEventLoggerFake.FakeUiEvent::eventId)
+        assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_KEYGUARD.id, ids[0])
+        assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_SHADE.id, ids[1])
+        assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_SHADE_LOCKED.id, ids[2])
+    }
+
+    @Test
+    fun testSetDozeAmountInternal_onlySetsOnce() {
+        val listener = mock(StatusBarStateController.StateListener::class.java)
+        underTest.addCallback(listener)
+
+        underTest.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */)
+        underTest.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */)
+        verify(listener).onDozeAmountChanged(eq(0.5f), anyFloat())
+    }
+
+    @Test
+    @DisableSceneContainer
+    fun testSetState_appliesState_sameStateButDifferentUpcomingState() {
+        underTest.state = StatusBarState.SHADE
+        underTest.setUpcomingState(StatusBarState.KEYGUARD)
+
+        assertEquals(underTest.state, StatusBarState.SHADE)
+
+        // We should return true (state change was applied) despite going from SHADE to SHADE, since
+        // the upcoming state was set to KEYGUARD.
+        assertTrue(underTest.setState(StatusBarState.SHADE))
+    }
+
+    @Test
+    @DisableSceneContainer
+    fun testSetState_appliesState_differentStateEqualToUpcomingState() {
+        underTest.state = StatusBarState.SHADE
+        underTest.setUpcomingState(StatusBarState.KEYGUARD)
+
+        assertEquals(underTest.state, StatusBarState.SHADE)
+
+        // Make sure we apply a SHADE -> KEYGUARD state change when the upcoming state is KEYGUARD.
+        assertTrue(underTest.setState(StatusBarState.KEYGUARD))
+    }
+
+    @Test
+    @DisableSceneContainer
+    fun testSetState_doesNotApplyState_currentAndUpcomingStatesSame() {
+        underTest.state = StatusBarState.SHADE
+        underTest.setUpcomingState(StatusBarState.SHADE)
+
+        assertEquals(underTest.state, StatusBarState.SHADE)
+
+        // We're going from SHADE -> SHADE, and the upcoming state is also SHADE, this should not do
+        // anything.
+        assertFalse(underTest.setState(StatusBarState.SHADE))
+
+        // Double check that we can still force it to happen.
+        assertTrue(underTest.setState(StatusBarState.SHADE, true /* force */))
+    }
+
+    @Test
+    fun testSetDozeAmount_immediatelyChangesDozeAmount_lockscreenTransitionFromAod() {
+        // Put controller in AOD state
+        underTest.setAndInstrumentDozeAmount(null, 1f, false)
+
+        // When waking from doze, CentralSurfaces#updateDozingState will update the dozing state
+        // before the doze amount changes
+        underTest.setIsDozing(false)
+
+        // Animate the doze amount to 0f, as would normally happen
+        underTest.setAndInstrumentDozeAmount(null, 0f, true)
+
+        // Check that the doze amount is immediately set to a value slightly less than 1f. This is
+        // to ensure that any scrim implementation changes its opacity immediately rather than
+        // waiting an extra frame. Waiting an extra frame will cause a relayout (which is expensive)
+        // and cause us to drop a frame during the LOCKSCREEN_TRANSITION_FROM_AOD CUJ.
+        assertEquals(0.99f, underTest.dozeAmount, 0.009f)
+    }
+
+    @Test
+    fun testSetDreamState_invokesCallback() {
+        val listener = mock(StatusBarStateController.StateListener::class.java)
+        underTest.addCallback(listener)
+
+        underTest.setIsDreaming(true)
+        verify(listener).onDreamingChanged(true)
+
+        Mockito.clearInvocations(listener)
+
+        underTest.setIsDreaming(false)
+        verify(listener).onDreamingChanged(false)
+    }
+
+    @Test
+    fun testSetDreamState_getterReturnsCurrentState() {
+        underTest.setIsDreaming(true)
+        assertTrue(underTest.isDreaming())
+
+        underTest.setIsDreaming(false)
+        assertFalse(underTest.isDreaming())
+    }
+
+    @Test
+    @EnableSceneContainer
+    fun start_hydratesStatusBarState_whileLocked() =
+        testScope.runTest {
+            var statusBarState = underTest.state
+            val listener =
+                object : StatusBarStateController.StateListener {
+                    override fun onStateChanged(newState: Int) {
+                        statusBarState = newState
+                    }
+                }
+            underTest.addCallback(listener)
+
+            val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
+            val deviceUnlockStatus by
+                collectLastValue(kosmos.deviceUnlockedInteractor.deviceUnlockStatus)
+
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Password
+            )
+            runCurrent()
+            assertThat(deviceUnlockStatus!!.isUnlocked).isFalse()
+
+            kosmos.sceneInteractor.changeScene(
+                toScene = Scenes.Lockscreen,
+                loggingReason = "reason"
+            )
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+            // Call start to begin hydrating based on the scene framework:
+            underTest.start()
+
+            kosmos.sceneInteractor.changeScene(toScene = Scenes.Bouncer, loggingReason = "reason")
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+            assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD)
+
+            kosmos.sceneInteractor.changeScene(toScene = Scenes.Shade, loggingReason = "reason")
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Shade)
+            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE_LOCKED)
+
+            kosmos.sceneInteractor.changeScene(
+                toScene = Scenes.QuickSettings,
+                loggingReason = "reason"
+            )
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE_LOCKED)
+
+            kosmos.sceneInteractor.changeScene(toScene = Scenes.Communal, loggingReason = "reason")
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Communal)
+            assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD)
+
+            kosmos.sceneInteractor.changeScene(
+                toScene = Scenes.Lockscreen,
+                loggingReason = "reason"
+            )
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD)
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun start_hydratesStatusBarState_whileUnlocked() =
+        testScope.runTest {
+            var statusBarState = underTest.state
+            val listener =
+                object : StatusBarStateController.StateListener {
+                    override fun onStateChanged(newState: Int) {
+                        statusBarState = newState
+                    }
+                }
+            underTest.addCallback(listener)
+
+            val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
+            val deviceUnlockStatus by
+                collectLastValue(kosmos.deviceUnlockedInteractor.deviceUnlockStatus)
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Password
+            )
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
+            runCurrent()
+
+            assertThat(deviceUnlockStatus!!.isUnlocked).isTrue()
+
+            kosmos.sceneInteractor.changeScene(toScene = Scenes.Gone, loggingReason = "reason")
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Gone)
+
+            // Call start to begin hydrating based on the scene framework:
+            underTest.start()
+
+            kosmos.sceneInteractor.changeScene(toScene = Scenes.Shade, loggingReason = "reason")
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.Shade)
+            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE)
+
+            kosmos.sceneInteractor.changeScene(
+                toScene = Scenes.QuickSettings,
+                loggingReason = "reason"
+            )
+            runCurrent()
+            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
index 53522e2..01e1aa59 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
@@ -23,15 +23,16 @@
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationStackAppearanceViewModel
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationScrollViewModel
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -45,11 +46,11 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class NotificationStackAppearanceIntegrationTest : SysuiTestCase() {
 
     private val kosmos =
         testKosmos().apply {
-            fakeSceneContainerFlags.enabled = true
             fakeFeatureFlagsClassic.apply {
                 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
                 set(Flags.NSSL_DEBUG_LINES, false)
@@ -57,27 +58,44 @@
         }
     private val testScope = kosmos.testScope
     private val placeholderViewModel by lazy { kosmos.notificationsPlaceholderViewModel }
-    private val appearanceViewModel by lazy { kosmos.notificationStackAppearanceViewModel }
+    private val appearanceViewModel by lazy { kosmos.notificationScrollViewModel }
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
     private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
 
     @Test
     fun updateBounds() =
         testScope.runTest {
-            val clipping by collectLastValue(appearanceViewModel.shadeScrimClipping)
+            val radius = MutableStateFlow(32)
+            val leftOffset = MutableStateFlow(0)
+            val shape by collectLastValue(appearanceViewModel.shadeScrimShape(radius, leftOffset))
 
-            val top = 200f
-            val left = 0f
-            val bottom = 550f
-            val right = 100f
-            placeholderViewModel.onBoundsChanged(
-                left = left,
-                top = top,
-                right = right,
-                bottom = bottom
+            placeholderViewModel.onScrimBoundsChanged(
+                ShadeScrimBounds(left = 0f, top = 200f, right = 100f, bottom = 550f)
             )
-            assertThat(clipping?.bounds)
-                .isEqualTo(ShadeScrimBounds(left = left, top = top, right = right, bottom = bottom))
+            assertThat(shape)
+                .isEqualTo(
+                    ShadeScrimShape(
+                        bounds =
+                            ShadeScrimBounds(left = 0f, top = 200f, right = 100f, bottom = 550f),
+                        topRadius = 32,
+                        bottomRadius = 0
+                    )
+                )
+
+            leftOffset.value = 200
+            radius.value = 24
+            placeholderViewModel.onScrimBoundsChanged(
+                ShadeScrimBounds(left = 210f, top = 200f, right = 300f, bottom = 550f)
+            )
+            assertThat(shape)
+                .isEqualTo(
+                    ShadeScrimShape(
+                        bounds =
+                            ShadeScrimBounds(left = 10f, top = 200f, right = 100f, bottom = 550f),
+                        topRadius = 24,
+                        bottomRadius = 0
+                    )
+                )
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
index dc928c4..50b77dc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
@@ -68,11 +68,11 @@
 
             kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
             assertThat(stackRounding)
-                .isEqualTo(ShadeScrimRounding(roundTop = true, roundBottom = false))
+                .isEqualTo(ShadeScrimRounding(isTopRounded = true, isBottomRounded = false))
 
             kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
             assertThat(stackRounding)
-                .isEqualTo(ShadeScrimRounding(roundTop = true, roundBottom = true))
+                .isEqualTo(ShadeScrimRounding(isTopRounded = true, isBottomRounded = true))
         }
 
     @Test(expected = IllegalStateException::class)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelTest.kt
index d4a7049..1f0812d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelTest.kt
@@ -16,14 +16,10 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
-import android.platform.test.annotations.DisableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.shared.model.NotificationContainerBounds
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor
 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
@@ -40,23 +36,21 @@
     private val underTest = kosmos.notificationsPlaceholderViewModel
 
     @Test
-    @DisableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun onBoundsChanged_setsNotificationContainerBounds() =
+    fun onBoundsChanged() =
         kosmos.testScope.runTest {
-            underTest.onBoundsChanged(left = 5f, top = 5f, right = 5f, bottom = 5f)
-            val containerBounds by
-                collectLastValue(kosmos.keyguardInteractor.notificationContainerBounds)
+            val bounds = ShadeScrimBounds(left = 5f, top = 15f, right = 25f, bottom = 35f)
+            underTest.onScrimBoundsChanged(bounds)
             val stackBounds by
                 collectLastValue(kosmos.notificationStackAppearanceInteractor.shadeScrimBounds)
-            assertThat(containerBounds)
-                .isEqualTo(NotificationContainerBounds(top = 5f, bottom = 5f))
-            assertThat(stackBounds)
-                .isEqualTo(ShadeScrimBounds(left = 5f, top = 5f, right = 5f, bottom = 5f))
+            assertThat(stackBounds).isEqualTo(bounds)
         }
 
     @Test
-    fun onContentTopChanged_setsContentTop() {
-        underTest.onContentTopChanged(padding = 5f)
-        assertThat(kosmos.notificationStackAppearanceInteractor.stackTop.value).isEqualTo(5f)
-    }
+    fun onStackBoundsChanged() =
+        kosmos.testScope.runTest {
+            underTest.onStackBoundsChanged(top = 5f, bottom = 500f)
+            assertThat(kosmos.notificationStackAppearanceInteractor.stackTop.value).isEqualTo(5f)
+            assertThat(kosmos.notificationStackAppearanceInteractor.stackBottom.value)
+                .isEqualTo(500f)
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 509a82d..a023033 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -19,15 +19,22 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX
+import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
+import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.NotificationContainerBounds
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.BrokenWithSceneContainer
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -44,6 +51,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.mockLargeScreenHeaderHelper
 import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
@@ -61,19 +69,36 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.mock
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @SmallTest
-@RunWith(AndroidJUnit4::class)
-class SharedNotificationContainerViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+// SharedNotificationContainerViewModel is only bound when FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT is on
+@EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+class SharedNotificationContainerViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
+
+    companion object {
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf(
+                    FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX,
+                )
+                .andSceneContainer()
+        }
+    }
+
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     val aodBurnInViewModel = mock(AodBurnInViewModel::class.java)
     lateinit var movementFlow: MutableStateFlow<BurnInModel>
 
     val kosmos =
         testKosmos().apply {
-            fakeFeatureFlagsClassic.apply {
-                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-                set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
-            }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
 
     init {
@@ -81,19 +106,28 @@
     }
 
     val testScope = kosmos.testScope
-    val configurationRepository = kosmos.fakeConfigurationRepository
-    val keyguardRepository = kosmos.fakeKeyguardRepository
-    val keyguardInteractor = kosmos.keyguardInteractor
-    val keyguardRootViewModel = kosmos.keyguardRootViewModel
-    val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
-    val shadeRepository = kosmos.shadeRepository
-    val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor
-    val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper
+    val configurationRepository
+        get() = kosmos.fakeConfigurationRepository
+    val keyguardRepository
+        get() = kosmos.fakeKeyguardRepository
+    val keyguardInteractor
+        get() = kosmos.keyguardInteractor
+    val keyguardRootViewModel
+        get() = kosmos.keyguardRootViewModel
+    val keyguardTransitionRepository
+        get() = kosmos.fakeKeyguardTransitionRepository
+    val shadeRepository
+        get() = kosmos.shadeRepository
+    val sharedNotificationContainerInteractor
+        get() = kosmos.sharedNotificationContainerInteractor
+    val largeScreenHeaderHelper
+        get() = kosmos.mockLargeScreenHeaderHelper
 
     lateinit var underTest: SharedNotificationContainerViewModel
 
     @Before
     fun setUp() {
+        assertThat(SceneContainerFlag.isEnabled).isEqualTo(SceneContainerFlag.isEnabled)
         overrideResource(R.bool.config_use_split_notification_shade, false)
         movementFlow = MutableStateFlow(BurnInModel())
         whenever(aodBurnInViewModel.movement(any())).thenReturn(movementFlow)
@@ -127,38 +161,38 @@
         }
 
     @Test
+    @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
     fun validatePaddingTopInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
         testScope.runTest {
-            mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
             whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
             overrideResource(R.bool.config_use_split_notification_shade, true)
             overrideResource(R.bool.config_use_large_screen_shade_header, true)
             overrideResource(R.dimen.large_screen_shade_header_height, 10)
             overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
 
-            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+            val paddingTop by collectLastValue(underTest.paddingTopDimen)
 
             configurationRepository.onAnyConfigurationChange()
 
             // Should directly use the header height (flagged off value)
-            assertThat(dimens!!.paddingTop).isEqualTo(10)
+            assertThat(paddingTop).isEqualTo(10)
         }
 
     @Test
+    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
     fun validatePaddingTopInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
         testScope.runTest {
-            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
             whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
             overrideResource(R.bool.config_use_split_notification_shade, true)
             overrideResource(R.bool.config_use_large_screen_shade_header, true)
             overrideResource(R.dimen.large_screen_shade_header_height, 10)
             overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
 
-            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+            val paddingTop by collectLastValue(underTest.paddingTopDimen)
             configurationRepository.onAnyConfigurationChange()
 
             // Should directly use the header height (flagged on value)
-            assertThat(dimens!!.paddingTop).isEqualTo(5)
+            assertThat(paddingTop).isEqualTo(5)
         }
 
     @Test
@@ -168,11 +202,11 @@
             overrideResource(R.dimen.large_screen_shade_header_height, 10)
             overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
 
-            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+            val paddingTop by collectLastValue(underTest.paddingTopDimen)
 
             configurationRepository.onAnyConfigurationChange()
 
-            assertThat(dimens!!.paddingTop).isEqualTo(0)
+            assertThat(paddingTop).isEqualTo(0)
         }
 
     @Test
@@ -200,9 +234,9 @@
         }
 
     @Test
+    @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, FLAG_SCENE_CONTAINER)
     fun validateMarginTopWithLargeScreenHeader_refactorFlagOff_usesResource() =
         testScope.runTest {
-            mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
             val headerResourceHeight = 50
             val headerHelperHeight = 100
             whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
@@ -219,9 +253,30 @@
         }
 
     @Test
+    @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
+    @EnableSceneContainer
+    fun validateMarginTopWithLargeScreenHeader_refactorFlagOff_sceneContainerFlagOn_stillZero() =
+        testScope.runTest {
+            val headerResourceHeight = 50
+            val headerHelperHeight = 100
+            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
+                .thenReturn(headerHelperHeight)
+            overrideResource(R.bool.config_use_large_screen_shade_header, true)
+            overrideResource(R.dimen.large_screen_shade_header_height, headerResourceHeight)
+            overrideResource(R.dimen.notification_panel_margin_top, 0)
+
+            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+
+            configurationRepository.onAnyConfigurationChange()
+
+            assertThat(dimens!!.marginTop).isEqualTo(0)
+        }
+
+    @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
+    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
     fun validateMarginTopWithLargeScreenHeader_refactorFlagOn_usesHelper() =
         testScope.runTest {
-            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
             val headerResourceHeight = 50
             val headerHelperHeight = 100
             whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
@@ -238,6 +293,27 @@
         }
 
     @Test
+    @EnableSceneContainer
+    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
+    fun validateMarginTopWithLargeScreenHeader_sceneContainerFlagOn_stillZero() =
+        testScope.runTest {
+            val headerResourceHeight = 50
+            val headerHelperHeight = 100
+            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
+                .thenReturn(headerHelperHeight)
+            overrideResource(R.bool.config_use_large_screen_shade_header, true)
+            overrideResource(R.dimen.large_screen_shade_header_height, headerResourceHeight)
+            overrideResource(R.dimen.notification_panel_margin_top, 0)
+
+            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+
+            configurationRepository.onAnyConfigurationChange()
+
+            assertThat(dimens!!.marginTop).isEqualTo(0)
+        }
+
+    @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun glanceableHubAlpha_lockscreenToHub() =
         testScope.runTest {
             val alpha by collectLastValue(underTest.glanceableHubAlpha)
@@ -387,6 +463,7 @@
         }
 
     @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun isOnLockscreenWithoutShade() =
         testScope.runTest {
             val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade)
@@ -423,6 +500,7 @@
         }
 
     @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun isOnGlanceableHubWithoutShade() =
         testScope.runTest {
             val isOnGlanceableHubWithoutShade by
@@ -459,6 +537,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun boundsOnLockscreenNotInSplitShade() =
         testScope.runTest {
             val bounds by collectLastValue(underTest.bounds)
@@ -479,9 +558,9 @@
         }
 
     @Test
+    @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, FLAG_SCENE_CONTAINER)
     fun boundsOnLockscreenInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
         testScope.runTest {
-            mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
             val bounds by collectLastValue(underTest.bounds)
 
             // When in split shade
@@ -503,13 +582,20 @@
             runCurrent()
 
             // Top should be equal to bounds (1) - padding adjustment (10)
-            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = -9f, bottom = 2f))
+            assertThat(bounds)
+                .isEqualTo(
+                    NotificationContainerBounds(
+                        top = -9f,
+                        bottom = 2f,
+                    )
+                )
         }
 
     @Test
+    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun boundsOnLockscreenInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
         testScope.runTest {
-            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
             val bounds by collectLastValue(underTest.bounds)
 
             // When in split shade
@@ -535,6 +621,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun boundsOnShade() =
         testScope.runTest {
             val bounds by collectLastValue(underTest.bounds)
@@ -550,6 +637,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun boundsOnQS() =
         testScope.runTest {
             val bounds by collectLastValue(underTest.bounds)
@@ -594,6 +682,7 @@
         }
 
     @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun maxNotificationsOnLockscreen_DoesNotUpdateWhenUserInteracting() =
         testScope.runTest {
             var notificationCount = 10
@@ -630,6 +719,7 @@
         }
 
     @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun maxNotificationsOnShade() =
         testScope.runTest {
             val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> 10 }
@@ -649,6 +739,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun translationYUpdatesOnKeyguardForBurnIn() =
         testScope.runTest {
             val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -661,6 +752,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun translationYUpdatesOnKeyguard() =
         testScope.runTest {
             val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -681,6 +773,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun translationYDoesNotUpdateWhenShadeIsExpanded() =
         testScope.runTest {
             val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -701,6 +794,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_SCENE_CONTAINER)
     fun updateBounds_fromKeyguardRoot() =
         testScope.runTest {
             val bounds by collectLastValue(underTest.bounds)
@@ -712,6 +806,7 @@
         }
 
     @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun alphaOnFullQsExpansion() =
         testScope.runTest {
             val viewState = ViewStateAccessor()
@@ -819,6 +914,7 @@
         }
 
     @Test
+    @BrokenWithSceneContainer(bugId = 333132830)
     fun shadeCollapseFadeIn() =
         testScope.runTest {
             val fadeIn by collectValues(underTest.shadeCollapseFadeIn)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
index c8062fb..1501d9c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
@@ -16,57 +16,20 @@
 
 package com.android.systemui.statusbar.phone
 
-import android.app.ActivityOptions
 import android.app.PendingIntent
 import android.content.Intent
-import android.os.Bundle
-import android.os.RemoteException
-import android.os.UserHandle
-import android.view.View
-import android.widget.FrameLayout
-import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.ActivityIntentHelper
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.ActivityTransitionAnimator
-import com.android.systemui.animation.LaunchableView
-import com.android.systemui.assist.AssistManager
-import com.android.systemui.keyguard.KeyguardViewMediator
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.shade.ShadeController
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.data.repository.ShadeAnimationRepository
-import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
-import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.NotificationLockscreenUserManager
-import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.statusbar.window.StatusBarWindowController
 import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.nullable
-import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
-import java.util.Optional
 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.anyBoolean
 import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
@@ -74,177 +37,21 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class ActivityStarterImplTest : SysuiTestCase() {
-    @Mock private lateinit var centralSurfaces: CentralSurfaces
-    @Mock private lateinit var assistManager: AssistManager
-    @Mock private lateinit var dozeServiceHost: DozeServiceHost
-    @Mock private lateinit var biometricUnlockController: BiometricUnlockController
-    @Mock private lateinit var keyguardViewMediator: KeyguardViewMediator
-    @Mock private lateinit var shadeController: ShadeController
-    @Mock private lateinit var commandQueue: CommandQueue
-    @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
-    @Mock private lateinit var mActivityTransitionAnimator: ActivityTransitionAnimator
-    @Mock private lateinit var lockScreenUserManager: NotificationLockscreenUserManager
-    @Mock private lateinit var statusBarWindowController: StatusBarWindowController
-    @Mock private lateinit var notifShadeWindowController: NotificationShadeWindowController
-    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
-    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var legacyActivityStarterInternal: LegacyActivityStarterInternalImpl
+    @Mock private lateinit var activityStarterInternal: ActivityStarterInternalImpl
     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
-    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
-    @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
-    @Mock private lateinit var userTracker: UserTracker
-    @Mock private lateinit var activityIntentHelper: ActivityIntentHelper
     private lateinit var underTest: ActivityStarterImpl
     private val mainExecutor = FakeExecutor(FakeSystemClock())
-    private val shadeAnimationInteractor =
-        ShadeAnimationInteractorLegacyImpl(ShadeAnimationRepository(), FakeShadeRepository())
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         underTest =
             ActivityStarterImpl(
-                Lazy { Optional.of(centralSurfaces) },
-                Lazy { assistManager },
-                Lazy { dozeServiceHost },
-                Lazy { biometricUnlockController },
-                Lazy { keyguardViewMediator },
-                Lazy { shadeController },
-                commandQueue,
-                shadeAnimationInteractor,
-                Lazy { statusBarKeyguardViewManager },
-                Lazy { notifShadeWindowController },
-                mActivityTransitionAnimator,
-                context,
-                DISPLAY_ID,
-                lockScreenUserManager,
-                statusBarWindowController,
-                wakefulnessLifecycle,
-                keyguardStateController,
-                statusBarStateController,
-                keyguardUpdateMonitor,
-                deviceProvisionedController,
-                userTracker,
-                activityIntentHelper,
-                mainExecutor,
+                statusBarStateController = statusBarStateController,
+                mainExecutor = mainExecutor,
+                legacyActivityStarter = { legacyActivityStarterInternal },
             )
-        whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER)
-    }
-
-    @Test
-    fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() {
-        val pendingIntent = mock(PendingIntent::class.java)
-        whenever(pendingIntent.isActivity).thenReturn(true)
-        whenever(keyguardStateController.isShowing).thenReturn(true)
-        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
-
-        underTest.startPendingIntentDismissingKeyguard(pendingIntent)
-        mainExecutor.runAllReady()
-
-        verify(statusBarKeyguardViewManager)
-            .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null))
-    }
-
-    @Test
-    fun startPendingIntentMaybeDismissingKeyguard_keyguardShowing_showOverLs_launchAnimator() {
-        val pendingIntent = mock(PendingIntent::class.java)
-        val parent = FrameLayout(context)
-        val view =
-            object : View(context), LaunchableView {
-                override fun setShouldBlockVisibilityChanges(block: Boolean) {}
-            }
-        parent.addView(view)
-        val controller = ActivityTransitionAnimator.Controller.fromView(view)
-        whenever(pendingIntent.isActivity).thenReturn(true)
-        whenever(keyguardStateController.isShowing).thenReturn(true)
-        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
-        whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt()))
-            .thenReturn(true)
-
-        underTest.startPendingIntentMaybeDismissingKeyguard(
-            intent = pendingIntent,
-            animationController = controller,
-            intentSentUiThreadCallback = null,
-        )
-        mainExecutor.runAllReady()
-
-        verify(mActivityTransitionAnimator)
-            .startPendingIntentWithAnimation(
-                nullable(),
-                eq(true),
-                nullable(),
-                eq(true),
-                any(),
-            )
-    }
-
-    fun startPendingIntentDismissingKeyguard_fillInIntentAndExtraOptions_sendAndReturnResult() {
-        val pendingIntent = mock(PendingIntent::class.java)
-        val fillInIntent = mock(Intent::class.java)
-        val parent = FrameLayout(context)
-        val view =
-            object : View(context), LaunchableView {
-                override fun setShouldBlockVisibilityChanges(block: Boolean) {}
-            }
-        parent.addView(view)
-        val controller = ActivityTransitionAnimator.Controller.fromView(view)
-        whenever(pendingIntent.isActivity).thenReturn(true)
-        whenever(keyguardStateController.isShowing).thenReturn(true)
-        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
-        whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt()))
-            .thenReturn(false)
-
-        // extra activity options to set on pending intent
-        val activityOptions = mock(ActivityOptions::class.java)
-        activityOptions.splashScreenStyle = SPLASH_SCREEN_STYLE_SOLID_COLOR
-        activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission = false
-        val bundleCaptor = argumentCaptor<Bundle>()
-
-        underTest.startPendingIntentMaybeDismissingKeyguard(
-            intent = pendingIntent,
-            animationController = controller,
-            intentSentUiThreadCallback = null,
-            fillInIntent = fillInIntent,
-            extraOptions = activityOptions.toBundle(),
-        )
-        mainExecutor.runAllReady()
-
-        // Fill-in intent is passed and options contain extra values specified
-        verify(pendingIntent)
-            .sendAndReturnResult(
-                eq(context),
-                eq(0),
-                eq(fillInIntent),
-                nullable(),
-                nullable(),
-                nullable(),
-                bundleCaptor.capture()
-            )
-        val options = ActivityOptions.fromBundle(bundleCaptor.value)
-        assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse()
-        assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR)
-    }
-
-    @Test
-    fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() {
-        val pendingIntent = mock(PendingIntent::class.java)
-        val associatedView = mock(ExpandableNotificationRow::class.java)
-
-        underTest.startPendingIntentDismissingKeyguard(
-            intent = pendingIntent,
-            intentSentUiThreadCallback = null,
-            associatedView = associatedView,
-        )
-
-        verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView)
-    }
-
-    @Test
-    fun startActivity_noUserHandleProvided_getUserHandle() {
-        val intent = mock(Intent::class.java)
-
-        underTest.startActivity(intent, false)
-
-        verify(userTracker).userHandle
     }
 
     @Test
@@ -258,115 +65,9 @@
 
     @Test
     fun postStartActivityDismissingKeyguard_intent_postsOnMain() {
-        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
-        val intent = mock(Intent::class.java)
-
-        underTest.postStartActivityDismissingKeyguard(intent, 0)
+        underTest.postStartActivityDismissingKeyguard(mock(Intent::class.java), 0)
 
         assertThat(mainExecutor.numPending()).isEqualTo(1)
-        mainExecutor.runAllReady()
-
-        verify(deviceProvisionedController).isDeviceProvisioned
-        verify(shadeController).collapseShadeForActivityStart()
-    }
-
-    @Test
-    fun postStartActivityDismissingKeyguard_intent_notDeviceProvisioned_doesNotProceed() {
-        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(false)
-        val intent = mock(Intent::class.java)
-
-        underTest.postStartActivityDismissingKeyguard(intent, 0)
-        mainExecutor.runAllReady()
-
-        verify(deviceProvisionedController).isDeviceProvisioned
-        verify(shadeController, never()).collapseShadeForActivityStart()
-    }
-
-    @Test
-    fun dismissKeyguardThenExecute_startWakeAndUnlock() {
-        whenever(wakefulnessLifecycle.wakefulness)
-            .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP)
-        whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true)
-        whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
-        whenever(dozeServiceHost.isPulsing).thenReturn(true)
-
-        underTest.dismissKeyguardThenExecute({ true }, {}, false)
-
-        verify(biometricUnlockController)
-            .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
-    }
-
-    @Test
-    fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() {
-        val customMessage = "Enter your pin."
-        whenever(keyguardStateController.isShowing).thenReturn(true)
-
-        underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage)
-
-        verify(statusBarKeyguardViewManager)
-            .dismissWithAction(
-                any(OnDismissAction::class.java),
-                any(Runnable::class.java),
-                eq(false),
-                eq(customMessage)
-            )
-    }
-
-    @Test
-    fun dismissKeyguardThenExecute_awakeDreams() {
-        val customMessage = "Enter your pin."
-        var dismissActionExecuted = false
-        whenever(keyguardStateController.isShowing).thenReturn(false)
-        whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true)
-
-        underTest.dismissKeyguardThenExecute(
-            {
-                dismissActionExecuted = true
-                true
-            },
-            {},
-            false,
-            customMessage
-        )
-
-        verify(centralSurfaces).awakenDreams()
-        assertThat(dismissActionExecuted).isTrue()
-    }
-
-    @Test
-    @Throws(RemoteException::class)
-    fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() {
-        whenever(keyguardStateController.isShowing).thenReturn(false)
-        whenever(keyguardStateController.isOccluded).thenReturn(false)
-        whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true)
-
-        underTest.executeRunnableDismissingKeyguard(
-            runnable = {},
-            cancelAction = null,
-            dismissShade = false,
-            afterKeyguardGone = false,
-            deferred = false
-        )
-
-        verify(centralSurfaces, times(1)).awakenDreams()
-    }
-
-    @Test
-    @Throws(RemoteException::class)
-    fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() {
-        whenever(keyguardStateController.isShowing).thenReturn(false)
-        whenever(keyguardStateController.isOccluded).thenReturn(false)
-        whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false)
-
-        underTest.executeRunnableDismissingKeyguard(
-            runnable = {},
-            cancelAction = null,
-            dismissShade = false,
-            afterKeyguardGone = false,
-            deferred = false
-        )
-
-        verify(centralSurfaces, never()).awakenDreams()
     }
 
     @Test
@@ -377,8 +78,4 @@
         mainExecutor.runAllReady()
         verify(statusBarStateController).setLeaveOpenOnKeyguardHide(true)
     }
-
-    private companion object {
-        private const val DISPLAY_ID = 0
-    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostCoroutinesTest.kt
new file mode 100644
index 0000000..1cd12f0
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostCoroutinesTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.phone
+
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.doze.DozeHost
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.data.repository.sceneContainerRepository
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidJUnit4::class)
+class DozeServiceHostCoroutinesTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private val sceneContainerRepository = kosmos.sceneContainerRepository
+    private val keyguardInteractor = kosmos.keyguardInteractor
+
+    val underTest =
+        kosmos.dozeServiceHost.apply {
+            initialize(
+                /* centralSurfaces = */ mock(),
+                /* statusBarKeyguardViewManager = */ mock(),
+                /* notificationShadeWindowViewController = */ mock(),
+                /* ambientIndicationContainer = */ mock(),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun startStopDozing() =
+        testScope.runTest {
+            val isDozing by collectLastValue(keyguardInteractor.isDozing)
+
+            // GIVEN a callback is set
+            val callback: DozeHost.Callback = mock()
+            underTest.addCallback(callback)
+            // AND we are on the lock screen
+            sceneContainerRepository.changeScene(Scenes.Lockscreen)
+            // AND dozing is not requested yet
+            assertThat(underTest.dozingRequested).isFalse()
+
+            // WHEN dozing started
+            underTest.startDozing()
+            runCurrent()
+
+            // THEN isDozing is set to true
+            assertThat(isDozing).isTrue()
+            assertThat(underTest.dozingRequested).isTrue()
+            verify(callback).onDozingChanged(true)
+
+            // WHEN dozing stopped
+            underTest.stopDozing()
+            runCurrent()
+
+            // THEN isDozing is set to false
+            assertThat(isDozing).isFalse()
+            assertThat(underTest.dozingRequested).isFalse()
+            verify(callback).onDozingChanged(false)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index 7e5205b..2114489 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -41,7 +41,7 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
-import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.DisableSceneContainer;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
@@ -98,13 +98,11 @@
     @Mock private DozeHost.Callback mCallback;
     @Mock private DozeInteractor mDozeInteractor;
 
-    private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
-
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mDozeServiceHost = new DozeServiceHost(mDozeLog, mPowerManager, mWakefullnessLifecycle,
-                mStatusBarStateController, mDeviceProvisionedController, mFeatureFlags,
+                mStatusBarStateController, mDeviceProvisionedController,
                 mHeadsUpManager, mBatteryController, mScrimController,
                 () -> mBiometricUnlockController, () -> mAssistManager, mDozeScrimController,
                 mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController,
@@ -119,6 +117,7 @@
     }
 
     @Test
+    @DisableSceneContainer
     public void testStartStopDozing() {
         mDozeServiceHost.addCallback(mCallback);
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
new file mode 100644
index 0000000..b443489
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.app.ActivityOptions
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.Bundle
+import android.os.RemoteException
+import android.os.UserHandle
+import android.view.View
+import android.widget.FrameLayout
+import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.LaunchableView
+import com.android.systemui.assist.AssistManager
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.data.repository.ShadeAnimationRepository
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import 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.anyBoolean
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LegacyActivityStarterInternalImplTest : SysuiTestCase() {
+    @Mock private lateinit var centralSurfaces: CentralSurfaces
+    @Mock private lateinit var assistManager: AssistManager
+    @Mock private lateinit var dozeServiceHost: DozeServiceHost
+    @Mock private lateinit var biometricUnlockController: BiometricUnlockController
+    @Mock private lateinit var keyguardViewMediator: KeyguardViewMediator
+    @Mock private lateinit var shadeController: ShadeController
+    @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+    @Mock private lateinit var activityTransitionAnimator: ActivityTransitionAnimator
+    @Mock private lateinit var lockScreenUserManager: NotificationLockscreenUserManager
+    @Mock private lateinit var statusBarWindowController: StatusBarWindowController
+    @Mock private lateinit var notifShadeWindowController: NotificationShadeWindowController
+    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var activityIntentHelper: ActivityIntentHelper
+    private lateinit var underTest: LegacyActivityStarterInternalImpl
+    private val mainExecutor = FakeExecutor(FakeSystemClock())
+    private val shadeAnimationInteractor =
+        ShadeAnimationInteractorLegacyImpl(ShadeAnimationRepository(), FakeShadeRepository())
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        underTest =
+            LegacyActivityStarterInternalImpl(
+                centralSurfacesOptLazy = { Optional.of(centralSurfaces) },
+                assistManagerLazy = { assistManager },
+                dozeServiceHostLazy = { dozeServiceHost },
+                biometricUnlockControllerLazy = { biometricUnlockController },
+                keyguardViewMediatorLazy = { keyguardViewMediator },
+                shadeControllerLazy = { shadeController },
+                commandQueue = commandQueue,
+                shadeAnimationInteractor = shadeAnimationInteractor,
+                statusBarKeyguardViewManagerLazy = { statusBarKeyguardViewManager },
+                notifShadeWindowControllerLazy = { notifShadeWindowController },
+                activityTransitionAnimator = activityTransitionAnimator,
+                context = context,
+                displayId = DISPLAY_ID,
+                lockScreenUserManager = lockScreenUserManager,
+                statusBarWindowController = statusBarWindowController,
+                wakefulnessLifecycle = wakefulnessLifecycle,
+                keyguardStateController = keyguardStateController,
+                statusBarStateController = statusBarStateController,
+                keyguardUpdateMonitor = keyguardUpdateMonitor,
+                deviceProvisionedController = deviceProvisionedController,
+                userTracker = userTracker,
+                activityIntentHelper = activityIntentHelper,
+                mainExecutor = mainExecutor,
+            )
+        whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER)
+    }
+
+    @Test
+    fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() {
+        val pendingIntent = mock(PendingIntent::class.java)
+        whenever(pendingIntent.isActivity).thenReturn(true)
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+
+        underTest.startPendingIntentDismissingKeyguard(pendingIntent)
+        mainExecutor.runAllReady()
+
+        verify(statusBarKeyguardViewManager)
+            .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null))
+    }
+
+    @Test
+    fun startPendingIntentMaybeDismissingKeyguard_keyguardShowing_showOverLs_launchAnimator() {
+        val pendingIntent = mock(PendingIntent::class.java)
+        val parent = FrameLayout(context)
+        val view =
+            object : View(context), LaunchableView {
+                override fun setShouldBlockVisibilityChanges(block: Boolean) {}
+            }
+        parent.addView(view)
+        val controller = ActivityTransitionAnimator.Controller.fromView(view)
+        whenever(pendingIntent.isActivity).thenReturn(true)
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+        whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt()))
+            .thenReturn(true)
+
+        startPendingIntentMaybeDismissingKeyguard(
+            intent = pendingIntent,
+            animationController = controller,
+            intentSentUiThreadCallback = null,
+        )
+        mainExecutor.runAllReady()
+
+        verify(activityTransitionAnimator)
+            .startPendingIntentWithAnimation(
+                nullable(),
+                eq(true),
+                nullable(),
+                eq(true),
+                any(),
+            )
+    }
+
+    fun startPendingIntentDismissingKeyguard_fillInIntentAndExtraOptions_sendAndReturnResult() {
+        val pendingIntent = mock(PendingIntent::class.java)
+        val fillInIntent = mock(Intent::class.java)
+        val parent = FrameLayout(context)
+        val view =
+            object : View(context), LaunchableView {
+                override fun setShouldBlockVisibilityChanges(block: Boolean) {}
+            }
+        parent.addView(view)
+        val controller = ActivityTransitionAnimator.Controller.fromView(view)
+        whenever(pendingIntent.isActivity).thenReturn(true)
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+        whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+        whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt()))
+            .thenReturn(false)
+
+        // extra activity options to set on pending intent
+        val activityOptions = mock(ActivityOptions::class.java)
+        activityOptions.splashScreenStyle = SPLASH_SCREEN_STYLE_SOLID_COLOR
+        activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission = false
+        val bundleCaptor = argumentCaptor<Bundle>()
+
+        startPendingIntentMaybeDismissingKeyguard(
+            intent = pendingIntent,
+            animationController = controller,
+            intentSentUiThreadCallback = null,
+            fillInIntent = fillInIntent,
+            extraOptions = activityOptions.toBundle(),
+        )
+        mainExecutor.runAllReady()
+
+        // Fill-in intent is passed and options contain extra values specified
+        verify(pendingIntent)
+            .sendAndReturnResult(
+                eq(context),
+                eq(0),
+                eq(fillInIntent),
+                nullable(),
+                nullable(),
+                nullable(),
+                bundleCaptor.capture()
+            )
+        val options = ActivityOptions.fromBundle(bundleCaptor.value)
+        assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse()
+        assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR)
+    }
+
+    @Test
+    fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() {
+        val pendingIntent = mock(PendingIntent::class.java)
+        val associatedView = mock(ExpandableNotificationRow::class.java)
+
+        underTest.startPendingIntentDismissingKeyguard(
+            intent = pendingIntent,
+            intentSentUiThreadCallback = null,
+            associatedView = associatedView,
+        )
+
+        verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView)
+    }
+
+    @Test
+    fun startActivity_noUserHandleProvided_getUserHandle() {
+        val intent = mock(Intent::class.java)
+
+        underTest.startActivity(intent, false, null, false, null)
+
+        verify(userTracker).userHandle
+    }
+
+    @Test
+    fun dismissKeyguardThenExecute_startWakeAndUnlock() {
+        whenever(wakefulnessLifecycle.wakefulness)
+            .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP)
+        whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true)
+        whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+        whenever(dozeServiceHost.isPulsing).thenReturn(true)
+
+        underTest.dismissKeyguardThenExecute({ true }, {}, false)
+
+        verify(biometricUnlockController)
+            .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
+    }
+
+    @Test
+    fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() {
+        val customMessage = "Enter your pin."
+        whenever(keyguardStateController.isShowing).thenReturn(true)
+
+        underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage)
+
+        verify(statusBarKeyguardViewManager)
+            .dismissWithAction(
+                any(OnDismissAction::class.java),
+                any(Runnable::class.java),
+                eq(false),
+                eq(customMessage)
+            )
+    }
+
+    @Test
+    fun dismissKeyguardThenExecute_awakeDreams() {
+        val customMessage = "Enter your pin."
+        var dismissActionExecuted = false
+        whenever(keyguardStateController.isShowing).thenReturn(false)
+        whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true)
+
+        underTest.dismissKeyguardThenExecute(
+            {
+                dismissActionExecuted = true
+                true
+            },
+            {},
+            false,
+            customMessage
+        )
+
+        verify(centralSurfaces).awakenDreams()
+        assertThat(dismissActionExecuted).isTrue()
+    }
+
+    @Test
+    @Throws(RemoteException::class)
+    fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() {
+        whenever(keyguardStateController.isShowing).thenReturn(false)
+        whenever(keyguardStateController.isOccluded).thenReturn(false)
+        whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true)
+
+        underTest.executeRunnableDismissingKeyguard(
+            runnable = {},
+            cancelAction = null,
+            dismissShade = false,
+            afterKeyguardGone = false,
+            deferred = false
+        )
+
+        verify(centralSurfaces, times(1)).awakenDreams()
+    }
+
+    @Test
+    @Throws(RemoteException::class)
+    fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() {
+        whenever(keyguardStateController.isShowing).thenReturn(false)
+        whenever(keyguardStateController.isOccluded).thenReturn(false)
+        whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false)
+
+        underTest.executeRunnableDismissingKeyguard(
+            runnable = {},
+            cancelAction = null,
+            dismissShade = false,
+            afterKeyguardGone = false,
+            deferred = false
+        )
+
+        verify(centralSurfaces, never()).awakenDreams()
+    }
+
+    private fun startPendingIntentMaybeDismissingKeyguard(
+        intent: PendingIntent,
+        intentSentUiThreadCallback: Runnable?,
+        animationController: ActivityTransitionAnimator.Controller?,
+        fillInIntent: Intent? = null,
+        extraOptions: Bundle? = null,
+    ) {
+        underTest.startPendingIntentDismissingKeyguard(
+            intent = intent,
+            intentSentUiThreadCallback = intentSentUiThreadCallback,
+            animationController = animationController,
+            showOverLockscreen = true,
+            fillInIntent = fillInIntent,
+            extraOptions = extraOptions,
+        )
+    }
+
+    private companion object {
+        private const val DISPLAY_ID = 0
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
deleted file mode 100644
index 638925d..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
+++ /dev/null
@@ -1,30 +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.airplane.data.repository
-
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-class FakeAirplaneModeRepository : AirplaneModeRepository {
-
-    private val _isAirplaneMode = MutableStateFlow(false)
-    override val isAirplaneMode: StateFlow<Boolean> = _isAirplaneMode
-
-    override suspend fun setIsAirplaneMode(isEnabled: Boolean) {
-        _isAirplaneMode.value = isEnabled
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
deleted file mode 100644
index 28d632d..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
+++ /dev/null
@@ -1,80 +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.shared.data.repository
-
-import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
-import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-/** Fake implementation of [ConnectivityRepository] exposing set methods for all the flows. */
-class FakeConnectivityRepository : ConnectivityRepository {
-    private val _forceHiddenIcons: MutableStateFlow<Set<ConnectivitySlot>> =
-        MutableStateFlow(emptySet())
-    override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = _forceHiddenIcons
-
-    override val defaultConnections: MutableStateFlow<DefaultConnectionModel> =
-        MutableStateFlow(DefaultConnectionModel())
-
-    override val vcnSubId: MutableStateFlow<Int?> = MutableStateFlow(null)
-
-    fun setForceHiddenIcons(hiddenIcons: Set<ConnectivitySlot>) {
-        _forceHiddenIcons.value = hiddenIcons
-    }
-
-    /**
-     * Convenience for setting mobile data connected, disconnected, or validated. Defaults to
-     * setting mobile connected && validated, since the default state is disconnected && not
-     * validated
-     */
-    @JvmOverloads
-    fun setMobileConnected(
-        default: Boolean = true,
-        validated: Boolean = true,
-    ) {
-        defaultConnections.value =
-            DefaultConnectionModel(
-                mobile = DefaultConnectionModel.Mobile(default),
-                isValidated = validated,
-            )
-    }
-
-    /** Similar convenience method for ethernet */
-    @JvmOverloads
-    fun setEthernetConnected(
-        default: Boolean = true,
-        validated: Boolean = true,
-    ) {
-        defaultConnections.value =
-            DefaultConnectionModel(
-                ethernet = DefaultConnectionModel.Ethernet(default),
-                isValidated = validated,
-            )
-    }
-
-    @JvmOverloads
-    fun setWifiConnected(
-        default: Boolean = true,
-        validated: Boolean = true,
-    ) {
-        defaultConnections.value =
-            DefaultConnectionModel(
-                wifi = DefaultConnectionModel.Wifi(default),
-                isValidated = validated,
-            )
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
index 106b548..97c8d5f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.statusbar.pipeline.wifi.data.repository
 
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryHelper.ACTIVITY_DEFAULT
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.ACTIVITY_DEFAULT
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
 import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index d06a6e2..a6fdd03 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -16,24 +16,28 @@
 
 package com.android.systemui.statusbar.pipeline.wifi.data.repository
 
-import android.net.ConnectivityManager
 import android.net.wifi.WifiManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl
-import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.kotlinArgumentCaptor
+import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
+import com.android.wifitrackerlib.WifiPickerTracker
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -59,14 +63,21 @@
     private lateinit var demoImpl: DemoWifiRepository
 
     @Mock private lateinit var demoModeController: DemoModeController
-    @Mock private lateinit var logger: WifiInputLogger
     @Mock private lateinit var tableLogger: TableLogBuffer
-    @Mock private lateinit var connectivityManager: ConnectivityManager
     @Mock private lateinit var wifiManager: WifiManager
     @Mock private lateinit var demoModeWifiDataSource: DemoModeWifiDataSource
+    @Mock private lateinit var wifiPickerTrackerFactory: WifiPickerTrackerFactory
+    @Mock private lateinit var wifiPickerTracker: WifiPickerTracker
+
+    private val wifiLogBuffer = LogBuffer("wifi", maxSize = 100, logcatEchoTracker = mock())
     private val demoModelFlow = MutableStateFlow<FakeWifiEventModel?>(null)
 
     private val mainExecutor = FakeExecutor(FakeSystemClock())
+    private val featureFlags =
+        FakeFeatureFlagsClassic().also {
+            it.set(Flags.INSTANT_TETHER, true)
+            it.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+        }
 
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
@@ -78,17 +89,18 @@
         // Never start in demo mode
         whenever(demoModeController.isInDemoMode).thenReturn(false)
 
+        whenever(wifiPickerTrackerFactory.create(any(), any(), any())).thenReturn(wifiPickerTracker)
+
         realImpl =
             WifiRepositoryImpl(
-                fakeBroadcastDispatcher,
-                connectivityManager,
-                FakeConnectivityRepository(),
-                logger,
-                tableLogger,
+                featureFlags,
+                testScope.backgroundScope,
                 mainExecutor,
                 testDispatcher,
-                testScope.backgroundScope,
+                wifiPickerTrackerFactory,
                 wifiManager,
+                wifiLogBuffer,
+                tableLogger,
             )
 
         whenever(demoModeWifiDataSource.wifiEvents).thenReturn(demoModelFlow)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
deleted file mode 100644
index cf20ba8..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ /dev/null
@@ -1,1323 +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.wifi.data.repository.prod
-
-import android.content.Intent
-import android.net.ConnectivityManager
-import android.net.Network
-import android.net.NetworkCapabilities
-import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
-import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
-import android.net.NetworkCapabilities.TRANSPORT_VPN
-import android.net.NetworkCapabilities.TRANSPORT_WIFI
-import android.net.TransportInfo
-import android.net.VpnTransportInfo
-import android.net.vcn.VcnTransportInfo
-import android.net.wifi.ScanResult
-import android.net.wifi.WifiInfo
-import android.net.wifi.WifiManager
-import android.net.wifi.WifiManager.TrafficStateCallback
-import android.net.wifi.WifiManager.UNKNOWN_SSID
-import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
-import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
-import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.Executor
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-/**
- * Note: Any new tests added here may also need to be added to [WifiRepositoryViaTrackerLibTest].
- */
-@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class WifiRepositoryImplTest : SysuiTestCase() {
-
-    private lateinit var underTest: WifiRepositoryImpl
-
-    @Mock private lateinit var logger: WifiInputLogger
-    @Mock private lateinit var tableLogger: TableLogBuffer
-    @Mock private lateinit var connectivityManager: ConnectivityManager
-    @Mock private lateinit var wifiManager: WifiManager
-    private lateinit var executor: Executor
-    private lateinit var connectivityRepository: ConnectivityRepository
-
-    private val dispatcher = StandardTestDispatcher()
-    private val testScope = TestScope(dispatcher)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        executor = FakeExecutor(FakeSystemClock())
-
-        connectivityRepository =
-            ConnectivityRepositoryImpl(
-                connectivityManager,
-                ConnectivitySlots(context),
-                context,
-                mock(),
-                mock(),
-                testScope.backgroundScope,
-                mock(),
-            )
-
-        underTest = createRepo()
-    }
-
-    @Test
-    fun isWifiEnabled_initiallyGetsWifiManagerValue() =
-        testScope.runTest {
-            whenever(wifiManager.isWifiEnabled).thenReturn(true)
-
-            underTest = createRepo()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiEnabled.value).isTrue()
-        }
-
-    @Test
-    fun isWifiEnabled_networkCapabilitiesChanged_valueUpdated() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(true)
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-
-            assertThat(latest).isTrue()
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(false)
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiEnabled_networkLost_valueUpdated() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(true)
-            getNetworkCallback().onLost(NETWORK)
-
-            assertThat(latest).isTrue()
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(false)
-            getNetworkCallback().onLost(NETWORK)
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiEnabled_intentsReceived_valueUpdated() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(true)
-            fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
-                context,
-                Intent(WifiManager.WIFI_STATE_CHANGED_ACTION),
-            )
-
-            assertThat(latest).isTrue()
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(false)
-            fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
-                context,
-                Intent(WifiManager.WIFI_STATE_CHANGED_ACTION),
-            )
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiEnabled_bothIntentAndNetworkUpdates_valueAlwaysUpdated() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(false)
-            fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
-                context,
-                Intent(WifiManager.WIFI_STATE_CHANGED_ACTION),
-            )
-            assertThat(latest).isFalse()
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(true)
-            getNetworkCallback().onLost(NETWORK)
-            assertThat(latest).isTrue()
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(false)
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-            assertThat(latest).isFalse()
-
-            whenever(wifiManager.isWifiEnabled).thenReturn(true)
-            fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
-                context,
-                Intent(WifiManager.WIFI_STATE_CHANGED_ACTION),
-            )
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_initiallyGetsDefault() =
-        testScope.runTest { assertThat(underTest.isWifiDefault.value).isFalse() }
-
-    @Test
-    fun isWifiDefault_wifiNetwork_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val wifiInfo = mock<WifiInfo>().apply { whenever(this.ssid).thenReturn(SSID) }
-
-            getDefaultNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-
-            assertThat(latest).isTrue()
-        }
-
-    /** Regression test for b/266628069. */
-    @Test
-    fun isWifiDefault_transportInfoIsNotWifi_andNoWifiTransport_false() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val transportInfo =
-                VpnTransportInfo(
-                    /* type= */ 0,
-                    /* sessionId= */ "sessionId",
-                )
-            val networkCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true)
-                    whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
-                    whenever(it.transportInfo).thenReturn(transportInfo)
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, networkCapabilities)
-
-            assertThat(latest).isFalse()
-        }
-
-    /** Regression test for b/266628069. */
-    @Test
-    fun isWifiDefault_transportInfoIsNotWifi_butHasWifiTransport_true() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val transportInfo =
-                VpnTransportInfo(
-                    /* type= */ 0,
-                    /* sessionId= */ "sessionId",
-                )
-            val networkCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true)
-                    whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
-                    whenever(it.transportInfo).thenReturn(transportInfo)
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, networkCapabilities)
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_carrierMergedViaCellular_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val carrierMergedInfo =
-                mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
-                    whenever(this.transportInfo).thenReturn(carrierMergedInfo)
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_carrierMergedViaCellular_withVcnTransport_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
-                    whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_carrierMergedViaWifi_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val carrierMergedInfo =
-                mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
-                    whenever(this.transportInfo).thenReturn(carrierMergedInfo)
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_carrierMergedViaWifi_withVcnTransport_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
-                    whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_cellularAndWifiTransports_usesCellular_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_cellularNotVcnNetwork_isFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.transportInfo).thenReturn(mock())
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiDefault_isCarrierMergedViaUnderlyingWifi_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val underlyingNetwork = mock<Network>()
-            val carrierMergedInfo =
-                mock<WifiInfo>().apply {
-                    mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
-                }
-            val underlyingWifiCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(carrierMergedInfo)
-                }
-            whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
-                .thenReturn(underlyingWifiCapabilities)
-
-            // WHEN the main capabilities have an underlying carrier merged network via WIFI
-            // transport and WifiInfo
-            val mainCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(null)
-                    whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
-
-            // THEN the wifi network is carrier merged, so wifi is default
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_isCarrierMergedViaUnderlyingCellular_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val underlyingCarrierMergedNetwork = mock<Network>()
-            val carrierMergedInfo =
-                mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
-            val underlyingCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
-                }
-            whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
-                .thenReturn(underlyingCapabilities)
-
-            // WHEN the main capabilities have an underlying carrier merged network via CELLULAR
-            // transport and VcnTransportInfo
-            val mainCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(null)
-                    whenever(it.underlyingNetworks)
-                        .thenReturn(listOf(underlyingCarrierMergedNetwork))
-                }
-
-            getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
-
-            // THEN the wifi network is carrier merged, so wifi is default
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_wifiNetworkLost_isFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            // First, add a network
-            getDefaultNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-            assertThat(latest).isTrue()
-
-            // WHEN the network is lost
-            getDefaultNetworkCallback().onLost(NETWORK)
-
-            // THEN we update to false
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun wifiNetwork_initiallyGetsDefault() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            assertThat(latest).isEqualTo(WIFI_NETWORK_DEFAULT)
-        }
-
-    @Test
-    fun wifiNetwork_primaryWifiNetworkAdded_flowHasNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-            val network = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo))
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestActive.ssid).isEqualTo(SSID)
-        }
-
-    @Test
-    fun wifiNetwork_neverHasHotspot() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-            val network = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo))
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
-        }
-
-    @Test
-    fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_isCarrierMergedViaUnderlyingWifi_flowHasCarrierMerged() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val underlyingNetwork = mock<Network>()
-            val carrierMergedInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-            val underlyingWifiCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(carrierMergedInfo)
-                }
-            whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
-                .thenReturn(underlyingWifiCapabilities)
-
-            // WHEN the main capabilities have an underlying carrier merged network via WIFI
-            // transport and WifiInfo
-            val mainCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(null)
-                    whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
-                }
-
-            getNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
-
-            // THEN the wifi network is carrier merged
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_isCarrierMergedViaUnderlyingCellular_flowHasCarrierMerged() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val underlyingCarrierMergedNetwork = mock<Network>()
-            val carrierMergedInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-            val underlyingCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
-                }
-            whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
-                .thenReturn(underlyingCapabilities)
-
-            // WHEN the main capabilities have an underlying carrier merged network via CELLULAR
-            // transport and VcnTransportInfo
-            val mainCapabilities =
-                mock<NetworkCapabilities>().also {
-                    whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(it.transportInfo).thenReturn(null)
-                    whenever(it.underlyingNetworks)
-                        .thenReturn(listOf(underlyingCarrierMergedNetwork))
-                }
-
-            getNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
-
-            // THEN the wifi network is carrier merged
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                    whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(wifiInfo),
-                )
-
-            assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java)
-        }
-
-    @Test
-    fun wifiNetwork_isCarrierMerged_getsCorrectValues() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val rssi = -57
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                    whenever(this.rssi).thenReturn(rssi)
-                    whenever(this.subscriptionId).thenReturn(567)
-                }
-
-            whenever(wifiManager.calculateSignalLevel(rssi)).thenReturn(2)
-            whenever(wifiManager.maxSignalLevel).thenReturn(5)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(wifiInfo),
-                )
-
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-            val latestCarrierMerged = latest as WifiNetworkModel.CarrierMerged
-            assertThat(latestCarrierMerged.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestCarrierMerged.subscriptionId).isEqualTo(567)
-            assertThat(latestCarrierMerged.level).isEqualTo(2)
-            // numberOfLevels = maxSignalLevel + 1
-            assertThat(latestCarrierMerged.numberOfLevels).isEqualTo(6)
-        }
-
-    @Test
-    fun wifiNetwork_notValidated_networkNotValidated() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = false)
-                )
-
-            assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse()
-        }
-
-    @Test
-    fun wifiNetwork_validated_networkValidated() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = true)
-                )
-
-            assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    whenever(this.isPrimary).thenReturn(false)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    /** Regression test for b/266628069. */
-    @Test
-    fun wifiNetwork_transportInfoIsNotWifi_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val transportInfo =
-                VpnTransportInfo(
-                    /* type= */ 0,
-                    /* sessionId= */ "sessionId",
-                )
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(transportInfo))
-
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_cellularVcnNetworkAdded_flowHasNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
-                }
-
-            getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestActive.ssid).isEqualTo(SSID)
-        }
-
-    @Test
-    fun wifiNetwork_nonPrimaryCellularVcnNetworkAdded_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    whenever(this.isPrimary).thenReturn(false)
-                }
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.transportInfo).thenReturn(VcnTransportInfo(wifiInfo))
-                }
-
-            getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_cellularNotVcnNetworkAdded_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.transportInfo).thenReturn(mock())
-                }
-
-            getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_cellularAndWifiTransports_usesCellular() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val capabilities =
-                mock<NetworkCapabilities>().apply {
-                    whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
-                    whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-                    whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
-                }
-
-            getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestActive.ssid).isEqualTo(SSID)
-        }
-
-    @Test
-    fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            // Start with the original network
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-
-            // WHEN we update to a new primary network
-            val newNetworkId = 456
-            val newNetwork =
-                mock<Network>().apply { whenever(this.getNetId()).thenReturn(newNetworkId) }
-            val newSsid = "CD"
-            val newWifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(newSsid)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(newNetwork, createWifiNetworkCapabilities(newWifiInfo))
-
-            // THEN we use the new network
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(newNetworkId)
-            assertThat(latestActive.ssid).isEqualTo(newSsid)
-        }
-
-    @Test
-    fun wifiNetwork_newNonPrimaryWifiNetwork_flowHasOldNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            // Start with the original network
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-
-            // WHEN we notify of a new but non-primary network
-            val newNetworkId = 456
-            val newNetwork =
-                mock<Network>().apply { whenever(this.getNetId()).thenReturn(newNetworkId) }
-            val newSsid = "EF"
-            val newWifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(newSsid)
-                    whenever(this.isPrimary).thenReturn(false)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(newNetwork, createWifiNetworkCapabilities(newWifiInfo))
-
-            // THEN we still use the original network
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestActive.ssid).isEqualTo(SSID)
-        }
-
-    @Test
-    fun wifiNetwork_newNetworkCapabilities_flowHasNewData() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-
-            // Start with the original network
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(wifiInfo, isValidated = true)
-                )
-
-            // WHEN we keep the same network ID but change the SSID
-            val newSsid = "CD"
-            val newWifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(newSsid)
-                    whenever(this.isPrimary).thenReturn(true)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(newWifiInfo, isValidated = false)
-                )
-
-            // THEN we've updated to the new SSID
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestActive.ssid).isEqualTo(newSsid)
-            assertThat(latestActive.isValidated).isFalse()
-        }
-
-    @Test
-    fun wifiNetwork_noCurrentNetwork_networkLost_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            // WHEN we receive #onLost without any #onCapabilitiesChanged beforehand
-            getNetworkCallback().onLost(NETWORK)
-
-            // THEN there's no crash and we still have no network
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_currentActiveNetworkLost_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-            assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID)
-
-            // WHEN we lose our current network
-            getNetworkCallback().onLost(NETWORK)
-
-            // THEN we update to no network
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    /** Possible regression test for b/278618530. */
-    @Test
-    fun wifiNetwork_currentCarrierMergedNetworkLost_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-            assertThat((latest as WifiNetworkModel.CarrierMerged).networkId).isEqualTo(NETWORK_ID)
-
-            // WHEN we lose our current network
-            getNetworkCallback().onLost(NETWORK)
-
-            // THEN we update to no network
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_unknownNetworkLost_flowHasPreviousNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-            assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID)
-
-            // WHEN we lose an unknown network
-            val unknownNetwork = mock<Network>().apply { whenever(this.getNetId()).thenReturn(543) }
-            getNetworkCallback().onLost(unknownNetwork)
-
-            // THEN we still have our previous network
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latestActive.ssid).isEqualTo(SSID)
-        }
-
-    @Test
-    fun wifiNetwork_notCurrentNetworkLost_flowHasCurrentNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-            assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID)
-
-            // WHEN we update to a new network...
-            val newNetworkId = 89
-            val newNetwork =
-                mock<Network>().apply { whenever(this.getNetId()).thenReturn(newNetworkId) }
-            getNetworkCallback()
-                .onCapabilitiesChanged(newNetwork, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-            // ...and lose the old network
-            getNetworkCallback().onLost(NETWORK)
-
-            // THEN we still have the new network
-            assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(newNetworkId)
-        }
-
-    /** Regression test for b/244173280. */
-    @Test
-    fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() =
-        testScope.runTest {
-            val latest1 by collectLastValue(underTest.wifiNetwork)
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
-
-            assertThat(latest1 is WifiNetworkModel.Active).isTrue()
-            val latest1Active = latest1 as WifiNetworkModel.Active
-            assertThat(latest1Active.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latest1Active.ssid).isEqualTo(SSID)
-
-            // WHEN we add a second subscriber after having already emitted a value
-            val latest2 by collectLastValue(underTest.wifiNetwork)
-
-            // THEN the second subscribe receives the already-emitted value
-            assertThat(latest2 is WifiNetworkModel.Active).isTrue()
-            val latest2Active = latest2 as WifiNetworkModel.Active
-            assertThat(latest2Active.networkId).isEqualTo(NETWORK_ID)
-            assertThat(latest2Active.ssid).isEqualTo(SSID)
-        }
-
-    @Test
-    fun secondaryNetworks_alwaysEmpty() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.secondaryNetworks)
-            collectLastValue(underTest.wifiNetwork)
-
-            // Even WHEN we do have non-primary wifi info
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    whenever(this.isPrimary).thenReturn(false)
-                }
-            val network = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo))
-
-            // THEN the secondary networks list is empty because this repo doesn't support it
-            assertThat(latest).isEmpty()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_inactiveNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.ssid).thenReturn(SSID)
-                    // A non-primary network is inactive
-                    whenever(this.isPrimary).thenReturn(false)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_carrierMergedNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_invalidNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.isCarrierMerged).thenReturn(true)
-                    whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(
-                    NETWORK,
-                    createWifiNetworkCapabilities(wifiInfo),
-                )
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeNetwork_nullSsid_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.ssid).thenReturn(null)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeNetwork_unknownSsid_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.ssid).thenReturn(UNKNOWN_SSID)
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeNetwork_validSsid_true() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.ssid).thenReturn("FakeSsid")
-                }
-
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeToInactive_trueToFalse() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            // Start with active
-            val wifiInfo =
-                mock<WifiInfo>().apply {
-                    whenever(this.isPrimary).thenReturn(true)
-                    whenever(this.ssid).thenReturn("FakeSsid")
-                }
-            getNetworkCallback()
-                .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue()
-
-            // WHEN the network is lost
-            getNetworkCallback().onLost(NETWORK)
-            testScope.runCurrent()
-
-            // THEN the isWifiConnected updates
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesNone_activityFlowHasNone() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_NONE)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesIn_activityFlowHasIn() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_IN)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false))
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesOut_activityFlowHasOut() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_OUT)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true))
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true))
-        }
-
-    @Test
-    fun wifiScanResults_containsSsidList() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiScanResults)
-
-            val scanResults =
-                listOf(
-                    ScanResult().also { it.SSID = "ssid 1" },
-                    ScanResult().also { it.SSID = "ssid 2" },
-                    ScanResult().also { it.SSID = "ssid 3" },
-                    ScanResult().also { it.SSID = "ssid 4" },
-                    ScanResult().also { it.SSID = "ssid 5" },
-                )
-            whenever(wifiManager.scanResults).thenReturn(scanResults)
-            getScanResultsCallback().onScanResultsAvailable()
-
-            val expected =
-                listOf(
-                    WifiScanEntry(ssid = "ssid 1"),
-                    WifiScanEntry(ssid = "ssid 2"),
-                    WifiScanEntry(ssid = "ssid 3"),
-                    WifiScanEntry(ssid = "ssid 4"),
-                    WifiScanEntry(ssid = "ssid 5"),
-                )
-
-            assertThat(latest).isEqualTo(expected)
-        }
-
-    @Test
-    fun wifiScanResults_updates() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiScanResults)
-
-            var scanResults =
-                listOf(
-                    ScanResult().also { it.SSID = "ssid 1" },
-                    ScanResult().also { it.SSID = "ssid 2" },
-                    ScanResult().also { it.SSID = "ssid 3" },
-                    ScanResult().also { it.SSID = "ssid 4" },
-                    ScanResult().also { it.SSID = "ssid 5" },
-                )
-            whenever(wifiManager.scanResults).thenReturn(scanResults)
-            getScanResultsCallback().onScanResultsAvailable()
-
-            // New scan representing no results
-            scanResults = emptyList()
-            whenever(wifiManager.scanResults).thenReturn(scanResults)
-            getScanResultsCallback().onScanResultsAvailable()
-
-            assertThat(latest).isEmpty()
-        }
-
-    private fun createRepo(): WifiRepositoryImpl {
-        return WifiRepositoryImpl(
-            fakeBroadcastDispatcher,
-            connectivityManager,
-            connectivityRepository,
-            logger,
-            tableLogger,
-            executor,
-            dispatcher,
-            testScope.backgroundScope,
-            wifiManager,
-        )
-    }
-
-    private fun getTrafficStateCallback(): TrafficStateCallback {
-        testScope.runCurrent()
-        val callbackCaptor = argumentCaptor<TrafficStateCallback>()
-        verify(wifiManager).registerTrafficStateCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.value!!
-    }
-
-    private fun getNetworkCallback(): ConnectivityManager.NetworkCallback {
-        testScope.runCurrent()
-        val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>()
-        verify(connectivityManager).registerNetworkCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.value!!
-    }
-
-    private fun getDefaultNetworkCallback(): ConnectivityManager.NetworkCallback {
-        testScope.runCurrent()
-        val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>()
-        verify(connectivityManager).registerDefaultNetworkCallback(callbackCaptor.capture())
-        return callbackCaptor.value!!
-    }
-
-    private fun getScanResultsCallback(): WifiManager.ScanResultsCallback {
-        testScope.runCurrent()
-        val callbackCaptor = argumentCaptor<WifiManager.ScanResultsCallback>()
-        verify(wifiManager).registerScanResultsCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.value!!
-    }
-
-    private fun createWifiNetworkCapabilities(
-        transportInfo: TransportInfo,
-        isValidated: Boolean = true,
-    ): NetworkCapabilities {
-        return mock<NetworkCapabilities>().also {
-            whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
-            whenever(it.transportInfo).thenReturn(transportInfo)
-            whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(isValidated)
-        }
-    }
-
-    private companion object {
-        const val NETWORK_ID = 45
-        val NETWORK = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) }
-        const val SSID = "AB"
-        val PRIMARY_WIFI_INFO: WifiInfo =
-            mock<WifiInfo>().apply {
-                whenever(this.ssid).thenReturn(SSID)
-                whenever(this.isPrimary).thenReturn(true)
-            }
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/AvalancheControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/AvalancheControllerTest.kt
index 29f286f..7420ea0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/AvalancheControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/AvalancheControllerTest.kt
@@ -248,6 +248,35 @@
     }
 
     @Test
+    fun testGetDurationMs_untrackedEntryEmptyAvalanche_useAutoDismissTime() {
+        val givenEntry = createHeadsUpEntry(id = 0)
+
+        // Nothing is showing
+        mAvalancheController.headsUpEntryShowing = null
+
+        // Nothing is next
+        mAvalancheController.clearNext()
+
+        val durationMs = mAvalancheController.getDurationMs(givenEntry, autoDismissMs = 5000)
+        Truth.assertThat(durationMs).isEqualTo(5000)
+    }
+
+    @Test
+    fun testGetDurationMs_untrackedEntryNonEmptyAvalanche_useAutoDismissTime() {
+        val givenEntry = createHeadsUpEntry(id = 0)
+
+        // Given entry not tracked
+        mAvalancheController.headsUpEntryShowing = createHeadsUpEntry(id = 1)
+
+        mAvalancheController.clearNext()
+        val nextEntry = createHeadsUpEntry(id = 2)
+        mAvalancheController.addToNext(nextEntry, runnableMock!!)
+
+        val durationMs = mAvalancheController.getDurationMs(givenEntry, autoDismissMs = 5000)
+        Truth.assertThat(durationMs).isEqualTo(5000)
+    }
+
+    @Test
     fun testGetDurationMs_lastEntry_useAutoDismissTime() {
         // Entry is showing
         val showingEntry = createHeadsUpEntry(id = 0)
@@ -261,7 +290,7 @@
     }
 
     @Test
-    fun testGetDurationMs_nextEntryLowerPriority_500() {
+    fun testGetDurationMs_nextEntryLowerPriority_5000() {
         // Entry is showing
         val showingEntry = createFsiHeadsUpEntry(id = 1)
         mAvalancheController.headsUpEntryShowing = showingEntry
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
index 7c130be..db8e14c1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
@@ -38,9 +38,9 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.Person;
+import android.platform.test.flag.junit.FlagsParameterization;
 import android.testing.TestableLooper;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.testing.UiEventLoggerFake;
@@ -62,9 +62,14 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 @SmallTest
 @TestableLooper.RunWithLooper
-@RunWith(AndroidJUnit4.class)
+@RunWith(ParameterizedAndroidJunit4.class)
 public class BaseHeadsUpManagerTest extends SysuiTestCase {
     @Rule
     public MockitoRule rule = MockitoJUnit.rule();
@@ -129,10 +134,18 @@
         }
     }
 
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getFlags() {
+        return FlagsParameterization.allCombinationsOf(NotificationThrottleHun.FLAG_NAME);
+    }
+
+    public BaseHeadsUpManagerTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
     @Override
     public void SysuiSetup() throws Exception {
         super.SysuiSetup();
-        mSetFlagsRule.disableFlags(NotificationThrottleHun.FLAG_NAME);
         mAvalancheController = new AvalancheController(dumpManager);
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java
index a8a75c0..f66e75a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java
@@ -26,9 +26,9 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.platform.test.flag.junit.FlagsParameterization;
 import android.testing.TestableLooper;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.UiEventLogger;
@@ -58,10 +58,14 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.List;
+
 import kotlinx.coroutines.flow.StateFlowKt;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(ParameterizedAndroidJunit4.class)
 @TestableLooper.RunWithLooper
 public class HeadsUpManagerPhoneTest extends BaseHeadsUpManagerTest {
     @Rule public MockitoRule rule = MockitoJUnit.rule();
@@ -141,12 +145,17 @@
         );
     }
 
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getFlags() {
+        return FlagsParameterization.allCombinationsOf(NotificationThrottleHun.FLAG_NAME);
+    }
+
+    public HeadsUpManagerPhoneTest(FlagsParameterization flags) {
+        super(flags);
+    }
+
     @Before
     public void setUp() {
-        // TODO(b/315362456) create separate test with the flag disabled
-        //  then modify this file to test with the flag enabled
-        mSetFlagsRule.disableFlags(NotificationThrottleHun.FLAG_NAME);
-
         when(mShadeInteractor.isAnyExpanded()).thenReturn(StateFlowKt.MutableStateFlow(false));
         final AccessibilityManagerWrapper accessibilityMgr =
                 mDependency.injectMockDependency(AccessibilityManagerWrapper.class);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java
index 3c9dc63..69207ba 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java
@@ -89,7 +89,7 @@
     }
 
     @Override
-    public boolean isHeadsUpGoingAway() {
+    public boolean isHeadsUpAnimatingAwayValue() {
         throw new UnsupportedOperationException();
     }
 
@@ -115,7 +115,7 @@
     }
 
     @Override
-    public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
+    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
         throw new UnsupportedOperationException();
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt
new file mode 100644
index 0000000..12f08a3
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt
@@ -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.systemui.unfold.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
+import com.google.common.truth.Truth.assertThat
+import java.util.Locale
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class UnfoldTransitionInteractorTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val unfoldTransitionProgressProvider = kosmos.fakeUnfoldTransitionProgressProvider
+
+    private val underTest: UnfoldTransitionInteractor = kosmos.unfoldTransitionInteractor
+
+    @Test
+    fun waitForTransitionFinish_noEvents_doesNotComplete() =
+        testScope.runTest {
+            val deferred = async { underTest.waitForTransitionFinish() }
+
+            runCurrent()
+
+            assertThat(deferred.isCompleted).isFalse()
+            deferred.cancel()
+        }
+
+    @Test
+    fun waitForTransitionFinish_finishEvent_completes() =
+        testScope.runTest {
+            val deferred = async { underTest.waitForTransitionFinish() }
+
+            runCurrent()
+            unfoldTransitionProgressProvider.onTransitionFinished()
+            runCurrent()
+
+            assertThat(deferred.isCompleted).isTrue()
+            deferred.cancel()
+        }
+
+    @Test
+    fun waitForTransitionFinish_otherEvent_doesNotComplete() =
+        testScope.runTest {
+            val deferred = async { underTest.waitForTransitionFinish() }
+
+            runCurrent()
+            unfoldTransitionProgressProvider.onTransitionStarted()
+            runCurrent()
+
+            assertThat(deferred.isCompleted).isFalse()
+            deferred.cancel()
+        }
+
+    @Test
+    fun unfoldTranslationX_leftToRight() =
+        testScope.runTest {
+            val maxTranslation = prepareConfiguration(isLeftToRight = true)
+            val translations by
+                collectLastValue(
+                    combine(
+                        underTest.unfoldTranslationX(isOnStartSide = true),
+                        underTest.unfoldTranslationX(isOnStartSide = false),
+                    ) { start, end ->
+                        Translations(
+                            start = start,
+                            end = end,
+                        )
+                    }
+                )
+            runCurrent()
+
+            unfoldTransitionProgressProvider.onTransitionStarted()
+            assertThat(translations?.start).isEqualTo(0f)
+            assertThat(translations?.end).isEqualTo(-0f)
+
+            repeat(10) { repetition ->
+                val transitionProgress = 1 - 0.1f * (repetition + 1)
+                unfoldTransitionProgressProvider.onTransitionProgress(transitionProgress)
+                assertThat(translations?.start).isEqualTo((1 - transitionProgress) * maxTranslation)
+                assertThat(translations?.end).isEqualTo(-(1 - transitionProgress) * maxTranslation)
+            }
+
+            unfoldTransitionProgressProvider.onTransitionFinishing()
+            assertThat(translations?.start).isEqualTo(maxTranslation)
+            assertThat(translations?.end).isEqualTo(-maxTranslation)
+
+            unfoldTransitionProgressProvider.onTransitionFinished()
+            assertThat(translations?.start).isEqualTo(0f)
+            assertThat(translations?.end).isEqualTo(-0f)
+        }
+
+    @Test
+    fun unfoldTranslationX_rightToLeft() =
+        testScope.runTest {
+            val maxTranslation = prepareConfiguration(isLeftToRight = false)
+            val translations by
+                collectLastValue(
+                    combine(
+                        underTest.unfoldTranslationX(isOnStartSide = true),
+                        underTest.unfoldTranslationX(isOnStartSide = false),
+                    ) { start, end ->
+                        Translations(
+                            start = start,
+                            end = end,
+                        )
+                    }
+                )
+            runCurrent()
+
+            unfoldTransitionProgressProvider.onTransitionStarted()
+            assertThat(translations?.start).isEqualTo(-0f)
+            assertThat(translations?.end).isEqualTo(0f)
+
+            repeat(10) { repetition ->
+                val transitionProgress = 1 - 0.1f * (repetition + 1)
+                unfoldTransitionProgressProvider.onTransitionProgress(transitionProgress)
+                assertThat(translations?.start)
+                    .isEqualTo(-(1 - transitionProgress) * maxTranslation)
+                assertThat(translations?.end).isEqualTo((1 - transitionProgress) * maxTranslation)
+            }
+
+            unfoldTransitionProgressProvider.onTransitionFinishing()
+            assertThat(translations?.start).isEqualTo(-maxTranslation)
+            assertThat(translations?.end).isEqualTo(maxTranslation)
+
+            unfoldTransitionProgressProvider.onTransitionFinished()
+            assertThat(translations?.start).isEqualTo(-0f)
+            assertThat(translations?.end).isEqualTo(0f)
+        }
+
+    private fun prepareConfiguration(
+        isLeftToRight: Boolean,
+    ): Int {
+        val configuration = context.resources.configuration
+        if (isLeftToRight) {
+            configuration.setLayoutDirection(Locale.US)
+        } else {
+            configuration.setLayoutDirection(Locale("he", "il"))
+        }
+        kosmos.fakeConfigurationRepository.onConfigurationChange(configuration)
+        val maxTranslation = 10
+        kosmos.fakeConfigurationRepository.setDimensionPixelSize(
+            R.dimen.notification_side_paddings,
+            maxTranslation
+        )
+        return maxTranslation
+    }
+
+    private data class Translations(
+        val start: Float,
+        val end: Float,
+    )
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt
index 96d1c0d..03a39f8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/util/kotlin/BooleanFlowOperatorsTest.kt
@@ -20,6 +20,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.android.systemui.util.kotlin.BooleanFlowOperators.and
@@ -27,6 +28,7 @@
 import com.android.systemui.util.kotlin.BooleanFlowOperators.or
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
@@ -62,6 +64,21 @@
         }
 
     @Test
+    fun and_onlyEmitsWhenValueChanges() =
+        testScope.runTest {
+            val flow1 = MutableStateFlow(false)
+            val flow2 = MutableStateFlow(false)
+            val values by collectValues(and(flow1, flow2))
+
+            assertThat(values).containsExactly(false)
+            flow1.value = true
+            // Overall value is still false, we should not have emitted again.
+            assertThat(values).containsExactly(false)
+            flow2.value = true
+            assertThat(values).containsExactly(false, true).inOrder()
+        }
+
+    @Test
     fun or_allTrue_returnsTrue() =
         testScope.runTest {
             val result by collectLastValue(or(TRUE, TRUE))
@@ -83,6 +100,20 @@
         }
 
     @Test
+    fun or_onlyEmitsWhenValueChanges() =
+        testScope.runTest {
+            val flow1 = MutableStateFlow(false)
+            val flow2 = MutableStateFlow(false)
+            val values by collectValues(or(flow1, flow2))
+
+            assertThat(values).containsExactly(false)
+            flow1.value = true
+            assertThat(values).containsExactly(false, true).inOrder()
+            flow2.value = true
+            assertThat(values).containsExactly(false, true).inOrder()
+        }
+
+    @Test
     fun not_true_returnsFalse() =
         testScope.runTest {
             val result by collectLastValue(not(TRUE))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
new file mode 100644
index 0000000..632196c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.interactor
+
+import android.bluetooth.BluetoothDevice
+import android.graphics.drawable.TestStubDrawable
+import android.media.AudioDeviceInfo
+import android.media.AudioDevicePort
+import android.media.AudioManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.settingslib.R
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.media.BluetoothMediaDevice
+import com.android.settingslib.media.MediaDevice
+import com.android.settingslib.media.PhoneMediaDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.bluetooth.cachedBluetoothDeviceManager
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+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.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.model.AudioOutputDevice
+import com.android.systemui.volume.localMediaController
+import com.android.systemui.volume.localMediaRepository
+import com.android.systemui.volume.mediaControllerRepository
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class AudioOutputInteractorTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+
+    lateinit var underTest: AudioOutputInteractor
+
+    @Before
+    fun setUp() {
+        with(kosmos) {
+            underTest = audioOutputInteractor
+
+            with(context.orCreateTestableResources) {
+                addOverride(R.drawable.ic_headphone, testIcon)
+                addOverride(R.drawable.ic_smartphone, testIcon)
+                addOverride(R.drawable.ic_media_speaker_device, testIcon)
+
+                addOverride(com.android.internal.R.drawable.ic_bt_hearing_aid, testIcon)
+            }
+        }
+    }
+
+    @Test
+    fun inCall_builtIn_returnsCommunicationDevice() {
+        with(kosmos) {
+            testScope.runTest {
+                with(audioRepository) {
+                    setMode(AudioManager.MODE_IN_CALL)
+                    setCommunicationDevice(builtInDevice)
+                }
+
+                val device by collectLastValue(underTest.currentAudioDevice)
+
+                runCurrent()
+
+                assertThat(device).isInstanceOf(AudioOutputDevice.BuiltIn::class.java)
+                assertThat(device!!.icon).isEqualTo(testIcon)
+                assertThat(device!!.name).isEqualTo("built_in")
+            }
+        }
+    }
+
+    @Test
+    fun inCall_wired_returnsCommunicationDevice() {
+        with(kosmos) {
+            testScope.runTest {
+                with(audioRepository) {
+                    setMode(AudioManager.MODE_IN_CALL)
+                    setCommunicationDevice(wiredDevice)
+                }
+
+                val device by collectLastValue(underTest.currentAudioDevice)
+
+                runCurrent()
+
+                assertThat(device).isInstanceOf(AudioOutputDevice.Wired::class.java)
+                assertThat(device!!.icon).isEqualTo(testIcon)
+                assertThat(device!!.name).isEqualTo("wired")
+            }
+        }
+    }
+
+    @Test
+    fun inCall_bluetooth_returnsCommunicationDevice() {
+        with(kosmos) {
+            testScope.runTest {
+                with(audioRepository) {
+                    setMode(AudioManager.MODE_IN_CALL)
+                    setCommunicationDevice(btDevice)
+                }
+                val bluetoothDevice: BluetoothDevice = mock {
+                    whenever(address).thenReturn(btDevice.address)
+                }
+                val cachedBluetoothDevice: CachedBluetoothDevice = mock {
+                    whenever(address).thenReturn(btDevice.address)
+                    whenever(name).thenReturn(btDevice.productName.toString())
+                    whenever(isHearingAidDevice).thenReturn(true)
+                }
+                whenever(bluetoothAdapter.getRemoteDevice(eq(btDevice.address)))
+                    .thenReturn(bluetoothDevice)
+                whenever(cachedBluetoothDeviceManager.findDevice(any()))
+                    .thenReturn(cachedBluetoothDevice)
+
+                val device by collectLastValue(underTest.currentAudioDevice)
+
+                runCurrent()
+
+                assertThat(device).isInstanceOf(AudioOutputDevice.Bluetooth::class.java)
+                assertThat(device!!.icon).isEqualTo(testIcon)
+                assertThat(device!!.name).isEqualTo("bt")
+            }
+        }
+    }
+
+    @Test
+    fun notInCall_builtIn_returnsMediaDevice() {
+        with(kosmos) {
+            testScope.runTest {
+                audioRepository.setMode(AudioManager.MODE_NORMAL)
+                mediaControllerRepository.setActiveSessions(listOf(localMediaController))
+                localMediaRepository.updateCurrentConnectedDevice(builtInMediaDevice)
+
+                val device by collectLastValue(underTest.currentAudioDevice)
+
+                runCurrent()
+
+                assertThat(device).isInstanceOf(AudioOutputDevice.BuiltIn::class.java)
+                assertThat(device!!.icon).isEqualTo(testIcon)
+                assertThat(device!!.name).isEqualTo("built_in_media")
+            }
+        }
+    }
+
+    @Test
+    fun notInCall_wired_returnsMediaDevice() {
+        with(kosmos) {
+            testScope.runTest {
+                audioRepository.setMode(AudioManager.MODE_NORMAL)
+                mediaControllerRepository.setActiveSessions(listOf(localMediaController))
+                localMediaRepository.updateCurrentConnectedDevice(wiredMediaDevice)
+
+                val device by collectLastValue(underTest.currentAudioDevice)
+
+                runCurrent()
+
+                assertThat(device).isInstanceOf(AudioOutputDevice.Wired::class.java)
+                assertThat(device!!.icon).isEqualTo(testIcon)
+                assertThat(device!!.name).isEqualTo("wired_media")
+            }
+        }
+    }
+
+    @Test
+    fun notInCall_bluetooth_returnsMediaDevice() {
+        with(kosmos) {
+            testScope.runTest {
+                audioRepository.setMode(AudioManager.MODE_NORMAL)
+                mediaControllerRepository.setActiveSessions(listOf(localMediaController))
+                localMediaRepository.updateCurrentConnectedDevice(bluetoothMediaDevice)
+
+                val device by collectLastValue(underTest.currentAudioDevice)
+
+                runCurrent()
+
+                assertThat(device).isInstanceOf(AudioOutputDevice.Bluetooth::class.java)
+                assertThat(device!!.icon).isEqualTo(testIcon)
+                assertThat(device!!.name).isEqualTo("bt_media")
+            }
+        }
+    }
+
+    private companion object {
+        val testIcon = TestStubDrawable()
+        val builtInDevice =
+            AudioDeviceInfo(
+                AudioDevicePort.createForTesting(
+                    AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
+                    "built_in",
+                    ""
+                )
+            )
+        val wiredDevice =
+            AudioDeviceInfo(
+                AudioDevicePort.createForTesting(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, "wired", "")
+            )
+        val btDevice =
+            AudioDeviceInfo(
+                AudioDevicePort.createForTesting(
+                    AudioDeviceInfo.TYPE_BLE_HEADSET,
+                    "bt",
+                    "test_address"
+                )
+            )
+        val builtInMediaDevice: MediaDevice =
+            mock<PhoneMediaDevice> {
+                whenever(name).thenReturn("built_in_media")
+                whenever(icon).thenReturn(testIcon)
+            }
+        val wiredMediaDevice: MediaDevice =
+            mock<PhoneMediaDevice> {
+                whenever(deviceType)
+                    .thenReturn(MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE)
+                whenever(name).thenReturn("wired_media")
+                whenever(icon).thenReturn(testIcon)
+            }
+        val bluetoothMediaDevice: MediaDevice =
+            mock<BluetoothMediaDevice> {
+                whenever(name).thenReturn("bt_media")
+                whenever(icon).thenReturn(testIcon)
+                val cachedBluetoothDevice: CachedBluetoothDevice = mock {
+                    whenever(isHearingAidDevice).thenReturn(true)
+                }
+                whenever(cachedDevice).thenReturn(cachedBluetoothDevice)
+            }
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt
index fa79e7f..675136c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt
@@ -31,7 +31,7 @@
 import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyInteractor
 import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyRepository
 import com.android.systemui.testKosmos
-import com.android.systemui.volume.audioRepository
+import com.android.systemui.volume.data.repository.audioRepository
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runCurrent
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt
new file mode 100644
index 0000000..89acbc8
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.startable
+
+import android.media.AudioManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.uiEventLogger
+import com.android.internal.logging.uiEventLoggerFake
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class AudioModeLoggerStartableTest : SysuiTestCase() {
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    private val kosmos = testKosmos()
+
+    private lateinit var underTest: AudioModeLoggerStartable
+
+    @Before
+    fun setUp() {
+        with(kosmos) {
+            underTest =
+                AudioModeLoggerStartable(
+                    applicationCoroutineScope,
+                    uiEventLogger,
+                    audioModeInteractor,
+                )
+        }
+    }
+
+    @Test
+    fun audioMode_inCall() {
+        with(kosmos) {
+            testScope.runTest {
+                audioRepository.setMode(AudioManager.MODE_IN_CALL)
+
+                underTest.start()
+                runCurrent()
+
+                assertThat(uiEventLoggerFake.eventId(0))
+                    .isEqualTo(VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_CALLING.id)
+            }
+        }
+    }
+
+    @Test
+    fun audioMode_notInCall() {
+        with(kosmos) {
+            testScope.runTest {
+                audioRepository.setMode(AudioManager.MODE_NORMAL)
+
+                underTest.start()
+                runCurrent()
+
+                assertThat(uiEventLoggerFake.eventId(0))
+                    .isEqualTo(VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_NORMAL.id)
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt
index e31cdcd..dc96139 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepositoryTest.kt
@@ -72,7 +72,7 @@
             testScope.runTest {
                 localMediaRepository.updateCurrentConnectedDevice(null)
 
-                val slice by collectLastValue(underTest.ancSlice(1))
+                val slice by collectLastValue(underTest.ancSlice(1, false, false))
                 runCurrent()
 
                 assertThat(slice).isNull()
@@ -86,7 +86,7 @@
             testScope.runTest {
                 localMediaRepository.updateCurrentConnectedDevice(createMediaDevice())
 
-                val slice by collectLastValue(underTest.ancSlice(1))
+                val slice by collectLastValue(underTest.ancSlice(1, false, false))
                 runCurrent()
 
                 assertThat(slice).isNotNull()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt
index 53f0bc9..81e6ac4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractorTest.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.testKosmos
 import com.android.systemui.volume.panel.component.anc.FakeSliceFactory
 import com.android.systemui.volume.panel.component.anc.ancSliceRepository
+import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runCurrent
@@ -57,10 +58,10 @@
                     FakeSliceFactory.createSlice(hasError = true, hasSliceItem = true)
                 )
 
-                val slice by collectLastValue(underTest.ancSlice)
+                val slice by collectLastValue(underTest.ancSlices)
                 runCurrent()
 
-                assertThat(slice).isNull()
+                assertThat(slice).isInstanceOf(AncSlices.Unavailable::class.java)
             }
         }
     }
@@ -74,10 +75,10 @@
                     FakeSliceFactory.createSlice(hasError = false, hasSliceItem = false)
                 )
 
-                val slice by collectLastValue(underTest.ancSlice)
+                val slice by collectLastValue(underTest.ancSlices)
                 runCurrent()
 
-                assertThat(slice).isNull()
+                assertThat(slice).isInstanceOf(AncSlices.Unavailable::class.java)
             }
         }
     }
@@ -91,10 +92,10 @@
                     FakeSliceFactory.createSlice(hasError = false, hasSliceItem = true)
                 )
 
-                val slice by collectLastValue(underTest.ancSlice)
+                val slice by collectLastValue(underTest.ancSlices)
                 runCurrent()
 
-                assertThat(slice).isNotNull()
+                assertThat(slice).isInstanceOf(AncSlices.Ready::class.java)
             }
         }
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt
index 2cc1ad3..27a813f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModelTest.kt
@@ -21,6 +21,8 @@
 import android.provider.Settings
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.uiEventLogger
+import com.android.internal.logging.uiEventLoggerFake
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
@@ -29,6 +31,7 @@
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import com.android.systemui.volume.panel.volumePanelViewModel
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,7 +61,10 @@
     private lateinit var underTest: BottomBarViewModel
 
     private fun initUnderTest() {
-        underTest = with(kosmos) { BottomBarViewModel(activityStarter, volumePanelViewModel) }
+        underTest =
+            with(kosmos) {
+                BottomBarViewModel(activityStarter, volumePanelViewModel, uiEventLogger)
+            }
     }
 
     @Test
@@ -96,6 +102,8 @@
                         /* userHandle = */ eq(null),
                     )
                 assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_SOUND_SETTINGS)
+                assertThat(uiEventLoggerFake.eventId(0))
+                    .isEqualTo(VolumePanelUiEvent.VOLUME_PANEL_SOUND_SETTINGS_CLICKED.id)
 
                 activityStartedCaptor.value.onActivityStarted(ActivityManager.START_SUCCESS)
                 val volumePanelState by collectLastValue(volumePanelViewModel.volumePanelState)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt
index 610195f..4cf924a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.uiEventLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
@@ -45,7 +46,12 @@
     fun setup() {
         underTest =
             with(kosmos) {
-                CaptioningViewModel(context, captioningInteractor, testScope.backgroundScope)
+                CaptioningViewModel(
+                    context,
+                    captioningInteractor,
+                    testScope.backgroundScope,
+                    uiEventLogger,
+                )
             }
     }
 
@@ -58,7 +64,7 @@
                 val buttonViewModel by collectLastValue(underTest.buttonViewModel)
                 runCurrent()
 
-                assertThat(buttonViewModel!!.isChecked).isFalse()
+                assertThat(buttonViewModel!!.isActive).isFalse()
             }
         }
     }
@@ -72,7 +78,7 @@
                 val buttonViewModel by collectLastValue(underTest.buttonViewModel)
                 runCurrent()
 
-                assertThat(buttonViewModel!!.isChecked).isTrue()
+                assertThat(buttonViewModel!!.isActive).isTrue()
             }
         }
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
index ec55c75..96b4dae 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
@@ -24,8 +24,8 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
-import com.android.systemui.volume.audioModeInteractor
-import com.android.systemui.volume.audioRepository
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runCurrent
@@ -46,7 +46,10 @@
 
     @Before
     fun setup() {
-        underTest = MediaOutputAvailabilityCriteria(kosmos.audioModeInteractor)
+        underTest =
+            MediaOutputAvailabilityCriteria(
+                kosmos.audioModeInteractor,
+            )
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
index 462f36d..30524d9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
@@ -22,6 +22,7 @@
 import android.testing.TestableLooper
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.uiEventLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.testScope
@@ -64,6 +65,7 @@
                     mediaOutputActionsInteractor,
                     mediaDeviceSessionInteractor,
                     mediaOutputInteractor,
+                    uiEventLogger,
                 )
 
             with(context.orCreateTestableResources) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt
deleted file mode 100644
index 79d3fe9..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractorTest.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.volume.domain.interactor
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class VolumeSliderInteractorTest : SysuiTestCase() {
-
-    private val underTest = VolumeSliderInteractor()
-
-    @Test
-    fun processVolumeToValue_returnsTranslatedVolume() {
-        assertThat(underTest.processVolumeToValue(2, volumeRange)).isEqualTo(20f)
-    }
-
-    private companion object {
-        val volumeRange = 0..10
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt
new file mode 100644
index 0000000..55e46dc
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.wmshell
+
+import android.content.pm.UserInfo
+import android.graphics.Color
+import android.platform.test.annotations.EnableFlags
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.keyguardUpdateMonitor
+import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel
+import com.android.systemui.communal.util.fakeCommunalColors
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.dock.DockManager
+import com.android.systemui.dock.fakeDockManager
+import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.keyguard.ScreenLifecycle
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.wakefulnessLifecycle
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.model.SysUiState
+import com.android.systemui.model.sysUiState
+import com.android.systemui.notetask.NoteTaskInitializer
+import com.android.systemui.settings.FakeDisplayTracker
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.settings.userTracker
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.commandQueue
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.policy.configurationController
+import com.android.systemui.statusbar.policy.keyguardStateController
+import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.fakeUserRepository
+import com.android.systemui.util.kotlin.JavaAdapter
+import com.android.wm.shell.desktopmode.DesktopMode
+import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
+import com.android.wm.shell.onehanded.OneHanded
+import com.android.wm.shell.onehanded.OneHandedEventCallback
+import com.android.wm.shell.onehanded.OneHandedTransitionCallback
+import com.android.wm.shell.pip.Pip
+import com.android.wm.shell.recents.RecentTasks
+import com.android.wm.shell.splitscreen.SplitScreen
+import com.android.wm.shell.sysui.ShellInterface
+import java.util.Optional
+import java.util.concurrent.Executor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/**
+ * Tests for [WMShell].
+ *
+ * Build/Install/Run: atest SystemUITests:WMShellTest
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WMShellTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    val testScope = kosmos.testScope
+
+    @Mock private lateinit var mShellInterface: ShellInterface
+    @Mock private lateinit var mScreenLifecycle: ScreenLifecycle
+    @Mock private lateinit var mPip: Pip
+    @Mock private lateinit var mSplitScreen: SplitScreen
+    @Mock private lateinit var mOneHanded: OneHanded
+    @Mock private lateinit var mNoteTaskInitializer: NoteTaskInitializer
+    @Mock private lateinit var mDesktopMode: DesktopMode
+    @Mock private lateinit var mRecentTasks: RecentTasks
+
+    private val mCommandQueue: CommandQueue = kosmos.commandQueue
+    private val mConfigurationController: ConfigurationController = kosmos.configurationController
+    private val mKeyguardStateController: KeyguardStateController = kosmos.keyguardStateController
+    private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor = kosmos.keyguardUpdateMonitor
+    private val mSysUiState: SysUiState = kosmos.sysUiState
+    private val mWakefulnessLifecycle: WakefulnessLifecycle = kosmos.wakefulnessLifecycle
+    private val mUserTracker: UserTracker = kosmos.userTracker
+    private val mSysUiMainExecutor: Executor = kosmos.fakeExecutor
+    private val communalTransitionViewModel = kosmos.communalTransitionViewModel
+
+    private lateinit var underTest: WMShell
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        val displayTracker = FakeDisplayTracker(mContext)
+
+        kosmos.fakeUserRepository.setUserInfos(listOf(MAIN_USER_INFO))
+        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
+
+        underTest =
+            WMShell(
+                mContext,
+                mShellInterface,
+                Optional.of(mPip),
+                Optional.of(mSplitScreen),
+                Optional.of(mOneHanded),
+                Optional.of(mDesktopMode),
+                Optional.of(mRecentTasks),
+                mCommandQueue,
+                mConfigurationController,
+                mKeyguardStateController,
+                mKeyguardUpdateMonitor,
+                mScreenLifecycle,
+                mSysUiState,
+                mWakefulnessLifecycle,
+                mUserTracker,
+                displayTracker,
+                mNoteTaskInitializer,
+                communalTransitionViewModel,
+                JavaAdapter(testScope.backgroundScope),
+                mSysUiMainExecutor
+            )
+    }
+
+    @Test
+    fun initPip_registersCommandQueueCallback() {
+        underTest.initPip(mPip)
+        verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks::class.java))
+    }
+
+    @Test
+    fun initOneHanded_registersCallbacks() {
+        underTest.initOneHanded(mOneHanded)
+        verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks::class.java))
+        verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer::class.java))
+        verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback::class.java))
+        verify(mOneHanded).registerEventCallback(any(OneHandedEventCallback::class.java))
+    }
+
+    @Test
+    fun initDesktopMode_registersListener() {
+        underTest.initDesktopMode(mDesktopMode)
+        verify(mDesktopMode)
+            .addVisibleTasksListener(
+                any(VisibleTasksListener::class.java),
+                any(Executor::class.java)
+            )
+    }
+
+    @Test
+    fun initRecentTasks_registersListener() {
+        underTest.initRecentTasks(mRecentTasks)
+        verify(mRecentTasks).addAnimationStateListener(any(Executor::class.java), any())
+    }
+
+    @Test
+    @EnableFlags(FLAG_COMMUNAL_HUB)
+    fun initRecentTasks_setRecentsBackgroundColorWhenCommunal() =
+        testScope.runTest {
+            val black = Color.valueOf(Color.BLACK)
+            kosmos.fakeCommunalColors.setBackgroundColor(black)
+
+            kosmos.fakeKeyguardRepository.setKeyguardShowing(false)
+
+            underTest.initRecentTasks(mRecentTasks)
+            runCurrent()
+            verify(mRecentTasks).setTransitionBackgroundColor(null)
+            verify(mRecentTasks, never()).setTransitionBackgroundColor(black)
+
+            setDocked(true)
+            // Make communal available
+            kosmos.fakeKeyguardRepository.setIsEncryptedOrLockdown(false)
+            kosmos.fakeUserRepository.setSelectedUserInfo(MAIN_USER_INFO)
+            kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
+
+            runCurrent()
+
+            verify(mRecentTasks).setTransitionBackgroundColor(black)
+        }
+
+    private fun TestScope.setDocked(docked: Boolean) {
+        kosmos.fakeDockManager.setIsDocked(docked)
+        val event =
+            if (docked) {
+                DockManager.STATE_DOCKED
+            } else {
+                DockManager.STATE_NONE
+            }
+        kosmos.fakeDockManager.setDockEvent(event)
+        runCurrent()
+    }
+
+    private companion object {
+        val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
index 8e2bd9b..79bf5f1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
@@ -267,6 +267,9 @@
 
     /** True if the clock will react to tone changes in the seed color. */
     val isReactiveToTone: Boolean = true,
+
+    /** True if the clock is large frame clock, which will use weather in compose. */
+    val useCustomClockScene: Boolean = false,
 )
 
 /** Render configuration options for a clock face. Modifies the way SystemUI behaves. */
@@ -283,6 +286,9 @@
      * animation will be used (e.g. a simple translation).
      */
     val hasCustomPositionUpdatedAnimation: Boolean = false,
+
+    /** True if the clock is large frame clock, which will use weatherBlueprint in compose. */
+    val useCustomClockScene: Boolean = false,
 )
 
 /** Structure for keeping clock-specific settings */
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
index 173d57b..3b6b5a0 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
@@ -91,6 +91,7 @@
                 android:layout_height="wrap_content"
                 android:contentDescription="@string/keyguard_accessibility_password"
                 android:gravity="center_horizontal"
+                android:layout_gravity="center"
                 android:imeOptions="flagForceAscii|actionDone"
                 android:inputType="textPassword"
                 android:maxLength="500"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 909d4fc..5aac653 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -55,6 +55,7 @@
              android:layout_height="wrap_content"
              android:contentDescription="@string/keyguard_accessibility_password"
              android:gravity="center"
+             android:layout_gravity="center"
              android:singleLine="true"
              android:textStyle="normal"
              android:inputType="textPassword"
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 529d609..b62e684b 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"መሣሪያ እንደገና ከጀመረ በኋላ ስርዓተ ጥለት ያስፈልጋል"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"መሣሪያ እንደገና ከጀመረ በኋላ ፒን ያስፈልጋል"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"መሣሪያ እንደገና ከጀመረ በኋላ የይለፍ ቃል ያስፈልጋል"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ለተጨማሪ ደህንነት በምትኩ ስርዓተ ጥለት ይጠቀሙ"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ለተጨማሪ ደህንነት በምትኩ ሥርዓተ ጥለት ይጠቀሙ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ለተጨማሪ ደህንነት በምትኩ ፒን ይጠቀሙ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ለተጨማሪ ደህንነት በምትኩ የይለፍ ቃል ይጠቀሙ"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"ፒን ለተጨማሪ ደህንነት ያስፈልጋል"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index d07c5b5..427373d 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -21,13 +21,13 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"‏أدخل رقم التعريف الشخصي (PIN)"</string>
-    <string name="keyguard_enter_pin" msgid="8114529922480276834">"أدخِل رقم التعريف الشخصي."</string>
+    <string name="keyguard_enter_pin" msgid="8114529922480276834">"أدخِل رقم التعريف الشخصي"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"أدخل النقش"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"ارسم النقش."</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"أدخل كلمة المرور"</string>
     <string name="keyguard_enter_password" msgid="6483623792371009758">"أدخِل كلمة المرور."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"بطاقة غير صالحة."</string>
-    <string name="keyguard_charged" msgid="5478247181205188995">"تم الشحن"</string>
+    <string name="keyguard_charged" msgid="5478247181205188995">"اكتمل الشحن"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن لاسلكيًا"</string>
     <string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
@@ -80,9 +80,9 @@
     <string name="kg_face_locked_out" msgid="2751559491287575">"يتعذّر فتح القفل بالوجه. أجريت محاولات كثيرة جدًا."</string>
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"يتعذّر الفتح ببصمة الإصبع. أجريت محاولات كثيرة جدًا."</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"ميزة \"الوكيل المعتمد\" غير متاحة."</string>
-    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"أجريت محاولات كثيرة جدًا بإدخال رقم تعريف شخصي خاطئ."</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"أجريت محاولات كثيرة جدًا برسم نقش خاطئ."</string>
-    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"أجريت محاولات كثيرة جدًا بإدخال كلمة مرور خاطئة."</string>
+    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"أجريت محاولات كثيرة جدًا باستخدام رقم تعريف شخصي خاطئ"</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"أجريت محاولات كثيرة جدًا باستخدام نقش خاطئ"</string>
+    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"أجريت محاولات كثيرة جدًا باستخدام كلمة مرور خاطئة"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{أعِد المحاولة خلال ثانية واحدة.}zero{أعِد المحاولة خلال # ثانية.}two{أعِد المحاولة خلال ثانيتين.}few{أعِد المحاولة خلال # ثوانٍ.}many{أعِد المحاولة خلال # ثانية.}other{أعِد المحاولة خلال # ثانية.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‏أدخل رقم التعريف الشخصي لشريحة SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏أدخل رقم التعريف الشخصي لشريحة SIM التابعة للمشغّل \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"يجب رسم النقش بعد إعادة تشغيل الجهاز."</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز."</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"يجب إدخال كلمة المرور بعد إعادة تشغيل الجهاز."</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"لمزيد من الأمان، استخدِم النقش بدلاً من ذلك."</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"لمزيد من الأمان، أدخِل رقم التعريف الشخصي بدلاً من ذلك."</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"لمزيد من الأمان، أدخِل كلمة المرور بدلاً من ذلك."</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"لمزيد من الأمان، يجب استخدام النقش"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"لمزيد من الأمان، يجب إدخال رقم التعريف الشخصي"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"لمزيد من الأمان، يجب إدخال كلمة المرور"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"يجب إدخال رقم التعريف الشخصي لمزيد من الأمان"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"يجب رسم النقش لمزيد من الأمان"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"يجب إدخال كلمة المرور لمزيد من الأمان"</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index ce8ebd3..4ed7e27 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত আৰ্হিৰ আৱশ্যক"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পিনৰ আৱশ্যক"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পাছৱৰ্ডৰ আৱশ্যক"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"অতিৰিক্ত সুৰক্ষাৰ বাবে, ইয়াৰ পৰিৱৰ্তে আৰ্হি ব্যৱহাৰ কৰক"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"অতিৰিক্ত সুৰক্ষাৰ বাবে, আৰ্হি ব্যৱহাৰ কৰক"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"অতিৰিক্ত সুৰক্ষাৰ বাবে, ইয়াৰ পৰিৱৰ্তে পিন ব্যৱহাৰ কৰক"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"অতিৰিক্ত সুৰক্ষাৰ বাবে, ইয়াৰ পৰিৱৰ্তে পাছৱৰ্ড ব্যৱহাৰ কৰক"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"অতিৰিক্ত সুৰক্ষাৰ বাবে পিন দিয়াটো বাধ্যতামূলক"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 96779450..4a5e789 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Uzorak je potreban nakon ponovnog pokretanja uređaja"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN je potreban nakon ponovnog pokretanja uređaja"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Lozinka je potrebna nakon pokretanja uređaja"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Radi dodatne zaštite, umjesto toga koristite uzorak"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Radi dodatne zaštite, umjesto toga koristite PIN"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Radi dodatne zašitite, umjesto toga koristite lozinku"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Za dodatnu sigurnost koristite uzorak"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Za dodatnu sigurnost koristite PIN"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Za dodatnu sigurnost koristite lozinku"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN je potreban radi dodatne sigurnosti"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Uzorak je potreban radi dodatne sigurnosti"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Lozinka je potrebna radi dodatne sigurnosti"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 8e97e84..5a03cec 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -83,7 +83,7 @@
     <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Příliš mnoho pokusů s nesprávným kódem PIN"</string>
     <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Příliš mnoho pokusů s nesprávným gestem"</string>
     <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Příliš mnoho pokusů s nesprávným heslem"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Zkuste to znovu za # sekundu.}few{Zkuste to znovu za # sekundy.}many{Zkuste to znovu za # sekundy.}other{Zkuste to znovu za # sekund.}}"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Zkuste to znovu za # sekundu}few{Zkuste to znovu za # sekundy}many{Zkuste to znovu za # sekundy}other{Zkuste to znovu za # sekund}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Zadejte kód PIN SIM karty."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Zadejte kód PIN SIM karty <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> eSIM kartu deaktivujte, chcete-li zařízení používat bez mobilních služeb."</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 2245710..195fdef 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/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="keyguard_enter_your_pin" msgid="5429932527814874032">"Gib deine PIN ein"</string>
+    <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN eingeben"</string>
     <string name="keyguard_enter_pin" msgid="8114529922480276834">"Gib die PIN ein"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Muster eingeben"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Zeichne das Muster"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 45e2a9d..bfb2ed0 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -83,7 +83,7 @@
     <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Demasiados intentos con PIN incorrecto"</string>
     <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Demasiados intentos con patrón incorrecto"</string>
     <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Demasiados intentos con contraseña incorrecta"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Vuelve a intentarlo en # segundo.}many{Vuelve a intentarlo en # segundos.}other{Vuelve a intentarlo en # segundos.}}"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Vuelve a intentarlo en # segundo}many{Vuelve a intentarlo en # segundos}other{Vuelve a intentarlo en # segundos}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Ingresa el PIN de la tarjeta SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Ingresa el PIN de la tarjeta SIM de \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Inhabilita la tarjeta eSIM para usar el dispositivo sin servicio móvil."</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index ea1dd13..c59bdc1 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Kuvio tarvitaan uudelleenkäynnistyksen jälkeen"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN-koodi tarvitaan uudelleenkäynnistyksen jälkeen"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Salasana tarvitaan uudelleenkäynnistyksen jälkeen"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Lisäsuojaa saat, kun käytät sen sijaan kuviota"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Lisäsuojaa saat, kun käytät sen sijaan PIN-koodia"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Lisäsuojaa saat, kun käytät sen sijaan salasanaa"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Käytä kuviota, niin saat lisäsuojaa"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Käytä PIN-koodia, niin saat lisäsuojaa"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Käytä salasanaa, niin saat lisäsuojaa"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN-koodi vaaditaan suojauksen parantamiseksi."</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Kuvio vaaditaan suojauksen parantamiseksi."</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Salasana vaaditaan suojauksen parantamiseksi."</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 6b51ac2..e5cd788 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Requírese o padrón tras reiniciar o dispositivo"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Requírese o PIN tras reiniciar o dispositivo"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Requírese o contrasinal tras reiniciar o dispositivo"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Utiliza un padrón para obter maior seguranza"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Utiliza un padrón para unha maior seguranza"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Utiliza un PIN para obter maior seguranza"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Utiliza un contrasinal para obter maior seguranza"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Utiliza un contrasinal para unha maior seguranza"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"É necesario poñer o PIN como medida de seguranza adicional"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"É necesario poñer o padrón como medida de seguranza adicional"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"É necesario poñer o contrasinal como medida de seguranza adicional"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index a762b49..2b01903 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -109,8 +109,8 @@
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"डिवाइस रीस्टार्ट करने पर, पिन डालना ज़रूरी है"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"डिवाइस रीस्टार्ट करने पर, पासवर्ड डालना ज़रूरी है"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ज़्यादा सुरक्षा के लिए, इसके बजाय पैटर्न का इस्तेमाल करें"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ज़्यादा सुरक्षा के लिए, इसके बजाय पिन का इस्तेमाल करें"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ज़्यादा सुरक्षा के लिए, इसके बजाय पासवर्ड का इस्तेमाल करें"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ज़्यादा सुरक्षा के लिए, पिन का इस्तेमाल करें"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ज़्यादा सुरक्षा के लिए, पासवर्ड का इस्तेमाल करें"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"अतिरिक्त सुरक्षा के लिए पिन ज़रूरी है"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"अतिरिक्त सुरक्षा के लिए पैटर्न ज़रूरी है"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"अतिरिक्त सुरक्षा के लिए पासवर्ड ज़रूरी है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index dc5b0b8..e2ac8b6 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -80,10 +80,10 @@
     <string name="kg_face_locked_out" msgid="2751559491287575">"Tidak dapat membuka kunci dengan wajah. Terlalu banyak upaya gagal."</string>
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"Tidak dapat membuka kunci dengan sidik jari. Terlalu banyak upaya gagal."</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"Perangkat tepercaya tidak tersedia"</string>
-    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Terlalu banyak upaya dengan PIN yang salah"</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Terlalu banyak upaya dengan pola yang salah"</string>
-    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Terlalu banyak upaya dengan sandi yang salah"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Coba lagi dalam # detik.}other{Coba lagi dalam # detik.}}"</string>
+    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Terlalu banyak pemakaian PIN yang salah"</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Terlalu banyak pemakaian pola yang salah"</string>
+    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Terlalu banyak pemakaian sandi yang salah"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Coba lagi setelah # detik.}other{Coba lagi setelah # detik.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Masukkan PIN SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Masukkan PIN SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Nonaktifkan eSIM untuk menggunakan perangkat tanpa layanan seluler."</string>
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Pola diperlukan setelah perangkat dimulai ulang"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN diperlukan setelah perangkat dimulai ulang"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Sandi diperlukan setelah perangkat dimulai ulang"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Untuk keamanan tambahan, gunakan pola"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Untuk keamanan tambahan, gunakan PIN"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Untuk keamanan tambahan, gunakan sandi"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Agar lebih aman, gunakan pola"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Agar lebih aman, gunakan PIN"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Agar lebih aman, gunakan sandi"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN diperlukan untuk keamanan tambahan"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Pola diperlukan untuk keamanan tambahan"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Sandi diperlukan untuk keamanan tambahan"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index 20808db..2deefd0 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Mynsturs er krafist eftir að tækið er endurræst"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN-númers er krafist eftir að tækið er endurræst"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Aðgangsorðs er krafist eftir að tækið er endurræst"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Fyrir aukið öryggi skaltu nota mynstur í staðinn"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Fyrir aukið öryggi skaltu nota PIN-númer í staðinn"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Fyrir aukið öryggi skaltu nota aðgangsorð í staðinn"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Til að auka öryggi skaltu nota mynstur í staðinn"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Til að auka öryggi skaltu nota PIN-númer í staðinn"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Til að auka öryggi skaltu nota aðgangsorð í staðinn"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"PIN-númers er krafist af öryggisástæðum"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Mynsturs er krafist af öryggisástæðum"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Aðgangsorðs er krafist af öryggisástæðum"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 71969c0..9752eca 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -80,9 +80,9 @@
     <string name="kg_face_locked_out" msgid="2751559491287575">"顔認証でロックを解除できません。何度もログインに失敗したためログインできません。"</string>
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"指紋でロックを解除できません。何度もログインに失敗したためログインできません。"</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"信頼エージェントは利用できません"</string>
-    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"間違った PIN による試行回数が上限を超えました"</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"間違ったパターンによる試行回数が上限を超えました"</string>
-    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"間違ったパスワードによる試行回数が上限を超えました"</string>
+    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"間違った PIN による試行回数が上限に達しました"</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"間違ったパターンによる試行回数が上限に達しました"</string>
+    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"間違ったパスワードによる試行回数が上限に達しました"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{# 秒後にもう一度お試しください。}other{# 秒後にもう一度お試しください。}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN を入力してください。"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"「<xliff:g id="CARRIER">%1$s</xliff:g>」の SIM PIN を入力してください。"</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index b816748..733e29c 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -80,9 +80,9 @@
     <string name="kg_face_locked_out" msgid="2751559491287575">"មិនអាចដោះសោដោយប្រើមុខទេ។ ព្យាយាមច្រើនដងពេក។"</string>
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"មិនអាចដោះសោដោយប្រើស្នាមម្រាមដៃទេ។ ព្យាយាមច្រើនដងពេក។"</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"ភ្នាក់ងារទុកចិត្តមិនទំនេរទេ"</string>
-    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"ព្យាយាមច្រើនដងពេកដោយប្រើកូដ PIN មិនត្រឹមត្រូវ"</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"ព្យាយាមច្រើនដងពេកដោយប្រើលំនាំមិនត្រឹមត្រូវ"</string>
-    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"ព្យាយាមច្រើនដងពេកដោយប្រើពាក្យសម្ងាត់មិនត្រឹមត្រូវ"</string>
+    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"ព្យាយាមដោយប្រើកូដ PIN មិនត្រឹមត្រូវច្រើនដងពេក"</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"ព្យាយាមដោយប្រើលំនាំមិនត្រឹមត្រូវច្រើនដងពេក"</string>
+    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"ព្យាយាមដោយប្រើពាក្យសម្ងាត់មិនត្រឹមត្រូវច្រើនដងពេក"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{ព្យាយាមម្តងទៀតក្នុងរយៈពេល # វិនាទីទៀត។}other{ព្យាយាមម្តងទៀតក្នុងរយៈពេល # វិនាទីទៀត។}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"បញ្ចូល​កូដ PIN របស់​ស៊ីម។"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"បញ្ចូល​កូដ PIN របស់​ស៊ីម​សម្រាប់ \"<xliff:g id="CARRIER">%1$s</xliff:g>\"។"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 8d86a8d..69154ae 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"기기가 다시 시작되어 패턴을 입력해야 합니다."</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"기기가 다시 시작되어 PIN을 입력해야 합니다."</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"기기가 다시 시작되어 비밀번호를 입력해야 합니다."</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"보안 강화를 위해 대신 패턴 사용"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"보안 강화를 위해 패턴 사용"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"보안 강화를 위해 대신 PIN 사용"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"보안 강화를 위해 대신 비밀번호 사용"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"보안 강화를 위해 PIN이 필요합니다."</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 6bfbd64..de53f9f 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -49,7 +49,7 @@
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM-картаны өчүрүү"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-картаны өчүрүүгө болбойт"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Катадан улам eSIM-картаны өчүрүүгө болбойт."</string>
-    <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Киргизүү"</string>
+    <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Графикалык ачкыч туура эмес"</string>
     <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"Графклк ачкч тура эмс. Кайтлап крүңз."</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Сырсөз туура эмес"</string>
@@ -80,9 +80,9 @@
     <string name="kg_face_locked_out" msgid="2751559491287575">"Жүз менен кулпусу ачылбай жатат. Өтө көп жолу аракет кылдыңыз."</string>
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"Манжа изи менен кулпусу ачылбай жатат. Өтө көп жолу аракет кылдыңыз."</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"Ишеним агенти жеткиликсиз"</string>
-    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Туура эмес PIN код менен өтө көп аракет"</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Туура эмес графикалык ачкыч менен өтө көп аракет"</string>
-    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Туура эмес сырсөз менен өтө көп аракет"</string>
+    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"PIN код өтө көп жолу туура эмес киргизилди."</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Графикалык ачкыч өтө көп жолу туура эмес тартылды."</string>
+    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Сырсөздү өтө көп жолу туура эмес киргиздиңиз."</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{# секунддан кийин кайталаңыз.}other{# секунддан кийин кайталаңыз.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM-картанын PIN кодун киргизиңиз."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" SIM-картасынын PIN кодун киргизиңиз."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 3e110b5..6c57d89 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -49,7 +49,7 @@
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Оневозможи ја eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Не може да се оневозможи eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM-картичката не може да се оневозможи поради грешка."</string>
-    <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Внеси"</string>
+    <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Погрешна шема"</string>
     <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"Погрешна шема. Обидете се повторно."</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Погрешна лозинка"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index ecf843d..0112d5d 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -83,7 +83,7 @@
     <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Terlalu banyak percubaan dengan PIN yang salah"</string>
     <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Terlalu banyak percubaan dengan corak yang salah"</string>
     <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Terlalu banyak percubaan dengan kata laluan yang salah"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Cuba lagi dalam # saat.}other{Cuba lagi dalam # saat.}}"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Cuba lagi selepas # saat.}other{Cuba lagi selepas # saat.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Masukkan PIN SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Masukkan PIN SIM untuk \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Lumpuhkan eSIM untuk menggunakan peranti tanpa perkhidmatan mudah alih."</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 95d638e..f74eb66 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"စက်ကို ပြန်စပြီးနောက် ပုံဖော်ခြင်းလိုအပ်သည်"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"စက်ကို ပြန်စပြီးနောက် ပင်နံပါတ်လိုအပ်သည်"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"စက်ကို ပြန်စပြီးနောက် စကားဝှက်လိုအပ်သည်"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ၎င်းအစား ပုံစံသုံးပါ"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ပုံစံကို အစားထိုးသုံးပါ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ၎င်းအစား ပင်နံပါတ်သုံးပါ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ထပ်ဆောင်းလုံခြုံရေးအတွက် ၎င်းအစား စကားဝှက်သုံးပါ"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"ထပ်ဆောင်း လုံခြုံရေးအတွက် ပင်နံပါတ် လိုအပ်သည်"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 219072b..65440e8 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -24,7 +24,7 @@
     <string name="keyguard_enter_pin" msgid="8114529922480276834">"PIN हाल्नुहोस्"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"प्याटर्न हाल्नुहोस्"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"प्याटर्न कोर्नुहोस्"</string>
-    <string name="keyguard_enter_your_password" msgid="7225626204122735501">"पासवर्ड हाल्नुहोस्…"</string>
+    <string name="keyguard_enter_your_password" msgid="7225626204122735501">"पासवर्ड हाल्नुहोस्"</string>
     <string name="keyguard_enter_password" msgid="6483623792371009758">"पासवर्ड हाल्नुहोस्"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अमान्य कार्ड।"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"चार्ज भयो"</string>
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"डिभाइस रिस्टार्ट भएपछि प्याटर्न कोर्नु पर्ने हुन्छ"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"डिभाइस रिस्टार्ट भएपछि PIN हाल्नु पर्ने हुन्छ"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"डिभाइस रिस्टार्ट भएपछि पासवर्ड हाल्नु पर्ने हुन्छ"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"अतिरिक्त सुरक्षाका लागि यो प्रमाणीकरण विधिको साटो प्याटर्न प्रयोग गर्नुहोस्"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"अतिरिक्त सुरक्षाका लागि यो प्रमाणीकरण विधिको साटो पिन प्रयोग गर्नुहोस्"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"अतिरिक्त सुरक्षाका लागि यो प्रमाणीकरण विधिको साटो पासवर्ड प्रयोग गर्नुहोस्"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"अतिरिक्त सुरक्षाका लागि यसको साटो पासवर्ड प्रयोग गर्नुहोस्"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"अतिरिक्त सुरक्षाका लागि यसको साटो पासवर्ड प्रयोग गर्नुहोस्"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"अतिरिक्त सुरक्षाका लागि यसको साटो पासवर्ड प्रयोग गर्नुहोस्"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"अतिरिक्त सुरक्षाका लागि PIN चाहिन्छ"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"अतिरिक्त सुरक्षाका लागि प्याटर्न चाहिन्छ"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"अतिरिक्त सुरक्षाका लागि पासवर्ड चाहिन्छ"</string>
@@ -126,8 +126,8 @@
     <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"आफ्नो डिभाइस अनलक गरी जारी राख्नुहोस्"</string>
     <string name="kg_prompt_unattended_update_pin" msgid="5979434876768801873">"पछि अपडेट इन्स्टल गर्न PIN हाल्नुहोस्"</string>
     <string name="kg_prompt_unattended_update_password" msgid="8805664437604967210">"पछि अपडेट इन्स्टल गर्न पासवर्ड हाल्नुहोस्"</string>
-    <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"पछि अपडेट इन्स्टल गर्न प्याटर्न बनाउनुहोस्"</string>
+    <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"पछि अपडेट इन्स्टल गर्न प्याटर्न कोर्नुहोस्"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"डिभाइस अपडेट गरिएको छ। जारी राख्न PIN हाल्नुहोस्।"</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"डिभाइस अपडेट गरिएको छ। जारी राख्न पासवर्ड हाल्नुहोस्।"</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"डिभाइस अपडेट गरिएको छ। जारी राख्न प्याटर्न बनाउनुहोस्।"</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"डिभाइस अपडेट गरिएको छ। जारी राख्न प्याटर्न कोर्नुहोस्।"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 0206403..9fb9e1b 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -22,7 +22,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Geef je pincode op"</string>
     <string name="keyguard_enter_pin" msgid="8114529922480276834">"Voer pincode in"</string>
-    <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Geef je patroon op"</string>
+    <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Voer je patroon in"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Teken het patroon"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Voer je wachtwoord in"</string>
     <string name="keyguard_enter_password" msgid="6483623792371009758">"Geef het wachtwoord op"</string>
@@ -80,9 +80,9 @@
     <string name="kg_face_locked_out" msgid="2751559491287575">"Kan niet ontgrendelen met gezicht. Te veel pogingen."</string>
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"Niet ontgrendeld met vingerafdruk. Te veel pogingen."</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"Trust agent is niet beschikbaar"</string>
-    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Te veel pogingen met onjuiste pincode"</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Te veel pogingen met onjuist patroon"</string>
-    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Te veel pogingen met onjuist wachtwoord"</string>
+    <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Pincode te vaak verkeerd ingevoerd"</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Patroon te vaak verkeerd getekend"</string>
+    <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Wachtwoord te vaak verkeerd ingevoerd"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Probeer het over # seconde opnieuw.}other{Probeer het over # seconden opnieuw.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Geef de pincode van de simkaart op."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Geef de pincode voor de simkaart van \'<xliff:g id="CARRIER">%1$s</xliff:g>\' op."</string>
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Patroon is vereist na opnieuw opstarten apparaat"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Pincode is vereist na opnieuw opstarten apparaat"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Wachtwoord is vereist na opnieuw opstarten apparaat"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Gebruik in plaats daarvan het patroon voor extra beveiliging"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Gebruik het patroon voor extra beveiliging"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Gebruik de pincode voor extra beveiliging"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Gebruik in plaats daarvan het wachtwoord voor extra beveiliging"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Gebruik het wachtwoord voor extra beveiliging"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Pincode vereist voor extra beveiliging"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Patroon vereist voor extra beveiliging"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Wachtwoord vereist voor extra beveiliging"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 4a89070..f25e9c5 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -83,7 +83,7 @@
     <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Zbyt wiele nieudanych prób wpisania kodu PIN"</string>
     <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Zbyt wiele nieudanych prób narysowania wzoru"</string>
     <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Zbyt wiele nieudanych prób wpisania hasła"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Spróbuj ponownie za # sekundę.}few{Spróbuj ponownie za # sekundy.}many{Spróbuj ponownie za # sekund.}other{Spróbuj ponownie za # sekundy.}}"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Spróbuj ponownie za # sekundę}few{Spróbuj ponownie za # sekundy}many{Spróbuj ponownie za # sekund}other{Spróbuj ponownie za # sekundy}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Wpisz kod PIN karty SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Wpisz kod PIN karty SIM „<xliff:g id="CARRIER">%1$s</xliff:g>”."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Wyłącz kartę eSIM, by używać urządzenia bez usługi sieci komórkowej."</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 1ae1aeb..b292204 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -24,7 +24,7 @@
     <string name="keyguard_enter_pin" msgid="8114529922480276834">"Introduza o PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introduza o padrão"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Desenhe o padrão"</string>
-    <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduza a palavra-passe."</string>
+    <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduza a palavra-passe"</string>
     <string name="keyguard_enter_password" msgid="6483623792371009758">"Introduza a palavra-passe"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string>
@@ -108,9 +108,9 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Padrão necessário após reiniciar o dispositivo"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"PIN necessário após reiniciar o dispositivo"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Palavra-passe necessária após reiniciar dispositivo"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para uma segurança adicional, use antes o padrão"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para uma segurança adicional, use antes o PIN"</string>
-    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para uma segurança adicional, use antes a palavra-passe"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para segurança adicional, use o padrão"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para segurança adicional, use o PIN"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para segurança adicional, use a palavra-passe"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Para segurança adicional, é necessária um PIN"</string>
     <string name="kg_prompt_added_security_pattern" msgid="1017068086102168544">"Para segurança adicional, é necessário um padrão"</string>
     <string name="kg_prompt_added_security_password" msgid="6053156069765029006">"Para segurança adicional, é necessária uma palavra-passe"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index aa2d080..fd90d08 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -81,7 +81,7 @@
     <string name="kg_fp_locked_out" msgid="6228277682396768830">"Превышен лимит попыток разблокировки отпечатком."</string>
     <string name="kg_trust_agent_disabled" msgid="5400691179958727891">"Агент доверия недоступен."</string>
     <string name="kg_primary_auth_locked_out_pin" msgid="5492230176361601475">"Слишком много неудачных попыток ввести PIN-код."</string>
-    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Слишком много неудачных попыток ввести граф. ключ."</string>
+    <string name="kg_primary_auth_locked_out_pattern" msgid="8266214607346180952">"Слишком много неудачных попыток ввести графический ключ."</string>
     <string name="kg_primary_auth_locked_out_password" msgid="6170245108400198659">"Слишком много неудачных попыток ввести пароль."</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Повторите попытку через # секунду.}one{Повторите попытку через # секунду.}few{Повторите попытку через # секунды.}many{Повторите попытку через # секунд.}other{Повторите попытку через # секунды.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Введите PIN-код SIM-карты."</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 5725fe0..9b0647a 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Po reštarte zariadenia sa vyžaduje vzor"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Po reštarte zariadenia sa vyžaduje kód PIN"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Po reštarte zariadenia sa vyžaduje heslo"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"V rámci zvýšenia zabezpečenia použite radšej vzor"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Z bezpečnostných dôvodov použite radšej vzor"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"V rámci zvýšenia zabezpečenia použite radšej PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"V rámci zvýšenia zabezpečenia použite radšej heslo"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Zvýšenie zabezpečenia vyžaduje kód PIN"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index bfe5ae0..cb17459 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Kailangan ang pattern pagka-restart ng device"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Kailangan ang PIN pagka-restart ng device"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Kailangan ang password pagka-restart ng device"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para sa karagdagang seguridad, gumamit na lang ng pattern"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para sa karagdagang seguridad, gumamit ng pattern"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para sa karagdagang seguridad, gumamit na lang ng PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para sa karagdagang seguridad, gumamit na lang ng password"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Kinakailangan ang PIN para sa karagdagang seguridad"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index bbd319c3..72ea850 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"Cần vẽ hình mở khoá sau khi khởi động lại thiết bị"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"Cần nhập mã PIN sau khi khởi động lại thiết bị"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"Cần nhập mật khẩu sau khi khởi động lại thiết bị"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Để tăng cường bảo mật, hãy sử dụng hình mở khoá"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Để tăng cường bảo mật, hãy dùng hình mở khoá"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Để tăng cường bảo mật, hãy sử dụng mã PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Để tăng cường bảo mật, hãy sử dụng mật khẩu"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"Yêu cầu mã PIN để tăng cường bảo mật"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index a316e8c..7d74c9c 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -22,7 +22,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"输入您的 PIN 码"</string>
     <string name="keyguard_enter_pin" msgid="8114529922480276834">"输入 PIN 码"</string>
-    <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"绘制您的图案"</string>
+    <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"绘制解锁图案"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"绘制图案"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"输入您的密码"</string>
     <string name="keyguard_enter_password" msgid="6483623792371009758">"输入密码"</string>
@@ -108,7 +108,7 @@
     <string name="kg_prompt_reason_restart_pattern" msgid="3321211830602827742">"设备重启后,必须绘制图案才能解锁"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="2672166323886110512">"设备重启后,必须输入 PIN 码才能解锁"</string>
     <string name="kg_prompt_reason_restart_password" msgid="3967993994418885887">"设备重启后,必须输入密码才能解锁"</string>
-    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"为增强安全性,请改用图案"</string>
+    <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"为增强安全性,请改用解锁图案"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"为增强安全性,请改用 PIN 码"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"为增强安全性,请改用密码"</string>
     <string name="kg_prompt_added_security_pin" msgid="5487992065995475528">"需要输入 PIN 码以进一步确保安全"</string>
diff --git a/packages/SystemUI/res-product/values-ar/strings.xml b/packages/SystemUI/res-product/values-ar/strings.xml
index 4d4d8d0..0ddb911 100644
--- a/packages/SystemUI/res-product/values-ar/strings.xml
+++ b/packages/SystemUI/res-product/values-ar/strings.xml
@@ -34,10 +34,10 @@
     <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بياناته."</string>
     <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بياناته."</string>
     <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بياناته."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بيانات الملف الشخصي."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بيانات الملف الشخصي."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
-    <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_erase_profile" product="tablet" msgid="1049523640263353830">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة ملف العمل، ومن ثم يتم حذف جميع بيانات الملف الشخصي."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة ملف العمل، ومن ثم يتم حذف جميع بيانات الملف الشخصي."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة ملف العمل، ومن ثم يتم حذف جميع بياناته."</string>
+    <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="thermal_shutdown_title" product="default" msgid="8039593017174903505">"تم إطفاء الهاتف بسبب ارتفاع درجة حرارته"</string>
diff --git a/packages/SystemUI/res/anim/shortcut_helper_close_anim.xml b/packages/SystemUI/res/anim/shortcut_helper_close_anim.xml
new file mode 100644
index 0000000..47fd78a
--- /dev/null
+++ b/packages/SystemUI/res/anim/shortcut_helper_close_anim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+    android:zAdjustment="top">
+
+    <translate
+        android:fromYDelta="0"
+        android:toYDelta="100%"
+        android:duration="@android:integer/config_shortAnimTime" />
+</set>
diff --git a/packages/SystemUI/res/anim/shortcut_helper_launch_anim.xml b/packages/SystemUI/res/anim/shortcut_helper_launch_anim.xml
new file mode 100644
index 0000000..77edf58
--- /dev/null
+++ b/packages/SystemUI/res/anim/shortcut_helper_launch_anim.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+    android:zAdjustment="top">
+
+    <translate android:fromYDelta="100%"
+        android:toYDelta="0"
+        android:startOffset="@android:integer/config_shortAnimTime"
+        android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/packages/SystemUI/res/anim/slide_in_up.xml b/packages/SystemUI/res/anim/slide_in_up.xml
new file mode 100644
index 0000000..6089a28
--- /dev/null
+++ b/packages/SystemUI/res/anim/slide_in_up.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<translate
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromYDelta="100%p"
+    android:toYDelta="0"
+    android:duration="@android:integer/config_shortAnimTime" />
diff --git a/packages/SystemUI/res/anim/slide_out_down.xml b/packages/SystemUI/res/anim/slide_out_down.xml
new file mode 100644
index 0000000..5a7b591
--- /dev/null
+++ b/packages/SystemUI/res/anim/slide_out_down.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<translate
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromYDelta="0"
+    android:toYDelta="100%p"
+    android:duration="@android:integer/config_shortAnimTime" />
diff --git a/packages/SystemUI/res/color/notification_focus_overlay_color.xml b/packages/SystemUI/res/color/notification_focus_overlay_color.xml
new file mode 100644
index 0000000..6a3c7a1
--- /dev/null
+++ b/packages/SystemUI/res/color/notification_focus_overlay_color.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:state_focused="true" android:color="?androidprv:attr/materialColorSecondary" />
+    <item android:color="@color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/hearing_devices_preset_spinner_background.xml b/packages/SystemUI/res/drawable/hearing_devices_preset_spinner_background.xml
new file mode 100644
index 0000000..6e6e032
--- /dev/null
+++ b/packages/SystemUI/res/drawable/hearing_devices_preset_spinner_background.xml
@@ -0,0 +1,43 @@
+<!--
+    Copyright (C) 2024 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:paddingMode="stack">
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/hearing_devices_preset_spinner_background_radius" />
+            <stroke
+                android:width="1dp"
+                android:color="?androidprv:attr/textColorTertiary" />
+            <solid android:color="@android:color/transparent"/>
+        </shape>
+    </item>
+    <item
+        android:end="20dp"
+        android:gravity="end|center_vertical">
+        <vector
+            android:width="@dimen/screenrecord_spinner_arrow_size"
+            android:height="@dimen/screenrecord_spinner_arrow_size"
+            android:viewportWidth="24"
+            android:viewportHeight="24"
+            android:tint="?androidprv:attr/colorControlNormal">
+            <path
+                android:fillColor="#FF000000"
+                android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/hearing_devices_preset_spinner_popup_background.xml b/packages/SystemUI/res/drawable/hearing_devices_preset_spinner_popup_background.xml
new file mode 100644
index 0000000..f35975e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/hearing_devices_preset_spinner_popup_background.xml
@@ -0,0 +1,22 @@
+<!--
+    Copyright (C) 2024 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/hearing_devices_preset_spinner_background_radius"/>
+    <solid android:color="?androidprv:attr/materialColorSurfaceContainer" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_bugreport.xml b/packages/SystemUI/res/drawable/ic_bugreport.xml
new file mode 100644
index 0000000..ed1c6c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_bugreport.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24.0dp"
+    android:height="24.0dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M20,10V8h-2.81c-0.45,-0.78 -1.07,-1.46 -1.82,-1.96L17,4.41L15.59,3l-2.17,2.17c-0.03,-0.01 -0.05,-0.01 -0.08,-0.01c-0.16,-0.04 -0.32,-0.06 -0.49,-0.09c-0.06,-0.01 -0.11,-0.02 -0.17,-0.03C12.46,5.02 12.23,5 12,5h0c-0.49,0 -0.97,0.07 -1.42,0.18l0.02,-0.01L8.41,3L7,4.41l1.62,1.63l0.01,0C7.88,6.54 7.26,7.22 6.81,8H4v2h2.09C6.03,10.33 6,10.66 6,11v1H4v2h2v1c0,0.34 0.04,0.67 0.09,1H4v2h2.81c1.04,1.79 2.97,3 5.19,3h0c2.22,0 4.15,-1.21 5.19,-3H20v-2h-2.09l0,0c0.05,-0.33 0.09,-0.66 0.09,-1v-1h2v-2h-2v-1c0,-0.34 -0.04,-0.67 -0.09,-1l0,0H20zM16,15c0,2.21 -1.79,4 -4,4c-2.21,0 -4,-1.79 -4,-4v-4c0,-2.21 1.79,-4 4,-4h0c2.21,0 4,1.79 4,4V15z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M10,14h4v2h-4z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M10,10h4v2h-4z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_noise_aware.xml b/packages/SystemUI/res/drawable/ic_noise_aware.xml
deleted file mode 100644
index 5482641..0000000
--- a/packages/SystemUI/res/drawable/ic_noise_aware.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-  ~ Copyright (C) 2024 The Android Open Source Project
-  ~
-  ~  Licensed under the Apache License, Version 2.0 (the "License");
-  ~  you may not use this file except in compliance with the License.
-  ~  You may obtain a copy of the License at
-  ~
-  ~       http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~  Unless required by applicable law or agreed to in writing, software
-  ~  distributed under the License is distributed on an "AS IS" BASIS,
-  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~  See the License for the specific language governing permissions and
-  ~  limitations under the License.
-  -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="960"
-    android:viewportHeight="960"
-    android:tint="?attr/colorControlNormal">
-  <path
-      android:fillColor="@android:color/white"
-      android:pathData="M440,82Q450,81 460,80.5Q470,80 480,80Q491,80 500.5,80.5Q510,81 520,82L520,162Q510,160 500.5,160Q491,160 480,160Q469,160 459.5,160Q450,160 440,162L440,82ZM272,138Q289,127 306.5,119Q324,111 343,104L378,176Q358,182 340.5,190.5Q323,199 306,210L272,138ZM654,210Q637,199 619.5,190.5Q602,182 582,176L617,104Q636,111 653.5,119Q671,127 688,138L654,210ZM753,311Q742,294 729,278.5Q716,263 702,249L765,199Q779,213 792,228.5Q805,244 816,261L753,311ZM143,263Q154,246 166.5,230.5Q179,215 193,201L256,251Q242,265 229.5,280.5Q217,296 206,313L143,263ZM83,428Q85,408 90,388.5Q95,369 101,350L180,368Q173,387 168.5,406.5Q164,426 162,446L83,428ZM799,449Q797,429 792.5,409Q788,389 781,370L859,352Q865,371 870,390.5Q875,410 877,430L799,449ZM781,590Q788,571 792,552Q796,533 798,513L877,531Q875,551 870,570.5Q865,590 859,609L781,590ZM162,514Q164,534 168.5,553.5Q173,573 180,592L101,610Q95,591 90,571.5Q85,552 83,532L162,514ZM705,708Q719,694 731,678.5Q743,663 754,646L818,696Q807,713 794.5,728.5Q782,744 768,758L705,708ZM194,760Q180,746 167.5,730Q155,714 144,697L206,647Q217,664 229.5,680Q242,696 256,710L194,760ZM583,783Q603,776 620,768Q637,760 654,749L689,821Q672,832 654.5,840.5Q637,849 618,856L583,783ZM344,857Q325,850 307,841.5Q289,833 272,822L307,750Q324,761 341.5,769.5Q359,778 379,784L344,857ZM480,880Q470,880 460,879.5Q450,879 440,878L440,798Q453,800 480,800Q491,800 500.5,800Q510,800 520,798L520,878Q510,879 500.5,879.5Q491,880 480,880ZM520,720Q482,720 450.5,697Q419,674 406,638Q403,629 399.5,620.5Q396,612 389,605L334,550Q308,524 294,490.5Q280,457 280,420Q280,345 332.5,292.5Q385,240 460,240Q529,240 580,285.5Q631,331 639,400L558,400Q551,365 523.5,342.5Q496,320 460,320Q418,320 389,349Q360,378 360,420Q360,440 368,459.5Q376,479 391,494L445,548Q459,562 467.5,578.5Q476,595 482,612Q487,625 497,632.5Q507,640 520,640Q537,640 548.5,628.5Q560,617 560,600L640,600Q640,650 605.5,685Q571,720 520,720ZM540,560Q515,560 497.5,542.5Q480,525 480,500Q480,474 497.5,457Q515,440 540,440Q566,440 583,457Q600,474 600,500Q600,525 583,542.5Q566,560 540,560Z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_shortcutlist_search.xml b/packages/SystemUI/res/drawable/ic_shortcutlist_search.xml
index 1b12e74..0406f0e 100644
--- a/packages/SystemUI/res/drawable/ic_shortcutlist_search.xml
+++ b/packages/SystemUI/res/drawable/ic_shortcutlist_search.xml
@@ -14,12 +14,15 @@
   limitations under the License
   -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
         android:width="24dp"
         android:height="24dp"
         android:viewportWidth="48"
         android:viewportHeight="48"
-        android:tint="?android:attr/textColorSecondary">
+        android:tint="?androidprv:attr/materialColorOnSurfaceVariant">
     <path
         android:fillColor="@android:color/white"
+        android:strokeColor="@android:color/white"
+        android:strokeWidth="2"
         android:pathData="M39.8,41.95 L26.65,28.8Q25.15,30.1 23.15,30.825Q21.15,31.55 18.9,31.55Q13.5,31.55 9.75,27.8Q6,24.05 6,18.75Q6,13.45 9.75,9.7Q13.5,5.95 18.85,5.95Q24.15,5.95 27.875,9.7Q31.6,13.45 31.6,18.75Q31.6,20.9 30.9,22.9Q30.2,24.9 28.8,26.65L42,39.75ZM18.85,28.55Q22.9,28.55 25.75,25.675Q28.6,22.8 28.6,18.75Q28.6,14.7 25.75,11.825Q22.9,8.95 18.85,8.95Q14.75,8.95 11.875,11.825Q9,14.7 9,18.75Q9,22.8 11.875,25.675Q14.75,28.55 18.85,28.55Z"/>
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/notification_material_bg.xml b/packages/SystemUI/res/drawable/notification_material_bg.xml
index 3f903ae..715be07 100644
--- a/packages/SystemUI/res/drawable/notification_material_bg.xml
+++ b/packages/SystemUI/res/drawable/notification_material_bg.xml
@@ -28,4 +28,10 @@
             <solid android:color="@color/notification_state_color_default" />
         </shape>
     </item>
+    <item android:id="@+id/notification_focus_overlay">
+        <shape>
+            <stroke android:width="@dimen/notification_focus_stroke_width"
+                android:color="@color/notification_focus_overlay_color"/>
+        </shape>
+    </item>
 </layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/shelf_action_chip_background.xml b/packages/SystemUI/res/drawable/shelf_action_chip_background.xml
new file mode 100644
index 0000000..63600be
--- /dev/null
+++ b/packages/SystemUI/res/drawable/shelf_action_chip_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<ripple
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:color="@color/overlay_button_ripple">
+    <item android:id="@android:id/background">
+        <shape android:shape="rectangle">
+            <solid android:color="?androidprv:attr/materialColorSecondary"/>
+            <corners android:radius="10000dp"/>  <!-- fully-rounded radius -->
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/SystemUI/res/drawable/shelf_action_chip_container_background.xml b/packages/SystemUI/res/drawable/shelf_action_chip_container_background.xml
new file mode 100644
index 0000000..bb8cece
--- /dev/null
+++ b/packages/SystemUI/res/drawable/shelf_action_chip_container_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<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/materialColorSurfaceBright"/>
+    <corners android:radius="10000dp"/>  <!-- fully-rounded radius -->
+</shape>
diff --git a/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml b/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml
new file mode 100644
index 0000000..a5b44e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/shelf_action_chip_divider.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<shape xmlns:android = "http://schemas.android.com/apk/res/android">
+    <size
+        android:width = "@dimen/overlay_action_chip_margin_start"
+        android:height = "0dp"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/shelf_action_container_clipping_shape.xml b/packages/SystemUI/res/drawable/shelf_action_container_clipping_shape.xml
new file mode 100644
index 0000000..76779f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/shelf_action_container_clipping_shape.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <!-- We don't actually draw anything, just expressing the shape for clipping. -->
+    <solid android:color="#0000"/>
+    <corners android:radius="10000dp"/>  <!-- fully-rounded radius -->
+</shape>
diff --git a/packages/SystemUI/res/drawable/shortcut_button_colored.xml b/packages/SystemUI/res/drawable/shortcut_button_colored.xml
index bf90853..2e2d9b9 100644
--- a/packages/SystemUI/res/drawable/shortcut_button_colored.xml
+++ b/packages/SystemUI/res/drawable/shortcut_button_colored.xml
@@ -21,7 +21,7 @@
         android:color="?android:attr/colorControlHighlight">
         <item>
             <shape android:shape="rectangle">
-                <corners android:radius="16dp"/>
+              <corners android:radius="@dimen/ksh_button_corner_radius"/>
                 <solid android:color="?androidprv:attr/materialColorSurfaceBright"/>
             </shape>
         </item>
diff --git a/packages/SystemUI/res/drawable/shortcut_button_focus_colored.xml b/packages/SystemUI/res/drawable/shortcut_button_focus_colored.xml
index f692ed97..5b88bb9 100644
--- a/packages/SystemUI/res/drawable/shortcut_button_focus_colored.xml
+++ b/packages/SystemUI/res/drawable/shortcut_button_focus_colored.xml
@@ -21,7 +21,7 @@
         android:color="?android:attr/colorControlHighlight">
         <item>
             <shape android:shape="rectangle">
-                <corners android:radius="16dp"/>
+              <corners android:radius="@dimen/ksh_button_corner_radius"/>
                 <solid android:color="?androidprv:attr/materialColorPrimary"/>
             </shape>
         </item>
diff --git a/packages/SystemUI/res/drawable/shortcut_dialog_bg.xml b/packages/SystemUI/res/drawable/shortcut_dialog_bg.xml
index 6ce3eae..aa0b268 100644
--- a/packages/SystemUI/res/drawable/shortcut_dialog_bg.xml
+++ b/packages/SystemUI/res/drawable/shortcut_dialog_bg.xml
@@ -17,8 +17,8 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
     <solid android:color="?android:attr/colorBackground"/>
-    <corners android:topLeftRadius="16dp"
-             android:topRightRadius="16dp"
+    <corners android:topLeftRadius="@dimen/ksh_dialog_top_corner_radius"
+             android:topRightRadius="@dimen/ksh_dialog_top_corner_radius"
              android:bottomLeftRadius="0dp"
              android:bottomRightRadius="0dp"/>
-</shape>
\ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/drawable/shortcut_search_background.xml b/packages/SystemUI/res/drawable/shortcut_search_background.xml
index 66fc191..d6847f0 100644
--- a/packages/SystemUI/res/drawable/shortcut_search_background.xml
+++ b/packages/SystemUI/res/drawable/shortcut_search_background.xml
@@ -19,8 +19,8 @@
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
     <item>
         <shape android:shape="rectangle">
-            <solid android:color="?androidprv:attr/colorSurface" />
-            <corners android:radius="24dp" />
+            <solid android:color="?androidprv:attr/materialColorSurfaceBright" />
+            <corners android:radius="@dimen/ksh_search_box_corner_radius" />
         </shape>
     </item>
-</layer-list>
\ No newline at end of file
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/shortcut_search_cancel_button.xml b/packages/SystemUI/res/drawable/shortcut_search_cancel_button.xml
index 6c4d4fb..2675906 100644
--- a/packages/SystemUI/res/drawable/shortcut_search_cancel_button.xml
+++ b/packages/SystemUI/res/drawable/shortcut_search_cancel_button.xml
@@ -20,7 +20,7 @@
     <shape android:shape="oval">
       <size android:width="24dp"
         android:height="24dp" />
-      <solid android:color="?androidprv:attr/colorSurface"/>
+      <solid android:color="?androidprv:attr/materialColorSurfaceBright"/>
     </shape>
   </item>
 </ripple>
diff --git a/packages/SystemUI/res/drawable/tv_volume_row_seek_thumb.xml b/packages/SystemUI/res/drawable/tv_volume_row_seek_thumb.xml
index 3c31861..a706c65 100644
--- a/packages/SystemUI/res/drawable/tv_volume_row_seek_thumb.xml
+++ b/packages/SystemUI/res/drawable/tv_volume_row_seek_thumb.xml
@@ -19,9 +19,4 @@
     <solid android:color="@color/tv_volume_dialog_accent" />
     <size android:width="@dimen/tv_volume_seek_bar_thumb_diameter"
           android:height="@dimen/tv_volume_seek_bar_thumb_diameter" />
-    <stroke android:width="@dimen/tv_volume_seek_bar_thumb_focus_ring_width"
-            android:color="@color/tv_volume_dialog_seek_thumb_focus_ring"/>
-    <item name="android:shadowColor">@color/tv_volume_dialog_seek_thumb_shadow</item>
-    <item name="android:shadowRadius">@dimen/tv_volume_seek_bar_thumb_shadow_radius</item>
-    <item name="android:shadowDy">@dimen/tv_volume_seek_bar_thumb_shadow_dy</item>
 </shape>
diff --git a/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml
index 1777bdf..dabfe9d 100644
--- a/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml
@@ -39,7 +39,6 @@
         android:layout_height="wrap_content"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="0.8"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         tools:srcCompat="@tools:sample/avatars" />
@@ -60,11 +59,12 @@
         android:id="@+id/scrollView"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        android:fillViewport="true"
-        android:padding="24dp"
-        app:layout_constrainedHeight="true"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toTopOf="@+id/buttonBarrier"
+        android:paddingBottom="16dp"
+        android:paddingLeft="24dp"
+        android:paddingRight="12dp"
+        android:paddingTop="24dp"
+        android:fadeScrollbars="false"
+        app:layout_constraintBottom_toTopOf="@+id/button_bar"
         app:layout_constraintEnd_toStartOf="@+id/midGuideline"
         app:layout_constraintStart_toStartOf="@id/leftGuideline"
         app:layout_constraintTop_toTopOf="@+id/topGuideline">
@@ -91,7 +91,7 @@
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:textAlignment="viewStart"
-                android:paddingLeft="8dp"
+                android:paddingLeft="16dp"
                 app:layout_constraintBottom_toBottomOf="@+id/logo"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toEndOf="@+id/logo"
@@ -119,7 +119,7 @@
                 style="@style/TextAppearance.AuthCredential.Subtitle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="12dp"
+                android:layout_marginTop="16dp"
                 android:gravity="@integer/biometric_dialog_text_gravity"
                 android:paddingHorizontal="0dp"
                 android:textAlignment="viewStart"
@@ -133,6 +133,7 @@
                 android:id="@+id/customized_view_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="24dp"
                 android:gravity="center_vertical"
                 android:orientation="vertical"
                 android:visibility="gone"
@@ -148,6 +149,7 @@
                 style="@style/TextAppearance.AuthCredential.Description"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="24dp"
                 android:gravity="@integer/biometric_dialog_text_gravity"
                 android:paddingHorizontal="0dp"
                 android:textAlignment="viewStart"
@@ -179,7 +181,7 @@
         android:fadingEdge="horizontal"
         android:gravity="center_horizontal"
         android:scrollHorizontally="true"
-        app:layout_constraintBottom_toTopOf="@+id/buttonBarrier"
+        app:layout_constraintBottom_toTopOf="@+id/button_bar"
         app:layout_constraintEnd_toEndOf="@+id/biometric_icon"
         app:layout_constraintStart_toStartOf="@+id/biometric_icon"
         app:layout_constraintTop_toBottomOf="@+id/biometric_icon"
@@ -189,7 +191,7 @@
         android:id="@+id/button_bar"
         layout="@layout/biometric_prompt_button_bar"
         android:layout_width="0dp"
-        android:layout_height="0dp"
+        android:layout_height="wrap_content"
         app:layout_constraintBottom_toTopOf="@id/bottomGuideline"
         app:layout_constraintEnd_toEndOf="@id/scrollView"
         app:layout_constraintStart_toStartOf="@id/scrollView"
@@ -204,14 +206,6 @@
         app:barrierDirection="top"
         app:constraint_referenced_ids="scrollView" />
 
-    <androidx.constraintlayout.widget.Barrier
-        android:id="@+id/buttonBarrier"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        app:barrierAllowsGoneWidgets="false"
-        app:barrierDirection="top"
-        app:constraint_referenced_ids="button_bar" />
-
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/leftGuideline"
         android:layout_width="wrap_content"
@@ -238,13 +232,13 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
-        app:layout_constraintGuide_end="@dimen/biometric_dialog_border_padding" />
+        app:layout_constraintGuide_end="40dp" />
 
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/topGuideline"
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:orientation="horizontal"
-        app:layout_constraintGuide_begin="@dimen/biometric_dialog_border_padding" />
+        app:layout_constraintGuide_begin="0dp" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml
index 8b886a7..240abab 100644
--- a/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout-sw600dp/biometric_prompt_constraint_layout.xml
@@ -29,28 +29,31 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@+id/rightGuideline"
         app:layout_constraintStart_toStartOf="@+id/leftGuideline"
-        app:layout_constraintTop_toTopOf="@+id/topBarrier" />
+        app:layout_constraintTop_toTopOf="@+id/topBarrier"
+        app:layout_constraintWidth_max="640dp" />
 
     <include
-        layout="@layout/biometric_prompt_button_bar"
         android:id="@+id/button_bar"
+        layout="@layout/biometric_prompt_button_bar"
         android:layout_width="0dp"
-        android:layout_height="match_parent"
-        app:layout_constraintBottom_toTopOf="@id/bottomGuideline"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="40dp"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="@id/panel"
-        app:layout_constraintStart_toStartOf="@id/panel"/>
+        app:layout_constraintStart_toStartOf="@id/panel" />
 
     <ScrollView
         android:id="@+id/scrollView"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
+        android:fadeScrollbars="false"
         android:fillViewport="true"
-        android:paddingBottom="36dp"
-        android:paddingHorizontal="24dp"
+        android:paddingBottom="32dp"
+        android:paddingHorizontal="32dp"
         android:paddingTop="24dp"
         app:layout_constrainedHeight="true"
         app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toTopOf="@+id/biometric_icon"
+        app:layout_constraintBottom_toTopOf="@+id/scrollBarrier"
         app:layout_constraintEnd_toEndOf="@id/panel"
         app:layout_constraintStart_toStartOf="@id/panel"
         app:layout_constraintTop_toTopOf="@+id/topGuideline"
@@ -63,10 +66,10 @@
 
             <ImageView
                 android:id="@+id/logo"
-                android:contentDescription="@string/biometric_dialog_logo"
                 android:layout_width="@dimen/biometric_prompt_logo_size"
                 android:layout_height="@dimen/biometric_prompt_logo_size"
                 android:layout_gravity="center"
+                android:contentDescription="@string/biometric_dialog_logo"
                 android:scaleType="fitXY"
                 android:visibility="visible"
                 app:layout_constraintBottom_toTopOf="@+id/logo_description"
@@ -79,6 +82,7 @@
                 style="@style/TextAppearance.AuthCredential.LogoDescription"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:paddingTop="16dp"
                 app:layout_constraintBottom_toTopOf="@+id/title"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
@@ -114,6 +118,7 @@
                 android:layout_height="wrap_content"
                 android:gravity="center_vertical"
                 android:orientation="vertical"
+                android:paddingTop="24dp"
                 android:visibility="gone"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
@@ -126,6 +131,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:gravity="@integer/biometric_dialog_text_gravity"
+                android:paddingTop="16dp"
+                android:textAlignment="viewStart"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
@@ -153,7 +160,7 @@
         android:fadingEdge="horizontal"
         android:gravity="center_horizontal"
         android:scrollHorizontally="true"
-        app:layout_constraintBottom_toTopOf="@+id/buttonBarrier"
+        app:layout_constraintBottom_toTopOf="@+id/button_bar"
         app:layout_constraintEnd_toEndOf="@+id/panel"
         app:layout_constraintStart_toStartOf="@+id/panel"
         app:layout_constraintTop_toBottomOf="@+id/biometric_icon"
@@ -172,12 +179,12 @@
 
     <!-- Try Again Button -->
     <androidx.constraintlayout.widget.Barrier
-        android:id="@+id/buttonBarrier"
+        android:id="@+id/scrollBarrier"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         app:barrierAllowsGoneWidgets="false"
         app:barrierDirection="top"
-        app:constraint_referenced_ids="button_bar" />
+        app:constraint_referenced_ids="biometric_icon, button_bar" />
 
     <!-- Guidelines for setting panel border -->
     <androidx.constraintlayout.widget.Guideline
@@ -199,14 +206,14 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
-        app:layout_constraintGuide_end="@dimen/biometric_dialog_border_padding" />
+        app:layout_constraintGuide_end="40dp" />
 
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/topGuideline"
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:orientation="horizontal"
-        app:layout_constraintGuide_percent="0.25171" />
+        app:layout_constraintGuide_begin="56dp" />
 
     <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper
         android:id="@+id/biometric_icon"
@@ -216,7 +223,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_bias="0.8"
+        app:layout_constraintVertical_bias="1.0"
         tools:srcCompat="@tools:sample/avatars" />
 
     <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper
diff --git a/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml b/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml
new file mode 100644
index 0000000..292e496
--- /dev/null
+++ b/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/shortcut_helper_sheet_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:id="@+id/shortcut_helper_sheet"
+        style="@style/Widget.Material3.BottomSheet"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
+
+        <!-- Drag handle for accessibility -->
+        <com.google.android.material.bottomsheet.BottomSheetDragHandleView
+            android:id="@+id/drag_handle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:textAppearance="?textAppearanceDisplayLarge"
+            android:background="?colorTertiaryContainer"
+            android:text="Shortcut Helper Content" />
+    </LinearLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/packages/SystemUI/res/layout/auth_biometric_icon.xml b/packages/SystemUI/res/layout/auth_biometric_icon.xml
deleted file mode 100644
index b2df63d..0000000
--- a/packages/SystemUI/res/layout/auth_biometric_icon.xml
+++ /dev/null
@@ -1,26 +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.
-  -->
-
-
-<com.airbnb.lottie.LottieAnimationView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/biometric_icon"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:contentDescription="@null"
-    android:scaleType="fitXY"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/biometric_prompt_button_bar.xml b/packages/SystemUI/res/layout/biometric_prompt_button_bar.xml
index 810c7433..4d2310a 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_button_bar.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_button_bar.xml
@@ -17,12 +17,13 @@
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:theme="@style/Theme.SystemUI.Dialog"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <!-- Negative Button, reserved for app -->
     <Button
         android:id="@+id/button_negative"
-        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+        style="@style/Widget.Dialog.Button.BorderButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
@@ -36,7 +37,7 @@
     <!-- Cancel Button, replaces negative button when biometric is accepted -->
     <Button
         android:id="@+id/button_cancel"
-        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+        style="@style/Widget.Dialog.Button.BorderButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
@@ -49,7 +50,7 @@
     <!-- "Use Credential" Button, replaces if device credential is allowed -->
     <Button
         android:id="@+id/button_use_credential"
-        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+        style="@style/Widget.Dialog.Button.BorderButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
@@ -61,7 +62,7 @@
     <!-- Positive Button -->
     <Button
         android:id="@+id/button_confirm"
-        style="@*android:style/Widget.DeviceDefault.Button.Colored"
+        style="@style/Widget.Dialog.Button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
@@ -76,7 +77,7 @@
     <!-- Try Again Button -->
     <Button
         android:id="@+id/button_try_again"
-        style="@*android:style/Widget.DeviceDefault.Button.Colored"
+        style="@style/Widget.Dialog.Button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
diff --git a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
index 74bf318..8e3cf4d 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
@@ -35,24 +35,26 @@
         android:id="@+id/button_bar"
         layout="@layout/biometric_prompt_button_bar"
         android:layout_width="0dp"
-        android:layout_height="match_parent"
-        app:layout_constraintBottom_toTopOf="@id/bottomGuideline"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="40dp"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="@id/panel"
         app:layout_constraintStart_toStartOf="@id/panel" />
 
     <ScrollView
         android:id="@+id/scrollView"
-        android:layout_width="match_parent"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:fillViewport="true"
+        android:fadeScrollbars="false"
         android:paddingBottom="36dp"
         android:paddingHorizontal="24dp"
         android:paddingTop="24dp"
         app:layout_constrainedHeight="true"
         app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toTopOf="@+id/biometric_icon"
-        app:layout_constraintEnd_toEndOf="@id/rightGuideline"
-        app:layout_constraintStart_toStartOf="@id/leftGuideline"
+        app:layout_constraintBottom_toTopOf="@+id/scrollBarrier"
+        app:layout_constraintEnd_toEndOf="@id/panel"
+        app:layout_constraintStart_toStartOf="@id/panel"
         app:layout_constraintTop_toTopOf="@+id/topGuideline"
         app:layout_constraintVertical_bias="1.0">
 
@@ -68,6 +70,7 @@
                 android:layout_height="@dimen/biometric_prompt_logo_size"
                 android:layout_gravity="center"
                 android:scaleType="fitXY"
+                android:importantForAccessibility="no"
                 app:layout_constraintBottom_toTopOf="@+id/logo_description"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
@@ -79,6 +82,7 @@
                 style="@style/TextAppearance.AuthCredential.LogoDescription"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:paddingTop="8dp"
                 app:layout_constraintBottom_toTopOf="@+id/title"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
@@ -114,8 +118,8 @@
                 android:layout_height="wrap_content"
                 android:gravity="center_vertical"
                 android:orientation="vertical"
-                android:visibility="gone"
                 android:paddingTop="24dp"
+                android:visibility="gone"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
@@ -127,7 +131,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:gravity="@integer/biometric_dialog_text_gravity"
-                android:paddingTop="24dp"
+                android:textAlignment="viewStart"
+                android:paddingTop="16dp"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
@@ -154,7 +159,7 @@
         android:fadingEdge="horizontal"
         android:gravity="center_horizontal"
         android:scrollHorizontally="true"
-        app:layout_constraintBottom_toTopOf="@+id/buttonBarrier"
+        app:layout_constraintBottom_toTopOf="@+id/button_bar"
         app:layout_constraintEnd_toEndOf="@+id/panel"
         app:layout_constraintStart_toStartOf="@+id/panel"
         app:layout_constraintTop_toBottomOf="@+id/biometric_icon"
@@ -169,12 +174,12 @@
         app:constraint_referenced_ids="scrollView" />
 
     <androidx.constraintlayout.widget.Barrier
-        android:id="@+id/buttonBarrier"
+        android:id="@+id/scrollBarrier"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         app:barrierAllowsGoneWidgets="false"
         app:barrierDirection="top"
-        app:constraint_referenced_ids="button_bar" />
+        app:constraint_referenced_ids="biometric_icon, button_bar" />
 
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/leftGuideline"
@@ -195,14 +200,14 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
-        app:layout_constraintGuide_end="@dimen/biometric_dialog_border_padding" />
+        app:layout_constraintGuide_end="40dp" />
 
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/topGuideline"
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:orientation="horizontal"
-        app:layout_constraintGuide_percent="0.25" />
+        app:layout_constraintGuide_begin="119dp" />
 
     <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper
         android:id="@+id/biometric_icon"
@@ -212,7 +217,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_bias="0.8"
+        app:layout_constraintVertical_bias="1.0"
         tools:srcCompat="@tools:sample/avatars" />
 
     <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper
diff --git a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
index 13355f3..76d10cc 100644
--- a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
@@ -47,7 +47,7 @@
         android:layout_marginBottom="@dimen/bluetooth_dialog_layout_margin"
         android:ellipsize="end"
         android:gravity="center_vertical|center_horizontal"
-        android:maxLines="1"
+        android:maxLines="2"
         android:text="@string/quick_settings_bluetooth_tile_subtitle"
         android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
         app:layout_constraintEnd_toEndOf="parent"
@@ -256,6 +256,24 @@
                 app:constraint_referenced_ids="pair_new_device_button,bluetooth_auto_on_toggle_info_text" />
 
             <Button
+                android:id="@+id/audio_sharing_button"
+                style="@style/Widget.Dialog.Button.BorderButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="9dp"
+                android:layout_marginBottom="@dimen/dialog_bottom_padding"
+                android:layout_marginEnd="@dimen/dialog_side_padding"
+                android:layout_marginStart="@dimen/dialog_side_padding"
+                android:ellipsize="end"
+                android:maxLines="1"
+                android:text="@string/quick_settings_bluetooth_audio_sharing_button"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/barrier"
+                app:layout_constraintVertical_bias="1"
+                android:visibility="gone" />
+
+            <Button
                 android:id="@+id/done_button"
                 style="@style/Widget.Dialog.Button"
                 android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index beb481a..b9ef88e 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -129,7 +129,7 @@
             android:id="@+id/hover_system_icons_container"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_gravity="right|center_vertical"
+            android:layout_gravity="end|center_vertical"
             android:gravity="center_vertical"
             android:paddingStart="@dimen/hover_system_icons_container_padding_start"
             android:paddingEnd="@dimen/hover_system_icons_container_padding_end"
diff --git a/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml b/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml
index a5cdaeb..8e1d0a5 100644
--- a/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml
@@ -17,6 +17,7 @@
 <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/root"
     style="@style/Widget.SliceView.Panel"
     android:layout_width="wrap_content"
@@ -26,9 +27,33 @@
         android:id="@+id/device_list"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/pair_new_device_button" />
+        app:layout_constraintBottom_toTopOf="@id/preset_spinner" />
+
+    <Spinner
+        android:id="@+id/preset_spinner"
+        style="@style/BluetoothTileDialog.Device"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/hearing_devices_preset_spinner_height"
+        android:layout_marginTop="@dimen/hearing_devices_preset_spinner_margin"
+        android:layout_marginBottom="@dimen/hearing_devices_preset_spinner_margin"
+        android:gravity="center_vertical"
+        android:background="@drawable/hearing_devices_preset_spinner_background"
+        android:popupBackground="@drawable/hearing_devices_preset_spinner_popup_background"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/device_list"
+        app:layout_constraintBottom_toTopOf="@id/pair_new_device_button"
+        android:visibility="gone"/>
+
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/device_barrier"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:barrierDirection="bottom"
+        app:constraint_referenced_ids="device_list,preset_spinner" />
 
     <Button
         android:id="@+id/pair_new_device_button"
@@ -41,7 +66,7 @@
         android:contentDescription="@string/accessibility_hearing_device_pair_new_device"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/device_list"
+        app:layout_constraintTop_toBottomOf="@id/device_barrier"
         android:drawableStart="@drawable/ic_add"
         android:drawablePadding="20dp"
         android:drawableTint="?android:attr/textColorPrimary"
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
index a005100..5ab2327 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -15,13 +15,14 @@
   ~ limitations under the License
   -->
 <com.android.systemui.statusbar.KeyboardShortcutAppItemLayout
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:orientation="horizontal"
         android:background="@drawable/list_item_background"
         android:focusable="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:minHeight="48dp"
+        android:minHeight="@dimen/ksh_app_item_minimum_height"
         android:paddingBottom="8dp">
     <ImageView
             android:id="@+id/keyboard_shortcuts_icon"
@@ -39,7 +40,8 @@
             android:layout_height="wrap_content"
             android:paddingEnd="12dp"
             android:paddingBottom="4dp"
-            android:textColor="?android:attr/textColorPrimary"
+            android:textColor="?androidprv:attr/materialColorOnSurface"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="16sp"
             android:maxLines="5"
             android:singleLine="false"
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_category_short_separator.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_short_separator.xml
index 530e46e..76e5b12 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_category_short_separator.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_short_separator.xml
@@ -15,6 +15,6 @@
   limitations under the License
   -->
 <View xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_marginTop="8dp"
-      android:layout_marginBottom="0dp"
+      android:layout_marginTop="@dimen/ksh_category_separator_margin"
+      android:layout_marginBottom="@dimen/ksh_category_separator_margin"
       style="@style/ShortcutHorizontalDivider" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
index 4f100f6..6e7fde6 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
@@ -16,10 +16,12 @@
   ~ limitations under the License
   -->
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
+          android:textAppearance="?android:attr/textAppearanceMedium"
           android:textSize="14sp"
-          android:fontFamily="sans-serif-medium"
+          android:textColor="?androidprv:attr/materialColorPrimary"
           android:importantForAccessibility="yes"
           android:paddingTop="20dp"
           android:paddingBottom="10dp"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_search_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_search_view.xml
index f6042e4..2cfd644 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_search_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_search_view.xml
@@ -16,15 +16,21 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:background="@drawable/shortcut_dialog_bg"
     android:layout_width="@dimen/ksh_layout_width"
     android:layout_height="wrap_content"
     android:orientation="vertical">
+
+    <com.google.android.material.bottomsheet.BottomSheetDragHandleView
+        android:id="@+id/drag_handle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+
     <TextView
         android:id="@+id/shortcut_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="40dp"
         android:layout_gravity="center_horizontal"
         android:textAppearance="?android:attr/textAppearanceLarge"
         android:textColor="?android:attr/textColorPrimary"
@@ -39,44 +45,47 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="24dp"
             android:layout_marginBottom="24dp"
-            android:layout_marginStart="49dp"
-            android:layout_marginEnd="49dp"
+            android:layout_marginStart="@dimen/ksh_container_horizontal_margin"
+            android:layout_marginEnd="@dimen/ksh_container_horizontal_margin"
             android:padding="16dp"
             android:background="@drawable/shortcut_search_background"
             android:drawableStart="@drawable/ic_shortcutlist_search"
             android:drawablePadding="15dp"
             android:singleLine="true"
-            android:textColor="?android:attr/textColorPrimary"
+            android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
             android:inputType="text"
             android:textDirection="locale"
             android:textAlignment="viewStart"
             android:hint="@string/keyboard_shortcut_search_list_hint"
-            android:textColorHint="?android:attr/textColorTertiary" />
+            android:textAppearance="@android:style/TextAppearance.Material"
+            android:textSize="16sp"
+            android:textColorHint="?androidprv:attr/materialColorOutline" />
 
         <ImageButton
             android:id="@+id/keyboard_shortcuts_search_cancel"
             android:layout_gravity="center_vertical|end"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginEnd="49dp"
+            android:layout_marginEnd="@dimen/ksh_container_horizontal_margin"
             android:padding="16dp"
             android:contentDescription="@string/keyboard_shortcut_clear_text"
             android:src="@drawable/ic_shortcutlist_search_button_cancel"
             android:background="@drawable/shortcut_search_cancel_button"
             style="@android:style/Widget.Material.Button.Borderless.Small"
-            android:pointerIcon="arrow" />
+            android:pointerIcon="arrow"
+            android:visibility="gone" />
     </FrameLayout>
 
     <HorizontalScrollView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginStart="49dp"
+        android:layout_marginStart="@dimen/ksh_container_horizontal_margin"
         android:layout_marginEnd="0dp"
         android:scrollbars="none">
         <LinearLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:gravity="center_vertical"
+            android:layout_gravity="center_vertical"
             android:orientation="horizontal">
             <Button
                 android:id="@+id/shortcut_system"
@@ -113,29 +122,29 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="50dp"
-        android:layout_marginStart="49dp"
-        android:layout_marginEnd="49dp"
+        android:layout_marginStart="@dimen/ksh_container_horizontal_margin"
+        android:layout_marginEnd="@dimen/ksh_container_horizontal_margin"
         android:layout_gravity="center_horizontal"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textColor="?android:attr/textColorPrimary"
         android:text="@string/keyboard_shortcut_search_list_no_result"/>
 
-    <ScrollView
+    <androidx.core.widget.NestedScrollView
         android:id="@+id/keyboard_shortcuts_scroll_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="16dp"
-        android:layout_marginStart="49dp"
-        android:layout_marginEnd="49dp"
+        android:layout_marginStart="@dimen/ksh_container_horizontal_margin"
+        android:layout_marginEnd="@dimen/ksh_container_horizontal_margin"
         android:overScrollMode="never"
-        android:layout_marginBottom="16dp"
+        android:clipToPadding="false"
         android:scrollbars="none">
         <LinearLayout
             android:id="@+id/keyboard_shortcuts_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"/>
-    </ScrollView>
+    </androidx.core.widget.NestedScrollView>
     <!-- Required for stretching to full available height when the items in the scroll view
          occupy less space then the full height -->
     <View
diff --git a/packages/SystemUI/res/layout/media_carousel.xml b/packages/SystemUI/res/layout/media_carousel.xml
index 825ece85..ffe269a 100644
--- a/packages/SystemUI/res/layout/media_carousel.xml
+++ b/packages/SystemUI/res/layout/media_carousel.xml
@@ -19,7 +19,7 @@
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="match_parent"
     android:clipChildren="false"
     android:clipToPadding="false"
     android:forceHasOverlappingRendering="false"
@@ -27,7 +27,7 @@
     <com.android.systemui.media.controls.ui.view.MediaScrollView
         android:id="@+id/media_carousel_scroller"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
         android:scrollbars="none"
         android:clipChildren="false"
         android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 1eb05bf..e3c5a7d 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -36,8 +36,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:background="@android:color/transparent"
-            android:focusable="true"
-            android:accessibilityTraversalBefore="@android:id/edit"
+            android:focusable="false"
+            android:importantForAccessibility="yes"
             android:clipToPadding="false"
             android:clipChildren="false">
 
diff --git a/packages/SystemUI/res/layout/record_issue_dialog.xml b/packages/SystemUI/res/layout/record_issue_dialog.xml
index 53ad9f1..30d7b0a 100644
--- a/packages/SystemUI/res/layout/record_issue_dialog.xml
+++ b/packages/SystemUI/res/layout/record_issue_dialog.xml
@@ -54,6 +54,7 @@
             android:layout_weight="0"
             android:src="@drawable/ic_screenrecord"
             app:tint="?androidprv:attr/materialColorOnSurface"
+            android:importantForAccessibility="no"
             android:layout_gravity="center"
             android:layout_marginEnd="@dimen/screenrecord_option_padding" />
 
@@ -78,4 +79,44 @@
             android:layout_weight="0"
             android:contentDescription="@string/quick_settings_screen_record_label" />
     </LinearLayout>
+
+    <!-- Bug Report Switch -->
+    <LinearLayout
+        android:id="@+id/bugreport_switch_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/qqs_layout_margin_top"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:layout_width="@dimen/screenrecord_option_icon_size"
+            android:layout_height="@dimen/screenrecord_option_icon_size"
+            android:layout_weight="0"
+            android:src="@drawable/ic_bugreport"
+            app:tint="?androidprv:attr/materialColorOnSurface"
+            android:importantForAccessibility="no"
+            android:layout_gravity="center"
+            android:layout_marginEnd="@dimen/screenrecord_option_padding" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:minHeight="@dimen/screenrecord_option_icon_size"
+            android:layout_weight="1"
+            android:layout_gravity="fill_vertical"
+            android:gravity="center"
+            android:text="@string/qs_record_issue_bug_report"
+            android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
+            android:importantForAccessibility="no"/>
+
+        <Switch
+            android:id="@+id/bugreport_switch"
+            android:layout_width="wrap_content"
+            android:minHeight="@dimen/screenrecord_option_icon_size"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:layout_gravity="fill_vertical"
+            android:layout_weight="0"
+            android:contentDescription="@string/qs_record_issue_bug_report" />
+    </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml
index c988b4a..26d3f43 100644
--- a/packages/SystemUI/res/layout/screenshot_shelf.xml
+++ b/packages/SystemUI/res/layout/screenshot_shelf.xml
@@ -20,47 +20,37 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    <ImageView
+    <FrameLayout
         android:id="@+id/actions_container_background"
         android:visibility="gone"
-        android:layout_height="0dp"
-        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
         android:elevation="4dp"
-        android:background="@drawable/action_chip_container_background"
-        android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
+        android:background="@drawable/shelf_action_chip_container_background"
+        android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal"
         android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="@+id/actions_container"
-        app:layout_constraintEnd_toEndOf="@+id/actions_container"
-        app:layout_constraintBottom_toTopOf="@id/guideline"/>
-    <HorizontalScrollView
-        android:id="@+id/actions_container"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="@dimen/overlay_action_container_margin_horizontal"
-        android:paddingHorizontal="@dimen/overlay_action_container_padding_end"
-        android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
-        android:elevation="4dp"
-        android:scrollbars="none"
-        app:layout_constraintHorizontal_bias="0"
-        app:layout_constraintWidth_percent="1.0"
-        app:layout_constraintWidth_max="wrap"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintBottom_toBottomOf="@id/actions_container_background">
-        <LinearLayout
-            android:id="@+id/screenshot_actions"
+        app:layout_constraintBottom_toTopOf="@id/guideline"
+        >
+        <HorizontalScrollView
+            android:id="@+id/actions_container"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content">
-            <include layout="@layout/overlay_action_chip"
-                     android:id="@+id/screenshot_share_chip"/>
-            <include layout="@layout/overlay_action_chip"
-                     android:id="@+id/screenshot_edit_chip"/>
-            <include layout="@layout/overlay_action_chip"
-                     android:id="@+id/screenshot_scroll_chip"
-                     android:visibility="gone" />
-        </LinearLayout>
-    </HorizontalScrollView>
+            android:layout_height="wrap_content"
+            android:layout_marginVertical="@dimen/overlay_action_container_padding_vertical"
+            android:layout_marginHorizontal="@dimen/overlay_action_chip_margin_start"
+            android:background="@drawable/shelf_action_container_clipping_shape"
+            android:clipToOutline="true"
+            android:scrollbars="none">
+            <LinearLayout
+                android:id="@+id/screenshot_actions"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:showDividers="middle"
+                android:divider="@drawable/shelf_action_chip_divider"
+                android:animateLayoutChanges="true"
+                />
+        </HorizontalScrollView>
+    </FrameLayout>
     <View
         android:id="@+id/screenshot_preview_border"
         android:layout_width="0dp"
@@ -74,7 +64,7 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="@id/screenshot_preview"
         app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
-        app:layout_constraintBottom_toTopOf="@id/actions_container"/>
+        app:layout_constraintBottom_toTopOf="@id/actions_container_background"/>
     <ImageView
         android:id="@+id/screenshot_preview"
         android:layout_width="@dimen/overlay_x_scale"
@@ -157,4 +147,11 @@
         <include layout="@layout/screenshot_work_profile_first_run" />
         <include layout="@layout/screenshot_detection_notice" />
     </FrameLayout>
+    <ImageView
+        android:id="@+id/screenshot_flash"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        android:elevation="12dp"
+        android:src="@android:color/white"/>
 </com.android.systemui.screenshot.ui.ScreenshotShelfView>
diff --git a/packages/SystemUI/res/layout/shelf_action_chip.xml b/packages/SystemUI/res/layout/shelf_action_chip.xml
new file mode 100644
index 0000000..c7606e4
--- /dev/null
+++ b/packages/SystemUI/res/layout/shelf_action_chip.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:theme="@style/FloatingOverlay"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:paddingVertical="@dimen/overlay_action_chip_padding_vertical"
+    android:gravity="center"
+    android:background="@drawable/shelf_action_chip_background"
+    >
+    <ImageView
+        android:id="@+id/overlay_action_chip_icon"
+        android:tint="?androidprv:attr/materialColorOnSecondary"
+        android:layout_width="@dimen/overlay_action_chip_icon_size"
+        android:layout_height="@dimen/overlay_action_chip_icon_size"/>
+    <TextView
+        android:id="@+id/overlay_action_chip_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+        android:textSize="@dimen/overlay_action_chip_text_size"
+        android:textColor="?androidprv:attr/materialColorOnSecondary"/>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/volume_ringer_drawer.xml b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
index 9b1fa23..8f1e061 100644
--- a/packages/SystemUI/res/layout/volume_ringer_drawer.xml
+++ b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
@@ -67,8 +67,8 @@
                     android:layout_width="@dimen/volume_ringer_drawer_icon_size"
                     android:layout_height="@dimen/volume_ringer_drawer_icon_size"
                     android:layout_gravity="center"
-                    android:tint="?android:attr/textColorPrimary"
-                    android:src="@drawable/ic_volume_ringer_vibrate" />
+                    android:src="@drawable/ic_volume_ringer_vibrate"
+                    android:tint="?android:attr/textColorPrimary" />
 
             </FrameLayout>
 
@@ -76,6 +76,7 @@
                 android:id="@+id/volume_drawer_mute"
                 android:layout_width="@dimen/volume_ringer_drawer_item_size"
                 android:layout_height="@dimen/volume_ringer_drawer_item_size"
+                android:accessibilityTraversalAfter="@id/volume_drawer_vibrate"
                 android:contentDescription="@string/volume_ringer_hint_mute"
                 android:gravity="center">
 
@@ -84,8 +85,8 @@
                     android:layout_width="@dimen/volume_ringer_drawer_icon_size"
                     android:layout_height="@dimen/volume_ringer_drawer_icon_size"
                     android:layout_gravity="center"
-                    android:tint="?android:attr/textColorPrimary"
-                    android:src="@drawable/ic_speaker_mute" />
+                    android:src="@drawable/ic_speaker_mute"
+                    android:tint="?android:attr/textColorPrimary" />
 
             </FrameLayout>
 
@@ -93,6 +94,7 @@
                 android:id="@+id/volume_drawer_normal"
                 android:layout_width="@dimen/volume_ringer_drawer_item_size"
                 android:layout_height="@dimen/volume_ringer_drawer_item_size"
+                android:accessibilityTraversalAfter="@id/volume_drawer_mute"
                 android:contentDescription="@string/volume_ringer_hint_unmute"
                 android:gravity="center">
 
@@ -101,8 +103,8 @@
                     android:layout_width="@dimen/volume_ringer_drawer_icon_size"
                     android:layout_height="@dimen/volume_ringer_drawer_icon_size"
                     android:layout_gravity="center"
-                    android:tint="?android:attr/textColorPrimary"
-                    android:src="@drawable/ic_speaker_on" />
+                    android:src="@drawable/ic_speaker_on"
+                    android:tint="?android:attr/textColorPrimary" />
 
             </FrameLayout>
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 2027d16..63c6132 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -71,7 +71,7 @@
     <string name="usb_port_enabled" msgid="531823867664717018">"USB-poort is geaktiveer om laaiers en bykomstighede te bespeur"</string>
     <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_screenshot" msgid="2760267567509131654">"Skermskoot"</string>
     <string name="global_action_smart_lock_disabled" msgid="6286551337177954859">"Hou Ontsluit is gedeaktiveer"</string>
     <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>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kennisgewingskerm."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Vinnige instellings."</string>
     <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_lock_screen" msgid="409034672704273634">"Sluitskerm"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Werksluitskerm"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Maak toe"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"volkome stilte"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Sien alles"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gebruik Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Gekoppel"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Oudiodeling"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gestoor"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ontkoppel"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveer"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Skakel dit môre outomaties weer aan"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Kenmerke soos Kitsdeel, Kry My Toestel en toestelligging gebruik Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth sal môre om 05:00 aanskakel"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Kenmerke soos Kitsdeel en Kry My Toestel gebruik Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth sal môreoggend aanskakel"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Oudiodeling"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Deel tans oudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batterykrag"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Oudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Kopstuk"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Neem kwessie op"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Begin"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Foutverslag"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Watter deel van jou toestelervaring is geraak?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Kies soort kwessie"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skermopname"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standaard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hoog"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Gehoortoestelle"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Gehoortoestelle"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Bind nuwe toestel saam"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nuwe toestel saam te bind"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokkeer toestelmikrofoon?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokkeer toestelkamera?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans vinnig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Legstukke op sluitskerm"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swiep links om die gemeenskaplike tutoriaal te begin"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pasmaak"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Maak toe"</string>
@@ -448,14 +451,16 @@
     <string name="button_to_remove_widget" msgid="3948204829181214098">"Verwyder"</string>
     <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Voeg legstuk by"</string>
     <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Klaar"</string>
-    <!-- no translation found for label_for_button_in_empty_state_cta (7314975555382055823) -->
-    <skip />
-    <!-- no translation found for title_for_empty_state_cta (6161654421223450530) -->
-    <skip />
+    <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Voeg legstukke by"</string>
+    <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Kry kitstoegang tot jou gunstelingapplegstukke sonder om jou tablet te ontsluit."</string>
     <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Laat enige legstuk op die sluitskerm toe?"</string>
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Maak instellings oop"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Hervat werkapps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Hervat"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Maak legstukke op sluitskerm toe"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Legstukke op sluitskerm"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
@@ -747,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Wissel sleutelborduitleg"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"of"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Maak soeknavraag skoon"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortpaaie"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Kortpadsleutels"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Soek kortpaaie"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen kortpaaie gevind nie"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Stelsel"</string>
@@ -772,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Maak Assistent oop"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Sluit skerm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Maak ’n nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Verrig veelvuldige stelseltake"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Gaan by verdeelde skerm in met huidige app aan die regterkant"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Gaan by verdeelde skerm in met huidige app aan die linkerkant"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Verrigting van veelvuldige take"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gebruik verdeelde skerm met huidige app aan die regterkant"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gebruik verdeelde skerm met huidige app aan die linkerkant"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Skakel oor van verdeelde skerm na volskerm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skakel oor na app regs of onder terwyl jy verdeelde skerm gebruik"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skakel oor na app links of bo terwyl jy verdeelde skerm gebruik"</string>
@@ -895,12 +900,12 @@
     <string name="notification_channel_alerts" msgid="3385787053375150046">"Opletberigte"</string>
     <string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string>
     <string name="notification_channel_screenshot" msgid="7665814998932211997">"Skermkiekies"</string>
-    <string name="notification_channel_instant" msgid="7556135423486752680">"Kitsprogramme"</string>
+    <string name="notification_channel_instant" msgid="7556135423486752680">"Kitsapps"</string>
     <string name="notification_channel_setup" msgid="7660580986090760350">"Opstelling"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"Berging"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"Wenke"</string>
     <string name="notification_channel_accessibility" msgid="8956203986976245820">"Toeganklikheid"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"Kitsprogramme"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Kitsapps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> loop tans"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"Program is oopgemaak sonder dat dit geïnstalleer is."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Program is oopgemaak sonder dat dit geïnstalleer is. Tik om meer te wete te kom."</string>
@@ -1195,8 +1200,8 @@
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kies gebruiker"</string>
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app is aktief}other{# apps is aktief}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nuwe inligting"</string>
-    <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktiewe programme"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Hierdie programme is aktief en werk, selfs wanneer jy hulle nie gebruik nie. Dit verbeter hul funksies, maar beïnvloed dalk ook batterylewe."</string>
+    <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktiewe apps"</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Hierdie apps is aktief en werk, selfs wanneer jy hulle nie gebruik nie. Dit verbeter hul funksies, maar beïnvloed dalk ook batterylewe."</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Stop"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Gestop"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Klaar"</string>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index 8f0532e..1b4781d 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Af"</item>
     <item msgid="5137565285664080143">"Aan"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nie beskikbaar nie"</item>
+    <item msgid="3079622119444911877">"Af"</item>
+    <item msgid="3028994095749238254">"Aan"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index a3700f2..1c80547 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"የማሳወቂያ ጥላ።"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ፈጣን ቅንብሮች።"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ፈጣን ቅንብሮች እና የማሳወቂያ ጥላ።"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ማያ ገፅ ቆልፍ።"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ማያ ገጽ ቁልፍ"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"የስራ ማያ ገፅ ቁልፍ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ዝጋ"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ሙሉ ለሙሉ ፀጥታ"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ሁሉንም ይመልከቱ"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ብሉቱዝን ይጠቀሙ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ተገናኝቷል"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"የድምጽ ማጋራት"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ተቀምጧል"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ግንኙነትን አቋርጥ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ያግብሩ"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ነገ እንደገና በራስ-ሰር አስጀምር"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"እንደ ፈጣን ማጋራት፣ የእኔን መሣሪያ አግኝ እና የመሣሪያ አካባቢ ያሉ ባህሪያት ብሉቱዝን ይጠቀማሉ"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ብሉቱዝ ነገ ጠዋቱ 5 ሰዓት ላይ ይበራል"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"እንደ ፈጣን ማጋራት እና የእኔን መሣሪያ አግኝ ያሉ ባህሪዎች ብሉቱዝን ይጠቀማሉ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ብሉቱዝ ነገ ጠዋት ይበራል"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"የድምጽ ማጋራት"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ድምጽን በማጋራት ላይ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ባትሪ"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ኦዲዮ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ማዳመጫ"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ችግርን ቅዳ"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ጀምር"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"አቁም"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"የሳንካ ሪፖርት"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"የትኛው የመሣሪያዎ ተሞክሮ ክፍል ተጎድቷል?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"የችግሩን አይነት ይምረጡ"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"የማያ መቅረጫ"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"መካከለኛ"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ከፍተኛ"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"የመስሚያ መሣሪያዎች"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"የመስማት ችሎታ መሣሪያ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"አዲስ መሣሪያ ያጣምሩ"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"አዲስ መሣሪያ ለማጣመር ጠቅ ያድርጉ"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"የመሣሪያ ማይክሮፎን እገዳ ይነሳ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"የመሣሪያ ካሜራ እገዳ ይነሳ?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ምግብሮች በማያ ገጽ ቁልፍ ላይ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"የጋራ አጋዥ ሥልጠናውን ለመጀመር ወደ ግራ ያንሸራትቱ።"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"አብጅ"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"አሰናብት"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ቅንብሮችን ክፈት"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"የሥራ መተግበሪያዎች ከቆሙበት ይቀጥሉ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ከቆመበት ቀጥል"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ምግብሮችን በማያ ገጽ ቁልፍ ላይ ዝጋ"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ምግብሮች በማያ ገጽ ቁልፍ ላይ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ተጠቃሚ ቀይር"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ወደታች ተጎታች ምናሌ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"የቁልፍ ሰሌዳ ገጽታ ለውጥ"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ወይም"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"የፍለጋ መጠይቅን አጽዳ"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"አቋራጮች"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"የቁልፍ ሰሌዳ አቋራጮች"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"ረዳትን ክፈት"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ማያ ገፅ ቁልፍ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ማስታወሻ ይውሰዱ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"የሥርዓት ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"ለአርኤችኤስ በአሁኑ መተግበሪያ ወደ የተከፈለ ማያ ገጽ ግባ"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"ለኤልኤችኤስ በአሁኑ መተግበሪያ ወደ የተከፈለ ማያ ገጽ ይግቡ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"የአሁኑ መተግበሪያ በስተቀኝ ላይ ሆኖ የተከፈለ ማያ ገጽን ይጠቀሙ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"የአሁኑ መተግበሪያ በስተግራ ላይ ሆኖ የተከፈለ ማያ ገጽን ይጠቀሙ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"ከየተከፈለ ማያ ገጽ ወደ ሙሉ ገጽ ዕይታ ቀይር"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"የተከፈለ ማያ ገጽን ሲጠቀሙ በቀኝ ወይም ከታች ወዳለ መተግበሪያ ይቀይሩ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"የተከፈለ ማያ ገጽን ሲጠቀሙ በቀኝ ወይም ከላይ ወዳለ መተግበሪያ ይቀይሩ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 767e909..c92a32b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -75,7 +75,7 @@
     <string name="global_action_smart_lock_disabled" msgid="6286551337177954859">"تم إيقاف ميزة \"إبقاء الجهاز مفتوحًا\"."</string>
     <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>
+    <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"جارٍ حفظ لقطة الشاشة في ملف العمل…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"تعذّر حفظ لقطة الشاشة"</string>
     <string name="screenshot_failed_external_display_indication" msgid="6555673132061101936">"الشاشة الخارجية"</string>
@@ -90,13 +90,13 @@
     <string name="screenshot_share_description" msgid="2861628935812656612">"مشاركة لقطة الشاشة"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"التقاط المزيد من المحتوى"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"إغلاق لقطة الشاشة"</string>
-    <string name="screenshot_dismiss_work_profile" msgid="3101530842987697045">"تجاهل رسالة الملف الشخصي للعمل"</string>
+    <string name="screenshot_dismiss_work_profile" msgid="3101530842987697045">"تجاهل رسالة ملف العمل"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"معاينة لقطة الشاشة"</string>
     <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"الحد العلوي <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"الحد السفلى <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"الحد الأيسر <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"الحد الأيمن <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
-    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"تم حفظ لقطة الشاشة في \"<xliff:g id="APP">%1$s</xliff:g>\" في الملف الشخصي للعمل."</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"تم حفظ لقطة الشاشة في \"<xliff:g id="APP">%1$s</xliff:g>\" في ملف العمل."</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"الملفات"</string>
     <string name="screenshot_detected_template" msgid="7940376642921719915">"رصَد تطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" لقطة الشاشة هذه."</string>
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"رصَد تطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" والتطبيقات المفتوحة الأخرى لقطة الشاشة هذه."</string>
@@ -120,7 +120,7 @@
     <string name="screenrecord_stop_label" msgid="72699670052087989">"إيقاف"</string>
     <string name="screenrecord_share_label" msgid="5025590804030086930">"مشاركة"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"تم حفظ تسجيل الشاشة"</string>
-    <string name="screenrecord_save_text" msgid="3008973099800840163">"انقر لعرض التسجيل."</string>
+    <string name="screenrecord_save_text" msgid="3008973099800840163">"انقر لعرض التسجيل"</string>
     <string name="screenrecord_save_error" msgid="5862648532560118815">"حدث خطأ أثناء حفظ تسجيل محتوى الشاشة."</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"حدث خطأ في بدء تسجيل الشاشة"</string>
     <string name="issuerecord_title" msgid="286627115110121849">"مسجّلة المشاكل"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مركز الإشعارات."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"الإعدادات السريعة."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"الإعدادات السريعة\" و\"مركز الإشعارات\""</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"شاشة القفل."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"شاشة القفل"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"شاشة قفل بيانات العمل"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"إغلاق"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"كتم الصوت تمامًا"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"عرض الكل"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"استخدام البلوتوث"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متّصل"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"مشاركة الصوت"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"إلغاء الربط"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"تفعيل"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"تفعيل البلوتوث تلقائيًا مرة أخرى غدًا"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"‏يُستخدَم البلوتوث في ميزات مثل Quick Share و\"العثور على جهازي\" والموقع الجغرافي للجهاز"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"سيتم تفعيل البلوتوث غدًا الساعة 5 صباحًا"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"‏يُستخدَم البلوتوث في ميزات مثل Quick Share و\"العثور على جهازي\""</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"سيتم تفعيل البلوتوث صباح الغد"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"مشاركة الصوت"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"مشاركة الصوت"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"صوت"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"سماعة الرأس"</string>
@@ -287,7 +290,7 @@
     <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_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>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"تسجيل المشكلة"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"بدء"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"إيقاف"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"تقرير خطأ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ما هو الجانب الذي تأثّر في تجربة استخدام الجهاز؟"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"اختيار نوع المشكلة"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"تسجيل الشاشة"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"عادي"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"متوسط"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"مرتفع"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعات الأذن الطبية"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سماعات الأذن الطبية"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"إقران جهاز جديد"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"انقر لإقران جهاز جديد"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"هل تريد إزالة حظر ميكروفون الجهاز؟"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"هل تريد إزالة حظر كاميرا الجهاز؟"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن سريعًا • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"التطبيقات المصغّرة على شاشة القفل"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"مرِّر سريعًا لليمين لبدء الدليل التوجيهي العام."</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"تخصيص"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"إغلاق"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"فتح الإعدادات"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"أتريد إعادة تفعيل تطبيقات العمل؟"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"إعادة التفعيل"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"إغلاق التطبيقات المصغّرة على شاشة القفل"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"التطبيقات المصغّرة على شاشة القفل"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"القائمة المنسدلة"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
@@ -518,9 +525,9 @@
     <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>."</string>
     <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"‏ينتمي هذا الجهاز إلى مؤسستك، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string>
     <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"‏ينتمي هذا الجهاز إلى <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string>
-    <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"يمكن لمؤسستك مراقبة حركة بيانات الشبكة في الملف الشخصي للعمل"</string>
+    <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"يمكن لمؤسستك مراقبة حركة بيانات الشبكة في ملف العمل"</string>
     <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملفك الشخصي للعمل"</string>
-    <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"تكون أنشطة شبكة الملف الشخصي للعمل مرئية لمشرف تكنولوجيا المعلومات."</string>
+    <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"تكون أنشطة شبكة ملف العمل مرئية لمشرف تكنولوجيا المعلومات."</string>
     <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"قد تكون الشبكة خاضعة للمراقبة"</string>
     <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"‏هذا الجهاز متّصل بالإنترنت من خلال خدمات الشبكات الافتراضية الخاصة (VPN)."</string>
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
@@ -639,7 +646,7 @@
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"إعدادات شاشة القفل"</string>
     <string name="qr_code_scanner_title" msgid="1938155688725760702">"ماسح ضوئي لرمز الاستجابة السريعة"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"جارٍ تعديل الحالة"</string>
-    <string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
+    <string name="status_bar_work" msgid="5238641949837091056">"ملف العمل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template" msgid="2234991538018805736">"في <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -649,7 +656,7 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"قمر صناعي، الاتصال ضعيف"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"قمر صناعي، الاتصال جيد"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
-    <string name="accessibility_managed_profile" msgid="4703836746209377356">"الملف الشخصي للعمل"</string>
+    <string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
     <string name="tuner_persistent_warning" msgid="230466285569307806">"يمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تبديل تنسيق لوحة المفاتيح"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"أو"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"محو طلب البحث"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"الاختصارات"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"اختصارات لوحة المفاتيح"</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>
@@ -770,14 +777,14 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"‏فتح \"مساعد Google\""</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"شاشة القفل"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"تدوين ملاحظة"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"تعدُّد المهام في النظام"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"تفعيل وضع \"تقسيم الشاشة\" مع عرض التطبيق الحالي على يسار الشاشة"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"تفعيل وضع \"تقسيم الشاشة\" مع عرض التطبيق الحالي على يمين الشاشة"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"تعدُّد المهام"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"استخدام \"وضع تقسيم الشاشة\" مع تثبيت التطبيق الحالي على اليمين"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"استخدام \"وضع تقسيم الشاشة\" مع تثبيت التطبيق الحالي على اليسار"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"التبديل من وضع \"تقسيم الشاشة\" إلى وضع \"ملء الشاشة\""</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"التبديل إلى التطبيق على اليسار أو الأسفل أثناء استخدام \"تقسيم الشاشة\""</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"التبديل إلى التطبيق على اليمين أو الأعلى أثناء استخدام \"تقسيم الشاشة\""</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"استبدال تطبيق بآخر في وضع \"تقسيم الشاشة\""</string>
-    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"إدخال"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"الإدخال"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"التبديل إلى اللغة التالية"</string>
     <string name="input_switch_input_language_previous" msgid="6043341362202336623">"التبديل إلى اللغة السابقة"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"الوصول إلى الرموز التعبيرية"</string>
@@ -789,7 +796,7 @@
     <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"البريد الإلكتروني"</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>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"‏تقويم Google"</string>
     <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"الآلة الحاسبة"</string>
     <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"‏خرائط Google"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"عدم الإزعاج"</string>
@@ -802,7 +809,7 @@
     <string name="data_saver" msgid="3484013368530820763">"توفير البيانات"</string>
     <string name="accessibility_data_saver_on" msgid="5394743820189757731">"تم تفعيل توفير البيانات"</string>
     <string name="switch_bar_on" msgid="1770868129120096114">"مفعّل"</string>
-    <string name="switch_bar_off" msgid="5669805115416379556">"متوقف"</string>
+    <string name="switch_bar_off" msgid="5669805115416379556">"غير مفعّل"</string>
     <string name="tile_unavailable" msgid="3095879009136616920">"غير متوفّر"</string>
     <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"مزيد من المعلومات"</string>
     <string name="nav_bar" msgid="4642708685386136807">"شريط التنقل"</string>
@@ -830,7 +837,7 @@
     <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_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</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>
     <string name="qs_edit" msgid="5583565172803472437">"تعديل"</string>
@@ -995,7 +1002,7 @@
     <string name="accessibility_floating_button_undo" msgid="511112888715708241">"تراجع"</string>
     <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"زر أدوات تسهيل الاستخدام مخفي"</string>
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"انقر لإظهار زر أدوات تسهيل الاستخدام."</string>
-    <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"تمت إزالة اختصار <xliff:g id="FEATURE_NAME">%s</xliff:g>."</string>
+    <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"تمت إزالة اختصار ميزة \"<xliff:g id="FEATURE_NAME">%s</xliff:g>\""</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{تمت إزالة اختصار واحد.}zero{تمت إزالة # اختصار.}two{تمت إزالة اختصارَين.}few{تمت إزالة # اختصارات.}many{تمت إزالة # اختصارًا.}other{تمت إزالة # اختصار.}}"</string>
     <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"النقل إلى أعلى يمين الشاشة"</string>
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"النقل إلى أعلى يسار الشاشة"</string>
@@ -1265,8 +1272,8 @@
     <string name="video_camera" msgid="7654002575156149298">"كاميرا فيديو"</string>
     <string name="call_from_work_profile_title" msgid="5418253516453177114">"لا يمكن الاتصال من تطبيق شخصي"</string>
     <string name="call_from_work_profile_text" msgid="2856337395968118274">"تسمح لك مؤسستك بإجراء المكالمات من تطبيقات العمل فقط."</string>
-    <string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
-    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"تثبيت تطبيق الهاتف في الملف الشخصي للعمل"</string>
+    <string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى ملف العمل"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"تثبيت تطبيق الهاتف في ملف العمل"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"إلغاء"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"تخصيص شاشة القفل"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"الفتح لتخصيص شاشة القفل"</string>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index 307a26e..a89650a 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"الخيار غير مفعَّل"</item>
     <item msgid="5137565285664080143">"الخيار مفعَّل"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"غير متوفّرة"</item>
+    <item msgid="3079622119444911877">"غير مفعَّلة"</item>
+    <item msgid="3028994095749238254">"مفعَّلة"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 5a083ab..f1291a0 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিং।"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ক্ষিপ্ৰ ছেটিং জাননী পেনেল।"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"লক স্ক্ৰীন"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"সম্পূৰ্ণ নিৰৱতা"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"আটাইবোৰ চাওক"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যৱহাৰ কৰক"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"সংযুক্ত আছে"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিঅ’ শ্বেয়াৰ কৰা"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ছেভ কৰা হৈছে"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"সংযোগ বিচ্ছিন্ন কৰক"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"সক্ৰিয় কৰক"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"কাইলৈ পুনৰ স্বয়ংক্ৰিয়ভাৱে অন কৰক"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Quick Share, Find My Device আৰু ডিভাইচৰ অৱস্থানৰ দৰে সুবিধাই ব্লুটুথ ব্যৱহাৰ কৰে"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"কাইলৈ পুৱা ৫ বজাত ব্লুটুথ অন হ’ব"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share আৰু Find My Deviceৰ দৰে সুবিধাসমূহে ব্লুটুথ ব্যৱহাৰ কৰে"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"কাইলৈ পুৱা ব্লুটুথ অন হ’ব"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"অডিঅ’ শ্বেয়াৰ কৰা"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"অডিঅ’ শ্বেয়াৰ কৰি থকা হৈছে"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"অডিঅ’"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"হেডছেট"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ৰেকৰ্ড সম্পৰ্কীয় সমস্যা"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"আৰম্ভ কৰক"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"বন্ধ কৰক"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"বাগ ৰিপ’ৰ্ট"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"আপোনাৰ ডিভাইচৰ অভিজ্ঞতাৰ কোনটো অংশ প্ৰভাৱিত হৈছিল?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"সমস্যাৰ প্ৰকাৰ বাছনি কৰক"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"স্ক্ৰীন ৰেকৰ্ড"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"মধ্যমীয়া"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"উচ্চ"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"শুনাৰ ডিভাইচ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"শুনাৰ ডিভাইচ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইচ পেয়াৰ কৰিবলৈ ক্লিক কৰক"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইচৰ মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইচৰ কেমেৰা অৱৰোধৰ পৰা আঁতৰাবনে?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্ৰুতগতিৰে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্ৰীনত ৱিজেট"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ বাওঁফালে ছোৱাইপ কৰক"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাষ্টমাইজ কৰক"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"অগ্ৰাহ্য কৰক"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ছেটিং খোলক"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"কাম সম্পৰ্কীয় এপ্ আনপজ কৰিবনে?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"আনপজ কৰক"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"লক স্ক্ৰীনত ৱিজেট বন্ধ কৰক"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"লক স্ক্ৰীনত ৱিজেট"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুল-ডাউনৰ মেনু"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীব\'ৰ্ডৰ সজ্জা সলনি কৰক"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"অথবা"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"সন্ধান কৰা প্ৰশ্ন মচক"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শ্বৰ্টকাট"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"কীব’ৰ্ডৰ শ্বৰ্টকাট"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant খোলক"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্ৰীন"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"টোকা লিখক"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ছিষ্টেম মাল্টিটাস্কিং"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"বৰ্তমানৰ এপৰ জৰিয়তে বিভাজিত স্ক্ৰীনৰ সোঁফালৰ স্ক্ৰীনখনত সোমাওক"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"বৰ্তমানৰ এপৰ জৰিয়তে বিভাজিত স্ক্ৰীনৰ বাওঁফালৰ স্ক্ৰীনখনত সোমাওক"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"মাল্টিটাস্কিং"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"বৰ্তমানৰ এপ্‌টোৰ সৈতে সোঁফালে বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰক"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"বৰ্তমানৰ এপ্‌টোৰ সৈতে বাওঁফালে বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰক"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"বিভাজিত স্ক্ৰীনৰ পৰা পূৰ্ণ স্ক্ৰীনলৈ সলনি কৰক"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰাৰ সময়ত সোঁফালে অথবা তলত থকা এপলৈ সলনি কৰক"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰাৰ সময়ত বাওঁফালে অথবা ওপৰত থকা এপলৈ সলনি কৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 7faec8a..b12d822 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildiriş kölgəsi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tez ayarlar."</string>
     <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_lock_screen" msgid="409034672704273634">"Kilid ekranı"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran kilidi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Qapadın"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"tam sakitlik"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Hamısına baxın"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth aç"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Qoşulub"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio paylaşma"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Yadda saxlandı"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"əlaqəni kəsin"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivləşdirin"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Sabah avtomatik aktiv edin"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Cəld Paylaşım, Cihazın Tapılması və cihaz məkanı kimi funksiyalar Bluetooth istifadə edir"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth sabah 05:00-da aktiv olacaq"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Cəld Paylaşım və Cihazın Tapılması kimi funksiyalar Bluetooth istifadə edir"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth sabah səhər aktiv ediləcək"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio paylaşma"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audio paylaşılır"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batareya"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Qulaqlıq"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Qeyd problemi"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Başlayın"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Dayandırın"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Baq hesabatı"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cihaz istifadəsinə necə təsir etdi?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Problem növü seçin"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekran qeydəalma"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standart"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Orta"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Yüksək"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eşitmə cihazları"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eşitmə cihazları"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yeni cihaz birləşdirin"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz birləşdirmək üçün klikləyin"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonu blokdan çıxarılsın?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerası blokdan çıxarılsın?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sürətlə şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilid ekranındakı vidcetlər"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"İcma təlimatını başlatmaq üçün sola sürüşdürün"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Fərdiləşdirin"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Bağlayın"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ayarları açın"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"İş tətbiqi üzrə pauza bitsin?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Pauzanı bitirin"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Kilid ekranında vidcetləri bağlayın"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Kilid ekranındakı vidcetlər"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aşağı çəkilən menyu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura düzümünü dəyişin"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"və ya"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Axtarış sorğusunu silin"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Qısayollar"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klaviatura qısayolları"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Qısayollar axtarın"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Qısayol tapılmadı"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistenti açın"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilid ekranı"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Qeyd götürün"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistemdə çoxsaylı tapşırıq icrası"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Cari tətbiq sağda olmaqla bölünmüş ekrana daxil olun"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Cari tətbiq solda olmaqla bölünmüş ekrana daxil olun"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Çoxsaylı tapşırıq icrası"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Cari tətbiq sağda olmaqla bölünmüş ekrandan istifadə edin"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Cari tətbiq solda olmaqla bölünmüş ekrandan istifadə edin"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Bölünmüş ekrandan tam ekrana keçin"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bölünmüş ekran istifadə edərkən sağda və ya aşağıda tətbiqə keçin"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bölünmüş ekran istifadə edərkən solda və ya yuxarıda tətbiqə keçin"</string>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index f390369..c24f402 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Deaktiv"</item>
     <item msgid="5137565285664080143">"Aktiv"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Əlçatan deyil"</item>
+    <item msgid="3079622119444911877">"Deaktiv"</item>
+    <item msgid="3028994095749238254">"Aktiv"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index cd5dc26..221d16c 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Prozor sa obaveštenjima."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brza podešavanja."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brza podešavanja i traka sa obaveštenjima."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključani ekran"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran za posao"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"potpuna tišina"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Prikaži sve"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvuka"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinite vezu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivirajte"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski ponovo uključi sutra"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funkcije kao što su Quick Share, Pronađi moj uređaj i lokacija uređaja koriste Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth će se uključiti sutra u 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkcije kao što su Quick Share i Pronađi moj uređaj koriste Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth će se uključiti sutra ujutru"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Deljenje zvuka"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Deli se zvuk"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalice"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Evidentirajte problem"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Pokreni"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zaustavi"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Izveštaj o grešci"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Na koji deo doživljaja na uređaju je ovo uticalo?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Izaberite tip problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje ekrana"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednje"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visoko"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Upari novi uređaj"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili nov uređaj"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite da odblokirate mikrofon uređaja?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite da odblokirate kameru uređaja?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulevo da biste započeli zajednički vodič"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otvori podešavanja"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Uključiti poslovne aplikacije?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Ponovo aktiviraj"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zatvorite vidžete na zaključanom ekranu"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Vidžeti na zaključanom ekranu"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zameni korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promeni raspored tastature"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Obriši upit za pretragu"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tasterske prečice"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečice"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
@@ -766,12 +774,12 @@
     <string name="group_system_cycle_back" msgid="8194102916946802902">"Pregledaj nedavno korišćene aplikacije unazad"</string>
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvori listu aplikacija"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvori podešavanja"</string>
-    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvori pomoćnika"</string>
+    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvori Pomoćnik"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Napravite belešku"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Obavljanje više zadataka sistema istovremeno"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Pokreni podeljeni ekran za aktuelnu aplikaciju na desnoj strani"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Pokreni podeljeni ekran za aktuelnu aplikaciju na levoj strani"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Napravi belešku"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Obavljanje više zadataka istovremeno"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Koristite podeljeni ekran sa aktuelnom aplikacijom s desne strane"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Koristite podeljeni ekran sa aktuelnom aplikacijom s leve strane"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Pređi sa podeljenog ekrana na ceo ekran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pređite u aplikaciju zdesna ili ispod dok koristite podeljeni ekran"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pređite u aplikaciju sleva ili iznad dok koristite podeljeni ekran"</string>
@@ -1295,9 +1303,9 @@
     <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Upravljaj pristupom"</string>
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Koristi telefonski poziv"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Nedavno korišćeno u telefonskom pozivu"</string>
-    <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
+    <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index a76c38b..d1c4a98 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Цень апавяшчэння.."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Хуткія налады."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Хуткія налады і шчыток апавяшчэнняў."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блакіроўкі."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Экран блакіроўкі"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Экран блакіроўкі дзейнасці"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыць"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"поўная цішыня"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Паглядзець усе"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Выкарыстоўваць Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Падключана"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Абагульванне аўдыя"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Захавана"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"адключыць"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"актываваць"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Аўтаматычнае ўключэнне заўтра"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Bluetooth выкарыстоўваецца для вызначэння месцазнаходжання прылады, а таксама такімі функцыямі, як Хуткае абагульванне і Знайсці прыладу"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth будзе ўключаны заўтра ў 5 гадзін раніцы"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Bluetooth выкарыстоўваецца такімі функцыямі і сэрвісамі, як Хуткае абагульванне і Знайсці прыладу"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth уключыцца заўтра раніцай"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Абагульванне аўдыя"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Ідзе абагульванне аўдыя"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Гук"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнітура"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Запіс праблемы"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Пачынайце"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Спыніцеся"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Справаздача"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"З чым была звязана праблема, якая вам сустрэлася?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Выберыце тып праблемы"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запіс экрана"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартная"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Сярэдняя"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Высокая"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слыхавыя апараты"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слыхавыя апараты"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Спалучыць новую прыладу"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Націсніце, каб спалучыць новую прыладу"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблакіраваць мікрафон прылады?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблакіраваць камеру прылады?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе хуткая зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджэты на экране блакіроўкі"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Правядзіце пальцам па экране ўлева, каб азнаёміцца з дапаможнікам"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Наладзіць"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыць"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Адкрыць налады"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Уключыць працоўныя праграмы?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Уключыць"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрыць віджэты на экране блакіроўкі"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Віджэты на экране блакіроўкі"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Перайсці да іншага карыстальніка"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"высоўнае меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пераключыць раскладку клавіятуры"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"або"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ачысціць пошукавы запыт"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ярлыкі"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Спалучэнні клавіш"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Выклікаць Памочніка"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экран блакіроўкі"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Стварыць нататку"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Шматзадачнасць сістэмы"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Перайсці ў рэжым падзеленага экрана з бягучай праграмай справа"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Перайсці ў рэжым падзеленага экрана з бягучай праграмай злева"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Шматзадачнасць"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Падзяліць экран і памясціць гэту праграму справа"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Падзяліць экран і памясціць гэту праграму злева"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Пераключыцца з рэжыму падзеленага экрана на поўнаэкранны рэжым"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Пераключыцца на праграму справа або ўнізе на падзеленым экране"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Пераключыцца на праграму злева або ўверсе на падзеленым экране"</string>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index 32619ef..33e704c 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Выключана"</item>
     <item msgid="5137565285664080143">"Уключана"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Недаступна"</item>
+    <item msgid="3079622119444911877">"Выключана"</item>
+    <item msgid="3028994095749238254">"Уключана"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index f8793b3..62d3fed 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Падащ панел с известия."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Бързи настройки."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Падащ панел с бързи настройки и известия."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заключване на екрана."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Заключен екран"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заключен екран на служебния профил"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затваряне"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"пълна тишина"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Преглед на всички"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Използване на Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Установена е връзка"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделяне на звука"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Запазено"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекратяване на връзката"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активиране"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматично включване отново утре"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Bluetooth се използва от различни функции, като например „Бързо споделяне“, „Намиране на устройството ми“ и местоположението на устройството"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ще се включи утре в 5:00 ч."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Функции като „Бързо споделяне“ и „Намиране на устройството ми“ използват Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ще се включи утре сутрин"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Споделяне на звука"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Звукът се споделя"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Слушалки"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Записване на проблем"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Стартиране"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Спиране"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Сигнал за грешка"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"С какво имахте проблем?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Изберете тип проблем"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запис на екрана"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартен"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Среден"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Висок"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухови апарати"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слухови апарати"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Сдвояване на ново устройство"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за сдвояване на ново устройство"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се отблокира ли микрофонът на устройството?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се отблокира ли камерата на устройството?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бързо • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Приспособления на заключения екран"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Прекарайте пръст наляво, за да стартирате общия урок"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Персонализиране"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отхвърляне"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Отваряне на настройките"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Отмяна на паузата за служ. прил.?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Отмяна на паузата"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затваряне на приспособленията на заключения екран"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Приспособления на заключения екран"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падащо меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Превкл. на клавиат. подредба"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Изчистване на заявката за търсене"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Клавишни комбинации"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Клавишни комбинации"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отваряне на Асистент"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заключване на екрана"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Създаване на бележка"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Едновременно изпълняване на няколко задачи в системата"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Преминаване към разделен екран с текущото приложение отдясно"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Преминаване към разделен екран с текущото приложение отляво"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Изпълняване на няколко задачи едновременно"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Използване на разделен екран с текущото приложение вдясно"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Използване на разделен екран с текущото приложение вляво"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Превключване от разделен към цял екран"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Превключване към приложението вдясно/отдолу в режима на разделен екран"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Превключване към приложението вляво/отгоре в режима на разделен екран"</string>
@@ -1285,7 +1292,7 @@
     <string name="dismiss_dialog" msgid="2195508495854675882">"Отхвърляне"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Свързан е екран"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
-    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Скорошно използване на приложението"</string>
+    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Скорошно използване от приложенията"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Вижте скорошния достъп"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Готово"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Разгъване и показване на опциите"</string>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index 381b0f0..e2fd653 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Изключено"</item>
     <item msgid="5137565285664080143">"Включено"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Не е налице"</item>
+    <item msgid="3079622119444911877">"Изкл."</item>
+    <item msgid="3028994095749238254">"Вкл."</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index f6de0e3..81e3fc4 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"বিজ্ঞপ্তি শেড৷"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"দ্রুত সেটিংস৷"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"দ্রুত সেটিংস এবং বিজ্ঞপ্তি শেড।"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"লক স্ক্রিন।"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"লক স্ক্রিন"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কর্মস্থলের স্ক্রিন লক"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ করুন"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"সম্পূর্ণ নীরব"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"সব দেখুন"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যবহার করুন"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"কানেক্ট করা আছে"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিও শেয়ারিং"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"সেভ করা আছে"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ডিসকানেক্ট করুন"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"চালু করুন"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"আগামীকাল অটোমেটিক আবার চালু হবে"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"\'দ্রুত শেয়ার\', \'Find My Device\' ও \'ডিভাইস লোকেশনের\' মতো ফিচার ব্লুটুথ ব্যবহার করে"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"আগামীকাল ভোর ৫টায় ব্লুটুথ চালু হবে"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"দ্রুত শেয়ার ও Find My Device-এর মতো ফিচার ব্লুটুথ ব্যবহার করে"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ব্লুটুথ আগামীকাল সকালে চালু হয়ে যাবে"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"অডিও শেয়ারিং"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"অডিও শেয়ার করা হচ্ছে"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"অডিও"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"হেডসেট"</string>
@@ -333,7 +336,7 @@
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"সূর্যোদয় পর্যন্ত"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> এ চালু হবে"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
-    <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"গাঢ় থিম"</string>
+    <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ডার্ক থিম"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ব্যাটারি সেভার"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূর্যাস্তে চালু হবে"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"রেকর্ডিংয়ে সমস্যা"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"শুরু করুন"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"বন্ধ করুন"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"সমস্যার রিপোর্ট"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ডিভাইস ব্যবহার করার সময় কোথায় অসুবিধা হয়েছিল?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"সমস্যার প্রকার বেছে নিন"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"স্ক্রিন রেকর্ড"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"স্ট্যান্ডার্ড"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"মিডিয়াম"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"হাই"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"হিয়ারিং ডিভাইস"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"হিয়ারিং ডিভাইস"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"নতুন ডিভাইস পেয়ার করুন"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইস পেয়ার করতে ক্লিক করুন"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইসের মাইক্রোফোন আনব্লক করতে চান?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইসের ক্যামেরা আনব্লক করতে চান?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্রুত চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্রিনে উইজেট"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"কমিউনিটি টিউটোরিয়াল চালু করতে বাঁদিকে সোয়াইপ করুন"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাস্টমাইজ করুন"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"বাতিল করুন"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"সেটিংস খুলুন"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"অফিসের অ্যাপ আনপজ করতে চান?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"আনপজ করুন"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"লক স্ক্রিনে উইজেট বন্ধ করুন"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"লক স্ক্রিনে উইজেট"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যবহারকারী পাল্টে দিন"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুলডাউন মেনু"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ ও ডেটা মুছে ফেলা হবে।"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীবোর্ড লে-আউট পাল্টান"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"অথবা"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"সার্চ কোয়েরি মুছুন"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শর্টকাট"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"কীবোর্ড শর্টকাট"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant খুলুন"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্রিন"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"একটি নোট লিখুন"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"সিস্টেম মাল্টিটাস্কিং"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"ডানদিকে থাকা বর্তমান অ্যাপ ব্যবহার করে \'স্প্লিট স্ক্রিন\' যোগ করুন"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"বাঁদিকে থাকা বর্তমান অ্যাপ ব্যবহার করে \'স্প্লিট স্ক্রিন\' যোগ করুন"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"মাল্টিটাস্কিং"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ডানদিকে বর্তমান অ্যাপে স্প্লিট স্ক্রিন ব্যবহার করুন"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"বাঁদিকে বর্তমান অ্যাপে স্প্লিট স্ক্রিন ব্যবহার করুন"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"\'স্প্লিট স্ক্রিন\' থেকে ফুল স্ক্রিনে পাল্টান"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"স্প্লিট স্ক্রিন ব্যবহার করার সময় ডানদিকের বা নিচের অ্যাপে পাল্টে নিন"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"স্প্লিট স্ক্রিন ব্যবহার করার সময় বাঁদিকের বা উপরের অ্যাপে পাল্টে নিন"</string>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index 2eebd97..6e4dfbf 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"বন্ধ আছে"</item>
     <item msgid="5137565285664080143">"চালু আছে"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"উপলভ্য নেই"</item>
+    <item msgid="3079622119444911877">"বন্ধ আছে"</item>
+    <item msgid="3028994095749238254">"চালু আছে"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 9347757..7d66851 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -235,7 +235,7 @@
     <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 lokacija za obavještenja."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključavanje ekrana"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"potpuna tišina"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Prikaži sve"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Dijeljenje zvuka"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekid veze"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski uključi ponovo sutra"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funkcije kao što su Quick Share, Pronađi moj uređaj i lokacija uređaja koriste Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth će se uključiti sutra u 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkcije kao što su Quick Share i Pronađi moj uređaj koriste Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth će se uključiti sutra ujutro"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Dijeljenje zvuka"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Dijeljenje zvuka"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> baterije"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvuk"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalice"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Snimite problem"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Pokrenite"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zaustavite"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Izvještaj o grešci"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Koji dio uređaja je imao problem?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Odaberite vrstu problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje ekrana"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardno"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednje"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visoko"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni aparati"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uparite novi uređaj"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da uparite novi uređaj"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokirati mikrofon uređaja?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokirati kameru uređaja?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulijevo da pokrenete zajednički vodič"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string>
@@ -448,12 +451,16 @@
     <string name="button_to_remove_widget" msgid="3948204829181214098">"Uklanjanje"</string>
     <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodajte vidžet"</string>
     <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gotovo"</string>
-    <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Dodaj widgete"</string>
-    <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Brzo pristupajte widgetima omiljenih aplikacija bez otključavanja tableta."</string>
+    <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Dodajte vidžet"</string>
+    <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Dobijte brz pristup omiljenim vidžetima aplikacija bez otključavanja tableta."</string>
     <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Dozvoliti bilo koji vidžet na zaključanom ekranu?"</string>
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otvori postavke"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Pokrenuti poslovne aplikacije?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Ponovo pokreni"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zatvaranje vidžeta na zaključanom ekranu"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Vidžeti na zaključanom ekranu"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zamijeni korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Zamijeni raspored tastature"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Brisanje upita za pretraživanje"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Prečice na tastaturi"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretraživanje prečica"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvaranje Asistenta"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Otvaranje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Otvaranje podijeljenog ekrana s trenutnom aplikacijom na lijevoj strani"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Korištenje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Korištenje podijeljenog ekrana s trenutnom aplikacijom na lijevoj strani"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prebacivanje s podijeljenog ekrana na prikaz preko cijelog ekrana"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pređite u aplikaciju desno ili ispod dok koristite podijeljeni ekran"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pređite u aplikaciju lijevo ili iznad dok koristite podijeljeni ekran"</string>
@@ -1005,7 +1012,7 @@
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Pomjeranje izvan ivice i prikaz"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Uklanjanje"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"aktiviranje/deaktiviranje"</string>
-    <string name="accessibility_floating_button_action_edit" msgid="1688227814600463987">"Uredite"</string>
+    <string name="accessibility_floating_button_action_edit" msgid="1688227814600463987">"Uređivanje"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"Odaberite aplikaciju da dodate kontrole"</string>
     <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>
diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
index e09cab5..df0b786 100644
--- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Isključeno"</item>
     <item msgid="5137565285664080143">"Uključeno"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nedostupno"</item>
+    <item msgid="3079622119444911877">"Isključeno"</item>
+    <item msgid="3028994095749238254">"Uključeno"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 40532ca..87af353 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Àrea de notificacions"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuració ràpida"</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silenci total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Mostra-ho tot"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utilitza\'l"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connectat"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartició d\'àudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Desat"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconnecta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activa"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Torna\'l a activar automàticament demà"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funcions com ara Quick Share, Troba el meu dispositiu i la ubicació del dispositiu utilitzen el Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"El Bluetooth s\'activarà demà a les 5:00 h"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Les funcions com Quick Share i Troba el meu dispositiu utilitzen el Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"El Bluetooth s\'activarà demà al matí"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Compartició d\'àudio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"S\'està compartint l\'àudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de bateria"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Àudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculars"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Registra el problema"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Inicia"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Atura"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Informe d\'errors"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"L\'experiència amb el dispositiu s\'ha vist afectada?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecciona el tipus de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravació de pantalla"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estàndard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mitjà"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alt"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audiòfons"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audiòfons"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincula un dispositiu nou"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fes clic per vincular un dispositiu nou"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vols desbloquejar el micròfon del dispositiu?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vols desbloquejar la càmera del dispositiu?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant ràpidament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets a la pantalla de bloqueig"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Llisca cap a l\'esquerra per iniciar el tutorial de la comunitat"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalitza"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignora"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Obre la configuració"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Reactivar les apps de treball?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reactiva"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tanca els widgets a la pantalla de bloqueig"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets a la pantalla de bloqueig"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Canvia d\'usuari"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
@@ -606,7 +613,7 @@
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Toca per silenciar."</string>
     <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Control de soroll"</string>
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Àudio espacial"</string>
-    <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Desactiva"</string>
+    <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Desactivat"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Fix"</string>
     <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Seguiment del cap"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"Toca per canviar el mode de timbre"</string>
@@ -745,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Canvia disposició de teclat"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Esborra la consulta de cerca"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Dreceres"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tecles de drecera"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca dreceres"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No s\'ha trobat cap drecera"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
-    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Obre aplicacions"</string>
+    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Aplicacions obertes"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplicació actual"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"S\'estan mostrant els resultats de la cerca"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"S\'estan mostrant les dreceres del sistema"</string>
@@ -768,11 +775,11 @@
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Obre la llista d\'aplicacions"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Obre la configuració"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Obre l\'Assistent"</string>
-    <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueig"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloqueja la pantalla"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Crea una nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasques del sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Entra al mode de pantalla dividida amb l\'aplicació actual a la dreta"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Entra al mode de pantalla dividida amb l\'aplicació actual a l\'esquerra"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasca"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utilitza la pantalla dividida amb l\'aplicació actual a la dreta"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utilitza la pantalla dividida amb l\'aplicació actual a l\'esquerra"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Canvia de pantalla dividida a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Canvia a l\'aplicació de la dreta o de sota amb la pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Canvia a l\'aplicació de l\'esquerra o de dalt amb la pantalla dividida"</string>
@@ -1001,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mou a dalt a la dreta"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mou a baix a l\'esquerra"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mou a baix a la dreta"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mou dins de les vores i amaga"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mou fins la vora i amaga"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mou fora de les vores i mostra"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Suprimeix"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"commuta"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroil·luminació del teclat"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivell %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Controls de la llar"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Utilitza controls de la llar com a salvapantalles"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Utilitza controls de la llar com a estalvi de pantalla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index 6a36b6f..67eb853 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desactivat"</item>
     <item msgid="5137565285664080143">"Activat"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"No disponible"</item>
+    <item msgid="3079622119444911877">"Desactivat"</item>
+    <item msgid="3028994095749238254">"Activat"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 16c2914..102768f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel oznámení."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rychlé nastavení."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"úplné ticho"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Zobrazit vše"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Použít Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Připojeno"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Sdílení zvuku"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uloženo"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojit"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovat"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Zítra znovu automaticky zapnout"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funkce jako Quick Share, Najdi moje zařízení a vyhledávání zařízení používají Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth se zapne zítra v 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkce jako Quick Share a Najdi moje zařízení využívají Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth se zapne zítra ráno"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Sdílení zvuku"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Sdílení zvuku"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvuk"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Sluchátka"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Zaznamenat problém"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Spustit"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ukončit"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Zpráva o chybě"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Co v zařízení bylo ovlivněno?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Vyberte druh problém"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Záznam obrazovky"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardní"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Střední"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Vysoká"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Naslouchátka"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Naslouchátka"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Spárovat nové zařízení"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zařízení"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokovat mikrofon zařízení?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokovat fotoaparát zařízení?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rychlé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgety na obrazovce uzamčení"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Přejetím doleva spustíte komunitní výukový program"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Přizpůsobit"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavřít"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otevřít nastavení"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Zrušit pozastavení pracovních aplikací?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Zrušit pozastavení"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zavřít widgety na obrazovce uzamčení"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgety na obrazovce uzamčení"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Přepnout uživatele"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbalovací nabídka"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
@@ -680,7 +687,7 @@
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny"</string>
     <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, deaktivuje režim Nerušit"</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny a deaktivuje režim Nerušit"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"Prioritní"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tato oznámení nelze upravit."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornění na hovor nelze upravit."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Přepnout rozložení klávesnice"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"nebo"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Vymazat vyhledávaný dotaz"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Zkratky"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klávesové zkratky"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Vyhledat zkratky"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Žádné zkratky nenalezeny"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systém"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otevřít Asistenta"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknout obrazovku"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Vytvořit poznámku"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systémový multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Přepnout na rozdělenou obrazovku s aktuálními aplikacemi napravo"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Přepnout na rozdělenou obrazovku s aktuálními aplikacemi nalevo"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Použít rozdělenou obrazovku se stávající aplikací vpravo"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Použít rozdělenou obrazovku se stávající aplikací vlevo"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Přepnout z rozdělené obrazovky na celou obrazovku"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Přechod na aplikaci vpravo nebo dole v režimu rozdělené obrazovky"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Přechod na aplikaci vlevo nebo nahoře v režimu rozdělené obrazovky"</string>
@@ -1147,7 +1154,7 @@
     <string name="audio_status" msgid="4237055636967709208">"Poslouchá"</string>
     <string name="game_status" msgid="1340694320630973259">"Hraji hru"</string>
     <string name="empty_user_name" msgid="3389155775773578300">"Přátelé"</string>
-    <string name="empty_status" msgid="5938893404951307749">"Proberem to večer?"</string>
+    <string name="empty_status" msgid="5938893404951307749">"Probereme to večer?"</string>
     <string name="status_before_loading" msgid="1500477307859631381">"Obsah se brzy zobrazí"</string>
     <string name="missed_call" msgid="4228016077700161689">"Zmeškaný hovor"</string>
     <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
@@ -1269,7 +1276,7 @@
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Nainstalovat pracovní telefonní aplikaci"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Zrušit"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Přizpůsobit obrazovku uzamčení"</string>
-    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Pokud chcete upravit obrazovku uzamčení, odemkněte zařízení"</string>
+    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Obrazovku uzamčení upravíte, když zařízení odemknete"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Síť Wi-Fi není dostupná"</string>
     <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokována"</string>
     <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofon jsou blokovány"</string>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index 02a0f5f..ae533a8 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Vypnuto"</item>
     <item msgid="5137565285664080143">"Zapnuto"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Není k dispozici"</item>
+    <item msgid="3079622119444911877">"Vypnuto"</item>
+    <item msgid="3028994095749238254">"Zapnuto"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4754dbb..d3138ab 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notifikationspanel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kvikmenu."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total stilhed"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Se alt"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Brug Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Der er oprettet forbindelse"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gemt"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"afbryd forbindelse"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivér"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivér automatisk igen i morgen"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funktioner som f.eks. Quick Share, Find min enhed og enhedslokation anvender Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth aktiveres i morgen kl. 5.00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funktioner som f.eks. Quick Share og Find min enhed anvender Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth aktiveres i morgen tidlig"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Lyddeling"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Deler lyd"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Lyd"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Optag problem"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Fejlrapport"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Hvilken del af din enhedsoplevelse blev påvirket?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Vælg problemtype"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skærmoptagelse"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Middel"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Høj"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Høreapparater"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Par ny enhed"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik for at parre en ny enhed"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du fjerne blokeringen af enhedens mikrofon?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du fjerne blokeringen af enhedens kamera?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader hurtigt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets på låseskærmen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Stryg mod venstre for at starte den fælles vejledning"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpas"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Luk"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Åbn Indstillinger"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Vil du genoptage arbejdsapps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Genoptag"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Luk widgets på låseskærmen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets på låseskærmen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skift bruger"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullemenu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skift tastaturlayout"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ryd søgeforespørgsel"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Genveje"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tastaturgenveje"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søg efter genveje"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ingen genveje blev fundet"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Åbn Assistent"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skærm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Skriv en note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systemmultitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Start opdelt skærm med aktuel app til højre"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Start opdelt skærm med aktuel app til venstre"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Brug opdelt skærm med aktuel app til højre"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Brug opdelt skærm med aktuel app til venstre"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Skift fra opdelt skærm til fuld skærm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skift til en app til højre eller nedenfor, når du bruger opdelt skærm"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skift til en app til venstre eller ovenfor, når du bruger opdelt skærm"</string>
@@ -1151,7 +1158,7 @@
     <string name="status_before_loading" msgid="1500477307859631381">"Indhold dukker snart op"</string>
     <string name="missed_call" msgid="4228016077700161689">"Ubesvaret opkald"</string>
     <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
-    <string name="people_tile_description" msgid="8154966188085545556">"Se dine seneste beskeder, mistede opkald og statusopdateringer"</string>
+    <string name="people_tile_description" msgid="8154966188085545556">"Se dine seneste beskeder, ubesvarede opkald og statusopdateringer"</string>
     <string name="people_tile_title" msgid="6589377493334871272">"Samtale"</string>
     <string name="paused_by_dnd" msgid="7856941866433556428">"Sat på pause af Forstyr ikke"</string>
     <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> har sendt en besked: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index 598fcfe..2c3b053 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Fra"</item>
     <item msgid="5137565285664080143">"Til"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Ikke tilgængelig"</item>
+    <item msgid="3079622119444911877">"Fra"</item>
+    <item msgid="3028994095749238254">"Til"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2fd26bc..03d04a6 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -198,7 +198,7 @@
     <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Entsperrung per Gesichtserkennung neu einrichten"</string>
     <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Entsperrung per Gesichtserkennung"</string>
     <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Entsperrung per Gesichtserkennung einrichten"</string>
-    <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Wenn du die Entsperrung per Gesichtserkennung neu einrichtest, wird dein aktuelles Gesichtsmodell gelöscht.\n\nDu musst diese Funktion neu einrichten, damit du dein Smartphone weiterhin mit deinem Gesicht entsperren kannst."</string>
+    <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Wenn du die Entsperrung per Gesichtserkennung neu einrichtest, wird dein aktuelles Gesichtsmodell gelöscht.\n\nDu musst diese Funktion neu einrichten, damit du dein Smartphone weiterhin mithilfe der Gesichtserkennung entsperren kannst."</string>
     <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Die Entsperrung per Gesichtserkennung konnte nicht eingerichtet werden. Gehe zu den Einstellungen und versuche es noch einmal."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Berühre den Fingerabdrucksensor"</string>
     <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tippe zum Fortfahren auf das Symbol „Entsperren“"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Benachrichtigungsleiste"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Schnelleinstellungen"</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"lautlos"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Alle anzeigen"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth verwenden"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbunden"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audiofreigabe"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gespeichert"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Verknüpfung aufheben"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivieren"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Morgen automatisch wieder aktivieren"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Für Funktionen wie Quick Share, „Mein Gerät finden“ und den Gerätestandort wird Bluetooth verwendet"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth wird morgen um 5:00 Uhr aktiviert"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funktionen wie „Quick Share“ und „Mein Gerät finden“ verwenden Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth wird morgen früh aktiviert"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audiofreigabe"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audioinhalte werden freigegeben"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problem aufnehmen"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Aufnahme starten"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Aufnahme beenden"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Fehlerbericht"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Welche Bereiche des Geräts waren betroffen?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Art des Problems auswählen"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Bildschirmaufnahme"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mittel"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hoch"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörgeräte"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hörgeräte"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Neues Gerät koppeln"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicken, um neues Gerät zu koppeln"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Blockierung des Gerätemikrofons aufheben?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Blockierung der Gerätekamera aufheben?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird schnell geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets auf dem Sperrbildschirm"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Wische nach links, um das gemeinsame Tutorial zu starten"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassen"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Schließen"</string>
@@ -448,14 +451,16 @@
     <string name="button_to_remove_widget" msgid="3948204829181214098">"Entfernen"</string>
     <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget hinzufügen"</string>
     <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Fertig"</string>
-    <!-- no translation found for label_for_button_in_empty_state_cta (7314975555382055823) -->
-    <skip />
-    <!-- no translation found for title_for_empty_state_cta (6161654421223450530) -->
-    <skip />
+    <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Widgets hinzufügen"</string>
+    <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Greife schnell auf deine App-Widgets zu, ohne das Tablet entsperren zu müssen."</string>
     <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Beliebige Widgets auf Sperrbildschirm zulassen?"</string>
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Einstellungen öffnen"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Geschäftliche Apps nicht mehr pausieren?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Nicht mehr pausieren"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Widgets auf dem Sperrbildschirm schließen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets auf dem Sperrbildschirm"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
@@ -747,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tastaturlayout wechseln"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"oder"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Suchanfrage löschen"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tastenkombinationen"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tastenkombinationen"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tastenkombinationen suchen"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Keine gefunden"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -772,16 +777,16 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant öffnen"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Sperrbildschirm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Notiz machen"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System-Multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Splitscreen aktivieren, aktuelle App rechts"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Splitscreen aktivieren, aktuelle App links"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Splitscreen mit der aktuellen App auf der rechten Seite nutzen"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Splitscreen mit der aktuellen App auf der linken Seite nutzen"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Vom Splitscreen zum Vollbild wechseln"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Im Splitscreen-Modus rechts oder unten zu einer App wechseln"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Im Splitscreen-Modus links oder oben zu einer App wechseln"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Im Splitscreen-Modus zu einer App rechts oder unten wechseln"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Im Splitscreen-Modus zu einer App links oder oben wechseln"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Im Splitscreen: eine App durch eine andere ersetzen"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Eingabe"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Zur nächsten Sprache wechseln"</string>
-    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Zu vorheriger Sprache wechseln"</string>
+    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Zur vorherigen Sprache wechseln"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"Auf Emoji zugreifen"</string>
     <string name="input_access_voice_typing" msgid="7291201476395326141">"Auf Spracheingabe zugreifen"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Apps"</string>
@@ -793,7 +798,7 @@
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musik"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
     <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Rechner"</string>
-    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Karten"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Bitte nicht stören"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"Tastenkombination für Lautstärketasten"</string>
     <string name="battery" msgid="769686279459897127">"Akku"</string>
@@ -1000,7 +1005,7 @@
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Verknüpfung für „<xliff:g id="FEATURE_NAME">%s</xliff:g>“ entfernt"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# Verknüpfung entfernt}other{# Verknüpfungen entfernt}}"</string>
     <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Nach oben links verschieben"</string>
-    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Nach rechts oben verschieben"</string>
+    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Nach oben rechts verschieben"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Nach unten links verschieben"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Nach unten rechts verschieben"</string>
     <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"An den Rand verschieben und verbergen"</string>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index 4b4eed5..0606cc7 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Aus"</item>
     <item msgid="5137565285664080143">"An"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nicht verfügbar"</item>
+    <item msgid="3079622119444911877">"Aus"</item>
+    <item msgid="3028994095749238254">"An"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0c3f0d5..89092ad 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Γρήγορες ρυθμίσεις."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Γρήγορες ρυθμίσεις και πλαίσιο σκίασης ειδοποιήσεων."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Οθόνη κλειδώματος"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Κλείδωμα οθόνης"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Οθόνη κλειδωμένης εργασίας"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Κλείσιμο"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"πλήρης σίγαση"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Εμφάνιση όλων"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Χρήση Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Συνδέθηκε"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Κοινή χρήση ήχου"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Αποθηκεύτηκε"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"αποσύνδεση"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ενεργοποίηση"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Αυτόματη ενεργοποίηση ξανά αύριο"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Λειτουργίες όπως το Quick Share, η Εύρεση συσκευής και η τοποθεσία της συσκευής χρησιμοποιούν Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Το Bluetooth θα ενεργοποιηθεί αύριο στις 5 π.μ."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Λειτουργίες όπως το Quick Share και η Εύρεση συσκευής χρησιμοποιούν το Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Το Bluetooth θα ενεργοποιηθεί αύριο το πρωί"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Κοινή χρήση ήχου"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Κοινή χρήση ήχου"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ήχος"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ακουστικά"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Εγγραφή προβλήματος"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Έναρξη"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Διακοπή"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Αναφορά σφάλματος"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ποιο κομμάτι της εμπειρίας συσκευής επηρεάστηκε;"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Επιλογή τύπου προβλήματος"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Εγγραφή οθόνης"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Τυπική"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Μέτρια"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Υψηλή"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Συσκευές ακοής"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Συσκευές ακοής"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Σύζευξη νέας συσκευής"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Κάντε κλικ για σύζευξη νέας συσκευής"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Κατάργηση αποκλεισμού μικροφώνου συσκευής;"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Κατάργηση αποκλεισμού κάμερας συσκευής;"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Γρήγορη φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Γραφικά στοιχεία στην οθόνη κλειδώματος"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Σύρετε προς τα αριστερά για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Προσαρμογή"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Παράβλεψη"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Άνοιγμα ρυθμίσεων"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Αναίρ. παύσης εφαρμ. εργασιών;"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Αναίρεση παύσης"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Κλείσιμο γραφικών στοιχείων στην οθόνη κλειδώματος"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Γραφικά στοιχεία στην οθόνη κλειδώματος"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Εναλλαγή χρήστη"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"αναπτυσσόμενο μενού"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Αλλαγή διάταξης πληκτρολογίου"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ή"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Διαγραφή ερωτήματος αναζήτησης"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Συντομεύσεις"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Συντομεύσ. πληκτρολογίου"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Άνοιγμα Βοηθού"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Κλείδωμα οθόνης"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Δημιουργία σημείωσης"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Πολυδιεργασία συστήματος"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Ενεργοποίηση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα δεξιά"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Ενεργοποίηση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα αριστερά"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Πολυδιεργασία"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Χρήση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα δεξιά"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Χρήση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα αριστερά"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Εναλλαγή από διαχωρισμό οθόνης σε πλήρη οθόνη"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Εναλλαγή στην εφαρμογή δεξιά ή κάτω κατά τη χρήση διαχωρισμού οθόνης"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Εναλλαγή σε εφαρμογή αριστερά ή επάνω κατά τη χρήση διαχωρισμού οθόνης"</string>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index e4c6854..d4545ff 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Ανενεργό"</item>
     <item msgid="5137565285664080143">"Ενεργό"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Μη διαθέσιμη"</item>
+    <item msgid="3079622119444911877">"Ανενεργή"</item>
+    <item msgid="3028994095749238254">"Ενεργή"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index a8848a5..459de64 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Lock screen"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total silence"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"See all"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Features like Quick Share, Find My Device and device location use Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth will turn on tomorrow at 5.00 a.m."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Features like Quick Share and Find My Device use Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth will turn on tomorrow morning"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio sharing"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Sharing audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bug report"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"High"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Open settings"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked, too many authentication attempts"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked – too many authentication attempts"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Device locked\nFailed authentication"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
index 304abe1..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Off"</item>
     <item msgid="5137565285664080143">"On"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Unavailable"</item>
+    <item msgid="3079622119444911877">"Off"</item>
+    <item msgid="3028994095749238254">"On"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 4b69255..4879850 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick settings and Notification shade."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Lock screen"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total silence"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"See all"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio Sharing"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Features like Quick Share, Find My Device, and device location use Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth will turn on tomorrow at 5 AM"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Features like Quick Share and Find My Device use Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth will turn on tomorrow morning"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio Sharing"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Sharing Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Record Issue"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bug Report"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string>
@@ -367,6 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string>
@@ -432,6 +437,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customize"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -450,6 +456,9 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Open settings"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
+    <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Customize widgets"</string>
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -741,7 +750,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard Shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -766,9 +775,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to app on right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to app on left or above while using split screen"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a8848a5..459de64 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Lock screen"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total silence"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"See all"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Features like Quick Share, Find My Device and device location use Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth will turn on tomorrow at 5.00 a.m."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Features like Quick Share and Find My Device use Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth will turn on tomorrow morning"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio sharing"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Sharing audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bug report"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"High"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Open settings"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked, too many authentication attempts"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked – too many authentication attempts"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Device locked\nFailed authentication"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
index 304abe1..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Off"</item>
     <item msgid="5137565285664080143">"On"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Unavailable"</item>
+    <item msgid="3079622119444911877">"Off"</item>
+    <item msgid="3028994095749238254">"On"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a8848a5..459de64 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Lock screen"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total silence"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"See all"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatically turn on again tomorrow"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Features like Quick Share, Find My Device and device location use Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth will turn on tomorrow at 5.00 a.m."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Features like Quick Share and Find My Device use Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth will turn on tomorrow morning"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio sharing"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Sharing audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bug report"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"What part of your device experience was affected?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Select issue type"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Screen record"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medium"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"High"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hearing devices"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hearing devices"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Pair new device"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Open settings"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Unpause work apps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Unpause"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Close widgets on lock screen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets on lock screen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked, too many authentication attempts"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Device was locked – too many authentication attempts"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Device locked\nFailed authentication"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Keyboard shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Open Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Enter split screen with current app to RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Enter split screen with current app to LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use split screen with current app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use split screen with current app on the left"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Switch from split screen to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
index 304abe1..39dd7c8 100644
--- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Off"</item>
     <item msgid="5137565285664080143">"On"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Unavailable"</item>
+    <item msgid="3079622119444911877">"Off"</item>
+    <item msgid="3028994095749238254">"On"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 3ed9fc5..a2340bd 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎Notification shade.‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‎Quick settings.‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎Quick settings and Notification shade.‎‏‎‎‏‎"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎Lock screen.‎‏‎‎‏‎"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎Lock screen‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎Work lock screen‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎Close‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎total silence‎‏‎‎‏‎"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎See all‎‏‎‎‏‎"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎Use Bluetooth‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎Connected‎‏‎‎‏‎"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎Audio Sharing‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎Saved‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎disconnect‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎activate‎‏‎‎‏‎"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‎Automatically turn on again tomorrow‎‏‎‎‏‎"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎Features like Quick Share, Find My Device, and device location use Bluetooth‎‏‎‎‏‎"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎Bluetooth will turn on tomorrow at 5 AM‎‏‎‎‏‎"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎Features like Quick Share and Find My Device use Bluetooth‎‏‎‎‏‎"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎Bluetooth will turn on tomorrow morning‎‏‎‎‏‎"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎Audio Sharing‎‏‎‎‏‎"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎Sharing Audio‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎Audio‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎Headset‎‏‎‎‏‎"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎Record Issue‎‏‎‎‏‎"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎Start‎‏‎‎‏‎"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎Stop‎‏‎‎‏‎"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎Bug Report‎‏‎‎‏‎"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎What part of your device experience was affected?‎‏‎‎‏‎"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‎Select issue type‎‏‎‎‏‎"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎Screen record‎‏‎‎‏‎"</string>
@@ -367,6 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‎Hearing devices‎‏‎‎‏‎"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎Pair new device‎‏‎‎‏‎"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎Click to pair new device‎‏‎‎‏‎"</string>
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‎Couldn\'t update preset‎‏‎‎‏‎"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎Unblock device microphone?‎‏‎‎‏‎"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎Unblock device camera?‎‏‎‎‏‎"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎Unblock device camera and microphone?‎‏‎‎‏‎"</string>
@@ -432,6 +437,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎Widgets on lock screen‎‏‎‎‏‎"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎Swipe left to start the communal tutorial‎‏‎‎‏‎"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‎Customize‎‏‎‎‏‎"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎Dismiss‎‏‎‎‏‎"</string>
@@ -450,6 +456,9 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎Open settings‎‏‎‎‏‎"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‎Unpause work apps?‎‏‎‎‏‎"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎Unpause‎‏‎‎‏‎"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎Close widgets on lock screen‎‏‎‎‏‎"</string>
+    <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎Customize widgets‎‏‎‎‏‎"</string>
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎Widgets on lock screen‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎Switch user‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎pulldown menu‎‏‎‎‏‎"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎All apps and data in this session will be deleted.‎‏‎‎‏‎"</string>
@@ -741,7 +750,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎Switch keyboard layout‎‏‎‎‏‎"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‎‎‎or‎‏‎‎‏‎"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎Clear search query‎‏‎‎‏‎"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎Shortcuts‎‏‎‎‏‎"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎Keyboard Shortcuts‎‏‎‎‏‎"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎Search shortcuts‎‏‎‎‏‎"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎No shortcuts found‎‏‎‎‏‎"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎System‎‏‎‎‏‎"</string>
@@ -766,9 +775,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎Open assistant‎‏‎‎‏‎"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎Lock screen‎‏‎‎‏‎"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎Take a note‎‏‎‎‏‎"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎System multitasking‎‏‎‎‏‎"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎Enter split screen with current app to RHS‎‏‎‎‏‎"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎Enter split screen with current app to LHS‎‏‎‎‏‎"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎Multitasking‎‏‎‎‏‎"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎Use split screen with current app on the right‎‏‎‎‏‎"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‎Use split screen with current app on the left‎‏‎‎‏‎"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎Switch from split screen to full screen‎‏‎‎‏‎"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎Switch to app on right or below while using split screen‎‏‎‎‏‎"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎Switch to app on left or above while using split screen‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 3755fb6..202bd93 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silencio total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Ver todos"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Uso compartido de audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Volver a activar automáticamente mañana"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Las funciones como Quick Share, Encontrar mi dispositivo y la ubicación del dispositivo usan Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Se activará el Bluetooth mañana a las 5 a.m."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Las funciones como Quick Share y Encontrar mi dispositivo usan Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"El Bluetooth se activará mañana a la mañana"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Uso compartido de audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Compartiendo audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Grabar error"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Detener"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Informe de errores"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"¿Qué parte de tu exp. del disp. se vio afectada?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Seleccionar tipo de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Grabadora de pant."</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estándar"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular dispositivo nuevo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para vincular un dispositivo nuevo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Quieres desbloquear el micrófono del dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Quieres desbloquear la cámara del dispositivo?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza el dedo a la izquierda para iniciar el instructivo comunal"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Descartar"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Abrir configuración"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"¿Reanudar apps de trabajo?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reanudar"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Cerrar widgets en la pantalla de bloqueo"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets en la pantalla de bloqueo"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú expandible"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
@@ -668,7 +675,7 @@
     <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string>
     <string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sin sonido ni vibración"</string>
-    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en la parte inferior de la sección de conversaciones."</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en la parte inferior de la sección de conversaciones"</string>
     <string name="notification_channel_summary_default" msgid="777294388712200605">"Puede sonar o vibrar según la configuración del dispositivo"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Puede sonar o vibrar según la configuración del dispositivo. Conversaciones de la burbuja de <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Dejar que el sistema determine si esta notificación debe emitir un sonido o una vibración"</string>
@@ -715,7 +722,7 @@
     <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Flecha hacia arriba"</string>
     <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Flecha hacia abajo"</string>
     <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha a la izquierda"</string>
-    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha hacia la derecha"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha a la derecha"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centro"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Espacio"</string>
@@ -743,10 +750,10 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificaciones"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ver combinaciones de teclas"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string>
-    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o bien"</string>
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar búsqueda"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string>
-    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar comb. de teclas"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Combinaciones de teclas"</string>
+    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar combinaciones de teclas"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No hay comb. de teclas"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
@@ -770,12 +777,12 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Asistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloquear la pantalla"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Crear una nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Tareas múltiples del sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Activar pantalla dividida con la app actual en el lado derecho (RHS)"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Activar pantalla dividida con la app actual en el lado izquierdo (LHS)"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Tareas múltiples"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar la pantalla dividida con la app actual a la derecha"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar la pantalla dividida con la app actual a la izquierda"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Cambiar de pantalla dividida a pantalla completa"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ubica la app a la derecha o abajo cuando usas la pantalla dividida"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ubica la app a la izquierda o arriba cuando usas la pantalla dividida"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ubicar la app a la derecha o abajo cuando usas la pantalla dividida"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ubicar la app a la izquierda o arriba cuando usas la pantalla dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Durante pantalla dividida: Reemplaza una app con otra"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Cambiar al próximo idioma"</string>
@@ -1001,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover arriba a la derecha"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover abajo a la izquierda"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover abajo a la derecha"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover fuera de borde y ocultar"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover al borde y ocultar"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover fuera de borde y mostrar"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Quitar"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activar o desactivar"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está activa}many{# apps están activas}other{# apps están activas}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nueva información"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps activas"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas apps están activas y en ejecución, incluso mientras no las usas. Esto mejora su funcionalidad, pero también afecta la duración de batería."</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas apps están activas y en ejecución, incluso mientras no las usas. Esto mejora su funcionalidad, pero también afecta la duración de la batería."</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Detener"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Detenida"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Listo"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Accede a controles de la casa como prot. de pant."</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Accede rápidamente a controles de la casa como prot. de pantalla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index 71efef9..869efff 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desactivado"</item>
     <item msgid="5137565285664080143">"Activado"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"No disponibles"</item>
+    <item msgid="3079622119444911877">"Desactivados"</item>
+    <item msgid="3028994095749238254">"Activados"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 01afa29..88fab2d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ajustes rápidos"</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silencio total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Ver todos"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartir audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Volver a activar automáticamente mañana"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Las funciones como Quick Share y Encontrar mi dispositivo, y la ubicación del dispositivo usan Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"El Bluetooth se activará mañana a las 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Las funciones como Quick Share y Encontrar mi dispositivo usan Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"El Bluetooth se activará mañana por la mañana"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Compartir audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Compartiendo audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problema de grabación"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Detener"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Informe errores"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"¿Qué parte de tu experiencia se ha visto afectada?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecciona el tipo de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Grabar pantalla"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estándar"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Audífonos"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audífonos"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Emparejar nuevo dispositivo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para emparejar un nuevo dispositivo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Desbloquear el micrófono del dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Desbloquear la cámara del dispositivo?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza hacia la izquierda para iniciar el tutorial de la comunidad"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Cerrar"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Abrir ajustes"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"¿Reactivar apps de trabajo?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reactivar"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Cerrar widgets en la pantalla de bloqueo"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets en la pantalla de bloqueo"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar de usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
@@ -481,7 +488,7 @@
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cuando compartes, grabas o envías una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
     <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Empezar"</string>
     <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha inhabilitado esta opción"</string>
-    <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"¿Empezar a enviar contenido?"</string>
+    <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"¿Empezar a enviar?"</string>
     <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cuando envías contenido, Android puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
     <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cuando envías una aplicación, Android puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
     <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Empezar a enviar"</string>
@@ -714,8 +721,8 @@
     <string name="keyboard_key_back" msgid="4185420465469481999">"Atrás"</string>
     <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Flecha hacia arriba"</string>
     <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Flecha hacia abajo"</string>
-    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha hacia la izquierda"</string>
-    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha hacia la derecha"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha izquierda"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha derecha"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centro"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabulador"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Espacio"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar la consulta de búsqueda"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Combinaciones de teclas"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar combinaciones de teclas"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ninguna encontrada"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -769,10 +776,10 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir ajustes"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir el Asistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Escribe una nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Función multitarea del sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Iniciar pantalla dividida con esta aplicación en el lado derecho"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Iniciar pantalla dividida con esta aplicación en el lado izquierdo"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Escribir una nota"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarea"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar la pantalla dividida con la aplicación actual a la derecha"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar la pantalla dividida con la aplicación actual a la izquierda"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Cambiar de pantalla dividida a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Cambiar a la app de la derecha o de abajo en pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Cambiar a la app de la izquierda o de arriba en pantalla dividida"</string>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index bd90056..5dbb2c1 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desactivado"</item>
     <item msgid="5137565285664080143">"Activado"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"No disponibles"</item>
+    <item msgid="3079622119444911877">"Desactivados"</item>
+    <item msgid="3028994095749238254">"Activados"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 52cbb0f..1b4cea7 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Märguande vari."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kiirseaded."</string>
     <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_lock_screen" msgid="409034672704273634">"Lukustuskuva"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Töö lukustuskuva"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sulgemine"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"täielik vaikus"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Kuva kõik"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Kasuta Bluetoothi"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ühendatud"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Heli jagamine"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvestatud"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkesta ühendus"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveeri"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Lülita automaatselt homme uuesti sisse"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funktsioonid, nagu Kiirjagamine, Leia mu seade ja seadme asukoht, kasutavad Bluetoothi"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth lülitatakse sisse homme kell viis hommikul"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funktsioonid, nagu Kiirjagamine ja Leia mu seade, kasutavad Bluetoothi"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth lülitub sisse homme hommikul"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Heli jagamine"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Heli jagamine"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> akut"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Heli"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Peakomplekt"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Probleemi salvestamine"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Alusta"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Peata"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Veaaruanne"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Millist seadme kasutuskogemuse osa see mõjutas?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Valige probleemi tüüp"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekraanisalvestus"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Tavaline"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Keskmine"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Kõrge"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuuldeseadmed"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuuldeseadmed"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uue seadme sidumine"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Uue seadme sidumiseks klõpsake"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kas tühistada seadme mikrofoni blokeerimine?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kas tühistada seadme kaamera blokeerimine?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kiirlaadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Lukustuskuva vidinad"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ühise õpetuse käivitamiseks pühkige vasakule"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Kohandage"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Loobuge"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ava seaded"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Kas lõpetada töörakenduste peatamine?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Lõpeta peatamine"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Lukustuskuva vidinate sulgemine"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Lukustuskuva vidinad"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rippmenüü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatuuripaigutuse vahetus"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"või"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Otsingupäringu tühjendamine"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Otseteed"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klaviatuuri otseteed"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Otseteede otsing"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Otseteid ei leitud"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Süsteem"</string>
@@ -769,10 +776,10 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Seadete avamine"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistendi avamine"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukustuskuva"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Kirjuta märkus"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Süsteemi multitegumtöö"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Ekraanikuva jagamine, nii et praegune rakendus on paremal"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Ekraanikuva jagamine, nii et praegune rakendus on vasakul"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Märkme tegemine"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitegumtöö"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Jagatud ekraanikuva kasutamine, praegune rakendus kuvatakse paremal"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Jagatud ekraanikuva kasutamine, praegune rakendus kuvatakse vasakul"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Jagatud ekraanikuvalt täisekraanile lülitamine"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Paremale või alumisele rakendusele lülitamine jagatud ekraani ajal"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vasakule või ülemisele rakendusele lülitamine jagatud ekraani ajal"</string>
@@ -1001,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Teisalda üles paremale"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Teisalda alla vasakule"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Teisalda alla paremale"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Teisalda serva ja kuva"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Teisalda serva ja peida"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Teisalda servast eemale ja kuva"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Eemalda"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"lülita"</string>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index 55bff30..704649e 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Väljas"</item>
     <item msgid="5137565285664080143">"Sees"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Pole saadaval"</item>
+    <item msgid="3079622119444911877">"Välja lülitatud"</item>
+    <item msgid="3028994095749238254">"Sisse lülitatud"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index b0056f6..b69ef30 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Jakinarazpenen panela."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ezarpen bizkorrak."</string>
     <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_lock_screen" msgid="409034672704273634">"Pantaila blokeatua"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Laneko pantaila blokeatua"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Itxi"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"isiltasun osoa"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Ikusi guztiak"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Erabili Bluetootha"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Konektatuta"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audioa partekatzea"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gordeta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deskonektatu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktibatu"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktibatu automatikoki berriro bihar"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Quick Share, Bilatu nire gailua, gailuaren kokapena eta beste eginbide batzuek Bluetootha darabilte"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetootha bihar 05:00etan aktibatuko da"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share, Bilatu nire gailua eta beste eginbide batzuek Bluetootha erabiltzen dute"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bihar goizean aktibatuko da Bluetootha"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audioa partekatzea"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audioa partekatzen"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audioa"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Entzungailua"</string>
@@ -329,13 +332,13 @@
     <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Laneko aplikazioak"</string>
     <string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"Pausatuta"</string>
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Gaueko argia"</string>
-    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ilunabarrean"</string>
+    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Ilunabarrean aktibatuta"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Ilunabarrera arte"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> arte"</string>
     <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Gai iluna"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Bateria-aurreztailea"</string>
-    <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuko da"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuta"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Desaktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Arazo bat dago grabaketarekin"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Hasi"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Gelditu"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Akatsen txostena"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Gailuaren erabileraren zer alderdiri eragin dio?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Hautatu arazo mota"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Pantaila-grabaketa"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Arrunta"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Tartekoa"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Altua"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Entzumen-gailuak"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Entzumen-gailuak"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parekatu beste gailu bat"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Egin klik beste gailu bat parekatzeko"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Gailuaren mikrofonoa desblokeatu nahi duzu?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Gailuaren kamera desblokeatu nahi duzu?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bizkor kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pantaila blokeatuko widgetak"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Tutorial komuna hasteko, pasatu hatza ezkerrera"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pertsonalizatu"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Baztertu"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ireki ezarpenak"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Laneko aplikazioak berraktibatu?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Berraktibatu"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Itxi pantaila blokeatuko widgetak"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Pantaila blokeatuko widgetak"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Aldatu erabiltzailea"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"zabaldu menua"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
@@ -737,7 +744,7 @@
     <string name="keyboard_key_numpad_template" msgid="7316338238459991821">"Zenbaki-teklatuko <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"Kendu eranskina"</string>
     <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"Sistema"</string>
-    <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Hasierako pantaila"</string>
+    <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Orri nagusia"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Azkenaldikoak"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Atzera"</string>
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Jakinarazpenak"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"edo"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Garbitu bilaketa-kontsulta"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lasterbideak"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ireki Laguntzailea"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Egin ohar bat"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Zereginen aldibereko sistemaren exekuzioa"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Sartu pantaila zatituaren eskuineko aldean oraingo aplikazioarekin"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Sartu pantaila zatituaren ezkerreko aldean oraingo aplikazioarekin"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Zeregin bat baino gehiago aldi berean exekutatzea"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Erabili pantaila zatitua eta ezarri aplikazio hau eskuinean"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Erabili pantaila zatitua eta ezarri aplikazio hau ezkerrean"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Aldatu pantaila zatitutik pantaila osora"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Aldatu eskuineko edo beheko aplikaziora pantaila zatitua erabiltzean"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Aldatu ezkerreko edo goiko aplikaziora pantaila zatitua erabiltzean"</string>
@@ -790,8 +797,8 @@
     <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>
-    <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="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulagailua"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"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>
@@ -1125,7 +1132,7 @@
     <string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string>
     <string name="select_conversation_title" msgid="6716364118095089519">"Elkarrizketa-widgetak"</string>
     <string name="select_conversation_text" msgid="3376048251434956013">"Sakatu elkarrizketa bat orri nagusian gehitzeko"</string>
-    <string name="no_conversations_text" msgid="5354115541282395015">"Azken elkarrizketak agertuko dira hemen"</string>
+    <string name="no_conversations_text" msgid="5354115541282395015">"Azkenaldiko elkarrizketak agertuko dira hemen"</string>
     <string name="priority_conversations" msgid="3967482288896653039">"Lehentasunezko elkarrizketak"</string>
     <string name="recent_conversations" msgid="8531874684782574622">"Azken elkarrizketak"</string>
     <string name="days_timestamp" msgid="5821854736213214331">"Duela <xliff:g id="DURATION">%1$s</xliff:g> egun"</string>
@@ -1151,7 +1158,7 @@
     <string name="status_before_loading" msgid="1500477307859631381">"Laster agertuko da edukia"</string>
     <string name="missed_call" msgid="4228016077700161689">"Dei galdua"</string>
     <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
-    <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerari buruzko informazio eguneratua"</string>
+    <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerei buruzko informazio eguneratua"</string>
     <string name="people_tile_title" msgid="6589377493334871272">"Elkarrizketa"</string>
     <string name="paused_by_dnd" msgid="7856941866433556428">"Ez molestatzeko moduak pausatu du"</string>
     <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak mezu bat bidali du: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
@@ -1304,6 +1311,6 @@
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) aplikazioak erabili du duela gutxi"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Teklatuaren hondoko argia"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d/%2$d maila"</string>
-    <string name="home_controls_dream_label" msgid="6567105701292324257">"Etxeko gailuak kontrolatzeko aukerak"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Atzitu etxeko gailuak kontrolatzeko aukerak pantaila-babesletik"</string>
+    <string name="home_controls_dream_label" msgid="6567105701292324257">"Etxeko gailuen kontrola"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Kontrolatu etxeko gailuak pantaila-babesletik"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index 7f38d44..13e14e0 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desaktibatuta"</item>
     <item msgid="5137565285664080143">"Aktibatuta"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Ez daude erabilgarri"</item>
+    <item msgid="3079622119444911877">"Desaktibatuta"</item>
+    <item msgid="3028994095749238254">"Aktibatuta"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index de97db35..94fb12f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مجموعه اعلان."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"تنظیمات سریع."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"تنظیمات فوری و کشوی اعلانات."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"صفحه قفل."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"صفحه قفل"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"صفحه قفل کاری"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"بستن"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"سکوت کامل"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"دیدن همه"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"استفاده از بلوتوث"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متصل"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"اشتراک صدا"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ذخیره‌شده"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"قطع اتصال"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کردن"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"فردا دوباره به‌طور خودکار روشن شود"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ویژگی‌هایی مثل «هم‌رسانی سریع»، «پیدا کردن دستگاهم»، و مکان دستگاه از بلوتوث استفاده می‌کنند"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"بلوتوث فردا ۵ ق.ظ روشن خواهد شد"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ویژگی‌هایی مثل «هم‌رسانی سریع» و «پیدا کردن دستگاهم» از بلوتوث استفاده می‌کنند"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"بلوتوث فردا صبح روشن خواهد شد"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"اشتراک صدا"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"درحال اشتراک‌گذاری صدا"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"شارژ باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"صوت"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"هدست"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ضبط مشکل"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"شروع"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"توقف"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"گزارش اشکال"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"کدام بخش تجربه استفاده از دستگاه تحت‌تأثیر قرار گرفت؟"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"انتخاب نوع مشکل"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ضبط صفحه‌نمایش"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"استاندارد"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"متوسط"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"بالا"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سمعک"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سمعک"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"جفت کردن دستگاه جدید"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"برای جفت کردن دستگاه جدید، کلیک کنید"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"میکروفون دستگاه لغو انسداد شود؟"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"دوربین دستگاه لغو انسداد شود؟"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن سریع • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن آهسته • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ابزارک‌ها در صفحه قفل"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"برای شروع آموزش گام‌به‌گام عمومی، تند به‌چپ بکشید"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"سفارشی‌سازی"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"بستن"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"باز کردن تنظیمات"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"مکث برنامه‌های کاری لغو شود؟"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"لغو مکث"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"بستن ابزارک‌ها در صفحه قفل"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ابزارک‌ها در صفحه قفل"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تغییر کاربر"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"منوی پایین‌پر"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامه‌ها و داده‌های این جلسه حذف خواهد شد."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"این دستگاه را ولی‌تان مدیریت می‌کند. ولی‌تان می‌تواند اطلاعاتی مثل برنامه‌هایی که استفاده می‌کنید، مکانتان، و مدت تماشای صفحه‌تان را ببیند و مدیریت کند."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"‏با TrustAgent قفل را باز نگه‌دارید"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"دستگاه قفل شد، تعداد تلاش‌ها برای اصالت‌سنجی بسیار زیاد بود"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"به‌دلیل تلاش‌های بیش‌از حد برای اصالت‌سنجی، دستگاه قفل شد"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"دستگاه قفل شد\nاصالت‌سنجی ناموفق بود"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. ‏<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"تنظیمات صدا"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر جانمایی صفحه‌کلید"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"یا"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"پاک کردن پُرسمان جستجو"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"میان‌برها"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"میان‌برهای صفحه‌کلید"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"باز کردن «دستیار»"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"قفل صفحه"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"یادداشت‌برداری"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"چندوظیفگی سیستم"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"وارد شدن به صفحهٔ دونیمه با برنامه فعلی در سمت راست"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"وارد شدن به صفحهٔ دونیمه با برنامه فعلی در سمت چپ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"چندوظیفگی"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"استفاده از صفحهٔ دونیمه با برنامه فعلی در سمت راست"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"استفاده از صفحهٔ دونیمه با برنامه فعلی در سمت چپ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"جابه‌جایی از صفحهٔ دونیمه به تمام صفحه"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"رفتن به برنامه سمت راست یا پایین درحین استفاده از صفحهٔ دونیمه"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"رفتن به برنامه سمت چپ یا بالا درحین استفاده از صفحهٔ دونیمه"</string>
@@ -1304,6 +1311,6 @@
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"اخیراً <xliff:g id="APP_NAME">%1$s</xliff:g> از آن استفاده کرده است (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"نور پس‌زمینه صفحه‌کلید"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"‏سطح %1$d از %2$d"</string>
-    <string name="home_controls_dream_label" msgid="6567105701292324257">"کنترل‌های لوازم خانگی"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"دسترسی سریع به کنترل‌های لوازم خانگی به‌عنوان محافظ صفحه‌نمایش"</string>
+    <string name="home_controls_dream_label" msgid="6567105701292324257">"کنترل خانه هوشمند"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"به کنترل خانه هوشمند به‌عنوان محافظ صفحه‌نمایش دسترسی سریع دارید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index 9a6b1af..756b442 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"خاموش"</item>
     <item msgid="5137565285664080143">"روشن"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"دردسترس نیست"</item>
+    <item msgid="3079622119444911877">"خاموش"</item>
+    <item msgid="3028994095749238254">"روشن"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 55413a0..a7754b0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -120,7 +120,7 @@
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Lopeta"</string>
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Jaa"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Näyttötallenne tallennettu"</string>
-    <string name="screenrecord_save_text" msgid="3008973099800840163">"Napauta näyttääksesi"</string>
+    <string name="screenrecord_save_text" msgid="3008973099800840163">"Katso napauttamalla"</string>
     <string name="screenrecord_save_error" msgid="5862648532560118815">"Virhe näyttötallenteen tallentamisessa"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Virhe näytön tallennuksen aloituksessa"</string>
     <string name="issuerecord_title" msgid="286627115110121849">"Ongelman tallentaja"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ilmoitusalue."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Pika-asetukset."</string>
     <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_lock_screen" msgid="409034672704273634">"Lukitusnäyttö"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Työlukitusnäyttö"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sulje"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"hiljennä kaikki"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Näytä kaikki"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Käytä Bluetoothia"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Yhdistetty"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audionjako"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Tallennettu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkaise yhteys"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivoi"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Laita automaattisesti päälle taas huomenna"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Ominaisuudet (esim. Quick Share ja Paikanna laite) ja laitteen sijainti käyttävät Bluetoothia"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth käynnistetään huomenna klo 5.00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share, Paikanna laite ja tietyt muut ominaisuudet käyttävät Bluetoothia"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth menee päälle huomisaamuna"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audionjako"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audiota jaetaan"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ääni"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Tallenna ongelma"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Aloita"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Lopeta"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Virheraportti"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Mitä osaa käyttökokemuksesta ongelma koski?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Valitse ongelman tyyppi"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Näytön tallentaja"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Tavallinen"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Keskitaso"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Suuri"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Kuulolaitteet"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuulolaitteet"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Muodosta uusi laitepari"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Muodosta uusi laitepari klikkaamalla"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kumotaanko laitteen mikrofonin esto?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kumotaanko laitteen kameran esto?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu nopeasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetit lukitusnäytöllä"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aloita yhteisöesittely pyyhkäisemällä vasemmalle"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Muokkaa"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hylkää"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Avaa asetukset"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Laita työsovellukset päälle?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Laita päälle"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Sulje widgetit lukitusnäytöllä"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgetit lukitusnäytöllä"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Vaihda käyttäjää"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"alasvetovalikko"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Vaihda näppäimistöasettelu"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"tai"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Tyhjennä hakulauseke"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pikanäppäimet"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Pikanäppäimet"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hae pikanäppäimiä"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Pikanäppäimiä ei löytynyt"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Järjestelmä"</string>
@@ -770,17 +777,17 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Avaa Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukitusnäyttö"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Tee muistiinpano"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Järjestelmän monikäyttö"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Siirry jaettuun näyttöön (sovellus oikeanpuoleiseen näyttöön)"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Siirry jaettuun näyttöön (sovellus vasemmanpuoleiseen näyttöön)"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitaskaus"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Käytä jaettua näyttöä niin, että nyt käytettävä sovellus on oikealla"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Käytä jaettua näyttöä niin, että nyt käytettävä sovellus on vasemmalla"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Vaihda jaetusta näytöstä koko näyttöön"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Vaihda sovellukseen oikealla tai alapuolella jaetun näytön avulla"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vaihda sovellukseen vasemmalla tai yläpuolella jaetun näytön avulla"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Vaihda sovellukseen oikealla tai alapuolella jaetussa näytössä"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vaihda sovellukseen vasemmalla tai yläpuolella jaetussa näytössä"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Jaetun näytön aikana: korvaa sovellus toisella"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Syöttötapa"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Vaihda seuraavaan kieleen"</string>
     <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Vaihda aiempaan kieleen"</string>
-    <string name="input_access_emoji" msgid="8105642858900406351">"Emojin käyttö"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"Emojien käyttö"</string>
     <string name="input_access_voice_typing" msgid="7291201476395326141">"Puhekirjoituksen käyttö"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Sovellukset"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Assistant"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# sovellus on aktiivinen}other{# sovellusta aktiivisena}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"Uutta tietoa"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aktiiviset sovellukset"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Nämä sovellukset ovat aktiivisia ja ne ovat käynnissä, vaikka et käyttäisi niitä. Näin sovellusten toimivuus paranee, mutta se voi vaikutta akunkestoon."</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Nämä sovellukset ovat aktiivisia ja käynnissä, vaikka et käyttäisi niitä. Näin sovellusten toimivuus paranee, mutta ne voivat vaikuttaa akunkestoon."</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Pysäytä"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Pysäytetty"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Valmis"</string>
@@ -1269,7 +1276,7 @@
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Asenna työpuhelinsovellus"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Peruuta"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Muokkaa lukitusnäyttöä"</string>
-    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Avaa lukitus muokataksesi lukitusnäyttöä"</string>
+    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Voit muokata lukitusnäyttöä, kun avaat lukituksen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi-yhteys ei ole käytettävissä"</string>
     <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera estetty"</string>
     <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ja mikrofoni estetty"</string>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index f1e3e61..5ecc9595 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Pois päältä"</item>
     <item msgid="5137565285664080143">"Päällä"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Ei saatavilla"</item>
+    <item msgid="3079622119444911877">"Pois päältä"</item>
+    <item msgid="3028994095749238254">"Päällä"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-feminine/strings.xml b/packages/SystemUI/res/values-fr-feminine/strings.xml
index ebdc3fb..16c16e1 100644
--- a/packages/SystemUI/res/values-fr-feminine/strings.xml
+++ b/packages/SystemUI/res/values-fr-feminine/strings.xml
@@ -20,6 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
-    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invitée"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-masculine/strings.xml b/packages/SystemUI/res/values-fr-masculine/strings.xml
index 6b94970..411af1f 100644
--- a/packages/SystemUI/res/values-fr-masculine/strings.xml
+++ b/packages/SystemUI/res/values-fr-masculine/strings.xml
@@ -20,6 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
-    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-neuter/strings.xml b/packages/SystemUI/res/values-fr-neuter/strings.xml
index e9d0191..4a4ac5a 100644
--- a/packages/SystemUI/res/values-fr-neuter/strings.xml
+++ b/packages/SystemUI/res/values-fr-neuter/strings.xml
@@ -20,6 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
-    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité·e"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 272e00e..5bacaaa 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Paramètres rapides"</string>
     <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_lock_screen" msgid="409034672704273634">"É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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"aucune interruption"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Tout afficher"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Déconnecter"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"Activer"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Activer le Bluetooth automatiquement demain"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Les fonctionnalités comme le Partage rapide, Localiser mon appareil et la position de l\'appareil utilisent le Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Le Bluetooth s\'activera demain à 5 h"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Les fonctionnalités comme Partage rapide et Localiser mon appareil utilisent le Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Le Bluetooth s\'activera demain matin"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Partage audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Partage de l\'audio en cours…"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Écouteurs"</string>
@@ -294,7 +297,7 @@
     <string name="quick_settings_user_title" msgid="8673045967216204537">"Utilisateur"</string>
     <string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
     <string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
-    <string name="quick_settings_networks_available" msgid="1875138606855420438">"Réseaux accessibles"</string>
+    <string name="quick_settings_networks_available" msgid="1875138606855420438">"Réseaux disponibles"</string>
     <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Aucun réseau accessible"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Aucun réseau Wi-Fi à proximité"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Activation en cours…"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Rapporter le problème"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Commencer"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Arrêter"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Rapport de bogue"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Quelle composante de l\'appareil a été affectée?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Sélectionner un type"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Enregistrement écran"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Moyen"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Élevé"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Appareils auditifs"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquez ici pour associer un nouvel appareil"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le microphone de l\'appareil?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer l\'appareil photo de l\'appareil?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer l\'écran vers la gauche pour démarrer le tutoriel communautaire"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string>
@@ -448,14 +451,16 @@
     <string name="button_to_remove_widget" msgid="3948204829181214098">"Retirer"</string>
     <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ajouter un widget"</string>
     <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Terminé"</string>
-    <!-- no translation found for label_for_button_in_empty_state_cta (7314975555382055823) -->
-    <skip />
-    <!-- no translation found for title_for_empty_state_cta (6161654421223450530) -->
-    <skip />
+    <string name="label_for_button_in_empty_state_cta" msgid="7314975555382055823">"Ajouter des widgets"</string>
+    <string name="title_for_empty_state_cta" msgid="6161654421223450530">"Accédez rapidement aux widgets de vos applications préférées sans déverrouiller votre tablette."</string>
     <string name="dialog_title_to_allow_any_widget" msgid="1004820948962675644">"Autoriser n\'importe quel widget sur l\'écran de verrouillage?"</string>
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ouvrir les paramètres"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Réactiver les applis pros?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Réactiver"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fermer les widgets sur l\'écran de verrouillage"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets sur l\'écran de verrouillage"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
@@ -553,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par ton parent. Ton parent peut voir et gérer de l\'information, comme les applications que tu utilises, ta position et ton temps d\'utilisation des écrans."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"RPV"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Maintenu déverrouillé par TrustAgent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"L\'appareil a été verrouillé, trop de tentatives d\'authentification"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"L\'appareil a été verrouillé : trop de tentatives d\'authentification"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Appareil verrouillé\nÉchec de l\'authentification"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Paramètres sonores"</string>
@@ -747,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Effacez la requête de recherche"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Raccourcis-clavier"</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>
@@ -772,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ouvrir l\'Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Écran de verrouillage"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Prendre une note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Passer à l\'écran divisé avec l\'application actuelle à droite"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Passer à l\'écran divisé avec l\'application actuelle à gauche"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitâche"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utiliser l\'Écran divisé avec l\'application actuelle à droite"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utiliser l\'Écran divisé avec l\'application actuelle à gauche"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Passer de l\'écran divisé au plein écran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passer à l\'application à droite ou en dessous avec l\'Écran divisé"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passer à l\'application à gauche ou au-dessus avec l\'Écran divisé"</string>
@@ -1003,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Déplacer dans coin sup. droit"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Déplacer dans coin inf. gauche"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Déplacer dans coin inf. droit"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Éloigner du bord et masquer"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Rapprocher du bord et masquer"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Éloigner du bord et afficher"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Retirer"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"basculer"</string>
@@ -1307,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Domotique"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Accès rapide : domot. sous forme d\'Écran de veille"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Accès rapide : domotique sous forme d\'Écran de veille"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index dfea45a..52b763b 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Désactivée"</item>
     <item msgid="5137565285664080143">"Activée"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Non accessible"</item>
+    <item msgid="3079622119444911877">"Désactivé"</item>
+    <item msgid="3028994095749238254">"Activé"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 41f9249..a4a039f1 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
     <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_lock_screen" msgid="409034672704273634">"É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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"aucune interruption"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Tout afficher"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"dissocier"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activer"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Réactiver automatiquement demain"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Certaines fonctionnalités telles que Quick Share, Localiser mon appareil ou encore la position de l\'appareil utilisent le Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Le Bluetooth sera activé demain à 5h00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Certaines fonctionnalités, telles que Quick Share et Localiser mon appareil, utilisent le Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Le Bluetooth sera activé demain matin"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Partage audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audio partagé"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batterie"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Casque"</string>
@@ -286,7 +289,7 @@
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotation automatique de l\'écran"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"Localisation"</string>
     <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Économiseur d\'écran"</string>
-    <string name="quick_settings_camera_label" msgid="5612076679385269339">"Accès à la caméra"</string>
+    <string name="quick_settings_camera_label" msgid="5612076679385269339">"Accès à l\'appareil photo"</string>
     <string name="quick_settings_mic_label" msgid="8392773746295266375">"Accès au micro"</string>
     <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponible"</string>
     <string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloqué"</string>
@@ -298,7 +301,7 @@
     <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Réseaux non disponibles"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Aucun réseau Wi-Fi disponible"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Activation…"</string>
-    <string name="quick_settings_cast_title" msgid="2279220930629235211">"Diffusion de l\'écran"</string>
+    <string name="quick_settings_cast_title" msgid="2279220930629235211">"Diffusion écran"</string>
     <string name="quick_settings_casting" msgid="1435880708719268055">"Diffusion"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Appareil sans nom"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Aucun appareil disponible."</string>
@@ -344,12 +347,13 @@
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string>
-    <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Enregistrement de l\'écran"</string>
+    <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Enregistr. écran"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string>
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Enregistrer le problème"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Début"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Arrêter"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Rapport de bug"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Quel problème avez-vous rencontré avec votre appareil ?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Sélectionnez un type de problème"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Enregistrement de l\'écran"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Moyen"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Élevé"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Prothèses auditives"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquer pour associer un nouvel appareil"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le micro de l\'appareil ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer la caméra de l\'appareil ?"</string>
@@ -400,7 +402,7 @@
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'écran Récents"</string>
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
-    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+    <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string>
     <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personnaliser"</string>
     <string name="zen_silence_introduction_voice" msgid="853573681302712348">"Cette option permet de bloquer TOUS les sons et les vibrations, y compris pour les alarmes, la musique, les vidéos et les jeux. Vous pourrez encore passer des appels téléphoniques."</string>
     <string name="zen_silence_introduction" msgid="6117517737057344014">"Cette option permet de bloquer TOUS les sons et les vibrations, y compris pour les alarmes, la musique, les vidéos et les jeux."</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge rapide • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer vers la gauche pour démarrer le tutoriel collectif"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ouvrir les paramètres"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Réactiver les applis pro ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Réactiver"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fermer les widgets sur l\'écran de verrouillage"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets sur l\'écran de verrouillage"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
@@ -637,7 +644,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Lecteur de code QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Lecteur code QR"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mise à jour"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
@@ -745,8 +752,8 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer disposition du clavier"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Effacer la requête de recherche"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
-    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Raccourcis de recherche"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Raccourcis clavier"</string>
+    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Rechercher 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">"Saisie"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Ouvrir l\'Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Verrouiller l\'écran"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Créer une note"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Passer en écran partagé avec l\'appli actuelle affichée à droite"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Passer en écran partagé avec l\'appli actuelle affichée à gauche"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitâche"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utiliser l\'écran partagé avec l\'appli actuelle sur la droite"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utiliser l\'écran partagé avec l\'appli actuelle sur la gauche"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Passer de l\'écran partagé au plein écran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passez à l\'appli à droite ou en dessous avec l\'écran partagé"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passez à l\'appli à gauche ou au-dessus avec l\'écran partagé"</string>
@@ -1247,7 +1254,7 @@
     <string name="home_quick_affordance_unavailable_configure_the_app" msgid="604424593994493281">"• Au moins un appareil ou un panneau de l\'appareil est disponible"</string>
     <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Sélectionnez une appli de notes par défaut pour utiliser le raccourci de prise de notes"</string>
     <string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Sélectionner une appli"</string>
-    <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur raccourci"</string>
+    <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur le raccourci"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Changer d\'écran maintenant"</string>
     <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Déplier le téléphone"</string>
@@ -1269,7 +1276,7 @@
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installer une appli professionnelle pour téléphoner"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Annuler"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personnaliser écran verrouillage"</string>
-    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouiller pour personnaliser l\'écran de verrouillage"</string>
+    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouillez pour personnaliser l\'écran de verrouillage"</string>
     <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>
@@ -1284,7 +1291,7 @@
     <string name="mirror_display" msgid="2515262008898122928">"Dupliquer l\'écran"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Fermer"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Écran connecté"</string>
-    <string name="privacy_dialog_title" msgid="7839968133469098311">"Micro et caméra"</string>
+    <string name="privacy_dialog_title" msgid="7839968133469098311">"Micro et appareil photo"</string>
     <string name="privacy_dialog_summary" msgid="2458769652125995409">"Utilisation récente par les applis"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Consulter les accès récents"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"OK"</string>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index 34ccb75..23c124c 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -88,8 +88,8 @@
   </string-array>
   <string-array name="tile_states_color_correction">
     <item msgid="2840507878437297682">"Indisponible"</item>
-    <item msgid="1909756493418256167">"Désactivé"</item>
-    <item msgid="4531508423703413340">"Activé"</item>
+    <item msgid="1909756493418256167">"Désactivée"</item>
+    <item msgid="4531508423703413340">"Activée"</item>
   </string-array>
   <string-array name="tile_states_inversion">
     <item msgid="3638187931191394628">"Indisponible"</item>
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Désactivé"</item>
     <item msgid="5137565285664080143">"Activé"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Non disponible"</item>
+    <item msgid="3079622119444911877">"Désactivé"</item>
+    <item msgid="3028994095749238254">"Activé"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 189f048..e2b1e53 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel despregable"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
     <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_lock_screen" msgid="409034672704273634">"Bloqueo de pantalla"</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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silencio total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Ver todo"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Estableceuse a conexión"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio compartido"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gardouse"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Volver activar automaticamente mañá"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"As funcións como Quick Share, Localizar o meu dispositivo ou a de localización do dispositivo utilizan o Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"O Bluetooth activarase mañá ás 05:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"As funcións como Quick Share e Localizar o meu dispositivo utilizan o Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"O Bluetooth activarase mañá á mañá"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio compartido"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Compartindo audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Rexistrar problema"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Deter"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Informe de erros"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cal foi o problema na experiencia co dispositivo?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecciona o tipo de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravación de pant."</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Nivel estándar"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Nivel medio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Nivel alto"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincular un dispositivo novo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic para vincular un novo dispositivo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Queres desbloquear o micrófono do dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Queres desbloquear a cámara do dispositivo?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rapidamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na pantalla de bloqueo"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Pasa o dedo cara á esquerda para iniciar o titorial comunitario"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Pechar"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Abrir configuración"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Reactivar apps do traballo?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reactivar"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Ocultar os widgets na pantalla de bloqueo"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets na pantalla de bloqueo"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú despregable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
@@ -632,7 +639,7 @@
     <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
     <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura un método de pago para comprar de xeito máis rápido e seguro co teléfono"</string>
     <string name="wallet_app_button_label" msgid="7123784239111190992">"Amosar todo"</string>
-    <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Tocar para abrir"</string>
+    <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Toca para abrir"</string>
     <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Actualizando"</string>
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar deseño do teclado"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar a busca"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atallos"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atallos de teclado"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar atallos"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Non se atoparon atallos"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Asistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Crear nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Activar pantalla dividida con esta aplicación no lado dereito"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Activar pantalla dividida con esta aplicación no lado esquerdo"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefa"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar pantalla dividida coa aplicación actual na dereita"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar pantalla dividida coa aplicación actual na esquerda"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Cambiar de pantalla dividida a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Cambiar á aplicación da dereita ou de abaixo coa pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Cambiar á aplicación da esquerda ou de arriba coa pantalla dividida"</string>
@@ -997,10 +1004,10 @@
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toca para mostrar o botón Accesibilidade"</string>
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Quitouse o atallo de <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Quitouse # atallo}other{Quitáronse # atallos}}"</string>
-    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover á parte super. esquerda"</string>
-    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover á parte superior dereita"</string>
-    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover á parte infer. esquerda"</string>
-    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover á parte inferior dereita"</string>
+    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba á esquerda"</string>
+    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover arriba á dereita"</string>
+    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover abaixo á esquerda"</string>
+    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover abaixo á dereita"</string>
     <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover ao bordo e ocultar"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Mover fóra do bordo e mostrar"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Quitar"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Controis domóticos"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Controis domóticos como protector de pantalla"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Usa os controis domóticos como protector de pantalla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index de8ee63..03b934e 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desactivado"</item>
     <item msgid="5137565285664080143">"Activado"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Non dispoñibles"</item>
+    <item msgid="3079622119444911877">"Desactivados"</item>
+    <item msgid="3028994095749238254">"Activados"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 54312e1..2883cc5 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"નોટિફિકેશન શેડ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ઝડપી સેટિંગ અને નોટિફિકેશન શેડ."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"લૉક સ્ક્રીન."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"લૉક સ્ક્રીન"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"કાર્ય લૉક સ્ક્રીન"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"બંધ કરો"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"બિલકુલ અવાજ નહીં"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"તમામ જુઓ"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"બ્લૂટૂથનો ઉપયોગ કરો"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"કનેક્ટેડ છે"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ઑડિયો શેરિંગ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"સાચવેલું"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ડિસ્કનેક્ટ કરો"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"સક્રિય કરો"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"આવતીકાલે ફરીથી ઑટોમૅટિક રીતે ચાલુ કરો"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ક્વિક શેર, Find My Device અને ડિવાઇસના લોકેશન જેવી સુવિધાઓ બ્લૂટૂથનો ઉપયોગ કરે છે"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"બ્લૂટૂથ આવતીકાલે સવારે 5 વાગ્યે ચાલુ થશે"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ક્વિક શેર અને Find My Device જેવી સુવિધાઓ બ્લૂટૂથનો ઉપયોગ કરે છે"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"બ્લૂટૂથ આવતીકાલે સવારે ચાલુ થશે"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ઑડિયો શેરિંગ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ઑડિયો શેર કરી રહ્યાં છીએ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> બૅટરી"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ઑડિયો"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"હૅડસેટ"</string>
@@ -333,7 +336,7 @@
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"સૂર્યોદય સુધી"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> સુધી"</string>
-    <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ઘેરી થીમ"</string>
+    <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ડાર્ક થીમ"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"બૅટરી સેવર"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"સૂર્યાસ્ત વખતે"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"રેકોર્ડિંગમાં સમસ્યા"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"શરૂ કરો"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"રોકો"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"બગ રિપોર્ટ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ડિવાઇસ સંબંધી તમારા અનુભવના કયા ભાગને અસર થઈ હતી?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"સમસ્યાનો પ્રકાર પસંદ કરો"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"સ્ક્રીન રેકોર્ડ કરો"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"સ્ટૅન્ડર્ડ"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"મધ્યમ"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"વધુ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"સાંભળવામાં મદદ આપતા ડિવાઇસ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"નવા ડિવાઇસ સાથે જોડાણ કરવા માટે ક્લિક કરો"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ડિવાઇસના માઇક્રોફોનને અનબ્લૉક કરીએ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ડિવાઇસના કૅમેરાને અનબ્લૉક કરીએ?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ઝડપથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"લૉક સ્ક્રીન પર વિજેટ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ડાબે સ્વાઇપ કરો"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"કસ્ટમાઇઝ કરો"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"છોડી દો"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"સેટિંગ ખોલો"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ઑફિસની થોભાવેલી ઍપ ચાલુ કરીએ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ફરી ચાલુ કરો"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"લૉક સ્ક્રીન પર વિજેટ બંધ કરો"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"લૉક સ્ક્રીન પર વિજેટ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"પુલડાઉન મેનૂ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ અને ડેટા કાઢી નાખવામાં આવશે."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"કીબોર્ડ લેઆઉટ સ્વિચ કરો"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"અથવા"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"શોધ ક્વેરી સાફ કરો"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"શૉર્ટકટ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"કીબોર્ડ શૉર્ટકટ"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ખોલો"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"લૉક સ્ક્રીન"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"નોંધ લો"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"સિસ્ટમ દ્વારા એકથી વધુ કાર્યો કરવા"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"જમણી બાજુ પર હાલની ઍપ સાથે વિભાજિત સ્ક્રીનમાં દાખલ થાઓ"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"ડાબી બાજુ પર હાલની ઍપ સાથે વિભાજિત સ્ક્રીનમાં દાખલ થાઓ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"એકસાથે એકથી વધુ કાર્યો કરવા"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"જમણી બાજુએ વર્તમાન ઍપ સાથે વિભાજિત સ્ક્રીનનો ઉપયોગ કરો"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ડાબી બાજુએ વર્તમાન ઍપ સાથે વિભાજિત સ્ક્રીનનો ઉપયોગ કરો"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"વિભાજિત સ્ક્રીનથી પૂર્ણ સ્ક્રીન પર સ્વિચ કરો"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરતી વખતે જમણી બાજુ કે નીચેની ઍપ પર સ્વિચ કરો"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરતી વખતે ડાબી બાજુની કે ઉપરની ઍપ પર સ્વિચ કરો"</string>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index c6a86e5..5c4a478 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"બંધ"</item>
     <item msgid="5137565285664080143">"ચાલુ"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"અનુપલબ્ધ"</item>
+    <item msgid="3079622119444911877">"બંધ છે"</item>
+    <item msgid="3028994095749238254">"ચાલુ છે"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ee3e40b..f30957d 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"त्वरित सेटिंग."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग और नोटिफ़िकेशन शेड."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"लॉक स्क्रीन"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"वर्क लॉक स्‍क्रीन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करें"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"कोई आवाज़ सुनाई नहीं देगी"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"सभी देखें"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लूटूथ इस्तेमाल करें"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट है"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडियो शेयर करने की सुविधा"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव किया गया"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिसकनेक्ट करें"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"चालू करें"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"कल फिर से अपने-आप चालू हो जाएगा"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"क्विक शेयर, Find My Device, और डिवाइस की जगह की जानकारी का पता लगाने जैसी सुविधाएं, ब्लूटूथ का इस्तेमाल करती हैं"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"कल सुबह 5 बजे ब्लूटूथ चालू हो जाएगा"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"क्विक शेयर और Find My Device जैसी सुविधाएं, ब्लूटूथ का इस्तेमाल करती हैं"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ब्लूटूथ कल सुबह चालू होगा"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ऑडियो शेयर करने की सुविधा"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ऑडियो शेयर किया जा रहा है"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> बैटरी"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ऑडियो"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"समस्या रिकॉर्ड करें"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"शुरू करें"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"रोकें"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"गड़बड़ी की रिपोर्ट"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"आपके डिवाइस की कौनसी सुविधा पर असर पड़ा था?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"समस्या का टाइप चुनें"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"स्क्रीन रिकॉर्डर"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"स्टैंडर्ड"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"सामान्य"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ज़्यादा"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"कान की मशीनें"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"कान की मशीनें"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नया डिवाइस जोड़ें"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नया डिवाइस जोड़ने के लिए क्लिक करें"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आपको डिवाइस का माइक्रोफ़ोन अनब्लॉक करना है?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आपको डिवाइस का कैमरा अनब्लॉक करना है?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • तेज़ चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीन पर विजेट"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, बाईं ओर स्वाइप करें"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"पसंद के मुताबिक बनाएं"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारिज करें"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"सेटिंग खोलें"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"वर्क ऐप्लिकेशन चालू करने हैं?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"चालू करें"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लॉक स्क्रीन पर विजेट बंद करें"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लॉक स्क्रीन पर विजेट"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सेशन के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
@@ -499,7 +506,7 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"मैनेज करें"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"नई सूचनाएं"</string>
-    <string name="notification_section_header_gentle" msgid="6804099527336337197">"बिना आवाज़ किए मिलने वाली सूचनाएं"</string>
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"साइलेंट मोड में मिली सूचनाएं"</string>
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचनाएं"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"बातचीत"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"बिना आवाज़ की सभी सूचनाएं हटाएं"</string>
@@ -552,7 +559,7 @@
     <string name="legacy_vpn_name" msgid="4174223520162559145">"वीपीएन"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent की वजह से अनलॉक रखा गया है"</string>
     <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"कई बार पुष्टि करने की कोशिश की वजह से, डिवाइस लॉक है"</string>
-    <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"डिवाइस लॉक है\nपुष्टि नहीं की जा सकी."</string>
+    <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"डिवाइस लॉक हो गया है\nपुष्टि नहीं की जा सकी"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"साउंड सेटिंग"</string>
     <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ऑडियो-वीडियो से अपने-आप कैप्शन बनना"</string>
@@ -678,7 +685,7 @@
     <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;स्थिति:&lt;/b&gt; रैंकिंग में नीचे किया गया"</string>
     <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"यह कई तरीकों से दिखती है, जैसे कि लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर और बातचीत वाली सूचनाओं में सबसे ऊपर"</string>
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"यह कई तरीकों से दिखती है, जैसे कि बातचीत वाली सूचनाओं में सबसे ऊपर, बबल के तौर पर, और लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर"</string>
-    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"यह कई तरीकों से दिखती है, जैसे कि लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर और बातचीत वाली सूचनाओं में सबसे ऊपर. साथ ही, इसकी वजह से, \'परेशान न करें\' सुविधा में भी रुकावट आती है"</string>
+    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"यह लॉक स्क्रीन पर, बातचीत वाली सूचनाओं में सबसे ऊपर और प्रोफ़ाइल फ़ोटो के साथ दिखती है. साथ ही, यह \'परेशान न करें\' मोड को बायपास कर सकती है."</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"यह कई तरीकों से दिखती है, जैसे कि बातचीत वाली सूचनाओं में सबसे ऊपर, बबल के तौर पर, और लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर. साथ ही, यह \'परेशान न करें\' मोड को बायपास कर सकती है"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर बातचीत की सुविधाएं काम नहीं करतीं"</string>
@@ -745,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट बदलें"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"या"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"सर्च क्वेरी साफ़ करें"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"कीबोर्ड शॉर्टकट"</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_open_apps" msgid="1450959949739257562">"ऐप्लिकेशन खोलने के लिए"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"मौजूदा ऐप्लिकेशन"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"खोज के नतीजे दिखाए जा रहे हैं"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"सिस्टम के शॉर्टकट दिखाए जा रहे हैं"</string>
@@ -759,8 +766,8 @@
     <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"मौजूदा ऐप्लिकेशन के लिए शॉर्टकट दिखाए जा रहे हैं"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचनाएं देखने के लिए"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रीनशॉट लेने के लिए"</string>
-    <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट दिखाने के लिए"</string>
-    <string name="group_system_go_back" msgid="2730322046244918816">"वापस पीछे जाने के लिए"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट देखने के लिए"</string>
+    <string name="group_system_go_back" msgid="2730322046244918816">"वापस जाने के लिए"</string>
     <string name="group_system_access_home_screen" msgid="4130366993484706483">"होम स्क्रीन पर जाने के लिए"</string>
     <string name="group_system_overview_open_apps" msgid="5659958952937994104">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने के लिए"</string>
     <string name="group_system_cycle_forward" msgid="5478663965957647805">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन के अगले पेज पर जाने के लिए"</string>
@@ -768,14 +775,14 @@
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"ऐप्लिकेशन की सूची खोलने के लिए"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"सेटिंग खोलने के लिए"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Google Assistant खोलने के लिए"</string>
-    <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट करें"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टम मल्टीटास्किंग"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"स्प्लिट स्क्रीन का इस्तेमाल करके, मौजूदा ऐप्लिकेशन को दाईं ओर ले जाएं"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"स्प्लिट स्क्रीन का इस्तेमाल करके, मौजूदा ऐप्लिकेशन को बाईं ओर ले जाएं"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रीन लॉक करने के लिए"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट करने के लिए"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टीटास्किंग (एक साथ कई काम करना)"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"मौजूदा ऐप्लिकेशन को दाईं ओर दिखाने वाली स्प्लिट स्क्रीन इस्तेमाल करें"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"मौजूदा ऐप्लिकेशन को बाईं ओर दिखाने वाली स्प्लिट स्क्रीन इस्तेमाल करें"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"स्प्लिट स्क्रीन से फ़ुल स्क्रीन मोड पर स्विच करने के लिए"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन इस्तेमाल करते समय दाईं ओर या नीचे के ऐप पर स्विच करें"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन इस्तेमाल करते समय बाईं ओर या ऊपर के ऐप पर स्विच करें"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन पर, दाईं ओर या नीचे के ऐप पर स्विच करने के लिए"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन पर, बाईं ओर या ऊपर के ऐप पर स्विच करने के लिए"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"स्प्लिट स्क्रीन के दौरान: एक ऐप्लिकेशन को दूसरे ऐप्लिकेशन से बदलें"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"इनपुट"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"अगली भाषा पर स्विच करने के लिए"</string>
@@ -829,7 +836,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>
@@ -1001,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सबसे ऊपर दाईं ओर ले जाएं"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"सबसे नीचे बाईं ओर ले जाएं"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"सबसे नीचे दाईं ओर ले जाएं"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"एज पर ले जाएं और छिपाएं"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"किनारे ले जाएं और छिपाएं"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"एज से निकालें और दिखाएं"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"हटाएं"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"टॉगल करें"</string>
@@ -1123,7 +1130,7 @@
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
     <string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string>
-    <string name="select_conversation_title" msgid="6716364118095089519">"बातचीत विजेट"</string>
+    <string name="select_conversation_title" msgid="6716364118095089519">"बातचीत वाला विजेट"</string>
     <string name="select_conversation_text" msgid="3376048251434956013">"किसी बातचीत को होम स्क्रीन पर जोड़ने के लिए, उस बातचीत पर टैप करें"</string>
     <string name="no_conversations_text" msgid="5354115541282395015">"हाल ही में हुई बातचीत यहां दिखेंगी"</string>
     <string name="priority_conversations" msgid="3967482288896653039">"अहम बातचीत"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# ऐप्लिकेशन चालू है}one{# ऐप्लिकेशन चालू है}other{# ऐप्लिकेशन चालू हैं}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"नई जानकारी"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"ये ऐप्लिकेशन चालू हैं"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"ये ऐप्लिकेशन चालू हैं और आपके इस्तेमाल न करने पर भी चल रहे हैं. इससे, ये बेहतर तरीके से फ़ंक्शन करते हैं. हालांकि, इससे बैटरी लाइफ़ पर भी असर पड़ सकता है."</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"ये ऐप्लिकेशन चालू हैं और आपके इस्तेमाल न करने पर भी चल रहे हैं. इससे ये बेहतर तरीके से काम कर पाते हैं. हालांकि, बैटरी लाइफ़ पर इसका असर पड़ सकता है."</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"बंद करें"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"बंद है"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"हो गया"</string>
@@ -1286,7 +1293,7 @@
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"डिसप्ले कनेक्ट किया गया"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"माइक्रोफ़ोन और कैमरा"</string>
     <string name="privacy_dialog_summary" msgid="2458769652125995409">"हाल ही में इस्तेमाल करने वाला ऐप्लिकेशन"</string>
-    <string name="privacy_dialog_more_button" msgid="7610604080293562345">"हाल में ऐक्सेस करने वाले ऐप"</string>
+    <string name="privacy_dialog_more_button" msgid="7610604080293562345">"हाल में ऐक्सेस करने वाला ऐप"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"हो गया"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"बड़ा करें और विकल्प दिखाएं"</string>
     <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"छोटा करें"</string>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index 0cb06c0..b89eeb3 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"बंद है"</item>
     <item msgid="5137565285664080143">"चालू है"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"उपलब्ध नहीं हैं"</item>
+    <item msgid="3079622119444911877">"बंद हैं"</item>
+    <item msgid="3028994095749238254">"चालू हैं"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index a1d885a..bada67e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -119,7 +119,7 @@
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"Prikaz dodira na zaslonu"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Dijeli"</string>
-    <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimanje zaslona spremljeno"</string>
+    <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimanje zaslona je spremljeno"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Dodirnite za prikaz"</string>
     <string name="screenrecord_save_error" msgid="5862648532560118815">"Pogreška prilikom spremanja snimke zaslona"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Pogreška prilikom pokretanja snimanja zaslona"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon obavijesti."</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_lock_screen" msgid="5983125095181194887">"Zaključavanje zaslona."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključavanje zaslona"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključani zaslon radnog profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvaranje"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"potpuna tišina"</string>
@@ -270,19 +270,22 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Pogledajte sve"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zajedničko slušanje"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Spremljeno"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekini vezu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviraj"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatski ponovo uključi sutra"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Značajke kao što su brzo dijeljenje, Pronađi moj uređaj i lokacija uređaja upotrebljavaju Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth će se uključiti sutra u 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Značajke kao što su brzo dijeljenje i Pronađi moj uređaj koriste Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth će se uključiti sutra ujutro"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Zajedničko slušanje"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Zajedničko slušanje"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> baterije"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalice"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Unos"</string>
     <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Slušna pomagala"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključivanje…"</string>
-    <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. zakretanje"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatsko zakretanje"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko zakretanje zaslona"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
     <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Čuvar zaslona"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Zabilježi poteškoću"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Pokreni"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zaustavi"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Izvješće o pogrešci"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Na koji dio doživljaja na uređaju to utjecalo?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Odaberite vrstu problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje zaslona"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardni"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednji"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visoki"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušna pomagala"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni uređaji"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uparivanje novog uređaja"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili novi uređaj"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite li deblokirati mikrofon uređaja?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite li deblokirati kameru uređaja?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • brzo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeti na zaključanom zaslonu"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prijeđite prstom ulijevo da biste pokrenuli zajednički vodič"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otvori postavke"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Pokrenuti poslovne aplikacije?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Ponovno pokreni"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zatvaranje widgeta na zaključanom zaslonu"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgeti na zaključanom zaslonu"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Promjena korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Izbrisat će se sve aplikacije i podaci u ovoj sesiji."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promjena rasporeda tipkovnice"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Brisanje upita za pretraživanje"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečaci"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tipkovni prečaci"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečace"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nema nijednog prečaca"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sustav"</string>
@@ -757,29 +764,29 @@
     <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Prikazuju se prečaci za unos"</string>
     <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Prikazuju se prečaci koji otvaraju aplikacije"</string>
     <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Prikazuju se prečaci za trenutačnu aplikaciju"</string>
-    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaži obavijesti"</string>
-    <string name="group_system_full_screenshot" msgid="5742204844232667785">"Snimi zaslon"</string>
+    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaz obavijesti"</string>
+    <string name="group_system_full_screenshot" msgid="5742204844232667785">"Snimanje zaslona"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Prikaži prečace"</string>
     <string name="group_system_go_back" msgid="2730322046244918816">"Natrag"</string>
-    <string name="group_system_access_home_screen" msgid="4130366993484706483">"Idi na početni zaslon"</string>
-    <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Prikaži nedavne aplikacije"</string>
-    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Kruži unaprijed kroz nedavne aplikacije"</string>
-    <string name="group_system_cycle_back" msgid="8194102916946802902">"Kruži unatrag kroz nedavne aplikacije"</string>
-    <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvori popis aplikacija"</string>
-    <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvori postavke"</string>
-    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvori Asistenta"</string>
+    <string name="group_system_access_home_screen" msgid="4130366993484706483">"Otvaranje početnog zaslona"</string>
+    <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Prikaz nedavnih aplikacija"</string>
+    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Kruženje unaprijed kroz nedavne aplikacije"</string>
+    <string name="group_system_cycle_back" msgid="8194102916946802902">"Kruženje unatrag kroz nedavne aplikacije"</string>
+    <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvaranje popisa aplikacija"</string>
+    <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvaranje postavki"</string>
+    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvaranje asistenta"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje zaslona"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Zapišite bilješku"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Obavljanje više zadataka sustava"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Otvori podijeljeni zaslon s trenutačnom aplikacijom s desne strane"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Otvori podijeljeni zaslon s trenutačnom aplikacijom s lijeve strane"</string>
-    <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prijeđi s podijeljenog zaslona na cijeli zaslon"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prijeđite na aplikaciju zdesna ili ispod uz podijeljeni zaslon"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prijeđite na aplikaciju slijeva ili iznad uz podijeljeni zaslon"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Obavljanje više zadataka"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Koristite podijeljeni zaslon s trenutačnom aplikacijom s desne strane"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Koristite podijeljeni zaslon s trenutačnom aplikacijom s lijeve strane"</string>
+    <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prelazak s podijeljenog zaslona na cijeli zaslon"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prelazak na aplikaciju zdesna ili ispod uz podijeljeni zaslon"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prelazak na aplikaciju slijeva ili iznad uz podijeljeni zaslon"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Tijekom podijeljenog zaslona: zamijeni aplikaciju drugom"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Unos"</string>
-    <string name="input_switch_input_language_next" msgid="3782155659868227855">"Prijeđi na sljedeći jezik"</string>
-    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Prijeđi na prethodni jezik"</string>
+    <string name="input_switch_input_language_next" msgid="3782155659868227855">"Prelazak na sljedeći jezik"</string>
+    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Prelazak na prethodni jezik"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"Pristupanje emojijima"</string>
     <string name="input_access_voice_typing" msgid="7291201476395326141">"Pristupanje unosu teksta govorom"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacije"</string>
@@ -1297,13 +1304,13 @@
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Koristi telefonski poziv"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Nedavno korišteno tijekom telefonskog poziva"</string>
     <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koristi: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno je koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koristi: <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Koristi: <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tipkovnice"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Razina %1$d od %2$d"</string>
-    <string name="home_controls_dream_label" msgid="6567105701292324257">"Upr. kuć. uređ."</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Brzo pristupajte Upr. kuć. uređ. kao čuvaru zasl."</string>
+    <string name="home_controls_dream_label" msgid="6567105701292324257">"Upravljanje uređajima"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Brzo upravljajte uređajima putem čuvara zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
index e09cab5..df0b786 100644
--- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Isključeno"</item>
     <item msgid="5137565285664080143">"Uključeno"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nedostupno"</item>
+    <item msgid="3079622119444911877">"Isključeno"</item>
+    <item msgid="3028994095749238254">"Uključeno"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index baea240..d216fa4 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"teljes némítás"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Összes megtekintése"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth használata"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Csatlakozva"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hang megosztása"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Mentve"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"leválasztás"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiválás"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatikus visszakapcsolás holnap"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Az olyan funkciók, mint a Quick Share, a Készülékkereső és az eszköz helyadatai Bluetootht használnak"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"A Bluetooth bekapcsol holnap reggel 5-kor"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Egyes funkciók (például a Quick Share és a Készülékkereső) Bluetootht használnak"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"A Bluetooth holnap reggel bekapcsol"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Hang megosztása"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Hang megosztása…"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Hang"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Probléma rögzítése"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Indítás"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Leállítás"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Hibajelentés"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Az eszközhasználati élmény mely része érintett?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Problématípus kiválasztása"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Képernyőrögzítés"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Normál"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Közepes"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Nagy"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hallókészülékek"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hallókészülékek"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Új eszköz párosítása"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kattintson új eszköz párosításához"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Feloldja az eszköz mikrofonjának letiltását?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Feloldja az eszköz kamerájának letiltását?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Gyors töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Modulok a lezárási képernyőn"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Csúsztasson gyorsan balra a közösségi útmutató elindításához"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Személyre szabás"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Elvetés"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Beállítások megnyitása"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Feloldja a munkahelyi appokat?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Szüneteltetés feloldása"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"A lezárási képernyőn lévő modulok bezárása"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Modulok a lezárási képernyőn"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Felhasználóváltás"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"lehúzható menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Billentyűzetkiosztás váltása"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"vagy"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Keresőkifejezés törlése"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Billentyűparancsok"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Billentyűparancsok"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Billentyűparancs keresése"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nincs billentyűparancs"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Rendszer"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"A Segéd megnyitása"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lezárási képernyő"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Jegyzetelés"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Rendszermultitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Osztott képernyő aktiválása; az aktuális alkalmazás kerüljön jobbra"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Osztott képernyő aktiválása; az aktuális alkalmazás kerüljön balra"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Osztott képernyő használata, a jelenlegi alkalmazás legyen jobb oldalt"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Osztott képernyő használata, a jelenlegi alkalmazás legyen bal oldalt"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Váltás osztott képernyőről teljes képernyőre"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Váltás a jobb oldalt, illetve lent lévő appra osztott képernyő esetén"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Váltás a bal oldalt, illetve fent lévő appra osztott képernyő esetén"</string>
@@ -1001,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Áthelyezés fel és jobbra"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Áthelyezés le és balra"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Áthelyezés le és jobbra"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Áthelyezés a szélen kívül és elrejtés"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Áthelyezés a szélére és elrejtés"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Áthelyezés a szélen kívül és mutatás"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Eltávolítás"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"váltás"</string>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index 8f75dc6..bbd6bc0 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Ki"</item>
     <item msgid="5137565285664080143">"Be"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nem áll rendelkezésre"</item>
+    <item msgid="3079622119444911877">"Ki"</item>
+    <item msgid="3028994095749238254">"Be"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 3f88746..034ac1a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ծանուցումների վահանակ:"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Արագ կարգավորումներ:"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Արագ կարգավորումներ և ծանուցումների վահանակ։"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Էկրանի կողպում:"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Կողպէկրան"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Աշխատանքային պրոֆիլի կողպէկրան"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Փակել"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"կատարյալ լռություն"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Տեսնել բոլորը"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Միացնել Bluetooth-ը"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Միացված է"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Աուդիոյի փոխանցում"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Պահված է"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"անջատել"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ակտիվացնել"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Վաղը նորից ավտոմատ միացնել"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Գործառույթները, ինչպիսիք են Quick Share-ը, «Գտնել իմ սարքը» գործառույթը և սարքի տեղորոշումը, օգտագործում են Bluetooth-ը"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth-ը կմիանա վաղը՝ ժամը 05։00-ին"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Bluetooth-ն օգտագործում են, օրինակ, Quick Share և «Գտնել իմ սարքը» գործառույթները"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth-ը կմիանա վաղն առավոտյան"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Աուդիոյի փոխանցում"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Աուդիոն փոխանցվում է"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Աուդիո"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ականջակալ"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Ձայնագրել"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Սկսել"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Կանգնեցնել"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Հաղորդում սխալի մասին"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Սարքի ո՞ր մասի հետ է կապված խնդիրը։"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Ընտրեք խնդրի տեսակը"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Էկրանի տեսագրում"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Սովորական"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Միջին"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Բարձր"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Լսողական սարքեր"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Լսողական սարքեր"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Նոր սարքի զուգակցում"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Սեղմեք՝ նոր սարք զուգակցելու համար"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Արգելահանե՞լ սարքի խոսափողը"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Արգելահանե՞լ սարքի տեսախցիկը"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Արագ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Վիջեթներ կողպէկրանին"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Թերթեք ձախ՝ ուղեցույցը գործարկելու համար"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Անհատականացնել"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Փակել"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Բացել կարգավորումները"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Վերսկսե՞լ աշխ. հավելվածները"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Վերսկսել"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Փակել վիջեթները կողպէկրանին"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Վիջեթներ կողպէկրանին"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Անջատել օգտվողին"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"իջնող ընտրացանկ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
@@ -720,7 +727,7 @@
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Բացատ"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Մուտք"</string>
-    <string name="keyboard_key_backspace" msgid="4095278312039628074">"Հետշարժ"</string>
+    <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string>
     <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Նվագարկում/դադար"</string>
     <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Կանգնեցնել"</string>
     <string name="keyboard_key_media_next" msgid="8502476691227914952">"Հաջորդը"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Դասավորության փոխարկում"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"կամ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ջնջել որոնման հարցումը"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Դյուրանցումներ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Ստեղնային դյուրանցումներ"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Բացել Օգնականը"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Կողպէկրան"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ստեղծել նշում"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Համակարգի բազմախնդրության ռեժիմ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Միացնել էկրանի տրոհումը՝ ընթացիկ հավելվածն աջ կողմում"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Միացնել էկրանի տրոհումը՝ ընթացիկ հավելվածը ձախ կողմում"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Բազմախնդրություն"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Աջ մասում օգտագործեք տրոհված էկրանն այս հավելվածի հետ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Ձախ մասում օգտագործեք տրոհված էկրանն այս հավելվածի հետ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Տրոհված էկրանից անցնել լիաէկրան ռեժիմ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Անցեք աջ կողմի կամ ներքևի հավելվածին տրոհված էկրանի միջոցով"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Անցեք աջ կողմի կամ վերևի հավելվածին տրոհված էկրանի միջոցով"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d՝ %2$d-ից"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարման տարրեր"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Օգտագործեք տան կառավարման տարրերը որպես էկրանապահ"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Տան կառավարման տարրերը դարձրեք էկրանապահ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index 118915d..eb77ccf 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Անջատված է"</item>
     <item msgid="5137565285664080143">"Միացված է"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Հասանելի չէ"</item>
+    <item msgid="3079622119444911877">"Անջատված է"</item>
+    <item msgid="3028994095749238254">"Միացված է"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0b07a32..d428ef8 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -119,7 +119,7 @@
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"Tampilkan lokasi sentuhan pada layar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Bagikan"</string>
-    <string name="screenrecord_save_title" msgid="1886652605520893850">"Perekaman layar disimpan"</string>
+    <string name="screenrecord_save_title" msgid="1886652605520893850">"Rekaman layar disimpan"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Ketuk untuk melihat"</string>
     <string name="screenrecord_save_error" msgid="5862648532560118815">"Terjadi error saat menyimpan rekaman layar"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Terjadi error saat memulai perekaman layar"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bayangan pemberitahuan."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setelan cepat."</string>
     <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_lock_screen" msgid="409034672704273634">"Kunci layar"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Layar kunci kantor"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"senyap total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Lihat semua"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Terhubung"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Berbagi Audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"putuskan koneksi"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Otomatis aktifkan lagi besok"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Fitur seperti Quick Share, Temukan Perangkat Saya, dan lokasi perangkat menggunakan Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth akan diaktifkan besok pada pukul 05.00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Fitur seperti Quick Share dan Temukan Perangkat Saya menggunakan Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth akan dinyalakan besok pagi"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Berbagi Audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Berbagi Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Mencatat Masalah"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Mulai"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Berhenti"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Laporan Bug"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Bagian pengalaman perangkat mana yang terpengaruh?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Pilih jenis masalah"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Perekaman layar"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standar"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Sedang"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Tinggi"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Alat bantu dengar"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Alat bantu dengar"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sambungkan perangkat baru"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menyambungkan perangkat baru"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Berhenti memblokir mikrofon perangkat?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Berhenti memblokir kamera perangkat?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan cepat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget di layar kunci"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Geser ke kiri untuk memulai tutorial komunal"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Tutup"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Buka setelan"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Batalkan jeda aplikasi kerja?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Batalkan jeda"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tutup widget di layar kunci"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget di layar kunci"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string>
@@ -594,7 +601,7 @@
     <string name="stream_accessibility" msgid="3873610336741987152">"Aksesibilitas"</string>
     <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Dering"</string>
     <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Getar"</string>
-    <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Nonaktifkan"</string>
+    <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Bisukan"</string>
     <string name="media_device_cast" msgid="4786241789687569892">"Transmisi"</string>
     <string name="stream_notification_unavailable" msgid="4313854556205836435">"Tidak tersedia - Volume dering dibisukan"</string>
     <string name="stream_alarm_unavailable" msgid="4059817189292197839">"Tidak tersedia - Fitur Jangan Ganggu aktif"</string>
@@ -638,7 +645,7 @@
     <string name="wallet_error_generic" msgid="257704570182963611">"Terjadi error saat mendapatkan kartu Anda, coba lagi nanti"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string>
     <string name="qr_code_scanner_title" msgid="1938155688725760702">"Pemindai kode QR"</string>
-    <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mengupdate"</string>
+    <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Update berlangsung"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -745,8 +752,8 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ganti tata letak keyboard"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"atau"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Hapus kueri penelusuran"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string>
-    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pintasan penelusuran"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Pintasan Keyboard"</string>
+    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Telusuri pintasan"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tidak ditemukan pintasan"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
@@ -763,16 +770,16 @@
     <string name="group_system_go_back" msgid="2730322046244918816">"Kembali"</string>
     <string name="group_system_access_home_screen" msgid="4130366993484706483">"Buka layar utama"</string>
     <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Lihat aplikasi terbaru"</string>
-    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Menavigasi maju pada aplikasi terbaru"</string>
-    <string name="group_system_cycle_back" msgid="8194102916946802902">"Menavigasi mundur pada aplikasi terbaru"</string>
+    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Berpindah-pindah aplikasi terbaru ke arah kanan"</string>
+    <string name="group_system_cycle_back" msgid="8194102916946802902">"Berpindah-pindah aplikasi terbaru ke arah kiri"</string>
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Buka daftar aplikasi"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Buka setelan"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Buka Asisten"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci layar"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Buat catatan"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking sistem"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Masuk ke layar terpisah dengan aplikasi saat ini ke RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Masuk ke layar terpisah dengan aplikasi saat ini ke LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gunakan layar terpisah dengan aplikasi saat ini di sebelah kanan"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gunakan layar terpisah dengan aplikasi saat ini di sebelah kiri"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Beralih dari layar terpisah ke layar penuh"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Beralih ke aplikasi di bagian kanan atau bawah saat menggunakan layar terpisah"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Beralih ke aplikasi di bagian kiri atau atas saat menggunakan layar terpisah"</string>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index bd429c1..a415f64 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Nonaktif"</item>
     <item msgid="5137565285664080143">"Aktif"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Tidak tersedia"</item>
+    <item msgid="3079622119444911877">"Nonaktif"</item>
+    <item msgid="3028994095749238254">"Aktif"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 56ea0d5..4b97299 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Tilkynningasvæði."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Flýtistillingar."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"algjör þögn"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Sjá allt"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Nota Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tengt"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hljóði deilt"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Vistað"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"aftengja"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"virkja"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Kveikja sjálfkrafa aftur á morgun"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Eiginleikar á borð við flýtideilingu, „Finna tækið mitt“ og staðsetningu tækis nota Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Kveikt verður á Bluetooth á morgun kl. 05:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Eiginleikar eins og Flýtideiling og Finna tækið mitt nota Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Kveikt verður á Bluetooth í fyrramálið"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Hljóði deilt"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Deilir hljóði"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> rafhlöðuhleðsla"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Hljóð"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Höfuðtól"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Vandamál tengt upptöku"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Byrja"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stöðva"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Villutilkynning"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Hvað í tækjaupplifuninni varð fyrir áhrifum?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Veldu gerð vandamáls"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skjáupptaka"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Staðlað"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Miðlungs"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Mikið"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Heyrnartæki"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Heyrnartæki"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Para nýtt tæki"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Smelltu til að para nýtt tæki"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Opna fyrir hljóðnema tækisins?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Opna fyrir myndavél tækisins?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hraðhleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Græjur á lásskjá"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Strjúktu til vinstri til að hefja samfélagsleiðsögnina"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sérsníða"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hunsa"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Opna stillingar"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Ljúka hléi vinnuforrita?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Ljúka hléi"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Loka græjum á lásskjá"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Græjur á lásskjá"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skipta um notanda"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Fellivalmynd"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skipta um lyklaskipan"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eða"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Hreinsa leitarfyrirspurn"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Flýtileiðir"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Flýtilyklar"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Leita að flýtileiðum"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Engar flýtileiðir fundust"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Kerfi"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Opna Hjálpara"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lásskjár"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Skrifa glósu"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Fjölvinnsla kerfis"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Opna skjáskiptingu hægra megin með núverandi forriti"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Opna skjáskiptingu vinstra megin með núverandi forriti"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Fjölvinnsla"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Notaðu skjáskiptingu með núverandi forriti til hægri"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Notaðu skjáskiptingu með núverandi forriti til vinstri"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Skipta úr skjáskiptingu yfir á allan skjáinn"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skiptu í forrit til hægri eða fyrir neðan þegar skjáskipting er notuð"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skiptu í forrit til vinstri eða fyrir ofan þegar skjáskipting er notuð"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Baklýsing lyklaborðs"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stig %1$d af %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Heimastýringar"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Fáðu skjótan aðgang að heimastýringum með því að stilla þær sem skjávara"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Fáðu skjótan aðgang að heimastýringum sem skjávara"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index abdc3e7..c9befd6 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Slökkt"</item>
     <item msgid="5137565285664080143">"Kveikt"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Ekki tiltækt"</item>
+    <item msgid="3079622119444911877">"Slökkt"</item>
+    <item msgid="3028994095749238254">"Kveikt"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 08f07ef..30bdfae 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Area notifiche."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Impostazioni rapide."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Area notifiche e Impostazioni rapide."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Schermata di blocco."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Schermata di blocco"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Schermata di blocco del profilo di lavoro"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Chiudi"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silenzio totale"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Visualizza tutti"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usa Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Dispositivo connesso"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Condivisione audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Dispositivo salvato"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnetti"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"attiva"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Riattiva automaticamente domani"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funzionalità come Quick Share, Trova il mio dispositivo e la posizione del dispositivo usano il Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Il Bluetooth verrà attivato domani alle 05:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funzionalità come Quick Share e Trova il mio dispositivo usano il Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Il Bluetooth verrà attivato domani mattina"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Condivisione audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Condivisione audio in corso…"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auricolare"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Registra problema"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Avvia"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Interrompi"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Segnalazione di bug"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Quali problemi ha l\'esperienza del dispositivo?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Seleziona il tipo di problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Regis. dello schermo"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Apparecchi acustici"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Protesi uditive"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Accoppia nuovo dispositivo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic per accoppiare un nuovo dispositivo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vuoi sbloccare il microfono del dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vuoi sbloccare la fotocamera del dispositivo?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica veloce • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget su schermata di blocco"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Scorri a sinistra per iniziare il tutorial della community"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizza"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chiudi"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Apri impostazioni"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Riattivare le app di lavoro?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Riattiva"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Chiudi widget su schermata di blocco"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget su schermata di blocco"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambio utente"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu a discesa"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
@@ -550,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Questo dispositivo è gestito da uno dei tuoi genitori, il quale può visualizzare e gestire informazioni come le app che usi, la tua posizione e il tuo tempo di utilizzo."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Sbloccato da TrustAgent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Dispositivo bloccato, troppi tentativi di autenticazione"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Dispositivo bloccato: troppi tentativi di autenticazione"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Dispositivo bloccato\nAutenticazione non riuscita"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Impostazioni audio"</string>
@@ -742,9 +750,9 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifiche"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Scorciatoie da tastiera"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambia layout della tastiera"</string>
-    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"oppure"</string>
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Cancella la query di ricerca"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Scorciatoie"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Scorciatoie da tastiera"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca scorciatoie"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Scorciatoie non trovate"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Apri l\'assistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Blocca lo schermo"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Scrivi una nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking di sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Attiva lo schermo diviso con l\'app corrente a destra"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Attiva lo schermo diviso con l\'app corrente a sinistra"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Utilizza schermo diviso con l\'app corrente a destra"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Utilizza schermo diviso con l\'app corrente a sinistra"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Passa da schermo diviso a schermo intero"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passa all\'app a destra o sotto mentre usi lo schermo diviso"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passa all\'app a sinistra o sopra mentre usi lo schermo diviso"</string>
@@ -1000,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sposta in alto a destra"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Sposta in basso a sinistra"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Sposta in basso a destra"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Sposta fino a bordo e nascondi"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Sposta fino al bordo e nascondi"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Sposta fuori da bordo e mostra"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Rimuovi"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"attiva/disattiva"</string>
@@ -1304,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroilluminazione della tastiera"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Livello %1$d di %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlli della casa"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Accedi ai controlli della casa dal salvaschermo"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Accedi rapidamente ai controlli della casa dal salvaschermo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 24ec785..bc1d91f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"לוח התראות."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"הגדרות מהירות."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"הגדרות מהירות ולוח ההתראות."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"מסך נעילה."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"מסך הנעילה"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"מסך נעילה של עבודה"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"סגירה"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"השתקה מוחלטת"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"הצגת הכול"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"מחובר"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"שיתוף אודיו"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"נשמר"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ניתוק"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"הפעלה"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"החיבור יופעל שוב אוטומטית מחר"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"‏תכונות כמו \'שיתוף מהיר\', \'איפה המכשיר שלי\' ומיקום המכשיר משתמשות בחיבור Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"‏‫Bluetooth יופעל מחר בשעה 5 בבוקר"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"‏תכונות כמו \'שיתוף מהיר\' ו\'איפה המכשיר שלי\' משתמשות ב-Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"‏חיבור ה-Bluetooth יופעל מחר בבוקר"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"שיתוף אודיו"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"מתבצע שיתוף של האודיו"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> סוללה"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"אודיו"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"אוזניות"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"תיעוד הבעיה"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"התחלה"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"עצירה"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"דיווח על באג"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"איזה חלק בחוויית השימוש שלך במכשיר הושפע?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"בחירה בסוג הבעיה"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"הקלטת המסך"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"רגילה"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"בינונית"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"גבוהה"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"מכשירי שמיעה"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"מכשירי שמיעה"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"התאמה של מכשיר חדש"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"צריך ללחוץ כדי להתאים מכשיר חדש"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"לבטל את חסימת המיקרופון של המכשיר?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"לבטל את חסימת המצלמה של המכשיר?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה מהירה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ווידג\'טים במסך הנעילה"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"אפשר להחליק שמאלה כדי להפעיל את המדריך המשותף"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"התאמה אישית"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"סגירה"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"לפתיחת ההגדרות"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"להפעיל את האפליקציות לעבודה?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ביטול ההשהיה"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"סגירת ווידג\'טים במסך הנעילה"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ווידג\'טים במסך הנעילה"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"החלפת משתמש"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"תפריט במשיכה למטה"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בסשן הזה יימחקו."</string>
@@ -481,10 +488,10 @@
     <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"‏בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
     <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"התחלה"</string>
     <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> השביתה את האפשרות הזו"</string>
-    <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"להתחיל את ההעברה?"</string>
+    <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"‏להפעיל Cast?"</string>
     <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"‏בזמן העברה (cast), תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
-    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‏בזמן העברה (cast) של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
-    <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"‏התחלת ההעברה (cast)"</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‏בזמן Cast מאפליקציה, תהיה ל-Android גישה לכל מה שמופיע באפליקציה ולכל מדיה שפועלת בה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+    <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"‏הפעלת Cast"</string>
     <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"להתחיל את השיתוף?"</string>
     <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"‏בזמן שיתוף, הקלטה או העברה (cast) תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
     <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"‏בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"החלפה של פריסת מקלדת"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"או"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ניקוי שאילתת החיפוש"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"מקשי קיצור"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"מקשי קיצור"</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>
@@ -757,7 +764,7 @@
     <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"מוצגים: קיצורי הדרך של הקלט"</string>
     <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"מוצגים: קיצורי הדרך לפתיחת אפליקציות"</string>
     <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"מוצגים: קיצורי הדרך של האפליקציה הנוכחית"</string>
-    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"הצגת הודעות"</string>
+    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"הצגת התראות"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"צילום המסך"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"הצגת מקשי הקיצור"</string>
     <string name="group_system_go_back" msgid="2730322046244918816">"חזרה"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"‏לפתיחת Google Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"מסך הנעילה"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"כתיבת הערה"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ריבוי משימות מערכת"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"‏כניסה למסך מפוצל עם האפליקציה הנוכחית ל-RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"‏כניסה למסך מפוצל עם האפליקציה הנוכחית ל-LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ריבוי משימות"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"שימוש במסך מפוצל כשהאפליקציה הנוכחית בצד ימין"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"שימוש במסך מפוצל כשהאפליקציה הנוכחית בצד שמאל"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"החלפה ממסך מפוצל למסך מלא"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"מעבר לאפליקציה משמאל או למטה בזמן שימוש במסך מפוצל"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"מעבר לאפליקציה מימין או למעלה בזמן שימוש במסך מפוצל"</string>
@@ -1247,7 +1254,7 @@
     <string name="home_quick_affordance_unavailable_configure_the_app" msgid="604424593994493281">"• יש לפחות מכשיר אחד או פאנל מכשיר אחד זמינים"</string>
     <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"צריך לבחור אפליקציית פתקים שתיפתח כברירת מחדל כשייעשה שימוש במקש הקיצור לכתיבת פתקים"</string>
     <string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"בחירת אפליקציה"</string>
-    <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"מקש קיצור ללחיצה ארוכה"</string>
+    <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"צריך ללחוץ לחיצה ארוכה על הלחצן"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ביטול"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"כן, אני רוצה להחליף בין המסכים"</string>
     <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"פתיחת הטלפון"</string>
@@ -1304,6 +1311,6 @@
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"נעשה שימוש לאחרונה על ידי <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"התאורה האחורית במקלדת"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"‏רמה %1$d מתוך %2$d"</string>
-    <string name="home_controls_dream_label" msgid="6567105701292324257">"ממשק השליטה במכשירים"</string>
+    <string name="home_controls_dream_label" msgid="6567105701292324257">"שליטה במכשירים"</string>
     <string name="home_controls_dream_description" msgid="4644150952104035789">"גישה מהירה לממשק השליטה במכשירים כשומר מסך"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 196a6c2..b5cb476 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"מושבת"</item>
     <item msgid="5137565285664080143">"מופעל"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"לא זמינים"</item>
+    <item msgid="3079622119444911877">"מצב מושבת"</item>
+    <item msgid="3028994095749238254">"מצב פעיל"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6e2ca40..b587f40 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -173,7 +173,7 @@
     <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"PIN が正しくありません"</string>
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"パターンが正しくありません"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"パスワードが正しくありません"</string>
-    <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"間違えた回数が上限を超えました。\n<xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"試行回数が上限に達しました。\n<xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。"</string>
     <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"緊急通報"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"もう一度お試しください。入力回数: <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> 回"</string>
     <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"データが削除されます"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知シェード"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"クイック設定"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"クイック設定と通知シェード。"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ロック画面"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ロック画面"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"仕事用プロファイルのロック画面"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"閉じる"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"サイレント"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"すべて表示"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth を使用"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"接続しました"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音声の共有"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"保存しました"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"接続を解除"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"有効化"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明日自動的に ON に戻す"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"クイック共有、デバイスを探す、デバイスの位置情報などの機能は Bluetooth を使用します"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"午前 5 時に Bluetooth が ON になります"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share や「デバイスを探す」などの機能は Bluetooth を使用します"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"明日の朝に Bluetooth が ON になります"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"音声の共有"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"音声を共有中"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"オーディオ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ヘッドセット"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"録音に関する問題"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"開始"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"バグレポート"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"デバイスのどの部分が影響を受けましたか?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"問題の種類を選択する"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"スクリーン レコード"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"補聴器"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"補聴器"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"新しいデバイスとペア設定"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"クリックすると、新しいデバイスをペア設定できます"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"デバイスのマイクのブロックを解除しますか?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"デバイスのカメラのブロックを解除しますか?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 急速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ロック画面のウィジェット"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"左にスワイプすると、コミュニティ チュートリアルが開始します"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"カスタマイズ"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"閉じる"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"設定を開く"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"仕事用アプリの停止解除"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"停止解除"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ロック画面のウィジェットを閉じる"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ロック画面のウィジェット"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ユーザーを切り替える"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"プルダウン メニュー"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
@@ -550,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"このデバイスは保護者によって管理されています。保護者は、あなたが使用するアプリ、あなたの現在地、デバイスの利用時間などの情報を確認したり、管理したりできます。"</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"信頼エージェントがロック解除を管理"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"認証の試行回数が上限を超えたため、デバイスがロックされました"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"認証の試行回数が上限に達したため、デバイスがロックされました"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"デバイスがロックされました\n認証に失敗しました"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"音声の設定"</string>
@@ -582,7 +590,7 @@
     <string name="screen_pinning_negative" msgid="6882816864569211666">"いいえ"</string>
     <string name="screen_pinning_start" msgid="7483998671383371313">"アプリを固定しました"</string>
     <string name="screen_pinning_exit" msgid="4553787518387346893">"アプリの固定を解除しました"</string>
-    <string name="stream_voice_call" msgid="7468348170702375660">"発信"</string>
+    <string name="stream_voice_call" msgid="7468348170702375660">"通話"</string>
     <string name="stream_system" msgid="7663148785370565134">"システム"</string>
     <string name="stream_ring" msgid="7550670036738697526">"着信音"</string>
     <string name="stream_music" msgid="2188224742361847580">"メディア"</string>
@@ -607,7 +615,7 @@
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"空間オーディオ"</string>
     <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"OFF"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"固定"</string>
-    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"ヘッド トラッキング"</string>
+    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"ヘ⁠ッ⁠ド ト⁠ラ⁠ッ⁠キ⁠ン⁠グ"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"タップすると、着信音のモードを変更できます"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"ミュート"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"ミュートを解除"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"キーボード レイアウトの切り替え"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"または"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"検索クエリをクリア"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ショートカット"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"キーボード ショートカット"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"アシスタントを開く"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"画面をロック"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"メモを入力する"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"システム マルチタスク"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"分割画面にして現在のアプリを右側に設定する"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"分割画面にして現在のアプリを左側に設定する"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"マルチタスク"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"分割画面の使用(現在のアプリを右側に表示)"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"分割画面の使用(現在のアプリを左側に表示)"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"分割画面から全画面に切り替える"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"分割画面の使用時に右側または下部のアプリに切り替える"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"分割画面の使用時に左側または上部のアプリに切り替える"</string>
@@ -1304,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"キーボード バックライト"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"レベル %1$d/%2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"ホーム コントロール"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"ホーム コントロールにスクリーンセーバーとしてすばやくアクセス"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"ホーム コントロールにスクリーンセーバーからすばやくアクセス"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index b2295f3..ff11d85 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"შეტყობინებების ფარდა"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"სწრაფი პარამეტრები"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"სწრაფი პარამეტრები და შეტყობინებების ფარდა"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ეკრანის დაბლოკვა."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ჩაკეტილი ეკრანი"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"სამსახურის ჩაკეტილი ეკრანი"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"დახურვა"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"სრული სიჩუმე"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ყველას ნახვა"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ის გამოყენება"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"დაკავშირებული"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"აუდიოს გაზიარება"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"შენახული"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"კავშირის გაწყვეტა"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"გააქტიურება"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ხელახლა ავტომატურად ჩართვა ხვალ"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ფუნქციები, როგორებიცაა „სწრაფი გაზიარება“, „ჩემი მოწყობილობის პოვნა“ და „მოწყობილობის მდებარეობა“ იყენებს Bluetooth-ს"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ჩაირთვება ხვალ დილის 5 საათზე"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ისეთი ფუნქციები, როგორიცაა სწრაფი გაზიარება და ჩემი მოწყობილობის პოვნა, იყენებს Bluetooth-ს"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ჩაირთვება ხვალ დილით"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"აუდიოს გაზიარება"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"აუდიოს გაზიარება"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ბატარეა"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"აუდიო"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ყურსაცვამი"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ჩაწერასთან დაკავშირებული პრობლემა"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"დაწყება"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"გაჩერება"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"სისტემის ხარვეზის ანგარიში"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"თქვენი მოწყობილობის გამოცდილების რა ნაწილზე მოხდა ზეგავლენა?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"აირჩიეთ პრობლემის ტიპი"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ეკრანის ჩანაწერი"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"საშუალო"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"მაღალი"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"სმენის აპარატები"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"სმენის აპარატები"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ახალი მოწყობილობის დაწყვილება"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"დააწკაპუნეთ ახალი მოწყობილობის დასაწყვილებლად"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"გსურთ მოწყობილობის მიკროფონის განბლოკვა?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"გსურთ მოწყობილობის კამერის განბლოკვა?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • სწრაფად იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ვიჯეტები ჩაკეტილ ეკრანზე"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"გადაფურცლეთ მარცხნივ, რათა დაიწყოთ საერთო სახელმძღვანელო"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"მორგება"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"უარყოფა"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"პარამეტრების გახსნა"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"კვლავ გააქტიურდეს სამსახურის აპები?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"გააქტიურება"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ჩაკეტილ ეკრანზე ვიჯეტების დახურვა"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ვიჯეტები ჩაკეტილ ეკრანზე"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ჩამოშლადი მენიუ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"კლავიატურის განლაგების გადართვა"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ან"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"საძიებო ფრაზის გასუფთავება"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"მალსახმობები"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"კლავიატურის მალსახმობები"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"ასისტენტის გახსნა"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ჩაკეტილი ეკრანი"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ჩაინიშნეთ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"სისტემის მრავალამოცანიანი რეჟიმი"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"ეკრანის გაყოფის შეყვანა მიმდინარე აპით RHS-ში"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"ეკრანის გაყოფის შეყვანა მიმდინარე აპით LHS-ში"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"მრავალამოცანიანი რეჟიმი"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ეკრანის გაყოფის გამოყენება მიმდინარე აპზე მარჯვნივ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ეკრანის გაყოფის გამოყენება მიმდინარე აპზე მარცხნივ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"გადართვა ეკრანის გაყოფიდან სრულ ეკრანზე"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ეკრანის გაყოფის გამოყენებისას აპზე მარჯვნივ ან ქვემოთ გადართვა"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ეკრანის გაყოფის გამოყენებისას აპზე მარცხნივ ან ზემოთ გადართვა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 127e81e..995a796 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Хабарландыру тақтасы"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Жылдам параметрлер."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Жылдам параметрлер мен хабарландыру тақтасы."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Бекіту экраны."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Құлыптаулы экран"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Әрекетті құлыптау экраны"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Жабу"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"үнсіз"</string>
@@ -270,18 +270,21 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Барлығын көру"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ты пайдалану"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Қосылды"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио бөлісу"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сақталды"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажырату"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"іске қосу"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ертең автоматты түрде қосылсын"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Quick Share, Find My Device сияқты функциялар мен құрылғы локациясы Bluetooth пайдаланады."</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ертең таңғы сағат 5-те қосылады."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share және Find My Device сияқты функциялар Bluetooth-ты пайдаланады."</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ертең таңертең қосылады."</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Аудио бөлісу"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Аудио бөлісу әрекеті орындалып жатыр."</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батарея деңгейі: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Aудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Кіріс"</string>
     <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Есту аппараттары"</string>
-    <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Қосылуда…"</string>
+    <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Қосылып жатыр…"</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>
@@ -297,7 +300,7 @@
     <string name="quick_settings_networks_available" msgid="1875138606855420438">"Желілер бар"</string>
     <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Желілер қолжетімді емес."</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Қолжетімді Wi-Fi желілері жоқ"</string>
-    <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Қосылуда…"</string>
+    <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Қосылып жатыр…"</string>
     <string name="quick_settings_cast_title" msgid="2279220930629235211">"Экранды трансляциялау"</string>
     <string name="quick_settings_casting" msgid="1435880708719268055">"Трансляциялануда"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Атаусыз құрылғы"</string>
@@ -312,9 +315,9 @@
     <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Жабу"</string>
     <string name="quick_settings_connected" msgid="3873605509184830379">"Қосылды"</string>
     <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Қосылды, батарея деңгейі: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="quick_settings_connecting" msgid="2381969772953268809">"Қосылуда…"</string>
+    <string name="quick_settings_connecting" msgid="2381969772953268809">"Қосылып жатыр…"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Хотспот"</string>
-    <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Қосылуда…"</string>
+    <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Қосылып жатыр…"</string>
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Трафикті үнемдеу режимі қосулы"</string>
     <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# құрылғы}other{# құрылғы}}"</string>
     <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Қолшам"</string>
@@ -331,13 +334,13 @@
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Түнгі жарық"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Күн батқанда қосу"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Күн шыққанға дейін"</string>
-    <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Қосылатын уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
     <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Қараңғы режим"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батареяны үнемдеу режимі"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батқанда қосу"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
-    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылатын уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_bedtime" msgid="2274300599408864897">"Ұйқы режимінде"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_bedtime_ends" msgid="1790772410777123685">"Ұйқы режимі аяқталғанға дейін"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Ақауды жазу"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Бастау"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Тоқтату"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Қате туралы есеп"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Құрылғы қызметінің қандай түріне әсер етті?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Мәселе түрін таңдаңыз."</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Экранды жазу"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Орташа"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Жоғары"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Есту құрылғылары"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Есту құрылғылары"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Жаңа құрылғыны жұптау"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңа құрылғыны жұптау үшін басыңыз."</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Құрылғы микрофонын блоктан шығару керек пе?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Құрылғы камерасын блоктан шығару керек пе?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жылдам зарядтау • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Құлыптаулы экрандағы виджеттер"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ортақ оқулықты ашу үшін солға қарай сырғытыңыз."</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Бейімдеу"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабу"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Параметрлерді ашу"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Жұмыс қолданбаларын қайта қосасыз ба?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Қайта қосу"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Құлыптаулы экранда виджеттерді жабу"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Құлыптаулы экрандағы виджеттер"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ашылмалы мәзір"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданба мен дерек жойылады."</string>
@@ -605,7 +613,7 @@
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Дыбысын өшіру үшін түртіңіз."</string>
     <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Шуды реттеу"</string>
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Кеңістіктік дыбыс"</string>
-    <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Өшіру"</string>
+    <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Өшірілген"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Бекітілген"</string>
     <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Бас қимылын қадағалау"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"Қоңырау режимін өзгерту үшін түртіңіз."</string>
@@ -636,7 +644,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR кодының сканері"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR сканері"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Жаңартылып жатыр"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пернетақта форматын ауыстыру"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"немесе"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Іздеу сұрауын өшіру"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Перне тіркесімдері"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Перне тіркесімдері"</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>
@@ -762,19 +770,19 @@
     <string name="group_system_go_back" msgid="2730322046244918816">"Артқа"</string>
     <string name="group_system_access_home_screen" msgid="4130366993484706483">"Негізгі экранға өту"</string>
     <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Соңғы қолданбаларды көру"</string>
-    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Соңғы қолданбаларға алға өту"</string>
-    <string name="group_system_cycle_back" msgid="8194102916946802902">"Соңғы қолданбаларға артқа өту"</string>
+    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Соңғы қолданбалар тізімінде алға өту"</string>
+    <string name="group_system_cycle_back" msgid="8194102916946802902">"Соңғы қолданбалар тізімінде артқа өту"</string>
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Қолданбалар тізімін ашу"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Параметрлерді ашу"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant-ті ашу"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды құлыптау"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ескертпе жазу"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Жүйе мультитаскингі"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Бөлінген экран режиміне кіру (ағымдағы қолданбаны оңға орналастыру)"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Бөлінген экран режиміне кіру (ағымдағы қолданбаны солға орналастыру)"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Мультитаскинг"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Ағымдағы қолданба оң жақта тұратын бөлінген экранды пайдаланыңыз"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Ағымдағы қолданба сол жақта тұратын бөлінген экранды пайдаланыңыз"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Бөлінген экран режимінен толық экран режиміне ауысу"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Экранды бөлуді қолданғанда, оң не жоғары жақтағы қолданбаға ауысыңыз"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Экранды бөлуді қолданғанда, сол не жоғары жақтағы қолданбаға ауысыңыз"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Бөлінген экранда оң не төмен жақтағы қолданбаға ауысу"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Бөлінген экранда сол не жоғары жақтағы қолданбаға ауысу"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Экранды бөлу кезінде: бір қолданбаны басқасымен алмастыру"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Енгізу"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Келесі тілге ауысу"</string>
@@ -1261,7 +1269,7 @@
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Қалған батарея заряды: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Стилусты зарядтағышқа жалғаңыз."</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Стилус батареясының заряды аз"</string>
-    <string name="video_camera" msgid="7654002575156149298">"Бейнекамера"</string>
+    <string name="video_camera" msgid="7654002575156149298">"Бейне­камера"</string>
     <string name="call_from_work_profile_title" msgid="5418253516453177114">"Жеке қолданбадан қоңырау шалу мүмкін емес"</string>
     <string name="call_from_work_profile_text" msgid="2856337395968118274">"Ұйымыңыз тек жұмыс қолданбаларынан қоңырау шалуға рұқсат етеді."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
@@ -1284,7 +1292,7 @@
     <string name="dismiss_dialog" msgid="2195508495854675882">"Жабу"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Дисплей қосылды"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон және камера"</string>
-    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Соңғы рет қолданбаның датчикті пайдалануы"</string>
+    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Қолданбалардың соңғы рет пайдалануы"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Соңғы рет пайдаланғандар"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Дайын"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Опцияларды көрсету және жаю"</string>
@@ -1304,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Пернетақта жарығы"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Деңгей: %1$d/%2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Үй басқару элементтері"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Үй басқару элементтерін скринсейвер ретінде жылдам қолдану"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Үй басқару элементтерін скринсейверден қолдану"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index f2596db..adcd3d6 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ពណ៌​ការ​ជូន​ដំណឹង"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ការ​កំណត់​រហ័ស។"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ការកំណត់រហ័ស និងផ្ទាំងជូនដំណឹង។"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ចាក់​សោ​អេក្រង់។"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ចាក់​សោ​អេក្រង់"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"អេក្រង់​ចាក់​សោ​លក្ខណៈ​ការងារ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"បិទ"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"បិទសំឡេង​ទាំងស្រុង"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"មើល​ទាំងអស់"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ប្រើប៊្លូធូស"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"បានភ្ជាប់"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ការស្ដាប់សំឡេងរួមគ្នា"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"បាន​រក្សាទុក"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ផ្ដាច់"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"បើកដំណើរការ"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"បើកដោយស្វ័យប្រវត្តិម្ដងទៀតនៅថ្ងៃស្អែក"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"មុខងារដូចជា Quick Share, រកឧបករណ៍របស់ខ្ញុំ និងប៊្លូធូសប្រើប្រាស់ទីតាំងឧបករណ៍"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ប៊្លូធូសនឹងបើកនៅថ្ងៃស្អែកនៅម៉ោង 5 ព្រឹក"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"មុខងារដូចជា Quick Share និង \"រកឧបករណ៍របស់ខ្ញុំ\" ប្រើប៊្លូធូស"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ប៊្លូធូសនឹងបើកនៅព្រឹកស្អែក"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ការស្ដាប់សំឡេងរួមគ្នា"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"កំពុងស្ដាប់សំឡេងរួមគ្នា"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"សំឡេង"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"កាស"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"កត់ត្រាបញ្ហា"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ចាប់ផ្ដើម"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"បញ្ឈប់"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"របាយការណ៍​អំពី​បញ្ហា"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"តើផ្នែកអ្វីនៃបទពិសោធប្រើប្រាស់ឧបករណ៍របស់អ្នកបានរងការប៉ះពាល់?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ជ្រើសរើសប្រភេទបញ្ហា"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ការថត​វីដេអូ​អេក្រង់"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"មធ្យម"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ខ្ពស់"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ផ្គូផ្គង​ឧបករណ៍ថ្មី"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ចុច ដើម្បីផ្គូផ្គងឧបករណ៍ថ្មី"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ឈប់ទប់ស្កាត់​មីក្រូហ្វូន​របស់ឧបករណ៍ឬ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ឈប់ទប់ស្កាត់​កាមេរ៉ា​របស់ឧបករណ៍ឬ?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្ម​យឺត • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ធាតុ​ក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"អូសទៅឆ្វេង ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ប្ដូរតាមបំណង"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ច្រានចោល"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"បើកការកំណត់"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ឈប់ផ្អាកកម្មវិធីការងារឬ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ឈប់ផ្អាក"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"បិទធាតុ​ក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ធាតុ​ក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរ​អ្នក​ប្រើ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយ​ទាញចុះ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យ​ទាំងអស់​ក្នុង​វគ្គ​នេះ​នឹង​ត្រូវ​លុប។"</string>
@@ -607,7 +615,7 @@
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"សំឡេងលំហ"</string>
     <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"បិទ"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"ថេរ"</string>
-    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"ការតាមដានក្បាល"</string>
+    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"រេតាមក្បាល"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"ចុច​ដើម្បីប្ដូរ​មុខងារ​រោទ៍"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"បិទ​សំឡេង"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"បើក​សំឡេង"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ប្ដូរប្លង់ក្ដារចុច"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ឬ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"សម្អាត​សំណួរ​ស្វែងរក"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ផ្លូវកាត់"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ផ្លូវកាត់ក្ដារចុច"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"បើក​ជំនួយការ"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ចាក់​សោ​អេក្រង់"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"កត់​ចំណាំ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ការដំណើរការបានច្រើននៃប្រព័ន្ធ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"ចូលក្នុងមុខងារបំបែកអេក្រង់ដោយប្រើកម្មវិធីបច្ចុប្បន្ននៅខាងស្ដាំដៃ"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"ចូលក្នុងមុខងារ​បំបែកអេក្រង់ដោយប្រើកម្មវិធីបច្ចុប្បន្ននៅខាងឆ្វេងដៃ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ការដំណើរការបានច្រើន"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ប្រើមុខងារបំបែកអេក្រង់ជាមួយកម្មវិធីបច្ចុប្បន្ននៅខាងស្ដាំ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ប្រើមុខងារបំបែកអេក្រង់ជាមួយកម្មវិធីបច្ចុប្បន្ននៅខាងឆ្វេង"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"ប្ដូរពីមុខងារ​បំបែកអេក្រង់ទៅជាអេក្រង់ពេញ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ប្ដូរទៅកម្មវិធីនៅខាងស្ដាំ ឬខាងក្រោម ពេលកំពុងប្រើមុខងារ​បំបែកអេក្រង់"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ប្ដូរទៅកម្មវិធីនៅខាងឆ្វេង ឬខាងលើ ពេលកំពុងប្រើមុខងារ​បំបែកអេក្រង់"</string>
@@ -1000,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ផ្លាស់ទីទៅខាងលើផ្នែកខាងស្ដាំ"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ផ្លាស់ទីទៅខាងក្រោមផ្នែកខាងឆ្វេង​"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ផ្លាស់ទីទៅខាងក្រោមផ្នែកខាងស្ដាំ"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ផ្លាស់ទីទៅផ្នែកខាងចុង រួចលាក់"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ផ្លាស់ទីទៅគែម រួចលាក់"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ផ្លាស់ទីចេញពីផ្នែកខាងចុង រួចបង្ហាញ"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"ដកចេញ"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"បិទ/បើក"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 7323450..ca22ba1 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -235,9 +235,9 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಯ ಪರದೆ."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್‌ ಸ್ಕ್ರೀನ್."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
-    <string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
+    <string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚಿ"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ಸಂಪೂರ್ಣ ನಿಶ್ಯಬ್ಧ"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"ಅಲಾರಮ್‌ಗಳು ಮಾತ್ರ"</string>
     <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ."</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ಬ್ಲೂಟೂತ್ ಬಳಸಿ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ಡಿಸ್‌ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ನಾಳೆ ಪುನಃ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಮಾಡಿ"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ಕ್ವಿಕ್ ಶೇರ್, Find My Device ನಂತಹ ಫೀಚರ್‌ಗಳು ಹಾಗೂ ಸಾಧನದ ಸ್ಥಳವು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಬಳಸುತ್ತವೆ"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ಬ್ಲೂಟೂತ್ ನಾಳೆ ಬೆಳಗ್ಗೆ 5 ಗಂಟೆಗೆ ಆನ್ ಆಗುತ್ತದೆ"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ಕ್ವಿಕ್ ಶೇರ್ ಮತ್ತು Find My Device ನಂತಹ ಫೀಚರ್‌ಗಳು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಬಳಸುತ್ತವೆ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ಬ್ಲೂಟೂತ್ ನಾಳೆ ಬೆಳಿಗ್ಗೆ ಆನ್ ಆಗುತ್ತದೆ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ಆಡಿಯೋವನ್ನು ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ಆಡಿಯೋ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ಹೆಡ್‌ಸೆಟ್"</string>
@@ -329,7 +332,7 @@
     <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ಗಳು"</string>
     <string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ನೈಟ್ ಲೈಟ್"</string>
-    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ಸೂರ್ಯಾಸ್ತದಲ್ಲಿ"</string>
+    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ಸೂರ್ಯಾಸ್ತಕ್ಕೆ ಆನ್"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ರೆಕಾರ್ಡ್ ದೋಷ"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"ನಿಲ್ಲಿಸಿ"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ಬಗ್ ವರದಿ ಮಾಡುವಿಕೆ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ಸಾಧನ ಬಳಸುವಾಗ ನೀವು ಯಾವ ರೀತಿಯ ಸಮಸ್ಯೆ ಎದುರಿಸುತ್ತೀರಿ?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ಸಮಸ್ಯೆಯ ಪ್ರಕಾರವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ಪ್ರಮಾಣಿತ"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ಮಧ್ಯಮ"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ಹೆಚ್ಚು"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ಹಿಯರಿಂಗ್ ಸಾಧನಗಳು"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ಹಿಯರಿಂಗ್ ಸಾಧನಗಳು"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ಹೊಸ ಸಾಧನವನ್ನು ಪೇರ್ ಮಾಡಿ"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳು"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ಸಮುದಾಯದ ಟ್ಯುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ವಜಾಗೊಳಿಸಿ"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ಕೆಲಸದ ಆ್ಯಪ್ ವಿರಾಮ ರದ್ದುಮಾಡಬೇಕೇ"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ವಿರಾಮವನ್ನು ರದ್ದುಗೊಳಿಸಿ"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳನ್ನು ಮುಚ್ಚಿರಿ"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳು"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ಪುಲ್‌ಡೌನ್ ಮೆನು"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಶನ್‌ನಲ್ಲಿನ ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ. ನೀವು ಬಳಸುವ ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸ್ಥಳ ಮತ್ತು ನಿಮ್ಮ ವೀಕ್ಷಣಾ ಅವಧಿಯಂತಹ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನೋಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ನಿಂದ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ, ಹಲವಾರು ದೃಢೀಕರಣ ಪ್ರಯತ್ನಗಳು"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"ಹಲವಾರು ದೃಢೀಕರಣ ಪ್ರಯತ್ನಗಳನ್ನು ಮಾಡಿರುವ ಕಾರಣ ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ\nದೃಢೀಕರಣ ವಿಫಲವಾಗಿದೆ"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"ಸೌಂಡ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ಕೀಬೋರ್ಡ್‌ ಲೇಔಟ್‌ ಬದಲಾಯಿಸಿ"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ಅಥವಾ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ಹುಡುಕಾಟದ ಪ್ರಶ್ನೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"assistant ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ಟಿಪ್ಪಣಿಯನ್ನು ತೆಗೆದುಕೊಳ್ಳಿ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ಸಿಸ್ಟಂ ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHS ಗೆ ಇರುವ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಸಹಾಯದಿಂದ ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ನಮೂದಿಸಿ"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHS ಗೆ ಇರುವ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಸಹಾಯದಿಂದ ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ನಮೂದಿಸಿ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ಬಲಭಾಗದಲ್ಲಿ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಮೂಲಕ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಿ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ಎಡಭಾಗದಲ್ಲಿ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಮೂಲಕ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಿ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್‌ನಿಂದ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ಗೆ ಬದಲಿಸಿ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಬಳಸುವಾಗ ಬಲಭಾಗ ಅಥವಾ ಕೆಳಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್‌ಗೆ ಬದಲಿಸಿ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಬಳಸುವಾಗ ಎಡಭಾಗ ಅಥವಾ ಮೇಲ್ಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್‌ಗೆ ಬದಲಿಸಿ"</string>
@@ -868,7 +875,7 @@
     <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಕ್ರಮವನ್ನು ಎಡಿಟ್ ಮಾಡಿ."</string>
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ಪವರ್ ಮೆನು"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
-    <string name="tuner_lock_screen" msgid="2267383813241144544">"ಲಾಕ್ ಪರದೆ"</string>
+    <string name="tuner_lock_screen" msgid="2267383813241144544">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
     <string name="finder_active" msgid="7907846989716941952">"ಪವರ್ ಆಫ್ ಆಗಿರುವಾಗಲೂ ನೀವು Find My Device ಮೂಲಕ ಈ ಫೋನ್ ಅನ್ನು ಪತ್ತೆ ಮಾಡಬಹುದು"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ಶಟ್ ಡೌನ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ಕಾಳಜಿಯ ಹಂತಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
@@ -1304,6 +1311,6 @@
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"ಇತ್ತೀಚೆಗೆ <xliff:g id="APP_NAME">%1$s</xliff:g> ಇದನ್ನು ಬಳಸಿದೆ (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ಕೀಬೋರ್ಡ್ ಬ್ಯಾಕ್‌ಲೈಟ್"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ರಲ್ಲಿ %1$d ಮಟ್ಟ"</string>
-    <string name="home_controls_dream_label" msgid="6567105701292324257">"ಹೋಮ್ ನಿಯಂತ್ರಣಗಳು"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"ಹೋಮ್ ನಿಯಂತ್ರಣವನ್ನು ಸ್ಕ್ರೀನ್‌ಸೇವರ್‌ನಂತೆ ತ್ವರಿತವಾಗಿ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
+    <string name="home_controls_dream_label" msgid="6567105701292324257">"ಮನೆ ನಿಯಂತ್ರಣಗಳು"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"ಮನೆ ನಿಯಂತ್ರಣವನ್ನು ಸ್ಕ್ರೀನ್‌ಸೇವರ್‌ನಂತೆ ಬೇಗ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index 9628323..afc7c1a 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"ಆಫ್ ಆಗಿದೆ"</item>
     <item msgid="5137565285664080143">"ಆನ್ ಆಗಿದೆ"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"ಲಭ್ಯವಿಲ್ಲ"</item>
+    <item msgid="3079622119444911877">"ಆಫ್ ಆಗಿದೆ"</item>
+    <item msgid="3028994095749238254">"ಆನ್"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 9a4c60b..4e7c4d0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"알림 세부정보"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"빠른 설정"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"빠른 설정 및 알림 창입니다."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"화면을 잠급니다."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"잠금 화면"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"업무용 잠금 화면"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"닫기"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"모두 음소거"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"모두 보기"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"블루투스 사용"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"연결됨"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"오디오 공유"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"저장됨"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"연결 해제"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"실행"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"내일 다시 자동으로 사용 설정"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Quick Share, 내 기기 찾기, 기기 위치 등의 기능에서 블루투스를 사용합니다."</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"블루투스가 내일 오전 5시에 켜집니다."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share, 내 기기 찾기 등의 기능에서 블루투스를 사용합니다."</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"블루투스가 내일 아침에 켜집니다."</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"오디오 공유"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"오디오 공유 중"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"오디오"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"헤드셋"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"문제 기록"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"시작"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"중지"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"버그 신고"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"기기 경험의 어떤 부분에 영향이 있었나요?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"문제 유형 선택"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"화면 녹화"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"표준"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"보통"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"높음"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"청각 보조 기기"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"청각 보조 기기"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"새 기기와 페어링"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"새 기기와 페어링하려면 클릭하세요"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"기기 마이크를 차단 해제하시겠습니까?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"기기 카메라를 차단 해제하시겠습니까?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 고속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"잠금 화면의 위젯"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"공동 튜토리얼을 시작하려면 왼쪽으로 스와이프하세요"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"맞춤설정"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"닫기"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"설정 열기"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"직장 앱 일시중지를 해제하시겠습니까?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"일시중지 해제"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"잠금 화면에서 위젯 닫기"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"잠금 화면의 위젯"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"사용자 전환"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"풀다운 메뉴"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
@@ -583,7 +590,7 @@
     <string name="screen_pinning_negative" msgid="6882816864569211666">"거부"</string>
     <string name="screen_pinning_start" msgid="7483998671383371313">"앱 고정됨"</string>
     <string name="screen_pinning_exit" msgid="4553787518387346893">"앱 고정 해제됨"</string>
-    <string name="stream_voice_call" msgid="7468348170702375660">"전화걸기"</string>
+    <string name="stream_voice_call" msgid="7468348170702375660">"통화"</string>
     <string name="stream_system" msgid="7663148785370565134">"시스템"</string>
     <string name="stream_ring" msgid="7550670036738697526">"벨소리"</string>
     <string name="stream_music" msgid="2188224742361847580">"미디어"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"키보드 레이아웃 전환"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"또는"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"검색어 삭제"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"단축키"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"단축키"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"어시스턴트 열기"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"메모 작성"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"시스템 멀티태스킹"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"현재 앱을 오른쪽으로 보내는 화면 분할 입력"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"현재 앱을 왼쪽으로 보내는 화면 분할 입력"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"멀티태스킹"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"현재 앱이 오른쪽에 오도록 화면 분할 사용"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"현재 앱이 왼쪽에 오도록 화면 분할 사용"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"화면 분할에서 전체 화면으로 전환"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"화면 분할을 사용하는 중에 오른쪽 또는 아래쪽에 있는 앱으로 전환하기"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"화면 분할을 사용하는 중에 왼쪽 또는 위쪽에 있는 앱으로 전환하기"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"키보드 백라이트"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d단계 중 %1$d단계"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"홈 컨트롤"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"화면 보호기로 홈 컨트롤에 빠르게 액세스합니다."</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"화면 보호기로 홈 컨트롤에 빠르게 액세스하기"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index d30aff2..bc4740d 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"사용 안함"</item>
     <item msgid="5137565285664080143">"사용"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"사용 불가"</item>
+    <item msgid="3079622119444911877">"사용 안함"</item>
+    <item msgid="3028994095749238254">"사용"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index d893887..1d005fb 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -212,7 +212,7 @@
     <string name="accessibility_bluetooth_device_icon" msgid="9163840051642587982">"Bluetooth түзмөгүнүн сүрөтчөсү"</string>
     <string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"Түзмөктүн чоо-жайын конфигурациялоо үчүн чыкылдатыңыз"</string>
     <string name="accessibility_bluetooth_device_settings_see_all" msgid="9111952496905423543">"Бардык түзмөктөрдү көрүү үчүн чыкылдатыңыз"</string>
-    <string name="accessibility_bluetooth_device_settings_pair_new_device" msgid="2435184865793496966">"Жаңы түзмөктү жупташтыруу үчүн чыкылдатыңыз"</string>
+    <string name="accessibility_bluetooth_device_settings_pair_new_device" msgid="2435184865793496966">"Жаңы түзмөк кошуу үчүн чыкылдатыңыз"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея кубатынын деңгээли белгисиз."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> менен туташты."</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Билдирмелер тактасы."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Тез тууралоолор."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ыкчам параметрлер жана билдирмелер тактасы."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Кулпуланган экран."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Экранды кулпулоо"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"тымтырс"</string>
@@ -266,16 +266,19 @@
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Жупташкан түзмөктөр жок"</string>
     <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Түзмөктү туташтыруу же ажыратуу үчүн таптаңыз"</string>
-    <string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Жаңы түзмөктү жупташтыруу"</string>
+    <string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Жаңы түзмөк кошуу"</string>
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Баарын көрүү"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Иштетүү"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Туташты"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Чогуу угуу"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сакталды"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажыратуу"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"иштетүү"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Эртең автоматтык түрдө кайра күйгүзүү"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Тез Бөлүшүү, \"Түзмөгүм кайда?\" жана түзмөктүн турган жерин аныктоо сыяктуу функциялар Bluetooth\'ду колдонот"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth эртең саат 05:00 күйөт"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Тез бөлүшүү жана Түзмөгүм кайда? сыяктуу функциялар Bluetooth\'ту колдонушат"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth эртең таңда күйөт"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Чогуу угуу"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Чогуу угулууда"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Маселени жаздыруу"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Баштоо"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Токтотуу"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Мүчүлүштүк тууралуу кабарлоо"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Түзмөгүңүздүн кайсы бөлүгүнө кедергиси тийди?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Маселенин түрүн тандоо"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Экрандан видео жаздырып алуу"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Кадимки"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Орточо"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Жогору"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Угуу аппараттары"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Угуу аппараттары"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Жаңы түзмөк кошуу"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңы түзмөк кошуу үчүн басыңыз"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Түзмөктүн микрофонун бөгөттөн чыгарасызбы?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Түзмөктүн камерасын бөгөттөн чыгарасызбы?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Тез кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Кулпуланган экрандагы виджеттер"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Жалпы үйрөткүчтү иштетүү үчүн солго сүрүңүз"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Ыңгайлаштыруу"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабуу"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Параметрлерди ачуу"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Жумуш колдонмолорун иштетесизби?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Иштетүү"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Виджеттерди кулпуланган экранда жабуу"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Кулпуланган экрандагы виджеттер"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Колдонуучуну которуу"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ылдый түшүүчү меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана аларга байланыштуу нерселер өчүрүлөт."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Бул түзмөктү ата-энең башкарат. Ата-энең сен иштеткен колдонмолорду, кайда жүргөнүңдү жана түзмөктү канча убакыт колдонгонуңду көрүп, башкарып турат."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ишеним агенти кулпусун ачты"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Түзмөк кулпуланды. Аутентификациядан өтүүгө өтө көп аракет жасалды"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Аутентификациядан өтө албай койгонуңуздан улам, түзмөк кулпуланды"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Түзмөк кулпуланды\nАутентификациядан өткөн жоксуз"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Добуштун параметрлери"</string>
@@ -719,7 +726,7 @@
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Ортолотуу"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Боштук"</string>
-    <string name="keyboard_key_enter" msgid="8633362970109751646">"Киргизүү"</string>
+    <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
     <string name="keyboard_key_backspace" msgid="4095278312039628074">"Артка өчүрүү"</string>
     <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Ойнотуу/Тындыруу"</string>
     <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Токтотуу"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Баскычтоп калыбын которуштуруу"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"же"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Изделген суроону тазалоо"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ыкчам баскычтар"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Ыкчам баскычтар"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Жардамчыны ачуу"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды кулпулоо"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Кыска жазуу түзүү"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Системанын бир нече тапшырма аткаруусу"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Учурда оң жактагы колдонмо менен экранды бөлүүнү иштетүү"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Учурда сол жактагы колдонмо менен экранды бөлүүнү иштетүү"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Бир нече тапшырма аткаруу"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Учурдагы колдонмону оңго жылдырып, экранды бөлүү"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Учурдагы колдонмону солго жылдырып, экранды бөлүү"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Экранды бөлүү режиминен толук экранга которулуу"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Бөлүнгөн экранды колдонуп жатканда сол же төмөн жактагы колдонмого которулуңуз"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Бөлүнгөн экранды колдонуп жатканда сол же жогору жактагы колдонмого которулуңуз"</string>
@@ -1286,21 +1293,21 @@
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Экран туташтырылды"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон жана камера"</string>
     <string name="privacy_dialog_summary" msgid="2458769652125995409">"Жакында колдонмолордо иштетилген"</string>
-    <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Акыркы пайдалануусун көрүү"</string>
+    <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Соңку маалыматты көрүү"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Бүттү"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Параметрлерди жайып көрсөтүү"</string>
     <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"Жыйыштыруу"</string>
     <string name="privacy_dialog_close_app_button" msgid="8006250171305878606">"Бул колдонмону жабуу"</string>
     <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"<xliff:g id="APP_NAME">%1$s</xliff:g> жабылды"</string>
     <string name="privacy_dialog_manage_service" msgid="8320590856621823604">"Кызматты тескөө"</string>
-    <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Кирүү мүмкүнчүлүгүн тескөө"</string>
+    <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Жеткиликтүүлүгүн башкаруу"</string>
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Телефон чалууда колдонулуп жатат"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Акыркы жолу телефон чалууда колдонулду"</string>
-    <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилип жатат"</string>
+    <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат"</string>
     <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Акыркы жолу <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилди"</string>
-    <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилип жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
+    <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Акыркы жолу <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) колдонмосунда иштетилди"</string>
-    <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштетилип жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
+    <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Акыркы жолу <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) колдонмосунда иштетилди"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ичинен %1$d-деңгээл"</string>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index 35795b7..694967e 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Өчүк"</item>
     <item msgid="5137565285664080143">"Күйүк"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Жеткиликсиз"</item>
+    <item msgid="3079622119444911877">"Өчүк"</item>
+    <item msgid="3028994095749238254">"Күйүк"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-land-television/dimens.xml b/packages/SystemUI/res/values-land-television/dimens.xml
index 52f591f..d3bafbc 100644
--- a/packages/SystemUI/res/values-land-television/dimens.xml
+++ b/packages/SystemUI/res/values-land-television/dimens.xml
@@ -28,9 +28,6 @@
   <dimen name="tv_volume_dialog_bubble_size">36dp</dimen>
   <dimen name="tv_volume_dialog_row_padding">6dp</dimen>
   <dimen name="tv_volume_number_text_size">16sp</dimen>
-  <dimen name="tv_volume_seek_bar_thumb_diameter">24dp</dimen>
-  <dimen name="tv_volume_seek_bar_thumb_focus_ring_width">8dp</dimen>
+  <dimen name="tv_volume_seek_bar_thumb_diameter">16dp</dimen>
   <dimen name="tv_volume_icons_size">20dp</dimen>
-  <dimen name="tv_volume_seek_bar_thumb_shadow_radius">4.0</dimen>
-  <dimen name="tv_volume_seek_bar_thumb_shadow_dy">4.0</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 55606aa..56ebc06 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -94,4 +94,7 @@
 
     <dimen name="keyguard_indication_margin_bottom">8dp</dimen>
     <dimen name="lock_icon_margin_bottom">24dp</dimen>
+
+    <!-- Keyboard shortcuts helper -->
+    <dimen name="ksh_container_horizontal_margin">48dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 873d75e..f95bb8e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ໜ້າຈໍແຈ້ງເຕືອນ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ການຕັ້ງຄ່າດ່ວນ."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ການຕັ້ງຄ່າດ່ວນ ແລະ ເງົາການແຈ້ງເຕືອນ."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ລັອກ​ໜ້າ​ຈໍ."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ໜ້າຈໍລັອກ"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ໜ້າຈໍລັອກວຽກ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ປິດ"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ງຽບທັງໝົດ"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ເບິ່ງທັງໝົດ"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ໃຊ້ Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ການແບ່ງປັນສຽງ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ບັນທຶກແລ້ວ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ຕັດການເຊື່ອມຕໍ່"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ເປີດນຳໃຊ້"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ເປີດໃຊ້ໂດຍອັດຕະໂນມັດອີກຄັ້ງມື້ອື່ນ"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ຄຸນສົມບັດຕ່າງໆ ເຊັ່ນ: ການແຊຣ໌ດ່ວນ, ຊອກຫາອຸປະກອນຂອງຂ້ອຍ ແລະ ສະຖານທີ່ຂອງອຸປະກອນແມ່ນໃຊ້ Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ຈະເປີດມື້ອື່ນເວລາ 05:00 ໂມງ"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ຄຸນສົມບັດຕ່າງໆໃຊ້ Bluetooth ເຊັ່ນ: ການແຊຣ໌ດ່ວນ ແລະ ຊອກຫາອຸປະກອນຂອງຂ້ອຍ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ຈະເປີດມື້ອື່ນເຊົ້າ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ການແບ່ງປັນສຽງ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ກຳລັງແບ່ງປັນສຽງ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ສຽງ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ຊຸດຫູຟັງ"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ບັນຫາກ່ຽວກັບການບັນທຶກ"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ເລີ່ມ"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"ຢຸດ"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ລາຍງານຂໍ້ຜິດພາດ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ສ່ວນໃດຂອງປະສົບການອຸປະກອນຂອງທ່ານໄດ້ຮັບຜົນກະທົບ?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ເລືອກປະເພດບັນຫາ"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ບັນທຶກໜ້າຈໍ"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ປານກາງ"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ສູງ"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ອຸປະກອນຊ່ວຍຟັງ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ອຸປະກອນຊ່ວຍຟັງ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ຄລິກເພື່ອຈັບຄູ່ອຸປະກອນໃໝ່"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ປົດບລັອກໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ປົດບລັອກກ້ອງຖ່າຍຮູບອຸ​ປະ​ກອນບໍ?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບໄວ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບຊ້າ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ປັດຊ້າຍເພື່ອເລີ່ມບົດແນະນຳສ່ວນກາງ"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ປັບແຕ່ງ"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ປ່ອຍ​ໄປ"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ເປີດການຕັ້ງຄ່າ"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ຍົກເລີກການຢຸດຊົ່ວຄາວແອັບບ່ອນເຮັດວຽກບໍ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ຍົກເລີກການຢຸດຊົ່ວຄາວ"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ປິດວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ສະຫຼັບຜູ້ໃຊ້"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ເມນູແບບດຶງລົງ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯ​ແລະ​ຂໍ້​ມູນ​ທັງ​ໝົດ​ໃນ​ເຊດ​ຊັນ​ນີ້​ຈະ​ຖືກ​ລຶບ​ອອກ."</string>
@@ -652,7 +660,7 @@
     <string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
     <string name="tuner_persistent_warning" msgid="230466285569307806">"ຄຸນສົມບັດທົດລອງໃຊ້ງານເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການອອກຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງສືບຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
-    <string name="got_it" msgid="477119182261892069">"ໄດ້​ແລ້ວ"</string>
+    <string name="got_it" msgid="477119182261892069">"ເຂົ້າ​ໃຈ​ແລ້ວ"</string>
     <string name="tuner_toast" msgid="3812684836514766951">"ຍິນດີດ້ວຍ! System UI Tuner ໄດ້ຖືກເພີ່ມໃສ່ການຕັ້ງຄ່າແລ້ວ"</string>
     <string name="remove_from_settings" msgid="633775561782209994">"ເອົາອອກ​ຈາກ​ການ​ຕັ້ງ​ຄ່າ"</string>
     <string name="remove_from_settings_prompt" msgid="551565437265615426">"ເອົາ System UI Tuner ອອກຈາກການຕັ້ງຄ່າ ແລະຢຸດການໃຊ້ທຸກຄຸນສົມບັດໃຊ້ງານຂອງມັນ?"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ສະຫຼັບແປ້ນພິມ"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ຫຼື"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ລຶບລ້າງຄຳຊອກຫາ"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ທາງລັດ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ຄີລັດ"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"ເປີດຜູ້ຊ່ວຍ"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ໜ້າຈໍລັອກ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ຈົດບັນທຶກ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນຂອງລະບົບ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"ເຂົ້າສູ່ແບ່ງໜ້າຈໍດ້ວຍແອັບປັດຈຸບັນໄປຫາ RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"ເຂົ້າສູ່ແບ່ງໜ້າຈໍດ້ວຍແອັບປັດຈຸບັນໄປຫາ LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນ"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ໃຊ້ການແບ່ງໜ້າຈໍກັບແອັບປັດຈຸບັນຢູ່ເບື້ອງຂວາ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ໃຊ້ການແບ່ງໜ້າຈໍກັບແອັບປັດຈຸບັນຢູ່ເບື້ອງຊ້າຍ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"ສະຫຼັບຈາກແບ່ງໜ້າຈໍໄປເປັນເຕັມຈໍ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ສະຫຼັບໄປໃຊ້ແອັບຢູ່ຂວາ ຫຼື ທາງລຸ່ມໃນຂະນະທີ່ໃຊ້ແບ່ງໜ້າຈໍ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ສະຫຼັບໄປໃຊ້ແອັບຢູ່ຊ້າຍ ຫຼື ທາງເທິງໃນຂະນະທີ່ໃຊ້ແບ່ງໜ້າຈໍ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d5d7929..040294f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pranešimų gaubtas."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Spartieji nustatymai."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"visiška tyla"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Žiūrėti viską"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"„Bluetooth“ naudojimas"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Prisijungta"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Garso įrašų bendrinimas"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Išsaugota"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atjungti"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"suaktyvinti"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatiškai vėl įjungti rytoj"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Tokioms funkcijoms kaip „Spartusis bendrinimas“, „Rasti įrenginį“ ir įrenginio vietovė naudojamas „Bluetooth“ ryšys"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"„Bluetooth“ bus įjungtas rytoj, 5 val."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Tokioms funkcijoms kaip „Spartusis bendrinimas“ ir „Rasti įrenginį“ naudojamas „Bluetooth“ ryšys"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"„Bluetooth“ ryšys bus įjungtas rytoj ryte"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Garso įrašų bendrinimas"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Bendrinamas garso įrašas"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akumuliatorius: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Garsas"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Virtualiosios realybės įrenginys"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Įrašyti problemą"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Pradėti"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stabdyti"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Pranešimas apie riktą"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Kuri įrenginio funkcija buvo paveikta?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Pasirinkite problemos tipą"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekrano įrašas"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Įprastas"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Vidutinis"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Aukštas"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Klausos įrenginiai"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Klausos įrenginiai"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Susieti naują įrenginį"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Spustelėkite, kad susietumėte naują įrenginį"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Panaikinti įrenginio mikrofono blokavimą?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Panaikinti įrenginio fotoaparato blokavimą?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sparčiai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Valdikliai užrakinimo ekrane"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Perbraukite kairėn, paleistumėte bendruomenės mokomąją medžiagą"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tinkinti"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Atsisakyti"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Atidaryti nustatymus"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Atš. darbo progr. pristabd.?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Atšaukti pristabdymą"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Uždaryti valdiklius užrakinimo ekrane"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Valdikliai užrakinimo ekrane"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Perjungti klaviat. išdėstymą"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"arba"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Išvalyti paieškos užklausą"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Spartieji klavišai"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Spartieji klavišai"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ieškoti sparčiųjų klavišų"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Sparčiųjų klavišų nerasta"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -770,16 +777,16 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Atidaryti Padėjėją"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Užrakinti ekraną"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Sukurti pastabą"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Kelių užduočių atlikimas sistemoje"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Eiti į išskaidyto ekrano režimą su dabartine programa dešinėje"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Eiti į išskaidyto ekrano režimą su dabartine programa kairėje"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Kelių užduočių atlikimas"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Naudoti išskaidyto ekrano režimą su dabartine programa dešinėje"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Naudoti išskaidyto ekrano režimą su dabartine programa kairėje"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Perjungti iš išskaidyto ekrano režimo į viso ekrano režimą"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Perjunkite į programą dešinėje arba apačioje išskaidyto ekrano režimu"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Perjunkite į programą kairėje arba viršuje išskaidyto ekrano režimu"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Išskaidyto ekrano režimu: pakeisti iš vienos programos į kitą"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Įvestis"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Perjungti į kitą kalbą"</string>
-    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Perjungti ankstesnę kalbą"</string>
+    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Perjungti į ankstesnę kalbą"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"Pasiekti jaustuką"</string>
     <string name="input_access_voice_typing" msgid="7291201476395326141">"Pasiekti rašymą balsu"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Programos"</string>
@@ -1297,7 +1304,7 @@
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Naudotojo telefono skambučio programa"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Neseniai naudojo telefono skambučio programa"</string>
     <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Naudoja <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Neseniai naudojo „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
+    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Neseniai naudojo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Naudoja <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Neseniai naudojo „<xliff:g id="APP_NAME">%1$s</xliff:g>“ (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Naudoja <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index cfa5552..c975e7e 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Išjungta"</item>
     <item msgid="5137565285664080143">"Įjungta"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nepasiekiama"</item>
+    <item msgid="3079622119444911877">"Išjungta"</item>
+    <item msgid="3028994095749238254">"Įjungta"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4413780..da58f33 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Paziņojumu panelis"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ātrie iestatījumi"</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"pilnīgs klusums"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Skatīt visas"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Izmantot Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Savienojums izveidots"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio kopīgošana"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saglabāta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atvienot"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizēt"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automātiski atkal ieslēgt rīt"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Tādas funkcijas kā “Ātrā kopīgošana”, “Atrast ierīci” un ierīces atrašanās vietas noteikšana izmanto tehnoloģiju Bluetooth."</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth tiks ieslēgts rīt plkst. 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Tādas funkcijas kā “Ātrā kopīgošana” un “Atrast ierīci” izmanto Bluetooth savienojumu"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth savienojums tiks ieslēgts rīt no rīta"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Kopīgot audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Notiek audio kopīgošana"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Akumulators: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Austiņas"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problēmas ierakstīšana"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Sākt"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Apturēt"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Kļūdas pārskats"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Kuras ierīces funkcijas tika ietekmētas?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Atlasiet problēmas veidu"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekrāna ierakstīšana"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standarta"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Vidējs"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Augsts"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dzirdes aparāti"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dzirdes aparāti"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Savienojiet pārī jaunu ierīci"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Noklikšķiniet, lai savienotu pārī jaunu ierīci"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vai atbloķēt ierīces mikrofonu?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vai vēlaties atbloķēt ierīces kameru?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ātrā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Logrīki bloķēšanas ekrānā"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Velciet pa kreisi, lai palaistu kopienas pamācību."</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pielāgot"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Nerādīt"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Atvērt iestatījumus"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Vai aktivizēt darba lietotnes?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Aktivizēt"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Aizvērt logrīkus bloķēšanas ekrānā"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Logrīki bloķēšanas ekrānā"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mainīt lietotāju"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"novelkamā izvēlne"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
@@ -606,7 +613,7 @@
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. Pieskarieties, lai izslēgtu skaņu."</string>
     <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Trokšņu kontrole"</string>
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Telpiskais audio"</string>
-    <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Izslēgts"</string>
+    <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Izslēgta"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Fiksēts"</string>
     <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Seko galvai"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"Pieskarieties, lai mainītu zvanītāja režīmu."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Mainīt tastatūras izkārtojumu"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"vai"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Notīrīt meklēšanas vaicājumu"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Īsinājumtaustiņi"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Īsinājumtaustiņi"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Meklēt īsinājumtaustiņus"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nav atrasti"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistēma"</string>
@@ -769,10 +776,10 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Atvērt iestatījumus"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Atvērt Asistentu"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloķēt ekrānu"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Piezīmes izveide"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistēmas vairākuzdevumu režīms"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Pāriet ekrāna sadalīšanas režīmā ar pašreizējo lietotni pa labi"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Pāriet ekrāna sadalīšanas režīmā ar pašreizējo lietotni pa kreisi"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Izveidot piezīmi"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Vairākuzdevumu režīms"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Izmantot ekrāna sadalīšanu ar pašreizējo lietotni labajā pusē"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Izmantot ekrāna sadalīšanu ar pašreizējo lietotni kreisajā pusē"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Pārslēgties no ekrāna sadalīšanas režīma uz pilnekrāna režīmu"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pāriet uz lietotni pa labi/lejā, kamēr izmantojat sadalīto ekrānu."</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pāriet uz lietotni pa kreisi/augšā, kamēr izmantojat sadalīto ekrānu."</string>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index e6b4dea..c65a1d4 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Izslēgts"</item>
     <item msgid="5137565285664080143">"Ieslēgts"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nav pieejams"</item>
+    <item msgid="3079622119444911877">"Izslēgts"</item>
+    <item msgid="3028994095749238254">"Ieslēgts"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 4f5bf6c..2faf243 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панел за известување"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брзи поставки."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"„Брзи поставки“ и „Панел со известувања“."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучен екран."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Заклучен екран"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"целосна тишина"</string>
@@ -270,13 +270,16 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Прикажи ги сите"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Поврзано"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделување аудио"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Зачувано"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекини врска"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирај"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматски вклучи повторно утре"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Функциите како „Брзо споделување“, „Најди го мојот уред“ и локација на уредот користат Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ќе се вклучи утре во 5:00"</string>
-    <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батерија"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Функциите како „Брзо споделување“ и „Најди го мојот уред“ користат Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ќе се вклучи утре наутро"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Споделување аудио"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Се споделува аудио"</string>
+    <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Слушалки"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Влез"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Евидентирајте проблем"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Започнете"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Сопрете"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Извештај за грешка"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Кој дел од доживувањето на уредот беше засегнат?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Изберете тип проблем"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Снимање екран"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандарден"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Среден"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Висок"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Спари нов уред"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за да спарите нов уред"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се одблокира пристапот до микрофонот на уредот?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се одблокира пристапот до камерата на уредот?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни брзо • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни бавно • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на заклучен екран"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Повлечете налево за да го започнете заедничкото упатство"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Приспособете"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отфрли"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Отвори ги поставките"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Да се актив. работните аплик.?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Прекини ја паузата"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затворете ги виџетите на заклучениот екран"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виџети на заклучен екран"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Промени го корисникот"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"паѓачко мени"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијава ќе се избришат."</string>
@@ -669,7 +676,7 @@
     <string name="notification_automatic_title" msgid="3745465364578762652">"Автоматски"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звук или вибрации"</string>
     <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звук или вибрации и се појавува подолу во делот со разговори"</string>
-    <string name="notification_channel_summary_default" msgid="777294388712200605">"Може да ѕвони или вибрира во зависност од поставките на уредот"</string>
+    <string name="notification_channel_summary_default" msgid="777294388712200605">"Може да ѕвони или вибрира во зависност од поставките за уредот"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Може да ѕвони или вибрира во зависност од поставките на уредот. Стандардно, разговорите од <xliff:g id="APP_NAME">%1$s</xliff:g> се во балончиња."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Дозволете системот да определи дали известувањево треба да испушти звук или да вибрира"</string>
     <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;Статус:&lt;/b&gt; поставено на „Стандардно“"</string>
@@ -719,7 +726,7 @@
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Центар"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
-    <string name="keyboard_key_enter" msgid="8633362970109751646">"Внеси"</string>
+    <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
     <string name="keyboard_key_backspace" msgid="4095278312039628074">"Бришење наназад"</string>
     <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Пушти/Паузирај"</string>
     <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Сопри"</string>
@@ -745,13 +752,13 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени јазик на тастатура"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Бришење поим за пребарување"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Кратенки"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Кратенки од тастатура"</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_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="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворање апликации"</string>
+    <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Тековна апликација"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Се прикажуваат резултати од пребарувањето"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Се прикажуваат системски кратенки"</string>
     <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Се прикажуваат кратенки за внесување"</string>
@@ -768,14 +775,14 @@
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Отворете го списокот со апликации"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Отворете „Поставки“"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отворете го „Помошникот“"</string>
-    <string name="group_system_lock_screen" msgid="7391191300363416543">"Заклучен екран"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Заклучете го екранот"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Фатете белешка"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Системски мултитаскинг"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Активирајте поделен екран со тековната апликација десно"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Активирајте поделен екран со тековната апликација лево"</string>
-    <string name="system_multitasking_full_screen" msgid="336048080383640562">"Префрлете од поделен екран во цел екран"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Префрлете на апликацијата десно или долу при користењето поделен екран"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Префрлете на апликацијата лево или горе при користењето поделен екран"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Мултитаскинг"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Користете поделен екран со тековната апликација оддесно"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Користете поделен екран со тековната апликација одлево"</string>
+    <string name="system_multitasking_full_screen" msgid="336048080383640562">"Префрлете се од поделен екран на цел екран"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Префрлете се на апликацијата десно или долу при користењето поделен екран"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Префрлете се на апликацијата лево или горе при користењето поделен екран"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"При поделен екран: префрлете ги аплик. од едната на другата страна"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Внесување"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Префрлете на следниот јазик"</string>
@@ -1005,7 +1012,7 @@
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Премести над работ и прикажи"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Отстрани"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"вклучување/исклучување"</string>
-    <string name="accessibility_floating_button_action_edit" msgid="1688227814600463987">"Изменете"</string>
+    <string name="accessibility_floating_button_action_edit" msgid="1688227814600463987">"Измени"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"Контроли за уредите"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"Изберете апликација за да додадете контроли"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Додадена е # контрола.}one{Додадени се # контрола.}other{Додадени се # контроли.}}"</string>
@@ -1285,7 +1292,7 @@
     <string name="dismiss_dialog" msgid="2195508495854675882">"Отфрли"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Екранот е поврзан"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
-    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Неодамнешно користење на апликација"</string>
+    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Неодамнешно користење од апликациите"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Видете го скорешниот пристап"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Готово"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Проширување и прикажување на опциите"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Осветлување на тастатура"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d од %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за домот"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Брзо прист. до контр. за дом. како штедач на екран"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Контролите за домот како штедач на екран"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index 0d81120..a8d9695 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Исклучено"</item>
     <item msgid="5137565285664080143">"Вклучено"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Недостапно"</item>
+    <item msgid="3079622119444911877">"Исклучено"</item>
+    <item msgid="3028994095749238254">"Вклучено"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 8ce3796..2fd4411 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"അറിയിപ്പ് ഷെയ്‌ഡ്."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ദ്രുത ക്രമീകരണങ്ങൾ."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"അറിയിപ്പ് ഷെയ്‌ഡിനുള്ള ദ്രുത ക്രമീകരണം."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ലോക്ക് സ്‌ക്രീൻ."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ലോക്ക് സ്‌ക്രീൻ"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ഔദ്യോഗിക ലോക്ക് സ്ക്രീൻ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"അവസാനിപ്പിക്കുക"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"പൂർണ്ണ നിശബ്‌ദത"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"എല്ലാം കാണുക"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ഉപയോഗിക്കുക"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"കണക്‌റ്റ് ചെയ്‌തു"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ഓഡിയോ പങ്കിടൽ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"സംരക്ഷിച്ചു"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"വിച്ഛേദിക്കുക"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"സജീവമാക്കുക"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"നാളെ വീണ്ടും സ്വയമേവ ഓണാക്കുക"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ക്വിക്ക് ഷെയർ, Find My Device, ഉപകരണ ലൊക്കേഷൻ എന്നിവ പോലുള്ള ഫീച്ചറുകൾ Bluetooth ഉപയോഗിക്കുന്നു"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth നാളെ 5 AM-ന് ഓണാക്കും"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ക്വിക്ക് ഷെയർ, Find My Device പോലുള്ള ഫീച്ചറുകൾ Bluetooth ഉപയോഗിക്കുന്നു"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth നാളെ രാവിലെ ഓണാകും"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ഓഡിയോ പങ്കിടൽ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ഓഡിയോ പങ്കിടുന്നു"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ബാറ്ററി"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ഓഡിയോ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ഹെഡ്‌സെറ്റ്"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"പ്രശ്‌നം റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ആരംഭിക്കുക"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"നിർത്തുക"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ബഗ് റിപ്പോർട്ട്"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"നിങ്ങളുടെ ഉപകരണ അനുഭവത്തിന്‍റെ ഏത് ഭാഗമാണ് ബാധിച്ചത്?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"പ്രശ്ന തരം തിരഞ്ഞെടുക്കുക"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"സ്‌ക്രീൻ റെക്കോർഡ്"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ഇടത്തരം"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"കൂടുതൽ"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"കേൾവിക്കുള്ള ഉപകരണങ്ങൾ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"പുതിയ ഉപകരണം ജോടിയാക്കുക"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"പുതിയ ഉപകരണം ജോടിയാക്കാൻ ക്ലിക്ക് ചെയ്യുക"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ഉപകരണ മൈക്രോഫോൺ അൺബ്ലോക്ക് ചെയ്യണോ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ഉപകരണ ക്യാമറ അൺബ്ലോക്ക് ചെയ്യണോ?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ലോക്ക് സ്‌ക്രീനിൽ വിജറ്റുകൾ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"കമ്മ്യൂണൽ ട്യൂട്ടോറിയൽ ആരംഭിക്കാൻ ഇടത്തോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ഇഷ്‌ടാനുസൃതമാക്കുക"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ഡിസ്‌മിസ് ചെയ്യുക"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ക്രമീകരണം തുറക്കുക"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"വർക്ക് ആപ്പുകൾ പുനരാരംഭിക്കണോ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"പുനരാരംഭിക്കുക"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ അടയ്ക്കുക"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ലോക്ക് സ്‌ക്രീനിൽ വിജറ്റുകൾ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"പുൾഡൗൺ മെനു"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"കീബോർഡ് ലേഔട്ട് മാറുക"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"അല്ലെങ്കിൽ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"തിരയൽ ചോദ്യം മായ്‌ക്കുക"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"കുറുക്കുവഴികൾ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"കീബോർഡ് കുറുക്കുവഴികൾ"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant തുറക്കുക"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ലോക്ക് സ്‌ക്രീൻ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ഒരു കുറിപ്പെടുക്കുക"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"സിസ്റ്റം മൾട്ടിടാസ്‌കിംഗ്"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"നിലവിലെ ആപ്പ് വലതുവശത്ത് വരുന്ന രീതിയിൽ സ്ക്രീൻ വിഭജന മോഡിൽ കടക്കുക"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"നിലവിലെ ആപ്പ് ഇടതുവശത്ത് വരുന്ന രീതിയിൽ സ്ക്രീൻ വിഭജന മോഡിൽ കടക്കുക"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"മൾട്ടിടാസ്‌കിംഗ്"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"വലതുവശത്തുള്ള നിലവിലെ ആപ്പിനൊപ്പം സ്‌ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുക"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ഇടതുവശത്തുള്ള നിലവിലെ ആപ്പിനൊപ്പം സ്‌ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുക"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"സ്‌ക്രീൻ വിഭജന മോഡിൽ നിന്ന് പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറുക"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുമ്പോൾ വലതുവശത്തെ/താഴത്തെ ആപ്പിലേക്ക് മാറൂ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുമ്പോൾ ഇടതുവശത്തെ/മുകളിലെ ആപ്പിലേക്ക് മാറൂ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 1a2e4b1f..94cdf4c 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Мэдэгдлийн хураангуй самбар"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Шуурхай тохиргоо."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Шуурхай тохиргоо болон мэдэгдлийн хураангуй самбар."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Дэлгэц түгжих."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Түгжээтэй дэлгэц"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ажлын түгжигдсэн дэлгэц"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Хаах"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"бүх дууг хаах"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Бүгдийг харах"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-г ашиглах"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Холбогдсон"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио хуваалцах"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Хадгалсан"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"салгах"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"идэвхжүүлэх"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Маргааш автоматаар дахин асаах"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Түргэн хуваалцах, Миний төхөөрөмжийг олох зэрэг онцлогууд болон төхөөрөмжийн байршил Bluetooth-г ашигладаг"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth маргааш ҮӨ 5 цагт асна"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Түргэн хуваалцах, Миний төхөөрөмжийг олох зэрэг онцлогууд Bluetooth-г ашигладаг"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth-г маргааш өглөө асаана"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Аудио хуваалцах"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Аудио хуваалцаж байна"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батарей"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Чихэвч"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Асуудлыг бичих"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Эхлүүлэх"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Зогсоох"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Алдааны мэдээ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Таны төхөөрөмжийн хэрэглээний аль хэсэгт нөлөөлсөн бэ?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Асуудлын төрөл сонгоно уу"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Дэлгэцийн бичлэг"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандарт"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Дунд зэрэг"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Өндөр"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Сонсголын төхөөрөмжүүд"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Сонсголын төхөөрөмжүүд"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Шинэ төхөөрөмж хослуулах"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Шинэ төхөөрөмж хослуулахын тулд товшино уу"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Төхөөрөмжийн микрофоныг блокоос гаргах уу?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Төхөөрөмжийн камерыг блокоос гаргах уу?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Хурдтай цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Түгжээтэй дэлгэц дээрх виджетүүд"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Нийтийн практик хичээлийг эхлүүлэхийн тулд зүүн тийш шударна уу"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Өөрчлөх"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Хаах"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Тохиргоог нээх"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Ажлын аппыг үргэлжлүүлэх үү?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Үргэлжлүүлэх"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Түгжээтэй дэлгэц дээр виджетүүдийг хаах"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Түгжээтэй дэлгэц дээрх виджетүүд"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Хэрэглэгчийг сэлгэх"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"эвхмэл цэс"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Гарын бүдүүвч рүү сэлгэх"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"эсвэл"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Хайлтын асуулгыг арилгах"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Товчлолууд"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Товчлуурын шууд холбоос"</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>
@@ -770,12 +777,12 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Туслахыг нээх"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Түгжээтэй дэлгэц"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Тэмдэглэл хөтлөх"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Систем олон ажил зэрэг хийх"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Одоогийн аппаар баруун гар талд дэлгэц хуваахад орох"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Одоогийн аппаар зүүн гар талд дэлгэц хуваахад орох"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Олон ажил зэрэг хийх"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Одоогийн аппыг баруун талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Одоогийн аппыг зүүн талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Дэлгэц хуваахаас бүтэн дэлгэц рүү сэлгэх"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Дэлгэц хуваахыг ашиглаж байхдаа баруун эсвэл доор байх апп руу сэлгэ"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Дэлгэц хуваахыг ашиглаж байхдаа зүүн эсвэл дээр байх апп руу сэлгэ"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Дэлгэц хуваахыг ашиглаж байхдаа баруун талд эсвэл доор байх апп руу сэлгэ"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Дэлгэц хуваахыг ашиглаж байхдаа зүүн талд эсвэл дээр байх апп руу сэлгэ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Дэлгэц хуваах үеэр: аппыг нэгээс нөгөөгөөр солих"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Оролт"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Дараагийн хэл рүү сэлгэх"</string>
@@ -1268,7 +1275,7 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Ажлын профайл руу сэлгэх"</string>
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Ажлын гар утасны апп суулгах"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Цуцлах"</string>
-    <string name="lock_screen_settings" msgid="6152703934761402399">"Түгжигдсэн дэлгэцийг өөрчлөх"</string>
+    <string name="lock_screen_settings" msgid="6152703934761402399">"Түгжээтэй дэлгэцийг өөрчлөх"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Түгжээтэй дэлгэцийг өөрчлөхийн тулд түгжээг тайлна уу"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi боломжгүй байна"</string>
     <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерыг блоклосон"</string>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index cfaf693..a3f5454 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Унтраалттай"</item>
     <item msgid="5137565285664080143">"Асаалттай"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Боломжгүй"</item>
+    <item msgid="3079622119444911877">"Унтраалттай"</item>
+    <item msgid="3028994095749238254">"Асаалттай"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 2e21fd0..dd53db5 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग्ज आणि सूचना शेड."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"लॉक स्क्रीन"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य लॉक स्क्रीन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"संपूर्ण शांतता"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"सर्व पहा"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्‍लूटूथ वापरा"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट केले"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडिओ शेअरिंग"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव्ह केले"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट करा"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ॲक्टिव्हेट करा"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"उद्या पुन्हा आपोआप सुरू करा"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"क्विक शेअर, Find My Device आणि डिव्हाइसचे स्थान यांसारखी वैशिष्ट्ये ब्लूटूथ वापरतात"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ब्लूटूथ उद्या सकाळी ५ वाजता सुरू होईल"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"क्विक शेअर आणि Find My Device यांसारखी वैशिष्‍ट्ये ब्लूटूथ वापरतात"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ब्लूटूथ उद्या सकाळी सुरू होईल"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ऑडिओ शेअरिंग"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ऑडिओ शेअर करत आहे"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> बॅटरी"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ऑडिओ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"समस्या रेकॉर्ड करा"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"सुरुवात करा"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"थांबवा"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"बग रिपोर्ट"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"तुमच्या डिव्हाइसबाबत कोणत्या अनुभवावर परिणाम झाला?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"समस्येचा प्रकार निवडा"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"स्क्रीन रेकॉर्ड"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"साधारण"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"मध्यम"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"उच्च"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"श्रवणयंत्रे"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"श्रवणयंत्रे"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नवीन डिव्हाइस पेअर करा"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नवीन डिव्हाइस पेअर करण्यासाठी क्लिक करा"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिव्हाइसचा मायक्रोफोन अनब्लॉक करायचा आहे का?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिव्हाइसचा कॅमेरा अनब्लॉक करायचा आहे का?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वेगाने चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीनवरील विजेट"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी डावीकडे स्वाइप करा"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइझ करा"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"डिसमिस करा"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"सेटिंग्ज उघडा"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"वर्क ॲप्स पुन्हा सुरू करायची?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"पुन्हा सुरू करा"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लॉक स्क्रीनवरील विजेट बंद करा"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लॉक स्क्रीनवरील विजेट"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनू"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अ‍ॅप्स आणि डेटा हटवला जाईल."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट स्विच करा"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"किंवा"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"शोध क्वेरी साफ करा"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"कीबोर्ड शॉर्टकट"</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>
@@ -757,7 +764,7 @@
     <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"इनपुट शॉर्टकट दाखवत आहे"</string>
     <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ॲप्स उघडणारे शॉर्टकट दाखवत आहे"</string>
     <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"सद्य अ‍ॅपसाठी शॉर्टकट दाखवत आहे"</string>
-    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचना पहा"</string>
+    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"नोटिफिकेशन पहा"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रीनशॉट घ्या"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट दाखवा"</string>
     <string name="group_system_go_back" msgid="2730322046244918816">"मागे जा"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant उघडा"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"नोंद घ्या"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टीम मल्टिटास्किंग"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"उजव्या बाजूला सध्याचे अ‍ॅप असलेल्या स्प्लिट स्क्रीनवर जा"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"डाव्या बाजूला सध्याचे अ‍ॅप असलेल्या स्प्लिट स्क्रीनवर जा"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टिटास्किंग"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"सद्य ॲप उजवीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"सद्य ॲप डावीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"स्प्लिट स्क्रीनवरून फुल स्क्रीनवर स्विच करा"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन वापरताना उजवीकडील किंवा खालील अ‍ॅपवर स्विच करा"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन वापरताना डावीकडील किंवा वरील अ‍ॅपवर स्विच करा"</string>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index abb7ace..54c320c 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"बंद आहे"</item>
     <item msgid="5137565285664080143">"सुरू आहे"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"उपलब्ध नाही"</item>
+    <item msgid="3079622119444911877">"बंद आहे"</item>
+    <item msgid="3028994095749238254">"सुरू आहे"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 9ae774f..6b858a4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
     <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_lock_screen" msgid="409034672704273634">"Kunci skrin"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"senyap sepenuhnya"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Lihat semua"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Disambungkan"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Perkongsian Audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"putuskan sambungan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Dihidupkan sekali lagi esok secara automatik"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Ciri seperti Quick Share, Find My Device dan lokasi peranti menggunakan Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth akan dihidupkan esok pada pukul 5 PG"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Ciri seperti Quick Share dan Find My Device menggunakan Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth akan dihidupkan esok pagi"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Perkongsian Audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Berkongsi Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> bateri"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Set Kepala"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Rekodkan masalah"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Mula"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Hentikan"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Laporan Pepijat"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Pengalaman peranti yang manakah yang terjejas?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Pilih jenis masalah"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rakam skrin"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Sederhana"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Tinggi"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Peranti pendengaran"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Peranti pendengaran"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Gandingkan peranti baharu"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menggandingkan peranti baharu"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Nyahsekat mikrofon peranti?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Nyahsekat kamera peranti?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan cepat • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget pada skrin kunci"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Leret ke kiri untuk memulakan tutorial umum"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ketepikan"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Buka tetapan"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Nyahjeda apl kerja?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Nyahjeda"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Tutup widget pada skrin kunci"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widget pada skrin kunci"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tukar reka letak papan kekunci"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"atau"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Kosongkan pertanyaan carian"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Pintasan Papan Kekunci"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cari pintasan"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tiada pintasan ditemukan"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
@@ -762,16 +770,16 @@
     <string name="group_system_go_back" msgid="2730322046244918816">"Kembali"</string>
     <string name="group_system_access_home_screen" msgid="4130366993484706483">"Akses skrin utama"</string>
     <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Lihat apl terbaharu"</string>
-    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Kitar ke hadapan menerusi apl terbaharu"</string>
-    <string name="group_system_cycle_back" msgid="8194102916946802902">"Kitar ke belakang menerusi apl terbaharu"</string>
+    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Navigasi apl terbaharu ke arah kanan"</string>
+    <string name="group_system_cycle_back" msgid="8194102916946802902">"Navigasi apl terbaharu ke arah kiri"</string>
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Buka senarai apl"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Buka tetapan"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Buka Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci skrin"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Catat nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Berbilang tugas sistem"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Masuk skrin pisah dengan apl semasa pada sisi kanan"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Masuk skrin pisah dengan apl semasa pada sisi kiri"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Berbilang tugas"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gunakan skrin pisah dengan apl semasa pada sebelah kanan"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gunakan skrin pisah dengan apl semasa pada sebelah kiri"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Beralih daripada skrin pisah kepada skrin penuh"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Tukar kepada apl di sebelah kanan/bawah semasa menggunakan skrin pisah"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Tukar kepada apl di sebelah kiri/atas semasa menggunakan skrin pisah"</string>
@@ -1124,7 +1132,7 @@
     <string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string>
     <string name="select_conversation_title" msgid="6716364118095089519">"Widget perbualan"</string>
     <string name="select_conversation_text" msgid="3376048251434956013">"Ketik perbualan untuk menambahkan perbualan itu pada skrin Utama anda"</string>
-    <string name="no_conversations_text" msgid="5354115541282395015">"Perbualan terbaharu anda akan dipaparkan di sini"</string>
+    <string name="no_conversations_text" msgid="5354115541282395015">"Perbualan terbaharu akan dipaparkan di sini"</string>
     <string name="priority_conversations" msgid="3967482288896653039">"Perbualan keutamaan"</string>
     <string name="recent_conversations" msgid="8531874684782574622">"Perbualan terbaharu"</string>
     <string name="days_timestamp" msgid="5821854736213214331">"<xliff:g id="DURATION">%1$s</xliff:g> hari lalu"</string>
@@ -1193,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# apl aktif}other{# apl aktif}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"Maklumat baharu"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apl aktif"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Apl ini aktif dan berfungsi walaupun anda tidak menggunakannya. Ini meningkatkan kefungsian apl tetapi mungkin akan memberikan kesan kepada hayat bateri."</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Apl ini aktif dan berfungsi walaupun anda tidak menggunakannya. Hal ini meningkatkan kefungsian apl tetapi akan memberikan kesan kepada hayat bateri."</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"Berhenti"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"Dihentikan"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"Selesai"</string>
@@ -1304,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Cahaya latar papan kekunci"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tahap %1$d daripada %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Kawalan Rumah"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Akses kawalan rumah anda sebagai penyelamat skrin dengan cepat"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Jadikan kawalan rumah anda sebagai penyelamat skrin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1249885..2472d1f 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"အ​ကြောင်းကြားစာအကွက်"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"အမြန်လုပ် အပြင်အဆင်"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‘အမြန်ဆက်တင်များ’ နှင့် ‘အကြောင်းကြားစာအကွက်’။"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"မျက်နှာပြင် သော့ပိတ်ရန်"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"လုံးဝ အသံပိတ်ထားရန်"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"အားလုံးကြည့်ရန်"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ဘလူးတုသ်သုံးရန်"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ချိတ်ဆက်ထားသည်"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"အော်ဒီယို မျှဝေခြင်း"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"သိမ်းထားသည်"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"စသုံးရန်"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"မနက်ဖြန် အလိုအလျောက် ထပ်ဖွင့်ရန်"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"‘အမြန် မျှဝေပါ’၊ Find My Device နှင့် စက်ပစ္စည်းတည်နေရာကဲ့သို့ တူးလ်များသည် ဘလူးတုသ်သုံးသည်"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"မနက်ဖြန် မနက် ၅ နာရီတွင် ဘလူးတုသ်ကို ဖွင့်ပါမည်"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"‘အမြန် မျှဝေပါ’ နှင့် Find My Device ကဲ့သို့ တူးလ်များသည် ဘလူးတုသ်သုံးသည်"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"မနက်ဖြန်နံနက်တွင် ဘလူးတုသ် ပွင့်ပါမည်"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"အော်ဒီယို မျှဝေခြင်း"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"အော်ဒီယို မျှဝေနေသည်"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ဘက်ထရီ"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"အသံ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"မိုက်ခွက်ပါနားကြပ်"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ပြဿနာကို မှတ်တမ်းတင်ခြင်း"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"စတင်ပါ"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"ရပ်ပါ"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ချွတ်ယွင်းမှု အစီရင်ခံစာ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"စက်အသုံးပြုမှု၏ မည်သည့်အပိုင်းကို သက်ရောက်သလဲ။"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ပြဿနာအမျိုးအစား ရွေးရန်"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ဖန်သားပြင်ရိုက်ကူးရန်"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"အသင့်အတင့်"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"များ"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"နားကြားကိရိယာ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"နားကြားကိရိယာ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"စက်အသစ်တွဲချိတ်ရန်"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"စက်အသစ် တွဲချိတ်ရန် နှိပ်ပါ"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"စက်၏မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"စက်၏ကင်မရာကို ပြန်ဖွင့်မလား။"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အမြန်အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် ဘယ်သို့ပွတ်ဆွဲပါ"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"စိတ်ကြိုက်လုပ်ရန်"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ပယ်ရန်"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ဆက်တင်များ ဖွင့်ရန်"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"အလုပ်သုံးအက်ပ် ပြန်ဖွင့်မလား။"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ပြန်ဖွင့်ရန်"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များကို ပိတ်ရန်"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ဆွဲချမီနူး"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
@@ -550,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်။ သင့်မိဘက သင်သုံးသောအက်ပ်များ၊ သင်၏တည်နေရာနှင့် အသုံးပြုချိန် ကဲ့သို့သော အချက်အလက်များကို မြင်နိုင်ပြီး စီမံခန့်ခွဲနိုင်သည်။"</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ဖြင့် ဆက်ဖွင့်ထားရန်"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"စက်လော့ခ်ကျနေသည်၊ အထောက်အထားစိစစ်ရန် ကြိုးပမ်းမှုအကြိမ်ရေ များလွန်းသည်"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"လော့ခ်ကျနေသည်၊ အထောက်အထားစိစစ်ရန် ကြိုးပမ်းကြိမ် များလွန်းသည်"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"စက်လော့ခ်ကျနေသည်\nအထောက်အထားစိစစ်၍ မရပါ"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>။ <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"အသံဆက်တင်များ"</string>
@@ -593,7 +601,7 @@
     <string name="stream_accessibility" msgid="3873610336741987152">"အများသုံးနိုင်မှု"</string>
     <string name="volume_ringer_status_normal" msgid="1339039682222461143">"အသံမြည်သည်"</string>
     <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"တုန်ခါသည်"</string>
-    <string name="volume_ringer_status_silent" msgid="3691324657849880883">"အသံတိတ်သည်"</string>
+    <string name="volume_ringer_status_silent" msgid="3691324657849880883">"အသံပိတ်ရန်"</string>
     <string name="media_device_cast" msgid="4786241789687569892">"ကာစ်လုပ်ရန်"</string>
     <string name="stream_notification_unavailable" msgid="4313854556205836435">"ဖုန်းမြည်သံပိတ်ထားသဖြင့် မရနိုင်ပါ"</string>
     <string name="stream_alarm_unavailable" msgid="4059817189292197839">"‘မနှောင့်ယှက်ရ’ ဖွင့်ထားသောကြောင့် မရနိုင်ပါ"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ကီးဘုတ်အပြင်အဆင် ပြောင်းခြင်း"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"သို့မဟုတ်"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ရှာဖွေစာလုံး ရှင်းထုတ်ရန်"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ဖြတ်လမ်းလင့်ခ်များ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"လက်ကွက်ဖြတ်လမ်းများ"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ဖွင့်ရန်"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"မှတ်စုရေးရန်"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"စနစ်က တစ်ပြိုင်နက် များစွာလုပ်ခြင်း"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"လက်ရှိအက်ပ်ကို မျက်နှာပြင် ခွဲ၍ပြသမှု၏ ညာဘက်တွင်ထည့်ရန်"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"လက်ရှိအက်ပ်ကို မျက်နှာပြင် ခွဲ၍ပြသမှု၏ ဘယ်ဘက်တွင်ထည့်ရန်"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"တစ်ပြိုင်နက် များစွာလုပ်ခြင်း"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"လက်ရှိအက်ပ်ကို ညာ၌ထားကာ မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံးရန်"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"လက်ရှိအက်ပ်ကို ဘယ်၌ထားကာ မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံးရန်"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"မျက်နှာပြင် ခွဲ၍ပြသမှုမှ မျက်နှာပြင်အပြည့်သို့ ပြောင်းရန်"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"မျက်နှာပြင်ခွဲ၍ပြသခြင်း သုံးစဉ် ညာ (သို့) အောက်ရှိအက်ပ်သို့ ပြောင်းရန်"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးစဉ် ဘယ် (သို့) အထက်ရှိအက်ပ်သို့ ပြောင်းရန်"</string>
@@ -867,7 +875,7 @@
     <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ဆက်တင်များ၏ အစီအစဉ်ကို တည်းဖြတ်ပါ။"</string>
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ပါဝါမီနူး"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်ချထားချိန် မျက်နှာပြင်"</string>
+    <string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="finder_active" msgid="7907846989716941952">"ပါဝါပိတ်ထားသော်လည်း Find My Device ဖြင့် ဤဖုန်းကို ရှာနိုင်သည်"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"စက်ပိတ်နေသည်…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0f9bb46..5bc2fe5 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Varselskygge."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hurtiginnstillinger."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total stillhet"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Se alle"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bruk Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tilkoblet"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Lagret"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koble fra"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiver"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Slå på igjen i morgen automatisk"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funksjoner som Quick Share, Finn enheten min og enhetsposisjon bruker Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth slås på i morgen kl. 05.00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funksjoner som Quick Share og Finn enheten min bruker Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth slås på i morgen tidlig"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Lyddeling"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Deler lyd"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Lyd"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Hodetelefoner"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Registrer problem"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stopp"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Feilrapport"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Hvilken del av enhetsopplevelsen din ble påvirket?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Velg problemtype"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skjermopptak"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Middels"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Høy"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Høreapparater"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Høreapparater"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Koble til en ny enhet"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klikk for å koble til en ny enhet"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du oppheve blokkeringen av enhetsmikrofonen?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du oppheve blokkeringen av enhetskameraet?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader raskt • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Moduler på låseskjermen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Sveip til venstre for å starte fellesveiledningen"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpass"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Lukk"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Åpne innstillingene"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Vil du slå på jobbapper igjen?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Slå på"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Lukk moduler på låseskjermen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Moduler på låseskjermen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullegardinmeny"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enheten administreres av forelderen din. Forelderen din kan se og administrere informasjon, for eksempel appene du bruker, posisjonen din og skjermtiden din."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Holdes opplåst med TrustAgent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Enheten var låst – for mange autentiseringsforsøk"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Enheten er låst – for mange autentiseringsforsøk"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Enheten er låst\nKunne ikke autentisere"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Lydinnstillinger"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Bytt tastaturoppsett"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Fjern søket"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Hurtigtaster"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Hurtigtaster"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søk etter hurtigtaster"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Fant ingen hurtigtaster"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Åpne assistenten"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Låseskjerm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ta et notat"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking på systemet"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Åpne delt skjerm med den aktive appen til høyre"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Åpne delt skjerm med den aktive appen til venstre"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Bruk delt skjerm med den nåværende appen til høyre"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Bruk delt skjerm med den nåværende appen til venstre"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Bytt fra delt skjerm til fullskjerm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bytt til appen til høyre eller under mens du bruker delt skjerm"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bytt til appen til venstre eller over mens du bruker delt skjerm"</string>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index af00423..a9efd1d 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Av"</item>
     <item msgid="5137565285664080143">"På"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Ikke tilgjengelig"</item>
+    <item msgid="3079622119444911877">"Av"</item>
+    <item msgid="3028994095749238254">"På"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5f51a91..f52466c 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -62,7 +62,7 @@
     <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi सेयर गर्नुहोस्"</string>
     <string name="wifi_debugging_title" msgid="7300007687492186076">"यस नेटवर्कमा वायरलेस डिबगिङ सेवा प्रयोग गर्न दिने हो?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"नेटवर्कको नाम (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi ठेगाना (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
-    <string name="wifi_debugging_always" msgid="2968383799517975155">"यस नेटवर्कमा सधैँ अनुमति दिइयोस्"</string>
+    <string name="wifi_debugging_always" msgid="2968383799517975155">"यस नेटवर्कमा सधैँ अनुमति दिनुहोस्"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"अनुमति दिनुहोस्"</string>
     <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"वायरलेस डिबगिङ सेवालाई अनुमति दिइएको छैन"</string>
     <string name="wifi_debugging_secondary_user_message" msgid="9085779370142222881">"हालैमा यस डिभाइसमा साइन इन भएका प्रयोगकर्ताले USB डिबगिङ सक्रिय गर्न सक्दैनन्। यो सुविधा प्रयोग गर्न कृपया खाताका एड्मिनका रूपमा साइन इन गर्नुहोस्।"</string>
@@ -108,7 +108,7 @@
     <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"तपाईंले रेकर्ड गर्दै गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
     <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"तपाईंले कुनै एप रेकर्ड गर्दै गर्दा Android ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"रेकर्ड गर्न थाल्नुहोस्"</string>
-    <string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गरियोस्"</string>
+    <string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गर्नुहोस्"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिभाइसको अडियो"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तपाईंको डिभाइसका सङ्गीत, कल र रिङटोन जस्ता साउन्ड"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"माइक्रोफोन"</string>
@@ -116,7 +116,7 @@
     <string name="screenrecord_continue" msgid="4055347133700593164">"सुरु गर्नुहोस्"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"स्क्रिन रेकर्ड गरिँदै छ"</string>
     <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"स्क्रिन र अडियो रेकर्ड गरिँदै छ"</string>
-    <string name="screenrecord_taps_label" msgid="1595690528298857649">"स्पर्श गरिएका स्थानहरू देखाइयोस्"</string>
+    <string name="screenrecord_taps_label" msgid="1595690528298857649">"स्पर्श गरिएका स्थानहरू देखाउनुहोस्"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"रोक्नुहोस्"</string>
     <string name="screenrecord_share_label" msgid="5025590804030086930">"सेयर गर्नुहोस्"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"स्क्रिन रेकर्डिङ सेभ गरियो"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना कक्ष।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिङहरू"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"द्रुत सेटिङ तथा सूचना कक्ष।"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"स्क्रीन बन्द गर्नुहोस्।"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"लक स्क्रिन"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य प्रोफाइलको लक स्क्रिन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बन्द गर्नुहोस्"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"पूर्ण मौनता"</string>
@@ -270,17 +270,20 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"सबै डिभाइसहरू हेर्नुहोस्"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लुटुथ प्रयोग गर्नुहोस्"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट गरिएको छ"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"अडियो सेयरिङ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेभ गरिएको छ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट गर्नुहोस्"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"एक्टिभेट गर्नुहोस्"</string>
-    <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"भोलि फेरि स्वतः अन गरियोस्"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"क्विक सेयर, Find My Device र डिभाइसको लोकेसन जस्ता सुविधाहरूले ब्लुटुथ प्रयोग गर्छन्"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ब्लुटुथ भोलि बिहान ५ बजे अन हुने छ"</string>
+    <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"भोलि फेरि स्वतः अन गर्नुहोस्"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"क्विक सेयर र Find My Device जस्ता सुविधाहरू प्रयोग गर्न ब्लुटुथ चाहिन्छ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ब्लुटुथ भोलि बिहान अन हुने छ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"अडियो सेयरिङ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"अडियो सेयर गरिँदै छ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ब्याट्री"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"अडियो"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"इनपुट"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"श्रवण यन्त्रहरू"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"हियरिङ डिभाइसहरू"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"सक्रिय गर्दै…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अटो रोटेट"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्क्रिन स्वतःघुम्ने"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"समस्या रेकर्ड गर्नुहोस्"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"सुरु गर्नुहोस्"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"रोक्नुहोस्"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"त्रुटिको रिपोर्ट"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"तपाईंको डिभाइसको कुन चाहिँ सुविधा प्रभावित भएको छ?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"समस्याको प्रकार चयन गर्नुहोस्"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"स्क्रिन रेकर्ड"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"डिफल्ट"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"मध्यम"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"उच्च"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"हियरिङ डिभाइसहरू"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"हियरिङ डिभाइसहरू"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नयाँ डिभाइस कनेक्ट गर्नुहोस्"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नयाँ डिभाइसमा कनेक्ट गर्न क्लिक गर्नुहोस्"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिभाइसको माइक्रोफोन अनब्लक गर्ने हो?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिभाइसको क्यामेरा अनब्लक गर्ने हो?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • छिटो चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लक स्क्रिनमा भएका विजेटहरू"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्युनल ट्युटोरियल सुरु गर्न बायाँतिर स्वाइप गर्नुहोस्"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइज गर्नुहोस्"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारेज गर्नुहोस्"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"सेटिङ खोल्नुहोस्"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"कामसम्बन्धी एपहरू अनपज गर्ने हो?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"अनपज गर्नुहोस्"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"लक स्क्रिनमा भएका विजेटहरू बन्द गर्नुहोस्"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"लक स्क्रिनमा भएका विजेटहरू"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनु"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यो सत्रमा भएका सबै एपहरू र डेटा मेटाइने छ।"</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"यो डिभाइस तपाईंका अभिभावक व्यवस्थापन गर्नुहुन्छ। तपाईंका अभिभावक तपाईंले प्रयोग गर्ने एप, तपाईंको स्थान र तपाईंले यन्त्र चलाएर बिताउने समय जस्ता जानकारी हेर्न तथा व्यवस्थापन गर्न सक्नुहुन्छ।"</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ले खुला राखेको"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"डिभाइस लक गरिएको छ, प्रमाणीकरण गर्ने निकै धेरै प्रयास गरिएका छन्"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"डिभाइस लक गरिएको छ, निकै धेरै पटक प्रमाणीकरण गर्ने प्रयास भएको छ"</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"डिभाइस लक गरिएको छ\nप्रमाणीकरण गर्न सकिएन"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"ध्वनिसम्बन्धी सेटिङहरू"</string>
@@ -631,7 +638,7 @@
     <string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
     <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
     <string name="wallet_empty_state_label" msgid="7776761245237530394">"फोनमार्फत अझ छिटो र थप सुरक्षित तरिकाले खरिद गर्न भुक्तानी विधि सेटअप गर्नुहोस्"</string>
-    <string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाइयोस्"</string>
+    <string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाउनुहोस्"</string>
     <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"खोल्न ट्याप गर्नुहोस्"</string>
     <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"अपडेट गरिँदै छ"</string>
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"किबोर्डको लेआउट बदल्नुहोस्"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"वा"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"किवर्ड हटाउनुहोस्"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"सर्टकटहरू"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"किबोर्डका सर्टकटहरू"</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>
@@ -759,7 +766,7 @@
     <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"हालको एपका लागि सर्टकटहरू देखाइँदै छ"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचनाहरू हेर्नुहोस्"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रिनसट खिच्नुहोस्"</string>
-    <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"सर्टकटहरू देखाइऊन्"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"सर्टकटहरू देखाउनुहोस्"</string>
     <string name="group_system_go_back" msgid="2730322046244918816">"पछाडि जानुहोस्"</string>
     <string name="group_system_access_home_screen" msgid="4130366993484706483">"होम स्क्रिनमा जानुहोस्"</string>
     <string name="group_system_overview_open_apps" msgid="5659958952937994104">"हालसालै चलाइएका एपहरू हेर्ने तरिका"</string>
@@ -769,10 +776,10 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"सेटिङ खोल्नुहोस्"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"एसिस्टेन्ट खोल्नुहोस्"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रिन लक गर्नुहोस्"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट लेख"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टम मल्टिटास्किङ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"हालको एप दायाँतर्फ रहने गरी स्प्लिट स्क्रिन मोड सुरु गर्नुहोस्"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"हालको एप बायाँतर्फ रहने गरी स्प्लिट स्क्रिन मोड सुरु गर्नुहोस्"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट लेख्नुहोस्"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"एकै पटक एकभन्दा बढी एप चलाउन मिल्ने सुविधा"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"हालको एप दायाँ भागमा पारेर स्प्लिट स्क्रिन प्रयोग गर्नुहोस्"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"हालको एप बायाँ भागमा पारेर स्प्लिट स्क्रिन प्रयोग गर्नुहोस्"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"स्प्लिट स्क्रिनको साटो फुल स्क्रिन प्रयोग गर्नुहोस्"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रिन प्रयोग गर्दै गर्दा दायाँ वा तलको एप चलाउनुहोस्"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रिन प्रयोग गर्दै गर्दा बायाँ वा माथिको एप चलाउनुहोस्"</string>
@@ -1001,7 +1008,7 @@
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सिरानको दायाँतिर सार्नुहोस्"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"पुछारको बायाँतिर सार्नुहोस्"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"पुछारको दायाँतिर सार्नुहोस्"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"किनारामा सार्नुहोस् र नदेखिने पार्नु…"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"किनारामा सार्नुहोस् र लुकाउनुहोस्"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"किनाराबाट सार्नुहोस् र देखिने पार्नु…"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"हटाउनुहोस्"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"टगल गर्नुहोस्"</string>
@@ -1028,8 +1035,8 @@
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"पुनः मिलाउनुहोस्"</string>
     <string name="controls_favorite_add_controls" msgid="1221420435546694004">"कन्ट्रोलहरू हाल्नुहोस्"</string>
     <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"सम्पादन गर्ने स्क्रिनमा फर्कनुहोस्"</string>
-    <string name="controls_favorite_load_error" msgid="5126216176144877419">"नियन्त्रण सुविधाहरू लोड गर्न सकिएन। <xliff:g id="APP">%s</xliff:g> एपका सेटिङ परिवर्तन गरिएका छैनन् भन्ने कुरा सुनिश्चित गर्न उक्त एप जाँच्नुहोस्।"</string>
-    <string name="controls_favorite_load_none" msgid="7687593026725357775">"मिल्दा नियन्त्रण सुविधाहरू उपलब्ध छैनन्"</string>
+    <string name="controls_favorite_load_error" msgid="5126216176144877419">"कन्ट्रोल लोड गर्न सकिएन। <xliff:g id="APP">%s</xliff:g> एपका सेटिङ परिवर्तन गरिएका छैनन् भन्ने कुरा सुनिश्चित गर्न उक्त एप जाँच्नुहोस्।"</string>
+    <string name="controls_favorite_load_none" msgid="7687593026725357775">"मिल्दा कन्ट्रोल उपलब्ध छैनन्"</string>
     <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>
@@ -1288,7 +1295,7 @@
     <string name="privacy_dialog_summary" msgid="2458769652125995409">"एपको हालसालैको प्रयोग"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"हालसालै एक्सेस गर्ने एप हेर्नुहोस्"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"पूरा भयो"</string>
-    <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"एक्स्पान्ड गरियोस् र विकल्पहरू देखाइयोस्"</string>
+    <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"एक्स्पान्ड गर्नुहोस् र विकल्पहरू देखाउनुहोस्"</string>
     <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"कोल्याप्स गर्नुहोस्"</string>
     <string name="privacy_dialog_close_app_button" msgid="8006250171305878606">"यो एप बन्द गर्नुहोस्"</string>
     <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"<xliff:g id="APP_NAME">%1$s</xliff:g> बन्द गरिएको छ"</string>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index 005a473..c1b2f34 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"अफ छ"</item>
     <item msgid="5137565285664080143">"अन छ"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"उपलब्ध छैन"</item>
+    <item msgid="3079622119444911877">"अफ छ"</item>
+    <item msgid="3028994095749238254">"अन छ"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml
index 291f8a2..546bf1c 100644
--- a/packages/SystemUI/res/values-night/styles.xml
+++ b/packages/SystemUI/res/values-night/styles.xml
@@ -72,4 +72,8 @@
         <item name="android:textColor">@color/material_dynamic_secondary80</item>
     </style>
 
+    <style name="ShortcutHelperTheme" parent="@style/ShortcutHelperThemeCommon">
+        <item name="android:windowLightNavigationBar">false</item>
+    </style>
+
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 1f780b3..7a37aa0 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -145,7 +145,7 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Spraakassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portemonnee"</string>
-    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-codescanner"</string>
+    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-code­scanner"</string>
     <string name="accessibility_unlock_button" msgid="3613812140816244310">"Ontgrendeld"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Apparaat vergrendeld"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gezicht scannen"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meldingenpaneel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snelle instellingen."</string>
     <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_lock_screen" msgid="409034672704273634">"Vergrendelscherm"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vergrendelscherm voor werk"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sluiten"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"totale stilte"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Alles tonen"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth gebruiken"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbonden"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio delen"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Opgeslagen"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"loskoppelen"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activeren"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Morgen weer automatisch aanzetten"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Functies zoals Quick Share, Vind mijn apparaat en apparaatlocatie maken gebruik van bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth gaat morgen om 05:00 uur aan"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Functies zoals Quick Share en Vind mijn apparaat gebruiken bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth wordt morgenochtend aangezet"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio delen"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audio delen…"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batterijniveau"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Probleem vastleggen"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Starten"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stoppen"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Bugrapport"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Op welk onderdeel van de apparaatfunctionaliteit had dit effect?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Probleemtype selecteren"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Schermopname"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standaard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Gemiddeld"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hoog"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hoortoestellen"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hoortoestellen"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Nieuw apparaat koppelen"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nieuw apparaat te koppelen"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Microfoon van apparaat niet meer blokkeren?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Apparaatcamera niet meer blokkeren?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Snel opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets op het vergrendelscherm"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe naar links om de communitytutorial te starten"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Aanpassen"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Sluiten"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Instellingen openen"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Werk-apps hervatten?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Hervatten"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Widgets op het vergrendelscherm sluiten"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets op het vergrendelscherm"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
@@ -551,7 +558,7 @@
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dit apparaat wordt beheerd door je ouder. Je ouder kan informatie bekijken en beheren, zoals de apps die je gebruikt, je locatie en je schermtijd."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Ontgrendeld gehouden door TrustAgent"</string>
-    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Het apparaat is vergrendeld na te veel verificatiepogingen"</string>
+    <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Te veel pogingen. Apparaat vergrendeld."</string>
     <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Apparaat vergrendeld\nVerificatie mislukt"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Geluidsinstellingen"</string>
@@ -608,7 +615,7 @@
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Ruimtelijke audio"</string>
     <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Uit"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Vast"</string>
-    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Hoofdbeweging volgen"</string>
+    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Hoofd­beweging volgen"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"Tik om de beltoonmodus te wijzigen"</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"geluid uit"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"geluid aanzetten"</string>
@@ -637,7 +644,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontgrendelen om te gebruiken"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Instellingen voor vergrendelscherm"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR-codescanner"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR-code­scanner"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Updaten"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuig­modus"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Toetsenbordindeling wisselen"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"of"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Zoekopdracht wissen"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Sneltoetsen"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Sneltoetsen"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sneltoetsen zoeken"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen sneltoetsen gevonden"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systeem"</string>
@@ -770,12 +777,12 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistent openen"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Scherm vergrendelen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Notitie maken"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systeem-multitasking"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Gesplitst scherm openen met huidige app rechts"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Gesplitst scherm openen met huidige app links"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasken"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gesplitst scherm gebruiken met de huidige app aan de rechterkant"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gesplitst scherm gebruiken met de huidige app aan de linkerkant"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Van gesplitst scherm naar volledig scherm schakelen"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ga naar de app rechts of onderaan als je een gesplitst scherm gebruikt"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ga naar de app links of bovenaan als je een gesplitst scherm gebruikt"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Naar de app rechts of onderaan gaan als je een gesplitst scherm gebruikt"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Naar de app links of bovenaan gaan als je een gesplitst scherm gebruikt"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Tijdens gesplitst scherm: een app vervangen door een andere"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Invoer"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Overschakelen naar volgende taal"</string>
@@ -829,8 +836,8 @@
     <string name="right_keycode" msgid="2480715509844798438">"Toetscode rechts"</string>
     <string name="left_icon" msgid="5036278531966897006">"Icoon links"</string>
     <string name="right_icon" msgid="1103955040645237425">"Icoon rechts"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Houd vast en sleep om tegels toe te voegen"</string>
-    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Houd vast en sleep om tegels opnieuw in te delen"</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Houd een tegel ingedrukt en sleep om die toe te voegen"</string>
+    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Houd een tegel ingedrukt en sleep om die te verplaatsen"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Sleep hier naartoe om te verwijderen"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"Je hebt minimaal <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tegels nodig"</string>
     <string name="qs_edit" msgid="5583565172803472437">"Bewerken"</string>
@@ -1262,7 +1269,7 @@
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Nog <xliff:g id="PERCENTAGE">%s</xliff:g> batterijlading"</string>
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Verbind je stylus met een oplader"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Batterij van stylus bijna leeg"</string>
-    <string name="video_camera" msgid="7654002575156149298">"Videocamera"</string>
+    <string name="video_camera" msgid="7654002575156149298">"Video­camera"</string>
     <string name="call_from_work_profile_title" msgid="5418253516453177114">"Kan niet bellen vanuit een app voor persoonlijke doeleinden"</string>
     <string name="call_from_work_profile_text" msgid="2856337395968118274">"Je organisatie staat je alleen toe om te bellen vanuit werk-apps"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Overschakelen naar werkprofiel"</string>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index 1b286f3..c5d9361 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Uit"</item>
     <item msgid="5137565285664080143">"Aan"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Niet beschikbaar"</item>
+    <item msgid="3079622119444911877">"Uit"</item>
+    <item msgid="3028994095749238254">"Aan"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 9a602b8..7e8ee6f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍‍।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"କୁଇକ ସେଟିଂସ ଏବଂ ବିଜ୍ଞପ୍ତି ସେଡ।"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ ସ୍କ୍ରିନ।"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ଲକ ସ୍କ୍ରିନ"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ୱର୍କ ଲକ୍‍ ସ୍କ୍ରୀନ୍‍"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ସମ୍ପୂର୍ଣ୍ଣ ନୀରବତା"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ସବୁ ଦେଖନ୍ତୁ"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"କନେକ୍ଟ କରାଯାଇଛି"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ଅଡିଓ ସେୟାରିଂ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ସେଭ କରାଯାଇଛି"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ଡିସକନେକ୍ଟ କରନ୍ତୁ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ଆସନ୍ତାକାଲି ସ୍ୱତଃ ପୁଣି ଚାଲୁ ହେବ"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Quick Share, Find My Device ଏବଂ ଡିଭାଇସ ଲୋକେସନ ପରି ଫିଚରଗୁଡ଼ିକ ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରେ"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ବ୍ଲୁଟୁଥ ଆସନ୍ତାକାଲି 5 AMରେ ଚାଲୁ ହେବ"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share ଏବଂ Find My Device ପରି ଫିଚରଗୁଡ଼ିକ ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରେ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ବ୍ଲୁଟୁଥ ଆସନ୍ତା କାଲି ସକାଳେ ଚାଲୁ ହେବ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ଅଡିଓ ସେୟାରିଂ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ଅଡିଓ ସେୟାର କରାଯାଉଛି"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ବ୍ୟାଟେରୀ"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ଅଡିଓ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ହେଡସେଟ୍‍"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ସମସ୍ୟାର ରେକର୍ଡ କରନ୍ତୁ"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ବଗ୍‌ ରିପୋର୍ଟ୍‌"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ଆପଣଙ୍କ ଡିଭାଇସ ଅନୁଭୂତିର କେଉଁ ଅଂଶ ପ୍ରଭାବିତ ହୋଇଛି?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ସମସ୍ୟାର ପ୍ରକାର ଚୟନ କରନ୍ତୁ"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ସ୍କ୍ରିନ ରେକର୍ଡ"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ଷ୍ଟାଣ୍ଡାର୍ଡ"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ମଧ୍ୟମ"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ଅଧିକ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ନୂଆ ଡିଭାଇସ ପେୟାର କର"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ନୂଆ ଡିଭାଇସ ପେୟାର କରିବାକୁ କ୍ଲିକ କରନ୍ତୁ"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ କରିବେ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ଡିଭାଇସର କେମେରାକୁ ଅନବ୍ଲକ କରିବେ?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ବାମକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ଖାରଜ କରନ୍ତୁ"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ସେଟିଂସ ଖୋଲନ୍ତୁ"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ୱାର୍କ ଆପ୍ସକୁ ପୁଣି ଚାଲୁ କରିବେ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକୁ ବନ୍ଦ କରନ୍ତୁ"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ୟୁଜର୍‍ ବଦଳାନ୍ତୁ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ପୁଲଡାଉନ ମେନୁ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍‌ ଓ ଡାଟା ଡିଲିଟ୍‌ ହୋଇଯିବ।"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"କୀ\'ବୋର୍ଡ୍‍ର ଲେଆଉଟ୍‍କୁ ବଦଳାନ୍ତୁ"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"କିମ୍ବା"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ସର୍ଚ୍ଚ କ୍ୱେରୀକୁ ଖାଲି କରନ୍ତୁ"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ସର୍ଟକଟଗୁଡ଼ିକ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"କୀବୋର୍ଡ ସର୍ଟକଟ"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ଖୋଲନ୍ତୁ"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ଲକ ସ୍କ୍ରିନ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ଏକ ନୋଟ ଲେଖନ୍ତୁ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ସିଷ୍ଟମ ମଲ୍ଟିଟାସ୍କିଂ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHSରେ ବର୍ତ୍ତମାନର ଆପ ସହ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ପ୍ରବେଶ କରାନ୍ତୁ"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHSରେ ବର୍ତ୍ତମାନର ଆପ ସହ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ପ୍ରବେଶ କରାନ୍ତୁ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ମଲ୍ଟିଟାସ୍କିଂ"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ଡାହାଣରେ ବର୍ତ୍ତମାନର ଆପ ସହିତ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ବାମରେ ବର୍ତ୍ତମାନର ଆପ ସହିତ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନରୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବା ସମୟରେ ଡାହାଣପଟର ବା ତଳର ଆପକୁ ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବା ସମୟରେ ବାମପଟର ବା ଉପରର ଆପକୁ ସୁଇଚ କରନ୍ତୁ"</string>
@@ -862,7 +869,7 @@
     <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"କ୍ଵିକ ସେଟିଂସ ଖୋଲନ୍ତୁ।"</string>
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ଦ୍ରୁତ ସେଟିଂସ୍ ବନ୍ଦ କରନ୍ତୁ।"</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g> ଭାବରେ ସାଇନ୍‌ ଇନ୍‌ କରିଛନ୍ତି"</string>
-    <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ଉପଯୋଗକର୍ତ୍ତା ବାଛନ୍ତୁ"</string>
+    <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ୟୁଜର ବାଛନ୍ତୁ"</string>
     <string name="data_connection_no_internet" msgid="691058178914184544">"କୌଣସି ଇଣ୍ଟରନେଟ୍‌ କନେକ୍ସନ୍ ନାହିଁ"</string>
     <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ସେଟିଙ୍ଗ ଖୋଲନ୍ତୁ।"</string>
     <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ସେଟିଂସର କ୍ରମ ଏଡିଟ କରନ୍ତୁ।"</string>
@@ -997,7 +1004,7 @@
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ଆକ୍ସେସିବିଲିଟୀ ବଟନ ଦେଖାଇବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{#ଟି ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି}other{#ଟି ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି}}"</string>
-    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ଶୀର୍ଷ ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
+    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ଶୀର୍ଷ ବାମକୁ ମୁଭ କରନ୍ତୁ"</string>
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ଶୀର୍ଷ ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ନିମ୍ନ ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
     <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ନିମ୍ନ ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"କୀବୋର୍ଡ ବେକଲାଇଟ"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dରୁ %1$d ନମ୍ବର ଲେଭେଲ"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"ହୋମ କଣ୍ଟ୍ରୋଲ୍ସ"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"ସ୍କ୍ରିନସେଭର ଭାବେ ହୋମ କଣ୍ଟ୍ରୋଲ୍ସକୁ ଶୀଘ୍ର ଆକ୍ସେସ କର"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"ସ୍କ୍ରିନସେଭର ଭାବେ ହୋମ କଣ୍ଟ୍ରୋଲ୍ସକୁ ଶୀଘ୍ର ଆକ୍ସେସ କରନ୍ତୁ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index fd727bf..fe187c2 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"ବନ୍ଦ ଅଛି"</item>
     <item msgid="5137565285664080143">"ଚାଲୁ ଅଛି"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"ଅନୁପଲବ୍ଧ"</item>
+    <item msgid="3079622119444911877">"ବନ୍ଦ ଅଛି"</item>
+    <item msgid="3028994095749238254">"ଚାଲୁ ଅଛି"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 40efd0b..df823cf 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ।"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">" ਲਾਕ  ਸਕ੍ਰੀਨ।"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ਕਾਰਜ-ਸਥਾਨ  ਲਾਕ  ਸਕ੍ਰੀਨ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ਬੰਦ ਕਰੋ"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ਪੂਰਾ ਸ਼ਾਂਤ"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ਸਭ ਦੇਖੋ"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ਬਲੂਟੁੱਥ ਵਰਤੋ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ਕਨੈਕਟ ਹੈ"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"ਕੱਲ੍ਹ ਨੂੰ ਆਪਣੇ ਆਪ ਚਾਲੂ ਹੋ ਜਾਵੇਗਾ"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ਕਵਿੱਕ ਸ਼ੇਅਰ, Find My Device ਅਤੇ ਡੀਵਾਈਸ ਦਾ ਟਿਕਾਣਾ ਵਰਗੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਬਲੂਟੁੱਥ ਦੀ ਵਰਤੋਂ ਕਰਦੀਆਂ ਹਨ"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"ਬਲੂਟੁੱਥ ਕੱਲ੍ਹ ਸਵੇਰੇ 5 ਵਜੇ ਚਾਲੂ ਹੋਵੇਗਾ"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ਕਵਿੱਕ ਸ਼ੇਅਰ ਅਤੇ Find My Device ਵਰਗੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਬਲੂਟੁੱਥ ਵਰਤਦੀਆਂ ਹਨ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ਬਲੂਟੁੱਥ ਕੱਲ੍ਹ ਸਵੇਰੇ ਚਾਲੂ ਹੋ ਜਾਵੇਗਾ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ਆਡੀਓ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ਆਡੀਓ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ਹੈੱਡਸੈੱਟ"</string>
@@ -328,7 +331,7 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string>
     <string name="quick_settings_work_mode_label" msgid="6440531507319809121">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ"</string>
     <string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"ਰੋਕਿਆ ਗਿਆ"</string>
-    <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ਰਾਤ ਦੀ ਰੋਸ਼ਨੀ"</string>
+    <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ਨਾਈਟ ਲਾਈਟ"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ਸਮੱਸਿਆ ਰਿਕਾਰਡ ਕਰੋ"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"ਬੰਦ ਕਰੋ"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"ਬੱਗ ਰਿਪੋਰਟ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਿਹੜੀ ਸੁਵਿਧਾ ਪ੍ਰਭਾਵਿਤ ਹੋਈ ਸੀ?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ਸਮੱਸਿਆ ਦੀ ਕਿਸਮ ਚੁਣੋ"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ਮਿਆਰੀ"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ਦਰਮਿਆਨਾ"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ਜ਼ਿਆਦਾ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"\'ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ\' \'ਤੇ ਕਲਿੱਕ ਕਰੋ"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ਖਾਰਜ ਕਰੋ"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਰੋਕ ਹਟਾਈਏ?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ਰੋਕ ਹਟਾਓ"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਬੰਦ ਕਰੋ"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ਪੁੱਲਡਾਊਨ ਮੀਨੂ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿਚਲੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟੇ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
@@ -583,9 +590,9 @@
     <string name="screen_pinning_negative" msgid="6882816864569211666">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="screen_pinning_start" msgid="7483998671383371313">"ਐਪ ਨੂੰ ਪਿੰਨ ਕੀਤਾ ਗਿਆ"</string>
     <string name="screen_pinning_exit" msgid="4553787518387346893">"ਐਪ ਨੂੰ ਅਨਪਿੰਨ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="stream_voice_call" msgid="7468348170702375660">"ਕਾਲ ਕਰੋ"</string>
+    <string name="stream_voice_call" msgid="7468348170702375660">"ਕਾਲ"</string>
     <string name="stream_system" msgid="7663148785370565134">"ਸਿਸਟਮ"</string>
-    <string name="stream_ring" msgid="7550670036738697526">"ਘੰਟੀ ਵਜਾਓ"</string>
+    <string name="stream_ring" msgid="7550670036738697526">"ਘੰਟੀ"</string>
     <string name="stream_music" msgid="2188224742361847580">"ਮੀਡੀਆ"</string>
     <string name="stream_alarm" msgid="16058075093011694">"ਅਲਾਰਮ"</string>
     <string name="stream_notification" msgid="7930294049046243939">"ਸੂਚਨਾ"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ਕੀ-ਬੋਰਡ ਖਾਕਾ ਬਦਲੋ"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ਜਾਂ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ਖੋਜ ਪੁੱਛਗਿੱਛ ਕਲੀਅਰ ਕਰੋ"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ਸ਼ਾਰਟਕੱਟ"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant ਖੋਲ੍ਹੋ"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ਨੋਟ ਲਿਖੋ"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ਸਿਸਟਮ ਮਲਟੀਟਾਸਕਿੰਗ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHS ਲਈ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHS ਲਈ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ਮਲਟੀਟਾਸਕਿੰਗ"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ਸੱਜੇ ਪਾਸੇ ਦਿੱਤੀ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ਖੱਬੇ ਪਾਸੇ ਦਿੱਤੀ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਤੋਂ ਪੂਰੀ ਸਕ੍ਰੀਨ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਸੱਜੇ ਜਾਂ ਹੇਠਾਂ ਮੌਜੂਦ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਖੱਬੇ ਜਾਂ ਉੱਪਰ ਮੌਜੂਦ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index afb1e8b..62dc05a 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"ਬੰਦ"</item>
     <item msgid="5137565285664080143">"ਚਾਲੂ"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"ਉਪਲਬਧ ਨਹੀਂ"</item>
+    <item msgid="3079622119444911877">"ਬੰਦ ਹੈ"</item>
+    <item msgid="3028994095749238254">"ਚਾਲੂ ਹੈ"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 48262a0..f6468af 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obszar powiadomień."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Szybkie ustawienia."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"całkowita cisza"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Pokaż wszystkie"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Używaj Bluetootha"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Połączone"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Udostępnianie dźwięku"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Zapisane"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"rozłącz"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktywuj"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automatycznie włącz ponownie jutro"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funkcje takie jak szybkie udostępnianie, Znajdź moje urządzenie czy lokalizacja urządzenia używają Bluetootha"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth włączy się jutro o 5 rano"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkcje takie jak szybkie udostępnianie czy Znajdź moje urządzenie korzystają z Bluetootha"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth włączy się jutro rano"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Udostępnianie dźwięku"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Udostępniam dźwięk"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> naładowania baterii"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Dźwięk"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Zestaw słuchawkowy"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Zarejestruj problem"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Rozpocznij"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zatrzymaj"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Raport o błędzie"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Którego aspektu korzystania z urządzenia dotyczył problem?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Wybierz typ problemu"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Nagrywanie ekranu"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardowy"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Średni"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Wysoki"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Urządzenia słuchowe"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Urządzenia słuchowe"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sparuj nowe urządzenie"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknij, aby sparować nowe urządzenie"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokować mikrofon urządzenia?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokować aparat urządzenia?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Szybkie ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widżety na ekranie blokady"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aby uruchomić wspólny samouczek, przeciągnij palcem w lewo"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Dostosuj"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zamknij"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otwórz ustawienia"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Cofnąć wstrzymanie aplikacji służbowych?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Cofnij wstrzymanie"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zamknij widżety na ekranie blokady"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widżety na ekranie blokady"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
@@ -670,15 +677,15 @@
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"Bez dźwięku i wibracji"</string>
     <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Brak dźwięku i wibracji, wyświetlają się niżej w sekcji rozmów"</string>
     <string name="notification_channel_summary_default" msgid="777294388712200605">"Mogą włączać dzwonek lub wibracje w zależności od ustawień urządzenia"</string>
-    <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Mogą włączyć dzwonek lub wibracje w zależności od ustawień urządzenia. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Mogą włączać dzwonek lub wibracje w zależności od ustawień urządzenia. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Pozwól systemowi decydować, czy o powiadomieniu powinien informować dźwięk czy wibracja"</string>
     <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;Stan:&lt;/b&gt; zmieniony na Domyślny"</string>
     <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"&lt;b&gt;Stan:&lt;/b&gt; zmieniono na Ciche"</string>
     <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"&lt;b&gt;Stan:&lt;/b&gt; podniesiono ważność"</string>
     <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;Stan:&lt;/b&gt; obniżono ważność"</string>
-    <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady"</string>
-    <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek"</string>
-    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, przerywa działanie trybu Nie przeszkadzać"</string>
+    <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Wyświetlają się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady"</string>
+    <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Wyświetlają się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek"</string>
+    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Wyświetlają się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, przerywają działanie trybu Nie przeszkadzać"</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorytetowe"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Przełącz układ klawiatury"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"lub"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Wyczyść wyszukiwanie hasło"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skróty"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Skróty klawiszowe"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Wyszukiwanie skrótów"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nie znaleziono skrótów"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -757,29 +764,29 @@
     <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Pokazuję skróty dotyczące danych wejściowych"</string>
     <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Pokazuję skróty otwierające aplikacje"</string>
     <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Pokazuję skróty dotyczące bieżącej aplikacji"</string>
-    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Wyświetlanie powiadomień"</string>
-    <string name="group_system_full_screenshot" msgid="5742204844232667785">"Robienie zrzutu ekranu"</string>
-    <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Pokazywanie skrótów"</string>
-    <string name="group_system_go_back" msgid="2730322046244918816">"Przechodzenie wstecz"</string>
-    <string name="group_system_access_home_screen" msgid="4130366993484706483">"Wyświetlanie ekranu głównego"</string>
-    <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Wyświetlanie ostatnich aplikacji"</string>
-    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Przełączanie się do przodu między ostatnimi aplikacjami"</string>
-    <string name="group_system_cycle_back" msgid="8194102916946802902">"Przełączanie się wstecz między ostatnimi aplikacjami"</string>
-    <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otwieranie listy aplikacji"</string>
-    <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otwieranie ustawień"</string>
-    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otwieranie asystenta"</string>
-    <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokada ekranu"</string>
+    <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Wyświetl powiadomienia"</string>
+    <string name="group_system_full_screenshot" msgid="5742204844232667785">"Zapisz zrzut ekranu"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Pokaż skróty"</string>
+    <string name="group_system_go_back" msgid="2730322046244918816">"Przejdź wstecz"</string>
+    <string name="group_system_access_home_screen" msgid="4130366993484706483">"Wyświetl ekran główny"</string>
+    <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Wyświetl ostatnie aplikacje"</string>
+    <string name="group_system_cycle_forward" msgid="5478663965957647805">"Przełącz się do przodu między ostatnimi aplikacjami"</string>
+    <string name="group_system_cycle_back" msgid="8194102916946802902">"Przełącz się wstecz między ostatnimi aplikacjami"</string>
+    <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otwórz listę aplikacji"</string>
+    <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otwórz ustawienia"</string>
+    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otwórz asystenta"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Zablokuj ekran"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Zanotuj"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Wielozadaniowość w systemie"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Uruchamianie trybu podzielonego ekranu z bieżącą aplikacją po prawej"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Uruchamianie trybu podzielonego ekranu z bieżącą aplikacją po lewej"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Wielozadaniowość"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Podziel ekran z bieżącą aplikacją widoczną po prawej"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Podziel ekran z bieżącą aplikacją widoczną po lewej"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Przełącz podzielony ekran na pełny ekran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Przełącz się na aplikację po prawej lub poniżej na podzielonym ekranie"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Przełącz się na aplikację po lewej lub powyżej na podzielonym ekranie"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Podczas podzielonego ekranu: zastępowanie aplikacji"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Wprowadzanie"</string>
-    <string name="input_switch_input_language_next" msgid="3782155659868227855">"Przełączanie na następny język"</string>
-    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Przełączanie na poprzedni język"</string>
+    <string name="input_switch_input_language_next" msgid="3782155659868227855">"Przełącz na następny język"</string>
+    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Przełącz na poprzedni język"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"Otwieranie emotikonów"</string>
     <string name="input_access_voice_typing" msgid="7291201476395326141">"Otwieranie pisania głosowego"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacje"</string>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index 5d1c02e..5aa719f 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Wyłączono"</item>
     <item msgid="5137565285664080143">"Włączono"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Niedostępne"</item>
+    <item msgid="3079622119444911877">"Wyłączono"</item>
+    <item msgid="3028994095749238254">"Włączone"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 04bdf14..a1c72dc 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silêncio total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Mostrar tudo"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ativar automaticamente de novo amanhã"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Recursos como o Quick Share, o Encontre Meu Dispositivo e a localização do dispositivo usam o Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"O Bluetooth será ativado amanhã às 5h"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Recursos como o Quick Share e o Encontre Meu Dispositivo usam Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"O Bluetooth será ativado amanhã de manhã"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Compartilhamento de áudio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Compartilhando áudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Áudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Fone de ouvido"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problema na gravação"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Relatório do bug"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Que parte da sua experiência no dispositivo foi afetada?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecionar tipo de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravação de tela"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Médio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparelhos auditivos"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parear novo dispositivo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregamento rápido • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Abrir as configurações"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Reativar apps de trabalho?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reativar"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fechar widgets na tela de bloqueio"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets na tela de bloqueio"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
@@ -597,8 +604,8 @@
     <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Desativar som"</string>
     <string name="media_device_cast" msgid="4786241789687569892">"Transmitir"</string>
     <string name="stream_notification_unavailable" msgid="4313854556205836435">"Indisponível com o toque silenciado"</string>
-    <string name="stream_alarm_unavailable" msgid="4059817189292197839">"Indisponível porque o Não perturbe está ativado"</string>
-    <string name="stream_media_unavailable" msgid="6823020894438959853">"Indisponível porque o Não perturbe está ativado"</string>
+    <string name="stream_alarm_unavailable" msgid="4059817189292197839">"Indisponível com o Não perturbe ativado"</string>
+    <string name="stream_media_unavailable" msgid="6823020894438959853">"Indisponível com o Não perturbe ativado"</string>
     <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. Toque para ativar o som."</string>
     <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. Toque para configurar para vibrar. É possível que os serviços de acessibilidade sejam silenciados."</string>
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar a consulta de pesquisa"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atalhos do teclado"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -769,10 +776,10 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir configurações"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir o Google Assistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Crie uma nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Usar a tela dividida com o app atual à direita"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Usar a tela dividida com o app atual à esquerda"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Criar nota"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefas"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar a tela dividida com o aplicativo atual à direita"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar a tela dividida com o app atual à esquerda"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Mudar da tela dividida para a tela cheia"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mude para o app à direita ou abaixo ao usar a tela dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para o app à esquerda ou acima ao usar a tela dividida"</string>
@@ -830,7 +837,7 @@
     <string name="left_icon" msgid="5036278531966897006">"Ícone à esquerda"</string>
     <string name="right_icon" msgid="1103955040645237425">"Ícone à direita"</string>
     <string name="drag_to_add_tiles" msgid="8933270127508303672">"Mantenha pressionado e arraste para adicionar blocos"</string>
-    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste."</string>
+    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arraste aqui para remover"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"É preciso haver pelo menos <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> blocos"</string>
     <string name="qs_edit" msgid="5583565172803472437">"Editar"</string>
@@ -1297,7 +1304,7 @@
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Em uso pela ligação telefônica"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Usado recentemente em uma ligação telefônica"</string>
     <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Uso recente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Acesse rapidamente a automação residencial como um protetor de tela"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Controles de automação residencial no protetor de tela"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
index 453d813..3526c77 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desativado"</item>
     <item msgid="5137565285664080143">"Ativado"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Indisponível"</item>
+    <item msgid="3079622119444911877">"Desativar"</item>
+    <item msgid="3028994095749238254">"Ativar"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b627090..eadb5e54 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silêncio total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Ver tudo"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ligado"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partilha de áudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desassociar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Reativar amanhã automaticamente"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"As funcionalidades como Partilha rápida, Localizar o meu dispositivo e localização do dispositivo usam o Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"O Bluetooth vai ser ativado amanhã às 05:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"As funcionalidades como a Partilha rápida e o serviço Localizar o meu dispositivo usam o Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"O Bluetooth vai ser ativado amanhã de manhã"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Partilha de áudio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"A partilhar áudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de bateria"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Áudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ausc. c/ mic. integ."</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Registar problema"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Relatório de erro"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Que parte da experiência do disposit. foi afetada?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecione o tipo de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravação de ecrã"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Médio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Dispositivos auditivos"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Dispositivos auditivos"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sincronizar novo dispositivo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para sincronizar um novo dispositivo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmara do dispositivo?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar rapidamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets no ecrã de bloqueio"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize rapidamente para a esquerda para iniciar o tutorial coletivo"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorar"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Abrir definições"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Retomar apps de trabalho?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Retomar"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fechar widgets no ecrã de bloqueio"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets no ecrã de bloqueio"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mudar utilizador"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pendente"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
@@ -667,7 +675,7 @@
     <string name="notification_alert_title" msgid="3656229781017543655">"Predefinição"</string>
     <string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sem som ou vibração"</string>
-    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sem som ou vibração e aparece na parte inferior na secção de conversas."</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sem som ou vibração e aparece na parte inferior na secção de conversas"</string>
     <string name="notification_channel_summary_default" msgid="777294388712200605">"Pode tocar ou vibrar com base nas definições do dispositivo"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Pode tocar ou vibrar com base nas definições do dispositivo. As conversas da app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem como um balão por predefinição."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se esta notificação deve emitir um som ou uma vibração"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar esquema de teclado"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar consulta de pesquisa"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atalhos de teclado"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pesquise atalhos"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -768,12 +776,12 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir definições"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Assistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecrã de bloqueio"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Tire uma nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Execução de várias tarefas em simultâneo no sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Aceder ao ecrã dividido com a app atual para RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Aceder ao ecrã dividido com a app atual para LHS"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Tire notas"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Execução de várias tarefas em simultâneo"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Use o ecrã dividido com a app atual à direita"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Use o ecrã dividido com a app atual à esquerda"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Mudar de ecrã dividido para ecrã inteiro"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mude para a app à direita ou abaixo enquanto usa o ecrã dividido"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mudar para a app à direita ou abaixo enquanto usa o ecrã dividido"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para a app à esquerda ou acima enquanto usa o ecrã dividido"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Durante o ecrã dividido: substituir uma app por outra"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
@@ -798,7 +806,7 @@
     <string name="accessibility_long_click_tile" msgid="210472753156768705">"Abrir as definições"</string>
     <string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Auscultadores ligados"</string>
     <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Auscultadores com microfone integrado ligados"</string>
-    <string name="data_saver" msgid="3484013368530820763">"Poup. dados"</string>
+    <string name="data_saver" msgid="3484013368530820763">"Poupança de dados"</string>
     <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Poupança de dados ativada"</string>
     <string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string>
     <string name="switch_bar_off" msgid="5669805115416379556">"Desativado"</string>
@@ -997,9 +1005,9 @@
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}many{# atalhos removidos}other{# atalhos removidos}}"</string>
     <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover p/ parte sup. esquerda"</string>
-    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover parte superior direita"</string>
+    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover p/ parte sup. direita"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover p/ parte infer. esquerda"</string>
-    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover parte inferior direita"</string>
+    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Mover p/ parte infer. direita"</string>
     <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Mover p/ extremidade e ocultar"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Retirar extremidade e mostrar"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Remover"</string>
@@ -1304,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlos domésticos"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Aceda rapid. aos contr. domést. como prot. de ecrã"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Use controlos domésticos como proteção de ecrã"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 04bdf14..a1c72dc 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"silêncio total"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Mostrar tudo"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ativar automaticamente de novo amanhã"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Recursos como o Quick Share, o Encontre Meu Dispositivo e a localização do dispositivo usam o Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"O Bluetooth será ativado amanhã às 5h"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Recursos como o Quick Share e o Encontre Meu Dispositivo usam Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"O Bluetooth será ativado amanhã de manhã"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Compartilhamento de áudio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Compartilhando áudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Áudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Fone de ouvido"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problema na gravação"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Relatório do bug"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Que parte da sua experiência no dispositivo foi afetada?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selecionar tipo de problema"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Gravação de tela"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Médio"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Alto"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparelhos auditivos"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparelhos auditivos"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parear novo dispositivo"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregamento rápido • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Abrir as configurações"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Reativar apps de trabalho?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reativar"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Fechar widgets na tela de bloqueio"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgets na tela de bloqueio"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
@@ -597,8 +604,8 @@
     <string name="volume_ringer_status_silent" msgid="3691324657849880883">"Desativar som"</string>
     <string name="media_device_cast" msgid="4786241789687569892">"Transmitir"</string>
     <string name="stream_notification_unavailable" msgid="4313854556205836435">"Indisponível com o toque silenciado"</string>
-    <string name="stream_alarm_unavailable" msgid="4059817189292197839">"Indisponível porque o Não perturbe está ativado"</string>
-    <string name="stream_media_unavailable" msgid="6823020894438959853">"Indisponível porque o Não perturbe está ativado"</string>
+    <string name="stream_alarm_unavailable" msgid="4059817189292197839">"Indisponível com o Não perturbe ativado"</string>
+    <string name="stream_media_unavailable" msgid="6823020894438959853">"Indisponível com o Não perturbe ativado"</string>
     <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. Toque para ativar o som."</string>
     <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. Toque para configurar para vibrar. É possível que os serviços de acessibilidade sejam silenciados."</string>
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar a consulta de pesquisa"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Atalhos do teclado"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
@@ -769,10 +776,10 @@
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir configurações"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir o Google Assistente"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Crie uma nota"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Usar a tela dividida com o app atual à direita"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Usar a tela dividida com o app atual à esquerda"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Criar nota"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefas"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Usar a tela dividida com o aplicativo atual à direita"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Usar a tela dividida com o app atual à esquerda"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Mudar da tela dividida para a tela cheia"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mude para o app à direita ou abaixo ao usar a tela dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para o app à esquerda ou acima ao usar a tela dividida"</string>
@@ -830,7 +837,7 @@
     <string name="left_icon" msgid="5036278531966897006">"Ícone à esquerda"</string>
     <string name="right_icon" msgid="1103955040645237425">"Ícone à direita"</string>
     <string name="drag_to_add_tiles" msgid="8933270127508303672">"Mantenha pressionado e arraste para adicionar blocos"</string>
-    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste."</string>
+    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Para reorganizar, toque no bloco sem soltar e arraste"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arraste aqui para remover"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"É preciso haver pelo menos <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> blocos"</string>
     <string name="qs_edit" msgid="5583565172803472437">"Editar"</string>
@@ -1297,7 +1304,7 @@
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Em uso pela ligação telefônica"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Usado recentemente em uma ligação telefônica"</string>
     <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Uso recente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Usado recentemente pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Em uso pelo app <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Acesse rapidamente a automação residencial como um protetor de tela"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Controles de automação residencial no protetor de tela"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index 453d813..3526c77 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Desativado"</item>
     <item msgid="5137565285664080143">"Ativado"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Indisponível"</item>
+    <item msgid="3079622119444911877">"Desativar"</item>
+    <item msgid="3028994095749238254">"Ativar"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7d65f96a..e53b4a4 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"niciun sunet"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Afișează tot"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Folosește Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectat"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Permiterea accesului la audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvat"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deconectează"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activează"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Activează din nou automat mâine"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funcții precum Quick Share, Găsește-mi dispozitivul și locația dispozitivului folosesc Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth se va activa mâine la 5 dimineața"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funcții precum Quick Share și Găsește-mi dispozitivul folosesc Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth se va activa mâine dimineață"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Permiterea accesului la audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Se permite accesul la conținutul audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Căști"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problemă legată de înregistrare"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Începe"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Oprește"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Raport de eroare"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ce parte a experienței pe dispozitiv a fost afectată?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Selectează tipul problemei"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Înregistrarea ecranului"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mediu"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Ridicat"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Aparate auditive"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Aparate auditive"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Asociază un nou dispozitiv"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Dă clic pentru a asocia un nou dispozitiv"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblochezi microfonul dispozitivului?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblochezi camera dispozitivului?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă rapid • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeturi pe ecranul de blocare"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Glisează spre stânga pentru a începe tutorialul pentru comunitate"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizează"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Respinge"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Deschide setările"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Reactivezi aplicații de lucru?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Reactivează"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Închide widgeturile de pe ecranul de blocare"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgeturi pe ecranul de blocare"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Schimbă utilizatorul"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"meniu vertical"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Schimbă aspectul tastaturii"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"sau"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Șterge termenul de căutare"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Comenzi rapide"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Comenzi rapide de la tastatură"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Caută comenzi rapide"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nu există comenzi rapide"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Deschide Asistentul"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecranul de blocare"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Creează o notă"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking pe sistem"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Accesează ecranul împărțit cu aplicația actuală în dreapta"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Accesează ecranul împărțit cu aplicația actuală în stânga"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Folosește ecranul împărțit cu aplicația curentă în dreapta"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Folosește ecranul împărțit cu aplicația curentă în stânga"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Comută de la ecranul împărțit la ecranul complet"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Treci la aplicația din dreapta sau de mai jos cu ecranul împărțit"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Treci la aplicația din stânga sau de mai sus cu ecranul împărțit"</string>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 5b96618..a68f140 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Dezactivat"</item>
     <item msgid="5137565285664080143">"Activat"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Indisponibil"</item>
+    <item msgid="3079622119444911877">"Dezactivat"</item>
+    <item msgid="3028994095749238254">"Activat"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 5e47464..8f6d7a8 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель уведомлений"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Быстрые настройки"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Быстрые настройки и панель уведомлений."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блокировки."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Блокировка экрана"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заблокировано"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыть"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"полная тишина"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Все"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Использовать"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Подключено"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Отправка аудио"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сохранено"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"отключить"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активировать"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Включить завтра автоматически"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Bluetooth используется в сервисе \"Найти устройство\", таких функциях, как Быстрая отправка, и при определении местоположения устройства"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth будет включен завтра в 05:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Bluetooth используется в таких функциях и сервисах, как \"Быстрая отправка\" и \"Найти устройство\""</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth включится завтра утром"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Отправка аудио"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Включена отправка аудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудиоустройство"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнитура"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Запись неисправности"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Начать"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Остановить"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Отчет об ошибке"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"С чем связана проблема, с которой вы столкнулись?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Выберите тип проблемы"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запись экрана"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартная"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Средняя"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Высокая"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слуховые аппараты"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слуховые аппараты"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Подключить новое устройство"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Нажмите, чтобы подключить новое устройство"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблокировать микрофон устройства?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблокировать камеру устройства?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Быстрая зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виджеты на заблокированном экране"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Чтобы ознакомиться с руководством, проведите по экрану влево"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Настроить"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыть"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Открыть настройки"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Включить рабочие приложения?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Включить"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрыть виджеты на заблокированном экране"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виджеты на заблокированном экране"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"раскрывающееся меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
@@ -607,8 +614,8 @@
     <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"Контроль уровня шума"</string>
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Пространственное звучание"</string>
     <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Отключено"</string>
-    <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Без отслеживания"</string>
-    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"С отслеживанием"</string>
+    <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Без отсле­живания"</string>
+    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"С отсле­живанием"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"Нажмите, чтобы изменить режим звонка."</string>
     <string name="volume_ringer_hint_mute" msgid="4263821214125126614">"отключить звук"</string>
     <string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"включить звук"</string>
@@ -678,7 +685,7 @@
     <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;Статус:&lt;/b&gt; уровень важности понижен"</string>
     <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Появляется в верхней части уведомлений о сообщениях, а также в качестве фото профиля на заблокированном экране"</string>
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране."</string>
-    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Появляется в верхней части уведомлений о сообщениях, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
+    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Появляется в верхней части уведомлений о сообщениях, а также в виде фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает функции разговоров."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Переключение раскладки"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Удалить поисковый запрос"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Сочетания клавиш"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Быстрые клавиши"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Открыть Ассистента"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокировать экран"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Создать заметку"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Режим многозадачности"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Включить разделение экрана с текущим приложением справа"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Включить разделение экрана с текущим приложением слева"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Многозадачность"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Разделить экран и поместить это приложение справа"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Разделить экран и поместить это приложение слева"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Изменить режим разделения экрана на полноэкранный режим"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Перейти к приложению справа или внизу на разделенном экране"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Перейти к приложению слева или вверху на разделенном экране"</string>
@@ -783,7 +790,7 @@
     <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="6772492350416591448">"Открыть Ассистента"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Ассистент"</string>
     <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Браузер"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакты"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Эл. почта"</string>
@@ -997,11 +1004,11 @@
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Чтобы вернуть ее, нажмите на уведомление."</string>
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>: сочетание клавиш удалено."</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# сочетание клавиш удалено}one{# сочетание клавиш удалено}few{# сочетания клавиш удалено}many{# сочетаний клавиш удалено}other{# сочетания клавиш удалено}}"</string>
-    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перенести в левый верхний угол"</string>
-    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перенести в правый верхний угол"</string>
-    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Перенести в левый нижний угол"</string>
-    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Перенести в правый нижний угол"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Перенести к краю и скрыть"</string>
+    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Переместить в левый верхний угол"</string>
+    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Переместить в правый верхний угол"</string>
+    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Переместить в левый нижний угол"</string>
+    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Переместить в правый нижний угол"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Переместить к краю и скрыть"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Вернуть из-за края и показать"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Убрать"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"включить или отключить"</string>
@@ -1123,8 +1130,8 @@
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
     <string name="basic_status" msgid="2315371112182658176">"Открытый чат"</string>
-    <string name="select_conversation_title" msgid="6716364118095089519">"Виджеты чатов"</string>
-    <string name="select_conversation_text" msgid="3376048251434956013">"Нажмите на чат, чтобы добавить его на главный экран"</string>
+    <string name="select_conversation_title" msgid="6716364118095089519">"Виджеты разговоров"</string>
+    <string name="select_conversation_text" msgid="3376048251434956013">"Нажмите на разговор, чтобы добавить его на главный экран"</string>
     <string name="no_conversations_text" msgid="5354115541282395015">"Здесь появятся ваши недавние разговоры."</string>
     <string name="priority_conversations" msgid="3967482288896653039">"Важные разговоры"</string>
     <string name="recent_conversations" msgid="8531874684782574622">"Недавние разговоры"</string>
@@ -1291,7 +1298,7 @@
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Развернуть и показать параметры"</string>
     <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"Свернуть"</string>
     <string name="privacy_dialog_close_app_button" msgid="8006250171305878606">"Закрыть это приложение"</string>
-    <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" закрыто."</string>
+    <string name="privacy_dialog_close_app_message" msgid="1316408652526310985">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" закрыто"</string>
     <string name="privacy_dialog_manage_service" msgid="8320590856621823604">"Настроить сервис"</string>
     <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Настроить доступ"</string>
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Сейчас используется для телефонного звонка"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка клавиатуры"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Уровень %1$d из %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Управление домом"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Добавьте настройки умного дома на заставку"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Быстрый доступ к управлению домом через заставку"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index cdc4a98..592937c 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Выключено"</item>
     <item msgid="5137565285664080143">"Включено"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Недоступны"</item>
+    <item msgid="3079622119444911877">"Отключены"</item>
+    <item msgid="3028994095749238254">"Включены"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 5eea02c..afb5755 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"දැනුම්දීම් ආවරණය."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ක්ෂණික සැකසීම්."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ඉක්මන් සැකසීම් සහ දැනුම්දීම් ඡායිතය."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"අගුළු තිරය."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"අගුළු තිරය"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"කාර්යාල අගුලු තිරය"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"වසන්න"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"සම්පූර්ණ නිහඬතාව"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"සියල්ල බලන්න"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"බ්ලූටූත් භාවිතා කරන්න"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"සම්බන්ධිතයි"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ශ්‍රව්‍ය බෙදා ගැනීම"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"සුරැකිණි"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"විසන්ධි කරන්න"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"සක්‍රිය කරන්න"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"හෙට ස්වයංක්‍රීයව නැවත ක්‍රියාත්මක කරන්න"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ඉක්මන් බෙදා ගැනීම, මගේ උපාංගය සෙවීම, සහ උපාංග ස්ථානය වැනි විශේෂාංග බ්ලූටූත් භාවිත කරයි"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"බ්ලූටූත් හෙට පෙ.ව. 5ට ක්‍රියාත්මක වනු ඇත"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ඉක්මන් බෙදා ගැනීම සහ මගේ උපාංගය සෙවීම වැනි විශේෂාංග බ්ලූටූත් භාවිත කරයි"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"බ්ලූටූත් හෙට උදේ සක්‍රීය වෙයි"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ශ්‍රව්‍ය බෙදා ගැනීම"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ශ්‍රව්‍යය බෙදා ගැනීම"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ශ්‍රව්‍ය"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"හෙඩ්සෙටය"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"පටිගත කිරීමේ ගැටලුව"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"අරඹන්න"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"නවත්වන්න"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"දෝෂ වර්තාව"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ඔබේ උපාංග අත්දැකීමේ කුමන කොටසට බලපෑවේ ද?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"ගැටලු වර්ගය තෝරන්න"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"තිර පටිගත කිරීම"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"සම්මත"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"මධ්‍යම"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"ඉහළ"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"ශ්‍රවණ උපාංග"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ශ්‍රවණ උපාංග"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"නව උපාංගය යුගල කරන්න"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"නව උපාංගය යුගල කිරීමට ක්ලික් කරන්න"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"උපාංග මයික්‍රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"උපාංග කැමරාව අවහිර කිරීම ඉවත් කරන්නද?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"අගුළු තිරයෙහි විජට්"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"පොදු නිබන්ධනය ආරම්භ කිරීමට වමට ස්වයිප් කරන්න"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"අභිරුචිකරණය කරන්න"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"අස් කරන්න"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"සැකසීම් විවෘත කරන්න"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"කාර්ය යෙදුම් විරාම නොකරන්න ද?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"විරාම නොකරන්න"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"අගුළු තිරයෙහි විජට් වසන්න"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"අගුළු තිරයෙහි විජට්"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"පරිශීලක මාරුව"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"නිපතන මෙනුව"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"යතුරුපුවරු පිරිසැලසුම මාරු කරන්න"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"හෝ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"සෙවීම් විමසුම හිස් කරන්න"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"කෙටිමං"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"යතුරු පුවරු කෙටිමං"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"සහායක විවෘත කරන්න"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"තිරය අගුළු දමන්න"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"සටහනක් ගන්න"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"පද්ධති බහු කාර්ය"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHS වෙත වත්මන් යෙදුම සමග බෙදුම් තිරයට ඇතුළු වන්න"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHS වෙත වත්මන් යෙදුම සමග බෙදුම් තිරයට ඇතුළු වන්න"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"බහුකාර්ය"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"දකුණේ වත්මන් යෙදුම සමග බෙදීම් තිරය භාවිතා කරන්න"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"වම් පැත්තේ වත්මන් යෙදුම සමග බෙදීම් තිරය භාවිතා කරන්න"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"බෙදුම් තිරයේ සිට පූර්ණ තිරයට මාරු වන්න"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"බෙදුම් තිරය භාවිත කරන අතරතුර දකුණේ හෝ පහළින් ඇති යෙදුමට මාරු වන්න"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"බෙදුම් තිරය භාවිත කරන අතරතුර වමේ හෝ ඉහළ ඇති යෙදුමට මාරු වන්න"</string>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index e7e9034..681f3d5 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"ක්‍රියාවිරහිතයි"</item>
     <item msgid="5137565285664080143">"ක්‍රියාත්මකයි"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"නොමැත"</item>
+    <item msgid="3079622119444911877">"ක්‍රියාවිරහිතයි"</item>
+    <item msgid="3028994095749238254">"ක්‍රියාත්මකයි"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ea1a8f8..453dd44 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel upozornení."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rýchle nastavenia."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"úplné ticho"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Zobraziť všetko"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Použiť Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Pripojené"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zdieľanie zvuku"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uložené"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojiť"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovať"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Automaticky zajtra znova zapnúť"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funkcie, ako sú Quick Share, Nájdi moje zariadenie a poloha zariadenia, používajú Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth sa zapne zajtra o 5:00."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkcie ako Quick Share a Nájdi moje zariadenie používajú Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth sa zapne zajtra ráno"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Zdieľanie zvuku"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Zdieľa sa zvuk"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvuk"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Náhlavná súprava"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Problém s nahrávaním"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Začnite"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Zastavte"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Hlásenie chyby"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Čo v zariadení bolo ovplyvnené?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Vyberte typ problému"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rekordér obrazovky"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Stredný"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Vysoký"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Načúvacie zariadenia"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Načúvacie zariadenia"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Párovanie nového zariadenia"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zariadenie"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Chcete odblokovať mikrofón zariadenia?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Chcete odblokovať kameru zariadenia?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa rýchlo • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikácie na uzamknutej obrazovke"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Potiahnutím doľava spustite komunitný návod"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prispôsobiť"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavrieť"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Otvoriť nastavenia"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Zrušiť pozast. prac. aplikácií?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Zrušiť pozastavenie"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zavrieť miniaplikácie na uzamknutej obrazovke"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Miniaplikácie na uzamknutej obrazovke"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Prepnutie používateľa"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbaľovacia ponuka"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
@@ -679,7 +687,7 @@
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Zobrazuje sa ako bublina v hornej časti upozornení konverzácie a profilová fotka na uzamknutej obrazovke"</string>
     <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Zobrazuje sa v hornej časti upozornení konverzácie a ako profilová fotka na uzamknutej obrazovke, preruší režim bez vyrušení"</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje sa ako bublina v hornej časti upozornení konverzácie a profilová fotka na uzamknutej obrazovke, preruší režim bez vyrušení"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"Prioritné"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje funkcie konverzácie"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tieto upozornenia sa nedajú upraviť."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornenia na hovory sa nedajú upraviť."</string>
@@ -744,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Prepnúť rozloženie klávesnice"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"alebo"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Vymazať vyhľadávací dopyt"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skratky"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klávesové skratky"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hľadajte skratky"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenašli sa žiadne skratky"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systém"</string>
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vstup"</string>
-    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorenie apl."</string>
+    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorené aplikácie"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuálna aplik."</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Zobrazujú sa výsledky vyhľadávania"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Zobrazujú sa skratky systému"</string>
@@ -767,11 +775,11 @@
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvorenie zoznamu aplikácií"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvorenie nastavení"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvorenie Asistenta"</string>
-    <string name="group_system_lock_screen" msgid="7391191300363416543">"Zamknúť obrazovku"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknutie obrazovky"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Napísanie poznámky"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking systému"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Rozdelenie obrazovky s aktuálnou aplikáciou vpravo"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Rozdelenie obrazovky s aktuálnou aplikáciou vľavo"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Použite rozdelenú obrazovku s aktuálnou aplikáciou vpravo"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Použite rozdelenú obrazovku s aktuálnou aplikáciou vľavo"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Prepnutie rozdelenej obrazovky na celú"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prechod na aplikáciu vpravo alebo dole pri rozdelenej obrazovke"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prechod na aplikáciu vľavo alebo hore pri rozdelenej obrazovke"</string>
@@ -1268,7 +1276,7 @@
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Inštalovať pracovnú telefónnu aplikáciu"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Zrušiť"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Prispôsobiť uzamknutú obrazovku"</string>
-    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ak chcete prispôsobiť uzamknutú obrazovku, odomknite ju"</string>
+    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Uzamknutú obrazovku môžete prispôsobiť po odomknutí"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi‑Fi nie je k dispozícii"</string>
     <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokovaná"</string>
     <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofón sú blokované"</string>
@@ -1284,7 +1292,7 @@
     <string name="dismiss_dialog" msgid="2195508495854675882">"Zavrieť"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Obrazovka je pripojená"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofón a fotoaparát"</string>
-    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedávne využitie aplikácie"</string>
+    <string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedávne použitie aplikáciami"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Zobraziť nedávny prístup"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Hotovo"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Rozbaliť a zobraziť možnosti"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 514d2f9..27c376a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon z obvestili."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hitre nastavitve."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"popolna tišina"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Pokaži vse"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Uporabi Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvoka"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Shranjeno"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinitev povezave"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Samodejno znova vklopi jutri"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funkcije, kot so Hitro deljenje, Poišči mojo napravo in zaznavanje lokacije naprave, uporabljajo Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth se bo vklopil jutri ob 5. uri"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funkcije, kot sta Hitro deljenje in Poišči mojo napravo, uporabljajo Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth se bo vklopil jutri zjutraj"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Deljenje zvoka"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Poteka deljenje zvoka"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Zvok"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Slušalke z mikrofonom"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Snemanje težave"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Začetek"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ustavitev"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Poročilo o napakah"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Na kateri del izkušnje z napravo je to vplivalo?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Izberite vrsto težave"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snemanje zaslona"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardni"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Srednji"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Visok"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Slušni pripomočki"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni pripomočki"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Seznanitev nove naprave"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite za seznanitev nove naprave"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite odblokirati mikrofon v napravi?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite odblokirati fotoaparat v napravi?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hitro polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pripomočki na zaklenjenem zaslonu"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Povlecite levo, da zaženete vadnico za skupnost"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Opusti"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Odpri nastavitve"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Želite znova aktivirati delovne aplikacije?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Znova aktiviraj"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Zapiranje pripomočkov na zaklenjenem zaslonu"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Pripomočki na zaklenjenem zaslonu"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
@@ -745,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Preklop postavitve tipkovnice"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ali"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Čiščenje iskalne poizvedbe"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Bližnjice"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Bližnjične tipke"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Iskanje bližnjic"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ni najdenih bližnjic."</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vnos"</string>
-    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Odprte aplikacije"</string>
+    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Odpiranje aplikacij"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutna aplikacija"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Prikaz rezultatov iskanja"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Prikaz sistemskih bližnjic"</string>
@@ -770,14 +777,14 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Odpiranje Pomočnika"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaklepanje zaslona"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ustvarjanje zapiska"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistemska večopravilnost"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Vklop razdeljenega zaslona s trenutno aplikacijo na desni"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Vklop razdeljenega zaslona s trenutno aplikacijo na levi"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Večopravilnost"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Uporaba razdeljenega zaslona s trenutno aplikacijo na desni"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Uporaba razdeljenega zaslona s trenutno aplikacijo na levi"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Preklop iz razdeljenega zaslona v celozaslonski način"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Preklop na aplikacijo desno ali spodaj med uporabo razdeljenega zaslona"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Preklop na aplikacijo levo ali zgoraj med uporabo razdeljenega zaslona"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Pri razdeljenem zaslonu: medsebojna zamenjava aplikacij"</string>
-    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vnosna naprava"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vnos"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Preklop na naslednji jezik"</string>
     <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Preklop na prejšnji jezik"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"Dostop do emodžijev"</string>
@@ -1005,7 +1012,7 @@
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Premakni z roba in pokaži"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Odstrani"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"preklop"</string>
-    <string name="accessibility_floating_button_action_edit" msgid="1688227814600463987">"Urejanje"</string>
+    <string name="accessibility_floating_button_action_edit" msgid="1688227814600463987">"Uredi"</string>
     <string name="quick_controls_title" msgid="6839108006171302273">"Kontrolniki naprave"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"Izberite aplikacijo za dodajanje kontrolnikov"</string>
     <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>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Osvetlitev tipkovnice"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stopnja %1$d od %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrolniki za dom"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Hiter dostop do kontrol. za dom na ohranj. zaslona"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Hiter dostop do kontrolnikov za dom na ohranjevalniku zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index 9f9175e..5f60ffd 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Izklopljeno"</item>
     <item msgid="5137565285664080143">"Vklopljeno"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Ni na voljo"</item>
+    <item msgid="3079622119444911877">"Izklopljeno"</item>
+    <item msgid="3028994095749238254">"Vklopljeno"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index c13d76b..071eda7 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"heshtje e plotë"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Shiko të gjitha"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Përdor Bluetooth-in"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Lidhur"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ndarja e audios"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ruajtur"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"shkëput"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizo"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivizoje automatikisht nesër"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Veçoritë si \"Ndarja e shpejtë\", \"Gjej pajisjen time\" dhe vendndodhja e pajisjes përdorin Bluetooth-in"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth-i do të aktivizohet nesër në 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Veçoritë e tilla si \"Ndarja e shpejtë\" dhe \"Gjej pajisjen time\" përdorin Bluetooth-in"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth-i do të aktivizohet nesër në mëngjes"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Ndarja e audios"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audioja po ndahet"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> bateri"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Kufje me mikrofon"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Regjistro problemin"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Nis"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ndalo"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Raporti i defekteve në kod"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cila pjesë e përvojës me pajisjen është prekur?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Zgjidh llojin e problemit"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Regjistrim i ekranit"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Mesatar"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"I lartë"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Pajisje ndihmëse për dëgjimin"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Pajisjet e dëgjimit"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Çifto pajisje të re"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliko për të çiftuar një pajisje të re"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Të zhbllokohet mikrofoni i pajisjes?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Të zhbllokohet kamera e pajisjes?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet shpejt • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikacionet në ekranin e kyçjes"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Rrëshqit shpejt majtas për të filluar udhëzuesin e përbashkët"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizo"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hiq"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Hap cilësimet"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Hiq nga pauza apl. e punës?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Hiq nga pauza"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Mbyll miniaplikacionet në ekranin e kyçjes"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Miniaplikacionet në ekranin e kyçjes"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ndërro përdorues"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyja me tërheqje poshtë"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ndërro strukturën e tastierës"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ose"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Pastro pyetjen e kërkimit"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shkurtoret"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Shkurtoret e tastierës"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kërko shkurtoret"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nuk u gjet shkurtore"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistemi"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Hap \"Asistentin\""</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekrani i kyçjes"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Mbaj një shënim"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Kryerja e shumë detyrave nga sistemi"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Hyr në ekranin e ndarë me aplikacionin aktual në anën e djathtë"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Hyr në ekranin e ndarë me aplikacionin aktual në anën e majtë"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Kryerja e shumë detyrave"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Përdor ekranin e ndarë me aplikacionin aktual në të djathtë"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Përdor ekranin e ndarë me aplikacionin aktual në të majtë"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Kalo nga ekrani i ndarë në ekranin e plotë"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Kalo tek aplikacioni djathtas ose poshtë kur përdor ekranin e ndarë"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Kalo tek aplikacioni në të majtë ose sipër kur përdor ekranin e ndarë"</string>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index aa4832d..9b5032e 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Joaktive"</item>
     <item msgid="5137565285664080143">"Aktive"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Nuk ofrohen"</item>
+    <item msgid="3079622119444911877">"Joaktive"</item>
+    <item msgid="3028994095749238254">"Aktive"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index bc6642a..233e516 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Прозор са обавештењима."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брза подешавања."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Брза подешавања и трака са обавештењима."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Закључан екран"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Закључани екран"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Закључан екран за посао"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"потпуна тишина"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Прикажи све"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Повезано"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Дељење звука"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сачувано"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекините везу"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирајте"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Аутоматски поново укључи сутра"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Функције као што су Quick Share, Пронађи мој уређај и локација уређаја користе Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ће се укључити сутра у 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Функције као што су Quick Share и Пронађи мој уређај користе Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ће се укључити сутра ујутру"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Дељење звука"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Дели се звук"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудио"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Слушалице"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Евидентирајте проблем"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Покрени"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Заустави"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Извештај о грешци"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"На који део доживљаја на уређају је ово утицало?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Изаберите тип проблема"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Снимање екрана"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Средње"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Високо"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слушни апарати"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Упари нови уређај"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликните да бисте упарили нов уређај"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Желите да одблокирате микрофон уређаја?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Желите да одблокирате камеру уређаја?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на закључаном екрану"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Превуците улево да бисте започели заједнички водич"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Прилагодите"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Одбаци"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Отвори подешавања"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Укључити пословне апликације?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Поново активирај"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Затворите виџете на закључаном екрану"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Виџети на закључаном екрану"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Замени корисника"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падајући мени"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени распоред тастатуре"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Обриши упит за претрагу"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Пречице"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Тастерске пречице"</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>
@@ -766,12 +774,12 @@
     <string name="group_system_cycle_back" msgid="8194102916946802902">"Прегледај недавно коришћене апликације уназад"</string>
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Отвори листу апликација"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Отвори подешавања"</string>
-    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отвори помоћника"</string>
+    <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Отвори Помоћник"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Закључавање екрана"</string>
-    <string name="group_system_quick_memo" msgid="3764560265935722903">"Направите белешку"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Обављање више задатака система истовремено"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Покрени подељени екран за актуелну апликацију на десној страни"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Покрени подељени екран за актуелну апликацију на левој страни"</string>
+    <string name="group_system_quick_memo" msgid="3764560265935722903">"Направи белешку"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Обављање више задатака истовремено"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Користите подељени екран са актуелном апликацијом с десне стране"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Користите подељени екран са актуелном апликацијом с леве стране"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Пређи са подељеног екрана на цео екран"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Пређите у апликацију здесна или испод док користите подељени екран"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Пређите у апликацију слева или изнад док користите подељени екран"</string>
@@ -1295,9 +1303,9 @@
     <string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Управљај приступом"</string>
     <string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Користи телефонски позив"</string>
     <string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Недавно коришћено у телефонском позиву"</string>
-    <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
+    <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
     <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 15c370c..579f526 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meddelandepanel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snabbinställningar."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"helt tyst"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Se alla"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Använd Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ansluten"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ljuddelning"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sparad"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koppla från"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivera"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Aktivera automatiskt igen i morgon"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Funktioner som Snabbdelning, Hitta min enhet och enhetens plats använder Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth aktiveras i morgon kl. 5.00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Funktioner som Snabbdelning och Hitta min enhet använder Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth aktiveras i morgon bitti"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Ljuddelning"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Delar ljud"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ljud"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Registrera problem"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Starta"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stoppa"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Felrapport"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Vilken enhetsupplevelse påverkades?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Välj problemtyp"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Skärminspelning"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Medelhög"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Hög"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Hörhjälpmedel"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hörhjälpmedel"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Parkoppla en ny enhet"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicka för att parkoppla en ny enhet"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vill du återaktivera enhetens mikrofon?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vill du återaktivera enhetens kamera?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas snabbt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetar på låsskärmen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Svep åt vänster för att börja med gruppguiden"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassa"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorera"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Öppna inställningarna"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Vill du återuppta jobbappar?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Återuppta"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Stäng widgetar på låsskärmen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Widgetar på låsskärmen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Byt användare"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullgardinsmeny"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Byt tangentbordslayout"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Rensa sökfråga"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortkommandon"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Kortkommandon"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sök efter kortkommando"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Inga resultat"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Öppna assistenten"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skärmen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Anteckna"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systemets multikörning"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Öppna delad skärm med aktuell app till höger"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Öppna delad skärm med aktuell app till vänster"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multikörning"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Anänd delad skärm med den aktuella appen till höger"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Använd delad skärm med den aktuella appen till vänster"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Byt mellan delad skärm och helskärm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Byt till appen till vänster eller nedanför när du använder delad skärm"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Byt till appen till vänster eller ovanför när du använder delad skärm"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrundsbelysning för tangentbord"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Hemstyrning"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Kom snabbt åt hemstyrningen som en skärmsläckare"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Kom snabbt åt hemstyrningen via skärmsläckaren"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index 522538a..cf49f8d 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Av"</item>
     <item msgid="5137565285664080143">"På"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Inte tillgänglig"</item>
+    <item msgid="3079622119444911877">"Av"</item>
+    <item msgid="3028994095749238254">"På"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 41bac7b..bc7b016 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kivuli cha arifa."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mipangilio ya haraka."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"kimya kabisa"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Angalia vyote"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Tumia Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Imeunganishwa"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Kusikiliza Pamoja"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Imehifadhiwa"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ondoa"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"anza kutumia"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Iwashe tena kesho kiotomatiki"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Vipengele kama vile Kutuma Haraka, Tafuta Kifaa Changu na mahali kifaa kilipo hutumia Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth itawaka kesho saa 11 alfajiri"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Vipengele kama vile Kutuma Haraka na Tafuta Kifaa Changu hutumia Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth itawaka kesho asubuhi"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Kusikiliza Pamoja"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Mnasikiliza Pamoja"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Sauti"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Vifaa vya sauti"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Hitilafu ya Kurekodi"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Anza"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Simamisha"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Ripoti ya Hitilafu"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ni sehemu gani ya matumizi ya kifaa iliathiriwa?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Chagua aina ya tatizo"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rekodi ya skrini"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Wastani"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Juu"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Vifaa vya kusikilizia"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Vifaa vya kusikilizia"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Unganisha kifaa kipya"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Bofya ili uunganishe kifaa kipya"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Ungependa kuwacha kuzuia maikrofoni ya kifaa?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Ungependa kuacha kuzuia kamera ya kifaa?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Wijeti kwenye skrini iliyofungwa"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Telezesha kidole kushoto ili uanze mafunzo ya pamoja"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Weka mapendeleo"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Funga"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Fungua mipangilio"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Je, ungependa kuacha kusitisha programu za kazini?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Acha kusitisha"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Funga wijeti kwenye skrini iliyofungwa"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Wijeti kwenye skrini iliyofungwa"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Badili mtumiaji"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyu ya kuvuta chini"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
@@ -636,7 +644,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Kichanganuzi cha msimbo wa QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Kichanganuzi cha QR"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Inasasisha"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
@@ -719,7 +727,7 @@
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
-    <string name="keyboard_key_backspace" msgid="4095278312039628074">"Nafasinyuma"</string>
+    <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string>
     <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Cheza/Sitisha"</string>
     <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Simamisha"</string>
     <string name="keyboard_key_media_next" msgid="8502476691227914952">"Inayofuata"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Badili mkao wa kibodi"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"au"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Futa hoja ya utafutaji"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Njia za mkato"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Mikato ya Kibodi"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tafuta njia za mkato"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Hakuna njia za mkato zilizopatikana"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Mfumo"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Fungua programu ya Mratibu wa Google"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Funga skrini"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Andika dokezo"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Majukumu mengi ya mfumo"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Tumia programu kwenye skrini iliyogawanywa upande wa kulia"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Tumia programu kwenye skrini iliyogawanywa upande wa kushoto"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Majukumu mengi"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Tumia hali ya kugawa skrini na programu ya sasa iwe upande wa kulia"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Tumia hali ya kugawa skrini na programu ya sasa iwe upande wa kushoto"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Badilisha kutoka skrini iliyogawanywa utumie skrini nzima"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Badilisha ili uende kwenye programu iliyo kulia au chini unapotumia hali ya kugawa skrini"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Badilisha uende kwenye programu iliyo kushoto au juu unapotumia hali ya kugawa skrini"</string>
@@ -1261,7 +1269,7 @@
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Chaji ya betri imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Unganisha stylus yako kwenye chaja"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Chaji ya betri ya Stylus imepungua"</string>
-    <string name="video_camera" msgid="7654002575156149298">"Kamera ya kuchukulia video"</string>
+    <string name="video_camera" msgid="7654002575156149298">"Kamera ya video"</string>
     <string name="call_from_work_profile_title" msgid="5418253516453177114">"Huwezi kupiga simu kwa kutumia programu ya binafsi"</string>
     <string name="call_from_work_profile_text" msgid="2856337395968118274">"Shirika lako linakuruhusu upige simu ukitumia programu za kazini pekee"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string>
@@ -1303,6 +1311,6 @@
     <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Ilitumiwa hivi majuzi na <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Mwanga chini ya kibodi"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Kiwango cha %1$d kati ya %2$d"</string>
-    <string name="home_controls_dream_label" msgid="6567105701292324257">"Vidhibiti vya Vifaa Nyumbani"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Fikia haraka vidhibiti vya vifaa nyumbani kama taswira ya skrini"</string>
+    <string name="home_controls_dream_label" msgid="6567105701292324257">"Dhibiti Vifaa Nyumbani"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Fikia haraka vidhibiti vya vifaa nyumbani vikiwa taswira ya skrini"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 019dddc..b2c83dc 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"அறிவிப்பு விவரம்."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"உடனடி அமைப்பு."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"விரைவு அமைப்புகளும் அறிவிப்பு விவரமும்."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"லாக் ஸ்கிரீன்."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"பூட்டுத் திரை"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"பணி லாக் ஸ்கிரீன்"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"மூடு"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"முழு அமைதி"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"அனைத்தையும் காட்டு"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"புளூடூத்தைப் பயன்படுத்துதல்"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"இணைக்கப்பட்டது"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ஆடியோ பகிர்வு"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"சேமிக்கப்பட்டது"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"இணைப்பு நீக்கும்"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"செயல்படுத்தும்"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"நாளைக்குத் தானாகவே மீண்டும் இயக்கப்படும்"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"விரைவுப் பகிர்தல், Find My Device போன்ற அம்சங்களும் சாதன இருப்பிடமும் புளூடூத்தைப் பயன்படுத்துகின்றன"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"நாளை 5 AMக்கு புளூடூத் ஆன் ஆகும்"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"விரைவுப் பகிர்தல், Find My Device போன்ற அம்சங்கள் புளூடூத்தைப் பயன்படுத்துகின்றன"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"நாளை காலை புளூடூத் இயக்கப்படும்"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ஆடியோ பகிர்வு"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ஆடியோ பகிரப்படுகிறது"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> பேட்டரி"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ஆடியோ"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ஹெட்செட்"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"சிக்கலை ரெக்கார்டு செய்தல்"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"தொடங்குங்கள்"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"நிறுத்துங்கள்"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"பிழை அறிக்கை"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"சாதன அனுபவத்தின் எந்தப் பகுதி பாதிக்கப்பட்டது?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"சிக்கல் வகையைத் தேர்வுசெய்க"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"ஸ்கிரீன் ரெக்கார்டு"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"இயல்புநிலை"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"நடுத்தரம்"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"அதிகம்"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"செவித்துணைக் கருவிகள்"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"செவித்துணைக் கருவிகள்"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"புதிய சாதனத்தை இணை"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"புதிய சாதனத்தை இணைக்க கிளிக் செய்யலாம்"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"சாதனத்தின் மைக்ரோஃபோனுக்கான தடுப்பை நீக்கவா?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"சாதனத்தின் கேமராவுக்கான தடுப்பை நீக்கவா?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வேகமாகச் சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"பூட்டுத் திரையில் விட்ஜெட்கள்"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"சமூகப் பயிற்சியைத் தொடங்க இடதுபுறம் ஸ்வைப் செய்யுங்கள்"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"பிரத்தியேகமாக்குங்கள்"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"மூடுக"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"அமைப்புகளைத் திற"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"பணி ஆப்ஸை மீண்டும் இயக்கவா?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"மீண்டும் இயக்கு"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"பூட்டுத் திரையில் விட்ஜெட்களை மூடும்"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"பூட்டுத் திரையில் விட்ஜெட்கள்"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"பயனரை மாற்று"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"கீழ் இழுக்கும் மெனு"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா ஆப்ஸும் தரவும் நீக்கப்படும்."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"கீபோர்டு லே அவுட்டை மாற்று"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"அல்லது"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"தேடல் வினவலை அழிக்கும்"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ஷார்ட்கட்கள்"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"கீபோர்டு ஷார்ட்கட்கள்"</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>
@@ -770,12 +777,12 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistantடைத் திறத்தல்"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"பூட்டுத் திரை"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"குறிப்பெடுத்தல்"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"சிஸ்டம் பல வேலைகளைச் செய்தல்"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"வலதுபுறத்தில் தற்போதைய ஆப்ஸ் தோன்றுமாறு திரைப் பிரிப்பை அமைத்தல்"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"இடதுபுறத்தில் தற்போதைய ஆப்ஸ் தோன்றுமாறு திரைப் பிரிப்பை அமைத்தல்"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"பல வேலைகளைச் செய்தல்"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"தற்போது உள்ள ஆப்ஸுடன் வலதுபுறத்தில் திரைப் பிரிப்பைப் பயன்படுத்துதல்"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"தற்போது உள்ள ஆப்ஸுடன் இடதுபுறத்தில் திரைப் பிரிப்பைப் பயன்படுத்துதல்"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"திரைப் பிரிப்பு பயன்முறையிலிருந்து முழுத்திரைக்கு மாற்றுதல்"</string>
-    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது வலது/கீழ் உள்ள ஆப்ஸுக்கு மாறுங்கள்"</string>
-    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது இடது/மேலே உள்ள ஆப்ஸுக்கு மாறுங்கள்"</string>
+    <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது வலது/கீழ் உள்ள ஆப்ஸுக்கு மாறுதல்"</string>
+    <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது இடது/மேலே உள்ள ஆப்ஸுக்கு மாறுதல்"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"திரைப் பிரிப்பின்போது: ஓர் ஆப்ஸுக்குப் பதிலாக மற்றொன்றை மாற்றுதல்"</string>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"உள்ளீடு"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"அடுத்த மொழிக்கு மாற்றுதல்"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"கீபோர்டு பேக்லைட்"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"நிலை, %2$d இல் %1$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"ஹோம் கன்ட்ரோல்கள்"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"ஹோம் கன்ட்ரோல்களை ஸ்கிரீன் சேவராக விரைவாக அணுகலாம்"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"ஹோம் கன்ட்ரோல்களை ஸ்கிரீன் சேவராக அணுகலாம்"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index cacde5e..a3b9538 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"முடக்கப்பட்டுள்ளது"</item>
     <item msgid="5137565285664080143">"இயக்கப்பட்டுள்ளது"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"கிடைக்கவில்லை"</item>
+    <item msgid="3079622119444911877">"முடக்கப்பட்டுள்ளது"</item>
+    <item msgid="3028994095749238254">"இயக்கப்பட்டுள்ளது"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 1b3c5e2..5cd1341 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -118,7 +118,7 @@
     <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"స్క్రీన్, ఆడియో రికార్డింగ్ చేయబడుతున్నాయి"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"స్క్రీన్‌పై తాకే స్థానాలను చూపండి"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయి"</string>
-    <string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయి"</string>
+    <string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయండి"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"స్క్రీన్ రికార్డింగ్ సేవ్ చేయబడింది"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"చూడటానికి ట్యాప్ చేయండి"</string>
     <string name="screenrecord_save_error" msgid="5862648532560118815">"స్క్రీన్ రికార్డింగ్‌ను సేవ్ చేయడంలో ఎర్రర్ ఏర్పడింది"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"నోటిఫికేషన్ షేడ్."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"శీఘ్ర సెట్టింగ్‌లు."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"క్విక్ సెట్టింగ్‌లు, నోటిఫికేషన్ తెర."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"లాక్ స్క్రీన్."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"లాక్ స్క్రీన్"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"కార్యాలయ లాక్ స్క్రీన్"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"మూసివేస్తుంది"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"మొత్తం నిశ్శబ్దం"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"అన్నింటినీ చూడండి"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"బ్లూటూత్ వాడండి"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"కనెక్ట్ అయింది"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ఆడియో షేరింగ్"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ చేయబడింది"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"డిస్‌కనెక్ట్ చేయండి"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"యాక్టివేట్ చేయండి"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"రేపు మళ్లీ ఆటోమేటిక్‌గా ఆన్ చేస్తుంది"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"క్విక్ షేర్, Find My Device, పరికర లొకేషన్ వంటి ఫీచర్‌లు బ్లూటూత్‌ను ఉపయోగిస్తాయి"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"బ్లూటూత్ రేపు ఉదయం 5 గంటలకు ఆన్ అవుతుంది"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"క్విక్ షేర్, Find My Device వంటి ఫీచర్‌లు బ్లూటూత్‌ను ఉపయోగిస్తాయి"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"బ్లూటూత్ రేపు ఉదయం ఆన్ అవుతుంది"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"ఆడియో షేరింగ్"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"ఆడియోను షేర్ చేస్తున్నారు"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> బ్యాటరీ"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ఆడియో"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"హెడ్‌సెట్"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"సమస్యను రికార్డ్ చేయడం"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"ప్రారంభించండి"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"ఆపివేయండి"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"బగ్ రిపోర్ట్"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"మీ పరికర అనుభవంలో ఏ భాగం ప్రభావితమైంది?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"సమస్య రకాన్ని ఎంచుకోండి"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"స్క్రీన్ రికార్డ్"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"స్టాండర్డ్"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"మధ్యస్థం"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"అధికం"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"వినికిడి పరికరాలు"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"వినికిడి పరికరం"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"కొత్త పరికరాన్ని పెయిర్ చేయడానికి క్లిక్ చేయండి"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"పరికరం మైక్రోఫోన్‌ను అన్‌బ్లాక్ చేయమంటారా?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"పరికరంలోని కెమెరాను అన్‌బ్లాక్ చేయమంటారా?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"లాక్ స్క్రీన్‌లో విడ్జెట్‌లు"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"కమ్యూనల్ ట్యుటోరియల్‌ను ప్రారంభించడానికి ఎడమ వైపునకు స్వైప్ చేయండి"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"అనుకూలంగా మార్చండి"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"విస్మరించండి"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"సెట్టింగ్‌లను తెరవండి"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"వర్క్ యాప్స్ అన్‌పాజ్ చేయాలా?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"అన్‌పాజ్ చేయండి"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"లాక్ స్క్రీన్‌లో విడ్జెట్‌లను మూసివేయండి"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"లాక్ స్క్రీన్‌లో విడ్జెట్‌లు"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"పుల్‌డౌన్ మెనూ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్‌లోని అన్ని యాప్‌లు మరియు డేటా తొలగించబడతాయి."</string>
@@ -678,7 +685,7 @@
     <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;స్టేటస్:&lt;/b&gt; తక్కువ ర్యాంక్‌కు సర్దుబాటు చేయబడింది"</string>
     <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌గా చూపిస్తుంది"</string>
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌గా చూపిస్తుంది, బబుల్‌గా కనిపిస్తుంది"</string>
-    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌గా చూపిస్తుంది, \'అంతరాయం కలిగించవద్దు\'ను అంతరాయం కలిగిస్తుంది"</string>
+    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, అలాగే లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌ రూపంలో కనబడుతుంది. \'అంతరాయం కలిగించవద్దు\' మోడ్‌లో ఉన్నా దాన్ని అధిగమిస్తుంది"</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌గా చూపిస్తుంది, బబుల్‌గా కనిపిస్తుంది, \'అంతరాయం కలిగించవద్దు\'ను అంతరాయం కలిగిస్తుంది"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> సంభాషణ ఫీచర్‌లను సపోర్ట్ చేయదు"</string>
@@ -718,7 +725,7 @@
     <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"కుడి వైపు బాణం"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"మధ్య"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
-    <string name="keyboard_key_space" msgid="6980847564173394012">"అంతరం"</string>
+    <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
     <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string>
     <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"ప్లే చేయి/పాజ్ చేయి"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"కీబోర్డ్ లేఅవుట్‌ను మార్చండి"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"లేదా"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"సెర్చ్ క్వెరీని క్లియర్ చేయండి"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"షార్ట్‌కట్‌లు"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"కీబోర్డ్ షార్ట్‌కట్‌లు"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"అసిస్టెంట్‌ను తెరవండి"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"లాక్ స్క్రీన్"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"గమనికను రాయండి"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"సిస్టమ్ మల్టీ-టాస్కింగ్"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"RHSకు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఎంటర్ చేయండి"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"LHSకు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఎంటర్ చేయండి"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"మల్టీ-టాస్కింగ్"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"కుడివైపు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఉపయోగించండి"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ఎడమవైపు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఉపయోగించండి"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"స్ప్లిట్ స్క్రీన్‌ను ఫుల్ స్క్రీన్‌కు మార్చండి"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"స్ప్లిట్ స్క్రీన్ ఉపయోగిస్తున్నప్పుడు కుడి లేదా పైన యాప్‌నకు మారండి"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"స్ప్లిట్ స్క్రీన్ ఉపయోగిస్తున్నప్పుడు ఎడమ లేదా పైన యాప్‌నకు మారండి"</string>
@@ -802,7 +809,7 @@
     <string name="data_saver" msgid="3484013368530820763">"డేటా సేవర్"</string>
     <string name="accessibility_data_saver_on" msgid="5394743820189757731">"డేటా సేవర్ ఆన్‌లో ఉంది"</string>
     <string name="switch_bar_on" msgid="1770868129120096114">"ఆన్"</string>
-    <string name="switch_bar_off" msgid="5669805115416379556">"ఆఫ్ చేయి"</string>
+    <string name="switch_bar_off" msgid="5669805115416379556">"ఆఫ్"</string>
     <string name="tile_unavailable" msgid="3095879009136616920">"అందుబాటులో లేదు"</string>
     <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"మరింత తెలుసుకోండి"</string>
     <string name="nav_bar" msgid="4642708685386136807">"నావిగేషన్ బార్"</string>
@@ -997,10 +1004,10 @@
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"యాక్సెసిబిలిటీ బటన్‌ను చూడటానికి ట్యాప్ చేయండి"</string>
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> షార్ట్‌కట్ తీసివేయబడింది"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# షార్ట్‌కట్ తీసివేయబడింది}other{# షార్ట్‌కట్‌లు తీసివేయబడ్డాయి}}"</string>
-    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ఎగువ ఎడమ వైపునకు తరలించు"</string>
-    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ఎగువ కుడి వైపునకు తరలించు"</string>
-    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"దిగువ ఎడమ వైపునకు తరలించు"</string>
-    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"దిగువ కుడి వైపునకు తరలించు"</string>
+    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ఎగువున ఎడమ వైపునకు వెళ్లండి"</string>
+    <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ఎగువున కుడి వైపునకు వెళ్లండి"</string>
+    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"దిగువున ఎడమ వైపునకు వెళ్లండి"</string>
+    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"దిగువున కుడి వైపునకు వెళ్లండి"</string>
     <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"అంచుకు తరలించి దాచండి"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"అంచుని తరలించి చూపించు"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"తీసివేయండి"</string>
@@ -1066,7 +1073,7 @@
     <string name="controls_media_button_next" msgid="6662636627525947610">"తర్వాతి ట్రాక్"</string>
     <string name="controls_media_button_connecting" msgid="3138354625847598095">"కనెక్ట్ అవుతోంది"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ప్లే చేయండి"</string>
-    <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>ను తెరవండి"</string>
+    <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"\'<xliff:g id="APP_LABEL">%1$s</xliff:g>\'ను తెరవండి"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి <xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g>‌ను ప్లే చేయండి"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> నుండి <xliff:g id="SONG_NAME">%1$s</xliff:g>‌ను ప్లే చేయండి"</string>
     <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"మీ కోసం"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# యాప్ యాక్టివ్‌గా ఉంది}other{# యాప్‌లు యాక్టివ్‌గా ఉన్నాయి}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"కొత్త సమాచారం"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"యాక్టివ్‌గా ఉన్న యాప్‌లు"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"మీరు ఈ యాప్‌లను ఉపయోగించపోయినా కూడా అవి యాక్టివ్‌గా ఉండి, రన్ అవుతూ ఉంటాయి. దీని వల్ల వాటి ఫంక్షనాలిటీ మెరుగవుతుంది. అయితే ఇది బ్యాటరీ లైఫ్‌ను కూడా ప్రభావితం చేయవచ్చు."</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"మీరు ఈ యాప్‌లను ఉపయోగించపోయినా కూడా అవి యాక్టివ్‌గా ఉండి, రన్ అవుతూ ఉంటాయి. తద్వారా వాటి ఫంక్షనాలిటీ మెరుగవుతుంది. అయితే దీనివల్ల బ్యాటరీ లైఫ్ ప్రభావితం అయ్యే అవకాశం ఉంది."</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"ఆపివేయండి"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"ఆపివేయబడింది"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"పూర్తయింది"</string>
@@ -1240,7 +1247,7 @@
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"మీ పరికరంలో జరిగే దాన్ని పరికర లాగ్‌లు రికార్డ్ చేస్తాయి. సమస్యలను కనుగొని, పరిష్కరించడానికి యాప్‌లు ఈ లాగ్‌లను ఉపయోగిస్తాయి.\n\nకొన్ని లాగ్‌లలో గోప్యమైన సమాచారం ఉండవచ్చు, కాబట్టి మీరు విశ్వసించే యాప్‌లను మాత్రమే అన్ని పరికర లాగ్‌లను యాక్సెస్ చేయడానికి అనుమతించండి. \n\nఅన్ని పరికర లాగ్‌లను యాక్సెస్ చేయడానికి మీరు ఈ యాప్‌ను అనుమతించకపోతే, అది తన స్వంత లాగ్‌లను ఇప్పటికి యాక్సెస్ చేయగలదు. మీ పరికర తయారీదారు ఇప్పటికీ మీ పరికరంలో కొన్ని లాగ్‌లు లేదా సమాచారాన్ని యాక్సెస్ చేయగలరు."</string>
     <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"మరింత తెలుసుకోండి"</string>
     <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>‌లో మరింత తెలుసుకోండి"</string>
-    <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>‌ను తెరవండి"</string>
+    <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"\'<xliff:g id="APPNAME">%1$s</xliff:g>\'ను తెరవండి"</string>
     <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, యాప్ ఇన్‌స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string>
     <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, కనీసం ఒక కార్డ్ జోడించబడిందని నిర్ధారించుకోండి"</string>
     <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, యాప్ ఇన్‌స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"కీబోర్డ్ బ్యాక్‌లైట్"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dలో %1$dవ స్థాయి"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"హోమ్ కంట్రోల్స్"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"స్క్రీన్ సేవర్‌గా మీ హోమ్ కంట్రోల్స్‌ను త్వరగా యాక్సెస్ చేయండి"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"హోమ్ కంట్రోల్స్‌ను స్క్రీన్ సేవర్‌గా చేసి వేగంగా యాక్సెస్ పొందండి"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index a1ee29f..6584cdd 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"ఆఫ్‌లో ఉంది"</item>
     <item msgid="5137565285664080143">"ఆన్‌లో ఉంది"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"అందుబాటులో లేదు"</item>
+    <item msgid="3079622119444911877">"ఆఫ్‌లో ఉంది"</item>
+    <item msgid="3028994095749238254">"ఆన్‌లో ఉంది"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index e8d376d..544844d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -119,7 +119,7 @@
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"แสดงการแตะบนหน้าจอ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"หยุด"</string>
     <string name="screenrecord_share_label" msgid="5025590804030086930">"แชร์"</string>
-    <string name="screenrecord_save_title" msgid="1886652605520893850">"บันทึกการบันทึกหน้าจอแล้ว"</string>
+    <string name="screenrecord_save_title" msgid="1886652605520893850">"จัดเก็บการบันทึกหน้าจอไว้แล้ว"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"แตะเพื่อดู"</string>
     <string name="screenrecord_save_error" msgid="5862648532560118815">"เกิดข้อผิดพลาดในการบันทึกหน้าจอ"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"เกิดข้อผิดพลาดขณะเริ่มบันทึกหน้าจอ"</string>
@@ -145,7 +145,7 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"โทรศัพท์"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ตัวช่วยเสียง"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
-    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"แอปสแกนคิวอาร์โค้ด"</string>
+    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"ตัวสแกนคิวอาร์โค้ด"</string>
     <string name="accessibility_unlock_button" msgid="3613812140816244310">"ปลดล็อกแล้ว"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"อุปกรณ์ถูกล็อก"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"กำลังสแกนใบหน้า"</string>
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"หน้าต่างแจ้งเตือน"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"การตั้งค่าด่วน"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"การตั้งค่าด่วนและหน้าต่างแจ้งเตือน"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ล็อกหน้าจอ"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"หน้าจอล็อก"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"หน้าจอล็อกของโปรไฟล์งาน"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ปิด"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ปิดเสียงทั้งหมด"</string>
@@ -260,7 +260,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"ขณะนี้หน้าจอถูกล็อกให้วางในแนวนอน"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"ขณะนี้หน้าจอถูกล็อกให้วางในแนวตั้ง"</string>
     <string name="dessert_case" msgid="9104973640704357717">"ชั้นแสดงของหวาน"</string>
-    <string name="start_dreams" msgid="9131802557946276718">"โปรแกรมรักษาหน้าจอ"</string>
+    <string name="start_dreams" msgid="9131802557946276718">"ภาพพักหน้าจอ"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"อีเทอร์เน็ต"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ห้ามรบกวน"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"บลูทูธ"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"ดูทั้งหมด"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"ใช้บลูทูธ"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"เชื่อมต่อแล้ว"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"การแชร์เสียง"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"บันทึกแล้ว"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ยกเลิกการเชื่อมต่อ"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"เปิดใช้งาน"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"เปิดอีกครั้งโดยอัตโนมัติในวันพรุ่งนี้"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"ฟีเจอร์ต่างๆ เช่น Quick Share, หาอุปกรณ์ของฉัน และตำแหน่งของอุปกรณ์ ใช้บลูทูธ"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"บลูทูธจะเปิดพรุ่งนี้เวลา 05:00 น."</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ฟีเจอร์ต่างๆ เช่น Quick Share และหาอุปกรณ์ของฉัน ใช้บลูทูธ"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"บลูทูธจะเปิดพรุ่งนี้เช้า"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"การแชร์เสียง"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"กำลังแชร์เสียง"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"เสียง"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ชุดหูฟัง"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"ปัญหาการบันทึก"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"เริ่ม"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"หยุด"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"รายงานข้อบกพร่อง"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ประสบการณ์การใช้งานอุปกรณ์ส่วนใดที่ได้รับผลกระทบ"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"เลือกประเภทปัญหา"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"บันทึกหน้าจอ"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"มาตรฐาน"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"ปานกลาง"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"สูง"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"เครื่องช่วยฟัง"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"เครื่องช่วยฟัง"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"จับคู่อุปกรณ์ใหม่"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"คลิกเพื่อจับคู่อุปกรณ์ใหม่"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"เลิกบล็อกไมโครโฟนของอุปกรณ์ใช่ไหม"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"เลิกบล็อกกล้องของอุปกรณ์ใช่ไหม"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างเร็ว • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"วิดเจ็ตในหน้าจอล็อก"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ปัดไปทางซ้ายเพื่อเริ่มบทแนะนำส่วนกลาง"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ปรับแต่ง"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ปิด"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"เปิดการตั้งค่า"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ยกเลิกการหยุดแอปงานชั่วคราวไหม"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"ยกเลิกการหยุดชั่วคราว"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"ปิดวิดเจ็ตในหน้าจอล็อก"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"วิดเจ็ตในหน้าจอล็อก"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"สลับผู้ใช้"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"เมนูแบบเลื่อนลง"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
@@ -637,7 +644,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ปลดล็อกเพื่อใช้"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"การตั้งค่าหน้าจอล็อก"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"แอปสแกนคิวอาร์โค้ด"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"ตัวสแกนคิวอาร์โค้ด"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"กำลังอัปเดต"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
@@ -745,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"สลับรูปแบบแป้นพิมพ์"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"หรือ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ล้างคำค้นหา"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"แป้นพิมพ์ลัด"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"แป้นพิมพ์ลัด"</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_open_apps" msgid="1450959949739257562">"เปิดแอป"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"แอปปัจจุบัน"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"แสดงผลการค้นหา"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"แสดงแป้นพิมพ์ลัดสำหรับระบบ"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"เปิด Assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ล็อกหน้าจอ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"จดโน้ต"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"การทํางานหลายอย่างพร้อมกันของระบบ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"เข้าสู่โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านขวา"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"เข้าสู่โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านซ้าย"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"การทํางานหลายอย่างพร้อมกัน"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"ใช้โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านขวา"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"ใช้โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านซ้าย"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"เปลี่ยนจากโหมดแยกหน้าจอเป็นเต็มหน้าจอ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"เปลี่ยนไปใช้แอปทางด้านขวาหรือด้านล่างขณะใช้โหมดแยกหน้าจอ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"เปลี่ยนไปใช้แอปทางด้านซ้ายหรือด้านบนขณะใช้โหมดแยกหน้าจอ"</string>
@@ -1000,7 +1007,7 @@
     <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ย้ายไปด้านซ้ายบน"</string>
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ย้ายไปด้านขวาบน"</string>
     <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ย้ายไปด้านซ้ายล่าง"</string>
-    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ย้ายไปด้านขาวล่าง"</string>
+    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"ย้ายไปด้านขวาล่าง"</string>
     <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"ย้ายไปที่ขอบและซ่อน"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"ย้ายออกจากขอบและแสดง"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"นำออก"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{ทำงานอยู่ # แอป}other{ทำงานอยู่ # แอป}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"ข้อมูลใหม่"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"แอปที่ทำงานอยู่"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"แอปเหล่านี้กำลังทำงานแม้ว่าคุณจะไม่ได้ใช้งานอยู่ก็ตาม วิธีนี้ช่วยให้ฟังก์ชันการทำงานของแอปมีประสิทธิภาพมากขึ้น แต่ก็อาจส่งผลต่ออายุการใช้งานแบตเตอรี่ด้วย"</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"แอปเหล่านี้กำลังทำงานแม้ว่าคุณจะไม่ได้ใช้งานอยู่ก็ตาม วิธีนี้ช่วยให้ฟังก์ชันการทำงานของแอปมีประสิทธิภาพมากขึ้น แต่ก็อาจส่งผลต่อระยะเวลาการใช้งานแบตเตอรี่ด้วย"</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"หยุด"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"หยุดแล้ว"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"เสร็จ"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ไฟแบ็กไลต์ของแป้นพิมพ์"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"ระดับที่ %1$d จาก %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"ระบบควบคุมอุปกรณ์สมาร์ทโฮม"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"เข้าถึงระบบควบคุมอุปกรณ์สมาร์ทโฮมได้อย่างรวดเร็วที่การพักหน้าจอ"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"เข้าถึงระบบควบคุมอุปกรณ์สมาร์ทโฮมได้อย่างรวดเร็วผ่านภาพพักหน้าจอ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index d6351ce..8b7187b 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"ปิด"</item>
     <item msgid="5137565285664080143">"เปิด"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"ไม่พร้อมใช้งาน"</item>
+    <item msgid="3079622119444911877">"ปิด"</item>
+    <item msgid="3028994095749238254">"เปิด"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 54bb74b..13e4bf8 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mga mabilisang setting."</string>
     <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_lock_screen" msgid="409034672704273634">"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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ganap na katahimikan"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Tingnan lahat"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Gumamit ng Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Nakakonekta"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Pag-share ng Audio"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Na-save"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"idiskonekta"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"i-activate"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Awtomatikong i-on ulit bukas"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Guamgamit ng Bluetooth ang mga feature tulad ng Quick Share, Hanapin ang Aking Device, at lokasyon ng device"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Mag-o-on ang Bluetooth bukas nang 5 AM"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Gumagamit ng Bluetooth ang mga feature tulad ng Quick Share at Hanapin ang Aking Device"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Mag-o-on ang Bluetooth bukas ng umaga"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Pag-share ng Audio"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Ibinabahagi ang Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> na baterya"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Mag-record ng Isyu"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Magsimula"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Ihinto"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Ulat ng Bug"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Ano\'ng naapektuhang parte ng experience sa device?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Piliin ang uri ng isyu"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Pag-record ng screen"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Katamtaman"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Mataas"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Mga hearing device"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Mga hearing device"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Magpares ng bagong device"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"I-click para magpares ng bagong device"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"I-unblock ang mikropono ng device?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"I-unblock ang camera ng device?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabilis na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Mga widget sa lock screen"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Mag-swipe pakaliwa para simulan ang communal na tutorial"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"I-customize"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"I-dismiss"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Buksan ang mga setting"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"I-unpause ang mga work app?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"I-unpause"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Isara ang mga widget sa lock screen"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Mga widget sa lock screen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Magpalit ng layout ng keyboard"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"I-clear ang query sa paghahanap"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Mga Shortcut"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Mga Keyboard Shortcut"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Maghanap ng mga shortcut"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Walang nakitang shortcut"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Buksan ang assistant"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"I-lock ang screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Magtala"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking ng system"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Lumipat sa split screen nang nasa RHS ang kasalukuyang app"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Lumipat sa split screen nang nasa LHS ang kasalukuyang app"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Pag-multitask"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Gumamit ng split screen nang nasa kanan ang kasalukuyang app"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Gumamit ng split screen nang nasa kaliwa ang kasalukuyang app"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Lumipat sa full screen mula sa split screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Lumipat sa app sa kanan o ibaba habang ginagamit ang split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Lumipat sa app sa kaliwa o itaas habang ginagamit ang split screen"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 5364c83..30b6ce4 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildirim gölgesi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hızlı ayarlar."</string>
     <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_lock_screen" msgid="409034672704273634">"Kilit ekranı"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"İş profili kilit ekranı"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Kapat"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"tamamen sessiz"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Tümünü göster"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth\'u kullan"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Bağlandı"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ses Paylaşımı"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Kaydedildi"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"bağlantıyı kes"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"etkinleştir"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Yarın otomatik olarak tekrar aç"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Quick Share, Cihazımı Bul ve cihaz konumu gibi özellikler Bluetooth\'u kullanır"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth yarın saat 05:00\'te açılacak"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Quick Share ve Cihazımı Bul gibi özellikler Bluetooth\'u kullanır"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth yarın sabah açılacak"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Ses Paylaşımı"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Ses paylaşılıyor"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ses"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Mikrofonlu kulaklık"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Sorunu Kaydedin"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Başlayın"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Durdurun"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Hata Raporu"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Cihaz deneyiminiz ne şekilde etkilendi?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Sorun türünü seçin"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekran kaydedicisi"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Orta"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Yüksek"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"İşitme cihazları"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"İşitme cihazları"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yeni cihaz eşle"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz eşlemek için tıklayın"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonunun engellemesi kaldırılsın mı?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerasının engellemesi kaldırılsın mı?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hızlı şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilit ekranındaki widget\'lar"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ortak eğitimi başlatmak için sola kaydırın"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Özelleştir"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Kapat"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Ayarları açın"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"İş uygulamaları devam ettirilsin mi?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Devam ettir"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Kilit ekranındaki widget\'ları kapat"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Kilit ekranındaki widget\'lar"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"açılır menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klavye düzenini değiştir"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"veya"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Arama sorgusunu temizle"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kısayollar"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Klavye Kısayolları"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kısayol araması yapın"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Kısayol bulunamadı"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Asistan\'ı aç"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilit ekranı"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Not al"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistem çoklu görevi"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Mevcut uygulamayı sağ tarafa alarak bölünmüş ekrana geç"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Mevcut uygulamayı sol tarafa alarak bölünmüş ekrana geç"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Çoklu görev"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Sağdaki mevcut uygulamayla birlikte bölünmüş ekranı kullanın"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Soldaki mevcut uygulamayla birlikte bölünmüş ekranı kullanın"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Bölünmüş ekrandan tam ekrana geç"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bölünmüş ekran kullanırken sağdaki veya alttaki uygulamaya geçiş yapın"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bölünmüş ekran kullanırken soldaki veya üstteki uygulamaya geçiş yapın"</string>
@@ -1304,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klavye aydınlatması"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Seviye %1$d / %2$d"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev Kontrolleri"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"Ekran koruyucu olan ev kontrollerinize hızlıca erişin"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"Ekran koruyucu olarak ev kontrollerinize hızla erişin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index da1dfa4..e1d768e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель сповіщень."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Швидке налаштування."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Швидкі налаштування й панель сповіщень."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заблокований екран."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Заблокований екран"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Екран блокування завдання"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрити"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"без сигналів"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Показати всі"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Увімкнути Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Підключено"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Надсилання аудіо"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Збережено"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"від’єднати"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активувати"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Автоматично ввімкнути знову завтра"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Такі функції, як швидкий обмін, \"Знайти пристрій\" і визначення місцезнаходження пристрою, використовують Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth увімкнеться завтра о 5:00"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Такі функції, як швидкий обмін і \"Знайти пристрій\", використовують Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth увімкнеться завтра вранці"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Надсилання аудіо"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Надсилання аудіо"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> заряду акумулятора"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Аудіопристрій"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Гарнітура"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Запис помилки"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Почати"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Зупинити"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Звіт про помилку"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"На який аспект роботи пристрою вплинула проблема?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Виберіть тип проблеми"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Запис відео з екрана"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартний"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Середній"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Високий"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Слухові апарати"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слухові апарати"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Підключити новий пристрій"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Натисніть, щоб підключити новий пристрій"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Надати доступ до мікрофона?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Надати доступ до камери пристрою?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Швидке заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджети на заблокованому екрані"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Проведіть пальцем уліво, щоб відкрити спільний навчальний посібник"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Налаштувати"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрити"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Відкрити налаштування"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Увімкнути робочі додатки?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Увімкнути"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Закрити віджети на заблокованому екрані"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Віджети на заблокованому екрані"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Змінити користувача"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"спадне меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Змінити розкладку клавіатури"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"або"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Очистити пошуковий запит"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Швидкі команди"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Комбінації клавіш"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Відкрити додаток Асистент"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокувати екран"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Створити нотатку"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Багатозадачність системи"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Розділити екран із поточним додатком праворуч"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Розділити екран із поточним додатком ліворуч"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Багатозадачність"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Розділити екран і показувати поточний додаток праворуч"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Розділити екран і показувати поточний додаток ліворуч"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Перейти з розділення екрана на весь екран"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Під час розділення екрана перемикатися на додаток праворуч або внизу"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Під час розділення екрана перемикатися на додаток ліворуч або вгорі"</string>
@@ -784,7 +791,7 @@
     <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="6772492350416591448">"Асистент"</string>
-    <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Веб-переглядач"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Вебпереглядач"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакти"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Електронна пошта"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
@@ -903,7 +910,7 @@
     <string name="instant_apps_message" msgid="6112428971833011754">"Додаток відкрито без встановлення."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Додаток відкрито без встановлення. Торкніться, щоб дізнатися більше."</string>
     <string name="app_info" msgid="5153758994129963243">"Про додаток"</string>
-    <string name="go_to_web" msgid="636673528981366511">"Веб-переглядач"</string>
+    <string name="go_to_web" msgid="636673528981366511">"Вебпереглядач"</string>
     <string name="mobile_data" msgid="4564407557775397216">"Мобільний трафік"</string>
     <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index be779eb..61e62e4 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"Вимкнено"</item>
     <item msgid="5137565285664080143">"Увімкнено"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"Недоступно"</item>
+    <item msgid="3079622119444911877">"Вимкнено"</item>
+    <item msgid="3028994095749238254">"Увімкнено"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index fa4bd02..16b40bf 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"اطلاعاتی شیڈ۔"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"فوری ترتیبات۔"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"فوری ترتیبات اور اطلاعاتی شیڈ۔"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"مقفل اسکرین۔"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"مقفل اسکرین"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"دفتری مقفل اسکرین"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"بند کریں"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"مکمل خاموشی"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"سبھی دیکھیں"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"بلوٹوتھ استعمال کریں"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"منسلک ہے"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"آڈیو کا اشتراک"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ ہے"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"غیر منسلک کریں"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کریں"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"کل دوبارہ خودکار طور پر آن ہوگا"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"فوری اشتراک، میرا آلہ ڈھونڈیں، اور آلہ کے مقام جیسی خصوصیات بلوٹوتھ کا استعمال کرتی ہیں"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"بلوٹوتھ کل صبح 5 بجے آن ہو جائے گا"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"فوری اشتراک اور \'میرا آلہ ڈھونڈیں\' جیسی خصوصیات بلوٹوتھ کا استعمال کرتی ہیں"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"بلوٹوتھ کل صبح آن ہو جائے گا"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"آڈیو کا اشتراک"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"آڈیو کا اشتراک ہو رہا ہے"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> بیٹری"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"آڈیو"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"ہیڈ سیٹ"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"مسئلہ ریکارڈ کریں"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"شروع کریں"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"روکیں"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"بگ رپورٹ"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"آپ کے آلے کے تجربے کا کون سا حصہ متاثر ہوا؟"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"مسئلہ کی قسم منتخب کریں"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"اسکرین ریکارڈ"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"متوسط"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"زیادہ"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"سماعت کے آلات"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"سماعت کے آلات"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"نئے آلے کا جوڑا بنائیں"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"نئے آلے کا جوڑا بنانے کے لیے کلک کریں"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"آلے کا مائیکروفون غیر مسدود کریں؟"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"آلے کا کیمرا غیر مسدود کریں؟"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • تیزی سے چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"مقفل اسکرین پر ویجیٹس"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"کمیونل ٹیوٹوریل شروع کرنے کے لیے بائیں سوائپ کریں"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"حسب ضرورت بنائیں"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"برخاست کریں"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"ترتیبات کھولیں"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"ورک ایپس کو غیر موقوف کریں؟"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"غیر موقوف کریں"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"مقفل اسکرین پر ویجٹس بند کریں"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"مقفل اسکرین پر ویجیٹس"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"پل ڈاؤن مینیو"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"کی بورڈ لے آؤٹ سوئچ کریں"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"یا"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"تلاش کا استفسار صاف کریں"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"شارٹ کٹس"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"کی بورڈ شارٹ کٹس"</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>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"اسسٹنٹ کھولیں"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"مقفل اسکرین"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"نوٹ لیں"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"سسٹم ملٹی ٹاسکنگ"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"موجودہ ایپ کے ساتھ دائیں جانب اسپلٹ اسکرین انٹر کریں"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"موجودہ ایپ کے ساتھ بائیں جانب اسپلٹ اسکرین انٹر کریں"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ملٹی ٹاسکنگ"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"دائیں جانب موجودہ ایپ کے ساتھ اسپلٹ اسکرین کا استعمال کریں"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"بائیں جانب موجودہ ایپ کے ساتھ اسپلٹ اسکرین کا استعمال کریں"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"اسپلٹ اسکرین سے پوری سکرین پر سوئچ کریں"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"اسپلٹ اسکرین کا استعمال کرتے ہوئے دائیں یا نیچے ایپ پر سوئچ کریں"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"اسپلٹ اسکرین کا استعمال کرتے ہوئے بائیں یا اوپر ایپ پر سوئچ کریں"</string>
@@ -1123,7 +1131,7 @@
     <string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
     <string name="basic_status" msgid="2315371112182658176">"گفتگو کھولیں"</string>
     <string name="select_conversation_title" msgid="6716364118095089519">"گفتگو ویجیٹس"</string>
-    <string name="select_conversation_text" msgid="3376048251434956013">"اسے اپنے ہوم اسکرین پر شامل کرنے کے لیے گفتگو پر تھپتھپائیں"</string>
+    <string name="select_conversation_text" msgid="3376048251434956013">"اسے اپنی ہوم اسکرین پر شامل کرنے کے لیے گفتگو پر تھپتھپائیں"</string>
     <string name="no_conversations_text" msgid="5354115541282395015">"آپ کی حالیہ گفتگوئیں یہاں دکھائی دیں گی"</string>
     <string name="priority_conversations" msgid="3967482288896653039">"ترجیحی گفتگوئیں"</string>
     <string name="recent_conversations" msgid="8531874684782574622">"حالیہ گفتگوئیں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 195b044..76694df 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Xabarnoma soyasi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tezkor sozlamalar."</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tezkor sozlamalar va eslatma soyasi."</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Qulflash ekrani."</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Ekran qulfi"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ishchi ekran qulfi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Yopish"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"jimjitlik"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Hammasi"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ishlatish"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ulangan"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio ulashuvi"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saqlangan"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"uzish"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"faollashtirish"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Ertaga yana avtomatik yoqilsin"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Tezkor ulashuv, Qurilmamni top va qurilma geolokatsiyasi kabi funksiyalar Bluetooth ishlatadi"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth ertaga soat 5 da yoqiladi"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Tezkor ulashuv va Qurilmamni top kabi funksiyalar Bluetooth ishlatadi"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth ertaga ertalab yoqiladi"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Audio ulashuvi"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Audio ulashuvi yoniq"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Garnitura"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Yozib olishda xato"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Boshlash"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Toʻxtatish"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Xatoliklar hisoboti"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Qurilma ishlashining qaysi qismiga taʼsir qildi?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Muammo turini tanlang"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ekran yozuvi"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Oʻrtacha"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Yuqori"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Eshitish qurilmalari"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eshitish qurilmalari"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yangi qurilmani ulash"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yangi qurilmani ulash uchun bosing"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Qurilma mikrofoni blokdan chiqarilsinmi?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Qurilma kamerasi blokdan chiqarilsinmi?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Tez quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Ekran qulfidagi vidjetlar"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Qoʻllanma bilan tanishish uchun chapga suring"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Moslash"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Yopish"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Sozlamalarni ochish"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Ishga oid ilovalar qaytarilsinmi?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Davom ettirish"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Ekran qulfida vidjetlarni yopish"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Ekran qulfidagi vidjetlar"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Foydalanuvchini almashtirish"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"tortib tushiriladigan menyu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura terilmasini almashtirish"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"yoki"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Qidiruv soʻrovini tozalash"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tezkor tugmalar"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Tezkor tugmalar"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tezkor tugmalar qidiruvi"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tezkor tugmalar topilmadi"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Tizim"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistentni ochish"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekran qulfi"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Qayd yaratish"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Tizimdagi multi-vazifalik"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Oʻng tomondagi ajratilgan ekran rejimiga kirish"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Chap tomondagi ajratilgan ekran rejimiga kirish"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-vazifalilik"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Ekranni ajratib, joriy ilovani oʻngga joylash"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Ekranni ajratib, joriy ilovani chapga joylash"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Ajratilgan ekran rejimidan butun ekranga almashtirish"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ajratilgan ekranda oʻngdagi yoki pastdagi ilovaga almashish"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ajratilgan ekranda chapdagi yoki yuqoridagi ilovaga almashish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 469430b..41066f9 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -235,7 +235,7 @@
     <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>
     <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_lock_screen" msgid="409034672704273634">"Màn hình khoá"</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>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"hoàn toàn tắt tiếng"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Xem tất cả"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Bật Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Đã kết nối"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Chia sẻ âm thanh"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Đã lưu"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ngắt kết nối"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"kích hoạt"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Tự động bật lại vào ngày mai"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Các tính năng như Chia sẻ nhanh, Tìm thiết bị của tôi và dịch vụ vị trí trên thiết bị có sử dụng Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"Bluetooth sẽ bật vào ngày mai lúc 5 giờ sáng"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Các tính năng như Chia sẻ nhanh và Tìm thiết bị của tôi đều sử dụng Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth sẽ bật vào sáng mai"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Chia sẻ âm thanh"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Đang chia sẻ âm thanh"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> pin"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Âm thanh"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Tai nghe"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Ghi lại vấn đề"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Bắt đầu"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Dừng"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Báo cáo lỗi"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Bạn gặp loại vấn đề gì khi dùng thiết bị?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Chọn loại vấn đề"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Ghi màn hình"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Vừa"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Cao"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Thiết bị trợ thính"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Thiết bị trợ thính"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Ghép nối thiết bị mới"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Nhấp để ghép nối thiết bị mới"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Bỏ chặn micrô của thiết bị?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Bỏ chặn camera của thiết bị?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc nhanh • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Các tiện ích trên màn hình khoá"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Vuốt sang trái để bắt đầu xem hướng dẫn chung"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tuỳ chỉnh"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Đóng"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Mở phần Cài đặt"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Tiếp tục dùng ứng dụng công việc?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Tiếp tục dùng"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Đóng các tiện ích trên màn hình khoá"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Các tiện ích trên màn hình khoá"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Chuyển đổi người dùng"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"trình đơn kéo xuống"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Chuyển đổi bố cục bàn phím"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"hoặc"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Xoá cụm từ tìm kiếm"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lối tắt"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Phím tắt"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Lối tắt tìm kiếm"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Không tìm thấy lối tắt"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Hệ thống"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Mở Trợ lý"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Màn hình khoá"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Tạo ghi chú"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Xử lý đa nhiệm trong hệ thống"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Vào chế độ chia đôi màn hình, ứng dụng hiện tại ở màn hình bên phải"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Vào chế độ chia đôi màn hình, ứng dụng hiện tại ở màn hình bên trái"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Đa nhiệm"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Dùng tính năng chia đôi màn hình, trong đó ứng dụng hiện tại ở bên phải"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Dùng tính năng chia đôi màn hình, trong đó ứng dụng hiện tại ở bên trái"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Chuyển từ chế độ chia đôi màn hình sang chế độ toàn màn hình"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Chuyển sang ứng dụng bên phải hoặc ở dưới khi đang chia đôi màn hình"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Chuyển sang ứng dụng bên trái hoặc ở trên khi đang chia đôi màn hình"</string>
@@ -994,7 +1002,7 @@
     <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Huỷ"</string>
     <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Đã ẩn nút hỗ trợ tiếp cận"</string>
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Nhấn để hiện nút hỗ trợ tiếp cận"</string>
-    <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Đã xoá phím tắt dành cho <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+    <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Đã xoá lối tắt cho <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Đã xoá # lối tắt}other{Đã xoá # lối tắt}}"</string>
     <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Chuyển lên trên cùng bên trái"</string>
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Chuyển lên trên cùng bên phải"</string>
@@ -1283,7 +1291,7 @@
     <string name="mirror_display" msgid="2515262008898122928">"Phản chiếu màn hình"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Đóng"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Đã kết nối màn hình"</string>
-    <string name="privacy_dialog_title" msgid="7839968133469098311">"Micrô và máy ảnh"</string>
+    <string name="privacy_dialog_title" msgid="7839968133469098311">"Micrô và camera"</string>
     <string name="privacy_dialog_summary" msgid="2458769652125995409">"Hoạt động sử dụng gần đây của ứng dụng"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Xem hoạt động truy cập gần đây"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Xong"</string>
diff --git a/packages/SystemUI/res/values-xlarge-land/config.xml b/packages/SystemUI/res/values-xlarge-land/config.xml
new file mode 100644
index 0000000..5e4304e
--- /dev/null
+++ b/packages/SystemUI/res/values-xlarge-land/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <item name="shortcut_helper_screen_width_fraction"  format="float" type="dimen">0.8</item>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6765d1e..60a46d60 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知栏。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷设置。"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快捷设置和通知栏。"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"锁定屏幕。"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"锁定的屏幕"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作锁定屏幕"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"关闭"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"完全静音"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"查看全部"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"使用蓝牙"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已连接"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音频分享"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已保存"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"断开连接"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"启用"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明天自动重新开启"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"“快速分享”“查找我的设备”“设备位置信息”等功能会使用蓝牙"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"蓝牙将于明天早晨 5 点开启"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"快速分享、查找我的设备等功能会使用蓝牙"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"蓝牙将在明天早上开启"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"音频分享"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"正在分享音频"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> 的电量"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"音频"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"耳机"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"录制问题"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"开始"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"错误报告"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"设备体验的哪个方面受到影响?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"选择问题类型"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"屏幕录制"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"标准"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助听装置"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助听装置"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"与新设备配对"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"点击即可与新设备配对"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解锁设备麦克风吗?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解锁设备摄像头吗?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"锁定屏幕上的微件"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑动即可启动公共教程"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自定义"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"关闭"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"打开设置"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"是否为工作应用解除暂停状态?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"解除暂停"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"关闭锁定屏幕上的微件"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"锁定屏幕上的微件"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切换用户"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉菜单"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
@@ -686,7 +693,7 @@
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"无法修改来电通知。"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"您无法在此处配置这组通知"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"代理通知"</string>
-    <string name="notification_channel_dialog_title" msgid="6856514143093200019">"所有的<xliff:g id="APP_NAME">%1$s</xliff:g>通知"</string>
+    <string name="notification_channel_dialog_title" msgid="6856514143093200019">"所有“<xliff:g id="APP_NAME">%1$s</xliff:g>”通知"</string>
     <string name="see_more_title" msgid="7409317011708185729">"查看更多"</string>
     <string name="feedback_alerted" msgid="5192459808484271208">"系统已自动将此通知的重要性&lt;b&gt;提升为“默认”&lt;/b&gt;。"</string>
     <string name="feedback_silenced" msgid="9116540317466126457">"系统已自动将此通知的重要性&lt;b&gt;降低为“静音”&lt;/b&gt;。"</string>
@@ -745,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切换键盘布局"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜索查询"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快捷键"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"键盘快捷键"</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_open_apps" msgid="1450959949739257562">"打开应用"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"当前应用"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"目前显示的是搜索结果"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"目前显示的是系统快捷键"</string>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"打开 Google 助理"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"锁定屏幕"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"添加记事"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系统多任务处理"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"进入分屏模式,当前应用显示于右侧"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"进入分屏模式,当前应用显示于左侧"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多任务处理"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"使用分屏模式,并且当前应用位于右侧"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"使用分屏模式,并且当前应用位于左侧"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"从分屏模式切换为全屏"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分屏模式时,切换到右侧或下方的应用"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分屏模式时,切换到左侧或上方的应用"</string>
@@ -830,7 +837,7 @@
     <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_rearrange_tiles" msgid="2143204300089638620">"按住并拖动即可重新排列图块"</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>
     <string name="qs_edit" msgid="5583565172803472437">"编辑"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 个应用处于活动状态}other{# 个应用处于活动状态}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"新信息"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"已开启的应用"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"这些应用正在保持活跃运行状态,即使您没有在使用它们。这可以改进它们的功能,但可能会影响到电池续航时间。"</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"这些应用即使在闲置时仍处于活跃运行状态。应用的功能会因此提升,但可能会影响电池续航时间。"</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"已停止"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"完成"</string>
@@ -1285,7 +1292,7 @@
     <string name="dismiss_dialog" msgid="2195508495854675882">"关闭"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"显示屏已连接"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"麦克风和摄像头"</string>
-    <string name="privacy_dialog_summary" msgid="2458769652125995409">"近期应用对手机传感器的使用情况"</string>
+    <string name="privacy_dialog_summary" msgid="2458769652125995409">"近期被应用使用的情况"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期使用情况"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"完成"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"展开并显示选项"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
index a9a377a..9467b9b 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"已关闭"</item>
     <item msgid="5137565285664080143">"已开启"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"不可用"</item>
+    <item msgid="3079622119444911877">"关闭"</item>
+    <item msgid="3028994095749238254">"开启"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d4891d5..995129e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快速設定。"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"上鎖畫面。"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"上鎖畫面"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作螢幕鎖定"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"完全靜音"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"查看全部"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連接"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享功能"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"解除連結"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟動"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明天自動重新開啟"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"「快速共享」、「尋找我的裝置」和裝置位置等功能都會使用藍牙"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"藍牙將於明天上午 5 時開啟"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"「快速共享」和「尋找我的裝置」等功能都會使用藍牙"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"藍牙將於明天上午開啟"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"音訊分享功能"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"正在分享音訊"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"音訊"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"耳機"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"錄製問題"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"開始"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"錯誤報告"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"哪些裝置使用體驗受影響?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"選取問題類型"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"螢幕錄影"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助聽器"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"配對新裝置"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"㩒一下就可以配對新裝置"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"上鎖畫面上的小工具"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可開始共用教學課程"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"開啟設定"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"要取消暫停工作應用程式嗎?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"取消暫停"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"關閉上鎖畫面上的小工具"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"上鎖畫面上的小工具"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
@@ -745,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜尋查詢"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"鍵盤快速鍵"</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>
@@ -770,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"開啟「Google 助理」"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"上鎖畫面"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"寫筆記"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系統多工處理"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"進入分割螢幕模式,並將目前的應用程式顯示在右側"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"進入分割螢幕模式,並將目前的應用程式顯示在左側"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多工處理"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"使用分割螢幕,並在右側顯示目前使用的應用程式"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"使用分割螢幕,並在左側顯示目前使用的應用程式"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"將分割螢幕切換為全螢幕"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分割螢幕時,切換至右邊或下方的應用程式"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分割螢幕時,切換至左邊或上方的應用程式"</string>
@@ -1305,5 +1312,5 @@
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"智能家居"</string>
-    <string name="home_controls_dream_description" msgid="4644150952104035789">"在螢幕保護程式畫面上快速存取家居控制功能"</string>
+    <string name="home_controls_dream_description" msgid="4644150952104035789">"在螢幕保護程式畫面上控制智能家居"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
index f0ccd9e..cca7ac4 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"關閉"</item>
     <item msgid="5137565285664080143">"開啟"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"無法使用"</item>
+    <item msgid="3079622119444911877">"關閉"</item>
+    <item msgid="3028994095749238254">"開啟"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index bc59988..d18f828 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷設定。"</string>
     <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
-    <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"螢幕鎖定。"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"螢幕鎖定"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work 螢幕鎖定"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"完全靜音"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"查看全部"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連線"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"取消連結"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟用"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"明天自動重新開啟"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"藍牙會用於快速分享、「尋找我的裝置」,以及裝置位置資訊等功能"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"藍牙將在明天早上 5 點開啟"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"「快速分享」和「尋找我的裝置」等功能需要藍牙"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"藍牙會在明天早上開啟"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"音訊分享"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"正在分享音訊"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"音訊"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"耳機"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"記錄問題"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"開始"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"停止"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"錯誤報告"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"哪些裝置使用體驗受到影響?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"選取問題類型"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"螢幕錄影"</string>
@@ -363,13 +367,11 @@
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string>
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"中"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"高"</string>
-    <!-- no translation found for quick_settings_hearing_devices_label (7277170419679404129) -->
-    <skip />
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"助聽器"</string>
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"助聽器"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"配對新裝置"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"按一下即可配對新裝置"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string>
@@ -436,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"螢幕鎖定畫面上的小工具"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可啟動通用教學課程"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string>
@@ -454,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"開啟設定"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"要解除工作應用程式的暫停狀態嗎?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"取消暫停"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"關閉螢幕鎖定畫面上的小工具"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"螢幕鎖定畫面上的小工具"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會刪除。"</string>
@@ -678,7 +685,7 @@
     <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;狀態:&lt;/b&gt;已調降順序"</string>
     <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片)"</string>
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"以對話框的形式顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片)"</string>
-    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片),並會中斷「零打擾」模式"</string>
+    <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"顯示在對話通知頂端 (螢幕鎖定時會顯示個人資料相片),並會中斷「零打擾」模式"</string>
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以對話框的形式顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片),並會中斷「零打擾」模式"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
@@ -745,12 +752,12 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜尋查詢"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"鍵盤快速鍵"</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_open_apps" msgid="1450959949739257562">"開啟應用程式"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"目前的應用程式"</string>
     <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"顯示搜尋結果"</string>
     <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"顯示系統快速鍵"</string>
@@ -763,16 +770,16 @@
     <string name="group_system_go_back" msgid="2730322046244918816">"返回"</string>
     <string name="group_system_access_home_screen" msgid="4130366993484706483">"前往主畫面"</string>
     <string name="group_system_overview_open_apps" msgid="5659958952937994104">"查看最近開啟的應用程式"</string>
-    <string name="group_system_cycle_forward" msgid="5478663965957647805">"前往最近開啟的應用程式"</string>
-    <string name="group_system_cycle_back" msgid="8194102916946802902">"返回最近開啟的應用程式"</string>
+    <string name="group_system_cycle_forward" msgid="5478663965957647805">"向前循環切換最近開啟的應用程式"</string>
+    <string name="group_system_cycle_back" msgid="8194102916946802902">"向後循環切換最近開啟的應用程式"</string>
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"開啟應用程式清單"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"開啟設定"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"開啟 Google 助理"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"螢幕鎖定"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"新增記事"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系統多工處理"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"進入分割畫面模式,並將目前的應用程式顯示於右側"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"進入分割畫面模式,並將目前的應用程式顯示於左側"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多工處理"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"使用分割畫面,並在右側顯示目前使用的應用程式"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"使用分割畫面,並在左側顯示目前使用的應用程式"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"從分割畫面切換到完整畫面"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分割畫面時,切換到右邊或上方的應用程式"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分割畫面時,切換到左邊或上方的應用程式"</string>
@@ -868,7 +875,7 @@
     <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"編輯設定順序。"</string>
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源鍵選單"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
-    <string name="tuner_lock_screen" msgid="2267383813241144544">"鎖定畫面"</string>
+    <string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string>
     <string name="finder_active" msgid="7907846989716941952">"即使這支手機關機,仍可透過「尋找我的裝置」找出手機位置"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"關機中…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看處理步驟"</string>
@@ -1194,7 +1201,7 @@
     <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# 個應用程式正在運作}other{# 個應用程式正在運作}}"</string>
     <string name="fgs_dot_content_description" msgid="2865071539464777240">"新資訊"</string>
     <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"運作中的應用程式"</string>
-    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"即使你並未使用,這些應用程式仍會持續運作。這可提升應用程式效能,但也可能影響電池續航力。"</string>
+    <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"這些應用程式會在沒有使用的情況下持續運作。應用程式的實用度會因此提升,但也可能影響電池續航力。"</string>
     <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string>
     <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"已停止"</string>
     <string name="clipboard_edit_text_done" msgid="4551887727694022409">"完成"</string>
@@ -1285,7 +1292,7 @@
     <string name="dismiss_dialog" msgid="2195508495854675882">"關閉"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"螢幕已連結"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"麥克風和相機"</string>
-    <string name="privacy_dialog_summary" msgid="2458769652125995409">"最近曾使用感應器的應用程式"</string>
+    <string name="privacy_dialog_summary" msgid="2458769652125995409">"最近使用的應用程式"</string>
     <string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期存取記錄"</string>
     <string name="privacy_dialog_done_button" msgid="4504330708531434263">"完成"</string>
     <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"展開並顯示選項"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
index 2c474f6..4cc5804 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -186,7 +186,9 @@
     <item msgid="2478289035899842865">"關閉"</item>
     <item msgid="5137565285664080143">"開啟"</item>
   </string-array>
-    <!-- no translation found for tile_states_hearing_devices:0 (1235334096484287173) -->
-    <!-- no translation found for tile_states_hearing_devices:1 (3079622119444911877) -->
-    <!-- no translation found for tile_states_hearing_devices:2 (3028994095749238254) -->
+  <string-array name="tile_states_hearing_devices">
+    <item msgid="1235334096484287173">"無法使用"</item>
+    <item msgid="3079622119444911877">"已關閉"</item>
+    <item msgid="3028994095749238254">"已開啟"</item>
+  </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 780fe94..a5caa3d 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -235,7 +235,7 @@
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Umthunzi wesaziso."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Izilingiselelo ezisheshayo."</string>
     <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_lock_screen" msgid="409034672704273634">"Khiya isikrini"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ukukhiya isikrini somsebenzi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Vala"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ukuthula okuphelele"</string>
@@ -260,7 +260,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Isikrini sikhiyelwe ngomumo we-landscape."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Isikrini sikhiyelwe ngomumo we-portrait."</string>
     <string name="dessert_case" msgid="9104973640704357717">"Isikhwama soswidi"</string>
-    <string name="start_dreams" msgid="9131802557946276718">"Isigcini sihenqo"</string>
+    <string name="start_dreams" msgid="9131802557946276718">"Isigciniskrini"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"I-Ethernet"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ungaphazamisi"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"I-Bluetooth"</string>
@@ -270,12 +270,15 @@
     <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Buka konke"</string>
     <string name="turn_on_bluetooth" msgid="5681370462180289071">"Sebenzisa i-Bluetooth"</string>
     <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ixhunyiwe"</string>
+    <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ukwabelana Ngokuqoshiwe"</string>
     <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ilondoloziwe"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"nqamula"</string>
     <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"yenza kusebenze"</string>
     <string name="turn_on_bluetooth_auto_tomorrow" msgid="414836329962473906">"Vula ngokuzenzekela futhi kusasa"</string>
-    <string name="turn_on_bluetooth_auto_info_disabled" msgid="8267380591344023327">"Izakhi ezifana Nokwabelana Ngokushesha, okuthi Thola Idivayisi Yami, kanye nendawo yedivayisi zisebenzisa i-Bluetooth"</string>
-    <string name="turn_on_bluetooth_auto_info_enabled" msgid="4802071533678400330">"I-Bluetooth izovulwa kusasa ngo-5 AM"</string>
+    <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Izakhi ezifana nokuthi Ukwabelana Ngokushesha kanye nokuthi Thola Idivayisi Yami zisebenzisa i-Bluetooth"</string>
+    <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"I-Bluetooth izovuleka kusasa ekuseni"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button" msgid="4499275822759907822">"Ukwabelana Ngokuqoshiwe"</string>
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="8626191139359072540">"Ukwabelana Ngomsindo"</string>
     <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ibhethri"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Umsindo"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ihedisethi"</string>
@@ -350,6 +353,7 @@
     <string name="qs_record_issue_label" msgid="8166290137285529059">"Rekhoda Inkinga"</string>
     <string name="qs_record_issue_start" msgid="2979831312582567056">"Qala"</string>
     <string name="qs_record_issue_stop" msgid="3531747965741982657">"Misa"</string>
+    <string name="qs_record_issue_bug_report" msgid="8229031766918650079">"Umbiko Wesiphazamisi"</string>
     <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"Kuthinteke yiphi ingxenye yokusebenzisa idivayisi?"</string>
     <string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"Khetha uhlobo lwenkinga"</string>
     <string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Irekhodi lesikrini"</string>
@@ -364,11 +368,10 @@
     <string name="quick_settings_contrast_medium" msgid="5158352575583902566">"Okuphakathi"</string>
     <string name="quick_settings_contrast_high" msgid="656049259587494499">"Phezulu"</string>
     <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"Izinsizakuzwa"</string>
-    <!-- no translation found for quick_settings_hearing_devices_dialog_title (9004774017688484981) -->
-    <skip />
-    <!-- no translation found for quick_settings_pair_hearing_devices (5987105102207447322) -->
-    <skip />
-    <!-- no translation found for accessibility_hearing_device_pair_new_device (8440082580186130090) -->
+    <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Izinsizakuzwa"</string>
+    <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Bhangqa idivayisi entsha"</string>
+    <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Chofoza ukuze ubhangqe idivayisi entsha"</string>
+    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
     <skip />
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vulela imakrofoni yedivayisi?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vulela ikhamera yedivayisi?"</string>
@@ -435,6 +438,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja ngokushesha • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Amawijethi ekukhiyeni isikrini"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swayiphela kwesokunxele ukuze uqale okokufundisa komphakathi"</string>
     <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Enza ngendlela oyifisayo"</string>
     <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chitha"</string>
@@ -453,6 +457,10 @@
     <string name="button_text_to_open_settings" msgid="1987729256950941628">"Vula amasethingi"</string>
     <string name="work_mode_off_title" msgid="5794818421357835873">"Susa ukumisa ama-app omsebenzi?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Qhubekisa"</string>
+    <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Vala amawijethi ekukhiyeni isikrini"</string>
+    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
+    <skip />
+    <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Amawijethi ekukhiyeni isikrini"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"imenyu yokudonsela phansi"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wonke ama-app nedatha kulesi sikhathi azosuswa."</string>
@@ -744,7 +752,7 @@
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Shintsha isakhiwo sekhibhodi"</string>
     <string name="keyboard_shortcut_join" msgid="3578314570034512676">"noma"</string>
     <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Sula umbuzo wosesho"</string>
-    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Izinqamuleli"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Izinqamuleli Zekhibhodi"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sesha izinqamuleli"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Azikho izinqamuleli ezitholakele"</string>
     <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Isistimu"</string>
@@ -769,9 +777,9 @@
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Vula umsizi"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Khiya isikrini"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Thatha inothi"</string>
-    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Ukwenza imisebenzi eminingi yesistimu"</string>
-    <string name="system_multitasking_rhs" msgid="2454557648974553729">"Faka ukuhlukanisa isikrini nge-app yamanje kuya ku-RHS"</string>
-    <string name="system_multitasking_lhs" msgid="3516599774920979402">"Faka ukuhlukanisa isikrini nge-app yamanje kuya ku-LHS"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Ukwenza imisebenzi eminingi"</string>
+    <string name="system_multitasking_rhs" msgid="8714224917276297810">"Sebenzisa isikrini esihlukanisayo nge-app yamanje kwesokudla"</string>
+    <string name="system_multitasking_lhs" msgid="8402954791206308783">"Sebenzisa isikrini sokuhlukanisa nge-app yamanje kwesokunxele"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Shintsha usuka ekuhlukaniseni isikrini uye kusikrini esigcwele"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Shintshela ku-app ngakwesokudla noma ngezansi ngenkathi usebenzisa uhlukanisa isikrini"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Shintshela ku-app ngakwesokunxele noma ngaphezulu ngenkathi usebenzisa ukuhlukanisa isikrini"</string>
@@ -996,11 +1004,11 @@
     <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Thepha ukuze ubonise inkinobho yokufinyeleleka."</string>
     <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Isinqamuleli se-<xliff:g id="FEATURE_NAME">%s</xliff:g> sisusiwe"</string>
     <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Isinqamuleli esingu-# sisusiwe}one{Izinqamuleli ezingu-# zisusiwe}other{Izinqamuleli ezingu-# zisusiwe}}"</string>
-    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Hamba phezulu kwesokunxele"</string>
+    <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Hambisa phezulu kwesokunxele"</string>
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Hamba phezulu ngakwesokudla"</string>
-    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Hamba phansi ngakwesokunxele"</string>
-    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Hamba phansi ngakwesokudla"</string>
-    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Hamba onqenqemeni ufihle"</string>
+    <string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Hambisa phansi ngakwesokunxele"</string>
+    <string name="accessibility_floating_button_action_move_bottom_right" msgid="6196904373227440500">"Hambisa phansi ngakwesokudla"</string>
+    <string name="accessibility_floating_button_action_move_to_edge_and_hide_to_half" msgid="662401168245782658">"Hambisa onqenqemeni ufihle"</string>
     <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"Phuma onqenqemeni ubonise"</string>
     <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"Susa"</string>
     <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"guqula"</string>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 2bab3cb..5d45607 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -28,8 +28,6 @@
 
     <color name="red">#FFCC0000</color>
     <color name="tv_volume_dialog_circle">#08FFFFFF</color>
-    <color name="tv_volume_dialog_seek_thumb_focus_ring">#1AFFFFFF</color>
-    <color name="tv_volume_dialog_seek_thumb_shadow">#40000000</color>
     <color name="tv_volume_dialog_seek_bar_background">#A03C4043</color>
     <color name="tv_volume_dialog_seek_bar_fill">#FFF8F9FA</color>
     <color name="tv_volume_dialog_accent">#FFDADCE0</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index a6f6d4d..19273ec 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -70,6 +70,9 @@
     <!-- The number of rows in the QuickSettings -->
     <integer name="quick_settings_max_rows">4</integer>
 
+    <!-- The number of columns in the infinite grid QuickSettings -->
+    <integer name="quick_settings_infinite_grid_num_columns">4</integer>
+
     <!-- Override column number for quick settings.
     For now, this value has effect only when flag lockscreen.enable_landscape is enabled.
     TODO (b/293252410) - change this comment/resource when flag is enabled -->
@@ -116,9 +119,6 @@
          The syntax is setting-name:spec. If the tile is a TileService, the spec should be specified
          as custom(package/class). Relative class name is supported. -->
     <string-array name="config_quickSettingsAutoAdd" translatable="false">
-        <item>accessibility_display_daltonizer_enabled:color_correction</item>
-        <item>accessibility_display_inversion_enabled:inversion</item>
-        <item>one_handed_mode_enabled:onehanded</item>
         <item>accessibility_font_scaling_has_been_changed:font_scaling</item>
     </string-array>
 
@@ -1010,4 +1010,7 @@
 
     <!-- Whether volume panel should use the large screen layout or not -->
     <bool name="volume_panel_is_large_screen">false</bool>
+
+    <!-- The width of the shortcut helper container, as a fraction of the screen's width. -->
+    <item name="shortcut_helper_screen_width_fraction" format="float" type="dimen">1.0</item>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f2288a4..df57f2a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -310,6 +310,9 @@
     <!-- Radius for notifications corners without adjacent notifications -->
     <dimen name="notification_corner_radius">28dp</dimen>
 
+    <!-- Stroke width for notifications focus state overlay, see id/notification_focus_outline -->
+    <dimen name="notification_focus_stroke_width">3dp</dimen>
+
     <!-- Distance over which notification corner animations run, near the shelf while scrolling. -->
     <dimen name="notification_corner_animation_distance">48dp</dimen>
 
@@ -613,7 +616,7 @@
     <dimen name="volume_panel_slice_vertical_padding">8dp</dimen>
     <dimen name="volume_panel_slice_horizontal_padding">24dp</dimen>
 
-    <dimen name="volume_panel_corner_radius">52dp</dimen>
+    <dimen name="volume_panel_corner_radius">28dp</dimen>
 
     <!-- Size of each item in the ringer selector drawer. -->
     <dimen name="volume_ringer_drawer_item_size">42dp</dimen>
@@ -978,6 +981,7 @@
     <dimen name="assist_disclosure_shadow_thickness">1.5dp</dimen>
 
     <!-- Keyboard shortcuts helper -->
+    <dimen name="ksh_container_horizontal_margin">32dp</dimen>
     <dimen name="ksh_layout_width">@dimen/match_parent</dimen>
     <dimen name="ksh_item_text_size">14sp</dimen>
     <dimen name="ksh_item_padding">0dp</dimen>
@@ -985,6 +989,11 @@
     <dimen name="ksh_icon_scaled_size">18dp</dimen>
     <dimen name="ksh_key_view_padding_vertical">4dp</dimen>
     <dimen name="ksh_key_view_padding_horizontal">12dp</dimen>
+    <dimen name="ksh_button_corner_radius">12dp</dimen>
+    <dimen name="ksh_dialog_top_corner_radius">28dp</dimen>
+    <dimen name="ksh_search_box_corner_radius">100dp</dimen>
+    <dimen name="ksh_app_item_minimum_height">64dp</dimen>
+    <dimen name="ksh_category_separator_margin">16dp</dimen>
 
     <!-- The size of corner radius of the arrow in the onboarding toast. -->
     <dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen>
@@ -1085,7 +1094,7 @@
     <dimen name="remote_input_history_extra_height">60dp</dimen>
 
     <!-- Biometric Dialog values -->
-    <dimen name="biometric_dialog_face_icon_size">64dp</dimen>
+    <dimen name="biometric_dialog_face_icon_size">54dp</dimen>
     <dimen name="biometric_dialog_fingerprint_icon_width">80dp</dimen>
     <dimen name="biometric_dialog_fingerprint_icon_height">80dp</dimen>
     <dimen name="biometric_dialog_button_negative_max_width">160dp</dimen>
@@ -1103,6 +1112,22 @@
     <dimen name="biometric_dialog_width">240dp</dimen>
     <dimen name="biometric_dialog_height">240dp</dimen>
 
+    <!-- Dimensions for biometric prompt panel padding -->
+    <dimen name="biometric_prompt_small_horizontal_guideline_padding">344dp</dimen>
+    <dimen name="biometric_prompt_udfps_horizontal_guideline_padding">114dp</dimen>
+    <dimen name="biometric_prompt_udfps_mid_guideline_padding">409dp</dimen>
+    <dimen name="biometric_prompt_medium_horizontal_guideline_padding">640dp</dimen>
+    <dimen name="biometric_prompt_medium_mid_guideline_padding">330dp</dimen>
+
+    <!-- Dimensions for biometric prompt icon padding -->
+    <dimen name="biometric_prompt_portrait_small_bottom_padding">60dp</dimen>
+    <dimen name="biometric_prompt_portrait_medium_bottom_padding">160dp</dimen>
+    <dimen name="biometric_prompt_portrait_large_screen_bottom_padding">176dp</dimen>
+    <dimen name="biometric_prompt_landscape_small_bottom_padding">192dp</dimen>
+    <dimen name="biometric_prompt_landscape_small_horizontal_padding">145dp</dimen>
+    <dimen name="biometric_prompt_landscape_medium_bottom_padding">148dp</dimen>
+    <dimen name="biometric_prompt_landscape_medium_horizontal_padding">125dp</dimen>
+
     <!-- Dimensions for biometric prompt custom content view. -->
     <dimen name="biometric_prompt_logo_size">32dp</dimen>
     <dimen name="biometric_prompt_content_corner_radius">28dp</dimen>
@@ -1740,6 +1765,14 @@
     <!-- The height of the main scroll view in bluetooth dialog with auto on toggle. -->
     <dimen name="bluetooth_dialog_scroll_view_min_height_with_auto_on">350dp</dimen>
 
+    <!-- Hearing devices dialog related dimensions -->
+    <dimen name="hearing_devices_preset_spinner_height">72dp</dimen>
+    <dimen name="hearing_devices_preset_spinner_margin">24dp</dimen>
+    <dimen name="hearing_devices_preset_spinner_text_padding_start">20dp</dimen>
+    <dimen name="hearing_devices_preset_spinner_text_padding_end">80dp</dimen>
+    <dimen name="hearing_devices_preset_spinner_arrow_size">24dp</dimen>
+    <dimen name="hearing_devices_preset_spinner_background_radius">28dp</dimen>
+
     <!-- Height percentage of the parent container occupied by the communal view -->
     <item name="communal_source_height_percentage" format="float" type="dimen">0.80</item>
 
@@ -1979,4 +2012,7 @@
 
     <!-- SliceView grid gutter for ANC Slice -->
     <dimen name="abc_slice_grid_gutter">0dp</dimen>
+    <!-- SliceView icon size -->
+    <dimen name="abc_slice_big_pic_min_height">64dp</dimen>
+    <dimen name="abc_slice_big_pic_max_height">64dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 035cfdc..b993a5a 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -186,6 +186,8 @@
     <item type="id" name="action_remove_menu"/>
     <item type="id" name="action_edit"/>
 
+    <item type="id" name="accessibility_action_open_communal_hub"/>
+
     <!-- rounded corner view id -->
     <item type="id" name="rounded_corner_top_left"/>
     <item type="id" name="rounded_corner_top_right"/>
@@ -231,6 +233,7 @@
     <item type="id" name="smart_space_barrier_bottom" />
     <item type="id" name="small_clock_guideline_top" />
     <item type="id" name="weather_clock_date_and_icons_barrier_bottom" />
+    <item type="id" name="accessibility_actions_view" />
 
     <!-- Privacy dialog -->
     <item type="id" name="privacy_dialog_close_app_button" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2446039..b8e78a4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -568,7 +568,7 @@
     <!-- Content description for the split notification shade that also includes QS (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_qs_notification_shade">Quick settings and Notification shade.</string>
     <!-- Content description for the lock screen (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_lock_screen">Lock screen.</string>
+    <string name="accessibility_desc_lock_screen">Lock screen</string>
     <!-- Content description for the work profile lock screen. This prevents work profile apps from being used, but personal apps can be used as normal (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_work_lock">Work lock screen</string>
     <!-- Content description for the close button in the zen mode panel introduction message. [CHAR LIMIT=NONE] -->
@@ -678,6 +678,8 @@
     <string name="turn_on_bluetooth">Use Bluetooth</string>
     <!-- QuickSettings: Bluetooth dialog device connected default summary [CHAR LIMIT=NONE]-->
     <string name="quick_settings_bluetooth_device_connected">Connected</string>
+    <!-- QuickSettings: Bluetooth dialog device in audio sharing default summary [CHAR LIMIT=50]-->
+    <string name="quick_settings_bluetooth_device_audio_sharing">Audio Sharing</string>
     <!-- QuickSettings: Bluetooth dialog device saved default summary [CHAR LIMIT=NONE]-->
     <string name="quick_settings_bluetooth_device_saved">Saved</string>
     <!-- QuickSettings: Accessibility label to disconnect a device [CHAR LIMIT=NONE]-->
@@ -687,9 +689,13 @@
     <!-- QuickSettings: Bluetooth auto on tomorrow [CHAR LIMIT=NONE]-->
     <string name="turn_on_bluetooth_auto_tomorrow">Automatically turn on again tomorrow</string>
     <!-- QuickSettings: Bluetooth auto on info text when disabled [CHAR LIMIT=NONE]-->
-    <string name="turn_on_bluetooth_auto_info_disabled">Features like Quick Share, Find My Device, and device location use Bluetooth</string>
+    <string name="turn_on_bluetooth_auto_info_disabled">Features like Quick Share and Find My Device use Bluetooth</string>
     <!-- QuickSettings: Bluetooth auto on info text when enabled [CHAR LIMIT=NONE]-->
-    <string name="turn_on_bluetooth_auto_info_enabled">Bluetooth will turn on tomorrow at 5 AM</string>
+    <string name="turn_on_bluetooth_auto_info_enabled">Bluetooth will turn on tomorrow morning</string>
+    <!-- QuickSettings: Bluetooth dialog audio sharing button text [CHAR LIMIT=50]-->
+    <string name="quick_settings_bluetooth_audio_sharing_button">Audio Sharing</string>
+    <!-- QuickSettings: Bluetooth dialog audio sharing button text when sharing audio [CHAR LIMIT=50]-->
+    <string name="quick_settings_bluetooth_audio_sharing_button_sharing">Sharing Audio</string>
 
     <!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
     <string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string>
@@ -872,6 +878,8 @@
     <string name="qs_record_issue_start">Start</string>
     <!-- QuickSettings: Text to prompt the user to stop an ongoing recording [CHAR LIMIT=20] -->
     <string name="qs_record_issue_stop">Stop</string>
+    <!-- QuickSettings: Should user take a bugreport or only share trace files [CHAR LIMIT=20] -->
+    <string name="qs_record_issue_bug_report">Bug Report</string>
 
     <!-- QuickSettings: Issue Type Drop down options in Record Issue Start Dialog [CHAR LIMIT=50] -->
     <string name="qs_record_issue_dropdown_header">What part of your device experience was affected?</string>
@@ -908,6 +916,8 @@
     <string name="quick_settings_pair_hearing_devices">Pair new device</string>
     <!-- QuickSettings: Content description of the hearing devices dialog pair new device [CHAR LIMIT=NONE] -->
     <string name="accessibility_hearing_device_pair_new_device">Click to pair new device</string>
+    <!-- Message when selecting hearing aids presets failed. [CHAR LIMIT=NONE] -->
+    <string name="hearing_devices_presets_error">Couldn\'t update preset</string>
 
     <!--- Title of dialog triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=150] -->
     <string name="sensor_privacy_start_use_mic_dialog_title">Unblock device microphone?</string>
@@ -1126,6 +1136,9 @@
     <!-- Indication on the keyguard that is shown when the device is dock charging. [CHAR LIMIT=80]-->
     <string name="keyguard_indication_charging_time_dock"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Charging • Full in <xliff:g id="charging_time_left" example="4 hr, 2 min">%1$s</xliff:g></string>
 
+    <!-- Label for accessibility action that shows widgets on lock screen on click. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_open_communal_hub">Widgets on lock screen</string>
+
     <!-- Indicator on keyguard to start the communal tutorial. [CHAR LIMIT=100] -->
     <string name="communal_tutorial_indicator_text">Swipe left to start the communal tutorial</string>
 
@@ -1163,6 +1176,12 @@
     <string name="work_mode_off_title">Unpause work apps?</string>
     <!-- Title for button to unpause on work profile. [CHAR LIMIT=NONE] -->
     <string name="work_mode_turn_on">Unpause</string>
+    <!-- Label for accessibility action that navigates to lock screen. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_label_close_communal_hub">Close widgets on lock screen</string>
+    <!-- Label for accessibility action that navigates to edit mode. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_label_edit_widgets">Customize widgets</string>
+    <!-- Accessibility content description for communal hub. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_content_description_for_communal_hub">Widgets on lock screen</string>
 
     <!-- Related to user switcher --><skip/>
 
@@ -1699,6 +1718,11 @@
     <!-- Accessibility label for available satellite connection [CHAR LIMIT=NONE] -->
     <string name="accessibility_status_bar_satellite_available">Satellite, connection available</string>
 
+    <!-- Text displayed indicating that the user is connected to a satellite signal. -->
+    <string name="satellite_connected_carrier_text">Connected to satellite</string>
+    <!-- Text displayed indicating that the user is not connected to a satellite signal. -->
+    <string name="satellite_not_connected_carrier_text">Not connected to satellite</string>
+
     <!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
     <string name="accessibility_managed_profile">Work profile</string>
 
@@ -1971,8 +1995,8 @@
     <!-- Content description for the clear search button in shortcut search list. [CHAR LIMIT=NONE] -->
     <string name="keyboard_shortcut_clear_text">Clear search query</string>
     <!-- The title for keyboard shortcut search list [CHAR LIMIT=25] -->
-    <string name="keyboard_shortcut_search_list_title">Shortcuts</string>
-    <!-- The hint for keyboard shortcut search list [CHAR LIMIT=25] -->
+    <string name="keyboard_shortcut_search_list_title">Keyboard Shortcuts</string>
+    <!-- The hint for keyboard shortcut search list [CHAR LIMIT=50] -->
     <string name="keyboard_shortcut_search_list_hint">Search shortcuts</string>
     <!-- The description for no shortcuts results [CHAR LIMIT=25] -->
     <string name="keyboard_shortcut_search_list_no_result">No shortcuts found</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index e825f32..3d57111 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -230,6 +230,8 @@
     <style name="TextAppearance.AuthCredential.Indicator" parent="TextAppearance.Material3.BodyMedium">
         <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
         <item name="android:marqueeRepeatLimit">marquee_forever</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">marquee</item>
     </style>
 
     <style name="TextAppearance.AuthCredential.Error">
@@ -366,6 +368,21 @@
         <item name="android:layout_height">wrap_content</item>
     </style>
 
+    <style name="KeyboardShortcutHelper" parent="@android:style/Theme.DeviceDefault.Settings">
+        <!-- Needed to be able to use BottomSheetDragHandleView -->
+        <item name="android:windowActionBar">false</item>
+        <item name="bottomSheetDragHandleStyle">@style/KeyboardShortcutHelper.BottomSheet.DragHandle</item>
+    </style>
+
+    <style name="KeyboardShortcutHelper.BottomSheet.DragHandle" parent="Widget.Material3.BottomSheet.DragHandle">
+        <item name="tint">?androidprv:attr/materialColorOutlineVariant</item>
+    </style>
+
+    <style name="KeyboardShortcutHelper.BottomSheetDialogAnimation">
+        <item name="android:windowEnterAnimation">@anim/slide_in_up</item>
+        <item name="android:windowExitAnimation">@anim/slide_out_down</item>
+    </style>
+
     <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer" />
 
     <style name="Animation" />
@@ -1598,14 +1615,15 @@
         <item name="android:layout_marginEnd">12dp</item>
         <item name="android:paddingLeft">24dp</item>
         <item name="android:paddingRight">24dp</item>
-        <item name="android:minHeight">40dp</item>
+        <item name="android:minHeight">36dp</item>
+        <item name="android:minWidth">120dp</item>
         <item name="android:stateListAnimator">@*android:anim/flat_button_state_list_anim_material</item>
         <item name="android:pointerIcon">arrow</item>
     </style>
 
     <style name="ShortcutHorizontalDivider">
-        <item name="android:layout_width">120dp</item>
-        <item name="android:layout_height">1dp</item>
+        <item name="android:layout_width">132dp</item>
+        <item name="android:layout_height">2dp</item>
         <item name="android:layout_gravity">center_horizontal</item>
         <item name="android:background">?android:attr/dividerHorizontal</item>
     </style>
@@ -1636,4 +1654,28 @@
     <style name="Theme.SystemUI.Dialog.StickyKeys" parent="@style/Theme.SystemUI.Dialog">
         <item name="android:colorBackground">@color/transparent</item>
     </style>
+
+    <style name="ShortcutHelperAnimation" parent="@android:style/Animation.Activity">
+        <item name="android:activityOpenEnterAnimation">@anim/shortcut_helper_launch_anim</item>
+        <item name="android:taskOpenEnterAnimation">@anim/shortcut_helper_launch_anim</item>
+        <item name="android:activityOpenExitAnimation">@anim/shortcut_helper_close_anim</item>
+        <item name="android:taskOpenExitAnimation">@anim/shortcut_helper_close_anim</item>
+    </style>
+
+    <style name="ShortcutHelperThemeCommon" parent="@style/Theme.Material3.DynamicColors.DayNight">
+        <item name="android:windowAnimationStyle">@style/ShortcutHelperAnimation</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:backgroundDimEnabled">true</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
+        <item name="android:windowLayoutInDisplayCutoutMode">always</item>
+        <item name="enableEdgeToEdge">true</item>
+    </style>
+
+    <style name="ShortcutHelperTheme" parent="@style/ShortcutHelperThemeCommon">
+        <item name="android:windowLightNavigationBar">true</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt
index a2b1198..f07dce5 100644
--- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt
+++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/FingerprintSensor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.biometrics.shared.model
 
+import android.graphics.Rect
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 
 /** Fingerprint sensor property. Represents [FingerprintSensorPropertiesInternal]. */
@@ -23,12 +24,23 @@
     val sensorId: Int,
     val sensorStrength: SensorStrength,
     val maxEnrollmentsPerUser: Int,
-    val sensorType: FingerprintSensorType
+    val sensorType: FingerprintSensorType,
+    val sensorBounds: Rect,
+    val sensorRadius: Int,
 )
 
 /** Convert [FingerprintSensorPropertiesInternal] to corresponding [FingerprintSensor] */
 fun FingerprintSensorPropertiesInternal.toFingerprintSensor(): FingerprintSensor {
     val sensorStrength: SensorStrength = this.sensorStrength.toSensorStrength()
     val sensorType: FingerprintSensorType = this.sensorType.toSensorType()
-    return FingerprintSensor(this.sensorId, sensorStrength, this.maxEnrollmentsPerUser, sensorType)
+    val sensorBounds: Rect = this.location.rect
+    val sensorRadius = this.location.sensorRadius
+    return FingerprintSensor(
+        this.sensorId,
+        sensorStrength,
+        this.maxEnrollmentsPerUser,
+        sensorType,
+        sensorBounds,
+        sensorRadius,
+    )
 }
diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
index 476daac..0f3d285 100644
--- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
+++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
@@ -33,3 +33,10 @@
         SensorProperties.STRENGTH_STRONG -> SensorStrength.STRONG
         else -> throw IllegalArgumentException("Invalid SensorStrength value: $this")
     }
+/** Convert [SensorStrength] to corresponding [Int] */
+fun SensorStrength.toInt(): Int =
+    when (this) {
+        SensorStrength.CONVENIENCE -> SensorProperties.STRENGTH_CONVENIENCE
+        SensorStrength.WEAK -> SensorProperties.STRENGTH_WEAK
+        SensorStrength.STRONG -> SensorProperties.STRENGTH_STRONG
+    }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 4632914..dcc1440 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -155,5 +155,10 @@
      */
     oneway void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) = 54;
 
-    // Next id = 55
+    /**
+     * Set the override value for home button long press duration in ms and slop multiplier.
+     */
+    oneway void setOverrideHomeButtonLongPress(long duration, float slopMultiplier) = 55;
+
+    // Next id = 56
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
index 7af9917..d0d5caf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
@@ -32,6 +32,8 @@
 import dagger.Provides
 import java.util.concurrent.Executor
 import javax.inject.Singleton
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.android.asCoroutineDispatcher
 
 /**
  * Dagger module with system-only dependencies for the unfold animation. The code that is used to
@@ -78,6 +80,13 @@
         @Provides
         @UnfoldBg
         @Singleton
+        fun unfoldBgDispatcher(@UnfoldBg handler: Handler): CoroutineDispatcher {
+            return handler.asCoroutineDispatcher("@UnfoldBg Dispatcher")
+        }
+
+        @Provides
+        @UnfoldBg
+        @Singleton
         fun provideBgLooper(): Looper {
             return HandlerThread("UnfoldBg", Process.THREAD_PRIORITY_FOREGROUND)
                 .apply { start() }
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
index b9b8fbe..5647b0b 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
@@ -19,6 +19,7 @@
 import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ACTIVE_DATA_SUB_CHANGED;
 import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ON_TELEPHONY_CAPABLE;
 import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_REFRESH_CARRIER_INFO;
+import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_SATELLITE_CHANGED;
 import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_SIM_ERROR_STATE_CHANGED;
 
 import android.content.Context;
@@ -43,17 +44,22 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.res.R;
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel;
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository;
 import com.android.systemui.telephony.TelephonyListenerManager;
+import com.android.systemui.util.kotlin.JavaAdapter;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.inject.Inject;
 
+import kotlinx.coroutines.Job;
+
 /**
  * Controller that generates text including the carrier names and/or the status of all the SIM
  * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
@@ -77,10 +83,17 @@
     protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final CarrierTextManagerLogger mLogger;
     private final WifiRepository mWifiRepository;
+    private final DeviceBasedSatelliteViewModel mDeviceBasedSatelliteViewModel;
+    private final JavaAdapter mJavaAdapter;
     private final boolean[] mSimErrorState;
     private final int mSimSlotsNumber;
     @Nullable // Check for nullability before dispatching
     private CarrierTextCallback mCarrierTextCallback;
+    @Nullable
+    private Job mSatelliteConnectionJob;
+
+    @Nullable private String mSatelliteCarrierText;
+
     private final Context mContext;
     private final TelephonyManager mTelephonyManager;
     private final CharSequence mSeparator;
@@ -178,6 +191,8 @@
             boolean showAirplaneMode,
             boolean showMissingSim,
             WifiRepository wifiRepository,
+            DeviceBasedSatelliteViewModel deviceBasedSatelliteViewModel,
+            JavaAdapter javaAdapter,
             TelephonyManager telephonyManager,
             TelephonyListenerManager telephonyListenerManager,
             WakefulnessLifecycle wakefulnessLifecycle,
@@ -192,6 +207,8 @@
         mShowAirplaneMode = showAirplaneMode;
         mShowMissingSim = showMissingSim;
         mWifiRepository = wifiRepository;
+        mDeviceBasedSatelliteViewModel = deviceBasedSatelliteViewModel;
+        mJavaAdapter = javaAdapter;
         mTelephonyManager = telephonyManager;
         mSeparator = separator;
         mTelephonyListenerManager = telephonyListenerManager;
@@ -282,6 +299,11 @@
                     mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
                 });
                 mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
+                cancelSatelliteCollectionJob(/* reason= */ "Starting new job");
+                mSatelliteConnectionJob =
+                    mJavaAdapter.alwaysCollectFlow(
+                        mDeviceBasedSatelliteViewModel.getCarrierText(),
+                        this::onSatelliteCarrierTextChanged);
             } else {
                 // Don't listen and clear out the text when the device isn't a phone.
                 mMainExecutor.execute(() -> callback.updateCarrierInfo(
@@ -294,6 +316,7 @@
                 mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
             });
             mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mPhoneStateListener);
+            cancelSatelliteCollectionJob(/* reason= */ "Stopping listening");
         }
     }
 
@@ -311,6 +334,12 @@
         return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo();
     }
 
+    private void onSatelliteCarrierTextChanged(@Nullable String text) {
+        mLogger.logUpdateCarrierTextForReason(REASON_SATELLITE_CHANGED);
+        mSatelliteCarrierText = text;
+        updateCarrierText();
+    }
+
     protected void updateCarrierText() {
         Trace.beginSection("CarrierTextManager#updateCarrierText");
         boolean allSimsMissing = true;
@@ -411,6 +440,12 @@
             airplaneMode = true;
         }
 
+        String currentSatelliteText = mSatelliteCarrierText;
+        if (currentSatelliteText != null) {
+            mLogger.logUsingSatelliteText(currentSatelliteText);
+            displayText = currentSatelliteText;
+        }
+
         final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
                 displayText,
                 carrierNames,
@@ -616,11 +651,20 @@
         return list;
     }
 
+    private void cancelSatelliteCollectionJob(String reason) {
+        Job job = mSatelliteConnectionJob;
+        if (job != null) {
+            job.cancel(new CancellationException(reason));
+        }
+    }
+
     /** Injectable Buildeer for {@#link CarrierTextManager}. */
     public static class Builder {
         private final Context mContext;
         private final String mSeparator;
         private final WifiRepository mWifiRepository;
+        private final DeviceBasedSatelliteViewModel mDeviceBasedSatelliteViewModel;
+        private final JavaAdapter mJavaAdapter;
         private final TelephonyManager mTelephonyManager;
         private final TelephonyListenerManager mTelephonyListenerManager;
         private final WakefulnessLifecycle mWakefulnessLifecycle;
@@ -637,6 +681,8 @@
                 Context context,
                 @Main Resources resources,
                 @Nullable WifiRepository wifiRepository,
+                DeviceBasedSatelliteViewModel deviceBasedSatelliteViewModel,
+                JavaAdapter javaAdapter,
                 TelephonyManager telephonyManager,
                 TelephonyListenerManager telephonyListenerManager,
                 WakefulnessLifecycle wakefulnessLifecycle,
@@ -648,6 +694,8 @@
             mSeparator = resources.getString(
                     com.android.internal.R.string.kg_text_message_separator);
             mWifiRepository = wifiRepository;
+            mDeviceBasedSatelliteViewModel = deviceBasedSatelliteViewModel;
+            mJavaAdapter = javaAdapter;
             mTelephonyManager = telephonyManager;
             mTelephonyListenerManager = telephonyListenerManager;
             mWakefulnessLifecycle = wakefulnessLifecycle;
@@ -682,9 +730,20 @@
         public CarrierTextManager build() {
             mLogger.setLocation(mDebugLocation);
             return new CarrierTextManager(
-                    mContext, mSeparator, mShowAirplaneMode, mShowMissingSim, mWifiRepository,
-                    mTelephonyManager, mTelephonyListenerManager, mWakefulnessLifecycle,
-                    mMainExecutor, mBgExecutor, mKeyguardUpdateMonitor, mLogger);
+                    mContext,
+                    mSeparator,
+                    mShowAirplaneMode,
+                    mShowMissingSim,
+                    mWifiRepository,
+                    mDeviceBasedSatelliteViewModel,
+                    mJavaAdapter,
+                    mTelephonyManager,
+                    mTelephonyListenerManager,
+                    mWakefulnessLifecycle,
+                    mMainExecutor,
+                    mBgExecutor,
+                    mKeyguardUpdateMonitor,
+                    mLogger);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 8a18efc..460779c 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -15,6 +15,7 @@
  */
 package com.android.keyguard
 
+import android.os.Trace
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
@@ -31,7 +32,6 @@
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.tracing.coroutines.launch
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.customization.R
 import com.android.systemui.dagger.qualifiers.Background
@@ -66,7 +66,6 @@
 import java.util.TimeZone
 import java.util.concurrent.Executor
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.Job
@@ -74,6 +73,7 @@
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.launch
 
 /**
  * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
@@ -91,7 +91,6 @@
     @DisplaySpecific private val resources: Resources,
     private val context: Context,
     @Main private val mainExecutor: DelayableExecutor,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
     @Background private val bgExecutor: Executor,
     private val clockBuffers: ClockMessageBuffers,
     private val featureFlags: FeatureFlagsClassic,
@@ -426,12 +425,13 @@
         keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
         zenModeController.addCallback(zenModeCallback)
         disposableHandle =
-            parent.repeatWhenAttached(mainImmediateDispatcher) {
+            parent.repeatWhenAttached {
                 repeatOnLifecycle(Lifecycle.State.CREATED) {
                     listenForDozing(this)
                     if (MigrateClocksToBlueprint.isEnabled) {
                         listenForDozeAmountTransition(this)
                         listenForAnyStateToAodTransition(this)
+                        listenForAnyStateToLockscreenTransition(this)
                     } else {
                         listenForDozeAmount(this)
                     }
@@ -522,8 +522,12 @@
     private fun handleDoze(doze: Float) {
         dozeAmount = doze
         clock?.run {
+            Trace.beginSection("$TAG#smallClock.animations.doze")
             smallClock.animations.doze(dozeAmount)
+            Trace.endSection()
+            Trace.beginSection("$TAG#largeClock.animations.doze")
             largeClock.animations.doze(dozeAmount)
+            Trace.endSection()
         }
         smallTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
         largeTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
@@ -531,20 +535,20 @@
 
     @VisibleForTesting
     internal fun listenForDozeAmount(scope: CoroutineScope): Job {
-        return scope.launch("$TAG#listenForDozeAmount") {
-            keyguardInteractor.dozeAmount.collect { handleDoze(it) }
-        }
+        return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } }
     }
 
     @VisibleForTesting
     internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job {
-        return scope.launch("$TAG#listenForDozeAmountTransition") {
+        return scope.launch {
             merge(
-                    keyguardTransitionInteractor.aodToLockscreenTransition.map { step ->
+                    keyguardTransitionInteractor.transition(AOD, LOCKSCREEN).map { step ->
                         step.copy(value = 1f - step.value)
                     },
-                    keyguardTransitionInteractor.lockscreenToAodTransition,
-                )
+                    keyguardTransitionInteractor.transition(LOCKSCREEN, AOD),
+                ).filter {
+                    it.transitionState != TransitionState.FINISHED
+                }
                 .collect { handleDoze(it.value) }
         }
     }
@@ -554,7 +558,7 @@
      */
     @VisibleForTesting
     internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
-        return scope.launch("$TAG#listenForAnyStateToAodTransition") {
+        return scope.launch {
             keyguardTransitionInteractor
                 .transitionStepsToState(AOD)
                 .filter { it.transitionState == TransitionState.STARTED }
@@ -564,8 +568,19 @@
     }
 
     @VisibleForTesting
+    internal fun listenForAnyStateToLockscreenTransition(scope: CoroutineScope): Job {
+        return scope.launch {
+            keyguardTransitionInteractor
+                    .transitionStepsToState(LOCKSCREEN)
+                    .filter { it.transitionState == TransitionState.STARTED }
+                    .filter { it.from != AOD }
+                    .collect { handleDoze(0f) }
+        }
+    }
+
+    @VisibleForTesting
     internal fun listenForDozing(scope: CoroutineScope): Job {
-        return scope.launch("$TAG#listenForDozing") {
+        return scope.launch {
             combine(
                     keyguardInteractor.dozeAmount,
                     keyguardInteractor.isDozing,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 790a843..47e4b49 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -68,6 +68,8 @@
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.settings.SecureSettings;
 
+import kotlinx.coroutines.DisposableHandle;
+
 import java.io.PrintWriter;
 import java.util.Locale;
 import java.util.concurrent.Executor;
@@ -75,8 +77,6 @@
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.DisposableHandle;
-
 /**
  * Injectable controller for {@link KeyguardClockSwitch}.
  */
@@ -593,7 +593,7 @@
 
     boolean isClockTopAligned() {
         if (MigrateClocksToBlueprint.isEnabled()) {
-            return mKeyguardClockInteractor.getClockSize().getValue() == LARGE;
+            return mKeyguardClockInteractor.getClockSize().getValue().getLegacyValue() == LARGE;
         }
         return mLargeClockFrame.getVisibility() != View.VISIBLE;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 458a21c5..75d925d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -107,7 +107,10 @@
         }
     }
 
-    private void updateMessageAreaVisibility() {
+    /**
+     * Determines whether to show the message area controlled by MessageAreaController.
+     */
+    public void updateMessageAreaVisibility() {
         if (mMessageAreaController == null) return;
         if (Flags.revampedBouncerMessages()) {
             mMessageAreaController.disable();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 25d7713..b916fc2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -39,7 +39,6 @@
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.hardware.biometrics.BiometricRequestConstants;
 import android.media.AudioManager;
 import android.metrics.LogMaker;
 import android.os.SystemClock;
@@ -73,9 +72,6 @@
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.Gefingerpoken;
 import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate;
-import com.android.systemui.biometrics.SideFpsController;
-import com.android.systemui.biometrics.SideFpsUiRequestSource;
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor;
 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.classifier.FalsingA11yDelegate;
@@ -83,14 +79,14 @@
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardWmStateRefactor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -101,16 +97,16 @@
 import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.systemui.util.settings.GlobalSettings;
 
+import dagger.Lazy;
+
+import kotlinx.coroutines.Job;
+
 import java.io.File;
 import java.util.Arrays;
-import java.util.Optional;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import dagger.Lazy;
-import kotlinx.coroutines.Job;
-
 /** Controller for {@link KeyguardSecurityContainer} */
 @KeyguardBouncerScope
 public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer>
@@ -133,9 +129,7 @@
     private final UserSwitcherController mUserSwitcherController;
     private final GlobalSettings mGlobalSettings;
     private final FeatureFlags mFeatureFlags;
-    private final SceneContainerFlags mSceneContainerFlags;
     private final SessionTracker mSessionTracker;
-    private final Optional<SideFpsController> mSideFpsController;
     private final FalsingA11yDelegate mFalsingA11yDelegate;
     private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
     private final BouncerMessageInteractor mBouncerMessageInteractor;
@@ -310,7 +304,7 @@
          */
         @Override
         public void finish(int targetUserId) {
-            if (!mFeatureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+            if (!RefactorKeyguardDismissIntent.isEnabled()) {
                 // If there's a pending runnable because the user interacted with a widget
                 // and we're leaving keyguard, then run it.
                 boolean deferKeyguardDone = false;
@@ -455,10 +449,8 @@
             FalsingManager falsingManager,
             UserSwitcherController userSwitcherController,
             FeatureFlags featureFlags,
-            SceneContainerFlags sceneContainerFlags,
             GlobalSettings globalSettings,
             SessionTracker sessionTracker,
-            Optional<SideFpsController> sideFpsController,
             FalsingA11yDelegate falsingA11yDelegate,
             TelephonyManager telephonyManager,
             ViewMediatorCallback viewMediatorCallback,
@@ -490,14 +482,8 @@
         mFalsingManager = falsingManager;
         mUserSwitcherController = userSwitcherController;
         mFeatureFlags = featureFlags;
-        mSceneContainerFlags = sceneContainerFlags;
         mGlobalSettings = globalSettings;
         mSessionTracker = sessionTracker;
-        if (SideFpsControllerRefactor.isEnabled()) {
-            mSideFpsController = Optional.empty();
-        } else {
-            mSideFpsController = sideFpsController;
-        }
         mFalsingA11yDelegate = falsingA11yDelegate;
         mTelephonyManager = telephonyManager;
         mViewMediatorCallback = viewMediatorCallback;
@@ -533,7 +519,7 @@
 
         showPrimarySecurityScreen(false);
 
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             // When the scene framework says that the lockscreen has been dismissed, dismiss the
             // keyguard here, revealing the underlying app or launcher:
             mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
@@ -580,28 +566,6 @@
         mView.clearFocus();
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /**
-     * Shows and hides the side finger print sensor animation.
-     *
-     * @param isVisible sets whether we show or hide the side fps animation
-     */
-    public void updateSideFpsVisibility(boolean isVisible) {
-        SideFpsControllerRefactor.assertInLegacyMode();
-        if (!mSideFpsController.isPresent()) {
-            return;
-        }
-
-        if (isVisible) {
-            mSideFpsController.get().show(
-                    SideFpsUiRequestSource.PRIMARY_BOUNCER,
-                    BiometricRequestConstants.REASON_AUTH_KEYGUARD
-            );
-        } else {
-            mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
-        }
-    }
-
     /**
      * Shows the primary security screen for the user. This will be either the multi-selector
      * or the user's security method.
@@ -613,6 +577,7 @@
         SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
                 mSelectedUserInteractor.getSelectedUserId()));
         if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
+        mPrimaryBouncerInteractor.get().setLastShownPrimarySecurityScreen(securityMode);
         showSecurityScreen(securityMode);
     }
 
@@ -649,7 +614,7 @@
      * @param action callback to be invoked when keyguard disappear animation completes.
      */
     public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
-        if (mFeatureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled()) {
             return;
         }
         if (mCancelAction != null) {
@@ -943,7 +908,7 @@
             mUiEventLogger.log(uiEvent, getSessionId());
         }
 
-        if (mFeatureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled()) {
             if (authenticatedWithPrimaryAuth) {
                 mPrimaryBouncerInteractor.get()
                         .notifyKeyguardAuthenticatedPrimaryAuth(targetUserId);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 558679e..3ef3418 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -118,6 +118,12 @@
     }
 
     @Override
+    public void updateMessageAreaVisibility() {
+        if (mMessageAreaController == null) return;
+        mMessageAreaController.setIsVisible(true);
+    }
+
+    @Override
     void resetState() {
         super.resetState();
         if (DEBUG) Log.v(TAG, "Resetting state");
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
index cb1c4b30..46225c7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -115,6 +115,12 @@
     }
 
     @Override
+    public void updateMessageAreaVisibility() {
+        if (mMessageAreaController == null) return;
+        mMessageAreaController.setIsVisible(true);
+    }
+
+    @Override
     public void onResume(int reason) {
         super.onResume(reason);
         if (mShowDefaultMessage) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 8c51a4e..519622e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -42,7 +42,6 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED;
-import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
 
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
@@ -1868,7 +1867,9 @@
                 @Override
                 public void onPostureChanged(@DevicePostureInt int posture) {
                     if (posture == DEVICE_POSTURE_OPENED) {
-                        mLogger.d("Posture changed to open - attempting to request active unlock");
+                        mLogger.d("Posture changed to open - attempting to request active"
+                                + " unlock and run face auth");
+                        getFaceAuthInteractor().onDeviceUnfolded();
                         requestActiveUnlockFromWakeReason(PowerManager.WAKE_REASON_UNFOLD_DEVICE,
                                 false);
                     }
@@ -2434,9 +2435,7 @@
                 updateFingerprintListeningState(BIOMETRIC_ACTION_START);
             }
         });
-        if (mConfigFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
-            mDevicePostureController.addCallback(mPostureCallback);
-        }
+        mDevicePostureController.addCallback(mPostureCallback);
         updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
 
         mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index 9b09265..afeb0f8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -189,6 +189,5 @@
             ShadeLockscreenInteractor shadeLockscreenInteractor,
             @Nullable ShadeExpansionStateManager shadeExpansionStateManager,
             BiometricUnlockController biometricUnlockController,
-            View notificationContainer,
-            KeyguardBypassController bypassController);
+            View notificationContainer);
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java
index 4e5df35..cf2675b 100644
--- a/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java
@@ -74,7 +74,7 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -131,7 +131,6 @@
     @NonNull private final KeyguardInteractor mKeyguardInteractor;
     @NonNull private final View.AccessibilityDelegate mAccessibilityDelegate;
     @NonNull private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractor;
-    @NonNull private final SceneContainerFlags mSceneContainerFlags;
 
     // Tracks the velocity of a touch to help filter out the touches that move too fast.
     private VelocityTracker mVelocityTracker;
@@ -208,8 +207,7 @@
             @NonNull FeatureFlags featureFlags,
             PrimaryBouncerInteractor primaryBouncerInteractor,
             Context context,
-            Lazy<DeviceEntryInteractor> deviceEntryInteractor,
-            SceneContainerFlags sceneContainerFlags
+            Lazy<DeviceEntryInteractor> deviceEntryInteractor
     ) {
         mStatusBarStateController = statusBarStateController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -236,7 +234,6 @@
         mResources = resources;
         mContext = context;
         mDeviceEntryInteractor = deviceEntryInteractor;
-        mSceneContainerFlags = sceneContainerFlags;
 
         mAccessibilityDelegate = new View.AccessibilityDelegate() {
             private final AccessibilityNodeInfo.AccessibilityAction mAccessibilityAuthenticateHint =
@@ -746,7 +743,7 @@
         // play device entry haptic (consistent with UDFPS controller longpress)
         vibrateOnLongPress();
 
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             mDeviceEntryInteractor.get().attemptDeviceEntry();
         } else {
             mKeyguardViewController.showPrimaryBouncer(/* scrim */ true);
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index afea224..4bbc2d6 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -16,23 +16,14 @@
 
 package com.android.keyguard.dagger;
 
-import static com.android.systemui.biometrics.SideFpsControllerKt.hasSideFpsSensor;
-
-import android.annotation.Nullable;
-import android.hardware.fingerprint.FingerprintManager;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
 import com.android.keyguard.KeyguardSecurityContainer;
 import com.android.keyguard.KeyguardSecurityViewFlipper;
-import com.android.systemui.res.R;
-import com.android.systemui.biometrics.SideFpsController;
-import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
-
-import java.util.Optional;
-
-import javax.inject.Provider;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.res.R;
 
 import dagger.Module;
 import dagger.Provides;
@@ -62,16 +53,4 @@
             KeyguardSecurityContainer containerView) {
         return containerView.findViewById(R.id.view_flipper);
     }
-
-    /** Provides {@link SideFpsController} if the device has the side fingerprint sensor. */
-    @Provides
-    @KeyguardBouncerScope
-    static Optional<SideFpsController> providesOptionalSidefpsController(
-            @Nullable FingerprintManager fingerprintManager,
-            Provider<SideFpsController> sidefpsControllerProvider) {
-        if (!hasSideFpsSensor(fingerprintManager)) {
-            return Optional.empty();
-        }
-        return Optional.of(sidefpsControllerProvider.get());
-    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt
index cb474d3..48fea55 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt
@@ -77,6 +77,15 @@
         )
     }
 
+    fun logUsingSatelliteText(satelliteText: String) {
+        buffer.log(
+            TAG,
+            LogLevel.VERBOSE,
+            { str1 = satelliteText },
+            { "┣ updateCarrierText: using satellite text. text=$str1" },
+        )
+    }
+
     /** De-structures the info object so that we don't have to generate new strings */
     fun logCallbackSentFromUpdate(info: CarrierTextCallbackInfo) {
         buffer.log(
@@ -129,6 +138,7 @@
         const val REASON_ON_TELEPHONY_CAPABLE = 2
         const val REASON_SIM_ERROR_STATE_CHANGED = 3
         const val REASON_ACTIVE_DATA_SUB_CHANGED = 4
+        const val REASON_SATELLITE_CHANGED = 5
 
         @Retention(AnnotationRetention.SOURCE)
         @IntDef(
@@ -138,6 +148,7 @@
                     REASON_ON_TELEPHONY_CAPABLE,
                     REASON_SIM_ERROR_STATE_CHANGED,
                     REASON_ACTIVE_DATA_SUB_CHANGED,
+                    REASON_SATELLITE_CHANGED,
                 ]
         )
         annotation class CarrierTextRefreshReason
@@ -148,6 +159,7 @@
                 REASON_ON_TELEPHONY_CAPABLE -> "ON_TELEPHONY_CAPABLE"
                 REASON_SIM_ERROR_STATE_CHANGED -> "SIM_ERROR_STATE_CHANGED"
                 REASON_ACTIVE_DATA_SUB_CHANGED -> "ACTIVE_DATA_SUB_CHANGED"
+                REASON_SATELLITE_CHANGED -> "SATELLITE_CHANGED"
                 else -> "unknown"
             }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/DeviceEntryIconLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/DeviceEntryIconLogger.kt
new file mode 100644
index 0000000..349964b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/logging/DeviceEntryIconLogger.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard.logging
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.core.LogLevel.DEBUG
+import com.android.systemui.log.core.LogLevel.INFO
+import com.android.systemui.log.dagger.DeviceEntryIconLog
+import com.google.errorprone.annotations.CompileTimeConstant
+import javax.inject.Inject
+
+private const val GENERIC_TAG = "DeviceEntryIconLogger"
+
+/** Helper class for logging for the DeviceEntryIcon */
+@SysUISingleton
+class DeviceEntryIconLogger
+@Inject
+constructor(@DeviceEntryIconLog private val logBuffer: LogBuffer) {
+    fun i(@CompileTimeConstant msg: String) = log(msg, INFO)
+    fun d(@CompileTimeConstant msg: String) = log(msg, DEBUG)
+    fun log(@CompileTimeConstant msg: String, level: LogLevel) =
+        logBuffer.log(GENERIC_TAG, level, msg)
+
+    fun logDeviceEntryUdfpsTouchOverlayShouldHandleTouches(
+        shouldHandleTouches: Boolean,
+        canTouchDeviceEntryViewAlpha: Boolean,
+        alternateBouncerVisible: Boolean,
+        hideAffordancesRequest: Boolean,
+    ) {
+        logBuffer.log(
+            "DeviceEntryUdfpsTouchOverlay",
+            DEBUG,
+            {
+                bool1 = canTouchDeviceEntryViewAlpha
+                bool2 = alternateBouncerVisible
+                bool3 = hideAffordancesRequest
+                bool4 = shouldHandleTouches
+            },
+            {
+                "shouldHandleTouches=$bool4 canTouchDeviceEntryViewAlpha=$bool1 " +
+                    "alternateBouncerVisible=$bool2 hideAffordancesRequest=$bool3"
+            }
+        )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/CoreStartable.java b/packages/SystemUI/src/com/android/systemui/CoreStartable.java
index 39e1c41..55ccaa6 100644
--- a/packages/SystemUI/src/com/android/systemui/CoreStartable.java
+++ b/packages/SystemUI/src/com/android/systemui/CoreStartable.java
@@ -33,12 +33,23 @@
  *  abstract fun bind(impl: FoobarStartable): CoreStartable
  *  </pre>
  *
- * If your CoreStartable depends on different CoreStartables starting before it, use a
- * {@link com.android.systemui.startable.Dependencies} annotation to list out those dependencies.
+ * If your CoreStartable depends on different CoreStartables starting before it, you can specify
+ * another map binding listing out its dependencies:
+ *  <pre>
+ *  &#64;Provides
+ *  &#64;IntoMap
+ *  &#64;Dependencies  // Important! com.android.systemui.startable.Dependencies.
+ *  &#64;ClassKey(FoobarStartable::class)
+ *  fun providesDeps(): Set&lt;Class&lt;out CoreStartable&gt;&gt; {
+ *      return setOf(OtherStartable::class.java)
+ *  }
+ *  </pre>
+ *
  *
  * @see SystemUIApplication#startSystemUserServicesIfNeeded()
  */
 public interface CoreStartable extends Dumpable {
+    String STARTABLE_DEPENDENCIES = "startable_dependencies";
 
     /** Main entry point for implementations. Called shortly after SysUI startup. */
     void start();
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 3e03fb8..b8af59d 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -401,8 +401,6 @@
         mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler);
         mExecutor.execute(this::startOnScreenDecorationsThread);
         mDotViewController.setUiExecutor(mExecutor);
-        mJavaAdapter.alwaysCollectFlow(mFacePropertyRepository.getSensorLocation(),
-                this::onFaceSensorLocationChanged);
         mCommandRegistry.registerCommand(ScreenDecorCommand.SCREEN_DECOR_CMD_NAME,
                 () -> new ScreenDecorCommand(mScreenDecorCommandCallback));
     }
@@ -579,6 +577,8 @@
         };
         mDisplayTracker.addDisplayChangeCallback(mDisplayListener, new HandlerExecutor(mHandler));
         updateConfiguration();
+        mJavaAdapter.alwaysCollectFlow(mFacePropertyRepository.getSensorLocation(),
+                this::onFaceSensorLocationChanged);
         Trace.endSection();
     }
 
@@ -1320,10 +1320,18 @@
     @VisibleForTesting
     void onFaceSensorLocationChanged(Point location) {
         mLogger.onSensorLocationChanged();
+
         if (mExecutor != null) {
             mExecutor.execute(
-                    () -> updateOverlayProviderViews(
-                            new Integer[]{mFaceScanningViewId}));
+                    () -> {
+                        if (getOverlayView(mFaceScanningViewId) == null) {
+                            // face sensor location was just initialized
+                            setupDecorations();
+                        } else {
+                            updateOverlayProviderViews(new Integer[]{mFaceScanningViewId});
+                        }
+                    }
+            );
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
index 5bd85a7..429d3f0 100644
--- a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui;
 
+import static com.android.systemui.Flags.sliceBroadcastRelayInBackground;
+
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentProvider;
@@ -23,13 +25,19 @@
 import android.net.Uri;
 import android.os.UserHandle;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.Log;
 
+import androidx.annotation.GuardedBy;
+import androidx.annotation.WorkerThread;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.SliceBroadcastRelay;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
+
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
@@ -42,14 +50,18 @@
     private static final String TAG = "SliceBroadcastRelay";
     private static final boolean DEBUG = false;
 
+    @GuardedBy("mRelays")
     private final ArrayMap<Uri, BroadcastRelay> mRelays = new ArrayMap<>();
     private final Context mContext;
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final Executor mBackgroundExecutor;
 
     @Inject
-    public SliceBroadcastRelayHandler(Context context, BroadcastDispatcher broadcastDispatcher) {
+    public SliceBroadcastRelayHandler(Context context, BroadcastDispatcher broadcastDispatcher,
+                                      @Background Executor backgroundExecutor) {
         mContext = context;
         mBroadcastDispatcher = broadcastDispatcher;
+        mBackgroundExecutor = backgroundExecutor;
     }
 
     @Override
@@ -57,21 +69,29 @@
         if (DEBUG) Log.d(TAG, "Start");
         IntentFilter filter = new IntentFilter(SliceBroadcastRelay.ACTION_REGISTER);
         filter.addAction(SliceBroadcastRelay.ACTION_UNREGISTER);
-        mBroadcastDispatcher.registerReceiver(mReceiver, filter);
+
+        if (sliceBroadcastRelayInBackground()) {
+            mBroadcastDispatcher.registerReceiver(mReceiver, filter, mBackgroundExecutor);
+        } else {
+            mBroadcastDispatcher.registerReceiver(mReceiver, filter);
+        }
     }
 
     // This does not use BroadcastDispatcher as the filter may have schemas or mime types.
+    @WorkerThread
     @VisibleForTesting
     void handleIntent(Intent intent) {
         if (SliceBroadcastRelay.ACTION_REGISTER.equals(intent.getAction())) {
-            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
+            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI, Uri.class);
             ComponentName receiverClass =
-                    intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_RECEIVER);
-            IntentFilter filter = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_FILTER);
+                    intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_RECEIVER,
+                            ComponentName.class);
+            IntentFilter filter = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_FILTER,
+                    IntentFilter.class);
             if (DEBUG) Log.d(TAG, "Register " + uri + " " + receiverClass + " " + filter);
             getOrCreateRelay(uri).register(mContext, receiverClass, filter);
         } else if (SliceBroadcastRelay.ACTION_UNREGISTER.equals(intent.getAction())) {
-            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
+            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI, Uri.class);
             if (DEBUG) Log.d(TAG, "Unregister " + uri);
             BroadcastRelay relay = getAndRemoveRelay(uri);
             if (relay != null) {
@@ -80,17 +100,23 @@
         }
     }
 
+    @WorkerThread
     private BroadcastRelay getOrCreateRelay(Uri uri) {
-        BroadcastRelay ret = mRelays.get(uri);
-        if (ret == null) {
-            ret = new BroadcastRelay(uri);
-            mRelays.put(uri, ret);
+        synchronized (mRelays) {
+            BroadcastRelay ret = mRelays.get(uri);
+            if (ret == null) {
+                ret = new BroadcastRelay(uri);
+                mRelays.put(uri, ret);
+            }
+            return ret;
         }
-        return ret;
     }
 
+    @WorkerThread
     private BroadcastRelay getAndRemoveRelay(Uri uri) {
-        return mRelays.remove(uri);
+        synchronized (mRelays) {
+            return mRelays.remove(uri);
+        }
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -102,7 +128,7 @@
 
     private static class BroadcastRelay extends BroadcastReceiver {
 
-        private final ArraySet<ComponentName> mReceivers = new ArraySet<>();
+        private final CopyOnWriteArraySet<ComponentName> mReceivers = new CopyOnWriteArraySet<>();
         private final UserHandle mUserId;
         private final Uri mUri;
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index ea8fe59..4b07402 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -44,16 +44,15 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.process.ProcessWrapper;
 import com.android.systemui.res.R;
-import com.android.systemui.startable.Dependencies;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.util.NotificationChannels;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayDeque;
-import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.StringJoiner;
 import java.util.TreeMap;
 
@@ -204,7 +203,7 @@
      */
 
     public void startSystemUserServicesIfNeeded() {
-        if (!mProcessWrapper.isSystemUser()) {
+        if (!shouldStartSystemUserServices()) {
             Log.wtf(TAG, "Tried starting SystemUser services on non-SystemUser");
             return;  // Per-user startables are handled in #startSystemUserServicesIfNeeded.
         }
@@ -227,7 +226,7 @@
      * <p>This method must only be called from the main thread.</p>
      */
     void startSecondaryUserServicesIfNeeded() {
-        if (mProcessWrapper.isSystemUser()) {
+        if (!shouldStartSecondaryUserServices()) {
             return;  // Per-user startables are handled in #startSystemUserServicesIfNeeded.
         }
         // Sort the startables so that we get a deterministic ordering.
@@ -238,6 +237,14 @@
                 sortedStartables, "StartSecondaryServices", null);
     }
 
+    protected boolean shouldStartSystemUserServices() {
+        return mProcessWrapper.isSystemUser();
+    }
+
+    protected boolean shouldStartSecondaryUserServices() {
+        return !mProcessWrapper.isSystemUser();
+    }
+
     private void startServicesIfNeeded(
             Map<Class<?>, Provider<CoreStartable>> startables,
             String metricsPrefix,
@@ -292,6 +299,7 @@
         int serviceIndex = 0;
 
         do {
+            startedAny = false;
             queue = nextQueue;
             nextQueue = new ArrayDeque<>(startables.size());
 
@@ -299,9 +307,9 @@
                 Map.Entry<Class<?>, Provider<CoreStartable>> entry = queue.removeFirst();
 
                 Class<?> cls = entry.getKey();
-                Dependencies dep = cls.getAnnotation(Dependencies.class);
-                Class<? extends CoreStartable>[] deps = (dep == null ? null : dep.value());
-                if (deps == null || startedStartables.containsAll(Arrays.asList(deps))) {
+                Set<Class<? extends CoreStartable>> deps =
+                        mSysUIComponent.getStartableDependencies().get(cls);
+                if (deps == null || startedStartables.containsAll(deps)) {
                     String clsName = cls.getName();
                     int i = serviceIndex;  // Copied to make lambda happy.
                     timeInitialization(
@@ -323,12 +331,12 @@
             while (!nextQueue.isEmpty()) {
                 Map.Entry<Class<?>, Provider<CoreStartable>> entry = nextQueue.removeFirst();
                 Class<?> cls = entry.getKey();
-                Dependencies dep = cls.getAnnotation(Dependencies.class);
-                Class<? extends CoreStartable>[] deps = (dep == null ? null : dep.value());
+                Set<Class<? extends CoreStartable>> deps =
+                        mSysUIComponent.getStartableDependencies().get(cls);
                 StringJoiner stringJoiner = new StringJoiner(", ");
-                for (int i = 0; deps != null && i < deps.length; i++) {
-                    if (!startedStartables.contains(deps[i])) {
-                        stringJoiner.add(deps[i].getName());
+                for (Class<? extends CoreStartable> c : deps) {
+                    if (!startedStartables.contains(c)) {
+                        stringJoiner.add(c.getName());
                     }
                 }
                 Log.e(TAG, "Failed to start " + cls.getName()
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
index 7e94804..5c75a49 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
@@ -94,7 +94,7 @@
                     .setOneHanded(mWMComponent.getOneHanded())
                     .setBubbles(mWMComponent.getBubbles())
                     .setTaskViewFactory(mWMComponent.getTaskViewFactory())
-                    .setTransitions(mWMComponent.getTransitions())
+                    .setShellTransitions(mWMComponent.getShellTransitions())
                     .setKeyguardTransitions(mWMComponent.getKeyguardTransitions())
                     .setStartingSurface(mWMComponent.getStartingSurface())
                     .setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
@@ -115,7 +115,7 @@
                     .setOneHanded(Optional.ofNullable(null))
                     .setBubbles(Optional.ofNullable(null))
                     .setTaskViewFactory(Optional.ofNullable(null))
-                    .setTransitions(new ShellTransitions() {})
+                    .setShellTransitions(new ShellTransitions() {})
                     .setKeyguardTransitions(new KeyguardTransitions() {})
                     .setDisplayAreaHelper(Optional.ofNullable(null))
                     .setStartingSurface(Optional.ofNullable(null))
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java
index af8149f..0bd6d6e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java
@@ -18,8 +18,15 @@
 
 import static android.view.WindowManager.LayoutParams;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.annotation.UiContext;
+import android.content.ComponentCallbacks;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -30,56 +37,123 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.UiThread;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.res.R;
 
+import java.util.concurrent.Executor;
 import java.util.function.Supplier;
 
-class FullscreenMagnificationController {
+class FullscreenMagnificationController implements ComponentCallbacks {
 
     private final Context mContext;
     private final AccessibilityManager mAccessibilityManager;
     private final WindowManager mWindowManager;
     private Supplier<SurfaceControlViewHost> mScvhSupplier;
-    private SurfaceControlViewHost mSurfaceControlViewHost;
+    private SurfaceControlViewHost mSurfaceControlViewHost = null;
+    private SurfaceControl mBorderSurfaceControl = null;
     private Rect mWindowBounds;
     private SurfaceControl.Transaction mTransaction;
     private View mFullscreenBorder = null;
     private int mBorderOffset;
     private final int mDisplayId;
     private static final Region sEmptyRegion = new Region();
+    private ValueAnimator mShowHideBorderAnimator;
+    private Executor mExecutor;
+    private boolean mFullscreenMagnificationActivated = false;
+    private final Configuration mConfiguration;
 
     FullscreenMagnificationController(
             @UiContext Context context,
+            Executor executor,
             AccessibilityManager accessibilityManager,
             WindowManager windowManager,
             Supplier<SurfaceControlViewHost> scvhSupplier) {
+        this(context, executor, accessibilityManager, windowManager, scvhSupplier,
+                new SurfaceControl.Transaction(), createNullTargetObjectAnimator(context));
+    }
+
+    @VisibleForTesting
+    FullscreenMagnificationController(
+            @UiContext Context context,
+            @Main Executor executor,
+            AccessibilityManager accessibilityManager,
+            WindowManager windowManager,
+            Supplier<SurfaceControlViewHost> scvhSupplier,
+            SurfaceControl.Transaction transaction,
+            ValueAnimator valueAnimator) {
         mContext = context;
+        mExecutor = executor;
         mAccessibilityManager = accessibilityManager;
         mWindowManager = windowManager;
         mWindowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
-        mTransaction = new SurfaceControl.Transaction();
+        mTransaction = transaction;
         mScvhSupplier = scvhSupplier;
         mBorderOffset = mContext.getResources().getDimensionPixelSize(
                 R.dimen.magnifier_border_width_fullscreen_with_offset)
                 - mContext.getResources().getDimensionPixelSize(
                 R.dimen.magnifier_border_width_fullscreen);
         mDisplayId = mContext.getDisplayId();
+        mConfiguration = new Configuration(context.getResources().getConfiguration());
+        mShowHideBorderAnimator = valueAnimator;
+        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
+                if (isReverse) {
+                    // The animation was played in reverse, which means we are hiding the border.
+                    // We would like to perform clean up after the border is fully hidden.
+                    cleanUpBorder();
+                }
+            }
+        });
     }
 
+    private static ValueAnimator createNullTargetObjectAnimator(Context context) {
+        final ValueAnimator valueAnimator =
+                ObjectAnimator.ofFloat(/* target= */ null, View.ALPHA, 0f, 1f);
+        Interpolator interpolator = new AccelerateDecelerateInterpolator();
+        final long longAnimationDuration = context.getResources().getInteger(
+                com.android.internal.R.integer.config_longAnimTime);
+
+        valueAnimator.setInterpolator(interpolator);
+        valueAnimator.setDuration(longAnimationDuration);
+        return valueAnimator;
+    }
+
+    /**
+     * Check the fullscreen magnification activation status, and proceed corresponding actions when
+     * there is an activation change.
+     */
     @UiThread
     void onFullscreenMagnificationActivationChanged(boolean activated) {
-        if (activated) {
-            createFullscreenMagnificationBorder();
-        } else {
-            removeFullscreenMagnificationBorder();
+        final boolean changed = (mFullscreenMagnificationActivated != activated);
+        if (changed) {
+            mFullscreenMagnificationActivated = activated;
+            if (activated) {
+                createFullscreenMagnificationBorder();
+            } else {
+                removeFullscreenMagnificationBorder();
+            }
         }
     }
 
+    /**
+     * This method should only be called when fullscreen magnification is changed from activated
+     * to inactivated.
+     */
     @UiThread
     private void removeFullscreenMagnificationBorder() {
+        mContext.unregisterComponentCallbacks(this);
+        mShowHideBorderAnimator.reverse();
+    }
+
+    private void cleanUpBorder() {
         if (mSurfaceControlViewHost != null) {
             mSurfaceControlViewHost.release();
             mSurfaceControlViewHost = null;
@@ -91,31 +165,57 @@
     }
 
     /**
-     * Since the device corners are not perfectly rounded, we would like to create a thick stroke,
-     * and set negative offset to the border view to fill up the spaces between the border and the
-     * device corners.
+     * This method should only be called when fullscreen magnification is changed from inactivated
+     * to activated.
      */
     @UiThread
     private void createFullscreenMagnificationBorder() {
-        mFullscreenBorder = LayoutInflater.from(mContext)
-                .inflate(R.layout.fullscreen_magnification_border, null);
-        mSurfaceControlViewHost = mScvhSupplier.get();
-        mSurfaceControlViewHost.setView(mFullscreenBorder, getBorderLayoutParams());
+        onConfigurationChanged(mContext.getResources().getConfiguration());
+        mContext.registerComponentCallbacks(this);
 
-        SurfaceControl surfaceControl = mSurfaceControlViewHost
-                .getSurfacePackage().getSurfaceControl();
+        if (mSurfaceControlViewHost == null) {
+            // Create the view only if it does not exist yet. If we are trying to enable fullscreen
+            // magnification before it was fully disabled, we use the previous view instead of
+            // creating a new one.
+            mFullscreenBorder = LayoutInflater.from(mContext)
+                    .inflate(R.layout.fullscreen_magnification_border, null);
+            // Set the initial border view alpha manually so we won't show the border accidentally
+            // after we apply show() to the SurfaceControl and before the animation starts to run.
+            mFullscreenBorder.setAlpha(0f);
+            mShowHideBorderAnimator.setTarget(mFullscreenBorder);
+            mSurfaceControlViewHost = mScvhSupplier.get();
+            mSurfaceControlViewHost.setView(mFullscreenBorder, getBorderLayoutParams());
+            mBorderSurfaceControl = mSurfaceControlViewHost.getSurfacePackage().getSurfaceControl();
+        }
 
         mTransaction
-                .setPosition(surfaceControl, -mBorderOffset, -mBorderOffset)
-                .setLayer(surfaceControl, Integer.MAX_VALUE)
-                .show(surfaceControl)
+                .addTransactionCommittedListener(
+                        mExecutor,
+                        () -> {
+                            if (mShowHideBorderAnimator.isRunning()) {
+                                // Since the method is only called when there is an activation
+                                // status change, the running animator is hiding the border.
+                                mShowHideBorderAnimator.reverse();
+                            } else {
+                                mShowHideBorderAnimator.start();
+                            }
+                        })
+                .setPosition(mBorderSurfaceControl, -mBorderOffset, -mBorderOffset)
+                .setLayer(mBorderSurfaceControl, Integer.MAX_VALUE)
+                .show(mBorderSurfaceControl)
                 .apply();
 
-        mAccessibilityManager.attachAccessibilityOverlayToDisplay(mDisplayId, surfaceControl);
+        mAccessibilityManager.attachAccessibilityOverlayToDisplay(
+                mDisplayId, mBorderSurfaceControl);
 
         applyTouchableRegion();
     }
 
+    /**
+     * Since the device corners are not perfectly rounded, we would like to create a thick stroke,
+     * and set negative offset to the border view to fill up the spaces between the border and the
+     * device corners.
+     */
     private LayoutParams getBorderLayoutParams() {
         LayoutParams params =  new LayoutParams(
                 mWindowBounds.width() + 2 * mBorderOffset,
@@ -137,4 +237,41 @@
         // all touch events to go through this view.
         surfaceControl.setTouchableRegion(sEmptyRegion);
     }
+
+    @Override
+    public void onConfigurationChanged(@NonNull Configuration newConfig) {
+        final int configDiff = newConfig.diff(mConfiguration);
+        mConfiguration.setTo(newConfig);
+        onConfigurationChanged(configDiff);
+    }
+
+    @VisibleForTesting
+    void onConfigurationChanged(int configDiff) {
+        boolean reCreateWindow = false;
+        if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0
+                || (configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
+                || (configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+            updateDimensions();
+            mWindowBounds.set(mWindowManager.getCurrentWindowMetrics().getBounds());
+            reCreateWindow = true;
+        }
+
+        if (mFullscreenBorder != null && reCreateWindow) {
+            final int newWidth = mWindowBounds.width() + 2 * mBorderOffset;
+            final int newHeight = mWindowBounds.height() + 2 * mBorderOffset;
+            mSurfaceControlViewHost.relayout(newWidth, newHeight);
+        }
+    }
+
+    private void updateDimensions() {
+        mBorderOffset = mContext.getResources().getDimensionPixelSize(
+                R.dimen.magnifier_border_width_fullscreen_with_offset)
+                - mContext.getResources().getDimensionPixelSize(
+                        R.dimen.magnifier_border_width_fullscreen);
+    }
+
+    @Override
+    public void onLowMemory() {
+
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java
index 70165f3..177d933 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java
@@ -54,6 +54,7 @@
 import com.android.systemui.util.settings.SecureSettings;
 
 import java.io.PrintWriter;
+import java.util.concurrent.Executor;
 import java.util.function.Supplier;
 
 import javax.inject.Inject;
@@ -71,6 +72,7 @@
     private final ModeSwitchesController mModeSwitchesController;
     private final Context mContext;
     private final Handler mHandler;
+    private final Executor mExecutor;
     private final AccessibilityManager mAccessibilityManager;
     private final CommandQueue mCommandQueue;
     private final OverviewProxyService mOverviewProxyService;
@@ -139,12 +141,13 @@
             DisplayIdIndexSupplier<FullscreenMagnificationController> {
 
         private final Context mContext;
+        private final Executor mExecutor;
 
-        FullscreenMagnificationControllerSupplier(Context context, Handler handler,
-                DisplayManager displayManager, SysUiState sysUiState,
-                SecureSettings secureSettings) {
+        FullscreenMagnificationControllerSupplier(Context context, DisplayManager displayManager,
+                Executor executor) {
             super(displayManager);
             mContext = context;
+            mExecutor = executor;
         }
 
         @Override
@@ -156,6 +159,7 @@
             windowContext.setTheme(com.android.systemui.res.R.style.Theme_SystemUI);
             return new FullscreenMagnificationController(
                     windowContext,
+                    mExecutor,
                     windowContext.getSystemService(AccessibilityManager.class),
                     windowContext.getSystemService(WindowManager.class),
                     scvhSupplier);
@@ -200,13 +204,14 @@
     DisplayIdIndexSupplier<MagnificationSettingsController> mMagnificationSettingsSupplier;
 
     @Inject
-    public Magnification(Context context, @Main Handler mainHandler,
+    public Magnification(Context context, @Main Handler mainHandler, @Main Executor executor,
             CommandQueue commandQueue, ModeSwitchesController modeSwitchesController,
             SysUiState sysUiState, OverviewProxyService overviewProxyService,
             SecureSettings secureSettings, DisplayTracker displayTracker,
             DisplayManager displayManager, AccessibilityLogger a11yLogger) {
         mContext = context;
         mHandler = mainHandler;
+        mExecutor = executor;
         mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
         mCommandQueue = commandQueue;
         mModeSwitchesController = modeSwitchesController;
@@ -218,7 +223,7 @@
                 mHandler, mWindowMagnifierCallback,
                 displayManager, sysUiState, secureSettings);
         mFullscreenMagnificationControllerSupplier = new FullscreenMagnificationControllerSupplier(
-                context, mHandler, displayManager, sysUiState, secureSettings);
+                context, displayManager, mExecutor);
         mMagnificationSettingsSupplier = new SettingsSupplier(context,
                 mMagnificationSettingsControllerCallback, displayManager, secureSettings);
 
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING b/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
index be26b43..17813cf 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
@@ -20,5 +20,10 @@
         }
       ]
     }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    }
   ]
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
index 0f4d63c..615363d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
@@ -72,6 +72,7 @@
     private boolean mEndAnimationCanceled = false;
     @MagnificationState
     private int mState = STATE_DISABLED;
+    private Runnable mOnAnimationEndRunnable;
 
     WindowMagnificationAnimationController(@UiContext Context context) {
         this(context, newValueAnimator(context.getResources()));
@@ -149,7 +150,7 @@
             if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
                 mValueAnimator.cancel();
             }
-            mController.enableWindowMagnificationInternal(scale, centerX, centerY,
+            mController.updateWindowMagnificationInternal(scale, centerX, centerY,
                     mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
             updateState();
             return;
@@ -159,7 +160,7 @@
 
         if (mEndSpec.equals(mStartSpec)) {
             if (mState == STATE_DISABLED) {
-                mController.enableWindowMagnificationInternal(scale, centerX, centerY,
+                mController.updateWindowMagnificationInternal(scale, centerX, centerY,
                         mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
             } else if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
                 mValueAnimator.cancel();
@@ -303,12 +304,7 @@
             return;
         }
 
-        // If the animation is playing backwards, mStartSpec will be the final spec we would
-        // like to reach.
-        AnimationSpec spec = isReverse ? mStartSpec : mEndSpec;
-        mController.enableWindowMagnificationInternal(
-                spec.mScale, spec.mCenterX, spec.mCenterY,
-                mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
+        mOnAnimationEndRunnable.run();
 
         if (mState == STATE_DISABLING) {
             mController.deleteWindowMagnification();
@@ -333,6 +329,10 @@
     public void onAnimationRepeat(Animator animation) {
     }
 
+    void setOnAnimationEndRunnable(Runnable runnable) {
+        mOnAnimationEndRunnable = runnable;
+    }
+
     private void sendAnimationCallback(boolean success) {
         if (mAnimationCallback != null) {
             try {
@@ -358,7 +358,7 @@
                 mStartSpec.mCenterX + (mEndSpec.mCenterX - mStartSpec.mCenterX) * fract;
         final float centerY =
                 mStartSpec.mCenterY + (mEndSpec.mCenterY - mStartSpec.mCenterY) * fract;
-        mController.enableWindowMagnificationInternal(sentScale, centerX, centerY,
+        mController.updateWindowMagnificationInternal(sentScale, centerX, centerY,
                 mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index d65cd5c..e66261c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -148,7 +148,7 @@
     /**
      * SourceBound is the bound of the magnified region which projects the magnified content.
      * SourceBound's center is equal to the parameters centerX and centerY in
-     * {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float, float)}}
+     * {@link WindowMagnificationController#updateWindowMagnificationInternal(float, float, float)}}
      * but it is calculated from {@link #mMagnificationFrame}'s center in the runtime.
      */
     private final Rect mSourceBounds = new Rect();
@@ -260,6 +260,11 @@
         mContext = context;
         mHandler = handler;
         mAnimationController = animationController;
+        mAnimationController.setOnAnimationEndRunnable(() -> {
+            if (Flags.createWindowlessWindowMagnifier()) {
+                notifySourceBoundsChanged();
+            }
+        });
         mAnimationController.setWindowMagnificationController(this);
         mWindowMagnifierCallback = callback;
         mSysUiState = sysUiState;
@@ -566,7 +571,7 @@
         // window size changed not caused by rotation.
         if (isActivated() && reCreateWindow) {
             deleteWindowMagnification();
-            enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
+            updateWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
         }
     }
 
@@ -721,11 +726,11 @@
         int windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin;
         int windowHeight = mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin;
 
-        // TODO delete TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, it shouldn't be needed anymore
-
+        // TODO: b/335440685 - Move to TYPE_ACCESSIBILITY_OVERLAY after the issues with
+        // that type preventing swipe to navigate are resolved.
         LayoutParams params = new LayoutParams(
                 windowWidth, windowHeight,
-                LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
+                LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
                 LayoutParams.FLAG_NOT_TOUCH_MODAL
                         | LayoutParams.FLAG_NOT_FOCUSABLE,
                 PixelFormat.TRANSPARENT);
@@ -1051,11 +1056,15 @@
 
             // Notify source bounds change when the magnifier is not animating.
             if (!mAnimationController.isAnimating()) {
-                mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds);
+                notifySourceBoundsChanged();
             }
         }
     }
 
+    private void notifySourceBoundsChanged() {
+        mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds);
+    }
+
     /**
      * Updates the position of {@link mSurfaceControlViewHost} and layout params of MirrorView based
      * on the position and size of {@link #mMagnificationFrame}.
@@ -1317,7 +1326,7 @@
     }
 
     /**
-     * Wraps {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float,
+     * Wraps {@link WindowMagnificationController#updateWindowMagnificationInternal(float, float,
      * float, float, float)}
      * with transition animation. If the window magnification is not enabled, the scale will start
      * from 1.0 and the center won't be changed during the animation. If animator is
@@ -1344,10 +1353,12 @@
     }
 
     /**
-     * Enables window magnification with specified parameters. If the given scale is <strong>less
-     * than or equal to 1.0f</strong>, then
+     * Updates window magnification status with specified parameters. If the given scale is
+     * <strong>less than 1.0f</strong>, then
      * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
-     * be consistent with the behavior of display magnification.
+     * be consistent with the behavior of display magnification. If the given scale is
+     * <strong>larger than or equal to 1.0f</strong>, and the window magnification is not activated
+     * yet, window magnification will be enabled.
      *
      * @param scale   the target scale, or {@link Float#NaN} to leave unchanged
      * @param centerX the screen-relative X coordinate around which to center for magnification,
@@ -1355,16 +1366,17 @@
      * @param centerY the screen-relative Y coordinate around which to center for magnification,
      *                or {@link Float#NaN} to leave unchanged.
      */
-    void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
-        enableWindowMagnificationInternal(scale, centerX, centerY, Float.NaN, Float.NaN);
+    void updateWindowMagnificationInternal(float scale, float centerX, float centerY) {
+        updateWindowMagnificationInternal(scale, centerX, centerY, Float.NaN, Float.NaN);
     }
 
     /**
-     * Enables window magnification with specified parameters. If the given scale is <strong>less
-     * than 1.0f</strong>, then
+     * Updates window magnification status with specified parameters. If the given scale is
+     * <strong>less than 1.0f</strong>, then
      * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
-     * be consistent with the behavior of display magnification.
-     *
+     * be consistent with the behavior of display magnification. If the given scale is
+     * <strong>larger than or equal to 1.0f</strong>, and the window magnification is not activated
+     * yet, window magnification will be enabled.
      * @param scale   the target scale, or {@link Float#NaN} to leave unchanged
      * @param centerX the screen-relative X coordinate around which to center for magnification,
      *                or {@link Float#NaN} to leave unchanged.
@@ -1377,7 +1389,7 @@
      *                                       between frame position Y and centerY,
      *                                       or {@link Float#NaN} to leave unchanged.
      */
-    void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
+    void updateWindowMagnificationInternal(float scale, float centerX, float centerY,
                 float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) {
         if (Float.compare(scale, 1.0f) < 0) {
             deleteWindowMagnification();
@@ -1433,7 +1445,7 @@
             return;
         }
 
-        enableWindowMagnificationInternal(scale, Float.NaN, Float.NaN);
+        updateWindowMagnificationInternal(scale, Float.NaN, Float.NaN);
         mHandler.removeCallbacks(mUpdateStateDescriptionRunnable);
         mHandler.postDelayed(mUpdateStateDescriptionRunnable, UPDATE_STATE_DESCRIPTION_DELAY_MS);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java
index 1018f70..eb840f1 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java
@@ -244,11 +244,13 @@
                 mSecureSettings.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
                 /* notifyForDescendants */ false, mMenuTargetFeaturesContentObserver,
                 UserHandle.USER_CURRENT);
-        mSecureSettings.registerContentObserverForUser(
-                mSecureSettings.getUriFor(ENABLED_ACCESSIBILITY_SERVICES),
-                /* notifyForDescendants */ false,
-                mMenuTargetFeaturesContentObserver,
-                UserHandle.USER_CURRENT);
+        if (!com.android.systemui.Flags.floatingMenuNarrowTargetContentObserver()) {
+            mSecureSettings.registerContentObserverForUser(
+                    mSecureSettings.getUriFor(ENABLED_ACCESSIBILITY_SERVICES),
+                    /* notifyForDescendants */ false,
+                    mMenuTargetFeaturesContentObserver,
+                    UserHandle.USER_CURRENT);
+        }
         mSecureSettings.registerContentObserverForUser(
                 mSecureSettings.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE),
                 /* notifyForDescendants */ false, mMenuSizeContentObserver,
@@ -263,8 +265,10 @@
                 UserHandle.USER_CURRENT);
         mContext.registerComponentCallbacks(mComponentCallbacks);
 
-        mAccessibilityManager.addAccessibilityServicesStateChangeListener(
-                mA11yServicesStateChangeListener);
+        if (!com.android.systemui.Flags.floatingMenuNarrowTargetContentObserver()) {
+            mAccessibilityManager.addAccessibilityServicesStateChangeListener(
+                    mA11yServicesStateChangeListener);
+        }
     }
 
     void unregisterObserversAndCallbacks() {
@@ -273,8 +277,10 @@
         mContext.getContentResolver().unregisterContentObserver(mMenuFadeOutContentObserver);
         mContext.unregisterComponentCallbacks(mComponentCallbacks);
 
-        mAccessibilityManager.removeAccessibilityServicesStateChangeListener(
-                mA11yServicesStateChangeListener);
+        if (!com.android.systemui.Flags.floatingMenuNarrowTargetContentObserver()) {
+            mAccessibilityManager.removeAccessibilityServicesStateChangeListener(
+                    mA11yServicesStateChangeListener);
+        }
     }
 
     interface OnSettingsContentsChanged {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
index 96eb4b3..7b5a09cb 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
@@ -21,6 +21,8 @@
 
 import static java.util.Collections.emptyList;
 
+import android.bluetooth.BluetoothHapClient;
+import android.bluetooth.BluetoothHapPresetInfo;
 import android.content.Context;
 import android.content.Intent;
 import android.media.AudioManager;
@@ -30,7 +32,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.Visibility;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -40,17 +46,21 @@
 
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HapClientProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.systemui.accessibility.hearingaid.HearingDevicesListAdapter.HearingDeviceItemCallback;
 import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.bluetooth.qsdialog.ActiveHearingDeviceItemFactory;
+import com.android.systemui.bluetooth.qsdialog.AvailableHearingDeviceItemFactory;
+import com.android.systemui.bluetooth.qsdialog.ConnectedDeviceItemFactory;
+import com.android.systemui.bluetooth.qsdialog.DeviceItem;
+import com.android.systemui.bluetooth.qsdialog.DeviceItemFactory;
+import com.android.systemui.bluetooth.qsdialog.DeviceItemType;
+import com.android.systemui.bluetooth.qsdialog.SavedHearingDeviceItemFactory;
+import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.tiles.dialog.bluetooth.ActiveHearingDeviceItemFactory;
-import com.android.systemui.qs.tiles.dialog.bluetooth.AvailableHearingDeviceItemFactory;
-import com.android.systemui.qs.tiles.dialog.bluetooth.ConnectedDeviceItemFactory;
-import com.android.systemui.qs.tiles.dialog.bluetooth.DeviceItem;
-import com.android.systemui.qs.tiles.dialog.bluetooth.DeviceItemFactory;
-import com.android.systemui.qs.tiles.dialog.bluetooth.SavedHearingDeviceItemFactory;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
@@ -80,11 +90,37 @@
     private final LocalBluetoothManager mLocalBluetoothManager;
     private final Handler mMainHandler;
     private final AudioManager mAudioManager;
-
+    private final LocalBluetoothProfileManager mProfileManager;
+    private final HapClientProfile mHapClientProfile;
     private HearingDevicesListAdapter mDeviceListAdapter;
+    private HearingDevicesPresetsController mPresetsController;
+    private Context mApplicationContext;
     private SystemUIDialog mDialog;
     private RecyclerView mDeviceList;
+    private List<DeviceItem> mHearingDeviceItemList;
+    private Spinner mPresetSpinner;
+    private ArrayAdapter<String> mPresetInfoAdapter;
     private Button mPairButton;
+    private final HearingDevicesPresetsController.PresetCallback mPresetCallback =
+            new HearingDevicesPresetsController.PresetCallback() {
+                @Override
+                public void onPresetInfoUpdated(List<BluetoothHapPresetInfo> presetInfos,
+                        int activePresetIndex) {
+                    mMainHandler.post(
+                            () -> refreshPresetInfoAdapter(presetInfos, activePresetIndex));
+                }
+
+                @Override
+                public void onPresetCommandFailed(int reason) {
+                    final List<BluetoothHapPresetInfo> presetInfos =
+                            mPresetsController.getAllPresetInfo();
+                    final int activePresetIndex = mPresetsController.getActivePresetIndex();
+                    mMainHandler.post(() -> {
+                        refreshPresetInfoAdapter(presetInfos, activePresetIndex);
+                        showPresetErrorToast(mApplicationContext);
+                    });
+                }
+            };
     private final List<DeviceItemFactory> mHearingDeviceItemFactoryList = List.of(
             new ActiveHearingDeviceItemFactory(),
             new AvailableHearingDeviceItemFactory(),
@@ -107,6 +143,7 @@
 
     @AssistedInject
     public HearingDevicesDialogDelegate(
+            @Application Context applicationContext,
             @Assisted boolean showPairNewDevice,
             SystemUIDialog.Factory systemUIDialogFactory,
             ActivityStarter activityStarter,
@@ -114,6 +151,7 @@
             @Nullable LocalBluetoothManager localBluetoothManager,
             @Main Handler handler,
             AudioManager audioManager) {
+        mApplicationContext = applicationContext;
         mShowPairNewDevice = showPairNewDevice;
         mSystemUIDialogFactory = systemUIDialogFactory;
         mActivityStarter = activityStarter;
@@ -121,6 +159,8 @@
         mLocalBluetoothManager = localBluetoothManager;
         mMainHandler = handler;
         mAudioManager = audioManager;
+        mProfileManager = localBluetoothManager.getProfileManager();
+        mHapClientProfile = mProfileManager.getHapClientProfile();
     }
 
     @Override
@@ -158,19 +198,34 @@
     @Override
     public void onActiveDeviceChanged(@Nullable CachedBluetoothDevice activeDevice,
             int bluetoothProfile) {
-        mMainHandler.post(() -> mDeviceListAdapter.refreshDeviceItemList(getHearingDevicesList()));
+        CachedBluetoothDevice activeHearingDevice;
+        mHearingDeviceItemList = getHearingDevicesList();
+        if (mPresetsController != null) {
+            activeHearingDevice = getActiveHearingDevice(mHearingDeviceItemList);
+            mPresetsController.setActiveHearingDevice(activeHearingDevice);
+        } else {
+            activeHearingDevice = null;
+        }
+        mMainHandler.post(() -> {
+            mDeviceListAdapter.refreshDeviceItemList(mHearingDeviceItemList);
+            mPresetSpinner.setVisibility(
+                    (activeHearingDevice != null && !mPresetInfoAdapter.isEmpty()) ? VISIBLE
+                            : GONE);
+        });
     }
 
     @Override
     public void onProfileConnectionStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
             int state, int bluetoothProfile) {
-        mMainHandler.post(() -> mDeviceListAdapter.refreshDeviceItemList(getHearingDevicesList()));
+        mHearingDeviceItemList = getHearingDevicesList();
+        mMainHandler.post(() -> mDeviceListAdapter.refreshDeviceItemList(mHearingDeviceItemList));
     }
 
     @Override
     public void onAclConnectionStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
             int state) {
-        mMainHandler.post(() -> mDeviceListAdapter.refreshDeviceItemList(getHearingDevicesList()));
+        mHearingDeviceItemList = getHearingDevicesList();
+        mMainHandler.post(() -> mDeviceListAdapter.refreshDeviceItemList(mHearingDeviceItemList));
     }
 
     @Override
@@ -187,10 +242,15 @@
 
     @Override
     public void onCreate(@NonNull SystemUIDialog dialog, @Nullable Bundle savedInstanceState) {
+        if (mLocalBluetoothManager == null) {
+            return;
+        }
         mPairButton = dialog.requireViewById(R.id.pair_new_device_button);
         mDeviceList = dialog.requireViewById(R.id.device_list);
+        mPresetSpinner = dialog.requireViewById(R.id.preset_spinner);
 
         setupDeviceListView(dialog);
+        setupPresetSpinner(dialog);
         setupPairNewDeviceButton(dialog, mShowPairNewDevice ? VISIBLE : GONE);
     }
 
@@ -199,7 +259,14 @@
         if (mLocalBluetoothManager == null) {
             return;
         }
+
         mLocalBluetoothManager.getEventManager().registerCallback(this);
+        if (mPresetsController != null) {
+            mPresetsController.registerHapCallback();
+            if (mHapClientProfile != null && !mHapClientProfile.isProfileReady()) {
+                mProfileManager.addServiceListener(mPresetsController);
+            }
+        }
     }
 
     @Override
@@ -207,15 +274,51 @@
         if (mLocalBluetoothManager == null) {
             return;
         }
+
+        if (mPresetsController != null) {
+            mPresetsController.unregisterHapCallback();
+            mProfileManager.removeServiceListener(mPresetsController);
+        }
         mLocalBluetoothManager.getEventManager().unregisterCallback(this);
     }
 
     private void setupDeviceListView(SystemUIDialog dialog) {
         mDeviceList.setLayoutManager(new LinearLayoutManager(dialog.getContext()));
-        mDeviceListAdapter = new HearingDevicesListAdapter(getHearingDevicesList(), this);
+        mHearingDeviceItemList = getHearingDevicesList();
+        mDeviceListAdapter = new HearingDevicesListAdapter(mHearingDeviceItemList, this);
         mDeviceList.setAdapter(mDeviceListAdapter);
     }
 
+    private void setupPresetSpinner(SystemUIDialog dialog) {
+        mPresetsController = new HearingDevicesPresetsController(mProfileManager, mPresetCallback);
+        final CachedBluetoothDevice activeHearingDevice = getActiveHearingDevice(
+                mHearingDeviceItemList);
+        mPresetsController.setActiveHearingDevice(activeHearingDevice);
+
+        mPresetInfoAdapter = new ArrayAdapter<>(dialog.getContext(),
+                android.R.layout.simple_spinner_dropdown_item);
+        mPresetInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mPresetSpinner.setAdapter(mPresetInfoAdapter);
+        mPresetSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                mPresetsController.selectPreset(
+                        mPresetsController.getAllPresetInfo().get(position).getIndex());
+                mPresetSpinner.setSelection(position);
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+                // Do nothing
+            }
+        });
+        final List<BluetoothHapPresetInfo> presetInfos = mPresetsController.getAllPresetInfo();
+        final int activePresetIndex = mPresetsController.getActivePresetIndex();
+        refreshPresetInfoAdapter(presetInfos, activePresetIndex);
+        mPresetSpinner.setVisibility(
+                (activeHearingDevice != null && !mPresetInfoAdapter.isEmpty()) ? VISIBLE : GONE);
+    }
+
     private void setupPairNewDeviceButton(SystemUIDialog dialog, @Visibility int visibility) {
         if (visibility == VISIBLE) {
             mPairButton.setOnClickListener(v -> {
@@ -230,6 +333,21 @@
         }
     }
 
+    private void refreshPresetInfoAdapter(List<BluetoothHapPresetInfo> presetInfos,
+            int activePresetIndex) {
+        mPresetInfoAdapter.clear();
+        mPresetInfoAdapter.addAll(
+                presetInfos.stream().map(BluetoothHapPresetInfo::getName).toList());
+        if (activePresetIndex != BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) {
+            final int size = mPresetInfoAdapter.getCount();
+            for (int position = 0; position < size; position++) {
+                if (presetInfos.get(position).getIndex() == activePresetIndex) {
+                    mPresetSpinner.setSelection(position);
+                }
+            }
+        }
+    }
+
     private List<DeviceItem> getHearingDevicesList() {
         if (mLocalBluetoothManager == null
                 || !mLocalBluetoothManager.getBluetoothAdapter().isEnabled()) {
@@ -242,6 +360,15 @@
                 .collect(Collectors.toList());
     }
 
+    @Nullable
+    private CachedBluetoothDevice getActiveHearingDevice(List<DeviceItem> hearingDeviceItemList) {
+        return hearingDeviceItemList.stream()
+                .filter(item -> item.getType() == DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
+                .map(DeviceItem::getCachedBluetoothDevice)
+                .findFirst()
+                .orElse(null);
+    }
+
     private DeviceItem createHearingDeviceItem(CachedBluetoothDevice cachedDevice) {
         final Context context = mDialog.getContext();
         if (cachedDevice == null) {
@@ -260,4 +387,8 @@
             mDialog.dismiss();
         }
     }
+
+    private void showPresetErrorToast(Context context) {
+        Toast.makeText(context, R.string.hearing_devices_presets_error, Toast.LENGTH_SHORT).show();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java
index 695d04f..737805b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java
@@ -27,7 +27,7 @@
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.systemui.qs.tiles.dialog.bluetooth.DeviceItem;
+import com.android.systemui.bluetooth.qsdialog.DeviceItem;
 import com.android.systemui.res.R;
 
 import kotlin.Pair;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesPresetsController.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesPresetsController.java
new file mode 100644
index 0000000..02fa003
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesPresetsController.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import static java.util.Collections.emptyList;
+
+import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHapClient;
+import android.bluetooth.BluetoothHapPresetInfo;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HapClientProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.List;
+
+/**
+ * The controller of the hearing devices presets of the bluetooth Hearing Access Profile.
+ */
+public class HearingDevicesPresetsController implements
+        LocalBluetoothProfileManager.ServiceListener, BluetoothHapClient.Callback {
+
+    private static final String TAG = "HearingDevicesPresetsController";
+    private static final boolean DEBUG = true;
+
+    private final LocalBluetoothProfileManager mProfileManager;
+    private final HapClientProfile mHapClientProfile;
+    private final PresetCallback mPresetCallback;
+
+    private CachedBluetoothDevice mActiveHearingDevice;
+    private int mSelectedPresetIndex;
+
+    public HearingDevicesPresetsController(LocalBluetoothProfileManager profileManager,
+            PresetCallback presetCallback) {
+        mProfileManager = profileManager;
+        mHapClientProfile = mProfileManager.getHapClientProfile();
+        mPresetCallback = presetCallback;
+    }
+
+    @Override
+    public void onServiceConnected() {
+        if (mHapClientProfile != null && mHapClientProfile.isProfileReady()) {
+            mProfileManager.removeServiceListener(this);
+            registerHapCallback();
+            mPresetCallback.onPresetInfoUpdated(getAllPresetInfo(), getActivePresetIndex());
+        }
+    }
+
+    @Override
+    public void onServiceDisconnected() {
+        // Do nothing
+    }
+
+    @Override
+    public void onPresetSelected(@NonNull BluetoothDevice device, int presetIndex, int reason) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (device.equals(mActiveHearingDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG, "onPresetSelected, device: " + device.getAddress()
+                        + ", presetIndex: " + presetIndex + ", reason: " + reason);
+            }
+            mPresetCallback.onPresetInfoUpdated(getAllPresetInfo(), getActivePresetIndex());
+        }
+    }
+
+    @Override
+    public void onPresetInfoChanged(@NonNull BluetoothDevice device,
+            @NonNull List<BluetoothHapPresetInfo> presetInfoList, int reason) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (device.equals(mActiveHearingDevice.getDevice())) {
+            if (DEBUG) {
+                Log.d(TAG, "onPresetInfoChanged, device: " + device.getAddress()
+                        + ", reason: " + reason + ", infoList: " + presetInfoList);
+            }
+            mPresetCallback.onPresetInfoUpdated(getAllPresetInfo(), getActivePresetIndex());
+        }
+    }
+
+    @Override
+    public void onPresetSelectionFailed(@NonNull BluetoothDevice device, int reason) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (device.equals(mActiveHearingDevice.getDevice())) {
+            Log.w(TAG, "onPresetSelectionFailed, device: " + device.getAddress()
+                    + ", reason: " + reason);
+            mPresetCallback.onPresetCommandFailed(reason);
+        }
+    }
+
+    @Override
+    public void onPresetSelectionForGroupFailed(int hapGroupId, int reason) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (hapGroupId == mHapClientProfile.getHapGroup(mActiveHearingDevice.getDevice())) {
+            Log.w(TAG, "onPresetSelectionForGroupFailed, group: " + hapGroupId
+                    + ", reason: " + reason);
+            selectPresetIndependently(mSelectedPresetIndex);
+        }
+    }
+
+    @Override
+    public void onSetPresetNameFailed(@NonNull BluetoothDevice device, int reason) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (device.equals(mActiveHearingDevice.getDevice())) {
+            Log.w(TAG, "onSetPresetNameFailed, device: " + device.getAddress()
+                    + ", reason: " + reason);
+            mPresetCallback.onPresetCommandFailed(reason);
+        }
+    }
+
+    @Override
+    public void onSetPresetNameForGroupFailed(int hapGroupId, int reason) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (hapGroupId == mHapClientProfile.getHapGroup(mActiveHearingDevice.getDevice())) {
+            Log.w(TAG, "onSetPresetNameForGroupFailed, group: " + hapGroupId
+                    + ", reason: " + reason);
+        }
+        mPresetCallback.onPresetCommandFailed(reason);
+    }
+
+    /**
+     * Registers a callback to be notified about operation changed for {@link HapClientProfile}.
+     */
+    public void registerHapCallback() {
+        if (mHapClientProfile != null) {
+            try {
+                mHapClientProfile.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
+            } catch (IllegalArgumentException e) {
+                // The callback was already registered
+                Log.w(TAG, "Cannot register callback: " + e.getMessage());
+            }
+
+        }
+    }
+
+    /**
+     * Removes a previously-added {@link HapClientProfile} callback.
+     */
+    public void unregisterHapCallback() {
+        if (mHapClientProfile != null) {
+            try {
+                mHapClientProfile.unregisterCallback(this);
+            } catch (IllegalArgumentException e) {
+                // The callback was never registered or was already unregistered
+                Log.w(TAG, "Cannot unregister callback: " + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Sets the hearing device for this controller to control the preset.
+     *
+     * @param activeHearingDevice the {@link CachedBluetoothDevice} need to be hearing aid device
+     */
+    public void setActiveHearingDevice(CachedBluetoothDevice activeHearingDevice) {
+        mActiveHearingDevice = activeHearingDevice;
+    }
+
+    /**
+     * Selects the currently active preset for {@code mActiveHearingDevice} individual device or
+     * the device group accoridng to whether it supports synchronized presets or not.
+     *
+     * @param presetIndex an index of one of the available presets
+     */
+    public void selectPreset(int presetIndex) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        mSelectedPresetIndex = presetIndex;
+        boolean supportSynchronizedPresets = mHapClientProfile.supportsSynchronizedPresets(
+                mActiveHearingDevice.getDevice());
+        int hapGroupId = mHapClientProfile.getHapGroup(mActiveHearingDevice.getDevice());
+        if (supportSynchronizedPresets) {
+            if (hapGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+                selectPresetSynchronously(hapGroupId, presetIndex);
+            } else {
+                Log.w(TAG, "supportSynchronizedPresets but hapGroupId is invalid.");
+                selectPresetIndependently(presetIndex);
+            }
+        } else {
+            selectPresetIndependently(presetIndex);
+        }
+    }
+
+    /**
+     * Gets all preset info for {@code mActiveHearingDevice} device.
+     *
+     * @return a list of all known preset info
+     */
+    public List<BluetoothHapPresetInfo> getAllPresetInfo() {
+        if (mActiveHearingDevice == null) {
+            return emptyList();
+        }
+        return mHapClientProfile.getAllPresetInfo(mActiveHearingDevice.getDevice());
+    }
+
+    /**
+     * Gets the currently active preset for {@code mActiveHearingDevice} device.
+     *
+     * @return active preset index
+     */
+    public int getActivePresetIndex() {
+        if (mActiveHearingDevice == null) {
+            return BluetoothHapClient.PRESET_INDEX_UNAVAILABLE;
+        }
+        return mHapClientProfile.getActivePresetIndex(mActiveHearingDevice.getDevice());
+    }
+
+    private void selectPresetSynchronously(int groupId, int presetIndex) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "selectPresetSynchronously"
+                    + ", presetIndex: " + presetIndex
+                    + ", groupId: " + groupId
+                    + ", device: " + mActiveHearingDevice.getAddress());
+        }
+        mHapClientProfile.selectPresetForGroup(groupId, presetIndex);
+    }
+
+    private void selectPresetIndependently(int presetIndex) {
+        if (mActiveHearingDevice == null) {
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "selectPresetIndependently"
+                    + ", presetIndex: " + presetIndex
+                    + ", device: " + mActiveHearingDevice.getAddress());
+        }
+        mHapClientProfile.selectPreset(mActiveHearingDevice.getDevice(), presetIndex);
+        final CachedBluetoothDevice subDevice = mActiveHearingDevice.getSubDevice();
+        if (subDevice != null) {
+            if (DEBUG) {
+                Log.d(TAG, "selectPreset for subDevice, device: " + subDevice);
+            }
+            mHapClientProfile.selectPreset(subDevice.getDevice(), presetIndex);
+        }
+        for (final CachedBluetoothDevice memberDevice :
+                mActiveHearingDevice.getMemberDevice()) {
+            if (DEBUG) {
+                Log.d(TAG, "selectPreset for memberDevice, device: " + memberDevice);
+            }
+            mHapClientProfile.selectPreset(memberDevice.getDevice(), presetIndex);
+        }
+    }
+
+    /**
+     * Interface to provide callbacks when preset command result from {@link HapClientProfile}
+     * changed.
+     */
+    public interface PresetCallback {
+        /**
+         * Called when preset info from {@link HapClientProfile} operation get updated.
+         *
+         * @param presetInfos all preset info for {@code mActiveHearingDevice} device
+         * @param activePresetIndex currently active preset index for {@code mActiveHearingDevice}
+         *                          device
+         */
+        void onPresetInfoUpdated(List<BluetoothHapPresetInfo> presetInfos, int activePresetIndex);
+
+        /**
+         * Called when preset operation from {@link HapClientProfile} failed to handle.
+         *
+         * @param reason failure reason
+         */
+        void onPresetCommandFailed(int reason);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
index 7cb028a..b8ff0c0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.accessibility.qs
 
+import com.android.systemui.Flags
 import com.android.systemui.qs.QsEventLogger
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tileimpl.QSTileImpl
@@ -40,9 +41,14 @@
 import com.android.systemui.qs.tiles.impl.inversion.domain.interactor.ColorInversionTileDataInteractor
 import com.android.systemui.qs.tiles.impl.inversion.domain.interactor.ColorInversionUserActionInteractor
 import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor.ReduceBrightColorsTileDataInteractor
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor.ReduceBrightColorsTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.android.systemui.qs.tiles.impl.reducebrightness.ui.ReduceBrightColorsTileMapper
 import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
 import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
 import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
+import com.android.systemui.qs.tiles.viewmodel.StubQSTileViewModel
 import com.android.systemui.res.R
 import dagger.Binds
 import dagger.Module
@@ -105,6 +111,7 @@
         const val COLOR_CORRECTION_TILE_SPEC = "color_correction"
         const val COLOR_INVERSION_TILE_SPEC = "inversion"
         const val FONT_SCALING_TILE_SPEC = "font_scaling"
+        const val REDUCE_BRIGHTNESS_TILE_SPEC = "reduce_brightness"
 
         @Provides
         @IntoMap
@@ -198,5 +205,41 @@
                 stateInteractor,
                 mapper,
             )
+
+        @Provides
+        @IntoMap
+        @StringKey(REDUCE_BRIGHTNESS_TILE_SPEC)
+        fun provideReduceBrightColorsTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(REDUCE_BRIGHTNESS_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.qs_extra_dim_icon_on,
+                        labelRes = com.android.internal.R.string.reduce_bright_colors_feature_name,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+
+        /**
+         * Inject Reduce Bright Colors Tile into tileViewModelMap in QSModule. The tile is hidden
+         * behind a flag.
+         */
+        @Provides
+        @IntoMap
+        @StringKey(REDUCE_BRIGHTNESS_TILE_SPEC)
+        fun provideReduceBrightColorsTileViewModel(
+            factory: QSTileViewModelFactory.Static<ReduceBrightColorsTileModel>,
+            mapper: ReduceBrightColorsTileMapper,
+            stateInteractor: ReduceBrightColorsTileDataInteractor,
+            userActionInteractor: ReduceBrightColorsTileUserActionInteractor
+        ): QSTileViewModel =
+            if (Flags.qsNewTilesFuture())
+                factory.create(
+                    TileSpec.create(REDUCE_BRIGHTNESS_TILE_SPEC),
+                    userActionInteractor,
+                    stateInteractor,
+                    mapper,
+                )
+            else StubQSTileViewModel
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS b/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS
new file mode 100644
index 0000000..b65d29c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ailabs/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 1495344
+
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
new file mode 100644
index 0000000..ea00398
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.dagger
+
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
+import com.android.systemui.ambient.touch.dagger.InputSessionComponent
+import dagger.Module
+
+@Module(subcomponents = [AmbientTouchComponent::class, InputSessionComponent::class])
+interface AmbientModule {
+    companion object {
+        const val TOUCH_HANDLERS = "touch_handlers"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
new file mode 100644
index 0000000..85aeb27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.Flags;
+import com.android.systemui.ambient.touch.dagger.BouncerSwipeModule;
+import com.android.systemui.ambient.touch.scrim.ScrimController;
+import com.android.systemui.ambient.touch.scrim.ScrimManager;
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * Monitor for tracking touches on the DreamOverlay to bring up the bouncer.
+ */
+public class BouncerSwipeTouchHandler implements TouchHandler {
+    /**
+     * An interface for creating ValueAnimators.
+     */
+    public interface ValueAnimatorCreator {
+        /**
+         * Creates {@link ValueAnimator}.
+         */
+        ValueAnimator create(float start, float finish);
+    }
+
+    /**
+     * An interface for obtaining VelocityTrackers.
+     */
+    public interface VelocityTrackerFactory {
+        /**
+         * Obtains {@link VelocityTracker}.
+         */
+        VelocityTracker obtain();
+    }
+
+    public static final float FLING_PERCENTAGE_THRESHOLD = 0.5f;
+
+    private static final String TAG = "BouncerSwipeTouchHandler";
+    private final NotificationShadeWindowController mNotificationShadeWindowController;
+    private final LockPatternUtils mLockPatternUtils;
+    private final UserTracker mUserTracker;
+    private final float mBouncerZoneScreenPercentage;
+    private final float mMinBouncerZoneScreenPercentage;
+
+    private final ScrimManager mScrimManager;
+    private ScrimController mCurrentScrimController;
+    private float mCurrentExpansion;
+    private final Optional<CentralSurfaces> mCentralSurfaces;
+
+    private VelocityTracker mVelocityTracker;
+
+    private final FlingAnimationUtils mFlingAnimationUtils;
+    private final FlingAnimationUtils mFlingAnimationUtilsClosing;
+
+    private Boolean mCapture;
+    private Boolean mExpanded;
+
+    private TouchSession mTouchSession;
+
+    private final ValueAnimatorCreator mValueAnimatorCreator;
+
+    private final VelocityTrackerFactory mVelocityTrackerFactory;
+
+    private final UiEventLogger mUiEventLogger;
+
+    private final ScrimManager.Callback mScrimManagerCallback = new ScrimManager.Callback() {
+        @Override
+        public void onScrimControllerChanged(ScrimController controller) {
+            if (mCurrentScrimController != null) {
+                mCurrentScrimController.reset();
+            }
+
+            mCurrentScrimController = controller;
+        }
+    };
+
+    private final GestureDetector.OnGestureListener mOnGestureListener =
+            new GestureDetector.SimpleOnGestureListener() {
+                @Override
+                public boolean onScroll(MotionEvent e1, @NonNull MotionEvent e2, float distanceX,
+                        float distanceY) {
+                    if (mCapture == null) {
+                        if (Flags.dreamOverlayBouncerSwipeDirectionFiltering()) {
+                            mCapture = Math.abs(distanceY) > Math.abs(distanceX)
+                                    && distanceY > 0;
+                        } else {
+                            // If the user scrolling favors a vertical direction, begin capturing
+                            // scrolls.
+                            mCapture = Math.abs(distanceY) > Math.abs(distanceX);
+                        }
+                        if (mCapture) {
+                            // reset expanding
+                            mExpanded = false;
+                            // Since the user is dragging the bouncer up, set scrimmed to false.
+                            mCurrentScrimController.show();
+                        }
+                    }
+
+                    if (!mCapture) {
+                        return false;
+                    }
+
+                    // Don't set expansion for downward scroll.
+                    if (e1.getY() < e2.getY()) {
+                        return true;
+                    }
+
+                    if (!mCentralSurfaces.isPresent()) {
+                        return true;
+                    }
+
+                    // If scrolling up and keyguard is not locked, dismiss the dream since there's
+                    // no bouncer to show.
+                    if (e1.getY() > e2.getY()
+                            && !mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
+                        mCentralSurfaces.get().awakenDreams();
+                        return true;
+                    }
+
+                    // For consistency, we adopt the expansion definition found in the
+                    // PanelViewController. In this case, expansion refers to the view above the
+                    // bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer
+                    // is fully hidden at full expansion (1) and fully visible when fully collapsed
+                    // (0).
+                    final float dragDownAmount = e2.getY() - e1.getY();
+                    final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY())
+                            / mTouchSession.getBounds().height();
+                    setPanelExpansion(1 - screenTravelPercentage);
+                    return true;
+                }
+            };
+
+    private void setPanelExpansion(float expansion) {
+        mCurrentExpansion = expansion;
+        ShadeExpansionChangeEvent event =
+                new ShadeExpansionChangeEvent(
+                        /* fraction= */ mCurrentExpansion,
+                        /* expanded= */ mExpanded,
+                        /* tracking= */ true);
+        mCurrentScrimController.expand(event);
+    }
+
+
+    @VisibleForTesting
+    public enum DreamEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "The screensaver has been swiped up.")
+        DREAM_SWIPED(988),
+
+        @UiEvent(doc = "The bouncer has become fully visible over dream.")
+        DREAM_BOUNCER_FULLY_VISIBLE(1056);
+
+        private final int mId;
+
+        DreamEvent(int id) {
+            mId = id;
+        }
+
+        @Override
+        public int getId() {
+            return mId;
+        }
+    }
+
+    @Inject
+    public BouncerSwipeTouchHandler(
+            ScrimManager scrimManager,
+            Optional<CentralSurfaces> centralSurfaces,
+            NotificationShadeWindowController notificationShadeWindowController,
+            ValueAnimatorCreator valueAnimatorCreator,
+            VelocityTrackerFactory velocityTrackerFactory,
+            LockPatternUtils lockPatternUtils,
+            UserTracker userTracker,
+            @Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
+            FlingAnimationUtils flingAnimationUtils,
+            @Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
+            FlingAnimationUtils flingAnimationUtilsClosing,
+            @Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage,
+            @Named(BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage,
+            UiEventLogger uiEventLogger) {
+        mCentralSurfaces = centralSurfaces;
+        mScrimManager = scrimManager;
+        mNotificationShadeWindowController = notificationShadeWindowController;
+        mLockPatternUtils = lockPatternUtils;
+        mUserTracker = userTracker;
+        mBouncerZoneScreenPercentage = swipeRegionPercentage;
+        mMinBouncerZoneScreenPercentage = minRegionPercentage;
+        mFlingAnimationUtils = flingAnimationUtils;
+        mFlingAnimationUtilsClosing = flingAnimationUtilsClosing;
+        mValueAnimatorCreator = valueAnimatorCreator;
+        mVelocityTrackerFactory = velocityTrackerFactory;
+        mUiEventLogger = uiEventLogger;
+    }
+
+    @Override
+    public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
+        final int width = bounds.width();
+        final int height = bounds.height();
+        final int minAllowableBottom = Math.round(height * (1 - mMinBouncerZoneScreenPercentage));
+
+        final Rect normalRegion = new Rect(0,
+                Math.round(height * (1 - mBouncerZoneScreenPercentage)),
+                width, height);
+
+        if (exclusionRect != null) {
+            int lowestBottom = Math.min(Math.max(0, exclusionRect.bottom), minAllowableBottom);
+            normalRegion.top = Math.max(normalRegion.top, lowestBottom);
+        }
+        region.union(normalRegion);
+    }
+
+
+    @Override
+    public void onSessionStart(TouchSession session) {
+        mVelocityTracker = mVelocityTrackerFactory.obtain();
+        mTouchSession = session;
+        mVelocityTracker.clear();
+        mNotificationShadeWindowController.setForcePluginOpen(true, this);
+        mScrimManager.addCallback(mScrimManagerCallback);
+        mCurrentScrimController = mScrimManager.getCurrentController();
+
+        session.registerCallback(() -> {
+            if (mVelocityTracker != null) {
+                mVelocityTracker.recycle();
+                mVelocityTracker = null;
+            }
+            mScrimManager.removeCallback(mScrimManagerCallback);
+            mCapture = null;
+            mNotificationShadeWindowController.setForcePluginOpen(false, this);
+        });
+
+        session.registerGestureListener(mOnGestureListener);
+        session.registerInputListener(ev -> onMotionEvent(ev));
+
+    }
+
+    private void onMotionEvent(InputEvent event) {
+        if (!(event instanceof MotionEvent)) {
+            Log.e(TAG, "non MotionEvent received:" + event);
+            return;
+        }
+
+        final MotionEvent motionEvent = (MotionEvent) event;
+
+        switch (motionEvent.getAction()) {
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                mTouchSession.pop();
+                // If we are not capturing any input, there is no need to consider animating to
+                // finish transition.
+                if (mCapture == null || !mCapture) {
+                    break;
+                }
+
+                // We must capture the resulting velocities as resetMonitor() will clear these
+                // values.
+                mVelocityTracker.computeCurrentVelocity(1000);
+                final float verticalVelocity = mVelocityTracker.getYVelocity();
+                final float horizontalVelocity = mVelocityTracker.getXVelocity();
+
+                final float velocityVector =
+                        (float) Math.hypot(horizontalVelocity, verticalVelocity);
+
+                mExpanded = !flingRevealsOverlay(verticalVelocity, velocityVector);
+                final float expansion = mExpanded
+                        ? KeyguardBouncerConstants.EXPANSION_VISIBLE
+                        : KeyguardBouncerConstants.EXPANSION_HIDDEN;
+
+                // Log the swiping up to show Bouncer event.
+                if (expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
+                    mUiEventLogger.log(DreamEvent.DREAM_SWIPED);
+                }
+
+                flingToExpansion(verticalVelocity, expansion);
+                break;
+            default:
+                mVelocityTracker.addMovement(motionEvent);
+                break;
+        }
+    }
+
+    private ValueAnimator createExpansionAnimator(float targetExpansion) {
+        final ValueAnimator animator =
+                mValueAnimatorCreator.create(mCurrentExpansion, targetExpansion);
+        animator.addUpdateListener(
+                animation -> {
+                    float expansionFraction = (float) animation.getAnimatedValue();
+                    setPanelExpansion(expansionFraction);
+                });
+        if (targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
+            animator.addListener(
+                    new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            mUiEventLogger.log(DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
+                        }
+                    });
+        }
+        return animator;
+    }
+
+    protected boolean flingRevealsOverlay(float velocity, float velocityVector) {
+        // Fully expand the space above the bouncer, if the user has expanded the bouncer less
+        // than halfway or final velocity was positive, indicating a downward direction.
+        if (Math.abs(velocityVector) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+            return mCurrentExpansion > FLING_PERCENTAGE_THRESHOLD;
+        } else {
+            return velocity > 0;
+        }
+    }
+
+    protected void flingToExpansion(float velocity, float expansion) {
+        if (!mCentralSurfaces.isPresent()) {
+            return;
+        }
+
+        // Don't set expansion if the user doesn't have a pin/password set.
+        if (!mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
+            return;
+        }
+
+        // The animation utils deal in pixel units, rather than expansion height.
+        final float viewHeight = mTouchSession.getBounds().height();
+        final float currentHeight = viewHeight * mCurrentExpansion;
+        final float targetHeight = viewHeight * expansion;
+        final ValueAnimator animator = createExpansionAnimator(expansion);
+        if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
+            // Hides the bouncer, i.e., fully expands the space above the bouncer.
+            mFlingAnimationUtilsClosing.apply(animator, currentHeight, targetHeight, velocity,
+                    viewHeight);
+        } else {
+            // Shows the bouncer, i.e., fully collapses the space above the bouncer.
+            mFlingAnimationUtils.apply(
+                    animator, currentHeight, targetHeight, velocity, viewHeight);
+        }
+
+        animator.start();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/InputSession.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/InputSession.java
new file mode 100644
index 0000000..6a76c87
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/InputSession.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.PILFER_ON_GESTURE_CONSUME;
+
+import android.os.Looper;
+import android.view.Choreographer;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+import com.android.systemui.Flags;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * {@link InputSession} encapsulates components behind input monitoring and handles their lifecycle.
+ * Sessions are meant to be disposable; actions such as exclusively capturing touch events is modal
+ * and destroying the sessions allows a reset. Additionally, {@link InputSession} is meant to have
+ * a single listener for input and gesture. Any broadcasting must be accomplished elsewhere.
+ */
+public class InputSession {
+    private final InputMonitorCompat mInputMonitor;
+    private final InputChannelCompat.InputEventReceiver mInputEventReceiver;
+    private final GestureDetector mGestureDetector;
+
+    // Pilfering is a destructive operation. Once pilfering starts, the all events will be captured
+    // by the associated monitor. We track whether we're pilfering since initiating pilfering
+    // requires reaching out to the InputManagerService, which can be a heavy operation. This is
+    // especially costly if this is happening on a continuous stream of motion events.
+    private boolean mPilfering;
+
+    /**
+     * Default session constructor.
+     * @param inputMonitor Input monitor to track input events.
+     * @param gestureDetector Gesture detector for detecting gestures.
+     * @param inputEventListener A listener to receive input events.
+     * @param choreographer Choreographer to use with the input receiver.
+     * @param looper Looper to use with the input receiver
+     * @param pilferOnGestureConsume Whether touch events should be pilfered after a gesture has
+     *                               been consumed.
+     */
+    @Inject
+    public InputSession(
+            InputMonitorCompat inputMonitor,
+            GestureDetector gestureDetector,
+            InputChannelCompat.InputEventListener inputEventListener,
+            Choreographer choreographer,
+            @Main Looper looper,
+            @Named(PILFER_ON_GESTURE_CONSUME) boolean pilferOnGestureConsume) {
+        mInputMonitor = inputMonitor;
+        mGestureDetector = gestureDetector;
+
+        mInputEventReceiver = mInputMonitor.getInputReceiver(looper, choreographer,
+                ev -> {
+                    // Process event. Since sometimes input may be a prerequisite for some
+                    // gesture logic, process input first.
+                    inputEventListener.onInputEvent(ev);
+
+                    if (ev instanceof MotionEvent
+                            && mGestureDetector.onTouchEvent((MotionEvent) ev)
+                            && pilferOnGestureConsume
+                            && !(mPilfering && Flags.dreamInputSessionPilferOnce())) {
+                        mPilfering = true;
+                        mInputMonitor.pilferPointers();
+                    }
+                });
+    }
+
+    /**
+     * Destroys the {@link InputSession}, removing any component from listening to future touch
+     * events.
+     */
+    public void dispose() {
+        if (mInputEventReceiver != null) {
+            mInputEventReceiver.dispose();
+        }
+
+        if (mInputMonitor != null) {
+            mInputMonitor.dispose();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java
new file mode 100644
index 0000000..9c7fc9d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import static com.android.systemui.ambient.touch.dagger.ShadeModule.NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * {@link ShadeTouchHandler} is responsible for handling swipe down gestures over dream
+ * to bring down the shade.
+ */
+public class ShadeTouchHandler implements TouchHandler {
+    private final Optional<CentralSurfaces> mSurfaces;
+    private final int mInitiationHeight;
+
+    /**
+     * Tracks whether or not we are capturing a given touch. Will be null before and after a touch.
+     */
+    private Boolean mCapture;
+
+    @Inject
+    ShadeTouchHandler(Optional<CentralSurfaces> centralSurfaces,
+            @Named(NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT) int initiationHeight) {
+        mSurfaces = centralSurfaces;
+        mInitiationHeight = initiationHeight;
+    }
+
+    @Override
+    public void onSessionStart(TouchSession session) {
+        if (mSurfaces.isEmpty()) {
+            session.pop();
+            return;
+        }
+
+        session.registerCallback(() -> mCapture = null);
+
+        session.registerInputListener(ev -> {
+            if (ev instanceof MotionEvent) {
+                if (mCapture != null && mCapture) {
+                    mSurfaces.get().handleExternalShadeWindowTouch((MotionEvent) ev);
+                }
+                if (((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) {
+                    session.pop();
+                }
+            }
+        });
+
+        session.registerGestureListener(new GestureDetector.SimpleOnGestureListener() {
+            @Override
+            public boolean onScroll(MotionEvent e1, @NonNull MotionEvent e2, float distanceX,
+                    float distanceY) {
+                if (mCapture == null) {
+                    // Only capture swipes that are going downwards.
+                    mCapture = Math.abs(distanceY) > Math.abs(distanceX) && distanceY < 0;
+                    if (mCapture) {
+                        // Send the initial touches over, as the input listener has already
+                        // processed these touches.
+                        mSurfaces.get().handleExternalShadeWindowTouch(e1);
+                        mSurfaces.get().handleExternalShadeWindowTouch(e2);
+                    }
+                }
+                return mCapture;
+            }
+
+            @Override
+            public boolean onFling(MotionEvent e1, @NonNull MotionEvent e2, float velocityX,
+                    float velocityY) {
+                return mCapture;
+            }
+        });
+    }
+
+    @Override
+    public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
+        final Rect outBounds = new Rect(bounds);
+        outBounds.inset(0, 0, 0, outBounds.height() - mInitiationHeight);
+        region.op(outBounds, Region.Op.UNION);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchHandler.java
new file mode 100644
index 0000000..190bc15
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchHandler.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.view.GestureDetector;
+
+import com.android.systemui.shared.system.InputChannelCompat;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The {@link TouchHandler} interface provides a way for dream overlay components to observe
+ * touch events and gestures with the ability to intercept the latter. Touch interaction sequences
+ * are abstracted as sessions. A session represents the time of first
+ * {@code android.view.MotionEvent.ACTION_DOWN} event to the last {@link TouchHandler}
+ * stopping interception of gestures. If no gesture is intercepted, the session continues
+ * indefinitely. {@link TouchHandler} have the ability to create a stack of sessions, which
+ * allows for motion logic to be captured in modal states.
+ */
+public interface TouchHandler {
+    /**
+     * A touch session captures the interaction surface of a {@link TouchHandler}. Clients
+     * register listeners as desired to participate in motion/gesture callbacks.
+     */
+    interface TouchSession {
+        interface Callback {
+            /**
+             * Invoked when the session has been removed.
+             */
+            void onRemoved();
+        }
+
+        /**
+         * Registers a callback to be notified when there are updates to the {@link TouchSession}.
+         */
+        void registerCallback(Callback callback);
+
+        /**
+         * Adds a input event listener for the given session.
+         * @param inputEventListener
+         */
+        boolean registerInputListener(InputChannelCompat.InputEventListener inputEventListener);
+
+        /**
+         * Adds a gesture listener for the given session.
+         * @param gestureListener
+         */
+        boolean registerGestureListener(GestureDetector.OnGestureListener gestureListener);
+
+        /**
+         * Creates a new {@link TouchSession} that will receive any updates that would have been
+         * directed to this {@link TouchSession}.
+         * @return The future which will return a new {@link TouchSession} that will receive
+         * subsequent events. If the operation fails, {@code null} will be returned.
+         */
+        ListenableFuture<TouchSession> push();
+
+        /**
+         * Explicitly releases this {@link TouchSession}. The registered listeners will no longer
+         * receive any further updates.
+         * @return The future containing the {@link TouchSession} that will receive subsequent
+         * events. This session will be the direct predecessor of the popped session. {@code null}
+         * if the popped {@link TouchSession} was the initial session or has already been popped.
+         */
+        ListenableFuture<TouchSession> pop();
+
+        /**
+         * Returns the number of currently active sessions.
+         */
+        int getActiveSessionCount();
+
+        /**
+         * Returns the bounds of the display the touch region.
+         */
+        Rect getBounds();
+    }
+
+    /**
+     * Returns whether the handler is enabled to handle touch on dream.
+     * @return isEnabled state. By default it's true.
+     */
+    default Boolean isEnabled() {
+        return true;
+    }
+
+    /**
+     * Sets whether to enable the handler to handle touch on dream.
+     * @param enabled new value to be set whether to enable the handler.
+     */
+    default void setIsEnabled(Boolean enabled){}
+
+    /**
+     * Returns the region the touch handler is interested in. By default, no region is specified,
+     * indicating the entire screen should be considered.
+     * @param region A {@link Region} that is passed in to the target entry touch region.
+     */
+    default void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
+    }
+
+    /**
+     * Informed a new touch session has begun. The first touch event will be delivered to any
+     * listener registered through
+     * {@link TouchSession#registerInputListener(InputChannelCompat.InputEventListener)} during this
+     * call. If there are no interactions with this touch session after this method returns, it will
+     * be dropped.
+     * @param session
+     */
+    void onSessionStart(TouchSession session);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
new file mode 100644
index 0000000..e7e12ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.systemui.shared.Flags.bouncerAreaExclusion;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.ISystemGestureExclusionListener;
+import android.view.IWindowManager;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.DisplayId;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.util.display.DisplayHelper;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import javax.inject.Inject;
+
+/**
+ * {@link TouchMonitor} is responsible for monitoring touches and gestures over the
+ * dream overlay and redirecting them to a set of listeners. This monitor is in charge of figuring
+ * out when listeners are eligible for receiving touches and filtering the listener pool if
+ * touches are consumed.
+ */
+public class TouchMonitor {
+    // This executor is used to protect {@code mActiveTouchSessions} from being modified
+    // concurrently. Any operation that adds or removes values should use this executor.
+    public String TAG = "DreamOverlayTouchMonitor";
+    private final Executor mMainExecutor;
+    private final Executor mBackgroundExecutor;
+    private final Lifecycle mLifecycle;
+    private Rect mExclusionRect = null;
+
+    private ISystemGestureExclusionListener mGestureExclusionListener =
+            new ISystemGestureExclusionListener.Stub() {
+                @Override
+                public void onSystemGestureExclusionChanged(int displayId,
+                        Region systemGestureExclusion,
+                        Region systemGestureExclusionUnrestricted) {
+                    mExclusionRect = systemGestureExclusion.getBounds();
+                }
+            };
+
+
+    /**
+     * Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures.
+     */
+    private ListenableFuture<TouchHandler.TouchSession> push(
+            TouchSessionImpl touchSessionImpl) {
+        return CallbackToFutureAdapter.getFuture(completer -> {
+            mMainExecutor.execute(() -> {
+                if (!mActiveTouchSessions.remove(touchSessionImpl)) {
+                    completer.set(null);
+                    return;
+                }
+
+                final TouchSessionImpl touchSession =
+                        new TouchSessionImpl(this, touchSessionImpl.getBounds(),
+                                touchSessionImpl);
+                mActiveTouchSessions.add(touchSession);
+                completer.set(touchSession);
+            });
+
+            return "DreamOverlayTouchMonitor::push";
+        });
+    }
+
+    /**
+     * Removes a {@link TouchSessionImpl} from receiving further updates.
+     */
+    private ListenableFuture<TouchHandler.TouchSession> pop(
+            TouchSessionImpl touchSessionImpl) {
+        return CallbackToFutureAdapter.getFuture(completer -> {
+            mMainExecutor.execute(() -> {
+                if (mActiveTouchSessions.remove(touchSessionImpl)) {
+                    touchSessionImpl.onRemoved();
+
+                    final TouchSessionImpl predecessor = touchSessionImpl.getPredecessor();
+
+                    if (predecessor != null) {
+                        mActiveTouchSessions.add(predecessor);
+                    }
+
+                    completer.set(predecessor);
+                }
+
+                if (mActiveTouchSessions.isEmpty() && mStopMonitoringPending) {
+                    stopMonitoring(false);
+                }
+            });
+
+            return "DreamOverlayTouchMonitor::pop";
+        });
+    }
+
+    private int getSessionCount() {
+        return mActiveTouchSessions.size();
+    }
+
+    /**
+     * {@link TouchSessionImpl} implements {@link TouchHandler.TouchSession} for
+     * {@link TouchMonitor}. It enables the monitor to access the associated listeners
+     * and provides the associated client with access to the monitor.
+     */
+    private static class TouchSessionImpl implements TouchHandler.TouchSession {
+        private final HashSet<InputChannelCompat.InputEventListener> mEventListeners =
+                new HashSet<>();
+        private final HashSet<GestureDetector.OnGestureListener> mGestureListeners =
+                new HashSet<>();
+        private final HashSet<Callback> mCallbacks = new HashSet<>();
+
+        private final TouchSessionImpl mPredecessor;
+        private final TouchMonitor mTouchMonitor;
+        private final Rect mBounds;
+
+        TouchSessionImpl(TouchMonitor touchMonitor, Rect bounds,
+                TouchSessionImpl predecessor) {
+            mPredecessor = predecessor;
+            mTouchMonitor = touchMonitor;
+            mBounds = bounds;
+        }
+
+        @Override
+        public void registerCallback(Callback callback) {
+            mCallbacks.add(callback);
+        }
+
+        @Override
+        public boolean registerInputListener(
+                InputChannelCompat.InputEventListener inputEventListener) {
+            return mEventListeners.add(inputEventListener);
+        }
+
+        @Override
+        public boolean registerGestureListener(GestureDetector.OnGestureListener gestureListener) {
+            return mGestureListeners.add(gestureListener);
+        }
+
+        @Override
+        public ListenableFuture<TouchHandler.TouchSession> push() {
+            return mTouchMonitor.push(this);
+        }
+
+        @Override
+        public ListenableFuture<TouchHandler.TouchSession> pop() {
+            return mTouchMonitor.pop(this);
+        }
+
+        @Override
+        public int getActiveSessionCount() {
+            return mTouchMonitor.getSessionCount();
+        }
+
+        /**
+         * Returns the active listeners to receive touch events.
+         */
+        public Collection<InputChannelCompat.InputEventListener> getEventListeners() {
+            return mEventListeners;
+        }
+
+        /**
+         * Returns the active listeners to receive gesture events.
+         */
+        public Collection<GestureDetector.OnGestureListener> getGestureListeners() {
+            return mGestureListeners;
+        }
+
+        /**
+         * Returns the {@link TouchSessionImpl} that preceded this current session. This will
+         * become the new active session when this session is popped.
+         */
+        private TouchSessionImpl getPredecessor() {
+            return mPredecessor;
+        }
+
+        /**
+         * Called by the monitor when this session is removed.
+         */
+        private void onRemoved() {
+            mEventListeners.clear();
+            mGestureListeners.clear();
+            final Iterator<Callback> iter = mCallbacks.iterator();
+            while (iter.hasNext()) {
+                final Callback callback = iter.next();
+                callback.onRemoved();
+                iter.remove();
+            }
+        }
+
+        @Override
+        public Rect getBounds() {
+            return mBounds;
+        }
+    }
+
+    /**
+     * This lifecycle observer ensures touch monitoring only occurs while the overlay is "resumed".
+     * This concept is mapped over from the equivalent view definition: The {@link LifecycleOwner}
+     * will report the dream is not resumed when it is obscured (from the notification shade being
+     * expanded for example) or not active (such as when it is destroyed).
+     */
+    private final LifecycleObserver mLifecycleObserver = new DefaultLifecycleObserver() {
+        @Override
+        public void onResume(@NonNull LifecycleOwner owner) {
+            startMonitoring();
+        }
+
+        @Override
+        public void onPause(@NonNull LifecycleOwner owner) {
+            stopMonitoring(false);
+        }
+
+        @Override
+        public void onDestroy(LifecycleOwner owner) {
+            stopMonitoring(true);
+        }
+    };
+
+    /**
+     * When invoked, instantiates a new {@link InputSession} to monitor touch events.
+     */
+    private void startMonitoring() {
+        stopMonitoring(true);
+        if (bouncerAreaExclusion()) {
+            mBackgroundExecutor.execute(() -> {
+                try {
+                    mWindowManagerService.registerSystemGestureExclusionListener(
+                            mGestureExclusionListener, mDisplayId);
+                } catch (RemoteException e) {
+                    // Handle the exception
+                    Log.e(TAG, "Failed to register gesture exclusion listener", e);
+                }
+            });
+        }
+        mCurrentInputSession = mInputSessionFactory.create(
+                        "dreamOverlay",
+                        mInputEventListener,
+                        mOnGestureListener,
+                        true)
+                .getInputSession();
+    }
+
+    /**
+     * Destroys any active {@link InputSession}.
+     */
+    private void stopMonitoring(boolean force) {
+        mExclusionRect = null;
+        if (bouncerAreaExclusion()) {
+            mBackgroundExecutor.execute(() -> {
+                try {
+                    mWindowManagerService.unregisterSystemGestureExclusionListener(
+                            mGestureExclusionListener, mDisplayId);
+                } catch (RemoteException e) {
+                    // Handle the exception
+                    Log.e(TAG, "unregisterSystemGestureExclusionListener: failed", e);
+                }
+            });
+        }
+        if (mCurrentInputSession == null) {
+            return;
+        }
+
+        if (!mActiveTouchSessions.isEmpty() && !force) {
+            mStopMonitoringPending = true;
+            return;
+        }
+
+        // When we stop monitoring touches, we must ensure that all active touch sessions and
+        // descendants informed of the removal so any cleanup for active tracking can proceed.
+        mMainExecutor.execute(() -> mActiveTouchSessions.forEach(touchSession -> {
+            while (touchSession != null) {
+                touchSession.onRemoved();
+                touchSession = touchSession.getPredecessor();
+            }
+        }));
+
+        mCurrentInputSession.dispose();
+        mCurrentInputSession = null;
+        mStopMonitoringPending = false;
+    }
+
+
+    private final HashSet<TouchSessionImpl> mActiveTouchSessions = new HashSet<>();
+    private final Collection<TouchHandler> mHandlers;
+    private final DisplayHelper mDisplayHelper;
+
+    private boolean mStopMonitoringPending;
+
+    private InputChannelCompat.InputEventListener mInputEventListener =
+            new InputChannelCompat.InputEventListener() {
+                @Override
+                public void onInputEvent(InputEvent ev) {
+                    // No Active sessions are receiving touches. Create sessions for each listener
+                    if (mActiveTouchSessions.isEmpty()) {
+                        final HashMap<TouchHandler, TouchHandler.TouchSession> sessionMap =
+                                new HashMap<>();
+
+                        for (TouchHandler handler : mHandlers) {
+                            if (!handler.isEnabled()) {
+                                continue;
+                            }
+                            final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(),
+                                    TYPE_APPLICATION_OVERLAY);
+                            final Region initiationRegion = Region.obtain();
+                            Rect exclusionRect = null;
+                            if (bouncerAreaExclusion()) {
+                                exclusionRect = getCurrentExclusionRect();
+                            }
+                            handler.getTouchInitiationRegion(
+                                    maxBounds, initiationRegion, exclusionRect);
+
+                            if (!initiationRegion.isEmpty()) {
+                                // Initiation regions require a motion event to determine pointer
+                                // location
+                                // within the region.
+                                if (!(ev instanceof MotionEvent)) {
+                                    continue;
+                                }
+
+                                final MotionEvent motionEvent = (MotionEvent) ev;
+
+                                // If the touch event is outside the region, then ignore.
+                                if (!initiationRegion.contains(Math.round(motionEvent.getX()),
+                                        Math.round(motionEvent.getY()))) {
+                                    continue;
+                                }
+                            }
+
+                            final TouchSessionImpl sessionStack = new TouchSessionImpl(
+                                    TouchMonitor.this, maxBounds, null);
+                            mActiveTouchSessions.add(sessionStack);
+                            sessionMap.put(handler, sessionStack);
+                        }
+
+                        // Informing handlers of new sessions is delayed until we have all
+                        // created so the
+                        // final session is correct.
+                        sessionMap.forEach((dreamTouchHandler, touchSession)
+                                -> dreamTouchHandler.onSessionStart(touchSession));
+                    }
+
+                    // Find active sessions and invoke on InputEvent.
+                    mActiveTouchSessions.stream()
+                            .map(touchSessionStack -> touchSessionStack.getEventListeners())
+                            .flatMap(Collection::stream)
+                            .forEach(inputEventListener -> inputEventListener.onInputEvent(ev));
+                }
+
+                private Rect getCurrentExclusionRect() {
+                    return mExclusionRect;
+                }
+            };
+
+    /**
+     * The {@link Evaluator} interface allows for callers to inspect a listener from the
+     * {@link android.view.GestureDetector.OnGestureListener} set. This helps reduce duplicated
+     * iteration loops over this set.
+     */
+    private interface Evaluator {
+        boolean evaluate(GestureDetector.OnGestureListener listener);
+    }
+
+    private GestureDetector.OnGestureListener mOnGestureListener =
+            new GestureDetector.OnGestureListener() {
+                private boolean evaluate(Evaluator evaluator) {
+                    final Set<TouchSessionImpl> consumingSessions = new HashSet<>();
+
+                    // When a gesture is consumed, it is assumed that all touches for the current
+                    // session
+                    // should be directed only to those TouchSessions until those sessions are
+                    // popped. All
+                    // non-participating sessions are removed from receiving further updates with
+                    // {@link DreamOverlayTouchMonitor#isolate}.
+                    final boolean eventConsumed = mActiveTouchSessions.stream()
+                            .map(touchSession -> {
+                                boolean consume = touchSession.getGestureListeners()
+                                        .stream()
+                                        .map(listener -> evaluator.evaluate(listener))
+                                        .anyMatch(consumed -> consumed);
+
+                                if (consume) {
+                                    consumingSessions.add(touchSession);
+                                }
+                                return consume;
+                            }).anyMatch(consumed -> consumed);
+
+                    if (eventConsumed) {
+                        TouchMonitor.this.isolate(consumingSessions);
+                    }
+
+                    return eventConsumed;
+                }
+
+                // This method is called for gesture events that cannot be consumed.
+                private void observe(Consumer<GestureDetector.OnGestureListener> consumer) {
+                    mActiveTouchSessions.stream()
+                            .map(touchSession -> touchSession.getGestureListeners())
+                            .flatMap(Collection::stream)
+                            .forEach(listener -> consumer.accept(listener));
+                }
+
+                @Override
+                public boolean onDown(MotionEvent e) {
+                    return evaluate(listener -> listener.onDown(e));
+                }
+
+                @Override
+                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+                        float velocityY) {
+                    return evaluate(listener -> listener.onFling(e1, e2, velocityX, velocityY));
+                }
+
+                @Override
+                public void onLongPress(MotionEvent e) {
+                    observe(listener -> listener.onLongPress(e));
+                }
+
+                @Override
+                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+                        float distanceY) {
+                    return evaluate(listener -> listener.onScroll(e1, e2, distanceX, distanceY));
+                }
+
+                @Override
+                public void onShowPress(MotionEvent e) {
+                    observe(listener -> listener.onShowPress(e));
+                }
+
+                @Override
+                public boolean onSingleTapUp(MotionEvent e) {
+                    return evaluate(listener -> listener.onSingleTapUp(e));
+                }
+            };
+
+    private InputSessionComponent.Factory mInputSessionFactory;
+    private InputSession mCurrentInputSession;
+    private final int mDisplayId;
+    private final IWindowManager mWindowManagerService;
+
+
+    /**
+     * Designated constructor for {@link TouchMonitor}
+     *
+     * @param executor            This executor will be used for maintaining the active listener
+     *                            list to avoid
+     *                            concurrent modification.
+     * @param lifecycle           {@link TouchMonitor} will listen to this lifecycle to determine
+     *                            whether touch monitoring should be active.
+     * @param inputSessionFactory This factory will generate the {@link InputSession} requested by
+     *                            the monitor. Each session should be unique and valid when
+     *                            returned.
+     * @param handlers            This set represents the {@link TouchHandler} instances that will
+     *                            participate in touch handling.
+     */
+    @Inject
+    public TouchMonitor(
+            @Main Executor executor,
+            @Background Executor backgroundExecutor,
+            Lifecycle lifecycle,
+            InputSessionComponent.Factory inputSessionFactory,
+            DisplayHelper displayHelper,
+            Set<TouchHandler> handlers,
+            IWindowManager windowManagerService,
+            @DisplayId int displayId) {
+        mDisplayId = displayId;
+        mHandlers = handlers;
+        mInputSessionFactory = inputSessionFactory;
+        mMainExecutor = executor;
+        mBackgroundExecutor = backgroundExecutor;
+        mLifecycle = lifecycle;
+        mDisplayHelper = displayHelper;
+        mWindowManagerService = windowManagerService;
+    }
+
+    /**
+     * Initializes the monitor. should only be called once after creation.
+     */
+    public void init() {
+        mLifecycle.addObserver(mLifecycleObserver);
+    }
+
+    private void isolate(Set<TouchSessionImpl> sessions) {
+        Collection<TouchSessionImpl> removedSessions = mActiveTouchSessions.stream()
+                .filter(touchSession -> !sessions.contains(touchSession))
+                .collect(Collectors.toCollection(HashSet::new));
+
+        removedSessions.forEach(touchSession -> touchSession.onRemoved());
+
+        mActiveTouchSessions.removeAll(removedSessions);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
new file mode 100644
index 0000000..390e53b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.ambient.touch.dagger
+
+import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.ambient.dagger.AmbientModule.Companion.TOUCH_HANDLERS
+import com.android.systemui.ambient.touch.TouchHandler
+import com.android.systemui.ambient.touch.TouchMonitor
+import dagger.BindsInstance
+import dagger.Subcomponent
+import javax.inject.Named
+
+/**
+ * {@link AmbientTouchComponent} can be used for setting up a touch environment over the entire
+ * display surface. This allows for implementing behaviors such as swiping up to bring up the
+ * bouncer.
+ */
+@Subcomponent(modules = [AmbientTouchModule::class, ShadeModule::class, BouncerSwipeModule::class])
+interface AmbientTouchComponent {
+    @Subcomponent.Factory
+    interface Factory {
+        fun create(
+            @BindsInstance lifecycleOwner: LifecycleOwner,
+            @BindsInstance
+            @Named(TOUCH_HANDLERS)
+            touchHandlers: Set<@JvmSuppressWildcards TouchHandler>
+        ): AmbientTouchComponent
+    }
+
+    /** Builds a [TouchMonitor] */
+    fun getTouchMonitor(): TouchMonitor
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchModule.kt
new file mode 100644
index 0000000..a4924d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchModule.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.ambient.touch.dagger
+
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.ambient.dagger.AmbientModule
+import com.android.systemui.ambient.touch.TouchHandler
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.ElementsIntoSet
+import javax.inject.Named
+
+@Module
+interface AmbientTouchModule {
+    companion object {
+        @JvmStatic
+        @Provides
+        fun providesLifecycle(lifecycleOwner: LifecycleOwner): Lifecycle {
+            return lifecycleOwner.lifecycle
+        }
+
+        @Provides
+        @ElementsIntoSet
+        fun providesDreamTouchHandlers(
+            @Named(AmbientModule.TOUCH_HANDLERS)
+            touchHandlers: Set<@JvmSuppressWildcards TouchHandler>
+        ): Set<@JvmSuppressWildcards TouchHandler> {
+            return touchHandlers
+        }
+
+        const val INPUT_SESSION_NAME = "INPUT_SESSION_NAME"
+        const val PILFER_ON_GESTURE_CONSUME = "PILFER_ON_GESTURE_CONSUME"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/BouncerSwipeModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/BouncerSwipeModule.java
new file mode 100644
index 0000000..dac2d8e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/BouncerSwipeModule.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.dagger;
+
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.util.TypedValue;
+import android.view.VelocityTracker;
+
+import com.android.systemui.ambient.touch.BouncerSwipeTouchHandler;
+import com.android.systemui.ambient.touch.TouchHandler;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
+import com.android.systemui.shade.ShadeViewController;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.IntoSet;
+
+import javax.inject.Named;
+import javax.inject.Provider;
+
+/**
+ * This module captures the components associated with {@link BouncerSwipeTouchHandler}.
+ */
+@Module
+public class BouncerSwipeModule {
+    /**
+     * The region, defined as the percentage of the screen, from which a touch gesture to start
+     * swiping up to the bouncer can occur.
+     */
+    public static final String SWIPE_TO_BOUNCER_START_REGION = "swipe_to_bouncer_start_region";
+
+    public static final String MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE =
+            "min_bouncer_zone_screen_percentage";
+
+    /**
+     * The {@link android.view.animation.AnimationUtils} for animating the bouncer closing.
+     */
+    public static final String SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING =
+            "swipe_to_bouncer_fling_animation_utils_closing";
+
+    /**
+     * The {@link android.view.animation.AnimationUtils} for animating the bouncer opening.
+     */
+    public static final String SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING =
+                    "swipe_to_bouncer_fling_animation_utils_opening";
+
+    /**
+     * Provides {@link BouncerSwipeTouchHandler} for inclusion in touch handling over the dream.
+     */
+    @Provides
+    @IntoSet
+    public static TouchHandler providesBouncerSwipeTouchHandler(
+            BouncerSwipeTouchHandler touchHandler) {
+        return touchHandler;
+    }
+
+    /**
+     * Provides {@link android.view.animation.AnimationUtils} for closing.
+     */
+    @Provides
+    @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
+    public static FlingAnimationUtils providesSwipeToBouncerFlingAnimationUtilsClosing(
+            Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
+        return flingAnimationUtilsBuilderProvider.get()
+                .reset()
+                .setMaxLengthSeconds(
+                        ShadeViewController.FLING_CLOSING_MAX_LENGTH_SECONDS)
+                .setSpeedUpFactor(ShadeViewController.FLING_SPEED_UP_FACTOR)
+                .build();
+    }
+
+    /**
+     * Provides {@link android.view.animation.AnimationUtils} for opening.
+     */
+    @Provides
+    @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
+    public static FlingAnimationUtils providesSwipeToBouncerFlingAnimationUtilsOpening(
+            Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
+        return flingAnimationUtilsBuilderProvider.get()
+                .reset()
+                .setMaxLengthSeconds(ShadeViewController.FLING_MAX_LENGTH_SECONDS)
+                .setSpeedUpFactor(ShadeViewController.FLING_SPEED_UP_FACTOR)
+                .build();
+    }
+
+    /**
+     * Provides the region to start swipe gestures from.
+     */
+    @Provides
+    @Named(SWIPE_TO_BOUNCER_START_REGION)
+    public static float providesSwipeToBouncerStartRegion(@Main Resources resources) {
+        TypedValue typedValue = new TypedValue();
+        resources.getValue(R.dimen.dream_overlay_bouncer_start_region_screen_percentage,
+                typedValue, true);
+        return typedValue.getFloat();
+    }
+
+    /**
+     * Provides the minimum region to start wipe gestures from.
+     */
+    @Provides
+    @Named(MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE)
+    public static float providesMinBouncerZoneScreenPercentage(@Main Resources resources) {
+        TypedValue typedValue = new TypedValue();
+        resources.getValue(R.dimen.dream_overlay_bouncer_min_region_screen_percentage,
+                typedValue, true);
+        return typedValue.getFloat();
+    }
+
+    /**
+     * Provides the default {@link BouncerSwipeTouchHandler.ValueAnimatorCreator}, which is simply
+     * a wrapper around {@link ValueAnimator}.
+     */
+    @Provides
+    public static BouncerSwipeTouchHandler.ValueAnimatorCreator providesValueAnimatorCreator() {
+        return (start, finish) -> ValueAnimator.ofFloat(start, finish);
+    }
+
+    /**
+     * Provides the default {@link BouncerSwipeTouchHandler.VelocityTrackerFactory}. which is a
+     * passthrough to {@link android.view.VelocityTracker}.
+     */
+    @Provides
+    public static BouncerSwipeTouchHandler.VelocityTrackerFactory providesVelocityTrackerFactory() {
+        return () -> VelocityTracker.obtain();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionComponent.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionComponent.java
new file mode 100644
index 0000000..203fb64
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionComponent.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.dagger;
+
+import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.INPUT_SESSION_NAME;
+import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.PILFER_ON_GESTURE_CONSUME;
+
+import android.view.GestureDetector;
+
+import com.android.systemui.ambient.touch.InputSession;
+import com.android.systemui.shared.system.InputChannelCompat;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+import javax.inject.Named;
+
+/**
+ * {@link InputSessionComponent} generates {@link InputSession} with specific instances bound for
+ * the session name and whether touches should be pilfered when consumed.
+ */
+@Subcomponent(
+        modules = { InputSessionModule.class }
+)
+public interface InputSessionComponent {
+    /**
+     * Generates {@link InputSessionComponent}.
+     */
+    @Subcomponent.Factory
+    interface Factory {
+        /** */
+        InputSessionComponent create(@Named(INPUT_SESSION_NAME) @BindsInstance String name,
+                @BindsInstance InputChannelCompat.InputEventListener inputEventListener,
+                @BindsInstance GestureDetector.OnGestureListener gestureListener,
+                @Named(PILFER_ON_GESTURE_CONSUME) @BindsInstance boolean pilferOnGestureConsume);
+    }
+
+    /** */
+    InputSession getInputSession();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java
new file mode 100644
index 0000000..99dbdee
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.dagger;
+
+import static com.android.systemui.ambient.touch.dagger.AmbientTouchModule.INPUT_SESSION_NAME;
+
+import android.view.GestureDetector;
+
+import com.android.systemui.settings.DisplayTracker;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+import dagger.Module;
+import dagger.Provides;
+
+import javax.inject.Named;
+
+
+/**
+ * Module for providing dependencies to {@link com.android.systemui.dreams.touch.InputSession}.
+ */
+@Module
+public interface InputSessionModule {
+    /** */
+    @Provides
+    static InputMonitorCompat providesInputMonitorCompat(@Named(INPUT_SESSION_NAME) String name,
+            DisplayTracker displayTracker) {
+        return new InputMonitorCompat(name, displayTracker.getDefaultDisplayId());
+    }
+
+    /** */
+    @Provides
+    static GestureDetector providesGestureDetector(
+            android.view.GestureDetector.OnGestureListener gestureListener) {
+        return new GestureDetector(gestureListener);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java
new file mode 100644
index 0000000..bc2f354
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/ShadeModule.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.dagger;
+
+import android.content.res.Resources;
+
+import com.android.systemui.ambient.touch.ShadeTouchHandler;
+import com.android.systemui.ambient.touch.TouchHandler;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.IntoSet;
+
+import javax.inject.Named;
+
+/**
+ * Dependencies for swipe down to notification over dream.
+ */
+@Module
+public abstract class ShadeModule {
+    /**
+     * The height, defined in pixels, of the gesture initiation region at the top of the screen for
+     * swiping down notifications.
+     */
+    public static final String NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT =
+            "notification_shade_gesture_initiation_height";
+
+    /**
+     * Provides {@link ShadeTouchHandler} to handle notification swipe down over dream.
+     */
+    @Binds
+    @IntoSet
+    public abstract TouchHandler providesNotificationShadeTouchHandler(
+            ShadeTouchHandler touchHandler);
+
+    /**
+     * Provides the height of the gesture area for notification swipe down.
+     */
+    @Provides
+    @Named(NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT)
+    public static int providesNotificationShadeGestureRegionHeight(@Main Resources resources) {
+        return resources.getDimensionPixelSize(R.dimen.dream_overlay_status_bar_height);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java
new file mode 100644
index 0000000..94c9982
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim;
+
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+
+import javax.inject.Inject;
+
+/**
+ * Implementation for handling swipe movements on the overlay when the keyguard is present.
+ */
+public class BouncerScrimController implements ScrimController {
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+
+    @Inject
+    BouncerScrimController(StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+    }
+
+    @Override
+    public void show() {
+        mStatusBarKeyguardViewManager.showPrimaryBouncer(false);
+    }
+
+    @Override
+    public void expand(ShadeExpansionChangeEvent event) {
+        mStatusBarKeyguardViewManager.onPanelExpansionChanged(event);
+    }
+
+    @Override
+    public void reset() {
+        mStatusBarKeyguardViewManager.reset(false);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimController.java
new file mode 100644
index 0000000..c453ddb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerlessScrimController.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim;
+
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
+import com.android.systemui.unfold.util.CallbackController;
+
+import java.util.HashSet;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * {@link BouncerlessScrimController} handles scrim progression when no keyguard is set. When
+ * fully expanded, the controller dismisses the dream.
+ */
+@SysUISingleton
+public class BouncerlessScrimController implements ScrimController,
+        CallbackController<BouncerlessScrimController.Callback> {
+    private static final String TAG = "BLScrimController";
+
+    /**
+     * {@link Callback} allows {@link BouncerlessScrimController} clients to be informed of
+     * expansion progression and wakeup
+     */
+    public interface Callback {
+        /**
+         * Invoked when there is a change to the scrim expansion.
+         */
+        void onExpansion(ShadeExpansionChangeEvent event);
+
+        /**
+         * Invoked after {@link BouncerlessScrimController} has started waking up the device.
+         */
+        void onWakeup();
+    }
+
+    private final Executor mExecutor;
+    private final PowerManager mPowerManager;
+
+    @Override
+    public void addCallback(Callback listener) {
+        mExecutor.execute(() -> mCallbacks.add(listener));
+    }
+
+    @Override
+    public void removeCallback(Callback listener) {
+        mExecutor.execute(() -> mCallbacks.remove(listener));
+    }
+
+    private final HashSet<Callback> mCallbacks;
+
+
+    @Inject
+    public BouncerlessScrimController(@Main Executor executor,
+            PowerManager powerManager) {
+        mExecutor = executor;
+        mPowerManager = powerManager;
+        mCallbacks = new HashSet<>();
+    }
+
+    @Override
+    public void expand(ShadeExpansionChangeEvent event) {
+        if (event.getExpanded())  {
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+                    "com.android.systemui:SwipeUp");
+            mExecutor.execute(() -> mCallbacks.forEach(callback -> callback.onWakeup()));
+        } else {
+            mExecutor.execute(() -> mCallbacks.forEach(callback -> callback.onExpansion(event)));
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java
new file mode 100644
index 0000000..0054352
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim;
+
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
+
+/**
+ * {@link ScrimController} provides an interface for the different consumers of scrolling/expansion
+ * events over the dream.
+ */
+public interface ScrimController {
+    /**
+     * Called at the start of expansion before any expansion amount updates.
+     */
+    default void show() {
+    }
+
+    /**
+     * Called for every expansion update.
+     * @param event {@link ShadeExpansionChangeEvent} detailing the change.
+     */
+    default void expand(ShadeExpansionChangeEvent event) {
+    }
+
+    /**
+     * Called at the end of the movement.
+     */
+    default void reset() {
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimManager.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimManager.java
new file mode 100644
index 0000000..676221d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimManager.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim;
+
+import static com.android.systemui.ambient.touch.scrim.dagger.ScrimModule.BOUNCERLESS_SCRIM_CONTROLLER;
+import static com.android.systemui.ambient.touch.scrim.dagger.ScrimModule.BOUNCER_SCRIM_CONTROLLER;
+
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import java.util.HashSet;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * {@link ScrimManager} helps manage multiple {@link ScrimController} instances, specifying the
+ * appropriate one to use at the current moment and managing the handoff between controllers.
+ */
+public class ScrimManager {
+    private final ScrimController mBouncerScrimController;
+    private final ScrimController mBouncerlessScrimController;
+    private final KeyguardStateController mKeyguardStateController;
+    private final Executor mExecutor;
+
+    private ScrimController mCurrentController;
+    private final HashSet<Callback> mCallbacks;
+
+    /**
+     * Interface implemented for receiving updates to the active {@link ScrimController}.
+     */
+    public interface Callback {
+        /**
+         * Invoked when the controller changes.
+         * @param controller The currently active {@link ScrimController}.
+         */
+        void onScrimControllerChanged(ScrimController controller);
+    }
+
+    private final KeyguardStateController.Callback mKeyguardStateCallback =
+            new KeyguardStateController.Callback() {
+                @Override
+                public void onKeyguardShowingChanged() {
+                    mExecutor.execute(() -> updateController());
+                }
+            };
+
+    @Inject
+    ScrimManager(@Main Executor executor,
+            @Named(BOUNCER_SCRIM_CONTROLLER) ScrimController bouncerScrimController,
+            @Named(BOUNCERLESS_SCRIM_CONTROLLER)ScrimController bouncerlessScrimController,
+            KeyguardStateController keyguardStateController) {
+        mExecutor = executor;
+        mCallbacks = new HashSet<>();
+        mBouncerlessScrimController = bouncerlessScrimController;
+        mBouncerScrimController = bouncerScrimController;
+        mKeyguardStateController = keyguardStateController;
+
+        mKeyguardStateController.addCallback(mKeyguardStateCallback);
+        updateController();
+    }
+
+    private void updateController() {
+        final ScrimController existingController = mCurrentController;
+        mCurrentController =  mKeyguardStateController.canDismissLockScreen()
+                ? mBouncerlessScrimController
+                : mBouncerScrimController;
+
+        if (existingController == mCurrentController) {
+            return;
+        }
+
+        mCallbacks.forEach(callback -> callback.onScrimControllerChanged(mCurrentController));
+    }
+
+    /**
+     * Adds a {@link Callback} to receive future changes to the active {@link ScrimController}.
+     */
+    public void addCallback(Callback callback) {
+        mExecutor.execute(() -> mCallbacks.add(callback));
+    }
+
+    /**
+     * Removes the {@link Callback} from receiving further updates.
+     */
+    public void removeCallback(Callback callback) {
+        mExecutor.execute(() -> mCallbacks.remove(callback));
+    }
+
+    /**
+     * Returns the currently get {@link ScrimController}.
+     * @return
+     */
+    public ScrimController getCurrentController() {
+        return mCurrentController;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/dagger/ScrimModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/dagger/ScrimModule.java
new file mode 100644
index 0000000..b07029b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/dagger/ScrimModule.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch.scrim.dagger;
+
+import com.android.systemui.ambient.touch.scrim.BouncerScrimController;
+import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController;
+import com.android.systemui.ambient.touch.scrim.ScrimController;
+
+import dagger.Module;
+import dagger.Provides;
+
+import javax.inject.Named;
+
+/**
+ * Module for scrim related dependencies.
+ */
+@Module
+public interface ScrimModule {
+    String BOUNCERLESS_SCRIM_CONTROLLER = "bouncerless_scrim_controller";
+    String BOUNCER_SCRIM_CONTROLLER = "bouncer_scrim_controller";
+
+    /** */
+    @Provides
+    @Named(BOUNCERLESS_SCRIM_CONTROLLER)
+    static ScrimController providesBouncerlessScrimController(
+            BouncerlessScrimController controller) {
+        return controller;
+    }
+
+    /** */
+    @Provides
+    @Named(BOUNCER_SCRIM_CONTROLLER)
+    static ScrimController providesBouncerScrimController(
+            BouncerScrimController controller) {
+        return controller;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index 454ed27..a9f985f 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -36,7 +36,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.user.data.repository.UserRepository
 import com.android.systemui.util.kotlin.onSubscriberAdded
@@ -186,7 +186,6 @@
 constructor(
     @Application private val applicationScope: CoroutineScope,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
-    flags: SceneContainerFlags,
     private val clock: SystemClock,
     private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>,
     private val userRepository: UserRepository,
@@ -255,7 +254,7 @@
     override val hasLockoutOccurred: StateFlow<Boolean> = _hasLockoutOccurred.asStateFlow()
 
     init {
-        if (flags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled) {
             // Hydrate failedAuthenticationAttempts initially and whenever the selected user
             // changes.
             applicationScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 8ca083f..5df7fc9 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -243,12 +243,6 @@
         }
 
         // Authentication failed.
-
-        if (tryAutoConfirm) {
-            // Auto-confirm is active, the failed attempt should have no side-effects.
-            return AuthenticationResult.FAILED
-        }
-
         repository.reportAuthenticationAttempt(isSuccessful = false)
 
         if (authenticationResult.lockoutDurationMs > 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
index a667de2..970699f 100644
--- a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
@@ -28,8 +28,9 @@
 import android.os.UserHandle
 import android.util.Log
 import com.android.app.tracing.traceSection
-import com.android.systemui.Flags.communalHub
 import com.android.systemui.backup.BackupHelper.Companion.ACTION_RESTORE_FINISHED
+import com.android.systemui.communal.data.backup.CommunalBackupHelper
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
 import com.android.systemui.communal.domain.backup.CommunalPrefsBackupHelper
 import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapper
 import com.android.systemui.controls.controller.ControlsFavoritePersistenceWrapper
@@ -59,6 +60,7 @@
             "systemui.keyguard.quickaffordance.shared_preferences"
         private const val COMMUNAL_PREFS_BACKUP_KEY =
             "systemui.communal.shared_preferences"
+        private const val COMMUNAL_STATE_BACKUP_KEY = "systemui.communal_state"
         val controlsDataLock = Any()
         const val ACTION_RESTORE_FINISHED = "com.android.systemui.backup.RESTORE_FINISHED"
         const val PERMISSION_SELF = "com.android.systemui.permission.SELF"
@@ -89,6 +91,10 @@
                     userId = userHandle.identifier,
                 )
             )
+            addHelper(
+                COMMUNAL_STATE_BACKUP_KEY,
+                CommunalBackupHelper(userHandle, CommunalBackupUtils(context = this)),
+            )
         }
     }
 
@@ -116,7 +122,7 @@
     }
 
     private fun communalEnabled(): Boolean {
-        return resources.getBoolean(R.bool.config_communalServiceEnabled) && communalHub()
+        return resources.getBoolean(R.bool.config_communalServiceEnabled)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index d85b81d..ca88d40d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -71,7 +71,6 @@
 import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
 import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor;
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor;
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor;
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
 import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel;
 import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel;
@@ -93,6 +92,9 @@
 
 import kotlin.Unit;
 
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.Job;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -106,9 +108,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlinx.coroutines.CoroutineScope;
-import kotlinx.coroutines.Job;
-
 /**
  * Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
  * appropriate biometric UI (e.g. BiometricDialogView).
@@ -136,7 +135,6 @@
     @Nullable private final FingerprintManager mFingerprintManager;
     @Nullable private final FaceManager mFaceManager;
     private final Provider<UdfpsController> mUdfpsControllerFactory;
-    private final Provider<SideFpsController> mSidefpsControllerFactory;
     private final CoroutineScope mApplicationCoroutineScope;
     private Job mBiometricContextListenerJob = null;
 
@@ -163,7 +161,6 @@
     @Nullable private UdfpsController mUdfpsController;
     @Nullable private UdfpsOverlayParams mUdfpsOverlayParams;
     @Nullable private IUdfpsRefreshRateRequestCallback mUdfpsRefreshRateRequestCallback;
-    @Nullable private SideFpsController mSideFpsController;
     @NonNull private Lazy<UdfpsLogger> mUdfpsLogger;
     @VisibleForTesting IBiometricSysuiReceiver mReceiver;
     @VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
@@ -320,14 +317,7 @@
                     this, mUdfpsLogger.get()));
             mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect();
         }
-
         mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
-        if (mSidefpsProps != null) {
-            if (!SideFpsControllerRefactor.isEnabled()) {
-                mSideFpsController = mSidefpsControllerFactory.get();
-            }
-        }
-
         mFingerprintManager.registerBiometricStateListener(new BiometricStateListener() {
             @Override
             public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
@@ -738,7 +728,6 @@
             @Nullable FingerprintManager fingerprintManager,
             @Nullable FaceManager faceManager,
             Provider<UdfpsController> udfpsControllerFactory,
-            Provider<SideFpsController> sidefpsControllerFactory,
             @NonNull DisplayManager displayManager,
             @NonNull WakefulnessLifecycle wakefulnessLifecycle,
             @NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@@ -766,7 +755,6 @@
         mFingerprintManager = fingerprintManager;
         mFaceManager = faceManager;
         mUdfpsControllerFactory = udfpsControllerFactory;
-        mSidefpsControllerFactory = sidefpsControllerFactory;
         mUdfpsLogger = udfpsLogger;
         mDisplayManager = displayManager;
         mWindowManager = windowManager;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
index df27cbb..027f674 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationBroadcastReceiver.java
@@ -35,6 +35,8 @@
     static final String ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG =
             "fingerprint_action_show_reenroll_dialog";
 
+    static final String EXTRA_IS_REENROLL_FORCED = "is_reenroll_forced";
+
     private static final String TAG = "BiometricNotificationBroadcastReceiver";
 
     private final Context mContext;
@@ -56,14 +58,16 @@
                 mNotificationDialogFactory.createReenrollDialog(
                         mContext.getUserId(),
                         mContext::startActivity,
-                        BiometricSourceType.FACE)
+                        BiometricSourceType.FACE,
+                        false)
                         .show();
                 break;
             case ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG:
                 mNotificationDialogFactory.createReenrollDialog(
                         mContext.getUserId(),
                         mContext::startActivity,
-                        BiometricSourceType.FINGERPRINT)
+                        BiometricSourceType.FINGERPRINT,
+                        intent.getBooleanExtra(EXTRA_IS_REENROLL_FORCED, false))
                         .show();
                 break;
             default:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
index fd0feef..4ac5a12 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationDialogFactory.java
@@ -29,13 +29,12 @@
 import android.provider.Settings;
 import android.util.Log;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import javax.inject.Inject;
-import javax.inject.Provider;
 
 /**
  * Manages the creation of dialogs to be shown for biometric re enroll notifications.
@@ -61,7 +60,8 @@
     }
 
     Dialog createReenrollDialog(
-            int userId, ActivityStarter activityStarter, BiometricSourceType biometricSourceType) {
+            int userId, ActivityStarter activityStarter, BiometricSourceType biometricSourceType,
+            boolean isReenrollForced) {
         SystemUIDialog sysuiDialog = mSystemUIDialogFactory.create();
         if (biometricSourceType == BiometricSourceType.FACE) {
             sysuiDialog.setTitle(mResources.getString(R.string.face_re_enroll_dialog_title));
@@ -80,8 +80,12 @@
         sysuiDialog.setPositiveButton(R.string.biometric_re_enroll_dialog_confirm,
                 (dialog, which) -> onReenrollDialogConfirm(
                         userId, biometricSourceType, activityStarter));
-        sysuiDialog.setNegativeButton(R.string.biometric_re_enroll_dialog_cancel,
-                (dialog, which) -> {});
+        if (!isReenrollForced) {
+            sysuiDialog.setNegativeButton(R.string.biometric_re_enroll_dialog_cancel,
+                    (dialog, which) -> {
+                    });
+        }
+        sysuiDialog.setCanceledOnTouchOutside(!isReenrollForced);
         return sysuiDialog;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
index d6a4cbb..3b49ce2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
@@ -17,6 +17,7 @@
 package com.android.systemui.biometrics;
 
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
 
 import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG;
 import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG;
@@ -43,8 +44,8 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import java.util.Optional;
@@ -80,6 +81,8 @@
     private boolean mFingerprintNotificationQueued;
     private boolean mFingerprintReenrollRequired;
 
+    private boolean mIsFingerprintReenrollForced;
+
     private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
             new KeyguardStateController.Callback() {
                 private boolean mIsShowing = true;
@@ -118,9 +121,11 @@
                 public void onBiometricHelp(int msgId, String helpString,
                         BiometricSourceType biometricSourceType) {
                     if (biometricSourceType == BiometricSourceType.FINGERPRINT
-                            && mFingerprintReEnrollNotification.isFingerprintReEnrollRequired(
+                            && mFingerprintReEnrollNotification.isFingerprintReEnrollRequested(
                                     msgId)) {
                         mFingerprintReenrollRequired = true;
+                        mIsFingerprintReenrollForced =
+                                mFingerprintReEnrollNotification.isFingerprintReEnrollForced(msgId);
                     }
                 }
             };
@@ -191,7 +196,7 @@
         final String name = mContext.getString(R.string.face_re_enroll_notification_name);
         mHandler.postDelayed(
                 () -> showNotification(ACTION_SHOW_FACE_REENROLL_DIALOG, title, content, name,
-                        FACE_NOTIFICATION_ID),
+                        FACE_NOTIFICATION_ID, false),
                 SHOW_NOTIFICATION_DELAY_MS);
     }
 
@@ -204,12 +209,12 @@
         final String name = mContext.getString(R.string.fingerprint_re_enroll_notification_name);
         mHandler.postDelayed(
                 () -> showNotification(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG, title, content,
-                        name, FINGERPRINT_NOTIFICATION_ID),
+                        name, FINGERPRINT_NOTIFICATION_ID, mIsFingerprintReenrollForced),
                 SHOW_NOTIFICATION_DELAY_MS);
     }
 
     private void showNotification(String action, CharSequence title, CharSequence content,
-            CharSequence name, int notificationId) {
+            CharSequence name, int notificationId, boolean isReenrollForced) {
         if (notificationId == FACE_NOTIFICATION_ID) {
             mFaceNotificationQueued = false;
         } else if (notificationId == FINGERPRINT_NOTIFICATION_ID) {
@@ -223,8 +228,12 @@
         }
 
         final Intent onClickIntent = new Intent(action);
+        onClickIntent.putExtra(BiometricNotificationBroadcastReceiver.EXTRA_IS_REENROLL_FORCED,
+                isReenrollForced);
+
         final PendingIntent onClickPendingIntent = PendingIntent.getBroadcastAsUser(mContext,
-                0 /* requestCode */, onClickIntent, FLAG_IMMUTABLE, UserHandle.CURRENT);
+                0 /* requestCode */, onClickIntent, FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT,
+                UserHandle.CURRENT);
 
         final Notification notification = new Notification.Builder(mContext, CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_SYSTEM)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
index 9050f26..5b9ed483 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
@@ -23,7 +23,16 @@
  */
 public interface FingerprintReEnrollNotification {
     //TODO: Remove this class and add a constant in the HAL API instead (b/281841852)
-    /** Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL. */
-    boolean isFingerprintReEnrollRequired(
+    /**
+     * Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL or
+     * FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED.
+     */
+    boolean isFingerprintReEnrollRequested(
+            @BiometricFingerprintConstants.FingerprintAcquired int msgId);
+
+    /**
+     * Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED.
+     */
+    boolean isFingerprintReEnrollForced(
             @BiometricFingerprintConstants.FingerprintAcquired int msgId);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
index 1f86bc6..d47e1e6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
@@ -23,7 +23,13 @@
  */
 public class FingerprintReEnrollNotificationImpl implements FingerprintReEnrollNotification{
     @Override
-    public boolean isFingerprintReEnrollRequired(int msgId) {
-        return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL;
+    public boolean isFingerprintReEnrollRequested(int msgId) {
+        return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL_OPTIONAL
+                || msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED;
+    }
+
+    @Override
+    public boolean isFingerprintReEnrollForced(int msgId) {
+        return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL_FORCED;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
deleted file mode 100644
index 85f63e9..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ /dev/null
@@ -1,537 +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.biometrics
-
-import android.app.ActivityTaskManager
-import android.content.Context
-import android.content.res.Configuration
-import android.graphics.Color
-import android.graphics.PixelFormat
-import android.graphics.PorterDuff
-import android.graphics.PorterDuffColorFilter
-import android.graphics.Rect
-import android.hardware.biometrics.BiometricRequestConstants
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.SensorLocationInternal
-import android.hardware.display.DisplayManager
-import android.hardware.fingerprint.FingerprintManager
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
-import android.hardware.fingerprint.ISidefpsController
-import android.os.Handler
-import android.util.Log
-import android.util.RotationUtils
-import android.view.Display
-import android.view.DisplayInfo
-import android.view.Gravity
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.View
-import android.view.View.AccessibilityDelegate
-import android.view.View.INVISIBLE
-import android.view.View.VISIBLE
-import android.view.ViewPropertyAnimator
-import android.view.WindowManager
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
-import android.view.accessibility.AccessibilityEvent
-import androidx.annotation.RawRes
-import com.airbnb.lottie.LottieAnimationView
-import com.airbnb.lottie.LottieProperty
-import com.airbnb.lottie.model.KeyPath
-import com.android.app.animation.Interpolators
-import com.android.app.tracing.traceSection
-import com.android.internal.annotations.VisibleForTesting
-import com.android.keyguard.KeyguardPINView
-import com.android.systemui.Dumpable
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.res.R
-import com.android.systemui.util.boundsOnScreen
-import com.android.systemui.util.concurrency.DelayableExecutor
-import java.io.PrintWriter
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-
-private const val TAG = "SideFpsController"
-
-/**
- * Shows and hides the side fingerprint sensor (side-fps) overlay and handles side fps touch events.
- */
-@SysUISingleton
-class SideFpsController
-@Inject
-constructor(
-    private val context: Context,
-    private val layoutInflater: LayoutInflater,
-    fingerprintManager: FingerprintManager?,
-    private val windowManager: WindowManager,
-    private val activityTaskManager: ActivityTaskManager,
-    displayManager: DisplayManager,
-    private val displayStateInteractor: DisplayStateInteractor,
-    @Main private val mainExecutor: DelayableExecutor,
-    @Main private val handler: Handler,
-    private val alternateBouncerInteractor: AlternateBouncerInteractor,
-    @Application private val applicationScope: CoroutineScope,
-    dumpManager: DumpManager,
-    fpsUnlockTracker: FpsUnlockTracker
-) : Dumpable {
-    private val requests: HashSet<SideFpsUiRequestSource> = HashSet()
-
-    @VisibleForTesting
-    val sensorProps: FingerprintSensorPropertiesInternal =
-        fingerprintManager?.sideFpsSensorProperties
-            ?: throw IllegalStateException("no side fingerprint sensor")
-
-    @VisibleForTesting
-    val orientationReasonListener =
-        OrientationReasonListener(
-            context,
-            displayManager,
-            handler,
-            sensorProps,
-            { reason -> onOrientationChanged(reason) },
-            BiometricRequestConstants.REASON_UNKNOWN
-        )
-
-    @VisibleForTesting val orientationListener = orientationReasonListener.orientationListener
-
-    private val isReverseDefaultRotation =
-        context.resources.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)
-
-    private var overlayShowAnimator: ViewPropertyAnimator? = null
-
-    private var overlayView: View? = null
-        set(value) {
-            field?.let { oldView ->
-                val lottie = oldView.requireViewById(R.id.sidefps_animation) as LottieAnimationView
-                lottie.pauseAnimation()
-                lottie.removeAllLottieOnCompositionLoadedListener()
-                windowManager.removeView(oldView)
-                orientationListener.disable()
-            }
-            overlayShowAnimator?.cancel()
-            overlayShowAnimator = null
-
-            field = value
-            field?.let { newView ->
-                if (requests.contains(SideFpsUiRequestSource.PRIMARY_BOUNCER)) {
-                    newView.alpha = 0f
-                    overlayShowAnimator =
-                        newView
-                            .animate()
-                            .alpha(1f)
-                            .setDuration(KeyguardPINView.ANIMATION_DURATION)
-                            .setInterpolator(Interpolators.ALPHA_IN)
-                }
-                windowManager.addView(newView, overlayViewParams)
-                orientationListener.enable()
-                overlayShowAnimator?.start()
-            }
-        }
-    @VisibleForTesting var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT
-
-    private val displayInfo = DisplayInfo()
-
-    private val overlayViewParams =
-        WindowManager.LayoutParams(
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
-                PixelFormat.TRANSLUCENT
-            )
-            .apply {
-                title = TAG
-                fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
-                gravity = Gravity.TOP or Gravity.LEFT
-                layoutInDisplayCutoutMode =
-                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
-                privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION
-            }
-
-    init {
-        if (!SideFpsControllerRefactor.isEnabled) {
-            fpsUnlockTracker.startTracking()
-            fingerprintManager?.setSidefpsController(
-                object : ISidefpsController.Stub() {
-                    override fun show(
-                        sensorId: Int,
-                        @BiometricRequestConstants.RequestReason reason: Int
-                    ) =
-                        if (reason.isReasonToAutoShow(activityTaskManager)) {
-                            show(SideFpsUiRequestSource.AUTO_SHOW, reason)
-                        } else {
-                            hide(SideFpsUiRequestSource.AUTO_SHOW)
-                        }
-
-                    override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
-                }
-            )
-            listenForAlternateBouncerVisibility()
-
-            dumpManager.registerDumpable(this)
-        }
-    }
-
-    private fun listenForAlternateBouncerVisibility() {
-        if (!DeviceEntryUdfpsRefactor.isEnabled) {
-            alternateBouncerInteractor.setAlternateBouncerUIAvailable(true, "SideFpsController")
-        }
-
-        applicationScope.launch {
-            alternateBouncerInteractor.isVisible.collect { isVisible: Boolean ->
-                if (isVisible) {
-                    show(SideFpsUiRequestSource.ALTERNATE_BOUNCER, REASON_AUTH_KEYGUARD)
-                } else {
-                    hide(SideFpsUiRequestSource.ALTERNATE_BOUNCER)
-                }
-            }
-        }
-    }
-
-    /** Shows the side fps overlay if not already shown. */
-    fun show(
-        request: SideFpsUiRequestSource,
-        @BiometricRequestConstants.RequestReason
-        reason: Int = BiometricRequestConstants.REASON_UNKNOWN
-    ) {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        if (!displayStateInteractor.isInRearDisplayMode.value) {
-            requests.add(request)
-            mainExecutor.execute {
-                if (overlayView == null) {
-                    traceSection(
-                        "SideFpsController#show(request=${request.name}, reason=$reason)"
-                    ) {
-                        createOverlayForDisplay(reason)
-                    }
-                } else {
-                    Log.v(TAG, "overlay already shown")
-                }
-            }
-        }
-    }
-
-    /** Hides the fps overlay if shown. */
-    fun hide(request: SideFpsUiRequestSource) {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        requests.remove(request)
-        mainExecutor.execute {
-            if (requests.isEmpty()) {
-                traceSection("SideFpsController#hide(${request.name})") { overlayView = null }
-            }
-        }
-    }
-
-    /** Hide the arrow indicator. */
-    fun hideIndicator() {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        val lottieAnimationView =
-            overlayView?.findViewById(R.id.sidefps_animation) as LottieAnimationView?
-        lottieAnimationView?.visibility = INVISIBLE
-    }
-
-    /** Show the arrow indicator. */
-    fun showIndicator() {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        val lottieAnimationView =
-            overlayView?.findViewById(R.id.sidefps_animation) as LottieAnimationView?
-        lottieAnimationView?.visibility = VISIBLE
-    }
-
-    override fun dump(pw: PrintWriter, args: Array<out String>) {
-        pw.println("requests:")
-        for (requestSource in requests) {
-            pw.println("     $requestSource.name")
-        }
-
-        pw.println("overlayView:")
-        pw.println("     width=${overlayView?.width}")
-        pw.println("     height=${overlayView?.height}")
-        pw.println("     boundsOnScreen=${overlayView?.boundsOnScreen}")
-
-        pw.println("displayStateInteractor:")
-        pw.println("     isInRearDisplayMode=${displayStateInteractor?.isInRearDisplayMode?.value}")
-
-        pw.println("sensorProps:")
-        pw.println("     displayId=${displayInfo.uniqueId}")
-        pw.println("     sensorType=${sensorProps?.sensorType}")
-        pw.println("     location=${sensorProps?.getLocation(displayInfo.uniqueId)}")
-        pw.println("lottieAnimationView:")
-        pw.println(
-            "     visibility=${overlayView?.findViewById<View>(R.id.sidefps_animation)?.visibility}"
-        )
-
-        pw.println("overlayOffsets=$overlayOffsets")
-        pw.println("isReverseDefaultRotation=$isReverseDefaultRotation")
-        pw.println("currentRotation=${displayInfo.rotation}")
-    }
-
-    private fun onOrientationChanged(@BiometricRequestConstants.RequestReason reason: Int) {
-        if (overlayView?.isAttachedToWindow == true) {
-            createOverlayForDisplay(reason)
-        }
-    }
-
-    private fun createOverlayForDisplay(@BiometricRequestConstants.RequestReason reason: Int) {
-        val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
-        overlayView = view
-        val display = context.display!!
-        // b/284098873 `context.display.rotation` may not up-to-date, we use displayInfo.rotation
-        display.getDisplayInfo(displayInfo)
-        val offsets =
-            sensorProps.getLocation(display.uniqueId).let { location ->
-                if (location == null) {
-                    Log.w(TAG, "No location specified for display: ${display.uniqueId}")
-                }
-                location ?: sensorProps.location
-            }
-        overlayOffsets = offsets
-
-        val lottie = view.requireViewById(R.id.sidefps_animation) as LottieAnimationView
-        view.rotation =
-            display.asSideFpsAnimationRotation(
-                offsets.isYAligned(),
-                getRotationFromDefault(displayInfo.rotation)
-            )
-        lottie.setAnimation(
-            display.asSideFpsAnimation(
-                offsets.isYAligned(),
-                getRotationFromDefault(displayInfo.rotation)
-            )
-        )
-        lottie.addLottieOnCompositionLoadedListener {
-            // Check that view is not stale, and that overlayView has not been hidden/removed
-            if (overlayView?.isAttachedToWindow == true && overlayView == view) {
-                updateOverlayParams(display, it.bounds)
-            }
-        }
-        orientationReasonListener.reason = reason
-        lottie.addOverlayDynamicColor(context, reason)
-
-        /**
-         * Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from
-         * speaking @string/accessibility_fingerprint_label twice when sensor location indicator is
-         * in focus
-         */
-        view.setAccessibilityDelegate(
-            object : AccessibilityDelegate() {
-                override fun dispatchPopulateAccessibilityEvent(
-                    host: View,
-                    event: AccessibilityEvent
-                ): Boolean {
-                    return if (
-                        event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
-                    ) {
-                        true
-                    } else {
-                        super.dispatchPopulateAccessibilityEvent(host, event)
-                    }
-                }
-            }
-        )
-    }
-
-    @VisibleForTesting
-    fun updateOverlayParams(display: Display, bounds: Rect) {
-        val isNaturalOrientation = display.isNaturalOrientation()
-        val isDefaultOrientation =
-            if (isReverseDefaultRotation) !isNaturalOrientation else isNaturalOrientation
-        val size = windowManager.maximumWindowMetrics.bounds
-
-        val displayWidth = if (isDefaultOrientation) size.width() else size.height()
-        val displayHeight = if (isDefaultOrientation) size.height() else size.width()
-        val boundsWidth = if (isDefaultOrientation) bounds.width() else bounds.height()
-        val boundsHeight = if (isDefaultOrientation) bounds.height() else bounds.width()
-
-        val sensorBounds =
-            if (overlayOffsets.isYAligned()) {
-                Rect(
-                    displayWidth - boundsWidth,
-                    overlayOffsets.sensorLocationY,
-                    displayWidth,
-                    overlayOffsets.sensorLocationY + boundsHeight
-                )
-            } else {
-                Rect(
-                    overlayOffsets.sensorLocationX,
-                    0,
-                    overlayOffsets.sensorLocationX + boundsWidth,
-                    boundsHeight
-                )
-            }
-
-        RotationUtils.rotateBounds(
-            sensorBounds,
-            Rect(0, 0, displayWidth, displayHeight),
-            getRotationFromDefault(display.rotation)
-        )
-
-        overlayViewParams.x = sensorBounds.left
-        overlayViewParams.y = sensorBounds.top
-
-        windowManager.updateViewLayout(overlayView, overlayViewParams)
-    }
-
-    private fun getRotationFromDefault(rotation: Int): Int =
-        if (isReverseDefaultRotation) (rotation + 1) % 4 else rotation
-}
-
-private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorPropertiesInternal?
-    get() = this?.sensorPropertiesInternal?.firstOrNull { it.isAnySidefpsType }
-
-/** Returns [True] when the device has a side fingerprint sensor. */
-fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null
-
[email protected]
-private fun Int.isReasonToAutoShow(activityTaskManager: ActivityTaskManager): Boolean =
-    when (this) {
-        REASON_AUTH_KEYGUARD -> false
-        REASON_AUTH_SETTINGS ->
-            when (activityTaskManager.topClass()) {
-                // TODO(b/186176653): exclude fingerprint overlays from this list view
-                "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
-                else -> true
-            }
-        else -> true
-    }
-
-private fun ActivityTaskManager.topClass(): String =
-    getTasks(1).firstOrNull()?.topActivity?.className ?: ""
-
-@RawRes
-private fun Display.asSideFpsAnimation(yAligned: Boolean, rotationFromDefault: Int): Int =
-    when (rotationFromDefault) {
-        Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
-        Surface.ROTATION_180 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
-        else -> if (yAligned) R.raw.sfps_pulse_landscape else R.raw.sfps_pulse
-    }
-
-private fun Display.asSideFpsAnimationRotation(yAligned: Boolean, rotationFromDefault: Int): Float =
-    when (rotationFromDefault) {
-        Surface.ROTATION_90 -> if (yAligned) 0f else 180f
-        Surface.ROTATION_180 -> 180f
-        Surface.ROTATION_270 -> if (yAligned) 180f else 0f
-        else -> 0f
-    }
-
-private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0
-
-private fun Display.isNaturalOrientation(): Boolean =
-    rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180
-
-private fun LottieAnimationView.addOverlayDynamicColor(
-    context: Context,
-    @BiometricRequestConstants.RequestReason reason: Int
-) {
-    fun update() {
-        val isKeyguard = reason == REASON_AUTH_KEYGUARD
-        if (isKeyguard) {
-            val color =
-                com.android.settingslib.Utils.getColorAttrDefaultColor(
-                    context,
-                    com.android.internal.R.attr.materialColorPrimaryFixed
-                )
-            val outerRimColor =
-                com.android.settingslib.Utils.getColorAttrDefaultColor(
-                    context,
-                    com.android.internal.R.attr.materialColorPrimaryFixedDim
-                )
-            val chevronFill =
-                com.android.settingslib.Utils.getColorAttrDefaultColor(
-                    context,
-                    com.android.internal.R.attr.materialColorOnPrimaryFixed
-                )
-            addValueCallback(KeyPath(".blue600", "**"), LottieProperty.COLOR_FILTER) {
-                PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
-            }
-            addValueCallback(KeyPath(".blue400", "**"), LottieProperty.COLOR_FILTER) {
-                PorterDuffColorFilter(outerRimColor, PorterDuff.Mode.SRC_ATOP)
-            }
-            addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) {
-                PorterDuffColorFilter(chevronFill, PorterDuff.Mode.SRC_ATOP)
-            }
-        } else {
-            if (!isDarkMode(context)) {
-                addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) {
-                    PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)
-                }
-            }
-            for (key in listOf(".blue600", ".blue400")) {
-                addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) {
-                    PorterDuffColorFilter(
-                        context.getColor(
-                            com.android.settingslib.color.R.color.settingslib_color_blue400
-                        ),
-                        PorterDuff.Mode.SRC_ATOP
-                    )
-                }
-            }
-        }
-    }
-
-    if (composition != null) {
-        update()
-    } else {
-        addLottieOnCompositionLoadedListener { update() }
-    }
-}
-
-private fun isDarkMode(context: Context): Boolean {
-    val darkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
-    return darkMode == Configuration.UI_MODE_NIGHT_YES
-}
-
-@VisibleForTesting
-class OrientationReasonListener(
-    context: Context,
-    displayManager: DisplayManager,
-    handler: Handler,
-    sensorProps: FingerprintSensorPropertiesInternal,
-    onOrientationChanged: (reason: Int) -> Unit,
-    @BiometricRequestConstants.RequestReason var reason: Int
-) {
-    val orientationListener =
-        BiometricDisplayListener(
-            context,
-            displayManager,
-            handler,
-            BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
-        ) {
-            onOrientationChanged(reason)
-        }
-}
-
-/**
- * The source of a request to show the side fps visual indicator. This is distinct from
- * [BiometricRequestConstants] which corresponds with the reason fingerprint authentication is
- * requested.
- */
-enum class SideFpsUiRequestSource {
-    /** see [isReasonToAutoShow] */
-    AUTO_SHOW,
-    /** Pin, pattern or password bouncer */
-    PRIMARY_BOUNCER,
-    ALTERNATE_BOUNCER,
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 9d79e87..b25c3da 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -403,6 +403,8 @@
             if (DeviceEntryUdfpsRefactor.isEnabled()) {
                 if (mOverlay != null && mOverlay.getRequestReason() == REASON_AUTH_KEYGUARD) {
                     mOverlay.updateOverlayParams(mOverlayParams);
+                } else {
+                    redrawOverlay();
                 }
             } else {
                 final boolean wasShowingAlternateBouncer =
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 3a45db1..4a60d19 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -323,7 +323,13 @@
         overlayParams = updatedOverlayParams
         sensorBounds = updatedOverlayParams.sensorBounds
         getTouchOverlay()?.let {
-            windowManager.updateViewLayout(it, coreLayoutParams.updateDimensions(null))
+            if (addViewRunnable == null) {
+                // Only updateViewLayout if there's no pending view to add to WM.
+                // If there is a pending view, that means the view hasn't been added yet so there's
+                // no need to update any layouts. Instead the correct params will be used when the
+                // view is eventually added.
+                windowManager.updateViewLayout(it, coreLayoutParams.updateDimensions(null))
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
index ec54e4ce..9816896 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
@@ -282,7 +282,8 @@
     @VisibleForTesting
     suspend fun listenForGoneToAodTransition(scope: CoroutineScope): Job {
         return scope.launch {
-            transitionInteractor.goneToAodTransition.collect { transitionStep ->
+            transitionInteractor.transition(KeyguardState.GONE, KeyguardState.AOD).collect {
+                transitionStep ->
                 view.onDozeAmountChanged(
                     transitionStep.value,
                     transitionStep.value,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
index 27bb023..cc52484 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
@@ -25,6 +25,15 @@
 import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
 import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR
 import android.hardware.biometrics.BiometricSourceType
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo
+import android.hardware.biometrics.events.AuthenticationErrorInfo
+import android.hardware.biometrics.events.AuthenticationFailedInfo
+import android.hardware.biometrics.events.AuthenticationHelpInfo
+import android.hardware.biometrics.events.AuthenticationStartedInfo
+import android.hardware.biometrics.events.AuthenticationStoppedInfo
+import android.hardware.biometrics.events.AuthenticationSucceededInfo
+import android.hardware.face.FaceManager
+import android.hardware.fingerprint.FingerprintManager
 import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
 import com.android.systemui.biometrics.shared.model.AuthenticationState
@@ -39,6 +48,7 @@
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.map
@@ -61,9 +71,17 @@
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    private val biometricManager: BiometricManager?
+    private val biometricManager: BiometricManager?,
 ) : BiometricStatusRepository {
 
+    /**
+     * TODO(b/322555228): Replace usages of onAuthenticationError, onAuthenticationHelp,
+     *   onAuthenticationSucceeded, onAuthenticationFailed, onAuthenticationAcquired in
+     *   [FingerprintManager.AuthenticationCallback] and [FaceManager.AuthenticationCallback],
+     *   onDetectionError in [FingerprintManager.FingerprintDetectionCallback] and
+     *   [FaceManager.FaceDetectionCallback], and onEnrollmentError, onEnrollmentHelp, and
+     *   onAcquired in [FingerprintManager.EnrollmentCallback] and [FaceManager.EnrollmentCallback]
+     */
     private val authenticationState: Flow<AuthenticationState> =
         conflatedCallbackFlow {
                 val updateAuthenticationState = { state: AuthenticationState ->
@@ -72,45 +90,83 @@
 
                 val authenticationStateListener =
                     object : AuthenticationStateListener.Stub() {
-                        override fun onAuthenticationStarted(requestReason: Int) {
-                            val authenticationReason = requestReason.toAuthenticationReason()
+                        override fun onAuthenticationAcquired(
+                            authInfo: AuthenticationAcquiredInfo
+                        ) {
                             updateAuthenticationState(
-                                AuthenticationState.AuthenticationStarted(authenticationReason)
+                                AuthenticationState.Acquired(
+                                    authInfo.biometricSourceType,
+                                    authInfo.requestReason.toAuthenticationReason(),
+                                    authInfo.acquiredInfo
+                                )
                             )
                         }
 
-                        override fun onAuthenticationStopped() {
+                        override fun onAuthenticationError(authInfo: AuthenticationErrorInfo) {
                             updateAuthenticationState(
-                                AuthenticationState.AuthenticationStopped(
+                                AuthenticationState.Error(
+                                    authInfo.biometricSourceType,
+                                    authInfo.errString,
+                                    authInfo.errCode,
+                                    authInfo.requestReason.toAuthenticationReason()
+                                )
+                            )
+                        }
+
+                        override fun onAuthenticationFailed(authInfo: AuthenticationFailedInfo) {
+                            updateAuthenticationState(
+                                AuthenticationState.Failed(
+                                    authInfo.biometricSourceType,
+                                    authInfo.requestReason.toAuthenticationReason(),
+                                    authInfo.userId
+                                )
+                            )
+                        }
+
+                        override fun onAuthenticationHelp(authInfo: AuthenticationHelpInfo) {
+                            updateAuthenticationState(
+                                AuthenticationState.Help(
+                                    authInfo.biometricSourceType,
+                                    authInfo.helpString,
+                                    authInfo.helpCode,
+                                    authInfo.requestReason.toAuthenticationReason()
+                                )
+                            )
+                        }
+
+                        override fun onAuthenticationStarted(authInfo: AuthenticationStartedInfo) {
+                            updateAuthenticationState(
+                                AuthenticationState.Started(
+                                    authInfo.biometricSourceType,
+                                    authInfo.requestReason.toAuthenticationReason()
+                                )
+                            )
+                        }
+
+                        override fun onAuthenticationStopped(authInfo: AuthenticationStoppedInfo) {
+                            updateAuthenticationState(
+                                AuthenticationState.Stopped(
+                                    authInfo.biometricSourceType,
                                     AuthenticationReason.NotRunning
                                 )
                             )
                         }
 
-                        override fun onAuthenticationSucceeded(requestReason: Int, userId: Int) {}
-
-                        override fun onAuthenticationFailed(requestReason: Int, userId: Int) {}
-
-                        override fun onAuthenticationAcquired(
-                            biometricSourceType: BiometricSourceType,
-                            requestReason: Int,
-                            acquiredInfo: Int
+                        override fun onAuthenticationSucceeded(
+                            authInfo: AuthenticationSucceededInfo
                         ) {
-                            val authReason = requestReason.toAuthenticationReason()
-
                             updateAuthenticationState(
-                                AuthenticationState.AuthenticationAcquired(
-                                    biometricSourceType,
-                                    authReason,
-                                    acquiredInfo
+                                AuthenticationState.Succeeded(
+                                    authInfo.biometricSourceType,
+                                    authInfo.isIsStrongBiometric,
+                                    authInfo.requestReason.toAuthenticationReason(),
+                                    authInfo.userId
                                 )
                             )
                         }
                     }
 
-                updateAuthenticationState(
-                    AuthenticationState.AuthenticationStarted(AuthenticationReason.NotRunning)
-                )
+                updateAuthenticationState(AuthenticationState.Idle(AuthenticationReason.NotRunning))
                 biometricManager?.registerAuthenticationStateListener(authenticationStateListener)
                 awaitClose {
                     biometricManager?.unregisterAuthenticationStateListener(
@@ -118,21 +174,24 @@
                     )
                 }
             }
+            .distinctUntilChanged()
             .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)
 
     override val fingerprintAuthenticationReason: Flow<AuthenticationReason> =
-        authenticationState.map { it.requestReason }
+        authenticationState
+            .filter {
+                it is AuthenticationState.Idle ||
+                    (it is AuthenticationState.Started &&
+                        it.biometricSourceType == BiometricSourceType.FINGERPRINT) ||
+                    (it is AuthenticationState.Stopped &&
+                        it.biometricSourceType == BiometricSourceType.FINGERPRINT)
+            }
+            .map { it.requestReason }
 
     override val fingerprintAcquiredStatus: Flow<FingerprintAuthenticationStatus> =
         authenticationState
-            .filterIsInstance<AuthenticationState.AuthenticationAcquired>()
-            .filter {
-                it.biometricSourceType == BiometricSourceType.FINGERPRINT &&
-                    // TODO(b/322555228) This check will be removed after consolidating device
-                    //  entry auth messages (currently in DeviceEntryFingerprintAuthRepository)
-                    //  with BP auth messages (here)
-                    it.requestReason == AuthenticationReason.BiometricPromptAuthentication
-            }
+            .filterIsInstance<AuthenticationState.Acquired>()
+            .filter { it.biometricSourceType == BiometricSourceType.FINGERPRINT }
             .map { AcquiredFingerprintAuthenticationStatus(it.requestReason, it.acquiredInfo) }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
index 59b59bf..7d4ba84 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
@@ -39,6 +39,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.shared.model.DevicePosture
 import com.android.systemui.res.R
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -68,6 +69,8 @@
 
     /** The info of current available camera. */
     val cameraInfo: StateFlow<CameraInfo?>
+
+    val supportedPostures: List<DevicePosture>
 }
 
 /** Describes a biometric sensor */
@@ -188,6 +191,15 @@
                 initialValue = if (cameraInfoList.isNotEmpty()) cameraInfoList[0] else null
             )
 
+    private val supportedPosture =
+        applicationContext.resources.getInteger(R.integer.config_face_auth_supported_posture)
+    override val supportedPostures: List<DevicePosture> =
+        if (supportedPosture == 0) {
+            DevicePosture.entries
+        } else {
+            listOf(DevicePosture.toPosture(supportedPosture))
+        }
+
     private val defaultSensorLocation: StateFlow<Point?> =
         cameraInfo
             .map { it?.cameraLocation }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt
index c4967ec..6e79e46 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt
@@ -18,13 +18,14 @@
 
 import android.app.ActivityTaskManager
 import com.android.systemui.biometrics.data.repository.BiometricStatusRepository
+import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
 import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
 import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatus
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
 
 /** Encapsulates business logic for interacting with biometric authentication state. */
 interface BiometricStatusInteractor {
@@ -43,12 +44,15 @@
 constructor(
     private val activityTaskManager: ActivityTaskManager,
     biometricStatusRepository: BiometricStatusRepository,
+    fingerprintPropertyRepository: FingerprintPropertyRepository,
 ) : BiometricStatusInteractor {
 
     override val sfpsAuthenticationReason: Flow<AuthenticationReason> =
-        biometricStatusRepository.fingerprintAuthenticationReason.map { reason: AuthenticationReason
-            ->
-            if (reason.isReasonToAlwaysUpdateSfpsOverlay(activityTaskManager)) {
+        combine(
+            biometricStatusRepository.fingerprintAuthenticationReason,
+            fingerprintPropertyRepository.sensorType
+        ) { reason: AuthenticationReason, sensorType ->
+            if (sensorType.isPowerButton() && reason.isReasonToAlwaysUpdateSfpsOverlay(activityTaskManager)) {
                 reason
             } else {
                 AuthenticationReason.NotRunning
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
index 7d67219..591da40 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.content.res.Configuration
-import android.view.Display
 import com.android.systemui.biometrics.data.repository.DisplayStateRepository
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -28,7 +27,6 @@
 import com.android.systemui.display.data.repository.DisplayRepository
 import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
 import com.android.systemui.unfold.updates.FoldProvider
-import com.android.systemui.util.kotlin.sample
 import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -36,8 +34,6 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /** Aggregates display state information. */
@@ -129,16 +125,7 @@
         screenSizeFoldProvider.onConfigurationChange(newConfig)
     }
 
-    private val defaultDisplay =
-        displayRepository.displays.map { displays ->
-            displays.firstOrNull { it.displayId == Display.DEFAULT_DISPLAY }
-        }
-
-    override val isDefaultDisplayOff =
-        displayRepository.displayChangeEvent
-            .filter { it == Display.DEFAULT_DISPLAY }
-            .sample(defaultDisplay)
-            .map { it?.state == Display.STATE_OFF }
+    override val isDefaultDisplayOff = displayRepository.defaultDisplayOff
 
     override val isLargeScreen: Flow<Boolean> = displayStateRepository.isLargeScreen
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt
deleted file mode 100644
index 899b07e..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.biometrics.shared
-
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-import com.android.systemui.shared.Flags
-
-/** Helper for reading or using the sidefps controller refactor flag state. */
-@Suppress("NOTHING_TO_INLINE")
-object SideFpsControllerRefactor {
-    /** The aconfig flag name */
-    const val FLAG_NAME = Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-
-    /** A token used for dependency declaration */
-    val token: FlagToken
-        get() = FlagToken(FLAG_NAME, isEnabled)
-
-    /** Is the refactor enabled */
-    @JvmStatic
-    inline val isEnabled
-        get() = Flags.sidefpsControllerRefactor()
-
-    /**
-     * Called to ensure code is only run when the flag is enabled. This protects users from the
-     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
-     * build to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun isUnexpectedlyInLegacyMode() =
-        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
-    /**
-     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
-     * the flag is enabled to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt
index 77cf840..5ceae36 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationState.kt
@@ -16,6 +16,9 @@
 
 package com.android.systemui.biometrics.shared.model
 
+import android.hardware.biometrics.BiometricFaceConstants
+import android.hardware.biometrics.BiometricFingerprintConstants
+import android.hardware.biometrics.BiometricRequestConstants
 import android.hardware.biometrics.BiometricSourceType
 
 /**
@@ -24,34 +27,113 @@
  * authentication.
  */
 sealed interface AuthenticationState {
+    /**
+     * Indicates [AuthenticationReason] from [BiometricRequestConstants.RequestReason] for
+     * requesting auth
+     */
     val requestReason: AuthenticationReason
 
     /**
-     * Authentication started
-     *
-     * @param requestReason [AuthenticationReason] for starting authentication
-     */
-    data class AuthenticationStarted(override val requestReason: AuthenticationReason) :
-        AuthenticationState
-
-    /**
-     * Authentication stopped
-     *
-     * @param requestReason [AuthenticationReason.NotRunning]
-     */
-    data class AuthenticationStopped(override val requestReason: AuthenticationReason) :
-        AuthenticationState
-
-    /**
-     * Authentication acquired
+     * AuthenticationState when a biometric has been acquired.
      *
      * @param biometricSourceType indicates [BiometricSourceType] of acquired authentication
-     * @param requestReason indicates [AuthenticationReason] for requesting auth
-     * @param acquiredInfo indicates
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
+     * @param acquiredInfo [BiometricFaceConstants.FaceAcquired] or
+     *   [BiometricFingerprintConstants.FingerprintAcquired] int corresponding to a known acquired
+     *   message.
      */
-    data class AuthenticationAcquired(
+    data class Acquired(
         val biometricSourceType: BiometricSourceType,
         override val requestReason: AuthenticationReason,
         val acquiredInfo: Int
     ) : AuthenticationState
+
+    /**
+     * AuthenticationState when an unrecoverable error is encountered during authentication.
+     *
+     * @param biometricSourceType identifies [BiometricSourceType] for auth error
+     * @param errString authentication error string shown on the UI
+     * @param errCode [BiometricFaceConstants.FaceError] or
+     *   [BiometricFingerprintConstants.FingerprintError] int identifying the error message for an
+     *   authentication error
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
+     */
+    data class Error(
+        val biometricSourceType: BiometricSourceType,
+        val errString: String?,
+        val errCode: Int,
+        override val requestReason: AuthenticationReason,
+    ) : AuthenticationState
+
+    /**
+     * AuthenticationState when a biometric couldn't be authenticated.
+     *
+     * @param biometricSourceType identifies [BiometricSourceType] for failed auth
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
+     * @param userId The user id for the requested authentication
+     */
+    data class Failed(
+        val biometricSourceType: BiometricSourceType,
+        override val requestReason: AuthenticationReason,
+        val userId: Int
+    ) : AuthenticationState
+
+    /**
+     * AuthenticationState when a recoverable error is encountered during authentication.
+     *
+     * @param biometricSourceType identifies [BiometricSourceType] for failed auth
+     * @param helpString helpString guidance help string shown on the UI
+     * @param helpCode An integer identifying the help message
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
+     */
+    data class Help(
+        val biometricSourceType: BiometricSourceType,
+        val helpString: String?,
+        val helpCode: Int,
+        override val requestReason: AuthenticationReason,
+    ) : AuthenticationState
+
+    /**
+     * Authentication state when no auth is running
+     *
+     * @param requestReason [AuthenticationReason.NotRunning]
+     */
+    data class Idle(override val requestReason: AuthenticationReason) : AuthenticationState
+
+    /**
+     * AuthenticationState when auth is started
+     *
+     * @param biometricSourceType identifies [BiometricSourceType] for auth
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
+     */
+    data class Started(
+        val biometricSourceType: BiometricSourceType,
+        override val requestReason: AuthenticationReason
+    ) : AuthenticationState
+
+    /**
+     * Authentication state when auth is stopped
+     *
+     * @param biometricSourceType identifies [BiometricSourceType] for auth stopped
+     * @param requestReason [AuthenticationReason.NotRunning]
+     */
+    data class Stopped(
+        val biometricSourceType: BiometricSourceType,
+        override val requestReason: AuthenticationReason
+    ) : AuthenticationState
+
+    /**
+     * AuthenticationState when a biometric is successfully authenticated.
+     *
+     * @param biometricSourceType identifies [BiometricSourceType] of successful auth
+     * @param isStrongBiometric indicates whether auth was from strong biometric
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
+     * @param userId The user id for the requested authentication
+     */
+    data class Succeeded(
+        val biometricSourceType: BiometricSourceType,
+        val isStrongBiometric: Boolean,
+        override val requestReason: AuthenticationReason,
+        val userId: Int
+    ) : AuthenticationState
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
index 83b3380..1eef91d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
@@ -27,7 +27,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import javax.inject.Inject
 
-private val SUPPORTED_ROTATIONS = setOf(Surface.ROTATION_90, Surface.ROTATION_270)
+private val SUPPORTED_ROTATIONS =
+    setOf(Surface.ROTATION_90, Surface.ROTATION_270, Surface.ROTATION_180)
 
 /**
  * TODO(b/259140693): Consider using an object pool of TouchProcessorResult to avoid allocations.
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index b2ade4f..072fe47 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -288,12 +288,14 @@
                 // set padding
                 launch {
                     viewModel.promptPadding.collect { promptPadding ->
-                        view.setPadding(
-                            promptPadding.left,
-                            promptPadding.top,
-                            promptPadding.right,
-                            promptPadding.bottom
-                        )
+                        if (!constraintBp()) {
+                            view.setPadding(
+                                promptPadding.left,
+                                promptPadding.top,
+                                promptPadding.right,
+                                promptPadding.bottom
+                            )
+                        }
                     }
                 }
 
@@ -461,6 +463,23 @@
                         }
                     }
                 }
+
+                // Retry and confirmation when finger on sensor
+                launch {
+                    combine(
+                            viewModel.canTryAgainNow,
+                            viewModel.hasFingerOnSensor,
+                            viewModel.isPendingConfirmation,
+                            ::Triple
+                        )
+                        .collect { (canRetry, fingerAcquired, pendingConfirmation) ->
+                            if (canRetry && fingerAcquired) {
+                                legacyCallback.onButtonTryAgain()
+                            } else if (pendingConfirmation && fingerAcquired) {
+                                viewModel.confirmAuthenticated()
+                            }
+                        }
+                }
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index e3c0cba..f380746 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -20,7 +20,6 @@
 import android.animation.AnimatorSet
 import android.animation.ValueAnimator
 import android.graphics.Outline
-import android.graphics.Rect
 import android.transition.AutoTransition
 import android.transition.TransitionManager
 import android.util.TypedValue
@@ -47,17 +46,14 @@
 import com.android.systemui.biometrics.ui.viewmodel.PromptPosition
 import com.android.systemui.biometrics.ui.viewmodel.PromptSize
 import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
-import com.android.systemui.biometrics.ui.viewmodel.isBottom
 import com.android.systemui.biometrics.ui.viewmodel.isLarge
 import com.android.systemui.biometrics.ui.viewmodel.isLeft
 import com.android.systemui.biometrics.ui.viewmodel.isMedium
 import com.android.systemui.biometrics.ui.viewmodel.isNullOrNotSmall
-import com.android.systemui.biometrics.ui.viewmodel.isRight
 import com.android.systemui.biometrics.ui.viewmodel.isSmall
-import com.android.systemui.biometrics.ui.viewmodel.isTop
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
-import kotlin.math.min
+import kotlin.math.abs
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 
@@ -97,8 +93,6 @@
         if (constraintBp()) {
             val leftGuideline = view.requireViewById<Guideline>(R.id.leftGuideline)
             val rightGuideline = view.requireViewById<Guideline>(R.id.rightGuideline)
-            val bottomGuideline = view.requireViewById<Guideline>(R.id.bottomGuideline)
-            val topGuideline = view.requireViewById<Guideline>(R.id.topGuideline)
             val midGuideline = view.findViewById<Guideline>(R.id.midGuideline)
 
             val iconHolderView = view.requireViewById<View>(R.id.biometric_icon)
@@ -121,165 +115,12 @@
 
             val largeConstraintSet = ConstraintSet()
             largeConstraintSet.clone(mediumConstraintSet)
+            largeConstraintSet.constrainMaxWidth(R.id.panel, view.width)
 
             // TODO: Investigate better way to handle 180 rotations
             val flipConstraintSet = ConstraintSet()
-            flipConstraintSet.clone(mediumConstraintSet)
-            flipConstraintSet.connect(
-                R.id.scrollView,
-                ConstraintSet.START,
-                R.id.midGuideline,
-                ConstraintSet.START
-            )
-            flipConstraintSet.connect(
-                R.id.scrollView,
-                ConstraintSet.END,
-                R.id.rightGuideline,
-                ConstraintSet.END
-            )
-            flipConstraintSet.setHorizontalBias(R.id.biometric_icon, .2f)
-
-            // Round the panel outline
-            panelView.outlineProvider =
-                object : ViewOutlineProvider() {
-                    override fun getOutline(view: View, outline: Outline) {
-                        outline.setRoundRect(
-                            0,
-                            0,
-                            view.width,
-                            view.height + cornerRadiusPx,
-                            cornerRadiusPx.toFloat()
-                        )
-                    }
-                }
 
             view.doOnLayout {
-                val windowBounds = windowManager.maximumWindowMetrics.bounds
-                val bottomInset =
-                    windowManager.maximumWindowMetrics.windowInsets
-                        .getInsets(WindowInsets.Type.navigationBars())
-                        .bottom
-
-                // TODO: Move to viewmodel
-                fun measureBounds(position: PromptPosition) {
-                    val density = windowManager.currentWindowMetrics.density
-                    val width = min((640 * density).toInt(), windowBounds.width())
-
-                    var left = -1
-                    var right = -1
-                    var bottom = -1
-                    var mid = -1
-
-                    when {
-                        position.isTop -> {
-                            // Round bottom corners
-                            panelView.outlineProvider =
-                                object : ViewOutlineProvider() {
-                                    override fun getOutline(view: View, outline: Outline) {
-                                        outline.setRoundRect(
-                                            0,
-                                            -cornerRadiusPx,
-                                            view.width,
-                                            view.height,
-                                            cornerRadiusPx.toFloat()
-                                        )
-                                    }
-                                }
-                            left = windowBounds.centerX() - width / 2 + viewModel.promptMargin
-                            right = windowBounds.centerX() - width / 2 + viewModel.promptMargin
-                            bottom = iconHolderView.centerY() * 2 - iconHolderView.centerY() / 4
-                        }
-                        position.isBottom -> {
-                            // Round top corners
-                            panelView.outlineProvider =
-                                object : ViewOutlineProvider() {
-                                    override fun getOutline(view: View, outline: Outline) {
-                                        outline.setRoundRect(
-                                            0,
-                                            0,
-                                            view.width,
-                                            view.height + cornerRadiusPx,
-                                            cornerRadiusPx.toFloat()
-                                        )
-                                    }
-                                }
-
-                            left = windowBounds.centerX() - width / 2
-                            right = windowBounds.centerX() - width / 2
-                            bottom = if (view.isLandscape()) bottomInset else 0
-                        }
-                        position.isLeft -> {
-                            // Round right corners
-                            panelView.outlineProvider =
-                                object : ViewOutlineProvider() {
-                                    override fun getOutline(view: View, outline: Outline) {
-                                        outline.setRoundRect(
-                                            -cornerRadiusPx,
-                                            0,
-                                            view.width,
-                                            view.height,
-                                            cornerRadiusPx.toFloat()
-                                        )
-                                    }
-                                }
-
-                            left = 0
-                            mid = (windowBounds.width() * .85).toInt() / 2
-                            right = windowBounds.width() - (windowBounds.width() * .85).toInt()
-                            bottom = if (view.isLandscape()) bottomInset else 0
-                        }
-                        position.isRight -> {
-                            // Round left corners
-                            panelView.outlineProvider =
-                                object : ViewOutlineProvider() {
-                                    override fun getOutline(view: View, outline: Outline) {
-                                        outline.setRoundRect(
-                                            0,
-                                            0,
-                                            view.width + cornerRadiusPx,
-                                            view.height,
-                                            cornerRadiusPx.toFloat()
-                                        )
-                                    }
-                                }
-
-                            left = windowBounds.width() - (windowBounds.width() * .85).toInt()
-                            right = 0
-                            bottom = if (view.isLandscape()) bottomInset else 0
-                            mid = windowBounds.width() - (windowBounds.width() * .85).toInt() / 2
-                        }
-                    }
-
-                    val bounds = Rect(left, mid, right, bottom)
-                    if (bounds.shouldAdjustLeftGuideline()) {
-                        leftGuideline.setGuidelineBegin(bounds.left)
-                        smallConstraintSet.setGuidelineBegin(leftGuideline.id, bounds.left)
-                        mediumConstraintSet.setGuidelineBegin(leftGuideline.id, bounds.left)
-                    }
-                    if (bounds.shouldAdjustRightGuideline()) {
-                        rightGuideline.setGuidelineEnd(bounds.right)
-                        smallConstraintSet.setGuidelineEnd(rightGuideline.id, bounds.right)
-                        mediumConstraintSet.setGuidelineEnd(rightGuideline.id, bounds.right)
-                    }
-                    if (bounds.shouldAdjustBottomGuideline()) {
-                        bottomGuideline.setGuidelineEnd(bounds.bottom)
-                        smallConstraintSet.setGuidelineEnd(bottomGuideline.id, bounds.bottom)
-                        mediumConstraintSet.setGuidelineEnd(bottomGuideline.id, bounds.bottom)
-                    }
-
-                    if (position.isBottom) {
-                        topGuideline.setGuidelinePercent(.25f)
-                        mediumConstraintSet.setGuidelinePercent(topGuideline.id, .25f)
-                    } else {
-                        topGuideline.setGuidelinePercent(0f)
-                        mediumConstraintSet.setGuidelinePercent(topGuideline.id, 0f)
-                    }
-
-                    if (mid != -1 && midGuideline != null) {
-                        midGuideline.setGuidelineBegin(mid)
-                    }
-                }
-
                 fun setVisibilities(size: PromptSize) {
                     viewsToHideWhenSmall.forEach { it.showContentOrHide(forceHide = size.isSmall) }
                     largeConstraintSet.setVisibility(iconHolderView.id, View.GONE)
@@ -297,36 +138,151 @@
                     }
                 }
 
+                fun roundCorners(size: PromptSize, position: PromptPosition) {
+                    var left = 0
+                    var top = 0
+                    var right = 0
+                    var bottom = 0
+                    when (size) {
+                        PromptSize.SMALL,
+                        PromptSize.MEDIUM ->
+                            when (position) {
+                                PromptPosition.Right -> {
+                                    left = 0
+                                    top = 0
+                                    right = view.width + cornerRadiusPx
+                                    bottom = view.height
+                                }
+                                PromptPosition.Left -> {
+                                    left = -cornerRadiusPx
+                                    top = 0
+                                    right = view.width
+                                    bottom = view.height
+                                }
+                                PromptPosition.Top -> {
+                                    left = 0
+                                    top = -cornerRadiusPx
+                                    right = panelView.width
+                                    bottom = view.height
+                                }
+                                PromptPosition.Bottom -> {
+                                    left = 0
+                                    top = 0
+                                    right = panelView.width
+                                    bottom = view.height + cornerRadiusPx
+                                }
+                            }
+                        PromptSize.LARGE -> {
+                            left = 0
+                            top = 0
+                            right = view.width
+                            bottom = view.height
+                        }
+                    }
+
+                    // Round the panel outline
+                    panelView.outlineProvider =
+                        object : ViewOutlineProvider() {
+                            override fun getOutline(view: View, outline: Outline) {
+                                outline.setRoundRect(
+                                    left,
+                                    top,
+                                    right,
+                                    bottom,
+                                    cornerRadiusPx.toFloat()
+                                )
+                            }
+                        }
+                }
+
                 view.repeatWhenAttached {
                     var currentSize: PromptSize? = null
 
                     lifecycleScope.launch {
+                        viewModel.guidelineBounds.collect { bounds ->
+                            if (bounds.left >= 0) {
+                                mediumConstraintSet.setGuidelineBegin(leftGuideline.id, bounds.left)
+                                smallConstraintSet.setGuidelineBegin(leftGuideline.id, bounds.left)
+                            } else if (bounds.left < 0) {
+                                mediumConstraintSet.setGuidelineEnd(
+                                    leftGuideline.id,
+                                    abs(bounds.left)
+                                )
+                                smallConstraintSet.setGuidelineEnd(
+                                    leftGuideline.id,
+                                    abs(bounds.left)
+                                )
+                            }
+
+                            if (bounds.right >= 0) {
+                                mediumConstraintSet.setGuidelineEnd(rightGuideline.id, bounds.right)
+                                smallConstraintSet.setGuidelineEnd(rightGuideline.id, bounds.right)
+                            } else if (bounds.right < 0) {
+                                mediumConstraintSet.setGuidelineBegin(
+                                    rightGuideline.id,
+                                    abs(bounds.right)
+                                )
+                                smallConstraintSet.setGuidelineBegin(
+                                    rightGuideline.id,
+                                    abs(bounds.right)
+                                )
+                            }
+
+                            if (midGuideline != null) {
+                                if (bounds.bottom >= 0) {
+                                    midGuideline.setGuidelineEnd(bounds.bottom)
+                                    mediumConstraintSet.setGuidelineEnd(
+                                        midGuideline.id,
+                                        bounds.bottom
+                                    )
+                                } else if (bounds.bottom < 0) {
+                                    midGuideline.setGuidelineBegin(abs(bounds.bottom))
+                                    mediumConstraintSet.setGuidelineBegin(
+                                        midGuideline.id,
+                                        abs(bounds.bottom)
+                                    )
+                                }
+                            }
+                        }
+                    }
+
+                    lifecycleScope.launch {
                         combine(viewModel.position, viewModel.size, ::Pair).collect {
                             (position, size) ->
                             view.doOnAttach {
+                                setVisibilities(size)
+
                                 if (position.isLeft) {
-                                    flipConstraintSet.applyTo(view)
-                                } else if (position.isRight) {
-                                    mediumConstraintSet.applyTo(view)
+                                    if (size.isSmall) {
+                                        flipConstraintSet.clone(smallConstraintSet)
+                                    } else {
+                                        flipConstraintSet.clone(mediumConstraintSet)
+                                    }
+
+                                    // Move all content to other panel
+                                    flipConstraintSet.connect(
+                                        R.id.scrollView,
+                                        ConstraintSet.START,
+                                        R.id.midGuideline,
+                                        ConstraintSet.START
+                                    )
+                                    flipConstraintSet.connect(
+                                        R.id.scrollView,
+                                        ConstraintSet.END,
+                                        R.id.rightGuideline,
+                                        ConstraintSet.END
+                                    )
                                 }
 
-                                measureBounds(position)
-                                setVisibilities(size)
+                                roundCorners(size, position)
+
                                 when {
                                     size.isSmall -> {
-                                        val ratio =
-                                            if (view.isLandscape()) {
-                                                (windowBounds.height() -
-                                                        bottomInset -
-                                                        viewModel.promptMargin)
-                                                    .toFloat() / windowBounds.height()
-                                            } else {
-                                                (windowBounds.height() - viewModel.promptMargin)
-                                                    .toFloat() / windowBounds.height()
-                                            }
-                                        smallConstraintSet.setVerticalBias(iconHolderView.id, ratio)
-
-                                        smallConstraintSet.applyTo(view as ConstraintLayout?)
+                                        if (position.isLeft) {
+                                            flipConstraintSet.applyTo(view)
+                                        } else {
+                                            smallConstraintSet.applyTo(view)
+                                        }
                                     }
                                     size.isMedium && currentSize.isSmall -> {
                                         val autoTransition = AutoTransition()
@@ -338,7 +294,19 @@
                                             view,
                                             autoTransition
                                         )
-                                        mediumConstraintSet.applyTo(view)
+
+                                        if (position.isLeft) {
+                                            flipConstraintSet.applyTo(view)
+                                        } else {
+                                            mediumConstraintSet.applyTo(view)
+                                        }
+                                    }
+                                    size.isMedium -> {
+                                        if (position.isLeft) {
+                                            flipConstraintSet.applyTo(view)
+                                        } else {
+                                            mediumConstraintSet.applyTo(view)
+                                        }
                                     }
                                     size.isLarge -> {
                                         val autoTransition = AutoTransition()
@@ -551,20 +519,6 @@
         }
 }
 
-private fun View.centerX(): Int {
-    return (x + width / 2).toInt()
-}
-
-private fun View.centerY(): Int {
-    return (y + height / 2).toInt()
-}
-
-private fun Rect.shouldAdjustLeftGuideline(): Boolean = left != -1
-
-private fun Rect.shouldAdjustRightGuideline(): Boolean = right != -1
-
-private fun Rect.shouldAdjustBottomGuideline(): Boolean = bottom != -1
-
 private fun View.asVerticalAnimator(
     duration: Long,
     toY: Float,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
index d8265c7..d9d3715 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
@@ -26,6 +26,7 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.airbnb.lottie.LottieAnimationView
+import com.airbnb.lottie.LottieOnCompositionLoadedListener
 import com.android.settingslib.widget.LottieColorUtils
 import com.android.systemui.Flags.constraintBp
 import com.android.systemui.biometrics.ui.viewmodel.PromptIconViewModel
@@ -37,7 +38,6 @@
 import com.android.systemui.util.kotlin.Utils.Companion.toTriple
 import com.android.systemui.util.kotlin.sample
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.launch
 
 /** Sub-binder for [BiometricPromptLayout.iconView]. */
@@ -78,6 +78,8 @@
                     }
 
                 launch {
+                    var lottieOnCompositionLoadedListener: LottieOnCompositionLoadedListener? = null
+
                     combine(viewModel.activeAuthType, viewModel.iconSize, ::Pair).collect {
                         (activeAuthType, iconSize) ->
                         // Every time after bp shows, [isIconViewLoaded] is set to false in
@@ -95,10 +97,18 @@
                                  * TODO(b/288175072): May be able to remove this once constraint
                                  *   layout is implemented
                                  */
-                                iconView.removeAllLottieOnCompositionLoadedListener()
-                                iconView.addLottieOnCompositionLoadedListener {
-                                    promptViewModel.setIsIconViewLoaded(true)
+                                if (lottieOnCompositionLoadedListener != null) {
+                                    iconView.removeLottieOnCompositionLoadedListener(
+                                        lottieOnCompositionLoadedListener!!
+                                    )
                                 }
+                                lottieOnCompositionLoadedListener =
+                                    LottieOnCompositionLoadedListener {
+                                        promptViewModel.setIsIconViewLoaded(true)
+                                    }
+                                iconView.addLottieOnCompositionLoadedListener(
+                                    lottieOnCompositionLoadedListener!!
+                                )
                             }
                             AuthType.Face -> {
                                 /**
@@ -127,14 +137,22 @@
                         if (constraintBp() && position != Rect()) {
                             val iconParams = iconView.layoutParams as ConstraintLayout.LayoutParams
 
-                            if (position.left != -1) {
+                            if (position.left != 0) {
                                 iconParams.endToEnd = ConstraintSet.UNSET
                                 iconParams.leftMargin = position.left
                             }
-                            if (position.top != -1) {
+                            if (position.top != 0) {
                                 iconParams.bottomToBottom = ConstraintSet.UNSET
                                 iconParams.topMargin = position.top
                             }
+                            if (position.right != 0) {
+                                iconParams.startToStart = ConstraintSet.UNSET
+                                iconParams.rightMargin = position.right
+                            }
+                            if (position.bottom != 0) {
+                                iconParams.topToTop = ConstraintSet.UNSET
+                                iconParams.bottomMargin = position.bottom
+                            }
                             iconView.layoutParams = iconParams
                         }
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
index 9949e4c..245817e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -36,7 +36,6 @@
 import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.biometrics.shared.model.AuthenticationReason.NotRunning
 import com.android.systemui.biometrics.shared.model.LottieCallback
 import com.android.systemui.biometrics.ui.viewmodel.SideFpsOverlayViewModel
@@ -73,10 +72,6 @@
 ) : CoreStartable {
 
     override fun start() {
-        if (!SideFpsControllerRefactor.isEnabled) {
-            return
-        }
-
         applicationScope
             .launch {
                 sfpsSensorInteractor.get().isAvailable.collect { isSfpsAvailable ->
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt
index 2797b7b..07e30ce 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.biometrics.ui.viewmodel
 
+import com.android.keyguard.logging.DeviceEntryIconLogger
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
 import com.android.systemui.statusbar.phone.SystemUIDialogManager
@@ -24,6 +25,8 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
 
 /**
  * View model for the UdfpsTouchOverlay for when UDFPS is being requested for device entry. Handles
@@ -37,16 +40,30 @@
     deviceEntryIconViewModel: DeviceEntryIconViewModel,
     alternateBouncerInteractor: AlternateBouncerInteractor,
     systemUIDialogManager: SystemUIDialogManager,
+    logger: DeviceEntryIconLogger,
 ) : UdfpsTouchOverlayViewModel {
+    private val deviceEntryViewAlphaIsMostlyVisible: Flow<Boolean> =
+        deviceEntryIconViewModel.deviceEntryViewAlpha
+            .map { it > ALLOW_TOUCH_ALPHA_THRESHOLD }
+            .distinctUntilChanged()
     override val shouldHandleTouches: Flow<Boolean> =
         combine(
-            deviceEntryIconViewModel.deviceEntryViewAlpha,
-            alternateBouncerInteractor.isVisible,
-            systemUIDialogManager.hideAffordancesRequest
-        ) { deviceEntryViewAlpha, alternateBouncerVisible, hideAffordancesRequest ->
-            (deviceEntryViewAlpha > ALLOW_TOUCH_ALPHA_THRESHOLD && !hideAffordancesRequest) ||
-                alternateBouncerVisible
-        }
+                deviceEntryViewAlphaIsMostlyVisible,
+                alternateBouncerInteractor.isVisible,
+                systemUIDialogManager.hideAffordancesRequest,
+            ) { canTouchDeviceEntryViewAlpha, alternateBouncerVisible, hideAffordancesRequest ->
+                val shouldHandleTouches =
+                    (canTouchDeviceEntryViewAlpha && !hideAffordancesRequest) ||
+                        alternateBouncerVisible
+                logger.logDeviceEntryUdfpsTouchOverlayShouldHandleTouches(
+                    shouldHandleTouches,
+                    canTouchDeviceEntryViewAlpha,
+                    alternateBouncerVisible,
+                    hideAffordancesRequest
+                )
+                shouldHandleTouches
+            }
+            .distinctUntilChanged()
 
     companion object {
         // only allow touches if the view is still mostly visible
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
index d0c140b..8dbed5f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
@@ -94,25 +94,76 @@
                     params.naturalDisplayHeight,
                     rotation.ordinal
                 )
-                rotatedBounds
+                Rect(
+                    rotatedBounds.left,
+                    rotatedBounds.top,
+                    params.logicalDisplayWidth - rotatedBounds.right,
+                    params.logicalDisplayHeight - rotatedBounds.bottom
+                )
             }
             .distinctUntilChanged()
 
     val iconPosition: Flow<Rect> =
-        combine(udfpsSensorBounds, promptViewModel.size, promptViewModel.modalities) {
-            sensorBounds,
-            size,
-            modalities ->
-            // If not Udfps, icon does not change from default layout position
-            if (!modalities.hasUdfps) {
-                Rect() // Empty rect, don't offset from default position
-            } else if (size.isSmall) {
-                // When small with Udfps, only set horizontal position
-                Rect(sensorBounds.left, -1, sensorBounds.right, -1)
-            } else {
-                sensorBounds
+        combine(
+                udfpsSensorBounds,
+                promptViewModel.size,
+                promptViewModel.position,
+                promptViewModel.modalities
+            ) { sensorBounds, size, position, modalities ->
+                when (position) {
+                    PromptPosition.Bottom ->
+                        if (size.isSmall) {
+                            Rect(0, 0, 0, promptViewModel.portraitSmallBottomPadding)
+                        } else if (size.isMedium && modalities.hasUdfps) {
+                            Rect(0, 0, 0, sensorBounds.bottom)
+                        } else if (size.isMedium) {
+                            Rect(0, 0, 0, promptViewModel.portraitMediumBottomPadding)
+                        } else {
+                            // Large screen
+                            Rect(0, 0, 0, promptViewModel.portraitLargeScreenBottomPadding)
+                        }
+                    PromptPosition.Right ->
+                        if (size.isSmall || modalities.hasFaceOnly) {
+                            Rect(
+                                0,
+                                0,
+                                promptViewModel.landscapeSmallHorizontalPadding,
+                                promptViewModel.landscapeSmallBottomPadding
+                            )
+                        } else if (size.isMedium && modalities.hasUdfps) {
+                            Rect(0, 0, sensorBounds.right, sensorBounds.bottom)
+                        } else {
+                            // SFPS
+                            Rect(
+                                0,
+                                0,
+                                promptViewModel.landscapeMediumHorizontalPadding,
+                                promptViewModel.landscapeMediumBottomPadding
+                            )
+                        }
+                    PromptPosition.Left ->
+                        if (size.isSmall || modalities.hasFaceOnly) {
+                            Rect(
+                                promptViewModel.landscapeSmallHorizontalPadding,
+                                0,
+                                0,
+                                promptViewModel.landscapeSmallBottomPadding
+                            )
+                        } else if (size.isMedium && modalities.hasUdfps) {
+                            Rect(sensorBounds.left, 0, 0, sensorBounds.bottom)
+                        } else {
+                            // SFPS
+                            Rect(
+                                promptViewModel.landscapeMediumHorizontalPadding,
+                                0,
+                                0,
+                                promptViewModel.landscapeMediumBottomPadding
+                            )
+                        }
+                    PromptPosition.Top -> Rect()
+                }
             }
-        }
+            .distinctUntilChanged()
 
     /** Whether an error message is currently being shown. */
     val showingError = promptViewModel.showingError
@@ -162,10 +213,11 @@
 
     val iconSize: Flow<Pair<Int, Int>> =
         combine(
+            promptViewModel.position,
             activeAuthType,
             promptViewModel.fingerprintSensorWidth,
             promptViewModel.fingerprintSensorHeight,
-        ) { activeAuthType, fingerprintSensorWidth, fingerprintSensorHeight ->
+        ) { _, activeAuthType, fingerprintSensorWidth, fingerprintSensorHeight ->
             if (activeAuthType == AuthType.Face) {
                 Pair(promptViewModel.faceIconWidth, promptViewModel.faceIconHeight)
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index fbd87fd..4e9acbd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -22,6 +22,7 @@
 import android.graphics.Rect
 import android.graphics.drawable.BitmapDrawable
 import android.graphics.drawable.Drawable
+import android.hardware.biometrics.BiometricFingerprintConstants
 import android.hardware.biometrics.BiometricPrompt
 import android.hardware.biometrics.Flags.customBiometricPrompt
 import android.hardware.biometrics.PromptContentView
@@ -32,6 +33,7 @@
 import com.android.systemui.Flags.constraintBp
 import com.android.systemui.biometrics.UdfpsUtils
 import com.android.systemui.biometrics.Utils
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
 import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
@@ -40,6 +42,7 @@
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.PromptKind
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
 import com.android.systemui.res.R
 import javax.inject.Inject
 import kotlinx.coroutines.Job
@@ -66,6 +69,7 @@
     promptSelectorInteractor: PromptSelectorInteractor,
     @Application private val context: Context,
     private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
+    private val biometricStatusInteractor: BiometricStatusInteractor,
     private val udfpsUtils: UdfpsUtils
 ) {
     /** The set of modalities available for this prompt */
@@ -86,6 +90,36 @@
     val faceIconHeight: Int =
         context.resources.getDimensionPixelSize(R.dimen.biometric_dialog_face_icon_size)
 
+    /** Padding for placing icons */
+    val portraitSmallBottomPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_portrait_small_bottom_padding
+        )
+    val portraitMediumBottomPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_portrait_medium_bottom_padding
+        )
+    val portraitLargeScreenBottomPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_portrait_large_screen_bottom_padding
+        )
+    val landscapeSmallBottomPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_landscape_small_bottom_padding
+        )
+    val landscapeSmallHorizontalPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_landscape_small_horizontal_padding
+        )
+    val landscapeMediumBottomPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_landscape_medium_bottom_padding
+        )
+    val landscapeMediumHorizontalPadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_landscape_medium_horizontal_padding
+        )
+
     val fingerprintSensorWidth: Flow<Int> =
         combine(modalities, udfpsOverlayInteractor.udfpsOverlayParams) { modalities, overlayParams
             ->
@@ -111,9 +145,6 @@
     /** Hint for talkback directional guidance */
     val accessibilityHint: Flow<String> = _accessibilityHint.asSharedFlow()
 
-    val promptMargin: Int =
-        context.resources.getDimensionPixelSize(R.dimen.biometric_dialog_border_padding)
-
     private val _isAuthenticating: MutableStateFlow<Boolean> = MutableStateFlow(false)
 
     /** If the user is currently authenticating (i.e. at least one biometric is scanning). */
@@ -158,6 +189,24 @@
     /** Fingerprint sensor state. */
     val fingerprintStartMode: Flow<FingerprintStartMode> = _fingerprintStartMode.asStateFlow()
 
+    /** Whether a finger has been acquired by the sensor */
+    // TODO(b/331948073): Add support for detecting SFPS finger without authentication running
+    val hasFingerBeenAcquired: Flow<Boolean> =
+        combine(biometricStatusInteractor.fingerprintAcquiredStatus, modalities) {
+                status,
+                modalities ->
+                modalities.hasSfps &&
+                    status is AcquiredFingerprintAuthenticationStatus &&
+                    status.acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START
+            }
+            .distinctUntilChanged()
+
+    /** Whether there is currently a finger on the sensor */
+    val hasFingerOnSensor: Flow<Boolean> =
+        combine(hasFingerBeenAcquired, _isOverlayTouched) { hasFingerBeenAcquired, overlayTouched ->
+            hasFingerBeenAcquired || overlayTouched
+        }
+
     private val _forceLargeSize = MutableStateFlow(false)
     private val _forceMediumSize = MutableStateFlow(false)
 
@@ -205,6 +254,66 @@
             }
             .distinctUntilChanged()
 
+    /** Prompt panel size padding */
+    private val smallHorizontalGuidelinePadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_small_horizontal_guideline_padding
+        )
+    private val udfpsHorizontalGuidelinePadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_udfps_horizontal_guideline_padding
+        )
+    private val udfpsMidGuidelinePadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_udfps_mid_guideline_padding
+        )
+    private val mediumHorizontalGuidelinePadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_medium_horizontal_guideline_padding
+        )
+    private val mediumMidGuidelinePadding =
+        context.resources.getDimensionPixelSize(
+            R.dimen.biometric_prompt_medium_mid_guideline_padding
+        )
+
+    /**
+     * Rect for positioning prompt guidelines (left, top, right, mid)
+     *
+     * Negative values are used to signify that guideline measuring should be flipped, measuring
+     * from opposite side of the screen
+     */
+    val guidelineBounds: Flow<Rect> =
+        combine(size, position, modalities) { size, position, modalities ->
+                if (position.isBottom) {
+                    Rect(0, 0, 0, 0)
+                } else if (position.isRight) {
+                    if (size.isSmall) {
+                        Rect(-smallHorizontalGuidelinePadding, 0, 0, 0)
+                    } else if (modalities.hasUdfps) {
+                        Rect(udfpsHorizontalGuidelinePadding, 0, 0, udfpsMidGuidelinePadding)
+                    } else if (modalities.isEmpty) {
+                        // TODO: Temporary fix until no biometric landscape layout is added
+                        Rect(-mediumHorizontalGuidelinePadding, 0, 0, 6)
+                    } else {
+                        Rect(-mediumHorizontalGuidelinePadding, 0, 0, mediumMidGuidelinePadding)
+                    }
+                } else if (position.isLeft) {
+                    if (size.isSmall) {
+                        Rect(0, 0, -smallHorizontalGuidelinePadding, 0)
+                    } else if (modalities.hasUdfps) {
+                        Rect(0, 0, udfpsHorizontalGuidelinePadding, -udfpsMidGuidelinePadding)
+                    } else if (modalities.isEmpty) {
+                        // TODO: Temporary fix until no biometric landscape layout is added
+                        Rect(0, 0, -mediumHorizontalGuidelinePadding, -6)
+                    } else {
+                        Rect(0, 0, -mediumHorizontalGuidelinePadding, -mediumMidGuidelinePadding)
+                    }
+                } else {
+                    Rect()
+                }
+            }
+            .distinctUntilChanged()
+
     /**
      * If the API caller or the user's personal preferences require explicit confirmation after
      * successful authentication. Confirmation always required when in explicit flow.
@@ -424,7 +533,7 @@
             isAuthenticated,
             promptSelectorInteractor.isCredentialAllowed,
         ) { size, _, authState, credentialAllowed ->
-            size.isNotSmall && authState.isNotAuthenticated && credentialAllowed
+            size.isMedium && authState.isNotAuthenticated && credentialAllowed
         }
 
     private val history = PromptHistoryImpl()
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
index cfda75c..412d0c3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
@@ -28,18 +28,19 @@
 import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
 import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
 import com.airbnb.lottie.model.KeyPath
+import com.android.systemui.Flags.constraintBp
 import com.android.systemui.biometrics.Utils
 import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
 import com.android.systemui.biometrics.domain.model.SideFpsSensorLocation
-import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.LottieCallback
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
 import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
 import com.android.systemui.res.R
+import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
@@ -155,17 +156,19 @@
             ->
             val topLeft = Point(sensorLocation.left, sensorLocation.top)
 
-            if (sensorLocation.isSensorVerticalInDefaultOrientation) {
-                if (displayRotation == DisplayRotation.ROTATION_0) {
-                    topLeft.x -= bounds!!.width()
-                } else if (displayRotation == DisplayRotation.ROTATION_270) {
-                    topLeft.y -= bounds!!.height()
-                }
-            } else {
-                if (displayRotation == DisplayRotation.ROTATION_180) {
-                    topLeft.y -= bounds!!.height()
-                } else if (displayRotation == DisplayRotation.ROTATION_270) {
-                    topLeft.x -= bounds!!.width()
+            if (!constraintBp()) {
+                if (sensorLocation.isSensorVerticalInDefaultOrientation) {
+                    if (displayRotation == DisplayRotation.ROTATION_0) {
+                        topLeft.x -= bounds!!.width()
+                    } else if (displayRotation == DisplayRotation.ROTATION_270) {
+                        topLeft.y -= bounds!!.height()
+                    }
+                } else {
+                    if (displayRotation == DisplayRotation.ROTATION_180) {
+                        topLeft.y -= bounds!!.height()
+                    } else if (displayRotation == DisplayRotation.ROTATION_270) {
+                        topLeft.x -= bounds!!.width()
+                    }
                 }
             }
             defaultOverlayViewParams.apply {
@@ -176,12 +179,9 @@
 
     /** List of LottieCallbacks use for adding dynamic color to the overlayView */
     val lottieCallbacks: Flow<List<LottieCallback>> =
-        combine(
-            biometricStatusInteractor.sfpsAuthenticationReason,
-            deviceEntrySideFpsOverlayInteractor.showIndicatorForDeviceEntry,
-            sideFpsProgressBarViewModel.isVisible
-        ) { reason: AuthenticationReason, showIndicatorForDeviceEntry: Boolean, progressBarIsVisible
-            ->
+        _lottieBounds.sample(deviceEntrySideFpsOverlayInteractor.showIndicatorForDeviceEntry) {
+            _,
+            showIndicatorForDeviceEntry: Boolean ->
             val callbacks = mutableListOf<LottieCallback>()
             if (showIndicatorForDeviceEntry) {
                 val indicatorColor =
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
index 161458f..a90e60d 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
@@ -56,4 +56,22 @@
             broadcastDialog.show();
         }
     }
+
+    /** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device
+     *
+     * @param currentBroadcastAppName Indicates the APP name currently broadcasting
+     * @param outputPkgName Indicates the output media package name to be switched
+     * @param controller Indicates the dialog controller of the source view.
+     */
+    public void createBroadcastDialogWithController(
+            String currentBroadcastAppName, String outputPkgName,
+            DialogTransitionAnimator.Controller controller) {
+        SystemUIDialog broadcastDialog = mBroadcastDialogFactory.create(
+                currentBroadcastAppName, outputPkgName).createDialog();
+        if (controller != null) {
+            mDialogTransitionAnimator.show(broadcastDialog, controller);
+        } else {
+            broadcastDialog.show();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java
index 66aeda6..207f7db 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java
@@ -217,10 +217,13 @@
         mSwitchBroadcast.setText(mContext.getString(
                 R.string.bt_le_audio_broadcast_dialog_switch_app, switchBroadcastApp), null);
         mSwitchBroadcast.setOnClickListener((view) -> startSwitchBroadcast());
-        changeOutput.setOnClickListener((view) -> {
-            mMediaOutputDialogManager.createAndShow(mOutputPackageName, true, null);
-            dialog.dismiss();
-        });
+        changeOutput.setOnClickListener(
+                (view) -> {
+                    // TODO: b/321969740 - Take the userHandle as a parameter and pass it through.
+                    //  The package name is not sufficient to unambiguously identify an app.
+                    mMediaOutputDialogManager.createAndShow(mOutputPackageName, true, null, null);
+                    dialog.dismiss();
+                });
         cancelBtn.setOnClickListener((view) -> {
             if (DEBUG) {
                 Log.d(TAG, "BroadcastDialog dismiss.");
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt
new file mode 100644
index 0000000..e44f054
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import androidx.annotation.StringRes
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.stateIn
+
+internal sealed class AudioSharingButtonState {
+    object Gone : AudioSharingButtonState()
+    data class Visible(@StringRes val resId: Int) : AudioSharingButtonState()
+}
+
+/** Holds business logic for the audio sharing state. */
+@SysUISingleton
+internal class AudioSharingInteractor
+@Inject
+constructor(
+    private val localBluetoothManager: LocalBluetoothManager?,
+    bluetoothStateInteractor: BluetoothStateInteractor,
+    deviceItemInteractor: DeviceItemInteractor,
+    @Application private val coroutineScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) {
+    /** Flow representing the update of AudioSharingButtonState. */
+    internal val audioSharingButtonStateUpdate: Flow<AudioSharingButtonState> =
+        combine(
+                bluetoothStateInteractor.bluetoothStateUpdate,
+                deviceItemInteractor.deviceItemUpdate
+            ) { bluetoothState, deviceItem ->
+                getButtonState(bluetoothState, deviceItem)
+            }
+            .flowOn(backgroundDispatcher)
+            .stateIn(
+                coroutineScope,
+                SharingStarted.WhileSubscribed(replayExpirationMillis = 0),
+                initialValue = AudioSharingButtonState.Gone
+            )
+
+    private fun getButtonState(
+        bluetoothState: Boolean,
+        deviceItem: List<DeviceItem>
+    ): AudioSharingButtonState {
+        return when {
+            // Don't show button when bluetooth is off
+            !bluetoothState -> AudioSharingButtonState.Gone
+            // Show sharing audio when broadcasting
+            BluetoothUtils.isBroadcasting(localBluetoothManager) ->
+                AudioSharingButtonState.Visible(
+                    R.string.quick_settings_bluetooth_audio_sharing_button_sharing
+                )
+            // When not broadcasting, don't show button if there's connected source in any device
+            deviceItem.any {
+                BluetoothUtils.hasConnectedBroadcastSource(
+                    it.cachedBluetoothDevice,
+                    localBluetoothManager
+                )
+            } -> AudioSharingButtonState.Gone
+            // Show audio sharing when there's a connected LE audio device
+            deviceItem.any { BluetoothUtils.isActiveLeAudioDevice(it.cachedBluetoothDevice) } ->
+                AudioSharingButtonState.Visible(
+                    R.string.quick_settings_bluetooth_audio_sharing_button
+                )
+            else -> AudioSharingButtonState.Gone
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnInteractor.kt
new file mode 100644
index 0000000..f86cad5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnInteractor.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+/** Interactor class responsible for interacting with the Bluetooth Auto-On feature. */
+@SysUISingleton
+class BluetoothAutoOnInteractor
+@Inject
+constructor(
+    private val bluetoothAutoOnRepository: BluetoothAutoOnRepository,
+) {
+
+    val isEnabled = bluetoothAutoOnRepository.isAutoOn
+
+    /** Checks if the auto on feature is supported. */
+    suspend fun isAutoOnSupported(): Boolean = bluetoothAutoOnRepository.isAutoOnSupported()
+
+    /**
+     * Sets enabled or disabled based on the provided value.
+     *
+     * @param value `true` to enable the feature, `false` to disable it.
+     */
+    suspend fun setEnabled(value: Boolean) {
+        if (!isAutoOnSupported()) {
+            Log.e(TAG, "Trying to set toggle value while feature not available.")
+        } else {
+            bluetoothAutoOnRepository.setAutoOn(value)
+        }
+    }
+
+    companion object {
+        private const val TAG = "BluetoothAutoOnInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnRepository.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnRepository.kt
new file mode 100644
index 0000000..81fe2a5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnRepository.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.util.Log
+import com.android.settingslib.bluetooth.BluetoothCallback
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+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 javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
+
+/**
+ * Repository class responsible for managing the Bluetooth Auto-On feature settings for the current
+ * user.
+ */
+@SysUISingleton
+class BluetoothAutoOnRepository
+@Inject
+constructor(
+    localBluetoothManager: LocalBluetoothManager?,
+    private val bluetoothAdapter: BluetoothAdapter?,
+    @Application private val coroutineScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) {
+
+    // Flow representing the auto on state for the current user
+    internal val isAutoOn: Flow<Boolean> =
+        localBluetoothManager?.eventManager?.let { eventManager ->
+            conflatedCallbackFlow {
+                    val listener =
+                        object : BluetoothCallback {
+                            override fun onAutoOnStateChanged(autoOnState: Int) {
+                                super.onAutoOnStateChanged(autoOnState)
+                                if (
+                                    autoOnState == BluetoothAdapter.AUTO_ON_STATE_ENABLED ||
+                                        autoOnState == BluetoothAdapter.AUTO_ON_STATE_DISABLED
+                                ) {
+                                    trySendWithFailureLogging(
+                                        autoOnState == BluetoothAdapter.AUTO_ON_STATE_ENABLED,
+                                        TAG,
+                                        "onAutoOnStateChanged"
+                                    )
+                                }
+                            }
+                        }
+                    eventManager.registerCallback(listener)
+                    awaitClose { eventManager.unregisterCallback(listener) }
+                }
+                .onStart { emit(isAutoOnEnabled()) }
+                .flowOn(backgroundDispatcher)
+                .stateIn(
+                    coroutineScope,
+                    SharingStarted.WhileSubscribed(replayExpirationMillis = 0),
+                    initialValue = false
+                )
+        }
+            ?: flowOf(false)
+
+    /**
+     * Checks if the auto on feature is supported for the current user.
+     *
+     * @throws Exception if an error occurs while checking auto-on support.
+     */
+    suspend fun isAutoOnSupported(): Boolean =
+        withContext(backgroundDispatcher) {
+            try {
+                bluetoothAdapter?.isAutoOnSupported ?: false
+            } catch (e: Exception) {
+                // Server could throw TimeoutException, InterruptedException or ExecutionException
+                Log.e(TAG, "Error calling isAutoOnSupported", e)
+                false
+            }
+        }
+
+    /** Sets the Bluetooth Auto-On for the current user. */
+    suspend fun setAutoOn(value: Boolean) {
+        withContext(backgroundDispatcher) {
+            try {
+                bluetoothAdapter?.setAutoOnEnabled(value)
+            } catch (e: Exception) {
+                // Server could throw IllegalStateException, TimeoutException, InterruptedException
+                // or ExecutionException
+                Log.e(TAG, "Error calling setAutoOnEnabled", e)
+            }
+        }
+    }
+
+    private suspend fun isAutoOnEnabled() =
+        withContext(backgroundDispatcher) {
+            try {
+                bluetoothAdapter?.isAutoOnEnabled ?: false
+            } catch (e: Exception) {
+                // Server could throw IllegalStateException, TimeoutException, InterruptedException
+                // or ExecutionException
+                Log.e(TAG, "Error calling isAutoOnEnabled", e)
+                false
+            }
+        }
+
+    private companion object {
+        const val TAG = "BluetoothAutoOnRepository"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt
new file mode 100644
index 0000000..17f9e63
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractor.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothAdapter.STATE_OFF
+import android.bluetooth.BluetoothAdapter.STATE_ON
+import com.android.settingslib.bluetooth.BluetoothCallback
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+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 javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
+
+/** Holds business logic for the Bluetooth Dialog's bluetooth and device connection state */
+@SysUISingleton
+internal class BluetoothStateInteractor
+@Inject
+constructor(
+    private val localBluetoothManager: LocalBluetoothManager?,
+    private val logger: BluetoothTileDialogLogger,
+    @Application private val coroutineScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) {
+
+    internal val bluetoothStateUpdate: StateFlow<Boolean> =
+        conflatedCallbackFlow {
+                val listener =
+                    object : BluetoothCallback {
+                        override fun onBluetoothStateChanged(bluetoothState: Int) {
+                            if (bluetoothState == STATE_ON || bluetoothState == STATE_OFF) {
+                                super.onBluetoothStateChanged(bluetoothState)
+                                logger.logBluetoothState(
+                                    BluetoothStateStage.BLUETOOTH_STATE_CHANGE_RECEIVED,
+                                    BluetoothAdapter.nameForState(bluetoothState)
+                                )
+                                trySendWithFailureLogging(
+                                    bluetoothState == STATE_ON,
+                                    TAG,
+                                    "onBluetoothStateChanged"
+                                )
+                            }
+                        }
+                    }
+                localBluetoothManager?.eventManager?.registerCallback(listener)
+                awaitClose { localBluetoothManager?.eventManager?.unregisterCallback(listener) }
+            }
+            .onStart { emit(isBluetoothEnabled()) }
+            .flowOn(backgroundDispatcher)
+            .stateIn(
+                coroutineScope,
+                SharingStarted.WhileSubscribed(replayExpirationMillis = 0),
+                initialValue = false
+            )
+
+    suspend fun isBluetoothEnabled(): Boolean =
+        withContext(backgroundDispatcher) {
+            localBluetoothManager?.bluetoothAdapter?.isEnabled == true
+        }
+
+    suspend fun setBluetoothEnabled(value: Boolean) {
+        withContext(backgroundDispatcher) {
+            if (isBluetoothEnabled() != value) {
+                localBluetoothManager?.bluetoothAdapter?.apply {
+                    if (value) enable() else disable()
+                    logger.logBluetoothState(
+                        BluetoothStateStage.BLUETOOTH_STATE_VALUE_SET,
+                        value.toString()
+                    )
+                }
+            }
+        }
+    }
+
+    companion object {
+        private const val TAG = "BtStateInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
new file mode 100644
index 0000000..dd8c0df
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.AccessibilityDelegate
+import android.view.View.GONE
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
+import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.ProgressBar
+import android.widget.Switch
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.recyclerview.widget.AsyncListDiffer
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.time.SystemClock
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.withContext
+
+/** Dialog for showing active, connected and saved bluetooth devices. */
+class BluetoothTileDialogDelegate
+@AssistedInject
+internal constructor(
+    @Assisted private val initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
+    @Assisted private val cachedContentHeight: Int,
+    @Assisted private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
+    @Assisted private val dismissListener: Runnable,
+    @Main private val mainDispatcher: CoroutineDispatcher,
+    private val systemClock: SystemClock,
+    private val uiEventLogger: UiEventLogger,
+    private val logger: BluetoothTileDialogLogger,
+    private val systemuiDialogFactory: SystemUIDialog.Factory,
+) : SystemUIDialog.Delegate {
+
+    private val mutableBluetoothStateToggle: MutableStateFlow<Boolean?> = MutableStateFlow(null)
+    internal val bluetoothStateToggle
+        get() = mutableBluetoothStateToggle.asStateFlow()
+
+    private val mutableBluetoothAutoOnToggle: MutableStateFlow<Boolean?> = MutableStateFlow(null)
+    internal val bluetoothAutoOnToggle
+        get() = mutableBluetoothAutoOnToggle.asStateFlow()
+
+    private val mutableDeviceItemClick: MutableSharedFlow<DeviceItem> =
+        MutableSharedFlow(extraBufferCapacity = 1)
+    internal val deviceItemClick
+        get() = mutableDeviceItemClick.asSharedFlow()
+
+    private val mutableContentHeight: MutableSharedFlow<Int> =
+        MutableSharedFlow(extraBufferCapacity = 1)
+    internal val contentHeight
+        get() = mutableContentHeight.asSharedFlow()
+
+    private val deviceItemAdapter: Adapter = Adapter(bluetoothTileDialogCallback)
+
+    private var lastUiUpdateMs: Long = -1
+
+    private var lastItemRow: Int = -1
+
+    @AssistedFactory
+    internal interface Factory {
+        fun create(
+            initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
+            cachedContentHeight: Int,
+            dialogCallback: BluetoothTileDialogCallback,
+            dimissListener: Runnable
+        ): BluetoothTileDialogDelegate
+    }
+
+    override fun createDialog(): SystemUIDialog {
+        return systemuiDialogFactory.create(this)
+    }
+
+    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+        SystemUIDialog.registerDismissListener(dialog, dismissListener)
+        uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_TILE_DIALOG_SHOWN)
+        val context = dialog.context
+
+        LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null).apply {
+            accessibilityPaneTitle = context.getText(R.string.accessibility_desc_quick_settings)
+            dialog.setContentView(this)
+        }
+
+        setupToggle(dialog)
+        setupRecyclerView(dialog)
+
+        getSubtitleTextView(dialog).text = context.getString(initialUiProperties.subTitleResId)
+        dialog.requireViewById<View>(R.id.done_button).setOnClickListener { dialog.dismiss() }
+        getSeeAllButton(dialog).setOnClickListener {
+            bluetoothTileDialogCallback.onSeeAllClicked(it)
+        }
+        getPairNewDeviceButton(dialog).setOnClickListener {
+            bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
+        }
+        getAudioSharingButtonView(dialog).setOnClickListener {
+            bluetoothTileDialogCallback.onAudioSharingButtonClicked(it)
+        }
+        getScrollViewContent(dialog).apply {
+            minimumHeight =
+                resources.getDimensionPixelSize(initialUiProperties.scrollViewMinHeightResId)
+            layoutParams.height = maxOf(cachedContentHeight, minimumHeight)
+        }
+    }
+
+    override fun onStart(dialog: SystemUIDialog) {
+        lastUiUpdateMs = systemClock.elapsedRealtime()
+    }
+
+    override fun onStop(dialog: SystemUIDialog) {
+        mutableContentHeight.tryEmit(getScrollViewContent(dialog).measuredHeight)
+    }
+
+    internal suspend fun animateProgressBar(dialog: SystemUIDialog, animate: Boolean) {
+        withContext(mainDispatcher) {
+            if (animate) {
+                showProgressBar(dialog)
+            } else {
+                delay(PROGRESS_BAR_ANIMATION_DURATION_MS)
+                hideProgressBar(dialog)
+            }
+        }
+    }
+
+    internal suspend fun onDeviceItemUpdated(
+        dialog: SystemUIDialog,
+        deviceItem: List<DeviceItem>,
+        showSeeAll: Boolean,
+        showPairNewDevice: Boolean
+    ) {
+        withContext(mainDispatcher) {
+            val start = systemClock.elapsedRealtime()
+            val itemRow = deviceItem.size + showSeeAll.toInt() + showPairNewDevice.toInt()
+            // If not the first load, add a slight delay for smoother dialog height change
+            if (itemRow != lastItemRow && lastItemRow != -1) {
+                delay(MIN_HEIGHT_CHANGE_INTERVAL_MS - (start - lastUiUpdateMs))
+            }
+            if (isActive) {
+                deviceItemAdapter.refreshDeviceItemList(deviceItem) {
+                    getSeeAllButton(dialog).visibility = if (showSeeAll) VISIBLE else GONE
+                    getPairNewDeviceButton(dialog).visibility =
+                        if (showPairNewDevice) VISIBLE else GONE
+                    // Update the height after data is updated
+                    getScrollViewContent(dialog).layoutParams.height = WRAP_CONTENT
+                    lastUiUpdateMs = systemClock.elapsedRealtime()
+                    lastItemRow = itemRow
+                    logger.logDeviceUiUpdate(lastUiUpdateMs - start)
+                }
+            }
+        }
+    }
+
+    internal fun onBluetoothStateUpdated(
+        dialog: SystemUIDialog,
+        isEnabled: Boolean,
+        uiProperties: BluetoothTileDialogViewModel.UiProperties
+    ) {
+        getToggleView(dialog).apply {
+            isChecked = isEnabled
+            setEnabled(true)
+            alpha = ENABLED_ALPHA
+        }
+        getSubtitleTextView(dialog).text = dialog.context.getString(uiProperties.subTitleResId)
+        getAutoOnToggleView(dialog).visibility = uiProperties.autoOnToggleVisibility
+    }
+
+    internal fun onBluetoothAutoOnUpdated(
+        dialog: SystemUIDialog,
+        isEnabled: Boolean,
+        @StringRes infoResId: Int
+    ) {
+        getAutoOnToggle(dialog).apply {
+            isChecked = isEnabled
+            setEnabled(true)
+            alpha = ENABLED_ALPHA
+        }
+        getAutoOnToggleInfoTextView(dialog).text = dialog.context.getString(infoResId)
+    }
+
+    internal fun onAudioSharingButtonUpdated(
+        dialog: SystemUIDialog,
+        visibility: Int,
+        label: String?
+    ) {
+        getAudioSharingButtonView(dialog).apply {
+            this.visibility = visibility
+            label?.let { text = it }
+        }
+    }
+
+    private fun setupToggle(dialog: SystemUIDialog) {
+        val toggleView = getToggleView(dialog)
+        toggleView.setOnCheckedChangeListener { view, isChecked ->
+            mutableBluetoothStateToggle.value = isChecked
+            view.apply {
+                isEnabled = false
+                alpha = DISABLED_ALPHA
+            }
+            logger.logBluetoothState(BluetoothStateStage.USER_TOGGLED, isChecked.toString())
+            uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_TOGGLE_CLICKED)
+        }
+
+        getAutoOnToggleView(dialog).visibility = initialUiProperties.autoOnToggleVisibility
+        getAutoOnToggle(dialog).setOnCheckedChangeListener { view, isChecked ->
+            mutableBluetoothAutoOnToggle.value = isChecked
+            view.apply {
+                isEnabled = false
+                alpha = DISABLED_ALPHA
+            }
+            uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_AUTO_ON_TOGGLE_CLICKED)
+        }
+    }
+
+    private fun getToggleView(dialog: SystemUIDialog): Switch {
+        return dialog.requireViewById(R.id.bluetooth_toggle)
+    }
+
+    private fun getSubtitleTextView(dialog: SystemUIDialog): TextView {
+        return dialog.requireViewById(R.id.bluetooth_tile_dialog_subtitle)
+    }
+
+    private fun getSeeAllButton(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.see_all_button)
+    }
+
+    private fun getPairNewDeviceButton(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.pair_new_device_button)
+    }
+
+    private fun getDeviceListView(dialog: SystemUIDialog): RecyclerView {
+        return dialog.requireViewById(R.id.device_list)
+    }
+
+    private fun getAutoOnToggle(dialog: SystemUIDialog): Switch {
+        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle)
+    }
+
+    private fun getAudioSharingButtonView(dialog: SystemUIDialog): Button {
+        return dialog.requireViewById(R.id.audio_sharing_button)
+    }
+
+    private fun getAutoOnToggleView(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_layout)
+    }
+
+    private fun getAutoOnToggleInfoTextView(dialog: SystemUIDialog): TextView {
+        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_info_text)
+    }
+
+    private fun getProgressBarAnimation(dialog: SystemUIDialog): ProgressBar {
+        return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
+    }
+
+    private fun getProgressBarBackground(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
+    }
+
+    private fun getScrollViewContent(dialog: SystemUIDialog): View {
+        return dialog.requireViewById(R.id.scroll_view)
+    }
+
+    private fun setupRecyclerView(dialog: SystemUIDialog) {
+        getDeviceListView(dialog).apply {
+            layoutManager = LinearLayoutManager(dialog.context)
+            adapter = deviceItemAdapter
+        }
+    }
+
+    private fun showProgressBar(dialog: SystemUIDialog) {
+        val progressBarAnimation = getProgressBarAnimation(dialog)
+        val progressBarBackground = getProgressBarBackground(dialog)
+        if (progressBarAnimation.visibility != VISIBLE) {
+            progressBarAnimation.visibility = VISIBLE
+            progressBarBackground.visibility = INVISIBLE
+        }
+    }
+
+    private fun hideProgressBar(dialog: SystemUIDialog) {
+        val progressBarAnimation = getProgressBarAnimation(dialog)
+        val progressBarBackground = getProgressBarBackground(dialog)
+        if (progressBarAnimation.visibility != INVISIBLE) {
+            progressBarAnimation.visibility = INVISIBLE
+            progressBarBackground.visibility = VISIBLE
+        }
+    }
+
+    internal inner class Adapter(private val onClickCallback: BluetoothTileDialogCallback) :
+        RecyclerView.Adapter<Adapter.DeviceItemViewHolder>() {
+
+        private val diffUtilCallback =
+            object : DiffUtil.ItemCallback<DeviceItem>() {
+                override fun areItemsTheSame(
+                    deviceItem1: DeviceItem,
+                    deviceItem2: DeviceItem
+                ): Boolean {
+                    return deviceItem1.cachedBluetoothDevice == deviceItem2.cachedBluetoothDevice
+                }
+
+                override fun areContentsTheSame(
+                    deviceItem1: DeviceItem,
+                    deviceItem2: DeviceItem
+                ): Boolean {
+                    return deviceItem1.type == deviceItem2.type &&
+                        deviceItem1.cachedBluetoothDevice == deviceItem2.cachedBluetoothDevice &&
+                        deviceItem1.deviceName == deviceItem2.deviceName &&
+                        deviceItem1.connectionSummary == deviceItem2.connectionSummary &&
+                        // Ignored the icon drawable
+                        deviceItem1.iconWithDescription?.second ==
+                            deviceItem2.iconWithDescription?.second &&
+                        deviceItem1.background == deviceItem2.background &&
+                        deviceItem1.isEnabled == deviceItem2.isEnabled &&
+                        deviceItem1.actionAccessibilityLabel == deviceItem2.actionAccessibilityLabel
+                }
+            }
+
+        private val asyncListDiffer = AsyncListDiffer(this, diffUtilCallback)
+
+        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeviceItemViewHolder {
+            val view =
+                LayoutInflater.from(parent.context)
+                    .inflate(R.layout.bluetooth_device_item, parent, false)
+            return DeviceItemViewHolder(view)
+        }
+
+        override fun getItemCount() = asyncListDiffer.currentList.size
+
+        override fun onBindViewHolder(holder: DeviceItemViewHolder, position: Int) {
+            val item = getItem(position)
+            holder.bind(item, onClickCallback)
+        }
+
+        internal fun getItem(position: Int) = asyncListDiffer.currentList[position]
+
+        internal fun refreshDeviceItemList(updated: List<DeviceItem>, callback: () -> Unit) {
+            asyncListDiffer.submitList(updated, callback)
+        }
+
+        internal inner class DeviceItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+            private val container = view.requireViewById<View>(R.id.bluetooth_device_row)
+            private val nameView = view.requireViewById<TextView>(R.id.bluetooth_device_name)
+            private val summaryView = view.requireViewById<TextView>(R.id.bluetooth_device_summary)
+            private val iconView = view.requireViewById<ImageView>(R.id.bluetooth_device_icon)
+            private val gearView = view.requireViewById<View>(R.id.gear_icon)
+
+            internal fun bind(
+                item: DeviceItem,
+                deviceItemOnClickCallback: BluetoothTileDialogCallback
+            ) {
+                container.apply {
+                    isEnabled = item.isEnabled
+                    background = item.background?.let { context.getDrawable(it) }
+                    setOnClickListener {
+                        mutableDeviceItemClick.tryEmit(item)
+                        uiEventLogger.log(BluetoothTileDialogUiEvent.DEVICE_CLICKED)
+                    }
+                    accessibilityDelegate =
+                        object : AccessibilityDelegate() {
+                            override fun onInitializeAccessibilityNodeInfo(
+                                host: View,
+                                info: AccessibilityNodeInfo
+                            ) {
+                                super.onInitializeAccessibilityNodeInfo(host, info)
+                                info.addAction(
+                                    AccessibilityAction(
+                                        AccessibilityAction.ACTION_CLICK.id,
+                                        item.actionAccessibilityLabel
+                                    )
+                                )
+                            }
+                        }
+                }
+                nameView.text = item.deviceName
+                summaryView.text = item.connectionSummary
+                iconView.apply {
+                    item.iconWithDescription?.let {
+                        setImageDrawable(it.first)
+                        contentDescription = it.second
+                    }
+                }
+                gearView.setOnClickListener {
+                    deviceItemOnClickCallback.onDeviceItemGearClicked(item, it)
+                }
+            }
+        }
+    }
+
+    internal companion object {
+        const val MIN_HEIGHT_CHANGE_INTERVAL_MS = 800L
+        const val MAX_DEVICE_ITEM_ENTRY = 3
+        const val ACTION_BLUETOOTH_DEVICE_DETAILS =
+            "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"
+        const val ACTION_PREVIOUSLY_CONNECTED_DEVICE =
+            "com.android.settings.PREVIOUSLY_CONNECTED_DEVICE"
+        const val ACTION_PAIR_NEW_DEVICE = "android.settings.BLUETOOTH_PAIRING_SETTINGS"
+        const val ACTION_AUDIO_SHARING =
+            "com.google.android.settings.BLUETOOTH_AUDIO_SHARING_SETTINGS"
+        const val DISABLED_ALPHA = 0.3f
+        const val ENABLED_ALPHA = 1f
+        const val PROGRESS_BAR_ANIMATION_DURATION_MS = 1500L
+
+        private fun Boolean.toInt(): Int {
+            return if (this) 1 else 0
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
new file mode 100644
index 0000000..c30aea0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel.DEBUG
+import com.android.systemui.log.dagger.BluetoothTileDialogLog
+import javax.inject.Inject
+
+private const val TAG = "BluetoothTileDialogLog"
+
+enum class BluetoothStateStage {
+    USER_TOGGLED,
+    BLUETOOTH_STATE_VALUE_SET,
+    BLUETOOTH_STATE_CHANGE_RECEIVED
+}
+
+enum class DeviceFetchTrigger {
+    FIRST_LOAD,
+    BLUETOOTH_STATE_CHANGE_RECEIVED,
+    BLUETOOTH_CALLBACK_RECEIVED
+}
+
+enum class JobStatus {
+    FINISHED,
+    CANCELLED
+}
+
+class BluetoothTileDialogLogger
+@Inject
+constructor(@BluetoothTileDialogLog private val logBuffer: LogBuffer) {
+
+    fun logBluetoothState(stage: BluetoothStateStage, state: String) =
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = stage.toString()
+                str2 = state
+            },
+            { "BluetoothState. stage=$str1 state=$str2" }
+        )
+
+    fun logDeviceClick(address: String, type: DeviceItemType) =
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = address
+                str2 = type.toString()
+            },
+            { "DeviceClick. address=$str1 type=$str2" }
+        )
+
+    fun logActiveDeviceChanged(address: String?, profileId: Int) =
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = address
+                int1 = profileId
+            },
+            { "ActiveDeviceChanged. address=$str1 profileId=$int1" }
+        )
+
+    fun logProfileConnectionStateChanged(address: String, state: String, profileId: Int) =
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = address
+                str2 = state
+                int1 = profileId
+            },
+            { "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" }
+        )
+
+    fun logDeviceFetch(status: JobStatus, trigger: DeviceFetchTrigger, duration: Long) =
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = status.toString()
+                str2 = trigger.toString()
+                long1 = duration
+            },
+            { "DeviceFetch. status=$str1 trigger=$str2 duration=$long1" }
+        )
+
+    fun logDeviceUiUpdate(duration: Long) =
+        logBuffer.log(TAG, DEBUG, { long1 = duration }, { "DeviceUiUpdate. duration=$long1" })
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
new file mode 100644
index 0000000..6e51915
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+/** Repository to get CachedBluetoothDevices for the Bluetooth Dialog. */
+@SysUISingleton
+internal class BluetoothTileDialogRepository
+@Inject
+constructor(
+    private val localBluetoothManager: LocalBluetoothManager?,
+    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
+) {
+    internal val cachedDevices: Collection<CachedBluetoothDevice>
+        get() {
+            return if (
+                localBluetoothManager == null ||
+                    bluetoothAdapter == null ||
+                    !bluetoothAdapter.isEnabled
+            ) {
+                emptyList()
+            } else {
+                localBluetoothManager.cachedDeviceManager.cachedDevicesCopy
+            }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.kt
new file mode 100644
index 0000000..b592b8ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogUiEvent.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.bluetooth.qsdialog
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+/** UI Events for the bluetooth tile dialog. */
+enum class BluetoothTileDialogUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum {
+    @UiEvent(doc = "The bluetooth tile dialog is shown") BLUETOOTH_TILE_DIALOG_SHOWN(1493),
+    @UiEvent(doc = "The master toggle is clicked") BLUETOOTH_TOGGLE_CLICKED(1494),
+    @UiEvent(doc = "Pair new device is clicked") PAIR_NEW_DEVICE_CLICKED(1495),
+    @UiEvent(doc = "See all is clicked") SEE_ALL_CLICKED(1496),
+    @UiEvent(doc = "Gear icon clicked") DEVICE_GEAR_CLICKED(1497),
+    @UiEvent(doc = "Device clicked") DEVICE_CLICKED(1498),
+    @UiEvent(doc = "Connected device clicked to active") CONNECTED_DEVICE_SET_ACTIVE(1499),
+    @UiEvent(doc = "Saved clicked to connect") SAVED_DEVICE_CONNECT(1500),
+    @UiEvent(doc = "Active device clicked to disconnect") ACTIVE_DEVICE_DISCONNECT(1507),
+    @UiEvent(doc = "Audio sharing device clicked, do nothing") AUDIO_SHARING_DEVICE_CLICKED(1699),
+    @UiEvent(doc = "Connected other device clicked to disconnect")
+    CONNECTED_OTHER_DEVICE_DISCONNECT(1508),
+    @UiEvent(doc = "The auto on toggle is clicked") BLUETOOTH_AUTO_ON_TOGGLE_CLICKED(1617),
+    @UiEvent(doc = "The audio sharing button is clicked")
+    BLUETOOTH_AUDIO_SHARING_BUTTON_CLICKED(1700);
+
+    override fun getId() = metricId
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
new file mode 100644
index 0000000..eb919e3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup
+import androidx.annotation.DimenRes
+import androidx.annotation.StringRes
+import androidx.annotation.VisibleForTesting
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.systemui.Prefs
+import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_AUDIO_SHARING
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.MAX_DEVICE_ITEM_ENTRY
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.channels.produce
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/** ViewModel for Bluetooth Dialog after clicking on the Bluetooth QS tile. */
+@SysUISingleton
+internal class BluetoothTileDialogViewModel
+@Inject
+constructor(
+    private val deviceItemInteractor: DeviceItemInteractor,
+    private val bluetoothStateInteractor: BluetoothStateInteractor,
+    private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
+    private val audioSharingInteractor: AudioSharingInteractor,
+    private val dialogTransitionAnimator: DialogTransitionAnimator,
+    private val activityStarter: ActivityStarter,
+    private val uiEventLogger: UiEventLogger,
+    @Application private val coroutineScope: CoroutineScope,
+    @Main private val mainDispatcher: CoroutineDispatcher,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    @Main private val sharedPreferences: SharedPreferences,
+    private val bluetoothDialogDelegateFactory: BluetoothTileDialogDelegate.Factory,
+) : BluetoothTileDialogCallback {
+
+    private var job: Job? = null
+
+    /**
+     * Shows the dialog.
+     *
+     * @param view The view from which the dialog is shown.
+     */
+    @kotlinx.coroutines.ExperimentalCoroutinesApi
+    fun showDialog(view: View?) {
+        cancelJob()
+
+        job =
+            coroutineScope.launch(mainDispatcher) {
+                var updateDeviceItemJob: Job?
+                var updateDialogUiJob: Job? = null
+                val dialogDelegate = createBluetoothTileDialog()
+                val dialog = dialogDelegate.createDialog()
+                val context = dialog.context
+
+                view?.let {
+                    dialogTransitionAnimator.showFromView(
+                        dialog,
+                        it,
+                        animateBackgroundBoundsChange = true,
+                        cuj =
+                            DialogCuj(
+                                InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+                                INTERACTION_JANK_TAG
+                            )
+                    )
+                }
+                    ?: dialog.show()
+
+                updateDeviceItemJob = launch {
+                    deviceItemInteractor.updateDeviceItems(context, DeviceFetchTrigger.FIRST_LOAD)
+                }
+
+                // deviceItemUpdate is emitted when device item list is done fetching, update UI and
+                // stop the progress bar.
+                deviceItemInteractor.deviceItemUpdate
+                    .onEach {
+                        updateDialogUiJob?.cancel()
+                        updateDialogUiJob = launch {
+                            dialogDelegate.apply {
+                                onDeviceItemUpdated(
+                                    dialog,
+                                    it.take(MAX_DEVICE_ITEM_ENTRY),
+                                    showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
+                                    showPairNewDevice =
+                                        bluetoothStateInteractor.isBluetoothEnabled()
+                                )
+                                animateProgressBar(dialog, false)
+                            }
+                        }
+                    }
+                    .launchIn(this)
+
+                // deviceItemUpdateRequest is emitted when a bluetooth callback is called, re-fetch
+                // the device item list and animiate the progress bar.
+                deviceItemInteractor.deviceItemUpdateRequest
+                    .onEach {
+                        dialogDelegate.animateProgressBar(dialog, true)
+                        updateDeviceItemJob?.cancel()
+                        updateDeviceItemJob = launch {
+                            deviceItemInteractor.updateDeviceItems(
+                                context,
+                                DeviceFetchTrigger.BLUETOOTH_CALLBACK_RECEIVED
+                            )
+                        }
+                    }
+                    .launchIn(this)
+
+                if (BluetoothUtils.isAudioSharingEnabled()) {
+                    audioSharingInteractor.audioSharingButtonStateUpdate
+                        .onEach {
+                            if (it is AudioSharingButtonState.Visible) {
+                                dialogDelegate.onAudioSharingButtonUpdated(
+                                    dialog,
+                                    VISIBLE,
+                                    context.getString(it.resId)
+                                )
+                            } else {
+                                dialogDelegate.onAudioSharingButtonUpdated(dialog, GONE, null)
+                            }
+                        }
+                        .launchIn(this)
+                }
+
+                // bluetoothStateUpdate is emitted when bluetooth on/off state is changed, re-fetch
+                // the device item list.
+                bluetoothStateInteractor.bluetoothStateUpdate
+                    .onEach {
+                        dialogDelegate.onBluetoothStateUpdated(
+                            dialog,
+                            it,
+                            UiProperties.build(it, isAutoOnToggleFeatureAvailable())
+                        )
+                        updateDeviceItemJob?.cancel()
+                        updateDeviceItemJob = launch {
+                            deviceItemInteractor.updateDeviceItems(
+                                context,
+                                DeviceFetchTrigger.BLUETOOTH_STATE_CHANGE_RECEIVED
+                            )
+                        }
+                    }
+                    .launchIn(this)
+
+                // bluetoothStateToggle is emitted when user toggles the bluetooth state switch,
+                // send the new value to the bluetoothStateInteractor and animate the progress bar.
+                dialogDelegate.bluetoothStateToggle
+                    .filterNotNull()
+                    .onEach {
+                        dialogDelegate.animateProgressBar(dialog, true)
+                        bluetoothStateInteractor.setBluetoothEnabled(it)
+                    }
+                    .launchIn(this)
+
+                // deviceItemClick is emitted when user clicked on a device item.
+                dialogDelegate.deviceItemClick
+                    .onEach { deviceItemInteractor.updateDeviceItemOnClick(it) }
+                    .launchIn(this)
+
+                // contentHeight is emitted when the dialog is dismissed.
+                dialogDelegate.contentHeight
+                    .onEach {
+                        withContext(backgroundDispatcher) {
+                            sharedPreferences.edit().putInt(CONTENT_HEIGHT_PREF_KEY, it).apply()
+                        }
+                    }
+                    .launchIn(this)
+
+                if (isAutoOnToggleFeatureAvailable()) {
+                    // bluetoothAutoOnUpdate is emitted when bluetooth auto on on/off state is
+                    // changed.
+                    bluetoothAutoOnInteractor.isEnabled
+                        .onEach {
+                            dialogDelegate.onBluetoothAutoOnUpdated(
+                                dialog,
+                                it,
+                                if (it) R.string.turn_on_bluetooth_auto_info_enabled
+                                else R.string.turn_on_bluetooth_auto_info_disabled
+                            )
+                        }
+                        .launchIn(this)
+
+                    // bluetoothAutoOnToggle is emitted when user toggles the bluetooth auto on
+                    // switch, send the new value to the bluetoothAutoOnInteractor.
+                    dialogDelegate.bluetoothAutoOnToggle
+                        .filterNotNull()
+                        .onEach { bluetoothAutoOnInteractor.setEnabled(it) }
+                        .launchIn(this)
+                }
+
+                produce<Unit> { awaitClose { dialog.cancel() } }
+            }
+    }
+
+    private suspend fun createBluetoothTileDialog(): BluetoothTileDialogDelegate {
+        val cachedContentHeight =
+            withContext(backgroundDispatcher) {
+                sharedPreferences.getInt(
+                    CONTENT_HEIGHT_PREF_KEY,
+                    ViewGroup.LayoutParams.WRAP_CONTENT
+                )
+            }
+
+        return bluetoothDialogDelegateFactory.create(
+            UiProperties.build(
+                bluetoothStateInteractor.isBluetoothEnabled(),
+                isAutoOnToggleFeatureAvailable()
+            ),
+            cachedContentHeight,
+            this@BluetoothTileDialogViewModel,
+            { cancelJob() }
+        )
+    }
+
+    override fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View) {
+        uiEventLogger.log(BluetoothTileDialogUiEvent.DEVICE_GEAR_CLICKED)
+        val intent =
+            Intent(ACTION_BLUETOOTH_DEVICE_DETAILS).apply {
+                putExtra(
+                    ":settings:show_fragment_args",
+                    Bundle().apply {
+                        putString("device_address", deviceItem.cachedBluetoothDevice.address)
+                    }
+                )
+            }
+        startSettingsActivity(intent, view)
+    }
+
+    override fun onSeeAllClicked(view: View) {
+        uiEventLogger.log(BluetoothTileDialogUiEvent.SEE_ALL_CLICKED)
+        startSettingsActivity(Intent(ACTION_PREVIOUSLY_CONNECTED_DEVICE), view)
+    }
+
+    override fun onPairNewDeviceClicked(view: View) {
+        uiEventLogger.log(BluetoothTileDialogUiEvent.PAIR_NEW_DEVICE_CLICKED)
+        startSettingsActivity(Intent(ACTION_PAIR_NEW_DEVICE), view)
+    }
+
+    override fun onAudioSharingButtonClicked(view: View) {
+        uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_AUDIO_SHARING_BUTTON_CLICKED)
+        startSettingsActivity(Intent(ACTION_AUDIO_SHARING), view)
+    }
+
+    private fun cancelJob() {
+        job?.cancel()
+        job = null
+    }
+
+    private fun startSettingsActivity(intent: Intent, view: View) {
+        if (job?.isActive == true) {
+            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
+            activityStarter.postStartActivityDismissingKeyguard(
+                intent,
+                0,
+                dialogTransitionAnimator.createActivityTransitionController(view)
+            )
+        }
+    }
+
+    @VisibleForTesting
+    internal suspend fun isAutoOnToggleFeatureAvailable() =
+        bluetoothAutoOnInteractor.isAutoOnSupported()
+
+    companion object {
+        private const val INTERACTION_JANK_TAG = "bluetooth_tile_dialog"
+        private const val CONTENT_HEIGHT_PREF_KEY = Prefs.Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT
+        private fun getSubtitleResId(isBluetoothEnabled: Boolean) =
+            if (isBluetoothEnabled) R.string.quick_settings_bluetooth_tile_subtitle
+            else R.string.bt_is_off
+    }
+
+    internal data class UiProperties(
+        @StringRes val subTitleResId: Int,
+        val autoOnToggleVisibility: Int,
+        @DimenRes val scrollViewMinHeightResId: Int,
+    ) {
+        companion object {
+            internal fun build(
+                isBluetoothEnabled: Boolean,
+                isAutoOnToggleFeatureAvailable: Boolean
+            ) =
+                UiProperties(
+                    subTitleResId = getSubtitleResId(isBluetoothEnabled),
+                    autoOnToggleVisibility =
+                        if (isAutoOnToggleFeatureAvailable && !isBluetoothEnabled) VISIBLE
+                        else GONE,
+                    scrollViewMinHeightResId =
+                        if (isAutoOnToggleFeatureAvailable)
+                            R.dimen.bluetooth_dialog_scroll_view_min_height_with_auto_on
+                        else R.dimen.bluetooth_dialog_scroll_view_min_height
+                )
+        }
+    }
+}
+
+interface BluetoothTileDialogCallback {
+    fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View)
+    fun onSeeAllClicked(view: View)
+    fun onPairNewDeviceClicked(view: View)
+    fun onAudioSharingButtonClicked(view: View)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt
new file mode 100644
index 0000000..0ea98d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItem.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.graphics.drawable.Drawable
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+
+enum class DeviceItemType {
+    ACTIVE_MEDIA_BLUETOOTH_DEVICE,
+    AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE,
+    AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
+    CONNECTED_BLUETOOTH_DEVICE,
+    SAVED_BLUETOOTH_DEVICE,
+}
+
+data class DeviceItem(
+    val type: DeviceItemType,
+    val cachedBluetoothDevice: CachedBluetoothDevice,
+    val deviceName: String = "",
+    val connectionSummary: String = "",
+    val iconWithDescription: Pair<Drawable, String>? = null,
+    val background: Int? = null,
+    var isEnabled: Boolean = true,
+    var actionAccessibilityLabel: String = "",
+)
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
new file mode 100644
index 0000000..49d0847
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothDevice
+import android.content.Context
+import android.media.AudioManager
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.settingslib.flags.Flags
+import com.android.settingslib.flags.Flags.enableLeAudioSharing
+import com.android.systemui.res.R
+
+private val backgroundOn = R.drawable.settingslib_switch_bar_bg_on
+private val backgroundOff = R.drawable.bluetooth_tile_dialog_bg_off
+private val backgroundOffBusy = R.drawable.bluetooth_tile_dialog_bg_off_busy
+private val connected = R.string.quick_settings_bluetooth_device_connected
+private val audioSharing = R.string.quick_settings_bluetooth_device_audio_sharing
+private val saved = R.string.quick_settings_bluetooth_device_saved
+private val actionAccessibilityLabelActivate =
+    R.string.accessibility_quick_settings_bluetooth_device_tap_to_activate
+private val actionAccessibilityLabelDisconnect =
+    R.string.accessibility_quick_settings_bluetooth_device_tap_to_disconnect
+
+/** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */
+internal abstract class DeviceItemFactory {
+    abstract fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager,
+    ): Boolean
+
+    abstract fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem
+
+    companion object {
+        @JvmStatic
+        fun createDeviceItem(
+            context: Context,
+            cachedDevice: CachedBluetoothDevice,
+            type: DeviceItemType,
+            connectionSummary: String,
+            background: Int,
+            actionAccessibilityLabel: String
+        ): DeviceItem {
+            return DeviceItem(
+                type = type,
+                cachedBluetoothDevice = cachedDevice,
+                deviceName = cachedDevice.name,
+                connectionSummary = connectionSummary,
+                iconWithDescription =
+                    BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let {
+                        Pair(it.first, it.second)
+                    },
+                background = background,
+                isEnabled = !cachedDevice.isBusy,
+                actionAccessibilityLabel = actionAccessibilityLabel
+            )
+        }
+    }
+}
+
+internal open class ActiveMediaDeviceItemFactory : DeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
+            BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager)
+    }
+
+    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
+        return createDeviceItem(
+            context,
+            cachedDevice,
+            DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE,
+            cachedDevice.connectionSummary ?: "",
+            backgroundOn,
+            context.getString(actionAccessibilityLabelDisconnect)
+        )
+    }
+}
+
+internal class AudioSharingMediaDeviceItemFactory(
+    private val localBluetoothManager: LocalBluetoothManager?
+) : DeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return enableLeAudioSharing() &&
+            BluetoothUtils.hasConnectedBroadcastSource(cachedDevice, localBluetoothManager)
+    }
+
+    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
+        return createDeviceItem(
+            context,
+            cachedDevice,
+            DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE,
+            cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
+                ?: context.getString(audioSharing),
+            if (cachedDevice.isBusy) backgroundOffBusy else backgroundOn,
+            ""
+        )
+    }
+}
+
+internal class ActiveHearingDeviceItemFactory : ActiveMediaDeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
+            BluetoothUtils.isAvailableHearingDevice(cachedDevice)
+    }
+}
+
+internal open class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return !BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
+            BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager)
+    }
+
+    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
+        return createDeviceItem(
+            context,
+            cachedDevice,
+            DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
+            cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
+                ?: context.getString(connected),
+            if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff,
+            context.getString(actionAccessibilityLabelActivate)
+        )
+    }
+}
+
+internal class AvailableHearingDeviceItemFactory : ActiveMediaDeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return !BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
+            BluetoothUtils.isAvailableHearingDevice(cachedDevice)
+    }
+}
+
+internal class ConnectedDeviceItemFactory : DeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
+                BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager)
+        } else {
+            BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager)
+        }
+    }
+
+    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
+        return createDeviceItem(
+            context,
+            cachedDevice,
+            DeviceItemType.CONNECTED_BLUETOOTH_DEVICE,
+            cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
+                ?: context.getString(connected),
+            if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff,
+            context.getString(actionAccessibilityLabelDisconnect)
+        )
+    }
+}
+
+internal open class SavedDeviceItemFactory : DeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
+                cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
+                !cachedDevice.isConnected
+        } else {
+            cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected
+        }
+    }
+
+    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
+        return createDeviceItem(
+            context,
+            cachedDevice,
+            DeviceItemType.SAVED_BLUETOOTH_DEVICE,
+            cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
+                ?: context.getString(saved),
+            if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff,
+            context.getString(actionAccessibilityLabelActivate)
+        )
+    }
+}
+
+internal class SavedHearingDeviceItemFactory : SavedDeviceItemFactory() {
+    override fun isFilterMatched(
+        context: Context,
+        cachedDevice: CachedBluetoothDevice,
+        audioManager: AudioManager
+    ): Boolean {
+        return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
+                context,
+                cachedDevice.getDevice()
+            ) &&
+                cachedDevice.isHearingAidDevice &&
+                cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
+                !cachedDevice.isConnected
+        } else {
+            cachedDevice.isHearingAidDevice &&
+                cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
+                !cachedDevice.isConnected
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
new file mode 100644
index 0000000..66e593b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.content.Context
+import android.media.AudioManager
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.bluetooth.BluetoothCallback
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+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.util.time.SystemClock
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.withContext
+
+/** Holds business logic for the Bluetooth Dialog after clicking on the Bluetooth QS tile. */
+@SysUISingleton
+internal class DeviceItemInteractor
+@Inject
+constructor(
+    private val bluetoothTileDialogRepository: BluetoothTileDialogRepository,
+    private val audioManager: AudioManager,
+    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter(),
+    private val localBluetoothManager: LocalBluetoothManager?,
+    private val systemClock: SystemClock,
+    private val uiEventLogger: UiEventLogger,
+    private val logger: BluetoothTileDialogLogger,
+    @Application private val coroutineScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) {
+
+    private val mutableDeviceItemUpdate: MutableSharedFlow<List<DeviceItem>> =
+        MutableSharedFlow(extraBufferCapacity = 1)
+    internal val deviceItemUpdate
+        get() = mutableDeviceItemUpdate.asSharedFlow()
+
+    internal val deviceItemUpdateRequest: SharedFlow<Unit> =
+        conflatedCallbackFlow {
+                val listener =
+                    object : BluetoothCallback {
+                        override fun onActiveDeviceChanged(
+                            activeDevice: CachedBluetoothDevice?,
+                            bluetoothProfile: Int
+                        ) {
+                            super.onActiveDeviceChanged(activeDevice, bluetoothProfile)
+                            logger.logActiveDeviceChanged(activeDevice?.address, bluetoothProfile)
+                            trySendWithFailureLogging(Unit, TAG, "onActiveDeviceChanged")
+                        }
+
+                        override fun onProfileConnectionStateChanged(
+                            cachedDevice: CachedBluetoothDevice,
+                            state: Int,
+                            bluetoothProfile: Int
+                        ) {
+                            super.onProfileConnectionStateChanged(
+                                cachedDevice,
+                                state,
+                                bluetoothProfile
+                            )
+                            logger.logProfileConnectionStateChanged(
+                                cachedDevice.address,
+                                state.toString(),
+                                bluetoothProfile
+                            )
+                            trySendWithFailureLogging(Unit, TAG, "onProfileConnectionStateChanged")
+                        }
+
+                        override fun onAclConnectionStateChanged(
+                            cachedDevice: CachedBluetoothDevice,
+                            state: Int
+                        ) {
+                            super.onAclConnectionStateChanged(cachedDevice, state)
+                            // Listen only when a device is disconnecting
+                            if (state == 0) {
+                                trySendWithFailureLogging(Unit, TAG, "onAclConnectionStateChanged")
+                            }
+                        }
+                    }
+                localBluetoothManager?.eventManager?.registerCallback(listener)
+                awaitClose { localBluetoothManager?.eventManager?.unregisterCallback(listener) }
+            }
+            .shareIn(coroutineScope, SharingStarted.WhileSubscribed(replayExpirationMillis = 0))
+
+    private var deviceItemFactoryList: List<DeviceItemFactory> =
+        listOf(
+            ActiveMediaDeviceItemFactory(),
+            AudioSharingMediaDeviceItemFactory(localBluetoothManager),
+            AvailableMediaDeviceItemFactory(),
+            ConnectedDeviceItemFactory(),
+            SavedDeviceItemFactory()
+        )
+
+    private var displayPriority: List<DeviceItemType> =
+        listOf(
+            DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE,
+            DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE,
+            DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
+            DeviceItemType.CONNECTED_BLUETOOTH_DEVICE,
+            DeviceItemType.SAVED_BLUETOOTH_DEVICE,
+        )
+
+    internal suspend fun updateDeviceItems(context: Context, trigger: DeviceFetchTrigger) {
+        withContext(backgroundDispatcher) {
+            val start = systemClock.elapsedRealtime()
+            val deviceItems =
+                bluetoothTileDialogRepository.cachedDevices
+                    .mapNotNull { cachedDevice ->
+                        deviceItemFactoryList
+                            .firstOrNull { it.isFilterMatched(context, cachedDevice, audioManager) }
+                            ?.create(context, cachedDevice)
+                    }
+                    .sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices)
+            // Only emit when the job is not cancelled
+            if (isActive) {
+                mutableDeviceItemUpdate.tryEmit(deviceItems)
+                logger.logDeviceFetch(
+                    JobStatus.FINISHED,
+                    trigger,
+                    systemClock.elapsedRealtime() - start
+                )
+            } else {
+                logger.logDeviceFetch(
+                    JobStatus.CANCELLED,
+                    trigger,
+                    systemClock.elapsedRealtime() - start
+                )
+            }
+        }
+    }
+
+    private fun List<DeviceItem>.sort(
+        displayPriority: List<DeviceItemType>,
+        mostRecentlyConnectedDevices: List<BluetoothDevice>?
+    ): List<DeviceItem> {
+        return this.sortedWith(
+            compareBy<DeviceItem> { displayPriority.indexOf(it.type) }
+                .thenBy {
+                    mostRecentlyConnectedDevices?.indexOf(it.cachedBluetoothDevice.device) ?: 0
+                }
+        )
+    }
+
+    internal suspend fun updateDeviceItemOnClick(deviceItem: DeviceItem) {
+        withContext(backgroundDispatcher) {
+            logger.logDeviceClick(deviceItem.cachedBluetoothDevice.address, deviceItem.type)
+
+            deviceItem.cachedBluetoothDevice.apply {
+                when (deviceItem.type) {
+                    DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE -> {
+                        disconnect()
+                        uiEventLogger.log(BluetoothTileDialogUiEvent.ACTIVE_DEVICE_DISCONNECT)
+                    }
+                    DeviceItemType.AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE -> {
+                        uiEventLogger.log(BluetoothTileDialogUiEvent.AUDIO_SHARING_DEVICE_CLICKED)
+                    }
+                    DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> {
+                        setActive()
+                        uiEventLogger.log(BluetoothTileDialogUiEvent.CONNECTED_DEVICE_SET_ACTIVE)
+                    }
+                    DeviceItemType.CONNECTED_BLUETOOTH_DEVICE -> {
+                        disconnect()
+                        uiEventLogger.log(
+                            BluetoothTileDialogUiEvent.CONNECTED_OTHER_DEVICE_DISCONNECT
+                        )
+                    }
+                    DeviceItemType.SAVED_BLUETOOTH_DEVICE -> {
+                        connect()
+                        uiEventLogger.log(BluetoothTileDialogUiEvent.SAVED_DEVICE_CONNECT)
+                    }
+                }
+            }
+        }
+    }
+
+    internal fun setDeviceItemFactoryListForTesting(list: List<DeviceItemFactory>) {
+        deviceItemFactoryList = list
+    }
+
+    internal fun setDisplayPriorityForTesting(list: List<DeviceItemType>) {
+        displayPriority = list
+    }
+
+    companion object {
+        private const val TAG = "DeviceItemInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
index d0ff185..0534824 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
@@ -18,7 +18,7 @@
 
 import android.os.Build
 import android.util.Log
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
+import com.android.keyguard.KeyguardSecurityModel
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
 import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel
 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
@@ -89,7 +89,9 @@
     val resourceUpdateRequests: StateFlow<Boolean>
     val alternateBouncerVisible: StateFlow<Boolean>
     val alternateBouncerUIAvailable: StateFlow<Boolean>
-    val sideFpsShowing: StateFlow<Boolean>
+
+    /** Last shown security mode of the primary bouncer (ie: pin/pattern/password/SIM) */
+    val lastShownSecurityMode: StateFlow<KeyguardSecurityModel.SecurityMode>
 
     /** Action that should be run right after the bouncer is dismissed. */
     var bouncerDismissActionModel: BouncerDismissActionModel?
@@ -126,8 +128,7 @@
 
     fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    fun setSideFpsShowing(isShowing: Boolean)
+    fun setLastShownSecurityMode(securityMode: KeyguardSecurityModel.SecurityMode)
 }
 
 @SysUISingleton
@@ -186,6 +187,11 @@
 
     private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
     override val showMessage = _showMessage.asStateFlow()
+    private val _lastShownSecurityMode =
+        MutableStateFlow(KeyguardSecurityModel.SecurityMode.Invalid)
+    override val lastShownSecurityMode: StateFlow<KeyguardSecurityModel.SecurityMode> =
+        _lastShownSecurityMode.asStateFlow()
+
     private val _resourceUpdateRequests = MutableStateFlow(false)
     override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
 
@@ -196,8 +202,6 @@
     private val _alternateBouncerUIAvailable = MutableStateFlow(false)
     override val alternateBouncerUIAvailable: StateFlow<Boolean> =
         _alternateBouncerUIAvailable.asStateFlow()
-    private val _sideFpsShowing = MutableStateFlow(false)
-    override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
 
     init {
         setUpLogging()
@@ -269,10 +273,8 @@
         _isBackButtonEnabled.value = isBackButtonEnabled
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    override fun setSideFpsShowing(isShowing: Boolean) {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        _sideFpsShowing.value = isShowing
+    override fun setLastShownSecurityMode(securityMode: KeyguardSecurityModel.SecurityMode) {
+        _lastShownSecurityMode.value = securityMode
     }
 
     /** Sets up logs for state flows. */
@@ -321,8 +323,9 @@
         alternateBouncerUIAvailable
             .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
             .launchIn(applicationScope)
-        sideFpsShowing
-            .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
+        lastShownSecurityMode
+            .map { it.name }
+            .logDiffsForTable(buffer, "", "lastShownSecurityMode", null)
             .launchIn(applicationScope)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
index 7525ce0..fa19bf4 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
@@ -27,9 +27,9 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.kotlin.BooleanFlowOperators.or
 import com.android.systemui.util.time.SystemClock
 import dagger.Lazy
 import javax.inject.Inject
@@ -78,15 +78,14 @@
             bouncerRepository.alternateBouncerUIAvailable
         }
     private val isDozingOrAod: Flow<Boolean> =
-        keyguardTransitionInteractor
-            .get()
-            .transitions
-            .map {
-                it.to == KeyguardState.DOZING ||
-                    it.to == KeyguardState.AOD ||
-                    ((it.from == KeyguardState.DOZING || it.from == KeyguardState.AOD) &&
-                        it.transitionState != TransitionState.FINISHED)
-            }
+        or(
+                keyguardTransitionInteractor.get().transitionValue(KeyguardState.DOZING).map {
+                    it > 0f
+                },
+                keyguardTransitionInteractor.get().transitionValue(KeyguardState.AOD).map {
+                    it > 0f
+                },
+            )
             .distinctUntilChanged()
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index aeb564d5..cb458ef 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -16,16 +16,26 @@
 
 package com.android.systemui.bouncer.domain.interactor
 
+import android.app.StatusBarManager.SESSION_KEYGUARD
+import com.android.compose.animation.scene.SceneKey
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.domain.interactor.AuthenticationResult
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Password
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Pattern
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Pin
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel.Sim
 import com.android.systemui.bouncer.data.repository.BouncerRepository
+import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
 import com.android.systemui.classifier.FalsingClassifier
 import com.android.systemui.classifier.domain.interactor.FalsingInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.log.SessionTracker
 import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.async
@@ -47,6 +57,9 @@
     private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
     private val falsingInteractor: FalsingInteractor,
     private val powerInteractor: PowerInteractor,
+    private val uiEventLogger: UiEventLogger,
+    private val sessionTracker: SessionTracker,
+    sceneInteractor: SceneInteractor,
 ) {
     private val _onIncorrectBouncerInput = MutableSharedFlow<Unit>()
     val onIncorrectBouncerInput: SharedFlow<Unit> = _onIncorrectBouncerInput
@@ -80,6 +93,10 @@
             }
             .map {}
 
+    /** The scene to show when bouncer is dismissed. */
+    val dismissDestination: Flow<SceneKey> =
+        sceneInteractor.previousScene(Scenes.Bouncer).map { it ?: Scenes.Lockscreen }
+
     /** Notifies that the user has places down a pointer, not necessarily dragging just yet. */
     fun onDown() {
         falsingInteractor.avoidGesture()
@@ -154,6 +171,18 @@
         ) {
             _onIncorrectBouncerInput.emit(Unit)
         }
+
+        if (authenticationInteractor.getAuthenticationMethod() in setOf(Pin, Password, Pattern)) {
+            if (authResult == AuthenticationResult.SUCCEEDED) {
+                uiEventLogger.log(BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS)
+            } else if (authResult == AuthenticationResult.FAILED) {
+                uiEventLogger.log(
+                    BouncerUiEvent.BOUNCER_PASSWORD_FAILURE,
+                    sessionTracker.getSessionId(SESSION_KEYGUARD)
+                )
+            }
+        }
+
         return authResult
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
index d20c607..1dbf6f1 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -38,7 +38,7 @@
 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.TrustRepository
 import com.android.systemui.user.data.repository.UserRepository
-import com.android.systemui.util.kotlin.Sextuple
+import com.android.systemui.util.kotlin.Septuple
 import com.android.systemui.util.kotlin.combine
 import javax.inject.Inject
 import kotlin.math.roundToInt
@@ -145,15 +145,16 @@
 
     private val initialBouncerMessage: Flow<BouncerMessageModel> =
         combine(
+                primaryBouncerInteractor.lastShownSecurityMode, // required to update defaultMessage
                 biometricSettingsRepository.authenticationFlags,
                 trustRepository.isCurrentUserTrustManaged,
                 isAnyBiometricsEnabledAndEnrolled,
                 deviceEntryFingerprintAuthInteractor.isLockedOut,
                 faceAuthRepository.isLockedOut,
                 isFingerprintAuthCurrentlyAllowedOnBouncer,
-                ::Sextuple
+                ::Septuple
             )
-            .map { (flags, _, biometricsEnrolledAndEnabled, fpLockedOut, faceLockedOut, _) ->
+            .map { (_, flags, _, biometricsEnrolledAndEnabled, fpLockedOut, faceLockedOut, _) ->
                 val isTrustUsuallyManaged = trustRepository.isCurrentUserTrustUsuallyManaged.value
                 val trustOrBiometricsAvailable =
                     (isTrustUsuallyManaged || biometricsEnrolledAndEnabled)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
index d88b3dc..3c5e571 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
@@ -18,18 +18,14 @@
 
 import android.content.Context
 import android.content.res.ColorStateList
-import android.hardware.biometrics.BiometricSourceType
 import android.os.Handler
 import android.os.Trace
 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.systemui.DejankUtils
 import com.android.systemui.Flags
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
@@ -107,6 +103,8 @@
     val resourceUpdateRequests: Flow<Boolean> = repository.resourceUpdateRequests.filter { it }
     val keyguardPosition: Flow<Float> = repository.keyguardPosition.filterNotNull()
     val panelExpansionAmount: Flow<Float> = repository.panelExpansionAmount
+    val lastShownSecurityMode: Flow<KeyguardSecurityModel.SecurityMode> =
+        repository.lastShownSecurityMode
 
     /** 0f = bouncer fully hidden. 1f = bouncer fully visible. */
     val bouncerExpansion: Flow<Float> =
@@ -122,31 +120,9 @@
 
     /** Allow for interaction when just about fully visible */
     val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
     private var currentUserActiveUnlockRunning = false
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /** This callback needs to be a class field so it does not get garbage collected. */
-    val keyguardUpdateMonitorCallback =
-        object : KeyguardUpdateMonitorCallback() {
-            override fun onBiometricRunningStateChanged(
-                running: Boolean,
-                biometricSourceType: BiometricSourceType?
-            ) {
-                updateSideFpsVisibility()
-            }
-
-            override fun onStrongAuthStateChanged(userId: Int) {
-                updateSideFpsVisibility()
-            }
-        }
-
     init {
-        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-        if (!SideFpsControllerRefactor.isEnabled) {
-            keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
-        }
         applicationScope.launch {
             trustRepository.isCurrentUserActiveUnlockRunning.collect {
                 currentUserActiveUnlockRunning = it
@@ -357,36 +333,6 @@
         repository.setPrimaryStartDisappearAnimation(runnable)
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /** Determine whether to show the side fps animation. */
-    fun updateSideFpsVisibility() {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        val sfpsEnabled: Boolean =
-            context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
-        val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
-        val isUnlockingWithFpAllowed: Boolean =
-            keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
-        val toShow =
-            (isBouncerShowing() &&
-                sfpsEnabled &&
-                fpsDetectionRunning &&
-                isUnlockingWithFpAllowed &&
-                !isAnimatingAway())
-
-        if (KeyguardConstants.DEBUG) {
-            Log.d(
-                TAG,
-                ("sideFpsToShow=$toShow\n" +
-                    "isBouncerShowing=${isBouncerShowing()}\n" +
-                    "configEnabled=$sfpsEnabled\n" +
-                    "fpsDetectionRunning=$fpsDetectionRunning\n" +
-                    "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
-                    "isAnimatingAway=${isAnimatingAway()}")
-            )
-        }
-        repository.setSideFpsShowing(toShow)
-    }
-
     /** Returns whether bouncer is fully showing. */
     fun isFullyShowing(): Boolean {
         return (repository.primaryBouncerShowingSoon.value || isBouncerShowing()) &&
@@ -440,6 +386,10 @@
         return isShowing.value
     }
 
+    fun setLastShownPrimarySecurityScreen(securityMode: KeyguardSecurityModel.SecurityMode) {
+        repository.setLastShownSecurityMode(securityMode)
+    }
+
     /** Whether we want to wait to show the bouncer in case passive auth succeeds. */
     private fun usePrimaryBouncerPassiveAuthDelay(): Boolean {
         val canRunActiveUnlock =
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
index e789475..62ef365 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
@@ -18,7 +18,7 @@
 
 import com.android.systemui.Flags
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import dagger.Module
 import dagger.Provides
 
@@ -42,11 +42,10 @@
     fun isOnlyComposeBouncerEnabled(): Boolean
 }
 
-class ComposeBouncerFlagsImpl(private val sceneContainerFlags: SceneContainerFlags) :
-    ComposeBouncerFlags {
+class ComposeBouncerFlagsImpl() : ComposeBouncerFlags {
 
     override fun isComposeBouncerOrSceneContainerEnabled(): Boolean {
-        return sceneContainerFlags.isEnabled() || Flags.composeBouncer()
+        return SceneContainerFlag.isEnabled || Flags.composeBouncer()
     }
 
     @Deprecated(
@@ -55,7 +54,7 @@
         replaceWith = ReplaceWith("isComposeBouncerOrSceneContainerEnabled()")
     )
     override fun isOnlyComposeBouncerEnabled(): Boolean {
-        return !sceneContainerFlags.isEnabled() && Flags.composeBouncer()
+        return !SceneContainerFlag.isEnabled && Flags.composeBouncer()
     }
 }
 
@@ -63,7 +62,7 @@
 object ComposeBouncerFlagsModule {
     @Provides
     @SysUISingleton
-    fun impl(sceneContainerFlags: SceneContainerFlags): ComposeBouncerFlags {
-        return ComposeBouncerFlagsImpl(sceneContainerFlags)
+    fun impl(): ComposeBouncerFlags {
+        return ComposeBouncerFlagsImpl()
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/logging/BouncerUiEvent.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/logging/BouncerUiEvent.kt
new file mode 100644
index 0000000..3be5499
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/logging/BouncerUiEvent.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.shared.logging
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+/**
+ * Legacy bouncer UI events {@link com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent}.
+ * Only contains that used by metrics.
+ */
+enum class BouncerUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
+    @UiEvent(doc = "Bouncer is dismissed using extended security access.")
+    BOUNCER_DISMISS_EXTENDED_ACCESS(413),
+
+    // PASSWORD here includes password, pattern, and pin.
+    @UiEvent(doc = "Bouncer is successfully unlocked using password.")
+    BOUNCER_PASSWORD_SUCCESS(418),
+    @UiEvent(doc = "An attempt to unlock bouncer using password has failed.")
+    BOUNCER_PASSWORD_FAILURE(419);
+
+    override fun getId() = _id
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
index 179fa87..eaca276 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
@@ -1,6 +1,9 @@
 package com.android.systemui.bouncer.ui.binder
 
 import android.view.ViewGroup
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.OnBackPressedDispatcherOwner
+import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
 import androidx.compose.ui.platform.ComposeView
 import androidx.core.view.isVisible
 import androidx.lifecycle.Lifecycle
@@ -30,7 +33,24 @@
     ) {
         view.addView(
             ComposeView(view.context).apply {
-                setContent { PlatformTheme { BouncerContent(viewModel, dialogFactory) } }
+                repeatWhenAttached {
+                    repeatOnLifecycle(Lifecycle.State.CREATED) {
+                        setViewTreeOnBackPressedDispatcherOwner(
+                            object : OnBackPressedDispatcherOwner {
+                                override val onBackPressedDispatcher =
+                                    OnBackPressedDispatcher().apply {
+                                        setOnBackInvokedDispatcher(
+                                            view.viewRootImpl.onBackInvokedDispatcher
+                                        )
+                                    }
+
+                                override val lifecycle: Lifecycle =
+                                    [email protected]
+                            }
+                        )
+                        setContent { PlatformTheme { BouncerContent(viewModel, dialogFactory) } }
+                    }
+                }
             }
         )
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
index cc387e9..b76520b4 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
@@ -27,7 +27,6 @@
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardSecurityView
 import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.bouncer.ui.BouncerViewDelegate
@@ -231,23 +230,6 @@
                             .collect { view.systemUiVisibility = it }
                     }
 
-                    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-                    if (!SideFpsControllerRefactor.isEnabled) {
-                        launch {
-                            viewModel.shouldUpdateSideFps.collect {
-                                viewModel.updateSideFpsVisibility()
-                            }
-                        }
-                    }
-
-                    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-                    if (!SideFpsControllerRefactor.isEnabled) {
-                        launch {
-                            viewModel.sideFpsShowing.collect {
-                                securityContainerController.updateSideFpsVisibility(it)
-                            }
-                        }
-                    }
                     awaitCancellation()
                 } finally {
                     viewModel.setBouncerViewDelegate(null)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 5c07cc57..7c41b75 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -21,6 +21,12 @@
 import android.content.Context
 import android.graphics.Bitmap
 import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.animation.scene.Back
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationWipeModel
@@ -35,6 +41,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.inputmethod.domain.interactor.InputMethodInteractor
+import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.user.ui.viewmodel.UserActionViewModel
 import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel
@@ -82,6 +89,15 @@
                 initialValue = null,
             )
 
+    val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
+        bouncerInteractor.dismissDestination
+            .map(::destinationSceneMap)
+            .stateIn(
+                applicationScope,
+                SharingStarted.WhileSubscribed(),
+                initialValue = destinationSceneMap(Scenes.Lockscreen),
+            )
+
     val message: BouncerMessageViewModel = bouncerMessageViewModel
 
     val userSwitcherDropdown: StateFlow<List<UserSwitcherDropdownItemViewModel>> =
@@ -310,8 +326,7 @@
                 { message },
                 failedAttempts,
                 remainingAttempts,
-            )
-                ?: message
+            ) ?: message
         } else {
             message
         }
@@ -328,8 +343,7 @@
                     .KEYGUARD_DIALOG_FAILED_ATTEMPTS_ERASING_PROFILE,
                 { message },
                 failedAttempts,
-            )
-                ?: message
+            ) ?: message
         } else {
             message
         }
@@ -357,6 +371,12 @@
         }
     }
 
+    private fun destinationSceneMap(prevScene: SceneKey) =
+        mapOf(
+            Back to UserActionResult(prevScene),
+            Swipe(SwipeDirection.Down) to UserActionResult(prevScene),
+        )
+
     data class DialogViewModel(
         val text: String,
 
@@ -400,13 +420,13 @@
             simBouncerInteractor = simBouncerInteractor,
             authenticationInteractor = authenticationInteractor,
             selectedUserInteractor = selectedUserInteractor,
+            devicePolicyManager = devicePolicyManager,
+            bouncerMessageViewModel = bouncerMessageViewModel,
             flags = flags,
             selectedUser = userSwitcherViewModel.selectedUser,
             users = userSwitcherViewModel.users,
             userSwitcherMenu = userSwitcherViewModel.menu,
             actionButton = actionButtonInteractor.actionButton,
-            devicePolicyManager = devicePolicyManager,
-            bouncerMessageViewModel = bouncerMessageViewModel,
         )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
index e1fea5f..3fef766 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.bouncer.ui.viewmodel
 
 import android.view.View
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
 import com.android.systemui.bouncer.ui.BouncerView
@@ -25,9 +24,7 @@
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
 
 /** Models UI state for the lock screen bouncer; handles user input. */
 @ExperimentalCoroutinesApi
@@ -64,19 +61,6 @@
     /** Observe whether keyguard is authenticated already. */
     val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticatedBiometrics
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /** Observe whether the side fps is showing. */
-    val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /** Observe whether we should update fps is showing. */
-    val shouldUpdateSideFps: Flow<Unit> =
-        merge(
-            interactor.isShowing.map {},
-            interactor.startingToHide,
-            interactor.startingDisappearAnimation.filterNotNull().map {}
-        )
-
     /** Observe whether we want to update resources. */
     fun notifyUpdateResources() {
         interactor.notifyUpdatedResources()
@@ -92,12 +76,6 @@
         interactor.onMessageShown()
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    fun updateSideFpsVisibility() {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        interactor.updateSideFpsVisibility()
-    }
-
     /** Observe whether back button is enabled. */
     fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
         return interactor.isBackButtonEnabled.map { enabled ->
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
index 62da5c0..4c2380c 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
@@ -99,7 +99,7 @@
             .map { if (it) ActionButtonAppearance.Hidden else ActionButtonAppearance.Shown }
             .stateIn(
                 scope = viewModelScope,
-                started = SharingStarted.Eagerly,
+                started = SharingStarted.WhileSubscribed(),
                 initialValue = ActionButtonAppearance.Hidden,
             )
 
@@ -135,8 +135,11 @@
 
         onIntentionalUserInput()
 
-        mutablePinInput.value = pinInput.append(input)
-        tryAuthenticate(useAutoConfirm = true)
+        val maxInputLength = hintedPinLength.value ?: Int.MAX_VALUE
+        if (pinInput.getPin().size < maxInputLength) {
+            mutablePinInput.value = pinInput.append(input)
+            tryAuthenticate(useAutoConfirm = true)
+        }
     }
 
     /** Notifies that the user clicked the backspace button. */
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index 357eca3..d2caefd 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -398,6 +398,7 @@
                 || mAccessibilityManager.isTouchExplorationEnabled()
                 || mDataProvider.isA11yAction()
                 || mDataProvider.isFromTrackpad()
+                || mDataProvider.isFromKeyboard()
                 || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
                     && mDataProvider.isUnfolded());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
index a79a654..76b228d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.classifier;
 
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 /**
@@ -50,6 +51,14 @@
     void onBouncerHidden();
 
     /**
+     * Call this to record a KeyEvent in the {@link com.android.systemui.plugins.FalsingManager}.
+     *
+     * This may decide to only collect certain KeyEvents and ignore others. Do not assume all
+     * KeyEvents are collected.
+     */
+    void onKeyEvent(KeyEvent ev);
+
+    /**
      * Call this to record a MotionEvent in the {@link com.android.systemui.plugins.FalsingManager}.
      *
      * Be sure to call {@link #onMotionEventComplete()} after the rest of SystemUI is done with the
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
index d6b9a11..dcd4195 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.classifier;
 
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 import javax.inject.Inject;
@@ -23,6 +24,8 @@
 /** */
 public class FalsingCollectorFake implements FalsingCollector {
 
+    public KeyEvent lastKeyEvent = null;
+
     @Override
     public void init() {
     }
@@ -70,6 +73,11 @@
     }
 
     @Override
+    public void onKeyEvent(KeyEvent ev) {
+        lastKeyEvent = ev;
+    }
+
+    @Override
     public void onTouchEvent(MotionEvent ev) {
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 4f4f3d0..beaa170 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -21,6 +21,7 @@
 import android.hardware.SensorManager;
 import android.hardware.biometrics.BiometricSourceType;
 import android.util.Log;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 import androidx.annotation.VisibleForTesting;
@@ -49,7 +50,10 @@
 
 import dagger.Lazy;
 
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.inject.Inject;
 
@@ -61,6 +65,14 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final long GESTURE_PROCESSING_DELAY_MS = 100;
 
+    private final Set<Integer> mAcceptedKeycodes = new HashSet<>(Arrays.asList(
+        KeyEvent.KEYCODE_ENTER,
+        KeyEvent.KEYCODE_ESCAPE,
+        KeyEvent.KEYCODE_SHIFT_LEFT,
+        KeyEvent.KEYCODE_SHIFT_RIGHT,
+        KeyEvent.KEYCODE_SPACE
+    ));
+
     private final FalsingDataProvider mFalsingDataProvider;
     private final FalsingManager mFalsingManager;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -279,6 +291,14 @@
     }
 
     @Override
+    public void onKeyEvent(KeyEvent ev) {
+        // Only collect if it is an ACTION_UP action and is allow-listed
+        if (ev.getAction() == KeyEvent.ACTION_UP && mAcceptedKeycodes.contains(ev.getKeyCode())) {
+            mFalsingDataProvider.onKeyEvent(ev);
+        }
+    }
+
+    @Override
     public void onTouchEvent(MotionEvent ev) {
         logDebug("REAL: onTouchEvent(" + ev.getActionMasked() + ")");
         if (!mKeyguardStateController.isShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt
index c5d8c79..b289fa4 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorNoOp.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.classifier
 
+import android.view.KeyEvent
 import android.view.MotionEvent
 import com.android.systemui.classifier.FalsingCollectorImpl.logDebug
 import com.android.systemui.dagger.SysUISingleton
@@ -59,6 +60,10 @@
         logDebug("NOOP: onBouncerHidden")
     }
 
+    override fun onKeyEvent(ev: KeyEvent) {
+        logDebug("NOOP: onKeyEvent(${ev.action}")
+    }
+
     override fun onTouchEvent(ev: MotionEvent) {
         logDebug("NOOP: onTouchEvent(${ev.actionMasked})")
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 809d5b2..1501701 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -20,6 +20,7 @@
 
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
 import android.util.DisplayMetrics;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
@@ -41,6 +42,7 @@
 public class FalsingDataProvider {
 
     private static final long MOTION_EVENT_AGE_MS = 1000;
+    private static final long KEY_EVENT_AGE_MS = 500;
     private static final long DROP_EVENT_THRESHOLD_MS = 50;
     private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
 
@@ -56,8 +58,10 @@
     private final List<MotionEventListener> mMotionEventListeners = new ArrayList<>();
     private final List<GestureFinalizedListener> mGestureFinalizedListeners = new ArrayList<>();
 
-    private TimeLimitedMotionEventBuffer mRecentMotionEvents =
-            new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
+    private TimeLimitedInputEventBuffer<MotionEvent> mRecentMotionEvents =
+            new TimeLimitedInputEventBuffer<>(MOTION_EVENT_AGE_MS);
+    private final TimeLimitedInputEventBuffer<KeyEvent> mRecentKeyEvents =
+            new TimeLimitedInputEventBuffer<>(KEY_EVENT_AGE_MS);
     private List<MotionEvent> mPriorMotionEvents = new ArrayList<>();
 
     private boolean mDirty = true;
@@ -89,6 +93,10 @@
         FalsingClassifier.logInfo("width, height: " + getWidthPixels() + ", " + getHeightPixels());
     }
 
+    void onKeyEvent(KeyEvent keyEvent) {
+        mRecentKeyEvents.add(keyEvent);
+    }
+
     void onMotionEvent(MotionEvent motionEvent) {
         List<MotionEvent> motionEvents = unpackMotionEvent(motionEvent);
         FalsingClassifier.logVerbose("Unpacked into: " + motionEvents.size());
@@ -109,6 +117,10 @@
         // previous ACTION_MOVE event and when it happens, it makes some classifiers fail.
         mDropLastEvent = shouldDropEvent(motionEvent);
 
+        if (!motionEvents.isEmpty() && !mRecentKeyEvents.isEmpty()) {
+            recycleAndClearRecentKeyEvents();
+        }
+
         mRecentMotionEvents.addAll(motionEvents);
 
         FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size());
@@ -141,7 +153,7 @@
                     mRecentMotionEvents.get(mRecentMotionEvents.size() - 1).getEventTime()));
 
             mPriorMotionEvents = mRecentMotionEvents;
-            mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
+            mRecentMotionEvents = new TimeLimitedInputEventBuffer<>(MOTION_EVENT_AGE_MS);
         }
         mDropLastEvent = false;
         mA11YAction = false;
@@ -261,6 +273,13 @@
         return mLastMotionEvent.getY() < mFirstRecentMotionEvent.getY();
     }
 
+    /**
+     * If it's a specific set of keys as collected from {@link FalsingCollector}
+     */
+    public boolean isFromKeyboard() {
+        return !mRecentKeyEvents.isEmpty();
+    }
+
     public boolean isFromTrackpad() {
         if (mRecentMotionEvents.isEmpty()) {
             return false;
@@ -318,6 +337,14 @@
         }
     }
 
+    private void recycleAndClearRecentKeyEvents() {
+        for (KeyEvent ev : mRecentKeyEvents) {
+            ev.recycle();
+        }
+
+        mRecentKeyEvents.clear();
+    }
+
     private List<MotionEvent> unpackMotionEvent(MotionEvent motionEvent) {
         List<MotionEvent> motionEvents = new ArrayList<>();
         List<PointerProperties> pointerPropertiesList = new ArrayList<>();
@@ -416,6 +443,8 @@
 
         mRecentMotionEvents.clear();
 
+        recycleAndClearRecentKeyEvents();
+
         mDirty = true;
 
         mSessionListeners.forEach(SessionListener::onSessionEnded);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
index af467ef..613280c 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
@@ -22,7 +22,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.statusbar.phone.NotificationTapHelper;
 
 import dagger.Binds;
@@ -51,9 +51,8 @@
     @SysUISingleton
     static FalsingCollector providesFalsingCollectorLegacy(
             FalsingCollectorImpl impl,
-            FalsingCollectorNoOp noOp,
-            SceneContainerFlags flags) {
-        return flags.isEnabled() ? noOp : impl;
+            FalsingCollectorNoOp noOp) {
+        return SceneContainerFlag.isEnabled() ? noOp : impl;
     }
 
     /** Provides the actual {@link FalsingCollector}. */
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedInputEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedInputEventBuffer.java
new file mode 100644
index 0000000..7627ad1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedInputEventBuffer.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.classifier;
+
+import android.view.InputEvent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * Maintains an ordered list of the last N milliseconds of InputEvents.
+ *
+ * This class is simply a convenience class designed to look like a simple list, but that
+ * automatically discards old InputEvents. It functions much like a queue - first in first out -
+ * but does not have a fixed size like a circular buffer.
+ */
+public class TimeLimitedInputEventBuffer<T extends InputEvent> implements List<T> {
+
+    private final List<T> mInputEvents;
+    private final long mMaxAgeMs;
+
+    public TimeLimitedInputEventBuffer(long maxAgeMs) {
+        super();
+        mMaxAgeMs = maxAgeMs;
+        mInputEvents = new ArrayList<>();
+    }
+
+    private void ejectOldEvents() {
+        if (mInputEvents.isEmpty()) {
+            return;
+        }
+        Iterator<T> iter = listIterator();
+        long mostRecentMs = mInputEvents.get(mInputEvents.size() - 1).getEventTime();
+        while (iter.hasNext()) {
+            T ev = iter.next();
+            if (mostRecentMs - ev.getEventTime() > mMaxAgeMs) {
+                iter.remove();
+                ev.recycle();
+            }
+        }
+    }
+
+    @Override
+    public void add(int index, T element) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public T remove(int index) {
+        return mInputEvents.remove(index);
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        return mInputEvents.indexOf(o);
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        return mInputEvents.lastIndexOf(o);
+    }
+
+    @Override
+    public int size() {
+        return mInputEvents.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return mInputEvents.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return mInputEvents.contains(o);
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return mInputEvents.iterator();
+    }
+
+    @Override
+    public Object[] toArray() {
+        return mInputEvents.toArray();
+    }
+
+    @Override
+    public <T2> T2[] toArray(T2[] a) {
+        return mInputEvents.toArray(a);
+    }
+
+    @Override
+    public boolean add(T element) {
+        boolean result = mInputEvents.add(element);
+        ejectOldEvents();
+        return result;
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        return mInputEvents.remove(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        return mInputEvents.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends T> collection) {
+        boolean result = mInputEvents.addAll(collection);
+        ejectOldEvents();
+        return result;
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends T> elements) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        return mInputEvents.removeAll(c);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        return mInputEvents.retainAll(c);
+    }
+
+    @Override
+    public void clear() {
+        mInputEvents.clear();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return mInputEvents.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return mInputEvents.hashCode();
+    }
+
+    @Override
+    public T get(int index) {
+        return mInputEvents.get(index);
+    }
+
+    @Override
+    public T set(int index, T element) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ListIterator<T> listIterator() {
+        return new Iter(0);
+    }
+
+    @Override
+    public ListIterator<T> listIterator(int index) {
+        return new Iter(index);
+    }
+
+    @Override
+    public List<T> subList(int fromIndex, int toIndex) {
+        return mInputEvents.subList(fromIndex, toIndex);
+    }
+
+    class Iter implements ListIterator<T> {
+
+        private final ListIterator<T> mIterator;
+
+        Iter(int index) {
+            this.mIterator = mInputEvents.listIterator(index);
+        }
+
+        @Override
+        public boolean hasNext() {
+            return mIterator.hasNext();
+        }
+
+        @Override
+        public T next() {
+            return mIterator.next();
+        }
+
+        @Override
+        public boolean hasPrevious() {
+            return mIterator.hasPrevious();
+        }
+
+        @Override
+        public T previous() {
+            return mIterator.previous();
+        }
+
+        @Override
+        public int nextIndex() {
+            return mIterator.nextIndex();
+        }
+
+        @Override
+        public int previousIndex() {
+            return mIterator.previousIndex();
+        }
+
+        @Override
+        public void remove() {
+            mIterator.remove();
+        }
+
+        @Override
+        public void set(T inputEvent) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void add(T element) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
deleted file mode 100644
index 51aede7..0000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.classifier;
-
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- * Maintains an ordered list of the last N milliseconds of MotionEvents.
- *
- * This class is simply a convenience class designed to look like a simple list, but that
- * automatically discards old MotionEvents. It functions much like a queue - first in first out -
- * but does not have a fixed size like a circular buffer.
- */
-public class TimeLimitedMotionEventBuffer implements List<MotionEvent> {
-
-    private final List<MotionEvent> mMotionEvents;
-    private final long mMaxAgeMs;
-
-    public TimeLimitedMotionEventBuffer(long maxAgeMs) {
-        super();
-        mMaxAgeMs = maxAgeMs;
-        mMotionEvents = new ArrayList<>();
-    }
-
-    private void ejectOldEvents() {
-        if (mMotionEvents.isEmpty()) {
-            return;
-        }
-        Iterator<MotionEvent> iter = listIterator();
-        long mostRecentMs = mMotionEvents.get(mMotionEvents.size() - 1).getEventTime();
-        while (iter.hasNext()) {
-            MotionEvent ev = iter.next();
-            if (mostRecentMs - ev.getEventTime() > mMaxAgeMs) {
-                iter.remove();
-                ev.recycle();
-            }
-        }
-    }
-
-    @Override
-    public void add(int index, MotionEvent element) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public MotionEvent remove(int index) {
-        return mMotionEvents.remove(index);
-    }
-
-    @Override
-    public int indexOf(Object o) {
-        return mMotionEvents.indexOf(o);
-    }
-
-    @Override
-    public int lastIndexOf(Object o) {
-        return mMotionEvents.lastIndexOf(o);
-    }
-
-    @Override
-    public int size() {
-        return mMotionEvents.size();
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return mMotionEvents.isEmpty();
-    }
-
-    @Override
-    public boolean contains(Object o) {
-        return mMotionEvents.contains(o);
-    }
-
-    @Override
-    public Iterator<MotionEvent> iterator() {
-        return mMotionEvents.iterator();
-    }
-
-    @Override
-    public Object[] toArray() {
-        return mMotionEvents.toArray();
-    }
-
-    @Override
-    public <T> T[] toArray(T[] a) {
-        return mMotionEvents.toArray(a);
-    }
-
-    @Override
-    public boolean add(MotionEvent element) {
-        boolean result = mMotionEvents.add(element);
-        ejectOldEvents();
-        return result;
-    }
-
-    @Override
-    public boolean remove(Object o) {
-        return mMotionEvents.remove(o);
-    }
-
-    @Override
-    public boolean containsAll(Collection<?> c) {
-        return mMotionEvents.containsAll(c);
-    }
-
-    @Override
-    public boolean addAll(Collection<? extends MotionEvent> collection) {
-        boolean result = mMotionEvents.addAll(collection);
-        ejectOldEvents();
-        return result;
-    }
-
-    @Override
-    public boolean addAll(int index, Collection<? extends MotionEvent> elements) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean removeAll(Collection<?> c) {
-        return mMotionEvents.removeAll(c);
-    }
-
-    @Override
-    public boolean retainAll(Collection<?> c) {
-        return mMotionEvents.retainAll(c);
-    }
-
-    @Override
-    public void clear() {
-        mMotionEvents.clear();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        return mMotionEvents.equals(o);
-    }
-
-    @Override
-    public int hashCode() {
-        return mMotionEvents.hashCode();
-    }
-
-    @Override
-    public MotionEvent get(int index) {
-        return mMotionEvents.get(index);
-    }
-
-    @Override
-    public MotionEvent set(int index, MotionEvent element) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public ListIterator<MotionEvent> listIterator() {
-        return new Iter(0);
-    }
-
-    @Override
-    public ListIterator<MotionEvent> listIterator(int index) {
-        return new Iter(index);
-    }
-
-    @Override
-    public List<MotionEvent> subList(int fromIndex, int toIndex) {
-        return mMotionEvents.subList(fromIndex, toIndex);
-    }
-
-    class Iter implements ListIterator<MotionEvent> {
-
-        private final ListIterator<MotionEvent> mIterator;
-
-        Iter(int index) {
-            this.mIterator = mMotionEvents.listIterator(index);
-        }
-
-        @Override
-        public boolean hasNext() {
-            return mIterator.hasNext();
-        }
-
-        @Override
-        public MotionEvent next() {
-            return mIterator.next();
-        }
-
-        @Override
-        public boolean hasPrevious() {
-            return mIterator.hasPrevious();
-        }
-
-        @Override
-        public MotionEvent previous() {
-            return mIterator.previous();
-        }
-
-        @Override
-        public int nextIndex() {
-            return mIterator.nextIndex();
-        }
-
-        @Override
-        public int previousIndex() {
-            return mIterator.previousIndex();
-        }
-
-        @Override
-        public void remove() {
-            mIterator.remove();
-        }
-
-        @Override
-        public void set(MotionEvent motionEvent) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void add(MotionEvent element) {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
index d4a1f74..0c181e9 100644
--- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
@@ -16,14 +16,14 @@
 
 package com.android.systemui.common.coroutine
 
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow as wrapped
 import kotlin.experimental.ExperimentalTypeInference
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.channels.ProducerScope
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.buffer
 import kotlinx.coroutines.flow.callbackFlow
 
+@Deprecated("Use com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow instead")
 object ConflatedCallbackFlow {
 
     /**
@@ -32,9 +32,15 @@
      * consumer(s) of the values in the flow), the values are buffered and, if the buffer fills up,
      * we drop the oldest values automatically instead of suspending the producer.
      */
-    @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-    @OptIn(ExperimentalTypeInference::class, ExperimentalCoroutinesApi::class)
+    @Deprecated(
+        "Use com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow instead",
+        ReplaceWith(
+            "conflatedCallbackFlow",
+            "com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow"
+        )
+    )
+    @OptIn(ExperimentalTypeInference::class)
     fun <T> conflatedCallbackFlow(
         @BuilderInference block: suspend ProducerScope<T>.() -> Unit,
-    ): Flow<T> = callbackFlow(block).buffer(capacity = Channel.CONFLATED)
+    ): Flow<T> = wrapped(block)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
index 5f6ff82..638af58 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
@@ -56,6 +56,13 @@
     val naturalMaxBounds: Flow<Rect> =
         repository.configurationValues.map { it.naturalScreenBounds }.distinctUntilChanged()
 
+    /**
+     * The layout direction. Will be either `View#LAYOUT_DIRECTION_LTR` or
+     * `View#LAYOUT_DIRECTION_RTL`.
+     */
+    val layoutDirection: Flow<Int> =
+        repository.configurationValues.map { it.layoutDirection }.distinctUntilChanged()
+
     /** Given [resourceId], emit the dimension pixel size on config change */
     fun dimensionPixelSize(resourceId: Int): Flow<Int> {
         return onAnyConfigurationChange.mapLatest { repository.getDimensionPixelSize(resourceId) }
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt
index ce798ba..f7ea25c 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.common.ui.view
 
 import android.view.View
+import kotlinx.coroutines.DisposableHandle
 
 /**
  * Set this view's [View#importantForAccessibility] to [View#IMPORTANT_FOR_ACCESSIBILITY_YES] or
@@ -43,3 +44,27 @@
     }
     return null
 }
+
+/** Adds a [View.OnLayoutChangeListener] and provides a [DisposableHandle] for teardown. */
+fun View.onLayoutChanged(onLayoutChanged: (v: View) -> Unit): DisposableHandle =
+    onLayoutChanged { v, _, _, _, _, _, _, _, _ ->
+        onLayoutChanged(v)
+    }
+
+/** Adds the [View.OnLayoutChangeListener] and provides a [DisposableHandle] for teardown. */
+fun View.onLayoutChanged(listener: View.OnLayoutChangeListener): DisposableHandle {
+    addOnLayoutChangeListener(listener)
+    return DisposableHandle { removeOnLayoutChangeListener(listener) }
+}
+
+/** Adds a [View.OnApplyWindowInsetsListener] and provides a [DisposableHandle] for teardown. */
+fun View.onApplyWindowInsets(listener: View.OnApplyWindowInsetsListener): DisposableHandle {
+    setOnApplyWindowInsetsListener(listener)
+    return DisposableHandle { setOnApplyWindowInsetsListener(null) }
+}
+
+/** Adds a [View.OnTouchListener] and provides a [DisposableHandle] for teardown. */
+fun View.onTouchListener(listener: View.OnTouchListener): DisposableHandle {
+    setOnTouchListener(listener)
+    return DisposableHandle { setOnTouchListener(null) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalBackupRestoreStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalBackupRestoreStartable.kt
new file mode 100644
index 0000000..cdeeb6f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalBackupRestoreStartable.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal
+
+import android.appwidget.AppWidgetManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import com.android.systemui.CoreStartable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.widgets.CommunalWidgetModule
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.CommunalLog
+import javax.inject.Inject
+
+@SysUISingleton
+class CommunalBackupRestoreStartable
+@Inject
+constructor(
+    private val broadcastDispatcher: BroadcastDispatcher,
+    private val communalInteractor: CommunalInteractor,
+    @CommunalLog logBuffer: LogBuffer,
+) : CoreStartable, BroadcastReceiver() {
+
+    private val logger = Logger(logBuffer, TAG)
+
+    override fun start() {
+        broadcastDispatcher.registerReceiver(
+            receiver = this,
+            filter = IntentFilter(AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED),
+        )
+    }
+
+    override fun onReceive(context: Context?, intent: Intent?) {
+        if (intent == null) {
+            logger.w("On app widget host restored, but intent is null")
+            return
+        }
+
+        if (intent.action != AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED) {
+            return
+        }
+
+        val hostId = intent.getIntExtra(AppWidgetManager.EXTRA_HOST_ID, 0)
+        if (hostId != CommunalWidgetModule.APP_WIDGET_HOST_ID) {
+            return
+        }
+
+        val oldIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS)
+        val newIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)
+
+        if (oldIds == null || newIds == null || oldIds.size != newIds.size) {
+            logger.w("On app widget host restored, but old to new ids mapping is invalid")
+            communalInteractor.abortRestoreWidgets()
+            return
+        }
+
+        val oldToNewWidgetIdMap = oldIds.zip(newIds).toMap()
+        communalInteractor.restoreWidgets(oldToNewWidgetIdMap)
+    }
+
+    companion object {
+        const val TAG = "CommunalBackupRestoreStartable"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
index 4d328d6..f437032 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
@@ -17,18 +17,22 @@
 package com.android.systemui.communal
 
 import android.provider.Settings
+import android.service.dreams.Flags.dreamTracksFocus
 import com.android.compose.animation.scene.SceneKey
 import com.android.systemui.CoreStartable
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.communal.shared.model.CommunalTransitionKeys
 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.dock.DockManager
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.util.kotlin.emitOnStart
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
@@ -36,15 +40,18 @@
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
 /**
  * A [CoreStartable] responsible for automatically navigating between communal scenes when certain
@@ -60,8 +67,10 @@
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val keyguardInteractor: KeyguardInteractor,
     private val systemSettings: SystemSettings,
+    private val notificationShadeWindowController: NotificationShadeWindowController,
     @Application private val applicationScope: CoroutineScope,
     @Background private val bgScope: CoroutineScope,
+    @Main private val mainDispatcher: CoroutineDispatcher,
 ) : CoreStartable {
     private var screenTimeout: Int = DEFAULT_SCREEN_TIMEOUT
 
@@ -70,9 +79,9 @@
         keyguardTransitionInteractor.startedKeyguardTransitionStep
             .mapLatest(::determineSceneAfterTransition)
             .filterNotNull()
-            // TODO(b/322787129): Also set a custom transition animation here to avoid the regular
-            // slide-in animation when setting the scene programmatically
-            .onEach { nextScene -> communalInteractor.changeScene(nextScene) }
+            .onEach { nextScene ->
+                communalInteractor.changeScene(nextScene, CommunalTransitionKeys.SimpleFade)
+            }
             .launchIn(applicationScope)
 
         // TODO(b/322787129): re-enable once custom animations are in place
@@ -133,6 +142,16 @@
                     }
                 }
         }
+
+        if (dreamTracksFocus()) {
+            bgScope.launch {
+                communalInteractor.isIdleOnCommunal.collectLatest {
+                    withContext(mainDispatcher) {
+                        notificationShadeWindowController.setGlanceableHubShowing(it)
+                    }
+                }
+            }
+        }
     }
 
     private suspend fun determineSceneAfterTransition(
@@ -143,7 +162,14 @@
         val docked = dockManager.isDocked
 
         return when {
-            docked && to == KeyguardState.LOCKSCREEN && from == KeyguardState.DREAMING -> {
+            to == KeyguardState.OCCLUDED -> {
+                // Hide communal when an activity is started on keyguard, to ensure the activity
+                // underneath the hub is shown.
+                CommunalScenes.Blank
+            }
+            to == KeyguardState.GLANCEABLE_HUB && from == KeyguardState.OCCLUDED -> {
+                // When transitioning to the hub from an occluded state, fade out the hub without
+                // doing any translation.
                 CommunalScenes.Communal
             }
             to == KeyguardState.GONE -> CommunalScenes.Blank
diff --git a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
index 72dcb26..7fa091a 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.communal.dagger
 
+import android.content.Context
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
 import com.android.systemui.communal.data.db.CommunalDatabaseModule
 import com.android.systemui.communal.data.repository.CommunalMediaRepositoryModule
 import com.android.systemui.communal.data.repository.CommunalPrefsRepositoryModule
@@ -24,6 +26,8 @@
 import com.android.systemui.communal.data.repository.CommunalTutorialRepositoryModule
 import com.android.systemui.communal.data.repository.CommunalWidgetRepositoryModule
 import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.communal.util.CommunalColors
+import com.android.systemui.communal.util.CommunalColorsImpl
 import com.android.systemui.communal.widgets.CommunalWidgetModule
 import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
 import com.android.systemui.communal.widgets.EditWidgetsActivityStarterImpl
@@ -60,6 +64,8 @@
     @Communal
     fun bindCommunalSceneDataSource(@Communal delegator: SceneDataSourceDelegator): SceneDataSource
 
+    @Binds fun bindCommunalColors(impl: CommunalColorsImpl): CommunalColors
+
     companion object {
         @Provides
         @Communal
@@ -74,5 +80,13 @@
                 )
             return SceneDataSourceDelegator(applicationScope, config)
         }
+
+        @Provides
+        @SysUISingleton
+        fun providesCommunalBackupUtils(
+            @Application context: Context,
+        ): CommunalBackupUtils {
+            return CommunalBackupUtils(context)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupHelper.kt b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupHelper.kt
new file mode 100644
index 0000000..b95c966
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupHelper.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.data.backup
+
+import android.app.backup.BackupDataInputStream
+import android.app.backup.BackupDataOutput
+import android.app.backup.BackupHelper
+import android.os.ParcelFileDescriptor
+import android.os.UserHandle
+import android.util.Log
+import com.android.systemui.Flags.communalHub
+import com.android.systemui.communal.proto.toByteArray
+import java.io.IOException
+
+/** Helps with backup & restore of the communal hub widgets. */
+class CommunalBackupHelper(
+    private val userHandle: UserHandle,
+    private val communalBackupUtils: CommunalBackupUtils,
+) : BackupHelper {
+
+    override fun performBackup(
+        oldState: ParcelFileDescriptor?,
+        data: BackupDataOutput?,
+        newState: ParcelFileDescriptor?
+    ) {
+        if (!communalHub()) {
+            Log.d(TAG, "Skipping backup. Communal not enabled")
+            return
+        }
+
+        if (data == null) {
+            Log.e(TAG, "Backup failed. Data is null")
+            return
+        }
+
+        if (!userHandle.isSystem) {
+            Log.d(TAG, "Backup skipped for non-system user")
+            return
+        }
+
+        val state = communalBackupUtils.getCommunalHubState()
+        Log.i(TAG, "Backing up communal state: $state")
+
+        val bytes = state.toByteArray()
+        try {
+            data.writeEntityHeader(ENTITY_KEY, bytes.size)
+            data.writeEntityData(bytes, bytes.size)
+        } catch (e: IOException) {
+            Log.e(TAG, "Backup failed while writing data: ${e.localizedMessage}")
+            return
+        }
+
+        Log.i(TAG, "Backup complete")
+    }
+
+    override fun restoreEntity(data: BackupDataInputStream?) {
+        if (data == null) {
+            Log.e(TAG, "Restore failed. Data is null")
+            return
+        }
+
+        if (!userHandle.isSystem) {
+            Log.d(TAG, "Restore skipped for non-system user")
+            return
+        }
+
+        if (data.key != ENTITY_KEY) {
+            Log.d(TAG, "Restore skipped due to mismatching entity key")
+            return
+        }
+
+        val dataSize = data.size()
+        val bytes = ByteArray(dataSize)
+        try {
+            data.read(bytes, /* offset= */ 0, dataSize)
+        } catch (e: IOException) {
+            Log.e(TAG, "Restore failed while reading data: ${e.localizedMessage}")
+            return
+        }
+
+        try {
+            communalBackupUtils.writeBytesToDisk(bytes)
+        } catch (e: Exception) {
+            Log.e(TAG, "Restore failed while writing to disk: ${e.localizedMessage}")
+            return
+        }
+
+        Log.i(TAG, "Restore complete")
+    }
+
+    override fun writeNewStateDescription(newState: ParcelFileDescriptor?) {
+        // Do nothing because there is no partial backup
+    }
+
+    companion object {
+        private const val TAG = "CommunalBackupHelper"
+
+        const val ENTITY_KEY = "communal_hub_state"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
new file mode 100644
index 0000000..a8e5174
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.data.backup
+
+import android.content.Context
+import androidx.annotation.WorkerThread
+import com.android.systemui.communal.data.db.CommunalDatabase
+import com.android.systemui.communal.nano.CommunalHubState
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+import java.io.IOException
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+
+/** Utilities for communal backup and restore. */
+class CommunalBackupUtils(
+    private val context: Context,
+) {
+
+    /**
+     * Retrieves a communal hub state protobuf that represents the current state of the communal
+     * database.
+     */
+    @WorkerThread
+    fun getCommunalHubState(): CommunalHubState {
+        val database = CommunalDatabase.getInstance(context)
+        val widgetsFromDb = runBlocking { database.communalWidgetDao().getWidgets().first() }
+        val widgetsState = mutableListOf<CommunalHubState.CommunalWidgetItem>()
+        widgetsFromDb.keys.forEach { rankItem ->
+            widgetsState.add(
+                CommunalHubState.CommunalWidgetItem().apply {
+                    rank = rankItem.rank
+                    widgetId = widgetsFromDb[rankItem]!!.widgetId
+                    componentName = widgetsFromDb[rankItem]?.componentName
+                }
+            )
+        }
+        return CommunalHubState().apply { widgets = widgetsState.toTypedArray() }
+    }
+
+    /**
+     * Writes [data] to disk as a file as [FILE_NAME], overwriting existing content if any.
+     *
+     * @throws FileNotFoundException if the file exists but is a directory rather than a regular
+     *   file, does not exist but cannot be created, or cannot be opened for any other reason.
+     * @throws SecurityException if write access is denied.
+     * @throws IOException if writing fails.
+     */
+    @WorkerThread
+    fun writeBytesToDisk(data: ByteArray) {
+        val output = FileOutputStream(getFile())
+        output.write(data)
+        output.close()
+    }
+
+    /**
+     * Reads bytes from [FILE_NAME], and throws if file does not exist.
+     *
+     * @throws FileNotFoundException if file does not exist.
+     * @throws SecurityException if read access is denied.
+     * @throws IOException if reading fails.
+     */
+    @WorkerThread
+    fun readBytesFromDisk(): ByteArray {
+        val input = FileInputStream(getFile())
+        val bytes = input.readAllBytes()
+        input.close()
+
+        return bytes
+    }
+
+    /**
+     * Removes the bytes written to disk at [FILE_NAME].
+     *
+     * @return True if and only if the file is successfully deleted
+     * @throws SecurityException if permission is denied
+     */
+    @WorkerThread
+    fun clear(): Boolean {
+        return getFile().delete()
+    }
+
+    /** Whether [FILE_NAME] exists. */
+    @WorkerThread
+    fun fileExists(): Boolean {
+        return getFile().exists()
+    }
+
+    @WorkerThread
+    private fun getFile(): File {
+        return File(context.filesDir, FILE_NAME)
+    }
+
+    companion object {
+        private const val FILE_NAME = "communal_restore"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
index 595d320..3ce8109 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
@@ -16,10 +16,53 @@
 
 package com.android.systemui.communal.data.db
 
+import android.content.Context
+import androidx.annotation.VisibleForTesting
 import androidx.room.Database
+import androidx.room.Room
 import androidx.room.RoomDatabase
+import com.android.systemui.res.R
 
 @Database(entities = [CommunalWidgetItem::class, CommunalItemRank::class], version = 1)
 abstract class CommunalDatabase : RoomDatabase() {
     abstract fun communalWidgetDao(): CommunalWidgetDao
+
+    companion object {
+        private var instance: CommunalDatabase? = null
+
+        /**
+         * Gets a singleton instance of the communal database. If this is called for the first time
+         * globally, a new instance is created.
+         *
+         * @param context The context the database is created in. Only effective when a new instance
+         *   is created.
+         * @param callback An optional callback registered to the database. Only effective when a
+         *   new instance is created.
+         */
+        fun getInstance(
+            context: Context,
+            callback: Callback? = null,
+        ): CommunalDatabase {
+            if (instance == null) {
+                instance =
+                    Room.databaseBuilder(
+                            context,
+                            CommunalDatabase::class.java,
+                            context.resources.getString(R.string.config_communalDatabase)
+                        )
+                        .also { builder ->
+                            builder.fallbackToDestructiveMigration(dropAllTables = false)
+                            callback?.let { callback -> builder.addCallback(callback) }
+                        }
+                        .build()
+            }
+
+            return instance!!
+        }
+
+        @VisibleForTesting
+        fun setInstance(database: CommunalDatabase) {
+            instance = database
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt
index e766290..b8161fd 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt
@@ -17,10 +17,8 @@
 package com.android.systemui.communal.data.db
 
 import android.content.Context
-import androidx.room.Room
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.res.R
 import dagger.Module
 import dagger.Provides
 
@@ -33,14 +31,7 @@
             @Application context: Context,
             defaultWidgetPopulation: DefaultWidgetPopulation,
         ): CommunalDatabase {
-            return Room.databaseBuilder(
-                    context,
-                    CommunalDatabase::class.java,
-                    context.resources.getString(R.string.config_communalDatabase)
-                )
-                .fallbackToDestructiveMigration()
-                .addCallback(defaultWidgetPopulation)
-                .build()
+            return CommunalDatabase.getInstance(context, defaultWidgetPopulation)
         }
 
         @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
index 9cd77c4..d174fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
@@ -23,6 +23,7 @@
 import androidx.room.RoomDatabase
 import androidx.room.Transaction
 import androidx.sqlite.db.SupportSQLiteDatabase
+import com.android.systemui.communal.nano.CommunalHubState
 import com.android.systemui.communal.widgets.CommunalWidgetHost
 import com.android.systemui.communal.widgets.CommunalWidgetModule.Companion.DEFAULT_WIDGETS
 import com.android.systemui.dagger.qualifiers.Application
@@ -116,6 +117,10 @@
     @Query("UPDATE communal_item_rank_table SET rank = :order WHERE uid = :itemUid")
     fun updateItemRank(itemUid: Long, order: Int)
 
+    @Query("DELETE FROM communal_widget_table") fun clearCommunalWidgetsTable()
+
+    @Query("DELETE FROM communal_item_rank_table") fun clearCommunalItemRankTable()
+
     @Transaction
     fun updateWidgetOrder(widgetIdToPriorityMap: Map<Int, Int>) {
         widgetIdToPriorityMap.forEach { (id, priority) ->
@@ -128,9 +133,18 @@
 
     @Transaction
     fun addWidget(widgetId: Int, provider: ComponentName, priority: Int): Long {
-        return insertWidget(
+        return addWidget(
             widgetId = widgetId,
             componentName = provider.flattenToString(),
+            priority = priority,
+        )
+    }
+
+    @Transaction
+    fun addWidget(widgetId: Int, componentName: String, priority: Int): Long {
+        return insertWidget(
+            widgetId = widgetId,
+            componentName = componentName,
             itemId = insertItemRank(priority),
         )
     }
@@ -145,4 +159,13 @@
         deleteWidgets(widget)
         return true
     }
+
+    /** Wipes current database and restores the snapshot represented by [state]. */
+    @Transaction
+    fun restoreCommunalHubState(state: CommunalHubState) {
+        clearCommunalWidgetsTable()
+        clearCommunalItemRankTable()
+
+        state.widgets.forEach { addWidget(it.widgetId, it.componentName, it.rank) }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
index c724244..9debe0e 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
@@ -57,6 +57,9 @@
      * Settings.
      */
     fun getWidgetCategories(user: UserInfo): Flow<CommunalWidgetCategories>
+
+    /** Keyguard widgets enabled state by Device Policy Manager for the specified user. */
+    fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean>
 }
 
 @SysUISingleton
@@ -115,6 +118,16 @@
             }
             .flowOn(bgDispatcher)
 
+    override fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean> =
+        broadcastDispatcher
+            .broadcastFlow(
+                filter =
+                    IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+                user = user.userHandle
+            )
+            .emitOnStart()
+            .map { devicePolicyManager.areKeyguardWidgetsAllowed(user.id) }
+
     private fun getEnabledByUser(user: UserInfo): Flow<Boolean> =
         secureSettings
             .observerFlow(userId = user.id, names = arrayOf(Settings.Secure.GLANCEABLE_HUB_ENABLED))
@@ -128,16 +141,6 @@
                 ) == 1
             }
 
-    private fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean> =
-        broadcastDispatcher
-            .broadcastFlow(
-                filter =
-                    IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                user = user.userHandle
-            )
-            .emitOnStart()
-            .map { devicePolicyManager.areKeyguardWidgetsAllowed(user.id) }
-
     companion object {
         const val GLANCEABLE_HUB_CONTENT_SETTING = "glanceable_hub_content_setting"
         private const val ENABLED_SETTING_DEFAULT = 1
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
index e395ca9..1f54e70 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
@@ -16,13 +16,17 @@
 
 package com.android.systemui.communal.data.repository
 
+import android.app.backup.BackupManager
 import android.appwidget.AppWidgetManager
 import android.content.ComponentName
 import android.os.UserHandle
 import androidx.annotation.WorkerThread
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
 import com.android.systemui.communal.data.db.CommunalItemRank
 import com.android.systemui.communal.data.db.CommunalWidgetDao
 import com.android.systemui.communal.data.db.CommunalWidgetItem
+import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.communal.proto.toCommunalHubState
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.communal.widgets.CommunalAppWidgetHost
 import com.android.systemui.communal.widgets.CommunalWidgetHost
@@ -69,6 +73,15 @@
      * @param widgetIdToPriorityMap mapping of the widget ids to the priority of the widget.
      */
     fun updateWidgetOrder(widgetIdToPriorityMap: Map<Int, Int>) {}
+
+    /**
+     * Restores the database by reading a state file from disk and updating the widget ids according
+     * to [oldToNewWidgetIdMap].
+     */
+    fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>)
+
+    /** Aborts the restore process and removes files from disk if necessary. */
+    fun abortRestoreWidgets()
 }
 
 @SysUISingleton
@@ -82,6 +95,8 @@
     private val communalWidgetHost: CommunalWidgetHost,
     private val communalWidgetDao: CommunalWidgetDao,
     @CommunalLog logBuffer: LogBuffer,
+    private val backupManager: BackupManager,
+    private val backupUtils: CommunalBackupUtils,
 ) : CommunalWidgetRepository {
     companion object {
         const val TAG = "CommunalWidgetRepository"
@@ -143,6 +158,7 @@
                     provider = provider,
                     priority = priority,
                 )
+                backupManager.dataChanged()
             } else {
                 appWidgetHost.deleteAppWidgetId(id)
             }
@@ -155,6 +171,7 @@
             if (communalWidgetDao.deleteWidgetById(widgetId)) {
                 appWidgetHost.deleteAppWidgetId(widgetId)
                 logger.i("Deleted widget with id $widgetId.")
+                backupManager.dataChanged()
             }
         }
     }
@@ -165,6 +182,76 @@
             logger.i({ "Updated the order of widget list with ids: $str1." }) {
                 str1 = widgetIdToPriorityMap.toString()
             }
+            backupManager.dataChanged()
+        }
+    }
+
+    override fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {
+        bgScope.launch {
+            // Read restored state file from disk
+            val state: CommunalHubState
+            try {
+                state = backupUtils.readBytesFromDisk().toCommunalHubState()
+            } catch (e: Exception) {
+                logger.e({ "Failed reading restore data from disk: $str1" }) {
+                    str1 = e.localizedMessage
+                }
+                abortRestoreWidgets()
+                return@launch
+            }
+
+            val widgetsWithHost = appWidgetHost.appWidgetIds.toList()
+            val widgetsToRemove = widgetsWithHost.toMutableList()
+
+            // Produce a new state to be restored, skipping invalid widgets
+            val newWidgets =
+                state.widgets.mapNotNull { restoredWidget ->
+                    val newWidgetId =
+                        oldToNewWidgetIdMap[restoredWidget.widgetId] ?: restoredWidget.widgetId
+
+                    // Skip if widget id is not registered with the host
+                    if (!widgetsWithHost.contains(newWidgetId)) {
+                        logger.d({
+                            "Skipped restoring widget (old:$int1 new:$int2) " +
+                                "because it is not registered with host"
+                        }) {
+                            int1 = restoredWidget.widgetId
+                            int2 = newWidgetId
+                        }
+                        return@mapNotNull null
+                    }
+
+                    widgetsToRemove.remove(newWidgetId)
+
+                    CommunalHubState.CommunalWidgetItem().apply {
+                        widgetId = newWidgetId
+                        componentName = restoredWidget.componentName
+                        rank = restoredWidget.rank
+                    }
+                }
+            val newState = CommunalHubState().apply { widgets = newWidgets.toTypedArray() }
+
+            // Restore database
+            logger.i("Restoring communal database $newState")
+            communalWidgetDao.restoreCommunalHubState(newState)
+
+            // Delete restored state file from disk
+            backupUtils.clear()
+
+            // Remove widgets from host that have not been restored
+            widgetsToRemove.forEach { widgetId ->
+                logger.i({ "Deleting widget $int1 from host since it has not been restored" }) {
+                    int1 = widgetId
+                }
+                appWidgetHost.deleteAppWidgetId(widgetId)
+            }
+        }
+    }
+
+    override fun abortRestoreWidgets() {
+        bgScope.launch {
+            logger.i("Restore widgets aborted")
+            backupUtils.clear()
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 246d5d9..7448e14 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -44,6 +44,8 @@
 import com.android.systemui.communal.widgets.WidgetConfigurator
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dock.DockManager
+import com.android.systemui.dock.retrieveIsDocked
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.Logger
@@ -53,7 +55,7 @@
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.smartspace.data.repository.SmartspaceRepository
@@ -97,14 +99,14 @@
     mediaRepository: CommunalMediaRepository,
     smartspaceRepository: SmartspaceRepository,
     keyguardInteractor: KeyguardInteractor,
-    communalSettingsInteractor: CommunalSettingsInteractor,
+    private val communalSettingsInteractor: CommunalSettingsInteractor,
     private val appWidgetHost: CommunalAppWidgetHost,
     private val editWidgetsActivityStarter: EditWidgetsActivityStarter,
     private val userTracker: UserTracker,
     private val activityStarter: ActivityStarter,
     private val userManager: UserManager,
+    private val dockManager: DockManager,
     sceneInteractor: SceneInteractor,
-    sceneContainerFlags: SceneContainerFlags,
     @CommunalLog logBuffer: LogBuffer,
     @CommunalTableLog tableLogBuffer: TableLogBuffer,
 ) {
@@ -123,7 +125,7 @@
         and(
                 communalSettingsInteractor.isCommunalEnabled,
                 not(keyguardInteractor.isEncryptedOrLockdown),
-                or(keyguardInteractor.isKeyguardVisible, keyguardInteractor.isDreaming)
+                or(keyguardInteractor.isKeyguardShowing, keyguardInteractor.isDreaming)
             )
             .distinctUntilChanged()
             .onEach { available ->
@@ -143,6 +145,9 @@
                 replay = 1,
             )
 
+    /** Whether to show communal by default */
+    val showByDefault: Flow<Boolean> = and(isCommunalAvailable, dockManager.retrieveIsDocked())
+
     /**
      * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene].
      *
@@ -165,6 +170,23 @@
     }
 
     /**
+     * Repopulates the communal widgets database by first reading a backed-up state from disk and
+     * updating the widget ids indicated by [oldToNewWidgetIdMap]. The backed-up state is removed
+     * from disk afterwards.
+     */
+    fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {
+        widgetRepository.restoreWidgets(oldToNewWidgetIdMap)
+    }
+
+    /**
+     * Aborts the task of restoring widgets from a backup. The backed up state stored on disk is
+     * removed.
+     */
+    fun abortRestoreWidgets() {
+        widgetRepository.abortRestoreWidgets()
+    }
+
+    /**
      * Updates the transition state of the hub [SceneTransitionLayout].
      *
      * Note that you must call is with `null` when the UI is done or risk a memory leak.
@@ -210,7 +232,7 @@
      */
     // TODO(b/323215860): rename to something more appropriate after cleaning up usages
     val isCommunalShowing: Flow<Boolean> =
-        flow { emit(sceneContainerFlags.isEnabled()) }
+        flow { emit(SceneContainerFlag.isEnabled) }
             .flatMapLatest { sceneContainerEnabled ->
                 if (sceneContainerEnabled) {
                     sceneInteractor.currentScene.map { it == Scenes.Communal }
@@ -352,7 +374,14 @@
     /** A list of widget content to be displayed in the communal hub. */
     val widgetContent: Flow<List<WidgetContent>> =
         combine(
-            widgetRepository.communalWidgets.map { filterWidgetsByExistingUsers(it) },
+            widgetRepository.communalWidgets
+                .map { filterWidgetsByExistingUsers(it) }
+                .combine(communalSettingsInteractor.allowedByDevicePolicyForWorkProfile) {
+                    // exclude widgets under work profile if not allowed by device policy
+                    widgets,
+                    allowedForWorkProfile ->
+                    filterWidgetsAllowedByDevicePolicy(widgets, allowedForWorkProfile)
+                },
             communalSettingsInteractor.communalWidgetCategories,
             updateOnWorkProfileBroadcastReceived,
         ) { widgets, allowedCategories, _ ->
@@ -374,6 +403,19 @@
             }
         }
 
+    /** Filter widgets based on whether their associated profile is allowed by device policy. */
+    private fun filterWidgetsAllowedByDevicePolicy(
+        list: List<CommunalWidgetContentModel>,
+        allowedByDevicePolicyForWorkProfile: Boolean
+    ): List<CommunalWidgetContentModel> =
+        if (allowedByDevicePolicyForWorkProfile) {
+            list
+        } else {
+            // Get associated work profile for the currently selected user.
+            val workProfile = userTracker.userProfiles.find { it.isManagedProfile }
+            list.filter { it.providerInfo.profile.identifier != workProfile?.id }
+        }
+
     /** A flow of available smartspace targets. Currently only showing timers. */
     private val smartspaceTargets: Flow<List<SmartspaceTarget>> =
         if (!smartspaceRepository.isSmartspaceRemoteViewsEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
index 20f60b7..f9de609 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.communal.domain.interactor
 
+import android.content.pm.UserInfo
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.communal.data.model.CommunalEnabledState
 import com.android.systemui.communal.data.model.CommunalWidgetCategories
 import com.android.systemui.communal.data.repository.CommunalSettingsRepository
@@ -24,13 +26,18 @@
 import com.android.systemui.log.dagger.CommunalTableLog
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
@@ -40,8 +47,10 @@
 @Inject
 constructor(
     @Background private val bgScope: CoroutineScope,
+    @Background private val bgExecutor: Executor,
     private val repository: CommunalSettingsRepository,
     userInteractor: SelectedUserInteractor,
+    private val userTracker: UserTracker,
     @CommunalTableLog tableLogBuffer: TableLogBuffer,
 ) {
     /** Whether or not communal is enabled for the currently selected user. */
@@ -68,4 +77,33 @@
                 started = SharingStarted.Eagerly,
                 initialValue = CommunalWidgetCategories().categories
             )
+
+    private val workProfileUserInfoCallbackFlow: Flow<UserInfo?> = conflatedCallbackFlow {
+        fun send(profiles: List<UserInfo>) {
+            trySend(profiles.find { it.isManagedProfile })
+        }
+
+        val callback =
+            object : UserTracker.Callback {
+                override fun onProfilesChanged(profiles: List<UserInfo>) {
+                    send(profiles)
+                }
+            }
+        userTracker.addCallback(callback, bgExecutor)
+        send(userTracker.userProfiles)
+
+        awaitClose { userTracker.removeCallback(callback) }
+    }
+
+    /** Whether or not keyguard widgets are allowed for work profile by device policy manager. */
+    val allowedByDevicePolicyForWorkProfile: StateFlow<Boolean> =
+        workProfileUserInfoCallbackFlow
+            .flatMapLatest { workProfile ->
+                workProfile?.let { repository.getAllowedByDevicePolicy(it) } ?: flowOf(false)
+            }
+            .stateIn(
+                scope = bgScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false
+            )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/proto/CommunalHubStateExt.kt b/packages/SystemUI/src/com/android/systemui/communal/proto/CommunalHubStateExt.kt
new file mode 100644
index 0000000..2d661cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/proto/CommunalHubStateExt.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.proto
+
+import com.android.systemui.communal.nano.CommunalHubState
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException
+
+/** Converts a [CommunalHubState] to bytes. */
+fun CommunalHubState.toByteArray(): ByteArray {
+    return CommunalHubState.toByteArray(this)
+}
+
+/**
+ * Converts bytes to a [CommunalHubState].
+ *
+ * @throws InvalidProtocolBufferNanoException if parsing fails.
+ */
+fun ByteArray.toCommunalHubState(): CommunalHubState {
+    return CommunalHubState.parseFrom(this)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto b/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
new file mode 100644
index 0000000..0816259
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package com.android.systemui.communal;
+
+option java_multiple_files = true;
+
+// Represents the state of communal hub for backup & restore.
+message CommunalHubState {
+    // Widgets in the communal hub.
+    repeated CommunalWidgetItem widgets = 1;
+
+    // Represents a widget in the communal hub.
+    message CommunalWidgetItem {
+        // Id of the widget.
+        int32 widget_id = 1;
+
+        // Component name of the widget.
+        string component_name = 2;
+
+        // Rank or order of the widget in the communal hub.
+        int32 rank = 3;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt
new file mode 100644
index 0000000..a3c61a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.shared.model
+
+import com.android.compose.animation.scene.TransitionKey
+
+/**
+ * Defines all known named transitions for [CommunalScenes].
+ *
+ * These transitions can be referenced by key when changing scenes programmatically.
+ */
+object CommunalTransitionKeys {
+    /** Fades the glanceable hub without any translation */
+    val SimpleFade = TransitionKey("SimpleFade")
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 095222a..4ac43bc 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -20,6 +20,7 @@
 import android.os.UserHandle
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.TransitionKey
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.domain.model.CommunalContentModel
 import com.android.systemui.communal.widgets.WidgetConfigurator
@@ -36,6 +37,9 @@
 ) {
     val currentScene: Flow<SceneKey> = communalInteractor.desiredScene
 
+    /** Whether communal hub can be focused to enable accessibility actions. */
+    val isFocusable: Flow<Boolean> = communalInteractor.isIdleOnCommunal
+
     /** Whether widgets are currently being re-ordered. */
     open val reorderingWidgets: StateFlow<Boolean> = MutableStateFlow(false)
 
@@ -49,8 +53,8 @@
         communalInteractor.signalUserInteraction()
     }
 
-    fun changeScene(scene: SceneKey) {
-        communalInteractor.changeScene(scene)
+    fun changeScene(scene: SceneKey, transitionKey: TransitionKey? = null) {
+        communalInteractor.changeScene(scene, transitionKey)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
index b3002cd..3f92223 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
@@ -63,7 +63,7 @@
 
     override val isEditMode = true
 
-    // Only widgets are editable. The CTA tile comes last in the list and remains visible.
+    // Only widgets are editable.
     override val communalContent: Flow<List<CommunalContentModel>> =
         communalInteractor.widgetContent.onEach { models ->
             logger.d({ "Content updated: $str1" }) { str1 = models.joinToString { it.key } }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
index 96e4b34..1bee83b 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
@@ -16,7 +16,13 @@
 
 package com.android.systemui.communal.ui.viewmodel
 
+import android.graphics.Color
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.util.CommunalColors
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel
@@ -24,7 +30,9 @@
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.merge
 
 /** View model for transitions related to the communal hub. */
@@ -33,10 +41,13 @@
 class CommunalTransitionViewModel
 @Inject
 constructor(
+    communalColors: CommunalColors,
     glanceableHubToLockscreenTransitionViewModel: GlanceableHubToLockscreenTransitionViewModel,
     lockscreenToGlanceableHubTransitionViewModel: LockscreenToGlanceableHubTransitionViewModel,
     dreamToGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
     glanceableHubToDreamTransitionViewModel: GlanceableHubToDreamingTransitionViewModel,
+    communalInteractor: CommunalInteractor,
+    keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) {
     /**
      * Whether UMO location should be on communal. This flow is responsive to transitions so that a
@@ -51,4 +62,23 @@
                 glanceableHubToDreamTransitionViewModel.showUmo,
             )
             .distinctUntilChanged()
+
+    /** Whether to show communal by default */
+    val showByDefault: Flow<Boolean> = communalInteractor.showByDefault
+
+    val transitionFromOccludedEnded =
+        keyguardTransitionInteractor.transitionStepsFromState(KeyguardState.OCCLUDED).filter { step
+            ->
+            step.transitionState == TransitionState.FINISHED ||
+                step.transitionState == TransitionState.CANCELED
+        }
+
+    val recentsBackgroundColor: Flow<Color?> =
+        combine(showByDefault, communalColors.backgroundColor) { showByDefault, backgroundColor ->
+            if (showByDefault) {
+                backgroundColor
+            } else {
+                null
+            }
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index c73d738..f13b5759 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.media.dagger.MediaModule
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.util.kotlin.BooleanFlowOperators.not
 import javax.inject.Inject
 import javax.inject.Named
 import kotlinx.coroutines.CoroutineScope
@@ -57,7 +56,7 @@
     @Application private val scope: CoroutineScope,
     private val communalInteractor: CommunalInteractor,
     tutorialInteractor: CommunalTutorialInteractor,
-    shadeInteractor: ShadeInteractor,
+    private val shadeInteractor: ShadeInteractor,
     deviceEntryInteractor: DeviceEntryInteractor,
     @Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
     @CommunalLog logBuffer: LogBuffer,
@@ -103,9 +102,6 @@
     val isEnableWorkProfileDialogShowing: Flow<Boolean> =
         _isEnableWorkProfileDialogShowing.asStateFlow()
 
-    /** Whether touches should be disabled in communal */
-    val touchesAllowed: Flow<Boolean> = not(shadeInteractor.isAnyFullyExpanded)
-
     val deviceUnlocked: Flow<Boolean> = deviceEntryInteractor.isUnlocked
 
     init {
@@ -192,6 +188,11 @@
         delayedHidePopupJob = null
     }
 
+    /** Whether we can transition to a new scene based on a user gesture. */
+    fun canChangeScene(): Boolean {
+        return !shadeInteractor.isAnyFullyExpanded.value
+    }
+
     companion object {
         const val POPUP_AUTO_HIDE_TIMEOUT_MS = 12000L
     }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/CommunalColors.kt b/packages/SystemUI/src/com/android/systemui/communal/util/CommunalColors.kt
new file mode 100644
index 0000000..1e04fe7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/util/CommunalColors.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.util
+
+import android.content.Context
+import android.graphics.Color
+import com.android.settingslib.Utils
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Wrapper around colors used for the communal UI. */
+interface CommunalColors {
+    /** The background color of the glanceable hub. */
+    val backgroundColor: StateFlow<Color>
+}
+
+@SysUISingleton
+class CommunalColorsImpl
+@Inject
+constructor(
+    @Application applicationScope: CoroutineScope,
+    private val context: Context,
+    configurationInteractor: ConfigurationInteractor,
+) : CommunalColors {
+    override val backgroundColor: StateFlow<Color> =
+        configurationInteractor.onAnyConfigurationChange
+            .map { loadBackgroundColor() }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = loadBackgroundColor()
+            )
+
+    private fun loadBackgroundColor(): Color =
+        Color.valueOf(
+            Utils.getColorAttrDefaultColor(
+                context,
+                com.android.internal.R.attr.materialColorOutlineVariant
+            )
+        )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt
index 60fb8d4..aa6516d 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt
@@ -38,7 +38,7 @@
 @Module
 interface CommunalWidgetModule {
     companion object {
-        private const val APP_WIDGET_HOST_ID = 116
+        const val APP_WIDGET_HOST_ID = 116
         const val DEFAULT_WIDGETS = "default_widgets"
 
         @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index 5f4b394..f20fafc 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -36,6 +36,7 @@
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.communal.shared.log.CommunalUiEvent
 import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.communal.shared.model.CommunalTransitionKeys
 import com.android.systemui.communal.ui.compose.CommunalHub
 import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
 import com.android.systemui.communal.util.WidgetPickerIntentUtils.getWidgetExtraFromIntent
@@ -149,7 +150,10 @@
 
     private fun onEditDone() {
         try {
-            communalViewModel.changeScene(CommunalScenes.Communal)
+            communalViewModel.changeScene(
+                CommunalScenes.Communal,
+                CommunalTransitionKeys.SimpleFade
+            )
             checkNotNull(windowManagerService).lockNow(/* options */ null)
             finish()
         } catch (e: RemoteException) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 1003050..3e98fc1 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -23,6 +23,7 @@
 import android.hardware.SensorPrivacyManager;
 
 import com.android.keyguard.KeyguardViewController;
+import com.android.systemui.CoreStartable;
 import com.android.systemui.ScreenDecorationsModule;
 import com.android.systemui.accessibility.SystemActionsModule;
 import com.android.systemui.battery.BatterySaverModule;
@@ -30,6 +31,7 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerImpl;
 import com.android.systemui.doze.DozeHost;
+import com.android.systemui.keyguard.ui.composable.blueprint.DefaultBlueprintModule;
 import com.android.systemui.media.dagger.MediaModule;
 import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionCli;
 import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
@@ -49,12 +51,15 @@
 import com.android.systemui.settings.MultiUserUtilsModule;
 import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
 import com.android.systemui.shade.ShadeModule;
+import com.android.systemui.startable.Dependencies;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyboardShortcutsModule;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.phone.HeadsUpModule;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -76,6 +81,10 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+import java.util.Set;
 
 import javax.inject.Named;
 
@@ -99,6 +108,7 @@
         BatterySaverModule.class,
         CollapsedStatusBarFragmentStartableModule.class,
         ConnectingDisplayViewModel.StartableModule.class,
+        DefaultBlueprintModule.class,
         GestureModule.class,
         HeadsUpModule.class,
         KeyboardShortcutsModule.class,
@@ -197,4 +207,13 @@
 
     @Binds
     abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
+
+    /** */
+    @Provides
+    @IntoMap
+    @Dependencies
+    @ClassKey(SysuiStatusBarStateController.class)
+    static Set<Class<? extends CoreStartable>> providesStatusBarStateControllerDeps() {
+        return Set.of(CentralSurfaces.class);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index e1041669..1dd3722 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -25,6 +25,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
 import com.android.systemui.people.PeopleProvider;
+import com.android.systemui.startable.Dependencies;
 import com.android.systemui.statusbar.NotificationInsetsModule;
 import com.android.systemui.statusbar.QsFrameTranslateModule;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -47,6 +48,7 @@
 
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 
 import javax.inject.Provider;
 
@@ -92,7 +94,7 @@
         Builder setTaskViewFactory(Optional<TaskViewFactory> t);
 
         @BindsInstance
-        Builder setTransitions(ShellTransitions t);
+        Builder setShellTransitions(ShellTransitions t);
 
         @BindsInstance
         Builder setKeyguardTransitions(KeyguardTransitions k);
@@ -160,6 +162,11 @@
     @PerUser Map<Class<?>, Provider<CoreStartable>> getPerUserStartables();
 
     /**
+     * Returns {@link CoreStartable} dependencies if there are any.
+     */
+    @Dependencies Map<Class<?>, Set<Class<? extends CoreStartable>>> getStartableDependencies();
+
+    /**
      * Member injection into the supplied argument.
      */
     void inject(SystemUIAppComponentFactoryBase factory);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 21ee5bd..593196c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.biometrics.BiometricNotificationService
 import com.android.systemui.clipboardoverlay.ClipboardListener
 import com.android.systemui.communal.CommunalDreamStartable
+import com.android.systemui.communal.CommunalBackupRestoreStartable
 import com.android.systemui.communal.CommunalSceneStartable
 import com.android.systemui.communal.log.CommunalLoggerStartable
 import com.android.systemui.communal.widgets.CommunalAppWidgetHostStartable
@@ -55,6 +56,7 @@
 import com.android.systemui.statusbar.notification.InstantAppNotifier
 import com.android.systemui.statusbar.phone.ScrimController
 import com.android.systemui.statusbar.phone.StatusBarHeadsUpChangeListener
+import com.android.systemui.statusbar.policy.BatteryControllerStartable
 import com.android.systemui.stylus.StylusUsiPowerStartable
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import com.android.systemui.theme.ThemeOverlayController
@@ -341,6 +343,19 @@
 
     @Binds
     @IntoMap
+    @ClassKey(CommunalBackupRestoreStartable::class)
+    abstract fun bindCommunalBackupRestoreStartable(
+        impl: CommunalBackupRestoreStartable
+    ): CoreStartable
+
+    @Binds
+    @IntoMap
     @ClassKey(HomeControlsDreamStartable::class)
     abstract fun bindHomeControlsDreamStartable(impl: HomeControlsDreamStartable): CoreStartable
+
+    /** Binds {@link BatteryControllerStartable} as a {@link CoreStartable}. */
+    @Binds
+    @IntoMap
+    @ClassKey(BatteryControllerStartable::class)
+    abstract fun bindsBatteryControllerStartable(impl: BatteryControllerStartable): CoreStartable
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 7d86e06..3462164 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -18,6 +18,7 @@
 
 import android.app.INotificationManager;
 import android.app.Service;
+import android.app.backup.BackupManager;
 import android.content.Context;
 import android.service.dreams.IDreamManager;
 
@@ -29,9 +30,11 @@
 import com.android.systemui.BootCompleteCache;
 import com.android.systemui.BootCompleteCacheImpl;
 import com.android.systemui.CameraProtectionModule;
+import com.android.systemui.CoreStartable;
 import com.android.systemui.SystemUISecondaryUserService;
 import com.android.systemui.accessibility.AccessibilityModule;
 import com.android.systemui.accessibility.data.repository.AccessibilityRepositoryModule;
+import com.android.systemui.ambient.dagger.AmbientModule;
 import com.android.systemui.appops.dagger.AppOpsModule;
 import com.android.systemui.assist.AssistModule;
 import com.android.systemui.authentication.AuthenticationModule;
@@ -104,6 +107,7 @@
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
 import com.android.systemui.shared.condition.Monitor;
 import com.android.systemui.smartspace.dagger.SmartspaceModule;
+import com.android.systemui.startable.Dependencies;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -161,15 +165,18 @@
 import dagger.Provides;
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
+import dagger.multibindings.Multibinds;
+
+import kotlinx.coroutines.CoroutineScope;
 
 import java.util.Collections;
+import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 import javax.inject.Named;
 
-import kotlinx.coroutines.CoroutineScope;
-
 /**
  * A dagger module for injecting components of System UI that are required by System UI.
  *
@@ -183,6 +190,7 @@
 @Module(includes = {
         AccessibilityModule.class,
         AccessibilityRepositoryModule.class,
+        AmbientModule.class,
         AppOpsModule.class,
         AssistModule.class,
         AuthenticationModule.class,
@@ -268,6 +276,10 @@
         })
 public abstract class SystemUIModule {
 
+    @Multibinds
+    @Dependencies
+    abstract Map<Class<?>, Set<Class<? extends CoreStartable>>> startableDependencyMap();
+
     @Binds
     abstract BootCompleteCache bindBootCompleteCache(BootCompleteCacheImpl bootCompleteCache);
 
@@ -307,6 +319,13 @@
         return new Monitor(executor, Collections.singleton(systemProcessCondition), logBuffer);
     }
 
+    /** Provides the package name for SystemUI. */
+    @SysUISingleton
+    @Provides
+    static BackupManager provideBackupManager(@Application Context context) {
+        return new BackupManager(context);
+    }
+
     @BindsOptionalOf
     abstract CommandQueue optionalCommandQueue();
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index e04a0e5..a3cdb2e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -94,7 +94,7 @@
     Optional<TaskViewFactory> getTaskViewFactory();
 
     @WMSingleton
-    ShellTransitions getTransitions();
+    ShellTransitions getShellTransitions();
 
     @WMSingleton
     KeyguardTransitions getKeyguardTransitions();
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java b/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java
index 672ade2..3021184 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java
@@ -37,6 +37,15 @@
         return NO_COMMANDS;
     }
 
+    /** Something simple enough to be recognizable in dumpsys logs */
+    default String logName() {
+        if (this.getClass().isAnonymousClass()) {
+            return getClass().getName();
+        } else {
+            return getClass().getSimpleName();
+        }
+    }
+
     String ACTION_DEMO = "com.android.systemui.demo";
 
     String EXTRA_COMMAND = "command";
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 45ff963..f03aa63 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -25,12 +25,12 @@
 import android.util.Log
 import com.android.systemui.Dumpable
 import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.demomode.DemoMode.ACTION_DEMO
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.policy.CallbackController
 import com.android.systemui.util.Assert
 import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
 import java.io.PrintWriter
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
@@ -209,20 +209,18 @@
         pw.println("DemoModeController state -")
         pw.println("  isInDemoMode=$isInDemoMode")
         pw.println("  isDemoModeAllowed=$isAvailable")
-        pw.print("  receivers=[")
-        val copy: List<DemoModeCommandReceiver>
+        val copy: List<DemoMode>
         synchronized(this) { copy = receivers.toList() }
-        copy.forEach { recv -> pw.print(" ${recv.javaClass.simpleName}") }
-        pw.println(" ]")
+
+        // List of all receivers
+        pw.println("  receivers=[${copy.joinToString(", ") { it.logName() }}]")
+
+        // Print out the map of COMMAND -> list of receivers for that command
         pw.println("  receiverMap= [")
-        receiverMap.keys.forEach { command ->
-            pw.print("    $command : [")
-            val recvs =
-                receiverMap[command]!!
-                    .map { receiver -> receiver.javaClass.simpleName }
-                    .joinToString(",")
-            pw.println("$recvs ]")
+        receiverMap.entries.forEach { (comm, recv) ->
+            pw.println("    $comm : [${recv.joinToString(", ") {it.logName()}}]")
         }
+        pw.println(" ]")
     }
 
     private val tracker =
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
index baae986..e418641 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -40,7 +40,6 @@
 import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus
 import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.keyguard.KeyguardWmStateRefactor
 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.BiometricType
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
@@ -51,6 +50,7 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.log.FaceAuthenticationLogger
@@ -295,7 +295,8 @@
     }
 
     private fun listenForSchedulingWatchdog() {
-        keyguardTransitionInteractor.anyStateToGoneTransition
+        keyguardTransitionInteractor
+            .transition(to = KeyguardState.GONE)
             .filter { it.transitionState == TransitionState.FINISHED }
             .onEach {
                 // We deliberately want to run this in background because scheduleWatchdog does
@@ -313,10 +314,16 @@
         // or device starts going to sleep.
         merge(
                 powerInteractor.isAsleep,
-                if (KeyguardWmStateRefactor.isEnabled) {
-                    keyguardTransitionInteractor.isInTransitionToState(KeyguardState.GONE)
-                } else {
-                    keyguardRepository.keyguardDoneAnimationsFinished.map { true }
+                combine(
+                    keyguardTransitionInteractor.isFinishedInState(KeyguardState.GONE),
+                    keyguardInteractor.statusBarState,
+                ) { isFinishedInGoneState, statusBarState ->
+                    // When the user is dragging the primary bouncer in (up) by manually scrolling
+                    // up on the lockscreen, the device won't be irreversibly transitioned to GONE
+                    // until the statusBarState updates to SHADE, so we check that here.
+                    // Else, we could reset the face auth state too early and end up in a strange
+                    // state.
+                    isFinishedInGoneState && statusBarState == StatusBarState.SHADE
                 },
                 userRepository.selectedUser.map {
                     it.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
index 7733de4..a32b2aa 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
@@ -68,6 +68,7 @@
     fun onPrimaryBouncerUserInput()
     fun onAccessibilityAction()
     fun onWalletLaunched()
+    fun onDeviceUnfolded()
 
     /** Whether face auth is considered class 3 */
     fun isFaceAuthStrong(): Boolean
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index 5c1ca64..662974d 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -19,6 +19,7 @@
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
@@ -63,6 +64,7 @@
     private val trustInteractor: TrustInteractor,
     private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
     private val systemPropertiesHelper: SystemPropertiesHelper,
+    private val alternateBouncerInteractor: AlternateBouncerInteractor,
 ) {
     /**
      * Whether the device is unlocked.
@@ -211,10 +213,14 @@
         //       4. Transition to bouncer scene
         applicationScope.launch {
             if (isAuthenticationRequired()) {
-                sceneInteractor.changeScene(
-                    toScene = Scenes.Bouncer,
-                    loggingReason = "request to unlock device while authentication required",
-                )
+                if (alternateBouncerInteractor.canShowAlternateBouncer.value) {
+                    alternateBouncerInteractor.forceShow()
+                } else {
+                    sceneInteractor.changeScene(
+                        toScene = Scenes.Bouncer,
+                        loggingReason = "request to unlock device while authentication required",
+                    )
+                }
             } else {
                 sceneInteractor.changeScene(
                     toScene = Scenes.Gone,
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
index 65f3eb7..6629f6e 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
@@ -66,4 +66,5 @@
     override fun onPrimaryBouncerUserInput() {}
     override fun onAccessibilityAction() {}
     override fun onWalletLaunched() = Unit
+    override fun onDeviceUnfolded() {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
index a7266503..6c6683a 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
@@ -37,6 +37,11 @@
 import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
+import com.android.systemui.keyguard.shared.model.KeyguardState.OFF
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.log.FaceAuthenticationLogger
 import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -121,9 +126,9 @@
             .launchIn(applicationScope)
 
         merge(
-                keyguardTransitionInteractor.aodToLockscreenTransition,
-                keyguardTransitionInteractor.offToLockscreenTransition,
-                keyguardTransitionInteractor.dozingToLockscreenTransition
+                keyguardTransitionInteractor.transition(AOD, LOCKSCREEN),
+                keyguardTransitionInteractor.transition(OFF, LOCKSCREEN),
+                keyguardTransitionInteractor.transition(DOZING, LOCKSCREEN),
             )
             .filter { it.transitionState == TransitionState.STARTED }
             .sample(powerInteractor.detailedWakefulness)
@@ -244,6 +249,12 @@
         }
     }
 
+    override fun onDeviceUnfolded() {
+        if (facePropertyRepository.supportedPostures.contains(DevicePosture.OPENED)) {
+            runFaceAuth(FaceAuthUiEvent.FACE_AUTH_UPDATED_POSTURE_CHANGED, true)
+        }
+    }
+
     override fun registerListener(listener: FaceAuthenticationListener) {
         listeners.add(listener)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index 1230156..4ac0c56 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -42,6 +42,7 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
@@ -67,6 +68,9 @@
      */
     val pendingDisplay: Flow<PendingDisplay?>
 
+    /** Whether the default display is currently off. */
+    val defaultDisplayOff: Flow<Boolean>
+
     /** Represents a connected display that has not been enabled yet. */
     interface PendingDisplay {
         /** Id of the pending display. */
@@ -290,6 +294,11 @@
             }
             .debugLog("pendingDisplay")
 
+    override val defaultDisplayOff: Flow<Boolean> =
+        displays
+            .map { displays -> displays.firstOrNull { it.displayId == Display.DEFAULT_DISPLAY } }
+            .map { it?.state == Display.STATE_OFF }
+
     private fun <T> Flow<T>.debugLog(flowName: String): Flow<T> {
         return if (DEBUG) {
             traceEach(flowName, logcat = true, traceEmissionCount = true)
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
deleted file mode 100644
index 989b0de..0000000
--- a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.display.ui.view
-
-import android.content.Context
-import android.os.Bundle
-import android.view.View
-import android.view.WindowInsets
-import android.widget.TextView
-import androidx.core.view.updatePadding
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.phone.SystemUIBottomSheetDialog
-import com.android.systemui.statusbar.policy.ConfigurationController
-import kotlin.math.max
-
-/**
- * Dialog used to decide what to do with a connected display.
- *
- * [onCancelMirroring] is called **only** if mirroring didn't start, or when the dismiss button is
- * pressed.
- */
-class MirroringConfirmationDialog(
-    context: Context,
-    private val onStartMirroringClickListener: View.OnClickListener,
-    private val onCancelMirroring: View.OnClickListener,
-    private val navbarBottomInsetsProvider: () -> Int,
-    configurationController: ConfigurationController? = null,
-    private val showConcurrentDisplayInfo: Boolean = false,
-    theme: Int = R.style.Theme_SystemUI_Dialog,
-) : SystemUIBottomSheetDialog(context, configurationController, theme) {
-
-    private lateinit var mirrorButton: TextView
-    private lateinit var dismissButton: TextView
-    private lateinit var dualDisplayWarning: TextView
-    private lateinit var bottomSheet: View
-    private var enabledPressed = false
-    private val defaultDialogBottomInset =
-        context.resources.getDimensionPixelSize(R.dimen.dialog_bottom_padding)
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.connected_display_dialog)
-
-        mirrorButton =
-            requireViewById<TextView>(R.id.enable_display).apply {
-                setOnClickListener(onStartMirroringClickListener)
-                enabledPressed = true
-            }
-        dismissButton =
-            requireViewById<TextView>(R.id.cancel).apply { setOnClickListener(onCancelMirroring) }
-
-        dualDisplayWarning =
-            requireViewById<TextView>(R.id.dual_display_warning).apply {
-                visibility = if (showConcurrentDisplayInfo) View.VISIBLE else View.GONE
-            }
-
-        bottomSheet = requireViewById(R.id.cd_bottom_sheet)
-
-        setOnDismissListener {
-            if (!enabledPressed) {
-                onCancelMirroring.onClick(null)
-            }
-        }
-        setupInsets()
-    }
-
-    private fun setupInsets(navbarInsets: Int = navbarBottomInsetsProvider()) {
-        // This avoids overlap between dialog content and navigation bars.
-        // we only care about the bottom inset as in all other configuration where navigations
-        // are in other display sides there is no overlap with the dialog.
-        bottomSheet.updatePadding(bottom = max(navbarInsets, defaultDialogBottomInset))
-    }
-
-    override fun onInsetsChanged(changedTypes: Int, insets: WindowInsets) {
-        val navbarType = WindowInsets.Type.navigationBars()
-        if (changedTypes and navbarType != 0) {
-            setupInsets(insets.getInsets(navbarType).bottom)
-        }
-    }
-
-    override fun onConfigurationChanged() {
-        super.onConfigurationChanged()
-        setupInsets()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegate.kt
new file mode 100644
index 0000000..19b2673
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegate.kt
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.display.ui.view
+
+import android.app.Dialog
+import android.content.Context
+import android.content.res.Configuration
+import android.os.Bundle
+import android.view.View
+import android.view.WindowInsets
+import android.view.WindowInsetsAnimation
+import android.widget.TextView
+import androidx.annotation.StyleRes
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.updatePadding
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.DialogDelegate
+import com.android.systemui.statusbar.phone.SystemUIBottomSheetDialog
+import javax.inject.Inject
+import kotlin.math.max
+
+/**
+ * Dialog used to decide what to do with a connected display.
+ *
+ * [onCancelMirroring] is called **only** if mirroring didn't start, or when the dismiss button is
+ * pressed.
+ */
+class MirroringConfirmationDialogDelegate
+@VisibleForTesting
+constructor(
+    context: Context,
+    private val showConcurrentDisplayInfo: Boolean = false,
+    private val onStartMirroringClickListener: View.OnClickListener,
+    private val onCancelMirroring: View.OnClickListener,
+    private val navbarBottomInsetsProvider: () -> Int,
+) : DialogDelegate<Dialog> {
+
+    private lateinit var mirrorButton: TextView
+    private lateinit var dismissButton: TextView
+    private lateinit var dualDisplayWarning: TextView
+    private lateinit var bottomSheet: View
+    private var enabledPressed = false
+    private val defaultDialogBottomInset =
+        context.resources.getDimensionPixelSize(R.dimen.dialog_bottom_padding)
+
+    override fun onCreate(dialog: Dialog, savedInstanceState: Bundle?) {
+        dialog.setContentView(R.layout.connected_display_dialog)
+
+        mirrorButton =
+            dialog.requireViewById<TextView>(R.id.enable_display).apply {
+                setOnClickListener(onStartMirroringClickListener)
+                enabledPressed = true
+            }
+        dismissButton =
+            dialog.requireViewById<TextView>(R.id.cancel).apply {
+                setOnClickListener(onCancelMirroring)
+            }
+
+        dualDisplayWarning =
+            dialog.requireViewById<TextView>(R.id.dual_display_warning).apply {
+                visibility = if (showConcurrentDisplayInfo) View.VISIBLE else View.GONE
+            }
+
+        bottomSheet = dialog.requireViewById(R.id.cd_bottom_sheet)
+
+        dialog.setOnDismissListener {
+            if (!enabledPressed) {
+                onCancelMirroring.onClick(null)
+            }
+        }
+        setupInsets()
+    }
+
+    override fun onStart(dialog: Dialog) {
+        dialog.window?.decorView?.setWindowInsetsAnimationCallback(insetsAnimationCallback)
+    }
+
+    override fun onStop(dialog: Dialog) {
+        dialog.window?.decorView?.setWindowInsetsAnimationCallback(null)
+    }
+
+    private fun setupInsets(navbarInsets: Int = navbarBottomInsetsProvider()) {
+        // This avoids overlap between dialog content and navigation bars.
+        // we only care about the bottom inset as in all other configuration where navigations
+        // are in other display sides there is no overlap with the dialog.
+        bottomSheet.updatePadding(bottom = max(navbarInsets, defaultDialogBottomInset))
+    }
+
+    override fun onConfigurationChanged(dialog: Dialog, configuration: Configuration) {
+        setupInsets()
+    }
+
+    private val insetsAnimationCallback =
+        object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
+
+            private var lastInsets: WindowInsets? = null
+
+            override fun onEnd(animation: WindowInsetsAnimation) {
+                lastInsets?.let { onInsetsChanged(animation.typeMask, it) }
+            }
+
+            override fun onProgress(
+                insets: WindowInsets,
+                animations: MutableList<WindowInsetsAnimation>,
+            ): WindowInsets {
+                lastInsets = insets
+                onInsetsChanged(changedTypes = allAnimationMasks(animations), insets)
+                return insets
+            }
+
+            private fun allAnimationMasks(animations: List<WindowInsetsAnimation>): Int =
+                animations.fold(0) { acc: Int, it -> acc or it.typeMask }
+
+            private fun onInsetsChanged(changedTypes: Int, insets: WindowInsets) {
+                val navbarType = WindowInsets.Type.navigationBars()
+                if (changedTypes and navbarType != 0) {
+                    setupInsets(insets.getInsets(navbarType).bottom)
+                }
+            }
+        }
+
+    class Factory
+    @Inject
+    constructor(
+        @Application private val context: Context,
+        private val dialogFactory: SystemUIBottomSheetDialog.Factory,
+    ) {
+
+        fun createDialog(
+            showConcurrentDisplayInfo: Boolean = false,
+            onStartMirroringClickListener: View.OnClickListener,
+            onCancelMirroring: View.OnClickListener,
+            navbarBottomInsetsProvider: () -> Int,
+            @StyleRes theme: Int = R.style.Theme_SystemUI_Dialog,
+        ): Dialog =
+            dialogFactory.create(
+                delegate =
+                    MirroringConfirmationDialogDelegate(
+                        context = context,
+                        showConcurrentDisplayInfo = showConcurrentDisplayInfo,
+                        onStartMirroringClickListener = onStartMirroringClickListener,
+                        onCancelMirroring = onCancelMirroring,
+                        navbarBottomInsetsProvider = navbarBottomInsetsProvider,
+                    ),
+                theme = theme,
+            )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
index fbf0538..81ea2e7 100644
--- a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
@@ -25,8 +25,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor
 import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
-import com.android.systemui.display.ui.view.MirroringConfirmationDialog
-import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.display.ui.view.MirroringConfirmationDialogDelegate
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -54,7 +53,7 @@
     private val connectedDisplayInteractor: ConnectedDisplayInteractor,
     @Application private val scope: CoroutineScope,
     @Background private val bgDispatcher: CoroutineDispatcher,
-    private val configurationController: ConfigurationController,
+    private val bottomSheetFactory: MirroringConfirmationDialogDelegate.Factory,
 ) : CoreStartable {
 
     private var dialog: Dialog? = null
@@ -91,8 +90,8 @@
     private fun showDialog(pendingDisplay: PendingDisplay, concurrentDisplaysInProgess: Boolean) {
         hideDialog()
         dialog =
-            MirroringConfirmationDialog(
-                    context,
+            bottomSheetFactory
+                .createDialog(
                     onStartMirroringClickListener = {
                         scope.launch(bgDispatcher) { pendingDisplay.enable() }
                         hideDialog()
@@ -102,7 +101,6 @@
                         hideDialog()
                     },
                     navbarBottomInsetsProvider = { Utils.getNavbarInsets(context).bottom },
-                    configurationController,
                     showConcurrentDisplayInfo = concurrentDisplaysInProgess
                 )
                 .apply { show() }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 1a855d7..95012a2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -54,8 +54,6 @@
     private final DozeParameters mDozeParameters;
     private final DozeLog mDozeLog;
     private final DelayableExecutor mBgExecutor;
-
-    private Runnable mCancelRunnable = null;
     private long mLastTimeTickElapsed = 0;
     // If time tick is scheduled and there's not a pending runnable to cancel:
     private volatile boolean mTimeTickScheduled;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index d0f2559..0c2709e 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -22,6 +22,7 @@
 import static com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTOM;
 import static com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP;
 import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
 import android.animation.Animator;
 import android.content.res.Resources;
@@ -33,14 +34,16 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.dream.lowlight.LowLightTransitionCoordinator;
-import com.android.systemui.res.R;
+import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
 import com.android.systemui.complication.ComplicationHostViewController;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
 import com.android.systemui.dreams.dagger.DreamOverlayModule;
-import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.KeyguardState;
+import com.android.systemui.res.R;
 import com.android.systemui.shade.ShadeExpansionChangeEvent;
 import com.android.systemui.statusbar.BlurUtils;
 import com.android.systemui.util.ViewController;
@@ -50,6 +53,8 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 /**
  * View controller for {@link DreamOverlayContainerView}.
  */
@@ -62,6 +67,7 @@
     private final DreamOverlayAnimationsController mDreamOverlayAnimationsController;
     private final DreamOverlayStateController mStateController;
     private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
+    private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
 
     private final ComplicationHostViewController mComplicationHostViewController;
 
@@ -81,6 +87,7 @@
 
     // Main thread handler used to schedule periodic tasks (e.g. burn-in protection updates).
     private final Handler mHandler;
+    private final CoroutineDispatcher mMainDispatcher;
     private final int mDreamOverlayMaxTranslationY;
     private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
 
@@ -88,6 +95,7 @@
 
     private boolean mBouncerAnimating;
     private boolean mWakingUpFromSwipe;
+    private boolean mAnyBouncerShowing;
 
     private final BouncerlessScrimController mBouncerlessScrimController;
 
@@ -170,6 +178,7 @@
             LowLightTransitionCoordinator lowLightTransitionCoordinator,
             BlurUtils blurUtils,
             @Main Handler handler,
+            @Main CoroutineDispatcher mainDispatcher,
             @Main Resources resources,
             @Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
             @Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
@@ -178,7 +187,8 @@
             PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
             DreamOverlayAnimationsController animationsController,
             DreamOverlayStateController stateController,
-            BouncerlessScrimController bouncerlessScrimController) {
+            BouncerlessScrimController bouncerlessScrimController,
+            KeyguardTransitionInteractor keyguardTransitionInteractor) {
         super(containerView);
         mDreamOverlayContentView = contentView;
         mStatusBarViewController = statusBarViewController;
@@ -190,6 +200,8 @@
         mBouncerlessScrimController = bouncerlessScrimController;
         mBouncerlessScrimController.addCallback(mBouncerlessExpansionCallback);
 
+        mKeyguardTransitionInteractor = keyguardTransitionInteractor;
+
         mComplicationHostViewController = complicationHostViewController;
         mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
                 R.dimen.dream_overlay_y_offset);
@@ -200,6 +212,7 @@
                         ViewGroup.LayoutParams.MATCH_PARENT));
 
         mHandler = handler;
+        mMainDispatcher = mainDispatcher;
         mMaxBurnInOffset = maxBurnInOffset;
         mBurnInProtectionUpdateInterval = burnInProtectionUpdateInterval;
         mMillisUntilFullJitter = millisUntilFullJitter;
@@ -225,6 +238,12 @@
         mView.getRootSurfaceControl().setTouchableRegion(emptyRegion);
         emptyRegion.recycle();
 
+        collectFlow(
+                mView,
+                mKeyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState),
+                isFinished -> mAnyBouncerShowing = isFinished,
+                mMainDispatcher);
+
         // Start dream entry animations. Skip animations for low light clock.
         if (!mStateController.isLowLightActive()) {
             // If this is transitioning from the low light dream to the user dream, the overlay
@@ -246,6 +265,10 @@
         return mView;
     }
 
+    boolean isBouncerShowing() {
+        return mAnyBouncerShowing;
+    }
+
     private void updateBurnInOffsets() {
         // Make sure the offset starts at zero, to avoid a big jump in the overlay when it first
         // appears.
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 675e8de..a9ef531 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -19,9 +19,11 @@
 import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
 import static com.android.systemui.dreams.dagger.DreamModule.DREAM_TOUCH_INSET_MANAGER;
 import static com.android.systemui.dreams.dagger.DreamModule.HOME_CONTROL_PANEL_DREAM_COMPONENT;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.drawable.ColorDrawable;
 import android.util.Log;
 import android.view.View;
@@ -34,7 +36,10 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
 import androidx.lifecycle.LifecycleRegistry;
+import androidx.lifecycle.LifecycleService;
+import androidx.lifecycle.ServiceLifecycleDispatcher;
 import androidx.lifecycle.ViewModelStore;
 
 import com.android.dream.lowlight.dagger.LowLightDreamModule;
@@ -43,16 +48,23 @@
 import com.android.internal.policy.PhoneWindow;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.ambient.touch.TouchMonitor;
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent;
+import com.android.systemui.ambient.touch.scrim.ScrimManager;
+import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.communal.shared.model.CommunalScenes;
 import com.android.systemui.complication.Complication;
 import com.android.systemui.complication.dagger.ComplicationComponent;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
-import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
 import com.android.systemui.touch.TouchInsetManager;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.function.Consumer;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -62,7 +74,8 @@
  * dream reaches directly out to the service with a Window reference (via LayoutParams), which the
  * service uses to insert its own child Window into the dream's parent Window.
  */
-public class DreamOverlayService extends android.service.dreams.DreamOverlayService {
+public class DreamOverlayService extends android.service.dreams.DreamOverlayService implements
+        LifecycleOwner {
     private static final String TAG = "DreamOverlayService";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -75,6 +88,7 @@
     private DreamOverlayContainerViewController mDreamOverlayContainerViewController;
     private final DreamOverlayCallbackController mDreamOverlayCallbackController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final ScrimManager mScrimManager;
     @Nullable
     private final ComponentName mLowLightDreamComponent;
     @Nullable
@@ -92,34 +106,96 @@
     // True if the service has been destroyed.
     private boolean mDestroyed = false;
 
+    /**
+     * True if the notification shade is open.
+     */
+    private boolean mShadeExpanded = false;
+
+    /**
+     * True if any part of the glanceable hub is visible.
+     */
+    private boolean mCommunalVisible = false;
+
+    /**
+     * True if the primary bouncer is visible.
+     */
+    private boolean mBouncerShowing = false;
+
     private final ComplicationComponent mComplicationComponent;
 
+    private final AmbientTouchComponent mAmbientTouchComponent;
+
     private final com.android.systemui.dreams.complication.dagger.ComplicationComponent
             mDreamComplicationComponent;
 
     private final DreamOverlayComponent mDreamOverlayComponent;
 
-    private final DreamOverlayLifecycleOwner mLifecycleOwner;
+    /**
+     * This {@link LifecycleRegistry} controls when dream overlay functionality, like touch
+     * handling, should be active. It will automatically be paused when the dream overlay is hidden
+     * while dreaming, such as when the notification shade, bouncer, or glanceable hub are visible.
+     */
     private final LifecycleRegistry mLifecycleRegistry;
 
-    private DreamOverlayTouchMonitor mDreamOverlayTouchMonitor;
+    /**
+     * Drives the lifecycle exposed by this service's {@link #getLifecycle()}.
+     * <p>
+     * Used to mimic a {@link LifecycleService}, though we do not update the lifecycle in
+     * {@link #onBind(Intent)} since it's final in the base class.
+     */
+    private final ServiceLifecycleDispatcher mDispatcher = new ServiceLifecycleDispatcher(this);
+
+    private TouchMonitor mTouchMonitor;
+
+    private final CommunalInteractor mCommunalInteractor;
+
+    private final SystemDialogsCloser mSystemDialogsCloser;
 
     private final KeyguardUpdateMonitorCallback mKeyguardCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
                 public void onShadeExpandedChanged(boolean expanded) {
                     mExecutor.execute(() -> {
-                        if (getCurrentStateLocked() != Lifecycle.State.RESUMED
-                                && getCurrentStateLocked() != Lifecycle.State.STARTED) {
+                        if (mShadeExpanded == expanded) {
                             return;
                         }
+                        mShadeExpanded = expanded;
 
-                        setCurrentStateLocked(
-                                expanded ? Lifecycle.State.STARTED : Lifecycle.State.RESUMED);
+                        updateLifecycleStateLocked();
                     });
                 }
             };
 
+    private final Consumer<Boolean> mCommunalVisibleConsumer = new Consumer<>() {
+        @Override
+        public void accept(Boolean communalVisible) {
+            mExecutor.execute(() -> {
+                if (mCommunalVisible == communalVisible) {
+                    return;
+                }
+
+                mCommunalVisible = communalVisible;
+
+                updateLifecycleStateLocked();
+            });
+        }
+    };
+
+    private final Consumer<Boolean> mBouncerShowingConsumer = new Consumer<>() {
+        @Override
+        public void accept(Boolean bouncerShowing) {
+            mExecutor.execute(() -> {
+                if (mBouncerShowing == bouncerShowing) {
+                    return;
+                }
+
+                mBouncerShowing = bouncerShowing;
+
+                updateLifecycleStateLocked();
+            });
+        }
+    };
+
     private final DreamOverlayStateController.Callback mExitAnimationFinishedCallback =
             new DreamOverlayStateController.Callback() {
                 @Override
@@ -162,21 +238,27 @@
             com.android.systemui.dreams.complication.dagger.ComplicationComponent.Factory
                     dreamComplicationComponentFactory,
             DreamOverlayComponent.Factory dreamOverlayComponentFactory,
+            AmbientTouchComponent.Factory ambientTouchComponentFactory,
             DreamOverlayStateController stateController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
+            ScrimManager scrimManager,
+            CommunalInteractor communalInteractor,
+            SystemDialogsCloser systemDialogsCloser,
             UiEventLogger uiEventLogger,
             @Named(DREAM_TOUCH_INSET_MANAGER) TouchInsetManager touchInsetManager,
             @Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
-                    ComponentName lowLightDreamComponent,
+            ComponentName lowLightDreamComponent,
             @Nullable @Named(HOME_CONTROL_PANEL_DREAM_COMPONENT)
-                    ComponentName homeControlPanelDreamComponent,
+            ComponentName homeControlPanelDreamComponent,
             DreamOverlayCallbackController dreamOverlayCallbackController,
+            KeyguardInteractor keyguardInteractor,
             @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
         super(executor);
         mContext = context;
         mExecutor = executor;
         mWindowManager = windowManager;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mScrimManager = scrimManager;
         mLowLightDreamComponent = lowLightDreamComponent;
         mHomeControlPanelDreamComponent = homeControlPanelDreamComponent;
         mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback);
@@ -184,6 +266,8 @@
         mUiEventLogger = uiEventLogger;
         mDreamOverlayCallbackController = dreamOverlayCallbackController;
         mWindowTitle = windowTitle;
+        mCommunalInteractor = communalInteractor;
+        mSystemDialogsCloser = systemDialogsCloser;
 
         final ViewModelStore viewModelStore = new ViewModelStore();
         final Complication.Host host =
@@ -194,13 +278,37 @@
         mDreamComplicationComponent = dreamComplicationComponentFactory.create(
                 mComplicationComponent.getVisibilityController(), touchInsetManager);
         mDreamOverlayComponent = dreamOverlayComponentFactory.create(lifecycleOwner,
-                mComplicationComponent.getComplicationHostViewController(), touchInsetManager,
+                mComplicationComponent.getComplicationHostViewController(), touchInsetManager);
+        mAmbientTouchComponent = ambientTouchComponentFactory.create(lifecycleOwner,
                 new HashSet<>(Arrays.asList(
-                        mDreamComplicationComponent.getHideComplicationTouchHandler())));
-        mLifecycleOwner = lifecycleOwner;
-        mLifecycleRegistry = mLifecycleOwner.getRegistry();
+                        mDreamComplicationComponent.getHideComplicationTouchHandler(),
+                        mDreamOverlayComponent.getCommunalTouchHandler())));
+        mLifecycleRegistry = lifecycleOwner.getRegistry();
 
-        mExecutor.execute(() -> setCurrentStateLocked(Lifecycle.State.CREATED));
+        mExecutor.execute(() -> setLifecycleStateLocked(Lifecycle.State.CREATED));
+
+        collectFlow(getLifecycle(), communalInteractor.isCommunalVisible(),
+                mCommunalVisibleConsumer);
+        collectFlow(getLifecycle(), keyguardInteractor.primaryBouncerShowing,
+                mBouncerShowingConsumer);
+    }
+
+    @NonNull
+    @Override
+    public Lifecycle getLifecycle() {
+        return mDispatcher.getLifecycle();
+    }
+
+    @Override
+    public void onCreate() {
+        mDispatcher.onServicePreSuperOnCreate();
+        super.onCreate();
+    }
+
+    @Override
+    public void onStart(Intent intent, int startId) {
+        mDispatcher.onServicePreSuperOnStart();
+        super.onStart(intent, startId);
     }
 
     @Override
@@ -208,19 +316,20 @@
         mKeyguardUpdateMonitor.removeCallback(mKeyguardCallback);
 
         mExecutor.execute(() -> {
-            setCurrentStateLocked(Lifecycle.State.DESTROYED);
+            setLifecycleStateLocked(Lifecycle.State.DESTROYED);
 
             resetCurrentDreamOverlayLocked();
 
             mDestroyed = true;
         });
 
+        mDispatcher.onServicePreSuperOnDestroy();
         super.onDestroy();
     }
 
     @Override
     public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
-        setCurrentStateLocked(Lifecycle.State.STARTED);
+        setLifecycleStateLocked(Lifecycle.State.STARTED);
 
         mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
 
@@ -239,8 +348,8 @@
 
         mDreamOverlayContainerViewController =
                 mDreamOverlayComponent.getDreamOverlayContainerViewController();
-        mDreamOverlayTouchMonitor = mDreamOverlayComponent.getDreamOverlayTouchMonitor();
-        mDreamOverlayTouchMonitor.init();
+        mTouchMonitor = mAmbientTouchComponent.getTouchMonitor();
+        mTouchMonitor.init();
 
         mStateController.setShouldShowComplications(shouldShowComplications());
 
@@ -250,7 +359,7 @@
             return;
         }
 
-        setCurrentStateLocked(Lifecycle.State.RESUMED);
+        setLifecycleStateLocked(Lifecycle.State.RESUMED);
         mStateController.setOverlayActive(true);
         final ComponentName dreamComponent = getDreamComponent();
         mStateController.setLowLightActive(
@@ -270,14 +379,27 @@
         resetCurrentDreamOverlayLocked();
     }
 
-    private Lifecycle.State getCurrentStateLocked() {
+    private Lifecycle.State getLifecycleStateLocked() {
         return mLifecycleRegistry.getCurrentState();
     }
 
-    private void setCurrentStateLocked(Lifecycle.State state) {
+    private void setLifecycleStateLocked(Lifecycle.State state) {
         mLifecycleRegistry.setCurrentState(state);
     }
 
+    private void updateLifecycleStateLocked() {
+        if (getLifecycleStateLocked() != Lifecycle.State.RESUMED
+                && getLifecycleStateLocked() != Lifecycle.State.STARTED) {
+            return;
+        }
+
+        // If anything is on top of the dream, we should stop touch handling.
+        boolean shouldPause = mShadeExpanded || mCommunalVisible || mBouncerShowing;
+
+        setLifecycleStateLocked(
+                shouldPause ? Lifecycle.State.STARTED : Lifecycle.State.RESUMED);
+    }
+
     @Override
     public void onWakeUp() {
         if (mDreamOverlayContainerViewController != null) {
@@ -286,6 +408,28 @@
         }
     }
 
+    @Override
+    public void onComeToFront() {
+        // Make sure the bouncer is closed. Expanding the shade effectively contracts the bouncer
+        // an equal amount.
+        if (mDreamOverlayContainerViewController != null
+                && mDreamOverlayContainerViewController.isBouncerShowing()) {
+            mScrimManager.getCurrentController().expand(
+                    new ShadeExpansionChangeEvent(
+                            /* fraction= */ 1.f,
+                            /* expanded= */ false,
+                            /* tracking= */ true));
+        }
+
+        // closeSystemDialogs takes care of closing anything that responds to the
+        // {@link Intent.ACTION_CLOSE_SYSTEM_DIALOGS} broadcast (which includes the notification
+        // shade).
+        mSystemDialogsCloser.closeSystemDialogs();
+
+        // Hide glanceable hub (this is a nop if glanceable hub is not open).
+        mCommunalInteractor.changeScene(CommunalScenes.Blank, null);
+    }
+
     /**
      * Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
      * called from the main executing thread. The window attributes closely mirror those that are
@@ -370,7 +514,7 @@
         mStateController.setEntryAnimationsFinished(false);
 
         mDreamOverlayContainerViewController = null;
-        mDreamOverlayTouchMonitor = null;
+        mTouchMonitor = null;
 
         mWindow = null;
         mStarted = false;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index 8d8702e..da72a56 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -16,30 +16,30 @@
 
 package com.android.systemui.dreams;
 
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
+
 import android.app.AlarmManager;
 import android.app.StatusBarManager;
 import android.content.res.Resources;
 import android.hardware.SensorPrivacyManager;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
 import android.provider.Settings;
 import android.text.format.DateFormat;
 import android.util.PluralsMessageFormatter;
 import android.view.View;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
 import com.android.systemui.log.LogBuffer;
 import com.android.systemui.log.dagger.DreamLog;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository;
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -65,7 +65,6 @@
 public class DreamOverlayStatusBarViewController extends ViewController<DreamOverlayStatusBarView> {
     private static final String TAG = "DreamStatusBarCtrl";
 
-    private final ConnectivityManager mConnectivityManager;
     private final TouchInsetManager.TouchInsetSession mTouchInsetSession;
     private final NextAlarmController mNextAlarmController;
     private final AlarmManager mAlarmManager;
@@ -77,6 +76,7 @@
     private final ZenModeController mZenModeController;
     private final DreamOverlayStateController mDreamOverlayStateController;
     private final UserTracker mUserTracker;
+    private final WifiRepository mWifiRepository;
     private final StatusBarWindowStateController mStatusBarWindowStateController;
     private final DreamOverlayStatusBarItemsProvider mStatusBarItemsProvider;
     private final Executor mMainExecutor;
@@ -89,28 +89,6 @@
     // Whether dream entry animations are finished.
     private boolean mEntryAnimationsFinished = false;
 
-    private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
-            .clearCapabilities()
-            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
-
-    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
-        @Override
-        public void onCapabilitiesChanged(
-                Network network, NetworkCapabilities networkCapabilities) {
-            updateWifiUnavailableStatusIcon();
-        }
-
-        @Override
-        public void onAvailable(Network network) {
-            updateWifiUnavailableStatusIcon();
-        }
-
-        @Override
-        public void onLost(Network network) {
-            updateWifiUnavailableStatusIcon();
-        }
-    };
-
     private final DreamOverlayStateController.Callback mDreamOverlayStateCallback =
             new DreamOverlayStateController.Callback() {
                 @Override
@@ -151,7 +129,6 @@
             DreamOverlayStatusBarView view,
             @Main Resources resources,
             @Main Executor mainExecutor,
-            ConnectivityManager connectivityManager,
             TouchInsetManager.TouchInsetSession touchInsetSession,
             AlarmManager alarmManager,
             NextAlarmController nextAlarmController,
@@ -163,11 +140,11 @@
             DreamOverlayStatusBarItemsProvider statusBarItemsProvider,
             DreamOverlayStateController dreamOverlayStateController,
             UserTracker userTracker,
+            WifiRepository wifiRepository,
             @DreamLog LogBuffer logBuffer) {
         super(view);
         mResources = resources;
         mMainExecutor = mainExecutor;
-        mConnectivityManager = connectivityManager;
         mTouchInsetSession = touchInsetSession;
         mAlarmManager = alarmManager;
         mNextAlarmController = nextAlarmController;
@@ -179,6 +156,7 @@
         mZenModeController = zenModeController;
         mDreamOverlayStateController = dreamOverlayStateController;
         mUserTracker = userTracker;
+        mWifiRepository = wifiRepository;
         mLogger = new DreamLogger(logBuffer, TAG);
 
         // Register to receive show/hide updates for the system status bar. Our custom status bar
@@ -190,8 +168,11 @@
     protected void onViewAttached() {
         mIsAttached = true;
 
-        mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
-        updateWifiUnavailableStatusIcon();
+        collectFlow(
+                mView,
+                mWifiRepository.getWifiNetwork(),
+                network -> updateWifiUnavailableStatusIcon(
+                        network instanceof WifiNetworkModel.Active));
 
         mNextAlarmController.addCallback(mNextAlarmCallback);
         updateAlarmStatusIcon();
@@ -215,7 +196,6 @@
         mZenModeController.removeCallback(mZenModeCallback);
         mSensorPrivacyController.removeCallback(mSensorCallback);
         mNextAlarmController.removeCallback(mNextAlarmCallback);
-        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
         mDreamOverlayNotificationCountProvider.ifPresent(
                 provider -> provider.removeCallback(mNotificationCountCallback));
         mStatusBarItemsProvider.removeCallback(mStatusBarItemsProviderCallback);
@@ -258,12 +238,8 @@
                 && !mStatusBarWindowStateController.windowIsShowing();
     }
 
-    private void updateWifiUnavailableStatusIcon() {
-        final NetworkCapabilities capabilities =
-                mConnectivityManager.getNetworkCapabilities(
-                        mConnectivityManager.getActiveNetwork());
-        final boolean available = capabilities != null
-                && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+    @VisibleForTesting
+    void updateWifiUnavailableStatusIcon(boolean available) {
         showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available,
                 R.string.wifi_unavailable_dream_overlay_content_description);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/SystemDialogsCloser.java b/packages/SystemUI/src/com/android/systemui/dreams/SystemDialogsCloser.java
new file mode 100644
index 0000000..6e7239a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/SystemDialogsCloser.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams;
+
+/** Defines an interface for a class that is responsible for closing system dialogs. */
+public interface SystemDialogsCloser {
+    /** Close any open system dialogs. */
+    void closeSystemDialogs();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java
index ee48ee5..f8ae5c2 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/HideComplicationTouchHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.dreams.complication;
 
+import static com.android.systemui.Flags.removeDreamOverlayHideOnTouch;
 import static com.android.systemui.dreams.complication.dagger.ComplicationModule.COMPLICATIONS_FADE_OUT_DELAY;
 import static com.android.systemui.dreams.complication.dagger.ComplicationModule.COMPLICATIONS_RESTORE_TIMEOUT;
 
@@ -25,11 +26,11 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.systemui.ambient.touch.TouchHandler;
+import com.android.systemui.ambient.touch.TouchMonitor;
 import com.android.systemui.complication.Complication;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayStateController;
-import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.touch.TouchInsetManager;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -46,12 +47,12 @@
  * {@link HideComplicationTouchHandler} is responsible for hiding the overlay complications from
  * visibility whenever there is touch interactions outside the overlay. The overlay interaction
  * scope includes touches to the complication plus any touch entry region for gestures as specified
- * to the {@link DreamOverlayTouchMonitor}.
+ * to the {@link TouchMonitor}.
  *
- * This {@link DreamTouchHandler} is also responsible for fading in the complications at the end
- * of the {@link com.android.systemui.dreams.touch.DreamTouchHandler.TouchSession}.
+ * This {@link TouchHandler} is also responsible for fading in the complications at the end
+ * of the {@link TouchHandler.TouchSession}.
  */
-public class HideComplicationTouchHandler implements DreamTouchHandler {
+public class HideComplicationTouchHandler implements TouchHandler {
     private static final String TAG = "HideComplicationHandler";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -120,7 +121,7 @@
         final boolean bouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
 
         // If other sessions are interested in this touch, do not fade out elements.
-        if (session.getActiveSessionCount() > 1 || bouncerShowing
+        if (removeDreamOverlayHideOnTouch() || session.getActiveSessionCount() > 1 || bouncerShowing
                 || mOverlayStateController.areExitAnimationsRunning()) {
             if (DEBUG) {
                 Log.d(TAG, "not fading. Active session count: " + session.getActiveSessionCount()
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 ba74742..516b8c5 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -25,16 +25,17 @@
 
 import com.android.dream.lowlight.dagger.LowLightDreamModule;
 import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.ambient.touch.scrim.dagger.ScrimModule;
 import com.android.systemui.complication.dagger.RegisteredComplicationsModule;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
 import com.android.systemui.dreams.DreamOverlayService;
+import com.android.systemui.dreams.SystemDialogsCloser;
 import com.android.systemui.dreams.complication.dagger.ComplicationComponent;
 import com.android.systemui.dreams.homecontrols.DreamActivityProvider;
 import com.android.systemui.dreams.homecontrols.DreamActivityProviderImpl;
 import com.android.systemui.dreams.homecontrols.HomeControlsDreamService;
-import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule;
 import com.android.systemui.res.R;
 import com.android.systemui.touch.TouchInsetManager;
 
@@ -146,6 +147,15 @@
         return Optional.empty();
     }
 
+    /**
+     * Provides an implementation for {@link SystemDialogsCloser} that calls
+     * {@link Context.closeSystemDialogs}.
+     */
+    @Provides
+    static SystemDialogsCloser providesSystemDialogsCloser(Context context) {
+        return () -> context.closeSystemDialogs();
+    }
+
     /** */
     @Provides
     @Named(DREAM_ONLY_ENABLED_FOR_DOCK_USER)
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java
index cb587c2..16276fe 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java
@@ -16,19 +16,14 @@
 
 package com.android.systemui.dreams.dagger;
 
-import static com.android.systemui.dreams.dagger.DreamOverlayModule.DREAM_TOUCH_HANDLERS;
-
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
-import android.annotation.Nullable;
-
 import androidx.lifecycle.LifecycleOwner;
 
 import com.android.systemui.complication.ComplicationHostViewController;
 import com.android.systemui.dreams.DreamOverlayContainerViewController;
-import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
-import com.android.systemui.dreams.touch.dagger.DreamTouchModule;
+import com.android.systemui.dreams.touch.CommunalTouchHandler;
+import com.android.systemui.dreams.touch.dagger.CommunalTouchModule;
 import com.android.systemui.touch.TouchInsetManager;
 
 import dagger.BindsInstance;
@@ -36,17 +31,15 @@
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
-import java.util.Set;
 
-import javax.inject.Named;
 import javax.inject.Scope;
 
 /**
  * Dagger subcomponent for {@link DreamOverlayModule}.
  */
 @Subcomponent(modules = {
-        DreamTouchModule.class,
         DreamOverlayModule.class,
+        CommunalTouchModule.class
 })
 @DreamOverlayComponent.DreamOverlayScope
 public interface DreamOverlayComponent {
@@ -56,9 +49,7 @@
         DreamOverlayComponent create(
                 @BindsInstance LifecycleOwner lifecycleOwner,
                 @BindsInstance ComplicationHostViewController complicationHostViewController,
-                @BindsInstance TouchInsetManager touchInsetManager,
-                @BindsInstance @Named(DREAM_TOUCH_HANDLERS) @Nullable
-                        Set<DreamTouchHandler> dreamTouchHandlers);
+                @BindsInstance TouchInsetManager touchInsetManager);
     }
 
     /** Scope annotation for singleton items within the {@link DreamOverlayComponent}. */
@@ -70,6 +61,6 @@
     /** Builds a {@link DreamOverlayContainerViewController}. */
     DreamOverlayContainerViewController getDreamOverlayContainerViewController();
 
-    /** Builds a {@link DreamOverlayTouchMonitor} */
-    DreamOverlayTouchMonitor getDreamOverlayTouchMonitor();
+    /** Builds communal touch handler */
+    CommunalTouchHandler getCommunalTouchHandler();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
index 34dd1008..999e681 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.dreams.dagger;
 
-import android.annotation.Nullable;
 import android.content.res.Resources;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
@@ -25,26 +24,20 @@
 import androidx.lifecycle.LifecycleOwner;
 
 import com.android.internal.util.Preconditions;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayContainerView;
 import com.android.systemui.dreams.DreamOverlayStatusBarView;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
+import com.android.systemui.res.R;
 import com.android.systemui.touch.TouchInsetManager;
 
 import dagger.Module;
 import dagger.Provides;
-import dagger.multibindings.ElementsIntoSet;
-
-import java.util.HashSet;
-import java.util.Set;
 
 import javax.inject.Named;
 
 /** Dagger module for {@link DreamOverlayComponent}. */
 @Module
 public abstract class DreamOverlayModule {
-    public static final String DREAM_TOUCH_HANDLERS = "dream_touch_handlers";
     public static final String DREAM_OVERLAY_CONTENT_VIEW = "dream_overlay_content_view";
     public static final String MAX_BURN_IN_OFFSET = "max_burn_in_offset";
     public static final String BURN_IN_PROTECTION_UPDATE_INTERVAL =
@@ -169,11 +162,4 @@
     static Lifecycle providesLifecycle(LifecycleOwner lifecycleOwner) {
         return lifecycleOwner.getLifecycle();
     }
-
-    @Provides
-    @ElementsIntoSet
-    static Set<DreamTouchHandler> providesDreamTouchHandlers(
-            @Named(DREAM_TOUCH_HANDLERS) @Nullable Set<DreamTouchHandler> touchHandlers) {
-        return touchHandlers != null ? touchHandlers : new HashSet<>();
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
deleted file mode 100644
index 75c50fd..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ /dev/null
@@ -1,395 +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.dreams.touch;
-
-import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING;
-import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING;
-import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION;
-import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.InputEvent;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.logging.UiEvent;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
-import com.android.systemui.dreams.touch.scrim.ScrimController;
-import com.android.systemui.dreams.touch.scrim.ScrimManager;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shade.ShadeExpansionChangeEvent;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.wm.shell.animation.FlingAnimationUtils;
-
-import java.util.Optional;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * Monitor for tracking touches on the DreamOverlay to bring up the bouncer.
- */
-public class BouncerSwipeTouchHandler implements DreamTouchHandler {
-    /**
-     * An interface for creating ValueAnimators.
-     */
-    public interface ValueAnimatorCreator {
-        /**
-         * Creates {@link ValueAnimator}.
-         */
-        ValueAnimator create(float start, float finish);
-    }
-
-    /**
-     * An interface for obtaining VelocityTrackers.
-     */
-    public interface VelocityTrackerFactory {
-        /**
-         * Obtains {@link VelocityTracker}.
-         */
-        VelocityTracker obtain();
-    }
-
-    public static final float FLING_PERCENTAGE_THRESHOLD = 0.5f;
-
-    private static final String TAG = "BouncerSwipeTouchHandler";
-    private final NotificationShadeWindowController mNotificationShadeWindowController;
-    private final LockPatternUtils mLockPatternUtils;
-    private final UserTracker mUserTracker;
-    private final float mBouncerZoneScreenPercentage;
-    private final float mMinBouncerZoneScreenPercentage;
-
-    private final ScrimManager mScrimManager;
-    private ScrimController mCurrentScrimController;
-    private float mCurrentExpansion;
-    private final Optional<CentralSurfaces> mCentralSurfaces;
-
-    private VelocityTracker mVelocityTracker;
-
-    private final FlingAnimationUtils mFlingAnimationUtils;
-    private final FlingAnimationUtils mFlingAnimationUtilsClosing;
-
-    private Boolean mCapture;
-    private Boolean mExpanded;
-
-    private boolean mBouncerInitiallyShowing;
-
-    private TouchSession mTouchSession;
-
-    private ValueAnimatorCreator mValueAnimatorCreator;
-
-    private VelocityTrackerFactory mVelocityTrackerFactory;
-
-    private final UiEventLogger mUiEventLogger;
-
-    private final ScrimManager.Callback mScrimManagerCallback = new ScrimManager.Callback() {
-        @Override
-        public void onScrimControllerChanged(ScrimController controller) {
-            if (mCurrentScrimController != null) {
-                mCurrentScrimController.reset();
-            }
-
-            mCurrentScrimController = controller;
-        }
-    };
-
-    private final GestureDetector.OnGestureListener mOnGestureListener =
-            new GestureDetector.SimpleOnGestureListener() {
-                @Override
-                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
-                        float distanceY) {
-                    if (mCapture == null) {
-                        // If the user scrolling favors a vertical direction, begin capturing
-                        // scrolls.
-                        mCapture = Math.abs(distanceY) > Math.abs(distanceX);
-                        mBouncerInitiallyShowing = mCentralSurfaces
-                                .map(CentralSurfaces::isBouncerShowing)
-                                .orElse(false);
-
-                        if (mCapture) {
-                            // reset expanding
-                            mExpanded = false;
-                            // Since the user is dragging the bouncer up, set scrimmed to false.
-                            mCurrentScrimController.show();
-                        }
-                    }
-
-                    if (!mCapture) {
-                        return false;
-                    }
-
-                    // Don't set expansion for downward scroll when the bouncer is hidden.
-                    if (!mBouncerInitiallyShowing && (e1.getY() < e2.getY())) {
-                        return true;
-                    }
-
-                    // Don't set expansion for upward scroll when the bouncer is shown.
-                    if (mBouncerInitiallyShowing && (e1.getY() > e2.getY())) {
-                        return true;
-                    }
-
-                    if (!mCentralSurfaces.isPresent()) {
-                        return true;
-                    }
-
-                    // If scrolling up and keyguard is not locked, dismiss the dream since there's
-                    // no bouncer to show.
-                    if (e1.getY() > e2.getY()
-                            && !mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
-                        mCentralSurfaces.get().awakenDreams();
-                        return true;
-                    }
-
-                    // For consistency, we adopt the expansion definition found in the
-                    // PanelViewController. In this case, expansion refers to the view above the
-                    // bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer
-                    // is fully hidden at full expansion (1) and fully visible when fully collapsed
-                    // (0).
-                    final float dragDownAmount = e2.getY() - e1.getY();
-                    final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY())
-                            / mTouchSession.getBounds().height();
-                    setPanelExpansion(mBouncerInitiallyShowing
-                            ? screenTravelPercentage : 1 - screenTravelPercentage);
-                    return true;
-                }
-            };
-
-    private void setPanelExpansion(float expansion) {
-        mCurrentExpansion = expansion;
-        ShadeExpansionChangeEvent event =
-                new ShadeExpansionChangeEvent(
-                        /* fraction= */ mCurrentExpansion,
-                        /* expanded= */ mExpanded,
-                        /* tracking= */ true);
-        mCurrentScrimController.expand(event);
-    }
-
-
-    @VisibleForTesting
-    public enum DreamEvent implements UiEventLogger.UiEventEnum {
-        @UiEvent(doc = "The screensaver has been swiped up.")
-        DREAM_SWIPED(988),
-
-        @UiEvent(doc = "The bouncer has become fully visible over dream.")
-        DREAM_BOUNCER_FULLY_VISIBLE(1056);
-
-        private final int mId;
-
-        DreamEvent(int id) {
-            mId = id;
-        }
-
-        @Override
-        public int getId() {
-            return mId;
-        }
-    }
-
-    @Inject
-    public BouncerSwipeTouchHandler(
-            ScrimManager scrimManager,
-            Optional<CentralSurfaces> centralSurfaces,
-            NotificationShadeWindowController notificationShadeWindowController,
-            ValueAnimatorCreator valueAnimatorCreator,
-            VelocityTrackerFactory velocityTrackerFactory,
-            LockPatternUtils lockPatternUtils,
-            UserTracker userTracker,
-            @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
-                    FlingAnimationUtils flingAnimationUtils,
-            @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
-                    FlingAnimationUtils flingAnimationUtilsClosing,
-            @Named(SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage,
-            @Named(MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage,
-            UiEventLogger uiEventLogger) {
-        mCentralSurfaces = centralSurfaces;
-        mScrimManager = scrimManager;
-        mNotificationShadeWindowController = notificationShadeWindowController;
-        mLockPatternUtils = lockPatternUtils;
-        mUserTracker = userTracker;
-        mBouncerZoneScreenPercentage = swipeRegionPercentage;
-        mMinBouncerZoneScreenPercentage = minRegionPercentage;
-        mFlingAnimationUtils = flingAnimationUtils;
-        mFlingAnimationUtilsClosing = flingAnimationUtilsClosing;
-        mValueAnimatorCreator = valueAnimatorCreator;
-        mVelocityTrackerFactory = velocityTrackerFactory;
-        mUiEventLogger = uiEventLogger;
-    }
-
-    @Override
-    public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
-        final int width = bounds.width();
-        final int height = bounds.height();
-        final float minBouncerHeight = height * mMinBouncerZoneScreenPercentage;
-        final int minAllowableBottom = Math.round(height * (1 - mMinBouncerZoneScreenPercentage));
-
-        final boolean isBouncerShowing =
-                mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false);
-        final Rect normalRegion = isBouncerShowing
-                ? new Rect(0, 0, width, Math.round(height * mBouncerZoneScreenPercentage))
-                : new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)),
-                        width, height);
-
-        if (!isBouncerShowing && exclusionRect != null) {
-            int lowestBottom = Math.min(Math.max(0, exclusionRect.bottom), minAllowableBottom);
-            normalRegion.top = Math.max(normalRegion.top, lowestBottom);
-        }
-        region.union(normalRegion);
-    }
-
-
-    @Override
-    public void onSessionStart(TouchSession session) {
-        mVelocityTracker = mVelocityTrackerFactory.obtain();
-        mTouchSession = session;
-        mVelocityTracker.clear();
-        mNotificationShadeWindowController.setForcePluginOpen(true, this);
-        mScrimManager.addCallback(mScrimManagerCallback);
-        mCurrentScrimController = mScrimManager.getCurrentController();
-
-        session.registerCallback(() -> {
-            if (mVelocityTracker != null) {
-                mVelocityTracker.recycle();
-                mVelocityTracker = null;
-            }
-            mScrimManager.removeCallback(mScrimManagerCallback);
-            mCapture = null;
-            mNotificationShadeWindowController.setForcePluginOpen(false, this);
-        });
-
-        session.registerGestureListener(mOnGestureListener);
-        session.registerInputListener(ev -> onMotionEvent(ev));
-
-    }
-
-    private void onMotionEvent(InputEvent event) {
-        if (!(event instanceof MotionEvent)) {
-            Log.e(TAG, "non MotionEvent received:" + event);
-            return;
-        }
-
-        final MotionEvent motionEvent = (MotionEvent) event;
-
-        switch (motionEvent.getAction()) {
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP:
-                mTouchSession.pop();
-                // If we are not capturing any input, there is no need to consider animating to
-                // finish transition.
-                if (mCapture == null || !mCapture) {
-                    break;
-                }
-
-                // We must capture the resulting velocities as resetMonitor() will clear these
-                // values.
-                mVelocityTracker.computeCurrentVelocity(1000);
-                final float verticalVelocity = mVelocityTracker.getYVelocity();
-                final float horizontalVelocity = mVelocityTracker.getXVelocity();
-
-                final float velocityVector =
-                        (float) Math.hypot(horizontalVelocity, verticalVelocity);
-
-                mExpanded = !flingRevealsOverlay(verticalVelocity, velocityVector);
-                final float expansion = mExpanded
-                        ? KeyguardBouncerConstants.EXPANSION_VISIBLE
-                        : KeyguardBouncerConstants.EXPANSION_HIDDEN;
-
-                // Log the swiping up to show Bouncer event.
-                if (!mBouncerInitiallyShowing
-                        && expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
-                    mUiEventLogger.log(DreamEvent.DREAM_SWIPED);
-                }
-
-                flingToExpansion(verticalVelocity, expansion);
-                break;
-            default:
-                mVelocityTracker.addMovement(motionEvent);
-                break;
-        }
-    }
-
-    private ValueAnimator createExpansionAnimator(float targetExpansion, float expansionHeight) {
-        final ValueAnimator animator =
-                mValueAnimatorCreator.create(mCurrentExpansion, targetExpansion);
-        animator.addUpdateListener(
-                animation -> {
-                    float expansionFraction = (float) animation.getAnimatedValue();
-                    float dragDownAmount = expansionFraction * expansionHeight;
-                    setPanelExpansion(expansionFraction);
-                });
-        if (!mBouncerInitiallyShowing
-                && targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
-            animator.addListener(
-                    new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            mUiEventLogger.log(DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
-                        }
-                    });
-        }
-        return animator;
-    }
-
-    protected boolean flingRevealsOverlay(float velocity, float velocityVector) {
-        // Fully expand the space above the bouncer, if the user has expanded the bouncer less
-        // than halfway or final velocity was positive, indicating a downward direction.
-        if (Math.abs(velocityVector) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
-            return mCurrentExpansion > FLING_PERCENTAGE_THRESHOLD;
-        } else {
-            return velocity > 0;
-        }
-    }
-
-    protected void flingToExpansion(float velocity, float expansion) {
-        if (!mCentralSurfaces.isPresent()) {
-            return;
-        }
-
-        // Don't set expansion if the user doesn't have a pin/password set.
-        if (!mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
-            return;
-        }
-
-        // The animation utils deal in pixel units, rather than expansion height.
-        final float viewHeight = mTouchSession.getBounds().height();
-        final float currentHeight = viewHeight * mCurrentExpansion;
-        final float targetHeight = viewHeight * expansion;
-        final float expansionHeight = targetHeight - currentHeight;
-        final ValueAnimator animator = createExpansionAnimator(expansion, expansionHeight);
-        if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
-            // Hides the bouncer, i.e., fully expands the space above the bouncer.
-            mFlingAnimationUtilsClosing.apply(animator, currentHeight, targetHeight, velocity,
-                    viewHeight);
-        } else {
-            // Shows the bouncer, i.e., fully collapses the space above the bouncer.
-            mFlingAnimationUtils.apply(
-                    animator, currentHeight, targetHeight, velocity, viewHeight);
-        }
-
-        animator.start();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java
index 13588c2..fff0c58 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.dreams.touch;
 
-import static com.android.systemui.dreams.touch.dagger.ShadeModule.COMMUNAL_GESTURE_INITIATION_WIDTH;
 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
 import android.graphics.Rect;
@@ -27,7 +26,9 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.Lifecycle;
 
+import com.android.systemui.ambient.touch.TouchHandler;
 import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.dreams.touch.dagger.CommunalTouchModule;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 
 import java.util.Optional;
@@ -36,8 +37,8 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
-/** {@link DreamTouchHandler} responsible for handling touches to open communal hub. **/
-public class CommunalTouchHandler implements DreamTouchHandler {
+/** {@link TouchHandler} responsible for handling touches to open communal hub. **/
+public class CommunalTouchHandler implements TouchHandler {
     private final int mInitiationWidth;
     private final Optional<CentralSurfaces> mCentralSurfaces;
     private final Lifecycle mLifecycle;
@@ -53,7 +54,7 @@
     @Inject
     public CommunalTouchHandler(
             Optional<CentralSurfaces> centralSurfaces,
-            @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth,
+            @Named(CommunalTouchModule.COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth,
             CommunalInteractor communalInteractor,
             Lifecycle lifecycle) {
         mInitiationWidth = initiationWidth;
@@ -97,7 +98,7 @@
         // Notification shade window has its own logic to be visible if the hub is open, no need to
         // do anything here other than send touch events over.
         session.registerInputListener(ev -> {
-            surfaces.handleDreamTouch((MotionEvent) ev);
+            surfaces.handleExternalShadeWindowTouch((MotionEvent) ev);
             if (ev != null && ((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) {
                 var unused = session.pop();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java
deleted file mode 100644
index 3b22b31..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java
+++ /dev/null
@@ -1,524 +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.dreams.touch;
-
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import static com.android.systemui.shared.Flags.bouncerAreaExclusion;
-
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.ISystemGestureExclusionListener;
-import android.view.IWindowManager;
-import android.view.InputEvent;
-import android.view.MotionEvent;
-
-import androidx.annotation.NonNull;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-import androidx.lifecycle.DefaultLifecycleObserver;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.DisplayId;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dreams.touch.dagger.InputSessionComponent;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.util.display.DisplayHelper;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import javax.inject.Inject;
-
-/**
- * {@link DreamOverlayTouchMonitor} is responsible for monitoring touches and gestures over the
- * dream overlay and redirecting them to a set of listeners. This monitor is in charge of figuring
- * out when listeners are eligible for receiving touches and filtering the listener pool if
- * touches are consumed.
- */
-public class DreamOverlayTouchMonitor {
-    // This executor is used to protect {@code mActiveTouchSessions} from being modified
-    // concurrently. Any operation that adds or removes values should use this executor.
-    public String TAG = "DreamOverlayTouchMonitor";
-    private final Executor mMainExecutor;
-    private final Executor mBackgroundExecutor;
-    private final Lifecycle mLifecycle;
-    private Rect mExclusionRect = null;
-
-    private ISystemGestureExclusionListener mGestureExclusionListener =
-            new ISystemGestureExclusionListener.Stub() {
-                @Override
-                public void onSystemGestureExclusionChanged(int displayId,
-                        Region systemGestureExclusion,
-                        Region systemGestureExclusionUnrestricted) {
-                    mExclusionRect = systemGestureExclusion.getBounds();
-                }
-            };
-
-
-
-    /**
-     * Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures.
-     */
-    private ListenableFuture<DreamTouchHandler.TouchSession> push(
-            TouchSessionImpl touchSessionImpl) {
-        return CallbackToFutureAdapter.getFuture(completer -> {
-            mMainExecutor.execute(() -> {
-                if (!mActiveTouchSessions.remove(touchSessionImpl)) {
-                    completer.set(null);
-                    return;
-                }
-
-                final TouchSessionImpl touchSession =
-                        new TouchSessionImpl(this, touchSessionImpl.getBounds(),
-                                touchSessionImpl);
-                mActiveTouchSessions.add(touchSession);
-                completer.set(touchSession);
-            });
-
-            return "DreamOverlayTouchMonitor::push";
-        });
-    }
-
-    /**
-     * Removes a {@link TouchSessionImpl} from receiving further updates.
-     */
-    private ListenableFuture<DreamTouchHandler.TouchSession> pop(
-            TouchSessionImpl touchSessionImpl) {
-        return CallbackToFutureAdapter.getFuture(completer -> {
-            mMainExecutor.execute(() -> {
-                if (mActiveTouchSessions.remove(touchSessionImpl)) {
-                    touchSessionImpl.onRemoved();
-
-                    final TouchSessionImpl predecessor = touchSessionImpl.getPredecessor();
-
-                    if (predecessor != null) {
-                        mActiveTouchSessions.add(predecessor);
-                    }
-
-                    completer.set(predecessor);
-                }
-
-                if (mActiveTouchSessions.isEmpty() && mStopMonitoringPending) {
-                    stopMonitoring(false);
-                }
-            });
-
-            return "DreamOverlayTouchMonitor::pop";
-        });
-    }
-
-    private int getSessionCount() {
-        return mActiveTouchSessions.size();
-    }
-
-    /**
-     * {@link TouchSessionImpl} implements {@link DreamTouchHandler.TouchSession} for
-     * {@link DreamOverlayTouchMonitor}. It enables the monitor to access the associated listeners
-     * and provides the associated client with access to the monitor.
-     */
-    private static class TouchSessionImpl implements DreamTouchHandler.TouchSession {
-        private final HashSet<InputChannelCompat.InputEventListener> mEventListeners =
-                new HashSet<>();
-        private final HashSet<GestureDetector.OnGestureListener> mGestureListeners =
-                new HashSet<>();
-        private final HashSet<Callback> mCallbacks = new HashSet<>();
-
-        private final TouchSessionImpl mPredecessor;
-        private final DreamOverlayTouchMonitor mTouchMonitor;
-        private final Rect mBounds;
-
-        TouchSessionImpl(DreamOverlayTouchMonitor touchMonitor, Rect bounds,
-                TouchSessionImpl predecessor) {
-            mPredecessor = predecessor;
-            mTouchMonitor = touchMonitor;
-            mBounds = bounds;
-        }
-
-        @Override
-        public void registerCallback(Callback callback) {
-            mCallbacks.add(callback);
-        }
-
-        @Override
-        public boolean registerInputListener(
-                InputChannelCompat.InputEventListener inputEventListener) {
-            return mEventListeners.add(inputEventListener);
-        }
-
-        @Override
-        public boolean registerGestureListener(GestureDetector.OnGestureListener gestureListener) {
-            return mGestureListeners.add(gestureListener);
-        }
-
-        @Override
-        public ListenableFuture<DreamTouchHandler.TouchSession> push() {
-            return mTouchMonitor.push(this);
-        }
-
-        @Override
-        public ListenableFuture<DreamTouchHandler.TouchSession> pop() {
-            return mTouchMonitor.pop(this);
-        }
-
-        @Override
-        public int getActiveSessionCount() {
-            return mTouchMonitor.getSessionCount();
-        }
-
-        /**
-         * Returns the active listeners to receive touch events.
-         */
-        public Collection<InputChannelCompat.InputEventListener> getEventListeners() {
-            return mEventListeners;
-        }
-
-        /**
-         * Returns the active listeners to receive gesture events.
-         */
-        public Collection<GestureDetector.OnGestureListener> getGestureListeners() {
-            return mGestureListeners;
-        }
-
-        /**
-         * Returns the {@link TouchSessionImpl} that preceded this current session. This will
-         * become the new active session when this session is popped.
-         */
-        private TouchSessionImpl getPredecessor() {
-            return mPredecessor;
-        }
-
-        /**
-         * Called by the monitor when this session is removed.
-         */
-        private void onRemoved() {
-            mEventListeners.clear();
-            mGestureListeners.clear();
-            final Iterator<Callback> iter = mCallbacks.iterator();
-            while (iter.hasNext()) {
-                final Callback callback = iter.next();
-                callback.onRemoved();
-                iter.remove();
-            }
-        }
-
-        @Override
-        public Rect getBounds() {
-            return mBounds;
-        }
-    }
-
-    /**
-     * This lifecycle observer ensures touch monitoring only occurs while the overlay is "resumed".
-     * This concept is mapped over from the equivalent view definition: The {@link LifecycleOwner}
-     * will report the dream is not resumed when it is obscured (from the notification shade being
-     * expanded for example) or not active (such as when it is destroyed).
-     */
-    private final LifecycleObserver mLifecycleObserver = new DefaultLifecycleObserver() {
-        @Override
-        public void onResume(@NonNull LifecycleOwner owner) {
-            startMonitoring();
-        }
-
-        @Override
-        public void onPause(@NonNull LifecycleOwner owner) {
-            stopMonitoring(false);
-        }
-
-        @Override
-        public void onDestroy(LifecycleOwner owner) {
-            stopMonitoring(true);
-        }
-    };
-
-    /**
-     * When invoked, instantiates a new {@link InputSession} to monitor touch events.
-     */
-    private void startMonitoring() {
-        stopMonitoring(true);
-        if (bouncerAreaExclusion()) {
-            mBackgroundExecutor.execute(() -> {
-                try {
-                    mWindowManagerService.registerSystemGestureExclusionListener(
-                            mGestureExclusionListener, mDisplayId);
-                } catch (RemoteException e) {
-                    // Handle the exception
-                    Log.e(TAG, "Failed to register gesture exclusion listener", e);
-                }
-            });
-        }
-        mCurrentInputSession = mInputSessionFactory.create(
-                "dreamOverlay",
-                mInputEventListener,
-                mOnGestureListener,
-                true)
-                .getInputSession();
-    }
-
-    /**
-     * Destroys any active {@link InputSession}.
-     */
-    private void stopMonitoring(boolean force) {
-        mExclusionRect = null;
-        if (bouncerAreaExclusion()) {
-            mBackgroundExecutor.execute(() -> {
-                try {
-                    mWindowManagerService.unregisterSystemGestureExclusionListener(
-                            mGestureExclusionListener, mDisplayId);
-                } catch (RemoteException e) {
-                    // Handle the exception
-                    Log.e(TAG, "unregisterSystemGestureExclusionListener: failed", e);
-                }
-            });
-        }
-        if (mCurrentInputSession == null) {
-            return;
-        }
-
-        if (!mActiveTouchSessions.isEmpty() && !force) {
-            mStopMonitoringPending = true;
-            return;
-        }
-
-        // When we stop monitoring touches, we must ensure that all active touch sessions and
-        // descendants informed of the removal so any cleanup for active tracking can proceed.
-        mMainExecutor.execute(() -> mActiveTouchSessions.forEach(touchSession -> {
-            while (touchSession != null) {
-                touchSession.onRemoved();
-                touchSession = touchSession.getPredecessor();
-            }
-        }));
-
-        mCurrentInputSession.dispose();
-        mCurrentInputSession = null;
-        mStopMonitoringPending = false;
-    }
-
-
-    private final HashSet<TouchSessionImpl> mActiveTouchSessions = new HashSet<>();
-    private final Collection<DreamTouchHandler> mHandlers;
-    private final DisplayHelper mDisplayHelper;
-
-    private boolean mStopMonitoringPending;
-
-    private InputChannelCompat.InputEventListener mInputEventListener =
-            new InputChannelCompat.InputEventListener() {
-        @Override
-        public void onInputEvent(InputEvent ev) {
-            // No Active sessions are receiving touches. Create sessions for each listener
-            if (mActiveTouchSessions.isEmpty()) {
-                final HashMap<DreamTouchHandler, DreamTouchHandler.TouchSession> sessionMap =
-                        new HashMap<>();
-
-                for (DreamTouchHandler handler : mHandlers) {
-                            if (!handler.isEnabled()) {
-                                continue;
-                            }
-                            final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(),
-                                    TYPE_APPLICATION_OVERLAY);
-                            final Region initiationRegion = Region.obtain();
-                            Rect exclusionRect = null;
-                            if (bouncerAreaExclusion()) {
-                                exclusionRect = getCurrentExclusionRect();
-                            }
-                            handler.getTouchInitiationRegion(
-                                            maxBounds, initiationRegion, exclusionRect);
-
-                    if (!initiationRegion.isEmpty()) {
-                        // Initiation regions require a motion event to determine pointer location
-                        // within the region.
-                        if (!(ev instanceof MotionEvent)) {
-                            continue;
-                        }
-
-                        final MotionEvent motionEvent = (MotionEvent) ev;
-
-                        // If the touch event is outside the region, then ignore.
-                        if (!initiationRegion.contains(Math.round(motionEvent.getX()),
-                                Math.round(motionEvent.getY()))) {
-                            continue;
-                        }
-                    }
-
-                    final TouchSessionImpl sessionStack = new TouchSessionImpl(
-                            DreamOverlayTouchMonitor.this, maxBounds, null);
-                    mActiveTouchSessions.add(sessionStack);
-                    sessionMap.put(handler, sessionStack);
-                }
-
-                // Informing handlers of new sessions is delayed until we have all created so the
-                // final session is correct.
-                sessionMap.forEach((dreamTouchHandler, touchSession)
-                        -> dreamTouchHandler.onSessionStart(touchSession));
-            }
-
-            // Find active sessions and invoke on InputEvent.
-            mActiveTouchSessions.stream()
-                    .map(touchSessionStack -> touchSessionStack.getEventListeners())
-                    .flatMap(Collection::stream)
-                    .forEach(inputEventListener -> inputEventListener.onInputEvent(ev));
-        }
-                    private Rect getCurrentExclusionRect() {
-                        return mExclusionRect;
-                    }
-    };
-
-    /**
-     * The {@link Evaluator} interface allows for callers to inspect a listener from the
-     * {@link android.view.GestureDetector.OnGestureListener} set. This helps reduce duplicated
-     * iteration loops over this set.
-     */
-    private interface Evaluator {
-        boolean evaluate(GestureDetector.OnGestureListener listener);
-    }
-
-    private GestureDetector.OnGestureListener mOnGestureListener =
-            new GestureDetector.OnGestureListener() {
-        private boolean evaluate(Evaluator evaluator) {
-            final Set<TouchSessionImpl> consumingSessions = new HashSet<>();
-
-            // When a gesture is consumed, it is assumed that all touches for the current session
-            // should be directed only to those TouchSessions until those sessions are popped. All
-            // non-participating sessions are removed from receiving further updates with
-            // {@link DreamOverlayTouchMonitor#isolate}.
-            final boolean eventConsumed = mActiveTouchSessions.stream()
-                    .map(touchSession -> {
-                        boolean consume = touchSession.getGestureListeners()
-                                .stream()
-                                .map(listener -> evaluator.evaluate(listener))
-                                .anyMatch(consumed -> consumed);
-
-                        if (consume) {
-                            consumingSessions.add(touchSession);
-                        }
-                        return consume;
-                    }).anyMatch(consumed -> consumed);
-
-            if (eventConsumed) {
-                DreamOverlayTouchMonitor.this.isolate(consumingSessions);
-            }
-
-            return eventConsumed;
-        }
-
-        // This method is called for gesture events that cannot be consumed.
-        private void observe(Consumer<GestureDetector.OnGestureListener> consumer) {
-            mActiveTouchSessions.stream()
-                    .map(touchSession -> touchSession.getGestureListeners())
-                    .flatMap(Collection::stream)
-                    .forEach(listener -> consumer.accept(listener));
-        }
-
-        @Override
-        public boolean onDown(MotionEvent e) {
-            return evaluate(listener -> listener.onDown(e));
-        }
-
-        @Override
-        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-            return evaluate(listener -> listener.onFling(e1, e2, velocityX, velocityY));
-        }
-
-        @Override
-        public void onLongPress(MotionEvent e) {
-            observe(listener -> listener.onLongPress(e));
-        }
-
-        @Override
-        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-            return evaluate(listener -> listener.onScroll(e1, e2, distanceX, distanceY));
-        }
-
-        @Override
-        public void onShowPress(MotionEvent e) {
-            observe(listener -> listener.onShowPress(e));
-        }
-
-        @Override
-        public boolean onSingleTapUp(MotionEvent e) {
-            return evaluate(listener -> listener.onSingleTapUp(e));
-        }
-    };
-
-    private InputSessionComponent.Factory mInputSessionFactory;
-    private InputSession mCurrentInputSession;
-    private final int mDisplayId;
-    private final IWindowManager mWindowManagerService;
-
-
-    /**
-     * Designated constructor for {@link DreamOverlayTouchMonitor}
-     * @param executor This executor will be used for maintaining the active listener list to avoid
-     *                 concurrent modification.
-     * @param lifecycle {@link DreamOverlayTouchMonitor} will listen to this lifecycle to determine
-     *                                                  whether touch monitoring should be active.
-     * @param inputSessionFactory This factory will generate the {@link InputSession} requested by
-     *                            the monitor. Each session should be unique and valid when
-     *                            returned.
-     * @param handlers This set represents the {@link DreamTouchHandler} instances that will
-     *                 participate in touch handling.
-     */
-    @Inject
-    public DreamOverlayTouchMonitor(
-            @Main Executor executor,
-            @Background Executor backgroundExecutor,
-            Lifecycle lifecycle,
-            InputSessionComponent.Factory inputSessionFactory,
-            DisplayHelper displayHelper,
-            Set<DreamTouchHandler> handlers,
-            IWindowManager windowManagerService,
-            @DisplayId int displayId) {
-        mDisplayId = displayId;
-        mHandlers = handlers;
-        mInputSessionFactory = inputSessionFactory;
-        mMainExecutor = executor;
-        mBackgroundExecutor = backgroundExecutor;
-        mLifecycle = lifecycle;
-        mDisplayHelper = displayHelper;
-        mWindowManagerService = windowManagerService;
-    }
-
-    /**
-     * Initializes the monitor. should only be called once after creation.
-     */
-    public void init() {
-        mLifecycle.addObserver(mLifecycleObserver);
-    }
-
-    private void isolate(Set<TouchSessionImpl> sessions) {
-        Collection<TouchSessionImpl> removedSessions = mActiveTouchSessions.stream()
-                .filter(touchSession -> !sessions.contains(touchSession))
-                .collect(Collectors.toCollection(HashSet::new));
-
-        removedSessions.forEach(touchSession -> touchSession.onRemoved());
-
-        mActiveTouchSessions.removeAll(removedSessions);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java
deleted file mode 100644
index 1ec0008..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java
+++ /dev/null
@@ -1,119 +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.dreams.touch;
-
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.view.GestureDetector;
-
-import com.android.systemui.shared.system.InputChannelCompat;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * The {@link DreamTouchHandler} interface provides a way for dream overlay components to observe
- * touch events and gestures with the ability to intercept the latter. Touch interaction sequences
- * are abstracted as sessions. A session represents the time of first
- * {@code android.view.MotionEvent.ACTION_DOWN} event to the last {@link DreamTouchHandler}
- * stopping interception of gestures. If no gesture is intercepted, the session continues
- * indefinitely. {@link DreamTouchHandler} have the ability to create a stack of sessions, which
- * allows for motion logic to be captured in modal states.
- */
-public interface DreamTouchHandler {
-    /**
-     * A touch session captures the interaction surface of a {@link DreamTouchHandler}. Clients
-     * register listeners as desired to participate in motion/gesture callbacks.
-     */
-    interface TouchSession {
-        interface Callback {
-            void onRemoved();
-        }
-
-        void registerCallback(Callback callback);
-
-        /**
-         * Adds a input event listener for the given session.
-         * @param inputEventListener
-         */
-        boolean registerInputListener(InputChannelCompat.InputEventListener inputEventListener);
-
-        /**
-         * Adds a gesture listener for the given session.
-         * @param gestureListener
-         */
-        boolean registerGestureListener(GestureDetector.OnGestureListener gestureListener);
-
-        /**
-         * Creates a new {@link TouchSession} that will receive any updates that would have been
-         * directed to this {@link TouchSession}.
-         * @return The future which will return a new {@link TouchSession} that will receive
-         * subsequent events. If the operation fails, {@code null} will be returned.
-         */
-        ListenableFuture<TouchSession> push();
-
-        /**
-         * Explicitly releases this {@link TouchSession}. The registered listeners will no longer
-         * receive any further updates.
-         * @return The future containing the {@link TouchSession} that will receive subsequent
-         * events. This session will be the direct predecessor of the popped session. {@code null}
-         * if the popped {@link TouchSession} was the initial session or has already been popped.
-         */
-        ListenableFuture<TouchSession> pop();
-
-        /**
-         * Returns the number of currently active sessions.
-         */
-        int getActiveSessionCount();
-
-        /**
-         * Returns the bounds of the display the touch region.
-         */
-        Rect getBounds();
-    }
-
-    /**
-     * Returns whether the handler is enabled to handle touch on dream.
-     * @return isEnabled state. By default it's true.
-     */
-    default Boolean isEnabled() {
-        return true;
-    }
-
-    /**
-     * Sets whether to enable the handler to handle touch on dream.
-     * @param enabled new value to be set whether to enable the handler.
-     */
-    default void setIsEnabled(Boolean enabled){}
-
-    /**
-     * Returns the region the touch handler is interested in. By default, no region is specified,
-     * indicating the entire screen should be considered.
-     * @param region A {@link Region} that is passed in to the target entry touch region.
-     */
-    default void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
-    }
-
-    /**
-     * Informed a new touch session has begun. The first touch event will be delivered to any
-     * listener registered through
-     * {@link TouchSession#registerInputListener(InputChannelCompat.InputEventListener)} during this
-     * call. If there are no interactions with this touch session after this method returns, it will
-     * be dropped.
-     * @param session
-     */
-    void onSessionStart(TouchSession session);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/InputSession.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/InputSession.java
deleted file mode 100644
index e1d0339..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/InputSession.java
+++ /dev/null
@@ -1,91 +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.dreams.touch;
-
-import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.INPUT_SESSION_NAME;
-import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.PILFER_ON_GESTURE_CONSUME;
-
-import android.os.Looper;
-import android.view.Choreographer;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-
-import com.android.systemui.settings.DisplayTracker;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.shared.system.InputMonitorCompat;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * {@link InputSession} encapsulates components behind input monitoring and handles their lifecycle.
- * Sessions are meant to be disposable; actions such as exclusively capturing touch events is modal
- * and destroying the sessions allows a reset. Additionally, {@link InputSession} is meant to have
- * a single listener for input and gesture. Any broadcasting must be accomplished elsewhere.
- */
-public class InputSession {
-    private final InputMonitorCompat mInputMonitor;
-    private final InputChannelCompat.InputEventReceiver mInputEventReceiver;
-    private final GestureDetector mGestureDetector;
-
-    /**
-     * Default session constructor.
-     * @param sessionName The session name that will be applied to the underlying
-     * {@link InputMonitorCompat}.
-     * @param inputEventListener A listener to receive input events.
-     * @param gestureListener A listener to receive gesture events.
-     * @param pilferOnGestureConsume Whether touch events should be pilfered after a gesture has
-     *                               been consumed.
-     */
-    @Inject
-    public InputSession(@Named(INPUT_SESSION_NAME) String sessionName,
-            InputChannelCompat.InputEventListener inputEventListener,
-            GestureDetector.OnGestureListener gestureListener,
-            DisplayTracker displayTracker,
-            @Named(PILFER_ON_GESTURE_CONSUME) boolean pilferOnGestureConsume) {
-        mInputMonitor = new InputMonitorCompat(sessionName, displayTracker.getDefaultDisplayId());
-        mGestureDetector = new GestureDetector(gestureListener);
-
-        mInputEventReceiver = mInputMonitor.getInputReceiver(Looper.getMainLooper(),
-                Choreographer.getInstance(),
-                ev -> {
-                    // Process event. Since sometimes input may be a prerequisite for some
-                    // gesture logic, process input first.
-                    inputEventListener.onInputEvent(ev);
-
-                    if (ev instanceof MotionEvent
-                            && mGestureDetector.onTouchEvent((MotionEvent) ev)
-                            && pilferOnGestureConsume) {
-                        mInputMonitor.pilferPointers();
-                    }
-                });
-    }
-
-    /**
-     * Destroys the {@link InputSession}, removing any component from listening to future touch
-     * events.
-     */
-    public void dispose() {
-        if (mInputEventReceiver != null) {
-            mInputEventReceiver.dispose();
-        }
-
-        if (mInputMonitor != null) {
-            mInputMonitor.dispose();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/ShadeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/ShadeTouchHandler.java
deleted file mode 100644
index e0bf52e..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/ShadeTouchHandler.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.systemui.dreams.touch;
-
-import static com.android.systemui.dreams.touch.dagger.ShadeModule.NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT;
-
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-
-import com.android.systemui.shade.ShadeViewController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-
-import java.util.Optional;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * {@link ShadeTouchHandler} is responsible for handling swipe down gestures over dream
- * to bring down the shade.
- */
-public class ShadeTouchHandler implements DreamTouchHandler {
-    private final Optional<CentralSurfaces> mSurfaces;
-    private final ShadeViewController mShadeViewController;
-    private final int mInitiationHeight;
-
-    @Inject
-    ShadeTouchHandler(Optional<CentralSurfaces> centralSurfaces,
-            ShadeViewController shadeViewController,
-            @Named(NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT) int initiationHeight) {
-        mSurfaces = centralSurfaces;
-        mShadeViewController = shadeViewController;
-        mInitiationHeight = initiationHeight;
-    }
-
-    @Override
-    public void onSessionStart(TouchSession session) {
-        if (mSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) {
-            session.pop();
-            return;
-        }
-
-        session.registerInputListener(ev -> {
-            mShadeViewController.handleExternalTouch((MotionEvent) ev);
-
-            if (ev instanceof MotionEvent) {
-                if (((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) {
-                    session.pop();
-                }
-            }
-        });
-
-        session.registerGestureListener(new GestureDetector.SimpleOnGestureListener() {
-            @Override
-            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
-                    float distanceY) {
-                return true;
-            }
-
-            @Override
-            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
-                    float velocityY) {
-                return true;
-            }
-        });
-    }
-
-    @Override
-    public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
-        final Rect outBounds = new Rect(bounds);
-        outBounds.inset(0, 0, 0, outBounds.height() - mInitiationHeight);
-        region.op(outBounds, Region.Op.UNION);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
deleted file mode 100644
index a5db2ff..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
+++ /dev/null
@@ -1,144 +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.dreams.touch.dagger;
-
-import android.animation.ValueAnimator;
-import android.content.res.Resources;
-import android.util.TypedValue;
-import android.view.VelocityTracker;
-
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dreams.touch.BouncerSwipeTouchHandler;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
-import com.android.systemui.res.R;
-import com.android.systemui.shade.ShadeViewController;
-import com.android.wm.shell.animation.FlingAnimationUtils;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.multibindings.IntoSet;
-
-import javax.inject.Named;
-import javax.inject.Provider;
-
-/**
- * This module captures the components associated with {@link BouncerSwipeTouchHandler}.
- */
-@Module
-public class BouncerSwipeModule {
-    /**
-     * The region, defined as the percentage of the screen, from which a touch gesture to start
-     * swiping up to the bouncer can occur.
-     */
-    public static final String SWIPE_TO_BOUNCER_START_REGION = "swipe_to_bouncer_start_region";
-
-    public static final String MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE =
-            "min_bouncer_zone_screen_percentage";
-
-    /**
-     * The {@link android.view.animation.AnimationUtils} for animating the bouncer closing.
-     */
-    public static final String SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING =
-            "swipe_to_bouncer_fling_animation_utils_closing";
-
-    /**
-     * The {@link android.view.animation.AnimationUtils} for animating the bouncer opening.
-     */
-    public static final String SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING =
-                    "swipe_to_bouncer_fling_animation_utils_opening";
-
-    /**
-     * Provides {@link BouncerSwipeTouchHandler} for inclusion in touch handling over the dream.
-     */
-    @Provides
-    @IntoSet
-    public static DreamTouchHandler providesBouncerSwipeTouchHandler(
-            BouncerSwipeTouchHandler touchHandler) {
-        return touchHandler;
-    }
-
-    /**
-     * Provides {@link android.view.animation.AnimationUtils} for closing.
-     */
-    @Provides
-    @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
-    public static FlingAnimationUtils providesSwipeToBouncerFlingAnimationUtilsClosing(
-            Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
-        return flingAnimationUtilsBuilderProvider.get()
-                .reset()
-                .setMaxLengthSeconds(
-                        ShadeViewController.FLING_CLOSING_MAX_LENGTH_SECONDS)
-                .setSpeedUpFactor(ShadeViewController.FLING_SPEED_UP_FACTOR)
-                .build();
-    }
-
-    /**
-     * Provides {@link android.view.animation.AnimationUtils} for opening.
-     */
-    @Provides
-    @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
-    public static FlingAnimationUtils providesSwipeToBouncerFlingAnimationUtilsOpening(
-            Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
-        return flingAnimationUtilsBuilderProvider.get()
-                .reset()
-                .setMaxLengthSeconds(ShadeViewController.FLING_MAX_LENGTH_SECONDS)
-                .setSpeedUpFactor(ShadeViewController.FLING_SPEED_UP_FACTOR)
-                .build();
-    }
-
-    /**
-     * Provides the region to start swipe gestures from.
-     */
-    @Provides
-    @Named(SWIPE_TO_BOUNCER_START_REGION)
-    public static float providesSwipeToBouncerStartRegion(@Main Resources resources) {
-        TypedValue typedValue = new TypedValue();
-        resources.getValue(R.dimen.dream_overlay_bouncer_start_region_screen_percentage,
-                typedValue, true);
-        return typedValue.getFloat();
-    }
-
-    /**
-     * Provides the minimum region to start wipe gestures from.
-     */
-    @Provides
-    @Named(MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE)
-    public static float providesMinBouncerZoneScreenPercentage(@Main Resources resources) {
-        TypedValue typedValue = new TypedValue();
-        resources.getValue(R.dimen.dream_overlay_bouncer_min_region_screen_percentage,
-                typedValue, true);
-        return typedValue.getFloat();
-    }
-
-    /**
-     * Provides the default {@link BouncerSwipeTouchHandler.ValueAnimatorCreator}, which is simply
-     * a wrapper around {@link ValueAnimator}.
-     */
-    @Provides
-    public static BouncerSwipeTouchHandler.ValueAnimatorCreator providesValueAnimatorCreator() {
-        return (start, finish) -> ValueAnimator.ofFloat(start, finish);
-    }
-
-    /**
-     * Provides the default {@link BouncerSwipeTouchHandler.VelocityTrackerFactory}. which is a
-     * passthrough to {@link android.view.VelocityTracker}.
-     */
-    @Provides
-    public static BouncerSwipeTouchHandler.VelocityTrackerFactory providesVelocityTrackerFactory() {
-        return () -> VelocityTracker.obtain();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/CommunalTouchModule.kt b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/CommunalTouchModule.kt
new file mode 100644
index 0000000..927ea4ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/CommunalTouchModule.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.dreams.touch.dagger
+
+import android.content.res.Resources
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
+import dagger.Module
+import dagger.Provides
+import javax.inject.Named
+
+@Module
+interface CommunalTouchModule {
+    companion object {
+        /** Provides the width of the gesture area for swiping open communal hub. */
+        @JvmStatic
+        @Provides
+        @Named(COMMUNAL_GESTURE_INITIATION_WIDTH)
+        fun providesCommunalGestureInitiationWidth(@Main resources: Resources): Int {
+            return resources.getDimensionPixelSize(R.dimen.communal_gesture_initiation_width)
+        }
+
+        /** Width of swipe gesture edge to show communal hub. */
+        const val COMMUNAL_GESTURE_INITIATION_WIDTH = "communal_gesture_initiation_width"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java
deleted file mode 100644
index b719126..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java
+++ /dev/null
@@ -1,33 +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.dreams.touch.dagger;
-
-import dagger.Module;
-
-/**
- * {@link DreamTouchModule} encapsulates dream touch-related components.
- */
-@Module(includes = {
-            BouncerSwipeModule.class,
-            ShadeModule.class,
-        }, subcomponents = {
-            InputSessionComponent.class,
-})
-public interface DreamTouchModule {
-    String INPUT_SESSION_NAME = "INPUT_SESSION_NAME";
-    String PILFER_ON_GESTURE_CONSUME = "PILFER_ON_GESTURE_CONSUME";
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/InputSessionComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/InputSessionComponent.java
deleted file mode 100644
index ad59a2e..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/InputSessionComponent.java
+++ /dev/null
@@ -1,51 +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.dreams.touch.dagger;
-
-import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.INPUT_SESSION_NAME;
-import static com.android.systemui.dreams.touch.dagger.DreamTouchModule.PILFER_ON_GESTURE_CONSUME;
-
-import android.view.GestureDetector;
-
-import com.android.systemui.dreams.touch.InputSession;
-import com.android.systemui.shared.system.InputChannelCompat;
-
-import javax.inject.Named;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * {@link InputSessionComponent} generates {@link InputSession} with specific instances bound for
- * the session name and whether touches should be pilfered when consumed.
- */
-@Subcomponent
-public interface InputSessionComponent {
-    /**
-     * Generates {@link InputSessionComponent}.
-     */
-    @Subcomponent.Factory
-    interface Factory {
-        InputSessionComponent create(@Named(INPUT_SESSION_NAME) @BindsInstance String name,
-                @BindsInstance InputChannelCompat.InputEventListener inputEventListener,
-                @BindsInstance GestureDetector.OnGestureListener gestureListener,
-                @Named(PILFER_ON_GESTURE_CONSUME) @BindsInstance boolean pilferOnGestureConsume);
-    }
-
-    /** */
-    InputSession getInputSession();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/ShadeModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/ShadeModule.java
deleted file mode 100644
index 0f08d37..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/ShadeModule.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.systemui.dreams.touch.dagger;
-
-import android.content.res.Resources;
-
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dreams.touch.CommunalTouchHandler;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
-import com.android.systemui.dreams.touch.ShadeTouchHandler;
-import com.android.systemui.res.R;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-import dagger.multibindings.IntoSet;
-
-import javax.inject.Named;
-
-/**
- * Dependencies for swipe down to notification over dream.
- */
-@Module
-public abstract class ShadeModule {
-    /**
-     * The height, defined in pixels, of the gesture initiation region at the top of the screen for
-     * swiping down notifications.
-     */
-    public static final String NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT =
-            "notification_shade_gesture_initiation_height";
-
-    /** Width of swipe gesture edge to show communal hub. */
-    public static final String COMMUNAL_GESTURE_INITIATION_WIDTH =
-            "communal_gesture_initiation_width";
-
-    /**
-     * Provides {@link ShadeTouchHandler} to handle notification swipe down over dream.
-     */
-    @Binds
-    @IntoSet
-    public abstract DreamTouchHandler providesNotificationShadeTouchHandler(
-            ShadeTouchHandler touchHandler);
-
-    /** Provides {@link CommunalTouchHandler}. */
-    @Binds
-    @IntoSet
-    public abstract DreamTouchHandler bindCommunalTouchHandler(CommunalTouchHandler touchHandler);
-
-    /**
-     * Provides the height of the gesture area for notification swipe down.
-     */
-    @Provides
-    @Named(NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT)
-    public static int providesNotificationShadeGestureRegionHeight(@Main Resources resources) {
-        return resources.getDimensionPixelSize(R.dimen.dream_overlay_status_bar_height);
-    }
-
-    /**
-     * Provides the width of the gesture area for swiping open communal hub.
-     */
-    @Provides
-    @Named(COMMUNAL_GESTURE_INITIATION_WIDTH)
-    public static int providesCommunalGestureInitiationWidth(@Main Resources resources) {
-        return resources.getDimensionPixelSize(R.dimen.communal_gesture_initiation_width);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
deleted file mode 100644
index 776b7bd..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim;
-
-import com.android.systemui.shade.ShadeExpansionChangeEvent;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-
-import javax.inject.Inject;
-
-/**
- * Implementation for handling swipe movements on the overlay when the keyguard is present.
- */
-public class BouncerScrimController implements ScrimController {
-    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-
-    @Inject
-    BouncerScrimController(StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
-        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
-    }
-
-    @Override
-    public void show() {
-        mStatusBarKeyguardViewManager.showPrimaryBouncer(false);
-    }
-
-    @Override
-    public void expand(ShadeExpansionChangeEvent event) {
-        mStatusBarKeyguardViewManager.onPanelExpansionChanged(event);
-    }
-
-    @Override
-    public void reset() {
-        mStatusBarKeyguardViewManager.reset(false);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimController.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimController.java
deleted file mode 100644
index 01e4d04..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimController.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim;
-
-import android.os.PowerManager;
-import android.os.SystemClock;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.shade.ShadeExpansionChangeEvent;
-import com.android.systemui.unfold.util.CallbackController;
-
-import java.util.HashSet;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-
-/**
- * {@link BouncerlessScrimController} handles scrim progression when no keyguard is set. When
- * fully expanded, the controller dismisses the dream.
- */
-@SysUISingleton
-public class BouncerlessScrimController implements ScrimController,
-        CallbackController<BouncerlessScrimController.Callback> {
-    private static final String TAG = "BLScrimController";
-
-    /**
-     * {@link Callback} allows {@link BouncerlessScrimController} clients to be informed of
-     * expansion progression and wakeup
-     */
-    public interface Callback {
-        /**
-         * Invoked when there is a change to the scrim expansion.
-         */
-        void onExpansion(ShadeExpansionChangeEvent event);
-
-        /**
-         * Invoked after {@link BouncerlessScrimController} has started waking up the device.
-         */
-        void onWakeup();
-    }
-
-    private final Executor mExecutor;
-    private final PowerManager mPowerManager;
-
-    @Override
-    public void addCallback(Callback listener) {
-        mExecutor.execute(() -> mCallbacks.add(listener));
-    }
-
-    @Override
-    public void removeCallback(Callback listener) {
-        mExecutor.execute(() -> mCallbacks.remove(listener));
-    }
-
-    private final HashSet<Callback> mCallbacks;
-
-
-    @Inject
-    public BouncerlessScrimController(@Main Executor executor,
-            PowerManager powerManager) {
-        mExecutor = executor;
-        mPowerManager = powerManager;
-        mCallbacks = new HashSet<>();
-    }
-
-    @Override
-    public void expand(ShadeExpansionChangeEvent event) {
-        if (event.getExpanded())  {
-            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
-                    "com.android.systemui:SwipeUp");
-            mExecutor.execute(() -> mCallbacks.forEach(callback -> callback.onWakeup()));
-        } else {
-            mExecutor.execute(() -> mCallbacks.forEach(callback -> callback.onExpansion(event)));
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimController.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimController.java
deleted file mode 100644
index 61629ef..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimController.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim;
-
-import com.android.systemui.shade.ShadeExpansionChangeEvent;
-
-/**
- * {@link ScrimController} provides an interface for the different consumers of scrolling/expansion
- * events over the dream.
- */
-public interface ScrimController {
-    /**
-     * Called at the start of expansion before any expansion amount updates.
-     */
-    default void show() {
-    }
-
-    /**
-     * Called for every expansion update.
-     * @param event {@link ShadeExpansionChangeEvent} detailing the change.
-     */
-    default void expand(ShadeExpansionChangeEvent event) {
-    }
-
-    /**
-     * Called at the end of the movement.
-     */
-    default void reset() {
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimManager.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimManager.java
deleted file mode 100644
index 0d0dff6..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/ScrimManager.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim;
-
-import static com.android.systemui.dreams.touch.scrim.dagger.ScrimModule.BOUNCERLESS_SCRIM_CONTROLLER;
-import static com.android.systemui.dreams.touch.scrim.dagger.ScrimModule.BOUNCER_SCRIM_CONTROLLER;
-
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-
-import java.util.HashSet;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * {@link ScrimManager} helps manage multiple {@link ScrimController} instances, specifying the
- * appropriate one to use at the current moment and managing the handoff between controllers.
- */
-public class ScrimManager {
-    private final ScrimController mBouncerScrimController;
-    private final ScrimController mBouncerlessScrimController;
-    private final KeyguardStateController mKeyguardStateController;
-    private final Executor mExecutor;
-
-    private ScrimController mCurrentController;
-    private final HashSet<Callback> mCallbacks;
-
-    /**
-     * Interface implemented for receiving updates to the active {@link ScrimController}.
-     */
-    public interface Callback {
-        /**
-         * Invoked when the controller changes.
-         * @param controller The currently active {@link ScrimController}.
-         */
-        void onScrimControllerChanged(ScrimController controller);
-    }
-
-    private final KeyguardStateController.Callback mKeyguardStateCallback =
-            new KeyguardStateController.Callback() {
-                @Override
-                public void onKeyguardShowingChanged() {
-                    mExecutor.execute(() -> updateController());
-                }
-            };
-
-    @Inject
-    ScrimManager(@Main Executor executor,
-            @Named(BOUNCER_SCRIM_CONTROLLER) ScrimController bouncerScrimController,
-            @Named(BOUNCERLESS_SCRIM_CONTROLLER)ScrimController bouncerlessScrimController,
-            KeyguardStateController keyguardStateController) {
-        mExecutor = executor;
-        mCallbacks = new HashSet<>();
-        mBouncerlessScrimController = bouncerlessScrimController;
-        mBouncerScrimController = bouncerScrimController;
-        mKeyguardStateController = keyguardStateController;
-
-        mKeyguardStateController.addCallback(mKeyguardStateCallback);
-        updateController();
-    }
-
-    private void updateController() {
-        final ScrimController existingController = mCurrentController;
-        mCurrentController =  mKeyguardStateController.canDismissLockScreen()
-                ? mBouncerlessScrimController
-                : mBouncerScrimController;
-
-        if (existingController == mCurrentController) {
-            return;
-        }
-
-        mCallbacks.forEach(callback -> callback.onScrimControllerChanged(mCurrentController));
-    }
-
-    /**
-     * Adds a {@link Callback} to receive future changes to the active {@link ScrimController}.
-     */
-    public void addCallback(Callback callback) {
-        mExecutor.execute(() -> mCallbacks.add(callback));
-    }
-
-    /**
-     * Removes the {@link Callback} from receiving further updates.
-     */
-    public void removeCallback(Callback callback) {
-        mExecutor.execute(() -> mCallbacks.remove(callback));
-    }
-
-    /**
-     * Returns the currently get {@link ScrimController}.
-     * @return
-     */
-    public ScrimController getCurrentController() {
-        return mCurrentController;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/dagger/ScrimModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/dagger/ScrimModule.java
deleted file mode 100644
index 4ad5161..0000000
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/dagger/ScrimModule.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dreams.touch.scrim.dagger;
-
-import com.android.systemui.dreams.touch.scrim.BouncerScrimController;
-import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
-import com.android.systemui.dreams.touch.scrim.ScrimController;
-
-import dagger.Module;
-import dagger.Provides;
-
-import javax.inject.Named;
-
-/**
- * Module for scrim related dependencies.
- */
-@Module
-public interface ScrimModule {
-    String BOUNCERLESS_SCRIM_CONTROLLER = "bouncerless_scrim_controller";
-    String BOUNCER_SCRIM_CONTROLLER = "bouncer_scrim_controller";
-
-    /** */
-    @Provides
-    @Named(BOUNCERLESS_SCRIM_CONTROLLER)
-    static ScrimController providesBouncerlessScrimController(
-            BouncerlessScrimController controller) {
-        return controller;
-    }
-
-    /** */
-    @Provides
-    @Named(BOUNCER_SCRIM_CONTROLLER)
-    static ScrimController providesBouncerScrimController(
-            BouncerScrimController controller) {
-        return controller;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
index 037c23b..221f790 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
@@ -21,13 +21,16 @@
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.shared.model.CommunalScenes
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.kotlin.FlowDumperImpl
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
@@ -44,19 +47,19 @@
     configurationInteractor: ConfigurationInteractor,
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
     fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel,
-    private val toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
+    toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
     private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
     private val communalInteractor: CommunalInteractor,
     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
     private val userTracker: UserTracker,
-) {
+    dumpManager: DumpManager,
+) : FlowDumperImpl(dumpManager) {
 
     fun startTransitionFromDream() {
         val showGlanceableHub =
             communalInteractor.isCommunalEnabled.value &&
                 !keyguardUpdateMonitor.isEncryptedOrLockdown(userTracker.userId)
         if (showGlanceableHub) {
-            toGlanceableHubTransitionViewModel.startTransition()
             communalInteractor.changeScene(CommunalScenes.Communal)
         } else {
             toLockscreenTransitionViewModel.startTransition()
@@ -83,6 +86,7 @@
                 toGlanceableHubTransitionViewModel.dreamAlpha,
             )
             .distinctUntilChanged()
+            .dumpWhileCollecting("dreamAlpha")
 
     val dreamOverlayAlpha: Flow<Float> =
         merge(
@@ -93,7 +97,7 @@
             .distinctUntilChanged()
 
     val transitionEnded =
-        keyguardTransitionInteractor.fromDreamingTransition.filter { step ->
+        keyguardTransitionInteractor.transition(from = DREAMING).filter { step ->
             step.transitionState == TransitionState.FINISHED ||
                 step.transitionState == TransitionState.CANCELED
         }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 640534c..04f1ad2 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -153,11 +153,6 @@
     // TODO(b/267722622): Tracking Bug
     @JvmField val WALLPAPER_PICKER_UI_FOR_AIWP = releasedFlag("wallpaper_picker_ui_for_aiwp")
 
-    /** Whether to use a new data source for intents to run on keyguard dismissal. */
-    // TODO(b/275069969): Tracking bug.
-    @JvmField
-    val REFACTOR_KEYGUARD_DISMISS_INTENT = unreleasedFlag("refactor_keyguard_dismiss_intent")
-
     /** Whether to allow long-press on the lock screen to directly open wallpaper picker. */
     // TODO(b/277220285): Tracking bug.
     @JvmField
@@ -260,9 +255,6 @@
     val FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS =
         releasedFlag("filter_provisioning_network_subscriptions")
 
-    // TODO(b/292533677): Tracking Bug
-    val WIFI_TRACKER_LIB_FOR_WIFI_ICON = releasedFlag("wifi_tracker_lib_for_wifi_icon")
-
     // TODO(b/293863612): Tracking Bug
     @JvmField val INCOMPATIBLE_CHARGING_BATTERY_ICON =
         releasedFlag("incompatible_charging_battery_icon")
@@ -342,11 +334,6 @@
             namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER,
         )
 
-    @Keep
-    @JvmField
-    val WM_CAPTION_ON_SHELL =
-        sysPropBooleanFlag("persist.wm.debug.caption_on_shell", default = true)
-
     // TODO(b/256873975): Tracking Bug
     @JvmField
     @Keep
@@ -377,16 +364,6 @@
     val WM_ALWAYS_ENFORCE_PREDICTIVE_BACK =
         sysPropBooleanFlag("persist.wm.debug.predictive_back_always_enforce", default = false)
 
-    // TODO(b/254512728): Tracking Bug
-    @JvmField val NEW_BACK_AFFORDANCE = releasedFlag("new_back_affordance")
-
-
-    // TODO(b/270987164): Tracking Bug
-    @JvmField val TRACKPAD_GESTURE_FEATURES = releasedFlag("trackpad_gesture_features")
-
-    // TODO(b/273800936): Tracking Bug
-    @JvmField val TRACKPAD_GESTURE_COMMON = releasedFlag("trackpad_gesture_common")
-
     // TODO(b/251205791): Tracking Bug
     @JvmField val SCREENSHOT_APP_CLIPS = releasedFlag("screenshot_app_clips")
 
@@ -497,12 +474,6 @@
     @JvmField val DECOUPLE_REMOTE_INPUT_DELEGATE_AND_CALLBACK_UPDATE =
             unreleasedFlag("decouple_remote_input_delegate_and_callback_update")
 
-    // 2900 - CentralSurfaces-related flags
-
-    // TODO(b/285174336): Tracking Bug
-    @JvmField
-    val USE_REPOS_FOR_BOUNCER_SHOWING = releasedFlag("use_repos_for_bouncer_showing")
-
     /** TODO(b/296223317): Enables the new keyguard presentation containing a clock. */
     @JvmField
     val ENABLE_CLOCK_KEYGUARD_PRESENTATION = releasedFlag("enable_clock_keyguard_presentation")
diff --git a/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt b/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt
index 2856011..567bf70 100644
--- a/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt
+++ b/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt
@@ -339,7 +339,7 @@
                 }
                 // Fallback to non-ImageDecoder load if the attempt failed (e.g. the resource
                 // is a Vector drawable which ImageDecoder doesn't support.)
-                ?: icon.loadDrawable(context)
+                ?: loadIconDrawable(icon, context)
             }
             Icon.TYPE_BITMAP -> {
                 BitmapDrawable(context.resources, icon.bitmap)
@@ -357,7 +357,7 @@
             }
             else -> {
                 // We don't recognize this icon, just fallback.
-                icon.loadDrawable(context)
+                loadIconDrawable(icon, context)
             }
         }?.let { drawable ->
             // Icons carry tint which we need to propagate down to a Drawable.
@@ -366,6 +366,14 @@
         }
     }
 
+    @WorkerThread
+    fun loadIconDrawable(icon: Icon, context: Context): Drawable? {
+        icon.loadDrawable(context)?.let { return it }
+
+        Log.w(TAG, "Failed to load drawable for $icon")
+        return null
+    }
+
     /**
      * Obtains the image size from the image header, without decoding the full image.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
index f1620d9..f1a8faf 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
@@ -17,50 +17,62 @@
 package com.android.systemui.haptics.qs
 
 import android.animation.ValueAnimator
-import android.annotation.SuppressLint
 import android.os.VibrationEffect
-import android.view.MotionEvent
 import android.view.View
-import android.view.ViewConfiguration
 import android.view.animation.AccelerateDecelerateInterpolator
 import androidx.annotation.VisibleForTesting
 import androidx.core.animation.doOnCancel
 import androidx.core.animation.doOnEnd
 import androidx.core.animation.doOnStart
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.statusbar.VibratorHelper
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.launch
+import kotlinx.coroutines.flow.combine
 
 /**
  * A class that handles the long press visuo-haptic effect for a QS tile.
  *
  * The class is also a [View.OnTouchListener] to handle the touch events, clicks and long-press
- * gestures of the tile. The class also provides a [State] that can be used to determine the current
+ * gestures of the tile. The class also provides a [State] tha can be used to determine the current
  * state of the long press effect.
  *
  * @property[vibratorHelper] The [VibratorHelper] to deliver haptic effects.
  * @property[effectDuration] The duration of the effect in ms.
  */
-class QSLongPressEffect(
+// TODO(b/332902869): In addition from being injectable, we can consider making it a singleton
+class QSLongPressEffect
+@Inject
+constructor(
     private val vibratorHelper: VibratorHelper?,
-    private val effectDuration: Int,
-) : View.OnTouchListener {
+    keyguardInteractor: KeyguardInteractor,
+) {
+
+    private var effectDuration = 0
 
     /** Current state */
-    var state = State.IDLE
-        @VisibleForTesting set
+    private var _state = MutableStateFlow(State.IDLE)
+    val state = _state.asStateFlow()
 
     /** Flows for view control and action */
     private val _effectProgress = MutableStateFlow<Float?>(null)
     val effectProgress = _effectProgress.asStateFlow()
 
-    private val _actionType = MutableStateFlow<ActionType?>(null)
-    val actionType = _actionType.asStateFlow()
+    // Actions to perform
+    private val _postedActionType = MutableStateFlow<ActionType?>(null)
+    val actionType: Flow<ActionType?> =
+        combine(
+            _postedActionType,
+            keyguardInteractor.isKeyguardDismissible,
+        ) { action, isDismissible ->
+            if (!isDismissible && action == ActionType.LONG_PRESS) {
+                ActionType.RESET_AND_LONG_PRESS
+            } else {
+                action
+            }
+        }
 
     /** Haptic effects */
     private val durations =
@@ -69,41 +81,33 @@
             VibrationEffect.Composition.PRIMITIVE_SPIN
         )
 
-    private val longPressHint =
-        LongPressHapticBuilder.createLongPressHint(
-            durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION,
-            durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION,
-            effectDuration
-        )
+    private var longPressHint: VibrationEffect? = null
 
     private val snapEffect = LongPressHapticBuilder.createSnapEffect()
 
-    /* A coroutine scope and a timer job that waits for the pressedTimeout */
-    var scope: CoroutineScope? = null
-    private var waitJob: Job? = null
+    private var effectAnimator: ValueAnimator? = null
 
-    private val effectAnimator =
-        ValueAnimator.ofFloat(0f, 1f).apply {
-            duration = effectDuration.toLong()
-            interpolator = AccelerateDecelerateInterpolator()
+    val hasInitialized: Boolean
+        get() = longPressHint != null && effectAnimator != null
 
-            doOnStart { handleAnimationStart() }
-            addUpdateListener { _effectProgress.value = animatedValue as Float }
-            doOnEnd { handleAnimationComplete() }
-            doOnCancel { handleAnimationCancel() }
-        }
+    @VisibleForTesting
+    fun setState(state: State) {
+        _state.value = state
+    }
 
     private fun reverse() {
-        val pausedProgress = effectAnimator.animatedFraction
-        val effect =
-            LongPressHapticBuilder.createReversedEffect(
-                pausedProgress,
-                durations?.get(0) ?: 0,
-                effectDuration,
-            )
-        vibratorHelper?.cancel()
-        vibrate(effect)
-        effectAnimator.reverse()
+        effectAnimator?.let {
+            val pausedProgress = it.animatedFraction
+            val effect =
+                LongPressHapticBuilder.createReversedEffect(
+                    pausedProgress,
+                    durations?.get(0) ?: 0,
+                    effectDuration,
+                )
+            vibratorHelper?.cancel()
+            vibrate(effect)
+            it.reverse()
+        }
     }
 
     private fun vibrate(effect: VibrationEffect?) {
@@ -112,69 +116,38 @@
         }
     }
 
-    /**
-     * Handle relevant touch events for the operation of a Tile.
-     *
-     * A click action is performed following the relevant logic that originates from the
-     * [MotionEvent.ACTION_UP] event depending on the current state.
-     */
-    @SuppressLint("ClickableViewAccessibility")
-    override fun onTouch(view: View?, event: MotionEvent?): Boolean {
-        when (event?.actionMasked) {
-            MotionEvent.ACTION_DOWN -> handleActionDown()
-            MotionEvent.ACTION_UP -> handleActionUp()
-            MotionEvent.ACTION_CANCEL -> handleActionCancel()
-        }
-        return true
-    }
-
-    private fun handleActionDown() {
-        when (state) {
+    fun handleActionDown() {
+        when (_state.value) {
             State.IDLE -> {
-                startPressedTimeoutWait()
-                state = State.TIMEOUT_WAIT
+                setState(State.TIMEOUT_WAIT)
             }
-            State.RUNNING_BACKWARDS -> effectAnimator.cancel()
+            State.RUNNING_BACKWARDS -> effectAnimator?.cancel()
             else -> {}
         }
     }
 
-    private fun startPressedTimeoutWait() {
-        waitJob =
-            scope?.launch {
-                try {
-                    delay(PRESSED_TIMEOUT)
-                    handleTimeoutComplete()
-                } catch (_: CancellationException) {
-                    state = State.IDLE
-                }
-            }
-    }
-
-    private fun handleActionUp() {
-        when (state) {
+    fun handleActionUp() {
+        when (_state.value) {
             State.TIMEOUT_WAIT -> {
-                waitJob?.cancel()
-                _actionType.value = ActionType.CLICK
-                state = State.IDLE
+                _postedActionType.value = ActionType.CLICK
+                setState(State.IDLE)
             }
             State.RUNNING_FORWARD -> {
                 reverse()
-                state = State.RUNNING_BACKWARDS
+                setState(State.RUNNING_BACKWARDS)
             }
             else -> {}
         }
     }
 
-    private fun handleActionCancel() {
-        when (state) {
+    fun handleActionCancel() {
+        when (_state.value) {
             State.TIMEOUT_WAIT -> {
-                waitJob?.cancel()
-                state = State.IDLE
+                setState(State.IDLE)
             }
             State.RUNNING_FORWARD -> {
                 reverse()
-                state = State.RUNNING_BACKWARDS
+                setState(State.RUNNING_BACKWARDS)
             }
             else -> {}
         }
@@ -182,54 +155,78 @@
 
     private fun handleAnimationStart() {
         vibrate(longPressHint)
-        state = State.RUNNING_FORWARD
+        setState(State.RUNNING_FORWARD)
     }
 
     /** This function is called both when an animator completes or gets cancelled */
     private fun handleAnimationComplete() {
-        if (state == State.RUNNING_FORWARD) {
+        if (_state.value == State.RUNNING_FORWARD) {
             vibrate(snapEffect)
-            _actionType.value = ActionType.LONG_PRESS
+            _postedActionType.value = ActionType.LONG_PRESS
             _effectProgress.value = null
         }
-        if (state != State.TIMEOUT_WAIT) {
+        if (_state.value != State.TIMEOUT_WAIT) {
             // This will happen if the animator did not finish by being cancelled
-            state = State.IDLE
+            setState(State.IDLE)
         }
     }
 
     private fun handleAnimationCancel() {
-        _effectProgress.value = 0f
-        startPressedTimeoutWait()
-        state = State.TIMEOUT_WAIT
+        _effectProgress.value = null
+        setState(State.TIMEOUT_WAIT)
     }
 
-    private fun handleTimeoutComplete() {
-        if (state == State.TIMEOUT_WAIT && !effectAnimator.isRunning) {
-            effectAnimator.start()
+    fun handleTimeoutComplete() {
+        if (_state.value == State.TIMEOUT_WAIT && effectAnimator?.isRunning == false) {
+            effectAnimator?.start()
         }
     }
 
     fun clearActionType() {
-        _actionType.value = null
+        _postedActionType.value = null
+    }
+
+    /** Reset the effect by going back to a default [IDLE] state */
+    fun resetEffect() {
+        if (effectAnimator?.isRunning == true) {
+            effectAnimator?.cancel()
+        }
+        longPressHint = null
+        effectAnimator = null
+        _effectProgress.value = null
+        _postedActionType.value = null
+        setState(State.IDLE)
     }
 
     /**
      * Reset the effect with a new effect duration.
      *
-     * The effect will go back to an [IDLE] state where it can begin its logic with a new duration.
-     *
      * @param[duration] New duration for the long-press effect
+     * @return true if the effect initialized correctly
      */
-    fun resetWithDuration(duration: Int) {
+    fun initializeEffect(duration: Int): Boolean {
         // The effect can't reset if it is running
-        if (effectAnimator.isRunning) return
+        if (duration <= 0) return false
 
-        effectAnimator.duration = duration.toLong()
-        _effectProgress.value = 0f
-        _actionType.value = null
-        waitJob?.cancel()
-        state = State.IDLE
+        resetEffect()
+        effectDuration = duration
+        effectAnimator =
+            ValueAnimator.ofFloat(0f, 1f).apply {
+                this.duration = effectDuration.toLong()
+                interpolator = AccelerateDecelerateInterpolator()
+
+                doOnStart { handleAnimationStart() }
+                addUpdateListener { _effectProgress.value = animatedValue as Float }
+                doOnEnd { handleAnimationComplete() }
+                doOnCancel { handleAnimationCancel() }
+            }
+        longPressHint =
+            LongPressHapticBuilder.createLongPressHint(
+                durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION,
+                durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION,
+                effectDuration
+            )
+        return true
     }
 
     enum class State {
@@ -243,13 +240,6 @@
     enum class ActionType {
         CLICK,
         LONG_PRESS,
-    }
-
-    companion object {
-        /**
-         * A timeout to let the tile resolve if it is being swiped/scrolled. Since QS tiles are
-         * inside a scrollable container, they will be considered pressed only after a tap timeout.
-         */
-        val PRESSED_TIMEOUT = ViewConfiguration.getTapTimeout().toLong() + 20L
+        RESET_AND_LONG_PRESS,
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
index f4998a7..dd7a285 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
@@ -16,6 +16,9 @@
 
 package com.android.systemui.haptics.qs
 
+import android.annotation.SuppressLint
+import android.view.MotionEvent
+import android.view.ViewConfiguration
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.tracing.coroutines.launch
@@ -23,54 +26,68 @@
 import com.android.systemui.qs.tileimpl.QSTileViewImpl
 import kotlinx.coroutines.DisposableHandle
 
-class QSLongPressEffectViewBinder {
-
-    private var handle: DisposableHandle? = null
-    val isBound: Boolean
-        get() = handle != null
+object QSLongPressEffectViewBinder {
 
     fun bind(
         tile: QSTileViewImpl,
+        qsLongPressEffect: QSLongPressEffect?,
         tileSpec: String?,
-        effect: QSLongPressEffect?,
-    ) {
-        if (effect == null) return
+    ): DisposableHandle? {
+        if (qsLongPressEffect == null) return null
 
-        handle =
-            tile.repeatWhenAttached {
-                repeatOnLifecycle(Lifecycle.State.CREATED) {
-                    effect.scope = this
-                    val tag = "${tileSpec ?: "unknownTileSpec"}#LongPressEffect"
+        // Set the touch listener as the long-press effect
+        setTouchListener(tile, qsLongPressEffect)
 
-                    launch("$tag#progress") {
-                        effect.effectProgress.collect { progress ->
-                            progress?.let {
-                                if (it == 0f) {
-                                    tile.bringToFront()
-                                }
+        return tile.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.CREATED) {
+                // Progress of the effect
+                launch({ "${tileSpec ?: "unknownTileSpec"}#LongPressEffect#progress" }) {
+                    qsLongPressEffect.effectProgress.collect { progress ->
+                        progress?.let {
+                            if (it == 0f) {
+                                tile.bringToFront()
+                            } else {
                                 tile.updateLongPressEffectProperties(it)
                             }
                         }
                     }
+                }
 
-                    launch("$tag#action") {
-                        effect.actionType.collect { action ->
-                            action?.let {
-                                when (it) {
-                                    QSLongPressEffect.ActionType.CLICK -> tile.performClick()
-                                    QSLongPressEffect.ActionType.LONG_PRESS ->
-                                        tile.performLongClick()
+                // Action to perform
+                launch({ "${tileSpec ?: "unknownTileSpec"}#LongPressEffect#action" }) {
+                    qsLongPressEffect.actionType.collect { action ->
+                        action?.let {
+                            when (it) {
+                                QSLongPressEffect.ActionType.CLICK -> tile.performClick()
+                                QSLongPressEffect.ActionType.LONG_PRESS -> tile.performLongClick()
+                                QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS -> {
+                                    tile.resetLongPressEffectProperties()
+                                    tile.performLongClick()
                                 }
-                                effect.clearActionType()
                             }
+                            qsLongPressEffect.clearActionType()
                         }
                     }
                 }
             }
+        }
     }
 
-    fun dispose() {
-        handle?.dispose()
-        handle = null
+    @SuppressLint("ClickableViewAccessibility")
+    private fun setTouchListener(tile: QSTileViewImpl, longPressEffect: QSLongPressEffect?) {
+        tile.setOnTouchListener { _, event ->
+            when (event.actionMasked) {
+                MotionEvent.ACTION_DOWN -> {
+                    tile.postDelayed(
+                        { longPressEffect?.handleTimeoutComplete() },
+                        ViewConfiguration.getTapTimeout().toLong(),
+                    )
+                    longPressEffect?.handleActionDown()
+                }
+                MotionEvent.ACTION_UP -> longPressEffect?.handleActionUp()
+                MotionEvent.ACTION_CANCEL -> longPressEffect?.handleActionCancel()
+            }
+            true
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt
index 304fdd6..ca6c8da 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt
@@ -23,11 +23,11 @@
 
 object HapticSliderViewBinder {
     /**
-     * Binds a [SeekableSliderHapticPlugin] to a [View]. The binded view should be a
+     * Binds a [SeekbarHapticPlugin] to a [View]. The binded view should be a
      * [android.widget.SeekBar] or a container of a [android.widget.SeekBar]
      */
     @JvmStatic
-    fun bind(view: View?, plugin: SeekableSliderHapticPlugin) {
+    fun bind(view: View?, plugin: SeekbarHapticPlugin) {
         view?.repeatWhenAttached {
             plugin.startInScope(lifecycleScope)
             try {
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderEventProducer.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderEventProducer.kt
deleted file mode 100644
index cfa5294..0000000
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderEventProducer.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.haptics.slider
-
-import android.widget.SeekBar
-import android.widget.SeekBar.OnSeekBarChangeListener
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
-
-/** An event producer for a Seekable element such as the Android [SeekBar] */
-class SeekableSliderEventProducer : SliderEventProducer, OnSeekBarChangeListener {
-
-    /** The current event reported by a SeekBar */
-    private val _currentEvent = MutableStateFlow(SliderEvent(SliderEventType.NOTHING, 0f))
-
-    override fun produceEvents(): Flow<SliderEvent> = _currentEvent.asStateFlow()
-
-    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
-        val eventType =
-            if (fromUser) SliderEventType.PROGRESS_CHANGE_BY_USER
-            else SliderEventType.PROGRESS_CHANGE_BY_PROGRAM
-
-        _currentEvent.value = SliderEvent(eventType, normalizeProgress(seekBar, progress))
-    }
-
-    /**
-     * Normalize the integer progress of a SeekBar to the range from 0F to 1F.
-     *
-     * @param[seekBar] The SeekBar that reports a progress.
-     * @param[progress] The integer progress of the SeekBar within its min and max values.
-     * @return The progress in the range from 0F to 1F.
-     */
-    private fun normalizeProgress(seekBar: SeekBar, progress: Int): Float {
-        if (seekBar.max == seekBar.min) {
-            return 1.0f
-        }
-        val range = seekBar.max - seekBar.min
-        return (progress - seekBar.min) / range.toFloat()
-    }
-
-    override fun onStartTrackingTouch(seekBar: SeekBar) {
-        _currentEvent.update { previousEvent ->
-            SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, previousEvent.currentProgress)
-        }
-    }
-
-    override fun onStopTrackingTouch(seekBar: SeekBar) {
-        _currentEvent.update { previousEvent ->
-            SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, previousEvent.currentProgress)
-        }
-    }
-
-    /** The arrow navigation that was operating the slider has stopped. */
-    fun onArrowUp() {
-        _currentEvent.update { previousEvent ->
-            SliderEvent(SliderEventType.ARROW_UP, previousEvent.currentProgress)
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt
deleted file mode 100644
index ed82278..0000000
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.haptics.slider
-
-import android.view.MotionEvent
-import android.view.VelocityTracker
-import android.widget.SeekBar
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.util.time.SystemClock
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-
-/**
- * A plugin added to a manager of a [android.widget.SeekBar] that adds dynamic haptic feedback.
- *
- * A [SeekableSliderEventProducer] is used as the producer of slider events, a
- * [SliderHapticFeedbackProvider] is used as the listener of slider states to play haptic feedback
- * depending on the state, and a [SeekableSliderTracker] is used as the state machine handler that
- * tracks and manipulates the slider state.
- */
-class SeekableSliderHapticPlugin
-@JvmOverloads
-constructor(
-    vibratorHelper: VibratorHelper,
-    systemClock: SystemClock,
-    sliderHapticFeedbackConfig: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(),
-    private val sliderTrackerConfig: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
-) {
-
-    private val velocityTracker = VelocityTracker.obtain()
-
-    private val sliderEventProducer = SeekableSliderEventProducer()
-
-    private val sliderHapticFeedbackProvider =
-        SliderHapticFeedbackProvider(
-            vibratorHelper,
-            velocityTracker,
-            sliderHapticFeedbackConfig,
-            systemClock,
-        )
-
-    private var sliderTracker: SeekableSliderTracker? = null
-
-    private var pluginScope: CoroutineScope? = null
-
-    val isTracking: Boolean
-        get() = sliderTracker?.isTracking == true
-
-    val trackerState: SliderState?
-        get() = sliderTracker?.currentState
-
-    /**
-     * A waiting [Job] for a timer that estimates the key-up event when a key-down event is
-     * received.
-     *
-     * This is useful for the cases where the slider is being operated by an external key, but the
-     * release of the key is not easily accessible (e.g., the volume keys)
-     */
-    private var keyUpJob: Job? = null
-
-    @VisibleForTesting
-    val isKeyUpTimerWaiting: Boolean
-        get() = keyUpJob != null && keyUpJob?.isActive == true
-
-    /**
-     * Specify the scope for the plugin's operations and start the slider tracker in this scope.
-     * This also involves the key-up timer job.
-     */
-    fun startInScope(scope: CoroutineScope) {
-        if (sliderTracker != null) stop()
-        sliderTracker =
-            SeekableSliderTracker(
-                sliderHapticFeedbackProvider,
-                sliderEventProducer,
-                scope,
-                sliderTrackerConfig,
-            )
-        pluginScope = scope
-        sliderTracker?.startTracking()
-    }
-
-    /**
-     * Stop the plugin
-     *
-     * This stops the tracking of slider states, events and triggers of haptic feedback.
-     */
-    fun stop() = sliderTracker?.stopTracking()
-
-    /** React to a touch event */
-    fun onTouchEvent(event: MotionEvent?) {
-        when (event?.actionMasked) {
-            MotionEvent.ACTION_UP,
-            MotionEvent.ACTION_CANCEL -> velocityTracker.clear()
-            MotionEvent.ACTION_DOWN,
-            MotionEvent.ACTION_MOVE -> velocityTracker.addMovement(event)
-        }
-    }
-
-    /** onStartTrackingTouch event from the slider's [android.widget.SeekBar] */
-    fun onStartTrackingTouch(seekBar: SeekBar) {
-        if (isTracking) {
-            sliderEventProducer.onStartTrackingTouch(seekBar)
-        }
-    }
-
-    /** onProgressChanged event from the slider's [android.widget.SeekBar] */
-    fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
-        if (isTracking) {
-            sliderEventProducer.onProgressChanged(seekBar, progress, fromUser)
-        }
-    }
-
-    /** onStopTrackingTouch event from the slider's [android.widget.SeekBar] */
-    fun onStopTrackingTouch(seekBar: SeekBar) {
-        if (isTracking) {
-            sliderEventProducer.onStopTrackingTouch(seekBar)
-        }
-    }
-
-    /** onArrowUp event recorded */
-    fun onArrowUp() {
-        if (isTracking) {
-            sliderEventProducer.onArrowUp()
-        }
-    }
-
-    /**
-     * An external key was pressed (e.g., a volume key).
-     *
-     * This event is used to estimate the key-up event based on a running a timer as a waiting
-     * coroutine in the [pluginScope]. A key-up event in a slider corresponds to an onArrowUp event.
-     * Therefore, [onArrowUp] must be called after the timeout.
-     */
-    fun onKeyDown() {
-        if (!isTracking) return
-
-        if (isKeyUpTimerWaiting) {
-            // Cancel the ongoing wait
-            keyUpJob?.cancel()
-        }
-        keyUpJob =
-            pluginScope?.launch {
-                delay(KEY_UP_TIMEOUT)
-                onArrowUp()
-            }
-    }
-
-    companion object {
-        const val KEY_UP_TIMEOUT = 60L
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderTracker.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderTracker.kt
deleted file mode 100644
index 0af3038..0000000
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderTracker.kt
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.haptics.slider
-
-import androidx.annotation.VisibleForTesting
-import kotlin.math.abs
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.isActive
-import kotlinx.coroutines.launch
-
-/**
- * Slider tracker attached to a seekable slider.
- *
- * The tracker runs a state machine to execute actions on touch-based events typical of a seekable
- * slider such as [android.widget.SeekBar]. Coroutines responsible for running the state machine,
- * collecting slider events and maintaining waiting states are run on the provided [CoroutineScope].
- *
- * @param[sliderStateListener] Listener of the slider state.
- * @param[sliderEventProducer] Producer of slider events arising from the slider.
- * @param[trackerScope] [CoroutineScope] used to launch coroutines for the collection of slider
- *   events and the launch of timer jobs.
- * @property[config] Configuration parameters of the slider tracker.
- */
-class SeekableSliderTracker(
-    sliderStateListener: SliderStateListener,
-    sliderEventProducer: SliderEventProducer,
-    trackerScope: CoroutineScope,
-    private val config: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
-) : SliderTracker(trackerScope, sliderStateListener, sliderEventProducer) {
-
-    // History of the latest progress collected from slider events
-    private var latestProgress = 0f
-    // Timer job for the wait state
-    private var timerJob: Job? = null
-    // Indicator that there is waiting job active
-    var isWaiting = false
-        private set
-        get() = timerJob != null && timerJob?.isActive == true
-
-    override suspend fun iterateState(event: SliderEvent) {
-        when (currentState) {
-            SliderState.IDLE -> handleIdle(event.type, event.currentProgress)
-            SliderState.WAIT -> handleWait(event.type, event.currentProgress)
-            SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH -> handleAcquired(event.type)
-            SliderState.DRAG_HANDLE_DRAGGING -> handleDragging(event.type, event.currentProgress)
-            SliderState.DRAG_HANDLE_REACHED_BOOKEND ->
-                handleReachedBookend(event.type, event.currentProgress)
-            SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH -> setState(SliderState.IDLE)
-            SliderState.JUMP_TRACK_LOCATION_SELECTED -> handleJumpToTrack(event.type)
-            SliderState.JUMP_BOOKEND_SELECTED -> handleJumpToBookend(event.type)
-            SliderState.ARROW_HANDLE_MOVED_ONCE -> handleArrowOnce(event.type)
-            SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY ->
-                handleArrowContinuous(event.type, event.currentProgress)
-            SliderState.ARROW_HANDLE_REACHED_BOOKEND -> handleArrowBookend()
-        }
-        latestProgress = event.currentProgress
-    }
-
-    private fun handleIdle(newEventType: SliderEventType, currentProgress: Float) {
-        if (newEventType == SliderEventType.STARTED_TRACKING_TOUCH) {
-            timerJob = launchTimer()
-            // The WAIT state will wait for the timer to complete or a slider progress to occur.
-            // This will disambiguate between an imprecise touch that acquires the slider handle,
-            // and a select and jump operation in the slider track.
-            setState(SliderState.WAIT)
-        } else if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_PROGRAM) {
-            val state =
-                if (bookendReached(currentProgress)) SliderState.ARROW_HANDLE_REACHED_BOOKEND
-                else SliderState.ARROW_HANDLE_MOVED_ONCE
-            setState(state)
-        }
-    }
-
-    private fun launchTimer() =
-        scope.launch {
-            delay(config.waitTimeMillis)
-            if (isActive && currentState == SliderState.WAIT) {
-                setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
-                // This transitory state must also trigger the corresponding action
-                executeOnState(currentState)
-            }
-        }
-
-    private fun handleWait(newEventType: SliderEventType, currentProgress: Float) {
-        // The timer may have completed and may have already modified the state
-        if (currentState != SliderState.WAIT) return
-
-        // The timer is still running but the state may be modified by the progress change
-        val deltaProgressIsJump = deltaProgressIsAboveThreshold(currentProgress)
-        if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER) {
-            if (bookendReached(currentProgress)) {
-                setState(SliderState.JUMP_BOOKEND_SELECTED)
-            } else if (deltaProgressIsJump) {
-                setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
-            } else {
-                setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
-            }
-        } else if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
-            setState(SliderState.IDLE)
-        }
-
-        // If the state changed, the timer does not need to complete. No further synchronization
-        // will be required onwards until WAIT is reached again.
-        if (currentState != SliderState.WAIT) {
-            timerJob?.cancel()
-            timerJob = null
-        }
-    }
-
-    private fun handleAcquired(newEventType: SliderEventType) {
-        if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
-            setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
-        } else if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER) {
-            setState(SliderState.DRAG_HANDLE_DRAGGING)
-        }
-    }
-
-    private fun handleDragging(newEventType: SliderEventType, currentProgress: Float) {
-        if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
-            setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
-        } else if (
-            newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER &&
-                bookendReached(currentProgress)
-        ) {
-            setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-        }
-    }
-
-    private fun handleReachedBookend(newEventType: SliderEventType, currentProgress: Float) {
-        if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER) {
-            if (!bookendReached(currentProgress)) {
-                setState(SliderState.DRAG_HANDLE_DRAGGING)
-            }
-        } else if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
-            setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
-        }
-    }
-
-    private fun handleJumpToTrack(newEventType: SliderEventType) {
-        when (newEventType) {
-            SliderEventType.PROGRESS_CHANGE_BY_USER -> setState(SliderState.DRAG_HANDLE_DRAGGING)
-            SliderEventType.STOPPED_TRACKING_TOUCH ->
-                setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
-            else -> {}
-        }
-    }
-
-    private fun handleJumpToBookend(newEventType: SliderEventType) {
-        when (newEventType) {
-            SliderEventType.PROGRESS_CHANGE_BY_USER -> setState(SliderState.DRAG_HANDLE_DRAGGING)
-            SliderEventType.STOPPED_TRACKING_TOUCH ->
-                setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
-            else -> {}
-        }
-    }
-
-    override fun executeOnState(currentState: SliderState) {
-        when (currentState) {
-            SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH -> sliderListener.onHandleAcquiredByTouch()
-            SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH -> {
-                sliderListener.onHandleReleasedFromTouch()
-                // This transitory state must also reset the state machine
-                resetState()
-            }
-            SliderState.DRAG_HANDLE_DRAGGING -> sliderListener.onProgress(latestProgress)
-            SliderState.DRAG_HANDLE_REACHED_BOOKEND -> executeOnBookend()
-            SliderState.JUMP_TRACK_LOCATION_SELECTED ->
-                sliderListener.onProgressJump(latestProgress)
-            SliderState.ARROW_HANDLE_MOVED_ONCE -> sliderListener.onSelectAndArrow(latestProgress)
-            SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY -> sliderListener.onProgress(latestProgress)
-            SliderState.ARROW_HANDLE_REACHED_BOOKEND -> {
-                executeOnBookend()
-                // This transitory execution must also reset the state
-                resetState()
-            }
-            else -> {}
-        }
-    }
-
-    private fun executeOnBookend() {
-        if (latestProgress >= config.upperBookendThreshold) sliderListener.onUpperBookend()
-        else sliderListener.onLowerBookend()
-    }
-
-    override fun resetState() {
-        timerJob?.cancel()
-        timerJob = null
-        super.resetState()
-    }
-
-    private fun deltaProgressIsAboveThreshold(
-        currentProgress: Float,
-        epsilon: Float = 0.00001f,
-    ): Boolean {
-        val delta = abs(currentProgress - latestProgress)
-        return delta > config.jumpThreshold - epsilon
-    }
-
-    private fun bookendReached(currentProgress: Float): Boolean {
-        return currentProgress >= config.upperBookendThreshold ||
-            currentProgress <= config.lowerBookendThreshold
-    }
-
-    private fun handleArrowOnce(newEventType: SliderEventType) {
-        val nextState =
-            when (newEventType) {
-                SliderEventType.STARTED_TRACKING_TOUCH -> {
-                    // Launching the timer and going to WAIT
-                    timerJob = launchTimer()
-                    SliderState.WAIT
-                }
-                SliderEventType.PROGRESS_CHANGE_BY_PROGRAM ->
-                    SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
-                SliderEventType.ARROW_UP -> SliderState.IDLE
-                else -> SliderState.ARROW_HANDLE_MOVED_ONCE
-            }
-        setState(nextState)
-    }
-
-    private fun handleArrowContinuous(newEventType: SliderEventType, currentProgress: Float) {
-        val reachedBookend = bookendReached(currentProgress)
-        val nextState =
-            when (newEventType) {
-                SliderEventType.ARROW_UP -> SliderState.IDLE
-                SliderEventType.STARTED_TRACKING_TOUCH -> {
-                    // Launching the timer and going to WAIT
-                    timerJob = launchTimer()
-                    SliderState.WAIT
-                }
-                SliderEventType.PROGRESS_CHANGE_BY_PROGRAM -> {
-                    if (reachedBookend) SliderState.ARROW_HANDLE_REACHED_BOOKEND
-                    else SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
-                }
-                else -> SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
-            }
-        setState(nextState)
-    }
-
-    private fun handleArrowBookend() = setState(SliderState.IDLE)
-
-    @VisibleForTesting
-    fun setState(state: SliderState) {
-        currentState = state
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
new file mode 100644
index 0000000..2007db34
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.slider
+
+import android.view.MotionEvent
+import android.view.VelocityTracker
+import android.widget.SeekBar
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.util.time.SystemClock
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/**
+ * A plugin added to a manager of a [android.widget.SeekBar] that adds dynamic haptic feedback.
+ *
+ * A [SliderStateProducer] is used as the producer of slider events, a
+ * [SliderHapticFeedbackProvider] is used as the listener of slider states to play haptic feedback
+ * depending on the state, and a [SliderStateTracker] is used as the state machine handler that
+ * tracks and manipulates the slider state.
+ */
+class SeekbarHapticPlugin
+@JvmOverloads
+constructor(
+    vibratorHelper: VibratorHelper,
+    systemClock: SystemClock,
+    sliderHapticFeedbackConfig: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(),
+    private val sliderTrackerConfig: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
+) {
+
+    private val velocityTracker = VelocityTracker.obtain()
+
+    private val sliderEventProducer = SliderStateProducer()
+
+    private val sliderHapticFeedbackProvider =
+        SliderHapticFeedbackProvider(
+            vibratorHelper,
+            velocityTracker,
+            sliderHapticFeedbackConfig,
+            systemClock,
+        )
+
+    private var sliderTracker: SliderStateTracker? = null
+
+    private var pluginScope: CoroutineScope? = null
+
+    val isTracking: Boolean
+        get() = sliderTracker?.isTracking == true
+
+    val trackerState: SliderState?
+        get() = sliderTracker?.currentState
+
+    /**
+     * A waiting [Job] for a timer that estimates the key-up event when a key-down event is
+     * received.
+     *
+     * This is useful for the cases where the slider is being operated by an external key, but the
+     * release of the key is not easily accessible (e.g., the volume keys)
+     */
+    private var keyUpJob: Job? = null
+
+    @VisibleForTesting
+    val isKeyUpTimerWaiting: Boolean
+        get() = keyUpJob != null && keyUpJob?.isActive == true
+
+    /**
+     * Specify the scope for the plugin's operations and start the slider tracker in this scope.
+     * This also involves the key-up timer job.
+     */
+    fun startInScope(scope: CoroutineScope) {
+        if (sliderTracker != null) stop()
+        sliderTracker =
+            SliderStateTracker(
+                sliderHapticFeedbackProvider,
+                sliderEventProducer,
+                scope,
+                sliderTrackerConfig,
+            )
+        pluginScope = scope
+        sliderTracker?.startTracking()
+    }
+
+    /**
+     * Stop the plugin
+     *
+     * This stops the tracking of slider states, events and triggers of haptic feedback.
+     */
+    fun stop() = sliderTracker?.stopTracking()
+
+    /** React to a touch event */
+    fun onTouchEvent(event: MotionEvent?) {
+        when (event?.actionMasked) {
+            MotionEvent.ACTION_UP,
+            MotionEvent.ACTION_CANCEL -> velocityTracker.clear()
+            MotionEvent.ACTION_DOWN,
+            MotionEvent.ACTION_MOVE -> velocityTracker.addMovement(event)
+        }
+    }
+
+    /** onStartTrackingTouch event from the slider's [android.widget.SeekBar] */
+    fun onStartTrackingTouch(seekBar: SeekBar) {
+        if (isTracking) {
+            sliderEventProducer.onStartTracking(true)
+        }
+    }
+
+    /** onProgressChanged event from the slider's [android.widget.SeekBar] */
+    fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+        if (isTracking) {
+            if (sliderTracker?.currentState == SliderState.IDLE && !fromUser) {
+                // This case translates to the slider starting to track program changes
+                sliderEventProducer.resetWithProgress(normalizeProgress(seekBar, progress))
+                sliderEventProducer.onStartTracking(false)
+            } else {
+                sliderEventProducer.onProgressChanged(
+                    fromUser,
+                    normalizeProgress(seekBar, progress),
+                )
+            }
+        }
+    }
+
+    /**
+     * Normalize the integer progress of a SeekBar to the range from 0F to 1F.
+     *
+     * @param[seekBar] The SeekBar that reports a progress.
+     * @param[progress] The integer progress of the SeekBar within its min and max values.
+     * @return The progress in the range from 0F to 1F.
+     */
+    private fun normalizeProgress(seekBar: SeekBar, progress: Int): Float {
+        if (seekBar.max == seekBar.min) {
+            return 1.0f
+        }
+        val range = seekBar.max - seekBar.min
+        return (progress - seekBar.min) / range.toFloat()
+    }
+
+    /** onStopTrackingTouch event from the slider's [android.widget.SeekBar] */
+    fun onStopTrackingTouch(seekBar: SeekBar) {
+        if (isTracking) {
+            sliderEventProducer.onStopTracking(true)
+        }
+    }
+
+    /** Programmatic changes have stopped */
+    private fun onStoppedTrackingProgram() {
+        if (isTracking) {
+            sliderEventProducer.onStopTracking(false)
+        }
+    }
+
+    /**
+     * An external key was pressed (e.g., a volume key).
+     *
+     * This event is used to estimate the key-up event based on a running a timer as a waiting
+     * coroutine in the [pluginScope]. A key-up event in a slider corresponds to an onArrowUp event.
+     * Therefore, [onStoppedTrackingProgram] must be called after the timeout.
+     */
+    fun onKeyDown() {
+        if (!isTracking) return
+
+        if (isKeyUpTimerWaiting) {
+            // Cancel the ongoing wait
+            keyUpJob?.cancel()
+        }
+        keyUpJob =
+            pluginScope?.launch {
+                delay(KEY_UP_TIMEOUT)
+                onStoppedTrackingProgram()
+            }
+    }
+
+    companion object {
+        const val KEY_UP_TIMEOUT = 60L
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt
index 4a63941..0edef99 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt
@@ -22,6 +22,8 @@
     NOTHING,
     /* The slider has captured a touch input and is tracking touch events. */
     STARTED_TRACKING_TOUCH,
+    /* The slider started tracking programmatic value changes */
+    STARTED_TRACKING_PROGRAM,
     /* The slider progress is changing due to user touch input. */
     PROGRESS_CHANGE_BY_USER,
     /* The slider progress is changing programmatically. */
@@ -29,5 +31,5 @@
     /* The slider has stopped tracking touch events. */
     STOPPED_TRACKING_TOUCH,
     /* The external (not touch) stimulus that was modifying the slider progress has stopped. */
-    ARROW_UP,
+    STOPPED_TRACKING_PROGRAM,
 }
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateProducer.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateProducer.kt
new file mode 100644
index 0000000..1124ab1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateProducer.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.slider
+
+import androidx.annotation.FloatRange
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+
+/** A stateful producer of [SliderEvent] */
+class SliderStateProducer : SliderEventProducer {
+
+    /** The current event of a slider */
+    private val _currentEvent = MutableStateFlow(SliderEvent(SliderEventType.NOTHING, 0f))
+
+    override fun produceEvents(): Flow<SliderEvent> = _currentEvent.asStateFlow()
+
+    fun onProgressChanged(fromUser: Boolean, @FloatRange(from = 0.0, to = 1.0) progress: Float) {
+        val eventType =
+            if (fromUser) SliderEventType.PROGRESS_CHANGE_BY_USER
+            else SliderEventType.PROGRESS_CHANGE_BY_PROGRAM
+
+        _currentEvent.value = SliderEvent(eventType, progress)
+    }
+
+    fun onStartTracking(fromUser: Boolean) {
+        val eventType =
+            if (fromUser) SliderEventType.STARTED_TRACKING_TOUCH
+            else SliderEventType.STARTED_TRACKING_PROGRAM
+        _currentEvent.update { previousEvent ->
+            SliderEvent(eventType, previousEvent.currentProgress)
+        }
+    }
+
+    fun onStopTracking(fromUser: Boolean) {
+        val eventType =
+            if (fromUser) SliderEventType.STOPPED_TRACKING_TOUCH
+            else SliderEventType.STOPPED_TRACKING_PROGRAM
+        _currentEvent.update { previousEvent ->
+            SliderEvent(eventType, previousEvent.currentProgress)
+        }
+    }
+
+    fun resetWithProgress(@FloatRange(from = 0.0, to = 1.0) progress: Float) {
+        _currentEvent.value = SliderEvent(SliderEventType.NOTHING, progress)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateTracker.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateTracker.kt
new file mode 100644
index 0000000..14cf411
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateTracker.kt
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.slider
+
+import androidx.annotation.VisibleForTesting
+import kotlin.math.abs
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+
+/**
+ * Slider tracker attached to a slider.
+ *
+ * The tracker runs a state machine to execute actions on touch-based events typical of a general
+ * slider (including a [android.widget.SeekBar]). Coroutines responsible for running the state
+ * machine, collecting slider events and maintaining waiting states are run on the provided
+ * [CoroutineScope].
+ *
+ * @param[sliderStateListener] Listener of the slider state.
+ * @param[sliderEventProducer] Producer of slider events arising from the slider.
+ * @param[trackerScope] [CoroutineScope] used to launch coroutines for the collection of slider
+ *   events and the launch of timer jobs.
+ * @property[config] Configuration parameters of the slider tracker.
+ */
+class SliderStateTracker(
+    sliderStateListener: SliderStateListener,
+    sliderEventProducer: SliderEventProducer,
+    trackerScope: CoroutineScope,
+    private val config: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
+) : SliderTracker(trackerScope, sliderStateListener, sliderEventProducer) {
+
+    // History of the latest progress collected from slider events
+    private var latestProgress = 0f
+    // Timer job for the wait state
+    private var timerJob: Job? = null
+    // Indicator that there is waiting job active
+    var isWaiting = false
+        private set
+        get() = timerJob != null && timerJob?.isActive == true
+
+    override suspend fun iterateState(event: SliderEvent) {
+        when (currentState) {
+            SliderState.IDLE -> handleIdle(event.type, event.currentProgress)
+            SliderState.WAIT -> handleWait(event.type, event.currentProgress)
+            SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH -> handleAcquired(event.type)
+            SliderState.DRAG_HANDLE_DRAGGING -> handleDragging(event.type, event.currentProgress)
+            SliderState.DRAG_HANDLE_REACHED_BOOKEND ->
+                handleReachedBookend(event.type, event.currentProgress)
+            SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH -> setState(SliderState.IDLE)
+            SliderState.JUMP_TRACK_LOCATION_SELECTED -> handleJumpToTrack(event.type)
+            SliderState.JUMP_BOOKEND_SELECTED -> handleJumpToBookend(event.type)
+            SliderState.ARROW_HANDLE_MOVED_ONCE -> handleArrowOnce(event.type)
+            SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY ->
+                handleArrowContinuous(event.type, event.currentProgress)
+            SliderState.ARROW_HANDLE_REACHED_BOOKEND -> handleArrowBookend()
+        }
+        latestProgress = event.currentProgress
+    }
+
+    private fun handleIdle(newEventType: SliderEventType, currentProgress: Float) {
+        if (newEventType == SliderEventType.STARTED_TRACKING_TOUCH) {
+            timerJob = launchTimer()
+            // The WAIT state will wait for the timer to complete or a slider progress to occur.
+            // This will disambiguate between an imprecise touch that acquires the slider handle,
+            // and a select and jump operation in the slider track.
+            setState(SliderState.WAIT)
+        } else if (newEventType == SliderEventType.STARTED_TRACKING_PROGRAM) {
+            val state =
+                if (bookendReached(currentProgress)) SliderState.ARROW_HANDLE_REACHED_BOOKEND
+                else SliderState.ARROW_HANDLE_MOVED_ONCE
+            setState(state)
+        }
+    }
+
+    private fun launchTimer() =
+        scope.launch {
+            delay(config.waitTimeMillis)
+            if (isActive && currentState == SliderState.WAIT) {
+                setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+                // This transitory state must also trigger the corresponding action
+                executeOnState(currentState)
+            }
+        }
+
+    private fun handleWait(newEventType: SliderEventType, currentProgress: Float) {
+        // The timer may have completed and may have already modified the state
+        if (currentState != SliderState.WAIT) return
+
+        // The timer is still running but the state may be modified by the progress change
+        val deltaProgressIsJump = deltaProgressIsAboveThreshold(currentProgress)
+        if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER) {
+            if (bookendReached(currentProgress)) {
+                setState(SliderState.JUMP_BOOKEND_SELECTED)
+            } else if (deltaProgressIsJump) {
+                setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
+            } else {
+                setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+            }
+        } else if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
+            setState(SliderState.IDLE)
+        }
+
+        // If the state changed, the timer does not need to complete. No further synchronization
+        // will be required onwards until WAIT is reached again.
+        if (currentState != SliderState.WAIT) {
+            timerJob?.cancel()
+            timerJob = null
+        }
+    }
+
+    private fun handleAcquired(newEventType: SliderEventType) {
+        if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
+            setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
+        } else if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER) {
+            setState(SliderState.DRAG_HANDLE_DRAGGING)
+        }
+    }
+
+    private fun handleDragging(newEventType: SliderEventType, currentProgress: Float) {
+        if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
+            setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
+        } else if (
+            newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER &&
+                bookendReached(currentProgress)
+        ) {
+            setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+        }
+    }
+
+    private fun handleReachedBookend(newEventType: SliderEventType, currentProgress: Float) {
+        if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_USER) {
+            if (!bookendReached(currentProgress)) {
+                setState(SliderState.DRAG_HANDLE_DRAGGING)
+            }
+        } else if (newEventType == SliderEventType.STOPPED_TRACKING_TOUCH) {
+            setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
+        }
+    }
+
+    private fun handleJumpToTrack(newEventType: SliderEventType) {
+        when (newEventType) {
+            SliderEventType.PROGRESS_CHANGE_BY_USER -> setState(SliderState.DRAG_HANDLE_DRAGGING)
+            SliderEventType.STOPPED_TRACKING_TOUCH ->
+                setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
+            else -> {}
+        }
+    }
+
+    private fun handleJumpToBookend(newEventType: SliderEventType) {
+        when (newEventType) {
+            SliderEventType.PROGRESS_CHANGE_BY_USER -> setState(SliderState.DRAG_HANDLE_DRAGGING)
+            SliderEventType.STOPPED_TRACKING_TOUCH ->
+                setState(SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH)
+            else -> {}
+        }
+    }
+
+    override fun executeOnState(currentState: SliderState) {
+        when (currentState) {
+            SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH -> sliderListener.onHandleAcquiredByTouch()
+            SliderState.DRAG_HANDLE_RELEASED_FROM_TOUCH -> {
+                sliderListener.onHandleReleasedFromTouch()
+                // This transitory state must also reset the state machine
+                resetState()
+            }
+            SliderState.DRAG_HANDLE_DRAGGING -> sliderListener.onProgress(latestProgress)
+            SliderState.DRAG_HANDLE_REACHED_BOOKEND -> executeOnBookend()
+            SliderState.JUMP_TRACK_LOCATION_SELECTED ->
+                sliderListener.onProgressJump(latestProgress)
+            SliderState.ARROW_HANDLE_MOVED_ONCE -> sliderListener.onSelectAndArrow(latestProgress)
+            SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY -> sliderListener.onProgress(latestProgress)
+            SliderState.ARROW_HANDLE_REACHED_BOOKEND -> {
+                executeOnBookend()
+                // This transitory execution must also reset the state
+                resetState()
+            }
+            else -> {}
+        }
+    }
+
+    private fun executeOnBookend() {
+        if (latestProgress >= config.upperBookendThreshold) sliderListener.onUpperBookend()
+        else sliderListener.onLowerBookend()
+    }
+
+    override fun resetState() {
+        timerJob?.cancel()
+        timerJob = null
+        super.resetState()
+    }
+
+    private fun deltaProgressIsAboveThreshold(
+        currentProgress: Float,
+        epsilon: Float = 0.00001f,
+    ): Boolean {
+        val delta = abs(currentProgress - latestProgress)
+        return delta > config.jumpThreshold - epsilon
+    }
+
+    private fun bookendReached(currentProgress: Float): Boolean {
+        return currentProgress >= config.upperBookendThreshold ||
+            currentProgress <= config.lowerBookendThreshold
+    }
+
+    private fun handleArrowOnce(newEventType: SliderEventType) {
+        val nextState =
+            when (newEventType) {
+                SliderEventType.STARTED_TRACKING_TOUCH -> {
+                    // Launching the timer and going to WAIT
+                    timerJob = launchTimer()
+                    SliderState.WAIT
+                }
+                SliderEventType.PROGRESS_CHANGE_BY_PROGRAM ->
+                    SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
+                SliderEventType.STOPPED_TRACKING_PROGRAM -> SliderState.IDLE
+                else -> SliderState.ARROW_HANDLE_MOVED_ONCE
+            }
+        setState(nextState)
+    }
+
+    private fun handleArrowContinuous(newEventType: SliderEventType, currentProgress: Float) {
+        val reachedBookend = bookendReached(currentProgress)
+        val nextState =
+            when (newEventType) {
+                SliderEventType.STOPPED_TRACKING_PROGRAM -> SliderState.IDLE
+                SliderEventType.STARTED_TRACKING_TOUCH -> {
+                    // Launching the timer and going to WAIT
+                    timerJob = launchTimer()
+                    SliderState.WAIT
+                }
+                SliderEventType.PROGRESS_CHANGE_BY_PROGRAM -> {
+                    if (reachedBookend) SliderState.ARROW_HANDLE_REACHED_BOOKEND
+                    else SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
+                }
+                else -> SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
+            }
+        setState(nextState)
+    }
+
+    private fun handleArrowBookend() = setState(SliderState.IDLE)
+
+    @VisibleForTesting
+    fun setState(state: SliderState) {
+        currentState = state
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt
new file mode 100644
index 0000000..692fbb0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut
+
+import android.graphics.Insets
+import android.os.Bundle
+import android.view.View
+import android.view.WindowInsets
+import androidx.activity.BackEventCompat
+import androidx.activity.ComponentActivity
+import androidx.activity.OnBackPressedCallback
+import androidx.core.view.updatePadding
+import com.android.systemui.res.R
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
+
+/**
+ * Activity that hosts the new version of the keyboard shortcut helper. It will be used both for
+ * small and large screen devices.
+ */
+class ShortcutHelperActivity : ComponentActivity() {
+
+    private val bottomSheetContainer
+        get() = requireViewById<View>(R.id.shortcut_helper_sheet_container)
+
+    private val bottomSheet
+        get() = requireViewById<View>(R.id.shortcut_helper_sheet)
+
+    private val bottomSheetBehavior
+        get() = BottomSheetBehavior.from(bottomSheet)
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        setupEdgeToEdge()
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_keyboard_shortcut_helper)
+        setUpBottomSheetWidth()
+        setUpInsets()
+        setUpPredictiveBack()
+        setUpSheetDismissListener()
+        setUpDismissOnTouchOutside()
+    }
+
+    private fun setupEdgeToEdge() {
+        // Draw behind system bars
+        window.setDecorFitsSystemWindows(false)
+    }
+
+    private fun setUpBottomSheetWidth() {
+        val sheetScreenWidthFraction =
+            resources.getFloat(R.dimen.shortcut_helper_screen_width_fraction)
+        // maxWidth needs to be set before the sheet is drawn, otherwise the call will have no
+        // effect.
+        val screenWidth = resources.displayMetrics.widthPixels
+        bottomSheetBehavior.maxWidth = (sheetScreenWidthFraction * screenWidth).toInt()
+    }
+
+    private fun setUpInsets() {
+        bottomSheetContainer.setOnApplyWindowInsetsListener { _, insets ->
+            val safeDrawingInsets = insets.safeDrawing
+            // Make sure the bottom sheet is not covered by the status bar.
+            bottomSheetContainer.updatePadding(top = safeDrawingInsets.top)
+            // Make sure the contents inside of the bottom sheet are not hidden by system bars, or
+            // cutouts.
+            bottomSheet.updatePadding(
+                left = safeDrawingInsets.left,
+                right = safeDrawingInsets.right,
+                bottom = safeDrawingInsets.bottom
+            )
+            // The bottom sheet has to be expanded only after setting up insets, otherwise there is
+            // a bug and it will not use full height.
+            expandBottomSheet()
+
+            // Return CONSUMED if you don't want want the window insets to keep passing
+            // down to descendant views.
+            WindowInsets.CONSUMED
+        }
+    }
+
+    private fun expandBottomSheet() {
+        bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+        bottomSheetBehavior.skipCollapsed = true
+    }
+
+    private fun setUpPredictiveBack() {
+        val onBackPressedCallback =
+            object : OnBackPressedCallback(/* enabled= */ true) {
+                override fun handleOnBackStarted(backEvent: BackEventCompat) {
+                    bottomSheetBehavior.startBackProgress(backEvent)
+                }
+
+                override fun handleOnBackProgressed(backEvent: BackEventCompat) {
+                    bottomSheetBehavior.updateBackProgress(backEvent)
+                }
+
+                override fun handleOnBackPressed() {
+                    bottomSheetBehavior.handleBackInvoked()
+                }
+
+                override fun handleOnBackCancelled() {
+                    bottomSheetBehavior.cancelBackProgress()
+                }
+            }
+        onBackPressedDispatcher.addCallback(
+            owner = this,
+            onBackPressedCallback = onBackPressedCallback
+        )
+    }
+
+    private fun setUpSheetDismissListener() {
+        bottomSheetBehavior.addBottomSheetCallback(
+            object : BottomSheetCallback() {
+                override fun onStateChanged(bottomSheet: View, newState: Int) {
+                    if (newState == STATE_HIDDEN) {
+                        finish()
+                    }
+                }
+
+                override fun onSlide(bottomSheet: View, slideOffset: Float) {}
+            }
+        )
+    }
+
+    private fun setUpDismissOnTouchOutside() {
+        bottomSheetContainer.setOnClickListener { finish() }
+    }
+}
+
+private val WindowInsets.safeDrawing
+    get() =
+        getInsets(WindowInsets.Type.systemBars())
+            .union(getInsets(WindowInsets.Type.ime()))
+            .union(getInsets(WindowInsets.Type.displayCutout()))
+
+private fun Insets.union(insets: Insets): Insets = Insets.max(this, insets)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 6b53f4e..a5d7e04 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -63,6 +63,7 @@
 import android.view.WindowManagerPolicyConstants;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransitionStub;
 import android.window.TransitionInfo;
 
 import com.android.internal.annotations.GuardedBy;
@@ -187,7 +188,7 @@
     // Note: Also used for wrapping occlude by Dream animation. It works (with some redundancy).
     public static IRemoteTransition wrap(final KeyguardViewMediator keyguardViewMediator,
             final IRemoteAnimationRunner runner) {
-        return new IRemoteTransition.Stub() {
+        return new RemoteTransitionStub() {
 
             @GuardedBy("mLeashMap")
             private final ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = new ArrayMap<>();
@@ -253,11 +254,6 @@
                 }
             }
 
-            @Override
-            public void onTransitionConsumed(IBinder transition, boolean aborted) {
-                // No-op.
-            }
-
             private static void initAlphaForAnimationTargets(@NonNull SurfaceControl.Transaction t,
                     @NonNull RemoteAnimationTarget[] targets) {
                 for (RemoteAnimationTarget target : targets) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 9f7e0d4..c32c226 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -41,7 +41,6 @@
 import com.android.systemui.CoreStartable
 import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
@@ -73,7 +72,6 @@
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import dagger.Lazy
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
@@ -110,7 +108,6 @@
     private val keyguardBlueprintViewBinder: KeyguardBlueprintViewBinder,
     private val clockInteractor: KeyguardClockInteractor,
     private val keyguardViewMediator: KeyguardViewMediator,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
 ) : CoreStartable {
 
     private var rootViewHandle: DisposableHandle? = null
@@ -208,13 +205,12 @@
                 chipbarCoordinator,
                 screenOffAnimationController,
                 shadeInteractor,
-                { keyguardStatusViewController!!.getClockController() },
+                clockInteractor,
                 interactionJankMonitor,
                 deviceEntryHapticsInteractor,
                 vibratorHelper,
                 falsingManager,
                 keyguardViewMediator,
-                mainImmediateDispatcher,
             )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 654610e..46aec25 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -43,7 +43,6 @@
 import static com.android.systemui.Flags.notifyPowerManagerUserActivityBackground;
 import static com.android.systemui.Flags.refactorGetCurrentUser;
 import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
-import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -98,7 +97,6 @@
 import android.view.SyncRtSurfaceTransactionApplier;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicyConstants;
 import android.view.animation.Animation;
@@ -137,6 +135,7 @@
 import com.android.systemui.animation.TransitionAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor;
@@ -164,7 +163,6 @@
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 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.phone.ScrimController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -178,6 +176,10 @@
 import com.android.systemui.wallpapers.data.repository.WallpaperRepository;
 import com.android.wm.shell.keyguard.KeyguardTransitions;
 
+import dagger.Lazy;
+
+import kotlinx.coroutines.CoroutineDispatcher;
+
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -187,9 +189,6 @@
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
-import dagger.Lazy;
-import kotlinx.coroutines.CoroutineDispatcher;
-
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
  * state of the keyguard, power management events that effect whether the keyguard
@@ -584,7 +583,7 @@
 
     private CentralSurfaces mCentralSurfaces;
 
-    private IRemoteAnimationFinishedCallback mUnoccludeFromDreamFinishedCallback;
+    private IRemoteAnimationFinishedCallback mUnoccludeFinishedCallback;
 
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
@@ -1234,10 +1233,12 @@
                             mUnoccludeAnimator.cancel();
                         }
 
-                        if (isDream) {
+                        if (isDream || mShowCommunalByDefault) {
                             initAlphaForAnimationTargets(wallpapers);
-                            mDreamViewModel.get().startTransitionFromDream();
-                            mUnoccludeFromDreamFinishedCallback = finishedCallback;
+                            if (isDream) {
+                                mDreamViewModel.get().startTransitionFromDream();
+                            }
+                            mUnoccludeFinishedCallback = finishedCallback;
                             return;
                         }
 
@@ -1304,7 +1305,10 @@
 
     private Consumer<Float> getRemoteSurfaceAlphaApplier() {
         return (Float alpha) -> {
-            if (mRemoteAnimationTarget == null) return;
+            if (mRemoteAnimationTarget == null) {
+                Log.e(TAG, "Attempting to set alpha on null animation target");
+                return;
+            }
             final View localView = mKeyguardViewControllerLazy.get().getViewRootImpl().getView();
             final SyncRtSurfaceTransactionApplier applier =
                     new SyncRtSurfaceTransactionApplier(localView);
@@ -1319,10 +1323,10 @@
 
     private Consumer<TransitionStep> getFinishedCallbackConsumer() {
         return (TransitionStep step) -> {
-            if (mUnoccludeFromDreamFinishedCallback == null) return;
+            if (mUnoccludeFinishedCallback == null) return;
             try {
-                mUnoccludeFromDreamFinishedCallback.onAnimationFinished();
-                mUnoccludeFromDreamFinishedCallback = null;
+                mUnoccludeFinishedCallback.onAnimationFinished();
+                mUnoccludeFinishedCallback = null;
             } catch (RemoteException e) {
                 Log.e(TAG, "Wasn't able to callback", e);
             }
@@ -1365,7 +1369,9 @@
     private final SessionTracker mSessionTracker;
     private final CoroutineDispatcher mMainDispatcher;
     private final Lazy<DreamViewModel> mDreamViewModel;
+    private final Lazy<CommunalTransitionViewModel> mCommunalTransitionViewModel;
     private RemoteAnimationTarget mRemoteAnimationTarget;
+    private boolean mShowCommunalByDefault = false;
 
     private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager;
 
@@ -1414,6 +1420,7 @@
             SystemClock systemClock,
             @Main CoroutineDispatcher mainDispatcher,
             Lazy<DreamViewModel> dreamViewModel,
+            Lazy<CommunalTransitionViewModel> communalTransitionViewModel,
             SystemPropertiesHelper systemPropertiesHelper,
             Lazy<WindowManagerLockscreenVisibilityManager> wmLockscreenVisibilityManager,
             SelectedUserInteractor selectedUserInteractor,
@@ -1485,6 +1492,7 @@
         mSessionTracker = sessionTracker;
 
         mDreamViewModel = dreamViewModel;
+        mCommunalTransitionViewModel = communalTransitionViewModel;
         mWmLockscreenVisibilityManager = wmLockscreenVisibilityManager;
         mMainDispatcher = mainDispatcher;
 
@@ -1613,14 +1621,18 @@
             adjustStatusBarLocked();
             mDreamOverlayStateController.addCallback(mDreamOverlayStateCallback);
 
-            ViewRootImpl viewRootImpl = mKeyguardViewControllerLazy.get().getViewRootImpl();
-            if (viewRootImpl != null) {
-                final DreamViewModel viewModel = mDreamViewModel.get();
-                collectFlow(viewRootImpl.getView(), viewModel.getDreamAlpha(),
-                        getRemoteSurfaceAlphaApplier(), mMainDispatcher);
-                collectFlow(viewRootImpl.getView(), viewModel.getTransitionEnded(),
-                        getFinishedCallbackConsumer(), mMainDispatcher);
-            }
+            final DreamViewModel dreamViewModel = mDreamViewModel.get();
+            final CommunalTransitionViewModel communalViewModel =
+                    mCommunalTransitionViewModel.get();
+
+            mJavaAdapter.alwaysCollectFlow(dreamViewModel.getDreamAlpha(),
+                    getRemoteSurfaceAlphaApplier());
+            mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitionEnded(),
+                    getFinishedCallbackConsumer());
+            mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowByDefault(),
+                    (showByDefault) -> mShowCommunalByDefault = showByDefault);
+            mJavaAdapter.alwaysCollectFlow(communalViewModel.getTransitionFromOccludedEnded(),
+                    getFinishedCallbackConsumer());
         }
         // Most services aren't available until the system reaches the ready state, so we
         // send it here when the device first boots.
@@ -3322,12 +3334,12 @@
                 flags |= KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
             }
 
+            mKeyguardStateController.notifyKeyguardGoingAway(true);
+
             if (!KeyguardWmStateRefactor.isEnabled()) {
                 // Handled in WmLockscreenVisibilityManager.
                 mActivityTaskManagerService.keyguardGoingAway(flags);
             }
-
-            mKeyguardStateController.notifyKeyguardGoingAway(true);
         } catch (RemoteException e) {
             mSurfaceBehindRemoteAnimationRequested = false;
             e.printStackTrace();
@@ -3539,15 +3551,14 @@
             ShadeLockscreenInteractor shadeLockscreenInteractor,
             @Nullable ShadeExpansionStateManager shadeExpansionStateManager,
             BiometricUnlockController biometricUnlockController,
-            View notificationContainer, KeyguardBypassController bypassController) {
+            View notificationContainer) {
         mCentralSurfaces = centralSurfaces;
         mKeyguardViewControllerLazy.get().registerCentralSurfaces(
                 centralSurfaces,
                 shadeLockscreenInteractor,
                 shadeExpansionStateManager,
                 biometricUnlockController,
-                notificationContainer,
-                bypassController);
+                notificationContainer);
         return mKeyguardViewControllerLazy.get();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt
index e101b0a..a65a882 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.utils.GlobalWindowManager
@@ -83,7 +84,7 @@
 
         applicationScope.launch(bgDispatcher) {
             // We drop 1 to avoid triggering on initial collect().
-            keyguardTransitionInteractor.anyStateToGoneTransition.collect { transition ->
+            keyguardTransitionInteractor.transition(to = GONE).collect { transition ->
                 if (transition.transitionState == TransitionState.FINISHED) {
                     onKeyguardGone()
                 }
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 a243b8e..7879ab6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -39,6 +39,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.classifier.FalsingModule;
+import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -161,6 +162,7 @@
             SystemClock systemClock,
             @Main CoroutineDispatcher mainDispatcher,
             Lazy<DreamViewModel> dreamViewModel,
+            Lazy<CommunalTransitionViewModel> communalTransitionViewModel,
             SystemPropertiesHelper systemPropertiesHelper,
             Lazy<WindowManagerLockscreenVisibilityManager> wmLockscreenVisibilityManager,
             SelectedUserInteractor selectedUserInteractor,
@@ -208,6 +210,7 @@
                 systemClock,
                 mainDispatcher,
                 dreamViewModel,
+                communalTransitionViewModel,
                 systemPropertiesHelper,
                 wmLockscreenVisibilityManager,
                 selectedUserInteractor,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
index 2bede977..0ebc92e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
@@ -259,7 +259,6 @@
                                 if (biometricSourceType != BiometricSourceType.FINGERPRINT) {
                                     return
                                 }
-
                                 trySendWithFailureLogging(
                                     authenticationStatus,
                                     TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
index 3f4d3a8..7087752 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
@@ -16,17 +16,21 @@
 
 package com.android.systemui.keyguard.data.repository
 
+import android.content.Context
 import android.os.UserHandle
 import android.provider.Settings
 import com.android.keyguard.ClockEventController
-import com.android.keyguard.KeyguardClockSwitch.ClockSize
-import com.android.keyguard.KeyguardClockSwitch.LARGE
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.systemui.util.settings.SecureSettings
 import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
@@ -47,11 +51,15 @@
 import kotlinx.coroutines.withContext
 
 interface KeyguardClockRepository {
-    /** clock size determined by notificationPanelViewController, LARGE or SMALL */
-    val clockSize: StateFlow<Int>
+    /**
+     * clock size determined by notificationPanelViewController, LARGE or SMALL
+     *
+     * @deprecated When scene container flag is on use clockSize from domain level.
+     */
+    val clockSize: StateFlow<ClockSize>
 
     /** clock size selected in picker, DYNAMIC or SMALL */
-    val selectedClockSize: StateFlow<SettingsClockSize>
+    val selectedClockSize: StateFlow<ClockSizeSetting>
 
     /** clock id, selected from clock carousel in wallpaper picker */
     val currentClockId: Flow<ClockId>
@@ -61,7 +69,10 @@
     val previewClock: Flow<ClockController>
 
     val clockEventController: ClockEventController
-    fun setClockSize(@ClockSize size: Int)
+
+    val shouldForceSmallClock: Boolean
+
+    fun setClockSize(size: ClockSize)
 }
 
 @SysUISingleton
@@ -73,17 +84,20 @@
     override val clockEventController: ClockEventController,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     @Application private val applicationScope: CoroutineScope,
+    @Application private val applicationContext: Context,
+    private val featureFlags: FeatureFlagsClassic,
 ) : KeyguardClockRepository {
 
     /** Receive SMALL or LARGE clock should be displayed on keyguard. */
-    private val _clockSize: MutableStateFlow<Int> = MutableStateFlow(LARGE)
-    override val clockSize: StateFlow<Int> = _clockSize.asStateFlow()
+    private val _clockSize: MutableStateFlow<ClockSize> = MutableStateFlow(ClockSize.LARGE)
+    override val clockSize: StateFlow<ClockSize> = _clockSize.asStateFlow()
 
-    override fun setClockSize(size: Int) {
+    override fun setClockSize(size: ClockSize) {
+        SceneContainerFlag.assertInLegacyMode()
         _clockSize.value = size
     }
 
-    override val selectedClockSize: StateFlow<SettingsClockSize> =
+    override val selectedClockSize: StateFlow<ClockSizeSetting> =
         secureSettings
             .observerFlow(
                 names = arrayOf(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
@@ -135,17 +149,19 @@
             clockRegistry.createCurrentClock()
         }
 
-    private fun getClockSize(): SettingsClockSize {
-        return if (
+    override val shouldForceSmallClock: Boolean
+        get() =
+            featureFlags.isEnabled(Flags.LOCKSCREEN_ENABLE_LANDSCAPE) &&
+                // True on small landscape screens
+                applicationContext.resources.getBoolean(R.bool.force_small_clock_on_lockscreen)
+
+    private fun getClockSize(): ClockSizeSetting {
+        return ClockSizeSetting.fromSettingValue(
             secureSettings.getIntForUser(
                 Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
-                1,
+                /* defaultValue= */ 1,
                 UserHandle.USER_CURRENT
-            ) == 1
-        ) {
-            SettingsClockSize.DYNAMIC
-        } else {
-            SettingsClockSize.SMALL
-        }
+            )
+        )
     }
 }
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 1298fa5..462d837 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
@@ -206,7 +206,11 @@
     )
     val keyguardDoneAnimationsFinished: Flow<Unit>
 
-    /** Receive whether clock should be centered on lockscreen. */
+    /**
+     * Receive whether clock should be centered on lockscreen.
+     *
+     * @deprecated When scene container flag is on use clockShouldBeCentered from domain level.
+     */
     val clockShouldBeCentered: Flow<Boolean>
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt
index bf1f074..eef4b97 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt
@@ -27,7 +27,7 @@
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -52,7 +52,6 @@
     @Application private val applicationScope: CoroutineScope,
     @Application private val context: Context,
     deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
-    private val sceneContainerFlags: SceneContainerFlags,
     private val sceneInteractor: SceneInteractor,
     private val primaryBouncerInteractor: PrimaryBouncerInteractor,
     alternateBouncerInteractor: AlternateBouncerInteractor,
@@ -75,7 +74,7 @@
         get() = context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
 
     private val isBouncerSceneActive: Flow<Boolean> =
-        if (sceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled) {
             sceneInteractor.currentScene.map { it == Scenes.Bouncer }.distinctUntilChanged()
         } else {
             flowOf(false)
@@ -115,7 +114,7 @@
             .distinctUntilChanged()
 
     private fun isBouncerActive(): Boolean {
-        if (sceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled) {
             return sceneInteractor.currentScene.value == Scenes.Bouncer
         }
         return primaryBouncerInteractor.isBouncerShowing() &&
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt
index af1802f..d04e4f1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt
@@ -19,6 +19,10 @@
 import android.graphics.Point
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import dagger.Lazy
 import javax.inject.Inject
 
 @SysUISingleton
@@ -26,7 +30,16 @@
 @Inject
 constructor(
     private val keyguardRepository: KeyguardRepository,
+    // TODO(b/336364825) Remove Lazy when SceneContainerFlag is released -
+    // while the flag is off, creating this object too early results in a crash
+    private val sceneInteractor: Lazy<SceneInteractor>,
 ) {
+    fun canDozeFromCurrentScene(): Boolean {
+        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+            return false
+        }
+        return sceneInteractor.get().currentScene.value == Scenes.Lockscreen
+    }
 
     fun setAodAvailable(value: Boolean) {
         keyguardRepository.setAodAvailable(value)
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 dfe56c8..e441017 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
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard.domain.interactor
 
 import android.animation.ValueAnimator
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -26,20 +27,26 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
-import com.android.systemui.util.kotlin.sample as sampleUtil
 import com.android.wm.shell.animation.Interpolators
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.launch
 
+@ExperimentalCoroutinesApi
 @SysUISingleton
 class FromAlternateBouncerTransitionInteractor
 @Inject
@@ -53,6 +60,7 @@
     private val communalInteractor: CommunalInteractor,
     powerInteractor: PowerInteractor,
     keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
+    private val primaryBouncerInteractor: PrimaryBouncerInteractor,
 ) :
     TransitionInteractor(
         fromState = KeyguardState.ALTERNATE_BOUNCER,
@@ -102,13 +110,14 @@
                     keyguardInteractor.primaryBouncerShowing,
                     powerInteractor.isAwake,
                     keyguardInteractor.isAodAvailable,
-                    communalInteractor.isIdleOnCommunal
+                    communalInteractor.isIdleOnCommunal,
+                    keyguardInteractor.isKeyguardOccluded,
                 )
                 .filterRelevantKeyguardStateAnd {
                     (isAlternateBouncerShowing, isPrimaryBouncerShowing, _, _, _) ->
                     !isAlternateBouncerShowing && !isPrimaryBouncerShowing
                 }
-                .collect { (_, _, isAwake, isAodAvailable, isIdleOnCommunal) ->
+                .collect { (_, _, isAwake, isAodAvailable, isIdleOnCommunal, isOccluded) ->
                     val to =
                         if (!isAwake) {
                             if (isAodAvailable) {
@@ -119,6 +128,8 @@
                         } else {
                             if (isIdleOnCommunal) {
                                 KeyguardState.GLANCEABLE_HUB
+                            } else if (isOccluded) {
+                                KeyguardState.OCCLUDED
                             } else {
                                 KeyguardState.LOCKSCREEN
                             }
@@ -135,13 +146,18 @@
         }
 
         scope.launch {
-            keyguardInteractor.isKeyguardGoingAway
-                .sampleUtil(finishedKeyguardState, ::Pair)
-                .collect { (isKeyguardGoingAway, keyguardState) ->
-                    if (isKeyguardGoingAway && keyguardState == KeyguardState.ALTERNATE_BOUNCER) {
-                        startTransitionTo(KeyguardState.GONE)
+            merge(
+                    keyguardInteractor.isKeyguardGoingAway.filter { it }.map {}, // map to Unit
+                    keyguardInteractor.isKeyguardOccluded.flatMapLatest { keyguardOccluded ->
+                        if (keyguardOccluded) {
+                            primaryBouncerInteractor.keyguardAuthenticatedBiometricsHandled
+                        } else {
+                            emptyFlow()
+                        }
                     }
-                }
+                )
+                .filterRelevantKeyguardState()
+                .collect { startTransitionTo(KeyguardState.GONE) }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index f359525..c415081 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -19,6 +19,7 @@
 import android.animation.ValueAnimator
 import com.android.app.animation.Interpolators
 import com.android.app.tracing.coroutines.launch
+import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
@@ -28,6 +29,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.sample
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
@@ -47,6 +49,8 @@
     private val keyguardInteractor: KeyguardInteractor,
     powerInteractor: PowerInteractor,
     keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
+    private val lockPatternUtils: LockPatternUtils,
+    private val selectedUserInteractor: SelectedUserInteractor,
 ) :
     TransitionInteractor(
         fromState = KeyguardState.AOD,
@@ -79,9 +83,8 @@
                     startedKeyguardTransitionStep,
                     keyguardInteractor.biometricUnlockState,
                     keyguardInteractor.primaryBouncerShowing,
-                    keyguardInteractor.isKeyguardShowing,
                     keyguardInteractor.isKeyguardOccluded,
-                    keyguardInteractor.isKeyguardDismissible,
+                    selectedUserInteractor.selectedUser,
                 )
                 .collect {
                     (
@@ -89,10 +92,11 @@
                         startedStep,
                         biometricUnlockState,
                         primaryBouncerShowing,
-                        _,
                         isKeyguardOccludedLegacy,
-                        _) ->
+                        currentUser,
+                    ) ->
                     if (!maybeHandleInsecurePowerGesture()) {
+                        val securityNone = lockPatternUtils.isLockScreenDisabled(currentUser)
                         val shouldTransitionToLockscreen =
                             if (KeyguardWmStateRefactor.isEnabled) {
                                 // Check with the superclass to see if an occlusion transition is
@@ -101,11 +105,13 @@
                                 // completes.
                                 !maybeStartTransitionToOccludedOrInsecureCamera() &&
                                     !isWakeAndUnlock(biometricUnlockState) &&
-                                    !primaryBouncerShowing
+                                    !primaryBouncerShowing &&
+                                    !securityNone
                             } else {
                                 !isKeyguardOccludedLegacy &&
                                     !isWakeAndUnlock(biometricUnlockState) &&
-                                    !primaryBouncerShowing
+                                    !primaryBouncerShowing &&
+                                    !securityNone
                             }
 
                         // With the refactor enabled, maybeStartTransitionToOccludedOrInsecureCamera
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 bef5ee5..69c2c78d 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
@@ -30,6 +30,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
+import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlin.time.Duration.Companion.seconds
@@ -64,6 +65,7 @@
     ) {
 
     override fun start() {
+        listenForDreamingToAlternateBouncer()
         listenForDreamingToOccluded()
         listenForDreamingToGoneWhenDismissable()
         listenForDreamingToGoneFromBiometricUnlock()
@@ -71,6 +73,17 @@
         listenForDreamingToAodOrDozing()
         listenForTransitionToCamera(scope, keyguardInteractor)
         listenForDreamingToGlanceableHub()
+        listenForDreamingToPrimaryBouncer()
+    }
+
+    private fun listenForDreamingToAlternateBouncer() {
+        scope.launch("$TAG#listenForDreamingToAlternateBouncer") {
+            keyguardInteractor.alternateBouncerShowing
+                .filterRelevantKeyguardStateAnd { isAlternateBouncerShowing ->
+                    isAlternateBouncerShowing
+                }
+                .collect { startTransitionTo(KeyguardState.ALTERNATE_BOUNCER) }
+        }
     }
 
     private fun listenForDreamingToGlanceableHub() {
@@ -84,6 +97,21 @@
         }
     }
 
+    private fun listenForDreamingToPrimaryBouncer() {
+        scope.launch {
+            keyguardInteractor.primaryBouncerShowing
+                .sample(startedKeyguardTransitionStep, ::Pair)
+                .collect { pair ->
+                    val (isBouncerShowing, lastStartedTransitionStep) = pair
+                    if (
+                        isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.DREAMING
+                    ) {
+                        startTransitionTo(KeyguardState.PRIMARY_BOUNCER)
+                    }
+                }
+        }
+    }
+
     fun startToLockscreenTransition() {
         scope.launch {
             KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode()
@@ -96,18 +124,6 @@
         }
     }
 
-    fun startToGlanceableHubTransition() {
-        scope.launch {
-            KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode()
-            if (
-                transitionInteractor.startedKeyguardState.replayCache.last() ==
-                    KeyguardState.DREAMING
-            ) {
-                startTransitionTo(KeyguardState.GLANCEABLE_HUB)
-            }
-        }
-    }
-
     @OptIn(FlowPreview::class)
     private fun listenForDreamingToOccluded() {
         if (KeyguardWmStateRefactor.isEnabled) {
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 b6289d4..ee589f4 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
@@ -87,12 +87,12 @@
             scope.launch {
                 keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop
                     .filterRelevantKeyguardStateAnd { onTop -> !onTop }
-                    .sample(communalInteractor.isIdleOnCommunal, ::Pair)
-                    .collect { (_, isIdleOnCommunal) ->
+                    .sample(communalInteractor.isIdleOnCommunal, communalInteractor.showByDefault)
+                    .collect { (_, isIdleOnCommunal, showCommunalByDefault) ->
                         // Occlusion signals come from the framework, and should interrupt any
                         // existing transition
                         val to =
-                            if (isIdleOnCommunal) {
+                            if (isIdleOnCommunal || showCommunalByDefault) {
                                 KeyguardState.GLANCEABLE_HUB
                             } else {
                                 KeyguardState.LOCKSCREEN
@@ -106,15 +106,16 @@
                     .sample(
                         keyguardInteractor.isKeyguardShowing,
                         communalInteractor.isIdleOnCommunal,
+                        communalInteractor.showByDefault,
                     )
-                    .filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _) ->
+                    .filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _, _) ->
                         !isOccluded && isShowing
                     }
-                    .collect { (_, _, isIdleOnCommunal) ->
+                    .collect { (_, _, isIdleOnCommunal, showCommunalByDefault) ->
                         // Occlusion signals come from the framework, and should interrupt any
                         // existing transition
                         val to =
-                            if (isIdleOnCommunal) {
+                            if (isIdleOnCommunal || showCommunalByDefault) {
                                 KeyguardState.GLANCEABLE_HUB
                             } else {
                                 KeyguardState.LOCKSCREEN
@@ -175,6 +176,7 @@
             duration =
                 when (toState) {
                     KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
+                    KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION
                     else -> DEFAULT_DURATION
                 }.inWholeMilliseconds
         }
@@ -184,6 +186,7 @@
         const val TAG = "FromOccludedTransitionInteractor"
         private val DEFAULT_DURATION = 500.milliseconds
         val TO_LOCKSCREEN_DURATION = 933.milliseconds
+        val TO_GLANCEABLE_HUB_DURATION = 250.milliseconds
         val TO_AOD_DURATION = DEFAULT_DURATION
         val TO_DOZING_DURATION = DEFAULT_DURATION
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
index d39bd3d..da4f85e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -31,15 +31,14 @@
 import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type
-import com.android.systemui.statusbar.policy.SplitShadeStateController
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
-import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.launch
 
 @SysUISingleton
@@ -49,14 +48,13 @@
     private val keyguardBlueprintRepository: KeyguardBlueprintRepository,
     @Application private val applicationScope: CoroutineScope,
     private val context: Context,
-    private val splitShadeStateController: SplitShadeStateController,
+    private val shadeInteractor: ShadeInteractor,
     private val clockInteractor: KeyguardClockInteractor,
     configurationInteractor: ConfigurationInteractor,
     fingerprintPropertyInteractor: FingerprintPropertyInteractor,
 ) {
-
     /** The current blueprint for the lockscreen. */
-    val blueprint: Flow<KeyguardBlueprint> = keyguardBlueprintRepository.blueprint
+    val blueprint: StateFlow<KeyguardBlueprint> = keyguardBlueprintRepository.blueprint
 
     /**
      * Triggered when the blueprint isn't changed, but the ConstraintSet should be rebuilt and
@@ -64,39 +62,23 @@
      */
     val refreshTransition = keyguardBlueprintRepository.refreshTransition
 
-    private val configOrPropertyChange =
-        merge(
+    /** Current BlueprintId */
+    val blueprintId =
+        combine(
             configurationInteractor.onAnyConfigurationChange,
-            fingerprintPropertyInteractor.propertiesInitialized.filter { it }.map {}, // map to Unit
-        )
-    init {
-        applicationScope.launch {
-            configOrPropertyChange.onStart { emit(Unit) }.collect { updateBlueprint() }
-        }
-        applicationScope.launch { clockInteractor.currentClock.collect { updateBlueprint() } }
-    }
-
-    /**
-     * Detects when a new blueprint should be applied and calls [transitionToBlueprint]. This may
-     * end up reapplying the same blueprint, which is fine as configuration may have changed.
-     */
-    private fun updateBlueprint() {
-        val useSplitShade =
-            splitShadeStateController.shouldUseSplitNotificationShade(context.resources)
-        // TODO(b/326098079): Make ID a constant value.
-        val useWeatherClockLayout =
-            clockInteractor.currentClock.value?.config?.id == "DIGITAL_CLOCK_WEATHER" &&
-                ComposeLockscreen.isEnabled
-
-        val blueprintId =
+            fingerprintPropertyInteractor.propertiesInitialized.filter { it },
+            clockInteractor.currentClock,
+            shadeInteractor.shadeMode,
+        ) { _, _, _, shadeMode ->
+            val useSplitShade = shadeMode == ShadeMode.Split && !ComposeLockscreen.isEnabled
             when {
-                useWeatherClockLayout && useSplitShade -> SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-                useWeatherClockLayout -> WEATHER_CLOCK_BLUEPRINT_ID
-                useSplitShade && !ComposeLockscreen.isEnabled -> SplitShadeKeyguardBlueprint.ID
+                useSplitShade -> SplitShadeKeyguardBlueprint.ID
                 else -> DefaultKeyguardBlueprint.DEFAULT
             }
+        }
 
-        transitionToBlueprint(blueprintId)
+    init {
+        applicationScope.launch { blueprintId.collect { transitionToBlueprint(it) } }
     }
 
     /**
@@ -128,13 +110,4 @@
     fun getCurrentBlueprint(): KeyguardBlueprint {
         return keyguardBlueprintRepository.blueprint.value
     }
-
-    companion object {
-        /**
-         * These values live here because classes in the composable package do not exist in some
-         * systems.
-         */
-        const val WEATHER_CLOCK_BLUEPRINT_ID = "weather-clock"
-        const val SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID = "split-shade-weather-clock"
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index 99b691e..142b1a0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -17,27 +17,52 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import android.util.Log
 import com.android.keyguard.ClockEventController
-import com.android.keyguard.KeyguardClockSwitch.ClockSize
+import com.android.keyguard.KeyguardClockSwitch
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
+import com.android.systemui.util.kotlin.combine
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
 
 private val TAG = KeyguardClockInteractor::class.simpleName
-/** Manages and ecapsulates the clock components of the lockscreen root view. */
+/** Manages and encapsulates the clock components of the lockscreen root view. */
 @SysUISingleton
 class KeyguardClockInteractor
 @Inject
 constructor(
-    private val keyguardClockRepository: KeyguardClockRepository,
+    mediaCarouselInteractor: MediaCarouselInteractor,
+    activeNotificationsInteractor: ActiveNotificationsInteractor,
+    shadeInteractor: ShadeInteractor,
+    keyguardInteractor: KeyguardInteractor,
+    keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    headsUpNotificationInteractor: HeadsUpNotificationInteractor,
+    @Application private val applicationScope: CoroutineScope,
+    val keyguardClockRepository: KeyguardClockRepository,
 ) {
+    private val isOnAod: Flow<Boolean> =
+        keyguardTransitionInteractor.currentKeyguardState.map { it == KeyguardState.AOD }
 
-    val selectedClockSize: StateFlow<SettingsClockSize> = keyguardClockRepository.selectedClockSize
+    val selectedClockSize: StateFlow<ClockSizeSetting> = keyguardClockRepository.selectedClockSize
 
     val currentClockId: Flow<ClockId> = keyguardClockRepository.currentClockId
 
@@ -49,11 +74,78 @@
 
     var clock: ClockController? by keyguardClockRepository.clockEventController::clock
 
-    val clockSize: StateFlow<Int> = keyguardClockRepository.clockSize
-    fun setClockSize(@ClockSize size: Int) {
+    val clockSize: StateFlow<ClockSize> =
+        if (SceneContainerFlag.isEnabled) {
+            combine(
+                    shadeInteractor.shadeMode,
+                    activeNotificationsInteractor.areAnyNotificationsPresent,
+                    mediaCarouselInteractor.hasActiveMediaOrRecommendation,
+                    keyguardInteractor.isDozing,
+                    isOnAod,
+                ) { shadeMode, hasNotifs, hasMedia, isDozing, isOnAod ->
+                    return@combine when {
+                        keyguardClockRepository.shouldForceSmallClock && !isOnAod -> ClockSize.SMALL
+                        shadeMode == ShadeMode.Single && (hasNotifs || hasMedia) -> ClockSize.SMALL
+                        shadeMode == ShadeMode.Single -> ClockSize.LARGE
+                        hasMedia && !isDozing -> ClockSize.SMALL
+                        else -> ClockSize.LARGE
+                    }
+                }
+                .stateIn(
+                    scope = applicationScope,
+                    started = SharingStarted.WhileSubscribed(),
+                    initialValue = ClockSize.LARGE
+                )
+        } else {
+            keyguardClockRepository.clockSize
+        }
+
+    val clockShouldBeCentered: Flow<Boolean> =
+        if (SceneContainerFlag.isEnabled) {
+            combine(
+                shadeInteractor.shadeMode,
+                activeNotificationsInteractor.areAnyNotificationsPresent,
+                keyguardInteractor.isActiveDreamLockscreenHosted,
+                isOnAod,
+                headsUpNotificationInteractor.isHeadsUpOrAnimatingAway,
+                keyguardInteractor.isDozing,
+            ) {
+                shadeMode,
+                areAnyNotificationsPresent,
+                isActiveDreamLockscreenHosted,
+                isOnAod,
+                isHeadsUp,
+                isDozing ->
+                when {
+                    shadeMode != ShadeMode.Split -> true
+                    !areAnyNotificationsPresent -> true
+                    isActiveDreamLockscreenHosted -> true
+                    // Pulsing notification appears on the right. Move clock left to avoid overlap.
+                    isHeadsUp && isDozing -> false
+                    else -> isOnAod
+                }
+            }
+        } else {
+            keyguardInteractor.clockShouldBeCentered
+        }
+
+    fun setClockSize(@KeyguardClockSwitch.ClockSize size: Int) =
+        setClockSize(ClockSize.fromLegacy(size))
+
+    fun setClockSize(size: ClockSize) {
+        SceneContainerFlag.assertInLegacyMode()
         keyguardClockRepository.setClockSize(size)
     }
 
+    val renderedClockId: ClockId
+        get() {
+            return clock?.let { clock -> clock.config.id }
+                ?: run {
+                    Log.e(TAG, "No clock is available")
+                    KeyguardClockSwitch.MISSING_CLOCK_ID
+                }
+        }
+
     fun animateFoldToAod(foldFraction: Float) {
         clock?.let { clock ->
             clock.smallClock.animations.fold(foldFraction)
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 2182fe3..d191768 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
@@ -44,7 +44,7 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.data.repository.ShadeRepository
 import com.android.systemui.statusbar.CommandQueue
@@ -84,7 +84,6 @@
     private val repository: KeyguardRepository,
     private val commandQueue: CommandQueue,
     powerInteractor: PowerInteractor,
-    sceneContainerFlags: SceneContainerFlags,
     bouncerRepository: KeyguardBouncerRepository,
     configurationInteractor: ConfigurationInteractor,
     shadeRepository: ShadeRepository,
@@ -210,7 +209,8 @@
                 keyguardTransitionInteractor
                     .transitionValue(GONE)
                     .map { it == 1f }
-                    .onStart { emit(false) },
+                    .onStart { emit(false) }
+                    .distinctUntilChanged(),
                 repository.topClippingBounds
             ) { _, isGone, topClippingBounds ->
                 if (!isGone) {
@@ -226,7 +226,7 @@
     val ambientIndicationVisible: Flow<Boolean> = repository.ambientIndicationVisible.asStateFlow()
 
     /** Whether the primary bouncer is showing or not. */
-    val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
+    @JvmField val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
 
     /** Whether the alternate bouncer is showing or not. */
     val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
@@ -330,7 +330,7 @@
 
     /** Whether to animate the next doze mode transition. */
     val animateDozingTransitions: Flow<Boolean> by lazy {
-        if (sceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled) {
             sceneInteractorProvider
                 .get()
                 .transitioningTo
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 8eb1a50..1e3eac8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -23,6 +23,7 @@
 import android.content.Intent
 import android.util.Log
 import com.android.app.tracing.coroutines.withContext
+import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.animation.Expandable
@@ -45,6 +46,9 @@
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
@@ -82,6 +86,7 @@
     private val biometricSettingsRepository: BiometricSettingsRepository,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     @Application private val appContext: Context,
+    private val sceneInteractor: Lazy<SceneInteractor>,
 ) {
 
     /**
@@ -102,7 +107,21 @@
         return combine(
             quickAffordanceAlwaysVisible(position),
             keyguardInteractor.isDozing,
-            keyguardInteractor.isKeyguardShowing,
+            if (SceneContainerFlag.isEnabled) {
+                sceneInteractor
+                    .get()
+                    .transitionState
+                    .map {
+                        when (it) {
+                            is ObservableTransitionState.Idle -> it.scene == Scenes.Lockscreen
+                            is ObservableTransitionState.Transition ->
+                                it.fromScene == Scenes.Lockscreen || it.toScene == Scenes.Lockscreen
+                        }
+                    }
+                    .distinctUntilChanged()
+            } else {
+                keyguardInteractor.isKeyguardShowing
+            },
             shadeInteractor.anyExpansion.map { it < 1.0f }.distinctUntilChanged(),
             biometricSettingsRepository.isCurrentUserInLockdown,
         ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible, isUserInLockdown ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt
index 67b5745..bb633b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt
@@ -24,8 +24,10 @@
 @SysUISingleton
 class KeyguardSmartspaceInteractor
 @Inject
-constructor(private val keyguardSmartspaceRepository: KeyguardSmartspaceRepository) {
-    var bcSmartspaceVisibility: StateFlow<Int> = keyguardSmartspaceRepository.bcSmartspaceVisibility
+constructor(
+    private val keyguardSmartspaceRepository: KeyguardSmartspaceRepository,
+) {
+    val bcSmartspaceVisibility: StateFlow<Int> = keyguardSmartspaceRepository.bcSmartspaceVisibility
 
     fun setBcSmartspaceVisibility(visibility: Int) {
         keyguardSmartspaceRepository.setBcSmartspaceVisibility(visibility)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt
index 80e94a2..20b7b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractor.kt
@@ -23,12 +23,14 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardSurfaceBehindModel
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor
+import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.kotlin.toPx
 import dagger.Lazy
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
 
 /**
  * Distance over which the surface behind the keyguard is animated in during a Y-translation
@@ -96,13 +98,21 @@
             .distinctUntilChanged()
 
     /**
+     * Whether a notification launch animation is running when we're not already in the GONE state.
+     */
+    private val isNotificationLaunchAnimationRunningOnKeyguard =
+        notificationLaunchInteractor.isLaunchAnimationRunning
+            .sample(transitionInteractor.finishedKeyguardState)
+            .map { it != KeyguardState.GONE }
+
+    /**
      * Whether we're animating the surface, or a notification launch animation is running (which
      * means we're going to animate the surface, even if animators aren't yet running).
      */
     val isAnimatingSurface =
         combine(
             repository.isAnimatingSurface,
-            notificationLaunchInteractor.isLaunchAnimationRunning
+            isNotificationLaunchAnimationRunningOnKeyguard,
         ) { animatingSurface, animatingLaunch ->
             animatingSurface || animatingLaunch
         }
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 68ea5d0..141cca3 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
@@ -21,6 +21,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.core.LogLevel.VERBOSE
 import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
 import javax.inject.Inject
@@ -69,9 +70,11 @@
             }
         }
 
-        scope.launch {
-            sharedNotificationContainerViewModel.bounds.collect {
-                logger.log(TAG, VERBOSE, "Notif: bounds", it)
+        if (!SceneContainerFlag.isEnabled) {
+            scope.launch {
+                sharedNotificationContainerViewModel.bounds.collect {
+                    logger.log(TAG, VERBOSE, "Notif: bounds", it)
+                }
             }
         }
 
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 97081d9..a18579d 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
@@ -20,19 +20,14 @@
 import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.Edge
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
-import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
-import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING_LOCKSCREEN_HOSTED
-import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
-import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
-import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
 import com.android.systemui.keyguard.shared.model.KeyguardState.OFF
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.shared.model.TransitionInfo
@@ -40,7 +35,6 @@
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.BufferOverflow
@@ -53,6 +47,7 @@
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
@@ -64,7 +59,6 @@
 @Inject
 constructor(
     @Application val scope: CoroutineScope,
-    @Main private val mainDispatcher: CoroutineDispatcher,
     private val keyguardRepository: KeyguardRepository,
     private val repository: KeyguardTransitionRepository,
     private val fromLockscreenTransitionInteractor: dagger.Lazy<FromLockscreenTransitionInteractor>,
@@ -75,14 +69,13 @@
         dagger.Lazy<FromAlternateBouncerTransitionInteractor>,
     private val fromDozingTransitionInteractor: dagger.Lazy<FromDozingTransitionInteractor>,
 ) {
-    private val TAG = this::class.simpleName
-
-    private val transitionValueCache = mutableMapOf<KeyguardState, MutableSharedFlow<Float>>()
+    private val transitionMap = mutableMapOf<Edge, MutableSharedFlow<TransitionStep>>()
 
     /**
      * Numerous flows are derived from, or care directly about, the transition value in and out of a
      * single state. This prevent the redundant filters from running.
      */
+    private val transitionValueCache = mutableMapOf<KeyguardState, MutableSharedFlow<Float>>()
     private fun getTransitionValueFlow(state: KeyguardState): MutableSharedFlow<Float> {
         return transitionValueCache.getOrPut(state) {
             MutableSharedFlow<Float>(
@@ -94,6 +87,7 @@
         }
     }
 
+    @Deprecated("Not performant - Use something else in this class")
     val transitions = repository.transitions
 
     /**
@@ -106,14 +100,14 @@
      * from when we were canceled.
      */
     val startedStepWithPrecedingStep =
-        transitions
+        repository.transitions
             .pairwise()
             .filter { it.newValue.transitionState == TransitionState.STARTED }
             .shareIn(scope, SharingStarted.Eagerly)
 
     init {
         // Collect non-canceled steps and emit transition values.
-        scope.launch(mainDispatcher) {
+        scope.launch {
             repository.transitions
                 .filter { it.transitionState != TransitionState.CANCELED }
                 .collect { step ->
@@ -122,11 +116,22 @@
                 }
         }
 
+        scope.launch {
+            repository.transitions.collect {
+                // FROM->TO
+                transitionMap[Edge(it.from, it.to)]?.emit(it)
+                // FROM->(ANY)
+                transitionMap[Edge(it.from, null)]?.emit(it)
+                // (ANY)->TO
+                transitionMap[Edge(null, it.to)]?.emit(it)
+            }
+        }
+
         // If a transition from state A -> B is canceled in favor of a transition from B -> C, we
         // need to ensure we emit transitionValue(A) = 0f, since no further steps will be emitted
         // where the from or to states are A. This would leave transitionValue(A) stuck at an
         // arbitrary non-zero value.
-        scope.launch(mainDispatcher) {
+        scope.launch {
             startedStepWithPrecedingStep.collect { (prevStep, startedStep) ->
                 if (
                     prevStep.transitionState == TransitionState.CANCELED &&
@@ -138,116 +143,42 @@
         }
     }
 
-    /** (any)->GONE transition information */
-    val anyStateToGoneTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == GONE }
-
-    /** (any)->AOD transition information */
-    val anyStateToAodTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == AOD }
-
-    /** DREAMING->(any) transition information. */
-    val fromDreamingTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.from == DREAMING }
-
-    /** LOCKSCREEN->(any) transition information. */
-    val fromLockscreenTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.from == LOCKSCREEN }
-
-    /** (any)->Lockscreen transition information */
-    val anyStateToLockscreenTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == LOCKSCREEN }
-
-    /** (any)->Occluded transition information */
-    val anyStateToOccludedTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == OCCLUDED }
-
-    /** (any)->PrimaryBouncer transition information */
-    val anyStateToPrimaryBouncerTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == PRIMARY_BOUNCER }
-
-    /** (any)->Dreaming transition information */
-    val anyStateToDreamingTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == DREAMING }
-
-    /** (any)->AlternateBouncer transition information */
-    val anyStateToAlternateBouncerTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == ALTERNATE_BOUNCER }
-
-    /** AOD->LOCKSCREEN transition information. */
-    val aodToLockscreenTransition: Flow<TransitionStep> = repository.transition(AOD, LOCKSCREEN)
-
-    /** DREAMING->LOCKSCREEN transition information. */
-    val dreamingToLockscreenTransition: Flow<TransitionStep> =
-        repository.transition(DREAMING, LOCKSCREEN)
-
-    /** DREAMING_LOCKSCREEN_HOSTED->LOCKSCREEN transition information. */
-    val dreamingLockscreenHostedToLockscreenTransition: Flow<TransitionStep> =
-        repository.transition(DREAMING_LOCKSCREEN_HOSTED, LOCKSCREEN)
-
-    /** GONE->AOD transition information. */
-    val goneToAodTransition: Flow<TransitionStep> = repository.transition(GONE, AOD)
-
-    /** GONE->DREAMING transition information. */
-    val goneToDreamingTransition: Flow<TransitionStep> = repository.transition(GONE, DREAMING)
-
-    /** GONE->DREAMING_LOCKSCREEN_HOSTED transition information. */
-    val goneToDreamingLockscreenHostedTransition: Flow<TransitionStep> =
-        repository.transition(GONE, DREAMING_LOCKSCREEN_HOSTED)
-
-    /** GONE->LOCKSCREEN transition information. */
-    val goneToLockscreenTransition: Flow<TransitionStep> = repository.transition(GONE, LOCKSCREEN)
-
-    /** LOCKSCREEN->AOD transition information. */
-    val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
-
-    /** LOCKSCREEN->DOZING transition information. */
-    val lockscreenToDozingTransition: Flow<TransitionStep> =
-        repository.transition(LOCKSCREEN, DOZING)
-
-    /** LOCKSCREEN->DREAMING transition information. */
-    val lockscreenToDreamingTransition: Flow<TransitionStep> =
-        repository.transition(LOCKSCREEN, DREAMING)
-
-    /** LOCKSCREEN->DREAMING_LOCKSCREEN_HOSTED transition information. */
-    val lockscreenToDreamingLockscreenHostedTransition: Flow<TransitionStep> =
-        repository.transition(LOCKSCREEN, DREAMING_LOCKSCREEN_HOSTED)
-
-    /** LOCKSCREEN->GLANCEABLE_HUB transition information. */
-    val lockscreenToGlanceableHubTransition: Flow<TransitionStep> =
-        repository.transition(LOCKSCREEN, GLANCEABLE_HUB)
-
-    /** LOCKSCREEN->OCCLUDED transition information. */
-    val lockscreenToOccludedTransition: Flow<TransitionStep> =
-        repository.transition(LOCKSCREEN, OCCLUDED)
-
-    /** GLANCEABLE_HUB->LOCKSCREEN transition information. */
-    val glanceableHubToLockscreenTransition: Flow<TransitionStep> =
-        repository.transition(GLANCEABLE_HUB, LOCKSCREEN)
-
-    /** OCCLUDED->LOCKSCREEN transition information. */
-    val occludedToLockscreenTransition: Flow<TransitionStep> =
-        repository.transition(OCCLUDED, LOCKSCREEN)
-
-    /** PRIMARY_BOUNCER->GONE transition information. */
-    val primaryBouncerToGoneTransition: Flow<TransitionStep> =
-        repository.transition(PRIMARY_BOUNCER, GONE)
-
-    /** OFF->LOCKSCREEN transition information. */
-    val offToLockscreenTransition: Flow<TransitionStep> = repository.transition(OFF, LOCKSCREEN)
-
-    /** DOZING->LOCKSCREEN transition information. */
-    val dozingToLockscreenTransition: Flow<TransitionStep> =
-        repository.transition(DOZING, LOCKSCREEN)
-
-    /** Receive all [TransitionStep] matching a filter of [from]->[to] */
-    fun transition(from: KeyguardState, to: KeyguardState): Flow<TransitionStep> {
-        return repository.transition(from, to)
+    /** Given an [edge], return a SharedFlow to collect only relevant [TransitionStep]. */
+    fun getOrCreateFlow(edge: Edge): MutableSharedFlow<TransitionStep> {
+        return transitionMap.getOrPut(edge) {
+            MutableSharedFlow<TransitionStep>(
+                extraBufferCapacity = 10,
+                onBufferOverflow = BufferOverflow.DROP_OLDEST
+            )
+        }
     }
 
     /**
-     * AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
-     * Lockscreen (0f).
+     * Receive all [TransitionStep] matching a filter of [from]->[to]. Allow nulls in order to match
+     * any transition, for instance (any)->GONE.
+     */
+    fun transition(from: KeyguardState? = null, to: KeyguardState? = null): Flow<TransitionStep> {
+        if (from == null && to == null) {
+            throw IllegalArgumentException("from and to cannot both be null")
+        }
+        return getOrCreateFlow(Edge(from = from, to = to))
+    }
+
+    /**
+     * The amount of transition into or out of the given [KeyguardState].
+     *
+     * The value will be `0` (or close to `0`, due to float point arithmetic) if not in this step or
+     * `1` when fully in the given state.
+     */
+    fun transitionValue(
+        state: KeyguardState,
+    ): Flow<Float> {
+        return getTransitionValueFlow(state)
+    }
+
+    /**
+     * AOD<->* transition information, mapped to dozeAmount range of AOD (1f) <->
+     * * (0f).
      */
     val dozeAmountTransition: Flow<TransitionStep> =
         repository.transitions
@@ -265,10 +196,6 @@
     val startedKeyguardTransitionStep: Flow<TransitionStep> =
         repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
 
-    /** The last [TransitionStep] with a [TransitionState] of CANCELED */
-    val canceledKeyguardTransitionStep: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.transitionState == TransitionState.CANCELED }
-
     /** The last [TransitionStep] with a [TransitionState] of FINISHED */
     val finishedKeyguardTransitionStep: Flow<TransitionStep> =
         repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
@@ -364,10 +291,6 @@
      * case, the smartspace will never be set to alpha = 1f and you'll have a half-faded smartspace
      * during the LS -> GONE transition.
      *
-     * If you need special-case handling for cancellations (such as conditional handling depending
-     * on which [KeyguardState] was canceled) you can collect [canceledKeyguardTransitionStep]
-     * directly.
-     *
      * As a helpful footnote, here's the values of [finishedKeyguardState] and
      * [currentKeyguardState] during a sequence with two cancellations:
      * 1. We're FINISHED in GONE. currentKeyguardState=GONE; finishedKeyguardState=GONE.
@@ -390,7 +313,7 @@
                 }
             }
             .distinctUntilChanged()
-            .shareIn(scope, SharingStarted.Eagerly, replay = 1)
+            .stateIn(scope, SharingStarted.Eagerly, KeyguardState.OFF)
 
     /**
      * The [TransitionInfo] of the most recent call to
@@ -420,24 +343,12 @@
     /** Whether we've currently STARTED a transition and haven't yet FINISHED it. */
     val isInTransitionToAnyState = isInTransitionWhere({ true }, { true })
 
-    /**
-     * The amount of transition into or out of the given [KeyguardState].
-     *
-     * The value will be `0` (or close to `0`, due to float point arithmetic) if not in this step or
-     * `1` when fully in the given state.
-     */
-    fun transitionValue(
-        state: KeyguardState,
-    ): Flow<Float> {
-        return getTransitionValueFlow(state)
-    }
-
     fun transitionStepsFromState(fromState: KeyguardState): Flow<TransitionStep> {
-        return repository.transitions.filter { step -> step.from == fromState }
+        return getOrCreateFlow(Edge(from = fromState, to = null))
     }
 
     fun transitionStepsToState(toState: KeyguardState): Flow<TransitionStep> {
-        return repository.transitions.filter { step -> step.to == toState }
+        return getOrCreateFlow(Edge(from = null, to = toState))
     }
 
     /**
@@ -464,17 +375,24 @@
     fun isInTransitionToState(
         state: KeyguardState,
     ): Flow<Boolean> {
-        return isInTransitionToStateWhere { it == state }
+        return getOrCreateFlow(Edge(from = null, to = state))
+            .mapLatest { it.transitionState.isTransitioning() }
+            .onStart { emit(false) }
+            .distinctUntilChanged()
     }
 
     /**
-     * Whether we're in a transition to a [KeyguardState] that matches the given predicate, but
-     * haven't yet completed it.
+     * Whether we're in a transition to and from the given [KeyguardState]s, but haven't yet
+     * completed it.
      */
-    fun isInTransitionToStateWhere(
-        stateMatcher: (KeyguardState) -> Boolean,
+    fun isInTransition(
+        from: KeyguardState,
+        to: KeyguardState,
     ): Flow<Boolean> {
-        return isInTransitionWhere(fromStatePredicate = { true }, toStatePredicate = stateMatcher)
+        return getOrCreateFlow(Edge(from = from, to = to))
+            .mapLatest { it.transitionState.isTransitioning() }
+            .onStart { emit(false) }
+            .distinctUntilChanged()
     }
 
     /**
@@ -483,12 +401,29 @@
     fun isInTransitionFromState(
         state: KeyguardState,
     ): Flow<Boolean> {
-        return isInTransitionFromStateWhere { it == state }
+        return getOrCreateFlow(Edge(from = state, to = null))
+            .mapLatest { it.transitionState.isTransitioning() }
+            .onStart { emit(false) }
+            .distinctUntilChanged()
+    }
+
+    /**
+     * Whether we're in a transition to a [KeyguardState] that matches the given predicate, but
+     * haven't yet completed it.
+     *
+     * If you only care about a single state, instead use the optimized [isInTransitionToState].
+     */
+    fun isInTransitionToStateWhere(
+        stateMatcher: (KeyguardState) -> Boolean,
+    ): Flow<Boolean> {
+        return isInTransitionWhere(fromStatePredicate = { true }, toStatePredicate = stateMatcher)
     }
 
     /**
      * Whether we're in a transition out of a [KeyguardState] that matches the given predicate, but
      * haven't yet completed it.
+     *
+     * If you only care about a single state, instead use the optimized [isInTransitionFromState].
      */
     fun isInTransitionFromStateWhere(
         stateMatcher: (KeyguardState) -> Boolean,
@@ -499,6 +434,9 @@
     /**
      * Whether we're in a transition between two [KeyguardState]s that match the given predicates,
      * but haven't yet completed it.
+     *
+     * If you only care about a single state for both from and to, instead use the optimized
+     * [isInTransition].
      */
     fun isInTransitionWhere(
         fromStatePredicate: (KeyguardState) -> Boolean,
@@ -507,6 +445,13 @@
         return isInTransitionWhere { from, to -> fromStatePredicate(from) && toStatePredicate(to) }
     }
 
+    /**
+     * Whether we're in a transition between two [KeyguardState]s that match the given predicates,
+     * but haven't yet completed it.
+     *
+     * If you only care about a single state for both from and to, instead use the optimized
+     * [isInTransition].
+     */
     fun isInTransitionWhere(
         fromToStatePredicate: (KeyguardState, KeyguardState) -> Boolean
     ): Flow<Boolean> {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
index e456a55..2850165 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
@@ -224,20 +224,12 @@
     ) {
         if (!KeyguardWmStateRefactor.isEnabled) {
             scope.launch {
-                keyguardInteractor.onCameraLaunchDetected
-                    .sample(transitionInteractor.finishedKeyguardState)
-                    .collect { finishedKeyguardState ->
-                        // Other keyguard state transitions may trigger on the first power button
-                        // push,
-                        // so use the last finishedKeyguardState to determine the overriding FROM
-                        // state
-                        if (finishedKeyguardState == fromState) {
-                            startTransitionTo(
-                                toState = KeyguardState.OCCLUDED,
-                                modeOnCanceled = TransitionModeOnCanceled.RESET,
-                            )
-                        }
-                    }
+                keyguardInteractor.onCameraLaunchDetected.filterRelevantKeyguardState().collect {
+                    startTransitionTo(
+                        toState = KeyguardState.OCCLUDED,
+                        modeOnCanceled = TransitionModeOnCanceled.RESET,
+                    )
+                }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt
new file mode 100644
index 0000000..a43eb71
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.shared
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for reading or using the refactor_keyguard_dismiss_intent flag. */
+@Suppress("NOTHING_TO_INLINE")
+object RefactorKeyguardDismissIntent {
+    /** The aconfig flag name */
+    const val FLAG_NAME = Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
+
+    /** A token used for dependency declaration */
+    val token: FlagToken
+        get() = FlagToken(FLAG_NAME, isEnabled)
+
+    /** Is the refactor enabled */
+    @JvmStatic
+    inline val isEnabled
+        get() = Flags.refactorKeyguardDismissIntent()
+
+    /**
+     * Called to ensure code is only run when the flag is enabled. This protects users from the
+     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+     * build to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun isUnexpectedlyInLegacyMode() =
+        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+    /**
+     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+     * the flag is enabled to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.kt
new file mode 100644
index 0000000..b661297
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.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.keyguard.shared.model
+
+import android.util.Log
+import com.android.keyguard.KeyguardClockSwitch
+
+enum class ClockSize(
+    @KeyguardClockSwitch.ClockSize val legacyValue: Int,
+) {
+    SMALL(KeyguardClockSwitch.SMALL),
+    LARGE(KeyguardClockSwitch.LARGE);
+
+    companion object {
+        private val TAG = ClockSize::class.simpleName!!
+        fun fromLegacy(@KeyguardClockSwitch.ClockSize value: Int): ClockSize {
+            for (enumVal in enumValues<ClockSize>()) {
+                if (enumVal.legacyValue == value) {
+                    return enumVal
+                }
+            }
+
+            Log.e(TAG, "Unrecognized legacy clock size value: $value")
+            return LARGE
+        }
+    }
+}
+
+enum class ClockSizeSetting(
+    val settingValue: Int,
+) {
+    DYNAMIC(1),
+    SMALL(0);
+
+    companion object {
+        private val TAG = ClockSizeSetting::class.simpleName!!
+        fun fromSettingValue(value: Int): ClockSizeSetting {
+            for (enumVal in enumValues<ClockSizeSetting>()) {
+                if (enumVal.settingValue == value) {
+                    return enumVal
+                }
+            }
+
+            Log.e(TAG, "Unrecognized clock setting value: $value")
+            return DYNAMIC
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
index 3440440..7ca2eba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
@@ -35,16 +35,18 @@
      * @param bindData: Whether to bind the data or not.
      */
     fun replaceViews(
-        previousBlueprint: KeyguardBlueprint?,
         constraintLayout: ConstraintLayout,
+        previousBlueprint: KeyguardBlueprint? = null,
         bindData: Boolean = true
     ) {
-        previousBlueprint?.let { previousBlueprint ->
-            previousBlueprint.sections.subtract(sections).forEach {
-                it.removeViews(constraintLayout)
+        val prevSections =
+            previousBlueprint?.let { prev ->
+                prev.sections.subtract(sections).forEach { it.removeViews(constraintLayout) }
+                prev.sections
             }
-        }
-        sections.subtract((previousBlueprint?.sections ?: setOf()).toSet()).forEach {
+                ?: listOf()
+
+        sections.subtract(prevSections).forEach {
             it.addViews(constraintLayout)
             if (bindData) {
                 it.bindData(constraintLayout)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
index 92612b8..7d05539 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
@@ -87,6 +87,7 @@
         }
 
         /** Whether either of the bouncers are visible when we're FINISHED in the given state. */
+        @JvmStatic
         fun isBouncerState(state: KeyguardState): Boolean {
             return state == PRIMARY_BOUNCER || state == ALTERNATE_BOUNCER
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SettingsClockSize.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SettingsClockSize.kt
deleted file mode 100644
index c6b0f58..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SettingsClockSize.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.keyguard.shared.model
-
-enum class SettingsClockSize {
-    DYNAMIC,
-    SMALL,
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
index 38a93b5..1cd188c9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
@@ -18,11 +18,21 @@
 /** Possible states for a running transition between [State] */
 enum class TransitionState {
     /* Transition has begun. */
-    STARTED,
+    STARTED {
+        override fun isTransitioning() = true
+    },
     /* Transition is actively running. */
-    RUNNING,
+    RUNNING {
+        override fun isTransitioning() = true
+    },
     /* Transition has completed successfully. */
-    FINISHED,
+    FINISHED {
+        override fun isTransitioning() = false
+    },
     /* Transition has been interrupted, and not completed successfully. */
-    CANCELED,
+    CANCELED {
+        override fun isTransitioning() = false
+    };
+
+    abstract fun isTransitioning(): Boolean
 }
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 5de1a61..735b109 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -19,8 +19,6 @@
 import com.android.app.animation.Interpolators.LINEAR
 import com.android.keyguard.logging.KeyguardTransitionAnimationLogger
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.Edge
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -35,15 +33,10 @@
 import kotlin.math.min
 import kotlin.time.Duration
 import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.BufferOverflow
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapNotNull
-import kotlinx.coroutines.launch
 
 /**
  * Assists in creating sub-flows for a KeyguardTransition. Call [setup] once for a transition, and
@@ -53,35 +46,9 @@
 class KeyguardTransitionAnimationFlow
 @Inject
 constructor(
-    @Application private val scope: CoroutineScope,
-    @Main private val mainDispatcher: CoroutineDispatcher,
     private val transitionInteractor: KeyguardTransitionInteractor,
     private val logger: KeyguardTransitionAnimationLogger,
 ) {
-    private val transitionMap = mutableMapOf<Edge, MutableSharedFlow<TransitionStep>>()
-
-    init {
-        scope.launch(mainDispatcher) {
-            transitionInteractor.transitions.collect {
-                // FROM->TO
-                transitionMap[Edge(it.from, it.to)]?.emit(it)
-                // FROM->(ANY)
-                transitionMap[Edge(it.from, null)]?.emit(it)
-                // (ANY)->TO
-                transitionMap[Edge(null, it.to)]?.emit(it)
-            }
-        }
-    }
-
-    private fun getOrCreateFlow(edge: Edge): MutableSharedFlow<TransitionStep> {
-        return transitionMap.getOrPut(edge) {
-            MutableSharedFlow<TransitionStep>(
-                extraBufferCapacity = 10,
-                onBufferOverflow = BufferOverflow.DROP_OLDEST
-            )
-        }
-    }
-
     /** Invoke once per transition between FROM->TO states to get access to a shared flow. */
     fun setup(
         duration: Duration,
@@ -185,7 +152,8 @@
                 }?.let { onStep(interpolator.getInterpolation(it)) }
             }
 
-            return getOrCreateFlow(edge)
+            return transitionInteractor
+                .getOrCreateFlow(edge)
                 .map { step ->
                     StateToValue(
                             from = step.from,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt
new file mode 100644
index 0000000..8f5a6a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.ui.binder
+
+import android.os.Bundle
+import android.view.View
+import android.view.accessibility.AccessibilityNodeInfo
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.keyguard.ui.viewmodel.AccessibilityActionsViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.launch
+
+/** View binder for accessibility actions placeholder on keyguard. */
+object AccessibilityActionsViewBinder {
+    fun bind(
+        view: View,
+        viewModel: AccessibilityActionsViewModel,
+    ): DisposableHandle {
+        val disposableHandle =
+            view.repeatWhenAttached {
+                repeatOnLifecycle(Lifecycle.State.STARTED) {
+                    view.contentDescription =
+                        view.resources.getString(R.string.accessibility_desc_lock_screen)
+
+                    launch {
+                        viewModel.isOnKeyguard.collect { isOnKeyguard ->
+                            view.importantForAccessibility =
+                                if (isOnKeyguard) {
+                                    View.IMPORTANT_FOR_ACCESSIBILITY_YES
+                                } else {
+                                    // The border won't be displayed when keyguard is not showing or
+                                    // when the focus was previously on it but is now transitioning
+                                    // away from the keyguard.
+                                    View.IMPORTANT_FOR_ACCESSIBILITY_NO
+                                }
+                        }
+                    }
+
+                    launch {
+                        viewModel.isCommunalAvailable.collect { canOpenGlanceableHub ->
+                            view.accessibilityDelegate =
+                                object : View.AccessibilityDelegate() {
+                                    override fun onInitializeAccessibilityNodeInfo(
+                                        host: View,
+                                        info: AccessibilityNodeInfo
+                                    ) {
+                                        super.onInitializeAccessibilityNodeInfo(host, info)
+                                        // Add custom actions
+                                        if (canOpenGlanceableHub) {
+                                            val action =
+                                                AccessibilityNodeInfo.AccessibilityAction(
+                                                    R.id.accessibility_action_open_communal_hub,
+                                                    view.resources.getString(
+                                                        R.string
+                                                            .accessibility_action_open_communal_hub
+                                                    ),
+                                                )
+                                            info.addAction(action)
+                                        }
+                                    }
+
+                                    override fun performAccessibilityAction(
+                                        host: View,
+                                        action: Int,
+                                        args: Bundle?
+                                    ): Boolean {
+                                        return if (
+                                            action == R.id.accessibility_action_open_communal_hub
+                                        ) {
+                                            viewModel.openCommunalHub()
+                                            true
+                                        } else super.performAccessibilityAction(host, action, args)
+                                    }
+                                }
+                        }
+                    }
+                }
+            }
+        return disposableHandle
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index e423fe0..cccb93c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -25,7 +25,6 @@
 import androidx.core.view.isInvisible
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.tracing.coroutines.launch
 import com.android.systemui.common.ui.view.LongPressHandlingView
 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
@@ -35,15 +34,13 @@
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.statusbar.VibratorHelper
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
 
 @ExperimentalCoroutinesApi
 object DeviceEntryIconViewBinder {
 
-    private const val TAG = "DeviceEntryIconViewBinder"
-
     /**
      * Updates UI for:
      * - device entry containing view (parent view for the below views)
@@ -61,7 +58,6 @@
         bgViewModel: DeviceEntryBackgroundViewModel,
         falsingManager: FalsingManager,
         vibratorHelper: VibratorHelper,
-        mainImmediateDispatcher: CoroutineDispatcher,
     ) {
         DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode()
         val longPressHandlingView = view.longPressHandlingView
@@ -77,33 +73,31 @@
                         view,
                         HapticFeedbackConstants.CONFIRM,
                     )
-                    applicationScope.launch("$TAG#viewModel.onLongPress") {
-                        viewModel.onLongPress()
-                    }
+                    applicationScope.launch { viewModel.onLongPress() }
                 }
             }
 
-        view.repeatWhenAttached(mainImmediateDispatcher) {
+        view.repeatWhenAttached {
             // Repeat on CREATED so that the view will always observe the entire
             // GONE => AOD transition (even though the view may not be visible until the middle
             // of the transition.
             repeatOnLifecycle(Lifecycle.State.CREATED) {
-                launch("$TAG#viewModel.isVisible") {
+                launch {
                     viewModel.isVisible.collect { isVisible ->
                         longPressHandlingView.isInvisible = !isVisible
                     }
                 }
-                launch("$TAG#viewModel.isLongPressEnabled") {
+                launch {
                     viewModel.isLongPressEnabled.collect { isEnabled ->
                         longPressHandlingView.setLongPressHandlingEnabled(isEnabled)
                     }
                 }
-                launch("$TAG#viewModel.accessibilityDelegateHint") {
+                launch {
                     viewModel.accessibilityDelegateHint.collect { hint ->
                         view.accessibilityHintType = hint
                     }
                 }
-                launch("$TAG#viewModel.useBackgroundProtection") {
+                launch {
                     viewModel.useBackgroundProtection.collect { useBackgroundProtection ->
                         if (useBackgroundProtection) {
                             bgView.visibility = View.VISIBLE
@@ -112,7 +106,7 @@
                         }
                     }
                 }
-                launch("$TAG#viewModel.burnInOffsets") {
+                launch {
                     viewModel.burnInOffsets.collect { burnInOffsets ->
                         view.translationX = burnInOffsets.x.toFloat()
                         view.translationY = burnInOffsets.y.toFloat()
@@ -120,22 +114,22 @@
                     }
                 }
 
-                launch("$TAG#viewModel.deviceEntryViewAlpha") {
-                    viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha }
-                }
+                launch { viewModel.deviceEntryViewAlpha.collect { alpha -> view.alpha = alpha } }
             }
         }
 
-        fgIconView.repeatWhenAttached(mainImmediateDispatcher) {
+        fgIconView.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.STARTED) {
                 // Start with an empty state
                 fgIconView.setImageState(StateSet.NOTHING, /* merge */ false)
-                launch("$TAG#fgViewModel.viewModel") {
+                launch {
                     fgViewModel.viewModel.collect { viewModel ->
                         fgIconView.setImageState(
                             view.getIconState(viewModel.type, viewModel.useAodVariant),
                             /* merge */ false
                         )
+                        fgIconView.contentDescription =
+                            fgIconView.resources.getString(viewModel.type.contentDescriptionResId)
                         fgIconView.imageTintList = ColorStateList.valueOf(viewModel.tint)
                         fgIconView.setPadding(
                             viewModel.padding,
@@ -150,10 +144,8 @@
 
         bgView.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.CREATED) {
-                launch("$TAG#bgViewModel.alpha") {
-                    bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha }
-                }
-                launch("$TAG#bgViewModel.color") {
+                launch { bgViewModel.alpha.collect { alpha -> bgView.alpha = alpha } }
+                launch {
                     bgViewModel.color.collect { color ->
                         bgView.imageTintList = ColorStateList.valueOf(color)
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
index b5d6177..52d7519 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
@@ -18,7 +18,6 @@
 package com.android.systemui.keyguard.ui.binder
 
 import android.os.Handler
-import android.os.Trace
 import android.transition.Transition
 import android.transition.TransitionManager
 import android.util.Log
@@ -30,6 +29,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
+import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.BaseBlueprintTransition
 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
@@ -38,12 +38,11 @@
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
+import com.android.systemui.shared.R as sharedR
+import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
 import kotlin.math.max
 
-private const val TAG = "KeyguardBlueprintViewBinder"
-private const val DEBUG = false
-
 @SysUISingleton
 class KeyguardBlueprintViewBinder
 @Inject
@@ -91,59 +90,59 @@
         constraintLayout.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.CREATED) {
                 launch("$TAG#viewModel.blueprint") {
-                    viewModel.blueprint.collect { blueprint ->
-                        Trace.beginSection("KeyguardBlueprintViewBinder#applyBlueprint")
-                        val prevBluePrint = viewModel.currentBluePrint
+                    viewModel.blueprint
+                        .pairwise(
+                            null as KeyguardBlueprint?,
+                        )
+                        .collect { (prevBlueprint, blueprint) ->
+                            val cs =
+                                ConstraintSet().apply {
+                                    clone(constraintLayout)
+                                    val emptyLayout = ConstraintSet.Layout()
+                                    knownIds.forEach {
+                                        getConstraint(it).layout.copyFrom(emptyLayout)
+                                    }
+                                    blueprint.applyConstraints(this)
+                                }
 
-                        val cs =
-                            ConstraintSet().apply {
-                                clone(constraintLayout)
-                                val emptyLayout = ConstraintSet.Layout()
-                                knownIds.forEach { getConstraint(it).layout.copyFrom(emptyLayout) }
-                                blueprint.applyConstraints(this)
-                            }
-
-                        var transition =
-                            if (
-                                !KeyguardBottomAreaRefactor.isEnabled &&
-                                    prevBluePrint != null &&
-                                    prevBluePrint != blueprint
-                            ) {
-                                BaseBlueprintTransition(clockViewModel)
-                                    .addTransition(
-                                        IntraBlueprintTransition(
-                                            Config.DEFAULT,
-                                            clockViewModel,
-                                            smartspaceViewModel
+                            var transition =
+                                if (
+                                    !KeyguardBottomAreaRefactor.isEnabled &&
+                                        prevBlueprint != null &&
+                                        prevBlueprint != blueprint
+                                ) {
+                                    BaseBlueprintTransition(clockViewModel)
+                                        .addTransition(
+                                            IntraBlueprintTransition(
+                                                Config.DEFAULT,
+                                                clockViewModel,
+                                                smartspaceViewModel
+                                            )
                                         )
+                                } else {
+                                    IntraBlueprintTransition(
+                                        Config.DEFAULT,
+                                        clockViewModel,
+                                        smartspaceViewModel
                                     )
-                            } else {
-                                IntraBlueprintTransition(
-                                    Config.DEFAULT,
-                                    clockViewModel,
-                                    smartspaceViewModel
-                                )
+                                }
+
+                            runTransition(constraintLayout, transition, Config.DEFAULT) {
+                                // Add and remove views of sections that are not contained by the
+                                // other.
+                                blueprint.replaceViews(constraintLayout, prevBlueprint)
+                                logAlphaVisibilityOfAppliedConstraintSet(cs, clockViewModel)
+                                cs.applyTo(constraintLayout)
                             }
-
-                        runTransition(constraintLayout, transition, Config.DEFAULT) {
-                            // Add and remove views of sections that are not contained by the other.
-                            blueprint.replaceViews(prevBluePrint, constraintLayout)
-                            logAlphaVisibilityOfAppliedConstraintSet(cs, clockViewModel)
-                            cs.applyTo(constraintLayout)
                         }
-
-                        viewModel.currentBluePrint = blueprint
-                        Trace.endSection()
-                    }
                 }
 
                 launch("$TAG#viewModel.refreshTransition") {
                     viewModel.refreshTransition.collect { transition ->
-                        Trace.beginSection("KeyguardBlueprintViewBinder#refreshTransition")
                         val cs =
                             ConstraintSet().apply {
                                 clone(constraintLayout)
-                                viewModel.currentBluePrint?.applyConstraints(this)
+                                viewModel.blueprint.value.applyConstraints(this)
                             }
 
                         runTransition(
@@ -158,7 +157,6 @@
                             logAlphaVisibilityOfAppliedConstraintSet(cs, clockViewModel)
                             cs.applyTo(constraintLayout)
                         }
-                        Trace.endSection()
                     }
                 }
             }
@@ -217,15 +215,26 @@
         if (!DEBUG || currentClock == null) return
         val smallClockViewId = R.id.lockscreen_clock_view
         val largeClockViewId = currentClock.largeClock.layout.views[0].id
+        val smartspaceDateId = sharedR.id.date_smartspace_view
         Log.i(
             TAG,
             "applyCsToSmallClock: vis=${cs.getVisibility(smallClockViewId)} " +
-                "alpha=${cs.getConstraint(smallClockViewId).propertySet}"
+                "alpha=${cs.getConstraint(smallClockViewId).propertySet.alpha}"
         )
         Log.i(
             TAG,
             "applyCsToLargeClock: vis=${cs.getVisibility(largeClockViewId)} " +
-                "alpha=${cs.getConstraint(largeClockViewId).propertySet}"
+                "alpha=${cs.getConstraint(largeClockViewId).propertySet.alpha}"
         )
+        Log.i(
+            TAG,
+            "applyCsToSmartspaceDate: vis=${cs.getVisibility(smartspaceDateId)} " +
+                "alpha=${cs.getConstraint(smartspaceDateId).propertySet.alpha}"
+        )
+    }
+
+    companion object {
+        private const val TAG = "KeyguardBlueprintViewBinder"
+        private const val DEBUG = false
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
index 1b06a69..ed5d53c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
@@ -26,22 +26,19 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.tracing.coroutines.launch
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.keyguard.KeyguardClockSwitch.SMALL
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
+import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type
 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.clocks.ClockController
-import com.android.systemui.shared.clocks.DEFAULT_CLOCK_ID
-import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.launch
 
 object KeyguardClockViewBinder {
-    private const val TAG = "KeyguardClockViewBinder"
+    private val TAG = KeyguardClockViewBinder::class.simpleName!!
     // When changing to new clock, we need to remove old clock views from burnInLayer
     private var lastClock: ClockController? = null
     @JvmStatic
@@ -51,36 +48,42 @@
         viewModel: KeyguardClockViewModel,
         keyguardClockInteractor: KeyguardClockInteractor,
         blueprintInteractor: KeyguardBlueprintInteractor,
-    ): DisposableHandle {
-        keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView)
-
-        return keyguardRootView.repeatWhenAttached {
+    ) {
+        keyguardRootView.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.CREATED) {
-                launch("$TAG#viewModel.currentClock") {
+                keyguardClockInteractor.clockEventController.registerListeners(keyguardRootView)
+            }
+        }
+
+        keyguardRootView.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.CREATED) {
+                launch {
                     if (!MigrateClocksToBlueprint.isEnabled) return@launch
                     viewModel.currentClock.collect { currentClock ->
                         cleanupClockViews(currentClock, keyguardRootView, viewModel.burnInLayer)
                         addClockViews(currentClock, keyguardRootView)
-                        updateBurnInLayer(keyguardRootView, viewModel)
+                        updateBurnInLayer(keyguardRootView, viewModel, viewModel.clockSize.value)
                         applyConstraints(clockSection, keyguardRootView, true)
                     }
                 }
-                launch("$TAG#viewModel.clockSize") {
+
+                launch {
                     if (!MigrateClocksToBlueprint.isEnabled) return@launch
-                    viewModel.clockSize.collect {
-                        updateBurnInLayer(keyguardRootView, viewModel)
+                    viewModel.clockSize.collect { clockSize ->
+                        updateBurnInLayer(keyguardRootView, viewModel, clockSize)
                         blueprintInteractor.refreshBlueprint(Type.ClockSize)
                     }
                 }
-                launch("$TAG#viewModel.clockShouldBeCentered") {
+
+                launch {
                     if (!MigrateClocksToBlueprint.isEnabled) return@launch
-                    viewModel.clockShouldBeCentered.collect { clockShouldBeCentered ->
+                    viewModel.clockShouldBeCentered.collect {
                         viewModel.currentClock.value?.let {
-                            // Weather clock also has hasCustomPositionUpdatedAnimation as true
-                            // TODO(b/323020908): remove ID check
+                            // TODO(b/301502635): remove "!it.config.useCustomClockScene" when
+                            // migrate clocks to blueprint is fully rolled out
                             if (
                                 it.largeClock.config.hasCustomPositionUpdatedAnimation &&
-                                    it.config.id == DEFAULT_CLOCK_ID
+                                    !it.config.useCustomClockScene
                             ) {
                                 blueprintInteractor.refreshBlueprint(Type.DefaultClockStepping)
                             } else {
@@ -89,13 +92,13 @@
                         }
                     }
                 }
-                launch("$TAG#viewModel.isAodIconsVisible") {
+
+                launch {
                     if (!MigrateClocksToBlueprint.isEnabled) return@launch
-                    viewModel.isAodIconsVisible.collect { isAodIconsVisible ->
+                    viewModel.isAodIconsVisible.collect {
                         viewModel.currentClock.value?.let {
-                            // Weather clock also has hasCustomPositionUpdatedAnimation as true
                             if (
-                                viewModel.useLargeClock && it.config.id == "DIGITAL_CLOCK_WEATHER"
+                                viewModel.isLargeClockVisible.value && it.config.useCustomClockScene
                             ) {
                                 blueprintInteractor.refreshBlueprint(Type.DefaultTransition)
                             }
@@ -110,18 +113,19 @@
     fun updateBurnInLayer(
         keyguardRootView: ConstraintLayout,
         viewModel: KeyguardClockViewModel,
+        clockSize: ClockSize,
     ) {
         val burnInLayer = viewModel.burnInLayer
         val clockController = viewModel.currentClock.value
         clockController?.let { clock ->
-            when (viewModel.clockSize.value) {
-                LARGE -> {
+            when (clockSize) {
+                ClockSize.LARGE -> {
                     clock.smallClock.layout.views.forEach { burnInLayer?.removeView(it) }
                     if (clock.config.useAlternateSmartspaceAODTransition) {
                         clock.largeClock.layout.views.forEach { burnInLayer?.addView(it) }
                     }
                 }
-                SMALL -> {
+                ClockSize.SMALL -> {
                     clock.smallClock.layout.views.forEach { burnInLayer?.addView(it) }
                     clock.largeClock.layout.views.forEach { burnInLayer?.removeView(it) }
                 }
@@ -138,15 +142,16 @@
         if (lastClock == currentClock) {
             return
         }
+
         lastClock?.let { clock ->
             clock.smallClock.layout.views.forEach {
                 burnInLayer?.removeView(it)
                 rootView.removeView(it)
             }
+
             // add large clock to burn in layer only when it will have same transition with other
-            // components in AOD
-            // otherwise, it will have a separate scale transition while other components only have
-            // translate transition
+            // components in AOD otherwise, it will have a separate scale transition while other
+            // components only have translate transition
             if (clock.config.useAlternateSmartspaceAODTransition) {
                 clock.largeClock.layout.views.forEach { burnInLayer?.removeView(it) }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
index d5add61..93b3ba5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
@@ -19,9 +19,8 @@
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
@@ -38,11 +37,10 @@
     private val interactor: KeyguardDismissActionInteractor,
     @Application private val scope: CoroutineScope,
     private val keyguardLogger: KeyguardLogger,
-    private val featureFlags: FeatureFlagsClassic,
 ) : CoreStartable {
 
     override fun start() {
-        if (!featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (!RefactorKeyguardDismissIntent.isEnabled) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
index 87d8164..f77d012 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
@@ -21,8 +21,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.keyguard.shared.model.KeyguardDone
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -44,7 +44,7 @@
 ) : CoreStartable {
 
     override fun start() {
-        if (!featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (!RefactorKeyguardDismissIntent.isEnabled) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
index 1382468..8386628 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
@@ -34,8 +34,9 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.tracing.coroutines.launch
+import com.android.internal.policy.SystemBarUtils
 import com.android.systemui.customization.R as customizationR
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.keyguard.ui.preview.KeyguardPreviewRenderer
 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection.Companion.getDimen
 import com.android.systemui.keyguard.ui.view.layout.sections.setVisibility
@@ -43,6 +44,7 @@
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.res.R
+import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.systemui.util.Utils
 import kotlin.reflect.KSuspendFunction1
 
@@ -76,37 +78,42 @@
         context: Context,
         rootView: ConstraintLayout,
         viewModel: KeyguardPreviewClockViewModel,
+        clockRegistry: ClockRegistry,
         updateClockAppearance: KSuspendFunction1<ClockController, Unit>,
     ) {
         rootView.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.STARTED) {
+                var lastClock: ClockController? = null
                 launch("$TAG#viewModel.previewClock") {
-                    var lastClock: ClockController? = null
-                    viewModel.previewClock.collect { currentClock ->
-                        lastClock?.let { clock ->
-                            (clock.largeClock.layout.views + clock.smallClock.layout.views)
-                                .forEach { rootView.removeView(it) }
-                        }
-                        lastClock = currentClock
-                        updateClockAppearance(currentClock)
+                        viewModel.previewClock.collect { currentClock ->
+                            lastClock?.let { clock ->
+                                (clock.largeClock.layout.views + clock.smallClock.layout.views)
+                                    .forEach { rootView.removeView(it) }
+                            }
+                            lastClock = currentClock
+                            updateClockAppearance(currentClock)
 
-                        if (viewModel.shouldHighlightSelectedAffordance) {
-                            (currentClock.largeClock.layout.views +
-                                    currentClock.smallClock.layout.views)
-                                .forEach { it.alpha = KeyguardPreviewRenderer.DIM_ALPHA }
-                        }
-                        currentClock.largeClock.layout.views.forEach {
-                            (it.parent as? ViewGroup)?.removeView(it)
-                            rootView.addView(it)
-                        }
+                            if (viewModel.shouldHighlightSelectedAffordance) {
+                                (currentClock.largeClock.layout.views +
+                                        currentClock.smallClock.layout.views)
+                                    .forEach { it.alpha = KeyguardPreviewRenderer.DIM_ALPHA }
+                            }
+                            currentClock.largeClock.layout.views.forEach {
+                                (it.parent as? ViewGroup)?.removeView(it)
+                                rootView.addView(it)
+                            }
 
-                        currentClock.smallClock.layout.views.forEach {
-                            (it.parent as? ViewGroup)?.removeView(it)
-                            rootView.addView(it)
+                            currentClock.smallClock.layout.views.forEach {
+                                (it.parent as? ViewGroup)?.removeView(it)
+                                rootView.addView(it)
+                            }
+                            applyPreviewConstraints(context, rootView, currentClock, viewModel)
                         }
-                        applyPreviewConstraints(context, rootView, currentClock, viewModel)
                     }
-                }
+                    .invokeOnCompletion {
+                        // recover seed color especially for Transit clock
+                        lastClock?.events?.onSeedColorChanged(clockRegistry.seedColor)
+                    }
             }
         }
     }
@@ -116,7 +123,7 @@
             constrainWidth(R.id.lockscreen_clock_view_large, ConstraintSet.WRAP_CONTENT)
             constrainHeight(R.id.lockscreen_clock_view_large, ConstraintSet.MATCH_CONSTRAINT)
             val largeClockTopMargin =
-                context.resources.getDimensionPixelSize(R.dimen.status_bar_height) +
+                SystemBarUtils.getStatusBarHeight(context) +
                     context.resources.getDimensionPixelSize(
                         customizationR.dimen.small_clock_padding_top
                     ) +
@@ -192,14 +199,14 @@
         // flickering
         val largeClockVisibility =
             when (viewModel.selectedClockSize.value) {
-                SettingsClockSize.DYNAMIC -> VISIBLE
-                SettingsClockSize.SMALL -> INVISIBLE
+                ClockSizeSetting.DYNAMIC -> VISIBLE
+                ClockSizeSetting.SMALL -> INVISIBLE
                 null -> INVISIBLE
             }
         val smallClockVisibility =
             when (viewModel.selectedClockSize.value) {
-                SettingsClockSize.DYNAMIC -> INVISIBLE
-                SettingsClockSize.SMALL -> VISIBLE
+                ClockSizeSetting.DYNAMIC -> INVISIBLE
+                ClockSizeSetting.SMALL -> VISIBLE
                 null -> INVISIBLE
             }
         cs.apply {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt
index 49ae35a..4b75b80 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt
@@ -23,7 +23,7 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.tracing.coroutines.launch
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 
@@ -32,7 +32,7 @@
 
     @JvmStatic
     fun bind(
-        context: Context,
+        previewContext: Context,
         smartspace: View,
         splitShadePreview: Boolean,
         viewModel: KeyguardPreviewSmartspaceViewModel,
@@ -43,13 +43,15 @@
                     viewModel.selectedClockSize.collect {
                         val topPadding =
                             when (it) {
-                                SettingsClockSize.DYNAMIC ->
+                                ClockSizeSetting.DYNAMIC ->
                                     viewModel.getLargeClockSmartspaceTopPadding(
                                         splitShadePreview,
+                                        previewContext,
                                     )
-                                SettingsClockSize.SMALL ->
+                                ClockSizeSetting.SMALL ->
                                     viewModel.getSmallClockSmartspaceTopPadding(
                                         splitShadePreview,
+                                        previewContext,
                                     )
                             }
                         smartspace.setTopPadding(topPadding)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index 6c21e6c..abd79ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -30,7 +30,6 @@
 import androidx.core.view.updateLayoutParams
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.tracing.coroutines.launch
 import com.android.settingslib.Utils
 import com.android.systemui.animation.Expandable
 import com.android.systemui.animation.view.LaunchableImageView
@@ -42,11 +41,11 @@
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.util.doOnEnd
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
 
 /** This is only for a SINGLE Quick affordance */
 object KeyguardQuickAffordanceViewBinder {
@@ -54,7 +53,6 @@
     private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L
     private const val SCALE_SELECTED_BUTTON = 1.23f
     private const val DIM_ALPHA = 0.3f
-    private const val TAG = "KeyguardQuickAffordanceViewBinder"
 
     /**
      * Defines interface for an object that acts as the binding between the view and its view-model.
@@ -76,15 +74,14 @@
         alpha: Flow<Float>,
         falsingManager: FalsingManager?,
         vibratorHelper: VibratorHelper?,
-        mainImmediateDispatcher: CoroutineDispatcher,
         messageDisplayer: (Int) -> Unit,
     ): Binding {
         val button = view as ImageView
         val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
         val disposableHandle =
-            view.repeatWhenAttached(mainImmediateDispatcher) {
+            view.repeatWhenAttached {
                 repeatOnLifecycle(Lifecycle.State.STARTED) {
-                    launch("$TAG#viewModel.collect") {
+                    launch {
                         viewModel.collect { buttonModel ->
                             updateButton(
                                 view = button,
@@ -96,7 +93,7 @@
                         }
                     }
 
-                    launch("$TAG#updateButtonAlpha") {
+                    launch {
                         updateButtonAlpha(
                             view = button,
                             viewModel = viewModel,
@@ -104,7 +101,7 @@
                         )
                     }
 
-                    launch("$TAG#configurationBasedDimensions") {
+                    launch {
                         configurationBasedDimensions.collect { dimensions ->
                             button.updateLayoutParams<ViewGroup.LayoutParams> {
                                 width = dimensions.buttonSizePx.width
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index 5f50f7e..ccc48b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -30,23 +30,30 @@
 import android.view.ViewGroup.OnHierarchyChangeListener
 import android.view.ViewPropertyAnimator
 import android.view.WindowInsets
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.OnBackPressedDispatcherOwner
+import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.animation.Interpolators
 import com.android.app.tracing.coroutines.launch
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
-import com.android.keyguard.KeyguardClockSwitch.MISSING_CLOCK_ID
 import com.android.systemui.Flags.newAodTransition
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.common.shared.model.Text
 import com.android.systemui.common.shared.model.TintedIcon
 import com.android.systemui.common.ui.ConfigurationState
+import com.android.systemui.common.ui.view.onApplyWindowInsets
+import com.android.systemui.common.ui.view.onLayoutChanged
+import com.android.systemui.common.ui.view.onTouchListener
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
 import com.android.systemui.keyguard.KeyguardViewMediator
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
+import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
+import com.android.systemui.keyguard.shared.ComposeLockscreen
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
@@ -55,7 +62,6 @@
 import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.res.R
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.CrossFadeHelper
@@ -65,13 +71,12 @@
 import com.android.systemui.temporarydisplay.ViewPriority
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo
+import com.android.systemui.util.kotlin.DisposableHandles
 import com.android.systemui.util.ui.AnimatedValue
 import com.android.systemui.util.ui.isAnimating
 import com.android.systemui.util.ui.stopAnimating
 import com.android.systemui.util.ui.value
-import javax.inject.Provider
 import kotlin.math.min
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.coroutineScope
@@ -79,6 +84,7 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
 
 /** Bind occludingAppDeviceEntryMessageViewModel to run whenever the keyguard view is attached. */
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -89,51 +95,64 @@
         view: ViewGroup,
         viewModel: KeyguardRootViewModel,
         configuration: ConfigurationState,
-        occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
-        chipbarCoordinator: ChipbarCoordinator,
+        occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel?,
+        chipbarCoordinator: ChipbarCoordinator?,
         screenOffAnimationController: ScreenOffAnimationController,
         shadeInteractor: ShadeInteractor,
-        clockControllerProvider: Provider<ClockController>?,
+        clockInteractor: KeyguardClockInteractor,
         interactionJankMonitor: InteractionJankMonitor?,
         deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor?,
         vibratorHelper: VibratorHelper?,
         falsingManager: FalsingManager?,
         keyguardViewMediator: KeyguardViewMediator?,
-        mainImmediateDispatcher: CoroutineDispatcher,
     ): DisposableHandle {
-        var onLayoutChangeListener: OnLayoutChange? = null
+        val disposables = DisposableHandles()
         val childViews = mutableMapOf<Int, View>()
 
         if (KeyguardBottomAreaRefactor.isEnabled) {
-            view.setOnTouchListener { _, event ->
-                if (falsingManager?.isFalseTap(FalsingManager.LOW_PENALTY) == false) {
-                    viewModel.setRootViewLastTapPosition(Point(event.x.toInt(), event.y.toInt()))
+            disposables +=
+                view.onTouchListener { _, event ->
+                    if (falsingManager?.isFalseTap(FalsingManager.LOW_PENALTY) == false) {
+                        viewModel.setRootViewLastTapPosition(
+                            Point(event.x.toInt(), event.y.toInt())
+                        )
+                    }
+                    false
                 }
-                false
-            }
         }
 
         val burnInParams = MutableStateFlow(BurnInParameters())
-        val viewState =
-            ViewStateAccessor(
-                alpha = { view.alpha },
-            )
-
-        val disposableHandle =
-            view.repeatWhenAttached(mainImmediateDispatcher) {
+        val viewState = ViewStateAccessor(alpha = { view.alpha })
+        disposables +=
+            view.repeatWhenAttached {
                 repeatOnLifecycle(Lifecycle.State.CREATED) {
-                    launch("$TAG#occludingAppDeviceEntryMessageViewModel.message") {
-                        occludingAppDeviceEntryMessageViewModel.message.collect { biometricMessage
+                    if (ComposeLockscreen.isEnabled) {
+                        view.setViewTreeOnBackPressedDispatcherOwner(
+                            object : OnBackPressedDispatcherOwner {
+                                override val onBackPressedDispatcher =
+                                    OnBackPressedDispatcher().apply {
+                                        setOnBackInvokedDispatcher(
+                                            view.viewRootImpl.onBackInvokedDispatcher
+                                        )
+                                    }
+
+                                override val lifecycle: Lifecycle =
+                                    [email protected]
+                            }
+                        )
+                    }
+                    launch {
+                        occludingAppDeviceEntryMessageViewModel?.message?.collect { biometricMessage
                             ->
                             if (biometricMessage?.message != null) {
-                                chipbarCoordinator.displayView(
+                                chipbarCoordinator!!.displayView(
                                     createChipbarInfo(
                                         biometricMessage.message,
                                         R.drawable.ic_lock,
                                     )
                                 )
                             } else {
-                                chipbarCoordinator.removeView(ID, "occludingAppMsgNull")
+                                chipbarCoordinator!!.removeView(ID, "occludingAppMsgNull")
                             }
                         }
                     }
@@ -141,7 +160,7 @@
                     if (
                         KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled
                     ) {
-                        launch("$TAG#viewModel.alpha") {
+                        launch {
                             viewModel.alpha(viewState).collect { alpha ->
                                 view.alpha = alpha
                                 if (KeyguardBottomAreaRefactor.isEnabled) {
@@ -153,21 +172,21 @@
                     }
 
                     if (MigrateClocksToBlueprint.isEnabled) {
-                        launch("$TAG#viewModel.burnInLayerVisibility") {
+                        launch {
                             viewModel.burnInLayerVisibility.collect { visibility ->
                                 childViews[burnInLayerId]?.visibility = visibility
                                 childViews[aodNotificationIconContainerId]?.visibility = visibility
                             }
                         }
 
-                        launch("$TAG#viewModel.burnInLayerAlpha") {
+                        launch {
                             viewModel.burnInLayerAlpha.collect { alpha ->
                                 childViews[statusViewId]?.alpha = alpha
                                 childViews[aodNotificationIconContainerId]?.alpha = alpha
                             }
                         }
 
-                        launch("$TAG#viewModel.topClippingBounds") {
+                        launch {
                             val clipBounds = Rect()
                             viewModel.topClippingBounds.collect { clipTop ->
                                 if (clipTop == null) {
@@ -184,13 +203,13 @@
                             }
                         }
 
-                        launch("$TAG#viewModel.lockscreenStateAlpha") {
+                        launch {
                             viewModel.lockscreenStateAlpha(viewState).collect { alpha ->
                                 childViews[statusViewId]?.alpha = alpha
                             }
                         }
 
-                        launch("$TAG#viewModel.translationY") {
+                        launch {
                             // When translation happens in burnInLayer, it won't be weather clock
                             // large clock isn't added to burnInLayer due to its scale transition
                             // so we also need to add translation to it here
@@ -202,7 +221,7 @@
                             }
                         }
 
-                        launch("$TAG#viewModel.translationX") {
+                        launch {
                             viewModel.translationX.collect { state ->
                                 val px = state.value ?: return@collect
                                 when {
@@ -229,7 +248,7 @@
                             }
                         }
 
-                        launch("$TAG#viewModel.scale") {
+                        launch {
                             viewModel.scale.collect { scaleViewModel ->
                                 if (scaleViewModel.scaleClockOnly) {
                                     // For clocks except weather clock, we have scale transition
@@ -260,7 +279,7 @@
                         }
 
                         if (NotificationIconContainerRefactor.isEnabled) {
-                            launch("$TAG#viewModel.isNotifIconContainerVisible") {
+                            launch {
                                 val iconsAppearTranslationPx =
                                     configuration
                                         .getDimensionPixelSize(R.dimen.shelf_appear_translation)
@@ -277,18 +296,15 @@
                         }
 
                         interactionJankMonitor?.let { jankMonitor ->
-                            launch("$TAG#viewModel.goneToAodTransition") {
+                            launch {
                                 viewModel.goneToAodTransition.collect {
                                     when (it.transitionState) {
                                         TransitionState.STARTED -> {
-                                            val clockId =
-                                                clockControllerProvider?.get()?.config?.id
-                                                    ?: MISSING_CLOCK_ID
+                                            val clockId = clockInteractor.renderedClockId
                                             val builder =
                                                 InteractionJankMonitor.Configuration.Builder
                                                     .withView(CUJ_SCREEN_OFF_SHOW_AOD, view)
                                                     .setTag(clockId)
-
                                             jankMonitor.begin(builder)
                                         }
                                         TransitionState.CANCELED ->
@@ -306,7 +322,7 @@
                         }
                     }
 
-                    launch("$TAG#shadeInteractor.isAnyFullyExpanded") {
+                    launch {
                         shadeInteractor.isAnyFullyExpanded.collect { isFullyAnyExpanded ->
                             view.visibility =
                                 if (isFullyAnyExpanded) {
@@ -317,12 +333,10 @@
                         }
                     }
 
-                    launch("$TAG#burnInParams.collect") {
-                        burnInParams.collect { viewModel.updateBurnInParams(it) }
-                    }
+                    launch { burnInParams.collect { viewModel.updateBurnInParams(it) } }
 
                     if (deviceEntryHapticsInteractor != null && vibratorHelper != null) {
-                        launch("$TAG#deviceEntryHapticsInteractor.playSuccessHaptic") {
+                        launch {
                             deviceEntryHapticsInteractor.playSuccessHaptic.collect {
                                 vibratorHelper.performHapticFeedback(
                                     view,
@@ -332,7 +346,7 @@
                             }
                         }
 
-                        launch("$TAG#deviceEntryHapticsInteractor.playErrorHaptic") {
+                        launch {
                             deviceEntryHapticsInteractor.playErrorHaptic.collect {
                                 vibratorHelper.performHapticFeedback(
                                     view,
@@ -345,20 +359,13 @@
                 }
             }
 
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            burnInParams.update { current ->
-                current.copy(clockControllerProvider = clockControllerProvider)
-            }
-        }
-
         if (MigrateClocksToBlueprint.isEnabled) {
             burnInParams.update { current ->
                 current.copy(translationY = { childViews[burnInLayerId]?.translationY })
             }
         }
 
-        onLayoutChangeListener = OnLayoutChange(viewModel, childViews, burnInParams)
-        view.addOnLayoutChangeListener(onLayoutChangeListener)
+        disposables += view.onLayoutChanged(OnLayoutChange(viewModel, childViews, burnInParams))
 
         // Views will be added or removed after the call to bind(). This is needed to avoid many
         // calls to findViewById
@@ -373,24 +380,21 @@
                 }
             }
         )
-
-        view.setOnApplyWindowInsetsListener { v: View, insets: WindowInsets ->
-            val insetTypes = WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout()
-            burnInParams.update { current ->
-                current.copy(topInset = insets.getInsetsIgnoringVisibility(insetTypes).top)
-            }
-            insets
+        disposables += DisposableHandle {
+            view.setOnHierarchyChangeListener(null)
+            childViews.clear()
         }
 
-        return object : DisposableHandle {
-            override fun dispose() {
-                disposableHandle.dispose()
-                view.removeOnLayoutChangeListener(onLayoutChangeListener)
-                view.setOnHierarchyChangeListener(null)
-                view.setOnApplyWindowInsetsListener(null)
-                childViews.clear()
+        disposables +=
+            view.onApplyWindowInsets { _: View, insets: WindowInsets ->
+                val insetTypes = WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout()
+                burnInParams.update { current ->
+                    current.copy(topInset = insets.getInsetsIgnoringVisibility(insetTypes).top)
+                }
+                insets
             }
-        }
+
+        return disposables
     }
 
     /**
@@ -597,5 +601,4 @@
 
     private const val ID = "occluding_app_device_entry_unlock_msg"
     private const val AOD_ICONS_APPEAR_DURATION: Long = 200
-    private const val TAG = "KeyguardRootViewBinder"
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
index 9a6dca3..76edda3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
@@ -20,8 +20,6 @@
 import android.graphics.Point
 import com.android.systemui.CoreStartable
 import com.android.systemui.Flags
-import com.android.systemui.biometrics.SideFpsController
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
@@ -38,7 +36,7 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 
-private const val spfsProgressBarCommand = "sfps-progress-bar"
+private const val sfpsProgressBarCommand = "sfps-progress-bar"
 
 @SysUISingleton
 class SideFpsProgressBarViewBinder
@@ -47,8 +45,6 @@
     private val viewModel: SideFpsProgressBarViewModel,
     private val view: SideFpsProgressBar,
     @Application private val applicationScope: CoroutineScope,
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    private val sfpsController: dagger.Lazy<SideFpsController>,
     private val logger: SideFpsLogger,
     private val commandRegistry: CommandRegistry,
 ) : CoreStartable {
@@ -61,7 +57,7 @@
         // not required.
         var layoutJob: Job? = null
         var progressJob: Job? = null
-        commandRegistry.registerCommand(spfsProgressBarCommand) { SfpsProgressBarCommand() }
+        commandRegistry.registerCommand(sfpsProgressBarCommand) { SfpsProgressBarCommand() }
         applicationScope.launch {
             viewModel.isProlongedTouchRequiredForAuthentication.collectLatest { enabled ->
                 logger.isProlongedTouchRequiredForAuthenticationChanged(enabled)
@@ -109,17 +105,6 @@
     ) {
         logger.sfpsProgressBarStateChanged(visible, location, fpDetectRunning, length, rotation)
         view.updateView(visible, location, length, thickness, rotation)
-        // We have to hide the SFPS indicator as the progress bar will
-        // be shown at the same location
-        if (!SideFpsControllerRefactor.isEnabled) {
-            if (visible) {
-                logger.hidingSfpsIndicator()
-                sfpsController.get().hideIndicator()
-            } else if (fpDetectRunning) {
-                logger.showingSfpsIndicator()
-                sfpsController.get().showIndicator()
-            }
-        }
     }
 
     inner class SfpsProgressBarCommand : Command {
@@ -164,7 +149,7 @@
         }
 
         override fun help(pw: PrintWriter) {
-            pw.println("Usage: adb shell cmd statusbar $spfsProgressBarCommand <command>")
+            pw.println("Usage: adb shell cmd statusbar $sfpsProgressBarCommand <command>")
             pw.println("Available commands:")
             pw.println("  show x y width height rotation")
             pw.println("  hide")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 9195b4f4..bda5be4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -47,6 +47,7 @@
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import androidx.core.view.isInvisible
+import com.android.internal.policy.SystemBarUtils
 import com.android.keyguard.ClockEventController
 import com.android.keyguard.KeyguardClockSwitch
 import com.android.systemui.animation.view.LaunchableImageView
@@ -60,6 +61,7 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
+import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
 import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
@@ -140,6 +142,7 @@
     private val secureSettings: SecureSettings,
     private val communalTutorialViewModel: CommunalTutorialIndicatorViewModel,
     private val defaultShortcutsSection: DefaultShortcutsSection,
+    private val keyguardClockInteractor: KeyguardClockInteractor,
 ) {
     val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
     private val width: Int = bundle.getInt(KEY_VIEW_WIDTH)
@@ -324,9 +327,12 @@
         smartSpaceView = lockscreenSmartspaceController.buildAndConnectDateView(parentView)
 
         val topPadding: Int =
-            smartspaceViewModel.getLargeClockSmartspaceTopPadding(previewInSplitShade())
-        val startPadding: Int = smartspaceViewModel.getSmartspaceStartPadding()
-        val endPadding: Int = smartspaceViewModel.getSmartspaceEndPadding()
+            smartspaceViewModel.getLargeClockSmartspaceTopPadding(
+                previewInSplitShade(),
+                previewContext,
+            )
+        val startPadding: Int = smartspaceViewModel.getSmartspaceStartPadding(previewContext)
+        val endPadding: Int = smartspaceViewModel.getSmartspaceEndPadding(previewContext)
 
         smartSpaceView?.let {
             it.setPaddingRelative(startPadding, topPadding, endPadding, 0)
@@ -364,6 +370,7 @@
             ),
         )
     }
+
     @OptIn(ExperimentalCoroutinesApi::class)
     private fun setupKeyguardRootView(previewContext: Context, rootView: FrameLayout) {
         val keyguardRootView = KeyguardRootView(previewContext, null)
@@ -377,13 +384,12 @@
                     chipbarCoordinator,
                     screenOffAnimationController,
                     shadeInteractor,
-                    null, // clock provider only needed for burn in
+                    keyguardClockInteractor,
                     null, // jank monitor not required for preview mode
                     null, // device entry haptics not required preview mode
                     null, // device entry haptics not required for preview mode
                     null, // falsing manager not required for preview mode
                     null, // keyguard view mediator is not required for preview mode
-                    mainDispatcher,
                 )
         }
         rootView.addView(
@@ -407,10 +413,11 @@
             setUpClock(previewContext, rootView)
             if (MigrateClocksToBlueprint.isEnabled) {
                 KeyguardPreviewClockViewBinder.bind(
-                    context,
+                    previewContext,
                     keyguardRootView,
                     clockViewModel,
-                    ::updateClockAppearance
+                    clockRegistry,
+                    ::updateClockAppearance,
                 )
             } else {
                 KeyguardPreviewClockViewBinder.bind(
@@ -425,7 +432,7 @@
 
         smartSpaceView?.let {
             KeyguardPreviewSmartspaceViewBinder.bind(
-                context,
+                previewContext,
                 it,
                 previewInSplitShade(),
                 smartspaceViewModel
@@ -450,7 +457,6 @@
                     alpha = flowOf(1f),
                     falsingManager = falsingManager,
                     vibratorHelper = vibratorHelper,
-                    mainImmediateDispatcher = mainDispatcher,
                 ) { message ->
                     indicationController.showTransientIndication(message)
                 }
@@ -465,7 +471,6 @@
                     alpha = flowOf(1f),
                     falsingManager = falsingManager,
                     vibratorHelper = vibratorHelper,
-                    mainImmediateDispatcher = mainDispatcher,
                 ) { message ->
                     indicationController.showTransientIndication(message)
                 }
@@ -536,7 +541,7 @@
                     )
                 )
             layoutParams.topMargin =
-                KeyguardPreviewSmartspaceViewModel.getStatusBarHeight(resources) +
+                SystemBarUtils.getStatusBarHeight(previewContext) +
                     resources.getDimensionPixelSize(
                         com.android.systemui.customization.R.dimen.small_clock_padding_top
                     )
@@ -617,7 +622,9 @@
     }
 
     private suspend fun updateClockAppearance(clock: ClockController) {
-        clockController.clock = clock
+        if (!MigrateClocksToBlueprint.isEnabled) {
+            clockController.clock = clock
+        }
         val colors = wallpaperColors
         if (clockRegistry.seedColor == null && colors != null) {
             // Seed color null means users do not override any color on the clock. The default
@@ -635,6 +642,11 @@
                 if (isWallpaperDark) lightClockColor else darkClockColor
             )
         }
+        // In clock preview, we should have a seed color for clock
+        // before setting clock to clockEventController to avoid updateColor with seedColor == null
+        if (MigrateClocksToBlueprint.isEnabled) {
+            clockController.clock = clock
+        }
     }
     private fun onClockChanged() {
         if (MigrateClocksToBlueprint.isEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
index af1d0df9..2735aed 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
@@ -68,12 +68,12 @@
             object : AccessibilityDelegate() {
                 private val accessibilityAuthenticateHint =
                     AccessibilityNodeInfo.AccessibilityAction(
-                        AccessibilityNodeInfoCompat.ACTION_CLICK,
+                        AccessibilityNodeInfoCompat.ACTION_LONG_CLICK,
                         resources.getString(R.string.accessibility_authenticate_hint)
                     )
                 private val accessibilityEnterHint =
                     AccessibilityNodeInfo.AccessibilityAction(
-                        AccessibilityNodeInfoCompat.ACTION_CLICK,
+                        AccessibilityNodeInfoCompat.ACTION_LONG_CLICK,
                         resources.getString(R.string.accessibility_enter_hint)
                     )
                 override fun onInitializeAccessibilityNodeInfo(
@@ -261,10 +261,10 @@
         return lockIconState
     }
 
-    enum class IconType {
-        LOCK,
-        UNLOCK,
-        FINGERPRINT,
+    enum class IconType(val contentDescriptionResId: Int) {
+        LOCK(R.string.accessibility_lock_icon),
+        UNLOCK(R.string.accessibility_unlock_button),
+        FINGERPRINT(R.string.accessibility_fingerprint_label),
     }
 
     enum class AccessibilityHintType {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index 77f7ac8..d5a9655 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.view.layout.sections.AccessibilityActionsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
@@ -52,6 +53,7 @@
 class DefaultKeyguardBlueprint
 @Inject
 constructor(
+    accessibilityActionsSection: AccessibilityActionsSection,
     defaultIndicationAreaSection: DefaultIndicationAreaSection,
     defaultDeviceEntrySection: DefaultDeviceEntrySection,
     defaultShortcutsSection: DefaultShortcutsSection,
@@ -73,6 +75,7 @@
 
     override val sections =
         listOfNotNull(
+            accessibilityActionsSection,
             defaultIndicationAreaSection,
             defaultShortcutsSection,
             defaultAmbientIndicationAreaSection.getOrNull(),
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt
index b4e57cc..04ac7bf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt
@@ -17,13 +17,9 @@
 
 package com.android.systemui.keyguard.ui.view.layout.blueprints
 
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID
 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
-import com.android.systemui.keyguard.shared.model.KeyguardSection
 import dagger.Binds
 import dagger.Module
-import dagger.Provides
 import dagger.multibindings.IntoSet
 
 @Module
@@ -45,26 +41,4 @@
     abstract fun bindShortcutsBesideUdfpsLockscreenBlueprint(
         shortcutsBesideUdfpsLockscreenBlueprint: ShortcutsBesideUdfpsKeyguardBlueprint
     ): KeyguardBlueprint
-
-    companion object {
-        /** This is a place holder for weather clock in compose. */
-        @Provides
-        @IntoSet
-        fun bindWeatherClockBlueprintPlaceHolder(): KeyguardBlueprint {
-            return object : KeyguardBlueprint {
-                override val id: String = WEATHER_CLOCK_BLUEPRINT_ID
-                override val sections: List<KeyguardSection> = listOf()
-            }
-        }
-
-        /** This is a place holder for weather clock in compose. */
-        @Provides
-        @IntoSet
-        fun bindSplitShadeWeatherClockBlueprintPlaceHolder(): KeyguardBlueprint {
-            return object : KeyguardBlueprint {
-                override val id: String = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-                override val sections: List<KeyguardSection> = listOf()
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
index 55b2381..b984a68 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.view.layout.sections.AccessibilityActionsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AlignShortcutsToUdfpsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
@@ -47,6 +48,7 @@
 class ShortcutsBesideUdfpsKeyguardBlueprint
 @Inject
 constructor(
+    accessibilityActionsSection: AccessibilityActionsSection,
     alignShortcutsToUdfpsSection: AlignShortcutsToUdfpsSection,
     defaultIndicationAreaSection: DefaultIndicationAreaSection,
     defaultDeviceEntrySection: DefaultDeviceEntrySection,
@@ -68,6 +70,7 @@
 
     override val sections =
         listOfNotNull(
+            accessibilityActionsSection,
             defaultIndicationAreaSection,
             alignShortcutsToUdfpsSection,
             defaultAmbientIndicationAreaSection.getOrNull(),
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
index 8472a9f..3447177 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.view.layout.sections.AccessibilityActionsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
@@ -49,6 +50,7 @@
 class SplitShadeKeyguardBlueprint
 @Inject
 constructor(
+    accessibilityActionsSection: AccessibilityActionsSection,
     defaultIndicationAreaSection: DefaultIndicationAreaSection,
     defaultDeviceEntrySection: DefaultDeviceEntrySection,
     defaultShortcutsSection: DefaultShortcutsSection,
@@ -70,6 +72,7 @@
 
     override val sections =
         listOfNotNull(
+            accessibilityActionsSection,
             defaultIndicationAreaSection,
             defaultShortcutsSection,
             defaultAmbientIndicationAreaSection.getOrNull(),
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AccessibilityActionsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AccessibilityActionsSection.kt
new file mode 100644
index 0000000..5e5330e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AccessibilityActionsSection.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.ui.view.layout.sections
+
+import android.content.Context
+import android.view.View
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.Flags
+import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.binder.AccessibilityActionsViewBinder
+import com.android.systemui.keyguard.ui.viewmodel.AccessibilityActionsViewModel
+import com.android.systemui.res.R
+import com.android.systemui.util.Utils
+import javax.inject.Inject
+import kotlinx.coroutines.DisposableHandle
+
+/**
+ * A placeholder section that provides shortcuts for navigating on the keyguard through
+ * accessibility actions.
+ */
+class AccessibilityActionsSection
+@Inject
+constructor(
+    private val context: Context,
+    private val accessibilityActionsViewModel: AccessibilityActionsViewModel,
+) : KeyguardSection() {
+    private var accessibilityActionsViewHandle: DisposableHandle? = null
+
+    override fun addViews(constraintLayout: ConstraintLayout) {
+        if (!communalEnabled(context)) {
+            return
+        }
+        val view = View(constraintLayout.context).apply { id = R.id.accessibility_actions_view }
+        constraintLayout.addView(view)
+    }
+
+    override fun bindData(constraintLayout: ConstraintLayout) {
+        if (!communalEnabled(context)) {
+            return
+        }
+        accessibilityActionsViewHandle =
+            AccessibilityActionsViewBinder.bind(
+                constraintLayout.requireViewById(R.id.accessibility_actions_view),
+                accessibilityActionsViewModel,
+            )
+    }
+
+    override fun applyConstraints(constraintSet: ConstraintSet) {
+        val accessibilityActionsViewId = R.id.accessibility_actions_view
+        constraintSet.apply {
+            // Starts from the bottom of the status bar.
+            connect(
+                accessibilityActionsViewId,
+                ConstraintSet.TOP,
+                ConstraintSet.PARENT_ID,
+                ConstraintSet.TOP,
+                Utils.getStatusBarHeaderHeightKeyguard(context)
+            )
+            connect(
+                accessibilityActionsViewId,
+                ConstraintSet.BOTTOM,
+                ConstraintSet.PARENT_ID,
+                ConstraintSet.BOTTOM,
+            )
+            // Full width
+            connect(
+                accessibilityActionsViewId,
+                ConstraintSet.START,
+                ConstraintSet.PARENT_ID,
+                ConstraintSet.START
+            )
+            connect(
+                accessibilityActionsViewId,
+                ConstraintSet.END,
+                ConstraintSet.PARENT_ID,
+                ConstraintSet.END
+            )
+        }
+    }
+
+    override fun removeViews(constraintLayout: ConstraintLayout) {
+        accessibilityActionsViewHandle?.dispose()
+        accessibilityActionsViewHandle = null
+        constraintLayout.removeView(R.id.accessibility_actions_view)
+    }
+}
+
+private fun communalEnabled(context: Context): Boolean {
+    return context.resources.getBoolean(R.bool.config_communalServiceEnabled) && Flags.communalHub()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
index 5404729..2e96638 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
@@ -36,7 +36,6 @@
 import com.android.systemui.statusbar.KeyguardIndicationController
 import com.android.systemui.statusbar.VibratorHelper
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 
 class AlignShortcutsToUdfpsSection
 @Inject
@@ -48,7 +47,6 @@
     private val falsingManager: FalsingManager,
     private val indicationController: KeyguardIndicationController,
     private val vibratorHelper: VibratorHelper,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
 ) : BaseShortcutSection() {
     override fun addViews(constraintLayout: ConstraintLayout) {
         if (KeyguardBottomAreaRefactor.isEnabled) {
@@ -66,7 +64,6 @@
                     keyguardQuickAffordancesCombinedViewModel.transitionAlpha,
                     falsingManager,
                     vibratorHelper,
-                    mainImmediateDispatcher,
                 ) {
                     indicationController.showTransientIndication(it)
                 }
@@ -77,7 +74,6 @@
                     keyguardQuickAffordancesCombinedViewModel.transitionAlpha,
                     falsingManager,
                     vibratorHelper,
-                    mainImmediateDispatcher,
                 ) {
                     indicationController.showTransientIndication(it)
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index e0bf815..ef29270 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -31,7 +31,7 @@
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import androidx.constraintlayout.widget.ConstraintSet.VISIBLE
 import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT
-import com.android.systemui.customization.R as customizationR
+import com.android.systemui.customization.R as custR
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
@@ -45,7 +45,6 @@
 import com.android.systemui.shared.R as sharedR
 import dagger.Lazy
 import javax.inject.Inject
-import kotlinx.coroutines.DisposableHandle
 
 internal fun ConstraintSet.setVisibility(
     views: Iterable<View>,
@@ -57,7 +56,7 @@
     alpha: Float,
 ) = views.forEach { view -> this.setAlpha(view.id, alpha) }
 
-open class ClockSection
+class ClockSection
 @Inject
 constructor(
     private val clockInteractor: KeyguardClockInteractor,
@@ -66,23 +65,18 @@
     val smartspaceViewModel: KeyguardSmartspaceViewModel,
     val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
 ) : KeyguardSection() {
-    private var handle: DisposableHandle? = null
-
     override fun addViews(constraintLayout: ConstraintLayout) {}
-
     override fun bindData(constraintLayout: ConstraintLayout) {
         if (!MigrateClocksToBlueprint.isEnabled) {
             return
         }
-        handle?.dispose()
-        handle =
-            KeyguardClockViewBinder.bind(
-                this,
-                constraintLayout,
-                keyguardClockViewModel,
-                clockInteractor,
-                blueprintInteractor.get()
-            )
+        KeyguardClockViewBinder.bind(
+            this,
+            constraintLayout,
+            keyguardClockViewModel,
+            clockInteractor,
+            blueprintInteractor.get()
+        )
     }
 
     override fun applyConstraints(constraintSet: ConstraintSet) {
@@ -94,13 +88,7 @@
         }
     }
 
-    override fun removeViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-        handle?.dispose()
-        handle = null
-    }
+    override fun removeViews(constraintLayout: ConstraintLayout) {}
 
     private fun buildConstraints(
         clock: ClockController,
@@ -117,21 +105,18 @@
             setVisibility(getNonTargetClockFace(clock).views, GONE)
             setAlpha(getTargetClockFace(clock).views, 1F)
             setAlpha(getNonTargetClockFace(clock).views, 0F)
-            if (!keyguardClockViewModel.useLargeClock) {
+            if (!keyguardClockViewModel.isLargeClockVisible.value) {
                 connect(sharedR.id.bc_smartspace_view, TOP, sharedR.id.date_smartspace_view, BOTTOM)
             }
         }
     }
 
     private fun getTargetClockFace(clock: ClockController): ClockFaceLayout =
-        if (keyguardClockViewModel.useLargeClock) getLargeClockFace(clock)
-        else getSmallClockFace(clock)
+        if (keyguardClockViewModel.isLargeClockVisible.value) clock.largeClock.layout
+        else clock.smallClock.layout
     private fun getNonTargetClockFace(clock: ClockController): ClockFaceLayout =
-        if (keyguardClockViewModel.useLargeClock) getSmallClockFace(clock)
-        else getLargeClockFace(clock)
-
-    private fun getLargeClockFace(clock: ClockController): ClockFaceLayout = clock.largeClock.layout
-    private fun getSmallClockFace(clock: ClockController): ClockFaceLayout = clock.smallClock.layout
+        if (keyguardClockViewModel.isLargeClockVisible.value) clock.smallClock.layout
+        else clock.largeClock.layout
 
     fun constrainWeatherClockDateIconsBarrier(constraints: ConstraintSet) {
         constraints.apply {
@@ -170,27 +155,27 @@
             connect(R.id.lockscreen_clock_view_large, START, PARENT_ID, START)
             connect(R.id.lockscreen_clock_view_large, END, guideline, END)
             connect(R.id.lockscreen_clock_view_large, BOTTOM, R.id.device_entry_icon_view, TOP)
-            var largeClockTopMargin = KeyguardClockViewModel.getLargeClockTopMargin(context)
-            largeClockTopMargin += getDimen(DATE_WEATHER_VIEW_HEIGHT)
-            largeClockTopMargin += getDimen(ENHANCED_SMARTSPACE_HEIGHT)
-
+            val largeClockTopMargin =
+                keyguardClockViewModel.getLargeClockTopMargin() +
+                    getDimen(DATE_WEATHER_VIEW_HEIGHT) +
+                    getDimen(ENHANCED_SMARTSPACE_HEIGHT)
             connect(R.id.lockscreen_clock_view_large, TOP, PARENT_ID, TOP, largeClockTopMargin)
             constrainWidth(R.id.lockscreen_clock_view_large, WRAP_CONTENT)
             constrainHeight(R.id.lockscreen_clock_view_large, MATCH_CONSTRAINT)
             constrainWidth(R.id.lockscreen_clock_view, WRAP_CONTENT)
             constrainHeight(
                 R.id.lockscreen_clock_view,
-                context.resources.getDimensionPixelSize(customizationR.dimen.small_clock_height)
+                context.resources.getDimensionPixelSize(custR.dimen.small_clock_height)
             )
             connect(
                 R.id.lockscreen_clock_view,
                 START,
                 PARENT_ID,
                 START,
-                context.resources.getDimensionPixelSize(customizationR.dimen.clock_padding_start) +
+                context.resources.getDimensionPixelSize(custR.dimen.clock_padding_start) +
                     context.resources.getDimensionPixelSize(R.dimen.status_view_margin_horizontal)
             )
-            val smallClockTopMargin = keyguardClockViewModel.getSmallClockTopMargin(context)
+            val smallClockTopMargin = keyguardClockViewModel.getSmallClockTopMargin()
             create(R.id.small_clock_guideline_top, ConstraintSet.HORIZONTAL_GUIDELINE)
             setGuidelineBegin(R.id.small_clock_guideline_top, smallClockTopMargin)
             connect(R.id.lockscreen_clock_view, TOP, R.id.small_clock_guideline_top, BOTTOM)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 865e989..29041d1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -30,7 +30,6 @@
 import com.android.keyguard.LockIconViewController
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
@@ -48,7 +47,6 @@
 import com.android.systemui.statusbar.VibratorHelper
 import dagger.Lazy
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
@@ -69,7 +67,6 @@
     private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
     private val falsingManager: Lazy<FalsingManager>,
     private val vibratorHelper: Lazy<VibratorHelper>,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
 ) : KeyguardSection() {
     private val deviceEntryIconViewId = R.id.device_entry_icon_view
 
@@ -107,7 +104,6 @@
                     deviceEntryBackgroundViewModel.get(),
                     falsingManager.get(),
                     vibratorHelper.get(),
-                    mainImmediateDispatcher,
                 )
             }
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 27ca5cd..45b8257 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -35,7 +35,6 @@
 import com.android.systemui.statusbar.KeyguardIndicationController
 import com.android.systemui.statusbar.VibratorHelper
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 
 class DefaultShortcutsSection
 @Inject
@@ -47,7 +46,6 @@
     private val falsingManager: FalsingManager,
     private val indicationController: KeyguardIndicationController,
     private val vibratorHelper: VibratorHelper,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
 ) : BaseShortcutSection() {
     override fun addViews(constraintLayout: ConstraintLayout) {
         if (KeyguardBottomAreaRefactor.isEnabled) {
@@ -65,7 +63,6 @@
                     keyguardQuickAffordancesCombinedViewModel.transitionAlpha,
                     falsingManager,
                     vibratorHelper,
-                    mainImmediateDispatcher,
                 ) {
                     indicationController.showTransientIndication(it)
                 }
@@ -76,7 +73,6 @@
                     keyguardQuickAffordancesCombinedViewModel.transitionAlpha,
                     falsingManager,
                     vibratorHelper,
-                    mainImmediateDispatcher,
                 ) {
                     indicationController.showTransientIndication(it)
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
index eaa5e33..9ec7a65 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.view.View
-import android.view.View.GONE
 import android.view.ViewTreeObserver.OnGlobalLayoutListener
 import androidx.constraintlayout.widget.Barrier
 import androidx.constraintlayout.widget.ConstraintLayout
@@ -205,8 +204,7 @@
         smartspaceController.requestSmartspaceUpdate()
 
         constraintSet.apply {
-            setVisibility(
-                sharedR.id.weather_smartspace_view,
+            val weatherVisibility =
                 when (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) {
                     true -> ConstraintSet.GONE
                     false ->
@@ -215,11 +213,18 @@
                             false -> ConstraintSet.GONE
                         }
                 }
+            setVisibility(sharedR.id.weather_smartspace_view, weatherVisibility)
+            setAlpha(
+                sharedR.id.weather_smartspace_view,
+                if (weatherVisibility == ConstraintSet.VISIBLE) 1f else 0f
             )
-            setVisibility(
-                sharedR.id.date_smartspace_view,
+            val dateVisibility =
                 if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) ConstraintSet.GONE
                 else ConstraintSet.VISIBLE
+            setVisibility(sharedR.id.date_smartspace_view, dateVisibility)
+            setAlpha(
+                sharedR.id.date_smartspace_view,
+                if (dateVisibility == ConstraintSet.VISIBLE) 1f else 0f
             )
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
index 4d3a78d..0bc60c4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
@@ -169,10 +169,7 @@
                     return@OnPreDrawListener true
                 }
 
-                anim.duration = duration
-                anim.startDelay = startDelay
-                anim.interpolator = interpolator
-                anim.addListener(
+                val listener =
                     object : AnimatorListenerAdapter() {
                         override fun onAnimationStart(anim: Animator) {
                             assignAnimValues("start", 0f, fromVis)
@@ -183,8 +180,21 @@
                             if (sendToBack) toView.translationZ = 0f
                             toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
                         }
+
+                        override fun onAnimationPause(anim: Animator) {
+                            toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
+                        }
+
+                        override fun onAnimationResume(anim: Animator) {
+                            toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
+                        }
                     }
-                )
+
+                anim.duration = duration
+                anim.startDelay = startDelay
+                anim.interpolator = interpolator
+                anim.addListener(listener)
+                anim.addPauseListener(listener)
 
                 assignAnimValues("init", 0f, fromVis)
                 toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
@@ -213,9 +223,10 @@
             duration = CLOCK_IN_MILLIS
             startDelay = CLOCK_IN_START_DELAY_MILLIS
             interpolator = CLOCK_IN_INTERPOLATOR
-            captureSmartspace = !viewModel.useLargeClock && smartspaceViewModel.isSmartspaceEnabled
+            captureSmartspace =
+                !viewModel.isLargeClockVisible.value && smartspaceViewModel.isSmartspaceEnabled
 
-            if (viewModel.useLargeClock) {
+            if (viewModel.isLargeClockVisible.value) {
                 viewModel.currentClock.value?.let {
                     it.largeClock.layout.views.forEach { addTarget(it) }
                 }
@@ -238,7 +249,7 @@
 
             fromBounds.left = toBounds.left
             fromBounds.right = toBounds.right
-            if (viewModel.useLargeClock) {
+            if (viewModel.isLargeClockVisible.value) {
                 // Large clock shouldn't move
                 fromBounds.top = toBounds.top
                 fromBounds.bottom = toBounds.bottom
@@ -273,9 +284,10 @@
         init {
             duration = CLOCK_OUT_MILLIS
             interpolator = CLOCK_OUT_INTERPOLATOR
-            captureSmartspace = viewModel.useLargeClock && smartspaceViewModel.isSmartspaceEnabled
+            captureSmartspace =
+                viewModel.isLargeClockVisible.value && smartspaceViewModel.isSmartspaceEnabled
 
-            if (viewModel.useLargeClock) {
+            if (viewModel.isLargeClockVisible.value) {
                 addTarget(R.id.lockscreen_clock_view)
             } else {
                 viewModel.currentClock.value?.let {
@@ -298,7 +310,7 @@
 
             toBounds.left = fromBounds.left
             toBounds.right = fromBounds.right
-            if (!viewModel.useLargeClock) {
+            if (!viewModel.isLargeClockVisible.value) {
                 // Large clock shouldn't move
                 toBounds.top = fromBounds.top
                 toBounds.bottom = fromBounds.bottom
@@ -331,7 +343,7 @@
     ) : VisibilityBoundsTransition() {
         init {
             duration =
-                if (viewModel.useLargeClock) STATUS_AREA_MOVE_UP_MILLIS
+                if (viewModel.isLargeClockVisible.value) STATUS_AREA_MOVE_UP_MILLIS
                 else STATUS_AREA_MOVE_DOWN_MILLIS
             interpolator = Interpolators.EMPHASIZED
             addTarget(sharedR.id.date_smartspace_view)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
new file mode 100644
index 0000000..34c1436
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState
+import javax.inject.Inject
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+
+/** View model for accessibility actions placeholder on keyguard */
+class AccessibilityActionsViewModel
+@Inject
+constructor(
+    private val communalInteractor: CommunalInteractor,
+    keyguardInteractor: KeyguardInteractor,
+    keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) {
+    val isCommunalAvailable = communalInteractor.isCommunalAvailable
+
+    // Checks that we are fully in lockscreen, not transitioning to another state, and shade is not
+    // opened.
+    val isOnKeyguard =
+        combine(
+                keyguardTransitionInteractor.transitionValue(KeyguardState.LOCKSCREEN).map {
+                    it == 1f
+                },
+                keyguardInteractor.statusBarState
+            ) { transitionFinishedOnLockscreen, statusBarState ->
+                transitionFinishedOnLockscreen && statusBarState == StatusBarState.KEYGUARD
+            }
+            .distinctUntilChanged()
+
+    fun openCommunalHub() = communalInteractor.changeScene(CommunalScenes.Communal)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
index 06a0c72..5a559fc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
@@ -18,61 +18,29 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import android.graphics.Color
-import com.android.systemui.keyguard.domain.interactor.FromAlternateBouncerTransitionInteractor.Companion.TRANSITION_DURATION_MS
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
-import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
-import com.android.wm.shell.animation.Interpolators
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
 
 @ExperimentalCoroutinesApi
 class AlternateBouncerViewModel
 @Inject
 constructor(
     private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
-    animationFlow: KeyguardTransitionAnimationFlow,
+    keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) {
     // When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be:
     private val alternateBouncerScrimAlpha = .66f
-    private val toAlternateBouncerTransition =
-        animationFlow
-            .setup(
-                duration = TRANSITION_DURATION_MS,
-                from = null,
-                to = ALTERNATE_BOUNCER,
-            )
-            .sharedFlow(
-                duration = TRANSITION_DURATION_MS,
-                onStep = { it },
-                onFinish = { 1f },
-                // Reset on cancel
-                onCancel = { 0f },
-                interpolator = Interpolators.FAST_OUT_SLOW_IN,
-            )
-    private val fromAlternateBouncerTransition =
-        animationFlow
-            .setup(
-                TRANSITION_DURATION_MS,
-                from = ALTERNATE_BOUNCER,
-                to = null,
-            )
-            .sharedFlow(
-                duration = TRANSITION_DURATION_MS,
-                onStep = { 1f - it },
-                // Reset on cancel
-                onCancel = { 0f },
-                interpolator = Interpolators.FAST_OUT_SLOW_IN,
-            )
 
     /** Progress to a fully transitioned alternate bouncer. 1f represents fully transitioned. */
     val transitionToAlternateBouncerProgress =
-        merge(fromAlternateBouncerTransition, toAlternateBouncerTransition)
+        keyguardTransitionInteractor.transitionValue(ALTERNATE_BOUNCER)
 
     val forcePluginOpen: Flow<Boolean> =
         transitionToAlternateBouncerProgress.map { it > 0f }.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt
index 7814576..5cf100e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt
@@ -19,7 +19,6 @@
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.TransitionState
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
@@ -38,12 +37,9 @@
     private val deviceSupportsAlternateBouncer: Flow<Boolean> =
         alternateBouncerInteractor.alternateBouncerSupported
     private val isTransitioningToOrFromOrShowingAlternateBouncer: Flow<Boolean> =
-        keyguardTransitionInteractor.transitions
-            .map {
-                it.to == KeyguardState.ALTERNATE_BOUNCER ||
-                    (it.from == KeyguardState.ALTERNATE_BOUNCER &&
-                        it.transitionState != TransitionState.FINISHED)
-            }
+        keyguardTransitionInteractor
+            .transitionValue(KeyguardState.ALTERNATE_BOUNCER)
+            .map { it > 0f }
             .distinctUntilChanged()
 
     val alternateBouncerWindowRequired: Flow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
index 2054932..644bea0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
@@ -21,7 +21,6 @@
 import android.util.Log
 import android.util.MathUtils
 import com.android.app.animation.Interpolators
-import com.android.keyguard.KeyguardClockSwitch
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
@@ -29,14 +28,10 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.BurnInModel
-import com.android.systemui.keyguard.shared.model.TransitionState
-import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
-import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
+import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.keyguard.ui.StateToValue
-import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.res.R
 import javax.inject.Inject
-import javax.inject.Provider
 import kotlin.math.max
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
@@ -99,9 +94,9 @@
                     occludedToLockscreen,
                     aodToLockscreen ->
                     val translationY =
-                        if (isInTransition(aodToLockscreen.transitionState)) {
+                        if (aodToLockscreen.transitionState.isTransitioning()) {
                             aodToLockscreen.value ?: 0f
-                        } else if (isInTransition(goneToAod.transitionState)) {
+                        } else if (goneToAod.transitionState.isTransitioning()) {
                             (goneToAod.value ?: 0f) + burnInModel.translationY
                         } else {
                             burnInModel.translationY + occludedToLockscreen + keyguardTranslationY
@@ -112,10 +107,6 @@
             .distinctUntilChanged()
     }
 
-    private fun isInTransition(state: TransitionState): Boolean {
-        return state == STARTED || state == RUNNING
-    }
-
     private fun burnIn(
         params: BurnInParameters,
     ): Flow<BurnInModel> {
@@ -128,12 +119,12 @@
                 yDimenResourceId = R.dimen.burn_in_prevention_offset_y
             ),
         ) { interpolated, burnIn ->
+            val useAltAod =
+                keyguardClockViewModel.currentClock.value?.let { clock ->
+                    clock.config.useAlternateSmartspaceAODTransition
+                } == true
             val useScaleOnly =
-                (clockController(params.clockControllerProvider)
-                    ?.get()
-                    ?.config
-                    ?.useAlternateSmartspaceAODTransition
-                    ?: false) && keyguardClockViewModel.clockSize.value == KeyguardClockSwitch.LARGE
+                useAltAod && keyguardClockViewModel.clockSize.value == ClockSize.LARGE
 
             if (useScaleOnly) {
                 BurnInModel(
@@ -164,21 +155,10 @@
             }
         }
     }
-
-    private fun clockController(
-        provider: Provider<ClockController>?,
-    ): Provider<ClockController>? {
-        return if (MigrateClocksToBlueprint.isEnabled) {
-            Provider { keyguardClockViewModel.currentClock.value }
-        } else {
-            provider
-        }
-    }
 }
 
 /** UI-sourced parameters to pass into the various methods of [AodBurnInViewModel]. */
 data class BurnInParameters(
-    val clockControllerProvider: Provider<ClockController>? = null,
     /** System insets that keyguard needs to stay out of */
     val topInset: Int = 0,
     /** The min y-value of the visible elements on lockscreen */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
index fe88b81..24429fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
@@ -18,9 +18,8 @@
 
 import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
@@ -44,13 +43,12 @@
     private val statusBarStateController: SysuiStatusBarStateController,
     private val primaryBouncerInteractor: PrimaryBouncerInteractor,
     private val keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>,
-    private val featureFlags: FeatureFlagsClassic,
     private val shadeInteractor: ShadeInteractor,
     private val animationFlow: KeyguardTransitionAnimationFlow,
 ) {
     /** Common fade for scrim alpha values during *BOUNCER->GONE */
     fun scrimAlpha(duration: Duration, fromState: KeyguardState): Flow<ScrimAlpha> {
-        return if (featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        return if (RefactorKeyguardDismissIntent.isEnabled) {
             keyguardDismissActionInteractor
                 .get()
                 .willAnimateDismissActionOnLockscreen
@@ -104,7 +102,7 @@
                 to = GONE,
             )
 
-        return shadeInteractor.shadeExpansion.flatMapLatest { shadeExpansion ->
+        return shadeInteractor.isAnyExpanded.flatMapLatest { isAnyExpanded ->
             transitionAnimation
                 .sharedFlow(
                     duration = duration,
@@ -112,7 +110,7 @@
                     onStart = {
                         leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide()
                         willRunDismissFromKeyguard = willRunAnimationOnKeyguard()
-                        isShadeExpanded = shadeExpansion > 0f
+                        isShadeExpanded = isAnyExpanded
                     },
                     onStep = { 1f - it },
                 )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index 49fffdd..45dca99 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -30,7 +30,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.util.kotlin.sample
 import dagger.Lazy
@@ -64,7 +64,6 @@
     transitionInteractor: KeyguardTransitionInteractor,
     val keyguardInteractor: KeyguardInteractor,
     val viewModel: AodToLockscreenTransitionViewModel,
-    private val sceneContainerFlags: SceneContainerFlags,
     private val keyguardViewController: Lazy<KeyguardViewController>,
     private val deviceEntryInteractor: DeviceEntryInteractor,
     private val deviceEntrySourceInteractor: DeviceEntrySourceInteractor,
@@ -242,7 +241,7 @@
         }
 
     suspend fun onLongPress() {
-        if (sceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled) {
             deviceEntryInteractor.attemptDeviceEntry()
         } else {
             keyguardViewController.get().showPrimaryBouncer(/* scrim */ true)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
index d948e47e..7468675 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
@@ -19,7 +19,6 @@
 import com.android.app.animation.Interpolators.EMPHASIZED
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import com.android.systemui.res.R
@@ -38,10 +37,7 @@
 constructor(
     animationFlow: KeyguardTransitionAnimationFlow,
     configurationInteractor: ConfigurationInteractor,
-    private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor,
 ) {
-    fun startTransition() = fromDreamingTransitionInteractor.startToGlanceableHubTransition()
-
     private val transitionAnimation =
         animationFlow.setup(
             duration = TO_GLANCEABLE_HUB_DURATION,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
index edd3318..b1f1898 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
@@ -18,7 +18,6 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
-import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import javax.inject.Inject
 
 class KeyguardBlueprintViewModel
@@ -26,7 +25,7 @@
 constructor(
     keyguardBlueprintInteractor: KeyguardBlueprintInteractor,
 ) {
-    var currentBluePrint: KeyguardBlueprint? = null
     val blueprint = keyguardBlueprintInteractor.blueprint
+    val blueprintId = keyguardBlueprintInteractor.blueprintId
     val refreshTransition = keyguardBlueprintInteractor.refreshTransition
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
index f6f3bb1..1f544c1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
@@ -16,25 +16,26 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import android.content.Context
+import android.content.res.Resources
 import androidx.annotation.VisibleForTesting
 import androidx.constraintlayout.helper.widget.Layer
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.keyguard.KeyguardClockSwitch.SMALL
-import com.android.systemui.customization.R as customizationR
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.customization.R as customR
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.shared.ComposeLockscreen
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.res.R
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
-import com.android.systemui.util.Utils
+import com.android.systemui.statusbar.ui.SystemBarUtilsProxy
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
@@ -45,48 +46,48 @@
 class KeyguardClockViewModel
 @Inject
 constructor(
-    keyguardInteractor: KeyguardInteractor,
-    private val keyguardClockInteractor: KeyguardClockInteractor,
+    keyguardClockInteractor: KeyguardClockInteractor,
     @Application private val applicationScope: CoroutineScope,
     notifsKeyguardInteractor: NotificationsKeyguardInteractor,
-    @VisibleForTesting val shadeInteractor: ShadeInteractor,
+    @get:VisibleForTesting val shadeInteractor: ShadeInteractor,
+    private val systemBarUtils: SystemBarUtilsProxy,
+    configurationInteractor: ConfigurationInteractor,
+    @Main private val resources: Resources,
 ) {
     var burnInLayer: Layer? = null
-    val useLargeClock: Boolean
-        get() = clockSize.value == LARGE
 
-    val clockSize =
-        combine(keyguardClockInteractor.selectedClockSize, keyguardClockInteractor.clockSize) {
-                selectedSize,
-                clockSize ->
-                if (selectedSize == SettingsClockSize.SMALL) {
-                    SMALL
-                } else {
-                    clockSize
-                }
+    val clockSize: StateFlow<ClockSize> =
+        combine(
+                keyguardClockInteractor.selectedClockSize,
+                keyguardClockInteractor.clockSize,
+            ) { selectedSize, clockSize ->
+                if (selectedSize == ClockSizeSetting.SMALL) ClockSize.SMALL else clockSize
             }
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = LARGE,
+                initialValue = ClockSize.LARGE,
             )
 
-    val isLargeClockVisible =
+    val isLargeClockVisible: StateFlow<Boolean> =
         clockSize
-            .map { it == LARGE }
+            .map { it == ClockSize.LARGE }
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = false,
+                initialValue = true,
             )
 
     val currentClock = keyguardClockInteractor.currentClock
 
     val hasCustomWeatherDataDisplay =
-        combine(clockSize, currentClock) { size, clock ->
-                clock?.let {
-                    (if (size == LARGE) clock.largeClock.config.hasCustomWeatherDataDisplay
-                    else clock.smallClock.config.hasCustomWeatherDataDisplay)
+        combine(
+                isLargeClockVisible,
+                currentClock,
+            ) { isLargeClock, clock ->
+                clock?.let { clock ->
+                    val face = if (isLargeClock) clock.largeClock else clock.smallClock
+                    face.config.hasCustomWeatherDataDisplay
                 }
                     ?: false
             }
@@ -98,7 +99,7 @@
             )
 
     val clockShouldBeCentered: StateFlow<Boolean> =
-        keyguardInteractor.clockShouldBeCentered.stateIn(
+        keyguardClockInteractor.clockShouldBeCentered.stateIn(
             scope = applicationScope,
             started = SharingStarted.WhileSubscribed(),
             initialValue = false
@@ -112,18 +113,32 @@
         )
 
     val currentClockLayout: StateFlow<ClockLayout> =
-        combine(isLargeClockVisible, clockShouldBeCentered, shadeInteractor.shadeMode) {
+        combine(
                 isLargeClockVisible,
                 clockShouldBeCentered,
-                shadeMode ->
+                shadeInteractor.shadeMode,
+                currentClock,
+            ) { isLargeClockVisible, clockShouldBeCentered, shadeMode, currentClock ->
                 val shouldUseSplitShade = shadeMode == ShadeMode.Split
-                when {
-                    shouldUseSplitShade && clockShouldBeCentered -> ClockLayout.LARGE_CLOCK
-                    shouldUseSplitShade && isLargeClockVisible ->
-                        ClockLayout.SPLIT_SHADE_LARGE_CLOCK
-                    shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
-                    isLargeClockVisible -> ClockLayout.LARGE_CLOCK
-                    else -> ClockLayout.SMALL_CLOCK
+                if (currentClock?.config?.useCustomClockScene == true) {
+                    when {
+                        shouldUseSplitShade && clockShouldBeCentered ->
+                            ClockLayout.WEATHER_LARGE_CLOCK
+                        shouldUseSplitShade && isLargeClockVisible ->
+                            ClockLayout.SPLIT_SHADE_WEATHER_LARGE_CLOCK
+                        shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
+                        isLargeClockVisible -> ClockLayout.WEATHER_LARGE_CLOCK
+                        else -> ClockLayout.SMALL_CLOCK
+                    }
+                } else {
+                    when {
+                        shouldUseSplitShade && clockShouldBeCentered -> ClockLayout.LARGE_CLOCK
+                        shouldUseSplitShade && isLargeClockVisible ->
+                            ClockLayout.SPLIT_SHADE_LARGE_CLOCK
+                        shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
+                        isLargeClockVisible -> ClockLayout.LARGE_CLOCK
+                        else -> ClockLayout.SMALL_CLOCK
+                    }
                 }
             }
             .stateIn(
@@ -144,39 +159,41 @@
             )
 
     /** Calculates the top margin for the small clock. */
-    fun getSmallClockTopMargin(context: Context): Int {
-        var topMargin: Int
-        val statusBarHeight = Utils.getStatusBarHeaderHeightKeyguard(context)
-
-        if (shadeInteractor.shadeMode.value == ShadeMode.Split) {
-            topMargin =
-                context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)
-            if (ComposeLockscreen.isEnabled) {
-                topMargin -= statusBarHeight
-            }
+    fun getSmallClockTopMargin(): Int {
+        val statusBarHeight = systemBarUtils.getStatusBarHeaderHeightKeyguard()
+        return if (shadeInteractor.shadeMode.value == ShadeMode.Split) {
+            resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) -
+                if (ComposeLockscreen.isEnabled) statusBarHeight else 0
         } else {
-            topMargin = context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)
-            if (!ComposeLockscreen.isEnabled) {
-                topMargin += statusBarHeight
-            }
+            resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
+                if (!ComposeLockscreen.isEnabled) statusBarHeight else 0
         }
-        return topMargin
     }
 
-    companion object {
-        fun getLargeClockTopMargin(context: Context): Int {
-            return context.resources.getDimensionPixelSize(R.dimen.status_bar_height) +
-                context.resources.getDimensionPixelSize(
-                    customizationR.dimen.small_clock_padding_top
-                ) +
-                context.resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset)
+    val smallClockTopMargin =
+        combine(
+            configurationInteractor.onAnyConfigurationChange,
+            shadeInteractor.shadeMode,
+        ) { _, _ ->
+            getSmallClockTopMargin()
         }
+
+    /** Calculates the top margin for the large clock. */
+    fun getLargeClockTopMargin(): Int {
+        return systemBarUtils.getStatusBarHeight() +
+            resources.getDimensionPixelSize(customR.dimen.small_clock_padding_top) +
+            resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset)
     }
 
+    val largeClockTopMargin: Flow<Int> =
+        configurationInteractor.onAnyConfigurationChange.map { getLargeClockTopMargin() }
+
     enum class ClockLayout {
         LARGE_CLOCK,
         SMALL_CLOCK,
         SPLIT_SHADE_LARGE_CLOCK,
         SPLIT_SHADE_SMALL_CLOCK,
+        WEATHER_LARGE_CLOCK,
+        SPLIT_SHADE_WEATHER_LARGE_CLOCK,
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt
index 4f2c6f5..3a825f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewClockViewModel.kt
@@ -16,13 +16,10 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import android.content.Context
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.plugins.clocks.ClockController
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.map
@@ -31,19 +28,17 @@
 class KeyguardPreviewClockViewModel
 @Inject
 constructor(
-    @Application private val context: Context,
     interactor: KeyguardClockInteractor,
-    @Application private val applicationScope: CoroutineScope,
 ) {
 
     var shouldHighlightSelectedAffordance: Boolean = false
     val isLargeClockVisible: Flow<Boolean> =
-        interactor.selectedClockSize.map { it == SettingsClockSize.DYNAMIC }
+        interactor.selectedClockSize.map { it == ClockSizeSetting.DYNAMIC }
 
     val isSmallClockVisible: Flow<Boolean> =
-        interactor.selectedClockSize.map { it == SettingsClockSize.SMALL }
+        interactor.selectedClockSize.map { it == ClockSizeSetting.SMALL }
 
     val previewClock: Flow<ClockController> = interactor.previewClock
 
-    val selectedClockSize: StateFlow<SettingsClockSize?> = interactor.selectedClockSize
+    val selectedClockSize: StateFlow<ClockSizeSetting?> = interactor.selectedClockSize
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt
index a90634e..0a84886 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt
@@ -17,10 +17,8 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import android.content.Context
-import android.content.res.Resources
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.res.R
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
@@ -32,13 +30,12 @@
 class KeyguardPreviewSmartspaceViewModel
 @Inject
 constructor(
-    @Application private val context: Context,
     interactor: KeyguardClockInteractor,
     val smartspaceViewModel: KeyguardSmartspaceViewModel,
     val clockViewModel: KeyguardClockViewModel,
 ) {
 
-    val selectedClockSize: StateFlow<SettingsClockSize> = interactor.selectedClockSize
+    val selectedClockSize: StateFlow<ClockSizeSetting> = interactor.selectedClockSize
 
     val shouldHideSmartspace: Flow<Boolean> =
         combine(
@@ -51,34 +48,34 @@
                     // TODO (b/284122375) This is temporary. We should use clockController
                     //      .largeClock.config.hasCustomWeatherDataDisplay instead, but
                     //      ClockRegistry.createCurrentClock is not reliable.
-                    SettingsClockSize.DYNAMIC -> currentClockId == "DIGITAL_CLOCK_WEATHER"
-                    SettingsClockSize.SMALL -> false
+                    ClockSizeSetting.DYNAMIC -> currentClockId == "DIGITAL_CLOCK_WEATHER"
+                    ClockSizeSetting.SMALL -> false
                 }
             }
 
-    fun getSmartspaceStartPadding(): Int {
+    fun getSmartspaceStartPadding(context: Context): Int {
         return KeyguardSmartspaceViewModel.getSmartspaceStartMargin(context)
     }
 
-    fun getSmartspaceEndPadding(): Int {
+    fun getSmartspaceEndPadding(context: Context): Int {
         return KeyguardSmartspaceViewModel.getSmartspaceEndMargin(context)
     }
 
-    fun getSmallClockSmartspaceTopPadding(splitShadePreview: Boolean): Int {
-        return getSmallClockTopPadding(splitShadePreview) +
+    fun getSmallClockSmartspaceTopPadding(splitShadePreview: Boolean, context: Context): Int {
+        return getSmallClockTopPadding(splitShadePreview, context) +
             context.resources.getDimensionPixelSize(
                 com.android.systemui.customization.R.dimen.small_clock_height
             )
     }
 
-    fun getLargeClockSmartspaceTopPadding(splitShadePreview: Boolean): Int {
-        return getSmallClockTopPadding(splitShadePreview)
+    fun getLargeClockSmartspaceTopPadding(splitShadePreview: Boolean, context: Context): Int {
+        return getSmallClockTopPadding(splitShadePreview, context)
     }
 
     /*
      * SmallClockTopPadding decides the top position of smartspace
      */
-    private fun getSmallClockTopPadding(splitShadePreview: Boolean): Int {
+    private fun getSmallClockTopPadding(splitShadePreview: Boolean, context: Context): Int {
         return with(context.resources) {
             if (splitShadePreview) {
                 getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)
@@ -89,14 +86,4 @@
             }
         }
     }
-    companion object {
-        fun getStatusBarHeight(resource: Resources): Int {
-            var result = 0
-            val resourceId: Int = resource.getIdentifier("status_bar_height", "dimen", "android")
-            if (resourceId > 0) {
-                result = resource.getDimensionPixelSize(resourceId)
-            }
-            return result
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 64e1565..24a7c51 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.util.kotlin.BooleanFlowOperators.or
 import com.android.systemui.util.kotlin.pairwise
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.ui.AnimatableEvent
@@ -133,22 +134,18 @@
     private val isOnLockscreen: Flow<Boolean> =
         combine(
                 keyguardTransitionInteractor.isFinishedInState(LOCKSCREEN).onStart { emit(false) },
-                keyguardTransitionInteractor
-                    .isInTransitionWhere { from, to -> from == LOCKSCREEN || to == LOCKSCREEN }
-                    .onStart { emit(false) }
+                or(
+                    keyguardTransitionInteractor.isInTransitionToState(LOCKSCREEN),
+                    keyguardTransitionInteractor.isInTransitionFromState(LOCKSCREEN),
+                ),
             ) { onLockscreen, transitioningToOrFromLockscreen ->
                 onLockscreen || transitioningToOrFromLockscreen
             }
             .distinctUntilChanged()
 
-    private val lockscreenToGoneTransitionRunning: Flow<Boolean> =
-        keyguardTransitionInteractor
-            .isInTransitionWhere { from, to -> from == LOCKSCREEN && to == GONE }
-            .onStart { emit(false) }
-
     private val alphaOnShadeExpansion: Flow<Float> =
         combineTransform(
-                lockscreenToGoneTransitionRunning,
+                keyguardTransitionInteractor.isInTransition(from = LOCKSCREEN, to = GONE),
                 isOnLockscreen,
                 shadeInteractor.qsExpansion,
                 shadeInteractor.shadeExpansion,
@@ -185,8 +182,12 @@
                     .transitionValue(OCCLUDED)
                     .map { it == 1f }
                     .onStart { emit(false) },
-            ) { isIdleOnCommunal, isGone, isOccluded ->
-                isIdleOnCommunal || isGone || isOccluded
+                keyguardTransitionInteractor
+                    .transitionValue(KeyguardState.DREAMING)
+                    .map { it == 1f }
+                    .onStart { emit(false) },
+            ) { isIdleOnCommunal, isGone, isOccluded, isDreaming ->
+                isIdleOnCommunal || isGone || isOccluded || isDreaming
             }
             .distinctUntilChanged()
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
index 9e7dbd4..dc053aa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt
@@ -84,7 +84,7 @@
     }
 
     /* trigger clock and smartspace constraints change when smartspace appears */
-    var bcSmartspaceVisibility: StateFlow<Int> = smartspaceInteractor.bcSmartspaceVisibility
+    val bcSmartspaceVisibility: StateFlow<Int> = smartspaceInteractor.bcSmartspaceVisibility
 
     companion object {
         fun getSmartspaceStartMargin(context: Context): Int {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
index 36896f9..c98f3b0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
@@ -17,16 +17,18 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import android.content.res.Resources
-import com.android.keyguard.KeyguardClockSwitch
+import com.android.internal.annotations.VisibleForTesting
 import com.android.keyguard.KeyguardClockSwitch.SMALL
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
+import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.res.R
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
@@ -46,13 +48,12 @@
     val longPress: KeyguardLongPressViewModel,
     val shadeInteractor: ShadeInteractor,
     @Application private val applicationScope: CoroutineScope,
+    private val unfoldTransitionInteractor: UnfoldTransitionInteractor,
 ) {
-    private val clockSize = clockInteractor.clockSize
+    @VisibleForTesting val clockSize = clockInteractor.clockSize
 
     val isUdfpsVisible: Boolean
         get() = authController.isUdfpsSupported
-    val isLargeClockVisible: Boolean
-        get() = clockSize.value == KeyguardClockSwitch.LARGE
 
     val shouldUseSplitNotificationShade: StateFlow<Boolean> =
         shadeInteractor.shadeMode
@@ -64,10 +65,11 @@
             )
 
     val areNotificationsVisible: StateFlow<Boolean> =
-        combine(clockSize, shouldUseSplitNotificationShade) {
+        combine(
                 clockSize,
-                shouldUseSplitNotificationShade ->
-                clockSize == SMALL || shouldUseSplitNotificationShade
+                shouldUseSplitNotificationShade,
+            ) { clockSize, shouldUseSplitNotificationShade ->
+                clockSize == ClockSize.SMALL || shouldUseSplitNotificationShade
             }
             .stateIn(
                 scope = applicationScope,
@@ -75,8 +77,25 @@
                 initialValue = false,
             )
 
+    /** Amount of horizontal translation that should be applied to elements in the scene. */
+    val unfoldTranslations: StateFlow<UnfoldTranslations> =
+        combine(
+                unfoldTransitionInteractor.unfoldTranslationX(isOnStartSide = true),
+                unfoldTransitionInteractor.unfoldTranslationX(isOnStartSide = false),
+            ) { start, end ->
+                UnfoldTranslations(
+                    start = start,
+                    end = end,
+                )
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = UnfoldTranslations(),
+            )
+
     fun getSmartSpacePaddingTop(resources: Resources): Int {
-        return if (isLargeClockVisible) {
+        return if (clockSize.value == ClockSize.LARGE) {
             resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset) +
                 resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)
         } else {
@@ -94,4 +113,20 @@
                 initialValue = interactor.getCurrentBlueprint().id,
             )
     }
+
+    data class UnfoldTranslations(
+
+        /**
+         * Amount of horizontal translation to apply to elements that are aligned to the start side
+         * (left in left-to-right layouts). Can also be used as horizontal padding for elements that
+         * need horizontal padding on both side. In pixels.
+         */
+        val start: Float = 0f,
+
+        /**
+         * Amount of horizontal translation to apply to elements that are aligned to the end side
+         * (right in left-to-right layouts). In pixels.
+         */
+        val end: Float = 0f,
+    )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
index 993e81b..d4c8456e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
@@ -37,6 +37,8 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.stateIn
 
 /** Models UI state and handles user input for the lockscreen scene. */
@@ -52,16 +54,23 @@
     val notifications: NotificationsPlaceholderViewModel,
 ) {
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
-        combine(
-                deviceEntryInteractor.isUnlocked,
-                communalInteractor.isCommunalAvailable,
-                shadeInteractor.shadeMode,
-            ) { isDeviceUnlocked, isCommunalAvailable, shadeMode ->
-                destinationScenes(
-                    isDeviceUnlocked = isDeviceUnlocked,
-                    isCommunalAvailable = isCommunalAvailable,
-                    shadeMode = shadeMode,
-                )
+        shadeInteractor.isShadeTouchable
+            .flatMapLatest { isShadeTouchable ->
+                if (!isShadeTouchable) {
+                    flowOf(emptyMap())
+                } else {
+                    combine(
+                        deviceEntryInteractor.isUnlocked,
+                        communalInteractor.isCommunalAvailable,
+                        shadeInteractor.shadeMode,
+                    ) { isDeviceUnlocked, isCommunalAvailable, shadeMode ->
+                        destinationScenes(
+                            isDeviceUnlocked = isDeviceUnlocked,
+                            isCommunalAvailable = isCommunalAvailable,
+                            shadeMode = shadeMode,
+                        )
+                    }
+                }
             }
             .stateIn(
                 scope = applicationScope,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt
new file mode 100644
index 0000000..d2c9cfb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+
+/** Breaks down OCCLUDED->GONE transition into discrete steps for corresponding views to consume. */
+@ExperimentalCoroutinesApi
+@SysUISingleton
+class OccludedToGoneTransitionViewModel
+@Inject
+constructor(
+    animationFlow: KeyguardTransitionAnimationFlow,
+) {
+    private val transitionAnimation =
+        animationFlow.setup(
+            duration = DEFAULT_DURATION,
+            from = KeyguardState.OCCLUDED,
+            to = KeyguardState.GONE,
+        )
+
+    fun notificationAlpha(viewState: ViewStateAccessor): Flow<Float> {
+        var currentAlpha = 0f
+        return transitionAnimation.sharedFlow(
+            duration = DEFAULT_DURATION,
+            onStart = { currentAlpha = viewState.alpha() },
+            onStep = { currentAlpha },
+            onFinish = { 1f },
+        )
+    }
+
+    companion object {
+        val DEFAULT_DURATION = 300.milliseconds
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index 3a19780..a09d58a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -21,15 +21,21 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
 import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.res.R
+import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
 
 /**
  * Breaks down OCCLUDED->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -43,6 +49,8 @@
     deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
     configurationInteractor: ConfigurationInteractor,
     animationFlow: KeyguardTransitionAnimationFlow,
+    keyguardInteractor: KeyguardInteractor,
+    keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) : DeviceEntryIconTransition {
 
     private val transitionAnimation =
@@ -74,11 +82,28 @@
 
     /** Lockscreen views alpha */
     val lockscreenAlpha: Flow<Float> =
-        transitionAnimation.sharedFlow(
-            startTime = 233.milliseconds,
-            duration = 250.milliseconds,
-            onStep = { it },
-            name = "OCCLUDED->LOCKSCREEN: lockscreenAlpha",
+        merge(
+            transitionAnimation.sharedFlow(
+                startTime = 233.milliseconds,
+                duration = 250.milliseconds,
+                onStep = { it },
+                name = "OCCLUDED->LOCKSCREEN: lockscreenAlpha",
+            ),
+            // Required to fix a bug where the shade expands while lockscreenAlpha=1f, due to a call
+            // to setOccluded(false) triggering a reset() call in KeyguardViewMediator. The
+            // permanent solution is to only expand the shade once the keyguard transition from
+            // OCCLUDED starts, but that requires more refactoring of expansion amounts. For now,
+            // emit alpha = 0f for OCCLUDED -> LOCKSCREEN whenever isOccluded flips from true to
+            // false while currentState == OCCLUDED, so that alpha = 0f when that expansion occurs.
+            // TODO(b/332946323): Remove this once it's no longer needed.
+            keyguardInteractor.isKeyguardOccluded
+                .pairwise()
+                .filter { (wasOccluded, isOccluded) ->
+                    wasOccluded &&
+                        !isOccluded &&
+                        keyguardTransitionInteractor.getCurrentState() == KeyguardState.OCCLUDED
+                }
+                .map { 0f }
         )
 
     val deviceEntryBackgroundViewAlpha: Flow<Float> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
index 0587826..a08a234 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -18,10 +18,9 @@
 
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
@@ -46,7 +45,6 @@
     private val statusBarStateController: SysuiStatusBarStateController,
     private val primaryBouncerInteractor: PrimaryBouncerInteractor,
     keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>,
-    featureFlags: FeatureFlagsClassic,
     bouncerToGoneFlows: BouncerToGoneFlows,
     animationFlow: KeyguardTransitionAnimationFlow,
 ) {
@@ -82,7 +80,7 @@
 
     /** Bouncer container alpha */
     val bouncerAlpha: Flow<Float> =
-        if (featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled) {
             keyguardDismissActionInteractor
                 .get()
                 .willAnimateDismissActionOnLockscreen
@@ -106,7 +104,7 @@
 
     /** Lockscreen alpha */
     val lockscreenAlpha: Flow<Float> =
-        if (featureFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled) {
             keyguardDismissActionInteractor
                 .get()
                 .willAnimateDismissActionOnLockscreen
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
index 00e5d35..c5909ed 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
@@ -96,6 +96,7 @@
                 biometricStatusInteractor.fingerprintAcquiredStatus,
                 deviceEntryFingerprintAuthInteractor.authenticationStatus
             )
+            .distinctUntilChanged()
             .filter {
                 if (it is AcquiredFingerprintAuthenticationStatus) {
                     it.authenticationReason == AuthenticationReason.DeviceEntryAuthentication ||
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index 1c11178..c997617 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -17,6 +17,7 @@
 
 package com.android.systemui.lifecycle
 
+import android.os.Trace
 import android.view.View
 import android.view.ViewTreeObserver
 import androidx.annotation.MainThread
@@ -26,7 +27,9 @@
 import androidx.lifecycle.lifecycleScope
 import com.android.app.tracing.coroutines.createCoroutineTracingContext
 import com.android.app.tracing.coroutines.launch
+import com.android.systemui.Flags.coroutineTracing
 import com.android.systemui.util.Assert
+import com.android.systemui.util.Compile
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
 import kotlinx.coroutines.Dispatchers
@@ -69,6 +72,12 @@
     // presumably want to call view methods that require being called from said UI thread.
     val lifecycleCoroutineContext =
         Dispatchers.Main + createCoroutineTracingContext() + coroutineContext
+    val traceName =
+        if (Compile.IS_DEBUG && coroutineTracing()) {
+            inferTraceSectionName()
+        } else {
+            DEFAULT_TRACE_NAME
+        }
     var lifecycleOwner: ViewLifecycleOwner? = null
     val onAttachListener =
         object : View.OnAttachStateChangeListener {
@@ -77,6 +86,7 @@
                 lifecycleOwner?.onDestroy()
                 lifecycleOwner =
                     createLifecycleOwnerAndRun(
+                        traceName,
                         view,
                         lifecycleCoroutineContext,
                         block,
@@ -93,6 +103,7 @@
     if (view.isAttachedToWindow) {
         lifecycleOwner =
             createLifecycleOwnerAndRun(
+                traceName,
                 view,
                 lifecycleCoroutineContext,
                 block,
@@ -109,18 +120,14 @@
 }
 
 private fun createLifecycleOwnerAndRun(
+    nameForTrace: String,
     view: View,
     coroutineContext: CoroutineContext,
     block: suspend LifecycleOwner.(View) -> Unit,
 ): ViewLifecycleOwner {
     return ViewLifecycleOwner(view).apply {
         onCreate()
-        lifecycleScope.launch(
-            "ViewLifecycleOwner(${view::class.java.simpleName})",
-            coroutineContext
-        ) {
-            block(view)
-        }
+        lifecycleScope.launch(nameForTrace, coroutineContext) { block(view) }
     }
 }
 
@@ -186,3 +193,29 @@
             }
     }
 }
+
+private fun isFrameInteresting(frame: StackWalker.StackFrame): Boolean =
+    frame.className != CURRENT_CLASS_NAME && frame.className != JAVA_ADAPTER_CLASS_NAME
+
+/** Get a name for the trace section include the name of the call site. */
+private fun inferTraceSectionName(): String {
+    try {
+        Trace.traceBegin(Trace.TRACE_TAG_APP, "RepeatWhenAttachedKt#inferTraceSectionName")
+        val interestingFrame =
+            StackWalker.getInstance().walk { stream ->
+                stream.filter(::isFrameInteresting).limit(5).findFirst()
+            }
+        if (interestingFrame.isPresent) {
+            val f = interestingFrame.get()
+            return "${f.className}#${f.methodName}:${f.lineNumber} [$DEFAULT_TRACE_NAME]"
+        } else {
+            return DEFAULT_TRACE_NAME
+        }
+    } finally {
+        Trace.traceEnd(Trace.TRACE_TAG_APP)
+    }
+}
+
+private const val DEFAULT_TRACE_NAME = "repeatWhenAttached"
+private const val CURRENT_CLASS_NAME = "com.android.systemui.lifecycle.RepeatWhenAttachedKt"
+private const val JAVA_ADAPTER_CLASS_NAME = "com.android.systemui.util.kotlin.JavaAdapterKt"
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceEntryIconLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceEntryIconLog.kt
new file mode 100644
index 0000000..f3414b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceEntryIconLog.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.log.dagger
+
+import java.lang.annotation.Documented
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for DeviceEntryIcon state. */
+@Qualifier @Documented @Retention(AnnotationRetention.RUNTIME) annotation class DeviceEntryIconLog
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 f2013be..5babc8b 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -654,4 +654,13 @@
     public static LogBuffer provideNavbarOrientationTrackingLogBuffer(LogBufferFactory factory) {
         return factory.create("NavbarOrientationTrackingLog", 50);
     }
+
+    /** Provides a {@link LogBuffer} for use by the DeviceEntryIcon and related classes. */
+    @Provides
+    @SysUISingleton
+    @DeviceEntryIconLog
+    public static LogBuffer provideDeviceEntryIconLogBuffer(LogBufferFactory factory) {
+        return factory.create("DeviceEntryIconLog", 100);
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/model/MediaSortKeyModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/model/MediaSortKeyModel.kt
new file mode 100644
index 0000000..cfe5cde
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/model/MediaSortKeyModel.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.data.model
+
+import com.android.internal.logging.InstanceId
+import com.android.systemui.media.controls.shared.model.MediaData.Companion.PLAYBACK_LOCAL
+
+data class MediaSortKeyModel(
+    /** Whether the item represents a Smartspace media recommendation that should be prioritized. */
+    val isPrioritizedRec: Boolean = false,
+    val isPlaying: Boolean? = null,
+    val playbackLocation: Int = PLAYBACK_LOCAL,
+    val active: Boolean = true,
+    val isResume: Boolean = false,
+    val lastActive: Long = 0L,
+    val notificationKey: String? = null,
+    val updateTime: Long = 0,
+    val instanceId: InstanceId? = null,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
index df34169..df3a974 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
@@ -18,8 +18,14 @@
 
 import com.android.internal.logging.InstanceId
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.media.controls.data.model.MediaSortKeyModel
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
 import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
+import com.android.systemui.util.time.SystemClock
+import java.util.TreeMap
 import javax.inject.Inject
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -27,7 +33,7 @@
 
 /** A repository that holds the state of filtered media data on the device. */
 @SysUISingleton
-class MediaFilterRepository @Inject constructor() {
+class MediaFilterRepository @Inject constructor(private val systemClock: SystemClock) {
 
     /** Instance id of media control that recommendations card reactivated. */
     private val _reactivatedId: MutableStateFlow<InstanceId?> = MutableStateFlow(null)
@@ -46,6 +52,31 @@
         MutableStateFlow(LinkedHashMap())
     val allUserEntries: StateFlow<Map<String, MediaData>> = _allUserEntries.asStateFlow()
 
+    private val comparator =
+        compareByDescending<MediaSortKeyModel> {
+                it.isPlaying == true && it.playbackLocation == MediaData.PLAYBACK_LOCAL
+            }
+            .thenByDescending {
+                it.isPlaying == true && it.playbackLocation == MediaData.PLAYBACK_CAST_LOCAL
+            }
+            .thenByDescending { it.active }
+            .thenByDescending { it.isPrioritizedRec }
+            .thenByDescending { !it.isResume }
+            .thenByDescending { it.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE }
+            .thenByDescending { it.lastActive }
+            .thenByDescending { it.updateTime }
+            .thenByDescending { it.notificationKey }
+
+    private val _sortedMedia: MutableStateFlow<TreeMap<MediaSortKeyModel, MediaCommonModel>> =
+        MutableStateFlow(TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator))
+    val sortedMedia: StateFlow<Map<MediaSortKeyModel, MediaCommonModel>> =
+        _sortedMedia.asStateFlow()
+
+    private val _isMediaFromRec: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    val isMediaFromRec: StateFlow<Boolean> = _isMediaFromRec.asStateFlow()
+
+    private var mediaFromRecPackageName: String? = null
+
     fun addMediaEntry(key: String, data: MediaData) {
         val entries = LinkedHashMap<String, MediaData>(_allUserEntries.value)
         entries[key] = data
@@ -110,4 +141,80 @@
     fun setReactivatedId(instanceId: InstanceId?) {
         _reactivatedId.value = instanceId
     }
+
+    fun addMediaDataLoadingState(mediaDataLoadingModel: MediaDataLoadingModel) {
+        val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator)
+        sortedMap.putAll(
+            _sortedMedia.value.filter { (_, commonModel) ->
+                commonModel !is MediaCommonModel.MediaControl ||
+                    commonModel.mediaLoadedModel.instanceId != mediaDataLoadingModel.instanceId
+            }
+        )
+
+        _selectedUserEntries.value[mediaDataLoadingModel.instanceId]?.let {
+            val sortKey =
+                MediaSortKeyModel(
+                    isPrioritizedRec = false,
+                    it.isPlaying,
+                    it.playbackLocation,
+                    it.active,
+                    it.resumption,
+                    it.lastActive,
+                    it.notificationKey,
+                    systemClock.currentTimeMillis(),
+                    it.instanceId,
+                )
+
+            if (mediaDataLoadingModel is MediaDataLoadingModel.Loaded) {
+                val isMediaFromRec = isMediaFromRec(it)
+
+                _isMediaFromRec.value = isMediaFromRec
+                if (isMediaFromRec) {
+                    mediaFromRecPackageName = null
+                }
+                sortedMap[sortKey] =
+                    MediaCommonModel.MediaControl(mediaDataLoadingModel, canBeRemoved(it))
+            }
+        }
+
+        _sortedMedia.value = sortedMap
+    }
+
+    fun setRecommendationsLoadingState(smartspaceMediaLoadingModel: SmartspaceMediaLoadingModel) {
+        val isPrioritized =
+            when (smartspaceMediaLoadingModel) {
+                is SmartspaceMediaLoadingModel.Loaded -> smartspaceMediaLoadingModel.isPrioritized
+                else -> false
+            }
+        val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator)
+        sortedMap.putAll(
+            _sortedMedia.value.filter { (_, commonModel) ->
+                commonModel !is MediaCommonModel.MediaRecommendations
+            }
+        )
+
+        val sortKey =
+            MediaSortKeyModel(
+                isPrioritizedRec = isPrioritized,
+                isPlaying = false,
+                active = _smartspaceMediaData.value.isActive,
+            )
+        if (smartspaceMediaLoadingModel is SmartspaceMediaLoadingModel.Loaded) {
+            sortedMap[sortKey] = MediaCommonModel.MediaRecommendations(smartspaceMediaLoadingModel)
+        }
+
+        _sortedMedia.value = sortedMap
+    }
+
+    fun setMediaFromRecPackageName(packageName: String) {
+        mediaFromRecPackageName = packageName
+    }
+
+    private fun canBeRemoved(data: MediaData): Boolean {
+        return data.isPlaying?.let { !it } ?: data.isClearable && !data.active
+    }
+
+    private fun isMediaFromRec(data: MediaData): Boolean {
+        return data.isPlaying == true && mediaFromRecPackageName == data.packageName
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
index d40069c..5432a18 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
@@ -28,7 +28,9 @@
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
 import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME
 import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.settings.UserTracker
@@ -67,10 +69,11 @@
     private val mediaFlags: MediaFlags,
     private val mediaFilterRepository: MediaFilterRepository,
 ) : MediaDataManager.Listener {
-    private val _listeners: MutableSet<Listener> = mutableSetOf()
-    val listeners: Set<Listener>
+    /** Non-UI listeners to media changes. */
+    private val _listeners: MutableSet<MediaDataProcessor.Listener> = mutableSetOf()
+    val listeners: Set<MediaDataProcessor.Listener>
         get() = _listeners.toSet()
-    lateinit var mediaDataManager: MediaDataManager
+    lateinit var mediaDataProcessor: MediaDataProcessor
 
     // Ensure the field (and associated reference) isn't removed during optimization.
     @KeepForWeakReference
@@ -111,8 +114,12 @@
 
         mediaFilterRepository.addSelectedUserMediaEntry(data)
 
+        mediaFilterRepository.addMediaDataLoadingState(
+            MediaDataLoadingModel.Loaded(data.instanceId)
+        )
+
         // Notify listeners
-        listeners.forEach { it.onMediaDataLoaded(data.instanceId) }
+        listeners.forEach { it.onMediaDataLoaded(key, oldKey, data) }
     }
 
     override fun onSmartspaceMediaDataLoaded(
@@ -159,7 +166,7 @@
             // reactivate.
             if (shouldReactivate) {
                 val lastActiveId = sorted.lastKey() // most recently active id
-                // Notify listeners to consider this media active
+                // Update loading state to consider this media active
                 Log.d(TAG, "reactivating $lastActiveId instead of smartspace")
                 mediaFilterRepository.setReactivatedId(lastActiveId)
                 val mediaData = sorted[lastActiveId]!!.copy(active = true)
@@ -168,14 +175,22 @@
                     mediaData.packageName,
                     mediaData.instanceId
                 )
-                listeners.forEach {
-                    it.onMediaDataLoaded(
-                        lastActiveId,
-                        receivedSmartspaceCardLatency =
-                            (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis)
-                                .toInt(),
-                        isSsReactivated = true
-                    )
+                mediaFilterRepository.addMediaDataLoadingState(
+                    MediaDataLoadingModel.Loaded(lastActiveId)
+                )
+                listeners.forEach { listener ->
+                    getKey(lastActiveId)?.let { lastActiveKey ->
+                        listener.onMediaDataLoaded(
+                            lastActiveKey,
+                            lastActiveKey,
+                            mediaData,
+                            receivedSmartspaceCardLatency =
+                                (systemClock.currentTimeMillis() -
+                                        data.headphoneConnectionTimeMillis)
+                                    .toInt(),
+                            isSsReactivated = true
+                        )
+                    }
                 }
             }
         } else if (data.isActive) {
@@ -192,15 +207,21 @@
             smartspaceMediaData.packageName,
             smartspaceMediaData.instanceId
         )
-        listeners.forEach { it.onSmartspaceMediaDataLoaded(key, shouldPrioritizeMutable) }
+        mediaFilterRepository.setRecommendationsLoadingState(
+            SmartspaceMediaLoadingModel.Loaded(key, shouldPrioritizeMutable)
+        )
+        listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) }
     }
 
     override fun onMediaDataRemoved(key: String) {
         mediaFilterRepository.removeMediaEntry(key)?.let { mediaData ->
             val instanceId = mediaData.instanceId
             mediaFilterRepository.removeSelectedUserMediaEntry(instanceId)?.let {
+                mediaFilterRepository.addMediaDataLoadingState(
+                    MediaDataLoadingModel.Removed(instanceId)
+                )
                 // Only notify listeners if something actually changed
-                listeners.forEach { it.onMediaDataRemoved(instanceId) }
+                listeners.forEach { it.onMediaDataRemoved(key) }
             }
         }
     }
@@ -210,10 +231,15 @@
         mediaFilterRepository.reactivatedId.value?.let { lastActiveId ->
             mediaFilterRepository.setReactivatedId(null)
             Log.d(TAG, "expiring reactivated key $lastActiveId")
-            // Notify listeners to update with actual active value
+            // Update loading state with actual active value
             mediaFilterRepository.selectedUserEntries.value[lastActiveId]?.let {
+                mediaFilterRepository.addMediaDataLoadingState(
+                    MediaDataLoadingModel.Loaded(lastActiveId, immediately)
+                )
                 listeners.forEach { listener ->
-                    listener.onMediaDataLoaded(lastActiveId, immediately)
+                    getKey(lastActiveId)?.let { lastActiveKey ->
+                        listener.onMediaDataLoaded(lastActiveKey, lastActiveKey, it, immediately)
+                    }
                 }
             }
         }
@@ -227,6 +253,9 @@
                 )
             )
         }
+        mediaFilterRepository.setRecommendationsLoadingState(
+            SmartspaceMediaLoadingModel.Removed(key, immediately)
+        )
         listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
     }
 
@@ -238,29 +267,43 @@
                 // Only remove media when the profile is unavailable.
                 if (DEBUG) Log.d(TAG, "Removing $key after profile change")
                 mediaFilterRepository.removeSelectedUserMediaEntry(data.instanceId, data)
-                listeners.forEach { listener -> listener.onMediaDataRemoved(data.instanceId) }
+                mediaFilterRepository.addMediaDataLoadingState(
+                    MediaDataLoadingModel.Removed(data.instanceId)
+                )
+                listeners.forEach { listener -> listener.onMediaDataRemoved(key) }
             }
         }
     }
 
     @VisibleForTesting
     internal fun handleUserSwitched() {
-        // If the user changes, remove all current MediaData objects and inform listeners
+        // If the user changes, remove all current MediaData objects.
         val listenersCopy = listeners
         val keyCopy = mediaFilterRepository.selectedUserEntries.value.keys.toMutableList()
-        // Clear the list first, to make sure callbacks from listeners if we have any entries
-        // are up to date
+        // Clear the list first and update loading state to remove media from UI.
         mediaFilterRepository.clearSelectedUserMedia()
         keyCopy.forEach { instanceId ->
             if (DEBUG) Log.d(TAG, "Removing $instanceId after user change")
-            listenersCopy.forEach { listener -> listener.onMediaDataRemoved(instanceId) }
+            mediaFilterRepository.addMediaDataLoadingState(
+                MediaDataLoadingModel.Removed(instanceId)
+            )
+            getKey(instanceId)?.let {
+                listenersCopy.forEach { listener -> listener.onMediaDataRemoved(it) }
+            }
         }
 
         mediaFilterRepository.allUserEntries.value.forEach { (key, data) ->
             if (lockscreenUserManager.isCurrentProfile(data.userId)) {
-                if (DEBUG) Log.d(TAG, "Re-adding $key after user change")
+                if (DEBUG)
+                    Log.d(
+                        TAG,
+                        "Re-adding $key with instanceId=${data.instanceId} after user change"
+                    )
                 mediaFilterRepository.addSelectedUserMediaEntry(data)
-                listenersCopy.forEach { listener -> listener.onMediaDataLoaded(data.instanceId) }
+                mediaFilterRepository.addMediaDataLoadingState(
+                    MediaDataLoadingModel.Loaded(data.instanceId)
+                )
+                listenersCopy.forEach { listener -> listener.onMediaDataLoaded(key, null, data) }
             }
         }
     }
@@ -272,7 +315,7 @@
         mediaEntries.forEach { (key, data) ->
             if (mediaFilterRepository.selectedUserEntries.value.containsKey(data.instanceId)) {
                 // Force updates to listeners, needed for re-activated card
-                mediaDataManager.setInactive(key, timedOut = true, forceUpdate = true)
+                mediaDataProcessor.setInactive(key, timedOut = true, forceUpdate = true)
             }
         }
         val smartspaceMediaData = mediaFilterRepository.smartspaceMediaData.value
@@ -294,7 +337,7 @@
 
             if (mediaFlags.isPersistentSsCardEnabled()) {
                 mediaFilterRepository.setRecommendation(smartspaceMediaData.copy(isActive = false))
-                mediaDataManager.setRecommendationInactive(smartspaceMediaData.targetId)
+                mediaDataProcessor.setRecommendationInactive(smartspaceMediaData.targetId)
             } else {
                 mediaFilterRepository.setRecommendation(
                     EMPTY_SMARTSPACE_MEDIA_DATA.copy(
@@ -302,7 +345,7 @@
                         instanceId = smartspaceMediaData.instanceId,
                     )
                 )
-                mediaDataManager.dismissSmartspaceRecommendation(
+                mediaDataProcessor.dismissSmartspaceRecommendation(
                     smartspaceMediaData.targetId,
                     delay = 0L,
                 )
@@ -311,10 +354,10 @@
     }
 
     /** Add a listener for filtered [MediaData] changes */
-    fun addListener(listener: Listener) = _listeners.add(listener)
+    fun addListener(listener: MediaDataProcessor.Listener) = _listeners.add(listener)
 
     /** Remove a listener that was registered with addListener */
-    fun removeListener(listener: Listener) = _listeners.remove(listener)
+    fun removeListener(listener: MediaDataProcessor.Listener) = _listeners.remove(listener)
 
     /**
      * Return the time since last active for the most-recent media.
@@ -335,46 +378,14 @@
         return sortedEntries[lastActiveInstanceId]?.let { now - it.lastActive } ?: Long.MAX_VALUE
     }
 
-    interface Listener {
-        /**
-         * Called whenever there's new MediaData Loaded for the consumption in views.
-         *
-         * @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.
-         * @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.
-         * @param isSsReactivated indicates resume media card is reactivated by Smartspace
-         *   recommendation signal
-         */
-        fun onMediaDataLoaded(
-            instanceId: InstanceId,
-            immediately: Boolean = true,
-            receivedSmartspaceCardLatency: Int = 0,
-            isSsReactivated: Boolean = false,
-        )
-
-        /**
-         * 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.
-         */
-        fun onSmartspaceMediaDataLoaded(key: String, shouldPrioritize: Boolean = false)
-
-        /** Called whenever a previously existing Media notification was removed. */
-        fun onMediaDataRemoved(instanceId: InstanceId)
-
-        /**
-         * 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.
-         */
-        fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true)
+    private fun getKey(instanceId: InstanceId): String? {
+        val allEntries = mediaFilterRepository.allUserEntries.value
+        val filteredEntries = allEntries.filter { (_, data) -> data.instanceId == instanceId }
+        return if (filteredEntries.isNotEmpty()) {
+            filteredEntries.keys.first()
+        } else {
+            null
+        }
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
index 7412290..1d7c025 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
@@ -590,7 +590,7 @@
     }
 
     /** Dismiss a media entry. Returns false if the key was not found. */
-    fun dismissMediaData(key: String, delay: Long): Boolean {
+    fun dismissMediaData(key: String, delayMs: Long): Boolean {
         val existed = mediaDataRepository.mediaEntries.value[key] != null
         backgroundExecutor.execute {
             mediaDataRepository.mediaEntries.value[key]?.let { mediaData ->
@@ -602,10 +602,21 @@
                 }
             }
         }
-        foregroundExecutor.executeDelayed({ removeEntry(key) }, delay)
+        foregroundExecutor.executeDelayed({ removeEntry(key) }, delayMs)
         return existed
     }
 
+    /** Dismiss a media entry. Returns false if the corresponding key was not found. */
+    fun dismissMediaData(instanceId: InstanceId, delayMs: Long): Boolean {
+        val mediaEntries = mediaDataRepository.mediaEntries.value
+        val filteredEntries = mediaEntries.filter { (_, data) -> data.instanceId == instanceId }
+        return if (filteredEntries.isNotEmpty()) {
+            dismissMediaData(filteredEntries.keys.first(), delayMs)
+        } else {
+            false
+        }
+    }
+
     /**
      * Called whenever the recommendation has been expired or removed by the user. This will remove
      * the recommendation card entirely from the carousel.
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
index c7cfb0b..0e2814b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
@@ -35,6 +35,7 @@
 import com.android.settingslib.media.LocalMediaManager
 import com.android.settingslib.media.MediaDevice
 import com.android.settingslib.media.PhoneMediaDevice
+import com.android.settingslib.media.flags.Flags
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.media.controls.shared.model.MediaData
@@ -178,7 +179,9 @@
             bgExecutor.execute {
                 if (!started) {
                     localMediaManager.registerCallback(this)
-                    localMediaManager.startScan()
+                    if (!Flags.removeUnnecessaryRouteScanning()) {
+                        localMediaManager.startScan()
+                    }
                     muteAwaitConnectionManager.startListening()
                     playbackType = controller?.playbackInfo?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
                     playbackVolumeControlId = controller?.playbackInfo?.volumeControlId
@@ -195,7 +198,9 @@
                 if (started) {
                     started = false
                     controller?.unregisterCallback(this)
-                    localMediaManager.stopScan()
+                    if (!Flags.removeUnnecessaryRouteScanning()) {
+                        localMediaManager.stopScan()
+                    }
                     localMediaManager.unregisterCallback(this)
                     muteAwaitConnectionManager.stopListening()
                     configurationController.removeCallback(configListener)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
index 7dbca0a..13f934e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
@@ -21,6 +21,7 @@
 import android.media.session.MediaSession
 import android.media.session.PlaybackState
 import android.service.notification.StatusBarNotification
+import com.android.internal.logging.InstanceId
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -34,6 +35,8 @@
 import com.android.systemui.media.controls.domain.pipeline.MediaSessionBasedFilter
 import com.android.systemui.media.controls.domain.pipeline.MediaTimeoutListener
 import com.android.systemui.media.controls.domain.resume.MediaResumeListener
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
+import com.android.systemui.media.controls.util.MediaControlsRefactorFlag
 import com.android.systemui.media.controls.util.MediaFlags
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -42,7 +45,6 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.stateIn
 
@@ -76,8 +78,11 @@
                     (smartspaceMediaData.isActive &&
                         (smartspaceMediaData.isValid() || reactivatedKey != null))
             }
-            .distinctUntilChanged()
-            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
 
     /** Are there any media entries we should display, including the recommendations? */
     val hasAnyMediaOrRecommendation: StateFlow<Boolean> =
@@ -92,22 +97,44 @@
                         smartspaceMediaData.isActive && smartspaceMediaData.isValid()
                     })
             }
-            .distinctUntilChanged()
-            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
 
     /** Are there any media notifications active, excluding the recommendations? */
     val hasActiveMedia: StateFlow<Boolean> =
         mediaFilterRepository.selectedUserEntries
             .mapLatest { entries -> entries.any { it.value.active } }
-            .distinctUntilChanged()
-            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
 
     /** Are there any media notifications, excluding the recommendations? */
     val hasAnyMedia: StateFlow<Boolean> =
         mediaFilterRepository.selectedUserEntries
             .mapLatest { entries -> entries.isNotEmpty() }
-            .distinctUntilChanged()
-            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
+
+    /** The most recent sorted set for user media instances */
+    val sortedMedia: StateFlow<List<MediaCommonModel>> =
+        mediaFilterRepository.sortedMedia
+            .mapLatest { it.values.toList() }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = emptyList(),
+            )
+
+    /** Whether the current change in media was done by clicking on a recommendation */
+    val isMediaFromRec: StateFlow<Boolean> = mediaFilterRepository.isMediaFromRec
 
     override fun start() {
         if (!mediaFlags.isMediaControlsRefactorEnabled()) {
@@ -139,13 +166,19 @@
             mediaDataProcessor.onSessionDestroyed(key)
         }
         mediaResumeListener.setManager(this)
-        mediaDataFilter.mediaDataManager = this
+        mediaDataFilter.mediaDataProcessor = mediaDataProcessor
     }
 
-    override fun setInactive(key: String, timedOut: Boolean, forceUpdate: Boolean) {
-        mediaDataProcessor.setInactive(key, timedOut, forceUpdate)
+    override fun addListener(listener: MediaDataManager.Listener) {
+        mediaDataFilter.addListener(listener)
     }
 
+    override fun removeListener(listener: MediaDataManager.Listener) {
+        mediaDataFilter.removeListener(listener)
+    }
+
+    override fun setInactive(key: String, timedOut: Boolean, forceUpdate: Boolean) = unsupported
+
     override fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
         mediaDataProcessor.onNotificationAdded(key, sbn)
     }
@@ -186,13 +219,15 @@
         return mediaDataProcessor.dismissMediaData(key, delay)
     }
 
+    fun removeMediaControl(instanceId: InstanceId, delay: Long) {
+        mediaDataProcessor.dismissMediaData(instanceId, delay)
+    }
+
     override fun dismissSmartspaceRecommendation(key: String, delay: Long) {
         return mediaDataProcessor.dismissSmartspaceRecommendation(key, delay)
     }
 
-    override fun setRecommendationInactive(key: String) {
-        mediaDataProcessor.setRecommendationInactive(key)
-    }
+    override fun setRecommendationInactive(key: String) = unsupported
 
     override fun onNotificationRemoved(key: String) {
         mediaDataProcessor.onNotificationRemoved(key)
@@ -223,4 +258,12 @@
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         mediaDeviceManager.dump(pw)
     }
+
+    companion object {
+        val unsupported: Nothing
+            get() =
+                error(
+                    "Code path not supported when ${MediaControlsRefactorFlag.FLAG_NAME} is enabled"
+                )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
index 5a0388d..c0bb628 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
@@ -16,20 +16,53 @@
 
 package com.android.systemui.media.controls.domain.pipeline.interactor
 
+import android.app.ActivityOptions
+import android.app.BroadcastOptions
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.media.session.MediaController
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
+import android.provider.Settings
+import android.util.Log
+import com.android.internal.jank.Cuj
 import com.android.internal.logging.InstanceId
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.Expandable
+import com.android.systemui.bluetooth.BroadcastDialogController
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
 import com.android.systemui.media.controls.domain.pipeline.MediaDataProcessor
 import com.android.systemui.media.controls.shared.model.MediaControlModel
 import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.dialog.MediaOutputDialogManager
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.kotlin.pairwiseBy
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 
 /** Encapsulates business logic for single media control. */
-class MediaControlInteractor(
-    instanceId: InstanceId,
+class MediaControlInteractor
+@AssistedInject
+constructor(
+    @Application applicationContext: Context,
+    @Assisted private val instanceId: InstanceId,
     repository: MediaFilterRepository,
     private val mediaDataProcessor: MediaDataProcessor,
+    private val keyguardStateController: KeyguardStateController,
+    private val activityStarter: ActivityStarter,
+    private val activityIntentHelper: ActivityIntentHelper,
+    private val lockscreenUserManager: NotificationLockscreenUserManager,
+    private val mediaOutputDialogManager: MediaOutputDialogManager,
+    private val broadcastDialogController: BroadcastDialogController,
 ) {
 
     val mediaControl: Flow<MediaControlModel?> =
@@ -37,8 +70,32 @@
             .map { entries -> entries[instanceId]?.let { toMediaControlModel(it) } }
             .distinctUntilChanged()
 
-    fun removeMediaControl(key: String, delayMs: Long): Boolean {
-        return mediaDataProcessor.dismissMediaData(key, delayMs)
+    val isStartedPlaying: Flow<Boolean> =
+        mediaControl
+            .map { mediaControl ->
+                mediaControl?.token?.let { token ->
+                    MediaController(applicationContext, token).playbackState?.let {
+                        it.state == PlaybackState.STATE_PLAYING
+                    }
+                }
+                    ?: false
+            }
+            .pairwiseBy(initialValue = false) { wasPlaying, isPlaying -> !wasPlaying && isPlaying }
+            .distinctUntilChanged()
+
+    fun removeMediaControl(
+        token: MediaSession.Token?,
+        instanceId: InstanceId,
+        delayMs: Long
+    ): Boolean {
+        val dismissed = mediaDataProcessor.dismissMediaData(instanceId, delayMs)
+        if (!dismissed) {
+            Log.w(
+                TAG,
+                "Manager failed to dismiss media of instanceId=$instanceId, Token uid=${token?.uid}"
+            )
+        }
+        return dismissed
     }
 
     private fun toMediaControlModel(data: MediaData): MediaControlModel {
@@ -53,14 +110,89 @@
                 appName = app,
                 songName = song,
                 artistName = artist,
+                showExplicit = isExplicit,
                 artwork = artwork,
                 deviceData = device,
                 semanticActionButtons = semanticActions,
                 notificationActionButtons = actions,
                 actionsToShowInCollapsed = actionsToShowInCompact,
+                isDismissible = isClearable,
                 isResume = resumption,
                 resumeProgress = resumeProgress,
             )
         }
     }
+
+    fun startSettings() {
+        activityStarter.startActivity(SETTINGS_INTENT, /* dismissShade= */ true)
+    }
+
+    fun startClickIntent(expandable: Expandable, clickIntent: PendingIntent) {
+        if (!launchOverLockscreen(clickIntent)) {
+            activityStarter.postStartActivityDismissingKeyguard(
+                clickIntent,
+                expandable.activityTransitionController(Cuj.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER)
+            )
+        }
+    }
+
+    fun startDeviceIntent(deviceIntent: PendingIntent) {
+        if (deviceIntent.isActivity) {
+            if (!launchOverLockscreen(deviceIntent)) {
+                activityStarter.postStartActivityDismissingKeyguard(deviceIntent)
+            }
+        } else {
+            Log.w(TAG, "Device pending intent of instanceId=$instanceId is not an activity.")
+        }
+    }
+
+    private fun launchOverLockscreen(pendingIntent: PendingIntent): Boolean {
+        val showOverLockscreen =
+            keyguardStateController.isShowing &&
+                activityIntentHelper.wouldPendingShowOverLockscreen(
+                    pendingIntent,
+                    lockscreenUserManager.currentUserId
+                )
+        if (showOverLockscreen) {
+            try {
+                val options = BroadcastOptions.makeBasic()
+                options.isInteractive = true
+                options.pendingIntentBackgroundActivityStartMode =
+                    ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+                pendingIntent.send(options.toBundle())
+            } catch (e: PendingIntent.CanceledException) {
+                Log.e(TAG, "pending intent of $instanceId was canceled")
+            }
+            return true
+        }
+        return false
+    }
+
+    fun startMediaOutputDialog(expandable: Expandable, packageName: String) {
+        mediaOutputDialogManager.createAndShowWithController(
+            packageName,
+            true,
+            expandable.dialogController()
+        )
+    }
+
+    fun startBroadcastDialog(expandable: Expandable, broadcastApp: String, packageName: String) {
+        broadcastDialogController.createBroadcastDialogWithController(
+            broadcastApp,
+            packageName,
+            expandable.dialogTransitionController()
+        )
+    }
+
+    private fun Expandable.dialogController(): DialogTransitionAnimator.Controller? {
+        return dialogTransitionController(
+            cuj =
+                DialogCuj(Cuj.CUJ_SHADE_DIALOG_OPEN, MediaOutputDialogManager.INTERACTION_JANK_TAG)
+        )
+    }
+
+    companion object {
+        private const val TAG = "MediaControlInteractor"
+        private val SETTINGS_INTENT = Intent(Settings.ACTION_MEDIA_CONTROLS_SETTINGS)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
index d57b049..dea5810 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
@@ -49,7 +49,7 @@
 constructor(
     @Application applicationScope: CoroutineScope,
     @Application private val applicationContext: Context,
-    repository: MediaFilterRepository,
+    private val repository: MediaFilterRepository,
     private val mediaDataProcessor: MediaDataProcessor,
     private val broadcastSender: BroadcastSender,
     private val activityStarter: ActivityStarter,
@@ -133,6 +133,10 @@
         }
     }
 
+    fun switchToMediaControl(packageName: String) {
+        repository.setMediaFromRecPackageName(packageName)
+    }
+
     companion object {
 
         private const val TAG = "MediaRecommendationsInteractor"
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/factory/MediaControlInteractorFactory.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/factory/MediaControlInteractorFactory.kt
new file mode 100644
index 0000000..d568600
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/factory/MediaControlInteractorFactory.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.domain.pipeline.interactor.factory
+
+import com.android.internal.logging.InstanceId
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaControlInteractor
+import dagger.assisted.AssistedFactory
+
+/** Factory to create [MediaControlInteractor] for each media control. */
+@SysUISingleton
+@AssistedFactory
+interface MediaControlInteractorFactory {
+
+    fun create(instanceId: InstanceId): MediaControlInteractor
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt
new file mode 100644
index 0000000..23860bb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.shared.model
+
+/** Models any type of media. */
+sealed class MediaCommonModel {
+    data class MediaControl(
+        val mediaLoadedModel: MediaDataLoadingModel.Loaded,
+        val canBeRemoved: Boolean = false,
+    ) : MediaCommonModel()
+
+    data class MediaRecommendations(val recsLoadingModel: SmartspaceMediaLoadingModel) :
+        MediaCommonModel()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt
index d4e34b5..f9134f5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaControlModel.kt
@@ -33,6 +33,7 @@
     val appName: String?,
     val songName: CharSequence?,
     val artistName: CharSequence?,
+    val showExplicit: Boolean,
     val artwork: Icon?,
     val deviceData: MediaDeviceData?,
     /** [MediaButton] contains [MediaAction] objects which represent specific buttons in the UI */
@@ -43,6 +44,7 @@
      * [Notification.MediaStyle.setShowActionsInCompactView].
      */
     val actionsToShowInCollapsed: List<Int>,
+    val isDismissible: Boolean,
     /** Whether player is in resumption state. */
     val isResume: Boolean,
     /** Track seek bar progress (0 - 1) when [isResume] is true. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt
new file mode 100644
index 0000000..170f1f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.shared.model
+
+import com.android.internal.logging.InstanceId
+
+/** Models media data loading state. */
+sealed class MediaDataLoadingModel {
+
+    abstract val instanceId: InstanceId
+
+    /** Media data has been loaded. */
+    data class Loaded(
+        override val instanceId: InstanceId,
+        val immediatelyUpdateUi: Boolean = true,
+    ) : MediaDataLoadingModel()
+
+    /** Media data has been removed. */
+    data class Removed(
+        override val instanceId: InstanceId,
+    ) : MediaDataLoadingModel()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaLoadingModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaLoadingModel.kt
new file mode 100644
index 0000000..90ddadf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaLoadingModel.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.shared.model
+
+/** Models smartspace media loading state. */
+sealed class SmartspaceMediaLoadingModel {
+
+    abstract val key: String
+
+    /** Smartspace media has been loaded. */
+    data class Loaded(
+        override val key: String,
+        val isPrioritized: Boolean = false,
+    ) : SmartspaceMediaLoadingModel()
+
+    /** Smartspace media has been removed. */
+    data class Removed(
+        override val key: String,
+        val immediatelyUpdateUi: Boolean = true,
+    ) : SmartspaceMediaLoadingModel()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
new file mode 100644
index 0000000..8dd3379
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.binder
+
+import android.content.Context
+import android.graphics.BlendMode
+import android.graphics.Color
+import android.graphics.ColorMatrix
+import android.graphics.ColorMatrixColorFilter
+import android.graphics.drawable.Animatable
+import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.LayerDrawable
+import android.graphics.drawable.TransitionDrawable
+import android.os.Trace
+import android.util.Pair
+import android.view.Gravity
+import android.view.View
+import android.widget.ImageButton
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.settingslib.widget.AdaptiveIcon
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.media.controls.ui.animation.AnimationBindHandler
+import com.android.systemui.media.controls.ui.animation.ColorSchemeTransition
+import com.android.systemui.media.controls.ui.controller.MediaViewController
+import com.android.systemui.media.controls.ui.util.MediaArtworkHelper
+import com.android.systemui.media.controls.ui.view.MediaViewHolder
+import com.android.systemui.media.controls.ui.viewmodel.MediaActionViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.MEDIA_PLAYER_SCRIM_END_ALPHA
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.MEDIA_PLAYER_SCRIM_START_ALPHA
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.SEMANTIC_ACTIONS_ALL
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Companion.SEMANTIC_ACTIONS_COMPACT
+import com.android.systemui.media.controls.ui.viewmodel.MediaOutputSwitcherViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaPlayerViewModel
+import com.android.systemui.media.controls.util.MediaDataUtils
+import com.android.systemui.media.controls.util.MediaFlags
+import com.android.systemui.monet.ColorScheme
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.res.R
+import com.android.systemui.surfaceeffects.ripple.MultiRippleView
+import com.android.systemui.surfaceeffects.ripple.RippleAnimation
+import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig
+import com.android.systemui.surfaceeffects.ripple.RippleShader
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+object MediaControlViewBinder {
+
+    fun bind(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaControlViewModel,
+        viewController: MediaViewController,
+        falsingManager: FalsingManager,
+        @Background backgroundDispatcher: CoroutineDispatcher,
+        @Main mainDispatcher: CoroutineDispatcher,
+        mediaFlags: MediaFlags,
+    ) {
+        val mediaCard = viewHolder.player
+        mediaCard.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch {
+                    viewModel.player.collectLatest { playerViewModel ->
+                        playerViewModel?.let {
+                            bindMediaCard(
+                                viewHolder,
+                                viewController,
+                                it,
+                                falsingManager,
+                                backgroundDispatcher,
+                                mainDispatcher,
+                                mediaFlags
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private suspend fun bindMediaCard(
+        viewHolder: MediaViewHolder,
+        viewController: MediaViewController,
+        viewModel: MediaPlayerViewModel,
+        falsingManager: FalsingManager,
+        backgroundDispatcher: CoroutineDispatcher,
+        mainDispatcher: CoroutineDispatcher,
+        mediaFlags: MediaFlags,
+    ) {
+        with(viewHolder) {
+            // AlbumView uses a hardware layer so that clipping of the foreground is handled with
+            // clipping the album art. Otherwise album art shows through at the edges.
+            albumView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
+            turbulenceNoiseView.setBlendMode(BlendMode.SCREEN)
+            loadingEffectView.setBlendMode(BlendMode.SCREEN)
+            loadingEffectView.visibility = View.INVISIBLE
+
+            player.contentDescription =
+                viewModel.contentDescription.invoke(viewController.isGutsVisible)
+            player.setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    if (!viewController.isGutsVisible) {
+                        viewModel.onClicked(Expandable.fromView(player))
+                    }
+                }
+            }
+            player.setOnLongClickListener {
+                if (!falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) {
+                    if (!viewController.isGutsVisible) {
+                        openGuts(viewHolder, viewController, viewModel)
+                    } else {
+                        closeGuts(viewHolder, viewController, viewModel)
+                    }
+                }
+                return@setOnLongClickListener true
+            }
+        }
+
+        viewController.bindSeekBar(viewModel.onSeek, viewModel.onBindSeekbar)
+        bindOutputSwitcherModel(
+            viewHolder,
+            viewModel.outputSwitcher,
+            viewController,
+            falsingManager
+        )
+        bindGutsViewModel(viewHolder, viewModel, viewController, falsingManager)
+        bindActionButtons(viewHolder, viewModel, viewController, falsingManager)
+        bindScrubbingTime(viewHolder, viewModel, viewController)
+
+        val isSongUpdated = bindSongMetadata(viewHolder, viewModel, viewController)
+
+        bindArtworkAndColor(
+            viewHolder,
+            viewModel,
+            viewController,
+            backgroundDispatcher,
+            mainDispatcher,
+            mediaFlags,
+            isSongUpdated
+        )
+
+        // TODO: We don't need to refresh this state constantly, only if the
+        // state actually changed to something which might impact the
+        // measurement. State refresh interferes with the translation
+        // animation, only run it if it's not running.
+        if (!viewController.metadataAnimationHandler.isRunning) {
+            // Don't refresh in scene framework, because it will calculate
+            // with invalid layout sizes
+            if (!mediaFlags.isSceneContainerEnabled()) {
+                viewController.refreshState()
+            }
+        }
+
+        if (viewModel.playTurbulenceNoise) {
+            viewController.setUpTurbulenceNoise()
+        }
+    }
+
+    private fun bindOutputSwitcherModel(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaOutputSwitcherViewModel,
+        viewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        with(viewHolder.seamless) {
+            visibility = View.VISIBLE
+            isEnabled = viewModel.isTapEnabled
+            contentDescription = viewModel.deviceString
+            setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)) {
+                    viewModel.onClicked.invoke(Expandable.fromView(viewHolder.seamlessButton))
+                }
+            }
+        }
+        when (viewModel.deviceIcon) {
+            is Icon.Loaded -> {
+                val icon = viewModel.deviceIcon.drawable
+                if (icon is AdaptiveIcon) {
+                    icon.setBackgroundColor(viewController.colorSchemeTransition.bgColor)
+                }
+                viewHolder.seamlessIcon.setImageDrawable(icon)
+            }
+            is Icon.Resource -> viewHolder.seamlessIcon.setImageResource(viewModel.deviceIcon.res)
+        }
+        viewHolder.seamlessButton.alpha = viewModel.alpha
+        viewHolder.seamlessText.text = viewModel.deviceString
+    }
+
+    private fun bindGutsViewModel(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaPlayerViewModel,
+        viewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        val gutsViewHolder = viewHolder.gutsViewHolder
+        val model = viewModel.gutsMenu
+        with(gutsViewHolder) {
+            gutsText.text = model.gutsText
+            dismissText.visibility = if (model.isDismissEnabled) View.VISIBLE else View.GONE
+            dismiss.isEnabled = model.isDismissEnabled
+            dismiss.setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    model.onDismissClicked.invoke()
+                }
+            }
+            cancelText.background = model.cancelTextBackground
+            cancel.setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    closeGuts(viewHolder, viewController, viewModel)
+                }
+            }
+            settings.setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    model.onSettingsClicked.invoke()
+                }
+            }
+            setDismissible(model.isDismissEnabled)
+            setTextPrimaryColor(model.textPrimaryColor)
+            setAccentPrimaryColor(model.accentPrimaryColor)
+            setSurfaceColor(model.surfaceColor)
+        }
+    }
+
+    private fun bindActionButtons(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaPlayerViewModel,
+        viewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        val genericButtons = MediaViewHolder.genericButtonIds.map { viewHolder.getAction(it) }
+        val expandedSet = viewController.expandedLayout
+        val collapsedSet = viewController.collapsedLayout
+        if (viewModel.useSemanticActions) {
+            // Hide all generic buttons
+            genericButtons.forEach {
+                setVisibleAndAlpha(expandedSet, it.id, false)
+                setVisibleAndAlpha(collapsedSet, it.id, false)
+            }
+
+            SEMANTIC_ACTIONS_ALL.forEachIndexed { index, id ->
+                val button = viewHolder.getAction(id)
+                val actionViewModel = viewModel.actionButtons[index]
+                if (button.id == R.id.actionPrev) {
+                    actionViewModel?.let {
+                        viewController.setUpPrevButtonInfo(true, it.notVisibleValue)
+                    }
+                } else if (button.id == R.id.actionNext) {
+                    actionViewModel?.let {
+                        viewController.setUpNextButtonInfo(true, it.notVisibleValue)
+                    }
+                }
+                actionViewModel?.let { action ->
+                    val animHandler = (button.tag ?: AnimationBindHandler()) as AnimationBindHandler
+                    animHandler.tryExecute {
+                        if (animHandler.updateRebindId(action.rebindId)) {
+                            animHandler.unregisterAll()
+                            animHandler.tryRegister(action.icon)
+                            animHandler.tryRegister(action.background)
+                            bindButtonCommon(
+                                button,
+                                viewHolder.multiRippleView,
+                                action,
+                                viewController,
+                                falsingManager,
+                            )
+                        }
+                        val visible = action.isVisibleWhenScrubbing || !viewController.isScrubbing
+                        setSemanticButtonVisibleAndAlpha(
+                            viewHolder.getAction(id),
+                            viewController.expandedLayout,
+                            viewController.collapsedLayout,
+                            visible,
+                            action.notVisibleValue,
+                            action.showInCollapsed
+                        )
+                    }
+                }
+                    ?: clearButton(button)
+            }
+        } else {
+            // Hide buttons that only appear for semantic actions
+            SEMANTIC_ACTIONS_COMPACT.forEach { buttonId ->
+                setVisibleAndAlpha(expandedSet, buttonId, visible = false)
+                setVisibleAndAlpha(expandedSet, buttonId, visible = false)
+            }
+
+            // Set all generic buttons
+            genericButtons.forEachIndexed { index, button ->
+                if (index < viewModel.actionButtons.size) {
+                    viewModel.actionButtons[index]?.let { action ->
+                        bindButtonCommon(
+                            button,
+                            viewHolder.multiRippleView,
+                            action,
+                            viewController,
+                            falsingManager,
+                        )
+                        setVisibleAndAlpha(expandedSet, button.id, visible = true)
+                        setVisibleAndAlpha(
+                            collapsedSet,
+                            button.id,
+                            visible = action.showInCollapsed
+                        )
+                    }
+                        ?: clearButton(button)
+                } else {
+                    // Hide any unused buttons
+                    clearButton(button)
+                    setVisibleAndAlpha(expandedSet, button.id, visible = false)
+                    setVisibleAndAlpha(collapsedSet, button.id, visible = false)
+                }
+            }
+        }
+        updateSeekBarVisibility(viewController.expandedLayout, isSeekBarEnabled = false)
+    }
+
+    private fun bindButtonCommon(
+        button: ImageButton,
+        multiRippleView: MultiRippleView,
+        actionViewModel: MediaActionViewModel,
+        viewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        button.setImageDrawable(actionViewModel.icon)
+        button.background = actionViewModel.background
+        button.contentDescription = actionViewModel.contentDescription
+        button.isEnabled = actionViewModel.isEnabled
+        if (actionViewModel.isEnabled) {
+            button.setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)) {
+                    actionViewModel.onClicked.invoke(it.id)
+
+                    viewController.multiRippleController.play(
+                        createTouchRippleAnimation(
+                            button,
+                            viewController.colorSchemeTransition,
+                            multiRippleView
+                        )
+                    )
+
+                    if (actionViewModel.icon is Animatable) {
+                        actionViewModel.icon.start()
+                    }
+
+                    if (actionViewModel.background is Animatable) {
+                        actionViewModel.background.start()
+                    }
+                }
+            }
+        }
+    }
+
+    private fun bindSongMetadata(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaPlayerViewModel,
+        viewController: MediaViewController,
+    ): Boolean {
+        val expandedSet = viewController.expandedLayout
+        val collapsedSet = viewController.collapsedLayout
+
+        return viewController.metadataAnimationHandler.setNext(
+            Triple(viewModel.titleName, viewModel.artistName, viewModel.isExplicitVisible),
+            {
+                viewHolder.titleText.text = viewModel.titleName
+                viewHolder.artistText.text = viewModel.artistName
+                setVisibleAndAlpha(
+                    expandedSet,
+                    R.id.media_explicit_indicator,
+                    viewModel.isExplicitVisible
+                )
+                setVisibleAndAlpha(
+                    collapsedSet,
+                    R.id.media_explicit_indicator,
+                    viewModel.isExplicitVisible
+                )
+
+                // refreshState is required here to resize the text views (and prevent ellipsis)
+                viewController.refreshState()
+            },
+            {
+                // After finishing the enter animation, we refresh state. This could pop if
+                // something is incorrectly bound, but needs to be run if other elements were
+                // updated while the enter animation was running
+                viewController.refreshState()
+            }
+        )
+    }
+
+    private suspend fun bindArtworkAndColor(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaPlayerViewModel,
+        viewController: MediaViewController,
+        backgroundDispatcher: CoroutineDispatcher,
+        mainDispatcher: CoroutineDispatcher,
+        mediaFlags: MediaFlags,
+        updateBackground: Boolean,
+    ) {
+        val traceCookie = viewHolder.hashCode()
+        val traceName = "MediaControlViewBinder#bindArtworkAndColor"
+        Trace.beginAsyncSection(traceName, traceCookie)
+        if (updateBackground) {
+            viewController.isArtworkBound = false
+        }
+        // Capture width & height from views in foreground for artwork scaling in background
+        var width = viewHolder.albumView.measuredWidth
+        var height = viewHolder.albumView.measuredHeight
+        if (mediaFlags.isSceneContainerEnabled() && (width <= 0 || height <= 0)) {
+            // TODO(b/312714128): ensure we have a valid size before setting background
+            width = viewController.widthInSceneContainerPx
+            height = viewController.heightInSceneContainerPx
+        }
+        withContext(backgroundDispatcher) {
+            val artwork =
+                if (viewModel.shouldAddGradient) {
+                    addGradientToPlayerAlbum(
+                        viewHolder.albumView.context,
+                        viewModel.backgroundCover!!,
+                        viewModel.colorScheme,
+                        width,
+                        height
+                    )
+                } else {
+                    ColorDrawable(Color.TRANSPARENT)
+                }
+            withContext(mainDispatcher) {
+                // Transition Colors to current color scheme
+                val colorSchemeChanged =
+                    viewController.colorSchemeTransition.updateColorScheme(viewModel.colorScheme)
+                val albumView = viewHolder.albumView
+                albumView.setPadding(0, 0, 0, 0)
+                if (
+                    updateBackground ||
+                        colorSchemeChanged ||
+                        (!viewController.isArtworkBound && viewModel.shouldAddGradient)
+                ) {
+                    viewController.prevArtwork?.let {
+                        // Since we throw away the last transition, this will pop if your
+                        // backgrounds are cycled too fast (or the correct background arrives very
+                        // soon after the metadata changes).
+                        val transitionDrawable = TransitionDrawable(arrayOf(it, artwork))
+
+                        scaleTransitionDrawableLayer(transitionDrawable, 0, width, height)
+                        scaleTransitionDrawableLayer(transitionDrawable, 1, width, height)
+                        transitionDrawable.setLayerGravity(0, Gravity.CENTER)
+                        transitionDrawable.setLayerGravity(1, Gravity.CENTER)
+                        transitionDrawable.isCrossFadeEnabled = true
+
+                        albumView.setImageDrawable(transitionDrawable)
+                        transitionDrawable.startTransition(
+                            if (viewModel.shouldAddGradient) 333 else 80
+                        )
+                    }
+                }
+                viewController.isArtworkBound = viewModel.shouldAddGradient
+                viewController.prevArtwork = artwork
+
+                if (viewModel.useGrayColorFilter) {
+                    // Used for resume players to use launcher icon
+                    viewHolder.appIcon.colorFilter = getGrayscaleFilter()
+                    when (viewModel.launcherIcon) {
+                        is Icon.Loaded ->
+                            viewHolder.appIcon.setImageDrawable(viewModel.launcherIcon.drawable)
+                        is Icon.Resource ->
+                            viewHolder.appIcon.setImageResource(viewModel.launcherIcon.res)
+                    }
+                } else {
+                    viewHolder.appIcon.setColorFilter(
+                        viewController.colorSchemeTransition.accentPrimary.targetColor
+                    )
+                    viewHolder.appIcon.setImageIcon(viewModel.appIcon)
+                }
+                Trace.endAsyncSection(traceName, traceCookie)
+            }
+        }
+    }
+
+    private fun scaleTransitionDrawableLayer(
+        transitionDrawable: TransitionDrawable,
+        layer: Int,
+        targetWidth: Int,
+        targetHeight: Int
+    ) {
+        val drawable = transitionDrawable.getDrawable(layer) ?: return
+        val width = drawable.intrinsicWidth
+        val height = drawable.intrinsicHeight
+        val scale =
+            MediaDataUtils.getScaleFactor(Pair(width, height), Pair(targetWidth, targetHeight))
+        if (scale == 0f) return
+        transitionDrawable.setLayerSize(layer, (scale * width).toInt(), (scale * height).toInt())
+    }
+
+    private fun addGradientToPlayerAlbum(
+        context: Context,
+        artworkIcon: android.graphics.drawable.Icon,
+        mutableColorScheme: ColorScheme,
+        width: Int,
+        height: Int
+    ): LayerDrawable {
+        val albumArt = MediaArtworkHelper.getScaledBackground(context, artworkIcon, width, height)
+        return MediaArtworkHelper.setUpGradientColorOnDrawable(
+            albumArt,
+            context.getDrawable(R.drawable.qs_media_scrim)?.mutate() as GradientDrawable,
+            mutableColorScheme,
+            MEDIA_PLAYER_SCRIM_START_ALPHA,
+            MEDIA_PLAYER_SCRIM_END_ALPHA
+        )
+    }
+
+    private fun clearButton(button: ImageButton) {
+        button.setImageDrawable(null)
+        button.contentDescription = null
+        button.isEnabled = false
+        button.background = null
+    }
+
+    private fun bindScrubbingTime(
+        viewHolder: MediaViewHolder,
+        viewModel: MediaPlayerViewModel,
+        viewController: MediaViewController,
+    ) {
+        val expandedSet = viewController.expandedLayout
+        val visible = viewModel.canShowTime && viewController.isScrubbing
+        viewController.canShowScrubbingTime = viewModel.canShowTime
+        setVisibleAndAlpha(expandedSet, viewHolder.scrubbingElapsedTimeView.id, visible)
+        setVisibleAndAlpha(expandedSet, viewHolder.scrubbingTotalTimeView.id, visible)
+        // Collapsed view is always GONE as set in XML, so doesn't need to be updated dynamically.
+    }
+
+    private fun createTouchRippleAnimation(
+        button: ImageButton,
+        colorSchemeTransition: ColorSchemeTransition,
+        multiRippleView: MultiRippleView
+    ): RippleAnimation {
+        val maxSize = (multiRippleView.width * 2).toFloat()
+        return RippleAnimation(
+            RippleAnimationConfig(
+                RippleShader.RippleShape.CIRCLE,
+                duration = 1500L,
+                centerX = button.x + button.width * 0.5f,
+                centerY = button.y + button.height * 0.5f,
+                maxSize,
+                maxSize,
+                button.context.resources.displayMetrics.density,
+                colorSchemeTransition.accentPrimary.currentColor,
+                opacity = 100,
+                sparkleStrength = 0f,
+                baseRingFadeParams = null,
+                sparkleRingFadeParams = null,
+                centerFillFadeParams = null,
+                shouldDistort = false
+            )
+        )
+    }
+
+    private fun openGuts(
+        viewHolder: MediaViewHolder,
+        viewController: MediaViewController,
+        viewModel: MediaPlayerViewModel,
+    ) {
+        viewHolder.marquee(true, MediaViewController.GUTS_ANIMATION_DURATION)
+        viewController.openGuts()
+        viewHolder.player.contentDescription = viewModel.contentDescription.invoke(true)
+        viewModel.onLongClicked.invoke()
+    }
+
+    private fun closeGuts(
+        viewHolder: MediaViewHolder,
+        viewController: MediaViewController,
+        viewModel: MediaPlayerViewModel,
+    ) {
+        viewHolder.marquee(false, MediaViewController.GUTS_ANIMATION_DURATION)
+        viewController.closeGuts(false)
+        viewHolder.player.contentDescription = viewModel.contentDescription.invoke(false)
+    }
+
+    fun setVisibleAndAlpha(set: ConstraintSet, resId: Int, visible: Boolean) {
+        setVisibleAndAlpha(set, resId, visible, ConstraintSet.GONE)
+    }
+
+    private fun setVisibleAndAlpha(
+        set: ConstraintSet,
+        resId: Int,
+        visible: Boolean,
+        notVisibleValue: Int
+    ) {
+        set.setVisibility(resId, if (visible) ConstraintSet.VISIBLE else notVisibleValue)
+        set.setAlpha(resId, if (visible) 1.0f else 0.0f)
+    }
+
+    fun updateSeekBarVisibility(constraintSet: ConstraintSet, isSeekBarEnabled: Boolean) {
+        if (isSeekBarEnabled) {
+            constraintSet.setVisibility(R.id.media_progress_bar, ConstraintSet.VISIBLE)
+            constraintSet.setAlpha(R.id.media_progress_bar, 1.0f)
+        } else {
+            constraintSet.setVisibility(R.id.media_progress_bar, ConstraintSet.INVISIBLE)
+            constraintSet.setAlpha(R.id.media_progress_bar, 0.0f)
+        }
+    }
+
+    fun setSemanticButtonVisibleAndAlpha(
+        button: ImageButton,
+        expandedSet: ConstraintSet,
+        collapsedSet: ConstraintSet,
+        visible: Boolean,
+        notVisibleValue: Int,
+        showInCollapsed: Boolean
+    ) {
+        if (notVisibleValue == ConstraintSet.INVISIBLE) {
+            // Since time views should appear instead of buttons.
+            button.isFocusable = visible
+            button.isClickable = visible
+        }
+        setVisibleAndAlpha(expandedSet, button.id, visible, notVisibleValue)
+        setVisibleAndAlpha(collapsedSet, button.id, visible = visible && showInCollapsed)
+    }
+
+    private fun getGrayscaleFilter(): ColorMatrixColorFilter {
+        val matrix = ColorMatrix()
+        matrix.setSaturation(0f)
+        return ColorMatrixColorFilter(matrix)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
new file mode 100644
index 0000000..fe13da6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.binder
+
+import android.content.Context
+import android.content.res.ColorStateList
+import android.content.res.Configuration
+import android.graphics.Matrix
+import android.util.TypedValue
+import android.view.View
+import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.animation.Expandable
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.media.controls.shared.model.NUM_REQUIRED_RECOMMENDATIONS
+import com.android.systemui.media.controls.ui.controller.MediaViewController
+import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
+import com.android.systemui.media.controls.ui.viewmodel.MediaRecViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaRecommendationsViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaRecsCardViewModel
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.res.R
+import com.android.systemui.util.animation.TransitionLayout
+import kotlin.math.min
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
+
+object MediaRecommendationsViewBinder {
+
+    /** Binds recommendations view holder to the given view-model */
+    fun bind(
+        viewHolder: RecommendationViewHolder,
+        viewModel: MediaRecommendationsViewModel,
+        mediaViewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        mediaViewController.recsConfigurationChangeListener = this::updateRecommendationsVisibility
+        val cardView = viewHolder.recommendations
+        cardView.repeatWhenAttached {
+            lifecycleScope.launch {
+                repeatOnLifecycle(Lifecycle.State.STARTED) {
+                    launch {
+                        viewModel.mediaRecsCard.collectLatest { viewModel ->
+                            viewModel?.let {
+                                bindRecsCard(viewHolder, it, mediaViewController, falsingManager)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private fun bindRecsCard(
+        viewHolder: RecommendationViewHolder,
+        viewModel: MediaRecsCardViewModel,
+        mediaViewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        // Bind main card.
+        viewHolder.cardTitle.setTextColor(viewModel.cardTitleColor)
+        viewHolder.recommendations.backgroundTintList = ColorStateList.valueOf(viewModel.cardColor)
+        viewHolder.recommendations.contentDescription =
+            viewModel.contentDescription.invoke(mediaViewController.isGutsVisible)
+
+        viewHolder.recommendations.setOnClickListener {
+            if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@setOnClickListener
+            viewModel.onClicked(Expandable.fromView(it))
+        }
+
+        viewHolder.recommendations.setOnLongClickListener {
+            if (falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY))
+                return@setOnLongClickListener true
+            if (!mediaViewController.isGutsVisible) {
+                openGuts(viewHolder, viewModel, mediaViewController)
+            } else {
+                closeGuts(viewHolder, viewModel, mediaViewController)
+            }
+            return@setOnLongClickListener true
+        }
+
+        // Bind all recommendations.
+        bindRecommendationsList(viewHolder, viewModel.mediaRecs, falsingManager)
+        updateRecommendationsVisibility(mediaViewController, viewHolder.recommendations)
+
+        // Set visibility of recommendations.
+        val expandedSet: ConstraintSet = mediaViewController.expandedLayout
+        val collapsedSet: ConstraintSet = mediaViewController.collapsedLayout
+        viewHolder.mediaTitles.forEach {
+            setVisibleAndAlpha(expandedSet, it.id, viewModel.areTitlesVisible)
+            setVisibleAndAlpha(collapsedSet, it.id, viewModel.areTitlesVisible)
+        }
+        viewHolder.mediaSubtitles.forEach {
+            setVisibleAndAlpha(expandedSet, it.id, viewModel.areSubtitlesVisible)
+            setVisibleAndAlpha(collapsedSet, it.id, viewModel.areSubtitlesVisible)
+        }
+
+        bindRecommendationsGuts(viewHolder, viewModel, mediaViewController, falsingManager)
+
+        mediaViewController.refreshState()
+    }
+
+    private fun bindRecommendationsGuts(
+        viewHolder: RecommendationViewHolder,
+        viewModel: MediaRecsCardViewModel,
+        mediaViewController: MediaViewController,
+        falsingManager: FalsingManager,
+    ) {
+        val gutsViewHolder = viewHolder.gutsViewHolder
+        val gutsViewModel = viewModel.gutsMenu
+
+        gutsViewHolder.gutsText.text = gutsViewModel.gutsText
+        gutsViewHolder.dismissText.visibility = View.VISIBLE
+        gutsViewHolder.dismiss.isEnabled = true
+        gutsViewHolder.dismiss.setOnClickListener {
+            if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@setOnClickListener
+            closeGuts(viewHolder, viewModel, mediaViewController)
+            gutsViewModel.onDismissClicked.invoke()
+        }
+
+        gutsViewHolder.cancelText.background = gutsViewModel.cancelTextBackground
+        gutsViewHolder.cancel.setOnClickListener {
+            if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                closeGuts(viewHolder, viewModel, mediaViewController)
+            }
+        }
+
+        gutsViewHolder.settings.setOnClickListener {
+            if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                gutsViewModel.onSettingsClicked.invoke()
+            }
+        }
+
+        gutsViewHolder.setDismissible(gutsViewModel.isDismissEnabled)
+        gutsViewHolder.setTextPrimaryColor(gutsViewModel.textPrimaryColor)
+        gutsViewHolder.setAccentPrimaryColor(gutsViewModel.accentPrimaryColor)
+        gutsViewHolder.setSurfaceColor(gutsViewModel.surfaceColor)
+    }
+
+    private fun bindRecommendationsList(
+        viewHolder: RecommendationViewHolder,
+        mediaRecs: List<MediaRecViewModel>,
+        falsingManager: FalsingManager
+    ) {
+        mediaRecs.forEachIndexed { index, mediaRecViewModel ->
+            if (index >= NUM_REQUIRED_RECOMMENDATIONS) return@forEachIndexed
+
+            val appIconView = viewHolder.mediaAppIcons[index]
+            appIconView.clearColorFilter()
+            if (mediaRecViewModel.appIcon != null) {
+                appIconView.setImageDrawable(mediaRecViewModel.appIcon)
+            } else {
+                appIconView.setImageResource(R.drawable.ic_music_note)
+            }
+
+            val mediaCoverContainer = viewHolder.mediaCoverContainers[index]
+            mediaCoverContainer.setOnClickListener {
+                if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@setOnClickListener
+                mediaRecViewModel.onClicked.invoke(Expandable.fromView(it), index)
+            }
+            mediaCoverContainer.setOnLongClickListener {
+                if (falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY))
+                    return@setOnLongClickListener true
+                (it.parent as View).performLongClick()
+                return@setOnLongClickListener true
+            }
+
+            val mediaCover = viewHolder.mediaCoverItems[index]
+            val width: Int =
+                mediaCover.context.resources.getDimensionPixelSize(R.dimen.qs_media_rec_album_width)
+            val height: Int =
+                mediaCover.context.resources.getDimensionPixelSize(
+                    R.dimen.qs_media_rec_album_height_expanded
+                )
+            val coverMatrix = Matrix(mediaCover.imageMatrix)
+            coverMatrix.postScale(1.25f, 1.25f, 0.5f * width, 0.5f * height)
+            mediaCover.imageMatrix = coverMatrix
+            mediaCover.setImageDrawable(mediaRecViewModel.albumIcon)
+            mediaCover.contentDescription = mediaRecViewModel.contentDescription
+
+            val title = viewHolder.mediaTitles[index]
+            title.text = mediaRecViewModel.title
+            title.setTextColor(ColorStateList.valueOf(mediaRecViewModel.titleColor))
+
+            val subtitle = viewHolder.mediaSubtitles[index]
+            subtitle.text = mediaRecViewModel.subtitle
+            subtitle.setTextColor(ColorStateList.valueOf(mediaRecViewModel.subtitleColor))
+
+            val progressBar = viewHolder.mediaProgressBars[index]
+            progressBar.progress = mediaRecViewModel.progress
+            progressBar.progressTintList = ColorStateList.valueOf(mediaRecViewModel.progressColor)
+            if (mediaRecViewModel.progress == 0) {
+                progressBar.visibility = View.GONE
+            }
+        }
+    }
+
+    private fun openGuts(
+        viewHolder: RecommendationViewHolder,
+        viewModel: MediaRecsCardViewModel,
+        mediaViewController: MediaViewController,
+    ) {
+        viewHolder.marquee(true, MediaViewController.GUTS_ANIMATION_DURATION)
+        mediaViewController.openGuts()
+        viewHolder.recommendations.contentDescription = viewModel.contentDescription.invoke(true)
+        viewModel.onLongClicked.invoke()
+    }
+
+    private fun closeGuts(
+        viewHolder: RecommendationViewHolder,
+        mediaRecsCardViewModel: MediaRecsCardViewModel,
+        mediaViewController: MediaViewController,
+    ) {
+        viewHolder.marquee(false, MediaViewController.GUTS_ANIMATION_DURATION)
+        mediaViewController.closeGuts(false)
+        viewHolder.recommendations.contentDescription =
+            mediaRecsCardViewModel.contentDescription.invoke(false)
+    }
+
+    private fun setVisibleAndAlpha(set: ConstraintSet, resId: Int, visible: Boolean) {
+        set.setVisibility(resId, if (visible) ConstraintSet.VISIBLE else ConstraintSet.GONE)
+        set.setAlpha(resId, if (visible) 1.0f else 0.0f)
+    }
+
+    fun updateRecommendationsVisibility(
+        mediaViewController: MediaViewController,
+        cardView: TransitionLayout,
+    ) {
+        val fittedRecsNum = getNumberOfFittedRecommendations(cardView.context)
+        val expandedSet = mediaViewController.expandedLayout
+        val collapsedSet = mediaViewController.collapsedLayout
+        val mediaCoverContainers = getMediaCoverContainers(cardView)
+        // Hide media cover that cannot fit in the recommendation card.
+        mediaCoverContainers.forEachIndexed { index, container ->
+            setVisibleAndAlpha(expandedSet, container.id, index < fittedRecsNum)
+            setVisibleAndAlpha(collapsedSet, container.id, index < fittedRecsNum)
+        }
+    }
+
+    private fun getMediaCoverContainers(cardView: TransitionLayout): List<ViewGroup> {
+        return listOf<ViewGroup>(
+            cardView.requireViewById(R.id.media_cover1_container),
+            cardView.requireViewById(R.id.media_cover2_container),
+            cardView.requireViewById(R.id.media_cover3_container),
+        )
+    }
+
+    private fun getNumberOfFittedRecommendations(context: Context): Int {
+        val res = context.resources
+        val config = res.configuration
+        val defaultDpWidth = res.getInteger(R.integer.default_qs_media_rec_width_dp)
+        val recCoverWidth =
+            (res.getDimensionPixelSize(R.dimen.qs_media_rec_album_width) +
+                res.getDimensionPixelSize(R.dimen.qs_media_info_spacing) * 2)
+
+        // On landscape, media controls should take half of the screen width.
+        val displayAvailableDpWidth =
+            if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                config.screenWidthDp / 2
+            } else {
+                config.screenWidthDp
+            }
+        val fittedNum =
+            if (displayAvailableDpWidth > defaultDpWidth) {
+                val recCoverDefaultWidth =
+                    res.getDimensionPixelSize(R.dimen.qs_media_rec_default_width)
+                recCoverDefaultWidth / recCoverWidth
+            } else {
+                val displayAvailableWidth =
+                    TypedValue.applyDimension(
+                            TypedValue.COMPLEX_UNIT_DIP,
+                            displayAvailableDpWidth.toFloat(),
+                            res.displayMetrics
+                        )
+                        .toInt()
+                displayAvailableWidth / recCoverWidth
+            }
+        return min(fittedNum.toDouble(), NUM_REQUIRED_RECOMMENDATIONS.toDouble()).toInt()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
index 963c602..c02ce3b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
@@ -297,6 +297,7 @@
         }
     }
 
-    private val activeContainer: ViewGroup? =
-        if (useSplitShade) splitShadeContainer else singlePaneContainer
+    // This field is only used to log current active container.
+    private val activeContainer: ViewGroup?
+        get() = if (useSplitShade) splitShadeContainer else singlePaneContainer
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index c3c1e83..d2dd289 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -46,6 +46,8 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
@@ -600,7 +602,8 @@
     @VisibleForTesting
     internal fun listenForAnyStateToGoneKeyguardTransition(scope: CoroutineScope): Job {
         return scope.launch {
-            keyguardTransitionInteractor.anyStateToGoneTransition
+            keyguardTransitionInteractor
+                .transition(to = GONE)
                 .filter { it.transitionState == TransitionState.FINISHED }
                 .collect {
                     showMediaCarousel()
@@ -612,7 +615,8 @@
     @VisibleForTesting
     internal fun listenForAnyStateToLockscreenTransition(scope: CoroutineScope): Job {
         return scope.launch {
-            keyguardTransitionInteractor.anyStateToLockscreenTransition
+            keyguardTransitionInteractor
+                .transition(to = LOCKSCREEN)
                 .filter { it.transitionState == TransitionState.FINISHED }
                 .collect {
                     if (!allowMediaPlayerOnLockScreen) {
@@ -652,8 +656,14 @@
         if (width == widthInSceneContainerPx && height == heightInSceneContainerPx) {
             return
         }
+        if (width <= 0 || height <= 0) {
+            // reject as invalid
+            return
+        }
         widthInSceneContainerPx = width
         heightInSceneContainerPx = height
+        mediaCarouselScrollHandler.playerWidthPlusPadding =
+            width + context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
         updatePlayers(recreateMedia = true)
     }
 
@@ -748,7 +758,7 @@
                     isSsReactivated,
                     debugLogger
                 )
-                updatePlayerToState(newPlayer, noAnimation = true)
+                updatePlayerToState(newPlayer.mediaViewController, noAnimation = true)
                 // Media data added from a recommendation card should starts playing.
                 if (
                     (shouldScrollToKey && data.isPlaying == true) ||
@@ -846,7 +856,7 @@
                 systemClock,
                 debugLogger,
             )
-            updatePlayerToState(newRecs, noAnimation = true)
+            updatePlayerToState(newRecs.mediaViewController, noAnimation = true)
             reorderAllPlayers(curVisibleMediaKey)
             updatePageIndicator()
             mediaFrame.requiresRemeasuring = true
@@ -876,7 +886,7 @@
         val removed =
             MediaPlayerData.removeMediaPlayer(key, dismissMediaData || dismissRecommendation)
         return removed?.apply {
-            mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
+            mediaCarouselScrollHandler.onPrePlayerRemoved(removed.mediaViewHolder?.player)
             mediaContent.removeView(removed.mediaViewHolder?.player)
             mediaContent.removeView(removed.recommendationViewHolder?.recommendations)
             removed.onDestroy()
@@ -970,7 +980,7 @@
             currentEndLocation = endLocation
             currentTransitionProgress = progress
             for (mediaPlayer in MediaPlayerData.players()) {
-                updatePlayerToState(mediaPlayer, immediately)
+                updatePlayerToState(mediaPlayer.mediaViewController, immediately)
             }
             maybeResetSettingsCog()
             updatePageIndicatorAlpha()
@@ -1070,8 +1080,8 @@
         }
     }
 
-    private fun updatePlayerToState(mediaPlayer: MediaControlPanel, noAnimation: Boolean) {
-        mediaPlayer.mediaViewController.setCurrentState(
+    private fun updatePlayerToState(viewController: MediaViewController, noAnimation: Boolean) {
+        viewController.setCurrentState(
             startLocation = currentStartLocation,
             endLocation = currentEndLocation,
             transitionProgress = currentTransitionProgress,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index 899b9ed..e6c785e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -57,6 +57,7 @@
 import android.media.session.PlaybackState;
 import android.os.Process;
 import android.os.Trace;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -118,8 +119,9 @@
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.surfaceeffects.PaintDrawCallback;
 import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect;
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState;
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.AnimationState;
 import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView;
 import com.android.systemui.surfaceeffects.ripple.MultiRippleController;
 import com.android.systemui.surfaceeffects.ripple.MultiRippleView;
@@ -264,15 +266,15 @@
     private boolean mWasPlaying = false;
     private boolean mButtonClicked = false;
 
-    private final LoadingEffect.Companion.PaintDrawCallback mNoiseDrawCallback =
-            new LoadingEffect.Companion.PaintDrawCallback() {
+    private final PaintDrawCallback mNoiseDrawCallback =
+            new PaintDrawCallback() {
                 @Override
-                public void onDraw(@NonNull Paint loadingPaint) {
-                    mMediaViewHolder.getLoadingEffectView().draw(loadingPaint);
+                public void onDraw(@NonNull Paint paint) {
+                    mMediaViewHolder.getLoadingEffectView().draw(paint);
                 }
             };
-    private final LoadingEffect.Companion.AnimationStateChangedCallback mStateChangedCallback =
-            new LoadingEffect.Companion.AnimationStateChangedCallback() {
+    private final LoadingEffect.AnimationStateChangedCallback mStateChangedCallback =
+            new LoadingEffect.AnimationStateChangedCallback() {
                 @Override
                 public void onStateChanged(@NonNull AnimationState oldState,
                         @NonNull AnimationState newState) {
@@ -737,8 +739,11 @@
                                     mPackageName, mMediaViewHolder.getSeamlessButton());
                         } else {
                             mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
-                            mMediaOutputDialogManager.createAndShow(mPackageName, true,
-                                    mMediaViewHolder.getSeamlessButton());
+                            mMediaOutputDialogManager.createAndShow(
+                                    mPackageName,
+                                    /* aboveStatusBar */ true,
+                                    mMediaViewHolder.getSeamlessButton(),
+                                    UserHandle.getUserHandleForUid(mUid));
                         }
                     } else {
                         mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
@@ -747,22 +752,30 @@
                             boolean showOverLockscreen = mKeyguardStateController.isShowing()
                                     && mActivityIntentHelper.wouldPendingShowOverLockscreen(
                                         deviceIntent, mLockscreenUserManager.getCurrentUserId());
-                            if (deviceIntent.isActivity() && !showOverLockscreen) {
-                                mActivityStarter.postStartActivityDismissingKeyguard(deviceIntent);
-                            } else {
-                                try {
-                                    BroadcastOptions options = BroadcastOptions.makeBasic();
-                                    options.setInteractive(true);
-                                    options.setPendingIntentBackgroundActivityStartMode(
+                            if (deviceIntent.isActivity()) {
+                                if (!showOverLockscreen) {
+                                    mActivityStarter.postStartActivityDismissingKeyguard(
+                                            deviceIntent);
+                                } else {
+                                    try {
+                                        BroadcastOptions options = BroadcastOptions.makeBasic();
+                                        options.setInteractive(true);
+                                        options.setPendingIntentBackgroundActivityStartMode(
                                             ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
-                                    deviceIntent.send(options.toBundle());
-                                } catch (PendingIntent.CanceledException e) {
-                                    Log.e(TAG, "Device pending intent was canceled");
+                                        deviceIntent.send(options.toBundle());
+                                    } catch (PendingIntent.CanceledException e) {
+                                        Log.e(TAG, "Device pending intent was canceled");
+                                    }
                                 }
+                            } else {
+                                Log.w(TAG, "Device pending intent is not an activity.");
                             }
                         } else {
-                            mMediaOutputDialogManager.createAndShow(mPackageName, true,
-                                    mMediaViewHolder.getSeamlessButton());
+                            mMediaOutputDialogManager.createAndShow(
+                                    mPackageName,
+                                    /* aboveStatusBar */ true,
+                                    mMediaViewHolder.getSeamlessButton(),
+                                    UserHandle.getUserHandleForUid(mUid));
                         }
                     }
                 });
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index ad7990b..2b59858 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -16,41 +16,74 @@
 
 package com.android.systemui.media.controls.ui.controller
 
+import android.animation.Animator
+import android.animation.AnimatorInflater
+import android.animation.AnimatorSet
 import android.content.Context
 import android.content.res.Configuration
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.drawable.Drawable
+import android.provider.Settings
+import android.view.View
+import android.view.animation.Interpolator
 import androidx.annotation.VisibleForTesting
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
+import com.android.app.animation.Interpolators
 import com.android.app.tracing.traceSection
+import com.android.systemui.Flags
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.media.controls.ui.animation.ColorSchemeTransition
+import com.android.systemui.media.controls.ui.animation.MetadataAnimationHandler
+import com.android.systemui.media.controls.ui.binder.MediaControlViewBinder
+import com.android.systemui.media.controls.ui.binder.MediaRecommendationsViewBinder
+import com.android.systemui.media.controls.ui.binder.SeekBarObserver
 import com.android.systemui.media.controls.ui.controller.MediaCarouselController.Companion.calculateAlpha
 import com.android.systemui.media.controls.ui.view.GutsViewHolder
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.media.controls.ui.view.MediaViewHolder
 import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
+import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel
+import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.surfaceeffects.PaintDrawCallback
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
+import com.android.systemui.surfaceeffects.ripple.MultiRippleController
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
 import com.android.systemui.util.animation.MeasurementInput
 import com.android.systemui.util.animation.MeasurementOutput
 import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.animation.TransitionLayoutController
 import com.android.systemui.util.animation.TransitionViewState
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.settings.GlobalSettings
 import java.lang.Float.max
 import java.lang.Float.min
+import java.util.Random
 import javax.inject.Inject
 
 /**
  * A class responsible for controlling a single instance of a media player handling interactions
  * with the view instance and keeping the media view states up to date.
  */
-class MediaViewController
+open class MediaViewController
 @Inject
 constructor(
     private val context: Context,
     private val configurationController: ConfigurationController,
     private val mediaHostStatesManager: MediaHostStatesManager,
     private val logger: MediaViewLogger,
+    private val seekBarViewModel: SeekBarViewModel,
+    @Main private val mainExecutor: DelayableExecutor,
     private val mediaFlags: MediaFlags,
+    private val globalSettings: GlobalSettings,
 ) {
 
     /**
@@ -69,6 +102,7 @@
     /** A listener when the current dimensions of the player change */
     lateinit var sizeChangedListener: () -> Unit
     lateinit var configurationChangeListener: () -> Unit
+    lateinit var recsConfigurationChangeListener: (MediaViewController, TransitionLayout) -> Unit
     private var firstRefresh: Boolean = true
     @VisibleForTesting private var transitionLayout: TransitionLayout? = null
     private val layoutController = TransitionLayoutController()
@@ -130,6 +164,75 @@
             return transitionLayout?.translationY ?: 0.0f
         }
 
+    /** Whether artwork is bound. */
+    var isArtworkBound: Boolean = false
+
+    /** previous background artwork */
+    var prevArtwork: Drawable? = null
+
+    /** Whether scrubbing time can show */
+    var canShowScrubbingTime: Boolean = false
+
+    /** Whether user is touching the seek bar to change the position */
+    var isScrubbing: Boolean = false
+
+    var isSeekBarEnabled: Boolean = false
+
+    /** Not visible value for previous button when scrubbing */
+    private var prevNotVisibleValue = ConstraintSet.GONE
+    private var isPrevButtonAvailable = false
+
+    /** Not visible value for next button when scrubbing */
+    private var nextNotVisibleValue = ConstraintSet.GONE
+    private var isNextButtonAvailable = false
+
+    /** View holders for controller */
+    lateinit var recommendationViewHolder: RecommendationViewHolder
+    lateinit var mediaViewHolder: MediaViewHolder
+
+    private lateinit var seekBarObserver: SeekBarObserver
+    private lateinit var turbulenceNoiseController: TurbulenceNoiseController
+    private lateinit var loadingEffect: LoadingEffect
+    private lateinit var turbulenceNoiseAnimationConfig: TurbulenceNoiseAnimationConfig
+    private lateinit var noiseDrawCallback: PaintDrawCallback
+    private lateinit var stateChangedCallback: LoadingEffect.AnimationStateChangedCallback
+    internal lateinit var metadataAnimationHandler: MetadataAnimationHandler
+    internal lateinit var colorSchemeTransition: ColorSchemeTransition
+    internal lateinit var multiRippleController: MultiRippleController
+
+    private val scrubbingChangeListener =
+        object : SeekBarViewModel.ScrubbingChangeListener {
+            override fun onScrubbingChanged(scrubbing: Boolean) {
+                if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+                if (isScrubbing == scrubbing) return
+                isScrubbing = scrubbing
+                updateDisplayForScrubbingChange()
+            }
+        }
+
+    private val enabledChangeListener =
+        object : SeekBarViewModel.EnabledChangeListener {
+            override fun onEnabledChanged(enabled: Boolean) {
+                if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+                if (isSeekBarEnabled == enabled) return
+                isSeekBarEnabled = enabled
+                MediaControlViewBinder.updateSeekBarVisibility(expandedLayout, isSeekBarEnabled)
+            }
+        }
+
+    /**
+     * Sets the listening state of the player.
+     *
+     * Should be set to true when the QS panel is open. Otherwise, false. This is a signal to avoid
+     * unnecessary work when the QS panel is closed.
+     *
+     * @param listening True when player should be active. Otherwise, false.
+     */
+    fun setListening(listening: Boolean) {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        seekBarViewModel.listening = listening
+    }
+
     /** A callback for config changes */
     private val configurationListener =
         object : ConfigurationController.ConfigurationListener {
@@ -160,7 +263,17 @@
                             )
                         )
                     }
-                    if (this@MediaViewController::configurationChangeListener.isInitialized) {
+                    if (mediaFlags.isMediaControlsRefactorEnabled()) {
+                        if (
+                            this@MediaViewController::recsConfigurationChangeListener.isInitialized
+                        ) {
+                            transitionLayout?.let {
+                                recsConfigurationChangeListener.invoke(this@MediaViewController, it)
+                            }
+                        }
+                    } else if (
+                        this@MediaViewController::configurationChangeListener.isInitialized
+                    ) {
                         configurationChangeListener.invoke()
                         refreshState()
                     }
@@ -221,6 +334,14 @@
      * Notify this controller that the view has been removed and all listeners should be destroyed
      */
     fun onDestroy() {
+        if (mediaFlags.isMediaControlsRefactorEnabled()) {
+            if (this::seekBarObserver.isInitialized) {
+                seekBarViewModel.progress.removeObserver(seekBarObserver)
+            }
+            seekBarViewModel.removeScrubbingChangeListener(scrubbingChangeListener)
+            seekBarViewModel.removeEnabledChangeListener(enabledChangeListener)
+            seekBarViewModel.onDestroy()
+        }
         mediaHostStatesManager.removeController(this)
         configurationController.removeCallback(configurationListener)
     }
@@ -535,6 +656,187 @@
             )
         }
 
+    fun attachPlayer(mediaViewHolder: MediaViewHolder) {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        this.mediaViewHolder = mediaViewHolder
+
+        // Setting up seek bar.
+        seekBarObserver = SeekBarObserver(mediaViewHolder)
+        seekBarViewModel.progress.observeForever(seekBarObserver)
+        seekBarViewModel.attachTouchHandlers(mediaViewHolder.seekBar)
+        seekBarViewModel.setScrubbingChangeListener(scrubbingChangeListener)
+        seekBarViewModel.setEnabledChangeListener(enabledChangeListener)
+
+        val mediaCard = mediaViewHolder.player
+        attach(mediaViewHolder.player, TYPE.PLAYER)
+
+        val turbulenceNoiseView = mediaViewHolder.turbulenceNoiseView
+        turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView)
+
+        multiRippleController = MultiRippleController(mediaViewHolder.multiRippleView)
+
+        // Metadata Animation
+        val titleText = mediaViewHolder.titleText
+        val artistText = mediaViewHolder.artistText
+        val explicitIndicator = mediaViewHolder.explicitIndicator
+        val enter =
+            loadAnimator(
+                mediaCard.context,
+                R.anim.media_metadata_enter,
+                Interpolators.EMPHASIZED_DECELERATE,
+                titleText,
+                artistText,
+                explicitIndicator
+            )
+        val exit =
+            loadAnimator(
+                mediaCard.context,
+                R.anim.media_metadata_exit,
+                Interpolators.EMPHASIZED_ACCELERATE,
+                titleText,
+                artistText,
+                explicitIndicator
+            )
+        metadataAnimationHandler = MetadataAnimationHandler(exit, enter)
+
+        colorSchemeTransition =
+            ColorSchemeTransition(
+                mediaCard.context,
+                mediaViewHolder,
+                multiRippleController,
+                turbulenceNoiseController
+            )
+
+        // For Turbulence noise.
+        val loadingEffectView = mediaViewHolder.loadingEffectView
+        turbulenceNoiseAnimationConfig =
+            createTurbulenceNoiseConfig(
+                loadingEffectView,
+                turbulenceNoiseView,
+                colorSchemeTransition
+            )
+        noiseDrawCallback =
+            object : PaintDrawCallback {
+                override fun onDraw(paint: Paint) {
+                    loadingEffectView.draw(paint)
+                }
+            }
+        stateChangedCallback =
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (newState === LoadingEffect.AnimationState.NOT_PLAYING) {
+                        loadingEffectView.visibility = View.INVISIBLE
+                    } else {
+                        loadingEffectView.visibility = View.VISIBLE
+                    }
+                }
+            }
+    }
+
+    fun updateAnimatorDurationScale() {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        if (this::seekBarObserver.isInitialized) {
+            seekBarObserver.animationEnabled =
+                globalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f
+        }
+    }
+
+    /** update view with the needed UI changes when user touches seekbar. */
+    private fun updateDisplayForScrubbingChange() {
+        mainExecutor.execute {
+            val isTimeVisible = canShowScrubbingTime && isScrubbing
+            MediaControlViewBinder.setVisibleAndAlpha(
+                expandedLayout,
+                mediaViewHolder.scrubbingTotalTimeView.id,
+                isTimeVisible
+            )
+            MediaControlViewBinder.setVisibleAndAlpha(
+                expandedLayout,
+                mediaViewHolder.scrubbingElapsedTimeView.id,
+                isTimeVisible
+            )
+
+            MediaControlViewModel.SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach { id ->
+                val isButtonVisible: Boolean
+                val notVisibleValue: Int
+                when (id) {
+                    R.id.actionPrev -> {
+                        isButtonVisible = isPrevButtonAvailable && !isTimeVisible
+                        notVisibleValue = prevNotVisibleValue
+                    }
+                    R.id.actionNext -> {
+                        isButtonVisible = isNextButtonAvailable && !isTimeVisible
+                        notVisibleValue = nextNotVisibleValue
+                    }
+                    else -> {
+                        isButtonVisible = !isTimeVisible
+                        notVisibleValue = ConstraintSet.GONE
+                    }
+                }
+                MediaControlViewBinder.setSemanticButtonVisibleAndAlpha(
+                    mediaViewHolder.getAction(id),
+                    expandedLayout,
+                    collapsedLayout,
+                    isButtonVisible,
+                    notVisibleValue,
+                    showInCollapsed = true
+                )
+            }
+
+            if (!metadataAnimationHandler.isRunning) {
+                refreshState()
+            }
+        }
+    }
+
+    fun attachRecommendations(recommendationViewHolder: RecommendationViewHolder) {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        this.recommendationViewHolder = recommendationViewHolder
+
+        attach(recommendationViewHolder.recommendations, TYPE.RECOMMENDATION)
+        recsConfigurationChangeListener =
+            MediaRecommendationsViewBinder::updateRecommendationsVisibility
+    }
+
+    fun bindSeekBar(onSeek: () -> Unit, onBindSeekBar: (SeekBarViewModel) -> Unit) {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        seekBarViewModel.logSeek = onSeek
+        onBindSeekBar.invoke(seekBarViewModel)
+    }
+
+    fun setUpTurbulenceNoise() {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        if (Flags.shaderlibLoadingEffectRefactor()) {
+            if (!this::loadingEffect.isInitialized) {
+                loadingEffect =
+                    LoadingEffect(
+                        TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
+                        turbulenceNoiseAnimationConfig,
+                        noiseDrawCallback,
+                        stateChangedCallback
+                    )
+            }
+            colorSchemeTransition.loadingEffect = loadingEffect
+            loadingEffect.play()
+            mainExecutor.executeDelayed(
+                loadingEffect::finish,
+                MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
+            )
+        } else {
+            turbulenceNoiseController.play(
+                TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
+                turbulenceNoiseAnimationConfig
+            )
+            mainExecutor.executeDelayed(
+                turbulenceNoiseController::finish,
+                MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
+            )
+        }
+    }
+
     /**
      * Obtain a measurement for a given location. This makes sure that the state is up to date and
      * all widgets know their location. Calling this method may create a measurement if we don't
@@ -790,6 +1092,75 @@
                 applyImmediately = true
             )
         }
+
+    @VisibleForTesting
+    protected open fun loadAnimator(
+        context: Context,
+        animId: Int,
+        motionInterpolator: Interpolator?,
+        vararg targets: View?
+    ): AnimatorSet {
+        val animators = ArrayList<Animator>()
+        for (target in targets) {
+            val animator = AnimatorInflater.loadAnimator(context, animId) as AnimatorSet
+            animator.childAnimations[0].interpolator = motionInterpolator
+            animator.setTarget(target)
+            animators.add(animator)
+        }
+        val result = AnimatorSet()
+        result.playTogether(animators)
+        return result
+    }
+
+    private fun createTurbulenceNoiseConfig(
+        loadingEffectView: LoadingEffectView,
+        turbulenceNoiseView: TurbulenceNoiseView,
+        colorSchemeTransition: ColorSchemeTransition
+    ): TurbulenceNoiseAnimationConfig {
+        val targetView: View =
+            if (Flags.shaderlibLoadingEffectRefactor()) {
+                loadingEffectView
+            } else {
+                turbulenceNoiseView
+            }
+        val width = targetView.width
+        val height = targetView.height
+        val random = Random()
+        return TurbulenceNoiseAnimationConfig(
+            gridCount = 2.14f,
+            TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
+            random.nextFloat(),
+            random.nextFloat(),
+            random.nextFloat(),
+            noiseMoveSpeedX = 0.42f,
+            noiseMoveSpeedY = 0f,
+            TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
+            // Color will be correctly updated in ColorSchemeTransition.
+            colorSchemeTransition.accentPrimary.currentColor,
+            screenColor = Color.BLACK,
+            width.toFloat(),
+            height.toFloat(),
+            TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
+            easeInDuration = 1350f,
+            easeOutDuration = 1350f,
+            targetView.context.resources.displayMetrics.density,
+            lumaMatteBlendFactor = 0.26f,
+            lumaMatteOverallBrightness = 0.09f,
+            shouldInverseNoiseLuminosity = false
+        )
+    }
+
+    fun setUpPrevButtonInfo(isAvailable: Boolean, notVisibleValue: Int = ConstraintSet.GONE) {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        isPrevButtonAvailable = isAvailable
+        prevNotVisibleValue = notVisibleValue
+    }
+
+    fun setUpNextButtonInfo(isAvailable: Boolean, notVisibleValue: Int = ConstraintSet.GONE) {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
+        isNextButtonAvailable = isAvailable
+        nextNotVisibleValue = notVisibleValue
+    }
 }
 
 /** An internal key for the cache of mediaViewStates. This is a subset of the full host state. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
index eec43a6..3b09f41 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt
@@ -18,6 +18,7 @@
 
 import android.app.WallpaperColors
 import android.content.Context
+import android.content.pm.PackageManager
 import android.graphics.Rect
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.GradientDrawable
@@ -27,6 +28,7 @@
 import com.android.systemui.media.controls.ui.animation.backgroundEndFromScheme
 import com.android.systemui.media.controls.ui.animation.backgroundStartFromScheme
 import com.android.systemui.monet.ColorScheme
+import com.android.systemui.monet.Style
 import com.android.systemui.util.getColorWithAlpha
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.withContext
@@ -94,4 +96,21 @@
             )
         return LayerDrawable(arrayOf(albumArt, gradient))
     }
+
+    /** Returns [ColorScheme] of media app given its [packageName]. */
+    fun getColorScheme(
+        applicationContext: Context,
+        packageName: String,
+        tag: String,
+        style: Style = Style.TONAL_SPOT
+    ): ColorScheme? {
+        return try {
+            // Set up media source app's logo.
+            val icon = applicationContext.packageManager.getApplicationIcon(packageName)
+            ColorScheme(WallpaperColors.fromDrawable(icon), darkTheme = true, style)
+        } catch (e: PackageManager.NameNotFoundException) {
+            Log.w(tag, "Fail to get media app info", e)
+            null
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt
new file mode 100644
index 0000000..952b134
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.util
+
+import androidx.recyclerview.widget.DiffUtil
+import com.android.systemui.media.controls.ui.viewmodel.MediaCommonViewModel
+
+/** A [DiffUtil.Callback] to calculate difference between old and new media view-model list. */
+class MediaViewModelCallback(
+    private val old: List<MediaCommonViewModel>,
+    private val new: List<MediaCommonViewModel>,
+) : DiffUtil.Callback() {
+
+    override fun getOldListSize(): Int {
+        return old.size
+    }
+
+    override fun getNewListSize(): Int {
+        return new.size
+    }
+
+    override fun areItemsTheSame(oldIndex: Int, newIndex: Int): Boolean {
+        val oldItem = old[oldIndex]
+        val newItem = new[newIndex]
+        return if (
+            oldItem is MediaCommonViewModel.MediaControl &&
+                newItem is MediaCommonViewModel.MediaControl
+        ) {
+            oldItem.instanceId == newItem.instanceId
+        } else {
+            oldItem is MediaCommonViewModel.MediaRecommendations &&
+                newItem is MediaCommonViewModel.MediaRecommendations
+        }
+    }
+
+    override fun areContentsTheSame(oldIndex: Int, newIndex: Int): Boolean {
+        val oldItem = old[oldIndex]
+        val newItem = new[newIndex]
+        return if (
+            oldItem is MediaCommonViewModel.MediaControl &&
+                newItem is MediaCommonViewModel.MediaControl
+        ) {
+            oldItem.immediatelyUpdateUi == newItem.immediatelyUpdateUi
+        } else if (
+            oldItem is MediaCommonViewModel.MediaRecommendations &&
+                newItem is MediaCommonViewModel.MediaRecommendations
+        ) {
+            oldItem.key == newItem.key && oldItem.loadingEnabled == newItem.loadingEnabled
+        } else {
+            false
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt
new file mode 100644
index 0000000..bd81e44
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.util
+
+import androidx.recyclerview.widget.ListUpdateCallback
+import com.android.systemui.media.controls.ui.viewmodel.MediaCommonViewModel
+
+/** A [ListUpdateCallback] to apply media events needed to reach the new state. */
+class MediaViewModelListUpdateCallback(
+    private val old: List<MediaCommonViewModel>,
+    private val new: List<MediaCommonViewModel>,
+    private val onAdded: (MediaCommonViewModel, Int) -> Unit,
+    private val onUpdated: (MediaCommonViewModel) -> Unit,
+    private val onRemoved: (MediaCommonViewModel) -> Unit,
+    private val onMoved: (MediaCommonViewModel, Int, Int) -> Unit,
+) : ListUpdateCallback {
+
+    override fun onInserted(position: Int, count: Int) {
+        for (i in position until position + count) {
+            onAdded(new[i], i)
+        }
+    }
+
+    override fun onRemoved(position: Int, count: Int) {
+        for (i in position until position + count) {
+            onRemoved(old[i])
+        }
+    }
+
+    override fun onMoved(fromPosition: Int, toPosition: Int) {
+        onMoved(old[fromPosition], fromPosition, toPosition)
+    }
+
+    override fun onChanged(position: Int, count: Int, payload: Any?) {
+        for (i in position until position + count) {
+            onUpdated(new[i])
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandler.kt
index b531ecf..d63c2e0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaCarouselScrollHandler.kt
@@ -31,11 +31,11 @@
 import com.android.settingslib.Utils
 import com.android.systemui.Gefingerpoken
 import com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS
-import com.android.systemui.media.controls.ui.controller.MediaControlPanel
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.PageIndicator
 import com.android.systemui.res.R
+import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.wm.shell.shared.animation.PhysicsAnimator
 
@@ -535,8 +535,8 @@
      * Notify that a player will be removed right away. This gives us the opporunity to look where
      * it was and update our scroll position.
      */
-    fun onPrePlayerRemoved(removed: MediaControlPanel) {
-        val removedIndex = mediaContent.indexOfChild(removed.mediaViewHolder?.player)
+    fun onPrePlayerRemoved(player: TransitionLayout?) {
+        val removedIndex = mediaContent.indexOfChild(player)
         // If the removed index is less than the visibleMediaIndex, then we need to decrement it.
         // RTL has no effect on this, because indices are always relative (start-to-end).
         // Update the index 'manually' since we won't always get a call to onMediaScrollingChanged
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt
index e508e1b..6c7c31c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt
@@ -22,9 +22,9 @@
 /** Models UI state for media guts menu */
 data class GutsViewModel(
     val gutsText: CharSequence,
-    @ColorInt val textColor: Int,
-    @ColorInt val buttonBackgroundColor: Int,
-    @ColorInt val buttonTextColor: Int,
+    @ColorInt val textPrimaryColor: Int,
+    @ColorInt val accentPrimaryColor: Int,
+    @ColorInt val surfaceColor: Int,
     val isDismissEnabled: Boolean = true,
     val onDismissClicked: () -> Unit,
     val cancelTextBackground: Drawable?,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt
new file mode 100644
index 0000000..82099e6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaActionViewModel.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.graphics.drawable.Drawable
+import androidx.constraintlayout.widget.ConstraintSet
+
+/** Models UI state of media buttons in media control. */
+data class MediaActionViewModel(
+    val icon: Drawable?,
+    val contentDescription: CharSequence?,
+    val background: Drawable?,
+    /** whether action is visible if user is touching seekbar to change position. */
+    val isVisibleWhenScrubbing: Boolean = true,
+    val notVisibleValue: Int = ConstraintSet.GONE,
+    val showInCollapsed: Boolean,
+    val rebindId: Int? = null,
+    val buttonId: Int? = null,
+    val isEnabled: Boolean,
+    val onClicked: (Int) -> Unit,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
new file mode 100644
index 0000000..5188132
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.content.Context
+import com.android.internal.logging.InstanceId
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
+import com.android.systemui.media.controls.domain.pipeline.interactor.factory.MediaControlInteractorFactory
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
+import com.android.systemui.media.controls.util.MediaFlags
+import com.android.systemui.media.controls.util.MediaUiEventLogger
+import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
+import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
+import com.android.systemui.util.Utils
+import com.android.systemui.util.kotlin.pairwiseBy
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.stateIn
+
+/** Models UI state and handles user inputs for media carousel */
+@SysUISingleton
+class MediaCarouselViewModel
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    @Application private val applicationContext: Context,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val visualStabilityProvider: VisualStabilityProvider,
+    private val interactor: MediaCarouselInteractor,
+    private val controlInteractorFactory: MediaControlInteractorFactory,
+    private val recommendationsViewModel: MediaRecommendationsViewModel,
+    private val logger: MediaUiEventLogger,
+    private val mediaFlags: MediaFlags,
+) {
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val mediaItems: StateFlow<List<MediaCommonViewModel>> =
+        conflatedCallbackFlow {
+                val listener = OnReorderingAllowedListener { trySend(Unit) }
+                visualStabilityProvider.addPersistentReorderingAllowedListener(listener)
+                trySend(Unit)
+                awaitClose { visualStabilityProvider.removeReorderingAllowedListener(listener) }
+            }
+            .flatMapLatest {
+                combine(interactor.isMediaFromRec, interactor.sortedMedia) {
+                    isRecsToMedia,
+                    sortedItems ->
+                    buildList {
+                        shouldReorder = isRecsToMedia
+                        val reorderAllowed = isReorderingAllowed()
+                        sortedItems.forEach { commonModel ->
+                            if (!reorderAllowed || !modelsPendingRemoval.contains(commonModel)) {
+                                when (commonModel) {
+                                    is MediaCommonModel.MediaControl ->
+                                        add(toViewModel(commonModel))
+                                    is MediaCommonModel.MediaRecommendations ->
+                                        add(toViewModel(commonModel))
+                                }
+                            }
+                        }
+                        if (reorderAllowed) {
+                            modelsPendingRemoval.clear()
+                        }
+                    }
+                }
+            }
+            .pairwiseBy { old, new ->
+                // This condition can only happen when view is attached. So the old emit is of the
+                // most recent list updated.
+                // If the old list is empty, it is okay to emit the new ordered list.
+                if (isReorderingAllowed() || shouldReorder || old.isEmpty()) {
+                    new
+                } else {
+                    old
+                }
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = emptyList(),
+            )
+
+    private val mediaControlByInstanceId =
+        mutableMapOf<InstanceId, MediaCommonViewModel.MediaControl>()
+
+    private var mediaRecs: MediaCommonViewModel.MediaRecommendations? = null
+
+    private var modelsPendingRemoval: MutableSet<MediaCommonModel> = mutableSetOf()
+
+    private var shouldReorder = true
+
+    fun onSwipeToDismiss() {
+        logger.logSwipeDismiss()
+        interactor.onSwipeToDismiss()
+    }
+
+    private fun toViewModel(
+        commonModel: MediaCommonModel.MediaControl
+    ): MediaCommonViewModel.MediaControl {
+        val instanceId = commonModel.mediaLoadedModel.instanceId
+        return mediaControlByInstanceId[instanceId]?.copy(
+            immediatelyUpdateUi = commonModel.mediaLoadedModel.immediatelyUpdateUi
+        )
+            ?: MediaCommonViewModel.MediaControl(
+                    instanceId = instanceId,
+                    immediatelyUpdateUi = commonModel.mediaLoadedModel.immediatelyUpdateUi,
+                    controlViewModel = createMediaControlViewModel(instanceId),
+                    onAdded = { onMediaControlAddedOrUpdated(it, commonModel) },
+                    onRemoved = {
+                        interactor.removeMediaControl(instanceId, delay = 0L)
+                        mediaControlByInstanceId.remove(instanceId)
+                    },
+                    onUpdated = { onMediaControlAddedOrUpdated(it, commonModel) },
+                )
+                .also { mediaControlByInstanceId[instanceId] = it }
+    }
+
+    private fun createMediaControlViewModel(instanceId: InstanceId): MediaControlViewModel {
+        return MediaControlViewModel(
+            applicationScope = applicationScope,
+            applicationContext = applicationContext,
+            backgroundDispatcher = backgroundDispatcher,
+            interactor = controlInteractorFactory.create(instanceId),
+            logger = logger,
+        )
+    }
+
+    private fun toViewModel(
+        commonModel: MediaCommonModel.MediaRecommendations
+    ): MediaCommonViewModel.MediaRecommendations {
+        return mediaRecs?.copy(
+            key = commonModel.recsLoadingModel.key,
+            loadingEnabled =
+                interactor.isRecommendationActive() || mediaFlags.isPersistentSsCardEnabled()
+        )
+            ?: MediaCommonViewModel.MediaRecommendations(
+                    key = commonModel.recsLoadingModel.key,
+                    loadingEnabled =
+                        interactor.isRecommendationActive() ||
+                            mediaFlags.isPersistentSsCardEnabled(),
+                    recsViewModel = recommendationsViewModel,
+                    onAdded = { commonViewModel ->
+                        onMediaRecommendationAddedOrUpdated(commonViewModel)
+                    },
+                    onRemoved = { immediatelyRemove ->
+                        onMediaRecommendationRemoved(commonModel, immediatelyRemove)
+                    },
+                    onUpdated = { commonViewModel ->
+                        onMediaRecommendationAddedOrUpdated(commonViewModel)
+                    },
+                )
+                .also { mediaRecs = it }
+    }
+
+    private fun onMediaControlAddedOrUpdated(
+        commonViewModel: MediaCommonViewModel,
+        commonModel: MediaCommonModel.MediaControl
+    ) {
+        // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_RECEIVED)
+        if (commonModel.canBeRemoved && !Utils.useMediaResumption(applicationContext)) {
+            // This media control is due for removal as it is now paused + timed out, and resumption
+            // setting is off.
+            if (isReorderingAllowed()) {
+                commonViewModel.onRemoved(true)
+            } else {
+                modelsPendingRemoval.add(commonModel)
+            }
+        } else {
+            modelsPendingRemoval.remove(commonModel)
+        }
+    }
+
+    private fun onMediaRecommendationAddedOrUpdated(commonViewModel: MediaCommonViewModel) {
+        if (!interactor.isRecommendationActive()) {
+            if (!mediaFlags.isPersistentSsCardEnabled()) {
+                commonViewModel.onRemoved(true)
+            }
+        } else {
+            // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_RECEIVED)
+        }
+    }
+
+    private fun onMediaRecommendationRemoved(
+        commonModel: MediaCommonModel.MediaRecommendations,
+        immediatelyRemove: Boolean
+    ) {
+        if (immediatelyRemove || isReorderingAllowed()) {
+            interactor.dismissSmartspaceRecommendation(commonModel.recsLoadingModel.key, 0L)
+            // TODO if not immediate remove update host visibility
+        } else {
+            modelsPendingRemoval.add(commonModel)
+        }
+    }
+
+    private fun isReorderingAllowed(): Boolean {
+        return visualStabilityProvider.isReorderingAllowed
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt
new file mode 100644
index 0000000..aeaa82e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import com.android.internal.logging.InstanceId
+
+/** Models media view model UI state. */
+sealed class MediaCommonViewModel {
+
+    abstract val onAdded: (MediaCommonViewModel) -> Unit
+    abstract val onRemoved: (Boolean) -> Unit
+    abstract val onUpdated: (MediaCommonViewModel) -> Unit
+
+    data class MediaControl(
+        val instanceId: InstanceId,
+        val immediatelyUpdateUi: Boolean,
+        val controlViewModel: MediaControlViewModel,
+        override val onAdded: (MediaCommonViewModel) -> Unit,
+        override val onRemoved: (Boolean) -> Unit,
+        override val onUpdated: (MediaCommonViewModel) -> Unit,
+    ) : MediaCommonViewModel()
+
+    data class MediaRecommendations(
+        val key: String,
+        val loadingEnabled: Boolean,
+        val recsViewModel: MediaRecommendationsViewModel,
+        override val onAdded: (MediaCommonViewModel) -> Unit,
+        override val onRemoved: (Boolean) -> Unit,
+        override val onUpdated: (MediaCommonViewModel) -> Unit,
+    ) : MediaCommonViewModel()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
new file mode 100644
index 0000000..52e49d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.media.session.MediaController
+import android.media.session.MediaSession.Token
+import android.text.TextUtils
+import android.util.Log
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.internal.logging.InstanceId
+import com.android.settingslib.flags.Flags.legacyLeAudioSharing
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaControlInteractor
+import com.android.systemui.media.controls.shared.model.MediaAction
+import com.android.systemui.media.controls.shared.model.MediaButton
+import com.android.systemui.media.controls.shared.model.MediaControlModel
+import com.android.systemui.media.controls.ui.animation.accentPrimaryFromScheme
+import com.android.systemui.media.controls.ui.animation.surfaceFromScheme
+import com.android.systemui.media.controls.ui.animation.textPrimaryFromScheme
+import com.android.systemui.media.controls.ui.util.MediaArtworkHelper
+import com.android.systemui.media.controls.util.MediaUiEventLogger
+import com.android.systemui.monet.ColorScheme
+import com.android.systemui.monet.Style
+import com.android.systemui.res.R
+import com.android.systemui.util.kotlin.sample
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/** Models UI state and handles user input for a media control. */
+class MediaControlViewModel(
+    @Application private val applicationContext: Context,
+    @Application private val applicationScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val interactor: MediaControlInteractor,
+    private val logger: MediaUiEventLogger,
+) {
+
+    private val isAnyButtonClicked: MutableStateFlow<Boolean> = MutableStateFlow(false)
+
+    private val playTurbulenceNoise: Flow<Boolean> =
+        interactor.mediaControl.sample(
+            combine(isAnyButtonClicked, interactor.isStartedPlaying) {
+                    isButtonClicked,
+                    isStartedPlaying ->
+                    isButtonClicked && isStartedPlaying
+                }
+                .distinctUntilChanged()
+        )
+
+    val player: Flow<MediaPlayerViewModel?> =
+        combine(playTurbulenceNoise, interactor.mediaControl) { playTurbulenceNoise, mediaControl ->
+                mediaControl?.let { toViewModel(it, playTurbulenceNoise) }
+            }
+            .distinctUntilChanged()
+            .flowOn(backgroundDispatcher)
+
+    private fun onDismissMediaData(
+        token: Token?,
+        uid: Int,
+        packageName: String,
+        instanceId: InstanceId
+    ) {
+        logger.logLongPressDismiss(uid, packageName, instanceId)
+        interactor.removeMediaControl(token, instanceId, MEDIA_PLAYER_ANIMATION_DELAY)
+    }
+
+    private suspend fun toViewModel(
+        model: MediaControlModel,
+        playTurbulenceNoise: Boolean
+    ): MediaPlayerViewModel? {
+        val wallpaperColors =
+            MediaArtworkHelper.getWallpaperColor(
+                applicationContext,
+                backgroundDispatcher,
+                model.artwork,
+                TAG
+            )
+        val scheme =
+            wallpaperColors?.let { ColorScheme(it, true, Style.CONTENT) }
+                ?: MediaArtworkHelper.getColorScheme(
+                    applicationContext,
+                    model.packageName,
+                    TAG,
+                    Style.CONTENT
+                )
+                    ?: return null
+
+        val gutsViewModel = toGutsViewModel(model, scheme)
+
+        // Resetting button clicks state.
+        isAnyButtonClicked.value = false
+
+        return MediaPlayerViewModel(
+            contentDescription = { gutsVisible ->
+                if (gutsVisible) {
+                    gutsViewModel.gutsText
+                } else {
+                    applicationContext.getString(
+                        R.string.controls_media_playing_item_description,
+                        model.songName,
+                        model.artistName,
+                        model.appName
+                    )
+                }
+            },
+            backgroundCover = model.artwork,
+            appIcon = model.appIcon,
+            launcherIcon = getIconFromApp(model.packageName),
+            useGrayColorFilter = model.appIcon == null || model.isResume,
+            artistName = model.artistName ?: "",
+            titleName = model.songName ?: "",
+            isExplicitVisible = model.showExplicit,
+            shouldAddGradient = wallpaperColors != null,
+            colorScheme = scheme,
+            canShowTime = canShowScrubbingTimeViews(model.semanticActionButtons),
+            playTurbulenceNoise = playTurbulenceNoise,
+            useSemanticActions = model.semanticActionButtons != null,
+            actionButtons = toActionViewModels(model),
+            outputSwitcher = toOutputSwitcherViewModel(model),
+            gutsMenu = gutsViewModel,
+            onClicked = { expandable ->
+                model.clickIntent?.let { clickIntent ->
+                    logger.logTapContentView(model.uid, model.packageName, model.instanceId)
+                    // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT)
+                    interactor.startClickIntent(expandable, clickIntent)
+                }
+            },
+            onLongClicked = {
+                logger.logLongPressOpen(model.uid, model.packageName, model.instanceId)
+            },
+            onSeek = {
+                logger.logSeek(model.uid, model.packageName, model.instanceId)
+                // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT)
+            },
+            onBindSeekbar = { seekBarViewModel ->
+                if (model.isResume && model.resumeProgress != null) {
+                    seekBarViewModel.updateStaticProgress(model.resumeProgress)
+                } else {
+                    applicationScope.launch {
+                        withContext(backgroundDispatcher) {
+                            seekBarViewModel.updateController(
+                                model.token?.let { MediaController(applicationContext, it) }
+                            )
+                        }
+                    }
+                }
+            }
+        )
+    }
+
+    private fun toOutputSwitcherViewModel(model: MediaControlModel): MediaOutputSwitcherViewModel {
+        val device = model.deviceData
+        val showBroadcastButton = legacyLeAudioSharing() && device?.showBroadcastButton == true
+
+        // TODO(b/233698402): Use the package name instead of app label to avoid the unexpected
+        //  result.
+        val isCurrentBroadcastApp =
+            device?.name?.let {
+                TextUtils.equals(
+                    it,
+                    applicationContext.getString(R.string.broadcasting_description_is_broadcasting)
+                )
+            }
+                ?: false
+        val useDisabledAlpha =
+            if (showBroadcastButton) {
+                !isCurrentBroadcastApp
+            } else {
+                device?.enabled == false || model.isResume
+            }
+        val deviceString =
+            device?.name
+                ?: if (showBroadcastButton) {
+                    applicationContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name)
+                } else {
+                    applicationContext.getString(R.string.media_seamless_other_device)
+                }
+        return MediaOutputSwitcherViewModel(
+            isTapEnabled = showBroadcastButton || !useDisabledAlpha,
+            deviceString = deviceString,
+            deviceIcon = device?.icon?.let { Icon.Loaded(it, null) }
+                    ?: if (showBroadcastButton) {
+                        Icon.Resource(R.drawable.settings_input_antenna, null)
+                    } else {
+                        Icon.Resource(R.drawable.ic_media_home_devices, null)
+                    },
+            isCurrentBroadcastApp = isCurrentBroadcastApp,
+            isIntentValid = device?.intent != null,
+            alpha =
+                if (useDisabledAlpha) {
+                    DISABLED_ALPHA
+                } else {
+                    1.0f
+                },
+            isVisible = showBroadcastButton,
+            onClicked = { expandable ->
+                if (showBroadcastButton) {
+                    // If the current media app is not broadcasted and users press the outputer
+                    // button, we should pop up the broadcast dialog to check do they want to
+                    // switch broadcast to the other media app, otherwise we still pop up the
+                    // media output dialog.
+                    if (!isCurrentBroadcastApp) {
+                        logger.logOpenBroadcastDialog(
+                            model.uid,
+                            model.packageName,
+                            model.instanceId
+                        )
+                        interactor.startBroadcastDialog(
+                            expandable,
+                            device?.name.toString(),
+                            model.packageName
+                        )
+                    } else {
+                        logger.logOpenOutputSwitcher(model.uid, model.packageName, model.instanceId)
+                        interactor.startMediaOutputDialog(expandable, model.packageName)
+                    }
+                } else {
+                    logger.logOpenOutputSwitcher(model.uid, model.packageName, model.instanceId)
+                    device?.intent?.let { interactor.startDeviceIntent(it) }
+                        ?: interactor.startMediaOutputDialog(expandable, model.packageName)
+                }
+            }
+        )
+    }
+
+    private fun toGutsViewModel(model: MediaControlModel, scheme: ColorScheme): GutsViewModel {
+        return GutsViewModel(
+            gutsText =
+                if (model.isDismissible) {
+                    applicationContext.getString(
+                        R.string.controls_media_close_session,
+                        model.appName
+                    )
+                } else {
+                    applicationContext.getString(R.string.controls_media_active_session)
+                },
+            textPrimaryColor = textPrimaryFromScheme(scheme),
+            accentPrimaryColor = accentPrimaryFromScheme(scheme),
+            surfaceColor = surfaceFromScheme(scheme),
+            isDismissEnabled = model.isDismissible,
+            onDismissClicked = {
+                onDismissMediaData(model.token, model.uid, model.packageName, model.instanceId)
+            },
+            cancelTextBackground =
+                if (model.isDismissible) {
+                    applicationContext.getDrawable(R.drawable.qs_media_outline_button)
+                } else {
+                    applicationContext.getDrawable(R.drawable.qs_media_solid_button)
+                },
+            onSettingsClicked = {
+                logger.logLongPressSettings(model.uid, model.packageName, model.instanceId)
+                interactor.startSettings()
+            },
+        )
+    }
+
+    private fun toActionViewModels(model: MediaControlModel): List<MediaActionViewModel?> {
+        val semanticActionButtons =
+            model.semanticActionButtons?.let { mediaButton ->
+                with(mediaButton) {
+                    val isScrubbingTimeEnabled = canShowScrubbingTimeViews(mediaButton)
+                    SEMANTIC_ACTIONS_ALL.map { buttonId ->
+                        getActionById(buttonId)?.let {
+                            toSemanticActionViewModel(model, it, buttonId, isScrubbingTimeEnabled)
+                        }
+                    }
+                }
+            }
+        val notifActionButtons =
+            model.notificationActionButtons.mapIndexed { index, mediaAction ->
+                toNotifActionViewModel(model, mediaAction, index)
+            }
+        return semanticActionButtons ?: notifActionButtons
+    }
+
+    private fun toSemanticActionViewModel(
+        model: MediaControlModel,
+        mediaAction: MediaAction,
+        buttonId: Int,
+        canShowScrubbingTimeViews: Boolean
+    ): MediaActionViewModel {
+        val showInCollapsed = SEMANTIC_ACTIONS_COMPACT.contains(buttonId)
+        val hideWhenScrubbing = SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.contains(buttonId)
+        val shouldHideWhenScrubbing = canShowScrubbingTimeViews && hideWhenScrubbing
+        return MediaActionViewModel(
+            icon = mediaAction.icon,
+            contentDescription = mediaAction.contentDescription,
+            background = mediaAction.background,
+            isVisibleWhenScrubbing = !shouldHideWhenScrubbing,
+            notVisibleValue =
+                if (
+                    (buttonId == R.id.actionPrev && model.semanticActionButtons!!.reservePrev) ||
+                        (buttonId == R.id.actionNext && model.semanticActionButtons!!.reserveNext)
+                ) {
+                    ConstraintSet.INVISIBLE
+                } else {
+                    ConstraintSet.GONE
+                },
+            showInCollapsed = showInCollapsed,
+            rebindId = mediaAction.rebindId,
+            buttonId = buttonId,
+            isEnabled = mediaAction.action != null,
+            onClicked = { id ->
+                mediaAction.action?.let {
+                    onButtonClicked(id, model.uid, model.packageName, model.instanceId, it)
+                }
+            },
+        )
+    }
+
+    private fun toNotifActionViewModel(
+        model: MediaControlModel,
+        mediaAction: MediaAction,
+        index: Int
+    ): MediaActionViewModel {
+        return MediaActionViewModel(
+            icon = mediaAction.icon,
+            contentDescription = mediaAction.contentDescription,
+            background = mediaAction.background,
+            showInCollapsed = model.actionsToShowInCollapsed.contains(index),
+            rebindId = mediaAction.rebindId,
+            isEnabled = mediaAction.action != null,
+            onClicked = { id ->
+                mediaAction.action?.let {
+                    onButtonClicked(id, model.uid, model.packageName, model.instanceId, it)
+                }
+            },
+        )
+    }
+
+    private fun onButtonClicked(
+        id: Int,
+        uid: Int,
+        packageName: String,
+        instanceId: InstanceId,
+        action: Runnable
+    ) {
+        logger.logTapAction(id, uid, packageName, instanceId)
+        // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT)
+        isAnyButtonClicked.value = true
+        action.run()
+    }
+
+    private fun getIconFromApp(packageName: String): Icon {
+        return try {
+            Icon.Loaded(applicationContext.packageManager.getApplicationIcon(packageName), null)
+        } catch (e: PackageManager.NameNotFoundException) {
+            Log.w(TAG, "Cannot find icon for package $packageName", e)
+            Icon.Resource(R.drawable.ic_music_note, null)
+        }
+    }
+
+    private fun canShowScrubbingTimeViews(semanticActions: MediaButton?): Boolean {
+        // The scrubbing time views replace the SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING action views,
+        // so we should only allow scrubbing times to be shown if those action views are present.
+        return semanticActions?.let {
+            SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.stream().allMatch { id: Int ->
+                semanticActions.getActionById(id) != null
+            }
+        }
+            ?: false
+    }
+
+    companion object {
+        private const val TAG = "MediaControlViewModel"
+        private const val MEDIA_PLAYER_ANIMATION_DELAY = 334L
+        private const val DISABLED_ALPHA = 0.38f
+
+        /** Buttons to show in small player when using semantic actions */
+        val SEMANTIC_ACTIONS_COMPACT =
+            listOf(R.id.actionPlayPause, R.id.actionPrev, R.id.actionNext)
+
+        /**
+         * Buttons that should get hidden when we are scrubbing (they will be replaced with the
+         * views showing scrubbing time)
+         */
+        val SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING = listOf(R.id.actionPrev, R.id.actionNext)
+
+        /** Buttons to show in player when using semantic actions. */
+        val SEMANTIC_ACTIONS_ALL =
+            listOf(
+                R.id.actionPlayPause,
+                R.id.actionPrev,
+                R.id.actionNext,
+                R.id.action0,
+                R.id.action1
+            )
+
+        const val TURBULENCE_NOISE_PLAY_MS_DURATION = 7500L
+        const val MEDIA_PLAYER_SCRIM_START_ALPHA = 0.25f
+        const val MEDIA_PLAYER_SCRIM_END_ALPHA = 1.0f
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt
new file mode 100644
index 0000000..9df9bcc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaOutputSwitcherViewModel.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.shared.model.Icon
+
+/** Models UI state of output switcher chip. */
+data class MediaOutputSwitcherViewModel(
+    val isTapEnabled: Boolean,
+    val deviceString: CharSequence,
+    val deviceIcon: Icon,
+    val isCurrentBroadcastApp: Boolean,
+    val isIntentValid: Boolean,
+    val alpha: Float,
+    val isVisible: Boolean,
+    val onClicked: (Expandable) -> Unit,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt
new file mode 100644
index 0000000..d1014e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.monet.ColorScheme
+
+/** Models UI state for media player. */
+data class MediaPlayerViewModel(
+    val contentDescription: (Boolean) -> CharSequence,
+    val backgroundCover: android.graphics.drawable.Icon?,
+    val appIcon: android.graphics.drawable.Icon?,
+    val launcherIcon: Icon,
+    val useGrayColorFilter: Boolean,
+    val artistName: CharSequence,
+    val titleName: CharSequence,
+    val isExplicitVisible: Boolean,
+    val shouldAddGradient: Boolean,
+    val colorScheme: ColorScheme,
+    val canShowTime: Boolean,
+    val playTurbulenceNoise: Boolean,
+    val useSemanticActions: Boolean,
+    val actionButtons: List<MediaActionViewModel?>,
+    val outputSwitcher: MediaOutputSwitcherViewModel,
+    val gutsMenu: GutsViewModel,
+    val onClicked: (Expandable) -> Unit,
+    val onLongClicked: () -> Unit,
+    val onSeek: () -> Unit,
+    val onBindSeekbar: (SeekBarViewModel) -> Unit,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
index 19ea00d..5cd9804 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
@@ -16,10 +16,8 @@
 
 package com.android.systemui.media.controls.ui.viewmodel
 
-import android.app.WallpaperColors
 import android.content.Context
 import android.content.Intent
-import android.content.pm.PackageManager
 import android.graphics.Bitmap
 import android.graphics.Color
 import android.graphics.drawable.BitmapDrawable
@@ -109,6 +107,10 @@
             logger.logRecommendationItemTap(packageName, instanceId, index)
         }
         // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT).
+
+        // set the package name of the player added by recommendation once the media is loaded.
+        interactor.switchToMediaControl(packageName)
+
         interactor.startClickIntent(expandable, intent)
     }
 
@@ -122,7 +124,9 @@
             return null
         }
 
-        val scheme = getColorScheme(model.packageName) ?: return null
+        val scheme =
+            MediaArtworkHelper.getColorScheme(applicationContext, model.packageName, TAG)
+                ?: return null
 
         // Capture width & height from views in foreground for artwork scaling in background
         val width =
@@ -213,9 +217,9 @@
         return GutsViewModel(
             gutsText =
                 applicationContext.getString(R.string.controls_media_close_session, model.appName),
-            textColor = textPrimaryFromScheme(scheme),
-            buttonBackgroundColor = accentPrimaryFromScheme(scheme),
-            buttonTextColor = surfaceFromScheme(scheme),
+            textPrimaryColor = textPrimaryFromScheme(scheme),
+            accentPrimaryColor = accentPrimaryFromScheme(scheme),
+            surfaceColor = surfaceFromScheme(scheme),
             onDismissClicked = {
                 onMediaRecommendationsDismissed(
                     model.key,
@@ -304,20 +308,6 @@
         }
     }
 
-    private fun getColorScheme(packageName: String): ColorScheme? {
-        // Set up recommendation card's header.
-        return try {
-            val packageManager = applicationContext.packageManager
-            val applicationInfo = packageManager.getApplicationInfo(packageName, 0 /* flags */)
-            // Set up media source app's logo.
-            val icon = packageManager.getApplicationIcon(applicationInfo)
-            ColorScheme(WallpaperColors.fromDrawable(icon), darkTheme = true)
-        } catch (e: PackageManager.NameNotFoundException) {
-            Log.w(TAG, "Fail to get media recommendation's app info", e)
-            null
-        }
-    }
-
     /** Returns a [Drawable] of a given [artworkIcon] scaled to [width]x[height] size, . */
     private fun getScaledRecommendationCover(
         artworkIcon: Icon,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
index cef1e69..22b3f35 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
@@ -33,12 +33,19 @@
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR
+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.media.controls.util.MediaFlags
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.statusbar.NotificationMediaManager
 import com.android.systemui.util.concurrency.RepeatableExecutor
 import javax.inject.Inject
 import kotlin.math.abs
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
 private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L
 private const val MIN_FLING_VELOCITY_SCALE_FACTOR = 10
@@ -81,8 +88,11 @@
 class SeekBarViewModel
 @Inject
 constructor(
+    @Application private val applicationScope: CoroutineScope,
+    @Main private val mainDispatcher: CoroutineDispatcher,
     @Background private val bgExecutor: RepeatableExecutor,
     private val falsingManager: FalsingManager,
+    private val mediaFlags: MediaFlags,
 ) {
     private var _data =
         Progress(
@@ -108,9 +118,19 @@
     private var controller: MediaController? = null
         set(value) {
             if (field?.sessionToken != value?.sessionToken) {
-                field?.unregisterCallback(callback)
-                value?.registerCallback(callback)
-                field = value
+                if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+                    field?.unregisterCallback(callback)
+                    value?.registerCallback(callback)
+                    field = value
+                } else {
+                    applicationScope.launch {
+                        withContext(mainDispatcher) {
+                            field?.unregisterCallback(callback)
+                            value?.registerCallback(callback)
+                            field = value
+                        }
+                    }
+                }
             }
         }
     private var playbackState: PlaybackState? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt
index 452cb7e..ff8e903b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/LocalMediaManagerFactory.kt
@@ -31,8 +31,9 @@
 ) {
     /** Creates a [LocalMediaManager] for the given package. */
     fun create(packageName: String?): LocalMediaManager {
-        return InfoMediaManager.createInstance(context, packageName, localBluetoothManager).run {
-            LocalMediaManager(context, localBluetoothManager, this, packageName)
-        }
+        // TODO: b/321969740 - Populate the userHandle parameter in InfoMediaManager. The user
+        // handle is necessary to disambiguate the same package running on different users.
+        return InfoMediaManager.createInstance(context, packageName, null, localBluetoothManager)
+            .run { LocalMediaManager(context, localBluetoothManager, this, packageName) }
     }
 }
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 d4bd6da..4e77d13 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
@@ -21,16 +21,11 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import javax.inject.Inject
 
 @SysUISingleton
-class MediaFlags
-@Inject
-constructor(
-    private val featureFlags: FeatureFlagsClassic,
-    private val sceneContainerFlags: SceneContainerFlags
-) {
+class MediaFlags @Inject constructor(private val featureFlags: FeatureFlagsClassic) {
     /**
      * Check whether media control actions should be based on PlaybackState instead of notification
      */
@@ -57,7 +52,7 @@
 
     /** Check whether to use scene framework */
     fun isSceneContainerEnabled() =
-        sceneContainerFlags.isEnabled() && MediaInSceneContainerFlag.isEnabled
+        SceneContainerFlag.isEnabled && MediaInSceneContainerFlag.isEnabled
 
     /** Check whether to use media refactor code */
     fun isMediaControlsRefactorEnabled() = MediaControlsRefactorFlag.isEnabled
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt
index 54d175c..06267e2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt
@@ -38,7 +38,9 @@
         // Dismiss the previous dialog, if any.
         mediaOutputBroadcastDialog?.dismiss()
 
-        val controller = mediaOutputControllerFactory.create(packageName)
+        // TODO: b/321969740 - Populate the userHandle parameter. The user handle is necessary to
+        //  disambiguate the same package running on different users.
+        val controller = mediaOutputControllerFactory.create(packageName, /* userHandle= */ null)
         val dialog =
             MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller)
         mediaOutputBroadcastDialog = dialog
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index adee7f2c..d6ca320 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -124,6 +124,7 @@
     private static final String ALLOWLIST_REASON = "mediaoutput:remote_transfer";
 
     private final String mPackageName;
+    private final UserHandle mUserHandle;
     private final Context mContext;
     private final MediaSessionManager mMediaSessionManager;
     private final LocalBluetoothManager mLocalBluetoothManager;
@@ -177,6 +178,7 @@
     public MediaOutputController(
             Context context,
             @Assisted String packageName,
+            @Assisted @Nullable UserHandle userHandle,
             MediaSessionManager mediaSessionManager,
             @Nullable LocalBluetoothManager lbm,
             ActivityStarter starter,
@@ -190,6 +192,7 @@
             UserTracker userTracker) {
         mContext = context;
         mPackageName = packageName;
+        mUserHandle = userHandle;
         mMediaSessionManager = mediaSessionManager;
         mLocalBluetoothManager = lbm;
         mActivityStarter = starter;
@@ -199,7 +202,8 @@
         mKeyGuardManager = keyGuardManager;
         mFeatureFlags = featureFlags;
         mUserTracker = userTracker;
-        InfoMediaManager imm = InfoMediaManager.createInstance(mContext, packageName, lbm);
+        InfoMediaManager imm =
+                InfoMediaManager.createInstance(mContext, packageName, userHandle, lbm);
         mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
         mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
         mDialogTransitionAnimator = dialogTransitionAnimator;
@@ -231,7 +235,7 @@
     @AssistedFactory
     public interface Factory {
         /** Construct a MediaOutputController */
-        MediaOutputController create(String packageName);
+        MediaOutputController create(String packageName, UserHandle userHandle);
     }
 
     protected void start(@NonNull Callback cb) {
@@ -946,11 +950,22 @@
     }
 
     void launchMediaOutputBroadcastDialog(View mediaOutputDialog, BroadcastSender broadcastSender) {
-        MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
-                mMediaSessionManager, mLocalBluetoothManager, mActivityStarter,
-                mNotifCollection, mDialogTransitionAnimator, mNearbyMediaDevicesManager,
-                mAudioManager, mPowerExemptionManager, mKeyGuardManager, mFeatureFlags,
-                mUserTracker);
+        MediaOutputController controller =
+                new MediaOutputController(
+                        mContext,
+                        mPackageName,
+                        mUserHandle,
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mActivityStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyGuardManager,
+                        mFeatureFlags,
+                        mUserTracker);
         MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true,
                 broadcastSender, controller);
         dialog.show();
@@ -1200,9 +1215,7 @@
     }
 
     boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
-        return (isPlayBackInfoLocal()
-                || device.getDeviceType() != MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE)
-                && !device.isVolumeFixed();
+        return !device.isVolumeFixed();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt
index e7816a4..04d1492 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.media.dialog
 
 import android.content.Context
+import android.os.UserHandle
 import android.view.View
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.logging.UiEventLogger
@@ -41,7 +42,15 @@
     }
 
     /** Creates a [MediaOutputDialog] for the given package. */
-    open fun createAndShow(packageName: String, aboveStatusBar: Boolean, view: View? = null) {
+    // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the
+    // package name. The user handle is necessary to disambiguate the same package running on
+    // different users.
+    open fun createAndShow(
+        packageName: String,
+        aboveStatusBar: Boolean,
+        view: View? = null,
+        userHandle: UserHandle? = null
+    ) {
         createAndShowWithController(
             packageName,
             aboveStatusBar,
@@ -55,20 +64,26 @@
                         )
                     )
                 },
+            userHandle = userHandle,
         )
     }
 
     /** Creates a [MediaOutputDialog] for the given package. */
+    // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the
+    // package name. The user handle is necessary to disambiguate the same package running on
+    // different users.
     open fun createAndShowWithController(
         packageName: String,
         aboveStatusBar: Boolean,
         controller: DialogTransitionAnimator.Controller?,
+        userHandle: UserHandle? = null,
     ) {
         createAndShow(
             packageName,
             aboveStatusBar,
             dialogTransitionAnimatorController = controller,
-            includePlaybackAndAppMetadata = true
+            includePlaybackAndAppMetadata = true,
+            userHandle = userHandle,
         )
     }
 
@@ -79,20 +94,25 @@
             packageName = null,
             aboveStatusBar = false,
             dialogTransitionAnimatorController = null,
-            includePlaybackAndAppMetadata = false
+            includePlaybackAndAppMetadata = false,
+            userHandle = null,
         )
     }
 
+    // TODO: b/321969740 - Make the userHandle non-optional, and place the parameter next to the
+    // package name. The user handle is necessary to disambiguate the same package running on
+    // different users.
     private fun createAndShow(
         packageName: String?,
         aboveStatusBar: Boolean,
         dialogTransitionAnimatorController: DialogTransitionAnimator.Controller?,
-        includePlaybackAndAppMetadata: Boolean = true
+        includePlaybackAndAppMetadata: Boolean = true,
+        userHandle: UserHandle? = null,
     ) {
         // Dismiss the previous dialog, if any.
         mediaOutputDialog?.dismiss()
 
-        val controller = mediaOutputControllerFactory.create(packageName)
+        val controller = mediaOutputControllerFactory.create(packageName, userHandle)
 
         val mediaOutputDialog =
             MediaOutputDialog(
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 6e7e0f2..9cc2888 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
@@ -18,6 +18,7 @@
 
 import android.annotation.MainThread;
 import android.content.Context;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -52,9 +53,10 @@
 
     @Override
     @MainThread
-    public void showMediaOutputSwitcher(String packageName) {
+    public void showMediaOutputSwitcher(String packageName, UserHandle userHandle) {
         if (!TextUtils.isEmpty(packageName)) {
-            mMediaOutputDialogManager.createAndShow(packageName, false, null);
+            mMediaOutputDialogManager.createAndShow(
+                    packageName, /* aboveStatusBar= */ false, /* view= */ null, userHandle);
         } else {
             Log.e(TAG, "Unable to launch media output dialog. Package name is empty.");
         }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index d247122..f08bc17 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -25,8 +25,8 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerLabelLoader
 import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
-import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
-import com.android.systemui.mediaprojection.appselector.data.IconLoaderLibAppIconLoader
+import com.android.systemui.mediaprojection.appselector.data.BasicAppIconLoader
+import com.android.systemui.mediaprojection.appselector.data.BasicPackageManagerAppIconLoader
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskLabelLoader
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader
@@ -102,7 +102,7 @@
 
     @Binds
     @MediaProjectionAppSelectorScope
-    fun bindAppIconLoader(impl: IconLoaderLibAppIconLoader): AppIconLoader
+    fun bindAppIconLoader(impl: BasicPackageManagerAppIconLoader): BasicAppIconLoader
 
     @Binds
     @IntoSet
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/AppIconLoader.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/AppIconLoader.kt
deleted file mode 100644
index b85d628..0000000
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/AppIconLoader.kt
+++ /dev/null
@@ -1,61 +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.mediaprojection.appselector.data
-
-import android.content.ComponentName
-import android.content.Context
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import com.android.launcher3.icons.BaseIconFactory.IconOptions
-import com.android.launcher3.icons.IconFactory
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.shared.system.PackageManagerWrapper
-import javax.inject.Inject
-import javax.inject.Provider
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.withContext
-
-interface AppIconLoader {
-    suspend fun loadIcon(userId: Int, component: ComponentName): Drawable?
-}
-
-class IconLoaderLibAppIconLoader
-@Inject
-constructor(
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
-    private val context: Context,
-    // Use wrapper to access hidden API that allows to get ActivityInfo for any user id
-    private val packageManagerWrapper: PackageManagerWrapper,
-    private val packageManager: PackageManager,
-    private val iconFactoryProvider: Provider<IconFactory>
-) : AppIconLoader {
-
-    override suspend fun loadIcon(userId: Int, component: ComponentName): Drawable? =
-        withContext(backgroundDispatcher) {
-            iconFactoryProvider.get().use<IconFactory, Drawable?> { iconFactory ->
-                val activityInfo =
-                    packageManagerWrapper.getActivityInfo(component, userId)
-                        ?: return@withContext null
-                val icon = activityInfo.loadIcon(packageManager) ?: return@withContext null
-                val userHandler = UserHandle.of(userId)
-                val options = IconOptions().apply { setUser(userHandler) }
-                val badgedIcon = iconFactory.createBadgedIconBitmap(icon, options)
-                badgedIcon.newIcon(context)
-            }
-        }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/BadgedAppIconLoader.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/BadgedAppIconLoader.kt
new file mode 100644
index 0000000..ca5b5f8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/BadgedAppIconLoader.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.mediaprojection.appselector.data
+
+import android.content.ComponentName
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import com.android.launcher3.icons.BaseIconFactory
+import com.android.launcher3.icons.IconFactory
+import com.android.launcher3.util.UserIconInfo
+import com.android.systemui.dagger.qualifiers.Background
+import javax.inject.Inject
+import javax.inject.Provider
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+class BadgedAppIconLoader
+@Inject
+constructor(
+    private val basicAppIconLoader: BasicAppIconLoader,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val context: Context,
+    private val iconFactoryProvider: Provider<IconFactory>,
+) {
+
+    suspend fun loadIcon(
+        userId: Int,
+        userType: RecentTask.UserType,
+        componentName: ComponentName
+    ): Drawable? =
+        withContext(backgroundDispatcher) {
+            iconFactoryProvider.get().use<IconFactory, Drawable?> { iconFactory ->
+                val icon =
+                    basicAppIconLoader.loadIcon(userId, componentName) ?: return@withContext null
+                val userHandler = UserHandle.of(userId)
+                val iconType = getIconType(userType)
+                val options =
+                    BaseIconFactory.IconOptions().apply {
+                        setUser(UserIconInfo(userHandler, iconType))
+                    }
+                val badgedIcon = iconFactory.createBadgedIconBitmap(icon, options)
+                badgedIcon.newIcon(context)
+            }
+        }
+
+    private fun getIconType(userType: RecentTask.UserType): Int =
+        when (userType) {
+            RecentTask.UserType.CLONED -> UserIconInfo.TYPE_CLONED
+            RecentTask.UserType.WORK -> UserIconInfo.TYPE_WORK
+            RecentTask.UserType.PRIVATE -> UserIconInfo.TYPE_PRIVATE
+            RecentTask.UserType.STANDARD -> UserIconInfo.TYPE_MAIN
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/BasicAppIconLoader.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/BasicAppIconLoader.kt
new file mode 100644
index 0000000..03f6f01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/BasicAppIconLoader.kt
@@ -0,0 +1,45 @@
+/*
+ * 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.mediaprojection.appselector.data
+
+import android.content.ComponentName
+import android.content.pm.PackageManager
+import android.graphics.drawable.Drawable
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.shared.system.PackageManagerWrapper
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+interface BasicAppIconLoader {
+    suspend fun loadIcon(userId: Int, component: ComponentName): Drawable?
+}
+
+class BasicPackageManagerAppIconLoader
+@Inject
+constructor(
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    // Use wrapper to access hidden API that allows to get ActivityInfo for any user id
+    private val packageManagerWrapper: PackageManagerWrapper,
+    private val packageManager: PackageManager,
+) : BasicAppIconLoader {
+
+    override suspend fun loadIcon(userId: Int, component: ComponentName): Drawable? =
+        withContext(backgroundDispatcher) {
+            packageManagerWrapper.getActivityInfo(component, userId)?.loadIcon(packageManager)
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt
index e9b4582..2dbe2aa 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt
@@ -18,7 +18,9 @@
 
 import android.annotation.ColorInt
 import android.annotation.UserIdInt
+import android.app.ActivityManager.RecentTaskInfo
 import android.content.ComponentName
+import com.android.wm.shell.util.SplitBounds
 
 data class RecentTask(
     val taskId: Int,
@@ -28,4 +30,30 @@
     val baseIntentComponent: ComponentName?,
     @ColorInt val colorBackground: Int?,
     val isForegroundTask: Boolean,
-)
+    val userType: UserType,
+    val splitBounds: SplitBounds?,
+) {
+    constructor(
+        taskInfo: RecentTaskInfo,
+        isForegroundTask: Boolean,
+        userType: UserType,
+        splitBounds: SplitBounds? = null
+    ) : this(
+        taskInfo.taskId,
+        taskInfo.displayId,
+        taskInfo.userId,
+        taskInfo.topActivity,
+        taskInfo.baseIntent?.component,
+        taskInfo.taskDescription?.backgroundColor,
+        isForegroundTask,
+        userType,
+        splitBounds
+    )
+
+    enum class UserType {
+        STANDARD,
+        WORK,
+        PRIVATE,
+        CLONED
+    }
+}
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 5dde14b..596c18f 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
@@ -17,6 +17,8 @@
 package com.android.systemui.mediaprojection.appselector.data
 
 import android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE
+import android.content.pm.UserInfo
+import android.os.UserManager
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.kotlin.getOrNull
@@ -41,7 +43,8 @@
     @Background private val coroutineDispatcher: CoroutineDispatcher,
     @Background private val backgroundExecutor: Executor,
     private val recentTasks: Optional<RecentTasks>,
-    private val userTracker: UserTracker
+    private val userTracker: UserTracker,
+    private val userManager: UserManager,
 ) : RecentTaskListProvider {
 
     private val recents by lazy { recentTasks.getOrNull() }
@@ -55,19 +58,27 @@
             val foregroundTaskId1 = foregroundGroup?.taskInfo1?.taskId
             val foregroundTaskId2 = foregroundGroup?.taskInfo2?.taskId
             val foregroundTaskIds = listOfNotNull(foregroundTaskId1, foregroundTaskId2)
-            groupedTasks
-                .flatMap { listOfNotNull(it.taskInfo1, it.taskInfo2) }
-                .map {
+            groupedTasks.flatMap {
+                val task1 =
                     RecentTask(
-                        it.taskId,
-                        it.displayId,
-                        it.userId,
-                        it.topActivity,
-                        it.baseIntent?.component,
-                        it.taskDescription?.backgroundColor,
-                        isForegroundTask = it.taskId in foregroundTaskIds && it.isVisible
+                        it.taskInfo1,
+                        it.taskInfo1.taskId in foregroundTaskIds && it.taskInfo1.isVisible,
+                        userManager.getUserInfo(it.taskInfo1.userId).toUserType(),
+                        it.splitBounds
                     )
-                }
+
+                val task2 =
+                    if (it.taskInfo2 != null) {
+                        RecentTask(
+                            it.taskInfo2!!,
+                            it.taskInfo2!!.taskId in foregroundTaskIds && it.taskInfo2!!.isVisible,
+                            userManager.getUserInfo(it.taskInfo2!!.userId).toUserType(),
+                            it.splitBounds
+                        )
+                    } else null
+
+                listOfNotNull(task1, task2)
+            }
         }
 
     private suspend fun RecentTasks.getTasks(): List<GroupedRecentTaskInfo> =
@@ -81,4 +92,15 @@
                 continuation.resume(tasks)
             }
         }
+
+    private fun UserInfo.toUserType(): RecentTask.UserType =
+        if (isCloneProfile) {
+            RecentTask.UserType.CLONED
+        } else if (isManagedProfile) {
+            RecentTask.UserType.WORK
+        } else if (isPrivateProfile) {
+            RecentTask.UserType.PRIVATE
+        } else {
+            RecentTask.UserType.STANDARD
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
index 7c7efd0..9549ab1 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
@@ -24,9 +24,12 @@
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.window.RemoteTransition
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.android.systemui.Flags.pssAppSelectorAbruptExitFix
+import com.android.systemui.Flags.pssAppSelectorRecentsSplitScreen
+import com.android.systemui.display.naturalBounds
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
 import com.android.systemui.mediaprojection.appselector.data.RecentTask
@@ -34,6 +37,11 @@
 import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
 import com.android.systemui.res.R
 import com.android.systemui.util.recycler.HorizontalSpacerItemDecoration
+import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
+import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
+import com.android.wm.shell.splitscreen.SplitScreen
+import com.android.wm.shell.util.SplitBounds
+import java.util.Optional
 import javax.inject.Inject
 
 /**
@@ -48,6 +56,7 @@
     private val taskViewSizeProvider: TaskPreviewSizeProvider,
     private val activityTaskManager: IActivityTaskManager,
     private val resultHandler: MediaProjectionAppSelectorResultHandler,
+    private val splitScreen: Optional<SplitScreen>,
 ) : RecentTaskClickListener, TaskPreviewSizeListener {
 
     private var views: Views? = null
@@ -63,11 +72,11 @@
     fun createView(parent: ViewGroup): ViewGroup =
         views?.root
             ?: createRecentViews(parent)
-                .also {
-                    views = it
-                    lastBoundData?.let { recents -> bind(recents) }
-                }
-                .root
+                    .also {
+                        views = it
+                        lastBoundData?.let { recents -> bind(recents) }
+                    }
+                    .root
 
     fun bind(recentTasks: List<RecentTask>) {
         views?.apply {
@@ -93,8 +102,10 @@
     private fun createRecentViews(parent: ViewGroup): Views {
         val recentsRoot =
             LayoutInflater.from(parent.context)
-                .inflate(R.layout.media_projection_recent_tasks, parent, /* attachToRoot= */ false)
-                as ViewGroup
+                    .inflate(R.layout.media_projection_recent_tasks,
+                        parent, /* attachToRoot= */
+                        false)
+                    as ViewGroup
 
         val container =
             recentsRoot.requireViewById<View>(R.id.media_projection_recent_tasks_container)
@@ -121,18 +132,34 @@
         return Views(recentsRoot, container, progress, recycler)
     }
 
+    private fun RecentTask.isLaunchingInSplitScreen(): Boolean {
+        return splitScreen.isPresent && splitBounds != null
+    }
+
     override fun onRecentAppClicked(task: RecentTask, view: View) {
         val launchCookie = LaunchCookie()
         val activityOptions = createAnimation(task, view)
         activityOptions.pendingIntentBackgroundActivityStartMode =
             MODE_BACKGROUND_ACTIVITY_START_ALLOWED
-        activityOptions.setLaunchCookie(launchCookie)
         activityOptions.launchDisplayId = task.displayId
+        activityOptions.setLaunchCookie(launchCookie)
 
-        activityTaskManager.startActivityFromRecents(task.taskId, activityOptions.toBundle())
-        resultHandler.returnSelectedApp(launchCookie)
+        val handleResult: () -> Unit = { resultHandler.returnSelectedApp(launchCookie)}
+
+        val taskId = task.taskId
+        val splitBounds = task.splitBounds
+
+        if (pssAppSelectorRecentsSplitScreen() &&
+            task.isLaunchingInSplitScreen() &&
+            !task.isForegroundTask) {
+            startSplitScreenTask(view, taskId, splitBounds!!, handleResult, activityOptions)
+        } else {
+            activityTaskManager.startActivityFromRecents(taskId, activityOptions.toBundle())
+            handleResult()
+        }
     }
 
+
     private fun createAnimation(task: RecentTask, view: View): ActivityOptions =
         if (pssAppSelectorAbruptExitFix() && task.isForegroundTask) {
             // When the selected task is in the foreground, the scale up animation doesn't work.
@@ -145,7 +172,14 @@
                 /* startedListener = */ null,
                 /* finishedListener = */ null
             )
+        } else if (task.isLaunchingInSplitScreen()) {
+            // When the selected task isn't in the foreground, but is launching in split screen,
+            // then we don't need to specify an animation, since we'll already be passing a
+            // manually built remote animation to SplitScreenController
+            ActivityOptions.makeBasic()
         } else {
+            // The default case is a selected task not in the foreground and launching fullscreen,
+            // so for this we can use the default ActivityOptions animation
             ActivityOptions.makeScaleUpAnimation(
                 view,
                 /* startX= */ 0,
@@ -155,6 +189,29 @@
             )
         }
 
+    private fun startSplitScreenTask(
+        view: View,
+        taskId: Int,
+        splitBounds: SplitBounds,
+        handleResult: () -> Unit,
+        activityOptions: ActivityOptions,
+    ) {
+        val isLeftTopTask = taskId == splitBounds.leftTopTaskId
+        val task2Id =
+            if (isLeftTopTask) splitBounds.rightBottomTaskId else splitBounds.leftTopTaskId
+        val splitPosition =
+            if (isLeftTopTask) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT
+
+        val animationRunner = RemoteRecentSplitTaskTransitionRunner(taskId, task2Id,
+            view.locationOnScreen, view.context.display.naturalBounds, handleResult)
+        val remoteTransition = RemoteTransition(animationRunner,
+            view.context.iApplicationThread, "startSplitScreenTask")
+
+        splitScreen.get().startTasks(taskId, activityOptions.toBundle(), task2Id, null,
+            splitPosition, splitBounds.snapPosition, remoteTransition, null)
+    }
+
+
     override fun onTaskSizeChanged(size: Rect) {
         views?.recentsContainer?.setTaskHeightSize()
     }
@@ -163,12 +220,12 @@
         val thumbnailHeight = taskViewSizeProvider.size.height()
         val itemHeight =
             thumbnailHeight +
-                context.resources.getDimensionPixelSize(
-                    R.dimen.media_projection_app_selector_task_icon_size
-                ) +
-                context.resources.getDimensionPixelSize(
-                    R.dimen.media_projection_app_selector_task_icon_margin
-                ) * 2
+                    context.resources.getDimensionPixelSize(
+                        R.dimen.media_projection_app_selector_task_icon_size
+                    ) +
+                    context.resources.getDimensionPixelSize(
+                        R.dimen.media_projection_app_selector_task_icon_margin
+                    ) * 2
 
         layoutParams = layoutParams.apply { height = itemHeight }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt
index 3fe040a..3b84d2c 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt
@@ -21,12 +21,12 @@
 import android.view.ViewGroup
 import android.widget.ImageView
 import androidx.recyclerview.widget.RecyclerView.ViewHolder
-import com.android.systemui.res.R
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelector
-import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
+import com.android.systemui.mediaprojection.appselector.data.BadgedAppIconLoader
 import com.android.systemui.mediaprojection.appselector.data.RecentTask
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskLabelLoader
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
@@ -39,7 +39,7 @@
 @AssistedInject
 constructor(
     @Assisted private val root: ViewGroup,
-    private val iconLoader: AppIconLoader,
+    private val iconLoader: BadgedAppIconLoader,
     private val thumbnailLoader: RecentTaskThumbnailLoader,
     private val labelLoader: RecentTaskLabelLoader,
     private val taskViewSizeProvider: TaskPreviewSizeProvider,
@@ -63,7 +63,7 @@
             scope.launch {
                 task.baseIntentComponent?.let { component ->
                     launch {
-                        val icon = iconLoader.loadIcon(task.userId, component)
+                        val icon = iconLoader.loadIcon(task.userId, task.userType, component)
                         iconView.setImageDrawable(icon)
                     }
                     launch {
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RemoteRecentSplitTaskTransitionRunner.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RemoteRecentSplitTaskTransitionRunner.kt
new file mode 100644
index 0000000..b7942f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RemoteRecentSplitTaskTransitionRunner.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.mediaprojection.appselector.view
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.annotation.UiThread
+import android.graphics.Rect
+import android.os.IBinder
+import android.os.RemoteException
+import android.util.Log
+import android.view.SurfaceControl
+import android.view.animation.DecelerateInterpolator
+import android.window.IRemoteTransitionFinishedCallback
+import android.window.RemoteTransitionStub
+import android.window.TransitionInfo
+import android.window.WindowContainerToken
+import com.android.app.viewcapture.ViewCapture
+import com.android.internal.policy.TransitionAnimation
+import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity.Companion.TAG
+
+class RemoteRecentSplitTaskTransitionRunner(
+    private val firstTaskId: Int,
+    private val secondTaskId: Int,
+    private val viewPosition: IntArray,
+    private val screenBounds: Rect,
+    private val handleResult: () -> Unit,
+) : RemoteTransitionStub() {
+    override fun startAnimation(
+        transition: IBinder?,
+        info: TransitionInfo?,
+        t: SurfaceControl.Transaction?,
+        finishedCallback: IRemoteTransitionFinishedCallback
+    ) {
+        val launchAnimation = AnimatorSet()
+        var rootCandidate =
+            info!!.changes.firstOrNull {
+                it.taskInfo?.taskId == firstTaskId || it.taskInfo?.taskId == secondTaskId
+            }
+
+        // If we could not find a proper root candidate, something went wrong.
+        check(rootCandidate != null) { "Could not find a split root candidate" }
+
+        // Recurse up the tree until parent is null, then we've found our root.
+        var parentToken: WindowContainerToken? = rootCandidate.parent
+        while (parentToken != null) {
+            rootCandidate = info.getChange(parentToken) ?: break
+            parentToken = rootCandidate.parent
+        }
+
+        // Make sure nothing weird happened, like getChange() returning null.
+        check(rootCandidate != null) { "Failed to find a root leash" }
+
+        // Ending position is the full device screen.
+        val startingScale = 0.25f
+
+        val startX = viewPosition[0]
+        val startY = viewPosition[1]
+        val endX = screenBounds.left
+        val endY = screenBounds.top
+
+        ViewCapture.MAIN_EXECUTOR.execute {
+            val progressUpdater = ValueAnimator.ofFloat(0f, 1f)
+            with(progressUpdater) {
+                interpolator = DecelerateInterpolator(1.5f)
+                setDuration(TransitionAnimation.DEFAULT_APP_TRANSITION_DURATION.toLong())
+
+                addUpdateListener { valueAnimator ->
+                    val progress = valueAnimator.animatedFraction
+
+                    val x = startX + ((endX - startX) * progress)
+                    val y = startY + ((endY - startY) * progress)
+                    val scale = startingScale + ((1 - startingScale) * progress)
+
+                    t!!
+                        .setPosition(rootCandidate.leash, x, y)
+                        .setScale(rootCandidate.leash, scale, scale)
+                        .setAlpha(rootCandidate.leash, progress)
+                        .apply()
+                }
+
+                addListener(
+                    object : AnimatorListenerAdapter() {
+                        override fun onAnimationEnd(animation: Animator) {
+                            try {
+                                onTransitionFinished()
+                                finishedCallback.onTransitionFinished(null, null)
+                            } catch (e: RemoteException) {
+                                Log.e(TAG, "Failed to call transition finished callback", e)
+                            }
+                        }
+                    }
+                )
+            }
+
+            launchAnimation.play(progressUpdater)
+            launchAnimation.start()
+        }
+    }
+
+    @Throws(RemoteException::class)
+    override fun onTransitionConsumed(transition: IBinder, aborted: Boolean) {
+        Log.w(TAG, "unexpected consumption of app selector transition: aborted=$aborted")
+    }
+
+    @UiThread
+    private fun onTransitionFinished() {
+        // After finished transition, then invoke callback to close the app selector, so that
+        // finish animation of app selector does not override the launch animation of the split
+        // tasks
+        handleResult()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
index da9e00d..e861ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
@@ -16,8 +16,11 @@
 
 package com.android.systemui.mediaprojection.permission;
 
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
 import static android.media.projection.IMediaProjectionManager.EXTRA_PACKAGE_REUSING_GRANTED_CONSENT;
 import static android.media.projection.IMediaProjectionManager.EXTRA_USER_REVIEW_GRANTED_CONSENT;
+import static android.media.projection.MediaProjectionManager.OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION;
 import static android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL;
 import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -26,11 +29,13 @@
 import static com.android.systemui.mediaprojection.permission.ScreenShareOptionKt.SINGLE_APP;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions.LaunchCookie;
 import android.app.AlertDialog;
 import android.app.StatusBarManager;
+import android.app.compat.CompatChanges;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -108,6 +113,7 @@
     }
 
     @Override
+    @RequiresPermission(allOf = {READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE})
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
@@ -235,6 +241,10 @@
         // the correct screen width when in split screen.
         Context dialogContext = getApplicationContext();
         if (isPartialScreenSharingEnabled()) {
+            final boolean overrideDisableSingleAppOption =
+                    CompatChanges.isChangeEnabled(
+                            OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION,
+                            mPackageName, getHostUserHandle());
             MediaProjectionPermissionDialogDelegate delegate =
                     new MediaProjectionPermissionDialogDelegate(
                             dialogContext,
@@ -246,6 +256,7 @@
                             },
                             () -> finish(RECORD_CANCEL, /* projection= */ null),
                             appName,
+                            overrideDisableSingleAppOption,
                             mUid,
                             mMediaProjectionMetricsLogger);
             mDialog =
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
index 0f54e93..8858041a 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegate.kt
@@ -30,11 +30,12 @@
     private val onStartRecordingClicked: Consumer<MediaProjectionPermissionDialogDelegate>,
     private val onCancelClicked: Runnable,
     private val appName: String?,
+    private val forceShowPartialScreenshare: Boolean,
     hostUid: Int,
     mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
 ) :
     BaseMediaProjectionPermissionDialogDelegate<AlertDialog>(
-        createOptionList(context, appName, mediaProjectionConfig),
+        createOptionList(context, appName, mediaProjectionConfig, forceShowPartialScreenshare),
         appName,
         hostUid,
         mediaProjectionMetricsLogger
@@ -65,7 +66,8 @@
         private fun createOptionList(
             context: Context,
             appName: String?,
-            mediaProjectionConfig: MediaProjectionConfig?
+            mediaProjectionConfig: MediaProjectionConfig?,
+            overrideDisableSingleAppOption: Boolean = false,
         ): List<ScreenShareOption> {
             val singleAppWarningText =
                 if (appName == null) {
@@ -80,8 +82,13 @@
                     R.string.media_projection_entry_app_permission_dialog_warning_entire_screen
                 }
 
+            // The single app option should only be disabled if there is an app name provided,
+            // the client has setup a MediaProjection with
+            // MediaProjectionConfig#createConfigForDefaultDisplay, AND it hasn't been overridden by
+            // the OVERRIDE_DISABLE_SINGLE_APP_OPTION per-app override.
             val singleAppOptionDisabled =
                 appName != null &&
+                    !overrideDisableSingleAppOption &&
                     mediaProjectionConfig?.regionToCapture ==
                         MediaProjectionConfig.CAPTURE_REGION_FIXED_DISPLAY
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 63989ef..a6b6d61 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -35,6 +35,7 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
@@ -74,6 +75,7 @@
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import dagger.Lazy;
@@ -101,7 +103,7 @@
         AccessibilityButtonModeObserver.ModeChangedListener,
         AccessibilityButtonTargetsObserver.TargetsChangedListener,
         OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
-        Dumpable, CommandQueue.Callbacks {
+        Dumpable, CommandQueue.Callbacks, ConfigurationController.ConfigurationListener {
     private static final String TAG = NavBarHelper.class.getSimpleName();
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -189,6 +191,7 @@
             UserTracker userTracker,
             DisplayTracker displayTracker,
             NotificationShadeWindowController notificationShadeWindowController,
+            ConfigurationController configurationController,
             DumpManager dumpManager,
             CommandQueue commandQueue,
             @Main Executor mainExecutor) {
@@ -215,6 +218,7 @@
 
         mNavBarMode = navigationModeController.addListener(this);
         mCommandQueue.addCallback(this);
+        configurationController.addCallback(this);
         overviewProxyService.addCallback(this);
         dumpManager.registerDumpable(this);
     }
@@ -359,6 +363,11 @@
         updateA11yState();
     }
 
+    @Override
+    public void onConfigChanged(Configuration newConfig) {
+        mEdgeBackGestureHandler.onConfigurationChanged(newConfig);
+    }
+
     /**
      * Updates the current accessibility button state. The accessibility button state is only
      * used for {@link Secure#ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR} and
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 4fe3a11..43c73c4 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -85,6 +85,7 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
@@ -186,6 +187,7 @@
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERANCE = 200;
     private static final long AUTODIM_TIMEOUT_MS = 2250;
+    private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 3f;
 
     private final Context mContext;
     private final Bundle mSavedState;
@@ -223,6 +225,7 @@
     private final int mNavColorSampleMargin;
     private EdgeBackGestureHandler mEdgeBackGestureHandler;
     private NavigationBarFrame mFrame;
+    private MotionEvent mCurrentDownEvent;
 
     private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
 
@@ -238,6 +241,8 @@
     private int mLayoutDirection;
 
     private Optional<Long> mHomeButtonLongPressDurationMs;
+    private Optional<Long> mOverrideHomeButtonLongPressDurationMs = Optional.empty();
+    private Optional<Float> mOverrideHomeButtonLongPressSlopMultiplier = Optional.empty();
 
     /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
     private @Appearance int mAppearance;
@@ -405,6 +410,23 @@
         }
 
         @Override
+        public void setOverrideHomeButtonLongPress(long duration, float slopMultiplier) {
+            Log.d(TAG, "setOverrideHomeButtonLongPress receives: " + duration + "; "
+                    + slopMultiplier);
+            mOverrideHomeButtonLongPressDurationMs = Optional.of(duration)
+                    .filter(value -> value > 0);
+            mOverrideHomeButtonLongPressSlopMultiplier = Optional.of(slopMultiplier)
+                    .filter(value -> value > 0);
+            mOverrideHomeButtonLongPressDurationMs.ifPresent(aLong
+                    -> Log.d(TAG, "Use duration override: " + aLong));
+            mOverrideHomeButtonLongPressSlopMultiplier.ifPresent(aFloat
+                    -> Log.d(TAG, "Use slop multiplier override: " + aFloat));
+            if (mView != null) {
+                reconfigureHomeLongClick();
+            }
+        }
+
+        @Override
         public void onHomeRotationEnabled(boolean enabled) {
             mView.getRotationButtonController().setHomeRotationEnabled(enabled);
         }
@@ -878,11 +900,6 @@
             refreshLayout(ld);
         }
         repositionNavigationBar(rotation);
-        // NOTE(b/260220098): In some cases, the recreated nav bar will already have the right
-        // configuration, which means that NavBarView will not receive a configuration change to
-        // propagate to EdgeBackGestureHandler (which is injected into this and NBV). As such, we
-        // should also force-update the gesture handler to ensure it updates to the right bounds
-        mEdgeBackGestureHandler.onConfigurationChanged(newConfig);
         if (canShowSecondaryHandle()) {
             if (rotation != mCurrentRotation) {
                 mCurrentRotation = rotation;
@@ -1016,7 +1033,10 @@
         if (mView.getHomeButton().getCurrentView() == null) {
             return;
         }
-        if (mHomeButtonLongPressDurationMs.isPresent() || !mLongPressHomeEnabled) {
+        if (mHomeButtonLongPressDurationMs.isPresent()
+                || mOverrideHomeButtonLongPressDurationMs.isPresent()
+                || mOverrideHomeButtonLongPressSlopMultiplier.isPresent()
+                || !mLongPressHomeEnabled) {
             mView.getHomeButton().getCurrentView().setLongClickable(false);
             mView.getHomeButton().getCurrentView().setHapticFeedbackEnabled(false);
             mView.getHomeButton().setOnLongClickListener(null);
@@ -1038,6 +1058,10 @@
         pw.println("  mStartingQuickSwitchRotation=" + mStartingQuickSwitchRotation);
         pw.println("  mCurrentRotation=" + mCurrentRotation);
         pw.println("  mHomeButtonLongPressDurationMs=" + mHomeButtonLongPressDurationMs);
+        pw.println("  mOverrideHomeButtonLongPressDurationMs="
+                + mOverrideHomeButtonLongPressDurationMs);
+        pw.println("  mOverrideHomeButtonLongPressSlopMultiplier="
+                + mOverrideHomeButtonLongPressSlopMultiplier);
         pw.println("  mLongPressHomeEnabled=" + mLongPressHomeEnabled);
         pw.println("  mNavigationBarWindowState="
                 + windowStateToString(mNavigationBarWindowState));
@@ -1331,6 +1355,10 @@
         final Optional<CentralSurfaces> centralSurfacesOptional = mCentralSurfacesOptionalLazy.get();
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
+                if (mCurrentDownEvent != null) {
+                    mCurrentDownEvent.recycle();
+                }
+                mCurrentDownEvent = MotionEvent.obtain(event);
                 mHomeBlockedThisTouch = false;
                 if (mTelecomManagerOptional.isPresent()
                         && mTelecomManagerOptional.get().isRinging()) {
@@ -1342,9 +1370,46 @@
                     }
                 }
                 if (mLongPressHomeEnabled) {
-                    mHomeButtonLongPressDurationMs.ifPresent(longPressDuration -> {
-                        mHandler.postDelayed(mOnVariableDurationHomeLongClick, longPressDuration);
-                    });
+                    if (mOverrideHomeButtonLongPressDurationMs.isPresent()) {
+                        Log.d(TAG, "ACTION_DOWN Launcher override duration: "
+                                + mOverrideHomeButtonLongPressDurationMs.get());
+                        mHandler.postDelayed(mOnVariableDurationHomeLongClick,
+                                mOverrideHomeButtonLongPressDurationMs.get());
+                    } else if (mOverrideHomeButtonLongPressSlopMultiplier.isPresent()) {
+                        // If override timeout doesn't exist but override touch slop exists, we use
+                        // system default long press duration
+                        Log.d(TAG, "ACTION_DOWN default duration: "
+                                + ViewConfiguration.getLongPressTimeout());
+                        mHandler.postDelayed(mOnVariableDurationHomeLongClick,
+                                ViewConfiguration.getLongPressTimeout());
+                    } else {
+                        mHomeButtonLongPressDurationMs.ifPresent(longPressDuration -> {
+                            Log.d(TAG, "ACTION_DOWN original duration: " + longPressDuration);
+                            mHandler.postDelayed(mOnVariableDurationHomeLongClick,
+                                    longPressDuration);
+                        });
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (!mHandler.hasCallbacks(mOnVariableDurationHomeLongClick)) {
+                    Log.v(TAG, "ACTION_MOVE no callback. Don't handle touch slop.");
+                    break;
+                }
+                Log.v(TAG, "ACTION_MOVE handle touch slop");
+                float customSlopMultiplier = mOverrideHomeButtonLongPressSlopMultiplier.orElse(1f);
+                float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+                float calculatedTouchSlop =
+                        customSlopMultiplier * QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON * touchSlop;
+                float touchSlopSquared = calculatedTouchSlop * calculatedTouchSlop;
+
+                float dx = event.getX() - mCurrentDownEvent.getX();
+                float dy = event.getY() - mCurrentDownEvent.getY();
+                double distanceSquared = (dx * dx) + (dy * dy);
+                if (distanceSquared > touchSlopSquared) {
+                    Log.i(TAG, "Touch slop passed. Abort.");
+                    mView.abortCurrentGesture();
+                    mHandler.removeCallbacks(mOnVariableDurationHomeLongClick);
                 }
                 break;
             case MotionEvent.ACTION_UP:
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
index 9f7d1b3..12f27038 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
@@ -162,14 +162,11 @@
         mIsLargeScreen = isLargeScreen(mContext);
         boolean willApplyConfig = mConfigChanges.applyNewConfig(mContext.getResources());
         boolean largeScreenChanged = mIsLargeScreen != isOldConfigLargeScreen;
-        // TODO(b/243765256): Disable this logging once b/243765256 is fixed.
+        // TODO(b/332635834): Disable this logging once b/332635834 is fixed.
         Log.i(DEBUG_MISSING_GESTURE_TAG, "NavbarController: newConfig=" + newConfig
                 + " mTaskbarDelegate initialized=" + mTaskbarDelegate.isInitialized()
                 + " willApplyConfigToNavbars=" + willApplyConfig
                 + " navBarCount=" + mNavigationBars.size());
-        if (mTaskbarDelegate.isInitialized()) {
-            mTaskbarDelegate.onConfigurationChanged(newConfig);
-        }
         // If we folded/unfolded while in 3 button, show navbar in folded state, hide in unfolded
         if (largeScreenChanged && updateNavbarForTaskbar()) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 1927f49..3c69ed9 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -1031,7 +1031,6 @@
         updateIcons(mTmpLastConfiguration);
         updateRecentsIcon();
         updateCurrentRotation();
-        mEdgeBackGestureHandler.onConfigurationChanged(mConfiguration);
         if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
                 || mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
             // If car mode or density changes, we need to reset the icons.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 5dd1bd8..f67973b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -39,7 +39,6 @@
 import android.app.StatusBarManager;
 import android.app.StatusBarManager.WindowVisibleState;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.inputmethodservice.InputMethodService;
@@ -72,7 +71,6 @@
 import com.android.systemui.statusbar.AutoHideUiElement;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BarTransitions;
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LightBarTransitionsController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -250,8 +248,6 @@
             mLightBarController.setNavigationBar(mLightBarTransitionsController);
             mPipOptional.ifPresent(this::addPipExclusionBoundsChangeListener);
             mEdgeBackGestureHandler.setBackAnimation(mBackAnimation);
-            mEdgeBackGestureHandler.onConfigurationChanged(
-                    mContext.getResources().getConfiguration());
             mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
             mInitialized = true;
         } finally {
@@ -495,10 +491,6 @@
         return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
     }
 
-    public void onConfigurationChanged(Configuration configuration) {
-        mEdgeBackGestureHandler.onConfigurationChanged(configuration);
-    }
-
     @Override
     public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
         mOverviewProxyService.onNavigationBarLumaSamplingEnabled(displayId, enable);
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 b3d848c..30f33a3 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -34,7 +34,6 @@
 import androidx.core.os.postDelayed
 import androidx.core.view.isVisible
 import androidx.dynamicanimation.animation.DynamicAnimation
-import com.android.internal.jank.Cuj.CUJ_BACK_PANEL_ARROW
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.util.LatencyTracker
 import com.android.systemui.dagger.qualifiers.Main
@@ -1039,7 +1038,7 @@
     override fun dump(pw: PrintWriter) {
         pw.println("$TAG:")
         pw.println("  currentState=$currentState")
-        pw.println("  isLeftPanel=$mView.isLeftPanel")
+        pw.println("  isLeftPanel=${mView.isLeftPanel}")
     }
 
     init {
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 9d0ea5e..b50ee57 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -71,8 +71,6 @@
 import com.android.internal.policy.GestureNavigationSettingsObserver;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.FalsingManager;
@@ -219,10 +217,8 @@
     private final Region mExcludeRegion = new Region();
     private final Region mDesktopModeExcludeRegion = new Region();
     private final Region mUnrestrictedExcludeRegion = new Region();
-    private final Provider<NavigationBarEdgePanel> mNavBarEdgePanelProvider;
     private final Provider<BackGestureTfClassifierProvider>
             mBackGestureTfClassifierProviderProvider;
-    private final FeatureFlags mFeatureFlags;
     private final Provider<LightBarController> mLightBarControllerProvider;
 
     // The left side edge width where touch down is allowed
@@ -264,8 +260,6 @@
     private boolean mIsEnabled;
     private boolean mIsNavBarShownTransiently;
     private boolean mIsBackGestureAllowed;
-    private boolean mIsNewBackAffordanceEnabled;
-    private boolean mIsTrackpadGestureFeaturesEnabled;
     private boolean mIsTrackpadThreeFingerSwipe;
     private boolean mIsButtonForcedVisible;
 
@@ -413,9 +407,7 @@
             Optional<Pip> pipOptional,
             Optional<DesktopMode> desktopModeOptional,
             FalsingManager falsingManager,
-            Provider<NavigationBarEdgePanel> navigationBarEdgePanelProvider,
             Provider<BackGestureTfClassifierProvider> backGestureTfClassifierProviderProvider,
-            FeatureFlags featureFlags,
             Provider<LightBarController> lightBarControllerProvider) {
         mContext = context;
         mDisplayId = context.getDisplayId();
@@ -435,13 +427,9 @@
         mPipOptional = pipOptional;
         mDesktopModeOptional = desktopModeOptional;
         mFalsingManager = falsingManager;
-        mNavBarEdgePanelProvider = navigationBarEdgePanelProvider;
         mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider;
-        mFeatureFlags = featureFlags;
         mLightBarControllerProvider = lightBarControllerProvider;
         mLastReportedConfig.setTo(mContext.getResources().getConfiguration());
-        mIsTrackpadGestureFeaturesEnabled = mFeatureFlags.isEnabled(
-                Flags.TRACKPAD_GESTURE_FEATURES);
         ComponentName recentsComponentName = ComponentName.unflattenFromString(
                 context.getString(com.android.internal.R.string.config_recentsComponentName));
         if (recentsComponentName != null) {
@@ -559,12 +547,10 @@
         mIsAttached = true;
         mOverviewProxyService.addCallback(mQuickSwitchListener);
         mSysUiState.addCallback(mSysUiStateCallback);
-        if (mIsTrackpadGestureFeaturesEnabled) {
-            mInputManager.registerInputDeviceListener(mInputDeviceListener, mMainHandler);
-            int [] inputDevices = mInputManager.getInputDeviceIds();
-            for (int inputDeviceId : inputDevices) {
-                mInputDeviceListener.onInputDeviceAdded(inputDeviceId);
-            }
+        mInputManager.registerInputDeviceListener(mInputDeviceListener, mMainHandler);
+        int [] inputDevices = mInputManager.getInputDeviceIds();
+        for (int inputDeviceId : inputDevices) {
+            mInputDeviceListener.onInputDeviceAdded(inputDeviceId);
         }
         updateIsEnabled();
         mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
@@ -616,9 +602,8 @@
         try {
             Trace.beginSection("EdgeBackGestureHandler#updateIsEnabled");
 
-            mIsGestureHandlingEnabled =
-                    mInGestureNavMode || (mIsTrackpadGestureFeaturesEnabled && mUsingThreeButtonNav
-                            && mIsTrackpadConnected);
+            mIsGestureHandlingEnabled = mInGestureNavMode || (mUsingThreeButtonNav
+                    && mIsTrackpadConnected);
             boolean isEnabled = mIsAttached && mIsGestureHandlingEnabled;
             if (isEnabled == mIsEnabled) {
                 return;
@@ -678,7 +663,6 @@
                         Choreographer.getInstance(), this::onInputEvent);
 
                 // Add a nav bar panel window
-                mIsNewBackAffordanceEnabled = mFeatureFlags.isEnabled(Flags.NEW_BACK_AFFORDANCE);
                 resetEdgeBackPlugin();
                 mPluginManager.addPluginListener(
                         this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
@@ -701,12 +685,7 @@
     }
 
     private void resetEdgeBackPlugin() {
-        if (mIsNewBackAffordanceEnabled) {
-            setEdgeBackPlugin(
-                    mBackPanelControllerFactory.create(mContext));
-        } else {
-            setEdgeBackPlugin(mNavBarEdgePanelProvider.get());
-        }
+        setEdgeBackPlugin(mBackPanelControllerFactory.create(mContext));
     }
 
     private void setEdgeBackPlugin(NavigationEdgeBackPlugin edgeBackPlugin) {
@@ -1001,8 +980,7 @@
                 Log.d(DEBUG_MISSING_GESTURE_TAG, "Start gesture: " + ev);
             }
 
-            mIsTrackpadThreeFingerSwipe = isTrackpadThreeFingerSwipe(
-                    mIsTrackpadGestureFeaturesEnabled, ev);
+            mIsTrackpadThreeFingerSwipe = isTrackpadThreeFingerSwipe(ev);
 
             // ACTION_UP or ACTION_CANCEL is not guaranteed to be called before a new
             // ACTION_DOWN, in that case we should just reuse the old instance.
@@ -1027,7 +1005,7 @@
                     && !mGestureBlockingActivityRunning.get()
                     && !QuickStepContract.isBackGestureDisabled(mSysUiFlags,
                             mIsTrackpadThreeFingerSwipe)
-                    && !isTrackpadScroll(mIsTrackpadGestureFeaturesEnabled, ev);
+                    && !isTrackpadScroll(ev);
             if (mIsTrackpadThreeFingerSwipe) {
                 // Trackpad back gestures don't have zones, so we don't need to check if the down
                 // event is within insets.
@@ -1187,7 +1165,7 @@
             updateDisabledForQuickstep(newConfig);
         }
 
-        // TODO(b/243765256): Disable this logging once b/243765256 is fixed.
+        // TODO(b/332635834): Disable this logging once b/332635834 is fixed.
         Log.i(DEBUG_MISSING_GESTURE_TAG, "Config changed: newConfig=" + newConfig
                 + " lastReportedConfig=" + mLastReportedConfig);
         mLastReportedConfig.updateFrom(newConfig);
@@ -1321,10 +1299,8 @@
         private final Optional<Pip> mPipOptional;
         private final Optional<DesktopMode> mDesktopModeOptional;
         private final FalsingManager mFalsingManager;
-        private final Provider<NavigationBarEdgePanel> mNavBarEdgePanelProvider;
         private final Provider<BackGestureTfClassifierProvider>
                 mBackGestureTfClassifierProviderProvider;
-        private final FeatureFlags mFeatureFlags;
         private final Provider<LightBarController> mLightBarControllerProvider;
 
         @Inject
@@ -1344,10 +1320,8 @@
                        Optional<Pip> pipOptional,
                        Optional<DesktopMode> desktopModeOptional,
                        FalsingManager falsingManager,
-                       Provider<NavigationBarEdgePanel> navBarEdgePanelProvider,
                        Provider<BackGestureTfClassifierProvider>
                                backGestureTfClassifierProviderProvider,
-                       FeatureFlags featureFlags,
                        Provider<LightBarController> lightBarControllerProvider) {
             mOverviewProxyService = overviewProxyService;
             mSysUiState = sysUiState;
@@ -1365,9 +1339,7 @@
             mPipOptional = pipOptional;
             mDesktopModeOptional = desktopModeOptional;
             mFalsingManager = falsingManager;
-            mNavBarEdgePanelProvider = navBarEdgePanelProvider;
             mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider;
-            mFeatureFlags = featureFlags;
             mLightBarControllerProvider = lightBarControllerProvider;
         }
 
@@ -1391,9 +1363,7 @@
                     mPipOptional,
                     mDesktopModeOptional,
                     mFalsingManager,
-                    mNavBarEdgePanelProvider,
                     mBackGestureTfClassifierProviderProvider,
-                    mFeatureFlags,
                     mLightBarControllerProvider);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
deleted file mode 100644
index 380846e..0000000
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.navigationbar.gestural;
-
-import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE;
-import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
-
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.os.VibrationEffect;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.ContextThemeWrapper;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
-
-import androidx.core.graphics.ColorUtils;
-import androidx.dynamicanimation.animation.DynamicAnimation;
-import androidx.dynamicanimation.animation.FloatPropertyCompat;
-import androidx.dynamicanimation.animation.SpringAnimation;
-import androidx.dynamicanimation.animation.SpringForce;
-
-import com.android.app.animation.Interpolators;
-import com.android.internal.util.LatencyTracker;
-import com.android.settingslib.Utils;
-import com.android.systemui.res.R;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.plugins.NavigationEdgeBackPlugin;
-import com.android.systemui.settings.DisplayTracker;
-import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
-import com.android.systemui.statusbar.VibratorHelper;
-
-import java.io.PrintWriter;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-
-public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPlugin {
-
-    private static final String TAG = "NavigationBarEdgePanel";
-
-    private static final boolean ENABLE_FAILSAFE = true;
-
-    private static final long COLOR_ANIMATION_DURATION_MS = 120;
-    private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 80;
-    private static final long DISAPPEAR_ARROW_ANIMATION_DURATION_MS = 100;
-    private static final long FAILSAFE_DELAY_MS = 200;
-
-    /**
-     * The time required since the first vibration effect to automatically trigger a click
-     */
-    private static final int GESTURE_DURATION_FOR_CLICK_MS = 400;
-
-    /**
-     * The size of the protection of the arrow in px. Only used if this is not background protected
-     */
-    private static final int PROTECTION_WIDTH_PX = 2;
-
-    /**
-     * The basic translation in dp where the arrow resides
-     */
-    private static final int BASE_TRANSLATION_DP = 32;
-
-    /**
-     * The length of the arrow leg measured from the center to the end
-     */
-    private static final int ARROW_LENGTH_DP = 18;
-
-    /**
-     * The angle measured from the xAxis, where the leg is when the arrow rests
-     */
-    private static final int ARROW_ANGLE_WHEN_EXTENDED_DEGREES = 56;
-
-    /**
-     * The angle that is added per 1000 px speed to the angle of the leg
-     */
-    private static final int ARROW_ANGLE_ADDED_PER_1000_SPEED = 4;
-
-    /**
-     * The maximum angle offset allowed due to speed
-     */
-    private static final int ARROW_MAX_ANGLE_SPEED_OFFSET_DEGREES = 4;
-
-    /**
-     * The thickness of the arrow. Adjusted to match the home handle (approximately)
-     */
-    private static final float ARROW_THICKNESS_DP = 2.5f;
-
-    /**
-     * The amount of rubber banding we do for the vertical translation
-     */
-    private static final int RUBBER_BAND_AMOUNT = 15;
-
-    /**
-     * The interpolator used to rubberband
-     */
-    private static final Interpolator RUBBER_BAND_INTERPOLATOR
-            = new PathInterpolator(1.0f / 5.0f, 1.0f, 1.0f, 1.0f);
-
-    /**
-     * The amount of rubber banding we do for the translation before base translation
-     */
-    private static final int RUBBER_BAND_AMOUNT_APPEAR = 4;
-
-    /**
-     * The interpolator used to rubberband the appearing of the arrow.
-     */
-    private static final Interpolator RUBBER_BAND_INTERPOLATOR_APPEAR
-            = new PathInterpolator(1.0f / RUBBER_BAND_AMOUNT_APPEAR, 1.0f, 1.0f, 1.0f);
-
-    private final WindowManager mWindowManager;
-    private final VibratorHelper mVibratorHelper;
-
-    /**
-     * The paint the arrow is drawn with
-     */
-    private final Paint mPaint = new Paint();
-    /**
-     * The paint the arrow protection is drawn with
-     */
-    private final Paint mProtectionPaint;
-
-    private final float mDensity;
-    private final float mBaseTranslation;
-    private final float mArrowLength;
-    private final float mArrowThickness;
-
-    /**
-     * The minimum delta needed in movement for the arrow to change direction / stop triggering back
-     */
-    private final float mMinDeltaForSwitch;
-    // The closest to y = 0 that the arrow will be displayed.
-    private int mMinArrowPosition;
-    // The amount the arrow is shifted to avoid the finger.
-    private int mFingerOffset;
-
-    private final float mSwipeTriggerThreshold;
-    private final float mSwipeProgressThreshold;
-    private final Path mArrowPath = new Path();
-    private final Point mDisplaySize = new Point();
-
-    private final SpringAnimation mAngleAnimation;
-    private final SpringAnimation mTranslationAnimation;
-    private final SpringAnimation mVerticalTranslationAnimation;
-    private final SpringForce mAngleAppearForce;
-    private final SpringForce mAngleDisappearForce;
-    private final ValueAnimator mArrowColorAnimator;
-    private final ValueAnimator mArrowDisappearAnimation;
-    private final SpringForce mRegularTranslationSpring;
-    private final SpringForce mTriggerBackSpring;
-    private final LatencyTracker mLatencyTracker;
-
-    private VelocityTracker mVelocityTracker;
-    private boolean mIsDark = false;
-    private boolean mShowProtection = false;
-    private int mProtectionColorLight;
-    private int mArrowPaddingEnd;
-    private int mArrowColorLight;
-    private int mProtectionColorDark;
-    private int mArrowColorDark;
-    private int mProtectionColor;
-    private int mArrowColor;
-    private RegionSamplingHelper mRegionSamplingHelper;
-    private final Rect mSamplingRect = new Rect();
-    private WindowManager.LayoutParams mLayoutParams;
-    private int mLeftInset;
-    private int mRightInset;
-
-    /**
-     * True if the panel is currently on the left of the screen
-     */
-    private boolean mIsLeftPanel;
-
-    private float mStartX;
-    private float mStartY;
-    private float mCurrentAngle;
-    /**
-     * The current translation of the arrow
-     */
-    private float mCurrentTranslation;
-    /**
-     * Where the arrow will be in the resting position.
-     */
-    private float mDesiredTranslation;
-
-    private boolean mDragSlopPassed;
-    private boolean mArrowsPointLeft;
-    private float mMaxTranslation;
-    private boolean mTriggerBack;
-    private float mPreviousTouchTranslation;
-    private float mTotalTouchDelta;
-    private float mVerticalTranslation;
-    private float mDesiredVerticalTranslation;
-    private float mDesiredAngle;
-    private float mAngleOffset;
-    private int mArrowStartColor;
-    private int mCurrentArrowColor;
-    private float mDisappearAmount;
-    private long mVibrationTime;
-    private int mScreenSize;
-    private boolean mTrackingBackArrowLatency = false;
-
-    private final Handler mHandler = new Handler();
-    private final Runnable mFailsafeRunnable = this::onFailsafe;
-
-    private DynamicAnimation.OnAnimationEndListener mSetGoneEndListener
-            = new DynamicAnimation.OnAnimationEndListener() {
-        @Override
-        public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
-                float velocity) {
-            animation.removeEndListener(this);
-            if (!canceled) {
-                setVisibility(GONE);
-            }
-        }
-    };
-    private static final FloatPropertyCompat<NavigationBarEdgePanel> CURRENT_ANGLE =
-            new FloatPropertyCompat<NavigationBarEdgePanel>("currentAngle") {
-        @Override
-        public void setValue(NavigationBarEdgePanel object, float value) {
-            object.setCurrentAngle(value);
-        }
-
-        @Override
-        public float getValue(NavigationBarEdgePanel object) {
-            return object.getCurrentAngle();
-        }
-    };
-
-    private static final FloatPropertyCompat<NavigationBarEdgePanel> CURRENT_TRANSLATION =
-            new FloatPropertyCompat<NavigationBarEdgePanel>("currentTranslation") {
-
-                @Override
-                public void setValue(NavigationBarEdgePanel object, float value) {
-                    object.setCurrentTranslation(value);
-                }
-
-                @Override
-                public float getValue(NavigationBarEdgePanel object) {
-                    return object.getCurrentTranslation();
-                }
-            };
-    private static final FloatPropertyCompat<NavigationBarEdgePanel> CURRENT_VERTICAL_TRANSLATION =
-            new FloatPropertyCompat<NavigationBarEdgePanel>("verticalTranslation") {
-
-                @Override
-                public void setValue(NavigationBarEdgePanel object, float value) {
-                    object.setVerticalTranslation(value);
-                }
-
-                @Override
-                public float getValue(NavigationBarEdgePanel object) {
-                    return object.getVerticalTranslation();
-                }
-            };
-    private BackCallback mBackCallback;
-
-    @Inject
-    public NavigationBarEdgePanel(
-            Context context,
-            LatencyTracker latencyTracker,
-            VibratorHelper vibratorHelper,
-            @Background Executor backgroundExecutor,
-            DisplayTracker displayTracker) {
-        super(context);
-
-        mWindowManager = context.getSystemService(WindowManager.class);
-        mVibratorHelper = vibratorHelper;
-
-        mDensity = context.getResources().getDisplayMetrics().density;
-
-        mBaseTranslation = dp(BASE_TRANSLATION_DP);
-        mArrowLength = dp(ARROW_LENGTH_DP);
-        mArrowThickness = dp(ARROW_THICKNESS_DP);
-        mMinDeltaForSwitch = dp(32);
-
-        mPaint.setStrokeWidth(mArrowThickness);
-        mPaint.setStrokeCap(Paint.Cap.ROUND);
-        mPaint.setAntiAlias(true);
-        mPaint.setStyle(Paint.Style.STROKE);
-        mPaint.setStrokeJoin(Paint.Join.ROUND);
-
-        mArrowColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
-        mArrowColorAnimator.setDuration(COLOR_ANIMATION_DURATION_MS);
-        mArrowColorAnimator.addUpdateListener(animation -> {
-            int newColor = ColorUtils.blendARGB(
-                    mArrowStartColor, mArrowColor, animation.getAnimatedFraction());
-            setCurrentArrowColor(newColor);
-        });
-
-        mArrowDisappearAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
-        mArrowDisappearAnimation.setDuration(DISAPPEAR_ARROW_ANIMATION_DURATION_MS);
-        mArrowDisappearAnimation.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        mArrowDisappearAnimation.addUpdateListener(animation -> {
-            mDisappearAmount = (float) animation.getAnimatedValue();
-            invalidate();
-        });
-
-        mAngleAnimation =
-                new SpringAnimation(this, CURRENT_ANGLE);
-        mAngleAppearForce = new SpringForce()
-                .setStiffness(500)
-                .setDampingRatio(0.5f);
-        mAngleDisappearForce = new SpringForce()
-                .setStiffness(SpringForce.STIFFNESS_MEDIUM)
-                .setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY)
-                .setFinalPosition(90);
-        mAngleAnimation.setSpring(mAngleAppearForce).setMaxValue(90);
-
-        mTranslationAnimation =
-                new SpringAnimation(this, CURRENT_TRANSLATION);
-        mRegularTranslationSpring = new SpringForce()
-                .setStiffness(SpringForce.STIFFNESS_MEDIUM)
-                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);
-        mTriggerBackSpring = new SpringForce()
-                .setStiffness(450)
-                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);
-        mTranslationAnimation.setSpring(mRegularTranslationSpring);
-        mVerticalTranslationAnimation =
-                new SpringAnimation(this, CURRENT_VERTICAL_TRANSLATION);
-        mVerticalTranslationAnimation.setSpring(
-                new SpringForce()
-                        .setStiffness(SpringForce.STIFFNESS_MEDIUM)
-                        .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
-
-        mProtectionPaint = new Paint(mPaint);
-        mProtectionPaint.setStrokeWidth(mArrowThickness + PROTECTION_WIDTH_PX);
-        loadDimens();
-
-        loadColors(context);
-        updateArrowDirection();
-
-        mSwipeTriggerThreshold = context.getResources()
-                .getDimension(R.dimen.navigation_edge_action_drag_threshold);
-        mSwipeProgressThreshold = context.getResources()
-                .getDimension(R.dimen.navigation_edge_action_progress_threshold);
-
-        setVisibility(GONE);
-
-        boolean isPrimaryDisplay = mContext.getDisplayId() == displayTracker.getDefaultDisplayId();
-        mRegionSamplingHelper = new RegionSamplingHelper(this,
-                new RegionSamplingHelper.SamplingCallback() {
-                    @Override
-                    public void onRegionDarknessChanged(boolean isRegionDark) {
-                        setIsDark(!isRegionDark, true /* animate */);
-                    }
-
-                    @Override
-                    public Rect getSampledRegion(View sampledView) {
-                        return mSamplingRect;
-                    }
-
-                    @Override
-                    public boolean isSamplingEnabled() {
-                        return isPrimaryDisplay;
-                    }
-                }, backgroundExecutor);
-        mRegionSamplingHelper.setWindowVisible(true);
-        mShowProtection = !isPrimaryDisplay;
-        mLatencyTracker = latencyTracker;
-    }
-
-    @Override
-    public void onDestroy() {
-        cancelFailsafe();
-        mWindowManager.removeView(this);
-        mRegionSamplingHelper.stop();
-        mRegionSamplingHelper = null;
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
-    private void setIsDark(boolean isDark, boolean animate) {
-        mIsDark = isDark;
-        updateIsDark(animate);
-    }
-
-    @Override
-    public void setIsLeftPanel(boolean isLeftPanel) {
-        mIsLeftPanel = isLeftPanel;
-        mLayoutParams.gravity = mIsLeftPanel
-                ? (Gravity.LEFT | Gravity.TOP)
-                : (Gravity.RIGHT | Gravity.TOP);
-    }
-
-    @Override
-    public void setInsets(int leftInset, int rightInset) {
-        mLeftInset = leftInset;
-        mRightInset = rightInset;
-    }
-
-    @Override
-    public void setDisplaySize(Point displaySize) {
-        mDisplaySize.set(displaySize.x, displaySize.y);
-        mScreenSize = Math.min(mDisplaySize.x, mDisplaySize.y);
-    }
-
-    @Override
-    public void setBackCallback(BackCallback callback) {
-        mBackCallback = callback;
-    }
-
-    @Override
-    public void setLayoutParams(WindowManager.LayoutParams layoutParams) {
-        mLayoutParams = layoutParams;
-        mWindowManager.addView(this, mLayoutParams);
-    }
-
-    /**
-     * Adjusts the sampling rect to conform to the actual visible bounding box of the arrow.
-     */
-    private void adjustSamplingRectToBoundingBox() {
-        float translation = mDesiredTranslation;
-        if (!mTriggerBack) {
-            // Let's take the resting position and bounds as the sampling rect, since we are not
-            // visible right now
-            translation = mBaseTranslation;
-            if (mIsLeftPanel && mArrowsPointLeft
-                    || (!mIsLeftPanel && !mArrowsPointLeft)) {
-                // If we're on the left we should move less, because the arrow is facing the other
-                // direction
-                translation -= getStaticArrowWidth();
-            }
-        }
-        float left = translation - mArrowThickness / 2.0f;
-        left = mIsLeftPanel ? left : mSamplingRect.width() - left;
-
-        // Let's calculate the position of the end based on the angle
-        float width = getStaticArrowWidth();
-        float height = polarToCartY(ARROW_ANGLE_WHEN_EXTENDED_DEGREES) * mArrowLength * 2.0f;
-        if (!mArrowsPointLeft) {
-            left -= width;
-        }
-
-        float top = (getHeight() * 0.5f) + mDesiredVerticalTranslation - height / 2.0f;
-        mSamplingRect.offset((int) left, (int) top);
-        mSamplingRect.set(mSamplingRect.left, mSamplingRect.top,
-                (int) (mSamplingRect.left + width),
-                (int) (mSamplingRect.top + height));
-        mRegionSamplingHelper.updateSamplingRect();
-    }
-
-    @Override
-    public void onMotionEvent(MotionEvent event) {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-        mVelocityTracker.addMovement(event);
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                mDragSlopPassed = false;
-                resetOnDown();
-                mStartX = event.getX();
-                mStartY = event.getY();
-                setVisibility(VISIBLE);
-                updatePosition(event.getY());
-                mRegionSamplingHelper.start(mSamplingRect);
-                mWindowManager.updateViewLayout(this, mLayoutParams);
-                mLatencyTracker.onActionStart(LatencyTracker.ACTION_SHOW_BACK_ARROW);
-                mTrackingBackArrowLatency = true;
-                break;
-            case MotionEvent.ACTION_MOVE:
-                handleMoveEvent(event);
-                break;
-            case MotionEvent.ACTION_UP:
-                if (DEBUG_MISSING_GESTURE) {
-                    Log.d(DEBUG_MISSING_GESTURE_TAG,
-                            "NavigationBarEdgePanel ACTION_UP, mTriggerBack=" + mTriggerBack);
-                }
-                if (mTriggerBack) {
-                    triggerBack();
-                } else {
-                    cancelBack();
-                }
-                mRegionSamplingHelper.stop();
-                mVelocityTracker.recycle();
-                mVelocityTracker = null;
-                break;
-            case MotionEvent.ACTION_CANCEL:
-                if (DEBUG_MISSING_GESTURE) {
-                    Log.d(DEBUG_MISSING_GESTURE_TAG, "NavigationBarEdgePanel ACTION_CANCEL");
-                }
-                cancelBack();
-                mRegionSamplingHelper.stop();
-                mVelocityTracker.recycle();
-                mVelocityTracker = null;
-                break;
-        }
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        updateArrowDirection();
-        loadDimens();
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        float pointerPosition = mCurrentTranslation - mArrowThickness / 2.0f;
-        canvas.save();
-        canvas.translate(
-                mIsLeftPanel ? pointerPosition : getWidth() - pointerPosition,
-                (getHeight() * 0.5f) + mVerticalTranslation);
-
-        // Let's calculate the position of the end based on the angle
-        float x = (polarToCartX(mCurrentAngle) * mArrowLength);
-        float y = (polarToCartY(mCurrentAngle) * mArrowLength);
-        Path arrowPath = calculatePath(x,y);
-        if (mShowProtection) {
-            canvas.drawPath(arrowPath, mProtectionPaint);
-        }
-
-        canvas.drawPath(arrowPath, mPaint);
-        canvas.restore();
-        if (mTrackingBackArrowLatency) {
-            mLatencyTracker.onActionEnd(LatencyTracker.ACTION_SHOW_BACK_ARROW);
-            mTrackingBackArrowLatency = false;
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-
-        mMaxTranslation = getWidth() - mArrowPaddingEnd;
-    }
-
-    private void loadDimens() {
-        Resources res = getResources();
-        mArrowPaddingEnd = res.getDimensionPixelSize(R.dimen.navigation_edge_panel_padding);
-        mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
-        mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
-    }
-
-    private void updateArrowDirection() {
-        // Both panels arrow point the same way
-        mArrowsPointLeft = getLayoutDirection() == LAYOUT_DIRECTION_LTR;
-        invalidate();
-    }
-
-    private void loadColors(Context context) {
-        final int dualToneDarkTheme = Utils.getThemeAttr(context, R.attr.darkIconTheme);
-        final int dualToneLightTheme = Utils.getThemeAttr(context, R.attr.lightIconTheme);
-        Context lightContext = new ContextThemeWrapper(context, dualToneLightTheme);
-        Context darkContext = new ContextThemeWrapper(context, dualToneDarkTheme);
-        mArrowColorLight = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
-        mArrowColorDark = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);
-        mProtectionColorDark = mArrowColorLight;
-        mProtectionColorLight = mArrowColorDark;
-        updateIsDark(false /* animate */);
-    }
-
-    private void updateIsDark(boolean animate) {
-        // TODO: Maybe animate protection as well
-        mProtectionColor = mIsDark ? mProtectionColorDark : mProtectionColorLight;
-        mProtectionPaint.setColor(mProtectionColor);
-        mArrowColor = mIsDark ? mArrowColorDark : mArrowColorLight;
-        mArrowColorAnimator.cancel();
-        if (!animate) {
-            setCurrentArrowColor(mArrowColor);
-        } else {
-            mArrowStartColor = mCurrentArrowColor;
-            mArrowColorAnimator.start();
-        }
-    }
-
-    private void setCurrentArrowColor(int color) {
-        mCurrentArrowColor = color;
-        mPaint.setColor(color);
-        invalidate();
-    }
-
-    private float getStaticArrowWidth() {
-        return polarToCartX(ARROW_ANGLE_WHEN_EXTENDED_DEGREES) * mArrowLength;
-    }
-
-    private float polarToCartX(float angleInDegrees) {
-        return (float) Math.cos(Math.toRadians(angleInDegrees));
-    }
-
-    private float polarToCartY(float angleInDegrees) {
-        return (float) Math.sin(Math.toRadians(angleInDegrees));
-    }
-
-    private Path calculatePath(float x, float y) {
-        if (!mArrowsPointLeft) {
-            x = -x;
-        }
-        float extent = MathUtils.lerp(1.0f, 0.75f, mDisappearAmount);
-        x = x * extent;
-        y = y * extent;
-        mArrowPath.reset();
-        mArrowPath.moveTo(x, y);
-        mArrowPath.lineTo(0, 0);
-        mArrowPath.lineTo(x, -y);
-        return mArrowPath;
-    }
-
-    private float getCurrentAngle() {
-        return mCurrentAngle;
-    }
-
-    private float getCurrentTranslation() {
-        return mCurrentTranslation;
-    }
-
-    private void triggerBack() {
-        mBackCallback.triggerBack();
-
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-        mVelocityTracker.computeCurrentVelocity(1000);
-        // Only do the extra translation if we're not already flinging
-        boolean isSlow = Math.abs(mVelocityTracker.getXVelocity()) < 500;
-        if (isSlow
-                || SystemClock.uptimeMillis() - mVibrationTime >= GESTURE_DURATION_FOR_CLICK_MS) {
-            mVibratorHelper.vibrate(VibrationEffect.EFFECT_CLICK);
-        }
-
-        // Let's also snap the angle a bit
-        if (mAngleOffset > -4) {
-            mAngleOffset = Math.max(-8, mAngleOffset - 8);
-            updateAngle(true /* animated */);
-        }
-
-        // Finally, after the translation, animate back and disappear the arrow
-        Runnable translationEnd = () -> {
-            // let's snap it back
-            mAngleOffset = Math.max(0, mAngleOffset + 8);
-            updateAngle(true /* animated */);
-
-            mTranslationAnimation.setSpring(mTriggerBackSpring);
-            // Translate the arrow back a bit to make for a nice transition
-            setDesiredTranslation(mDesiredTranslation - dp(32), true /* animated */);
-            animate().alpha(0f).setDuration(DISAPPEAR_FADE_ANIMATION_DURATION_MS)
-                    .withEndAction(() -> setVisibility(GONE));
-            mArrowDisappearAnimation.start();
-            // Schedule failsafe in case alpha end callback is not called
-            scheduleFailsafe();
-        };
-        if (mTranslationAnimation.isRunning()) {
-            mTranslationAnimation.addEndListener(new DynamicAnimation.OnAnimationEndListener() {
-                @Override
-                public void onAnimationEnd(DynamicAnimation animation, boolean canceled,
-                        float value,
-                        float velocity) {
-                    animation.removeEndListener(this);
-                    if (!canceled) {
-                        translationEnd.run();
-                    }
-                }
-            });
-            // Schedule failsafe in case mTranslationAnimation end callback is not called
-            scheduleFailsafe();
-        } else {
-            translationEnd.run();
-        }
-    }
-
-    private void cancelBack() {
-        mBackCallback.cancelBack();
-
-        if (mTranslationAnimation.isRunning()) {
-            mTranslationAnimation.addEndListener(mSetGoneEndListener);
-            // Schedule failsafe in case mTranslationAnimation end callback is not called
-            scheduleFailsafe();
-        } else {
-            setVisibility(GONE);
-        }
-    }
-
-    private void resetOnDown() {
-        animate().cancel();
-        mAngleAnimation.cancel();
-        mTranslationAnimation.cancel();
-        mVerticalTranslationAnimation.cancel();
-        mArrowDisappearAnimation.cancel();
-        mAngleOffset = 0;
-        mTranslationAnimation.setSpring(mRegularTranslationSpring);
-        // Reset the arrow to the side
-        if (DEBUG_MISSING_GESTURE) {
-            Log.d(DEBUG_MISSING_GESTURE_TAG, "reset mTriggerBack=false");
-        }
-        setTriggerBack(false /* triggerBack */, false /* animated */);
-        setDesiredTranslation(0, false /* animated */);
-        setCurrentTranslation(0);
-        updateAngle(false /* animate */);
-        mPreviousTouchTranslation = 0;
-        mTotalTouchDelta = 0;
-        mVibrationTime = 0;
-        setDesiredVerticalTransition(0, false /* animated */);
-        cancelFailsafe();
-    }
-
-    private void handleMoveEvent(MotionEvent event) {
-        float x = event.getX();
-        float y = event.getY();
-        float touchTranslation = MathUtils.abs(x - mStartX);
-        float yOffset = y - mStartY;
-        float delta = touchTranslation - mPreviousTouchTranslation;
-        if (Math.abs(delta) > 0) {
-            if (Math.signum(delta) == Math.signum(mTotalTouchDelta)) {
-                mTotalTouchDelta += delta;
-            } else {
-                mTotalTouchDelta = delta;
-            }
-        }
-        mPreviousTouchTranslation = touchTranslation;
-
-        // Apply a haptic on drag slop passed
-        if (!mDragSlopPassed && touchTranslation > mSwipeTriggerThreshold) {
-            mDragSlopPassed = true;
-            mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
-            mVibrationTime = SystemClock.uptimeMillis();
-
-            // Let's show the arrow and animate it in!
-            mDisappearAmount = 0.0f;
-            setAlpha(1f);
-            // And animate it go to back by default!
-            if (DEBUG_MISSING_GESTURE) {
-                Log.d(DEBUG_MISSING_GESTURE_TAG, "set mTriggerBack=true");
-            }
-            setTriggerBack(true /* triggerBack */, true /* animated */);
-        }
-
-        // Let's make sure we only go to the baseextend and apply rubberbanding afterwards
-        if (touchTranslation > mBaseTranslation) {
-            float diff = touchTranslation - mBaseTranslation;
-            float progress = MathUtils.saturate(diff / (mScreenSize - mBaseTranslation));
-            progress = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
-                    * (mMaxTranslation - mBaseTranslation);
-            touchTranslation = mBaseTranslation + progress;
-        } else {
-            float diff = mBaseTranslation - touchTranslation;
-            float progress = MathUtils.saturate(diff / mBaseTranslation);
-            progress = RUBBER_BAND_INTERPOLATOR_APPEAR.getInterpolation(progress)
-                    * (mBaseTranslation / RUBBER_BAND_AMOUNT_APPEAR);
-            touchTranslation = mBaseTranslation - progress;
-        }
-        // By default we just assume the current direction is kept
-        boolean triggerBack = mTriggerBack;
-
-        //  First lets see if we had continuous motion in one direction for a while
-        if (Math.abs(mTotalTouchDelta) > mMinDeltaForSwitch) {
-            triggerBack = mTotalTouchDelta > 0;
-        }
-
-        // Then, let's see if our velocity tells us to change direction
-        mVelocityTracker.computeCurrentVelocity(1000);
-        float xVelocity = mVelocityTracker.getXVelocity();
-        float yVelocity = mVelocityTracker.getYVelocity();
-        float velocity = MathUtils.mag(xVelocity, yVelocity);
-        mAngleOffset = Math.min(velocity / 1000 * ARROW_ANGLE_ADDED_PER_1000_SPEED,
-                ARROW_MAX_ANGLE_SPEED_OFFSET_DEGREES) * Math.signum(xVelocity);
-        if (mIsLeftPanel && mArrowsPointLeft || !mIsLeftPanel && !mArrowsPointLeft) {
-            mAngleOffset *= -1;
-        }
-
-        // Last if the direction in Y is bigger than X * 2 we also abort
-        if (Math.abs(yOffset) > Math.abs(x - mStartX) * 2) {
-            triggerBack = false;
-        }
-        if (DEBUG_MISSING_GESTURE && mTriggerBack != triggerBack) {
-            Log.d(DEBUG_MISSING_GESTURE_TAG, "set mTriggerBack=" + triggerBack
-                    + ", mTotalTouchDelta=" + mTotalTouchDelta
-                    + ", mMinDeltaForSwitch=" + mMinDeltaForSwitch
-                    + ", yOffset=" + yOffset
-                    + ", x=" + x
-                    + ", mStartX=" + mStartX);
-        }
-        setTriggerBack(triggerBack, true /* animated */);
-
-        if (!mTriggerBack) {
-            touchTranslation = 0;
-        } else if (mIsLeftPanel && mArrowsPointLeft
-                || (!mIsLeftPanel && !mArrowsPointLeft)) {
-            // If we're on the left we should move less, because the arrow is facing the other
-            // direction
-            touchTranslation -= getStaticArrowWidth();
-        }
-        setDesiredTranslation(touchTranslation, true /* animated */);
-        updateAngle(true /* animated */);
-
-        float maxYOffset = getHeight() / 2.0f - mArrowLength;
-        float progress = MathUtils.constrain(
-                Math.abs(yOffset) / (maxYOffset * RUBBER_BAND_AMOUNT),
-                0, 1);
-        float verticalTranslation = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
-                * maxYOffset * Math.signum(yOffset);
-        setDesiredVerticalTransition(verticalTranslation, true /* animated */);
-        updateSamplingRect();
-    }
-
-    private void updatePosition(float touchY) {
-        float position = touchY - mFingerOffset;
-        position = Math.max(position, mMinArrowPosition);
-        position -= mLayoutParams.height / 2.0f;
-        mLayoutParams.y = MathUtils.constrain((int) position, 0, mDisplaySize.y);
-        updateSamplingRect();
-    }
-
-    private void updateSamplingRect() {
-        int top = mLayoutParams.y;
-        int left = mIsLeftPanel ? mLeftInset : mDisplaySize.x - mRightInset - mLayoutParams.width;
-        int right = left + mLayoutParams.width;
-        int bottom = top + mLayoutParams.height;
-        mSamplingRect.set(left, top, right, bottom);
-        adjustSamplingRectToBoundingBox();
-    }
-
-    private void setDesiredVerticalTransition(float verticalTranslation, boolean animated) {
-        if (mDesiredVerticalTranslation != verticalTranslation) {
-            mDesiredVerticalTranslation = verticalTranslation;
-            if (!animated) {
-                setVerticalTranslation(verticalTranslation);
-            } else {
-                mVerticalTranslationAnimation.animateToFinalPosition(verticalTranslation);
-            }
-            invalidate();
-        }
-    }
-
-    private void setVerticalTranslation(float verticalTranslation) {
-        mVerticalTranslation = verticalTranslation;
-        invalidate();
-    }
-
-    private float getVerticalTranslation() {
-        return mVerticalTranslation;
-    }
-
-    private void setDesiredTranslation(float desiredTranslation, boolean animated) {
-        if (mDesiredTranslation != desiredTranslation) {
-            mDesiredTranslation = desiredTranslation;
-            if (!animated) {
-                setCurrentTranslation(desiredTranslation);
-            } else {
-                mTranslationAnimation.animateToFinalPosition(desiredTranslation);
-            }
-        }
-    }
-
-    private void setCurrentTranslation(float currentTranslation) {
-        mCurrentTranslation = currentTranslation;
-        invalidate();
-    }
-
-    private void setTriggerBack(boolean triggerBack, boolean animated) {
-        if (mTriggerBack != triggerBack) {
-            mTriggerBack = triggerBack;
-            mAngleAnimation.cancel();
-            updateAngle(animated);
-            // Whenever the trigger back state changes the existing translation animation should be
-            // cancelled
-            mTranslationAnimation.cancel();
-            mBackCallback.setTriggerBack(mTriggerBack);
-        }
-    }
-
-    private void updateAngle(boolean animated) {
-        float newAngle = mTriggerBack ? ARROW_ANGLE_WHEN_EXTENDED_DEGREES + mAngleOffset : 90;
-        if (newAngle != mDesiredAngle) {
-            if (!animated) {
-                setCurrentAngle(newAngle);
-            } else {
-                mAngleAnimation.setSpring(mTriggerBack ? mAngleAppearForce : mAngleDisappearForce);
-                mAngleAnimation.animateToFinalPosition(newAngle);
-            }
-            mDesiredAngle = newAngle;
-        }
-    }
-
-    private void setCurrentAngle(float currentAngle) {
-        mCurrentAngle = currentAngle;
-        invalidate();
-    }
-
-    private void scheduleFailsafe() {
-        if (!ENABLE_FAILSAFE) {
-            return;
-        }
-        cancelFailsafe();
-        mHandler.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY_MS);
-    }
-
-    private void cancelFailsafe() {
-        mHandler.removeCallbacks(mFailsafeRunnable);
-    }
-
-    private void onFailsafe() {
-        setVisibility(GONE);
-    }
-
-    private float dp(float dp) {
-        return mDensity * dp;
-    }
-
-    @Override
-    public void dump(PrintWriter pw) {
-        pw.println("NavigationBarEdgePanel:");
-        pw.println("  mIsLeftPanel=" + mIsLeftPanel);
-        pw.println("  mTriggerBack=" + mTriggerBack);
-        pw.println("  mDragSlopPassed=" + mDragSlopPassed);
-        pw.println("  mCurrentAngle=" + mCurrentAngle);
-        pw.println("  mDesiredAngle=" + mDesiredAngle);
-        pw.println("  mCurrentTranslation=" + mCurrentTranslation);
-        pw.println("  mDesiredTranslation=" + mDesiredTranslation);
-        pw.println("  mTranslationAnimation running=" + mTranslationAnimation.isRunning());
-        mRegionSamplingHelper.dump(pw);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
index 10a88c8..b46f2d2 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
@@ -24,16 +24,12 @@
 
 public final class Utilities {
 
-    public static boolean isTrackpadScroll(boolean isTrackpadGestureFeaturesEnabled,
-            MotionEvent event) {
-        return isTrackpadGestureFeaturesEnabled
-                && event.getClassification() == CLASSIFICATION_TWO_FINGER_SWIPE;
+    public static boolean isTrackpadScroll(MotionEvent event) {
+        return event.getClassification() == CLASSIFICATION_TWO_FINGER_SWIPE;
     }
 
-    public static boolean isTrackpadThreeFingerSwipe(boolean isTrackpadGestureFeaturesEnabled,
-            MotionEvent event) {
-        return isTrackpadGestureFeaturesEnabled
-                && event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE
+    public static boolean isTrackpadThreeFingerSwipe(MotionEvent event) {
+        return event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE
                 && event.getAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index 9698548d..54a59f30 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -38,7 +38,7 @@
 import javax.inject.Inject
 
 /** Class responsible to "glue" all note task dependencies. */
-internal class NoteTaskInitializer
+class NoteTaskInitializer
 @Inject
 constructor(
     private val controller: NoteTaskController,
@@ -138,11 +138,12 @@
      * Returns a [NoteTaskEntryPoint] if an action should be taken, and null otherwise.
      */
     private fun KeyEvent.toNoteTaskEntryPointOrNull(): NoteTaskEntryPoint? {
-        val entryPoint = when {
-            keyCode == KEYCODE_STYLUS_BUTTON_TAIL && isTailButtonNotesGesture() -> TAIL_BUTTON
-            keyCode == KEYCODE_N && isMetaPressed && isCtrlPressed -> KEYBOARD_SHORTCUT
-            else -> null
-        }
+        val entryPoint =
+            when {
+                keyCode == KEYCODE_STYLUS_BUTTON_TAIL && isTailButtonNotesGesture() -> TAIL_BUTTON
+                keyCode == KEYCODE_N && isMetaPressed && isCtrlPressed -> KEYBOARD_SHORTCUT
+                else -> null
+            }
         debugLog { "toNoteTaskEntryPointOrNull: entryPoint=$entryPoint" }
         return entryPoint
     }
@@ -164,7 +165,9 @@
 
         // For now, trigger action immediately on UP of a single press, without waiting for
         // the multi-press timeout to expire.
-        debugLog { "isTailButtonNotesGesture: isMultiPress=$isMultiPress, isLongPress=$isLongPress" }
+        debugLog {
+            "isTailButtonNotesGesture: isMultiPress=$isMultiPress, isLongPress=$isLongPress"
+        }
         return !isMultiPress && !isLongPress
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
index 3f8834a..9380d44 100644
--- a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
@@ -281,5 +281,10 @@
                 powerButtonLaunchGestureTriggeredDuringSleep = false,
             )
         }
+
+        /** Helper method for tests to simulate the device screen state change event. */
+        fun PowerInteractor.setScreenPowerState(screenPowerState: ScreenPowerState) {
+            this.onScreenPowerStateUpdated(screenPowerState)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 4ee2db7..042fb63f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -75,6 +75,10 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        // set layer to make alpha animation of brightness slider nicer - otherwise elements
+        // of slider are animated separately and it doesn't look good. See b/329244723
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+
         mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view);
         mQSPanel = findViewById(R.id.quick_settings_panel);
         mHeader = findViewById(R.id.header);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index ffbc560..7ccdf0a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -24,7 +24,7 @@
 
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.util.ViewController;
 
@@ -66,15 +66,14 @@
             QSPanelController qsPanelController,
             QuickStatusBarHeaderController quickStatusBarHeaderController,
             ConfigurationController configurationController,
-            FalsingManager falsingManager,
-            SceneContainerFlags sceneContainerFlags) {
+            FalsingManager falsingManager) {
         super(view);
         mQsPanelController = qsPanelController;
         mQuickStatusBarHeaderController = quickStatusBarHeaderController;
         mConfigurationController = configurationController;
         mFalsingManager = falsingManager;
         mQSPanelContainer = mView.getQSPanelContainer();
-        mSceneContainerEnabled = sceneContainerFlags.isEnabled();
+        mSceneContainerEnabled = SceneContainerFlag.isEnabled();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
index 3b3844a..e424975 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
@@ -31,7 +31,7 @@
 import com.android.systemui.plugins.qs.QSContainerController;
 import com.android.systemui.qs.dagger.QSFragmentComponent;
 import com.android.systemui.res.R;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.settings.brightness.MirrorController;
 import com.android.systemui.util.LifecycleFragment;
 
 import java.util.function.Consumer;
@@ -182,7 +182,7 @@
     }
 
     public void setBrightnessMirrorController(
-            BrightnessMirrorController brightnessMirrorController) {
+            MirrorController brightnessMirrorController) {
         if (mQsImpl != null) {
             mQsImpl.setBrightnessMirrorController(brightnessMirrorController);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
index a000d63..1f4838e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
@@ -60,7 +60,8 @@
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
+import com.android.systemui.settings.brightness.MirrorController;
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusBarState;
@@ -68,7 +69,6 @@
 import com.android.systemui.statusbar.disableflags.DisableFlagsLogger;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.util.Utils;
 
@@ -174,8 +174,6 @@
     @Nullable
     private View mFooterActionsView;
 
-    private final SceneContainerFlags mSceneContainerFlags;
-
     @Inject
     public QSImpl(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
             SysuiStatusBarStateController statusBarStateController, CommandQueue commandQueue,
@@ -188,8 +186,7 @@
             FooterActionsViewModel.Factory footerActionsViewModelFactory,
             FooterActionsViewBinder footerActionsViewBinder,
             LargeScreenShadeInterpolator largeScreenShadeInterpolator,
-            FeatureFlags featureFlags,
-            SceneContainerFlags sceneContainerFlags) {
+            FeatureFlags featureFlags) {
         mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
         mQsMediaHost = qsMediaHost;
         mQqsMediaHost = qqsMediaHost;
@@ -205,8 +202,7 @@
         mFooterActionsViewModelFactory = footerActionsViewModelFactory;
         mFooterActionsViewBinder = footerActionsViewBinder;
         mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
-        mSceneContainerFlags = sceneContainerFlags;
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             mStatusBarState = StatusBarState.SHADE;
         }
     }
@@ -224,7 +220,7 @@
         mQSPanelController.init();
         mQuickQSPanelController.init();
 
-        if (!mSceneContainerFlags.isEnabled()) {
+        if (!SceneContainerFlag.isEnabled()) {
             mQSFooterActionsViewModel = mFooterActionsViewModelFactory
                     .create(mListeningAndVisibilityLifecycleOwner);
             bindFooterActionsView(mRootView);
@@ -249,7 +245,7 @@
                         mScrollListener.onQsPanelScrollChanged(scrollY);
                     }
                 });
-        mQSPanelScrollView.setScrollingEnabled(!mSceneContainerFlags.isEnabled());
+        mQSPanelScrollView.setScrollingEnabled(!SceneContainerFlag.isEnabled());
         mHeader = mRootView.findViewById(R.id.header);
         mFooter = qsComponent.getQSFooter();
 
@@ -509,7 +505,7 @@
 
     @VisibleForTesting
     boolean isKeyguardState() {
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             return false;
         } else {
             // We want the freshest state here since otherwise we'll have some weirdness if earlier
@@ -544,7 +540,7 @@
     }
 
     public void setBrightnessMirrorController(
-            BrightnessMirrorController brightnessMirrorController) {
+            @Nullable MirrorController brightnessMirrorController) {
         mQSPanelController.setBrightnessMirror(brightnessMirrorController);
     }
 
@@ -573,7 +569,7 @@
     }
 
     private void setKeyguardShowing(boolean keyguardShowing) {
-        if (!mSceneContainerFlags.isEnabled()) {
+        if (!SceneContainerFlag.isEnabled()) {
             if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
             mLastQSExpansion = -1;
 
@@ -651,7 +647,7 @@
 
     @Override
     public int getHeightDiff() {
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             return mQSPanelController.getViewBottom() - mHeader.getBottom()
                     + mHeader.getPaddingBottom();
         } else {
@@ -720,7 +716,7 @@
         mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
         mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
 
-        if (!mSceneContainerFlags.isEnabled()) {
+        if (!SceneContainerFlag.isEnabled()) {
             float qsScrollViewTranslation =
                     onKeyguard && !mShowCollapsedOnKeyguard ? panelTranslationY : 0;
             mQSPanelScrollView.setTranslationY(qsScrollViewTranslation);
@@ -824,7 +820,7 @@
             mQsBounds.set(-sideMargin, 0, mQSPanelScrollView.getWidth() + sideMargin,
                     mQSPanelScrollView.getHeight());
         }
-        if (!mSceneContainerFlags.isEnabled()) {
+        if (!SceneContainerFlag.isEnabled()) {
             mQSPanelScrollView.setClipBounds(mQsBounds);
 
             mQSPanelScrollView.getLocationOnScreen(mLocationTemp);
@@ -907,7 +903,7 @@
         // The customize state changed, so our height changed.
         mContainer.updateExpansion();
         boolean customizing = isCustomizing();
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             mQSPanelController.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
         } else {
             mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE);
@@ -984,7 +980,7 @@
 
     @Override
     public void onStateChanged(int newState) {
-        if (mSceneContainerFlags.isEnabled() || newState == mStatusBarState) {
+        if (SceneContainerFlag.isEnabled() || newState == mStatusBarState) {
             return;
         }
         mStatusBarState = newState;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index cd65119..e24caf1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -24,9 +24,12 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.haptics.qs.QSLongPressEffect;
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
 import com.android.systemui.media.controls.ui.view.MediaHost;
 import com.android.systemui.media.controls.ui.view.MediaHostState;
@@ -34,18 +37,18 @@
 import com.android.systemui.qs.customize.QSCustomizerController;
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.settings.brightness.BrightnessController;
 import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
-import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.settings.brightness.MirrorController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.SplitShadeStateController;
 import com.android.systemui.tuner.TunerService;
 
 import javax.inject.Inject;
 import javax.inject.Named;
+import javax.inject.Provider;
 
 /**
  * Controller for {@link QSPanel}.
@@ -91,11 +94,10 @@
             FalsingManager falsingManager,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             SplitShadeStateController splitShadeStateController,
-            SceneContainerFlags sceneContainerFlags,
-            VibratorHelper vibratorHelper) {
+            Provider<QSLongPressEffect> longPRessEffectProvider) {
         super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost,
                 metricsLogger, uiEventLogger, qsLogger, dumpManager, splitShadeStateController,
-                vibratorHelper);
+                longPRessEffectProvider);
         mTunerService = tunerService;
         mQsCustomizerController = qsCustomizerController;
         mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
@@ -110,7 +112,7 @@
         mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mLastDensity = view.getResources().getConfiguration().densityDpi;
-        mSceneContainerEnabled = sceneContainerFlags.isEnabled();
+        mSceneContainerEnabled = SceneContainerFlag.isEnabled();
     }
 
     @Override
@@ -139,6 +141,7 @@
         mBrightnessMirrorHandler.onQsPanelAttached();
         PagedTileLayout pagedTileLayout= ((PagedTileLayout) mView.getOrCreateTileLayout());
         pagedTileLayout.setOnTouchListener(mTileLayoutTouchListener);
+        maybeReinflateBrightnessSlider();
     }
 
     @Override
@@ -157,15 +160,18 @@
     @Override
     protected void onConfigurationChanged() {
         mView.updateResources();
+        maybeReinflateBrightnessSlider();
+        if (mView.isListening()) {
+            refreshAllTiles();
+        }
+    }
+
+    private void maybeReinflateBrightnessSlider() {
         int newDensity = mView.getResources().getConfiguration().densityDpi;
         if (newDensity != mLastDensity) {
             mLastDensity = newDensity;
             reinflateBrightnessSlider();
         }
-
-        if (mView.isListening()) {
-            refreshAllTiles();
-        }
     }
 
     private void reinflateBrightnessSlider() {
@@ -210,7 +216,7 @@
         }
     }
 
-    public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
+    public void setBrightnessMirror(@Nullable MirrorController brightnessMirrorController) {
         mBrightnessMirrorHandler.setController(brightnessMirrorController);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index d8e8187..583cfb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import static com.android.systemui.Flags.quickSettingsVisualHapticsLongpress;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -32,6 +33,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.haptics.qs.QSLongPressEffect;
 import com.android.systemui.media.controls.ui.view.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTileView;
@@ -39,7 +41,6 @@
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileViewImpl;
-import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.SplitShadeStateController;
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.animation.DisappearParameters;
@@ -55,6 +56,8 @@
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
+import javax.inject.Provider;
+
 /**
  * Controller for QSPanel views.
  *
@@ -88,7 +91,7 @@
 
     private SplitShadeStateController mSplitShadeStateController;
 
-    private final VibratorHelper mVibratorHelper;
+    private final Provider<QSLongPressEffect> mLongPressEffectProvider;
 
     @VisibleForTesting
     protected final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
@@ -148,7 +151,7 @@
             QSLogger qsLogger,
             DumpManager dumpManager,
             SplitShadeStateController splitShadeStateController,
-            VibratorHelper vibratorHelper
+            Provider<QSLongPressEffect> longPressEffectProvider
     ) {
         super(view);
         mHost = host;
@@ -162,7 +165,7 @@
         mSplitShadeStateController = splitShadeStateController;
         mShouldUseSplitNotificationShade =
                 mSplitShadeStateController.shouldUseSplitNotificationShade(getResources());
-        mVibratorHelper = vibratorHelper;
+        mLongPressEffectProvider = longPressEffectProvider;
     }
 
     @Override
@@ -305,8 +308,14 @@
     }
 
     private void addTile(final QSTile tile, boolean collapsedView) {
+        QSLongPressEffect longPressEffect;
+        if (quickSettingsVisualHapticsLongpress()) {
+            longPressEffect = mLongPressEffectProvider.get();
+        } else {
+            longPressEffect = null;
+        }
         final QSTileViewImpl tileView = new QSTileViewImpl(
-                getContext(), collapsedView, mVibratorHelper);
+                getContext(), collapsedView, longPressEffect);
         final TileRecord r = new TileRecord(tile, tileView);
         // TODO(b/250618218): Remove the QSLogger in QSTileViewImpl once we know the root cause of
         // b/250618218.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 05bb088..6cda740 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -25,6 +25,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.haptics.qs.QSLongPressEffect;
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
 import com.android.systemui.media.controls.ui.view.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
@@ -32,7 +33,6 @@
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.res.R;
-import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.SplitShadeStateController;
 import com.android.systemui.util.leak.RotationUtils;
 
@@ -58,10 +58,11 @@
                     Provider<Boolean> usingCollapsedLandscapeMediaProvider,
             MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
             DumpManager dumpManager, SplitShadeStateController splitShadeStateController,
-            VibratorHelper vibratorHelper
+            Provider<QSLongPressEffect> longPressEffectProvider
     ) {
         super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
-                uiEventLogger, qsLogger, dumpManager, splitShadeStateController, vibratorHelper);
+                uiEventLogger, qsLogger, dumpManager, splitShadeStateController,
+                longPressEffectProvider);
         mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 1d92d78..bb40d3e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -17,7 +17,7 @@
 package com.android.systemui.qs;
 
 import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
@@ -34,12 +34,11 @@
 
     @Inject
     QuickStatusBarHeaderController(QuickStatusBarHeader view,
-            QuickQSPanelController quickQSPanelController,
-            SceneContainerFlags sceneContainerFlags
+            QuickQSPanelController quickQSPanelController
     ) {
         super(view);
         mQuickQSPanelController = quickQSPanelController;
-        mSceneContainerEnabled = sceneContainerFlags.isEnabled();
+        mSceneContainerEnabled = SceneContainerFlag.isEnabled();
     }
     @Override
     protected void onViewAttached() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java
index a01d658..10c8e53 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,124 +16,21 @@
 
 package com.android.systemui.qs;
 
-import android.content.Context;
-import android.database.ContentObserver;
-import android.hardware.display.ColorDisplayManager;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerExecutor;
-import android.provider.Settings;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.CallbackController;
-import com.android.systemui.util.settings.SecureSettings;
 
-import java.util.ArrayList;
-
-import javax.inject.Inject;
-
-/**
- * @hide
- */
-@SysUISingleton
-public class ReduceBrightColorsController implements
+public interface ReduceBrightColorsController extends
         CallbackController<ReduceBrightColorsController.Listener> {
-    private final ColorDisplayManager mManager;
-    private final UserTracker mUserTracker;
-    private UserTracker.Callback mCurrentUserTrackerCallback;
-    private final Handler mHandler;
-    private final ContentObserver mContentObserver;
-    private final SecureSettings mSecureSettings;
-    private final ArrayList<ReduceBrightColorsController.Listener> mListeners = new ArrayList<>();
-
-    @Inject
-    public ReduceBrightColorsController(UserTracker userTracker,
-            @Background Handler handler,
-            ColorDisplayManager colorDisplayManager,
-            SecureSettings secureSettings) {
-        mManager = colorDisplayManager;
-        mUserTracker = userTracker;
-        mHandler = handler;
-        mSecureSettings = secureSettings;
-        mContentObserver = new ContentObserver(mHandler) {
-            @Override
-            public void onChange(boolean selfChange, Uri uri) {
-                super.onChange(selfChange, uri);
-                final String setting = uri == null ? null : uri.getLastPathSegment();
-                synchronized (mListeners) {
-                    if (setting != null && mListeners.size() != 0) {
-                        if (setting.equals(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED)) {
-                            dispatchOnActivated(mManager.isReduceBrightColorsActivated());
-                        }
-                    }
-                }
-            }
-        };
-
-        mCurrentUserTrackerCallback = new UserTracker.Callback() {
-            @Override
-            public void onUserChanged(int newUser, Context userContext) {
-                synchronized (mListeners) {
-                    if (mListeners.size() > 0) {
-                        mSecureSettings.unregisterContentObserver(mContentObserver);
-                        mSecureSettings.registerContentObserverForUser(
-                                Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
-                                false, mContentObserver, newUser);
-                    }
-                }
-            }
-        };
-        mUserTracker.addCallback(mCurrentUserTrackerCallback, new HandlerExecutor(handler));
-    }
-
-    @Override
-    public void addCallback(@NonNull Listener listener) {
-        synchronized (mListeners) {
-            if (!mListeners.contains(listener)) {
-                mListeners.add(listener);
-                if (mListeners.size() == 1) {
-                    mSecureSettings.registerContentObserverForUser(
-                            Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
-                            false, mContentObserver, mUserTracker.getUserId());
-                }
-            }
-        }
-    }
-
-    @Override
-    public void removeCallback(@androidx.annotation.NonNull Listener listener) {
-        synchronized (mListeners) {
-            if (mListeners.remove(listener) && mListeners.size() == 0) {
-                mSecureSettings.unregisterContentObserver(mContentObserver);
-            }
-        }
-    }
 
     /** Returns {@code true} if Reduce Bright Colors is activated */
-    public boolean isReduceBrightColorsActivated() {
-        return mManager.isReduceBrightColorsActivated();
-    }
+    boolean isReduceBrightColorsActivated();
 
     /** Sets the activation state of Reduce Bright Colors */
-    public void setReduceBrightColorsActivated(boolean activated) {
-        mManager.setReduceBrightColorsActivated(activated);
-    }
-
-    private void dispatchOnActivated(boolean activated) {
-        ArrayList<Listener> copy = new ArrayList<>(mListeners);
-        for (Listener l : copy) {
-            l.onActivated(activated);
-        }
-    }
+    void setReduceBrightColorsActivated(boolean activated);
 
     /**
      * Listener invoked whenever the Reduce Bright Colors settings are changed.
      */
-    public interface Listener {
+    interface Listener {
         /**
          * Listener invoked when the activated state changes.
          *
@@ -142,4 +39,4 @@
         default void onActivated(boolean activated) {
         }
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsControllerImpl.java
new file mode 100644
index 0000000..4fc6609
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsControllerImpl.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+/**
+ * @hide
+ */
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.display.ColorDisplayManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+
+@SysUISingleton
+public class ReduceBrightColorsControllerImpl implements
+        ReduceBrightColorsController {
+    private final ColorDisplayManager mManager;
+    private final UserTracker mUserTracker;
+    private UserTracker.Callback mCurrentUserTrackerCallback;
+    private final Handler mHandler;
+    private final ContentObserver mContentObserver;
+    private final SecureSettings mSecureSettings;
+    private final ArrayList<ReduceBrightColorsController.Listener> mListeners = new ArrayList<>();
+
+    @Inject
+    public ReduceBrightColorsControllerImpl(UserTracker userTracker,
+            @Background Handler handler,
+            ColorDisplayManager colorDisplayManager,
+            SecureSettings secureSettings) {
+        mManager = colorDisplayManager;
+        mUserTracker = userTracker;
+        mHandler = handler;
+        mSecureSettings = secureSettings;
+        mContentObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                super.onChange(selfChange, uri);
+                final String setting = uri == null ? null : uri.getLastPathSegment();
+                synchronized (mListeners) {
+                    if (setting != null && mListeners.size() != 0) {
+                        if (setting.equals(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED)) {
+                            dispatchOnActivated(mManager.isReduceBrightColorsActivated());
+                        }
+                    }
+                }
+            }
+        };
+
+        mCurrentUserTrackerCallback = new UserTracker.Callback() {
+            @Override
+            public void onUserChanged(int newUser, Context userContext) {
+                synchronized (mListeners) {
+                    if (mListeners.size() > 0) {
+                        mSecureSettings.unregisterContentObserver(mContentObserver);
+                        mSecureSettings.registerContentObserverForUser(
+                                Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
+                                false, mContentObserver, newUser);
+                    }
+                }
+            }
+        };
+        mUserTracker.addCallback(mCurrentUserTrackerCallback, new HandlerExecutor(handler));
+    }
+
+    @Override
+    public void addCallback(@NonNull Listener listener) {
+        synchronized (mListeners) {
+            if (!mListeners.contains(listener)) {
+                mListeners.add(listener);
+                if (mListeners.size() == 1) {
+                    mSecureSettings.registerContentObserverForUser(
+                            Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
+                            false, mContentObserver, mUserTracker.getUserId());
+                }
+            }
+        }
+    }
+
+    @Override
+    public void removeCallback(@androidx.annotation.NonNull Listener listener) {
+        synchronized (mListeners) {
+            if (mListeners.remove(listener) && mListeners.size() == 0) {
+                mSecureSettings.unregisterContentObserver(mContentObserver);
+            }
+        }
+    }
+
+    @Override
+    public boolean isReduceBrightColorsActivated() {
+        return mManager.isReduceBrightColorsActivated();
+    }
+
+    @Override
+    public void setReduceBrightColorsActivated(boolean activated) {
+        mManager.setReduceBrightColorsActivated(activated);
+    }
+
+    private void dispatchOnActivated(boolean activated) {
+        ArrayList<Listener> copy = new ArrayList<>(mListeners);
+        for (Listener l : copy) {
+            l.onActivated(activated);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 34b1b2d..a222b3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -42,7 +42,7 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -107,8 +107,7 @@
     protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
             QSHost qsHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
             KeyguardStateController keyguardStateController, LightBarController lightBarController,
-            ConfigurationController configurationController, UiEventLogger uiEventLogger,
-            SceneContainerFlags sceneContainerFlags) {
+            ConfigurationController configurationController, UiEventLogger uiEventLogger) {
         super(view);
         mTileQueryHelper = tileQueryHelper;
         mQsHost = qsHost;
@@ -118,7 +117,7 @@
         mLightBarController = lightBarController;
         mConfigurationController = configurationController;
         mUiEventLogger = uiEventLogger;
-        view.setSceneContainerEnabled(sceneContainerFlags.isEnabled());
+        view.setSceneContainerEnabled(SceneContainerFlag.isEnabled());
 
         mToolbar = mView.findViewById(com.android.internal.R.id.action_bar);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 8d3500a..b705a03 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -28,6 +28,7 @@
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.ReduceBrightColorsController;
+import com.android.systemui.qs.ReduceBrightColorsControllerImpl;
 import com.android.systemui.qs.external.QSExternalModule;
 import com.android.systemui.qs.panels.dagger.PanelsModule;
 import com.android.systemui.qs.pipeline.dagger.QSPipelineModule;
@@ -118,4 +119,11 @@
 
     @Binds
     QSSceneAdapter bindsQsSceneInteractor(QSSceneAdapterImpl impl);
+
+    /**
+     * Dims the screen
+     */
+    @Binds
+    ReduceBrightColorsController bindReduceBrightColorsController(
+            ReduceBrightColorsControllerImpl impl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
index 1307296..ee4eeb8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
@@ -18,10 +18,20 @@
 
 import com.android.systemui.qs.panels.data.repository.IconTilesRepository
 import com.android.systemui.qs.panels.data.repository.IconTilesRepositoryImpl
+import com.android.systemui.qs.panels.shared.model.GridLayoutTypeKey
+import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
+import com.android.systemui.qs.panels.ui.compose.GridLayout
+import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
 import dagger.Binds
 import dagger.Module
+import dagger.multibindings.IntoMap
 
 @Module
 interface PanelsModule {
     @Binds fun bindIconTilesRepository(impl: IconTilesRepositoryImpl): IconTilesRepository
+
+    @Binds
+    @IntoMap
+    @GridLayoutTypeKey(InfiniteGridLayoutType::class)
+    fun bindGridLayout(impl: InfiniteGridLayout): GridLayout
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/GridLayoutTypeRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/GridLayoutTypeRepository.kt
new file mode 100644
index 0000000..02dd33e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/GridLayoutTypeRepository.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.shared.model.GridLayoutType
+import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+
+@SysUISingleton
+class GridLayoutTypeRepository @Inject constructor() {
+    val layout: Flow<GridLayoutType> = flowOf(InfiniteGridLayoutType)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt
new file mode 100644
index 0000000..b6be578
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.data.repository.GridLayoutTypeRepository
+import com.android.systemui.qs.panels.shared.model.GridLayoutType
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class GridLayoutTypeInteractor @Inject constructor(repo: GridLayoutTypeRepository) {
+    val layout: Flow<GridLayoutType> = repo.layout
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
index 367c670..1aec193 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
@@ -24,6 +24,6 @@
 
 /** Interactor for retrieving the list of [TileSpec] to be displayed as icons. */
 @SysUISingleton
-class IconTilesInteractor @Inject constructor(private val repo: IconTilesRepository) {
+class IconTilesInteractor @Inject constructor(repo: IconTilesRepository) {
     val iconTilesSpecs: Flow<Set<TileSpec>> = repo.iconTilesSpecs
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutType.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutType.kt
new file mode 100644
index 0000000..23110dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutType.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.shared.model
+
+/**
+ * Grid type for a QS grid layout.
+ *
+ * Used to inject grid layouts with Dagger and the [GridLayoutTypeKey] annotation.
+ */
+interface GridLayoutType
+
+/** Grid type representing a scrollable vertical grid. */
+data object InfiniteGridLayoutType : GridLayoutType
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
new file mode 100644
index 0000000..0dbaaba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/shared/model/GridLayoutTypeKey.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.shared.model
+
+import dagger.MapKey
+import kotlin.reflect.KClass
+
+/**
+ * Dagger map key to associate a [GridLayoutType] with its
+ * [com.android.systemui.qs.panels.ui.compose.GridLayout].
+ */
+@Retention(AnnotationRetention.RUNTIME)
+@MapKey
+annotation class GridLayoutTypeKey(val value: KClass<out GridLayoutType>)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
new file mode 100644
index 0000000..920cbe7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.compose
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
+
+interface GridLayout {
+    @Composable
+    fun TileGrid(
+        tiles: List<TileViewModel>,
+        modifier: Modifier,
+        tile: @Composable (TileViewModel) -> Unit,
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
new file mode 100644
index 0000000..4d0089e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.compose
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.GridItemSpan
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.integerResource
+import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+class InfiniteGridLayout @Inject constructor() : GridLayout {
+
+    @Composable
+    override fun TileGrid(
+        tiles: List<TileViewModel>,
+        modifier: Modifier,
+        tile: @Composable (TileViewModel) -> Unit
+    ) {
+        DisposableEffect(tiles) {
+            val token = Any()
+            tiles.forEach { it.startListening(token) }
+            onDispose { tiles.forEach { it.stopListening(token) } }
+        }
+
+        LazyVerticalGrid(
+            columns =
+                GridCells.Fixed(
+                    integerResource(R.integer.quick_settings_infinite_grid_num_columns)
+                ),
+            verticalArrangement =
+                Arrangement.spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical)),
+            horizontalArrangement =
+                Arrangement.spacedBy(dimensionResource(R.dimen.qs_tile_margin_horizontal)),
+            modifier = modifier
+        ) {
+            tiles.forEach { item(span = { it.span() }) { tile(it) } }
+        }
+    }
+
+    private fun TileViewModel.span(): GridItemSpan =
+        if (iconOnly) {
+            GridItemSpan(1)
+        } else {
+            GridItemSpan(2)
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
new file mode 100644
index 0000000..35f2970
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.compose
+
+import android.graphics.drawable.Animatable
+import android.text.TextUtils
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
+import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.basicMarquee
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.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.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.dimensionResource
+import com.android.compose.theme.colorAttr
+import com.android.systemui.common.shared.model.Icon as IconModel
+import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.qs.panels.ui.viewmodel.TileUiState
+import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.res.R
+import kotlinx.coroutines.delay
+
+@Composable
+fun Tile(
+    tileViewModel: TileViewModel,
+    modifier: Modifier = Modifier,
+) {
+    val state: TileUiState by tileViewModel.state.collectAsState(tileViewModel.currentState)
+    val context = LocalContext.current
+    val horizontalAlignment =
+        if (state.iconOnly) {
+            Alignment.CenterHorizontally
+        } else {
+            Alignment.Start
+        }
+
+    Row(
+        modifier =
+            modifier
+                .fillMaxWidth()
+                .clip(RoundedCornerShape(dimensionResource(R.dimen.qs_corner_radius)))
+                .clickable { tileViewModel.onClick(null) }
+                .background(colorAttr(state.colors.background))
+                .padding(horizontal = dimensionResource(id = R.dimen.qs_label_container_margin)),
+        verticalAlignment = Alignment.CenterVertically,
+        horizontalArrangement =
+            Arrangement.spacedBy(
+                space = dimensionResource(id = R.dimen.qs_label_container_margin),
+                alignment = horizontalAlignment
+            )
+    ) {
+        val icon =
+            remember(state.icon) {
+                state.icon.get().let {
+                    if (it is QSTileImpl.ResourceIcon) {
+                        IconModel.Resource(it.resId, null)
+                    } else {
+                        IconModel.Loaded(it.getDrawable(context), null)
+                    }
+                }
+            }
+        TileIcon(icon, colorAttr(state.colors.icon))
+
+        if (!state.iconOnly) {
+            Column(verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight()) {
+                Text(
+                    state.label.toString(),
+                    color = colorAttr(state.colors.label),
+                    modifier = Modifier.basicMarquee(),
+                )
+                if (!TextUtils.isEmpty(state.secondaryLabel)) {
+                    Text(
+                        state.secondaryLabel.toString(),
+                        color = colorAttr(state.colors.secondaryLabel),
+                        modifier = Modifier.basicMarquee(),
+                    )
+                }
+            }
+        }
+    }
+}
+
+@OptIn(ExperimentalAnimationGraphicsApi::class)
+@Composable
+private fun TileIcon(icon: IconModel, color: Color) {
+    val modifier = Modifier.size(dimensionResource(id = R.dimen.qs_icon_size))
+    val context = LocalContext.current
+    val loadedDrawable =
+        remember(icon, context) {
+            when (icon) {
+                is IconModel.Loaded -> icon.drawable
+                is IconModel.Resource -> AppCompatResources.getDrawable(context, icon.res)
+            }
+        }
+    if (loadedDrawable !is Animatable) {
+        Icon(
+            icon = icon,
+            tint = color,
+            modifier = modifier,
+        )
+    } else if (icon is IconModel.Resource) {
+        val image = AnimatedImageVector.animatedVectorResource(id = icon.res)
+        var atEnd by remember(icon.res) { mutableStateOf(false) }
+        LaunchedEffect(key1 = icon.res) {
+            delay(350)
+            atEnd = true
+        }
+        val painter = rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd)
+        Image(
+            painter = painter,
+            contentDescription = null,
+            colorFilter = ColorFilter.tint(color = color),
+            modifier = modifier
+        )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
new file mode 100644
index 0000000..a528eed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.compose
+
+import androidx.compose.foundation.layout.height
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.dimensionResource
+import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
+import com.android.systemui.res.R
+
+@Composable
+fun TileGrid(viewModel: TileGridViewModel, modifier: Modifier = Modifier) {
+    val gridLayout by viewModel.gridLayout.collectAsState(InfiniteGridLayout())
+    val tiles by viewModel.tileViewModels.collectAsState(emptyList())
+
+    gridLayout.TileGrid(tiles, modifier) {
+        Tile(it, modifier = Modifier.height(dimensionResource(id = R.dimen.qs_tile_height)))
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileColorAttributes.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileColorAttributes.kt
new file mode 100644
index 0000000..1290bf3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileColorAttributes.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import android.service.quicksettings.Tile
+import androidx.annotation.AttrRes
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.res.R
+
+data class TileColorAttributes(
+    @AttrRes val background: Int = 0,
+    @AttrRes val label: Int = 0,
+    @AttrRes val secondaryLabel: Int = 0,
+    @AttrRes val icon: Int = 0,
+)
+
+val ActiveTileColorAttributes =
+    TileColorAttributes(
+        background = R.attr.shadeActive,
+        label = R.attr.onShadeActive,
+        secondaryLabel = R.attr.onShadeActiveVariant,
+        icon = R.attr.onShadeActive,
+    )
+
+val InactiveTileColorAttributes =
+    TileColorAttributes(
+        background = R.attr.shadeInactive,
+        label = R.attr.onShadeInactive,
+        secondaryLabel = R.attr.onShadeInactiveVariant,
+        icon = R.attr.onShadeInactiveVariant,
+    )
+
+val UnavailableTileColorAttributes =
+    TileColorAttributes(
+        background = R.attr.shadeDisabled,
+        label = R.attr.outline,
+        secondaryLabel = R.attr.outline,
+        icon = R.attr.outline,
+    )
+
+fun QSTile.State.colors(): TileColorAttributes =
+    when (state) {
+        Tile.STATE_UNAVAILABLE -> UnavailableTileColorAttributes
+        Tile.STATE_ACTIVE -> ActiveTileColorAttributes
+        Tile.STATE_INACTIVE -> InactiveTileColorAttributes
+        else -> TileColorAttributes()
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
new file mode 100644
index 0000000..fc13460
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.domain.interactor.GridLayoutTypeInteractor
+import com.android.systemui.qs.panels.domain.interactor.IconTilesInteractor
+import com.android.systemui.qs.panels.shared.model.GridLayoutType
+import com.android.systemui.qs.panels.ui.compose.GridLayout
+import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
+import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+
+@SysUISingleton
+class TileGridViewModel
+@Inject
+constructor(
+    gridLayoutTypeInteractor: GridLayoutTypeInteractor,
+    gridLayoutMap: Map<Class<out GridLayoutType>, @JvmSuppressWildcards GridLayout>,
+    tilesInteractor: CurrentTilesInteractor,
+    iconTilesInteractor: IconTilesInteractor,
+) {
+    val gridLayout: Flow<GridLayout> =
+        gridLayoutTypeInteractor.layout.map {
+            gridLayoutMap[it::class.java] ?: InfiniteGridLayout()
+        }
+    val tileViewModels: Flow<List<TileViewModel>> =
+        combine(tilesInteractor.currentTiles, iconTilesInteractor.iconTilesSpecs) {
+            tiles,
+            iconTilesSpecs ->
+            tiles.map { TileViewModel(it.tile, iconTilesSpecs.contains(it.spec)) }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
new file mode 100644
index 0000000..f4b7255
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.plugins.qs.QSTile
+import java.util.function.Supplier
+
+data class TileUiState(
+    val label: CharSequence,
+    val secondaryLabel: CharSequence,
+    val colors: TileColorAttributes,
+    val icon: Supplier<QSTile.Icon>,
+    val iconOnly: Boolean,
+)
+
+fun QSTile.State.toUiState(iconOnly: Boolean): TileUiState {
+    return TileUiState(
+        label ?: "",
+        secondaryLabel ?: "",
+        colors(),
+        icon?.let { Supplier { icon } } ?: iconSupplier,
+        iconOnly,
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt
new file mode 100644
index 0000000..08e9119
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileViewModel.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import android.view.View
+import android.view.View.OnLongClickListener
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+
+class TileViewModel(private val tile: QSTile, val iconOnly: Boolean = false) :
+    OnLongClickListener, View.OnClickListener {
+    val state: Flow<TileUiState> =
+        conflatedCallbackFlow {
+                val callback = QSTile.Callback { trySend(it.copy()) }
+
+                tile.addCallback(callback)
+
+                awaitClose { tile.removeCallback(callback) }
+            }
+            .onStart { emit(tile.state) }
+            .map { it.toUiState(iconOnly) }
+            .distinctUntilChanged()
+
+    val currentState: TileUiState
+        get() = tile.state.toUiState(iconOnly)
+
+    override fun onClick(view: View?) {
+        tile.click(view)
+    }
+
+    override fun onLongClick(view: View?): Boolean {
+        tile.longClick(view)
+        return true
+    }
+
+    fun startListening(token: Any) = tile.setListening(token, true)
+
+    fun stopListening(token: Any) = tile.setListening(token, false)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt
index 267e2b7..9c1b857 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddable.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.pipeline.domain.autoaddable
 
+import android.view.accessibility.Flags
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.qs.ReduceBrightColorsController
 import com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE
@@ -58,7 +59,9 @@
 
     override val autoAddTracking
         get() =
-            if (available) {
+            if (Flags.a11yQsShortcut()) {
+                AutoAddTracking.Disabled
+            } else if (available) {
                 super.autoAddTracking
             } else {
                 AutoAddTracking.Disabled
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 3004485..40cf4a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -62,15 +62,15 @@
 import com.android.systemui.qs.logging.QSLogger
 import com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH
 import com.android.systemui.res.R
-import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.util.children
+import kotlinx.coroutines.DisposableHandle
 import java.util.Objects
 
 private const val TAG = "QSTileViewImpl"
 open class QSTileViewImpl @JvmOverloads constructor(
     context: Context,
     private val collapsed: Boolean = false,
-    private val vibratorHelper: VibratorHelper? = null,
+    private val longPressEffect: QSLongPressEffect? = null,
 ) : QSTileView(context), HeightOverrideable, LaunchableView {
 
     companion object {
@@ -180,15 +180,14 @@
     private val locInScreen = IntArray(2)
 
     /** Visuo-haptic long-press effects */
-    private var longPressEffect: QSLongPressEffect? = null
-    private val longPressEffectViewBinder = QSLongPressEffectViewBinder()
     private var initialLongPressProperties: QSLongPressProperties? = null
     private var finalLongPressProperties: QSLongPressProperties? = null
     private val colorEvaluator = ArgbEvaluator.getInstance()
-    val hasLongPressEffect: Boolean
-        get() = longPressEffect != null
-    @VisibleForTesting val isLongPressEffectBound: Boolean
-        get() = longPressEffectViewBinder.isBound
+    val isLongPressEffectInitialized: Boolean
+        get() = longPressEffect?.hasInitialized == true
+    private var longPressEffectHandle: DisposableHandle? = null
+    val isLongPressEffectBound: Boolean
+        get() = longPressEffectHandle != null
 
     init {
         val typedValue = TypedValue()
@@ -325,6 +324,13 @@
     }
 
     private fun updateHeight() {
+        // TODO(b/332900989): Find a more robust way of resetting the tile if not reset by the
+        //  launch animation.
+        if (scaleX != 1f || scaleY != 1f) {
+            // The launch animation of a long-press effect did not reset the long-press effect so
+            // we must do it here
+            resetLongPressEffectProperties()
+        }
         val actualHeight = if (heightOverride != HeightOverrideable.NO_OVERRIDE) {
             heightOverride
         } else {
@@ -614,25 +620,28 @@
         lastIconTint = icon.getColor(state)
 
         // Long-press effects
-        if (quickSettingsVisualHapticsLongpress()){
-            if (state.handlesLongClick && maybeCreateAndInitializeLongPressEffect()) {
-                // set the valid long-press effect as the touch listener
-                showRippleEffect = false
-                setOnTouchListener(longPressEffect)
-                if (!longPressEffectViewBinder.isBound) {
-                    longPressEffectViewBinder.bind(this, state.spec, longPressEffect)
-                }
-            } else {
-                // Long-press effects might have been enabled before but the new state does not
-                // handle a long-press. In this case, we go back to the behaviour of a regular tile
-                // and clean-up the resources
-                longPressEffectViewBinder.dispose()
-                showRippleEffect = isClickable
-                setOnTouchListener(null)
-                longPressEffect = null
-                initialLongPressProperties = null
-                finalLongPressProperties = null
+        if (state.handlesLongClick &&
+            longPressEffect?.initializeEffect(longPressEffectDuration) == true) {
+            // bind the long-press effect and set it as the touch listener
+            if (!isLongPressEffectBound) {
+                longPressEffectHandle =
+                    QSLongPressEffectViewBinder.bind(
+                        this,
+                        longPressEffect,
+                        state.spec,
+                    )
             }
+            showRippleEffect = false
+            initializeLongPressProperties()
+        } else {
+            // Long-press effects might have been enabled before but the new state does not
+            // handle a long-press. In this case, we go back to the behaviour of a regular tile
+            // and clean-up the resources
+            setOnTouchListener(null)
+            unbindLongPressEffect()
+            showRippleEffect = isClickable
+            initialLongPressProperties = null
+            finalLongPressProperties = null
         }
     }
 
@@ -821,10 +830,15 @@
         changeCornerRadius(newRadius)
     }
 
+    private fun unbindLongPressEffect() {
+        longPressEffectHandle?.dispose()
+        longPressEffectHandle = null
+    }
+
     private fun interpolateFloat(fraction: Float, start: Float, end: Float): Float =
         start + fraction * (end - start)
 
-    private fun resetLongPressEffectProperties() {
+    fun resetLongPressEffectProperties() {
         scaleY = 1f
         scaleX = 1f
         for (child in children) {
@@ -842,27 +856,6 @@
         icon.setTint(icon.mIcon as ImageView, lastIconTint)
     }
 
-    private fun maybeCreateAndInitializeLongPressEffect(): Boolean {
-        // Don't setup the effect if the long-press duration is invalid
-        val effectDuration = longPressEffectDuration
-        if (effectDuration <= 0) {
-            longPressEffect = null
-            return false
-        }
-
-        initializeLongPressProperties()
-        if (longPressEffect == null) {
-            longPressEffect =
-                QSLongPressEffect(
-                    vibratorHelper,
-                    effectDuration,
-                )
-        } else {
-            longPressEffect?.resetWithDuration(effectDuration)
-        }
-        return true
-    }
-
     private fun initializeLongPressProperties() {
         initialLongPressProperties =
             QSLongPressProperties(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index b0707db..6eae32a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -39,6 +39,7 @@
 import com.android.settingslib.Utils;
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogViewModel;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
@@ -51,7 +52,6 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogViewModel;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
index 2f8fe42..3eeb2a3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -25,6 +25,7 @@
 import android.provider.Settings;
 import android.safetycenter.SafetyCenterManager;
 import android.service.quicksettings.Tile;
+import android.text.TextUtils;
 import android.view.View;
 import android.widget.Switch;
 
@@ -127,7 +128,7 @@
         } else {
             state.secondaryLabel = mContext.getString(R.string.quick_settings_camera_mic_available);
         }
-        state.contentDescription = state.label;
+        state.contentDescription = TextUtils.concat(state.label, ", ", state.secondaryLabel);
         state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt
index 6c9a8a4..5122e1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider
 import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
 import com.android.systemui.qs.tiles.viewmodel.QSTileViewModelAdapter
+import com.android.systemui.qs.tiles.viewmodel.StubQSTileViewModel
 import javax.inject.Inject
 import javax.inject.Provider
 
@@ -57,7 +58,9 @@
         val viewModel: QSTileViewModel =
             when (val spec = TileSpec.create(tileSpec)) {
                 is TileSpec.CustomTileSpec -> createCustomTileViewModel(spec)
-                is TileSpec.PlatformTileSpec -> tileMap[tileSpec]?.get()
+                // when using the stub, we default to old tile rather than adding the stub
+                is TileSpec.PlatformTileSpec ->
+                    tileMap[tileSpec]?.get()?.takeIf { it !is StubQSTileViewModel }
                 is TileSpec.Invalid -> null
             }
                 ?: return null
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index b866dda..19b45d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -25,6 +25,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -37,8 +38,12 @@
 import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.systemui.res.R;
+import com.android.wifi.flags.Flags;
 import com.android.wifitrackerlib.WifiEntry;
 
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.Job;
+
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -50,6 +55,7 @@
     private static final String TAG = "InternetAdapter";
 
     private final InternetDialogController mInternetDialogController;
+    private final CoroutineScope mCoroutineScope;
     @Nullable
     private List<WifiEntry> mWifiEntries;
     @VisibleForTesting
@@ -60,8 +66,9 @@
     protected View mHolderView;
     protected Context mContext;
 
-    public InternetAdapter(InternetDialogController controller) {
+    public InternetAdapter(InternetDialogController controller, CoroutineScope coroutineScope) {
         mInternetDialogController = controller;
+        mCoroutineScope = coroutineScope;
     }
 
     @Override
@@ -70,7 +77,7 @@
         mContext = viewGroup.getContext();
         mHolderView = LayoutInflater.from(mContext).inflate(R.layout.internet_list_item,
                 viewGroup, false);
-        return new InternetViewHolder(mHolderView, mInternetDialogController);
+        return new InternetViewHolder(mHolderView, mInternetDialogController, mCoroutineScope);
     }
 
     @Override
@@ -131,11 +138,16 @@
         final ImageView mWifiEndIcon;
         final Context mContext;
         final InternetDialogController mInternetDialogController;
+        final CoroutineScope mCoroutineScope;
+        @Nullable
+        private Job mJob;
 
-        InternetViewHolder(View view, InternetDialogController internetDialogController) {
+        InternetViewHolder(View view, InternetDialogController internetDialogController,
+                CoroutineScope coroutineScope) {
             super(view);
             mContext = view.getContext();
             mInternetDialogController = internetDialogController;
+            mCoroutineScope = coroutineScope;
             mContainerLayout = view.requireViewById(R.id.internet_container);
             mWifiListLayout = view.requireViewById(R.id.wifi_list);
             mWifiNetworkLayout = view.requireViewById(R.id.wifi_network_layout);
@@ -176,6 +188,24 @@
         }
 
         void onWifiClick(@NonNull WifiEntry wifiEntry, @NonNull View view) {
+            if (Flags.androidVWifiApi() && wifiEntry.getSecurityTypes().contains(
+                    WifiEntry.SECURITY_WEP)) {
+                if (mJob == null) {
+                    mJob = WifiUtils.checkWepAllowed(mContext, mCoroutineScope, wifiEntry.getSsid(),
+                            WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, intent -> {
+                                mInternetDialogController.startActivity(intent, view);
+                                return null;
+                            }, () -> {
+                                wifiConnect(wifiEntry, view);
+                                return null;
+                            });
+                }
+                return;
+            }
+            wifiConnect(wifiEntry, view);
+        }
+
+        void wifiConnect(@NonNull WifiEntry wifiEntry, @NonNull View view) {
             if (wifiEntry.shouldEditBeforeConnect()) {
                 final Intent intent = WifiUtils.getWifiDialogIntent(wifiEntry.getKey(),
                         true /* connectForCaller */);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index a531ee6..d5b05ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -747,7 +747,7 @@
         return summary;
     }
 
-    private void startActivity(Intent intent, View view) {
+    void startActivity(Intent intent, View view) {
         ActivityTransitionAnimator.Controller controller =
                 mDialogTransitionAnimator.createActivityTransitionController(view);
 
@@ -1348,15 +1348,12 @@
         mDefaultDataSubId = defaultDataSubId;
     }
 
-    boolean mayLaunchShareWifiSettings(WifiEntry wifiEntry) {
+    boolean mayLaunchShareWifiSettings(WifiEntry wifiEntry, View view) {
         Intent intent = getConfiguratorQrCodeGeneratorIntentOrNull(wifiEntry);
         if (intent == null) {
             return false;
         }
-        if (mCallback != null) {
-            mCallback.dismissDialog();
-        }
-        mActivityStarter.startActivity(intent, false /* dismissShade */);
+        startActivity(intent, view);
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
index 52cf4ec..1a881b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
@@ -68,13 +68,15 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.wifitrackerlib.WifiEntry;
 
-import java.util.List;
-import java.util.concurrent.Executor;
-
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
 import dagger.assisted.AssistedInject;
 
+import kotlinx.coroutines.CoroutineScope;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
 /**
  * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks.
  */
@@ -165,7 +167,8 @@
         InternetDialogDelegate create(
                 @Assisted(ABOVE_STATUS_BAR) boolean aboveStatusBar,
                 @Assisted(CAN_CONFIG_MOBILE_DATA) boolean canConfigMobileData,
-                @Assisted(CAN_CONFIG_WIFI) boolean canConfigWifi);
+                @Assisted(CAN_CONFIG_WIFI) boolean canConfigWifi,
+                @Assisted CoroutineScope coroutineScope);
     }
 
     @AssistedInject
@@ -176,6 +179,7 @@
             @Assisted(ABOVE_STATUS_BAR) boolean canConfigMobileData,
             @Assisted(CAN_CONFIG_MOBILE_DATA) boolean canConfigWifi,
             @Assisted(CAN_CONFIG_WIFI) boolean aboveStatusBar,
+            @Assisted CoroutineScope coroutineScope,
             UiEventLogger uiEventLogger,
             DialogTransitionAnimator dialogTransitionAnimator,
             @Main Handler handler,
@@ -202,7 +206,7 @@
 
         mUiEventLogger = uiEventLogger;
         mDialogTransitionAnimator = dialogTransitionAnimator;
-        mAdapter = new InternetAdapter(mInternetDialogController);
+        mAdapter = new InternetAdapter(mInternetDialogController, coroutineScope);
     }
 
     @Override
@@ -391,7 +395,7 @@
                 });
         mDoneButton.setOnClickListener(v -> dialog.dismiss());
         mShareWifiButton.setOnClickListener(v -> {
-            if (mInternetDialogController.mayLaunchShareWifiSettings(mConnectedWifiEntry)) {
+            if (mInternetDialogController.mayLaunchShareWifiSettings(mConnectedWifiEntry, v)) {
                 mUiEventLogger.log(InternetDialogEvent.SHARE_WIFI_QS_BUTTON_CLICKED);
             }
         });
@@ -415,7 +419,7 @@
     }
 
     private void setMobileDataLayout(SystemUIDialog dialog, boolean activeNetworkIsCellular,
-                                     boolean isCarrierNetworkActive) {
+            boolean isCarrierNetworkActive) {
         boolean isNetworkConnected = activeNetworkIsCellular || isCarrierNetworkActive;
         // 1. Mobile network should be gone if airplane mode ON or the list of active
         //    subscriptionId is null.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
index 2a177c7..5aef950 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
@@ -21,26 +21,35 @@
 import com.android.systemui.animation.DialogCuj
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.cancel
 
 private const val TAG = "InternetDialogFactory"
 private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
 
-/**
- * Factory to create [InternetDialogDelegate] objects.
- */
+/** Factory to create [InternetDialogDelegate] objects. */
 @SysUISingleton
-class InternetDialogManager @Inject constructor(
+class InternetDialogManager
+@Inject
+constructor(
     private val dialogTransitionAnimator: DialogTransitionAnimator,
-    private val dialogFactory: InternetDialogDelegate.Factory
+    private val dialogFactory: InternetDialogDelegate.Factory,
+    @Background private val bgDispatcher: CoroutineDispatcher,
 ) {
+    private lateinit var coroutineScope: CoroutineScope
     companion object {
         private const val INTERACTION_JANK_TAG = "internet"
         var dialog: SystemUIDialog? = null
     }
 
-    /** Creates a [InternetDialogDelegate]. The dialog will be animated from [view] if it is not null. */
+    /**
+     * Creates a [InternetDialogDelegate]. The dialog will be animated from [view] if it is not
+     * null.
+     */
     fun create(
         aboveStatusBar: Boolean,
         canConfigMobileData: Boolean,
@@ -53,16 +62,21 @@
             }
             return
         } else {
-            dialog = dialogFactory.create(
-                    aboveStatusBar, canConfigMobileData, canConfigWifi).createDialog()
+            coroutineScope = CoroutineScope(bgDispatcher)
+            dialog =
+                dialogFactory
+                    .create(aboveStatusBar, canConfigMobileData, canConfigWifi, coroutineScope)
+                    .createDialog()
             if (view != null) {
                 dialogTransitionAnimator.showFromView(
-                        dialog!!, view,
+                    dialog!!,
+                    view,
                     animateBackgroundBoundsChange = true,
-                    cuj = DialogCuj(
-                        InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
-                        INTERACTION_JANK_TAG
-                    )
+                    cuj =
+                        DialogCuj(
+                            InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+                            INTERACTION_JANK_TAG
+                        )
                 )
             } else {
                 dialog!!.show()
@@ -74,6 +88,9 @@
         if (DEBUG) {
             Log.d(TAG, "destroyDialog")
         }
+        if (dialog != null) {
+            coroutineScope.cancel()
+        }
         dialog = null
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnInteractor.kt
deleted file mode 100644
index 59fc81c..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnInteractor.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.util.Log
-import com.android.systemui.dagger.SysUISingleton
-import javax.inject.Inject
-
-/** Interactor class responsible for interacting with the Bluetooth Auto-On feature. */
-@SysUISingleton
-class BluetoothAutoOnInteractor
-@Inject
-constructor(
-    private val bluetoothAutoOnRepository: BluetoothAutoOnRepository,
-) {
-
-    val isEnabled = bluetoothAutoOnRepository.isAutoOn
-
-    /** Checks if the auto on feature is supported. */
-    suspend fun isAutoOnSupported(): Boolean = bluetoothAutoOnRepository.isAutoOnSupported()
-
-    /**
-     * Sets enabled or disabled based on the provided value.
-     *
-     * @param value `true` to enable the feature, `false` to disable it.
-     */
-    suspend fun setEnabled(value: Boolean) {
-        if (!isAutoOnSupported()) {
-            Log.e(TAG, "Trying to set toggle value while feature not available.")
-        } else {
-            bluetoothAutoOnRepository.setAutoOn(value)
-        }
-    }
-
-    companion object {
-        private const val TAG = "BluetoothAutoOnInteractor"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnRepository.kt
deleted file mode 100644
index 9ee582a..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnRepository.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.util.Log
-import com.android.settingslib.bluetooth.BluetoothCallback
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-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 javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.withContext
-
-/**
- * Repository class responsible for managing the Bluetooth Auto-On feature settings for the current
- * user.
- */
-@SysUISingleton
-class BluetoothAutoOnRepository
-@Inject
-constructor(
-    localBluetoothManager: LocalBluetoothManager?,
-    private val bluetoothAdapter: BluetoothAdapter?,
-    @Application private val coroutineScope: CoroutineScope,
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
-) {
-
-    // Flow representing the auto on state for the current user
-    internal val isAutoOn: Flow<Boolean> =
-        localBluetoothManager?.eventManager?.let { eventManager ->
-            conflatedCallbackFlow {
-                    val listener =
-                        object : BluetoothCallback {
-                            override fun onAutoOnStateChanged(autoOnState: Int) {
-                                super.onAutoOnStateChanged(autoOnState)
-                                if (
-                                    autoOnState == BluetoothAdapter.AUTO_ON_STATE_ENABLED ||
-                                        autoOnState == BluetoothAdapter.AUTO_ON_STATE_DISABLED
-                                ) {
-                                    trySendWithFailureLogging(
-                                        autoOnState == BluetoothAdapter.AUTO_ON_STATE_ENABLED,
-                                        TAG,
-                                        "onAutoOnStateChanged"
-                                    )
-                                }
-                            }
-                        }
-                    eventManager.registerCallback(listener)
-                    awaitClose { eventManager.unregisterCallback(listener) }
-                }
-                .onStart { emit(isAutoOnEnabled()) }
-                .flowOn(backgroundDispatcher)
-                .stateIn(
-                    coroutineScope,
-                    SharingStarted.WhileSubscribed(replayExpirationMillis = 0),
-                    initialValue = false
-                )
-        }
-            ?: flowOf(false)
-
-    /**
-     * Checks if the auto on feature is supported for the current user.
-     *
-     * @throws Exception if an error occurs while checking auto-on support.
-     */
-    suspend fun isAutoOnSupported(): Boolean =
-        withContext(backgroundDispatcher) {
-            try {
-                bluetoothAdapter?.isAutoOnSupported ?: false
-            } catch (e: Exception) {
-                // Server could throw TimeoutException, InterruptedException or ExecutionException
-                Log.e(TAG, "Error calling isAutoOnSupported", e)
-                false
-            }
-        }
-
-    /** Sets the Bluetooth Auto-On for the current user. */
-    suspend fun setAutoOn(value: Boolean) {
-        withContext(backgroundDispatcher) {
-            try {
-                bluetoothAdapter?.setAutoOnEnabled(value)
-            } catch (e: Exception) {
-                // Server could throw IllegalStateException, TimeoutException, InterruptedException
-                // or ExecutionException
-                Log.e(TAG, "Error calling setAutoOnEnabled", e)
-            }
-        }
-    }
-
-    private suspend fun isAutoOnEnabled() =
-        withContext(backgroundDispatcher) {
-            try {
-                bluetoothAdapter?.isAutoOnEnabled ?: false
-            } catch (e: Exception) {
-                // Server could throw IllegalStateException, TimeoutException, InterruptedException
-                // or ExecutionException
-                Log.e(TAG, "Error calling isAutoOnEnabled", e)
-                false
-            }
-        }
-
-    private companion object {
-        const val TAG = "BluetoothAutoOnRepository"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothStateInteractor.kt
deleted file mode 100644
index 9c63a30..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothStateInteractor.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.bluetooth.BluetoothAdapter.STATE_OFF
-import android.bluetooth.BluetoothAdapter.STATE_ON
-import com.android.settingslib.bluetooth.BluetoothCallback
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.stateIn
-
-/** Holds business logic for the Bluetooth Dialog's bluetooth and device connection state */
-@SysUISingleton
-internal class BluetoothStateInteractor
-@Inject
-constructor(
-    private val localBluetoothManager: LocalBluetoothManager?,
-    private val logger: BluetoothTileDialogLogger,
-    @Application private val coroutineScope: CoroutineScope,
-) {
-
-    internal val bluetoothStateUpdate: StateFlow<Boolean?> =
-        conflatedCallbackFlow {
-                val listener =
-                    object : BluetoothCallback {
-                        override fun onBluetoothStateChanged(bluetoothState: Int) {
-                            if (bluetoothState == STATE_ON || bluetoothState == STATE_OFF) {
-                                super.onBluetoothStateChanged(bluetoothState)
-                                logger.logBluetoothState(
-                                    BluetoothStateStage.BLUETOOTH_STATE_CHANGE_RECEIVED,
-                                    BluetoothAdapter.nameForState(bluetoothState)
-                                )
-                                trySendWithFailureLogging(
-                                    bluetoothState == STATE_ON,
-                                    TAG,
-                                    "onBluetoothStateChanged"
-                                )
-                            }
-                        }
-                    }
-                localBluetoothManager?.eventManager?.registerCallback(listener)
-                awaitClose { localBluetoothManager?.eventManager?.unregisterCallback(listener) }
-            }
-            .stateIn(
-                coroutineScope,
-                SharingStarted.WhileSubscribed(replayExpirationMillis = 0),
-                initialValue = null
-            )
-
-    internal var isBluetoothEnabled: Boolean
-        get() = localBluetoothManager?.bluetoothAdapter?.isEnabled == true
-        set(value) {
-            if (isBluetoothEnabled != value) {
-                localBluetoothManager?.bluetoothAdapter?.apply {
-                    if (value) enable() else disable()
-                    logger.logBluetoothState(
-                        BluetoothStateStage.BLUETOOTH_STATE_VALUE_SET,
-                        value.toString()
-                    )
-                }
-            }
-        }
-
-    companion object {
-        private const val TAG = "BtStateInteractor"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
deleted file mode 100644
index a8d9e78..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.View.AccessibilityDelegate
-import android.view.View.GONE
-import android.view.View.INVISIBLE
-import android.view.View.VISIBLE
-import android.view.ViewGroup
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import android.view.accessibility.AccessibilityNodeInfo
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
-import android.widget.ImageView
-import android.widget.ProgressBar
-import android.widget.Switch
-import android.widget.TextView
-import androidx.annotation.StringRes
-import androidx.recyclerview.widget.AsyncListDiffer
-import androidx.recyclerview.widget.DiffUtil
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import com.android.internal.logging.UiEventLogger
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.util.time.SystemClock
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.isActive
-import kotlinx.coroutines.withContext
-
-/** Dialog for showing active, connected and saved bluetooth devices. */
-class BluetoothTileDialogDelegate
-@AssistedInject
-internal constructor(
-    @Assisted private val initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
-    @Assisted private val cachedContentHeight: Int,
-    @Assisted private val bluetoothToggleInitialValue: Boolean,
-    @Assisted private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
-    @Assisted private val dismissListener: Runnable,
-    @Main private val mainDispatcher: CoroutineDispatcher,
-    private val systemClock: SystemClock,
-    private val uiEventLogger: UiEventLogger,
-    private val logger: BluetoothTileDialogLogger,
-    private val systemuiDialogFactory: SystemUIDialog.Factory,
-) : SystemUIDialog.Delegate {
-
-    private val mutableBluetoothStateToggle: MutableStateFlow<Boolean> =
-        MutableStateFlow(bluetoothToggleInitialValue)
-    internal val bluetoothStateToggle
-        get() = mutableBluetoothStateToggle.asStateFlow()
-
-    private val mutableBluetoothAutoOnToggle: MutableStateFlow<Boolean?> = MutableStateFlow(null)
-    internal val bluetoothAutoOnToggle
-        get() = mutableBluetoothAutoOnToggle.asStateFlow()
-
-    private val mutableDeviceItemClick: MutableSharedFlow<DeviceItem> =
-        MutableSharedFlow(extraBufferCapacity = 1)
-    internal val deviceItemClick
-        get() = mutableDeviceItemClick.asSharedFlow()
-
-    private val mutableContentHeight: MutableSharedFlow<Int> =
-        MutableSharedFlow(extraBufferCapacity = 1)
-    internal val contentHeight
-        get() = mutableContentHeight.asSharedFlow()
-
-    private val deviceItemAdapter: Adapter = Adapter(bluetoothTileDialogCallback)
-
-    private var lastUiUpdateMs: Long = -1
-
-    private var lastItemRow: Int = -1
-
-    @AssistedFactory
-    internal interface Factory {
-        fun create(
-            initialUiProperties: BluetoothTileDialogViewModel.UiProperties,
-            cachedContentHeight: Int,
-            bluetoothEnabled: Boolean,
-            dialogCallback: BluetoothTileDialogCallback,
-            dimissListener: Runnable
-        ): BluetoothTileDialogDelegate
-    }
-
-    override fun createDialog(): SystemUIDialog {
-        return systemuiDialogFactory.create(this)
-    }
-
-    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
-        SystemUIDialog.registerDismissListener(dialog, dismissListener)
-        uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_TILE_DIALOG_SHOWN)
-        val context = dialog.context
-
-        LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null).apply {
-            accessibilityPaneTitle = context.getText(R.string.accessibility_desc_quick_settings)
-            dialog.setContentView(this)
-        }
-
-        setupToggle(dialog)
-        setupRecyclerView(dialog)
-
-        getSubtitleTextView(dialog).text = context.getString(initialUiProperties.subTitleResId)
-        dialog.requireViewById<View>(R.id.done_button).setOnClickListener { dialog.dismiss() }
-        getSeeAllButton(dialog).setOnClickListener {
-            bluetoothTileDialogCallback.onSeeAllClicked(it)
-        }
-        getPairNewDeviceButton(dialog).setOnClickListener {
-            bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
-        }
-        getScrollViewContent(dialog).apply {
-            minimumHeight =
-                resources.getDimensionPixelSize(initialUiProperties.scrollViewMinHeightResId)
-            layoutParams.height = maxOf(cachedContentHeight, minimumHeight)
-        }
-    }
-
-    override fun onStart(dialog: SystemUIDialog) {
-        lastUiUpdateMs = systemClock.elapsedRealtime()
-    }
-
-    override fun onStop(dialog: SystemUIDialog) {
-        mutableContentHeight.tryEmit(getScrollViewContent(dialog).measuredHeight)
-    }
-
-    internal suspend fun animateProgressBar(dialog: SystemUIDialog, animate: Boolean) {
-        withContext(mainDispatcher) {
-            if (animate) {
-                showProgressBar(dialog)
-            } else {
-                delay(PROGRESS_BAR_ANIMATION_DURATION_MS)
-                hideProgressBar(dialog)
-            }
-        }
-    }
-
-    internal suspend fun onDeviceItemUpdated(
-        dialog: SystemUIDialog,
-        deviceItem: List<DeviceItem>,
-        showSeeAll: Boolean,
-        showPairNewDevice: Boolean
-    ) {
-        withContext(mainDispatcher) {
-            val start = systemClock.elapsedRealtime()
-            val itemRow = deviceItem.size + showSeeAll.toInt() + showPairNewDevice.toInt()
-            // If not the first load, add a slight delay for smoother dialog height change
-            if (itemRow != lastItemRow && lastItemRow != -1) {
-                delay(MIN_HEIGHT_CHANGE_INTERVAL_MS - (start - lastUiUpdateMs))
-            }
-            if (isActive) {
-                deviceItemAdapter.refreshDeviceItemList(deviceItem) {
-                    getSeeAllButton(dialog).visibility = if (showSeeAll) VISIBLE else GONE
-                    getPairNewDeviceButton(dialog).visibility =
-                        if (showPairNewDevice) VISIBLE else GONE
-                    // Update the height after data is updated
-                    getScrollViewContent(dialog).layoutParams.height = WRAP_CONTENT
-                    lastUiUpdateMs = systemClock.elapsedRealtime()
-                    lastItemRow = itemRow
-                    logger.logDeviceUiUpdate(lastUiUpdateMs - start)
-                }
-            }
-        }
-    }
-
-    internal fun onBluetoothStateUpdated(
-        dialog: SystemUIDialog,
-        isEnabled: Boolean,
-        uiProperties: BluetoothTileDialogViewModel.UiProperties
-    ) {
-        getToggleView(dialog).apply {
-            isChecked = isEnabled
-            setEnabled(true)
-            alpha = ENABLED_ALPHA
-        }
-        getSubtitleTextView(dialog).text = dialog.context.getString(uiProperties.subTitleResId)
-        getAutoOnToggleView(dialog).visibility = uiProperties.autoOnToggleVisibility
-    }
-
-    internal fun onBluetoothAutoOnUpdated(
-        dialog: SystemUIDialog,
-        isEnabled: Boolean,
-        @StringRes infoResId: Int
-    ) {
-        getAutoOnToggle(dialog).apply {
-            isChecked = isEnabled
-            setEnabled(true)
-            alpha = ENABLED_ALPHA
-        }
-        getAutoOnToggleInfoTextView(dialog).text = dialog.context.getString(infoResId)
-    }
-
-    private fun setupToggle(dialog: SystemUIDialog) {
-        val toggleView = getToggleView(dialog)
-        toggleView.isChecked = bluetoothToggleInitialValue
-        toggleView.setOnCheckedChangeListener { view, isChecked ->
-            mutableBluetoothStateToggle.value = isChecked
-            view.apply {
-                isEnabled = false
-                alpha = DISABLED_ALPHA
-            }
-            logger.logBluetoothState(BluetoothStateStage.USER_TOGGLED, isChecked.toString())
-            uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_TOGGLE_CLICKED)
-        }
-
-        getAutoOnToggleView(dialog).visibility = initialUiProperties.autoOnToggleVisibility
-        getAutoOnToggle(dialog).setOnCheckedChangeListener { view, isChecked ->
-            mutableBluetoothAutoOnToggle.value = isChecked
-            view.apply {
-                isEnabled = false
-                alpha = DISABLED_ALPHA
-            }
-            uiEventLogger.log(BluetoothTileDialogUiEvent.BLUETOOTH_AUTO_ON_TOGGLE_CLICKED)
-        }
-    }
-
-    private fun getToggleView(dialog: SystemUIDialog): Switch {
-        return dialog.requireViewById(R.id.bluetooth_toggle)
-    }
-
-    private fun getSubtitleTextView(dialog: SystemUIDialog): TextView {
-        return dialog.requireViewById(R.id.bluetooth_tile_dialog_subtitle)
-    }
-
-    private fun getSeeAllButton(dialog: SystemUIDialog): View {
-        return dialog.requireViewById(R.id.see_all_button)
-    }
-
-    private fun getPairNewDeviceButton(dialog: SystemUIDialog): View {
-        return dialog.requireViewById(R.id.pair_new_device_button)
-    }
-
-    private fun getDeviceListView(dialog: SystemUIDialog): RecyclerView {
-        return dialog.requireViewById(R.id.device_list)
-    }
-
-    private fun getAutoOnToggle(dialog: SystemUIDialog): Switch {
-        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle)
-    }
-
-    private fun getAutoOnToggleView(dialog: SystemUIDialog): View {
-        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_layout)
-    }
-
-    private fun getAutoOnToggleInfoTextView(dialog: SystemUIDialog): TextView {
-        return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_info_text)
-    }
-
-    private fun getProgressBarAnimation(dialog: SystemUIDialog): ProgressBar {
-        return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
-    }
-
-    private fun getProgressBarBackground(dialog: SystemUIDialog): View {
-        return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
-    }
-
-    private fun getScrollViewContent(dialog: SystemUIDialog): View {
-        return dialog.requireViewById(R.id.scroll_view)
-    }
-
-    private fun setupRecyclerView(dialog: SystemUIDialog) {
-        getDeviceListView(dialog).apply {
-            layoutManager = LinearLayoutManager(dialog.context)
-            adapter = deviceItemAdapter
-        }
-    }
-
-    private fun showProgressBar(dialog: SystemUIDialog) {
-        val progressBarAnimation = getProgressBarAnimation(dialog)
-        val progressBarBackground = getProgressBarBackground(dialog)
-        if (progressBarAnimation.visibility != VISIBLE) {
-            progressBarAnimation.visibility = VISIBLE
-            progressBarBackground.visibility = INVISIBLE
-        }
-    }
-
-    private fun hideProgressBar(dialog: SystemUIDialog) {
-        val progressBarAnimation = getProgressBarAnimation(dialog)
-        val progressBarBackground = getProgressBarBackground(dialog)
-        if (progressBarAnimation.visibility != INVISIBLE) {
-            progressBarAnimation.visibility = INVISIBLE
-            progressBarBackground.visibility = VISIBLE
-        }
-    }
-
-    internal inner class Adapter(private val onClickCallback: BluetoothTileDialogCallback) :
-        RecyclerView.Adapter<Adapter.DeviceItemViewHolder>() {
-
-        private val diffUtilCallback =
-            object : DiffUtil.ItemCallback<DeviceItem>() {
-                override fun areItemsTheSame(
-                    deviceItem1: DeviceItem,
-                    deviceItem2: DeviceItem
-                ): Boolean {
-                    return deviceItem1.cachedBluetoothDevice == deviceItem2.cachedBluetoothDevice
-                }
-
-                override fun areContentsTheSame(
-                    deviceItem1: DeviceItem,
-                    deviceItem2: DeviceItem
-                ): Boolean {
-                    return deviceItem1.type == deviceItem2.type &&
-                        deviceItem1.cachedBluetoothDevice == deviceItem2.cachedBluetoothDevice &&
-                        deviceItem1.deviceName == deviceItem2.deviceName &&
-                        deviceItem1.connectionSummary == deviceItem2.connectionSummary &&
-                        // Ignored the icon drawable
-                        deviceItem1.iconWithDescription?.second ==
-                            deviceItem2.iconWithDescription?.second &&
-                        deviceItem1.background == deviceItem2.background &&
-                        deviceItem1.isEnabled == deviceItem2.isEnabled &&
-                        deviceItem1.actionAccessibilityLabel == deviceItem2.actionAccessibilityLabel
-                }
-            }
-
-        private val asyncListDiffer = AsyncListDiffer(this, diffUtilCallback)
-
-        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeviceItemViewHolder {
-            val view =
-                LayoutInflater.from(parent.context)
-                    .inflate(R.layout.bluetooth_device_item, parent, false)
-            return DeviceItemViewHolder(view)
-        }
-
-        override fun getItemCount() = asyncListDiffer.currentList.size
-
-        override fun onBindViewHolder(holder: DeviceItemViewHolder, position: Int) {
-            val item = getItem(position)
-            holder.bind(item, onClickCallback)
-        }
-
-        internal fun getItem(position: Int) = asyncListDiffer.currentList[position]
-
-        internal fun refreshDeviceItemList(updated: List<DeviceItem>, callback: () -> Unit) {
-            asyncListDiffer.submitList(updated, callback)
-        }
-
-        internal inner class DeviceItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
-            private val container = view.requireViewById<View>(R.id.bluetooth_device_row)
-            private val nameView = view.requireViewById<TextView>(R.id.bluetooth_device_name)
-            private val summaryView = view.requireViewById<TextView>(R.id.bluetooth_device_summary)
-            private val iconView = view.requireViewById<ImageView>(R.id.bluetooth_device_icon)
-            private val gearView = view.requireViewById<View>(R.id.gear_icon)
-
-            internal fun bind(
-                item: DeviceItem,
-                deviceItemOnClickCallback: BluetoothTileDialogCallback
-            ) {
-                container.apply {
-                    isEnabled = item.isEnabled
-                    background = item.background?.let { context.getDrawable(it) }
-                    setOnClickListener {
-                        mutableDeviceItemClick.tryEmit(item)
-                        uiEventLogger.log(BluetoothTileDialogUiEvent.DEVICE_CLICKED)
-                    }
-                    accessibilityDelegate =
-                        object : AccessibilityDelegate() {
-                            override fun onInitializeAccessibilityNodeInfo(
-                                host: View,
-                                info: AccessibilityNodeInfo
-                            ) {
-                                super.onInitializeAccessibilityNodeInfo(host, info)
-                                info.addAction(
-                                    AccessibilityAction(
-                                        AccessibilityAction.ACTION_CLICK.id,
-                                        item.actionAccessibilityLabel
-                                    )
-                                )
-                            }
-                        }
-                }
-                nameView.text = item.deviceName
-                summaryView.text = item.connectionSummary
-                iconView.apply {
-                    item.iconWithDescription?.let {
-                        setImageDrawable(it.first)
-                        contentDescription = it.second
-                    }
-                }
-                gearView.setOnClickListener {
-                    deviceItemOnClickCallback.onDeviceItemGearClicked(item, it)
-                }
-            }
-        }
-    }
-
-    internal companion object {
-        const val MIN_HEIGHT_CHANGE_INTERVAL_MS = 800L
-        const val MAX_DEVICE_ITEM_ENTRY = 3
-        const val ACTION_BLUETOOTH_DEVICE_DETAILS =
-            "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"
-        const val ACTION_PREVIOUSLY_CONNECTED_DEVICE =
-            "com.android.settings.PREVIOUSLY_CONNECTED_DEVICE"
-        const val ACTION_PAIR_NEW_DEVICE = "android.settings.BLUETOOTH_PAIRING_SETTINGS"
-        const val DISABLED_ALPHA = 0.3f
-        const val ENABLED_ALPHA = 1f
-        const val PROGRESS_BAR_ANIMATION_DURATION_MS = 1500L
-
-        private fun Boolean.toInt(): Int {
-            return if (this) 1 else 0
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogLogger.kt
deleted file mode 100644
index 5d18dc1..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogLogger.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.core.LogLevel.DEBUG
-import com.android.systemui.log.dagger.BluetoothTileDialogLog
-import javax.inject.Inject
-
-private const val TAG = "BluetoothTileDialogLog"
-
-enum class BluetoothStateStage {
-    USER_TOGGLED,
-    BLUETOOTH_STATE_VALUE_SET,
-    BLUETOOTH_STATE_CHANGE_RECEIVED
-}
-
-enum class DeviceFetchTrigger {
-    FIRST_LOAD,
-    BLUETOOTH_STATE_CHANGE_RECEIVED,
-    BLUETOOTH_CALLBACK_RECEIVED
-}
-
-enum class JobStatus {
-    FINISHED,
-    CANCELLED
-}
-
-class BluetoothTileDialogLogger
-@Inject
-constructor(@BluetoothTileDialogLog private val logBuffer: LogBuffer) {
-
-    fun logBluetoothState(stage: BluetoothStateStage, state: String) =
-        logBuffer.log(
-            TAG,
-            DEBUG,
-            {
-                str1 = stage.toString()
-                str2 = state
-            },
-            { "BluetoothState. stage=$str1 state=$str2" }
-        )
-
-    fun logDeviceClick(address: String, type: DeviceItemType) =
-        logBuffer.log(
-            TAG,
-            DEBUG,
-            {
-                str1 = address
-                str2 = type.toString()
-            },
-            { "DeviceClick. address=$str1 type=$str2" }
-        )
-
-    fun logActiveDeviceChanged(address: String?, profileId: Int) =
-        logBuffer.log(
-            TAG,
-            DEBUG,
-            {
-                str1 = address
-                int1 = profileId
-            },
-            { "ActiveDeviceChanged. address=$str1 profileId=$int1" }
-        )
-
-    fun logProfileConnectionStateChanged(address: String, state: String, profileId: Int) =
-        logBuffer.log(
-            TAG,
-            DEBUG,
-            {
-                str1 = address
-                str2 = state
-                int1 = profileId
-            },
-            { "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" }
-        )
-
-    fun logDeviceFetch(status: JobStatus, trigger: DeviceFetchTrigger, duration: Long) =
-        logBuffer.log(
-            TAG,
-            DEBUG,
-            {
-                str1 = status.toString()
-                str2 = trigger.toString()
-                long1 = duration
-            },
-            { "DeviceFetch. status=$str1 trigger=$str2 duration=$long1" }
-        )
-
-    fun logDeviceUiUpdate(duration: Long) =
-        logBuffer.log(TAG, DEBUG, { long1 = duration }, { "DeviceUiUpdate. duration=$long1" })
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogRepository.kt
deleted file mode 100644
index ea51bee..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogRepository.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.dagger.SysUISingleton
-import javax.inject.Inject
-
-/** Repository to get CachedBluetoothDevices for the Bluetooth Dialog. */
-@SysUISingleton
-internal class BluetoothTileDialogRepository
-@Inject
-constructor(
-    private val localBluetoothManager: LocalBluetoothManager?,
-    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
-) {
-    internal val cachedDevices: Collection<CachedBluetoothDevice>
-        get() {
-            return if (
-                localBluetoothManager == null ||
-                    bluetoothAdapter == null ||
-                    !bluetoothAdapter.isEnabled
-            ) {
-                emptyList()
-            } else {
-                localBluetoothManager.cachedDeviceManager.cachedDevicesCopy
-            }
-        }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogUiEvent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogUiEvent.kt
deleted file mode 100644
index cd52e0d..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogUiEvent.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import com.android.internal.logging.UiEvent
-import com.android.internal.logging.UiEventLogger
-
-/** UI Events for the bluetooth tile dialog. */
-enum class BluetoothTileDialogUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum {
-    @UiEvent(doc = "The bluetooth tile dialog is shown") BLUETOOTH_TILE_DIALOG_SHOWN(1493),
-    @UiEvent(doc = "The master toggle is clicked") BLUETOOTH_TOGGLE_CLICKED(1494),
-    @UiEvent(doc = "Pair new device is clicked") PAIR_NEW_DEVICE_CLICKED(1495),
-    @UiEvent(doc = "See all is clicked") SEE_ALL_CLICKED(1496),
-    @UiEvent(doc = "Gear icon clicked") DEVICE_GEAR_CLICKED(1497),
-    @UiEvent(doc = "Device clicked") DEVICE_CLICKED(1498),
-    @UiEvent(doc = "Connected device clicked to active") CONNECTED_DEVICE_SET_ACTIVE(1499),
-    @UiEvent(doc = "Saved clicked to connect") SAVED_DEVICE_CONNECT(1500),
-    @UiEvent(doc = "Active device clicked to disconnect") ACTIVE_DEVICE_DISCONNECT(1507),
-    @UiEvent(doc = "Connected other device clicked to disconnect")
-    CONNECTED_OTHER_DEVICE_DISCONNECT(1508),
-    @UiEvent(doc = "The auto on toggle is clicked") BLUETOOTH_AUTO_ON_TOGGLE_CLICKED(1617);
-
-    override fun getId() = metricId
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
deleted file mode 100644
index fd624d2..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.content.Intent
-import android.content.SharedPreferences
-import android.os.Bundle
-import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
-import android.view.ViewGroup
-import androidx.annotation.DimenRes
-import androidx.annotation.StringRes
-import androidx.annotation.VisibleForTesting
-import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.logging.UiEventLogger
-import com.android.systemui.Prefs
-import com.android.systemui.animation.DialogCuj
-import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogDelegate.Companion.MAX_DEVICE_ITEM_ENTRY
-import com.android.systemui.res.R
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.channels.produce
-import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-
-/** ViewModel for Bluetooth Dialog after clicking on the Bluetooth QS tile. */
-@SysUISingleton
-internal class BluetoothTileDialogViewModel
-@Inject
-constructor(
-    private val deviceItemInteractor: DeviceItemInteractor,
-    private val bluetoothStateInteractor: BluetoothStateInteractor,
-    private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
-    private val dialogTransitionAnimator: DialogTransitionAnimator,
-    private val activityStarter: ActivityStarter,
-    private val uiEventLogger: UiEventLogger,
-    @Application private val coroutineScope: CoroutineScope,
-    @Main private val mainDispatcher: CoroutineDispatcher,
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
-    @Main private val sharedPreferences: SharedPreferences,
-    private val bluetoothDialogDelegateFactory: BluetoothTileDialogDelegate.Factory,
-) : BluetoothTileDialogCallback {
-
-    private var job: Job? = null
-
-    /**
-     * Shows the dialog.
-     *
-     * @param view The view from which the dialog is shown.
-     */
-    @kotlinx.coroutines.ExperimentalCoroutinesApi
-    fun showDialog(view: View?) {
-        cancelJob()
-
-        job =
-            coroutineScope.launch(mainDispatcher) {
-                var updateDeviceItemJob: Job?
-                var updateDialogUiJob: Job? = null
-                val dialogDelegate = createBluetoothTileDialog()
-                val dialog = dialogDelegate.createDialog()
-                val context = dialog.context
-
-                view?.let {
-                    dialogTransitionAnimator.showFromView(
-                        dialog,
-                        it,
-                        animateBackgroundBoundsChange = true,
-                        cuj =
-                            DialogCuj(
-                                InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
-                                INTERACTION_JANK_TAG
-                            )
-                    )
-                }
-                    ?: dialog.show()
-
-                updateDeviceItemJob = launch {
-                    deviceItemInteractor.updateDeviceItems(context, DeviceFetchTrigger.FIRST_LOAD)
-                }
-
-                // deviceItemUpdate is emitted when device item list is done fetching, update UI and
-                // stop the progress bar.
-                deviceItemInteractor.deviceItemUpdate
-                    .onEach {
-                        updateDialogUiJob?.cancel()
-                        updateDialogUiJob = launch {
-                            dialogDelegate.apply {
-                                onDeviceItemUpdated(
-                                    dialog,
-                                    it.take(MAX_DEVICE_ITEM_ENTRY),
-                                    showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
-                                    showPairNewDevice = bluetoothStateInteractor.isBluetoothEnabled
-                                )
-                                animateProgressBar(dialog, false)
-                            }
-                        }
-                    }
-                    .launchIn(this)
-
-                // deviceItemUpdateRequest is emitted when a bluetooth callback is called, re-fetch
-                // the device item list and animiate the progress bar.
-                deviceItemInteractor.deviceItemUpdateRequest
-                    .onEach {
-                        dialogDelegate.animateProgressBar(dialog, true)
-                        updateDeviceItemJob?.cancel()
-                        updateDeviceItemJob = launch {
-                            deviceItemInteractor.updateDeviceItems(
-                                context,
-                                DeviceFetchTrigger.BLUETOOTH_CALLBACK_RECEIVED
-                            )
-                        }
-                    }
-                    .launchIn(this)
-
-                // bluetoothStateUpdate is emitted when bluetooth on/off state is changed, re-fetch
-                // the device item list.
-                bluetoothStateInteractor.bluetoothStateUpdate
-                    .filterNotNull()
-                    .onEach {
-                        dialogDelegate.onBluetoothStateUpdated(
-                            dialog,
-                            it,
-                            UiProperties.build(it, isAutoOnToggleFeatureAvailable())
-                        )
-                        updateDeviceItemJob?.cancel()
-                        updateDeviceItemJob = launch {
-                            deviceItemInteractor.updateDeviceItems(
-                                context,
-                                DeviceFetchTrigger.BLUETOOTH_STATE_CHANGE_RECEIVED
-                            )
-                        }
-                    }
-                    .launchIn(this)
-
-                // bluetoothStateToggle is emitted when user toggles the bluetooth state switch,
-                // send the new value to the bluetoothStateInteractor and animate the progress bar.
-                dialogDelegate.bluetoothStateToggle
-                    .onEach {
-                        dialogDelegate.animateProgressBar(dialog, true)
-                        bluetoothStateInteractor.isBluetoothEnabled = it
-                    }
-                    .launchIn(this)
-
-                // deviceItemClick is emitted when user clicked on a device item.
-                dialogDelegate.deviceItemClick
-                    .onEach { deviceItemInteractor.updateDeviceItemOnClick(it) }
-                    .launchIn(this)
-
-                // contentHeight is emitted when the dialog is dismissed.
-                dialogDelegate.contentHeight
-                    .onEach {
-                        withContext(backgroundDispatcher) {
-                            sharedPreferences.edit().putInt(CONTENT_HEIGHT_PREF_KEY, it).apply()
-                        }
-                    }
-                    .launchIn(this)
-
-                if (isAutoOnToggleFeatureAvailable()) {
-                    // bluetoothAutoOnUpdate is emitted when bluetooth auto on on/off state is
-                    // changed.
-                    bluetoothAutoOnInteractor.isEnabled
-                        .onEach {
-                            dialogDelegate.onBluetoothAutoOnUpdated(
-                                dialog,
-                                it,
-                                if (it) R.string.turn_on_bluetooth_auto_info_enabled
-                                else R.string.turn_on_bluetooth_auto_info_disabled
-                            )
-                        }
-                        .launchIn(this)
-
-                    // bluetoothAutoOnToggle is emitted when user toggles the bluetooth auto on
-                    // switch, send the new value to the bluetoothAutoOnInteractor.
-                    dialogDelegate.bluetoothAutoOnToggle
-                        .filterNotNull()
-                        .onEach { bluetoothAutoOnInteractor.setEnabled(it) }
-                        .launchIn(this)
-                }
-
-                produce<Unit> { awaitClose { dialog.cancel() } }
-            }
-    }
-
-    private suspend fun createBluetoothTileDialog(): BluetoothTileDialogDelegate {
-        val cachedContentHeight =
-            withContext(backgroundDispatcher) {
-                sharedPreferences.getInt(
-                    CONTENT_HEIGHT_PREF_KEY,
-                    ViewGroup.LayoutParams.WRAP_CONTENT
-                )
-            }
-
-        return bluetoothDialogDelegateFactory.create(
-            UiProperties.build(
-                bluetoothStateInteractor.isBluetoothEnabled,
-                isAutoOnToggleFeatureAvailable()
-            ),
-            cachedContentHeight,
-            bluetoothStateInteractor.isBluetoothEnabled,
-            this@BluetoothTileDialogViewModel,
-            { cancelJob() }
-        )
-    }
-
-    override fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View) {
-        uiEventLogger.log(BluetoothTileDialogUiEvent.DEVICE_GEAR_CLICKED)
-        val intent =
-            Intent(ACTION_BLUETOOTH_DEVICE_DETAILS).apply {
-                putExtra(
-                    ":settings:show_fragment_args",
-                    Bundle().apply {
-                        putString("device_address", deviceItem.cachedBluetoothDevice.address)
-                    }
-                )
-            }
-        startSettingsActivity(intent, view)
-    }
-
-    override fun onSeeAllClicked(view: View) {
-        uiEventLogger.log(BluetoothTileDialogUiEvent.SEE_ALL_CLICKED)
-        startSettingsActivity(Intent(ACTION_PREVIOUSLY_CONNECTED_DEVICE), view)
-    }
-
-    override fun onPairNewDeviceClicked(view: View) {
-        uiEventLogger.log(BluetoothTileDialogUiEvent.PAIR_NEW_DEVICE_CLICKED)
-        startSettingsActivity(Intent(ACTION_PAIR_NEW_DEVICE), view)
-    }
-
-    private fun cancelJob() {
-        job?.cancel()
-        job = null
-    }
-
-    private fun startSettingsActivity(intent: Intent, view: View) {
-        if (job?.isActive == true) {
-            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
-            activityStarter.postStartActivityDismissingKeyguard(
-                intent,
-                0,
-                dialogTransitionAnimator.createActivityTransitionController(view)
-            )
-        }
-    }
-
-    @VisibleForTesting
-    internal suspend fun isAutoOnToggleFeatureAvailable() =
-        bluetoothAutoOnInteractor.isAutoOnSupported()
-
-    companion object {
-        private const val INTERACTION_JANK_TAG = "bluetooth_tile_dialog"
-        private const val CONTENT_HEIGHT_PREF_KEY = Prefs.Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT
-        private fun getSubtitleResId(isBluetoothEnabled: Boolean) =
-            if (isBluetoothEnabled) R.string.quick_settings_bluetooth_tile_subtitle
-            else R.string.bt_is_off
-    }
-
-    internal data class UiProperties(
-        @StringRes val subTitleResId: Int,
-        val autoOnToggleVisibility: Int,
-        @DimenRes val scrollViewMinHeightResId: Int,
-    ) {
-        companion object {
-            internal fun build(
-                isBluetoothEnabled: Boolean,
-                isAutoOnToggleFeatureAvailable: Boolean
-            ) =
-                UiProperties(
-                    subTitleResId = getSubtitleResId(isBluetoothEnabled),
-                    autoOnToggleVisibility =
-                        if (isAutoOnToggleFeatureAvailable && !isBluetoothEnabled) VISIBLE
-                        else GONE,
-                    scrollViewMinHeightResId =
-                        if (isAutoOnToggleFeatureAvailable)
-                            R.dimen.bluetooth_dialog_scroll_view_min_height_with_auto_on
-                        else R.dimen.bluetooth_dialog_scroll_view_min_height
-                )
-        }
-    }
-}
-
-interface BluetoothTileDialogCallback {
-    fun onDeviceItemGearClicked(deviceItem: DeviceItem, view: View)
-    fun onSeeAllClicked(view: View)
-    fun onPairNewDeviceClicked(view: View)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItem.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItem.kt
deleted file mode 100644
index 1c621b8..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItem.kt
+++ /dev/null
@@ -1,54 +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.
- */
-
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.graphics.drawable.Drawable
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-
-enum class DeviceItemType {
-    ACTIVE_MEDIA_BLUETOOTH_DEVICE,
-    AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
-    CONNECTED_BLUETOOTH_DEVICE,
-    SAVED_BLUETOOTH_DEVICE,
-}
-
-data class DeviceItem(
-    val type: DeviceItemType,
-    val cachedBluetoothDevice: CachedBluetoothDevice,
-    val deviceName: String = "",
-    val connectionSummary: String = "",
-    val iconWithDescription: Pair<Drawable, String>? = null,
-    val background: Int? = null,
-    var isEnabled: Boolean = true,
-    var actionAccessibilityLabel: String = "",
-)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactory.kt
deleted file mode 100644
index 56ba079..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactory.kt
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothDevice
-import android.content.Context
-import android.media.AudioManager
-import com.android.settingslib.bluetooth.BluetoothUtils
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.flags.Flags
-import com.android.systemui.res.R
-
-private val backgroundOn = R.drawable.settingslib_switch_bar_bg_on
-private val backgroundOff = R.drawable.bluetooth_tile_dialog_bg_off
-private val backgroundOffBusy = R.drawable.bluetooth_tile_dialog_bg_off_busy
-private val connected = R.string.quick_settings_bluetooth_device_connected
-private val saved = R.string.quick_settings_bluetooth_device_saved
-private val actionAccessibilityLabelActivate =
-    R.string.accessibility_quick_settings_bluetooth_device_tap_to_activate
-private val actionAccessibilityLabelDisconnect =
-    R.string.accessibility_quick_settings_bluetooth_device_tap_to_disconnect
-
-/** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */
-internal abstract class DeviceItemFactory {
-    abstract fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean
-
-    abstract fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem
-}
-
-internal open class ActiveMediaDeviceItemFactory : DeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
-            BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager)
-    }
-
-    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
-        return DeviceItem(
-            type = DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE,
-            cachedBluetoothDevice = cachedDevice,
-            deviceName = cachedDevice.name,
-            connectionSummary = cachedDevice.connectionSummary ?: "",
-            iconWithDescription =
-                BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p ->
-                    Pair(p.first, p.second)
-                },
-            background = backgroundOn,
-            isEnabled = !cachedDevice.isBusy,
-            actionAccessibilityLabel = context.getString(actionAccessibilityLabelDisconnect),
-        )
-    }
-}
-
-internal class ActiveHearingDeviceItemFactory : ActiveMediaDeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
-            BluetoothUtils.isAvailableHearingDevice(cachedDevice)
-    }
-}
-
-internal open class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return !BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
-            BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager)
-    }
-
-    // TODO(b/298124674): move create() to the abstract class to reduce duplicate code
-    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
-        return DeviceItem(
-            type = DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
-            cachedBluetoothDevice = cachedDevice,
-            deviceName = cachedDevice.name,
-            connectionSummary = cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
-                    ?: context.getString(connected),
-            iconWithDescription =
-                BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p ->
-                    Pair(p.first, p.second)
-                },
-            background = if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff,
-            isEnabled = !cachedDevice.isBusy,
-            actionAccessibilityLabel = context.getString(actionAccessibilityLabelActivate),
-        )
-    }
-}
-
-internal class AvailableHearingDeviceItemFactory : ActiveMediaDeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return !BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
-            BluetoothUtils.isAvailableHearingDevice(cachedDevice)
-    }
-}
-
-internal class ConnectedDeviceItemFactory : DeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
-            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
-                context,
-                cachedDevice.getDevice()
-            ) && BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager)
-        } else {
-            BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager)
-        }
-    }
-
-    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
-        return DeviceItem(
-            type = DeviceItemType.CONNECTED_BLUETOOTH_DEVICE,
-            cachedBluetoothDevice = cachedDevice,
-            deviceName = cachedDevice.name,
-            connectionSummary = cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
-                    ?: context.getString(connected),
-            iconWithDescription =
-                BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p ->
-                    Pair(p.first, p.second)
-                },
-            background = if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff,
-            isEnabled = !cachedDevice.isBusy,
-            actionAccessibilityLabel = context.getString(actionAccessibilityLabelDisconnect),
-        )
-    }
-}
-
-internal open class SavedDeviceItemFactory : DeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
-            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
-                context,
-                cachedDevice.getDevice()
-            ) && cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected
-        } else {
-            cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected
-        }
-    }
-
-    override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
-        return DeviceItem(
-            type = DeviceItemType.SAVED_BLUETOOTH_DEVICE,
-            cachedBluetoothDevice = cachedDevice,
-            deviceName = cachedDevice.name,
-            connectionSummary = cachedDevice.connectionSummary.takeUnless { it.isNullOrEmpty() }
-                    ?: context.getString(saved),
-            iconWithDescription =
-                BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).let { p ->
-                    Pair(p.first, p.second)
-                },
-            background = if (cachedDevice.isBusy) backgroundOffBusy else backgroundOff,
-            isEnabled = !cachedDevice.isBusy,
-            actionAccessibilityLabel = context.getString(actionAccessibilityLabelActivate),
-        )
-    }
-}
-
-internal class SavedHearingDeviceItemFactory : SavedDeviceItemFactory() {
-    override fun isFilterMatched(
-        context: Context,
-        cachedDevice: CachedBluetoothDevice,
-        audioManager: AudioManager?
-    ): Boolean {
-        return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
-            !BluetoothUtils.isExclusivelyManagedBluetoothDevice(
-                context,
-                cachedDevice.getDevice()
-            ) &&
-                cachedDevice.isHearingAidDevice &&
-                cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
-                !cachedDevice.isConnected
-        } else {
-            cachedDevice.isHearingAidDevice &&
-                cachedDevice.bondState == BluetoothDevice.BOND_BONDED &&
-                !cachedDevice.isConnected
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractor.kt
deleted file mode 100644
index fce25ec..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractor.kt
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.bluetooth.BluetoothDevice
-import android.content.Context
-import android.media.AudioManager
-import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.bluetooth.BluetoothCallback
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-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.util.time.SystemClock
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.flow.shareIn
-import kotlinx.coroutines.isActive
-import kotlinx.coroutines.withContext
-
-/** Holds business logic for the Bluetooth Dialog after clicking on the Bluetooth QS tile. */
-@SysUISingleton
-internal class DeviceItemInteractor
-@Inject
-constructor(
-    private val bluetoothTileDialogRepository: BluetoothTileDialogRepository,
-    private val audioManager: AudioManager,
-    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter(),
-    private val localBluetoothManager: LocalBluetoothManager?,
-    private val systemClock: SystemClock,
-    private val uiEventLogger: UiEventLogger,
-    private val logger: BluetoothTileDialogLogger,
-    @Application private val coroutineScope: CoroutineScope,
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
-) {
-
-    private val mutableDeviceItemUpdate: MutableSharedFlow<List<DeviceItem>> =
-        MutableSharedFlow(extraBufferCapacity = 1)
-    internal val deviceItemUpdate
-        get() = mutableDeviceItemUpdate.asSharedFlow()
-
-    internal val deviceItemUpdateRequest: SharedFlow<Unit> =
-        conflatedCallbackFlow {
-                val listener =
-                    object : BluetoothCallback {
-                        override fun onActiveDeviceChanged(
-                            activeDevice: CachedBluetoothDevice?,
-                            bluetoothProfile: Int
-                        ) {
-                            super.onActiveDeviceChanged(activeDevice, bluetoothProfile)
-                            logger.logActiveDeviceChanged(activeDevice?.address, bluetoothProfile)
-                            trySendWithFailureLogging(Unit, TAG, "onActiveDeviceChanged")
-                        }
-
-                        override fun onProfileConnectionStateChanged(
-                            cachedDevice: CachedBluetoothDevice,
-                            state: Int,
-                            bluetoothProfile: Int
-                        ) {
-                            super.onProfileConnectionStateChanged(
-                                cachedDevice,
-                                state,
-                                bluetoothProfile
-                            )
-                            logger.logProfileConnectionStateChanged(
-                                cachedDevice.address,
-                                state.toString(),
-                                bluetoothProfile
-                            )
-                            trySendWithFailureLogging(Unit, TAG, "onProfileConnectionStateChanged")
-                        }
-
-                        override fun onAclConnectionStateChanged(
-                            cachedDevice: CachedBluetoothDevice,
-                            state: Int
-                        ) {
-                            super.onAclConnectionStateChanged(cachedDevice, state)
-                            // Listen only when a device is disconnecting
-                            if (state == 0) {
-                                trySendWithFailureLogging(Unit, TAG, "onAclConnectionStateChanged")
-                            }
-                        }
-                    }
-                localBluetoothManager?.eventManager?.registerCallback(listener)
-                awaitClose { localBluetoothManager?.eventManager?.unregisterCallback(listener) }
-            }
-            .shareIn(coroutineScope, SharingStarted.WhileSubscribed(replayExpirationMillis = 0))
-
-    private var deviceItemFactoryList: List<DeviceItemFactory> =
-        listOf(
-            ActiveMediaDeviceItemFactory(),
-            AvailableMediaDeviceItemFactory(),
-            ConnectedDeviceItemFactory(),
-            SavedDeviceItemFactory()
-        )
-
-    private var displayPriority: List<DeviceItemType> =
-        listOf(
-            DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE,
-            DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
-            DeviceItemType.CONNECTED_BLUETOOTH_DEVICE,
-            DeviceItemType.SAVED_BLUETOOTH_DEVICE,
-        )
-
-    internal suspend fun updateDeviceItems(context: Context, trigger: DeviceFetchTrigger) {
-        withContext(backgroundDispatcher) {
-            val start = systemClock.elapsedRealtime()
-            val deviceItems =
-                bluetoothTileDialogRepository.cachedDevices
-                    .mapNotNull { cachedDevice ->
-                        deviceItemFactoryList
-                            .firstOrNull { it.isFilterMatched(context, cachedDevice, audioManager) }
-                            ?.create(context, cachedDevice)
-                    }
-                    .sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices)
-            // Only emit when the job is not cancelled
-            if (isActive) {
-                mutableDeviceItemUpdate.tryEmit(deviceItems)
-                logger.logDeviceFetch(
-                    JobStatus.FINISHED,
-                    trigger,
-                    systemClock.elapsedRealtime() - start
-                )
-            } else {
-                logger.logDeviceFetch(
-                    JobStatus.CANCELLED,
-                    trigger,
-                    systemClock.elapsedRealtime() - start
-                )
-            }
-        }
-    }
-
-    private fun List<DeviceItem>.sort(
-        displayPriority: List<DeviceItemType>,
-        mostRecentlyConnectedDevices: List<BluetoothDevice>?
-    ): List<DeviceItem> {
-        return this.sortedWith(
-            compareBy<DeviceItem> { displayPriority.indexOf(it.type) }
-                .thenBy {
-                    mostRecentlyConnectedDevices?.indexOf(it.cachedBluetoothDevice.device) ?: 0
-                }
-        )
-    }
-
-    internal suspend fun updateDeviceItemOnClick(deviceItem: DeviceItem) {
-        withContext(backgroundDispatcher) {
-            logger.logDeviceClick(deviceItem.cachedBluetoothDevice.address, deviceItem.type)
-
-            deviceItem.cachedBluetoothDevice.apply {
-                when (deviceItem.type) {
-                    DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE -> {
-                        disconnect()
-                        uiEventLogger.log(BluetoothTileDialogUiEvent.ACTIVE_DEVICE_DISCONNECT)
-                    }
-                    DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> {
-                        setActive()
-                        uiEventLogger.log(BluetoothTileDialogUiEvent.CONNECTED_DEVICE_SET_ACTIVE)
-                    }
-                    DeviceItemType.CONNECTED_BLUETOOTH_DEVICE -> {
-                        disconnect()
-                        uiEventLogger.log(
-                            BluetoothTileDialogUiEvent.CONNECTED_OTHER_DEVICE_DISCONNECT
-                        )
-                    }
-                    DeviceItemType.SAVED_BLUETOOTH_DEVICE -> {
-                        connect()
-                        uiEventLogger.log(BluetoothTileDialogUiEvent.SAVED_DEVICE_CONNECT)
-                    }
-                }
-            }
-        }
-    }
-
-    internal fun setDeviceItemFactoryListForTesting(list: List<DeviceItemFactory>) {
-        deviceItemFactoryList = list
-    }
-
-    internal fun setDisplayPriorityForTesting(list: List<DeviceItemType>) {
-        displayPriority = list
-    }
-
-    companion object {
-        private const val TAG = "DeviceItemInteractor"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractor.kt
new file mode 100644
index 0000000..98fd561
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileDataInteractor.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor
+
+import android.os.UserHandle
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.ReduceBrightColorsController
+import com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.android.systemui.util.kotlin.isEnabled
+import javax.inject.Inject
+import javax.inject.Named
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+
+/** Observes reduce bright colors state changes providing the [ReduceBrightColorsTileModel]. */
+class ReduceBrightColorsTileDataInteractor
+@Inject
+constructor(
+    @Background private val bgCoroutineContext: CoroutineContext,
+    @Named(RBC_AVAILABLE) private val isAvailable: Boolean,
+    private val reduceBrightColorsController: ReduceBrightColorsController,
+) : QSTileDataInteractor<ReduceBrightColorsTileModel> {
+
+    override fun tileData(
+        user: UserHandle,
+        triggers: Flow<DataUpdateTrigger>
+    ): Flow<ReduceBrightColorsTileModel> {
+        return reduceBrightColorsController
+            .isEnabled()
+            .distinctUntilChanged()
+            .map { ReduceBrightColorsTileModel(it) }
+            .flowOn(bgCoroutineContext)
+    }
+    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(isAvailable)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
new file mode 100644
index 0000000..762f863
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/interactor/ReduceBrightColorsTileUserActionInteractor.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.domain.interactor
+
+import android.content.Intent
+import android.provider.Settings
+import com.android.systemui.qs.ReduceBrightColorsController
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
+import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import javax.inject.Inject
+
+/** Handles reduce bright colors tile clicks. */
+class ReduceBrightColorsTileUserActionInteractor
+@Inject
+constructor(
+    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
+    private val reduceBrightColorsController: ReduceBrightColorsController,
+) : QSTileUserActionInteractor<ReduceBrightColorsTileModel> {
+
+    override suspend fun handleInput(input: QSTileInput<ReduceBrightColorsTileModel>): Unit =
+        with(input) {
+            when (action) {
+                is QSTileUserAction.Click -> {
+                    reduceBrightColorsController.setReduceBrightColorsActivated(
+                        !input.data.isEnabled
+                    )
+                }
+                is QSTileUserAction.LongClick -> {
+                    qsTileIntentUserActionHandler.handle(
+                        action.view,
+                        Intent(Settings.ACTION_REDUCE_BRIGHT_COLORS_SETTINGS)
+                    )
+                }
+            }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/model/ReduceBrightColorsTileModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/model/ReduceBrightColorsTileModel.kt
new file mode 100644
index 0000000..05e0f5d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/domain/model/ReduceBrightColorsTileModel.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.domain.model
+
+/**
+ * Reduce bright colors tile model.
+ *
+ * @param isEnabled is true when the reduce bright colors is enabled;
+ */
+@JvmInline value class ReduceBrightColorsTileModel(val isEnabled: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
new file mode 100644
index 0000000..fca93df
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness.ui
+
+import android.content.res.Resources
+import android.service.quicksettings.Tile
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.impl.reducebrightness.domain.model.ReduceBrightColorsTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+/** Maps [ReduceBrightColorsTileModel] to [QSTileState]. */
+class ReduceBrightColorsTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<ReduceBrightColorsTileModel> {
+
+    override fun map(config: QSTileConfig, data: ReduceBrightColorsTileModel): QSTileState =
+        QSTileState.build(resources, theme, config.uiConfig) {
+            if (data.isEnabled) {
+                activationState = QSTileState.ActivationState.ACTIVE
+                icon = {
+                    Icon.Loaded(
+                        drawable = resources.getDrawable(R.drawable.qs_extra_dim_icon_on, theme),
+                        contentDescription = null
+                    )
+                }
+
+                secondaryLabel =
+                    resources
+                        .getStringArray(R.array.tile_states_reduce_brightness)[Tile.STATE_ACTIVE]
+            } else {
+                activationState = QSTileState.ActivationState.INACTIVE
+                icon = {
+                    Icon.Loaded(
+                        drawable = resources.getDrawable(R.drawable.qs_extra_dim_icon_off, theme),
+                        contentDescription = null
+                    )
+                }
+                secondaryLabel =
+                    resources
+                        .getStringArray(R.array.tile_states_reduce_brightness)[Tile.STATE_INACTIVE]
+            }
+            label =
+                resources.getString(com.android.internal.R.string.reduce_bright_colors_feature_name)
+            contentDescription = label
+            supportedActions =
+                setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileDataInteractor.kt
new file mode 100644
index 0000000..85d2e3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileDataInteractor.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor
+
+import android.os.UserHandle
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.screenrecord.RecordingController
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.onStart
+
+/** Observes screen record state changes providing the [ScreenRecordTileModel]. */
+class ScreenRecordTileDataInteractor
+@Inject
+constructor(
+    @Background private val bgCoroutineContext: CoroutineContext,
+    private val recordingController: RecordingController,
+) : QSTileDataInteractor<ScreenRecordTileModel> {
+
+    override fun tileData(
+        user: UserHandle,
+        triggers: Flow<DataUpdateTrigger>
+    ): Flow<ScreenRecordTileModel> =
+        ConflatedCallbackFlow.conflatedCallbackFlow {
+                val callback =
+                    object : RecordingController.RecordingStateChangeCallback {
+                        override fun onRecordingStart() {
+                            trySend(ScreenRecordTileModel.Recording)
+                        }
+                        override fun onRecordingEnd() {
+                            trySend(ScreenRecordTileModel.DoingNothing)
+                        }
+                        override fun onCountdown(millisUntilFinished: Long) {
+                            trySend(ScreenRecordTileModel.Starting(millisUntilFinished))
+                        }
+                        override fun onCountdownEnd() {
+                            if (
+                                !recordingController.isRecording && !recordingController.isStarting
+                            ) {
+                                // The tile was in Starting state and got canceled before recording
+                                trySend(ScreenRecordTileModel.DoingNothing)
+                            }
+                        }
+                    }
+                recordingController.addCallback(callback)
+                awaitClose { recordingController.removeCallback(callback) }
+            }
+            .onStart { emit(generateModel()) }
+            .distinctUntilChanged()
+            .flowOn(bgCoroutineContext)
+
+    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(true)
+
+    private fun generateModel(): ScreenRecordTileModel {
+        if (recordingController.isRecording) {
+            return ScreenRecordTileModel.Recording
+        } else if (recordingController.isStarting) {
+            return ScreenRecordTileModel.Starting(0)
+        } else {
+            return ScreenRecordTileModel.DoingNothing
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
new file mode 100644
index 0000000..d2bd09f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor
+
+import android.content.Context
+import android.util.Log
+import android.view.View
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
+import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import com.android.systemui.screenrecord.RecordingController
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.withContext
+
+/** Handles screen recorder tile clicks. */
+class ScreenRecordTileUserActionInteractor
+@Inject
+constructor(
+    @Application private val context: Context,
+    @Main private val mainContext: CoroutineContext,
+    @Background private val backgroundContext: CoroutineContext,
+    private val recordingController: RecordingController,
+    private val keyguardInteractor: KeyguardInteractor,
+    private val keyguardDismissUtil: KeyguardDismissUtil,
+    private val dialogTransitionAnimator: DialogTransitionAnimator,
+    private val panelInteractor: PanelInteractor,
+    private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+    private val featureFlags: FeatureFlagsClassic,
+    private val activityStarter: ActivityStarter,
+) : QSTileUserActionInteractor<ScreenRecordTileModel> {
+    override suspend fun handleInput(input: QSTileInput<ScreenRecordTileModel>): Unit =
+        with(input) {
+            when (action) {
+                is QSTileUserAction.Click -> {
+                    when (data) {
+                        is ScreenRecordTileModel.Starting -> {
+                            Log.d(TAG, "Cancelling countdown")
+                            withContext(backgroundContext) { recordingController.cancelCountdown() }
+                        }
+                        is ScreenRecordTileModel.Recording ->
+                            withContext(backgroundContext) { recordingController.stopRecording() }
+                        is ScreenRecordTileModel.DoingNothing ->
+                            withContext(mainContext) { showPrompt(action.view, user.identifier) }
+                    }
+                }
+                is QSTileUserAction.LongClick -> {} // no-op
+            }
+        }
+
+    private fun showPrompt(view: View?, userId: Int) {
+        // Create the recording dialog that will collapse the shade only if we start the recording.
+        val onStartRecordingClicked = Runnable {
+            // We dismiss the shade. Since starting the recording will also dismiss the dialog, we
+            // disable the exit animation which looks weird when it happens at the same time as the
+            // shade collapsing.
+            dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations()
+            panelInteractor.collapsePanels()
+        }
+
+        val dialog =
+            recordingController.createScreenRecordDialog(
+                context,
+                featureFlags,
+                dialogTransitionAnimator,
+                activityStarter,
+                onStartRecordingClicked
+            )
+
+        if (dialog == null) {
+            Log.w(TAG, "showPrompt: dialog was null")
+            return
+        }
+
+        // We animate from the touched view only if we are not on the keyguard, given that if we
+        // are we will dismiss it which will also collapse the shade.
+        val shouldAnimateFromView = view != null && !keyguardInteractor.isKeyguardShowing()
+        val dismissAction =
+            ActivityStarter.OnDismissAction {
+                if (shouldAnimateFromView) {
+                    dialogTransitionAnimator.showFromView(
+                        dialog,
+                        view!!,
+                        DialogCuj(
+                            InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+                            INTERACTION_JANK_TAG
+                        ),
+                        animateBackgroundBoundsChange = true
+                    )
+                } else {
+                    dialog.show()
+                }
+                mediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(userId)
+                false
+            }
+
+        keyguardDismissUtil.executeWhenUnlocked(
+            dismissAction,
+            false /* requiresShadeOpen */,
+            true /* afterKeyguardDone */
+        )
+    }
+
+    private companion object {
+        const val TAG = "ScreenRecordTileUserActionInteractor"
+        const val INTERACTION_JANK_TAG = "screen_record"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/model/ScreenRecordTileModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/model/ScreenRecordTileModel.kt
new file mode 100644
index 0000000..26b0b01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/model/ScreenRecordTileModel.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.domain.model
+
+/** Data model for screen record tile */
+sealed interface ScreenRecordTileModel {
+    data object Recording : ScreenRecordTileModel
+    data class Starting(val millisUntilStarted: Long) : ScreenRecordTileModel
+    data object DoingNothing : ScreenRecordTileModel
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
new file mode 100644
index 0000000..c09b0e3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord.domain.ui
+
+import android.content.res.Resources
+import android.text.TextUtils
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+/** Maps [ScreenRecordTileModel] to [QSTileState]. */
+class ScreenRecordTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<ScreenRecordTileModel> {
+    override fun map(config: QSTileConfig, data: ScreenRecordTileModel): QSTileState =
+        QSTileState.build(resources, theme, config.uiConfig) {
+            label = resources.getString(R.string.quick_settings_screen_record_label)
+            supportedActions = setOf(QSTileState.UserAction.CLICK)
+
+            when (data) {
+                is ScreenRecordTileModel.Recording -> {
+                    activationState = QSTileState.ActivationState.ACTIVE
+                    val loadedIcon =
+                        Icon.Loaded(
+                            resources.getDrawable(R.drawable.qs_screen_record_icon_on, theme),
+                            contentDescription = null
+                        )
+                    icon = { loadedIcon }
+                    sideViewIcon = QSTileState.SideViewIcon.None
+                    secondaryLabel = resources.getString(R.string.quick_settings_screen_record_stop)
+                }
+                is ScreenRecordTileModel.Starting -> {
+                    activationState = QSTileState.ActivationState.ACTIVE
+                    val loadedIcon =
+                        Icon.Loaded(
+                            resources.getDrawable(R.drawable.qs_screen_record_icon_on, theme),
+                            contentDescription = null
+                        )
+                    icon = { loadedIcon }
+                    val countDown = Math.floorDiv(data.millisUntilStarted + 500, 1000)
+                    sideViewIcon = QSTileState.SideViewIcon.None
+                    secondaryLabel = String.format("%d...", countDown)
+                }
+                is ScreenRecordTileModel.DoingNothing -> {
+                    activationState = QSTileState.ActivationState.INACTIVE
+                    val loadedIcon =
+                        Icon.Loaded(
+                            resources.getDrawable(R.drawable.qs_screen_record_icon_off, theme),
+                            contentDescription = null
+                        )
+                    icon = { loadedIcon }
+                    sideViewIcon = QSTileState.SideViewIcon.Chevron // tapping will open dialog
+                    secondaryLabel =
+                        resources.getString(R.string.quick_settings_screen_record_start)
+                }
+            }
+            contentDescription =
+                if (TextUtils.isEmpty(secondaryLabel)) label
+                else TextUtils.concat(label, ", ", secondaryLabel)
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/StubQSTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/StubQSTileViewModel.kt
new file mode 100644
index 0000000..64f1fd3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/StubQSTileViewModel.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.viewmodel
+
+import android.os.UserHandle
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.StateFlow
+
+object StubQSTileViewModel : QSTileViewModel {
+
+    override val state: SharedFlow<QSTileState>
+        get() = error("Don't call stubs")
+
+    override val config: QSTileConfig
+        get() = error("Don't call stubs")
+
+    override val isAvailable: StateFlow<Boolean>
+        get() = error("Don't call stubs")
+
+    override fun onUserChanged(user: UserHandle) = error("Don't call stubs")
+
+    override fun forceUpdate() = error("Don't call stubs")
+
+    override fun onActionPerformed(userAction: QSTileUserAction) = error("Don't call stubs")
+
+    override fun destroy() = error("Don't call stubs")
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
index 6710504..3d86e3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.qs.QSImpl
 import com.android.systemui.qs.dagger.QSSceneComponent
 import com.android.systemui.res.R
+import com.android.systemui.settings.brightness.MirrorController
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.util.kotlin.sample
@@ -68,6 +69,9 @@
      */
     val qsView: Flow<View>
 
+    /** Sets the [MirrorController] in [QSImpl]. Set to `null` to remove. */
+    fun setBrightnessMirrorController(mirrorController: MirrorController?)
+
     /**
      * Inflate an instance of [QSImpl] for this context. Once inflated, it will be available in
      * [qsView]. Re-inflations due to configuration changes will use the last used [context].
@@ -93,6 +97,9 @@
     val isQsFullyCollapsed: Boolean
         get() = true
 
+    /** Request that the customizer be closed. Possibly animating it. */
+    fun requestCloseCustomizer()
+
     sealed interface State {
 
         val isVisible: Boolean
@@ -203,7 +210,7 @@
         applicationScope.launch {
             launch {
                 state.sample(_isCustomizing, ::Pair).collect { (state, customizing) ->
-                    _qsImpl.value?.apply {
+                    qsImpl.value?.apply {
                         if (state != QSSceneAdapter.State.QS && customizing) {
                             [email protected]()
                         }
@@ -277,6 +284,14 @@
         bottomNavBarSize.emit(padding)
     }
 
+    override fun requestCloseCustomizer() {
+        qsImpl.value?.closeCustomizer()
+    }
+
+    override fun setBrightnessMirrorController(mirrorController: MirrorController?) {
+        qsImpl.value?.setBrightnessMirrorController(mirrorController)
+    }
+
     private fun QSImpl.applyState(state: QSSceneAdapter.State) {
         setQsVisible(state.isVisible)
         setExpanded(state.isVisible && state.expansion > 0f)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt
index a3c2cbb..d6325c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsContainerViewModel.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.brightness.ui.viewmodel.BrightnessSliderViewModel
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
 import javax.inject.Inject
 
 @SysUISingleton
@@ -25,4 +26,5 @@
 @Inject
 constructor(
     val brightnessSliderViewModel: BrightnessSliderViewModel,
+    val tileGridViewModel: TileGridViewModel,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
index c695d4c..c1986fa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
@@ -18,45 +18,106 @@
 
 import androidx.lifecycle.LifecycleOwner
 import com.android.compose.animation.scene.Back
+import com.android.compose.animation.scene.Edge
+import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.SwipeDirection
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.qs.FooterActionsController
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
+import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
-import kotlinx.coroutines.flow.map
+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.stateIn
 
 /** Models UI state and handles user input for the quick settings scene. */
 @SysUISingleton
 class QuickSettingsSceneViewModel
 @Inject
 constructor(
+    @Application private val applicationScope: CoroutineScope,
+    deviceEntryInteractor: DeviceEntryInteractor,
+    val brightnessMirrorViewModel: BrightnessMirrorViewModel,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
     val qsSceneAdapter: QSSceneAdapter,
     val notifications: NotificationsPlaceholderViewModel,
     private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
     private val footerActionsController: FooterActionsController,
+    sceneInteractor: SceneInteractor,
 ) {
-    val destinationScenes =
-        qsSceneAdapter.isCustomizing.map { customizing ->
-            if (customizing) {
-                mapOf<UserAction, UserActionResult>(Back to UserActionResult(Scenes.QuickSettings))
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
+        combine(
+                deviceEntryInteractor.isUnlocked,
+                deviceEntryInteractor.canSwipeToEnter,
+                qsSceneAdapter.isCustomizing,
+                sceneInteractor.previousScene(ignored = Scenes.QuickSettings),
+            ) { isUnlocked, canSwipeToDismiss, isCustomizing, previousScene ->
+                destinationScenes(
+                    isUnlocked,
+                    canSwipeToDismiss,
+                    isCustomizing,
+                    previousScene,
+                )
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue =
+                    destinationScenes(
+                        isUnlocked = deviceEntryInteractor.isUnlocked.value,
+                        canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
+                        isCustomizing = qsSceneAdapter.isCustomizing.value,
+                        previousScene = sceneInteractor
+                                .previousScene(ignored = Scenes.QuickSettings).value,
+                    ),
+            )
+
+    private fun destinationScenes(
+        isUnlocked: Boolean,
+        canSwipeToDismiss: Boolean?,
+        isCustomizing: Boolean,
+        previousScene: SceneKey?
+    ): Map<UserAction, UserActionResult> {
+        val upBottomEdge =
+            when {
+                canSwipeToDismiss == true -> Scenes.Lockscreen
+                isUnlocked -> Scenes.Gone
+                else -> Scenes.Lockscreen
+            }
+
+        return buildMap {
+            if (isCustomizing) {
+                // TODO(b/332749288) Empty map so there are no back handlers and back can close
+                // customizer
+
                 // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade
                 // while customizing
             } else {
-                mapOf(
-                    Back to UserActionResult(Scenes.Shade),
-                    Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Shade),
-                )
+                this[Back] = UserActionResult(previousScene ?: Scenes.Shade)
+                this[Swipe(SwipeDirection.Up)] = UserActionResult(previousScene ?: Scenes.Shade)
+                this[
+                    Swipe(
+                        fromSource = Edge.Bottom,
+                        direction = SwipeDirection.Up,
+                    )] = UserActionResult(upBottomEdge)
             }
         }
+    }
 
     private val footerActionsControllerInitialized = AtomicBoolean(false)
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 7c1a2c0..1ddc094 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -98,7 +98,8 @@
 import com.android.systemui.navigationbar.buttons.KeyButtonView;
 import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
+import com.android.systemui.scene.shared.model.Scenes;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.ShadeViewController;
@@ -145,7 +146,6 @@
     private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
 
     private final Context mContext;
-    private final SceneContainerFlags mSceneContainerFlags;
     private final Executor mMainExecutor;
     private final ShellInterface mShellInterface;
     private final Lazy<ShadeViewController> mShadeViewControllerLazy;
@@ -207,7 +207,7 @@
         @Override
         public void onStatusBarTouchEvent(MotionEvent event) {
             verifyCallerAndClearCallingIdentity("onStatusBarTouchEvent", () -> {
-                if (mSceneContainerFlags.isEnabled()) {
+                if (SceneContainerFlag.isEnabled()) {
                     //TODO(b/329863123) implement latency tracking for shade scene
                     Log.i(TAG_OPS, "Scene container enabled. Latency tracking not started.");
                 } else if (event.getActionMasked() == ACTION_DOWN) {
@@ -222,7 +222,7 @@
 
                         // If scene framework is enabled, set the scene container window to
                         // visible and let the touch "slip" into that window.
-                        if (mSceneContainerFlags.isEnabled()) {
+                        if (SceneContainerFlag.isEnabled()) {
                             mSceneInteractor.get().onRemoteUserInteractionStarted("launcher swipe");
                         } else {
                             mShadeViewControllerLazy.get().startInputFocusTransfer();
@@ -231,7 +231,7 @@
                     if (action == ACTION_UP || action == ACTION_CANCEL) {
                         mInputFocusTransferStarted = false;
 
-                        if (!mSceneContainerFlags.isEnabled()) {
+                        if (!SceneContainerFlag.isEnabled()) {
                             float velocity = (event.getY() - mInputFocusTransferStartY)
                                     / (event.getEventTime() - mInputFocusTransferStartMillis);
                             if (action == ACTION_CANCEL) {
@@ -239,6 +239,11 @@
                             } else {
                                 mShadeViewControllerLazy.get().finishInputFocusTransfer(velocity);
                             }
+                        } else if (action == ACTION_UP) {
+                            // Gesture was too short to be picked up by scene container touch
+                            // handling; programmatically start the transition to shade scene.
+                            mSceneInteractor.get().changeScene(
+                                    Scenes.Shade, "short launcher swipe");
                         }
                     }
                     event.recycle();
@@ -259,6 +264,12 @@
         }
 
         @Override
+        public void setOverrideHomeButtonLongPress(long duration, float slopMultiplier) {
+            verifyCallerAndClearCallingIdentityPostMain("setOverrideHomeButtonLongPress",
+                    () -> notifySetOverrideHomeButtonLongPress(duration, slopMultiplier));
+        }
+
+        @Override
         public void onBackPressed() {
             verifyCallerAndClearCallingIdentityPostMain("onBackPressed", () -> {
                 sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
@@ -600,7 +611,6 @@
             KeyguardUnlockAnimationController sysuiUnlockAnimationController,
             InWindowLauncherUnlockAnimationManager inWindowLauncherUnlockAnimationManager,
             AssistUtils assistUtils,
-            SceneContainerFlags sceneContainerFlags,
             DumpManager dumpManager,
             Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder,
             BroadcastDispatcher broadcastDispatcher
@@ -612,7 +622,6 @@
         }
 
         mContext = context;
-        mSceneContainerFlags = sceneContainerFlags;
         mMainExecutor = mainExecutor;
         mShellInterface = shellInterface;
         mShadeViewControllerLazy = shadeViewControllerLazy;
@@ -947,6 +956,12 @@
         }
     }
 
+    private void notifySetOverrideHomeButtonLongPress(long duration, float slopMultiplier) {
+        for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+            mConnectionCallbacks.get(i).setOverrideHomeButtonLongPress(duration, slopMultiplier);
+        }
+    }
+
     public void notifyAssistantVisibilityChanged(float visibility) {
         try {
             if (mOverviewProxy != null) {
@@ -1104,6 +1119,8 @@
         default void startAssistant(Bundle bundle) {}
         default void setAssistantOverridesRequested(int[] invocationTypes) {}
         default void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {}
+        /** Set override of home button long press duration and touch slop multiplier. */
+        default void setOverrideHomeButtonLongPress(long override, float slopMultiplier) {}
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
index 5e4919d..4e290e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recordissue
 
+import android.app.IActivityManager
 import android.app.NotificationManager
 import android.content.Context
 import android.content.Intent
@@ -46,12 +47,13 @@
 import java.util.zip.ZipEntry
 import java.util.zip.ZipOutputStream
 import javax.inject.Inject
+import kotlin.jvm.optionals.getOrElse
 
 class IssueRecordingService
 @Inject
 constructor(
     controller: RecordingController,
-    @LongRunning executor: Executor,
+    @LongRunning private val bgExecutor: Executor,
     @Main handler: Handler,
     uiEventLogger: UiEventLogger,
     notificationManager: NotificationManager,
@@ -60,10 +62,12 @@
     private val dialogTransitionAnimator: DialogTransitionAnimator,
     private val panelInteractor: PanelInteractor,
     private val issueRecordingState: IssueRecordingState,
+    private val iActivityManager: IActivityManager,
+    private val launcherApps: LauncherApps,
 ) :
     RecordingService(
         controller,
-        executor,
+        bgExecutor,
         handler,
         uiEventLogger,
         notificationManager,
@@ -103,12 +107,26 @@
                 // ViewCapture needs to save it's data before it is disabled, or else the data will
                 // be lost. This is expected to change in the near future, and when that happens
                 // this line should be removed.
-                getSystemService(LauncherApps::class.java)?.saveViewCaptureData()
+                launcherApps.saveViewCaptureData()
                 TraceUtils.traceStop(contentResolver)
                 issueRecordingState.isRecording = false
             }
             ACTION_SHARE -> {
-                shareRecording(intent)
+                bgExecutor.execute {
+                    mNotificationManager.cancelAsUser(
+                        null,
+                        mNotificationId,
+                        UserHandle(mUserContextTracker.userContext.userId)
+                    )
+
+                    val screenRecording = intent.getParcelableExtra(EXTRA_PATH, Uri::class.java)
+                    if (issueRecordingState.takeBugReport) {
+                        iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
+                    } else {
+                        shareRecording(screenRecording)
+                    }
+                }
+
                 dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations()
                 panelInteractor.collapsePanels()
 
@@ -122,22 +140,26 @@
         return super.onStartCommand(intent, flags, startId)
     }
 
-    private fun shareRecording(intent: Intent) {
-        val sharableUri: Uri =
-            zipAndPackageRecordings(
-                TraceUtils.traceDump(contentResolver, TRACE_FILE_NAME).get(),
-                intent.getStringExtra(EXTRA_PATH)
-            )
-                ?: return
-        val sendIntent =
-            FileSender.buildSendIntent(this, listOf(sharableUri))
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+    private fun shareRecording(screenRecording: Uri?) {
+        val traces =
+            TraceUtils.traceDump(contentResolver, TRACE_FILE_NAME).getOrElse {
+                Log.v(
+                    TAG,
+                    "Traces were not present. This can happen if users double" +
+                        "click on share notification. Traces are cleaned up after sharing" +
+                        "so they won't be present for the 2nd share attempt."
+                )
+                return
+            }
+        val perfetto = FileProvider.getUriForFile(this, AUTHORITY, traces.first())
+        val urisToShare = mutableListOf(perfetto)
+        traces.removeFirst()
 
-        mNotificationManager.cancelAsUser(
-            null,
-            mNotificationId,
-            UserHandle(mUserContextTracker.userContext.userId)
-        )
+        getZipWinscopeFileUri(traces)?.let { urisToShare.add(it) }
+        screenRecording?.let { urisToShare.add(it) }
+
+        val sendIntent =
+            FileSender.buildSendIntent(this, urisToShare).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
 
         // TODO: Debug why the notification shade isn't closing upon starting the BetterBug activity
         mKeyguardDismissUtil.executeWhenUnlocked(
@@ -150,7 +172,7 @@
         )
     }
 
-    private fun zipAndPackageRecordings(traceFiles: List<File>, screenRecordingUri: String?): Uri? {
+    private fun getZipWinscopeFileUri(traceFiles: List<File>): Uri? {
         try {
             externalCacheDir?.mkdirs()
             val outZip: File = File.createTempFile(TEMP_FILE_PREFIX, ZIP_SUFFIX, externalCacheDir)
@@ -160,13 +182,6 @@
                     Files.copy(file.toPath(), os)
                     os.closeEntry()
                 }
-                if (screenRecordingUri != null) {
-                    contentResolver.openInputStream(Uri.parse(screenRecordingUri))?.use {
-                        os.putNextEntry(ZipEntry(SCREEN_RECORDING_ZIP_LABEL))
-                        it.transferTo(os)
-                        os.closeEntry()
-                    }
-                }
             }
             return FileProvider.getUriForFile(this, AUTHORITY, outZip)
         } catch (e: Exception) {
@@ -181,8 +196,7 @@
         private const val EXTRA_SCREEN_RECORD = "extra_screenRecord"
         private const val EXTRA_WINSCOPE_TRACING = "extra_winscopeTracing"
         private const val ZIP_SUFFIX = ".zip"
-        private const val TEMP_FILE_PREFIX = "issue_recording"
-        private const val SCREEN_RECORDING_ZIP_LABEL = "screen-recording.mp4"
+        private const val TEMP_FILE_PREFIX = "winscope_recordings"
 
         private val DEFAULT_TRACE_TAGS = listOf<String>()
         private const val DEFAULT_BUFFER_SIZE = 16384
@@ -215,7 +229,7 @@
         fun getStartIntent(
             context: Context,
             screenRecord: Boolean,
-            winscopeTracing: Boolean
+            winscopeTracing: Boolean,
         ): Intent =
             Intent(context, IssueRecordingService::class.java)
                 .setAction(ACTION_START)
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingState.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingState.kt
index 394c5c2..12ed06d 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingState.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingState.kt
@@ -25,6 +25,8 @@
 
     private val listeners = CopyOnWriteArrayList<Runnable>()
 
+    var takeBugReport: Boolean = false
+
     var isRecording = false
         set(value) {
             field = value
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt
index dab61fa..68b8836 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt
@@ -63,6 +63,7 @@
     private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
     private val userFileManager: UserFileManager,
     private val screenCaptureDisabledDialogDelegate: ScreenCaptureDisabledDialogDelegate,
+    private val issueRecordingState: IssueRecordingState,
     @Assisted private val onStarted: Consumer<IssueRecordingConfig>,
 ) : SystemUIDialog.Delegate {
 
@@ -74,6 +75,7 @@
     }
 
     @SuppressLint("UseSwitchCompatOrMaterialCode") private lateinit var screenRecordSwitch: Switch
+    @SuppressLint("UseSwitchCompatOrMaterialCode") private lateinit var bugReportSwitch: Switch
     private lateinit var issueTypeButton: Button
 
     @MainThread
@@ -86,6 +88,7 @@
             setPositiveButton(
                 R.string.qs_record_issue_start,
                 { _, _ ->
+                    issueRecordingState.takeBugReport = bugReportSwitch.isChecked
                     onStarted.accept(
                         IssueRecordingConfig(
                             screenRecordSwitch.isChecked,
@@ -113,6 +116,7 @@
                     bgExecutor.execute { onScreenRecordSwitchClicked() }
                 }
             }
+            bugReportSwitch = requireViewById(R.id.bugreport_switch)
             val startButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
             issueTypeButton = requireViewById(R.id.issue_type_button)
             issueTypeButton.setOnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index afd0746..8277c73 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.scene
 
-import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
 import dagger.Module
@@ -29,7 +28,6 @@
             EmptySceneModule::class,
             GoneSceneModule::class,
             QuickSettingsSceneModule::class,
-            SceneContainerFlagsModule::class,
             ShadeSceneModule::class,
         ],
 )
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 62b0914..69f9443 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -20,7 +20,6 @@
 import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlagsModule
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.startable.SceneContainerStartable
-import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
 import dagger.Binds
@@ -40,7 +39,6 @@
             GoneSceneModule::class,
             LockscreenSceneModule::class,
             QuickSettingsSceneModule::class,
-            SceneContainerFlagsModule::class,
             ShadeSceneModule::class,
         ],
 )
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
index 0665c9e..d202c24 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.scene
 
-import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
 import dagger.Module
@@ -30,7 +29,6 @@
             EmptySceneModule::class,
             GoneSceneModule::class,
             LockscreenSceneModule::class,
-            SceneContainerFlagsModule::class,
         ],
 )
 object ShadelessSceneContainerFrameworkModule {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index 994b012..3082eb9 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -24,6 +24,8 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.SceneDataSource
+import com.android.systemui.util.kotlin.WithPrev
+import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,6 +36,7 @@
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /** Source of truth for scene framework application state. */
@@ -44,7 +47,32 @@
     private val config: SceneContainerConfig,
     private val dataSource: SceneDataSource,
 ) {
-    val currentScene: StateFlow<SceneKey> = dataSource.currentScene
+    private val previousAndCurrentScene: StateFlow<WithPrev<SceneKey?, SceneKey>> =
+        dataSource.currentScene
+            .pairwise()
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = WithPrev(null, dataSource.currentScene.value),
+            )
+
+    val currentScene: StateFlow<SceneKey> =
+        previousAndCurrentScene
+            .map { it.newValue }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = previousAndCurrentScene.value.newValue,
+            )
+
+    val previousScene: StateFlow<SceneKey?> =
+        previousAndCurrentScene
+            .map { it.previousValue }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = previousAndCurrentScene.value.previousValue,
+            )
 
     private val _isVisible = MutableStateFlow(true)
     val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 2ccd3b9..8ced222 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -140,6 +140,33 @@
             )
 
     /**
+     * The previous scene (or `null` if the previous scene is the [ignored] scene).
+     *
+     * This is effectively the previous value of [currentScene] which means that all caveats, for
+     * example regarding when in a transition the current scene changes, apply.
+     *
+     * @param ignored If the previous scene is the same as [ignored], `null` is emitted. This is
+     *   designed to reduce the chances of a scene using [previousScene] naively to then set up a
+     *   user action that ends up leading to itself, which is an illegal operation that would cause
+     *   a crash.
+     */
+    fun previousScene(
+        ignored: SceneKey? = null,
+    ): StateFlow<SceneKey?> {
+        fun SceneKey?.nullifyIfIgnored(): SceneKey? {
+            return this?.takeIf { this != ignored }
+        }
+
+        return repository.previousScene
+            .map { it.nullifyIfIgnored() }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = repository.previousScene.value.nullifyIfIgnored(),
+            )
+    }
+
+    /**
      * Returns the keys of all scenes in the container.
      *
      * The scenes will be sorted in z-order such that the last one is the one that should be
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
index c736707..1cf1c18 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
@@ -24,7 +24,7 @@
 import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
@@ -53,7 +53,6 @@
     private val headsUpManager: HeadsUpManager,
     private val powerInteractor: PowerInteractor,
     private val activeNotificationsInteractor: ActiveNotificationsInteractor,
-    sceneContainerFlags: SceneContainerFlags,
     sceneInteractorProvider: Provider<SceneInteractor>,
 ) : CoreStartable {
 
@@ -68,7 +67,7 @@
      * false if the bouncer is visible.
      */
     val isLockscreenOrShadeVisible: StateFlow<Boolean> =
-        if (!sceneContainerFlags.isEnabled()) {
+        if (!SceneContainerFlag.isEnabled) {
             windowRootViewVisibilityRepository.isLockscreenOrShadeVisible
         } else {
             sceneInteractorProvider
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 32d72e0..4fc24b8 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -21,11 +21,13 @@
 import android.app.StatusBarManager
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.CoreStartable
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor
+import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.classifier.FalsingCollectorActual
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -35,6 +37,7 @@
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
+import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.model.SceneContainerPlugin
 import com.android.systemui.model.SysUiState
@@ -44,9 +47,10 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
 import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.logger.SceneLogger
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
 import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -61,6 +65,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
@@ -68,10 +73,12 @@
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.filterIsInstance
+import kotlinx.coroutines.flow.filterNot
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
 /**
@@ -88,7 +95,6 @@
     private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
     private val bouncerInteractor: BouncerInteractor,
     private val keyguardInteractor: KeyguardInteractor,
-    private val flags: SceneContainerFlags,
     private val sysUiState: SysUiState,
     @DisplayId private val displayId: Int,
     private val sceneLogger: SceneLogger,
@@ -103,32 +109,36 @@
     private val headsUpInteractor: HeadsUpNotificationInteractor,
     private val occlusionInteractor: SceneContainerOcclusionInteractor,
     private val faceUnlockInteractor: DeviceEntryFaceAuthInteractor,
+    private val shadeInteractor: ShadeInteractor,
+    private val uiEventLogger: UiEventLogger,
 ) : CoreStartable {
 
     override fun start() {
-        if (flags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled) {
             sceneLogger.logFrameworkEnabled(isEnabled = true)
             hydrateVisibility()
             automaticallySwitchScenes()
             hydrateSystemUiState()
             collectFalsingSignals()
             respondToFalsingDetections()
-            hydrateWindowFocus()
             hydrateInteractionState()
             handleBouncerOverscroll()
+            hydrateWindowController()
         } else {
             sceneLogger.logFrameworkEnabled(
                 isEnabled = false,
-                reason = flags.requirementDescription(),
+                reason = SceneContainerFlag.requirementDescription(),
             )
         }
     }
 
     override fun dump(pw: PrintWriter, args: Array<out String>) =
         pw.asIndenting().run {
-            printSection("SceneContainerFlags") {
-                println("isEnabled", flags.isEnabled())
-                printSection("requirementDescription") { println(flags.requirementDescription()) }
+            printSection("SceneContainerFlag") {
+                println("isEnabled", SceneContainerFlag.isEnabled)
+                printSection("requirementDescription") {
+                    println(SceneContainerFlag.requirementDescription())
+                }
             }
         }
 
@@ -185,6 +195,14 @@
 
     /** Switches between scenes based on ever-changing application state. */
     private fun automaticallySwitchScenes() {
+        handleBouncerImeVisibility()
+        handleSimUnlock()
+        handleDeviceUnlockStatus()
+        handlePowerState()
+        handleShadeTouchability()
+    }
+
+    private fun handleBouncerImeVisibility() {
         applicationScope.launch {
             // TODO (b/308001302): Move this to a bouncer specific interactor.
             bouncerInteractor.onImeHiddenByUser.collectLatest {
@@ -196,6 +214,9 @@
                 }
             }
         }
+    }
+
+    private fun handleSimUnlock() {
         applicationScope.launch {
             simBouncerInteractor
                 .get()
@@ -229,7 +250,17 @@
                     }
                 }
         }
+    }
+
+    private fun handleDeviceUnlockStatus() {
         applicationScope.launch {
+            // Track the previous scene (sans Bouncer), so that we know where to go when the device
+            // is unlocked whilst on the bouncer.
+            val previousScene =
+                sceneInteractor
+                    .previousScene()
+                    .filterNot { it == Scenes.Bouncer }
+                    .stateIn(this, SharingStarted.Eagerly, initialValue = null)
             deviceUnlockedInteractor.deviceUnlockStatus
                 .mapNotNull { deviceUnlockStatus ->
                     val renderedScenes =
@@ -255,10 +286,24 @@
                         }
                     }
 
+                    if (
+                        isOnBouncer &&
+                            deviceUnlockStatus.deviceUnlockSource == DeviceUnlockSource.TrustAgent
+                    ) {
+                        uiEventLogger.log(BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS)
+                    }
                     when {
                         isOnBouncer ->
-                            // When the device becomes unlocked in Bouncer, go to Gone.
-                            Scenes.Gone to "device was unlocked in Bouncer scene"
+                            // When the device becomes unlocked in Bouncer, go to previous scene,
+                            // or Gone.
+                            if (previousScene.value == Scenes.Lockscreen) {
+                                Scenes.Gone to "device was unlocked in Bouncer scene"
+                            } else {
+                                val prevScene = previousScene.value
+                                (prevScene
+                                    ?: Scenes.Gone) to
+                                    "device was unlocked in Bouncer scene, from sceneKey=$prevScene"
+                            }
                         isOnLockscreen ->
                             // The lockscreen should be dismissed automatically in 2 scenarios:
                             // 1. When face auth bypass is enabled and authentication happens while
@@ -288,7 +333,9 @@
                     )
                 }
         }
+    }
 
+    private fun handlePowerState() {
         applicationScope.launch {
             powerInteractor.isAsleep.collect { isAsleep ->
                 if (isAsleep) {
@@ -317,7 +364,7 @@
                     ) {
                         switchToScene(
                             targetSceneKey = Scenes.Bouncer,
-                            loggingReason = "device is starting to wake up with a locked sim"
+                            loggingReason = "device is starting to wake up with a locked sim",
                         )
                     }
                 }
@@ -325,6 +372,20 @@
         }
     }
 
+    private fun handleShadeTouchability() {
+        applicationScope.launch {
+            shadeInteractor.isShadeTouchable
+                .distinctUntilChanged()
+                .filter { !it }
+                .collect {
+                    switchToScene(
+                        targetSceneKey = Scenes.Lockscreen,
+                        loggingReason = "device became non-interactive",
+                    )
+                }
+        }
+    }
+
     /** Keeps [SysUiState] up-to-date */
     private fun hydrateSystemUiState() {
         applicationScope.launch {
@@ -352,6 +413,40 @@
         }
     }
 
+    private fun hydrateWindowController() {
+        applicationScope.launch {
+            sceneInteractor.transitionState
+                .mapNotNull { transitionState ->
+                    (transitionState as? ObservableTransitionState.Idle)?.scene
+                }
+                .distinctUntilChanged()
+                .collect { sceneKey ->
+                    windowController.setNotificationShadeFocusable(sceneKey != Scenes.Gone)
+                }
+        }
+
+        applicationScope.launch {
+            deviceEntryInteractor.isDeviceEntered.collect { isDeviceEntered ->
+                windowController.setKeyguardShowing(!isDeviceEntered)
+            }
+        }
+
+        applicationScope.launch {
+            sceneInteractor.currentScene
+                .map { it == Scenes.Bouncer }
+                .distinctUntilChanged()
+                .collect { isBouncerShowing ->
+                    windowController.setBouncerShowing(isBouncerShowing)
+                }
+        }
+
+        applicationScope.launch {
+            occlusionInteractor.invisibleDueToOcclusion.collect { invisibleDueToOcclusion ->
+                windowController.setKeyguardOccluded(invisibleDueToOcclusion)
+            }
+        }
+    }
+
     /** Collects and reports signals into the falsing system. */
     private fun collectFalsingSignals() {
         applicationScope.launch {
@@ -413,20 +508,6 @@
         }
     }
 
-    /** Keeps the focus state of the window view up-to-date. */
-    private fun hydrateWindowFocus() {
-        applicationScope.launch {
-            sceneInteractor.transitionState
-                .mapNotNull { transitionState ->
-                    (transitionState as? ObservableTransitionState.Idle)?.scene
-                }
-                .distinctUntilChanged()
-                .collect { sceneKey ->
-                    windowController.setNotificationShadeFocusable(sceneKey != Scenes.Gone)
-                }
-        }
-    }
-
     /** Keeps the interaction state of [CentralSurfaces] up-to-date. */
     private fun hydrateInteractionState() {
         applicationScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
new file mode 100644
index 0000000..234eda8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE")
+
+package com.android.systemui.scene.shared.flag
+
+import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
+import com.android.systemui.Flags.sceneContainer
+import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
+import com.android.systemui.keyguard.KeyguardWmStateRefactor
+import com.android.systemui.keyguard.MigrateClocksToBlueprint
+import com.android.systemui.keyguard.shared.ComposeLockscreen
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
+import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
+import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor
+import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag
+
+/** Helper for reading or using the scene container flag state. */
+object SceneContainerFlag {
+    /** The flag description -- not an aconfig flag name */
+    const val DESCRIPTION = "SceneContainerFlag"
+
+    @JvmStatic
+    inline val isEnabled
+        get() =
+            sceneContainer() && // mainAconfigFlag
+            ComposeLockscreen.isEnabled &&
+                KeyguardBottomAreaRefactor.isEnabled &&
+                KeyguardWmStateRefactor.isEnabled &&
+                MediaInSceneContainerFlag.isEnabled &&
+                MigrateClocksToBlueprint.isEnabled &&
+                NotificationsHeadsUpRefactor.isEnabled &&
+                PredictiveBackSysUiFlag.isEnabled &&
+                DeviceEntryUdfpsRefactor.isEnabled &&
+                RefactorKeyguardDismissIntent.isEnabled
+    // NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
+
+    /** The main aconfig flag. */
+    inline fun getMainAconfigFlag() = FlagToken(FLAG_SCENE_CONTAINER, sceneContainer())
+
+    /** The set of secondary flags which must be enabled for scene container to work properly */
+    inline fun getSecondaryFlags(): Sequence<FlagToken> =
+        sequenceOf(
+            ComposeLockscreen.token,
+            KeyguardBottomAreaRefactor.token,
+            KeyguardWmStateRefactor.token,
+            MediaInSceneContainerFlag.token,
+            MigrateClocksToBlueprint.token,
+            NotificationsHeadsUpRefactor.token,
+            PredictiveBackSysUiFlag.token,
+            DeviceEntryUdfpsRefactor.token,
+            RefactorKeyguardDismissIntent.token,
+            // NOTE: Changes should also be made in isEnabled and @EnableSceneContainer
+        )
+
+    /** The full set of requirements for SceneContainer */
+    inline fun getAllRequirements(): Sequence<FlagToken> {
+        return sequenceOf(getMainAconfigFlag()) + getSecondaryFlags()
+    }
+
+    /** Return all dependencies of this flag in pairs where [Pair.first] depends on [Pair.second] */
+    inline fun getFlagDependencies(): Sequence<Pair<FlagToken, FlagToken>> {
+        val mainAconfigFlag = getMainAconfigFlag()
+        return getSecondaryFlags().map { mainAconfigFlag to it }
+    }
+
+    /**
+     * Called to ensure code is only run when the flag is enabled. This protects users from the
+     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+     * build to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun isUnexpectedlyInLegacyMode() =
+        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, DESCRIPTION)
+
+    /**
+     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+     * the flag is enabled to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, DESCRIPTION)
+
+    /** Returns a developer-readable string that describes the current requirement list. */
+    @JvmStatic
+    fun requirementDescription(): String {
+        return buildString {
+            getAllRequirements().forEach { requirement ->
+                append('\n')
+                append(if (requirement.isEnabled) "    [MET]" else "[NOT MET]")
+                append(" ${requirement.name}")
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
deleted file mode 100644
index 5664d59..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
+++ /dev/null
@@ -1,128 +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.
- */
-
-@file:Suppress("NOTHING_TO_INLINE")
-
-package com.android.systemui.scene.shared.flag
-
-import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
-import com.android.systemui.Flags.sceneContainer
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
-import com.android.systemui.keyguard.KeyguardWmStateRefactor
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
-import com.android.systemui.keyguard.shared.ComposeLockscreen
-import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
-import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag
-import dagger.Module
-import dagger.Provides
-
-/** Helper for reading or using the scene container flag state. */
-object SceneContainerFlag {
-    /** The flag description -- not an aconfig flag name */
-    const val DESCRIPTION = "SceneContainerFlag"
-
-    @JvmStatic
-    inline val isEnabled
-        get() =
-            sceneContainer() && // mainAconfigFlag
-            KeyguardBottomAreaRefactor.isEnabled &&
-                MigrateClocksToBlueprint.isEnabled &&
-                ComposeLockscreen.isEnabled &&
-                MediaInSceneContainerFlag.isEnabled &&
-                KeyguardWmStateRefactor.isEnabled &&
-                PredictiveBackSysUiFlag.isEnabled
-    // NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
-
-    /** The main aconfig flag. */
-    inline fun getMainAconfigFlag() = FlagToken(FLAG_SCENE_CONTAINER, sceneContainer())
-
-    /** The set of secondary flags which must be enabled for scene container to work properly */
-    inline fun getSecondaryFlags(): Sequence<FlagToken> =
-        sequenceOf(
-            KeyguardBottomAreaRefactor.token,
-            MigrateClocksToBlueprint.token,
-            KeyguardWmStateRefactor.token,
-            ComposeLockscreen.token,
-            MediaInSceneContainerFlag.token,
-            // NOTE: Changes should also be made in isEnabled and @EnableSceneContainer
-        )
-
-    /** The full set of requirements for SceneContainer */
-    inline fun getAllRequirements(): Sequence<FlagToken> {
-        return sequenceOf(getMainAconfigFlag()) + getSecondaryFlags()
-    }
-
-    /** Return all dependencies of this flag in pairs where [Pair.first] depends on [Pair.second] */
-    inline fun getFlagDependencies(): Sequence<Pair<FlagToken, FlagToken>> {
-        val mainAconfigFlag = getMainAconfigFlag()
-        return getSecondaryFlags().map { mainAconfigFlag to it }
-    }
-
-    /**
-     * Called to ensure code is only run when the flag is enabled. This protects users from the
-     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
-     * build to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun isUnexpectedlyInLegacyMode() =
-        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, DESCRIPTION)
-
-    /**
-     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
-     * the flag is enabled to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, DESCRIPTION)
-}
-
-/**
- * Defines interface for classes that can check whether the scene container framework feature is
- * enabled.
- */
-interface SceneContainerFlags {
-
-    /** Returns `true` if the Scene Container Framework is enabled; `false` otherwise. */
-    fun isEnabled(): Boolean
-
-    /** Returns a developer-readable string that describes the current requirement list. */
-    fun requirementDescription(): String
-}
-
-class SceneContainerFlagsImpl : SceneContainerFlags {
-
-    override fun isEnabled(): Boolean {
-        return SceneContainerFlag.isEnabled
-    }
-
-    override fun requirementDescription(): String {
-        return buildString {
-            SceneContainerFlag.getAllRequirements().forEach { requirement ->
-                append('\n')
-                append(if (requirement.isEnabled) "    [MET]" else "[NOT MET]")
-                append(" ${requirement.name}")
-            }
-        }
-    }
-}
-
-@Module
-object SceneContainerFlagsModule {
-
-    @Provides @SysUISingleton fun impl(): SceneContainerFlags = SceneContainerFlagsImpl()
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
index 67dc0cc..259a8bf 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -4,7 +4,6 @@
 import android.util.AttributeSet
 import android.view.View
 import android.view.WindowInsets
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.scene.shared.model.Scene
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
@@ -31,7 +30,6 @@
         viewModel: SceneContainerViewModel,
         containerConfig: SceneContainerConfig,
         sharedNotificationContainer: SharedNotificationContainer,
-        flags: SceneContainerFlags,
         scenes: Set<Scene>,
         layoutInsetController: LayoutInsetsController,
         sceneDataSourceDelegator: SceneDataSourceDelegator,
@@ -44,7 +42,6 @@
             windowInsets = windowInsets,
             containerConfig = containerConfig,
             sharedNotificationContainer = sharedNotificationContainer,
-            flags = flags,
             scenes = scenes,
             onVisibilityChangedInternal = { isVisible ->
                 super.setVisibility(if (isVisible) View.VISIBLE else View.INVISIBLE)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 809ac2e..2ef9b73 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -39,7 +39,7 @@
 import com.android.systemui.common.ui.compose.windowinsets.ScreenDecorProvider
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scene
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
@@ -63,7 +63,6 @@
         windowInsets: StateFlow<WindowInsets?>,
         containerConfig: SceneContainerConfig,
         sharedNotificationContainer: SharedNotificationContainer,
-        flags: SceneContainerFlags,
         scenes: Set<Scene>,
         onVisibilityChangedInternal: (isVisible: Boolean) -> Unit,
         dataSourceDelegator: SceneDataSourceDelegator,
@@ -115,7 +114,7 @@
                     //  the SceneContainerView. This SharedNotificationContainer should contain NSSL
                     //  due to the NotificationStackScrollLayoutSection (legacy) or
                     //  NotificationSection (scene container) moving it there.
-                    if (flags.isEnabled()) {
+                    if (SceneContainerFlag.isEnabled) {
                         (sharedNotificationContainer.parent as? ViewGroup)?.removeView(
                             sharedNotificationContainer
                         )
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index 231b284..ef7829f 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -19,15 +19,22 @@
 import android.view.MotionEvent
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.classifier.Classifier
 import com.android.systemui.classifier.domain.interactor.FalsingInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.Scene
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
 
 /** Models UI state for the scene container. */
 @SysUISingleton
@@ -37,6 +44,7 @@
     private val sceneInteractor: SceneInteractor,
     private val falsingInteractor: FalsingInteractor,
     private val powerInteractor: PowerInteractor,
+    scenes: Set<@JvmSuppressWildcards Scene>,
 ) {
     /**
      * Keys of all scenes in the container.
@@ -52,6 +60,23 @@
     /** Whether the container is visible. */
     val isVisible: StateFlow<Boolean> = sceneInteractor.isVisible
 
+    private val destinationScenesBySceneKey =
+        scenes.associate { scene -> scene.key to scene.destinationScenes }
+
+    fun currentDestinationScenes(
+        scope: CoroutineScope,
+    ): StateFlow<Map<UserAction, UserActionResult>> {
+        return currentScene
+            .flatMapLatestConflated { currentSceneKey ->
+                checkNotNull(destinationScenesBySceneKey[currentSceneKey])
+            }
+            .stateIn(
+                scope = scope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = emptyMap(),
+            )
+    }
+
     /**
      * Binds the given flow so the system remembers it.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index b2c01e1..cbb61b3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -206,7 +206,7 @@
                 break;
 
             case ACTION_SHARE:
-                Uri shareUri = Uri.parse(intent.getStringExtra(EXTRA_PATH));
+                Uri shareUri = intent.getParcelableExtra(EXTRA_PATH, Uri.class);
 
                 Intent shareIntent = new Intent(Intent.ACTION_SEND)
                         .setType("video/mp4")
@@ -356,7 +356,7 @@
                 PendingIntent.getService(
                         this,
                         REQUEST_CODE,
-                        getShareIntent(this, uri != null ? uri.toString() : null),
+                        getShareIntent(this, uri),
                         PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
                 .build();
 
@@ -512,7 +512,7 @@
         return new Intent(context, this.getClass()).setAction(ACTION_STOP_NOTIF);
     }
 
-    private Intent getShareIntent(Context context, String path) {
+    private Intent getShareIntent(Context context, Uri path) {
         return new Intent(context, this.getClass()).setAction(ACTION_SHARE)
                 .putExtra(EXTRA_PATH, path);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt
index 0bc02ed..8c675e3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt
@@ -16,10 +16,22 @@
 
 package com.android.systemui.screenrecord
 
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.qs.tiles.ScreenRecordTile
+import com.android.systemui.qs.tiles.base.viewmodel.QSTileViewModelFactory
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor.ScreenRecordTileDataInteractor
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor.ScreenRecordTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.model.ScreenRecordTileModel
+import com.android.systemui.qs.tiles.impl.screenrecord.domain.ui.ScreenRecordTileMapper
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
+import com.android.systemui.res.R
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.IntoMap
 import dagger.multibindings.StringKey
 
@@ -30,4 +42,39 @@
     @IntoMap
     @StringKey(ScreenRecordTile.TILE_SPEC)
     fun bindScreenRecordTile(screenRecordTile: ScreenRecordTile): QSTileImpl<*>
+
+    companion object {
+        private const val SCREEN_RECORD_TILE_SPEC = "screenrecord"
+
+        @Provides
+        @IntoMap
+        @StringKey(SCREEN_RECORD_TILE_SPEC)
+        fun provideScreenRecordTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(SCREEN_RECORD_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.qs_screen_record_icon_off,
+                        labelRes = R.string.quick_settings_screen_record_label,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+
+        /** Inject ScreenRecord Tile into tileViewModelMap in QSModule */
+        @Provides
+        @IntoMap
+        @StringKey(SCREEN_RECORD_TILE_SPEC)
+        fun provideScreenRecordTileViewModel(
+            factory: QSTileViewModelFactory.Static<ScreenRecordTileModel>,
+            mapper: ScreenRecordTileMapper,
+            stateInteractor: ScreenRecordTileDataInteractor,
+            userActionInteractor: ScreenRecordTileUserActionInteractor
+        ): QSTileViewModel =
+            factory.create(
+                TileSpec.create(SCREEN_RECORD_TILE_SPEC),
+                userActionInteractor,
+                stateInteractor,
+                mapper,
+            )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt
new file mode 100644
index 0000000..caa67df
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionExecutor.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.app.ActivityOptions
+import android.app.BroadcastOptions
+import android.app.ExitTransitionCoordinator
+import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.UserHandle
+import android.util.Log
+import android.util.Pair
+import android.view.View
+import android.view.Window
+import com.android.app.tracing.coroutines.launch
+import com.android.internal.app.ChooserActivity
+import com.android.systemui.dagger.qualifiers.Application
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.CoroutineScope
+
+class ActionExecutor
+@AssistedInject
+constructor(
+    private val intentExecutor: ActionIntentExecutor,
+    @Application private val applicationScope: CoroutineScope,
+    @Assisted val window: Window,
+    @Assisted val transitionView: View,
+    @Assisted val onDismiss: (() -> Unit)
+) {
+
+    var isPendingSharedTransition = false
+        private set
+
+    fun startSharedTransition(intent: Intent, user: UserHandle, overrideTransition: Boolean) {
+        isPendingSharedTransition = true
+        val windowTransition = createWindowTransition()
+        applicationScope.launch("$TAG#launchIntentAsync") {
+            intentExecutor.launchIntent(
+                intent,
+                user,
+                overrideTransition,
+                windowTransition.first,
+                windowTransition.second
+            )
+        }
+    }
+
+    fun sendPendingIntent(pendingIntent: PendingIntent) {
+        try {
+            val options = BroadcastOptions.makeBasic()
+            options.setInteractive(true)
+            options.setPendingIntentBackgroundActivityStartMode(
+                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+            )
+            pendingIntent.send(options.toBundle())
+            onDismiss.invoke()
+        } catch (e: PendingIntent.CanceledException) {
+            Log.e(TAG, "Intent cancelled", e)
+        }
+    }
+
+    /**
+     * Supplies the necessary bits for the shared element transition to share sheet. Note that once
+     * called, the action intent to share must be sent immediately after.
+     */
+    private fun createWindowTransition(): Pair<ActivityOptions, ExitTransitionCoordinator> {
+        val callbacks: ExitTransitionCallbacks =
+            object : ExitTransitionCallbacks {
+                override fun isReturnTransitionAllowed(): Boolean {
+                    return false
+                }
+
+                override fun hideSharedElements() {
+                    isPendingSharedTransition = false
+                    onDismiss.invoke()
+                }
+
+                override fun onFinish() {}
+            }
+        return ActivityOptions.startSharedElementAnimation(
+            window,
+            callbacks,
+            null,
+            Pair.create(transitionView, ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME)
+        )
+    }
+
+    @AssistedFactory
+    interface Factory {
+        fun create(window: Window, transitionView: View, onDismiss: (() -> Unit)): ActionExecutor
+    }
+
+    companion object {
+        private const val TAG = "ActionExecutor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 8e9769ab..a0cef52 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -23,7 +23,9 @@
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
+import android.os.UserHandle
 import com.android.systemui.res.R
+import com.android.systemui.screenshot.scroll.LongScreenshotActivity
 
 object ActionIntentCreator {
     /** @return a chooser intent to share the given URI. */
@@ -89,6 +91,14 @@
             .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
     }
 
+    /** @return an Intent to start the LongScreenshotActivity */
+    fun createLongScreenshotIntent(owner: UserHandle, context: Context): Intent {
+        return Intent(context, LongScreenshotActivity::class.java)
+            .putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE, owner)
+            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+    }
+
     private const val EXTRA_EDIT_SOURCE = "edit_source"
     private const val EDIT_SOURCE_SCREENSHOT = "screenshot"
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
index 1f9853b..4eca51d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
@@ -25,7 +25,6 @@
 import android.os.RemoteException
 import android.os.UserHandle
 import android.util.Log
-import android.util.Pair
 import android.view.IRemoteAnimationFinishedCallback
 import android.view.IRemoteAnimationRunner
 import android.view.RemoteAnimationAdapter
@@ -67,20 +66,22 @@
      */
     fun launchIntentAsync(
         intent: Intent,
-        transition: Pair<ActivityOptions, ExitTransitionCoordinator>?,
         user: UserHandle,
         overrideTransition: Boolean,
+        options: ActivityOptions?,
+        transitionCoordinator: ExitTransitionCoordinator?,
     ) {
         applicationScope.launch("$TAG#launchIntentAsync") {
-            launchIntent(intent, transition, user, overrideTransition)
+            launchIntent(intent, user, overrideTransition, options, transitionCoordinator)
         }
     }
 
     suspend fun launchIntent(
         intent: Intent,
-        transition: Pair<ActivityOptions, ExitTransitionCoordinator>?,
         user: UserHandle,
         overrideTransition: Boolean,
+        options: ActivityOptions?,
+        transitionCoordinator: ExitTransitionCoordinator?,
     ) {
         if (screenshotActionDismissSystemWindows()) {
             keyguardController.dismiss()
@@ -90,14 +91,12 @@
         } else {
             dismissKeyguard()
         }
-        transition?.second?.startExit()
+        transitionCoordinator?.startExit()
 
         if (user == myUserHandle()) {
-            withContext(mainDispatcher) {
-                context.startActivity(intent, transition?.first?.toBundle())
-            }
+            withContext(mainDispatcher) { context.startActivity(intent, options?.toBundle()) }
         } else {
-            launchCrossProfileIntent(user, intent, transition?.first?.toBundle())
+            launchCrossProfileIntent(user, intent, options?.toBundle())
         }
 
         if (overrideTransition) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java b/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java
index ab8fc65..12bff49 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/AssistContentRequester.java
@@ -15,6 +15,7 @@
  */
 
 package com.android.systemui.screenshot;
+import android.annotation.Nullable;
 import android.app.ActivityTaskManager;
 import android.app.IActivityTaskManager;
 import android.app.IAssistDataReceiver;
@@ -55,7 +56,7 @@
          * Called when the {@link android.app.assist.AssistContent} of the requested task is
          * available.
          **/
-        void onAssistContentAvailable(AssistContent assistContent);
+        void onAssistContentAvailable(@Nullable AssistContent assistContent);
     }
 
     private final IActivityTaskManager mActivityTaskManager;
@@ -117,15 +118,9 @@
 
         @Override
         public void onHandleAssistData(Bundle data) {
-            if (data == null) {
-                return;
-            }
-
-            final AssistContent content = data.getParcelable(ASSIST_KEY_CONTENT);
-            if (content == null) {
-                Log.e(TAG, "Received AssistData, but no AssistContent found");
-                return;
-            }
+            final AssistContent content = (data == null) ? null
+                    : data.getParcelable(
+                            ASSIST_KEY_CONTENT, AssistContent.class);
 
             AssistContentRequester requester = mParentRef.get();
             if (requester != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
index 6224e1b..afb0280a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenshot;
 
+import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
 
@@ -29,4 +30,9 @@
     static ScreenshotNotificationSmartActionsProvider providesScrnshtNotifSmartActionsProvider() {
         return new ScreenshotNotificationSmartActionsProvider();
     }
+
+    /** */
+    @Binds
+    ScreenshotActionsProvider.Factory bindScreenshotActionsProviderFactory(
+            DefaultScreenshotActionsProvider.Factory defaultScreenshotActionsProviderFactory);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
index ca0a539..07e143a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
@@ -16,54 +16,43 @@
 
 package com.android.systemui.screenshot
 
-import android.app.ActivityOptions
-import android.app.BroadcastOptions
-import android.app.ExitTransitionCoordinator
-import android.app.PendingIntent
+import android.app.assist.AssistContent
 import android.content.Context
-import android.content.Intent
-import android.os.Process
-import android.os.UserHandle
-import android.provider.DeviceConfig
 import android.util.Log
-import android.util.Pair
 import androidx.appcompat.content.res.AppCompatResources
-import com.android.app.tracing.coroutines.launch
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
 import com.android.internal.logging.UiEventLogger
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.log.DebugLogger.debugLog
 import com.android.systemui.res.R
 import com.android.systemui.screenshot.ActionIntentCreator.createEdit
 import com.android.systemui.screenshot.ActionIntentCreator.createShareWithSubject
-import com.android.systemui.screenshot.ScreenshotController.SavedImageData
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_EDIT_TAPPED
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SHARE_TAPPED
-import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED
-import com.android.systemui.screenshot.ui.viewmodel.ActionButtonViewModel
+import com.android.systemui.screenshot.ui.viewmodel.ActionButtonAppearance
 import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
-import java.text.DateFormat
-import java.util.Date
-import kotlinx.coroutines.CoroutineScope
 
 /**
  * Provides actions for screenshots. This class can be overridden by a vendor-specific SysUI
  * implementation.
  */
 interface ScreenshotActionsProvider {
-    fun setCompletedScreenshot(result: SavedImageData)
-    fun isPendingSharedTransition(): Boolean
+    fun onScrollChipReady(onClick: Runnable)
+    fun setCompletedScreenshot(result: ScreenshotSavedResult)
+
+    /**
+     * Provide the AssistContent for the focused task if available, null if the focused task isn't
+     * known or didn't return data.
+     */
+    fun onAssistContent(assistContent: AssistContent?) {}
 
     interface Factory {
         fun create(
             request: ScreenshotData,
             requestId: String,
-            windowTransition: () -> Pair<ActivityOptions, ExitTransitionCoordinator>,
-            requestDismissal: () -> Unit,
+            actionExecutor: ActionExecutor,
         ): ScreenshotActionsProvider
     }
 }
@@ -73,182 +62,98 @@
 constructor(
     private val context: Context,
     private val viewModel: ScreenshotViewModel,
-    private val actionExecutor: ActionIntentExecutor,
-    private val smartActionsProvider: SmartActionsProvider,
     private val uiEventLogger: UiEventLogger,
-    @Application private val applicationScope: CoroutineScope,
     @Assisted val request: ScreenshotData,
     @Assisted val requestId: String,
-    @Assisted val windowTransition: () -> Pair<ActivityOptions, ExitTransitionCoordinator>,
-    @Assisted val requestDismissal: () -> Unit,
+    @Assisted val actionExecutor: ActionExecutor,
 ) : ScreenshotActionsProvider {
-    private var pendingAction: ((SavedImageData) -> Unit)? = null
-    private var result: SavedImageData? = null
-    private var isPendingSharedTransition = false
+    private var pendingAction: ((ScreenshotSavedResult) -> Unit)? = null
+    private var result: ScreenshotSavedResult? = null
 
     init {
         viewModel.setPreviewAction {
             debugLog(LogConfig.DEBUG_ACTIONS) { "Preview tapped" }
             uiEventLogger.log(SCREENSHOT_PREVIEW_TAPPED, 0, request.packageNameString)
             onDeferrableActionTapped { result ->
-                startSharedTransition(createEdit(result.uri, context), true)
+                actionExecutor.startSharedTransition(
+                    createEdit(result.uri, context),
+                    result.user,
+                    true
+                )
             }
         }
         viewModel.addAction(
-            ActionButtonViewModel(
+            ActionButtonAppearance(
                 AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_edit),
                 context.resources.getString(R.string.screenshot_edit_label),
                 context.resources.getString(R.string.screenshot_edit_description),
-            ) {
-                debugLog(LogConfig.DEBUG_ACTIONS) { "Edit tapped" }
-                uiEventLogger.log(SCREENSHOT_EDIT_TAPPED, 0, request.packageNameString)
-                onDeferrableActionTapped { result ->
-                    startSharedTransition(createEdit(result.uri, context), true)
-                }
+            )
+        ) {
+            debugLog(LogConfig.DEBUG_ACTIONS) { "Edit tapped" }
+            uiEventLogger.log(SCREENSHOT_EDIT_TAPPED, 0, request.packageNameString)
+            onDeferrableActionTapped { result ->
+                actionExecutor.startSharedTransition(
+                    createEdit(result.uri, context),
+                    result.user,
+                    true
+                )
             }
-        )
+        }
+
         viewModel.addAction(
-            ActionButtonViewModel(
+            ActionButtonAppearance(
                 AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_share),
                 context.resources.getString(R.string.screenshot_share_label),
                 context.resources.getString(R.string.screenshot_share_description),
-            ) {
-                debugLog(LogConfig.DEBUG_ACTIONS) { "Share tapped" }
-                uiEventLogger.log(SCREENSHOT_SHARE_TAPPED, 0, request.packageNameString)
-                onDeferrableActionTapped { result ->
-                    startSharedTransition(createShareWithSubject(result.uri, result.subject), false)
-                }
-            }
-        )
-        if (smartActionsEnabled(request.userHandle ?: Process.myUserHandle())) {
-            smartActionsProvider.requestQuickShare(request, requestId) { quickShare ->
-                if (!quickShare.actionIntent.isImmutable) {
-                    viewModel.addAction(
-                        ActionButtonViewModel(
-                            quickShare.getIcon().loadDrawable(context),
-                            quickShare.title,
-                            quickShare.title
-                        ) {
-                            debugLog(LogConfig.DEBUG_ACTIONS) { "Quickshare tapped" }
-                            onDeferrableActionTapped { result ->
-                                uiEventLogger.log(
-                                    SCREENSHOT_SMART_ACTION_TAPPED,
-                                    0,
-                                    request.packageNameString
-                                )
-                                sendPendingIntent(
-                                    smartActionsProvider
-                                        .wrapIntent(
-                                            quickShare,
-                                            result.uri,
-                                            result.subject,
-                                            requestId
-                                        )
-                                        .actionIntent
-                                )
-                            }
-                        }
-                    )
-                } else {
-                    Log.w(TAG, "Received immutable quick share pending intent; ignoring")
-                }
-            }
-        }
-    }
-
-    override fun setCompletedScreenshot(result: SavedImageData) {
-        if (this.result != null) {
-            Log.e(TAG, "Got a second completed screenshot for existing request!")
-            return
-        }
-        if (result.uri == null || result.owner == null || result.imageTime == null) {
-            Log.e(TAG, "Invalid result provided!")
-            return
-        }
-        if (result.subject == null) {
-            result.subject = getSubjectString(result.imageTime)
-        }
-        this.result = result
-        pendingAction?.invoke(result)
-        if (smartActionsEnabled(result.owner)) {
-            smartActionsProvider.requestSmartActions(request, requestId, result) { smartActions ->
-                viewModel.addActions(
-                    smartActions.map {
-                        ActionButtonViewModel(
-                            it.getIcon().loadDrawable(context),
-                            it.title,
-                            it.title
-                        ) {
-                            sendPendingIntent(it.actionIntent)
-                        }
-                    }
+            )
+        ) {
+            debugLog(LogConfig.DEBUG_ACTIONS) { "Share tapped" }
+            uiEventLogger.log(SCREENSHOT_SHARE_TAPPED, 0, request.packageNameString)
+            onDeferrableActionTapped { result ->
+                actionExecutor.startSharedTransition(
+                    createShareWithSubject(result.uri, result.subject),
+                    result.user,
+                    false
                 )
             }
         }
     }
 
-    override fun isPendingSharedTransition(): Boolean {
-        return isPendingSharedTransition
+    override fun onScrollChipReady(onClick: Runnable) {
+        viewModel.addAction(
+            ActionButtonAppearance(
+                AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_scroll),
+                context.resources.getString(R.string.screenshot_scroll_label),
+                context.resources.getString(R.string.screenshot_scroll_label),
+            )
+        ) {
+            onClick.run()
+        }
     }
 
-    private fun onDeferrableActionTapped(onResult: (SavedImageData) -> Unit) {
+    override fun setCompletedScreenshot(result: ScreenshotSavedResult) {
+        if (this.result != null) {
+            Log.e(TAG, "Got a second completed screenshot for existing request!")
+            return
+        }
+        this.result = result
+        pendingAction?.invoke(result)
+    }
+
+    private fun onDeferrableActionTapped(onResult: (ScreenshotSavedResult) -> Unit) {
         result?.let { onResult.invoke(it) } ?: run { pendingAction = onResult }
     }
 
-    private fun startSharedTransition(intent: Intent, overrideTransition: Boolean) {
-        val user =
-            result?.owner
-                ?: run {
-                    Log.wtf(TAG, "User handle not provided in screenshot result! Result: $result")
-                    return
-                }
-        isPendingSharedTransition = true
-        applicationScope.launch("$TAG#launchIntentAsync") {
-            actionExecutor.launchIntent(intent, windowTransition.invoke(), user, overrideTransition)
-        }
-    }
-
-    private fun sendPendingIntent(pendingIntent: PendingIntent) {
-        try {
-            val options = BroadcastOptions.makeBasic()
-            options.setInteractive(true)
-            options.setPendingIntentBackgroundActivityStartMode(
-                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
-            )
-            pendingIntent.send(options.toBundle())
-            requestDismissal.invoke()
-        } catch (e: PendingIntent.CanceledException) {
-            Log.e(TAG, "Intent cancelled", e)
-        }
-    }
-
-    private fun smartActionsEnabled(user: UserHandle): Boolean {
-        val savingToOtherUser = user != Process.myUserHandle()
-        return !savingToOtherUser &&
-            DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS,
-                true
-            )
-    }
-
-    private fun getSubjectString(imageTime: Long): String {
-        val subjectDate = DateFormat.getDateTimeInstance().format(Date(imageTime))
-        return String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate)
-    }
-
     @AssistedFactory
     interface Factory : ScreenshotActionsProvider.Factory {
         override fun create(
             request: ScreenshotData,
             requestId: String,
-            windowTransition: () -> Pair<ActivityOptions, ExitTransitionCoordinator>,
-            requestDismissal: () -> Unit,
+            actionExecutor: ActionExecutor,
         ): DefaultScreenshotActionsProvider
     }
 
     companion object {
         private const val TAG = "ScreenshotActionsProvider"
-        private const val SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 70d1129..501a4a7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -19,7 +19,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
 
-import static com.android.systemui.Flags.screenshotShelfUi;
+import static com.android.systemui.Flags.screenshotShelfUi2;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT;
@@ -34,7 +34,6 @@
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ExitTransitionCoordinator;
 import android.app.ICompatCameraControlCallback;
@@ -51,7 +50,6 @@
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -59,17 +57,12 @@
 import android.util.Log;
 import android.util.Pair;
 import android.view.Display;
-import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationRunner;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationTarget;
 import android.view.ScrollCaptureResponse;
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
 import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
 import android.widget.Toast;
 import android.window.WindowContext;
 
@@ -84,10 +77,7 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.res.R;
 import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback;
-import com.android.systemui.screenshot.scroll.LongScreenshotActivity;
-import com.android.systemui.screenshot.scroll.LongScreenshotData;
-import com.android.systemui.screenshot.scroll.ScrollCaptureClient;
-import com.android.systemui.screenshot.scroll.ScrollCaptureController;
+import com.android.systemui.screenshot.scroll.ScrollCaptureExecutor;
 import com.android.systemui.util.Assert;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -100,12 +90,9 @@
 
 import java.util.List;
 import java.util.UUID;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
 import java.util.function.Consumer;
 
 import javax.inject.Provider;
@@ -117,34 +104,6 @@
 public class ScreenshotController {
     private static final String TAG = logTag(ScreenshotController.class);
 
-    private ScrollCaptureResponse mLastScrollCaptureResponse;
-    private ListenableFuture<ScrollCaptureResponse> mLastScrollCaptureRequest;
-
-    /**
-     * This is effectively a no-op, but we need something non-null to pass in, in order to
-     * successfully override the pending activity entrance animation.
-     */
-    static final IRemoteAnimationRunner.Stub SCREENSHOT_REMOTE_RUNNER =
-            new IRemoteAnimationRunner.Stub() {
-                @Override
-                public void onAnimationStart(
-                        @WindowManager.TransitionOldType int transit,
-                        RemoteAnimationTarget[] apps,
-                        RemoteAnimationTarget[] wallpapers,
-                        RemoteAnimationTarget[] nonApps,
-                        final IRemoteAnimationFinishedCallback finishedCallback) {
-                    try {
-                        finishedCallback.onAnimationFinished();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Error finishing screenshot remote animation", e);
-                    }
-                }
-
-                @Override
-                public void onAnimationCancelled() {
-                }
-            };
-
     /**
      * POD used in the AsyncTask which saves an image in the background.
      */
@@ -217,11 +176,12 @@
 
     // These strings are used for communicating the action invoked to
     // ScreenshotNotificationSmartActionsProvider.
-    static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
-    static final String EXTRA_ID = "android:screenshot_id";
-    static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
-    static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
-    static final String EXTRA_ACTION_INTENT_FILLIN = "android:screenshot_action_intent_fillin";
+    public static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
+    public static final String EXTRA_ID = "android:screenshot_id";
+    public static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
+    public static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
+    public static final String EXTRA_ACTION_INTENT_FILLIN =
+            "android:screenshot_action_intent_fillin";
 
 
     // From WizardManagerHelper.java
@@ -242,22 +202,20 @@
     private final ExecutorService mBgExecutor;
     private final BroadcastSender mBroadcastSender;
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final ActionExecutor mActionExecutor;
 
     private final WindowManager mWindowManager;
     private final WindowManager.LayoutParams mWindowLayoutParams;
     @Nullable
     private final ScreenshotSoundController mScreenshotSoundController;
-    private final ScrollCaptureClient mScrollCaptureClient;
     private final PhoneWindow mWindow;
     private final DisplayManager mDisplayManager;
     private final int mDisplayId;
-    private final ScrollCaptureController mScrollCaptureController;
-    private final LongScreenshotData mLongScreenshotHolder;
-    private final boolean mIsLowRamDevice;
+    private final ScrollCaptureExecutor mScrollCaptureExecutor;
     private final ScreenshotNotificationSmartActionsProvider
             mScreenshotNotificationSmartActionsProvider;
     private final TimeoutHandler mScreenshotHandler;
-    private final ActionIntentExecutor mActionExecutor;
+    private final ActionIntentExecutor mActionIntentExecutor;
     private final UserManager mUserManager;
     private final AssistContentRequester mAssistContentRequester;
 
@@ -299,19 +257,17 @@
             ScreenshotActionsProvider.Factory actionsProviderFactory,
             ScreenshotSmartActions screenshotSmartActions,
             ScreenshotNotificationsController.Factory screenshotNotificationsControllerFactory,
-            ScrollCaptureClient scrollCaptureClient,
             UiEventLogger uiEventLogger,
             ImageExporter imageExporter,
             ImageCapture imageCapture,
             @Main Executor mainExecutor,
-            ScrollCaptureController scrollCaptureController,
-            LongScreenshotData longScreenshotHolder,
-            ActivityManager activityManager,
+            ScrollCaptureExecutor scrollCaptureExecutor,
             TimeoutHandler timeoutHandler,
             BroadcastSender broadcastSender,
             BroadcastDispatcher broadcastDispatcher,
             ScreenshotNotificationSmartActionsProvider screenshotNotificationSmartActionsProvider,
-            ActionIntentExecutor actionExecutor,
+            ActionIntentExecutor actionIntentExecutor,
+            ActionExecutor.Factory actionExecutorFactory,
             UserManager userManager,
             AssistContentRequester assistContentRequester,
             MessageContainerController messageContainerController,
@@ -322,14 +278,11 @@
         mScreenshotSmartActions = screenshotSmartActions;
         mActionsProviderFactory = actionsProviderFactory;
         mNotificationsController = screenshotNotificationsControllerFactory.create(displayId);
-        mScrollCaptureClient = scrollCaptureClient;
         mUiEventLogger = uiEventLogger;
         mImageExporter = imageExporter;
         mImageCapture = imageCapture;
         mMainExecutor = mainExecutor;
-        mScrollCaptureController = scrollCaptureController;
-        mLongScreenshotHolder = longScreenshotHolder;
-        mIsLowRamDevice = activityManager.isLowRamDevice();
+        mScrollCaptureExecutor = scrollCaptureExecutor;
         mScreenshotNotificationSmartActionsProvider = screenshotNotificationSmartActionsProvider;
         mBgExecutor = Executors.newSingleThreadExecutor();
         mBroadcastSender = broadcastSender;
@@ -345,7 +298,7 @@
         final Context displayContext = context.createDisplayContext(getDisplay());
         mContext = (WindowContext) displayContext.createWindowContext(TYPE_SCREENSHOT, null);
         mFlags = flags;
-        mActionExecutor = actionExecutor;
+        mActionIntentExecutor = actionIntentExecutor;
         mUserManager = userManager;
         mMessageContainerController = messageContainerController;
         mAssistContentRequester = assistContentRequester;
@@ -369,6 +322,12 @@
         mConfigChanges.applyNewConfig(context.getResources());
         reloadAssets();
 
+        mActionExecutor = actionExecutorFactory.create(mWindow, mViewProxy.getScreenshotPreview(),
+                () -> {
+                    requestDismissal(null);
+                    return Unit.INSTANCE;
+                });
+
         // Sound is only reproduced from the controller of the default display.
         if (displayId == Display.DEFAULT_DISPLAY) {
             mScreenshotSoundController = screenshotSoundController.get();
@@ -395,10 +354,10 @@
         Assert.isMainThread();
 
         mCurrentRequestCallback = requestCallback;
-        if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_FULLSCREEN) {
+        if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_FULLSCREEN
+                && screenshot.getBitmap() == null) {
             Rect bounds = getFullScreenRect();
-            screenshot.setBitmap(
-                    mImageCapture.captureDisplay(mDisplayId, bounds));
+            screenshot.setBitmap(mImageCapture.captureDisplay(mDisplayId, bounds));
             screenshot.setScreenBounds(bounds);
         }
 
@@ -444,15 +403,19 @@
             return;
         }
 
-        if (screenshotShelfUi()) {
+        if (screenshotShelfUi2()) {
             final UUID requestId = UUID.randomUUID();
             final String screenshotId = String.format("Screenshot_%s", requestId);
-            mActionsProvider = mActionsProviderFactory.create(screenshot, screenshotId,
-                    this::createWindowTransition, () -> {
-                        mViewProxy.requestDismissal(null);
-                        return Unit.INSTANCE;
-                    });
+            mActionsProvider = mActionsProviderFactory.create(
+                    screenshot, screenshotId, mActionExecutor);
             saveScreenshotInBackground(screenshot, requestId, finisher);
+
+            if (screenshot.getTaskId() >= 0) {
+                mAssistContentRequester.requestAssistContent(screenshot.getTaskId(),
+                        assistContent -> mActionsProvider.onAssistContent(assistContent));
+            } else {
+                mActionsProvider.onAssistContent(null);
+            }
         } else {
             saveScreenshotInWorkerThread(screenshot.getUserHandle(), finisher,
                     this::showUiOnActionsReady, this::showUiOnQuickShareActionReady);
@@ -491,7 +454,7 @@
         // ignore system bar insets for the purpose of window layout
         mWindow.getDecorView().setOnApplyWindowInsetsListener(
                 (v, insets) -> WindowInsets.CONSUMED);
-        if (!screenshotShelfUi()) {
+        if (!screenshotShelfUi2()) {
             mScreenshotHandler.cancelTimeout(); // restarted after animation
         }
     }
@@ -540,8 +503,8 @@
     }
 
     boolean isPendingSharedTransition() {
-        if (screenshotShelfUi()) {
-            return mActionsProvider != null && mActionsProvider.isPendingSharedTransition();
+        if (screenshotShelfUi2()) {
+            return mActionExecutor.isPendingSharedTransition();
         } else {
             return mViewProxy.isPendingSharedTransition();
         }
@@ -556,7 +519,7 @@
         removeWindow();
         releaseMediaPlayer();
         releaseContext();
-        mBgExecutor.shutdownNow();
+        mBgExecutor.shutdown();
     }
 
     /**
@@ -592,8 +555,9 @@
 
             @Override
             public void onAction(Intent intent, UserHandle owner, boolean overrideTransition) {
-                mActionExecutor.launchIntentAsync(
-                        intent, createWindowTransition(), owner, overrideTransition);
+                Pair<ActivityOptions, ExitTransitionCoordinator> exit = createWindowTransition();
+                mActionIntentExecutor.launchIntentAsync(
+                        intent, owner, overrideTransition, exit.first, exit.second);
             }
 
             @Override
@@ -630,9 +594,8 @@
                                 mViewProxy.hideScrollChip();
                                 // Delay scroll capture eval a bit to allow the underlying activity
                                 // to set up in the new orientation.
-                                mScreenshotHandler.postDelayed(() -> {
-                                    requestScrollCapture(owner);
-                                }, 150);
+                                mScreenshotHandler.postDelayed(
+                                        () -> requestScrollCapture(owner), 150);
                                 mViewProxy.updateInsets(
                                         mWindowManager.getCurrentWindowMetrics().getWindowInsets());
                                 // Screenshot animation calculations won't be valid anymore,
@@ -655,119 +618,51 @@
     }
 
     private void requestScrollCapture(UserHandle owner) {
-        if (!allowLongScreenshots()) {
-            Log.d(TAG, "Long screenshots not supported on this device");
+        mScrollCaptureExecutor.requestScrollCapture(
+                mDisplayId,
+                mWindow.getDecorView().getWindowToken(),
+                (response) -> {
+                    mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION,
+                            0, response.getPackageName());
+                    if (screenshotShelfUi2() && mActionsProvider != null) {
+                        mActionsProvider.onScrollChipReady(
+                                () -> onScrollButtonClicked(owner, response));
+                    } else {
+                        mViewProxy.showScrollChip(response.getPackageName(),
+                                () -> onScrollButtonClicked(owner, response));
+                    }
+                    return Unit.INSTANCE;
+                }
+        );
+    }
+
+    private void onScrollButtonClicked(UserHandle owner, ScrollCaptureResponse response) {
+        if (DEBUG_INPUT) {
+            Log.d(TAG, "scroll chip tapped");
+        }
+        mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED, 0,
+                response.getPackageName());
+        Bitmap newScreenshot = mImageCapture.captureDisplay(mDisplayId, getFullScreenRect());
+        if (newScreenshot == null) {
+            Log.e(TAG, "Failed to capture current screenshot for scroll transition!");
             return;
         }
-        mScrollCaptureClient.setHostWindowToken(mWindow.getDecorView().getWindowToken());
-        if (mLastScrollCaptureRequest != null) {
-            mLastScrollCaptureRequest.cancel(true);
-        }
-        final ListenableFuture<ScrollCaptureResponse> future = mScrollCaptureClient.request(
-                mDisplayId);
-        mLastScrollCaptureRequest = future;
-        mLastScrollCaptureRequest.addListener(() ->
-                onScrollCaptureResponseReady(future, owner), mMainExecutor);
+        // delay starting scroll capture to make sure scrim is up before the app moves
+        mViewProxy.prepareScrollingTransition(response, mScreenBitmap, newScreenshot,
+                mScreenshotTakenInPortrait, () -> executeBatchScrollCapture(response, owner));
     }
 
-    private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture,
-            UserHandle owner) {
-        try {
-            if (mLastScrollCaptureResponse != null) {
-                mLastScrollCaptureResponse.close();
-                mLastScrollCaptureResponse = null;
-            }
-            if (responseFuture.isCancelled()) {
-                return;
-            }
-            mLastScrollCaptureResponse = responseFuture.get();
-            if (!mLastScrollCaptureResponse.isConnected()) {
-                // No connection means that the target window wasn't found
-                // or that it cannot support scroll capture.
-                Log.d(TAG, "ScrollCapture: " + mLastScrollCaptureResponse.getDescription() + " ["
-                        + mLastScrollCaptureResponse.getWindowTitle() + "]");
-                return;
-            }
-            Log.d(TAG, "ScrollCapture: connected to window ["
-                    + mLastScrollCaptureResponse.getWindowTitle() + "]");
+    private void executeBatchScrollCapture(ScrollCaptureResponse response, UserHandle owner) {
+        mScrollCaptureExecutor.executeBatchScrollCapture(response,
+                () -> {
+                    final Intent intent = ActionIntentCreator.INSTANCE.createLongScreenshotIntent(
+                            owner, mContext);
+                    mActionIntentExecutor.launchIntentAsync(intent, owner, true,
+                            ActivityOptions.makeCustomAnimation(mContext, 0, 0), null);
 
-            final ScrollCaptureResponse response = mLastScrollCaptureResponse;
-            mViewProxy.showScrollChip(response.getPackageName(), /* onClick */ () -> {
-                Bitmap newScreenshot =
-                        mImageCapture.captureDisplay(mDisplayId, getFullScreenRect());
-
-                if (newScreenshot != null) {
-                    // delay starting scroll capture to make sure scrim is up before the app
-                    // moves
-                    mViewProxy.prepareScrollingTransition(
-                            response, mScreenBitmap, newScreenshot, mScreenshotTakenInPortrait,
-                            () -> runBatchScrollCapture(response, owner));
-                } else {
-                    Log.wtf(TAG, "failed to capture current screenshot for scroll transition");
-                }
-            });
-        } catch (InterruptedException | ExecutionException e) {
-            Log.e(TAG, "requestScrollCapture failed", e);
-        }
-    }
-
-    ListenableFuture<ScrollCaptureController.LongScreenshot> mLongScreenshotFuture;
-
-    private void runBatchScrollCapture(ScrollCaptureResponse response, UserHandle owner) {
-        // Clear the reference to prevent close() in dismissScreenshot
-        mLastScrollCaptureResponse = null;
-
-        if (mLongScreenshotFuture != null) {
-            mLongScreenshotFuture.cancel(true);
-        }
-        mLongScreenshotFuture = mScrollCaptureController.run(response);
-        mLongScreenshotFuture.addListener(() -> {
-            ScrollCaptureController.LongScreenshot longScreenshot;
-            try {
-                longScreenshot = mLongScreenshotFuture.get();
-            } catch (CancellationException e) {
-                Log.e(TAG, "Long screenshot cancelled");
-                return;
-            } catch (InterruptedException | ExecutionException e) {
-                Log.e(TAG, "Exception", e);
-                mViewProxy.restoreNonScrollingUi();
-                return;
-            }
-
-            if (longScreenshot.getHeight() == 0) {
-                mViewProxy.restoreNonScrollingUi();
-                return;
-            }
-
-            mLongScreenshotHolder.setLongScreenshot(longScreenshot);
-            mLongScreenshotHolder.setTransitionDestinationCallback(
-                    (transitionDestination, onTransitionEnd) -> {
-                        mViewProxy.startLongScreenshotTransition(
-                                transitionDestination, onTransitionEnd,
-                                longScreenshot);
-                        // TODO: Do this via ActionIntentExecutor instead.
-                        mContext.closeSystemDialogs();
-                    }
-            );
-
-            final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
-            intent.putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE,
-                    owner);
-            intent.setFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
-            mContext.startActivity(intent,
-                    ActivityOptions.makeCustomAnimation(mContext, 0, 0).toBundle());
-            RemoteAnimationAdapter runner = new RemoteAnimationAdapter(
-                    SCREENSHOT_REMOTE_RUNNER, 0, 0);
-            try {
-                WindowManagerGlobal.getWindowManagerService()
-                        .overridePendingAppTransitionRemote(runner,
-                                mDisplayId);
-            } catch (Exception e) {
-                Log.e(TAG, "Error overriding screenshot app transition", e);
-            }
-        }, mMainExecutor);
+                },
+                mViewProxy::restoreNonScrollingUi,
+                mViewProxy::startLongScreenshotTransition);
     }
 
     private void withWindowAttached(Runnable action) {
@@ -912,17 +807,7 @@
     /** Reset screenshot view and then call onCompleteRunnable */
     private void finishDismiss() {
         Log.d(TAG, "finishDismiss");
-        if (mLastScrollCaptureRequest != null) {
-            mLastScrollCaptureRequest.cancel(true);
-            mLastScrollCaptureRequest = null;
-        }
-        if (mLastScrollCaptureResponse != null) {
-            mLastScrollCaptureResponse.close();
-            mLastScrollCaptureResponse = null;
-        }
-        if (mLongScreenshotFuture != null) {
-            mLongScreenshotFuture.cancel(true);
-        }
+        mScrollCaptureExecutor.close();
         if (mCurrentRequestCallback != null) {
             mCurrentRequestCallback.onFinish();
             mCurrentRequestCallback = null;
@@ -935,7 +820,7 @@
     private void saveScreenshotInBackground(
             ScreenshotData screenshot, UUID requestId, Consumer<Uri> finisher) {
         ListenableFuture<ImageExporter.Result> future = mImageExporter.export(mBgExecutor,
-                requestId, screenshot.getBitmap(), screenshot.getUserHandle(), mDisplayId);
+                requestId, screenshot.getBitmap(), screenshot.getUserOrDefault(), mDisplayId);
         future.addListener(() -> {
             try {
                 ImageExporter.Result result = future.get();
@@ -943,12 +828,8 @@
                 logScreenshotResultStatus(result.uri, screenshot.getUserHandle());
                 mScreenshotHandler.resetTimeout();
                 if (result.uri != null) {
-                    final SavedImageData savedImageData = new SavedImageData();
-                    savedImageData.uri = result.uri;
-                    savedImageData.owner = screenshot.getUserHandle();
-                    savedImageData.imageTime = result.timestamp;
-                    mActionsProvider.setCompletedScreenshot(savedImageData);
-                    mViewProxy.setChipIntents(savedImageData);
+                    mActionsProvider.setCompletedScreenshot(new ScreenshotSavedResult(
+                            result.uri, screenshot.getUserOrDefault(), result.timestamp));
                 }
                 if (DEBUG_CALLBACK) {
                     Log.d(TAG, "finished background processing, Calling (Consumer<Uri>) "
@@ -1110,10 +991,6 @@
         return mDisplayManager.getDisplay(mDisplayId);
     }
 
-    private boolean allowLongScreenshots() {
-        return !mIsLowRamDevice;
-    }
-
     private Rect getFullScreenRect() {
         DisplayMetrics displayMetrics = new DisplayMetrics();
         getDisplay().getRealMetrics(displayMetrics);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
index 92e933a..4fdd90b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
@@ -5,6 +5,7 @@
 import android.graphics.Insets
 import android.graphics.Rect
 import android.net.Uri
+import android.os.Process
 import android.os.UserHandle
 import android.view.Display
 import android.view.WindowManager.ScreenshotSource
@@ -31,6 +32,10 @@
     val packageNameString: String
         get() = if (topComponent == null) "" else topComponent!!.packageName
 
+    fun getUserOrDefault(): UserHandle {
+        return userHandle ?: Process.myUserHandle()
+    }
+
     companion object {
         @JvmStatic
         fun fromRequest(request: ScreenshotRequest, displayId: Int = Display.DEFAULT_DISPLAY) =
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
index 3eafbfb..23f05e0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
@@ -44,7 +44,7 @@
     public static final String DEFAULT_ACTION_TYPE = "Smart Action";
 
     /* Define phases of screenshot execution. */
-    protected enum ScreenshotOp {
+    public enum ScreenshotOp {
         OP_UNKNOWN,
         RETRIEVE_SMART_ACTIONS,
         REQUEST_SMART_ACTIONS,
@@ -52,7 +52,7 @@
     }
 
     /* Enum to report success or failure for screenshot execution phases. */
-    protected enum ScreenshotOpStatus {
+    public enum ScreenshotOpStatus {
         OP_STATUS_UNKNOWN,
         SUCCESS,
         ERROR,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt
index 796457d..3ad4075a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt
@@ -17,13 +17,14 @@
 package com.android.systemui.screenshot
 
 /** Processes a screenshot request sent from [ScreenshotHelper]. */
-interface ScreenshotRequestProcessor {
+fun interface ScreenshotRequestProcessor {
     /**
      * Inspects the incoming ScreenshotData, potentially modifying it based upon policy.
      *
-     * @param screenshot the screenshot to process
+     * @param original the screenshot to process
+     * @return a potentially modified screenshot data
      */
-    suspend fun process(screenshot: ScreenshotData): ScreenshotData
+    suspend fun process(original: ScreenshotData): ScreenshotData
 }
 
 /** Exception thrown by [RequestProcessor] if something goes wrong. */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt
new file mode 100644
index 0000000..5b6e7ac
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSavedResult.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.net.Uri
+import android.os.UserHandle
+import java.text.DateFormat
+import java.util.Date
+
+/**
+ * Represents a saved screenshot, with the uri and user it was saved to as well as the time it was
+ * saved.
+ */
+data class ScreenshotSavedResult(val uri: Uri, val user: UserHandle, val imageTime: Long) {
+    val subject: String
+
+    init {
+        val subjectDate = DateFormat.getDateTimeInstance().format(Date(imageTime))
+        subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate)
+    }
+
+    companion object {
+        private const val SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
index 6b9332b..12a3daa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
@@ -28,8 +28,10 @@
 import android.view.View
 import android.view.ViewTreeObserver
 import android.view.WindowInsets
+import android.view.WindowManager
 import android.window.OnBackInvokedCallback
 import android.window.OnBackInvokedDispatcher
+import androidx.core.animation.doOnEnd
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.log.DebugLogger.debugLog
 import com.android.systemui.res.R
@@ -53,6 +55,7 @@
 constructor(
     private val logger: UiEventLogger,
     private val viewModel: ScreenshotViewModel,
+    private val windowManager: WindowManager,
     @Assisted private val context: Context,
     @Assisted private val displayId: Int
 ) : ScreenshotViewProxy {
@@ -75,10 +78,26 @@
     private val animationController = ScreenshotAnimationController(view)
 
     init {
-        ScreenshotShelfViewBinder.bind(view, viewModel, LayoutInflater.from(context))
+        ScreenshotShelfViewBinder.bind(
+            view,
+            viewModel,
+            LayoutInflater.from(context),
+            onDismissalRequested = { event, velocity -> requestDismissal(event, velocity) },
+            onDismissalCancelled = { animationController.getSwipeReturnAnimation().start() }
+        )
         addPredictiveBackListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
         setOnKeyListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
         debugLog(DEBUG_WINDOW) { "adding OnComputeInternalInsetsListener" }
+        view.viewTreeObserver.addOnComputeInternalInsetsListener { info ->
+            val touchableRegion =
+                view.getTouchRegion(
+                    windowManager.currentWindowMetrics.windowInsets.getInsets(
+                        WindowInsets.Type.systemGestures()
+                    )
+                )
+            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION)
+            info.touchableRegion.set(touchableRegion)
+        }
         screenshotPreview = view.screenshotPreview
     }
 
@@ -91,7 +110,10 @@
     override fun updateOrientation(insets: WindowInsets) {}
 
     override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
-        return animationController.getEntranceAnimation()
+        val entrance = animationController.getEntranceAnimation(screenRect, showFlash)
+        // reset the timeout when animation finishes
+        entrance.doOnEnd { callbacks?.onUserInteraction() }
+        return entrance
     }
 
     override fun addQuickShareChip(quickShareAction: Notification.Action) {}
@@ -99,6 +121,10 @@
     override fun setChipIntents(imageData: SavedImageData) {}
 
     override fun requestDismissal(event: ScreenshotEvent?) {
+        requestDismissal(event, null)
+    }
+
+    private fun requestDismissal(event: ScreenshotEvent?, velocity: Float?) {
         debugLog(DEBUG_DISMISS) { "screenshot dismissal requested: $event" }
 
         // If we're already animating out, don't restart the animation
@@ -107,7 +133,7 @@
             return
         }
         event?.let { logger.log(it, 0, packageName) }
-        val animator = animationController.getExitAnimation()
+        val animator = animationController.getSwipeDismissAnimation(velocity)
         animator.addListener(
             object : AnimatorListenerAdapter() {
                 override fun onAnimationStart(animator: Animator) {
@@ -194,6 +220,7 @@
             }
         )
     }
+
     private fun setOnKeyListener(onDismissRequested: (ScreenshotEvent) -> Unit) {
         view.setOnKeyListener(
             object : View.OnKeyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index 65e8457..59e38a8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -259,16 +259,8 @@
         if (DEBUG_SCROLL) {
             Log.d(TAG, "Showing Scroll option");
         }
-        mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION, 0, packageName);
         mScrollChip.setVisibility(VISIBLE);
-        mScrollChip.setOnClickListener((v) -> {
-            if (DEBUG_INPUT) {
-                Log.d(TAG, "scroll chip tapped");
-            }
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED, 0,
-                    packageName);
-            onClick.run();
-        });
+        mScrollChip.setOnClickListener((v) -> onClick.run());
     }
 
     @Override // ViewTreeObserver.OnComputeInternalInsetsListener
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt
deleted file mode 100644
index 2eaff86..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsProvider.kt
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import android.app.Notification
-import android.app.PendingIntent
-import android.content.ClipData
-import android.content.ClipDescription
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.graphics.Bitmap
-import android.net.Uri
-import android.os.Bundle
-import android.os.Process
-import android.os.SystemClock
-import android.os.UserHandle
-import android.provider.DeviceConfig
-import android.util.Log
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-import com.android.systemui.log.DebugLogger.debugLog
-import com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS
-import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.QUICK_SHARE_ACTION
-import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.REGULAR_SMART_ACTIONS
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.TimeoutException
-import javax.inject.Inject
-import kotlin.random.Random
-
-/**
- * Handle requesting smart/quickshare actions from the provider and executing an action when the
- * action futures complete.
- */
-class SmartActionsProvider
-@Inject
-constructor(
-    private val context: Context,
-    private val smartActions: ScreenshotNotificationSmartActionsProvider,
-) {
-    /**
-     * Requests quick share action for a given screenshot.
-     *
-     * @param data the ScreenshotData request
-     * @param id the request id for the screenshot
-     * @param onAction callback to run when quick share action is returned
-     */
-    fun requestQuickShare(
-        data: ScreenshotData,
-        id: String,
-        onAction: (Notification.Action) -> Unit
-    ) {
-        val bitmap = data.bitmap ?: return
-        val user = data.userHandle ?: return
-        val component = data.topComponent ?: ComponentName("", "")
-        requestQuickShareAction(id, bitmap, component, user) { quickShareAction ->
-            onAction(quickShareAction)
-        }
-    }
-
-    /**
-     * Requests smart actions for a given screenshot.
-     *
-     * @param data the ScreenshotData request
-     * @param id the request id for the screenshot
-     * @param result the data for the saved image
-     * @param onActions callback to run when actions are returned
-     */
-    fun requestSmartActions(
-        data: ScreenshotData,
-        id: String,
-        result: ScreenshotController.SavedImageData,
-        onActions: (List<Notification.Action>) -> Unit
-    ) {
-        val bitmap = data.bitmap ?: return
-        val user = data.userHandle ?: return
-        val uri = result.uri ?: return
-        val component = data.topComponent ?: ComponentName("", "")
-        requestSmartActions(id, bitmap, component, user, uri, REGULAR_SMART_ACTIONS) { actions ->
-            onActions(actions)
-        }
-    }
-
-    /**
-     * Wraps the given quick share action in a broadcast intent.
-     *
-     * @param quickShare the quick share action to wrap
-     * @param uri the URI of the saved screenshot
-     * @param subject the subject/title for the screenshot
-     * @param id the request ID of the screenshot
-     * @return the wrapped action
-     */
-    fun wrapIntent(
-        quickShare: Notification.Action,
-        uri: Uri,
-        subject: String,
-        id: String
-    ): Notification.Action {
-        val wrappedIntent: Intent =
-            Intent(context, SmartActionsReceiver::class.java)
-                .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, quickShare.actionIntent)
-                .putExtra(
-                    ScreenshotController.EXTRA_ACTION_INTENT_FILLIN,
-                    createFillInIntent(uri, subject)
-                )
-                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
-        val extras: Bundle = quickShare.extras
-        val actionType =
-            extras.getString(
-                ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
-                ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE
-            )
-        // We only query for quick share actions when smart actions are enabled, so we can assert
-        // that it's true here.
-        wrappedIntent
-            .putExtra(ScreenshotController.EXTRA_ACTION_TYPE, actionType)
-            .putExtra(ScreenshotController.EXTRA_ID, id)
-            .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, true)
-        val broadcastIntent =
-            PendingIntent.getBroadcast(
-                context,
-                Random.nextInt(),
-                wrappedIntent,
-                PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
-            )
-        return Notification.Action.Builder(quickShare.getIcon(), quickShare.title, broadcastIntent)
-            .setContextual(true)
-            .addExtras(extras)
-            .build()
-    }
-
-    private fun createFillInIntent(uri: Uri, subject: String): Intent {
-        val fillIn = Intent()
-        fillIn.setType("image/png")
-        fillIn.putExtra(Intent.EXTRA_STREAM, uri)
-        fillIn.putExtra(Intent.EXTRA_SUBJECT, subject)
-        // Include URI in ClipData also, so that grantPermission picks it up.
-        // We don't use setData here because some apps interpret this as "to:".
-        val clipData =
-            ClipData(ClipDescription("content", arrayOf("image/png")), ClipData.Item(uri))
-        fillIn.clipData = clipData
-        fillIn.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
-        return fillIn
-    }
-
-    private fun requestQuickShareAction(
-        id: String,
-        image: Bitmap,
-        component: ComponentName,
-        user: UserHandle,
-        timeoutMs: Long = 500,
-        onAction: (Notification.Action) -> Unit
-    ) {
-        requestSmartActions(id, image, component, user, null, QUICK_SHARE_ACTION, timeoutMs) {
-            it.firstOrNull()?.let { action -> onAction(action) }
-        }
-    }
-
-    private fun requestSmartActions(
-        id: String,
-        image: Bitmap,
-        component: ComponentName,
-        user: UserHandle,
-        uri: Uri?,
-        actionType: ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType,
-        timeoutMs: Long = 500,
-        onActions: (List<Notification.Action>) -> Unit
-    ) {
-        val enabled = isSmartActionsEnabled(user)
-        debugLog(DEBUG_ACTIONS) {
-            ("getSmartActionsFuture id=$id, uri=$uri, provider=$smartActions, " +
-                "actionType=$actionType, smartActionsEnabled=$enabled, userHandle=$user")
-        }
-        if (!enabled) {
-            debugLog(DEBUG_ACTIONS) { "Screenshot Intelligence not enabled, returning empty list" }
-            onActions(listOf())
-            return
-        }
-        if (image.config != Bitmap.Config.HARDWARE) {
-            debugLog(DEBUG_ACTIONS) {
-                "Bitmap expected: Hardware, Bitmap found: ${image.config}. Returning empty list."
-            }
-            onActions(listOf())
-            return
-        }
-        var smartActionsFuture: CompletableFuture<List<Notification.Action>>
-        val startTimeMs = SystemClock.uptimeMillis()
-        try {
-            smartActionsFuture =
-                smartActions.getActions(id, uri, image, component, actionType, user)
-        } catch (e: Throwable) {
-            val waitTimeMs = SystemClock.uptimeMillis() - startTimeMs
-            debugLog(DEBUG_ACTIONS, error = e) {
-                "Failed to get future for screenshot notification smart actions."
-            }
-            notifyScreenshotOp(
-                id,
-                ScreenshotNotificationSmartActionsProvider.ScreenshotOp.REQUEST_SMART_ACTIONS,
-                ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR,
-                waitTimeMs
-            )
-            onActions(listOf())
-            return
-        }
-        try {
-            val actions = smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)
-            val waitTimeMs = SystemClock.uptimeMillis() - startTimeMs
-            debugLog(DEBUG_ACTIONS) {
-                ("Got ${actions.size} smart actions. Wait time: $waitTimeMs ms, " +
-                    "actionType=$actionType")
-            }
-            notifyScreenshotOp(
-                id,
-                ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
-                ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS,
-                waitTimeMs
-            )
-            onActions(actions)
-        } catch (e: Throwable) {
-            val waitTimeMs = SystemClock.uptimeMillis() - startTimeMs
-            debugLog(DEBUG_ACTIONS, error = e) {
-                "Error getting smart actions. Wait time: $waitTimeMs ms, actionType=$actionType"
-            }
-            val status =
-                if (e is TimeoutException) {
-                    ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT
-                } else {
-                    ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR
-                }
-            notifyScreenshotOp(
-                id,
-                ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
-                status,
-                waitTimeMs
-            )
-            onActions(listOf())
-        }
-    }
-
-    private fun notifyScreenshotOp(
-        screenshotId: String,
-        op: ScreenshotNotificationSmartActionsProvider.ScreenshotOp,
-        status: ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus,
-        durationMs: Long
-    ) {
-        debugLog(DEBUG_ACTIONS) {
-            "$smartActions notifyOp: $op id=$screenshotId, status=$status, durationMs=$durationMs"
-        }
-        try {
-            smartActions.notifyOp(screenshotId, op, status, durationMs)
-        } catch (e: Throwable) {
-            Log.e(TAG, "Error in notifyScreenshotOp: ", e)
-        }
-    }
-    private fun isSmartActionsEnabled(user: UserHandle): Boolean {
-        // Smart actions don't yet work for cross-user saves.
-        val savingToOtherUser = user !== Process.myUserHandle()
-        val actionsEnabled =
-            DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS,
-                true
-            )
-        return !savingToOtherUser && actionsEnabled
-    }
-
-    companion object {
-        private const val TAG = "SmartActionsProvider"
-        private const val SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
index 92d3e55..e56a4f4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
@@ -22,7 +22,7 @@
 interface TakeScreenshotExecutor {
     suspend fun executeScreenshots(
         screenshotRequest: ScreenshotRequest,
-        onSaved: (Uri) -> Unit,
+        onSaved: (Uri?) -> Unit,
         requestCallback: RequestCallback
     )
     fun onCloseSystemDialogsReceived()
@@ -30,7 +30,7 @@
     fun onDestroy()
     fun executeScreenshotsAsync(
         screenshotRequest: ScreenshotRequest,
-        onSaved: Consumer<Uri>,
+        onSaved: Consumer<Uri?>,
         requestCallback: RequestCallback
     )
 }
@@ -65,7 +65,7 @@
      */
     override suspend fun executeScreenshots(
         screenshotRequest: ScreenshotRequest,
-        onSaved: (Uri) -> Unit,
+        onSaved: (Uri?) -> Unit,
         requestCallback: RequestCallback
     ) {
         val displayIds = getDisplaysToScreenshot(screenshotRequest.type)
@@ -86,20 +86,20 @@
     /** All logging should be triggered only by this method. */
     private suspend fun dispatchToController(
         rawScreenshotData: ScreenshotData,
-        onSaved: (Uri) -> Unit,
+        onSaved: (Uri?) -> Unit,
         callback: RequestCallback
     ) {
         // Let's wait before logging "screenshot requested", as we should log the processed
         // ScreenshotData.
         val screenshotData =
-            try {
-                screenshotRequestProcessor.process(rawScreenshotData)
-            } catch (e: RequestProcessorException) {
-                Log.e(TAG, "Failed to process screenshot request!", e)
-                logScreenshotRequested(rawScreenshotData)
-                onFailedScreenshotRequest(rawScreenshotData, callback)
-                return
-            }
+            runCatching { screenshotRequestProcessor.process(rawScreenshotData) }
+                .onFailure {
+                    Log.e(TAG, "Failed to process screenshot request!", it)
+                    logScreenshotRequested(rawScreenshotData)
+                    onFailedScreenshotRequest(rawScreenshotData, callback)
+                }
+                .getOrNull()
+                ?: return
 
         logScreenshotRequested(screenshotData)
         Log.d(TAG, "Screenshot request: $screenshotData")
@@ -185,7 +185,7 @@
     /** For java compatibility only. see [executeScreenshots] */
     override fun executeScreenshotsAsync(
         screenshotRequest: ScreenshotRequest,
-        onSaved: Consumer<Uri>,
+        onSaved: Consumer<Uri?>,
         requestCallback: RequestCallback
     ) {
         mainScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index 6ff0fda..9b8d047 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -16,17 +16,15 @@
 
 package com.android.systemui.screenshot.dagger;
 
-import static com.android.systemui.Flags.screenshotShelfUi;
+import static com.android.systemui.Flags.screenshotShelfUi2;
 
 import android.app.Service;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.screenshot.DefaultScreenshotActionsProvider;
 import com.android.systemui.screenshot.ImageCapture;
 import com.android.systemui.screenshot.ImageCaptureImpl;
 import com.android.systemui.screenshot.LegacyScreenshotViewProxy;
-import com.android.systemui.screenshot.ScreenshotActionsProvider;
 import com.android.systemui.screenshot.ScreenshotPolicy;
 import com.android.systemui.screenshot.ScreenshotPolicyImpl;
 import com.android.systemui.screenshot.ScreenshotShelfViewProxy;
@@ -90,10 +88,6 @@
     abstract ScreenshotSoundController bindScreenshotSoundController(
             ScreenshotSoundControllerImpl screenshotSoundProviderImpl);
 
-    @Binds
-    abstract ScreenshotActionsProvider.Factory bindScreenshotActionsProviderFactory(
-            DefaultScreenshotActionsProvider.Factory defaultScreenshotActionsProviderFactory);
-
     @Provides
     @SysUISingleton
     static ScreenshotViewModel providesScreenshotViewModel(
@@ -105,7 +99,7 @@
     static ScreenshotViewProxy.Factory providesScreenshotViewProxyFactory(
             ScreenshotShelfViewProxy.Factory shelfScreenshotViewProxyFactory,
             LegacyScreenshotViewProxy.Factory legacyScreenshotViewProxyFactory) {
-        if (screenshotShelfUi()) {
+        if (screenshotShelfUi2()) {
             return shelfScreenshotViewProxyFactory;
         } else {
             return legacyScreenshotViewProxyFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/data/model/ChildTaskModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/data/model/ChildTaskModel.kt
new file mode 100644
index 0000000..c380db0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/data/model/ChildTaskModel.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.data.model
+
+import android.content.ComponentName
+import android.graphics.Rect
+
+/** A child task within a RootTaskInfo */
+data class ChildTaskModel(
+    /** The task identifier */
+    val id: Int,
+    /** The task name */
+    val name: String,
+    /** The location and size of the task */
+    val bounds: Rect,
+    /** The user which created the task. */
+    val userId: Int,
+) {
+    val componentName: ComponentName?
+        get() = ComponentName.unflattenFromString(name)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/data/model/DisplayContentModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/data/model/DisplayContentModel.kt
index 837a661..2048b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/data/model/DisplayContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/data/model/DisplayContentModel.kt
@@ -24,6 +24,6 @@
     val displayId: Int,
     /** Information about the current System UI state which can affect capture. */
     val systemUiState: SystemUiState,
-    /** A list of root tasks on the display, ordered from bottom to top along the z-axis */
+    /** A list of root tasks on the display, ordered from top to bottom along the z-axis */
     val rootTasks: List<RootTaskInfo>,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/data/repository/DisplayContentRepository.kt b/packages/SystemUI/src/com/android/systemui/screenshot/data/repository/DisplayContentRepository.kt
index 9c81b32..48e813d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/data/repository/DisplayContentRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/data/repository/DisplayContentRepository.kt
@@ -18,7 +18,7 @@
 import com.android.systemui.screenshot.data.model.DisplayContentModel
 
 /** Provides information about tasks related to a display. */
-interface DisplayContentRepository {
+fun interface DisplayContentRepository {
     /** Provides information about the tasks and content presented on a given display. */
     suspend fun getDisplayContent(displayId: Int): DisplayContentModel
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureParameters.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureParameters.kt
new file mode 100644
index 0000000..5e2b576
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureParameters.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.content.ComponentName
+import android.os.UserHandle
+
+/** The parameters dictated by a [CapturePolicy], used to adjust alter screenshot request. */
+data class CaptureParameters(
+    /** How should the content be captured? */
+    val type: CaptureType,
+    /** The focused or top component at the time of the screenshot. */
+    val component: ComponentName?,
+    /** Which user should receive the screenshot file? */
+    val owner: UserHandle,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt
new file mode 100644
index 0000000..0fb5366
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CapturePolicy.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+
+/** Contains logic to determine when and how an adjust to screenshot behavior applies. */
+fun interface CapturePolicy {
+    /**
+     * Test the policy against the current display task state. If the policy applies, Returns a
+     * [PolicyResult.Matched] containing [CaptureParameters] used to alter the request.
+     */
+    suspend fun check(content: DisplayContentModel): PolicyResult
+
+    /** The result of a screen capture policy check. */
+    sealed interface PolicyResult {
+        /** The policy rules matched the given display content and will be applied. */
+        data class Matched(
+            /** The name of the policy rule which matched. */
+            val policy: String,
+            /** Why the policy matched. */
+            val reason: String,
+            /** Details on how to modify the screen capture request. */
+            val parameters: CaptureParameters,
+        ) : PolicyResult
+
+        /** The policy rules do not match the given display content and do not apply. */
+        data class NotMatched(
+            /** The name of the policy rule which matched. */
+            val policy: String,
+            /** Why the policy did not match. */
+            val reason: String
+        ) : PolicyResult
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt
new file mode 100644
index 0000000..0ef5207
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/CaptureType.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.graphics.Rect
+
+/** What to capture */
+sealed interface CaptureType {
+    /** Capture the entire screen contents. */
+    data class FullScreen(val displayId: Int) : CaptureType
+
+    /** Capture the contents of the task only. */
+    data class IsolatedTask(
+        val taskId: Int,
+        val taskBounds: Rect?,
+    ) : CaptureType
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt
new file mode 100644
index 0000000..80aa0ef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.app.ActivityTaskManager.RootTaskInfo
+import android.app.WindowConfiguration
+import android.content.ComponentName
+import android.graphics.Bitmap
+import android.graphics.Rect
+import android.os.Process.myUserHandle
+import android.os.UserHandle
+import android.util.Log
+import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN
+import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.screenshot.ImageCapture
+import com.android.systemui.screenshot.ScreenshotData
+import com.android.systemui.screenshot.ScreenshotRequestProcessor
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.repository.DisplayContentRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.FullScreen
+import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+private const val TAG = "PolicyRequestProcessor"
+
+/** A [ScreenshotRequestProcessor] which supports general policy rule matching. */
+class PolicyRequestProcessor(
+    @Background private val background: CoroutineDispatcher,
+    private val capture: ImageCapture,
+    /** Provides information about the tasks on a given display */
+    private val displayTasks: DisplayContentRepository,
+    /** The list of policies to apply, in order of priority */
+    private val policies: List<CapturePolicy>,
+    /** The owner to assign for screenshot when a focused task isn't visible */
+    private val defaultOwner: UserHandle = myUserHandle(),
+    /** The assigned component when no application has focus, or not visible */
+    private val defaultComponent: ComponentName,
+) : ScreenshotRequestProcessor {
+    override suspend fun process(original: ScreenshotData): ScreenshotData {
+        if (original.type == TAKE_SCREENSHOT_PROVIDED_IMAGE) {
+            // The request contains an already captured screenshot, accept it as is.
+            Log.i(TAG, "Screenshot bitmap provided. No modifications applied.")
+            return original
+        }
+        val displayContent = displayTasks.getDisplayContent(original.displayId)
+
+        // If policies yield explicit modifications, apply them and return the result
+        Log.i(TAG, "Applying policy checks....")
+        policies.map { policy ->
+            when (val result = policy.check(displayContent)) {
+                is Matched -> {
+                    Log.i(TAG, "$result")
+                    return modify(original, result.parameters)
+                }
+                is NotMatched -> Log.i(TAG, "$result")
+            }
+        }
+
+        // Otherwise capture normally, filling in additional information as needed.
+        return captureScreenshot(original, displayContent)
+    }
+
+    /** Produce a new [ScreenshotData] using [CaptureParameters] */
+    suspend fun modify(original: ScreenshotData, updates: CaptureParameters): ScreenshotData {
+        // Update and apply bitmap capture depending on the parameters.
+        val updated =
+            when (val type = updates.type) {
+                is IsolatedTask ->
+                    replaceWithTaskSnapshot(
+                        original,
+                        updates.component,
+                        updates.owner,
+                        type.taskId,
+                        type.taskBounds
+                    )
+                is FullScreen ->
+                    replaceWithScreenshot(
+                        original,
+                        updates.component,
+                        updates.owner,
+                        type.displayId
+                    )
+            }
+        return updated
+    }
+
+    private suspend fun captureScreenshot(
+        original: ScreenshotData,
+        displayContent: DisplayContentModel,
+    ): ScreenshotData {
+        // The first root task on the display, excluding Picture-in-Picture
+        val topMainRootTask =
+            if (!displayContent.systemUiState.shadeExpanded) {
+                displayContent.rootTasks.firstOrNull(::nonPipVisibleTask)
+            } else {
+                null // Otherwise attributed to SystemUI / current user
+            }
+
+        return replaceWithScreenshot(
+            original = original,
+            componentName = topMainRootTask?.topActivity ?: defaultComponent,
+            owner = topMainRootTask?.userId?.let { UserHandle.of(it) } ?: defaultOwner,
+            displayId = original.displayId
+        )
+    }
+
+    suspend fun replaceWithTaskSnapshot(
+        original: ScreenshotData,
+        componentName: ComponentName?,
+        owner: UserHandle,
+        taskId: Int,
+        taskBounds: Rect?,
+    ): ScreenshotData {
+        Log.i(TAG, "Capturing task snapshot: $componentName / $owner")
+        val taskSnapshot = capture.captureTask(taskId)
+        return original.copy(
+            type = TAKE_SCREENSHOT_PROVIDED_IMAGE,
+            bitmap = taskSnapshot,
+            userHandle = owner,
+            taskId = taskId,
+            topComponent = componentName,
+            screenBounds = taskBounds
+        )
+    }
+
+    suspend fun replaceWithScreenshot(
+        original: ScreenshotData,
+        componentName: ComponentName?,
+        owner: UserHandle?,
+        displayId: Int,
+    ): ScreenshotData {
+        Log.i(TAG, "Capturing screenshot: $componentName / $owner")
+        val screenshot = captureDisplay(displayId)
+        return original.copy(
+            type = TAKE_SCREENSHOT_FULLSCREEN,
+            bitmap = screenshot,
+            userHandle = owner,
+            topComponent = componentName,
+            screenBounds = Rect(0, 0, screenshot?.width ?: 0, screenshot?.height ?: 0)
+        )
+    }
+
+    /** Filter for the task used to attribute a full screen capture to an owner */
+    private fun nonPipVisibleTask(info: RootTaskInfo): Boolean {
+        return info.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED &&
+            info.isVisible &&
+            info.isRunning &&
+            info.numActivities > 0 &&
+            info.topActivity != null &&
+            info.childTaskIds.isNotEmpty()
+    }
+
+    /** TODO: Move to ImageCapture (existing function is non-suspending) */
+    private suspend fun captureDisplay(displayId: Int): Bitmap? {
+        return withContext(background) { capture.captureDisplay(displayId) }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt
new file mode 100644
index 0000000..1945c25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.os.UserHandle
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.model.ProfileType
+import com.android.systemui.screenshot.data.repository.ProfileTypeRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.FullScreen
+import javax.inject.Inject
+
+/**
+ * Condition: When any visible task belongs to a private user.
+ *
+ * Parameters: Capture the whole screen, owned by the private user.
+ */
+class PrivateProfilePolicy
+@Inject
+constructor(
+    private val profileTypes: ProfileTypeRepository,
+) : CapturePolicy {
+    override suspend fun check(content: DisplayContentModel): PolicyResult {
+        // The systemUI notification shade isn't a private profile app, skip.
+        if (content.systemUiState.shadeExpanded) {
+            return NotMatched(policy = NAME, reason = SHADE_EXPANDED)
+        }
+
+        // Find the first visible rootTaskInfo with a child task owned by a private user
+        val childTask =
+            content.rootTasks
+                .filter { it.isVisible }
+                .firstNotNullOfOrNull { root ->
+                    root
+                        .childTasksTopDown()
+                        .firstOrNull {
+                            profileTypes.getProfileType(it.userId) == ProfileType.PRIVATE
+                        }
+                }
+                ?: return NotMatched(policy = NAME, reason = NO_VISIBLE_TASKS)
+
+        // If matched, return parameters needed to modify the request.
+        return Matched(
+            policy = NAME,
+            reason = PRIVATE_TASK_VISIBLE,
+            CaptureParameters(
+                type = FullScreen(content.displayId),
+                component = content.rootTasks.first { it.isVisible }.topActivity,
+                owner = UserHandle.of(childTask.userId),
+            )
+        )
+    }
+    companion object {
+        const val NAME = "PrivateProfile"
+        const val SHADE_EXPANDED = "Notification shade is expanded"
+        const val NO_VISIBLE_TASKS = "No private profile tasks are visible"
+        const val PRIVATE_TASK_VISIBLE = "At least one private profile task is visible"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt
new file mode 100644
index 0000000..f768cfb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.app.ActivityTaskManager.RootTaskInfo
+import com.android.systemui.screenshot.data.model.ChildTaskModel
+
+/** The child tasks of A RootTaskInfo as [ChildTaskModel] in top-down (z-index ascending) order. */
+internal fun RootTaskInfo.childTasksTopDown(): Sequence<ChildTaskModel> {
+    return ((childTaskIds.size - 1) downTo 0).asSequence().map { index ->
+        ChildTaskModel(
+            childTaskIds[index],
+            childTaskNames[index],
+            childTaskBounds[index],
+            childTaskUserIds[index]
+        )
+    }
+}
+
+internal fun RootTaskInfo.hasChildTasks() = childTaskUserIds.isNotEmpty()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt
index bc71ab7..44f767a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt
@@ -16,7 +16,14 @@
 
 package com.android.systemui.screenshot.policy
 
+import android.content.ComponentName
+import android.content.Context
+import android.os.Process
+import com.android.systemui.Flags.screenshotPrivateProfileBehaviorFix
+import com.android.systemui.SystemUIService
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.screenshot.ImageCapture
 import com.android.systemui.screenshot.RequestProcessor
 import com.android.systemui.screenshot.ScreenshotPolicy
@@ -29,6 +36,7 @@
 import dagger.Module
 import dagger.Provides
 import javax.inject.Provider
+import kotlinx.coroutines.CoroutineDispatcher
 
 @Module
 interface ScreenshotPolicyModule {
@@ -37,18 +45,46 @@
     @SysUISingleton
     fun bindProfileTypeRepository(impl: ProfileTypeRepositoryImpl): ProfileTypeRepository
 
-    companion object {
-        @Provides
-        @SysUISingleton
-        fun bindScreenshotRequestProcessor(
-            imageCapture: ImageCapture,
-            policyProvider: Provider<ScreenshotPolicy>,
-        ): ScreenshotRequestProcessor {
-            return RequestProcessor(imageCapture, policyProvider.get())
-        }
-    }
-
     @Binds
     @SysUISingleton
     fun bindDisplayContentRepository(impl: DisplayContentRepositoryImpl): DisplayContentRepository
+
+    companion object {
+        @JvmStatic
+        @Provides
+        @SysUISingleton
+        fun bindCapturePolicyList(
+            privateProfilePolicy: PrivateProfilePolicy,
+            workProfilePolicy: WorkProfilePolicy,
+        ): List<CapturePolicy> {
+            // In order of priority. The first matching policy applies.
+            return listOf(workProfilePolicy, privateProfilePolicy)
+        }
+
+        @JvmStatic
+        @Provides
+        @SysUISingleton
+        fun bindScreenshotRequestProcessor(
+            @Application context: Context,
+            @Background background: CoroutineDispatcher,
+            imageCapture: ImageCapture,
+            policyProvider: Provider<ScreenshotPolicy>,
+            displayContentRepoProvider: Provider<DisplayContentRepository>,
+            policyListProvider: Provider<List<CapturePolicy>>,
+        ): ScreenshotRequestProcessor {
+            return if (screenshotPrivateProfileBehaviorFix()) {
+                PolicyRequestProcessor(
+                    background = background,
+                    capture = imageCapture,
+                    displayTasks = displayContentRepoProvider.get(),
+                    policies = policyListProvider.get(),
+                    defaultOwner = Process.myUserHandle(),
+                    defaultComponent =
+                        ComponentName(context.packageName, SystemUIService::class.java.toString())
+                )
+            } else {
+                RequestProcessor(imageCapture, policyProvider.get())
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt
new file mode 100644
index 0000000..fdf16aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
+import android.os.UserHandle
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.model.ProfileType
+import com.android.systemui.screenshot.data.repository.ProfileTypeRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask
+import com.android.window.flags.Flags
+import javax.inject.Inject
+import kotlinx.coroutines.flow.first
+
+/**
+ * Condition: When the top visible task (excluding PIP mode) belongs to a work user.
+ *
+ * Parameters: Capture only the foreground task, owned by the work user.
+ */
+class WorkProfilePolicy
+@Inject
+constructor(
+    private val profileTypes: ProfileTypeRepository,
+) : CapturePolicy {
+
+    override suspend fun check(content: DisplayContentModel): PolicyResult {
+        // The systemUI notification shade isn't a work app, skip.
+        if (content.systemUiState.shadeExpanded) {
+            return NotMatched(policy = NAME, reason = SHADE_EXPANDED)
+        }
+
+        if (Flags.enableDesktopWindowingMode()) {
+            content.rootTasks.firstOrNull()?.also {
+                if (it.windowingMode == WINDOWING_MODE_FREEFORM) {
+                    return NotMatched(policy = NAME, reason = DESKTOP_MODE_ENABLED)
+                }
+            }
+        }
+
+        // Find the first non PiP rootTask with a top child task owned by a work user
+        val (rootTask, childTask) =
+            content.rootTasks
+                .filter {
+                    it.isVisible && it.windowingMode != WINDOWING_MODE_PINNED && it.hasChildTasks()
+                }
+                .map { it to it.childTasksTopDown().first() }
+                .firstOrNull { (_, child) ->
+                    profileTypes.getProfileType(child.userId) == ProfileType.WORK
+                }
+                ?: return NotMatched(
+                    policy = NAME,
+                    reason = WORK_TASK_NOT_TOP,
+                )
+
+        // If matched, return parameters needed to modify the request.
+        return PolicyResult.Matched(
+            policy = NAME,
+            reason = WORK_TASK_IS_TOP,
+            CaptureParameters(
+                type = IsolatedTask(taskId = childTask.id, taskBounds = childTask.bounds),
+                component = childTask.componentName ?: rootTask.topActivity,
+                owner = UserHandle.of(childTask.userId),
+            )
+        )
+    }
+
+    companion object {
+        const val NAME = "WorkProfile"
+        const val SHADE_EXPANDED = "Notification shade is expanded"
+        const val WORK_TASK_NOT_TOP =
+            "The top-most non-PINNED task does not belong to a work profile user"
+        const val WORK_TASK_IS_TOP = "The top-most non-PINNED task belongs to a work profile user"
+        const val DESKTOP_MODE_ENABLED =
+            "enable_desktop_windowing_mode is enabled and top " +
+                "RootTask has WINDOWING_MODE_FREEFORM"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java
index 1e1a577..b43a1d2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/LongScreenshotActivity.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.HardwareRenderer;
+import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
@@ -38,9 +39,11 @@
 import android.view.Display;
 import android.view.ScrollCaptureResponse;
 import android.view.View;
+import android.view.WindowInsets;
 import android.widget.ImageView;
 
 import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.view.WindowCompat;
 
 import com.android.internal.app.ChooserActivity;
 import com.android.internal.logging.UiEventLogger;
@@ -127,6 +130,10 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        // Enable edge-to-edge explicitly.
+        WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+
         setContentView(R.layout.long_screenshot);
 
         mPreview = requireViewById(R.id.preview);
@@ -149,6 +156,13 @@
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
                         updateImageDimensions());
 
+        requireViewById(R.id.root).setOnApplyWindowInsetsListener(
+                (view, windowInsets) -> {
+                    Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars());
+                    view.setPadding(insets.left, insets.top, insets.right, insets.bottom);
+                    return WindowInsets.CONSUMED;
+                });
+
         Intent intent = getIntent();
         mScrollCaptureResponse = intent.getParcelableExtra(EXTRA_CAPTURE_RESPONSE);
         mScreenshotUserHandle = intent.getParcelableExtra(EXTRA_SCREENSHOT_USER_HANDLE,
@@ -335,8 +349,8 @@
             // TODO: Fix transition for work profile. Omitting it in the meantime.
             mActionExecutor.launchIntentAsync(
                     ActionIntentCreator.INSTANCE.createEdit(uri, this),
-                    null,
-                    mScreenshotUserHandle, false);
+                    mScreenshotUserHandle, false,
+                    /* activityOptions */ null, /* transitionCoordinator */ null);
         } else {
             String editorPackage = getString(R.string.config_screenshotEditor);
             Intent intent = new Intent(Intent.ACTION_EDIT);
@@ -363,7 +377,8 @@
 
     private void doShare(Uri uri) {
         Intent shareIntent = ActionIntentCreator.INSTANCE.createShare(uri);
-        mActionExecutor.launchIntentAsync(shareIntent, null, mScreenshotUserHandle, false);
+        mActionExecutor.launchIntentAsync(shareIntent, mScreenshotUserHandle, false,
+                /* activityOptions */ null, /* transitionCoordinator */ null);
     }
 
     private void onClicked(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureExecutor.kt
new file mode 100644
index 0000000..6c4ee3e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureExecutor.kt
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.scroll
+
+import android.app.ActivityManager
+import android.graphics.Rect
+import android.os.IBinder
+import android.util.Log
+import android.view.ScrollCaptureResponse
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.screenshot.scroll.ScrollCaptureController.LongScreenshot
+import com.google.common.util.concurrent.ListenableFuture
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.Executor
+import java.util.concurrent.Future
+import javax.inject.Inject
+
+class ScrollCaptureExecutor
+@Inject
+constructor(
+    activityManager: ActivityManager,
+    private val scrollCaptureClient: ScrollCaptureClient,
+    private val scrollCaptureController: ScrollCaptureController,
+    private val longScreenshotHolder: LongScreenshotData,
+    @Main private val mainExecutor: Executor
+) {
+    private val isLowRamDevice = activityManager.isLowRamDevice
+    private var lastScrollCaptureRequest: ListenableFuture<ScrollCaptureResponse>? = null
+    private var lastScrollCaptureResponse: ScrollCaptureResponse? = null
+    private var longScreenshotFuture: ListenableFuture<LongScreenshot>? = null
+
+    fun requestScrollCapture(
+        displayId: Int,
+        token: IBinder,
+        callback: (ScrollCaptureResponse) -> Unit
+    ) {
+        if (!allowLongScreenshots()) {
+            Log.d(TAG, "Long screenshots not supported on this device")
+            return
+        }
+        scrollCaptureClient.setHostWindowToken(token)
+        lastScrollCaptureRequest?.cancel(true)
+        val scrollRequest =
+            scrollCaptureClient.request(displayId).apply {
+                addListener(
+                    { onScrollCaptureResponseReady(this)?.let { callback.invoke(it) } },
+                    mainExecutor
+                )
+            }
+        lastScrollCaptureRequest = scrollRequest
+    }
+
+    fun interface ScrollTransitionReady {
+        fun onTransitionReady(
+            destRect: Rect,
+            onTransitionEnd: Runnable,
+            longScreenshot: LongScreenshot
+        )
+    }
+
+    fun executeBatchScrollCapture(
+        response: ScrollCaptureResponse,
+        onCaptureComplete: Runnable,
+        onFailure: Runnable,
+        transition: ScrollTransitionReady,
+    ) {
+        // Clear the reference to prevent close() on reset
+        lastScrollCaptureResponse = null
+        longScreenshotFuture?.cancel(true)
+        longScreenshotFuture =
+            scrollCaptureController.run(response).apply {
+                addListener(
+                    {
+                        getLongScreenshotChecked(this, onFailure)?.let {
+                            longScreenshotHolder.setLongScreenshot(it)
+                            longScreenshotHolder.setTransitionDestinationCallback {
+                                destinationRect: Rect,
+                                onTransitionEnd: Runnable ->
+                                transition.onTransitionReady(destinationRect, onTransitionEnd, it)
+                            }
+                            onCaptureComplete.run()
+                        }
+                    },
+                    mainExecutor
+                )
+            }
+    }
+
+    fun close() {
+        lastScrollCaptureRequest?.cancel(true)
+        lastScrollCaptureRequest = null
+        lastScrollCaptureResponse?.close()
+        lastScrollCaptureResponse = null
+        longScreenshotFuture?.cancel(true)
+    }
+
+    private fun getLongScreenshotChecked(
+        future: ListenableFuture<LongScreenshot>,
+        onFailure: Runnable
+    ): LongScreenshot? {
+        var longScreenshot: LongScreenshot? = null
+        runCatching { longScreenshot = future.get() }
+            .onFailure {
+                Log.e(TAG, "Caught exception", it)
+                onFailure.run()
+                return null
+            }
+        if (longScreenshot?.height != 0) {
+            return longScreenshot
+        }
+        onFailure.run()
+        return null
+    }
+
+    private fun onScrollCaptureResponseReady(
+        responseFuture: Future<ScrollCaptureResponse>
+    ): ScrollCaptureResponse? {
+        try {
+            lastScrollCaptureResponse?.close()
+            lastScrollCaptureResponse = null
+            if (responseFuture.isCancelled) {
+                return null
+            }
+            val captureResponse = responseFuture.get().apply { lastScrollCaptureResponse = this }
+            if (!captureResponse.isConnected) {
+                // No connection means that the target window wasn't found
+                // or that it cannot support scroll capture.
+                Log.d(
+                    TAG,
+                    "ScrollCapture: ${captureResponse.description} [${captureResponse.windowTitle}]"
+                )
+                return null
+            }
+            Log.d(TAG, "ScrollCapture: connected to window [${captureResponse.windowTitle}]")
+            return captureResponse
+        } catch (e: InterruptedException) {
+            Log.e(TAG, "requestScrollCapture interrupted", e)
+        } catch (e: ExecutionException) {
+            Log.e(TAG, "requestScrollCapture failed", e)
+        }
+        return null
+    }
+
+    private fun allowLongScreenshots(): Boolean {
+        return !isLowRamDevice
+    }
+
+    private companion object {
+        private const val TAG = "ScrollCaptureExecutor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
index 2c17873..3f4f74b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
@@ -17,43 +17,103 @@
 package com.android.systemui.screenshot.ui
 
 import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
 import android.animation.ValueAnimator
+import android.graphics.PointF
+import android.graphics.Rect
+import android.util.MathUtils
 import android.view.View
+import android.view.animation.AnimationUtils
+import androidx.core.animation.doOnEnd
+import androidx.core.animation.doOnStart
+import com.android.systemui.res.R
+import kotlin.math.abs
+import kotlin.math.max
+import kotlin.math.sign
 
-class ScreenshotAnimationController(private val view: View) {
+class ScreenshotAnimationController(private val view: ScreenshotShelfView) {
     private var animator: Animator? = null
-
-    fun getEntranceAnimation(): Animator {
-        val animator = ValueAnimator.ofFloat(0f, 1f)
-        animator.addUpdateListener { view.alpha = it.animatedFraction }
-        animator.addListener(
-            object : AnimatorListenerAdapter() {
-                override fun onAnimationStart(animator: Animator) {
-                    view.alpha = 0f
-                }
-                override fun onAnimationEnd(animator: Animator) {
-                    view.alpha = 1f
-                }
-            }
+    private val screenshotPreview = view.requireViewById<View>(R.id.screenshot_preview)
+    private val flashView = view.requireViewById<View>(R.id.screenshot_flash)
+    private val actionContainer = view.requireViewById<View>(R.id.actions_container_background)
+    private val fastOutSlowIn =
+        AnimationUtils.loadInterpolator(view.context, android.R.interpolator.fast_out_slow_in)
+    private val staticUI =
+        listOf<View>(
+            view.requireViewById(R.id.screenshot_preview_border),
+            view.requireViewById(R.id.actions_container_background),
+            view.requireViewById(R.id.screenshot_badge),
+            view.requireViewById(R.id.screenshot_dismiss_button)
         )
+
+    fun getEntranceAnimation(bounds: Rect, showFlash: Boolean): Animator {
+        val entranceAnimation = AnimatorSet()
+
+        val previewAnimator = getPreviewAnimator(bounds)
+
+        if (showFlash) {
+            val flashInAnimator =
+                ObjectAnimator.ofFloat(flashView, "alpha", 0f, 1f).apply {
+                    duration = FLASH_IN_DURATION_MS
+                    interpolator = fastOutSlowIn
+                }
+            val flashOutAnimator =
+                ObjectAnimator.ofFloat(flashView, "alpha", 1f, 0f).apply {
+                    duration = FLASH_OUT_DURATION_MS
+                    interpolator = fastOutSlowIn
+                }
+            flashInAnimator.doOnStart { flashView.visibility = View.VISIBLE }
+            flashOutAnimator.doOnEnd { flashView.visibility = View.GONE }
+            entranceAnimation.play(flashOutAnimator).after(flashInAnimator)
+            entranceAnimation.play(previewAnimator).with(flashOutAnimator)
+            entranceAnimation.doOnStart { screenshotPreview.visibility = View.INVISIBLE }
+        }
+
+        val fadeInAnimator = ValueAnimator.ofFloat(0f, 1f)
+        fadeInAnimator.addUpdateListener {
+            for (child in staticUI) {
+                child.alpha = it.animatedValue as Float
+            }
+        }
+        entranceAnimation.play(fadeInAnimator).after(previewAnimator)
+        entranceAnimation.doOnStart {
+            for (child in staticUI) {
+                child.alpha = 0f
+            }
+        }
+
+        this.animator = entranceAnimation
+        return entranceAnimation
+    }
+
+    fun getSwipeReturnAnimation(): Animator {
+        animator?.cancel()
+        val animator = ValueAnimator.ofFloat(view.translationX, 0f)
+        animator.addUpdateListener { view.translationX = it.animatedValue as Float }
         this.animator = animator
         return animator
     }
 
-    fun getExitAnimation(): Animator {
-        val animator = ValueAnimator.ofFloat(1f, 0f)
-        animator.addUpdateListener { view.alpha = it.animatedValue as Float }
-        animator.addListener(
-            object : AnimatorListenerAdapter() {
-                override fun onAnimationStart(animator: Animator) {
-                    view.alpha = 1f
-                }
-                override fun onAnimationEnd(animator: Animator) {
-                    view.alpha = 0f
-                }
+    fun getSwipeDismissAnimation(requestedVelocity: Float?): Animator {
+        val velocity = getAdjustedVelocity(requestedVelocity)
+        val screenWidth = view.resources.displayMetrics.widthPixels
+        // translation at which point the visible UI is fully off the screen (in the direction
+        // according to velocity)
+        val endX =
+            if (velocity < 0) {
+                -1f * actionContainer.right
+            } else {
+                (screenWidth - actionContainer.left).toFloat()
             }
-        )
+        val distance = endX - view.translationX
+        val animator = ValueAnimator.ofFloat(view.translationX, endX)
+        animator.addUpdateListener {
+            view.translationX = it.animatedValue as Float
+            view.alpha = 1f - it.animatedFraction
+        }
+        animator.duration = ((abs(distance / velocity))).toLong()
+
         this.animator = animator
         return animator
     }
@@ -61,4 +121,60 @@
     fun cancel() {
         animator?.cancel()
     }
+
+    private fun getPreviewAnimator(bounds: Rect): Animator {
+        val targetPosition = Rect()
+        screenshotPreview.getHitRect(targetPosition)
+        val startXScale = bounds.width() / targetPosition.width().toFloat()
+        val startYScale = bounds.height() / targetPosition.height().toFloat()
+        val startPos = PointF(bounds.exactCenterX(), bounds.exactCenterY())
+        val endPos = PointF(targetPosition.exactCenterX(), targetPosition.exactCenterY())
+
+        val previewYAnimator =
+            ValueAnimator.ofFloat(startPos.y, endPos.y).apply {
+                duration = PREVIEW_Y_ANIMATION_DURATION_MS
+                interpolator = fastOutSlowIn
+            }
+        previewYAnimator.addUpdateListener {
+            val progress = it.animatedValue as Float
+            screenshotPreview.y = progress - screenshotPreview.height / 2f
+        }
+        // scale animation starts/finishes at the same time as x placement
+        val previewXAndScaleAnimator =
+            ValueAnimator.ofFloat(0f, 1f).apply {
+                duration = PREVIEW_X_ANIMATION_DURATION_MS
+                interpolator = fastOutSlowIn
+            }
+        previewXAndScaleAnimator.addUpdateListener {
+            val t = it.animatedFraction
+            screenshotPreview.scaleX = MathUtils.lerp(startXScale, 1f, t)
+            screenshotPreview.scaleY = MathUtils.lerp(startYScale, 1f, t)
+            screenshotPreview.x =
+                MathUtils.lerp(startPos.x, endPos.x, t) - screenshotPreview.width / 2f
+        }
+
+        val previewAnimator = AnimatorSet()
+        previewAnimator.play(previewXAndScaleAnimator).with(previewYAnimator)
+
+        previewAnimator.doOnStart { screenshotPreview.visibility = View.VISIBLE }
+        return previewAnimator
+    }
+
+    private fun getAdjustedVelocity(requestedVelocity: Float?): Float {
+        return if (requestedVelocity == null) {
+            val isLTR = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR
+            // dismiss to the left in LTR locales, to the right in RTL
+            if (isLTR) -MINIMUM_VELOCITY else MINIMUM_VELOCITY
+        } else {
+            sign(requestedVelocity) * max(MINIMUM_VELOCITY, abs(requestedVelocity))
+        }
+    }
+
+    companion object {
+        private const val MINIMUM_VELOCITY = 1.5f // pixels per second
+        private const val FLASH_IN_DURATION_MS: Long = 133
+        private const val FLASH_OUT_DURATION_MS: Long = 217
+        private const val PREVIEW_X_ANIMATION_DURATION_MS: Long = 234
+        private const val PREVIEW_Y_ANIMATION_DURATION_MS: Long = 500
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
index 747ad4f..f9af4b9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotShelfView.kt
@@ -17,17 +17,81 @@
 package com.android.systemui.screenshot.ui
 
 import android.content.Context
+import android.graphics.Insets
+import android.graphics.Rect
+import android.graphics.Region
 import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.View
 import android.widget.ImageView
 import androidx.constraintlayout.widget.ConstraintLayout
 import com.android.systemui.res.R
+import com.android.systemui.screenshot.FloatingWindowUtil
 
 class ScreenshotShelfView(context: Context, attrs: AttributeSet? = null) :
     ConstraintLayout(context, attrs) {
     lateinit var screenshotPreview: ImageView
+    var onTouchInterceptListener: ((MotionEvent) -> Boolean)? = null
+
+    private val displayMetrics = context.resources.displayMetrics
+    private val tmpRect = Rect()
+    private lateinit var actionsContainerBackground: View
+    private lateinit var dismissButton: View
 
     override fun onFinishInflate() {
         super.onFinishInflate()
+        // Get focus so that the key events go to the layout.
+        isFocusableInTouchMode = true
         screenshotPreview = requireViewById(R.id.screenshot_preview)
+        actionsContainerBackground = requireViewById(R.id.actions_container_background)
+        dismissButton = requireViewById(R.id.screenshot_dismiss_button)
+    }
+
+    fun getTouchRegion(gestureInsets: Insets): Region {
+        val region = getSwipeRegion()
+
+        // Receive touches in gesture insets so they don't cause TOUCH_OUTSIDE
+        // left edge gesture region
+        val insetRect = Rect(0, 0, gestureInsets.left, displayMetrics.heightPixels)
+        region.op(insetRect, Region.Op.UNION)
+        // right edge gesture region
+        insetRect.set(
+            displayMetrics.widthPixels - gestureInsets.right,
+            0,
+            displayMetrics.widthPixels,
+            displayMetrics.heightPixels
+        )
+        region.op(insetRect, Region.Op.UNION)
+
+        return region
+    }
+
+    private fun getSwipeRegion(): Region {
+        val swipeRegion = Region()
+        val padding = FloatingWindowUtil.dpToPx(displayMetrics, -1 * TOUCH_PADDING_DP).toInt()
+        swipeRegion.addInsetView(screenshotPreview, padding)
+        swipeRegion.addInsetView(actionsContainerBackground, padding)
+        swipeRegion.addInsetView(dismissButton, padding)
+        findViewById<View>(R.id.screenshot_message_container)?.let {
+            swipeRegion.addInsetView(it, padding)
+        }
+        return swipeRegion
+    }
+
+    private fun Region.addInsetView(view: View, padding: Int = 0) {
+        view.getBoundsOnScreen(tmpRect)
+        tmpRect.inset(padding, padding)
+        this.op(tmpRect, Region.Op.UNION)
+    }
+
+    companion object {
+        private const val TOUCH_PADDING_DP = 12f
+    }
+
+    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
+        if (onTouchInterceptListener?.invoke(ev) == true) {
+            return true
+        }
+        return super.onInterceptTouchEvent(ev)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt
new file mode 100644
index 0000000..61d4489
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.ui
+
+import android.view.MotionEvent
+import android.view.VelocityTracker
+import android.view.View
+import com.android.systemui.screenshot.FloatingWindowUtil
+import kotlin.math.abs
+
+class SwipeGestureListener(
+    private val view: View,
+    private val onDismiss: (Float?) -> Unit,
+    private val onCancel: () -> Unit
+) {
+    private val velocityTracker = VelocityTracker.obtain()
+    private val displayMetrics = view.resources.displayMetrics
+
+    private var startX = 0f
+
+    fun onMotionEvent(ev: MotionEvent): Boolean {
+        ev.offsetLocation(view.translationX, 0f)
+        when (ev.actionMasked) {
+            MotionEvent.ACTION_DOWN -> {
+                velocityTracker.addMovement(ev)
+                startX = ev.rawX
+            }
+            MotionEvent.ACTION_UP -> {
+                velocityTracker.computeCurrentVelocity(1)
+                val xVelocity = velocityTracker.xVelocity
+                if (
+                    abs(xVelocity) > FloatingWindowUtil.dpToPx(displayMetrics, FLING_THRESHOLD_DP)
+                ) {
+                    onDismiss.invoke(xVelocity)
+                    return true
+                } else if (
+                    abs(view.translationX) >
+                        FloatingWindowUtil.dpToPx(displayMetrics, DISMISS_THRESHOLD_DP)
+                ) {
+                    onDismiss.invoke(xVelocity)
+                    return true
+                } else {
+                    velocityTracker.clear()
+                    onCancel.invoke()
+                }
+            }
+            MotionEvent.ACTION_MOVE -> {
+                velocityTracker.addMovement(ev)
+                view.translationX = ev.rawX - startX
+            }
+        }
+        return false
+    }
+
+    companion object {
+        private const val DISMISS_THRESHOLD_DP = 80f
+        private const val FLING_THRESHOLD_DP = .8f // dp per ms
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt
index c7fe3f6..3c5a0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ActionButtonViewBinder.kt
@@ -28,15 +28,16 @@
     fun bind(view: View, viewModel: ActionButtonViewModel) {
         val iconView = view.requireViewById<ImageView>(R.id.overlay_action_chip_icon)
         val textView = view.requireViewById<TextView>(R.id.overlay_action_chip_text)
-        iconView.setImageDrawable(viewModel.icon)
-        textView.text = viewModel.name
-        setMargins(iconView, textView, viewModel.name?.isNotEmpty() ?: false)
+        iconView.setImageDrawable(viewModel.appearance.icon)
+        textView.text = viewModel.appearance.label
+        setMargins(iconView, textView, viewModel.appearance.label?.isNotEmpty() ?: false)
         if (viewModel.onClicked != null) {
             view.setOnClickListener { viewModel.onClicked.invoke() }
         } else {
             view.setOnClickListener(null)
         }
-        view.contentDescription = viewModel.description
+        view.tag = viewModel.id
+        view.contentDescription = viewModel.appearance.description
         view.visibility = View.VISIBLE
         view.alpha = 1f
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
index b191a1a..3376b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
@@ -16,10 +16,8 @@
 
 package com.android.systemui.screenshot.ui.binder
 
-import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
-import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.LinearLayout
 import androidx.lifecycle.Lifecycle
@@ -27,24 +25,44 @@
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
+import com.android.systemui.screenshot.ScreenshotEvent
+import com.android.systemui.screenshot.ui.ScreenshotShelfView
+import com.android.systemui.screenshot.ui.SwipeGestureListener
 import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
 import com.android.systemui.util.children
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 
 object ScreenshotShelfViewBinder {
     fun bind(
-        view: ViewGroup,
+        view: ScreenshotShelfView,
         viewModel: ScreenshotViewModel,
         layoutInflater: LayoutInflater,
+        onDismissalRequested: (event: ScreenshotEvent, velocity: Float?) -> Unit,
+        onDismissalCancelled: () -> Unit,
     ) {
+        val swipeGestureListener =
+            SwipeGestureListener(
+                view,
+                onDismiss = {
+                    onDismissalRequested(ScreenshotEvent.SCREENSHOT_SWIPE_DISMISSED, it)
+                },
+                onCancel = onDismissalCancelled
+            )
+        view.onTouchInterceptListener = { swipeGestureListener.onMotionEvent(it) }
+
         val previewView: ImageView = view.requireViewById(R.id.screenshot_preview)
         val previewBorder = view.requireViewById<View>(R.id.screenshot_preview_border)
         previewView.clipToOutline = true
         val actionsContainer: LinearLayout = view.requireViewById(R.id.screenshot_actions)
-        view.requireViewById<View>(R.id.screenshot_dismiss_button).visibility =
-            if (viewModel.showDismissButton) View.VISIBLE else View.GONE
+        val dismissButton = view.requireViewById<View>(R.id.screenshot_dismiss_button)
+        dismissButton.visibility = if (viewModel.showDismissButton) View.VISIBLE else View.GONE
+        dismissButton.setOnClickListener {
+            onDismissalRequested(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL, null)
+        }
 
-        view.repeatWhenAttached {
+        // use immediate dispatcher to ensure screenshot bitmap is set before animation
+        view.repeatWhenAttached(Dispatchers.Main.immediate) {
             lifecycleScope.launch {
                 repeatOnLifecycle(Lifecycle.State.STARTED) {
                     launch {
@@ -66,26 +84,43 @@
                     }
                     launch {
                         viewModel.actions.collect { actions ->
-                            if (actions.isNotEmpty()) {
+                            val visibleActions = actions.filter { it.visible }
+
+                            if (visibleActions.isNotEmpty()) {
                                 view
                                     .requireViewById<View>(R.id.actions_container_background)
                                     .visibility = View.VISIBLE
                             }
-                            val viewPool = actionsContainer.children.toList()
-                            actionsContainer.removeAllViews()
-                            val actionButtons =
-                                List(actions.size) {
-                                    viewPool.getOrElse(it) {
+
+                            // Remove any buttons not in the new list, then do another pass to add
+                            // any new actions and update any that are already there.
+                            // This assumes that actions can never change order and that each action
+                            // ID is unique.
+                            val newIds = visibleActions.map { it.id }
+
+                            for (child in actionsContainer.children.toList()) {
+                                if (child.tag !in newIds) {
+                                    actionsContainer.removeView(child)
+                                }
+                            }
+
+                            for ((index, action) in visibleActions.withIndex()) {
+                                val currentView: View? = actionsContainer.getChildAt(index)
+                                if (action.id == currentView?.tag) {
+                                    // Same ID, update the display
+                                    ActionButtonViewBinder.bind(currentView, action)
+                                } else {
+                                    // Different ID. Removals have already happened so this must
+                                    // mean that the new action must be inserted here.
+                                    val actionButton =
                                         layoutInflater.inflate(
-                                            R.layout.overlay_action_chip,
+                                            R.layout.shelf_action_chip,
                                             actionsContainer,
                                             false
                                         )
-                                    }
+                                    actionsContainer.addView(actionButton, index)
+                                    ActionButtonViewBinder.bind(actionButton, action)
                                 }
-                            actionButtons.zip(actions).forEach {
-                                actionsContainer.addView(it.first)
-                                ActionButtonViewBinder.bind(it.first, it.second)
                             }
                         }
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonAppearance.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonAppearance.kt
new file mode 100644
index 0000000..55a2ad2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonAppearance.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.ui.viewmodel
+
+import android.graphics.drawable.Drawable
+
+/** Data describing how an action should be shown to the user. */
+data class ActionButtonAppearance(
+    val icon: Drawable?,
+    val label: CharSequence?,
+    val description: CharSequence,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt
index 05bfed1..c5fa8db 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ActionButtonViewModel.kt
@@ -16,11 +16,20 @@
 
 package com.android.systemui.screenshot.ui.viewmodel
 
-import android.graphics.drawable.Drawable
-
 data class ActionButtonViewModel(
-    val icon: Drawable?,
-    val name: CharSequence?,
-    val description: CharSequence,
-    val onClicked: (() -> Unit)?
-)
+    val appearance: ActionButtonAppearance,
+    val id: Int,
+    val visible: Boolean,
+    val onClicked: (() -> Unit)?,
+) {
+    companion object {
+        private var nextId = 0
+
+        private fun getId() = nextId.also { nextId += 1 }
+
+        fun withNextId(
+            appearance: ActionButtonAppearance,
+            onClicked: (() -> Unit)?
+        ): ActionButtonViewModel = ActionButtonViewModel(appearance, getId(), true, onClicked)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt
index ddfa69b..f67ad40 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.screenshot.ui.viewmodel
 
 import android.graphics.Bitmap
+import android.util.Log
 import android.view.accessibility.AccessibilityManager
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -39,16 +40,56 @@
         _previewAction.value = onClick
     }
 
-    fun addAction(action: ActionButtonViewModel) {
+    fun addAction(actionAppearance: ActionButtonAppearance, onClicked: (() -> Unit)): Int {
         val actionList = _actions.value.toMutableList()
+        val action = ActionButtonViewModel.withNextId(actionAppearance, onClicked)
         actionList.add(action)
         _actions.value = actionList
+        return action.id
     }
 
-    fun addActions(actions: List<ActionButtonViewModel>) {
+    fun setActionVisibility(actionId: Int, visible: Boolean) {
         val actionList = _actions.value.toMutableList()
-        actionList.addAll(actions)
-        _actions.value = actionList
+        val index = actionList.indexOfFirst { it.id == actionId }
+        if (index >= 0) {
+            actionList[index] =
+                ActionButtonViewModel(
+                    actionList[index].appearance,
+                    actionId,
+                    visible,
+                    actionList[index].onClicked
+                )
+            _actions.value = actionList
+        } else {
+            Log.w(TAG, "Attempted to update unknown action id $actionId")
+        }
+    }
+
+    fun updateActionAppearance(actionId: Int, appearance: ActionButtonAppearance) {
+        val actionList = _actions.value.toMutableList()
+        val index = actionList.indexOfFirst { it.id == actionId }
+        if (index >= 0) {
+            actionList[index] =
+                ActionButtonViewModel(
+                    appearance,
+                    actionId,
+                    actionList[index].visible,
+                    actionList[index].onClicked
+                )
+            _actions.value = actionList
+        } else {
+            Log.w(TAG, "Attempted to update unknown action id $actionId")
+        }
+    }
+
+    fun removeAction(actionId: Int) {
+        val actionList = _actions.value.toMutableList()
+        if (actionList.removeIf { it.id == actionId }) {
+            // Update if something was removed.
+            _actions.value = actionList
+        } else {
+            Log.w(TAG, "Attempted to remove unknown action id $actionId")
+        }
     }
 
     fun reset() {
@@ -56,4 +97,8 @@
         _previewAction.value = null
         _actions.value = listOf()
     }
+
+    companion object {
+        const val TAG = "ScreenshotViewModel"
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 92d6ec97..37f2a21 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -47,12 +47,13 @@
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.systemui.Flags;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.util.settings.SecureSettings;
 
 import dagger.assisted.Assisted;
@@ -107,7 +108,7 @@
     private ValueAnimator mSliderAnimator;
 
     @Override
-    public void setMirror(BrightnessMirrorController controller) {
+    public void setMirror(@Nullable MirrorController controller) {
         mControl.setMirrorControllerAndMirror(controller);
     }
 
@@ -371,10 +372,18 @@
         mBackgroundHandler.post(new Runnable() {
             @Override
             public void run() {
-                mControl.setEnforcedAdmin(
+                int userId = mUserTracker.getUserId();
+                RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
                         RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
                                 UserManager.DISALLOW_CONFIG_BRIGHTNESS,
-                                mUserTracker.getUserId()));
+                                userId);
+                if (Flags.enforceBrightnessBaseUserRestriction() && enforcedAdmin == null
+                        && RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
+                        UserManager.DISALLOW_CONFIG_BRIGHTNESS,
+                        userId)) {
+                    enforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+                }
+                mControl.setEnforcedAdmin(enforcedAdmin);
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
index 701d814..073279b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
@@ -16,12 +16,9 @@
 
 package com.android.systemui.settings.brightness
 
-import com.android.systemui.statusbar.policy.BrightnessMirrorController
-import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener
-
 class BrightnessMirrorHandler(brightnessController: MirroredBrightnessController) {
 
-    var mirrorController: BrightnessMirrorController? = null
+    var mirrorController: MirrorController? = null
         private set
 
     var brightnessController: MirroredBrightnessController = brightnessController
@@ -30,7 +27,8 @@
             updateBrightnessMirror()
         }
 
-    private val brightnessMirrorListener = BrightnessMirrorListener { updateBrightnessMirror() }
+    private val brightnessMirrorListener =
+            MirrorController.BrightnessMirrorListener { updateBrightnessMirror() }
 
     fun onQsPanelAttached() {
         mirrorController?.addCallback(brightnessMirrorListener)
@@ -40,7 +38,7 @@
         mirrorController?.removeCallback(brightnessMirrorListener)
     }
 
-    fun setController(controller: BrightnessMirrorController?) {
+    fun setController(controller: MirrorController?) {
         mirrorController?.removeCallback(brightnessMirrorListener)
         mirrorController = controller
         mirrorController?.addCallback(brightnessMirrorListener)
@@ -48,6 +46,6 @@
     }
 
     private fun updateBrightnessMirror() {
-        mirrorController?.let { brightnessController.setMirror(it) }
+        brightnessController.setMirror(mirrorController)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index 539b0c2..083cee7 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -33,7 +33,7 @@
 import com.android.systemui.Gefingerpoken;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.haptics.slider.HapticSliderViewBinder;
-import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin;
+import com.android.systemui.haptics.slider.SeekbarHapticPlugin;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.res.R;
@@ -57,13 +57,15 @@
         ToggleSlider {
 
     private Listener mListener;
+    @Nullable
     private ToggleSlider mMirror;
-    private BrightnessMirrorController mMirrorController;
+    @Nullable
+    private MirrorController mMirrorController;
     private boolean mTracking;
     private final FalsingManager mFalsingManager;
     private final UiEventLogger mUiEventLogger;
 
-    private final SeekableSliderHapticPlugin mBrightnessSliderHapticPlugin;
+    private final SeekbarHapticPlugin mBrightnessSliderHapticPlugin;
     private final ActivityStarter mActivityStarter;
 
     private final Gefingerpoken mOnInterceptListener = new Gefingerpoken() {
@@ -87,7 +89,7 @@
             BrightnessSliderView brightnessSliderView,
             FalsingManager falsingManager,
             UiEventLogger uiEventLogger,
-            SeekableSliderHapticPlugin brightnessSliderHapticPlugin,
+            SeekbarHapticPlugin brightnessSliderHapticPlugin,
             ActivityStarter activityStarter) {
         super(brightnessSliderView);
         mFalsingManager = falsingManager;
@@ -108,6 +110,9 @@
     protected void onViewAttached() {
         mView.setOnSeekBarChangeListener(mSeekListener);
         mView.setOnInterceptListener(mOnInterceptListener);
+        if (mMirror != null) {
+            mView.setOnDispatchTouchEventListener(this::mirrorTouchEvent);
+        }
     }
 
     @Override
@@ -129,7 +134,10 @@
 
     private boolean copyEventToMirror(MotionEvent ev) {
         MotionEvent copy = ev.copy();
-        boolean out = mMirror.mirrorTouchEvent(copy);
+        boolean out = false;
+        if (mMirror != null) {
+            out = mMirror.mirrorTouchEvent(copy);
+        }
         copy.recycle();
         return out;
     }
@@ -166,9 +174,13 @@
      * @param c
      */
     @Override
-    public void setMirrorControllerAndMirror(BrightnessMirrorController c) {
+    public void setMirrorControllerAndMirror(@Nullable MirrorController c) {
         mMirrorController = c;
-        setMirror(c.getToggleSlider());
+        if (c != null) {
+            setMirror(c.getToggleSlider());
+        } else {
+            setMirror(null);
+        }
     }
 
     @Override
@@ -302,7 +314,7 @@
             int layout = getLayout();
             BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context)
                     .inflate(layout, viewRoot, false);
-            SeekableSliderHapticPlugin plugin = new SeekableSliderHapticPlugin(
+            SeekbarHapticPlugin plugin = new SeekbarHapticPlugin(
                     mVibratorHelper,
                     mSystemClock);
             if (hapticBrightnessSlider()) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index 92006a4..e051dab 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -63,7 +63,6 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        setLayerType(LAYER_TYPE_HARDWARE, null);
 
         mSlider = requireViewById(R.id.slider);
         mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/MirrorController.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/MirrorController.kt
new file mode 100644
index 0000000..6a9af26
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/MirrorController.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness
+
+import android.view.View
+import com.android.systemui.settings.brightness.MirrorController.BrightnessMirrorListener
+import com.android.systemui.statusbar.policy.CallbackController
+
+interface MirrorController : CallbackController<BrightnessMirrorListener> {
+
+    /**
+     * Get the [ToggleSlider] currently associated with this controller, or `null` if none currently
+     */
+    fun getToggleSlider(): ToggleSlider?
+
+    /**
+     * Indicate to this controller that the user is dragging on the brightness view and the mirror
+     * should show
+     */
+    fun showMirror()
+
+    /**
+     * Indicate to this controller that the user has stopped dragging on the brightness view and the
+     * mirror should hide
+     */
+    fun hideMirror()
+
+    /**
+     * Set the location and size of the current brightness [view] in QS so it can be properly
+     * adapted to show the mirror in the same location and with the same size.
+     */
+    fun setLocationAndSize(view: View)
+
+    fun interface BrightnessMirrorListener {
+        fun onBrightnessMirrorReinflated(brightnessMirror: View?)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
index 8d857de..b1a532b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
@@ -22,5 +22,5 @@
  * Indicates controller that has brightness slider and uses [BrightnessMirrorController]
  */
 interface MirroredBrightnessController {
-    fun setMirror(controller: BrightnessMirrorController)
+    fun setMirror(controller: MirrorController?)
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
index 648e33b..24bc670 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
@@ -19,7 +19,6 @@
 import android.view.MotionEvent;
 
 import com.android.settingslib.RestrictedLockUtils;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 
 public interface ToggleSlider {
     interface Listener {
@@ -27,7 +26,7 @@
     }
 
     void setEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin);
-    void setMirrorControllerAndMirror(BrightnessMirrorController c);
+    void setMirrorControllerAndMirror(MirrorController c);
     boolean mirrorTouchEvent(MotionEvent ev);
 
     void setOnChangedListener(Listener l);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepository.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepository.kt
new file mode 100644
index 0000000..a0c9be4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepository.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+@SysUISingleton
+class BrightnessMirrorShowingRepository @Inject constructor() {
+    private val _isShowing = MutableStateFlow(false)
+    val isShowing = _isShowing.asStateFlow()
+
+    fun setMirrorShowing(showing: Boolean) {
+        _isShowing.value = showing
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractor.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractor.kt
new file mode 100644
index 0000000..ef6e72f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractor.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.settings.brightness.data.repository.BrightnessMirrorShowingRepository
+import javax.inject.Inject
+
+@SysUISingleton
+class BrightnessMirrorShowingInteractor
+@Inject
+constructor(
+    private val brightnessMirrorShowingRepository: BrightnessMirrorShowingRepository,
+) {
+    val isShowing = brightnessMirrorShowingRepository.isShowing
+
+    fun setMirrorShowing(showing: Boolean) {
+        brightnessMirrorShowingRepository.setMirrorShowing(showing)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflater.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflater.kt
new file mode 100644
index 0000000..468a873
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflater.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.ui.binder
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.isVisible
+import com.android.systemui.res.R
+import com.android.systemui.settings.brightness.BrightnessSliderController
+
+object BrightnessMirrorInflater {
+
+    fun inflate(
+        context: Context,
+        sliderControllerFactory: BrightnessSliderController.Factory,
+    ): Pair<View, BrightnessSliderController> {
+        val frame =
+            (LayoutInflater.from(context).inflate(R.layout.brightness_mirror_container, null)
+                    as ViewGroup)
+                .apply { isVisible = true }
+        val sliderController = sliderControllerFactory.create(context, frame)
+        sliderController.init()
+        frame.addView(
+            sliderController.rootView,
+            ViewGroup.LayoutParams.MATCH_PARENT,
+            ViewGroup.LayoutParams.WRAP_CONTENT
+        )
+        return frame to sliderController
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/viewModel/BrightnessMirrorViewModel.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/viewModel/BrightnessMirrorViewModel.kt
new file mode 100644
index 0000000..2651a994
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/viewModel/BrightnessMirrorViewModel.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.ui.viewModel
+
+import android.content.res.Resources
+import android.view.View
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
+import com.android.systemui.settings.brightness.BrightnessSliderController
+import com.android.systemui.settings.brightness.MirrorController
+import com.android.systemui.settings.brightness.ToggleSlider
+import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+@SysUISingleton
+class BrightnessMirrorViewModel
+@Inject
+constructor(
+    private val brightnessMirrorShowingInteractor: BrightnessMirrorShowingInteractor,
+    @Main private val resources: Resources,
+    val sliderControllerFactory: BrightnessSliderController.Factory,
+) : MirrorController {
+
+    private val tempPosition = IntArray(2)
+
+    private var _toggleSlider: BrightnessSliderController? = null
+
+    val isShowing = brightnessMirrorShowingInteractor.isShowing
+
+    private val _locationAndSize: MutableStateFlow<LocationAndSize> =
+        MutableStateFlow(LocationAndSize())
+    val locationAndSize = _locationAndSize.asStateFlow()
+
+    override fun getToggleSlider(): ToggleSlider? {
+        return _toggleSlider
+    }
+
+    fun setToggleSlider(toggleSlider: BrightnessSliderController) {
+        _toggleSlider = toggleSlider
+    }
+
+    override fun showMirror() {
+        brightnessMirrorShowingInteractor.setMirrorShowing(true)
+    }
+
+    override fun hideMirror() {
+        brightnessMirrorShowingInteractor.setMirrorShowing(false)
+    }
+
+    override fun setLocationAndSize(view: View) {
+        view.getLocationInWindow(tempPosition)
+        val padding = resources.getDimensionPixelSize(R.dimen.rounded_slider_background_padding)
+        _toggleSlider?.rootView?.setPadding(padding, padding, padding, padding)
+        // Account for desired padding
+        _locationAndSize.value =
+            LocationAndSize(
+                yOffset = tempPosition[1] - padding,
+                width = view.measuredWidth + 2 * padding,
+                height = view.measuredHeight + 2 * padding,
+            )
+    }
+
+    // Callbacks are used for indicating reinflation when the config changes in some ways (like
+    // density). However, we don't need that as we recompose the view anyway
+    override fun addCallback(listener: MirrorController.BrightnessMirrorListener) {}
+
+    override fun removeCallback(listener: MirrorController.BrightnessMirrorListener) {}
+}
+
+data class LocationAndSize(
+    val yOffset: Int = 0,
+    val width: Int = 0,
+    val height: Int = 0,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java b/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
index c42fdf8..b24edd9 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
@@ -25,6 +25,7 @@
 import android.graphics.drawable.Drawable;
 
 import com.android.keyguard.LockIconViewController;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 
 import java.util.HashSet;
@@ -80,12 +81,14 @@
                         mNotificationPanelViewController.getClockPositionResult()
                                 .stackScrollerPadding),
                 Color.YELLOW, "calculatePanelHeightShade()");
-        drawDebugInfo(canvas,
-                (int) mQsController.calculateNotificationsTopPadding(
-                        mNotificationPanelViewController.isExpandingOrCollapsing(),
-                        mNotificationPanelViewController.getKeyguardNotificationStaticPadding(),
-                        mNotificationPanelViewController.getExpandedFraction()),
-                Color.MAGENTA, "calculateNotificationsTopPadding()");
+        if (!SceneContainerFlag.isEnabled()) {
+            drawDebugInfo(canvas,
+                    (int) mQsController.calculateNotificationsTopPadding(
+                            mNotificationPanelViewController.isExpandingOrCollapsing(),
+                            mNotificationPanelViewController.getKeyguardNotificationStaticPadding(),
+                            mNotificationPanelViewController.getExpandedFraction()),
+                    Color.MAGENTA, "calculateNotificationsTopPadding()");
+        }
         drawDebugInfo(canvas, mNotificationPanelViewController.getClockPositionResult().clockY,
                 Color.GRAY, "mClockPositionResult.clockY");
         drawDebugInfo(canvas, (int) mLockIconViewController.getTop(), Color.GRAY,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index f6b1bcc..a5a5474 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -23,23 +23,39 @@
 import android.view.MotionEvent
 import android.view.View
 import android.view.ViewGroup
+import androidx.activity.OnBackPressedDispatcher
+import androidx.activity.OnBackPressedDispatcherOwner
+import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
 import androidx.compose.ui.platform.ComposeView
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import com.android.compose.theme.PlatformTheme
 import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.ambient.touch.TouchMonitor
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
 import com.android.systemui.communal.dagger.Communal
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.ui.compose.CommunalContainer
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
+import com.android.systemui.communal.util.CommunalColors
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialogFactory
+import com.android.systemui.util.kotlin.BooleanFlowOperators.and
+import com.android.systemui.util.kotlin.BooleanFlowOperators.not
+import com.android.systemui.util.kotlin.BooleanFlowOperators.or
 import com.android.systemui.util.kotlin.collectFlow
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.launch
 
 /**
  * Controller that's responsible for the glanceable hub container view and its touch handling.
@@ -56,12 +72,28 @@
     private val keyguardInteractor: KeyguardInteractor,
     private val shadeInteractor: ShadeInteractor,
     private val powerManager: PowerManager,
-    @Communal private val dataSourceDelegator: SceneDataSourceDelegator,
-) {
+    private val communalColors: CommunalColors,
+    private val ambientTouchComponentFactory: AmbientTouchComponent.Factory,
+    @Communal private val dataSourceDelegator: SceneDataSourceDelegator
+) : LifecycleOwner {
     /** The container view for the hub. This will not be initialized until [initView] is called. */
     private var communalContainerView: View? = null
 
     /**
+     * This lifecycle is used to control when the [touchMonitor] listens to touches. The lifecycle
+     * should only be [Lifecycle.State.RESUMED] when the hub is showing and not covered by anything,
+     * such as the notification shade or bouncer.
+     */
+    private var lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
+
+    /**
+     * This [TouchMonitor] listens for top and bottom swipe gestures globally when the hub is open.
+     * When a top or bottom swipe is detected, they will be intercepted and used to open the
+     * notification shade/bouncer.
+     */
+    private var touchMonitor: TouchMonitor? = null
+
+    /**
      * The width of the area in which a right edge swipe can open the hub, in pixels. Read from
      * resources when [initView] is called.
      */
@@ -69,20 +101,6 @@
     private var rightEdgeSwipeRegionWidth: Int = 0
 
     /**
-     * The height of the area in which a top edge swipe while the hub is open will not intercept
-     * touches, in pixels. This allows the top edge swipe to instead open the notification shade.
-     * Read from resources when [initView] is called.
-     */
-    private var topEdgeSwipeRegionWidth: Int = 0
-
-    /**
-     * The height of the area in which a bottom edge swipe while the hub is open will not intercept
-     * touches, in pixels. This allows the bottom edge swipe to instead open the bouncer. Read from
-     * resources when [initView] is called.
-     */
-    private var bottomEdgeSwipeRegionWidth: Int = 0
-
-    /**
      * True if we are currently tracking a gesture for opening the hub that started in the edge
      * swipe region.
      */
@@ -91,9 +109,6 @@
     /** True if we are currently tracking a touch on the hub while it's open. */
     private var isTrackingHubTouch = false
 
-    /** True if we are tracking a top or bottom swipe gesture while the hub is open. */
-    private var isTrackingHubGesture = false
-
     /**
      * True if the hub UI is fully open, meaning it should receive touch input.
      *
@@ -110,9 +125,15 @@
     private var anyBouncerShowing = false
 
     /**
-     * True if the shade is fully expanded, meaning the hub should not receive any touch input.
+     * True if the shade is fully expanded and the user is not interacting with it anymore, meaning
+     * the hub should not receive any touch input.
      *
-     * Tracks [ShadeInteractor.isAnyFullyExpanded].
+     * We need to not pause the touch handling lifecycle as soon as the shade opens because if the
+     * user swipes down, then back up without lifting their finger, the lifecycle will be paused
+     * then resumed, and resuming force-stops all active touch sessions. This means the shade will
+     * not receive the end of the gesture and will be stuck open.
+     *
+     * Based on [ShadeInteractor.isAnyFullyExpanded] and [ShadeInteractor.isUserInteracting].
      */
     private var shadeShowing = false
 
@@ -121,13 +142,12 @@
      * and just let the dream overlay's touch handling deal with them.
      *
      * Tracks [KeyguardInteractor.isDreaming].
-     *
-     * TODO(b/328838259): figure out a proper solution for touch handling above the lock screen too
      */
     private var isDreaming = false
 
     /** Returns a flow that tracks whether communal hub is available. */
-    fun communalAvailable(): Flow<Boolean> = communalInteractor.isCommunalAvailable
+    fun communalAvailable(): Flow<Boolean> =
+        or(communalInteractor.isCommunalAvailable, communalInteractor.editModeOpen)
 
     /**
      * Creates the container view containing the glanceable hub UI.
@@ -139,13 +159,34 @@
     ): View {
         return initView(
             ComposeView(context).apply {
-                setContent {
-                    PlatformTheme {
-                        CommunalContainer(
-                            viewModel = communalViewModel,
-                            dataSourceDelegator = dataSourceDelegator,
-                            dialogFactory = dialogFactory,
-                        )
+                repeatWhenAttached {
+                    lifecycleScope.launch {
+                        repeatOnLifecycle(Lifecycle.State.CREATED) {
+                            setViewTreeOnBackPressedDispatcherOwner(
+                                object : OnBackPressedDispatcherOwner {
+                                    override val onBackPressedDispatcher =
+                                        OnBackPressedDispatcher().apply {
+                                            setOnBackInvokedDispatcher(
+                                                viewRootImpl.onBackInvokedDispatcher
+                                            )
+                                        }
+
+                                    override val lifecycle: Lifecycle =
+                                        [email protected]
+                                }
+                            )
+
+                            setContent {
+                                PlatformTheme {
+                                    CommunalContainer(
+                                        viewModel = communalViewModel,
+                                        colors = communalColors,
+                                        dataSourceDelegator = dataSourceDelegator,
+                                        dialogFactory = dialogFactory,
+                                    )
+                                }
+                            }
+                        }
                     }
                 }
             }
@@ -159,28 +200,45 @@
             throw RuntimeException("Communal view has already been initialized")
         }
 
+        if (touchMonitor == null) {
+            touchMonitor =
+                ambientTouchComponentFactory.create(this, HashSet()).getTouchMonitor().apply {
+                    init()
+                }
+        }
+        lifecycleRegistry.currentState = Lifecycle.State.CREATED
+
         communalContainerView = containerView
 
         rightEdgeSwipeRegionWidth =
             containerView.resources.getDimensionPixelSize(
                 R.dimen.communal_right_edge_swipe_region_width
             )
-        topEdgeSwipeRegionWidth =
-            containerView.resources.getDimensionPixelSize(
-                R.dimen.communal_top_edge_swipe_region_height
-            )
-        bottomEdgeSwipeRegionWidth =
-            containerView.resources.getDimensionPixelSize(
-                R.dimen.communal_bottom_edge_swipe_region_height
-            )
 
         collectFlow(
             containerView,
             keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState),
-            { anyBouncerShowing = it }
+            {
+                anyBouncerShowing = it
+                updateLifecycleState()
+            }
         )
-        collectFlow(containerView, communalInteractor.isCommunalShowing, { hubShowing = it })
-        collectFlow(containerView, shadeInteractor.isAnyFullyExpanded, { shadeShowing = it })
+        collectFlow(
+            containerView,
+            communalInteractor.isCommunalShowing,
+            {
+                hubShowing = it
+                updateLifecycleState()
+            }
+        )
+        collectFlow(
+            containerView,
+            and(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)),
+            {
+                shadeShowing = it
+                updateLifecycleState()
+            }
+        )
         collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it })
 
         communalContainerView = containerView
@@ -188,10 +246,24 @@
         return containerView
     }
 
+    /**
+     * Updates the lifecycle stored by the [lifecycleRegistry] to control when the [touchMonitor]
+     * should listen for and intercept top and bottom swipes.
+     */
+    private fun updateLifecycleState() {
+        val shouldInterceptGestures = hubShowing && !(shadeShowing || anyBouncerShowing)
+        if (shouldInterceptGestures) {
+            lifecycleRegistry.currentState = Lifecycle.State.RESUMED
+        } else {
+            lifecycleRegistry.currentState = Lifecycle.State.STARTED
+        }
+    }
+
     /** Removes the container view from its parent. */
     fun disposeView() {
         communalContainerView?.let {
             (it.parent as ViewGroup).removeView(it)
+            lifecycleRegistry.currentState = Lifecycle.State.CREATED
             communalContainerView = null
         }
     }
@@ -229,15 +301,7 @@
         if (isDown && !hubOccluded) {
             // Only intercept down events if the hub isn't occluded by the bouncer or
             // notification shade.
-            val y = ev.rawY
-            val topSwipe: Boolean = y <= topEdgeSwipeRegionWidth
-            val bottomSwipe = y >= view.height - bottomEdgeSwipeRegionWidth
-
-            if (topSwipe || bottomSwipe) {
-                isTrackingHubGesture = true
-            } else {
-                isTrackingHubTouch = true
-            }
+            isTrackingHubTouch = true
         }
 
         if (isTrackingHubTouch) {
@@ -250,19 +314,6 @@
             // gesture
             // may return false from dispatchTouchEvent.
             return true
-        } else if (isTrackingHubGesture) {
-            // Tracking a top or bottom swipe on the hub UI.
-            if (isUp || isCancel) {
-                isTrackingHubGesture = false
-            }
-
-            // If we're dreaming, intercept touches so the hub UI doesn't receive them, but
-            // don't do anything so that the dream's touch handling takes care of opening
-            // the bouncer or shade.
-            //
-            // If we're not dreaming, we don't intercept touches at the top/bottom edge so that
-            // swipes can open the notification shade and bouncer.
-            return isDreaming
         }
 
         return false
@@ -314,4 +365,7 @@
             0
         )
     }
+
+    override val lifecycle: Lifecycle
+        get() = lifecycleRegistry
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index dcfd47b..aa915e3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -30,6 +30,11 @@
 import static com.android.systemui.classifier.Classifier.GENERIC;
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
 import static com.android.systemui.classifier.Classifier.UNLOCK;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING_LOCKSCREEN_HOSTED;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.GONE;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED;
 import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll;
 import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
 import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED;
@@ -186,6 +191,7 @@
 import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor;
+import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor;
 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -286,7 +292,6 @@
      */
 
     public final boolean mAnimateBack;
-    private final boolean mTrackpadGestureFeaturesEnabled;
     /**
      * The minimum scale to "squish" the Shade and associated elements down to, for Back gesture
      */
@@ -433,6 +438,7 @@
     private boolean mExpandingFromHeadsUp;
     private boolean mCollapsedOnDown;
     private boolean mClosingWithAlphaFadeOut;
+    private boolean mHeadsUpVisible;
     private boolean mHeadsUpAnimatingAway;
     private final FalsingManager mFalsingManager;
     private final FalsingCollector mFalsingCollector;
@@ -600,6 +606,7 @@
     private final PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
     private final SharedNotificationContainerInteractor mSharedNotificationContainerInteractor;
     private final ActiveNotificationsInteractor mActiveNotificationsInteractor;
+    private final HeadsUpNotificationInteractor mHeadsUpNotificationInteractor;
     private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private final KeyguardInteractor mKeyguardInteractor;
     private final PowerInteractor mPowerInteractor;
@@ -765,6 +772,7 @@
             ActivityStarter activityStarter,
             SharedNotificationContainerInteractor sharedNotificationContainerInteractor,
             ActiveNotificationsInteractor activeNotificationsInteractor,
+            HeadsUpNotificationInteractor headsUpNotificationInteractor,
             ShadeAnimationInteractor shadeAnimationInteractor,
             KeyguardViewConfigurator keyguardViewConfigurator,
             DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
@@ -799,6 +807,7 @@
         mKeyguardTransitionInteractor = keyguardTransitionInteractor;
         mSharedNotificationContainerInteractor = sharedNotificationContainerInteractor;
         mActiveNotificationsInteractor = activeNotificationsInteractor;
+        mHeadsUpNotificationInteractor = headsUpNotificationInteractor;
         mKeyguardInteractor = keyguardInteractor;
         mPowerInteractor = powerInteractor;
         mKeyguardViewConfigurator = keyguardViewConfigurator;
@@ -881,7 +890,6 @@
         mLayoutInflater = layoutInflater;
         mFeatureFlags = featureFlags;
         mAnimateBack = predictiveBackAnimateShade();
-        mTrackpadGestureFeaturesEnabled = mFeatureFlags.isEnabled(Flags.TRACKPAD_GESTURE_FEATURES);
         mFalsingCollector = falsingCollector;
         mWakeUpCoordinator = coordinator;
         mMainDispatcher = mainDispatcher;
@@ -1119,7 +1127,7 @@
                 controller.setup(mNotificationContainerParent));
 
         // Dreaming->Lockscreen
-        collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
+        collectFlow(mView, mKeyguardTransitionInteractor.transition(DREAMING, LOCKSCREEN),
                 mDreamingToLockscreenTransition, mMainDispatcher);
         collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
                 setDreamLockscreenTransitionAlpha(mNotificationStackScrollLayoutController),
@@ -1130,7 +1138,7 @@
 
         // Gone -> Dreaming hosted in lockscreen
         collectFlow(mView, mKeyguardTransitionInteractor
-                        .getGoneToDreamingLockscreenHostedTransition(),
+                        .transition(GONE, DREAMING_LOCKSCREEN_HOSTED),
                 mGoneToDreamingLockscreenHostedTransition, mMainDispatcher);
         collectFlow(mView, mGoneToDreamingLockscreenHostedTransitionViewModel.getLockscreenAlpha(),
                 setTransitionAlpha(mNotificationStackScrollLayoutController),
@@ -1138,16 +1146,16 @@
 
         // Lockscreen -> Dreaming hosted in lockscreen
         collectFlow(mView, mKeyguardTransitionInteractor
-                        .getLockscreenToDreamingLockscreenHostedTransition(),
+                        .transition(LOCKSCREEN, DREAMING_LOCKSCREEN_HOSTED),
                 mLockscreenToDreamingLockscreenHostedTransition, mMainDispatcher);
 
         // Dreaming hosted in lockscreen -> Lockscreen
         collectFlow(mView, mKeyguardTransitionInteractor
-                        .getDreamingLockscreenHostedToLockscreenTransition(),
+                        .transition(DREAMING_LOCKSCREEN_HOSTED, LOCKSCREEN),
                 mDreamingLockscreenHostedToLockscreenTransition, mMainDispatcher);
 
         // Occluded->Lockscreen
-        collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
+        collectFlow(mView, mKeyguardTransitionInteractor.transition(OCCLUDED, LOCKSCREEN),
                 mOccludedToLockscreenTransition, mMainDispatcher);
         if (!MigrateClocksToBlueprint.isEnabled()) {
             collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
@@ -1158,7 +1166,7 @@
         }
 
         // Lockscreen->Dreaming
-        collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+        collectFlow(mView, mKeyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING),
                 mLockscreenToDreamingTransition, mMainDispatcher);
         if (!MigrateClocksToBlueprint.isEnabled()) {
             collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
@@ -1170,7 +1178,7 @@
                 setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
         // Gone->Dreaming
-        collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
+        collectFlow(mView, mKeyguardTransitionInteractor.transition(GONE, DREAMING),
                 mGoneToDreamingTransition, mMainDispatcher);
         if (!MigrateClocksToBlueprint.isEnabled()) {
             collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
@@ -1181,7 +1189,7 @@
                 setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
         // Lockscreen->Occluded
-        collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
+        collectFlow(mView, mKeyguardTransitionInteractor.transition(LOCKSCREEN, OCCLUDED),
                 mLockscreenToOccludedTransition, mMainDispatcher);
         if (!MigrateClocksToBlueprint.isEnabled()) {
             collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
@@ -1201,6 +1209,21 @@
                                 "mPrimaryBouncerToGoneTransitionViewModel.getNotificationAlpha()");
                     }, mMainDispatcher);
         }
+
+        // Ensures that flags are updated when an activity launches
+        collectFlow(mView,
+                mShadeAnimationInteractor.isLaunchingActivity(),
+                isLaunchingActivity -> {
+                    if (isLaunchingActivity) {
+                        updateSystemUiStateFlags();
+                    }
+                },
+                mMainDispatcher);
+
+        if (NotificationsHeadsUpRefactor.isEnabled()) {
+            collectFlow(mView, mHeadsUpNotificationInteractor.isHeadsUpOrAnimatingAway(),
+                    setHeadsUpVisible(), mMainDispatcher);
+        }
     }
 
     @VisibleForTesting
@@ -1588,7 +1611,8 @@
      * @param forceClockUpdate Should the clock be updated even when not on keyguard
      */
     private void positionClockAndNotifications(boolean forceClockUpdate) {
-        boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
+        boolean animate = !SceneContainerFlag.isEnabled()
+                && mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
         int stackScrollerPadding;
         boolean onKeyguard = isKeyguardShowing();
 
@@ -1675,7 +1699,8 @@
                 mClockPositionResult.clockX, mClockPositionResult.clockY);
         }
 
-        boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
+        boolean animate = !SceneContainerFlag.isEnabled()
+                && mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
         boolean animateClock = (animate || mAnimateNextPositionUpdate) && shouldAnimateClockChange;
 
         if (!MigrateClocksToBlueprint.isEnabled()) {
@@ -2483,6 +2508,7 @@
 
     /** Returns the topPadding of notifications when on keyguard not respecting QS expansion. */
     int getKeyguardNotificationStaticPadding() {
+        SceneContainerFlag.assertInLegacyMode();
         if (!isKeyguardShowing()) {
             return 0;
         }
@@ -2524,12 +2550,14 @@
     }
 
     void requestScrollerTopPaddingUpdate(boolean animate) {
-        float padding = mQsController.calculateNotificationsTopPadding(mIsExpandingOrCollapsing,
-                getKeyguardNotificationStaticPadding(), mExpandedFraction);
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            mSharedNotificationContainerInteractor.setTopPosition(padding);
-        } else {
-            mNotificationStackScrollLayoutController.updateTopPadding(padding, animate);
+        if (!SceneContainerFlag.isEnabled()) {
+            float padding = mQsController.calculateNotificationsTopPadding(mIsExpandingOrCollapsing,
+                    getKeyguardNotificationStaticPadding(), mExpandedFraction);
+            if (MigrateClocksToBlueprint.isEnabled()) {
+                mSharedNotificationContainerInteractor.setTopPosition(padding);
+            } else {
+                mNotificationStackScrollLayoutController.updateTopPadding(padding, animate);
+            }
         }
 
         if (isKeyguardShowing()
@@ -3035,7 +3063,21 @@
         mPanelAlphaEndAction = r;
     }
 
+    private Consumer<Boolean> setHeadsUpVisible() {
+        return (Boolean isHeadsUpVisible) -> {
+            mHeadsUpVisible = isHeadsUpVisible;
+
+            if (isHeadsUpVisible) {
+                updateNotificationTranslucency();
+            }
+            updateExpansionAndVisibility();
+            updateGestureExclusionRect();
+            mKeyguardStatusBarViewController.updateForHeadsUp();
+        };
+    }
+
     private void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+        NotificationsHeadsUpRefactor.assertInLegacyMode();
         mHeadsUpAnimatingAway = headsUpAnimatingAway;
         mNotificationStackScrollLayoutController.setHeadsUpAnimatingAway(headsUpAnimatingAway);
         updateVisibility();
@@ -3051,13 +3093,16 @@
     }
 
     private boolean shouldPanelBeVisible() {
-        boolean headsUpVisible = mHeadsUpAnimatingAway || mHeadsUpPinnedMode;
+        boolean headsUpVisible = NotificationsHeadsUpRefactor.isEnabled() ? mHeadsUpVisible
+                : (mHeadsUpAnimatingAway || mHeadsUpPinnedMode);
         return headsUpVisible || isExpanded() || mBouncerShowing;
     }
 
     private void setHeadsUpManager(HeadsUpManager headsUpManager) {
         mHeadsUpManager = headsUpManager;
-        mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
+        if (!NotificationsHeadsUpRefactor.isEnabled()) {
+            mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
+        }
         mHeadsUpTouchHelper = new HeadsUpTouchHelper(
                 headsUpManager,
                 mStatusBarService,
@@ -3145,8 +3190,9 @@
     }
 
     private boolean isPanelVisibleBecauseOfHeadsUp() {
-        return (mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway)
-                && mBarState == StatusBarState.SHADE;
+        boolean headsUpVisible = NotificationsHeadsUpRefactor.isEnabled() ? mHeadsUpVisible
+                : (mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway);
+        return headsUpVisible && mBarState == StatusBarState.SHADE;
     }
 
     private boolean isPanelVisibleBecauseScrimIsAnimatingOff() {
@@ -3459,6 +3505,7 @@
         ipw.print("mExpandingFromHeadsUp="); ipw.println(mExpandingFromHeadsUp);
         ipw.print("mCollapsedOnDown="); ipw.println(mCollapsedOnDown);
         ipw.print("mClosingWithAlphaFadeOut="); ipw.println(mClosingWithAlphaFadeOut);
+        ipw.print("mHeadsUpVisible="); ipw.println(mHeadsUpVisible);
         ipw.print("mHeadsUpAnimatingAway="); ipw.println(mHeadsUpAnimatingAway);
         ipw.print("mShowIconsWhenExpanded="); ipw.println(mShowIconsWhenExpanded);
         ipw.print("mIndicationBottomPadding="); ipw.println(mIndicationBottomPadding);
@@ -3627,7 +3674,8 @@
                     + isFullyExpanded() + " inQs=" + mQsController.getExpanded());
         }
         mSysUiState
-                .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE, isPanelExpanded())
+                .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE,
+                        isPanelExpanded() && !isCollapsing())
                 .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
                         isFullyExpanded() && !mQsController.getExpanded())
                 .setFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
@@ -3964,7 +4012,9 @@
             mShadeRepository.setLegacyShadeExpansion(mExpandedFraction);
             mQsController.setShadeExpansion(mExpandedHeight, mExpandedFraction);
             mExpansionDragDownAmountPx = h;
-            mAmbientState.setExpansionFraction(mExpandedFraction);
+            if (!SceneContainerFlag.isEnabled()) {
+                mAmbientState.setExpansionFraction(mExpandedFraction);
+            }
             onHeightUpdated(mExpandedHeight);
             updateExpansionAndVisibility();
         });
@@ -4361,6 +4411,8 @@
     private final class ShadeHeadsUpChangedListener implements OnHeadsUpChangedListener {
         @Override
         public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {
+            NotificationsHeadsUpRefactor.assertInLegacyMode();
+
             if (inPinnedMode) {
                 mHeadsUpExistenceChangedRunnable.run();
                 updateNotificationTranslucency();
@@ -4377,9 +4429,7 @@
 
         @Override
         public void onHeadsUpPinned(NotificationEntry entry) {
-            if (NotificationsHeadsUpRefactor.isEnabled()) {
-                return;
-            }
+            NotificationsHeadsUpRefactor.assertInLegacyMode();
 
             if (!isKeyguardShowing()) {
                 mNotificationStackScrollLayoutController.generateHeadsUpAnimation(entry, true);
@@ -4388,9 +4438,7 @@
 
         @Override
         public void onHeadsUpUnPinned(NotificationEntry entry) {
-            if (NotificationsHeadsUpRefactor.isEnabled()) {
-                return;
-            }
+            NotificationsHeadsUpRefactor.assertInLegacyMode();
 
             // When we're unpinning the notification via active edge they remain heads-upped,
             // we need to make sure that an animation happens in this case, otherwise the
@@ -4875,9 +4923,8 @@
             final float x = event.getX(pointerIndex);
             final float y = event.getY(pointerIndex);
             boolean canCollapsePanel = canCollapsePanelOnTouch();
-            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(
-                    mTrackpadGestureFeaturesEnabled, event) || isTrackpadThreeFingerSwipe(
-                    mTrackpadGestureFeaturesEnabled, event);
+            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(event)
+                    || isTrackpadThreeFingerSwipe(event);
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
@@ -4897,7 +4944,7 @@
 
                     mIsTrackpadReverseScroll =
                             !mNaturalScrollingSettingObserver.isNaturalScrollingEnabled()
-                                    && isTrackpadScroll(mTrackpadGestureFeaturesEnabled, event);
+                                    && isTrackpadScroll(event);
                     if (!isTracking() || isFullyCollapsed()) {
                         mInitialExpandY = y;
                         mInitialExpandX = x;
@@ -5120,9 +5167,8 @@
                 mIgnoreXTouchSlop = true;
             }
 
-            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(
-                    mTrackpadGestureFeaturesEnabled, event) || isTrackpadThreeFingerSwipe(
-                    mTrackpadGestureFeaturesEnabled, event);
+            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(event)
+                    || isTrackpadThreeFingerSwipe(event);
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 89e8413..8b7e11c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -59,7 +59,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.scene.ui.view.WindowRootViewComponent;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.domain.interactor.ShadeInteractor;
@@ -117,7 +117,6 @@
     private final AuthController mAuthController;
     private final Lazy<SelectedUserInteractor> mUserInteractor;
     private final Lazy<ShadeInteractor> mShadeInteractorLazy;
-    private final SceneContainerFlags mSceneContainerFlags;
     private final Lazy<CommunalInteractor> mCommunalInteractor;
     private ViewGroup mWindowRootView;
     private LayoutParams mLp;
@@ -166,7 +165,6 @@
             ShadeWindowLogger logger,
             Lazy<SelectedUserInteractor> userInteractor,
             UserTracker userTracker,
-            SceneContainerFlags sceneContainerFlags,
             Lazy<CommunalInteractor> communalInteractor) {
         mContext = context;
         mWindowRootViewComponentFactory = windowRootViewComponentFactory;
@@ -186,7 +184,6 @@
         dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this);
         mAuthController = authController;
         mUserInteractor = userInteractor;
-        mSceneContainerFlags = sceneContainerFlags;
         mCommunalInteractor = communalInteractor;
         mLastKeyguardRotationAllowed = mKeyguardStateController.isKeyguardScreenRotationAllowed();
         mLockScreenDisplayTimeout = context.getResources()
@@ -289,7 +286,7 @@
         mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mLp.privateFlags |= PRIVATE_FLAG_OPTIMIZE_MEASURE;
 
-        if (mSceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             // This prevents the appearance and disappearance of the software keyboard (also known
             // as the "IME") from scrolling/panning the window to make room for the keyboard.
             //
@@ -417,6 +414,12 @@
         } else {
             mLpChanged.flags &= ~LayoutParams.FLAG_SECURE;
         }
+
+        if (state.bouncerShowing) {
+            mLpChanged.inputFeatures |= LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+        } else {
+            mLpChanged.inputFeatures &= ~LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
+        }
     }
 
     protected boolean isDebuggable() {
@@ -445,6 +448,9 @@
                 || mScreenOffAnimationController.shouldIgnoreKeyguardTouches()) {
             mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
             mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else if (state.glanceableHubShowing) {
+            mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
             mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
             // Make sure to remove FLAG_ALT_FOCUSABLE_IM when keyguard needs input.
@@ -608,6 +614,7 @@
                 state.panelVisible,
                 state.shadeOrQsExpanded,
                 state.notificationShadeFocusable,
+                state.glanceableHubShowing,
                 state.bouncerShowing,
                 state.keyguardFadingAway,
                 state.keyguardGoingAway,
@@ -737,6 +744,12 @@
     }
 
     @Override
+    public void setGlanceableHubShowing(boolean showing) {
+        mCurrentState.glanceableHubShowing = showing;
+        apply(mCurrentState);
+    }
+
+    @Override
     public void setBackdropShowing(boolean showing) {
         mCurrentState.mediaBackdropShowing = showing;
         apply(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
index e0a98b3..6a4b52a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
@@ -35,6 +35,7 @@
     @JvmField var shadeOrQsExpanded: Boolean = false,
     @JvmField var notificationShadeFocusable: Boolean = false,
     @JvmField var bouncerShowing: Boolean = false,
+    @JvmField var glanceableHubShowing: Boolean = false,
     @JvmField var keyguardFadingAway: Boolean = false,
     @JvmField var keyguardGoingAway: Boolean = false,
     @JvmField var qsExpanded: Boolean = false,
@@ -79,6 +80,7 @@
             shadeOrQsExpanded.toString(),
             notificationShadeFocusable.toString(),
             bouncerShowing.toString(),
+            glanceableHubShowing.toString(),
             keyguardFadingAway.toString(),
             keyguardGoingAway.toString(),
             qsExpanded.toString(),
@@ -119,6 +121,7 @@
             panelVisible: Boolean,
             panelExpanded: Boolean,
             notificationShadeFocusable: Boolean,
+            glanceableHubShowing: Boolean,
             bouncerShowing: Boolean,
             keyguardFadingAway: Boolean,
             keyguardGoingAway: Boolean,
@@ -149,6 +152,7 @@
                 this.panelVisible = panelVisible
                 this.shadeOrQsExpanded = panelExpanded
                 this.notificationShadeFocusable = notificationShadeFocusable
+                this.glanceableHubShowing = glanceableHubShowing
                 this.bouncerShowing = bouncerShowing
                 this.keyguardFadingAway = keyguardFadingAway
                 this.keyguardGoingAway = keyguardGoingAway
@@ -197,6 +201,7 @@
                 "panelVisible",
                 "panelExpanded",
                 "notificationShadeFocusable",
+                "glanceableHubShowing",
                 "bouncerShowing",
                 "keyguardFadingAway",
                 "keyguardGoingAway",
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index f9b4e67..903af61 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -81,6 +81,8 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
+        mInteractionEventHandler.collectKeyEvent(event);
+
         if (mInteractionEventHandler.interceptMediaKey(event)) {
             return true;
         }
@@ -301,6 +303,11 @@
         boolean dispatchKeyEvent(KeyEvent event);
 
         boolean dispatchKeyEventPreIme(KeyEvent event);
+
+        /**
+         * Collects the KeyEvent without intercepting it
+         */
+        void collectKeyEvent(KeyEvent event);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 324dfdf..44f86da 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -17,14 +17,14 @@
 package com.android.systemui.shade;
 
 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
-import static com.android.systemui.flags.Flags.TRACKPAD_GESTURE_COMMON;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING;
+import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN;
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
 import android.app.StatusBarManager;
 import android.util.Log;
 import android.view.GestureDetector;
-import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -73,14 +73,14 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.util.time.SystemClock;
 
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
 import java.io.PrintWriter;
 import java.util.Optional;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
 /**
  * Controller for {@link NotificationShadeWindowView}.
  */
@@ -102,7 +102,6 @@
     private final PulsingGestureListener mPulsingGestureListener;
     private final LockscreenHostedDreamGestureListener mLockscreenHostedDreamGestureListener;
     private final NotificationInsetsController mNotificationInsetsController;
-    private final boolean mIsTrackpadCommonEnabled;
     private final FeatureFlagsClassic mFeatureFlagsClassic;
     private final SysUIKeyEventHandler mSysUIKeyEventHandler;
     private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@@ -137,6 +136,11 @@
     private final PanelExpansionInteractor mPanelExpansionInteractor;
     private final ShadeExpansionStateManager mShadeExpansionStateManager;
 
+    /**
+     * If {@code true}, an external touch sent in {@link #handleExternalTouch(MotionEvent)} has been
+     * intercepted and all future touch events for the gesture should be processed by this view.
+     */
+    private boolean mExternalTouchIntercepted = false;
     private boolean mIsTrackingBarGesture = false;
     private boolean mIsOcclusionTransitionRunning = false;
     private DisableSubpixelTextTransitionListener mDisableSubpixelTextTransitionListener;
@@ -209,7 +213,6 @@
         mLockscreenHostedDreamGestureListener = lockscreenHostedDreamGestureListener;
         mNotificationInsetsController = notificationInsetsController;
         mGlanceableHubContainerController = glanceableHubContainerController;
-        mIsTrackpadCommonEnabled = featureFlagsClassic.isEnabled(TRACKPAD_GESTURE_COMMON);
         mFeatureFlagsClassic = featureFlagsClassic;
         mSysUIKeyEventHandler = sysUIKeyEventHandler;
         mPrimaryBouncerInteractor = primaryBouncerInteractor;
@@ -221,7 +224,7 @@
         mDisableSubpixelTextTransitionListener = new DisableSubpixelTextTransitionListener(mView);
         bouncerViewBinder.bind(mView.findViewById(R.id.keyguard_bouncer_container));
 
-        collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+        collectFlow(mView, keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING),
                 mLockscreenToDreamingTransition);
         collectFlow(
                 mView,
@@ -254,11 +257,28 @@
     }
 
     /**
-     * Handle a touch event while dreaming by forwarding the event to the content view.
+     * Handle a touch event while dreaming or on the hub by forwarding the event to the content
+     * view.
+     * <p>
+     * Since important logic for handling touches lives in the dispatch/intercept phases, we
+     * simulate going through all of these stages before sending onTouchEvent if intercepted.
+     *
      * @param event The event to forward.
      */
-    public void handleDreamTouch(MotionEvent event) {
-        mView.dispatchTouchEvent(event);
+    public void handleExternalTouch(MotionEvent event) {
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            mExternalTouchIntercepted = false;
+        }
+
+        if (!mView.dispatchTouchEvent(event)) {
+            return;
+        }
+        if (!mExternalTouchIntercepted) {
+            mExternalTouchIntercepted = mView.onInterceptTouchEvent(event);
+        }
+        if (mExternalTouchIntercepted) {
+            mView.onTouchEvent(event);
+        }
     }
 
     /** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
@@ -382,12 +402,15 @@
                     float x = ev.getRawX();
                     float y = ev.getRawY();
                     if (mStatusBarViewController.touchIsWithinView(x, y)) {
-                        if (mStatusBarWindowStateController.windowIsShowing()) {
-                            mIsTrackingBarGesture = true;
-                            return logDownDispatch(ev, "sending touch to status bar",
-                                    mStatusBarViewController.sendTouchToView(ev));
-                        } else {
-                            return logDownDispatch(ev, "hidden or hiding", true);
+                        if (!(MigrateClocksToBlueprint.isEnabled()
+                                && mPrimaryBouncerInteractor.isBouncerShowing())) {
+                            if (mStatusBarWindowStateController.windowIsShowing()) {
+                                mIsTrackingBarGesture = true;
+                                return logDownDispatch(ev, "sending touch to status bar",
+                                        mStatusBarViewController.sendTouchToView(ev));
+                            } else {
+                                return logDownDispatch(ev, "hidden or hiding", true);
+                            }
                         }
                     }
                 } else if (mIsTrackingBarGesture) {
@@ -563,6 +586,11 @@
             public boolean dispatchKeyEvent(KeyEvent event) {
                 return mSysUIKeyEventHandler.dispatchKeyEvent(event);
             }
+
+            @Override
+            public void collectKeyEvent(KeyEvent event) {
+                mFalsingCollector.onKeyEvent(event);
+            }
         });
 
         mView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@@ -633,22 +661,19 @@
         if (mTouchActive) {
             final long now = mClock.uptimeMillis();
             final MotionEvent event;
-            if (mIsTrackpadCommonEnabled) {
-                event = MotionEvent.obtain(mDownEvent);
-                event.setDownTime(now);
-                event.setAction(MotionEvent.ACTION_CANCEL);
-                event.setLocation(0.0f, 0.0f);
-            } else {
-                event = MotionEvent.obtain(now, now,
-                        MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
-                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-            }
+            event = MotionEvent.obtain(mDownEvent);
+            event.setDownTime(now);
+            event.setAction(MotionEvent.ACTION_CANCEL);
+            event.setLocation(0.0f, 0.0f);
             Log.w(TAG, "Canceling current touch event (should be very rare)");
             mView.dispatchTouchEvent(event);
             event.recycle();
             mTouchCancelled = true;
         }
         mAmbientState.setSwipingUp(false);
+        if (MigrateClocksToBlueprint.isEnabled()) {
+            mDragDownHelper.stopDragging();
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index 35b4059..6df8ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -19,7 +19,6 @@
 
 import static android.view.WindowInsets.Type.ime;
 
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
 import static com.android.systemui.Flags.centralizedStatusBarHeightFix;
 import static com.android.systemui.classifier.Classifier.QS_COLLAPSE;
 import static com.android.systemui.shade.NotificationPanelViewController.COUNTER_PANEL_OPEN_QS;
@@ -57,6 +56,7 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.Cuj;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
@@ -153,7 +153,7 @@
     private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
     private final CastController mCastController;
     private final SplitShadeStateController mSplitShadeStateController;
-    private final InteractionJankMonitor mInteractionJankMonitor;
+    private final Lazy<InteractionJankMonitor> mInteractionJankMonitorLazy;
     private final ShadeRepository mShadeRepository;
     private final ShadeInteractor mShadeInteractor;
     private final ActiveNotificationsInteractor mActiveNotificationsInteractor;
@@ -324,7 +324,7 @@
             AccessibilityManager accessibilityManager,
             LockscreenGestureLogger lockscreenGestureLogger,
             MetricsLogger metricsLogger,
-            InteractionJankMonitor interactionJankMonitor,
+            Lazy<InteractionJankMonitor> interactionJankMonitorLazy,
             ShadeLogger shadeLog,
             DumpManager dumpManager,
             DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
@@ -375,7 +375,7 @@
         mShadeLog = shadeLog;
         mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
         mCastController = castController;
-        mInteractionJankMonitor = interactionJankMonitor;
+        mInteractionJankMonitorLazy = interactionJankMonitorLazy;
         mShadeRepository = shadeRepository;
         mShadeInteractor = shadeInteractor;
         mActiveNotificationsInteractor = activeNotificationsInteractor;
@@ -1371,6 +1371,7 @@
     @Override
     public float calculateNotificationsTopPadding(boolean isShadeExpanding,
             int keyguardNotificationStaticPadding, float expandedFraction) {
+        SceneContainerFlag.assertInLegacyMode();
         float topPadding;
         boolean keyguardShowing = mBarState == KEYGUARD;
         if (mSplitShadeEnabled) {
@@ -2311,44 +2312,46 @@
     }
 
     void beginJankMonitoring(boolean isFullyCollapsed) {
-        if (mInteractionJankMonitor == null) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor == null) {
             return;
         }
         // TODO (b/265193930): remove dependency on NPVC
         InteractionJankMonitor.Configuration.Builder builder =
                 InteractionJankMonitor.Configuration.Builder.withView(
-                        InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE,
+                        Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE,
                         mPanelView).setTag(isFullyCollapsed ? "Expand" : "Collapse");
-        mInteractionJankMonitor.begin(builder);
+        monitor.begin(builder);
     }
 
     void endJankMonitoring() {
-        if (mInteractionJankMonitor == null) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor == null) {
             return;
         }
-        InteractionJankMonitor.getInstance().end(
-                InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
+        monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
     }
 
     void cancelJankMonitoring() {
-        if (mInteractionJankMonitor == null) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor == null) {
             return;
         }
-        InteractionJankMonitor.getInstance().cancel(
-                InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
+        monitor.cancel(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
     }
 
     void traceQsJank(boolean startTracing, boolean wasCancelled) {
-        if (mInteractionJankMonitor == null) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor == null) {
             return;
         }
         if (startTracing) {
-            mInteractionJankMonitor.begin(mPanelView, CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
+            monitor.begin(mPanelView, Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
         } else {
             if (wasCancelled) {
-                mInteractionJankMonitor.cancel(CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
+                monitor.cancel(Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
             } else {
-                mInteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
+                monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt
index b8250cc..3462993 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerSceneImpl.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.shade
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.qs.QSContainerController
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import javax.inject.Inject
@@ -28,7 +27,6 @@
 constructor(
     private val shadeInteractor: ShadeInteractor,
     private val qsSceneAdapter: QSSceneAdapter,
-    private val qsContainerController: QSContainerController,
 ) : QuickSettingsController {
 
     override val expanded: Boolean
@@ -43,7 +41,7 @@
     }
 
     override fun closeQsCustomizer() {
-        qsContainerController.setCustomizerShowing(false)
+        qsSceneAdapter.requestCloseCustomizer()
     }
 
     @Deprecated("specific to legacy split shade")
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
index ebebbe6..8c15817 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
@@ -124,7 +124,6 @@
             // release focus immediately to kick off focus change transition
             notificationShadeWindowController.setNotificationShadeFocusable(false)
             notificationStackScrollLayout.cancelExpandHelper()
-            sceneInteractor.changeScene(Scenes.Shade, "ShadeController.animateExpandShade")
             if (delayed) {
                 scope.launch {
                     delay(125)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 648d4b5..a0c9391 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -19,7 +19,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.plugins.qs.QSContainerController
 import com.android.systemui.qs.ui.adapter.QSSceneAdapterImpl
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.data.repository.PrivacyChipRepository
 import com.android.systemui.shade.data.repository.PrivacyChipRepositoryImpl
 import com.android.systemui.shade.data.repository.ShadeRepository
@@ -50,11 +50,10 @@
         @Provides
         @SysUISingleton
         fun provideBaseShadeInteractor(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<ShadeInteractorSceneContainerImpl>,
             sceneContainerOff: Provider<ShadeInteractorLegacyImpl>
         ): BaseShadeInteractor {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
@@ -64,11 +63,10 @@
         @Provides
         @SysUISingleton
         fun provideShadeController(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<ShadeControllerSceneImpl>,
             sceneContainerOff: Provider<ShadeControllerImpl>
         ): ShadeController {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
@@ -78,11 +76,10 @@
         @Provides
         @SysUISingleton
         fun provideShadeAnimationInteractor(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<ShadeAnimationInteractorSceneContainerImpl>,
             sceneContainerOff: Provider<ShadeAnimationInteractorLegacyImpl>
         ): ShadeAnimationInteractor {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
@@ -92,11 +89,10 @@
         @Provides
         @SysUISingleton
         fun provideShadeBackActionInteractor(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<ShadeBackActionInteractorImpl>,
             sceneContainerOff: Provider<NotificationPanelViewController>
         ): ShadeBackActionInteractor {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
@@ -106,11 +102,10 @@
         @Provides
         @SysUISingleton
         fun provideShadeLockscreenInteractor(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<ShadeLockscreenInteractorImpl>,
             sceneContainerOff: Provider<NotificationPanelViewController>
         ): ShadeLockscreenInteractor {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
@@ -120,11 +115,10 @@
         @Provides
         @SysUISingleton
         fun providePanelExpansionInteractor(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<PanelExpansionInteractorImpl>,
             sceneContainerOff: Provider<NotificationPanelViewController>
         ): PanelExpansionInteractor {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
@@ -134,11 +128,10 @@
         @Provides
         @SysUISingleton
         fun provideQuickSettingsController(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<QuickSettingsControllerSceneImpl>,
             sceneContainerOff: Provider<QuickSettingsControllerImpl>,
         ): QuickSettingsController {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index 2cb9f9a..bc23778 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -22,6 +22,7 @@
 import android.view.LayoutInflater
 import android.view.ViewStub
 import androidx.constraintlayout.motion.widget.MotionLayout
+import com.android.compose.animation.scene.SceneKey
 import com.android.keyguard.logging.ScrimLogger
 import com.android.systemui.battery.BatteryMeterView
 import com.android.systemui.battery.BatteryMeterViewController
@@ -32,7 +33,7 @@
 import com.android.systemui.keyguard.ui.view.KeyguardRootView
 import com.android.systemui.privacy.OngoingPrivacyChip
 import com.android.systemui.res.R
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scene
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
@@ -43,6 +44,7 @@
 import com.android.systemui.statusbar.LightRevealScrim
 import com.android.systemui.statusbar.NotificationInsetsController
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
 import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
 import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
 import com.android.systemui.statusbar.phone.StatusBarLocation
@@ -51,6 +53,7 @@
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.tuner.TunerService
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import javax.inject.Named
@@ -59,6 +62,14 @@
 /** Module for providing views related to the shade. */
 @Module
 abstract class ShadeViewProviderModule {
+
+    @Binds
+    @SysUISingleton
+    // TODO(b/277762009): Only allow this view's binder to inject the view.
+    abstract fun bindsNotificationScrollView(
+        notificationStackScrollLayout: NotificationStackScrollLayout
+    ): NotificationScrollView
+
     companion object {
         const val SHADE_HEADER = "large_screen_shade_header"
 
@@ -67,15 +78,14 @@
         @SysUISingleton
         fun providesWindowRootView(
             layoutInflater: LayoutInflater,
-            sceneContainerFlags: SceneContainerFlags,
             viewModelProvider: Provider<SceneContainerViewModel>,
             containerConfigProvider: Provider<SceneContainerConfig>,
-            flagsProvider: Provider<SceneContainerFlags>,
             scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
             layoutInsetController: NotificationInsetsController,
             sceneDataSourceDelegator: Provider<SceneDataSourceDelegator>,
         ): WindowRootView {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
+                checkNoSceneDuplicates(scenesProvider.get())
                 val sceneWindowRootView =
                     layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
                 sceneWindowRootView.init(
@@ -83,7 +93,6 @@
                     containerConfig = containerConfigProvider.get(),
                     sharedNotificationContainer =
                         sceneWindowRootView.requireViewById(R.id.shared_notification_container),
-                    flags = flagsProvider.get(),
                     scenes = scenesProvider.get(),
                     layoutInsetController = layoutInsetController,
                     sceneDataSourceDelegator = sceneDataSourceDelegator.get(),
@@ -103,9 +112,8 @@
         @SysUISingleton
         fun providesNotificationShadeWindowView(
             root: WindowRootView,
-            sceneContainerFlags: SceneContainerFlags,
         ): NotificationShadeWindowView {
-            if (sceneContainerFlags.isEnabled()) {
+            if (SceneContainerFlag.isEnabled) {
                 return root.requireViewById(R.id.legacy_window_root)
             }
             return root as NotificationShadeWindowView?
@@ -271,5 +279,21 @@
         ): StatusIconContainer {
             return header.requireViewById(R.id.statusIcons)
         }
+
+        private fun checkNoSceneDuplicates(scenes: Set<Scene>) {
+            val keys = mutableSetOf<SceneKey>()
+            val duplicates = mutableSetOf<SceneKey>()
+            scenes
+                .map { it.key }
+                .forEach { sceneKey ->
+                    if (keys.contains(sceneKey)) {
+                        duplicates.add(sceneKey)
+                    } else {
+                        keys.add(sceneKey)
+                    }
+                }
+
+            check(duplicates.isEmpty()) { "Duplicate scenes detected: $duplicates" }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
index 3349345..c429329 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
@@ -345,9 +345,7 @@
             }
         }
 
-        if (mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
-            Log.d(TAG, "ignoring old pipeline callback because new mobile icon is enabled");
-        } else {
+        if (!mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
             for (int i = 0; i < SIM_SLOTS; i++) {
                 mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
index d68e28c..0b45c08 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
@@ -82,7 +82,7 @@
     override val isShadeTouchable: Flow<Boolean> =
         combine(
             powerInteractor.isAsleep,
-            keyguardTransitionInteractor.isInTransitionToStateWhere { it == KeyguardState.AOD },
+            keyguardTransitionInteractor.isInTransitionToState(KeyguardState.AOD),
             keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING },
         ) { isAsleep, goingToSleep, isPulsing ->
             when {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt
index 72a9c8d..6c76061 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt
@@ -22,9 +22,11 @@
 import android.icu.text.DateFormat
 import android.icu.text.DisplayContext
 import android.os.UserHandle
+import android.provider.Settings
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.privacy.OngoingPrivacyChip
 import com.android.systemui.privacy.PrivacyItem
 import com.android.systemui.res.R
@@ -54,6 +56,7 @@
 constructor(
     @Application private val applicationScope: CoroutineScope,
     context: Context,
+    private val activityStarter: ActivityStarter,
     shadeInteractor: ShadeInteractor,
     mobileIconsInteractor: MobileIconsInteractor,
     val mobileIconsViewModel: MobileIconsViewModel,
@@ -136,6 +139,14 @@
         clockInteractor.launchClockActivity()
     }
 
+    /** Notifies that the shadeCarrierGroup was clicked. */
+    fun onShadeCarrierGroupClicked() {
+        activityStarter.postStartActivityDismissingKeyguard(
+            Intent(Settings.ACTION_WIRELESS_SETTINGS),
+            0
+        )
+    }
+
     private fun updateDateTexts(invalidateFormats: Boolean) {
         if (invalidateFormats) {
             longerDateFormat.value = getFormatFromPattern(longerPattern)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
index 9362cd0..5b76acb 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
@@ -33,9 +33,11 @@
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -57,11 +59,13 @@
     val qsSceneAdapter: QSSceneAdapter,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
     val notifications: NotificationsPlaceholderViewModel,
+    val brightnessMirrorViewModel: BrightnessMirrorViewModel,
     val mediaDataManager: MediaDataManager,
     shadeInteractor: ShadeInteractor,
     private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
     private val footerActionsController: FooterActionsController,
     private val sceneInteractor: SceneInteractor,
+    private val unfoldTransitionInteractor: UnfoldTransitionInteractor,
 ) {
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
         combine(
@@ -104,6 +108,14 @@
 
     val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode
 
+    /**
+     * Amount of X-axis translation to apply to various elements as the unfolded foldable is folded
+     * slightly, in pixels.
+     */
+    fun unfoldTranslationX(isOnStartSide: Boolean): Flow<Float> {
+        return unfoldTransitionInteractor.unfoldTranslationX(isOnStartSide)
+    }
+
     /** Notifies that some content in the shade was clicked. */
     fun onContentClicked() {
         if (!isClickable.value) {
diff --git a/packages/SystemUI/src/com/android/systemui/startable/Dependencies.kt b/packages/SystemUI/src/com/android/systemui/startable/Dependencies.kt
index 5e57f1d..396c5f2 100644
--- a/packages/SystemUI/src/com/android/systemui/startable/Dependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/startable/Dependencies.kt
@@ -16,7 +16,8 @@
 package com.android.systemui.startable
 
 import com.android.systemui.CoreStartable
-import kotlin.reflect.KClass
+import java.lang.annotation.Documented
+import javax.inject.Qualifier
 
 /**
  * Allows a [CoreStartable] to declare that it must be started after its dependencies.
@@ -24,7 +25,4 @@
  * This creates a partial, topological ordering. See [com.android.systemui.SystemUIApplication] for
  * how this ordering is enforced at runtime.
  */
-@MustBeDocumented
-@Target(AnnotationTarget.CLASS)
-@Retention(AnnotationRetention.RUNTIME)
-annotation class Dependencies(vararg val value: KClass<out CoreStartable> = [])
+@Qualifier @Documented @Retention(AnnotationRetention.RUNTIME) annotation class Dependencies()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index e7b159a..d955349 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -50,6 +50,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Pair;
 import android.util.SparseArray;
 import android.view.KeyEvent;
@@ -516,7 +517,7 @@
         /**
          * @see IStatusBar#showMediaOutputSwitcher
          */
-        default void showMediaOutputSwitcher(String packageName) {}
+        default void showMediaOutputSwitcher(String packageName, UserHandle userHandle) {}
 
         /**
          * @see IStatusBar#confirmImmersivePrompt
@@ -1361,7 +1362,7 @@
         }
     }
     @Override
-    public void showMediaOutputSwitcher(String packageName) {
+    public void showMediaOutputSwitcher(String packageName, UserHandle userHandle) {
         int callingUid = Binder.getCallingUid();
         if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
             throw new SecurityException("Call only allowed from system server.");
@@ -1369,6 +1370,7 @@
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = packageName;
+            args.arg2 = userHandle;
             mHandler.obtainMessage(MSG_SHOW_MEDIA_OUTPUT_SWITCHER, args).sendToTarget();
         }
     }
@@ -1939,8 +1941,10 @@
                 case MSG_SHOW_MEDIA_OUTPUT_SWITCHER:
                     args = (SomeArgs) msg.obj;
                     String clientPackageName = (String) args.arg1;
+                    UserHandle clientUserHandle = (UserHandle) args.arg2;
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).showMediaOutputSwitcher(clientPackageName);
+                        mCallbacks.get(i).showMediaOutputSwitcher(clientPackageName,
+                                clientUserHandle);
                     }
                     break;
                 case MSG_CONFIRM_IMMERSIVE_PROMPT:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
index d6858ca..78e108d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
@@ -40,6 +40,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.text.Editable;
+import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
 import android.util.Pair;
@@ -57,6 +58,7 @@
 import android.view.View.AccessibilityDelegate;
 import android.view.ViewGroup;
 import android.view.Window;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Button;
@@ -104,6 +106,7 @@
 
     private WindowManager mWindowManager;
     private EditText mSearchEditText;
+    private ImageButton mEditTextCancel;
     private String mQueryString;
     private int mCurrentCategoryIndex = 0;
     private Map<Integer, Boolean> mKeySearchResultMap = new HashMap<>();
@@ -143,7 +146,7 @@
     @VisibleForTesting
     KeyboardShortcutListSearch(Context context, WindowManager windowManager) {
         this.mContext = new ContextThemeWrapper(
-                context, android.R.style.Theme_DeviceDefault_Settings);
+                context, R.style.KeyboardShortcutHelper);
         this.mPackageManager = AppGlobals.getPackageManager();
         if (windowManager != null) {
             this.mWindowManager = windowManager;
@@ -853,13 +856,14 @@
             List<List<KeyboardShortcutMultiMappingGroup>> keyboardShortcutMultiMappingGroupList) {
         mQueryString = null;
         LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
-        mKeyboardShortcutsBottomSheetDialog =
-                new BottomSheetDialog(mContext);
+        mKeyboardShortcutsBottomSheetDialog  = new BottomSheetDialog(mContext);
         final View keyboardShortcutsView = inflater.inflate(
                 R.layout.keyboard_shortcuts_search_view, null);
         LinearLayout shortcutsContainer = keyboardShortcutsView.findViewById(
                 R.id.keyboard_shortcuts_container);
         mNoSearchResults = keyboardShortcutsView.findViewById(R.id.shortcut_search_no_result);
+        Window keyboardShortcutsWindow = mKeyboardShortcutsBottomSheetDialog.getWindow();
+        setWindowProperties(keyboardShortcutsWindow);
         mKeyboardShortcutsBottomSheetDialog.setContentView(keyboardShortcutsView);
         setButtonsDefaultStatus(keyboardShortcutsView);
         populateCurrentAppButton();
@@ -874,25 +878,11 @@
         }
 
         BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
+        behavior.setDraggable(true);
         behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
         behavior.setSkipCollapsed(true);
-        behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
-                    @Override
-                    public void onStateChanged(@NonNull View bottomSheet, int newState) {
-                        if (newState == BottomSheetBehavior.STATE_DRAGGING) {
-                            behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
-                        }
-                    }
 
-                    @Override
-                    public void onSlide(@NonNull View bottomSheet, float slideOffset) {
-                        // Do nothing.
-                    }
-                });
 
-        mKeyboardShortcutsBottomSheetDialog.setCanceledOnTouchOutside(true);
-        Window keyboardShortcutsWindow = mKeyboardShortcutsBottomSheetDialog.getWindow();
-        keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
         synchronized (sLock) {
             // show KeyboardShortcutsBottomSheetDialog only if it has not been dismissed already
             if (sInstance != null) {
@@ -908,6 +898,8 @@
             }
         }
         mSearchEditText = keyboardShortcutsView.findViewById(R.id.keyboard_shortcuts_search);
+        mEditTextCancel = keyboardShortcutsView.findViewById(
+                R.id.keyboard_shortcuts_search_cancel);
         mSearchEditText.addTextChangedListener(
                 new TextWatcher() {
                     @Override
@@ -921,6 +913,8 @@
                             shortcutsContainer.setAccessibilityPaneTitle(mContext.getString(
                                     R.string.keyboard_shortcut_a11y_show_search_results));
                         }
+                        mEditTextCancel.setVisibility(
+                                TextUtils.isEmpty(mQueryString) ? View.GONE : View.VISIBLE);
                     }
 
                     @Override
@@ -933,9 +927,28 @@
                         // Do nothing.
                     }
                 });
-        ImageButton editTextCancel = keyboardShortcutsView.findViewById(
-                R.id.keyboard_shortcuts_search_cancel);
-        editTextCancel.setOnClickListener(v -> mSearchEditText.setText(null));
+
+        mEditTextCancel.setOnClickListener(v -> mSearchEditText.setText(null));
+    }
+
+    private static void setWindowProperties(Window keyboardShortcutsWindow) {
+        keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+        params.copyFrom(keyboardShortcutsWindow.getAttributes());
+        // Allows the bottom sheet dialog to render all the way to the bottom of the screen,
+        // behind the gesture navigation bar.
+        params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+        params.setFitInsetsTypes(WindowInsets.Type.statusBars());
+        keyboardShortcutsWindow.setAttributes(params);
+        keyboardShortcutsWindow.getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
+            int bottom = insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
+            View container = v.findViewById(R.id.keyboard_shortcuts_container);
+            container.setPadding(container.getPaddingLeft(), container.getPaddingTop(),
+                    container.getPaddingRight(), bottom);
+            return WindowInsets.CONSUMED;
+        });
+        keyboardShortcutsWindow.setWindowAnimations(
+                R.style.KeyboardShortcutHelper_BottomSheetDialogAnimation);
     }
 
     private void populateKeyboardShortcutSearchList(LinearLayout keyboardShortcutsLayout) {
@@ -1256,10 +1269,10 @@
         if (mContext.getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_PORTRAIT) {
             lp.width = (int) (display.getWidth() * 0.8);
-            lp.height = (int) (display.getHeight() * 0.7);
+            lp.height = (int) (display.getHeight() * 0.8);
         } else {
             lp.width = (int) (display.getWidth() * 0.7);
-            lp.height = (int) (display.getHeight() * 0.8);
+            lp.height = (int) (display.getHeight() * 0.95);
         }
         window.setGravity(Gravity.BOTTOM);
         window.setAttributes(lp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 815236e0..09985f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -195,20 +195,20 @@
     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;
+    protected boolean mPowerPluggedIn;
+    protected boolean mPowerPluggedInWired;
+    protected boolean mPowerPluggedInWireless;
+    protected boolean mPowerPluggedInDock;
 
     private boolean mPowerCharged;
     private boolean mBatteryDefender;
     private boolean mEnableBatteryDefender;
     private boolean mIncompatibleCharger;
-    private int mChargingSpeed;
+    protected int mChargingSpeed;
     private int mChargingWattage;
     private int mBatteryLevel;
     private boolean mBatteryPresent = true;
-    private long mChargingTimeRemaining;
+    protected long mChargingTimeRemaining;
     private Pair<String, BiometricSourceType> mBiometricErrorMessageToShowOnScreenOn;
     private final Set<Integer> mCoExFaceAcquisitionMsgIdsToShow;
     private final FaceHelpMessageDeferral mFaceAcquiredMessageDeferral;
@@ -1053,20 +1053,24 @@
      * Assumption: device is charging
      */
     protected String computePowerIndication() {
-        int chargingId;
         if (mBatteryDefender) {
-            chargingId = R.string.keyguard_plugged_in_charging_limited;
             String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
-            return mContext.getResources().getString(chargingId, percentage);
+            return mContext.getResources().getString(
+                    R.string.keyguard_plugged_in_charging_limited, percentage);
         } else if (mPowerPluggedIn && mIncompatibleCharger) {
-            chargingId = R.string.keyguard_plugged_in_incompatible_charger;
             String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
-            return mContext.getResources().getString(chargingId, percentage);
+            return mContext.getResources().getString(
+                    R.string.keyguard_plugged_in_incompatible_charger, percentage);
         } else if (mPowerCharged) {
             return mContext.getResources().getString(R.string.keyguard_charged);
         }
 
+        return computePowerChargingStringIndication();
+    }
+
+    protected String computePowerChargingStringIndication() {
         final boolean hasChargingTime = mChargingTimeRemaining > 0;
+        int chargingId;
         if (mPowerPluggedInWired) {
             switch (mChargingSpeed) {
                 case BatteryStatus.CHARGING_FAST:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 519d719..222b070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -33,9 +33,9 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
 import com.android.systemui.res.R
-import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
 import com.android.systemui.shade.data.repository.ShadeRepository
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -813,7 +813,7 @@
                 initialTouchX = x
                 isTrackpadReverseScroll =
                     !naturalScrollingSettingObserver.isNaturalScrollingEnabled &&
-                        isTrackpadScroll(true, event)
+                        isTrackpadScroll(event)
             }
             MotionEvent.ACTION_MOVE -> {
                 val h = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
@@ -959,7 +959,7 @@
         anim.start()
     }
 
-    private fun stopDragging() {
+    fun stopDragging() {
         if (startingChild != null) {
             cancelChildExpansion(startingChild!!)
             startingChild = null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
index e669556..707d59aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
@@ -86,6 +86,9 @@
     /** Sets the state of whether the bouncer is showing or not. */
     default void setBouncerShowing(boolean showing) {}
 
+    /** Sets the state of whether the glanceable hub is showing or not. */
+    default void setGlanceableHubShowing(boolean showing) {}
+
     /** Sets the state of whether the backdrop is showing or not. */
     default void setBackdropShowing(boolean showing) {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index bb6ee24..f8193a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -57,6 +57,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
+import com.android.systemui.Flags;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.NotificationContentDescription;
 import com.android.systemui.statusbar.notification.NotificationDozeHelper;
@@ -208,6 +209,10 @@
         initializeDecorColor();
         reloadDimens();
         maybeUpdateIconScaleDimens();
+
+        if (Flags.statusBarMonochromeIconsFix()) {
+            setCropToPadding(true);
+        }
     }
 
     /** Should always be preceded by {@link #reloadDimens()} */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 8ea29dd6..4f8c3caa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -49,7 +49,6 @@
 import com.android.systemui.deviceentry.shared.model.DeviceUnlockStatus;
 import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
-import com.android.systemui.plugins.clocks.ClockController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.res.R;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
@@ -107,7 +106,7 @@
 
     private final ArrayList<RankedListener> mListeners = new ArrayList<>();
     private final UiEventLogger mUiEventLogger;
-    private final InteractionJankMonitor mInteractionJankMonitor;
+    private final Lazy<InteractionJankMonitor> mInteractionJankMonitorLazy;
     private final JavaAdapter mJavaAdapter;
     private final Lazy<ShadeInteractor> mShadeInteractorLazy;
     private final Lazy<DeviceUnlockedInteractor> mDeviceUnlockedInteractorLazy;
@@ -174,14 +173,14 @@
     @Inject
     public StatusBarStateControllerImpl(
             UiEventLogger uiEventLogger,
-            InteractionJankMonitor interactionJankMonitor,
+            Lazy<InteractionJankMonitor> interactionJankMonitorLazy,
             JavaAdapter javaAdapter,
             Lazy<ShadeInteractor> shadeInteractorLazy,
             Lazy<DeviceUnlockedInteractor> deviceUnlockedInteractorLazy,
             Lazy<SceneInteractor> sceneInteractorLazy,
             Lazy<KeyguardClockInteractor> keyguardClockInteractorLazy) {
         mUiEventLogger = uiEventLogger;
-        mInteractionJankMonitor = interactionJankMonitor;
+        mInteractionJankMonitorLazy = interactionJankMonitorLazy;
         mJavaAdapter = javaAdapter;
         mShadeInteractorLazy = shadeInteractorLazy;
         mDeviceUnlockedInteractorLazy = deviceUnlockedInteractorLazy;
@@ -469,13 +468,7 @@
     /** Returns the id of the currently rendering clock */
     public String getClockId() {
         if (MigrateClocksToBlueprint.isEnabled()) {
-            ClockController clock = mKeyguardClockInteractorLazy.get()
-                    .getCurrentClock().getValue();
-            if (clock == null) {
-                Log.e(TAG, "No clock is available");
-                return KeyguardClockSwitch.MISSING_CLOCK_ID;
-            }
-            return clock.getConfig().getId();
+            return mKeyguardClockInteractorLazy.get().getRenderedClockId();
         }
 
         if (mClockSwitchView == null) {
@@ -489,7 +482,8 @@
     private void beginInteractionJankMonitor() {
         final boolean shouldPost =
                 (mIsDozing && mDozeAmount == 0) || (!mIsDozing && mDozeAmount == 1);
-        if (mInteractionJankMonitor != null && mView != null && mView.isAttachedToWindow()) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor != null && mView != null && mView.isAttachedToWindow()) {
             if (shouldPost) {
                 Choreographer.getInstance().postCallback(
                         Choreographer.CALLBACK_ANIMATION, this::beginInteractionJankMonitor, null);
@@ -497,23 +491,25 @@
                 Configuration.Builder builder = Configuration.Builder.withView(getCujType(), mView)
                         .setTag(getClockId())
                         .setDeferMonitorForAnimationStart(false);
-                mInteractionJankMonitor.begin(builder);
+                monitor.begin(builder);
             }
         }
     }
 
     private void endInteractionJankMonitor() {
-        if (mInteractionJankMonitor == null) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor == null) {
             return;
         }
-        mInteractionJankMonitor.end(getCujType());
+        monitor.end(getCujType());
     }
 
     private void cancelInteractionJankMonitor() {
-        if (mInteractionJankMonitor == null) {
+        InteractionJankMonitor monitor = mInteractionJankMonitorLazy.get();
+        if (monitor == null) {
             return;
         }
-        mInteractionJankMonitor.cancel(getCujType());
+        monitor.cancel(getCujType());
     }
 
     private int getCujType() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 724b19c..e3c47a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -83,6 +83,10 @@
 import com.android.systemui.telephony.TelephonyListenerManager;
 import com.android.systemui.util.CarrierConfigTracker;
 
+import dalvik.annotation.optimization.NeverCompile;
+
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -97,9 +101,6 @@
 
 import javax.inject.Inject;
 
-import dalvik.annotation.optimization.NeverCompile;
-import kotlin.Unit;
-
 /** Platform implementation of the network controller. **/
 @SysUISingleton
 public class NetworkControllerImpl extends BroadcastReceiver
@@ -464,7 +465,10 @@
             });
         };
 
-        mDemoModeController.addCallback(this);
+        // TODO(b/336357360): Until we can remove this class entirely, disable its handling of ALL
+        // demo mode commands, due to the fact that the mobile command handler has an infinite
+        // loop bug if you use any slot other than 1.
+        // mDemoModeController.addCallback(this);
 
         mDumpManager.registerNormalDumpable(TAG, this);
     }
@@ -1317,6 +1321,8 @@
             int carrierId = TextUtils.isEmpty(carrierIdString) ? 0
                     : Integer.parseInt(carrierIdString);
             // Ensure we have enough sim slots
+            // TODO(b/336357360): This is the origination of the infinite loop bug, for those
+            // following along at home.
             List<SubscriptionInfo> subs = new ArrayList<>();
             while (mMobileSignalControllers.size() <= slot) {
                 int nextSlot = mMobileSignalControllers.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index e5b6497..594c191 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -35,7 +35,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
 import com.android.systemui.power.domain.interactor.PowerInteractor;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.ShadeSurface;
@@ -61,8 +61,6 @@
 import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
-import javax.inject.Provider;
-
 import dagger.Binds;
 import dagger.Lazy;
 import dagger.Module;
@@ -70,6 +68,8 @@
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
 
+import javax.inject.Provider;
+
 /**
  * This module provides instances needed to construct {@link CentralSurfacesImpl}. These are moved to
  * this separate from {@link CentralSurfacesModule} module so that components that wish to build
@@ -185,10 +185,9 @@
     @Provides
     @SysUISingleton
     static ShadeSurface provideShadeSurface(
-            SceneContainerFlags sceneContainerFlags,
             Provider<ShadeSurfaceImpl> sceneContainerOn,
             Provider<NotificationPanelViewController> sceneContainerOff) {
-        if (sceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             return sceneContainerOn.get();
         } else {
             return sceneContainerOff.get();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 9ce38db..8b673c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -49,7 +49,6 @@
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.SnoozeCriterion;
 import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
 import android.view.ContentInfo;
 
 import androidx.annotation.NonNull;
@@ -150,10 +149,8 @@
     private int mCachedContrastColor = COLOR_INVALID;
     private int mCachedContrastColorIsFor = COLOR_INVALID;
     private InflationTask mRunningTask = null;
-    private Throwable mDebugThrowable;
     public CharSequence remoteInputTextWhenReset;
     public long lastRemoteInputSent = NOT_LAUNCHED_YET;
-    public final ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
 
     private final MutableStateFlow<CharSequence> mHeadsUpStatusBarText =
             StateFlowKt.MutableStateFlow(null);
@@ -190,11 +187,6 @@
     private boolean mBlockable;
 
     /**
-     * The {@link SystemClock#elapsedRealtime()} when this notification entry was created.
-     */
-    public long mCreationElapsedRealTime;
-
-    /**
      * Whether this notification has ever been a non-sticky HUN.
      */
     private boolean mIsDemoted = false;
@@ -264,13 +256,8 @@
         mKey = sbn.getKey();
         setSbn(sbn);
         setRanking(ranking);
-        mCreationElapsedRealTime = SystemClock.elapsedRealtime();
     }
 
-    @VisibleForTesting
-    public void setCreationElapsedRealTime(long time) {
-        mCreationElapsedRealTime = time;
-    }
     @Override
     public NotificationEntry getRepresentativeEntry() {
         return this;
@@ -581,19 +568,6 @@
         return mRunningTask;
     }
 
-    /**
-     * Set a throwable that is used for debugging
-     *
-     * @param debugThrowable the throwable to save
-     */
-    public void setDebugThrowable(Throwable debugThrowable) {
-        mDebugThrowable = debugThrowable;
-    }
-
-    public Throwable getDebugThrowable() {
-        return mDebugThrowable;
-    }
-
     public void onRemoteInputInserted() {
         lastRemoteInputSent = NOT_LAUNCHED_YET;
         remoteInputTextWhenReset = null;
@@ -749,12 +723,6 @@
         return row != null && row.areChildrenExpanded();
     }
 
-
-    //TODO: probably less confusing to say "is group fully visible"
-    public boolean isGroupNotFullyVisible() {
-        return row == null || row.isGroupNotFullyVisible();
-    }
-
     public NotificationGuts getGuts() {
         if (row != null) return row.getGuts();
         return null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt
index ed8c056..e9306a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRepository.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.data.repository
 
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
 
 /**
  * A repository of currently displayed heads up notifications.
@@ -29,13 +30,15 @@
 
     /**
      * True if we are exiting the headsUp pinned mode, and some notifications might still be
-     * animating out. This is used to keep the touchable regions in a reasonable state.
+     * animating out. This is used to keep their view container visible.
      */
-    val headsUpAnimatingAway: Flow<Boolean>
+    val isHeadsUpAnimatingAway: StateFlow<Boolean>
 
     /** The heads up row that should be displayed on top. */
     val topHeadsUpRow: Flow<HeadsUpRowRepository?>
 
     /** Set of currently active top-level heads up rows to be displayed. */
     val activeHeadsUpRows: Flow<Set<HeadsUpRowRepository>>
+
+    fun setHeadsUpAnimatingAway(animatingAway: Boolean)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
index d1dd7b5..98b52ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
@@ -29,7 +29,7 @@
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 
-class HeadsUpNotificationInteractor @Inject constructor(repository: HeadsUpRepository) {
+class HeadsUpNotificationInteractor @Inject constructor(private val repository: HeadsUpRepository) {
 
     val topHeadsUpRow: Flow<HeadsUpRowKey?> = repository.topHeadsUpRow
 
@@ -60,13 +60,16 @@
         }
 
     val isHeadsUpOrAnimatingAway: Flow<Boolean> =
-        combine(hasPinnedRows, repository.headsUpAnimatingAway) { hasPinnedRows, animatingAway ->
+        combine(hasPinnedRows, repository.isHeadsUpAnimatingAway) { hasPinnedRows, animatingAway ->
             hasPinnedRows || animatingAway
         }
 
     fun headsUpRow(key: HeadsUpRowKey): HeadsUpRowInteractor =
         HeadsUpRowInteractor(key as HeadsUpRowRepository)
     fun elementKeyFor(key: HeadsUpRowKey) = (key as HeadsUpRowRepository).elementKey
+    fun setHeadsUpAnimatingAway(animatingAway: Boolean) {
+        repository.setHeadsUpAnimatingAway(animatingAway)
+    }
 }
 
 class HeadsUpRowInteractor(repository: HeadsUpRowRepository)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
index adcbbfb..968b591 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
@@ -45,6 +45,7 @@
 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
 import com.android.systemui.statusbar.notification.row.FooterViewButton;
 import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
 import com.android.systemui.statusbar.notification.stack.ViewState;
 import com.android.systemui.util.DrawableDumpKt;
@@ -102,6 +103,11 @@
         setClearAllButtonVisible(visible, animate, /* onAnimationEnded = */ null);
     }
 
+    /** Set the visibility of the "Manage"/"History" button to {@code visible}. */
+    public void setManageOrHistoryButtonVisible(boolean visible) {
+        mManageOrHistoryButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
     /**
      * Set the visibility of the "Clear all" button to {@code visible}. Animate the change if
      * {@code animate} is true.
@@ -274,14 +280,23 @@
 
     /** Show a message instead of the footer buttons. */
     public void setFooterLabelVisible(boolean isVisible) {
-        if (isVisible) {
-            mManageOrHistoryButton.setVisibility(View.GONE);
-            mClearAllButton.setVisibility(View.GONE);
-            mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
+        // In the refactored code, hiding the buttons is handled in the FooterViewModel
+        if (FooterViewRefactor.isEnabled()) {
+            if (isVisible) {
+                mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
+            } else {
+                mSeenNotifsFooterTextView.setVisibility(View.GONE);
+            }
         } else {
-            mManageOrHistoryButton.setVisibility(View.VISIBLE);
-            mClearAllButton.setVisibility(View.VISIBLE);
-            mSeenNotifsFooterTextView.setVisibility(View.GONE);
+            if (isVisible) {
+                mManageOrHistoryButton.setVisibility(View.GONE);
+                mClearAllButton.setVisibility(View.GONE);
+                mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
+            } else {
+                mManageOrHistoryButton.setVisibility(View.VISIBLE);
+                mClearAllButton.setVisibility(View.VISIBLE);
+                mSeenNotifsFooterTextView.setVisibility(View.GONE);
+            }
         }
     }
 
@@ -443,6 +458,12 @@
          */
         public boolean hideContent;
 
+        /**
+         * When true, skip animating Y on the next #animateTo.
+         * Once true, remains true until reset in #animateTo.
+         */
+        public boolean resetY = false;
+
         @Override
         public void copyFrom(ViewState viewState) {
             super.copyFrom(viewState);
@@ -459,5 +480,17 @@
                 footerView.setContentVisibleAnimated(!hideContent);
             }
         }
+
+        @Override
+        public void animateTo(View child, AnimationProperties properties) {
+            if (child instanceof FooterView) {
+                // Must set animateY=false before super.animateTo, which checks for animateY
+                if (resetY) {
+                    properties.getAnimationFilter().animateY = false;
+                    resetY = false;
+                }
+            }
+            super.animateTo(child, properties);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt
index 65ab4fd..637cadd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt
@@ -141,8 +141,12 @@
             }
         }
 
-        // NOTE: The manage/history button is always visible as long as the footer is visible, no
-        //  need to update the visibility here.
+        launch {
+            viewModel.manageOrHistoryButton.isVisible.collect { isVisible ->
+                // NOTE: This visibility change is never animated.
+                footer.setManageOrHistoryButtonVisible(isVisible.value)
+            }
+        }
     }
 
     private suspend fun bindMessage(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
index b23ef35..90fb728 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
@@ -34,6 +34,7 @@
 import javax.inject.Provider
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
@@ -45,12 +46,33 @@
     seenNotificationsInteractor: SeenNotificationsInteractor,
     shadeInteractor: ShadeInteractor,
 ) {
+    /** A message to show instead of the footer buttons. */
+    val message: FooterMessageViewModel =
+        FooterMessageViewModel(
+            messageId = R.string.unlock_to_see_notif_text,
+            iconId = R.drawable.ic_friction_lock_closed,
+            isVisible = seenNotificationsInteractor.hasFilteredOutSeenNotifications,
+        )
+
+    private val clearAllButtonVisible =
+        activeNotificationsInteractor.hasClearableNotifications
+            .combine(message.isVisible) { hasClearableNotifications, isMessageVisible ->
+                if (isMessageVisible) {
+                    // If the message is visible, the button never is
+                    false
+                } else {
+                    hasClearableNotifications
+                }
+            }
+            .distinctUntilChanged()
+
+    /** The button for clearing notifications. */
     val clearAllButton: FooterButtonViewModel =
         FooterButtonViewModel(
             labelId = flowOf(R.string.clear_all_notifications_text),
             accessibilityDescriptionId = flowOf(R.string.accessibility_clear_all),
             isVisible =
-                activeNotificationsInteractor.hasClearableNotifications
+                clearAllButtonVisible
                     .sample(
                         // TODO(b/322167853): This check is currently duplicated in
                         //  NotificationListViewModel, but instead it should be a field in
@@ -61,9 +83,9 @@
                                 ::Pair
                             )
                             .onStart { emit(Pair(false, false)) }
-                    ) { hasClearableNotifications, (isShadeFullyExpanded, animationsEnabled) ->
+                    ) { clearAllButtonVisible, (isShadeFullyExpanded, animationsEnabled) ->
                         val shouldAnimate = isShadeFullyExpanded && animationsEnabled
-                        AnimatableEvent(hasClearableNotifications, shouldAnimate)
+                        AnimatableEvent(clearAllButtonVisible, shouldAnimate)
                     }
                     .toAnimatedValueFlow(),
         )
@@ -77,18 +99,16 @@
             else R.string.manage_notifications_text
         }
 
+    /** The button for managing notification settings or opening notification history. */
     val manageOrHistoryButton: FooterButtonViewModel =
         FooterButtonViewModel(
             labelId = manageOrHistoryButtonText,
             accessibilityDescriptionId = manageOrHistoryButtonText,
-            isVisible = flowOf(AnimatedValue.NotAnimating(true)),
-        )
-
-    val message: FooterMessageViewModel =
-        FooterMessageViewModel(
-            messageId = R.string.unlock_to_see_notif_text,
-            iconId = R.drawable.ic_friction_lock_closed,
-            isVisible = seenNotificationsInteractor.hasFilteredOutSeenNotifications,
+            isVisible =
+                // Hide the manage button if the message is visible
+                message.isVisible.map { messageVisible ->
+                    AnimatedValue.NotAnimating(!messageVisible)
+                },
         )
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index 4ebb699..271b0a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -39,13 +39,13 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import java.util.concurrent.ConcurrentHashMap
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
-import java.util.concurrent.ConcurrentHashMap
-import javax.inject.Inject
-import kotlin.coroutines.CoroutineContext
 
 /**
  * Inflates and updates icons associated with notifications
@@ -239,8 +239,8 @@
 
         val sbi = icon.toStatusBarIcon(entry)
 
-        // Cache if important conversation.
-        if (isImportantConversation(entry)) {
+        // Cache if important conversation or app icon.
+        if (isImportantConversation(entry) || android.app.Flags.notificationsUseAppIcon()) {
             if (showPeopleAvatar) {
                 entry.icons.peopleAvatarDescriptor = sbi
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
index bfeaced..2fdd2c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
@@ -20,6 +20,7 @@
 import android.view.View
 import com.android.app.tracing.traceSection
 import com.android.internal.util.ContrastColorUtil
+import com.android.systemui.Flags
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.StatusBarIconView
 import com.android.systemui.statusbar.StatusBarIconView.NO_COLOR
@@ -34,9 +35,12 @@
     //  view-model (which, at the time of this writing, does not yet exist).
 
     suspend fun bindColor(view: StatusBarIconView, color: Flow<Int>) {
-        color.collectTracingEach("SBIV#bindColor") { color ->
-            view.staticDrawableColor = color
-            view.setDecorColor(color)
+        // Don't change the icon color if an app icon experiment is enabled.
+        if (!android.app.Flags.notificationsUseAppIcon()) {
+            color.collectTracingEach("SBIV#bindColor") { color ->
+                view.staticDrawableColor = color
+                view.setDecorColor(color)
+            }
         }
     }
 
@@ -53,12 +57,15 @@
         iconColors: Flow<NotificationIconColors>,
         contrastColorUtil: ContrastColorUtil,
     ) {
-        iconColors.collectTracingEach("SBIV#bindIconColors") { colors ->
-            val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L)
-            val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil)
-            view.staticDrawableColor =
-                if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR
-            view.setDecorColor(colors.tint)
+        // Don't change the icon color if an app icon experiment is enabled.
+        if (!android.app.Flags.notificationsUseAppIcon()) {
+            iconColors.collectTracingEach("SBIV#bindIconColors") { colors ->
+                val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L)
+                val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil)
+                view.staticDrawableColor =
+                    if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR
+                view.setDecorColor(colors.tint)
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
index c4d9ab7..9619aca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
@@ -27,6 +27,7 @@
 import android.hardware.display.AmbientDisplayConfiguration
 import android.os.Handler
 import android.os.PowerManager
+import android.provider.Settings
 import android.provider.Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED
 import android.provider.Settings.Global.HEADS_UP_OFF
 import com.android.systemui.dagger.qualifiers.Main
@@ -42,6 +43,7 @@
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.settings.SystemSettings
 import com.android.systemui.util.time.SystemClock
 
 class PeekDisabledSuppressor(
@@ -231,6 +233,7 @@
 class AvalancheSuppressor(
     private val avalancheProvider: AvalancheProvider,
     private val systemClock: SystemClock,
+    private val systemSettings: SystemSettings,
 ) :
     VisualInterruptionFilter(
         types = setOf(PEEK, PULSE),
@@ -253,12 +256,23 @@
     }
 
     override fun shouldSuppress(entry: NotificationEntry): Boolean {
-        val timeSinceAvalanche = systemClock.currentTimeMillis() - avalancheProvider.startTime
-        val isActive = timeSinceAvalanche < avalancheProvider.timeoutMs
+        if (!isCooldownEnabled()) {
+            reason = "FALSE avalanche cooldown setting DISABLED"
+            return false
+        }
+        val timeSinceAvalancheMs = systemClock.currentTimeMillis() - avalancheProvider.startTime
+        val timedOut = timeSinceAvalancheMs >= avalancheProvider.timeoutMs
+        if (timedOut) {
+            reason = "FALSE avalanche event TIMED OUT. " +
+                    "${timeSinceAvalancheMs/1000} seconds since last avalanche"
+            return false
+        }
         val state = calculateState(entry)
-        val suppress = isActive && state == State.SUPPRESS
-        reason = "avalanche suppress=$suppress isActive=$isActive state=$state"
-        return suppress
+        if (state != State.SUPPRESS) {
+            reason = "FALSE avalanche IN ALLOWLIST: $state"
+            return false
+        }
+        return true
     }
 
     private fun calculateState(entry: NotificationEntry): State {
@@ -294,4 +308,11 @@
         }
         return State.SUPPRESS
     }
+
+    private fun isCooldownEnabled(): Boolean {
+        return systemSettings.getInt(
+            Settings.System.NOTIFICATION_COOLDOWN_ENABLED,
+            /* def */ 1
+        ) == 1
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
index 375b6e5c..e6d97c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
@@ -40,6 +40,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.EventLog
 import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.settings.SystemSettings
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
 
@@ -61,7 +62,8 @@
     private val systemClock: SystemClock,
     private val uiEventLogger: UiEventLogger,
     private val userTracker: UserTracker,
-    private val avalancheProvider: AvalancheProvider
+    private val avalancheProvider: AvalancheProvider,
+    private val systemSettings: SystemSettings
 ) : VisualInterruptionDecisionProvider {
 
     init {
@@ -170,7 +172,7 @@
         addFilter(AlertKeyguardVisibilitySuppressor(keyguardNotificationVisibilityProvider))
 
         if (NotificationAvalancheSuppression.isEnabled) {
-            addFilter(AvalancheSuppressor(avalancheProvider, systemClock))
+            addFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings))
             avalancheProvider.register()
         }
         started = true
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 eb6c7b5..bdeaabf 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
@@ -1767,7 +1767,8 @@
      */
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         this(context, attrs, context);
-        Log.wtf(TAG, "This constructor shouldn't be called");
+        // NOTE(b/317503801): Always crash when using the insecure constructor.
+        throw new UnsupportedOperationException("Insecure constructor");
     }
 
     /**
@@ -2068,6 +2069,8 @@
         // Remove views that don't translate
         mTranslateableViews.remove(mChildrenContainerStub);
         mTranslateableViews.remove(mGutsStub);
+        // We don't handle focus highlight in this view, it's done in background drawable instead
+        setDefaultFocusHighlightEnabled(false);
     }
 
     /**
@@ -2804,12 +2807,7 @@
     }
 
     public boolean isExpanded(boolean allowOnKeyguard) {
-        if (DEBUG) {
-            if (!mShowingPublicInitialized && !allowOnKeyguard) {
-                Log.d(TAG, "mShowingPublic is not initialized.");
-            }
-        }
-        return !mShowingPublic && (!mOnKeyguard || allowOnKeyguard)
+        return (!shouldShowPublic()) && (!mOnKeyguard || allowOnKeyguard)
                 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
                 || isUserExpanded());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index ed3a38d..d0db514 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -53,6 +53,8 @@
     private int mTintColor;
     @Nullable private Integer mRippleColor;
     private final float[] mCornerRadii = new float[8];
+    private final float[] mFocusOverlayCornerRadii = new float[8];
+    private float mFocusOverlayStroke = 0;
     private boolean mBottomIsRounded;
     private boolean mBottomAmountClips = true;
     private int mActualHeight = -1;
@@ -74,6 +76,7 @@
                 R.color.notification_state_color_dark);
         mNormalColor = Utils.getColorAttrDefaultColor(mContext,
                 com.android.internal.R.attr.materialColorSurfaceContainerHigh);
+        mFocusOverlayStroke = getResources().getDimension(R.dimen.notification_focus_stroke_width);
     }
 
     @Override
@@ -290,16 +293,30 @@
         if (mDontModifyCorners) {
             return;
         }
-        if (mBackground instanceof LayerDrawable) {
-            int numberOfLayers = ((LayerDrawable) mBackground).getNumberOfLayers();
+        if (mBackground instanceof LayerDrawable layerDrawable) {
+            int numberOfLayers = layerDrawable.getNumberOfLayers();
             for (int i = 0; i < numberOfLayers; i++) {
-                GradientDrawable gradientDrawable =
-                        (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(i);
+                GradientDrawable gradientDrawable = (GradientDrawable) layerDrawable.getDrawable(i);
                 gradientDrawable.setCornerRadii(mCornerRadii);
             }
+            updateFocusOverlayRadii(layerDrawable);
         }
     }
 
+    private void updateFocusOverlayRadii(LayerDrawable background) {
+        GradientDrawable overlay =
+                (GradientDrawable) background.findDrawableByLayerId(
+                        R.id.notification_focus_overlay);
+        for (int i = 0; i < mCornerRadii.length; i++) {
+            // in theory subtracting mFocusOverlayStroke/2 should be enough but notification
+            // background is still peeking a bit from below - probably due to antialiasing or
+            // overlay uneven scaling. So let's subtract full mFocusOverlayStroke to make sure the
+            // radius is a bit smaller and covers background corners fully
+            mFocusOverlayCornerRadii[i] = Math.max(0, mCornerRadii[i] - mFocusOverlayStroke);
+        }
+        overlay.setCornerRadii(mFocusOverlayCornerRadii);
+    }
+
     /** Set the current expand animation size. */
     public void setExpandAnimationSize(int width, int height) {
         mExpandAnimationHeight = height;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
index 5fbcebd..35afda7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
@@ -33,6 +33,8 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.util.time.SystemClock;
 
+import java.util.concurrent.Executor;
+
 import javax.inject.Inject;
 
 /**
@@ -58,10 +60,22 @@
     }
 
     /**
-     * Inflates a new notificationView. This should not be called twice on this object
+     * Inflates a new notificationView asynchronously, calling the {@code listener} on the main
+     * thread when done. This should not be called twice on this object.
      */
     public void inflate(Context context, ViewGroup parent, NotificationEntry entry,
             RowInflationFinishedListener listener) {
+        inflate(context, parent, entry, null, listener);
+    }
+
+    /**
+     * Inflates a new notificationView asynchronously, calling the {@code listener} on the supplied
+     * {@code listenerExecutor} (or the main thread if null) when done. This should not be called
+     * twice on this object.
+     */
+    @VisibleForTesting
+    public void inflate(Context context, ViewGroup parent, NotificationEntry entry,
+            @Nullable Executor listenerExecutor, RowInflationFinishedListener listener) {
         if (TRACE_ORIGIN) {
             mInflateOrigin = new Throwable("inflate requested here");
         }
@@ -72,7 +86,7 @@
 
         mLogger.logInflateStart(entry);
         mInflateStartTimeMs = mSystemClock.elapsedRealtime();
-        inflater.inflate(R.layout.status_bar_notification_row, parent, this);
+        inflater.inflate(R.layout.status_bar_notification_row, parent, listenerExecutor, this);
     }
 
     private RowAsyncLayoutInflater makeRowInflater(NotificationEntry entry) {
@@ -80,12 +94,12 @@
     }
 
     @VisibleForTesting
-    static class RowAsyncLayoutInflater implements AsyncLayoutFactory {
+    public static class RowAsyncLayoutInflater implements AsyncLayoutFactory {
         private final NotificationEntry mEntry;
         private final SystemClock mSystemClock;
         private final RowInflaterTaskLogger mLogger;
 
-        RowAsyncLayoutInflater(NotificationEntry entry, SystemClock systemClock,
+        public RowAsyncLayoutInflater(NotificationEntry entry, SystemClock systemClock,
                 RowInflaterTaskLogger logger) {
             mEntry = entry;
             mSystemClock = systemClock;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index d6118a0..d3c874c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.row
 
+import android.app.Flags
 import android.app.Notification
 import android.app.Notification.MessagingStyle
 import android.app.Person
@@ -131,7 +132,7 @@
         val senderName =
             systemUiContext.resources.getString(
                 R.string.conversation_single_line_name_display,
-                name
+                if (Flags.cleanUpSpansAndNewLines()) name?.toString() else name
             )
 
         // We need to find back-up values for those texts if they are needed and empty
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 5b9eb21..dedf366 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
@@ -291,7 +291,7 @@
         mOverExpansion = overExpansion;
     }
 
-    float getOverExpansion() {
+    public float getOverExpansion() {
         return mOverExpansion;
     }
 
@@ -742,7 +742,7 @@
         pw.println("mHideSensitive=" + mHideSensitive);
         pw.println("mShadeExpanded=" + mShadeExpanded);
         pw.println("mClearAllInProgress=" + mClearAllInProgress);
-        pw.println("mStatusBarState=" + mStatusBarState);
+        pw.println("mStatusBarState=" + StatusBarState.toString(mStatusBarState));
         pw.println("mExpansionChanging=" + mExpansionChanging);
         pw.println("mPanelFullWidth=" + mIsSmallScreen);
         pw.println("mPulsing=" + mPulsing);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
index 03a1082..0c248f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
@@ -30,7 +30,7 @@
     public static final int NO_DELAY = -1;
     boolean animateAlpha;
     boolean animateX;
-    boolean animateY;
+    public boolean animateY;
     ArraySet<View> animateYViews = new ArraySet<>();
     boolean animateZ;
     boolean animateHeight;
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 5dc37e0..92c597c 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
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.notification.row.HybridGroupManager;
 import com.android.systemui.statusbar.notification.row.HybridNotificationView;
 import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 
@@ -1429,7 +1430,7 @@
             if (singleLineView != null) {
                 minExpandHeight += singleLineView.getHeight();
             } else {
-                if (AsyncGroupHeaderViewInflation.isEnabled()) {
+                if (AsyncHybridViewInflation.isEnabled()) {
                     minExpandHeight += mMinSingleLineHeight;
                 } else {
                     Log.e(TAG, "getMinHeight: child " + child.getEntry().getKey()
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 6a7a5cd..de0f247 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
@@ -23,6 +23,7 @@
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_CLEAR_ALL;
 import static com.android.systemui.Flags.newAodTransition;
+import static com.android.systemui.Flags.notificationOverExpansionClippingFix;
 import static com.android.systemui.flags.Flags.UNCLEARED_TRANSIENT_HUN_FIX;
 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
 import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
@@ -111,8 +112,12 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
+import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor;
 import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation;
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape;
+import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -135,6 +140,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.function.BiConsumer;
@@ -143,7 +149,9 @@
 /**
  * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
  */
-public class NotificationStackScrollLayout extends ViewGroup implements Dumpable {
+public class NotificationStackScrollLayout
+        extends ViewGroup
+        implements Dumpable, NotificationScrollView {
 
     public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
     private static final String TAG = "StackScroller";
@@ -218,6 +226,7 @@
      */
     private final StackScrollAlgorithm mStackScrollAlgorithm;
     private final AmbientState mAmbientState;
+    private final ScrollViewFields mScrollViewFields = new ScrollViewFields();
 
     private final GroupMembershipManager mGroupMembershipManager;
     private final GroupExpansionManager mGroupExpansionManager;
@@ -443,7 +452,9 @@
     private boolean mIsClipped;
     private Rect mRequestedClipBounds;
     private boolean mInHeadsUpPinnedMode;
-    private boolean mHeadsUpAnimatingAway;
+    @VisibleForTesting
+    boolean mHeadsUpAnimatingAway;
+    private Consumer<Boolean> mHeadsUpAnimatingAwayListener;
     private int mStatusBarState;
     private int mUpcomingStatusBarState;
     private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
@@ -472,7 +483,6 @@
     private Interpolator mHideXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
 
     private final NotificationSectionsManager mSectionsManager;
-    private boolean mAnimateBottomOnLayout;
     private float mLastSentAppear;
     private float mLastSentExpandedHeight;
     private boolean mWillExpand;
@@ -507,6 +517,7 @@
     private int mRoundedRectClippingTop;
     private int mRoundedRectClippingBottom;
     private int mRoundedRectClippingRight;
+    private int mRoundedRectClippingYTranslation;
     private final float[] mBgCornerRadii = new float[8];
 
     /**
@@ -590,7 +601,7 @@
         @Override
         public boolean isScrolledToTop() {
             if (SceneContainerFlag.isEnabled()) {
-                return mController.isPlaceholderScrolledToTop();
+                return mScrollViewFields.isScrolledToTop();
             } else {
                 return mOwnScrollY == 0;
             }
@@ -662,6 +673,9 @@
      */
     void setOverExpansion(float margin) {
         mAmbientState.setOverExpansion(margin);
+        if (notificationOverExpansionClippingFix() && !SceneContainerFlag.isEnabled()) {
+            setRoundingClippingYTranslation((int) margin);
+        }
         updateStackPosition();
         requestChildrenUpdate();
     }
@@ -855,7 +869,8 @@
         drawDebugInfo(canvas, y, Color.MAGENTA,
                 /* label= */ "mContentHeight = " + y);
 
-        drawDebugInfo(canvas, mRoundedRectClippingBottom, Color.DKGRAY,
+        y = mRoundedRectClippingBottom;
+        drawDebugInfo(canvas, y, Color.DKGRAY,
                 /* label= */ "mRoundedRectClippingBottom) = " + y);
     }
 
@@ -1131,6 +1146,48 @@
         }
     }
 
+    @Override
+    public View asView() {
+        return this;
+    }
+
+    @Override
+    public void setScrolledToTop(boolean scrolledToTop) {
+        mScrollViewFields.setScrolledToTop(scrolledToTop);
+    }
+
+    @Override
+    public void setStackTop(float stackTop) {
+        mScrollViewFields.setStackTop(stackTop);
+        // TODO(b/332574413): replace the following with using stackTop
+        updateTopPadding(stackTop, isAddOrRemoveAnimationPending());
+    }
+
+    @Override
+    public void setStackBottom(float stackBottom) {
+        mScrollViewFields.setStackBottom(stackBottom);
+    }
+
+    @Override
+    public void setHeadsUpTop(float headsUpTop) {
+        mScrollViewFields.setHeadsUpTop(headsUpTop);
+    }
+
+    @Override
+    public void setSyntheticScrollConsumer(@Nullable Consumer<Float> consumer) {
+        mScrollViewFields.setSyntheticScrollConsumer(consumer);
+    }
+
+    @Override
+    public void setStackHeightConsumer(@Nullable Consumer<Float> consumer) {
+        mScrollViewFields.setStackHeightConsumer(consumer);
+    }
+
+    @Override
+    public void setHeadsUpHeightConsumer(@Nullable Consumer<Float> consumer) {
+        mScrollViewFields.setHeadsUpHeightConsumer(consumer);
+    }
+
     /**
      * @param listener to be notified after the location of Notification children might have
      *                 changed.
@@ -1381,6 +1438,31 @@
         mOnStackYChanged = onStackYChanged;
     }
 
+    @Override
+    public void setExpandFraction(float expandFraction) {
+        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
+        final float oldFraction = mAmbientState.getExpansionFraction();
+        final boolean wasExpanding = oldFraction != 0f && oldFraction != 1f;
+        final boolean nowExpanding = expandFraction != 0f && expandFraction != 1f;
+
+        // need to enter 'expanding' state before handling the new expand fraction, and then
+        if (nowExpanding && !wasExpanding) {
+            onExpansionStarted();
+            mController.checkSnoozeLeavebehind();
+        }
+
+        // Update the expand progress between started/stopped events
+        mAmbientState.setExpansionFraction(expandFraction);
+        // TODO(b/332577544): don't convert to height which then converts to the fraction again
+        setExpandedHeight(expandFraction * getHeight());
+
+        // expansion stopped event requires that the expandFraction has already been updated
+        if (!nowExpanding && wasExpanding) {
+            setCheckForLeaveBehind(false);
+            onExpansionStopped();
+        }
+    }
+
     /**
      * Update the height of the panel.
      *
@@ -1793,6 +1875,13 @@
     private void updateImeInset(WindowInsets windowInsets) {
         mImeInset = windowInsets.getInsets(WindowInsets.Type.ime()).bottom;
 
+        if (mFooterView != null && mFooterView.getViewState() != null) {
+            // Do not animate footer Y when showing IME so that after IME hides, the footer
+            // appears at the correct Y. Once resetY is true, it remains true (even when IME
+            // hides, where mImeInset=0) until reset in FooterViewState#animateTo.
+            ((FooterView.FooterViewState) mFooterView.getViewState()).resetY |= mImeInset > 0;
+        }
+
         if (mForcedScroll != null) {
             updateForcedScroll();
         }
@@ -2315,7 +2404,7 @@
                         /* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications,
                         shelfIntrinsicHeight);
         mIntrinsicContentHeight = height;
-        mController.setIntrinsicContentHeight(mIntrinsicContentHeight);
+        mScrollViewFields.sendStackHeight(height);
 
         // The topPadding can be bigger than the regular padding when qs is expanded, in that
         // state the maxPanelHeight and the contentHeight should be bigger
@@ -2856,23 +2945,11 @@
     }
 
     private void updateFirstAndLastBackgroundViews() {
-        NotificationSection firstSection = getFirstVisibleSection();
-        NotificationSection lastSection = getLastVisibleSection();
-        ExpandableView previousFirstChild =
-                firstSection == null ? null : firstSection.getFirstVisibleChild();
-        ExpandableView previousLastChild =
-                lastSection == null ? null : lastSection.getLastVisibleChild();
-
-        ExpandableView firstChild = getFirstChildWithBackground();
         ExpandableView lastChild = getLastChildWithBackground();
         boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsForAllSections(
                 mSections, getChildrenWithBackground());
 
-        if (mAnimationsEnabled && mIsExpanded) {
-        } else {
-        }
         mAmbientState.setLastVisibleBackgroundChild(lastChild);
-        mAnimateBottomOnLayout = false;
         invalidate();
     }
 
@@ -3555,7 +3632,7 @@
 
     protected boolean isInsideQsHeader(MotionEvent ev) {
         if (SceneContainerFlag.isEnabled()) {
-            return ev.getY() < mController.getPlaceholderTop();
+            return ev.getY() < mScrollViewFields.getScrimClippingShape().getBounds().getTop();
         }
 
         mQsHeader.getBoundsOnScreen(mQsHeaderBound);
@@ -4002,7 +4079,14 @@
         mSwipeHelper.setIsExpanded(isExpanded);
         if (changed) {
             mWillExpand = false;
-            if (!mIsExpanded) {
+            if (mIsExpanded) {
+                // Resetting headsUpAnimatingAway on Shade expansion avoids delays caused by
+                // waiting for all child animations to finish.
+                // TODO(b/328390331) Do we need to reset this on QS expanded as well?
+                if (NotificationsHeadsUpRefactor.isEnabled()) {
+                    setHeadsUpAnimatingAway(false);
+                }
+            } else {
                 mGroupExpansionManager.collapseGroups();
                 mExpandHelper.cancelImmediately();
                 if (!mIsExpansionChanging) {
@@ -4088,7 +4172,7 @@
                     // to it so that it can scroll the stack and scrim accordingly.
                     if (SceneContainerFlag.isEnabled()) {
                         float diff = endPosition - layoutEnd;
-                        mController.sendSyntheticScrollToSceneFramework(diff);
+                        mScrollViewFields.sendSyntheticScroll(diff);
                     }
                     setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
                     mDisallowScrollingInThisMotion = true;
@@ -4108,6 +4192,9 @@
 
     void onChildAnimationFinished() {
         setAnimationRunning(false);
+        if (NotificationsHeadsUpRefactor.isEnabled()) {
+            setHeadsUpAnimatingAway(false);
+        }
         requestChildrenUpdate();
         runAnimationFinishedRunnables();
         clearTransient();
@@ -4303,7 +4390,8 @@
     /**
      * See {@link AmbientState#setDozing}.
      */
-    public void setDozing(boolean dozing, boolean animate) {
+    @Override
+    public void setDozing(boolean dozing) {
         if (mAmbientState.isDozing() == dozing) {
             return;
         }
@@ -4427,18 +4515,18 @@
         mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
 
         if (areNotificationsHiddenInShade) {
-            updateEmptyShadeView(R.string.dnd_suppressing_shade_text, 0, 0);
+            updateEmptyShadeViewResources(R.string.dnd_suppressing_shade_text, 0, 0);
         } else if (hasFilteredOutSeenNotifications) {
-            updateEmptyShadeView(
+            updateEmptyShadeViewResources(
                     R.string.no_unseen_notif_text,
                     R.string.unlock_to_see_notif_text,
                     R.drawable.ic_friction_lock_closed);
         } else {
-            updateEmptyShadeView(R.string.empty_shade_text, 0, 0);
+            updateEmptyShadeViewResources(R.string.empty_shade_text, 0, 0);
         }
     }
 
-    private void updateEmptyShadeView(
+    private void updateEmptyShadeViewResources(
             @StringRes int newTextRes,
             @StringRes int newFooterTextRes,
             @DrawableRes int newFooterIconRes) {
@@ -4635,6 +4723,7 @@
     }
 
     public void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
+        NotificationsHeadsUpRefactor.assertInLegacyMode();
         ExpandableNotificationRow row = entry.getHeadsUpAnimationView();
         generateHeadsUpAnimation(row, isHeadsUp);
     }
@@ -4668,6 +4757,9 @@
             mNeedsAnimation = true;
             if (!mIsExpanded && !mWillExpand && !isHeadsUp) {
                 row.setHeadsUpAnimatingAway(true);
+                if (NotificationsHeadsUpRefactor.isEnabled()) {
+                    setHeadsUpAnimatingAway(true);
+                }
             }
             requestChildrenUpdate();
         }
@@ -4857,11 +4949,28 @@
         updateClipping();
     }
 
+    /** TODO(b/328390331) make this private, when {@link NotificationsHeadsUpRefactor} is removed */
     public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
-        mHeadsUpAnimatingAway = headsUpAnimatingAway;
+        if (mHeadsUpAnimatingAway != headsUpAnimatingAway) {
+            mHeadsUpAnimatingAway = headsUpAnimatingAway;
+            if (mHeadsUpAnimatingAwayListener != null) {
+                mHeadsUpAnimatingAwayListener.accept(headsUpAnimatingAway);
+            }
+        }
         updateClipping();
     }
 
+    /**
+     * Sets a listener to be notified about the heads up disappear animation state changes. If there
+     * are overlapping animations, it will receive updates when the first disappar animation has
+     * started, and when the last has finished.
+     *
+     * @param headsUpAnimatingAwayListener to be notified about disappear animation state changes.
+     */
+    public void setHeadsUpAnimatingAwayListener(
+            Consumer<Boolean> headsUpAnimatingAwayListener) {
+        mHeadsUpAnimatingAwayListener = headsUpAnimatingAwayListener;
+    }
     @VisibleForTesting
     public void setStatusBarState(int statusBarState) {
         mStatusBarState = statusBarState;
@@ -4971,6 +5080,7 @@
                     elapsedRealtime - mLastUpdateSidePaddingElapsedRealtime);
             println(pw, "isSmallLandscapeLockscreenEnabled", mIsSmallLandscapeLockscreenEnabled);
             mNotificationStackSizeCalculator.dump(pw, args);
+            mScrollViewFields.dump(pw);
         });
         pw.println();
         pw.println("Contents:");
@@ -5011,6 +5121,7 @@
         pw.append(" t=").print(mRoundedRectClippingTop);
         pw.append(" r=").print(mRoundedRectClippingRight);
         pw.append(" b=").print(mRoundedRectClippingBottom);
+        pw.append(" +y=").print(mRoundedRectClippingYTranslation);
         pw.append("} topRadius=").print(mBgCornerRadii[0]);
         pw.append(" bottomRadius=").println(mBgCornerRadii[4]);
     }
@@ -5255,7 +5366,8 @@
             mActivityStarter.startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
         });
         setEmptyShadeView(view);
-        updateEmptyShadeView(
+        view.setVisible(oldView != null && oldView.isVisible(), /* animate = */ false);
+        updateEmptyShadeViewResources(
                 oldView == null ? R.string.empty_shade_text : oldView.getTextResource(),
                 oldView == null ? 0 : oldView.getFooterTextResource(),
                 oldView == null ? 0 : oldView.getFooterIconResource());
@@ -5347,10 +5459,6 @@
         }
     }
 
-    void setAnimateBottomOnLayout(boolean animateBottomOnLayout) {
-        mAnimateBottomOnLayout = animateBottomOnLayout;
-    }
-
     public void setOnPulseHeightChangedListener(Runnable listener) {
         mAmbientState.setOnPulseHeightChangedListener(listener);
     }
@@ -5511,8 +5619,40 @@
     /**
      * Set rounded rect clipping bounds on this view.
      */
+    @Override
+    public void setScrimClippingShape(@Nullable ShadeScrimShape shape) {
+        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
+        if (Objects.equals(mScrollViewFields.getScrimClippingShape(), shape)) return;
+        mScrollViewFields.setScrimClippingShape(shape);
+        mShouldUseRoundedRectClipping = shape != null;
+        mRoundedClipPath.reset();
+        if (shape != null) {
+            ShadeScrimBounds bounds = shape.getBounds();
+            mRoundedRectClippingLeft = (int) bounds.getLeft();
+            mRoundedRectClippingTop = (int) bounds.getTop();
+            mRoundedRectClippingRight = (int) bounds.getRight();
+            mRoundedRectClippingBottom = (int) bounds.getBottom();
+            mBgCornerRadii[0] = shape.getTopRadius();
+            mBgCornerRadii[1] = shape.getTopRadius();
+            mBgCornerRadii[2] = shape.getTopRadius();
+            mBgCornerRadii[3] = shape.getTopRadius();
+            mBgCornerRadii[4] = shape.getBottomRadius();
+            mBgCornerRadii[5] = shape.getBottomRadius();
+            mBgCornerRadii[6] = shape.getBottomRadius();
+            mBgCornerRadii[7] = shape.getBottomRadius();
+            mRoundedClipPath.addRoundRect(
+                    bounds.getLeft(), bounds.getTop(), bounds.getRight(), bounds.getBottom(),
+                    mBgCornerRadii, Path.Direction.CW);
+        }
+        invalidate();
+    }
+
+    /**
+     * Set rounded rect clipping bounds on this view.
+     */
     public void setRoundedClippingBounds(int left, int top, int right, int bottom, int topRadius,
                                          int bottomRadius) {
+        SceneContainerFlag.assertInLegacyMode();
         if (mRoundedRectClippingLeft == left && mRoundedRectClippingRight == right
                 && mRoundedRectClippingBottom == bottom && mRoundedRectClippingTop == top
                 && mBgCornerRadii[0] == topRadius && mBgCornerRadii[5] == bottomRadius) {
@@ -5530,8 +5670,28 @@
         mBgCornerRadii[5] = bottomRadius;
         mBgCornerRadii[6] = bottomRadius;
         mBgCornerRadii[7] = bottomRadius;
+        updateRoundedClipPath();
+    }
+
+    // see b/288553572
+    private void setRoundingClippingYTranslation(int yTranslation) {
+        SceneContainerFlag.assertInLegacyMode();
+        if (mRoundedRectClippingYTranslation == yTranslation) {
+            return;
+        }
+        mRoundedRectClippingYTranslation = yTranslation;
+        updateRoundedClipPath();
+    }
+
+    private void updateRoundedClipPath() {
+        SceneContainerFlag.assertInLegacyMode();
         mRoundedClipPath.reset();
-        mRoundedClipPath.addRoundRect(left, top, right, bottom, mBgCornerRadii, Path.Direction.CW);
+        mRoundedClipPath.addRoundRect(
+                mRoundedRectClippingLeft,
+                mRoundedRectClippingTop + mRoundedRectClippingYTranslation,
+                mRoundedRectClippingRight,
+                mRoundedRectClippingBottom + mRoundedRectClippingYTranslation,
+                mBgCornerRadii, Path.Direction.CW);
         if (mShouldUseRoundedRectClipping) {
             invalidate();
         }
@@ -5590,6 +5750,7 @@
      * Should we use rounded rect clipping
      */
     private void updateUseRoundedRectClipping() {
+        if (SceneContainerFlag.isEnabled()) return;
         // We don't want to clip notifications when QS is expanded, because incoming heads up on
         // the bottom would be clipped otherwise
         boolean qsAllowsClipping = mQsExpansionFraction < 0.5f || mShouldUseSplitNotificationShade;
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 59901ac..9ed5ac9 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
@@ -68,8 +68,6 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
 import com.android.systemui.keyguard.shared.model.KeyguardState;
@@ -83,6 +81,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.domain.interactor.PowerInteractor;
 import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.scene.ui.view.WindowRootView;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.shade.ShadeViewController;
@@ -99,6 +98,7 @@
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -125,7 +125,6 @@
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.row.NotificationSnooze;
 import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor;
 import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
@@ -168,6 +167,7 @@
     private final NotificationGutsManager mNotificationGutsManager;
     private final NotificationsController mNotificationsController;
     private final NotificationVisibilityProvider mVisibilityProvider;
+    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
     private final HeadsUpManager mHeadsUpManager;
     private final NotificationRoundnessManager mNotificationRoundnessManager;
     private final TunerService mTunerService;
@@ -189,7 +189,6 @@
     private final VisibilityLocationProviderDelegator mVisibilityLocationProviderDelegator;
     private final ShadeController mShadeController;
     private final Provider<WindowRootView> mWindowRootView;
-    private final NotificationStackAppearanceInteractor mStackAppearanceInteractor;
     private final KeyguardMediaController mKeyguardMediaController;
     private final SysuiStatusBarStateController mStatusBarStateController;
     private final KeyguardBypassController mKeyguardBypassController;
@@ -211,11 +210,9 @@
     @Nullable
     private Boolean mHistoryEnabled;
     private int mBarState;
-    private boolean mIsBouncerShowingFromCentralSurfaces;
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private boolean mIsInTransitionToAod = false;
 
-    private final FeatureFlagsClassic mFeatureFlags;
     private final NotificationTargetsHelper mNotificationTargetsHelper;
     private final SecureSettings mSecureSettings;
     private final NotificationDismissibilityProvider mDismissibilityProvider;
@@ -311,10 +308,6 @@
     };
 
     private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> {
-        if (mView.isExpanded()) {
-            // The bottom might change because we're using the final actual height of the view
-            mView.setAnimateBottomOnLayout(true);
-        }
         if (!FooterViewRefactor.isEnabled()) {
             // Let's update the footer once the notifications have been updated (in the next frame)
             mView.post(this::updateFooter);
@@ -710,6 +703,7 @@
             NotificationGutsManager notificationGutsManager,
             NotificationsController notificationsController,
             NotificationVisibilityProvider visibilityProvider,
+            NotificationWakeUpCoordinator wakeUpCoordinator,
             HeadsUpManager headsUpManager,
             NotificationRoundnessManager notificationRoundnessManager,
             TunerService tunerService,
@@ -742,12 +736,10 @@
             NotificationListViewBinder viewBinder,
             ShadeController shadeController,
             Provider<WindowRootView> windowRootView,
-            NotificationStackAppearanceInteractor stackAppearanceInteractor,
             InteractionJankMonitor jankMonitor,
             StackStateLogger stackLogger,
             NotificationStackScrollLogger logger,
             NotificationStackSizeCalculator notificationStackSizeCalculator,
-            FeatureFlagsClassic featureFlags,
             NotificationTargetsHelper notificationTargetsHelper,
             SecureSettings secureSettings,
             NotificationDismissibilityProvider dismissibilityProvider,
@@ -763,6 +755,7 @@
         mNotificationGutsManager = notificationGutsManager;
         mNotificationsController = notificationsController;
         mVisibilityProvider = visibilityProvider;
+        mWakeUpCoordinator = wakeUpCoordinator;
         mHeadsUpManager = headsUpManager;
         mNotificationRoundnessManager = notificationRoundnessManager;
         mTunerService = tunerService;
@@ -795,14 +788,15 @@
         mSeenNotificationsInteractor = seenNotificationsInteractor;
         mShadeController = shadeController;
         mWindowRootView = windowRootView;
-        mStackAppearanceInteractor = stackAppearanceInteractor;
-        mFeatureFlags = featureFlags;
         mNotificationTargetsHelper = notificationTargetsHelper;
         mSecureSettings = secureSettings;
         mDismissibilityProvider = dismissibilityProvider;
         mActivityStarter = activityStarter;
         mSensitiveNotificationProtectionController = sensitiveNotificationProtectionController;
         mView.passSplitShadeStateController(splitShadeStateController);
+        if (SceneContainerFlag.isEnabled()) {
+            mWakeUpCoordinator.setStackScroller(this);
+        }
         mDumpManager.registerDumpable(this);
         updateResources();
         setUpView();
@@ -1124,6 +1118,7 @@
     }
 
     public boolean isAddOrRemoveAnimationPending() {
+        SceneContainerFlag.assertInLegacyMode();
         return mView != null && mView.isAddOrRemoveAnimationPending();
     }
 
@@ -1163,29 +1158,6 @@
         }
     }
 
-    /** Send internal notification expansion to the scene container framework. */
-    public void sendSyntheticScrollToSceneFramework(Float delta) {
-        mStackAppearanceInteractor.setSyntheticScroll(delta);
-    }
-
-    /** Get the y-coordinate of the top bound of the stack. */
-    public float getPlaceholderTop() {
-        return mStackAppearanceInteractor.getShadeScrimBounds().getValue().getTop();
-    }
-
-    /**
-     * Returns whether the notification stack is scrolled to the top; i.e., it cannot be scrolled
-     * down any further.
-     */
-    public boolean isPlaceholderScrolledToTop() {
-        return mStackAppearanceInteractor.getScrolledToTop().getValue();
-    }
-
-    /** Set the intrinsic height of the stack content without additional padding. */
-    public void setIntrinsicContentHeight(float intrinsicContentHeight) {
-        mStackAppearanceInteractor.setStackHeight(intrinsicContentHeight);
-    }
-
     public void setIntrinsicPadding(int intrinsicPadding) {
         mView.setIntrinsicPadding(intrinsicPadding);
     }
@@ -1264,6 +1236,7 @@
     }
 
     public void setScrollingEnabled(boolean enabled) {
+        SceneContainerFlag.assertInLegacyMode();
         mView.setScrollingEnabled(enabled);
     }
 
@@ -1284,6 +1257,7 @@
     }
 
     public void updateTopPadding(float qsHeight, boolean animate) {
+        SceneContainerFlag.assertInLegacyMode();
         mView.updateTopPadding(qsHeight, animate);
     }
 
@@ -1386,11 +1360,13 @@
     }
 
     public void onExpansionStarted() {
+        SceneContainerFlag.assertInLegacyMode();
         mView.onExpansionStarted();
         checkSnoozeLeavebehind();
     }
 
     public void onExpansionStopped() {
+        SceneContainerFlag.assertInLegacyMode();
         mView.setCheckForLeaveBehind(false);
         mView.onExpansionStopped();
     }
@@ -1412,14 +1388,6 @@
     }
 
     /**
-     * Sets whether the bouncer is currently showing. Should only be called from
-     * {@link CentralSurfaces}.
-     */
-    public void setBouncerShowingFromCentralSurfaces(boolean bouncerShowing) {
-        mIsBouncerShowingFromCentralSurfaces = bouncerShowing;
-    }
-
-    /**
      * Set the visibility of the view, and propagate it to specific children.
      *
      * @param visible either the view is visible or not.
@@ -1456,7 +1424,7 @@
                 // For more details, see: b/228790482
                 && !mIsInTransitionToAod
                 // Don't show any notification content if the bouncer is showing. See b/267060171.
-                && !isBouncerShowing();
+                && !mPrimaryBouncerInteractor.isBouncerShowing();
 
         mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
 
@@ -1464,24 +1432,6 @@
     }
 
     /**
-     * Returns whether the bouncer is currently showing.
-     *
-     * There's a possible timing difference between when CentralSurfaces marks the bouncer as not
-     * showing and when PrimaryBouncerInteractor marks the bouncer as not showing. (CentralSurfaces
-     * appears to mark the bouncer as showing for 10-200ms longer than PrimaryBouncerInteractor.)
-     *
-     * This timing difference could be load bearing, which is why we have a feature flag protecting
-     * where we fetch the value from. This flag is intended to be short-lived.
-     */
-    private boolean isBouncerShowing() {
-        if (mFeatureFlags.isEnabled(Flags.USE_REPOS_FOR_BOUNCER_SHOWING)) {
-            return mPrimaryBouncerInteractor.isBouncerShowing();
-        } else {
-            return mIsBouncerShowingFromCentralSurfaces;
-        }
-    }
-
-    /**
      * Update the importantForAccessibility of NotificationStackScrollLayout.
      * <p>
      * We want the NSSL to be unimportant for accessibility when there's no
@@ -1503,6 +1453,7 @@
     }
 
     public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+        NotificationsHeadsUpRefactor.assertInLegacyMode();
         mView.setHeadsUpAnimatingAway(headsUpAnimatingAway);
     }
 
@@ -1519,6 +1470,7 @@
     }
 
     public void setExpandedHeight(float expandedHeight) {
+        SceneContainerFlag.assertInLegacyMode();
         mView.setExpandedHeight(expandedHeight);
     }
 
@@ -1534,7 +1486,8 @@
     }
 
     public void setDozing(boolean dozing, boolean animate) {
-        mView.setDozing(dozing, animate);
+        SceneContainerFlag.assertInLegacyMode();
+        mView.setDozing(dozing);
     }
 
     public void setPulsing(boolean pulsing, boolean animatePulse) {
@@ -1794,6 +1747,7 @@
      */
     public void setRoundedClippingBounds(int left, int top, int right, int bottom, int topRadius,
             int bottomRadius) {
+        SceneContainerFlag.assertInLegacyMode();
         mView.setRoundedClippingBounds(left, top, right, bottom, topRadius, bottomRadius);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
new file mode 100644
index 0000000..edac5ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack
+
+import android.util.IndentingPrintWriter
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
+import com.android.systemui.util.printSection
+import com.android.systemui.util.println
+import java.util.function.Consumer
+
+/**
+ * This is a state holder object used by [NSSL][NotificationStackScrollLayout] to contain states
+ * provided by the `NotificationScrollViewBinder` to the `NotificationScrollView`.
+ *
+ * Unlike AmbientState, no class other than NSSL should ever have access to this class in any way.
+ * These fields are effectively NSSL's private fields.
+ */
+class ScrollViewFields {
+    /** Used to produce the clipping path */
+    var scrimClippingShape: ShadeScrimShape? = null
+    /** Y coordinate in view pixels of the top of the notification stack */
+    var stackTop: Float = 0f
+    /**
+     * Y coordinate in view pixels above which the bottom of the notification stack / shelf / footer
+     * must be.
+     */
+    var stackBottom: Float = 0f
+    /** Y coordinate in view pixels of the top of the HUN */
+    var headsUpTop: Float = 0f
+    /** Whether the notifications are scrolled all the way to the top (i.e. when freshly opened) */
+    var isScrolledToTop: Boolean = true
+
+    /**
+     * When internal NSSL expansion requires the stack to be scrolled (e.g. to keep an expanding
+     * notification in view), that scroll amount can be sent here and it will be handled by the
+     * placeholder
+     */
+    var syntheticScrollConsumer: Consumer<Float>? = null
+    /**
+     * Any time the stack height is recalculated, it should be updated here to be used by the
+     * placeholder
+     */
+    var stackHeightConsumer: Consumer<Float>? = null
+    /**
+     * Any time the heads up height is recalculated, it should be updated here to be used by the
+     * placeholder
+     */
+    var headsUpHeightConsumer: Consumer<Float>? = null
+
+    /** send the [syntheticScroll] to the [syntheticScrollConsumer], if present. */
+    fun sendSyntheticScroll(syntheticScroll: Float) =
+        syntheticScrollConsumer?.accept(syntheticScroll)
+    /** send the [stackHeight] to the [stackHeightConsumer], if present. */
+    fun sendStackHeight(stackHeight: Float) = stackHeightConsumer?.accept(stackHeight)
+    /** send the [headsUpHeight] to the [headsUpHeightConsumer], if present. */
+    fun sendHeadsUpHeight(headsUpHeight: Float) = headsUpHeightConsumer?.accept(headsUpHeight)
+
+    fun dump(pw: IndentingPrintWriter) {
+        pw.printSection("StackViewStates") {
+            pw.println("scrimClippingShape", scrimClippingShape)
+            pw.println("stackTop", stackTop)
+            pw.println("stackBottom", stackBottom)
+            pw.println("headsUpTop", headsUpTop)
+            pw.println("isScrolledToTop", isScrolledToTop)
+        }
+    }
+}
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 5eaccd9..e980794 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
@@ -594,7 +594,11 @@
         );
         if (view instanceof FooterView) {
             if (FooterViewRefactor.isEnabled()) {
-                if (((FooterView) view).shouldBeHidden()) {
+                // TODO(b/333445519): shouldBeHidden should reflect whether the shade is closed
+                //  already, so we shouldn't need to use ambientState here. However, currently it
+                //  doesn't get updated quickly enough and can cause the footer to flash when
+                //  closing the shade. As such, we temporarily also check the ambientState directly.
+                if (((FooterView) view).shouldBeHidden() || !ambientState.isShadeExpanded()) {
                     viewState.hidden = true;
                 } else {
                     final float footerEnd = algorithmState.mCurrentExpandedYPosition
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt
index 462547e..b047379 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationPlaceholderRepository.kt
@@ -27,8 +27,12 @@
  */
 @SysUISingleton
 class NotificationPlaceholderRepository @Inject constructor() {
-    /** The bounds of the notification shade scrim / container in the current scene. */
-    val shadeScrimBounds = MutableStateFlow(ShadeScrimBounds())
+    /**
+     * The bounds of the notification shade scrim / container in the current scene.
+     *
+     * When `null`, clipping should not be applied to notifications.
+     */
+    val shadeScrimBounds = MutableStateFlow<ShadeScrimBounds?>(null)
 
     /**
      * The y-coordinate in px of top of the contents of the notification stack. This value can be
@@ -44,7 +48,7 @@
     val headsUpTop = MutableStateFlow(0f)
 
     /** height made available to the notifications in the size-constrained mode of lock screen. */
-    val constrainedAvailableSpace = MutableStateFlow(0f)
+    val constrainedAvailableSpace = MutableStateFlow(0)
 
     /**
      * Whether the notification stack is scrolled to the top; i.e., it cannot be scrolled down any
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
index 938e43e..8a9da69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
@@ -35,7 +35,7 @@
     val stackHeight = MutableStateFlow(0f)
 
     /** The height in px of the current heads up notification. */
-    val activeHeadsUpRowHeight = MutableStateFlow(0f)
+    val headsUpHeight = MutableStateFlow(0f)
 
     /**
      * The amount in px that the notification stack should scroll due to internal expansion. This
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
index 32562f1..a5b4f5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
@@ -42,7 +42,7 @@
     shadeInteractor: ShadeInteractor,
 ) {
     /** The bounds of the notification stack in the current scene. */
-    val shadeScrimBounds: StateFlow<ShadeScrimBounds> =
+    val shadeScrimBounds: StateFlow<ShadeScrimBounds?> =
         placeholderRepository.shadeScrimBounds.asStateFlow()
 
     /**
@@ -59,8 +59,8 @@
                 isExpandingFromHeadsUp,
             ) { shadeMode, isExpandingFromHeadsUp ->
                 ShadeScrimRounding(
-                    roundTop = !(shadeMode == ShadeMode.Split && isExpandingFromHeadsUp),
-                    roundBottom = shadeMode != ShadeMode.Single,
+                    isTopRounded = !(shadeMode == ShadeMode.Split && isExpandingFromHeadsUp),
+                    isBottomRounded = shadeMode != ShadeMode.Single,
                 )
             }
             .distinctUntilChanged()
@@ -72,15 +72,28 @@
      */
     val stackHeight: StateFlow<Float> = viewHeightRepository.stackHeight.asStateFlow()
 
+    /** The height in px of the contents of the HUN. */
+    val headsUpHeight: StateFlow<Float> = viewHeightRepository.headsUpHeight.asStateFlow()
+
     /** The y-coordinate in px of top of the contents of the notification stack. */
     val stackTop: StateFlow<Float> = placeholderRepository.stackTop.asStateFlow()
 
+    /** The y-coordinate in px of bottom of the contents of the notification stack. */
+    val stackBottom: StateFlow<Float> = placeholderRepository.stackBottom.asStateFlow()
+
+    /** The height of the keyguard's available space bounds */
+    val constrainedAvailableSpace: StateFlow<Int> =
+        placeholderRepository.constrainedAvailableSpace.asStateFlow()
+
     /**
      * Whether the notification stack is scrolled to the top; i.e., it cannot be scrolled down any
      * further.
      */
     val scrolledToTop: StateFlow<Boolean> = placeholderRepository.scrolledToTop.asStateFlow()
 
+    /** The y-coordinate in px of bottom of the contents of the HUN. */
+    val headsUpTop: StateFlow<Float> = placeholderRepository.headsUpTop.asStateFlow()
+
     /**
      * The amount in px that the notification stack should scroll due to internal expansion. This
      * should only happen when a notification expansion hits the bottom of the screen, so it is
@@ -89,8 +102,8 @@
     val syntheticScroll: Flow<Float> = viewHeightRepository.syntheticScroll.asStateFlow()
 
     /** Sets the position of the notification stack in the current scene. */
-    fun setShadeScrimBounds(bounds: ShadeScrimBounds) {
-        check(bounds.top <= bounds.bottom) { "Invalid bounds: $bounds" }
+    fun setShadeScrimBounds(bounds: ShadeScrimBounds?) {
+        check(bounds == null || bounds.top <= bounds.bottom) { "Invalid bounds: $bounds" }
         placeholderRepository.shadeScrimBounds.value = bounds
     }
 
@@ -99,9 +112,19 @@
         viewHeightRepository.stackHeight.value = height
     }
 
+    /** Sets the height of heads up notification. */
+    fun setHeadsUpHeight(height: Float) {
+        viewHeightRepository.headsUpHeight.value = height
+    }
+
     /** Sets the y-coord in px of the top of the contents of the notification stack. */
-    fun setStackTop(startY: Float) {
-        placeholderRepository.stackTop.value = startY
+    fun setStackTop(stackTop: Float) {
+        placeholderRepository.stackTop.value = stackTop
+    }
+
+    /** Sets the y-coord in px of the bottom of the contents of the notification stack. */
+    fun setStackBottom(stackBottom: Float) {
+        placeholderRepository.stackBottom.value = stackBottom
     }
 
     /** Sets whether the notification stack is scrolled to the top. */
@@ -113,4 +136,12 @@
     fun setSyntheticScroll(delta: Float) {
         viewHeightRepository.syntheticScroll.value = delta
     }
+
+    fun setConstrainedAvailableSpace(height: Int) {
+        placeholderRepository.constrainedAvailableSpace.value = height
+    }
+
+    fun setHeadsUpTop(headsUpTop: Float) {
+        placeholderRepository.headsUpTop.value = headsUpTop
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimBounds.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimBounds.kt
index 448127a..832e690 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimBounds.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimBounds.kt
@@ -29,4 +29,16 @@
 ) {
     /** The current height of the notification container. */
     val height: Float = bottom - top
+
+    fun minus(leftOffset: Int = 0, topOffset: Int = 0) =
+        if (leftOffset == 0 && topOffset == 0) {
+            this
+        } else {
+            ShadeScrimBounds(
+                left = this.left - leftOffset,
+                top = this.top - topOffset,
+                right = this.right - leftOffset,
+                bottom = this.bottom - topOffset,
+            )
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimClipping.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimClipping.kt
index 621dd0c..e86fd1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimClipping.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimClipping.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.notification.stack.shared.model
 
-/** Models the clipping rounded rectangle of the notification stack */
+/** Models the clipping rounded rectangle of the notification stack, where the rounding is binary */
 data class ShadeScrimClipping(
     val bounds: ShadeScrimBounds = ShadeScrimBounds(),
     val rounding: ShadeScrimRounding = ShadeScrimRounding()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimRounding.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimRounding.kt
index 2fe265f..9d4231c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimRounding.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimRounding.kt
@@ -19,7 +19,7 @@
 /** Models the corner rounds of the notification stack. */
 data class ShadeScrimRounding(
     /** Whether the top corners of the notification stack should be rounded. */
-    val roundTop: Boolean = false,
+    val isTopRounded: Boolean = false,
     /** Whether the bottom corners of the notification stack should be rounded. */
-    val roundBottom: Boolean = false,
+    val isBottomRounded: Boolean = false,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimShape.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimShape.kt
new file mode 100644
index 0000000..e6f0647
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/model/ShadeScrimShape.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.shared.model
+
+/** Models the clipping rounded rectangle of the notification stack, with corner radii in px */
+data class ShadeScrimShape(
+    val bounds: ShadeScrimBounds = ShadeScrimBounds(),
+    /** radius in px of the top corners */
+    val topRadius: Int,
+    /** radius in px of the bottom corners */
+    val bottomRadius: Int,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
new file mode 100644
index 0000000..f356578ea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.ui.view
+
+import android.view.View
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
+import java.util.function.Consumer
+
+/**
+ * This view (interface) is the view which scrolls and positions the heads up notification and
+ * notification stack, but is otherwise agnostic to the content.
+ */
+interface NotificationScrollView {
+    /**
+     * Since this is an interface rather than a literal View, this provides cast-like access to the
+     * underlying view.
+     */
+    fun asView(): View
+
+    /** Set the clipping bounds used when drawing */
+    fun setScrimClippingShape(shape: ShadeScrimShape?)
+
+    /** set the y position in px of the top of the stack in this view's coordinates */
+    fun setStackTop(stackTop: Float)
+
+    /** set the y position in px of the bottom of the stack in this view's coordinates */
+    fun setStackBottom(stackBottom: Float)
+
+    /** set the y position in px of the top of the HUN in this view's coordinates */
+    fun setHeadsUpTop(headsUpTop: Float)
+
+    /** set whether the view has been scrolled all the way to the top */
+    fun setScrolledToTop(scrolledToTop: Boolean)
+
+    /** Set a consumer for synthetic scroll events */
+    fun setSyntheticScrollConsumer(consumer: Consumer<Float>?)
+    /** Set a consumer for stack height changed events */
+    fun setStackHeightConsumer(consumer: Consumer<Float>?)
+    /** Set a consumer for heads up height changed events */
+    fun setHeadsUpHeightConsumer(consumer: Consumer<Float>?)
+
+    /** sets that scrolling is allowed */
+    fun setScrollingEnabled(enabled: Boolean)
+
+    /** sets the current expand fraction */
+    fun setExpandFraction(expandFraction: Float)
+
+    /** Sets whether the view is displayed in doze mode. */
+    fun setDozing(dozing: Boolean)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
new file mode 100644
index 0000000..2f9c2f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.ui.viewbinder
+
+import android.util.Log
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.common.ui.ConfigurationState
+import com.android.systemui.common.ui.view.onLayoutChanged
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationScrollViewModel
+import com.android.systemui.util.kotlin.FlowDumperImpl
+import com.android.systemui.util.kotlin.launchAndDispose
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+
+/** Binds the [NotificationScrollView]. */
+@SysUISingleton
+class NotificationScrollViewBinder
+@Inject
+constructor(
+    dumpManager: DumpManager,
+    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
+    private val view: NotificationScrollView,
+    private val viewModel: NotificationScrollViewModel,
+    private val configuration: ConfigurationState,
+) : FlowDumperImpl(dumpManager) {
+
+    private val viewLeftOffset = MutableStateFlow(0).dumpValue("viewLeftOffset")
+
+    private fun updateViewPosition() {
+        val trueView = view.asView()
+        if (trueView.top != 0) {
+            Log.w("NSSL", "Expected $trueView to have top==0")
+        }
+        viewLeftOffset.value = trueView.left
+    }
+
+    fun bindWhileAttached(): DisposableHandle {
+        return view.asView().repeatWhenAttached(mainImmediateDispatcher) {
+            repeatOnLifecycle(Lifecycle.State.CREATED) { bind() }
+        }
+    }
+
+    suspend fun bind() = coroutineScope {
+        launchAndDispose {
+            updateViewPosition()
+            view.asView().onLayoutChanged { updateViewPosition() }
+        }
+
+        launch {
+            viewModel
+                .shadeScrimShape(cornerRadius = scrimRadius, viewLeftOffset = viewLeftOffset)
+                .collect { view.setScrimClippingShape(it) }
+        }
+
+        launch { viewModel.stackTop.collect { view.setStackTop(it) } }
+        launch { viewModel.stackBottom.collect { view.setStackBottom(it) } }
+        launch { viewModel.scrolledToTop.collect { view.setScrolledToTop(it) } }
+        launch { viewModel.headsUpTop.collect { view.setHeadsUpTop(it) } }
+        launch { viewModel.expandFraction.collect { view.setExpandFraction(it) } }
+        launch { viewModel.isScrollable.collect { view.setScrollingEnabled(it) } }
+        launch { viewModel.isDozing.collect { isDozing -> view.setDozing(isDozing) } }
+
+        launchAndDispose {
+            view.setSyntheticScrollConsumer(viewModel.syntheticScrollConsumer)
+            view.setStackHeightConsumer(viewModel.stackHeightConsumer)
+            view.setHeadsUpHeightConsumer(viewModel.headsUpHeightConsumer)
+            DisposableHandle {
+                view.setSyntheticScrollConsumer(null)
+                view.setStackHeightConsumer(null)
+                view.setHeadsUpHeightConsumer(null)
+            }
+        }
+    }
+
+    /** flow of the scrim clipping radius */
+    private val scrimRadius: Flow<Int>
+        get() = configuration.getDimensionPixelOffset(R.dimen.notification_scrim_corner_radius)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackViewBinder.kt
deleted file mode 100644
index d6d31db..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackViewBinder.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.stack.ui.viewbinder
-
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.systemui.common.ui.ConfigurationState
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.notification.stack.AmbientState
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
-import javax.inject.Inject
-import kotlin.math.roundToInt
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.launch
-
-/** Binds the NSSL/Controller/AmbientState to their ViewModel. */
-@SysUISingleton
-class NotificationStackViewBinder
-@Inject
-constructor(
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
-    private val ambientState: AmbientState,
-    private val view: NotificationStackScrollLayout,
-    private val controller: NotificationStackScrollLayoutController,
-    private val viewModel: NotificationStackAppearanceViewModel,
-    private val configuration: ConfigurationState,
-) {
-
-    fun bindWhileAttached(): DisposableHandle {
-        return view.repeatWhenAttached(mainImmediateDispatcher) {
-            repeatOnLifecycle(Lifecycle.State.CREATED) { bind() }
-        }
-    }
-
-    suspend fun bind() = coroutineScope {
-        launch {
-            combine(viewModel.shadeScrimClipping, clipRadius, ::Pair).collect {
-                (clipping, clipRadius) ->
-                val (bounds, rounding) = clipping
-                val viewLeft = controller.view.left
-                val viewTop = controller.view.top
-                controller.setRoundedClippingBounds(
-                    bounds.left.roundToInt() - viewLeft,
-                    bounds.top.roundToInt() - viewTop,
-                    bounds.right.roundToInt() - viewLeft,
-                    bounds.bottom.roundToInt() - viewTop,
-                    if (rounding.roundTop) clipRadius else 0,
-                    if (rounding.roundBottom) clipRadius else 0,
-                )
-            }
-        }
-
-        launch {
-            viewModel.stackTop.collect {
-                controller.updateTopPadding(it, controller.isAddOrRemoveAnimationPending)
-            }
-        }
-
-        launch {
-            var wasExpanding = false
-            viewModel.expandFraction.collect { expandFraction ->
-                val nowExpanding = expandFraction != 0f && expandFraction != 1f
-                if (nowExpanding && !wasExpanding) {
-                    controller.onExpansionStarted()
-                }
-                ambientState.expansionFraction = expandFraction
-                controller.expandedHeight = expandFraction * controller.view.height
-                if (!nowExpanding && wasExpanding) {
-                    controller.onExpansionStopped()
-                }
-                wasExpanding = nowExpanding
-            }
-        }
-
-        launch { viewModel.isScrollable.collect { controller.setScrollingEnabled(it) } }
-    }
-
-    private val clipRadius: Flow<Int>
-        get() = configuration.getDimensionPixelOffset(R.dimen.notification_scrim_corner_radius)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index 4a096a8..cf5366b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -21,12 +21,14 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.Flags.communalHub
+import com.android.systemui.common.ui.view.onApplyWindowInsets
+import com.android.systemui.common.ui.view.onLayoutChanged
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
 import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
@@ -46,10 +48,9 @@
 class SharedNotificationContainerBinder
 @Inject
 constructor(
-    private val sceneContainerFlags: SceneContainerFlags,
     private val controller: NotificationStackScrollLayoutController,
     private val notificationStackSizeCalculator: NotificationStackSizeCalculator,
-    private val notificationStackViewBinder: NotificationStackViewBinder,
+    private val notificationScrollViewBinder: NotificationScrollViewBinder,
     @Main private val mainImmediateDispatcher: CoroutineDispatcher,
 ) {
 
@@ -127,7 +128,7 @@
                             .collect { controller.setMaxDisplayedNotifications(it) }
                     }
 
-                    if (!sceneContainerFlags.isEnabled()) {
+                    if (!SceneContainerFlag.isEnabled) {
                         launch {
                             viewModel.bounds.collect {
                                 val animate =
@@ -137,10 +138,12 @@
                         }
                     }
 
-                    launch {
-                        burnInParams
-                            .flatMapLatest { params -> viewModel.translationY(params) }
-                            .collect { y -> controller.setTranslationY(y) }
+                    if (!SceneContainerFlag.isEnabled) {
+                        launch {
+                            burnInParams
+                                .flatMapLatest { params -> viewModel.translationY(params) }
+                                .collect { y -> controller.setTranslationY(y) }
+                        }
                     }
 
                     launch { viewModel.translationX.collect { x -> controller.translationX = x } }
@@ -161,29 +164,23 @@
                 }
             }
 
-        if (sceneContainerFlags.isEnabled()) {
-            disposables += notificationStackViewBinder.bindWhileAttached()
+        if (SceneContainerFlag.isEnabled) {
+            disposables += notificationScrollViewBinder.bindWhileAttached()
         }
 
         controller.setOnHeightChangedRunnable { viewModel.notificationStackChanged() }
         disposables += DisposableHandle { controller.setOnHeightChangedRunnable(null) }
 
-        view.setOnApplyWindowInsetsListener { v: View, insets: WindowInsets ->
-            val insetTypes = WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout()
-            burnInParams.update { current ->
-                current.copy(topInset = insets.getInsetsIgnoringVisibility(insetTypes).top)
+        disposables +=
+            view.onApplyWindowInsets { _: View, insets: WindowInsets ->
+                val insetTypes = WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout()
+                burnInParams.update { current ->
+                    current.copy(topInset = insets.getInsetsIgnoringVisibility(insetTypes).top)
+                }
+                insets
             }
-            insets
-        }
-        disposables += DisposableHandle { view.setOnApplyWindowInsetsListener(null) }
 
-        // Required to capture keyguard media changes and ensure the notification count is correct
-        val layoutChangeListener =
-            View.OnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
-                viewModel.notificationStackChanged()
-            }
-        view.addOnLayoutChangeListener(layoutChangeListener)
-        disposables += DisposableHandle { view.removeOnLayoutChangeListener(layoutChangeListener) }
+        disposables += view.onLayoutChanged { viewModel.notificationStackChanged() }
 
         return disposables
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
index 5ab5857..3a89630 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.domain.interactor.RemoteInputInteractor
@@ -31,6 +32,7 @@
 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.UserSetupInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
+import com.android.systemui.util.kotlin.FlowDumperImpl
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.ui.AnimatableEvent
 import com.android.systemui.util.ui.AnimatedValue
@@ -64,7 +66,8 @@
     userSetupInteractor: UserSetupInteractor,
     zenModeInteractor: ZenModeInteractor,
     @Background bgDispatcher: CoroutineDispatcher,
-) {
+    dumpManager: DumpManager,
+) : FlowDumperImpl(dumpManager) {
     /**
      * We want the NSSL to be unimportant for accessibility when there are no notifications in it
      * while the device is on lock screen, to avoid an unlabelled NSSL view in TalkBack. Otherwise,
@@ -81,8 +84,9 @@
                 ) { hasNotifications, isShowingOnLockscreen ->
                     hasNotifications || !isShowingOnLockscreen
                 }
-                .flowOn(bgDispatcher)
                 .distinctUntilChanged()
+                .dumpWhileCollecting("isImportantForAccessibility")
+                .flowOn(bgDispatcher)
         }
     }
 
@@ -105,8 +109,9 @@
                         else -> true
                     }
                 }
-                .flowOn(bgDispatcher)
                 .distinctUntilChanged()
+                .dumpWhileCollecting("shouldShowEmptyShadeView")
+                .flowOn(bgDispatcher)
         }
     }
 
@@ -125,8 +130,9 @@
             // the footer to be counted as part of the shade for measurements.
             shadeInteractor.shadeExpansion
                 .map { it == 0f }
-                .flowOn(bgDispatcher)
                 .distinctUntilChanged()
+                .dumpWhileCollecting("shouldHideFooterView")
+                .flowOn(bgDispatcher)
         }
     }
 
@@ -173,7 +179,6 @@
                         else -> VisibilityChange.APPEAR_WITH_ANIMATION
                     }
                 }
-                .flowOn(bgDispatcher)
                 .distinctUntilChanged(
                     // Equivalent unless visibility changes
                     areEquivalent = { a: VisibilityChange, b: VisibilityChange ->
@@ -199,6 +204,8 @@
                     AnimatableEvent(visibilityChange.visible, shouldAnimate)
                 }
                 .toAnimatedValueFlow()
+                .dumpWhileCollecting("shouldIncludeFooterView")
+                .flowOn(bgDispatcher)
         }
     }
 
@@ -213,7 +220,9 @@
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(false)
         } else {
-            zenModeInteractor.areNotificationsHiddenInShade
+            zenModeInteractor.areNotificationsHiddenInShade.dumpWhileCollecting(
+                "areNotificationsHiddenInShade"
+            )
         }
     }
 
@@ -222,7 +231,9 @@
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(false)
         } else {
-            seenNotificationsInteractor.hasFilteredOutSeenNotifications
+            seenNotificationsInteractor.hasFilteredOutSeenNotifications.dumpWhileCollecting(
+                "hasFilteredOutSeenNotifications"
+            )
         }
     }
 
@@ -230,7 +241,9 @@
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(false)
         } else {
-            activeNotificationsInteractor.hasClearableAlertingNotifications
+            activeNotificationsInteractor.hasClearableAlertingNotifications.dumpWhileCollecting(
+                "hasClearableAlertingNotifications"
+            )
         }
     }
 
@@ -238,7 +251,9 @@
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(false)
         } else {
-            activeNotificationsInteractor.hasNonClearableSilentNotifications
+            activeNotificationsInteractor.hasNonClearableSilentNotifications.dumpWhileCollecting(
+                "hasNonClearableSilentNotifications"
+            )
         }
     }
 
@@ -246,7 +261,7 @@
         if (NotificationsHeadsUpRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(null)
         } else {
-            headsUpNotificationInteractor.topHeadsUpRow
+            headsUpNotificationInteractor.topHeadsUpRow.dumpWhileCollecting("topHeadsUpRow")
         }
     }
 
@@ -254,15 +269,20 @@
         if (NotificationsHeadsUpRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(emptySet())
         } else {
-            headsUpNotificationInteractor.pinnedHeadsUpRows
+            headsUpNotificationInteractor.pinnedHeadsUpRows.dumpWhileCollecting("pinnedHeadsUpRows")
         }
     }
 
     val headsUpAnimationsEnabled: Flow<Boolean> by lazy {
-        combine(keyguardInteractor.isKeyguardShowing, shadeInteractor.isShadeFullyExpanded) {
-            (isKeyguardShowing, isShadeFullyExpanded) ->
-            // TODO(b/325936094) use isShadeFullyCollapsed instead
-            !isKeyguardShowing && !isShadeFullyExpanded
+        if (NotificationsHeadsUpRefactor.isUnexpectedlyInLegacyMode()) {
+            flowOf(false)
+        } else {
+            combine(keyguardInteractor.isKeyguardShowing, shadeInteractor.isShadeFullyExpanded) {
+                    (isKeyguardShowing, isShadeFullyExpanded) ->
+                    // TODO(b/325936094) use isShadeFullyCollapsed instead
+                    !isKeyguardShowing && !isShadeFullyExpanded
+                }
+                .dumpWhileCollecting("headsUpAnimationsEnabled")
         }
     }
 
@@ -270,7 +290,7 @@
         if (NotificationsHeadsUpRefactor.isUnexpectedlyInLegacyMode()) {
             flowOf(false)
         } else {
-            headsUpNotificationInteractor.hasPinnedRows
+            headsUpNotificationInteractor.hasPinnedRows.dumpWhileCollecting("hasPinnedHeadsUpRow")
         }
     }
 
@@ -279,4 +299,8 @@
         HeadsUpRowViewModel(headsUpNotificationInteractor.headsUpRow(key))
 
     fun elementKeyFor(key: HeadsUpRowKey): Any = headsUpNotificationInteractor.elementKeyFor(key)
+
+    fun setHeadsUpAnimatingAway(animatingAway: Boolean) {
+        headsUpNotificationInteractor.setHeadsUpAnimatingAway(animatingAway)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
new file mode 100644
index 0000000..7aeff71
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.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.statusbar.notification.stack.ui.viewmodel
+
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimClipping
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_DELAYED_STACK_FADE_IN
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
+import com.android.systemui.util.kotlin.FlowDumperImpl
+import dagger.Lazy
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import javax.inject.Inject
+
+/** ViewModel which represents the state of the NSSL/Controller in the world of flexiglass */
+@SysUISingleton
+class NotificationScrollViewModel
+@Inject
+constructor(
+    dumpManager: DumpManager,
+    stackAppearanceInteractor: NotificationStackAppearanceInteractor,
+    shadeInteractor: ShadeInteractor,
+    sceneInteractor: SceneInteractor,
+    // TODO(b/336364825) Remove Lazy when SceneContainerFlag is released -
+    // while the flag is off, creating this object too early results in a crash
+    keyguardInteractor: Lazy<KeyguardInteractor>,
+) : FlowDumperImpl(dumpManager) {
+    /**
+     * The expansion fraction of the notification stack. It should go from 0 to 1 when transitioning
+     * from Gone to Shade scenes, and remain at 1 when in Lockscreen or Shade scenes and while
+     * transitioning from Shade to QuickSettings scenes.
+     */
+    val expandFraction: Flow<Float> =
+        combine(
+                shadeInteractor.shadeExpansion,
+                shadeInteractor.qsExpansion,
+                sceneInteractor.transitionState,
+            ) { shadeExpansion, qsExpansion, transitionState ->
+                when (transitionState) {
+                    is ObservableTransitionState.Idle -> {
+                        if (transitionState.scene == Scenes.Lockscreen) {
+                            1f
+                        } else {
+                            shadeExpansion
+                        }
+                    }
+                    is ObservableTransitionState.Transition -> {
+                        if (
+                            (transitionState.fromScene == Scenes.Shade &&
+                                transitionState.toScene == Scenes.QuickSettings) ||
+                                (transitionState.fromScene == Scenes.QuickSettings &&
+                                    transitionState.toScene == Scenes.Shade)
+                        ) {
+                            1f
+                        } else if (
+                            (transitionState.fromScene == Scenes.Gone ||
+                                transitionState.fromScene == Scenes.Lockscreen) &&
+                                transitionState.toScene == Scenes.QuickSettings
+                        ) {
+                            // during QS expansion, increase fraction at same rate as scrim alpha,
+                            // but start when scrim alpha is at EXPANSION_FOR_DELAYED_STACK_FADE_IN.
+                            (qsExpansion / EXPANSION_FOR_MAX_SCRIM_ALPHA -
+                                    EXPANSION_FOR_DELAYED_STACK_FADE_IN)
+                                .coerceIn(0f, 1f)
+                        } else {
+                            shadeExpansion
+                        }
+                    }
+                }
+            }
+            .distinctUntilChanged()
+            .dumpWhileCollecting("expandFraction")
+
+    /** The bounds of the notification stack in the current scene. */
+    private val shadeScrimClipping: Flow<ShadeScrimClipping?> =
+        combine(
+                stackAppearanceInteractor.shadeScrimBounds,
+                stackAppearanceInteractor.shadeScrimRounding,
+            ) { bounds, rounding ->
+                bounds?.let { ShadeScrimClipping(it, rounding) }
+            }
+            .dumpWhileCollecting("stackClipping")
+
+    fun shadeScrimShape(
+        cornerRadius: Flow<Int>,
+        viewLeftOffset: Flow<Int>
+    ): Flow<ShadeScrimShape?> =
+        combine(shadeScrimClipping, cornerRadius, viewLeftOffset) { clipping, radius, leftOffset ->
+                if (clipping == null) return@combine null
+                ShadeScrimShape(
+                    bounds = clipping.bounds.minus(leftOffset = leftOffset),
+                    topRadius = radius.takeIf { clipping.rounding.isTopRounded } ?: 0,
+                    bottomRadius = radius.takeIf { clipping.rounding.isBottomRounded } ?: 0
+                )
+            }
+            .dumpWhileCollecting("shadeScrimShape")
+
+    /** The y-coordinate in px of top of the contents of the notification stack. */
+    val stackTop: Flow<Float> = stackAppearanceInteractor.stackTop.dumpValue("stackTop")
+    /** The y-coordinate in px of bottom of the contents of the notification stack. */
+    val stackBottom: Flow<Float> = stackAppearanceInteractor.stackBottom.dumpValue("stackBottom")
+    /**
+     * Whether the notification stack is scrolled to the top; i.e., it cannot be scrolled down any
+     * further.
+     */
+    val scrolledToTop: Flow<Boolean> =
+        stackAppearanceInteractor.scrolledToTop.dumpValue("scrolledToTop")
+    /** The y-coordinate in px of bottom of the contents of the HUN. */
+    val headsUpTop: Flow<Float> = stackAppearanceInteractor.headsUpTop.dumpValue("headsUpTop")
+
+    /** Receives the amount (px) that the stack should scroll due to internal expansion. */
+    val syntheticScrollConsumer: (Float) -> Unit = stackAppearanceInteractor::setSyntheticScroll
+    /** Receives the height of the contents of the notification stack. */
+    val stackHeightConsumer: (Float) -> Unit = stackAppearanceInteractor::setStackHeight
+    /** Receives the height of the heads up notification. */
+    val headsUpHeightConsumer: (Float) -> Unit = stackAppearanceInteractor::setHeadsUpHeight
+
+    /** Whether the notification stack is scrollable or not. */
+    val isScrollable: Flow<Boolean> =
+        sceneInteractor.currentScene.map { it == Scenes.Shade }.dumpWhileCollecting("isScrollable")
+
+    /** Whether the notification stack is displayed in doze mode. */
+    val isDozing: Flow<Boolean> by lazy {
+        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+            flowOf(false)
+        } else {
+            keyguardInteractor.get().isDozing.dumpWhileCollecting("isDozing")
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
deleted file mode 100644
index 071127c..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.statusbar.notification.stack.ui.viewmodel
-
-import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.shared.model.Scenes.Shade
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
-import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimClipping
-import com.android.systemui.util.kotlin.FlowDumperImpl
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
-
-/** ViewModel which represents the state of the NSSL/Controller in the world of flexiglass */
-@SysUISingleton
-class NotificationStackAppearanceViewModel
-@Inject
-constructor(
-    dumpManager: DumpManager,
-    stackAppearanceInteractor: NotificationStackAppearanceInteractor,
-    shadeInteractor: ShadeInteractor,
-    sceneInteractor: SceneInteractor,
-) : FlowDumperImpl(dumpManager) {
-    /**
-     * The expansion fraction of the notification stack. It should go from 0 to 1 when transitioning
-     * from Gone to Shade scenes, and remain at 1 when in Lockscreen or Shade scenes and while
-     * transitioning from Shade to QuickSettings scenes.
-     */
-    val expandFraction: Flow<Float> =
-        combine(
-                shadeInteractor.shadeExpansion,
-                sceneInteractor.transitionState,
-            ) { shadeExpansion, transitionState ->
-                when (transitionState) {
-                    is ObservableTransitionState.Idle -> {
-                        if (transitionState.scene == Scenes.Lockscreen) {
-                            1f
-                        } else {
-                            shadeExpansion
-                        }
-                    }
-                    is ObservableTransitionState.Transition -> {
-                        if (
-                            (transitionState.fromScene == Scenes.Shade &&
-                                transitionState.toScene == Scenes.QuickSettings) ||
-                                (transitionState.fromScene == Scenes.QuickSettings &&
-                                    transitionState.toScene == Scenes.Shade)
-                        ) {
-                            1f
-                        } else {
-                            shadeExpansion
-                        }
-                    }
-                }
-            }
-            .distinctUntilChanged()
-            .dumpWhileCollecting("expandFraction")
-
-    /** The bounds of the notification stack in the current scene. */
-    val shadeScrimClipping: Flow<ShadeScrimClipping> =
-        combine(
-                stackAppearanceInteractor.shadeScrimBounds,
-                stackAppearanceInteractor.shadeScrimRounding,
-                ::ShadeScrimClipping
-            )
-            .dumpWhileCollecting("stackClipping")
-
-    /** The y-coordinate in px of top of the contents of the notification stack. */
-    val stackTop: StateFlow<Float> = stackAppearanceInteractor.stackTop.dumpValue("stackTop")
-
-    /** Whether the notification stack is scrollable or not. */
-    val isScrollable: Flow<Boolean> =
-        sceneInteractor.currentScene.map { it == Shade }.dumpWhileCollecting("isScrollable")
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
index 477f139..bf3b2c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
@@ -18,16 +18,19 @@
 
 import com.android.systemui.common.shared.model.NotificationContainerBounds
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
 import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding
+import com.android.systemui.util.kotlin.FlowDumperImpl
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
 
 /**
  * ViewModel used by the Notification placeholders inside the scene container to update the
@@ -37,70 +40,82 @@
 class NotificationsPlaceholderViewModel
 @Inject
 constructor(
+    dumpManager: DumpManager,
     private val interactor: NotificationStackAppearanceInteractor,
     shadeInteractor: ShadeInteractor,
-    flags: SceneContainerFlags,
     featureFlags: FeatureFlagsClassic,
     private val keyguardInteractor: KeyguardInteractor,
-) {
+) : FlowDumperImpl(dumpManager) {
     /** DEBUG: whether the placeholder should be made slightly visible for positional debugging. */
     val isVisualDebuggingEnabled: Boolean = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES)
 
     /** DEBUG: whether the debug logging should be output. */
-    val isDebugLoggingEnabled: Boolean = flags.isEnabled()
+    val isDebugLoggingEnabled: Boolean = SceneContainerFlag.isEnabled
 
-    /**
-     * Notifies that the bounds of the notification placeholder have changed.
-     *
-     * @param top The position of the top of the container in its window coordinate system, in
-     *   pixels.
-     * @param bottom The position of the bottom of the container in its window coordinate system, in
-     *   pixels.
-     */
-    fun onBoundsChanged(
-        left: Float,
+    /** Notifies that the bounds of the notification scrim have changed. */
+    fun onScrimBoundsChanged(bounds: ShadeScrimBounds?) {
+        interactor.setShadeScrimBounds(bounds)
+    }
+
+    /** Notifies that the bounds of the notification placeholder have changed. */
+    fun onStackBoundsChanged(
         top: Float,
-        right: Float,
         bottom: Float,
     ) {
         keyguardInteractor.setNotificationContainerBounds(
             NotificationContainerBounds(top = top, bottom = bottom)
         )
-        interactor.setShadeScrimBounds(
-            ShadeScrimBounds(top = top, bottom = bottom, left = left, right = right)
-        )
+        interactor.setStackTop(top)
+        interactor.setStackBottom(bottom)
+    }
+
+    /** Sets the available space */
+    fun onConstrainedAvailableSpaceChanged(height: Int) {
+        interactor.setConstrainedAvailableSpace(height)
+    }
+
+    fun onHeadsUpTopChanged(headsUpTop: Float) {
+        interactor.setHeadsUpTop(headsUpTop)
     }
 
     /** Corner rounding of the stack */
-    val shadeScrimRounding: Flow<ShadeScrimRounding> = interactor.shadeScrimRounding
+    val shadeScrimRounding: Flow<ShadeScrimRounding> =
+        interactor.shadeScrimRounding.dumpWhileCollecting("shadeScrimRounding")
 
     /**
      * The height in px of the contents of notification stack. Depending on the number of
      * notifications, this can exceed the space available on screen to show notifications, at which
      * point the notification stack should become scrollable.
      */
-    val stackHeight = interactor.stackHeight
+    val stackHeight: StateFlow<Float> = interactor.stackHeight.dumpValue("stackHeight")
+
+    /** The height in px of the contents of the HUN. */
+    val headsUpHeight: StateFlow<Float> = interactor.headsUpHeight.dumpValue("headsUpHeight")
 
     /**
-     * The amount [0-1] that the shade has been opened. At 0, the shade is closed; at 1, the shade
-     * is open.
+     * The amount [0-1] that the shade or quick settings has been opened. At 0, the shade is closed;
+     * at 1, either the shade or quick settings is open.
      */
-    val expandFraction: Flow<Float> = shadeInteractor.shadeExpansion
+    val expandFraction: Flow<Float> = shadeInteractor.anyExpansion.dumpValue("expandFraction")
 
     /**
      * The amount in px that the notification stack should scroll due to internal expansion. This
      * should only happen when a notification expansion hits the bottom of the screen, so it is
      * necessary to scroll up to keep expanding the notification.
      */
-    val syntheticScroll: Flow<Float> = interactor.syntheticScroll
-
-    /** Sets the y-coord in px of the top of the contents of the notification stack. */
-    fun onContentTopChanged(padding: Float) {
-        interactor.setStackTop(padding)
-    }
+    val syntheticScroll: Flow<Float> =
+        interactor.syntheticScroll.dumpWhileCollecting("syntheticScroll")
 
     /** Sets whether the notification stack is scrolled to the top. */
     fun setScrolledToTop(scrolledToTop: Boolean) {
         interactor.setScrolledToTop(scrolledToTop)
     }
 }
+
+// Expansion fraction thresholds (between 0-1f) at which the corresponding value should be
+// at its maximum, given they are at their minimum value at expansion = 0f.
+object NotificationTransitionThresholds {
+    const val EXPANSION_FOR_MAX_CORNER_RADIUS = 0.1f
+    const val EXPANSION_FOR_MAX_SCRIM_ALPHA = 0.3f
+    const val EXPANSION_FOR_DELAYED_STACK_FADE_IN = 0.5f
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 9f57606..37bbbd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -19,6 +19,7 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
+import androidx.annotation.VisibleForTesting
 import com.android.systemui.common.shared.model.NotificationContainerBounds
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -56,12 +57,16 @@
 import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.LockscreenToPrimaryBouncerTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.OccludedToAodTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToGoneTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
 import com.android.systemui.util.kotlin.BooleanFlowOperators.and
 import com.android.systemui.util.kotlin.BooleanFlowOperators.or
 import com.android.systemui.util.kotlin.FlowDumperImpl
@@ -76,6 +81,7 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.combineTransform
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flow
@@ -97,6 +103,7 @@
     private val keyguardInteractor: KeyguardInteractor,
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val shadeInteractor: ShadeInteractor,
+    private val notificationStackAppearanceInteractor: NotificationStackAppearanceInteractor,
     private val alternateBouncerToGoneTransitionViewModel:
         AlternateBouncerToGoneTransitionViewModel,
     private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
@@ -117,11 +124,13 @@
         LockscreenToPrimaryBouncerTransitionViewModel,
     private val lockscreenToOccludedTransitionViewModel: LockscreenToOccludedTransitionViewModel,
     private val occludedToAodTransitionViewModel: OccludedToAodTransitionViewModel,
+    private val occludedToGoneTransitionViewModel: OccludedToGoneTransitionViewModel,
     private val occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
     private val primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
     private val primaryBouncerToLockscreenTransitionViewModel:
         PrimaryBouncerToLockscreenTransitionViewModel,
     private val aodBurnInViewModel: AodBurnInViewModel,
+    unfoldTransitionInteractor: UnfoldTransitionInteractor,
 ) : FlowDumperImpl(dumpManager) {
     private val statesForConstrainedNotifications: Set<KeyguardState> =
         setOf(AOD, LOCKSCREEN, DOZING, ALTERNATE_BOUNCER, PRIMARY_BOUNCER)
@@ -163,23 +172,35 @@
             )
             .dumpWhileCollecting("isShadeLocked")
 
+    @VisibleForTesting
+    val paddingTopDimen: Flow<Int> =
+        interactor.configurationBasedDimensions
+            .map {
+                when {
+                    !it.useSplitShade -> 0
+                    it.useLargeScreenHeader -> it.marginTopLargeScreen
+                    else -> it.marginTop
+                }
+            }
+            .distinctUntilChanged()
+            .dumpWhileCollecting("paddingTopDimen")
+
     val configurationBasedDimensions: Flow<ConfigurationBasedDimensions> =
         interactor.configurationBasedDimensions
             .map {
                 val marginTop =
-                    if (it.useLargeScreenHeader) it.marginTopLargeScreen else it.marginTop
+                    when {
+                        // y position of the NSSL in the window needs to be 0 under scene container
+                        SceneContainerFlag.isEnabled -> 0
+                        it.useLargeScreenHeader -> it.marginTopLargeScreen
+                        else -> it.marginTop
+                    }
                 ConfigurationBasedDimensions(
                     marginStart = if (it.useSplitShade) 0 else it.marginHorizontal,
                     marginEnd = it.marginHorizontal,
                     marginBottom = it.marginBottom,
                     marginTop = marginTop,
                     useSplitShade = it.useSplitShade,
-                    paddingTop =
-                        if (it.useSplitShade) {
-                            marginTop
-                        } else {
-                            0
-                        },
                 )
             }
             .distinctUntilChanged()
@@ -191,9 +212,7 @@
                 keyguardTransitionInteractor.finishedKeyguardState.map {
                     statesForConstrainedNotifications.contains(it)
                 },
-                keyguardTransitionInteractor
-                    .isInTransitionWhere { from, to -> from == LOCKSCREEN || to == LOCKSCREEN }
-                    .onStart { emit(false) }
+                keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f },
             ) { constrainedNotificationState, transitioningToOrFromLockscreen ->
                 constrainedNotificationState || transitioningToOrFromLockscreen
             }
@@ -225,11 +244,10 @@
                 keyguardTransitionInteractor.finishedKeyguardState.map { state ->
                     state == GLANCEABLE_HUB
                 },
-                keyguardTransitionInteractor
-                    .isInTransitionWhere { from, to ->
-                        from == GLANCEABLE_HUB || to == GLANCEABLE_HUB
-                    }
-                    .onStart { emit(false) }
+                or(
+                    keyguardTransitionInteractor.isInTransitionToState(GLANCEABLE_HUB),
+                    keyguardTransitionInteractor.isInTransitionFromState(GLANCEABLE_HUB),
+                ),
             ) { isOnGlanceableHub, transitioningToOrFromHub ->
                 isOnGlanceableHub || transitioningToOrFromHub
             }
@@ -274,12 +292,10 @@
         var aodTransitionIsComplete = true
         return combine(
                 isOnLockscreenWithoutShade,
-                keyguardTransitionInteractor
-                    .isInTransitionWhere(
-                        fromStatePredicate = { it == LOCKSCREEN },
-                        toStatePredicate = { it == AOD }
-                    )
-                    .onStart { emit(false) },
+                keyguardTransitionInteractor.isInTransition(
+                    from = LOCKSCREEN,
+                    to = AOD,
+                ),
                 ::Pair
             )
             .transformWhile { (isOnLockscreenWithoutShade, aodTransitionIsRunning) ->
@@ -334,20 +350,21 @@
      *
      * When the shade is expanding, the position is controlled by... the shade.
      */
-    val bounds: StateFlow<NotificationContainerBounds> =
+    val bounds: StateFlow<NotificationContainerBounds> by lazy {
+        SceneContainerFlag.assertInLegacyMode()
         combine(
                 isOnLockscreenWithoutShade,
                 keyguardInteractor.notificationContainerBounds,
-                configurationBasedDimensions,
+                paddingTopDimen,
                 interactor.topPosition
                     .sampleCombine(
                         keyguardTransitionInteractor.isInTransitionToAnyState,
                         shadeInteractor.qsExpansion,
                     )
                     .onStart { emit(Triple(0f, false, 0f)) }
-            ) { onLockscreen, bounds, config, (top, isInTransitionToAnyState, qsExpansion) ->
+            ) { onLockscreen, bounds, paddingTop, (top, isInTransitionToAnyState, qsExpansion) ->
                 if (onLockscreen) {
-                    bounds.copy(top = bounds.top - config.paddingTop)
+                    bounds.copy(top = bounds.top - paddingTop)
                 } else {
                     // When QS expansion > 0, it should directly set the top padding so do not
                     // animate it
@@ -364,6 +381,7 @@
                 initialValue = NotificationContainerBounds(),
             )
             .dumpValue("bounds")
+    }
 
     /**
      * Ensure view is visible when the shade/qs are expanded. Also, as QS is expanding, fade out
@@ -459,6 +477,7 @@
                 lockscreenToOccludedTransitionViewModel.lockscreenAlpha,
                 lockscreenToPrimaryBouncerTransitionViewModel.lockscreenAlpha,
                 occludedToAodTransitionViewModel.lockscreenAlpha,
+                occludedToGoneTransitionViewModel.notificationAlpha(viewState),
                 occludedToLockscreenTransitionViewModel.lockscreenAlpha,
                 primaryBouncerToGoneTransitionViewModel.notificationAlpha,
                 primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha,
@@ -539,6 +558,8 @@
      * translated as the keyguard fades out.
      */
     fun translationY(params: BurnInParameters): Flow<Float> {
+        // with SceneContainer, x translation is handled by views, y is handled by compose
+        SceneContainerFlag.assertInLegacyMode()
         return combine(
                 aodBurnInViewModel
                     .movement(params)
@@ -559,20 +580,29 @@
             .dumpWhileCollecting("translationY")
     }
 
-    /**
-     * The container may need to be translated in the x direction as the keyguard fades out, such as
-     * when swiping open the glanceable hub from the lockscreen.
-     */
+    /** Horizontal translation to apply to the container. */
     val translationX: Flow<Float> =
         merge(
+                // The container may need to be translated along the X axis as the keyguard fades
+                // out, such as when swiping open the glanceable hub from the lockscreen.
                 lockscreenToGlanceableHubTransitionViewModel.notificationTranslationX,
                 glanceableHubToLockscreenTransitionViewModel.notificationTranslationX,
+                if (SceneContainerFlag.isEnabled) {
+                    // The container may need to be translated along the X axis as the unfolded
+                    // foldable is folded slightly.
+                    unfoldTransitionInteractor.unfoldTranslationX(isOnStartSide = false)
+                } else {
+                    emptyFlow()
+                }
             )
             .dumpWhileCollecting("translationX")
 
     private val availableHeight: Flow<Float> =
-        bounds
-            .map { it.bottom - it.top }
+        if (SceneContainerFlag.isEnabled) {
+                notificationStackAppearanceInteractor.constrainedAvailableSpace.map { it.toFloat() }
+            } else {
+                bounds.map { it.bottom - it.top }
+            }
             .distinctUntilChanged()
             .dumpWhileCollecting("availableHeight")
 
@@ -634,6 +664,5 @@
         val marginEnd: Int,
         val marginBottom: Int,
         val useSplitShade: Boolean,
-        val paddingTop: Int,
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt
index cb360fe..52cb48b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt
@@ -16,19 +16,18 @@
 
 package com.android.systemui.statusbar.notification.ui.viewbinder
 
-import android.util.Log
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.shared.HeadsUpRowKey
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel
 import com.android.systemui.util.kotlin.sample
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
 import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.launch
 
-private const val TAG = "HunBinder"
-private val DEBUG = true // Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG)
-
 class HeadsUpNotificationViewBinder
 @Inject
 constructor(private val viewModel: NotificationListViewModel) {
@@ -39,10 +38,6 @@
                 viewModel.pinnedHeadsUpRows
                     .sample(viewModel.headsUpAnimationsEnabled, ::Pair)
                     .collect { (newKeys, animationsEnabled) ->
-                        if (DEBUG) {
-                            Log.d(TAG, "update:$newKeys")
-                        }
-
                         val added = newKeys - previousKeys
                         val removed = previousKeys - newKeys
                         previousKeys = newKeys
@@ -70,9 +65,18 @@
             launch {
                 viewModel.hasPinnedHeadsUpRow.collect { parentView.setInHeadsUpPinnedMode(it) }
             }
+            launch {
+                parentView.isHeadsUpAnimatingAway.collect { viewModel.setHeadsUpAnimatingAway(it) }
+            }
         }
 
     private fun obtainView(key: HeadsUpRowKey): ExpandableNotificationRow {
         return viewModel.elementKeyFor(key) as ExpandableNotificationRow
     }
 }
+
+private val NotificationStackScrollLayout.isHeadsUpAnimatingAway: Flow<Boolean>
+    get() = conflatedCallbackFlow {
+        setHeadsUpAnimatingAwayListener { animatingAway -> trySend(animatingAway) }
+        awaitClose { setHeadsUpAnimatingAwayListener(null) }
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
index 37646ae..6546db9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
@@ -14,51 +14,19 @@
 
 package com.android.systemui.statusbar.phone
 
-import android.app.ActivityManager
-import android.app.ActivityOptions
-import android.app.ActivityTaskManager
 import android.app.PendingIntent
-import android.app.TaskStackBuilder
-import android.content.Context
 import android.content.Intent
 import android.os.Bundle
-import android.os.RemoteException
 import android.os.UserHandle
-import android.provider.Settings
-import android.util.Log
-import android.view.RemoteAnimationAdapter
 import android.view.View
-import android.view.WindowManager
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.ActivityIntentHelper
 import com.android.systemui.animation.ActivityTransitionAnimator
-import com.android.systemui.animation.ActivityTransitionAnimator.PendingIntentStarter
-import com.android.systemui.animation.DelegateTransitionAnimatorController
-import com.android.systemui.assist.AssistManager
-import com.android.systemui.camera.CameraIntents.Companion.isInsecureCameraIntent
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.DisplayId
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.KeyguardViewMediator
-import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction
-import com.android.systemui.res.R
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.shade.ShadeController
-import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor
-import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.NotificationLockscreenUserManager
-import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.statusbar.window.StatusBarWindowController
 import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.kotlin.getOrNull
 import dagger.Lazy
-import java.util.Optional
 import javax.inject.Inject
 
 /** Handles start activity logic in SystemUI. */
@@ -66,38 +34,12 @@
 class ActivityStarterImpl
 @Inject
 constructor(
-    private val centralSurfacesOptLazy: Lazy<Optional<CentralSurfaces>>,
-    private val assistManagerLazy: Lazy<AssistManager>,
-    private val dozeServiceHostLazy: Lazy<DozeServiceHost>,
-    private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
-    private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>,
-    private val shadeControllerLazy: Lazy<ShadeController>,
-    private val commandQueue: CommandQueue,
-    private val shadeAnimationInteractor: ShadeAnimationInteractor,
-    private val statusBarKeyguardViewManagerLazy: Lazy<StatusBarKeyguardViewManager>,
-    private val notifShadeWindowControllerLazy: Lazy<NotificationShadeWindowController>,
-    private val activityTransitionAnimator: ActivityTransitionAnimator,
-    private val context: Context,
-    @DisplayId private val displayId: Int,
-    private val lockScreenUserManager: NotificationLockscreenUserManager,
-    private val statusBarWindowController: StatusBarWindowController,
-    private val wakefulnessLifecycle: WakefulnessLifecycle,
-    private val keyguardStateController: KeyguardStateController,
     private val statusBarStateController: SysuiStatusBarStateController,
-    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
-    private val deviceProvisionedController: DeviceProvisionedController,
-    private val userTracker: UserTracker,
-    private val activityIntentHelper: ActivityIntentHelper,
     @Main private val mainExecutor: DelayableExecutor,
+    legacyActivityStarter: Lazy<LegacyActivityStarterInternalImpl>
 ) : ActivityStarter {
-    companion object {
-        const val TAG = "ActivityStarterImpl"
-    }
 
-    private val centralSurfaces: CentralSurfaces?
-        get() = centralSurfacesOptLazy.get().getOrNull()
-
-    private val activityStarterInternal = ActivityStarterInternal()
+    private val activityStarterInternal: ActivityStarterInternal = legacyActivityStarter.get()
 
     override fun startPendingIntentDismissingKeyguard(intent: PendingIntent) {
         activityStarterInternal.startPendingIntentDismissingKeyguard(intent = intent)
@@ -401,575 +343,11 @@
         }
     }
 
+    override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean {
+        return activityStarterInternal.shouldAnimateLaunch(isActivityIntent)
+    }
+
     private fun postOnUiThread(delay: Int = 0, runnable: Runnable) {
         mainExecutor.executeDelayed(runnable, delay.toLong())
     }
-
-    /**
-     * Whether we should animate an activity launch.
-     *
-     * Note: This method must be called *before* dismissing the keyguard.
-     */
-    private fun shouldAnimateLaunch(
-        isActivityIntent: Boolean,
-        showOverLockscreen: Boolean,
-    ): Boolean {
-        // TODO(b/294418322): Support launch animations when occluded.
-        if (keyguardStateController.isOccluded) {
-            return false
-        }
-
-        // Always animate if we are not showing the keyguard or if we animate over the lockscreen
-        // (without unlocking it).
-        if (showOverLockscreen || !keyguardStateController.isShowing) {
-            return true
-        }
-
-        // We don't animate non-activity launches as they can break the animation.
-        // TODO(b/184121838): Support non activity launches on the lockscreen.
-        return isActivityIntent
-    }
-
-    override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean {
-        return shouldAnimateLaunch(isActivityIntent, false)
-    }
-
-    /**
-     * Encapsulates the activity logic for activity starter.
-     *
-     * Logic is duplicated in {@link CentralSurfacesImpl}
-     */
-    private inner class ActivityStarterInternal {
-        /** Starts an activity after dismissing keyguard. */
-        fun startActivityDismissingKeyguard(
-            intent: Intent,
-            onlyProvisioned: Boolean = false,
-            dismissShade: Boolean = false,
-            disallowEnterPictureInPictureWhileLaunching: Boolean = false,
-            callback: ActivityStarter.Callback? = null,
-            flags: Int = 0,
-            animationController: ActivityTransitionAnimator.Controller? = null,
-            userHandle: UserHandle? = null,
-            customMessage: String? = null,
-        ) {
-            val userHandle: UserHandle = userHandle ?: getActivityUserHandle(intent)
-
-            if (onlyProvisioned && !deviceProvisionedController.isDeviceProvisioned) return
-
-            val willLaunchResolverActivity: Boolean =
-                activityIntentHelper.wouldLaunchResolverActivity(
-                    intent,
-                    lockScreenUserManager.currentUserId
-                )
-
-            val animate =
-                animationController != null &&
-                    !willLaunchResolverActivity &&
-                    shouldAnimateLaunch(isActivityIntent = true)
-            val animController =
-                wrapAnimationControllerForShadeOrStatusBar(
-                    animationController = animationController,
-                    dismissShade = dismissShade,
-                    isLaunchForActivity = true,
-                )
-
-            // If we animate, we will dismiss the shade only once the animation is done. This is
-            // taken care of by the StatusBarLaunchAnimationController.
-            val dismissShadeDirectly = dismissShade && animController == null
-
-            val runnable = Runnable {
-                assistManagerLazy.get().hideAssist()
-                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
-                intent.addFlags(flags)
-                val result = intArrayOf(ActivityManager.START_CANCELED)
-                activityTransitionAnimator.startIntentWithAnimation(
-                    animController,
-                    animate,
-                    intent.getPackage()
-                ) { adapter: RemoteAnimationAdapter? ->
-                    val options =
-                        ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter))
-
-                    // We know that the intent of the caller is to dismiss the keyguard and
-                    // this runnable is called right after the keyguard is solved, so we tell
-                    // WM that we should dismiss it to avoid flickers when opening an activity
-                    // that can also be shown over the keyguard.
-                    options.setDismissKeyguardIfInsecure()
-                    options.setDisallowEnterPictureInPictureWhileLaunching(
-                        disallowEnterPictureInPictureWhileLaunching
-                    )
-                    if (isInsecureCameraIntent(intent)) {
-                        // Normally an activity will set it's requested rotation
-                        // animation on its window. However when launching an activity
-                        // causes the orientation to change this is too late. In these cases
-                        // the default animation is used. This doesn't look good for
-                        // the camera (as it rotates the camera contents out of sync
-                        // with physical reality). So, we ask the WindowManager to
-                        // force the cross fade animation if an orientation change
-                        // happens to occur during the launch.
-                        options.rotationAnimationHint =
-                            WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
-                    }
-                    if (Settings.Panel.ACTION_VOLUME == intent.action) {
-                        // Settings Panel is implemented as activity(not a dialog), so
-                        // underlying app is paused and may enter picture-in-picture mode
-                        // as a result.
-                        // So we need to disable picture-in-picture mode here
-                        // if it is volume panel.
-                        options.setDisallowEnterPictureInPictureWhileLaunching(true)
-                    }
-                    try {
-                        result[0] =
-                            ActivityTaskManager.getService()
-                                .startActivityAsUser(
-                                    null,
-                                    context.basePackageName,
-                                    context.attributionTag,
-                                    intent,
-                                    intent.resolveTypeIfNeeded(context.contentResolver),
-                                    null,
-                                    null,
-                                    0,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK,
-                                    null,
-                                    options.toBundle(),
-                                    userHandle.identifier,
-                                )
-                    } catch (e: RemoteException) {
-                        Log.w(TAG, "Unable to start activity", e)
-                    }
-                    result[0]
-                }
-                callback?.onActivityStarted(result[0])
-            }
-            val cancelRunnable = Runnable {
-                callback?.onActivityStarted(ActivityManager.START_CANCELED)
-            }
-            // Do not deferKeyguard when occluded because, when keyguard is occluded,
-            // we do not launch the activity until keyguard is done.
-            val occluded = (keyguardStateController.isShowing && keyguardStateController.isOccluded)
-            val deferred = !occluded
-            executeRunnableDismissingKeyguard(
-                runnable,
-                cancelRunnable,
-                dismissShadeDirectly,
-                willLaunchResolverActivity,
-                deferred,
-                animate,
-                customMessage,
-            )
-        }
-
-        /**
-         * Starts a pending intent after dismissing keyguard.
-         *
-         * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in
-         * the main thread).
-         */
-        fun startPendingIntentDismissingKeyguard(
-            intent: PendingIntent,
-            intentSentUiThreadCallback: Runnable? = null,
-            associatedView: View? = null,
-            animationController: ActivityTransitionAnimator.Controller? = null,
-            showOverLockscreen: Boolean = false,
-            fillInIntent: Intent? = null,
-            extraOptions: Bundle? = null,
-        ) {
-            val animationController =
-                if (associatedView is ExpandableNotificationRow) {
-                    centralSurfaces?.getAnimatorControllerFromNotification(associatedView)
-                } else animationController
-
-            val willLaunchResolverActivity =
-                (intent.isActivity &&
-                    activityIntentHelper.wouldPendingLaunchResolverActivity(
-                        intent,
-                        lockScreenUserManager.currentUserId,
-                    ))
-
-            val actuallyShowOverLockscreen =
-                showOverLockscreen &&
-                    intent.isActivity &&
-                    activityIntentHelper.wouldPendingShowOverLockscreen(
-                        intent,
-                        lockScreenUserManager.currentUserId
-                    )
-
-            val animate =
-                !willLaunchResolverActivity &&
-                    animationController != null &&
-                    shouldAnimateLaunch(intent.isActivity, actuallyShowOverLockscreen)
-
-            // We wrap animationCallback with a StatusBarLaunchAnimatorController so
-            // that the shade is collapsed after the animation (or when it is cancelled,
-            // aborted, etc).
-            val statusBarController =
-                wrapAnimationControllerForShadeOrStatusBar(
-                    animationController = animationController,
-                    dismissShade = true,
-                    isLaunchForActivity = intent.isActivity,
-                )
-            val controller =
-                if (actuallyShowOverLockscreen) {
-                    wrapAnimationControllerForLockscreen(statusBarController)
-                } else {
-                    statusBarController
-                }
-
-            // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we
-            // run the animation on the keyguard). The animation will take care of (instantly)
-            // collapsing the shade and hiding the keyguard once it is done.
-            val collapse = !animate
-            val runnable = Runnable {
-                try {
-                    activityTransitionAnimator.startPendingIntentWithAnimation(
-                        controller,
-                        animate,
-                        intent.creatorPackage,
-                        actuallyShowOverLockscreen,
-                        object : PendingIntentStarter {
-                            override fun startPendingIntent(
-                                animationAdapter: RemoteAnimationAdapter?
-                            ): Int {
-                                val options =
-                                    ActivityOptions(
-                                        CentralSurfaces.getActivityOptions(
-                                                displayId,
-                                                animationAdapter
-                                            )
-                                            .apply { extraOptions?.let { putAll(it) } }
-                                    )
-                                // TODO b/221255671: restrict this to only be set for
-                                // notifications
-                                options.isEligibleForLegacyPermissionPrompt = true
-                                options.setPendingIntentBackgroundActivityStartMode(
-                                    ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
-                                )
-                                return intent.sendAndReturnResult(
-                                    context,
-                                    0,
-                                    fillInIntent,
-                                    null,
-                                    null,
-                                    null,
-                                    options.toBundle()
-                                )
-                            }
-                        },
-                    )
-                } catch (e: PendingIntent.CanceledException) {
-                    // the stack trace isn't very helpful here.
-                    // Just log the exception message.
-                    Log.w(TAG, "Sending intent failed: $e")
-                    if (!collapse) {
-                        // executeRunnableDismissingKeyguard did not collapse for us already.
-                        shadeControllerLazy.get().collapseOnMainThread()
-                    }
-                    // TODO: Dismiss Keyguard.
-                }
-                if (intent.isActivity) {
-                    assistManagerLazy.get().hideAssist()
-                    // This activity could have started while the device is dreaming, in which case
-                    // the dream would occlude the activity. In order to show the newly started
-                    // activity, we wake from the dream.
-                    keyguardUpdateMonitor.awakenFromDream()
-                }
-                intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) }
-            }
-
-            if (!actuallyShowOverLockscreen) {
-                postOnUiThread(delay = 0) {
-                    executeRunnableDismissingKeyguard(
-                        runnable = runnable,
-                        afterKeyguardGone = willLaunchResolverActivity,
-                        dismissShade = collapse,
-                        willAnimateOnKeyguard = animate,
-                    )
-                }
-            } else {
-                postOnUiThread(delay = 0, runnable)
-            }
-        }
-
-        /** Starts an Activity. */
-        fun startActivity(
-            intent: Intent,
-            dismissShade: Boolean = false,
-            animationController: ActivityTransitionAnimator.Controller? = null,
-            showOverLockscreenWhenLocked: Boolean = false,
-            userHandle: UserHandle? = null,
-        ) {
-            val userHandle = userHandle ?: getActivityUserHandle(intent)
-            // Make sure that we dismiss the keyguard if it is directly dismissible or when we don't
-            // want to show the activity above it.
-            if (keyguardStateController.isUnlocked || !showOverLockscreenWhenLocked) {
-                startActivityDismissingKeyguard(
-                    intent = intent,
-                    onlyProvisioned = false,
-                    dismissShade = dismissShade,
-                    disallowEnterPictureInPictureWhileLaunching = false,
-                    callback = null,
-                    flags = 0,
-                    animationController = animationController,
-                    userHandle = userHandle,
-                )
-                return
-            }
-
-            val animate =
-                animationController != null &&
-                    shouldAnimateLaunch(
-                        /* isActivityIntent= */ true,
-                        showOverLockscreenWhenLocked
-                    ) == true
-
-            var controller: ActivityTransitionAnimator.Controller? = null
-            if (animate) {
-                // Wrap the animation controller to dismiss the shade and set
-                // mIsLaunchingActivityOverLockscreen during the animation.
-                val delegate =
-                    wrapAnimationControllerForShadeOrStatusBar(
-                        animationController = animationController,
-                        dismissShade = dismissShade,
-                        isLaunchForActivity = true,
-                    )
-                controller = wrapAnimationControllerForLockscreen(delegate)
-            } else if (dismissShade) {
-                // The animation will take care of dismissing the shade at the end of the animation.
-                // If we don't animate, collapse it directly.
-                shadeControllerLazy.get().cancelExpansionAndCollapseShade()
-            }
-
-            // We should exit the dream to prevent the activity from starting below the
-            // dream.
-            if (keyguardUpdateMonitor.isDreaming) {
-                centralSurfaces?.awakenDreams()
-            }
-
-            activityTransitionAnimator.startIntentWithAnimation(
-                controller,
-                animate,
-                intent.getPackage(),
-                showOverLockscreenWhenLocked
-            ) { adapter: RemoteAnimationAdapter? ->
-                TaskStackBuilder.create(context)
-                    .addNextIntent(intent)
-                    .startActivities(
-                        CentralSurfaces.getActivityOptions(displayId, adapter),
-                        userHandle
-                    )
-            }
-        }
-
-        /** Executes an action after dismissing keyguard. */
-        fun dismissKeyguardThenExecute(
-            action: OnDismissAction,
-            cancel: Runnable? = null,
-            afterKeyguardGone: Boolean = false,
-            customMessage: String? = null,
-        ) {
-            if (
-                !action.willRunAnimationOnKeyguard() &&
-                    wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP &&
-                    keyguardStateController.canDismissLockScreen() &&
-                    !statusBarStateController.leaveOpenOnKeyguardHide() &&
-                    dozeServiceHostLazy.get().isPulsing
-            ) {
-                // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a
-                // pulse.
-                // TODO: Factor this transition out of BiometricUnlockController.
-                biometricUnlockControllerLazy
-                    .get()
-                    .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
-            }
-            if (keyguardStateController.isShowing) {
-                statusBarKeyguardViewManagerLazy
-                    .get()
-                    .dismissWithAction(action, cancel, afterKeyguardGone, customMessage)
-            } else {
-                // If the keyguard isn't showing but the device is dreaming, we should exit the
-                // dream.
-                if (keyguardUpdateMonitor.isDreaming) {
-                    centralSurfaces?.awakenDreams()
-                }
-                action.onDismiss()
-            }
-        }
-
-        /** Executes an action after dismissing keyguard. */
-        fun executeRunnableDismissingKeyguard(
-            runnable: Runnable? = null,
-            cancelAction: Runnable? = null,
-            dismissShade: Boolean = false,
-            afterKeyguardGone: Boolean = false,
-            deferred: Boolean = false,
-            willAnimateOnKeyguard: Boolean = false,
-            customMessage: String? = null,
-        ) {
-            val onDismissAction: OnDismissAction =
-                object : OnDismissAction {
-                    override fun onDismiss(): Boolean {
-                        if (runnable != null) {
-                            if (
-                                keyguardStateController.isShowing &&
-                                    keyguardStateController.isOccluded
-                            ) {
-                                statusBarKeyguardViewManagerLazy
-                                    .get()
-                                    .addAfterKeyguardGoneRunnable(runnable)
-                            } else {
-                                mainExecutor.execute(runnable)
-                            }
-                        }
-                        if (dismissShade) {
-                            shadeControllerLazy.get().collapseShadeForActivityStart()
-                        }
-                        return deferred
-                    }
-
-                    override fun willRunAnimationOnKeyguard(): Boolean {
-                        return willAnimateOnKeyguard
-                    }
-                }
-            dismissKeyguardThenExecute(
-                onDismissAction,
-                cancelAction,
-                afterKeyguardGone,
-                customMessage,
-            )
-        }
-
-        /**
-         * Return a [ActivityTransitionAnimator.Controller] wrapping `animationController` so that:
-         * - if it launches in the notification shade window and `dismissShade` is true, then the
-         *   shade will be instantly dismissed at the end of the animation.
-         * - if it launches in status bar window, it will make the status bar window match the
-         *   device size during the animation (that way, the animation won't be clipped by the
-         *   status bar size).
-         *
-         * @param animationController the controller that is wrapped and will drive the main
-         *   animation.
-         * @param dismissShade whether the notification shade will be dismissed at the end of the
-         *   animation. This is ignored if `animationController` is not animating in the shade
-         *   window.
-         * @param isLaunchForActivity whether the launch is for an activity.
-         */
-        private fun wrapAnimationControllerForShadeOrStatusBar(
-            animationController: ActivityTransitionAnimator.Controller?,
-            dismissShade: Boolean,
-            isLaunchForActivity: Boolean,
-        ): ActivityTransitionAnimator.Controller? {
-            if (animationController == null) {
-                return null
-            }
-            val rootView = animationController.transitionContainer.rootView
-            val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> =
-                statusBarWindowController.wrapAnimationControllerIfInStatusBar(
-                    rootView,
-                    animationController
-                )
-            if (controllerFromStatusBar.isPresent) {
-                return controllerFromStatusBar.get()
-            }
-
-            centralSurfaces?.let {
-                // If the view is not in the status bar, then we are animating a view in the shade.
-                // We have to make sure that we collapse it when the animation ends or is cancelled.
-                if (dismissShade) {
-                    return StatusBarTransitionAnimatorController(
-                        animationController,
-                        shadeAnimationInteractor,
-                        shadeControllerLazy.get(),
-                        notifShadeWindowControllerLazy.get(),
-                        commandQueue,
-                        displayId,
-                        isLaunchForActivity
-                    )
-                }
-            }
-
-            return animationController
-        }
-
-        /**
-         * Wraps an animation controller so that if an activity would be launched on top of the
-         * lockscreen, the correct flags are set for it to be occluded.
-         */
-        private fun wrapAnimationControllerForLockscreen(
-            animationController: ActivityTransitionAnimator.Controller?
-        ): ActivityTransitionAnimator.Controller? {
-            return animationController?.let {
-                object : DelegateTransitionAnimatorController(it) {
-                    override fun onIntentStarted(willAnimate: Boolean) {
-                        delegate.onIntentStarted(willAnimate)
-                        if (willAnimate) {
-                            centralSurfaces?.setIsLaunchingActivityOverLockscreen(true)
-                        }
-                    }
-
-                    override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
-                        super.onTransitionAnimationStart(isExpandingFullyAbove)
-
-                        // Double check that the keyguard is still showing and not going
-                        // away, but if so set the keyguard occluded. Typically, WM will let
-                        // KeyguardViewMediator know directly, but we're overriding that to
-                        // play the custom launch animation, so we need to take care of that
-                        // here. The unocclude animation is not overridden, so WM will call
-                        // KeyguardViewMediator's unocclude animation runner when the
-                        // activity is exited.
-                        if (
-                            keyguardStateController.isShowing &&
-                                !keyguardStateController.isKeyguardGoingAway
-                        ) {
-                            Log.d(TAG, "Setting occluded = true in #startActivity.")
-                            keyguardViewMediatorLazy
-                                .get()
-                                .setOccluded(true /* isOccluded */, true /* animate */)
-                        }
-                    }
-
-                    override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
-                        // Set mIsLaunchingActivityOverLockscreen to false before actually
-                        // finishing the animation so that we can assume that
-                        // mIsLaunchingActivityOverLockscreen being true means that we will
-                        // collapse the shade (or at least run the post collapse runnables)
-                        // later on.
-                        centralSurfaces?.setIsLaunchingActivityOverLockscreen(false)
-                        delegate.onTransitionAnimationEnd(isExpandingFullyAbove)
-                    }
-
-                    override fun onTransitionAnimationCancelled(
-                        newKeyguardOccludedState: Boolean?
-                    ) {
-                        if (newKeyguardOccludedState != null) {
-                            keyguardViewMediatorLazy
-                                .get()
-                                .setOccluded(newKeyguardOccludedState, false /* animate */)
-                        }
-
-                        // Set mIsLaunchingActivityOverLockscreen to false before actually
-                        // finishing the animation so that we can assume that
-                        // mIsLaunchingActivityOverLockscreen being true means that we will
-                        // collapse the shade (or at least run the // post collapse
-                        // runnables) later on.
-                        centralSurfaces?.setIsLaunchingActivityOverLockscreen(false)
-                        delegate.onTransitionAnimationCancelled(newKeyguardOccludedState)
-                    }
-                }
-            }
-        }
-
-        /** Retrieves the current user handle to start the Activity. */
-        private fun getActivityUserHandle(intent: Intent): UserHandle {
-            val packages: Array<String> =
-                context.resources.getStringArray(R.array.system_ui_packages)
-            for (pkg in packages) {
-                val componentName = intent.component ?: break
-                if (pkg == componentName.packageName) {
-                    return UserHandle(UserHandle.myUserId())
-                }
-            }
-            return userTracker.userHandle
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt
new file mode 100644
index 0000000..e844398
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.Bundle
+import android.os.UserHandle
+import android.view.View
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.plugins.ActivityStarter
+
+interface ActivityStarterInternal {
+    /**
+     * Starts a pending intent after dismissing keyguard.
+     *
+     * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in the
+     * main thread).
+     */
+    fun startPendingIntentDismissingKeyguard(
+        intent: PendingIntent,
+        intentSentUiThreadCallback: Runnable? = null,
+        associatedView: View? = null,
+        animationController: ActivityTransitionAnimator.Controller? = null,
+        showOverLockscreen: Boolean = false,
+        fillInIntent: Intent? = null,
+        extraOptions: Bundle? = null,
+    )
+
+    /** Starts an activity after dismissing keyguard. */
+    fun startActivityDismissingKeyguard(
+        intent: Intent,
+        dismissShade: Boolean,
+        onlyProvisioned: Boolean = false,
+        callback: ActivityStarter.Callback? = null,
+        flags: Int = 0,
+        animationController: ActivityTransitionAnimator.Controller? = null,
+        customMessage: String? = null,
+        disallowEnterPictureInPictureWhileLaunching: Boolean = false,
+        userHandle: UserHandle? = null,
+    )
+
+    /** Starts an Activity. */
+    fun startActivity(
+        intent: Intent,
+        dismissShade: Boolean,
+        animationController: ActivityTransitionAnimator.Controller?,
+        showOverLockscreenWhenLocked: Boolean,
+        userHandle: UserHandle? = null,
+    )
+
+    /** Executes an action after dismissing keyguard. */
+    fun dismissKeyguardThenExecute(
+        action: ActivityStarter.OnDismissAction,
+        cancel: Runnable?,
+        afterKeyguardGone: Boolean,
+        customMessage: String? = null,
+    )
+
+    /** Executes an action after dismissing keyguard. */
+    fun executeRunnableDismissingKeyguard(
+        runnable: Runnable?,
+        cancelAction: Runnable? = null,
+        dismissShade: Boolean = false,
+        afterKeyguardGone: Boolean = false,
+        deferred: Boolean = false,
+        willAnimateOnKeyguard: Boolean = false,
+        customMessage: String? = null,
+    )
+
+    /** Whether we should animate an activity launch. */
+    fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
new file mode 100644
index 0000000..c101755
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.Bundle
+import android.os.UserHandle
+import android.view.View
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.ActivityStarter
+import javax.inject.Inject
+
+/**
+ * Encapsulates the activity logic for activity starter when flexiglass is enabled.
+ *
+ * TODO: b/308819693
+ */
+@SysUISingleton
+class ActivityStarterInternalImpl @Inject constructor() : ActivityStarterInternal {
+    override fun startPendingIntentDismissingKeyguard(
+        intent: PendingIntent,
+        intentSentUiThreadCallback: Runnable?,
+        associatedView: View?,
+        animationController: ActivityTransitionAnimator.Controller?,
+        showOverLockscreen: Boolean,
+        fillInIntent: Intent?,
+        extraOptions: Bundle?
+    ) {
+        TODO("Not yet implemented b/308819693")
+    }
+
+    override fun startActivityDismissingKeyguard(
+        intent: Intent,
+        dismissShade: Boolean,
+        onlyProvisioned: Boolean,
+        callback: ActivityStarter.Callback?,
+        flags: Int,
+        animationController: ActivityTransitionAnimator.Controller?,
+        customMessage: String?,
+        disallowEnterPictureInPictureWhileLaunching: Boolean,
+        userHandle: UserHandle?
+    ) {
+        TODO("Not yet implemented b/308819693")
+    }
+
+    override fun startActivity(
+        intent: Intent,
+        dismissShade: Boolean,
+        animationController: ActivityTransitionAnimator.Controller?,
+        showOverLockscreenWhenLocked: Boolean,
+        userHandle: UserHandle?
+    ) {
+        TODO("Not yet implemented b/308819693")
+    }
+
+    override fun dismissKeyguardThenExecute(
+        action: ActivityStarter.OnDismissAction,
+        cancel: Runnable?,
+        afterKeyguardGone: Boolean,
+        customMessage: String?
+    ) {
+        TODO("Not yet implemented b/308819693")
+    }
+
+    override fun executeRunnableDismissingKeyguard(
+        runnable: Runnable?,
+        cancelAction: Runnable?,
+        dismissShade: Boolean,
+        afterKeyguardGone: Boolean,
+        deferred: Boolean,
+        willAnimateOnKeyguard: Boolean,
+        customMessage: String?
+    ) {
+        TODO("Not yet implemented b/308819693")
+    }
+
+    override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean {
+        TODO("Not yet implemented b/308819693")
+    }
+}
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 8b7b348..79e6a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -67,6 +67,8 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -77,8 +79,6 @@
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
 /**
  * Controller which coordinates all the biometric unlocking actions with the UI.
  */
@@ -183,6 +183,7 @@
     private final SystemClock mSystemClock;
     private final boolean mOrderUnlockAndWake;
     private final Lazy<SelectedUserInteractor> mSelectedUserInteractor;
+    private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private long mLastFpFailureUptimeMillis;
     private int mNumConsecutiveFpFailures;
 
@@ -323,6 +324,7 @@
         mOrderUnlockAndWake = resources.getBoolean(
                 com.android.internal.R.bool.config_orderUnlockAndWake);
         mSelectedUserInteractor = selectedUserInteractor;
+        mKeyguardTransitionInteractor = keyguardTransitionInteractor;
         javaAdapter.alwaysCollectFlow(
                 keyguardTransitionInteractor.getStartedKeyguardTransitionStep(),
                 this::consumeTransitionStepOnStartedKeyguardState);
@@ -665,7 +667,8 @@
         }
         if (isKeyguardShowing) {
             if ((mKeyguardViewController.primaryBouncerIsOrWillBeShowing()
-                    || mKeyguardBypassController.getAltBouncerShowing()) && unlockingAllowed) {
+                    || mKeyguardTransitionInteractor.getCurrentState()
+                    == KeyguardState.ALTERNATE_BOUNCER) && unlockingAllowed) {
                 return MODE_DISMISS_BOUNCER;
             } else if (unlockingAllowed && bypass) {
                 return MODE_UNLOCK_COLLAPSING;
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 a1fae03..7d97428 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -37,6 +37,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.AuthKeyguardMessageArea;
+import com.android.systemui.CoreStartable;
 import com.android.systemui.Dumpable;
 import com.android.systemui.animation.ActivityTransitionAnimator;
 import com.android.systemui.animation.RemoteAnimationRunnerCompat;
@@ -50,7 +51,7 @@
 import java.io.PrintWriter;
 
 /** */
-public interface CentralSurfaces extends Dumpable, LifecycleOwner {
+public interface CentralSurfaces extends Dumpable, LifecycleOwner, CoreStartable {
     boolean MULTIUSER_DEBUG = false;
     // Should match the values in PhoneWindowManager
     String SYSTEM_DIALOG_REASON_KEY = "reason";
@@ -103,8 +104,8 @@
     /**
      * Returns an ActivityOptions bundle created using the given parameters.
      *
-     * @param displayId The ID of the display to launch the activity in. Typically this would
-     *                  be the display the status bar is on.
+     * @param displayId        The ID of the display to launch the activity in. Typically this would
+     *                         be the display the status bar is on.
      * @param animationAdapter The animation adapter used to start this activity, or {@code null}
      *                         for the default animation.
      */
@@ -182,6 +183,9 @@
         return contextForUser.getPackageManager();
     }
 
+    /** Default impl for CoreStartable. */
+    default void start() {}
+
     boolean updateIsKeyguard();
 
     boolean updateIsKeyguard(boolean forceStateChange);
@@ -197,7 +201,7 @@
 
     void onKeyguardViewManagerStatesUpdated();
 
-    /** */
+    /**  */
     boolean getCommandQueuePanelsEnabled();
 
     void showWirelessChargingAnimation(int batteryLevel);
@@ -279,11 +283,12 @@
     void awakenDreams();
 
     /**
-     * Handle a touch event while dreaming when the touch was initiated within a prescribed
-     * swipeable area. This method is provided for cases where swiping in certain areas of a dream
-     * should be handled by CentralSurfaces instead (e.g. swiping communal hub open).
+     * Handle a touch event while dreaming or on the glanceable hub when the touch was initiated
+     * within a prescribed swipeable area. This method is provided for cases where swiping in
+     * certain areas should be handled by CentralSurfaces instead (e.g. swiping hub open, opening
+     * the notification shade over dream or hub).
      */
-    void handleDreamTouch(MotionEvent event);
+    void handleExternalShadeWindowTouch(MotionEvent event);
 
     boolean isBouncerShowing();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
index 8af7ee8..d5e66ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
@@ -79,7 +79,7 @@
     override fun updateScrimController() {}
     override fun shouldIgnoreTouch() = false
     override fun isDeviceInteractive() = false
-    override fun handleDreamTouch(event: MotionEvent?) {}
+    override fun handleExternalShadeWindowTouch(event: MotionEvent?) {}
     override fun awakenDreams() {}
     override fun isBouncerShowing() = false
     override fun isBouncerShowingScrimmed() = false
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 5baf6a0..b2b2cea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -164,10 +164,10 @@
 import com.android.systemui.res.R;
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
 import com.android.systemui.scene.shared.flag.SceneContainerFlag;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor;
 import com.android.systemui.shade.CameraLauncher;
 import com.android.systemui.shade.NotificationShadeWindowView;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
@@ -591,8 +591,7 @@
 
     private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
             (extractor, which) -> updateTheme();
-
-    private final SceneContainerFlags mSceneContainerFlags;
+    private final BrightnessMirrorShowingInteractor mBrightnessMirrorShowingInteractor;
 
     /**
      * Public constructor for CentralSurfaces.
@@ -705,7 +704,7 @@
             UserTracker userTracker,
             Provider<FingerprintManager> fingerprintManager,
             ActivityStarter activityStarter,
-            SceneContainerFlags sceneContainerFlags
+            BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor
     ) {
         mContext = context;
         mNotificationsController = notificationsController;
@@ -800,7 +799,7 @@
         mUserTracker = userTracker;
         mFingerprintManager = fingerprintManager;
         mActivityStarter = activityStarter;
-        mSceneContainerFlags = sceneContainerFlags;
+        mBrightnessMirrorShowingInteractor = brightnessMirrorShowingInteractor;
 
         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
         mStartingSurfaceOptional = startingSurfaceOptional;
@@ -1083,6 +1082,12 @@
         mJavaAdapter.alwaysCollectFlow(
                 mCommunalInteractor.isIdleOnCommunal(),
                 mIdleOnCommunalConsumer);
+        if (SceneContainerFlag.isEnabled()) {
+            mJavaAdapter.alwaysCollectFlow(
+                    mBrightnessMirrorShowingInteractor.isShowing(),
+                    this::setBrightnessMirrorShowing
+            );
+        }
     }
 
     /**
@@ -1266,7 +1271,7 @@
 
         // Set up the quick settings tile panel
         final View container = getNotificationShadeWindowView().findViewById(R.id.qs_frame);
-        if (container != null && !mSceneContainerFlags.isEnabled()) {
+        if (container != null && !SceneContainerFlag.isEnabled()) {
             FragmentHostManager fragmentHostManager =
                     mFragmentService.getFragmentHostManager(container);
             ExtensionFragmentListener.attachExtensonToFragment(
@@ -1284,10 +1289,7 @@
                     mShadeSurface,
                     mNotificationShadeDepthControllerLazy.get(),
                     mBrightnessSliderFactory,
-                    (visible) -> {
-                        mBrightnessMirrorVisible = visible;
-                        updateScrimController();
-                    });
+                    this::setBrightnessMirrorShowing);
             fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                 QS qs = (QS) f;
                 if (qs instanceof QSFragmentLegacy) {
@@ -1346,6 +1348,10 @@
         ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
     }
 
+    private void setBrightnessMirrorShowing(boolean showing) {
+        mBrightnessMirrorVisible = showing;
+        updateScrimController();
+    }
 
     /**
      * When swiping up to dismiss the lock screen, the panel expansion fraction goes from 1f to 0f.
@@ -1533,8 +1539,7 @@
                 mShadeSurface,
                 mShadeExpansionStateManager,
                 mBiometricUnlockController,
-                mStackScroller,
-                mKeyguardBypassController);
+                mStackScroller);
         mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
         mKeyguardIndicationController
                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -2411,7 +2416,6 @@
         mBouncerShowing = bouncerShowing;
         mKeyguardBypassController.setBouncerShowing(bouncerShowing);
         mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
-        mStackScrollerController.setBouncerShowingFromCentralSurfaces(bouncerShowing);
         setBouncerShowingForStatusBarComponents(bouncerShowing);
         mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing);
         mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -2924,8 +2928,8 @@
     };
 
     @Override
-    public void handleDreamTouch(MotionEvent event) {
-        getNotificationShadeWindowViewController().handleDreamTouch(event);
+    public void handleExternalShadeWindowTouch(MotionEvent event) {
+        getNotificationShadeWindowViewController().handleExternalTouch(event);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 7abcf13..033659b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -37,9 +37,9 @@
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.flags.FeatureFlagsClassic;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
 import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -84,7 +84,6 @@
     private final SysuiStatusBarStateController mStatusBarStateController;
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final HeadsUpManager mHeadsUpManager;
-    private final FeatureFlagsClassic mFeatureFlags;
     private final BatteryController mBatteryController;
     private final ScrimController mScrimController;
     private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@@ -110,7 +109,6 @@
             WakefulnessLifecycle wakefulnessLifecycle,
             SysuiStatusBarStateController statusBarStateController,
             DeviceProvisionedController deviceProvisionedController,
-            FeatureFlagsClassic featureFlags,
             HeadsUpManager headsUpManager, BatteryController batteryController,
             ScrimController scrimController,
             Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
@@ -135,7 +133,6 @@
         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
         mAssistManagerLazy = assistManagerLazy;
         mDozeScrimController = dozeScrimController;
-        mFeatureFlags = featureFlags;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mPulseExpansionHandler = pulseExpansionHandler;
         mNotificationShadeWindowController = notificationShadeWindowController;
@@ -236,8 +233,14 @@
     void updateDozing() {
         Assert.isMainThread();
 
-        boolean dozing =
-                mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+        boolean dozing;
+        if (SceneContainerFlag.isEnabled()) {
+            dozing = mDozingRequested && mDozeInteractor.canDozeFromCurrentScene();
+        } else {
+            dozing = mDozingRequested
+                    && mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+        }
+
         // When in wake-and-unlock we may not have received a change to StatusBarState
         // but we still should not be dozing, manually set to false.
         if (mBiometricUnlockControllerLazy.get().getMode()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 495b4e1..4c3c7d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -41,6 +41,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationIconInteractor;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
@@ -421,9 +422,12 @@
     public void updateHeader(NotificationEntry entry) {
         ExpandableNotificationRow row = entry.getRow();
         float headerVisibleAmount = 1.0f;
-        if (row.isPinned() || row.isHeadsUpAnimatingAway() || row == mTrackedChild
-                || row.showingPulsing()) {
-            headerVisibleAmount = mAppearFraction;
+        // To fix the invisible HUN group header issue
+        if (!AsyncGroupHeaderViewInflation.isEnabled()) {
+            if (row.isPinned() || row.isHeadsUpAnimatingAway() || row == mTrackedChild
+                    || row.showingPulsing()) {
+                headerVisibleAmount = mAppearFraction;
+            }
         }
         row.setHeaderVisibleAmount(headerVisibleAmount);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 3f200d5..8ec8d1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -91,7 +91,8 @@
             StateFlowKt.MutableStateFlow(null);
     private final MutableStateFlow<Set<HeadsUpRowRepository>> mHeadsUpNotificationRows =
             StateFlowKt.MutableStateFlow(new HashSet<>());
-    private final MutableStateFlow<Boolean> mHeadsUpGoingAway = StateFlowKt.MutableStateFlow(false);
+    private final MutableStateFlow<Boolean> mHeadsUpAnimatingAway =
+            StateFlowKt.MutableStateFlow(false);
     private boolean mReleaseOnExpandFinish;
     private boolean mTrackingHeadsUp;
     private final HashSet<String> mSwipedOutKeys = new HashSet<>();
@@ -167,7 +168,10 @@
                 updateResources();
             }
         });
-        javaAdapter.alwaysCollectFlow(shadeInteractor.isAnyExpanded(), this::onShadeOrQsExpanded);
+        if (!NotificationsHeadsUpRefactor.isEnabled()) {
+            javaAdapter.alwaysCollectFlow(shadeInteractor.isAnyExpanded(),
+                    this::onShadeOrQsExpanded);
+        }
     }
 
     public void setAnimationStateHandler(AnimationStateHandler handler) {
@@ -184,7 +188,7 @@
     //  Public methods:
 
     /**
-     * Add a listener to receive callbacks onHeadsUpGoingAway
+     * Add a listener to receive callbacks {@link #setHeadsUpAnimatingAway(boolean)}
      */
     @Override
     public void addHeadsUpPhoneListener(OnHeadsUpPhoneListenerChange listener) {
@@ -261,10 +265,11 @@
     }
 
     private void onShadeOrQsExpanded(Boolean isExpanded) {
+        NotificationsHeadsUpRefactor.assertInLegacyMode();
         if (isExpanded != mIsExpanded) {
             mIsExpanded = isExpanded;
             if (isExpanded) {
-                mHeadsUpGoingAway.setValue(false);
+                mHeadsUpAnimatingAway.setValue(false);
             }
         }
     }
@@ -274,20 +279,15 @@
      * animating out. This is used to keep the touchable regions in a reasonable state.
      */
     @Override
-    public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
-        if (headsUpGoingAway != mHeadsUpGoingAway.getValue()) {
+    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+        if (headsUpAnimatingAway != mHeadsUpAnimatingAway.getValue()) {
             for (OnHeadsUpPhoneListenerChange listener : mHeadsUpPhoneListeners) {
-                listener.onHeadsUpGoingAwayStateChanged(headsUpGoingAway);
+                listener.onHeadsUpAnimatingAwayStateChanged(headsUpAnimatingAway);
             }
-            mHeadsUpGoingAway.setValue(headsUpGoingAway);
+            mHeadsUpAnimatingAway.setValue(headsUpAnimatingAway);
         }
     }
 
-    @Override
-    public boolean isHeadsUpGoingAway() {
-        return mHeadsUpGoingAway.getValue();
-    }
-
     /**
      * Notifies that a remote input textbox in notification gets active or inactive.
      *
@@ -504,8 +504,13 @@
 
     @Override
     @NonNull
-    public Flow<Boolean> getHeadsUpAnimatingAway() {
-        return mHeadsUpGoingAway;
+    public StateFlow<Boolean> isHeadsUpAnimatingAway() {
+        return mHeadsUpAnimatingAway;
+    }
+
+    @Override
+    public boolean isHeadsUpAnimatingAwayValue() {
+        return mHeadsUpAnimatingAway.getValue();
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index a3d316b..a8941bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -17,8 +17,8 @@
 package com.android.systemui.statusbar.phone
 
 import android.annotation.IntDef
-import android.content.Context
 import android.content.pm.PackageManager
+import android.content.res.Resources
 import android.hardware.biometrics.BiometricSourceType
 import android.provider.Settings
 import androidx.annotation.VisibleForTesting
@@ -26,7 +26,10 @@
 import com.android.systemui.Dumpable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
 import com.android.systemui.shade.data.repository.ShadeRepository
@@ -46,12 +49,20 @@
 import javax.inject.Inject
 
 @SysUISingleton
-open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassController {
+class KeyguardBypassController @Inject constructor(
+        @Main resources: Resources,
+        packageManager: PackageManager,
+        @Application applicationScope: CoroutineScope,
+        tunerService: TunerService,
+        private val statusBarStateController: StatusBarStateController,
+        lockscreenUserManager: NotificationLockscreenUserManager,
+        private val keyguardStateController: KeyguardStateController,
+        private val shadeRepository: ShadeRepository,
+        devicePostureController: DevicePostureController,
+        private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+        dumpManager: DumpManager
+) : Dumpable, StackScrollAlgorithm.BypassController {
 
-    private val mKeyguardStateController: KeyguardStateController
-    private val statusBarStateController: StatusBarStateController
-    private val shadeRepository: ShadeRepository
-    private val devicePostureController: DevicePostureController
     @BypassOverride private val bypassOverride: Int
     private var hasFaceFeature: Boolean
     @DevicePostureInt private val configFaceAuthSupportedPosture: Int
@@ -99,7 +110,7 @@
                 FACE_UNLOCK_BYPASS_NEVER -> false
                 else -> field
             }
-            return enabled && mKeyguardStateController.isFaceEnrolledAndEnabled &&
+            return enabled && keyguardStateController.isFaceEnrolledAndEnabled &&
                     isPostureAllowedForFaceAuth()
         }
         private set(value) {
@@ -108,70 +119,44 @@
         }
 
     var bouncerShowing: Boolean = false
-    var altBouncerShowing: Boolean = false
     var launchingAffordance: Boolean = false
     var qsExpanded = false
 
-    @Inject
-    constructor(
-        context: Context,
-        @Application applicationScope: CoroutineScope,
-        tunerService: TunerService,
-        statusBarStateController: StatusBarStateController,
-        lockscreenUserManager: NotificationLockscreenUserManager,
-        keyguardStateController: KeyguardStateController,
-        shadeRepository: ShadeRepository,
-        devicePostureController: DevicePostureController,
-        dumpManager: DumpManager
-    ) {
-        this.mKeyguardStateController = keyguardStateController
-        this.statusBarStateController = statusBarStateController
-        this.shadeRepository = shadeRepository
-        this.devicePostureController = devicePostureController
-
-        bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override)
+    init {
+        bypassOverride = resources.getInteger(R.integer.config_face_unlock_bypass_override)
         configFaceAuthSupportedPosture =
-            context.resources.getInteger(R.integer.config_face_auth_supported_posture)
-
-        hasFaceFeature = context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
-        if (!hasFaceFeature) {
-            return
-        }
-
-
-        if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
-            devicePostureController.addCallback { posture ->
-                if (postureState != posture) {
-                    postureState = posture
-                    notifyListeners()
+            resources.getInteger(R.integer.config_face_auth_supported_posture)
+        hasFaceFeature = packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
+        if (hasFaceFeature) {
+            if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
+                devicePostureController.addCallback { posture ->
+                    if (postureState != posture) {
+                        postureState = posture
+                        notifyListeners()
+                    }
                 }
             }
-        }
-
-        dumpManager.registerNormalDumpable("KeyguardBypassController", this)
-        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
-            override fun onStateChanged(newState: Int) {
-                if (newState != StatusBarState.KEYGUARD) {
-                    pendingUnlock = null
-                }
-            }
-        })
-
-        listenForQsExpandedChange(applicationScope)
-
-        val dismissByDefault = if (context.resources.getBoolean(
-                com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
-
-        tunerService.addTunable({ key, _ ->
-            bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0
-        }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD)
-
-        lockscreenUserManager.addUserChangedListener(
-            object : NotificationLockscreenUserManager.UserChangedListener {
-                override fun onUserChanged(userId: Int) {
-                    pendingUnlock = null
+            dumpManager.registerNormalDumpable("KeyguardBypassController", this)
+            statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
+                override fun onStateChanged(newState: Int) {
+                    if (newState != StatusBarState.KEYGUARD) {
+                        pendingUnlock = null
+                    }
                 }
             })
+            listenForQsExpandedChange(applicationScope)
+            val dismissByDefault = if (resources.getBoolean(
+                            com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
+            tunerService.addTunable({ key, _ ->
+                bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0
+            }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD)
+            lockscreenUserManager.addUserChangedListener(
+                    object : NotificationLockscreenUserManager.UserChangedListener {
+                        override fun onUserChanged(userId: Int) {
+                            pendingUnlock = null
+                        }
+                    })
+        }
     }
 
     @VisibleForTesting
@@ -228,7 +213,8 @@
         if (bypassEnabled) {
             return when {
                 bouncerShowing -> true
-                altBouncerShowing -> true
+                keyguardTransitionInteractor.getCurrentState() == KeyguardState.ALTERNATE_BOUNCER ->
+                    true
                 statusBarStateController.state != StatusBarState.KEYGUARD -> false
                 launchingAffordance -> false
                 isPulseExpanding || qsExpanded -> false
@@ -260,7 +246,8 @@
         pw.println("  bypassEnabled: $bypassEnabled")
         pw.println("  canBypass: ${canBypass()}")
         pw.println("  bouncerShowing: $bouncerShowing")
-        pw.println("  altBouncerShowing: $altBouncerShowing")
+        pw.println("  altBouncerShowing:" +
+            " ${keyguardTransitionInteractor.getCurrentState() == KeyguardState.ALTERNATE_BOUNCER}")
         pw.println("  isPulseExpanding: $isPulseExpanding")
         pw.println("  launchingAffordance: $launchingAffordance")
         pw.println("  qSExpanded: $qsExpanded")
@@ -273,7 +260,7 @@
         val start = listeners.isEmpty()
         listeners.add(listener)
         if (start) {
-            mKeyguardStateController.addCallback(faceAuthEnabledChangedCallback)
+            keyguardStateController.addCallback(faceAuthEnabledChangedCallback)
         }
     }
 
@@ -284,7 +271,7 @@
     fun unregisterOnBypassStateChangedListener(listener: OnBypassStateChangedListener) {
         listeners.remove(listener)
         if (listeners.isEmpty()) {
-            mKeyguardStateController.removeCallback(faceAuthEnabledChangedCallback)
+            keyguardStateController.removeCallback(faceAuthEnabledChangedCallback)
         }
     }
 
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 38b3718..3343779 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -658,6 +658,7 @@
         updateForHeadsUp(true);
     }
 
+    // TODO(b/328579846) bind the StatusBar visibility to heads up events
     void updateForHeadsUp(boolean animate) {
         boolean showingKeyguardHeadsUp =
                 isKeyguardShowing() && mShadeViewStateProvider.shouldHeadsUpBeVisible();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
new file mode 100644
index 0000000..68d54e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
@@ -0,0 +1,639 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.app.ActivityManager
+import android.app.ActivityOptions
+import android.app.ActivityTaskManager
+import android.app.PendingIntent
+import android.app.TaskStackBuilder
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.os.RemoteException
+import android.os.UserHandle
+import android.provider.Settings
+import android.util.Log
+import android.view.RemoteAnimationAdapter
+import android.view.View
+import android.view.WindowManager
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.DelegateTransitionAnimatorController
+import com.android.systemui.assist.AssistManager
+import com.android.systemui.camera.CameraIntents
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.DisplayId
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.res.R
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.kotlin.getOrNull
+import dagger.Lazy
+import java.util.Optional
+import javax.inject.Inject
+
+/** Encapsulates the activity logic for activity starter. */
+@SysUISingleton
+class LegacyActivityStarterInternalImpl
+@Inject
+constructor(
+    private val centralSurfacesOptLazy: Lazy<Optional<CentralSurfaces>>,
+    private val keyguardStateController: KeyguardStateController,
+    private val statusBarStateController: SysuiStatusBarStateController,
+    private val assistManagerLazy: Lazy<AssistManager>,
+    private val dozeServiceHostLazy: Lazy<DozeServiceHost>,
+    private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
+    private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>,
+    private val shadeControllerLazy: Lazy<ShadeController>,
+    private val commandQueue: CommandQueue,
+    private val shadeAnimationInteractor: ShadeAnimationInteractor,
+    private val statusBarKeyguardViewManagerLazy: Lazy<StatusBarKeyguardViewManager>,
+    private val notifShadeWindowControllerLazy: Lazy<NotificationShadeWindowController>,
+    private val activityTransitionAnimator: ActivityTransitionAnimator,
+    private val context: Context,
+    @DisplayId private val displayId: Int,
+    private val lockScreenUserManager: NotificationLockscreenUserManager,
+    private val statusBarWindowController: StatusBarWindowController,
+    private val wakefulnessLifecycle: WakefulnessLifecycle,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+    private val deviceProvisionedController: DeviceProvisionedController,
+    private val userTracker: UserTracker,
+    private val activityIntentHelper: ActivityIntentHelper,
+    @Main private val mainExecutor: DelayableExecutor,
+) : ActivityStarterInternal {
+    private val centralSurfaces: CentralSurfaces?
+        get() = centralSurfacesOptLazy.get().getOrNull()
+
+    override fun startActivityDismissingKeyguard(
+        intent: Intent,
+        dismissShade: Boolean,
+        onlyProvisioned: Boolean,
+        callback: ActivityStarter.Callback?,
+        flags: Int,
+        animationController: ActivityTransitionAnimator.Controller?,
+        customMessage: String?,
+        disallowEnterPictureInPictureWhileLaunching: Boolean,
+        userHandle: UserHandle?,
+    ) {
+        val userHandle: UserHandle = userHandle ?: getActivityUserHandle(intent)
+
+        if (onlyProvisioned && !deviceProvisionedController.isDeviceProvisioned) return
+
+        val willLaunchResolverActivity: Boolean =
+            activityIntentHelper.wouldLaunchResolverActivity(
+                intent,
+                lockScreenUserManager.currentUserId
+            )
+
+        val animate =
+            animationController != null &&
+                !willLaunchResolverActivity &&
+                shouldAnimateLaunch(isActivityIntent = true)
+        val animController =
+            wrapAnimationControllerForShadeOrStatusBar(
+                animationController = animationController,
+                dismissShade = dismissShade,
+                isLaunchForActivity = true,
+            )
+
+        // If we animate, we will dismiss the shade only once the animation is done. This is
+        // taken care of by the StatusBarLaunchAnimationController.
+        val dismissShadeDirectly = dismissShade && animController == null
+
+        val runnable = Runnable {
+            assistManagerLazy.get().hideAssist()
+            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
+            intent.addFlags(flags)
+            val result = intArrayOf(ActivityManager.START_CANCELED)
+            activityTransitionAnimator.startIntentWithAnimation(
+                animController,
+                animate,
+                intent.getPackage()
+            ) { adapter: RemoteAnimationAdapter? ->
+                val options =
+                    ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter))
+
+                // We know that the intent of the caller is to dismiss the keyguard and
+                // this runnable is called right after the keyguard is solved, so we tell
+                // WM that we should dismiss it to avoid flickers when opening an activity
+                // that can also be shown over the keyguard.
+                options.setDismissKeyguardIfInsecure()
+                options.setDisallowEnterPictureInPictureWhileLaunching(
+                    disallowEnterPictureInPictureWhileLaunching
+                )
+                if (CameraIntents.isInsecureCameraIntent(intent)) {
+                    // Normally an activity will set it's requested rotation
+                    // animation on its window. However when launching an activity
+                    // causes the orientation to change this is too late. In these cases
+                    // the default animation is used. This doesn't look good for
+                    // the camera (as it rotates the camera contents out of sync
+                    // with physical reality). So, we ask the WindowManager to
+                    // force the cross fade animation if an orientation change
+                    // happens to occur during the launch.
+                    options.rotationAnimationHint =
+                        WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
+                }
+                if (Settings.Panel.ACTION_VOLUME == intent.action) {
+                    // Settings Panel is implemented as activity(not a dialog), so
+                    // underlying app is paused and may enter picture-in-picture mode
+                    // as a result.
+                    // So we need to disable picture-in-picture mode here
+                    // if it is volume panel.
+                    options.setDisallowEnterPictureInPictureWhileLaunching(true)
+                }
+                try {
+                    result[0] =
+                        ActivityTaskManager.getService()
+                            .startActivityAsUser(
+                                null,
+                                context.basePackageName,
+                                context.attributionTag,
+                                intent,
+                                intent.resolveTypeIfNeeded(context.contentResolver),
+                                null,
+                                null,
+                                0,
+                                Intent.FLAG_ACTIVITY_NEW_TASK,
+                                null,
+                                options.toBundle(),
+                                userHandle.identifier,
+                            )
+                } catch (e: RemoteException) {
+                    Log.w(TAG, "Unable to start activity", e)
+                }
+                result[0]
+            }
+            callback?.onActivityStarted(result[0])
+        }
+        val cancelRunnable = Runnable {
+            callback?.onActivityStarted(ActivityManager.START_CANCELED)
+        }
+        // Do not deferKeyguard when occluded because, when keyguard is occluded,
+        // we do not launch the activity until keyguard is done.
+        val occluded = (keyguardStateController.isShowing && keyguardStateController.isOccluded)
+        val deferred = !occluded
+        executeRunnableDismissingKeyguard(
+            runnable,
+            cancelRunnable,
+            dismissShadeDirectly,
+            willLaunchResolverActivity,
+            deferred,
+            animate,
+            customMessage,
+        )
+    }
+
+    override fun startPendingIntentDismissingKeyguard(
+        intent: PendingIntent,
+        intentSentUiThreadCallback: Runnable?,
+        associatedView: View?,
+        animationController: ActivityTransitionAnimator.Controller?,
+        showOverLockscreen: Boolean,
+        fillInIntent: Intent?,
+        extraOptions: Bundle?,
+    ) {
+        val animationController =
+            if (associatedView is ExpandableNotificationRow) {
+                centralSurfaces?.getAnimatorControllerFromNotification(associatedView)
+            } else animationController
+
+        val willLaunchResolverActivity =
+            (intent.isActivity &&
+                activityIntentHelper.wouldPendingLaunchResolverActivity(
+                    intent,
+                    lockScreenUserManager.currentUserId,
+                ))
+
+        val actuallyShowOverLockscreen =
+            showOverLockscreen &&
+                intent.isActivity &&
+                activityIntentHelper.wouldPendingShowOverLockscreen(
+                    intent,
+                    lockScreenUserManager.currentUserId
+                )
+
+        val animate =
+            !willLaunchResolverActivity &&
+                animationController != null &&
+                shouldAnimateLaunch(intent.isActivity, actuallyShowOverLockscreen)
+
+        // We wrap animationCallback with a StatusBarLaunchAnimatorController so
+        // that the shade is collapsed after the animation (or when it is cancelled,
+        // aborted, etc).
+        val statusBarController =
+            wrapAnimationControllerForShadeOrStatusBar(
+                animationController = animationController,
+                dismissShade = true,
+                isLaunchForActivity = intent.isActivity,
+            )
+        val controller =
+            if (actuallyShowOverLockscreen) {
+                wrapAnimationControllerForLockscreen(statusBarController)
+            } else {
+                statusBarController
+            }
+
+        // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we
+        // run the animation on the keyguard). The animation will take care of (instantly)
+        // collapsing the shade and hiding the keyguard once it is done.
+        val collapse = !animate
+        val runnable = Runnable {
+            try {
+                activityTransitionAnimator.startPendingIntentWithAnimation(
+                    controller,
+                    animate,
+                    intent.creatorPackage,
+                    actuallyShowOverLockscreen,
+                    object : ActivityTransitionAnimator.PendingIntentStarter {
+                        override fun startPendingIntent(
+                            animationAdapter: RemoteAnimationAdapter?
+                        ): Int {
+                            val options =
+                                ActivityOptions(
+                                    CentralSurfaces.getActivityOptions(displayId, animationAdapter)
+                                        .apply { extraOptions?.let { putAll(it) } }
+                                )
+                            // TODO b/221255671: restrict this to only be set for
+                            // notifications
+                            options.isEligibleForLegacyPermissionPrompt = true
+                            options.setPendingIntentBackgroundActivityStartMode(
+                                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+                            )
+                            return intent.sendAndReturnResult(
+                                context,
+                                0,
+                                fillInIntent,
+                                null,
+                                null,
+                                null,
+                                options.toBundle()
+                            )
+                        }
+                    },
+                )
+            } catch (e: PendingIntent.CanceledException) {
+                // the stack trace isn't very helpful here.
+                // Just log the exception message.
+                Log.w(TAG, "Sending intent failed: $e")
+                if (!collapse) {
+                    // executeRunnableDismissingKeyguard did not collapse for us already.
+                    shadeControllerLazy.get().collapseOnMainThread()
+                }
+                // TODO: Dismiss Keyguard.
+            }
+            if (intent.isActivity) {
+                assistManagerLazy.get().hideAssist()
+                // This activity could have started while the device is dreaming, in which case
+                // the dream would occlude the activity. In order to show the newly started
+                // activity, we wake from the dream.
+                keyguardUpdateMonitor.awakenFromDream()
+            }
+            intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) }
+        }
+
+        if (!actuallyShowOverLockscreen) {
+            postOnUiThread(delay = 0) {
+                executeRunnableDismissingKeyguard(
+                    runnable = runnable,
+                    afterKeyguardGone = willLaunchResolverActivity,
+                    dismissShade = collapse,
+                    willAnimateOnKeyguard = animate,
+                )
+            }
+        } else {
+            postOnUiThread(delay = 0, runnable)
+        }
+    }
+
+    override fun startActivity(
+        intent: Intent,
+        dismissShade: Boolean,
+        animationController: ActivityTransitionAnimator.Controller?,
+        showOverLockscreenWhenLocked: Boolean,
+        userHandle: UserHandle?,
+    ) {
+        val userHandle = userHandle ?: getActivityUserHandle(intent)
+        // Make sure that we dismiss the keyguard if it is directly dismissible or when we don't
+        // want to show the activity above it.
+        if (keyguardStateController.isUnlocked || !showOverLockscreenWhenLocked) {
+            startActivityDismissingKeyguard(
+                intent = intent,
+                onlyProvisioned = false,
+                dismissShade = dismissShade,
+                disallowEnterPictureInPictureWhileLaunching = false,
+                callback = null,
+                flags = 0,
+                animationController = animationController,
+                userHandle = userHandle,
+            )
+            return
+        }
+
+        val animate =
+            animationController != null &&
+                shouldAnimateLaunch(/* isActivityIntent= */ true, showOverLockscreenWhenLocked)
+
+        var controller: ActivityTransitionAnimator.Controller? = null
+        if (animate) {
+            // Wrap the animation controller to dismiss the shade and set
+            // mIsLaunchingActivityOverLockscreen during the animation.
+            val delegate =
+                wrapAnimationControllerForShadeOrStatusBar(
+                    animationController = animationController,
+                    dismissShade = dismissShade,
+                    isLaunchForActivity = true,
+                )
+            controller = wrapAnimationControllerForLockscreen(delegate)
+        } else if (dismissShade) {
+            // The animation will take care of dismissing the shade at the end of the animation.
+            // If we don't animate, collapse it directly.
+            shadeControllerLazy.get().cancelExpansionAndCollapseShade()
+        }
+
+        // We should exit the dream to prevent the activity from starting below the
+        // dream.
+        if (keyguardUpdateMonitor.isDreaming) {
+            centralSurfaces?.awakenDreams()
+        }
+
+        activityTransitionAnimator.startIntentWithAnimation(
+            controller,
+            animate,
+            intent.getPackage(),
+            showOverLockscreenWhenLocked
+        ) { adapter: RemoteAnimationAdapter? ->
+            TaskStackBuilder.create(context)
+                .addNextIntent(intent)
+                .startActivities(CentralSurfaces.getActivityOptions(displayId, adapter), userHandle)
+        }
+    }
+
+    override fun dismissKeyguardThenExecute(
+        action: ActivityStarter.OnDismissAction,
+        cancel: Runnable?,
+        afterKeyguardGone: Boolean,
+        customMessage: String?,
+    ) {
+        if (
+            !action.willRunAnimationOnKeyguard() &&
+                wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP &&
+                keyguardStateController.canDismissLockScreen() &&
+                !statusBarStateController.leaveOpenOnKeyguardHide() &&
+                dozeServiceHostLazy.get().isPulsing
+        ) {
+            // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a
+            // pulse.
+            // TODO: Factor this transition out of BiometricUnlockController.
+            biometricUnlockControllerLazy
+                .get()
+                .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
+        }
+        if (keyguardStateController.isShowing) {
+            statusBarKeyguardViewManagerLazy
+                .get()
+                .dismissWithAction(action, cancel, afterKeyguardGone, customMessage)
+        } else {
+            // If the keyguard isn't showing but the device is dreaming, we should exit the
+            // dream.
+            if (keyguardUpdateMonitor.isDreaming) {
+                centralSurfaces?.awakenDreams()
+            }
+            action.onDismiss()
+        }
+    }
+
+    override fun executeRunnableDismissingKeyguard(
+        runnable: Runnable?,
+        cancelAction: Runnable?,
+        dismissShade: Boolean,
+        afterKeyguardGone: Boolean,
+        deferred: Boolean,
+        willAnimateOnKeyguard: Boolean,
+        customMessage: String?,
+    ) {
+        val onDismissAction: ActivityStarter.OnDismissAction =
+            object : ActivityStarter.OnDismissAction {
+                override fun onDismiss(): Boolean {
+                    if (runnable != null) {
+                        if (
+                            keyguardStateController.isShowing && keyguardStateController.isOccluded
+                        ) {
+                            statusBarKeyguardViewManagerLazy
+                                .get()
+                                .addAfterKeyguardGoneRunnable(runnable)
+                        } else {
+                            mainExecutor.execute(runnable)
+                        }
+                    }
+                    if (dismissShade) {
+                        shadeControllerLazy.get().collapseShadeForActivityStart()
+                    }
+                    return deferred
+                }
+
+                override fun willRunAnimationOnKeyguard(): Boolean {
+                    return willAnimateOnKeyguard
+                }
+            }
+        dismissKeyguardThenExecute(
+            onDismissAction,
+            cancelAction,
+            afterKeyguardGone,
+            customMessage,
+        )
+    }
+
+    /**
+     * Return a [ActivityTransitionAnimator.Controller] wrapping `animationController` so that:
+     * - if it launches in the notification shade window and `dismissShade` is true, then the shade
+     *   will be instantly dismissed at the end of the animation.
+     * - if it launches in status bar window, it will make the status bar window match the device
+     *   size during the animation (that way, the animation won't be clipped by the status bar
+     *   size).
+     *
+     * @param animationController the controller that is wrapped and will drive the main animation.
+     * @param dismissShade whether the notification shade will be dismissed at the end of the
+     *   animation. This is ignored if `animationController` is not animating in the shade window.
+     * @param isLaunchForActivity whether the launch is for an activity.
+     */
+    private fun wrapAnimationControllerForShadeOrStatusBar(
+        animationController: ActivityTransitionAnimator.Controller?,
+        dismissShade: Boolean,
+        isLaunchForActivity: Boolean,
+    ): ActivityTransitionAnimator.Controller? {
+        if (animationController == null) {
+            return null
+        }
+        val rootView = animationController.transitionContainer.rootView
+        val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> =
+            statusBarWindowController.wrapAnimationControllerIfInStatusBar(
+                rootView,
+                animationController
+            )
+        if (controllerFromStatusBar.isPresent) {
+            return controllerFromStatusBar.get()
+        }
+
+        centralSurfaces?.let {
+            // If the view is not in the status bar, then we are animating a view in the shade.
+            // We have to make sure that we collapse it when the animation ends or is cancelled.
+            if (dismissShade) {
+                return StatusBarTransitionAnimatorController(
+                    animationController,
+                    shadeAnimationInteractor,
+                    shadeControllerLazy.get(),
+                    notifShadeWindowControllerLazy.get(),
+                    commandQueue,
+                    displayId,
+                    isLaunchForActivity
+                )
+            }
+        }
+
+        return animationController
+    }
+
+    /**
+     * Wraps an animation controller so that if an activity would be launched on top of the
+     * lockscreen, the correct flags are set for it to be occluded.
+     */
+    private fun wrapAnimationControllerForLockscreen(
+        animationController: ActivityTransitionAnimator.Controller?
+    ): ActivityTransitionAnimator.Controller? {
+        return animationController?.let {
+            object : DelegateTransitionAnimatorController(it) {
+                override fun onIntentStarted(willAnimate: Boolean) {
+                    delegate.onIntentStarted(willAnimate)
+                    if (willAnimate) {
+                        centralSurfaces?.setIsLaunchingActivityOverLockscreen(true)
+                    }
+                }
+
+                override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
+                    super.onTransitionAnimationStart(isExpandingFullyAbove)
+
+                    // Double check that the keyguard is still showing and not going
+                    // away, but if so set the keyguard occluded. Typically, WM will let
+                    // KeyguardViewMediator know directly, but we're overriding that to
+                    // play the custom launch animation, so we need to take care of that
+                    // here. The unocclude animation is not overridden, so WM will call
+                    // KeyguardViewMediator's unocclude animation runner when the
+                    // activity is exited.
+                    if (
+                        keyguardStateController.isShowing &&
+                            !keyguardStateController.isKeyguardGoingAway
+                    ) {
+                        Log.d(TAG, "Setting occluded = true in #startActivity.")
+                        keyguardViewMediatorLazy
+                            .get()
+                            .setOccluded(true /* isOccluded */, true /* animate */)
+                    }
+                }
+
+                override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
+                    // Set mIsLaunchingActivityOverLockscreen to false before actually
+                    // finishing the animation so that we can assume that
+                    // mIsLaunchingActivityOverLockscreen being true means that we will
+                    // collapse the shade (or at least run the post collapse runnables)
+                    // later on.
+                    centralSurfaces?.setIsLaunchingActivityOverLockscreen(false)
+                    delegate.onTransitionAnimationEnd(isExpandingFullyAbove)
+                }
+
+                override fun onTransitionAnimationCancelled(newKeyguardOccludedState: Boolean?) {
+                    if (newKeyguardOccludedState != null) {
+                        keyguardViewMediatorLazy
+                            .get()
+                            .setOccluded(newKeyguardOccludedState, false /* animate */)
+                    }
+
+                    // Set mIsLaunchingActivityOverLockscreen to false before actually
+                    // finishing the animation so that we can assume that
+                    // mIsLaunchingActivityOverLockscreen being true means that we will
+                    // collapse the shade (or at least run the // post collapse
+                    // runnables) later on.
+                    centralSurfaces?.setIsLaunchingActivityOverLockscreen(false)
+                    delegate.onTransitionAnimationCancelled(newKeyguardOccludedState)
+                }
+            }
+        }
+    }
+
+    /** Retrieves the current user handle to start the Activity. */
+    private fun getActivityUserHandle(intent: Intent): UserHandle {
+        val packages: Array<String> = context.resources.getStringArray(R.array.system_ui_packages)
+        for (pkg in packages) {
+            val componentName = intent.component ?: break
+            if (pkg == componentName.packageName) {
+                return UserHandle(UserHandle.myUserId())
+            }
+        }
+        return userTracker.userHandle
+    }
+
+    /**
+     * Whether we should animate an activity launch.
+     *
+     * Note: This method must be called *before* dismissing the keyguard.
+     */
+    private fun shouldAnimateLaunch(
+        isActivityIntent: Boolean,
+        showOverLockscreen: Boolean,
+    ): Boolean {
+        // TODO(b/294418322): Support launch animations when occluded.
+        if (keyguardStateController.isOccluded) {
+            return false
+        }
+
+        // Always animate if we are not showing the keyguard or if we animate over the lockscreen
+        // (without unlocking it).
+        if (showOverLockscreen || !keyguardStateController.isShowing) {
+            return true
+        }
+
+        // We don't animate non-activity launches as they can break the animation.
+        // TODO(b/184121838): Support non activity launches on the lockscreen.
+        return isActivityIntent
+    }
+
+    override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean {
+        return shouldAnimateLaunch(isActivityIntent, false)
+    }
+
+    private fun postOnUiThread(delay: Int = 0, runnable: Runnable) {
+        mainExecutor.executeDelayed(runnable, delay.toLong())
+    }
+
+    companion object {
+        private const val TAG = "LegacyActivityStarterInternalImpl"
+    }
+}
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 92fd90a..5206e46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -24,10 +24,10 @@
 import android.view.ViewGroup
 import android.view.ViewTreeObserver
 import com.android.systemui.Gefingerpoken
-import com.android.systemui.res.R
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.ui.view.WindowRootView
 import com.android.systemui.shade.ShadeController
 import com.android.systemui.shade.ShadeLogger
@@ -65,7 +65,6 @@
     private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
     private val userChipViewModel: StatusBarUserChipViewModel,
     private val viewUtil: ViewUtil,
-    private val sceneContainerFlags: SceneContainerFlags,
     private val configurationController: ConfigurationController,
     private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
 ) : ViewController<PhoneStatusBarView>(view) {
@@ -205,7 +204,7 @@
 
             // If scene framework is enabled, route the touch to it and
             // ignore the rest of the gesture.
-            if (sceneContainerFlags.isEnabled()) {
+            if (SceneContainerFlag.isEnabled) {
                 windowRootView.get().dispatchTouchEvent(event)
                 return true
             }
@@ -267,7 +266,6 @@
         @Named(UNFOLD_STATUS_BAR)
         private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
         private val featureFlags: FeatureFlags,
-        private val sceneContainerFlags: SceneContainerFlags,
         private val userChipViewModel: StatusBarUserChipViewModel,
         private val centralSurfaces: CentralSurfaces,
         private val statusBarWindowStateController: StatusBarWindowStateController,
@@ -301,7 +299,6 @@
                 statusBarMoveFromCenterAnimationController,
                 userChipViewModel,
                 viewUtil,
-                sceneContainerFlags,
                 configurationController,
                 statusOverlayHoverListenerFactory,
             )
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
index ed1f6ff..da5877b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
@@ -24,6 +24,7 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -98,15 +99,21 @@
                 // we need to keep the panel open artificially, let's wait until the
                 //animation
                 // is finished.
-                mHeadsUpManager.setHeadsUpGoingAway(true);
+                setHeadsAnimatingAway(true);
                 mNsslController.runAfterAnimationFinished(() -> {
                     if (!mHeadsUpManager.hasPinnedHeadsUp()) {
                         mNotificationShadeWindowController.setHeadsUpShowing(false);
-                        mHeadsUpManager.setHeadsUpGoingAway(false);
+                        setHeadsAnimatingAway(false);
                     }
                     mNotificationRemoteInputManager.onPanelCollapsed();
                 });
             }
         }
     }
+
+    private void setHeadsAnimatingAway(boolean headsUpAnimatingAway) {
+        if (!NotificationsHeadsUpRefactor.isEnabled()) {
+            mHeadsUpManager.setHeadsUpAnimatingAway(headsUpAnimatingAway);
+        }
+    }
 }
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 5f26702..a141b53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -67,12 +67,12 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardWmStateRefactor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor;
+import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent;
 import com.android.systemui.keyguard.shared.model.DismissAction;
 import com.android.systemui.keyguard.shared.model.KeyguardDone;
 import com.android.systemui.keyguard.shared.model.KeyguardState;
@@ -332,7 +332,6 @@
     private final LatencyTracker mLatencyTracker;
     private final KeyguardSecurityModel mKeyguardSecurityModel;
     private final SelectedUserInteractor mSelectedUserInteractor;
-    @Nullable private KeyguardBypassController mBypassController;
     @Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
 
     @Nullable private TaskbarDelegate mTaskbarDelegate;
@@ -381,7 +380,6 @@
             Lazy<ShadeController> shadeController,
             LatencyTracker latencyTracker,
             KeyguardSecurityModel keyguardSecurityModel,
-            FeatureFlags featureFlags,
             PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
             PrimaryBouncerInteractor primaryBouncerInteractor,
             BouncerView primaryBouncerView,
@@ -413,7 +411,6 @@
         mShadeController = shadeController;
         mLatencyTracker = latencyTracker;
         mKeyguardSecurityModel = keyguardSecurityModel;
-        mFlags = featureFlags;
         mPrimaryBouncerCallbackInteractor = primaryBouncerCallbackInteractor;
         mPrimaryBouncerInteractor = primaryBouncerInteractor;
         mPrimaryBouncerView = primaryBouncerView;
@@ -442,8 +439,7 @@
             ShadeLockscreenInteractor shadeLockscreenInteractor,
             ShadeExpansionStateManager shadeExpansionStateManager,
             BiometricUnlockController biometricUnlockController,
-            View notificationContainer,
-            KeyguardBypassController bypassController) {
+            View notificationContainer) {
         mCentralSurfaces = centralSurfaces;
         mBiometricUnlockController = biometricUnlockController;
 
@@ -454,7 +450,6 @@
                     shadeExpansionStateManager.addExpansionListener(this);
             onPanelExpansionChanged(currentState);
         }
-        mBypassController = bypassController;
         mNotificationContainer = notificationContainer;
         if (!DeviceEntryUdfpsRefactor.isEnabled()) {
             mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create(
@@ -805,7 +800,7 @@
 
     public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
             boolean afterKeyguardGone, String message) {
-        if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled()) {
             if (r == null) {
                 return;
             }
@@ -857,7 +852,7 @@
                     return;
                 }
 
-                if (!mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+                if (!RefactorKeyguardDismissIntent.isEnabled()) {
                     mAfterKeyguardGoneAction = r;
                     mKeyguardGoneCancelAction = cancelAction;
                     mDismissActionWillAnimateOnKeyguard = r != null
@@ -925,7 +920,7 @@
      * Adds a {@param runnable} to be executed after Keyguard is gone.
      */
     public void addAfterKeyguardGoneRunnable(Runnable runnable) {
-        if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled()) {
             if (runnable != null) {
                 mKeyguardDismissActionInteractor.get().runAfterKeyguardGone(runnable);
             }
@@ -975,7 +970,6 @@
             mKeyguardMessageAreaController.setIsVisible(isShowingAlternateBouncer);
             mKeyguardMessageAreaController.setMessage("");
         }
-        mBypassController.setAltBouncerShowing(isShowingAlternateBouncer);
         mKeyguardUpdateManager.setAlternateBouncerShowing(isShowingAlternateBouncer);
 
         if (updateScrim) {
@@ -1118,7 +1112,7 @@
             // We update the state (which will show the keyguard) only if an animation will run on
             // the keyguard. If there is no animation, we wait before updating the state so that we
             // go directly from bouncer to launcher/app.
-            if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+            if (RefactorKeyguardDismissIntent.isEnabled()) {
                 if (mKeyguardDismissActionInteractor.get().runDismissAnimationOnKeyguard()) {
                     updateStates();
                 }
@@ -1245,7 +1239,7 @@
     }
 
     private void executeAfterKeyguardGoneAction() {
-        if (mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT)) {
+        if (RefactorKeyguardDismissIntent.isEnabled()) {
             return;
         }
         if (mAfterKeyguardGoneAction != null) {
@@ -1298,9 +1292,11 @@
             return;
         }
 
+        boolean hideBouncerOverDream = isBouncerShowing()
+                && mDreamOverlayStateController.isOverlayActive();
         mCentralSurfaces.endAffordanceLaunch();
         // The second condition is for SIM card locked bouncer
-        if (primaryBouncerIsScrimmed() && !needsFullscreenBouncer()) {
+        if (hideBouncerOverDream || (primaryBouncerIsScrimmed() && !needsFullscreenBouncer())) {
             hideBouncer(false);
             updateStates();
         } else {
@@ -1634,7 +1630,7 @@
         pw.println("  bouncerIsOrWillBeShowing(): " + primaryBouncerIsOrWillBeShowing());
         pw.println("  Registered KeyguardViewManagerCallbacks:");
         pw.println(" refactorKeyguardDismissIntent enabled:"
-                + mFlags.isEnabled(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT));
+                + RefactorKeyguardDismissIntent.isEnabled());
         for (KeyguardViewManagerCallback callback : mCallbacks) {
             pw.println("      " + callback);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
index 4211cab..66e909c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
@@ -70,7 +70,7 @@
     fun logSendPendingIntent(entry: NotificationEntry, pendingIntent: PendingIntent, result: Int) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
-            str2 = pendingIntent.intent.toString()
+            str2 = pendingIntent.intent?.toString()
             int1 = result
         }, {
             "(5/5) Started intent $str2 for notification $str1 with result code $int1"
@@ -120,7 +120,7 @@
     fun logSendingFullScreenIntent(entry: NotificationEntry, pendingIntent: PendingIntent) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
-            str2 = pendingIntent.intent.toString()
+            str2 = pendingIntent.intent?.toString()
         }, {
             "Notification $str1 has fullScreenIntent; sending fullScreenIntent $str2"
         })
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index c615887..d1189e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -37,7 +37,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.res.R;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.shade.ShadeExpansionStateManager;
 import com.android.systemui.shade.domain.interactor.ShadeInteractor;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -91,7 +91,6 @@
             ShadeInteractor shadeInteractor,
             Provider<SceneInteractor> sceneInteractor,
             JavaAdapter javaAdapter,
-            SceneContainerFlags sceneContainerFlags,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             PrimaryBouncerInteractor primaryBouncerInteractor,
             AlternateBouncerInteractor alternateBouncerInteractor
@@ -121,7 +120,7 @@
                         updateTouchableRegion();
                     }
                 });
-        mHeadsUpManager.addHeadsUpPhoneListener(this::onHeadsUpGoingAwayStateChanged);
+        mHeadsUpManager.addHeadsUpPhoneListener(this::onHeadsUpAnimatingAwayStateChanged);
 
         mNotificationShadeWindowController = notificationShadeWindowController;
         mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> {
@@ -130,7 +129,7 @@
 
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
 
-        if (sceneContainerFlags.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             javaAdapter.alwaysCollectFlow(
                     sceneInteractor.get().isVisible(),
                     this::onSceneContainerVisibilityChanged);
@@ -214,7 +213,7 @@
                 && (mNotificationShadeWindowView.getRootWindowInsets() != null)
                 && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null);
         boolean shouldObserve = mHeadsUpManager.hasPinnedHeadsUp()
-                        || mHeadsUpManager.isHeadsUpGoingAway()
+                        || mHeadsUpManager.isHeadsUpAnimatingAwayValue()
                         || mForceCollapsedUntilLayout
                         || hasCutoutInset
                         || mNotificationShadeWindowController.getForcePluginOpen();
@@ -288,8 +287,8 @@
                 || mUnlockedScreenOffAnimationController.isAnimationPlaying();
     }
 
-    private void onHeadsUpGoingAwayStateChanged(boolean headsUpGoingAway) {
-        if (!headsUpGoingAway) {
+    private void onHeadsUpAnimatingAwayStateChanged(boolean headsUpAnimatingAway) {
+        if (!headsUpAnimatingAway) {
             updateTouchableRegionAfterLayout();
         } else {
             updateTouchableRegion();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt
index 541ac48..31c2134 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt
@@ -15,36 +15,55 @@
  */
 package com.android.systemui.statusbar.phone
 
+import android.annotation.StyleRes
 import android.app.Dialog
 import android.content.Context
-import android.content.res.Configuration
 import android.graphics.Color
 import android.graphics.drawable.ColorDrawable
 import android.os.Bundle
 import android.view.Gravity
 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import android.view.WindowInsets
-import android.view.WindowInsets.Type.InsetsType
-import android.view.WindowInsetsAnimation
 import android.view.WindowManager.LayoutParams.MATCH_PARENT
 import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
 import android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
 import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL
+import androidx.activity.ComponentDialog
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
+import com.android.systemui.statusbar.policy.onConfigChanged
+import dagger.Lazy
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.launch
 
 /** A dialog shown as a bottom sheet. */
-open class SystemUIBottomSheetDialog(
+class SystemUIBottomSheetDialog
+@VisibleForTesting
+constructor(
     context: Context,
-    private val configurationController: ConfigurationController? = null,
-    theme: Int = R.style.Theme_SystemUI_Dialog
-) : Dialog(context, theme) {
+    private val coroutineScope: CoroutineScope,
+    private val configurationController: ConfigurationController,
+    private val delegate: DialogDelegate<in Dialog>,
+    private val windowLayout: WindowLayout,
+    theme: Int,
+) : ComponentDialog(context, theme) {
+
+    private var job: Job? = null
+
     override fun onCreate(savedInstanceState: Bundle?) {
+        delegate.beforeCreate(this, savedInstanceState)
         super.onCreate(savedInstanceState)
         setupWindow()
-        setupEdgeToEdge()
         setCanceledOnTouchOutside(true)
+        delegate.onCreate(this, savedInstanceState)
     }
 
     private fun setupWindow() {
@@ -62,60 +81,84 @@
         }
     }
 
-    private fun setupEdgeToEdge() {
-        val edgeToEdgeHorizontally =
-            context.resources.getBoolean(R.bool.config_edgeToEdgeBottomSheetDialog)
-        val width = if (edgeToEdgeHorizontally) MATCH_PARENT else WRAP_CONTENT
-        val height = WRAP_CONTENT
-        window?.setLayout(width, height)
-    }
-
     override fun onStart() {
         super.onStart()
-        configurationController?.addCallback(onConfigChanged)
-        window?.decorView?.setWindowInsetsAnimationCallback(insetsAnimationCallback)
+        job?.cancel()
+        job =
+            coroutineScope.launch {
+                windowLayout
+                    .calculate()
+                    .onEach { window?.apply { setLayout(it.width, it.height) } }
+                    .launchIn(this)
+                configurationController.onConfigChanged
+                    .onEach { delegate.onConfigurationChanged(this@SystemUIBottomSheetDialog, it) }
+                    .launchIn(this)
+            }
+        delegate.onStart(this)
     }
 
     override fun onStop() {
+        job?.cancel()
+        delegate.onStop(this)
         super.onStop()
-        configurationController?.removeCallback(onConfigChanged)
-        window?.decorView?.setWindowInsetsAnimationCallback(null)
     }
 
-    /** Called after any insets change. */
-    open fun onInsetsChanged(@InsetsType changedTypes: Int, insets: WindowInsets) {}
+    override fun onWindowFocusChanged(hasFocus: Boolean) {
+        super.onWindowFocusChanged(hasFocus)
+        delegate.onWindowFocusChanged(this, hasFocus)
+    }
 
-    /** Can be overridden by subclasses to receive config changed events. */
-    open fun onConfigurationChanged() {}
+    class Factory
+    @Inject
+    constructor(
+        @Application private val context: Context,
+        @Application private val coroutineScope: CoroutineScope,
+        private val defaultWindowLayout: Lazy<WindowLayout.LimitedEdgeToEdge>,
+        private val configurationController: ConfigurationController,
+    ) {
 
-    private val insetsAnimationCallback =
-        object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
+        fun create(
+            delegate: DialogDelegate<in Dialog>,
+            windowLayout: WindowLayout = defaultWindowLayout.get(),
+            @StyleRes theme: Int = R.style.Theme_SystemUI_Dialog,
+        ): SystemUIBottomSheetDialog =
+            SystemUIBottomSheetDialog(
+                context = context,
+                configurationController = configurationController,
+                coroutineScope = coroutineScope,
+                delegate = delegate,
+                windowLayout = windowLayout,
+                theme = theme,
+            )
+    }
 
-            private var lastInsets: WindowInsets? = null
+    /** [SystemUIBottomSheetDialog] uses this to determine the [android.view.Window] layout. */
+    interface WindowLayout {
 
-            override fun onEnd(animation: WindowInsetsAnimation) {
-                lastInsets?.let { onInsetsChanged(animation.typeMask, it) }
-            }
+        /** Returns a [Layout] to apply to [android.view.Window.setLayout]. */
+        fun calculate(): Flow<Layout>
 
-            override fun onProgress(
-                insets: WindowInsets,
-                animations: MutableList<WindowInsetsAnimation>,
-            ): WindowInsets {
-                lastInsets = insets
-                onInsetsChanged(changedTypes = allAnimationMasks(animations), insets)
-                return insets
-            }
+        /** Edge to edge with which doesn't fill the whole space on the large screen. */
+        class LimitedEdgeToEdge
+        @Inject
+        constructor(
+            @Application private val context: Context,
+            private val configurationController: ConfigurationController,
+        ) : WindowLayout {
 
-            private fun allAnimationMasks(animations: List<WindowInsetsAnimation>): Int =
-                animations.fold(0) { acc: Int, it -> acc or it.typeMask }
-        }
+            override fun calculate(): Flow<Layout> {
+                return configurationController.onConfigChanged
+                    .onStart { emit(context.resources.configuration) }
+                    .map {
+                        val edgeToEdgeHorizontally =
+                            context.resources.getBoolean(R.bool.config_edgeToEdgeBottomSheetDialog)
+                        val width = if (edgeToEdgeHorizontally) MATCH_PARENT else WRAP_CONTENT
 
-    private val onConfigChanged =
-        object : ConfigurationListener {
-            override fun onConfigChanged(newConfig: Configuration?) {
-                super.onConfigChanged(newConfig)
-                setupEdgeToEdge()
-                onConfigurationChanged()
+                        Layout(width, WRAP_CONTENT)
+                    }
             }
         }
+
+        data class Layout(val width: Int, val height: Int)
+    }
 }
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 2b90e64..b80ff38 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
@@ -19,8 +19,6 @@
 import android.net.wifi.WifiManager
 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.log.LogBuffer
 import com.android.systemui.log.LogBufferFactory
 import com.android.systemui.log.table.TableLogBuffer
@@ -44,6 +42,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxyImpl
 import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
 import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModelImpl
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder
@@ -52,12 +52,9 @@
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModelImpl
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryDagger
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryViaTrackerLibDagger
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.DisabledWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryViaTrackerLib
 import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
 import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
 import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository
@@ -90,6 +87,11 @@
         impl: DeviceBasedSatelliteRepositoryImpl
     ): DeviceBasedSatelliteRepository
 
+    @Binds
+    abstract fun deviceBasedSatelliteViewModel(
+        impl: DeviceBasedSatelliteViewModelImpl
+    ): DeviceBasedSatelliteViewModel
+
     @Binds abstract fun wifiRepository(impl: WifiRepositorySwitcher): WifiRepository
 
     @Binds abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
@@ -131,19 +133,15 @@
         impl: CollapsedStatusBarViewBinderImpl
     ): CollapsedStatusBarViewBinder
 
-    @Binds
-    @IntoMap
-    @ClassKey(WifiRepositoryDagger::class)
-    abstract fun bindWifiRepositoryDagger(impl: WifiRepositoryDagger): CoreStartable
-
     companion object {
+
         @Provides
         @SysUISingleton
-        fun provideWifiRepositoryDagger(
+        fun provideRealWifiRepository(
             wifiManager: WifiManager?,
             disabledWifiRepository: DisabledWifiRepository,
             wifiRepositoryImplFactory: WifiRepositoryImpl.Factory,
-        ): WifiRepositoryDagger {
+        ): RealWifiRepository {
             // If we have a null [WifiManager], then the wifi repository should be permanently
             // disabled.
             return if (wifiManager == null) {
@@ -155,36 +153,6 @@
 
         @Provides
         @SysUISingleton
-        fun provideWifiRepositoryViaTrackerLibDagger(
-            wifiManager: WifiManager?,
-            disabledWifiRepository: DisabledWifiRepository,
-            wifiRepositoryFromTrackerLibFactory: WifiRepositoryViaTrackerLib.Factory,
-        ): WifiRepositoryViaTrackerLibDagger {
-            // If we have a null [WifiManager], then the wifi repository should be permanently
-            // disabled.
-            return if (wifiManager == null) {
-                disabledWifiRepository
-            } else {
-                wifiRepositoryFromTrackerLibFactory.create(wifiManager)
-            }
-        }
-
-        @Provides
-        @SysUISingleton
-        fun provideRealWifiRepository(
-            wifiRepository: WifiRepositoryDagger,
-            wifiRepositoryFromTrackerLib: WifiRepositoryViaTrackerLibDagger,
-            flags: FeatureFlags,
-        ): RealWifiRepository {
-            return if (flags.isEnabled(Flags.WIFI_TRACKER_LIB_FOR_WIFI_ICON)) {
-                wifiRepositoryFromTrackerLib
-            } else {
-                wifiRepository
-            }
-        }
-
-        @Provides
-        @SysUISingleton
         @Named(FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON)
         fun provideFirstMobileSubShowingNetworkTypeIconProvider(
             mobileIconsViewModel: MobileIconsViewModel,
@@ -197,16 +165,8 @@
         @Provides
         @SysUISingleton
         @WifiInputLog
-        fun provideWifiInputLogBuffer(factory: LogBufferFactory): LogBuffer {
-            return factory.create("WifiInputLog", 50)
-        }
-
-        @Provides
-        @SysUISingleton
-        @WifiTrackerLibInputLog
-        fun provideWifiTrackerLibInputLogBuffer(factory: LogBufferFactory): LogBuffer {
-            // WifiTrackerLib is pretty noisy, so give it more room than WifiInputLog.
-            return factory.create("WifiTrackerLibInputLog", 200)
+        fun provideWifiLogBuffer(factory: LogBufferFactory): LogBuffer {
+            return factory.create("WifiInputLog", 200)
         }
 
         @Provides
@@ -218,13 +178,6 @@
 
         @Provides
         @SysUISingleton
-        @WifiTrackerLibTableLog
-        fun provideWifiTrackerLibTableLogBuffer(factory: TableLogBufferFactory): TableLogBuffer {
-            return factory.create("WifiTrackerLibTableLog", 100)
-        }
-
-        @Provides
-        @SysUISingleton
         @AirplaneTableLog
         fun provideAirplaneTableLogBuffer(factory: TableLogBufferFactory): TableLogBuffer {
             return factory.create("AirplaneTableLog", 30)
@@ -248,7 +201,7 @@
         @SysUISingleton
         @MobileInputLog
         fun provideMobileInputLogBuffer(factory: LogBufferFactory): LogBuffer {
-            return factory.create("MobileInputLog", 100)
+            return factory.create("MobileInputLog", 300)
         }
 
         @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt
index 6db6944..9ba802c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt
@@ -18,8 +18,8 @@
 
 import javax.inject.Qualifier
 
-/** Wifi logs for inputs into the wifi pipeline. */
-@Qualifier
-@MustBeDocumented
[email protected](AnnotationRetention.RUNTIME)
-annotation class WifiInputLog
+/**
+ * Wifi logs for inputs into
+ * [com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl].
+ */
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class WifiInputLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiTrackerLibInputLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiTrackerLibInputLog.kt
deleted file mode 100644
index b84b01e..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiTrackerLibInputLog.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.dagger
-
-import javax.inject.Qualifier
-
-/** Wifi logs for inputs into [WifiRepositoryViaTrackerLib]. */
-@Qualifier
-@MustBeDocumented
[email protected](AnnotationRetention.RUNTIME)
-annotation class WifiTrackerLibInputLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiTrackerLibTableLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiTrackerLibTableLog.kt
deleted file mode 100644
index 7ca7030..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiTrackerLibTableLog.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.dagger
-
-import javax.inject.Qualifier
-
-/** Wifi logs from [WifiRepositoryViaTrackerLib] in table format. */
-@Qualifier
-@MustBeDocumented
-@Retention(AnnotationRetention.RUNTIME)
-annotation class WifiTrackerLibTableLog
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 3b2930f..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
@@ -18,7 +18,6 @@
 
 import android.os.PersistableBundle
 import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
-import android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT
 import android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL
 import androidx.annotation.VisibleForTesting
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -43,11 +42,10 @@
  * using the default config for logging purposes.
  *
  * NOTE to add new keys to be tracked:
- * 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig] or [IntCarrierConfig]
- * 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config] or
- *    [IntCarrierConfig.config]
- * 3. Add the new wrapped public flow to the list of tracked configs, so they are properly updated
- *    when a new carrier config comes down
+ * 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
  */
 class SystemUiCarrierConfig
 internal constructor(
@@ -68,16 +66,10 @@
     /** Flow tracking the [KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL] config */
     val showOperatorNameInStatusBar: StateFlow<Boolean> = showOperatorName.config
 
-    private val satelliteHysteresisSeconds =
-        IntCarrierConfig(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, defaultConfig)
-    /** Flow tracking the [KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT] config */
-    val satelliteConnectionHysteresisSeconds: StateFlow<Int> = satelliteHysteresisSeconds.config
-
     private val trackedConfigs =
         listOf(
             inflateSignalStrength,
             showOperatorName,
-            satelliteHysteresisSeconds,
         )
 
     /** Ingest a new carrier config, and switch all of the tracked keys over to the new values */
@@ -98,19 +90,15 @@
     override fun toString(): String = trackedConfigs.joinToString { it.toString() }
 }
 
-interface CarrierConfig {
-    fun update(config: PersistableBundle)
-}
-
 /** Extracts [key] from the carrier config, and stores it in a flow */
 private class BooleanCarrierConfig(
     val key: String,
     defaultConfig: PersistableBundle,
-) : CarrierConfig {
+) {
     private val _configValue = MutableStateFlow(defaultConfig.getBoolean(key))
     val config = _configValue.asStateFlow()
 
-    override fun update(config: PersistableBundle) {
+    fun update(config: PersistableBundle) {
         _configValue.value = config.getBoolean(key)
     }
 
@@ -118,20 +106,3 @@
         return "$key=${config.value}"
     }
 }
-
-/** Extracts [key] from the carrier config, and stores it in a flow */
-private class IntCarrierConfig(
-    val key: String,
-    defaultConfig: PersistableBundle,
-) : CarrierConfig {
-    private val _configValue = MutableStateFlow(defaultConfig.getInt(key))
-    val config = _configValue.asStateFlow()
-
-    override fun update(config: PersistableBundle) {
-        _configValue.value = config.getInt(key)
-    }
-
-    override fun toString(): String {
-        return "$key=${config.value}"
-    }
-}
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 8f00b43..2278597 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
@@ -44,6 +44,9 @@
     /** The carrierId for this connection. See [TelephonyManager.getSimCarrierId] */
     val carrierId: StateFlow<Int>
 
+    /** Reflects the value from the carrier config INFLATE_SIGNAL_STRENGTH for this connection */
+    val inflateSignalStrength: StateFlow<Boolean>
+
     /**
      * The table log buffer created for this connection. Will have the name "MobileConnectionLog
      * [subId]"
@@ -141,9 +144,6 @@
      */
     val hasPrioritizedNetworkCapabilities: StateFlow<Boolean>
 
-    /** Duration in seconds of the hysteresis to use when losing satellite connection. */
-    val satelliteConnectionHysteresisSeconds: StateFlow<Int>
-
     /**
      * True if this connection is in emergency callback mode.
      *
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
index af34a57..83d5f2b 100644
--- 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
@@ -43,6 +43,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /**
@@ -67,6 +68,17 @@
             )
             .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value)
 
+    private val _inflateSignalStrength: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    override val inflateSignalStrength =
+        _inflateSignalStrength
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = "inflate",
+                _inflateSignalStrength.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _inflateSignalStrength.value)
+
     private val _isEmergencyOnly = MutableStateFlow(false)
     override val isEmergencyOnly =
         _isEmergencyOnly
@@ -191,7 +203,16 @@
             .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value)
             .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)
 
-    override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS)
+    override val numberOfLevels =
+        _inflateSignalStrength
+            .map { shouldInflate ->
+                if (shouldInflate) {
+                    DEFAULT_NUM_LEVELS + 1
+                } else {
+                    DEFAULT_NUM_LEVELS
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
 
     override val dataEnabled = MutableStateFlow(true)
 
@@ -206,8 +227,6 @@
 
     override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false)
 
-    override val satelliteConnectionHysteresisSeconds = MutableStateFlow(0)
-
     override suspend fun isInEcmMode(): Boolean = false
 
     /**
@@ -226,8 +245,7 @@
 
         _carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID
 
-        numberOfLevels.value =
-            if (event.inflateStrength) DEFAULT_NUM_LEVELS + 1 else DEFAULT_NUM_LEVELS
+        _inflateSignalStrength.value = event.inflateStrength
 
         cdmaRoaming.value = event.roaming
         _isRoaming.value = event.roaming
@@ -258,7 +276,6 @@
         carrierName.value = NetworkNameModel.SubscriptionDerived(CARRIER_MERGED_NAME)
         // TODO(b/276943904): is carrierId a thing with carrier merged networks?
         _carrierId.value = INVALID_SUBSCRIPTION_ID
-        numberOfLevels.value = event.numberOfLevels
         cdmaRoaming.value = false
         _primaryLevel.value = event.level
         _cdmaLevel.value = event.level
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 2bc3bcb..a532e62 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
@@ -165,6 +165,7 @@
 
     override val isRoaming = MutableStateFlow(false).asStateFlow()
     override val carrierId = MutableStateFlow(INVALID_SUBSCRIPTION_ID).asStateFlow()
+    override val inflateSignalStrength = MutableStateFlow(false).asStateFlow()
     override val isEmergencyOnly = MutableStateFlow(false).asStateFlow()
     override val operatorAlphaShort = MutableStateFlow(null).asStateFlow()
     override val isInService = MutableStateFlow(true).asStateFlow()
@@ -186,9 +187,6 @@
      */
     override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false).asStateFlow()
 
-    /** Non-applicable to carrier merged connections. */
-    override val satelliteConnectionHysteresisSeconds = MutableStateFlow(0).asStateFlow()
-
     override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
 
     override suspend fun isInEcmMode(): Boolean =
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 b085d80..41559b2 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
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
+import android.util.IndentingPrintWriter
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.log.table.TableLogBuffer
@@ -24,6 +25,7 @@
 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.MobileConnectionRepository
+import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -291,6 +293,21 @@
             )
             .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.dataEnabled.value)
 
+    override val inflateSignalStrength =
+        activeRepo
+            .flatMapLatest { it.inflateSignalStrength }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = "inflate",
+                initialValue = activeRepo.value.inflateSignalStrength.value,
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.inflateSignalStrength.value
+            )
+
     override val numberOfLevels =
         activeRepo
             .flatMapLatest { it.numberOfLevels }
@@ -334,17 +351,29 @@
                 activeRepo.value.hasPrioritizedNetworkCapabilities.value,
             )
 
-    override val satelliteConnectionHysteresisSeconds =
-        activeRepo
-            .flatMapLatest { it.satelliteConnectionHysteresisSeconds }
-            .stateIn(
-                scope,
-                SharingStarted.WhileSubscribed(),
-                activeRepo.value.satelliteConnectionHysteresisSeconds.value
-            )
-
     override suspend fun isInEcmMode(): Boolean = activeRepo.value.isInEcmMode()
 
+    fun dump(pw: PrintWriter) {
+        val ipw = IndentingPrintWriter(pw, "  ")
+
+        ipw.println("MobileConnectionRepository[$subId]")
+        ipw.increaseIndent()
+
+        ipw.println("carrierMerged=${_isCarrierMerged.value}")
+
+        ipw.print("Type (cellular or carrier merged): ")
+        when (activeRepo.value) {
+            is CarrierMergedConnectionRepository -> ipw.println("Carrier merged")
+            is MobileConnectionRepositoryImpl -> ipw.println("Cellular")
+        }
+
+        ipw.increaseIndent()
+        ipw.println("Provider: ${activeRepo.value}")
+        ipw.decreaseIndent()
+
+        ipw.decreaseIndent()
+    }
+
     class Factory
     @Inject
     constructor(
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 5ab2ae8..b3885d2 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
@@ -302,8 +302,10 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), UnknownNetworkType)
 
+    override val inflateSignalStrength = systemUiCarrierConfig.shouldInflateSignalStrength
+
     override val numberOfLevels =
-        systemUiCarrierConfig.shouldInflateSignalStrength
+        inflateSignalStrength
             .map { shouldInflate ->
                 if (shouldInflate) {
                     DEFAULT_NUM_LEVELS + 1
@@ -448,9 +450,6 @@
             .flowOn(bgDispatcher)
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
-    override val satelliteConnectionHysteresisSeconds: StateFlow<Int> =
-        systemUiCarrierConfig.satelliteConnectionHysteresisSeconds
-
     class Factory
     @Inject
     constructor(
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 a455db2..5d91ef3 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
@@ -26,17 +26,20 @@
 import android.telephony.TelephonyCallback
 import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener
 import android.telephony.TelephonyManager
+import android.util.IndentingPrintWriter
 import androidx.annotation.VisibleForTesting
 import com.android.internal.telephony.PhoneConstants
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.settingslib.SignalIcon.MobileIconGroup
 import com.android.settingslib.mobile.MobileMappings.Config
+import com.android.systemui.Dumpable
 import com.android.systemui.broadcast.BroadcastDispatcher
 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.dump.DumpManager
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.res.R
@@ -52,6 +55,8 @@
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.util.kotlin.pairwise
+import java.io.PrintWriter
+import java.lang.ref.WeakReference
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -97,8 +102,12 @@
     wifiRepository: WifiRepository,
     private val fullMobileRepoFactory: FullMobileConnectionRepository.Factory,
     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
-) : MobileConnectionsRepository {
-    private var subIdRepositoryCache: MutableMap<Int, FullMobileConnectionRepository> =
+    private val dumpManager: DumpManager,
+) : MobileConnectionsRepository, Dumpable {
+
+    // TODO(b/333912012): for now, we are never invalidating the cache. We can do better though
+    private var subIdRepositoryCache:
+        MutableMap<Int, WeakReference<FullMobileConnectionRepository>> =
         mutableMapOf()
 
     private val defaultNetworkName =
@@ -109,6 +118,10 @@
     private val networkNameSeparator: String =
         context.getString(R.string.status_bar_network_name_separator)
 
+    init {
+        dumpManager.registerNormalDumpable("MobileConnectionsRepository", this)
+    }
+
     private val carrierMergedSubId: StateFlow<Int?> =
         combine(
                 wifiRepository.wifiNetwork,
@@ -283,8 +296,10 @@
         getOrCreateRepoForSubId(subId)
 
     private fun getOrCreateRepoForSubId(subId: Int) =
-        subIdRepositoryCache[subId]
-            ?: createRepositoryForSubId(subId).also { subIdRepositoryCache[subId] = it }
+        subIdRepositoryCache[subId]?.get()
+            ?: createRepositoryForSubId(subId).also {
+                subIdRepositoryCache[subId] = WeakReference(it)
+            }
 
     override val mobileIsDefault: StateFlow<Boolean> =
         connectivityRepository.defaultConnections
@@ -374,9 +389,8 @@
     }
 
     private fun updateRepos(newInfos: List<SubscriptionModel>) {
-        dropUnusedReposFromCache(newInfos)
         subIdRepositoryCache.forEach { (subId, repo) ->
-            repo.setIsCarrierMerged(isCarrierMerged(subId))
+            repo.get()?.setIsCarrierMerged(isCarrierMerged(subId))
         }
     }
 
@@ -384,13 +398,6 @@
         return subId == carrierMergedSubId.value
     }
 
-    private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) {
-        // Remove any connection repository from the cache that isn't in the new set of IDs. They
-        // will get garbage collected once their subscribers go away
-        subIdRepositoryCache =
-            subIdRepositoryCache.filter { checkSub(it.key, newInfos) }.toMutableMap()
-    }
-
     /**
      * True if the checked subId is in the list of current subs or the active mobile data subId
      *
@@ -422,6 +429,22 @@
             profileClass = profileClass,
         )
 
+    override fun dump(pw: PrintWriter, args: Array<String>) {
+        val ipw = IndentingPrintWriter(pw, " ")
+        ipw.println("Connection cache:")
+
+        ipw.increaseIndent()
+        subIdRepositoryCache.entries.forEach { (subId, repo) ->
+            ipw.println("$subId: ${repo.get()}")
+        }
+        ipw.decreaseIndent()
+
+        ipw.println("Connections (${subIdRepositoryCache.size} total):")
+        ipw.increaseIndent()
+        subIdRepositoryCache.values.forEach { it.get()?.dump(ipw) }
+        ipw.decreaseIndent()
+    }
+
     companion object {
         private const val LOGGING_PREFIX = "Repo"
     }
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 9d194cf..ed9e405 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
@@ -35,25 +35,18 @@
 import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
 import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.util.kotlin.pairwiseBy
-import kotlin.time.DurationUnit
-import kotlin.time.toDuration
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
 
 interface MobileIconInteractor {
     /** The table log created for this connection */
@@ -269,43 +262,6 @@
             MutableStateFlow(false).asStateFlow()
         }
 
-    private val hysteresisActive = MutableStateFlow(false)
-
-    private val isNonTerrestrialWithHysteresis: StateFlow<Boolean> =
-        combine(isNonTerrestrial, hysteresisActive) { isNonTerrestrial, hysteresisActive ->
-                if (hysteresisActive) {
-                    true
-                } else {
-                    isNonTerrestrial
-                }
-            }
-            .logDiffsForTable(
-                tableLogBuffer = tableLogBuffer,
-                columnName = "isNonTerrestrialWithHysteresis",
-                columnPrefix = "",
-                initialValue = Flags.carrierEnabledSatelliteFlag(),
-            )
-            .stateIn(scope, SharingStarted.Eagerly, Flags.carrierEnabledSatelliteFlag())
-
-    private val lostSatelliteConnection =
-        isNonTerrestrial.pairwiseBy { old, new -> hysteresisActive.value = old && !new }
-
-    init {
-        scope.launch { lostSatelliteConnection.collect() }
-        scope.launch {
-            hysteresisActive.collectLatest {
-                if (it) {
-                    delay(
-                        connectionRepository.satelliteConnectionHysteresisSeconds.value.toDuration(
-                            DurationUnit.SECONDS
-                        )
-                    )
-                    hysteresisActive.value = false
-                }
-            }
-        }
-    }
-
     override val isRoaming: StateFlow<Boolean> =
         combine(
                 connectionRepository.carrierNetworkChangeActive,
@@ -367,8 +323,11 @@
         combine(
                 level,
                 isInService,
-            ) { level, isInService ->
-                if (isInService) level else 0
+                connectionRepository.inflateSignalStrength,
+            ) { level, isInService, inflate ->
+                if (isInService) {
+                    if (inflate) level + 1 else level
+                } else 0
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), 0)
 
@@ -404,7 +363,7 @@
                 showExclamationMark.value,
                 carrierNetworkChangeActive.value,
             )
-        isNonTerrestrialWithHysteresis
+        isNonTerrestrial
             .flatMapLatest { ntn ->
                 if (ntn) {
                     satelliteIcon
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 a0c5618..5f08afd 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
@@ -128,6 +128,8 @@
                                 mobileGroupView,
                                 dotView,
                             )
+
+                            view.requestLayout()
                         }
                     }
 
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 eda5c44..103b0e3 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
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
 
-import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH
+import com.android.settingslib.AccessibilityContentDescriptions
 import com.android.systemui.Flags.statusBarStaticInoutIndicators
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
@@ -50,7 +50,7 @@
     /** True if this view should be visible at all. */
     val isVisible: StateFlow<Boolean>
     val icon: Flow<SignalIconModel>
-    val contentDescription: Flow<ContentDescription>
+    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.Resource?>
@@ -123,7 +123,7 @@
 
     override val icon: Flow<SignalIconModel> = vmProvider.flatMapLatest { it.icon }
 
-    override val contentDescription: Flow<ContentDescription> =
+    override val contentDescription: Flow<ContentDescription?> =
         vmProvider.flatMapLatest { it.contentDescription }
 
     override val roaming: Flow<Boolean> = vmProvider.flatMapLatest { it.roaming }
@@ -206,12 +206,26 @@
 
     override val icon: Flow<SignalIconModel> = iconInteractor.signalLevelIcon
 
-    override val contentDescription: Flow<ContentDescription> = run {
-        val initial = ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[0])
+    override val contentDescription: Flow<ContentDescription?> =
         iconInteractor.signalLevelIcon
-            .map { ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[it.level]) }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
-    }
+            .map {
+                // We expect the signal icon to be cellular here since this is the cellular vm
+                if (it !is SignalIconModel.Cellular) {
+                    null
+                } else {
+                    val resId =
+                        AccessibilityContentDescriptions.getDescriptionForLevel(
+                            it.level,
+                            it.numberOfLevels
+                        )
+                    if (resId != 0) {
+                        ContentDescription.Resource(resId)
+                    } else {
+                        null
+                    }
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
 
     private val showNetworkTypeIcon: Flow<Boolean> =
         combine(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
index 08ed030..054116d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
 import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -41,6 +43,7 @@
     val repo: DeviceBasedSatelliteRepository,
     iconsInteractor: MobileIconsInteractor,
     deviceProvisioningInteractor: DeviceProvisioningInteractor,
+    wifiInteractor: WifiInteractor,
     @Application scope: CoroutineScope,
 ) {
     /** Must be observed by any UI showing Satellite iconography */
@@ -73,6 +76,9 @@
 
     val isDeviceProvisioned: Flow<Boolean> = deviceProvisioningInteractor.isDeviceProvisioned
 
+    val isWifiActive: Flow<Boolean> =
+        wifiInteractor.wifiNetwork.map { it is WifiNetworkModel.Active }
+
     /** When all connections are considered OOS, satellite connectivity is potentially valid */
     val areAllConnectionsOutOfService =
         if (Flags.oemEnabledSatelliteFlag()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
index 40641be..f2255f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
@@ -16,13 +16,16 @@
 
 package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel
 
+import android.content.Context
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.LogLevel
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.dagger.OemSatelliteInputLog
 import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
 import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.seconds
@@ -42,15 +45,30 @@
  * View-Model for the device-based satellite icon. This icon will only show in the status bar if
  * satellite is available AND all other service states are considered OOS.
  */
+interface DeviceBasedSatelliteViewModel {
+    /**
+     * The satellite icon that should be displayed, or null if no satellite icon should be
+     * displayed.
+     */
+    val icon: StateFlow<Icon?>
+
+    /**
+     * The satellite-related text that should be used as the carrier text string when satellite is
+     * active, or null if the carrier text string shouldn't include any satellite information.
+     */
+    val carrierText: StateFlow<String?>
+}
+
 @OptIn(ExperimentalCoroutinesApi::class)
-class DeviceBasedSatelliteViewModel
+class DeviceBasedSatelliteViewModelImpl
 @Inject
 constructor(
+    context: Context,
     interactor: DeviceBasedSatelliteInteractor,
     @Application scope: CoroutineScope,
     airplaneModeRepository: AirplaneModeRepository,
     @OemSatelliteInputLog logBuffer: LogBuffer,
-) {
+) : DeviceBasedSatelliteViewModel {
     private val shouldShowIcon: Flow<Boolean> =
         interactor.areAllConnectionsOutOfService.flatMapLatest { allOos ->
             if (!allOos) {
@@ -59,9 +77,10 @@
                 combine(
                     interactor.isSatelliteAllowed,
                     interactor.isDeviceProvisioned,
+                    interactor.isWifiActive,
                     airplaneModeRepository.isAirplaneMode
-                ) { isSatelliteAllowed, isDeviceProvisioned, isAirplaneMode ->
-                    isSatelliteAllowed && isDeviceProvisioned && !isAirplaneMode
+                ) { isSatelliteAllowed, isDeviceProvisioned, isWifiActive, isAirplaneMode ->
+                    isSatelliteAllowed && isDeviceProvisioned && !isWifiActive && !isAirplaneMode
                 }
             }
         }
@@ -86,7 +105,7 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
-    val icon: StateFlow<Icon?> =
+    override val icon: StateFlow<Icon?> =
         combine(
                 shouldActuallyShowIcon,
                 interactor.connectionState,
@@ -100,6 +119,26 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), null)
 
+    override val carrierText: StateFlow<String?> =
+        combine(
+                shouldActuallyShowIcon,
+                interactor.connectionState,
+            ) { shouldShow, connectionState ->
+                if (shouldShow) {
+                    when (connectionState) {
+                        SatelliteConnectionState.Connected ->
+                            context.getString(R.string.satellite_connected_carrier_text)
+                        SatelliteConnectionState.On ->
+                            context.getString(R.string.satellite_not_connected_carrier_text)
+                        SatelliteConnectionState.Off,
+                        SatelliteConnectionState.Unknown -> null
+                    }
+                } else {
+                    null
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+
     companion object {
         private const val TAG = "DeviceBasedSatelliteViewModel"
         private val DELAY_DURATION = 10.seconds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
index 52a6d8c..cc87e8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
@@ -19,6 +19,9 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
+import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
@@ -77,15 +80,13 @@
     @Application coroutineScope: CoroutineScope,
 ) : CollapsedStatusBarViewModel {
     override val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean> =
-        keyguardTransitionInteractor.lockscreenToOccludedTransition
-            .map {
-                it.transitionState == TransitionState.STARTED ||
-                    it.transitionState == TransitionState.RUNNING
-            }
+        keyguardTransitionInteractor
+            .isInTransition(LOCKSCREEN, OCCLUDED)
             .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false)
 
     override val transitionFromLockscreenToDreamStartedEvent: Flow<Unit> =
-        keyguardTransitionInteractor.lockscreenToDreamingTransition
+        keyguardTransitionInteractor
+            .transition(LOCKSCREEN, DREAMING)
             .filter { it.transitionState == TransitionState.STARTED }
             .map {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index b22e09e..fc7a672 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.pipeline.wifi.data.repository
 
-import com.android.systemui.CoreStartable
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
@@ -80,8 +79,3 @@
  * repository.
  */
 interface RealWifiRepository : WifiRepository
-
-/** Used only by Dagger to bind [WifiRepositoryImpl]. */
-interface WifiRepositoryDagger : RealWifiRepository, CoreStartable
-/** Used only by Dagger to bind [WifiRepositoryViaTrackerLib]. */
-interface WifiRepositoryViaTrackerLibDagger : RealWifiRepository
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 ca042e2..af6e8a0 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
@@ -25,7 +25,6 @@
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
 import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt
index cfdbe4a..b79fb9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt
@@ -18,8 +18,7 @@
 
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryDagger
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryViaTrackerLibDagger
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
 import javax.inject.Inject
@@ -34,10 +33,7 @@
  * wifi information.
  */
 @SysUISingleton
-class DisabledWifiRepository @Inject constructor() :
-    WifiRepositoryDagger, WifiRepositoryViaTrackerLibDagger {
-    override fun start() {}
-
+class DisabledWifiRepository @Inject constructor() : RealWifiRepository {
     override val isWifiEnabled: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
 
     override val isWifiDefault: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt
deleted file mode 100644
index 67dd32f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod
-
-import android.annotation.SuppressLint
-import android.net.wifi.ScanResult
-import android.net.wifi.WifiManager
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.logDiffsForTable
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
-import java.util.concurrent.Executor
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.asExecutor
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.stateIn
-
-/**
- * Object to provide shared helper functions between [WifiRepositoryImpl] and
- * [WifiRepositoryViaTrackerLib].
- */
-object WifiRepositoryHelper {
-    /** Creates a flow that fetches the [DataActivityModel] from [WifiManager]. */
-    fun createActivityFlow(
-        wifiManager: WifiManager,
-        @Main mainExecutor: Executor,
-        scope: CoroutineScope,
-        tableLogBuffer: TableLogBuffer,
-        inputLogger: (String) -> Unit,
-    ): StateFlow<DataActivityModel> {
-        return conflatedCallbackFlow {
-                val callback =
-                    WifiManager.TrafficStateCallback { state ->
-                        inputLogger.invoke(prettyPrintActivity(state))
-                        trySend(state.toWifiDataActivityModel())
-                    }
-                wifiManager.registerTrafficStateCallback(mainExecutor, callback)
-                awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
-            }
-            .logDiffsForTable(
-                tableLogBuffer,
-                columnPrefix = ACTIVITY_PREFIX,
-                initialValue = ACTIVITY_DEFAULT,
-            )
-            .stateIn(
-                scope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = ACTIVITY_DEFAULT,
-            )
-    }
-
-    /**
-     * Creates a flow that listens for new [ScanResult]s from [WifiManager]. Does not request a scan
-     */
-    fun createNetworkScanFlow(
-        wifiManager: WifiManager,
-        scope: CoroutineScope,
-        @Background dispatcher: CoroutineDispatcher,
-        inputLogger: () -> Unit,
-    ): StateFlow<List<WifiScanEntry>> {
-        return conflatedCallbackFlow {
-                val callback =
-                    object : WifiManager.ScanResultsCallback() {
-                        @SuppressLint("MissingPermission")
-                        override fun onScanResultsAvailable() {
-                            inputLogger.invoke()
-                            trySend(wifiManager.scanResults.toModel())
-                        }
-                    }
-
-                wifiManager.registerScanResultsCallback(dispatcher.asExecutor(), callback)
-
-                awaitClose { wifiManager.unregisterScanResultsCallback(callback) }
-            }
-            .stateIn(scope, SharingStarted.Eagerly, emptyList())
-    }
-
-    private fun List<ScanResult>.toModel(): List<WifiScanEntry> = map { WifiScanEntry(it.SSID) }
-
-    // TODO(b/292534484): This print should only be done in [MessagePrinter] part of the log buffer.
-    private fun prettyPrintActivity(activity: Int): String {
-        return when (activity) {
-            WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE -> "NONE"
-            WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN -> "IN"
-            WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT -> "OUT"
-            WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT -> "INOUT"
-            else -> "INVALID"
-        }
-    }
-
-    private const val ACTIVITY_PREFIX = "wifiActivity"
-    val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
-}
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 59ef884..20e44e7 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
@@ -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.
@@ -17,309 +17,447 @@
 package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod
 
 import android.annotation.SuppressLint
-import android.content.IntentFilter
-import android.net.ConnectivityManager
-import android.net.Network
-import android.net.NetworkCapabilities
-import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
-import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
-import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
-import android.net.NetworkCapabilities.TRANSPORT_WIFI
-import android.net.NetworkRequest
-import android.net.wifi.WifiInfo
+import android.net.wifi.ScanResult
 import android.net.wifi.WifiManager
 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import com.android.systemui.broadcast.BroadcastDispatcher
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
+import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
+import com.android.systemui.statusbar.pipeline.dagger.WifiInputLog
 import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
-import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.getMainOrUnderlyingWifiInfo
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
+import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.CARRIER_MERGED_INVALID_SUB_ID_REASON
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_DEFAULT
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_ENABLED
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryDagger
-import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Inactive.toHotspotDeviceType
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
+import com.android.wifitrackerlib.HotspotNetworkEntry
+import com.android.wifitrackerlib.MergedCarrierEntry
+import com.android.wifitrackerlib.WifiEntry
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE
+import com.android.wifitrackerlib.WifiPickerTracker
 import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.asExecutor
 import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.flow.merge
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
-/** Real implementation of [WifiRepository]. */
-@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
+/**
+ * A real implementation of [WifiRepository] that uses [com.android.wifitrackerlib] as the source of
+ * truth for wifi information.
+ */
 @SysUISingleton
-@SuppressLint("MissingPermission")
 class WifiRepositoryImpl
 @Inject
 constructor(
-    broadcastDispatcher: BroadcastDispatcher,
-    connectivityManager: ConnectivityManager,
-    connectivityRepository: ConnectivityRepository,
-    logger: WifiInputLogger,
-    @WifiTableLog wifiTableLogBuffer: TableLogBuffer,
-    @Main mainExecutor: Executor,
-    @Background private val bgDispatcher: CoroutineDispatcher,
+    featureFlags: FeatureFlags,
     @Application private val scope: CoroutineScope,
+    @Main private val mainExecutor: Executor,
+    @Background private val bgDispatcher: CoroutineDispatcher,
+    private val wifiPickerTrackerFactory: WifiPickerTrackerFactory,
     private val wifiManager: WifiManager,
-) : WifiRepositoryDagger {
+    @WifiInputLog private val inputLogger: LogBuffer,
+    @WifiTableLog private val tableLogger: TableLogBuffer,
+) : RealWifiRepository, LifecycleOwner {
 
-    override fun start() {
-        // There are two possible [WifiRepository] implementations: This class (old) and
-        // [WifiRepositoryFromTrackerLib] (new). While we migrate to the new class, we want this old
-        // class to still be running in the background so that we can collect logs and compare
-        // discrepancies. This #start method collects on the flows to ensure that the logs are
-        // collected.
-        scope.launch { isWifiEnabled.collect {} }
-        scope.launch { isWifiDefault.collect {} }
-        scope.launch { wifiNetwork.collect {} }
-        scope.launch { wifiActivity.collect {} }
+    override val lifecycle =
+        LifecycleRegistry(this).also {
+            mainExecutor.execute { it.currentState = Lifecycle.State.CREATED }
+        }
+
+    private val isInstantTetherEnabled = featureFlags.isEnabled(Flags.INSTANT_TETHER)
+
+    private var wifiPickerTracker: WifiPickerTracker? = null
+
+    private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> = run {
+        var current =
+            WifiPickerTrackerInfo(
+                state = WIFI_STATE_DEFAULT,
+                isDefault = false,
+                primaryNetwork = WIFI_NETWORK_DEFAULT,
+                secondaryNetworks = emptyList(),
+            )
+        callbackFlow {
+                val callback =
+                    object : WifiPickerTracker.WifiPickerTrackerCallback {
+                        override fun onWifiEntriesChanged() {
+                            val connectedEntry = wifiPickerTracker.mergedOrPrimaryConnection
+                            logOnWifiEntriesChanged(connectedEntry)
+
+                            val secondaryNetworks =
+                                if (featureFlags.isEnabled(Flags.WIFI_SECONDARY_NETWORKS)) {
+                                    val activeNetworks =
+                                        wifiPickerTracker?.activeWifiEntries ?: emptyList()
+                                    activeNetworks
+                                        .filter { it != connectedEntry && !it.isPrimaryNetwork }
+                                        .map { it.toWifiNetworkModel() }
+                                } else {
+                                    emptyList()
+                                }
+
+                            // [WifiPickerTracker.connectedWifiEntry] will return the same instance
+                            // but with updated internals. For example, when its validation status
+                            // changes from false to true, the same instance is re-used but with the
+                            // validated field updated.
+                            //
+                            // Because it's the same instance, the flow won't re-emit the value
+                            // (even though the internals have changed). So, we need to transform it
+                            // into our internal model immediately. [toWifiNetworkModel] always
+                            // returns a new instance, so the flow is guaranteed to emit.
+                            send(
+                                newPrimaryNetwork = connectedEntry?.toPrimaryWifiNetworkModel()
+                                        ?: WIFI_NETWORK_DEFAULT,
+                                newSecondaryNetworks = secondaryNetworks,
+                                newIsDefault = connectedEntry?.isDefaultNetwork ?: false,
+                            )
+                        }
+
+                        override fun onWifiStateChanged() {
+                            val state = wifiPickerTracker?.wifiState
+                            logOnWifiStateChanged(state)
+                            send(newState = state ?: WIFI_STATE_DEFAULT)
+                        }
+
+                        override fun onNumSavedNetworksChanged() {}
+
+                        override fun onNumSavedSubscriptionsChanged() {}
+
+                        private fun send(
+                            newState: Int = current.state,
+                            newIsDefault: Boolean = current.isDefault,
+                            newPrimaryNetwork: WifiNetworkModel = current.primaryNetwork,
+                            newSecondaryNetworks: List<WifiNetworkModel> =
+                                current.secondaryNetworks,
+                        ) {
+                            val new =
+                                WifiPickerTrackerInfo(
+                                    newState,
+                                    newIsDefault,
+                                    newPrimaryNetwork,
+                                    newSecondaryNetworks,
+                                )
+                            current = new
+                            trySend(new)
+                        }
+                    }
+
+                wifiPickerTracker =
+                    wifiPickerTrackerFactory.create(lifecycle, callback, "WifiRepository").apply {
+                        // By default, [WifiPickerTracker] will scan to see all available wifi
+                        // networks in the area. Because SysUI only needs to display the
+                        // **connected** network, we don't need scans to be running (and in fact,
+                        // running scans is costly and should be avoided whenever possible).
+                        this?.disableScanning()
+                    }
+                // The lifecycle must be STARTED in order for the callback to receive events.
+                mainExecutor.execute { lifecycle.currentState = Lifecycle.State.STARTED }
+                awaitClose {
+                    mainExecutor.execute { lifecycle.currentState = Lifecycle.State.CREATED }
+                }
+            }
+            .stateIn(scope, SharingStarted.Eagerly, current)
     }
 
-    private val wifiStateChangeEvents: Flow<Unit> =
-        broadcastDispatcher
-            .broadcastFlow(IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION))
-            .onEach { logger.logIntent("WIFI_STATE_CHANGED_ACTION") }
-
-    private val wifiNetworkChangeEvents: MutableSharedFlow<Unit> =
-        MutableSharedFlow(extraBufferCapacity = 1)
-
-    // Because [WifiManager] doesn't expose a wifi enabled change listener, we do it
-    // internally by fetching [WifiManager.isWifiEnabled] whenever we think the state may
-    // have changed.
     override val isWifiEnabled: StateFlow<Boolean> =
-        merge(wifiNetworkChangeEvents, wifiStateChangeEvents)
-            .onStart { emit(Unit) }
-            .mapLatest { isWifiEnabled() }
+        wifiPickerTrackerInfo
+            .map { it.state == WifiManager.WIFI_STATE_ENABLED }
             .distinctUntilChanged()
             .logDiffsForTable(
-                wifiTableLogBuffer,
+                tableLogger,
                 columnPrefix = "",
                 columnName = COL_NAME_IS_ENABLED,
                 initialValue = false,
             )
-            .stateIn(
-                scope = scope,
-                started = SharingStarted.Eagerly,
-                initialValue = false,
-            )
+            .stateIn(scope, SharingStarted.Eagerly, false)
 
-    // [WifiManager.isWifiEnabled] is a blocking IPC call, so fetch it in the background.
-    private suspend fun isWifiEnabled(): Boolean =
-        withContext(bgDispatcher) { wifiManager.isWifiEnabled }
-
-    override val isWifiDefault: StateFlow<Boolean> =
-        connectivityRepository.defaultConnections
-            // TODO(b/274493701): Should wifi be considered default if it's carrier merged?
-            .map { it.wifi.isDefault || it.carrierMerged.isDefault }
+    override val wifiNetwork: StateFlow<WifiNetworkModel> =
+        wifiPickerTrackerInfo
+            .map { it.primaryNetwork }
             .distinctUntilChanged()
             .logDiffsForTable(
-                wifiTableLogBuffer,
+                tableLogger,
+                columnPrefix = "",
+                initialValue = WIFI_NETWORK_DEFAULT,
+            )
+            .stateIn(scope, SharingStarted.Eagerly, WIFI_NETWORK_DEFAULT)
+
+    override val secondaryNetworks: StateFlow<List<WifiNetworkModel>> =
+        wifiPickerTrackerInfo
+            .map { it.secondaryNetworks }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                tableLogger,
+                columnPrefix = "",
+                columnName = "secondaryNetworks",
+                initialValue = emptyList(),
+            )
+            .stateIn(scope, SharingStarted.Eagerly, emptyList())
+
+    /**
+     * [WifiPickerTracker.getConnectedWifiEntry] stores a [MergedCarrierEntry] separately from the
+     * [WifiEntry] for the primary connection. Therefore, we have to prefer the carrier-merged entry
+     * if it exists, falling back on the connected entry if null
+     */
+    private val WifiPickerTracker?.mergedOrPrimaryConnection: WifiEntry?
+        get() {
+            val mergedEntry: MergedCarrierEntry? = this?.mergedCarrierEntry
+            return if (mergedEntry != null && mergedEntry.isDefaultNetwork) {
+                mergedEntry
+            } else {
+                this?.connectedWifiEntry
+            }
+        }
+
+    /**
+     * Converts WifiTrackerLib's [WifiEntry] into our internal model only if the entry is the
+     * primary network. Returns an inactive network if it's not primary.
+     */
+    private fun WifiEntry.toPrimaryWifiNetworkModel(): WifiNetworkModel {
+        return if (!this.isPrimaryNetwork) {
+            WIFI_NETWORK_DEFAULT
+        } else {
+            this.toWifiNetworkModel()
+        }
+    }
+
+    /** Converts WifiTrackerLib's [WifiEntry] into our internal model. */
+    private fun WifiEntry.toWifiNetworkModel(): WifiNetworkModel {
+        return if (this is MergedCarrierEntry) {
+            this.convertCarrierMergedToModel()
+        } else {
+            this.convertNormalToModel()
+        }
+    }
+
+    private fun MergedCarrierEntry.convertCarrierMergedToModel(): WifiNetworkModel {
+        return if (this.subscriptionId == INVALID_SUBSCRIPTION_ID) {
+            WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
+        } else {
+            WifiNetworkModel.CarrierMerged(
+                networkId = NETWORK_ID,
+                subscriptionId = this.subscriptionId,
+                level = this.level,
+                // WifiManager APIs to calculate the signal level start from 0, so
+                // maxSignalLevel + 1 represents the total level buckets count.
+                numberOfLevels = wifiManager.maxSignalLevel + 1,
+            )
+        }
+    }
+
+    private fun WifiEntry.convertNormalToModel(): WifiNetworkModel {
+        if (this.level == WIFI_LEVEL_UNREACHABLE || this.level !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX) {
+            // If our level means the network is unreachable or the level is otherwise invalid, we
+            // don't have an active network.
+            return WifiNetworkModel.Inactive
+        }
+
+        val hotspotDeviceType =
+            if (isInstantTetherEnabled && this is HotspotNetworkEntry) {
+                this.deviceType.toHotspotDeviceType()
+            } else {
+                WifiNetworkModel.HotspotDeviceType.NONE
+            }
+
+        return WifiNetworkModel.Active(
+            networkId = NETWORK_ID,
+            isValidated = this.hasInternetAccess(),
+            level = this.level,
+            ssid = this.title,
+            hotspotDeviceType = hotspotDeviceType,
+            // With WifiTrackerLib, [WifiEntry.title] will appropriately fetch the  SSID for
+            // typical wifi networks *and* passpoint/OSU APs. So, the AP-specific values can
+            // always be false/null in this repository.
+            // TODO(b/292534484): Remove these fields from the wifi network model once this
+            //  repository is fully enabled.
+            isPasspointAccessPoint = false,
+            isOnlineSignUpForPasspointAccessPoint = false,
+            passpointProviderFriendlyName = null,
+        )
+    }
+
+    override val isWifiDefault: StateFlow<Boolean> =
+        wifiPickerTrackerInfo
+            .map { it.isDefault }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                tableLogger,
                 columnPrefix = "",
                 columnName = COL_NAME_IS_DEFAULT,
                 initialValue = false,
             )
-            .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
+            .stateIn(scope, SharingStarted.Eagerly, false)
 
-    override val wifiNetwork: StateFlow<WifiNetworkModel> =
+    override val wifiActivity: StateFlow<DataActivityModel> =
         conflatedCallbackFlow {
-                var currentWifi: WifiNetworkModel = WIFI_NETWORK_DEFAULT
-
                 val callback =
-                    object : ConnectivityManager.NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
-                        override fun onCapabilitiesChanged(
-                            network: Network,
-                            networkCapabilities: NetworkCapabilities
-                        ) {
-                            logger.logOnCapabilitiesChanged(
-                                network,
-                                networkCapabilities,
-                                isDefaultNetworkCallback = false,
-                            )
-
-                            wifiNetworkChangeEvents.tryEmit(Unit)
-
-                            val wifiInfo =
-                                networkCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
-                            if (wifiInfo?.isPrimary == true) {
-                                val wifiNetworkModel =
-                                    createWifiNetworkModel(
-                                        wifiInfo,
-                                        network,
-                                        networkCapabilities,
-                                        wifiManager,
-                                    )
-                                currentWifi = wifiNetworkModel
-                                trySend(wifiNetworkModel)
-                            }
-                        }
-
-                        override fun onLost(network: Network) {
-                            logger.logOnLost(network, isDefaultNetworkCallback = false)
-
-                            wifiNetworkChangeEvents.tryEmit(Unit)
-
-                            val wifi = currentWifi
-                            if (
-                                (wifi is WifiNetworkModel.Active &&
-                                    wifi.networkId == network.getNetId()) ||
-                                    (wifi is WifiNetworkModel.CarrierMerged &&
-                                        wifi.networkId == network.getNetId())
-                            ) {
-                                val newNetworkModel = WifiNetworkModel.Inactive
-                                currentWifi = newNetworkModel
-                                trySend(newNetworkModel)
-                            }
-                        }
+                    WifiManager.TrafficStateCallback { state ->
+                        logActivity(state)
+                        trySend(state.toWifiDataActivityModel())
                     }
-
-                connectivityManager.registerNetworkCallback(WIFI_NETWORK_CALLBACK_REQUEST, callback)
-
-                awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
+                wifiManager.registerTrafficStateCallback(mainExecutor, callback)
+                awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
             }
-            .distinctUntilChanged()
             .logDiffsForTable(
-                wifiTableLogBuffer,
-                columnPrefix = "",
-                initialValue = WIFI_NETWORK_DEFAULT,
+                tableLogger,
+                columnPrefix = ACTIVITY_PREFIX,
+                initialValue = ACTIVITY_DEFAULT,
             )
-            // There will be multiple wifi icons in different places that will frequently
-            // subscribe/unsubscribe to flows as the views attach/detach. Using [stateIn] ensures
-            // that new subscribes will get the latest value immediately upon subscription.
-            // Otherwise, the views could show stale data. See b/244173280.
             .stateIn(
                 scope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = WIFI_NETWORK_DEFAULT,
+                initialValue = ACTIVITY_DEFAULT,
             )
 
-    // Secondary networks can only be supported by [WifiRepositoryViaTrackerLib].
-    override val secondaryNetworks: StateFlow<List<WifiNetworkModel>> =
-        MutableStateFlow(emptyList<WifiNetworkModel>()).asStateFlow()
-
-    override val wifiActivity: StateFlow<DataActivityModel> =
-        WifiRepositoryHelper.createActivityFlow(
-            wifiManager,
-            mainExecutor,
-            scope,
-            wifiTableLogBuffer,
-            logger::logActivity,
-        )
-
     override val wifiScanResults: StateFlow<List<WifiScanEntry>> =
-        WifiRepositoryHelper.createNetworkScanFlow(
-            wifiManager,
-            scope,
-            bgDispatcher,
-            logger::logScanResults
-        )
+        conflatedCallbackFlow {
+                val callback =
+                    object : WifiManager.ScanResultsCallback() {
+                        @SuppressLint("MissingPermission")
+                        override fun onScanResultsAvailable() {
+                            logScanResults()
+                            trySend(wifiManager.scanResults.toModel())
+                        }
+                    }
 
-    companion object {
-        // Start out with no known wifi network.
-        // Note: [WifiStatusTracker] (the old implementation of connectivity logic) does do an
-        // initial fetch to get a starting wifi network. But, it uses a deprecated API
-        // [WifiManager.getConnectionInfo()], and the deprecation doc indicates to just use
-        // [ConnectivityManager.NetworkCallback] results instead. So, for now we'll just rely on the
-        // NetworkCallback inside [wifiNetwork] for our wifi network information.
-        val WIFI_NETWORK_DEFAULT = WifiNetworkModel.Inactive
+                wifiManager.registerScanResultsCallback(bgDispatcher.asExecutor(), callback)
 
-        const val WIFI_STATE_DEFAULT = WifiManager.WIFI_STATE_DISABLED
-
-        private fun createWifiNetworkModel(
-            wifiInfo: WifiInfo,
-            network: Network,
-            networkCapabilities: NetworkCapabilities,
-            wifiManager: WifiManager,
-        ): WifiNetworkModel {
-            return if (wifiInfo.isCarrierMerged) {
-                if (wifiInfo.subscriptionId == INVALID_SUBSCRIPTION_ID) {
-                    WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
-                } else {
-                    WifiNetworkModel.CarrierMerged(
-                        networkId = network.getNetId(),
-                        subscriptionId = wifiInfo.subscriptionId,
-                        level = wifiManager.calculateSignalLevel(wifiInfo.rssi),
-                        // The WiFi signal level returned by WifiManager#calculateSignalLevel start
-                        // from 0, so WifiManager#getMaxSignalLevel + 1 represents the total level
-                        // buckets count.
-                        numberOfLevels = wifiManager.maxSignalLevel + 1,
-                    )
-                }
-            } else {
-                WifiNetworkModel.Active(
-                    network.getNetId(),
-                    isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED),
-                    level = wifiManager.calculateSignalLevel(wifiInfo.rssi),
-                    wifiInfo.ssid,
-                    // This repository doesn't support any hotspot information.
-                    WifiNetworkModel.HotspotDeviceType.NONE,
-                    wifiInfo.isPasspointAp,
-                    wifiInfo.isOsuAp,
-                    wifiInfo.passpointProviderFriendlyName
-                )
+                awaitClose { wifiManager.unregisterScanResultsCallback(callback) }
             }
-        }
+            .stateIn(scope, SharingStarted.Eagerly, emptyList())
 
-        private val WIFI_NETWORK_CALLBACK_REQUEST: NetworkRequest =
-            NetworkRequest.Builder()
-                .clearCapabilities()
-                .addCapability(NET_CAPABILITY_NOT_VPN)
-                .addTransportType(TRANSPORT_WIFI)
-                .addTransportType(TRANSPORT_CELLULAR)
-                .build()
+    private fun List<ScanResult>.toModel(): List<WifiScanEntry> = map { WifiScanEntry(it.SSID) }
+
+    private fun logOnWifiEntriesChanged(connectedEntry: WifiEntry?) {
+        inputLogger.log(
+            TAG,
+            LogLevel.DEBUG,
+            { str1 = connectedEntry.toString() },
+            { "onWifiEntriesChanged. ConnectedEntry=$str1" },
+        )
     }
 
+    private fun logOnWifiStateChanged(state: Int?) {
+        inputLogger.log(
+            TAG,
+            LogLevel.DEBUG,
+            { int1 = state ?: -1 },
+            { "onWifiStateChanged. State=${if (int1 == -1) null else int1}" },
+        )
+    }
+
+    private fun logActivity(activity: Int) {
+        inputLogger.log(
+            TAG,
+            LogLevel.DEBUG,
+            { str1 = prettyPrintActivity(activity) },
+            { "onActivityChanged: $str1" }
+        )
+    }
+
+    // TODO(b/292534484): This print should only be done in [MessagePrinter] part of the log buffer.
+    private fun prettyPrintActivity(activity: Int): String {
+        return when (activity) {
+            WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE -> "NONE"
+            WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN -> "IN"
+            WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT -> "OUT"
+            WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT -> "INOUT"
+            else -> "INVALID"
+        }
+    }
+
+    private fun logScanResults() =
+        inputLogger.log(TAG, LogLevel.DEBUG, {}, { "onScanResultsAvailable" })
+
+    /**
+     * Data class storing all the information fetched from [WifiPickerTracker].
+     *
+     * Used so that we only register a single callback on [WifiPickerTracker].
+     */
+    data class WifiPickerTrackerInfo(
+        /** The current wifi state. See [WifiManager.getWifiState]. */
+        val state: Int,
+        /** True if wifi is currently the default connection and false otherwise. */
+        val isDefault: Boolean,
+        /** The currently primary wifi network. */
+        val primaryNetwork: WifiNetworkModel,
+        /** The current secondary network(s), if any. Specifically excludes the primary network. */
+        val secondaryNetworks: List<WifiNetworkModel>
+    )
+
     @SysUISingleton
     class Factory
     @Inject
     constructor(
-        private val broadcastDispatcher: BroadcastDispatcher,
-        private val connectivityManager: ConnectivityManager,
-        private val connectivityRepository: ConnectivityRepository,
-        private val logger: WifiInputLogger,
-        @WifiTableLog private val wifiTableLogBuffer: TableLogBuffer,
+        private val featureFlags: FeatureFlags,
+        @Application private val scope: CoroutineScope,
         @Main private val mainExecutor: Executor,
         @Background private val bgDispatcher: CoroutineDispatcher,
-        @Application private val scope: CoroutineScope,
+        private val wifiPickerTrackerFactory: WifiPickerTrackerFactory,
+        @WifiInputLog private val inputLogger: LogBuffer,
+        @WifiTableLog private val tableLogger: TableLogBuffer,
     ) {
         fun create(wifiManager: WifiManager): WifiRepositoryImpl {
             return WifiRepositoryImpl(
-                broadcastDispatcher,
-                connectivityManager,
-                connectivityRepository,
-                logger,
-                wifiTableLogBuffer,
+                featureFlags,
+                scope,
                 mainExecutor,
                 bgDispatcher,
-                scope,
+                wifiPickerTrackerFactory,
                 wifiManager,
+                inputLogger,
+                tableLogger,
             )
         }
     }
+
+    companion object {
+        // Start out with no known wifi network.
+        @VisibleForTesting val WIFI_NETWORK_DEFAULT = WifiNetworkModel.Inactive
+
+        private const val WIFI_STATE_DEFAULT = WifiManager.WIFI_STATE_DISABLED
+
+        private const val ACTIVITY_PREFIX = "wifiActivity"
+        val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
+
+        private const val TAG = "WifiTrackerLibInputLog"
+
+        /**
+         * [WifiNetworkModel.Active.networkId] is only used at the repository layer. It's used by
+         * [WifiRepositoryImpl], which tracks the ID in order to correctly apply the framework
+         * callbacks within the repository.
+         *
+         * Since this class does not need to manually apply framework callbacks and since the
+         * network ID is not used beyond the repository, it's safe to use an invalid ID in this
+         * repository.
+         *
+         * The [WifiNetworkModel.Active.networkId] field should be deleted once we've fully migrated
+         * to [WifiRepositoryImpl].
+         */
+        private const val NETWORK_ID = -1
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
deleted file mode 100644
index 1670dd3..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod
-
-import android.net.wifi.WifiManager
-import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.LifecycleRegistry
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.core.LogLevel
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.logDiffsForTable
-import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
-import com.android.systemui.statusbar.pipeline.dagger.WifiTrackerLibInputLog
-import com.android.systemui.statusbar.pipeline.dagger.WifiTrackerLibTableLog
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.CARRIER_MERGED_INVALID_SUB_ID_REASON
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_DEFAULT
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_ENABLED
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryViaTrackerLibDagger
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_STATE_DEFAULT
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Inactive.toHotspotDeviceType
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
-import com.android.wifitrackerlib.HotspotNetworkEntry
-import com.android.wifitrackerlib.MergedCarrierEntry
-import com.android.wifitrackerlib.WifiEntry
-import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX
-import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN
-import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE
-import com.android.wifitrackerlib.WifiPickerTracker
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
-
-/**
- * An implementation of [WifiRepository] that uses [com.android.wifitrackerlib] as the source of
- * truth for wifi information.
- *
- * Serves as a possible replacement for [WifiRepositoryImpl]. See b/292534484.
- */
-@SysUISingleton
-class WifiRepositoryViaTrackerLib
-@Inject
-constructor(
-    featureFlags: FeatureFlags,
-    @Application private val scope: CoroutineScope,
-    @Main private val mainExecutor: Executor,
-    @Background private val bgDispatcher: CoroutineDispatcher,
-    private val wifiPickerTrackerFactory: WifiPickerTrackerFactory,
-    private val wifiManager: WifiManager,
-    @WifiTrackerLibInputLog private val inputLogger: LogBuffer,
-    @WifiTrackerLibTableLog private val wifiTrackerLibTableLogBuffer: TableLogBuffer,
-) : WifiRepositoryViaTrackerLibDagger, LifecycleOwner {
-
-    override val lifecycle =
-        LifecycleRegistry(this).also {
-            mainExecutor.execute { it.currentState = Lifecycle.State.CREATED }
-        }
-
-    private val isInstantTetherEnabled = featureFlags.isEnabled(Flags.INSTANT_TETHER)
-
-    private var wifiPickerTracker: WifiPickerTracker? = null
-
-    private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> = run {
-        var current =
-            WifiPickerTrackerInfo(
-                state = WIFI_STATE_DEFAULT,
-                isDefault = false,
-                primaryNetwork = WIFI_NETWORK_DEFAULT,
-                secondaryNetworks = emptyList(),
-            )
-        callbackFlow {
-                val callback =
-                    object : WifiPickerTracker.WifiPickerTrackerCallback {
-                        override fun onWifiEntriesChanged() {
-                            val connectedEntry = wifiPickerTracker.mergedOrPrimaryConnection
-                            logOnWifiEntriesChanged(connectedEntry)
-
-                            val secondaryNetworks =
-                                if (featureFlags.isEnabled(Flags.WIFI_SECONDARY_NETWORKS)) {
-                                    val activeNetworks =
-                                        wifiPickerTracker?.activeWifiEntries ?: emptyList()
-                                    activeNetworks
-                                        .filter { it != connectedEntry && !it.isPrimaryNetwork }
-                                        .map { it.toWifiNetworkModel() }
-                                } else {
-                                    emptyList()
-                                }
-
-                            // [WifiPickerTracker.connectedWifiEntry] will return the same instance
-                            // but with updated internals. For example, when its validation status
-                            // changes from false to true, the same instance is re-used but with the
-                            // validated field updated.
-                            //
-                            // Because it's the same instance, the flow won't re-emit the value
-                            // (even though the internals have changed). So, we need to transform it
-                            // into our internal model immediately. [toWifiNetworkModel] always
-                            // returns a new instance, so the flow is guaranteed to emit.
-                            send(
-                                newPrimaryNetwork = connectedEntry?.toPrimaryWifiNetworkModel()
-                                        ?: WIFI_NETWORK_DEFAULT,
-                                newSecondaryNetworks = secondaryNetworks,
-                                newIsDefault = connectedEntry?.isDefaultNetwork ?: false,
-                            )
-                        }
-
-                        override fun onWifiStateChanged() {
-                            val state = wifiPickerTracker?.wifiState
-                            logOnWifiStateChanged(state)
-                            send(newState = state ?: WIFI_STATE_DEFAULT)
-                        }
-
-                        override fun onNumSavedNetworksChanged() {}
-
-                        override fun onNumSavedSubscriptionsChanged() {}
-
-                        private fun send(
-                            newState: Int = current.state,
-                            newIsDefault: Boolean = current.isDefault,
-                            newPrimaryNetwork: WifiNetworkModel = current.primaryNetwork,
-                            newSecondaryNetworks: List<WifiNetworkModel> =
-                                current.secondaryNetworks,
-                        ) {
-                            val new =
-                                WifiPickerTrackerInfo(
-                                    newState,
-                                    newIsDefault,
-                                    newPrimaryNetwork,
-                                    newSecondaryNetworks,
-                                )
-                            current = new
-                            trySend(new)
-                        }
-                    }
-
-                wifiPickerTracker =
-                    wifiPickerTrackerFactory.create(lifecycle, callback, "WifiRepository").apply {
-                        // By default, [WifiPickerTracker] will scan to see all available wifi
-                        // networks in the area. Because SysUI only needs to display the
-                        // **connected** network, we don't need scans to be running (and in fact,
-                        // running scans is costly and should be avoided whenever possible).
-                        this?.disableScanning()
-                    }
-                // The lifecycle must be STARTED in order for the callback to receive events.
-                mainExecutor.execute { lifecycle.currentState = Lifecycle.State.STARTED }
-                awaitClose {
-                    mainExecutor.execute { lifecycle.currentState = Lifecycle.State.CREATED }
-                }
-            }
-            .stateIn(scope, SharingStarted.Eagerly, current)
-    }
-
-    override val isWifiEnabled: StateFlow<Boolean> =
-        wifiPickerTrackerInfo
-            .map { it.state == WifiManager.WIFI_STATE_ENABLED }
-            .distinctUntilChanged()
-            .logDiffsForTable(
-                wifiTrackerLibTableLogBuffer,
-                columnPrefix = "",
-                columnName = COL_NAME_IS_ENABLED,
-                initialValue = false,
-            )
-            .stateIn(scope, SharingStarted.Eagerly, false)
-
-    override val wifiNetwork: StateFlow<WifiNetworkModel> =
-        wifiPickerTrackerInfo
-            .map { it.primaryNetwork }
-            .distinctUntilChanged()
-            .logDiffsForTable(
-                wifiTrackerLibTableLogBuffer,
-                columnPrefix = "",
-                initialValue = WIFI_NETWORK_DEFAULT,
-            )
-            .stateIn(scope, SharingStarted.Eagerly, WIFI_NETWORK_DEFAULT)
-
-    override val secondaryNetworks: StateFlow<List<WifiNetworkModel>> =
-        wifiPickerTrackerInfo
-            .map { it.secondaryNetworks }
-            .distinctUntilChanged()
-            .logDiffsForTable(
-                wifiTrackerLibTableLogBuffer,
-                columnPrefix = "",
-                columnName = "secondaryNetworks",
-                initialValue = emptyList(),
-            )
-            .stateIn(scope, SharingStarted.Eagerly, emptyList())
-
-    /**
-     * [WifiPickerTracker.getConnectedWifiEntry] stores a [MergedCarrierEntry] separately from the
-     * [WifiEntry] for the primary connection. Therefore, we have to prefer the carrier-merged entry
-     * if it exists, falling back on the connected entry if null
-     */
-    private val WifiPickerTracker?.mergedOrPrimaryConnection: WifiEntry?
-        get() {
-            val mergedEntry: MergedCarrierEntry? = this?.mergedCarrierEntry
-            return if (mergedEntry != null && mergedEntry.isDefaultNetwork) {
-                mergedEntry
-            } else {
-                this?.connectedWifiEntry
-            }
-        }
-
-    /**
-     * Converts WifiTrackerLib's [WifiEntry] into our internal model only if the entry is the
-     * primary network. Returns an inactive network if it's not primary.
-     */
-    private fun WifiEntry.toPrimaryWifiNetworkModel(): WifiNetworkModel {
-        return if (!this.isPrimaryNetwork) {
-            WIFI_NETWORK_DEFAULT
-        } else {
-            this.toWifiNetworkModel()
-        }
-    }
-
-    /** Converts WifiTrackerLib's [WifiEntry] into our internal model. */
-    private fun WifiEntry.toWifiNetworkModel(): WifiNetworkModel {
-        return if (this is MergedCarrierEntry) {
-            this.convertCarrierMergedToModel()
-        } else {
-            this.convertNormalToModel()
-        }
-    }
-
-    private fun MergedCarrierEntry.convertCarrierMergedToModel(): WifiNetworkModel {
-        return if (this.subscriptionId == INVALID_SUBSCRIPTION_ID) {
-            WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
-        } else {
-            WifiNetworkModel.CarrierMerged(
-                networkId = NETWORK_ID,
-                subscriptionId = this.subscriptionId,
-                level = this.level,
-                // WifiManager APIs to calculate the signal level start from 0, so
-                // maxSignalLevel + 1 represents the total level buckets count.
-                numberOfLevels = wifiManager.maxSignalLevel + 1,
-            )
-        }
-    }
-
-    private fun WifiEntry.convertNormalToModel(): WifiNetworkModel {
-        if (this.level == WIFI_LEVEL_UNREACHABLE || this.level !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX) {
-            // If our level means the network is unreachable or the level is otherwise invalid, we
-            // don't have an active network.
-            return WifiNetworkModel.Inactive
-        }
-
-        val hotspotDeviceType =
-            if (isInstantTetherEnabled && this is HotspotNetworkEntry) {
-                this.deviceType.toHotspotDeviceType()
-            } else {
-                WifiNetworkModel.HotspotDeviceType.NONE
-            }
-
-        return WifiNetworkModel.Active(
-            networkId = NETWORK_ID,
-            isValidated = this.hasInternetAccess(),
-            level = this.level,
-            ssid = this.title,
-            hotspotDeviceType = hotspotDeviceType,
-            // With WifiTrackerLib, [WifiEntry.title] will appropriately fetch the  SSID for
-            // typical wifi networks *and* passpoint/OSU APs. So, the AP-specific values can
-            // always be false/null in this repository.
-            // TODO(b/292534484): Remove these fields from the wifi network model once this
-            //  repository is fully enabled.
-            isPasspointAccessPoint = false,
-            isOnlineSignUpForPasspointAccessPoint = false,
-            passpointProviderFriendlyName = null,
-        )
-    }
-
-    override val isWifiDefault: StateFlow<Boolean> =
-        wifiPickerTrackerInfo
-            .map { it.isDefault }
-            .distinctUntilChanged()
-            .logDiffsForTable(
-                wifiTrackerLibTableLogBuffer,
-                columnPrefix = "",
-                columnName = COL_NAME_IS_DEFAULT,
-                initialValue = false,
-            )
-            .stateIn(scope, SharingStarted.Eagerly, false)
-
-    override val wifiActivity: StateFlow<DataActivityModel> =
-        WifiRepositoryHelper.createActivityFlow(
-            wifiManager,
-            mainExecutor,
-            scope,
-            wifiTrackerLibTableLogBuffer,
-            this::logActivity,
-        )
-
-    override val wifiScanResults: StateFlow<List<WifiScanEntry>> =
-        WifiRepositoryHelper.createNetworkScanFlow(
-            wifiManager,
-            scope,
-            bgDispatcher,
-            this::logScanResults,
-        )
-
-    private fun logOnWifiEntriesChanged(connectedEntry: WifiEntry?) {
-        inputLogger.log(
-            TAG,
-            LogLevel.DEBUG,
-            { str1 = connectedEntry.toString() },
-            { "onWifiEntriesChanged. ConnectedEntry=$str1" },
-        )
-    }
-
-    private fun logOnWifiStateChanged(state: Int?) {
-        inputLogger.log(
-            TAG,
-            LogLevel.DEBUG,
-            { int1 = state ?: -1 },
-            { "onWifiStateChanged. State=${if (int1 == -1) null else int1}" },
-        )
-    }
-
-    private fun logActivity(activity: String) {
-        inputLogger.log(TAG, LogLevel.DEBUG, { str1 = activity }, { "onActivityChanged: $str1" })
-    }
-
-    private fun logScanResults() =
-        inputLogger.log(TAG, LogLevel.DEBUG, {}, { "onScanResultsAvailable" })
-
-    /**
-     * Data class storing all the information fetched from [WifiPickerTracker].
-     *
-     * Used so that we only register a single callback on [WifiPickerTracker].
-     */
-    data class WifiPickerTrackerInfo(
-        /** The current wifi state. See [WifiManager.getWifiState]. */
-        val state: Int,
-        /** True if wifi is currently the default connection and false otherwise. */
-        val isDefault: Boolean,
-        /** The currently primary wifi network. */
-        val primaryNetwork: WifiNetworkModel,
-        /** The current secondary network(s), if any. Specifically excludes the primary network. */
-        val secondaryNetworks: List<WifiNetworkModel>
-    )
-
-    @SysUISingleton
-    class Factory
-    @Inject
-    constructor(
-        private val featureFlags: FeatureFlags,
-        @Application private val scope: CoroutineScope,
-        @Main private val mainExecutor: Executor,
-        @Background private val bgDispatcher: CoroutineDispatcher,
-        private val wifiPickerTrackerFactory: WifiPickerTrackerFactory,
-        @WifiTrackerLibInputLog private val inputLogger: LogBuffer,
-        @WifiTrackerLibTableLog private val wifiTrackerLibTableLogBuffer: TableLogBuffer,
-    ) {
-        fun create(wifiManager: WifiManager): WifiRepositoryViaTrackerLib {
-            return WifiRepositoryViaTrackerLib(
-                featureFlags,
-                scope,
-                mainExecutor,
-                bgDispatcher,
-                wifiPickerTrackerFactory,
-                wifiManager,
-                inputLogger,
-                wifiTrackerLibTableLogBuffer,
-            )
-        }
-    }
-
-    companion object {
-        private const val TAG = "WifiTrackerLibInputLog"
-
-        /**
-         * [WifiNetworkModel.Active.networkId] is only used at the repository layer. It's used by
-         * [WifiRepositoryImpl], which tracks the ID in order to correctly apply the framework
-         * callbacks within the repository.
-         *
-         * Since this class does not need to manually apply framework callbacks and since the
-         * network ID is not used beyond the repository, it's safe to use an invalid ID in this
-         * repository.
-         *
-         * The [WifiNetworkModel.Active.networkId] field should be deleted once we've fully migrated
-         * to [WifiRepositoryViaTrackerLib].
-         */
-        private const val NETWORK_ID = -1
-    }
-}
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
deleted file mode 100644
index b76bb51..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.wifi.shared
-
-import android.net.Network
-import android.net.NetworkCapabilities
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.core.LogLevel
-import com.android.systemui.statusbar.pipeline.dagger.WifiInputLog
-import com.android.systemui.statusbar.pipeline.shared.LoggerHelper
-import javax.inject.Inject
-
-/**
- * Logger for all the wifi-related inputs (intents, callbacks, etc.) that the wifi repo receives.
- */
-@SysUISingleton
-class WifiInputLogger
-@Inject
-constructor(
-    @WifiInputLog val buffer: LogBuffer,
-) {
-    fun logOnCapabilitiesChanged(
-        network: Network,
-        networkCapabilities: NetworkCapabilities,
-        isDefaultNetworkCallback: Boolean,
-    ) {
-        LoggerHelper.logOnCapabilitiesChanged(
-            buffer,
-            TAG,
-            network,
-            networkCapabilities,
-            isDefaultNetworkCallback,
-        )
-    }
-
-    fun logOnLost(network: Network, isDefaultNetworkCallback: Boolean) {
-        LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback)
-    }
-
-    fun logIntent(intentName: String) {
-        buffer.log(TAG, LogLevel.DEBUG, { str1 = intentName }, { "Intent received: $str1" })
-    }
-
-    fun logActivity(activity: String) {
-        buffer.log(TAG, LogLevel.DEBUG, { str1 = activity }, { "Activity: $str1" })
-    }
-
-    fun logScanResults() = buffer.log(TAG, LogLevel.DEBUG, {}, { "onScanResultsAvailable" })
-}
-
-private const val TAG = "WifiInputLog"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt
index 9cdecef..36c23d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt
@@ -69,7 +69,7 @@
             runnable.run()
             return
         }
-        val fn = "[$label] => AvalancheController.update ${getKey(entry)}"
+        val fn = "[$label] => AvalancheController.update [${getKey(entry)}]"
         if (entry == null) {
             log { "Entry is NULL, stop update." }
             return;
@@ -78,13 +78,13 @@
             debugRunnableLabelMap[runnable] = label
         }
         if (isShowing(entry)) {
-            log { "$fn => [update showing]" }
+            log { "\n$fn => [update showing]" }
             runnable.run()
         } else if (entry in nextMap) {
-            log { "$fn => [update next]" }
+            log { "\n$fn => [update next]" }
             nextMap[entry]?.add(runnable)
         } else if (headsUpEntryShowing == null) {
-            log { "$fn => [showNow]" }
+            log { "\n$fn => [showNow]" }
             showNow(entry, arrayListOf(runnable))
         } else {
             // Clean up invalid state when entry is in list but not map and vice versa
@@ -115,13 +115,16 @@
      * Run or ignore Runnable for given HeadsUpEntry. If entry was never shown, ignore and delete
      * all Runnables associated with that entry.
      */
-    fun delete(entry: HeadsUpEntry, runnable: Runnable, label: String) {
+    fun delete(entry: HeadsUpEntry?, runnable: Runnable, label: String) {
         if (!NotificationThrottleHun.isEnabled) {
             runnable.run()
             return
         }
         val fn = "[$label] => AvalancheController.delete " + getKey(entry)
-
+        if (entry == null) {
+            log { "$fn => cannot remove NULL entry" }
+            return
+        }
         if (entry in nextMap) {
             log { "$fn => [remove from next]" }
             if (entry in nextMap) nextMap.remove(entry)
@@ -151,24 +154,44 @@
             return autoDismissMs
         }
         val showingList: MutableList<HeadsUpEntry> = mutableListOf()
-        headsUpEntryShowing?.let { showingList.add(it) }
-
+        if (headsUpEntryShowing != null) {
+            showingList.add(headsUpEntryShowing!!)
+        }
+        nextList.sort()
         val entryList = showingList + nextList
-        if (entryList.indexOf(entry) == entryList.size - 1) {
-            // Use default duration if last entry
+        if (entryList.isEmpty()) {
+            log { "No avalanche HUNs, use default ms: $autoDismissMs" }
             return autoDismissMs
         }
+        // entryList.indexOf(entry) returns -1 even when the entry is in entryList
+        var thisEntryIndex = -1
+        for ((i, e) in entryList.withIndex()) {
+            if (e == entry) {
+                thisEntryIndex = i
+            }
+        }
+        if (thisEntryIndex == -1) {
+            log { "Untracked entry, use default ms: $autoDismissMs" }
+            return autoDismissMs
+        }
+        val nextEntryIndex = thisEntryIndex + 1
 
-        nextList.sort()
-        val nextEntry = nextList[0]
-
+        // If last entry, use default duration
+        if (nextEntryIndex >= entryList.size) {
+            log { "Last entry, use default ms: $autoDismissMs" }
+            return autoDismissMs
+        }
+        val nextEntry = entryList[nextEntryIndex]
         if (nextEntry.compareNonTimeFields(entry) == -1) {
             // Next entry is higher priority
+            log { "Next entry is higher priority: 500ms" }
             return 500
         } else if (nextEntry.compareNonTimeFields(entry) == 0) {
             // Next entry is same priority
+            log { "Next entry is same priority: 1000ms" }
             return 1000
         } else {
+            log { "Next entry is lower priority, use default ms: $autoDismissMs" }
             return autoDismissMs
         }
     }
@@ -203,24 +226,24 @@
     }
 
     private fun showNow(entry: HeadsUpEntry, runnableList: MutableList<Runnable>) {
-        log { "show " + getKey(entry) + " backlog size: " + runnableList.size }
+        log { "SHOW: " + getKey(entry) }
 
         headsUpEntryShowing = entry
 
         runnableList.forEach {
             if (it in debugRunnableLabelMap) {
-                log { "run runnable from: ${debugRunnableLabelMap[it]}" }
+                log { "RUNNABLE: ${debugRunnableLabelMap[it]}" }
             }
             it.run()
         }
     }
 
     private fun showNext() {
-        log { "showNext" }
+        log { "SHOW NEXT" }
         headsUpEntryShowing = null
 
         if (nextList.isEmpty()) {
-            log { "no more to show!" }
+            log { "NO MORE TO SHOW" }
             return
         }
 
@@ -260,41 +283,44 @@
     }
 
     private fun getStateStr(): String {
-        return "SHOWING: ${getKey(headsUpEntryShowing)}" +
-            "\tNEXT LIST: $nextListStr\tMAP: $nextMapStr" +
-            "\tDROP: $dropSetStr"
+        return "SHOWING: [${getKey(headsUpEntryShowing)}]" +
+                "\nNEXT LIST: $nextListStr" +
+                "\nNEXT MAP: $nextMapStr" +
+                "\nDROPPED: $dropSetStr"
     }
 
     private fun logState(reason: String) {
-        log { "REASON $reason" }
+        log { "\n================================================================================="}
+        log { "STATE $reason" }
         log { getStateStr() }
+        log { "=================================================================================\n"}
     }
 
     private val dropSetStr: String
         get() {
             val queue = ArrayList<String>()
             for (entry in debugDropSet) {
-                queue.add(getKey(entry))
+                queue.add("[${getKey(entry)}]")
             }
-            return java.lang.String.join(" ", queue)
+            return java.lang.String.join("\n", queue)
         }
 
     private val nextListStr: String
         get() {
             val queue = ArrayList<String>()
             for (entry in nextList) {
-                queue.add(getKey(entry))
+                queue.add("[${getKey(entry)}]")
             }
-            return java.lang.String.join(" ", queue)
+            return java.lang.String.join("\n", queue)
         }
 
     private val nextMapStr: String
         get() {
             val queue = ArrayList<String>()
             for (entry in nextMap.keys) {
-                queue.add(getKey(entry))
+                queue.add("[${getKey(entry)}]")
             }
-            return java.lang.String.join(" ", queue)
+            return java.lang.String.join("\n", queue)
         }
 
     fun getKey(entry: HeadsUpEntry?): String {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
index 20a82a4..b8318a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
@@ -165,6 +165,8 @@
     public void showNotification(@NonNull NotificationEntry entry) {
         HeadsUpEntry headsUpEntry = createHeadsUpEntry(entry);
 
+        mLogger.logShowNotificationRequest(entry);
+
         Runnable runnable = () -> {
             // TODO(b/315362456) log outside runnable too
             mLogger.logShowNotification(entry);
@@ -219,6 +221,8 @@
      */
     public void updateNotification(@NonNull String key, boolean shouldHeadsUpAgain) {
         HeadsUpEntry headsUpEntry = mHeadsUpEntryMap.get(key);
+        mLogger.logUpdateNotificationRequest(key, shouldHeadsUpAgain, headsUpEntry != null);
+
         Runnable runnable = () -> {
             updateNotificationInternal(key, shouldHeadsUpAgain);
         };
@@ -252,10 +256,15 @@
         // A copy is necessary here as we are changing the underlying map.  This would cause
         // undefined behavior if we iterated over the key set directly.
         ArraySet<String> keysToRemove = new ArraySet<>(mHeadsUpEntryMap.keySet());
+
+        // Must get waiting keys before calling removeEntry, which clears waiting entries in
+        // AvalancheController
+        List<String> waitingKeysToRemove = mAvalancheController.getWaitingKeys();
+
         for (String key : keysToRemove) {
             removeEntry(key);
         }
-        for (String key : mAvalancheController.getWaitingKeys()) {
+        for (String key : waitingKeysToRemove) {
             removeEntry(key);
         }
     }
@@ -378,8 +387,11 @@
      */
     protected final void removeEntry(@NonNull String key) {
         HeadsUpEntry headsUpEntry = mHeadsUpEntryMap.get(key);
+        mLogger.logRemoveEntryRequest(key);
 
         Runnable runnable = () -> {
+            mLogger.logRemoveEntry(key);
+
             if (headsUpEntry == null) {
                 return;
             }
@@ -566,8 +578,10 @@
     public void unpinAll(boolean userUnPinned) {
         for (String key : mHeadsUpEntryMap.keySet()) {
             HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
-
+            mLogger.logUnpinEntryRequest(key);
             Runnable runnable = () -> {
+                mLogger.logUnpinEntry(key);
+
                 setEntryPinned(headsUpEntry, false /* isPinned */);
                 // maybe it got un sticky
                 headsUpEntry.updateEntry(false /* updatePostTime */, "unpinAll");
@@ -886,6 +900,7 @@
          * Clear any pending removal runnables.
          */
         public void cancelAutoRemovalCallbacks(@Nullable String reason) {
+            mLogger.logAutoRemoveCancelRequest(this.mEntry, reason);
             Runnable runnable = () -> {
                 final boolean removed = cancelAutoRemovalCallbackInternal();
 
@@ -893,13 +908,18 @@
                     mLogger.logAutoRemoveCanceled(mEntry, reason);
                 }
             };
-            mAvalancheController.update(this, runnable,
-                    reason + " removeAutoRemovalCallbacks");
+            if (isHeadsUpEntry(this.mEntry.getKey())) {
+                mAvalancheController.update(this, runnable, reason + " cancelAutoRemovalCallbacks");
+            } else {
+                // Just removed
+                runnable.run();
+            }
         }
 
         public void scheduleAutoRemovalCallback(FinishTimeUpdater finishTimeCalculator,
                 @NonNull String reason) {
 
+            mLogger.logAutoRemoveRequest(this.mEntry, reason);
             Runnable runnable = () -> {
                 long delayMs = finishTimeCalculator.updateAndGetTimeRemaining();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 45078e3..dab27bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -22,6 +22,7 @@
 import static android.os.BatteryManager.EXTRA_PRESENT;
 
 import static com.android.settingslib.fuelgauge.BatterySaverLogging.SAVER_ENABLED_QS;
+import static com.android.systemui.Flags.registerBatteryControllerReceiversInCorestartable;
 import static com.android.systemui.util.DumpUtilsKt.asIndenting;
 
 import android.annotation.WorkerThread;
@@ -36,7 +37,6 @@
 import android.os.PowerManager;
 import android.os.PowerSaveState;
 import android.util.IndentingPrintWriter;
-import android.util.Log;
 import android.view.View;
 
 import androidx.annotation.NonNull;
@@ -76,8 +76,6 @@
 
     private static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
 
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
     private final EnhancedEstimates mEstimates;
     protected final BroadcastDispatcher mBroadcastDispatcher;
     protected final ArrayList<BatteryController.BatteryStateChangeCallback>
@@ -151,7 +149,9 @@
     @Override
     public void init() {
         mLogger.logBatteryControllerInit(this, mHasReceivedBattery);
-        registerReceiver();
+        if (!registerBatteryControllerReceiversInCorestartable()) {
+            registerReceiver();
+        }
         if (!mHasReceivedBattery) {
             // Get initial state. Relying on Sticky behavior until API for getting info.
             Intent intent = mContext.registerReceiver(
@@ -446,7 +446,6 @@
         PowerSaveState state = mPowerManager.getPowerSaveState(PowerManager.ServiceType.AOD);
         mAodPowerSave = state.batterySaverEnabled;
 
-        if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
         firePowerSaveChanged();
     }
 
@@ -472,6 +471,7 @@
     }
 
     private void firePowerSaveChanged() {
+        mLogger.logPowerSaveChangedCallback(mPowerSave);
         dispatchSafeChange((callback) -> callback.onPowerSaveChanged(mPowerSave));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerLogger.kt
index 4a2a2db..85871e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerLogger.kt
@@ -105,6 +105,15 @@
         )
     }
 
+    fun logPowerSaveChangedCallback(isPowerSave: Boolean) {
+        logBuffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            { bool1 = isPowerSave },
+            { "Sending onPowerSaveChanged callback with powerSave=$bool1" }
+        )
+    }
+
     private fun Int.report(): String =
         if (this == DEFAULT) {
             "(missing)"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerStartable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerStartable.java
new file mode 100644
index 0000000..7f601c8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerStartable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static com.android.systemui.Flags.registerBatteryControllerReceiversInCorestartable;
+
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbManager;
+import android.os.PowerManager;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/** A {@link CoreStartable} responsible for registering the receivers for
+ * {@link BatteryControllerImpl}.
+ */
+@SysUISingleton
+public class BatteryControllerStartable implements CoreStartable {
+
+    private final BatteryController mBatteryController;
+    private final Executor mBackgroundExecutor;
+
+    private static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
+
+    protected final BroadcastDispatcher mBroadcastDispatcher;
+    @Inject
+    public BatteryControllerStartable(
+            BatteryController batteryController,
+            BroadcastDispatcher broadcastDispatcher,
+            @Background Executor backgroundExecutor) {
+        mBatteryController = batteryController;
+        mBroadcastDispatcher = broadcastDispatcher;
+        mBackgroundExecutor = backgroundExecutor;
+    }
+
+    private void registerReceiver() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
+        filter.addAction(ACTION_LEVEL_TEST);
+        filter.addAction(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED);
+        mBroadcastDispatcher.registerReceiver((BroadcastReceiver) mBatteryController, filter);
+    }
+
+    @Override
+    public void start() {
+        if (registerBatteryControllerReceiversInCorestartable()
+                && mBatteryController instanceof BatteryControllerImpl) {
+            mBackgroundExecutor.execute(() -> registerReceiver());
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 13f76fe..7d920ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -27,6 +27,7 @@
 
 import com.android.systemui.res.R;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.settings.brightness.MirrorController;
 import com.android.systemui.settings.brightness.ToggleSlider;
 import com.android.systemui.shade.NotificationShadeWindowView;
 import com.android.systemui.shade.ShadeViewController;
@@ -38,8 +39,7 @@
 /**
  * Controls showing and hiding of the brightness mirror.
  */
-public class BrightnessMirrorController
-        implements CallbackController<BrightnessMirrorController.BrightnessMirrorListener> {
+public class BrightnessMirrorController implements MirrorController {
 
     private final NotificationShadeWindowView mStatusBarWindow;
     private final Consumer<Boolean> mVisibilityCallback;
@@ -71,6 +71,7 @@
         updateResources();
     }
 
+    @Override
     public void showMirror() {
         mBrightnessMirror.setVisibility(View.VISIBLE);
         mVisibilityCallback.accept(true);
@@ -78,16 +79,14 @@
         mDepthController.setBrightnessMirrorVisible(true);
     }
 
+    @Override
     public void hideMirror() {
         mVisibilityCallback.accept(false);
         mNotificationPanel.setAlpha(255, true /* animate */);
         mDepthController.setBrightnessMirrorVisible(false);
     }
 
-    /**
-     * Set the location and size of the mirror container to match that of the slider in QS
-     * @param original the original view in QS
-     */
+    @Override
     public void setLocationAndSize(View original) {
         original.getLocationInWindow(mInt2Cache);
 
@@ -112,6 +111,7 @@
         }
     }
 
+    @Override
     public ToggleSlider getToggleSlider() {
         return mToggleSliderController;
     }
@@ -176,8 +176,4 @@
     public void onUiModeChanged() {
         reinflate();
     }
-
-    public interface BrightnessMirrorListener {
-        void onBrightnessMirrorReinflated(View brightnessMirror);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index b98eff8..615cc74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -51,7 +51,7 @@
 public class FlashlightControllerImpl implements FlashlightController {
 
     private static final String TAG = "FlashlightController";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean DEBUG = true;
 
     private static final int DISPATCH_ERROR = 0;
     private static final int DISPATCH_CHANGED = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
index 52a2e9c..28a2a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
@@ -73,7 +73,8 @@
     /** Returns whether or not the given notification is managed by this manager. */
     fun isHeadsUpEntry(key: String): Boolean
 
-    fun isHeadsUpGoingAway(): Boolean
+    /** @see setHeadsUpAnimatingAway */
+    fun isHeadsUpAnimatingAwayValue(): Boolean
 
     /** Returns if the given notification is snoozed or not. */
     fun isSnoozed(packageName: String): Boolean
@@ -130,7 +131,7 @@
      * Set that we are exiting the headsUp pinned mode, but some notifications might still be
      * animating out. This is used to keep the touchable regions in a reasonable state.
      */
-    fun setHeadsUpGoingAway(headsUpGoingAway: Boolean)
+    fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean)
 
     /**
      * Notifies that a remote input textbox in notification gets active or inactive.
@@ -194,10 +195,10 @@
 interface OnHeadsUpPhoneListenerChange {
     /**
      * Called when a heads up notification is 'going away' or no longer 'going away'. See
-     * [HeadsUpManager.setHeadsUpGoingAway].
+     * [HeadsUpManager.setHeadsUpAnimatingAway].
      */
     // TODO(b/325936094) delete this callback, and listen to the flow instead
-    fun onHeadsUpGoingAwayStateChanged(headsUpGoingAway: Boolean)
+    fun onHeadsUpAnimatingAwayStateChanged(headsUpAnimatingAway: Boolean)
 }
 
 /* No op impl of HeadsUpManager. */
@@ -215,7 +216,7 @@
     override fun getTopEntry() = null
     override fun hasPinnedHeadsUp() = false
     override fun isHeadsUpEntry(key: String) = false
-    override fun isHeadsUpGoingAway() = false
+    override fun isHeadsUpAnimatingAwayValue() = false
     override fun isSnoozed(packageName: String) = false
     override fun isSticky(key: String?) = false
     override fun isTrackingHeadsUp() = false
@@ -228,7 +229,7 @@
     override fun setAnimationStateHandler(handler: AnimationStateHandler) {}
     override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {}
     override fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean) {}
-    override fun setHeadsUpGoingAway(headsUpGoingAway: Boolean) {}
+    override fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean) {}
     override fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean) {}
     override fun setTrackingHeadsUp(tracking: Boolean) {}
     override fun setUser(user: Int) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
index f6154afe..11cbc9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
@@ -58,6 +58,14 @@
         })
     }
 
+    fun logShowNotificationRequest(entry: NotificationEntry) {
+        buffer.log(TAG, INFO, {
+            str1 = entry.logKey
+        }, {
+            "request: show notification $str1"
+        })
+    }
+
     fun logShowNotification(entry: NotificationEntry) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
@@ -76,6 +84,15 @@
         })
     }
 
+    fun logAutoRemoveRequest(entry: NotificationEntry, reason: String) {
+        buffer.log(TAG, INFO, {
+            str1 = entry.logKey
+            str2 = reason
+        }, {
+            "request: reschedule auto remove of $str1 reason: $str2"
+        })
+    }
+
     fun logAutoRemoveRescheduled(entry: NotificationEntry, delayMillis: Long, reason: String) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
@@ -86,6 +103,15 @@
         })
     }
 
+    fun logAutoRemoveCancelRequest(entry: NotificationEntry, reason: String?) {
+        buffer.log(TAG, INFO, {
+            str1 = entry.logKey
+            str2 = reason ?: "unknown"
+        }, {
+            "request: cancel auto remove of $str1 reason: $str2"
+        })
+    }
+
     fun logAutoRemoveCanceled(entry: NotificationEntry, reason: String?) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
@@ -95,6 +121,38 @@
         })
     }
 
+    fun logRemoveEntryRequest(key: String) {
+        buffer.log(TAG, INFO, {
+            str1 = logKey(key)
+        }, {
+            "request: remove entry $str1"
+        })
+    }
+
+    fun logRemoveEntry(key: String) {
+        buffer.log(TAG, INFO, {
+            str1 = logKey(key)
+        }, {
+            "remove entry $str1"
+        })
+    }
+
+    fun logUnpinEntryRequest(key: String) {
+        buffer.log(TAG, INFO, {
+            str1 = logKey(key)
+        }, {
+            "request: unpin entry $str1"
+        })
+    }
+
+    fun logUnpinEntry(key: String) {
+        buffer.log(TAG, INFO, {
+            str1 = logKey(key)
+        }, {
+            "unpin entry $str1"
+        })
+    }
+
     fun logRemoveNotification(key: String, releaseImmediately: Boolean) {
         buffer.log(TAG, INFO, {
             str1 = logKey(key)
@@ -112,13 +170,23 @@
         })
     }
 
+    fun logUpdateNotificationRequest(key: String, alert: Boolean, hasEntry: Boolean) {
+        buffer.log(TAG, INFO, {
+            str1 = logKey(key)
+            bool1 = alert
+            bool2 = hasEntry
+        }, {
+            "request: update notification $str1 alert: $bool1 hasEntry: $bool2"
+        })
+    }
+
     fun logUpdateNotification(key: String, alert: Boolean, hasEntry: Boolean) {
         buffer.log(TAG, INFO, {
             str1 = logKey(key)
             bool1 = alert
             bool2 = hasEntry
         }, {
-            "update notification $str1 alert: $bool1 hasEntry: $bool2 reason: $str2"
+            "update notification $str1 alert: $bool1 hasEntry: $bool2"
         })
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
index 0d53277..40bb67f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java
@@ -34,6 +34,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -62,7 +63,10 @@
     private static final String LOG_TAG = "SNPC";
     private final SensitiveNotificationProtectionControllerLogger mLogger;
     private final PackageManager mPackageManager;
-    private final ArraySet<String> mExemptPackages = new ArraySet<>();
+    // Packages exempt from projection session protections (if they start a projection session)
+    private final ArraySet<String> mSessionProtectionExemptPackages = new ArraySet<>();
+    // Packages exempt from individual notification protections (if they post a notification)
+    private final ArraySet<String> mNotificationProtectionExemptPackages = new ArraySet<>();
     private final ListenerSet<Runnable> mListeners = new ListenerSet<>();
     private volatile MediaProjectionInfo mProjection;
     private SensitiveNotificatioMediaProjectionSession mActiveMediaProjectionSession;
@@ -161,6 +165,7 @@
             MediaProjectionManager mediaProjectionManager,
             IActivityManager activityManager,
             PackageManager packageManager,
+            TelephonyManager telephonyManager,
             @Main Handler mainHandler,
             @Background Executor bgExecutor,
             SensitiveNotificationProtectionControllerLogger logger) {
@@ -191,26 +196,18 @@
         bgExecutor.execute(() -> developerOptionsObserver.onChange(true));
 
         bgExecutor.execute(() -> {
-            ArraySet<String> exemptPackages = new ArraySet<>();
-            // Exempt SystemUI
-            exemptPackages.add(context.getPackageName());
+            ArraySet<String> sessionProtectionExemptPackages =
+                    getSessionProtectionExemptPackages(context, activityManager);
 
-            // Exempt approved bug report handlers
-            try {
-                exemptPackages.addAll(activityManager.getBugreportWhitelistedPackages());
-            } catch (RemoteException e) {
-                Log.e(
-                        LOG_TAG,
-                        "Error adding bug report handlers to exemption, continuing without",
-                        e);
-                // silent failure, skip adding packages to exemption
-            }
+            ArraySet<String> notificationProtectionExemptPackages =
+                    getNotificationProtectionExemptPackages(telephonyManager);
 
             // if currently projecting, notify listeners of exemption changes
             mainHandler.post(() -> {
                 Trace.beginSection("SNPC.exemptPackagesUpdated");
                 try {
-                    updateExemptPackagesAndNotifyListeners(exemptPackages);
+                    updateExemptPackagesAndNotifyListeners(sessionProtectionExemptPackages,
+                            notificationProtectionExemptPackages);
                 } finally {
                     Trace.endSection();
                 }
@@ -220,15 +217,66 @@
         mediaProjectionManager.addCallback(mMediaProjectionCallback, mainHandler);
     }
 
+    @NonNull
+    private static ArraySet<String> getSessionProtectionExemptPackages(Context context,
+            IActivityManager activityManager) {
+        ArraySet<String> sessionProtectionExemptPackages = new ArraySet<>();
+        // Exempt SystemUI
+        sessionProtectionExemptPackages.add(context.getPackageName());
+
+        // Exempt approved bug report handlers
+        try {
+            sessionProtectionExemptPackages.addAll(
+                    activityManager.getBugreportWhitelistedPackages());
+        } catch (RemoteException e) {
+            Log.w(
+                    LOG_TAG,
+                    "Error adding bug report handlers to exemption, continuing without",
+                    e);
+            // silent failure, skip adding packages to exemption
+        }
+        return sessionProtectionExemptPackages;
+    }
+
+    @NonNull
+    private static ArraySet<String> getNotificationProtectionExemptPackages(
+            TelephonyManager telephonyManager) {
+        ArraySet<String> notificationProtectionExemptPackages = new ArraySet<>();
+
+        // Get Emergency Assistance Package, all notifications from this package should not be
+        // hidden/redacted.
+        if (screenshareNotificationHidingBugFix()) {
+            try {
+                String emergencyAssistancePackageName =
+                        telephonyManager.getEmergencyAssistancePackageName();
+                if (emergencyAssistancePackageName != null) {
+                    notificationProtectionExemptPackages.add(emergencyAssistancePackageName);
+                }
+            } catch (IllegalStateException e) {
+                Log.w(
+                        LOG_TAG,
+                        "Error adding emergency assistance package to exemption",
+                        e);
+                // silent failure, skip adding packages to exemption
+            }
+        }
+        return notificationProtectionExemptPackages;
+    }
+
     /**
      * Notify listeners of possible ProjectionState change regardless of current
      * isSensitiveStateActive value. Method used to ensure updates occur after mExemptPackages gets
      * updated, which directly changes the outcome of isSensitiveStateActive
      */
     @MainThread
-    private void updateExemptPackagesAndNotifyListeners(ArraySet<String> exemptPackages) {
+    private void updateExemptPackagesAndNotifyListeners(
+            ArraySet<String> sessionProtectionExemptPackages,
+            ArraySet<String> notificationProtectionExemptPackages) {
         Assert.isMainThread();
-        mExemptPackages.addAll(exemptPackages);
+        mSessionProtectionExemptPackages.addAll(sessionProtectionExemptPackages);
+        if (screenshareNotificationHidingBugFix()) {
+            mNotificationProtectionExemptPackages.addAll(notificationProtectionExemptPackages);
+        }
 
         if (mProjection != null) {
             updateProjectionStateAndNotifyListeners(mProjection);
@@ -258,7 +306,8 @@
         if (mDisableScreenShareProtections) {
             Log.w(LOG_TAG, "Screen share protections disabled");
             return null;
-        } else if (info != null && mExemptPackages.contains(info.getPackageName())) {
+        } else if (info != null
+                && mSessionProtectionExemptPackages.contains(info.getPackageName())) {
             Log.w(LOG_TAG, "Screen share protections exempt for package " + info.getPackageName());
             return null;
         } else if (info != null && canRecordSensitiveContent(info.getPackageName())) {
@@ -322,6 +371,11 @@
             return false; // do not hide/redact notifications from system uid
         }
 
+        if (screenshareNotificationHidingBugFix()
+                && mNotificationProtectionExemptPackages.contains(sbn.getPackageName())) {
+            return false; // do not hide/redact notifications from emergency app
+        }
+
         // Only protect/redact notifications if the developer has not explicitly set notification
         // visibility as public and users has not adjusted default channel visibility to private
         boolean notificationRequestsRedaction = entry.isNotificationVisibilityPrivate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt
index 2b3fb70..68bb6c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt
@@ -19,8 +19,10 @@
 import android.content.Context
 import com.android.internal.policy.SystemBarUtils
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.res.R
 import dagger.Binds
 import javax.inject.Inject
+import kotlin.math.max
 
 /**
  * Proxy interface to [SystemBarUtils], allowing injection of different logic for testing.
@@ -29,6 +31,7 @@
  */
 interface SystemBarUtilsProxy {
     fun getStatusBarHeight(): Int
+    fun getStatusBarHeaderHeightKeyguard(): Int
 }
 
 class SystemBarUtilsProxyImpl
@@ -37,6 +40,13 @@
     @Application private val context: Context,
 ) : SystemBarUtilsProxy {
     override fun getStatusBarHeight(): Int = SystemBarUtils.getStatusBarHeight(context)
+    override fun getStatusBarHeaderHeightKeyguard(): Int {
+        val cutout = context.display.cutout
+        val waterfallInsetTop = if (cutout == null) 0 else cutout.waterfallInsets.top
+        val statusBarHeaderHeightKeyguard =
+            context.resources.getDimensionPixelSize(R.dimen.status_bar_header_height_keyguard)
+        return max(getStatusBarHeight(), statusBarHeaderHeightKeyguard + waterfallInsetTop)
+    }
 
     @dagger.Module
     interface Module {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt
index 10137a0..2314f01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt
@@ -52,4 +52,14 @@
             .distinctUntilChanged()
             .flowOn(bgContext)
             .conflate()
+
+    val statusBarHeaderHeightKeyguard: Flow<Int> =
+        configurationController.onConfigChanged
+            .onStart<Any> { emit(Unit) }
+            .flowOn(mainContext)
+            .conflate()
+            .map { proxy.getStatusBarHeaderHeightKeyguard() }
+            .distinctUntilChanged()
+            .flowOn(bgContext)
+            .conflate()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
index e977014..aea739d 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
@@ -20,11 +20,10 @@
 import android.animation.AnimatorListenerAdapter
 import android.animation.ValueAnimator
 import android.annotation.BinderThread
-import android.content.Context
-import android.os.Handler
 import android.os.SystemProperties
 import android.util.Log
 import android.view.animation.DecelerateInterpolator
+import com.android.app.tracing.TraceUtils.traceAsync
 import com.android.internal.foldables.FoldLockSettingAvailabilityProvider
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.display.data.repository.DeviceStateRepository
@@ -36,12 +35,13 @@
 import com.android.systemui.unfold.FullscreenLightRevealAnimationController.Companion.isVerticalRotation
 import com.android.systemui.unfold.dagger.UnfoldBg
 import com.android.systemui.util.animation.data.repository.AnimationStatusRepository
+import com.android.systemui.util.kotlin.race
 import javax.inject.Inject
 import kotlin.coroutines.resume
 import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.TimeoutCancellationException
-import kotlinx.coroutines.android.asCoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.distinctUntilChanged
@@ -59,13 +59,13 @@
 class FoldLightRevealOverlayAnimation
 @Inject
 constructor(
-    private val context: Context,
-    @UnfoldBg private val bgHandler: Handler,
+    @UnfoldBg private val bgDispatcher: CoroutineDispatcher,
     private val deviceStateRepository: DeviceStateRepository,
     private val powerInteractor: PowerInteractor,
     @Background private val applicationScope: CoroutineScope,
     private val animationStatusRepository: AnimationStatusRepository,
-    private val controllerFactory: FullscreenLightRevealAnimationController.Factory
+    private val controllerFactory: FullscreenLightRevealAnimationController.Factory,
+    private val foldLockSettingAvailabilityProvider: FoldLockSettingAvailabilityProvider
 ) : FullscreenLightRevealAnimation {
 
     private val revealProgressValueAnimator: ValueAnimator =
@@ -79,7 +79,7 @@
     override fun init() {
         // This method will be called only on devices where this animation is enabled,
         // so normally this thread won't be created
-        if (!FoldLockSettingAvailabilityProvider(context.resources).isFoldLockBehaviorAvailable) {
+        if (!foldLockSettingAvailabilityProvider.isFoldLockBehaviorAvailable) {
             return
         }
 
@@ -91,7 +91,6 @@
             )
         controller.init()
 
-        val bgDispatcher = bgHandler.asCoroutineDispatcher("@UnfoldBg Handler")
         applicationScope.launch(bgDispatcher) {
             powerInteractor.screenPowerState.collect {
                 if (it == ScreenPowerState.SCREEN_ON) {
@@ -109,14 +108,21 @@
                             if (!areAnimationEnabled.first() || !isFolded) {
                                 return@flow
                             }
-                            withTimeout(WAIT_FOR_ANIMATION_TIMEOUT_MS) {
-                                readyCallback = CompletableDeferred()
-                                val onReady = readyCallback?.await()
-                                readyCallback = null
-                                controller.addOverlay(ALPHA_OPAQUE, onReady)
-                                waitForScreenTurnedOn()
-                            }
-                            playFoldLightRevealOverlayAnimation()
+                            race(
+                                {
+                                    traceAsync(TAG, "prepareAndPlayFoldAnimation()") {
+                                        withTimeout(WAIT_FOR_ANIMATION_TIMEOUT_MS) {
+                                            readyCallback = CompletableDeferred()
+                                            val onReady = readyCallback?.await()
+                                            readyCallback = null
+                                            controller.addOverlay(ALPHA_OPAQUE, onReady)
+                                            waitForScreenTurnedOn()
+                                        }
+                                        playFoldLightRevealOverlayAnimation()
+                                    }
+                                },
+                                { waitForGoToSleep() }
+                            )
                         }
                         .catchTimeoutAndLog()
                         .onCompletion {
@@ -135,9 +141,13 @@
         readyCallback?.complete(onOverlayReady) ?: onOverlayReady.run()
     }
 
-    private suspend fun waitForScreenTurnedOn() {
-        powerInteractor.screenPowerState.filter { it == ScreenPowerState.SCREEN_ON }.first()
-    }
+    private suspend fun waitForScreenTurnedOn() =
+        traceAsync(TAG, "waitForScreenTurnedOn()") {
+            powerInteractor.screenPowerState.filter { it == ScreenPowerState.SCREEN_ON }.first()
+        }
+
+    private suspend fun waitForGoToSleep() =
+        traceAsync(TAG, "waitForGoToSleep()") { powerInteractor.isAsleep.filter { it }.first() }
 
     private suspend fun playFoldLightRevealOverlayAnimation() {
         revealProgressValueAnimator.duration = ANIMATION_DURATION
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index 9bd0e32..37ef1f2 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.hardware.devicestate.DeviceStateManager
 import android.os.SystemProperties
+import com.android.internal.foldables.FoldLockSettingAvailabilityProvider
 import com.android.systemui.CoreStartable
 import com.android.systemui.Flags
 import com.android.systemui.dagger.qualifiers.Application
@@ -31,8 +32,6 @@
 import com.android.systemui.unfold.data.repository.FoldStateRepositoryImpl
 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository
 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl
-import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
-import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractorImpl
 import com.android.systemui.unfold.system.SystemUnfoldSharedModule
 import com.android.systemui.unfold.updates.FoldProvider
 import com.android.systemui.unfold.updates.FoldStateProvider
@@ -175,12 +174,16 @@
     fun provideDisplaySwitchLatencyLogger(): DisplaySwitchLatencyLogger =
         DisplaySwitchLatencyLogger()
 
+    @Provides
+    @Singleton
+    fun provideFoldLockSettingAvailabilityProvider(
+        context: Context
+    ): FoldLockSettingAvailabilityProvider = FoldLockSettingAvailabilityProvider(context.resources)
+
     @Module
     interface Bindings {
         @Binds fun bindRepository(impl: UnfoldTransitionRepositoryImpl): UnfoldTransitionRepository
 
-        @Binds fun bindInteractor(impl: UnfoldTransitionInteractorImpl): UnfoldTransitionInteractor
-
         @Binds fun bindFoldStateRepository(impl: FoldStateRepositoryImpl): FoldStateRepository
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt
index 0d3682c..fbbd2b9 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/data/repository/UnfoldTransitionRepository.kt
@@ -15,9 +15,11 @@
  */
 package com.android.systemui.unfold.data.repository
 
+import androidx.annotation.FloatRange
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished
+import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionInProgress
 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted
 import com.android.systemui.util.kotlin.getOrNull
 import java.util.Optional
@@ -42,6 +44,10 @@
 sealed class UnfoldTransitionStatus {
     /** Status that is sent when fold or unfold transition is in started state */
     data object TransitionStarted : UnfoldTransitionStatus()
+    /** Status that is sent while fold or unfold transition is in progress */
+    data class TransitionInProgress(
+        @FloatRange(from = 0.0, to = 1.0) val progress: Float,
+    ) : UnfoldTransitionStatus()
     /** Status that is sent when fold or unfold transition is finished */
     data object TransitionFinished : UnfoldTransitionStatus()
 }
@@ -66,6 +72,10 @@
                             trySend(TransitionStarted)
                         }
 
+                        override fun onTransitionProgress(progress: Float) {
+                            trySend(TransitionInProgress(progress))
+                        }
+
                         override fun onTransitionFinished() {
                             trySend(TransitionFinished)
                         }
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt
index 3e2e564..03499cb 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractor.kt
@@ -15,40 +15,79 @@
  */
 package com.android.systemui.unfold.domain.interactor
 
+import android.view.View
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.res.R
 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository
 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished
+import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionInProgress
 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted
 import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
 
 /**
  * Contains business-logic related to fold-unfold transitions while interacting with
  * [UnfoldTransitionRepository]
  */
-interface UnfoldTransitionInteractor {
+@SysUISingleton
+class UnfoldTransitionInteractor
+@Inject
+constructor(
+    private val repository: UnfoldTransitionRepository,
+    private val configurationInteractor: ConfigurationInteractor,
+) {
     /** Returns availability of fold/unfold transitions on the device */
     val isAvailable: Boolean
-
-    /** Suspends and waits for a fold/unfold transition to finish */
-    suspend fun waitForTransitionFinish()
-
-    /** Suspends and waits for a fold/unfold transition to start */
-    suspend fun waitForTransitionStart()
-}
-
-class UnfoldTransitionInteractorImpl
-@Inject
-constructor(private val repository: UnfoldTransitionRepository) : UnfoldTransitionInteractor {
-
-    override val isAvailable: Boolean
         get() = repository.isAvailable
 
-    override suspend fun waitForTransitionFinish() {
+    /**
+     * This mapping emits 1 when the device is completely unfolded and 0.0 when the device is
+     * completely folded.
+     */
+    private val unfoldProgress: Flow<Float> =
+        repository.transitionStatus
+            .map { (it as? TransitionInProgress)?.progress ?: 1f }
+            .onStart { emit(1f) }
+            .distinctUntilChanged()
+
+    /**
+     * Amount of X-axis translation to apply to various elements as the unfolded foldable is folded
+     * slightly, in pixels.
+     *
+     * @param isOnStartSide Whether the consumer wishes to get a translation amount that's suitable
+     *   for an element that's on the start-side (left hand-side in left-to-right layouts); if
+     *   `true`, the values will provide positive translations to push the left-hand-side element
+     *   towards the foldable hinge; if `false`, the values will be inverted to provide negative
+     *   translations to push the right-hand-side element towards the foldable hinge. Note that this
+     *   method already accounts for left-to-right vs. right-to-left layout directions.
+     */
+    fun unfoldTranslationX(isOnStartSide: Boolean): Flow<Float> {
+        return combine(
+            unfoldProgress,
+            configurationInteractor.dimensionPixelSize(R.dimen.notification_side_paddings),
+            configurationInteractor.layoutDirection.map {
+                if (it == View.LAYOUT_DIRECTION_RTL) -1 else 1
+            },
+        ) { unfoldedAmount, max, layoutDirectionMultiplier ->
+            val sideMultiplier = if (isOnStartSide) 1 else -1
+            max * (1 - unfoldedAmount) * sideMultiplier * layoutDirectionMultiplier
+        }
+    }
+
+    /** Suspends and waits for a fold/unfold transition to finish */
+    suspend fun waitForTransitionFinish() {
         repository.transitionStatus.filter { it is TransitionFinished }.first()
     }
 
-    override suspend fun waitForTransitionStart() {
+    /** Suspends and waits for a fold/unfold transition to start */
+    suspend fun waitForTransitionStart() {
         repository.transitionStatus.filter { it is TransitionStarted }.first()
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index 7861ded..3953188 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -128,7 +128,10 @@
 
     /**
      * Gets the {@link R.dimen#status_bar_header_height_keyguard}.
+     *
+     * @deprecated Prefer SystemBarUtilsState or SystemBarUtilsProxy
      */
+    @Deprecated
     public static int getStatusBarHeaderHeightKeyguard(Context context) {
         final int statusBarHeight = SystemBarUtils.getStatusBarHeight(context);
         final DisplayCutout cutout = context.getDisplay().getCutout();
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt
index 693a835..b300885 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/BooleanFlowOperators.kt
@@ -18,6 +18,7 @@
 
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 
 object BooleanFlowOperators {
@@ -31,7 +32,7 @@
      * ```
      */
     fun and(vararg flows: Flow<Boolean>): Flow<Boolean> =
-        combine(flows.asIterable()) { values -> values.all { it } }
+        combine(flows.asIterable()) { values -> values.all { it } }.distinctUntilChanged()
 
     /**
      * Logical NOT operator for a boolean flow.
@@ -48,5 +49,5 @@
      * determine the result.
      */
     fun or(vararg flows: Flow<Boolean>): Flow<Boolean> =
-        combine(flows.asIterable()) { values -> values.any { it } }
+        combine(flows.asIterable()) { values -> values.any { it } }.distinctUntilChanged()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt
index 909a18be..97d957d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt
@@ -17,8 +17,14 @@
 package com.android.systemui.util.kotlin
 
 import com.android.systemui.lifecycle.repeatWhenAttached
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.launch
 
 /**
  * Suspends to keep getting updates until cancellation. Once cancelled, mark this as eligible for
@@ -42,3 +48,22 @@
         dispose()
     }
 }
+
+/**
+ * This will [launch], run [onLaunch] to get a [DisposableHandle], and finally
+ * [awaitCancellationThenDispose][DisposableHandle.awaitCancellationThenDispose]. This can be used
+ * to structure self-disposing code which attaches listeners, for example in ViewBinders:
+ * ```
+ * suspend fun bind(view: MyView, viewModel: MyViewModel) = coroutineScope {
+ *     launchAndDispose {
+ *         view.setOnClickListener { viewModel.handleClick() }
+ *         DisposableHandle { view.setOnClickListener(null) }
+ *     }
+ * }
+ * ```
+ */
+inline fun CoroutineScope.launchAndDispose(
+    context: CoroutineContext = EmptyCoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    crossinline onLaunch: () -> DisposableHandle
+): Job = launch(context, start) { onLaunch().awaitCancellationThenDispose() }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/ReduceBrightColorsControllerExt.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/ReduceBrightColorsControllerExt.kt
new file mode 100644
index 0000000..ee00e8b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/ReduceBrightColorsControllerExt.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.qs.ReduceBrightColorsController
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.onStart
+
+fun ReduceBrightColorsController.isEnabled(): Flow<Boolean> {
+    return conflatedCallbackFlow {
+            val callback =
+                object : ReduceBrightColorsController.Listener {
+                    override fun onActivated(activated: Boolean) {
+                        trySend(activated)
+                    }
+                }
+            addCallback(callback)
+            awaitClose { removeCallback(callback) }
+        }
+        .onStart { emit(isReduceBrightColorsActivated) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Util.java b/packages/SystemUI/src/com/android/systemui/volume/Util.java
index 7edb5a5..df19013 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Util.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Util.java
@@ -17,6 +17,7 @@
 package com.android.systemui.volume;
 
 import android.media.AudioManager;
+import android.util.MathUtils;
 import android.view.View;
 
 /**
@@ -46,4 +47,27 @@
         if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
         v.setVisibility(vis ? View.VISIBLE : View.GONE);
     }
+
+    /**
+     * Translates a value from one range to another.
+     *
+     * ```
+     * Given: currentValue=3, currentRange=[0, 8], targetRange=[0, 100]
+     * Result: 37.5
+     * ```
+     */
+    public static float translateToRange(float value,
+            float valueRangeStart,
+            float valueRangeEnd,
+            float targetRangeStart,
+            float targetRangeEnd) {
+        float currentRangeLength = valueRangeEnd - valueRangeStart;
+        float targetRangeLength = targetRangeEnd - targetRangeStart;
+        if (currentRangeLength == 0f || targetRangeLength == 0f) {
+            return targetRangeStart;
+        }
+        float valueFraction = (value - valueRangeStart) / currentRangeLength;
+        return MathUtils.constrain(targetRangeStart + valueFraction * targetRangeLength,
+                targetRangeStart, targetRangeEnd);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 27a708a..cd82e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -118,7 +118,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.haptics.slider.HapticSliderViewBinder;
-import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin;
+import com.android.systemui.haptics.slider.SeekbarHapticPlugin;
 import com.android.systemui.haptics.slider.SliderHapticFeedbackConfig;
 import com.android.systemui.media.dialog.MediaOutputDialogManager;
 import com.android.systemui.plugins.VolumeDialog;
@@ -137,13 +137,13 @@
 import com.android.systemui.volume.domain.interactor.VolumePanelNavigationInteractor;
 import com.android.systemui.volume.ui.navigation.VolumeNavigator;
 
-import dagger.Lazy;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
 
+import dagger.Lazy;
+
 /**
  * Visual presentation of the volume dialog.
  *
@@ -166,6 +166,7 @@
 
     private static final int DRAWER_ANIMATION_DURATION_SHORT = 175;
     private static final int DRAWER_ANIMATION_DURATION = 250;
+    private static final int DISPLAY_RANGE_MULTIPLIER = 100;
 
     /** Shows volume dialog show animation. */
     private static final String TYPE_SHOW = "show";
@@ -826,12 +827,14 @@
         writer.print("  mSilentMode: "); writer.println(mSilentMode);
     }
 
-    private static int getImpliedLevel(SeekBar seekBar, int progress) {
-        final int m = seekBar.getMax();
-        final int n = m / 100 - 1;
-        final int level = progress == 0 ? 0
-                : progress == m ? (m / 100) : (1 + (int) ((progress / (float) m) * n));
-        return level;
+    private static int getVolumeFromProgress(StreamState state, SeekBar seekBar, int progress) {
+        return (int) Util.translateToRange(progress, seekBar.getMin(), seekBar.getMax(),
+                state.levelMin, state.levelMax);
+    }
+
+    private static int getProgressFromVolume(StreamState state, SeekBar seekBar, int volume) {
+        return (int) Util.translateToRange(volume, state.levelMin, state.levelMax, seekBar.getMin(),
+                seekBar.getMax());
     }
 
     @SuppressLint("InflateParams")
@@ -854,6 +857,8 @@
         addSliderHapticsToRow(row);
         row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
         row.number = row.view.findViewById(R.id.volume_number);
+        row.slider.setAccessibilityDelegate(
+                new VolumeDialogSeekBarAccessibilityDelegate(DISPLAY_RANGE_MULTIPLIER));
 
         row.anim = null;
 
@@ -1129,7 +1134,9 @@
         }
 
         updateSelectedRingerContainerDescription(true);
-
+        mSelectedRingerContainer.setImportantForAccessibility(
+                View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+        mSelectedRingerContainer.clearFocus();
         mIsRingerDrawerOpen = true;
     }
 
@@ -1175,7 +1182,8 @@
                 .start();
 
         updateSelectedRingerContainerDescription(false);
-
+        mSelectedRingerContainer.setImportantForAccessibility(
+                View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
         mIsRingerDrawerOpen = false;
     }
 
@@ -1746,7 +1754,7 @@
             boolean isZenMuted = mState.zenMode == Global.ZEN_MODE_ALARMS
                     || mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
                     || (mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
-                        && mState.disallowRinger);
+                    && mState.disallowRinger);
             enableRingerViewsH(!isZenMuted);
             switch (mState.ringerModeInternal) {
                 case AudioManager.RINGER_MODE_VIBRATE:
@@ -1796,7 +1804,7 @@
             public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
                 super.onInitializeAccessibilityNodeInfo(host, info);
                 info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
-                                AccessibilityNodeInfo.ACTION_CLICK, hintLabel));
+                        AccessibilityNodeInfo.ACTION_CLICK, hintLabel));
             }
         });
     }
@@ -1913,12 +1921,12 @@
                 : false;
 
         // update slider max
-        final int max = ss.levelMax * 100;
+        final int max = ss.levelMax * DISPLAY_RANGE_MULTIPLIER;
         if (max != row.slider.getMax()) {
             row.slider.setMax(max);
         }
         // update slider min
-        final int min = ss.levelMin * 100;
+        final int min = ss.levelMin * DISPLAY_RANGE_MULTIPLIER;
         if (min != row.slider.getMin()) {
             row.slider.setMin(min);
         }
@@ -2066,7 +2074,7 @@
             return;  // don't update if user is sliding
         }
         final int progress = row.slider.getProgress();
-        final int level = getImpliedLevel(row.slider, progress);
+        final int level = getVolumeFromProgress(row.ss, row.slider, progress);
         final boolean rowVisible = row.view.getVisibility() == VISIBLE;
         final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
                 < USER_ATTEMPT_GRACE_PERIOD;
@@ -2082,7 +2090,7 @@
                 return;  // don't clamp if visible
             }
         }
-        final int newProgress = vlevel * 100;
+        final int newProgress = getProgressFromVolume(row.ss, row.slider, vlevel);
         if (progress != newProgress) {
             if (mShowing && rowVisible) {
                 // animate!
@@ -2527,13 +2535,13 @@
                     + " onProgressChanged " + progress + " fromUser=" + fromUser);
             if (!fromUser) return;
             if (mRow.ss.levelMin > 0) {
-                final int minProgress = mRow.ss.levelMin * 100;
+                final int minProgress = getProgressFromVolume(mRow.ss, seekBar, mRow.ss.levelMin);
                 if (progress < minProgress) {
                     seekBar.setProgress(minProgress);
                     progress = minProgress;
                 }
             }
-            final int userLevel = getImpliedLevel(seekBar, progress);
+            final int userLevel = getVolumeFromProgress(mRow.ss, seekBar, progress);
             if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) {
                 mRow.userAttempt = SystemClock.uptimeMillis();
                 if (mRow.requestedLevel != userLevel) {
@@ -2566,7 +2574,7 @@
             }
             mRow.tracking = false;
             mRow.userAttempt = SystemClock.uptimeMillis();
-            final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
+            final int userLevel = getVolumeFromProgress(mRow.ss, seekBar, seekBar.getProgress());
             Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel);
             if (mRow.ss.level != userLevel) {
                 mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
@@ -2632,7 +2640,7 @@
         private ObjectAnimator anim;  // slider progress animation for non-touch-related updates
         private int animTargetProgress;
         private int lastAudibleLevel = 1;
-        private SeekableSliderHapticPlugin mHapticPlugin;
+        private SeekbarHapticPlugin mHapticPlugin;
         private int mProgressHapticsType = PROGRESS_HAPTICS_DISABLED;
 
         void setIcon(int iconRes, Resources.Theme theme) {
@@ -2650,7 +2658,7 @@
                 com.android.systemui.util.time.SystemClock systemClock) {
             if (mHapticPlugin != null) return;
 
-            mHapticPlugin = new SeekableSliderHapticPlugin(
+            mHapticPlugin = new SeekbarHapticPlugin(
                 vibratorHelper,
                 systemClock,
                 sSliderHapticFeedbackConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogSeekBarAccessibilityDelegate.kt b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogSeekBarAccessibilityDelegate.kt
new file mode 100644
index 0000000..cd31a95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogSeekBarAccessibilityDelegate.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume
+
+import android.os.Bundle
+import android.view.View
+import android.view.View.AccessibilityDelegate
+import android.view.accessibility.AccessibilityNodeInfo
+import android.widget.SeekBar
+import com.android.internal.R
+
+class VolumeDialogSeekBarAccessibilityDelegate(
+    private val accessibilityStep: Int,
+) : AccessibilityDelegate() {
+
+    override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean {
+        require(host is SeekBar) { "This class only works with the SeekBar" }
+        val seekBar: SeekBar = host
+        if (
+            action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD ||
+                action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
+        ) {
+            var increment = accessibilityStep
+            if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
+                increment = -increment
+            }
+
+            return super.performAccessibilityAction(
+                host,
+                R.id.accessibilityActionSetProgress,
+                Bundle().apply {
+                    putFloat(
+                        AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE,
+                        (seekBar.progress + increment).coerceIn(seekBar.min, seekBar.max).toFloat(),
+                    )
+                },
+            )
+        }
+        return super.performAccessibilityAction(host, action, args)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/UiEventLoggerStartableModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/UiEventLoggerStartableModule.kt
new file mode 100644
index 0000000..9b84090
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/UiEventLoggerStartableModule.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.systemui.volume.dagger
+
+import com.android.systemui.volume.domain.startable.AudioModeLoggerStartable
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+@Module
+interface UiEventLoggerStartableModule {
+
+    @Binds
+    @IntoSet
+    fun bindAudioModeLoggerStartable(
+        audioModeLoggerStartable: AudioModeLoggerStartable,
+    ): VolumePanelStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
new file mode 100644
index 0000000..ed44699
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.interactor
+
+import android.bluetooth.BluetoothAdapter
+import android.media.AudioDeviceInfo
+import android.media.AudioDeviceInfo.TYPE_WIRED_HEADPHONES
+import android.media.AudioDeviceInfo.TYPE_WIRED_HEADSET
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.settingslib.media.BluetoothMediaDevice
+import com.android.settingslib.media.MediaDevice
+import com.android.settingslib.media.MediaDevice.MediaDeviceType
+import com.android.settingslib.volume.data.repository.AudioRepository
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.volume.domain.model.AudioOutputDevice
+import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
+import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Provides a currently active audio device data. */
+@VolumePanelScope
+@OptIn(ExperimentalCoroutinesApi::class)
+class AudioOutputInteractor
+@Inject
+constructor(
+    audioRepository: AudioRepository,
+    audioModeInteractor: AudioModeInteractor,
+    @VolumePanelScope scope: CoroutineScope,
+    @Background backgroundCoroutineContext: CoroutineContext,
+    private val localBluetoothManager: LocalBluetoothManager?,
+    private val bluetoothAdapter: BluetoothAdapter?,
+    private val deviceIconInteractor: DeviceIconInteractor,
+    private val mediaOutputInteractor: MediaOutputInteractor,
+    private val localMediaRepositoryFactory: LocalMediaRepositoryFactory,
+) {
+
+    val currentAudioDevice: Flow<AudioOutputDevice> =
+        audioModeInteractor.isOngoingCall
+            .flatMapLatest { isOngoingCall ->
+                if (isOngoingCall) {
+                    audioRepository.communicationDevice.map { communicationDevice ->
+                        communicationDevice?.toAudioOutputDevice()
+                    }
+                } else {
+                    mediaOutputInteractor.defaultActiveMediaSession
+                        .flatMapLatest {
+                            localMediaRepositoryFactory
+                                .create(it?.packageName)
+                                .currentConnectedDevice
+                        }
+                        .map { mediaDevice -> mediaDevice?.toAudioOutputDevice() }
+                }
+            }
+            .map { it ?: AudioOutputDevice.Unknown }
+            .flowOn(backgroundCoroutineContext)
+            .stateIn(scope, SharingStarted.Eagerly, AudioOutputDevice.Unknown)
+
+    private fun AudioDeviceInfo.toAudioOutputDevice(): AudioOutputDevice {
+        if (type == TYPE_WIRED_HEADPHONES || type == TYPE_WIRED_HEADSET) {
+            return AudioOutputDevice.Wired(
+                name = productName.toString(),
+                icon = deviceIconInteractor.loadIcon(type),
+            )
+        }
+        val cachedBluetoothDevice: CachedBluetoothDevice? =
+            if (address.isEmpty() || localBluetoothManager == null || bluetoothAdapter == null) {
+                null
+            } else {
+                val remoteDevice = bluetoothAdapter.getRemoteDevice(address)
+                localBluetoothManager.cachedDeviceManager.findDevice(remoteDevice)
+            }
+        return cachedBluetoothDevice?.let {
+            AudioOutputDevice.Bluetooth(
+                name = it.name,
+                icon = deviceIconInteractor.loadIcon(it),
+                cachedBluetoothDevice = it,
+            )
+        }
+            ?: AudioOutputDevice.BuiltIn(
+                name = productName.toString(),
+                icon = deviceIconInteractor.loadIcon(type),
+            )
+    }
+
+    private fun MediaDevice.toAudioOutputDevice(): AudioOutputDevice {
+        return when {
+            this is BluetoothMediaDevice ->
+                AudioOutputDevice.Bluetooth(
+                    name = name,
+                    icon = icon,
+                    cachedBluetoothDevice = cachedDevice,
+                )
+            deviceType == MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE ->
+                AudioOutputDevice.Wired(
+                    name = name,
+                    icon = icon,
+                )
+            else ->
+                AudioOutputDevice.BuiltIn(
+                    name = name,
+                    icon = icon,
+                )
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractor.kt
new file mode 100644
index 0000000..a2f7d4a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractor.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.interactor
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.media.AudioDeviceInfo
+import com.android.settingslib.R
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.media.DeviceIconUtil
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import javax.inject.Inject
+
+/** Utility class to load an icon for a [CachedBluetoothDevice]. */
+@VolumePanelScope
+@SuppressLint("UseCompatLoadingForDrawables")
+class DeviceIconInteractor @Inject constructor(@Application private val context: Context) {
+
+    private val iconUtil: DeviceIconUtil = DeviceIconUtil(context)
+
+    fun loadIcon(@AudioDeviceInfo.AudioDeviceType type: Int): Drawable? =
+        context.getDrawable(iconUtil.getIconResIdFromAudioDeviceType(type))
+
+    fun loadIcon(cachedDevice: CachedBluetoothDevice): Drawable? {
+        return if (BluetoothUtils.isAdvancedUntetheredDevice(cachedDevice.device))
+            context.getDrawable(R.drawable.ic_earbuds_advanced)
+        else BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).first
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/model/AudioOutputDevice.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/model/AudioOutputDevice.kt
new file mode 100644
index 0000000..ba0b082
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/model/AudioOutputDevice.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.model
+
+import android.graphics.drawable.Drawable
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+
+/** Models an audio output device. */
+sealed interface AudioOutputDevice {
+
+    val name: String
+    val icon: Drawable?
+
+    /** Models a built audio output device. */
+    data class BuiltIn(
+        override val name: String,
+        override val icon: Drawable?,
+    ) : AudioOutputDevice
+
+    /** Models a wired audio output device. */
+    data class Wired(
+        override val name: String,
+        override val icon: Drawable?,
+    ) : AudioOutputDevice
+
+    /** Models a bluetooth audio output device. */
+    data class Bluetooth(
+        override val name: String,
+        override val icon: Drawable?,
+        val cachedBluetoothDevice: CachedBluetoothDevice,
+    ) : AudioOutputDevice
+
+    /** Models a state when the current audio output device is unknown. */
+    data object Unknown : AudioOutputDevice {
+        override val name: String
+            get() = error("Unsupported for unknown device")
+
+        override val icon: Drawable
+            get() = error("Unsupported for unknown device")
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt
new file mode 100644
index 0000000..1244757
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.startable
+
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.launch
+
+/** Logger for audio mode */
+@VolumePanelScope
+class AudioModeLoggerStartable
+@Inject
+constructor(
+    @VolumePanelScope private val scope: CoroutineScope,
+    private val uiEventLogger: UiEventLogger,
+    private val audioModeInteractor: AudioModeInteractor,
+) : VolumePanelStartable {
+
+    override fun start() {
+        scope.launch {
+            audioModeInteractor.isOngoingCall.distinctUntilChanged().collect { ongoingCall ->
+                uiEventLogger.log(
+                    if (ongoingCall) VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_CALLING
+                    else VolumePanelUiEvent.VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_NORMAL
+                )
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt
index 8f18aa8..8ce3b1f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/data/repository/AncSliceRepository.kt
@@ -41,12 +41,14 @@
 interface AncSliceRepository {
 
     /**
-     * ANC slice with a given width. Emits null when there is no ANC slice available. This can mean
-     * that:
+     * ANC slice with a given width. [isCollapsed] slice shows a single button, and expanded shows a
+     * row buttons.
+     *
+     * Emits null when there is no ANC slice available. This can mean that:
      * - there is no supported device connected;
      * - there is no slice provider for the uri;
      */
-    fun ancSlice(width: Int): Flow<Slice?>
+    fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?>
 }
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -60,9 +62,14 @@
 
     private val localMediaRepository = mediaRepositoryFactory.create(null)
 
-    override fun ancSlice(width: Int): Flow<Slice?> {
+    override fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> {
         return localMediaRepository.currentConnectedDevice
-            .map { (it as? BluetoothMediaDevice)?.cachedDevice?.device?.getExtraControlUri(width) }
+            .map {
+                (it as? BluetoothMediaDevice)
+                    ?.cachedDevice
+                    ?.device
+                    ?.getExtraControlUri(width, isCollapsed, hideLabel)
+            }
             .distinctUntilChanged()
             .flatMapLatest { sliceUri ->
                 sliceUri ?: return@flatMapLatest flowOf(null)
@@ -71,7 +78,11 @@
             .flowOn(backgroundCoroutineContext)
     }
 
-    private fun BluetoothDevice.getExtraControlUri(width: Int): Uri? {
+    private fun BluetoothDevice.getExtraControlUri(
+        width: Int,
+        isCollapsed: Boolean,
+        hideLabel: Boolean
+    ): Uri? {
         val uri: String? = BluetoothUtils.getControlUriMetaData(this)
         uri ?: return null
 
@@ -81,7 +92,8 @@
             Uri.parse(
                 "$uri$width" +
                     "&version=${SliceParameters.VERSION}" +
-                    "&is_collapsed=${SliceParameters.IS_COLLAPSED}"
+                    "&is_collapsed=$isCollapsed" +
+                    "&hide_label=$hideLabel"
             )
         }
     }
@@ -98,11 +110,5 @@
          * 2) new slice
          */
         const val VERSION = 2
-
-        /**
-         * Collapsed slice shows a single button, and expanded shows a row buttons. Supported since
-         * [VERSION]==2.
-         */
-        const val IS_COLLAPSED = false
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt
index 89b9274..dc4be26 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/AncAvailabilityCriteria.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.volume.panel.component.anc.domain
 
 import com.android.systemui.volume.panel.component.anc.domain.interactor.AncSliceInteractor
+import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
 import javax.inject.Inject
@@ -31,5 +32,6 @@
     private val ancSliceInteractor: AncSliceInteractor,
 ) : ComponentAvailabilityCriteria {
 
-    override fun isAvailable(): Flow<Boolean> = ancSliceInteractor.ancSlice.map { it != null }
+    override fun isAvailable(): Flow<Boolean> =
+        ancSliceInteractor.ancSlices.map { it is AncSlices.Ready }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt
index 91af622..cefa269 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt
@@ -20,16 +20,19 @@
 import android.app.slice.SliceItem.FORMAT_SLICE
 import androidx.slice.Slice
 import com.android.systemui.volume.panel.component.anc.data.repository.AncSliceRepository
+import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
 
 /** Provides a valid slice from [AncSliceRepository]. */
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -41,25 +44,35 @@
     scope: CoroutineScope,
 ) {
 
-    // Start with a positive width to check is the Slice is available.
-    private val width = MutableStateFlow(1)
+    // Any positive width to check if the Slice is available.
+    private val buttonSliceWidth = MutableStateFlow(1)
+    private val popupSliceWidth = MutableStateFlow(1)
 
-    /** Provides a valid ANC slice. */
-    val ancSlice: SharedFlow<Slice?> =
-        width
-            .flatMapLatest { width -> ancSliceRepository.ancSlice(width) }
-            .map { slice ->
-                if (slice?.isValidSlice() == true) {
-                    slice
+    val ancSlices: StateFlow<AncSlices> =
+        combine(
+                buttonSliceWidth.flatMapLatest {
+                    ancSlice(width = it, isCollapsed = true, hideLabel = true)
+                },
+                popupSliceWidth.flatMapLatest {
+                    ancSlice(width = it, isCollapsed = false, hideLabel = false)
+                }
+            ) { buttonSlice, popupSlice ->
+                if (buttonSlice != null && popupSlice != null) {
+                    AncSlices.Ready(buttonSlice = buttonSlice, popupSlice = popupSlice)
                 } else {
-                    null
+                    AncSlices.Unavailable
                 }
             }
-            .shareIn(scope, SharingStarted.Eagerly, replay = 1)
+            .stateIn(scope, SharingStarted.Eagerly, AncSlices.Unavailable)
 
-    /** Updates the width of the [ancSlice] */
-    fun changeWidth(newWidth: Int) {
-        width.value = newWidth
+    /**
+     * Provides a valid [isCollapsed] ANC slice for a given [width]. Use [hideLabel] == true to
+     * remove the labels from the [Slice].
+     */
+    private fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> {
+        return ancSliceRepository
+            .ancSlice(width = width, isCollapsed = isCollapsed, hideLabel = hideLabel)
+            .filter { it?.isValidSlice() != false }
     }
 
     private fun Slice.isValidSlice(): Boolean {
@@ -73,4 +86,20 @@
         }
         return false
     }
+
+    /**
+     * Call this to update [AncSlices.Ready.popupSlice] width in a reaction to container size
+     * change.
+     */
+    fun onPopupSliceWidthChanged(width: Int) {
+        popupSliceWidth.tryEmit(width)
+    }
+
+    /**
+     * Call this to update [AncSlices.Ready.buttonSlice] width in a reaction to container size
+     * change.
+     */
+    fun onButtonSliceWidthChanged(width: Int) {
+        buttonSliceWidth.tryEmit(width)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/model/AncSlices.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/model/AncSlices.kt
new file mode 100644
index 0000000..3cd4e67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/model/AncSlices.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.anc.domain.model
+
+import androidx.slice.Slice
+
+/** Modes current ANC slices state */
+sealed interface AncSlices {
+
+    data class Ready(
+        val popupSlice: Slice,
+        val buttonSlice: Slice,
+    ) : AncSlices
+
+    /** Couldn't one or both slices. */
+    data object Unavailable : AncSlices
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
index eb96f6c..bee79bb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
@@ -16,52 +16,56 @@
 
 package com.android.systemui.volume.panel.component.anc.ui.viewmodel
 
-import android.content.Context
 import androidx.slice.Slice
-import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.res.R
+import com.android.systemui.volume.panel.component.anc.domain.AncAvailabilityCriteria
 import com.android.systemui.volume.panel.component.anc.domain.interactor.AncSliceInteractor
-import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
+import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /** Volume Panel ANC component view model. */
+@OptIn(ExperimentalCoroutinesApi::class)
 @VolumePanelScope
 class AncViewModel
 @Inject
 constructor(
-    @Application private val context: Context,
     @VolumePanelScope private val coroutineScope: CoroutineScope,
     private val interactor: AncSliceInteractor,
+    private val availabilityCriteria: AncAvailabilityCriteria,
 ) {
 
-    /** ANC [Slice]. Null when there is no slice available for ANC. */
-    val slice: StateFlow<Slice?> =
-        interactor.ancSlice.stateIn(coroutineScope, SharingStarted.Eagerly, null)
+    val isAvailable: Flow<Boolean>
+        get() = availabilityCriteria.isAvailable()
 
-    /**
-     * ButtonViewModel to be shown in the VolumePanel. Null when there is no ANC Slice available.
-     */
-    val button: StateFlow<ButtonViewModel?> =
-        interactor.ancSlice
-            .map { slice ->
-                slice?.let {
-                    ButtonViewModel(
-                        Icon.Resource(R.drawable.ic_noise_aware, null),
-                        context.getString(R.string.volume_panel_noise_control_title)
-                    )
-                }
-            }
+    /** ANC [Slice]. Null when there is no slice available for ANC. */
+    val popupSlice: StateFlow<Slice?> =
+        interactor.ancSlices
+            .filterIsInstance<AncSlices.Ready>()
+            .map { it.popupSlice }
             .stateIn(coroutineScope, SharingStarted.Eagerly, null)
 
-    /** Call this to update [slice] width in a reaction to container size change. */
-    fun changeSliceWidth(width: Int) {
-        interactor.changeWidth(width)
+    /** Button [Slice] to be shown in the VolumePanel. Null when there is no ANC Slice available. */
+    val buttonSlice: StateFlow<Slice?> =
+        interactor.ancSlices
+            .filterIsInstance<AncSlices.Ready>()
+            .map { it.buttonSlice }
+            .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+
+    /** Call this to update [popupSlice] width in a reaction to container size change. */
+    fun onPopupSliceWidthChanged(width: Int) {
+        interactor.onPopupSliceWidthChanged(width)
+    }
+
+    /** Call this to update [buttonSlice] width in a reaction to container size change. */
+    fun onButtonSliceWidthChanged(width: Int) {
+        interactor.onButtonSliceWidthChanged(width)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt
index 04d7b1f..3ca9cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/bottombar/ui/viewmodel/BottomBarViewModel.kt
@@ -18,8 +18,10 @@
 
 import android.content.Intent
 import android.provider.Settings
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
 import javax.inject.Inject
 
@@ -29,6 +31,7 @@
 constructor(
     private val activityStarter: ActivityStarter,
     private val volumePanelViewModel: VolumePanelViewModel,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
     fun onDoneClicked() {
@@ -36,6 +39,7 @@
     }
 
     fun onSettingsClicked() {
+        uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_SOUND_SETTINGS_CLICKED)
         activityStarter.startActivityDismissingKeyguard(
             /* intent = */ Intent(Settings.ACTION_SOUND_SETTINGS),
             /* onlyProvisioned = */ false,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ButtonViewModel.kt
index 754d258..4d11f44 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ButtonViewModel.kt
@@ -1,17 +1,17 @@
 /*
  * Copyright (C) 2024 The Android Open Source Project
  *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- *       http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package com.android.systemui.volume.panel.component.button.ui.viewmodel
@@ -22,4 +22,5 @@
 data class ButtonViewModel(
     val icon: Icon,
     val label: CharSequence,
+    val isActive: Boolean = true,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt
deleted file mode 100644
index 6c47aec..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.button.ui.viewmodel
-
-import com.android.systemui.common.shared.model.Icon
-
-data class ToggleButtonViewModel(
-    val isChecked: Boolean,
-    val icon: Icon,
-    val label: CharSequence,
-)
-
-fun ToggleButtonViewModel.toButtonViewModel(): ButtonViewModel =
-    ButtonViewModel(icon = icon, label = label)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
index aab825fb..85da1d0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
@@ -16,18 +16,36 @@
 
 package com.android.systemui.volume.panel.component.captioning.domain
 
+import com.android.internal.logging.UiEventLogger
 import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.shareIn
 
 @VolumePanelScope
 class CaptioningAvailabilityCriteria
 @Inject
-constructor(private val captioningInteractor: CaptioningInteractor) :
-    ComponentAvailabilityCriteria {
+constructor(
+    captioningInteractor: CaptioningInteractor,
+    @VolumePanelScope private val scope: CoroutineScope,
+    private val uiEventLogger: UiEventLogger,
+) : ComponentAvailabilityCriteria {
 
-    override fun isAvailable(): Flow<Boolean> =
+    private val availability =
         captioningInteractor.isSystemAudioCaptioningUiEnabled
+            .onEach { visible ->
+                uiEventLogger.log(
+                    if (visible) VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_SHOWN
+                    else VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_GONE
+                )
+            }
+            .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+
+    override fun isAvailable(): Flow<Boolean> = availability
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt
index 92f8f22..ca5aef8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt
@@ -17,11 +17,13 @@
 package com.android.systemui.volume.panel.component.captioning.ui.viewmodel
 
 import android.content.Context
+import com.android.internal.logging.UiEventLogger
 import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.res.R
-import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
@@ -38,13 +40,14 @@
     private val context: Context,
     private val captioningInteractor: CaptioningInteractor,
     @VolumePanelScope private val coroutineScope: CoroutineScope,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
-    val buttonViewModel: StateFlow<ToggleButtonViewModel?> =
+    val buttonViewModel: StateFlow<ButtonViewModel?> =
         captioningInteractor.isSystemAudioCaptioningEnabled
             .map { isEnabled ->
-                ToggleButtonViewModel(
-                    isChecked = isEnabled,
+                ButtonViewModel(
+                    isActive = isEnabled,
                     icon =
                         Icon.Resource(
                             if (isEnabled) R.drawable.ic_volume_odi_captions
@@ -57,6 +60,13 @@
             .stateIn(coroutineScope, SharingStarted.Eagerly, null)
 
     fun setIsSystemAudioCaptioningEnabled(enabled: Boolean) {
+        uiEventLogger.logWithPosition(
+            VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_CLICKED,
+            0,
+            null,
+            if (enabled) VolumePanelUiEvent.LIVE_CAPTION_TOGGLE_ENABLED
+            else VolumePanelUiEvent.LIVE_CAPTION_TOGGLE_DISABLED
+        )
         coroutineScope.launch { captioningInteractor.setIsSystemAudioCaptioningEnabled(enabled) }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
index eebb6fb..22c0530 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
@@ -21,7 +21,7 @@
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.animation.Expandable
 import com.android.systemui.media.dialog.MediaOutputDialogManager
-import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlayback
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import javax.inject.Inject
 
@@ -33,10 +33,10 @@
     private val mediaOutputDialogManager: MediaOutputDialogManager,
 ) {
 
-    fun onBarClick(sessionWithPlayback: SessionWithPlayback?, expandable: Expandable) {
-        if (sessionWithPlayback?.playback?.isActive == true) {
+    fun onBarClick(sessionWithPlaybackState: SessionWithPlaybackState?, expandable: Expandable) {
+        if (sessionWithPlaybackState?.isPlaybackActive == true) {
             mediaOutputDialogManager.createAndShowWithController(
-                sessionWithPlayback.session.packageName,
+                sessionWithPlaybackState.session.packageName,
                 false,
                 expandable.dialogController()
             )
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index 41ad035..83b8029 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -94,7 +94,7 @@
 
     /** Currently connected [MediaDevice]. */
     val currentConnectedDevice: Flow<MediaDevice?> =
-        localMediaRepository.flatMapLatest { it.currentConnectedDevice }
+        localMediaRepository.flatMapLatest { it.currentConnectedDevice }.distinctUntilChanged()
 
     private suspend fun getApplicationLabel(packageName: String): CharSequence? {
         return try {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
deleted file mode 100644
index c4476fc..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
-
-import android.media.session.PlaybackState
-
-data class SessionWithPlayback(
-    val session: MediaDeviceSession,
-    val playback: PlaybackState,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlaybackState.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlaybackState.kt
new file mode 100644
index 0000000..bac969d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlaybackState.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+
+data class SessionWithPlaybackState(
+    val session: MediaDeviceSession,
+    val isPlaybackActive: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
index fc9602e..d60d981 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.volume.panel.component.mediaoutput.ui.viewmodel
 
 import android.content.Context
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.Color
 import com.android.systemui.common.shared.model.Icon
@@ -24,8 +25,10 @@
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
-import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlayback
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,7 +37,7 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.stateIn
 
 /** Models the UI of the Media Output Volume Panel component. */
@@ -48,34 +51,42 @@
     private val actionsInteractor: MediaOutputActionsInteractor,
     private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
     interactor: MediaOutputInteractor,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
-    private val sessionWithPlayback: StateFlow<SessionWithPlayback?> =
+    private val sessionWithPlaybackState: StateFlow<Result<SessionWithPlaybackState?>> =
         interactor.defaultActiveMediaSession
             .flatMapLatest { session ->
                 if (session == null) {
-                    flowOf(null)
+                    flowOf(Result.Data<SessionWithPlaybackState?>(null))
                 } else {
-                    mediaDeviceSessionInteractor.playbackState(session).map { playback ->
-                        playback?.let { SessionWithPlayback(session, it) }
+                    mediaDeviceSessionInteractor.playbackState(session).mapNotNull { playback ->
+                        playback?.let {
+                            Result.Data<SessionWithPlaybackState?>(
+                                SessionWithPlaybackState(session, playback.isActive())
+                            )
+                        }
                     }
                 }
             }
             .stateIn(
                 coroutineScope,
                 SharingStarted.Eagerly,
-                null,
+                Result.Loading(),
             )
 
     val connectedDeviceViewModel: StateFlow<ConnectedDeviceViewModel?> =
-        combine(sessionWithPlayback, interactor.currentConnectedDevice) {
+        combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
                 mediaDeviceSession,
                 currentConnectedDevice ->
+                if (mediaDeviceSession !is Result.Data) {
+                    return@combine null
+                }
                 ConnectedDeviceViewModel(
-                    if (mediaDeviceSession?.playback?.isActive == true) {
+                    if (mediaDeviceSession.data?.isPlaybackActive == true) {
                         context.getString(
                             R.string.media_output_label_title,
-                            mediaDeviceSession.session.appLabel
+                            mediaDeviceSession.data.session.appLabel
                         )
                     } else {
                         context.getString(R.string.media_output_title_without_playing)
@@ -90,16 +101,16 @@
             )
 
     val deviceIconViewModel: StateFlow<DeviceIconViewModel?> =
-        combine(sessionWithPlayback, interactor.currentConnectedDevice) {
+        combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
                 mediaDeviceSession,
                 currentConnectedDevice ->
-                if (mediaDeviceSession?.playback?.isActive == true) {
-                    val icon =
-                        currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
-                            ?: Icon.Resource(
-                                com.android.internal.R.drawable.ic_bt_headphones_a2dp,
-                                null
-                            )
+                if (mediaDeviceSession !is Result.Data) {
+                    return@combine null
+                }
+                val icon: Icon =
+                    currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
+                        ?: Icon.Resource(R.drawable.ic_media_home_devices, null)
+                if (mediaDeviceSession.data?.isPlaybackActive == true) {
                     DeviceIconViewModel.IsPlaying(
                         icon = icon,
                         iconColor =
@@ -109,7 +120,7 @@
                     )
                 } else {
                     DeviceIconViewModel.IsNotPlaying(
-                        icon = Icon.Resource(R.drawable.ic_media_home_devices, null),
+                        icon = icon,
                         iconColor =
                             Color.Attribute(
                                 com.android.internal.R.attr.materialColorOnSurfaceVariant
@@ -126,6 +137,8 @@
             )
 
     fun onBarClick(expandable: Expandable) {
-        actionsInteractor.onBarClick(sessionWithPlayback.value, expandable)
+        uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_MEDIA_OUTPUT_CLICKED)
+        val result = sessionWithPlaybackState.value
+        actionsInteractor.onBarClick((result as? Result.Data)?.data, expandable)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt
index 9f9275b..f7a602e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt
@@ -16,13 +16,10 @@
 
 package com.android.systemui.volume.panel.component.spatial.ui.viewmodel
 
-import com.android.systemui.common.shared.model.Color
-import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
 import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel
 
 data class SpatialAudioButtonViewModel(
     val model: SpatialAudioEnabledModel,
-    val button: ToggleButtonViewModel,
-    val iconColor: Color,
-    val labelColor: Color,
+    val button: ButtonViewModel,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt
index f022039..4b2d26a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt
@@ -17,18 +17,17 @@
 package com.android.systemui.volume.panel.component.spatial.ui.viewmodel
 
 import android.content.Context
-import com.android.systemui.common.shared.model.Color
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.res.R
 import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
-import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel
-import com.android.systemui.volume.panel.component.button.ui.viewmodel.toButtonViewModel
 import com.android.systemui.volume.panel.component.spatial.domain.SpatialAudioAvailabilityCriteria
 import com.android.systemui.volume.panel.component.spatial.domain.interactor.SpatialAudioComponentInteractor
 import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioAvailabilityModel
 import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
@@ -46,13 +45,14 @@
     @VolumePanelScope private val scope: CoroutineScope,
     availabilityCriteria: SpatialAudioAvailabilityCriteria,
     private val interactor: SpatialAudioComponentInteractor,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
     val spatialAudioButton: StateFlow<ButtonViewModel?> =
         interactor.isEnabled
             .map {
-                it.toViewModel(true)
-                    .toButtonViewModel()
+                val isChecked = it is SpatialAudioEnabledModel.SpatialAudioEnabled
+                it.toViewModel(isChecked)
                     .copy(label = context.getString(R.string.volume_panel_spatial_audio_title))
             }
             .stateIn(scope, SharingStarted.Eagerly, null)
@@ -74,56 +74,49 @@
                     }
                     .map { isEnabled ->
                         val isChecked = isEnabled == currentIsEnabled
-                        val buttonViewModel: ToggleButtonViewModel =
-                            isEnabled.toViewModel(isChecked)
-                        SpatialAudioButtonViewModel(
-                            button = buttonViewModel,
-                            model = isEnabled,
-                            iconColor =
-                                Color.Attribute(
-                                    if (isChecked) {
-                                        com.android.internal.R.attr.materialColorOnPrimaryContainer
-                                    } else {
-                                        com.android.internal.R.attr.materialColorOnSurfaceVariant
-                                    }
-                                ),
-                            labelColor =
-                                Color.Attribute(
-                                    if (isChecked) {
-                                        com.android.internal.R.attr.materialColorOnSurface
-                                    } else {
-                                        com.android.internal.R.attr.materialColorOnSurfaceVariant
-                                    }
-                                ),
-                        )
+                        val buttonViewModel: ButtonViewModel = isEnabled.toViewModel(isChecked)
+                        SpatialAudioButtonViewModel(button = buttonViewModel, model = isEnabled)
                     }
             }
             .stateIn(scope, SharingStarted.Eagerly, emptyList())
 
     fun setEnabled(model: SpatialAudioEnabledModel) {
+        uiEventLogger.logWithPosition(
+            VolumePanelUiEvent.VOLUME_PANEL_SPATIAL_AUDIO_TOGGLE_CLICKED,
+            0,
+            null,
+            when (model) {
+                SpatialAudioEnabledModel.Disabled -> 0
+                SpatialAudioEnabledModel.SpatialAudioEnabled -> 1
+                SpatialAudioEnabledModel.HeadTrackingEnabled -> 2
+                else -> {
+                    -1
+                }
+            }
+        )
         scope.launch { interactor.setEnabled(model) }
     }
 
-    private fun SpatialAudioEnabledModel.toViewModel(isChecked: Boolean): ToggleButtonViewModel {
+    private fun SpatialAudioEnabledModel.toViewModel(isChecked: Boolean): ButtonViewModel {
         if (this is SpatialAudioEnabledModel.HeadTrackingEnabled) {
-            return ToggleButtonViewModel(
-                isChecked = isChecked,
+            return ButtonViewModel(
+                isActive = isChecked,
                 icon = Icon.Resource(R.drawable.ic_head_tracking, contentDescription = null),
                 label = context.getString(R.string.volume_panel_spatial_audio_tracking)
             )
         }
 
         if (this is SpatialAudioEnabledModel.SpatialAudioEnabled) {
-            return ToggleButtonViewModel(
-                isChecked = isChecked,
+            return ButtonViewModel(
+                isActive = isChecked,
                 icon = Icon.Resource(R.drawable.ic_spatial_audio, contentDescription = null),
                 label = context.getString(R.string.volume_panel_spatial_audio_fixed)
             )
         }
 
         if (this is SpatialAudioEnabledModel.Disabled) {
-            return ToggleButtonViewModel(
-                isChecked = isChecked,
+            return ButtonViewModel(
+                isActive = isChecked,
                 icon = Icon.Resource(R.drawable.ic_spatial_audio_off, contentDescription = null),
                 label = context.getString(R.string.volume_panel_spatial_audio_off)
             )
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
new file mode 100644
index 0000000..ac8092c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.volume.domain.interactor
+
+import android.media.AudioDeviceInfo
+import android.media.AudioManager
+import com.android.settingslib.volume.data.repository.AudioRepository
+import com.android.settingslib.volume.shared.model.AudioStream
+import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession
+import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combineTransform
+import kotlinx.coroutines.flow.stateIn
+
+/** Provides volume sliders to show in the Volume Panel. */
+@VolumePanelScope
+class AudioSlidersInteractor
+@Inject
+constructor(
+    @VolumePanelScope scope: CoroutineScope,
+    mediaOutputInteractor: MediaOutputInteractor,
+    audioRepository: AudioRepository,
+) {
+
+    val volumePanelSliders: StateFlow<List<SliderType>> =
+        combineTransform(
+                mediaOutputInteractor.activeMediaDeviceSessions,
+                mediaOutputInteractor.defaultActiveMediaSession,
+                audioRepository.communicationDevice,
+            ) { activeSessions, defaultSession, communicationDevice ->
+                coroutineScope {
+                    val viewModels = buildList {
+                        if (defaultSession?.isTheSameSession(activeSessions.remote) == true) {
+                            addSession(activeSessions.remote)
+                            addStream(AudioManager.STREAM_MUSIC)
+                        } else {
+                            addStream(AudioManager.STREAM_MUSIC)
+                            addSession(activeSessions.remote)
+                        }
+
+                        if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
+                            addStream(AudioManager.STREAM_BLUETOOTH_SCO)
+                        } else {
+                            addStream(AudioManager.STREAM_VOICE_CALL)
+                        }
+                        addStream(AudioManager.STREAM_RING)
+                        addStream(AudioManager.STREAM_NOTIFICATION)
+                        addStream(AudioManager.STREAM_ALARM)
+                    }
+                    emit(viewModels)
+                }
+            }
+            .stateIn(scope, SharingStarted.Eagerly, emptyList())
+
+    private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) {
+        if (remoteMediaDeviceSession?.canAdjustVolume == true) {
+            add(SliderType.MediaDeviceCast(remoteMediaDeviceSession))
+        }
+    }
+
+    private fun MutableList<SliderType>.addStream(stream: Int) {
+        add(SliderType.Stream(AudioStream(stream)))
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt
deleted file mode 100644
index ecd89ea..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/VolumeSliderInteractor.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package com.android.systemui.volume.panel.component.volume.domain.interactor
-
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
-import javax.inject.Inject
-
-/** Converts from slider value to volume and back. */
-@VolumePanelScope
-class VolumeSliderInteractor @Inject constructor() {
-
-    /** mimic percentage volume setting */
-    private val displayValueRange: ClosedFloatingPointRange<Float> = 0f..100f
-
-    /**
-     * Translates [volume], that belongs to [volumeRange] to the value that belongs to
-     * [displayValueRange].
-     */
-    fun processVolumeToValue(
-        volume: Int,
-        volumeRange: ClosedRange<Int>,
-    ): Float {
-        val currentRangeStart: Float = volumeRange.start.toFloat()
-        val targetRangeStart: Float = displayValueRange.start
-        val currentRangeLength: Float = (volumeRange.endInclusive.toFloat() - currentRangeStart)
-        val targetRangeLength: Float = displayValueRange.endInclusive - targetRangeStart
-        if (currentRangeLength == 0f || targetRangeLength == 0f) {
-            return 0f
-        }
-        val volumeFraction: Float = (volume.toFloat() - currentRangeStart) / currentRangeLength
-        return targetRangeStart + volumeFraction * targetRangeLength
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt
index b97123b..6129ce5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.volume.panel.component.volume.domain.model
 
 import com.android.settingslib.volume.shared.model.AudioStream
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
 
 /** The type of volume slider that can be shown at the UI. */
 sealed interface SliderType {
@@ -25,5 +26,5 @@
     data class Stream(val stream: AudioStream) : SliderType
 
     /** The represents media device casting volume. */
-    data object MediaDeviceCast : SliderType
+    data class MediaDeviceCast(val session: MediaDeviceSession) : SliderType
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
index 57b5d57..ee642a6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
@@ -18,13 +18,14 @@
 
 import android.content.Context
 import android.media.AudioManager
+import com.android.internal.logging.UiEventLogger
 import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor
 import com.android.settingslib.volume.shared.model.AudioStream
 import com.android.settingslib.volume.shared.model.AudioStreamModel
 import com.android.settingslib.volume.shared.model.RingerMode
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.res.R
-import com.android.systemui.volume.panel.component.volume.domain.interactor.VolumeSliderInteractor
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
@@ -44,7 +45,7 @@
     @Assisted private val coroutineScope: CoroutineScope,
     private val context: Context,
     private val audioVolumeInteractor: AudioVolumeInteractor,
-    private val volumeSliderInteractor: VolumeSliderInteractor,
+    private val uiEventLogger: UiEventLogger,
 ) : SliderViewModel {
 
     private val audioStream = audioStreamWrapper.audioStream
@@ -52,6 +53,7 @@
         mapOf(
             AudioStream(AudioManager.STREAM_MUSIC) to R.drawable.ic_music_note,
             AudioStream(AudioManager.STREAM_VOICE_CALL) to R.drawable.ic_call,
+            AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to R.drawable.ic_call,
             AudioStream(AudioManager.STREAM_RING) to R.drawable.ic_ring_volume,
             AudioStream(AudioManager.STREAM_NOTIFICATION) to R.drawable.ic_volume_ringer,
             AudioStream(AudioManager.STREAM_ALARM) to R.drawable.ic_volume_alarm,
@@ -60,6 +62,7 @@
         mapOf(
             AudioStream(AudioManager.STREAM_MUSIC) to R.string.stream_music,
             AudioStream(AudioManager.STREAM_VOICE_CALL) to R.string.stream_voice_call,
+            AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to R.string.stream_voice_call,
             AudioStream(AudioManager.STREAM_RING) to R.string.stream_ring,
             AudioStream(AudioManager.STREAM_NOTIFICATION) to R.string.stream_notification,
             AudioStream(AudioManager.STREAM_ALARM) to R.string.stream_alarm,
@@ -71,6 +74,21 @@
             AudioStream(AudioManager.STREAM_ALARM) to R.string.stream_alarm_unavailable,
             AudioStream(AudioManager.STREAM_MUSIC) to R.string.stream_media_unavailable,
         )
+    private val uiEventByStream =
+        mapOf(
+            AudioStream(AudioManager.STREAM_MUSIC) to
+                VolumePanelUiEvent.VOLUME_PANEL_MUSIC_SLIDER_TOUCHED,
+            AudioStream(AudioManager.STREAM_VOICE_CALL) to
+                VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED,
+            AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to
+                VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED,
+            AudioStream(AudioManager.STREAM_RING) to
+                VolumePanelUiEvent.VOLUME_PANEL_RING_SLIDER_TOUCHED,
+            AudioStream(AudioManager.STREAM_NOTIFICATION) to
+                VolumePanelUiEvent.VOLUME_PANEL_NOTIFICATION_SLIDER_TOUCHED,
+            AudioStream(AudioManager.STREAM_ALARM) to
+                VolumePanelUiEvent.VOLUME_PANEL_ALARM_SLIDER_TOUCHED,
+        )
 
     override val slider: StateFlow<SliderState> =
         combine(
@@ -90,6 +108,10 @@
         }
     }
 
+    override fun onValueChangeFinished() {
+        uiEventByStream[audioStream]?.let { uiEventLogger.log(it) }
+    }
+
     override fun toggleMuted(state: SliderState) {
         val audioViewModel = state as? State
         audioViewModel ?: return
@@ -105,10 +127,6 @@
         return State(
             value = volume.toFloat(),
             valueRange = volumeRange.first.toFloat()..volumeRange.last.toFloat(),
-            valueText =
-                SliderViewModel.formatValue(
-                    volumeSliderInteractor.processVolumeToValue(volume, volumeRange)
-                ),
             icon = getIcon(ringerMode),
             label = labelsByStream[audioStream]?.let(context::getString)
                     ?: error("No label for the stream: $audioStream"),
@@ -157,7 +175,6 @@
         override val valueRange: ClosedFloatingPointRange<Float>,
         override val icon: Icon,
         override val label: String,
-        override val valueText: String,
         override val disabledMessage: String?,
         override val isEnabled: Boolean,
         override val a11yStep: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt
index 8d8fa17..956ab66 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.res.R
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
-import com.android.systemui.volume.panel.component.volume.domain.interactor.VolumeSliderInteractor
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
@@ -41,7 +40,6 @@
     @Assisted private val coroutineScope: CoroutineScope,
     private val context: Context,
     private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
-    private val volumeSliderInteractor: VolumeSliderInteractor,
 ) : SliderViewModel {
 
     override val slider: StateFlow<SliderState> =
@@ -56,6 +54,8 @@
         }
     }
 
+    override fun onValueChangeFinished() {}
+
     override fun toggleMuted(state: SliderState) {
         // do nothing because this action isn't supported for Cast sliders.
     }
@@ -66,13 +66,6 @@
             value = currentVolume.toFloat(),
             valueRange = volumeRange.first.toFloat()..volumeRange.last.toFloat(),
             icon = Icon.Resource(R.drawable.ic_cast, null),
-            valueText =
-                SliderViewModel.formatValue(
-                    volumeSliderInteractor.processVolumeToValue(
-                        volume = currentVolume,
-                        volumeRange = volumeRange,
-                    )
-                ),
             label = context.getString(R.string.media_device_cast),
             isEnabled = true,
             a11yStep = 1
@@ -83,13 +76,13 @@
         override val value: Float,
         override val valueRange: ClosedFloatingPointRange<Float>,
         override val icon: Icon,
-        override val valueText: String,
         override val label: String,
         override val isEnabled: Boolean,
         override val a11yStep: Int,
     ) : SliderState {
         override val disabledMessage: String?
             get() = null
+
         override val isMutable: Boolean
             get() = false
     }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt
index 8eb0b89..d71a9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt
@@ -28,7 +28,6 @@
     val valueRange: ClosedFloatingPointRange<Float>
     val icon: Icon?
     val isEnabled: Boolean
-    val valueText: String
     val label: String
     /**
      * A11y slider controls works by adjusting one step up or down. The default slider step isn't
@@ -42,7 +41,6 @@
         override val value: Float = 0f
         override val valueRange: ClosedFloatingPointRange<Float> = 0f..1f
         override val icon: Icon? = null
-        override val valueText: String = ""
         override val label: String = ""
         override val disabledMessage: String? = null
         override val a11yStep: Int = 0
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt
index e78f833..7ded8c5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderViewModel.kt
@@ -25,10 +25,7 @@
 
     fun onValueChanged(state: SliderState, newValue: Float)
 
+    fun onValueChangeFinished()
+
     fun toggleMuted(state: SliderState)
-
-    companion object {
-
-        fun formatValue(value: Float): String = "%.0f".format(value)
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 09e56c1..741f5cf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -16,12 +16,12 @@
 
 package com.android.systemui.volume.panel.component.volume.ui.viewmodel
 
-import android.media.AudioManager
 import com.android.settingslib.volume.shared.model.AudioStream
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
-import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession
+import com.android.systemui.volume.panel.component.volume.domain.interactor.AudioSlidersInteractor
+import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
 import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel
 import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel
 import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel
@@ -33,12 +33,12 @@
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combineTransform
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.transformLatest
 import kotlinx.coroutines.launch
 
 /**
@@ -55,28 +55,21 @@
     private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
     private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory,
     private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory,
+    streamsInteractor: AudioSlidersInteractor,
 ) {
 
     val sliderViewModels: StateFlow<List<SliderViewModel>> =
-        combineTransform(
-                mediaOutputInteractor.activeMediaDeviceSessions,
-                mediaOutputInteractor.defaultActiveMediaSession,
-            ) { activeSessions, defaultSession ->
+        streamsInteractor.volumePanelSliders
+            .transformLatest { sliderTypes ->
                 coroutineScope {
-                    val viewModels = buildList {
-                        if (defaultSession?.isTheSameSession(activeSessions.remote) == true) {
-                            addRemoteViewModelIfNeeded(this, activeSessions.remote)
-                            addStreamViewModel(this, AudioManager.STREAM_MUSIC)
-                        } else {
-                            addStreamViewModel(this, AudioManager.STREAM_MUSIC)
-                            addRemoteViewModelIfNeeded(this, activeSessions.remote)
+                    val viewModels =
+                        sliderTypes.map { type ->
+                            when (type) {
+                                is SliderType.Stream -> createStreamViewModel(type.stream)
+                                is SliderType.MediaDeviceCast ->
+                                    createSessionViewModel(type.session)
+                            }
                         }
-
-                        addStreamViewModel(this, AudioManager.STREAM_VOICE_CALL)
-                        addStreamViewModel(this, AudioManager.STREAM_RING)
-                        addStreamViewModel(this, AudioManager.STREAM_NOTIFICATION)
-                        addStreamViewModel(this, AudioManager.STREAM_ALARM)
-                    }
                     emit(viewModels)
                 }
             }
@@ -98,29 +91,18 @@
         scope.launch { mutableIsExpanded.emit(isExpanded) }
     }
 
-    private fun CoroutineScope.addRemoteViewModelIfNeeded(
-        list: MutableList<SliderViewModel>,
-        remoteMediaDeviceSession: MediaDeviceSession?
-    ) {
-        if (remoteMediaDeviceSession?.canAdjustVolume == true) {
-            val viewModel =
-                castVolumeSliderViewModelFactory.create(
-                    remoteMediaDeviceSession,
-                    this,
-                )
-            list.add(viewModel)
-        }
+    private fun CoroutineScope.createSessionViewModel(
+        session: MediaDeviceSession
+    ): CastVolumeSliderViewModel {
+        return castVolumeSliderViewModelFactory.create(session, this)
     }
 
-    private fun CoroutineScope.addStreamViewModel(
-        list: MutableList<SliderViewModel>,
-        stream: Int,
-    ) {
-        val viewModel =
-            streamSliderViewModelFactory.create(
-                AudioStreamSliderViewModel.FactoryAudioStreamWrapper(AudioStream(stream)),
-                this,
-            )
-        list.add(viewModel)
+    private fun CoroutineScope.createStreamViewModel(
+        stream: AudioStream,
+    ): AudioStreamSliderViewModel {
+        return streamSliderViewModelFactory.create(
+            AudioStreamSliderViewModel.FactoryAudioStreamWrapper(stream),
+            this,
+        )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt
index d1d5390..f889ed6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/DefaultMultibindsModule.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.volume.panel.dagger
 
 import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
 import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
 import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent
 import dagger.Module
@@ -31,4 +32,6 @@
     @Multibinds fun criteriaMap(): Map<VolumePanelComponentKey, ComponentAvailabilityCriteria>
 
     @Multibinds fun components(): Map<VolumePanelComponentKey, VolumePanelUiComponent>
+
+    @Multibinds fun startables(): Set<VolumePanelStartable>
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
index d868c33..ec64f3d9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.volume.panel.dagger
 
+import com.android.systemui.volume.dagger.UiEventLoggerStartableModule
 import com.android.systemui.volume.panel.component.anc.AncModule
 import com.android.systemui.volume.panel.component.bottombar.BottomBarModule
 import com.android.systemui.volume.panel.component.captioning.CaptioningModule
@@ -25,6 +26,7 @@
 import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import com.android.systemui.volume.panel.domain.DomainModule
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
 import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor
 import com.android.systemui.volume.panel.ui.UiModule
 import com.android.systemui.volume.panel.ui.composable.ComponentsFactory
@@ -47,6 +49,7 @@
             DefaultMultibindsModule::class,
             DomainModule::class,
             UiModule::class,
+            UiEventLoggerStartableModule::class,
             // Components modules
             BottomBarModule::class,
             AncModule::class,
@@ -66,6 +69,8 @@
 
     fun componentsLayoutManager(): ComponentsLayoutManager
 
+    fun volumePanelStartables(): Set<VolumePanelStartable>
+
     @Subcomponent.Factory
     interface Factory : VolumePanelComponentFactory {
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/domain/VolumePanelStartable.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/VolumePanelStartable.kt
new file mode 100644
index 0000000..9c39f5e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/VolumePanelStartable.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.domain
+
+/** Code that needs to be run when Volume Panel is started.. */
+interface VolumePanelStartable {
+    fun start()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
new file mode 100644
index 0000000..8793538
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.shared.model
+
+/** Models a loadable result */
+sealed interface Result<T> {
+
+    /** The data is still loading */
+    class Loading<T> : Result<T>
+
+    /** The data is loaded successfully */
+    data class Data<T>(val data: T) : Result<T>
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/VolumePanelUiEvent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/VolumePanelUiEvent.kt
new file mode 100644
index 0000000..8b8714f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/VolumePanelUiEvent.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.ui
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+/** UI events for Volume Panel. */
+enum class VolumePanelUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum {
+    @UiEvent(doc = "The volume panel is shown") VOLUME_PANEL_SHOWN(1634),
+    @UiEvent(doc = "The volume panel is gone") VOLUME_PANEL_GONE(1635),
+    @UiEvent(doc = "Media output is clicked") VOLUME_PANEL_MEDIA_OUTPUT_CLICKED(1636),
+    @UiEvent(doc = "Audio mode changed to normal") VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_NORMAL(1680),
+    @UiEvent(doc = "Audio mode changed to calling") VOLUME_PANEL_AUDIO_MODE_CHANGE_TO_CALLING(1681),
+    @UiEvent(doc = "Sound settings is clicked") VOLUME_PANEL_SOUND_SETTINGS_CLICKED(1638),
+    @UiEvent(doc = "The music volume slider is touched") VOLUME_PANEL_MUSIC_SLIDER_TOUCHED(1639),
+    @UiEvent(doc = "The voice call volume slider is touched")
+    VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED(1640),
+    @UiEvent(doc = "The ring volume slider is touched") VOLUME_PANEL_RING_SLIDER_TOUCHED(1641),
+    @UiEvent(doc = "The notification volume slider is touched")
+    VOLUME_PANEL_NOTIFICATION_SLIDER_TOUCHED(1642),
+    @UiEvent(doc = "The alarm volume slider is touched") VOLUME_PANEL_ALARM_SLIDER_TOUCHED(1643),
+    @UiEvent(doc = "Live caption toggle is shown") VOLUME_PANEL_LIVE_CAPTION_TOGGLE_SHOWN(1644),
+    @UiEvent(doc = "Live caption toggle is gone") VOLUME_PANEL_LIVE_CAPTION_TOGGLE_GONE(1645),
+    @UiEvent(doc = "Live caption toggle is clicked") VOLUME_PANEL_LIVE_CAPTION_TOGGLE_CLICKED(1646),
+    @UiEvent(doc = "Spatial audio button is shown") VOLUME_PANEL_SPATIAL_AUDIO_BUTTON_SHOWN(1647),
+    @UiEvent(doc = "Spatial audio button is gone") VOLUME_PANEL_SPATIAL_AUDIO_BUTTON_GONE(1648),
+    @UiEvent(doc = "Spatial audio popup is shown") VOLUME_PANEL_SPATIAL_AUDIO_POP_UP_SHOWN(1649),
+    @UiEvent(doc = "Spatial audio toggle is clicked")
+    VOLUME_PANEL_SPATIAL_AUDIO_TOGGLE_CLICKED(1650),
+    @UiEvent(doc = "ANC button is shown") VOLUME_PANEL_ANC_BUTTON_SHOWN(1651),
+    @UiEvent(doc = "ANC button is gone") VOLUME_PANEL_ANC_BUTTON_GONE(1652),
+    @UiEvent(doc = "ANC popup is shown") VOLUME_PANEL_ANC_POPUP_SHOWN(1653),
+    @UiEvent(doc = "ANC toggle is clicked") VOLUME_PANEL_ANC_TOGGLE_CLICKED(1654);
+
+    override fun getId() = metricId
+
+    companion object {
+        const val LIVE_CAPTION_TOGGLE_DISABLED = 0
+        const val LIVE_CAPTION_TOGGLE_ENABLED = 1
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
index c728fef..ccb91ac 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/activity/VolumePanelActivity.kt
@@ -21,8 +21,10 @@
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
 import androidx.activity.viewModels
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag
+import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import com.android.systemui.volume.panel.ui.composable.VolumePanelRoot
 import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
 import javax.inject.Inject
@@ -34,6 +36,7 @@
     private val volumePanelViewModelFactory: Provider<VolumePanelViewModel.Factory>,
     private val volumePanelFlag: VolumePanelFlag,
     private val configurationController: ConfigurationController,
+    private val uiEventLogger: UiEventLogger,
 ) : ComponentActivity() {
 
     private val viewModel: VolumePanelViewModel by
@@ -43,8 +46,16 @@
         enableEdgeToEdge()
         super.onCreate(savedInstanceState)
         volumePanelFlag.assertNewVolumePanel()
-
-        setContent { VolumePanelRoot(viewModel = viewModel, onDismiss = ::finish) }
+        uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_SHOWN)
+        setContent {
+            VolumePanelRoot(
+                viewModel = viewModel,
+                onDismiss = {
+                    uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_GONE)
+                    finish()
+                }
+            )
+        }
     }
 
     override fun onContentChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
index 5ae827f..1de4fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.statusbar.policy.onConfigChanged
 import com.android.systemui.volume.panel.dagger.VolumePanelComponent
 import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
 import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor
 import com.android.systemui.volume.panel.ui.composable.ComponentsFactory
 import com.android.systemui.volume.panel.ui.layout.ComponentsLayout
@@ -109,6 +110,10 @@
                 replay = 1,
             )
 
+    init {
+        volumePanelComponent.volumePanelStartables().onEach(VolumePanelStartable::start)
+    }
+
     fun dismissPanel() {
         mutablePanelVisibility.update { false }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 9bfc4ce..1568e8c0 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -20,8 +20,12 @@
 import static android.app.WallpaperManager.FLAG_SYSTEM;
 import static android.app.WallpaperManager.SetWallpaperFlags;
 
+import static com.android.window.flags.Flags.offloadColorExtraction;
+
+import android.annotation.Nullable;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.RecordingCanvas;
@@ -134,6 +138,12 @@
                     mLongExecutor,
                     mLock,
                     new WallpaperLocalColorExtractor.WallpaperLocalColorExtractorCallback() {
+
+                        @Override
+                        public void onColorsProcessed() {
+                            CanvasEngine.this.notifyColorsChanged();
+                        }
+
                         @Override
                         public void onColorsProcessed(List<RectF> regions,
                                 List<WallpaperColors> colors) {
@@ -183,8 +193,11 @@
 
         @Override
         public void onDestroy() {
-            getDisplayContext().getSystemService(DisplayManager.class)
-                    .unregisterDisplayListener(this);
+            Context context = getDisplayContext();
+            if (context != null) {
+                DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+                if (displayManager != null) displayManager.unregisterDisplayListener(this);
+            }
             mWallpaperLocalColorExtractor.cleanUp();
         }
 
@@ -429,6 +442,12 @@
         }
 
         @Override
+        public @Nullable WallpaperColors onComputeColors() {
+            if (!offloadColorExtraction()) return null;
+            return mWallpaperLocalColorExtractor.onComputeColors();
+        }
+
+        @Override
         public boolean supportsLocalColorExtraction() {
             return true;
         }
@@ -465,6 +484,12 @@
         }
 
         @Override
+        public void onDimAmountChanged(float dimAmount) {
+            if (!offloadColorExtraction()) return;
+            mWallpaperLocalColorExtractor.onDimAmountChanged(dimAmount);
+        }
+
+        @Override
         public void onDisplayAdded(int displayId) {
 
         }
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
index e2ec8dc..d37dfb4 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
@@ -17,6 +17,8 @@
 
 package com.android.systemui.wallpapers;
 
+import static com.android.window.flags.Flags.offloadColorExtraction;
+
 import android.app.WallpaperColors;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
@@ -66,6 +68,12 @@
     private final List<RectF> mPendingRegions = new ArrayList<>();
     private final Set<RectF> mProcessedRegions = new ArraySet<>();
 
+    private float mWallpaperDimAmount = 0f;
+    private WallpaperColors mWallpaperColors;
+
+    // By default we assume that colors were loaded from disk and don't need to be recomputed
+    private boolean mRecomputeColors = false;
+
     @LongRunning
     private final Executor mLongExecutor;
 
@@ -75,6 +83,12 @@
      * Interface to handle the callbacks after the different steps of the color extraction
      */
     public interface WallpaperLocalColorExtractorCallback {
+
+        /**
+         * Callback after the wallpaper colors have been computed
+         */
+        void onColorsProcessed();
+
         /**
          * Callback after the colors of new regions have been extracted
          * @param regions the list of new regions that have been processed
@@ -129,7 +143,7 @@
             if (displayWidth == mDisplayWidth && displayHeight == mDisplayHeight) return;
             mDisplayWidth = displayWidth;
             mDisplayHeight = displayHeight;
-            processColorsInternal();
+            processLocalColorsInternal();
         }
     }
 
@@ -166,7 +180,8 @@
             mBitmapHeight = bitmap.getHeight();
             mMiniBitmap = createMiniBitmap(bitmap);
             mWallpaperLocalColorExtractorCallback.onMiniBitmapUpdated();
-            recomputeColors();
+            if (offloadColorExtraction() && mRecomputeColors) recomputeColorsInternal();
+            recomputeLocalColors();
         }
     }
 
@@ -184,16 +199,66 @@
             if (mPages == pages) return;
             mPages = pages;
             if (mMiniBitmap != null && !mMiniBitmap.isRecycled()) {
-                recomputeColors();
+                recomputeLocalColors();
             }
         }
     }
 
-    // helper to recompute colors, to be called in synchronized methods
-    private void recomputeColors() {
+    /**
+     * Should be called when the dim amount of the wallpaper changes, to recompute the colors
+     */
+    public void onDimAmountChanged(float dimAmount) {
+        mLongExecutor.execute(() -> onDimAmountChangedSynchronized(dimAmount));
+    }
+
+    private void onDimAmountChangedSynchronized(float dimAmount) {
+        synchronized (mLock) {
+            if (mWallpaperDimAmount == dimAmount) return;
+            mWallpaperDimAmount = dimAmount;
+            mRecomputeColors = true;
+            recomputeColorsInternal();
+        }
+    }
+
+    /**
+     * To be called by {@link ImageWallpaper.CanvasEngine#onComputeColors}. This will either
+     * return the current wallpaper colors, or if the bitmap is not yet loaded, return null and call
+     * {@link WallpaperLocalColorExtractorCallback#onColorsProcessed()} when the colors are ready.
+     */
+    public WallpaperColors onComputeColors() {
+        mLongExecutor.execute(this::onComputeColorsSynchronized);
+        return mWallpaperColors;
+    }
+
+    private void onComputeColorsSynchronized() {
+        synchronized (mLock) {
+            if (mRecomputeColors) return;
+            mRecomputeColors = true;
+            recomputeColorsInternal();
+        }
+    }
+
+    /**
+     * helper to recompute main colors, to be called in synchronized methods
+     */
+    private void recomputeColorsInternal() {
+        if (mMiniBitmap == null) return;
+        mWallpaperColors = getWallpaperColors(mMiniBitmap, mWallpaperDimAmount);
+        mWallpaperLocalColorExtractorCallback.onColorsProcessed();
+    }
+
+    @VisibleForTesting
+    WallpaperColors getWallpaperColors(@NonNull Bitmap bitmap, float dimAmount) {
+        return WallpaperColors.fromBitmap(bitmap, dimAmount);
+    }
+
+    /**
+     * helper to recompute local colors, to be called in synchronized methods
+     */
+    private void recomputeLocalColors() {
         mPendingRegions.addAll(mProcessedRegions);
         mProcessedRegions.clear();
-        processColorsInternal();
+        processLocalColorsInternal();
     }
 
     /**
@@ -216,7 +281,7 @@
             if (!wasActive && isActive()) {
                 mWallpaperLocalColorExtractorCallback.onActivated();
             }
-            processColorsInternal();
+            processLocalColorsInternal();
         }
     }
 
@@ -353,7 +418,7 @@
      * then notify the callback with the resulting colors for these regions
      * This method should only be called synchronously
      */
-    private void processColorsInternal() {
+    private void processLocalColorsInternal() {
         /*
          * if the miniBitmap is not yet loaded, that means the onBitmapChanged has not yet been
          * called, and thus the wallpaper is not yet loaded. In that case, exit, the function
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index e48b639..263ddc1 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -43,6 +43,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.CoreStartable;
+import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.WMComponent;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -55,6 +56,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.wm.shell.desktopmode.DesktopMode;
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
 import com.android.wm.shell.onehanded.OneHanded;
@@ -124,6 +126,8 @@
     private final UserTracker mUserTracker;
     private final DisplayTracker mDisplayTracker;
     private final NoteTaskInitializer mNoteTaskInitializer;
+    private final CommunalTransitionViewModel mCommunalTransitionViewModel;
+    private final JavaAdapter mJavaAdapter;
     private final Executor mSysUiMainExecutor;
 
     // Listeners and callbacks. Note that we prefer member variable over anonymous class here to
@@ -187,6 +191,8 @@
             UserTracker userTracker,
             DisplayTracker displayTracker,
             NoteTaskInitializer noteTaskInitializer,
+            CommunalTransitionViewModel communalTransitionViewModel,
+            JavaAdapter javaAdapter,
             @Main Executor sysUiMainExecutor) {
         mContext = context;
         mShell = shell;
@@ -205,6 +211,8 @@
         mUserTracker = userTracker;
         mDisplayTracker = displayTracker;
         mNoteTaskInitializer = noteTaskInitializer;
+        mCommunalTransitionViewModel = communalTransitionViewModel;
+        mJavaAdapter = javaAdapter;
         mSysUiMainExecutor = sysUiMainExecutor;
     }
 
@@ -381,6 +389,8 @@
     void initRecentTasks(RecentTasks recentTasks) {
         recentTasks.addAnimationStateListener(mSysUiMainExecutor,
                 mCommandQueue::onRecentsAnimationStateChanged);
+        mJavaAdapter.alwaysCollectFlow(mCommunalTransitionViewModel.getRecentsBackgroundColor(),
+                recentTasks::setTransitionBackgroundColor);
     }
 
     @Override
diff --git a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
index ec6c421..a95735e 100644
--- a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
+++ b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
@@ -68,9 +68,9 @@
             SmallTest.class,
             MediumTest.class,
             LargeTest.class,
-            android.test.suitebuilder.annotation.SmallTest.class,
-            android.test.suitebuilder.annotation.MediumTest.class,
-            android.test.suitebuilder.annotation.LargeTest.class,
+            androidx.test.filters.SmallTest.class,
+            androidx.test.filters.MediumTest.class,
+            androidx.test.filters.LargeTest.class,
     };
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java
index ffedb30..52af8fb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java
@@ -18,11 +18,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
index f8fdd8d..6512e70 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
@@ -16,7 +16,7 @@
 
 package com.android.keyguard
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import com.android.systemui.SysuiTestCase
 import com.google.common.truth.Truth.assertThat
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index 08c1de1..11d31c6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -50,19 +50,23 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.text.TextUtils;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.keyguard.logging.CarrierTextManagerLogger;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
 import com.android.systemui.log.LogBufferHelperKt;
 import com.android.systemui.res.R;
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.FakeDeviceBasedSatelliteViewModel;
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository;
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel;
 import com.android.systemui.telephony.TelephonyListenerManager;
 import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
@@ -77,6 +81,8 @@
 import java.util.HashMap;
 import java.util.List;
 
+import kotlinx.coroutines.test.TestScope;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class CarrierTextManagerTest extends SysuiTestCase {
@@ -98,6 +104,8 @@
             TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "",
             DATA_ROAMING_ENABLE, null, null, null, null, false, null, "");
     private FakeWifiRepository mWifiRepository = new FakeWifiRepository();
+    private final FakeDeviceBasedSatelliteViewModel mSatelliteViewModel =
+            new FakeDeviceBasedSatelliteViewModel();
     @Mock
     private WakefulnessLifecycle mWakefulnessLifecycle;
     @Mock
@@ -123,6 +131,10 @@
             new CarrierTextManagerLogger(
                     LogBufferHelperKt.logcatLogBuffer("CarrierTextManagerLog"));
 
+    private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
+    private final TestScope mTestScope = mKosmos.getTestScope();
+    private final JavaAdapter mJavaAdapter = new JavaAdapter(mTestScope.getBackgroundScope());
+
     private Void checkMainThread(InvocationOnMock inv) {
         assertThat(mMainExecutor.isExecuting()).isTrue();
         assertThat(mBgExecutor.isExecuting()).isFalse();
@@ -155,9 +167,18 @@
         when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
 
         mCarrierTextManager = new CarrierTextManager.Builder(
-                mContext, mContext.getResources(), mWifiRepository,
-                mTelephonyManager, mTelephonyListenerManager, mWakefulnessLifecycle, mMainExecutor,
-                mBgExecutor, mKeyguardUpdateMonitor, mLogger)
+                mContext,
+                mContext.getResources(),
+                mWifiRepository,
+                mSatelliteViewModel,
+                mJavaAdapter,
+                mTelephonyManager,
+                mTelephonyListenerManager,
+                mWakefulnessLifecycle,
+                mMainExecutor,
+                mBgExecutor,
+                mKeyguardUpdateMonitor,
+                mLogger)
                 .setShowAirplaneMode(true)
                 .setShowMissingSim(true)
                 .build();
@@ -210,6 +231,8 @@
                 getContextSpyForStickyBroadcast(stickyIntent),
                 mContext.getResources(),
                 mWifiRepository,
+                mSatelliteViewModel,
+                mJavaAdapter,
                 mTelephonyManager,
                 mTelephonyListenerManager,
                 mWakefulnessLifecycle,
@@ -450,6 +473,107 @@
     }
 
     @Test
+    public void carrierText_satelliteTextNull_notUsed() {
+        reset(mCarrierTextCallback);
+        List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(TEST_SUBSCRIPTION);
+        when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+                TelephonyManager.SIM_STATE_READY);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+        mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+        // WHEN the satellite text is null
+        mSatelliteViewModel.getCarrierText().setValue(null);
+        mTestScope.getTestScheduler().runCurrent();
+
+        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+                ArgumentCaptor.forClass(
+                        CarrierTextManager.CarrierTextCallbackInfo.class);
+        FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+
+        // THEN the default subscription carrier text is used
+        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+        assertThat(captor.getValue().carrierText).isEqualTo(TEST_CARRIER);
+    }
+
+    @Test
+    public void carrierText_satelliteTextUpdates_autoTriggersCallback() {
+        reset(mCarrierTextCallback);
+        List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(TEST_SUBSCRIPTION);
+        when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+                TelephonyManager.SIM_STATE_READY);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+        mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+        // WHEN the satellite text is set
+        mSatelliteViewModel.getCarrierText().setValue("Test satellite text");
+        mTestScope.getTestScheduler().runCurrent();
+
+        // THEN we should automatically re-trigger #updateCarrierText and get callback info
+        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+                ArgumentCaptor.forClass(
+                        CarrierTextManager.CarrierTextCallbackInfo.class);
+        FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+        // AND use the satellite text as the carrier text
+        assertThat(captor.getValue().carrierText).isEqualTo("Test satellite text");
+
+        // WHEN the satellite text is reset to null
+        reset(mCarrierTextCallback);
+        mSatelliteViewModel.getCarrierText().setValue(null);
+        mTestScope.getTestScheduler().runCurrent();
+
+        // THEN we should automatically re-trigger #updateCarrierText and get callback info
+        // that doesn't include the satellite info
+        FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+        assertThat(captor.getValue().carrierText).isEqualTo(TEST_CARRIER);
+    }
+
+    @Test
+    public void carrierText_updatedWhileNotListening_getsNewValueWhenListening() {
+        reset(mCarrierTextCallback);
+        List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(TEST_SUBSCRIPTION);
+        when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+                TelephonyManager.SIM_STATE_READY);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+        mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+        mSatelliteViewModel.getCarrierText().setValue("Old satellite text");
+        mTestScope.getTestScheduler().runCurrent();
+
+        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+                ArgumentCaptor.forClass(
+                        CarrierTextManager.CarrierTextCallbackInfo.class);
+        FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+        assertThat(captor.getValue().carrierText).isEqualTo("Old satellite text");
+
+        // WHEN we stop listening
+        reset(mCarrierTextCallback);
+        mCarrierTextManager.setListening(null);
+
+        // AND the satellite text updates
+        mSatelliteViewModel.getCarrierText().setValue("New satellite text");
+
+        // THEN we don't get new callback info because we aren't listening
+        verify(mCarrierTextCallback, never()).updateCarrierInfo(any());
+
+        // WHEN we start listening again
+        reset(mCarrierTextCallback);
+        mCarrierTextManager.setListening(mCarrierTextCallback);
+
+        // THEN we should automatically re-trigger #updateCarrierText and get callback info
+        // that includes the new satellite text
+        mTestScope.getTestScheduler().runCurrent();
+        FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+        assertThat(captor.getValue().carrierText).isEqualTo("New satellite text");
+    }
+
+    @Test
     public void testCreateInfo_noSubscriptions() {
         reset(mCarrierTextCallback);
         when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(
@@ -470,6 +594,28 @@
     }
 
     @Test
+    public void testCarrierText_oneValidSubscription() {
+        reset(mCarrierTextCallback);
+        List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(TEST_SUBSCRIPTION);
+        when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+                TelephonyManager.SIM_STATE_READY);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+
+        mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+        ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+                ArgumentCaptor.forClass(
+                        CarrierTextManager.CarrierTextCallbackInfo.class);
+
+        mCarrierTextManager.updateCarrierText();
+        FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+        assertThat(captor.getValue().carrierText).isEqualTo(TEST_CARRIER);
+    }
+
+    @Test
     public void testCarrierText_twoValidSubscriptions() {
         reset(mCarrierTextCallback);
         List<SubscriptionInfo> list = new ArrayList<>();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 6a35340..e72027a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -142,7 +142,6 @@
                 context.resources,
                 context,
                 mainExecutor,
-                IMMEDIATE,
                 bgExecutor,
                 clockBuffers,
                 withDeps.featureFlags,
@@ -320,9 +319,19 @@
     fun listenForDozeAmountTransition_updatesClockDozeAmount() =
         runBlocking(IMMEDIATE) {
             val transitionStep = MutableStateFlow(TransitionStep())
-            whenever(keyguardTransitionInteractor.lockscreenToAodTransition)
+            whenever(
+                    keyguardTransitionInteractor.transition(
+                        KeyguardState.LOCKSCREEN,
+                        KeyguardState.AOD
+                    )
+                )
                 .thenReturn(transitionStep)
-            whenever(keyguardTransitionInteractor.aodToLockscreenTransition)
+            whenever(
+                    keyguardTransitionInteractor.transition(
+                        KeyguardState.AOD,
+                        KeyguardState.LOCKSCREEN
+                    )
+                )
                 .thenReturn(transitionStep)
 
             val job = underTest.listenForDozeAmountTransition(this)
@@ -330,7 +339,8 @@
                 TransitionStep(
                     from = KeyguardState.LOCKSCREEN,
                     to = KeyguardState.AOD,
-                    value = 0.4f
+                    value = 0.4f,
+                    transitionState = TransitionState.RUNNING,
                 )
             yield()
 
@@ -361,6 +371,27 @@
         }
 
     @Test
+    fun listenForTransitionToLSFromOccluded_updatesClockDozeAmountToOne() =
+        runBlocking(IMMEDIATE) {
+            val transitionStep = MutableStateFlow(TransitionStep())
+            whenever(keyguardTransitionInteractor.transitionStepsToState(KeyguardState.LOCKSCREEN))
+                    .thenReturn(transitionStep)
+
+            val job = underTest.listenForAnyStateToLockscreenTransition(this)
+            transitionStep.value =
+                    TransitionStep(
+                            from = KeyguardState.OCCLUDED,
+                            to = KeyguardState.LOCKSCREEN,
+                            transitionState = TransitionState.STARTED,
+                    )
+            yield()
+
+            verify(animations, times(2)).doze(0f)
+
+            job.cancel()
+        }
+
+    @Test
     fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() =
         runBlocking(IMMEDIATE) {
             val transitionStep = MutableStateFlow(TransitionStep())
@@ -378,6 +409,27 @@
 
             verify(animations, never()).doze(1f)
 
+                job.cancel()
+            }
+
+    @Test
+    fun listenForAnyStateToLockscreenTransition_neverUpdatesClockDozeAmount() =
+        runBlocking(IMMEDIATE) {
+            val transitionStep = MutableStateFlow(TransitionStep())
+            whenever(keyguardTransitionInteractor.transitionStepsToState(KeyguardState.LOCKSCREEN))
+                    .thenReturn(transitionStep)
+
+            val job = underTest.listenForAnyStateToLockscreenTransition(this)
+            transitionStep.value =
+                    TransitionStep(
+                            from = KeyguardState.AOD,
+                            to = KeyguardState.LOCKSCREEN,
+                            transitionState = TransitionState.STARTED,
+                    )
+            yield()
+
+            verify(animations, never()).doze(0f)
+
             job.cancel()
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
index a249961..319b615 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
@@ -205,9 +205,9 @@
         when(mClockRegistry.createCurrentClock()).thenReturn(mClockController);
         when(mClockEventController.getClock()).thenReturn(mClockController);
         when(mSmallClockController.getConfig())
-                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false));
+                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false, false));
         when(mLargeClockController.getConfig())
-                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false));
+                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false, false));
 
         mSliceView = new View(getContext());
         when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 9d81b96..99b5a4b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -272,9 +272,9 @@
         assertEquals(View.VISIBLE, mFakeDateView.getVisibility());
 
         when(mSmallClockController.getConfig())
-                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false));
+                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false, true));
         when(mLargeClockController.getConfig())
-                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false));
+                .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false, true));
         verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture());
         listenerArgumentCaptor.getValue().onCurrentClockChanged();
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index b4a9d40..e2063d2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -30,7 +30,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.AttributeSet;
@@ -40,6 +39,8 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.clocks.ClockController;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java
index 93e7602..6228ff8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java
@@ -27,12 +27,13 @@
 import static org.mockito.Mockito.when;
 
 import android.hardware.biometrics.BiometricSourceType;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.text.Editable;
 import android.text.TextWatcher;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
index 9b5364e..7151c42 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
@@ -115,6 +115,7 @@
     @Test
     fun onViewAttached() {
         underTest.onViewAttached()
+        verify(keyguardMessageAreaController).setIsVisible(true)
         verify(keyguardMessageAreaController)
             .setMessage(context.resources.getString(R.string.keyguard_enter_your_pin), false)
         verify(keyguardUpdateMonitor)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
index e71490c..acae913 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
@@ -103,7 +103,9 @@
 
     @Test
     fun onViewAttached() {
+        Mockito.reset(keyguardMessageAreaController)
         underTest.onViewAttached()
+        Mockito.verify(keyguardMessageAreaController).setIsVisible(true)
         Mockito.verify(keyguardUpdateMonitor)
             .registerCallback(any(KeyguardUpdateMonitorCallback::class.java))
         Mockito.verify(keyguardMessageAreaController)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java
index edb910a..c566826 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java
@@ -23,12 +23,13 @@
 
 import android.content.pm.PackageManager;
 import android.os.Handler;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index 6654a6c..a0e8065 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -17,7 +17,6 @@
 
 import android.graphics.Color;
 import android.net.Uri;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.LayoutInflater;
@@ -27,10 +26,11 @@
 import androidx.slice.SliceSpecs;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.widget.RowContent;
+import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.res.R;
 
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
index e6b6964..ed61ee12 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
@@ -1,8 +1,8 @@
 package com.android.keyguard
 
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import org.junit.Assert.assertEquals
 import org.junit.Before
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 11fe862..0696a4b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -31,11 +31,12 @@
 
 import android.animation.AnimatorTestRule;
 import android.platform.test.annotations.DisableFlags;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.app.animation.Interpolators;
 import com.android.systemui.Flags;
 import com.android.systemui.animation.ViewHierarchyAnimator;
@@ -98,7 +99,7 @@
     public void updatePosition_primaryClockAnimation() {
         ClockController mockClock = mock(ClockController.class);
         when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
-        when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", false, true));
+        when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", false, true, false));
 
         mController.updatePosition(10, 15, 20f, true);
 
@@ -113,7 +114,7 @@
     public void updatePosition_alternateClockAnimation() {
         ClockController mockClock = mock(ClockController.class);
         when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
-        when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", true, true));
+        when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", true, true, false));
 
         mController.updatePosition(10, 15, 20f, true);
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt
index 17f77aa..3b57d8f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.keyguard
 
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
 import com.android.systemui.power.shared.model.ScreenPowerState
 import kotlinx.coroutines.cancelChildren
 import kotlinx.coroutines.test.runCurrent
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
index 86439e5..afd2034 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -1,6 +1,6 @@
 package com.android.keyguard
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.LayoutInflater
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index fde45d3..d354fa2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -106,11 +106,12 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.text.TextUtils;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.foldables.FoldGracePeriodProvider;
 import com.android.internal.jank.InteractionJankMonitor;
@@ -2015,6 +2016,16 @@
     }
 
     @Test
+    public void unfoldFromPostureChange_sendActionToFaceAuthInteractor() {
+        // WHEN device posture changes to unfold
+        deviceInPostureStateOpened();
+        mTestableLooper.processAllMessages();
+
+        // THEN request face auth
+        verify(mFaceAuthInteractor).onDeviceUnfolded();
+    }
+
+    @Test
     public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
         ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
                 ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java
index f924ab4..b09357f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerBaseTest.java
@@ -36,6 +36,7 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.ImageView;
 
 import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
@@ -51,6 +52,7 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -78,6 +80,7 @@
     protected final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
     protected @Mock DeviceEntryInteractor mDeviceEntryInteractor;
     protected @Mock LockIconView mLockIconView;
+    protected @Mock ImageView mLockIcon;
     protected @Mock AnimatedStateListDrawable mIconDrawable;
     protected @Mock Context mContext;
     protected @Mock Resources mResources;
@@ -146,8 +149,10 @@
         when(mStatusBarStateController.isDozing()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
 
-        mSetFlagsRule.disableFlags(Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR);
-        mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT);
+        if (!SceneContainerFlag.isEnabled()) {
+            mSetFlagsRule.disableFlags(Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR);
+            mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT);
+        }
 
         mFeatureFlags = new FakeFeatureFlags();
         mFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false);
@@ -172,8 +177,7 @@
                 mFeatureFlags,
                 mPrimaryBouncerInteractor,
                 mContext,
-                () -> mDeviceEntryInteractor,
-                mKosmos.getFakeSceneContainerFlags()
+                () -> mDeviceEntryInteractor
         );
     }
 
@@ -225,6 +229,7 @@
     protected void setupLockIconViewMocks() {
         when(mLockIconView.getResources()).thenReturn(mResources);
         when(mLockIconView.getContext()).thenReturn(mContext);
+        when(mLockIconView.getLockIcon()).thenReturn(mLockIcon);
     }
 
     protected void resetLockIconView() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java
index 8689842..255c7d9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.biometrics.UdfpsController;
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
 import com.android.systemui.doze.util.BurnInHelperKt;
+import com.android.systemui.flags.EnableSceneContainer;
 import com.android.systemui.statusbar.StatusBarState;
 
 import org.junit.Test;
@@ -373,7 +374,6 @@
     @Test
     public void longPress_showBouncer_sceneContainerNotEnabled() {
         init(/* useMigrationFlag= */ false);
-        mKosmos.getFakeSceneContainerFlags().setEnabled(false);
         when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(false);
 
         // WHEN longPress
@@ -385,9 +385,9 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void longPress_showBouncer() {
         init(/* useMigrationFlag= */ false);
-        mKosmos.getFakeSceneContainerFlags().setEnabled(true);
         when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(false);
 
         // WHEN longPress
@@ -399,9 +399,9 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void longPress_falsingTriggered_doesNotShowBouncer() {
         init(/* useMigrationFlag= */ false);
-        mKosmos.getFakeSceneContainerFlags().setEnabled(true);
         when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(true);
 
         // WHEN longPress
diff --git a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
index 532c59a..d6a5b4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
@@ -28,8 +28,8 @@
 
 import android.content.res.Resources;
 import android.graphics.Canvas;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.R;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index c20367e..d267ad4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -1274,6 +1274,28 @@
     }
 
     @Test
+    public void delayedFaceSensorLocationChangesAddsFaceScanningOverlay() {
+        setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
+                0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+        mScreenDecorations.start();
+        verifyFaceScanningViewExists(false); // face scanning view not added yet
+
+        // WHEN the sensor location is updated
+        mFaceScanningProviders = new ArrayList<>();
+        mFaceScanningProviders.add(mFaceScanningDecorProvider);
+        when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
+        when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(true);
+        final Point location = new Point();
+        mFakeFacePropertyRepository.setSensorLocation(location);
+        mScreenDecorations.onFaceSensorLocationChanged(location);
+        mExecutor.runAllReady();
+
+        // THEN the face scanning view is added
+        verifyFaceScanningViewExists(true);
+    }
+
+    @Test
     public void testPrivacyDotShowingListenerWorkWellWithNullParameter() {
         mPrivacyDotShowingListener.onPrivacyDotShown(null);
         mPrivacyDotShowingListener.onPrivacyDotHidden(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
index 7c121e1..d7bd59e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
@@ -31,36 +31,57 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
-import android.testing.AndroidTestingRunner;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.settingslib.SliceBroadcastRelay;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-@RunWith(AndroidTestingRunner.class)
+import java.util.List;
+
+@RunWith(Parameterized.class)
 @SmallTest
 public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
 
+    @Parameterized.Parameters(name = "{0}")
+    public static List<FlagsParameterization> getFlags() {
+        return FlagsParameterization.allCombinationsOf(
+                Flags.FLAG_SLICE_BROADCAST_RELAY_IN_BACKGROUND);
+    }
+
     private static final String TEST_ACTION = "com.android.systemui.action.TEST_ACTION";
+    private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
+
     private SliceBroadcastRelayHandler mRelayHandler;
     private Context mSpyContext;
     @Mock
     private BroadcastDispatcher mBroadcastDispatcher;
 
+
+    public SliceBroadcastRelayHandlerTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mSpyContext = spy(mContext);
 
-        mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext, mBroadcastDispatcher);
+        mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext, mBroadcastDispatcher,
+                mBackgroundExecutor);
     }
 
     @Test
@@ -80,6 +101,7 @@
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, testUri);
 
         mRelayHandler.handleIntent(intent);
+        mBackgroundExecutor.runAllReady();
         verify(mSpyContext).registerReceiver(any(), eq(value), anyInt());
     }
 
@@ -99,12 +121,14 @@
         intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);
 
         mRelayHandler.handleIntent(intent);
+        mBackgroundExecutor.runAllReady();
         ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
         verify(mSpyContext).registerReceiver(relay.capture(), eq(value), anyInt());
 
         intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
         mRelayHandler.handleIntent(intent);
+        mBackgroundExecutor.runAllReady();
         verify(mSpyContext).unregisterReceiver(eq(relay.getValue()));
     }
 
@@ -119,6 +143,7 @@
         Intent intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
         intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
         mRelayHandler.handleIntent(intent);
+        mBackgroundExecutor.runAllReady();
         // No crash
     }
 
@@ -138,6 +163,7 @@
         intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);
 
         mRelayHandler.handleIntent(intent);
+        mBackgroundExecutor.runAllReady();
         ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
         verify(mSpyContext).registerReceiver(relay.capture(), eq(value), anyInt());
         relay.getValue().onReceive(mSpyContext, new Intent(TEST_ACTION));
@@ -146,8 +172,10 @@
     }
 
     @Test
-    public void testRegisteredWithDispatcher() {
+    @DisableFlags(Flags.FLAG_SLICE_BROADCAST_RELAY_IN_BACKGROUND)
+    public void testRegisteredWithDispatcher_onMainThread() {
         mRelayHandler.start();
+        mBackgroundExecutor.runAllReady();
 
         verify(mBroadcastDispatcher)
                 .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
@@ -155,6 +183,19 @@
                 .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_SLICE_BROADCAST_RELAY_IN_BACKGROUND)
+    public void testRegisteredWithDispatcher_onBackgroundThread() {
+        mRelayHandler.start();
+        mBackgroundExecutor.runAllReady();
+
+        verify(mBroadcastDispatcher)
+                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
+                        eq(mBackgroundExecutor));
+        verify(mSpyContext, never())
+                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+    }
+
     public static class Receiver extends BroadcastReceiver {
         private static BroadcastReceiver sReceiver;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SystemUIApplicationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/SystemUIApplicationTest.kt
index e157fc5..4f7610a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SystemUIApplicationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/SystemUIApplicationTest.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.flags.systemPropertiesHelper
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.process.processWrapper
-import com.android.systemui.startable.Dependencies
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import javax.inject.Provider
@@ -56,6 +55,19 @@
     @Mock private lateinit var bootCompleteCache: BootCompleteCacheImpl
     @Mock private lateinit var initController: InitController
 
+    class StartableA : TestableStartable()
+    class StartableB : TestableStartable()
+    class StartableC : TestableStartable()
+    class StartableD : TestableStartable()
+    class StartableE : TestableStartable()
+
+    val dependencyMap: Map<Class<*>, Set<Class<out CoreStartable>>> =
+        mapOf(
+            StartableC::class.java to setOf(StartableA::class.java),
+            StartableD::class.java to setOf(StartableA::class.java, StartableB::class.java),
+            StartableE::class.java to setOf(StartableD::class.java, StartableB::class.java),
+        )
+
     private val startableA = StartableA()
     private val startableB = StartableB()
     private val startableC = StartableC()
@@ -76,6 +88,7 @@
         whenever(sysuiComponent.provideBootCacheImpl()).thenReturn(bootCompleteCache)
         whenever(sysuiComponent.createDumpManager()).thenReturn(kosmos.dumpManager)
         whenever(sysuiComponent.initController).thenReturn(initController)
+        whenever(sysuiComponent.startableDependencies).thenReturn(dependencyMap)
         kosmos.processWrapper.systemUser = true
 
         app.setContextAvailableCallback(contextAvailableCallback)
@@ -168,13 +181,4 @@
             startOrder++
         }
     }
-
-    class StartableA : TestableStartable()
-    class StartableB : TestableStartable()
-
-    @Dependencies(StartableA::class) class StartableC : TestableStartable()
-
-    @Dependencies(StartableA::class, StartableB::class) class StartableD : TestableStartable()
-
-    @Dependencies(StartableD::class, StartableB::class) class StartableE : TestableStartable()
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java
index 12f334b..5bc9aa4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java
@@ -16,49 +16,84 @@
 
 package com.android.systemui.accessibility;
 
+import static android.os.Build.HW_TIMEOUT_MULTIPLIER;
+
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
 import android.window.InputTransferToken;
 
+import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
 
 @SmallTest
 @TestableLooper.RunWithLooper
 @RunWith(AndroidTestingRunner.class)
 public class FullscreenMagnificationControllerTest extends SysuiTestCase {
-
+    private static final long ANIMATION_DURATION_MS = 100L;
+    private static final long WAIT_TIMEOUT_S = 5L * HW_TIMEOUT_MULTIPLIER;
+    private static final long ANIMATION_TIMEOUT_MS =
+            5L * ANIMATION_DURATION_MS * HW_TIMEOUT_MULTIPLIER;
     private FullscreenMagnificationController mFullscreenMagnificationController;
     private SurfaceControlViewHost mSurfaceControlViewHost;
+    private ValueAnimator mShowHideBorderAnimator;
+    private SurfaceControl.Transaction mTransaction;
+    private TestableWindowManager mWindowManager;
 
     @Before
     public void setUp() {
         getInstrumentation().runOnMainSync(() -> mSurfaceControlViewHost =
-                new SurfaceControlViewHost(mContext, mContext.getDisplay(),
-                        new InputTransferToken(), "FullscreenMagnification"));
-
+                spy(new SurfaceControlViewHost(mContext, mContext.getDisplay(),
+                        new InputTransferToken(), "FullscreenMagnification")));
         Supplier<SurfaceControlViewHost> scvhSupplier = () -> mSurfaceControlViewHost;
+        final WindowManager wm = mContext.getSystemService(WindowManager.class);
+        mWindowManager = new TestableWindowManager(wm);
+        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
 
+        mTransaction = new SurfaceControl.Transaction();
+        mShowHideBorderAnimator = spy(newNullTargetObjectAnimator());
         mFullscreenMagnificationController = new FullscreenMagnificationController(
                 mContext,
+                mContext.getMainExecutor(),
                 mContext.getSystemService(AccessibilityManager.class),
                 mContext.getSystemService(WindowManager.class),
-                scvhSupplier);
+                scvhSupplier,
+                mTransaction,
+                mShowHideBorderAnimator);
     }
 
     @After
@@ -69,29 +104,143 @@
     }
 
     @Test
-    public void onFullscreenMagnificationActivationChange_activated_visibleBorder() {
-        getInstrumentation().runOnMainSync(
-                () -> mFullscreenMagnificationController
-                        .onFullscreenMagnificationActivationChanged(true)
-        );
-
-        // Wait for Rects updated.
-        waitForIdleSync();
+    public void enableFullscreenMagnification_visibleBorder() throws InterruptedException {
+        CountDownLatch transactionCommittedLatch = new CountDownLatch(1);
+        CountDownLatch animationEndLatch = new CountDownLatch(1);
+        mTransaction.addTransactionCommittedListener(
+                Runnable::run, transactionCommittedLatch::countDown);
+        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                animationEndLatch.countDown();
+            }
+        });
+        getInstrumentation().runOnMainSync(() ->
+                //Enable fullscreen magnification
+                mFullscreenMagnificationController
+                        .onFullscreenMagnificationActivationChanged(true));
+        assertTrue("Failed to wait for transaction committed",
+                transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
+        assertTrue("Failed to wait for animation to be finished",
+                animationEndLatch.await(ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        verify(mShowHideBorderAnimator).start();
         assertThat(mSurfaceControlViewHost.getView().isVisibleToUser()).isTrue();
     }
 
     @Test
-    public void onFullscreenMagnificationActivationChange_deactivated_invisibleBorder() {
-        getInstrumentation().runOnMainSync(
-                () -> {
-                    mFullscreenMagnificationController
-                            .onFullscreenMagnificationActivationChanged(true);
-                    mFullscreenMagnificationController
-                            .onFullscreenMagnificationActivationChanged(false);
+    public void disableFullscreenMagnification_reverseAnimationAndReleaseScvh()
+            throws InterruptedException {
+        CountDownLatch transactionCommittedLatch = new CountDownLatch(1);
+        CountDownLatch enableAnimationEndLatch = new CountDownLatch(1);
+        CountDownLatch disableAnimationEndLatch = new CountDownLatch(1);
+        mTransaction.addTransactionCommittedListener(
+                Runnable::run, transactionCommittedLatch::countDown);
+        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
+                if (isReverse) {
+                    disableAnimationEndLatch.countDown();
+                } else {
+                    enableAnimationEndLatch.countDown();
                 }
-        );
+            }
+        });
+        getInstrumentation().runOnMainSync(() ->
+                //Enable fullscreen magnification
+                mFullscreenMagnificationController
+                        .onFullscreenMagnificationActivationChanged(true));
+        assertTrue("Failed to wait for transaction committed",
+                transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
+        assertTrue("Failed to wait for enabling animation to be finished",
+                enableAnimationEndLatch.await(
+                        ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        verify(mShowHideBorderAnimator).start();
 
-        assertThat(mSurfaceControlViewHost.getView()).isNull();
+        getInstrumentation().runOnMainSync(() ->
+                // Disable fullscreen magnification
+                mFullscreenMagnificationController
+                        .onFullscreenMagnificationActivationChanged(false));
+
+        assertTrue("Failed to wait for disabling animation to be finished",
+                disableAnimationEndLatch.await(
+                        ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        verify(mShowHideBorderAnimator).reverse();
+        verify(mSurfaceControlViewHost).release();
     }
 
+    @Test
+    public void onFullscreenMagnificationActivationChangeTrue_deactivating_reverseAnimator()
+            throws InterruptedException {
+        // Simulate the hiding border animation is running
+        when(mShowHideBorderAnimator.isRunning()).thenReturn(true);
+        CountDownLatch transactionCommittedLatch = new CountDownLatch(1);
+        CountDownLatch animationEndLatch = new CountDownLatch(1);
+        mTransaction.addTransactionCommittedListener(
+                Runnable::run, transactionCommittedLatch::countDown);
+        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                animationEndLatch.countDown();
+            }
+        });
+
+        getInstrumentation().runOnMainSync(
+                () -> mFullscreenMagnificationController
+                            .onFullscreenMagnificationActivationChanged(true));
+
+        assertTrue("Failed to wait for transaction committed",
+                transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
+        assertTrue("Failed to wait for animation to be finished",
+                animationEndLatch.await(ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        verify(mShowHideBorderAnimator).reverse();
+    }
+
+    @Test
+    public void onScreenSizeChanged_activated_borderChangedToExpectedSize()
+            throws InterruptedException {
+        CountDownLatch transactionCommittedLatch = new CountDownLatch(1);
+        CountDownLatch animationEndLatch = new CountDownLatch(1);
+        mTransaction.addTransactionCommittedListener(
+                Runnable::run, transactionCommittedLatch::countDown);
+        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                animationEndLatch.countDown();
+            }
+        });
+        getInstrumentation().runOnMainSync(() ->
+                //Enable fullscreen magnification
+                mFullscreenMagnificationController
+                        .onFullscreenMagnificationActivationChanged(true));
+        assertTrue("Failed to wait for transaction committed",
+                transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
+        assertTrue("Failed to wait for animation to be finished",
+                animationEndLatch.await(ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        final Rect testWindowBounds = new Rect(
+                mWindowManager.getCurrentWindowMetrics().getBounds());
+        testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
+                testWindowBounds.right + 100, testWindowBounds.bottom + 100);
+        mWindowManager.setWindowBounds(testWindowBounds);
+
+        getInstrumentation().runOnMainSync(() ->
+                mFullscreenMagnificationController.onConfigurationChanged(
+                        ActivityInfo.CONFIG_SCREEN_SIZE));
+
+        int borderOffset = mContext.getResources().getDimensionPixelSize(
+                R.dimen.magnifier_border_width_fullscreen_with_offset)
+                - mContext.getResources().getDimensionPixelSize(
+                R.dimen.magnifier_border_width_fullscreen);
+        final int newWidth = testWindowBounds.width() + 2 * borderOffset;
+        final int newHeight = testWindowBounds.height() + 2 * borderOffset;
+        verify(mSurfaceControlViewHost).relayout(newWidth, newHeight);
+    }
+
+    private ValueAnimator newNullTargetObjectAnimator() {
+        final ValueAnimator animator =
+                ObjectAnimator.ofFloat(/* target= */ null, View.ALPHA, 0f, 1f);
+        Interpolator interpolator = new DecelerateInterpolator(2.5f);
+        animator.setInterpolator(interpolator);
+        animator.setDuration(ANIMATION_DURATION_MS);
+        return animator;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
index 41d5d5d..25e5470 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
@@ -101,7 +101,7 @@
         }).when(mAccessibilityManager).setMagnificationConnection(
                 any(IMagnificationConnection.class));
         mMagnification = new Magnification(getContext(),
-                getContext().getMainThreadHandler(), mCommandQueue,
+                getContext().getMainThreadHandler(), getContext().getMainExecutor(), mCommandQueue,
                 mModeSwitchesController, mSysUiState, mOverviewProxyService, mSecureSettings,
                 mDisplayTracker, getContext().getSystemService(DisplayManager.class), mA11yLogger);
         mMagnification.mWindowMagnificationControllerSupplier =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
index 3b5cbea..6dc5b72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
@@ -121,7 +121,8 @@
 
         mCommandQueue = new CommandQueue(getContext(), mDisplayTracker);
         mMagnification = new Magnification(getContext(),
-                getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController,
+                getContext().getMainThreadHandler(), getContext().getMainExecutor(),
+                mCommandQueue, mModeSwitchesController,
                 mSysUiState, mOverviewProxyService, mSecureSettings, mDisplayTracker,
                 getContext().getSystemService(DisplayManager.class), mA11yLogger);
         mMagnification.mWindowMagnificationControllerSupplier = new FakeControllerSupplier(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 69cd592..44207a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -181,7 +181,7 @@
             throws RemoteException {
         enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -220,7 +220,7 @@
                 mWaitAnimationDuration, /* targetScale= */ 1.0f,
                 DEFAULT_CENTER_X, DEFAULT_CENTER_Y, mAnimationCallback);
 
-        verify(mSpyController).enableWindowMagnificationInternal(1.0f, DEFAULT_CENTER_X,
+        verify(mSpyController).updateWindowMagnificationInternal(1.0f, DEFAULT_CENTER_X,
                 DEFAULT_CENTER_Y, 0f, 0f);
         verify(mAnimationCallback).onResult(true);
     }
@@ -244,7 +244,7 @@
             advanceTimeBy(mWaitAnimationDuration);
         });
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -299,7 +299,7 @@
             advanceTimeBy(mWaitAnimationDuration);
         });
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -341,7 +341,7 @@
             advanceTimeBy(mWaitAnimationDuration);
         });
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -377,7 +377,7 @@
             advanceTimeBy(mWaitAnimationDuration);
         });
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -439,7 +439,7 @@
         enableWindowMagnificationAndWaitAnimating(
                 mWaitAnimationDuration, Float.NaN, Float.NaN, Float.NaN, mAnimationCallback2);
 
-        verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
+        verify(mSpyController, never()).updateWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
         verify(mAnimationCallback).onResult(false);
         verify(mAnimationCallback2).onResult(true);
@@ -477,9 +477,8 @@
         });
 
         // Verify the method is called in
-        // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once and
-        // {@link Animator.AnimatorListener#onAnimationEnd} once in {@link ValueAnimator#end()}
-        verify(mSpyController, times(2)).enableWindowMagnificationInternal(
+        // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once
+        verify(mSpyController).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -526,7 +525,7 @@
         enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, Float.NaN,
                 Float.NaN, Float.NaN, mAnimationCallback2);
 
-        verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
+        verify(mSpyController, never()).updateWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
         verify(mSpyController, never()).deleteWindowMagnification();
         verify(mAnimationCallback).onResult(false);
@@ -551,7 +550,7 @@
             advanceTimeBy(mWaitAnimationDuration);
         });
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -594,10 +593,10 @@
         final float expectedY = (int) (windowBounds.exactCenterY() + expectedOffset
                 - defaultMagnificationWindowSize / 2);
 
-        // This is called 5 times when (1) first creating WindowlessMirrorWindow (2) SurfaceView is
+        // This is called 4 times when (1) first creating WindowlessMirrorWindow (2) SurfaceView is
         // created and we place the mirrored content as a child of the SurfaceView
-        // (3) the animation starts (4) the animation updates (5) the animation ends
-        verify(mTransaction, times(5))
+        // (3) the animation starts (4) the animation updates
+        verify(mTransaction, times(4))
                 .setPosition(any(SurfaceControl.class), eq(expectedX), eq(expectedY));
     }
 
@@ -720,7 +719,7 @@
 
         enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
-        verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
+        verify(mSpyController, never()).updateWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
         verify(mAnimationCallback).onResult(true);
     }
@@ -733,7 +732,7 @@
         resetMockObjects();
         deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController, atLeast(2)).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -788,9 +787,8 @@
         waitForIdleSync();
 
         // Verify the method is called in
-        // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once and
-        // {@link Animator.AnimatorListener#onAnimationEnd} once in {@link ValueAnimator#end()}
-        verify(mSpyController, times(2)).enableWindowMagnificationInternal(
+        // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once
+        verify(mSpyController).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -832,10 +830,8 @@
         deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback2);
 
         // Verify the method is called in
-        // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once and
-        // {@link Animator.AnimatorListener#onAnimationEnd} once when running the animation at
-        // the final duration time.
-        verify(mSpyController, times(2)).enableWindowMagnificationInternal(
+        // {@link ValueAnimator.AnimatorUpdateListener#onAnimationUpdate} once
+        verify(mSpyController).updateWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -1040,17 +1036,17 @@
         }
 
         @Override
-        void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
-            super.enableWindowMagnificationInternal(scale, centerX, centerY);
-            mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY);
+        void updateWindowMagnificationInternal(float scale, float centerX, float centerY) {
+            super.updateWindowMagnificationInternal(scale, centerX, centerY);
+            mSpyController.updateWindowMagnificationInternal(scale, centerX, centerY);
         }
 
         @Override
-        void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
+        void updateWindowMagnificationInternal(float scale, float centerX, float centerY,
                 float magnificationOffsetFrameRatioX, float magnificationOffsetFrameRatioY) {
-            super.enableWindowMagnificationInternal(scale, centerX, centerY,
+            super.updateWindowMagnificationInternal(scale, centerX, centerY,
                     magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY);
-            mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY,
+            mSpyController.updateWindowMagnificationInternal(scale, centerX, centerY,
                     magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 6f285fb..cb42078 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -273,7 +273,7 @@
     @Test
     public void enableWindowMagnification_showControlAndNotifyBoundsChanged() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -341,7 +341,7 @@
     @Test
     public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         // Wait for Rects updated.
@@ -358,7 +358,7 @@
         mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize));
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -373,7 +373,7 @@
     @Test
     public void deleteWindowMagnification_destroyControlAndUnregisterComponentCallback() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN,
                         Float.NaN));
 
@@ -391,7 +391,7 @@
         setSystemGestureInsets();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     bounds.bottom);
         });
         ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag);
@@ -407,7 +407,7 @@
     @Test
     public void deleteWindowMagnification_notifySourceBoundsChanged() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN,
                         Float.NaN));
 
@@ -423,7 +423,7 @@
     @Test
     public void moveMagnifier_schedulesFrame() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.moveWindowMagnifier(100f, 100f);
         });
@@ -506,7 +506,7 @@
     @Test
     public void setScale_enabled_expectedValueAndUpdateStateDescription() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(2.0f,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(2.0f,
                         Float.NaN, Float.NaN));
 
         mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f));
@@ -539,7 +539,7 @@
         final float displayWidth = windowBounds.width();
         final PointF magnifiedCenter = new PointF(center, center + 5f);
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                     magnifiedCenter.x, magnifiedCenter.y);
             // Get the center again in case the center we set is out of screen.
             magnifiedCenter.set(mWindowMagnificationController.getCenterX(),
@@ -582,7 +582,7 @@
         final float expectedRatio = 0.5f;
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -621,8 +621,8 @@
                         preferredWindowSize.toString())
                 .commit();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController
-                    .enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
+                    Float.NaN);
         });
 
         // Change screen density and size to trigger restoring the preferred window size
@@ -649,7 +649,7 @@
     @Test
     public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         final int screenSize = mWindowManager.getCurrentWindowMetrics().getBounds().width() * 10;
@@ -674,7 +674,7 @@
     @Test
     public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             Mockito.reset(mWindowManager);
             Mockito.reset(mMirrorWindowControl);
@@ -703,7 +703,7 @@
     @Test
     public void initializeA11yNode_enabled_expectedValues() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
         final View mirrorView = mWindowManager.getAttachedView();
@@ -727,7 +727,7 @@
     public void performA11yActions_visible_expectedResults() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(1.5f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(1.5f, Float.NaN,
                     Float.NaN);
         });
 
@@ -761,7 +761,7 @@
     public void performA11yActions_visible_notifyAccessibilityActionPerformed() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
 
@@ -774,7 +774,7 @@
     @Test
     public void windowMagnifierEditMode_performA11yClickAction_exitEditMode() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
         });
@@ -812,7 +812,7 @@
                 /* pbase= */ 1);
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -852,7 +852,7 @@
                 /* pbase= */ 1);
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -888,7 +888,7 @@
         final int startingHeight = windowBounds.height();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -908,7 +908,7 @@
         final int startingHeight = windowBounds.height();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -931,7 +931,7 @@
                 /* base= */ 1,
                 /* pbase= */ 1);
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -971,7 +971,7 @@
                 /* pbase= */ 1);
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -1007,7 +1007,7 @@
         final int startingSize = mMinWindowSize;
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -1027,7 +1027,7 @@
         final int startingSize = mMinWindowSize;
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -1043,7 +1043,7 @@
     @Test
     public void enableWindowMagnification_hasA11yWindowTitle() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -1054,12 +1054,12 @@
     @Test
     public void enableWindowMagnificationWithScaleLessThanOne_enabled_disabled() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(0.9f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(0.9f, Float.NaN,
                     Float.NaN);
         });
 
@@ -1078,7 +1078,7 @@
         final int newRotation = simulateRotateTheDevice();
 
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         assertEquals(newRotation, mWindowMagnificationController.mRotation);
@@ -1087,7 +1087,7 @@
     @Test
     public void enableWindowMagnification_registerComponentCallback() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN,
                         Float.NaN));
 
@@ -1098,7 +1098,7 @@
     public void onLocaleChanged_enabled_updateA11yWindowTitle() {
         final String newA11yWindowTitle = "new a11y window title";
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         final TestableResources testableResources = getContext().getOrCreateTestableResources();
@@ -1116,7 +1116,7 @@
     @Test
     public void onSingleTap_enabled_scaleAnimates() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -1143,7 +1143,7 @@
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -1161,7 +1161,7 @@
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mWindowMagnificationController.enableWindowMagnificationInternal(
+                    mWindowMagnificationController.updateWindowMagnificationInternal(
                             Float.NaN, Float.NaN, Float.NaN);
                 });
 
@@ -1197,7 +1197,7 @@
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mWindowMagnificationController.enableWindowMagnificationInternal(
+                    mWindowMagnificationController.updateWindowMagnificationInternal(
                             Float.NaN, Float.NaN, Float.NaN);
                 });
 
@@ -1232,7 +1232,7 @@
         final int  expectedWindowHeight = minimumWindowSize;
         final int  expectedWindowWidth = minimumWindowSize;
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1259,7 +1259,7 @@
         final AtomicInteger actualWindowWidth = new AtomicInteger();
         mInstrumentation.runOnMainSync(() -> {
             mWindowMagnificationController.setWindowSize(expectedWindowWidth, expectedWindowHeight);
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                     Float.NaN, Float.NaN);
             actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
             actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
@@ -1274,7 +1274,7 @@
         final int minimumWindowSize = mResources.getDimensionPixelSize(
                 com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1294,7 +1294,7 @@
     public void setWindowSizeLargerThanScreenSize_enabled_windowSizeIsScreenSize() {
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1323,7 +1323,7 @@
 
         mInstrumentation.runOnMainSync(
                 () ->
-                        mWindowMagnificationController.enableWindowMagnificationInternal(
+                        mWindowMagnificationController.updateWindowMagnificationInternal(
                                 Float.NaN, Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1348,7 +1348,7 @@
 
         mInstrumentation.runOnMainSync(
                 () ->
-                        mWindowMagnificationController.enableWindowMagnificationInternal(
+                        mWindowMagnificationController.updateWindowMagnificationInternal(
                                 Float.NaN, Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1382,7 +1382,7 @@
 
         mInstrumentation.runOnMainSync(
                 () ->
-                        mWindowMagnificationController.enableWindowMagnificationInternal(
+                        mWindowMagnificationController.updateWindowMagnificationInternal(
                                 Float.NaN, Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1408,7 +1408,7 @@
                 com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger magnificationCenterX = new AtomicInteger();
@@ -1429,7 +1429,7 @@
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mWindowMagnificationController.enableWindowMagnificationInternal(
+                    mWindowMagnificationController.updateWindowMagnificationInternal(
                             1.5f, bounds.centerX(), bounds.centerY());
                 });
         View dragButton = getInternalView(R.id.drag_handle);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java
index e9d36b8..01e4d58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java
@@ -46,6 +46,7 @@
 import static org.mockito.Mockito.doAnswer;
 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.timeout;
 import static org.mockito.Mockito.times;
@@ -282,7 +283,7 @@
     @Test
     public void enableWindowMagnification_showControlAndNotifyBoundsChanged() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -351,7 +352,7 @@
     @Test
     public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         // Wait for Rects updated.
@@ -368,7 +369,7 @@
         mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize));
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -383,7 +384,7 @@
     @Test
     public void deleteWindowMagnification_destroyControlAndUnregisterComponentCallback() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN,
                         Float.NaN));
 
@@ -401,7 +402,7 @@
         setSystemGestureInsets();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     bounds.bottom);
         });
         ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag);
@@ -417,7 +418,7 @@
     @Test
     public void deleteWindowMagnification_notifySourceBoundsChanged() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN,
                         Float.NaN));
 
@@ -433,7 +434,7 @@
     @Test
     public void moveMagnifier_schedulesFrame() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -459,6 +460,7 @@
         final float targetCenterX = sourceBoundsCaptor.getValue().exactCenterX() + 10;
         final float targetCenterY = sourceBoundsCaptor.getValue().exactCenterY() + 10;
 
+        reset(mWindowMagnifierCallback);
         mInstrumentation.runOnMainSync(() -> {
             mWindowMagnificationController.moveWindowMagnifierToPosition(
                     targetCenterX, targetCenterY, mAnimationCallback);
@@ -491,6 +493,7 @@
         final float centerX = sourceBoundsCaptor.getValue().exactCenterX();
         final float centerY = sourceBoundsCaptor.getValue().exactCenterY();
 
+        reset(mWindowMagnifierCallback);
         mInstrumentation.runOnMainSync(() -> {
             mWindowMagnificationController.moveWindowMagnifierToPosition(
                     centerX + 10, centerY + 10, mAnimationCallback);
@@ -520,7 +523,7 @@
     @Test
     public void setScale_enabled_expectedValueAndUpdateStateDescription() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(2.0f,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(2.0f,
                         Float.NaN, Float.NaN));
 
         mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f));
@@ -553,7 +556,7 @@
         final float displayWidth = windowBounds.width();
         final PointF magnifiedCenter = new PointF(center, center + 5f);
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                     magnifiedCenter.x, magnifiedCenter.y);
             // Get the center again in case the center we set is out of screen.
             magnifiedCenter.set(mWindowMagnificationController.getCenterX(),
@@ -596,7 +599,7 @@
         final float expectedRatio = 0.5f;
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -635,8 +638,8 @@
                         preferredWindowSize.toString())
                 .commit();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController
-                    .enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
+                    Float.NaN);
         });
 
         // Screen density and size change
@@ -663,7 +666,7 @@
     @Test
     public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         final int screenSize = mWindowManager.getCurrentWindowMetrics().getBounds().width() * 10;
@@ -688,7 +691,7 @@
     @Test
     public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             Mockito.reset(mWindowManager);
             Mockito.reset(mMirrorWindowControl);
@@ -717,7 +720,7 @@
     @Test
     public void initializeA11yNode_enabled_expectedValues() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
         final View mirrorView = mSurfaceControlViewHost.getView();
@@ -741,7 +744,7 @@
     public void performA11yActions_visible_expectedResults() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(1.5f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(1.5f, Float.NaN,
                     Float.NaN);
         });
 
@@ -775,7 +778,7 @@
     public void performA11yActions_visible_notifyAccessibilityActionPerformed() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
 
@@ -788,7 +791,7 @@
     @Test
     public void windowMagnifierEditMode_performA11yClickAction_exitEditMode() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
         });
@@ -829,7 +832,7 @@
                 /* pbase= */ 1);
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -871,7 +874,7 @@
                 /* pbase= */ 1);
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -909,7 +912,7 @@
         final int startingHeight = windowBounds.height();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -929,7 +932,7 @@
         final int startingHeight = windowBounds.height();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -952,7 +955,7 @@
                 /* base= */ 1,
                 /* pbase= */ 1);
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -994,7 +997,7 @@
                 /* pbase= */ 1);
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -1032,7 +1035,7 @@
         final int startingSize = mMinWindowSize;
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -1052,7 +1055,7 @@
         final int startingSize = mMinWindowSize;
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.setWindowSize(startingSize, startingSize);
             mWindowMagnificationController.setEditMagnifierSizeMode(true);
@@ -1068,7 +1071,7 @@
     @Test
     public void enableWindowMagnification_hasA11yWindowTitle() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -1079,12 +1082,12 @@
     @Test
     public void enableWindowMagnificationWithScaleLessThanOne_enabled_disabled() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(0.9f, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(0.9f, Float.NaN,
                     Float.NaN);
         });
 
@@ -1103,7 +1106,7 @@
         final int newRotation = simulateRotateTheDevice();
 
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         assertEquals(newRotation, mWindowMagnificationController.mRotation);
@@ -1112,7 +1115,7 @@
     @Test
     public void enableWindowMagnification_registerComponentCallback() {
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN,
                         Float.NaN));
 
@@ -1123,7 +1126,7 @@
     public void onLocaleChanged_enabled_updateA11yWindowTitle() {
         final String newA11yWindowTitle = "new a11y window title";
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         final TestableResources testableResources = getContext().getOrCreateTestableResources();
@@ -1141,7 +1144,7 @@
     @Test
     public void onSingleTap_enabled_scaleAnimates() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -1168,7 +1171,7 @@
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -1186,7 +1189,7 @@
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mWindowMagnificationController.enableWindowMagnificationInternal(
+                    mWindowMagnificationController.updateWindowMagnificationInternal(
                             Float.NaN, Float.NaN, Float.NaN);
                 });
         // Wait for Region updated.
@@ -1215,7 +1218,7 @@
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mWindowMagnificationController.enableWindowMagnificationInternal(
+                    mWindowMagnificationController.updateWindowMagnificationInternal(
                             Float.NaN, Float.NaN, Float.NaN);
                 });
         // Wait for Region updated.
@@ -1244,7 +1247,7 @@
         final int  expectedWindowHeight = minimumWindowSize;
         final int  expectedWindowWidth = minimumWindowSize;
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1271,7 +1274,7 @@
         final AtomicInteger actualWindowWidth = new AtomicInteger();
         mInstrumentation.runOnMainSync(() -> {
             mWindowMagnificationController.setWindowSize(expectedWindowWidth, expectedWindowHeight);
-            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                     Float.NaN, Float.NaN);
             actualWindowHeight.set(mSurfaceControlViewHost.getView().getLayoutParams().height);
             actualWindowWidth.set(mSurfaceControlViewHost.getView().getLayoutParams().width);
@@ -1286,7 +1289,7 @@
         final int minimumWindowSize = mResources.getDimensionPixelSize(
                 com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1306,7 +1309,7 @@
     public void setWindowSizeLargerThanScreenSize_enabled_windowSizeIsScreenSize() {
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1335,7 +1338,7 @@
 
         mInstrumentation.runOnMainSync(
                 () ->
-                        mWindowMagnificationController.enableWindowMagnificationInternal(
+                        mWindowMagnificationController.updateWindowMagnificationInternal(
                                 Float.NaN, Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1362,7 +1365,7 @@
 
         mInstrumentation.runOnMainSync(
                 () ->
-                        mWindowMagnificationController.enableWindowMagnificationInternal(
+                        mWindowMagnificationController.updateWindowMagnificationInternal(
                                 Float.NaN, Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1398,7 +1401,7 @@
 
         mInstrumentation.runOnMainSync(
                 () ->
-                        mWindowMagnificationController.enableWindowMagnificationInternal(
+                        mWindowMagnificationController.updateWindowMagnificationInternal(
                                 Float.NaN, Float.NaN, Float.NaN));
 
         final AtomicInteger actualWindowHeight = new AtomicInteger();
@@ -1426,7 +1429,7 @@
                 com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                () -> mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                         Float.NaN, Float.NaN));
 
         final AtomicInteger magnificationCenterX = new AtomicInteger();
@@ -1447,7 +1450,7 @@
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mWindowMagnificationController.enableWindowMagnificationInternal(
+                    mWindowMagnificationController.updateWindowMagnificationInternal(
                             1.5f, bounds.centerX(), bounds.centerY());
                 });
         View dragButton = getInternalView(R.id.drag_handle);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java
index b843fda..516b665 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java
@@ -23,11 +23,12 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.Size;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.FakeSharedPreferences;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
index b0f0363..ebb6b48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
@@ -39,14 +39,16 @@
 import com.android.settingslib.bluetooth.BluetoothEventManager;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.HapClientProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogTransitionAnimator;
+import com.android.systemui.bluetooth.qsdialog.DeviceItem;
+import com.android.systemui.bluetooth.qsdialog.DeviceItemType;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.tiles.dialog.bluetooth.DeviceItem;
-import com.android.systemui.qs.tiles.dialog.bluetooth.DeviceItemType;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.phone.SystemUIDialogManager;
@@ -88,6 +90,10 @@
     @Mock
     private LocalBluetoothAdapter mLocalBluetoothAdapter;
     @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private HapClientProfile mHapClientProfile;
+    @Mock
     private CachedBluetoothDeviceManager mCachedDeviceManager;
     @Mock
     private BluetoothEventManager mBluetoothEventManager;
@@ -106,6 +112,8 @@
     public void setUp() {
         mTestableLooper = TestableLooper.get(this);
         when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
+        when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
         when(mLocalBluetoothAdapter.isEnabled()).thenReturn(true);
         when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
@@ -163,6 +171,7 @@
 
     private void setUpPairNewDeviceDialog() {
         mDialogDelegate = new HearingDevicesDialogDelegate(
+                mContext,
                 true,
                 mSystemUIDialogFactory,
                 mActivityStarter,
@@ -185,6 +194,7 @@
 
     private void setUpDeviceListDialog() {
         mDialogDelegate = new HearingDevicesDialogDelegate(
+                mContext,
                 false,
                 mSystemUIDialogFactory,
                 mActivityStarter,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapterTest.java
index 95d5597..d16db65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapterTest.java
@@ -27,7 +27,7 @@
 
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.qs.tiles.dialog.bluetooth.DeviceItem;
+import com.android.systemui.bluetooth.qsdialog.DeviceItem;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/InputSessionTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/InputSessionTest.java
new file mode 100644
index 0000000..2f4999b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/InputSessionTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.EnableFlags;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.Choreographer;
+import android.view.GestureDetector;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.Flags;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+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;
+
+/**
+ * A test suite for exercising {@link InputSession}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
[email protected]()
+public class InputSessionTest extends SysuiTestCase {
+    @Mock
+    InputMonitorCompat mInputMonitor;
+
+    @Mock
+    GestureDetector mGestureDetector;
+
+    @Mock
+    InputChannelCompat.InputEventListener mInputEventListener;
+
+    TestableLooper mLooper;
+
+    @Mock
+    Choreographer mChoreographer;
+
+    @Mock
+    InputChannelCompat.InputEventReceiver mInputEventReceiver;
+
+    InputSession mSession;
+
+    InputChannelCompat.InputEventListener mEventListener;
+
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mLooper = TestableLooper.get(this);
+    }
+
+    private void createSession(boolean pilfer) {
+        when(mInputMonitor.getInputReceiver(any(), any(), any()))
+                .thenReturn(mInputEventReceiver);
+        mSession = new InputSession(mInputMonitor, mGestureDetector,
+                mInputEventListener, mChoreographer, mLooper.getLooper(), pilfer);
+        final ArgumentCaptor<InputChannelCompat.InputEventListener> listenerCaptor =
+                ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+        verify(mInputMonitor).getInputReceiver(any(), any(), listenerCaptor.capture());
+        mEventListener = listenerCaptor.getValue();
+    }
+
+    /**
+     * Ensures consumed motion events are pilfered when option is set.
+     */
+    @Test
+    public void testPilferOnMotionEventGestureConsume() {
+        createSession(true);
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        when(mGestureDetector.onTouchEvent(event)).thenReturn(true);
+        mEventListener.onInputEvent(event);
+        verify(mInputEventListener).onInputEvent(eq(event));
+        verify(mInputMonitor).pilferPointers();
+    }
+
+    /**
+     * Ensures consumed motion events are not pilfered when option is not set.
+     */
+    @Test
+    public void testNoPilferOnMotionEventGestureConsume() {
+        createSession(false);
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        when(mGestureDetector.onTouchEvent(event)).thenReturn(true);
+        mEventListener.onInputEvent(event);
+        verify(mInputEventListener).onInputEvent(eq(event));
+        verify(mInputMonitor, never()).pilferPointers();
+    }
+
+    /**
+     * Ensures input events are never pilfered.
+     */
+    @Test
+    public void testNoPilferOnInputEvent() {
+        createSession(true);
+        final InputEvent event = Mockito.mock(InputEvent.class);
+        mEventListener.onInputEvent(event);
+        verify(mInputEventListener).onInputEvent(eq(event));
+        verify(mInputMonitor, never()).pilferPointers();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_DREAM_INPUT_SESSION_PILFER_ONCE)
+    public void testPilferOnce() {
+        createSession(true);
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        when(mGestureDetector.onTouchEvent(event)).thenReturn(true);
+        mEventListener.onInputEvent(event);
+        mEventListener.onInputEvent(event);
+        verify(mInputEventListener, times(2)).onInputEvent(eq(event));
+        verify(mInputMonitor, times(1)).pilferPointers();
+    }
+
+    /**
+     * Ensures components are properly disposed.
+     */
+    @Test
+    public void testDispose() {
+        createSession(true);
+        mSession.dispose();
+        verify(mInputMonitor).dispose();
+        verify(mInputEventReceiver).dispose();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
new file mode 100644
index 0000000..1e3b556
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.ambient.touch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.testing.AndroidTestingRunner;
+import android.util.Pair;
+import android.view.GestureDetector;
+import android.view.IWindowManager;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.display.DisplayHelper;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class TouchMonitorTest extends SysuiTestCase {
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    private static class Environment {
+        private final InputSessionComponent.Factory mInputFactory;
+        private final InputSession mInputSession;
+        private final Lifecycle mLifecycle;
+        private final LifecycleOwner mLifecycleOwner;
+        private final TouchMonitor mMonitor;
+        private final DefaultLifecycleObserver mLifecycleObserver;
+        private final InputChannelCompat.InputEventListener mEventListener;
+        private final GestureDetector.OnGestureListener mGestureListener;
+        private final DisplayHelper mDisplayHelper;
+        private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+        private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
+        private final Rect mDisplayBounds = Mockito.mock(Rect.class);
+        private final IWindowManager mIWindowManager;
+
+        Environment(Set<TouchHandler> handlers) {
+            mLifecycle = Mockito.mock(Lifecycle.class);
+            mLifecycleOwner = Mockito.mock(LifecycleOwner.class);
+            mIWindowManager = Mockito.mock(IWindowManager.class);
+
+            mInputFactory = Mockito.mock(InputSessionComponent.Factory.class);
+            final InputSessionComponent inputComponent = Mockito.mock(InputSessionComponent.class);
+            mInputSession = Mockito.mock(InputSession.class);
+
+            when(mInputFactory.create(any(), any(), any(), anyBoolean()))
+                    .thenReturn(inputComponent);
+            when(inputComponent.getInputSession()).thenReturn(mInputSession);
+
+            mDisplayHelper = Mockito.mock(DisplayHelper.class);
+            when(mDisplayHelper.getMaxBounds(anyInt(), anyInt()))
+                    .thenReturn(mDisplayBounds);
+            mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor,
+                    mLifecycle, mInputFactory, mDisplayHelper, handlers, mIWindowManager, 0);
+            mMonitor.init();
+
+            final ArgumentCaptor<LifecycleObserver> lifecycleObserverCaptor =
+                    ArgumentCaptor.forClass(LifecycleObserver.class);
+            verify(mLifecycle).addObserver(lifecycleObserverCaptor.capture());
+            assertThat(lifecycleObserverCaptor.getValue() instanceof DefaultLifecycleObserver)
+                    .isTrue();
+            mLifecycleObserver = (DefaultLifecycleObserver) lifecycleObserverCaptor.getValue();
+
+            updateLifecycle(observer -> observer.first.onResume(observer.second));
+
+            // Capture creation request.
+            final ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
+                    ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+            final ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+                    ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+            verify(mInputFactory).create(any(), inputEventListenerCaptor.capture(),
+                    gestureListenerCaptor.capture(),
+                    eq(true));
+            mEventListener = inputEventListenerCaptor.getValue();
+            mGestureListener = gestureListenerCaptor.getValue();
+        }
+
+        public Rect getDisplayBounds() {
+            return mDisplayBounds;
+        }
+
+        void executeAll() {
+            mExecutor.runAllReady();
+        }
+
+        void publishInputEvent(InputEvent event) {
+            mEventListener.onInputEvent(event);
+        }
+
+        void publishGestureEvent(Consumer<GestureDetector.OnGestureListener> listenerConsumer) {
+            listenerConsumer.accept(mGestureListener);
+        }
+
+        void updateLifecycle(Consumer<Pair<DefaultLifecycleObserver, LifecycleOwner>> consumer) {
+            consumer.accept(Pair.create(mLifecycleObserver, mLifecycleOwner));
+        }
+
+        void verifyInputSessionDispose() {
+            verify(mInputSession).dispose();
+            Mockito.clearInvocations(mInputSession);
+        }
+    }
+
+    @Test
+    public void testReportedDisplayBounds() {
+        final TouchHandler touchHandler = createTouchHandler();
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
+        when(initialEvent.getX()).thenReturn(0.0f);
+        when(initialEvent.getY()).thenReturn(0.0f);
+        environment.publishInputEvent(initialEvent);
+
+        // Verify display bounds passed into TouchHandler#getTouchInitiationRegion
+        verify(touchHandler).getTouchInitiationRegion(
+                eq(environment.getDisplayBounds()), any(), any());
+        final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor =
+                ArgumentCaptor.forClass(TouchHandler.TouchSession.class);
+        verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
+
+        // Verify that display bounds provided from TouchSession#getBounds
+        assertThat(touchSessionArgumentCaptor.getValue().getBounds())
+                .isEqualTo(environment.getDisplayBounds());
+    }
+
+    @Test
+    public void testEntryTouchZone() {
+        final TouchHandler touchHandler = createTouchHandler();
+        final Rect touchArea = new Rect(4, 4, 8 , 8);
+
+        doAnswer(invocation -> {
+            final Region region = (Region) invocation.getArguments()[1];
+            region.set(touchArea);
+            return null;
+        }).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        // Ensure touch outside specified region is not delivered.
+        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
+        when(initialEvent.getX()).thenReturn(0.0f);
+        when(initialEvent.getY()).thenReturn(1.0f);
+        environment.publishInputEvent(initialEvent);
+        verify(touchHandler, never()).onSessionStart(any());
+
+        // Make sure touch inside region causes session start.
+        when(initialEvent.getX()).thenReturn(5.0f);
+        when(initialEvent.getY()).thenReturn(5.0f);
+        environment.publishInputEvent(initialEvent);
+        verify(touchHandler).onSessionStart(any());
+    }
+
+    @Test
+    public void testSessionCount() {
+        final TouchHandler touchHandler = createTouchHandler();
+        final Rect touchArea = new Rect(4, 4, 8 , 8);
+
+        final TouchHandler unzonedTouchHandler = createTouchHandler();
+        doAnswer(invocation -> {
+            final Region region = (Region) invocation.getArguments()[1];
+            region.set(touchArea);
+            return null;
+        }).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
+
+        final Environment environment = new Environment(Stream.of(touchHandler, unzonedTouchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        // Ensure touch outside specified region is delivered to unzoned touch handler.
+        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
+        when(initialEvent.getX()).thenReturn(0.0f);
+        when(initialEvent.getY()).thenReturn(1.0f);
+        environment.publishInputEvent(initialEvent);
+
+        ArgumentCaptor<TouchHandler.TouchSession> touchSessionCaptor = ArgumentCaptor.forClass(
+                TouchHandler.TouchSession.class);
+
+        // Make sure only one active session.
+        {
+            verify(unzonedTouchHandler).onSessionStart(touchSessionCaptor.capture());
+            final TouchHandler.TouchSession touchSession = touchSessionCaptor.getValue();
+            assertThat(touchSession.getActiveSessionCount()).isEqualTo(1);
+            touchSession.pop();
+            environment.executeAll();
+        }
+
+        // Make sure touch inside the touch region.
+        when(initialEvent.getX()).thenReturn(5.0f);
+        when(initialEvent.getY()).thenReturn(5.0f);
+        environment.publishInputEvent(initialEvent);
+
+        // Make sure there are two active sessions.
+        {
+            verify(touchHandler).onSessionStart(touchSessionCaptor.capture());
+            final TouchHandler.TouchSession touchSession = touchSessionCaptor.getValue();
+            assertThat(touchSession.getActiveSessionCount()).isEqualTo(2);
+            touchSession.pop();
+        }
+    }
+
+
+    @Test
+    public void testNoActiveSessionWhenHandlerDisabled() {
+        final TouchHandler touchHandler = Mockito.mock(TouchHandler.class);
+        // disable the handler
+        when(touchHandler.isEnabled()).thenReturn(false);
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
+        when(initialEvent.getX()).thenReturn(5.0f);
+        when(initialEvent.getY()).thenReturn(5.0f);
+        environment.publishInputEvent(initialEvent);
+
+        // Make sure there is no active session.
+        verify(touchHandler, never()).onSessionStart(any());
+        verify(touchHandler, never()).getTouchInitiationRegion(any(), any(), any());
+    }
+
+    @Test
+    public void testInputEventPropagation() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        // Ensure session started
+        final InputChannelCompat.InputEventListener eventListener =
+                registerInputEventListener(touchHandler);
+
+        // First event will be missed since we register after the execution loop,
+        final InputEvent event = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(event);
+        verify(eventListener).onInputEvent(eq(event));
+    }
+
+    @Test
+    public void testInputEventPropagationAfterRemoval() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        // Ensure session started
+        final TouchHandler.TouchSession session = captureSession(touchHandler);
+        final InputChannelCompat.InputEventListener eventListener =
+                registerInputEventListener(session);
+
+        session.pop();
+        environment.executeAll();
+
+        final InputEvent event = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(event);
+
+        verify(eventListener, never()).onInputEvent(eq(event));
+    }
+
+    @Test
+    public void testInputGesturePropagation() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        // Ensure session started
+        final GestureDetector.OnGestureListener gestureListener =
+                registerGestureListener(touchHandler);
+
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        environment.publishGestureEvent(onGestureListener -> onGestureListener.onShowPress(event));
+        verify(gestureListener).onShowPress(eq(event));
+    }
+
+    @Test
+    public void testGestureConsumption() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        // Ensure session started
+        final GestureDetector.OnGestureListener gestureListener =
+                registerGestureListener(touchHandler);
+
+        when(gestureListener.onDown(any())).thenReturn(true);
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        environment.publishGestureEvent(onGestureListener -> {
+            assertThat(onGestureListener.onDown(event)).isTrue();
+        });
+
+        verify(gestureListener).onDown(eq(event));
+    }
+
+    @Test
+    public void testBroadcast() {
+        final TouchHandler touchHandler = createTouchHandler();
+        final TouchHandler touchHandler2 = createTouchHandler();
+        when(touchHandler2.isEnabled()).thenReturn(true);
+
+        final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        final HashSet<InputChannelCompat.InputEventListener> inputListeners = new HashSet<>();
+
+        inputListeners.add(registerInputEventListener(touchHandler));
+        inputListeners.add(registerInputEventListener(touchHandler));
+        inputListeners.add(registerInputEventListener(touchHandler2));
+
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        environment.publishInputEvent(event);
+
+        inputListeners
+                .stream()
+                .forEach(inputEventListener -> verify(inputEventListener).onInputEvent(event));
+    }
+
+    @Test
+    public void testPush() throws InterruptedException, ExecutionException {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        final TouchHandler.TouchSession session = captureSession(touchHandler);
+        final InputChannelCompat.InputEventListener eventListener =
+                registerInputEventListener(session);
+
+        final ListenableFuture<TouchHandler.TouchSession> frontSessionFuture = session.push();
+        environment.executeAll();
+        final TouchHandler.TouchSession frontSession = frontSessionFuture.get();
+        final InputChannelCompat.InputEventListener frontEventListener =
+                registerInputEventListener(frontSession);
+
+        final MotionEvent event = Mockito.mock(MotionEvent.class);
+        environment.publishInputEvent(event);
+
+        verify(frontEventListener).onInputEvent(eq(event));
+        verify(eventListener, never()).onInputEvent(any());
+
+        Mockito.clearInvocations(eventListener, frontEventListener);
+
+        ListenableFuture<TouchHandler.TouchSession> sessionFuture = frontSession.pop();
+        environment.executeAll();
+
+        TouchHandler.TouchSession returnedSession = sessionFuture.get();
+        assertThat(session == returnedSession).isTrue();
+
+        environment.executeAll();
+
+        final MotionEvent followupEvent = Mockito.mock(MotionEvent.class);
+        environment.publishInputEvent(followupEvent);
+
+        verify(eventListener).onInputEvent(eq(followupEvent));
+        verify(frontEventListener, never()).onInputEvent(any());
+    }
+
+    @Test
+    public void testPop() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final TouchHandler.TouchSession.Callback callback =
+                Mockito.mock(TouchHandler.TouchSession.Callback.class);
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        final TouchHandler.TouchSession session = captureSession(touchHandler);
+        session.registerCallback(callback);
+        session.pop();
+        environment.executeAll();
+
+        verify(callback).onRemoved();
+    }
+
+    @Test
+    public void testPauseWithNoActiveSessions() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        environment.updateLifecycle(observerOwnerPair -> {
+            observerOwnerPair.first.onPause(observerOwnerPair.second);
+        });
+
+        environment.verifyInputSessionDispose();
+    }
+
+    @Test
+    public void testDeferredPauseWithActiveSessions() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        // Ensure session started
+        final InputChannelCompat.InputEventListener eventListener =
+                registerInputEventListener(touchHandler);
+
+        // First event will be missed since we register after the execution loop,
+        final InputEvent event = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(event);
+        verify(eventListener).onInputEvent(eq(event));
+
+        final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor =
+                ArgumentCaptor.forClass(TouchHandler.TouchSession.class);
+
+        verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
+
+        environment.updateLifecycle(observerOwnerPair -> {
+            observerOwnerPair.first.onPause(observerOwnerPair.second);
+        });
+
+        verify(environment.mInputSession, never()).dispose();
+
+        // End session
+        touchSessionArgumentCaptor.getValue().pop();
+        environment.executeAll();
+
+        // Check to make sure the input session is now disposed.
+        environment.verifyInputSessionDispose();
+    }
+
+    @Test
+    public void testDestroyWithActiveSessions() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        // Ensure session started
+        final InputChannelCompat.InputEventListener eventListener =
+                registerInputEventListener(touchHandler);
+
+        // First event will be missed since we register after the execution loop,
+        final InputEvent event = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(event);
+        verify(eventListener).onInputEvent(eq(event));
+
+        final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor =
+                ArgumentCaptor.forClass(TouchHandler.TouchSession.class);
+
+        verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
+
+        environment.updateLifecycle(observerOwnerPair -> {
+            observerOwnerPair.first.onDestroy(observerOwnerPair.second);
+        });
+
+        // Check to make sure the input session is now disposed.
+        environment.verifyInputSessionDispose();
+    }
+
+
+    @Test
+    public void testPilfering() {
+        final TouchHandler touchHandler1 = createTouchHandler();
+        final TouchHandler touchHandler2 = createTouchHandler();
+        final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        final TouchHandler.TouchSession session1 = captureSession(touchHandler1);
+        final GestureDetector.OnGestureListener gestureListener1 =
+                registerGestureListener(session1);
+
+        final TouchHandler.TouchSession session2 = captureSession(touchHandler2);
+        final GestureDetector.OnGestureListener gestureListener2 =
+                registerGestureListener(session2);
+        when(gestureListener2.onDown(any())).thenReturn(true);
+
+        final MotionEvent gestureEvent = Mockito.mock(MotionEvent.class);
+        environment.publishGestureEvent(
+                onGestureListener -> onGestureListener.onDown(gestureEvent));
+
+        Mockito.clearInvocations(gestureListener1, gestureListener2);
+
+        final MotionEvent followupEvent = Mockito.mock(MotionEvent.class);
+        environment.publishGestureEvent(
+                onGestureListener -> onGestureListener.onDown(followupEvent));
+
+        verify(gestureListener1, never()).onDown(any());
+        verify(gestureListener2).onDown(eq(followupEvent));
+    }
+
+    @Test
+    public void testOnRemovedCallbackOnStopMonitoring() {
+        final TouchHandler touchHandler = createTouchHandler();
+
+        final TouchHandler.TouchSession.Callback callback =
+                Mockito.mock(TouchHandler.TouchSession.Callback.class);
+
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)));
+
+        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+        environment.publishInputEvent(initialEvent);
+
+        final TouchHandler.TouchSession session = captureSession(touchHandler);
+        session.registerCallback(callback);
+
+        environment.executeAll();
+
+        environment.updateLifecycle(observerOwnerPair -> {
+            observerOwnerPair.first.onDestroy(observerOwnerPair.second);
+        });
+
+        environment.executeAll();
+
+        verify(callback).onRemoved();
+    }
+
+    private GestureDetector.OnGestureListener registerGestureListener(TouchHandler handler) {
+        final GestureDetector.OnGestureListener gestureListener = Mockito.mock(
+                GestureDetector.OnGestureListener.class);
+        final ArgumentCaptor<TouchHandler.TouchSession> sessionCaptor =
+                ArgumentCaptor.forClass(TouchHandler.TouchSession.class);
+        verify(handler).onSessionStart(sessionCaptor.capture());
+        sessionCaptor.getValue().registerGestureListener(gestureListener);
+
+        return gestureListener;
+    }
+
+    private GestureDetector.OnGestureListener registerGestureListener(
+            TouchHandler.TouchSession session) {
+        final GestureDetector.OnGestureListener gestureListener = Mockito.mock(
+                GestureDetector.OnGestureListener.class);
+        session.registerGestureListener(gestureListener);
+
+        return gestureListener;
+    }
+
+    private InputChannelCompat.InputEventListener registerInputEventListener(
+            TouchHandler.TouchSession session) {
+        final InputChannelCompat.InputEventListener eventListener = Mockito.mock(
+                InputChannelCompat.InputEventListener.class);
+        session.registerInputListener(eventListener);
+
+        return eventListener;
+    }
+
+    private TouchHandler.TouchSession captureSession(TouchHandler handler) {
+        final ArgumentCaptor<TouchHandler.TouchSession> sessionCaptor =
+                ArgumentCaptor.forClass(TouchHandler.TouchSession.class);
+        verify(handler).onSessionStart(sessionCaptor.capture());
+        return sessionCaptor.getValue();
+    }
+
+    private InputChannelCompat.InputEventListener registerInputEventListener(
+            TouchHandler handler) {
+        return registerInputEventListener(captureSession(handler));
+    }
+
+    private TouchHandler createTouchHandler() {
+        final TouchHandler touchHandler = Mockito.mock(TouchHandler.class);
+        // enable the handler by default
+        when(touchHandler.isEnabled()).thenReturn(true);
+        return touchHandler;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogTransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogTransitionAnimatorTest.kt
index 9182e4101..d84a578 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogTransitionAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogTransitionAnimatorTest.kt
@@ -15,11 +15,11 @@
 import android.widget.FrameLayout
 import android.widget.LinearLayout
 import androidx.test.filters.SmallTest
-import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.jank.Cuj
 import com.android.internal.policy.DecorView
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.jank.interactionJankMonitor
-import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertFalse
@@ -42,16 +42,15 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
 class DialogTransitionAnimatorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
     private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator
     private val attachedViews = mutableSetOf<View>()
-
-    private val interactionJankMonitor = Kosmos().interactionJankMonitor
-    @get:Rule val rule: MockitoRule = MockitoJUnit.rule()
+    @get:Rule
+    val rule: MockitoRule = MockitoJUnit.rule()
 
     @Before
     fun setUp() {
-        mDialogTransitionAnimator =
-            fakeDialogTransitionAnimator(interactionJankMonitor = interactionJankMonitor)
+        mDialogTransitionAnimator = kosmos.dialogTransitionAnimator
     }
 
     @After
@@ -96,7 +95,7 @@
 
         // The dialog content is inside this fake window view.
         assertNotNull(
-            dialogContentWithBackground.findViewByPredicate { it === dialog.contentView }
+                dialogContentWithBackground.findViewByPredicate { it === dialog.contentView }
         )
 
         // Clicking the transparent background should dismiss the dialog.
@@ -126,8 +125,8 @@
         val firstDialog = createAndShowDialog()
         val secondDialog = createDialogAndShowFromDialog(firstDialog)
 
-        val controller =
-            mDialogTransitionAnimator.createActivityTransitionController(secondDialog.contentView)!!
+        val controller = mDialogTransitionAnimator
+                .createActivityTransitionController(secondDialog.contentView)!!
 
         // The dialog shouldn't be dismissable during the animation.
         runOnMainThreadAndWaitForIdleSync {
@@ -156,18 +155,24 @@
     @Test
     fun testActivityLaunchWhenLockedWithoutAlternateAuth() {
         val dialogTransitionAnimator =
-            fakeDialogTransitionAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = false)
+                fakeDialogTransitionAnimator(
+                        isUnlocked = false,
+                        isShowingAlternateAuthOnUnlock = false,
+                        interactionJankMonitor = kosmos.interactionJankMonitor)
         val dialog = createAndShowDialog(dialogTransitionAnimator)
         assertNull(dialogTransitionAnimator.createActivityTransitionController(dialog.contentView))
     }
 
     @Test
     fun testActivityLaunchWhenLockedWithAlternateAuth() {
-        val dialogTransitionAnimator =
-            fakeDialogTransitionAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = true)
+        val dialogTransitionAnimator = fakeDialogTransitionAnimator(
+                isUnlocked = false,
+                isShowingAlternateAuthOnUnlock = true,
+                interactionJankMonitor = kosmos.interactionJankMonitor
+        )
         val dialog = createAndShowDialog(dialogTransitionAnimator)
         assertNotNull(
-            dialogTransitionAnimator.createActivityTransitionController(dialog.contentView)
+                dialogTransitionAnimator.createActivityTransitionController(dialog.contentView)
         )
     }
 
@@ -193,11 +198,14 @@
         runOnMainThreadAndWaitForIdleSync {
             val dialog = TestDialog(context)
             mDialogTransitionAnimator.showFromView(
-                dialog, touchSurface, cuj = DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN))
+                    dialog,
+                    touchSurface,
+                    cuj = DialogCuj(Cuj.CUJ_SHADE_DIALOG_OPEN)
+            )
         }
 
-        verify(interactionJankMonitor).begin(any())
-        verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN)
+        verify(kosmos.interactionJankMonitor).begin(any())
+        verify(kosmos.interactionJankMonitor).end(Cuj.CUJ_SHADE_DIALOG_OPEN)
     }
 
     @Test
@@ -206,11 +214,14 @@
         runOnMainThreadAndWaitForIdleSync {
             val dialog = TestDialog(context)
             mDialogTransitionAnimator.showFromDialog(
-                dialog, firstDialog, cuj = DialogCuj(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN))
+                    dialog,
+                    firstDialog,
+                    cuj = DialogCuj(Cuj.CUJ_USER_DIALOG_OPEN)
+            )
             dialog
         }
-        verify(interactionJankMonitor).begin(any())
-        verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
+        verify(kosmos.interactionJankMonitor).begin(any())
+        verify(kosmos.interactionJankMonitor).end(Cuj.CUJ_USER_DIALOG_OPEN)
     }
 
     @Test
@@ -280,7 +291,7 @@
     }
 
     private fun createAndShowDialog(
-        animator: DialogTransitionAnimator = mDialogTransitionAnimator,
+            animator: DialogTransitionAnimator = mDialogTransitionAnimator,
     ): TestDialog {
         val touchSurface = createTouchSurface()
         return showDialogFromView(touchSurface, animator)
@@ -302,8 +313,8 @@
     }
 
     private fun showDialogFromView(
-        touchSurface: View,
-        animator: DialogTransitionAnimator = mDialogTransitionAnimator,
+            touchSurface: View,
+            animator: DialogTransitionAnimator = mDialogTransitionAnimator,
     ): TestDialog {
         return runOnMainThreadAndWaitForIdleSync {
             val dialog = TestDialog(context)
@@ -331,10 +342,10 @@
 
     private class TouchSurfaceView(context: Context) : FrameLayout(context), LaunchableView {
         private val delegate =
-            LaunchableViewDelegate(
-                this,
-                superSetVisibility = { super.setVisibility(it) },
-            )
+                LaunchableViewDelegate(
+                        this,
+                        superSetVisibility = { super.setVisibility(it) },
+                )
 
         override fun setShouldBlockVisibilityChanges(block: Boolean) {
             delegate.setShouldBlockVisibilityChanges(block)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
index f490f3c..cbad133 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
@@ -41,7 +41,6 @@
 import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.scene.ui.view.WindowRootView
 import com.android.systemui.shade.QuickSettingsController
 import com.android.systemui.shade.ShadeController
@@ -109,7 +108,6 @@
             headsUpManager,
             powerInteractor,
             activeNotificationsInteractor,
-            kosmos.sceneContainerFlags,
             kosmos::sceneInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 33a6010..de3b741 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.biometrics
 
+import android.app.ActivityTaskManager
 import android.app.admin.DevicePolicyManager
 import android.content.pm.PackageManager
 import android.hardware.biometrics.BiometricAuthenticator
@@ -44,9 +45,12 @@
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.Flags.FLAG_CONSTRAINT_BP
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
 import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
 import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
 import com.android.systemui.biometrics.data.repository.FakePromptRepository
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor
@@ -120,10 +124,12 @@
     lateinit var selectedUserInteractor: SelectedUserInteractor
     @Mock
     private lateinit var packageManager: PackageManager
+    @Mock private lateinit var activityTaskManager: ActivityTaskManager
 
     private val testScope = TestScope(StandardTestDispatcher())
     private val fakeExecutor = FakeExecutor(FakeSystemClock())
     private val biometricPromptRepository = FakePromptRepository()
+    private val biometricStatusRepository = FakeBiometricStatusRepository()
     private val fingerprintRepository = FakeFingerprintPropertyRepository()
     private val displayStateRepository = FakeDisplayStateRepository()
     private val credentialInteractor = FakeCredentialInteractor()
@@ -143,6 +149,7 @@
     private lateinit var displayRepository: FakeDisplayRepository
     private lateinit var displayStateInteractor: DisplayStateInteractor
     private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
+    private lateinit var biometricStatusInteractor: BiometricStatusInteractor
 
     private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor)
     private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android)
@@ -168,6 +175,9 @@
                         selectedUserInteractor,
                         testScope.backgroundScope,
                 )
+        biometricStatusInteractor =
+                BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository,
+                    fingerprintRepository)
         // Set up default logo icon
         whenever(packageManager.getApplicationIcon(OP_PACKAGE_NAME)).thenReturn(defaultLogoIcon)
         context.setMockPackageManager(packageManager)
@@ -645,6 +655,7 @@
             promptSelectorInteractor,
             context,
             udfpsOverlayInteractor,
+            biometricStatusInteractor,
             udfpsUtils
         ),
         { credentialViewModel },
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
index 8c8544c..d2c6957 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationDialogFactoryTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.biometrics;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -90,7 +91,8 @@
         assumeTrue(getContext().getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
 
-        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT);
+        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT,
+                false);
 
         verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
 
@@ -115,7 +117,8 @@
         assumeTrue(getContext().getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
 
-        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT);
+        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT,
+                false);
 
         verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
 
@@ -134,11 +137,25 @@
     }
 
     @Test
+    public void testFingerprintReEnrollDialog_forced() {
+        assumeTrue(getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT));
+
+        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FINGERPRINT,
+                true);
+
+        verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
+
+        verify(mDialog, never()).setNegativeButton(anyInt(), any());
+    }
+
+    @Test
     public void testFaceReEnrollDialog_onRemovalSucceeded() {
         assumeTrue(getContext().getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_FACE));
 
-        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE);
+        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE,
+                false);
 
         verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
 
@@ -163,7 +180,8 @@
         assumeTrue(getContext().getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_FACE));
 
-        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE);
+        mDialogFactory.createReenrollDialog(0, mActivityStarter, BiometricSourceType.FACE,
+                false);
 
         verify(mDialog).setPositiveButton(anyInt(), mOnClickListenerArgumentCaptor.capture());
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
index c6771b2..a279d3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
@@ -18,7 +18,9 @@
 
 import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FACE_REENROLL_DIALOG;
 import static com.android.systemui.biometrics.BiometricNotificationBroadcastReceiver.ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
@@ -98,7 +100,7 @@
     public void setUp() {
         when(mFingerprintReEnrollNotificationOptional.orElse(any()))
                 .thenReturn(mFingerprintReEnrollNotification);
-        when(mFingerprintReEnrollNotification.isFingerprintReEnrollRequired(
+        when(mFingerprintReEnrollNotification.isFingerprintReEnrollRequested(
                 FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(true);
 
         mLooper = TestableLooper.get(this);
@@ -140,8 +142,10 @@
     }
 
     @Test
-    public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll() {
+    public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll_Optional() {
         when(mKeyguardStateController.isShowing()).thenReturn(false);
+        when(mFingerprintReEnrollNotification.isFingerprintReEnrollForced(
+                FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(false);
 
         mKeyguardUpdateMonitorCallback.onBiometricHelp(
                 FINGERPRINT_ACQUIRED_RE_ENROLL,
@@ -160,6 +164,35 @@
 
         assertThat(fingerprintNotification.contentIntent.getIntent().getAction())
                 .isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG);
+        assertThat(fingerprintNotification.contentIntent.getIntent().getBooleanExtra(
+                BiometricNotificationBroadcastReceiver.EXTRA_IS_REENROLL_FORCED, false)).isFalse();
+    }
+
+    @Test
+    public void testShowFingerprintReEnrollNotification_onAcquiredReEnroll_force() {
+        when(mKeyguardStateController.isShowing()).thenReturn(false);
+        when(mFingerprintReEnrollNotification.isFingerprintReEnrollForced(
+                FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(true);
+
+        mKeyguardUpdateMonitorCallback.onBiometricHelp(
+                FINGERPRINT_ACQUIRED_RE_ENROLL,
+                "Testing Fingerprint Re-enrollment" /* errString */,
+                BiometricSourceType.FINGERPRINT
+        );
+        mKeyguardStateControllerCallback.onKeyguardShowingChanged();
+
+        mLooper.moveTimeForward(SHOW_NOTIFICATION_DELAY_MS);
+        mLooper.processAllMessages();
+
+        verify(mNotificationManager).notifyAsUser(eq(TAG), eq(FINGERPRINT_NOTIFICATION_ID),
+                mNotificationArgumentCaptor.capture(), any());
+
+        Notification fingerprintNotification = mNotificationArgumentCaptor.getValue();
+
+        assertThat(fingerprintNotification.contentIntent.getIntent().getAction())
+                .isEqualTo(ACTION_SHOW_FINGERPRINT_REENROLL_DIALOG);
+        assertThat(fingerprintNotification.contentIntent.getIntent().getBooleanExtra(
+                BiometricNotificationBroadcastReceiver.EXTRA_IS_REENROLL_FORCED, false)).isTrue();
     }
     @Test
     public void testShowFaceReEnrollNotification_onErrorReEnroll() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
index 8fbeb6f..b3e845f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
@@ -26,18 +26,20 @@
 import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
 import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR
 import android.hardware.biometrics.BiometricSourceType
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo
+import android.hardware.biometrics.events.AuthenticationStartedInfo
+import android.hardware.biometrics.events.AuthenticationStoppedInfo
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -57,19 +59,18 @@
     @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
     @Mock private lateinit var biometricManager: BiometricManager
 
+    private val kosmos = testKosmos()
     private lateinit var underTest: BiometricStatusRepository
 
-    private val testScope = TestScope(StandardTestDispatcher())
-
     @Before
     fun setUp() {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        underTest = BiometricStatusRepositoryImpl(testScope.backgroundScope, biometricManager)
+        underTest =
+            BiometricStatusRepositoryImpl(kosmos.testScope.backgroundScope, biometricManager)
     }
 
     @Test
     fun updatesFingerprintAuthenticationReason_whenBiometricPromptAuthenticationStarted() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAuthenticationReason by
                 collectLastValue(underTest.fingerprintAuthenticationReason)
             runCurrent()
@@ -78,14 +79,17 @@
 
             assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            listener.onAuthenticationStarted(REASON_AUTH_BP)
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT, REASON_AUTH_BP)
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason)
                 .isEqualTo(AuthenticationReason.BiometricPromptAuthentication)
         }
 
     @Test
     fun updatesFingerprintAuthenticationReason_whenDeviceEntryAuthenticationStarted() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAuthenticationReason by
                 collectLastValue(underTest.fingerprintAuthenticationReason)
             runCurrent()
@@ -94,14 +98,20 @@
 
             assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            listener.onAuthenticationStarted(REASON_AUTH_KEYGUARD)
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_AUTH_KEYGUARD
+                    )
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason)
                 .isEqualTo(AuthenticationReason.DeviceEntryAuthentication)
         }
 
     @Test
     fun updatesFingerprintAuthenticationReason_whenOtherAuthenticationStarted() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAuthenticationReason by
                 collectLastValue(underTest.fingerprintAuthenticationReason)
             runCurrent()
@@ -110,14 +120,20 @@
 
             assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            listener.onAuthenticationStarted(REASON_AUTH_OTHER)
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_AUTH_OTHER
+                    )
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason)
                 .isEqualTo(AuthenticationReason.OtherAuthentication)
         }
 
     @Test
     fun updatesFingerprintAuthenticationReason_whenSettingsAuthenticationStarted() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAuthenticationReason by
                 collectLastValue(underTest.fingerprintAuthenticationReason)
             runCurrent()
@@ -126,14 +142,20 @@
 
             assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            listener.onAuthenticationStarted(REASON_AUTH_SETTINGS)
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_AUTH_SETTINGS
+                    )
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason)
                 .isEqualTo(AuthenticationReason.SettingsAuthentication(SettingsOperations.OTHER))
         }
 
     @Test
     fun updatesFingerprintAuthenticationReason_whenEnrollmentAuthenticationStarted() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAuthenticationReason by
                 collectLastValue(underTest.fingerprintAuthenticationReason)
             runCurrent()
@@ -142,7 +164,13 @@
 
             assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            listener.onAuthenticationStarted(REASON_ENROLL_FIND_SENSOR)
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_ENROLL_FIND_SENSOR
+                    )
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason)
                 .isEqualTo(
                     AuthenticationReason.SettingsAuthentication(
@@ -150,7 +178,13 @@
                     )
                 )
 
-            listener.onAuthenticationStarted(REASON_ENROLL_ENROLLING)
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_ENROLL_ENROLLING
+                    )
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason)
                 .isEqualTo(
                     AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_ENROLLING)
@@ -159,29 +193,38 @@
 
     @Test
     fun updatesFingerprintAuthenticationReason_whenAuthenticationStopped() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAuthenticationReason by
                 collectLastValue(underTest.fingerprintAuthenticationReason)
             runCurrent()
 
             val listener = biometricManager.captureListener()
 
-            listener.onAuthenticationStarted(REASON_AUTH_BP)
-            listener.onAuthenticationStopped()
+            listener.onAuthenticationStarted(
+                AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT, REASON_AUTH_BP)
+                    .build()
+            )
+            listener.onAuthenticationStopped(
+                AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT, REASON_AUTH_BP)
+                    .build()
+            )
             assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
         }
 
     @Test
     fun updatesFingerprintAcquiredStatusWhenBiometricPromptAuthenticationAcquired() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAcquiredStatus by collectLastValue(underTest.fingerprintAcquiredStatus)
             runCurrent()
 
             val listener = biometricManager.captureListener()
             listener.onAuthenticationAcquired(
-                BiometricSourceType.FINGERPRINT,
-                REASON_AUTH_BP,
-                BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START
+                AuthenticationAcquiredInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_AUTH_BP,
+                        BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START
+                    )
+                    .build()
             )
 
             assertThat(fingerprintAcquiredStatus)
@@ -192,6 +235,31 @@
                     )
                 )
         }
+
+    @Test
+    fun updatesFingerprintAcquiredStatusWhenDeviceEntryAuthenticationAcquired() =
+        kosmos.testScope.runTest {
+            val fingerprintAcquiredStatus by collectLastValue(underTest.fingerprintAcquiredStatus)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+            listener.onAuthenticationAcquired(
+                AuthenticationAcquiredInfo.Builder(
+                        BiometricSourceType.FINGERPRINT,
+                        REASON_AUTH_KEYGUARD,
+                        BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START
+                    )
+                    .build()
+            )
+
+            assertThat(fingerprintAcquiredStatus)
+                .isEqualTo(
+                    AcquiredFingerprintAuthenticationStatus(
+                        AuthenticationReason.DeviceEntryAuthentication,
+                        BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START
+                    )
+                )
+        }
 }
 
 private fun BiometricManager.captureListener() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
index 5c34fd9..4cff3e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
@@ -17,62 +17,67 @@
 package com.android.systemui.biometrics.domain.interactor
 
 import android.app.ActivityManager
-import android.app.ActivityTaskManager
 import android.content.ComponentName
 import android.hardware.biometrics.BiometricFingerprintConstants
 import androidx.test.filters.SmallTest
+import com.android.app.activityTaskManager
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
+import com.android.systemui.biometrics.data.repository.biometricStatusRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
 import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(JUnit4::class)
 class BiometricStatusInteractorImplTest : SysuiTestCase() {
-    @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
-    @Mock private lateinit var activityTaskManager: ActivityTaskManager
-
-    private lateinit var biometricStatusRepository: FakeBiometricStatusRepository
+    private val kosmos = testKosmos()
     private lateinit var underTest: BiometricStatusInteractorImpl
 
-    private val testScope = TestScope(StandardTestDispatcher())
-
     @Before
     fun setup() {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        biometricStatusRepository = FakeBiometricStatusRepository()
-        underTest = BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository)
+        underTest = kosmos.biometricStatusInteractor
     }
 
     @Test
-    fun updatesSfpsAuthenticationReason_whenBiometricPromptAuthenticationStarted() =
-        testScope.runTest {
+    fun doesNotUpdatesSfpsAuthenticationReason_whenUdfpsAuthenticationStarted() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsUdfps()
             val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
             runCurrent()
 
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.BiometricPromptAuthentication
+            )
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+        }
+
+    @Test
+    fun updatesSfpsAuthenticationReason_whenSfpsBiometricPromptAuthenticationStarted() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsSideFps()
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.BiometricPromptAuthentication
             )
             assertThat(sfpsAuthenticationReason)
@@ -80,58 +85,62 @@
         }
 
     @Test
-    fun doesNotUpdateSfpsAuthenticationReason_whenDeviceEntryAuthenticationStarted() =
-        testScope.runTest {
+    fun doesNotUpdateSfpsAuthenticationReason_whenSfpsDeviceEntryAuthenticationStarted() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsSideFps()
             val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
             runCurrent()
 
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.DeviceEntryAuthentication
             )
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
         }
 
     @Test
-    fun updatesSfpsAuthenticationReason_whenOtherAuthenticationStarted() =
-        testScope.runTest {
+    fun updatesSfpsAuthenticationReason_whenOtherSfpsAuthenticationStarted() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsSideFps()
             val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
             runCurrent()
 
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.OtherAuthentication
             )
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.OtherAuthentication)
         }
 
     @Test
-    fun doesNotUpdateSfpsAuthenticationReason_whenOtherSettingsAuthenticationStarted() =
-        testScope.runTest {
+    fun doesNotUpdateSfpsAuthenticationReason_whenOtherSfpsSettingsAuthenticationStarted() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsSideFps()
             val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
             runCurrent()
 
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            `when`(activityTaskManager.getTasks(Mockito.anyInt()))
+            `when`(kosmos.activityTaskManager.getTasks(Mockito.anyInt()))
                 .thenReturn(listOf(fpSettingsTask()))
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.SettingsAuthentication(SettingsOperations.OTHER)
             )
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
         }
 
     @Test
-    fun updatesSfpsAuthenticationReason_whenEnrollmentAuthenticationStarted() =
-        testScope.runTest {
+    fun updatesSfpsAuthenticationReason_whenSfpsEnrollmentStarted() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsSideFps()
             val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
             runCurrent()
 
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_FIND_SENSOR)
             )
             assertThat(sfpsAuthenticationReason)
@@ -141,7 +150,7 @@
                     )
                 )
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_ENROLLING)
             )
             assertThat(sfpsAuthenticationReason)
@@ -151,15 +160,16 @@
         }
 
     @Test
-    fun updatesFingerprintAuthenticationReason_whenAuthenticationStopped() =
-        testScope.runTest {
+    fun updatesFingerprintAuthenticationReason_whenSfpsAuthenticationStopped() =
+        kosmos.testScope.runTest {
+            kosmos.fingerprintPropertyRepository.supportsSideFps()
             val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
             runCurrent()
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.BiometricPromptAuthentication
             )
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
             assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
@@ -167,11 +177,11 @@
 
     @Test
     fun updatesFingerprintAcquiredStatusWhenBiometricPromptAuthenticationAcquired() =
-        testScope.runTest {
+        kosmos.testScope.runTest {
             val fingerprintAcquiredStatus by collectLastValue(underTest.fingerprintAcquiredStatus)
             runCurrent()
 
-            biometricStatusRepository.setFingerprintAcquiredStatus(
+            kosmos.biometricStatusRepository.setFingerprintAcquiredStatus(
                 AcquiredFingerprintAuthenticationStatus(
                     AuthenticationReason.BiometricPromptAuthentication,
                     BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt
index bf6caad..31bdde2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt
@@ -1,13 +1,11 @@
 package com.android.systemui.biometrics.domain.interactor
 
-import android.view.Display
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.display.data.repository.FakeDisplayRepository
-import com.android.systemui.display.data.repository.display
 import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
 import com.android.systemui.unfold.updates.FoldProvider
 import com.android.systemui.util.concurrency.FakeExecutor
@@ -101,14 +99,11 @@
     fun isDefaultDisplayOffChanges() =
         testScope.runTest {
             val isDefaultDisplayOff by collectLastValue(interactor.isDefaultDisplayOff)
-            runCurrent()
 
-            displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_OFF)))
-            displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY)
+            displayRepository.setDefaultDisplayOff(true)
             assertThat(isDefaultDisplayOff).isTrue()
 
-            displayRepository.emit(setOf(display(0, 0, Display.DEFAULT_DISPLAY, Display.STATE_ON)))
-            displayRepository.emitDisplayChangeEvent(Display.DEFAULT_DISPLAY)
+            displayRepository.setDefaultDisplayOff(false)
             assertThat(isDefaultDisplayOff).isFalse()
         }
 }
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
index c0e108e..5e7adb7 100644
--- 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
@@ -17,9 +17,9 @@
 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 androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
index 99c2c40..aff93bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
@@ -465,10 +465,34 @@
         nativeYOutsideSensor = 150f,
     )
 
-/* ROTATION_180 is not supported. It's treated the same as ROTATION_0. */
+/*
+ * ROTATION_180 map:
+ * _ _ _ _
+ * _ _ s _
+ * _ _ s _
+ * _ _ _ _
+ * _ O _ _
+ * _ _ _ _
+ *
+ * (_) empty space
+ * (S) sensor
+ * (O) touch outside of the sensor
+ */
+private val ROTATION_180_NATIVE_SENSOR_BOUNDS =
+    Rect(
+        200, /* left */
+        100, /* top */
+        300, /* right */
+        300, /* bottom */
+    )
 private val ROTATION_180_INPUTS =
-    ROTATION_0_INPUTS.copy(
+    OrientationBasedInputs(
         rotation = Surface.ROTATION_180,
+        nativeOrientation = (ORIENTATION - Math.PI.toFloat() / 2),
+        nativeXWithinSensor = ROTATION_180_NATIVE_SENSOR_BOUNDS.exactCenterX(),
+        nativeYWithinSensor = ROTATION_180_NATIVE_SENSOR_BOUNDS.exactCenterY(),
+        nativeXOutsideSensor = 150f,
+        nativeYOutsideSensor = 450f,
     )
 
 /*
@@ -639,33 +663,6 @@
     }
 }
 
-private fun genTestCasesForUnsupportedAction(
-    motionEventAction: Int
-): List<SinglePointerTouchProcessorTest.TestCase> {
-    val isGoodOverlap = true
-    val previousPointerOnSensorIds = listOf(INVALID_POINTER_ID, POINTER_ID_1)
-    return previousPointerOnSensorIds.map { previousPointerOnSensorId ->
-        val overlayParams = ROTATION_0_INPUTS.toOverlayParams(scaleFactor = 1f)
-        val nativeX = ROTATION_0_INPUTS.getNativeX(isGoodOverlap)
-        val nativeY = ROTATION_0_INPUTS.getNativeY(isGoodOverlap)
-        val event =
-            MOTION_EVENT.copy(
-                action = motionEventAction,
-                x = nativeX,
-                y = nativeY,
-                minor = NATIVE_MINOR,
-                major = NATIVE_MAJOR,
-            )
-        SinglePointerTouchProcessorTest.TestCase(
-            event = event,
-            currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = isGoodOverlap)),
-            previousPointerOnSensorId = previousPointerOnSensorId,
-            overlayParams = overlayParams,
-            expected = TouchProcessorResult.Failure(),
-        )
-    }
-}
-
 private fun obtainMotionEvent(
     action: Int,
     pointerId: Int,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
index 30c5e6e..01d9df8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
@@ -78,8 +78,6 @@
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.phone.dozeServiceHost
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.testKosmos
@@ -176,8 +174,6 @@
 
     @Before
     fun setup() {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-
         allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread
 
         mContext = spy(mContext)
@@ -204,7 +200,11 @@
             )
 
         biometricStatusInteractor =
-            BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository)
+            BiometricStatusInteractorImpl(
+                activityTaskManager,
+                biometricStatusRepository,
+                fingerprintPropertyRepository
+            )
 
         displayStateInteractor =
             DisplayStateInteractorImpl(
@@ -239,7 +239,6 @@
                 testScope.backgroundScope,
                 mContext,
                 deviceEntryFingerprintAuthRepository,
-                kosmos.fakeSceneContainerFlags,
                 kosmos.sceneInteractor,
                 primaryBouncerInteractor,
                 alternateBouncerInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 5b0df5d..a732418 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -16,12 +16,14 @@
 
 package com.android.systemui.biometrics.ui.viewmodel
 
+import android.app.ActivityTaskManager
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
 import android.content.res.Configuration
 import android.graphics.Bitmap
 import android.graphics.Point
 import android.graphics.drawable.BitmapDrawable
+import android.hardware.biometrics.BiometricFingerprintConstants
 import android.hardware.biometrics.Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT
 import android.hardware.biometrics.PromptContentItemBulletedText
 import android.hardware.biometrics.PromptContentView
@@ -40,9 +42,12 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.biometrics.UdfpsUtils
+import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
 import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
 import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
 import com.android.systemui.biometrics.data.repository.FakePromptRepository
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
@@ -51,6 +56,7 @@
 import com.android.systemui.biometrics.extractAuthenticatorTypes
 import com.android.systemui.biometrics.faceSensorPropertiesInternal
 import com.android.systemui.biometrics.fingerprintSensorPropertiesInternal
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.BiometricModalities
 import com.android.systemui.biometrics.shared.model.BiometricModality
 import com.android.systemui.biometrics.shared.model.DisplayRotation
@@ -59,6 +65,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
 import com.android.systemui.res.R
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.concurrency.FakeExecutor
@@ -102,6 +109,7 @@
     @Mock private lateinit var packageManager: PackageManager
     @Mock private lateinit var applicationInfoWithIcon: ApplicationInfo
     @Mock private lateinit var applicationInfoNoIcon: ApplicationInfo
+    @Mock private lateinit var activityTaskManager: ActivityTaskManager
 
     private val fakeExecutor = FakeExecutor(FakeSystemClock())
     private val testScope = TestScope()
@@ -115,9 +123,11 @@
     private lateinit var fingerprintRepository: FakeFingerprintPropertyRepository
     private lateinit var promptRepository: FakePromptRepository
     private lateinit var displayStateRepository: FakeDisplayStateRepository
+    private lateinit var biometricStatusRepository: FakeBiometricStatusRepository
     private lateinit var displayRepository: FakeDisplayRepository
     private lateinit var displayStateInteractor: DisplayStateInteractor
     private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
+    private lateinit var biometricStatusInteractor: BiometricStatusInteractor
 
     private lateinit var selector: PromptSelectorInteractor
     private lateinit var viewModel: PromptViewModel
@@ -157,6 +167,10 @@
                 selectedUserInteractor,
                 testScope.backgroundScope
             )
+        biometricStatusRepository = FakeBiometricStatusRepository()
+        biometricStatusInteractor =
+            BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository,
+                fingerprintRepository)
         selector =
             PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils)
         selector.resetPrompt()
@@ -178,6 +192,7 @@
                 selector,
                 mContext,
                 udfpsOverlayInteractor,
+                biometricStatusInteractor,
                 udfpsUtils
             )
         iconViewModel = viewModel.iconViewModel
@@ -1053,8 +1068,7 @@
     fun auto_confirm_authentication_when_finger_down() = runGenericTest {
         val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
 
-        // No icon button when face only, can't confirm before auth
-        if (!testCase.isFaceOnly) {
+        if (testCase.isCoex) {
             viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_DOWN))
         }
         viewModel.showAuthenticated(testCase.authenticatedModality, 0)
@@ -1069,14 +1083,18 @@
         assertThat(canTryAgain).isFalse()
         assertThat(authenticated?.isAuthenticated).isTrue()
 
-        if (testCase.isFaceOnly && expectConfirmation) {
-            assertThat(size).isEqualTo(PromptSize.MEDIUM)
-            assertButtonsVisible(
-                cancel = true,
-                confirm = true,
-            )
+        if (expectConfirmation) {
+            if (testCase.isFaceOnly) {
+                assertThat(size).isEqualTo(PromptSize.MEDIUM)
+                assertButtonsVisible(
+                    cancel = true,
+                    confirm = true,
+                )
 
-            viewModel.confirmAuthenticated()
+                viewModel.confirmAuthenticated()
+            } else if (testCase.isCoex) {
+                assertThat(authenticated?.isAuthenticatedAndConfirmed).isTrue()
+            }
             assertThat(message).isEqualTo(PromptMessage.Empty)
             assertButtonsVisible()
         }
@@ -1086,8 +1104,7 @@
     fun cannot_auto_confirm_authentication_when_finger_up() = runGenericTest {
         val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
 
-        // No icon button when face only, can't confirm before auth
-        if (!testCase.isFaceOnly) {
+        if (testCase.isCoex) {
             viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_DOWN))
             viewModel.onOverlayTouch(obtainMotionEvent(MotionEvent.ACTION_UP))
         }
@@ -1413,6 +1430,12 @@
             packageName = packageName,
         )
 
+        biometricStatusRepository.setFingerprintAcquiredStatus(
+            AcquiredFingerprintAuthenticationStatus(
+                AuthenticationReason.BiometricPromptAuthentication,
+                BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN
+            )
+        )
         // put the view model in the initial authenticating state, unless explicitly skipped
         val startMode =
             when {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
index 1acb203..05ec64e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
@@ -33,6 +33,7 @@
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.settingslib.Utils
+import com.android.systemui.Flags.FLAG_CONSTRAINT_BP
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
 import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
@@ -76,8 +77,6 @@
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.phone.dozeServiceHost
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.testKosmos
@@ -176,8 +175,6 @@
 
     @Before
     fun setup() {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-
         mContext = spy(mContext)
 
         val resources = mContext.resources
@@ -235,7 +232,6 @@
                 testScope.backgroundScope,
                 mContext,
                 deviceEntryFingerprintAuthRepository,
-                kosmos.fakeSceneContainerFlags,
                 kosmos.sceneInteractor,
                 primaryBouncerInteractor,
                 alternateBouncerInteractor,
@@ -351,6 +347,7 @@
     @Test
     fun updatesOverlayViewParams_onDisplayRotationChange_xAlignedSensor() {
         testScope.runTest {
+            mSetFlagsRule.disableFlags(FLAG_CONSTRAINT_BP)
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
@@ -392,6 +389,7 @@
     @Test
     fun updatesOverlayViewParams_onDisplayRotationChange_yAlignedSensor() {
         testScope.runTest {
+            mSetFlagsRule.disableFlags(FLAG_CONSTRAINT_BP)
             setupTestConfiguration(
                 DeviceConfig.Y_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt
new file mode 100644
index 0000000..8a1a082
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.res.R
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
+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
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class AudioSharingInteractorTest : SysuiTestCase() {
+    private val testDispatcher = UnconfinedTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+    private val bluetoothState = MutableStateFlow(false)
+    private val deviceItemUpdate: MutableSharedFlow<List<DeviceItem>> = MutableSharedFlow()
+    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+    @Mock private lateinit var bluetoothStateInteractor: BluetoothStateInteractor
+    @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor
+    @Mock private lateinit var deviceItem: DeviceItem
+    private lateinit var mockitoSession: StaticMockitoSession
+    private lateinit var audioSharingInteractor: AudioSharingInteractor
+
+    @Before
+    fun setUp() {
+        mockitoSession =
+            mockitoSession().initMocks(this).mockStatic(BluetoothUtils::class.java).startMocking()
+        whenever(bluetoothStateInteractor.bluetoothStateUpdate).thenReturn(bluetoothState)
+        whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(deviceItemUpdate)
+        audioSharingInteractor =
+            AudioSharingInteractor(
+                localBluetoothManager,
+                bluetoothStateInteractor,
+                deviceItemInteractor,
+                testScope.backgroundScope,
+                testDispatcher,
+            )
+    }
+
+    @After
+    fun tearDown() {
+        mockitoSession.finishMocking()
+    }
+
+    @Test
+    fun testButtonStateUpdate_bluetoothOff_returnGone() {
+        testScope.runTest {
+            val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate)
+
+            assertThat(actual).isEqualTo(AudioSharingButtonState.Gone)
+        }
+    }
+
+    @Test
+    fun testButtonStateUpdate_noDevice_returnGone() {
+        testScope.runTest {
+            val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate)
+            bluetoothState.value = true
+            runCurrent()
+
+            assertThat(actual).isEqualTo(AudioSharingButtonState.Gone)
+        }
+    }
+
+    @Test
+    fun testButtonStateUpdate_isBroadcasting_returnSharingAudio() {
+        testScope.runTest {
+            whenever(BluetoothUtils.isBroadcasting(localBluetoothManager)).thenReturn(true)
+
+            val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate)
+            bluetoothState.value = true
+            deviceItemUpdate.emit(listOf())
+            runCurrent()
+
+            assertThat(actual)
+                .isEqualTo(
+                    AudioSharingButtonState.Visible(
+                        R.string.quick_settings_bluetooth_audio_sharing_button_sharing
+                    )
+                )
+        }
+    }
+
+    @Test
+    fun testButtonStateUpdate_hasSource_returnGone() {
+        testScope.runTest {
+            whenever(BluetoothUtils.isBroadcasting(localBluetoothManager)).thenReturn(false)
+            whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice)
+            whenever(
+                    BluetoothUtils.hasConnectedBroadcastSource(
+                        cachedBluetoothDevice,
+                        localBluetoothManager
+                    )
+                )
+                .thenReturn(true)
+
+            val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate)
+            bluetoothState.value = true
+            deviceItemUpdate.emit(listOf(deviceItem))
+            runCurrent()
+
+            assertThat(actual).isEqualTo(AudioSharingButtonState.Gone)
+        }
+    }
+
+    @Test
+    fun testButtonStateUpdate_hasActiveDevice_returnAudioSharing() {
+        testScope.runTest {
+            whenever(BluetoothUtils.isBroadcasting(localBluetoothManager)).thenReturn(false)
+            whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice)
+            whenever(
+                    BluetoothUtils.hasConnectedBroadcastSource(
+                        cachedBluetoothDevice,
+                        localBluetoothManager
+                    )
+                )
+                .thenReturn(false)
+            whenever(BluetoothUtils.isActiveLeAudioDevice(cachedBluetoothDevice)).thenReturn(true)
+
+            val actual by collectLastValue(audioSharingInteractor.audioSharingButtonStateUpdate)
+            bluetoothState.value = true
+            deviceItemUpdate.emit(listOf(deviceItem))
+            runCurrent()
+
+            assertThat(actual)
+                .isEqualTo(
+                    AudioSharingButtonState.Visible(
+                        R.string.quick_settings_bluetooth_audio_sharing_button
+                    )
+                )
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnInteractorTest.kt
new file mode 100644
index 0000000..4949716
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnInteractorTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import kotlin.test.Test
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BluetoothAutoOnInteractorTest : SysuiTestCase() {
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+    private val bluetoothAdapter =
+        mock<BluetoothAdapter> {
+            var autoOn = false
+            whenever(isAutoOnEnabled).thenAnswer { autoOn }
+
+            whenever(setAutoOnEnabled(anyBoolean())).thenAnswer { invocation ->
+                autoOn = invocation.getArgument(0) as Boolean
+                autoOn
+            }
+        }
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+    private lateinit var bluetoothAutoOnInteractor: BluetoothAutoOnInteractor
+
+    @Before
+    fun setUp() {
+        bluetoothAutoOnInteractor =
+            BluetoothAutoOnInteractor(
+                BluetoothAutoOnRepository(
+                    localBluetoothManager,
+                    bluetoothAdapter,
+                    testScope.backgroundScope,
+                    testDispatcher,
+                )
+            )
+    }
+
+    @Test
+    fun testSetEnabled_bluetoothAutoOnUnsupported_doNothing() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(false)
+
+            bluetoothAutoOnInteractor.setEnabled(true)
+            runCurrent()
+
+            assertFalse(bluetoothAdapter.isAutoOnEnabled)
+        }
+    }
+
+    @Test
+    fun testSetEnabled_bluetoothAutoOnSupported_setNewValue() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(true)
+
+            bluetoothAutoOnInteractor.setEnabled(true)
+            runCurrent()
+
+            assertTrue(bluetoothAdapter.isAutoOnEnabled)
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnRepositoryTest.kt
new file mode 100644
index 0000000..85e2a8d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothAutoOnRepositoryTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.BluetoothEventManager
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.whenever
+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.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BluetoothAutoOnRepositoryTest : SysuiTestCase() {
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+    @Mock private lateinit var bluetoothAdapter: BluetoothAdapter
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+    @Mock private lateinit var eventManager: BluetoothEventManager
+
+    private lateinit var bluetoothAutoOnRepository: BluetoothAutoOnRepository
+
+    @Before
+    fun setUp() {
+        whenever(localBluetoothManager.eventManager).thenReturn(eventManager)
+        bluetoothAutoOnRepository =
+            BluetoothAutoOnRepository(
+                localBluetoothManager,
+                bluetoothAdapter,
+                testScope.backgroundScope,
+                testDispatcher,
+            )
+    }
+
+    @Test
+    fun testIsAutoOn_returnFalse() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnEnabled).thenReturn(false)
+            val actualValue by collectLastValue(bluetoothAutoOnRepository.isAutoOn)
+
+            runCurrent()
+
+            assertThat(actualValue).isEqualTo(false)
+        }
+    }
+
+    @Test
+    fun testIsAutoOn_returnTrue() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnEnabled).thenReturn(true)
+            val actualValue by collectLastValue(bluetoothAutoOnRepository.isAutoOn)
+
+            runCurrent()
+
+            assertThat(actualValue).isEqualTo(true)
+        }
+    }
+
+    @Test
+    fun testIsAutoOnSupported_returnTrue() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(true)
+            val actualValue = bluetoothAutoOnRepository.isAutoOnSupported()
+
+            runCurrent()
+
+            assertThat(actualValue).isEqualTo(true)
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt
new file mode 100644
index 0000000..6fe7d86
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class BluetoothStateInteractorTest : SysuiTestCase() {
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    private lateinit var bluetoothStateInteractor: BluetoothStateInteractor
+
+    @Mock private lateinit var bluetoothAdapter: LocalBluetoothAdapter
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+    @Mock private lateinit var logger: BluetoothTileDialogLogger
+
+    @Before
+    fun setUp() {
+        bluetoothStateInteractor =
+            BluetoothStateInteractor(
+                localBluetoothManager,
+                logger,
+                testScope.backgroundScope,
+                testDispatcher
+            )
+        `when`(localBluetoothManager.bluetoothAdapter).thenReturn(bluetoothAdapter)
+    }
+
+    @Test
+    fun testGet_isBluetoothEnabled() {
+        testScope.runTest {
+            `when`(bluetoothAdapter.isEnabled).thenReturn(true)
+
+            assertThat(bluetoothStateInteractor.isBluetoothEnabled()).isTrue()
+        }
+    }
+
+    @Test
+    fun testGet_isBluetoothDisabled() {
+        testScope.runTest {
+            `when`(bluetoothAdapter.isEnabled).thenReturn(false)
+
+            assertThat(bluetoothStateInteractor.isBluetoothEnabled()).isFalse()
+        }
+    }
+
+    @Test
+    fun testSet_bluetoothEnabled() {
+        testScope.runTest {
+            `when`(bluetoothAdapter.isEnabled).thenReturn(false)
+
+            bluetoothStateInteractor.setBluetoothEnabled(true)
+            verify(bluetoothAdapter).enable()
+            verify(logger)
+                .logBluetoothState(BluetoothStateStage.BLUETOOTH_STATE_VALUE_SET, true.toString())
+        }
+    }
+
+    @Test
+    fun testSet_bluetoothNoChange() {
+        testScope.runTest {
+            `when`(bluetoothAdapter.isEnabled).thenReturn(false)
+
+            bluetoothStateInteractor.setBluetoothEnabled(false)
+            verify(bluetoothAdapter, never()).enable()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt
new file mode 100644
index 0000000..62c98b0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.graphics.drawable.Drawable
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.model.SysUiState
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.phone.SystemUIDialogManager
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class BluetoothTileDialogDelegateTest : SysuiTestCase() {
+    companion object {
+        const val DEVICE_NAME = "device"
+        const val DEVICE_CONNECTION_SUMMARY = "active"
+        const val ENABLED = true
+        const val CONTENT_HEIGHT = WRAP_CONTENT
+    }
+
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
+
+    @Mock private lateinit var bluetoothTileDialogCallback: BluetoothTileDialogCallback
+
+    @Mock private lateinit var drawable: Drawable
+
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+
+    @Mock private lateinit var logger: BluetoothTileDialogLogger
+
+    private val uiProperties =
+        BluetoothTileDialogViewModel.UiProperties.build(
+            isBluetoothEnabled = ENABLED,
+            isAutoOnToggleFeatureAvailable = ENABLED
+        )
+    @Mock private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
+    @Mock private lateinit var dialogManager: SystemUIDialogManager
+    @Mock private lateinit var sysuiState: SysUiState
+    @Mock private lateinit var dialogTransitionAnimator: DialogTransitionAnimator
+
+    private val fakeSystemClock = FakeSystemClock()
+
+    private lateinit var scheduler: TestCoroutineScheduler
+    private lateinit var dispatcher: CoroutineDispatcher
+    private lateinit var testScope: TestScope
+    private lateinit var icon: Pair<Drawable, String>
+    private lateinit var mBluetoothTileDialogDelegate: BluetoothTileDialogDelegate
+    private lateinit var deviceItem: DeviceItem
+
+    @Before
+    fun setUp() {
+        scheduler = TestCoroutineScheduler()
+        dispatcher = UnconfinedTestDispatcher(scheduler)
+        testScope = TestScope(dispatcher)
+
+        whenever(sysuiState.setFlag(anyInt(), anyBoolean())).thenReturn(sysuiState)
+
+        mBluetoothTileDialogDelegate =
+            BluetoothTileDialogDelegate(
+                uiProperties,
+                CONTENT_HEIGHT,
+                bluetoothTileDialogCallback,
+                {},
+                dispatcher,
+                fakeSystemClock,
+                uiEventLogger,
+                logger,
+                sysuiDialogFactory
+            )
+
+        whenever(sysuiDialogFactory.create(any(SystemUIDialog.Delegate::class.java))).thenAnswer {
+            SystemUIDialog(
+                mContext,
+                0,
+                SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
+                dialogManager,
+                sysuiState,
+                fakeBroadcastDispatcher,
+                dialogTransitionAnimator,
+                it.getArgument(0)
+            )
+        }
+
+        icon = Pair(drawable, DEVICE_NAME)
+        deviceItem =
+            DeviceItem(
+                type = DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
+                cachedBluetoothDevice = cachedBluetoothDevice,
+                deviceName = DEVICE_NAME,
+                connectionSummary = DEVICE_CONNECTION_SUMMARY,
+                iconWithDescription = icon,
+                background = null
+            )
+        `when`(cachedBluetoothDevice.isBusy).thenReturn(false)
+    }
+
+    @Test
+    fun testShowDialog_createRecyclerViewWithAdapter() {
+        val dialog = mBluetoothTileDialogDelegate.createDialog()
+        dialog.show()
+
+        val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
+
+        assertThat(recyclerView).isNotNull()
+        assertThat(recyclerView.visibility).isEqualTo(VISIBLE)
+        assertThat(recyclerView.adapter).isNotNull()
+        assertThat(recyclerView.layoutManager is LinearLayoutManager).isTrue()
+        dialog.dismiss()
+    }
+
+    @Test
+    fun testShowDialog_displayBluetoothDevice() {
+        testScope.runTest {
+            val dialog = mBluetoothTileDialogDelegate.createDialog()
+            dialog.show()
+            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
+            mBluetoothTileDialogDelegate.onDeviceItemUpdated(
+                dialog,
+                listOf(deviceItem),
+                showSeeAll = false,
+                showPairNewDevice = false
+            )
+
+            val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
+            val adapter = recyclerView?.adapter as BluetoothTileDialogDelegate.Adapter
+            assertThat(adapter.itemCount).isEqualTo(1)
+            assertThat(adapter.getItem(0).deviceName).isEqualTo(DEVICE_NAME)
+            assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
+            assertThat(adapter.getItem(0).iconWithDescription).isEqualTo(icon)
+            dialog.dismiss()
+        }
+    }
+
+    @Test
+    fun testDeviceItemViewHolder_cachedDeviceNotBusy() {
+        deviceItem.isEnabled = true
+
+        val view =
+            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
+        val viewHolder =
+            mBluetoothTileDialogDelegate
+                .Adapter(bluetoothTileDialogCallback)
+                .DeviceItemViewHolder(view)
+        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
+        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
+
+        assertThat(container).isNotNull()
+        assertThat(container.isEnabled).isTrue()
+        assertThat(container.hasOnClickListeners()).isTrue()
+    }
+
+    @Test
+    fun testDeviceItemViewHolder_cachedDeviceBusy() {
+        deviceItem.isEnabled = false
+
+        val view =
+            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
+        val viewHolder =
+            BluetoothTileDialogDelegate(
+                    uiProperties,
+                    CONTENT_HEIGHT,
+                    bluetoothTileDialogCallback,
+                    {},
+                    dispatcher,
+                    fakeSystemClock,
+                    uiEventLogger,
+                    logger,
+                    sysuiDialogFactory,
+                )
+                .Adapter(bluetoothTileDialogCallback)
+                .DeviceItemViewHolder(view)
+        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
+        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
+
+        assertThat(container).isNotNull()
+        assertThat(container.isEnabled).isFalse()
+        assertThat(container.hasOnClickListeners()).isTrue()
+    }
+
+    @Test
+    fun testOnDeviceUpdated_hideSeeAll_showPairNew() {
+        testScope.runTest {
+            val dialog = mBluetoothTileDialogDelegate.createDialog()
+            dialog.show()
+            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
+            mBluetoothTileDialogDelegate.onDeviceItemUpdated(
+                dialog,
+                listOf(deviceItem),
+                showSeeAll = false,
+                showPairNewDevice = true
+            )
+
+            val seeAllButton = dialog.requireViewById<View>(R.id.see_all_button)
+            val pairNewButton = dialog.requireViewById<View>(R.id.pair_new_device_button)
+            val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
+            val adapter = recyclerView?.adapter as BluetoothTileDialogDelegate.Adapter
+            val scrollViewContent = dialog.requireViewById<View>(R.id.scroll_view)
+
+            assertThat(seeAllButton).isNotNull()
+            assertThat(seeAllButton.visibility).isEqualTo(GONE)
+            assertThat(pairNewButton).isNotNull()
+            assertThat(pairNewButton.visibility).isEqualTo(VISIBLE)
+            assertThat(adapter.itemCount).isEqualTo(1)
+            assertThat(scrollViewContent.layoutParams.height).isEqualTo(WRAP_CONTENT)
+            dialog.dismiss()
+        }
+    }
+
+    @Test
+    fun testShowDialog_cachedHeightLargerThanMinHeight_displayFromCachedHeight() {
+        testScope.runTest {
+            val cachedHeight = Int.MAX_VALUE
+            val dialog =
+                BluetoothTileDialogDelegate(
+                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
+                        cachedHeight,
+                        bluetoothTileDialogCallback,
+                        {},
+                        dispatcher,
+                        fakeSystemClock,
+                        uiEventLogger,
+                        logger,
+                        sysuiDialogFactory,
+                    )
+                    .createDialog()
+            dialog.show()
+            assertThat(dialog.requireViewById<View>(R.id.scroll_view).layoutParams.height)
+                .isEqualTo(cachedHeight)
+            dialog.dismiss()
+        }
+    }
+
+    @Test
+    fun testShowDialog_cachedHeightLessThanMinHeight_displayFromUiProperties() {
+        testScope.runTest {
+            val dialog =
+                BluetoothTileDialogDelegate(
+                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
+                        MATCH_PARENT,
+                        bluetoothTileDialogCallback,
+                        {},
+                        dispatcher,
+                        fakeSystemClock,
+                        uiEventLogger,
+                        logger,
+                        sysuiDialogFactory,
+                    )
+                    .createDialog()
+            dialog.show()
+            assertThat(dialog.requireViewById<View>(R.id.scroll_view).layoutParams.height)
+                .isGreaterThan(MATCH_PARENT)
+            dialog.dismiss()
+        }
+    }
+
+    @Test
+    fun testShowDialog_bluetoothEnabled_autoOnToggleGone() {
+        testScope.runTest {
+            val dialog =
+                BluetoothTileDialogDelegate(
+                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
+                        MATCH_PARENT,
+                        bluetoothTileDialogCallback,
+                        {},
+                        dispatcher,
+                        fakeSystemClock,
+                        uiEventLogger,
+                        logger,
+                        sysuiDialogFactory,
+                    )
+                    .createDialog()
+            dialog.show()
+            assertThat(
+                    dialog.requireViewById<View>(R.id.bluetooth_auto_on_toggle_layout).visibility
+                )
+                .isEqualTo(GONE)
+            dialog.dismiss()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepositoryTest.kt
new file mode 100644
index 0000000..4aa6209
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepositoryTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class BluetoothTileDialogRepositoryTest : SysuiTestCase() {
+
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+
+    @Mock private lateinit var bluetoothAdapter: BluetoothAdapter
+
+    @Mock private lateinit var cachedDeviceManager: CachedBluetoothDeviceManager
+
+    @Mock private lateinit var cachedDevicesCopy: Collection<CachedBluetoothDevice>
+
+    private lateinit var repository: BluetoothTileDialogRepository
+
+    @Before
+    fun setUp() {
+        `when`(localBluetoothManager.cachedDeviceManager).thenReturn(cachedDeviceManager)
+        `when`(cachedDeviceManager.cachedDevicesCopy).thenReturn(cachedDevicesCopy)
+
+        repository = BluetoothTileDialogRepository(localBluetoothManager, bluetoothAdapter)
+    }
+
+    @Test
+    fun testCachedDevices_bluetoothOff_emptyList() {
+        `when`(bluetoothAdapter.isEnabled).thenReturn(false)
+
+        val result = repository.cachedDevices
+
+        assertThat(result).isEmpty()
+    }
+
+    @Test
+    fun testCachedDevices_bluetoothOn_returnDevice() {
+        `when`(bluetoothAdapter.isEnabled).thenReturn(true)
+
+        val result = repository.cachedDevices
+
+        assertThat(result).isEqualTo(cachedDevicesCopy)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
new file mode 100644
index 0000000..b05d959
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.widget.LinearLayout
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.settingslib.flags.Flags
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.kotlin.getMutableStateFlow
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class BluetoothTileDialogViewModelTest : SysuiTestCase() {
+
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+    private val fakeSystemClock = FakeSystemClock()
+    private val backgroundExecutor = FakeExecutor(fakeSystemClock)
+
+    private lateinit var bluetoothTileDialogViewModel: BluetoothTileDialogViewModel
+
+    @Mock private lateinit var bluetoothStateInteractor: BluetoothStateInteractor
+
+    @Mock private lateinit var audioSharingInteractor: AudioSharingInteractor
+
+    @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor
+
+    @Mock private lateinit var activityStarter: ActivityStarter
+
+    @Mock private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator
+
+    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
+
+    @Mock private lateinit var deviceItem: DeviceItem
+
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+
+    @Mock private lateinit var bluetoothAdapter: BluetoothAdapter
+
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+
+    @Mock private lateinit var bluetoothTileDialogLogger: BluetoothTileDialogLogger
+
+    @Mock
+    private lateinit var mBluetoothTileDialogDelegateDelegateFactory:
+        BluetoothTileDialogDelegate.Factory
+
+    @Mock private lateinit var bluetoothTileDialogDelegate: BluetoothTileDialogDelegate
+
+    @Mock private lateinit var sysuiDialog: SystemUIDialog
+
+    private val sharedPreferences = FakeSharedPreferences()
+
+    private lateinit var scheduler: TestCoroutineScheduler
+    private lateinit var dispatcher: CoroutineDispatcher
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setUp() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE)
+        scheduler = TestCoroutineScheduler()
+        dispatcher = UnconfinedTestDispatcher(scheduler)
+        testScope = TestScope(dispatcher)
+        bluetoothTileDialogViewModel =
+            BluetoothTileDialogViewModel(
+                deviceItemInteractor,
+                BluetoothStateInteractor(
+                    localBluetoothManager,
+                    bluetoothTileDialogLogger,
+                    testScope.backgroundScope,
+                    dispatcher
+                ),
+                // TODO(b/316822488): Create FakeBluetoothAutoOnInteractor.
+                BluetoothAutoOnInteractor(
+                    BluetoothAutoOnRepository(
+                        localBluetoothManager,
+                        bluetoothAdapter,
+                        testScope.backgroundScope,
+                        dispatcher
+                    )
+                ),
+                audioSharingInteractor,
+                mDialogTransitionAnimator,
+                activityStarter,
+                uiEventLogger,
+                testScope.backgroundScope,
+                dispatcher,
+                dispatcher,
+                sharedPreferences,
+                mBluetoothTileDialogDelegateDelegateFactory
+            )
+        whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
+        whenever(deviceItemInteractor.deviceItemUpdateRequest)
+            .thenReturn(MutableStateFlow(Unit).asStateFlow())
+        whenever(mBluetoothTileDialogDelegateDelegateFactory.create(any(), anyInt(), any(), any()))
+            .thenReturn(bluetoothTileDialogDelegate)
+        whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog)
+        whenever(sysuiDialog.context).thenReturn(mContext)
+        whenever(bluetoothTileDialogDelegate.bluetoothStateToggle)
+            .thenReturn(getMutableStateFlow(false))
+        whenever(bluetoothTileDialogDelegate.deviceItemClick)
+            .thenReturn(getMutableStateFlow(deviceItem))
+        whenever(bluetoothTileDialogDelegate.contentHeight).thenReturn(getMutableStateFlow(0))
+        whenever(bluetoothTileDialogDelegate.bluetoothAutoOnToggle)
+            .thenReturn(getMutableStateFlow(false))
+        whenever(audioSharingInteractor.audioSharingButtonStateUpdate)
+            .thenReturn(getMutableStateFlow(AudioSharingButtonState.Gone))
+    }
+
+    @Test
+    fun testShowDialog_noAnimation() {
+        testScope.runTest {
+            bluetoothTileDialogViewModel.showDialog(null)
+
+            verify(mDialogTransitionAnimator, never()).showFromView(any(), any(), any(), any())
+        }
+    }
+
+    @Test
+    fun testShowDialog_animated() {
+        testScope.runTest {
+            bluetoothTileDialogViewModel.showDialog(LinearLayout(mContext))
+
+            verify(mDialogTransitionAnimator).showFromView(any(), any(), nullable(), anyBoolean())
+        }
+    }
+
+    @Test
+    fun testShowDialog_animated_callInBackgroundThread() {
+        testScope.runTest {
+            backgroundExecutor.execute {
+                bluetoothTileDialogViewModel.showDialog(LinearLayout(mContext))
+
+                verify(mDialogTransitionAnimator)
+                    .showFromView(any(), any(), nullable(), anyBoolean())
+            }
+        }
+    }
+
+    @Test
+    fun testShowDialog_fetchDeviceItem() {
+        testScope.runTest {
+            bluetoothTileDialogViewModel.showDialog(null)
+
+            verify(deviceItemInteractor).deviceItemUpdate
+        }
+    }
+
+    @Test
+    fun testStartSettingsActivity_activityLaunched_dialogDismissed() {
+        testScope.runTest {
+            whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice)
+            bluetoothTileDialogViewModel.showDialog(null)
+
+            val clickedView = View(context)
+            bluetoothTileDialogViewModel.onPairNewDeviceClicked(clickedView)
+
+            verify(uiEventLogger).log(BluetoothTileDialogUiEvent.PAIR_NEW_DEVICE_CLICKED)
+            verify(activityStarter).postStartActivityDismissingKeyguard(any(), anyInt(), nullable())
+        }
+    }
+
+    @Test
+    fun testBuildUiProperties_bluetoothOn_shouldHideAutoOn() {
+        testScope.runTest {
+            val actual =
+                BluetoothTileDialogViewModel.UiProperties.build(
+                    isBluetoothEnabled = true,
+                    isAutoOnToggleFeatureAvailable = true
+                )
+            assertThat(actual.autoOnToggleVisibility).isEqualTo(GONE)
+        }
+    }
+
+    @Test
+    fun testBuildUiProperties_bluetoothOff_shouldShowAutoOn() {
+        testScope.runTest {
+            val actual =
+                BluetoothTileDialogViewModel.UiProperties.build(
+                    isBluetoothEnabled = false,
+                    isAutoOnToggleFeatureAvailable = true
+                )
+            assertThat(actual.autoOnToggleVisibility).isEqualTo(VISIBLE)
+        }
+    }
+
+    @Test
+    fun testBuildUiProperties_bluetoothOff_autoOnFeatureUnavailable_shouldHideAutoOn() {
+        testScope.runTest {
+            val actual =
+                BluetoothTileDialogViewModel.UiProperties.build(
+                    isBluetoothEnabled = false,
+                    isAutoOnToggleFeatureAvailable = false
+                )
+            assertThat(actual.autoOnToggleVisibility).isEqualTo(GONE)
+        }
+    }
+
+    @Test
+    fun testIsAutoOnToggleFeatureAvailable_returnTrue() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(true)
+
+            val actual = bluetoothTileDialogViewModel.isAutoOnToggleFeatureAvailable()
+            assertThat(actual).isTrue()
+        }
+    }
+
+    @Test
+    fun testIsAutoOnToggleFeatureAvailable_returnFalse() {
+        testScope.runTest {
+            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(false)
+
+            val actual = bluetoothTileDialogViewModel.isAutoOnToggleFeatureAvailable()
+            assertThat(actual).isFalse()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
new file mode 100644
index 0000000..28cbcb4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothDevice
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.media.AudioManager
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.flags.Flags
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class DeviceItemFactoryTest : SysuiTestCase() {
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var cachedDevice: CachedBluetoothDevice
+    @Mock private lateinit var bluetoothDevice: BluetoothDevice
+    @Mock private lateinit var packageManager: PackageManager
+
+    private val availableMediaDeviceItemFactory = AvailableMediaDeviceItemFactory()
+    private val connectedDeviceItemFactory = ConnectedDeviceItemFactory()
+    private val savedDeviceItemFactory = SavedDeviceItemFactory()
+
+    private val audioManager = context.getSystemService(AudioManager::class.java)!!
+
+    @Before
+    fun setup() {
+        `when`(cachedDevice.name).thenReturn(DEVICE_NAME)
+        `when`(cachedDevice.address).thenReturn(DEVICE_ADDRESS)
+        `when`(cachedDevice.device).thenReturn(bluetoothDevice)
+        `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY)
+
+        context.setMockPackageManager(packageManager)
+    }
+
+    @Test
+    fun testAvailableMediaDeviceItemFactory_createFromCachedDevice() {
+        val deviceItem = availableMediaDeviceItemFactory.create(context, cachedDevice)
+
+        assertDeviceItem(deviceItem, DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE)
+    }
+
+    @Test
+    fun testConnectedDeviceItemFactory_createFromCachedDevice() {
+        val deviceItem = connectedDeviceItemFactory.create(context, cachedDevice)
+
+        assertDeviceItem(deviceItem, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+    }
+
+    @Test
+    fun testSavedDeviceItemFactory_createFromCachedDevice() {
+        val deviceItem = savedDeviceItemFactory.create(context, cachedDevice)
+
+        assertDeviceItem(deviceItem, DeviceItemType.SAVED_BLUETOOTH_DEVICE)
+        assertThat(deviceItem.background).isNotNull()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTrue() {
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_connected_returnsFalse() {
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(true)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() {
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
+        val exclusiveManagerName =
+            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
+        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
+            .thenReturn(exclusiveManagerName.toByteArray())
+        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo())
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_noExclusiveManager_returnsTrue() {
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() {
+        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
+            .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray())
+        `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0))
+            .thenReturn(PackageInfo())
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() {
+        val exclusiveManagerName =
+            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
+        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
+            .thenReturn(exclusiveManagerName.toByteArray())
+        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0))
+            .thenThrow(PackageManager.NameNotFoundException("Test!"))
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() {
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
+        `when`(cachedDevice.isConnected).thenReturn(false)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalse() {
+        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(cachedDevice.isConnected).thenReturn(true)
+
+        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() {
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() {
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(false)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_notBonded_returnsFalse() {
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
+        val exclusiveManagerName =
+            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
+        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
+            .thenReturn(exclusiveManagerName.toByteArray())
+        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo())
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTrue() {
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() {
+        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
+            .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray())
+        `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0))
+            .thenReturn(PackageInfo())
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() {
+        val exclusiveManagerName =
+            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
+        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
+            .thenReturn(exclusiveManagerName.toByteArray())
+        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0))
+            .thenThrow(PackageManager.NameNotFoundException("Test!"))
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isTrue()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() {
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
+        `when`(bluetoothDevice.isConnected).thenReturn(true)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+    fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalse() {
+        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
+        `when`(bluetoothDevice.isConnected).thenReturn(false)
+        audioManager.setMode(AudioManager.MODE_NORMAL)
+
+        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+            .isFalse()
+    }
+
+    private fun assertDeviceItem(deviceItem: DeviceItem?, deviceItemType: DeviceItemType) {
+        assertThat(deviceItem).isNotNull()
+        assertThat(deviceItem!!.type).isEqualTo(deviceItemType)
+        assertThat(deviceItem.cachedBluetoothDevice).isEqualTo(cachedDevice)
+        assertThat(deviceItem.deviceName).isEqualTo(DEVICE_NAME)
+        assertThat(deviceItem.connectionSummary).isEqualTo(CONNECTION_SUMMARY)
+    }
+
+    companion object {
+        const val DEVICE_NAME = "DeviceName"
+        const val CONNECTION_SUMMARY = "ConnectionSummary"
+        private const val FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name"
+        private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
new file mode 100644
index 0000000..daf4a3c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.content.Context
+import android.media.AudioManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class DeviceItemInteractorTest : SysuiTestCase() {
+
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var bluetoothTileDialogRepository: BluetoothTileDialogRepository
+
+    @Mock private lateinit var cachedDevice1: CachedBluetoothDevice
+
+    @Mock private lateinit var cachedDevice2: CachedBluetoothDevice
+
+    @Mock private lateinit var device1: BluetoothDevice
+
+    @Mock private lateinit var device2: BluetoothDevice
+
+    @Mock private lateinit var deviceItem1: DeviceItem
+
+    @Mock private lateinit var deviceItem2: DeviceItem
+
+    @Mock private lateinit var audioManager: AudioManager
+
+    @Mock private lateinit var adapter: BluetoothAdapter
+
+    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
+
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+
+    @Mock private lateinit var logger: BluetoothTileDialogLogger
+
+    private val fakeSystemClock = FakeSystemClock()
+
+    private lateinit var interactor: DeviceItemInteractor
+
+    private lateinit var dispatcher: CoroutineDispatcher
+
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setUp() {
+        dispatcher = UnconfinedTestDispatcher()
+        testScope = TestScope(dispatcher)
+        interactor =
+            DeviceItemInteractor(
+                bluetoothTileDialogRepository,
+                audioManager,
+                adapter,
+                localBluetoothManager,
+                fakeSystemClock,
+                uiEventLogger,
+                logger,
+                testScope.backgroundScope,
+                dispatcher
+            )
+
+        `when`(deviceItem1.cachedBluetoothDevice).thenReturn(cachedDevice1)
+        `when`(deviceItem2.cachedBluetoothDevice).thenReturn(cachedDevice2)
+        `when`(cachedDevice1.address).thenReturn("ADDRESS")
+        `when`(cachedDevice1.device).thenReturn(device1)
+        `when`(cachedDevice2.device).thenReturn(device2)
+        `when`(bluetoothTileDialogRepository.cachedDevices)
+            .thenReturn(listOf(cachedDevice1, cachedDevice2))
+    }
+
+    @Test
+    fun testUpdateDeviceItems_noCachedDevice_returnEmpty() {
+        testScope.runTest {
+            `when`(bluetoothTileDialogRepository.cachedDevices).thenReturn(emptyList())
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(createFactory({ true }, deviceItem1))
+            )
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(emptyList<DeviceItem>())
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItems_hasCachedDevice_filterNotMatch_returnEmpty() {
+        testScope.runTest {
+            `when`(bluetoothTileDialogRepository.cachedDevices).thenReturn(listOf(cachedDevice1))
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(createFactory({ false }, deviceItem1))
+            )
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(emptyList<DeviceItem>())
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItems_hasCachedDevice_filterMatch_returnDeviceItem() {
+        testScope.runTest {
+            `when`(bluetoothTileDialogRepository.cachedDevices).thenReturn(listOf(cachedDevice1))
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(createFactory({ true }, deviceItem1))
+            )
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(listOf(deviceItem1))
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItems_hasCachedDevice_filterMatch_returnMultipleDeviceItem() {
+        testScope.runTest {
+            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null)
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(createFactory({ false }, deviceItem1), createFactory({ true }, deviceItem2))
+            )
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2))
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItems_sortByDisplayPriority() {
+        testScope.runTest {
+            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null)
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(
+                    createFactory({ cachedDevice -> cachedDevice.device == device1 }, deviceItem1),
+                    createFactory({ cachedDevice -> cachedDevice.device == device2 }, deviceItem2)
+                )
+            )
+            interactor.setDisplayPriorityForTesting(
+                listOf(
+                    DeviceItemType.SAVED_BLUETOOTH_DEVICE,
+                    DeviceItemType.CONNECTED_BLUETOOTH_DEVICE
+                )
+            )
+            `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+            `when`(deviceItem2.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItems_sameType_sortByRecentlyConnected() {
+        testScope.runTest {
+            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(listOf(device2, device1))
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(
+                    createFactory({ cachedDevice -> cachedDevice.device == device1 }, deviceItem1),
+                    createFactory({ cachedDevice -> cachedDevice.device == device2 }, deviceItem2)
+                )
+            )
+            interactor.setDisplayPriorityForTesting(
+                listOf(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+            )
+            `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+            `when`(deviceItem2.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItemOnClick_connectedMedia_setActive() {
+        testScope.runTest {
+            `when`(deviceItem1.type).thenReturn(DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE)
+
+            interactor.updateDeviceItemOnClick(deviceItem1)
+
+            verify(cachedDevice1).setActive()
+            verify(logger)
+                .logDeviceClick(
+                    cachedDevice1.address,
+                    DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE
+                )
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItemOnClick_activeMedia_disconnect() {
+        testScope.runTest {
+            `when`(deviceItem1.type).thenReturn(DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
+
+            interactor.updateDeviceItemOnClick(deviceItem1)
+
+            verify(cachedDevice1).disconnect()
+            verify(logger)
+                .logDeviceClick(cachedDevice1.address, DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItemOnClick_connectedOtherDevice_disconnect() {
+        testScope.runTest {
+            `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+
+            interactor.updateDeviceItemOnClick(deviceItem1)
+
+            verify(cachedDevice1).disconnect()
+            verify(logger)
+                .logDeviceClick(cachedDevice1.address, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItemOnClick_saved_connect() {
+        testScope.runTest {
+            `when`(deviceItem1.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
+
+            interactor.updateDeviceItemOnClick(deviceItem1)
+
+            verify(cachedDevice1).connect()
+            verify(logger)
+                .logDeviceClick(cachedDevice1.address, DeviceItemType.SAVED_BLUETOOTH_DEVICE)
+        }
+    }
+
+    private fun createFactory(
+        isFilterMatchFunc: (CachedBluetoothDevice) -> Boolean,
+        deviceItem: DeviceItem
+    ): DeviceItemFactory {
+        return object : DeviceItemFactory() {
+            override fun isFilterMatched(
+                context: Context,
+                cachedDevice: CachedBluetoothDevice,
+                audioManager: AudioManager
+            ) = isFilterMatchFunc(cachedDevice)
+
+            override fun create(context: Context, cachedDevice: CachedBluetoothDevice) = deviceItem
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
index f5990be..b7ed27f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -21,7 +21,7 @@
 import android.content.Intent
 import android.content.IntentFilter
 import android.os.UserHandle
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
index eb6e517..2c17181 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -24,7 +24,7 @@
 import android.os.Looper
 import android.os.PatternMatcher
 import android.os.UserHandle
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
index 39e4467..582f301 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -21,7 +21,7 @@
 import android.content.IntentFilter
 import android.os.Handler
 import android.os.UserHandle
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt
index feaedc5..1e522fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.camera
 
 import android.content.Intent
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import com.android.systemui.SysuiTestCase
 import org.junit.Assert.assertFalse
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
index 45d20dc..8e5ddc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
@@ -27,6 +27,7 @@
 
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 import androidx.test.filters.SmallTest;
@@ -202,6 +203,36 @@
     }
 
     @Test
+    public void testPassThroughEnterKeyEvent() {
+        KeyEvent enterDown = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER,
+                0, 0, 0, 0, 0, 0, 0, "");
+        KeyEvent enterUp = KeyEvent.obtain(0, 0, MotionEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0,
+                0, 0, 0, 0, 0, 0, "");
+
+        mFalsingCollector.onKeyEvent(enterDown);
+        verify(mFalsingDataProvider, never()).onKeyEvent(any(KeyEvent.class));
+
+        mFalsingCollector.onKeyEvent(enterUp);
+        verify(mFalsingDataProvider, times(1)).onKeyEvent(enterUp);
+    }
+
+    @Test
+    public void testAvoidAKeyEvent() {
+        // Arbitrarily chose the "A" key, as it is not currently allowlisted. If this key is
+        // allowlisted in the future, please choose another key that will not be collected.
+        KeyEvent aKeyDown = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A,
+                0, 0, 0, 0, 0, 0, 0, "");
+        KeyEvent aKeyUp = KeyEvent.obtain(0, 0, MotionEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0,
+                0, 0, 0, 0, 0, 0, "");
+
+        mFalsingCollector.onKeyEvent(aKeyDown);
+        verify(mFalsingDataProvider, never()).onKeyEvent(any(KeyEvent.class));
+
+        mFalsingCollector.onKeyEvent(aKeyUp);
+        verify(mFalsingDataProvider, never()).onKeyEvent(any(KeyEvent.class));
+    }
+
+    @Test
     public void testPassThroughGesture() {
         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
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 0353f87..057b0a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -27,6 +27,7 @@
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
 import android.testing.AndroidTestingRunner;
 import android.util.DisplayMetrics;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 import androidx.test.filters.SmallTest;
@@ -282,6 +283,22 @@
     }
 
     @Test
+    public void test_isFromKeyboard_disallowedKey_false() {
+        KeyEvent eventDown = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0,
+                0, 0, 0, 0, 0, 0, "");
+        KeyEvent eventUp = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, 0,
+                0, 0, 0, 0, 0, "");
+
+        //events have not come in yet
+        assertThat(mDataProvider.isFromKeyboard()).isFalse();
+
+        mDataProvider.onKeyEvent(eventDown);
+        mDataProvider.onKeyEvent(eventUp);
+        assertThat(mDataProvider.isFromKeyboard()).isTrue();
+        mDataProvider.onSessionEnd();
+    }
+
+    @Test
     public void test_IsFromTrackpad() {
         MotionEvent motionEventOrigin = appendTrackpadDownEvent(0, 0);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedInputEventBufferTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedInputEventBufferTest.java
new file mode 100644
index 0000000..ad7afa3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedInputEventBufferTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.classifier;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import android.testing.AndroidTestingRunner;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class TimeLimitedInputEventBufferTest extends SysuiTestCase {
+
+    private static final long MAX_AGE_MS = 100;
+
+    private TimeLimitedInputEventBuffer<InputEvent> mBuffer;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mBuffer = new TimeLimitedInputEventBuffer<>(MAX_AGE_MS);
+    }
+
+    @After
+    public void tearDown() {
+        for (InputEvent inputEvent : mBuffer) {
+            inputEvent.recycle();
+        }
+        mBuffer.clear();
+    }
+
+    @Test
+    public void testMotionEventAllEventsRetained() {
+        MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+        MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+        MotionEvent eventC = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 0, 0, 0);
+        MotionEvent eventD = MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, 0, 0, 0);
+
+        mBuffer.add(eventA);
+        mBuffer.add(eventB);
+        mBuffer.add(eventC);
+        mBuffer.add(eventD);
+
+        assertThat(mBuffer.size(), is(4));
+    }
+
+    @Test
+    public void testMotionEventOlderEventsRemoved() {
+        MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+        MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+        MotionEvent eventC = MotionEvent.obtain(
+                0, MAX_AGE_MS + 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+        MotionEvent eventD = MotionEvent.obtain(
+                0, MAX_AGE_MS + 2, MotionEvent.ACTION_UP, 0, 0, 0);
+
+        mBuffer.add(eventA);
+        mBuffer.add(eventB);
+        assertThat(mBuffer.size(), is(2));
+
+        mBuffer.add(eventC);
+        mBuffer.add(eventD);
+        assertThat(mBuffer.size(), is(2));
+
+        assertThat(mBuffer.get(0), is(eventC));
+        assertThat(mBuffer.get(1), is(eventD));
+    }
+
+    @Test
+    public void testKeyEventAllEventsRetained() {
+        KeyEvent eventA = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, 0,
+                0, 0, 0, 0, 0, "");
+        KeyEvent eventB = KeyEvent.obtain(0, 3, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0, 0, 0, 0,
+                0, 0, 0, "");
+
+        mBuffer.add(eventA);
+        mBuffer.add(eventB);
+
+        assertThat(mBuffer.size(), is(2));
+    }
+
+    @Test
+    public void testKeyEventOlderEventsRemoved() {
+        KeyEvent eventA = KeyEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, KeyEvent.KEYCODE_A, 0, 0,
+                0, 0, 0, 0, 0, "");
+        KeyEvent eventB = KeyEvent.obtain(0, 1, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A, 0, 0, 0, 0,
+                0, 0, 0, "");
+        KeyEvent eventC = KeyEvent.obtain(0, MAX_AGE_MS + 1, MotionEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_A, 0, 0, 0, 0, 0, 0, 0, "");
+        KeyEvent eventD = KeyEvent.obtain(0, MAX_AGE_MS + 2, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A,
+                0, 0, 0, 0, 0, 0, 0, "");
+
+        mBuffer.add(eventA);
+        mBuffer.add(eventB);
+        assertThat(mBuffer.size(), is(2));
+
+        mBuffer.add(eventC);
+        mBuffer.add(eventD);
+        assertThat(mBuffer.size(), is(2));
+
+        assertThat(mBuffer.get(0), is(eventC));
+        assertThat(mBuffer.get(1), is(eventD));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedMotionEventBufferTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedMotionEventBufferTest.java
deleted file mode 100644
index 901196f..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TimeLimitedMotionEventBufferTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.classifier;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import android.testing.AndroidTestingRunner;
-import android.view.MotionEvent;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class TimeLimitedMotionEventBufferTest extends SysuiTestCase {
-
-    private static final long MAX_AGE_MS = 100;
-
-    private TimeLimitedMotionEventBuffer mBuffer;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mBuffer = new TimeLimitedMotionEventBuffer(MAX_AGE_MS);
-    }
-
-    @After
-    public void tearDown() {
-        for (MotionEvent motionEvent : mBuffer) {
-            motionEvent.recycle();
-        }
-        mBuffer.clear();
-    }
-
-    @Test
-    public void testAllEventsRetained() {
-        MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
-        MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
-        MotionEvent eventC = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 0, 0, 0);
-        MotionEvent eventD = MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, 0, 0, 0);
-
-        mBuffer.add(eventA);
-        mBuffer.add(eventB);
-        mBuffer.add(eventC);
-        mBuffer.add(eventD);
-
-        assertThat(mBuffer.size(), is(4));
-    }
-
-    @Test
-    public void testOlderEventsRemoved() {
-        MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
-        MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
-        MotionEvent eventC = MotionEvent.obtain(
-                0, MAX_AGE_MS + 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
-        MotionEvent eventD = MotionEvent.obtain(
-                0, MAX_AGE_MS + 2, MotionEvent.ACTION_UP, 0, 0, 0);
-
-        mBuffer.add(eventA);
-        mBuffer.add(eventB);
-        assertThat(mBuffer.size(), is(2));
-
-        mBuffer.add(eventC);
-        mBuffer.add(eventD);
-        assertThat(mBuffer.size(), is(2));
-
-        assertThat(mBuffer.get(0), is(eventC));
-        assertThat(mBuffer.get(1), is(eventD));
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
new file mode 100644
index 0000000..7094848
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.data.backup
+
+import android.app.backup.BackupDataInput
+import android.app.backup.BackupDataInputStream
+import android.app.backup.BackupDataOutput
+import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import androidx.room.Room
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.backup.CommunalBackupUtilsTest.Companion.represents
+import com.android.systemui.communal.data.backup.CommunalBackupUtilsTest.FakeWidgetMetadata
+import com.android.systemui.communal.data.db.CommunalDatabase
+import com.android.systemui.communal.data.db.CommunalWidgetDao
+import com.android.systemui.communal.proto.toCommunalHubState
+import com.android.systemui.lifecycle.InstantTaskExecutorRule
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalBackupHelperTest : SysuiTestCase() {
+    @JvmField @Rule val instantTaskExecutor = InstantTaskExecutorRule()
+
+    private lateinit var database: CommunalDatabase
+    private lateinit var dao: CommunalWidgetDao
+    private lateinit var backupUtils: CommunalBackupUtils
+
+    // Temporary file used for storing backed-up data.
+    private lateinit var backupDataFile: File
+
+    private lateinit var underTest: CommunalBackupHelper
+
+    @Before
+    fun setup() {
+        database =
+            Room.inMemoryDatabaseBuilder(context, CommunalDatabase::class.java)
+                .allowMainThreadQueries()
+                .build()
+        CommunalDatabase.setInstance(database)
+
+        dao = database.communalWidgetDao()
+        backupUtils = CommunalBackupUtils(context)
+
+        backupDataFile = File(context.cacheDir, "backup_data_file")
+
+        underTest = CommunalBackupHelper(UserHandle.SYSTEM, backupUtils)
+    }
+
+    @After
+    fun teardown() {
+        backupDataFile.delete()
+        database.close()
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
+    fun backupAndRestoreCommunalHub() {
+        val expectedWidgets = setUpDatabase()
+
+        underTest.performBackup(oldState = null, data = getBackupDataOutput(), newState = null)
+        underTest.restoreEntity(getBackupDataInputStream())
+
+        // Verify restored state matches backed-up state
+        val restoredState = backupUtils.readBytesFromDisk().toCommunalHubState()
+        val restoredWidgets = restoredState.widgets.toList()
+        assertThat(restoredWidgets)
+            .comparingElementsUsing(represents)
+            .containsExactlyElementsIn(expectedWidgets)
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_COMMUNAL_HUB)
+    fun backup_skippedWhenCommunalDisabled() {
+        setUpDatabase()
+
+        underTest.performBackup(oldState = null, data = getBackupDataOutput(), newState = null)
+
+        // Verify nothing written to the backup
+        assertThat(backupDataFile.length()).isEqualTo(0)
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
+    fun backup_skippedForNonSystemUser() {
+        setUpDatabase()
+
+        val helper = CommunalBackupHelper(UserHandle.CURRENT, backupUtils)
+        helper.performBackup(oldState = null, data = getBackupDataOutput(), newState = null)
+
+        // Verify nothing written to the backup
+        assertThat(backupDataFile.length()).isEqualTo(0)
+    }
+
+    private fun setUpDatabase(): List<FakeWidgetMetadata> {
+        return listOf(
+                FakeWidgetMetadata(11, "com.android.fakePackage1/fakeWidget1", 3),
+                FakeWidgetMetadata(12, "com.android.fakePackage2/fakeWidget2", 2),
+                FakeWidgetMetadata(13, "com.android.fakePackage3/fakeWidget3", 1),
+            )
+            .onEach { dao.addWidget(it.widgetId, it.componentName, it.rank) }
+    }
+
+    private fun getBackupDataInputStream(): BackupDataInputStream {
+        val input = BackupDataInput(FileInputStream(backupDataFile).fd).apply { readNextHeader() }
+
+        // Construct BackupDataInputStream using reflection because its constructor is package
+        // private
+        val inputStream = BackupDataInputStream::class.constructors.first().call(input)
+
+        // Set key
+        with(inputStream.javaClass.getDeclaredField("key")) {
+            isAccessible = true
+            set(inputStream, input.key)
+        }
+
+        // Set dataSize
+        with(inputStream.javaClass.getDeclaredField("dataSize")) {
+            isAccessible = true
+            set(inputStream, input.dataSize)
+        }
+
+        return inputStream
+    }
+
+    private fun getBackupDataOutput(): BackupDataOutput {
+        return BackupDataOutput(FileOutputStream(backupDataFile).fd)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
new file mode 100644
index 0000000..bed05ee
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.data.backup
+
+import androidx.room.Room
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.db.CommunalDatabase
+import com.android.systemui.communal.data.db.CommunalWidgetDao
+import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.lifecycle.InstantTaskExecutorRule
+import com.google.common.truth.Correspondence
+import com.google.common.truth.Truth.assertThat
+import java.io.FileNotFoundException
+import java.nio.charset.Charset
+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
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalBackupUtilsTest : SysuiTestCase() {
+    @JvmField @Rule val instantTaskExecutor = InstantTaskExecutorRule()
+
+    private lateinit var database: CommunalDatabase
+    private lateinit var dao: CommunalWidgetDao
+    private lateinit var underTest: CommunalBackupUtils
+
+    @Before
+    fun setup() {
+        database =
+            Room.inMemoryDatabaseBuilder(context, CommunalDatabase::class.java)
+                .allowMainThreadQueries()
+                .build()
+        CommunalDatabase.setInstance(database)
+
+        dao = database.communalWidgetDao()
+        underTest = CommunalBackupUtils(context)
+    }
+
+    @After
+    fun teardown() {
+        database.close()
+        underTest.clear()
+    }
+
+    @Test
+    fun getCommunalHubState_returnsExpectedWidgets() {
+        // Set up database
+        val expectedWidgets =
+            listOf(
+                FakeWidgetMetadata(11, "com.android.fakePackage1/fakeWidget1", 3),
+                FakeWidgetMetadata(12, "com.android.fakePackage2/fakeWidget2", 2),
+                FakeWidgetMetadata(13, "com.android.fakePackage3/fakeWidget3", 1),
+            )
+        expectedWidgets.forEach { dao.addWidget(it.widgetId, it.componentName, it.rank) }
+
+        // Get communal hub state
+        val state = underTest.getCommunalHubState()
+        val actualWidgets = state.widgets.toList()
+
+        // Verify the state contains widgets as expected
+        assertThat(actualWidgets)
+            .comparingElementsUsing(represents)
+            .containsExactlyElementsIn(expectedWidgets)
+    }
+
+    @Test
+    fun write_existingContentIsOverwritten() {
+        // Write old data
+        val dataToWrite = "I am old data. Erase me."
+        underTest.writeBytesToDisk(dataToWrite.toByteArray(Charset.defaultCharset()))
+
+        // Verify old data written
+        var dataRead = underTest.readBytesFromDisk().toString(Charset.defaultCharset())
+        assertThat(dataRead).isEqualTo(dataToWrite)
+
+        // Write new data
+        val newDataToWrite = "I am new data."
+        underTest.writeBytesToDisk(newDataToWrite.toByteArray(Charset.defaultCharset()))
+
+        // Verify new data overwrites old
+        dataRead = underTest.readBytesFromDisk().toString(Charset.defaultCharset())
+        assertThat(dataRead).isEqualTo(newDataToWrite)
+    }
+
+    @Ignore("Ignored until we figure out why it is flaky b/336561027")
+    @Test(expected = FileNotFoundException::class)
+    fun read_fileNotFoundException() {
+        underTest.readBytesFromDisk()
+    }
+
+    @Test(expected = FileNotFoundException::class)
+    fun clear_returnsTrueWhenFileDeleted() {
+        // Write bytes to disk
+        underTest.writeBytesToDisk(byteArrayOf(1, 2, 3))
+
+        assertThat(underTest.clear()).isTrue()
+
+        // Verify a read after that throws a FileNotFoundException
+        underTest.readBytesFromDisk()
+    }
+
+    @Test
+    fun clear_returnsFalseWhenFileDoesNotExist() {
+        assertThat(underTest.clear()).isFalse()
+    }
+
+    @Test
+    fun fileExists() {
+        assertThat(underTest.fileExists()).isFalse()
+
+        underTest.writeBytesToDisk(byteArrayOf(1, 2, 3))
+        assertThat(underTest.fileExists()).isTrue()
+
+        underTest.clear()
+        assertThat(underTest.fileExists()).isFalse()
+    }
+
+    data class FakeWidgetMetadata(val widgetId: Int, val componentName: String, val rank: Int)
+
+    companion object {
+        /**
+         * A comparator for whether a [CommunalHubState.CommunalWidgetItem] represents a
+         * [FakeWidgetMetadata]
+         */
+        val represents: Correspondence<CommunalHubState.CommunalWidgetItem, FakeWidgetMetadata> =
+            Correspondence.from(
+                { actual, expected ->
+                    actual?.widgetId == expected?.widgetId &&
+                        actual?.componentName == expected?.componentName &&
+                        actual?.rank == expected?.rank
+                },
+                "represents",
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
index 20dd913..f77c7a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
@@ -21,6 +21,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.nano.CommunalHubState
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.lifecycle.InstantTaskExecutorRule
 import com.google.common.truth.Truth.assertThat
@@ -224,6 +225,42 @@
                 .inOrder()
         }
 
+    @Test
+    fun restoreCommunalHubState() =
+        testScope.runTest {
+            // Set up db
+            listOf(widgetInfo1, widgetInfo2, widgetInfo3).forEach { addWidget(it) }
+
+            // Restore db to fake state
+            communalWidgetDao.restoreCommunalHubState(fakeState)
+
+            // Verify db matches new state
+            val expected = mutableMapOf<CommunalItemRank, CommunalWidgetItem>()
+            fakeState.widgets.forEachIndexed { index, fakeWidget ->
+                // Auto-generated uid continues after the initial 3 widgets and starts at 4
+                val uid = index + 4L
+                val rank = CommunalItemRank(uid = uid, rank = fakeWidget.rank)
+                val widget =
+                    CommunalWidgetItem(
+                        uid = uid,
+                        widgetId = fakeWidget.widgetId,
+                        componentName = fakeWidget.componentName,
+                        itemId = rank.uid,
+                    )
+                expected[rank] = widget
+            }
+            val widgets by collectLastValue(communalWidgetDao.getWidgets())
+            assertThat(widgets).containsExactlyEntriesIn(expected)
+        }
+
+    private fun addWidget(metadata: FakeWidgetMetadata, priority: Int? = null) {
+        communalWidgetDao.addWidget(
+            widgetId = metadata.widgetId,
+            provider = metadata.provider,
+            priority = priority ?: metadata.priority,
+        )
+    }
+
     data class FakeWidgetMetadata(
         val widgetId: Int,
         val provider: ComponentName,
@@ -273,5 +310,22 @@
                 componentName = widgetInfo3.provider.flattenToString(),
                 itemId = communalItemRankEntry3.uid,
             )
+        val fakeState =
+            CommunalHubState().apply {
+                widgets =
+                    listOf(
+                            CommunalHubState.CommunalWidgetItem().apply {
+                                widgetId = 1
+                                componentName = "pk_name/fake_widget_1"
+                                rank = 1
+                            },
+                            CommunalHubState.CommunalWidgetItem().apply {
+                                widgetId = 2
+                                componentName = "pk_name/fake_widget_2"
+                                rank = 2
+                            },
+                        )
+                        .toTypedArray()
+            }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
index 6a79ee8..6cc3ef19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.controls.ui
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.view.HapticFeedbackConstants
 import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt
index dac88a3..e06134b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt
@@ -119,6 +119,7 @@
     fun faceAuthIsRequestedWhenLockscreenBecomesVisibleFromOffState() =
         testScope.runTest {
             underTest.start()
+            runCurrent()
 
             powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_LID)
             faceWakeUpTriggersConfig.setTriggerFaceAuthOnWakeUpFrom(
@@ -160,6 +161,7 @@
     fun faceAuthIsRequestedWhenLockscreenBecomesVisibleFromAodState() =
         testScope.runTest {
             underTest.start()
+            runCurrent()
 
             powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_LID)
             faceWakeUpTriggersConfig.setTriggerFaceAuthOnWakeUpFrom(
@@ -207,6 +209,7 @@
     fun faceAuthIsRequestedWhenLockscreenBecomesVisibleFromDozingState() =
         testScope.runTest {
             underTest.start()
+            runCurrent()
 
             powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_LID)
             faceWakeUpTriggersConfig.setTriggerFaceAuthOnWakeUpFrom(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
index 806930d..68d49c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
@@ -22,6 +22,7 @@
 import android.testing.TestableLooper
 import android.view.Display
 import android.view.Display.TYPE_EXTERNAL
+import android.view.Display.TYPE_INTERNAL
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.FlowValue
@@ -427,6 +428,35 @@
             assertThat(display!!.type).isEqualTo(TYPE_EXTERNAL)
         }
 
+    @Test
+    fun defaultDisplayOff_changes() =
+        testScope.runTest {
+            val defaultDisplayOff by latestDefaultDisplayOffFlowValue()
+            setDisplays(
+                listOf(
+                    display(
+                        type = TYPE_INTERNAL,
+                        id = Display.DEFAULT_DISPLAY,
+                        state = Display.STATE_OFF
+                    )
+                )
+            )
+            displayListener.value.onDisplayChanged(Display.DEFAULT_DISPLAY)
+            assertThat(defaultDisplayOff).isTrue()
+
+            setDisplays(
+                listOf(
+                    display(
+                        type = TYPE_INTERNAL,
+                        id = Display.DEFAULT_DISPLAY,
+                        state = Display.STATE_ON
+                    )
+                )
+            )
+            displayListener.value.onDisplayChanged(Display.DEFAULT_DISPLAY)
+            assertThat(defaultDisplayOff).isFalse()
+        }
+
     private fun Iterable<Display>.ids(): List<Int> = map { it.displayId }
 
     // Wrapper to capture the displayListener.
@@ -436,6 +466,13 @@
         return flowValue
     }
 
+    // Wrapper to capture the displayListener.
+    private fun TestScope.latestDefaultDisplayOffFlowValue(): FlowValue<Boolean?> {
+        val flowValue = collectLastValue(displayRepository.defaultDisplayOff)
+        captureAddedRemovedListener()
+        return flowValue
+    }
+
     private fun TestScope.lastPendingDisplay(): FlowValue<DisplayRepository.PendingDisplay?> {
         val flowValue = collectLastValue(displayRepository.pendingDisplay)
         captureAddedRemovedListener()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt
new file mode 100644
index 0000000..d118cc7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogDelegateTest.kt
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.display.ui.view
+
+import android.app.Dialog
+import android.graphics.Insets
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import android.view.View
+import android.view.Window
+import android.view.WindowInsets
+import android.view.WindowInsetsAnimation
+import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
+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.ArgumentCaptor
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class MirroringConfirmationDialogDelegateTest : SysuiTestCase() {
+
+    private lateinit var underTest: MirroringConfirmationDialogDelegate
+
+    private val onStartMirroringCallback = mock<View.OnClickListener>()
+    private val onCancelCallback = mock<View.OnClickListener>()
+    private val windowDecorView: View = mock {}
+    private val windowInsetsAnimationCallbackCaptor =
+        ArgumentCaptor.forClass(WindowInsetsAnimation.Callback::class.java)
+    private val dialog: Dialog =
+        mock<Dialog> {
+            var view: View? = null
+            whenever(setContentView(any<Int>())).then {
+                view =
+                    LayoutInflater.from([email protected])
+                        .inflate(it.arguments[0] as Int, null, false)
+                Unit
+            }
+            whenever(requireViewById<View>(any<Int>())).then {
+                view?.requireViewById(it.arguments[0] as Int)
+            }
+            val window: Window = mock { whenever(decorView).thenReturn(windowDecorView) }
+            whenever(this.window).thenReturn(window)
+        }
+
+    @Before
+    fun setUp() {
+        underTest =
+            MirroringConfirmationDialogDelegate(
+                context = context,
+                showConcurrentDisplayInfo = false,
+                onStartMirroringClickListener = onStartMirroringCallback,
+                onCancelMirroring = onCancelCallback,
+                navbarBottomInsetsProvider = { 0 },
+            )
+    }
+
+    @Test
+    fun startMirroringButton_clicked_callsCorrectCallback() {
+        underTest.onCreate(dialog, null)
+
+        dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+        verify(onStartMirroringCallback).onClick(any())
+        verify(onCancelCallback, never()).onClick(any())
+    }
+
+    @Test
+    fun cancelButton_clicked_callsCorrectCallback() {
+        underTest.onCreate(dialog, null)
+
+        dialog.requireViewById<View>(R.id.cancel).callOnClick()
+
+        verify(onCancelCallback).onClick(any())
+        verify(onStartMirroringCallback, never()).onClick(any())
+    }
+
+    @Test
+    fun onCancel_afterEnablingMirroring_cancelCallbackNotCalled() {
+        underTest.onCreate(dialog, null)
+        dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+        underTest.onStop(dialog)
+
+        verify(onCancelCallback, never()).onClick(any())
+        verify(onStartMirroringCallback).onClick(any())
+    }
+
+    @Test
+    fun onDismiss_afterEnablingMirroring_cancelCallbackNotCalled() {
+        underTest.onCreate(dialog, null)
+        dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+        underTest.onStop(dialog)
+
+        verify(onCancelCallback, never()).onClick(any())
+        verify(onStartMirroringCallback).onClick(any())
+    }
+
+    @Test
+    fun onInsetsChanged_navBarInsets_updatesBottomPadding() {
+        underTest.onCreate(dialog, null)
+        underTest.onStart(dialog)
+
+        val insets = buildInsets(WindowInsets.Type.navigationBars(), TEST_BOTTOM_INSETS)
+
+        triggerInsetsChanged(WindowInsets.Type.navigationBars(), insets)
+
+        assertThat(dialog.requireViewById<View>(R.id.cd_bottom_sheet).paddingBottom)
+            .isEqualTo(TEST_BOTTOM_INSETS)
+    }
+
+    @Test
+    fun onInsetsChanged_otherType_doesNotUpdateBottomPadding() {
+        underTest.onCreate(dialog, null)
+        underTest.onStart(dialog)
+
+        val insets = buildInsets(WindowInsets.Type.ime(), TEST_BOTTOM_INSETS)
+        triggerInsetsChanged(WindowInsets.Type.ime(), insets)
+
+        assertThat(dialog.requireViewById<View>(R.id.cd_bottom_sheet).paddingBottom)
+            .isNotEqualTo(TEST_BOTTOM_INSETS)
+    }
+
+    private fun buildInsets(@WindowInsets.Type.InsetsType type: Int, bottom: Int): WindowInsets {
+        return WindowInsets.Builder().setInsets(type, Insets.of(0, 0, 0, bottom)).build()
+    }
+
+    private fun triggerInsetsChanged(type: Int, insets: WindowInsets) {
+        verify(windowDecorView)
+            .setWindowInsetsAnimationCallback(capture(windowInsetsAnimationCallbackCaptor))
+        windowInsetsAnimationCallbackCaptor.value.onProgress(
+            insets,
+            listOf(WindowInsetsAnimation(type, Interpolators.INSTANT, 0))
+        )
+    }
+
+    private companion object {
+        const val TEST_BOTTOM_INSETS = 1000 // arbitrarily high number
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
deleted file mode 100644
index 30519b0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
+++ /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 com.android.systemui.display.ui.view
-
-import android.graphics.Insets
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.View
-import android.view.WindowInsets
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.res.R
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class MirroringConfirmationDialogTest : SysuiTestCase() {
-
-    private lateinit var dialog: MirroringConfirmationDialog
-
-    private val onStartMirroringCallback = mock<View.OnClickListener>()
-    private val onCancelCallback = mock<View.OnClickListener>()
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        dialog =
-            MirroringConfirmationDialog(
-                context,
-                onStartMirroringCallback,
-                onCancelCallback,
-                navbarBottomInsetsProvider = { 0 },
-            )
-    }
-
-    @Test
-    fun startMirroringButton_clicked_callsCorrectCallback() {
-        dialog.show()
-
-        dialog.requireViewById<View>(R.id.enable_display).callOnClick()
-
-        verify(onStartMirroringCallback).onClick(any())
-        verify(onCancelCallback, never()).onClick(any())
-    }
-
-    @Test
-    fun cancelButton_clicked_callsCorrectCallback() {
-        dialog.show()
-
-        dialog.requireViewById<View>(R.id.cancel).callOnClick()
-
-        verify(onCancelCallback).onClick(any())
-        verify(onStartMirroringCallback, never()).onClick(any())
-    }
-
-    @Test
-    fun onCancel_afterEnablingMirroring_cancelCallbackNotCalled() {
-        dialog.show()
-        dialog.requireViewById<View>(R.id.enable_display).callOnClick()
-
-        dialog.cancel()
-
-        verify(onCancelCallback, never()).onClick(any())
-        verify(onStartMirroringCallback).onClick(any())
-    }
-
-    @Test
-    fun onDismiss_afterEnablingMirroring_cancelCallbackNotCalled() {
-        dialog.show()
-        dialog.requireViewById<View>(R.id.enable_display).callOnClick()
-
-        dialog.dismiss()
-
-        verify(onCancelCallback, never()).onClick(any())
-        verify(onStartMirroringCallback).onClick(any())
-    }
-
-    @Test
-    fun onInsetsChanged_navBarInsets_updatesBottomPadding() {
-        dialog.show()
-
-        val insets = buildInsets(WindowInsets.Type.navigationBars(), TEST_BOTTOM_INSETS)
-        dialog.onInsetsChanged(WindowInsets.Type.navigationBars(), insets)
-
-        assertThat(dialog.requireViewById<View>(R.id.cd_bottom_sheet).paddingBottom)
-            .isEqualTo(TEST_BOTTOM_INSETS)
-    }
-
-    @Test
-    fun onInsetsChanged_otherType_doesNotUpdateBottomPadding() {
-        dialog.show()
-
-        val insets = buildInsets(WindowInsets.Type.ime(), TEST_BOTTOM_INSETS)
-        dialog.onInsetsChanged(WindowInsets.Type.ime(), insets)
-
-        assertThat(dialog.requireViewById<View>(R.id.cd_bottom_sheet).paddingBottom)
-            .isNotEqualTo(TEST_BOTTOM_INSETS)
-    }
-
-    private fun buildInsets(@WindowInsets.Type.InsetsType type: Int, bottom: Int): WindowInsets {
-        return WindowInsets.Builder().setInsets(type, Insets.of(0, 0, 0, bottom)).build()
-    }
-
-    @After
-    fun teardown() {
-        if (::dialog.isInitialized) {
-            dialog.dismiss()
-        }
-    }
-
-    private companion object {
-        const val TEST_BOTTOM_INSETS = 1000 // arbitrarily high number
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java
deleted file mode 100644
index a127631..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java
+++ /dev/null
@@ -1,643 +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.dreams.touch;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.testing.AndroidTestingRunner;
-import android.util.Pair;
-import android.view.GestureDetector;
-import android.view.IWindowManager;
-import android.view.InputEvent;
-import android.view.MotionEvent;
-
-import androidx.lifecycle.DefaultLifecycleObserver;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dreams.touch.dagger.InputSessionComponent;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.display.DisplayHelper;
-import com.android.systemui.util.time.FakeSystemClock;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    private static class Environment {
-        private final InputSessionComponent.Factory mInputFactory;
-        private final InputSession mInputSession;
-        private final Lifecycle mLifecycle;
-        private final LifecycleOwner mLifecycleOwner;
-        private final DreamOverlayTouchMonitor mMonitor;
-        private final DefaultLifecycleObserver mLifecycleObserver;
-        private final InputChannelCompat.InputEventListener mEventListener;
-        private final GestureDetector.OnGestureListener mGestureListener;
-        private final DisplayHelper mDisplayHelper;
-        private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
-        private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
-        private final Rect mDisplayBounds = Mockito.mock(Rect.class);
-        private final IWindowManager mIWindowManager;
-
-        Environment(Set<DreamTouchHandler> handlers) {
-            mLifecycle = Mockito.mock(Lifecycle.class);
-            mLifecycleOwner = Mockito.mock(LifecycleOwner.class);
-            mIWindowManager = Mockito.mock(IWindowManager.class);
-
-            mInputFactory = Mockito.mock(InputSessionComponent.Factory.class);
-            final InputSessionComponent inputComponent = Mockito.mock(InputSessionComponent.class);
-            mInputSession = Mockito.mock(InputSession.class);
-
-            when(mInputFactory.create(any(), any(), any(), anyBoolean()))
-                    .thenReturn(inputComponent);
-            when(inputComponent.getInputSession()).thenReturn(mInputSession);
-
-            mDisplayHelper = Mockito.mock(DisplayHelper.class);
-            when(mDisplayHelper.getMaxBounds(anyInt(), anyInt()))
-                    .thenReturn(mDisplayBounds);
-            mMonitor = new DreamOverlayTouchMonitor(mExecutor, mBackgroundExecutor,
-                    mLifecycle, mInputFactory, mDisplayHelper, handlers, mIWindowManager, 0);
-            mMonitor.init();
-
-            final ArgumentCaptor<LifecycleObserver> lifecycleObserverCaptor =
-                    ArgumentCaptor.forClass(LifecycleObserver.class);
-            verify(mLifecycle).addObserver(lifecycleObserverCaptor.capture());
-            assertThat(lifecycleObserverCaptor.getValue() instanceof DefaultLifecycleObserver)
-                    .isTrue();
-            mLifecycleObserver = (DefaultLifecycleObserver) lifecycleObserverCaptor.getValue();
-
-            updateLifecycle(observer -> observer.first.onResume(observer.second));
-
-            // Capture creation request.
-            final ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
-                    ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
-            final ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
-                    ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-            verify(mInputFactory).create(any(), inputEventListenerCaptor.capture(),
-                    gestureListenerCaptor.capture(),
-                    eq(true));
-            mEventListener = inputEventListenerCaptor.getValue();
-            mGestureListener = gestureListenerCaptor.getValue();
-        }
-
-        public Rect getDisplayBounds() {
-            return mDisplayBounds;
-        }
-
-        void executeAll() {
-            mExecutor.runAllReady();
-        }
-
-        void publishInputEvent(InputEvent event) {
-            mEventListener.onInputEvent(event);
-        }
-
-        void publishGestureEvent(Consumer<GestureDetector.OnGestureListener> listenerConsumer) {
-            listenerConsumer.accept(mGestureListener);
-        }
-
-        void updateLifecycle(Consumer<Pair<DefaultLifecycleObserver, LifecycleOwner>> consumer) {
-            consumer.accept(Pair.create(mLifecycleObserver, mLifecycleOwner));
-        }
-
-        void verifyInputSessionDispose() {
-            verify(mInputSession).dispose();
-            Mockito.clearInvocations(mInputSession);
-        }
-    }
-
-    @Test
-    public void testReportedDisplayBounds() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
-        when(initialEvent.getX()).thenReturn(0.0f);
-        when(initialEvent.getY()).thenReturn(0.0f);
-        environment.publishInputEvent(initialEvent);
-
-        // Verify display bounds passed into TouchHandler#getTouchInitiationRegion
-        verify(touchHandler).getTouchInitiationRegion(
-                eq(environment.getDisplayBounds()), any(), any());
-        final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
-                ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
-        verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
-
-        // Verify that display bounds provided from TouchSession#getBounds
-        assertThat(touchSessionArgumentCaptor.getValue().getBounds())
-                .isEqualTo(environment.getDisplayBounds());
-    }
-
-    @Test
-    public void testEntryTouchZone() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-        final Rect touchArea = new Rect(4, 4, 8 , 8);
-
-        doAnswer(invocation -> {
-            final Region region = (Region) invocation.getArguments()[1];
-            region.set(touchArea);
-            return null;
-        }).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        // Ensure touch outside specified region is not delivered.
-        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
-        when(initialEvent.getX()).thenReturn(0.0f);
-        when(initialEvent.getY()).thenReturn(1.0f);
-        environment.publishInputEvent(initialEvent);
-        verify(touchHandler, never()).onSessionStart(any());
-
-        // Make sure touch inside region causes session start.
-        when(initialEvent.getX()).thenReturn(5.0f);
-        when(initialEvent.getY()).thenReturn(5.0f);
-        environment.publishInputEvent(initialEvent);
-        verify(touchHandler).onSessionStart(any());
-    }
-
-    @Test
-    public void testSessionCount() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-        final Rect touchArea = new Rect(4, 4, 8 , 8);
-
-        final DreamTouchHandler unzonedTouchHandler = createTouchHandler();
-        doAnswer(invocation -> {
-            final Region region = (Region) invocation.getArguments()[1];
-            region.set(touchArea);
-            return null;
-        }).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
-
-        final Environment environment = new Environment(Stream.of(touchHandler, unzonedTouchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        // Ensure touch outside specified region is delivered to unzoned touch handler.
-        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
-        when(initialEvent.getX()).thenReturn(0.0f);
-        when(initialEvent.getY()).thenReturn(1.0f);
-        environment.publishInputEvent(initialEvent);
-
-        ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionCaptor = ArgumentCaptor.forClass(
-                DreamTouchHandler.TouchSession.class);
-
-        // Make sure only one active session.
-        {
-            verify(unzonedTouchHandler).onSessionStart(touchSessionCaptor.capture());
-            final DreamTouchHandler.TouchSession touchSession = touchSessionCaptor.getValue();
-            assertThat(touchSession.getActiveSessionCount()).isEqualTo(1);
-            touchSession.pop();
-            environment.executeAll();
-        }
-
-        // Make sure touch inside the touch region.
-        when(initialEvent.getX()).thenReturn(5.0f);
-        when(initialEvent.getY()).thenReturn(5.0f);
-        environment.publishInputEvent(initialEvent);
-
-        // Make sure there are two active sessions.
-        {
-            verify(touchHandler).onSessionStart(touchSessionCaptor.capture());
-            final DreamTouchHandler.TouchSession touchSession = touchSessionCaptor.getValue();
-            assertThat(touchSession.getActiveSessionCount()).isEqualTo(2);
-            touchSession.pop();
-        }
-    }
-
-
-    @Test
-    public void testNoActiveSessionWhenHandlerDisabled() {
-        final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
-        // disable the handler
-        when(touchHandler.isEnabled()).thenReturn(false);
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
-        when(initialEvent.getX()).thenReturn(5.0f);
-        when(initialEvent.getY()).thenReturn(5.0f);
-        environment.publishInputEvent(initialEvent);
-
-        // Make sure there is no active session.
-        verify(touchHandler, never()).onSessionStart(any());
-        verify(touchHandler, never()).getTouchInitiationRegion(any(), any(), any());
-    }
-
-    @Test
-    public void testInputEventPropagation() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        // Ensure session started
-        final InputChannelCompat.InputEventListener eventListener =
-                registerInputEventListener(touchHandler);
-
-        // First event will be missed since we register after the execution loop,
-        final InputEvent event = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(event);
-        verify(eventListener).onInputEvent(eq(event));
-    }
-
-    @Test
-    public void testInputEventPropagationAfterRemoval() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        // Ensure session started
-        final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
-        final InputChannelCompat.InputEventListener eventListener =
-                registerInputEventListener(session);
-
-        session.pop();
-        environment.executeAll();
-
-        final InputEvent event = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(event);
-
-        verify(eventListener, never()).onInputEvent(eq(event));
-    }
-
-    @Test
-    public void testInputGesturePropagation() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        // Ensure session started
-        final GestureDetector.OnGestureListener gestureListener =
-                registerGestureListener(touchHandler);
-
-        final MotionEvent event = Mockito.mock(MotionEvent.class);
-        environment.publishGestureEvent(onGestureListener -> onGestureListener.onShowPress(event));
-        verify(gestureListener).onShowPress(eq(event));
-    }
-
-    @Test
-    public void testGestureConsumption() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        // Ensure session started
-        final GestureDetector.OnGestureListener gestureListener =
-                registerGestureListener(touchHandler);
-
-        when(gestureListener.onDown(any())).thenReturn(true);
-        final MotionEvent event = Mockito.mock(MotionEvent.class);
-        environment.publishGestureEvent(onGestureListener -> {
-            assertThat(onGestureListener.onDown(event)).isTrue();
-        });
-
-        verify(gestureListener).onDown(eq(event));
-    }
-
-    @Test
-    public void testBroadcast() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-        final DreamTouchHandler touchHandler2 = createTouchHandler();
-        when(touchHandler2.isEnabled()).thenReturn(true);
-
-        final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        final HashSet<InputChannelCompat.InputEventListener> inputListeners = new HashSet<>();
-
-        inputListeners.add(registerInputEventListener(touchHandler));
-        inputListeners.add(registerInputEventListener(touchHandler));
-        inputListeners.add(registerInputEventListener(touchHandler2));
-
-        final MotionEvent event = Mockito.mock(MotionEvent.class);
-        environment.publishInputEvent(event);
-
-        inputListeners
-                .stream()
-                .forEach(inputEventListener -> verify(inputEventListener).onInputEvent(event));
-    }
-
-    @Test
-    public void testPush() throws InterruptedException, ExecutionException {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
-        final InputChannelCompat.InputEventListener eventListener =
-                registerInputEventListener(session);
-
-        final ListenableFuture<DreamTouchHandler.TouchSession> frontSessionFuture = session.push();
-        environment.executeAll();
-        final DreamTouchHandler.TouchSession frontSession = frontSessionFuture.get();
-        final InputChannelCompat.InputEventListener frontEventListener =
-                registerInputEventListener(frontSession);
-
-        final MotionEvent event = Mockito.mock(MotionEvent.class);
-        environment.publishInputEvent(event);
-
-        verify(frontEventListener).onInputEvent(eq(event));
-        verify(eventListener, never()).onInputEvent(any());
-
-        Mockito.clearInvocations(eventListener, frontEventListener);
-
-        ListenableFuture<DreamTouchHandler.TouchSession> sessionFuture = frontSession.pop();
-        environment.executeAll();
-
-        DreamTouchHandler.TouchSession returnedSession = sessionFuture.get();
-        assertThat(session == returnedSession).isTrue();
-
-        environment.executeAll();
-
-        final MotionEvent followupEvent = Mockito.mock(MotionEvent.class);
-        environment.publishInputEvent(followupEvent);
-
-        verify(eventListener).onInputEvent(eq(followupEvent));
-        verify(frontEventListener, never()).onInputEvent(any());
-    }
-
-    @Test
-    public void testPop() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final DreamTouchHandler.TouchSession.Callback callback =
-                Mockito.mock(DreamTouchHandler.TouchSession.Callback.class);
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
-        session.registerCallback(callback);
-        session.pop();
-        environment.executeAll();
-
-        verify(callback).onRemoved();
-    }
-
-    @Test
-    public void testPauseWithNoActiveSessions() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onPause(observerOwnerPair.second);
-        });
-
-        environment.verifyInputSessionDispose();
-    }
-
-    @Test
-    public void testDeferredPauseWithActiveSessions() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        // Ensure session started
-        final InputChannelCompat.InputEventListener eventListener =
-                registerInputEventListener(touchHandler);
-
-        // First event will be missed since we register after the execution loop,
-        final InputEvent event = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(event);
-        verify(eventListener).onInputEvent(eq(event));
-
-        final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
-                ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
-
-        verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
-
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onPause(observerOwnerPair.second);
-        });
-
-        verify(environment.mInputSession, never()).dispose();
-
-        // End session
-        touchSessionArgumentCaptor.getValue().pop();
-        environment.executeAll();
-
-        // Check to make sure the input session is now disposed.
-        environment.verifyInputSessionDispose();
-    }
-
-    @Test
-    public void testDestroyWithActiveSessions() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        // Ensure session started
-        final InputChannelCompat.InputEventListener eventListener =
-                registerInputEventListener(touchHandler);
-
-        // First event will be missed since we register after the execution loop,
-        final InputEvent event = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(event);
-        verify(eventListener).onInputEvent(eq(event));
-
-        final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
-                ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
-
-        verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
-
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onDestroy(observerOwnerPair.second);
-        });
-
-        // Check to make sure the input session is now disposed.
-        environment.verifyInputSessionDispose();
-    }
-
-
-    @Test
-    public void testPilfering() {
-        final DreamTouchHandler touchHandler1 = createTouchHandler();
-        final DreamTouchHandler touchHandler2 = createTouchHandler();
-        final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        final DreamTouchHandler.TouchSession session1 = captureSession(touchHandler1);
-        final GestureDetector.OnGestureListener gestureListener1 =
-                registerGestureListener(session1);
-
-        final DreamTouchHandler.TouchSession session2 = captureSession(touchHandler2);
-        final GestureDetector.OnGestureListener gestureListener2 =
-                registerGestureListener(session2);
-        when(gestureListener2.onDown(any())).thenReturn(true);
-
-        final MotionEvent gestureEvent = Mockito.mock(MotionEvent.class);
-        environment.publishGestureEvent(
-                onGestureListener -> onGestureListener.onDown(gestureEvent));
-
-        Mockito.clearInvocations(gestureListener1, gestureListener2);
-
-        final MotionEvent followupEvent = Mockito.mock(MotionEvent.class);
-        environment.publishGestureEvent(
-                onGestureListener -> onGestureListener.onDown(followupEvent));
-
-        verify(gestureListener1, never()).onDown(any());
-        verify(gestureListener2).onDown(eq(followupEvent));
-    }
-
-    @Test
-    public void testOnRemovedCallbackOnStopMonitoring() {
-        final DreamTouchHandler touchHandler = createTouchHandler();
-
-        final DreamTouchHandler.TouchSession.Callback callback =
-                Mockito.mock(DreamTouchHandler.TouchSession.Callback.class);
-
-        final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
-
-        final InputEvent initialEvent = Mockito.mock(InputEvent.class);
-        environment.publishInputEvent(initialEvent);
-
-        final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
-        session.registerCallback(callback);
-
-        environment.executeAll();
-
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onDestroy(observerOwnerPair.second);
-        });
-
-        environment.executeAll();
-
-        verify(callback).onRemoved();
-    }
-
-    public GestureDetector.OnGestureListener registerGestureListener(DreamTouchHandler handler) {
-        final GestureDetector.OnGestureListener gestureListener = Mockito.mock(
-                GestureDetector.OnGestureListener.class);
-        final ArgumentCaptor<DreamTouchHandler.TouchSession> sessionCaptor =
-                ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
-        verify(handler).onSessionStart(sessionCaptor.capture());
-        sessionCaptor.getValue().registerGestureListener(gestureListener);
-
-        return gestureListener;
-    }
-
-    public GestureDetector.OnGestureListener registerGestureListener(
-            DreamTouchHandler.TouchSession session) {
-        final GestureDetector.OnGestureListener gestureListener = Mockito.mock(
-                GestureDetector.OnGestureListener.class);
-        session.registerGestureListener(gestureListener);
-
-        return gestureListener;
-    }
-
-    public InputChannelCompat.InputEventListener registerInputEventListener(
-            DreamTouchHandler.TouchSession session) {
-        final InputChannelCompat.InputEventListener eventListener = Mockito.mock(
-                InputChannelCompat.InputEventListener.class);
-        session.registerInputListener(eventListener);
-
-        return eventListener;
-    }
-
-    public DreamTouchHandler.TouchSession captureSession(DreamTouchHandler handler) {
-        final ArgumentCaptor<DreamTouchHandler.TouchSession> sessionCaptor =
-                ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
-        verify(handler).onSessionStart(sessionCaptor.capture());
-        return sessionCaptor.getValue();
-    }
-
-    public InputChannelCompat.InputEventListener registerInputEventListener(
-            DreamTouchHandler handler) {
-        return registerInputEventListener(captureSession(handler));
-    }
-
-    private DreamTouchHandler createTouchHandler() {
-        final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
-        // enable the handler by default
-        when(touchHandler.isEnabled()).thenReturn(true);
-        return touchHandler;
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
index 523127e0..dbe59e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
@@ -23,7 +23,7 @@
 import android.content.res.Resources.NotFoundException
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_SYSUI_TEAMFOOD
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt
index 70d6dd9..943e212 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt
@@ -17,7 +17,7 @@
 
 import android.content.pm.PackageManager.NameNotFoundException
 import android.content.res.Resources
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertThrows
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt
index 7c1325e..d500dd2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.flags
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
 import java.io.PrintWriter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
index 303aaa1..5e87a6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
@@ -19,7 +19,7 @@
 import android.database.ContentObserver
 import android.net.Uri
 import android.os.Handler
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
index db6f85f..755cc46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.flags
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
index 7d7abab..0fdda08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.flags
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.statusbar.policy.BatteryController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
index e287f19..3c965ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.flags
 
 import android.os.PowerManager
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.util.concurrency.FakeExecutor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
index 1f04828..0116e53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.flags
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.power.domain.interactor.PowerInteractor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
index 1d1949d..2daa86b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.systemui.flags
 
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.DeviceConfigProxyFake
 import com.android.systemui.util.concurrency.FakeExecutor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
index 4ba1bc6..8a29217 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
@@ -2,7 +2,7 @@
 
 import android.app.Fragment
 import android.os.Looper
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.util.mockito.mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderEventProducerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderEventProducerTest.kt
deleted file mode 100644
index c22d35c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderEventProducerTest.kt
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.haptics.slider
-
-import android.widget.SeekBar
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import junit.framework.Assert.assertEquals
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SeekableSliderEventProducerTest : SysuiTestCase() {
-
-    private val seekBar = SeekBar(mContext)
-    private val eventProducer = SeekableSliderEventProducer()
-    private val eventFlow = eventProducer.produceEvents()
-
-    @Test
-    fun onStartTrackingTouch_noProgress_trackingTouchEventProduced() = runTest {
-        val latest by collectLastValue(eventFlow)
-
-        eventProducer.onStartTrackingTouch(seekBar)
-
-        assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0F), latest)
-    }
-
-    @Test
-    fun onStopTrackingTouch_noProgress_StoppedTrackingTouchEventProduced() = runTest {
-        val latest by collectLastValue(eventFlow)
-
-        eventProducer.onStopTrackingTouch(seekBar)
-
-        assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0F), latest)
-    }
-
-    @Test
-    fun onProgressChangeByUser_changeByUserEventProduced_withNormalizedProgress() = runTest {
-        val progress = 50
-        val latest by collectLastValue(eventFlow)
-
-        eventProducer.onProgressChanged(seekBar, progress, true)
-
-        assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5F), latest)
-    }
-
-    @Test
-    fun onProgressChangeByUser_zeroWidthSlider_changeByUserEventProduced_withMaxProgress() =
-        runTest {
-            // No-width slider where the min and max values are the same
-            seekBar.min = 100
-            seekBar.max = 100
-            val progress = 50
-            val latest by collectLastValue(eventFlow)
-
-            eventProducer.onProgressChanged(seekBar, progress, true)
-
-            assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 1.0F), latest)
-        }
-
-    @Test
-    fun onProgressChangeByProgram_changeByProgramEventProduced_withNormalizedProgress() = runTest {
-        val progress = 50
-        val latest by collectLastValue(eventFlow)
-
-        eventProducer.onProgressChanged(seekBar, progress, false)
-
-        assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, 0.5F), latest)
-    }
-
-    @Test
-    fun onProgressChangeByProgram_zeroWidthSlider_changeByProgramEventProduced_withMaxProgress() =
-        runTest {
-            // No-width slider where the min and max values are the same
-            seekBar.min = 100
-            seekBar.max = 100
-            val progress = 50
-            val latest by collectLastValue(eventFlow)
-
-            eventProducer.onProgressChanged(seekBar, progress, false)
-
-            assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, 1.0F), latest)
-        }
-
-    @Test
-    fun onStartTrackingTouch_afterProgress_trackingTouchEventProduced_withNormalizedProgress() =
-        runTest {
-            val progress = 50
-            val latest by collectLastValue(eventFlow)
-
-            eventProducer.onProgressChanged(seekBar, progress, true)
-            eventProducer.onStartTrackingTouch(seekBar)
-
-            assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0.5F), latest)
-        }
-
-    @Test
-    fun onStopTrackingTouch_afterProgress_stopTrackingTouchEventProduced_withNormalizedProgress() =
-        runTest {
-            val progress = 50
-            val latest by collectLastValue(eventFlow)
-
-            eventProducer.onProgressChanged(seekBar, progress, true)
-            eventProducer.onStopTrackingTouch(seekBar)
-
-            assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5F), latest)
-        }
-
-    @Test
-    fun onArrowUp_afterStartTrackingTouch_ArrowUpProduced() = runTest {
-        val latest by collectLastValue(eventFlow)
-
-        eventProducer.onStartTrackingTouch(seekBar)
-        eventProducer.onArrowUp()
-
-        assertEquals(SliderEvent(SliderEventType.ARROW_UP, 0f), latest)
-    }
-
-    @Test
-    fun onArrowUp_afterChangeByProgram_ArrowUpProduced_withProgress() = runTest {
-        val progress = 50
-        val latest by collectLastValue(eventFlow)
-
-        eventProducer.onProgressChanged(seekBar, progress, false)
-        eventProducer.onArrowUp()
-
-        assertEquals(SliderEvent(SliderEventType.ARROW_UP, 0.5f), latest)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderTrackerTest.kt
deleted file mode 100644
index 796d6d9..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderTrackerTest.kt
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.haptics.slider
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-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.mockito.Mock
-import org.mockito.Mockito.anyFloat
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
-@RunWith(AndroidJUnit4::class)
-class SeekableSliderTrackerTest : SysuiTestCase() {
-
-    @Mock private lateinit var sliderStateListener: SliderStateListener
-    private val sliderEventProducer = FakeSliderEventProducer()
-    private lateinit var mSeekableSliderTracker: SeekableSliderTracker
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-    }
-
-    @Test
-    fun initializeSliderTracker_startsTracking() = runTest {
-        // GIVEN Initialized tracker
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // THEN the tracker job is active
-        assertThat(mSeekableSliderTracker.isTracking).isTrue()
-    }
-
-    @Test
-    fun stopTracking_onAnyState_resetsToIdle() = runTest {
-        enumValues<SliderState>().forEach {
-            // GIVEN Initialized tracker
-            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-            // GIVEN a state in the state machine
-            mSeekableSliderTracker.setState(it)
-
-            // WHEN the tracker stops tracking the state and listening to events
-            mSeekableSliderTracker.stopTracking()
-
-            // THEN The state is idle and the tracker is not active
-            assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-            assertThat(mSeekableSliderTracker.isTracking).isFalse()
-        }
-    }
-
-    // Tests on the IDLE state
-    @Test
-    fun initializeSliderTracker_isIdle() = runTest {
-        // GIVEN Initialized tracker
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // THEN The state is idle and the listener is not called to play haptics
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyZeroInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun startsTrackingTouch_onIdle_entersWaitState() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a start of tracking touch event
-        val progress = 0f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // THEN the tracker moves to the wait state and the timer job begins
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.WAIT)
-        verifyZeroInteractions(sliderStateListener)
-        assertThat(mSeekableSliderTracker.isWaiting).isTrue()
-    }
-
-    // Tests on the WAIT state
-
-    @OptIn(ExperimentalCoroutinesApi::class)
-    @Test
-    fun waitCompletes_onWait_movesToHandleAcquired() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a start of tracking touch event that moves the tracker to WAIT
-        val progress = 0f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // WHEN the wait time completes plus a small buffer time
-        advanceTimeBy(config.waitTimeMillis + 10L)
-
-        // THEN the tracker moves to the DRAG_HANDLE_ACQUIRED_BY_TOUCH state
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
-        assertThat(mSeekableSliderTracker.isWaiting).isFalse()
-        verify(sliderStateListener).onHandleAcquiredByTouch()
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun impreciseTouch_onWait_movesToHandleAcquired() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
-        // slider
-        var progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // GIVEN a progress event due to an imprecise touch with a progress below threshold
-        progress += (config.jumpThreshold - 0.01f)
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker moves to the DRAG_HANDLE_ACQUIRED_BY_TOUCH state without the timer job
-        // being complete
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
-        assertThat(mSeekableSliderTracker.isWaiting).isFalse()
-        verify(sliderStateListener).onHandleAcquiredByTouch()
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun trackJump_onWait_movesToJumpTrackLocationSelected() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
-        // slider
-        var progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // GIVEN a progress event due to a touch on the slider track beyond threshold
-        progress += (config.jumpThreshold + 0.01f)
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker moves to the jump-track location selected state
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.JUMP_TRACK_LOCATION_SELECTED)
-        assertThat(mSeekableSliderTracker.isWaiting).isFalse()
-        verify(sliderStateListener).onProgressJump(anyFloat())
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun upperBookendSelection_onWait_movesToBookendSelected() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
-        // slider
-        var progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // GIVEN a progress event due to a touch on the slider upper bookend zone.
-        progress = (config.upperBookendThreshold + 0.01f)
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker moves to the jump-track location selected state
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
-        assertThat(mSeekableSliderTracker.isWaiting).isFalse()
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun lowerBookendSelection_onWait_movesToBookendSelected() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
-        // slider
-        var progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // GIVEN a progress event due to a touch on the slider lower bookend zone
-        progress = (config.lowerBookendThreshold - 0.01f)
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker moves to the JUMP_TRACK_LOCATION_SELECTED state
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
-        assertThat(mSeekableSliderTracker.isWaiting).isFalse()
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun stopTracking_onWait_whenWaitingJobIsActive_resetsToIdle() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
-        // slider
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0.5f))
-        assertThat(mSeekableSliderTracker.isWaiting).isTrue()
-
-        // GIVEN that the tracker stops tracking the state and listening to events
-        mSeekableSliderTracker.stopTracking()
-
-        // THEN the tracker moves to the IDLE state without the timer job being complete
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        assertThat(mSeekableSliderTracker.isWaiting).isFalse()
-        assertThat(mSeekableSliderTracker.isTracking).isFalse()
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    // Tests on the JUMP_TRACK_LOCATION_SELECTED state
-
-    @Test
-    fun progressChangeByUser_onJumpTrackLocationSelected_movesToDragHandleDragging() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a JUMP_TRACK_LOCATION_SELECTED state
-        mSeekableSliderTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
-
-        // GIVEN a progress event due to dragging the handle
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5f))
-
-        // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
-        verify(sliderStateListener).onProgress(anyFloat())
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun touchRelease_onJumpTrackLocationSelected_movesToIdle() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a JUMP_TRACK_LOCATION_SELECTED state
-        mSeekableSliderTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
-
-        // GIVEN that the slider stopped tracking touch
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
-
-        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
-        verify(sliderStateListener).onHandleReleasedFromTouch()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun progressChangeByUser_onJumpBookendSelected_movesToDragHandleDragging() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a JUMP_BOOKEND_SELECTED state
-        mSeekableSliderTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
-
-        // GIVEN that the slider stopped tracking touch
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5f))
-
-        // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
-        verify(sliderStateListener).onProgress(anyFloat())
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun touchRelease_onJumpBookendSelected_movesToIdle() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a JUMP_BOOKEND_SELECTED state
-        mSeekableSliderTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
-
-        // GIVEN that the slider stopped tracking touch
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
-
-        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
-        verify(sliderStateListener).onHandleReleasedFromTouch()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    // Tests on the DRAG_HANDLE_ACQUIRED state
-
-    @Test
-    fun progressChangeByUser_onHandleAcquired_movesToDragHandleDragging() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a DRAG_HANDLE_ACQUIRED_BY_TOUCH state
-        mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
-
-        // GIVEN a progress change by the user
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
-        verify(sliderStateListener).onProgress(progress)
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun touchRelease_onHandleAcquired_movesToIdle() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a DRAG_HANDLE_ACQUIRED_BY_TOUCH state
-        mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
-
-        // GIVEN that the handle stops tracking touch
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
-
-        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
-        verify(sliderStateListener).onHandleReleasedFromTouch()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    // Tests on DRAG_HANDLE_DRAGGING
-
-    @Test
-    fun progressChangeByUser_onHandleDragging_progressOutsideOfBookends_doesNotChangeState() =
-        runTest {
-            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-            // GIVEN a DRAG_HANDLE_DRAGGING state
-            mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
-
-            // GIVEN a progress change by the user outside of bookend bounds
-            val progress = 0.5f
-            sliderEventProducer.sendEvent(
-                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-            )
-
-            // THEN the tracker does not change state and executes the onProgress call
-            assertThat(mSeekableSliderTracker.currentState)
-                .isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
-            verify(sliderStateListener).onProgress(progress)
-            verifyNoMoreInteractions(sliderStateListener)
-        }
-
-    @Test
-    fun progressChangeByUser_onHandleDragging_reachesLowerBookend_movesToHandleReachedBookend() =
-        runTest {
-            val config = SeekableSliderTrackerConfig()
-            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-            // GIVEN a DRAG_HANDLE_DRAGGING state
-            mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
-
-            // GIVEN a progress change by the user reaching the lower bookend
-            val progress = config.lowerBookendThreshold - 0.01f
-            sliderEventProducer.sendEvent(
-                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-            )
-
-            // THEN the tracker moves to the DRAG_HANDLE_REACHED_BOOKEND state and executes the
-            // corresponding callback
-            assertThat(mSeekableSliderTracker.currentState)
-                .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-            verify(sliderStateListener).onLowerBookend()
-            verifyNoMoreInteractions(sliderStateListener)
-        }
-
-    @Test
-    fun progressChangeByUser_onHandleDragging_reachesUpperBookend_movesToHandleReachedBookend() =
-        runTest {
-            val config = SeekableSliderTrackerConfig()
-            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-            // GIVEN a DRAG_HANDLE_DRAGGING state
-            mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
-
-            // GIVEN a progress change by the user reaching the upper bookend
-            val progress = config.upperBookendThreshold + 0.01f
-            sliderEventProducer.sendEvent(
-                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-            )
-
-            // THEN the tracker moves to the DRAG_HANDLE_REACHED_BOOKEND state and executes the
-            // corresponding callback
-            assertThat(mSeekableSliderTracker.currentState)
-                .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-            verify(sliderStateListener).onUpperBookend()
-            verifyNoMoreInteractions(sliderStateListener)
-        }
-
-    @Test
-    fun touchRelease_onHandleDragging_movesToIdle() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a DRAG_HANDLE_DRAGGING state
-        mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
-
-        // GIVEN that the slider stops tracking touch
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
-
-        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
-        verify(sliderStateListener).onHandleReleasedFromTouch()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    // Tests on the DRAG_HANDLE_REACHED_BOOKEND state
-
-    @Test
-    fun progressChangeByUser_outsideOfBookendRange_onLowerBookend_movesToDragHandleDragging() =
-        runTest {
-            val config = SeekableSliderTrackerConfig()
-            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-            // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
-            mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-
-            // GIVEN a progress event that falls outside of the lower bookend range
-            val progress = config.lowerBookendThreshold + 0.01f
-            sliderEventProducer.sendEvent(
-                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-            )
-
-            // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state and executes accordingly
-            verify(sliderStateListener).onProgress(progress)
-            assertThat(mSeekableSliderTracker.currentState)
-                .isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
-            verifyNoMoreInteractions(sliderStateListener)
-        }
-
-    @Test
-    fun progressChangeByUser_insideOfBookendRange_onLowerBookend_doesNotChangeState() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
-        mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-
-        // GIVEN a progress event that falls inside of the lower bookend range
-        val progress = config.lowerBookendThreshold - 0.01f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker stays in the current state and executes accordingly
-        verify(sliderStateListener).onLowerBookend()
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun progressChangeByUser_outsideOfBookendRange_onUpperBookend_movesToDragHandleDragging() =
-        runTest {
-            val config = SeekableSliderTrackerConfig()
-            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-            // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
-            mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-
-            // GIVEN a progress event that falls outside of the upper bookend range
-            val progress = config.upperBookendThreshold - 0.01f
-            sliderEventProducer.sendEvent(
-                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-            )
-
-            // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state and executes accordingly
-            verify(sliderStateListener).onProgress(progress)
-            assertThat(mSeekableSliderTracker.currentState)
-                .isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
-            verifyNoMoreInteractions(sliderStateListener)
-        }
-
-    @Test
-    fun progressChangeByUser_insideOfBookendRange_onUpperBookend_doesNotChangeState() = runTest {
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
-        mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-
-        // GIVEN a progress event that falls inside of the upper bookend range
-        val progress = config.upperBookendThreshold + 0.01f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
-        )
-
-        // THEN the tracker stays in the current state and executes accordingly
-        verify(sliderStateListener).onUpperBookend()
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun touchRelease_onHandleReachedBookend_movesToIdle() = runTest {
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
-        mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
-
-        // GIVEN that the handle stops tracking touch
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
-
-        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
-        verify(sliderStateListener).onHandleReleasedFromTouch()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyNoMoreInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun onProgressChangeByProgram_atTheMiddle_onIdle_movesToArrowHandleMovedOnce() = runTest {
-        // GIVEN an initialized tracker in the IDLE state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-
-        // GIVEN a progress due to an external source that lands at the middle of the slider
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the state moves to ARROW_HANDLE_MOVED_ONCE and the listener is called to play
-        // haptics
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
-        verify(sliderStateListener).onSelectAndArrow(progress)
-    }
-
-    @Test
-    fun onProgressChangeByProgram_atUpperBookend_onIdle_movesToIdle() = runTest {
-        // GIVEN an initialized tracker in the IDLE state
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // GIVEN a progress due to an external source that lands at the upper bookend
-        val progress = config.upperBookendThreshold + 0.01f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the tracker executes upper bookend haptics before moving back to IDLE
-        verify(sliderStateListener).onUpperBookend()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-    }
-
-    @Test
-    fun onProgressChangeByProgram_atLowerBookend_onIdle_movesToIdle() = runTest {
-        // GIVEN an initialized tracker in the IDLE state
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-
-        // WHEN a progress is recorded due to an external source that lands at the lower bookend
-        val progress = config.lowerBookendThreshold - 0.01f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the tracker executes lower bookend haptics before moving to IDLE
-        verify(sliderStateListener).onLowerBookend()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-    }
-
-    @Test
-    fun onArrowUp_onArrowMovedOnce_movesToIdle() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
-
-        // WHEN the external stimulus is released
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.ARROW_UP, progress))
-
-        // THEN the tracker moves back to IDLE and there are no haptics
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyZeroInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun onStartTrackingTouch_onArrowMovedOnce_movesToWait() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
-
-        // WHEN the slider starts tracking touch
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // THEN the tracker moves back to WAIT and starts the waiting job. Also, there are no
-        // haptics
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.WAIT)
-        assertThat(mSeekableSliderTracker.isWaiting).isTrue()
-        verifyZeroInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun onProgressChangeByProgram_onArrowMovedOnce_movesToArrowMovesContinuously() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
-
-        // WHEN the slider gets an external progress change
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the tracker moves to ARROW_HANDLE_MOVES_CONTINUOUSLY and calls the appropriate
-        // haptics
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-        verify(sliderStateListener).onProgress(progress)
-    }
-
-    @Test
-    fun onArrowUp_onArrowMovesContinuously_movesToIdle() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-
-        // WHEN the external stimulus is released
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.ARROW_UP, progress))
-
-        // THEN the tracker moves to IDLE and no haptics are played
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-        verifyZeroInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun onStartTrackingTouch_onArrowMovesContinuously_movesToWait() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-
-        // WHEN the slider starts tracking touch
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
-
-        // THEN the tracker moves to WAIT and the wait job starts.
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.WAIT)
-        assertThat(mSeekableSliderTracker.isWaiting).isTrue()
-        verifyZeroInteractions(sliderStateListener)
-    }
-
-    @Test
-    fun onProgressChangeByProgram_onArrowMovesContinuously_preservesState() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-
-        // WHEN the slider changes progress programmatically at the middle
-        val progress = 0.5f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the tracker stays in the same state and haptics are delivered appropriately
-        assertThat(mSeekableSliderTracker.currentState)
-            .isEqualTo(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-        verify(sliderStateListener).onProgress(progress)
-    }
-
-    @Test
-    fun onProgramProgress_atLowerBookend_onArrowMovesContinuously_movesToIdle() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-
-        // WHEN the slider reaches the lower bookend programmatically
-        val progress = config.lowerBookendThreshold - 0.01f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the tracker executes lower bookend haptics before moving to IDLE
-        verify(sliderStateListener).onLowerBookend()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-    }
-
-    @Test
-    fun onProgramProgress_atUpperBookend_onArrowMovesContinuously_movesToIdle() = runTest {
-        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
-        val config = SeekableSliderTrackerConfig()
-        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
-        mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
-
-        // WHEN the slider reaches the lower bookend programmatically
-        val progress = config.upperBookendThreshold + 0.01f
-        sliderEventProducer.sendEvent(
-            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
-        )
-
-        // THEN the tracker executes upper bookend haptics before moving to IDLE
-        verify(sliderStateListener).onUpperBookend()
-        assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
-    }
-
-    @OptIn(ExperimentalCoroutinesApi::class)
-    private fun initTracker(
-        scope: CoroutineScope,
-        config: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
-    ) {
-        mSeekableSliderTracker =
-            SeekableSliderTracker(sliderStateListener, sliderEventProducer, scope, config)
-        mSeekableSliderTracker.startTracking()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderStateTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderStateTrackerTest.kt
new file mode 100644
index 0000000..a09d345
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderStateTrackerTest.kt
@@ -0,0 +1,729 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.slider
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+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.mockito.Mock
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+class SliderStateTrackerTest : SysuiTestCase() {
+
+    @Mock private lateinit var sliderStateListener: SliderStateListener
+    private val sliderEventProducer = FakeSliderEventProducer()
+    private lateinit var mSliderStateTracker: SliderStateTracker
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun initializeSliderTracker_startsTracking() = runTest {
+        // GIVEN Initialized tracker
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // THEN the tracker job is active
+        assertThat(mSliderStateTracker.isTracking).isTrue()
+    }
+
+    @Test
+    fun stopTracking_onAnyState_resetsToIdle() = runTest {
+        enumValues<SliderState>().forEach {
+            // GIVEN Initialized tracker
+            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+            // GIVEN a state in the state machine
+            mSliderStateTracker.setState(it)
+
+            // WHEN the tracker stops tracking the state and listening to events
+            mSliderStateTracker.stopTracking()
+
+            // THEN The state is idle and the tracker is not active
+            assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+            assertThat(mSliderStateTracker.isTracking).isFalse()
+        }
+    }
+
+    // Tests on the IDLE state
+    @Test
+    fun initializeSliderTracker_isIdle() = runTest {
+        // GIVEN Initialized tracker
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // THEN The state is idle and the listener is not called to play haptics
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyZeroInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun startsTrackingTouch_onIdle_entersWaitState() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a start of tracking touch event
+        val progress = 0f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // THEN the tracker moves to the wait state and the timer job begins
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.WAIT)
+        verifyZeroInteractions(sliderStateListener)
+        assertThat(mSliderStateTracker.isWaiting).isTrue()
+    }
+
+    // Tests on the WAIT state
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun waitCompletes_onWait_movesToHandleAcquired() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a start of tracking touch event that moves the tracker to WAIT
+        val progress = 0f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // WHEN the wait time completes plus a small buffer time
+        advanceTimeBy(config.waitTimeMillis + 10L)
+
+        // THEN the tracker moves to the DRAG_HANDLE_ACQUIRED_BY_TOUCH state
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+        assertThat(mSliderStateTracker.isWaiting).isFalse()
+        verify(sliderStateListener).onHandleAcquiredByTouch()
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun impreciseTouch_onWait_movesToHandleAcquired() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
+        // slider
+        var progress = 0.5f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // GIVEN a progress event due to an imprecise touch with a progress below threshold
+        progress += (config.jumpThreshold - 0.01f)
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker moves to the DRAG_HANDLE_ACQUIRED_BY_TOUCH state without the timer job
+        // being complete
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+        assertThat(mSliderStateTracker.isWaiting).isFalse()
+        verify(sliderStateListener).onHandleAcquiredByTouch()
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun trackJump_onWait_movesToJumpTrackLocationSelected() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
+        // slider
+        var progress = 0.5f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // GIVEN a progress event due to a touch on the slider track beyond threshold
+        progress += (config.jumpThreshold + 0.01f)
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker moves to the jump-track location selected state
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.JUMP_TRACK_LOCATION_SELECTED)
+        assertThat(mSliderStateTracker.isWaiting).isFalse()
+        verify(sliderStateListener).onProgressJump(anyFloat())
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun upperBookendSelection_onWait_movesToBookendSelected() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
+        // slider
+        var progress = 0.5f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // GIVEN a progress event due to a touch on the slider upper bookend zone.
+        progress = (config.upperBookendThreshold + 0.01f)
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker moves to the jump-track location selected state
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
+        assertThat(mSliderStateTracker.isWaiting).isFalse()
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun lowerBookendSelection_onWait_movesToBookendSelected() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
+        // slider
+        var progress = 0.5f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // GIVEN a progress event due to a touch on the slider lower bookend zone
+        progress = (config.lowerBookendThreshold - 0.01f)
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker moves to the JUMP_TRACK_LOCATION_SELECTED state
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
+        assertThat(mSliderStateTracker.isWaiting).isFalse()
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun stopTracking_onWait_whenWaitingJobIsActive_resetsToIdle() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
+        // slider
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0.5f))
+        assertThat(mSliderStateTracker.isWaiting).isTrue()
+
+        // GIVEN that the tracker stops tracking the state and listening to events
+        mSliderStateTracker.stopTracking()
+
+        // THEN the tracker moves to the IDLE state without the timer job being complete
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        assertThat(mSliderStateTracker.isWaiting).isFalse()
+        assertThat(mSliderStateTracker.isTracking).isFalse()
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    // Tests on the JUMP_TRACK_LOCATION_SELECTED state
+
+    @Test
+    fun progressChangeByUser_onJumpTrackLocationSelected_movesToDragHandleDragging() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a JUMP_TRACK_LOCATION_SELECTED state
+        mSliderStateTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
+
+        // GIVEN a progress event due to dragging the handle
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5f))
+
+        // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+        verify(sliderStateListener).onProgress(anyFloat())
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun touchRelease_onJumpTrackLocationSelected_movesToIdle() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a JUMP_TRACK_LOCATION_SELECTED state
+        mSliderStateTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
+
+        // GIVEN that the slider stopped tracking touch
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
+
+        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
+        verify(sliderStateListener).onHandleReleasedFromTouch()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun progressChangeByUser_onJumpBookendSelected_movesToDragHandleDragging() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a JUMP_BOOKEND_SELECTED state
+        mSliderStateTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
+
+        // GIVEN that the slider stopped tracking touch
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5f))
+
+        // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+        verify(sliderStateListener).onProgress(anyFloat())
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun touchRelease_onJumpBookendSelected_movesToIdle() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a JUMP_BOOKEND_SELECTED state
+        mSliderStateTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
+
+        // GIVEN that the slider stopped tracking touch
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
+
+        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
+        verify(sliderStateListener).onHandleReleasedFromTouch()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    // Tests on the DRAG_HANDLE_ACQUIRED state
+
+    @Test
+    fun progressChangeByUser_onHandleAcquired_movesToDragHandleDragging() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a DRAG_HANDLE_ACQUIRED_BY_TOUCH state
+        mSliderStateTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+
+        // GIVEN a progress change by the user
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
+        verify(sliderStateListener).onProgress(progress)
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun touchRelease_onHandleAcquired_movesToIdle() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a DRAG_HANDLE_ACQUIRED_BY_TOUCH state
+        mSliderStateTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+
+        // GIVEN that the handle stops tracking touch
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
+
+        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
+        verify(sliderStateListener).onHandleReleasedFromTouch()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    // Tests on DRAG_HANDLE_DRAGGING
+
+    @Test
+    fun progressChangeByUser_onHandleDragging_progressOutsideOfBookends_doesNotChangeState() =
+        runTest {
+            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+            // GIVEN a DRAG_HANDLE_DRAGGING state
+            mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+
+            // GIVEN a progress change by the user outside of bookend bounds
+            val progress = 0.5f
+            sliderEventProducer.sendEvent(
+                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+            )
+
+            // THEN the tracker does not change state and executes the onProgress call
+            assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+            verify(sliderStateListener).onProgress(progress)
+            verifyNoMoreInteractions(sliderStateListener)
+        }
+
+    @Test
+    fun progressChangeByUser_onHandleDragging_reachesLowerBookend_movesToHandleReachedBookend() =
+        runTest {
+            val config = SeekableSliderTrackerConfig()
+            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+            // GIVEN a DRAG_HANDLE_DRAGGING state
+            mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+
+            // GIVEN a progress change by the user reaching the lower bookend
+            val progress = config.lowerBookendThreshold - 0.01f
+            sliderEventProducer.sendEvent(
+                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+            )
+
+            // THEN the tracker moves to the DRAG_HANDLE_REACHED_BOOKEND state and executes the
+            // corresponding callback
+            assertThat(mSliderStateTracker.currentState)
+                .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+            verify(sliderStateListener).onLowerBookend()
+            verifyNoMoreInteractions(sliderStateListener)
+        }
+
+    @Test
+    fun progressChangeByUser_onHandleDragging_reachesUpperBookend_movesToHandleReachedBookend() =
+        runTest {
+            val config = SeekableSliderTrackerConfig()
+            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+            // GIVEN a DRAG_HANDLE_DRAGGING state
+            mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+
+            // GIVEN a progress change by the user reaching the upper bookend
+            val progress = config.upperBookendThreshold + 0.01f
+            sliderEventProducer.sendEvent(
+                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+            )
+
+            // THEN the tracker moves to the DRAG_HANDLE_REACHED_BOOKEND state and executes the
+            // corresponding callback
+            assertThat(mSliderStateTracker.currentState)
+                .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+            verify(sliderStateListener).onUpperBookend()
+            verifyNoMoreInteractions(sliderStateListener)
+        }
+
+    @Test
+    fun touchRelease_onHandleDragging_movesToIdle() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a DRAG_HANDLE_DRAGGING state
+        mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+
+        // GIVEN that the slider stops tracking touch
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
+
+        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
+        verify(sliderStateListener).onHandleReleasedFromTouch()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    // Tests on the DRAG_HANDLE_REACHED_BOOKEND state
+
+    @Test
+    fun progressChangeByUser_outsideOfBookendRange_onLowerBookend_movesToDragHandleDragging() =
+        runTest {
+            val config = SeekableSliderTrackerConfig()
+            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+            // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
+            mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+
+            // GIVEN a progress event that falls outside of the lower bookend range
+            val progress = config.lowerBookendThreshold + 0.01f
+            sliderEventProducer.sendEvent(
+                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+            )
+
+            // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state and executes accordingly
+            verify(sliderStateListener).onProgress(progress)
+            assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+            verifyNoMoreInteractions(sliderStateListener)
+        }
+
+    @Test
+    fun progressChangeByUser_insideOfBookendRange_onLowerBookend_doesNotChangeState() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
+        mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+
+        // GIVEN a progress event that falls inside of the lower bookend range
+        val progress = config.lowerBookendThreshold - 0.01f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker stays in the current state and executes accordingly
+        verify(sliderStateListener).onLowerBookend()
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun progressChangeByUser_outsideOfBookendRange_onUpperBookend_movesToDragHandleDragging() =
+        runTest {
+            val config = SeekableSliderTrackerConfig()
+            initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+            // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
+            mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+
+            // GIVEN a progress event that falls outside of the upper bookend range
+            val progress = config.upperBookendThreshold - 0.01f
+            sliderEventProducer.sendEvent(
+                SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+            )
+
+            // THEN the tracker moves to the DRAG_HANDLE_DRAGGING state and executes accordingly
+            verify(sliderStateListener).onProgress(progress)
+            assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+            verifyNoMoreInteractions(sliderStateListener)
+        }
+
+    @Test
+    fun progressChangeByUser_insideOfBookendRange_onUpperBookend_doesNotChangeState() = runTest {
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
+        mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+
+        // GIVEN a progress event that falls inside of the upper bookend range
+        val progress = config.upperBookendThreshold + 0.01f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress)
+        )
+
+        // THEN the tracker stays in the current state and executes accordingly
+        verify(sliderStateListener).onUpperBookend()
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun touchRelease_onHandleReachedBookend_movesToIdle() = runTest {
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
+        mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+
+        // GIVEN that the handle stops tracking touch
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
+
+        // THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
+        verify(sliderStateListener).onHandleReleasedFromTouch()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyNoMoreInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun onStartedTrackingProgram_atTheMiddle_onIdle_movesToArrowHandleMovedOnce() = runTest {
+        // GIVEN an initialized tracker in the IDLE state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+
+        // GIVEN a progress due to an external source that lands at the middle of the slider
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress)
+        )
+
+        // THEN the state moves to ARROW_HANDLE_MOVED_ONCE and the listener is called to play
+        // haptics
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
+        verify(sliderStateListener).onSelectAndArrow(progress)
+    }
+
+    @Test
+    fun onStartedTrackingProgram_atUpperBookend_onIdle_movesToIdle() = runTest {
+        // GIVEN an initialized tracker in the IDLE state
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // GIVEN a progress due to an external source that lands at the upper bookend
+        val progress = config.upperBookendThreshold + 0.01f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress)
+        )
+
+        // THEN the tracker executes upper bookend haptics before moving back to IDLE
+        verify(sliderStateListener).onUpperBookend()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+    }
+
+    @Test
+    fun onStartedTrackingProgram_atLowerBookend_onIdle_movesToIdle() = runTest {
+        // GIVEN an initialized tracker in the IDLE state
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+
+        // WHEN a progress is recorded due to an external source that lands at the lower bookend
+        val progress = config.lowerBookendThreshold - 0.01f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress)
+        )
+
+        // THEN the tracker executes lower bookend haptics before moving to IDLE
+        verify(sliderStateListener).onLowerBookend()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+    }
+
+    @Test
+    fun onArrowUp_onArrowMovedOnce_movesToIdle() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
+
+        // WHEN the external stimulus is released
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, progress)
+        )
+
+        // THEN the tracker moves back to IDLE and there are no haptics
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyZeroInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun onStartTrackingTouch_onArrowMovedOnce_movesToWait() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
+
+        // WHEN the slider starts tracking touch
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // THEN the tracker moves back to WAIT and starts the waiting job. Also, there are no
+        // haptics
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.WAIT)
+        assertThat(mSliderStateTracker.isWaiting).isTrue()
+        verifyZeroInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun onProgressChangeByProgram_onArrowMovedOnce_movesToArrowMovesContinuously() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
+
+        // WHEN the slider gets an external progress change
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+        )
+
+        // THEN the tracker moves to ARROW_HANDLE_MOVES_CONTINUOUSLY and calls the appropriate
+        // haptics
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+        verify(sliderStateListener).onProgress(progress)
+    }
+
+    @Test
+    fun onArrowUp_onArrowMovesContinuously_movesToIdle() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+
+        // WHEN the external stimulus is released
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, progress)
+        )
+
+        // THEN the tracker moves to IDLE and no haptics are played
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+        verifyZeroInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun onStartTrackingTouch_onArrowMovesContinuously_movesToWait() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+
+        // WHEN the slider starts tracking touch
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
+
+        // THEN the tracker moves to WAIT and the wait job starts.
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.WAIT)
+        assertThat(mSliderStateTracker.isWaiting).isTrue()
+        verifyZeroInteractions(sliderStateListener)
+    }
+
+    @Test
+    fun onProgressChangeByProgram_onArrowMovesContinuously_preservesState() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+
+        // WHEN the slider changes progress programmatically at the middle
+        val progress = 0.5f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+        )
+
+        // THEN the tracker stays in the same state and haptics are delivered appropriately
+        assertThat(mSliderStateTracker.currentState)
+            .isEqualTo(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+        verify(sliderStateListener).onProgress(progress)
+    }
+
+    @Test
+    fun onProgramProgress_atLowerBookend_onArrowMovesContinuously_movesToIdle() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+
+        // WHEN the slider reaches the lower bookend programmatically
+        val progress = config.lowerBookendThreshold - 0.01f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+        )
+
+        // THEN the tracker executes lower bookend haptics before moving to IDLE
+        verify(sliderStateListener).onLowerBookend()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+    }
+
+    @Test
+    fun onProgramProgress_atUpperBookend_onArrowMovesContinuously_movesToIdle() = runTest {
+        // GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
+        val config = SeekableSliderTrackerConfig()
+        initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
+        mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+
+        // WHEN the slider reaches the lower bookend programmatically
+        val progress = config.upperBookendThreshold + 0.01f
+        sliderEventProducer.sendEvent(
+            SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+        )
+
+        // THEN the tracker executes upper bookend haptics before moving to IDLE
+        verify(sliderStateListener).onUpperBookend()
+        assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    private fun initTracker(
+        scope: CoroutineScope,
+        config: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
+    ) {
+        mSliderStateTracker =
+            SliderStateTracker(sliderStateListener, sliderEventProducer, scope, config)
+        mSliderStateTracker.startTracking()
+    }
+}
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 1a6da76..36bfa09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -51,6 +51,7 @@
 import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.domain.interactor.shadeInteractor
@@ -203,6 +204,7 @@
                 biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
+                sceneInteractor = { kosmos.sceneInteractor },
             )
         underTest.previewManager =
             KeyguardRemotePreviewManager(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 11ec417f..709f779 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -25,8 +25,8 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
-import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER;
 import static com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR;
+import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER;
 import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
 import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
 import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
@@ -91,6 +91,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.ui.viewmodel.DreamViewModel;
 import com.android.systemui.dump.DumpManager;
@@ -101,7 +102,6 @@
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.scene.FakeWindowRootViewComponent;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scene.ui.view.WindowRootView;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -219,8 +219,8 @@
 
     private @Mock CoroutineDispatcher mDispatcher;
     private @Mock DreamViewModel mDreamViewModel;
+    private @Mock CommunalTransitionViewModel mCommunalTransitionViewModel;
     private @Mock SystemPropertiesHelper mSystemPropertiesHelper;
-    private @Mock SceneContainerFlags mSceneContainerFlags;
 
     private FakeFeatureFlags mFeatureFlags;
     private final int mDefaultUserId = 100;
@@ -241,6 +241,10 @@
                 .thenReturn(mock(Flow.class));
         when(mDreamViewModel.getTransitionEnded())
                 .thenReturn(mock(Flow.class));
+        when(mCommunalTransitionViewModel.getShowByDefault())
+                .thenReturn(mock(Flow.class));
+        when(mCommunalTransitionViewModel.getTransitionFromOccludedEnded())
+                .thenReturn(mock(Flow.class));
         when(mSelectedUserInteractor.getSelectedUserId()).thenReturn(mDefaultUserId);
         when(mSelectedUserInteractor.getSelectedUserId(anyBoolean())).thenReturn(mDefaultUserId);
         mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
@@ -264,7 +268,6 @@
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
                 mUserTracker,
-                mSceneContainerFlags,
                 mKosmos::getCommunalInteractor);
         mFeatureFlags = new FakeFeatureFlags();
         mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER);
@@ -1229,6 +1232,7 @@
                 mSystemClock,
                 mDispatcher,
                 () -> mDreamViewModel,
+                () -> mCommunalTransitionViewModel,
                 mSystemPropertiesHelper,
                 () -> mock(WindowManagerLockscreenVisibilityManager.class),
                 mSelectedUserInteractor,
@@ -1236,7 +1240,7 @@
                 mock(WindowManagerOcclusionManager.class));
         mViewMediator.start();
 
-        mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
+        mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null);
     }
 
     private void captureKeyguardStateControllerCallback() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
index 2b51863..b50d248 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
@@ -15,14 +15,14 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.utils.GlobalWindowManager
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -42,8 +42,7 @@
 class ResourceTrimmerTest : SysuiTestCase() {
     val kosmos = testKosmos()
 
-    private val testDispatcher = UnconfinedTestDispatcher()
-    private val testScope = TestScope(testDispatcher)
+    private val testScope = kosmos.testScope
     private val keyguardRepository = kosmos.fakeKeyguardRepository
     private val featureFlags = kosmos.fakeFeatureFlagsClassic
     private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
@@ -63,8 +62,8 @@
 
         val withDeps =
             KeyguardInteractorFactory.create(
-                repository = keyguardRepository,
                 featureFlags = featureFlags,
+                repository = keyguardRepository,
             )
         val keyguardInteractor = withDeps.keyguardInteractor
         resourceTrimmer =
@@ -74,7 +73,7 @@
                 kosmos.keyguardTransitionInteractor,
                 globalWindowManager,
                 testScope.backgroundScope,
-                testDispatcher,
+                kosmos.testDispatcher,
                 featureFlags
             )
         resourceTrimmer.start()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt
index d75cbec..9aac8e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt
@@ -21,7 +21,10 @@
 import com.android.keyguard.ClockEventController
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
+import com.android.systemui.res.R
 import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth
@@ -49,6 +52,7 @@
     private lateinit var fakeSettings: FakeSettings
     @Mock private lateinit var clockRegistry: ClockRegistry
     @Mock private lateinit var clockEventController: ClockEventController
+    private val fakeFeatureFlagsClassic = FakeFeatureFlagsClassic()
 
     @Before
     fun setup() {
@@ -63,7 +67,9 @@
                 clockRegistry,
                 clockEventController,
                 dispatcher,
-                scope.backgroundScope
+                scope.backgroundScope,
+                context,
+                fakeFeatureFlagsClassic,
             )
     }
 
@@ -72,7 +78,7 @@
         scope.runTest {
             fakeSettings.putInt(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 0)
             val value = collectLastValue(underTest.selectedClockSize)
-            Truth.assertThat(value()).isEqualTo(SettingsClockSize.SMALL)
+            Truth.assertThat(value()).isEqualTo(ClockSizeSetting.SMALL)
         }
 
     @Test
@@ -80,6 +86,14 @@
         scope.runTest {
             fakeSettings.putInt(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1)
             val value = collectLastValue(underTest.selectedClockSize)
-            Truth.assertThat(value()).isEqualTo(SettingsClockSize.DYNAMIC)
+            Truth.assertThat(value()).isEqualTo(ClockSizeSetting.DYNAMIC)
+        }
+
+    @Test
+    fun testShouldForceSmallClock() =
+        scope.runTest {
+            overrideResource(R.bool.force_small_clock_on_lockscreen, true)
+            fakeFeatureFlagsClassic.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true)
+            Truth.assertThat(underTest.shouldForceSmallClock).isTrue()
         }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
index 9266af4..472d045 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
@@ -40,9 +41,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.testKosmos
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -86,9 +85,6 @@
 
     @Before
     fun setup() {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-        kosmos.fakeSceneContainerFlags.enabled = false
-
         primaryBouncerInteractor =
             PrimaryBouncerInteractor(
                 bouncerRepository,
@@ -127,7 +123,6 @@
                 testScope.backgroundScope,
                 mContext,
                 deviceEntryFingerprintAuthRepository,
-                kosmos.fakeSceneContainerFlags,
                 kosmos.sceneInteractor,
                 primaryBouncerInteractor,
                 alternateBouncerInteractor,
@@ -168,15 +163,14 @@
         }
 
     @Test
+    @EnableSceneContainer
     fun updatesShowIndicatorForDeviceEntry_onBouncerSceneActive() =
         testScope.runTest {
-            kosmos.fakeSceneContainerFlags.enabled = true
             underTest =
                 DeviceEntrySideFpsOverlayInteractor(
                     testScope.backgroundScope,
                     mContext,
                     deviceEntryFingerprintAuthRepository,
-                    kosmos.fakeSceneContainerFlags,
                     kosmos.sceneInteractor,
                     primaryBouncerInteractor,
                     alternateBouncerInteractor,
@@ -196,15 +190,14 @@
         }
 
     @Test
+    @EnableSceneContainer
     fun updatesShowIndicatorForDeviceEntry_onBouncerSceneInactive() =
         testScope.runTest {
-            kosmos.fakeSceneContainerFlags.enabled = true
             underTest =
                 DeviceEntrySideFpsOverlayInteractor(
                     testScope.backgroundScope,
                     mContext,
                     deviceEntryFingerprintAuthRepository,
-                    kosmos.fakeSceneContainerFlags,
                     kosmos.sceneInteractor,
                     primaryBouncerInteractor,
                     alternateBouncerInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
index 0a7e72c..6f17c55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
@@ -36,6 +36,7 @@
 import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.widget.lockPatternUtils
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
@@ -53,6 +54,7 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.whenever
 import junit.framework.Assert.assertEquals
 import kotlin.test.Test
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -61,6 +63,7 @@
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.spy
 
@@ -300,4 +303,32 @@
             assertThat(transitionRepository)
                 .startedTransition(from = KeyguardState.AOD, to = KeyguardState.OCCLUDED)
         }
+
+    @Test
+    fun testTransitionToGone_onWakeUpFromAod_dismissibleKeyguard_securityNone() =
+        testScope.runTest {
+            whenever(kosmos.lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(true)
+            kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
+            powerInteractor.setAwakeForTest()
+            testScope.testScheduler.advanceTimeBy(100) // account for debouncing
+            runCurrent()
+
+            // We should head back to GONE since we started there.
+            assertThat(transitionRepository)
+                .startedTransition(from = KeyguardState.AOD, to = KeyguardState.GONE)
+        }
+
+    @Test
+    fun testTransitionToGone_onWakeUpFromAod_dismissibleKeyguard_securitySwipe() =
+        testScope.runTest {
+            whenever(kosmos.lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false)
+            kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
+            powerInteractor.setAwakeForTest()
+            testScope.testScheduler.advanceTimeBy(100) // account for debouncing
+            runCurrent()
+
+            // We should head back to GONE since we started there.
+            assertThat(transitionRepository)
+                .startedTransition(from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN)
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
index f534ba5..8435a03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
@@ -37,6 +37,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -160,4 +161,17 @@
                     to = KeyguardState.LOCKSCREEN,
                 )
         }
+
+    @Test
+    fun testTransitionToAlternateBouncer() =
+        testScope.runTest {
+            kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(true)
+            runCurrent()
+
+            assertThat(transitionRepository)
+                .startedTransition(
+                    from = KeyguardState.DREAMING,
+                    to = KeyguardState.ALTERNATE_BOUNCER,
+                )
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
index b6b4571..ac5823e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
@@ -24,17 +24,18 @@
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID
 import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
 import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.clocks.ClockConfig
 import com.android.systemui.plugins.clocks.ClockController
-import com.android.systemui.res.R
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
@@ -63,17 +64,24 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
+        whenever(clockController.config).thenReturn(ClockConfig("TEST", "Test", ""))
+        fingerprintPropertyRepository.setProperties(
+            sensorId = 1,
+            strength = SensorStrength.STRONG,
+            sensorType = FingerprintSensorType.POWER_BUTTON,
+            sensorLocations = mapOf()
+        )
     }
 
     @Test
     fun testAppliesDefaultBlueprint() {
         testScope.runTest {
-            val blueprint by collectLastValue(underTest.blueprint)
-            overrideResource(R.bool.config_use_split_notification_shade, false)
+            val blueprintId by collectLastValue(underTest.blueprintId)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
             configurationRepository.onConfigurationChange()
             runCurrent()
 
-            assertThat(blueprint?.id).isEqualTo(DefaultKeyguardBlueprint.Companion.DEFAULT)
+            assertThat(blueprintId).isEqualTo(DefaultKeyguardBlueprint.Companion.DEFAULT)
         }
     }
 
@@ -81,12 +89,12 @@
     @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
     fun testAppliesSplitShadeBlueprint() {
         testScope.runTest {
-            val blueprint by collectLastValue(underTest.blueprint)
-            overrideResource(R.bool.config_use_split_notification_shade, true)
+            val blueprintId by collectLastValue(underTest.blueprintId)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
             configurationRepository.onConfigurationChange()
             runCurrent()
 
-            assertThat(blueprint?.id).isEqualTo(SplitShadeKeyguardBlueprint.Companion.ID)
+            assertThat(blueprintId).isEqualTo(SplitShadeKeyguardBlueprint.Companion.ID)
         }
     }
 
@@ -94,77 +102,12 @@
     @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
     fun fingerprintPropertyInitialized_updatesBlueprint() {
         testScope.runTest {
-            val blueprint by collectLastValue(underTest.blueprint)
-            overrideResource(R.bool.config_use_split_notification_shade, true)
+            val blueprintId by collectLastValue(underTest.blueprintId)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
             fingerprintPropertyRepository.supportsUdfps() // initialize properties
             runCurrent()
-            assertThat(blueprint?.id).isEqualTo(SplitShadeKeyguardBlueprint.Companion.ID)
-        }
-    }
 
-    @Test
-    @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
-    fun composeLockscreenOff_DoesAppliesSplitShadeWeatherClockBlueprint() {
-        testScope.runTest {
-            val blueprint by collectLastValue(underTest.blueprint)
-            whenever(clockController.config)
-                .thenReturn(
-                    ClockConfig(
-                        id = "DIGITAL_CLOCK_WEATHER",
-                        name = "clock",
-                        description = "clock",
-                    )
-                )
-            clockRepository.setCurrentClock(clockController)
-            overrideResource(R.bool.config_use_split_notification_shade, true)
-            configurationRepository.onConfigurationChange()
-            runCurrent()
-
-            assertThat(blueprint?.id).isNotEqualTo(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID)
-        }
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
-    fun testDoesAppliesSplitShadeWeatherClockBlueprint() {
-        testScope.runTest {
-            val blueprint by collectLastValue(underTest.blueprint)
-            whenever(clockController.config)
-                .thenReturn(
-                    ClockConfig(
-                        id = "DIGITAL_CLOCK_WEATHER",
-                        name = "clock",
-                        description = "clock",
-                    )
-                )
-            clockRepository.setCurrentClock(clockController)
-            overrideResource(R.bool.config_use_split_notification_shade, true)
-            configurationRepository.onConfigurationChange()
-            runCurrent()
-
-            assertThat(blueprint?.id).isEqualTo(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID)
-        }
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
-    fun testAppliesWeatherClockBlueprint() {
-        testScope.runTest {
-            val blueprint by collectLastValue(underTest.blueprint)
-            whenever(clockController.config)
-                .thenReturn(
-                    ClockConfig(
-                        id = "DIGITAL_CLOCK_WEATHER",
-                        name = "clock",
-                        description = "clock",
-                    )
-                )
-            clockRepository.setCurrentClock(clockController)
-            overrideResource(R.bool.config_use_split_notification_shade, false)
-            configurationRepository.onConfigurationChange()
-            runCurrent()
-
-            assertThat(blueprint?.id).isEqualTo(WEATHER_CLOCK_BLUEPRINT_ID)
+            assertThat(blueprintId).isEqualTo(SplitShadeKeyguardBlueprint.Companion.ID)
         }
     }
 
@@ -172,13 +115,13 @@
     @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
     fun testDoesNotApplySplitShadeBlueprint() {
         testScope.runTest {
-            overrideResource(R.bool.config_use_split_notification_shade, true)
-            val blueprint by collectLastValue(underTest.blueprint)
+            val blueprintId by collectLastValue(underTest.blueprintId)
+            kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
             clockRepository.setCurrentClock(clockController)
             configurationRepository.onConfigurationChange()
             runCurrent()
 
-            assertThat(blueprint?.id).isEqualTo(DefaultKeyguardBlueprint.DEFAULT)
+            assertThat(blueprintId).isEqualTo(DefaultKeyguardBlueprint.DEFAULT)
         }
     }
 }
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 45b2a42..96b7596 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
@@ -43,6 +43,7 @@
 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.scene.domain.interactor.sceneInteractor
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
@@ -329,6 +330,7 @@
                 biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
+                sceneInteractor = { kosmos.sceneInteractor },
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
index 3f05bfa..9ccf212 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
@@ -19,6 +19,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -227,4 +228,50 @@
                 { it == KeyguardSurfaceBehindModel(alpha = 0f) },
             )
         }
+
+    @Test
+    fun notificationLaunchFromLockscreen_isAnimatingSurfaceTrue() =
+        testScope.runTest {
+            val isAnimatingSurface by collectLastValue(underTest.isAnimatingSurface)
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.GONE,
+                    to = KeyguardState.LOCKSCREEN,
+                    transitionState = TransitionState.STARTED,
+                )
+            )
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.GONE,
+                    to = KeyguardState.LOCKSCREEN,
+                    transitionState = TransitionState.FINISHED,
+                )
+            )
+            kosmos.notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(true)
+            runCurrent()
+            assertThat(isAnimatingSurface).isTrue()
+        }
+
+    @Test
+    fun notificationLaunchFromGone_isAnimatingSurfaceFalse() =
+        testScope.runTest {
+            val isAnimatingSurface by collectLastValue(underTest.isAnimatingSurface)
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.GONE,
+                    transitionState = TransitionState.STARTED,
+                )
+            )
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.GONE,
+                    transitionState = TransitionState.FINISHED,
+                )
+            )
+            kosmos.notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(true)
+            runCurrent()
+            assertThat(isAnimatingSurface).isFalse()
+        }
 }
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 2c0a518..3827046 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
@@ -27,6 +27,8 @@
 import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.communal.domain.interactor.communalInteractor
 import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.dock.DockManager
+import com.android.systemui.dock.fakeDockManager
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.fakeCommandQueue
@@ -108,6 +110,7 @@
 
     private val powerInteractor = kosmos.powerInteractor
     private val communalInteractor = kosmos.communalInteractor
+    private val dockManager = kosmos.fakeDockManager
 
     @Before
     fun setUp() {
@@ -752,35 +755,6 @@
         }
 
     @Test
-    fun goneToDreamingLockscreenHosted() =
-        testScope.runTest {
-            // GIVEN a device that is not dreaming or dozing
-            keyguardRepository.setDreamingWithOverlay(false)
-            keyguardRepository.setDozeTransitionModel(
-                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
-            )
-            runCurrent()
-
-            // GIVEN a prior transition has run to GONE
-            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
-
-            // WHEN the device begins to dream with the lockscreen hosted dream
-            keyguardRepository.setDreamingWithOverlay(true)
-            keyguardRepository.setIsActiveDreamLockscreenHosted(true)
-            advanceTimeBy(100L)
-
-            assertThat(transitionRepository)
-                .startedTransition(
-                    to = KeyguardState.DREAMING_LOCKSCREEN_HOSTED,
-                    from = KeyguardState.GONE,
-                    ownerName = "FromGoneTransitionInteractor",
-                    animatorAssertion = { it.isNotNull() }
-                )
-
-            coroutineContext.cancelChildren()
-        }
-
-    @Test
     fun goneToGlanceableHub() =
         testScope.runTest {
             // GIVEN a prior transition has run to GONE
@@ -923,6 +897,31 @@
         }
 
     @Test
+    fun alternateBouncerToGone() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to ALTERNATE_BOUNCER
+            bouncerRepository.setAlternateVisible(true)
+            runTransitionAndSetWakefulness(
+                KeyguardState.LOCKSCREEN,
+                KeyguardState.ALTERNATE_BOUNCER
+            )
+
+            // GIVEN the keyguard is going away
+            keyguardRepository.setKeyguardGoingAway(true)
+            runCurrent()
+
+            assertThat(transitionRepository)
+                .startedTransition(
+                    ownerName = "FromAlternateBouncerTransitionInteractor",
+                    from = KeyguardState.ALTERNATE_BOUNCER,
+                    to = KeyguardState.GONE,
+                    animatorAssertion = { it.isNotNull() },
+                )
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
     fun alternateBouncerToGlanceableHub() =
         testScope.runTest {
             // GIVEN a prior transition has run to ALTERNATE_BOUNCER
@@ -1230,6 +1229,44 @@
         }
 
     @Test
+    fun occludedToGlanceableHubWhenDocked() =
+        testScope.runTest {
+            // GIVEN a device on lockscreen
+            keyguardRepository.setKeyguardShowing(true)
+            runCurrent()
+
+            // GIVEN a prior transition has run to OCCLUDED
+            runTransitionAndSetWakefulness(KeyguardState.GLANCEABLE_HUB, KeyguardState.OCCLUDED)
+            keyguardRepository.setKeyguardOccluded(true)
+            runCurrent()
+
+            // GIVEN device is docked/communal is available
+            dockManager.setIsDocked(true)
+            dockManager.setDockEvent(DockManager.STATE_DOCKED)
+            val idleTransitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Idle(CommunalScenes.Communal)
+                )
+            communalInteractor.setTransitionState(idleTransitionState)
+            runCurrent()
+
+            // WHEN occlusion ends
+            keyguardRepository.setKeyguardOccluded(false)
+            runCurrent()
+
+            // THEN a transition to GLANCEABLE_HUB should occur
+            assertThat(transitionRepository)
+                .startedTransition(
+                    ownerName = FromOccludedTransitionInteractor::class.simpleName,
+                    from = KeyguardState.OCCLUDED,
+                    to = KeyguardState.GLANCEABLE_HUB,
+                    animatorAssertion = { it.isNotNull() },
+                )
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
     fun occludedToAlternateBouncer() =
         testScope.runTest {
             // GIVEN a prior transition has run to OCCLUDED
@@ -1337,6 +1374,8 @@
 
             // WHEN the keyguard is occluded and device wakes up and is no longer dreaming
             keyguardRepository.setDreaming(false)
+            testScheduler.advanceTimeBy(150) // The dreaming signal is debounced.
+            runCurrent()
             keyguardRepository.setKeyguardOccluded(true)
             powerInteractor.setAwakeForTest()
             runCurrent()
@@ -1344,7 +1383,7 @@
             // THEN a transition to OCCLUDED should occur
             assertThat(transitionRepository)
                 .startedTransition(
-                    ownerName = "FromDreamingTransitionInteractor",
+                    ownerName = "FromDreamingTransitionInteractor(Occluded but no longer dreaming)",
                     from = KeyguardState.DREAMING,
                     to = KeyguardState.OCCLUDED,
                     animatorAssertion = { it.isNotNull() },
@@ -1354,6 +1393,30 @@
         }
 
     @Test
+    fun dreamingToPrimaryBouncer() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to DREAMING
+            keyguardRepository.setDreaming(true)
+            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.DREAMING)
+            runCurrent()
+
+            // WHEN the primary bouncer is set to show
+            bouncerRepository.setPrimaryShow(true)
+            runCurrent()
+
+            // THEN a transition to PRIMARY_BOUNCER should occur
+            assertThat(transitionRepository)
+                .startedTransition(
+                    ownerName = "FromDreamingTransitionInteractor",
+                    from = KeyguardState.DREAMING,
+                    to = KeyguardState.PRIMARY_BOUNCER,
+                    animatorAssertion = { it.isNotNull() },
+                )
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
     fun dreamingToAod() =
         testScope.runTest {
             // GIVEN a prior transition has run to DREAMING
@@ -1457,7 +1520,7 @@
             // THEN a transition to OCCLUDED should occur
             assertThat(transitionRepository)
                 .startedTransition(
-                    ownerName = "FromAodTransitionInteractor",
+                    ownerName = "FromAodTransitionInteractor(isOccluded = true)",
                     from = KeyguardState.AOD,
                     to = KeyguardState.OCCLUDED,
                     animatorAssertion = { it.isNotNull() },
@@ -1496,7 +1559,8 @@
             runTransitionAndSetWakefulness(KeyguardState.AOD, KeyguardState.LOCKSCREEN)
             runCurrent()
 
-            // WHEN the device begins to sleep (first power button press)...
+            // WHEN the device begins to sleep (first power button press), which starts
+            // LS -> DOZING...
             powerInteractor.setAsleepForTest()
             runCurrent()
             reset(transitionRepository)
@@ -1509,11 +1573,11 @@
             }
             runCurrent()
 
-            // THEN a transition from LOCKSCREEN => OCCLUDED should occur
+            // THEN a transition from DOZING => OCCLUDED should occur
             assertThat(transitionRepository)
                 .startedTransition(
-                    ownerName = "FromLockscreenTransitionInteractor",
-                    from = KeyguardState.LOCKSCREEN,
+                    ownerName = "FromDozingTransitionInteractor",
+                    from = KeyguardState.DOZING,
                     to = KeyguardState.OCCLUDED,
                     animatorAssertion = { it.isNotNull() },
                 )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
index 6d605a5..b1a8dd1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
@@ -281,6 +281,14 @@
             // Oh no, we're still surfaceBehindAnimating=true, but no longer transitioning to GONE.
             transitionRepository.sendTransitionStep(
                 TransitionStep(
+                    transitionState = TransitionState.CANCELED,
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.GONE,
+                )
+            )
+            runCurrent()
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
                     transitionState = TransitionState.STARTED,
                     from = KeyguardState.LOCKSCREEN,
                     to = KeyguardState.AOD,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
deleted file mode 100644
index f0607f4..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.ui
-
-import androidx.test.filters.SmallTest
-import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
-import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
-import com.android.systemui.keyguard.shared.model.TransitionState
-import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlin.time.Duration.Companion.milliseconds
-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.junit.runners.JUnit4
-
-@SmallTest
-@RunWith(JUnit4::class)
-class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
-    val kosmos = testKosmos()
-    val testScope = kosmos.testScope
-    val animationFlow = kosmos.keyguardTransitionAnimationFlow
-    val repository = kosmos.fakeKeyguardTransitionRepository
-
-    private lateinit var underTest: KeyguardTransitionAnimationFlow.FlowBuilder
-
-    @Before
-    fun setUp() {
-        underTest =
-            animationFlow.setup(
-                duration = 1000.milliseconds,
-                from = GONE,
-                to = DREAMING,
-            )
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun zeroDurationThrowsException() =
-        testScope.runTest {
-            val flow = underTest.sharedFlow(duration = 0.milliseconds, onStep = { it })
-        }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun startTimePlusDurationGreaterThanTransitionDurationThrowsException() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    startTime = 300.milliseconds,
-                    duration = 800.milliseconds,
-                    onStep = { it }
-                )
-        }
-
-    @Test
-    fun onFinishRunsWhenSpecified() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    duration = 100.milliseconds,
-                    onStep = { it },
-                    onFinish = { 10f },
-                )
-            var animationValues = collectLastValue(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(1f, TransitionState.FINISHED), validateStep = false)
-            assertThat(animationValues()).isEqualTo(10f)
-        }
-
-    @Test
-    fun onCancelRunsWhenSpecified() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    duration = 100.milliseconds,
-                    onStep = { it },
-                    onCancel = { 100f },
-                )
-            var animationValues = collectLastValue(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
-            assertThat(animationValues()).isEqualTo(100f)
-        }
-
-    @Test
-    fun usesStartTime() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    startTime = 500.milliseconds,
-                    duration = 500.milliseconds,
-                    onStep = { it },
-                )
-            var animationValues = collectLastValue(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
-            assertThat(animationValues()).isEqualTo(0f)
-
-            // Should not emit a value
-            repository.sendTransitionStep(step(0.1f, TransitionState.RUNNING))
-
-            repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
-            assertFloat(animationValues(), 0f)
-            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
-            assertFloat(animationValues(), 0.2f)
-            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
-            assertFloat(animationValues(), 0.6f)
-            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
-            assertFloat(animationValues(), 1f)
-        }
-
-    @Test
-    fun usesInterpolator() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    duration = 1000.milliseconds,
-                    interpolator = EMPHASIZED_ACCELERATE,
-                    onStep = { it },
-                )
-            var animationValues = collectLastValue(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
-            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0f))
-            repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
-            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.5f))
-            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
-            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.6f))
-            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
-            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.8f))
-            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
-            assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(1f))
-        }
-
-    @Test
-    fun usesOnStepToDoubleValue() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    duration = 1000.milliseconds,
-                    onStep = { it * 2 },
-                )
-            val animationValues by collectLastValue(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
-            assertFloat(animationValues, 0f)
-            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
-            assertFloat(animationValues, 0.6f)
-            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
-            assertFloat(animationValues, 1.2f)
-            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
-            assertFloat(animationValues, 1.6f)
-            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
-            assertFloat(animationValues, 2f)
-        }
-
-    @Test
-    fun usesOnStepToDoubleValueWithState() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlowWithState(
-                    duration = 1000.milliseconds,
-                    onStep = { it * 2 },
-                )
-            val animationValues by collectLastValue(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
-            assertThat(animationValues)
-                .isEqualTo(
-                    StateToValue(
-                        from = GONE,
-                        to = DREAMING,
-                        transitionState = TransitionState.STARTED,
-                        value = 0f
-                    )
-                )
-            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
-            assertThat(animationValues)
-                .isEqualTo(
-                    StateToValue(
-                        from = GONE,
-                        to = DREAMING,
-                        transitionState = TransitionState.RUNNING,
-                        value = 0.6f
-                    )
-                )
-            repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
-            assertThat(animationValues)
-                .isEqualTo(
-                    StateToValue(
-                        from = GONE,
-                        to = DREAMING,
-                        transitionState = TransitionState.RUNNING,
-                        value = 1.2f
-                    )
-                )
-            repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
-            assertThat(animationValues)
-                .isEqualTo(
-                    StateToValue(
-                        from = GONE,
-                        to = DREAMING,
-                        transitionState = TransitionState.RUNNING,
-                        value = 1.6f
-                    )
-                )
-            repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
-            assertThat(animationValues)
-                .isEqualTo(
-                    StateToValue(
-                        from = GONE,
-                        to = DREAMING,
-                        transitionState = TransitionState.RUNNING,
-                        value = 2f
-                    )
-                )
-            repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
-            assertThat(animationValues)
-                .isEqualTo(
-                    StateToValue(
-                        from = GONE,
-                        to = DREAMING,
-                        transitionState = TransitionState.FINISHED,
-                        value = null
-                    )
-                )
-        }
-
-    @Test
-    fun sameFloatValueWithTheSameTransitionStateDoesNotEmitTwice() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    duration = 1000.milliseconds,
-                    onStep = { it },
-                )
-            val values by collectValues(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
-            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
-
-            assertThat(values.size).isEqualTo(1)
-            assertThat(values[0]).isEqualTo(0.3f)
-        }
-
-    @Test
-    fun sameFloatValueWithADifferentTransitionStateDoesEmitTwice() =
-        testScope.runTest {
-            val flow =
-                underTest.sharedFlow(
-                    duration = 1000.milliseconds,
-                    onStep = { it },
-                )
-            val values by collectValues(flow)
-            runCurrent()
-
-            repository.sendTransitionStep(step(0.3f, TransitionState.STARTED))
-            repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
-
-            assertThat(values.size).isEqualTo(2)
-            assertThat(values[0]).isEqualTo(0.3f)
-            assertThat(values[0]).isEqualTo(0.3f)
-        }
-
-    private fun assertFloat(actual: Float?, expected: Float) {
-        assertThat(actual!!).isWithin(0.01f).of(expected)
-    }
-
-    private fun step(
-        value: Float,
-        state: TransitionState = TransitionState.RUNNING
-    ): TransitionStep {
-        return TransitionStep(
-            from = GONE,
-            to = DREAMING,
-            value = value,
-            transitionState = state,
-            ownerName = "GoneToDreamingTransitionViewModelTest"
-        )
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
index 66aa572..2f650c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
@@ -24,6 +24,7 @@
 import com.android.keyguard.KeyguardClockSwitch.LARGE
 import com.android.keyguard.KeyguardClockSwitch.SMALL
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
 import com.android.systemui.plugins.clocks.ClockConfig
 import com.android.systemui.plugins.clocks.ClockController
@@ -53,7 +54,7 @@
     @Mock private lateinit var smallClockFaceLayout: ClockFaceLayout
     @Mock private lateinit var largeClockFaceLayout: ClockFaceLayout
     @Mock private lateinit var clockViewModel: KeyguardClockViewModel
-    private val clockSize = MutableStateFlow(LARGE)
+    private val clockSize = MutableStateFlow(ClockSize.LARGE)
     private val currentClock: MutableStateFlow<ClockController?> = MutableStateFlow(null)
 
     @Before
@@ -82,8 +83,7 @@
     @Test
     fun addClockViewsToBurnInLayer_LargeWeatherClock() {
         setupWeatherClock()
-        clockSize.value = LARGE
-        KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel)
+        KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel, ClockSize.LARGE)
         verify(burnInLayer).removeView(smallClockView)
         verify(burnInLayer).addView(largeClockView)
     }
@@ -91,8 +91,7 @@
     @Test
     fun addClockViewsToBurnInLayer_LargeNonWeatherClock() {
         setupNonWeatherClock()
-        clockSize.value = LARGE
-        KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel)
+        KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel, ClockSize.LARGE)
         verify(burnInLayer).removeView(smallClockView)
         verify(burnInLayer, never()).addView(largeClockView)
     }
@@ -100,8 +99,7 @@
     @Test
     fun addClockViewsToBurnInLayer_SmallClock() {
         setupNonWeatherClock()
-        clockSize.value = SMALL
-        KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel)
+        KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel, ClockSize.SMALL)
         verify(burnInLayer).addView(smallClockView)
         verify(burnInLayer).removeView(largeClockView)
     }
@@ -113,7 +111,8 @@
                 id = "WEATHER_CLOCK",
                 name = "",
                 description = "",
-                useAlternateSmartspaceAODTransition = true
+                useAlternateSmartspaceAODTransition = true,
+                useCustomClockScene = true
             )
         whenever(clock.config).thenReturn(clockConfig)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
index 9c7f254..616aac7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.keyguard.ui.view.KeyguardRootView
+import com.android.systemui.keyguard.ui.view.layout.sections.AccessibilityActionsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
 import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
@@ -58,6 +59,7 @@
 class DefaultKeyguardBlueprintTest : SysuiTestCase() {
     private lateinit var underTest: DefaultKeyguardBlueprint
     private lateinit var rootView: KeyguardRootView
+    @Mock private lateinit var accessibilityActionsSection: AccessibilityActionsSection
     @Mock private lateinit var defaultIndicationAreaSection: DefaultIndicationAreaSection
     @Mock private lateinit var mDefaultDeviceEntrySection: DefaultDeviceEntrySection
     @Mock private lateinit var defaultShortcutsSection: DefaultShortcutsSection
@@ -81,6 +83,7 @@
         rootView = KeyguardRootView(context, null)
         underTest =
             DefaultKeyguardBlueprint(
+                accessibilityActionsSection,
                 defaultIndicationAreaSection,
                 mDefaultDeviceEntrySection,
                 defaultShortcutsSection,
@@ -102,7 +105,7 @@
     @Test
     fun replaceViews() {
         val constraintLayout = ConstraintLayout(context, null)
-        underTest.replaceViews(null, constraintLayout)
+        underTest.replaceViews(constraintLayout)
         underTest.sections.forEach { verify(it)?.addViews(constraintLayout) }
     }
 
@@ -113,7 +116,7 @@
         whenever(prevBlueprint.sections)
             .thenReturn(underTest.sections.minus(mDefaultDeviceEntrySection).plus(someSection))
         val constraintLayout = ConstraintLayout(context, null)
-        underTest.replaceViews(prevBlueprint, constraintLayout)
+        underTest.replaceViews(constraintLayout, prevBlueprint)
         underTest.sections.minus(mDefaultDeviceEntrySection).forEach {
             verify(it, never())?.addViews(constraintLayout)
         }
@@ -125,7 +128,7 @@
     @Test
     fun deviceEntryIconIsOnTop() {
         val constraintLayout = ConstraintLayout(context, null)
-        underTest.replaceViews(null, constraintLayout)
+        underTest.replaceViews(constraintLayout)
         underTest.sections.forEach { verify(it)?.addViews(constraintLayout) }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
index 2ca5aef..ba2efe6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
@@ -24,243 +24,297 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.customization.R as customR
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardBlueprintInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardSmartspaceInteractor
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.ui.viewmodel.keyguardClockViewModel
+import com.android.systemui.keyguard.ui.viewmodel.keyguardSmartspaceViewModel
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.shared.model.ShadeMode
-import com.android.systemui.util.Utils
+import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
+import com.android.systemui.statusbar.policy.fakeConfigurationController
+import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
-import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.anyString
-import org.mockito.Mock
 import org.mockito.MockitoAnnotations
 
 @RunWith(JUnit4::class)
 @SmallTest
 class ClockSectionTest : SysuiTestCase() {
-    @Mock private lateinit var keyguardClockInteractor: KeyguardClockInteractor
-    @Mock private lateinit var keyguardClockViewModel: KeyguardClockViewModel
-    @Mock private lateinit var shadeInteractor: ShadeInteractor
-    @Mock private lateinit var smartspaceViewModel: KeyguardSmartspaceViewModel
-    @Mock private lateinit var blueprintInteractor: Lazy<KeyguardBlueprintInteractor>
-    private val bcSmartspaceVisibility: MutableStateFlow<Int> = MutableStateFlow(VISIBLE)
-    private val clockShouldBeCentered: MutableStateFlow<Boolean> = MutableStateFlow(true)
-    private val isAodIconsVisible: MutableStateFlow<Boolean> = MutableStateFlow(true)
-    private val shadeMode: MutableStateFlow<ShadeMode> = MutableStateFlow(ShadeMode.Single)
-
     private lateinit var underTest: ClockSection
 
-    private val SMALL_CLOCK_TOP_SPLIT_SHADE =
-        context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)
+    private val LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE: Int
+        get() =
+            kosmos.fakeSystemBarUtilsProxy.getStatusBarHeight() +
+                context.resources.getDimensionPixelSize(customR.dimen.small_clock_padding_top) +
+                context.resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset)
 
-    private val SMALL_CLOCK_TOP_NON_SPLIT_SHADE =
-        context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
-            Utils.getStatusBarHeaderHeightKeyguard(context)
+    private val LARGE_CLOCK_TOP
+        get() =
+            LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE +
+                SMART_SPACE_DATE_WEATHER_HEIGHT +
+                ENHANCED_SMART_SPACE_HEIGHT
 
-    private val LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE =
-        context.resources.getDimensionPixelSize(R.dimen.status_bar_height) +
-            context.resources.getDimensionPixelSize(
-                com.android.systemui.customization.R.dimen.small_clock_padding_top
-            ) +
-            context.resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset)
+    private val CLOCK_FADE_TRANSLATION_Y
+        get() = context.resources.getDimensionPixelSize(customR.dimen.small_clock_height)
 
-    private val LARGE_CLOCK_TOP =
-        LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE +
-            SMART_SPACE_DATE_WEATHER_HEIGHT +
-            ENHANCED_SMART_SPACE_HEIGHT
-
-    private val CLOCK_FADE_TRANSLATION_Y =
-        context.resources.getDimensionPixelSize(
-            com.android.systemui.customization.R.dimen.small_clock_height
-        )
-
-    private var DIMENSION_BY_IDENTIFIER_NAME: List<Pair<String, Int>> = listOf()
+    private var DIMENSION_BY_IDENTIFIER: List<Pair<String, Int>> = listOf()
+    private lateinit var kosmos: Kosmos
 
     @Before
     fun setup() {
-        DIMENSION_BY_IDENTIFIER_NAME =
+        DIMENSION_BY_IDENTIFIER =
             listOf(
                 "date_weather_view_height" to SMART_SPACE_DATE_WEATHER_HEIGHT,
                 "enhanced_smartspace_height" to ENHANCED_SMART_SPACE_HEIGHT,
             )
 
         MockitoAnnotations.initMocks(this)
-        val remoteResources = mock<Resources>()
-        whenever(remoteResources.getIdentifier(anyString(), eq("dimen"), anyString())).then {
-            invocation ->
-            val name = invocation.arguments[0] as String
-            val index = DIMENSION_BY_IDENTIFIER_NAME.indexOfFirst { (key, _) -> key == name }
-            // increment index so that the not-found sentinel value lines up w/ what is
-            // returned by getIdentifier when a resource is not found
-            index + 1
-        }
-        whenever(remoteResources.getDimensionPixelSize(anyInt())).then { invocation ->
-            val id = invocation.arguments[0] as Int
-            DIMENSION_BY_IDENTIFIER_NAME[id - 1].second
-        }
-        val packageManager = mock<PackageManager>()
-        whenever(packageManager.getResourcesForApplication(anyString())).thenReturn(remoteResources)
-        mContext.setMockPackageManager(packageManager)
-
-        whenever(keyguardClockViewModel.clockShouldBeCentered).thenReturn(clockShouldBeCentered)
-        whenever(keyguardClockViewModel.isAodIconsVisible).thenReturn(isAodIconsVisible)
-        whenever(shadeInteractor.shadeMode).thenReturn(shadeMode)
-        whenever(keyguardClockViewModel.shadeInteractor).thenReturn(shadeInteractor)
-        whenever(smartspaceViewModel.bcSmartspaceVisibility).thenReturn(bcSmartspaceVisibility)
-
-        underTest =
-            ClockSection(
-                keyguardClockInteractor,
-                keyguardClockViewModel,
-                context,
-                smartspaceViewModel,
-                blueprintInteractor
-            )
-    }
-
-    @Test
-    fun testApplyDefaultConstraints_LargeClock_SplitShade() {
-        setLargeClock(true)
-        setSplitShade(true)
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-
-        val expectedLargeClockTopMargin = LARGE_CLOCK_TOP
-        assertLargeClockTop(cs, expectedLargeClockTopMargin)
-
-        val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_SPLIT_SHADE
-        assertSmallClockTop(cs)
-    }
-
-    @Test
-    fun testApplyDefaultConstraints_LargeClock_NonSplitShade() {
-        setLargeClock(true)
-        setSplitShade(false)
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-
-        val expectedLargeClockTopMargin = LARGE_CLOCK_TOP
-        assertLargeClockTop(cs, expectedLargeClockTopMargin)
-
-        val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_NON_SPLIT_SHADE
-        assertSmallClockTop(cs)
-    }
-
-    @Test
-    fun testApplyDefaultConstraints_LargeClock_MissingSmartspace_SplitShade() {
-        DIMENSION_BY_IDENTIFIER_NAME = listOf() // Remove Smartspace from mock
-        setLargeClock(true)
-        setSplitShade(true)
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-
-        val expectedLargeClockTopMargin = LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE
-        assertLargeClockTop(cs, expectedLargeClockTopMargin)
-
-        val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_SPLIT_SHADE
-        assertSmallClockTop(cs)
-    }
-
-    @Test
-    fun testApplyDefaultConstraints_LargeClock_MissingSmartspace_NonSplitShade() {
-        DIMENSION_BY_IDENTIFIER_NAME = listOf() // Remove Smartspace from mock
-        setLargeClock(true)
-        setSplitShade(false)
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-
-        val expectedLargeClockTopMargin = LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE
-        assertLargeClockTop(cs, expectedLargeClockTopMargin)
-
-        val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_NON_SPLIT_SHADE
-        assertSmallClockTop(cs)
-    }
-
-    @Test
-    fun testApplyDefaultConstraints_SmallClock_SplitShade() {
-        setLargeClock(false)
-        setSplitShade(true)
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-
-        val expectedLargeClockTopMargin = LARGE_CLOCK_TOP
-        assertLargeClockTop(cs, expectedLargeClockTopMargin)
-
-        val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_SPLIT_SHADE
-        assertSmallClockTop(cs)
-    }
-
-    @Test
-    fun testApplyDefaultConstraints_SmallClock_NonSplitShade() {
-        setLargeClock(false)
-        setSplitShade(false)
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-        val expectedLargeClockTopMargin = LARGE_CLOCK_TOP
-        assertLargeClockTop(cs, expectedLargeClockTopMargin)
-
-        val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_NON_SPLIT_SHADE
-        assertSmallClockTop(cs)
-    }
-
-    @Test
-    fun testSmartspaceVisible_weatherClockDateAndIconsBarrierBottomBelowBCSmartspace() {
-        isAodIconsVisible.value = false
-        bcSmartspaceVisibility.value = VISIBLE
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-        val referencedIds = cs.getReferencedIds(R.id.weather_clock_date_and_icons_barrier_bottom)
-        referencedIds.contentEquals(intArrayOf(com.android.systemui.shared.R.id.bc_smartspace_view))
-    }
-
-    @Test
-    fun testSmartspaceGone_weatherClockDateAndIconsBarrierBottomBelowSmartspaceDateWeather() {
-        isAodIconsVisible.value = false
-        bcSmartspaceVisibility.value = GONE
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-        val referencedIds = cs.getReferencedIds(R.id.weather_clock_date_and_icons_barrier_bottom)
-        referencedIds.contentEquals(intArrayOf(R.id.lockscreen_clock_view))
-    }
-
-    @Test
-    fun testHasAodIcons_weatherClockDateAndIconsBarrierBottomBelowSmartspaceDateWeather() {
-        isAodIconsVisible.value = true
-        val cs = ConstraintSet()
-        underTest.applyDefaultConstraints(cs)
-        val referencedIds = cs.getReferencedIds(R.id.weather_clock_date_and_icons_barrier_bottom)
-        referencedIds.contentEquals(
-            intArrayOf(
-                com.android.systemui.shared.R.id.bc_smartspace_view,
-                R.id.aod_notification_icon_container
-            )
+        val remoteResources =
+            mock<Resources>().apply {
+                whenever(getIdentifier(anyString(), eq("dimen"), anyString())).then { invocation ->
+                    val name = invocation.arguments[0] as String
+                    val index = DIMENSION_BY_IDENTIFIER.indexOfFirst { (key, _) -> key == name }
+                    // increment index so that the not-found sentinel value lines up w/ what is
+                    // returned by getIdentifier when a resource is not found
+                    index + 1
+                }
+                whenever(getDimensionPixelSize(anyInt())).then { invocation ->
+                    val id = invocation.arguments[0] as Int
+                    DIMENSION_BY_IDENTIFIER[id - 1].second
+                }
+            }
+        mContext.setMockPackageManager(
+            mock<PackageManager>().apply {
+                whenever(getResourcesForApplication(anyString())).thenReturn(remoteResources)
+            }
         )
-    }
 
-    private fun setLargeClock(useLargeClock: Boolean) {
-        whenever(keyguardClockViewModel.useLargeClock).thenReturn(useLargeClock)
-    }
-
-    private fun setSplitShade(isInSplitShade: Boolean) {
-        if (isInSplitShade) {
-            shadeMode.value = ShadeMode.Split
-        } else {
-            shadeMode.value = ShadeMode.Single
+        kosmos = testKosmos()
+        with(kosmos) {
+            underTest =
+                ClockSection(
+                    keyguardClockInteractor,
+                    keyguardClockViewModel,
+                    context,
+                    keyguardSmartspaceViewModel,
+                    { keyguardBlueprintInteractor },
+                )
         }
     }
 
+    @Test
+    fun testApplyDefaultConstraints_LargeClock_SplitShade() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                keyguardClockInteractor.setClockSize(ClockSize.LARGE)
+                advanceUntilIdle()
+            }
+
+            val cs = ConstraintSet()
+            underTest.applyDefaultConstraints(cs)
+
+            assertLargeClockTop(cs, LARGE_CLOCK_TOP)
+            assertSmallClockTop(cs)
+        }
+
+    @Test
+    fun testApplyDefaultConstraints_LargeClock_NonSplitShade() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+                val isLargeClockVisible by
+                    collectLastValue(keyguardClockViewModel.isLargeClockVisible)
+
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                keyguardClockInteractor.setClockSize(ClockSize.LARGE)
+                fakeKeyguardRepository.setClockShouldBeCentered(true)
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+
+                val cs = ConstraintSet()
+                underTest.applyDefaultConstraints(cs)
+
+                assertLargeClockTop(cs, LARGE_CLOCK_TOP)
+                assertSmallClockTop(cs)
+            }
+        }
+
+    @Test
+    fun testApplyDefaultConstraints_LargeClock_MissingSmartspace_SplitShade() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                DIMENSION_BY_IDENTIFIER = listOf() // Remove Smartspace from mock
+                val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+                val isLargeClockVisible by
+                    collectLastValue(keyguardClockViewModel.isLargeClockVisible)
+
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                keyguardClockInteractor.setClockSize(ClockSize.LARGE)
+                fakeKeyguardRepository.setClockShouldBeCentered(true)
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+
+                val cs = ConstraintSet()
+                underTest.applyDefaultConstraints(cs)
+
+                assertLargeClockTop(cs, LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE)
+                assertSmallClockTop(cs)
+            }
+        }
+
+    @Test
+    fun testApplyDefaultConstraints_LargeClock_MissingSmartspace_NonSplitShade() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                DIMENSION_BY_IDENTIFIER = listOf() // Remove Smartspace from mock
+                val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+                val isLargeClockVisible by
+                    collectLastValue(keyguardClockViewModel.isLargeClockVisible)
+
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                keyguardClockInteractor.setClockSize(ClockSize.LARGE)
+                fakeKeyguardRepository.setClockShouldBeCentered(true)
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+
+                val cs = ConstraintSet()
+                underTest.applyDefaultConstraints(cs)
+
+                assertLargeClockTop(cs, LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE)
+                assertSmallClockTop(cs)
+            }
+        }
+
+    @Test
+    fun testApplyDefaultConstraints_SmallClock_SplitShade() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+                val isLargeClockVisible by
+                    collectLastValue(keyguardClockViewModel.isLargeClockVisible)
+
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                keyguardClockInteractor.setClockSize(ClockSize.SMALL)
+                fakeKeyguardRepository.setClockShouldBeCentered(true)
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+
+                val cs = ConstraintSet()
+                underTest.applyDefaultConstraints(cs)
+
+                assertLargeClockTop(cs, LARGE_CLOCK_TOP)
+                assertSmallClockTop(cs)
+            }
+        }
+
+    @Test
+    fun testApplyDefaultConstraints_SmallClock_NonSplitShade() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+                val isLargeClockVisible by
+                    collectLastValue(keyguardClockViewModel.isLargeClockVisible)
+
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                keyguardClockInteractor.setClockSize(ClockSize.SMALL)
+                fakeKeyguardRepository.setClockShouldBeCentered(true)
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+
+                val cs = ConstraintSet()
+                underTest.applyDefaultConstraints(cs)
+                assertLargeClockTop(cs, LARGE_CLOCK_TOP)
+                assertSmallClockTop(cs)
+            }
+        }
+
+    @Test
+    fun testSmartspaceVisible_weatherClockDateAndIconsBarrierBottomBelowBCSmartspace() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(VISIBLE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+            }
+
+            val cs = ConstraintSet()
+            underTest.applyDefaultConstraints(cs)
+            val referencedIds =
+                cs.getReferencedIds(R.id.weather_clock_date_and_icons_barrier_bottom)
+            referencedIds.contentEquals(
+                intArrayOf(com.android.systemui.shared.R.id.bc_smartspace_view)
+            )
+        }
+
+    @Test
+    fun testSmartspaceGone_weatherClockDateAndIconsBarrierBottomBelowSmartspaceDateWeather() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
+                keyguardSmartspaceInteractor.setBcSmartspaceVisibility(GONE)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+            }
+
+            val cs = ConstraintSet()
+            underTest.applyDefaultConstraints(cs)
+            val referencedIds =
+                cs.getReferencedIds(R.id.weather_clock_date_and_icons_barrier_bottom)
+            referencedIds.contentEquals(intArrayOf(R.id.lockscreen_clock_view))
+        }
+
+    @Test
+    fun testHasAodIcons_weatherClockDateAndIconsBarrierBottomBelowSmartspaceDateWeather() =
+        kosmos.testScope.runTest {
+            with(kosmos) {
+                notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+                fakeConfigurationController.notifyConfigurationChanged()
+                advanceUntilIdle()
+            }
+
+            val cs = ConstraintSet()
+            underTest.applyDefaultConstraints(cs)
+            val referencedIds =
+                cs.getReferencedIds(R.id.weather_clock_date_and_icons_barrier_bottom)
+            referencedIds.contentEquals(
+                intArrayOf(
+                    com.android.systemui.shared.R.id.bc_smartspace_view,
+                    R.id.aod_notification_icon_container
+                )
+            )
+        }
+
     private fun assertLargeClockTop(cs: ConstraintSet, expectedLargeClockTopMargin: Int) {
         val largeClockConstraint = cs.getConstraint(R.id.lockscreen_clock_view_large)
         assertThat(largeClockConstraint.layout.topToTop).isEqualTo(ConstraintSet.PARENT_ID)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index b5f668c..4f2b690 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -38,7 +38,6 @@
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.TestScope
@@ -86,7 +85,6 @@
                 { mock(DeviceEntryBackgroundViewModel::class.java) },
                 { falsingManager },
                 { mock(VibratorHelper::class.java) },
-                mock(CoroutineDispatcher::class.java),
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
index d410dac..f1c93c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
@@ -32,7 +32,6 @@
 import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -67,7 +66,7 @@
     fun transitionToAlternateBouncer_scrimAlphaUpdate() =
         testScope.runTest {
             val scrimAlphas by collectValues(underTest.scrimAlpha)
-            runCurrent()
+            assertThat(scrimAlphas.size).isEqualTo(1) // initial value is 0f
 
             transitionRepository.sendTransitionSteps(
                 listOf(
@@ -79,7 +78,7 @@
                 testScope,
             )
 
-            assertThat(scrimAlphas.size).isEqualTo(4)
+            assertThat(scrimAlphas.size).isEqualTo(5)
             scrimAlphas.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
         }
 
@@ -87,7 +86,7 @@
     fun transitionFromAlternateBouncer_scrimAlphaUpdate() =
         testScope.runTest {
             val scrimAlphas by collectValues(underTest.scrimAlpha)
-            runCurrent()
+            assertThat(scrimAlphas.size).isEqualTo(1) // initial value is 0f
 
             transitionRepository.sendTransitionSteps(
                 listOf(
@@ -98,7 +97,7 @@
                 ),
                 testScope,
             )
-            assertThat(scrimAlphas.size).isEqualTo(4)
+            assertThat(scrimAlphas.size).isEqualTo(5)
             scrimAlphas.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt
index 143c4da..1396b20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModelTest.kt
@@ -57,11 +57,18 @@
                     stepFromAlternateBouncer(0f, TransitionState.STARTED),
                     stepFromAlternateBouncer(.4f),
                     stepFromAlternateBouncer(.6f),
-                    stepFromAlternateBouncer(1f),
                 ),
                 testScope,
             )
             assertThat(alternateBouncerWindowRequired).isTrue()
+
+            transitionRepository.sendTransitionSteps(
+                listOf(
+                    stepFromAlternateBouncer(1.0f, TransitionState.FINISHED),
+                ),
+                testScope,
+            )
+            assertThat(alternateBouncerWindowRequired).isFalse()
         }
 
     @Test
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 7290863..6b317ea 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
@@ -52,6 +52,7 @@
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.domain.interactor.shadeInteractor
@@ -233,6 +234,7 @@
                         biometricSettingsRepository = biometricSettingsRepository,
                         backgroundDispatcher = testDispatcher,
                         appContext = mContext,
+                        sceneInteractor = { kosmos.sceneInteractor },
                     ),
                 bottomAreaInteractor = KeyguardBottomAreaInteractor(repository = repository),
                 burnInHelperWrapper = burnInHelperWrapper,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
index 7b5dd1f..1d98dc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -12,44 +12,36 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF 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 android.provider.Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import androidx.test.filters.SmallTest
-import com.android.keyguard.ClockEventController
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.keyguard.KeyguardClockSwitch.SMALL
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
-import com.android.systemui.keyguard.data.repository.KeyguardClockRepositoryImpl
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
-import com.android.systemui.keyguard.shared.ComposeLockscreen
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel.ClockLayout
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.clocks.ClockConfig
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockFaceConfig
 import com.android.systemui.plugins.clocks.ClockFaceController
 import com.android.systemui.res.R
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.shared.model.ShadeMode
-import com.android.systemui.shared.clocks.ClockRegistry
-import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
-import com.android.systemui.util.Utils
+import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import kotlin.test.Test
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestCoroutineScheduler
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.runner.RunWith
@@ -59,144 +51,230 @@
 
 @SmallTest
 @RunWith(JUnit4::class)
+@DisableSceneContainer
 class KeyguardClockViewModelTest : SysuiTestCase() {
-    private lateinit var scheduler: TestCoroutineScheduler
-    private lateinit var dispatcher: CoroutineDispatcher
-    private lateinit var scope: TestScope
-    private lateinit var underTest: KeyguardClockViewModel
-    private lateinit var keyguardInteractor: KeyguardInteractor
-    private lateinit var keyguardRepository: KeyguardRepository
-    private lateinit var keyguardClockInteractor: KeyguardClockInteractor
-    private lateinit var keyguardClockRepository: KeyguardClockRepository
-    private lateinit var fakeSettings: FakeSettings
-    private val shadeMode = MutableStateFlow<ShadeMode>(ShadeMode.Single)
-    @Mock private lateinit var clockRegistry: ClockRegistry
-    @Mock private lateinit var clock: ClockController
-    @Mock private lateinit var largeClock: ClockFaceController
-    @Mock private lateinit var clockFaceConfig: ClockFaceConfig
-    @Mock private lateinit var eventController: ClockEventController
-    @Mock private lateinit var notifsKeyguardInteractor: NotificationsKeyguardInteractor
-    @Mock private lateinit var areNotificationsFullyHidden: Flow<Boolean>
-    @Mock private lateinit var shadeInteractor: ShadeInteractor
+    val kosmos = testKosmos()
+    val testScope = kosmos.testScope
+    val underTest = kosmos.keyguardClockViewModel
+    val res = context.resources
+
+    @Mock lateinit var clockController: ClockController
+    @Mock lateinit var largeClock: ClockFaceController
+    @Mock lateinit var smallClock: ClockFaceController
+
+    var config = ClockConfig("TEST", "Test", "")
+    var faceConfig = ClockFaceConfig()
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        KeyguardInteractorFactory.create().let {
-            keyguardInteractor = it.keyguardInteractor
-            keyguardRepository = it.repository
-        }
-        fakeSettings = FakeSettings()
-        scheduler = TestCoroutineScheduler()
-        dispatcher = StandardTestDispatcher(scheduler)
-        scope = TestScope(dispatcher)
-        setupMockClock()
-        keyguardClockRepository =
-            KeyguardClockRepositoryImpl(
-                fakeSettings,
-                clockRegistry,
-                eventController,
-                dispatcher,
-                scope.backgroundScope
-            )
-        keyguardClockInteractor = KeyguardClockInteractor(keyguardClockRepository)
-        whenever(notifsKeyguardInteractor.areNotificationsFullyHidden)
-            .thenReturn(areNotificationsFullyHidden)
-        whenever(shadeInteractor.shadeMode).thenReturn(shadeMode)
-        underTest =
-            KeyguardClockViewModel(
-                keyguardInteractor,
-                keyguardClockInteractor,
-                scope.backgroundScope,
-                notifsKeyguardInteractor,
-                shadeInteractor,
-            )
+
+        whenever(clockController.largeClock).thenReturn(largeClock)
+        whenever(clockController.smallClock).thenReturn(smallClock)
+        whenever(clockController.config).thenAnswer { config }
+        whenever(largeClock.config).thenAnswer { faceConfig }
+        whenever(smallClock.config).thenAnswer { faceConfig }
     }
 
     @Test
-    fun testClockSize_alwaysSmallClock() =
-        scope.runTest {
-            // When use double line clock is disabled,
-            // should always return small
-            fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 0)
-            keyguardClockRepository.setClockSize(LARGE)
-            val value = collectLastValue(underTest.clockSize)
-            assertThat(value()).isEqualTo(SMALL)
+    fun currentClockLayout_splitShadeOn_clockCentered_largeClock() =
+        testScope.runTest {
+            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
+
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                keyguardRepository.setClockShouldBeCentered(true)
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+            }
+
+            assertThat(currentClockLayout).isEqualTo(ClockLayout.LARGE_CLOCK)
+        }
+
+    @Test
+    fun currentClockLayout_splitShadeOn_clockNotCentered_largeClock_splitShadeLargeClock() =
+        testScope.runTest {
+            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
+
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                keyguardRepository.setClockShouldBeCentered(false)
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+            }
+
+            assertThat(currentClockLayout).isEqualTo(ClockLayout.SPLIT_SHADE_LARGE_CLOCK)
+        }
+
+    @Test
+    fun currentClockLayout_splitShadeOn_clockNotCentered_smallClock_splitShadeSmallClock() =
+        testScope.runTest {
+            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
+
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                keyguardRepository.setClockShouldBeCentered(false)
+                keyguardClockRepository.setClockSize(ClockSize.SMALL)
+            }
+
+            assertThat(currentClockLayout).isEqualTo(ClockLayout.SPLIT_SHADE_SMALL_CLOCK)
+        }
+
+    @Test
+    fun currentClockLayout_singleShade_smallClock_smallClock() =
+        testScope.runTest {
+            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
+
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                keyguardClockRepository.setClockSize(ClockSize.SMALL)
+            }
+
+            assertThat(currentClockLayout).isEqualTo(ClockLayout.SMALL_CLOCK)
+        }
+
+    @Test
+    fun currentClockLayout_singleShade_largeClock_largeClock() =
+        testScope.runTest {
+            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
+
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+            }
+
+            assertThat(currentClockLayout).isEqualTo(ClockLayout.LARGE_CLOCK)
+        }
+
+    @Test
+    fun hasCustomPositionUpdatedAnimation_withConfigTrue_isTrue() =
+        testScope.runTest {
+            val hasCustomPositionUpdatedAnimation by
+                collectLastValue(underTest.hasCustomPositionUpdatedAnimation)
+
+            with(kosmos) {
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+                faceConfig = ClockFaceConfig(hasCustomPositionUpdatedAnimation = true)
+                fakeKeyguardClockRepository.setCurrentClock(clockController)
+            }
+
+            assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(true)
+        }
+
+    @Test
+    fun hasCustomPositionUpdatedAnimation_withConfigFalse_isFalse() =
+        testScope.runTest {
+            val hasCustomPositionUpdatedAnimation by
+                collectLastValue(underTest.hasCustomPositionUpdatedAnimation)
+
+            with(kosmos) {
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+                faceConfig = ClockFaceConfig(hasCustomPositionUpdatedAnimation = false)
+                fakeKeyguardClockRepository.setCurrentClock(clockController)
+            }
+
+            assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(false)
+        }
+
+    @Test
+    fun testClockSize_alwaysSmallClockSize() =
+        testScope.runTest {
+            val value by collectLastValue(underTest.clockSize)
+
+            with(kosmos) {
+                fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.SMALL)
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+            }
+
+            assertThat(value).isEqualTo(ClockSize.SMALL)
         }
 
     @Test
     fun testClockSize_dynamicClockSize() =
-        scope.runTest {
-            fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1)
-            keyguardClockRepository.setClockSize(SMALL)
-            var value = collectLastValue(underTest.clockSize)
-            assertThat(value()).isEqualTo(SMALL)
+        testScope.runTest {
+            with(kosmos) {
+                val value by collectLastValue(underTest.clockSize)
+                fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.DYNAMIC)
 
-            keyguardClockRepository.setClockSize(LARGE)
-            value = collectLastValue(underTest.clockSize)
-            assertThat(value()).isEqualTo(LARGE)
+                keyguardClockRepository.setClockSize(ClockSize.SMALL)
+                assertThat(value).isEqualTo(ClockSize.SMALL)
+
+                keyguardClockRepository.setClockSize(ClockSize.LARGE)
+                assertThat(value).isEqualTo(ClockSize.LARGE)
+            }
         }
 
     @Test
     fun isLargeClockVisible_whenLargeClockSize_isTrue() =
-        scope.runTest {
-            fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1)
-            keyguardClockRepository.setClockSize(LARGE)
-            var value = collectLastValue(underTest.isLargeClockVisible)
-            assertThat(value()).isEqualTo(true)
+        testScope.runTest {
+            val value by collectLastValue(underTest.isLargeClockVisible)
+            kosmos.keyguardClockRepository.setClockSize(ClockSize.LARGE)
+            assertThat(value).isEqualTo(true)
         }
 
     @Test
     fun isLargeClockVisible_whenSmallClockSize_isFalse() =
-        scope.runTest {
-            fakeSettings.putInt(LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1)
-            keyguardClockRepository.setClockSize(SMALL)
-            var value = collectLastValue(underTest.isLargeClockVisible)
-            assertThat(value()).isEqualTo(false)
+        testScope.runTest {
+            val value by collectLastValue(underTest.isLargeClockVisible)
+            kosmos.keyguardClockRepository.setClockSize(ClockSize.SMALL)
+            assertThat(value).isEqualTo(false)
         }
 
     @Test
-    fun testSmallClockTop_splitshade() =
-        scope.runTest {
-            shadeMode.value = ShadeMode.Split
-            if (!ComposeLockscreen.isEnabled) {
-                assertThat(underTest.getSmallClockTopMargin(context))
-                    .isEqualTo(
-                        context.resources.getDimensionPixelSize(
-                            R.dimen.keyguard_split_shade_top_margin
-                        )
-                    )
-            } else {
-                assertThat(underTest.getSmallClockTopMargin(context))
-                    .isEqualTo(
-                        context.resources.getDimensionPixelSize(
-                            R.dimen.keyguard_split_shade_top_margin
-                        ) - Utils.getStatusBarHeaderHeightKeyguard(context)
-                    )
+    @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+    fun testSmallClockTop_splitShade_composeLockscreenOn() =
+        testScope.runTest {
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
             }
+
+            val expected =
+                res.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) -
+                    KEYGUARD_STATUS_BAR_HEIGHT
+            assertThat(underTest.getSmallClockTopMargin()).isEqualTo(expected)
         }
 
     @Test
-    fun testSmallClockTop_nonSplitshade() =
-        scope.runTest {
-            if (!ComposeLockscreen.isEnabled) {
-                assertThat(underTest.getSmallClockTopMargin(context))
-                    .isEqualTo(
-                        context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
-                            Utils.getStatusBarHeaderHeightKeyguard(context)
-                    )
-            } else {
-                assertThat(underTest.getSmallClockTopMargin(context))
-                    .isEqualTo(
-                        context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)
-                    )
+    @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+    fun testSmallClockTop_splitShade_composeLockscreenOff() =
+        testScope.runTest {
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Split)
+                fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
             }
+
+            assertThat(underTest.getSmallClockTopMargin())
+                .isEqualTo(res.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin))
         }
 
-    private fun setupMockClock() {
-        whenever(clock.largeClock).thenReturn(largeClock)
-        whenever(largeClock.config).thenReturn(clockFaceConfig)
-        whenever(clockFaceConfig.hasCustomWeatherDataDisplay).thenReturn(false)
-        whenever(clockRegistry.createCurrentClock()).thenReturn(clock)
+    @Test
+    @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+    fun testSmallClockTop_nonSplitShade_composeLockscreenOn() =
+        testScope.runTest {
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
+            }
+
+            assertThat(underTest.getSmallClockTopMargin())
+                .isEqualTo(res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin))
+        }
+
+    @Test
+    @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+    fun testSmallClockTop_nonSplitShade_composeLockscreenOff() =
+        testScope.runTest {
+            with(kosmos) {
+                shadeRepository.setShadeMode(ShadeMode.Single)
+                fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
+            }
+
+            val expected =
+                res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
+                    KEYGUARD_STATUS_BAR_HEIGHT
+            assertThat(underTest.getSmallClockTopMargin()).isEqualTo(expected)
+        }
+
+    companion object {
+        private const val KEYGUARD_STATUS_BAR_HEIGHT = 20
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelWithKosmosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelWithKosmosTest.kt
deleted file mode 100644
index d12980a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelWithKosmosTest.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.ui.viewmodel
-
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardClockSwitch
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
-import com.android.systemui.keyguard.data.repository.keyguardClockRepository
-import com.android.systemui.keyguard.data.repository.keyguardRepository
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.plugins.clocks.ClockController
-import com.android.systemui.plugins.clocks.ClockFaceConfig
-import com.android.systemui.plugins.clocks.ClockFaceController
-import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
-import com.android.systemui.testKosmos
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.Test
-import kotlinx.coroutines.test.runTest
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.Mockito.mock
-
-@SmallTest
-@RunWith(JUnit4::class)
-class KeyguardClockViewModelWithKosmosTest : SysuiTestCase() {
-    private val kosmos = testKosmos()
-    private val underTest = kosmos.keyguardClockViewModel
-    private val testScope = kosmos.testScope
-
-    @Test
-    fun currentClockLayout_splitShadeOn_clockCentered_largeClock() =
-        testScope.runTest {
-            with(kosmos) {
-                shadeRepository.setShadeMode(ShadeMode.Split)
-                keyguardRepository.setClockShouldBeCentered(true)
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-            }
-            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
-            assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.LARGE_CLOCK)
-        }
-
-    @Test
-    fun currentClockLayout_splitShadeOn_clockNotCentered_largeClock_splitShadeLargeClock() =
-        testScope.runTest {
-            with(kosmos) {
-                shadeRepository.setShadeMode(ShadeMode.Split)
-                keyguardRepository.setClockShouldBeCentered(false)
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-            }
-            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
-            assertThat(currentClockLayout)
-                .isEqualTo(KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_LARGE_CLOCK)
-        }
-
-    @Test
-    fun currentClockLayout_splitShadeOn_clockNotCentered_smallClock_splitShadeSmallClock() =
-        testScope.runTest {
-            with(kosmos) {
-                shadeRepository.setShadeMode(ShadeMode.Split)
-                keyguardRepository.setClockShouldBeCentered(false)
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL)
-            }
-            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
-            assertThat(currentClockLayout)
-                .isEqualTo(KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_SMALL_CLOCK)
-        }
-
-    @Test
-    fun currentClockLayout_singleShade_smallClock_smallClock() =
-        testScope.runTest {
-            with(kosmos) {
-                shadeRepository.setShadeMode(ShadeMode.Single)
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.SMALL)
-            }
-            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
-            assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.SMALL_CLOCK)
-        }
-
-    @Test
-    fun currentClockLayout_singleShade_largeClock_largeClock() =
-        testScope.runTest {
-            with(kosmos) {
-                shadeRepository.setShadeMode(ShadeMode.Single)
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-            }
-            val currentClockLayout by collectLastValue(underTest.currentClockLayout)
-            assertThat(currentClockLayout).isEqualTo(KeyguardClockViewModel.ClockLayout.LARGE_CLOCK)
-        }
-
-    @Test
-    fun hasCustomPositionUpdatedAnimation_withConfigTrue_isTrue() =
-        testScope.runTest {
-            with(kosmos) {
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-                fakeKeyguardClockRepository.setCurrentClock(
-                    buildClockController(hasCustomPositionUpdatedAnimation = true)
-                )
-            }
-
-            val hasCustomPositionUpdatedAnimation by
-                collectLastValue(underTest.hasCustomPositionUpdatedAnimation)
-            assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(true)
-        }
-
-    @Test
-    fun hasCustomPositionUpdatedAnimation_withConfigFalse_isFalse() =
-        testScope.runTest {
-            with(kosmos) {
-                keyguardClockRepository.setClockSize(KeyguardClockSwitch.LARGE)
-                fakeKeyguardClockRepository.setCurrentClock(
-                    buildClockController(hasCustomPositionUpdatedAnimation = false)
-                )
-            }
-
-            val hasCustomPositionUpdatedAnimation by
-                collectLastValue(underTest.hasCustomPositionUpdatedAnimation)
-            assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(false)
-        }
-
-    private fun buildClockController(
-        hasCustomPositionUpdatedAnimation: Boolean = false
-    ): ClockController {
-        val clockController = mock(ClockController::class.java)
-        val largeClock = mock(ClockFaceController::class.java)
-        val config = mock(ClockFaceConfig::class.java)
-
-        whenever(clockController.largeClock).thenReturn(largeClock)
-        whenever(largeClock.config).thenReturn(config)
-        whenever(config.hasCustomPositionUpdatedAnimation)
-            .thenReturn(hasCustomPositionUpdatedAnimation)
-
-        return clockController
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index b80dcd4..83382207 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -49,13 +49,17 @@
 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.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -67,8 +71,6 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -141,9 +143,11 @@
         GlanceableHubToLockscreenTransitionViewModel
     @Mock private lateinit var transitionInteractor: KeyguardTransitionInteractor
 
+    private val kosmos = testKosmos()
+
     private lateinit var underTest: KeyguardQuickAffordancesCombinedViewModel
 
-    private lateinit var testScope: TestScope
+    private val testScope = kosmos.testScope
     private lateinit var repository: FakeKeyguardRepository
     private lateinit var homeControlsQuickAffordanceConfig: FakeKeyguardQuickAffordanceConfig
     private lateinit var quickAccessWalletAffordanceConfig: FakeKeyguardQuickAffordanceConfig
@@ -201,8 +205,6 @@
         whenever(userTracker.userHandle).thenReturn(mock())
         whenever(lockPatternUtils.getStrongAuthForUser(ArgumentMatchers.anyInt()))
             .thenReturn(LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED)
-        val testDispatcher = StandardTestDispatcher()
-        testScope = TestScope(testDispatcher)
 
         val localUserSelectionManager =
             KeyguardQuickAffordanceLocalUserSelectionManager(
@@ -238,7 +240,7 @@
                 legacySettingSyncer =
                     KeyguardQuickAffordanceLegacySettingSyncer(
                         scope = testScope.backgroundScope,
-                        backgroundDispatcher = testDispatcher,
+                        backgroundDispatcher = kosmos.testDispatcher,
                         secureSettings = FakeSettings(),
                         selectionsManager = localUserSelectionManager,
                     ),
@@ -301,8 +303,9 @@
                         devicePolicyManager = devicePolicyManager,
                         dockManager = dockManager,
                         biometricSettingsRepository = biometricSettingsRepository,
-                        backgroundDispatcher = testDispatcher,
+                        backgroundDispatcher = kosmos.testDispatcher,
                         appContext = mContext,
+                        sceneInteractor = { kosmos.sceneInteractor },
                     ),
                 keyguardInteractor = keyguardInteractor,
                 shadeInteractor = shadeInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
deleted file mode 100644
index a08e491..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.util
-
-import androidx.core.animation.ValueAnimator
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.TransitionInfo
-import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
-import com.google.common.truth.FailureMetadata
-import com.google.common.truth.Subject
-import com.google.common.truth.Truth
-import com.google.common.truth.Truth.assertAbout
-import junit.framework.Assert.assertEquals
-import kotlin.test.fail
-import org.mockito.Mockito
-
-/** [Subject] used to make assertions about a [Mockito.spy] KeyguardTransitionRepository. */
-class KeyguardTransitionRepositorySpySubject
-private constructor(
-    failureMetadata: FailureMetadata,
-    private val repository: KeyguardTransitionRepository,
-) : Subject(failureMetadata, repository) {
-
-    /**
-     * Asserts that we started a transition to the given state, optionally checking additional
-     * parameters. If an animator param or assertion is not provided, we will not assert anything
-     * about the animator.
-     */
-    suspend fun startedTransition(
-        ownerName: String? = null,
-        from: KeyguardState? = null,
-        to: KeyguardState,
-        modeOnCanceled: TransitionModeOnCanceled? = null,
-    ) {
-        startedTransition(ownerName, from, to, {}, modeOnCanceled)
-    }
-
-    /**
-     * Asserts that we started a transition to the given state, optionally verifying additional
-     * params.
-     */
-    suspend fun startedTransition(
-        ownerName: String? = null,
-        from: KeyguardState? = null,
-        to: KeyguardState,
-        animator: ValueAnimator?,
-        modeOnCanceled: TransitionModeOnCanceled? = null,
-    ) {
-        startedTransition(ownerName, from, to, { assertEquals(animator, it) }, modeOnCanceled)
-    }
-
-    /**
-     * Asserts that we started a transition to the given state, optionally verifying additional
-     * params.
-     */
-    suspend fun startedTransition(
-        ownerName: String? = null,
-        from: KeyguardState? = null,
-        to: KeyguardState,
-        animatorAssertion: (Subject) -> Unit,
-        modeOnCanceled: TransitionModeOnCanceled? = null,
-    ) {
-        // TODO(b/331799060): Remove this workaround once atest supports mocking suspend functions.
-        Mockito.mockingDetails(repository).invocations.forEach { invocation ->
-            if (invocation.method.equals(KeyguardTransitionRepository::startTransition.name)) {
-                val transitionInfo = invocation.arguments.firstOrNull() as TransitionInfo
-                assertEquals(to, transitionInfo.to)
-                animatorAssertion.invoke(Truth.assertThat(transitionInfo.animator))
-                from?.let { assertEquals(it, transitionInfo.from) }
-                ownerName?.let { assertEquals(it, transitionInfo.ownerName) }
-                modeOnCanceled?.let { assertEquals(it, transitionInfo.modeOnCanceled) }
-                invocation.markVerified()
-            }
-        }
-    }
-
-    /** Verifies that [KeyguardTransitionRepository.startTransition] was never called. */
-    suspend fun noTransitionsStarted() {
-        // TODO(b/331799060): Remove this workaround once atest supports mocking suspend functions.
-        Mockito.mockingDetails(repository).invocations.forEach {
-            if (
-                it.method.equals(KeyguardTransitionRepository::startTransition.name) &&
-                    !it.isVerified
-            ) {
-                fail(
-                    "Expected no transitions started, however this transition was started: " +
-                        it.arguments.firstOrNull()
-                )
-            }
-        }
-    }
-
-    companion object {
-        fun assertThat(
-            repository: KeyguardTransitionRepository
-        ): KeyguardTransitionRepositorySpySubject =
-            assertAbout { failureMetadata, repository: KeyguardTransitionRepository ->
-                    if (!Mockito.mockingDetails(repository).isSpy) {
-                        fail(
-                            "Cannot assert on a non-spy KeyguardTransitionRepository. " +
-                                "Use Mockito.spy(keyguardTransitionRepository)."
-                        )
-                    }
-                    KeyguardTransitionRepositorySpySubject(failureMetadata, repository)
-                }
-                .that(repository)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
index b70cc30..b3cfcf2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
@@ -28,8 +28,11 @@
 import com.android.systemui.media.controls.MediaTestUtils
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
 import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
 import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
 import com.android.systemui.media.controls.ui.controller.MediaPlayerData
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
@@ -53,7 +56,6 @@
 import org.mockito.ArgumentMatchers.anyLong
 import org.mockito.Mock
 import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -76,10 +78,10 @@
 @TestableLooper.RunWithLooper
 class MediaDataFilterImplTest : SysuiTestCase() {
 
-    @Mock private lateinit var listener: MediaDataFilterImpl.Listener
+    @Mock private lateinit var listener: MediaDataProcessor.Listener
     @Mock private lateinit var userTracker: UserTracker
     @Mock private lateinit var broadcastSender: BroadcastSender
-    @Mock private lateinit var mediaDataManager: MediaDataManager
+    @Mock private lateinit var mediaDataProcessor: MediaDataProcessor
     @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager
     @Mock private lateinit var executor: Executor
     @Mock private lateinit var smartspaceData: SmartspaceMediaData
@@ -89,7 +91,7 @@
     @Mock private lateinit var cardAction: SmartspaceAction
 
     private lateinit var mediaDataFilter: MediaDataFilterImpl
-    private lateinit var mediaFilterRepository: MediaFilterRepository
+    private lateinit var repository: MediaFilterRepository
     private lateinit var testScope: TestScope
     private lateinit var dataMain: MediaData
     private lateinit var dataGuest: MediaData
@@ -102,7 +104,7 @@
         MediaPlayerData.clear()
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
         testScope = TestScope()
-        mediaFilterRepository = MediaFilterRepository()
+        repository = MediaFilterRepository(FakeSystemClock())
         mediaDataFilter =
             MediaDataFilterImpl(
                 context,
@@ -113,9 +115,9 @@
                 clock,
                 logger,
                 mediaFlags,
-                mediaFilterRepository,
+                repository,
             )
-        mediaDataFilter.mediaDataManager = mediaDataManager
+        mediaDataFilter.mediaDataProcessor = mediaDataProcessor
         mediaDataFilter.addListener(listener)
 
         // Start all tests as main user
@@ -162,91 +164,141 @@
     }
 
     @Test
-    fun testOnDataLoadedForCurrentUser_callsListener() {
-        // GIVEN a media for main user
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+    fun onDataLoadedForCurrentUser_updatesLoadedStates() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val mediaCommonModel =
+                MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(dataMain.instanceId))
 
-        // THEN we should tell the listener
-        verify(listener).onMediaDataLoaded(eq(dataMain.instanceId), eq(true), eq(0), eq(false))
-    }
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+
+            verify(listener)
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true), eq(0), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(mediaCommonModel)
+        }
 
     @Test
-    fun testOnDataLoadedForGuest_doesNotCallListener() {
-        // GIVEN a media for guest user
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest)
+    fun onDataLoadedForGuest_doesNotUpdateLoadedStates() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val mediaCommonModel =
+                MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(dataMain.instanceId))
 
-        // THEN we should NOT tell the listener
-        verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean())
-    }
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest)
+
+            verify(listener, never())
+                .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean())
+            assertThat(sortedMedia?.values).doesNotContain(mediaCommonModel)
+        }
 
     @Test
-    fun testOnRemovedForCurrent_callsListener() {
-        // GIVEN a media was removed for main user
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
-        mediaDataFilter.onMediaDataRemoved(KEY)
+    fun onRemovedForCurrent_updatesLoadedStates() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val mediaCommonModel =
+                MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(dataMain.instanceId))
 
-        // THEN we should tell the listener
-        verify(listener).onMediaDataRemoved(eq(dataMain.instanceId))
-    }
+            // GIVEN a media was removed for main user
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+
+            assertThat(sortedMedia?.values).containsExactly(mediaCommonModel)
+
+            mediaDataFilter.onMediaDataRemoved(KEY)
+
+            verify(listener).onMediaDataRemoved(eq(KEY))
+            assertThat(sortedMedia?.values).doesNotContain(mediaCommonModel)
+        }
 
     @Test
-    fun testOnRemovedForGuest_doesNotCallListener() {
-        // GIVEN a media was removed for guest user
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest)
-        mediaDataFilter.onMediaDataRemoved(KEY)
+    fun onRemovedForGuest_doesNotUpdateLoadedStates() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
 
-        // THEN we should NOT tell the listener
-        verify(listener, never()).onMediaDataRemoved(eq(dataGuest.instanceId))
-    }
+            // GIVEN a media was removed for guest user
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest)
+            mediaDataFilter.onMediaDataRemoved(KEY)
+
+            verify(listener, never()).onMediaDataRemoved(eq(KEY))
+            assertThat(sortedMedia).isEmpty()
+        }
 
     @Test
-    fun testOnUserSwitched_removesOldUserControls() {
-        // GIVEN that we have a media loaded for main user
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+    fun onUserSwitched_removesOldUserControls() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val mediaLoaded = MediaDataLoadingModel.Loaded(dataMain.instanceId)
 
-        // and we switch to guest user
-        setUser(USER_GUEST)
+            // GIVEN that we have a media loaded for main user
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
 
-        // THEN we should remove the main user's media
-        verify(listener).onMediaDataRemoved(eq(dataMain.instanceId))
-    }
+            assertThat(sortedMedia?.values)
+                .containsExactly(MediaCommonModel.MediaControl(mediaLoaded))
+
+            // and we switch to guest user
+            setUser(USER_GUEST)
+
+            // THEN we should remove the main user's media
+            verify(listener).onMediaDataRemoved(eq(KEY))
+            assertThat(sortedMedia).isEmpty()
+        }
 
     @Test
-    fun testOnUserSwitched_addsNewUserControls() {
-        // GIVEN that we had some media for both users
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
-        mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataGuest)
-        reset(listener)
+    fun onUserSwitched_addsNewUserControls() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val guestLoadedStatesModel = MediaDataLoadingModel.Loaded(dataGuest.instanceId)
+            val mainLoadedStatesModel = MediaDataLoadingModel.Loaded(dataMain.instanceId)
 
-        // and we switch to guest user
-        setUser(USER_GUEST)
+            // GIVEN that we had some media for both users
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+            mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataGuest)
 
-        // THEN we should add back the guest user media
-        verify(listener).onMediaDataLoaded(eq(dataGuest.instanceId), eq(true), eq(0), eq(false))
+            // and we switch to guest user
+            setUser(USER_GUEST)
 
-        // but not the main user's
-        verify(listener, never())
-            .onMediaDataLoaded(eq(dataMain.instanceId), anyBoolean(), anyInt(), anyBoolean())
-    }
+            // THEN we should add back the guest user media
+            verify(listener)
+                .onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true), eq(0), eq(false))
+
+            // but not the main user's
+            verify(listener, never())
+                .onMediaDataLoaded(
+                    eq(KEY),
+                    any(),
+                    eq(dataMain),
+                    anyBoolean(),
+                    anyInt(),
+                    anyBoolean()
+                )
+            assertThat(sortedMedia?.values)
+                .containsExactly(MediaCommonModel.MediaControl(guestLoadedStatesModel))
+            assertThat(sortedMedia?.values)
+                .doesNotContain(MediaCommonModel.MediaControl(mainLoadedStatesModel))
+        }
 
     @Test
-    fun testOnProfileChanged_profileUnavailable_loadControls() {
-        // GIVEN that we had some media for both profiles
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
-        mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataPrivateProfile)
-        reset(listener)
+    fun onProfileChanged_profileUnavailable_updateStates() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
 
-        // and we change profile status
-        setPrivateProfileUnavailable()
+            // GIVEN that we had some media for both profiles
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+            mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataPrivateProfile)
 
-        // THEN we should add the private profile media
-        verify(listener).onMediaDataRemoved(eq(dataPrivateProfile.instanceId))
-    }
+            // and we change profile status
+            setPrivateProfileUnavailable()
+
+            val mediaLoadedStatesModel = MediaDataLoadingModel.Loaded(dataMain.instanceId)
+            // THEN we should remove the private profile media
+            verify(listener).onMediaDataRemoved(eq(KEY_ALT))
+            assertThat(sortedMedia?.values)
+                .containsExactly(MediaCommonModel.MediaControl(mediaLoadedStatesModel))
+        }
 
     @Test
     fun hasAnyMedia_mediaSet_returnsTrue() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain)
 
             assertThat(hasAnyMedia(selectedUserEntries)).isTrue()
@@ -255,7 +307,7 @@
     @Test
     fun hasAnyMedia_recommendationSet_returnsFalse() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
             assertThat(hasAnyMedia(selectedUserEntries)).isFalse()
@@ -264,8 +316,8 @@
     @Test
     fun hasAnyMediaOrRecommendation_mediaSet_returnsTrue() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain)
 
             assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData))
@@ -275,8 +327,8 @@
     @Test
     fun hasAnyMediaOrRecommendation_recommendationSet_returnsTrue() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
             assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData))
@@ -286,7 +338,7 @@
     @Test
     fun hasActiveMedia_inactiveMediaSet_returnsFalse() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
 
             val data = dataMain.copy(active = false)
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data)
@@ -297,7 +349,7 @@
     @Test
     fun hasActiveMedia_activeMediaSet_returnsTrue() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
             val data = dataMain.copy(active = true)
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data)
 
@@ -307,9 +359,9 @@
     @Test
     fun hasActiveMediaOrRecommendation_inactiveMediaSet_returnsFalse() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
             val data = dataMain.copy(active = false)
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data)
 
@@ -326,9 +378,9 @@
     @Test
     fun hasActiveMediaOrRecommendation_activeMediaSet_returnsTrue() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
             val data = dataMain.copy(active = true)
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data)
 
@@ -345,9 +397,9 @@
     @Test
     fun hasActiveMediaOrRecommendation_inactiveRecommendationSet_returnsFalse() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
             whenever(smartspaceData.isActive).thenReturn(false)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
@@ -364,9 +416,9 @@
     @Test
     fun hasActiveMediaOrRecommendation_invalidRecommendationSet_returnsFalse() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
             whenever(smartspaceData.isValid()).thenReturn(false)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
@@ -383,9 +435,9 @@
     @Test
     fun hasActiveMediaOrRecommendation_activeAndValidRecommendationSet_returnsTrue() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
             whenever(smartspaceData.isActive).thenReturn(true)
             whenever(smartspaceData.isValid()).thenReturn(true)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
@@ -401,10 +453,10 @@
         }
 
     @Test
-    fun testHasAnyMediaOrRecommendation_onlyCurrentUser() =
+    fun hasAnyMediaOrRecommendation_onlyCurrentUser() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
             assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData))
                 .isFalse()
 
@@ -415,11 +467,11 @@
         }
 
     @Test
-    fun testHasActiveMediaOrRecommendation_onlyCurrentUser() =
+    fun hasActiveMediaOrRecommendation_onlyCurrentUser() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -443,10 +495,10 @@
         }
 
     @Test
-    fun testOnNotificationRemoved_doesNotHaveMedia() =
+    fun onNotificationRemoved_doesNotHaveMedia() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
 
             mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain)
             mediaDataFilter.onMediaDataRemoved(KEY)
@@ -456,23 +508,27 @@
         }
 
     @Test
-    fun testOnSwipeToDismiss_setsTimedOut() {
+    fun onSwipeToDismiss_setsTimedOut() {
         mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
         mediaDataFilter.onSwipeToDismiss()
 
-        verify(mediaDataManager).setInactive(eq(KEY), eq(true), eq(true))
+        verify(mediaDataProcessor).setInactive(eq(KEY), eq(true), eq(true))
     }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_noMedia_activeValidRec_prioritizesSmartspace() =
+    fun onSmartspaceMediaDataLoaded_noMedia_activeValidRec_prioritizesSmartspace() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val recommendationsLoadingModel =
+                SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY, isPrioritized = true)
 
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(true))
+            assertThat(sortedMedia?.values)
+                .containsExactly(MediaCommonModel.MediaRecommendations(recommendationsLoadingModel))
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -482,23 +538,25 @@
                 )
                 .isTrue()
             assertThat(hasActiveMedia(selectedUserEntries)).isFalse()
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
             verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID)
             verify(logger, never()).logRecommendationActivated(any(), any(), any())
         }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_noMedia_inactiveRec_showsNothing() =
+    fun onSmartspaceMediaDataLoaded_noMedia_inactiveRec_showsNothing() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
 
             whenever(smartspaceData.isActive).thenReturn(false)
 
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean())
-            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean())
+            assertThat(sortedMedia).isEmpty()
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -508,22 +566,35 @@
                 )
                 .isFalse()
             assertThat(hasActiveMedia(selectedUserEntries)).isFalse()
+            verify(listener, never())
+                .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean())
+            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
             verify(logger, never()).logRecommendationAdded(any(), any())
             verify(logger, never()).logRecommendationActivated(any(), any(), any())
         }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_noRecentMedia_activeValidRec_prioritizesSmartspace() =
+    fun onSmartspaceMediaDataLoaded_noRecentMedia_activeValidRec_prioritizesSmartspace() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val recsCommonModel =
+                MediaCommonModel.MediaRecommendations(
+                    SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY, isPrioritized = true)
+                )
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
             val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataOld)
             clock.advanceTime(MediaDataFilterImpl.SMARTSPACE_MAX_AGE + 100)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(true))
+            assertThat(sortedMedia?.values).containsExactly(recsCommonModel, controlCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -533,16 +604,19 @@
                 )
                 .isTrue()
             assertThat(hasActiveMedia(selectedUserEntries)).isFalse()
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
             verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID)
             verify(logger, never()).logRecommendationActivated(any(), any(), any())
         }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_noRecentMedia_inactiveRec_showsNothing() =
+    fun onSmartspaceMediaDataLoaded_noRecentMedia_inactiveRec_showsNothing() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
             whenever(smartspaceData.isActive).thenReturn(false)
 
             val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
@@ -550,7 +624,12 @@
             clock.advanceTime(MediaDataFilterImpl.SMARTSPACE_MAX_AGE + 100)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean())
+            assertThat(sortedMedia?.values)
+                .doesNotContain(
+                    MediaCommonModel.MediaRecommendations(
+                        SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
+                    )
+                )
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -560,32 +639,39 @@
                 )
                 .isFalse()
             assertThat(hasActiveMedia(selectedUserEntries)).isFalse()
+            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
             verify(logger, never()).logRecommendationAdded(any(), any())
             verify(logger, never()).logRecommendationActivated(any(), any(), any())
         }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_inactiveRec_showsNothing() =
+    fun onSmartspaceMediaDataLoaded_hasRecentMedia_inactiveRec_showsNothing() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
 
             whenever(smartspaceData.isActive).thenReturn(false)
 
             // WHEN we have media that was recently played, but not currently active
             val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
-            verify(listener)
-                .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
 
-            reset(listener)
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
+            verify(listener)
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+
             // AND we get a smartspace signal
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            // THEN we should tell listeners to treat the media as not active instead
-            verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean())
-            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean())
+            // THEN we should treat the media as not active instead
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -595,32 +681,41 @@
                 )
                 .isFalse()
             assertThat(hasActiveMedia(selectedUserEntries)).isFalse()
+            verify(listener, never())
+                .onMediaDataLoaded(eq(KEY), eq(KEY), any(), anyBoolean(), anyInt(), anyBoolean())
+            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
             verify(logger, never()).logRecommendationAdded(any(), any())
             verify(logger, never()).logRecommendationActivated(any(), any(), any())
         }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_activeInvalidRec_usesMedia() =
+    fun onSmartspaceMediaDataLoaded_hasRecentMedia_activeInvalidRec_usesMedia() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
             whenever(smartspaceData.isValid()).thenReturn(false)
 
             // WHEN we have media that was recently played, but not currently active
             val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
 
             // AND we get a smartspace signal
             runCurrent()
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            // THEN we should tell listeners to treat the media as active instead
+            // THEN we should treat the media as active instead
             val dataCurrentAndActive = dataCurrent.copy(active = true)
-            verify(listener)
-                .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true))
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -629,32 +724,61 @@
                     )
                 )
                 .isTrue()
+            verify(listener)
+                .onMediaDataLoaded(
+                    eq(KEY),
+                    eq(KEY),
+                    eq(dataCurrentAndActive),
+                    eq(true),
+                    eq(100),
+                    eq(true)
+                )
             // Smartspace update shouldn't be propagated for the empty rec list.
-            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), anyBoolean())
+            verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
             verify(logger, never()).logRecommendationAdded(any(), any())
             verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID))
         }
 
     @Test
-    fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_activeValidRec_usesBoth() =
+    fun onSmartspaceMediaDataLoaded_hasRecentMedia_activeValidRec_usesBoth() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
             // WHEN we have media that was recently played, but not currently active
             val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
+            val recsCommonModel =
+                MediaCommonModel.MediaRecommendations(
+                    SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
+                )
+
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
 
             // AND we get a smartspace signal
             runCurrent()
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            // THEN we should tell listeners to treat the media as active instead
+            // THEN we should treat the media as active instead
             val dataCurrentAndActive = dataCurrent.copy(active = true)
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true))
+                .onMediaDataLoaded(
+                    eq(KEY),
+                    eq(KEY),
+                    eq(dataCurrentAndActive),
+                    eq(true),
+                    eq(100),
+                    eq(true)
+                )
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -664,22 +788,26 @@
                 )
                 .isTrue()
             // Smartspace update should also be propagated but not prioritized.
-            verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel, recsCommonModel)
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
             verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID)
             verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID))
         }
 
     @Test
-    fun testOnSmartspaceMediaDataRemoved_usedSmartspace_clearsSmartspace() =
+    fun onSmartspaceMediaDataRemoved_usedSmartspace_clearsSmartspace() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
 
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
             mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
 
             verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
+            assertThat(sortedMedia?.values).isEmpty()
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -692,26 +820,42 @@
         }
 
     @Test
-    fun testOnSmartspaceMediaDataRemoved_usedMediaAndSmartspace_clearsBoth() =
+    fun onSmartspaceMediaDataRemoved_usedMediaAndSmartspace_clearsBoth() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
             val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
 
             runCurrent()
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
             val dataCurrentAndActive = dataCurrent.copy(active = true)
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true))
+                .onMediaDataLoaded(
+                    eq(KEY),
+                    eq(KEY),
+                    eq(dataCurrentAndActive),
+                    eq(true),
+                    eq(100),
+                    eq(true)
+                )
 
             mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
 
             verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -724,17 +868,24 @@
         }
 
     @Test
-    fun testOnSmartspaceLoaded_persistentEnabled_isInactive_notifiesListeners() =
+    fun onSmartspaceLoaded_persistentEnabled_isInactive() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val recsCommonModel =
+                MediaCommonModel.MediaRecommendations(
+                    SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
+                )
             whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
             whenever(smartspaceData.isActive).thenReturn(false)
 
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false))
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(recsCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -748,11 +899,21 @@
         }
 
     @Test
-    fun testOnSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() =
+    fun onSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val recsCommonModel =
+                MediaCommonModel.MediaRecommendations(
+                    SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
+                )
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
 
             whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
             whenever(smartspaceData.isActive).thenReturn(false)
@@ -760,16 +921,20 @@
             // If there is media that was recently played but inactive
             val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
-            verify(listener)
-                .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
 
-            reset(listener)
+            verify(listener)
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
+
             // And an inactive recommendation is loaded
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
             // Smartspace is loaded but the media stays inactive
-            verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false))
-            verify(listener, never()).onMediaDataLoaded(any(), anyBoolean(), anyInt(), anyBoolean())
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+            verify(listener, never())
+                .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean())
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel, recsCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -783,7 +948,7 @@
         }
 
     @Test
-    fun testOnSwipeToDismiss_persistentEnabled_recommendationSetInactive() {
+    fun onSwipeToDismiss_persistentEnabled_recommendationSetInactive() {
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
 
         val data =
@@ -796,22 +961,34 @@
         mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, data)
         mediaDataFilter.onSwipeToDismiss()
 
-        verify(mediaDataManager).setRecommendationInactive(eq(SMARTSPACE_KEY))
-        verify(mediaDataManager, never())
+        verify(mediaDataProcessor).setRecommendationInactive(eq(SMARTSPACE_KEY))
+        verify(mediaDataProcessor, never())
             .dismissSmartspaceRecommendation(eq(SMARTSPACE_KEY), anyLong())
     }
 
     @Test
-    fun testSmartspaceLoaded_shouldTriggerResume_doesTrigger() =
+    fun smartspaceLoaded_shouldTriggerResume_doesTrigger() =
         testScope.runTest {
-            val selectedUserEntries by collectLastValue(mediaFilterRepository.selectedUserEntries)
-            val smartspaceMediaData by collectLastValue(mediaFilterRepository.smartspaceMediaData)
-            val reactivatedKey by collectLastValue(mediaFilterRepository.reactivatedId)
+            val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
+            val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
+            val reactivatedKey by collectLastValue(repository.reactivatedId)
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val recsCommonModel =
+                MediaCommonModel.MediaRecommendations(
+                    SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
+                )
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
             // WHEN we have media that was recently played, but not currently active
             val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
             mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
 
             // AND we get a smartspace signal with extra to trigger resume
             runCurrent()
@@ -819,10 +996,18 @@
             whenever(cardAction.extras).thenReturn(extras)
             mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
-            // THEN we should tell listeners to treat the media as active instead
+            // THEN we should treat the media as active instead
             val dataCurrentAndActive = dataCurrent.copy(active = true)
             verify(listener)
-                .onMediaDataLoaded(eq(dataCurrentAndActive.instanceId), eq(true), eq(100), eq(true))
+                .onMediaDataLoaded(
+                    eq(KEY),
+                    eq(KEY),
+                    eq(dataCurrentAndActive),
+                    eq(true),
+                    eq(100),
+                    eq(true)
+                )
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel, recsCommonModel)
             assertThat(
                     hasActiveMediaOrRecommendation(
                         selectedUserEntries,
@@ -831,27 +1016,46 @@
                     )
                 )
                 .isTrue()
-            // And send the smartspace data, but not prioritized
-            verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false))
+            // And update the smartspace data state, but not prioritized
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
         }
 
     @Test
-    fun testSmartspaceLoaded_notShouldTriggerResume_doesNotTrigger() {
-        // WHEN we have media that was recently played, but not currently active
-        val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
-        mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
-        verify(listener).onMediaDataLoaded(eq(dataCurrent.instanceId), eq(true), eq(0), eq(false))
+    fun smartspaceLoaded_notShouldTriggerResume_doesNotTrigger() =
+        testScope.runTest {
+            val sortedMedia by collectLastValue(repository.sortedMedia)
+            val recsCommonModel =
+                MediaCommonModel.MediaRecommendations(
+                    SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
+                )
+            val controlCommonModel =
+                MediaCommonModel.MediaControl(
+                    MediaDataLoadingModel.Loaded(dataMain.instanceId),
+                    true
+                )
 
-        // AND we get a smartspace signal with extra to not trigger resume
-        val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) }
-        whenever(cardAction.extras).thenReturn(extras)
-        mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+            // WHEN we have media that was recently played, but not currently active
+            val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+            mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
 
-        // THEN listeners are not updated to show media
-        verify(listener, never()).onMediaDataLoaded(any(), eq(true), eq(100), eq(true))
-        // But the smartspace update is still propagated
-        verify(listener).onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(false))
-    }
+            verify(listener)
+                .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel)
+
+            // AND we get a smartspace signal with extra to not trigger resume
+            val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) }
+            whenever(cardAction.extras).thenReturn(extras)
+            mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+            // THEN listeners are not updated to show media
+            verify(listener, never())
+                .onMediaDataLoaded(eq(KEY), eq(KEY), any(), eq(true), eq(100), eq(true))
+            // But the smartspace update is still propagated
+            verify(listener)
+                .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+            assertThat(sortedMedia?.values).containsExactly(controlCommonModel, recsCommonModel)
+        }
 
     private fun hasActiveMediaOrRecommendation(
         entries: Map<InstanceId, MediaData>?,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index 5c275b4..ffb50c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -210,7 +210,7 @@
         )
         testDispatcher = UnconfinedTestDispatcher()
         testScope = TestScope(testDispatcher)
-        mediaFilterRepository = MediaFilterRepository()
+        mediaFilterRepository = MediaFilterRepository(clock)
         mediaDataRepository = MediaDataRepository(mediaFlags, dumpManager)
         mediaDataProcessor =
             MediaDataProcessor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/AnimationBindHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/AnimationBindHandlerTest.kt
index eb885fd..4fcd3bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/AnimationBindHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/AnimationBindHandlerTest.kt
@@ -18,9 +18,9 @@
 
 import android.graphics.drawable.Animatable2
 import android.graphics.drawable.Drawable
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/MetadataAnimationHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/MetadataAnimationHandlerTest.kt
index 711669e..bb95ba3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/MetadataAnimationHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/animation/MetadataAnimationHandlerTest.kt
@@ -17,9 +17,9 @@
 package com.android.systemui.media.controls.ui.animation
 
 import android.animation.Animator
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import junit.framework.Assert.fail
 import org.junit.After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
index 37dea11..791563a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
@@ -16,12 +16,13 @@
 
 package com.android.systemui.media.controls.ui.controller
 
-import android.test.suitebuilder.annotation.SmallTest
+import android.provider.Settings
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View.GONE
 import android.view.View.VISIBLE
 import android.widget.FrameLayout
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.media.controls.ui.view.MediaHost
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt
index a73bb2c..e5d3082 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt
@@ -16,29 +16,54 @@
 
 package com.android.systemui.media.controls.ui.controller
 
+import android.animation.AnimatorSet
+import android.content.Context
 import android.content.res.Configuration
 import android.content.res.Configuration.ORIENTATION_LANDSCAPE
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.RippleDrawable
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
+import android.view.ViewGroup
+import android.view.animation.Interpolator
+import android.widget.FrameLayout
+import android.widget.ImageButton
+import android.widget.ImageView
+import android.widget.SeekBar
+import android.widget.TextView
 import androidx.constraintlayout.widget.ConstraintSet
+import androidx.lifecycle.LiveData
 import androidx.test.filters.SmallTest
+import com.android.internal.widget.CachingIconView
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.media.controls.ui.view.GutsViewHolder
 import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.media.controls.ui.view.MediaViewHolder
 import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
+import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.res.R
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
+import com.android.systemui.surfaceeffects.ripple.MultiRippleView
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
 import com.android.systemui.util.animation.MeasurementInput
 import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.animation.TransitionViewState
 import com.android.systemui.util.animation.WidgetState
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.withArgCaptor
+import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert.assertTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.floatThat
 import org.mockito.Mock
+import org.mockito.Mockito
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
@@ -55,6 +80,31 @@
         com.android.systemui.statusbar.phone.ConfigurationControllerImpl(context)
     private var player = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0)
     private var recommendation = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0)
+    private val clock = FakeSystemClock()
+    private lateinit var mainExecutor: FakeExecutor
+    private lateinit var seekBar: SeekBar
+    private lateinit var multiRippleView: MultiRippleView
+    private lateinit var turbulenceNoiseView: TurbulenceNoiseView
+    private lateinit var loadingEffectView: LoadingEffectView
+    private lateinit var settings: ImageButton
+    private lateinit var cancel: View
+    private lateinit var cancelText: TextView
+    private lateinit var dismiss: FrameLayout
+    private lateinit var dismissText: TextView
+    private lateinit var titleText: TextView
+    private lateinit var artistText: TextView
+    private lateinit var explicitIndicator: CachingIconView
+    private lateinit var seamless: ViewGroup
+    private lateinit var seamlessButton: View
+    private lateinit var seamlessIcon: ImageView
+    private lateinit var seamlessText: TextView
+    private lateinit var scrubbingElapsedTimeView: TextView
+    private lateinit var scrubbingTotalTimeView: TextView
+    private lateinit var actionPlayPause: ImageButton
+    private lateinit var actionNext: ImageButton
+    private lateinit var actionPrev: ImageButton
+    @Mock private lateinit var seamlessBackground: RippleDrawable
+    @Mock private lateinit var albumView: ImageView
     @Mock lateinit var logger: MediaViewLogger
     @Mock private lateinit var mockViewState: TransitionViewState
     @Mock private lateinit var mockCopiedState: TransitionViewState
@@ -64,6 +114,14 @@
     @Mock private lateinit var mediaSubTitleWidgetState: WidgetState
     @Mock private lateinit var mediaContainerWidgetState: WidgetState
     @Mock private lateinit var mediaFlags: MediaFlags
+    @Mock private lateinit var seekBarViewModel: SeekBarViewModel
+    @Mock private lateinit var seekBarData: LiveData<SeekBarViewModel.Progress>
+    @Mock private lateinit var globalSettings: GlobalSettings
+    @Mock private lateinit var viewHolder: MediaViewHolder
+    @Mock private lateinit var view: TransitionLayout
+    @Mock private lateinit var mockAnimator: AnimatorSet
+    @Mock private lateinit var gutsViewHolder: GutsViewHolder
+    @Mock private lateinit var gutsText: TextView
 
     private val delta = 0.1F
 
@@ -72,14 +130,30 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
+        mainExecutor = FakeExecutor(clock)
         mediaViewController =
-            MediaViewController(
-                context,
-                configurationController,
-                mediaHostStatesManager,
-                logger,
-                mediaFlags,
-            )
+            object :
+                MediaViewController(
+                    context,
+                    configurationController,
+                    mediaHostStatesManager,
+                    logger,
+                    seekBarViewModel,
+                    mainExecutor,
+                    mediaFlags,
+                    globalSettings,
+                ) {
+                override fun loadAnimator(
+                    context: Context,
+                    animId: Int,
+                    motionInterpolator: Interpolator?,
+                    vararg targets: View?
+                ): AnimatorSet {
+                    return mockAnimator
+                }
+            }
+        initGutsViewHolderMocks()
+        initMediaViewHolderMocks()
     }
 
     @Test
@@ -299,4 +373,270 @@
         verify(mediaTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
         verify(mediaSubTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
     }
+
+    @Test
+    fun attachPlayer_seekBarDisabled_seekBarVisibilityIsSetToInvisible() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        getEnabledChangeListener().onEnabledChanged(enabled = true)
+        getEnabledChangeListener().onEnabledChanged(enabled = false)
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar))
+            .isEqualTo(ConstraintSet.INVISIBLE)
+    }
+
+    @Test
+    fun attachPlayer_seekBarEnabled_seekBarVisible() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        getEnabledChangeListener().onEnabledChanged(enabled = true)
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar))
+            .isEqualTo(ConstraintSet.VISIBLE)
+    }
+
+    @Test
+    fun attachPlayer_seekBarStatusUpdate_seekBarVisibilityChanges() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        getEnabledChangeListener().onEnabledChanged(enabled = true)
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar))
+            .isEqualTo(ConstraintSet.VISIBLE)
+
+        getEnabledChangeListener().onEnabledChanged(enabled = false)
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.media_progress_bar))
+            .isEqualTo(ConstraintSet.INVISIBLE)
+    }
+
+    @Test
+    fun attachPlayer_notScrubbing_scrubbingViewsGone() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        mediaViewController.canShowScrubbingTime = true
+        getScrubbingChangeListener().onScrubbingChanged(true)
+        getScrubbingChangeListener().onScrubbingChanged(false)
+        mainExecutor.runAllReady()
+
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+    }
+
+    @Test
+    fun setIsScrubbing_noSemanticActions_scrubbingViewsGone() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        mediaViewController.canShowScrubbingTime = false
+        getScrubbingChangeListener().onScrubbingChanged(true)
+        mainExecutor.runAllReady()
+
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+    }
+
+    @Test
+    fun setIsScrubbing_noPrevButton_scrubbingTimesNotShown() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        mediaViewController.setUpNextButtonInfo(true)
+        mediaViewController.setUpPrevButtonInfo(false)
+        getScrubbingChangeListener().onScrubbingChanged(true)
+        mainExecutor.runAllReady()
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext))
+            .isEqualTo(ConstraintSet.VISIBLE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+    }
+
+    @Test
+    fun setIsScrubbing_noNextButton_scrubbingTimesNotShown() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        mediaViewController.setUpNextButtonInfo(false)
+        mediaViewController.setUpPrevButtonInfo(true)
+        getScrubbingChangeListener().onScrubbingChanged(true)
+        mainExecutor.runAllReady()
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev))
+            .isEqualTo(ConstraintSet.VISIBLE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+    }
+
+    @Test
+    fun setIsScrubbing_scrubbingViewsShownAndPrevNextHiddenOnlyInExpanded() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        mediaViewController.setUpNextButtonInfo(true)
+        mediaViewController.setUpPrevButtonInfo(true)
+        mediaViewController.canShowScrubbingTime = true
+        getScrubbingChangeListener().onScrubbingChanged(true)
+        mainExecutor.runAllReady()
+
+        // Only in expanded, we should show the scrubbing times and hide prev+next
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev))
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext))
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.VISIBLE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.VISIBLE)
+    }
+
+    @Test
+    fun setIsScrubbing_trueThenFalse_reservePrevAndNextButtons() {
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(true)
+
+        mediaViewController.attachPlayer(viewHolder)
+        mediaViewController.setUpNextButtonInfo(true, ConstraintSet.INVISIBLE)
+        mediaViewController.setUpPrevButtonInfo(true, ConstraintSet.INVISIBLE)
+        mediaViewController.canShowScrubbingTime = true
+
+        getScrubbingChangeListener().onScrubbingChanged(true)
+        mainExecutor.runAllReady()
+
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev))
+            .isEqualTo(ConstraintSet.INVISIBLE)
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext))
+            .isEqualTo(ConstraintSet.INVISIBLE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.VISIBLE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.VISIBLE)
+
+        getScrubbingChangeListener().onScrubbingChanged(false)
+        mainExecutor.runAllReady()
+
+        // Only in expanded, we should hide the scrubbing times and show prev+next
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionPrev))
+            .isEqualTo(ConstraintSet.VISIBLE)
+        assertThat(mediaViewController.expandedLayout.getVisibility(R.id.actionNext))
+            .isEqualTo(ConstraintSet.VISIBLE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_elapsed_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+        assertThat(
+                mediaViewController.expandedLayout.getVisibility(R.id.media_scrubbing_total_time)
+            )
+            .isEqualTo(ConstraintSet.GONE)
+    }
+
+    private fun initGutsViewHolderMocks() {
+        settings = ImageButton(context)
+        cancel = View(context)
+        cancelText = TextView(context)
+        dismiss = FrameLayout(context)
+        dismissText = TextView(context)
+        whenever(gutsViewHolder.gutsText).thenReturn(gutsText)
+        whenever(gutsViewHolder.settings).thenReturn(settings)
+        whenever(gutsViewHolder.cancel).thenReturn(cancel)
+        whenever(gutsViewHolder.cancelText).thenReturn(cancelText)
+        whenever(gutsViewHolder.dismiss).thenReturn(dismiss)
+        whenever(gutsViewHolder.dismissText).thenReturn(dismissText)
+    }
+
+    private fun initMediaViewHolderMocks() {
+        titleText = TextView(context)
+        artistText = TextView(context)
+        explicitIndicator = CachingIconView(context).also { it.id = R.id.media_explicit_indicator }
+        seamless = FrameLayout(context)
+        seamless.foreground = seamlessBackground
+        seamlessButton = View(context)
+        seamlessIcon = ImageView(context)
+        seamlessText = TextView(context)
+        seekBar = SeekBar(context).also { it.id = R.id.media_progress_bar }
+
+        actionPlayPause = ImageButton(context).also { it.id = R.id.actionPlayPause }
+        actionPrev = ImageButton(context).also { it.id = R.id.actionPrev }
+        actionNext = ImageButton(context).also { it.id = R.id.actionNext }
+        scrubbingElapsedTimeView =
+            TextView(context).also { it.id = R.id.media_scrubbing_elapsed_time }
+        scrubbingTotalTimeView = TextView(context).also { it.id = R.id.media_scrubbing_total_time }
+
+        multiRippleView = MultiRippleView(context, null)
+        turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        loadingEffectView = LoadingEffectView(context, null)
+
+        whenever(viewHolder.player).thenReturn(view)
+        whenever(view.context).thenReturn(context)
+        whenever(viewHolder.albumView).thenReturn(albumView)
+        whenever(albumView.foreground).thenReturn(Mockito.mock(Drawable::class.java))
+        whenever(viewHolder.titleText).thenReturn(titleText)
+        whenever(viewHolder.artistText).thenReturn(artistText)
+        whenever(viewHolder.explicitIndicator).thenReturn(explicitIndicator)
+        whenever(seamlessBackground.getDrawable(0))
+            .thenReturn(Mockito.mock(GradientDrawable::class.java))
+        whenever(viewHolder.seamless).thenReturn(seamless)
+        whenever(viewHolder.seamlessButton).thenReturn(seamlessButton)
+        whenever(viewHolder.seamlessIcon).thenReturn(seamlessIcon)
+        whenever(viewHolder.seamlessText).thenReturn(seamlessText)
+        whenever(viewHolder.seekBar).thenReturn(seekBar)
+        whenever(viewHolder.scrubbingElapsedTimeView).thenReturn(scrubbingElapsedTimeView)
+        whenever(viewHolder.scrubbingTotalTimeView).thenReturn(scrubbingTotalTimeView)
+        whenever(viewHolder.gutsViewHolder).thenReturn(gutsViewHolder)
+        whenever(seekBarViewModel.progress).thenReturn(seekBarData)
+
+        // Action buttons
+        whenever(viewHolder.actionPlayPause).thenReturn(actionPlayPause)
+        whenever(viewHolder.getAction(R.id.actionNext)).thenReturn(actionNext)
+        whenever(viewHolder.getAction(R.id.actionPrev)).thenReturn(actionPrev)
+        whenever(viewHolder.getAction(R.id.actionPlayPause)).thenReturn(actionPlayPause)
+
+        whenever(viewHolder.multiRippleView).thenReturn(multiRippleView)
+        whenever(viewHolder.turbulenceNoiseView).thenReturn(turbulenceNoiseView)
+        whenever(viewHolder.loadingEffectView).thenReturn(loadingEffectView)
+    }
+
+    private fun getScrubbingChangeListener(): SeekBarViewModel.ScrubbingChangeListener =
+        withArgCaptor {
+            verify(seekBarViewModel).setScrubbingChangeListener(capture())
+        }
+
+    private fun getEnabledChangeListener(): SeekBarViewModel.EnabledChangeListener = withArgCaptor {
+        verify(seekBarViewModel).setEnabledChangeListener(capture())
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
index e1c2d3f..cb4ab64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
@@ -29,7 +29,12 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.Classifier
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.media.controls.util.MediaFlags
+import com.android.systemui.media.controls.util.mediaFlags
 import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.testKosmos
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.concurrency.FakeRepeatableExecutor
 import com.android.systemui.util.time.FakeSystemClock
@@ -56,6 +61,7 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class SeekBarViewModelTest : SysuiTestCase() {
+    val kosmos = testKosmos()
 
     private lateinit var viewModel: SeekBarViewModel
     private lateinit var fakeExecutor: FakeExecutor
@@ -75,6 +81,7 @@
     @Mock private lateinit var mockTransport: MediaController.TransportControls
     @Mock private lateinit var falsingManager: FalsingManager
     @Mock private lateinit var mockBar: SeekBar
+    @Mock private lateinit var mediaFlags: MediaFlags
     private val token1 = MediaSession.Token(1, null)
     private val token2 = MediaSession.Token(2, null)
 
@@ -83,10 +90,18 @@
     @Before
     fun setUp() {
         fakeExecutor = FakeExecutor(FakeSystemClock())
-        viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor), falsingManager)
+        viewModel =
+            SeekBarViewModel(
+                kosmos.applicationCoroutineScope,
+                kosmos.testDispatcher,
+                FakeRepeatableExecutor(fakeExecutor),
+                falsingManager,
+                mediaFlags,
+            )
         viewModel.logSeek = {}
         whenever(mockController.sessionToken).thenReturn(token1)
         whenever(mockBar.context).thenReturn(context)
+        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(false)
 
         // LiveData to run synchronously
         ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 695d3b2..9bb21f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -47,6 +48,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.media.LocalMediaManager;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogTransitionAnimator;
 import com.android.systemui.broadcast.BroadcastSender;
@@ -121,11 +123,28 @@
         mMediaControllers.add(mMediaController);
         when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers);
 
-        mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mContext,
+                        TEST_PACKAGE,
+                        mContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
+
+        // Using a fake package will cause routing operations to fail, so we intercept
+        // scanning-related operations.
+        mMediaOutputController.mLocalMediaManager = mock(LocalMediaManager.class);
+        doNothing().when(mMediaOutputController.mLocalMediaManager).startScan();
+        doNothing().when(mMediaOutputController.mLocalMediaManager).stopScan();
 
         mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
                 mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
index c9eb67e..2e6388a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
@@ -124,11 +124,22 @@
         when(mLocalBluetoothLeBroadcast.getBroadcastCode()).thenReturn(
                 BROADCAST_CODE_TEST.getBytes(StandardCharsets.UTF_8));
 
-        mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mContext,
+                        TEST_PACKAGE,
+                        mContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputBroadcastDialog = new MediaOutputBroadcastDialog(mContext, false,
                 mBroadcastSender, mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 980eb59..4eb0038 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -194,11 +194,22 @@
         when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(
                 mCachedBluetoothDeviceManager);
 
-        mMediaOutputController = new MediaOutputController(mSpyContext, mPackageName,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        mPackageName,
+                        mContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
         mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
         when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(false);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
@@ -276,11 +287,22 @@
 
     @Test
     public void start_withoutPackageName_verifyMediaControllerInit() {
-        mMediaOutputController = new MediaOutputController(mSpyContext, null,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        null,
+                        mContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
 
         mMediaOutputController.start(mCb);
 
@@ -306,11 +328,22 @@
 
     @Test
     public void stop_withoutPackageName_verifyMediaControllerDeinit() {
-        mMediaOutputController = new MediaOutputController(mSpyContext, null,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        null,
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
 
         mMediaOutputController.start(mCb);
 
@@ -550,12 +583,22 @@
 
     @Test
     public void getAppSourceName_packageNameIsNull_returnsNull() {
-        MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
-                "",
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        MediaOutputController testMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        "",
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
         testMediaOutputController.start(mCb);
         reset(mCb);
 
@@ -573,12 +616,22 @@
 
     @Test
     public void getNotificationSmallIcon_packageNameIsNull_returnsNull() {
-        MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
-                "",
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        MediaOutputController testMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        "",
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
         testMediaOutputController.start(mCb);
         reset(mCb);
 
@@ -609,12 +662,22 @@
 
     @Test
     public void addDeviceToPlayMedia_callsLocalMediaManager() {
-        MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
-                null,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        MediaOutputController testMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        null,
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
 
         LocalMediaManager mockLocalMediaManager = mock(LocalMediaManager.class);
         testMediaOutputController.mLocalMediaManager = mockLocalMediaManager;
@@ -625,12 +688,22 @@
 
     @Test
     public void removeDeviceFromPlayMedia_callsLocalMediaManager() {
-        MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
-                null,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        MediaOutputController testMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        null,
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
 
         LocalMediaManager mockLocalMediaManager = mock(LocalMediaManager.class);
         testMediaOutputController.mLocalMediaManager = mockLocalMediaManager;
@@ -894,11 +967,22 @@
 
     @Test
     public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
-        mMediaOutputController = new MediaOutputController(mSpyContext, null,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        null,
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
 
         assertThat(mMediaOutputController.getNotificationIcon()).isNull();
     }
@@ -1085,12 +1169,22 @@
 
     @Test
     public void setTemporaryAllowListExceptionIfNeeded_packageNameIsNull_NoAction() {
-        MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
-                null,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        MediaOutputController testMediaOutputController =
+                new MediaOutputController(
+                        mSpyContext,
+                        null,
+                        mSpyContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
 
         testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
index 83def8e4..3b6a88a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -61,7 +62,7 @@
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
         verify(mMockMediaOutputDialogManager, times(1))
-                .createAndShow(getContext().getPackageName(), false, null);
+                .createAndShow(eq(getContext().getPackageName()), eq(false), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -72,7 +73,8 @@
         intent.putExtra("Wrong Package Name Key", getContext().getPackageName());
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -82,7 +84,8 @@
         Intent intent = new Intent(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG);
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -95,7 +98,8 @@
         intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName());
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -108,9 +112,10 @@
         intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName());
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, times(1))
-                .createAndShow(getContext().getPackageName(), true, null);
+                .createAndShow(eq(getContext().getPackageName()), eq(true), any());
     }
 
     @Test
@@ -121,7 +126,8 @@
         intent.putExtra("Wrong Package Name Key", getContext().getPackageName());
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -133,7 +139,8 @@
                 MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -145,7 +152,8 @@
         intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName());
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
@@ -155,7 +163,8 @@
         Intent intent = new Intent("UnKnown Action");
         mMediaOutputDialogReceiver.onReceive(getContext(), intent);
 
-        verify(mMockMediaOutputDialogManager, never()).createAndShow(any(), anyBoolean(), any());
+        verify(mMockMediaOutputDialogManager, never())
+                .createAndShow(any(), anyBoolean(), any(), any());
         verify(mMockMediaOutputBroadcastDialogManager, never())
                 .createAndShow(any(), anyBoolean(), any());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 84300da..cdef964 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -137,11 +137,22 @@
                 Mockito.eq(userHandle))).thenReturn(
                 mMediaControllers);
 
-        mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
-                mMediaSessionManager, mLocalBluetoothManager, mStarter,
-                mNotifCollection, mDialogTransitionAnimator,
-                mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
-                mKeyguardManager, mFlags, mUserTracker);
+        mMediaOutputController =
+                new MediaOutputController(
+                        mContext,
+                        TEST_PACKAGE,
+                        mContext.getUser(),
+                        mMediaSessionManager,
+                        mLocalBluetoothManager,
+                        mStarter,
+                        mNotifCollection,
+                        mDialogTransitionAnimator,
+                        mNearbyMediaDevicesManager,
+                        mAudioManager,
+                        mPowerExemptionManager,
+                        mKeyguardManager,
+                        mFlags,
+                        mUserTracker);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputDialog = makeTestDialog(mMediaOutputController);
         mMediaOutputDialog.show();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
index 44798ea..2536078 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
@@ -257,6 +257,8 @@
             userId = userId,
             colorBackground = 0,
             isForegroundTask = isForegroundTask,
+            userType = RecentTask.UserType.STANDARD,
+            splitBounds = null,
         )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt
new file mode 100644
index 0000000..fa1c8f8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/BasicPackageManagerAppIconLoaderTest.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.mediaprojection.appselector.data
+
+import android.content.ComponentName
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import androidx.test.filters.SmallTest
+import com.android.launcher3.icons.FastBitmapDrawable
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shared.system.PackageManagerWrapper
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class BasicPackageManagerAppIconLoaderTest : SysuiTestCase() {
+
+    private val packageManagerWrapper: PackageManagerWrapper = mock()
+    private val packageManager: PackageManager = mock()
+    private val dispatcher = Dispatchers.Unconfined
+
+    private val appIconLoader =
+        BasicPackageManagerAppIconLoader(
+            backgroundDispatcher = dispatcher,
+            packageManagerWrapper = packageManagerWrapper,
+            packageManager = packageManager,
+        )
+
+    @Test
+    fun loadIcon_loadsIconUsingTheSameUserId() {
+        val icon = createIcon()
+        val component = ComponentName("com.test", "TestApplication")
+        givenIcon(component, userId = 123, icon = icon)
+
+        val loadedIcon = runBlocking { appIconLoader.loadIcon(userId = 123, component = component) }
+
+        assertThat(loadedIcon).isEqualTo(icon)
+    }
+
+    private fun givenIcon(component: ComponentName, userId: Int, icon: FastBitmapDrawable) {
+        val activityInfo = mock<ActivityInfo>()
+        whenever(packageManagerWrapper.getActivityInfo(component, userId)).thenReturn(activityInfo)
+        whenever(activityInfo.loadIcon(packageManager)).thenReturn(icon)
+    }
+
+    private fun createIcon(): FastBitmapDrawable =
+        FastBitmapDrawable(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/IconLoaderLibAppIconLoaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/IconLoaderLibAppIconLoaderTest.kt
deleted file mode 100644
index 9b346d0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/IconLoaderLibAppIconLoaderTest.kt
+++ /dev/null
@@ -1,83 +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.mediaprojection.appselector.data
-
-import android.content.ComponentName
-import android.content.pm.ActivityInfo
-import android.content.pm.PackageManager
-import android.graphics.Bitmap
-import android.graphics.drawable.Drawable
-import androidx.test.filters.SmallTest
-import com.android.launcher3.icons.BitmapInfo
-import com.android.launcher3.icons.FastBitmapDrawable
-import com.android.launcher3.icons.IconFactory
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.shared.system.PackageManagerWrapper
-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.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@SmallTest
-@RunWith(JUnit4::class)
-class IconLoaderLibAppIconLoaderTest : SysuiTestCase() {
-
-    private val iconFactory: IconFactory = mock()
-    private val packageManagerWrapper: PackageManagerWrapper = mock()
-    private val packageManager: PackageManager = mock()
-    private val dispatcher = Dispatchers.Unconfined
-
-    private val appIconLoader =
-        IconLoaderLibAppIconLoader(
-            backgroundDispatcher = dispatcher,
-            context = context,
-            packageManagerWrapper = packageManagerWrapper,
-            packageManager = packageManager,
-            iconFactoryProvider = { iconFactory }
-        )
-
-    @Test
-    fun loadIcon_loadsIconUsingTheSameUserId() {
-        val icon = createIcon()
-        val component = ComponentName("com.test", "TestApplication")
-        givenIcon(component, userId = 123, icon = icon)
-
-        val loadedIcon = runBlocking { appIconLoader.loadIcon(userId = 123, component = component) }
-
-        assertThat(loadedIcon).isEqualTo(icon)
-    }
-
-    private fun givenIcon(component: ComponentName, userId: Int, icon: FastBitmapDrawable) {
-        val activityInfo = mock<ActivityInfo>()
-        whenever(packageManagerWrapper.getActivityInfo(component, userId)).thenReturn(activityInfo)
-        val rawIcon = mock<Drawable>()
-        whenever(activityInfo.loadIcon(packageManager)).thenReturn(rawIcon)
-
-        val bitmapInfo = mock<BitmapInfo>()
-        whenever(iconFactory.createBadgedIconBitmap(eq(rawIcon), any())).thenReturn(bitmapInfo)
-        whenever(bitmapInfo.newIcon(context)).thenReturn(icon)
-    }
-
-    private fun createIcon(): FastBitmapDrawable =
-        FastBitmapDrawable(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
index b593def..6ac86f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
@@ -1,9 +1,15 @@
 package com.android.systemui.mediaprojection.appselector.data
 
 import android.app.ActivityManager.RecentTaskInfo
+import android.content.pm.UserInfo
+import android.os.UserManager
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.mediaprojection.appselector.data.RecentTask.UserType.CLONED
+import com.android.systemui.mediaprojection.appselector.data.RecentTask.UserType.PRIVATE
+import com.android.systemui.mediaprojection.appselector.data.RecentTask.UserType.STANDARD
+import com.android.systemui.mediaprojection.appselector.data.RecentTask.UserType.WORK
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
@@ -17,6 +23,7 @@
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
@@ -25,12 +32,16 @@
     private val dispatcher = Dispatchers.Unconfined
     private val recentTasks: RecentTasks = mock()
     private val userTracker: UserTracker = mock()
+    private val userManager: UserManager = mock {
+        whenever(getUserInfo(anyInt())).thenReturn(mock())
+    }
     private val recentTaskListProvider =
         ShellRecentTaskListProvider(
             dispatcher,
             Runnable::run,
             Optional.of(recentTasks),
-            userTracker
+            userTracker,
+            userManager,
         )
 
     @Test
@@ -147,6 +158,22 @@
             .inOrder()
     }
 
+    @Test
+    fun loadRecentTasks_assignsCorrectUserType() {
+        givenRecentTasks(
+            createSingleTask(taskId = 1, userId = 10, userType = STANDARD),
+            createSingleTask(taskId = 2, userId = 20, userType = WORK),
+            createSingleTask(taskId = 3, userId = 30, userType = CLONED),
+            createSingleTask(taskId = 4, userId = 40, userType = PRIVATE),
+        )
+
+        val result = runBlocking { recentTaskListProvider.loadRecentTasks() }
+
+        assertThat(result.map { it.userType })
+            .containsExactly(STANDARD, WORK, CLONED, PRIVATE)
+            .inOrder()
+    }
+
     @Suppress("UNCHECKED_CAST")
     private fun givenRecentTasks(vararg tasks: GroupedRecentTaskInfo) {
         whenever(recentTasks.getRecentTasks(any(), any(), any(), any(), any())).thenAnswer {
@@ -155,7 +182,10 @@
         }
     }
 
-    private fun createRecentTask(taskId: Int): RecentTask =
+    private fun createRecentTask(
+        taskId: Int,
+        userType: RecentTask.UserType = STANDARD
+    ): RecentTask =
         RecentTask(
             taskId = taskId,
             displayId = 0,
@@ -164,25 +194,43 @@
             baseIntentComponent = null,
             colorBackground = null,
             isForegroundTask = false,
+            userType = userType,
+            splitBounds = null
         )
 
-    private fun createSingleTask(taskId: Int, isVisible: Boolean = false): GroupedRecentTaskInfo =
-        GroupedRecentTaskInfo.forSingleTask(createTaskInfo(taskId, isVisible))
+    private fun createSingleTask(
+        taskId: Int,
+        userId: Int = 0,
+        isVisible: Boolean = false,
+        userType: RecentTask.UserType = STANDARD,
+    ): GroupedRecentTaskInfo {
+        val userInfo =
+            mock<UserInfo> {
+                whenever(isCloneProfile).thenReturn(userType == CLONED)
+                whenever(isManagedProfile).thenReturn(userType == WORK)
+                whenever(isPrivateProfile).thenReturn(userType == PRIVATE)
+            }
+        whenever(userManager.getUserInfo(userId)).thenReturn(userInfo)
+        return GroupedRecentTaskInfo.forSingleTask(createTaskInfo(taskId, userId, isVisible))
+    }
 
     private fun createTaskPair(
         taskId1: Int,
+        userId1: Int = 0,
         taskId2: Int,
+        userId2: Int = 0,
         isVisible: Boolean = false
     ): GroupedRecentTaskInfo =
         GroupedRecentTaskInfo.forSplitTasks(
-            createTaskInfo(taskId1, isVisible),
-            createTaskInfo(taskId2, isVisible),
+            createTaskInfo(taskId1, userId1, isVisible),
+            createTaskInfo(taskId2, userId2, isVisible),
             null
         )
 
-    private fun createTaskInfo(taskId: Int, isVisible: Boolean = false) =
+    private fun createTaskInfo(taskId: Int, userId: Int, isVisible: Boolean = false) =
         RecentTaskInfo().apply {
             this.taskId = taskId
             this.isVisible = isVisible
+            this.userId = userId
         }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt
index ac41073..f4c5ccf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt
@@ -18,22 +18,28 @@
 
 import android.app.ActivityOptions
 import android.app.IActivityTaskManager
+import android.graphics.Rect
 import android.os.Bundle
 import android.view.View
 import android.view.ViewGroup
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX
+import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
 import com.android.systemui.mediaprojection.appselector.data.RecentTask
 import com.android.systemui.util.mockito.mock
+import com.android.wm.shell.splitscreen.SplitScreen
+import com.android.wm.shell.util.SplitBounds
 import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertThat
+import java.util.Optional
 import org.junit.Rule
 import org.junit.Test
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.verify
 
 @SmallTest
@@ -46,9 +52,10 @@
     private val taskViewSizeProvider = mock<TaskPreviewSizeProvider>()
     private val activityTaskManager = mock<IActivityTaskManager>()
     private val resultHandler = mock<MediaProjectionAppSelectorResultHandler>()
+    private val splitScreen = Optional.of(mock<SplitScreen>())
     private val bundleCaptor = ArgumentCaptor.forClass(Bundle::class.java)
 
-    private val task =
+    private val fullScreenTask =
         RecentTask(
             taskId = 123,
             displayId = 456,
@@ -56,7 +63,22 @@
             topActivityComponent = null,
             baseIntentComponent = null,
             colorBackground = null,
-            isForegroundTask = false
+            isForegroundTask = false,
+            userType = RecentTask.UserType.STANDARD,
+            splitBounds = null
+        )
+
+    private val splitScreenTask =
+        RecentTask(
+            taskId = 123,
+            displayId = 456,
+            userId = 789,
+            topActivityComponent = null,
+            baseIntentComponent = null,
+            colorBackground = null,
+            isForegroundTask = false,
+            userType = RecentTask.UserType.STANDARD,
+            splitBounds = SplitBounds(Rect(), Rect(), 0, 0, 0)
         )
 
     private val taskView =
@@ -69,61 +91,97 @@
             tasksAdapterFactory,
             taskViewSizeProvider,
             activityTaskManager,
-            resultHandler
+            resultHandler,
+            splitScreen,
         )
 
     @Test
-    fun onRecentAppClicked_taskWithSameIdIsStartedFromRecents() {
-        controller.onRecentAppClicked(task, taskView)
+    fun onRecentAppClicked_fullScreenTaskWithSameIdIsStartedFromRecents() {
+        controller.onRecentAppClicked(fullScreenTask, taskView)
 
-        verify(activityTaskManager).startActivityFromRecents(eq(task.taskId), any())
+        verify(activityTaskManager).startActivityFromRecents(eq(fullScreenTask.taskId), any())
+    }
+
+    @Test
+    fun onRecentAppClicked_splitScreenTaskWithSameIdIsStartedFromRecents() {
+        mSetFlagsRule.enableFlags(FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN)
+        controller.onRecentAppClicked(splitScreenTask, taskView)
+
+        verify(splitScreen.get())
+            .startTasks(
+                eq(splitScreenTask.taskId),
+                any(),
+                anyInt(),
+                any(),
+                anyInt(),
+                anyInt(),
+                any(),
+                any()
+            )
     }
 
     @Test
     fun onRecentAppClicked_launchDisplayIdIsSet() {
-        controller.onRecentAppClicked(task, taskView)
+        controller.onRecentAppClicked(fullScreenTask, taskView)
 
-        assertThat(getStartedTaskActivityOptions().launchDisplayId).isEqualTo(task.displayId)
+        assertThat(getStartedTaskActivityOptions(fullScreenTask.taskId).launchDisplayId)
+            .isEqualTo(fullScreenTask.displayId)
     }
 
     @Test
-    fun onRecentAppClicked_taskNotInForeground_usesScaleUpAnimation() {
-        controller.onRecentAppClicked(task, taskView)
+    fun onRecentAppClicked_fullScreenTaskNotInForeground_usesScaleUpAnimation() {
+        assertThat(fullScreenTask.isForegroundTask).isFalse()
+        controller.onRecentAppClicked(fullScreenTask, taskView)
 
-        assertThat(getStartedTaskActivityOptions().animationType)
+        assertThat(getStartedTaskActivityOptions(fullScreenTask.taskId).animationType)
             .isEqualTo(ActivityOptions.ANIM_SCALE_UP)
     }
 
     @Test
-    fun onRecentAppClicked_taskInForeground_flagOff_usesScaleUpAnimation() {
+    fun onRecentAppClicked_fullScreenTaskInForeground_flagOff_usesScaleUpAnimation() {
         mSetFlagsRule.disableFlags(FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX)
 
-        controller.onRecentAppClicked(task, taskView)
+        controller.onRecentAppClicked(fullScreenTask, taskView)
 
-        assertThat(getStartedTaskActivityOptions().animationType)
+        assertThat(getStartedTaskActivityOptions(fullScreenTask.taskId).animationType)
             .isEqualTo(ActivityOptions.ANIM_SCALE_UP)
     }
 
     @Test
-    fun onRecentAppClicked_taskInForeground_flagOn_usesDefaultAnimation() {
+    fun onRecentAppClicked_fullScreenTaskInForeground_flagOn_usesDefaultAnimation() {
         mSetFlagsRule.enableFlags(FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX)
-        val foregroundTask = task.copy(isForegroundTask = true)
+        assertForegroundTaskUsesDefaultCloseAnimation(fullScreenTask)
+    }
 
+    @Test
+    fun onRecentAppClicked_splitScreenTaskInForeground_flagOn_usesDefaultAnimation() {
+        mSetFlagsRule.enableFlags(
+            FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX,
+            FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN
+        )
+        assertForegroundTaskUsesDefaultCloseAnimation(splitScreenTask)
+    }
+
+    private fun assertForegroundTaskUsesDefaultCloseAnimation(task: RecentTask) {
+        val foregroundTask = task.copy(isForegroundTask = true)
         controller.onRecentAppClicked(foregroundTask, taskView)
 
         expect
-            .that(getStartedTaskActivityOptions().animationType)
+            .that(getStartedTaskActivityOptions(foregroundTask.taskId).animationType)
             .isEqualTo(ActivityOptions.ANIM_CUSTOM)
-        expect.that(getStartedTaskActivityOptions().overrideTaskTransition).isTrue()
         expect
-            .that(getStartedTaskActivityOptions().customExitResId)
+            .that(getStartedTaskActivityOptions(foregroundTask.taskId).overrideTaskTransition)
+            .isTrue()
+        expect
+            .that(getStartedTaskActivityOptions(foregroundTask.taskId).customExitResId)
             .isEqualTo(com.android.internal.R.anim.resolver_close_anim)
-        expect.that(getStartedTaskActivityOptions().customEnterResId).isEqualTo(0)
+        expect
+            .that(getStartedTaskActivityOptions(foregroundTask.taskId).customEnterResId)
+            .isEqualTo(0)
     }
 
-    private fun getStartedTaskActivityOptions(): ActivityOptions {
-        verify(activityTaskManager)
-            .startActivityFromRecents(eq(task.taskId), bundleCaptor.capture())
+    private fun getStartedTaskActivityOptions(taskId: Int): ActivityOptions {
+        verify(activityTaskManager).startActivityFromRecents(eq(taskId), bundleCaptor.capture())
         return ActivityOptions.fromBundle(bundleCaptor.value)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
new file mode 100644
index 0000000..e044eec
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionDialogDelegateTest.kt
@@ -0,0 +1,141 @@
+/*
+ * 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.mediaprojection.permission
+
+import android.app.AlertDialog
+import android.media.projection.MediaProjectionConfig
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.WindowManager
+import android.widget.Spinner
+import android.widget.TextView
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.AlertDialogWithDelegate
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.mock
+import junit.framework.Assert.assertEquals
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class MediaProjectionPermissionDialogDelegateTest : SysuiTestCase() {
+
+    private lateinit var dialog: AlertDialog
+
+    private val flags = mock<FeatureFlagsClassic>()
+    private val onStartRecordingClicked = mock<Runnable>()
+    private val mediaProjectionMetricsLogger = mock<MediaProjectionMetricsLogger>()
+
+    private val mediaProjectionConfig: MediaProjectionConfig =
+        MediaProjectionConfig.createConfigForDefaultDisplay()
+    private val appName: String = "testApp"
+    private val hostUid: Int = 12345
+
+    private val resIdSingleApp = R.string.screen_share_permission_dialog_option_single_app
+    private val resIdFullScreen = R.string.screen_share_permission_dialog_option_entire_screen
+    private val resIdSingleAppDisabled =
+        R.string.media_projection_entry_app_permission_dialog_single_app_disabled
+
+    @Before
+    fun setUp() {
+        whenever(flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)).thenReturn(true)
+    }
+
+    @After
+    fun teardown() {
+        if (::dialog.isInitialized) {
+            dialog.dismiss()
+        }
+    }
+
+    @Test
+    fun showDialog_forceShowPartialScreenShareFalse() {
+        // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and
+        // overrideDisableSingleAppOption = false
+        val overrideDisableSingleAppOption = false
+        setUpAndShowDialog(overrideDisableSingleAppOption)
+
+        val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner)
+        val secondOptionText =
+            spinner.adapter
+                .getDropDownView(1, null, spinner)
+                .findViewById<TextView>(android.R.id.text2)
+                ?.text
+
+        // check that the first option is full screen and enabled
+        assertEquals(context.getString(resIdFullScreen), spinner.selectedItem)
+
+        // check that the second option is single app and disabled
+        assertEquals(context.getString(resIdSingleAppDisabled, appName), secondOptionText)
+    }
+
+    @Test
+    fun showDialog_forceShowPartialScreenShareTrue() {
+        // Set up dialog with MediaProjectionConfig.createConfigForDefaultDisplay() and
+        // overrideDisableSingleAppOption = true
+        val overrideDisableSingleAppOption = true
+        setUpAndShowDialog(overrideDisableSingleAppOption)
+
+        val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner)
+        val secondOptionText =
+            spinner.adapter
+                .getDropDownView(1, null, spinner)
+                .findViewById<TextView>(android.R.id.text1)
+                ?.text
+
+        // check that the first option is single app and enabled
+        assertEquals(context.getString(resIdSingleApp), spinner.selectedItem)
+
+        // check that the second option is full screen and enabled
+        assertEquals(context.getString(resIdFullScreen), secondOptionText)
+    }
+
+    private fun setUpAndShowDialog(overrideDisableSingleAppOption: Boolean) {
+        val delegate =
+            MediaProjectionPermissionDialogDelegate(
+                context,
+                mediaProjectionConfig,
+                {},
+                onStartRecordingClicked,
+                appName,
+                overrideDisableSingleAppOption,
+                hostUid,
+                mediaProjectionMetricsLogger
+            )
+
+        dialog = AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate)
+        SystemUIDialog.applyFlags(dialog)
+        SystemUIDialog.setDialogSize(dialog)
+
+        dialog.window?.addSystemFlags(
+            WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS
+        )
+
+        delegate.onCreate(dialog, savedInstanceState = null)
+        dialog.show()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.kt
index 261e8c0..9f0e67b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.kt
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.monet
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.util.Log
 import com.android.systemui.SysuiTestCase
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 a702dda..224e755 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.content.res.Configuration;
 import android.view.IWindowManager;
 import android.view.accessibility.AccessibilityManager;
 
@@ -55,6 +56,8 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.FakeConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import dagger.Lazy;
@@ -117,6 +120,7 @@
     EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
     @Mock
     NotificationShadeWindowController mNotificationShadeWindowController;
+    ConfigurationController mConfigurationController = new FakeConfigurationController();
 
     private AccessibilityManager.AccessibilityServicesStateChangeListener
             mAccessibilityServicesStateChangeListener;
@@ -144,9 +148,8 @@
                 mSystemActions, mOverviewProxyService, mAssistManagerLazy,
                 () -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
                 mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
-                mDisplayTracker, mNotificationShadeWindowController, mDumpManager, mCommandQueue,
-                mSynchronousExecutor);
-
+                mDisplayTracker, mNotificationShadeWindowController, mConfigurationController,
+                mDumpManager, mCommandQueue, mSynchronousExecutor);
     }
 
     @Test
@@ -335,6 +338,12 @@
         assertThat(state2.mWindowState).isNotEqualTo(newState);
     }
 
+    @Test
+    public void configUpdatePropagatesToEdgeBackGestureHandler() {
+        mConfigurationController.onConfigurationChanged(Configuration.EMPTY);
+        verify(mEdgeBackGestureHandler, times(1)).onConfigurationChanged(any());
+    }
+
     private List<String> createFakeShortcutTargets() {
         return new ArrayList<>(List.of("a", "b", "c", "d"));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
index d405df7..354a87a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
@@ -37,11 +37,8 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
-import android.content.res.Configuration;
 import android.testing.AndroidTestingRunner;
 import android.util.SparseArray;
 
@@ -293,23 +290,6 @@
     }
 
     @Test
-    public void testConfigurationChange_taskbarNotInitialized() {
-        Configuration configuration = mContext.getResources().getConfiguration();
-        mNavigationBarController.mIsLargeScreen = true;
-        mNavigationBarController.onConfigChanged(configuration);
-        verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
-    }
-
-    @Test
-    public void testConfigurationChange_taskbarInitialized() {
-        Configuration configuration = mContext.getResources().getConfiguration();
-        mNavigationBarController.mIsLargeScreen = true;
-        when(mTaskbarDelegate.isInitialized()).thenReturn(true);
-        mNavigationBarController.onConfigChanged(configuration);
-        verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
-    }
-
-    @Test
     public void testShouldRenderTaskbar_taskbarNotRenderedOnPhone() {
         mNavigationBarController.mIsLargeScreen = false;
         mNavigationBarController.mIsPhone = true;
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 b38d5e3..0e7a215 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -111,6 +111,7 @@
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LightBarTransitionsController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.DeviceConfigProxyFake;
@@ -275,8 +276,8 @@
                     mKeyguardStateController, mock(NavigationModeController.class),
                     mEdgeBackGestureHandlerFactory, mock(IWindowManager.class),
                     mock(UserTracker.class), mock(DisplayTracker.class),
-                    mNotificationShadeWindowController, mock(DumpManager.class),
-                    mock(CommandQueue.class), mSynchronousExecutor));
+                    mNotificationShadeWindowController, mock(ConfigurationController.class),
+                    mock(DumpManager.class), mock(CommandQueue.class), mSynchronousExecutor));
             mNavigationBar = createNavBar(mContext);
             mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
         });
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
index 6e0919f..e6c259a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
@@ -31,10 +31,10 @@
 import com.android.internal.util.LatencyTracker
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.jank.interactionJankMonitor
-import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.plugins.NavigationEdgeBackPlugin
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
@@ -53,6 +53,7 @@
     companion object {
         private const val START_X: Float = 0f
     }
+    private val kosmos = testKosmos()
     private lateinit var mBackPanelController: BackPanelController
     private lateinit var testableLooper: TestableLooper
     private var triggerThreshold: Float = 0.0f
@@ -61,7 +62,7 @@
     @Mock private lateinit var windowManager: WindowManager
     @Mock private lateinit var configurationController: ConfigurationController
     @Mock private lateinit var latencyTracker: LatencyTracker
-    private val interactionJankMonitor = Kosmos().interactionJankMonitor
+    private val interactionJankMonitor by lazy { kosmos.interactionJankMonitor }
     @Mock private lateinit var layoutParams: WindowManager.LayoutParams
     @Mock private lateinit var backCallback: NavigationEdgeBackPlugin.BackCallback
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
index b4f5528..4101c94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
@@ -16,7 +16,7 @@
 package com.android.systemui.notetask
 
 import android.os.UserHandle
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
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 e09c804..2c86a8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -19,7 +19,7 @@
 import android.app.role.RoleManager
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
-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.util.mockito.eq
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 ebd34de..231b333 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
@@ -25,8 +25,8 @@
 import android.hardware.input.InputSettings
 import android.os.UserHandle
 import android.os.UserManager
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
 import com.android.dx.mockito.inline.extended.ExtendedMockito
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 4547bff..9429725 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -42,11 +42,12 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 2bdad2b..cae170f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -38,18 +38,19 @@
 import android.provider.Settings;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.testing.TestableResources;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.settingslib.fuelgauge.Estimate;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.power.PowerUI.WarningsUI;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
index e4a4836..6956bea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
@@ -57,6 +57,7 @@
 import com.android.keyguard.BouncerPanelExpansionCalculator;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.EnableSceneContainer;
 import com.android.systemui.flags.FeatureFlagsClassic;
 import com.android.systemui.media.controls.ui.view.MediaHost;
 import com.android.systemui.qs.customize.QSCustomizerController;
@@ -66,7 +67,6 @@
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.res.R;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.CommandQueue;
@@ -115,7 +115,6 @@
     @Mock private FooterActionsViewBinder mFooterActionsViewBinder;
     @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
     @Mock private FeatureFlagsClassic mFeatureFlags;
-    @Mock private SceneContainerFlags mSceneContainerFlags;
     private ViewGroup mQsView;
 
     private final CommandQueue mCommandQueue =
@@ -127,7 +126,6 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        when(mSceneContainerFlags.isEnabled()).thenReturn(false);
 
         mUnderTest = instantiate();
 
@@ -496,8 +494,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void testSceneContainerFlagsEnabled_FooterActionsRemoved_controllerNotStarted() {
-        when(mSceneContainerFlags.isEnabled()).thenReturn(true);
         clearInvocations(
                 mFooterActionsViewBinder, mFooterActionsViewModel, mFooterActionsViewModelFactory);
         QSImpl other = instantiate();
@@ -513,9 +511,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void testSceneContainerFlagsEnabled_statusBarStateIsShade() {
-        when(mSceneContainerFlags.isEnabled()).thenReturn(true);
-
         mUnderTest.onStateChanged(KEYGUARD);
         assertThat(mUnderTest.getStatusBarState()).isEqualTo(SHADE);
 
@@ -524,9 +521,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void testSceneContainerFlagsEnabled_isKeyguardState_alwaysFalse() {
-        when(mSceneContainerFlags.isEnabled()).thenReturn(true);
-
         mUnderTest.onStateChanged(KEYGUARD);
         assertThat(mUnderTest.isKeyguardState()).isFalse();
 
@@ -559,8 +555,8 @@
                 mFooterActionsViewModelFactory,
                 mFooterActionsViewBinder,
                 mLargeScreenShadeInterpolator,
-                mFeatureFlags,
-                mSceneContainerFlags);
+                mFeatureFlags
+        );
     }
 
     private void setUpOther() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 0101741..542bfaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs;
 
+import static com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
@@ -33,6 +35,8 @@
 
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.ContextThemeWrapper;
@@ -45,13 +49,14 @@
 import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.haptics.qs.QSLongPressEffect;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
 import com.android.systemui.media.controls.ui.view.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.customize.QSCustomizerController;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.res.R;
-import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
 import com.android.systemui.util.animation.DisappearParameters;
 
@@ -66,11 +71,14 @@
 import java.util.Collections;
 import java.util.List;
 
+import javax.inject.Provider;
+
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
 public class QSPanelControllerBaseTest extends SysuiTestCase {
 
+    private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
     @Mock
     private QSPanel mQSPanel;
     @Mock
@@ -101,8 +109,8 @@
     Configuration mConfiguration;
     @Mock
     Runnable mHorizontalLayoutListener;
-    @Mock
-    VibratorHelper mVibratorHelper;
+    private TestableLongPressEffectProvider mLongPressEffectProvider =
+            new TestableLongPressEffectProvider();
 
     private QSPanelControllerBase<QSPanel> mController;
 
@@ -114,7 +122,7 @@
                 DumpManager dumpManager) {
             super(view, host, qsCustomizerController, true, mediaHost, metricsLogger, uiEventLogger,
                     qsLogger, dumpManager, new ResourcesSplitShadeStateController(),
-                    mVibratorHelper);
+                    mLongPressEffectProvider);
         }
 
         @Override
@@ -123,6 +131,17 @@
         }
     }
 
+    private class TestableLongPressEffectProvider implements Provider<QSLongPressEffect> {
+
+        private int mEffectsProvided = 0;
+
+        @Override
+        public QSLongPressEffect get() {
+            mEffectsProvided++;
+            return mKosmos.getQsLongPressEffect();
+        }
+    }
+
     @Before
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -421,6 +440,27 @@
     }
 
     @Test
+    @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
+    public void setTiles_longPressEffectEnabled_nonNullLongPressEffectsAreProvided() {
+        mLongPressEffectProvider.mEffectsProvided = 0;
+        when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+        mController.setTiles();
+
+        // There is one non-null effect provided for each tile in the host
+        assertThat(mLongPressEffectProvider.mEffectsProvided).isEqualTo(2);
+    }
+
+    @Test
+    @DisableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
+    public void setTiles_longPressEffectDisabled_noLongPressEffectsAreProvided() {
+        mLongPressEffectProvider.mEffectsProvided = 0;
+        when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+        mController.setTiles();
+
+        assertThat(mLongPressEffectProvider.mEffectsProvided).isEqualTo(0);
+    }
+
+    @Test
     public void setTiles_differentTiles_extraTileRemoved() {
         when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
         mController.setTiles();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index 916e8dd..e50320d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -1,29 +1,29 @@
 package com.android.systemui.qs
 
 import android.content.res.Configuration
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableResources
 import android.view.ContextThemeWrapper
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.logging.UiEventLogger
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.haptics.qs.QSLongPressEffect
 import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.qs.customize.QSCustomizerController
 import com.android.systemui.qs.logging.QSLogger
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.res.R
 import com.android.systemui.settings.brightness.BrightnessController
 import com.android.systemui.settings.brightness.BrightnessSliderController
-import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
 import com.android.systemui.tuner.TunerService
 import com.google.common.truth.Truth.assertThat
+import javax.inject.Provider
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
@@ -62,9 +62,7 @@
     @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
     @Mock private lateinit var configuration: Configuration
     @Mock private lateinit var pagedTileLayout: PagedTileLayout
-    @Mock private lateinit var vibratorHelper: VibratorHelper
-
-    private val sceneContainerFlags = FakeSceneContainerFlags()
+    @Mock private lateinit var longPressEffectProvider: Provider<QSLongPressEffect>
 
     private lateinit var controller: QSPanelController
     private val testableResources: TestableResources = mContext.orCreateTestableResources
@@ -102,8 +100,7 @@
             falsingManager,
             statusBarKeyguardViewManager,
             ResourcesSplitShadeStateController(),
-            sceneContainerFlags,
-            vibratorHelper,
+            longPressEffectProvider,
         )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 718e302f..0abcc64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -42,7 +42,6 @@
 import android.os.Looper;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -52,6 +51,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
+import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogTransitionAnimator;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 71a9a8b..1eb0a51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -22,15 +22,15 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.logging.testing.UiEventLoggerFake
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.haptics.qs.QSLongPressEffect
 import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.qs.customize.QSCustomizerController
 import com.android.systemui.qs.logging.QSLogger
-import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
 import com.android.systemui.util.leak.RotationUtils
 import org.junit.After
@@ -45,6 +45,7 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import javax.inject.Provider
 import org.mockito.Mockito.`when` as whenever
 
 @SmallTest
@@ -60,7 +61,7 @@
     @Mock private lateinit var tile: QSTile
     @Mock private lateinit var tileLayout: TileLayout
     @Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
-    @Mock private lateinit var vibratorHelper: VibratorHelper
+    @Mock private lateinit var longPressEffectProvider: Provider<QSLongPressEffect>
 
     private val uiEventLogger = UiEventLoggerFake()
     private val dumpManager = DumpManager()
@@ -92,7 +93,7 @@
                 uiEventLogger,
                 qsLogger,
                 dumpManager,
-                vibratorHelper,
+                longPressEffectProvider,
             )
 
         controller.init()
@@ -161,7 +162,7 @@
         uiEventLogger: UiEventLoggerFake,
         qsLogger: QSLogger,
         dumpManager: DumpManager,
-        vibratorHelper: VibratorHelper,
+        longPressEffectProvider: Provider<QSLongPressEffect>,
     ) :
         QuickQSPanelController(
             view,
@@ -175,7 +176,7 @@
             qsLogger,
             dumpManager,
             ResourcesSplitShadeStateController(),
-            vibratorHelper,
+            longPressEffectProvider,
         ) {
 
         private var rotation = RotationUtils.ROTATION_NONE
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 8acde36..4915e55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -20,15 +20,14 @@
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Answers
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -43,8 +42,6 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private lateinit var context: Context
 
-    private val sceneContainerFlags = FakeSceneContainerFlags()
-
     private lateinit var controller: QuickStatusBarHeaderController
 
     @Before
@@ -55,9 +52,8 @@
         `when`(view.context).thenReturn(context)
 
         controller = QuickStatusBarHeaderController(
-                view,
-                quickQSPanelController,
-                sceneContainerFlags,
+            view,
+            quickQSPanelController,
         )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 0eae5aa..98adbb0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -31,12 +31,12 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.TestableLooper;
 import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTest.java
index c43c3e6..29e2a8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTest.java
@@ -16,9 +16,9 @@
 
 import static junit.framework.Assert.assertEquals;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
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 33f8f1f..ef979d2 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
@@ -31,7 +31,7 @@
 import android.os.Parcel
 import android.service.quicksettings.IQSTileService
 import android.service.quicksettings.Tile
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.IWindowManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java
index b8e6403..eb013c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java
@@ -19,12 +19,12 @@
 
 import android.content.res.ColorStateList;
 import android.service.quicksettings.Tile;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 8142456..0a36ae6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -56,9 +56,9 @@
 import android.service.quicksettings.IQSService;
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.TileService;
-import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.annotation.Nullable;
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
index 28331bb..0ff29db 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
@@ -34,8 +34,8 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index d011821..248af1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -34,11 +34,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.quicksettings.IQSTileService;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.qs.QSHost;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelTest.kt
new file mode 100644
index 0000000..e8c5fd9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelTest.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.FakeQSFactory
+import com.android.systemui.qs.pipeline.data.repository.tileSpecRepository
+import com.android.systemui.qs.pipeline.domain.interactor.FakeQSTile
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.qsTileFactory
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class TileGridViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos().apply { qsTileFactory = FakeQSFactory(::tileCreator) }
+    private val underTest = with(kosmos) { tileGridViewModel }
+
+    @Test
+    fun noIconTiles() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(underTest.tileViewModels)
+
+                tileSpecRepository.setTiles(
+                    0,
+                    listOf(
+                        TileSpec.create("bluetooth"),
+                        TileSpec.create("internet"),
+                        TileSpec.create("alarm")
+                    )
+                )
+
+                latest!!.forEach { Assert.assertFalse(it.iconOnly) }
+            }
+        }
+
+    @Test
+    fun withIconTiles() =
+        with(kosmos) {
+            testScope.runTest {
+                val latest by collectLastValue(underTest.tileViewModels)
+
+                tileSpecRepository.setTiles(
+                    0,
+                    listOf(
+                        TileSpec.create("airplane"),
+                        TileSpec.create("flashlight"),
+                        TileSpec.create("rotation")
+                    )
+                )
+
+                latest!!.forEach { Assert.assertTrue(it.iconOnly) }
+            }
+        }
+
+    private fun tileCreator(spec: String): QSTile {
+        return FakeQSTile(0).apply { tileSpec = spec }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
index 2b1ac91..ecbd0f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.graphics.drawable.Drawable
-import android.platform.test.annotations.EnableFlags
 import android.service.quicksettings.Tile
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
@@ -28,10 +27,12 @@
 import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.TextView
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS
 import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.haptics.qs.QSLongPressEffect
+import com.android.systemui.haptics.qs.qsLongPressEffect
 import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
@@ -50,13 +51,14 @@
     private lateinit var tileView: FakeTileView
     private lateinit var customDrawableView: View
     private lateinit var chevronView: View
+    private val kosmos = testKosmos()
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         context.ensureTestableResources()
 
-        tileView = FakeTileView(context, false)
+        tileView = FakeTileView(context, false, kosmos.qsLongPressEffect)
         customDrawableView = tileView.requireViewById(R.id.customDrawable)
         chevronView = tileView.requireViewById(R.id.chevron)
     }
@@ -383,8 +385,7 @@
     }
 
     @Test
-    @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
-    fun onStateChange_longPressEffectActive_withInvalidDuration_doesNotCreateEffect() {
+    fun onStateChange_longPressEffectActive_withInvalidDuration_doesNotInitializeEffect() {
         val state = QSTile.State() // A state that handles longPress
 
         // GIVEN an invalid long-press effect duration
@@ -393,25 +394,23 @@
         // WHEN the state changes
         tileView.changeState(state)
 
-        // THEN the long-press effect is not created
-        assertThat(tileView.hasLongPressEffect).isFalse()
+        // THEN the long-press effect is not initialized
+        assertThat(tileView.isLongPressEffectInitialized).isFalse()
     }
 
     @Test
-    @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
-    fun onStateChange_longPressEffectActive_withValidDuration_createsEffect() {
+    fun onStateChange_longPressEffectActive_withValidDuration_initializesEffect() {
         // GIVEN a test state that handles long-press and a valid long-press effect duration
         val state = QSTile.State()
 
         // WHEN the state changes
         tileView.changeState(state)
 
-        // THEN the long-press effect created
-        assertThat(tileView.hasLongPressEffect).isTrue()
+        // THEN the long-press effect is initialized
+        assertThat(tileView.isLongPressEffectInitialized).isTrue()
     }
 
     @Test
-    @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
     fun onStateChange_fromLongPress_to_noLongPress_unBoundsTile() {
         // GIVEN a state that no longer handles long-press
         val state = QSTile.State()
@@ -425,7 +424,6 @@
     }
 
     @Test
-    @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
     fun onStateChange_fromNoLongPress_to_longPress_bindsTile() {
         // GIVEN that the tile has changed to a state that does not handle long-press
         val state = QSTile.State()
@@ -440,12 +438,50 @@
         assertThat(tileView.isLongPressEffectBound).isTrue()
     }
 
+    @Test
+    fun onStateChange_withoutLongPressEffect_fromLongPress_to_noLongPress_neverBindsEffect() {
+        // GIVEN a tile where the long-press effect is null
+        tileView = FakeTileView(context, false, null)
+
+        // GIVEN a state that no longer handles long-press
+        val state = QSTile.State()
+        state.handlesLongClick = false
+
+        // WHEN the state changes
+        tileView.changeState(state)
+
+        // THEN the view binder does not bind the view and no effect is initialized
+        assertThat(tileView.isLongPressEffectBound).isFalse()
+        assertThat(tileView.isLongPressEffectInitialized).isFalse()
+    }
+
+    @Test
+    fun onStateChange_withoutLongPressEffect_fromNoLongPress_to_longPress_neverBindsEffect() {
+        // GIVEN a tile where the long-press effect is null
+        tileView = FakeTileView(context, false, null)
+
+        // GIVEN that the tile has changed to a state that does not handle long-press
+        val state = QSTile.State()
+        state.handlesLongClick = false
+        tileView.changeState(state)
+
+        // WHEN the state changes back to handling long-press
+        state.handlesLongClick = true
+        tileView.changeState(state)
+
+        // THEN the view binder does not bind the view and no effect is initialized
+        assertThat(tileView.isLongPressEffectBound).isFalse()
+        assertThat(tileView.isLongPressEffectInitialized).isFalse()
+    }
+
     class FakeTileView(
         context: Context,
-        collapsed: Boolean
+        collapsed: Boolean,
+        longPressEffect: QSLongPressEffect?,
     ) : QSTileViewImpl(
             ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings),
-            collapsed
+            collapsed,
+            longPressEffect,
     ) {
         var constantLongPressEffectDuration = 500
 
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 82ee99a..830f08a 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
@@ -23,7 +23,7 @@
 import com.android.systemui.qs.QsEventLogger
 import com.android.systemui.qs.logging.QSLogger
 import com.android.systemui.qs.tileimpl.QSTileImpl
-import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialogViewModel
+import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogViewModel
 import com.android.systemui.statusbar.policy.BluetoothController
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
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 440270b..c02fca7 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
@@ -27,13 +27,13 @@
 import android.content.pm.PackageManager;
 import android.hardware.SensorPrivacyManager;
 import android.os.Handler;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableResources;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.ActivityStarter;
@@ -43,6 +43,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DeviceStateRotationLockSettingController;
 import com.android.systemui.statusbar.policy.RotationLockController;
@@ -57,7 +58,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index 8004c6d..ff712ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -20,10 +20,12 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.wifitrackerlib.WifiEntry;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -50,6 +52,8 @@
     public MockitoRule mRule = MockitoJUnit.rule();
     @Spy
     private Context mSpyContext = mContext;
+    @Mock
+    CoroutineScope mScope;
 
     @Mock
     private WifiEntry mInternetWifiEntry;
@@ -81,7 +85,7 @@
         when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
         when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
 
-        mInternetAdapter = new InternetAdapter(mInternetDialogController);
+        mInternetAdapter = new InternetAdapter(mInternetDialogController, mScope);
         mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mContext), 0);
         mInternetAdapter.setWifiEntries(Arrays.asList(mWifiEntry), 1 /* wifiEntriesCount */);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
index db9f5cf..6f88891 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
@@ -1,7 +1,9 @@
 package com.android.systemui.qs.tiles.dialog;
 
 import static com.android.systemui.qs.tiles.dialog.InternetDialogController.MAX_WIFI_ENTRY_COUNT;
+
 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.eq;
@@ -38,6 +40,8 @@
 import com.android.systemui.util.time.FakeSystemClock;
 import com.android.wifitrackerlib.WifiEntry;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -64,6 +68,8 @@
     @Mock
     private Handler mHandler;
     @Mock
+    CoroutineScope mScope;
+    @Mock
     private TelephonyManager mTelephonyManager;
     @Mock
     private WifiEntry mInternetWifiEntry;
@@ -133,6 +139,7 @@
                 true,
                 true,
                 true,
+                mScope,
                 mock(UiEventLogger.class),
                 mDialogTransitionAnimator,
                 mHandler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnInteractorTest.kt
deleted file mode 100644
index 036d3c8..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnInteractorTest.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.testing.AndroidTestingRunner
-import androidx.test.filters.SmallTest
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import kotlin.test.Test
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Rule
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class BluetoothAutoOnInteractorTest : SysuiTestCase() {
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-    private val testDispatcher = StandardTestDispatcher()
-    private val testScope = TestScope(testDispatcher)
-    private val bluetoothAdapter =
-        mock<BluetoothAdapter> {
-            var autoOn = false
-            whenever(isAutoOnEnabled).thenAnswer { autoOn }
-
-            whenever(setAutoOnEnabled(anyBoolean())).thenAnswer { invocation ->
-                autoOn = invocation.getArgument(0) as Boolean
-                autoOn
-            }
-        }
-    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
-    private lateinit var bluetoothAutoOnInteractor: BluetoothAutoOnInteractor
-
-    @Before
-    fun setUp() {
-        bluetoothAutoOnInteractor =
-            BluetoothAutoOnInteractor(
-                BluetoothAutoOnRepository(
-                    localBluetoothManager,
-                    bluetoothAdapter,
-                    testScope.backgroundScope,
-                    testDispatcher,
-                )
-            )
-    }
-
-    @Test
-    fun testSetEnabled_bluetoothAutoOnUnsupported_doNothing() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(false)
-
-            bluetoothAutoOnInteractor.setEnabled(true)
-            runCurrent()
-
-            assertFalse(bluetoothAdapter.isAutoOnEnabled)
-        }
-    }
-
-    @Test
-    fun testSetEnabled_bluetoothAutoOnSupported_setNewValue() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(true)
-
-            bluetoothAutoOnInteractor.setEnabled(true)
-            runCurrent()
-
-            assertTrue(bluetoothAdapter.isAutoOnEnabled)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnRepositoryTest.kt
deleted file mode 100644
index 3119284..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothAutoOnRepositoryTest.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.testing.AndroidTestingRunner
-import androidx.test.filters.SmallTest
-import com.android.settingslib.bluetooth.BluetoothEventManager
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.util.mockito.whenever
-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.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class BluetoothAutoOnRepositoryTest : SysuiTestCase() {
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-    private val testDispatcher = StandardTestDispatcher()
-    private val testScope = TestScope(testDispatcher)
-    @Mock private lateinit var bluetoothAdapter: BluetoothAdapter
-    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
-    @Mock private lateinit var eventManager: BluetoothEventManager
-
-    private lateinit var bluetoothAutoOnRepository: BluetoothAutoOnRepository
-
-    @Before
-    fun setUp() {
-        whenever(localBluetoothManager.eventManager).thenReturn(eventManager)
-        bluetoothAutoOnRepository =
-            BluetoothAutoOnRepository(
-                localBluetoothManager,
-                bluetoothAdapter,
-                testScope.backgroundScope,
-                testDispatcher,
-            )
-    }
-
-    @Test
-    fun testIsAutoOn_returnFalse() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnEnabled).thenReturn(false)
-            val actualValue by collectLastValue(bluetoothAutoOnRepository.isAutoOn)
-
-            runCurrent()
-
-            assertThat(actualValue).isEqualTo(false)
-        }
-    }
-
-    @Test
-    fun testIsAutoOn_returnTrue() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnEnabled).thenReturn(true)
-            val actualValue by collectLastValue(bluetoothAutoOnRepository.isAutoOn)
-
-            runCurrent()
-
-            assertThat(actualValue).isEqualTo(true)
-        }
-    }
-
-    @Test
-    fun testIsAutoOnSupported_returnTrue() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(true)
-            val actualValue = bluetoothAutoOnRepository.isAutoOnSupported()
-
-            runCurrent()
-
-            assertThat(actualValue).isEqualTo(true)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothStateInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothStateInteractorTest.kt
deleted file mode 100644
index 479e62d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothStateInteractorTest.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.settingslib.bluetooth.LocalBluetoothAdapter
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.SysuiTestCase
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class BluetoothStateInteractorTest : SysuiTestCase() {
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-    private val testScope = TestScope()
-
-    private lateinit var bluetoothStateInteractor: BluetoothStateInteractor
-
-    @Mock private lateinit var bluetoothAdapter: LocalBluetoothAdapter
-    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
-    @Mock private lateinit var logger: BluetoothTileDialogLogger
-
-    @Before
-    fun setUp() {
-        bluetoothStateInteractor =
-            BluetoothStateInteractor(localBluetoothManager, logger, testScope.backgroundScope)
-        `when`(localBluetoothManager.bluetoothAdapter).thenReturn(bluetoothAdapter)
-    }
-
-    @Test
-    fun testGet_isBluetoothEnabled() {
-        testScope.runTest {
-            `when`(bluetoothAdapter.isEnabled).thenReturn(true)
-
-            assertThat(bluetoothStateInteractor.isBluetoothEnabled).isTrue()
-        }
-    }
-
-    @Test
-    fun testGet_isBluetoothDisabled() {
-        testScope.runTest {
-            `when`(bluetoothAdapter.isEnabled).thenReturn(false)
-
-            assertThat(bluetoothStateInteractor.isBluetoothEnabled).isFalse()
-        }
-    }
-
-    @Test
-    fun testSet_bluetoothEnabled() {
-        testScope.runTest {
-            `when`(bluetoothAdapter.isEnabled).thenReturn(false)
-
-            bluetoothStateInteractor.isBluetoothEnabled = true
-            verify(bluetoothAdapter).enable()
-            verify(logger)
-                .logBluetoothState(BluetoothStateStage.BLUETOOTH_STATE_VALUE_SET, true.toString())
-        }
-    }
-
-    @Test
-    fun testSet_bluetoothNoChange() {
-        testScope.runTest {
-            `when`(bluetoothAdapter.isEnabled).thenReturn(false)
-
-            bluetoothStateInteractor.isBluetoothEnabled = false
-            verify(bluetoothAdapter, never()).enable()
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegateTest.kt
deleted file mode 100644
index 17b6127..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegateTest.kt
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.content.Context
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.LayoutInflater
-import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
-import android.view.ViewGroup.LayoutParams.MATCH_PARENT
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.model.SysUiState
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.statusbar.phone.SystemUIDialogManager
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.test.TestCoroutineScheduler
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class BluetoothTileDialogDelegateTest : SysuiTestCase() {
-    companion object {
-        const val DEVICE_NAME = "device"
-        const val DEVICE_CONNECTION_SUMMARY = "active"
-        const val ENABLED = true
-        const val CONTENT_HEIGHT = WRAP_CONTENT
-    }
-
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-
-    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
-
-    @Mock private lateinit var bluetoothTileDialogCallback: BluetoothTileDialogCallback
-
-    @Mock private lateinit var drawable: Drawable
-
-    @Mock private lateinit var uiEventLogger: UiEventLogger
-
-    @Mock private lateinit var logger: BluetoothTileDialogLogger
-
-    private val uiProperties =
-        BluetoothTileDialogViewModel.UiProperties.build(
-            isBluetoothEnabled = ENABLED,
-            isAutoOnToggleFeatureAvailable = ENABLED
-        )
-    @Mock private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
-    @Mock private lateinit var dialogManager: SystemUIDialogManager
-    @Mock private lateinit var sysuiState: SysUiState
-    @Mock private lateinit var dialogTransitionAnimator: DialogTransitionAnimator
-
-    private val fakeSystemClock = FakeSystemClock()
-
-    private lateinit var scheduler: TestCoroutineScheduler
-    private lateinit var dispatcher: CoroutineDispatcher
-    private lateinit var testScope: TestScope
-    private lateinit var icon: Pair<Drawable, String>
-    private lateinit var mBluetoothTileDialogDelegate: BluetoothTileDialogDelegate
-    private lateinit var deviceItem: DeviceItem
-
-    @Before
-    fun setUp() {
-        scheduler = TestCoroutineScheduler()
-        dispatcher = UnconfinedTestDispatcher(scheduler)
-        testScope = TestScope(dispatcher)
-
-        whenever(sysuiState.setFlag(anyInt(), anyBoolean())).thenReturn(sysuiState)
-
-        mBluetoothTileDialogDelegate =
-            BluetoothTileDialogDelegate(
-                uiProperties,
-                CONTENT_HEIGHT,
-                ENABLED,
-                bluetoothTileDialogCallback,
-                {},
-                dispatcher,
-                fakeSystemClock,
-                uiEventLogger,
-                logger,
-                sysuiDialogFactory
-            )
-
-        whenever(
-                sysuiDialogFactory.create(
-                    any(SystemUIDialog.Delegate::class.java)
-                )
-            )
-            .thenAnswer {
-                SystemUIDialog(
-                    mContext,
-                    0,
-                    SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK,
-                    dialogManager,
-                    sysuiState,
-                    fakeBroadcastDispatcher,
-                    dialogTransitionAnimator,
-                    it.getArgument(0)
-                )
-            }
-
-        icon = Pair(drawable, DEVICE_NAME)
-        deviceItem =
-            DeviceItem(
-                type = DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE,
-                cachedBluetoothDevice = cachedBluetoothDevice,
-                deviceName = DEVICE_NAME,
-                connectionSummary = DEVICE_CONNECTION_SUMMARY,
-                iconWithDescription = icon,
-                background = null
-            )
-        `when`(cachedBluetoothDevice.isBusy).thenReturn(false)
-    }
-
-    @Test
-    fun testShowDialog_createRecyclerViewWithAdapter() {
-        val dialog = mBluetoothTileDialogDelegate.createDialog()
-        dialog.show()
-
-        val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
-
-        assertThat(recyclerView).isNotNull()
-        assertThat(recyclerView.visibility).isEqualTo(VISIBLE)
-        assertThat(recyclerView.adapter).isNotNull()
-        assertThat(recyclerView.layoutManager is LinearLayoutManager).isTrue()
-    }
-
-    @Test
-    fun testShowDialog_displayBluetoothDevice() {
-        testScope.runTest {
-            val dialog = mBluetoothTileDialogDelegate.createDialog()
-            dialog.show()
-            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
-            mBluetoothTileDialogDelegate.onDeviceItemUpdated(
-                dialog,
-                listOf(deviceItem),
-                showSeeAll = false,
-                showPairNewDevice = false
-            )
-
-            val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
-            val adapter = recyclerView?.adapter as BluetoothTileDialogDelegate.Adapter
-            assertThat(adapter.itemCount).isEqualTo(1)
-            assertThat(adapter.getItem(0).deviceName).isEqualTo(DEVICE_NAME)
-            assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
-            assertThat(adapter.getItem(0).iconWithDescription).isEqualTo(icon)
-        }
-    }
-
-    @Test
-    fun testDeviceItemViewHolder_cachedDeviceNotBusy() {
-        deviceItem.isEnabled = true
-
-        val view =
-            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
-        val viewHolder =
-            mBluetoothTileDialogDelegate
-                .Adapter(bluetoothTileDialogCallback)
-                .DeviceItemViewHolder(view)
-        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
-        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
-
-        assertThat(container).isNotNull()
-        assertThat(container.isEnabled).isTrue()
-        assertThat(container.hasOnClickListeners()).isTrue()
-    }
-
-    @Test
-    fun testDeviceItemViewHolder_cachedDeviceBusy() {
-        deviceItem.isEnabled = false
-
-        val view =
-            LayoutInflater.from(mContext).inflate(R.layout.bluetooth_device_item, null, false)
-        val viewHolder =
-            BluetoothTileDialogDelegate(
-                    uiProperties,
-                    CONTENT_HEIGHT,
-                    ENABLED,
-                    bluetoothTileDialogCallback,
-                    {},
-                    dispatcher,
-                    fakeSystemClock,
-                    uiEventLogger,
-                    logger,
-                    sysuiDialogFactory,
-                )
-                .Adapter(bluetoothTileDialogCallback)
-                .DeviceItemViewHolder(view)
-        viewHolder.bind(deviceItem, bluetoothTileDialogCallback)
-        val container = view.requireViewById<View>(R.id.bluetooth_device_row)
-
-        assertThat(container).isNotNull()
-        assertThat(container.isEnabled).isFalse()
-        assertThat(container.hasOnClickListeners()).isTrue()
-    }
-
-    @Test
-    fun testOnDeviceUpdated_hideSeeAll_showPairNew() {
-        testScope.runTest {
-            val dialog = mBluetoothTileDialogDelegate.createDialog()
-            dialog.show()
-            fakeSystemClock.setElapsedRealtime(Long.MAX_VALUE)
-            mBluetoothTileDialogDelegate.onDeviceItemUpdated(
-                dialog,
-                listOf(deviceItem),
-                showSeeAll = false,
-                showPairNewDevice = true
-            )
-
-            val seeAllButton = dialog.requireViewById<View>(R.id.see_all_button)
-            val pairNewButton = dialog.requireViewById<View>(R.id.pair_new_device_button)
-            val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
-            val adapter = recyclerView?.adapter as BluetoothTileDialogDelegate.Adapter
-            val scrollViewContent = dialog.requireViewById<View>(R.id.scroll_view)
-
-            assertThat(seeAllButton).isNotNull()
-            assertThat(seeAllButton.visibility).isEqualTo(GONE)
-            assertThat(pairNewButton).isNotNull()
-            assertThat(pairNewButton.visibility).isEqualTo(VISIBLE)
-            assertThat(adapter.itemCount).isEqualTo(1)
-            assertThat(scrollViewContent.layoutParams.height).isEqualTo(WRAP_CONTENT)
-        }
-    }
-
-    @Test
-    fun testShowDialog_cachedHeightLargerThanMinHeight_displayFromCachedHeight() {
-        testScope.runTest {
-            val cachedHeight = Int.MAX_VALUE
-            val dialog =
-                BluetoothTileDialogDelegate(
-                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
-                        cachedHeight,
-                        ENABLED,
-                        bluetoothTileDialogCallback,
-                        {},
-                        dispatcher,
-                        fakeSystemClock,
-                        uiEventLogger,
-                        logger,
-                        sysuiDialogFactory,
-                    )
-                    .createDialog()
-            dialog.show()
-            assertThat(dialog.requireViewById<View>(R.id.scroll_view).layoutParams.height)
-                .isEqualTo(cachedHeight)
-        }
-    }
-
-    @Test
-    fun testShowDialog_cachedHeightLessThanMinHeight_displayFromUiProperties() {
-        testScope.runTest {
-            val dialog =
-                BluetoothTileDialogDelegate(
-                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
-                        MATCH_PARENT,
-                        ENABLED,
-                        bluetoothTileDialogCallback,
-                        {},
-                        dispatcher,
-                        fakeSystemClock,
-                        uiEventLogger,
-                        logger,
-                        sysuiDialogFactory,
-                    )
-                    .createDialog()
-            dialog.show()
-            assertThat(dialog.requireViewById<View>(R.id.scroll_view).layoutParams.height)
-                .isGreaterThan(MATCH_PARENT)
-        }
-    }
-
-    @Test
-    fun testShowDialog_bluetoothEnabled_autoOnToggleGone() {
-        testScope.runTest {
-            val dialog =
-                BluetoothTileDialogDelegate(
-                        BluetoothTileDialogViewModel.UiProperties.build(ENABLED, ENABLED),
-                        MATCH_PARENT,
-                        ENABLED,
-                        bluetoothTileDialogCallback,
-                        {},
-                        dispatcher,
-                        fakeSystemClock,
-                        uiEventLogger,
-                        logger,
-                        sysuiDialogFactory,
-                    )
-                    .createDialog()
-            dialog.show()
-            assertThat(
-                    dialog.requireViewById<View>(R.id.bluetooth_auto_on_toggle_layout).visibility
-                )
-                .isEqualTo(GONE)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogRepositoryTest.kt
deleted file mode 100644
index da8f60a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogRepositoryTest.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.SysuiTestCase
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class BluetoothTileDialogRepositoryTest : SysuiTestCase() {
-
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-
-    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
-
-    @Mock private lateinit var bluetoothAdapter: BluetoothAdapter
-
-    @Mock private lateinit var cachedDeviceManager: CachedBluetoothDeviceManager
-
-    @Mock private lateinit var cachedDevicesCopy: Collection<CachedBluetoothDevice>
-
-    private lateinit var repository: BluetoothTileDialogRepository
-
-    @Before
-    fun setUp() {
-        `when`(localBluetoothManager.cachedDeviceManager).thenReturn(cachedDeviceManager)
-        `when`(cachedDeviceManager.cachedDevicesCopy).thenReturn(cachedDevicesCopy)
-
-        repository = BluetoothTileDialogRepository(localBluetoothManager, bluetoothAdapter)
-    }
-
-    @Test
-    fun testCachedDevices_bluetoothOff_emptyList() {
-        `when`(bluetoothAdapter.isEnabled).thenReturn(false)
-
-        val result = repository.cachedDevices
-
-        assertThat(result).isEmpty()
-    }
-
-    @Test
-    fun testCachedDevices_bluetoothOn_returnDevice() {
-        `when`(bluetoothAdapter.isEnabled).thenReturn(true)
-
-        val result = repository.cachedDevices
-
-        assertThat(result).isEqualTo(cachedDevicesCopy)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
deleted file mode 100644
index c8a2aa6..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
-import android.widget.LinearLayout
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.settingslib.flags.Flags
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.util.FakeSharedPreferences
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.kotlin.getMutableStateFlow
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.nullable
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.test.TestCoroutineScheduler
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class BluetoothTileDialogViewModelTest : SysuiTestCase() {
-
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-    private val fakeSystemClock = FakeSystemClock()
-    private val backgroundExecutor = FakeExecutor(fakeSystemClock)
-
-    private lateinit var bluetoothTileDialogViewModel: BluetoothTileDialogViewModel
-
-    @Mock private lateinit var bluetoothStateInteractor: BluetoothStateInteractor
-
-    @Mock private lateinit var bluetoothAutoOnInteractor: BluetoothAutoOnInteractor
-
-    @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor
-
-    @Mock private lateinit var activityStarter: ActivityStarter
-
-    @Mock private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator
-
-    @Mock private lateinit var cachedBluetoothDevice: CachedBluetoothDevice
-
-    @Mock private lateinit var deviceItem: DeviceItem
-
-    @Mock private lateinit var uiEventLogger: UiEventLogger
-
-    @Mock private lateinit var bluetoothAdapter: BluetoothAdapter
-
-    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
-
-    @Mock
-    private lateinit var mBluetoothTileDialogDelegateDelegateFactory:
-        BluetoothTileDialogDelegate.Factory
-
-    @Mock private lateinit var bluetoothTileDialogDelegate: BluetoothTileDialogDelegate
-
-    @Mock private lateinit var sysuiDialog: SystemUIDialog
-
-    private val sharedPreferences = FakeSharedPreferences()
-
-    private lateinit var scheduler: TestCoroutineScheduler
-    private lateinit var dispatcher: CoroutineDispatcher
-    private lateinit var testScope: TestScope
-
-    @Before
-    fun setUp() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE)
-        scheduler = TestCoroutineScheduler()
-        dispatcher = UnconfinedTestDispatcher(scheduler)
-        testScope = TestScope(dispatcher)
-        bluetoothTileDialogViewModel =
-            BluetoothTileDialogViewModel(
-                deviceItemInteractor,
-                bluetoothStateInteractor,
-                // TODO(b/316822488): Create FakeBluetoothAutoOnInteractor.
-                BluetoothAutoOnInteractor(
-                    BluetoothAutoOnRepository(
-                        localBluetoothManager,
-                        bluetoothAdapter,
-                        testScope.backgroundScope,
-                        dispatcher
-                    )
-                ),
-                mDialogTransitionAnimator,
-                activityStarter,
-                uiEventLogger,
-                testScope.backgroundScope,
-                dispatcher,
-                dispatcher,
-                sharedPreferences,
-                mBluetoothTileDialogDelegateDelegateFactory
-            )
-        whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
-        whenever(bluetoothStateInteractor.bluetoothStateUpdate)
-            .thenReturn(MutableStateFlow(null).asStateFlow())
-        whenever(deviceItemInteractor.deviceItemUpdateRequest)
-            .thenReturn(MutableStateFlow(Unit).asStateFlow())
-        whenever(bluetoothStateInteractor.isBluetoothEnabled).thenReturn(true)
-        whenever(
-                mBluetoothTileDialogDelegateDelegateFactory.create(
-                    any(),
-                    anyInt(),
-                    ArgumentMatchers.anyBoolean(),
-                    any(),
-                    any()
-                )
-            )
-            .thenReturn(bluetoothTileDialogDelegate)
-        whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog)
-        whenever(sysuiDialog.context).thenReturn(mContext)
-        whenever(bluetoothTileDialogDelegate.bluetoothStateToggle)
-            .thenReturn(getMutableStateFlow(false))
-        whenever(bluetoothTileDialogDelegate.deviceItemClick)
-            .thenReturn(getMutableStateFlow(deviceItem))
-        whenever(bluetoothTileDialogDelegate.contentHeight).thenReturn(getMutableStateFlow(0))
-        whenever(bluetoothTileDialogDelegate.bluetoothAutoOnToggle)
-            .thenReturn(getMutableStateFlow(false))
-    }
-
-    @Test
-    fun testShowDialog_noAnimation() {
-        testScope.runTest {
-            bluetoothTileDialogViewModel.showDialog(null)
-
-            verify(mDialogTransitionAnimator, never()).showFromView(any(), any(), any(), any())
-        }
-    }
-
-    @Test
-    fun testShowDialog_animated() {
-        testScope.runTest {
-            bluetoothTileDialogViewModel.showDialog(LinearLayout(mContext))
-
-            verify(mDialogTransitionAnimator).showFromView(any(), any(), nullable(), anyBoolean())
-        }
-    }
-
-    @Test
-    fun testShowDialog_animated_callInBackgroundThread() {
-        testScope.runTest {
-            backgroundExecutor.execute {
-                bluetoothTileDialogViewModel.showDialog(LinearLayout(mContext))
-
-                verify(mDialogTransitionAnimator)
-                    .showFromView(any(), any(), nullable(), anyBoolean())
-            }
-        }
-    }
-
-    @Test
-    fun testShowDialog_fetchDeviceItem() {
-        testScope.runTest {
-            bluetoothTileDialogViewModel.showDialog(null)
-
-            verify(deviceItemInteractor).deviceItemUpdate
-        }
-    }
-
-    @Test
-    fun testShowDialog_withBluetoothStateValue() {
-        testScope.runTest {
-            bluetoothTileDialogViewModel.showDialog(null)
-
-            verify(bluetoothStateInteractor).bluetoothStateUpdate
-        }
-    }
-
-    @Test
-    fun testStartSettingsActivity_activityLaunched_dialogDismissed() {
-        testScope.runTest {
-            whenever(deviceItem.cachedBluetoothDevice).thenReturn(cachedBluetoothDevice)
-            bluetoothTileDialogViewModel.showDialog(null)
-
-            val clickedView = View(context)
-            bluetoothTileDialogViewModel.onPairNewDeviceClicked(clickedView)
-
-            verify(uiEventLogger).log(BluetoothTileDialogUiEvent.PAIR_NEW_DEVICE_CLICKED)
-            verify(activityStarter).postStartActivityDismissingKeyguard(any(), anyInt(), nullable())
-        }
-    }
-
-    @Test
-    fun testBuildUiProperties_bluetoothOn_shouldHideAutoOn() {
-        testScope.runTest {
-            val actual =
-                BluetoothTileDialogViewModel.UiProperties.build(
-                    isBluetoothEnabled = true,
-                    isAutoOnToggleFeatureAvailable = true
-                )
-            assertThat(actual.autoOnToggleVisibility).isEqualTo(GONE)
-        }
-    }
-
-    @Test
-    fun testBuildUiProperties_bluetoothOff_shouldShowAutoOn() {
-        testScope.runTest {
-            val actual =
-                BluetoothTileDialogViewModel.UiProperties.build(
-                    isBluetoothEnabled = false,
-                    isAutoOnToggleFeatureAvailable = true
-                )
-            assertThat(actual.autoOnToggleVisibility).isEqualTo(VISIBLE)
-        }
-    }
-
-    @Test
-    fun testBuildUiProperties_bluetoothOff_autoOnFeatureUnavailable_shouldHideAutoOn() {
-        testScope.runTest {
-            val actual =
-                BluetoothTileDialogViewModel.UiProperties.build(
-                    isBluetoothEnabled = false,
-                    isAutoOnToggleFeatureAvailable = false
-                )
-            assertThat(actual.autoOnToggleVisibility).isEqualTo(GONE)
-        }
-    }
-
-    @Test
-    fun testIsAutoOnToggleFeatureAvailable_returnTrue() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(true)
-
-            val actual = bluetoothTileDialogViewModel.isAutoOnToggleFeatureAvailable()
-            assertThat(actual).isTrue()
-        }
-    }
-
-    @Test
-    fun testIsAutoOnToggleFeatureAvailable_returnFalse() {
-        testScope.runTest {
-            whenever(bluetoothAdapter.isAutoOnSupported).thenReturn(false)
-
-            val actual = bluetoothTileDialogViewModel.isAutoOnToggleFeatureAvailable()
-            assertThat(actual).isFalse()
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactoryTest.kt
deleted file mode 100644
index a8cd8c8..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactoryTest.kt
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothDevice
-import android.content.pm.PackageInfo
-import android.content.pm.PackageManager
-import android.media.AudioManager
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.settingslib.bluetooth.BluetoothUtils
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.flags.Flags
-import com.android.systemui.SysuiTestCase
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class DeviceItemFactoryTest : SysuiTestCase() {
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-
-    @Mock private lateinit var cachedDevice: CachedBluetoothDevice
-    @Mock private lateinit var bluetoothDevice: BluetoothDevice
-    @Mock private lateinit var packageManager: PackageManager
-
-    private val availableMediaDeviceItemFactory = AvailableMediaDeviceItemFactory()
-    private val connectedDeviceItemFactory = ConnectedDeviceItemFactory()
-    private val savedDeviceItemFactory = SavedDeviceItemFactory()
-
-    private val audioManager = context.getSystemService(AudioManager::class.java)!!
-
-    @Before
-    fun setup() {
-        `when`(cachedDevice.name).thenReturn(DEVICE_NAME)
-        `when`(cachedDevice.address).thenReturn(DEVICE_ADDRESS)
-        `when`(cachedDevice.device).thenReturn(bluetoothDevice)
-        `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY)
-
-        context.setMockPackageManager(packageManager)
-    }
-
-    @Test
-    fun testAvailableMediaDeviceItemFactory_createFromCachedDevice() {
-        val deviceItem = availableMediaDeviceItemFactory.create(context, cachedDevice)
-
-        assertDeviceItem(deviceItem, DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE)
-    }
-
-    @Test
-    fun testConnectedDeviceItemFactory_createFromCachedDevice() {
-        val deviceItem = connectedDeviceItemFactory.create(context, cachedDevice)
-
-        assertDeviceItem(deviceItem, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-    }
-
-    @Test
-    fun testSavedDeviceItemFactory_createFromCachedDevice() {
-        val deviceItem = savedDeviceItemFactory.create(context, cachedDevice)
-
-        assertDeviceItem(deviceItem, DeviceItemType.SAVED_BLUETOOTH_DEVICE)
-        assertThat(deviceItem.background).isNotNull()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTrue() {
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_connected_returnsFalse() {
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(true)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() {
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
-        val exclusiveManagerName =
-            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
-        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
-            .thenReturn(exclusiveManagerName.toByteArray())
-        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo())
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_noExclusiveManager_returnsTrue() {
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() {
-        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
-            .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray())
-        `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0))
-            .thenReturn(PackageInfo())
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() {
-        val exclusiveManagerName =
-            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
-        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
-            .thenReturn(exclusiveManagerName.toByteArray())
-        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0))
-            .thenThrow(PackageManager.NameNotFoundException("Test!"))
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() {
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
-        `when`(cachedDevice.isConnected).thenReturn(false)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalse() {
-        `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(cachedDevice.isConnected).thenReturn(true)
-
-        assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() {
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() {
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(false)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_notBonded_returnsFalse() {
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() {
-        val exclusiveManagerName =
-            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
-        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
-            .thenReturn(exclusiveManagerName.toByteArray())
-        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo())
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTrue() {
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() {
-        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
-            .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray())
-        `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0))
-            .thenReturn(PackageInfo())
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() {
-        val exclusiveManagerName =
-            BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME
-        `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER))
-            .thenReturn(exclusiveManagerName.toByteArray())
-        `when`(packageManager.getPackageInfo(exclusiveManagerName, 0))
-            .thenThrow(PackageManager.NameNotFoundException("Test!"))
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isTrue()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() {
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
-        `when`(bluetoothDevice.isConnected).thenReturn(true)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
-    fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalse() {
-        `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
-        `when`(bluetoothDevice.isConnected).thenReturn(false)
-        audioManager.setMode(AudioManager.MODE_NORMAL)
-
-        assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
-            .isFalse()
-    }
-
-    private fun assertDeviceItem(deviceItem: DeviceItem?, deviceItemType: DeviceItemType) {
-        assertThat(deviceItem).isNotNull()
-        assertThat(deviceItem!!.type).isEqualTo(deviceItemType)
-        assertThat(deviceItem.cachedBluetoothDevice).isEqualTo(cachedDevice)
-        assertThat(deviceItem.deviceName).isEqualTo(DEVICE_NAME)
-        assertThat(deviceItem.connectionSummary).isEqualTo(CONNECTION_SUMMARY)
-    }
-
-    companion object {
-        const val DEVICE_NAME = "DeviceName"
-        const val CONNECTION_SUMMARY = "ConnectionSummary"
-        private const val FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name"
-        private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C"
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractorTest.kt
deleted file mode 100644
index ddf0b9a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractorTest.kt
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.dialog.bluetooth
-
-import android.bluetooth.BluetoothAdapter
-import android.bluetooth.BluetoothDevice
-import android.content.Context
-import android.media.AudioManager
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.bluetooth.CachedBluetoothDevice
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
-class DeviceItemInteractorTest : SysuiTestCase() {
-
-    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
-
-    @Mock private lateinit var bluetoothTileDialogRepository: BluetoothTileDialogRepository
-
-    @Mock private lateinit var cachedDevice1: CachedBluetoothDevice
-
-    @Mock private lateinit var cachedDevice2: CachedBluetoothDevice
-
-    @Mock private lateinit var device1: BluetoothDevice
-
-    @Mock private lateinit var device2: BluetoothDevice
-
-    @Mock private lateinit var deviceItem1: DeviceItem
-
-    @Mock private lateinit var deviceItem2: DeviceItem
-
-    @Mock private lateinit var audioManager: AudioManager
-
-    @Mock private lateinit var adapter: BluetoothAdapter
-
-    @Mock private lateinit var localBluetoothManager: LocalBluetoothManager
-
-    @Mock private lateinit var uiEventLogger: UiEventLogger
-
-    @Mock private lateinit var logger: BluetoothTileDialogLogger
-
-    private val fakeSystemClock = FakeSystemClock()
-
-    private lateinit var interactor: DeviceItemInteractor
-
-    private lateinit var dispatcher: CoroutineDispatcher
-
-    private lateinit var testScope: TestScope
-
-    @Before
-    fun setUp() {
-        dispatcher = UnconfinedTestDispatcher()
-        testScope = TestScope(dispatcher)
-        interactor =
-            DeviceItemInteractor(
-                bluetoothTileDialogRepository,
-                audioManager,
-                adapter,
-                localBluetoothManager,
-                fakeSystemClock,
-                uiEventLogger,
-                logger,
-                testScope.backgroundScope,
-                dispatcher
-            )
-
-        `when`(deviceItem1.cachedBluetoothDevice).thenReturn(cachedDevice1)
-        `when`(deviceItem2.cachedBluetoothDevice).thenReturn(cachedDevice2)
-        `when`(cachedDevice1.address).thenReturn("ADDRESS")
-        `when`(cachedDevice1.device).thenReturn(device1)
-        `when`(cachedDevice2.device).thenReturn(device2)
-        `when`(bluetoothTileDialogRepository.cachedDevices)
-            .thenReturn(listOf(cachedDevice1, cachedDevice2))
-    }
-
-    @Test
-    fun testUpdateDeviceItems_noCachedDevice_returnEmpty() {
-        testScope.runTest {
-            `when`(bluetoothTileDialogRepository.cachedDevices).thenReturn(emptyList())
-            interactor.setDeviceItemFactoryListForTesting(
-                listOf(createFactory({ true }, deviceItem1))
-            )
-
-            val latest by collectLastValue(interactor.deviceItemUpdate)
-            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
-
-            assertThat(latest).isEqualTo(emptyList<DeviceItem>())
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItems_hasCachedDevice_filterNotMatch_returnEmpty() {
-        testScope.runTest {
-            `when`(bluetoothTileDialogRepository.cachedDevices).thenReturn(listOf(cachedDevice1))
-            interactor.setDeviceItemFactoryListForTesting(
-                listOf(createFactory({ false }, deviceItem1))
-            )
-
-            val latest by collectLastValue(interactor.deviceItemUpdate)
-            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
-
-            assertThat(latest).isEqualTo(emptyList<DeviceItem>())
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItems_hasCachedDevice_filterMatch_returnDeviceItem() {
-        testScope.runTest {
-            `when`(bluetoothTileDialogRepository.cachedDevices).thenReturn(listOf(cachedDevice1))
-            interactor.setDeviceItemFactoryListForTesting(
-                listOf(createFactory({ true }, deviceItem1))
-            )
-
-            val latest by collectLastValue(interactor.deviceItemUpdate)
-            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
-
-            assertThat(latest).isEqualTo(listOf(deviceItem1))
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItems_hasCachedDevice_filterMatch_returnMultipleDeviceItem() {
-        testScope.runTest {
-            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null)
-            interactor.setDeviceItemFactoryListForTesting(
-                listOf(createFactory({ false }, deviceItem1), createFactory({ true }, deviceItem2))
-            )
-
-            val latest by collectLastValue(interactor.deviceItemUpdate)
-            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
-
-            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2))
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItems_sortByDisplayPriority() {
-        testScope.runTest {
-            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null)
-            interactor.setDeviceItemFactoryListForTesting(
-                listOf(
-                    createFactory({ cachedDevice -> cachedDevice.device == device1 }, deviceItem1),
-                    createFactory({ cachedDevice -> cachedDevice.device == device2 }, deviceItem2)
-                )
-            )
-            interactor.setDisplayPriorityForTesting(
-                listOf(
-                    DeviceItemType.SAVED_BLUETOOTH_DEVICE,
-                    DeviceItemType.CONNECTED_BLUETOOTH_DEVICE
-                )
-            )
-            `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-            `when`(deviceItem2.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
-
-            val latest by collectLastValue(interactor.deviceItemUpdate)
-            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
-
-            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItems_sameType_sortByRecentlyConnected() {
-        testScope.runTest {
-            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(listOf(device2, device1))
-            interactor.setDeviceItemFactoryListForTesting(
-                listOf(
-                    createFactory({ cachedDevice -> cachedDevice.device == device1 }, deviceItem1),
-                    createFactory({ cachedDevice -> cachedDevice.device == device2 }, deviceItem2)
-                )
-            )
-            interactor.setDisplayPriorityForTesting(
-                listOf(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-            )
-            `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-            `when`(deviceItem2.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-
-            val latest by collectLastValue(interactor.deviceItemUpdate)
-            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
-
-            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItemOnClick_connectedMedia_setActive() {
-        testScope.runTest {
-            `when`(deviceItem1.type).thenReturn(DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE)
-
-            interactor.updateDeviceItemOnClick(deviceItem1)
-
-            verify(cachedDevice1).setActive()
-            verify(logger)
-                .logDeviceClick(
-                    cachedDevice1.address,
-                    DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE
-                )
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItemOnClick_activeMedia_disconnect() {
-        testScope.runTest {
-            `when`(deviceItem1.type).thenReturn(DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
-
-            interactor.updateDeviceItemOnClick(deviceItem1)
-
-            verify(cachedDevice1).disconnect()
-            verify(logger)
-                .logDeviceClick(cachedDevice1.address, DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItemOnClick_connectedOtherDevice_disconnect() {
-        testScope.runTest {
-            `when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-
-            interactor.updateDeviceItemOnClick(deviceItem1)
-
-            verify(cachedDevice1).disconnect()
-            verify(logger)
-                .logDeviceClick(cachedDevice1.address, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
-        }
-    }
-
-    @Test
-    fun testUpdateDeviceItemOnClick_saved_connect() {
-        testScope.runTest {
-            `when`(deviceItem1.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
-
-            interactor.updateDeviceItemOnClick(deviceItem1)
-
-            verify(cachedDevice1).connect()
-            verify(logger)
-                .logDeviceClick(cachedDevice1.address, DeviceItemType.SAVED_BLUETOOTH_DEVICE)
-        }
-    }
-
-    private fun createFactory(
-        isFilterMatchFunc: (CachedBluetoothDevice) -> Boolean,
-        deviceItem: DeviceItem
-    ): DeviceItemFactory {
-        return object : DeviceItemFactory() {
-            override fun isFilterMatched(
-                context: Context,
-                cachedDevice: CachedBluetoothDevice,
-                audioManager: AudioManager?
-            ) = isFilterMatchFunc(cachedDevice)
-
-            override fun create(context: Context, cachedDevice: CachedBluetoothDevice) = deviceItem
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index 1313227..387f27d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -42,7 +42,6 @@
 import com.android.systemui.navigationbar.NavigationBarController
 import com.android.systemui.navigationbar.NavigationModeController
 import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
 import com.android.systemui.settings.FakeDisplayTracker
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.ShadeViewController
@@ -249,7 +248,6 @@
             sysuiUnlockAnimationController,
             inWindowLauncherUnlockAnimationManager,
             assistUtils,
-            FakeSceneContainerFlags(),
             dumpManager,
             unfoldTransitionProgressForwarder,
             broadcastDispatcher
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt
index 9104f8e..6846c72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt
@@ -88,6 +88,7 @@
     private lateinit var dialog: SystemUIDialog
     private lateinit var factory: SystemUIDialog.Factory
     private lateinit var latch: CountDownLatch
+    private var issueRecordingState = IssueRecordingState()
 
     @Before
     fun setup() {
@@ -128,6 +129,7 @@
                     mediaProjectionMetricsLogger,
                     userFileManager,
                     screenCaptureDisabledDialogDelegate,
+                    issueRecordingState,
                 ) {
                     latch.countDown()
                 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
deleted file mode 100644
index 63a05d7..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/FakeWindowRootViewComponent.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.systemui.scene
-
-import com.android.systemui.scene.ui.view.WindowRootView
-import com.android.systemui.scene.ui.view.WindowRootViewComponent
-
-class FakeWindowRootViewComponent(private val view: WindowRootView) : WindowRootViewComponent {
-    override fun getWindowRootView(): WindowRootView {
-        return view
-    }
-
-    class Factory(private val view: WindowRootView) : WindowRootViewComponent.Factory {
-        override fun create(): WindowRootViewComponent = FakeWindowRootViewComponent(view)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
deleted file mode 100644
index 543f6c9..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.shared.flag
-
-import android.platform.test.annotations.DisableFlags
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.EnableSceneContainer
-import com.google.common.truth.Truth
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-internal class SceneContainerFlagsTest : SysuiTestCase() {
-
-    @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER)
-    fun isNotEnabled_withoutAconfigFlags() {
-        Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(false)
-        Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(false)
-    }
-
-    @Test
-    @EnableSceneContainer
-    fun isEnabled_withAconfigFlags() {
-        Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(true)
-        Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(true)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt
new file mode 100644
index 0000000..91f3912
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionExecutorTest.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.Bundle
+import android.os.UserHandle
+import android.testing.AndroidTestingRunner
+import android.view.View
+import android.view.Window
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Ignore
+import kotlin.test.Test
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.kotlin.capture
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.verifyBlocking
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ActionExecutorTest : SysuiTestCase() {
+    private val scheduler = TestCoroutineScheduler()
+    private val mainDispatcher = StandardTestDispatcher(scheduler)
+    private val testScope = TestScope(mainDispatcher)
+
+    private val intentExecutor = mock<ActionIntentExecutor>()
+    private val window = mock<Window>()
+    private val view = mock<View>()
+    private val onDismiss = mock<(() -> Unit)>()
+    private val pendingIntent = mock<PendingIntent>()
+
+    private lateinit var actionExecutor: ActionExecutor
+
+    @Ignore // Fixed with newer mockito version (in main)
+    @Test
+    fun startSharedTransition_callsLaunchIntent() = runTest {
+        actionExecutor = createActionExecutor()
+
+        actionExecutor.startSharedTransition(Intent(Intent.ACTION_EDIT), UserHandle.CURRENT, true)
+        scheduler.advanceUntilIdle()
+
+        val intentCaptor = argumentCaptor<Intent>()
+        verifyBlocking(intentExecutor) {
+            launchIntent(capture(intentCaptor), eq(UserHandle.CURRENT), eq(true), any(), any())
+        }
+        assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_EDIT)
+    }
+
+    @Test
+    fun sendPendingIntent_dismisses() = runTest {
+        actionExecutor = createActionExecutor()
+
+        actionExecutor.sendPendingIntent(pendingIntent)
+
+        verify(pendingIntent).send(any(Bundle::class.java))
+        verify(onDismiss).invoke()
+    }
+
+    private fun createActionExecutor(): ActionExecutor {
+        return ActionExecutor(intentExecutor, testScope, window, view, onDismiss)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt
index 0c32470..5e53fe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt
@@ -64,7 +64,7 @@
             val intent = Intent(Intent.ACTION_EDIT).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK }
             val userHandle = myUserHandle()
 
-            actionIntentExecutor.launchIntent(intent, null, userHandle, false)
+            actionIntentExecutor.launchIntent(intent, userHandle, false, null, null)
             scheduler.advanceUntilIdle()
 
             verify(activityManagerWrapper)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt
index 4a5cf57..853e50a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt
@@ -16,65 +16,38 @@
 
 package com.android.systemui.screenshot
 
-import android.app.ActivityOptions
-import android.app.ExitTransitionCoordinator
-import android.app.Notification
-import android.app.PendingIntent
 import android.content.Intent
 import android.net.Uri
+import android.os.Process
 import android.os.UserHandle
 import android.testing.AndroidTestingRunner
 import android.view.accessibility.AccessibilityManager
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.clipboardoverlay.EditTextActivity
-import com.android.systemui.res.R
 import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
-import kotlin.test.Ignore
 import kotlin.test.Test
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestCoroutineScheduler
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Assert.assertNotNull
 import org.junit.Before
 import org.junit.runner.RunWith
 import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.kotlin.any
-import org.mockito.kotlin.never
 import org.mockito.kotlin.verify
-import org.mockito.kotlin.verifyBlocking
-import org.mockito.kotlin.whenever
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
 class DefaultScreenshotActionsProviderTest : SysuiTestCase() {
-    private val scheduler = TestCoroutineScheduler()
-    private val mainDispatcher = StandardTestDispatcher(scheduler)
-    private val testScope = TestScope(mainDispatcher)
-
-    private val actionIntentExecutor = mock<ActionIntentExecutor>()
+    private val actionExecutor = mock<ActionExecutor>()
     private val accessibilityManager = mock<AccessibilityManager>()
     private val uiEventLogger = mock<UiEventLogger>()
-    private val smartActionsProvider = mock<SmartActionsProvider>()
-    private val transition = mock<android.util.Pair<ActivityOptions, ExitTransitionCoordinator>>()
-    private val requestDismissal = mock<() -> Unit>()
 
     private val request = ScreenshotData.forTesting()
-    private val invalidResult = ScreenshotController.SavedImageData()
-    private val validResult =
-        ScreenshotController.SavedImageData().apply {
-            uri = Uri.EMPTY
-            owner = UserHandle.OWNER
-            subject = "Test"
-            imageTime = 0
-        }
+    private val validResult = ScreenshotSavedResult(Uri.EMPTY, Process.myUserHandle(), 0)
 
     private lateinit var viewModel: ScreenshotViewModel
     private lateinit var actionsProvider: ScreenshotActionsProvider
@@ -91,7 +64,7 @@
 
         assertNotNull(viewModel.previewAction.value)
         viewModel.previewAction.value!!.invoke()
-        verifyNoMoreInteractions(actionIntentExecutor)
+        verifyNoMoreInteractions(actionExecutor)
     }
 
     @Test
@@ -105,39 +78,24 @@
         assertThat(secondAction.onClicked).isNotNull()
         firstAction.onClicked!!.invoke()
         secondAction.onClicked!!.invoke()
-        verifyNoMoreInteractions(actionIntentExecutor)
+        verifyNoMoreInteractions(actionExecutor)
     }
 
     @Test
-    fun actionAccessed_withInvalidResult_doesNothing() {
-        actionsProvider = createActionsProvider()
-
-        actionsProvider.setCompletedScreenshot(invalidResult)
-        viewModel.previewAction.value!!.invoke()
-        viewModel.actions.value[1].onClicked!!.invoke()
-
-        verifyNoMoreInteractions(actionIntentExecutor)
-    }
-
-    @Test
-    @Ignore("b/332526567")
     fun actionAccessed_withResult_launchesIntent() = runTest {
         actionsProvider = createActionsProvider()
 
         actionsProvider.setCompletedScreenshot(validResult)
         viewModel.actions.value[0].onClicked!!.invoke()
-        scheduler.advanceUntilIdle()
 
         verify(uiEventLogger).log(eq(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED), eq(0), eq(""))
         val intentCaptor = argumentCaptor<Intent>()
-        verifyBlocking(actionIntentExecutor) {
-            launchIntent(capture(intentCaptor), eq(transition), eq(UserHandle.CURRENT), eq(true))
-        }
+        verify(actionExecutor)
+            .startSharedTransition(capture(intentCaptor), eq(Process.myUserHandle()), eq(true))
         assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_EDIT)
     }
 
     @Test
-    @Ignore("b/332526567")
     fun actionAccessed_whilePending_launchesMostRecentAction() = runTest {
         actionsProvider = createActionsProvider()
 
@@ -145,59 +103,22 @@
         viewModel.previewAction.value!!.invoke()
         viewModel.actions.value[1].onClicked!!.invoke()
         actionsProvider.setCompletedScreenshot(validResult)
-        scheduler.advanceUntilIdle()
 
         verify(uiEventLogger).log(eq(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED), eq(0), eq(""))
         val intentCaptor = argumentCaptor<Intent>()
-        verifyBlocking(actionIntentExecutor) {
-            launchIntent(capture(intentCaptor), eq(transition), eq(UserHandle.CURRENT), eq(false))
-        }
+        verify(actionExecutor)
+            .startSharedTransition(capture(intentCaptor), eq(Process.myUserHandle()), eq(false))
         assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_CHOOSER)
     }
 
-    @Test
-    fun quickShareTapped_wrapsAndSendsIntent() = runTest {
-        val quickShare =
-            Notification.Action(
-                R.drawable.ic_screenshot_edit,
-                "TestQuickShare",
-                PendingIntent.getActivity(
-                    context,
-                    0,
-                    Intent(context, EditTextActivity::class.java),
-                    PendingIntent.FLAG_MUTABLE
-                )
-            )
-        whenever(smartActionsProvider.requestQuickShare(any(), any(), any())).then {
-            (it.getArgument(2) as ((Notification.Action) -> Unit)).invoke(quickShare)
-        }
-        whenever(smartActionsProvider.wrapIntent(any(), any(), any(), any())).thenAnswer {
-            it.getArgument(0)
-        }
-        actionsProvider = createActionsProvider()
-
-        viewModel.actions.value[2].onClicked?.invoke()
-        verify(uiEventLogger, never())
-            .log(eq(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED), any(), any())
-        verify(smartActionsProvider, never()).wrapIntent(any(), any(), any(), any())
-        actionsProvider.setCompletedScreenshot(validResult)
-        verify(smartActionsProvider)
-            .wrapIntent(eq(quickShare), eq(validResult.uri), eq(validResult.subject), eq("testid"))
-        verify(uiEventLogger).log(eq(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED), eq(0), eq(""))
-    }
-
     private fun createActionsProvider(): ScreenshotActionsProvider {
         return DefaultScreenshotActionsProvider(
             context,
             viewModel,
-            actionIntentExecutor,
-            smartActionsProvider,
             uiEventLogger,
-            testScope,
             request,
             "testid",
-            { transition },
-            requestDismissal,
+            actionExecutor
         )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
index 587da2d..3756ec1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
@@ -18,11 +18,6 @@
 
 import android.app.ActivityTaskManager.RootTaskInfo
 import android.app.IActivityTaskManager
-import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
-import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
-import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
-import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
-import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
 import android.content.ComponentName
 import android.content.Context
 import android.graphics.Rect
@@ -31,6 +26,12 @@
 import android.testing.AndroidTestingRunner
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
+import com.android.systemui.screenshot.policy.ActivityType.Home
+import com.android.systemui.screenshot.policy.ActivityType.Undefined
+import com.android.systemui.screenshot.policy.WindowingMode.FullScreen
+import com.android.systemui.screenshot.policy.WindowingMode.PictureInPicture
+import com.android.systemui.screenshot.policy.newChildTask
+import com.android.systemui.screenshot.policy.newRootTaskInfo
 import com.android.systemui.settings.FakeDisplayTracker
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -58,20 +59,19 @@
                     ),
                     Rect(0, 0, 1080, 2400),
                     UserHandle.of(MANAGED_PROFILE_USER),
-                    65))
+                    65
+                )
+            )
     }
 
     @Test
     fun findPrimaryContent_ignoresPipTask() = runBlocking {
-        val policy = fakeTasksPolicyImpl(
-            mContext,
-            shadeExpanded = false,
-            tasks = listOf(
-                    pipTask,
-                    fullScreenWorkProfileTask,
-                    launcherTask,
-                    emptyTask)
-        )
+        val policy =
+            fakeTasksPolicyImpl(
+                mContext,
+                shadeExpanded = false,
+                tasks = listOf(pipTask, fullScreenWorkProfileTask, launcherTask, emptyTask)
+            )
 
         val info = policy.findPrimaryContent(DISPLAY_ID)
         assertThat(info).isEqualTo(fullScreenWorkProfileTask.toDisplayContentInfo())
@@ -79,14 +79,12 @@
 
     @Test
     fun findPrimaryContent_shadeExpanded_ignoresTopTask() = runBlocking {
-        val policy = fakeTasksPolicyImpl(
-            mContext,
-            shadeExpanded = true,
-            tasks = listOf(
-                fullScreenWorkProfileTask,
-                launcherTask,
-                emptyTask)
-        )
+        val policy =
+            fakeTasksPolicyImpl(
+                mContext,
+                shadeExpanded = true,
+                tasks = listOf(fullScreenWorkProfileTask, launcherTask, emptyTask)
+            )
 
         val info = policy.findPrimaryContent(DISPLAY_ID)
         assertThat(info).isEqualTo(policy.systemUiContent)
@@ -94,11 +92,7 @@
 
     @Test
     fun findPrimaryContent_emptyTaskList() = runBlocking {
-        val policy = fakeTasksPolicyImpl(
-            mContext,
-            shadeExpanded = false,
-            tasks = listOf()
-        )
+        val policy = fakeTasksPolicyImpl(mContext, shadeExpanded = false, tasks = listOf())
 
         val info = policy.findPrimaryContent(DISPLAY_ID)
         assertThat(info).isEqualTo(policy.systemUiContent)
@@ -106,14 +100,12 @@
 
     @Test
     fun findPrimaryContent_workProfileNotOnTop() = runBlocking {
-        val policy = fakeTasksPolicyImpl(
-            mContext,
-            shadeExpanded = false,
-            tasks = listOf(
-                launcherTask,
-                fullScreenWorkProfileTask,
-                emptyTask)
-        )
+        val policy =
+            fakeTasksPolicyImpl(
+                mContext,
+                shadeExpanded = false,
+                tasks = listOf(launcherTask, fullScreenWorkProfileTask, emptyTask)
+            )
 
         val info = policy.findPrimaryContent(DISPLAY_ID)
         assertThat(info).isEqualTo(launcherTask.toDisplayContentInfo())
@@ -129,102 +121,80 @@
         val dispatcher = Dispatchers.Unconfined
         val displayTracker = FakeDisplayTracker(context)
 
-        return object : ScreenshotPolicyImpl(context, userManager, atmService, dispatcher,
-                displayTracker) {
+        return object :
+            ScreenshotPolicyImpl(context, userManager, atmService, dispatcher, displayTracker) {
             override suspend fun isManagedProfile(userId: Int) = (userId == MANAGED_PROFILE_USER)
             override suspend fun getAllRootTaskInfosOnDisplay(displayId: Int) = tasks
             override suspend fun isNotificationShadeExpanded() = shadeExpanded
         }
     }
 
-    private val pipTask = RootTaskInfo().apply {
-        configuration.windowConfiguration.apply {
-            windowingMode = WINDOWING_MODE_PINNED
-            setBounds(Rect(628, 1885, 1038, 2295))
-            activityType = ACTIVITY_TYPE_STANDARD
+    private val pipTask =
+        newRootTaskInfo(
+            taskId = 66,
+            userId = PRIMARY_USER,
+            displayId = DISPLAY_ID,
+            bounds = Rect(628, 1885, 1038, 2295),
+            windowingMode = PictureInPicture,
+            topActivity = ComponentName.unflattenFromString(YOUTUBE_PIP_ACTIVITY),
+        ) {
+            listOf(newChildTask(taskId = 66, userId = 0, name = YOUTUBE_HOME_ACTIVITY))
         }
-        displayId = DISPLAY_ID
-        userId = PRIMARY_USER
-        taskId = 66
-        visible = true
-        isVisible = true
-        isRunning = true
-        numActivities = 1
-        topActivity = ComponentName(
-            "com.google.android.youtube",
-            "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity"
-        )
-        childTaskIds = intArrayOf(66)
-        childTaskNames = arrayOf("com.google.android.youtube/" +
-                "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity")
-        childTaskUserIds = intArrayOf(0)
-        childTaskBounds = arrayOf(Rect(628, 1885, 1038, 2295))
-    }
 
-    private val fullScreenWorkProfileTask = RootTaskInfo().apply {
-        configuration.windowConfiguration.apply {
-            windowingMode = WINDOWING_MODE_FULLSCREEN
-            setBounds(Rect(0, 0, 1080, 2400))
-            activityType = ACTIVITY_TYPE_STANDARD
+    private val fullScreenWorkProfileTask =
+        newRootTaskInfo(
+            taskId = 65,
+            userId = MANAGED_PROFILE_USER,
+            displayId = DISPLAY_ID,
+            bounds = Rect(0, 0, 1080, 2400),
+            windowingMode = FullScreen,
+            topActivity = ComponentName.unflattenFromString(FILES_HOME_ACTIVITY),
+        ) {
+            listOf(
+                newChildTask(taskId = 65, userId = MANAGED_PROFILE_USER, name = FILES_HOME_ACTIVITY)
+            )
         }
-        displayId = DISPLAY_ID
-        userId = MANAGED_PROFILE_USER
-        taskId = 65
-        visible = true
-        isVisible = true
-        isRunning = true
-        numActivities = 1
-        topActivity = ComponentName(
-            "com.google.android.apps.nbu.files",
-            "com.google.android.apps.nbu.files.home.HomeActivity"
-        )
-        childTaskIds = intArrayOf(65)
-        childTaskNames = arrayOf("com.google.android.apps.nbu.files/" +
-                "com.google.android.apps.nbu.files.home.HomeActivity")
-        childTaskUserIds = intArrayOf(MANAGED_PROFILE_USER)
-        childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400))
-    }
+    private val launcherTask =
+        newRootTaskInfo(
+            taskId = 1,
+            userId = PRIMARY_USER,
+            displayId = DISPLAY_ID,
+            activityType = Home,
+            windowingMode = FullScreen,
+            bounds = Rect(0, 0, 1080, 2400),
+            topActivity = ComponentName.unflattenFromString(LAUNCHER_ACTIVITY),
+        ) {
+            listOf(newChildTask(taskId = 1, userId = 0, name = LAUNCHER_ACTIVITY))
+        }
 
-    private val launcherTask = RootTaskInfo().apply {
-        configuration.windowConfiguration.apply {
-            windowingMode = WINDOWING_MODE_FULLSCREEN
-            setBounds(Rect(0, 0, 1080, 2400))
-            activityType = ACTIVITY_TYPE_HOME
+    private val emptyTask =
+        newRootTaskInfo(
+            taskId = 2,
+            userId = PRIMARY_USER,
+            displayId = DISPLAY_ID,
+            visible = false,
+            running = false,
+            numActivities = 0,
+            activityType = Undefined,
+            bounds = Rect(0, 0, 1080, 2400),
+        ) {
+            listOf(
+                newChildTask(taskId = 3, name = ""),
+                newChildTask(taskId = 4, name = ""),
+            )
         }
-        displayId = DISPLAY_ID
-        taskId = 1
-        userId = PRIMARY_USER
-        visible = true
-        isVisible = true
-        isRunning = true
-        numActivities = 1
-        topActivity = ComponentName(
-            "com.google.android.apps.nexuslauncher",
-            "com.google.android.apps.nexuslauncher.NexusLauncherActivity",
-        )
-        childTaskIds = intArrayOf(1)
-        childTaskNames = arrayOf("com.google.android.apps.nexuslauncher/" +
-                "com.google.android.apps.nexuslauncher.NexusLauncherActivity")
-        childTaskUserIds = intArrayOf(0)
-        childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400))
-    }
-
-    private val emptyTask = RootTaskInfo().apply {
-        configuration.windowConfiguration.apply {
-            windowingMode = WINDOWING_MODE_FULLSCREEN
-            setBounds(Rect(0, 0, 1080, 2400))
-            activityType = ACTIVITY_TYPE_UNDEFINED
-        }
-        displayId = DISPLAY_ID
-        taskId = 2
-        userId = PRIMARY_USER
-        visible = false
-        isVisible = false
-        isRunning = false
-        numActivities = 0
-        childTaskIds = intArrayOf(3, 4)
-        childTaskNames = arrayOf("", "")
-        childTaskUserIds = intArrayOf(0, 0)
-        childTaskBounds = arrayOf(Rect(0, 0, 1080, 2400), Rect(0, 2400, 1080, 4800))
-    }
 }
+
+private const val YOUTUBE_HOME_ACTIVITY =
+    "com.google.android.youtube/" + "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity"
+
+private const val FILES_HOME_ACTIVITY =
+    "com.google.android.apps.nbu.files/" + "com.google.android.apps.nbu.files.home.HomeActivity"
+
+private const val YOUTUBE_PIP_ACTIVITY =
+    "com.google.android.youtube/" +
+        "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity"
+
+private const val LAUNCHER_ACTIVITY =
+    "com.google.android.apps.nexuslauncher/" +
+        "com.google.android.apps.nexuslauncher.NexusLauncherActivity"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
index c900463..0f37143 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import java.lang.IllegalStateException
+import java.util.function.Consumer
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runCurrent
@@ -78,7 +79,7 @@
     fun executeScreenshots_severalDisplays_callsControllerForEachOne() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             verify(controllerFactory).create(eq(0), any())
@@ -107,7 +108,7 @@
     fun executeScreenshots_providedImageType_callsOnlyDefaultDisplayController() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(
                 createScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE),
                 onSaved,
@@ -136,7 +137,7 @@
     fun executeScreenshots_onlyVirtualDisplays_noInteractionsWithControllers() =
         testScope.runTest {
             setDisplays(display(TYPE_VIRTUAL, id = 0), display(TYPE_VIRTUAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             verifyNoMoreInteractions(controllerFactory)
@@ -154,7 +155,7 @@
                 display(TYPE_OVERLAY, id = 2),
                 display(TYPE_WIFI, id = 3)
             )
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             verify(controller0, times(4)).handleScreenshot(any(), any(), any())
@@ -165,7 +166,7 @@
     fun executeScreenshots_reportsOnFinishedOnlyWhenBothFinished() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             val capturer0 = ArgumentCaptor<TakeScreenshotService.RequestCallback>()
@@ -190,7 +191,7 @@
     fun executeScreenshots_oneFinishesOtherFails_reportFailsOnlyAtTheEnd() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             val capturer0 = ArgumentCaptor<TakeScreenshotService.RequestCallback>()
@@ -217,7 +218,7 @@
     fun executeScreenshots_allDisplaysFail_reportsFail() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             val capturer0 = ArgumentCaptor<TakeScreenshotService.RequestCallback>()
@@ -244,7 +245,7 @@
     fun onDestroy_propagatedToControllers() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             screenshotExecutor.onDestroy()
@@ -256,7 +257,7 @@
     fun removeWindows_propagatedToControllers() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             screenshotExecutor.removeWindows()
@@ -270,7 +271,7 @@
     fun onCloseSystemDialogsReceived_propagatedToControllers() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             screenshotExecutor.onCloseSystemDialogsReceived()
@@ -286,7 +287,7 @@
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
             whenever(controller0.isPendingSharedTransition).thenReturn(true)
             whenever(controller1.isPendingSharedTransition).thenReturn(false)
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
 
             screenshotExecutor.onCloseSystemDialogsReceived()
@@ -304,7 +305,7 @@
             val toBeReturnedByProcessor = ScreenshotData.forTesting()
             requestProcessor.toReturn = toBeReturnedByProcessor
 
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             screenshotExecutor.executeScreenshots(screenshotRequest, onSaved, callback)
 
             assertThat(requestProcessor.processed)
@@ -321,7 +322,7 @@
     fun executeScreenshots_errorFromProcessor_logsScreenshotRequested() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             requestProcessor.shouldThrowException = true
 
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
@@ -338,7 +339,7 @@
     fun executeScreenshots_errorFromProcessor_logsUiError() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             requestProcessor.shouldThrowException = true
 
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
@@ -355,7 +356,7 @@
     fun executeScreenshots_errorFromProcessorOnDefaultDisplay_showsErrorNotification() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             requestProcessor.shouldThrowException = true
 
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
@@ -368,7 +369,7 @@
     fun executeScreenshots_errorFromProcessorOnSecondaryDisplay_showsErrorNotification() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             requestProcessor.shouldThrowException = true
 
             screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
@@ -381,7 +382,7 @@
     fun executeScreenshots_errorFromScreenshotController_reportsRequested() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             whenever(controller0.handleScreenshot(any(), any(), any()))
                 .thenThrow(IllegalStateException::class.java)
             whenever(controller1.handleScreenshot(any(), any(), any()))
@@ -401,7 +402,7 @@
     fun executeScreenshots_errorFromScreenshotController_reportsError() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             whenever(controller0.handleScreenshot(any(), any(), any()))
                 .thenThrow(IllegalStateException::class.java)
             whenever(controller1.handleScreenshot(any(), any(), any()))
@@ -421,7 +422,7 @@
     fun executeScreenshots_errorFromScreenshotController_showsErrorNotification() =
         testScope.runTest {
             setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1))
-            val onSaved = { _: Uri -> }
+            val onSaved = { _: Uri? -> }
             whenever(controller0.handleScreenshot(any(), any(), any()))
                 .thenThrow(IllegalStateException::class.java)
             whenever(controller1.handleScreenshot(any(), any(), any()))
@@ -434,6 +435,25 @@
             screenshotExecutor.onDestroy()
         }
 
+    @Test
+    fun executeScreenshots_finisherCalledWithNullUri_succeeds() =
+        testScope.runTest {
+            setDisplays(display(TYPE_INTERNAL, id = 0))
+            var onSavedCallCount = 0
+            val onSaved: (Uri?) -> Unit = {
+                assertThat(it).isNull()
+                onSavedCallCount += 1
+            }
+            whenever(controller0.handleScreenshot(any(), any(), any())).thenAnswer {
+                (it.getArgument(1) as Consumer<Uri?>).accept(null)
+            }
+
+            screenshotExecutor.executeScreenshots(createScreenshotRequest(), onSaved, callback)
+            assertThat(onSavedCallCount).isEqualTo(1)
+
+            screenshotExecutor.onDestroy()
+        }
+
     private suspend fun TestScope.setDisplays(vararg displays: Display) {
         fakeDisplayRepository.emit(displays.toSet())
         runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
index 0776aa7..77b5c91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
@@ -232,7 +232,7 @@
     override fun onCloseSystemDialogsReceived() {}
     override suspend fun executeScreenshots(
         screenshotRequest: ScreenshotRequest,
-        onSaved: (Uri) -> Unit,
+        onSaved: (Uri?) -> Unit,
         requestCallback: RequestCallback,
     ) {
         requestReceived = screenshotRequest
@@ -248,7 +248,7 @@
 
     override fun executeScreenshotsAsync(
         screenshotRequest: ScreenshotRequest,
-        onSaved: Consumer<Uri>,
+        onSaved: Consumer<Uri?>,
         requestCallback: RequestCallback,
     ) {
         runBlocking {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
new file mode 100644
index 0000000..254f1e1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.data.model
+
+import android.content.ComponentName
+import android.graphics.Rect
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.FREE_FORM
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.FULL_SCREEN
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.PIP
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.SPLIT_BOTTOM
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.SPLIT_TOP
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.emptyRootSplit
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.freeForm
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.fullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.launcher
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.pictureInPicture
+import com.android.systemui.screenshot.policy.ActivityType
+import com.android.systemui.screenshot.policy.TestUserIds
+import com.android.systemui.screenshot.policy.WindowingMode
+import com.android.systemui.screenshot.policy.newChildTask
+import com.android.systemui.screenshot.policy.newRootTaskInfo
+
+/** Tools for creating a [DisplayContentModel] for different usage scenarios. */
+object DisplayContentScenarios {
+
+    data class TaskSpec(val taskId: Int, val userId: Int, val name: String)
+
+    /** Home screen, with only the launcher visible */
+    fun launcherOnly(shadeExpanded: Boolean = false) =
+        DisplayContentModel(
+            displayId = 0,
+            systemUiState = SystemUiState(shadeExpanded = shadeExpanded),
+            rootTasks =
+                listOf(
+                    launcher(visible = true),
+                    emptyRootSplit,
+                )
+        )
+
+    /** A Full screen activity for the personal (primary) user, with launcher behind it */
+    fun singleFullScreen(spec: TaskSpec, shadeExpanded: Boolean = false) =
+        DisplayContentModel(
+            displayId = 0,
+            systemUiState = SystemUiState(shadeExpanded = shadeExpanded),
+            rootTasks =
+                listOf(
+                    fullScreen(spec, visible = true),
+                    launcher(visible = false),
+                    emptyRootSplit,
+                )
+        )
+
+    fun splitScreenApps(
+        top: TaskSpec,
+        bottom: TaskSpec,
+        focusedTaskId: Int,
+        shadeExpanded: Boolean = false,
+    ): DisplayContentModel {
+        val topBounds = SPLIT_TOP
+        val bottomBounds = SPLIT_BOTTOM
+        return DisplayContentModel(
+            displayId = 0,
+            systemUiState = SystemUiState(shadeExpanded = shadeExpanded),
+            rootTasks =
+                listOf(
+                    newRootTaskInfo(
+                        taskId = 2,
+                        userId = TestUserIds.PERSONAL,
+                        bounds = FULL_SCREEN,
+                        topActivity =
+                            ComponentName.unflattenFromString(
+                                if (top.taskId == focusedTaskId) top.name else bottom.name
+                            ),
+                    ) {
+                        listOf(
+                                newChildTask(
+                                    taskId = top.taskId,
+                                    bounds = topBounds,
+                                    userId = top.userId,
+                                    name = top.name
+                                ),
+                                newChildTask(
+                                    taskId = bottom.taskId,
+                                    bounds = bottomBounds,
+                                    userId = bottom.userId,
+                                    name = bottom.name
+                                )
+                            )
+                            // Child tasks are ordered bottom-up in RootTaskInfo.
+                            // Sort 'focusedTaskId' last.
+                            // Boolean natural ordering: [false, true].
+                            .sortedBy { it.id == focusedTaskId }
+                    },
+                    launcher(visible = false),
+                )
+        )
+    }
+
+    fun pictureInPictureApp(
+        pip: TaskSpec,
+        fullScreen: TaskSpec? = null,
+        shadeExpanded: Boolean = false,
+    ): DisplayContentModel {
+        return DisplayContentModel(
+            displayId = 0,
+            systemUiState = SystemUiState(shadeExpanded = shadeExpanded),
+            rootTasks =
+                buildList {
+                    add(pictureInPicture(pip))
+                    fullScreen?.also { add(fullScreen(it, visible = true)) }
+                    add(launcher(visible = (fullScreen == null)))
+                    add(emptyRootSplit)
+                }
+        )
+    }
+
+    fun freeFormApps(
+        vararg tasks: TaskSpec,
+        focusedTaskId: Int,
+        shadeExpanded: Boolean = false,
+    ): DisplayContentModel {
+        val freeFormTasks =
+            tasks
+                .map { freeForm(it) }
+                // Root tasks are ordered top-down in List<RootTaskInfo>.
+                // Sort 'focusedTaskId' last (Boolean natural ordering: [false, true])
+                .sortedBy { it.childTaskIds[0] != focusedTaskId }
+        return DisplayContentModel(
+            displayId = 0,
+            systemUiState = SystemUiState(shadeExpanded = shadeExpanded),
+            rootTasks = freeFormTasks + launcher(visible = true) + emptyRootSplit
+        )
+    }
+
+    /**
+     * All of these are arbitrary dimensions exposed for asserting equality on test data.
+     *
+     * They should not be updated nor compared with any real device usage, except to keep them
+     * somewhat sensible in terms of logical position (Re: PIP, SPLIT, etc).
+     */
+    object Bounds {
+        val FULL_SCREEN = Rect(0, 0, 1080, 2400)
+        val PIP = Rect(440, 1458, 1038, 1794)
+        val SPLIT_TOP = Rect(0, 0, 1080, 1187)
+        val SPLIT_BOTTOM = Rect(0, 1213, 1080, 2400)
+        val FREE_FORM = Rect(119, 332, 1000, 1367)
+    }
+
+    /** A collection of task names used in test scenarios */
+    object ActivityNames {
+        /** The main YouTube activity */
+        const val YOUTUBE =
+            "com.google.android.youtube/" +
+                "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity"
+
+        /** The main Files Activity */
+        const val FILES =
+            "com.google.android.apps.nbu.files/" +
+                "com.google.android.apps.nbu.files.home.HomeActivity"
+
+        /** The YouTube picture-in-picture activity */
+        const val YOUTUBE_PIP =
+            "com.google.android.youtube/" +
+                "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity"
+
+        /** The NexusLauncher activity */
+        const val LAUNCHER =
+            "com.google.android.apps.nexuslauncher/" +
+                "com.google.android.apps.nexuslauncher.NexusLauncherActivity"
+    }
+
+    /**
+     * A set of predefined RootTaskInfo used in test scenarios, matching as closely as possible
+     * actual values returned by ActivityTaskManager
+     */
+    object RootTasks {
+        /** An empty RootTaskInfo with no child tasks. */
+        val emptyWithNoChildTasks =
+            newRootTaskInfo(
+                taskId = 2,
+                visible = true,
+                running = true,
+                numActivities = 0,
+                bounds = FULL_SCREEN,
+            ) {
+                emptyList()
+            }
+
+        /**
+         * The empty RootTaskInfo that is always at the end of a list from ActivityTaskManager when
+         * no other visible activities are in split mode
+         */
+        val emptyRootSplit =
+            newRootTaskInfo(
+                taskId = 2,
+                visible = false,
+                running = false,
+                numActivities = 0,
+                bounds = FULL_SCREEN,
+                activityType = ActivityType.Undefined,
+            ) {
+                listOf(
+                    newChildTask(taskId = 3, bounds = FULL_SCREEN, name = ""),
+                    newChildTask(taskId = 4, bounds = Rect(0, 2400, 1080, 3600), name = ""),
+                )
+            }
+
+        /** NexusLauncher on the default display. Usually below all other visible tasks */
+        fun launcher(visible: Boolean) =
+            newRootTaskInfo(
+                taskId = 1,
+                activityType = ActivityType.Home,
+                visible = visible,
+                bounds = FULL_SCREEN,
+                topActivity = ComponentName.unflattenFromString(ActivityNames.LAUNCHER),
+                topActivityType = ActivityType.Home,
+            ) {
+                listOf(newChildTask(taskId = 1002, name = ActivityNames.LAUNCHER))
+            }
+
+        /** A full screen Activity */
+        fun fullScreen(task: TaskSpec, visible: Boolean) =
+            newRootTaskInfo(
+                taskId = task.taskId,
+                userId = task.userId,
+                visible = visible,
+                bounds = FULL_SCREEN,
+                topActivity = ComponentName.unflattenFromString(task.name),
+            ) {
+                listOf(newChildTask(taskId = task.taskId, userId = task.userId, name = task.name))
+            }
+
+        /** An activity in Picture-in-Picture mode */
+        fun pictureInPicture(task: TaskSpec) =
+            newRootTaskInfo(
+                taskId = task.taskId,
+                userId = task.userId,
+                bounds = PIP,
+                windowingMode = WindowingMode.PictureInPicture,
+                topActivity = ComponentName.unflattenFromString(task.name),
+            ) {
+                listOf(newChildTask(taskId = task.taskId, userId = userId, name = task.name))
+            }
+
+        /** An activity in FreeForm mode */
+        fun freeForm(task: TaskSpec) =
+            newRootTaskInfo(
+                taskId = task.taskId,
+                userId = task.userId,
+                bounds = FREE_FORM,
+                windowingMode = WindowingMode.Freeform,
+                topActivity = ComponentName.unflattenFromString(task.name),
+            ) {
+                listOf(newChildTask(taskId = task.taskId, userId = userId, name = task.name))
+            }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt
new file mode 100644
index 0000000..9d2b56a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.screenshot.data.model.ProfileType
+import com.android.systemui.screenshot.policy.TestUserIds
+
+val Kosmos.profileTypeRepository by
+    Kosmos.Fixture {
+        ProfileTypeRepository { userId ->
+            when (userId) {
+                TestUserIds.WORK -> ProfileType.WORK
+                TestUserIds.CLONE -> ProfileType.CLONE
+                TestUserIds.PRIVATE -> ProfileType.PRIVATE
+                else -> ProfileType.NONE
+            }
+        }
+    }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt
new file mode 100644
index 0000000..6c35b23
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/NewRootTaskInfo.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.app.ActivityTaskManager.RootTaskInfo
+import android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT
+import android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM
+import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
+import android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS
+import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
+import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
+import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
+import android.content.ComponentName
+import android.graphics.Rect
+import android.os.UserHandle
+import android.view.Display
+import com.android.systemui.screenshot.data.model.ChildTaskModel
+import com.android.systemui.screenshot.policy.ActivityType.Standard
+import com.android.systemui.screenshot.policy.WindowingMode.FullScreen
+
+/** An enum mapping to [android.app.WindowConfiguration] constants via [toInt]. */
+enum class ActivityType(private val intValue: Int) {
+    Undefined(ACTIVITY_TYPE_UNDEFINED),
+    Standard(ACTIVITY_TYPE_STANDARD),
+    Home(ACTIVITY_TYPE_HOME),
+    Recents(ACTIVITY_TYPE_RECENTS),
+    Assistant(ACTIVITY_TYPE_ASSISTANT),
+    Dream(ACTIVITY_TYPE_DREAM);
+
+    /** Returns the [android.app.WindowConfiguration] int constant for the type. */
+    fun toInt() = intValue
+}
+
+/** An enum mapping to [android.app.WindowConfiguration] constants via [toInt]. */
+enum class WindowingMode(private val intValue: Int) {
+    Undefined(WINDOWING_MODE_UNDEFINED),
+    FullScreen(WINDOWING_MODE_FULLSCREEN),
+    PictureInPicture(WINDOWING_MODE_PINNED),
+    Freeform(WINDOWING_MODE_FREEFORM),
+    MultiWindow(WINDOWING_MODE_MULTI_WINDOW);
+
+    /** Returns the [android.app.WindowConfiguration] int constant for the mode. */
+    fun toInt() = intValue
+}
+
+/**
+ * Constructs a child task for a [RootTaskInfo], copying [RootTaskInfo.bounds] and
+ * [RootTaskInfo.userId] from the parent by default.
+ */
+fun RootTaskInfo.newChildTask(
+    taskId: Int,
+    name: String,
+    bounds: Rect? = null,
+    userId: Int? = null
+): ChildTaskModel {
+    return ChildTaskModel(taskId, name, bounds ?: this.bounds, userId ?: this.userId)
+}
+
+/** Constructs a new [RootTaskInfo]. */
+fun newRootTaskInfo(
+    taskId: Int,
+    userId: Int = UserHandle.USER_SYSTEM,
+    displayId: Int = Display.DEFAULT_DISPLAY,
+    visible: Boolean = true,
+    running: Boolean = true,
+    activityType: ActivityType = Standard,
+    windowingMode: WindowingMode = FullScreen,
+    bounds: Rect? = null,
+    topActivity: ComponentName? = null,
+    topActivityType: ActivityType = Standard,
+    numActivities: Int? = null,
+    childTaskListBuilder: RootTaskInfo.() -> List<ChildTaskModel>,
+): RootTaskInfo {
+    return RootTaskInfo().apply {
+        configuration.windowConfiguration.apply {
+            setWindowingMode(windowingMode.toInt())
+            setActivityType(activityType.toInt())
+            setBounds(bounds)
+        }
+        this.bounds = bounds
+        this.displayId = displayId
+        this.userId = userId
+        this.taskId = taskId
+        this.visible = visible
+        this.isVisible = visible
+        this.isRunning = running
+        this.topActivity = topActivity
+        this.topActivityType = topActivityType.toInt()
+        // NOTE: topActivityInfo is _not_ populated by this code
+
+        val childTasks = childTaskListBuilder(this)
+        this.numActivities = numActivities ?: childTasks.size
+
+        childTaskNames = childTasks.map { it.name }.toTypedArray()
+        childTaskIds = childTasks.map { it.id }.toIntArray()
+        childTaskBounds = childTasks.map { it.bounds }.toTypedArray()
+        childTaskUserIds = childTasks.map { it.userId }.toIntArray()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
new file mode 100644
index 0000000..9e3ae05
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.content.ComponentName
+import android.os.UserHandle
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.FILES
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.YOUTUBE
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.YOUTUBE_PIP
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.emptyRootSplit
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.fullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.launcher
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.TaskSpec
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.pictureInPictureApp
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.singleFullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.splitScreenApps
+import com.android.systemui.screenshot.data.model.SystemUiState
+import com.android.systemui.screenshot.data.repository.profileTypeRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.FullScreen
+import com.android.systemui.screenshot.policy.TestUserIds.PERSONAL
+import com.android.systemui.screenshot.policy.TestUserIds.PRIVATE
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class PrivateProfilePolicyTest {
+    private val kosmos = Kosmos()
+    private val policy = PrivateProfilePolicy(kosmos.profileTypeRepository)
+
+    // TODO:
+    // private app in PIP
+    // private app below personal PIP app
+    // Freeform windows
+
+    @Test
+    fun shadeExpanded_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(
+                    spec = TaskSpec(taskId = 1002, name = YOUTUBE, userId = PRIVATE),
+                    shadeExpanded = true
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(NotMatched(PrivateProfilePolicy.NAME, PrivateProfilePolicy.SHADE_EXPANDED))
+    }
+
+    @Test
+    fun noPrivate_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL))
+            )
+
+        assertThat(result)
+            .isEqualTo(NotMatched(PrivateProfilePolicy.NAME, PrivateProfilePolicy.NO_VISIBLE_TASKS))
+    }
+
+    @Test
+    fun withPrivateFullScreen_isMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(TaskSpec(taskId = 1002, name = YOUTUBE, userId = PRIVATE))
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateNotVisible_notMatched() = runTest {
+        val result =
+            policy.check(
+                DisplayContentModel(
+                    displayId = 0,
+                    systemUiState = SystemUiState(shadeExpanded = false),
+                    rootTasks =
+                        listOf(
+                            fullScreen(
+                                TaskSpec(taskId = 1002, name = FILES, userId = PERSONAL),
+                                visible = true
+                            ),
+                            fullScreen(
+                                TaskSpec(taskId = 1003, name = YOUTUBE, userId = PRIVATE),
+                                visible = false
+                            ),
+                            launcher(visible = false),
+                            emptyRootSplit,
+                        )
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.NO_VISIBLE_TASKS,
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateFocusedInSplitScreen_isMatched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = PERSONAL),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PRIVATE),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateNotFocusedInSplitScreen_isMatched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = PERSONAL),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PRIVATE),
+                    focusedTaskId = 1002
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivatePictureInPictureApp_isMatched() = runTest {
+        val result =
+            policy.check(
+                pictureInPictureApp(TaskSpec(taskId = 1002, name = YOUTUBE_PIP, userId = PRIVATE))
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE_PIP),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateAppBelowPictureInPictureApp_isMatched() = runTest {
+        val result =
+            policy.check(
+                pictureInPictureApp(
+                    pip = TaskSpec(taskId = 1002, name = YOUTUBE_PIP, userId = PERSONAL),
+                    fullScreen = TaskSpec(taskId = 1003, name = FILES, userId = PRIVATE),
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE_PIP),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/TestUserIds.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/TestUserIds.kt
new file mode 100644
index 0000000..7a6d280
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/TestUserIds.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.os.UserHandle
+
+object TestUserIds {
+    val PERSONAL: Int = UserHandle.USER_SYSTEM
+    val WORK: Int = 10
+    val CLONE: Int = 11
+    val PRIVATE: Int = 12
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
new file mode 100644
index 0000000..5d35528
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.content.ComponentName
+import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.FILES
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.YOUTUBE
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.FREE_FORM
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.FULL_SCREEN
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.SPLIT_TOP
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.TaskSpec
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.freeFormApps
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.pictureInPictureApp
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.singleFullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.splitScreenApps
+import com.android.systemui.screenshot.data.model.SystemUiState
+import com.android.systemui.screenshot.data.repository.profileTypeRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask
+import com.android.systemui.screenshot.policy.TestUserIds.PERSONAL
+import com.android.systemui.screenshot.policy.TestUserIds.WORK
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.DESKTOP_MODE_ENABLED
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.SHADE_EXPANDED
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.WORK_TASK_IS_TOP
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.WORK_TASK_NOT_TOP
+import com.android.window.flags.Flags
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Rule
+import org.junit.Test
+
+class WorkProfilePolicyTest {
+    @JvmField @Rule val setFlagsRule = SetFlagsRule()
+
+    private val kosmos = Kosmos()
+    private val policy = WorkProfilePolicy(kosmos.profileTypeRepository)
+
+    /**
+     * There is no guarantee that every RootTaskInfo contains a non-empty list of child tasks. Test
+     * the case where the RootTaskInfo would match but child tasks are empty.
+     */
+    @Test
+    fun withEmptyChildTasks_notMatched() = runTest {
+        val result =
+            policy.check(
+                DisplayContentModel(
+                    displayId = 0,
+                    systemUiState = SystemUiState(shadeExpanded = false),
+                    rootTasks = listOf(RootTasks.emptyWithNoChildTasks)
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    WORK_TASK_NOT_TOP,
+                )
+            )
+    }
+
+    @Test
+    fun noWorkApp_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL))
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    WORK_TASK_NOT_TOP,
+                )
+            )
+    }
+
+    @Test
+    fun withWorkFullScreen_shadeExpanded_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(
+                    TaskSpec(taskId = 1002, name = FILES, userId = WORK),
+                    shadeExpanded = true
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    SHADE_EXPANDED,
+                )
+            )
+    }
+
+    @Test
+    fun withWorkFullScreen_matched() = runTest {
+        val result =
+            policy.check(singleFullScreen(TaskSpec(taskId = 1002, name = FILES, userId = WORK)))
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1002, taskBounds = FULL_SCREEN),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withWorkFocusedInSplitScreen_matched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = WORK),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PERSONAL),
+                    focusedTaskId = 1002
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1002, taskBounds = SPLIT_TOP),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withWorkNotFocusedInSplitScreen_notMatched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = WORK),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PERSONAL),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    WORK_TASK_NOT_TOP,
+                )
+            )
+    }
+
+    @Test
+    fun withWorkBelowPersonalPictureInPicture_matched() = runTest {
+        val result =
+            policy.check(
+                pictureInPictureApp(
+                    pip = TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL),
+                    fullScreen = TaskSpec(taskId = 1003, name = FILES, userId = WORK),
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1003, taskBounds = FULL_SCREEN),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    fun withWorkFocusedInFreeForm_matched() = runTest {
+        val result =
+            policy.check(
+                freeFormApps(
+                    TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL),
+                    TaskSpec(taskId = 1003, name = FILES, userId = WORK),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1003, taskBounds = FREE_FORM),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    fun withWorkFocusedInFreeForm_desktopModeEnabled_notMatched() = runTest {
+        val result =
+            policy.check(
+                freeFormApps(
+                    TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL),
+                    TaskSpec(taskId = 1003, name = FILES, userId = WORK),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    DESKTOP_MODE_ENABLED,
+                )
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
new file mode 100644
index 0000000..d44e26c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.ui.viewmodel
+
+import android.view.accessibility.AccessibilityManager
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.mockito.Mockito.mock
+
+@SmallTest
+class ScreenshotViewModelTest {
+    private val accessibilityManager: AccessibilityManager = mock(AccessibilityManager::class.java)
+    private val appearance = ActionButtonAppearance(null, "Label", "Description")
+    private val onclick = {}
+
+    @Test
+    fun testAddAction() {
+        val viewModel = ScreenshotViewModel(accessibilityManager)
+
+        assertThat(viewModel.actions.value).isEmpty()
+
+        viewModel.addAction(appearance, onclick)
+
+        assertThat(viewModel.actions.value).hasSize(1)
+
+        val added = viewModel.actions.value[0]
+        assertThat(added.appearance).isEqualTo(appearance)
+        assertThat(added.onClicked).isEqualTo(onclick)
+    }
+
+    @Test
+    fun testRemoveAction() {
+        val viewModel = ScreenshotViewModel(accessibilityManager)
+        val firstId = viewModel.addAction(ActionButtonAppearance(null, "", ""), {})
+        val secondId = viewModel.addAction(appearance, onclick)
+
+        assertThat(viewModel.actions.value).hasSize(2)
+        assertThat(firstId).isNotEqualTo(secondId)
+
+        viewModel.removeAction(firstId)
+
+        assertThat(viewModel.actions.value).hasSize(1)
+
+        val remaining = viewModel.actions.value[0]
+        assertThat(remaining.appearance).isEqualTo(appearance)
+        assertThat(remaining.onClicked).isEqualTo(onclick)
+    }
+
+    @Test
+    fun testUpdateActionAppearance() {
+        val viewModel = ScreenshotViewModel(accessibilityManager)
+        val id = viewModel.addAction(appearance, onclick)
+        val otherAppearance = ActionButtonAppearance(null, "Other", "Other")
+
+        viewModel.updateActionAppearance(id, otherAppearance)
+
+        assertThat(viewModel.actions.value).hasSize(1)
+        val updated = viewModel.actions.value[0]
+        assertThat(updated.appearance).isEqualTo(otherAppearance)
+        assertThat(updated.onClicked).isEqualTo(onclick)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index 25ba09a..fb91c78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -24,7 +24,7 @@
 import com.android.settingslib.RestrictedLockUtils
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.FalsingManagerFake
-import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin
+import com.android.systemui.haptics.slider.SeekbarHapticPlugin
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.policy.BrightnessMirrorController
@@ -84,7 +84,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        whenever(mirrorController.toggleSlider).thenReturn(mirror)
+        whenever(mirrorController.getToggleSlider()).thenReturn(mirror)
         whenever(motionEvent.copy()).thenReturn(motionEvent)
         whenever(vibratorHelper.getPrimitiveDurations(anyInt())).thenReturn(intArrayOf(0))
 
@@ -93,7 +93,7 @@
                 brightnessSliderView,
                 mFalsingManager,
                 uiEventLogger,
-                SeekableSliderHapticPlugin(vibratorHelper, systemClock),
+                SeekbarHapticPlugin(vibratorHelper, systemClock),
                 activityStarter,
             )
         mController.init()
@@ -129,7 +129,7 @@
 
     @Test
     fun testNullMirrorNotTrackingTouch() {
-        whenever(mirrorController.toggleSlider).thenReturn(null)
+        whenever(mirrorController.getToggleSlider()).thenReturn(null)
 
         mController.setMirrorControllerAndMirror(mirrorController)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index e611da0..03f5ecf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -25,21 +25,24 @@
 import android.view.View
 import android.view.WindowManager
 import android.widget.FrameLayout
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.SceneKey
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.ambient.touch.TouchHandler
+import com.android.systemui.ambient.touch.TouchMonitor
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
 import com.android.systemui.communal.data.repository.FakeCommunalRepository
 import com.android.systemui.communal.data.repository.fakeCommunalRepository
-import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.domain.interactor.communalInteractor
 import com.android.systemui.communal.domain.interactor.setCommunalAvailable
 import com.android.systemui.communal.shared.model.CommunalScenes
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.communal.util.CommunalColors
+import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -49,7 +52,6 @@
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
 import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialogFactory
 import com.android.systemui.testKosmos
@@ -58,7 +60,6 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.After
 import org.junit.Assert.assertThrows
@@ -85,15 +86,14 @@
     @Mock private lateinit var communalViewModel: CommunalViewModel
     @Mock private lateinit var powerManager: PowerManager
     @Mock private lateinit var dialogFactory: SystemUIDialogFactory
-    private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
-    private lateinit var shadeInteractor: ShadeInteractor
-    private lateinit var keyguardInteractor: KeyguardInteractor
+    @Mock private lateinit var touchMonitor: TouchMonitor
+    @Mock private lateinit var communalColors: CommunalColors
+    private lateinit var ambientTouchComponentFactory: AmbientTouchComponent.Factory
 
     private lateinit var parentView: FrameLayout
     private lateinit var containerView: View
     private lateinit var testableLooper: TestableLooper
 
-    private lateinit var communalInteractor: CommunalInteractor
     private lateinit var communalRepository: FakeCommunalRepository
     private lateinit var underTest: GlanceableHubContainerController
 
@@ -101,31 +101,37 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        communalInteractor = kosmos.communalInteractor
         communalRepository = kosmos.fakeCommunalRepository
-        keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor
-        keyguardInteractor = kosmos.keyguardInteractor
-        shadeInteractor = kosmos.shadeInteractor
 
-        underTest =
-            GlanceableHubContainerController(
-                communalInteractor,
-                communalViewModel,
-                dialogFactory,
-                keyguardTransitionInteractor,
-                keyguardInteractor,
-                shadeInteractor,
-                powerManager,
-                kosmos.sceneDataSourceDelegator,
-            )
+        ambientTouchComponentFactory =
+            object : AmbientTouchComponent.Factory {
+                override fun create(
+                    lifecycleOwner: LifecycleOwner,
+                    touchHandlers: Set<TouchHandler>
+                ): AmbientTouchComponent =
+                    object : AmbientTouchComponent {
+                        override fun getTouchMonitor(): TouchMonitor = touchMonitor
+                    }
+            }
+
+        with(kosmos) {
+            underTest =
+                GlanceableHubContainerController(
+                    communalInteractor,
+                    communalViewModel,
+                    dialogFactory,
+                    keyguardTransitionInteractor,
+                    keyguardInteractor,
+                    shadeInteractor,
+                    powerManager,
+                    communalColors,
+                    ambientTouchComponentFactory,
+                    kosmos.sceneDataSourceDelegator,
+                )
+        }
         testableLooper = TestableLooper.get(this)
 
         overrideResource(R.dimen.communal_right_edge_swipe_region_width, RIGHT_SWIPE_REGION_WIDTH)
-        overrideResource(R.dimen.communal_top_edge_swipe_region_height, TOP_SWIPE_REGION_WIDTH)
-        overrideResource(
-            R.dimen.communal_bottom_edge_swipe_region_height,
-            BOTTOM_SWIPE_REGION_WIDTH
-        )
 
         // Make communal available so that communalInteractor.desiredScene accurately reflects
         // scene changes instead of just returning Blank.
@@ -156,6 +162,8 @@
                         keyguardInteractor,
                         shadeInteractor,
                         powerManager,
+                        communalColors,
+                        ambientTouchComponentFactory,
                         kosmos.sceneDataSourceDelegator,
                     )
 
@@ -210,62 +218,6 @@
         }
 
     @Test
-    fun onTouchEvent_topSwipeWhenCommunalOpen_doesNotIntercept() =
-        with(kosmos) {
-            testScope.runTest {
-                // Communal is open.
-                goToScene(CommunalScenes.Communal)
-
-                // Touch event in the top swipe region is not intercepted.
-                assertThat(underTest.onTouchEvent(DOWN_IN_TOP_SWIPE_REGION_EVENT)).isFalse()
-            }
-        }
-
-    @Test
-    fun onTouchEvent_bottomSwipeWhenCommunalOpen_doesNotIntercept() =
-        with(kosmos) {
-            testScope.runTest {
-                // Communal is open.
-                goToScene(CommunalScenes.Communal)
-
-                // Touch event in the bottom swipe region is not intercepted.
-                assertThat(underTest.onTouchEvent(DOWN_IN_BOTTOM_SWIPE_REGION_EVENT)).isFalse()
-            }
-        }
-
-    @Test
-    fun onTouchEvent_topSwipeWhenDreaming_doesNotIntercept() =
-        with(kosmos) {
-            testScope.runTest {
-                // Communal is open.
-                goToScene(CommunalScenes.Communal)
-
-                // Device is dreaming.
-                fakeKeyguardRepository.setDreaming(true)
-                runCurrent()
-
-                // Touch event in the top swipe region is not intercepted.
-                assertThat(underTest.onTouchEvent(DOWN_IN_TOP_SWIPE_REGION_EVENT)).isFalse()
-            }
-        }
-
-    @Test
-    fun onTouchEvent_bottomSwipeWhenDreaming_doesNotIntercept() =
-        with(kosmos) {
-            testScope.runTest {
-                // Communal is open.
-                goToScene(CommunalScenes.Communal)
-
-                // Device is dreaming.
-                fakeKeyguardRepository.setDreaming(true)
-                runCurrent()
-
-                // Touch event in the bottom swipe region is not intercepted.
-                assertThat(underTest.onTouchEvent(DOWN_IN_BOTTOM_SWIPE_REGION_EVENT)).isFalse()
-            }
-        }
-
-    @Test
     fun onTouchEvent_communalAndBouncerShowing_doesNotIntercept() =
         with(kosmos) {
             testScope.runTest {
@@ -321,6 +273,154 @@
             }
         }
 
+    @Test
+    fun lifecycle_initializedAfterConstruction() =
+        with(kosmos) {
+            val underTest =
+                GlanceableHubContainerController(
+                    communalInteractor,
+                    communalViewModel,
+                    dialogFactory,
+                    keyguardTransitionInteractor,
+                    keyguardInteractor,
+                    shadeInteractor,
+                    powerManager,
+                    communalColors,
+                    ambientTouchComponentFactory,
+                    kosmos.sceneDataSourceDelegator,
+                )
+
+            assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.INITIALIZED)
+        }
+
+    @Test
+    fun lifecycle_createdAfterViewCreated() =
+        with(kosmos) {
+            val underTest =
+                GlanceableHubContainerController(
+                    communalInteractor,
+                    communalViewModel,
+                    dialogFactory,
+                    keyguardTransitionInteractor,
+                    keyguardInteractor,
+                    shadeInteractor,
+                    powerManager,
+                    communalColors,
+                    ambientTouchComponentFactory,
+                    kosmos.sceneDataSourceDelegator,
+                )
+
+            // Only initView without attaching a view as we don't want the flows to start collecting
+            // yet.
+            underTest.initView(View(context))
+
+            assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+        }
+
+    @Test
+    fun lifecycle_startedAfterFlowsUpdate() {
+        // Flows start collecting due to test setup, causing the state to advance to STARTED.
+        assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+    }
+
+    @Test
+    fun lifecycle_resumedAfterCommunalShows() {
+        // Communal is open.
+        goToScene(CommunalScenes.Communal)
+
+        assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+    }
+
+    @Test
+    fun lifecycle_startedAfterCommunalCloses() =
+        with(kosmos) {
+            testScope.runTest {
+                // Communal is open.
+                goToScene(CommunalScenes.Communal)
+
+                assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+
+                // Communal closes.
+                goToScene(CommunalScenes.Blank)
+
+                assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+            }
+        }
+
+    @Test
+    fun lifecycle_startedAfterPrimaryBouncerShows() =
+        with(kosmos) {
+            testScope.runTest {
+                // Communal is open.
+                goToScene(CommunalScenes.Communal)
+
+                // Bouncer is visible.
+                fakeKeyguardTransitionRepository.sendTransitionSteps(
+                    KeyguardState.GLANCEABLE_HUB,
+                    KeyguardState.PRIMARY_BOUNCER,
+                    testScope
+                )
+                testableLooper.processAllMessages()
+
+                assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+            }
+        }
+
+    @Test
+    fun lifecycle_startedAfterAlternateBouncerShows() =
+        with(kosmos) {
+            testScope.runTest {
+                // Communal is open.
+                goToScene(CommunalScenes.Communal)
+
+                // Bouncer is visible.
+                fakeKeyguardTransitionRepository.sendTransitionSteps(
+                    KeyguardState.GLANCEABLE_HUB,
+                    KeyguardState.ALTERNATE_BOUNCER,
+                    testScope
+                )
+                testableLooper.processAllMessages()
+
+                assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+            }
+        }
+
+    @Test
+    fun lifecycle_createdAfterDisposeView() {
+        // Container view disposed.
+        underTest.disposeView()
+
+        assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+    }
+
+    @Test
+    fun lifecycle_startedAfterShadeShows() =
+        with(kosmos) {
+            testScope.runTest {
+                // Communal is open.
+                goToScene(CommunalScenes.Communal)
+
+                // Shade shows up.
+                fakeShadeRepository.setQsExpansion(1.0f)
+                testableLooper.processAllMessages()
+
+                assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+            }
+        }
+
+    @Test
+    fun editMode_communalAvailable() =
+        with(kosmos) {
+            testScope.runTest {
+                val available by collectLastValue(underTest.communalAvailable())
+                setCommunalAvailable(false)
+
+                assertThat(available).isFalse()
+                communalInteractor.setEditModeOpen(true)
+                assertThat(available).isTrue()
+            }
+        }
+
     private fun initAndAttachContainerView() {
         containerView = View(context)
 
@@ -353,8 +453,6 @@
         private const val CONTAINER_WIDTH = 100
         private const val CONTAINER_HEIGHT = 100
         private const val RIGHT_SWIPE_REGION_WIDTH = 20
-        private const val TOP_SWIPE_REGION_WIDTH = 20
-        private const val BOTTOM_SWIPE_REGION_WIDTH = 20
 
         /**
          * A touch down event right in the middle of the screen, to avoid being in any of the swipe
@@ -371,17 +469,6 @@
             )
         private val DOWN_IN_RIGHT_SWIPE_REGION_EVENT =
             MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat(), 0f, 0)
-        private val DOWN_IN_TOP_SWIPE_REGION_EVENT =
-            MotionEvent.obtain(
-                0L,
-                0L,
-                MotionEvent.ACTION_DOWN,
-                0f,
-                TOP_SWIPE_REGION_WIDTH.toFloat(),
-                0
-            )
-        private val DOWN_IN_BOTTOM_SWIPE_REGION_EVENT =
-            MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, CONTAINER_HEIGHT.toFloat(), 0)
         private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
         private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
     }
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 dfe72cf..d5e88fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -154,6 +154,7 @@
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
 import com.android.systemui.statusbar.notification.data.repository.NotificationsKeyguardViewStateRepository;
 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor;
+import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor;
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
@@ -161,6 +162,7 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
+import com.android.systemui.statusbar.notification.stack.data.repository.FakeHeadsUpNotificationRepository;
 import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
@@ -358,6 +360,10 @@
     protected TestScope mTestScope = mKosmos.getTestScope();
     protected ShadeInteractor mShadeInteractor;
     protected PowerInteractor mPowerInteractor;
+    protected FakeHeadsUpNotificationRepository mFakeHeadsUpNotificationRepository =
+            new FakeHeadsUpNotificationRepository();
+    protected HeadsUpNotificationInteractor mHeadsUpNotificationInteractor =
+            new HeadsUpNotificationInteractor(mFakeHeadsUpNotificationRepository);
     protected NotificationPanelViewController.TouchHandler mTouchHandler;
     protected ConfigurationController mConfigurationController;
     protected SysuiStatusBarStateController mStatusBarStateController;
@@ -384,7 +390,6 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mFeatureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false);
         mFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false);
         mFeatureFlags.set(Flags.QS_USER_DETAIL_SHORTCUT, false);
 
@@ -398,7 +403,7 @@
         mFakeKeyguardRepository = keyguardInteractorDeps.getRepository();
         mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(mFakeKeyguardRepository);
         mFakeKeyguardClockRepository = new FakeKeyguardClockRepository();
-        mKeyguardClockInteractor = new KeyguardClockInteractor(mFakeKeyguardClockRepository);
+        mKeyguardClockInteractor = mKosmos.getKeyguardClockInteractor();
         mKeyguardInteractor = keyguardInteractorDeps.getKeyguardInteractor();
         mShadeRepository = new FakeShadeRepository();
         mShadeAnimationInteractor = new ShadeAnimationInteractorLegacyImpl(
@@ -410,6 +415,8 @@
                 mock(DeviceEntryUdfpsInteractor.class);
         when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
 
+        when(mKeyguardTransitionInteractor.isInTransitionToState(any())).thenReturn(emptyFlow());
+
         mShadeInteractor = new ShadeInteractorImpl(
                 mTestScope.getBackgroundScope(),
                 mKosmos.getDeviceProvisioningInteractor(),
@@ -437,7 +444,7 @@
         SystemClock systemClock = new FakeSystemClock();
         mStatusBarStateController = new StatusBarStateControllerImpl(
                 mUiEventLogger,
-                mKosmos.getInteractionJankMonitor(),
+                () -> mKosmos.getInteractionJankMonitor(),
                 mJavaAdapter,
                 () -> mShadeInteractor,
                 () -> mKosmos.getDeviceUnlockedInteractor(),
@@ -539,7 +546,7 @@
         }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
 
         // Dreaming->Lockscreen
-        when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition())
+        when(mKeyguardTransitionInteractor.transition(any(), any()))
                 .thenReturn(emptyFlow());
         when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha())
                 .thenReturn(emptyFlow());
@@ -547,46 +554,28 @@
                 .thenReturn(emptyFlow());
 
         // Occluded->Lockscreen
-        when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition())
-                .thenReturn(emptyFlow());
         when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
                 .thenReturn(emptyFlow());
         when(mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY())
                 .thenReturn(emptyFlow());
 
         // Lockscreen->Dreaming
-        when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
-                .thenReturn(emptyFlow());
         when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
                 .thenReturn(emptyFlow());
         when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
                 .thenReturn(emptyFlow());
 
         // Gone->Dreaming
-        when(mKeyguardTransitionInteractor.getGoneToDreamingTransition())
-                .thenReturn(emptyFlow());
         when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
                 .thenReturn(emptyFlow());
         when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
                 .thenReturn(emptyFlow());
 
         // Gone->Dreaming lockscreen hosted
-        when(mKeyguardTransitionInteractor.getGoneToDreamingLockscreenHostedTransition())
-                .thenReturn(emptyFlow());
         when(mGoneToDreamingLockscreenHostedTransitionViewModel.getLockscreenAlpha())
                 .thenReturn(emptyFlow());
 
-        // Dreaming lockscreen hosted->Lockscreen
-        when(mKeyguardTransitionInteractor.getDreamingLockscreenHostedToLockscreenTransition())
-                .thenReturn(emptyFlow());
-
-        // Lockscreen->Dreaming lockscreen hosted
-        when(mKeyguardTransitionInteractor.getLockscreenToDreamingLockscreenHostedTransition())
-                .thenReturn(emptyFlow());
-
         // Lockscreen->Occluded
-        when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition())
-                .thenReturn(emptyFlow());
         when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
                 .thenReturn(emptyFlow());
         when(mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY())
@@ -609,7 +598,7 @@
                         mock(HeadsUpManager.class),
                         new StatusBarStateControllerImpl(
                                 new UiEventLoggerFake(),
-                                mKosmos.getInteractionJankMonitor(),
+                                () -> mKosmos.getInteractionJankMonitor(),
                                 mJavaAdapter,
                                 () -> mShadeInteractor,
                                 () -> mKosmos.getDeviceUnlockedInteractor(),
@@ -746,6 +735,7 @@
                 mActivityStarter,
                 mSharedNotificationContainerInteractor,
                 mActiveNotificationsInteractor,
+                mHeadsUpNotificationInteractor,
                 mShadeAnimationInteractor,
                 mKeyguardViewConfigurator,
                 mDeviceEntryFaceAuthInteractor,
@@ -812,7 +802,7 @@
                 mAccessibilityManager,
                 mLockscreenGestureLogger,
                 mMetricsLogger,
-                mKosmos.getInteractionJankMonitor(),
+                () -> mKosmos.getInteractionJankMonitor(),
                 mShadeLog,
                 mDumpManager,
                 mDeviceEntryFaceAuthInteractor,
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 650c45b..81e20c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -46,6 +46,7 @@
 import android.animation.ValueAnimator;
 import android.graphics.Point;
 import android.os.PowerManager;
+import android.platform.test.annotations.DisableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.MotionEvent;
@@ -62,6 +63,7 @@
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.phone.KeyguardClockPositionAlgorithm;
@@ -1287,6 +1289,7 @@
     }
 
     @Test
+    @DisableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
     public void shadeExpanded_whenHunIsPresent() {
         when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
         assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
index 4df7ef5..6631d29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.shade
 
+import android.platform.test.annotations.EnableFlags
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.HapticFeedbackConstants
@@ -29,10 +32,14 @@
 import com.android.systemui.statusbar.StatusBarState.KEYGUARD
 import com.android.systemui.statusbar.StatusBarState.SHADE
 import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
+import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository
+import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor
+import com.android.systemui.statusbar.notification.stack.data.repository.setNotifications
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.cancelChildren
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.advanceUntilIdle
@@ -235,4 +242,41 @@
         val bottomAreaAlpha by collectLastValue(mFakeKeyguardRepository.bottomAreaAlpha)
         assertThat(bottomAreaAlpha).isEqualTo(1f)
     }
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    fun shadeExpanded_whenHunIsPresent() = runTest {
+        launch(mainDispatcher) {
+            givenViewAttached()
+
+            // WHEN a pinned heads up is present
+            mFakeHeadsUpNotificationRepository.setNotifications(
+                fakeHeadsUpRowRepository("key", isPinned = true)
+            )
+        }
+        advanceUntilIdle()
+
+        // THEN the panel should be visible
+        assertThat(mNotificationPanelViewController.isExpanded).isTrue()
+    }
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    fun shadeExpanded_whenHunIsAnimatingAway() = runTest {
+        launch(mainDispatcher) {
+            givenViewAttached()
+
+            // WHEN a heads up is animating away
+            mFakeHeadsUpNotificationRepository.isHeadsUpAnimatingAway.value = true
+        }
+        advanceUntilIdle()
+
+        // THEN the panel should be visible
+        assertThat(mNotificationPanelViewController.isExpanded).isTrue()
+    }
+
+    private fun fakeHeadsUpRowRepository(key: String, isPinned: Boolean = false) =
+        FakeHeadsUpRowRepository(key = key, elementKey = Any()).apply {
+            this.isPinned.value = isPinned
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
deleted file mode 100644
index 02f2e16..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade;
-
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
-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.eq;
-import static org.mockito.Mockito.atLeastOnce;
-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.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-
-import android.app.IActivityManager;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
-import android.view.WindowManager;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.KeyguardSecurityModel;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
-import com.android.systemui.communal.domain.interactor.CommunalInteractor;
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FakeFeatureFlagsClassic;
-import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
-import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.kosmos.KosmosJavaAdapter;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.power.domain.interactor.PowerInteractor;
-import com.android.systemui.res.R;
-import com.android.systemui.scene.FakeWindowRootViewComponent;
-import com.android.systemui.scene.data.repository.SceneContainerRepository;
-import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
-import com.android.systemui.scene.shared.logger.SceneLogger;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shade.data.repository.FakeShadeRepository;
-import com.android.systemui.shade.domain.interactor.ShadeInteractor;
-import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl;
-import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
-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.phone.ScrimController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
-import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository;
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.android.systemui.user.domain.interactor.UserSwitcherInteractor;
-
-import com.google.common.util.concurrent.MoreExecutors;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-
-import kotlinx.coroutines.test.TestScope;
-
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-@SmallTest
-public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
-
-    @Mock private WindowManager mWindowManager;
-    @Mock private DozeParameters mDozeParameters;
-    @Spy private final NotificationShadeWindowView mNotificationShadeWindowView = spy(
-            new NotificationShadeWindowView(mContext, null));
-    @Mock private IActivityManager mActivityManager;
-    @Mock private ConfigurationController mConfigurationController;
-    @Mock private KeyguardViewMediator mKeyguardViewMediator;
-    @Mock private KeyguardBypassController mKeyguardBypassController;
-    @Mock private SysuiColorExtractor mColorExtractor;
-    @Mock private ColorExtractor.GradientColors mGradientColors;
-    @Mock private DumpManager mDumpManager;
-    @Mock private KeyguardSecurityModel mKeyguardSecurityModel;
-    @Mock private KeyguardStateController mKeyguardStateController;
-    @Mock private AuthController mAuthController;
-    @Mock private ShadeWindowLogger mShadeWindowLogger;
-    @Mock private SelectedUserInteractor mSelectedUserInteractor;
-    @Mock private UserTracker mUserTracker;
-    @Mock private SceneContainerFlags mSceneContainerFlags;
-    @Mock private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
-    @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
-    @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
-
-    private final Executor mMainExecutor = MoreExecutors.directExecutor();
-    private final Executor mBackgroundExecutor = MoreExecutors.directExecutor();
-    private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
-    private final TestScope mTestScope = mKosmos.getTestScope();
-    private ShadeInteractor mShadeInteractor;
-
-    private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
-    private float mPreferredRefreshRate = -1;
-    private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor;
-    private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor;
-    private ScreenOffAnimationController mScreenOffAnimationController;
-    private SysuiStatusBarStateController mStatusBarStateController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        // Preferred refresh rate is equal to the first displayMode's refresh rate
-        mPreferredRefreshRate = mContext.getDisplay().getSupportedModes()[0].getRefreshRate();
-        overrideResource(
-                R.integer.config_keyguardRefreshRate,
-                (int) mPreferredRefreshRate
-        );
-
-        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
-        when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
-
-        FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository();
-        FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
-        FakeShadeRepository shadeRepository = new FakeShadeRepository();
-
-        mScreenOffAnimationController = mKosmos.getScreenOffAnimationController();
-        mStatusBarStateController = spy(mKosmos.getStatusBarStateController());
-        PowerInteractor powerInteractor = mKosmos.getPowerInteractor();
-
-        SceneInteractor sceneInteractor = new SceneInteractor(
-                mTestScope.getBackgroundScope(),
-                new SceneContainerRepository(
-                        mTestScope.getBackgroundScope(),
-                        mKosmos.getFakeSceneContainerConfig(),
-                        mKosmos.getSceneDataSource()),
-                mock(SceneLogger.class),
-                mKosmos.getDeviceUnlockedInteractor());
-
-        FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
-        FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags();
-        KeyguardTransitionInteractor keyguardTransitionInteractor =
-                mKosmos.getKeyguardTransitionInteractor();
-        KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
-                keyguardRepository,
-                new FakeCommandQueue(),
-                powerInteractor,
-                sceneContainerFlags,
-                new FakeKeyguardBouncerRepository(),
-                new ConfigurationInteractor(configurationRepository),
-                shadeRepository,
-                keyguardTransitionInteractor,
-                () -> sceneInteractor,
-                () -> mKosmos.getFromGoneTransitionInteractor(),
-                () -> mKosmos.getSharedNotificationContainerInteractor(),
-                mTestScope);
-        CommunalInteractor communalInteractor = mKosmos.getCommunalInteractor();
-
-        mFromLockscreenTransitionInteractor = mKosmos.getFromLockscreenTransitionInteractor();
-        mFromPrimaryBouncerTransitionInteractor =
-                mKosmos.getFromPrimaryBouncerTransitionInteractor();
-
-        DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
-                mock(DeviceEntryUdfpsInteractor.class);
-        when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
-
-        mShadeInteractor = new ShadeInteractorImpl(
-                mTestScope.getBackgroundScope(),
-                mKosmos.getDeviceProvisioningInteractor(),
-                new FakeDisableFlagsRepository(),
-                mock(DozeParameters.class),
-                keyguardRepository,
-                keyguardTransitionInteractor,
-                powerInteractor,
-                new FakeUserSetupRepository(),
-                mock(UserSwitcherInteractor.class),
-                new ShadeInteractorLegacyImpl(
-                        mTestScope.getBackgroundScope(),
-                        keyguardRepository,
-                        new SharedNotificationContainerInteractor(
-                                configurationRepository,
-                                mContext,
-                                new ResourcesSplitShadeStateController(),
-                                keyguardInteractor,
-                                deviceEntryUdfpsInteractor,
-                                () -> mLargeScreenHeaderHelper),
-                        shadeRepository
-                )
-        );
-
-        mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
-                mContext,
-                new FakeWindowRootViewComponent.Factory(mNotificationShadeWindowView),
-                mWindowManager,
-                mActivityManager,
-                mDozeParameters,
-                mStatusBarStateController,
-                mConfigurationController,
-                mKeyguardViewMediator,
-                mKeyguardBypassController,
-                mMainExecutor,
-                mBackgroundExecutor,
-                mColorExtractor,
-                mDumpManager,
-                mKeyguardStateController,
-                mScreenOffAnimationController,
-                mAuthController,
-                () -> mShadeInteractor,
-                mShadeWindowLogger,
-                () -> mSelectedUserInteractor,
-                mUserTracker,
-                mSceneContainerFlags,
-                () -> communalInteractor) {
-                    @Override
-                    protected boolean isDebuggable() {
-                        return false;
-                    }
-            };
-        mNotificationShadeWindowController.setScrimsVisibilityListener((visibility) -> {});
-        mNotificationShadeWindowController.fetchWindowRootView();
-
-        mNotificationShadeWindowController.attach();
-        verify(mWindowManager).addView(eq(mNotificationShadeWindowView), any());
-        verify(mStatusBarStateController).addCallback(mStateListener.capture(), anyInt());
-    }
-
-    @Test
-    public void testSetDozing_hidesSystemOverlays() {
-        mNotificationShadeWindowController.setDozing(true);
-        ArgumentCaptor<WindowManager.LayoutParams> captor =
-                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
-        verify(mWindowManager).updateViewLayout(any(), captor.capture());
-        int flag = captor.getValue().privateFlags
-                & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-        assertThat(flag).isNotEqualTo(0);
-
-        reset(mWindowManager);
-        mNotificationShadeWindowController.setDozing(false);
-        verify(mWindowManager).updateViewLayout(any(), captor.capture());
-        flag = captor.getValue().privateFlags
-                & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-        assertThat(flag).isEqualTo(0);
-    }
-
-    @Test
-    public void testOnThemeChanged_doesntCrash() {
-        mNotificationShadeWindowController.onThemeChanged();
-    }
-
-    @Test
-    public void testAdd_updatesVisibilityFlags() {
-        verify(mNotificationShadeWindowView).setSystemUiVisibility(anyInt());
-    }
-
-    @Test
-    public void testSetForcePluginOpen_beforeStatusBarInitialization() {
-        mNotificationShadeWindowController.setForcePluginOpen(true, this);
-    }
-
-    @Test
-    public void attach_visibleWithWallpaper() {
-        clearInvocations(mWindowManager);
-        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
-        mNotificationShadeWindowController.attach();
-
-        verify(mNotificationShadeWindowView).setVisibility(eq(View.VISIBLE));
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue();
-    }
-
-    @Test
-    public void attach_lightScrimHidesWallpaper() {
-        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
-        mNotificationShadeWindowController.attach();
-
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.setLightRevealScrimOpaque(true);
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) == 0).isTrue();
-    }
-
-    @Test
-    public void attach_scrimDoesntHideWallpaper() {
-        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
-        mNotificationShadeWindowController.attach();
-
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.setScrimsVisibility(ScrimController.OPAQUE);
-        // The scrim used to remove the wallpaper flag, but this causes a relayout.
-        // Instead, we're not relying on SurfaceControl#setOpaque on
-        // NotificationShadeDepthController.
-        verify(mWindowManager, never()).updateViewLayout(any(), mLayoutParameters.capture());
-    }
-
-    @Test
-    public void setScrimsVisibility_earlyReturn() {
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.setScrimsVisibility(ScrimController.TRANSPARENT);
-        // Abort early if value didn't change
-        verify(mWindowManager, never()).updateViewLayout(any(), mLayoutParameters.capture());
-    }
-
-    @Test
-    public void attach_animatingKeyguardAndSurface_wallpaperVisible() {
-        clearInvocations(mWindowManager);
-        when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true);
-        when(mKeyguardViewMediator
-                .isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe())
-                .thenReturn(true);
-        mNotificationShadeWindowController.attach();
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue();
-    }
-
-    @Test
-    public void setBackgroundBlurRadius_expandedWithBlurs() {
-        mNotificationShadeWindowController.setBackgroundBlurRadius(10);
-        verify(mNotificationShadeWindowView).setVisibility(eq(View.VISIBLE));
-
-        mNotificationShadeWindowController.setBackgroundBlurRadius(0);
-        verify(mNotificationShadeWindowView).setVisibility(eq(View.INVISIBLE));
-    }
-
-    @Test
-    public void setBouncerShowing_isFocusable_whenNeedsInput() {
-        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.setBouncerShowing(true);
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
-        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
-    }
-
-    @Test
-    public void setKeyguardShowing_focusable_notAltFocusable_whenNeedsInput() {
-        mNotificationShadeWindowController.setKeyguardShowing(true);
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
-        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
-    }
-
-    @Test
-    public void setPanelExpanded_notFocusable_altFocusable_whenPanelIsOpen() {
-        mNotificationShadeWindowController.onShadeOrQsExpanded(true);
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.onShadeOrQsExpanded(true);
-        verifyNoMoreInteractions(mWindowManager);
-        mNotificationShadeWindowController.setNotificationShadeFocusable(true);
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
-        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) != 0).isTrue();
-    }
-
-    @Test
-    public void setCommunalVisible_userTimeout() {
-        setKeyguardShowing();
-        clearInvocations(mWindowManager);
-
-        mNotificationShadeWindowController.onCommunalVisibleChanged(true);
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat(mLayoutParameters.getValue().userActivityTimeout)
-                .isEqualTo(CommunalInteractor.AWAKE_INTERVAL_MS);
-        clearInvocations(mWindowManager);
-
-        // Bouncer showing over communal overrides communal value
-        mNotificationShadeWindowController.setBouncerShowing(true);
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat(mLayoutParameters.getValue().userActivityTimeout)
-                .isEqualTo(KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS);
-    }
-
-    @Test
-    public void setKeyguardShowing_notFocusable_byDefault() {
-        mNotificationShadeWindowController.setKeyguardShowing(false);
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) != 0).isTrue();
-        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
-    }
-
-    @Test
-    public void setKeyguardShowing_enablesSecureFlag() {
-        mNotificationShadeWindowController.setBouncerShowing(true);
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) != 0).isTrue();
-    }
-
-    @Test
-    public void setKeyguardNotShowing_disablesSecureFlag() {
-        mNotificationShadeWindowController.setBouncerShowing(false);
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) == 0).isTrue();
-    }
-
-    @Test
-    public void rotationBecameAllowed_layoutParamsUpdated() {
-        mNotificationShadeWindowController.setKeyguardShowing(true);
-        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
-        mNotificationShadeWindowController.onConfigChanged(new Configuration());
-        clearInvocations(mWindowManager);
-
-        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true);
-        mNotificationShadeWindowController.onConfigChanged(new Configuration());
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat(mLayoutParameters.getValue().screenOrientation)
-                .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_USER);
-    }
-
-    @Test
-    public void rotationBecameNotAllowed_layoutParamsUpdated() {
-        mNotificationShadeWindowController.setKeyguardShowing(true);
-        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true);
-        mNotificationShadeWindowController.onConfigChanged(new Configuration());
-        clearInvocations(mWindowManager);
-
-        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
-        mNotificationShadeWindowController.onConfigChanged(new Configuration());
-
-        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat(mLayoutParameters.getValue().screenOrientation)
-                .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
-    }
-
-    @Test
-    public void batchApplyWindowLayoutParams_doesNotDispatchEvents() {
-        mNotificationShadeWindowController.setForceDozeBrightness(true);
-        verify(mWindowManager).updateViewLayout(any(), any());
-        mNotificationShadeWindowController.setForceDozeBrightness(true);
-        verifyNoMoreInteractions(mWindowManager);
-
-        clearInvocations(mWindowManager);
-        mNotificationShadeWindowController.batchApplyWindowLayoutParams(() -> {
-            mNotificationShadeWindowController.setForceDozeBrightness(false);
-            verify(mWindowManager, never()).updateViewLayout(any(), any());
-        });
-        verify(mWindowManager).updateViewLayout(any(), any());
-    }
-
-    @Test
-    public void bouncerShowing_OrientationNoSensor() {
-        mNotificationShadeWindowController.setKeyguardShowing(true);
-        mNotificationShadeWindowController.setKeyguardOccluded(true);
-        mNotificationShadeWindowController.setBouncerShowing(true);
-        when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
-        mNotificationShadeWindowController.onConfigChanged(new Configuration());
-
-        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
-        assertThat(mLayoutParameters.getValue().screenOrientation)
-                .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
-    }
-
-    @Test
-    public void udfpsEnrolled_minAndMaxRefreshRateSetToPreferredRefreshRate() {
-        // GIVEN optical udfps is enrolled
-        when(mAuthController.isOpticalUdfpsEnrolled(anyInt())).thenReturn(true);
-
-        // WHEN keyguard is showing
-        setKeyguardShowing();
-
-        // THEN min and max refresh rate is set to the preferredRefreshRate
-        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
-        final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
-        final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
-        assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(mPreferredRefreshRate);
-        assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(mPreferredRefreshRate);
-    }
-
-    @Test
-    public void opticalUdfpsNotEnrolled_refreshRateUnset() {
-        // GIVEN udfps is NOT enrolled
-        when(mAuthController.isOpticalUdfpsEnrolled(anyInt())).thenReturn(false);
-
-        // WHEN keyguard is showing
-        setKeyguardShowing();
-
-        // THEN min and max refresh rate aren't set (set to 0)
-        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
-        final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
-        final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
-        assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(0);
-        assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0);
-    }
-
-    @Test
-    public void keyguardNotShowing_refreshRateUnset() {
-        // GIVEN optical UDFPS is enrolled
-        when(mAuthController.isOpticalUdfpsEnrolled(anyInt())).thenReturn(true);
-
-        // WHEN keyguard is NOT showing
-        mNotificationShadeWindowController.setKeyguardShowing(false);
-
-        // THEN min and max refresh rate aren't set (set to 0)
-        verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
-        final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
-        final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
-        assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(0);
-        assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0);
-    }
-
-    private void setKeyguardShowing() {
-        mNotificationShadeWindowController.setKeyguardShowing(true);
-        mNotificationShadeWindowController.setKeyguardGoingAway(false);
-        mNotificationShadeWindowController.setKeyguardFadingAway(false);
-        mStateListener.getValue().onStateChanged(StatusBarState.KEYGUARD);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index dfbb699..d95cc2e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -38,11 +38,11 @@
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED
 import com.android.systemui.flags.Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION
-import com.android.systemui.flags.Flags.TRACKPAD_GESTURE_COMMON
-import com.android.systemui.flags.Flags.TRACKPAD_GESTURE_FEATURES
 import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
@@ -69,7 +69,6 @@
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
-import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.emptyFlow
@@ -87,6 +86,8 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import kotlin.test.assertEquals
+import java.util.Optional
 import org.mockito.Mockito.`when` as whenever
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -138,6 +139,7 @@
     private val notificationLaunchAnimationInteractor =
         NotificationLaunchAnimationInteractor(notificationLaunchAnimationRepository)
 
+    private lateinit var falsingCollector: FalsingCollectorFake
     private lateinit var fakeClock: FakeSystemClock
     private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
     private lateinit var interactionEventHandler: InteractionEventHandler
@@ -158,23 +160,22 @@
             .thenReturn(keyguardBouncerComponent)
         whenever(keyguardBouncerComponent.securityContainerController)
             .thenReturn(keyguardSecurityContainerController)
-        whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+        whenever(keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING))
             .thenReturn(emptyFlow<TransitionStep>())
 
         featureFlagsClassic = FakeFeatureFlagsClassic()
-        featureFlagsClassic.set(TRACKPAD_GESTURE_COMMON, true)
-        featureFlagsClassic.set(TRACKPAD_GESTURE_FEATURES, false)
         featureFlagsClassic.set(SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
         featureFlagsClassic.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
         mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
         mSetFlagsRule.enableFlags(Flags.FLAG_REVAMPED_BOUNCER_MESSAGES)
 
         testScope = TestScope()
+        falsingCollector = FalsingCollectorFake()
         fakeClock = FakeSystemClock()
         underTest =
             NotificationShadeWindowViewController(
                 lockscreenShadeTransitionController,
-                FalsingCollectorFake(),
+                falsingCollector,
                 sysuiStatusBarStateController,
                 dockManager,
                 notificationShadeDepthController,
@@ -499,6 +500,46 @@
     }
 
     @Test
+    fun handleExternalTouch_intercepted_sendsOnTouch() {
+        // Accept dispatch and also intercept.
+        whenever(view.dispatchTouchEvent(any())).thenReturn(true)
+        whenever(view.onInterceptTouchEvent(any())).thenReturn(true)
+
+        underTest.handleExternalTouch(DOWN_EVENT)
+        underTest.handleExternalTouch(MOVE_EVENT)
+
+        // Once intercepted, both events are sent to the view.
+        verify(view).onTouchEvent(DOWN_EVENT)
+        verify(view).onTouchEvent(MOVE_EVENT)
+    }
+
+    @Test
+    fun handleExternalTouch_notDispatched_interceptNotCalled() {
+        // Don't accept dispatch
+        whenever(view.dispatchTouchEvent(any())).thenReturn(false)
+
+        underTest.handleExternalTouch(DOWN_EVENT)
+
+        // Interception is not offered.
+        verify(view, never()).onInterceptTouchEvent(any())
+    }
+
+    @Test
+    fun handleExternalTouch_notIntercepted_onTouchNotSent() {
+        // Accept dispatch, but don't dispatch
+        whenever(view.dispatchTouchEvent(any())).thenReturn(true)
+        whenever(view.onInterceptTouchEvent(any())).thenReturn(false)
+
+        underTest.handleExternalTouch(DOWN_EVENT)
+        underTest.handleExternalTouch(MOVE_EVENT)
+
+        // Interception offered for both events, but onTouchEvent is never called.
+        verify(view).onInterceptTouchEvent(DOWN_EVENT)
+        verify(view).onInterceptTouchEvent(MOVE_EVENT)
+        verify(view, never()).onTouchEvent(any())
+    }
+
+    @Test
     fun testGetKeyguardMessageArea() =
         testScope.runTest {
             underTest.keyguardMessageArea
@@ -566,6 +607,21 @@
         verify(sysUIKeyEventHandler).interceptMediaKey(keyEvent)
     }
 
+    @Test
+    fun forwardsCollectKeyEvent() {
+        val keyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A)
+        interactionEventHandler.collectKeyEvent(keyEvent)
+        assertEquals(keyEvent, falsingCollector.lastKeyEvent)
+    }
+
+    @Test
+    fun cancelCurrentTouch_callsDragDownHelper() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        underTest.cancelCurrentTouch()
+
+        verify(dragDownHelper).stopDragging()
+    }
+
     companion object {
         private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
         private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 98a815c..f380b6c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -36,6 +36,8 @@
 import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
@@ -149,12 +151,10 @@
         whenever(statusBarStateController.isDozing).thenReturn(false)
         mDependency.injectTestDependency(ShadeController::class.java, shadeController)
         whenever(dockManager.isDocked).thenReturn(false)
-        whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+        whenever(keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING))
             .thenReturn(emptyFlow())
 
         val featureFlags = FakeFeatureFlags()
-        featureFlags.set(Flags.TRACKPAD_GESTURE_COMMON, true)
-        featureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false)
         featureFlags.set(Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
         featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
         mSetFlagsRule.disableFlags(AConfigFlags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index 20d877e..0f51878 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -31,7 +31,6 @@
 import android.view.ViewParent;
 import android.view.accessibility.AccessibilityManager;
 
-import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.keyguard.KeyguardStatusView;
@@ -62,7 +61,6 @@
 import com.android.systemui.res.R;
 import com.android.systemui.scene.data.repository.SceneContainerRepository;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
 import com.android.systemui.scene.shared.logger.SceneLogger;
 import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.shade.data.repository.FakeShadeRepository;
@@ -170,7 +168,6 @@
     protected FakeKeyguardRepository mKeyguardRepository = new FakeKeyguardRepository();
     protected FakeShadeRepository mShadeRepository = new FakeShadeRepository();
 
-    protected InteractionJankMonitor mInteractionJankMonitor;
     protected SysuiStatusBarStateController mStatusBarStateController;
     protected ShadeInteractor mShadeInteractor;
 
@@ -191,7 +188,6 @@
         MockitoAnnotations.initMocks(this);
         when(mPanelViewControllerLazy.get()).thenReturn(mNotificationPanelViewController);
         mStatusBarStateController = mKosmos.getStatusBarStateController();
-        mInteractionJankMonitor = mKosmos.getInteractionJankMonitor();
 
         mKosmos.getFakeDeviceProvisioningRepository().setDeviceProvisioned(true);
         FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
@@ -208,14 +204,12 @@
                 mock(SceneLogger.class),
                 mKosmos.getDeviceUnlockedInteractor());
 
-        FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags();
         KeyguardTransitionInteractor keyguardTransitionInteractor =
                 mKosmos.getKeyguardTransitionInteractor();
         KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
                 mKeyguardRepository,
                 new FakeCommandQueue(),
                 powerInteractor,
-                sceneContainerFlags,
                 new FakeKeyguardBouncerRepository(),
                 new ConfigurationInteractor(configurationRepository),
                 mShadeRepository,
@@ -325,7 +319,7 @@
                 mAccessibilityManager,
                 mLockscreenGestureLogger,
                 mMetricsLogger,
-                mInteractionJankMonitor,
+                () -> mKosmos.getInteractionJankMonitor(),
                 mShadeLogger,
                 mDumpManager,
                 mock(DeviceEntryFaceAuthInteractor.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
index 433c95a..6bdd3ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
@@ -33,7 +33,6 @@
 import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
@@ -95,7 +94,6 @@
             headsUpManager,
             PowerInteractorFactory.create().powerInteractor,
             ActiveNotificationsInteractor(activeNotificationsRepository, testDispatcher),
-            kosmos.sceneContainerFlags,
             kosmos::sceneInteractor,
         )
     }
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 f2abb90..7c33648 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
@@ -1,15 +1,14 @@
 package com.android.systemui.shade.transition
 
-import android.platform.test.annotations.DisableFlags
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
 import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.DisableSceneContainer
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.SceneInteractor
@@ -70,7 +69,7 @@
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
+    @DisableSceneContainer
     fun onPanelExpansionChanged_setsFractionEqualToEventFraction() {
         underTest.onPanelExpansionChanged(DEFAULT_EXPANSION_EVENT)
 
@@ -78,7 +77,7 @@
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
+    @DisableSceneContainer
     fun onPanelStateChanged_forwardsToScrimTransitionController() {
         startLegacyPanelExpansion()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
index eb418fd..4679a58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
@@ -19,11 +19,12 @@
 import android.content.Context
 import android.content.res.Resources
 import android.content.res.TypedArray
+import android.platform.test.annotations.PlatinumTest
 import android.testing.AndroidTestingRunner
 import android.util.AttributeSet
 import androidx.test.filters.SmallTest
-import com.android.systemui.shared.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.shared.R
 import com.android.systemui.shared.shadow.DoubleShadowTextClock
 import com.android.systemui.util.mockito.whenever
 import junit.framework.Assert.assertTrue
@@ -36,6 +37,7 @@
 import org.mockito.junit.MockitoJUnit
 import org.mockito.junit.MockitoRule
 
+@PlatinumTest(focusArea = "sysui")
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 class DoubleShadowTextClockTest : SysuiTestCase() {
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 56fc0c7..a05a23b 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
@@ -21,7 +21,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction
 import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.ViewIdToTranslate
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
@@ -34,21 +34,19 @@
 @RunWith(AndroidTestingRunner::class)
 class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() {
 
-    private val progressProvider = TestUnfoldTransitionProvider()
+    private val progressProvider = FakeUnfoldTransitionProvider()
 
-    @Mock
-    private lateinit var parent: ViewGroup
+    @Mock private lateinit var parent: ViewGroup
 
-    @Mock
-    private lateinit var shouldBeAnimated: () -> Boolean
+    @Mock private lateinit var shouldBeAnimated: () -> Boolean
 
     private lateinit var animator: UnfoldConstantTranslateAnimator
 
     private val viewsIdToRegister
         get() =
             setOf(
-                    ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
-                    ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
+                ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
+                ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
             )
 
     @Before
@@ -122,11 +120,12 @@
         progressProvider.onTransitionStarted()
         progressProvider.onTransitionProgress(0f)
 
-        val rtlMultiplier = if (layoutDirection == View.LAYOUT_DIRECTION_LTR) {
-            1
-        } else {
-            -1
-        }
+        val rtlMultiplier =
+            if (layoutDirection == View.LAYOUT_DIRECTION_LTR) {
+                1
+            } else {
+                -1
+            }
         list.forEach { (view, direction) ->
             assertEquals(
                 (-MAX_TRANSLATION * direction * rtlMultiplier).toInt(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
index 8841f48..3cb48d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
@@ -15,7 +15,7 @@
 package com.android.systemui.shared.animation
 
 import android.graphics.Point
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.view.Display
 import android.view.Surface.ROTATION_0
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
index c39b29f..e9222c3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
@@ -37,8 +37,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
index 02954b8..7ddf7a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
@@ -26,9 +26,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
deleted file mode 100644
index de61086..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.statusbar
-
-import android.animation.ObjectAnimator
-import android.platform.test.annotations.DisableFlags
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.testing.UiEventLoggerFake
-import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
-import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.classifier.FalsingCollectorFake
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
-import com.android.systemui.flags.EnableSceneContainer
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.jank.interactionJankMonitor
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.fromGoneTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.fromLockscreenTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.fromPrimaryBouncerTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.data.repository.FakePowerRepository
-import com.android.systemui.power.domain.interactor.PowerInteractor
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
-import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.LargeScreenHeaderHelper
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl
-import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
-import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
-import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
-import com.android.systemui.testKosmos
-import com.android.systemui.util.kotlin.JavaAdapter
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mockito
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
[email protected]
-class StatusBarStateControllerImplTest : SysuiTestCase() {
-
-    private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
-    private lateinit var shadeInteractor: ShadeInteractor
-    private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
-    private lateinit var fromPrimaryBouncerTransitionInteractor:
-        FromPrimaryBouncerTransitionInteractor
-    private val mockDarkAnimator = mock<ObjectAnimator>()
-    private val deviceEntryUdfpsInteractor = mock<DeviceEntryUdfpsInteractor>()
-    private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
-
-    private lateinit var underTest: StatusBarStateControllerImpl
-    private lateinit var uiEventLogger: UiEventLoggerFake
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        uiEventLogger = UiEventLoggerFake()
-        underTest =
-            object :
-                StatusBarStateControllerImpl(
-                    uiEventLogger,
-                    kosmos.interactionJankMonitor,
-                    JavaAdapter(testScope.backgroundScope),
-                    { shadeInteractor },
-                    { kosmos.deviceUnlockedInteractor },
-                    { kosmos.sceneInteractor },
-                    { kosmos.keyguardClockInteractor },
-                ) {
-                override fun createDarkAnimator(): ObjectAnimator {
-                    return mockDarkAnimator
-                }
-            }
-
-        val powerInteractor =
-            PowerInteractor(FakePowerRepository(), FalsingCollectorFake(), mock(), underTest)
-        val keyguardRepository = FakeKeyguardRepository()
-        val keyguardTransitionRepository = FakeKeyguardTransitionRepository()
-        val featureFlags = FakeFeatureFlagsClassic()
-        val shadeRepository = FakeShadeRepository()
-        val sceneContainerFlags = FakeSceneContainerFlags()
-        val configurationRepository = FakeConfigurationRepository()
-        val keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor
-        fromLockscreenTransitionInteractor = kosmos.fromLockscreenTransitionInteractor
-        fromPrimaryBouncerTransitionInteractor = kosmos.fromPrimaryBouncerTransitionInteractor
-
-        val keyguardInteractor =
-            KeyguardInteractor(
-                keyguardRepository,
-                FakeCommandQueue(),
-                powerInteractor,
-                sceneContainerFlags,
-                FakeKeyguardBouncerRepository(),
-                ConfigurationInteractor(configurationRepository),
-                shadeRepository,
-                keyguardTransitionInteractor,
-                { kosmos.sceneInteractor },
-                { kosmos.fromGoneTransitionInteractor },
-                { kosmos.sharedNotificationContainerInteractor },
-                testScope,
-            )
-
-        whenever(deviceEntryUdfpsInteractor.isUdfpsSupported).thenReturn(MutableStateFlow(false))
-        shadeInteractor =
-            ShadeInteractorImpl(
-                testScope.backgroundScope,
-                kosmos.deviceProvisioningInteractor,
-                FakeDisableFlagsRepository(),
-                mock(),
-                keyguardRepository,
-                keyguardTransitionInteractor,
-                powerInteractor,
-                FakeUserSetupRepository(),
-                mock(),
-                ShadeInteractorLegacyImpl(
-                    testScope.backgroundScope,
-                    keyguardRepository,
-                    SharedNotificationContainerInteractor(
-                        configurationRepository,
-                        mContext,
-                        ResourcesSplitShadeStateController(),
-                        keyguardInteractor,
-                        deviceEntryUdfpsInteractor,
-                        largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
-                    ),
-                    shadeRepository,
-                )
-            )
-    }
-
-    @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER)
-    fun testChangeState_logged() {
-        TestableLooper.get(this).runWithLooper {
-            underTest.state = StatusBarState.KEYGUARD
-            underTest.state = StatusBarState.SHADE
-            underTest.state = StatusBarState.SHADE_LOCKED
-        }
-
-        val logs = uiEventLogger.logs
-        assertEquals(3, logs.size)
-        val ids = logs.map(UiEventLoggerFake.FakeUiEvent::eventId)
-        assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_KEYGUARD.id, ids[0])
-        assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_SHADE.id, ids[1])
-        assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_SHADE_LOCKED.id, ids[2])
-    }
-
-    @Test
-    fun testSetDozeAmountInternal_onlySetsOnce() {
-        val listener = mock(StatusBarStateController.StateListener::class.java)
-        underTest.addCallback(listener)
-
-        underTest.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */)
-        underTest.setAndInstrumentDozeAmount(null, 0.5f, false /* animated */)
-        verify(listener).onDozeAmountChanged(eq(0.5f), anyFloat())
-    }
-
-    @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER)
-    fun testSetState_appliesState_sameStateButDifferentUpcomingState() {
-        underTest.state = StatusBarState.SHADE
-        underTest.setUpcomingState(StatusBarState.KEYGUARD)
-
-        assertEquals(underTest.state, StatusBarState.SHADE)
-
-        // We should return true (state change was applied) despite going from SHADE to SHADE, since
-        // the upcoming state was set to KEYGUARD.
-        assertTrue(underTest.setState(StatusBarState.SHADE))
-    }
-
-    @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER)
-    fun testSetState_appliesState_differentStateEqualToUpcomingState() {
-        underTest.state = StatusBarState.SHADE
-        underTest.setUpcomingState(StatusBarState.KEYGUARD)
-
-        assertEquals(underTest.state, StatusBarState.SHADE)
-
-        // Make sure we apply a SHADE -> KEYGUARD state change when the upcoming state is KEYGUARD.
-        assertTrue(underTest.setState(StatusBarState.KEYGUARD))
-    }
-
-    @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER)
-    fun testSetState_doesNotApplyState_currentAndUpcomingStatesSame() {
-        underTest.state = StatusBarState.SHADE
-        underTest.setUpcomingState(StatusBarState.SHADE)
-
-        assertEquals(underTest.state, StatusBarState.SHADE)
-
-        // We're going from SHADE -> SHADE, and the upcoming state is also SHADE, this should not do
-        // anything.
-        assertFalse(underTest.setState(StatusBarState.SHADE))
-
-        // Double check that we can still force it to happen.
-        assertTrue(underTest.setState(StatusBarState.SHADE, true /* force */))
-    }
-
-    @Test
-    fun testSetDozeAmount_immediatelyChangesDozeAmount_lockscreenTransitionFromAod() {
-        // Put controller in AOD state
-        underTest.setAndInstrumentDozeAmount(null, 1f, false)
-
-        // When waking from doze, CentralSurfaces#updateDozingState will update the dozing state
-        // before the doze amount changes
-        underTest.setIsDozing(false)
-
-        // Animate the doze amount to 0f, as would normally happen
-        underTest.setAndInstrumentDozeAmount(null, 0f, true)
-
-        // Check that the doze amount is immediately set to a value slightly less than 1f. This is
-        // to ensure that any scrim implementation changes its opacity immediately rather than
-        // waiting an extra frame. Waiting an extra frame will cause a relayout (which is expensive)
-        // and cause us to drop a frame during the LOCKSCREEN_TRANSITION_FROM_AOD CUJ.
-        assertEquals(0.99f, underTest.dozeAmount, 0.009f)
-    }
-
-    @Test
-    fun testSetDreamState_invokesCallback() {
-        val listener = mock(StatusBarStateController.StateListener::class.java)
-        underTest.addCallback(listener)
-
-        underTest.setIsDreaming(true)
-        verify(listener).onDreamingChanged(true)
-
-        Mockito.clearInvocations(listener)
-
-        underTest.setIsDreaming(false)
-        verify(listener).onDreamingChanged(false)
-    }
-
-    @Test
-    fun testSetDreamState_getterReturnsCurrentState() {
-        underTest.setIsDreaming(true)
-        assertTrue(underTest.isDreaming())
-
-        underTest.setIsDreaming(false)
-        assertFalse(underTest.isDreaming())
-    }
-
-    @Test
-    @EnableSceneContainer
-    fun start_hydratesStatusBarState_whileLocked() =
-        testScope.runTest {
-            var statusBarState = underTest.state
-            val listener =
-                object : StatusBarStateController.StateListener {
-                    override fun onStateChanged(newState: Int) {
-                        statusBarState = newState
-                    }
-                }
-            underTest.addCallback(listener)
-
-            val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
-            val deviceUnlockStatus by
-                collectLastValue(kosmos.deviceUnlockedInteractor.deviceUnlockStatus)
-
-            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
-                AuthenticationMethodModel.Password
-            )
-            runCurrent()
-            assertThat(deviceUnlockStatus!!.isUnlocked).isFalse()
-
-            kosmos.sceneInteractor.changeScene(
-                toScene = Scenes.Lockscreen,
-                loggingReason = "reason"
-            )
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
-
-            // Call start to begin hydrating based on the scene framework:
-            underTest.start()
-
-            kosmos.sceneInteractor.changeScene(toScene = Scenes.Bouncer, loggingReason = "reason")
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
-            assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD)
-
-            kosmos.sceneInteractor.changeScene(toScene = Scenes.Shade, loggingReason = "reason")
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Shade)
-            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE_LOCKED)
-
-            kosmos.sceneInteractor.changeScene(
-                toScene = Scenes.QuickSettings,
-                loggingReason = "reason"
-            )
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
-            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE_LOCKED)
-
-            kosmos.sceneInteractor.changeScene(toScene = Scenes.Communal, loggingReason = "reason")
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Communal)
-            assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD)
-
-            kosmos.sceneInteractor.changeScene(
-                toScene = Scenes.Lockscreen,
-                loggingReason = "reason"
-            )
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
-            assertThat(statusBarState).isEqualTo(StatusBarState.KEYGUARD)
-        }
-
-    @Test
-    @EnableSceneContainer
-    fun start_hydratesStatusBarState_whileUnlocked() =
-        testScope.runTest {
-            var statusBarState = underTest.state
-            val listener =
-                object : StatusBarStateController.StateListener {
-                    override fun onStateChanged(newState: Int) {
-                        statusBarState = newState
-                    }
-                }
-            underTest.addCallback(listener)
-
-            val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
-            val deviceUnlockStatus by
-                collectLastValue(kosmos.deviceUnlockedInteractor.deviceUnlockStatus)
-            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
-                AuthenticationMethodModel.Password
-            )
-            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
-                SuccessFingerprintAuthenticationStatus(0, true)
-            )
-            runCurrent()
-
-            assertThat(deviceUnlockStatus!!.isUnlocked).isTrue()
-
-            kosmos.sceneInteractor.changeScene(toScene = Scenes.Gone, loggingReason = "reason")
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Gone)
-
-            // Call start to begin hydrating based on the scene framework:
-            underTest.start()
-
-            kosmos.sceneInteractor.changeScene(toScene = Scenes.Shade, loggingReason = "reason")
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.Shade)
-            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE)
-
-            kosmos.sceneInteractor.changeScene(
-                toScene = Scenes.QuickSettings,
-                loggingReason = "reason"
-            )
-            runCurrent()
-            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
-            assertThat(statusBarState).isEqualTo(StatusBarState.SHADE)
-        }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
index 16eb1d9..b18b7f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.commandline
 
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
index 5bc75e8..7e88ae0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.statusbar.connectivity
 
 import android.os.UserManager
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.lifecycle.Lifecycle
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
index 44e3bb4..7bd77a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
@@ -22,14 +22,14 @@
 
 import android.os.HandlerThread;
 import android.telephony.SubscriptionInfo;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.connectivity.NetworkController.EmergencyListener;
 import com.android.systemui.res.R;
+import com.android.systemui.statusbar.connectivity.NetworkController.EmergencyListener;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt
index a226ded..7aed4f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt
@@ -15,8 +15,8 @@
  */
 package com.android.systemui.statusbar.connectivity
 
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.SysuiTestCase
 import junit.framework.Assert.assertFalse
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
index f667b83..461d804 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
@@ -39,11 +39,12 @@
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.settingslib.SignalIcon.MobileIconGroup;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java
index f6f939a..3bbf06d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java
@@ -19,10 +19,11 @@
 import static junit.framework.Assert.assertEquals;
 
 import android.net.NetworkCapabilities;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 
+import androidx.test.filters.SmallTest;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
index 375ca063..35609a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
@@ -33,17 +33,18 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.res.R;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.log.LogBuffer;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.util.CarrierConfigTracker;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
index 9e73487..5bf0a94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.connectivity
 
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
 import com.android.settingslib.SignalIcon.MobileIconGroup
 import com.android.systemui.SysuiTestCase
 import com.google.common.truth.Truth.assertThat
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
index 2b94561..6b2ee76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
@@ -19,12 +19,13 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.widget.FrameLayout;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
index fda8f51..fc4702c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
@@ -42,10 +42,11 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.service.notification.StatusBarNotification;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
index eb692eb..eafa78e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
@@ -25,13 +25,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.media.dialog.MediaOutputDialogManager;
 import com.android.systemui.res.R;
@@ -40,6 +41,9 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.RowContentBindParams;
 import com.android.systemui.statusbar.notification.row.RowContentBindStage;
+import com.android.systemui.statusbar.notification.row.RowInflaterTask;
+import com.android.systemui.statusbar.notification.row.RowInflaterTaskLogger;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -114,20 +118,25 @@
 
     private NotificationEntry addGroup(int size) {
         NotificationEntry summary = new NotificationEntryBuilder().build();
-        summary.setRow(createRow());
+        summary.setRow(createRow(summary));
         ArrayList<NotificationEntry> children = new ArrayList<>();
         for (int i = 0; i < size; i++) {
             NotificationEntry child = new NotificationEntryBuilder().build();
-            child.setRow(createRow());
+            child.setRow(createRow(child));
             children.add(child);
         }
         mGroupNotifs.put(summary, children);
         return summary;
     }
 
-    private ExpandableNotificationRow createRow() {
+    private ExpandableNotificationRow createRow(NotificationEntry entry) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        inflater.setFactory2(
+                new RowInflaterTask.RowAsyncLayoutInflater(entry, new FakeSystemClock(), mock(
+                        RowInflaterTaskLogger.class)));
+
         ExpandableNotificationRow row = (ExpandableNotificationRow)
-                LayoutInflater.from(mContext).inflate(R.layout.status_bar_notification_row, null);
+                inflater.inflate(R.layout.status_bar_notification_row, null);
         row.getPrivateLayout().setContractedChild(new View(mContext));
         row.getPrivateLayout().setExpandedChild(new View(mContext));
         return row;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
index a6381d1..5b72ca0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java
@@ -25,10 +25,11 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -38,7 +39,6 @@
 import org.junit.Before;
 import org.junit.Test;
 
-
 @SmallTest
 @org.junit.runner.RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
index 811e9bf..3b3f05d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
@@ -8,7 +8,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.jank.interactionJankMonitor
-import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -19,9 +19,9 @@
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.statusbar.policy.HeadsUpUtil
+import com.android.systemui.testKosmos
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
-import kotlinx.coroutines.test.TestScope
 import org.junit.Assert.assertNotSame
 import org.junit.Assert.assertSame
 import org.junit.Before
@@ -48,7 +48,8 @@
     private val notificationLaunchAnimationInteractor =
         NotificationLaunchAnimationInteractor(NotificationLaunchAnimationRepository())
 
-    private val testScope = TestScope()
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
 
     private val notificationKey: String
         get() = notification.entry.sbn.key
@@ -67,7 +68,7 @@
                 notificationListContainer,
                 headsUpManager,
                 notification,
-                Kosmos().interactionJankMonitor,
+                kosmos.interactionJankMonitor,
                 onFinishAnimationCallback
             )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
index 2ef4374..2d8e692 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
@@ -18,8 +18,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
 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.anyBoolean;
@@ -30,7 +30,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.UiThreadTest;
 import android.util.FloatProperty;
@@ -38,6 +37,8 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.app.animation.Interpolators;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.res.R;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
index cac4a8d..6bda4d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
@@ -299,8 +299,6 @@
     @Test
     public void testSetFooterLabelVisible() {
         mView.setFooterLabelVisible(true);
-        assertThat(mView.findViewById(R.id.manage_text).getVisibility()).isEqualTo(View.GONE);
-        assertThat(mView.findSecondaryView().getVisibility()).isEqualTo(View.GONE);
         assertThat(mView.findViewById(R.id.unlock_prompt_footer).getVisibility())
                 .isEqualTo(View.VISIBLE);
     }
@@ -308,8 +306,6 @@
     @Test
     public void testSetFooterLabelInvisible() {
         mView.setFooterLabelVisible(false);
-        assertThat(mView.findViewById(R.id.manage_text).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mView.findSecondaryView().getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mView.findViewById(R.id.unlock_prompt_footer).getVisibility())
                 .isEqualTo(View.GONE);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
index 620d972..158f38d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
@@ -66,7 +66,7 @@
     val underTest = kosmos.footerViewModel
 
     @Test
-    fun testMessageVisible_whenFilteredNotifications() =
+    fun messageVisible_whenFilteredNotifications() =
         testScope.runTest {
             val visible by collectLastValue(underTest.message.isVisible)
 
@@ -76,7 +76,7 @@
         }
 
     @Test
-    fun testMessageVisible_whenNoFilteredNotifications() =
+    fun messageVisible_whenNoFilteredNotifications() =
         testScope.runTest {
             val visible by collectLastValue(underTest.message.isVisible)
 
@@ -86,7 +86,7 @@
         }
 
     @Test
-    fun testClearAllButtonVisible_whenHasClearableNotifs() =
+    fun clearAllButtonVisible_whenHasClearableNotifs() =
         testScope.runTest {
             val visible by collectLastValue(underTest.clearAllButton.isVisible)
 
@@ -104,7 +104,7 @@
         }
 
     @Test
-    fun testClearAllButtonVisible_whenHasNoClearableNotifs() =
+    fun clearAllButtonVisible_whenHasNoClearableNotifs() =
         testScope.runTest {
             val visible by collectLastValue(underTest.clearAllButton.isVisible)
 
@@ -122,7 +122,26 @@
         }
 
     @Test
-    fun testClearAllButtonAnimating_whenShadeExpandedAndTouchable() =
+    fun clearAllButtonVisible_whenMessageVisible() =
+        testScope.runTest {
+            val visible by collectLastValue(underTest.clearAllButton.isVisible)
+
+            activeNotificationListRepository.notifStats.value =
+                NotifStats(
+                    numActiveNotifs = 2,
+                    hasNonClearableAlertingNotifs = false,
+                    hasClearableAlertingNotifs = true,
+                    hasNonClearableSilentNotifs = false,
+                    hasClearableSilentNotifs = true,
+                )
+            activeNotificationListRepository.hasFilteredOutSeenNotifications.value = true
+            runCurrent()
+
+            assertThat(visible?.value).isFalse()
+        }
+
+    @Test
+    fun clearAllButtonAnimating_whenShadeExpandedAndTouchable() =
         testScope.runTest {
             val visible by collectLastValue(underTest.clearAllButton.isVisible)
             runCurrent()
@@ -156,7 +175,7 @@
         }
 
     @Test
-    fun testClearAllButtonAnimating_whenShadeNotExpanded() =
+    fun clearAllButtonAnimating_whenShadeNotExpanded() =
         testScope.runTest {
             val visible by collectLastValue(underTest.clearAllButton.isVisible)
             runCurrent()
@@ -190,7 +209,7 @@
         }
 
     @Test
-    fun testManageButton_whenHistoryDisabled() =
+    fun manageButton_whenHistoryDisabled() =
         testScope.runTest {
             val buttonLabel by collectLastValue(underTest.manageOrHistoryButton.labelId)
             runCurrent()
@@ -203,7 +222,7 @@
         }
 
     @Test
-    fun testHistoryButton_whenHistoryEnabled() =
+    fun historyButton_whenHistoryEnabled() =
         testScope.runTest {
             val buttonLabel by collectLastValue(underTest.manageOrHistoryButton.labelId)
             runCurrent()
@@ -214,4 +233,24 @@
             // THEN label is "History"
             assertThat(buttonLabel).isEqualTo(R.string.manage_notifications_history_text)
         }
+
+    @Test
+    fun manageButtonVisible_whenMessageVisible() =
+        testScope.runTest {
+            val visible by collectLastValue(underTest.manageOrHistoryButton.isVisible)
+
+            activeNotificationListRepository.hasFilteredOutSeenNotifications.value = true
+
+            assertThat(visible?.value).isFalse()
+        }
+
+    @Test
+    fun manageButtonVisible_whenMessageNotVisible() =
+        testScope.runTest {
+            val visible by collectLastValue(underTest.manageOrHistoryButton.isVisible)
+
+            activeNotificationListRepository.hasFilteredOutSeenNotifications.value = false
+
+            assertThat(visible?.value).isTrue()
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
index 4eb7daa..894e02e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
@@ -188,6 +188,9 @@
     @Test
     fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
         testComponent.runTest {
+            val animationsEnabled by collectLastValue(underTest.areContainerChangesAnimated)
+            assertThat(animationsEnabled).isTrue()
+
             powerRepository.updateWakefulness(
                 rawState = WakefulnessState.STARTING_TO_SLEEP,
                 lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -201,8 +204,6 @@
                 )
             )
             whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
-            val animationsEnabled by collectLastValue(underTest.areContainerChangesAnimated)
-            runCurrent()
             assertThat(animationsEnabled).isTrue()
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
index 35b8493..78b7615 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
@@ -195,6 +195,9 @@
     @Test
     fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
         testComponent.runTest {
+            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+            assertThat(animationsEnabled).isTrue()
+
             powerRepository.updateWakefulness(
                 rawState = WakefulnessState.STARTING_TO_SLEEP,
                 lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -208,7 +211,7 @@
                 )
             )
             whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+
             runCurrent()
             assertThat(animationsEnabled).isTrue()
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
index 5410864..edab9d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
@@ -50,7 +50,8 @@
             systemClock,
             uiEventLogger,
             userTracker,
-            avalancheProvider
+            avalancheProvider,
+            systemSettings
         )
     }
 
@@ -82,7 +83,7 @@
     fun testAvalancheFilter_duringAvalanche_allowConversationFromAfterEvent() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_HIGH
@@ -97,7 +98,7 @@
     fun testAvalancheFilter_duringAvalanche_suppressConversationFromBeforeEvent() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldNotHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_DEFAULT
@@ -112,7 +113,7 @@
     fun testAvalancheFilter_duringAvalanche_allowHighPriorityConversation() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_HIGH
@@ -125,7 +126,7 @@
     fun testAvalancheFilter_duringAvalanche_allowCall() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_HIGH
@@ -138,7 +139,7 @@
     fun testAvalancheFilter_duringAvalanche_allowCategoryReminder() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_HIGH
@@ -151,7 +152,7 @@
     fun testAvalancheFilter_duringAvalanche_allowCategoryEvent() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_HIGH
@@ -164,7 +165,7 @@
     fun testAvalancheFilter_duringAvalanche_allowFsi() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             assertFsiNotSuppressed()
         }
     }
@@ -173,7 +174,7 @@
     fun testAvalancheFilter_duringAvalanche_allowColorized() {
         avalancheProvider.startTime = whenAgo(10)
 
-        withFilter(AvalancheSuppressor(avalancheProvider, systemClock)) {
+        withFilter(AvalancheSuppressor(avalancheProvider, systemClock, systemSettings)) {
             ensurePeekState()
             assertShouldHeadsUp(buildEntry {
                 importance = NotificationManager.IMPORTANCE_HIGH
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
index 24f6708..3b979a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
@@ -77,6 +77,8 @@
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.settings.FakeGlobalSettings
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.settings.SystemSettings
 import com.android.systemui.util.time.FakeSystemClock
 import com.android.systemui.utils.leaks.FakeBatteryController
 import com.android.systemui.utils.leaks.FakeKeyguardStateController
@@ -126,6 +128,7 @@
     protected val uiEventLogger = UiEventLoggerFake()
     protected val userTracker = FakeUserTracker()
     protected val avalancheProvider: AvalancheProvider = mock()
+    lateinit var systemSettings: SystemSettings
 
     protected abstract val provider: VisualInterruptionDecisionProvider
 
@@ -153,6 +156,7 @@
 
         deviceProvisionedController.currentUser = userId
         userTracker.set(listOf(user), /* currentUserIndex = */ 0)
+        systemSettings = FakeSettings()
 
         provider.start()
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt
index 620ad9c..60aaa64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestUtil.kt
@@ -30,6 +30,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.EventLog
 import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.settings.SystemSettings
 import com.android.systemui.util.time.SystemClock
 
 object VisualInterruptionDecisionProviderTestUtil {
@@ -51,7 +52,8 @@
         systemClock: SystemClock,
         uiEventLogger: UiEventLogger,
         userTracker: UserTracker,
-        avalancheProvider: AvalancheProvider
+        avalancheProvider: AvalancheProvider,
+        systemSettings: SystemSettings
     ): VisualInterruptionDecisionProvider {
         return if (VisualInterruptionRefactor.isEnabled) {
             VisualInterruptionDecisionProviderImpl(
@@ -70,7 +72,8 @@
                 systemClock,
                 uiEventLogger,
                 userTracker,
-                avalancheProvider
+                avalancheProvider,
+                systemSettings
             )
         } else {
             NotificationInterruptStateProviderWrapper(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 69e0db9..bb68ec5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -138,7 +138,6 @@
                 mHeadsUpManager,
                 mPowerInteractor,
                 mActiveNotificationsInteractor,
-                mKosmos.getFakeSceneContainerFlags(),
                 () -> mKosmos.getSceneInteractor());
         mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
index 33a838e..4b0b4b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
@@ -25,6 +25,7 @@
 import android.util.StatsEvent
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.assertLogsWtf
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -133,8 +134,10 @@
         val pipeline: NotifPipeline = mock()
         whenever(pipeline.allNotifs).thenThrow(RuntimeException("Something broke!"))
         val logger = NotificationMemoryLogger(pipeline, statsManager, immediate, bgExecutor)
-        assertThat(logger.onPullAtom(SysUiStatsLog.NOTIFICATION_MEMORY_USE, mutableListOf()))
-            .isEqualTo(StatsManager.PULL_SKIP)
+        assertLogsWtf {
+            assertThat(logger.onPullAtom(SysUiStatsLog.NOTIFICATION_MEMORY_USE, mutableListOf()))
+                .isEqualTo(StatsManager.PULL_SKIP)
+        }
     }
 
     @Test
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 06a4d08..aa79c23 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
@@ -398,7 +398,7 @@
     }
 
     @Test
-    public void testAboveShelfChangedListenerCalledHeadsUpGoingAway() throws Exception {
+    public void testAboveShelfChangedListenerCalledHeadsUpAnimatingAway() throws Exception {
         ExpandableNotificationRow row = mNotificationTestHelper.createRow();
         AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
         row.setAboveShelfChangedListener(listener);
@@ -772,8 +772,7 @@
         row.setUserExpanded(true);
         row.setOnKeyguard(false);
         row.setSensitive(/* sensitive= */true, /* hideSensitive= */false);
-        row.setHideSensitive(/* hideSensitive= */true, /* animated= */false,
-                /* delay= */0L, /* duration= */0L);
+        row.setHideSensitiveForIntrinsicHeight(/* hideSensitive= */true);
 
         // THEN
         assertThat(row.isExpanded()).isFalse();
@@ -787,8 +786,7 @@
         row.setUserExpanded(true);
         row.setOnKeyguard(false);
         row.setSensitive(/* sensitive= */true, /* hideSensitive= */false);
-        row.setHideSensitive(/* hideSensitive= */false, /* animated= */false,
-                /* delay= */0L, /* duration= */0L);
+        row.setHideSensitiveForIntrinsicHeight(/* hideSensitive= */false);
 
         // THEN
         assertThat(row.isExpanded()).isTrue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
index 9c20e54..ffb8646 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
@@ -45,7 +45,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.UiThreadTest;
 import android.view.LayoutInflater;
@@ -53,6 +52,8 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
index 91e4666..7332bc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
@@ -79,10 +79,11 @@
         initMocks(this)
         fakeParent =
             spy(FrameLayout(mContext, /* attrs= */ null).also { it.visibility = View.GONE })
+        val mockEntry = createMockNotificationEntry()
         row =
             spy(
-                ExpandableNotificationRow(mContext, /* attrs= */ null).apply {
-                    entry = createMockNotificationEntry()
+                ExpandableNotificationRow(mContext, /* attrs= */ null, mockEntry).apply {
+                    entry = mockEntry
                 }
             )
         ViewUtils.attachView(fakeParent)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 3c1f559..97cb11e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -65,7 +65,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.notification.StatusBarNotification;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.LayoutInflater;
@@ -73,11 +72,13 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.notification.ConversationIconFactory;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
+import com.android.systemui.res.R;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.SbnBuilder;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
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 fe0d9d0..9e2856d 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
@@ -23,7 +23,6 @@
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 
-import static com.android.systemui.concurrency.FakeExecutorKosmosKt.getFakeExecutor;
 import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
 
 import static junit.framework.Assert.assertNotNull;
@@ -97,7 +96,6 @@
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.kotlin.JavaAdapter;
-import com.android.systemui.util.time.FakeSystemClock;
 import com.android.systemui.wmshell.BubblesManager;
 
 import org.junit.Before;
@@ -182,7 +180,6 @@
                 mHeadsUpManager,
                 PowerInteractorFactory.create().getPowerInteractor(),
                 mActiveNotificationsInteractor,
-                mKosmos.getFakeSceneContainerFlags(),
                 () -> mKosmos.getSceneInteractor()
         );
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
index 65a960b..1b85dfa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
@@ -45,6 +45,7 @@
 import com.android.internal.statusbar.statusBarService
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager
@@ -55,7 +56,6 @@
 import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.UserContextProvider
 import com.android.systemui.shade.shadeControllerSceneImpl
@@ -93,6 +93,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper
+@EnableSceneContainer
 class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
     private val testNotificationChannel =
         NotificationChannel(
@@ -143,8 +144,6 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        val sceneContainerFlags = kosmos.fakeSceneContainerFlags
-        sceneContainerFlags.enabled = true
         allowTestableLooperAsMainThread()
         helper = NotificationTestHelper(mContext, mDependency)
         Mockito.`when`(accessibilityManager.isTouchExplorationEnabled).thenReturn(false)
@@ -156,9 +155,9 @@
                 headsUpManager,
                 create().powerInteractor,
                 activeNotificationsInteractor,
-                sceneContainerFlags,
-                { sceneInteractor },
-            )
+            ) {
+                sceneInteractor
+            }
         gutsManager =
             NotificationGutsManager(
                 mContext,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index f31b1c4..13ced92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -55,20 +55,20 @@
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.telecom.TelecomManager;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.testing.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -82,8 +82,6 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import java.util.HashSet;
-import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
 @SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java
index 0a15f0d..4a91cd2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java
@@ -16,16 +16,23 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+
 import android.provider.Settings;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableResources;
 import android.testing.UiThreadTest;
 import android.util.KeyValueListParser;
 
-import com.android.systemui.res.R;
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -33,12 +40,6 @@
 
 import java.util.ArrayList;
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.mock;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @UiThreadTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
index ccedd36..51665d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
@@ -41,7 +41,6 @@
 import android.graphics.drawable.Icon;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.text.SpannableString;
@@ -50,10 +49,12 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 
@@ -65,8 +66,6 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import java.util.HashSet;
-import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
 @SmallTest
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 9a7b8ec..745d20d 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
@@ -1,5 +1,6 @@
 package com.android.systemui.statusbar.notification.stack
 
+import android.service.notification.StatusBarNotification
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.LayoutInflater
@@ -14,6 +15,7 @@
 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.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.row.ExpandableView
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
@@ -457,8 +459,13 @@
         expansionFraction: Float,
         expectedAlpha: Float
     ) {
+        val sbnMock: StatusBarNotification = mock()
+        val mockEntry = mock<NotificationEntry>().apply {
+            whenever(this.sbn).thenReturn(sbnMock)
+        }
+        val row = ExpandableNotificationRow(mContext, null, mockEntry)
         whenever(ambientState.lastVisibleBackgroundChild)
-            .thenReturn(ExpandableNotificationRow(mContext, null))
+            .thenReturn(row)
         whenever(ambientState.isExpansionChanging).thenReturn(true)
         whenever(ambientState.expansionFraction).thenReturn(expansionFraction)
         whenever(hostLayoutController.speedBumpIndex).thenReturn(0)
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 cd8be57..a66a136 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
@@ -22,6 +22,8 @@
 import static com.android.systemui.statusbar.StatusBarState.SHADE;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
 
+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;
@@ -36,8 +38,6 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-
 import android.metrics.LogMaker;
 import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
@@ -56,8 +56,6 @@
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
 import com.android.systemui.keyguard.shared.model.KeyguardState;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -78,6 +76,7 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.ColorUpdateLogger;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
@@ -94,7 +93,6 @@
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent;
 import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor;
 import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -127,10 +125,10 @@
 public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
 
     protected KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
-    private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
     @Mock private NotificationGutsManager mNotificationGutsManager;
     @Mock private NotificationsController mNotificationsController;
     @Mock private NotificationVisibilityProvider mVisibilityProvider;
+    @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
     @Mock private HeadsUpManager mHeadsUpManager;
     @Mock private NotificationRoundnessManager mNotificationRoundnessManager;
     @Mock private TunerService mTunerService;
@@ -161,7 +159,6 @@
     @Mock private VisibilityLocationProviderDelegator mVisibilityLocationProviderDelegator;
     @Mock private ShadeController mShadeController;
     @Mock private Provider<WindowRootView> mWindowRootView;
-    @Mock private NotificationStackAppearanceInteractor mNotificationStackAppearanceInteractor;
     private final StackStateLogger mStackLogger = new StackStateLogger(logcatLogBuffer(),
             logcatLogBuffer());
     private final NotificationStackScrollLogger mLogger = new NotificationStackScrollLogger(
@@ -195,8 +192,6 @@
         allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
 
-        mFeatureFlags.set(Flags.USE_REPOS_FOR_BOUNCER_SHOWING, true);
-
         when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper);
         when(mKeyguardTransitionRepo.getTransitions()).thenReturn(emptyFlow());
     }
@@ -301,36 +296,11 @@
 
     @Test
     @DisableFlags(FooterViewRefactor.FLAG_NAME)
-    public void testUpdateEmptyShadeView_bouncerShowing_flagOff_hideEmptyView() {
+    public void testUpdateEmptyShadeView_bouncerShowing_hideEmptyView() {
         when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
         initController(/* viewIsAttached= */ true);
 
-        // WHEN the flag is off and *only* CentralSurfaces has bouncer as showing
-        mFeatureFlags.set(Flags.USE_REPOS_FOR_BOUNCER_SHOWING, false);
-        mController.setBouncerShowingFromCentralSurfaces(true);
-        when(mPrimaryBouncerInteractor.isBouncerShowing()).thenReturn(false);
-
-        setupShowEmptyShadeViewState(true);
-        reset(mNotificationStackScrollLayout);
-        mController.updateShowEmptyShadeView();
-
-        // THEN the CentralSurfaces value is used. Since the bouncer is showing, we hide the empty
-        // view.
-        verify(mNotificationStackScrollLayout).updateEmptyShadeView(
-                /* visible= */ false,
-                /* areNotificationsHiddenInShade= */ false);
-    }
-
-    @Test
-    @DisableFlags(FooterViewRefactor.FLAG_NAME)
-    public void testUpdateEmptyShadeView_bouncerShowing_flagOn_hideEmptyView() {
-        when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
-        initController(/* viewIsAttached= */ true);
-
-        // WHEN the flag is on and *only* PrimaryBouncerInteractor has bouncer as showing
-        mFeatureFlags.set(Flags.USE_REPOS_FOR_BOUNCER_SHOWING, true);
         when(mPrimaryBouncerInteractor.isBouncerShowing()).thenReturn(true);
-        mController.setBouncerShowingFromCentralSurfaces(false);
 
         setupShowEmptyShadeViewState(true);
         reset(mNotificationStackScrollLayout);
@@ -345,36 +315,11 @@
 
     @Test
     @DisableFlags(FooterViewRefactor.FLAG_NAME)
-    public void testUpdateEmptyShadeView_bouncerNotShowing_flagOff_showEmptyView() {
+    public void testUpdateEmptyShadeView_bouncerNotShowing_showEmptyView() {
         when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
         initController(/* viewIsAttached= */ true);
 
-        // WHEN the flag is off and *only* CentralSurfaces has bouncer as not showing
-        mFeatureFlags.set(Flags.USE_REPOS_FOR_BOUNCER_SHOWING, false);
-        mController.setBouncerShowingFromCentralSurfaces(false);
-        when(mPrimaryBouncerInteractor.isBouncerShowing()).thenReturn(true);
-
-        setupShowEmptyShadeViewState(true);
-        reset(mNotificationStackScrollLayout);
-        mController.updateShowEmptyShadeView();
-
-        // THEN the CentralSurfaces value is used. Since the bouncer isn't showing, we can show the
-        // empty view.
-        verify(mNotificationStackScrollLayout).updateEmptyShadeView(
-                /* visible= */ true,
-                /* areNotificationsHiddenInShade= */ false);
-    }
-
-    @Test
-    @DisableFlags(FooterViewRefactor.FLAG_NAME)
-    public void testUpdateEmptyShadeView_bouncerNotShowing_flagOn_showEmptyView() {
-        when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
-        initController(/* viewIsAttached= */ true);
-
-        // WHEN the flag is on and *only* PrimaryBouncerInteractor has bouncer as not showing
-        mFeatureFlags.set(Flags.USE_REPOS_FOR_BOUNCER_SHOWING, true);
         when(mPrimaryBouncerInteractor.isBouncerShowing()).thenReturn(false);
-        mController.setBouncerShowingFromCentralSurfaces(true);
 
         setupShowEmptyShadeViewState(true);
         reset(mNotificationStackScrollLayout);
@@ -984,6 +929,7 @@
                 mNotificationGutsManager,
                 mNotificationsController,
                 mVisibilityProvider,
+                mNotificationWakeUpCoordinator,
                 mHeadsUpManager,
                 mNotificationRoundnessManager,
                 mTunerService,
@@ -1016,12 +962,10 @@
                 mViewBinder,
                 mShadeController,
                 mWindowRootView,
-                mNotificationStackAppearanceInteractor,
                 mKosmos.getInteractionJankMonitor(),
                 mStackLogger,
                 mLogger,
                 mNotificationStackSizeCalculator,
-                mFeatureFlags,
                 mNotificationTargetsHelper,
                 mSecureSettings,
                 mock(NotificationDismissibilityProvider.class),
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 abb9432..89ae9f4 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
@@ -20,7 +20,6 @@
 import static android.view.WindowInsets.Type.ime;
 
 import static com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION;
-import static com.android.systemui.Flags.FLAG_SCENE_CONTAINER;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.RUBBER_BAND_FACTOR_NORMAL;
@@ -72,6 +71,7 @@
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.DisableSceneContainer;
 import com.android.systemui.flags.EnableSceneContainer;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.FeatureFlags;
@@ -90,6 +90,7 @@
 import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -106,6 +107,7 @@
 import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 /**
  * Tests for {@link NotificationStackScrollLayout}.
@@ -227,7 +229,7 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test
+    @DisableSceneContainer // TODO(b/312473478): address disabled test
     public void testUpdateStackHeight_qsExpansionZero() {
         final float expansionFraction = 0.2f;
         final float overExpansion = 50f;
@@ -726,7 +728,7 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address lack of QS Header
+    @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
     public void testInsideQSHeader_noOffset() {
         ViewGroup qsHeader = mock(ViewGroup.class);
         Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -743,7 +745,7 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address lack of QS Header
+    @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
     public void testInsideQSHeader_Offset() {
         ViewGroup qsHeader = mock(ViewGroup.class);
         Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -763,14 +765,14 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test
+    @DisableSceneContainer // TODO(b/312473478): address disabled test
     public void setFractionToShade_recomputesStackHeight() {
         mStackScroller.setFractionToShade(1f);
         verify(mNotificationStackSizeCalculator).computeHeight(any(), anyInt(), anyFloat());
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test
+    @DisableSceneContainer // TODO(b/312473478): address disabled test
     public void testSetOwnScrollY_shadeNotClosing_scrollYChanges() {
         // Given: shade is not closing, scrollY is 0
         mAmbientState.setScrollY(0);
@@ -869,7 +871,7 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test
+    @DisableSceneContainer // TODO(b/312473478): address disabled test
     public void testSplitShade_hasTopOverscroll() {
         mTestableResources
                 .addOverride(R.bool.config_use_split_notification_shade, /* value= */ true);
@@ -942,7 +944,7 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER) // TODO(b/312473478): address disabled test
+    @DisableSceneContainer // TODO(b/312473478): address disabled test
     public void testSetMaxDisplayedNotifications_notifiesListeners() {
         ExpandableView.OnHeightChangedListener listener =
                 mock(ExpandableView.OnHeightChangedListener.class);
@@ -957,7 +959,7 @@
     }
 
     @Test
-    @DisableFlags(FLAG_SCENE_CONTAINER)
+    @DisableSceneContainer
     public void testDispatchTouchEvent_sceneContainerDisabled() {
         MotionEvent event = MotionEvent.obtain(
                 SystemClock.uptimeMillis(),
@@ -1044,6 +1046,96 @@
         assertFalse(mStackScroller.getIsBeingDragged());
     }
 
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    public void testGenerateHeadsUpDisappearEvent_setsHeadsUpAnimatingAway() {
+        // GIVEN NSSL is ready for HUN animations
+        Consumer<Boolean> headsUpAnimatingAwayListener = mock(BooleanConsumer.class);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        prepareStackScrollerForHunAnimations(headsUpAnimatingAwayListener);
+
+        // WHEN we generate a disappear event
+        mStackScroller.generateHeadsUpAnimation(row, /* isHeadsUp = */ false);
+
+        // THEN headsUpAnimatingAway is true
+        verify(headsUpAnimatingAwayListener).accept(true);
+        assertTrue(mStackScroller.mHeadsUpAnimatingAway);
+    }
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    public void testGenerateHeadsUpDisappearEvent_stackExpanded_headsUpAnimatingAwayNotSet() {
+        // GIVEN NSSL would be ready for HUN animations, BUT it is expanded
+        Consumer<Boolean> headsUpAnimatingAwayListener = mock(BooleanConsumer.class);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        assertTrue("Should be expanded by default.", mStackScroller.isExpanded());
+        mStackScroller.setHeadsUpAnimatingAwayListener(headsUpAnimatingAwayListener);
+        mStackScroller.setAnimationsEnabled(true);
+        mStackScroller.setHeadsUpGoingAwayAnimationsAllowed(true);
+
+        // WHEN we generate a disappear event
+        mStackScroller.generateHeadsUpAnimation(row, /* isHeadsUp = */ false);
+
+        // THEN nothing happens
+        verify(headsUpAnimatingAwayListener, never()).accept(anyBoolean());
+        assertFalse(mStackScroller.mHeadsUpAnimatingAway);
+    }
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    public void testGenerateHeadsUpDisappearEvent_pendingAppearEvent_headsUpAnimatingAwayNotSet() {
+        // GIVEN NSSL is ready for HUN animations
+        Consumer<Boolean> headsUpAnimatingAwayListener = mock(BooleanConsumer.class);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        prepareStackScrollerForHunAnimations(headsUpAnimatingAwayListener);
+        // BUT there is a pending appear event
+        mStackScroller.generateHeadsUpAnimation(row, /* isHeadsUp = */ true);
+
+        // WHEN we generate a disappear event
+        mStackScroller.generateHeadsUpAnimation(row, /* isHeadsUp = */ false);
+
+        // THEN nothing happens
+        verify(headsUpAnimatingAwayListener, never()).accept(anyBoolean());
+        assertFalse(mStackScroller.mHeadsUpAnimatingAway);
+    }
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    public void testGenerateHeadsUpAppearEvent_headsUpAnimatingAwayNotSet() {
+        // GIVEN NSSL is ready for HUN animations
+        Consumer<Boolean> headsUpAnimatingAwayListener = mock(BooleanConsumer.class);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        prepareStackScrollerForHunAnimations(headsUpAnimatingAwayListener);
+
+        // WHEN we generate a disappear event
+        mStackScroller.generateHeadsUpAnimation(row, /* isHeadsUp = */ true);
+
+        // THEN headsUpAnimatingWay is not set
+        verify(headsUpAnimatingAwayListener, never()).accept(anyBoolean());
+        assertFalse(mStackScroller.mHeadsUpAnimatingAway);
+    }
+
+    @Test
+    @EnableFlags(NotificationsHeadsUpRefactor.FLAG_NAME)
+    public void testOnChildAnimationsFinished_resetsheadsUpAnimatingAway() {
+        // GIVEN NSSL is ready for HUN animations
+        Consumer<Boolean> headsUpAnimatingAwayListener = mock(BooleanConsumer.class);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        prepareStackScrollerForHunAnimations(headsUpAnimatingAwayListener);
+
+        // AND there is a HUN animating away
+        mStackScroller.generateHeadsUpAnimation(row, /* isHeadsUp = */ false);
+        assertTrue("a HUN should be animating away", mStackScroller.mHeadsUpAnimatingAway);
+
+        // WHEN the child animations are finished
+        mStackScroller.onChildAnimationFinished();
+
+        // THEN headsUpAnimatingAway is false
+        verify(headsUpAnimatingAwayListener).accept(false);
+        assertFalse(mStackScroller.mHeadsUpAnimatingAway);
+    }
+
     private MotionEvent captureTouchSentToSceneFramework() {
         ArgumentCaptor<MotionEvent> captor = ArgumentCaptor.forClass(MotionEvent.class);
         verify(mStackScrollLayoutController).sendTouchToSceneFramework(captor.capture());
@@ -1056,6 +1148,14 @@
         mStackScroller.setStatusBarState(state);
     }
 
+    private void prepareStackScrollerForHunAnimations(
+            Consumer<Boolean> headsUpAnimatingAwayListener) {
+        mStackScroller.setHeadsUpAnimatingAwayListener(headsUpAnimatingAwayListener);
+        mStackScroller.setIsExpanded(false);
+        mStackScroller.setAnimationsEnabled(true);
+        mStackScroller.setHeadsUpGoingAwayAnimationsAllowed(true);
+    }
+
     private ExpandableNotificationRow createClearableRow() {
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
         NotificationEntry entry = mock(NotificationEntry.class);
@@ -1116,4 +1216,6 @@
             assertThat(mActual.getY()).isEqualTo(expected.getY());
         }
     }
+
+    private abstract static class BooleanConsumer implements Consumer<Boolean> { }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt
index 4bfd7e3..e2ac203 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractorTest.kt
@@ -31,9 +31,9 @@
 import com.android.systemui.power.shared.model.ScreenPowerState.SCREEN_ON
 import com.android.systemui.power.shared.model.WakefulnessState.STARTING_TO_SLEEP
 import com.android.systemui.statusbar.policy.FakeConfigurationController
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl
-import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractorImpl
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
 import com.android.systemui.util.animation.data.repository.FakeAnimationStatusRepository
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -59,7 +59,7 @@
 
     private val animationStatus = FakeAnimationStatusRepository()
     private val configurationController = FakeConfigurationController()
-    private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider()
+    private val unfoldTransitionProgressProvider = FakeUnfoldTransitionProvider()
     private val powerRepository = FakePowerRepository()
     private val powerInteractor =
         PowerInteractor(
@@ -69,11 +69,6 @@
             statusBarStateController = mock()
         )
 
-    private val unfoldTransitionRepository =
-        UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider))
-    private val unfoldTransitionInteractor =
-        UnfoldTransitionInteractorImpl(unfoldTransitionRepository)
-
     private val configurationRepository =
         ConfigurationRepositoryImpl(
             configurationController,
@@ -83,6 +78,11 @@
         )
     private val configurationInteractor = ConfigurationInteractor(configurationRepository)
 
+    private val unfoldTransitionRepository =
+        UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider))
+    private val unfoldTransitionInteractor =
+        UnfoldTransitionInteractor(unfoldTransitionRepository, configurationInteractor)
+
     private lateinit var configuration: Configuration
     private lateinit var underTest: HideNotificationsInteractor
 
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 50f81ff..f49dc98 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
@@ -37,12 +37,13 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.testing.TestableResources;
 import android.view.ViewRootImpl;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -131,6 +132,8 @@
     private SelectedUserInteractor mSelectedUserInteractor;
     @Mock
     private BiometricUnlockInteractor mBiometricUnlockInteractor;
+    @Mock
+    private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private final FakeSystemClock mSystemClock = new FakeSystemClock();
     private BiometricUnlockController mBiometricUnlockController;
 
@@ -167,7 +170,7 @@
                 () -> mSelectedUserInteractor,
                 mBiometricUnlockInteractor,
                 mock(JavaAdapter.class),
-                mock(KeyguardTransitionInteractor.class)
+                mKeyguardTransitionInteractor
         );
         biometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
         biometricUnlockController.addListener(mBiometricUnlockEventsListener);
@@ -374,6 +377,24 @@
     }
 
     @Test
+    public void onBiometricAuthenticated_whenFaceOnAlternateBouncer_dismissBouncer() {
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+        when(mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()).thenReturn(false);
+        when(mKeyguardTransitionInteractor.getCurrentState())
+                .thenReturn(KeyguardState.ALTERNATE_BOUNCER);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
+        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
+
+        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER);
+        assertThat(mBiometricUnlockController.getBiometricType())
+                .isEqualTo(BiometricSourceType.FACE);
+    }
+
+    @Test
     public void onBiometricAuthenticated_whenBypassOnBouncer_dismissBouncer() {
         reset(mKeyguardBypassController);
         when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).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 ed29665..041e61c 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
@@ -25,10 +25,13 @@
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.statusbar.StatusBarState.SHADE;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
@@ -99,6 +102,8 @@
 import com.android.systemui.communal.shared.model.CommunalScenes;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.DisableSceneContainer;
+import com.android.systemui.flags.EnableSceneContainer;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.FragmentService;
@@ -118,10 +123,10 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor;
 import com.android.systemui.res.R;
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor;
 import com.android.systemui.shade.CameraLauncher;
 import com.android.systemui.shade.NotificationPanelView;
 import com.android.systemui.shade.NotificationPanelViewController;
@@ -179,7 +184,9 @@
 import com.android.systemui.util.concurrency.MessageRouterImpl;
 import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.systemui.util.settings.FakeGlobalSettings;
+import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.settings.SystemSettings;
 import com.android.systemui.util.time.FakeSystemClock;
 import com.android.systemui.util.time.SystemClock;
 import com.android.systemui.volume.VolumeComponent;
@@ -323,6 +330,7 @@
     private ShadeController mShadeController;
     private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
     private final FakeGlobalSettings mFakeGlobalSettings = new FakeGlobalSettings();
+    private final SystemSettings mSystemSettings = new FakeSettings();
     private final FakeEventLog mFakeEventLog = new FakeEventLog();
     private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
     private final FakeExecutor mUiBgExecutor = new FakeExecutor(mFakeSystemClock);
@@ -331,7 +339,8 @@
     private final DumpManager mDumpManager = new DumpManager();
     private final ScreenLifecycle mScreenLifecycle = new ScreenLifecycle(mDumpManager);
 
-    private final SceneContainerFlags mSceneContainerFlags = new FakeSceneContainerFlags();
+    private final BrightnessMirrorShowingInteractor mBrightnessMirrorShowingInteractor =
+            mKosmos.getBrightnessMirrorShowingInteractor();
 
     @Before
     public void setup() throws Exception {
@@ -343,7 +352,9 @@
         // Turn AOD on and toggle feature flag for jank fixes
         mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
         when(mDozeParameters.getAlwaysOn()).thenReturn(true);
-        mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+        if (!SceneContainerFlag.isEnabled()) {
+            mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+        }
 
         IThermalService thermalService = mock(IThermalService.class);
         mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
@@ -370,7 +381,8 @@
                         mFakeSystemClock,
                         mock(UiEventLogger.class),
                         mUserTracker,
-                        mAvalancheProvider);
+                        mAvalancheProvider,
+                        mSystemSettings);
         mVisualInterruptionDecisionProvider.start();
 
         mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
@@ -417,22 +429,25 @@
             ((Runnable) invocation.getArgument(0)).run();
             return null;
         }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
-
-        mShadeController = spy(new ShadeControllerImpl(
-                mCommandQueue,
-                mMainExecutor,
-                mock(WindowRootViewVisibilityInteractor.class),
-                mKeyguardStateController,
-                mStatusBarStateController,
-                mStatusBarKeyguardViewManager,
-                mStatusBarWindowController,
-                mDeviceProvisionedController,
-                mNotificationShadeWindowController,
-                0,
-                () -> mNotificationPanelViewController,
-                () -> mAssistManager,
-                () -> mNotificationGutsManager
-        ));
+        if (SceneContainerFlag.isEnabled()) {
+            mShadeController = spy(mKosmos.getShadeController());
+        } else {
+            mShadeController = spy(new ShadeControllerImpl(
+                    mCommandQueue,
+                    mMainExecutor,
+                    mock(WindowRootViewVisibilityInteractor.class),
+                    mKeyguardStateController,
+                    mStatusBarStateController,
+                    mStatusBarKeyguardViewManager,
+                    mStatusBarWindowController,
+                    mDeviceProvisionedController,
+                    mNotificationShadeWindowController,
+                    0,
+                    () -> mNotificationPanelViewController,
+                    () -> mAssistManager,
+                    () -> mNotificationGutsManager
+            ));
+        }
         mShadeController.setNotificationShadeWindowViewController(
                 mNotificationShadeWindowViewController);
         mShadeController.setNotificationPresenter(mNotificationPresenter);
@@ -553,7 +568,7 @@
                 mUserTracker,
                 () -> mFingerprintManager,
                 mActivityStarter,
-                mSceneContainerFlags
+                mBrightnessMirrorShowingInteractor
         );
         mScreenLifecycle.addObserver(mCentralSurfaces.mScreenObserver);
         mCentralSurfaces.initShadeVisibilityListener();
@@ -562,8 +577,7 @@
                 any(NotificationPanelViewController.class),
                 any(ShadeExpansionStateManager.class),
                 any(BiometricUnlockController.class),
-                any(ViewGroup.class),
-                any(KeyguardBypassController.class)))
+                any(ViewGroup.class)))
                 .thenReturn(mStatusBarKeyguardViewManager);
 
         when(mKeyguardViewMediator.getViewMediatorCallback()).thenReturn(
@@ -1084,6 +1098,34 @@
         verify(mStatusBarWindowController).refreshStatusBarHeight();
     }
 
+    @Test
+    @EnableSceneContainer
+    public void brightnesShowingChanged_flagEnabled_ScrimControllerNotified() {
+        mCentralSurfaces.registerCallbacks();
+
+        mBrightnessMirrorShowingInteractor.setMirrorShowing(true);
+        mTestScope.getTestScheduler().runCurrent();
+        verify(mScrimController, atLeastOnce()).transitionTo(ScrimState.BRIGHTNESS_MIRROR);
+
+        mBrightnessMirrorShowingInteractor.setMirrorShowing(false);
+        mTestScope.getTestScheduler().runCurrent();
+        ArgumentCaptor<ScrimState> captor = ArgumentCaptor.forClass(ScrimState.class);
+        // The default is to call the one with the callback argument
+        verify(mScrimController, atLeastOnce()).transitionTo(captor.capture(), any());
+        assertThat(captor.getValue()).isNotEqualTo(ScrimState.BRIGHTNESS_MIRROR);
+    }
+
+    @Test
+    @DisableSceneContainer
+    public void brightnesShowingChanged_flagDisabled_ScrimControllerNotified() {
+        mCentralSurfaces.registerCallbacks();
+
+        mBrightnessMirrorShowingInteractor.setMirrorShowing(true);
+        mTestScope.getTestScheduler().runCurrent();
+        verify(mScrimController, never()).transitionTo(ScrimState.BRIGHTNESS_MIRROR);
+        verify(mScrimController, never()).transitionTo(eq(ScrimState.BRIGHTNESS_MIRROR), any());
+    }
+
     /**
      * 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 6fecbb0..7cb41f1 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
@@ -34,8 +34,8 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.provider.Settings;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index c1ef1ad..3e9006e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.platform.test.annotations.DisableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -46,6 +47,7 @@
 import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationIconInteractor;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.policy.Clock;
@@ -157,6 +159,7 @@
     }
 
     @Test
+    @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
     public void testHeaderUpdated() {
         mRow.setPinned(true);
         when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
index 7362e34..4dd97bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
@@ -17,13 +17,15 @@
 package com.android.systemui.statusbar.phone
 
 import android.content.pm.PackageManager
-import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
@@ -72,6 +74,7 @@
     @Mock private lateinit var statusBarStateController: StatusBarStateController
     @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager
     @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
     @Mock private lateinit var devicePostureController: DevicePostureController
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var packageManager: PackageManager
@@ -138,7 +141,8 @@
     private fun initKeyguardBypassController() {
         keyguardBypassController =
             KeyguardBypassController(
-                context,
+                context.resources,
+                context.packageManager,
                 testScope.backgroundScope,
                 tunerService,
                 statusBarStateController,
@@ -146,7 +150,8 @@
                 keyguardStateController,
                 shadeRepository,
                 devicePostureController,
-                dumpManager
+                keyguardTransitionInteractor,
+                dumpManager,
             )
     }
 
@@ -302,4 +307,26 @@
             job.cancel()
         }
     }
+
+    @Test
+    fun canBypass_bypassDisabled() {
+        context.orCreateTestableResources.addOverride(
+            R.integer.config_face_unlock_bypass_override,
+            2 /* FACE_UNLOCK_BYPASS_NEVER */
+        )
+        initKeyguardBypassController()
+        assertThat(keyguardBypassController.canBypass()).isFalse()
+    }
+
+    @Test
+    fun canBypass_bypassEnabled_alternateBouncerShowing() {
+        context.orCreateTestableResources.addOverride(
+            R.integer.config_face_unlock_bypass_override,
+            1 /* FACE_UNLOCK_BYPASS_ALWAYS */
+        )
+        initKeyguardBypassController()
+        whenever(keyguardTransitionInteractor.getCurrentState())
+            .thenReturn(KeyguardState.ALTERNATE_BOUNCER)
+        assertThat(keyguardBypassController.canBypass()).isTrue()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index 05fd63e..a6a4f24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -20,9 +20,9 @@
 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
 import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
 
+import static com.android.systemui.Flags.FLAG_UPDATE_USER_SWITCHER_BACKGROUND;
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.statusbar.StatusBarState.SHADE;
-import static com.android.systemui.Flags.FLAG_UPDATE_USER_SWITCHER_BACKGROUND;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -172,7 +172,6 @@
                 mKeyguardRepository,
                 mCommandQueue,
                 PowerInteractorFactory.create().getPowerInteractor(),
-                mKosmos.getFakeSceneContainerFlags(),
                 new FakeKeyguardBouncerRepository(),
                 new ConfigurationInteractor(new FakeConfigurationRepository()),
                 new FakeShadeRepository(),
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 1463680..d365663 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
@@ -33,7 +33,6 @@
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.res.R
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
 import com.android.systemui.scene.ui.view.WindowRootView
 import com.android.systemui.shade.ShadeControllerImpl
 import com.android.systemui.shade.ShadeLogger
@@ -51,6 +50,8 @@
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.view.ViewUtil
 import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import javax.inject.Provider
 import org.junit.Before
 import org.junit.Test
 import org.mockito.ArgumentCaptor
@@ -61,8 +62,6 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
-import java.util.Optional
-import javax.inject.Provider
 
 @SmallTest
 class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@@ -296,7 +295,6 @@
             Optional.of(sysuiUnfoldComponent),
             Optional.of(progressProvider),
             featureFlags,
-            FakeSceneContainerFlags(),
             userChipViewModel,
             centralSurfacesImpl,
             statusBarWindowStateController,
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 34605fe..f04a5ab 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
@@ -76,8 +76,6 @@
 import com.android.systemui.bouncer.ui.BouncerViewDelegate;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dreams.DreamOverlayStateController;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -145,7 +143,6 @@
     @Mock private SysUIUnfoldComponent mSysUiUnfoldComponent;
     @Mock private DreamOverlayStateController mDreamOverlayStateController;
     @Mock private LatencyTracker mLatencyTracker;
-    private FakeFeatureFlags mFeatureFlags;
     @Mock private KeyguardSecurityModel mKeyguardSecurityModel;
     @Mock private PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
     @Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@@ -188,11 +185,10 @@
                 .thenReturn(mKeyguardMessageAreaController);
         when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
         when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
-        mFeatureFlags = new FakeFeatureFlags();
-        mFeatureFlags.set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false);
         mSetFlagsRule.disableFlags(
                 com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR,
-                com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
+                com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR,
+                com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
         );
 
         when(mNotificationShadeWindowController.getWindowRootView())
@@ -218,7 +214,6 @@
                         () -> mShadeController,
                         mLatencyTracker,
                         mKeyguardSecurityModel,
-                        mFeatureFlags,
                         mPrimaryBouncerCallbackInteractor,
                         mPrimaryBouncerInteractor,
                         mBouncerView,
@@ -246,8 +241,7 @@
                 mShadeLockscreenInteractor,
                 new ShadeExpansionStateManager(),
                 mBiometricUnlockController,
-                mNotificationContainer,
-                mBypassController);
+                mNotificationContainer);
         mStatusBarKeyguardViewManager.show(null);
         ArgumentCaptor<PrimaryBouncerExpansionCallback> callbackArgumentCaptor =
                 ArgumentCaptor.forClass(PrimaryBouncerExpansionCallback.class);
@@ -728,7 +722,6 @@
                         () -> mShadeController,
                         mLatencyTracker,
                         mKeyguardSecurityModel,
-                        mFeatureFlags,
                         mPrimaryBouncerCallbackInteractor,
                         mPrimaryBouncerInteractor,
                         mBouncerView,
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 feff046..1ec1765 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,7 +8,7 @@
 import android.view.WindowManager
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.unfold.util.CurrentActivityTypeProvider
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
 import com.android.systemui.util.mockito.whenever
@@ -23,17 +23,14 @@
 @TestableLooper.RunWithLooper
 class StatusBarMoveFromCenterAnimationControllerTest : SysuiTestCase() {
 
-    @Mock
-    private lateinit var windowManager: WindowManager
+    @Mock private lateinit var windowManager: WindowManager
 
-    @Mock
-    private lateinit var display: Display
+    @Mock private lateinit var display: Display
 
-    @Mock
-    private lateinit var currentActivityTypeProvider: CurrentActivityTypeProvider
+    @Mock private lateinit var currentActivityTypeProvider: CurrentActivityTypeProvider
 
     private val view: View = View(context)
-    private val progressProvider = TestUnfoldTransitionProvider()
+    private val progressProvider = FakeUnfoldTransitionProvider()
     private val scopedProvider = ScopedUnfoldTransitionProgressProvider(progressProvider)
 
     private lateinit var controller: StatusBarMoveFromCenterAnimationController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
index 1e628bd..dedd0af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
@@ -13,68 +13,103 @@
  */
 package com.android.systemui.statusbar.phone
 
+import android.app.Dialog
 import android.content.res.Configuration
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
+import android.view.WindowManager
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
 import kotlin.test.Test
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.runner.RunWith
 import org.mockito.Mockito.verify
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper(setAsMainLooper = true)
 class SystemUIBottomSheetDialogTest : SysuiTestCase() {
 
+    private val kosmos = testKosmos()
     private val configurationController = mock<ConfigurationController>()
     private val config = mock<Configuration>()
+    private val delegate = mock<DialogDelegate<Dialog>>()
 
     private lateinit var dialog: SystemUIBottomSheetDialog
 
     @Before
     fun setup() {
-        dialog = SystemUIBottomSheetDialog(mContext, configurationController)
+        dialog =
+            with(kosmos) {
+                SystemUIBottomSheetDialog(
+                    context,
+                    testScope.backgroundScope,
+                    configurationController,
+                    delegate,
+                    TestLayout(),
+                    0,
+                )
+            }
     }
 
     @Test
     fun onStart_registersConfigCallback() {
-        dialog.show()
+        kosmos.testScope.runTest {
+            dialog.show()
+            runCurrent()
 
-        verify(configurationController).addCallback(any())
+            verify(configurationController).addCallback(any())
+        }
     }
 
     @Test
     fun onStop_unregisterConfigCallback() {
-        dialog.show()
-        dialog.dismiss()
+        kosmos.testScope.runTest {
+            dialog.show()
+            runCurrent()
+            dialog.dismiss()
+            runCurrent()
 
-        verify(configurationController).removeCallback(any())
+            verify(configurationController).removeCallback(any())
+        }
     }
 
     @Test
-    fun onConfigurationChanged_calledInSubclass() {
-        var onConfigChangedCalled = false
-        val subclass =
-            object : SystemUIBottomSheetDialog(mContext, configurationController) {
-                override fun onConfigurationChanged() {
-                    onConfigChangedCalled = true
-                }
-            }
+    fun onConfigurationChanged_calledInDelegate() {
+        kosmos.testScope.runTest {
+            dialog.show()
+            runCurrent()
+            val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
+            verify(configurationController).addCallback(capture(captor))
 
-        subclass.show()
+            captor.value.onConfigChanged(config)
+            runCurrent()
 
-        val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
-        verify(configurationController).addCallback(capture(captor))
-        captor.value.onConfigChanged(config)
+            verify(delegate).onConfigurationChanged(any(), any())
+        }
+    }
 
-        assertThat(onConfigChangedCalled).isTrue()
+    private class TestLayout : SystemUIBottomSheetDialog.WindowLayout {
+        override fun calculate(): Flow<SystemUIBottomSheetDialog.WindowLayout.Layout> {
+            return flowOf(
+                SystemUIBottomSheetDialog.WindowLayout.Layout(
+                    WindowManager.LayoutParams.MATCH_PARENT,
+                    WindowManager.LayoutParams.MATCH_PARENT,
+                )
+            )
+        }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index 7b73528c..efd7f99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -22,6 +22,7 @@
 import android.app.Notification
 import android.app.PendingIntent
 import android.app.Person
+import android.platform.test.annotations.DisableFlags
 import android.service.notification.NotificationListenerService.REASON_USER_STOPPED
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
@@ -193,6 +194,7 @@
 
     /** Regression test for b/192379214. */
     @Test
+    @DisableFlags(android.app.Flags.FLAG_UPDATE_RANKING_TIME)
     fun onEntryUpdated_notificationWhenIsZero_timeHidden() {
         val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
         notification.modifyNotification(context).setWhen(0)
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 9b6940e..598b12c 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
@@ -137,6 +137,7 @@
                 wifiRepository,
                 mock(),
                 mock(),
+                mock(),
             )
 
         demoRepo =
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 c13e830..3c13906 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
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
 import android.net.ConnectivityManager
+import android.os.PersistableBundle
 import android.telephony.ServiceState
 import android.telephony.SignalStrength
 import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
@@ -99,6 +100,9 @@
             )
         )
 
+    // Use a real config, with no overrides
+    private val systemUiCarrierConfig = SystemUiCarrierConfig(SUB_ID, PersistableBundle())
+
     private lateinit var mobileRepo: FakeMobileConnectionRepository
     private lateinit var carrierMergedRepo: FakeMobileConnectionRepository
 
@@ -680,10 +684,6 @@
         telephonyManager: TelephonyManager,
     ): MobileConnectionRepositoryImpl {
         whenever(telephonyManager.subscriptionId).thenReturn(SUB_ID)
-        val systemUiCarrierConfigMock: SystemUiCarrierConfig = mock()
-        whenever(systemUiCarrierConfigMock.satelliteConnectionHysteresisSeconds)
-            .thenReturn(MutableStateFlow(0))
-
         val realRepo =
             MobileConnectionRepositoryImpl(
                 SUB_ID,
@@ -693,7 +693,7 @@
                 SEP,
                 connectivityManager,
                 telephonyManager,
-                systemUiCarrierConfig = systemUiCarrierConfigMock,
+                systemUiCarrierConfig = systemUiCarrierConfig,
                 fakeBroadcastDispatcher,
                 mobileMappingsProxy = mock(),
                 testDispatcher,
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 f761bcf..9d14116 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
@@ -1030,6 +1030,26 @@
         }
 
     @Test
+    fun inflateSignalStrength_usesCarrierConfig() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.inflateSignalStrength)
+
+            assertThat(latest).isEqualTo(false)
+
+            systemUiCarrierConfig.processNewCarrierConfig(
+                configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true)
+            )
+
+            assertThat(latest).isEqualTo(true)
+
+            systemUiCarrierConfig.processNewCarrierConfig(
+                configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
+            )
+
+            assertThat(latest).isEqualTo(false)
+        }
+
+    @Test
     fun isAllowedDuringAirplaneMode_alwaysFalse() =
         testScope.runTest {
             val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode)
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 07abd27..b5525b1 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
@@ -26,6 +26,7 @@
 import android.net.NetworkCapabilities.TRANSPORT_WIFI
 import android.net.vcn.VcnTransportInfo
 import android.net.wifi.WifiInfo
+import android.net.wifi.WifiManager
 import android.os.ParcelUuid
 import android.telephony.CarrierConfigManager
 import android.telephony.SubscriptionInfo
@@ -46,8 +47,10 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
+import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -64,10 +67,14 @@
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
+import com.android.wifitrackerlib.MergedCarrierEntry
+import com.android.wifitrackerlib.WifiEntry
+import com.android.wifitrackerlib.WifiPickerTracker
 import com.google.common.truth.Truth.assertThat
 import java.util.UUID
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -80,6 +87,7 @@
 import kotlinx.coroutines.test.runTest
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.anyString
@@ -96,7 +104,11 @@
 class MobileConnectionsRepositoryTest : SysuiTestCase() {
 
     private val flags =
-        FakeFeatureFlagsClassic().also { it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
+        FakeFeatureFlagsClassic().also {
+            it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true)
+            it.set(Flags.INSTANT_TETHER, true)
+            it.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+        }
 
     private lateinit var connectionFactory: MobileConnectionRepositoryImpl.Factory
     private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory
@@ -113,9 +125,17 @@
     @Mock private lateinit var summaryLogger: TableLogBuffer
     @Mock private lateinit var logBufferFactory: TableLogBufferFactory
     @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var wifiManager: WifiManager
+    @Mock private lateinit var wifiPickerTrackerFactory: WifiPickerTrackerFactory
+    @Mock private lateinit var wifiPickerTracker: WifiPickerTracker
+    @Mock private lateinit var wifiTableLogBuffer: TableLogBuffer
 
     private val mobileMappings = FakeMobileMappingsProxy()
     private val subscriptionManagerProxy = FakeSubscriptionManagerProxy()
+    private val mainExecutor = FakeExecutor(FakeSystemClock())
+    private val wifiLogBuffer = LogBuffer("wifi", maxSize = 100, logcatEchoTracker = mock())
+    private val wifiPickerTrackerCallback =
+        argumentCaptor<WifiPickerTracker.WifiPickerTrackerCallback>()
 
     private val dispatcher = StandardTestDispatcher()
     private val testScope = TestScope(dispatcher)
@@ -138,6 +158,9 @@
             mock<TableLogBuffer>()
         }
 
+        whenever(wifiPickerTrackerFactory.create(any(), capture(wifiPickerTrackerCallback), any()))
+            .thenReturn(wifiPickerTracker)
+
         // For convenience, set up the subscription info callbacks
         whenever(subscriptionManager.getActiveSubscriptionInfo(anyInt())).thenAnswer { invocation ->
             when (invocation.getArgument(0) as Int) {
@@ -164,15 +187,14 @@
 
         wifiRepository =
             WifiRepositoryImpl(
-                fakeBroadcastDispatcher,
-                connectivityManager,
-                connectivityRepository,
-                mock(),
-                mock(),
-                FakeExecutor(FakeSystemClock()),
-                dispatcher,
+                flags,
                 testScope.backgroundScope,
-                mock(),
+                mainExecutor,
+                dispatcher,
+                wifiPickerTrackerFactory,
+                wifiManager,
+                wifiLogBuffer,
+                wifiTableLogBuffer,
             )
 
         carrierConfigRepository =
@@ -229,6 +251,7 @@
                 wifiRepository,
                 fullConnectionFactory,
                 updateMonitor,
+                mock(),
             )
 
         testScope.runCurrent()
@@ -276,7 +299,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.subscriptions)
 
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -289,7 +312,7 @@
         testScope.runTest {
             val latest by collectLastValue(underTest.subscriptions)
 
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_1, SUB_2, SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -443,7 +466,7 @@
             collectLastValue(underTest.subscriptions)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -460,7 +483,7 @@
             collectLastValue(underTest.subscriptions)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_1, SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -477,7 +500,7 @@
             collectLastValue(underTest.subscriptions)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_1, SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -489,7 +512,7 @@
 
             // WHEN the wifi network updates to be not carrier merged
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE)
+            setWifiState(isCarrierMerged = false)
             runCurrent()
 
             // THEN the repos update
@@ -505,7 +528,7 @@
             collectLastValue(underTest.subscriptions)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE)
+            setWifiState(isCarrierMerged = false)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_1, SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -518,7 +541,7 @@
 
             // WHEN the wifi network updates to be carrier merged
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             runCurrent()
 
             // THEN the repos update
@@ -529,6 +552,7 @@
         }
 
     @Test
+    @Ignore("b/333912012")
     fun testConnectionCache_clearsInvalidSubscriptions() =
         testScope.runTest {
             collectLastValue(underTest.subscriptions)
@@ -553,12 +577,13 @@
         }
 
     @Test
+    @Ignore("b/333912012")
     fun testConnectionCache_clearsInvalidSubscriptions_includingCarrierMerged() =
         testScope.runTest {
             collectLastValue(underTest.subscriptions)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             whenever(subscriptionManager.completeActiveSubscriptionInfoList)
                 .thenReturn(listOf(SUB_1, SUB_2, SUB_CM))
             getSubscriptionCallback().onSubscriptionsChanged()
@@ -581,6 +606,7 @@
 
     /** Regression test for b/261706421 */
     @Test
+    @Ignore("b/333912012")
     fun testConnectionsCache_clearMultipleSubscriptionsAtOnce_doesNotThrow() =
         testScope.runTest {
             collectLastValue(underTest.subscriptions)
@@ -604,6 +630,54 @@
         }
 
     @Test
+    fun testConnectionsCache_keepsReposCached() =
+        testScope.runTest {
+            // Collect subscriptions to start the job
+            collectLastValue(underTest.subscriptions)
+
+            whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+                .thenReturn(listOf(SUB_1))
+            getSubscriptionCallback().onSubscriptionsChanged()
+
+            val repo1_1 = underTest.getRepoForSubId(SUB_1_ID)
+
+            // All subscriptions disappear
+            whenever(subscriptionManager.completeActiveSubscriptionInfoList).thenReturn(listOf())
+            getSubscriptionCallback().onSubscriptionsChanged()
+
+            // Sub1 comes back
+            whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+                .thenReturn(listOf(SUB_1))
+            getSubscriptionCallback().onSubscriptionsChanged()
+
+            val repo1_2 = underTest.getRepoForSubId(SUB_1_ID)
+
+            assertThat(repo1_1).isSameInstanceAs(repo1_2)
+        }
+
+    @Test
+    fun testConnectionsCache_doesNotDropReferencesThatHaveBeenRealized() =
+        testScope.runTest {
+            // Collect subscriptions to start the job
+            collectLastValue(underTest.subscriptions)
+
+            whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+                .thenReturn(listOf(SUB_1))
+            getSubscriptionCallback().onSubscriptionsChanged()
+
+            // Client grabs a reference to a repository, but doesn't keep it around
+            underTest.getRepoForSubId(SUB_1_ID)
+
+            // All subscriptions disappear
+            whenever(subscriptionManager.completeActiveSubscriptionInfoList).thenReturn(listOf())
+            getSubscriptionCallback().onSubscriptionsChanged()
+
+            val repo1 = underTest.getRepoForSubId(SUB_1_ID)
+
+            assertThat(repo1).isNotNull()
+        }
+
+    @Test
     fun testConnectionRepository_invalidSubId_doesNotThrow() =
         testScope.runTest {
             underTest.getRepoForSubId(SUB_1_ID)
@@ -792,7 +866,7 @@
             val latest by collectLastValue(underTest.hasCarrierMergedConnection)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+            setWifiState(isCarrierMerged = true)
 
             assertThat(latest).isTrue()
         }
@@ -814,7 +888,7 @@
             val latest by collectLastValue(underTest.hasCarrierMergedConnection)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+            setWifiState(isCarrierMerged = true)
 
             assertThat(latest).isTrue()
         }
@@ -837,7 +911,7 @@
             val latest by collectLastValue(underTest.hasCarrierMergedConnection)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+            setWifiState(isCarrierMerged = true)
 
             assertThat(latest).isTrue()
         }
@@ -859,7 +933,7 @@
             val latest by collectLastValue(underTest.hasCarrierMergedConnection)
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+            setWifiState(isCarrierMerged = true)
 
             assertThat(latest).isTrue()
         }
@@ -893,7 +967,7 @@
                 }
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
+            setWifiState(isCarrierMerged = true)
 
             // THEN there's a carrier merged connection
             assertThat(latest).isTrue()
@@ -929,7 +1003,7 @@
                 }
 
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
+            setWifiState(isCarrierMerged = true)
 
             // THEN there's a carrier merged connection
             assertThat(latest).isTrue()
@@ -952,7 +1026,7 @@
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
 
             // BUT the wifi repo has gotten updates that it *is* carrier merged
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
 
             // THEN hasCarrierMergedConnection is true
             assertThat(latest).isTrue()
@@ -973,7 +1047,7 @@
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
 
             // BUT the wifi repo has gotten updates that it *is* carrier merged
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
 
             // THEN hasCarrierMergedConnection is **false** (The default network being CELLULAR
             // takes precedence over the wifi network being carrier merged.)
@@ -995,7 +1069,7 @@
             getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
 
             // BUT the wifi repo has gotten updates that it *is* carrier merged
-            getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM)
+            setWifiState(isCarrierMerged = true)
             // AND we're in airplane mode
             airplaneModeRepository.setIsAirplaneMode(true)
 
@@ -1063,7 +1137,8 @@
                     airplaneModeRepository,
                     wifiRepository,
                     fullConnectionFactory,
-                    updateMonitor
+                    updateMonitor,
+                    mock(),
                 )
 
             val latest by collectLastValue(underTest.defaultDataSubRatConfig)
@@ -1223,12 +1298,26 @@
         return callbackCaptor.value!!
     }
 
-    // Note: This is used to update the [WifiRepository].
-    private fun TestScope.getNormalNetworkCallback(): ConnectivityManager.NetworkCallback {
-        runCurrent()
-        val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>()
-        verify(connectivityManager).registerNetworkCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.value!!
+    private fun setWifiState(isCarrierMerged: Boolean) {
+        if (isCarrierMerged) {
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                    whenever(this.subscriptionId).thenReturn(SUB_CM_ID)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+        } else {
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(null)
+        }
+        wifiPickerTrackerCallback.value.onWifiEntriesChanged()
     }
 
     private fun TestScope.getSubscriptionCallback():
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 c49fcf8..dfe8023 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
@@ -43,15 +43,12 @@
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlin.time.Duration.Companion.seconds
-import kotlin.time.DurationUnit
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -181,6 +178,22 @@
         }
 
     @Test
+    fun inflateSignalStrength_arbitrarilyAddsOneToTheReportedLevel() =
+        testScope.runTest {
+            connectionRepository.inflateSignalStrength.value = false
+            val latest by collectLastValue(underTest.signalLevelIcon)
+
+            connectionRepository.primaryLevel.value = 4
+            assertThat(latest!!.level).isEqualTo(4)
+
+            connectionRepository.inflateSignalStrength.value = true
+            connectionRepository.primaryLevel.value = 4
+
+            // when INFLATE_SIGNAL_STRENGTH is true, we add 1 to the reported signal level
+            assertThat(latest!!.level).isEqualTo(5)
+        }
+
+    @Test
     fun iconGroup_three_g() =
         testScope.runTest {
             connectionRepository.resolvedNetworkType.value =
@@ -678,32 +691,6 @@
             assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java)
         }
 
-    @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
-    @Test
-    fun satBasedIcon_hasHysteresisWhenDisabled() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.signalLevelIcon)
-
-            val hysteresisDuration = 5.seconds
-            connectionRepository.satelliteConnectionHysteresisSeconds.value =
-                hysteresisDuration.toInt(DurationUnit.SECONDS)
-
-            connectionRepository.isNonTerrestrial.value = true
-
-            assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java)
-
-            // Disable satellite
-            connectionRepository.isNonTerrestrial.value = false
-
-            // Satellite icon should still be visible
-            assertThat(latest).isInstanceOf(SignalIconModel.Satellite::class.java)
-
-            // Wait for the icon to change
-            advanceTimeBy(hysteresisDuration)
-
-            assertThat(latest).isInstanceOf(SignalIconModel.Cellular::class.java)
-        }
-
     private fun createInteractor(
         overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl()
     ) =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index 83d0fe8..cec4155 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -54,6 +54,7 @@
 import com.android.systemui.util.CarrierConfigTracker
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.launchIn
@@ -279,6 +280,76 @@
         }
 
     @Test
+    fun contentDescription_nonInflated_invalidLevelIsNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.contentDescription)
+
+            repository.inflateSignalStrength.value = false
+            repository.setAllLevels(-1)
+            assertThat(latest).isNull()
+
+            repository.setAllLevels(100)
+            assertThat(latest).isNull()
+        }
+
+    @Test
+    fun contentDescription_inflated_invalidLevelIsNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.contentDescription)
+
+            repository.inflateSignalStrength.value = true
+            repository.numberOfLevels.value = 6
+            repository.setAllLevels(-2)
+            assertThat(latest).isNull()
+
+            repository.setAllLevels(100)
+            assertThat(latest).isNull()
+        }
+
+    @Test
+    fun contentDescription_nonInflated_testABunchOfLevelsForNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.contentDescription)
+
+            repository.inflateSignalStrength.value = false
+            repository.numberOfLevels.value = 5
+
+            // -1 and 5 are out of the bounds for non-inflated content descriptions
+            for (i in -1..5) {
+                repository.setAllLevels(i)
+                when (i) {
+                    -1,
+                    5 -> assertWithMessage("Level $i is expected to be null").that(latest).isNull()
+                    else ->
+                        assertWithMessage("Level $i is expected not to be null")
+                            .that(latest)
+                            .isNotNull()
+                }
+            }
+        }
+
+    @Test
+    fun contentDescription_inflated_testABunchOfLevelsForNull() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.contentDescription)
+            repository.inflateSignalStrength.value = true
+            repository.numberOfLevels.value = 6
+            // -1 and 6 are out of the bounds for inflated content descriptions
+            // Note that the interactor adds 1 to the reported level, hence the -2 to 5 range
+            for (i in -2..5) {
+                repository.setAllLevels(i)
+                when (i) {
+                    -2,
+                    5 -> assertWithMessage("Level $i is expected to be null").that(latest).isNull()
+                    else ->
+                        assertWithMessage("Level $i is not expected to be null")
+                            .that(latest)
+                            .isNotNull()
+                }
+            }
+        }
+
+    @Test
     fun networkType_dataEnabled_groupIsRepresented() =
         testScope.runTest {
             val expected =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
index 42bbe3e..c4ab943 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
@@ -26,6 +26,10 @@
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.satellite.data.prod.FakeDeviceBasedSatelliteRepository
 import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
 import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
 import com.android.systemui.util.mockito.mock
@@ -53,6 +57,10 @@
     private val deviceProvisionedRepository = FakeDeviceProvisioningRepository()
     private val deviceProvisioningInteractor =
         DeviceProvisioningInteractor(deviceProvisionedRepository)
+    private val connectivityRepository = FakeConnectivityRepository()
+    private val wifiRepository = FakeWifiRepository()
+    private val wifiInteractor =
+        WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
 
     @Before
     fun setUp() {
@@ -61,6 +69,7 @@
                 repo,
                 iconsInteractor,
                 deviceProvisioningInteractor,
+                wifiInteractor,
                 testScope.backgroundScope,
             )
     }
@@ -103,6 +112,7 @@
                     repo,
                     iconsInteractor,
                     deviceProvisioningInteractor,
+                    wifiInteractor,
                     testScope.backgroundScope,
                 )
 
@@ -150,6 +160,7 @@
                     repo,
                     iconsInteractor,
                     deviceProvisioningInteractor,
+                    wifiInteractor,
                     testScope.backgroundScope,
                 )
 
@@ -205,6 +216,7 @@
                     repo,
                     iconsInteractor,
                     deviceProvisioningInteractor,
+                    wifiInteractor,
                     testScope.backgroundScope,
                 )
 
@@ -337,6 +349,7 @@
                     repo,
                     iconsInteractor,
                     deviceProvisioningInteractor,
+                    wifiInteractor,
                     testScope.backgroundScope,
                 )
 
@@ -353,4 +366,28 @@
             // THEN the value is still false, because the flag is off
             assertThat(latest).isFalse()
         }
+
+    @Test
+    fun isWifiActive_falseWhenWifiNotActive() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiActive)
+
+            // WHEN wifi is not active
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Invalid("test"))
+
+            // THEN the interactor returns false due to the wifi network not being active
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiActive_trueWhenWifiIsActive() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiActive)
+
+            // WHEN wifi is active
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+
+            // THEN the interactor returns true due to the wifi network being active
+            assertThat(latest).isTrue()
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
index 1d6cd37..8eea29b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
@@ -21,11 +21,17 @@
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.log.core.FakeLogBuffer
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.satellite.data.prod.FakeDeviceBasedSatelliteRepository
 import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
 import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
 import com.android.systemui.util.mockito.mock
@@ -44,14 +50,18 @@
     private lateinit var underTest: DeviceBasedSatelliteViewModel
     private lateinit var interactor: DeviceBasedSatelliteInteractor
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
-
     private val repo = FakeDeviceBasedSatelliteRepository()
+    private val testScope = TestScope()
+
     private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
+
     private val deviceProvisionedRepository = FakeDeviceProvisioningRepository()
     private val deviceProvisioningInteractor =
         DeviceProvisioningInteractor(deviceProvisionedRepository)
-
-    private val testScope = TestScope()
+    private val connectivityRepository = FakeConnectivityRepository()
+    private val wifiRepository = FakeWifiRepository()
+    private val wifiInteractor =
+        WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
 
     @Before
     fun setUp() {
@@ -63,11 +73,13 @@
                 repo,
                 mobileIconsInteractor,
                 deviceProvisioningInteractor,
+                wifiInteractor,
                 testScope.backgroundScope,
             )
 
         underTest =
-            DeviceBasedSatelliteViewModel(
+            DeviceBasedSatelliteViewModelImpl(
+                context,
                 interactor,
                 testScope.backgroundScope,
                 airplaneModeRepository,
@@ -115,6 +127,7 @@
             assertThat(latest).isNull()
         }
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun icon_nullWhenShouldNotShow_isEmergencyOnly() =
         testScope.runTest {
@@ -253,4 +266,349 @@
             // THEN icon is null because the device is not provisioned
             assertThat(latest).isInstanceOf(Icon::class.java)
         }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun icon_wifiIsActive() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.icon)
+
+            // GIVEN satellite is allowed
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // GIVEN device is provisioned
+            deviceProvisionedRepository.setDeviceProvisioned(true)
+
+            // GIVEN wifi network is active
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+
+            // THEN icon is null because the device is connected to wifi
+            assertThat(latest).isNull()
+
+            // GIVEN device loses wifi connection
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Invalid("test"))
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            // THEN icon is set because the device lost wifi connection
+            assertThat(latest).isInstanceOf(Icon::class.java)
+        }
+
+    @Test
+    fun carrierText_nullWhenShouldNotShow_satelliteNotAllowed() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is not allowed
+            repo.isSatelliteAllowedForCurrentLocation.value = false
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // THEN carrier text is null because we should not be showing it
+            assertThat(latest).isNull()
+        }
+
+    @Test
+    fun carrierText_nullWhenShouldNotShow_notAllOos() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are not OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = true
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // THEN carrier text is null because we have service
+            assertThat(latest).isNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_nullWhenShouldNotShow_isEmergencyOnly() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            // THEN carrier text is set because we don't have service
+            assertThat(latest).isNotNull()
+
+            // GIVEN the connection is emergency only
+            i1.isEmergencyOnly.value = true
+
+            // THEN carrier text is null because we have emergency connection
+            assertThat(latest).isNull()
+        }
+
+    @Test
+    fun carrierText_nullWhenShouldNotShow_apmIsEnabled() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is enabled
+            airplaneModeRepository.setIsAirplaneMode(true)
+
+            // THEN carrier text is null because we should not be showing it
+            assertThat(latest).isNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_satelliteIsOn() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            // THEN carrier text is set because we don't have service
+            assertThat(latest).isNotNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_hysteresisWhenEnablingText() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // THEN carrier text is null because of the hysteresis
+            assertThat(latest).isNull()
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            // THEN carrier text is set after the delay
+            assertThat(latest).isNotNull()
+
+            // GIVEN apm is enabled
+            airplaneModeRepository.setIsAirplaneMode(true)
+
+            // THEN carrier text is null immediately
+            assertThat(latest).isNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_deviceIsProvisioned() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // GIVEN device is not provisioned
+            deviceProvisionedRepository.setDeviceProvisioned(false)
+
+            // THEN carrier text is null because the device is not provisioned
+            assertThat(latest).isNull()
+
+            // GIVEN device becomes provisioned
+            deviceProvisionedRepository.setDeviceProvisioned(true)
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            // THEN carrier text is null because the device is not provisioned
+            assertThat(latest).isNotNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_wifiIsActive() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // GIVEN satellite is allowed + connected
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // GIVEN all icons are OOS
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+
+            // GIVEN apm is disabled
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            // GIVEN device is provisioned
+            deviceProvisionedRepository.setDeviceProvisioned(true)
+
+            // GIVEN wifi network is active
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+
+            // THEN carrier text is null because the device is connected to wifi
+            assertThat(latest).isNull()
+
+            // GIVEN device loses wifi connection
+            wifiRepository.setWifiNetwork(WifiNetworkModel.Invalid("test"))
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            // THEN carrier text is set because the device lost wifi connection
+            assertThat(latest).isNotNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_connectionStateUnknown_null() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // Set up the conditions for satellite to be enabled
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            repo.connectionState.value = SatelliteConnectionState.Unknown
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            assertThat(latest).isNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_connectionStateOff_null() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // Set up the conditions for satellite to be enabled
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            repo.connectionState.value = SatelliteConnectionState.Off
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            assertThat(latest).isNull()
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_connectionStateOn_notConnectedString() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // Set up the conditions for satellite to be enabled
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            repo.connectionState.value = SatelliteConnectionState.On
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            assertThat(latest)
+                .isEqualTo(context.getString(R.string.satellite_not_connected_carrier_text))
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun carrierText_connectionStateConnected_connectedString() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.carrierText)
+
+            // Set up the conditions for satellite to be enabled
+            repo.isSatelliteAllowedForCurrentLocation.value = true
+            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            i1.isInService.value = false
+            i1.isEmergencyOnly.value = false
+            airplaneModeRepository.setIsAirplaneMode(false)
+
+            repo.connectionState.value = SatelliteConnectionState.Connected
+
+            // Wait for delay to be completed
+            advanceTimeBy(10.seconds)
+
+            assertThat(latest)
+                .isEqualTo(context.getString(R.string.satellite_connected_carrier_text))
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
new file mode 100644
index 0000000..f125ef12
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel
+
+import com.android.systemui.common.shared.model.Icon
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeDeviceBasedSatelliteViewModel : DeviceBasedSatelliteViewModel {
+    override val icon = MutableStateFlow<Icon?>(null)
+    override val carrierText = MutableStateFlow<String?>(null)
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
new file mode 100644
index 0000000..f8d50f5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -0,0 +1,1281 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.wifi.data.repository.prod
+
+import android.net.wifi.ScanResult
+import android.net.wifi.WifiManager
+import android.net.wifi.WifiManager.UNKNOWN_SSID
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.android.wifitrackerlib.HotspotNetworkEntry
+import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType
+import com.android.wifitrackerlib.MergedCarrierEntry
+import com.android.wifitrackerlib.WifiEntry
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE
+import com.android.wifitrackerlib.WifiPickerTracker
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.verify
+
+/**
+ * Note: Most of these tests are duplicates of [WifiRepositoryImplTest] tests.
+ *
+ * Any new tests added here may also need to be added to [WifiRepositoryImplTest].
+ */
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
[email protected](setAsMainLooper = true)
+class WifiRepositoryImplTest : SysuiTestCase() {
+
+    // Using lazy means that the class will only be constructed once it's fetched. Because the
+    // repository internally sets some values on construction, we need to set up some test
+    // parameters (like feature flags) *before* construction. Using lazy allows us to do that setup
+    // inside each test case without needing to manually recreate the repository.
+    private val underTest: WifiRepositoryImpl by lazy {
+        WifiRepositoryImpl(
+            featureFlags,
+            testScope.backgroundScope,
+            executor,
+            dispatcher,
+            wifiPickerTrackerFactory,
+            wifiManager,
+            logger,
+            tableLogger,
+        )
+    }
+
+    private val executor = FakeExecutor(FakeSystemClock())
+    private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock())
+    private val featureFlags = FakeFeatureFlags()
+    private val tableLogger = mock<TableLogBuffer>()
+    private val wifiManager =
+        mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) }
+    private val wifiPickerTrackerFactory = mock<WifiPickerTrackerFactory>()
+    private val wifiPickerTracker = mock<WifiPickerTracker>()
+
+    private val callbackCaptor = argumentCaptor<WifiPickerTracker.WifiPickerTrackerCallback>()
+
+    private val dispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(dispatcher)
+
+    @Before
+    fun setUp() {
+        featureFlags.set(Flags.INSTANT_TETHER, false)
+        featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
+        whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor), any()))
+            .thenReturn(wifiPickerTracker)
+    }
+
+    @Test
+    fun wifiPickerTrackerCreation_scansDisabled() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+            testScope.runCurrent()
+
+            verify(wifiPickerTracker).disableScanning()
+        }
+
+    @Test
+    fun isWifiEnabled_enabled_true() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiEnabled)
+
+            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLED)
+            getCallback().onWifiStateChanged()
+
+            assertThat(latest).isTrue()
+        }
+
+    @Test
+    fun isWifiEnabled_enabling_false() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiEnabled)
+
+            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLING)
+            getCallback().onWifiStateChanged()
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiEnabled_disabling_true() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiEnabled)
+
+            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLING)
+            getCallback().onWifiStateChanged()
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiEnabled_disabled_false() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiEnabled)
+
+            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLED)
+            getCallback().onWifiStateChanged()
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiEnabled_respondsToUpdates() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiEnabled)
+            executor.runAllReady()
+
+            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLED)
+            getCallback().onWifiStateChanged()
+
+            assertThat(latest).isTrue()
+
+            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLED)
+            getCallback().onWifiStateChanged()
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiDefault_initiallyGetsDefault() =
+        testScope.runTest { assertThat(underTest.isWifiDefault.value).isFalse() }
+
+    @Test
+    fun isWifiDefault_wifiNetwork_isTrue() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiDefault)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(true) }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isTrue()
+        }
+
+    @Test
+    fun isWifiDefault_carrierMerged_isTrue() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiDefault)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isTrue()
+        }
+
+    @Test
+    fun isWifiDefault_wifiNetworkNotDefault_isFalse() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiDefault)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(false) }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiDefault_carrierMergedNotDefault_isFalse() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiDefault)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isDefaultNetwork).thenReturn(false)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun isWifiDefault_noWifiNetwork_isFalse() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.isWifiDefault)
+
+            // First, add a network
+            val wifiEntry =
+                mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(true) }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isTrue()
+
+            // WHEN the network is lost
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+
+            // THEN we update to false
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun wifiNetwork_initiallyGetsDefault() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            assertThat(latest).isEqualTo(WIFI_NETWORK_DEFAULT)
+        }
+
+    @Test
+    fun wifiNetwork_primaryWifiNetworkAdded_flowHasNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.title).thenReturn(TITLE)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.Active).isTrue()
+            val latestActive = latest as WifiNetworkModel.Active
+            assertThat(latestActive.level).isEqualTo(3)
+            assertThat(latestActive.ssid).isEqualTo(TITLE)
+        }
+
+    @Test
+    fun accessPointInfo_alwaysFalse() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.title).thenReturn(TITLE)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.Active).isTrue()
+            val latestActive = latest as WifiNetworkModel.Active
+            assertThat(latestActive.isPasspointAccessPoint).isFalse()
+            assertThat(latestActive.isOnlineSignUpForPasspointAccessPoint).isFalse()
+            assertThat(latestActive.passpointProviderFriendlyName).isNull()
+        }
+
+    @Test
+    fun wifiNetwork_unreachableLevel_inactiveNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+        }
+
+    @Test
+    fun wifiNetwork_levelTooHigh_inactiveNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(WIFI_LEVEL_MAX + 1)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+        }
+
+    @Test
+    fun wifiNetwork_levelTooLow_inactiveNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(WIFI_LEVEL_MIN - 1)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+        }
+
+    @Test
+    fun wifiNetwork_levelIsMax_activeNetworkWithMaxLevel() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(WIFI_LEVEL_MAX)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java)
+            assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MAX)
+        }
+
+    @Test
+    fun wifiNetwork_levelIsMin_activeNetworkWithMinLevel() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(WIFI_LEVEL_MIN)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java)
+            assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MIN)
+        }
+
+    @Test
+    fun wifiNetwork_notHotspot_none() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(true) }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_unknown() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.UNKNOWN)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_phone() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.PHONE)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_tablet() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.TABLET)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_laptop() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.LAPTOP)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_watch() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.WATCH)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_auto() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.AUTO)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_invalid() =
+        testScope.runTest {
+            featureFlags.set(Flags.INSTANT_TETHER, true)
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(1234)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.INVALID)
+        }
+
+    @Test
+    fun wifiNetwork_hotspot_flagOff_valueNotUsed() =
+        testScope.runTest {
+            // WHEN the flag is off
+            featureFlags.set(Flags.INSTANT_TETHER, false)
+
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            // THEN NONE is always used, even if the wifi entry does have a hotspot device type
+            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+                .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
+        }
+
+    @Test
+    fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.subscriptionId).thenReturn(567)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+            val latestMerged = latest as WifiNetworkModel.CarrierMerged
+            assertThat(latestMerged.level).isEqualTo(3)
+            assertThat(latestMerged.subscriptionId).isEqualTo(567)
+        }
+
+    @Test
+    fun wifiNetwork_isCarrierMerged_getsMaxSignalLevel() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            whenever(wifiManager.maxSignalLevel).thenReturn(5)
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+            val latestMerged = latest as WifiNetworkModel.CarrierMerged
+            // numberOfLevels = maxSignalLevel + 1
+            assertThat(latestMerged.numberOfLevels).isEqualTo(6)
+        }
+
+    @Test
+    fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java)
+        }
+
+    @Test
+    fun wifiNetwork_notValidated_networkNotValidated() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.hasInternetAccess()).thenReturn(false)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse()
+        }
+
+    @Test
+    fun wifiNetwork_validated_networkValidated() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.hasInternetAccess()).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue()
+        }
+
+    @Test
+    fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(false) }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+        }
+
+    @Test
+    fun wifiNetwork_nonPrimaryCarrierMergedNetworkAdded_flowHasNoNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(false)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+        }
+
+    @Test
+    fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            // Start with the original network
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.title).thenReturn("AB")
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.Active).isTrue()
+            var latestActive = latest as WifiNetworkModel.Active
+            assertThat(latestActive.level).isEqualTo(3)
+            assertThat(latestActive.ssid).isEqualTo("AB")
+
+            // WHEN we update to a new primary network
+            val newWifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(4)
+                    whenever(this.title).thenReturn("CD")
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(newWifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            // THEN we use the new network
+            assertThat(latest is WifiNetworkModel.Active).isTrue()
+            latestActive = latest as WifiNetworkModel.Active
+            assertThat(latestActive.level).isEqualTo(4)
+            assertThat(latestActive.ssid).isEqualTo("CD")
+        }
+
+    @Test
+    fun wifiNetwork_noCurrentNetwork_networkLost_flowHasNoNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            // WHEN we receive a null network without any networks beforehand
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+
+            // THEN there's no crash and we still have no network
+            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
+        }
+
+    @Test
+    fun wifiNetwork_currentActiveNetworkLost_flowHasNoNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.title).thenReturn(TITLE)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat((latest as WifiNetworkModel.Active).ssid).isEqualTo(TITLE)
+
+            // WHEN we lose our current network
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+
+            // THEN we update to no network
+            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
+        }
+
+    /** Possible regression test for b/278618530. */
+    @Test
+    fun wifiNetwork_currentCarrierMergedNetworkLost_flowHasNoNetwork() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+            assertThat((latest as WifiNetworkModel.CarrierMerged).level).isEqualTo(3)
+
+            // WHEN we lose our current network
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+
+            // THEN we update to no network
+            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
+        }
+
+    /** Regression test for b/244173280. */
+    @Test
+    fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() =
+        testScope.runTest {
+            val latest1 by collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(1)
+                    whenever(this.title).thenReturn(TITLE)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest1 is WifiNetworkModel.Active).isTrue()
+            val latest1Active = latest1 as WifiNetworkModel.Active
+            assertThat(latest1Active.level).isEqualTo(1)
+            assertThat(latest1Active.ssid).isEqualTo(TITLE)
+
+            // WHEN we add a second subscriber after having already emitted a value
+            val latest2 by collectLastValue(underTest.wifiNetwork)
+
+            // THEN the second subscribe receives the already-emitted value
+            assertThat(latest2 is WifiNetworkModel.Active).isTrue()
+            val latest2Active = latest2 as WifiNetworkModel.Active
+            assertThat(latest2Active.level).isEqualTo(1)
+            assertThat(latest2Active.ssid).isEqualTo(TITLE)
+        }
+
+    @Test
+    fun wifiNetwork_carrierMerged_default_usesCarrierMergedInfo() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.isDefaultNetwork).thenReturn(true)
+                }
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(1)
+                    whenever(this.title).thenReturn(TITLE)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+        }
+
+    @Test
+    fun wifiNetwork_carrierMerged_notDefault_usesConnectedInfo() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiNetwork)
+
+            val mergedEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(3)
+                    whenever(this.isDefaultNetwork).thenReturn(false)
+                }
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(1)
+                    whenever(this.title).thenReturn(TITLE)
+                }
+            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest is WifiNetworkModel.Active).isTrue()
+        }
+
+    @Test
+    fun secondaryNetworks_activeEntriesEmpty_isEmpty() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf())
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEmpty()
+        }
+
+    @Test
+    fun secondaryNetworks_oneActiveEntry_hasOne() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val wifiEntry = mock<WifiEntry>()
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).hasSize(1)
+        }
+
+    @Test
+    fun secondaryNetworks_multipleActiveEntries_hasMultiple() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val wifiEntry1 = mock<WifiEntry>()
+            val wifiEntry2 = mock<WifiEntry>()
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry1, wifiEntry2))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).hasSize(2)
+        }
+
+    @Test
+    fun secondaryNetworks_mapsToInactive() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val inactiveEntry =
+                mock<WifiEntry>().apply { whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE) }
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(inactiveEntry))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).hasSize(1)
+            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Inactive::class.java)
+        }
+
+    @Test
+    fun secondaryNetworks_mapsToActive() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(activeEntry))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).hasSize(1)
+            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Active::class.java)
+            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
+        }
+
+    @Test
+    fun secondaryNetworks_mapsToCarrierMerged() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val carrierMergedEntry =
+                mock<MergedCarrierEntry>().apply { whenever(this.level).thenReturn(3) }
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(carrierMergedEntry))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).hasSize(1)
+            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.CarrierMerged::class.java)
+            assertThat((latest!![0] as WifiNetworkModel.CarrierMerged).level).isEqualTo(3)
+        }
+
+    @Test
+    fun secondaryNetworks_mapsMultipleInOrder() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
+            val carrierMergedEntry =
+                mock<MergedCarrierEntry>().apply { whenever(this.level).thenReturn(3) }
+            whenever(wifiPickerTracker.activeWifiEntries)
+                .thenReturn(listOf(activeEntry, carrierMergedEntry))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Active::class.java)
+            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
+            assertThat(latest!![1]).isInstanceOf(WifiNetworkModel.CarrierMerged::class.java)
+            assertThat((latest!![1] as WifiNetworkModel.CarrierMerged).level).isEqualTo(3)
+        }
+
+    @Test
+    fun secondaryNetworks_filtersOutConnectedEntry() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val connectedEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(1) }
+            val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
+            val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) }
+            // WHEN the active list has both a primary and secondary networks
+            whenever(wifiPickerTracker.activeWifiEntries)
+                .thenReturn(listOf(connectedEntry, secondaryEntry1, secondaryEntry2))
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(connectedEntry)
+
+            getCallback().onWifiEntriesChanged()
+
+            // THEN only the secondary networks are included
+            assertThat(latest).hasSize(2)
+            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
+            assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3)
+        }
+
+    @Test
+    fun secondaryNetworks_noConnectedEntry_hasAllActiveEntries() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
+            val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) }
+            whenever(wifiPickerTracker.activeWifiEntries)
+                .thenReturn(listOf(secondaryEntry1, secondaryEntry2))
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).hasSize(2)
+            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
+            assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3)
+        }
+
+    @Test
+    fun secondaryNetworks_filtersOutPrimaryNetwork() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val primaryEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.level).thenReturn(1)
+                }
+            val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
+            val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) }
+            // WHEN the active list has both a primary and secondary networks
+            whenever(wifiPickerTracker.activeWifiEntries)
+                .thenReturn(listOf(secondaryEntry1, primaryEntry, secondaryEntry2))
+
+            getCallback().onWifiEntriesChanged()
+
+            // THEN only the secondary networks are included
+            assertThat(latest).hasSize(2)
+            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
+            assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3)
+        }
+
+    @Test
+    fun secondaryNetworks_flagOff_noNetworks() =
+        testScope.runTest {
+            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
+            val latest by collectLastValue(underTest.secondaryNetworks)
+
+            val wifiEntry = mock<WifiEntry>()
+            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry))
+
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(latest).isEmpty()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_inactiveNetwork_false() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_nonPrimaryNetwork_false() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(false) }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_carrierMergedNetwork_false() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_invalidNetwork_false() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<MergedCarrierEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_activeNetwork_nullTitle_false() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.title).thenReturn(null)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_activeNetwork_unknownTitle_false() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.title).thenReturn(UNKNOWN_SSID)
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_activeNetwork_validTitle_true() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.title).thenReturn("fakeSsid")
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue()
+        }
+
+    @Test
+    fun isWifiConnectedWithValidSsid_activeToInactive_trueToFalse() =
+        testScope.runTest {
+            collectLastValue(underTest.wifiNetwork)
+
+            // Start with active
+            val wifiEntry =
+                mock<WifiEntry>().apply {
+                    whenever(this.isPrimaryNetwork).thenReturn(true)
+                    whenever(this.title).thenReturn("fakeSsid")
+                }
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue()
+
+            // WHEN the network is lost
+            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
+            getCallback().onWifiEntriesChanged()
+            testScope.runCurrent()
+
+            // THEN the isWifiConnected updates
+            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+        }
+
+    @Test
+    fun wifiActivity_callbackGivesNone_activityFlowHasNone() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiActivity)
+
+            getTrafficStateCallback()
+                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE)
+
+            assertThat(latest)
+                .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
+        }
+
+    @Test
+    fun wifiActivity_callbackGivesIn_activityFlowHasIn() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiActivity)
+
+            getTrafficStateCallback()
+                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN)
+
+            assertThat(latest)
+                .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false))
+        }
+
+    @Test
+    fun wifiActivity_callbackGivesOut_activityFlowHasOut() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiActivity)
+
+            getTrafficStateCallback()
+                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT)
+
+            assertThat(latest)
+                .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true))
+        }
+
+    @Test
+    fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiActivity)
+
+            getTrafficStateCallback()
+                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT)
+
+            assertThat(latest)
+                .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true))
+        }
+
+    @Test
+    fun wifiScanResults_containsSsidList() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiScanResults)
+
+            val scanResults =
+                listOf(
+                    ScanResult().also { it.SSID = "ssid 1" },
+                    ScanResult().also { it.SSID = "ssid 2" },
+                    ScanResult().also { it.SSID = "ssid 3" },
+                    ScanResult().also { it.SSID = "ssid 4" },
+                    ScanResult().also { it.SSID = "ssid 5" },
+                )
+            whenever(wifiManager.scanResults).thenReturn(scanResults)
+            getScanResultsCallback().onScanResultsAvailable()
+
+            val expected =
+                listOf(
+                    WifiScanEntry(ssid = "ssid 1"),
+                    WifiScanEntry(ssid = "ssid 2"),
+                    WifiScanEntry(ssid = "ssid 3"),
+                    WifiScanEntry(ssid = "ssid 4"),
+                    WifiScanEntry(ssid = "ssid 5"),
+                )
+
+            assertThat(latest).isEqualTo(expected)
+        }
+
+    @Test
+    fun wifiScanResults_updates() =
+        testScope.runTest {
+            val latest by collectLastValue(underTest.wifiScanResults)
+
+            var scanResults =
+                listOf(
+                    ScanResult().also { it.SSID = "ssid 1" },
+                    ScanResult().also { it.SSID = "ssid 2" },
+                    ScanResult().also { it.SSID = "ssid 3" },
+                    ScanResult().also { it.SSID = "ssid 4" },
+                    ScanResult().also { it.SSID = "ssid 5" },
+                )
+            whenever(wifiManager.scanResults).thenReturn(scanResults)
+            getScanResultsCallback().onScanResultsAvailable()
+
+            // New scan representing no results
+            scanResults = listOf()
+            whenever(wifiManager.scanResults).thenReturn(scanResults)
+            getScanResultsCallback().onScanResultsAvailable()
+
+            assertThat(latest).isEmpty()
+        }
+
+    private fun getCallback(): WifiPickerTracker.WifiPickerTrackerCallback {
+        testScope.runCurrent()
+        return callbackCaptor.value
+    }
+
+    private fun getTrafficStateCallback(): WifiManager.TrafficStateCallback {
+        testScope.runCurrent()
+        val callbackCaptor = argumentCaptor<WifiManager.TrafficStateCallback>()
+        verify(wifiManager).registerTrafficStateCallback(any(), callbackCaptor.capture())
+        return callbackCaptor.value!!
+    }
+
+    private fun createHotspotWithType(@DeviceType type: Int): HotspotNetworkEntry {
+        return mock<HotspotNetworkEntry>().apply {
+            whenever(this.isPrimaryNetwork).thenReturn(true)
+            whenever(this.deviceType).thenReturn(type)
+        }
+    }
+
+    private fun getScanResultsCallback(): WifiManager.ScanResultsCallback {
+        testScope.runCurrent()
+        val callbackCaptor = argumentCaptor<WifiManager.ScanResultsCallback>()
+        verify(wifiManager).registerScanResultsCallback(any(), callbackCaptor.capture())
+        return callbackCaptor.value!!
+    }
+
+    private companion object {
+        const val TITLE = "AB"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
deleted file mode 100644
index 3126362..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
+++ /dev/null
@@ -1,1281 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod
-
-import android.net.wifi.ScanResult
-import android.net.wifi.WifiManager
-import android.net.wifi.WifiManager.UNKNOWN_SSID
-import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo
-import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
-import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import com.android.wifitrackerlib.HotspotNetworkEntry
-import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType
-import com.android.wifitrackerlib.MergedCarrierEntry
-import com.android.wifitrackerlib.WifiEntry
-import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX
-import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN
-import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE
-import com.android.wifitrackerlib.WifiPickerTracker
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.mockito.Mockito.verify
-
-/**
- * Note: Most of these tests are duplicates of [WifiRepositoryImplTest] tests.
- *
- * Any new tests added here may also need to be added to [WifiRepositoryImplTest].
- */
-@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
[email protected](setAsMainLooper = true)
-class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
-
-    // Using lazy means that the class will only be constructed once it's fetched. Because the
-    // repository internally sets some values on construction, we need to set up some test
-    // parameters (like feature flags) *before* construction. Using lazy allows us to do that setup
-    // inside each test case without needing to manually recreate the repository.
-    private val underTest: WifiRepositoryViaTrackerLib by lazy {
-        WifiRepositoryViaTrackerLib(
-            featureFlags,
-            testScope.backgroundScope,
-            executor,
-            dispatcher,
-            wifiPickerTrackerFactory,
-            wifiManager,
-            logger,
-            tableLogger,
-        )
-    }
-
-    private val executor = FakeExecutor(FakeSystemClock())
-    private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock())
-    private val featureFlags = FakeFeatureFlags()
-    private val tableLogger = mock<TableLogBuffer>()
-    private val wifiManager =
-        mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) }
-    private val wifiPickerTrackerFactory = mock<WifiPickerTrackerFactory>()
-    private val wifiPickerTracker = mock<WifiPickerTracker>()
-
-    private val callbackCaptor = argumentCaptor<WifiPickerTracker.WifiPickerTrackerCallback>()
-
-    private val dispatcher = StandardTestDispatcher()
-    private val testScope = TestScope(dispatcher)
-
-    @Before
-    fun setUp() {
-        featureFlags.set(Flags.INSTANT_TETHER, false)
-        featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
-        whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor), any()))
-            .thenReturn(wifiPickerTracker)
-    }
-
-    @Test
-    fun wifiPickerTrackerCreation_scansDisabled() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-            testScope.runCurrent()
-
-            verify(wifiPickerTracker).disableScanning()
-        }
-
-    @Test
-    fun isWifiEnabled_enabled_true() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLED)
-            getCallback().onWifiStateChanged()
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiEnabled_enabling_false() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLING)
-            getCallback().onWifiStateChanged()
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiEnabled_disabling_true() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLING)
-            getCallback().onWifiStateChanged()
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiEnabled_disabled_false() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiEnabled)
-
-            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLED)
-            getCallback().onWifiStateChanged()
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiEnabled_respondsToUpdates() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiEnabled)
-            executor.runAllReady()
-
-            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLED)
-            getCallback().onWifiStateChanged()
-
-            assertThat(latest).isTrue()
-
-            whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLED)
-            getCallback().onWifiStateChanged()
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiDefault_initiallyGetsDefault() =
-        testScope.runTest { assertThat(underTest.isWifiDefault.value).isFalse() }
-
-    @Test
-    fun isWifiDefault_wifiNetwork_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(true) }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_carrierMerged_isTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isDefaultNetwork).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isTrue()
-        }
-
-    @Test
-    fun isWifiDefault_wifiNetworkNotDefault_isFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(false) }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiDefault_carrierMergedNotDefault_isFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isDefaultNetwork).thenReturn(false)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun isWifiDefault_noWifiNetwork_isFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.isWifiDefault)
-
-            // First, add a network
-            val wifiEntry =
-                mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(true) }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isTrue()
-
-            // WHEN the network is lost
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-
-            // THEN we update to false
-            assertThat(latest).isFalse()
-        }
-
-    @Test
-    fun wifiNetwork_initiallyGetsDefault() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            assertThat(latest).isEqualTo(WIFI_NETWORK_DEFAULT)
-        }
-
-    @Test
-    fun wifiNetwork_primaryWifiNetworkAdded_flowHasNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.level).isEqualTo(3)
-            assertThat(latestActive.ssid).isEqualTo(TITLE)
-        }
-
-    @Test
-    fun accessPointInfo_alwaysFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            val latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.isPasspointAccessPoint).isFalse()
-            assertThat(latestActive.isOnlineSignUpForPasspointAccessPoint).isFalse()
-            assertThat(latestActive.passpointProviderFriendlyName).isNull()
-        }
-
-    @Test
-    fun wifiNetwork_unreachableLevel_inactiveNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
-        }
-
-    @Test
-    fun wifiNetwork_levelTooHigh_inactiveNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(WIFI_LEVEL_MAX + 1)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
-        }
-
-    @Test
-    fun wifiNetwork_levelTooLow_inactiveNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(WIFI_LEVEL_MIN - 1)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
-        }
-
-    @Test
-    fun wifiNetwork_levelIsMax_activeNetworkWithMaxLevel() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(WIFI_LEVEL_MAX)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java)
-            assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MAX)
-        }
-
-    @Test
-    fun wifiNetwork_levelIsMin_activeNetworkWithMinLevel() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(WIFI_LEVEL_MIN)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java)
-            assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MIN)
-        }
-
-    @Test
-    fun wifiNetwork_notHotspot_none() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(true) }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_unknown() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.UNKNOWN)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_phone() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.PHONE)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_tablet() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.TABLET)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_laptop() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.LAPTOP)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_watch() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.WATCH)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_auto() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.AUTO)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_invalid() =
-        testScope.runTest {
-            featureFlags.set(Flags.INSTANT_TETHER, true)
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(1234)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.INVALID)
-        }
-
-    @Test
-    fun wifiNetwork_hotspot_flagOff_valueNotUsed() =
-        testScope.runTest {
-            // WHEN the flag is off
-            featureFlags.set(Flags.INSTANT_TETHER, false)
-
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            // THEN NONE is always used, even if the wifi entry does have a hotspot device type
-            assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
-                .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
-        }
-
-    @Test
-    fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.subscriptionId).thenReturn(567)
-                    whenever(this.isDefaultNetwork).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-            val latestMerged = latest as WifiNetworkModel.CarrierMerged
-            assertThat(latestMerged.level).isEqualTo(3)
-            assertThat(latestMerged.subscriptionId).isEqualTo(567)
-        }
-
-    @Test
-    fun wifiNetwork_isCarrierMerged_getsMaxSignalLevel() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.isDefaultNetwork).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            whenever(wifiManager.maxSignalLevel).thenReturn(5)
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-            val latestMerged = latest as WifiNetworkModel.CarrierMerged
-            // numberOfLevels = maxSignalLevel + 1
-            assertThat(latestMerged.numberOfLevels).isEqualTo(6)
-        }
-
-    @Test
-    fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
-                    whenever(this.isDefaultNetwork).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java)
-        }
-
-    @Test
-    fun wifiNetwork_notValidated_networkNotValidated() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.hasInternetAccess()).thenReturn(false)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse()
-        }
-
-    @Test
-    fun wifiNetwork_validated_networkValidated() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.hasInternetAccess()).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(false) }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
-        }
-
-    @Test
-    fun wifiNetwork_nonPrimaryCarrierMergedNetworkAdded_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(false)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
-        }
-
-    @Test
-    fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            // Start with the original network
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.title).thenReturn("AB")
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            var latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.level).isEqualTo(3)
-            assertThat(latestActive.ssid).isEqualTo("AB")
-
-            // WHEN we update to a new primary network
-            val newWifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(4)
-                    whenever(this.title).thenReturn("CD")
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(newWifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            // THEN we use the new network
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-            latestActive = latest as WifiNetworkModel.Active
-            assertThat(latestActive.level).isEqualTo(4)
-            assertThat(latestActive.ssid).isEqualTo("CD")
-        }
-
-    @Test
-    fun wifiNetwork_noCurrentNetwork_networkLost_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            // WHEN we receive a null network without any networks beforehand
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-
-            // THEN there's no crash and we still have no network
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_currentActiveNetworkLost_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat((latest as WifiNetworkModel.Active).ssid).isEqualTo(TITLE)
-
-            // WHEN we lose our current network
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-
-            // THEN we update to no network
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    /** Possible regression test for b/278618530. */
-    @Test
-    fun wifiNetwork_currentCarrierMergedNetworkLost_flowHasNoNetwork() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.isDefaultNetwork).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-            assertThat((latest as WifiNetworkModel.CarrierMerged).level).isEqualTo(3)
-
-            // WHEN we lose our current network
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-
-            // THEN we update to no network
-            assertThat(latest is WifiNetworkModel.Inactive).isTrue()
-        }
-
-    /** Regression test for b/244173280. */
-    @Test
-    fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() =
-        testScope.runTest {
-            val latest1 by collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(1)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest1 is WifiNetworkModel.Active).isTrue()
-            val latest1Active = latest1 as WifiNetworkModel.Active
-            assertThat(latest1Active.level).isEqualTo(1)
-            assertThat(latest1Active.ssid).isEqualTo(TITLE)
-
-            // WHEN we add a second subscriber after having already emitted a value
-            val latest2 by collectLastValue(underTest.wifiNetwork)
-
-            // THEN the second subscribe receives the already-emitted value
-            assertThat(latest2 is WifiNetworkModel.Active).isTrue()
-            val latest2Active = latest2 as WifiNetworkModel.Active
-            assertThat(latest2Active.level).isEqualTo(1)
-            assertThat(latest2Active.ssid).isEqualTo(TITLE)
-        }
-
-    @Test
-    fun wifiNetwork_carrierMerged_default_usesCarrierMergedInfo() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.isDefaultNetwork).thenReturn(true)
-                }
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(1)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
-        }
-
-    @Test
-    fun wifiNetwork_carrierMerged_notDefault_usesConnectedInfo() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiNetwork)
-
-            val mergedEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(3)
-                    whenever(this.isDefaultNetwork).thenReturn(false)
-                }
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(1)
-                    whenever(this.title).thenReturn(TITLE)
-                }
-            whenever(wifiPickerTracker.mergedCarrierEntry).thenReturn(mergedEntry)
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest is WifiNetworkModel.Active).isTrue()
-        }
-
-    @Test
-    fun secondaryNetworks_activeEntriesEmpty_isEmpty() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf())
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEmpty()
-        }
-
-    @Test
-    fun secondaryNetworks_oneActiveEntry_hasOne() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val wifiEntry = mock<WifiEntry>()
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).hasSize(1)
-        }
-
-    @Test
-    fun secondaryNetworks_multipleActiveEntries_hasMultiple() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val wifiEntry1 = mock<WifiEntry>()
-            val wifiEntry2 = mock<WifiEntry>()
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry1, wifiEntry2))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).hasSize(2)
-        }
-
-    @Test
-    fun secondaryNetworks_mapsToInactive() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val inactiveEntry =
-                mock<WifiEntry>().apply { whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE) }
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(inactiveEntry))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).hasSize(1)
-            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Inactive::class.java)
-        }
-
-    @Test
-    fun secondaryNetworks_mapsToActive() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(activeEntry))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).hasSize(1)
-            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Active::class.java)
-            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
-        }
-
-    @Test
-    fun secondaryNetworks_mapsToCarrierMerged() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val carrierMergedEntry =
-                mock<MergedCarrierEntry>().apply { whenever(this.level).thenReturn(3) }
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(carrierMergedEntry))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).hasSize(1)
-            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.CarrierMerged::class.java)
-            assertThat((latest!![0] as WifiNetworkModel.CarrierMerged).level).isEqualTo(3)
-        }
-
-    @Test
-    fun secondaryNetworks_mapsMultipleInOrder() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
-            val carrierMergedEntry =
-                mock<MergedCarrierEntry>().apply { whenever(this.level).thenReturn(3) }
-            whenever(wifiPickerTracker.activeWifiEntries)
-                .thenReturn(listOf(activeEntry, carrierMergedEntry))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Active::class.java)
-            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
-            assertThat(latest!![1]).isInstanceOf(WifiNetworkModel.CarrierMerged::class.java)
-            assertThat((latest!![1] as WifiNetworkModel.CarrierMerged).level).isEqualTo(3)
-        }
-
-    @Test
-    fun secondaryNetworks_filtersOutConnectedEntry() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val connectedEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(1) }
-            val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
-            val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) }
-            // WHEN the active list has both a primary and secondary networks
-            whenever(wifiPickerTracker.activeWifiEntries)
-                .thenReturn(listOf(connectedEntry, secondaryEntry1, secondaryEntry2))
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(connectedEntry)
-
-            getCallback().onWifiEntriesChanged()
-
-            // THEN only the secondary networks are included
-            assertThat(latest).hasSize(2)
-            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
-            assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3)
-        }
-
-    @Test
-    fun secondaryNetworks_noConnectedEntry_hasAllActiveEntries() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
-            val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) }
-            whenever(wifiPickerTracker.activeWifiEntries)
-                .thenReturn(listOf(secondaryEntry1, secondaryEntry2))
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).hasSize(2)
-            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
-            assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3)
-        }
-
-    @Test
-    fun secondaryNetworks_filtersOutPrimaryNetwork() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val primaryEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.level).thenReturn(1)
-                }
-            val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
-            val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) }
-            // WHEN the active list has both a primary and secondary networks
-            whenever(wifiPickerTracker.activeWifiEntries)
-                .thenReturn(listOf(secondaryEntry1, primaryEntry, secondaryEntry2))
-
-            getCallback().onWifiEntriesChanged()
-
-            // THEN only the secondary networks are included
-            assertThat(latest).hasSize(2)
-            assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2)
-            assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3)
-        }
-
-    @Test
-    fun secondaryNetworks_flagOff_noNetworks() =
-        testScope.runTest {
-            featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
-            val latest by collectLastValue(underTest.secondaryNetworks)
-
-            val wifiEntry = mock<WifiEntry>()
-            whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry))
-
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(latest).isEmpty()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_inactiveNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_nonPrimaryNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(false) }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_carrierMergedNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_invalidNetwork_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<MergedCarrierEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeNetwork_nullTitle_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.title).thenReturn(null)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeNetwork_unknownTitle_false() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.title).thenReturn(UNKNOWN_SSID)
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeNetwork_validTitle_true() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.title).thenReturn("fakeSsid")
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue()
-        }
-
-    @Test
-    fun isWifiConnectedWithValidSsid_activeToInactive_trueToFalse() =
-        testScope.runTest {
-            collectLastValue(underTest.wifiNetwork)
-
-            // Start with active
-            val wifiEntry =
-                mock<WifiEntry>().apply {
-                    whenever(this.isPrimaryNetwork).thenReturn(true)
-                    whenever(this.title).thenReturn("fakeSsid")
-                }
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue()
-
-            // WHEN the network is lost
-            whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
-            getCallback().onWifiEntriesChanged()
-            testScope.runCurrent()
-
-            // THEN the isWifiConnected updates
-            assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesNone_activityFlowHasNone() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback()
-                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesIn_activityFlowHasIn() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback()
-                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false))
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesOut_activityFlowHasOut() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback()
-                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true))
-        }
-
-    @Test
-    fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiActivity)
-
-            getTrafficStateCallback()
-                .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT)
-
-            assertThat(latest)
-                .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true))
-        }
-
-    @Test
-    fun wifiScanResults_containsSsidList() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiScanResults)
-
-            val scanResults =
-                listOf(
-                    ScanResult().also { it.SSID = "ssid 1" },
-                    ScanResult().also { it.SSID = "ssid 2" },
-                    ScanResult().also { it.SSID = "ssid 3" },
-                    ScanResult().also { it.SSID = "ssid 4" },
-                    ScanResult().also { it.SSID = "ssid 5" },
-                )
-            whenever(wifiManager.scanResults).thenReturn(scanResults)
-            getScanResultsCallback().onScanResultsAvailable()
-
-            val expected =
-                listOf(
-                    WifiScanEntry(ssid = "ssid 1"),
-                    WifiScanEntry(ssid = "ssid 2"),
-                    WifiScanEntry(ssid = "ssid 3"),
-                    WifiScanEntry(ssid = "ssid 4"),
-                    WifiScanEntry(ssid = "ssid 5"),
-                )
-
-            assertThat(latest).isEqualTo(expected)
-        }
-
-    @Test
-    fun wifiScanResults_updates() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.wifiScanResults)
-
-            var scanResults =
-                listOf(
-                    ScanResult().also { it.SSID = "ssid 1" },
-                    ScanResult().also { it.SSID = "ssid 2" },
-                    ScanResult().also { it.SSID = "ssid 3" },
-                    ScanResult().also { it.SSID = "ssid 4" },
-                    ScanResult().also { it.SSID = "ssid 5" },
-                )
-            whenever(wifiManager.scanResults).thenReturn(scanResults)
-            getScanResultsCallback().onScanResultsAvailable()
-
-            // New scan representing no results
-            scanResults = listOf()
-            whenever(wifiManager.scanResults).thenReturn(scanResults)
-            getScanResultsCallback().onScanResultsAvailable()
-
-            assertThat(latest).isEmpty()
-        }
-
-    private fun getCallback(): WifiPickerTracker.WifiPickerTrackerCallback {
-        testScope.runCurrent()
-        return callbackCaptor.value
-    }
-
-    private fun getTrafficStateCallback(): WifiManager.TrafficStateCallback {
-        testScope.runCurrent()
-        val callbackCaptor = argumentCaptor<WifiManager.TrafficStateCallback>()
-        verify(wifiManager).registerTrafficStateCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.value!!
-    }
-
-    private fun createHotspotWithType(@DeviceType type: Int): HotspotNetworkEntry {
-        return mock<HotspotNetworkEntry>().apply {
-            whenever(this.isPrimaryNetwork).thenReturn(true)
-            whenever(this.deviceType).thenReturn(type)
-        }
-    }
-
-    private fun getScanResultsCallback(): WifiManager.ScanResultsCallback {
-        testScope.runCurrent()
-        val callbackCaptor = argumentCaptor<WifiManager.ScanResultsCallback>()
-        verify(wifiManager).registerScanResultsCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.value!!
-    }
-
-    private companion object {
-        const val TITLE = "AB"
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerStartableTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerStartableTest.java
new file mode 100644
index 0000000..c4a7463
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerStartableTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
+import com.android.systemui.Flags;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+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 org.mockito.MockitoSession;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
[email protected]
+public class BatteryControllerStartableTest extends SysuiTestCase {
+
+    private BatteryController mBatteryController;
+    private BatteryControllerStartable mBatteryControllerStartable;
+    private MockitoSession mMockitoSession;
+    private FakeExecutor mExecutor;
+    @Mock
+    private BroadcastDispatcher mBroadcastDispatcher;
+
+    @Before
+    public void setUp() throws IllegalStateException {
+        MockitoAnnotations.initMocks(this);
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .mockStatic(BatterySaverUtils.class)
+                .startMocking();
+
+        mExecutor = new FakeExecutor(new FakeSystemClock());
+
+        mBatteryController = new BatteryControllerImpl(getContext(),
+                mock(EnhancedEstimates.class),
+                mock(PowerManager.class),
+                mock(BroadcastDispatcher.class),
+                mock(DemoModeController.class),
+                mock(DumpManager.class),
+                mock(BatteryControllerLogger.class),
+                new Handler(Looper.getMainLooper()),
+                new Handler(Looper.getMainLooper()));
+        mBatteryController.init();
+
+        mBatteryControllerStartable = new BatteryControllerStartable(mBatteryController,
+                mBroadcastDispatcher, mExecutor);
+    }
+
+    @After
+    public void tearDown() {
+        mMockitoSession.finishMocking();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_REGISTER_BATTERY_CONTROLLER_RECEIVERS_IN_CORESTARTABLE)
+    public void start_flagEnabled_registersListeners() {
+        mBatteryControllerStartable.start();
+        mExecutor.runAllReady();
+
+        verify(mBroadcastDispatcher).registerReceiver(any(), any());
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_REGISTER_BATTERY_CONTROLLER_RECEIVERS_IN_CORESTARTABLE)
+    public void start_flagDisabled_doesNotRegistersListeners() {
+        mBatteryControllerStartable.start();
+        mExecutor.runAllReady();
+
+        verifyZeroInteractions(mBroadcastDispatcher);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index a5c766d..9d4f1fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -36,11 +36,12 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerSaveState;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.dx.mockito.inline.extended.StaticInOrder;
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt
index 777fa28..1c54263 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt
@@ -20,7 +20,7 @@
 import android.hardware.camera2.CameraCharacteristics
 import android.hardware.camera2.CameraManager
 import android.hardware.camera2.impl.CameraMetadataNative
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastSender
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index cb6ce68..9bb7607 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -44,8 +44,8 @@
 import android.os.Handler;
 import android.os.UserManager;
 import android.security.IKeyChainService;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
index 358709f..3e20f68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt
@@ -21,6 +21,7 @@
 import android.media.projection.MediaProjectionManager
 import android.os.Handler
 import android.platform.test.annotations.DisableFlags
+import android.telephony.TelephonyManager
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.server.notification.Flags
@@ -46,6 +47,7 @@
     @Mock private lateinit var activityManager: IActivityManager
     @Mock private lateinit var mediaProjectionManager: MediaProjectionManager
     @Mock private lateinit var packageManager: PackageManager
+    @Mock private lateinit var telephonyManager: TelephonyManager
     private lateinit var controller: SensitiveNotificationProtectionControllerImpl
 
     @Before
@@ -59,6 +61,7 @@
                 mediaProjectionManager,
                 activityManager,
                 packageManager,
+                telephonyManager,
                 handler,
                 FakeExecutor(FakeSystemClock()),
                 logger
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
index 4ace163..2127057 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt
@@ -37,6 +37,7 @@
 import android.platform.test.annotations.RequiresFlagsEnabled
 import android.platform.test.flag.junit.DeviceFlagsValueProvider
 import android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS
+import android.telephony.TelephonyManager
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
@@ -89,6 +90,7 @@
     @Mock private lateinit var activityManager: IActivityManager
     @Mock private lateinit var mediaProjectionManager: MediaProjectionManager
     @Mock private lateinit var packageManager: PackageManager
+    @Mock private lateinit var telephonyManager: TelephonyManager
     @Mock private lateinit var listener1: Runnable
     @Mock private lateinit var listener2: Runnable
     @Mock private lateinit var listener3: Runnable
@@ -141,6 +143,9 @@
         whenever(packageManager.checkPermission(anyString(), anyString()))
             .thenReturn(PackageManager.PERMISSION_DENIED)
 
+        whenever(telephonyManager.getEmergencyAssistancePackageName())
+            .thenReturn(EMERGENCY_ASSISTANCE_PACKAGE_NAME)
+
         executor = FakeExecutor(FakeSystemClock())
         globalSettings = FakeGlobalSettings()
         controller =
@@ -150,6 +155,7 @@
                 mediaProjectionManager,
                 activityManager,
                 packageManager,
+                telephonyManager,
                 mockExecutorHandler(executor),
                 executor,
                 logger
@@ -407,6 +413,26 @@
     }
 
     @Test
+    @DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
+    fun shouldProtectNotification_projectionActive_isFromEmergencyPackage_fixDisabled_true() {
+        mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+        val notificationEntry = setupNotificationEntry(EMERGENCY_ASSISTANCE_PACKAGE_NAME)
+
+        assertTrue(controller.shouldProtectNotification(notificationEntry))
+    }
+
+    @Test
+    @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
+    fun shouldProtectNotification_projectionActive_isFromEmergencyPackage_false() {
+        mediaProjectionCallback.onStart(mediaProjectionInfo)
+
+        val notificationEntry = setupNotificationEntry(EMERGENCY_ASSISTANCE_PACKAGE_NAME)
+
+        assertFalse(controller.shouldProtectNotification(notificationEntry))
+    }
+
+    @Test
     fun shouldProtectNotification_projectionActive_sysuiExempt_false() {
         // SystemUi context package name is exempt, but in test scenarios its
         // com.android.systemui.tests so use that instead of hardcoding
@@ -742,6 +768,7 @@
         private const val TEST_PROJECTION_PACKAGE_NAME =
             "com.android.systemui.statusbar.policy.projectionpackage"
         private const val TEST_PACKAGE_NAME = "com.android.systemui.statusbar.policy.testpackage"
+        private const val EMERGENCY_ASSISTANCE_PACKAGE_NAME = "com.android.test.emergencyassistance"
         private const val BUGREPORT_PACKAGE_NAME = "com.android.test.bugreporthandler"
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
index dc0d07c..b9557d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
@@ -23,14 +23,15 @@
 import android.app.RemoteInput;
 import android.os.Handler;
 import android.provider.DeviceConfig;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableResources;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.util.DeviceConfigProxyFake;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
index ae34256..bdd3d18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ui/viewmodel/KeyguardStatusBarViewModelTest.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.data.repository.FakeKeyguardStatusBarRepository
@@ -60,7 +59,6 @@
             keyguardRepository,
             mock<CommandQueue>(),
             PowerInteractorFactory.create().powerInteractor,
-            kosmos.fakeSceneContainerFlags,
             FakeKeyguardBouncerRepository(),
             ConfigurationInteractor(FakeConfigurationRepository()),
             FakeShadeRepository(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectTest.kt
new file mode 100644
index 0000000..8105cc5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectTest.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.gloweffect
+
+import android.graphics.Color
+import android.graphics.RenderEffect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.animation.AnimatorTestRule
+import com.android.systemui.model.SysUiStateTest
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class GlowPieEffectTest : SysUiStateTest() {
+
+    @get:Rule val animatorTestRule = AnimatorTestRule(this)
+
+    @Test
+    fun play_triggersDrawCallback() {
+        var effectFromCallback: RenderEffect? = null
+        val glowPieEffectConfig =
+            GlowPieEffectConfig(
+                centerX = 0f,
+                centerY = 0f,
+                width = 1f,
+                height = 1f,
+                cornerRadius = 0.5f,
+                colors = intArrayOf(Color.RED, Color.GREEN, Color.BLUE)
+            )
+        val drawCallback =
+            object : RenderEffectDrawCallback {
+                override fun onDraw(renderEffect: RenderEffect) {
+                    effectFromCallback = renderEffect
+                }
+            }
+        val glowPieEffect = GlowPieEffect(glowPieEffectConfig, drawCallback)
+
+        assertThat(effectFromCallback).isNull()
+
+        glowPieEffect.play()
+
+        animatorTestRule.advanceTimeBy(100L)
+
+        assertThat(effectFromCallback).isNotNull()
+    }
+
+    @Test
+    fun finish_cancelsAnimator() {
+        val glowPieEffectConfig =
+            GlowPieEffectConfig(
+                centerX = 0f,
+                centerY = 0f,
+                width = 1f,
+                height = 1f,
+                cornerRadius = 0.5f,
+                colors = intArrayOf(Color.RED, Color.GREEN, Color.BLUE)
+            )
+        val drawCallback =
+            object : RenderEffectDrawCallback {
+                override fun onDraw(renderEffect: RenderEffect) {}
+            }
+        val glowPieEffect = GlowPieEffect(glowPieEffectConfig, drawCallback)
+
+        glowPieEffect.play()
+        animatorTestRule.advanceTimeBy(100L)
+
+        assertThat(glowPieEffect.mainAnimator.isRunning).isTrue()
+
+        glowPieEffect.finish()
+
+        assertThat(glowPieEffect.mainAnimator.isRunning).isFalse()
+    }
+
+    @Test
+    fun glowPie_progress_computesProgressCorrectly() {
+        val myGlowPieConfig =
+            object : GlowPieEffect.GlowPie {
+                override val startMs: Float = 0f
+                override val endMs: Float = GlowPieEffect.DURATION_MS.toFloat()
+                override val startAngle: Float = 0f
+                override val endAngle: Float = 6f * GlowPieEffect.PI
+                override val alphaFadeStartMs: Float = 0f
+                override val alphaFadeEndMs: Float = GlowPieEffect.DURATION_MS.toFloat()
+                override var progress: Float = 0f
+                override var time: Float = 0f
+            }
+
+        val playTime = GlowPieEffect.DURATION_MS.toFloat() * 0.5f
+        val tolerance = 1e-4f
+        myGlowPieConfig.updateProgress(playTime)
+
+        assertThat(myGlowPieConfig.time).isWithin(tolerance).of(playTime)
+        assertThat(myGlowPieConfig.progress).isWithin(tolerance).of(0.5f)
+        assertThat(myGlowPieConfig.angle()).isWithin(tolerance).of(-3.5f * GlowPieEffect.PI)
+        assertThat(myGlowPieConfig.bottomThreshold())
+            .isWithin(tolerance)
+            .of((1f - GlowPieEffect.FEATHER) * 0.5f)
+        assertThat(myGlowPieConfig.topThreshold())
+            .isWithin(tolerance)
+            .of((1f + GlowPieEffect.FEATHER) * 0.5f)
+        assertThat(myGlowPieConfig.alpha()).isWithin(tolerance).of(0.5f)
+
+        myGlowPieConfig.resetProgress()
+
+        assertThat(myGlowPieConfig.time).isEqualTo(0f)
+        assertThat(myGlowPieConfig.progress).isEqualTo(0f)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
index 7a83cfe..6f58941 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
@@ -23,14 +23,8 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.animation.AnimatorTestRule
 import com.android.systemui.model.SysUiStateTest
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.EASE_IN
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.EASE_OUT
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.MAIN
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.NOT_PLAYING
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationStateChangedCallback
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.PaintDrawCallback
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.RenderEffectDrawCallback
+import com.android.systemui.surfaceeffects.PaintDrawCallback
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader
 import com.google.common.truth.Truth.assertThat
@@ -50,8 +44,8 @@
         var paintFromCallback: Paint? = null
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {
-                    paintFromCallback = loadingPaint
+                override fun onDraw(paint: Paint) {
+                    paintFromCallback = paint
                 }
             }
         val loadingEffect =
@@ -75,8 +69,8 @@
         var renderEffectFromCallback: RenderEffect? = null
         val drawCallback =
             object : RenderEffectDrawCallback {
-                override fun onDraw(loadingRenderEffect: RenderEffect) {
-                    renderEffectFromCallback = loadingRenderEffect
+                override fun onDraw(renderEffect: RenderEffect) {
+                    renderEffectFromCallback = renderEffect
                 }
             }
         val loadingEffect =
@@ -98,16 +92,19 @@
     @Test
     fun play_animationStateChangesInOrder() {
         val config = TurbulenceNoiseAnimationConfig()
-        val states = mutableListOf(NOT_PLAYING)
+        val states = mutableListOf(LoadingEffect.AnimationState.NOT_PLAYING)
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
                     states.add(newState)
                 }
             }
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         val loadingEffect =
             LoadingEffect(
@@ -125,7 +122,14 @@
         animatorTestRule.advanceTimeBy(config.easeOutDuration.toLong())
         animatorTestRule.advanceTimeBy(500)
 
-        assertThat(states).containsExactly(NOT_PLAYING, EASE_IN, MAIN, EASE_OUT, NOT_PLAYING)
+        assertThat(states)
+            .containsExactly(
+                LoadingEffect.AnimationState.NOT_PLAYING,
+                LoadingEffect.AnimationState.EASE_IN,
+                LoadingEffect.AnimationState.MAIN,
+                LoadingEffect.AnimationState.EASE_OUT,
+                LoadingEffect.AnimationState.NOT_PLAYING
+            )
     }
 
     @Test
@@ -133,16 +137,22 @@
         val config = TurbulenceNoiseAnimationConfig()
         var numPlay = 0
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
-                    if (oldState == NOT_PLAYING && newState == EASE_IN) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (
+                        oldState == LoadingEffect.AnimationState.NOT_PLAYING &&
+                            newState == LoadingEffect.AnimationState.EASE_IN
+                    ) {
                         numPlay++
                     }
                 }
             }
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         val loadingEffect =
             LoadingEffect(
@@ -172,9 +182,15 @@
             }
         var isFinished = false
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
-                    if (oldState == EASE_OUT && newState == NOT_PLAYING) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (
+                        oldState == LoadingEffect.AnimationState.EASE_OUT &&
+                            newState == LoadingEffect.AnimationState.NOT_PLAYING
+                    ) {
                         isFinished = true
                     }
                 }
@@ -205,13 +221,19 @@
         val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         var isFinished = false
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
-                    if (oldState == MAIN && newState == NOT_PLAYING) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (
+                        oldState == LoadingEffect.AnimationState.MAIN &&
+                            newState == LoadingEffect.AnimationState.NOT_PLAYING
+                    ) {
                         isFinished = true
                     }
                 }
@@ -242,7 +264,7 @@
             )
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         val loadingEffect =
             LoadingEffect(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt
new file mode 100644
index 0000000..b1df159
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.surfaceeffects.revealeffect
+
+import android.graphics.RenderEffect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.animation.AnimatorTestRule
+import com.android.systemui.model.SysUiStateTest
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
[email protected](setAsMainLooper = true)
+class RippleRevealEffectTest : SysUiStateTest() {
+
+    @get:Rule val animatorTestRule = AnimatorTestRule(this)
+
+    @Test
+    fun play_triggersDrawCallback() {
+        var effectFromCallback: RenderEffect? = null
+        val revealEffectConfig = RippleRevealEffectConfig(duration = 1000f)
+        val drawCallback =
+            object : RenderEffectDrawCallback {
+                override fun onDraw(renderEffect: RenderEffect) {
+                    effectFromCallback = renderEffect
+                }
+            }
+        val revealEffect = RippleRevealEffect(revealEffectConfig, drawCallback)
+        assertThat(effectFromCallback).isNull()
+
+        revealEffect.play()
+
+        animatorTestRule.advanceTimeBy(500L)
+
+        assertThat(effectFromCallback).isNotNull()
+    }
+
+    @Test
+    fun play_triggersStateChangedCallback() {
+        val revealEffectConfig = RippleRevealEffectConfig(duration = 1000f)
+        val drawCallback =
+            object : RenderEffectDrawCallback {
+                override fun onDraw(renderEffect: RenderEffect) {}
+            }
+        var animationStartedCalled = false
+        var animationEndedCalled = false
+        val stateChangedCallback =
+            object : RippleRevealEffect.AnimationStateChangedCallback {
+                override fun onAnimationStart() {
+                    animationStartedCalled = true
+                }
+
+                override fun onAnimationEnd() {
+                    animationEndedCalled = true
+                }
+            }
+        val revealEffect =
+            RippleRevealEffect(revealEffectConfig, drawCallback, stateChangedCallback)
+
+        assertThat(animationStartedCalled).isFalse()
+        assertThat(animationEndedCalled).isFalse()
+
+        revealEffect.play()
+
+        assertThat(animationStartedCalled).isTrue()
+
+        animatorTestRule.advanceTimeBy(revealEffectConfig.duration.toLong())
+
+        assertThat(animationEndedCalled).isTrue()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
index 28adbce..2cdc8d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
@@ -22,6 +22,8 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.ConfigurationRepositoryImpl
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.display.data.repository.DeviceStateRepository
 import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -31,11 +33,12 @@
 import com.android.systemui.power.shared.model.WakefulnessModel
 import com.android.systemui.power.shared.model.WakefulnessState
 import com.android.systemui.shared.system.SysUiStatsLog
+import com.android.systemui.statusbar.policy.FakeConfigurationController
 import com.android.systemui.unfold.DisplaySwitchLatencyTracker.Companion.FOLDABLE_DEVICE_STATE_CLOSED
 import com.android.systemui.unfold.DisplaySwitchLatencyTracker.Companion.FOLDABLE_DEVICE_STATE_HALF_OPEN
 import com.android.systemui.unfold.DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent
 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl
-import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractorImpl
+import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
 import com.android.systemui.util.animation.data.repository.AnimationStatusRepository
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
@@ -86,11 +89,20 @@
     private val areAnimationEnabled = MutableStateFlow(true)
     private val lastWakefulnessEvent = MutableStateFlow(WakefulnessModel())
     private val systemClock = FakeSystemClock()
-    private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider()
+    private val configurationController = FakeConfigurationController()
+    private val configurationRepository =
+        ConfigurationRepositoryImpl(
+            configurationController,
+            context,
+            testScope.backgroundScope,
+            mock()
+        )
+    private val configurationInteractor = ConfigurationInteractor(configurationRepository)
+    private val unfoldTransitionProgressProvider = FakeUnfoldTransitionProvider()
     private val unfoldTransitionRepository =
         UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider))
     private val unfoldTransitionInteractor =
-        UnfoldTransitionInteractorImpl(unfoldTransitionRepository)
+        UnfoldTransitionInteractor(unfoldTransitionRepository, configurationInteractor)
 
     @Before
     fun setup() {
@@ -155,7 +167,10 @@
     fun unfold_progressUnavailable_logsLatencyTillScreenTurnedOn() {
         testScope.runTest {
             val unfoldTransitionInteractorWithEmptyProgressProvider =
-                UnfoldTransitionInteractorImpl(UnfoldTransitionRepositoryImpl(Optional.empty()))
+                UnfoldTransitionInteractor(
+                    UnfoldTransitionRepositoryImpl(Optional.empty()),
+                    configurationInteractor,
+                )
             displaySwitchLatencyTracker =
                 DisplaySwitchLatencyTracker(
                     mockContext,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt
new file mode 100644
index 0000000..dddc712
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import android.os.PowerManager
+import android.os.SystemProperties
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.foldables.FoldLockSettingAvailabilityProvider
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState
+import com.android.systemui.display.data.repository.fakeDeviceStateRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
+import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setScreenPowerState
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.power.shared.model.ScreenPowerState
+import com.android.systemui.util.animation.data.repository.fakeAnimationStatusRepository
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+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.mockito.Mockito.atLeast
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
[email protected](setAsMainLooper = true)
+@RunWith(AndroidTestingRunner::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class FoldLightRevealOverlayAnimationTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val testScope: TestScope = kosmos.testScope
+    private val fakeDeviceStateRepository = kosmos.fakeDeviceStateRepository
+    private val powerInteractor = kosmos.powerInteractor
+    private val fakeAnimationStatusRepository = kosmos.fakeAnimationStatusRepository
+    private val mockControllerFactory = kosmos.fullscreenLightRevealAnimationControllerFactory
+    private val mockFullScreenController = kosmos.fullscreenLightRevealAnimationController
+    private val mockFoldLockSettingAvailabilityProvider =
+        mock<FoldLockSettingAvailabilityProvider>()
+    private val onOverlayReady = mock<Runnable>()
+    private lateinit var foldLightRevealAnimation: FoldLightRevealOverlayAnimation
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        whenever(mockFoldLockSettingAvailabilityProvider.isFoldLockBehaviorAvailable)
+            .thenReturn(true)
+        fakeAnimationStatusRepository.onAnimationStatusChanged(true)
+
+        foldLightRevealAnimation =
+            FoldLightRevealOverlayAnimation(
+                kosmos.testDispatcher,
+                fakeDeviceStateRepository,
+                powerInteractor,
+                testScope.backgroundScope,
+                fakeAnimationStatusRepository,
+                mockControllerFactory,
+                mockFoldLockSettingAvailabilityProvider
+            )
+        foldLightRevealAnimation.init()
+    }
+
+    @Test
+    fun foldToScreenOn_playFoldAnimation() =
+        testScope.runTest {
+            foldDeviceToScreenOff()
+            turnScreenOn()
+
+            verifyFoldAnimationPlayed()
+        }
+
+    @Test
+    fun foldToAod_doNotPlayFoldAnimation() =
+        testScope.runTest {
+            foldDeviceToScreenOff()
+            emitLastWakefulnessEventStartingToSleep()
+            advanceTimeBy(SHORT_DELAY_MS)
+            turnScreenOn()
+            advanceTimeBy(ANIMATION_DURATION)
+
+            verifyFoldAnimationDidNotPlay()
+        }
+
+    @Test
+    fun foldToScreenOff_doNotPlayFoldAnimation() =
+        testScope.runTest {
+            foldDeviceToScreenOff()
+            emitLastWakefulnessEventStartingToSleep()
+            advanceTimeBy(SHORT_DELAY_MS)
+            advanceTimeBy(ANIMATION_DURATION)
+
+            verifyFoldAnimationDidNotPlay()
+        }
+
+    @Test
+    fun foldToScreenOnWithDelay_doNotPlayFoldAnimation() =
+        testScope.runTest {
+            foldDeviceToScreenOff()
+            foldLightRevealAnimation.onScreenTurningOn {}
+            advanceTimeBy(WAIT_FOR_ANIMATION_TIMEOUT_MS)
+            powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+            advanceTimeBy(SHORT_DELAY_MS)
+            advanceTimeBy(ANIMATION_DURATION)
+
+            verifyFoldAnimationDidNotPlay()
+        }
+
+    @Test
+    fun immediateUnfoldAfterFold_removeOverlayAfterCancellation() =
+        testScope.runTest {
+            foldDeviceToScreenOff()
+            foldLightRevealAnimation.onScreenTurningOn {}
+            advanceTimeBy(SHORT_DELAY_MS)
+            advanceTimeBy(ANIMATION_DURATION)
+            fakeDeviceStateRepository.emit(DeviceState.HALF_FOLDED)
+            advanceTimeBy(SHORT_DELAY_MS)
+            powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+
+            verifyOverlayWasRemoved()
+        }
+
+    @Test
+    fun foldToScreenOn_removeOverlayAfterCompletion() =
+        testScope.runTest {
+            foldDeviceToScreenOff()
+            turnScreenOn()
+            advanceTimeBy(ANIMATION_DURATION)
+
+            verifyOverlayWasRemoved()
+        }
+
+    @Test
+    fun unfold_immediatelyRunRunnable() =
+        testScope.runTest {
+            foldLightRevealAnimation.onScreenTurningOn(onOverlayReady)
+
+            verify(onOverlayReady).run()
+        }
+
+    private suspend fun TestScope.foldDeviceToScreenOff() {
+        fakeDeviceStateRepository.emit(DeviceState.HALF_FOLDED)
+        powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+        advanceTimeBy(SHORT_DELAY_MS)
+        fakeDeviceStateRepository.emit(DeviceState.FOLDED)
+        advanceTimeBy(SHORT_DELAY_MS)
+        powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_OFF)
+        advanceTimeBy(SHORT_DELAY_MS)
+    }
+
+    private fun TestScope.turnScreenOn() {
+        foldLightRevealAnimation.onScreenTurningOn {}
+        advanceTimeBy(SHORT_DELAY_MS)
+        powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
+        advanceTimeBy(SHORT_DELAY_MS)
+    }
+
+    private fun emitLastWakefulnessEventStartingToSleep() =
+        powerInteractor.setAsleepForTest(PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD)
+
+    private fun verifyFoldAnimationPlayed() =
+        verify(mockFullScreenController, atLeast(1)).updateRevealAmount(any())
+
+    private fun verifyFoldAnimationDidNotPlay() =
+        verify(mockFullScreenController, never()).updateRevealAmount(any())
+
+    private fun verifyOverlayWasRemoved() =
+        verify(mockFullScreenController, atLeast(1)).ensureOverlayRemoved()
+
+    private companion object {
+        const val WAIT_FOR_ANIMATION_TIMEOUT_MS = 2000L
+        val ANIMATION_DURATION: Long
+            get() = SystemProperties.getLong("persist.fold_animation_duration", 200L)
+        const val SHORT_DELAY_MS = 50L
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/TestUnfoldTransitionProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/TestUnfoldTransitionProvider.kt
deleted file mode 100644
index 56c6245..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/TestUnfoldTransitionProvider.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.android.systemui.unfold
-
-import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
-
-class TestUnfoldTransitionProvider : UnfoldTransitionProgressProvider, TransitionProgressListener {
-
-    private val listeners = mutableListOf<TransitionProgressListener>()
-
-    override fun destroy() {
-        listeners.clear()
-    }
-
-    override fun addCallback(listener: TransitionProgressListener) {
-        listeners.add(listener)
-    }
-
-    override fun removeCallback(listener: TransitionProgressListener) {
-        listeners.remove(listener)
-    }
-
-    override fun onTransitionStarted() {
-        listeners.forEach { it.onTransitionStarted() }
-    }
-
-    override fun onTransitionFinished() {
-        listeners.forEach { it.onTransitionFinished() }
-    }
-
-    override fun onTransitionFinishing() {
-        listeners.forEach { it.onTransitionFinishing() }
-    }
-
-    override fun onTransitionProgress(progress: Float) {
-        listeners.forEach { it.onTransitionProgress(progress) }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
index b9c7e61..fd513c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
@@ -35,7 +35,7 @@
 @SmallTest
 class UnfoldHapticsPlayerTest : SysuiTestCase() {
 
-    private val progressProvider = TestUnfoldTransitionProvider()
+    private val progressProvider = FakeUnfoldTransitionProvider()
     private val vibrator: Vibrator = mock()
     private val testFoldProvider = TestFoldProvider()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
index ba72716..2955384 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.unfold.util.FoldableDeviceStates
 import com.android.systemui.unfold.util.FoldableTestUtils
 import com.android.systemui.util.mockito.any
+import java.util.Optional
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -37,45 +38,41 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.MockitoAnnotations
-import java.util.Optional
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
 class UnfoldLatencyTrackerTest : SysuiTestCase() {
 
-    @Mock
-    lateinit var latencyTracker: LatencyTracker
+    @Mock lateinit var latencyTracker: LatencyTracker
 
-    @Mock
-    lateinit var deviceStateManager: DeviceStateManager
+    @Mock lateinit var deviceStateManager: DeviceStateManager
 
-    @Mock
-    lateinit var screenLifecycle: ScreenLifecycle
+    @Mock lateinit var screenLifecycle: ScreenLifecycle
 
-    @Captor
-    private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>
+    @Captor private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>
 
-    @Captor
-    private lateinit var screenLifecycleCaptor: ArgumentCaptor<ScreenLifecycle.Observer>
+    @Captor private lateinit var screenLifecycleCaptor: ArgumentCaptor<ScreenLifecycle.Observer>
 
     private lateinit var deviceStates: FoldableDeviceStates
 
     private lateinit var unfoldLatencyTracker: UnfoldLatencyTracker
 
-    private val transitionProgressProvider = TestUnfoldTransitionProvider()
+    private val transitionProgressProvider = FakeUnfoldTransitionProvider()
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        unfoldLatencyTracker = UnfoldLatencyTracker(
-            latencyTracker,
-            deviceStateManager,
-            Optional.of(transitionProgressProvider),
-            context.mainExecutor,
-            context,
-            context.contentResolver,
-            screenLifecycle
-        ).apply { init() }
+        unfoldLatencyTracker =
+            UnfoldLatencyTracker(
+                    latencyTracker,
+                    deviceStateManager,
+                    Optional.of(transitionProgressProvider),
+                    context.mainExecutor,
+                    context,
+                    context.contentResolver,
+                    screenLifecycle
+                )
+                .apply { init() }
         deviceStates = FoldableTestUtils.findDeviceStates(context)
 
         verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture())
@@ -107,7 +104,7 @@
     }
 
     @Test
-    fun unfold_firstFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventNotPropagated() {
+    fun firstFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventNotPropagated() {
         setAnimationsEnabled(true)
         sendFoldEvent(folded = false)
 
@@ -118,7 +115,7 @@
     }
 
     @Test
-    fun unfold_secondFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() {
+    fun secondFoldEventAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() {
         setAnimationsEnabled(true)
         sendFoldEvent(folded = true)
         sendFoldEvent(folded = false)
@@ -131,7 +128,7 @@
     }
 
     @Test
-    fun unfold_unfoldFoldUnfoldAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() {
+    fun unfoldFoldUnfoldAnimationsEnabledOnScreenTurnedOnAndTransitionStarted_eventPropagated() {
         setAnimationsEnabled(true)
         sendFoldEvent(folded = false)
         sendFoldEvent(folded = true)
@@ -196,4 +193,4 @@
             durationScale.toString()
         )
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
index 6ec0251..0c452eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
@@ -17,21 +17,18 @@
 @SmallTest
 class UnfoldTransitionWallpaperControllerTest : SysuiTestCase() {
 
-    @Mock
-    private lateinit var wallpaperController: WallpaperController
+    @Mock private lateinit var wallpaperController: WallpaperController
 
-    private val progressProvider = TestUnfoldTransitionProvider()
+    private val progressProvider = FakeUnfoldTransitionProvider()
 
-    @JvmField
-    @Rule
-    val mockitoRule = MockitoJUnit.rule()
+    @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
 
     private lateinit var unfoldWallpaperController: UnfoldTransitionWallpaperController
 
     @Before
     fun setup() {
-        unfoldWallpaperController = UnfoldTransitionWallpaperController(progressProvider,
-            wallpaperController)
+        unfoldWallpaperController =
+            UnfoldTransitionWallpaperController(progressProvider, wallpaperController)
         unfoldWallpaperController.init()
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt
deleted file mode 100644
index 6a801e0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorTest.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.unfold.domain.interactor
-
-import android.testing.AndroidTestingRunner
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
-import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl
-import com.google.common.truth.Truth.assertThat
-import java.util.Optional
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.async
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.MockitoAnnotations
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-open class UnfoldTransitionInteractorTest : SysuiTestCase() {
-
-    private val testScope = TestScope()
-
-    private val unfoldTransitionProgressProvider = TestUnfoldTransitionProvider()
-    private val unfoldTransitionRepository =
-        UnfoldTransitionRepositoryImpl(Optional.of(unfoldTransitionProgressProvider))
-
-    private lateinit var underTest: UnfoldTransitionInteractor
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        underTest = UnfoldTransitionInteractorImpl(unfoldTransitionRepository)
-    }
-
-    @Test
-    fun waitForTransitionFinish_noEvents_doesNotComplete() =
-        testScope.runTest {
-            val deferred = async { underTest.waitForTransitionFinish() }
-
-            runCurrent()
-
-            assertThat(deferred.isCompleted).isFalse()
-            deferred.cancel()
-        }
-
-    @Test
-    fun waitForTransitionFinish_finishEvent_completes() =
-        testScope.runTest {
-            val deferred = async { underTest.waitForTransitionFinish() }
-
-            runCurrent()
-            unfoldTransitionProgressProvider.onTransitionFinished()
-            runCurrent()
-
-            assertThat(deferred.isCompleted).isTrue()
-            deferred.cancel()
-        }
-
-    @Test
-    fun waitForTransitionFinish_otherEvent_doesNotComplete() =
-        testScope.runTest {
-            val deferred = async { underTest.waitForTransitionFinish() }
-
-            runCurrent()
-            unfoldTransitionProgressProvider.onTransitionStarted()
-            runCurrent()
-
-            assertThat(deferred.isCompleted).isFalse()
-            deferred.cancel()
-        }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt
index 2bc05fc..e5f619b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt
@@ -23,7 +23,7 @@
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.utils.os.FakeHandler
 import kotlin.test.Test
 import kotlinx.coroutines.test.runTest
@@ -34,7 +34,7 @@
 @RunWithLooper(setAsMainLooper = true)
 class MainThreadUnfoldTransitionProgressProviderTest : SysuiTestCase() {
 
-    private val wrappedProgressProvider = TestUnfoldTransitionProvider()
+    private val wrappedProgressProvider = FakeUnfoldTransitionProvider()
     private val fakeHandler = FakeHandler(Looper.getMainLooper())
     private val listener = TestUnfoldProgressListener()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
index d864d53..70ec050 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
@@ -20,7 +20,7 @@
 import android.view.Surface
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
 import com.android.systemui.unfold.updates.RotationChangeProvider
 import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
@@ -43,14 +43,14 @@
 
     @Mock lateinit var rotationChangeProvider: RotationChangeProvider
 
-    private val sourceProvider = TestUnfoldTransitionProvider()
+    private val sourceProvider = FakeUnfoldTransitionProvider()
 
     @Mock lateinit var transitionListener: TransitionProgressListener
 
     @Captor private lateinit var rotationListenerCaptor: ArgumentCaptor<RotationListener>
 
     lateinit var progressProvider: NaturalRotationUnfoldProgressProvider
-    private lateinit var testableLooper : TestableLooper
+    private lateinit var testableLooper: TestableLooper
 
     @Before
     fun setUp() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
index 2f29b3b..451bd24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
@@ -22,7 +22,7 @@
 import android.testing.TestableLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
 import com.android.systemui.util.mockito.any
 import org.junit.Before
@@ -42,7 +42,7 @@
 
     @Mock lateinit var sinkProvider: TransitionProgressListener
 
-    private val sourceProvider = TestUnfoldTransitionProvider()
+    private val sourceProvider = FakeUnfoldTransitionProvider()
 
     private lateinit var contentResolver: ContentResolver
     private lateinit var progressProvider: ScaleAwareTransitionProgressProvider
@@ -132,6 +132,6 @@
             durationScale.toString()
         )
 
-        animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */false)
+        animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */ false)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt
index 95c934e..4486402 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt
@@ -23,7 +23,7 @@
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.unfold.progress.TestUnfoldProgressListener
 import com.google.common.truth.Truth.assertThat
 import kotlin.time.Duration.Companion.seconds
@@ -43,7 +43,7 @@
 @RunWithLooper
 class ScopedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
 
-    private val rootProvider = TestUnfoldTransitionProvider()
+    private val rootProvider = FakeUnfoldTransitionProvider()
     private val listener = TestUnfoldProgressListener()
     private val testScope = TestScope(UnconfinedTestDispatcher())
     private val bgThread =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt
index f484ea0..cd4d7b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt
@@ -19,7 +19,7 @@
 import android.testing.TestableLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.FakeUnfoldTransitionProvider
 import com.android.systemui.unfold.progress.TestUnfoldProgressListener
 import com.google.common.util.concurrent.MoreExecutors
 import org.junit.Before
@@ -32,7 +32,7 @@
 class UnfoldOnlyProgressProviderTest : SysuiTestCase() {
 
     private val listener = TestUnfoldProgressListener()
-    private val sourceProvider = TestUnfoldTransitionProvider()
+    private val sourceProvider = FakeUnfoldTransitionProvider()
 
     private val foldProvider = TestFoldProvider()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
index a85ae7df..35f9c41 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
@@ -3,7 +3,7 @@
 import android.content.pm.UserInfo
 import android.graphics.Bitmap
 import android.os.UserManager
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/NotificationChannelsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/NotificationChannelsTest.java
index 900d792..2436725 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/NotificationChannelsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/NotificationChannelsTest.java
@@ -22,9 +22,9 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.Context;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java
index b10f16c..ab52c34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java
@@ -25,9 +25,10 @@
 import static org.mockito.Mockito.when;
 
 import android.hardware.Sensor;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.concurrency.FakeExecution;
 import com.android.systemui.util.concurrency.FakeExecutor;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java
index b0bd83e..741b2e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java
@@ -27,10 +27,11 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.media.AudioManager;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.concurrency.FakeExecutor;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
index fb82b8f..483dc0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
@@ -15,14 +15,14 @@
  */
 package com.android.systemui.volume;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.media.MediaMetadata;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 
-import junit.framework.Assert;
-
 import org.junit.Test;
 
 @SmallTest
@@ -30,11 +30,59 @@
 
     @Test
     public void testMediaMetadataToString_null() {
-        Assert.assertEquals(null, Util.mediaMetadataToString(null));
+        assertThat(Util.mediaMetadataToString(null)).isNull();
     }
 
     @Test
     public void testMediaMetadataToString_notNull() {
-        Assert.assertNotNull(Util.mediaMetadataToString(new MediaMetadata.Builder().build()));
+        assertThat(Util.mediaMetadataToString(new MediaMetadata.Builder().build())).isNotNull();
+    }
+
+    @Test
+    public void translateToRange_translatesStartToStart() {
+        assertThat(
+                (int) Util.translateToRange(
+                        /* value= */ 0,
+                        /* valueRangeStart= */ 0,
+                        /* valueRangeEnd= */ 7,
+                        /* targetRangeStart= */ 0,
+                        /* targetRangeEnd= */700)
+        ).isEqualTo(0);
+    }
+
+    @Test
+    public void translateToRange_translatesValueToValue() {
+        assertThat(
+                (int) Util.translateToRange(
+                        /* value= */ 4,
+                        /* valueRangeStart= */ 0,
+                        /* valueRangeEnd= */ 7,
+                        /* targetRangeStart= */ 0,
+                        /* targetRangeEnd= */700)
+        ).isEqualTo(400);
+    }
+
+    @Test
+    public void translateToRange_translatesEndToEnd() {
+        assertThat(
+                (int) Util.translateToRange(
+                        /* value= */ 7,
+                        /* valueRangeStart= */ 0,
+                        /* valueRangeEnd= */ 7,
+                        /* targetRangeStart= */ 0,
+                        /* targetRangeEnd= */700)
+        ).isEqualTo(700);
+    }
+
+    @Test
+    public void translateToRange_returnsStartForEmptyRange() {
+        assertThat(
+                (int) Util.translateToRange(
+                        /* value= */ 7,
+                        /* valueRangeStart= */ 7,
+                        /* valueRangeEnd= */ 7,
+                        /* targetRangeStart= */ 700,
+                        /* targetRangeEnd= */700)
+        ).isEqualTo(700);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 11a53f75..3b468aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -65,6 +65,7 @@
 import android.widget.SeekBar;
 
 import androidx.test.core.view.MotionEventBuilder;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.jank.InteractionJankMonitor;
@@ -247,6 +248,8 @@
             VolumeDialogController.StreamState ss = new VolumeDialogController.StreamState();
             ss.name = STREAMS.get(i);
             ss.level = 1;
+            ss.levelMin = 0;
+            ss.levelMax = 25;
             state.states.append(i, ss);
         }
         return state;
@@ -293,7 +296,7 @@
         mTestableLooper.processAllMessages();
     }
 
-    @Test
+    @Test @FlakyTest(bugId = 329099861)
     @EnableFlags(FLAG_HAPTIC_VOLUME_SLIDER)
     public void testVolumeChange_withSliderHaptics_deliversOnProgressChangedHapticsEagerly() {
         // create haptic plugins on the rows with the flag enabled
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java
index 1125d41..0eba21a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java
@@ -16,9 +16,12 @@
 
 package com.android.systemui.wallpapers;
 
+import static com.android.window.flags.Flags.FLAG_OFFLOAD_COLOR_EXTRACTION;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
@@ -32,6 +35,7 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.platform.test.annotations.EnableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -77,6 +81,7 @@
     private Executor mBackgroundExecutor;
 
     private int mColorsProcessed;
+    private int mLocalColorsProcessed;
     private int mMiniBitmapUpdatedCount;
     private int mActivatedCount;
     private int mDeactivatedCount;
@@ -93,6 +98,7 @@
 
     private void resetCounters() {
         mColorsProcessed = 0;
+        mLocalColorsProcessed = 0;
         mMiniBitmapUpdatedCount = 0;
         mActivatedCount = 0;
         mDeactivatedCount = 0;
@@ -112,10 +118,14 @@
                 new Object(),
                 new WallpaperLocalColorExtractor.WallpaperLocalColorExtractorCallback() {
                     @Override
+                    public void onColorsProcessed() {
+                        mColorsProcessed++;
+                    }
+                    @Override
                     public void onColorsProcessed(List<RectF> regions,
                             List<WallpaperColors> colors) {
                         assertThat(regions.size()).isEqualTo(colors.size());
-                        mColorsProcessed += regions.size();
+                        mLocalColorsProcessed += regions.size();
                     }
 
                     @Override
@@ -148,8 +158,10 @@
                 .when(spyColorExtractor)
                 .createMiniBitmap(any(Bitmap.class), anyInt(), anyInt());
 
-        doReturn(new WallpaperColors(Color.valueOf(0), Color.valueOf(0), Color.valueOf(0)))
-                .when(spyColorExtractor).getLocalWallpaperColors(any(Rect.class));
+        WallpaperColors colors = new WallpaperColors(
+                Color.valueOf(0), Color.valueOf(0), Color.valueOf(0));
+        doReturn(colors).when(spyColorExtractor).getLocalWallpaperColors(any(Rect.class));
+        doReturn(colors).when(spyColorExtractor).getWallpaperColors(any(Bitmap.class), anyFloat());
 
         return spyColorExtractor;
     }
@@ -244,7 +256,7 @@
 
             assertThat(mActivatedCount).isEqualTo(1);
             assertThat(mMiniBitmapUpdatedCount).isEqualTo(1);
-            assertThat(mColorsProcessed).isEqualTo(regions.size());
+            assertThat(mLocalColorsProcessed).isEqualTo(regions.size());
 
             spyColorExtractor.removeLocalColorAreas(regions);
             assertThat(mDeactivatedCount).isEqualTo(1);
@@ -329,12 +341,69 @@
                 spyColorExtractor.onBitmapChanged(newBitmap);
                 assertThat(mMiniBitmapUpdatedCount).isEqualTo(1);
             }
-            assertThat(mColorsProcessed).isEqualTo(regions.size());
+            assertThat(mLocalColorsProcessed).isEqualTo(regions.size());
         }
         spyColorExtractor.removeLocalColorAreas(regions);
         assertThat(mDeactivatedCount).isEqualTo(1);
     }
 
+    /**
+     * Test that after the bitmap changes, the colors are computed only if asked via onComputeColors
+     */
+    @Test
+    @EnableFlags(FLAG_OFFLOAD_COLOR_EXTRACTION)
+    public void testRecomputeColors() {
+        resetCounters();
+        Bitmap bitmap = getMockBitmap(HIGH_BMP_WIDTH, HIGH_BMP_HEIGHT);
+        WallpaperLocalColorExtractor spyColorExtractor = getSpyWallpaperLocalColorExtractor();
+        spyColorExtractor.onBitmapChanged(bitmap);
+        assertThat(mColorsProcessed).isEqualTo(0);
+        spyColorExtractor.onComputeColors();
+        assertThat(mColorsProcessed).isEqualTo(1);
+    }
+
+    /**
+     * Test that after onComputeColors is called, the colors are computed once the bitmap is loaded
+     */
+    @Test
+    @EnableFlags(FLAG_OFFLOAD_COLOR_EXTRACTION)
+    public void testRecomputeColorsBeforeBitmapLoaded() {
+        resetCounters();
+        Bitmap bitmap = getMockBitmap(HIGH_BMP_WIDTH, HIGH_BMP_HEIGHT);
+        WallpaperLocalColorExtractor spyColorExtractor = getSpyWallpaperLocalColorExtractor();
+        spyColorExtractor.onComputeColors();
+        spyColorExtractor.onBitmapChanged(bitmap);
+        assertThat(mColorsProcessed).isEqualTo(1);
+    }
+
+    /**
+     * Test that after the dim changes, the colors are computed if the bitmap is already loaded
+     */
+    @Test
+    @EnableFlags(FLAG_OFFLOAD_COLOR_EXTRACTION)
+    public void testRecomputeColorsOnDimChanged() {
+        resetCounters();
+        Bitmap bitmap = getMockBitmap(HIGH_BMP_WIDTH, HIGH_BMP_HEIGHT);
+        WallpaperLocalColorExtractor spyColorExtractor = getSpyWallpaperLocalColorExtractor();
+        spyColorExtractor.onBitmapChanged(bitmap);
+        spyColorExtractor.onDimAmountChanged(0.5f);
+        assertThat(mColorsProcessed).isEqualTo(1);
+    }
+
+    /**
+     * Test that after the dim changes, the colors will be recomputed once the bitmap is loaded
+     */
+    @Test
+    @EnableFlags(FLAG_OFFLOAD_COLOR_EXTRACTION)
+    public void testRecomputeColorsOnDimChangedBeforeBitmapLoaded() {
+        resetCounters();
+        Bitmap bitmap = getMockBitmap(HIGH_BMP_WIDTH, HIGH_BMP_HEIGHT);
+        WallpaperLocalColorExtractor spyColorExtractor = getSpyWallpaperLocalColorExtractor();
+        spyColorExtractor.onDimAmountChanged(0.3f);
+        spyColorExtractor.onBitmapChanged(bitmap);
+        assertThat(mColorsProcessed).isEqualTo(1);
+    }
+
     @Test
     public void testCleanUp() {
         resetCounters();
@@ -346,6 +415,6 @@
         assertThat(mMiniBitmapUpdatedCount).isEqualTo(1);
         spyColorExtractor.cleanUp();
         spyColorExtractor.addLocalColorsAreas(listOfRandomAreas(MIN_AREAS, MAX_AREAS));
-        assertThat(mColorsProcessed).isEqualTo(0);
+        assertThat(mLocalColorsProcessed).isEqualTo(0);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index aabd4e9..d9a0c4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -121,8 +121,6 @@
 import com.android.systemui.scene.FakeWindowRootViewComponent;
 import com.android.systemui.scene.data.repository.SceneContainerRepository;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
-import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scene.shared.logger.SceneLogger;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.settings.UserTracker;
@@ -174,6 +172,7 @@
 import com.android.systemui.user.domain.interactor.UserSwitcherInteractor;
 import com.android.systemui.util.FakeEventLog;
 import com.android.systemui.util.settings.FakeGlobalSettings;
+import com.android.systemui.util.settings.SystemSettings;
 import com.android.systemui.util.time.SystemClock;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.WindowManagerShellWrapper;
@@ -359,8 +358,6 @@
     @Mock
     private Display mDefaultDisplay;
     @Mock
-    private SceneContainerFlags mSceneContainerFlags;
-    @Mock
     private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
 
     private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
@@ -429,14 +426,12 @@
                 mock(SceneLogger.class),
                 mKosmos.getDeviceUnlockedInteractor());
 
-        FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags();
         KeyguardTransitionInteractor keyguardTransitionInteractor =
                 mKosmos.getKeyguardTransitionInteractor();
         KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
                 keyguardRepository,
                 new FakeCommandQueue(),
                 powerInteractor,
-                sceneContainerFlags,
                 new FakeKeyguardBouncerRepository(),
                 new ConfigurationInteractor(configurationRepository),
                 shadeRepository,
@@ -502,7 +497,6 @@
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
                 mUserTracker,
-                mSceneContainerFlags,
                 mKosmos::getCommunalInteractor
         );
         mNotificationShadeWindowController.fetchWindowRootView();
@@ -554,7 +548,8 @@
                         mock(SystemClock.class),
                         mock(UiEventLogger.class),
                         mock(UserTracker.class),
-                        mock(AvalancheProvider.class)
+                        mock(AvalancheProvider.class),
+                        mock(SystemSettings.class)
                         );
         interruptionDecisionProvider.start();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
deleted file mode 100644
index d2c8aea..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.wmshell;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.notetask.NoteTaskInitializer;
-import com.android.systemui.settings.FakeDisplayTracker;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.desktopmode.DesktopMode;
-import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
-import com.android.wm.shell.onehanded.OneHanded;
-import com.android.wm.shell.onehanded.OneHandedEventCallback;
-import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
-import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.recents.RecentTasks;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.sysui.ShellInterface;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Optional;
-import java.util.concurrent.Executor;
-
-/**
- * Tests for {@link WMShell}.
- *
- * Build/Install/Run:
- *  atest SystemUITests:WMShellTest
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class WMShellTest extends SysuiTestCase {
-    WMShell mWMShell;
-
-    @Mock ShellInterface mShellInterface;
-    @Mock CommandQueue mCommandQueue;
-    @Mock ConfigurationController mConfigurationController;
-    @Mock KeyguardStateController mKeyguardStateController;
-    @Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    @Mock ScreenLifecycle mScreenLifecycle;
-    @Mock SysUiState mSysUiState;
-    @Mock Pip mPip;
-    @Mock SplitScreen mSplitScreen;
-    @Mock OneHanded mOneHanded;
-    @Mock WakefulnessLifecycle mWakefulnessLifecycle;
-    @Mock UserTracker mUserTracker;
-    @Mock ShellExecutor mSysUiMainExecutor;
-    @Mock NoteTaskInitializer mNoteTaskInitializer;
-    @Mock DesktopMode mDesktopMode;
-    @Mock RecentTasks mRecentTasks;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeDisplayTracker displayTracker = new FakeDisplayTracker(mContext);
-        mWMShell = new WMShell(
-                mContext,
-                mShellInterface,
-                Optional.of(mPip),
-                Optional.of(mSplitScreen),
-                Optional.of(mOneHanded),
-                Optional.of(mDesktopMode),
-                Optional.of(mRecentTasks),
-                mCommandQueue,
-                mConfigurationController,
-                mKeyguardStateController,
-                mKeyguardUpdateMonitor,
-                mScreenLifecycle,
-                mSysUiState,
-                mWakefulnessLifecycle,
-                mUserTracker,
-                displayTracker,
-                mNoteTaskInitializer,
-                mSysUiMainExecutor
-        );
-    }
-
-    @Test
-    public void initPip_registersCommandQueueCallback() {
-        mWMShell.initPip(mPip);
-
-        verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
-    }
-
-    @Test
-    public void initOneHanded_registersCallbacks() {
-        mWMShell.initOneHanded(mOneHanded);
-
-        verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
-        verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class));
-        verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class));
-        verify(mOneHanded).registerEventCallback(any(OneHandedEventCallback.class));
-    }
-
-    @Test
-    public void initDesktopMode_registersListener() {
-        mWMShell.initDesktopMode(mDesktopMode);
-        verify(mDesktopMode).addVisibleTasksListener(
-                any(DesktopModeTaskRepository.VisibleTasksListener.class),
-                any(Executor.class));
-    }
-
-    @Test
-    public void initRecentTasks_registersListener() {
-        mWMShell.initRecentTasks(mRecentTasks);
-        verify(mRecentTasks).addAnimationStateListener(any(Executor.class), any());
-    }
-}
diff --git a/packages/SystemUI/tests/utils/src/android/os/LooperKosmos.kt b/packages/SystemUI/tests/utils/src/android/os/LooperKosmos.kt
index a8ca9bfc..4303365 100644
--- a/packages/SystemUI/tests/utils/src/android/os/LooperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/android/os/LooperKosmos.kt
@@ -22,7 +22,12 @@
 import com.android.systemui.kosmos.testCase
 
 val Kosmos.looper by Fixture {
-    checkNotNull(TestableLooper.get(testCase).looper) {
-        "TestableLooper is returning null, make sure the test class is annotated with RunWithLooper"
+    val testableLooper = TestableLooper.get(testCase)
+    checkNotNull(testableLooper) {
+        "TestableLooper is null, make sure the test class is annotated with RunWithLooper"
+    }
+    checkNotNull(testableLooper.looper) {
+        "TestableLooper.getLooper() is returning null, make sure the test class is annotated " +
+            "with RunWithLooper"
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt
index 7185b7c..96c4c45 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt
@@ -18,5 +18,7 @@
 
 import android.content.applicationContext
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-val Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) }
+val Kosmos.mockActivityIntentHelper by Kosmos.Fixture { mock<ActivityIntentHelper>() }
+var Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt
index de7b14d..42b6e18 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysUITestModule.kt
@@ -30,8 +30,9 @@
 import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfigModule
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor
+import com.android.systemui.keyguard.ui.composable.blueprint.DefaultBlueprintModule
 import com.android.systemui.scene.SceneContainerFrameworkModule
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.SceneDataSource
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
@@ -60,6 +61,7 @@
             TestMocksModule::class,
             CoroutineTestScopeModule::class,
             FakeSystemUiModule::class,
+            DefaultBlueprintModule::class,
             SceneContainerFrameworkModule::class,
             FaceWakeUpTriggersConfigModule::class,
         ]
@@ -104,11 +106,10 @@
 
         @Provides
         fun provideBaseShadeInteractor(
-            sceneContainerFlags: SceneContainerFlags,
             sceneContainerOn: Provider<ShadeInteractorSceneContainerImpl>,
             sceneContainerOff: Provider<ShadeInteractorLegacyImpl>
         ): BaseShadeInteractor {
-            return if (sceneContainerFlags.isEnabled()) {
+            return if (SceneContainerFlag.isEnabled) {
                 sceneContainerOn.get()
             } else {
                 sceneContainerOff.get()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 353d9709b..9dcd946 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -177,7 +177,7 @@
         // TODO(b/292141694): build out Ravenwood support for Instrumentation
         // Ravenwood doesn't yet provide Instrumentation, so we sidestep this global configuration
         // step; any tests that rely on it are already being excluded on Ravenwood
-        if (!isRavenwoodTest()) {
+        if (!isRavenwoodTest() && !isScreenshotTest()) {
             mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
             Instrumentation inst = spy(mRealInstrumentation);
             when(inst.getContext()).thenAnswer(invocation -> {
@@ -288,6 +288,10 @@
         return !isRavenwoodTest() && Build.FINGERPRINT.contains("robolectric");
     }
 
+    protected boolean isScreenshotTest() {
+        return false;
+    }
+
     public static boolean isRavenwoodTest() {
         return RavenwoodRule.isOnRavenwood();
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestDependency.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestDependency.kt
index 7bb4218..4e6a7a9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestDependency.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestDependency.kt
@@ -4,7 +4,6 @@
 import android.os.Looper
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.animation.fakeDialogTransitionAnimator
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.broadcast.FakeBroadcastDispatcher
 import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
@@ -39,10 +38,7 @@
         // Ravenwood doesn't yet provide UI animations, so we sidestep this global configuration
         // step; any tests that rely on it are already being excluded under Ravenwood
         if (!SysuiTestCase.isRavenwoodTest()) {
-            dependency.injectTestDependency(
-                DialogTransitionAnimator::class.java,
-                fakeDialogTransitionAnimator()
-            )
+            dependency.injectMockDependency(DialogTransitionAnimator::class.java)
         }
 
         // Many tests end up creating a BroadcastDispatcher. Instead, give them a fake that will
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt
index 65dd411d..9dae44d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt
@@ -24,6 +24,7 @@
 import android.view.LayoutInflater
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.statusbar.IStatusBarService
+import com.android.internal.widget.LockPatternUtils
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardViewController
@@ -152,6 +153,7 @@
     @get:Provides val displayMetrics: DisplayMetrics = mock(),
     @get:Provides val metricsLogger: MetricsLogger = mock(),
     @get:Provides val userManager: UserManager = mock(),
+    @get:Provides val lockPatternUtils: LockPatternUtils = mock(),
 
     // system server mocks
     @get:Provides val mockStatusBarService: IStatusBarService = mock(),
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/FakeReduceBrightColorsController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/FakeReduceBrightColorsController.kt
new file mode 100644
index 0000000..8b0affe2
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/FakeReduceBrightColorsController.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility
+
+import com.android.systemui.qs.ReduceBrightColorsController
+
+class FakeReduceBrightColorsController : ReduceBrightColorsController {
+
+    private var isEnabled = false
+
+    private val callbacks = LinkedHashSet<ReduceBrightColorsController.Listener>()
+
+    override fun addCallback(listener: ReduceBrightColorsController.Listener) {
+        callbacks.add(listener)
+    }
+
+    override fun removeCallback(listener: ReduceBrightColorsController.Listener) {
+        callbacks.remove(listener)
+    }
+
+    override fun isReduceBrightColorsActivated(): Boolean {
+        return isEnabled
+    }
+
+    override fun setReduceBrightColorsActivated(activated: Boolean) {
+        if (activated != isEnabled) {
+            isEnabled = activated
+            for (callback in callbacks) {
+                callback.onActivated(activated)
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/ReduceBrightColorsControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/ReduceBrightColorsControllerKosmos.kt
new file mode 100644
index 0000000..5bbe3bf
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/ReduceBrightColorsControllerKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.ReduceBrightColorsController
+
+var Kosmos.reduceBrightColorsController: ReduceBrightColorsController by
+    Kosmos.Fixture { fakeReduceBrightColorsController }
+val Kosmos.fakeReduceBrightColorsController by Kosmos.Fixture { FakeReduceBrightColorsController() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/DialogTransitionAnimatorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/DialogTransitionAnimatorKosmos.kt
index ed291d1..77cb167 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/DialogTransitionAnimatorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/DialogTransitionAnimatorKosmos.kt
@@ -16,7 +16,10 @@
 
 package com.android.systemui.animation
 
+import com.android.systemui.jank.interactionJankMonitor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 
-val Kosmos.dialogTransitionAnimator by Fixture { fakeDialogTransitionAnimator() }
+val Kosmos.dialogTransitionAnimator by Fixture {
+    fakeDialogTransitionAnimator(interactionJankMonitor = interactionJankMonitor)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt
index 7c5bb12..48b72d0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt
@@ -15,15 +15,15 @@
 package com.android.systemui.animation
 
 import com.android.internal.jank.InteractionJankMonitor
-import org.mockito.Mockito.mock
+import com.android.systemui.jank.interactionJankMonitor
 
 /** A [DialogTransitionAnimator] to be used in tests. */
 @JvmOverloads
 fun fakeDialogTransitionAnimator(
     isUnlocked: Boolean = true,
     isShowingAlternateAuthOnUnlock: Boolean = false,
-    interactionJankMonitor: InteractionJankMonitor = mock(InteractionJankMonitor::class.java),
     isPredictiveBackQsDialogAnim: Boolean = false,
+    interactionJankMonitor: InteractionJankMonitor,
 ): DialogTransitionAnimator {
     return DialogTransitionAnimator(
         callback =
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
index a6dd3cd..219794f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
@@ -32,6 +32,8 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.currentTime
 
@@ -68,6 +70,8 @@
 
     var lockoutStartedReportCount = 0
 
+    private val credentialCheckingMutex = Mutex(locked = false)
+
     override suspend fun getAuthenticationMethod(): AuthenticationMethodModel {
         return authenticationMethod.value
     }
@@ -124,30 +128,32 @@
     override suspend fun checkCredential(
         credential: LockscreenCredential
     ): AuthenticationResultModel {
-        val expectedCredential = credentialOverride ?: getExpectedCredential(securityMode)
-        val isSuccessful =
-            when {
-                credential.type != getCurrentCredentialType(securityMode) -> false
-                credential.type == LockPatternUtils.CREDENTIAL_TYPE_PIN ->
-                    credential.isPin && credential.matches(expectedCredential)
-                credential.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ->
-                    credential.isPassword && credential.matches(expectedCredential)
-                credential.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN ->
-                    credential.isPattern && credential.matches(expectedCredential)
-                else -> error("Unexpected credential type ${credential.type}!")
-            }
+        return credentialCheckingMutex.withLock {
+            val expectedCredential = credentialOverride ?: getExpectedCredential(securityMode)
+            val isSuccessful =
+                when {
+                    credential.type != getCurrentCredentialType(securityMode) -> false
+                    credential.type == LockPatternUtils.CREDENTIAL_TYPE_PIN ->
+                        credential.isPin && credential.matches(expectedCredential)
+                    credential.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ->
+                        credential.isPassword && credential.matches(expectedCredential)
+                    credential.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN ->
+                        credential.isPattern && credential.matches(expectedCredential)
+                    else -> error("Unexpected credential type ${credential.type}!")
+                }
 
-        val failedAttempts = _failedAuthenticationAttempts.value
-        return if (isSuccessful || failedAttempts < MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) {
-            AuthenticationResultModel(
-                isSuccessful = isSuccessful,
-                lockoutDurationMs = 0,
-            )
-        } else {
-            AuthenticationResultModel(
-                isSuccessful = false,
-                lockoutDurationMs = LOCKOUT_DURATION_MS,
-            )
+            val failedAttempts = _failedAuthenticationAttempts.value
+            if (isSuccessful || failedAttempts < MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) {
+                AuthenticationResultModel(
+                    isSuccessful = isSuccessful,
+                    lockoutDurationMs = 0,
+                )
+            } else {
+                AuthenticationResultModel(
+                    isSuccessful = false,
+                    lockoutDurationMs = LOCKOUT_DURATION_MS,
+                )
+            }
         }
     }
 
@@ -155,6 +161,23 @@
         _isPinEnhancedPrivacyEnabled.value = isEnabled
     }
 
+    /**
+     * Pauses any future credential checking. The test must call [unpauseCredentialChecking] to
+     * flush the accumulated credential checks.
+     */
+    suspend fun pauseCredentialChecking() {
+        credentialCheckingMutex.lock()
+    }
+
+    /**
+     * Unpauses future credential checking, if it was paused using [pauseCredentialChecking]. This
+     * doesn't flush any pending coroutine jobs; the test code may still choose to do that using
+     * `runCurrent`.
+     */
+    fun unpauseCredentialChecking() {
+        credentialCheckingMutex.unlock()
+    }
+
     private fun getExpectedCredential(securityMode: SecurityMode): List<Any> {
         return when (val credentialType = getCurrentCredentialType(securityMode)) {
             LockPatternUtils.CREDENTIAL_TYPE_PIN -> credentialOverride ?: DEFAULT_PIN
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
index 8a95136..65eb338 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
@@ -20,6 +20,7 @@
 import android.graphics.Point
 import com.android.systemui.biometrics.shared.model.LockoutMode
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.DevicePosture
 import dagger.Binds
 import dagger.Module
 import javax.inject.Inject
@@ -42,6 +43,8 @@
     override val cameraInfo: StateFlow<CameraInfo?>
         get() = currentCameraInfo
 
+    override val supportedPostures: List<DevicePosture> = listOf(DevicePosture.CLOSED)
+
     fun setLockoutMode(userId: Int, mode: LockoutMode) {
         lockoutModesForUser[userId] = mode
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorKosmos.kt
index 1493f14..081e89b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorKosmos.kt
@@ -18,12 +18,14 @@
 
 import com.android.app.activityTaskManager
 import com.android.systemui.biometrics.data.repository.biometricStatusRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 
 val Kosmos.biometricStatusInteractor by Fixture {
     BiometricStatusInteractorImpl(
         activityTaskManager = activityTaskManager,
-        biometricStatusRepository = biometricStatusRepository
+        biometricStatusRepository = biometricStatusRepository,
+        fingerprintPropertyRepository = fingerprintPropertyRepository
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt
index 8b1a1d9..e2386a6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelKosmos.kt
@@ -16,11 +16,13 @@
 
 package com.android.systemui.biometrics.ui.viewmodel
 
+import com.android.keyguard.logging.DeviceEntryIconLogger
 import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
 import com.android.systemui.keyguard.ui.viewmodel.deviceEntryIconViewModel
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.statusbar.phone.systemUIDialogManager
+import com.android.systemui.util.mockito.mock
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 @ExperimentalCoroutinesApi
@@ -29,5 +31,6 @@
         deviceEntryIconViewModel = deviceEntryIconViewModel,
         alternateBouncerInteractor = alternateBouncerInteractor,
         systemUIDialogManager = systemUIDialogManager,
+        logger = mock<DeviceEntryIconLogger>(),
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt
index 9cbe633..2ae6f542 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelKosmos.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.biometrics.ui.viewmodel
 
 import android.content.applicationContext
+import com.android.systemui.biometrics.domain.interactor.biometricStatusInteractor
 import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.promptSelectorInteractor
 import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor
@@ -30,6 +31,7 @@
         promptSelectorInteractor = promptSelectorInteractor,
         context = applicationContext,
         udfpsOverlayInteractor = udfpsOverlayInteractor,
+        biometricStatusInteractor = biometricStatusInteractor,
         udfpsUtils = udfpsUtils
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BluetoothAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BluetoothAdapterKosmos.kt
new file mode 100644
index 0000000..854548c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BluetoothAdapterKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth
+
+import android.bluetooth.BluetoothAdapter
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+var Kosmos.bluetoothAdapter: BluetoothAdapter by Kosmos.Fixture { mock {} }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt
new file mode 100644
index 0000000..e9d7266
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BroadcastDialogControllerKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.mockBroadcastDialogController by Kosmos.Fixture { mock<BroadcastDialogController>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/CachedBluetoothDeviceManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/CachedBluetoothDeviceManagerKosmos.kt
new file mode 100644
index 0000000..07f0995
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/CachedBluetoothDeviceManagerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth
+
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+var Kosmos.cachedBluetoothDeviceManager: CachedBluetoothDeviceManager by Kosmos.Fixture { mock {} }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/LocalBluetoothManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/LocalBluetoothManagerKosmos.kt
new file mode 100644
index 0000000..eef89e7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/LocalBluetoothManagerKosmos.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bluetooth
+
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+
+var Kosmos.localBluetoothManager: LocalBluetoothManager? by
+    Kosmos.Fixture {
+        mock { whenever(cachedDeviceManager).thenReturn(cachedBluetoothDeviceManager) }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
index 8010261..baaf604 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
@@ -1,6 +1,6 @@
 package com.android.systemui.bouncer.data.repository
 
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
+import com.android.keyguard.KeyguardSecurityModel
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel
 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
@@ -11,7 +11,6 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asStateFlow
 
@@ -52,8 +51,8 @@
     override var lastAlternateBouncerVisibleTime: Long = 0L
     private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
     override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
-    private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
+    override val lastShownSecurityMode: MutableStateFlow<KeyguardSecurityModel.SecurityMode> =
+        MutableStateFlow(KeyguardSecurityModel.SecurityMode.Invalid)
     override var bouncerDismissActionModel: BouncerDismissActionModel? = null
 
     override fun setPrimaryScrimmed(isScrimmed: Boolean) {
@@ -116,10 +115,8 @@
         _isBackButtonEnabled.value = isBackButtonEnabled
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    override fun setSideFpsShowing(isShowing: Boolean) {
-        SideFpsControllerRefactor.assertInLegacyMode()
-        _sideFpsShowing.value = isShowing
+    override fun setLastShownSecurityMode(securityMode: KeyguardSecurityModel.SecurityMode) {
+        lastShownSecurityMode.value = securityMode
     }
 }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt
index c0655457..4a02f6d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.bouncer.domain.interactor
 
+import com.android.internal.logging.uiEventLogger
 import com.android.systemui.authentication.domain.interactor.authenticationInteractor
 import com.android.systemui.bouncer.data.repository.bouncerRepository
 import com.android.systemui.classifier.domain.interactor.falsingInteractor
@@ -23,7 +24,9 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.log.sessionTracker
 import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 
 val Kosmos.bouncerInteractor by Fixture {
     BouncerInteractor(
@@ -33,5 +36,8 @@
         deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
         falsingInteractor = falsingInteractor,
         powerInteractor = powerInteractor,
+        uiEventLogger = uiEventLogger,
+        sessionTracker = sessionTracker,
+        sceneInteractor = sceneInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt
index 5c3e1f4..60d97d1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlagsKosmos.kt
@@ -17,8 +17,6 @@
 package com.android.systemui.bouncer.shared.flag
 
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 
-var Kosmos.fakeComposeBouncerFlags by
-    Kosmos.Fixture { FakeComposeBouncerFlags(fakeSceneContainerFlags) }
+var Kosmos.fakeComposeBouncerFlags by Kosmos.Fixture { FakeComposeBouncerFlags() }
 val Kosmos.composeBouncerFlags by Kosmos.Fixture<ComposeBouncerFlags> { fakeComposeBouncerFlags }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt
index c116bbd..7482c0f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/shared/flag/FakeComposeBouncerFlags.kt
@@ -16,14 +16,11 @@
 
 package com.android.systemui.bouncer.shared.flag
 
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 
-class FakeComposeBouncerFlags(
-    private val sceneContainerFlags: SceneContainerFlags,
-    var composeBouncerEnabled: Boolean = false
-) : ComposeBouncerFlags {
+class FakeComposeBouncerFlags(var composeBouncerEnabled: Boolean = false) : ComposeBouncerFlags {
     override fun isComposeBouncerOrSceneContainerEnabled(): Boolean {
-        return sceneContainerFlags.isEnabled() || composeBouncerEnabled
+        return SceneContainerFlag.isEnabled || composeBouncerEnabled
     }
 
     @Deprecated(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
index 0f6c7cf..c3dad74 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
@@ -18,6 +18,7 @@
 
 package com.android.systemui.bouncer.ui.viewmodel
 
+import android.app.admin.devicePolicyManager
 import android.content.applicationContext
 import com.android.systemui.authentication.domain.interactor.authenticationInteractor
 import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor
@@ -31,7 +32,6 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.user.domain.interactor.selectedUserInteractor
 import com.android.systemui.user.ui.viewmodel.userSwitcherViewModel
-import com.android.systemui.util.mockito.mock
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 val Kosmos.bouncerViewModel by Fixture {
@@ -44,12 +44,12 @@
         simBouncerInteractor = simBouncerInteractor,
         authenticationInteractor = authenticationInteractor,
         selectedUserInteractor = selectedUserInteractor,
+        devicePolicyManager = devicePolicyManager,
+        bouncerMessageViewModel = bouncerMessageViewModel,
         flags = composeBouncerFlags,
         selectedUser = userSwitcherViewModel.selectedUser,
         users = userSwitcherViewModel.users,
         userSwitcherMenu = userSwitcherViewModel.menu,
         actionButton = bouncerActionButtonInteractor.actionButton,
-        devicePolicyManager = mock(),
-        bouncerMessageViewModel = bouncerMessageViewModel,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt
index 3a72d11..d31491d2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt
@@ -18,4 +18,4 @@
 
 import com.android.systemui.kosmos.Kosmos
 
-val Kosmos.falsingCollector by Kosmos.Fixture { FalsingCollectorFake() }
+var Kosmos.falsingCollector by Kosmos.Fixture<FalsingCollector> { FalsingCollectorFake() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
index 4ed6fe2..329c0f1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
@@ -46,6 +46,10 @@
         _communalWidgets.value = _communalWidgets.value.filter { it.appWidgetId != widgetId }
     }
 
+    override fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {}
+
+    override fun abortRestoreWidgets() {}
+
     private fun onConfigured(id: Int, providerInfo: AppWidgetProviderInfo, priority: Int) {
         _communalWidgets.value += listOf(CommunalWidgetContentModel(id, providerInfo, priority))
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
index 8866fd3..3dd382f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.communal.data.repository.communalRepository
 import com.android.systemui.communal.data.repository.communalWidgetRepository
 import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
+import com.android.systemui.dock.fakeDockManager
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -33,7 +34,6 @@
 import com.android.systemui.log.logcatLogBuffer
 import com.android.systemui.plugins.activityStarter
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.settings.userTracker
 import com.android.systemui.smartspace.data.repository.smartspaceRepository
 import com.android.systemui.user.data.repository.fakeUserRepository
@@ -45,20 +45,20 @@
         broadcastDispatcher = broadcastDispatcher,
         communalRepository = communalRepository,
         widgetRepository = communalWidgetRepository,
-        mediaRepository = communalMediaRepository,
         communalPrefsRepository = communalPrefsRepository,
+        mediaRepository = communalMediaRepository,
         smartspaceRepository = smartspaceRepository,
-        appWidgetHost = mock(),
         keyguardInteractor = keyguardInteractor,
+        communalSettingsInteractor = communalSettingsInteractor,
+        appWidgetHost = mock(),
         editWidgetsActivityStarter = editWidgetsActivityStarter,
         userTracker = userTracker,
         activityStarter = activityStarter,
         userManager = userManager,
+        dockManager = fakeDockManager,
+        sceneInteractor = sceneInteractor,
         logBuffer = logcatLogBuffer("CommunalInteractor"),
         tableLogBuffer = mock(),
-        communalSettingsInteractor = communalSettingsInteractor,
-        sceneInteractor = sceneInteractor,
-        sceneContainerFlags = fakeSceneContainerFlags,
     )
 }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt
index b4773f6..cd2710e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractorKosmos.kt
@@ -17,17 +17,21 @@
 package com.android.systemui.communal.domain.interactor
 
 import com.android.systemui.communal.data.repository.communalSettingsRepository
+import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.settings.userTracker
 import com.android.systemui.user.domain.interactor.selectedUserInteractor
 import com.android.systemui.util.mockito.mock
 
 val Kosmos.communalSettingsInteractor by Fixture {
     CommunalSettingsInteractor(
         bgScope = applicationCoroutineScope,
+        bgExecutor = fakeExecutor,
         repository = communalSettingsRepository,
         userInteractor = selectedUserInteractor,
+        userTracker = userTracker,
         tableLogBuffer = mock(),
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt
index 2396722..e3c218d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModelKosmos.kt
@@ -16,6 +16,9 @@
 
 package com.android.systemui.communal.ui.viewmodel
 
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.util.communalColors
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.ui.viewmodel.dreamingToGlanceableHubTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToDreamingTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel
@@ -27,9 +30,14 @@
 val Kosmos.communalTransitionViewModel by
     Kosmos.Fixture {
         CommunalTransitionViewModel(
-            glanceableHubToLockscreenTransitionViewModel,
-            lockscreenToGlanceableHubTransitionViewModel,
-            dreamingToGlanceableHubTransitionViewModel,
-            glanceableHubToDreamingTransitionViewModel,
+            glanceableHubToLockscreenTransitionViewModel =
+                glanceableHubToLockscreenTransitionViewModel,
+            lockscreenToGlanceableHubTransitionViewModel =
+                lockscreenToGlanceableHubTransitionViewModel,
+            dreamToGlanceableHubTransitionViewModel = dreamingToGlanceableHubTransitionViewModel,
+            glanceableHubToDreamTransitionViewModel = glanceableHubToDreamingTransitionViewModel,
+            communalInteractor = communalInteractor,
+            keyguardTransitionInteractor = keyguardTransitionInteractor,
+            communalColors = communalColors,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/util/CommunalColorsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/util/CommunalColorsKosmos.kt
new file mode 100644
index 0000000..e76cf68
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/util/CommunalColorsKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.util
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.communalColors: CommunalColors by Kosmos.Fixture { fakeCommunalColors }
+val Kosmos.fakeCommunalColors by Kosmos.Fixture { FakeCommunalColors() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/util/FakeCommunalColors.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/util/FakeCommunalColors.kt
new file mode 100644
index 0000000..7046658
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/util/FakeCommunalColors.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.util
+
+import android.graphics.Color
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class FakeCommunalColors : CommunalColors {
+    private val _backgroundColor = MutableStateFlow(Color.valueOf(Color.BLACK))
+
+    override val backgroundColor: StateFlow<Color>
+        get() = _backgroundColor.asStateFlow()
+
+    fun setBackgroundColor(color: Color) {
+        _backgroundColor.value = color
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
index bff10a1..1200866 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.deviceentry.domain.interactor
 
 import com.android.systemui.authentication.domain.interactor.authenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
 import com.android.systemui.deviceentry.data.repository.deviceEntryRepository
 import com.android.systemui.flags.fakeSystemPropertiesHelper
 import com.android.systemui.keyguard.domain.interactor.trustInteractor
@@ -39,5 +40,6 @@
             trustInteractor = trustInteractor,
             deviceUnlockedInteractor = deviceUnlockedInteractor,
             systemPropertiesHelper = fakeSystemPropertiesHelper,
+            alternateBouncerInteractor = alternateBouncerInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
index 0fc0a3c..6c3cf91 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
@@ -23,6 +23,8 @@
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import org.mockito.Mockito.`when` as whenever
 
 /** Creates a mock display. */
@@ -69,12 +71,20 @@
     override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?>
         get() = pendingDisplayFlow
 
+    val _defaultDisplayOff: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    override val defaultDisplayOff: Flow<Boolean>
+        get() = _defaultDisplayOff.asStateFlow()
+
     override val displayAdditionEvent: Flow<Display?>
         get() = displayAdditionEventFlow
 
     private val _displayChangeEvent = MutableSharedFlow<Int>(replay = 1)
     override val displayChangeEvent: Flow<Int> = _displayChangeEvent
     suspend fun emitDisplayChangeEvent(displayId: Int) = _displayChangeEvent.emit(displayId)
+
+    fun setDefaultDisplayOff(defaultDisplayOff: Boolean) {
+        _defaultDisplayOff.value = defaultDisplayOff
+    }
 }
 
 @Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFake.java
new file mode 100644
index 0000000..b99310b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFake.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dock;
+
+/**
+ * A rudimentary fake for DockManager.
+ */
+public class DockManagerFake implements DockManager {
+    DockEventListener mCallback;
+    AlignmentStateListener mAlignmentListener;
+    private boolean mDocked;
+
+    @Override
+    public void addListener(DockEventListener callback) {
+        this.mCallback = callback;
+    }
+
+    @Override
+    public void removeListener(DockEventListener callback) {
+        this.mCallback = null;
+    }
+
+    @Override
+    public void addAlignmentStateListener(AlignmentStateListener listener) {
+        mAlignmentListener = listener;
+    }
+
+    @Override
+    public void removeAlignmentStateListener(AlignmentStateListener listener) {
+        mAlignmentListener = listener;
+    }
+
+    @Override
+    public boolean isDocked() {
+        return mDocked;
+    }
+
+    /** Sets the docked state */
+    public void setIsDocked(boolean docked) {
+        mDocked = docked;
+    }
+
+    @Override
+    public boolean isHidden() {
+        return false;
+    }
+
+    /** Notifies callbacks of dock state change */
+    public void setDockEvent(int event) {
+        mCallback.onEvent(event);
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFakeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFakeKosmos.kt
similarity index 100%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/dock/DockManagerFakeKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/dock/DockManagerFakeKosmos.kt
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/doze/DozeLogKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/doze/DozeLogKosmos.kt
new file mode 100644
index 0000000..c54e9d6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/doze/DozeLogKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.doze
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.dozeLog: DozeLog by Fixture { mock<DozeLog>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/BrokenWithSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/BrokenWithSceneContainer.kt
new file mode 100644
index 0000000..29b088b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/BrokenWithSceneContainer.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
+
+/**
+ * This is used by [SceneContainerRule] to assert that the test is broken when
+ * [FLAG_SCENE_CONTAINER] is enabled.
+ */
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
+annotation class BrokenWithSceneContainer(val bugId: Int)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/DisableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/DisableSceneContainer.kt
new file mode 100644
index 0000000..09f3430
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/DisableSceneContainer.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.platform.test.annotations.DisableFlags
+import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
+
+/**
+ * This includes @[DisableFlags] to work with [SetFlagsRule] to disable all aconfig flags required
+ * by that feature.
+ */
+@DisableFlags(
+    FLAG_SCENE_CONTAINER,
+)
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
+annotation class DisableSceneContainer
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
index 5934e04..e83205c5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
@@ -18,11 +18,14 @@
 
 import android.platform.test.annotations.EnableFlags
 import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN
+import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR
 import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
 import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
 import com.android.systemui.Flags.FLAG_MEDIA_IN_SCENE_CONTAINER
 import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
+import com.android.systemui.Flags.FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR
 import com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_SYSUI
+import com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
 import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
 
 /**
@@ -30,13 +33,16 @@
  * that feature. It is also picked up by [SceneContainerRule] to set non-aconfig prerequisites.
  */
 @EnableFlags(
-    FLAG_SCENE_CONTAINER,
-    FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR,
-    FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
     FLAG_COMPOSE_LOCKSCREEN,
-    FLAG_MEDIA_IN_SCENE_CONTAINER,
+    FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR,
     FLAG_KEYGUARD_WM_STATE_REFACTOR,
+    FLAG_MEDIA_IN_SCENE_CONTAINER,
+    FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
+    FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR,
     FLAG_PREDICTIVE_BACK_SYSUI,
+    FLAG_SCENE_CONTAINER,
+    FLAG_DEVICE_ENTRY_UDFPS_REFACTOR,
+    FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
 )
 @Retention(AnnotationRetention.RUNTIME)
 @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt
index d6f2f77..45ea364 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt
@@ -34,8 +34,9 @@
     Kosmos.Fixture {
         FakeFeatureFlagsClassic().apply {
             set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-            set(Flags.NSSL_DEBUG_LINES, false)
             set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false)
+            set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
+            set(Flags.NSSL_DEBUG_LINES, false)
         }
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt
new file mode 100644
index 0000000..e2a1fe4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
+import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
+
+/** The name of the one flag to be disabled for OFF parameterization */
+private const val flagNameToDisable = FLAG_SCENE_CONTAINER
+
+/** Cache of the flags to be enabled for ON parameterization */
+private val flagNamesToEnable =
+    EnableSceneContainer::class.java.getAnnotation(EnableFlags::class.java)!!.value.toList()
+
+/**
+ * Provides one or two copies of this [FlagsParameterization]; one which disabled
+ * [FLAG_SCENE_CONTAINER] and if none of the dependencies of it are disabled by this, a second copy
+ * which enables [FLAG_SCENE_CONTAINER] and all the dependencies (just like [EnableSceneContainer]).
+ */
+fun FlagsParameterization.andSceneContainer(): Sequence<FlagsParameterization> = sequence {
+    check(flagNameToDisable !in mOverrides) {
+        "Can't add $flagNameToDisable to FlagsParameterization: $this"
+    }
+    yield(FlagsParameterization(mOverrides + mapOf(flagNameToDisable to false)))
+    if (flagNamesToEnable.all { mOverrides[it] != false }) {
+        // Can't add the parameterization of enabling SceneContainerFlag to a parameterization that
+        // explicitly disables one of the prerequisite flags.
+        yield(FlagsParameterization(mOverrides + flagNamesToEnable.associateWith { true }))
+    }
+}
+
+/**
+ * Doubles (roughly; see below) the given list of [FlagsParameterization] for enabling and disabling
+ * SceneContainerFlag.
+ *
+ * The input parameterization may not define [FLAG_SCENE_CONTAINER].
+ *
+ * Any [FlagsParameterization] which disables any flag that is a dependency of
+ * [FLAG_SCENE_CONTAINER], will not add a state for enabling, and the state will simply be converted
+ * to one which disables. Just like [EnableSceneContainer], enabling will also enable all the other
+ * dependencies. For any flag parameterization where a dependency is disabled, an "enabled"
+ * parameterization is inconsistent, so it will not be added.
+ */
+fun List<FlagsParameterization>.andSceneContainer(): List<FlagsParameterization> =
+    flatMap { it.andSceneContainer() }.toList()
+
+/** Parameterizes only the scene container flag. */
+fun parameterizeSceneContainerFlag(): List<FlagsParameterization> {
+    return FlagsParameterization.allCombinationsOf().andSceneContainer()
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt
index 775ad14..5f9f6b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerRule.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import org.junit.Assert
+import org.junit.AssumptionViolatedException
 import org.junit.rules.TestRule
 import org.junit.runner.Description
 import org.junit.runners.model.Statement
@@ -33,10 +34,7 @@
         return object : Statement() {
             @Throws(Throwable::class)
             override fun evaluate() {
-                val hasAnnotation =
-                    description?.testClass?.getAnnotation(EnableSceneContainer::class.java) !=
-                        null || description?.getAnnotation(EnableSceneContainer::class.java) != null
-                if (hasAnnotation) {
+                if (description.hasAnnotation<EnableSceneContainer>()) {
                     Assert.assertTrue(
                         "SceneContainerFlag.isEnabled is false:" +
                             "\n * Did you forget to add a new aconfig flag dependency in" +
@@ -45,8 +43,46 @@
                         SceneContainerFlag.isEnabled
                     )
                 }
+                // Get the flag value, treating the unset error as false.
+                val sceneContainerAconfigEnabled = try {
+                    com.android.systemui.Flags.sceneContainer()
+                } catch (e: Exception) {
+                    false
+                }
+                if (sceneContainerAconfigEnabled) {
+                    Assert.assertTrue(
+                            "FLAG_SCENE_CONTAINER is enabled but SceneContainerFlag.isEnabled" +
+                                    " is false.  Use `.andSceneContainer()` from" +
+                                    " SceneContainerFlagParameterization.kt to parameterize this" +
+                                    " flag correctly.",
+                            SceneContainerFlag.isEnabled
+                    )
+                }
+                if (
+                    description.hasAnnotation<BrokenWithSceneContainer>() &&
+                        SceneContainerFlag.isEnabled
+                ) {
+                    runCatching { base?.evaluate() }
+                        .onFailure { exception ->
+                            if (exception is AssumptionViolatedException) {
+                                throw AssertionError(
+                                    "This is marked @BrokenWithSceneContainer, but was skipped.",
+                                    exception
+                                )
+                            }
+                            throw AssumptionViolatedException("Test is still broken", exception)
+                        }
+                    throw AssertionError(
+                        "HOORAY! You fixed a test that was marked @BrokenWithSceneContainer. " +
+                            "Remove the obsolete annotation to fix this failure."
+                    )
+                }
                 base?.evaluate()
             }
         }
     }
+
+    inline fun <reified T : Annotation> Description?.hasAnnotation(): Boolean =
+        this?.testClass?.getAnnotation(T::class.java) != null ||
+            this?.getAnnotation(T::class.java) != null
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt
new file mode 100644
index 0000000..24603ef
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.qs
+
+import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.qsLongPressEffect by
+    Kosmos.Fixture { QSLongPressEffect(vibratorHelper, keyguardInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/jank/InteractionJankMonitorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/jank/InteractionJankMonitorKosmos.kt
index e2b5869..f0f1cc0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/jank/InteractionJankMonitorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/jank/InteractionJankMonitorKosmos.kt
@@ -17,23 +17,40 @@
 package com.android.systemui.jank
 
 import android.os.HandlerThread
+import android.os.fakeExecutorHandler
+import android.view.View
 import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.jank.InteractionJankMonitor.Configuration.Builder
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.util.mockito.any
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.spy
+import org.mockito.Mockito
 
 val Kosmos.interactionJankMonitor by
     Fixture<InteractionJankMonitor> {
-        spy(InteractionJankMonitor(HandlerThread("InteractionJankMonitor-Kosmos"))).apply {
-            doReturn(true).`when`(this).shouldMonitor()
-            doReturn(true).`when`(this).begin(any(), anyInt())
-            doReturn(true).`when`(this).begin(any<Builder>())
-            doReturn(true).`when`(this).end(anyInt())
-            doReturn(true).`when`(this).cancel(anyInt())
-            doReturn(true).`when`(this).cancel(anyInt(), anyInt())
-        }
+        val worker =
+            Mockito.mock(HandlerThread::class.java).also { worker ->
+                Mockito.doAnswer {
+                        fakeExecutorHandler.also { handler ->
+                            Mockito.doAnswer {
+                                    // TODO(b/333927129): Should return `android.os.looper` instead
+                                    null
+                                }
+                                .`when`(handler)
+                                .looper
+                        }
+                    }
+                    .`when`(worker)
+                    .threadHandler
+            }
+
+        // Return a `spy` so that tests can verify method calls
+        Mockito.spy(
+            object : InteractionJankMonitor(worker) {
+                override fun shouldMonitor(): Boolean = true
+                override fun begin(builder: Configuration.Builder): Boolean = true
+                override fun begin(v: View?, cujType: Int): Boolean = true
+                override fun end(cujType: Int): Boolean = true
+                override fun cancel(cujType: Int): Boolean = true
+                override fun cancel(cujType: Int, reason: Int) = true
+            }
+        )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
index eba5a11..5e5f8cb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
@@ -17,26 +17,24 @@
 package com.android.systemui.keyguard.data.repository
 
 import com.android.keyguard.ClockEventController
-import com.android.keyguard.KeyguardClockSwitch.ClockSize
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.systemui.keyguard.shared.model.SettingsClockSize
+import com.android.systemui.keyguard.shared.model.ClockSize
+import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockId
 import com.android.systemui.shared.clocks.DEFAULT_CLOCK_ID
 import com.android.systemui.util.mockito.mock
 import dagger.Binds
 import dagger.Module
-import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import org.mockito.Mockito
 
-class FakeKeyguardClockRepository @Inject constructor() : KeyguardClockRepository {
-    private val _clockSize = MutableStateFlow(LARGE)
-    override val clockSize: StateFlow<Int> = _clockSize
+class FakeKeyguardClockRepository() : KeyguardClockRepository {
+    private val _clockSize = MutableStateFlow(ClockSize.LARGE)
+    override val clockSize: StateFlow<ClockSize> = _clockSize
 
-    private val _selectedClockSize = MutableStateFlow(SettingsClockSize.DYNAMIC)
+    private val _selectedClockSize = MutableStateFlow(ClockSizeSetting.DYNAMIC)
     override val selectedClockSize = _selectedClockSize
 
     private val _currentClockId = MutableStateFlow(DEFAULT_CLOCK_ID)
@@ -50,13 +48,25 @@
         get() = _previewClock
     override val clockEventController: ClockEventController
         get() = mock()
+    override val shouldForceSmallClock: Boolean
+        get() = _shouldForceSmallClock
+    private var _shouldForceSmallClock: Boolean = false
 
-    override fun setClockSize(@ClockSize size: Int) {
+    override fun setClockSize(size: ClockSize) {
         _clockSize.value = size
     }
 
+    fun setSelectedClockSize(size: ClockSizeSetting) {
+        _selectedClockSize.value = size
+    }
+
     fun setCurrentClock(clockController: ClockController) {
         _currentClock.value = clockController
+        _currentClockId.value = clockController.config.id
+    }
+
+    fun setShouldForceSmallClock(shouldForceSmallClock: Boolean) {
+        _shouldForceSmallClock = shouldForceSmallClock
     }
 }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index 75489b6..90a93f4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -16,60 +16,83 @@
 
 package com.android.systemui.keyguard.data.repository
 
+import android.content.applicationContext
 import android.os.fakeExecutorHandler
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID
-import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
-import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
+import com.android.systemui.keyguard.domain.interactor.keyguardBlueprintInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
+import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
 import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
+import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
+import com.android.systemui.keyguard.ui.viewmodel.keyguardClockViewModel
+import com.android.systemui.keyguard.ui.viewmodel.keyguardSmartspaceViewModel
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.ThreadAssert
 import com.android.systemui.util.mockito.mock
+import java.util.Optional
+
+val Kosmos.keyguardClockSection: ClockSection by
+    Kosmos.Fixture {
+        ClockSection(
+            clockInteractor = keyguardClockInteractor,
+            keyguardClockViewModel = keyguardClockViewModel,
+            context = applicationContext,
+            smartspaceViewModel = keyguardSmartspaceViewModel,
+            blueprintInteractor = { keyguardBlueprintInteractor },
+        )
+    }
+
+val Kosmos.defaultKeyguardBlueprint by
+    Kosmos.Fixture {
+        DefaultKeyguardBlueprint(
+            defaultIndicationAreaSection = mock(),
+            defaultDeviceEntrySection = mock(),
+            defaultShortcutsSection = mock(),
+            defaultAmbientIndicationAreaSection = Optional.of(mock()),
+            defaultSettingsPopupMenuSection = mock(),
+            defaultStatusViewSection = mock(),
+            defaultStatusBarSection = mock(),
+            defaultNotificationStackScrollLayoutSection = mock(),
+            aodNotificationIconsSection = mock(),
+            aodBurnInSection = mock(),
+            communalTutorialIndicatorSection = mock(),
+            clockSection = keyguardClockSection,
+            smartspaceSection = mock(),
+            keyguardSliceViewSection = mock(),
+            udfpsAccessibilityOverlaySection = mock(),
+            accessibilityActionsSection = mock(),
+        )
+    }
+
+val Kosmos.splitShadeBlueprint by
+    Kosmos.Fixture {
+        SplitShadeKeyguardBlueprint(
+            defaultIndicationAreaSection = mock(),
+            defaultDeviceEntrySection = mock(),
+            defaultShortcutsSection = mock(),
+            defaultAmbientIndicationAreaSection = Optional.of(mock()),
+            defaultSettingsPopupMenuSection = mock(),
+            defaultStatusViewSection = mock(),
+            defaultStatusBarSection = mock(),
+            splitShadeNotificationStackScrollLayoutSection = mock(),
+            splitShadeGuidelines = mock(),
+            aodNotificationIconsSection = mock(),
+            aodBurnInSection = mock(),
+            communalTutorialIndicatorSection = mock(),
+            clockSection = keyguardClockSection,
+            smartspaceSection = mock(),
+            mediaSection = mock(),
+            accessibilityActionsSection = mock(),
+        )
+    }
 
 val Kosmos.keyguardBlueprintRepository by
     Kosmos.Fixture {
         KeyguardBlueprintRepository(
             blueprints =
                 setOf(
-                    defaultBlueprint,
+                    defaultKeyguardBlueprint,
                     splitShadeBlueprint,
-                    weatherClockBlueprint,
-                    splitShadeWeatherClockBlueprint,
                 ),
             handler = fakeExecutorHandler,
-            assert = mock<ThreadAssert>(),
+            assert = mock(),
         )
     }
-
-private val defaultBlueprint =
-    object : KeyguardBlueprint {
-        override val id: String
-            get() = DEFAULT
-        override val sections: List<KeyguardSection>
-            get() = listOf()
-    }
-
-private val weatherClockBlueprint =
-    object : KeyguardBlueprint {
-        override val id: String
-            get() = WEATHER_CLOCK_BLUEPRINT_ID
-        override val sections: List<KeyguardSection>
-            get() = listOf()
-    }
-
-private val splitShadeWeatherClockBlueprint =
-    object : KeyguardBlueprint {
-        override val id: String
-            get() = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
-        override val sections: List<KeyguardSection>
-            get() = listOf()
-    }
-
-private val splitShadeBlueprint =
-    object : KeyguardBlueprint {
-        override val id: String
-            get() = SplitShadeKeyguardBlueprint.Companion.ID
-        override val sections: List<KeyguardSection>
-            get() = listOf()
-    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt
new file mode 100644
index 0000000..dc7103f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryKosmos.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.keyguardSmartspaceRepository by Kosmos.Fixture { KeyguardSmartspaceRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DozeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DozeInteractorKosmos.kt
new file mode 100644
index 0000000..3304d44
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DozeInteractorKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+
+val Kosmos.dozeInteractor: DozeInteractor by Fixture {
+    DozeInteractor(
+        keyguardRepository,
+        { sceneInteractor },
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt
index 530cbed..78a419f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
 import com.android.systemui.communal.domain.interactor.communalInteractor
 import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
 import com.android.systemui.kosmos.Kosmos
@@ -23,7 +24,9 @@
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 
+@ExperimentalCoroutinesApi
 val Kosmos.fromAlternateBouncerTransitionInteractor by
     Kosmos.Fixture {
         FromAlternateBouncerTransitionInteractor(
@@ -36,5 +39,6 @@
             communalInteractor = communalInteractor,
             powerInteractor = powerInteractor,
             keyguardOcclusionInteractor = keyguardOcclusionInteractor,
+            primaryBouncerInteractor = primaryBouncerInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
index bbe37c1..91057b6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
@@ -16,12 +16,14 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import com.android.internal.widget.lockPatternUtils
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
+import com.android.systemui.user.domain.interactor.selectedUserInteractor
 
 val Kosmos.fromAodTransitionInteractor by
     Kosmos.Fixture {
@@ -34,5 +36,7 @@
             keyguardInteractor = keyguardInteractor,
             powerInteractor = powerInteractor,
             keyguardOcclusionInteractor = keyguardOcclusionInteractor,
+            selectedUserInteractor = selectedUserInteractor,
+            lockPatternUtils = lockPatternUtils,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
index 87d6c17..5256ce4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
@@ -22,7 +22,7 @@
 import com.android.systemui.keyguard.data.repository.keyguardBlueprintRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.statusbar.policy.splitShadeStateController
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 
 val Kosmos.keyguardBlueprintInteractor by
     Kosmos.Fixture {
@@ -30,7 +30,7 @@
             keyguardBlueprintRepository = keyguardBlueprintRepository,
             applicationScope = applicationCoroutineScope,
             context = applicationContext,
-            splitShadeStateController = splitShadeStateController,
+            shadeInteractor = shadeInteractor,
             clockInteractor = keyguardClockInteractor,
             configurationInteractor = configurationInteractor,
             fingerprintPropertyInteractor = fingerprintPropertyInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
index d791e94..d52883e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
@@ -18,6 +18,22 @@
 
 import com.android.systemui.keyguard.data.repository.keyguardClockRepository
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
+import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
 
 val Kosmos.keyguardClockInteractor by
-    Kosmos.Fixture { KeyguardClockInteractor(keyguardClockRepository = keyguardClockRepository) }
+    Kosmos.Fixture {
+        KeyguardClockInteractor(
+            keyguardClockRepository = keyguardClockRepository,
+            applicationScope = applicationCoroutineScope,
+            mediaCarouselInteractor = mediaCarouselInteractor,
+            activeNotificationsInteractor = activeNotificationsInteractor,
+            shadeInteractor = shadeInteractor,
+            keyguardInteractor = keyguardInteractor,
+            keyguardTransitionInteractor = keyguardTransitionInteractor,
+            headsUpNotificationInteractor = headsUpNotificationInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
new file mode 100644
index 0000000..2c6d44f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@ExperimentalCoroutinesApi
+val Kosmos.keyguardDismissActionInteractor by
+    Kosmos.Fixture {
+        KeyguardDismissActionInteractor(
+            repository = keyguardRepository,
+            transitionInteractor = keyguardTransitionInteractor,
+            dismissInteractor = keyguardDismissInteractor,
+            applicationScope = testScope.backgroundScope,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
new file mode 100644
index 0000000..f33ca95
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.keyguard.data.repository.trustRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.user.domain.interactor.selectedUserInteractor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@ExperimentalCoroutinesApi
+val Kosmos.keyguardDismissInteractor by
+    Kosmos.Fixture {
+        KeyguardDismissInteractor(
+            trustRepository = trustRepository,
+            keyguardRepository = keyguardRepository,
+            primaryBouncerInteractor = primaryBouncerInteractor,
+            alternateBouncerInteractor = alternateBouncerInteractor,
+            powerInteractor = powerInteractor,
+            selectedUserInteractor = selectedUserInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index e21c766..2e751cc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -24,12 +24,9 @@
 import com.android.systemui.keyguard.data.repository.FakeCommandQueue
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
 import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor.ConfigurationBasedDimensions
@@ -49,7 +46,6 @@
     @JvmStatic
     fun create(
         featureFlags: FakeFeatureFlags = FakeFeatureFlags(),
-        sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(),
         repository: FakeKeyguardRepository = FakeKeyguardRepository(),
         commandQueue: FakeCommandQueue = FakeCommandQueue(),
         bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
@@ -88,7 +84,6 @@
             repository = repository,
             commandQueue = commandQueue,
             featureFlags = featureFlags,
-            sceneContainerFlags = sceneContainerFlags,
             bouncerRepository = bouncerRepository,
             configurationRepository = configurationRepository,
             shadeRepository = shadeRepository,
@@ -96,13 +91,12 @@
             KeyguardInteractor(
                 repository = repository,
                 commandQueue = commandQueue,
-                sceneContainerFlags = sceneContainerFlags,
+                powerInteractor = powerInteractor,
                 bouncerRepository = bouncerRepository,
                 configurationInteractor = ConfigurationInteractor(configurationRepository),
                 shadeRepository = shadeRepository,
-                sceneInteractorProvider = { sceneInteractor },
                 keyguardTransitionInteractor = keyguardTransitionInteractor,
-                powerInteractor = powerInteractor,
+                sceneInteractorProvider = { sceneInteractor },
                 fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
                 sharedNotificationContainerInteractor = { sncInteractor },
                 applicationScope = testScope,
@@ -114,7 +108,6 @@
         val repository: FakeKeyguardRepository,
         val commandQueue: FakeCommandQueue,
         val featureFlags: FakeFeatureFlags,
-        val sceneContainerFlags: SceneContainerFlags,
         val bouncerRepository: FakeKeyguardBouncerRepository,
         val configurationRepository: FakeConfigurationRepository,
         val shadeRepository: FakeShadeRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
index 2a0c01c..9426718 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
@@ -23,7 +23,6 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.statusbar.commandQueue
 import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
@@ -34,7 +33,6 @@
             repository = keyguardRepository,
             commandQueue = commandQueue,
             powerInteractor = powerInteractor,
-            sceneContainerFlags = sceneContainerFlags,
             bouncerRepository = keyguardBouncerRepository,
             configurationInteractor = configurationInteractor,
             shadeRepository = shadeRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractorKosmos.kt
new file mode 100644
index 0000000..b5d5d64
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractorKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.keyguard.data.repository.keyguardSmartspaceRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+var Kosmos.keyguardSmartspaceInteractor by Fixture {
+    KeyguardSmartspaceInteractor(
+        keyguardSmartspaceRepository = keyguardSmartspaceRepository,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt
index 185deda..6cc1e8e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorKosmos.kt
@@ -20,13 +20,11 @@
 import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testDispatcher
 
 val Kosmos.keyguardTransitionInteractor: KeyguardTransitionInteractor by
     Kosmos.Fixture {
         KeyguardTransitionInteractor(
             scope = applicationCoroutineScope,
-            mainDispatcher = testDispatcher,
             repository = keyguardTransitionRepository,
             keyguardRepository = keyguardRepository,
             fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt
index f7de5a4..1a05d21 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowKosmos.kt
@@ -22,14 +22,10 @@
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testDispatcher
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 val Kosmos.keyguardTransitionAnimationFlow by Fixture {
     KeyguardTransitionAnimationFlow(
-        scope = applicationCoroutineScope,
-        mainDispatcher = testDispatcher,
         transitionInteractor = keyguardTransitionInteractor,
         logger = keyguardTransitionAnimationLogger,
     )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinderKosmos.kt
new file mode 100644
index 0000000..24d2c2f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinderKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.binder
+
+import android.os.fakeExecutorHandler
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.keyguardBlueprintViewBinder by
+    Kosmos.Fixture { KeyguardBlueprintViewBinder(fakeExecutorHandler) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt
new file mode 100644
index 0000000..bc35dc8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+
+val Kosmos.accessibilityActionsViewModelKosmos by Fixture {
+    AccessibilityActionsViewModel(
+        communalInteractor = communalInteractor,
+        keyguardTransitionInteractor = keyguardTransitionInteractor,
+        keyguardInteractor = keyguardInteractor,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt
index b4f1218..bdd4afa 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelKosmos.kt
@@ -18,7 +18,7 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager
@@ -27,6 +27,6 @@
 val Kosmos.alternateBouncerViewModel by Fixture {
     AlternateBouncerViewModel(
         statusBarKeyguardViewManager = statusBarKeyguardViewManager,
-        animationFlow = keyguardTransitionAnimationFlow,
+        keyguardTransitionInteractor = keyguardTransitionInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt
index ffa4133..9774e4a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsKosmos.kt
@@ -19,21 +19,19 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.domain.interactor.keyguardDismissActionInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.sysuiStatusBarStateController
-import com.android.systemui.util.mockito.mock
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 val Kosmos.bouncerToGoneFlows by Fixture {
     BouncerToGoneFlows(
         statusBarStateController = sysuiStatusBarStateController,
         primaryBouncerInteractor = mockPrimaryBouncerInteractor,
-        keyguardDismissActionInteractor = mock(),
-        featureFlags = featureFlagsClassic,
+        keyguardDismissActionInteractor = { keyguardDismissActionInteractor },
         shadeInteractor = shadeInteractor,
         animationFlow = keyguardTransitionAnimationFlow,
     )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
index 709f864..58b0ff8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -47,7 +46,6 @@
         transitionInteractor = keyguardTransitionInteractor,
         keyguardInteractor = keyguardInteractor,
         viewModel = aodToLockscreenTransitionViewModel,
-        sceneContainerFlags = sceneContainerFlags,
         keyguardViewController = { statusBarKeyguardViewManager },
         deviceEntryInteractor = deviceEntryInteractor,
         deviceEntrySourceInteractor = deviceEntrySourceInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
index 298c70d..00741eb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.common.ui.domain.interactor.configurationInteractor
-import com.android.systemui.keyguard.domain.interactor.fromDreamingTransitionInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
 import com.android.systemui.kosmos.Kosmos
 
@@ -26,6 +25,5 @@
         DreamingToGlanceableHubTransitionViewModel(
             configurationInteractor = configurationInteractor,
             animationFlow = keyguardTransitionAnimationFlow,
-            fromDreamingTransitionInteractor = fromDreamingTransitionInteractor
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt
new file mode 100644
index 0000000..63b87c0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardBlueprintInteractor
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.keyguardBlueprintViewModel by
+    Kosmos.Fixture { KeyguardBlueprintViewModel(keyguardBlueprintInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
index 60dd48a..6d46694 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
@@ -16,20 +16,24 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
+import android.content.res.mainResources
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
+import com.android.systemui.statusbar.ui.systemBarUtilsProxy
 
 val Kosmos.keyguardClockViewModel by
     Kosmos.Fixture {
         KeyguardClockViewModel(
-            keyguardInteractor = keyguardInteractor,
             keyguardClockInteractor = keyguardClockInteractor,
             applicationScope = applicationCoroutineScope,
             notifsKeyguardInteractor = notificationsKeyguardInteractor,
             shadeInteractor = shadeInteractor,
+            systemBarUtils = systemBarUtilsProxy,
+            configurationInteractor = configurationInteractor,
+            resources = mainResources
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModelKosmos.kt
new file mode 100644
index 0000000..d33d594
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModelKosmos.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.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardSmartspaceInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.keyguardSmartspaceViewModel by
+    Kosmos.Fixture {
+        KeyguardSmartspaceViewModel(
+            applicationScope = applicationCoroutineScope,
+            smartspaceController = mock(),
+            keyguardClockViewModel = keyguardClockViewModel,
+            smartspaceInteractor = keyguardSmartspaceInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt
index 1e25f7f..30a4f21 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelKosmos.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor
 
 val Kosmos.lockscreenContentViewModel by
     Kosmos.Fixture {
@@ -32,5 +33,6 @@
             longPress = keyguardLongPressViewModel,
             shadeInteractor = shadeInteractor,
             applicationScope = applicationCoroutineScope,
+            unfoldTransitionInteractor = unfoldTransitionInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModelKosmos.kt
new file mode 100644
index 0000000..3b96912
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModelKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+var Kosmos.occludedToGoneTransitionViewModel by Fixture {
+    OccludedToGoneTransitionViewModel(
+        animationFlow = keyguardTransitionAnimationFlow,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt
index e6651a4..f86e9b7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelKosmos.kt
@@ -20,6 +20,8 @@
 
 import com.android.systemui.common.ui.domain.interactor.configurationInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
@@ -30,5 +32,7 @@
         deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
         configurationInteractor = configurationInteractor,
         animationFlow = keyguardTransitionAnimationFlow,
+        keyguardInteractor = keyguardInteractor,
+        keyguardTransitionInteractor = keyguardTransitionInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
index 4ecff73..d6edea2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
@@ -19,20 +19,18 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.keyguard.domain.interactor.keyguardDismissActionInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.statusbar.sysuiStatusBarStateController
-import com.android.systemui.util.mockito.mock
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 val Kosmos.primaryBouncerToGoneTransitionViewModel by Fixture {
     PrimaryBouncerToGoneTransitionViewModel(
         statusBarStateController = sysuiStatusBarStateController,
         primaryBouncerInteractor = mockPrimaryBouncerInteractor,
-        keyguardDismissActionInteractor = mock(),
-        featureFlags = featureFlagsClassic,
+        keyguardDismissActionInteractor = { keyguardDismissActionInteractor },
         bouncerToGoneFlows = bouncerToGoneFlows,
         animationFlow = keyguardTransitionAnimationFlow,
     )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
new file mode 100644
index 0000000..450f08f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.util
+
+import androidx.core.animation.ValueAnimator
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertAbout
+import junit.framework.Assert.assertEquals
+import org.junit.Assert.fail
+import org.mockito.Mockito
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+/** [Subject] used to make assertions about a [Mockito.spy] KeyguardTransitionRepository. */
+class KeyguardTransitionRepositorySpySubject
+private constructor(
+    failureMetadata: FailureMetadata,
+    private val repository: KeyguardTransitionRepository,
+) : Subject(failureMetadata, repository) {
+
+    /**
+     * Asserts that we started a transition to the given state, optionally checking additional
+     * parameters. If an animator param or assertion is not provided, we will not assert anything
+     * about the animator.
+     */
+    suspend fun startedTransition(
+        ownerName: String? = null,
+        from: KeyguardState? = null,
+        to: KeyguardState,
+        modeOnCanceled: TransitionModeOnCanceled? = null,
+    ) {
+        startedTransition(ownerName, from, to, {}, modeOnCanceled)
+    }
+
+    /**
+     * Asserts that we started a transition to the given state, optionally verifying additional
+     * params.
+     */
+    suspend fun startedTransition(
+        ownerName: String? = null,
+        from: KeyguardState? = null,
+        to: KeyguardState,
+        animator: ValueAnimator?,
+        modeOnCanceled: TransitionModeOnCanceled? = null,
+    ) {
+        startedTransition(ownerName, from, to, { assertEquals(animator, it) }, modeOnCanceled)
+    }
+
+    /**
+     * Asserts that we started a transition to the given state, optionally verifying additional
+     * params.
+     */
+    suspend fun startedTransition(
+        ownerName: String? = null,
+        from: KeyguardState? = null,
+        to: KeyguardState,
+        animatorAssertion: (Subject) -> Unit,
+        modeOnCanceled: TransitionModeOnCanceled? = null,
+    ) {
+        withArgCaptor<TransitionInfo> { verify(repository).startTransition(capture()) }
+            .also { transitionInfo ->
+                assertEquals(to, transitionInfo.to)
+                animatorAssertion.invoke(Truth.assertThat(transitionInfo.animator))
+                from?.let { assertEquals(it, transitionInfo.from) }
+                ownerName?.let { assertEquals(it, transitionInfo.ownerName) }
+                modeOnCanceled?.let { assertEquals(it, transitionInfo.modeOnCanceled) }
+            }
+    }
+
+    /** Verifies that [KeyguardTransitionRepository.startTransition] was never called. */
+    suspend fun noTransitionsStarted() {
+        verify(repository, never()).startTransition(any())
+    }
+
+    companion object {
+        fun assertThat(
+            repository: KeyguardTransitionRepository
+        ): KeyguardTransitionRepositorySpySubject =
+            assertAbout { failureMetadata, repository: KeyguardTransitionRepository ->
+                    if (!Mockito.mockingDetails(repository).isSpy) {
+                        fail(
+                            "Cannot assert on a non-spy KeyguardTransitionRepository. " +
+                                "Use Mockito.spy(keyguardTransitionRepository)."
+                        )
+                    }
+                    KeyguardTransitionRepositorySpySubject(failureMetadata, repository)
+                }
+                .that(repository)
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 1b23296..d4b7937 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -22,6 +22,7 @@
 import android.os.fakeExecutorHandler
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.bouncer.data.repository.bouncerRepository
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
 import com.android.systemui.classifier.falsingCollector
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
@@ -30,9 +31,10 @@
 import com.android.systemui.communal.domain.interactor.communalInteractor
 import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
-import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.globalactions.domain.interactor.globalActionsInteractor
+import com.android.systemui.haptics.qs.qsLongPressEffect
 import com.android.systemui.jank.interactionJankMonitor
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -40,6 +42,7 @@
 import com.android.systemui.keyguard.domain.interactor.fromLockscreenTransitionInteractor
 import com.android.systemui.keyguard.domain.interactor.fromPrimaryBouncerTransitionInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.model.sceneContainerPlugin
 import com.android.systemui.plugins.statusbar.statusBarStateController
@@ -47,8 +50,11 @@
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.sceneContainerConfig
-import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
 import com.android.systemui.scene.shared.model.sceneDataSource
+import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shadeController
 import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
 import com.android.systemui.statusbar.phone.screenOffAnimationController
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
@@ -67,8 +73,6 @@
 
     val testDispatcher by lazy { kosmos.testDispatcher }
     val testScope by lazy { kosmos.testScope }
-    val fakeFeatureFlags by lazy { kosmos.fakeFeatureFlagsClassic }
-    val fakeSceneContainerFlags by lazy { kosmos.fakeSceneContainerFlags }
     val fakeExecutor by lazy { kosmos.fakeExecutor }
     val fakeExecutorHandler by lazy { kosmos.fakeExecutorHandler }
     val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
@@ -76,6 +80,8 @@
     val bouncerRepository by lazy { kosmos.bouncerRepository }
     val communalRepository by lazy { kosmos.fakeCommunalRepository }
     val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+    val keyguardBouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
+    val keyguardInteractor by lazy { kosmos.keyguardInteractor }
     val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
     val keyguardTransitionInteractor by lazy { kosmos.keyguardTransitionInteractor }
     val powerRepository by lazy { kosmos.fakePowerRepository }
@@ -90,6 +96,7 @@
     val falsingCollector by lazy { kosmos.falsingCollector }
     val powerInteractor by lazy { kosmos.powerInteractor }
     val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor }
+    val deviceEntryUdfpsInteractor by lazy { kosmos.deviceEntryUdfpsInteractor }
     val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
     val communalInteractor by lazy { kosmos.communalInteractor }
     val sceneContainerPlugin by lazy { kosmos.sceneContainerPlugin }
@@ -106,6 +113,11 @@
     val sharedNotificationContainerInteractor by lazy {
         kosmos.sharedNotificationContainerInteractor
     }
+    val brightnessMirrorShowingInteractor by lazy { kosmos.brightnessMirrorShowingInteractor }
+    val qsLongPressEffect by lazy { kosmos.qsLongPressEffect }
+    val shadeController by lazy { kosmos.shadeController }
+    val shadeRepository by lazy { kosmos.shadeRepository }
+    val shadeInteractor by lazy { kosmos.shadeInteractor }
 
     init {
         kosmos.applicationContext = testCase.context
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/log/SessionTrackerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/SessionTrackerKosmos.kt
new file mode 100644
index 0000000..eac9149
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/SessionTrackerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.sessionTracker: SessionTracker by Kosmos.Fixture { sessionTrackerMock }
+val Kosmos.sessionTrackerMock: SessionTracker by Kosmos.Fixture { mock() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
index 7ce810e..7dab5c2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
@@ -17,5 +17,6 @@
 package com.android.systemui.media.controls.data.repository
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.time.systemClock
 
-val Kosmos.mediaFilterRepository by Kosmos.Fixture { MediaFilterRepository() }
+val Kosmos.mediaFilterRepository by Kosmos.Fixture { MediaFilterRepository(systemClock) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt
index 29c5bd5..81adefa 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractorKosmos.kt
@@ -16,16 +16,30 @@
 
 package com.android.systemui.media.controls.domain.pipeline.interactor
 
+import android.content.applicationContext
+import com.android.systemui.activityIntentHelper
+import com.android.systemui.bluetooth.mockBroadcastDialogController
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.media.controls.data.repository.mediaFilterRepository
 import com.android.systemui.media.controls.domain.pipeline.mediaDataProcessor
 import com.android.systemui.media.controls.util.mediaInstanceId
+import com.android.systemui.media.mediaOutputDialogManager
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.statusbar.notificationLockscreenUserManager
+import com.android.systemui.statusbar.policy.keyguardStateController
 
 val Kosmos.mediaControlInteractor by
     Kosmos.Fixture {
         MediaControlInteractor(
+            applicationContext = applicationContext,
             instanceId = mediaInstanceId,
             repository = mediaFilterRepository,
             mediaDataProcessor = mediaDataProcessor,
+            keyguardStateController = keyguardStateController,
+            activityStarter = activityStarter,
+            activityIntentHelper = activityIntentHelper,
+            lockscreenUserManager = notificationLockscreenUserManager,
+            mediaOutputDialogManager = mediaOutputDialogManager,
+            broadcastDialogController = mockBroadcastDialogController,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/factory/MediaControlInteractorFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/factory/MediaControlInteractorFactoryKosmos.kt
new file mode 100644
index 0000000..461eaa2
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/interactor/factory/MediaControlInteractorFactoryKosmos.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.domain.pipeline.interactor.factory
+
+import android.content.applicationContext
+import com.android.internal.logging.InstanceId
+import com.android.systemui.activityIntentHelper
+import com.android.systemui.bluetooth.mockBroadcastDialogController
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaControlInteractor
+import com.android.systemui.media.controls.domain.pipeline.mediaDataProcessor
+import com.android.systemui.media.mediaOutputDialogManager
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.statusbar.notificationLockscreenUserManager
+import com.android.systemui.statusbar.policy.keyguardStateController
+
+val Kosmos.mediaControlInteractorFactory by
+    Kosmos.Fixture {
+        object : MediaControlInteractorFactory {
+            override fun create(instanceId: InstanceId): MediaControlInteractor {
+                return MediaControlInteractor(
+                    applicationContext = applicationContext,
+                    instanceId = instanceId,
+                    repository = mediaFilterRepository,
+                    mediaDataProcessor = mediaDataProcessor,
+                    keyguardStateController = keyguardStateController,
+                    activityStarter = activityStarter,
+                    activityIntentHelper = activityIntentHelper,
+                    lockscreenUserManager = notificationLockscreenUserManager,
+                    mediaOutputDialogManager = mediaOutputDialogManager,
+                    broadcastDialogController = mockBroadcastDialogController,
+                )
+            }
+        }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
new file mode 100644
index 0000000..6eae28f7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.media.controls.domain.pipeline.interactor.factory.mediaControlInteractorFactory
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
+import com.android.systemui.media.controls.util.mediaFlags
+import com.android.systemui.media.controls.util.mediaUiEventLogger
+import com.android.systemui.statusbar.notification.collection.provider.visualStabilityProvider
+
+val Kosmos.mediaCarouselViewModel by
+    Kosmos.Fixture {
+        MediaCarouselViewModel(
+            applicationScope = applicationCoroutineScope,
+            applicationContext = applicationContext,
+            backgroundDispatcher = testDispatcher,
+            visualStabilityProvider = visualStabilityProvider,
+            interactor = mediaCarouselInteractor,
+            controlInteractorFactory = mediaControlInteractorFactory,
+            recommendationsViewModel = mediaRecommendationsViewModel,
+            logger = mediaUiEventLogger,
+            mediaFlags = mediaFlags,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
new file mode 100644
index 0000000..b3fb15f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.media.controls.domain.pipeline.interactor.mediaControlInteractor
+import com.android.systemui.media.controls.util.mediaUiEventLogger
+
+val Kosmos.mediaControlViewModel by
+    Kosmos.Fixture {
+        MediaControlViewModel(
+            applicationScope = applicationCoroutineScope,
+            applicationContext = applicationContext,
+            backgroundDispatcher = testDispatcher,
+            interactor = mediaControlInteractor,
+            logger = mediaUiEventLogger,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt
index 6f652f2..e88d22a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaFlagsKosmos.kt
@@ -18,9 +18,5 @@
 
 import com.android.systemui.flags.featureFlagsClassic
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 
-val Kosmos.mediaFlags by
-    Kosmos.Fixture {
-        MediaFlags(featureFlags = featureFlagsClassic, sceneContainerFlags = sceneContainerFlags)
-    }
+val Kosmos.mediaFlags by Kosmos.Fixture { MediaFlags(featureFlags = featureFlagsClassic) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt
index 8faeb39..6ddf633 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/model/SysUiStateKosmos.kt
@@ -19,10 +19,13 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.settings.displayTracker
+import org.mockito.Mockito.spy
 
 val Kosmos.sysUiState by Fixture {
-    SysUiState(
-        displayTracker,
-        sceneContainerPlugin,
+    spy(
+        SysUiState(
+            displayTracker,
+            sceneContainerPlugin,
+        )
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt
index 695e594..3762497 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/statusbar/StatusBarStateControllerKosmos.kt
@@ -31,7 +31,7 @@
     Kosmos.Fixture {
         StatusBarStateControllerImpl(
             uiEventLogger,
-            interactionJankMonitor,
+            { interactionJankMonitor },
             mock(),
             { shadeInteractor },
             { deviceUnlockedInteractor },
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
index 1ce2610..0de76c8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
@@ -35,7 +35,6 @@
 import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
 import com.android.systemui.qs.footer.foregroundServicesRepository
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
-import com.android.systemui.qs.tiles.di.NewQSTileFactory
 import com.android.systemui.security.data.repository.securityRepository
 import com.android.systemui.settings.userTracker
 import com.android.systemui.statusbar.policy.deviceProvisionedController
@@ -49,7 +48,6 @@
     QsEventLoggerFake(uiEventLoggerFake, instanceIdSequenceFake)
 }
 
-var Kosmos.newQSTileFactory by Fixture<NewQSTileFactory>()
 var Kosmos.qsTileFactory by Fixture<QSFactory>()
 
 val Kosmos.fgsManagerController by Fixture { FakeFgsManagerController() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/GridLayoutTypeRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/GridLayoutTypeRepositoryKosmos.kt
new file mode 100644
index 0000000..f846d57
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/GridLayoutTypeRepositoryKosmos.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.gridLayoutTypeRepository by Kosmos.Fixture { GridLayoutTypeRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconTilesRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconTilesRepositoryKosmos.kt
new file mode 100644
index 0000000..685e772
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/data/repository/IconTilesRepositoryKosmos.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.iconTilesRepository by Kosmos.Fixture { IconTilesRepositoryImpl() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt
new file mode 100644
index 0000000..e44fa07
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.data.repository.gridLayoutTypeRepository
+
+val Kosmos.gridLayoutTypeInteractor by
+    Kosmos.Fixture { GridLayoutTypeInteractor(gridLayoutTypeRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
new file mode 100644
index 0000000..eaa702f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractorKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.data.repository.iconTilesRepository
+
+val Kosmos.iconTilesInteractor by Kosmos.Fixture { IconTilesInteractor(iconTilesRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt
new file mode 100644
index 0000000..9851f04
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModelKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.panels.domain.interactor.gridLayoutTypeInteractor
+import com.android.systemui.qs.panels.domain.interactor.iconTilesInteractor
+import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
+import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout
+import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor
+
+val Kosmos.tileGridViewModel by
+    Kosmos.Fixture {
+        TileGridViewModel(
+            gridLayoutTypeInteractor,
+            mapOf(Pair(InfiniteGridLayoutType::class.java, InfiniteGridLayout())),
+            currentTilesInteractor,
+            iconTilesInteractor
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt
index 9ef44c4..b870039 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.qs.external.customTileStatePersister
 import com.android.systemui.qs.external.tileLifecycleManagerFactory
-import com.android.systemui.qs.newQSTileFactory
 import com.android.systemui.qs.pipeline.data.repository.customTileAddedRepository
 import com.android.systemui.qs.pipeline.data.repository.installedTilesRepository
 import com.android.systemui.qs.pipeline.data.repository.minimumTilesRepository
@@ -29,6 +28,7 @@
 import com.android.systemui.qs.pipeline.shared.logging.qsLogger
 import com.android.systemui.qs.pipeline.shared.pipelineFlagsRepository
 import com.android.systemui.qs.qsTileFactory
+import com.android.systemui.qs.tiles.di.newQSTileFactory
 import com.android.systemui.settings.userTracker
 import com.android.systemui.user.data.repository.userRepository
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/di/NewQSTileFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/di/NewQSTileFactoryKosmos.kt
new file mode 100644
index 0000000..5c4b390
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/di/NewQSTileFactoryKosmos.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.di
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
+import com.android.systemui.qs.tiles.viewmodel.qSTileConfigProvider
+import com.android.systemui.qs.tiles.viewmodel.qsTileViewModelAdaperFactory
+import com.android.systemui.util.mockito.mock
+import javax.inject.Provider
+import org.mockito.Mockito
+
+var Kosmos.newFactoryTileMap by Kosmos.Fixture { emptyMap<String, Provider<QSTileViewModel>>() }
+
+val Kosmos.newQSTileFactory by
+    Kosmos.Fixture {
+        NewQSTileFactory(
+            qSTileConfigProvider,
+            qsTileViewModelAdaperFactory,
+            newFactoryTileMap,
+            mock(Mockito.withSettings().defaultAnswer(Mockito.RETURNS_MOCKS)),
+            mock(Mockito.withSettings().defaultAnswer(Mockito.RETURNS_MOCKS)),
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/reducebrightness/ReduceBrightColorsTileKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/reducebrightness/ReduceBrightColorsTileKosmos.kt
new file mode 100644
index 0000000..339f3bb
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/reducebrightness/ReduceBrightColorsTileKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.reducebrightness
+
+import com.android.systemui.accessibility.qs.QSAccessibilityModule
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.qsEventLogger
+
+val Kosmos.qsReduceBrightColorsTileConfig by
+    Kosmos.Fixture { QSAccessibilityModule.provideReduceBrightColorsTileConfig(qsEventLogger) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/screenrecord/ScreenRecordTileKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/screenrecord/ScreenRecordTileKosmos.kt
new file mode 100644
index 0000000..ddcca94
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/screenrecord/ScreenRecordTileKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.screenrecord
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.qsEventLogger
+import com.android.systemui.screenrecord.ScreenRecordModule
+
+val Kosmos.qsScreenRecordTileConfig by
+    Kosmos.Fixture { ScreenRecordModule.provideScreenRecordTileConfig(qsEventLogger) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderKosmos.kt
new file mode 100644
index 0000000..1d57979
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfigProviderKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.fakeQSTileConfigProvider by Kosmos.Fixture { FakeQSTileConfigProvider() }
+var Kosmos.qSTileConfigProvider: QSTileConfigProvider by Kosmos.Fixture { fakeQSTileConfigProvider }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt
new file mode 100644
index 0000000..a908765
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapterKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.qsTileViewModelAdaperFactory by
+    Kosmos.Fixture {
+        object : QSTileViewModelAdapter.Factory {
+            override fun create(qsTileViewModel: QSTileViewModel): QSTileViewModelAdapter {
+                return QSTileViewModelAdapter(
+                    applicationCoroutineScope,
+                    mock(),
+                    qsTileViewModel,
+                )
+            }
+        }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
index 4d902fa..a654d6f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
@@ -18,6 +18,7 @@
 
 import android.content.Context
 import android.view.View
+import com.android.systemui.settings.brightness.MirrorController
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -41,6 +42,9 @@
     private val _navBarPadding = MutableStateFlow<Int>(0)
     val navBarPadding = _navBarPadding.asStateFlow()
 
+    var brightnessMirrorController: MirrorController? = null
+        private set
+
     override var isQsFullyCollapsed: Boolean = true
 
     override suspend fun inflate(context: Context) {
@@ -60,4 +64,12 @@
     override suspend fun applyBottomNavBarPadding(padding: Int) {
         _navBarPadding.value = padding
     }
+
+    override fun requestCloseCustomizer() {
+        _customizing.value = false
+    }
+
+    override fun setBrightnessMirrorController(mirrorController: MirrorController?) {
+        brightnessMirrorController = mirrorController
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
new file mode 100644
index 0000000..6ac3a62
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import com.android.systemui.scene.ui.view.WindowRootView
+import com.android.systemui.scene.ui.view.WindowRootViewComponent
+
+class FakeWindowRootViewComponent(private val view: WindowRootView) : WindowRootViewComponent {
+    override fun getWindowRootView(): WindowRootView {
+        return view
+    }
+
+    class Factory(private val view: WindowRootView) : WindowRootViewComponent.Factory {
+        override fun create(): WindowRootViewComponent = FakeWindowRootViewComponent(view)
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index 2cdf76d..7f6a7bd3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -2,6 +2,8 @@
 
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.shared.model.FakeScene
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
 
@@ -16,5 +18,18 @@
     )
 }
 
+val Kosmos.fakeScenes by Fixture {
+    sceneKeys
+        .map { key ->
+            FakeScene(
+                scope = testScope.backgroundScope,
+                key = key,
+            )
+        }
+        .toSet()
+}
+
+val Kosmos.scenes by Fixture { fakeScenes }
+
 val Kosmos.initialSceneKey by Fixture { Scenes.Lockscreen }
 val Kosmos.sceneContainerConfig by Fixture { SceneContainerConfig(sceneKeys, initialSceneKey) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
new file mode 100644
index 0000000..c7cf934
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.domain.interactor
+
+import com.android.internal.logging.uiEventLogger
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
+import com.android.systemui.classifier.falsingCollector
+import com.android.systemui.classifier.falsingManager
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.model.sysUiState
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.startable.SceneContainerStartable
+import com.android.systemui.scene.shared.logger.sceneLogger
+import com.android.systemui.settings.displayTracker
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
+import com.android.systemui.statusbar.notificationShadeWindowController
+import com.android.systemui.statusbar.phone.centralSurfaces
+import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
+import dagger.Lazy
+
+val Kosmos.sceneContainerStartable by Fixture {
+    SceneContainerStartable(
+        applicationScope = testScope.backgroundScope,
+        sceneInteractor = sceneInteractor,
+        deviceEntryInteractor = deviceEntryInteractor,
+        deviceUnlockedInteractor = deviceUnlockedInteractor,
+        bouncerInteractor = bouncerInteractor,
+        keyguardInteractor = keyguardInteractor,
+        sysUiState = sysUiState,
+        displayId = displayTracker.defaultDisplayId,
+        sceneLogger = sceneLogger,
+        falsingCollector = falsingCollector,
+        falsingManager = falsingManager,
+        powerInteractor = powerInteractor,
+        simBouncerInteractor = Lazy { simBouncerInteractor },
+        authenticationInteractor = Lazy { authenticationInteractor },
+        windowController = notificationShadeWindowController,
+        deviceProvisioningInteractor = deviceProvisioningInteractor,
+        centralSurfaces = centralSurfaces,
+        headsUpInteractor = headsUpNotificationInteractor,
+        occlusionInteractor = sceneContainerOcclusionInteractor,
+        faceUnlockInteractor = deviceEntryFaceAuthInteractor,
+        shadeInteractor = shadeInteractor,
+        uiEventLogger = uiEventLogger,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
deleted file mode 100644
index bae5257..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
+++ /dev/null
@@ -1,44 +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 com.android.systemui.scene.shared.flag
-
-import dagger.Binds
-import dagger.Module
-import dagger.Provides
-
-class FakeSceneContainerFlags(
-    var enabled: Boolean = false,
-) : SceneContainerFlags {
-
-    override fun isEnabled(): Boolean {
-        return enabled
-    }
-
-    override fun requirementDescription(): String {
-        return ""
-    }
-}
-
-@Module(includes = [FakeSceneContainerFlagsModule.Bindings::class])
-class FakeSceneContainerFlagsModule(
-    @get:Provides val sceneContainerFlags: FakeSceneContainerFlags = FakeSceneContainerFlags(),
-) {
-    @Module
-    interface Bindings {
-        @Binds fun bindFake(fake: FakeSceneContainerFlags): SceneContainerFlags
-    }
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsKosmos.kt
deleted file mode 100644
index 979d8e7..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsKosmos.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.shared.flag
-
-import com.android.systemui.kosmos.Kosmos
-
-var Kosmos.fakeSceneContainerFlags by Kosmos.Fixture { FakeSceneContainerFlags() }
-val Kosmos.sceneContainerFlags by Kosmos.Fixture<SceneContainerFlags> { fakeSceneContainerFlags }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeScene.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeScene.kt
new file mode 100644
index 0000000..eeaa9db
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeScene.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.shared.model
+
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.onCompletion
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.flow.stateIn
+
+class FakeScene(
+    val scope: CoroutineScope,
+    override val key: SceneKey,
+) : Scene {
+    var isDestinationScenesBeingCollected = false
+
+    private val destinationScenesChannel = Channel<Map<UserAction, UserActionResult>>()
+
+    override val destinationScenes =
+        destinationScenesChannel
+            .receiveAsFlow()
+            .onStart { isDestinationScenesBeingCollected = true }
+            .onCompletion { isDestinationScenesBeingCollected = false }
+            .stateIn(
+                scope = scope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = emptyMap(),
+            )
+
+    suspend fun setDestinationScenes(value: Map<UserAction, UserActionResult>) {
+        destinationScenesChannel.send(value)
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
new file mode 100644
index 0000000..8b7e5d8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings
+
+import com.android.internal.logging.uiEventLogger
+import com.android.systemui.classifier.falsingManager
+import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.settings.brightness.BrightnessSliderController
+import com.android.systemui.util.time.systemClock
+
+/** This factory creates empty mocks. */
+var Kosmos.brightnessSliderControllerFactory by
+    Kosmos.Fixture<BrightnessSliderController.Factory> {
+        BrightnessSliderController.Factory(
+            falsingManager,
+            uiEventLogger,
+            vibratorHelper,
+            systemClock,
+            activityStarter,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepositoryKosmos.kt
new file mode 100644
index 0000000..6db46499
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/data/repository/BrightnessMirrorShowingRepositoryKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.brightnessMirrorShowingRepository by
+    Kosmos.Fixture { BrightnessMirrorShowingRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractorKosmos.kt
new file mode 100644
index 0000000..8f6b829
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/domain/interactor/BrightnessMirrorShowingInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.settings.brightness.data.repository.brightnessMirrorShowingRepository
+
+val Kosmos.brightnessMirrorShowingInteractor by
+    Kosmos.Fixture { BrightnessMirrorShowingInteractor(brightnessMirrorShowingRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/ui/viewmodel/BrightnessMirrorViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/ui/viewmodel/BrightnessMirrorViewModelKosmos.kt
new file mode 100644
index 0000000..8fb370c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/brightness/ui/viewmodel/BrightnessMirrorViewModelKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings.brightness.ui.viewmodel
+
+import android.content.res.mainResources
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
+import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
+import com.android.systemui.settings.brightnessSliderControllerFactory
+
+val Kosmos.brightnessMirrorViewModel by
+    Kosmos.Fixture {
+        BrightnessMirrorViewModel(
+            brightnessMirrorShowingInteractor,
+            mainResources,
+            brightnessSliderControllerFactory,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
new file mode 100644
index 0000000..a47b2e8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.data.repository.FakeShadeRepository
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import org.junit.Assert
+
+/** Sets up shade state for tests for either value of the scene container flag. */
+class ShadeTestUtil constructor(val delegate: ShadeTestUtilDelegate) {
+
+    /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */
+    fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) {
+        Assert.assertTrue(
+            "One expansion must be zero or both must add up to 1",
+            shadeExpansion == 0f || qsExpansion == 0f || shadeExpansion + qsExpansion == 1f,
+        )
+        delegate.assertFlagValid()
+        delegate.setShadeAndQsExpansionInternal(shadeExpansion, qsExpansion)
+    }
+}
+
+/** Sets up shade state for tests for a specific value of the scene container flag. */
+interface ShadeTestUtilDelegate {
+    /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */
+    fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float)
+
+    /** Asserts that the scene container flag matches this implementation. */
+    fun assertFlagValid()
+}
+
+/** Sets up shade state for tests when the scene container flag is disabled. */
+class ShadeTestUtilLegacyImpl(val testScope: TestScope, val shadeRepository: FakeShadeRepository) :
+    ShadeTestUtilDelegate {
+    override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) {
+        shadeRepository.setLegacyShadeExpansion(shadeExpansion)
+        shadeRepository.setQsExpansion(qsExpansion)
+        testScope.runCurrent()
+    }
+
+    override fun assertFlagValid() {
+        Assert.assertFalse(SceneContainerFlag.isEnabled)
+    }
+}
+
+/** Sets up shade state for tests when the scene container flag is disabled. */
+class ShadeTestUtilSceneImpl(val testScope: TestScope, val sceneInteractor: SceneInteractor) :
+    ShadeTestUtilDelegate {
+    override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) {
+        if (shadeExpansion == 0f) {
+            setTransitionProgress(Scenes.Lockscreen, Scenes.QuickSettings, qsExpansion)
+        } else if (qsExpansion == 0f) {
+            setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, shadeExpansion)
+        } else {
+            setTransitionProgress(Scenes.Shade, Scenes.QuickSettings, qsExpansion)
+        }
+    }
+
+    private fun setTransitionProgress(from: SceneKey, to: SceneKey, progress: Float) {
+        sceneInteractor.changeScene(from, "test")
+        val transitionState =
+            MutableStateFlow<ObservableTransitionState>(
+                ObservableTransitionState.Transition(
+                    fromScene = from,
+                    toScene = to,
+                    progress = MutableStateFlow(progress),
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
+                )
+            )
+        sceneInteractor.setTransitionState(transitionState)
+        testScope.runCurrent()
+    }
+
+    override fun assertFlagValid() {
+        Assert.assertTrue(SceneContainerFlag.isEnabled)
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtilKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtilKosmos.kt
new file mode 100644
index 0000000..9eeb345
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtilKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.shade.data.repository.fakeShadeRepository
+
+var Kosmos.shadeTestUtil: ShadeTestUtil by
+    Kosmos.Fixture {
+        ShadeTestUtil(
+            if (SceneContainerFlag.isEnabled) {
+                ShadeTestUtilSceneImpl(testScope, sceneInteractor)
+            } else {
+                ShadeTestUtilLegacyImpl(testScope, fakeShadeRepository)
+            }
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
index 07e2d6b..543d5b6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
@@ -23,7 +23,6 @@
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.shade.ShadeModule
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.statusbar.disableflags.data.repository.disableFlagsRepository
@@ -36,7 +35,6 @@
 var Kosmos.baseShadeInteractor: BaseShadeInteractor by
     Kosmos.Fixture {
         ShadeModule.provideBaseShadeInteractor(
-            sceneContainerFlags = sceneContainerFlags,
             sceneContainerOn = { shadeInteractorSceneContainerImpl },
             sceneContainerOff = { shadeInteractorLegacyImpl },
         )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.kt
new file mode 100644
index 0000000..8d653f7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelKosmos.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.shade.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.plugins.activityStarter
+import com.android.systemui.shade.domain.interactor.privacyChipInteractor
+import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.mobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.mobileIconsViewModel
+
+val Kosmos.shadeHeaderViewModel: ShadeHeaderViewModel by
+    Kosmos.Fixture {
+        ShadeHeaderViewModel(
+            applicationScope = applicationCoroutineScope,
+            context = applicationContext,
+            activityStarter = activityStarter,
+            shadeInteractor = shadeInteractor,
+            mobileIconsInteractor = mobileIconsInteractor,
+            mobileIconsViewModel = mobileIconsViewModel,
+            privacyChipInteractor = privacyChipInteractor,
+            clockInteractor = shadeHeaderClockInteractor,
+            broadcastDispatcher = broadcastDispatcher,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
new file mode 100644
index 0000000..73b775e
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.pulseExpansionHandler: PulseExpansionHandler by
+    Kosmos.Fixture { mock<PulseExpansionHandler>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderKosmos.kt
new file mode 100644
index 0000000..9a5f126
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderKosmos.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.provider
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.visualStabilityProvider by Kosmos.Fixture { VisualStabilityProvider() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt
index 165c942..7bf77e5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/data/repository/HeadsUpNotificationRepositoryKosmos.kt
@@ -26,8 +26,11 @@
 val Kosmos.headsUpNotificationRepository by Fixture { FakeHeadsUpNotificationRepository() }
 
 class FakeHeadsUpNotificationRepository : HeadsUpRepository {
-    override val headsUpAnimatingAway: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    override val isHeadsUpAnimatingAway: MutableStateFlow<Boolean> = MutableStateFlow(false)
     override val topHeadsUpRow: Flow<HeadsUpRowRepository?> = MutableStateFlow(null)
     override val activeHeadsUpRows: MutableStateFlow<Set<HeadsUpRowRepository>> =
         MutableStateFlow(emptySet())
+    override fun setHeadsUpAnimatingAway(animatingAway: Boolean) {
+        isHeadsUpAnimatingAway.value = animatingAway
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt
index c65d0a3..94f6ecd3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
+import com.android.systemui.dump.dumpManager
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
@@ -48,5 +49,6 @@
         userSetupInteractor,
         zenModeInteractor,
         testDispatcher,
+        dumpManager,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt
new file mode 100644
index 0000000..6370a5d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.ui.viewmodel
+
+import com.android.systemui.dump.dumpManager
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor
+
+val Kosmos.notificationScrollViewModel by Fixture {
+    NotificationScrollViewModel(
+        dumpManager = dumpManager,
+        stackAppearanceInteractor = notificationStackAppearanceInteractor,
+        shadeInteractor = shadeInteractor,
+        sceneInteractor = sceneInteractor,
+        keyguardInteractor = { keyguardInteractor },
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModelKosmos.kt
deleted file mode 100644
index bada2a6..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModelKosmos.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.stack.ui.viewmodel
-
-import com.android.systemui.dump.dumpManager
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor
-
-val Kosmos.notificationStackAppearanceViewModel by Fixture {
-    NotificationStackAppearanceViewModel(
-        dumpManager = dumpManager,
-        stackAppearanceInteractor = notificationStackAppearanceInteractor,
-        shadeInteractor = shadeInteractor,
-        sceneInteractor = sceneInteractor,
-    )
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt
index 29faa58..f0eea38 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt
@@ -16,19 +16,19 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
+import com.android.systemui.dump.dumpManager
 import com.android.systemui.flags.featureFlagsClassic
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor
 
 val Kosmos.notificationsPlaceholderViewModel by Fixture {
     NotificationsPlaceholderViewModel(
+        dumpManager = dumpManager,
         interactor = notificationStackAppearanceInteractor,
         shadeInteractor = shadeInteractor,
-        flags = sceneContainerFlags,
         featureFlags = featureFlagsClassic,
         keyguardInteractor = keyguardInteractor,
     )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
index de0cc65..cbba80b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.lockscreenToOccludedTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.lockscreenToPrimaryBouncerTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.occludedToAodTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.occludedToGoneTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.occludedToLockscreenTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.primaryBouncerToGoneTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.primaryBouncerToLockscreenTransitionViewModel
@@ -43,7 +44,9 @@
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
+import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -55,6 +58,7 @@
         keyguardInteractor = keyguardInteractor,
         keyguardTransitionInteractor = keyguardTransitionInteractor,
         shadeInteractor = shadeInteractor,
+        notificationStackAppearanceInteractor = notificationStackAppearanceInteractor,
         alternateBouncerToGoneTransitionViewModel = alternateBouncerToGoneTransitionViewModel,
         aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
         aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel,
@@ -72,10 +76,12 @@
         lockscreenToPrimaryBouncerTransitionViewModel =
             lockscreenToPrimaryBouncerTransitionViewModel,
         occludedToAodTransitionViewModel = occludedToAodTransitionViewModel,
+        occludedToGoneTransitionViewModel = occludedToGoneTransitionViewModel,
         occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
         primaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel,
         primaryBouncerToLockscreenTransitionViewModel =
             primaryBouncerToLockscreenTransitionViewModel,
         aodBurnInViewModel = aodBurnInViewModel,
+        unfoldTransitionInteractor = unfoldTransitionInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt
index cf800d0..9c3f510 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/WindowRootViewVisibilityInteractorKosmos.kt
@@ -24,7 +24,6 @@
 import com.android.systemui.scene.data.repository.windowRootViewVisibilityRepository
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.shared.flag.sceneContainerFlags
 import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
 import com.android.systemui.statusbar.policy.headsUpManager
 
@@ -36,7 +35,7 @@
         headsUpManager = headsUpManager,
         powerInteractor = powerInteractor,
         activeNotificationsInteractor = activeNotificationsInteractor,
-        sceneInteractorProvider = { sceneInteractor },
-        sceneContainerFlags = sceneContainerFlags,
-    )
+    ) {
+        sceneInteractor
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/BiometricUnlockController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/BiometricUnlockController.kt
new file mode 100644
index 0000000..f377e28b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/BiometricUnlockController.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.phone
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.biometricUnlockController: BiometricUnlockController by Fixture {
+    mock<BiometricUnlockController>()
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt
new file mode 100644
index 0000000..1611f62
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/CentralSurfacesKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.centralSurfaces by Fixture { mock<CentralSurfaces>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeScrimController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeScrimController.kt
new file mode 100644
index 0000000..0a1923d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeScrimController.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.dozeScrimController: DozeScrimController by Fixture { mock<DozeScrimController>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt
index 370b177..0b5a68e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt
@@ -16,9 +16,45 @@
 
 package com.android.systemui.statusbar.phone
 
+import android.os.powerManager
+import com.android.keyguard.keyguardUpdateMonitor
+import com.android.systemui.assist.assistManager
+import com.android.systemui.biometrics.authController
+import com.android.systemui.doze.dozeLog
+import com.android.systemui.keyguard.domain.interactor.dozeInteractor
+import com.android.systemui.keyguard.wakefulnessLifecycle
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.plugins.statusbar.statusBarStateController
+import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor
+import com.android.systemui.statusbar.notificationShadeWindowController
+import com.android.systemui.statusbar.policy.batteryController
+import com.android.systemui.statusbar.policy.deviceProvisionedController
+import com.android.systemui.statusbar.policy.headsUpManager
+import com.android.systemui.statusbar.pulseExpansionHandler
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import org.mockito.Mockito.mock
 
 @OptIn(ExperimentalCoroutinesApi::class)
-val Kosmos.dozeServiceHost: DozeServiceHost by Kosmos.Fixture { mock(DozeServiceHost::class.java) }
+val Kosmos.dozeServiceHost: DozeServiceHost by
+    Kosmos.Fixture {
+        DozeServiceHost(
+            dozeLog,
+            powerManager,
+            wakefulnessLifecycle,
+            statusBarStateController,
+            deviceProvisionedController,
+            headsUpManager,
+            batteryController,
+            scrimController,
+            { biometricUnlockController },
+            { assistManager },
+            dozeScrimController,
+            keyguardUpdateMonitor,
+            pulseExpansionHandler,
+            notificationShadeWindowController,
+            notificationWakeUpCoordinator,
+            authController,
+            notificationIconAreaController,
+            shadeLockscreenInteractor,
+            dozeInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/NotificationWakeUpCoordinator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/NotificationWakeUpCoordinator.kt
new file mode 100644
index 0000000..0c0f87b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/NotificationWakeUpCoordinator.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.notificationWakeUpCoordinator: NotificationWakeUpCoordinator by Fixture {
+    mock<NotificationWakeUpCoordinator>()
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
new file mode 100644
index 0000000..74b2da4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.airplane.data.repository
+
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class FakeAirplaneModeRepository : AirplaneModeRepository {
+
+    private val _isAirplaneMode = MutableStateFlow(false)
+    override val isAirplaneMode: StateFlow<Boolean> = _isAirplaneMode
+
+    override suspend fun setIsAirplaneMode(isEnabled: Boolean) {
+        _isAirplaneMode.value = isEnabled
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
new file mode 100644
index 0000000..386c7c5
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.airplane.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+
+val Kosmos.airplaneModeInteractor: AirplaneModeInteractor by
+    Kosmos.Fixture {
+        AirplaneModeInteractor(
+            FakeAirplaneModeRepository(),
+            FakeConnectivityRepository(),
+            FakeMobileConnectionsRepository(),
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
index 2d5a361..eb2d6c0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
@@ -31,6 +31,7 @@
     override val tableLogBuffer: TableLogBuffer,
 ) : MobileConnectionRepository {
     override val carrierId = MutableStateFlow(UNKNOWN_CARRIER_ID)
+    override val inflateSignalStrength: MutableStateFlow<Boolean> = MutableStateFlow(false)
     override val isEmergencyOnly = MutableStateFlow(false)
     override val isRoaming = MutableStateFlow(false)
     override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
@@ -63,8 +64,6 @@
 
     override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false)
 
-    override val satelliteConnectionHysteresisSeconds = MutableStateFlow(0)
-
     private var isInEcmMode: Boolean = false
 
     override suspend fun isInEcmMode(): Boolean = isInEcmMode
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorKosmos.kt
new file mode 100644
index 0000000..eb6265a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorKosmos.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.mobileIconsInteractor: MobileIconsInteractor by
+    Kosmos.Fixture { fakeMobileIconsInteractor }
+val Kosmos.fakeMobileIconsInteractor: FakeMobileIconsInteractor by
+    Kosmos.Fixture { FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelKosmos.kt
new file mode 100644
index 0000000..c5f6557
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelKosmos.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
+
+import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.airplaneModeInteractor
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.mobileIconsInteractor
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.mobileIconsViewModel: MobileIconsViewModel by
+    Kosmos.Fixture {
+        MobileIconsViewModel(
+            logger = mock(),
+            verboseLogger = mock(),
+            interactor = mobileIconsInteractor,
+            airplaneModeInteractor = airplaneModeInteractor,
+            constants = mock(),
+            flags = featureFlagsClassic,
+            scope = applicationCoroutineScope,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
new file mode 100644
index 0000000..331e2fa
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.data.repository
+
+import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
+import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+/** Fake implementation of [ConnectivityRepository] exposing set methods for all the flows. */
+class FakeConnectivityRepository : ConnectivityRepository {
+    private val _forceHiddenIcons: MutableStateFlow<Set<ConnectivitySlot>> =
+        MutableStateFlow(emptySet())
+    override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = _forceHiddenIcons
+
+    override val defaultConnections: MutableStateFlow<DefaultConnectionModel> =
+        MutableStateFlow(DefaultConnectionModel())
+
+    override val vcnSubId: MutableStateFlow<Int?> = MutableStateFlow(null)
+
+    fun setForceHiddenIcons(hiddenIcons: Set<ConnectivitySlot>) {
+        _forceHiddenIcons.value = hiddenIcons
+    }
+
+    /**
+     * Convenience for setting mobile data connected, disconnected, or validated. Defaults to
+     * setting mobile connected && validated, since the default state is disconnected && not
+     * validated
+     */
+    @JvmOverloads
+    fun setMobileConnected(
+        default: Boolean = true,
+        validated: Boolean = true,
+    ) {
+        defaultConnections.value =
+            DefaultConnectionModel(
+                mobile = DefaultConnectionModel.Mobile(default),
+                isValidated = validated,
+            )
+    }
+
+    /** Similar convenience method for ethernet */
+    @JvmOverloads
+    fun setEthernetConnected(
+        default: Boolean = true,
+        validated: Boolean = true,
+    ) {
+        defaultConnections.value =
+            DefaultConnectionModel(
+                ethernet = DefaultConnectionModel.Ethernet(default),
+                isValidated = validated,
+            )
+    }
+
+    @JvmOverloads
+    fun setWifiConnected(
+        default: Boolean = true,
+        validated: Boolean = true,
+    ) {
+        defaultConnections.value =
+            DefaultConnectionModel(
+                wifi = DefaultConnectionModel.Wifi(default),
+                isValidated = validated,
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/BatteryControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/BatteryControllerKosmos.kt
new file mode 100644
index 0000000..b31a45c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/BatteryControllerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.batteryController: BatteryController by Fixture { mock<BatteryController>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt
index d38baba..7e993b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt
@@ -16,6 +16,31 @@
 
 package com.android.systemui.statusbar.ui
 
-class FakeSystemBarUtilsProxy(private var statusBarHeight: Int) : SystemBarUtilsProxy {
-    override fun getStatusBarHeight(): Int = statusBarHeight
+import com.android.systemui.statusbar.policy.FakeConfigurationController
+
+class FakeSystemBarUtilsProxy(
+    val fakeConfigurationController: FakeConfigurationController,
+    statusBarHeight: Int,
+    keyguardStatusBarHeight: Int,
+) : SystemBarUtilsProxy {
+    var fakeStatusBarHeight: Int = statusBarHeight
+        get() = field
+        set(value) {
+            if (field != value) {
+                field = value
+                fakeConfigurationController.notifyConfigurationChanged()
+            }
+        }
+
+    var fakeKeyguardStatusBarHeight = keyguardStatusBarHeight
+        get() = field
+        set(value) {
+            if (field != value) {
+                field = value
+                fakeConfigurationController.notifyConfigurationChanged()
+            }
+        }
+
+    override fun getStatusBarHeight(): Int = fakeStatusBarHeight
+    override fun getStatusBarHeaderHeightKeyguard(): Int = fakeKeyguardStatusBarHeight
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt
index f24037d..dce22f8b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.res.R
+import com.android.systemui.statusbar.policy.fakeConfigurationController
 
 /**
  * Main fixture for supplying a [SystemBarUtilsProxy]. Should be used by other fixtures. Unless
@@ -47,5 +48,9 @@
  * tests in order to provide custom results.
  */
 var Kosmos.fakeSystemBarUtilsProxy by Fixture {
-    FakeSystemBarUtilsProxy(mainResources.getDimensionPixelSize(R.dimen.status_bar_height))
+    FakeSystemBarUtilsProxy(
+        fakeConfigurationController,
+        mainResources.getDimensionPixelSize(R.dimen.status_bar_height),
+        mainResources.getDimensionPixelSize(R.dimen.status_bar_header_height_keyguard),
+    )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/truth/TruthUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/TruthUtils.kt
new file mode 100644
index 0000000..64fed68
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/truth/TruthUtils.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.truth
+
+import com.google.common.truth.MapSubject
+import com.google.common.truth.Ordered
+
+fun MapSubject.containsEntriesExactly(entry: Pair<*, *>, vararg entries: Pair<*, *>): Ordered =
+    containsExactly(
+        entry.first,
+        entry.second,
+        *entries
+            .asSequence()
+            .flatMap { (key, value) -> sequenceOf(key, value) }
+            .toList()
+            .toTypedArray()
+    )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FakeUnfoldTransitionProvider.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FakeUnfoldTransitionProvider.kt
new file mode 100644
index 0000000..94f0c44
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FakeUnfoldTransitionProvider.kt
@@ -0,0 +1,36 @@
+package com.android.systemui.unfold
+
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+
+class FakeUnfoldTransitionProvider : UnfoldTransitionProgressProvider, TransitionProgressListener {
+
+    private val listeners = mutableListOf<TransitionProgressListener>()
+
+    override fun destroy() {
+        listeners.clear()
+    }
+
+    override fun addCallback(listener: TransitionProgressListener) {
+        listeners.add(listener)
+    }
+
+    override fun removeCallback(listener: TransitionProgressListener) {
+        listeners.remove(listener)
+    }
+
+    override fun onTransitionStarted() {
+        listeners.forEach { it.onTransitionStarted() }
+    }
+
+    override fun onTransitionFinished() {
+        listeners.forEach { it.onTransitionFinished() }
+    }
+
+    override fun onTransitionFinishing() {
+        listeners.forEach { it.onTransitionFinishing() }
+    }
+
+    override fun onTransitionProgress(progress: Float) {
+        listeners.forEach { it.onTransitionProgress(progress) }
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FullscreenLightRevealAnimationKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FullscreenLightRevealAnimationKosmos.kt
new file mode 100644
index 0000000..43d6c48
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/FullscreenLightRevealAnimationKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+
+var Kosmos.fullscreenLightRevealAnimationController by Fixture {
+    mock<FullscreenLightRevealAnimationController>()
+}
+var Kosmos.fullscreenLightRevealAnimationControllerFactory by Fixture {
+    var mockControllerFactory = mock<FullscreenLightRevealAnimationController.Factory>()
+    whenever(mockControllerFactory.create(any(), any(), any()))
+        .thenReturn(fullscreenLightRevealAnimationController)
+    mockControllerFactory
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt
index 7c54a57..a0f5b58 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/UnfoldTransitionProgressProviderKosmos.kt
@@ -18,6 +18,8 @@
 
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.util.mockito.mock
 
-var Kosmos.unfoldTransitionProgressProvider by Fixture { mock<UnfoldTransitionProgressProvider>() }
+val Kosmos.fakeUnfoldTransitionProgressProvider by Fixture { FakeUnfoldTransitionProvider() }
+
+val Kosmos.unfoldTransitionProgressProvider by
+    Fixture<UnfoldTransitionProgressProvider> { fakeUnfoldTransitionProgressProvider }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorKosmos.kt
index d03616a..6faa3b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/unfold/domain/interactor/UnfoldTransitionInteractorKosmos.kt
@@ -16,10 +16,14 @@
 
 package com.android.systemui.unfold.domain.interactor
 
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.unfold.data.repository.unfoldTransitionRepository
 
 val Kosmos.unfoldTransitionInteractor by Fixture {
-    UnfoldTransitionInteractorImpl(repository = unfoldTransitionRepository)
+    UnfoldTransitionInteractor(
+        repository = unfoldTransitionRepository,
+        configurationInteractor = configurationInteractor,
+    )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
deleted file mode 100644
index 5e1f85c..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume
-
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.data.repository.FakeAudioRepository
-
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
-val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
new file mode 100644
index 0000000..5cf214a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
index 4788624..617fc52 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
@@ -30,16 +30,14 @@
 class FakeAudioRepository : AudioRepository {
 
     private val mutableMode = MutableStateFlow(0)
-    override val mode: StateFlow<Int>
-        get() = mutableMode.asStateFlow()
+    override val mode: StateFlow<Int> = mutableMode.asStateFlow()
 
     private val mutableRingerMode = MutableStateFlow(RingerMode(0))
-    override val ringerMode: StateFlow<RingerMode>
-        get() = mutableRingerMode.asStateFlow()
+    override val ringerMode: StateFlow<RingerMode> = mutableRingerMode.asStateFlow()
 
     private val mutableCommunicationDevice = MutableStateFlow<AudioDeviceInfo?>(null)
-    override val communicationDevice: StateFlow<AudioDeviceInfo?>
-        get() = mutableCommunicationDevice.asStateFlow()
+    override val communicationDevice: StateFlow<AudioDeviceInfo?> =
+        mutableCommunicationDevice.asStateFlow()
 
     private val models: MutableMap<AudioStream, MutableStateFlow<AudioStreamModel>> = mutableMapOf()
     private val lastAudibleVolumes: MutableMap<AudioStream, Int> = mutableMapOf()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioModeInteractorKosmos.kt
new file mode 100644
index 0000000..99354be
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioModeInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.interactor
+
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.volume.data.repository.audioRepository
+
+val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt
new file mode 100644
index 0000000..1b18ff5
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.interactor
+
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.bluetooth.localBluetoothManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.localMediaRepositoryFactory
+import com.android.systemui.volume.mediaOutputInteractor
+
+val Kosmos.audioOutputInteractor by
+    Kosmos.Fixture {
+        AudioOutputInteractor(
+            audioRepository,
+            audioModeInteractor,
+            testScope.backgroundScope,
+            testScope.testScheduler,
+            localBluetoothManager,
+            bluetoothAdapter,
+            deviceIconInteractor,
+            mediaOutputInteractor,
+            localMediaRepositoryFactory,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractorKosmos.kt
new file mode 100644
index 0000000..0a27c2a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.domain.interactor
+
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
+
+var Kosmos.deviceIconInteractor: DeviceIconInteractor by
+    Kosmos.Fixture { DeviceIconInteractor(applicationContext) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt
index d341073..348a02e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/VolumePanelKosmos.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.volume.panel.dagger.factory.KosmosVolumePanelComponentFactory
 import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
 import com.android.systemui.volume.panel.domain.TestComponentAvailabilityCriteria
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
 import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor
 import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractorImpl
 import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
@@ -44,6 +45,8 @@
 var Kosmos.componentsLayoutManager: ComponentsLayoutManager by Kosmos.Fixture()
 var Kosmos.enabledComponents: Collection<VolumePanelComponentKey> by
     Kosmos.Fixture { componentByKey.keys }
+var Kosmos.volumePanelStartables: Set<VolumePanelStartable> by
+    Kosmos.Fixture { emptySet<VolumePanelStartable>() }
 val Kosmos.unavailableCriteria: Provider<ComponentAvailabilityCriteria> by
     Kosmos.Fixture { Provider { TestComponentAvailabilityCriteria(false) } }
 val Kosmos.availableCriteria: Provider<ComponentAvailabilityCriteria> by
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt
index b66d7f9..d4a72b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/anc/data/repository/FakeAncSliceRepository.kt
@@ -24,8 +24,9 @@
 
     private val sliceByWidth = mutableMapOf<Int, MutableStateFlow<Slice?>>()
 
-    override fun ancSlice(width: Int): Flow<Slice?> =
-        sliceByWidth.getOrPut(width) { MutableStateFlow(null) }
+    override fun ancSlice(width: Int, isCollapsed: Boolean, hideLabel: Boolean): Flow<Slice?> {
+        return sliceByWidth.getOrPut(width) { MutableStateFlow(null) }
+    }
 
     fun putSlice(width: Int, slice: Slice?) {
         sliceByWidth.getOrPut(width) { MutableStateFlow(null) }.value = slice
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt
index 49041ed..e5f5d4e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/dagger/factory/KosmosVolumePanelComponentFactory.kt
@@ -22,10 +22,12 @@
 import com.android.systemui.volume.panel.componentsInteractor
 import com.android.systemui.volume.panel.componentsLayoutManager
 import com.android.systemui.volume.panel.dagger.VolumePanelComponent
+import com.android.systemui.volume.panel.domain.VolumePanelStartable
 import com.android.systemui.volume.panel.domain.interactor.ComponentsInteractor
 import com.android.systemui.volume.panel.ui.composable.ComponentsFactory
 import com.android.systemui.volume.panel.ui.layout.ComponentsLayoutManager
 import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
+import com.android.systemui.volume.panel.volumePanelStartables
 import kotlinx.coroutines.CoroutineScope
 
 class KosmosVolumePanelComponentFactory(private val kosmos: Kosmos) : VolumePanelComponentFactory {
@@ -41,5 +43,8 @@
 
             override fun componentsLayoutManager(): ComponentsLayoutManager =
                 kosmos.componentsLayoutManager
+
+            override fun volumePanelStartables(): Set<VolumePanelStartable> =
+                kosmos.volumePanelStartables
         }
 }
diff --git a/packages/SystemUI/utils/Android.bp b/packages/SystemUI/utils/Android.bp
new file mode 100644
index 0000000..1ef3816
--- /dev/null
+++ b/packages/SystemUI/utils/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+java_library {
+    name: "SystemUI-shared-utils",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    static_libs: [
+        "kotlin-stdlib",
+        "kotlinx_coroutines",
+    ],
+}
diff --git a/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/FlowConflated.kt b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/FlowConflated.kt
new file mode 100644
index 0000000..ed97c60
--- /dev/null
+++ b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/FlowConflated.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalTypeInference::class)
+
+package com.android.systemui.utils.coroutines.flow
+
+import kotlin.experimental.ExperimentalTypeInference
+import kotlinx.coroutines.channels.ProducerScope
+import kotlinx.coroutines.channels.SendChannel
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.buffer
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.channelFlow
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.produceIn
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+/**
+ * Creates an instance of a _cold_ [Flow] with elements that are sent to a [SendChannel] provided to
+ * the builder's [block] of code via [ProducerScope]. It allows elements to be produced by code that
+ * is running in a different context or concurrently.
+ *
+ * The resulting flow is _cold_, which means that [block] is called every time a terminal operator
+ * is applied to the resulting flow.
+ *
+ * This builder ensures thread-safety and context preservation, thus the provided [ProducerScope]
+ * can be used from any context, e.g. from a callback-based API. The resulting flow completes as
+ * soon as the code in the [block] completes. [awaitClose] should be used to keep the flow running,
+ * otherwise the channel will be closed immediately when block completes. [awaitClose] argument is
+ * called either when a flow consumer cancels the flow collection or when a callback-based API
+ * invokes [SendChannel.close] manually and is typically used to cleanup the resources after the
+ * completion, e.g. unregister a callback. Using [awaitClose] is mandatory in order to prevent
+ * memory leaks when the flow collection is cancelled, otherwise the callback may keep running even
+ * when the flow collector is already completed. To avoid such leaks, this method throws
+ * [IllegalStateException] if block returns, but the channel is not closed yet.
+ *
+ * A [conflated][conflate] channel is used. Use the [buffer] operator on the resulting flow to
+ * specify a user-defined value and to control what happens when data is produced faster than
+ * consumed, i.e. to control the back-pressure behavior.
+ *
+ * Adjacent applications of [callbackFlow], [flowOn], [buffer], and [produceIn] are always fused so
+ * that only one properly configured channel is used for execution.
+ *
+ * Example of usage that converts a multi-shot callback API to a flow. For single-shot callbacks use
+ * [suspendCancellableCoroutine].
+ *
+ * ```
+ * fun flowFrom(api: CallbackBasedApi): Flow<T> = callbackFlow {
+ *     val callback = object : Callback { // Implementation of some callback interface
+ *         override fun onNextValue(value: T) {
+ *             // To avoid blocking you can configure channel capacity using
+ *             // either buffer(Channel.CONFLATED) or buffer(Channel.UNLIMITED) to avoid overfill
+ *             trySendBlocking(value)
+ *                 .onFailure { throwable ->
+ *                     // Downstream has been cancelled or failed, can log here
+ *                 }
+ *         }
+ *         override fun onApiError(cause: Throwable) {
+ *             cancel(CancellationException("API Error", cause))
+ *         }
+ *         override fun onCompleted() = channel.close()
+ *     }
+ *     api.register(callback)
+ *     /*
+ *      * Suspends until either 'onCompleted'/'onApiError' from the callback is invoked
+ *      * or flow collector is cancelled (e.g. by 'take(1)' or because a collector's coroutine was cancelled).
+ *      * In both cases, callback will be properly unregistered.
+ *      */
+ *     awaitClose { api.unregister(callback) }
+ * }
+ * ```
+ * > The callback `register`/`unregister` methods provided by an external API must be thread-safe,
+ * > because `awaitClose` block can be called at any time due to asynchronous nature of
+ * > cancellation, even concurrently with the call of the callback.
+ *
+ * This builder is to be preferred over [callbackFlow], due to the latter's default configuration of
+ * using an internal buffer, negatively impacting system health.
+ *
+ * @see callbackFlow
+ */
+fun <T> conflatedCallbackFlow(
+    @BuilderInference block: suspend ProducerScope<T>.() -> Unit,
+): Flow<T> = callbackFlow(block).conflate()
+
+/**
+ * Creates an instance of a _cold_ [Flow] with elements that are sent to a [SendChannel] provided to
+ * the builder's [block] of code via [ProducerScope]. It allows elements to be produced by code that
+ * is running in a different context or concurrently. The resulting flow is _cold_, which means that
+ * [block] is called every time a terminal operator is applied to the resulting flow.
+ *
+ * This builder ensures thread-safety and context preservation, thus the provided [ProducerScope]
+ * can be used concurrently from different contexts. The resulting flow completes as soon as the
+ * code in the [block] and all its children completes. Use [awaitClose] as the last statement to
+ * keep it running. A more detailed example is provided in the documentation of [callbackFlow].
+ *
+ * A [conflated][conflate] channel is used. Use the [buffer] operator on the resulting flow to
+ * specify a user-defined value and to control what happens when data is produced faster than
+ * consumed, i.e. to control the back-pressure behavior.
+ *
+ * Adjacent applications of [channelFlow], [flowOn], [buffer], and [produceIn] are always fused so
+ * that only one properly configured channel is used for execution.
+ *
+ * Examples of usage:
+ * ```
+ * fun <T> Flow<T>.merge(other: Flow<T>): Flow<T> = channelFlow {
+ *     // collect from one coroutine and send it
+ *     launch {
+ *         collect { send(it) }
+ *     }
+ *     // collect and send from this coroutine, too, concurrently
+ *     other.collect { send(it) }
+ * }
+ *
+ * fun <T> contextualFlow(): Flow<T> = channelFlow {
+ *     // send from one coroutine
+ *     launch(Dispatchers.IO) {
+ *         send(computeIoValue())
+ *     }
+ *     // send from another coroutine, concurrently
+ *     launch(Dispatchers.Default) {
+ *         send(computeCpuValue())
+ *     }
+ * }
+ * ```
+ *
+ * This builder is to be preferred over [channelFlow], due to the latter's default configuration of
+ * using an internal buffer, negatively impacting system health.
+ *
+ * @see channelFlow
+ */
+fun <T> conflatedChannelFlow(
+    @BuilderInference block: suspend ProducerScope<T>.() -> Unit,
+): Flow<T> = channelFlow(block).conflate()
diff --git a/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/LatestConflated.kt b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/LatestConflated.kt
new file mode 100644
index 0000000..5f8c660
--- /dev/null
+++ b/packages/SystemUI/utils/src/com/android/systemui/utils/coroutines/flow/LatestConflated.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalTypeInference::class)
+
+package com.android.systemui.utils.coroutines.flow
+
+import kotlin.experimental.ExperimentalTypeInference
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.FlowCollector
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.transformLatest
+
+/**
+ * Returns a flow that emits elements from the original flow transformed by [transform] function.
+ * When the original flow emits a new value, computation of the [transform] block for previous value
+ * is cancelled.
+ *
+ * For example, the following flow:
+ * ```
+ * flow {
+ *     emit("a")
+ *     delay(100)
+ *     emit("b")
+ * }.mapLatest { value ->
+ *     println("Started computing $value")
+ *     delay(200)
+ *     "Computed $value"
+ * }
+ * ```
+ *
+ * will print "Started computing a" and "Started computing b", but the resulting flow will contain
+ * only "Computed b" value.
+ *
+ * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
+ * [mapLatest], due to the latter's default configuration of using an internal buffer, negatively
+ * impacting system health.
+ *
+ * @see mapLatest
+ */
+fun <T, R> Flow<T>.mapLatestConflated(@BuilderInference transform: suspend (T) -> R): Flow<R> =
+    mapLatest(transform).conflate()
+
+/**
+ * Returns a flow that switches to a new flow produced by [transform] function every time the
+ * original flow emits a value. When the original flow emits a new value, the previous flow produced
+ * by `transform` block is cancelled.
+ *
+ * For example, the following flow:
+ * ```
+ * flow {
+ *     emit("a")
+ *     delay(100)
+ *     emit("b")
+ * }.flatMapLatest { value ->
+ *     flow {
+ *         emit(value)
+ *         delay(200)
+ *         emit(value + "_last")
+ *     }
+ * }
+ * ```
+ *
+ * produces `a b b_last`
+ *
+ * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
+ * [flatMapLatest], due to the latter's default configuration of using an internal buffer,
+ * negatively impacting system health.
+ *
+ * @see flatMapLatest
+ */
+fun <T, R> Flow<T>.flatMapLatestConflated(
+    @BuilderInference transform: suspend (T) -> Flow<R>,
+): Flow<R> = flatMapLatest(transform).conflate()
+
+/**
+ * Returns a flow that produces element by [transform] function every time the original flow emits a
+ * value. When the original flow emits a new value, the previous `transform` block is cancelled,
+ * thus the name `transformLatest`.
+ *
+ * For example, the following flow:
+ * ```
+ * flow {
+ *     emit("a")
+ *     delay(100)
+ *     emit("b")
+ * }.transformLatest { value ->
+ *     emit(value)
+ *     delay(200)
+ *     emit(value + "_last")
+ * }
+ * ```
+ *
+ * produces `a b b_last`.
+ *
+ * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
+ * [transformLatest], due to the latter's default configuration of using an internal buffer,
+ * negatively impacting system health.
+ *
+ * @see transformLatest
+ */
+fun <T, R> Flow<T>.transformLatestConflated(
+    @BuilderInference transform: suspend FlowCollector<R>.(T) -> Unit,
+): Flow<R> = transformLatest(transform).conflate()
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 23e269a..cbbce1a 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -19,6 +19,7 @@
 import static android.app.WallpaperManager.FLAG_LOCK;
 import static android.app.WallpaperManager.FLAG_SYSTEM;
 import static android.app.WallpaperManager.ORIENTATION_UNKNOWN;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
 
 import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_INELIGIBLE;
 import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_METADATA;
@@ -39,6 +40,7 @@
 import android.content.SharedPreferences;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
+import android.graphics.BitmapFactory;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
@@ -109,22 +111,16 @@
     static final String LOCK_WALLPAPER_STAGE = "wallpaper-lock-stage";
     @VisibleForTesting
     static final String WALLPAPER_INFO_STAGE = "wallpaper-info-stage";
-
     @VisibleForTesting
     static final String WALLPAPER_BACKUP_DEVICE_INFO_STAGE = "wallpaper-backup-device-info-stage";
-
     static final String EMPTY_SENTINEL = "empty";
     static final String QUOTA_SENTINEL = "quota";
-
     // Shared preferences constants.
     static final String PREFS_NAME = "wbprefs.xml";
     static final String SYSTEM_GENERATION = "system_gen";
     static final String LOCK_GENERATION = "lock_gen";
 
-    /**
-     * An approximate area threshold to compare device dimension similarity
-     */
-    static final int AREA_THRESHOLD = 50; // TODO (b/327637867): determine appropriate threshold
+    static final float DEFAULT_ACCEPTABLE_PARALLAX = 0.2f;
 
     // If this file exists, it means we exceeded our quota last time
     private File mQuotaFile;
@@ -336,7 +332,6 @@
         mEventLogger.onSystemImageWallpaperBackupFailed(error);
     }
 
-
     private void backupLockWallpaperFileIfItExists(SharedPreferences sharedPrefs,
             boolean lockChanged, int lockGeneration, FullBackupDataOutput data) throws IOException {
         final File lockImageStage = new File(getFilesDir(), LOCK_WALLPAPER_STAGE);
@@ -409,6 +404,16 @@
         }
     }
 
+    private static String readText(TypedXmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        String result = "";
+        if (parser.next() == XmlPullParser.TEXT) {
+            result = parser.getText();
+            parser.nextTag();
+        }
+        return result;
+    }
+
     @VisibleForTesting
     // fullBackupFile is final, so we intercept backups here in tests.
     protected void backupFile(File file, FullBackupDataOutput data) {
@@ -438,18 +443,10 @@
         boolean lockImageStageExists = lockImageStage.exists();
 
         try {
-            // Parse the device dimensions of the source device and compare with target to
-            // to identify whether we need to skip the remainder of the restore process
+            // Parse the device dimensions of the source device
             Pair<Point, Point> sourceDeviceDimensions = parseDeviceDimensions(
                     deviceDimensionsStage);
 
-            Point targetDeviceDimensions = getScreenDimensions();
-            if (sourceDeviceDimensions != null && targetDeviceDimensions != null
-                    && isSourceDeviceSignificantlySmallerThanTarget(sourceDeviceDimensions.first,
-                    targetDeviceDimensions)) {
-                Slog.d(TAG, "The source device is significantly smaller than target");
-            }
-
             // First parse the live component name so that we know for logging if we care about
             // logging errors with the image restore.
             ComponentName wpService = parseWallpaperComponent(infoStage, "wp");
@@ -466,9 +463,10 @@
             // to back up the original image on the source device, or there was no user-supplied
             // wallpaper image present.
             if (lockImageStageExists) {
-                restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK);
+                restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK,
+                        sourceDeviceDimensions);
             }
-            restoreFromStage(imageStage, infoStage, "wp", sysWhich);
+            restoreFromStage(imageStage, infoStage, "wp", sysWhich, sourceDeviceDimensions);
 
             // And reset to the wallpaper service we should be using
             if (mLockHasLiveComponent) {
@@ -543,16 +541,6 @@
         }
     }
 
-    private static String readText(TypedXmlPullParser parser)
-            throws IOException, XmlPullParserException {
-        String result = "";
-        if (parser.next() == XmlPullParser.TEXT) {
-            result = parser.getText();
-            parser.nextTag();
-        }
-        return result;
-    }
-
     @VisibleForTesting
     void updateWallpaperComponent(ComponentName wpService, int which)
             throws IOException {
@@ -578,10 +566,13 @@
         }
     }
 
-    private void restoreFromStage(File stage, File info, String hintTag, int which)
+    private void restoreFromStage(File stage, File info, String hintTag, int which,
+            Pair<Point, Point> sourceDeviceDimensions)
             throws IOException {
         if (stage.exists()) {
             if (multiCrop()) {
+                // TODO(b/332937943): implement offset adjustment by manually adjusting crop to
+                //  adhere to device aspect ratio
                 SparseArray<Rect> cropHints = parseCropHints(info, hintTag);
                 if (cropHints != null) {
                     Slog.i(TAG, "Got restored wallpaper; applying which=" + which
@@ -601,7 +592,6 @@
                 }
                 return;
             }
-
             // Parse the restored info file to find the crop hint.  Note that this currently
             // relies on a priori knowledge of the wallpaper info file schema.
             Rect cropHint = parseCropHint(info, hintTag);
@@ -609,8 +599,33 @@
                 Slog.i(TAG, "Got restored wallpaper; applying which=" + which
                         + "; cropHint = " + cropHint);
                 try (FileInputStream in = new FileInputStream(stage)) {
-                    mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint, true,
-                            which);
+
+                    if (sourceDeviceDimensions != null && sourceDeviceDimensions.first != null) {
+                        BitmapFactory.Options options = new BitmapFactory.Options();
+                        options.inJustDecodeBounds = true;
+                        ParcelFileDescriptor pdf = ParcelFileDescriptor.open(stage, MODE_READ_ONLY);
+                        BitmapFactory.decodeFileDescriptor(pdf.getFileDescriptor(),
+                                null, options);
+                        Point bitmapSize = new Point(options.outWidth, options.outHeight);
+                        Point sourceDeviceSize = new Point(sourceDeviceDimensions.first.x,
+                                sourceDeviceDimensions.first.y);
+                        Point targetDeviceDimensions = getScreenDimensions();
+
+                        // TODO: for now we handle only the case where the target device has smaller
+                        // aspect ratio than the source device i.e. the target device is more narrow
+                        // than the source device
+                        if (isTargetMoreNarrowThanSource(targetDeviceDimensions,
+                                sourceDeviceSize)) {
+                            Rect adjustedCrop = findNewCropfromOldCrop(cropHint,
+                                    sourceDeviceDimensions.first, true, targetDeviceDimensions,
+                                    bitmapSize, true);
+
+                            cropHint.set(adjustedCrop);
+                        }
+                    }
+
+                    mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint,
+                            true, which);
 
                     // And log the success
                     if ((which & FLAG_SYSTEM) > 0) {
@@ -629,6 +644,209 @@
         }
     }
 
+    /**
+     * This method computes the crop of the stored wallpaper to preserve its center point as the
+     * user had set it in the previous device.
+     *
+     * The algorithm involves first computing the original crop of the user (without parallax). Then
+     * manually adjusting the user's original crop to respect the current device's aspect ratio
+     * (thereby preserving the center point). Then finally, adding any leftover image real-estate
+     * (i.e. space left over on the horizontal axis) to add parallax effect. Parallax is only added
+     * if was present in the old device's settings.
+     *
+     */
+    private Rect findNewCropfromOldCrop(Rect oldCrop, Point oldDisplaySize, boolean oldRtl,
+            Point newDisplaySize, Point bitmapSize, boolean newRtl) {
+        Rect cropWithoutParallax = withoutParallax(oldCrop, oldDisplaySize, oldRtl, bitmapSize);
+        oldCrop = oldCrop.isEmpty() ? new Rect(0, 0, bitmapSize.x, bitmapSize.y) : oldCrop;
+        float oldParallaxAmount = ((float) oldCrop.width() / cropWithoutParallax.width()) - 1;
+
+        Rect newCropWithSameCenterWithoutParallax = sameCenter(newDisplaySize, bitmapSize,
+                cropWithoutParallax);
+
+        Rect newCrop = newCropWithSameCenterWithoutParallax;
+
+        // calculate the amount of left-over space there is in the image after adjusting the crop
+        // from the above operation i.e. in a rtl configuration, this is the remaining space in the
+        // image after subtracting the new crop's right edge coordinate from the image itself, and
+        // for ltr, its just the new crop's left edge coordinate (as it's the distance from the
+        // beginning of the image)
+        int widthAvailableForParallaxOnTheNewDevice =
+                (newRtl) ? newCrop.left : bitmapSize.x - newCrop.right;
+
+        // calculate relatively how much this available space is as a fraction of the total cropped
+        // image
+        float availableParallaxAmount =
+                (float) widthAvailableForParallaxOnTheNewDevice / newCrop.width();
+
+        float minAcceptableParallax = Math.min(DEFAULT_ACCEPTABLE_PARALLAX, oldParallaxAmount);
+
+        if (DEBUG) {
+            Slog.d(TAG, "- cropWithoutParallax: " + cropWithoutParallax);
+            Slog.d(TAG, "- oldParallaxAmount: " + oldParallaxAmount);
+            Slog.d(TAG, "- newCropWithSameCenterWithoutParallax: "
+                    + newCropWithSameCenterWithoutParallax);
+            Slog.d(TAG, "- widthAvailableForParallaxOnTheNewDevice: "
+                    + widthAvailableForParallaxOnTheNewDevice);
+            Slog.d(TAG, "- availableParallaxAmount: " + availableParallaxAmount);
+            Slog.d(TAG, "- minAcceptableParallax: " + minAcceptableParallax);
+            Slog.d(TAG, "- oldCrop: " + oldCrop);
+            Slog.d(TAG, "- oldDisplaySize: " + oldDisplaySize);
+            Slog.d(TAG, "- oldRtl: " + oldRtl);
+            Slog.d(TAG, "- newDisplaySize: " + newDisplaySize);
+            Slog.d(TAG, "- bitmapSize: " + bitmapSize);
+            Slog.d(TAG, "- newRtl: " + newRtl);
+        }
+        if (availableParallaxAmount >= minAcceptableParallax) {
+            // but in any case, don't put more parallax than the amount of the old device
+            float parallaxToAdd = Math.min(availableParallaxAmount, oldParallaxAmount);
+
+            int widthToAddForParallax = (int) (newCrop.width() * parallaxToAdd);
+            if (DEBUG) {
+                Slog.d(TAG, "- parallaxToAdd: " + parallaxToAdd);
+                Slog.d(TAG, "- widthToAddForParallax: " + widthToAddForParallax);
+            }
+            if (newRtl) {
+                newCrop.left -= widthToAddForParallax;
+            } else {
+                newCrop.right += widthToAddForParallax;
+            }
+        }
+        return newCrop;
+    }
+
+    /**
+     * This method computes the original crop of the user without parallax.
+     *
+     * NOTE: When the user sets the wallpaper with a specific crop, there may additional image added
+     * to the crop to support parallax. In order to determine the user's actual crop the parallax
+     * must be removed if it exists.
+     */
+    Rect withoutParallax(Rect crop, Point displaySize, boolean rtl, Point bitmapSize) {
+        // in the case an image's crop is not set, we assume the image itself is cropped
+        if (crop.isEmpty()) {
+            crop = new Rect(0, 0, bitmapSize.x, bitmapSize.y);
+        }
+
+        if (DEBUG) {
+            Slog.w(TAG, "- crop: " + crop);
+        }
+
+        Rect adjustedCrop = new Rect(crop);
+        float suggestedDisplayRatio = (float) displaySize.x / displaySize.y;
+
+        // here we calculate the width of the wallpaper image such that it has the same aspect ratio
+        // as the given display i.e. the width of the image on a single page of the device without
+        // parallax (i.e. displaySize will correspond to the display the crop was originally set on)
+        int wallpaperWidthWithoutParallax = (int) (0.5f + (float) displaySize.x * crop.height()
+                / displaySize.y);
+        // subtracting wallpaperWidthWithoutParallax from the wallpaper crop gives the amount of
+        // parallax added
+        int widthToRemove = Math.max(0, crop.width() - wallpaperWidthWithoutParallax);
+
+        if (DEBUG) {
+            Slog.d(TAG, "- adjustedCrop: " + adjustedCrop);
+            Slog.d(TAG, "- suggestedDisplayRatio: " + suggestedDisplayRatio);
+            Slog.d(TAG, "- wallpaperWidthWithoutParallax: " + wallpaperWidthWithoutParallax);
+            Slog.d(TAG, "- widthToRemove: " + widthToRemove);
+        }
+        if (rtl) {
+            adjustedCrop.left += widthToRemove;
+        } else {
+            adjustedCrop.right -= widthToRemove;
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG, "- adjustedCrop: " + crop);
+        }
+        return adjustedCrop;
+    }
+
+    /**
+     * This method computes a new crop based on the given crop in order to preserve the center point
+     * of the given crop on the provided displaySize. This is only for the case where the device
+     * displaySize has a smaller aspect ratio than the cropped image.
+     *
+     * NOTE: If the width to height ratio is less in the device display than cropped image
+     * this means the aspect ratios are off and there will be distortions in the image
+     * if the image is applied to the current display (i.e. the image will be skewed ->
+     * pixels in the image will not align correctly with the same pixels in the image that are
+     * above them)
+     */
+    Rect sameCenter(Point displaySize, Point bitmapSize, Rect crop) {
+
+        // in the case an image's crop is not set, we assume the image itself is cropped
+        if (crop.isEmpty()) {
+            crop = new Rect(0, 0, bitmapSize.x, bitmapSize.y);
+        }
+
+        float screenRatio = (float) displaySize.x / displaySize.y;
+        float cropRatio = (float) crop.width() / crop.height();
+
+        Rect adjustedCrop = new Rect(crop);
+
+        if (screenRatio < cropRatio) {
+            // the screen is more narrow than the image, and as such, the image will need to be
+            // zoomed in till it fits in the vertical axis. Due to this, we need to manually adjust
+            // the image's crop in order for it to fit into the screen without having the framework
+            // do it (since the framework left aligns the image after zooming)
+
+            // Calculate the height of the adjusted wallpaper crop so it respects the aspect ratio
+            // of the device. To calculate the height, we will use the width of the current crop.
+            // This is so we find the largest height possible which also respects the device aspect
+            // ratio.
+            int heightToAdd = (int) (0.5f + crop.width() / screenRatio - crop.height());
+
+            // Calculate how much extra image space available that can be used to adjust
+            // the crop. If this amount is less than heightToAdd, from above, then that means we
+            // can't use heightToAdd. Instead we will need to use the maximum possible height, which
+            // is the height of the original bitmap. NOTE: the bitmap height may be different than
+            // the crop.
+            // since there is no guarantee to have height available on both sides
+            // (e.g. the available height might be fully at the bottom), grab the minimum
+            int availableHeight = 2 * Math.min(crop.top, bitmapSize.y - crop.bottom);
+            int actualHeightToAdd = Math.min(heightToAdd, availableHeight);
+
+            // half of the additional height is added to the top and bottom of the crop
+            adjustedCrop.top -= actualHeightToAdd / 2 + actualHeightToAdd % 2;
+            adjustedCrop.bottom += actualHeightToAdd / 2;
+
+            // Calculate the width of the adjusted crop. Initially we used the fixed width of the
+            // crop to calculate the heightToAdd, but since this height may be invalid (based on
+            // the calculation above) we calculate the width again instead of using the fixed width,
+            // using the adjustedCrop's updated height.
+            int widthToRemove = (int) (0.5f + crop.width() - adjustedCrop.height() * screenRatio);
+
+            // half of the additional width is subtracted from the left and right side of the crop
+            int widthToRemoveLeft = widthToRemove / 2;
+            int widthToRemoveRight = widthToRemove / 2 + widthToRemove % 2;
+
+            adjustedCrop.left += widthToRemoveLeft;
+            adjustedCrop.right -= widthToRemoveRight;
+
+            if (DEBUG) {
+                Slog.d(TAG, "cropRatio: " + cropRatio);
+                Slog.d(TAG, "screenRatio: " + screenRatio);
+                Slog.d(TAG, "heightToAdd: " + heightToAdd);
+                Slog.d(TAG, "actualHeightToAdd: " + actualHeightToAdd);
+                Slog.d(TAG, "availableHeight: " + availableHeight);
+                Slog.d(TAG, "widthToRemove: " + widthToRemove);
+                Slog.d(TAG, "adjustedCrop: " + adjustedCrop);
+            }
+
+            return adjustedCrop;
+        }
+
+        return adjustedCrop;
+    }
+
+    private boolean isTargetMoreNarrowThanSource(Point targetDisplaySize, Point srcDisplaySize) {
+        float targetScreenRatio = (float) targetDisplaySize.x / targetDisplaySize.y;
+        float srcScreenRatio = (float) srcDisplaySize.x / srcDisplaySize.y;
+
+        return (targetScreenRatio < srcScreenRatio);
+    }
+
     private void logRestoreErrorIfNoLiveComponent(int which, String error) {
         if (mSystemHasLiveComponent) {
             return;
@@ -644,6 +862,7 @@
             mEventLogger.onLockImageWallpaperRestoreFailed(error);
         }
     }
+
     private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
         Rect cropHint = new Rect();
         try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
@@ -681,7 +900,7 @@
                 if (type != XmlPullParser.START_TAG) continue;
                 String tag = parser.getName();
                 if (!sectionTag.equals(tag)) continue;
-                for (Pair<Integer, String> pair: List.of(
+                for (Pair<Integer, String> pair : List.of(
                         new Pair<>(WallpaperManager.PORTRAIT, "Portrait"),
                         new Pair<>(WallpaperManager.LANDSCAPE, "Landscape"),
                         new Pair<>(WallpaperManager.SQUARE_PORTRAIT, "SquarePortrait"),
@@ -907,22 +1126,6 @@
         return internalDisplays;
     }
 
-    /**
-     * This method compares the source and target dimensions, and returns true if there is a
-     * significant difference in area between them and the source dimensions are smaller than the
-     * target dimensions.
-     *
-     * @param sourceDimensions is the dimensions of the source device
-     * @param targetDimensions is the dimensions of the target device
-     */
-    @VisibleForTesting
-    boolean isSourceDeviceSignificantlySmallerThanTarget(Point sourceDimensions,
-            Point targetDimensions) {
-        int rawAreaDelta = (targetDimensions.x * targetDimensions.y)
-                - (sourceDimensions.x * sourceDimensions.y);
-        return rawAreaDelta > AREA_THRESHOLD;
-    }
-
     @VisibleForTesting
     boolean isDeviceInRestore() {
         try {
diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
index ec9223c..3ecdf3f 100644
--- a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
+++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
@@ -59,7 +59,6 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
@@ -841,26 +840,6 @@
         testParseCropHints(testMap);
     }
 
-    @Test
-    public void test_sourceDimensionsAreLargerThanTarget() {
-        // source device is larger than target, expecting to get false
-        Point sourceDimensions = new Point(2208, 1840);
-        Point targetDimensions = new Point(1080, 2092);
-        boolean isSourceSmaller = mWallpaperBackupAgent
-                .isSourceDeviceSignificantlySmallerThanTarget(sourceDimensions, targetDimensions);
-        assertThat(isSourceSmaller).isEqualTo(false);
-    }
-
-    @Test
-    public void test_sourceDimensionsMuchSmallerThanTarget() {
-        // source device is smaller than target, expecting to get true
-        Point sourceDimensions = new Point(1080, 2092);
-        Point targetDimensions = new Point(2208, 1840);
-        boolean isSourceSmaller = mWallpaperBackupAgent
-                .isSourceDeviceSignificantlySmallerThanTarget(sourceDimensions, targetDimensions);
-        assertThat(isSourceSmaller).isEqualTo(true);
-    }
-
     private void testParseCropHints(Map<Integer, Rect> testMap) throws Exception {
         assumeTrue(multiCrop());
         mockRestoredStaticWallpaperFile(testMap);
diff --git a/packages/overlays/Android.bp b/packages/overlays/Android.bp
index 5e001fb..5075f63 100644
--- a/packages/overlays/Android.bp
+++ b/packages/overlays/Android.bp
@@ -30,9 +30,6 @@
         "FontNotoSerifSourceOverlay",
         "NavigationBarMode3ButtonOverlay",
         "NavigationBarModeGesturalOverlay",
-        "NavigationBarModeGesturalOverlayNarrowBack",
-        "NavigationBarModeGesturalOverlayWideBack",
-        "NavigationBarModeGesturalOverlayExtraWideBack",
         "TransparentNavigationBarOverlay",
         "NotesRoleEnabledOverlay",
         "preinstalled-packages-platform-overlays.xml",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
deleted file mode 100644
index 28f9f33..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-//  Copyright 2019, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // 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: "NavigationBarModeGesturalOverlayExtraWideBack",
-    theme: "NavigationBarModeGesturalExtraWideBack",
-    product_specific: true,
-}
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml
deleted file mode 100644
index ba7beba..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.internal.systemui.navbar.gestural_extra_wide_back"
-        android:versionCode="1"
-        android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="com.android.internal.navigation_bar_mode"
-        android:priority="1"/>
-
-    <application android:label="@string/navigation_bar_mode_title" android:hasCode="false"/>
-</manifest>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml
deleted file mode 100644
index be1f081..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
deleted file mode 100644
index 120a489..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- Controls the navigation bar interaction mode:
-         0: 3 button mode (back, home, overview buttons)
-         1: 2 button mode (back, home buttons + swipe up for overview)
-         2: gestures only for back, home and overview -->
-    <integer name="config_navBarInteractionMode">2</integer>
-
-    <!-- Controls whether the nav bar can move from the bottom to the side in landscape.
-         Only applies if the device display is not square. -->
-    <bool name="config_navBarCanMove">false</bool>
-
-    <!-- Controls whether the navigation bar lets through taps. -->
-    <bool name="config_navBarTapThrough">true</bool>
-
-    <!-- Controls whether the IME renders the back and IME switcher buttons or not. -->
-    <bool name="config_imeDrawsImeNavBar">true</bool>
-
-    <!-- Controls the size of the back gesture inset. -->
-    <dimen name="config_backGestureInset">40dp</dimen>
-
-    <!-- Controls whether the navbar needs a scrim with
-     {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
-    <bool name="config_navBarNeedsScrim">false</bool>
-
-    <!-- Controls the opacity of the navigation bar depending on the visibility of the
-     various workspace stacks.
-     0 - Nav bar is always opaque when either the freeform stack or docked stack is visible.
-     1 - Nav bar is always translucent when the freeform stack is visible, otherwise always
-         opaque.
-     2 - Nav bar is never forced opaque.
-     -->
-    <integer name="config_navBarOpacityMode">2</integer>
-
-    <!-- Controls whether seamless rotation should be allowed even though the navbar can move
-         (which normally prevents seamless rotation). -->
-    <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
-
-    <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
-         show. -->
-    <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
-
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
deleted file mode 100644
index 674bc74..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- Height of the bottom navigation / system bar. -->
-    <dimen name="navigation_bar_height">24dp</dimen>
-    <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
-    <dimen name="navigation_bar_height_landscape">24dp</dimen>
-    <!-- Width of the navigation bar when it is placed vertically on the screen -->
-    <dimen name="navigation_bar_width">24dp</dimen>
-    <!-- Height of the bottom navigation / system bar. -->
-    <dimen name="navigation_bar_frame_height">48dp</dimen>
-    <!-- The height of the bottom navigation gesture area. -->
-    <dimen name="navigation_bar_gesture_height">32dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml
deleted file mode 100644
index bbab5e047..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Name of overlay [CHAR LIMIT=64] -->
-    <string name="navigation_bar_mode_title" translatable="false">Gestural Navigation Bar</string>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
deleted file mode 100644
index f8a5603..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-//  Copyright 2019, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // 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: "NavigationBarModeGesturalOverlayNarrowBack",
-    theme: "NavigationBarModeGesturalNarrowBack",
-    product_specific: true,
-}
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml
deleted file mode 100644
index 8de91c0..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.internal.systemui.navbar.gestural_narrow_back"
-        android:versionCode="1"
-        android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="com.android.internal.navigation_bar_mode"
-        android:priority="1"/>
-
-    <application android:label="@string/navigation_bar_mode_title" android:hasCode="false"/>
-</manifest>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml
deleted file mode 100644
index be1f081..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
deleted file mode 100644
index c18d892..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- Controls the navigation bar interaction mode:
-         0: 3 button mode (back, home, overview buttons)
-         1: 2 button mode (back, home buttons + swipe up for overview)
-         2: gestures only for back, home and overview -->
-    <integer name="config_navBarInteractionMode">2</integer>
-
-    <!-- Controls whether the nav bar can move from the bottom to the side in landscape.
-         Only applies if the device display is not square. -->
-    <bool name="config_navBarCanMove">false</bool>
-
-    <!-- Controls whether the navigation bar lets through taps. -->
-    <bool name="config_navBarTapThrough">true</bool>
-
-    <!-- Controls whether the IME renders the back and IME switcher buttons or not. -->
-    <bool name="config_imeDrawsImeNavBar">true</bool>
-
-    <!-- Controls the size of the back gesture inset. -->
-    <dimen name="config_backGestureInset">18dp</dimen>
-
-    <!-- Controls whether the navbar needs a scrim with
-     {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
-    <bool name="config_navBarNeedsScrim">false</bool>
-
-    <!-- Controls the opacity of the navigation bar depending on the visibility of the
-     various workspace stacks.
-     0 - Nav bar is always opaque when either the freeform stack or docked stack is visible.
-     1 - Nav bar is always translucent when the freeform stack is visible, otherwise always
-         opaque.
-     2 - Nav bar is never forced opaque.
-     -->
-    <integer name="config_navBarOpacityMode">2</integer>
-
-    <!-- Controls whether seamless rotation should be allowed even though the navbar can move
-         (which normally prevents seamless rotation). -->
-    <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
-
-    <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
-         show. -->
-    <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
-
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
deleted file mode 100644
index 674bc74..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- Height of the bottom navigation / system bar. -->
-    <dimen name="navigation_bar_height">24dp</dimen>
-    <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
-    <dimen name="navigation_bar_height_landscape">24dp</dimen>
-    <!-- Width of the navigation bar when it is placed vertically on the screen -->
-    <dimen name="navigation_bar_width">24dp</dimen>
-    <!-- Height of the bottom navigation / system bar. -->
-    <dimen name="navigation_bar_frame_height">48dp</dimen>
-    <!-- The height of the bottom navigation gesture area. -->
-    <dimen name="navigation_bar_gesture_height">32dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml
deleted file mode 100644
index bbab5e047..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Name of overlay [CHAR LIMIT=64] -->
-    <string name="navigation_bar_mode_title" translatable="false">Gestural Navigation Bar</string>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
deleted file mode 100644
index 60ee6d5..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-//  Copyright 2019, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // 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: "NavigationBarModeGesturalOverlayWideBack",
-    theme: "NavigationBarModeGesturalWideBack",
-    product_specific: true,
-}
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml
deleted file mode 100644
index daf4613..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.internal.systemui.navbar.gestural_wide_back"
-        android:versionCode="1"
-        android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="com.android.internal.navigation_bar_mode"
-        android:priority="1"/>
-
-    <application android:label="@string/navigation_bar_mode_title" android:hasCode="false"/>
-</manifest>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml
deleted file mode 100644
index be1f081..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
deleted file mode 100644
index 877b5f8..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- Controls the navigation bar interaction mode:
-         0: 3 button mode (back, home, overview buttons)
-         1: 2 button mode (back, home buttons + swipe up for overview)
-         2: gestures only for back, home and overview -->
-    <integer name="config_navBarInteractionMode">2</integer>
-
-    <!-- Controls whether the nav bar can move from the bottom to the side in landscape.
-         Only applies if the device display is not square. -->
-    <bool name="config_navBarCanMove">false</bool>
-
-    <!-- Controls whether the navigation bar lets through taps. -->
-    <bool name="config_navBarTapThrough">true</bool>
-
-    <!-- Controls whether the IME renders the back and IME switcher buttons or not. -->
-    <bool name="config_imeDrawsImeNavBar">true</bool>
-
-    <!-- Controls the size of the back gesture inset. -->
-    <dimen name="config_backGestureInset">32dp</dimen>
-
-    <!-- Controls whether the navbar needs a scrim with
-     {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
-    <bool name="config_navBarNeedsScrim">false</bool>
-
-    <!-- Controls the opacity of the navigation bar depending on the visibility of the
-     various workspace stacks.
-     0 - Nav bar is always opaque when either the freeform stack or docked stack is visible.
-     1 - Nav bar is always translucent when the freeform stack is visible, otherwise always
-         opaque.
-     2 - Nav bar is never forced opaque.
-     -->
-    <integer name="config_navBarOpacityMode">2</integer>
-
-    <!-- Controls whether seamless rotation should be allowed even though the navbar can move
-         (which normally prevents seamless rotation). -->
-    <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
-
-    <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
-         show. -->
-    <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
-
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
deleted file mode 100644
index 674bc74..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- Height of the bottom navigation / system bar. -->
-    <dimen name="navigation_bar_height">24dp</dimen>
-    <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
-    <dimen name="navigation_bar_height_landscape">24dp</dimen>
-    <!-- Width of the navigation bar when it is placed vertically on the screen -->
-    <dimen name="navigation_bar_width">24dp</dimen>
-    <!-- Height of the bottom navigation / system bar. -->
-    <dimen name="navigation_bar_frame_height">48dp</dimen>
-    <!-- The height of the bottom navigation gesture area. -->
-    <dimen name="navigation_bar_gesture_height">32dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml
deleted file mode 100644
index bbab5e047..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Name of overlay [CHAR LIMIT=64] -->
-    <string name="navigation_bar_mode_title" translatable="false">Gestural Navigation Bar</string>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml
index ff920b2..97559b4 100644
--- a/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"लुकाइयोस्"</string>
+    <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"लुकाउनुहोस्"</string>
 </resources>
diff --git a/proto/src/am_capabilities.proto b/proto/src/am_capabilities.proto
index d97bf81..fc9f7a45 100644
--- a/proto/src/am_capabilities.proto
+++ b/proto/src/am_capabilities.proto
@@ -7,6 +7,16 @@
   string name = 1;
 }
 
+message VMCapability {
+  string name  = 1;
+}
+
+message FrameworkCapability {
+  string name  = 1;
+}
+
 message Capabilities {
   repeated Capability values = 1;
+  repeated VMCapability vm_capabilities = 2;
+  repeated FrameworkCapability framework_capabilities = 3;
 }
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index a5b28ad..e77f846f 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -5,6 +5,17 @@
     },
     {
       "name": "RavenwoodBivalentTest_device"
+    },
+    {
+      "name": "SystemUIGoogleTests",
+      "options": [
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
     }
   ],
   "ravenwood-presubmit": [
diff --git a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp b/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
index 5e66b29..83f756e 100644
--- a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
+++ b/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp
@@ -42,7 +42,7 @@
     ALOGI("%s: JNI_OnLoad", __FILE__);
 
     int res = jniRegisterNativeMethods(env,
-            "com/android/platform/test/ravenwood/bivalenttest/RavenwoodJniTest",
+            "com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest",
             sMethods, NELEM(sMethods));
     if (res < 0) {
         return res;
diff --git a/ravenwood/bivalenttest/test/com/android/platform/test/ravenwood/bivalenttest/RavenwoodJniTest.java b/ravenwood/bivalenttest/test/com/android/platform/test/ravenwood/bivalenttest/RavenwoodJniTest.java
deleted file mode 100644
index 3b106da..0000000
--- a/ravenwood/bivalenttest/test/com/android/platform/test/ravenwood/bivalenttest/RavenwoodJniTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.platform.test.ravenwood.bivalenttest;
-
-import static junit.framework.Assert.assertEquals;
-
-import android.platform.test.ravenwood.RavenwoodRule;
-import android.platform.test.ravenwood.RavenwoodUtils;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public final class RavenwoodJniTest {
-    static {
-        RavenwoodUtils.loadJniLibrary("ravenwoodbivalenttest_jni");
-    }
-
-    @Rule
-    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder().build();
-
-    private static native int add(int a, int b);
-
-    @Test
-    public void testNativeMethod() {
-        assertEquals(5, add(2, 3));
-    }
-}
diff --git a/ravenwood/bivalenttest/test/com/android/platform/test/ravenwood/bivalenttest/RavenwoodRuleTest.java b/ravenwood/bivalenttest/test/com/android/platform/test/ravenwood/bivalenttest/RavenwoodRuleTest.java
deleted file mode 100644
index 4b650b4..0000000
--- a/ravenwood/bivalenttest/test/com/android/platform/test/ravenwood/bivalenttest/RavenwoodRuleTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.platform.test.ravenwood.bivalenttest;
-
-import android.platform.test.annotations.DisabledOnNonRavenwood;
-import android.platform.test.annotations.DisabledOnRavenwood;
-import android.platform.test.ravenwood.RavenwoodRule;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RavenwoodRuleTest {
-    @Rule
-    public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Test
-    @DisabledOnRavenwood
-    public void testDeviceOnly() {
-        Assert.assertFalse(RavenwoodRule.isOnRavenwood());
-    }
-
-    @Test
-    @DisabledOnNonRavenwood
-    public void testRavenwoodOnly() {
-        Assert.assertTrue(RavenwoodRule.isOnRavenwood());
-    }
-
-    // TODO: Add more tests
-}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java
new file mode 100644
index 0000000..d91e734
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import static org.junit.Assert.assertEquals;
+
+import android.util.ArrayMap;
+import android.util.Size;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+// Tests for calling simple Android APIs.
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodAndroidApiTest {
+    @Test
+    public void testArrayMapSimple() {
+        final Map<String, String> map = new ArrayMap<>();
+
+        map.put("key1", "value1");
+        assertEquals("value1", map.get("key1"));
+    }
+
+    @Test
+    public void testSizeSimple() {
+        final var size = new Size(1, 2);
+
+        assertEquals(2, size.getHeight());
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java
new file mode 100644
index 0000000..3a24c0e
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import android.platform.test.annotations.DisabledOnRavenwood;
+import android.platform.test.ravenwood.RavenwoodClassRule;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@DisabledOnRavenwood
+public class RavenwoodClassRuleDeviceOnlyTest {
+    @ClassRule
+    public static final RavenwoodClassRule sRavenwood = new RavenwoodClassRule();
+
+    @Test
+    public void testDeviceOnly() {
+        Assert.assertFalse(RavenwoodRule.isOnRavenwood());
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleRavenwoodOnlyTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleRavenwoodOnlyTest.java
new file mode 100644
index 0000000..aa33dc3
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleRavenwoodOnlyTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import android.platform.test.ravenwood.RavenwoodClassRule;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+// TODO: atest RavenwoodBivalentTest_device fails with the following message.
+// `RUNNER ERROR: Instrumentation reported numtests=7 but only ran 6`
+// @android.platform.test.annotations.DisabledOnNonRavenwood
+// Figure it out and then make DisabledOnNonRavenwood support TYPEs as well.
+@Ignore
+public class RavenwoodClassRuleRavenwoodOnlyTest {
+    @ClassRule
+    public static final RavenwoodClassRule sRavenwood = new RavenwoodClassRule();
+
+    @Test
+    public void testRavenwoodOnly() {
+        Assert.assertTrue(RavenwoodRule.isOnRavenwood());
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
new file mode 100644
index 0000000..59467e9
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.platform.test.ravenwood.RavenwoodUtils;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public final class RavenwoodJniTest {
+    static {
+        RavenwoodUtils.loadJniLibrary("ravenwoodbivalenttest_jni");
+    }
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder().build();
+
+    private static native int add(int a, int b);
+
+    @Test
+    public void testNativeMethod() {
+        assertEquals(5, add(2, 3));
+    }
+}
diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java
new file mode 100644
index 0000000..3edca7e
--- /dev/null
+++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.bivalenttest;
+
+import android.platform.test.annotations.DisabledOnNonRavenwood;
+import android.platform.test.annotations.DisabledOnRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodRuleTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
+    @DisabledOnRavenwood
+    public void testDeviceOnly() {
+        Assert.assertFalse(RavenwoodRule.isOnRavenwood());
+    }
+
+    @Test
+    @DisabledOnNonRavenwood
+    public void testRavenwoodOnly() {
+        Assert.assertTrue(RavenwoodRule.isOnRavenwood());
+    }
+
+    // TODO: Add more tests
+}
diff --git a/ravenwood/coretest/test/com/android/platform/test/ravenwood/coretest/RavenwoodTestRunnerValidationTest.java b/ravenwood/coretest/test/com/android/platform/test/ravenwood/coretest/RavenwoodTestRunnerValidationTest.java
deleted file mode 100644
index 2cd585f..0000000
--- a/ravenwood/coretest/test/com/android/platform/test/ravenwood/coretest/RavenwoodTestRunnerValidationTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.platform.test.ravenwood.coretest;
-
-import android.platform.test.ravenwood.RavenwoodRule;
-
-import androidx.test.runner.AndroidJUnit4; // Intentionally use the deprecated one.
-
-import org.junit.Assume;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.RuleChain;
-import org.junit.runner.RunWith;
-
-/**
- * Test for the test runner validator in RavenwoodRule.
- */
-@RunWith(AndroidJUnit4.class)
-public class RavenwoodTestRunnerValidationTest {
-    // Note the following rules don't have a @Rule, because they need to be applied in a specific
-    // order. So we use a RuleChain instead.
-    private ExpectedException mThrown = ExpectedException.none();
-    private final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Rule
-    public final RuleChain chain = RuleChain.outerRule(mThrown).around(mRavenwood);
-
-    public RavenwoodTestRunnerValidationTest() {
-        Assume.assumeTrue(mRavenwood._ravenwood_private$isOptionalValidationEnabled());
-        // Because RavenwoodRule will throw this error before executing the test method,
-        // we can't do it in the test method itself.
-        // So instead, we initialize it here.
-        mThrown.expectMessage("Switch to androidx.test.ext.junit.runners.AndroidJUnit4");
-    }
-
-    @Test
-    public void testValidateTestRunner() {
-    }
-}
diff --git a/ravenwood/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodTestRunnerValidationTest.java b/ravenwood/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodTestRunnerValidationTest.java
new file mode 100644
index 0000000..f1e33cb
--- /dev/null
+++ b/ravenwood/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodTestRunnerValidationTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.coretest;
+
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4; // Intentionally use the deprecated one.
+
+import org.junit.Assume;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+/**
+ * Test for the test runner validator in RavenwoodRule.
+ */
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodTestRunnerValidationTest {
+    // Note the following rules don't have a @Rule, because they need to be applied in a specific
+    // order. So we use a RuleChain instead.
+    private ExpectedException mThrown = ExpectedException.none();
+    private final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Rule
+    public final RuleChain chain = RuleChain.outerRule(mThrown).around(mRavenwood);
+
+    public RavenwoodTestRunnerValidationTest() {
+        Assume.assumeTrue(RavenwoodRule._$RavenwoodPrivate.isOptionalValidationEnabled());
+        // Because RavenwoodRule will throw this error before executing the test method,
+        // we can't do it in the test method itself.
+        // So instead, we initialize it here.
+        mThrown.expectMessage("Switch to androidx.test.ext.junit.runners.AndroidJUnit4");
+    }
+
+    @Test
+    public void testValidateTestRunner() {
+    }
+}
diff --git a/ravenwood/junit-src/android/platform/test/annotations/DisabledOnNonRavenwood.java b/ravenwood/junit-src/android/platform/test/annotations/DisabledOnNonRavenwood.java
index 8ca34ba..2fb8074 100644
--- a/ravenwood/junit-src/android/platform/test/annotations/DisabledOnNonRavenwood.java
+++ b/ravenwood/junit-src/android/platform/test/annotations/DisabledOnNonRavenwood.java
@@ -31,13 +31,17 @@
  * which means if a test class has this annotation, you can't negate it in subclasses or
  * on a per-method basis.
  *
+ * THIS ANNOTATION CANNOT BE ADDED TO CLASSES AT THIS PONINT.
+ * See {@link com.android.ravenwoodtest.bivalenttest.RavenwoodClassRuleRavenwoodOnlyTest}
+ * for the reason.
+ *
  * The {@code RAVENWOOD_RUN_DISABLED_TESTS} environmental variable won't work because it won't be
  * propagated to the device. (We may support it in the future, possibly using a debug. sysprop.)
  *
  * @hide
  */
 @Inherited
-@Target({ElementType.METHOD, ElementType.TYPE})
+@Target({ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface DisabledOnNonRavenwood {
     /**
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java
index 9a4d488..f4b7ec36 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodClassRule.java
@@ -25,6 +25,7 @@
 import android.platform.test.annotations.DisabledOnRavenwood;
 import android.platform.test.annotations.EnabledOnRavenwood;
 
+import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
@@ -41,27 +42,16 @@
 public class RavenwoodClassRule implements TestRule {
     @Override
     public Statement apply(Statement base, Description description) {
-        // No special treatment when running outside Ravenwood; run tests as-is
         if (!IS_ON_RAVENWOOD) {
-            Assume.assumeTrue(shouldEnableOnDevice(description));
-            return base;
-        }
-
-        if (ENABLE_PROBE_IGNORED) {
+            // This should be "Assume", not Assert, but if we use assume here, the device side
+            // test runner would complain.
+            // See the TODO comment in RavenwoodClassRuleRavenwoodOnlyTest.
+            Assert.assertTrue(shouldEnableOnDevice(description));
+        } else if (ENABLE_PROBE_IGNORED) {
             Assume.assumeFalse(shouldStillIgnoreInProbeIgnoreMode(description));
-            // Pass through to possible underlying RavenwoodRule for both environment
-            // configuration and handling method-level annotations
-            return base;
         } else {
-            return new Statement() {
-                @Override
-                public void evaluate() throws Throwable {
-                    Assume.assumeTrue(shouldEnableOnRavenwood(description));
-                    // Pass through to possible underlying RavenwoodRule for both environment
-                    // configuration and handling method-level annotations
-                    base.evaluate();
-                }
-            };
+            Assume.assumeTrue(shouldEnableOnRavenwood(description));
         }
+        return base;
     }
 }
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index 52ea340..21d8019 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -28,7 +28,6 @@
 import android.platform.test.annotations.DisabledOnRavenwood;
 import android.platform.test.annotations.EnabledOnRavenwood;
 import android.platform.test.annotations.IgnoreUnderRavenwood;
-import android.util.ArraySet;
 
 import org.junit.Assume;
 import org.junit.rules.TestRule;
@@ -278,6 +277,12 @@
                 return false;
             }
         }
+        final var clazz = description.getTestClass();
+        if (clazz != null) {
+            if (clazz.getAnnotation(DisabledOnNonRavenwood.class) != null) {
+                return false;
+            }
+        }
         return true;
     }
 
@@ -308,14 +313,17 @@
         }
 
         // Otherwise, consult any class-level annotations
-        if (description.getTestClass().getAnnotation(EnabledOnRavenwood.class) != null) {
-            return true;
-        }
-        if (description.getTestClass().getAnnotation(DisabledOnRavenwood.class) != null) {
-            return false;
-        }
-        if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) {
-            return false;
+        final var clazz = description.getTestClass();
+        if (clazz != null) {
+            if (description.getTestClass().getAnnotation(EnabledOnRavenwood.class) != null) {
+                return true;
+            }
+            if (description.getTestClass().getAnnotation(DisabledOnRavenwood.class) != null) {
+                return false;
+            }
+            if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) {
+                return false;
+            }
         }
 
         // When no annotations have been requested, assume test should be included
@@ -413,10 +421,9 @@
         };
     }
 
-    /**
-     * Do not use it outside ravenwood core classes.
-     */
-    public boolean _ravenwood_private$isOptionalValidationEnabled() {
-        return ENABLE_OPTIONAL_VALIDATION;
+    public static class _$RavenwoodPrivate {
+        public static boolean isOptionalValidationEnabled() {
+            return ENABLE_OPTIONAL_VALIDATION;
+        }
     }
 }
diff --git a/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoDeviceOnlyTest.java b/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoDeviceOnlyTest.java
deleted file mode 100644
index d02fe69..0000000
--- a/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoDeviceOnlyTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.ravenwood.mockito;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.ActivityManager;
-import android.platform.test.ravenwood.RavenwoodRule;
-
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.quality.Strictness;
-
-public class RavenwoodMockitoDeviceOnlyTest {
-    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Test
-    public void testStaticMockOnDevice() {
-        var mockingSession = ExtendedMockito.mockitoSession()
-                .strictness(Strictness.LENIENT)
-                .mockStatic(ActivityManager.class)
-                .startMocking();
-        try {
-            ExtendedMockito.doReturn(true).when(ActivityManager::isUserAMonkey);
-
-            assertThat(ActivityManager.isUserAMonkey()).isEqualTo(true);
-        } finally {
-            mockingSession.finishMocking();
-        }
-    }
-}
diff --git a/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoRavenwoodOnlyTest.java b/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoRavenwoodOnlyTest.java
deleted file mode 100644
index 0c137d5..0000000
--- a/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoRavenwoodOnlyTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.ravenwood.mockito;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.ActivityManager;
-import android.platform.test.ravenwood.RavenwoodRule;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
-
-public class RavenwoodMockitoRavenwoodOnlyTest {
-    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Test
-    public void testStaticMockOnRavenwood() {
-        try (MockedStatic<ActivityManager> am = Mockito.mockStatic(ActivityManager.class)) {
-            am.when(ActivityManager::isUserAMonkey).thenReturn(true);
-            assertThat(ActivityManager.isUserAMonkey()).isEqualTo(true);
-        }
-    }
-}
diff --git a/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoTest.java b/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoTest.java
deleted file mode 100644
index 9566710..0000000
--- a/ravenwood/mockito/test/com/android/ravenwood/mockito/RavenwoodMockitoTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.ravenwood.mockito;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Parcel;
-import android.platform.test.ravenwood.RavenwoodRule;
-
-import org.junit.Rule;
-import org.junit.Test;
-
-public class RavenwoodMockitoTest {
-    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule();
-
-    @Test
-    public void testMockJdkClass() {
-        Process object = mock(Process.class);
-
-        when(object.exitValue()).thenReturn(42);
-
-        assertThat(object.exitValue()).isEqualTo(42);
-    }
-
-    @Test
-    public void testMockAndroidClass1() {
-        Intent object = mock(Intent.class);
-
-        when(object.getAction()).thenReturn("ACTION_RAVENWOOD");
-
-        assertThat(object.getAction()).isEqualTo("ACTION_RAVENWOOD");
-    }
-
-    @Test
-    public void testMockAndroidClass2() {
-        Context object = mock(Context.class);
-
-        when(object.getPackageName()).thenReturn("android");
-
-        assertThat(object.getPackageName()).isEqualTo("android");
-    }
-
-    @Test
-    public void testMockFinalClass() {
-        var object = mock(Parcel.class);
-
-        when(object.readInt()).thenReturn(123);
-
-        assertThat(object.readInt()).isEqualTo(123);
-    }
-}
diff --git a/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoDeviceOnlyTest.java b/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoDeviceOnlyTest.java
new file mode 100644
index 0000000..d566977
--- /dev/null
+++ b/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoDeviceOnlyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.mockito;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityManager;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.quality.Strictness;
+
+public class RavenwoodMockitoDeviceOnlyTest {
+    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
+    public void testStaticMockOnDevice() {
+        var mockingSession = ExtendedMockito.mockitoSession()
+                .strictness(Strictness.LENIENT)
+                .mockStatic(ActivityManager.class)
+                .startMocking();
+        try {
+            ExtendedMockito.doReturn(true).when(ActivityManager::isUserAMonkey);
+
+            assertThat(ActivityManager.isUserAMonkey()).isEqualTo(true);
+        } finally {
+            mockingSession.finishMocking();
+        }
+    }
+}
diff --git a/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoRavenwoodOnlyTest.java b/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoRavenwoodOnlyTest.java
new file mode 100644
index 0000000..aa2b7611
--- /dev/null
+++ b/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoRavenwoodOnlyTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.mockito;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityManager;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+public class RavenwoodMockitoRavenwoodOnlyTest {
+    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
+    public void testStaticMockOnRavenwood() {
+        try (MockedStatic<ActivityManager> am = Mockito.mockStatic(ActivityManager.class)) {
+            am.when(ActivityManager::isUserAMonkey).thenReturn(true);
+            assertThat(ActivityManager.isUserAMonkey()).isEqualTo(true);
+        }
+    }
+}
diff --git a/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoTest.java b/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoTest.java
new file mode 100644
index 0000000..fcc6c9c
--- /dev/null
+++ b/ravenwood/mockito/test/com/android/ravenwoodtest/mockito/RavenwoodMockitoTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.mockito;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Parcel;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+public class RavenwoodMockitoTest {
+    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
+    public void testMockJdkClass() {
+        Process object = mock(Process.class);
+
+        when(object.exitValue()).thenReturn(42);
+
+        assertThat(object.exitValue()).isEqualTo(42);
+    }
+
+    @Test
+    public void testMockAndroidClass1() {
+        Intent object = mock(Intent.class);
+
+        when(object.getAction()).thenReturn("ACTION_RAVENWOOD");
+
+        assertThat(object.getAction()).isEqualTo("ACTION_RAVENWOOD");
+    }
+
+    @Test
+    public void testMockAndroidClass2() {
+        Context object = mock(Context.class);
+
+        when(object.getPackageName()).thenReturn("android");
+
+        assertThat(object.getPackageName()).isEqualTo("android");
+    }
+
+    @Test
+    public void testMockFinalClass() {
+        var object = mock(Parcel.class);
+
+        when(object.readInt()).thenReturn(123);
+
+        assertThat(object.readInt()).isEqualTo(123);
+    }
+}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
index 7414110..0f65544 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
@@ -100,6 +100,16 @@
             mLastStateChangeTimestampMs = timestampMs;
         }
 
+        public void copyStatesFrom(LongArrayMultiStateCounterRavenwood source) {
+            for (int i = 0; i < mStateCount; i++) {
+                mStates[i].mTimeInStateSinceUpdate = source.mStates[i].mTimeInStateSinceUpdate;
+                Arrays.fill(mStates[i].mCounter, 0);
+            }
+            mCurrentState = source.mCurrentState;
+            mLastStateChangeTimestampMs = source.mLastStateChangeTimestampMs;
+            mLastUpdateTimestampMs = source.mLastUpdateTimestampMs;
+        }
+
         public void setValue(int state, long[] values) {
             System.arraycopy(values, 0, mStates[state].mCounter, 0, mArrayLength);
         }
@@ -335,6 +345,10 @@
         getInstance(instanceId).setState(state, timestampMs);
     }
 
+    public static void native_copyStatesFrom(long targetInstanceId, long sourceInstanceId) {
+        getInstance(targetInstanceId).copyStatesFrom(getInstance(sourceInstanceId));
+    }
+
     public static void native_incrementValues(long instanceId, long containerInstanceId,
             long timestampMs) {
         getInstance(instanceId).incrementValues(
diff --git a/ravenwood/services-test/test/com/android/ravenwood/RavenwoodServicesDependenciesTest.java b/ravenwood/services-test/test/com/android/ravenwood/RavenwoodServicesDependenciesTest.java
deleted file mode 100644
index efe468d..0000000
--- a/ravenwood/services-test/test/com/android/ravenwood/RavenwoodServicesDependenciesTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ravenwood;
-
-import static org.junit.Assert.assertEquals;
-
-import android.platform.test.ravenwood.RavenwoodRule;
-import android.ravenwood.example.BlueManager;
-import android.ravenwood.example.RedManager;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RavenwoodServicesDependenciesTest {
-    // NOTE: we carefully only ask for RedManager here, and rely on Ravenwood internals to spin
-    // up the implicit dependency on BlueManager
-    @Rule
-    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
-            .setProcessSystem()
-            .setServicesRequired(RedManager.class)
-            .build();
-
-    @Test
-    public void testDirect() {
-        final RedManager red = mRavenwood.getContext().getSystemService(
-                RedManager.class);
-        assertEquals("blue+red", red.getInterfaceDescriptor());
-    }
-
-    @Test
-    public void testIndirect() {
-        final BlueManager blue = mRavenwood.getContext().getSystemService(
-                BlueManager.class);
-        assertEquals("blue", blue.getInterfaceDescriptor());
-    }
-}
diff --git a/ravenwood/services-test/test/com/android/ravenwood/RavenwoodServicesTest.java b/ravenwood/services-test/test/com/android/ravenwood/RavenwoodServicesTest.java
deleted file mode 100644
index c1dee5d..0000000
--- a/ravenwood/services-test/test/com/android/ravenwood/RavenwoodServicesTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ravenwood;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import android.content.Context;
-import android.hardware.SerialManager;
-import android.hardware.SerialManagerInternal;
-import android.platform.test.ravenwood.RavenwoodRule;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.server.LocalServices;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RavenwoodServicesTest {
-    private static final String TEST_VIRTUAL_PORT = "virtual:example";
-
-    @Rule
-    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
-            .setProcessSystem()
-            .setServicesRequired(SerialManager.class)
-            .build();
-
-    @Test
-    public void testDefined() {
-        final SerialManager fromName = (SerialManager)
-                mRavenwood.getContext().getSystemService(Context.SERIAL_SERVICE);
-        final SerialManager fromClass =
-                mRavenwood.getContext().getSystemService(SerialManager.class);
-        assertNotNull(fromName);
-        assertNotNull(fromClass);
-        assertEquals(fromName, fromClass);
-
-        assertNotNull(LocalServices.getService(SerialManagerInternal.class));
-    }
-
-    @Test
-    public void testSimple() {
-        // Verify that we can obtain a manager, and talk to the backend service, and that no
-        // serial ports are configured by default
-        final SerialManager service = (SerialManager)
-                mRavenwood.getContext().getSystemService(Context.SERIAL_SERVICE);
-        final String[] ports = service.getSerialPorts();
-        assertEquals(0, ports.length);
-    }
-
-    @Test
-    public void testDriven() {
-        final SerialManager service = (SerialManager)
-                mRavenwood.getContext().getSystemService(Context.SERIAL_SERVICE);
-        final SerialManagerInternal internal = LocalServices.getService(
-                SerialManagerInternal.class);
-
-        internal.addVirtualSerialPortForTest(TEST_VIRTUAL_PORT, () -> {
-            throw new UnsupportedOperationException(
-                    "Needs socketpair() to offer accurate emulation");
-        });
-        final String[] ports = service.getSerialPorts();
-        assertEquals(1, ports.length);
-        assertEquals(TEST_VIRTUAL_PORT, ports[0]);
-    }
-}
diff --git a/ravenwood/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesDependenciesTest.java b/ravenwood/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesDependenciesTest.java
new file mode 100644
index 0000000..f833782
--- /dev/null
+++ b/ravenwood/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesDependenciesTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ravenwoodtest.servicestest;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.ravenwood.example.BlueManager;
+import android.ravenwood.example.RedManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodServicesDependenciesTest {
+    // NOTE: we carefully only ask for RedManager here, and rely on Ravenwood internals to spin
+    // up the implicit dependency on BlueManager
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProcessSystem()
+            .setServicesRequired(RedManager.class)
+            .build();
+
+    @Test
+    public void testDirect() {
+        final RedManager red = mRavenwood.getContext().getSystemService(
+                RedManager.class);
+        assertEquals("blue+red", red.getInterfaceDescriptor());
+    }
+
+    @Test
+    public void testIndirect() {
+        final BlueManager blue = mRavenwood.getContext().getSystemService(
+                BlueManager.class);
+        assertEquals("blue", blue.getInterfaceDescriptor());
+    }
+}
diff --git a/ravenwood/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java b/ravenwood/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java
new file mode 100644
index 0000000..044239f
--- /dev/null
+++ b/ravenwood/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ravenwoodtest.servicestest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.hardware.SerialManager;
+import android.hardware.SerialManagerInternal;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RavenwoodServicesTest {
+    private static final String TEST_VIRTUAL_PORT = "virtual:example";
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProcessSystem()
+            .setServicesRequired(SerialManager.class)
+            .build();
+
+    @Test
+    public void testDefined() {
+        final SerialManager fromName = (SerialManager)
+                mRavenwood.getContext().getSystemService(Context.SERIAL_SERVICE);
+        final SerialManager fromClass =
+                mRavenwood.getContext().getSystemService(SerialManager.class);
+        assertNotNull(fromName);
+        assertNotNull(fromClass);
+        assertEquals(fromName, fromClass);
+
+        assertNotNull(LocalServices.getService(SerialManagerInternal.class));
+    }
+
+    @Test
+    public void testSimple() {
+        // Verify that we can obtain a manager, and talk to the backend service, and that no
+        // serial ports are configured by default
+        final SerialManager service = (SerialManager)
+                mRavenwood.getContext().getSystemService(Context.SERIAL_SERVICE);
+        final String[] ports = service.getSerialPorts();
+        assertEquals(0, ports.length);
+    }
+
+    @Test
+    public void testDriven() {
+        final SerialManager service = (SerialManager)
+                mRavenwood.getContext().getSystemService(Context.SERIAL_SERVICE);
+        final SerialManagerInternal internal = LocalServices.getService(
+                SerialManagerInternal.class);
+
+        internal.addVirtualSerialPortForTest(TEST_VIRTUAL_PORT, () -> {
+            throw new UnsupportedOperationException(
+                    "Needs socketpair() to offer accurate emulation");
+        });
+        final String[] ports = service.getSerialPorts();
+        assertEquals(1, ports.length);
+        assertEquals(TEST_VIRTUAL_PORT, ports[0]);
+    }
+}
diff --git a/ravenwood/test-authors.md b/ravenwood/test-authors.md
index 7c0cee8..2ab43bb 100644
--- a/ravenwood/test-authors.md
+++ b/ravenwood/test-authors.md
@@ -17,6 +17,7 @@
     name: "MyTestsRavenwood",
     static_libs: [
         "androidx.annotation_annotation",
+        "androidx.test.ext.junit",
         "androidx.test.rules",
     ],
     srcs: [
@@ -34,7 +35,7 @@
 import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.ravenwood.RavenwoodRule;
 
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 9b4d378..243e224 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -266,6 +266,8 @@
 android.telephony.ModemActivityInfo
 android.telephony.ServiceState
 
+android.os.connectivity.WifiActivityEnergyInfo
+
 com.android.server.LocalServices
 
 com.android.internal.util.BitUtils
diff --git a/services/Android.bp b/services/Android.bp
index 881d6e1..cd974c5 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -241,6 +241,7 @@
     libs: [
         "android.hidl.manager-V1.0-java",
         "framework-tethering.stubs.module_lib",
+        "keepanno-annotations",
         "service-art.stubs.system_server",
         "service-permission.stubs.system_server",
         "service-rkp.stubs.system_server",
@@ -323,34 +324,34 @@
             baseline_file: "api/lint-baseline.txt",
         },
     },
-    dists: [
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system-server/api",
-            dest: "android-non-updatable.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system-server/api",
-            dest: "android-non-updatable-removed.txt",
-        },
-    ],
     soong_config_variables: {
         release_hidden_api_exportable_stubs: {
             dists: [
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/system-server/api",
+                    dest: "android-non-updatable.txt",
                     tag: ".exportable.api.txt",
                 },
                 {
+                    targets: ["sdk"],
+                    dir: "apistubs/android/system-server/api",
+                    dest: "android-non-updatable-removed.txt",
                     tag: ".exportable.removed-api.txt",
                 },
             ],
             conditions_default: {
                 dists: [
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/system-server/api",
+                        dest: "android-non-updatable.txt",
                         tag: ".api.txt",
                     },
                     {
+                        targets: ["sdk"],
+                        dir: "apistubs/android/system-server/api",
+                        dest: "android-non-updatable-removed.txt",
                         tag: ".removed-api.txt",
                     },
                 ],
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index 467adc7..7a99b60 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -58,6 +58,7 @@
 aconfig_declarations {
     name: "com_android_server_accessibility_flags",
     package: "com.android.server.accessibility",
+    container: "system",
     srcs: [
         "accessibility.aconfig",
     ],
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index 04b19ff..0448f6d 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.accessibility"
+container: "system"
 
 # NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
 
@@ -48,6 +49,20 @@
 }
 
 flag {
+    name: "enable_a11y_checker_logging"
+    namespace: "accessibility"
+    description: "Whether to identify and log app a11y issues."
+    bug: "325420273"
+}
+
+flag {
+  name: "enable_hardware_shortcut_disables_warning"
+  namespace: "accessibility"
+  description: "When the user purposely enables the hardware shortcut, preemptively disables the first-time warning message."
+  bug: "287065325"
+}
+
+flag {
     name: "enable_magnification_joystick"
     namespace: "accessibility"
     description: "Whether to enable joystick controls for magnification"
@@ -76,6 +91,16 @@
 }
 
 flag {
+    name: "focus_click_point_window_bounds_from_a11y_window_info"
+    namespace: "accessibility"
+    description: "Uses A11yWindowInfo bounds for focus click point bounds checking"
+    bug: "317166487"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "fullscreen_fling_gesture"
     namespace: "accessibility"
     description: "When true, adds a fling gesture animation for fullscreen magnification"
@@ -93,6 +118,16 @@
 }
 
 flag {
+    name: "manager_avoid_receiver_timeout"
+    namespace: "accessibility"
+    description: "Avoid broadcast receiver timeout by offloading potentially slow operations to the background thread."
+    bug: "333890389"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "pinch_zoom_zero_min_span"
     namespace: "accessibility"
     description: "Whether to set min span of ScaleGestureDetector to zero."
@@ -129,3 +164,12 @@
     description: "Sends accessibility events in TouchExplorer#onAccessibilityEvent based on internal state to keep it consistent. This reduces test flakiness."
     bug: "295575684"
 }
+flag {
+    name: "send_hover_events_based_on_event_stream"
+    namespace: "accessibility"
+    description: "Send hover enter and exit based on the state of the hover event stream rather than the internal state of the touch explorer state machine. Because of the nondeterministic nature of gesture detection when done in talkback, relying on the internal state can cause crashes."
+    bug: "314251047"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 73584154..8a699ef 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -1617,9 +1617,7 @@
             final int displayId = displays[i].getDisplayId();
             onDisplayRemoved(displayId);
         }
-        if (com.android.server.accessibility.Flags.cleanupA11yOverlays()) {
             detachAllOverlays();
-        }
     }
 
     /**
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0811c87..ad869a1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -16,7 +16,15 @@
 
 package com.android.server.accessibility;
 
+import static android.Manifest.permission.CREATE_VIRTUAL_DEVICE;
+import static android.Manifest.permission.INJECT_EVENTS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.Manifest.permission.MANAGE_ACCESSIBILITY;
+import static android.Manifest.permission.MANAGE_BIND_INSTANT_SERVICE;
+import static android.Manifest.permission.MODIFY_ACCESSIBILITY_DATA;
+import static android.Manifest.permission.RETRIEVE_WINDOW_CONTENT;
+import static android.Manifest.permission.SET_SYSTEM_AUDIO_CAPTION;
+import static android.Manifest.permission.STATUS_BAR_SERVICE;
 import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_MANAGER;
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_MANAGER_CLIENT;
@@ -45,7 +53,6 @@
 import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain;
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
-import android.Manifest;
 import android.accessibilityservice.AccessibilityGestureEvent;
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
@@ -53,9 +60,11 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.accessibilityservice.MagnificationConfig;
 import android.accessibilityservice.TouchInteractionController;
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
+import android.annotation.PermissionManuallyEnforced;
+import android.annotation.RequiresNoPermission;
 import android.annotation.UserIdInt;
 import android.app.ActivityOptions;
 import android.app.AlertDialog;
@@ -95,6 +104,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PermissionEnforcer;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
@@ -204,7 +214,6 @@
  * event dispatch for {@link AccessibilityEvent}s generated across all processes
  * on the device. Events are dispatched to {@link AccessibilityService}s.
  */
-@SuppressWarnings("MissingPermissionAnnotation")
 public class AccessibilityManagerService extends IAccessibilityManager.Stub
         implements AbstractAccessibilityServiceConnection.SystemSupport,
         AccessibilityUserState.ServiceInfoChangeListener,
@@ -479,7 +488,9 @@
             AccessibilityDisplayListener a11yDisplayListener,
             MagnificationController magnificationController,
             @Nullable AccessibilityInputFilter inputFilter,
-            ProxyManager proxyManager) {
+            ProxyManager proxyManager,
+            PermissionEnforcer permissionEnforcer) {
+        super(permissionEnforcer);
         mContext = context;
         mPowerManager =  (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
@@ -514,6 +525,7 @@
      * @param context A {@link Context} instance.
      */
     public AccessibilityManagerService(Context context) {
+        super(PermissionEnforcer.fromContext(context));
         mContext = context;
         mPowerManager = context.getSystemService(PowerManager.class);
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
@@ -627,6 +639,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public IAccessibilityManager.WindowTransformationSpec getWindowTransformationSpec(
             int windowId) {
         IAccessibilityManager.WindowTransformationSpec windowTransformationSpec =
@@ -723,8 +736,7 @@
 
     void setBindInstantServiceAllowed(int userId, boolean allowed) {
         mContext.enforceCallingOrSelfPermission(
-                Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
-                "setBindInstantServiceAllowed");
+                MANAGE_BIND_INSTANT_SERVICE, "setBindInstantServiceAllowed");
         synchronized (mLock) {
             final AccessibilityUserState userState = getUserStateLocked(userId);
             if (allowed != userState.getBindInstantServiceAllowedLocked()) {
@@ -982,43 +994,10 @@
                             "context=" + context + ";intent=" + intent);
                 }
 
-                String action = intent.getAction();
-                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
-                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
-                    unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
-                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
-                } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
-                    final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
-                    if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
-                        synchronized (mLock) {
-                            restoreEnabledAccessibilityServicesLocked(
-                                    intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
-                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
-                                    intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
-                                            0));
-                        }
-                    } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
-                        synchronized (mLock) {
-                            restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
-                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
-                                    intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
-                                            0));
-                        }
-                    } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
-                        synchronized (mLock) {
-                            restoreAccessibilityButtonTargetsLocked(
-                                    intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
-                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
-                        }
-                    } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
-                        if (!android.view.accessibility.Flags.a11yQsShortcut()) {
-                            return;
-                        }
-                        restoreAccessibilityQsTargets(
-                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
-                    }
+                if (com.android.server.accessibility.Flags.managerAvoidReceiverTimeout()) {
+                    BackgroundThread.getHandler().post(() -> processBroadcast(intent));
+                } else {
+                    processBroadcast(intent);
                 }
             }
         }, UserHandle.ALL, intentFilter, null, null);
@@ -1120,6 +1099,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public long addClient(IAccessibilityManagerClient callback, int userId) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".addClient", FLAGS_ACCESSIBILITY_MANAGER,
@@ -1183,6 +1163,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public boolean removeClient(IAccessibilityManagerClient callback, int userId) {
         // TODO(b/190216606): Add tracing for removeClient when implementation is the same in master
 
@@ -1211,6 +1192,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".sendAccessibilityEvent", FLAGS_ACCESSIBILITY_MANAGER,
@@ -1327,12 +1309,13 @@
      * system action.
      */
     @Override
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     public void registerSystemAction(RemoteAction action, int actionId) {
+        registerSystemAction_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".registerSystemAction",
                     FLAGS_ACCESSIBILITY_MANAGER, "action=" + action + ";actionId=" + actionId);
         }
-        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
         getSystemActionPerformer().registerSystemAction(actionId, action);
     }
 
@@ -1342,12 +1325,14 @@
      * system action.
      */
     @Override
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     public void unregisterSystemAction(int actionId) {
+        unregisterSystemAction_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".unregisterSystemAction",
                     FLAGS_ACCESSIBILITY_MANAGER, "actionId=" + actionId);
         }
-        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+
         getSystemActionPerformer().unregisterSystemAction(actionId);
     }
 
@@ -1360,6 +1345,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public ParceledListSlice<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(
             int userId) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
@@ -1403,6 +1389,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
             int userId) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
@@ -1445,6 +1432,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void interrupt(int userId) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".interrupt",
@@ -1498,6 +1486,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public int addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken,
             IAccessibilityInteractionConnection connection, String packageName,
             int userId) throws RemoteException {
@@ -1513,6 +1502,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void removeAccessibilityInteractionConnection(IWindow window) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".removeAccessibilityInteractionConnection",
@@ -1522,23 +1512,25 @@
     }
 
     @Override
+    @EnforcePermission(MODIFY_ACCESSIBILITY_DATA)
     public void setPictureInPictureActionReplacingConnection(
             IAccessibilityInteractionConnection connection) throws RemoteException {
+        setPictureInPictureActionReplacingConnection_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".setPictureInPictureActionReplacingConnection",
                     FLAGS_ACCESSIBILITY_MANAGER, "connection=" + connection);
         }
-        mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA,
-                SET_PIP_ACTION_REPLACEMENT);
         mA11yWindowManager.setPictureInPictureActionReplacingConnection(connection);
     }
 
     @Override
+    @EnforcePermission(RETRIEVE_WINDOW_CONTENT)
     public void registerUiTestAutomationService(IBinder owner,
             IAccessibilityServiceClient serviceClient,
             AccessibilityServiceInfo accessibilityServiceInfo,
             int userId,
             int flags) {
+        registerUiTestAutomationService_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".registerUiTestAutomationService",
                     FLAGS_ACCESSIBILITY_MANAGER,
@@ -1546,9 +1538,6 @@
                     + ";accessibilityServiceInfo=" + accessibilityServiceInfo + ";flags=" + flags);
         }
 
-        mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
-                FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
-
         synchronized (mLock) {
             changeCurrentUserForTestAutomationIfNeededLocked(userId);
             mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient,
@@ -1560,6 +1549,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".unregisterUiTestAutomationService",
@@ -1619,15 +1609,14 @@
     }
 
     @Override
+    @EnforcePermission(RETRIEVE_WINDOW_CONTENT)
     public IBinder getWindowToken(int windowId, int userId) {
+        getWindowToken_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".getWindowToken",
                     FLAGS_ACCESSIBILITY_MANAGER, "windowId=" + windowId + ";userId=" + userId);
         }
 
-        mSecurityPolicy.enforceCallingPermission(
-                Manifest.permission.RETRIEVE_WINDOW_TOKEN,
-                GET_WINDOW_TOKEN);
         synchronized (mLock) {
             // We treat calls from a profile as if made by its parent as profiles
             // share the accessibility state of the parent. The call below
@@ -1663,18 +1652,15 @@
      *        specified target.
      */
     @Override
+    @EnforcePermission(STATUS_BAR_SERVICE)
     public void notifyAccessibilityButtonClicked(int displayId, String targetName) {
+        notifyAccessibilityButtonClicked_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".notifyAccessibilityButtonClicked",
                     FLAGS_ACCESSIBILITY_MANAGER,
                     "displayId=" + displayId + ";targetName=" + targetName);
         }
 
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Caller does not hold permission "
-                    + android.Manifest.permission.STATUS_BAR_SERVICE);
-        }
         if (targetName == null) {
             synchronized (mLock) {
                 final AccessibilityUserState userState = getCurrentUserStateLocked();
@@ -1694,37 +1680,27 @@
      *                  user, {@code false} otherwise
      */
     @Override
+    @EnforcePermission(STATUS_BAR_SERVICE)
     public void notifyAccessibilityButtonVisibilityChanged(boolean shown) {
+        notifyAccessibilityButtonVisibilityChanged_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".notifyAccessibilityButtonVisibilityChanged",
                     FLAGS_ACCESSIBILITY_MANAGER, "shown=" + shown);
         }
 
-        mSecurityPolicy.enforceCallingOrSelfPermission(
-                android.Manifest.permission.STATUS_BAR_SERVICE);
         synchronized (mLock) {
             notifyAccessibilityButtonVisibilityChangedLocked(shown);
         }
     }
 
     @Override
-    @RequiresPermission(allOf = {
-            Manifest.permission.STATUS_BAR_SERVICE,
-            Manifest.permission.MANAGE_ACCESSIBILITY
-    })
+    @EnforcePermission(allOf = { STATUS_BAR_SERVICE, MANAGE_ACCESSIBILITY })
     public void notifyQuickSettingsTilesChanged(
             @UserIdInt int userId, @NonNull List<ComponentName> tileComponentNames) {
+        notifyQuickSettingsTilesChanged_enforcePermission();
         if (!android.view.accessibility.Flags.a11yQsShortcut()) {
             return;
         }
-
-        mContext.enforceCallingPermission(
-                Manifest.permission.STATUS_BAR_SERVICE,
-                /* function= */ "notifyQuickSettingsTilesChanged");
-        mContext.enforceCallingPermission(
-                Manifest.permission.MANAGE_ACCESSIBILITY,
-                /* function= */ "notifyQuickSettingsTilesChanged");
-
         if (DEBUG) {
             Slog.d(LOG_TAG, TextUtils.formatSimple(
                     "notifyQuickSettingsTilesChanged userId: %d, tileComponentNames: %s",
@@ -2024,6 +2000,19 @@
         mA11yWindowManager.onTouchInteractionEnd();
     }
 
+    private void processBroadcast(Intent intent) {
+        String action = intent.getAction();
+        if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+            switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+        } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+            unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+        } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+            removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+        } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
+            restoreSetting(intent);
+        }
+    }
+
     @VisibleForTesting
     void switchUser(int userId) {
         mMagnificationController.updateUserIdIfNeeded(userId);
@@ -2116,6 +2105,38 @@
         getMagnificationController().onUserRemoved(userId);
     }
 
+    private void restoreSetting(Intent intent) {
+        final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+        if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
+            synchronized (mLock) {
+                restoreEnabledAccessibilityServicesLocked(
+                        intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+                        intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
+                        intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
+                                0));
+            }
+        } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
+            synchronized (mLock) {
+                restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
+                        intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
+                        intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
+                                0));
+            }
+        } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
+            synchronized (mLock) {
+                restoreAccessibilityButtonTargetsLocked(
+                        intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+                        intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+            }
+        } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
+            if (!android.view.accessibility.Flags.a11yQsShortcut()) {
+                return;
+            }
+            restoreAccessibilityQsTargets(
+                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+        }
+    }
+
     // Called only during settings restore; currently supports only the owner user
     // TODO: http://b/22388012
     void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting,
@@ -2734,10 +2755,13 @@
                 userState.mComponentNameToServiceMap;
         boolean isUnlockingOrUnlocked = mUmi.isUserUnlockingOrUnlocked(userState.mUserId);
 
+        // Store the list of installed services.
+        mTempComponentNameSet.clear();
         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
             ComponentName componentName = ComponentName.unflattenFromString(
                     installedService.getId());
+            mTempComponentNameSet.add(componentName);
 
             AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName);
 
@@ -2797,6 +2821,25 @@
             audioManager.setAccessibilityServiceUids(mTempIntArray);
         }
         mActivityTaskManagerService.setAccessibilityServiceUids(mTempIntArray);
+
+        // If any services have been removed, remove them from the enabled list and the touch
+        // exploration granted list.
+        boolean anyServiceRemoved =
+                userState.mEnabledServices.removeIf((comp) -> !mTempComponentNameSet.contains(comp))
+                        || userState.mTouchExplorationGrantedServices.removeIf(
+                                (comp) -> !mTempComponentNameSet.contains(comp));
+        if (anyServiceRemoved) {
+            // Update the enabled services setting.
+            persistComponentNamesToSettingLocked(
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                    userState.mEnabledServices,
+                    userState.mUserId);
+            // Update the touch exploration granted services setting.
+            persistComponentNamesToSettingLocked(
+                    Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    userState.mTouchExplorationGrantedServices,
+                    userState.mUserId);
+        }
         updateAccessibilityEnabledSettingLocked(userState);
     }
 
@@ -3931,19 +3974,15 @@
      *        class implementing a supported accessibility feature, or {@code null} if there's no
      *        specified target.
      */
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     @Override
     public void performAccessibilityShortcut(String targetName) {
+        performAccessibilityShortcut_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".performAccessibilityShortcut",
                     FLAGS_ACCESSIBILITY_MANAGER, "targetName=" + targetName);
         }
 
-        if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)
-                && (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
-                != PackageManager.PERMISSION_GRANTED)) {
-            throw new SecurityException(
-                    "performAccessibilityShortcut requires the MANAGE_ACCESSIBILITY permission");
-        }
         mMainHandler.sendMessage(obtainMessage(
                 AccessibilityManagerService::performAccessibilityShortcutInternal, this,
                 Display.DEFAULT_DISPLAY, UserShortcutType.HARDWARE, targetName));
@@ -4150,11 +4189,11 @@
      * @hide
      */
     @Override
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     public void enableShortcutsForTargets(
             boolean enable, @UserShortcutType int shortcutTypes,
             @NonNull List<String> shortcutTargets, @UserIdInt int userId) {
-        mContext.enforceCallingPermission(
-                Manifest.permission.MANAGE_ACCESSIBILITY, "enableShortcutsForTargets");
+        enableShortcutsForTargets_enforcePermission();
         for (int shortcutType : USER_SHORTCUT_TYPES) {
             if ((shortcutTypes & shortcutType) == shortcutType) {
                 enableShortcutForTargets(enable, shortcutType, shortcutTargets, userId);
@@ -4246,6 +4285,13 @@
         }
         if (shortcutType == UserShortcutType.HARDWARE) {
             skipVolumeShortcutDialogTimeoutRestriction(userId);
+            if (com.android.server.accessibility.Flags.enableHardwareShortcutDisablesWarning()) {
+                persistIntToSetting(
+                        userId,
+                        Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                        AccessibilityShortcutController.DialogStatus.SHOWN
+                );
+            }
         } else if (shortcutType == UserShortcutType.SOFTWARE) {
             // Update the A11y FAB size to large when the Magnification shortcut is
             // enabled and the user hasn't changed the floating button size
@@ -4342,10 +4388,9 @@
     }
 
     @Override
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     public Bundle getA11yFeatureToTileMap(@UserIdInt int userId) {
-        mContext.enforceCallingPermission(
-                Manifest.permission.MANAGE_ACCESSIBILITY, "getA11yFeatureToTileMap");
-
+        getA11yFeatureToTileMap_enforcePermission();
         Bundle bundle = new Bundle();
         Map<ComponentName, ComponentName> a11yFeatureToTile =
                 getA11yFeatureToTileMapInternal(userId);
@@ -4401,17 +4446,13 @@
     }
 
     @Override
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     public List<String> getAccessibilityShortcutTargets(@UserShortcutType int shortcutType) {
+        getAccessibilityShortcutTargets_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".getAccessibilityShortcutTargets",
                     FLAGS_ACCESSIBILITY_MANAGER, "shortcutType=" + shortcutType);
         }
-
-        if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "getAccessibilityShortcutService requires the MANAGE_ACCESSIBILITY permission");
-        }
         return getAccessibilityShortcutTargetsInternal(shortcutType);
     }
 
@@ -4502,6 +4543,7 @@
      * doesn't.
      */
     @Override
+    @RequiresNoPermission
     public boolean sendFingerprintGesture(int gestureKeyCode) {
         if (mTraceManager.isA11yTracingEnabledForTypes(
                 FLAGS_ACCESSIBILITY_MANAGER | FLAGS_FINGERPRINT)) {
@@ -4512,6 +4554,8 @@
 
         synchronized(mLock) {
             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
+                // TODO(b/333547153) remove the AIDL definitions for these functions that are
+                // restricted to system server and move them to AccessibilityManagerInternal.
                 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture");
             }
         }
@@ -4530,6 +4574,7 @@
      *   registered.
      */
     @Override
+    @RequiresNoPermission
     public int getAccessibilityWindowId(@Nullable IBinder windowToken) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".getAccessibilityWindowId",
@@ -4552,6 +4597,7 @@
      * integer for non-interactive one.
      */
     @Override
+    @RequiresNoPermission
     public long getRecommendedTimeoutMillis() {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(
@@ -4576,8 +4622,10 @@
     }
 
     @Override
+    @EnforcePermission(STATUS_BAR_SERVICE)
     public void setMagnificationConnection(
             IMagnificationConnection connection) throws RemoteException {
+        setMagnificationConnection_enforcePermission();
         if (mTraceManager.isA11yTracingEnabledForTypes(
                 FLAGS_ACCESSIBILITY_MANAGER | FLAGS_MAGNIFICATION_CONNECTION)) {
             mTraceManager.logTrace(LOG_TAG + ".setMagnificationConnection",
@@ -4585,10 +4633,21 @@
                     "connection=" + connection);
         }
 
-        mSecurityPolicy.enforceCallingOrSelfPermission(
-                android.Manifest.permission.STATUS_BAR_SERVICE);
-
         getMagnificationConnectionManager().setConnection(connection);
+
+        if (com.android.window.flags.Flags.alwaysDrawMagnificationFullscreenBorder()
+                && connection == null
+                && mMagnificationController.isFullScreenMagnificationControllerInitialized()) {
+            // Since the connection does not exist, the system ui cannot provide the border
+            // implementation for fullscreen magnification. So we call reset to deactivate the
+            // fullscreen magnification to prevent the magnified but no border situation.
+            final ArrayList<Display> displays = getValidDisplayList();
+            for (int i = 0; i < displays.size(); i++) {
+                final Display display = displays.get(i);
+                getMagnificationController().getFullScreenMagnificationController()
+                        .reset(display.getDisplayId(), false);
+            }
+        }
     }
 
     /**
@@ -4612,6 +4671,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void associateEmbeddedHierarchy(@NonNull IBinder host, @NonNull IBinder embedded) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".associateEmbeddedHierarchy",
@@ -4624,6 +4684,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void disassociateEmbeddedHierarchy(@NonNull IBinder token) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".disassociateEmbeddedHierarchy",
@@ -4640,6 +4701,7 @@
      * @return The stroke width.
      */
     @Override
+    @RequiresNoPermission
     public int getFocusStrokeWidth() {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".getFocusStrokeWidth", FLAGS_ACCESSIBILITY_MANAGER);
@@ -4661,6 +4723,7 @@
      * @return The color.
      */
     @Override
+    @RequiresNoPermission
     public int getFocusColor() {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".getFocusColor", FLAGS_ACCESSIBILITY_MANAGER);
@@ -4682,6 +4745,7 @@
      * @return {@code true} if the audio description is enabled, {@code false} otherwise.
      */
     @Override
+    @RequiresNoPermission
     public boolean isAudioDescriptionByDefaultEnabled() {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".isAudioDescriptionByDefaultEnabled",
@@ -4704,6 +4768,7 @@
      * @param attributes The accessibility window attributes.
      */
     @Override
+    @RequiresNoPermission
     public void setAccessibilityWindowAttributes(int displayId, int windowId, int userId,
             AccessibilityWindowAttributes attributes) {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
@@ -4715,34 +4780,30 @@
     }
 
     @Override
-    @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)
+    @EnforcePermission(SET_SYSTEM_AUDIO_CAPTION)
     public void setSystemAudioCaptioningEnabled(boolean isEnabled, int userId) {
-        mContext.enforceCallingOrSelfPermission(
-                Manifest.permission.SET_SYSTEM_AUDIO_CAPTION,
-                "setSystemAudioCaptioningEnabled");
-
+        setSystemAudioCaptioningEnabled_enforcePermission();
         mCaptioningManagerImpl.setSystemAudioCaptioningEnabled(isEnabled, userId);
     }
 
     @Override
+    @RequiresNoPermission
     public boolean isSystemAudioCaptioningUiEnabled(int userId) {
         return mCaptioningManagerImpl.isSystemAudioCaptioningUiEnabled(userId);
     }
 
     @Override
-    @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION)
+    @EnforcePermission(SET_SYSTEM_AUDIO_CAPTION)
     public void setSystemAudioCaptioningUiEnabled(boolean isEnabled, int userId) {
-        mContext.enforceCallingOrSelfPermission(
-                Manifest.permission.SET_SYSTEM_AUDIO_CAPTION,
-                "setSystemAudioCaptioningUiEnabled");
-
+        setSystemAudioCaptioningUiEnabled_enforcePermission();
         mCaptioningManagerImpl.setSystemAudioCaptioningUiEnabled(isEnabled, userId);
     }
 
     @Override
+    @EnforcePermission(CREATE_VIRTUAL_DEVICE)
     public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)
             throws RemoteException {
-        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+        registerProxyForDisplay_enforcePermission();
         mSecurityPolicy.checkForAccessibilityPermissionOrRole();
         if (client == null) {
             return false;
@@ -4778,8 +4839,9 @@
     }
 
     @Override
+    @EnforcePermission(CREATE_VIRTUAL_DEVICE)
     public boolean unregisterProxyForDisplay(int displayId) {
-        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+        unregisterProxyForDisplay_enforcePermission();
         mSecurityPolicy.checkForAccessibilityPermissionOrRole();
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -4794,6 +4856,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public boolean startFlashNotificationSequence(String opPkg,
             @FlashNotificationReason int reason, IBinder token) {
         final long identity = Binder.clearCallingIdentity();
@@ -4806,6 +4869,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public boolean stopFlashNotificationSequence(String opPkg) {
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -4816,6 +4880,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public boolean startFlashNotificationEvent(String opPkg,
             @FlashNotificationReason int reason, String reasonPkg) {
         final long identity = Binder.clearCallingIdentity();
@@ -4828,6 +4893,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId) {
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -4869,6 +4935,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     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)) {
@@ -4902,8 +4969,9 @@
     }
 
     @Override
+    @EnforcePermission(MANAGE_ACCESSIBILITY)
     public boolean isAccessibilityServiceWarningRequired(AccessibilityServiceInfo info) {
-        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+        isAccessibilityServiceWarningRequired_enforcePermission();
         final ComponentName componentName = info.getComponentName();
 
         // Warning is not required if the service is already enabled.
@@ -4949,6 +5017,7 @@
     }
 
     @Override
+    @PermissionManuallyEnforced // DUMP
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
         synchronized (mLock) {
@@ -5091,6 +5160,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
             FileDescriptor err, String[] args, ShellCallback callback,
             ResultReceiver resultReceiver) {
@@ -5200,7 +5270,14 @@
 
                 //Clip to the window bounds.
                 Rect windowBounds = mTempRect1;
-                getWindowBounds(focus.getWindowId(), windowBounds);
+                if (Flags.focusClickPointWindowBoundsFromA11yWindowInfo()) {
+                    AccessibilityWindowInfo window = focus.getWindow();
+                    if (window != null) {
+                        window.getBoundsInScreen(windowBounds);
+                    }
+                } else {
+                    getWindowBounds(focus.getWindowId(), windowBounds);
+                }
                 if (!boundsInScreenBeforeMagnification.intersect(windowBounds)) {
                     return false;
                 }
@@ -6104,9 +6181,9 @@
     }
 
     @Override
+    @EnforcePermission(INJECT_EVENTS)
     public void injectInputEventToInputFilter(InputEvent event) {
-        mSecurityPolicy.enforceCallingPermission(Manifest.permission.INJECT_EVENTS,
-                "injectInputEventToInputFilter");
+        injectInputEventToInputFilter_enforcePermission();
         synchronized (mLock) {
             final long endMillis =
                     SystemClock.uptimeMillis() + WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS;
@@ -6191,11 +6268,11 @@
         }
     }
 
+    /** Used to attach accessibility overlays from the system itself i.e. magnification. */
+    @EnforcePermission(INTERNAL_SYSTEM_WINDOW)
     @Override
-    public void attachAccessibilityOverlayToDisplay(
-            int displayId, SurfaceControl sc) {
-        mContext.enforceCallingPermission(
-                INTERNAL_SYSTEM_WINDOW, "attachAccessibilityOverlayToDisplay");
+    public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) {
+        attachAccessibilityOverlayToDisplay_enforcePermission();
         mMainHandler.sendMessage(
                 obtainMessage(
                         AccessibilityManagerService::attachAccessibilityOverlayToDisplayInternal,
@@ -6206,6 +6283,7 @@
                         null));
     }
 
+    /** Called by services to attach accessibility overlays. */
     @Override
     public void attachAccessibilityOverlayToDisplay(
             int interactionId,
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index b119d7d..853b824 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -17,6 +17,7 @@
 package com.android.server.accessibility;
 
 import android.accessibilityservice.AccessibilityService;
+import android.annotation.RequiresNoPermission;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -34,7 +35,6 @@
  * If we are stripping and/or replacing the actions from a window, we need to intercept the
  * nodes heading back to the service and swap out the actions.
  */
-@SuppressWarnings("MissingPermissionAnnotation")
 public class ActionReplacingCallback extends IAccessibilityInteractionConnectionCallback.Stub {
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "ActionReplacingCallback";
@@ -97,6 +97,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, int interactionId) {
         synchronized (mLock) {
             if (interactionId == mInteractionId) {
@@ -114,6 +115,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
             int interactionId) {
         synchronized (mLock) {
@@ -132,6 +134,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void setPrefetchAccessibilityNodeInfoResult(List<AccessibilityNodeInfo> infos,
                                                        int interactionId)
             throws RemoteException {
@@ -163,6 +166,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId)
             throws RemoteException {
         // There's no reason to use this class when performing actions. Do something reasonable.
@@ -170,6 +174,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void sendTakeScreenshotOfWindowError(int errorCode, int interactionId)
             throws RemoteException {
         mServiceCallback.sendTakeScreenshotOfWindowError(errorCode, interactionId);
@@ -285,6 +290,7 @@
     }
 
     @Override
+    @RequiresNoPermission
     public void sendAttachOverlayResult(
             @AccessibilityService.AttachOverlayResult int result, int interactionId)
             throws RemoteException {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index be2ad21..2f54f8c 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -240,7 +240,7 @@
     }
 
     private void clear(MotionEvent event, int policyFlags) {
-        if (mState.isTouchExploring()) {
+        if (mState.isTouchExploring() || Flags.sendHoverEventsBasedOnEventStream()) {
             // If a touch exploration gesture is in progress send events for its end.
             sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
         }
@@ -563,7 +563,7 @@
         mSendHoverEnterAndMoveDelayed.clear();
         mSendHoverExitDelayed.cancel();
         // If a touch exploration gesture is in progress send events for its end.
-        if (mState.isTouchExploring()) {
+        if (mState.isTouchExploring() || Flags.sendHoverEventsBasedOnEventStream()) {
             sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
         }
         if (mState.isClear()) {
@@ -852,11 +852,9 @@
         final int pointerIdBits = (1 << pointerId);
         if (mSendHoverEnterAndMoveDelayed.isPending()) {
             // If we have not delivered the enter schedule an exit.
-            if (Flags.resetHoverEventTimerOnActionUp()) {
-                // We cancel first to reset the time window so that the user has the full amount of
-                // time to do a multi tap.
-                mSendHoverEnterAndMoveDelayed.repost();
-            }
+            // We cancel first to reset the time window so that the user has the full amount of
+            // time to do a multi tap.
+            mSendHoverEnterAndMoveDelayed.repost();
             mSendHoverExitDelayed.post(event, rawEvent, pointerIdBits, policyFlags);
         } else {
             // The user is touch exploring so we send events for end.
@@ -1601,9 +1599,12 @@
                                 + " pointers down.");
                 return;
             }
-            if (Flags.resetHoverEventTimerOnActionUp() && mEvents.size() == 0) {
+            if (mEvents.size() == 0) {
                 return;
             }
+            if (Flags.sendHoverEventsBasedOnEventStream()) {
+                sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
+            }
             // Send an accessibility event to announce the touch exploration start.
             mDispatcher.sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
             if (isSendMotionEventsEnabled()) {
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 a5bbc7e..aa0af7e 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -118,6 +118,7 @@
 
     private final MagnificationThumbnailFeatureFlag mMagnificationThumbnailFeatureFlag;
     @NonNull private final Supplier<MagnificationThumbnail> mThumbnailSupplier;
+    @NonNull private final Supplier<Boolean> mMagnificationConnectionStateSupplier;
 
     /**
      * This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
@@ -682,6 +683,12 @@
             if (!mRegistered) {
                 return false;
             }
+            // If the border implementation is on system ui side but the connection is not
+            // established, the fullscreen magnification should not work.
+            if (com.android.window.flags.Flags.alwaysDrawMagnificationFullscreenBorder()
+                    && !mMagnificationConnectionStateSupplier.get()) {
+                return false;
+            }
             if (DEBUG) {
                 Slog.i(LOG_TAG,
                         "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
@@ -941,7 +948,8 @@
             @NonNull AccessibilityTraceManager traceManager, @NonNull Object lock,
             @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
             @NonNull MagnificationScaleProvider scaleProvider,
-            @NonNull Executor backgroundExecutor) {
+            @NonNull Executor backgroundExecutor,
+            @NonNull Supplier<Boolean> magnificationConnectionStateSupplier) {
         this(
                 new ControllerContext(
                         context,
@@ -955,7 +963,8 @@
                 /* thumbnailSupplier= */ null,
                 backgroundExecutor,
                 () -> new Scroller(context),
-                TimeAnimator::new);
+                TimeAnimator::new,
+                magnificationConnectionStateSupplier);
     }
 
     /** Constructor for tests */
@@ -968,11 +977,13 @@
             Supplier<MagnificationThumbnail> thumbnailSupplier,
             @NonNull Executor backgroundExecutor,
             Supplier<Scroller> scrollerSupplier,
-            Supplier<TimeAnimator> timeAnimatorSupplier) {
+            Supplier<TimeAnimator> timeAnimatorSupplier,
+            @NonNull Supplier<Boolean> magnificationConnectionStateSupplier) {
         mControllerCtx = ctx;
         mLock = lock;
         mScrollerSupplier = scrollerSupplier;
         mTimeAnimatorSupplier = timeAnimatorSupplier;
+        mMagnificationConnectionStateSupplier = magnificationConnectionStateSupplier;
         mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
         mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
         addInfoChangedCallback(magnificationInfoChangedCallback);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 20bec59..76367a2 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -798,7 +798,9 @@
                         mLock,
                         this,
                         mScaleProvider,
-                        mBackgroundExecutor
+                        mBackgroundExecutor,
+                        () -> (isMagnificationConnectionManagerInitialized()
+                                && getMagnificationConnectionManager().isConnected())
                 );
             }
         }
@@ -831,6 +833,12 @@
         }
     }
 
+    private boolean isMagnificationConnectionManagerInitialized() {
+        synchronized (mLock) {
+            return mMagnificationConnectionManager != null;
+        }
+    }
+
     private @Nullable PointF getCurrentMagnificationCenterLocked(int displayId, int targetMode) {
         if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
             if (mMagnificationConnectionManager == null
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 5e566aa..522aa67 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -202,6 +202,7 @@
     // Default max API calls per reset interval for generated preview API rate limiting.
     private static final int DEFAULT_GENERATED_PREVIEW_MAX_CALLS_PER_INTERVAL = 2;
 
+    private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids";
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -228,6 +229,11 @@
                     onPackageBroadcastReceived(intent, getSendingUserId());
                     updateWidgetPackageSuspensionMaskedState(intent, false, getSendingUserId());
                     break;
+                case Intent.ACTION_PACKAGE_RESTARTED:
+                case Intent.ACTION_PACKAGE_UNSTOPPED:
+                    if (!android.content.pm.Flags.stayStopped()) return;
+                    updateWidgetPackageStoppedMaskedState(intent);
+                    break;
                 default:
                     onPackageBroadcastReceived(intent, getSendingUserId());
                     break;
@@ -396,7 +402,10 @@
         packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_UNSTOPPED);
         packageFilter.addDataScheme("package");
+        packageFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                 packageFilter, null, mCallbackHandler);
 
@@ -581,14 +590,19 @@
                 changed |= provider.setMaskedByQuietProfileLocked(quietProfile);
                 try {
                     boolean suspended;
+                    boolean stopped;
                     try {
                         suspended = mPackageManager.isPackageSuspendedForUser(
                                 provider.id.componentName.getPackageName(), provider.getUserId());
+                        stopped = mPackageManager.isPackageStoppedForUser(
+                                provider.id.componentName.getPackageName(), provider.getUserId());
                     } catch (IllegalArgumentException ex) {
                         // Package not found.
                         suspended = false;
+                        stopped = false;
                     }
                     changed |= provider.setMaskedBySuspendedPackageLocked(suspended);
+                    changed |= provider.setMaskedByStoppedPackageLocked(stopped);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Failed to query application info", e);
                 }
@@ -636,6 +650,82 @@
     }
 
     /**
+     * Update the masked state for a stopped or unstopped package.
+     */
+    private void updateWidgetPackageStoppedMaskedState(@NonNull Intent intent) {
+        final int providerUid = intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID);
+        final Uri uri = intent.getData();
+        if (providerUid == Process.INVALID_UID || uri == null) {
+            return;
+        }
+
+        final String packageName = uri.getSchemeSpecificPart();
+        if (packageName == null) {
+            return;
+        }
+
+        boolean isStopped;
+        try {
+            isStopped = mPackageManager.isPackageStoppedForUser(packageName,
+                    UserHandle.getUserId(providerUid));
+        } catch (Exception e) {
+            Slog.e(TAG, "Failed to query package stopped state", e);
+            return;
+        }
+
+        if (DEBUG) {
+            Slog.i(TAG, "Updating package stopped masked state for uid " + providerUid + " package "
+                    + packageName + " isStopped " + isStopped);
+        }
+        synchronized (mLock) {
+            final int count = mProviders.size();
+            for (int i = 0; i < count; i++) {
+                Provider provider = mProviders.get(i);
+                if (providerUid != provider.id.uid
+                        || !packageName.equals(provider.id.componentName.getPackageName())) {
+                    continue;
+                }
+                if (provider.setMaskedByStoppedPackageLocked(isStopped)) {
+                    if (provider.isMaskedLocked()) {
+                        maskWidgetsViewsLocked(provider, null);
+                        cancelBroadcastsLocked(provider);
+                    } else {
+                        unmaskWidgetsViewsLocked(provider);
+                        final int widgetCount = provider.widgets.size();
+                        if (widgetCount > 0) {
+                            final int[] widgetIds = new int[widgetCount];
+                            for (int j = 0; j < widgetCount; j++) {
+                                widgetIds[j] = provider.widgets.get(j).appWidgetId;
+                            }
+                            registerForBroadcastsLocked(provider, widgetIds);
+                            sendUpdateIntentLocked(provider, widgetIds, /* interactive= */ false);
+                        }
+
+                        final int pendingIdsCount = provider.pendingDeletedWidgetIds.size();
+                        if (pendingIdsCount > 0) {
+                            if (DEBUG) {
+                                Slog.i(TAG, "Sending missed deleted broadcasts for "
+                                        + provider.id.componentName + " "
+                                        + provider.pendingDeletedWidgetIds);
+                            }
+                            for (int j = 0; j < pendingIdsCount; j++) {
+                                sendDeletedIntentLocked(provider.id.componentName,
+                                        provider.id.getProfile(),
+                                        provider.pendingDeletedWidgetIds.get(j));
+                            }
+                            provider.pendingDeletedWidgetIds.clear();
+                            if (widgetCount == 0) {
+                                sendDisabledIntentLocked(provider);
+                            }
+                            saveGroupStateAsync(provider.id.getProfile().getIdentifier());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
      * Mask the target widget belonging to the specified provider, or all active widgets
      * of the provider if target widget == null.
      */
@@ -648,11 +738,11 @@
                 R.layout.work_widget_mask_view);
         ApplicationInfo appInfo = provider.info.providerInfo.applicationInfo;
         final int appUserId = provider.getUserId();
-        boolean showBadge;
+        boolean showBadge = false;
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            final Intent onClickIntent;
+            Intent onClickIntent = null;
 
             if (provider.maskedByQuietProfile) {
                 showBadge = true;
@@ -676,7 +766,7 @@
                             appInfo.packageName, suspendingPackage, dialogInfo, null, null,
                             appUserId);
                 }
-            } else /* provider.maskedByLockedProfile */ {
+            } else if (provider.maskedByLockedProfile) {
                 showBadge = true;
                 onClickIntent = mKeyguardManager
                         .createConfirmDeviceCredentialIntent(null, null, appUserId);
@@ -684,6 +774,8 @@
                     onClickIntent.setFlags(
                             FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                 }
+            } else if (provider.maskedByStoppedPackage) {
+                showBadge = mUserManager.hasBadge(appUserId);
             }
 
             Icon icon = appInfo.icon != 0
@@ -697,7 +789,14 @@
             for (int j = 0; j < widgetCount; j++) {
                 Widget widget = provider.widgets.get(j);
                 if (targetWidget != null && targetWidget != widget) continue;
-                if (onClickIntent != null) {
+                if (provider.maskedByStoppedPackage) {
+                    Intent intent = createUpdateIntentLocked(provider,
+                            new int[] { widget.appWidgetId });
+                    views.setOnClickPendingIntent(android.R.id.background,
+                            PendingIntent.getBroadcast(mContext, widget.appWidgetId,
+                                    intent, PendingIntent.FLAG_UPDATE_CURRENT
+                                            | PendingIntent.FLAG_IMMUTABLE));
+                } else if (onClickIntent != null) {
                     views.setOnClickPendingIntent(android.R.id.background,
                             PendingIntent.getActivity(mContext, widget.appWidgetId, onClickIntent,
                                     PendingIntent.FLAG_UPDATE_CURRENT
@@ -1950,15 +2049,23 @@
         if (provider != null) {
             provider.widgets.remove(widget);
             if (!provider.zombie) {
-                // send the broacast saying that this appWidgetId has been deleted
-                sendDeletedIntentLocked(widget);
+                // If the package is not stopped, send the broadcast saying that this appWidgetId
+                // has been deleted. Otherwise, save the ID and send the broadcast when the package
+                // is unstopped.
+                if (!provider.maskedByStoppedPackage) {
+                    sendDeletedIntentLocked(widget);
+                } else {
+                    provider.pendingDeletedWidgetIds.add(widget.appWidgetId);
+                }
 
                 if (provider.widgets.isEmpty()) {
                     // cancel the future updates
                     cancelBroadcastsLocked(provider);
 
-                    // send the broacast saying that the provider is not in use any more
-                    sendDisabledIntentLocked(provider);
+                    // send the broadcast saying that the provider is not in use any more
+                    if (!provider.maskedByStoppedPackage) {
+                        sendDisabledIntentLocked(provider);
+                    }
                 }
             }
         }
@@ -2033,8 +2140,9 @@
             final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
             if (ids.remove(widget.appWidgetId)) {
                 // If we have removed the last app widget referencing this service, then we
-                // should destroy it and remove it from this set
-                if (ids.isEmpty()) {
+                // should destroy it and remove it from this set. This is skipped for widgets whose
+                // provider is in a stopped package, to avoid waking up the package.
+                if (ids.isEmpty() && !widget.provider.maskedByStoppedPackage) {
                     destroyRemoteViewsService(key.second.getIntent(), widget);
                     it.remove();
                 }
@@ -2544,18 +2652,29 @@
 
     private void sendUpdateIntentLocked(Provider provider, int[] appWidgetIds,
             boolean interactive) {
-        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
-        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
-        intent.setComponent(provider.id.componentName);
+        Intent intent = createUpdateIntentLocked(provider, appWidgetIds);
         sendBroadcastAsUser(intent, provider.id.getProfile(), interactive);
     }
 
+    private Intent createUpdateIntentLocked(Provider provider, int[] appWidgetIds) {
+        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
+        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
+        intent.setComponent(provider.id.componentName);
+        return intent;
+    }
+
     private void sendDeletedIntentLocked(Widget widget) {
+        sendDeletedIntentLocked(widget.provider.id.componentName, widget.provider.id.getProfile(),
+                widget.appWidgetId);
+    }
+
+    private void sendDeletedIntentLocked(ComponentName provider, UserHandle profile,
+            int appWidgetId) {
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
-        intent.setComponent(widget.provider.id.componentName);
-        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
+        intent.setComponent(provider);
+        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
         // Cleanup after deletion isn't an interactive UX case
-        sendBroadcastAsUser(intent, widget.provider.id.getProfile(), false);
+        sendBroadcastAsUser(intent, profile, false);
     }
 
     private void sendDisabledIntentLocked(Provider provider) {
@@ -2684,6 +2803,14 @@
         if (persistsProviderInfo && p.mInfoParsed) {
             AppWidgetXmlUtil.writeAppWidgetProviderInfoLocked(out, p.info);
         }
+        final int pendingIdsCount = p.pendingDeletedWidgetIds.size();
+        if (pendingIdsCount > 0) {
+            final List<String> idStrings = new ArrayList<>();
+            for (int i = 0; i < pendingIdsCount; i++) {
+                idStrings.add(String.valueOf(p.pendingDeletedWidgetIds.get(i)));
+            }
+            out.attribute(null, PENDING_DELETED_IDS_ATTR, String.join(",", idStrings));
+        }
         out.endTag(null, "p");
     }
 
@@ -3022,7 +3149,7 @@
                     continue;
                 }
 
-                if (provider.widgets.size() > 0) {
+                if (provider.widgets.size() > 0 && !provider.maskedByStoppedPackage) {
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                             "appwidget init " + provider.id.componentName.getPackageName());
                     provider.widgets.forEach(widget -> {
@@ -3440,6 +3567,16 @@
                                 legacyProviderIndex);
                         provider.tag = providerTag;
                         provider.infoTag = parser.getAttributeValue(null, "info_tag");
+
+                        final String pendingDeletedIds = parser.getAttributeValue(null,
+                                PENDING_DELETED_IDS_ATTR);
+                        if (pendingDeletedIds != null && !pendingDeletedIds.isEmpty()) {
+                            final String[] idStrings = pendingDeletedIds.split(",");
+                            for (int i = 0; i < idStrings.length; i++) {
+                                provider.pendingDeletedWidgetIds.add(
+                                        Integer.parseInt(idStrings[i]));
+                            }
+                        }
                     } else if ("h".equals(tag)) {
                         legacyHostIndex++;
                         Host host = new Host();
@@ -4443,6 +4580,11 @@
         boolean maskedByLockedProfile;
         boolean maskedByQuietProfile;
         boolean maskedBySuspendedPackage;
+        // This provider's package has been stopped
+        boolean maskedByStoppedPackage;
+        // Widget IDs for which we haven't yet sent DELETED broadcasts because the package was
+        // stopped.
+        IntArray pendingDeletedWidgetIds = new IntArray();
 
         boolean mInfoParsed = false;
 
@@ -4598,8 +4740,15 @@
             return masked != oldState;
         }
 
+        public boolean setMaskedByStoppedPackageLocked(boolean masked) {
+            boolean oldState = maskedByStoppedPackage;
+            maskedByStoppedPackage = masked;
+            return masked != oldState;
+        }
+
         public boolean isMaskedLocked() {
-            return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
+            return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage
+                    || maskedByStoppedPackage;
         }
 
         public boolean shouldBePersisted() {
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
index 0a3906a..0c3d40d 100644
--- a/services/autofill/bugfixes.aconfig
+++ b/services/autofill/bugfixes.aconfig
@@ -42,3 +42,17 @@
   description: "Use weak reference to address binder leak problem"
   bug: "307972253"
 }
+
+flag {
+  name: "add_last_focused_id_to_client_state"
+  namespace: "autofill"
+  description: "Include the current view id into the FillEventHistory events as part of ClientState"
+  bug: "334141398"
+}
+
+flag {
+  name: "add_session_id_to_client_state"
+  namespace: "autofill"
+  description: "Include the session id into the FillEventHistory events as part of ClientState"
+  bug: "333927465"
+}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index c96688c..7ceb3bb 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -28,6 +28,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.ICancellationSignal;
 import android.os.RemoteException;
 import android.service.autofill.AutofillService;
@@ -42,7 +43,6 @@
 import android.service.autofill.SaveRequest;
 import android.text.format.DateUtils;
 import android.util.Slog;
-import android.view.autofill.IAutoFillManagerClient;
 
 import com.android.internal.infra.AbstractRemoteService;
 import com.android.internal.infra.ServiceConnector;
@@ -283,8 +283,7 @@
         return callback;
     }
 
-    public void onFillCredentialRequest(@NonNull FillRequest request,
-            IAutoFillManagerClient autofillCallback) {
+    public void onFillCredentialRequest(@NonNull FillRequest request, IBinder autofillCallback) {
         if (sVerbose) {
             Slog.v(TAG, "onFillRequest:" + request);
         }
diff --git a/services/autofill/java/com/android/server/autofill/SecondaryProviderHandler.java b/services/autofill/java/com/android/server/autofill/SecondaryProviderHandler.java
index 4506779..044a064 100644
--- a/services/autofill/java/com/android/server/autofill/SecondaryProviderHandler.java
+++ b/services/autofill/java/com/android/server/autofill/SecondaryProviderHandler.java
@@ -16,21 +16,16 @@
 
 package com.android.server.autofill;
 
-import static com.android.server.autofill.Session.REQUEST_ID_KEY;
-import static com.android.server.autofill.Session.SESSION_ID_KEY;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
-import android.os.Bundle;
+import android.os.IBinder;
 import android.service.autofill.ConvertCredentialResponse;
 import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
 import android.util.Slog;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.inputmethod.InlineSuggestionsRequest;
 
 /**
  * Requests autofill response from a Remote Autofill Service. This autofill service can be
@@ -55,6 +50,7 @@
 
     private final RemoteFillService mRemoteFillService;
     private final SecondaryProviderCallback mCallback;
+
     private int mLastFlag;
 
     SecondaryProviderHandler(
@@ -109,37 +105,17 @@
     /**
      * Requests a new fill response.
      */
-    public void onFillRequest(FillRequest pendingFillRequest,
-            InlineSuggestionsRequest pendingInlineSuggestionsRequest, int flag, int id,
-            IAutoFillManagerClient client) {
+    public void onFillRequest(FillRequest pendingFillRequest, int flag, IBinder client) {
         Slog.v(TAG, "Requesting fill response to secondary provider.");
         mLastFlag = flag;
         if (mRemoteFillService != null && mRemoteFillService.isCredentialAutofillService()) {
             Slog.v(TAG, "About to call CredAutofill service as secondary provider");
-            FillRequest request = addSessionIdAndRequestIdToClientState(pendingFillRequest,
-                    pendingInlineSuggestionsRequest, id);
-            mRemoteFillService.onFillCredentialRequest(request, client);
+            mRemoteFillService.onFillCredentialRequest(pendingFillRequest, client);
         } else {
             mRemoteFillService.onFillRequest(pendingFillRequest);
         }
     }
 
-    private FillRequest addSessionIdAndRequestIdToClientState(FillRequest pendingFillRequest,
-            InlineSuggestionsRequest pendingInlineSuggestionsRequest, int sessionId) {
-        if (pendingFillRequest.getClientState() == null) {
-            pendingFillRequest = new FillRequest(pendingFillRequest.getId(),
-                    pendingFillRequest.getFillContexts(),
-                    pendingFillRequest.getHints(),
-                    new Bundle(),
-                    pendingFillRequest.getFlags(),
-                    pendingInlineSuggestionsRequest,
-                    pendingFillRequest.getDelayedFillIntentSender());
-        }
-        pendingFillRequest.getClientState().putInt(SESSION_ID_KEY, sessionId);
-        pendingFillRequest.getClientState().putInt(REQUEST_ID_KEY, pendingFillRequest.getId());
-        return pendingFillRequest;
-    }
-
     public void destroy() {
         mRemoteFillService.destroy();
     }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0b68f5f..cd1ef88 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -117,6 +117,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ServiceInfo;
+import android.credentials.CredentialManager;
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialResponse;
 import android.graphics.Bitmap;
@@ -252,7 +253,6 @@
     private final AutofillManagerServiceImpl mService;
     private final Handler mHandler;
     private final AutoFillUI mUi;
-
     /**
      * Context associated with the session, it has the same {@link Context#getDisplayId() displayId}
      * of the activity being autofilled.
@@ -751,14 +751,20 @@
             if (shouldRequestSecondaryProvider(mPendingFillRequest.getFlags())
                     && mSecondaryProviderHandler != null) {
                 Slog.v(TAG, "Requesting fill response to secondary provider.");
+                if (!mIsPrimaryCredential) {
+                    mPendingFillRequest = addCredentialManagerDataToClientState(
+                            mPendingFillRequest,
+                            mPendingInlineSuggestionsRequest, id);
+                }
                 mSecondaryProviderHandler.onFillRequest(mPendingFillRequest,
-                        mPendingInlineSuggestionsRequest,
-                        mPendingFillRequest.getFlags(), id, mClient);
+                        mPendingFillRequest.getFlags(), mClient.asBinder());
             } else if (mRemoteFillService != null) {
                 if (mIsPrimaryCredential) {
-                    mPendingFillRequest = addSessionIdAndRequestIdToClientState(mPendingFillRequest,
+                    mPendingFillRequest = addCredentialManagerDataToClientState(
+                            mPendingFillRequest,
                             mPendingInlineSuggestionsRequest, id);
-                    mRemoteFillService.onFillCredentialRequest(mPendingFillRequest, mClient);
+                    mRemoteFillService.onFillCredentialRequest(mPendingFillRequest,
+                            mClient.asBinder());
                 } else {
                     mRemoteFillService.onFillRequest(mPendingFillRequest);
                 }
@@ -904,8 +910,9 @@
         }
     }
 
-    private FillRequest addSessionIdAndRequestIdToClientState(FillRequest pendingFillRequest,
+    private FillRequest addCredentialManagerDataToClientState(FillRequest pendingFillRequest,
             InlineSuggestionsRequest pendingInlineSuggestionsRequest, int sessionId) {
+
         if (pendingFillRequest.getClientState() == null) {
             pendingFillRequest = new FillRequest(pendingFillRequest.getId(),
                     pendingFillRequest.getFillContexts(),
@@ -917,6 +924,10 @@
         }
         pendingFillRequest.getClientState().putInt(SESSION_ID_KEY, sessionId);
         pendingFillRequest.getClientState().putInt(REQUEST_ID_KEY, pendingFillRequest.getId());
+        ResultReceiver resultReceiver = constructCredentialManagerCallback(
+                pendingFillRequest.getId());
+        pendingFillRequest.getClientState().putParcelable(
+                CredentialManager.EXTRA_AUTOFILL_RESULT_RECEIVER, resultReceiver);
         return pendingFillRequest;
     }
 
@@ -2887,7 +2898,7 @@
                     + ", clientState=" + newClientState + ", authenticationId=" + authenticationId);
         }
         if (Flags.autofillCredmanDevIntegration() && exception != null
-                && exception instanceof GetCredentialException) {
+                && !exception.getType().equals(GetCredentialException.TYPE_USER_CANCELED)) {
             if (dataset != null && dataset.getFieldIds().size() == 1) {
                 if (sDebug) {
                     Slog.d(TAG, "setAuthenticationResultLocked(): result returns with"
@@ -4870,10 +4881,6 @@
 
         }
 
-        if (isCredmanIntegrationActive(response)) {
-            addCredentialManagerCallback(response);
-        }
-
         if (response.supportsInlineSuggestions()) {
             synchronized (mLock) {
                 if (requestShowInlineSuggestionsLocked(response, filterText)) {
@@ -5153,30 +5160,14 @@
         return mInlineSessionController.setInlineFillUiLocked(inlineFillUi);
     }
 
-    private void addCredentialManagerCallback(FillResponse response) {
-        if (response.getDatasets() == null) {
-            return;
-        }
-        for (Dataset dataset: response.getDatasets()) {
-            if (dataset.getId() != null
-                    && dataset.getId().equals(AutofillManager.PINNED_DATASET_ID)) {
-                Slog.d(TAG, "Adding Credential Manager callback to a pinned entry");
-                addCredentialManagerCallbackForDataset(dataset, response.getRequestId());
-            }
-        }
-    }
-
-    private void addCredentialManagerCallbackForDataset(Dataset dataset, int requestId) {
-        AutofillId autofillId = null;
-        if (dataset != null && dataset.getFieldIds().size() == 1) {
-            autofillId = dataset.getFieldIds().get(0);
-        }
-        final AutofillId finalAutofillId = autofillId;
+    private ResultReceiver constructCredentialManagerCallback(int requestId) {
         final ResultReceiver resultReceiver = new ResultReceiver(mHandler) {
+            final AutofillId mAutofillId = mCurrentViewId;
             @Override
             protected void onReceiveResult(int resultCode, Bundle resultData) {
                 if (resultCode == SUCCESS_CREDMAN_SELECTOR) {
-                    Slog.d(TAG, "onReceiveResult from Credential Manager bottom sheet");
+                    Slog.d(TAG, "onReceiveResult from Credential Manager "
+                            + "bottom sheet with mCurrentViewId: " + mAutofillId);
                     GetCredentialResponse getCredentialResponse =
                             resultData.getParcelable(
                                     CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE,
@@ -5184,7 +5175,7 @@
 
                     if (Flags.autofillCredmanDevIntegration()) {
                         sendCredentialManagerResponseToApp(getCredentialResponse,
-                                /*exception=*/ null, finalAutofillId);
+                                /*exception=*/ null, mAutofillId);
                     } else {
                         Dataset datasetFromCredential = getDatasetFromCredentialResponse(
                                 getCredentialResponse);
@@ -5198,12 +5189,14 @@
                     String[] exception =  resultData.getStringArray(
                             CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION);
                     if (exception != null && exception.length >= 2) {
+                        String errType = exception[0];
+                        String errMsg = exception[1];
                         Slog.w(TAG, "Credman bottom sheet from pinned "
-                                + "entry failed with: + " + exception[0] + " , "
-                                + exception[1]);
+                                + "entry failed with: + " + errType + " , "
+                                + errMsg);
                         sendCredentialManagerResponseToApp(/*response=*/ null,
-                                new GetCredentialException(exception[0], exception[1]),
-                                finalAutofillId);
+                                new GetCredentialException(errType, errMsg),
+                                mAutofillId);
                     }
                 } else {
                     Slog.d(TAG, "Unknown resultCode from credential "
@@ -5214,15 +5207,7 @@
         ResultReceiver ipcFriendlyResultReceiver =
                 toIpcFriendlyResultReceiver(resultReceiver);
 
-        Intent metadataIntent = dataset.getCredentialFillInIntent();
-        if (metadataIntent == null) {
-            metadataIntent = new Intent();
-        }
-
-        metadataIntent.putExtra(
-                android.credentials.selection.Constants.EXTRA_FINAL_RESPONSE_RECEIVER,
-                ipcFriendlyResultReceiver);
-        dataset.setCredentialFillInIntent(metadataIntent);
+        return ipcFriendlyResultReceiver;
     }
 
     private ResultReceiver toIpcFriendlyResultReceiver(ResultReceiver resultReceiver) {
@@ -6510,21 +6495,15 @@
                     }
                 }
                 if (exception != null) {
-                    mClient.onGetCredentialException(id, viewId, exception.getType(),
-                            exception.getMessage());
+                    if (viewId.isVirtualInt()) {
+                        sendResponseToViewNode(viewId, /*response=*/ null, exception);
+                    } else {
+                        mClient.onGetCredentialException(id, viewId, exception.getType(),
+                                exception.getMessage());
+                    }
                 } else if (response != null) {
                     if (viewId.isVirtualInt()) {
-                        ViewNode viewNode = getViewNodeFromContextsLocked(viewId);
-                        if (viewNode != null && viewNode.getPendingCredentialCallback() != null) {
-                            Bundle resultData = new Bundle();
-                            resultData.putParcelable(
-                                    CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE,
-                                    response);
-                            viewNode.getPendingCredentialCallback().send(SUCCESS_CREDMAN_SELECTOR,
-                                        resultData);
-                        } else {
-                            Slog.w(TAG, "View node not found after GetCredentialResponse");
-                        }
+                        sendResponseToViewNode(viewId, response, /*exception=*/ null);
                     } else {
                         mClient.onGetCredentialResponse(id, viewId, response);
                     }
@@ -6538,6 +6517,30 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private void sendResponseToViewNode(AutofillId viewId, GetCredentialResponse response,
+            GetCredentialException exception) {
+        ViewNode viewNode = getViewNodeFromContextsLocked(viewId);
+        if (viewNode != null && viewNode.getPendingCredentialCallback() != null) {
+            Bundle resultData = new Bundle();
+            if (response != null) {
+                resultData.putParcelable(
+                        CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE,
+                        response);
+                viewNode.getPendingCredentialCallback().send(SUCCESS_CREDMAN_SELECTOR,
+                        resultData);
+            } else if (exception != null) {
+                resultData.putStringArray(
+                        CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION,
+                        new String[] {exception.getType(), exception.getMessage()});
+                viewNode.getPendingCredentialCallback().send(FAILURE_CREDMAN_SELECTOR,
+                        resultData);
+            }
+        } else {
+            Slog.w(TAG, "View node not found after GetCredentialResponse");
+        }
+    }
+
     void autoFillApp(Dataset dataset) {
         synchronized (mLock) {
             if (mDestroyed) {
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index 2a85eb6..e13746e 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -30,5 +30,6 @@
 aconfig_declarations {
     name: "backup_flags",
     package: "com.android.server.backup",
+    container: "system",
     srcs: ["flags.aconfig"],
 }
diff --git a/services/backup/flags.aconfig b/services/backup/flags.aconfig
index 74adfe0..d53f949 100644
--- a/services/backup/flags.aconfig
+++ b/services/backup/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.backup"
+container: "system"
 
 flag {
     name: "enable_skipping_restore_launched_apps"
@@ -58,4 +59,4 @@
     description: "Increase BMM logging coverage in restore at install flow."
     bug: "331749778"
     is_fixed_read_only: true
-}
\ No newline at end of file
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index ce9cdc2..5f0071d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1510,39 +1510,48 @@
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) {
             return;
         }
-        dumpWithoutCheckingPermission(fd, pw, args);
-    }
 
-    @VisibleForTesting
-    void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) {
-        int userId = binderGetCallingUserId();
-        if (!isUserReadyForBackup(userId)) {
-            pw.println("Inactive");
+        int argIndex = 0;
+
+        String op = nextArg(args, argIndex);
+        argIndex++;
+
+        if ("--help".equals(op) || "-h".equals(op)) {
+            showDumpUsage(pw);
+            return;
+        }
+        if ("users".equals(op)) {
+            pw.print(DUMP_RUNNING_USERS_MESSAGE);
+            for (int i = 0; i < mUserServices.size(); i++) {
+                UserBackupManagerService userBackupManagerService =
+                        getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i),
+                                "dump()");
+                if (userBackupManagerService != null) {
+                    pw.print(" " + userBackupManagerService.getUserId());
+                }
+            }
+            pw.println();
+            return;
+        }
+        if ("--user".equals(op)) {
+            String userArg = nextArg(args, argIndex);
+            argIndex++;
+            if (userArg == null) {
+                showDumpUsage(pw);
+                return;
+            }
+            int userId = UserHandle.parseUserArg(userArg);
+            UserBackupManagerService userBackupManagerService =
+                    getServiceForUserIfCallerHasPermission(userId, "dump()");
+            if (userBackupManagerService != null) {
+                userBackupManagerService.dump(fd, pw, args);
+            }
             return;
         }
 
-        if (args != null) {
-            for (String arg : args) {
-                if ("-h".equals(arg)) {
-                    pw.println("'dumpsys backup' optional arguments:");
-                    pw.println("  -h       : this help text");
-                    pw.println("  a[gents] : dump information about defined backup agents");
-                    pw.println("  transportclients : dump information about transport clients");
-                    pw.println("  transportstats : dump transport statts");
-                    pw.println("  users    : dump the list of users for which backup service "
-                            + "is running");
-                    return;
-                } else if ("users".equals(arg.toLowerCase())) {
-                    pw.print(DUMP_RUNNING_USERS_MESSAGE);
-                    for (int i = 0; i < mUserServices.size(); i++) {
-                        pw.print(" " + mUserServices.keyAt(i));
-                    }
-                    pw.println();
-                    return;
-                }
-            }
-        }
-
+        // We get here if we have no parameters or parameters unkonwn to us.
+        // Print dumpsys info in either case: bug report creation passes some parameter to
+        // dumpsys that we don't need to check.
         for (int i = 0; i < mUserServices.size(); i++) {
             UserBackupManagerService userBackupManagerService =
                     getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()");
@@ -1552,6 +1561,23 @@
         }
     }
 
+    private String nextArg(String[] args, int argIndex) {
+        if (argIndex >= args.length) {
+            return null;
+        }
+        return args[argIndex];
+    }
+
+    private static void showDumpUsage(PrintWriter pw) {
+        pw.println("'dumpsys backup' optional arguments:");
+        pw.println("  --help    : this help text");
+        pw.println("  a[gents] : dump information about defined backup agents");
+        pw.println("  transportclients : dump information about transport clients");
+        pw.println("  transportstats : dump transport stats");
+        pw.println("  users    : dump the list of users for which backup service is running");
+        pw.println("  --user <userId> : dump information for user userId");
+    }
+
     /**
      * Used by the {@link JobScheduler} to run a full backup when conditions are right. The model we
      * use is to perform one app backup per scheduled job execution, and to reschedule the job with
@@ -1661,7 +1687,7 @@
      * @param message A message to include in the exception if it is thrown.
      */
     void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
-        if (Binder.getCallingUserHandle().getIdentifier() != userId) {
+        if (binderGetCallingUserId() != userId) {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
         }
diff --git a/services/companion/java/com/android/server/companion/BackupRestoreProcessor.java b/services/companion/java/com/android/server/companion/BackupRestoreProcessor.java
index 82e9a26..7a2106b 100644
--- a/services/companion/java/com/android/server/companion/BackupRestoreProcessor.java
+++ b/services/companion/java/com/android/server/companion/BackupRestoreProcessor.java
@@ -175,7 +175,7 @@
 
             // Create a new association reassigned to this user and a valid association ID
             final String packageName = restored.getPackageName();
-            final int newId = mAssociationStore.getNextId(userId);
+            final int newId = mAssociationStore.getNextId();
             AssociationInfo newAssociation = new AssociationInfo.Builder(newId, userId, packageName,
                     restored).build();
 
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 4dae6d5..30e4a3e 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -52,6 +52,7 @@
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.ecm.EnhancedConfirmationManager;
 import android.companion.AssociationInfo;
 import android.companion.AssociationRequest;
 import android.companion.IAssociationRequestCallback;
@@ -64,6 +65,7 @@
 import android.companion.datatransfer.PermissionSyncRequest;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -80,6 +82,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.flags.Flags;
 import android.util.ArraySet;
 import android.util.ExceptionUtils;
 import android.util.Slog;
@@ -448,15 +451,26 @@
             }
 
             return Binder.withCleanCallingIdentity(() -> {
+                final Intent intent;
                 if (!isRestrictedSettingsAllowed(getContext(), callingPackage, callingUid)) {
                     Slog.e(TAG, "Side loaded app must enable restricted "
                             + "setting before request the notification access");
-                    return null;
+                    if (Flags.enhancedConfirmationModeApisEnabled()) {
+                        intent = getContext()
+                                .getSystemService(EnhancedConfirmationManager.class)
+                                .createRestrictedSettingDialogIntent(callingPackage,
+                                        AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
+                    } else {
+                        return null;
+                    }
+                } else {
+                    intent = NotificationAccessConfirmationActivityContract.launcherIntent(
+                            getContext(), userId, component);
                 }
+
                 return PendingIntent.getActivityAsUser(getContext(),
                         0 /* request code */,
-                        NotificationAccessConfirmationActivityContract.launcherIntent(
-                                getContext(), userId, component),
+                        intent,
                         PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT
                                 | PendingIntent.FLAG_CANCEL_CURRENT,
                         null /* options */,
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index 9cfb535..c892b84 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -85,7 +85,7 @@
                     final int userId = getNextIntArgRequired();
                     final List<AssociationInfo> associationsForUser =
                             mAssociationStore.getActiveAssociationsByUser(userId);
-                    final int maxId = mAssociationStore.getMaxId(userId);
+                    final int maxId = mAssociationStore.getMaxId();
                     out.println("Max ID: " + maxId);
                     out.println("Association ID | Package Name | Mac Address");
                     for (AssociationInfo association : associationsForUser) {
diff --git a/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java
index a18776e..d09d7e6 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java
@@ -130,7 +130,7 @@
     private final @NonNull PackageManagerInternal mPackageManagerInternal;
     private final @NonNull AssociationStore mAssociationStore;
     @NonNull
-    private final ComponentName mCompanionDeviceActivity;
+    private final ComponentName mCompanionAssociationActivity;
 
     public AssociationRequestsProcessor(@NonNull Context context,
             @NonNull PackageManagerInternal packageManagerInternal,
@@ -138,9 +138,9 @@
         mContext = context;
         mPackageManagerInternal = packageManagerInternal;
         mAssociationStore = associationStore;
-        mCompanionDeviceActivity = createRelative(
+        mCompanionAssociationActivity = createRelative(
                 mContext.getString(R.string.config_companionDeviceManagerPackage),
-                ".CompanionDeviceActivity");
+                ".CompanionAssociationActivity");
     }
 
     /**
@@ -204,7 +204,7 @@
         extras.putParcelable(EXTRA_RESULT_RECEIVER, prepareForIpc(mOnRequestConfirmationReceiver));
 
         final Intent intent = new Intent();
-        intent.setComponent(mCompanionDeviceActivity);
+        intent.setComponent(mCompanionAssociationActivity);
         intent.putExtras(extras);
 
         // 2b.3. Create a PendingIntent.
@@ -232,7 +232,7 @@
         extras.putBoolean(EXTRA_FORCE_CANCEL_CONFIRMATION, true);
 
         final Intent intent = new Intent();
-        intent.setComponent(mCompanionDeviceActivity);
+        intent.setComponent(mCompanionAssociationActivity);
         intent.putExtras(extras);
 
         return createPendingIntent(packageUid, intent);
@@ -284,7 +284,7 @@
             @Nullable String deviceProfile, @Nullable AssociatedDevice associatedDevice,
             boolean selfManaged, @Nullable IAssociationRequestCallback callback,
             @Nullable ResultReceiver resultReceiver) {
-        final int id = mAssociationStore.getNextId(userId);
+        final int id = mAssociationStore.getNextId();
         final long timestamp = System.currentTimeMillis();
 
         final AssociationInfo association = new AssociationInfo(id, userId, packageName,
diff --git a/services/companion/java/com/android/server/companion/association/AssociationStore.java b/services/companion/java/com/android/server/companion/association/AssociationStore.java
index ae2b708..29e8095 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationStore.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationStore.java
@@ -132,7 +132,7 @@
     @GuardedBy("mLock")
     private final Map<Integer, AssociationInfo> mIdToAssociationMap = new HashMap<>();
     @GuardedBy("mLock")
-    private final Map<Integer, Integer> mUserToMaxId = new HashMap<>();
+    private int mMaxId = 0;
 
     @GuardedBy("mLocalListeners")
     private final Set<OnChangeListener> mLocalListeners = new LinkedHashSet<>();
@@ -162,7 +162,7 @@
                 mPersisted = false;
 
                 mIdToAssociationMap.clear();
-                mUserToMaxId.clear();
+                mMaxId = 0;
 
                 // The data is stored in DE directories, so we can read the data for all users now
                 // (which would not be possible if the data was stored to CE directories).
@@ -172,7 +172,7 @@
                     for (AssociationInfo association : entry.getValue().getAssociations()) {
                         mIdToAssociationMap.put(association.getId(), association);
                     }
-                    mUserToMaxId.put(entry.getKey(), entry.getValue().getMaxId());
+                    mMaxId = Math.max(mMaxId, entry.getValue().getMaxId());
                 }
 
                 mPersisted = true;
@@ -183,18 +183,18 @@
     /**
      * Get the current max association id.
      */
-    public int getMaxId(int userId) {
+    public int getMaxId() {
         synchronized (mLock) {
-            return mUserToMaxId.getOrDefault(userId, 0);
+            return mMaxId;
         }
     }
 
     /**
      * Get the next available association id.
      */
-    public int getNextId(int userId) {
+    public int getNextId() {
         synchronized (mLock) {
-            return getMaxId(userId) + 1;
+            return getMaxId() + 1;
         }
     }
 
@@ -214,7 +214,7 @@
             }
 
             mIdToAssociationMap.put(id, association);
-            mUserToMaxId.put(userId, Math.max(mUserToMaxId.getOrDefault(userId, 0), id));
+            mMaxId = Math.max(mMaxId, id);
 
             writeCacheToDisk(userId);
 
@@ -305,7 +305,7 @@
         mExecutor.execute(() -> {
             Associations associations = new Associations();
             synchronized (mLock) {
-                associations.setMaxId(mUserToMaxId.getOrDefault(userId, 0));
+                associations.setMaxId(mMaxId);
                 associations.setAssociations(
                         CollectionUtils.filter(mIdToAssociationMap.values().stream().toList(),
                                 a -> a.getUserId() == userId));
diff --git a/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java b/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java
index cfb7f337..af49df6 100644
--- a/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java
+++ b/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java
@@ -56,6 +56,7 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.CollectionUtils;
 import com.android.server.companion.association.AssociationStore;
 
 import java.io.PrintWriter;
@@ -1031,6 +1032,9 @@
     public void sendDevicePresenceEventOnUnlocked(int userId) {
         final List<DevicePresenceEvent> deviceEvents = getPendingDevicePresenceEventsByUserId(
                 userId);
+        if (CollectionUtils.isEmpty(deviceEvents)) {
+            return;
+        }
         final List<ObservableUuid> observableUuids =
                 mObservableUuidStore.getObservableUuidsForUser(userId);
         // Notify and bind the app after the phone is unlocked.
@@ -1068,7 +1072,7 @@
             }
         }
 
-        clearPendingDevicePresenceEventsByUserId(userId);
+        removePendingDevicePresenceEventsByUserId(userId);
     }
 
     private List<DevicePresenceEvent> getPendingDevicePresenceEventsByUserId(int userId) {
@@ -1077,9 +1081,11 @@
         }
     }
 
-    private void clearPendingDevicePresenceEventsByUserId(int userId) {
+    private void removePendingDevicePresenceEventsByUserId(int userId) {
         synchronized (mPendingDevicePresenceEvents) {
-            mPendingDevicePresenceEvents.get(userId).clear();
+            if (mPendingDevicePresenceEvents.contains(userId)) {
+                mPendingDevicePresenceEvents.remove(userId);
+            }
         }
     }
 
diff --git a/services/companion/java/com/android/server/companion/utils/PermissionsUtils.java b/services/companion/java/com/android/server/companion/utils/PermissionsUtils.java
index d7e766ee..f397814 100644
--- a/services/companion/java/com/android/server/companion/utils/PermissionsUtils.java
+++ b/services/companion/java/com/android/server/companion/utils/PermissionsUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.server.companion.utils;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.MANAGE_COMPANION_DEVICES;
 import static android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED;
@@ -209,7 +211,9 @@
      */
     public static void enforceCallerCanObserveDevicePresenceByUuid(@NonNull Context context) {
         if (context.checkCallingPermission(REQUEST_OBSERVE_DEVICE_UUID_PRESENCE)
-                != PERMISSION_GRANTED) {
+                != PERMISSION_GRANTED
+                || context.checkCallingPermission(BLUETOOTH_SCAN) != PERMISSION_GRANTED
+                || context.checkCallingPermission(BLUETOOTH_CONNECT) != PERMISSION_GRANTED) {
             throw new SecurityException("Caller (uid=" + getCallingUid() + ") does not have "
                     + "permissions to request observing device presence base on the UUID");
         }
diff --git a/services/companion/java/com/android/server/companion/virtual/Android.bp b/services/companion/java/com/android/server/companion/virtual/Android.bp
index 4a2030f..66313e6 100644
--- a/services/companion/java/com/android/server/companion/virtual/Android.bp
+++ b/services/companion/java/com/android/server/companion/virtual/Android.bp
@@ -10,6 +10,7 @@
 aconfig_declarations {
     name: "virtualdevice_flags",
     package: "com.android.server.companion.virtual",
+    container: "system",
     srcs: [
         "flags.aconfig",
     ],
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 f38d772b..afeafa4 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -28,6 +28,7 @@
 import android.app.WindowConfiguration;
 import android.app.compat.CompatChanges;
 import android.companion.virtual.VirtualDeviceManager.ActivityListener;
+import android.companion.virtual.flags.Flags;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.content.AttributionSource;
@@ -298,14 +299,28 @@
     public boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
             @Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
             int launchingFromDisplayId, boolean isNewTask) {
-        if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId, isNewTask)) {
-            notifyActivityBlocked(activityInfo);
-            return false;
-        }
-        if (mIntentListenerCallback != null && intent != null
-                && mIntentListenerCallback.shouldInterceptIntent(intent)) {
-            Slog.d(TAG, "Virtual device intercepting intent");
-            return false;
+        if (Flags.interceptIntentsBeforeApplyingPolicy()) {
+            if (mIntentListenerCallback != null && intent != null
+                    && mIntentListenerCallback.shouldInterceptIntent(intent)) {
+                logActivityLaunchBlocked("Virtual device intercepting intent");
+                return false;
+            }
+            if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId,
+                    isNewTask)) {
+                notifyActivityBlocked(activityInfo);
+                return false;
+            }
+        } else {
+            if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId,
+                    isNewTask)) {
+                notifyActivityBlocked(activityInfo);
+                return false;
+            }
+            if (mIntentListenerCallback != null && intent != null
+                    && mIntentListenerCallback.shouldInterceptIntent(intent)) {
+                logActivityLaunchBlocked("Virtual device intercepting intent");
+                return false;
+            }
         }
         return true;
     }
@@ -316,15 +331,17 @@
             boolean isNewTask) {
         // Mirror displays cannot contain activities.
         if (waitAndGetIsMirrorDisplay()) {
-            Slog.d(TAG, "Mirror virtual displays cannot contain activities.");
+            logActivityLaunchBlocked("Mirror virtual displays cannot contain activities.");
             return false;
         }
         if (!isWindowingModeSupported(windowingMode)) {
-            Slog.d(TAG, "Virtual device doesn't support windowing mode " + windowingMode);
+            logActivityLaunchBlocked(
+                    "Virtual device doesn't support windowing mode " + windowingMode);
             return false;
         }
         if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
-            Slog.d(TAG, "Virtual device requires android:canDisplayOnRemoteDevices=true");
+            logActivityLaunchBlocked(
+                    "Activity requires android:canDisplayOnRemoteDevices=true");
             return false;
         }
         final UserHandle activityUser =
@@ -335,11 +352,11 @@
             return true;
         }
         if (!activityUser.isSystem() && !mAllowedUsers.contains(activityUser)) {
-            Slog.d(TAG, "Virtual device launch disallowed from user " + activityUser);
+            logActivityLaunchBlocked("Activity launch disallowed from user " + activityUser);
             return false;
         }
         if (!activityMatchesDisplayCategory(activityInfo)) {
-            Slog.d(TAG, "The activity's required display category '"
+            logActivityLaunchBlocked("The activity's required display category '"
                     + activityInfo.requiredDisplayCategory
                     + "' not found on virtual display with the following categories: "
                     + mDisplayCategories);
@@ -348,7 +365,7 @@
         synchronized (mGenericWindowPolicyControllerLock) {
             if (!isAllowedByPolicy(mActivityLaunchAllowedByDefault, mActivityPolicyExemptions,
                     activityComponent)) {
-                Slog.d(TAG, "Virtual device launch disallowed by policy: "
+                logActivityLaunchBlocked("Activity launch disallowed by policy: "
                         + activityComponent);
                 return false;
             }
@@ -356,7 +373,7 @@
         if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY
                 && !isAllowedByPolicy(mCrossTaskNavigationAllowedByDefault,
                         mCrossTaskNavigationExemptions, activityComponent)) {
-            Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
+            logActivityLaunchBlocked("Cross task navigation disallowed by policy: "
                     + activityComponent);
             return false;
         }
@@ -365,12 +382,18 @@
         // based on FLAG_STREAM_PERMISSIONS
         if (mPermissionDialogComponent != null
                 && mPermissionDialogComponent.equals(activityComponent)) {
+            logActivityLaunchBlocked("Permission dialog not allowed on virtual device");
             return false;
         }
 
         return true;
     }
 
+    private void logActivityLaunchBlocked(String reason) {
+        Slog.d(TAG, "Virtual device activity launch disallowed on display "
+                + waitAndGetDisplayId() + ", reason: " + reason);
+    }
+
     @Override
     @SuppressWarnings("AndroidFrameworkRequiresPermission")
     public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
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 93243fc..215f640 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -28,8 +28,6 @@
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
 import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 import static android.companion.virtualdevice.flags.Flags.virtualCameraServiceDiscovery;
 
 import android.annotation.EnforcePermission;
@@ -1068,6 +1066,10 @@
 
     @Override
     public boolean hasCustomAudioInputSupport() throws RemoteException {
+        return hasCustomAudioInputSupportInternal();
+    }
+
+    private boolean hasCustomAudioInputSupportInternal() {
         if (!Flags.vdmPublicApis()) {
             return false;
         }
@@ -1119,6 +1121,8 @@
         if (mVirtualCameraController != null) {
             mVirtualCameraController.dump(fout, indent);
         }
+        fout.println(
+                indent + "hasCustomAudioInputSupport: " + hasCustomAudioInputSupportInternal());
     }
 
     // For display mirroring, we want to dispatch all key events to the source (default) display,
@@ -1150,8 +1154,8 @@
                 Flags.vdmCustomHome() ? mParams.getHomeComponent() : null;
 
         final GenericWindowPolicyController gwpc = new GenericWindowPolicyController(
-                FLAG_SECURE,
-                SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+                WindowManager.LayoutParams.FLAG_SECURE,
+                WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
                 mAttributionSource,
                 getAllowedUserHandles(),
                 activityLaunchAllowedByDefault,
@@ -1265,7 +1269,7 @@
         // if the secure window is shown on a non-secure virtual display.
         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
         Display display = displayManager.getDisplay(displayId);
-        if ((display.getFlags() & FLAG_SECURE) == 0) {
+        if ((display.getFlags() & Display.FLAG_SECURE) == 0) {
             showToastWhereUidIsRunning(uid, com.android.internal.R.string.vdm_secure_window,
                     Toast.LENGTH_LONG, mContext.getMainLooper());
 
diff --git a/services/companion/java/com/android/server/companion/virtual/flags.aconfig b/services/companion/java/com/android/server/companion/virtual/flags.aconfig
index 6297e91..616f5d0 100644
--- a/services/companion/java/com/android/server/companion/virtual/flags.aconfig
+++ b/services/companion/java/com/android/server/companion/virtual/flags.aconfig
@@ -1,6 +1,7 @@
 # OLD PACKAGE, DO NOT USE: Prefer `flags.aconfig` in core/java/android/companion/virtual
 # (or other custom files) to define your flags
 package: "com.android.server.companion.virtual"
+container: "system"
 
 flag {
   name: "dump_history"
diff --git a/services/contextualsearch/flags/flags.aconfig b/services/contextualsearch/flags/flags.aconfig
new file mode 100644
index 0000000..6d2da06
--- /dev/null
+++ b/services/contextualsearch/flags/flags.aconfig
@@ -0,0 +1,10 @@
+package: "com.android.server.contextualsearch.flags"
+container: "system"
+
+flag {
+    name: "enable_exclude_persistent_ui"
+    namespace: "machine_learning"
+    description: "Excluding persistent UI from contextual search screenshot."
+    is_fixed_read_only: true
+    bug: "333312675"
+}
\ No newline at end of file
diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
index 16a9933..9a73a2d 100644
--- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
+++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
@@ -17,18 +17,30 @@
 package com.android.server.contextualsearch;
 
 import static android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH;
+import static android.app.AppOpsManager.OP_ASSIST_SCREENSHOT;
+import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
 import static android.content.Context.CONTEXTUAL_SEARCH_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
 import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+
+import static com.android.server.contextualsearch.flags.Flags.enableExcludePersistentUi;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.ActivityOptions;
+import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
 import android.app.contextualsearch.CallbackToken;
 import android.app.contextualsearch.ContextualSearchManager;
 import android.app.contextualsearch.ContextualSearchState;
@@ -37,6 +49,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.graphics.Bitmap;
 import android.os.Binder;
@@ -49,15 +62,20 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ServiceManager;
 import android.os.ShellCallback;
+import android.os.SystemClock;
 import android.util.Log;
 import android.util.Slog;
+import android.view.IWindowManager;
 import android.window.ScreenCapture;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.am.AssistDataRequester;
+import com.android.server.am.AssistDataRequester.AssistDataRequesterCallbacks;
 import com.android.server.wm.ActivityAssistInfo;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
@@ -66,21 +84,69 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 public class ContextualSearchManagerService extends SystemService {
-
+    private static final String TAG = ContextualSearchManagerService.class.getSimpleName();
     private static final int MSG_RESET_TEMPORARY_PACKAGE = 0;
     private static final int MAX_TEMP_PACKAGE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
+
     private final Context mContext;
     private final ActivityTaskManagerInternal mAtmInternal;
+    private final PackageManagerInternal mPackageManager;
     private final WindowManagerInternal mWmInternal;
     private final DevicePolicyManagerInternal mDpmInternal;
+    private final Object mLock = new Object();
+    private final AssistDataRequester mAssistDataRequester;
 
-    private Handler mTemporaryHandler;
+    private final AssistDataRequesterCallbacks mAssistDataCallbacks =
+            new AssistDataRequesterCallbacks() {
+                @Override
+                public boolean canHandleReceivedAssistDataLocked() {
+                    synchronized (mLock) {
+                        return mStateCallback != null;
+                    }
+                }
+
+                @Override
+                public void onAssistDataReceivedLocked(
+                        final Bundle data,
+                        final int activityIndex,
+                        final int activityCount) {
+                    final IContextualSearchCallback callback;
+                    synchronized (mLock) {
+                        callback = mStateCallback;
+                    }
+
+                    if (callback != null) {
+                        try {
+                            callback.onResult(new ContextualSearchState(
+                                    data.getParcelable(ASSIST_KEY_STRUCTURE, AssistStructure.class),
+                                    data.getParcelable(ASSIST_KEY_CONTENT, AssistContent.class),
+                                    data));
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error invoking ContextualSearchCallback", e);
+                        }
+                    } else {
+                        Log.w(TAG, "Callback went away!");
+                    }
+                }
+
+                @Override
+                public void onAssistRequestCompleted() {
+                    synchronized (mLock) {
+                        mStateCallback = null;
+                    }
+                }
+            };
 
     @GuardedBy("this")
+    private Handler mTemporaryHandler;
+    @GuardedBy("this")
     private String mTemporaryPackage = null;
-    private static final String TAG = ContextualSearchManagerService.class.getSimpleName();
+
+    @GuardedBy("mLock")
+    private IContextualSearchCallback mStateCallback;
 
     public ContextualSearchManagerService(@NonNull Context context) {
         super(context);
@@ -88,8 +154,14 @@
         mContext = context;
         mAtmInternal = Objects.requireNonNull(
                 LocalServices.getService(ActivityTaskManagerInternal.class));
+        mPackageManager = LocalServices.getService(PackageManagerInternal.class);
         mWmInternal = Objects.requireNonNull(LocalServices.getService(WindowManagerInternal.class));
         mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
+        mAssistDataRequester = new AssistDataRequester(
+                mContext,
+                IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE)),
+                mContext.getSystemService(AppOpsManager.class),
+                mAssistDataCallbacks, mLock, OP_ASSIST_STRUCTURE, OP_ASSIST_SCREENSHOT);
     }
 
     @Override
@@ -174,25 +246,53 @@
         if (DEBUG_USER) Log.d(TAG, "Launch component: " + launchIntent.getComponent());
         launchIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION
                 | FLAG_ACTIVITY_NO_USER_ACTION);
+        launchIntent.putExtra(
+                ContextualSearchManager.EXTRA_INVOCATION_TIME_MS,
+                SystemClock.uptimeMillis());
         launchIntent.putExtra(ContextualSearchManager.EXTRA_ENTRYPOINT, entrypoint);
         launchIntent.putExtra(ContextualSearchManager.EXTRA_TOKEN, mToken);
         boolean isAssistDataAllowed = mAtmInternal.isAssistDataAllowed();
         final List<ActivityAssistInfo> records = mAtmInternal.getTopVisibleActivities();
+        final List<IBinder> activityTokens = new ArrayList<>(records.size());
         ArrayList<String> visiblePackageNames = new ArrayList<>();
         boolean isManagedProfileVisible = false;
         for (ActivityAssistInfo record : records) {
             // Add the package name to the list only if assist data is allowed.
             if (isAssistDataAllowed) {
                 visiblePackageNames.add(record.getComponentName().getPackageName());
+                activityTokens.add(record.getActivityToken());
             }
             if (mDpmInternal != null
                     && mDpmInternal.isUserOrganizationManaged(record.getUserId())) {
                 isManagedProfileVisible = true;
             }
         }
+        if (isAssistDataAllowed) {
+            try {
+                final String csPackage = Objects.requireNonNull(launchIntent.getPackage());
+                final int csUid = mPackageManager.getPackageUid(csPackage, 0, 0);
+                mAssistDataRequester.requestAssistData(
+                        activityTokens,
+                        /* fetchData */ true,
+                        /* fetchScreenshot */ false,
+                        /* allowFetchData */ true,
+                        /* allowFetchScreenshot */ false,
+                        csUid,
+                        csPackage,
+                        null);
+            } catch (Exception e) {
+                Log.e(TAG, "Could not request assist data", e);
+            }
+        }
         final ScreenCapture.ScreenshotHardwareBuffer shb;
         if (mWmInternal != null) {
-            shb = mWmInternal.takeAssistScreenshot();
+            if (enableExcludePersistentUi()) {
+                shb = mWmInternal.takeAssistScreenshot(
+                        Set.of(TYPE_STATUS_BAR, TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL));
+            } else {
+                shb = mWmInternal.takeAssistScreenshot(/* windowTypesToExclude= */ Set.of());
+            }
+
         } else {
             shb = null;
         }
@@ -264,6 +364,7 @@
             synchronized (this) {
                 if (DEBUG_USER) Log.d(TAG, "startContextualSearch");
                 enforcePermission("startContextualSearch");
+                mAssistDataRequester.cancel();
                 mToken = new CallbackToken();
                 // We get the launch intent with the system server's identity because the system
                 // server has READ_FRAME_BUFFER permission to get the screenshot and because only
@@ -298,17 +399,19 @@
                 return;
             }
             mToken = null;
-            // Process data request
-            try {
-                callback.onResult(new ContextualSearchState(null, null, Bundle.EMPTY));
-            } catch (RemoteException e) {
-                Log.e(TAG, "Could not invoke onResult callback", e);
+            synchronized (mLock) {
+                mStateCallback = callback;
             }
+            mAssistDataRequester.processPendingAssistData();
         }
 
-        public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
-                @Nullable FileDescriptor err, @NonNull String[] args,
-                @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) {
+        public void onShellCommand(
+                @Nullable FileDescriptor in,
+                @Nullable FileDescriptor out,
+                @Nullable FileDescriptor err,
+                @NonNull String[] args,
+                @Nullable ShellCallback callback,
+                @NonNull ResultReceiver resultReceiver) {
             new ContextualSearchManagerShellCommand(ContextualSearchManagerService.this)
                     .exec(this, in, out, err, args, callback, resultReceiver);
         }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index c7d9942..300b147 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -145,6 +145,7 @@
     defaults: [
         "platform_service_defaults",
         "android.hardware.power-java_shared",
+        "latest_android_hardware_broadcastradio_java_static",
     ],
     srcs: [
         ":android.hardware.tv.hdmi.connection-V1-java-source",
@@ -182,6 +183,7 @@
         "android.hardware.vibrator-V2-java",
         "app-compat-annotations",
         "framework-tethering.stubs.module_lib",
+        "keepanno-annotations",
         "service-art.stubs.system_server",
         "service-permission.stubs.system_server",
         "service-rkp.stubs.system_server",
@@ -206,14 +208,15 @@
         "android.hardware.boot-V1.2-java", // HIDL
         "android.hardware.boot-V1-java", // AIDL
         "android.hardware.broadcastradio-V2.0-java", // HIDL
-        "android.hardware.broadcastradio-V2-java", // AIDL
         "android.hardware.health-V1.0-java", // HIDL
         "android.hardware.health-V2.0-java", // HIDL
         "android.hardware.health-V2.1-java", // HIDL
         "android.hardware.health-V3-java", // AIDL
         "android.hardware.health-translate-java",
         "android.hardware.light-V1-java",
+        "android.hardware.security.authgraph-V1-java",
         "android.hardware.security.rkp-V3-java",
+        "android.hardware.security.secretkeeper-V1-java",
         "android.hardware.tv.cec-V1.1-java",
         "android.hardware.tv.hdmi.cec-V1-java",
         "android.hardware.tv.hdmi.connection-V1-java",
@@ -231,7 +234,6 @@
         "android.hidl.manager-V1.2-java",
         "cbor-java",
         "com.android.media.audio-aconfig-java",
-        "dropbox_flags_lib",
         "icu4j_calendar_astronomer",
         "android.security.aaid_aidl-java",
         "netd-client",
@@ -240,7 +242,6 @@
         "com.android.sysprop.watchdog",
         "securebox",
         "apache-commons-math",
-        "backstage_power_flags_lib",
         "notification_flags_lib",
         "power_hint_flags_lib",
         "biometrics_flags_lib",
@@ -254,6 +255,7 @@
         "net_flags_lib",
         "stats_flags_lib",
         "core_os_flags_lib",
+        "connectivity_flags_lib",
     ],
     javac_shard_size: 50,
     javacflags: [
diff --git a/packages/CrashRecovery/services/java/com/android/server/ExplicitHealthCheckController.java b/services/core/java/com/android/server/ExplicitHealthCheckController.java
similarity index 100%
rename from packages/CrashRecovery/services/java/com/android/server/ExplicitHealthCheckController.java
rename to services/core/java/com/android/server/ExplicitHealthCheckController.java
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 1741593..ccc44a4 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static com.android.internal.R.integer.config_defaultMinEmergencyGestureTapDurationMillis;
+
 import android.app.ActivityManager;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
@@ -70,12 +72,6 @@
      */
     @VisibleForTesting static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300;
 
-    /**
-     * Min time in milliseconds to complete the emergency gesture for it count. If the gesture is
-     * completed faster than this, we assume it's not performed by human and the
-     * event gets ignored.
-     */
-    @VisibleForTesting static final int EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS = 200;
 
     /**
      * Interval in milliseconds in which the power button must be depressed in succession to be
@@ -570,7 +566,8 @@
                     long emergencyGestureTapDetectionMinTimeMs = Settings.Global.getInt(
                             mContext.getContentResolver(),
                             Settings.Global.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS,
-                            EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS);
+                            mContext.getResources().getInteger(
+                                    config_defaultMinEmergencyGestureTapDurationMillis));
                     if (emergencyGestureSpentTime <= emergencyGestureTapDetectionMinTimeMs) {
                         Slog.i(TAG, "Emergency gesture detected but it's too fast. Gesture time: "
                                 + emergencyGestureSpentTime + " ms");
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index bdc4a7a..2545620 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -22,6 +22,7 @@
 per-file *Battery* = file:/BATTERY_STATS_OWNERS
 per-file *BinaryTransparency* = file:/core/java/android/transparency/OWNERS
 per-file *Binder* = file:/core/java/com/android/internal/os/BINDER_OWNERS
+per-file ExplicitHealthCheckController.java = file:/services/core/java/com/android/server/crashrecovery/OWNERS
 per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
 per-file **IpSec* = file:/services/core/java/com/android/server/net/OWNERS
 per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
@@ -35,9 +36,9 @@
 per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
 per-file MmsServiceBroker.java = file:/telephony/OWNERS
 per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS
-per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS
+per-file PackageWatchdog.java = file:/services/core/java/com/android/server/crashrecovery/OWNERS
 per-file PinnerService.java = file:/core/java/android/app/pinner/OWNERS
-per-file RescueParty.java = [email protected], [email protected], [email protected]
+per-file RescueParty.java = file:/services/core/java/com/android/server/crashrecovery/OWNERS
 per-file SensitiveContentProtectionManagerService.java = file:/core/java/android/permission/OWNERS
 per-file SystemClockTime.java = file:/services/core/java/com/android/server/timedetector/OWNERS
 per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
new file mode 100644
index 0000000..6f20adf
--- /dev/null
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -0,0 +1,1971 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static android.service.watchdog.ExplicitHealthCheckService.PackageConfig;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.crashrecovery.flags.Flags;
+import android.net.ConnectivityModuleConnector;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Process;
+import android.os.SystemProperties;
+import android.provider.DeviceConfig;
+import android.sysprop.CrashRecoveryProperties;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.LongArrayQueue;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.XmlUtils;
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Monitors the health of packages on the system and notifies interested observers when packages
+ * fail. On failure, the registered observer with the least user impacting mitigation will
+ * be notified.
+ */
+public class PackageWatchdog {
+    private static final String TAG = "PackageWatchdog";
+
+    static final String PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS =
+            "watchdog_trigger_failure_duration_millis";
+    static final String PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT =
+            "watchdog_trigger_failure_count";
+    static final String PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED =
+            "watchdog_explicit_health_check_enabled";
+
+    // TODO: make the following values configurable via DeviceConfig
+    private static final long NATIVE_CRASH_POLLING_INTERVAL_MILLIS =
+            TimeUnit.SECONDS.toMillis(30);
+    private static final long NUMBER_OF_NATIVE_CRASH_POLLS = 10;
+
+
+    public static final int FAILURE_REASON_UNKNOWN = 0;
+    public static final int FAILURE_REASON_NATIVE_CRASH = 1;
+    public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
+    public static final int FAILURE_REASON_APP_CRASH = 3;
+    public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
+    public static final int FAILURE_REASON_BOOT_LOOP = 5;
+
+    @IntDef(prefix = { "FAILURE_REASON_" }, value = {
+            FAILURE_REASON_UNKNOWN,
+            FAILURE_REASON_NATIVE_CRASH,
+            FAILURE_REASON_EXPLICIT_HEALTH_CHECK,
+            FAILURE_REASON_APP_CRASH,
+            FAILURE_REASON_APP_NOT_RESPONDING,
+            FAILURE_REASON_BOOT_LOOP
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FailureReasons {}
+
+    // Duration to count package failures before it resets to 0
+    @VisibleForTesting
+    static final int DEFAULT_TRIGGER_FAILURE_DURATION_MS =
+            (int) TimeUnit.MINUTES.toMillis(1);
+    // Number of package failures within the duration above before we notify observers
+    @VisibleForTesting
+    static final int DEFAULT_TRIGGER_FAILURE_COUNT = 5;
+    @VisibleForTesting
+    static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2);
+    // Sliding window for tracking how many mitigation calls were made for a package.
+    @VisibleForTesting
+    static final long DEFAULT_DEESCALATION_WINDOW_MS = TimeUnit.HOURS.toMillis(1);
+    // Whether explicit health checks are enabled or not
+    private static final boolean DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED = true;
+
+    @VisibleForTesting
+    static final int DEFAULT_BOOT_LOOP_TRIGGER_COUNT = 5;
+
+    static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10);
+
+    // Threshold level at which or above user might experience significant disruption.
+    private static final String MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
+            "persist.device_config.configuration.major_user_impact_level_threshold";
+    private static final int DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
+            PackageHealthObserverImpact.USER_IMPACT_LEVEL_71;
+
+    private long mNumberOfNativeCrashPollsRemaining;
+
+    private static final int DB_VERSION = 1;
+    private static final String TAG_PACKAGE_WATCHDOG = "package-watchdog";
+    private static final String TAG_PACKAGE = "package";
+    private static final String TAG_OBSERVER = "observer";
+    private static final String ATTR_VERSION = "version";
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_DURATION = "duration";
+    private static final String ATTR_EXPLICIT_HEALTH_CHECK_DURATION = "health-check-duration";
+    private static final String ATTR_PASSED_HEALTH_CHECK = "passed-health-check";
+    private static final String ATTR_MITIGATION_CALLS = "mitigation-calls";
+    private static final String ATTR_MITIGATION_COUNT = "mitigation-count";
+
+    // A file containing information about the current mitigation count in the case of a boot loop.
+    // This allows boot loop information to persist in the case of an fs-checkpoint being
+    // aborted.
+    private static final String METADATA_FILE = "/metadata/watchdog/mitigation_count.txt";
+
+    @GuardedBy("PackageWatchdog.class")
+    private static PackageWatchdog sPackageWatchdog;
+
+    private final Object mLock = new Object();
+    // System server context
+    private final Context mContext;
+    // Handler to run short running tasks
+    private final Handler mShortTaskHandler;
+    // Handler for processing IO and long running tasks
+    private final Handler mLongTaskHandler;
+    // Contains (observer-name -> observer-handle) that have ever been registered from
+    // previous boots. Observers with all packages expired are periodically pruned.
+    // It is saved to disk on system shutdown and repouplated on startup so it survives reboots.
+    @GuardedBy("mLock")
+    private final ArrayMap<String, ObserverInternal> mAllObservers = new ArrayMap<>();
+    // File containing the XML data of monitored packages /data/system/package-watchdog.xml
+    private final AtomicFile mPolicyFile;
+    private final ExplicitHealthCheckController mHealthCheckController;
+    private final ConnectivityModuleConnector mConnectivityModuleConnector;
+    private final Runnable mSyncRequests = this::syncRequests;
+    private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason;
+    private final Runnable mSaveToFile = this::saveToFile;
+    private final SystemClock mSystemClock;
+    private final BootThreshold mBootThreshold;
+    private final DeviceConfig.OnPropertiesChangedListener
+            mOnPropertyChangedListener = this::onPropertyChanged;
+
+    // The set of packages that have been synced with the ExplicitHealthCheckController
+    @GuardedBy("mLock")
+    private Set<String> mRequestedHealthCheckPackages = new ArraySet<>();
+    @GuardedBy("mLock")
+    private boolean mIsPackagesReady;
+    // Flag to control whether explicit health checks are supported or not
+    @GuardedBy("mLock")
+    private boolean mIsHealthCheckEnabled = DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED;
+    @GuardedBy("mLock")
+    private int mTriggerFailureDurationMs = DEFAULT_TRIGGER_FAILURE_DURATION_MS;
+    @GuardedBy("mLock")
+    private int mTriggerFailureCount = DEFAULT_TRIGGER_FAILURE_COUNT;
+    // SystemClock#uptimeMillis when we last executed #syncState
+    // 0 if no prune is scheduled.
+    @GuardedBy("mLock")
+    private long mUptimeAtLastStateSync;
+    // If true, sync explicit health check packages with the ExplicitHealthCheckController.
+    @GuardedBy("mLock")
+    private boolean mSyncRequired = false;
+
+    @FunctionalInterface
+    @VisibleForTesting
+    interface SystemClock {
+        long uptimeMillis();
+    }
+
+    private PackageWatchdog(Context context) {
+        // Needs to be constructed inline
+        this(context, new AtomicFile(
+                        new File(new File(Environment.getDataDirectory(), "system"),
+                                "package-watchdog.xml")),
+                new Handler(Looper.myLooper()), BackgroundThread.getHandler(),
+                new ExplicitHealthCheckController(context),
+                ConnectivityModuleConnector.getInstance(),
+                android.os.SystemClock::uptimeMillis);
+    }
+
+    /**
+     * Creates a PackageWatchdog that allows injecting dependencies.
+     */
+    @VisibleForTesting
+    PackageWatchdog(Context context, AtomicFile policyFile, Handler shortTaskHandler,
+            Handler longTaskHandler, ExplicitHealthCheckController controller,
+            ConnectivityModuleConnector connectivityModuleConnector, SystemClock clock) {
+        mContext = context;
+        mPolicyFile = policyFile;
+        mShortTaskHandler = shortTaskHandler;
+        mLongTaskHandler = longTaskHandler;
+        mHealthCheckController = controller;
+        mConnectivityModuleConnector = connectivityModuleConnector;
+        mSystemClock = clock;
+        mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
+        mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
+                DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS);
+
+        loadFromFile();
+        sPackageWatchdog = this;
+    }
+
+    /** Creates or gets singleton instance of PackageWatchdog. */
+    public static PackageWatchdog getInstance(Context context) {
+        synchronized (PackageWatchdog.class) {
+            if (sPackageWatchdog == null) {
+                new PackageWatchdog(context);
+            }
+            return sPackageWatchdog;
+        }
+    }
+
+    /**
+     * Called during boot to notify when packages are ready on the device so we can start
+     * binding.
+     */
+    public void onPackagesReady() {
+        synchronized (mLock) {
+            mIsPackagesReady = true;
+            mHealthCheckController.setCallbacks(packageName -> onHealthCheckPassed(packageName),
+                    packages -> onSupportedPackages(packages),
+                    this::onSyncRequestNotified);
+            setPropertyChangedListenerLocked();
+            updateConfigs();
+            registerConnectivityModuleHealthListener();
+        }
+    }
+
+    /**
+     * Registers {@code observer} to listen for package failures. Add a new ObserverInternal for
+     * this observer if it does not already exist.
+     *
+     * <p>Observers are expected to call this on boot. It does not specify any packages but
+     * it will resume observing any packages requested from a previous boot.
+     */
+    public void registerHealthObserver(PackageHealthObserver observer) {
+        synchronized (mLock) {
+            ObserverInternal internalObserver = mAllObservers.get(observer.getName());
+            if (internalObserver != null) {
+                internalObserver.registeredObserver = observer;
+            } else {
+                internalObserver = new ObserverInternal(observer.getName(), new ArrayList<>());
+                internalObserver.registeredObserver = observer;
+                mAllObservers.put(observer.getName(), internalObserver);
+                syncState("added new observer");
+            }
+        }
+    }
+
+    /**
+     * Starts observing the health of the {@code packages} for {@code observer} and notifies
+     * {@code observer} of any package failures within the monitoring duration.
+     *
+     * <p>If monitoring a package supporting explicit health check, at the end of the monitoring
+     * duration if {@link #onHealthCheckPassed} was never called,
+     * {@link PackageHealthObserver#execute} will be called as if the package failed.
+     *
+     * <p>If {@code observer} is already monitoring a package in {@code packageNames},
+     * the monitoring window of that package will be reset to {@code durationMs} and the health
+     * check state will be reset to a default depending on if the package is contained in
+     * {@link mPackagesWithExplicitHealthCheckEnabled}.
+     *
+     * <p>If {@code packageNames} is empty, this will be a no-op.
+     *
+     * <p>If {@code durationMs} is less than 1, a default monitoring duration
+     * {@link #DEFAULT_OBSERVING_DURATION_MS} will be used.
+     */
+    public void startObservingHealth(PackageHealthObserver observer, List<String> packageNames,
+            long durationMs) {
+        if (packageNames.isEmpty()) {
+            Slog.wtf(TAG, "No packages to observe, " + observer.getName());
+            return;
+        }
+        if (durationMs < 1) {
+            Slog.wtf(TAG, "Invalid duration " + durationMs + "ms for observer "
+                    + observer.getName() + ". Not observing packages " + packageNames);
+            durationMs = DEFAULT_OBSERVING_DURATION_MS;
+        }
+
+        List<MonitoredPackage> packages = new ArrayList<>();
+        for (int i = 0; i < packageNames.size(); i++) {
+            // Health checks not available yet so health check state will start INACTIVE
+            MonitoredPackage pkg = newMonitoredPackage(packageNames.get(i), durationMs, false);
+            if (pkg != null) {
+                packages.add(pkg);
+            } else {
+                Slog.w(TAG, "Failed to create MonitoredPackage for pkg=" + packageNames.get(i));
+            }
+        }
+
+        if (packages.isEmpty()) {
+            return;
+        }
+
+        // Sync before we add the new packages to the observers. This will #pruneObservers,
+        // causing any elapsed time to be deducted from all existing packages before we add new
+        // packages. This maintains the invariant that the elapsed time for ALL (new and existing)
+        // packages is the same.
+        mLongTaskHandler.post(() -> {
+            syncState("observing new packages");
+
+            synchronized (mLock) {
+                ObserverInternal oldObserver = mAllObservers.get(observer.getName());
+                if (oldObserver == null) {
+                    Slog.d(TAG, observer.getName() + " started monitoring health "
+                            + "of packages " + packageNames);
+                    mAllObservers.put(observer.getName(),
+                            new ObserverInternal(observer.getName(), packages));
+                } else {
+                    Slog.d(TAG, observer.getName() + " added the following "
+                            + "packages to monitor " + packageNames);
+                    oldObserver.updatePackagesLocked(packages);
+                }
+            }
+
+            // Register observer in case not already registered
+            registerHealthObserver(observer);
+
+            // Sync after we add the new packages to the observers. We may have received packges
+            // requiring an earlier schedule than we are currently scheduled for.
+            syncState("updated observers");
+        });
+
+    }
+
+    /**
+     * Unregisters {@code observer} from listening to package failure.
+     * Additionally, this stops observing any packages that may have previously been observed
+     * even from a previous boot.
+     */
+    public void unregisterHealthObserver(PackageHealthObserver observer) {
+        mLongTaskHandler.post(() -> {
+            synchronized (mLock) {
+                mAllObservers.remove(observer.getName());
+            }
+            syncState("unregistering observer: " + observer.getName());
+        });
+    }
+
+    /**
+     * Called when a process fails due to a crash, ANR or explicit health check.
+     *
+     * <p>For each package contained in the process, one registered observer with the least user
+     * impact will be notified for mitigation.
+     *
+     * <p>This method could be called frequently if there is a severe problem on the device.
+     */
+    public void onPackageFailure(List<VersionedPackage> packages,
+            @FailureReasons int failureReason) {
+        if (packages == null) {
+            Slog.w(TAG, "Could not resolve a list of failing packages");
+            return;
+        }
+        mLongTaskHandler.post(() -> {
+            synchronized (mLock) {
+                if (mAllObservers.isEmpty()) {
+                    return;
+                }
+                boolean requiresImmediateAction = (failureReason == FAILURE_REASON_NATIVE_CRASH
+                        || failureReason == FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+                if (requiresImmediateAction) {
+                    handleFailureImmediately(packages, failureReason);
+                } else {
+                    for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
+                        VersionedPackage versionedPackage = packages.get(pIndex);
+                        // Observer that will receive failure for versionedPackage
+                        PackageHealthObserver currentObserverToNotify = null;
+                        int currentObserverImpact = Integer.MAX_VALUE;
+                        MonitoredPackage currentMonitoredPackage = null;
+
+                        // Find observer with least user impact
+                        for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
+                            ObserverInternal observer = mAllObservers.valueAt(oIndex);
+                            PackageHealthObserver registeredObserver = observer.registeredObserver;
+                            if (registeredObserver != null
+                                    && observer.onPackageFailureLocked(
+                                    versionedPackage.getPackageName())) {
+                                MonitoredPackage p = observer.getMonitoredPackage(
+                                        versionedPackage.getPackageName());
+                                int mitigationCount = 1;
+                                if (p != null) {
+                                    mitigationCount = p.getMitigationCountLocked() + 1;
+                                }
+                                int impact = registeredObserver.onHealthCheckFailed(
+                                        versionedPackage, failureReason, mitigationCount);
+                                if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
+                                        && impact < currentObserverImpact) {
+                                    currentObserverToNotify = registeredObserver;
+                                    currentObserverImpact = impact;
+                                    currentMonitoredPackage = p;
+                                }
+                            }
+                        }
+
+                        // Execute action with least user impact
+                        if (currentObserverToNotify != null) {
+                            int mitigationCount = 1;
+                            if (currentMonitoredPackage != null) {
+                                currentMonitoredPackage.noteMitigationCallLocked();
+                                mitigationCount =
+                                        currentMonitoredPackage.getMitigationCountLocked();
+                            }
+                            if (Flags.recoverabilityDetection()) {
+                                maybeExecute(currentObserverToNotify, versionedPackage,
+                                        failureReason, currentObserverImpact, mitigationCount);
+                            } else {
+                                currentObserverToNotify.execute(versionedPackage,
+                                        failureReason, mitigationCount);
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * For native crashes or explicit health check failures, call directly into each observer to
+     * mitigate the error without going through failure threshold logic.
+     */
+    private void handleFailureImmediately(List<VersionedPackage> packages,
+            @FailureReasons int failureReason) {
+        VersionedPackage failingPackage = packages.size() > 0 ? packages.get(0) : null;
+        PackageHealthObserver currentObserverToNotify = null;
+        int currentObserverImpact = Integer.MAX_VALUE;
+        for (ObserverInternal observer: mAllObservers.values()) {
+            PackageHealthObserver registeredObserver = observer.registeredObserver;
+            if (registeredObserver != null) {
+                int impact = registeredObserver.onHealthCheckFailed(
+                        failingPackage, failureReason, 1);
+                if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
+                        && impact < currentObserverImpact) {
+                    currentObserverToNotify = registeredObserver;
+                    currentObserverImpact = impact;
+                }
+            }
+        }
+        if (currentObserverToNotify != null) {
+            if (Flags.recoverabilityDetection()) {
+                maybeExecute(currentObserverToNotify, failingPackage, failureReason,
+                        currentObserverImpact, /*mitigationCount=*/ 1);
+            } else {
+                currentObserverToNotify.execute(failingPackage,  failureReason, 1);
+            }
+        }
+    }
+
+    private void maybeExecute(PackageHealthObserver currentObserverToNotify,
+                              VersionedPackage versionedPackage,
+                              @FailureReasons int failureReason,
+                              int currentObserverImpact,
+                              int mitigationCount) {
+        if (currentObserverImpact < getUserImpactLevelLimit()) {
+            currentObserverToNotify.execute(versionedPackage, failureReason, mitigationCount);
+        }
+    }
+
+
+    /**
+     * Called when the system server boots. If the system server is detected to be in a boot loop,
+     * query each observer and perform the mitigation action with the lowest user impact.
+     *
+     * Note: PackageWatchdog considers system_server restart loop as bootloop. Full reboots
+     * are not counted in bootloop.
+     */
+    @SuppressWarnings("GuardedBy")
+    public void noteBoot() {
+        synchronized (mLock) {
+            // if boot count has reached threshold, start mitigation.
+            // We wait until threshold number of restarts only for the first time. Perform
+            // mitigations for every restart after that.
+            boolean mitigate = mBootThreshold.incrementAndTest();
+            if (mitigate) {
+                if (!Flags.recoverabilityDetection()) {
+                    mBootThreshold.reset();
+                }
+                int mitigationCount = mBootThreshold.getMitigationCount() + 1;
+                PackageHealthObserver currentObserverToNotify = null;
+                ObserverInternal currentObserverInternal = null;
+                int currentObserverImpact = Integer.MAX_VALUE;
+                for (int i = 0; i < mAllObservers.size(); i++) {
+                    final ObserverInternal observer = mAllObservers.valueAt(i);
+                    PackageHealthObserver registeredObserver = observer.registeredObserver;
+                    if (registeredObserver != null) {
+                        int impact = Flags.recoverabilityDetection()
+                                ? registeredObserver.onBootLoop(
+                                        observer.getBootMitigationCount() + 1)
+                                : registeredObserver.onBootLoop(mitigationCount);
+                        if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0
+                                && impact < currentObserverImpact) {
+                            currentObserverToNotify = registeredObserver;
+                            currentObserverInternal = observer;
+                            currentObserverImpact = impact;
+                        }
+                    }
+                }
+                if (currentObserverToNotify != null) {
+                    if (Flags.recoverabilityDetection()) {
+                        int currentObserverMitigationCount =
+                                currentObserverInternal.getBootMitigationCount() + 1;
+                        currentObserverInternal.setBootMitigationCount(
+                                currentObserverMitigationCount);
+                        saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
+                        currentObserverToNotify.executeBootLoopMitigation(
+                                currentObserverMitigationCount);
+                    } else {
+                        mBootThreshold.setMitigationCount(mitigationCount);
+                        mBootThreshold.saveMitigationCountToMetadata();
+                        currentObserverToNotify.executeBootLoopMitigation(mitigationCount);
+                    }
+                }
+            }
+        }
+    }
+
+    // TODO(b/120598832): Optimize write? Maybe only write a separate smaller file? Also
+    // avoid holding lock?
+    // This currently adds about 7ms extra to shutdown thread
+    /** Writes the package information to file during shutdown. */
+    public void writeNow() {
+        synchronized (mLock) {
+            // Must only run synchronous tasks as this runs on the ShutdownThread and no other
+            // thread is guaranteed to run during shutdown.
+            if (!mAllObservers.isEmpty()) {
+                mLongTaskHandler.removeCallbacks(mSaveToFile);
+                pruneObserversLocked();
+                saveToFile();
+                Slog.i(TAG, "Last write to update package durations");
+            }
+        }
+    }
+
+    /**
+     * Enables or disables explicit health checks.
+     * <p> If explicit health checks are enabled, the health check service is started.
+     * <p> If explicit health checks are disabled, pending explicit health check requests are
+     * passed and the health check service is stopped.
+     */
+    private void setExplicitHealthCheckEnabled(boolean enabled) {
+        synchronized (mLock) {
+            mIsHealthCheckEnabled = enabled;
+            mHealthCheckController.setEnabled(enabled);
+            mSyncRequired = true;
+            // Prune to update internal state whenever health check is enabled/disabled
+            syncState("health check state " + (enabled ? "enabled" : "disabled"));
+        }
+    }
+
+    /**
+     * This method should be only called on mShortTaskHandler, since it modifies
+     * {@link #mNumberOfNativeCrashPollsRemaining}.
+     */
+    private void checkAndMitigateNativeCrashes() {
+        mNumberOfNativeCrashPollsRemaining--;
+        // Check if native watchdog reported a crash
+        if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
+            // We rollback all available low impact rollbacks when crash is unattributable
+            onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH);
+            // we stop polling after an attempt to execute rollback, regardless of whether the
+            // attempt succeeds or not
+        } else {
+            if (mNumberOfNativeCrashPollsRemaining > 0) {
+                mShortTaskHandler.postDelayed(() -> checkAndMitigateNativeCrashes(),
+                        NATIVE_CRASH_POLLING_INTERVAL_MILLIS);
+            }
+        }
+    }
+
+    /**
+     * Since this method can eventually trigger a rollback, it should be called
+     * only once boot has completed {@code onBootCompleted} and not earlier, because the install
+     * session must be entirely completed before we try to rollback.
+     */
+    public void scheduleCheckAndMitigateNativeCrashes() {
+        Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check "
+                + "and mitigate native crashes");
+        mShortTaskHandler.post(()->checkAndMitigateNativeCrashes());
+    }
+
+    private int getUserImpactLevelLimit() {
+        return SystemProperties.getInt(MAJOR_USER_IMPACT_LEVEL_THRESHOLD,
+                DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD);
+    }
+
+    /** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */
+    @Retention(SOURCE)
+    @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_10,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_20,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_30,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_50,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_71,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_75,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_80,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_90,
+                     PackageHealthObserverImpact.USER_IMPACT_LEVEL_100})
+    public @interface PackageHealthObserverImpact {
+        /** No action to take. */
+        int USER_IMPACT_LEVEL_0 = 0;
+        /* Action has low user impact, user of a device will barely notice. */
+        int USER_IMPACT_LEVEL_10 = 10;
+        /* Actions having medium user impact, user of a device will likely notice. */
+        int USER_IMPACT_LEVEL_20 = 20;
+        int USER_IMPACT_LEVEL_30 = 30;
+        int USER_IMPACT_LEVEL_50 = 50;
+        int USER_IMPACT_LEVEL_70 = 70;
+        /* Action has high user impact, a last resort, user of a device will be very frustrated. */
+        int USER_IMPACT_LEVEL_71 = 71;
+        int USER_IMPACT_LEVEL_75 = 75;
+        int USER_IMPACT_LEVEL_80 = 80;
+        int USER_IMPACT_LEVEL_90 = 90;
+        int USER_IMPACT_LEVEL_100 = 100;
+    }
+
+    /** Register instances of this interface to receive notifications on package failure. */
+    public interface PackageHealthObserver {
+        /**
+         * Called when health check fails for the {@code versionedPackage}.
+         *
+         * @param versionedPackage the package that is failing. This may be null if a native
+         *                          service is crashing.
+         * @param failureReason   the type of failure that is occurring.
+         * @param mitigationCount the number of times mitigation has been called for this package
+         *                        (including this time).
+         *
+         *
+         * @return any one of {@link PackageHealthObserverImpact} to express the impact
+         * to the user on {@link #execute}
+         */
+        @PackageHealthObserverImpact int onHealthCheckFailed(
+                @Nullable VersionedPackage versionedPackage,
+                @FailureReasons int failureReason,
+                int mitigationCount);
+
+        /**
+         * Executes mitigation for {@link #onHealthCheckFailed}.
+         *
+         * @param versionedPackage the package that is failing. This may be null if a native
+         *                          service is crashing.
+         * @param failureReason   the type of failure that is occurring.
+         * @param mitigationCount the number of times mitigation has been called for this package
+         *                        (including this time).
+         * @return {@code true} if action was executed successfully, {@code false} otherwise
+         */
+        boolean execute(@Nullable VersionedPackage versionedPackage,
+                @FailureReasons int failureReason, int mitigationCount);
+
+
+        /**
+         * Called when the system server has booted several times within a window of time, defined
+         * by {@link #mBootThreshold}
+         *
+         * @param mitigationCount the number of times mitigation has been attempted for this
+         *                        boot loop (including this time).
+         */
+        default @PackageHealthObserverImpact int onBootLoop(int mitigationCount) {
+            return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+        }
+
+        /**
+         * Executes mitigation for {@link #onBootLoop}
+         * @param mitigationCount the number of times mitigation has been attempted for this
+         *                        boot loop (including this time).
+         */
+        default boolean executeBootLoopMitigation(int mitigationCount) {
+            return false;
+        }
+
+        // TODO(b/120598832): Ensure uniqueness?
+        /**
+         * Identifier for the observer, should not change across device updates otherwise the
+         * watchdog may drop observing packages with the old name.
+         */
+        String getName();
+
+        /**
+         * An observer will not be pruned if this is set, even if the observer is not explicitly
+         * monitoring any packages.
+         */
+        default boolean isPersistent() {
+            return false;
+        }
+
+        /**
+         * Returns {@code true} if this observer wishes to observe the given package, {@code false}
+         * otherwise
+         *
+         * <p> A persistent observer may choose to start observing certain failing packages, even if
+         * it has not explicitly asked to watch the package with {@link #startObservingHealth}.
+         */
+        default boolean mayObservePackage(String packageName) {
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    long getTriggerFailureCount() {
+        synchronized (mLock) {
+            return mTriggerFailureCount;
+        }
+    }
+
+    @VisibleForTesting
+    long getTriggerFailureDurationMs() {
+        synchronized (mLock) {
+            return mTriggerFailureDurationMs;
+        }
+    }
+
+    /**
+     * Serializes and syncs health check requests with the {@link ExplicitHealthCheckController}.
+     */
+    private void syncRequestsAsync() {
+        mShortTaskHandler.removeCallbacks(mSyncRequests);
+        mShortTaskHandler.post(mSyncRequests);
+    }
+
+    /**
+     * Syncs health check requests with the {@link ExplicitHealthCheckController}.
+     * Calls to this must be serialized.
+     *
+     * @see #syncRequestsAsync
+     */
+    private void syncRequests() {
+        boolean syncRequired = false;
+        synchronized (mLock) {
+            if (mIsPackagesReady) {
+                Set<String> packages = getPackagesPendingHealthChecksLocked();
+                if (mSyncRequired || !packages.equals(mRequestedHealthCheckPackages)
+                        || packages.isEmpty()) {
+                    syncRequired = true;
+                    mRequestedHealthCheckPackages = packages;
+                }
+            } // else, we will sync requests when packages become ready
+        }
+
+        // Call outside lock to avoid holding lock when calling into the controller.
+        if (syncRequired) {
+            Slog.i(TAG, "Syncing health check requests for packages: "
+                    + mRequestedHealthCheckPackages);
+            mHealthCheckController.syncRequests(mRequestedHealthCheckPackages);
+            mSyncRequired = false;
+        }
+    }
+
+    /**
+     * Updates the observers monitoring {@code packageName} that explicit health check has passed.
+     *
+     * <p> This update is strictly for registered observers at the time of the call
+     * Observers that register after this signal will have no knowledge of prior signals and will
+     * effectively behave as if the explicit health check hasn't passed for {@code packageName}.
+     *
+     * <p> {@code packageName} can still be considered failed if reported by
+     * {@link #onPackageFailureLocked} before the package expires.
+     *
+     * <p> Triggered by components outside the system server when they are fully functional after an
+     * update.
+     */
+    private void onHealthCheckPassed(String packageName) {
+        Slog.i(TAG, "Health check passed for package: " + packageName);
+        boolean isStateChanged = false;
+
+        synchronized (mLock) {
+            for (int observerIdx = 0; observerIdx < mAllObservers.size(); observerIdx++) {
+                ObserverInternal observer = mAllObservers.valueAt(observerIdx);
+                MonitoredPackage monitoredPackage = observer.getMonitoredPackage(packageName);
+
+                if (monitoredPackage != null) {
+                    int oldState = monitoredPackage.getHealthCheckStateLocked();
+                    int newState = monitoredPackage.tryPassHealthCheckLocked();
+                    isStateChanged |= oldState != newState;
+                }
+            }
+        }
+
+        if (isStateChanged) {
+            syncState("health check passed for " + packageName);
+        }
+    }
+
+    private void onSupportedPackages(List<PackageConfig> supportedPackages) {
+        boolean isStateChanged = false;
+
+        Map<String, Long> supportedPackageTimeouts = new ArrayMap<>();
+        Iterator<PackageConfig> it = supportedPackages.iterator();
+        while (it.hasNext()) {
+            PackageConfig info = it.next();
+            supportedPackageTimeouts.put(info.getPackageName(), info.getHealthCheckTimeoutMillis());
+        }
+
+        synchronized (mLock) {
+            Slog.d(TAG, "Received supported packages " + supportedPackages);
+            Iterator<ObserverInternal> oit = mAllObservers.values().iterator();
+            while (oit.hasNext()) {
+                Iterator<MonitoredPackage> pit = oit.next().getMonitoredPackages()
+                        .values().iterator();
+                while (pit.hasNext()) {
+                    MonitoredPackage monitoredPackage = pit.next();
+                    String packageName = monitoredPackage.getName();
+                    int oldState = monitoredPackage.getHealthCheckStateLocked();
+                    int newState;
+
+                    if (supportedPackageTimeouts.containsKey(packageName)) {
+                        // Supported packages become ACTIVE if currently INACTIVE
+                        newState = monitoredPackage.setHealthCheckActiveLocked(
+                                supportedPackageTimeouts.get(packageName));
+                    } else {
+                        // Unsupported packages are marked as PASSED unless already FAILED
+                        newState = monitoredPackage.tryPassHealthCheckLocked();
+                    }
+                    isStateChanged |= oldState != newState;
+                }
+            }
+        }
+
+        if (isStateChanged) {
+            syncState("updated health check supported packages " + supportedPackages);
+        }
+    }
+
+    private void onSyncRequestNotified() {
+        synchronized (mLock) {
+            mSyncRequired = true;
+            syncRequestsAsync();
+        }
+    }
+
+    @GuardedBy("mLock")
+    private Set<String> getPackagesPendingHealthChecksLocked() {
+        Set<String> packages = new ArraySet<>();
+        Iterator<ObserverInternal> oit = mAllObservers.values().iterator();
+        while (oit.hasNext()) {
+            ObserverInternal observer = oit.next();
+            Iterator<MonitoredPackage> pit =
+                    observer.getMonitoredPackages().values().iterator();
+            while (pit.hasNext()) {
+                MonitoredPackage monitoredPackage = pit.next();
+                String packageName = monitoredPackage.getName();
+                if (monitoredPackage.isPendingHealthChecksLocked()) {
+                    packages.add(packageName);
+                }
+            }
+        }
+        return packages;
+    }
+
+    /**
+     * Syncs the state of the observers.
+     *
+     * <p> Prunes all observers, saves new state to disk, syncs health check requests with the
+     * health check service and schedules the next state sync.
+     */
+    private void syncState(String reason) {
+        synchronized (mLock) {
+            Slog.i(TAG, "Syncing state, reason: " + reason);
+            pruneObserversLocked();
+
+            saveToFileAsync();
+            syncRequestsAsync();
+
+            // Done syncing state, schedule the next state sync
+            scheduleNextSyncStateLocked();
+        }
+    }
+
+    private void syncStateWithScheduledReason() {
+        syncState("scheduled");
+    }
+
+    @GuardedBy("mLock")
+    private void scheduleNextSyncStateLocked() {
+        long durationMs = getNextStateSyncMillisLocked();
+        mShortTaskHandler.removeCallbacks(mSyncStateWithScheduledReason);
+        if (durationMs == Long.MAX_VALUE) {
+            Slog.i(TAG, "Cancelling state sync, nothing to sync");
+            mUptimeAtLastStateSync = 0;
+        } else {
+            mUptimeAtLastStateSync = mSystemClock.uptimeMillis();
+            mShortTaskHandler.postDelayed(mSyncStateWithScheduledReason, durationMs);
+        }
+    }
+
+    /**
+     * Returns the next duration in millis to sync the watchdog state.
+     *
+     * @returns Long#MAX_VALUE if there are no observed packages.
+     */
+    @GuardedBy("mLock")
+    private long getNextStateSyncMillisLocked() {
+        long shortestDurationMs = Long.MAX_VALUE;
+        for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
+            ArrayMap<String, MonitoredPackage> packages = mAllObservers.valueAt(oIndex)
+                    .getMonitoredPackages();
+            for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
+                MonitoredPackage mp = packages.valueAt(pIndex);
+                long duration = mp.getShortestScheduleDurationMsLocked();
+                if (duration < shortestDurationMs) {
+                    shortestDurationMs = duration;
+                }
+            }
+        }
+        return shortestDurationMs;
+    }
+
+    /**
+     * Removes {@code elapsedMs} milliseconds from all durations on monitored packages
+     * and updates other internal state.
+     */
+    @GuardedBy("mLock")
+    private void pruneObserversLocked() {
+        long elapsedMs = mUptimeAtLastStateSync == 0
+                ? 0 : mSystemClock.uptimeMillis() - mUptimeAtLastStateSync;
+        if (elapsedMs <= 0) {
+            Slog.i(TAG, "Not pruning observers, elapsed time: " + elapsedMs + "ms");
+            return;
+        }
+
+        Iterator<ObserverInternal> it = mAllObservers.values().iterator();
+        while (it.hasNext()) {
+            ObserverInternal observer = it.next();
+            Set<MonitoredPackage> failedPackages =
+                    observer.prunePackagesLocked(elapsedMs);
+            if (!failedPackages.isEmpty()) {
+                onHealthCheckFailed(observer, failedPackages);
+            }
+            if (observer.getMonitoredPackages().isEmpty() && (observer.registeredObserver == null
+                    || !observer.registeredObserver.isPersistent())) {
+                Slog.i(TAG, "Discarding observer " + observer.name + ". All packages expired");
+                it.remove();
+            }
+        }
+    }
+
+    private void onHealthCheckFailed(ObserverInternal observer,
+            Set<MonitoredPackage> failedPackages) {
+        mLongTaskHandler.post(() -> {
+            synchronized (mLock) {
+                PackageHealthObserver registeredObserver = observer.registeredObserver;
+                if (registeredObserver != null) {
+                    Iterator<MonitoredPackage> it = failedPackages.iterator();
+                    while (it.hasNext()) {
+                        VersionedPackage versionedPkg = getVersionedPackage(it.next().getName());
+                        if (versionedPkg != null) {
+                            Slog.i(TAG,
+                                    "Explicit health check failed for package " + versionedPkg);
+                            registeredObserver.execute(versionedPkg,
+                                    PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK, 1);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Gets PackageInfo for the given package. Matches any user and apex.
+     *
+     * @throws PackageManager.NameNotFoundException if no such package is installed.
+     */
+    private PackageInfo getPackageInfo(String packageName)
+            throws PackageManager.NameNotFoundException {
+        PackageManager pm = mContext.getPackageManager();
+        try {
+            // The MATCH_ANY_USER flag doesn't mix well with the MATCH_APEX
+            // flag, so make two separate attempts to get the package info.
+            // We don't need both flags at the same time because we assume
+            // apex files are always installed for all users.
+            return pm.getPackageInfo(packageName, PackageManager.MATCH_ANY_USER);
+        } catch (PackageManager.NameNotFoundException e) {
+            return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
+        }
+    }
+
+    @Nullable
+    private VersionedPackage getVersionedPackage(String packageName) {
+        final PackageManager pm = mContext.getPackageManager();
+        if (pm == null || TextUtils.isEmpty(packageName)) {
+            return null;
+        }
+        try {
+            final long versionCode = getPackageInfo(packageName).getLongVersionCode();
+            return new VersionedPackage(packageName, versionCode);
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Loads mAllObservers from file.
+     *
+     * <p>Note that this is <b>not</b> thread safe and should only called be called
+     * from the constructor.
+     */
+    private void loadFromFile() {
+        InputStream infile = null;
+        mAllObservers.clear();
+        try {
+            infile = mPolicyFile.openRead();
+            final TypedXmlPullParser parser = Xml.resolvePullParser(infile);
+            XmlUtils.beginDocument(parser, TAG_PACKAGE_WATCHDOG);
+            int outerDepth = parser.getDepth();
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                ObserverInternal observer = ObserverInternal.read(parser, this);
+                if (observer != null) {
+                    mAllObservers.put(observer.name, observer);
+                }
+            }
+        } catch (FileNotFoundException e) {
+            // Nothing to monitor
+        } catch (IOException | NumberFormatException | XmlPullParserException e) {
+            Slog.wtf(TAG, "Unable to read monitored packages, deleting file", e);
+            mPolicyFile.delete();
+        } finally {
+            IoUtils.closeQuietly(infile);
+        }
+    }
+
+    private void onPropertyChanged(DeviceConfig.Properties properties) {
+        try {
+            updateConfigs();
+        } catch (Exception ignore) {
+            Slog.w(TAG, "Failed to reload device config changes");
+        }
+    }
+
+    /** Adds a {@link DeviceConfig#OnPropertiesChangedListener}. */
+    private void setPropertyChangedListenerLocked() {
+        DeviceConfig.addOnPropertiesChangedListener(
+                DeviceConfig.NAMESPACE_ROLLBACK,
+                mContext.getMainExecutor(),
+                mOnPropertyChangedListener);
+    }
+
+    @VisibleForTesting
+    void removePropertyChangedListener() {
+        DeviceConfig.removeOnPropertiesChangedListener(mOnPropertyChangedListener);
+    }
+
+    /**
+     * Health check is enabled or disabled after reading the flags
+     * from DeviceConfig.
+     */
+    @VisibleForTesting
+    void updateConfigs() {
+        synchronized (mLock) {
+            mTriggerFailureCount = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_ROLLBACK,
+                    PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
+                    DEFAULT_TRIGGER_FAILURE_COUNT);
+            if (mTriggerFailureCount <= 0) {
+                mTriggerFailureCount = DEFAULT_TRIGGER_FAILURE_COUNT;
+            }
+
+            mTriggerFailureDurationMs = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_ROLLBACK,
+                    PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS,
+                    DEFAULT_TRIGGER_FAILURE_DURATION_MS);
+            if (mTriggerFailureDurationMs <= 0) {
+                mTriggerFailureDurationMs = DEFAULT_TRIGGER_FAILURE_DURATION_MS;
+            }
+
+            setExplicitHealthCheckEnabled(DeviceConfig.getBoolean(
+                    DeviceConfig.NAMESPACE_ROLLBACK,
+                    PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED,
+                    DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED));
+        }
+    }
+
+    private void registerConnectivityModuleHealthListener() {
+        // TODO: have an internal method to trigger a rollback by reporting high severity errors,
+        // and rely on ActivityManager to inform the watchdog of severe network stack crashes
+        // instead of having this listener in parallel.
+        mConnectivityModuleConnector.registerHealthListener(
+                packageName -> {
+                    final VersionedPackage pkg = getVersionedPackage(packageName);
+                    if (pkg == null) {
+                        Slog.wtf(TAG, "NetworkStack failed but could not find its package");
+                        return;
+                    }
+                    final List<VersionedPackage> pkgList = Collections.singletonList(pkg);
+                    onPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+                });
+    }
+
+    /**
+     * Persists mAllObservers to file. Threshold information is ignored.
+     */
+    private boolean saveToFile() {
+        Slog.i(TAG, "Saving observer state to file");
+        synchronized (mLock) {
+            FileOutputStream stream;
+            try {
+                stream = mPolicyFile.startWrite();
+            } catch (IOException e) {
+                Slog.w(TAG, "Cannot update monitored packages", e);
+                return false;
+            }
+
+            try {
+                TypedXmlSerializer out = Xml.resolveSerializer(stream);
+                out.startDocument(null, true);
+                out.startTag(null, TAG_PACKAGE_WATCHDOG);
+                out.attributeInt(null, ATTR_VERSION, DB_VERSION);
+                for (int oIndex = 0; oIndex < mAllObservers.size(); oIndex++) {
+                    mAllObservers.valueAt(oIndex).writeLocked(out);
+                }
+                out.endTag(null, TAG_PACKAGE_WATCHDOG);
+                out.endDocument();
+                mPolicyFile.finishWrite(stream);
+                return true;
+            } catch (IOException e) {
+                Slog.w(TAG, "Failed to save monitored packages, restoring backup", e);
+                mPolicyFile.failWrite(stream);
+                return false;
+            } finally {
+                IoUtils.closeQuietly(stream);
+            }
+        }
+    }
+
+    private void saveToFileAsync() {
+        if (!mLongTaskHandler.hasCallbacks(mSaveToFile)) {
+            mLongTaskHandler.post(mSaveToFile);
+        }
+    }
+
+    /** Convert a {@code LongArrayQueue} to a String of comma-separated values. */
+    public static String longArrayQueueToString(LongArrayQueue queue) {
+        if (queue.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(queue.get(0));
+            for (int i = 1; i < queue.size(); i++) {
+                sb.append(",");
+                sb.append(queue.get(i));
+            }
+            return sb.toString();
+        }
+        return "";
+    }
+
+    /** Parse a comma-separated String of longs into a LongArrayQueue. */
+    public static LongArrayQueue parseLongArrayQueue(String commaSeparatedValues) {
+        LongArrayQueue result = new LongArrayQueue();
+        if (!TextUtils.isEmpty(commaSeparatedValues)) {
+            String[] values = commaSeparatedValues.split(",");
+            for (String value : values) {
+                result.addLast(Long.parseLong(value));
+            }
+        }
+        return result;
+    }
+
+
+    /** Dump status of every observer in mAllObservers. */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("Package Watchdog status");
+        pw.increaseIndent();
+        synchronized (mLock) {
+            for (String observerName : mAllObservers.keySet()) {
+                pw.println("Observer name: " + observerName);
+                pw.increaseIndent();
+                ObserverInternal observerInternal = mAllObservers.get(observerName);
+                observerInternal.dump(pw);
+                pw.decreaseIndent();
+            }
+        }
+    }
+
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    void registerObserverInternal(ObserverInternal observerInternal) {
+        mAllObservers.put(observerInternal.name, observerInternal);
+    }
+
+    /**
+     * Represents an observer monitoring a set of packages along with the failure thresholds for
+     * each package.
+     *
+     * <p> Note, the PackageWatchdog#mLock must always be held when reading or writing
+     * instances of this class.
+     */
+    static class ObserverInternal {
+        public final String name;
+        @GuardedBy("mLock")
+        private final ArrayMap<String, MonitoredPackage> mPackages = new ArrayMap<>();
+        @Nullable
+        @GuardedBy("mLock")
+        public PackageHealthObserver registeredObserver;
+        private int mMitigationCount;
+
+        ObserverInternal(String name, List<MonitoredPackage> packages) {
+            this(name, packages, /*mitigationCount=*/ 0);
+        }
+
+        ObserverInternal(String name, List<MonitoredPackage> packages, int mitigationCount) {
+            this.name = name;
+            updatePackagesLocked(packages);
+            this.mMitigationCount = mitigationCount;
+        }
+
+        /**
+         * Writes important {@link MonitoredPackage} details for this observer to file.
+         * Does not persist any package failure thresholds.
+         */
+        @GuardedBy("mLock")
+        public boolean writeLocked(TypedXmlSerializer out) {
+            try {
+                out.startTag(null, TAG_OBSERVER);
+                out.attribute(null, ATTR_NAME, name);
+                if (Flags.recoverabilityDetection()) {
+                    out.attributeInt(null, ATTR_MITIGATION_COUNT, mMitigationCount);
+                }
+                for (int i = 0; i < mPackages.size(); i++) {
+                    MonitoredPackage p = mPackages.valueAt(i);
+                    p.writeLocked(out);
+                }
+                out.endTag(null, TAG_OBSERVER);
+                return true;
+            } catch (IOException e) {
+                Slog.w(TAG, "Cannot save observer", e);
+                return false;
+            }
+        }
+
+        public int getBootMitigationCount() {
+            return mMitigationCount;
+        }
+
+        public void setBootMitigationCount(int mitigationCount) {
+            mMitigationCount = mitigationCount;
+        }
+
+        @GuardedBy("mLock")
+        public void updatePackagesLocked(List<MonitoredPackage> packages) {
+            for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
+                MonitoredPackage p = packages.get(pIndex);
+                MonitoredPackage existingPackage = getMonitoredPackage(p.getName());
+                if (existingPackage != null) {
+                    existingPackage.updateHealthCheckDuration(p.mDurationMs);
+                } else {
+                    putMonitoredPackage(p);
+                }
+            }
+        }
+
+        /**
+         * Reduces the monitoring durations of all packages observed by this observer by
+         * {@code elapsedMs}. If any duration is less than 0, the package is removed from
+         * observation. If any health check duration is less than 0, the health check result
+         * is evaluated.
+         *
+         * @return a {@link Set} of packages that were removed from the observer without explicit
+         * health check passing, or an empty list if no package expired for which an explicit health
+         * check was still pending
+         */
+        @GuardedBy("mLock")
+        private Set<MonitoredPackage> prunePackagesLocked(long elapsedMs) {
+            Set<MonitoredPackage> failedPackages = new ArraySet<>();
+            Iterator<MonitoredPackage> it = mPackages.values().iterator();
+            while (it.hasNext()) {
+                MonitoredPackage p = it.next();
+                int oldState = p.getHealthCheckStateLocked();
+                int newState = p.handleElapsedTimeLocked(elapsedMs);
+                if (oldState != HealthCheckState.FAILED
+                        && newState == HealthCheckState.FAILED) {
+                    Slog.i(TAG, "Package " + p.getName() + " failed health check");
+                    failedPackages.add(p);
+                }
+                if (p.isExpiredLocked()) {
+                    it.remove();
+                }
+            }
+            return failedPackages;
+        }
+
+        /**
+         * Increments failure counts of {@code packageName}.
+         * @returns {@code true} if failure threshold is exceeded, {@code false} otherwise
+         */
+        @GuardedBy("mLock")
+        public boolean onPackageFailureLocked(String packageName) {
+            if (getMonitoredPackage(packageName) == null && registeredObserver.isPersistent()
+                    && registeredObserver.mayObservePackage(packageName)) {
+                putMonitoredPackage(sPackageWatchdog.newMonitoredPackage(
+                        packageName, DEFAULT_OBSERVING_DURATION_MS, false));
+            }
+            MonitoredPackage p = getMonitoredPackage(packageName);
+            if (p != null) {
+                return p.onFailureLocked();
+            }
+            return false;
+        }
+
+        /**
+         * Returns the map of packages monitored by this observer.
+         *
+         * @return a mapping of package names to {@link MonitoredPackage} objects.
+         */
+        @GuardedBy("mLock")
+        public ArrayMap<String, MonitoredPackage> getMonitoredPackages() {
+            return mPackages;
+        }
+
+        /**
+         * Returns the {@link MonitoredPackage} associated with a given package name if the
+         * package is being monitored by this observer.
+         *
+         * @param packageName: the name of the package.
+         * @return the {@link MonitoredPackage} object associated with the package name if one
+         *         exists, {@code null} otherwise.
+         */
+        @GuardedBy("mLock")
+        @Nullable
+        public MonitoredPackage getMonitoredPackage(String packageName) {
+            return mPackages.get(packageName);
+        }
+
+        /**
+         * Associates a {@link MonitoredPackage} with the observer.
+         *
+         * @param p: the {@link MonitoredPackage} to store.
+         */
+        @GuardedBy("mLock")
+        public void putMonitoredPackage(MonitoredPackage p) {
+            mPackages.put(p.getName(), p);
+        }
+
+        /**
+         * Returns one ObserverInternal from the {@code parser} and advances its state.
+         *
+         * <p>Note that this method is <b>not</b> thread safe. It should only be called from
+         * #loadFromFile which in turn is only called on construction of the
+         * singleton PackageWatchdog.
+         **/
+        public static ObserverInternal read(TypedXmlPullParser parser, PackageWatchdog watchdog) {
+            String observerName = null;
+            int observerMitigationCount = 0;
+            if (TAG_OBSERVER.equals(parser.getName())) {
+                observerName = parser.getAttributeValue(null, ATTR_NAME);
+                if (TextUtils.isEmpty(observerName)) {
+                    Slog.wtf(TAG, "Unable to read observer name");
+                    return null;
+                }
+            }
+            List<MonitoredPackage> packages = new ArrayList<>();
+            int innerDepth = parser.getDepth();
+            try {
+                if (Flags.recoverabilityDetection()) {
+                    observerMitigationCount = parser.getAttributeInt(null, ATTR_MITIGATION_COUNT);
+                }
+                while (XmlUtils.nextElementWithin(parser, innerDepth)) {
+                    if (TAG_PACKAGE.equals(parser.getName())) {
+                        try {
+                            MonitoredPackage pkg = watchdog.parseMonitoredPackage(parser);
+                            if (pkg != null) {
+                                packages.add(pkg);
+                            }
+                        } catch (NumberFormatException e) {
+                            Slog.wtf(TAG, "Skipping package for observer " + observerName, e);
+                            continue;
+                        }
+                    }
+                }
+            } catch (XmlPullParserException | IOException e) {
+                Slog.wtf(TAG, "Unable to read observer " + observerName, e);
+                return null;
+            }
+            if (packages.isEmpty()) {
+                return null;
+            }
+            return new ObserverInternal(observerName, packages, observerMitigationCount);
+        }
+
+        /** Dumps information about this observer and the packages it watches. */
+        public void dump(IndentingPrintWriter pw) {
+            boolean isPersistent = registeredObserver != null && registeredObserver.isPersistent();
+            pw.println("Persistent: " + isPersistent);
+            for (String packageName : mPackages.keySet()) {
+                MonitoredPackage p = getMonitoredPackage(packageName);
+                pw.println(packageName +  ": ");
+                pw.increaseIndent();
+                pw.println("# Failures: " + p.mFailureHistory.size());
+                pw.println("Monitoring duration remaining: " + p.mDurationMs + "ms");
+                pw.println("Explicit health check duration: " + p.mHealthCheckDurationMs + "ms");
+                pw.println("Health check state: " + p.toString(p.mHealthCheckState));
+                pw.decreaseIndent();
+            }
+        }
+    }
+
+    @Retention(SOURCE)
+    @IntDef(value = {
+            HealthCheckState.ACTIVE,
+            HealthCheckState.INACTIVE,
+            HealthCheckState.PASSED,
+            HealthCheckState.FAILED})
+    public @interface HealthCheckState {
+        // The package has not passed health check but has requested a health check
+        int ACTIVE = 0;
+        // The package has not passed health check and has not requested a health check
+        int INACTIVE = 1;
+        // The package has passed health check
+        int PASSED = 2;
+        // The package has failed health check
+        int FAILED = 3;
+    }
+
+    MonitoredPackage newMonitoredPackage(
+            String name, long durationMs, boolean hasPassedHealthCheck) {
+        return newMonitoredPackage(name, durationMs, Long.MAX_VALUE, hasPassedHealthCheck,
+                new LongArrayQueue());
+    }
+
+    MonitoredPackage newMonitoredPackage(String name, long durationMs, long healthCheckDurationMs,
+            boolean hasPassedHealthCheck, LongArrayQueue mitigationCalls) {
+        return new MonitoredPackage(name, durationMs, healthCheckDurationMs,
+                hasPassedHealthCheck, mitigationCalls);
+    }
+
+    MonitoredPackage parseMonitoredPackage(TypedXmlPullParser parser)
+            throws XmlPullParserException {
+        String packageName = parser.getAttributeValue(null, ATTR_NAME);
+        long duration = parser.getAttributeLong(null, ATTR_DURATION);
+        long healthCheckDuration = parser.getAttributeLong(null,
+                        ATTR_EXPLICIT_HEALTH_CHECK_DURATION);
+        boolean hasPassedHealthCheck = parser.getAttributeBoolean(null, ATTR_PASSED_HEALTH_CHECK);
+        LongArrayQueue mitigationCalls = parseLongArrayQueue(
+                parser.getAttributeValue(null, ATTR_MITIGATION_CALLS));
+        return newMonitoredPackage(packageName,
+                duration, healthCheckDuration, hasPassedHealthCheck, mitigationCalls);
+    }
+
+    /**
+     * Represents a package and its health check state along with the time
+     * it should be monitored for.
+     *
+     * <p> Note, the PackageWatchdog#mLock must always be held when reading or writing
+     * instances of this class.
+     */
+    class MonitoredPackage {
+        private final String mPackageName;
+        // Times when package failures happen sorted in ascending order
+        @GuardedBy("mLock")
+        private final LongArrayQueue mFailureHistory = new LongArrayQueue();
+        // Times when an observer was called to mitigate this package's failure. Sorted in
+        // ascending order.
+        @GuardedBy("mLock")
+        private final LongArrayQueue mMitigationCalls;
+        // One of STATE_[ACTIVE|INACTIVE|PASSED|FAILED]. Updated on construction and after
+        // methods that could change the health check state: handleElapsedTimeLocked and
+        // tryPassHealthCheckLocked
+        private int mHealthCheckState = HealthCheckState.INACTIVE;
+        // Whether an explicit health check has passed.
+        // This value in addition with mHealthCheckDurationMs determines the health check state
+        // of the package, see #getHealthCheckStateLocked
+        @GuardedBy("mLock")
+        private boolean mHasPassedHealthCheck;
+        // System uptime duration to monitor package.
+        @GuardedBy("mLock")
+        private long mDurationMs;
+        // System uptime duration to check the result of an explicit health check
+        // Initially, MAX_VALUE until we get a value from the health check service
+        // and request health checks.
+        // This value in addition with mHasPassedHealthCheck determines the health check state
+        // of the package, see #getHealthCheckStateLocked
+        @GuardedBy("mLock")
+        private long mHealthCheckDurationMs = Long.MAX_VALUE;
+
+        MonitoredPackage(String packageName, long durationMs,
+                long healthCheckDurationMs, boolean hasPassedHealthCheck,
+                LongArrayQueue mitigationCalls) {
+            mPackageName = packageName;
+            mDurationMs = durationMs;
+            mHealthCheckDurationMs = healthCheckDurationMs;
+            mHasPassedHealthCheck = hasPassedHealthCheck;
+            mMitigationCalls = mitigationCalls;
+            updateHealthCheckStateLocked();
+        }
+
+        /** Writes the salient fields to disk using {@code out}. */
+        @GuardedBy("mLock")
+        public void writeLocked(TypedXmlSerializer out) throws IOException {
+            out.startTag(null, TAG_PACKAGE);
+            out.attribute(null, ATTR_NAME, getName());
+            out.attributeLong(null, ATTR_DURATION, mDurationMs);
+            out.attributeLong(null, ATTR_EXPLICIT_HEALTH_CHECK_DURATION, mHealthCheckDurationMs);
+            out.attributeBoolean(null, ATTR_PASSED_HEALTH_CHECK, mHasPassedHealthCheck);
+            LongArrayQueue normalizedCalls = normalizeMitigationCalls();
+            out.attribute(null, ATTR_MITIGATION_CALLS, longArrayQueueToString(normalizedCalls));
+            out.endTag(null, TAG_PACKAGE);
+        }
+
+        /**
+         * Increment package failures or resets failure count depending on the last package failure.
+         *
+         * @return {@code true} if failure count exceeds a threshold, {@code false} otherwise
+         */
+        @GuardedBy("mLock")
+        public boolean onFailureLocked() {
+            // Sliding window algorithm: find out if there exists a window containing failures >=
+            // mTriggerFailureCount.
+            final long now = mSystemClock.uptimeMillis();
+            mFailureHistory.addLast(now);
+            while (now - mFailureHistory.peekFirst() > mTriggerFailureDurationMs) {
+                // Prune values falling out of the window
+                mFailureHistory.removeFirst();
+            }
+            boolean failed = mFailureHistory.size() >= mTriggerFailureCount;
+            if (failed) {
+                mFailureHistory.clear();
+            }
+            return failed;
+        }
+
+        /**
+         * Notes the timestamp of a mitigation call into the observer.
+         */
+        @GuardedBy("mLock")
+        public void noteMitigationCallLocked() {
+            mMitigationCalls.addLast(mSystemClock.uptimeMillis());
+        }
+
+        /**
+         * Prunes any mitigation calls outside of the de-escalation window, and returns the
+         * number of calls that are in the window afterwards.
+         *
+         * @return the number of mitigation calls made in the de-escalation window.
+         */
+        @GuardedBy("mLock")
+        public int getMitigationCountLocked() {
+            try {
+                final long now = mSystemClock.uptimeMillis();
+                while (now - mMitigationCalls.peekFirst() > DEFAULT_DEESCALATION_WINDOW_MS) {
+                    mMitigationCalls.removeFirst();
+                }
+            } catch (NoSuchElementException ignore) {
+            }
+
+            return mMitigationCalls.size();
+        }
+
+        /**
+         * Before writing to disk, make the mitigation call timestamps relative to the current
+         * system uptime. This is because they need to be relative to the uptime which will reset
+         * at the next boot.
+         *
+         * @return a LongArrayQueue of the mitigation calls relative to the current system uptime.
+         */
+        @GuardedBy("mLock")
+        public LongArrayQueue normalizeMitigationCalls() {
+            LongArrayQueue normalized = new LongArrayQueue();
+            final long now = mSystemClock.uptimeMillis();
+            for (int i = 0; i < mMitigationCalls.size(); i++) {
+                normalized.addLast(mMitigationCalls.get(i) - now);
+            }
+            return normalized;
+        }
+
+        /**
+         * Sets the initial health check duration.
+         *
+         * @return the new health check state
+         */
+        @GuardedBy("mLock")
+        public int setHealthCheckActiveLocked(long initialHealthCheckDurationMs) {
+            if (initialHealthCheckDurationMs <= 0) {
+                Slog.wtf(TAG, "Cannot set non-positive health check duration "
+                        + initialHealthCheckDurationMs + "ms for package " + getName()
+                        + ". Using total duration " + mDurationMs + "ms instead");
+                initialHealthCheckDurationMs = mDurationMs;
+            }
+            if (mHealthCheckState == HealthCheckState.INACTIVE) {
+                // Transitions to ACTIVE
+                mHealthCheckDurationMs = initialHealthCheckDurationMs;
+            }
+            return updateHealthCheckStateLocked();
+        }
+
+        /**
+         * Updates the monitoring durations of the package.
+         *
+         * @return the new health check state
+         */
+        @GuardedBy("mLock")
+        public int handleElapsedTimeLocked(long elapsedMs) {
+            if (elapsedMs <= 0) {
+                Slog.w(TAG, "Cannot handle non-positive elapsed time for package " + getName());
+                return mHealthCheckState;
+            }
+            // Transitions to FAILED if now <= 0 and health check not passed
+            mDurationMs -= elapsedMs;
+            if (mHealthCheckState == HealthCheckState.ACTIVE) {
+                // We only update health check durations if we have #setHealthCheckActiveLocked
+                // This ensures we don't leave the INACTIVE state for an unexpected elapsed time
+                // Transitions to FAILED if now <= 0 and health check not passed
+                mHealthCheckDurationMs -= elapsedMs;
+            }
+            return updateHealthCheckStateLocked();
+        }
+
+        /** Explicitly update the monitoring duration of the package. */
+        @GuardedBy("mLock")
+        public void updateHealthCheckDuration(long newDurationMs) {
+            mDurationMs = newDurationMs;
+        }
+
+        /**
+         * Marks the health check as passed and transitions to {@link HealthCheckState.PASSED}
+         * if not yet {@link HealthCheckState.FAILED}.
+         *
+         * @return the new {@link HealthCheckState health check state}
+         */
+        @GuardedBy("mLock")
+        @HealthCheckState
+        public int tryPassHealthCheckLocked() {
+            if (mHealthCheckState != HealthCheckState.FAILED) {
+                // FAILED is a final state so only pass if we haven't failed
+                // Transition to PASSED
+                mHasPassedHealthCheck = true;
+            }
+            return updateHealthCheckStateLocked();
+        }
+
+        /** Returns the monitored package name. */
+        private String getName() {
+            return mPackageName;
+        }
+
+        /**
+         * Returns the current {@link HealthCheckState health check state}.
+         */
+        @GuardedBy("mLock")
+        @HealthCheckState
+        public int getHealthCheckStateLocked() {
+            return mHealthCheckState;
+        }
+
+        /**
+         * Returns the shortest duration before the package should be scheduled for a prune.
+         *
+         * @return the duration or {@link Long#MAX_VALUE} if the package should not be scheduled
+         */
+        @GuardedBy("mLock")
+        public long getShortestScheduleDurationMsLocked() {
+            // Consider health check duration only if #isPendingHealthChecksLocked is true
+            return Math.min(toPositive(mDurationMs),
+                    isPendingHealthChecksLocked()
+                    ? toPositive(mHealthCheckDurationMs) : Long.MAX_VALUE);
+        }
+
+        /**
+         * Returns {@code true} if the total duration left to monitor the package is less than or
+         * equal to 0 {@code false} otherwise.
+         */
+        @GuardedBy("mLock")
+        public boolean isExpiredLocked() {
+            return mDurationMs <= 0;
+        }
+
+        /**
+         * Returns {@code true} if the package, {@link #getName} is expecting health check results
+         * {@code false} otherwise.
+         */
+        @GuardedBy("mLock")
+        public boolean isPendingHealthChecksLocked() {
+            return mHealthCheckState == HealthCheckState.ACTIVE
+                    || mHealthCheckState == HealthCheckState.INACTIVE;
+        }
+
+        /**
+         * Updates the health check state based on {@link #mHasPassedHealthCheck}
+         * and {@link #mHealthCheckDurationMs}.
+         *
+         * @return the new {@link HealthCheckState health check state}
+         */
+        @GuardedBy("mLock")
+        @HealthCheckState
+        private int updateHealthCheckStateLocked() {
+            int oldState = mHealthCheckState;
+            if (mHasPassedHealthCheck) {
+                // Set final state first to avoid ambiguity
+                mHealthCheckState = HealthCheckState.PASSED;
+            } else if (mHealthCheckDurationMs <= 0 || mDurationMs <= 0) {
+                // Set final state first to avoid ambiguity
+                mHealthCheckState = HealthCheckState.FAILED;
+            } else if (mHealthCheckDurationMs == Long.MAX_VALUE) {
+                mHealthCheckState = HealthCheckState.INACTIVE;
+            } else {
+                mHealthCheckState = HealthCheckState.ACTIVE;
+            }
+
+            if (oldState != mHealthCheckState) {
+                Slog.i(TAG, "Updated health check state for package " + getName() + ": "
+                        + toString(oldState) + " -> " + toString(mHealthCheckState));
+            }
+            return mHealthCheckState;
+        }
+
+        /** Returns a {@link String} representation of the current health check state. */
+        private String toString(@HealthCheckState int state) {
+            switch (state) {
+                case HealthCheckState.ACTIVE:
+                    return "ACTIVE";
+                case HealthCheckState.INACTIVE:
+                    return "INACTIVE";
+                case HealthCheckState.PASSED:
+                    return "PASSED";
+                case HealthCheckState.FAILED:
+                    return "FAILED";
+                default:
+                    return "UNKNOWN";
+            }
+        }
+
+        /** Returns {@code value} if it is greater than 0 or {@link Long#MAX_VALUE} otherwise. */
+        private long toPositive(long value) {
+            return value > 0 ? value : Long.MAX_VALUE;
+        }
+
+        /** Compares the equality of this object with another {@link MonitoredPackage}. */
+        @VisibleForTesting
+        boolean isEqualTo(MonitoredPackage pkg) {
+            return (getName().equals(pkg.getName()))
+                    && mDurationMs == pkg.mDurationMs
+                    && mHasPassedHealthCheck == pkg.mHasPassedHealthCheck
+                    && mHealthCheckDurationMs == pkg.mHealthCheckDurationMs
+                    && (mMitigationCalls.toString()).equals(pkg.mMitigationCalls.toString());
+        }
+    }
+
+    @GuardedBy("mLock")
+    @SuppressWarnings("GuardedBy")
+    void saveAllObserversBootMitigationCountToMetadata(String filePath) {
+        HashMap<String, Integer> bootMitigationCounts = new HashMap<>();
+        for (int i = 0; i < mAllObservers.size(); i++) {
+            final ObserverInternal observer = mAllObservers.valueAt(i);
+            bootMitigationCounts.put(observer.name, observer.getBootMitigationCount());
+        }
+
+        try {
+            FileOutputStream fileStream = new FileOutputStream(new File(filePath));
+            ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
+            objectStream.writeObject(bootMitigationCounts);
+            objectStream.flush();
+            objectStream.close();
+            fileStream.close();
+        } catch (Exception e) {
+            Slog.i(TAG, "Could not save observers metadata to file: " + e);
+        }
+    }
+
+    /**
+     * Handles the thresholding logic for system server boots.
+     */
+    class BootThreshold {
+
+        private final int mBootTriggerCount;
+        private final long mTriggerWindow;
+
+        BootThreshold(int bootTriggerCount, long triggerWindow) {
+            this.mBootTriggerCount = bootTriggerCount;
+            this.mTriggerWindow = triggerWindow;
+        }
+
+        public void reset() {
+            setStart(0);
+            setCount(0);
+        }
+
+        protected int getCount() {
+            return CrashRecoveryProperties.rescueBootCount().orElse(0);
+        }
+
+        protected void setCount(int count) {
+            CrashRecoveryProperties.rescueBootCount(count);
+        }
+
+        public long getStart() {
+            return CrashRecoveryProperties.rescueBootStart().orElse(0L);
+        }
+
+        public int getMitigationCount() {
+            return CrashRecoveryProperties.bootMitigationCount().orElse(0);
+        }
+
+        public void setStart(long start) {
+            CrashRecoveryProperties.rescueBootStart(getStartTime(start));
+        }
+
+        public void setMitigationStart(long start) {
+            CrashRecoveryProperties.bootMitigationStart(getStartTime(start));
+        }
+
+        public long getMitigationStart() {
+            return CrashRecoveryProperties.bootMitigationStart().orElse(0L);
+        }
+
+        public void setMitigationCount(int count) {
+            CrashRecoveryProperties.bootMitigationCount(count);
+        }
+
+        private static long constrain(long amount, long low, long high) {
+            return amount < low ? low : (amount > high ? high : amount);
+        }
+
+        public long getStartTime(long start) {
+            final long now = mSystemClock.uptimeMillis();
+            return constrain(start, 0, now);
+        }
+
+        public void saveMitigationCountToMetadata() {
+            try (BufferedWriter writer = new BufferedWriter(new FileWriter(METADATA_FILE))) {
+                writer.write(String.valueOf(getMitigationCount()));
+            } catch (Exception e) {
+                Slog.e(TAG, "Could not save metadata to file: " + e);
+            }
+        }
+
+        public void readMitigationCountFromMetadataIfNecessary() {
+            File bootPropsFile = new File(METADATA_FILE);
+            if (bootPropsFile.exists()) {
+                try (BufferedReader reader = new BufferedReader(new FileReader(METADATA_FILE))) {
+                    String mitigationCount = reader.readLine();
+                    setMitigationCount(Integer.parseInt(mitigationCount));
+                    bootPropsFile.delete();
+                } catch (Exception e) {
+                    Slog.i(TAG, "Could not read metadata file: " + e);
+                }
+            }
+        }
+
+
+        /** Increments the boot counter, and returns whether the device is bootlooping. */
+        @GuardedBy("mLock")
+        public boolean incrementAndTest() {
+            if (Flags.recoverabilityDetection()) {
+                readAllObserversBootMitigationCountIfNecessary(METADATA_FILE);
+            } else {
+                readMitigationCountFromMetadataIfNecessary();
+            }
+
+            final long now = mSystemClock.uptimeMillis();
+            if (now - getStart() < 0) {
+                Slog.e(TAG, "Window was less than zero. Resetting start to current time.");
+                setStart(now);
+                setMitigationStart(now);
+            }
+            if (now - getMitigationStart() > DEFAULT_DEESCALATION_WINDOW_MS) {
+                setMitigationStart(now);
+                if (Flags.recoverabilityDetection()) {
+                    resetAllObserversBootMitigationCount();
+                } else {
+                    setMitigationCount(0);
+                }
+            }
+            final long window = now - getStart();
+            if (window >= mTriggerWindow) {
+                setCount(1);
+                setStart(now);
+                return false;
+            } else {
+                int count = getCount() + 1;
+                setCount(count);
+                EventLogTags.writeRescueNote(Process.ROOT_UID, count, window);
+                if (Flags.recoverabilityDetection()) {
+                    // After a reboot (e.g. by WARM_REBOOT or mainline rollback) we apply
+                    // mitigations without waiting for DEFAULT_BOOT_LOOP_TRIGGER_COUNT.
+                    return (count >= mBootTriggerCount)
+                            || (performedMitigationsDuringWindow() && count > 1);
+                }
+                return count >= mBootTriggerCount;
+            }
+        }
+
+        @GuardedBy("mLock")
+        private boolean performedMitigationsDuringWindow() {
+            for (ObserverInternal observerInternal: mAllObservers.values()) {
+                if (observerInternal.getBootMitigationCount() > 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @GuardedBy("mLock")
+        private void resetAllObserversBootMitigationCount() {
+            for (int i = 0; i < mAllObservers.size(); i++) {
+                final ObserverInternal observer = mAllObservers.valueAt(i);
+                observer.setBootMitigationCount(0);
+            }
+            saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
+        }
+
+        @GuardedBy("mLock")
+        @SuppressWarnings("GuardedBy")
+        void readAllObserversBootMitigationCountIfNecessary(String filePath) {
+            File metadataFile = new File(filePath);
+            if (metadataFile.exists()) {
+                try {
+                    FileInputStream fileStream = new FileInputStream(metadataFile);
+                    ObjectInputStream objectStream = new ObjectInputStream(fileStream);
+                    HashMap<String, Integer> bootMitigationCounts =
+                            (HashMap<String, Integer>) objectStream.readObject();
+                    objectStream.close();
+                    fileStream.close();
+
+                    for (int i = 0; i < mAllObservers.size(); i++) {
+                        final ObserverInternal observer = mAllObservers.valueAt(i);
+                        if (bootMitigationCounts.containsKey(observer.name)) {
+                            observer.setBootMitigationCount(
+                                    bootMitigationCounts.get(observer.name));
+                        }
+                    }
+                } catch (Exception e) {
+                    Slog.i(TAG, "Could not read observer metadata file: " + e);
+                }
+            }
+        }
+
+    }
+}
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
new file mode 100644
index 0000000..37c2d26
--- /dev/null
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -0,0 +1,1068 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static android.provider.DeviceConfig.Properties;
+
+import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.crashrecovery.flags.Flags;
+import android.os.Build;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.PowerManager;
+import android.os.RecoverySystem;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.sysprop.CrashRecoveryProperties;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.PackageWatchdog.FailureReasons;
+import com.android.server.PackageWatchdog.PackageHealthObserver;
+import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
+import com.android.server.am.SettingsToPropertiesMapper;
+import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
+
+import java.io.File;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Utilities to help rescue the system from crash loops. Callers are expected to
+ * report boot events and persistent app crashes, and if they happen frequently
+ * enough this class will slowly escalate through several rescue operations
+ * before finally rebooting and prompting the user if they want to wipe data as
+ * a last resort.
+ *
+ * @hide
+ */
+public class RescueParty {
+    @VisibleForTesting
+    static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
+    @VisibleForTesting
+    static final int LEVEL_NONE = 0;
+    @VisibleForTesting
+    static final int LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 1;
+    @VisibleForTesting
+    static final int LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 2;
+    @VisibleForTesting
+    static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
+    @VisibleForTesting
+    static final int LEVEL_WARM_REBOOT = 4;
+    @VisibleForTesting
+    static final int LEVEL_FACTORY_RESET = 5;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_NONE = 0;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET = 1;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET = 2;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_WARM_REBOOT = 3;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 4;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 5;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 6;
+    @VisibleForTesting
+    static final int RESCUE_LEVEL_FACTORY_RESET = 7;
+
+    @IntDef(prefix = { "RESCUE_LEVEL_" }, value = {
+        RESCUE_LEVEL_NONE,
+        RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET,
+        RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET,
+        RESCUE_LEVEL_WARM_REBOOT,
+        RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+        RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
+        RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
+        RESCUE_LEVEL_FACTORY_RESET
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface RescueLevels {}
+
+    @VisibleForTesting
+    static final String RESCUE_NON_REBOOT_LEVEL_LIMIT = "persist.sys.rescue_non_reboot_level_limit";
+    @VisibleForTesting
+    static final int DEFAULT_RESCUE_NON_REBOOT_LEVEL_LIMIT = RESCUE_LEVEL_WARM_REBOOT - 1;
+    @VisibleForTesting
+    static final String TAG = "RescueParty";
+    @VisibleForTesting
+    static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2);
+    @VisibleForTesting
+    static final int DEVICE_CONFIG_RESET_MODE = Settings.RESET_MODE_TRUSTED_DEFAULTS;
+    // The DeviceConfig namespace containing all RescueParty switches.
+    @VisibleForTesting
+    static final String NAMESPACE_CONFIGURATION = "configuration";
+    @VisibleForTesting
+    static final String NAMESPACE_TO_PACKAGE_MAPPING_FLAG =
+            "namespace_to_package_mapping";
+    @VisibleForTesting
+    static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 1440;
+
+    private static final String NAME = "rescue-party-observer";
+
+    private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
+    private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device";
+    private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
+            "persist.device_config.configuration.disable_rescue_party";
+    private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
+            "persist.device_config.configuration.disable_rescue_party_factory_reset";
+    private static final String PROP_THROTTLE_DURATION_MIN_FLAG =
+            "persist.device_config.configuration.rescue_party_throttle_duration_min";
+
+    private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
+            | ApplicationInfo.FLAG_SYSTEM;
+
+    /** Register the Rescue Party observer as a Package Watchdog health observer */
+    public static void registerHealthObserver(Context context) {
+        PackageWatchdog.getInstance(context).registerHealthObserver(
+                RescuePartyObserver.getInstance(context));
+    }
+
+    private static boolean isDisabled() {
+        // Check if we're explicitly enabled for testing
+        if (SystemProperties.getBoolean(PROP_ENABLE_RESCUE, false)) {
+            return false;
+        }
+
+        // We're disabled if the DeviceConfig disable flag is set to true.
+        // This is in case that an emergency rollback of the feature is needed.
+        if (SystemProperties.getBoolean(PROP_DEVICE_CONFIG_DISABLE_FLAG, false)) {
+            Slog.v(TAG, "Disabled because of DeviceConfig flag");
+            return true;
+        }
+
+        // We're disabled on all engineering devices
+        if (Build.TYPE.equals("eng")) {
+            Slog.v(TAG, "Disabled because of eng build");
+            return true;
+        }
+
+        // We're disabled on userdebug devices connected over USB, since that's
+        // a decent signal that someone is actively trying to debug the device,
+        // or that it's in a lab environment.
+        if (Build.TYPE.equals("userdebug") && isUsbActive()) {
+            Slog.v(TAG, "Disabled because of active USB connection");
+            return true;
+        }
+
+        // One last-ditch check
+        if (SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false)) {
+            Slog.v(TAG, "Disabled because of manual property");
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if we're currently attempting to reboot for a factory reset. This method must
+     * return true if RescueParty tries to reboot early during a boot loop, since the device
+     * will not be fully booted at this time.
+     */
+    public static boolean isRecoveryTriggeredReboot() {
+        return isFactoryResetPropertySet() || isRebootPropertySet();
+    }
+
+    static boolean isFactoryResetPropertySet() {
+        return CrashRecoveryProperties.attemptingFactoryReset().orElse(false);
+    }
+
+    static boolean isRebootPropertySet() {
+        return CrashRecoveryProperties.attemptingReboot().orElse(false);
+    }
+
+    protected static long getLastFactoryResetTimeMs() {
+        return CrashRecoveryProperties.lastFactoryResetTimeMs().orElse(0L);
+    }
+
+    protected static int getMaxRescueLevelAttempted() {
+        return CrashRecoveryProperties.maxRescueLevelAttempted().orElse(LEVEL_NONE);
+    }
+
+    protected static void setFactoryResetProperty(boolean value) {
+        CrashRecoveryProperties.attemptingFactoryReset(value);
+    }
+    protected static void setRebootProperty(boolean value) {
+        CrashRecoveryProperties.attemptingReboot(value);
+    }
+
+    protected static void setLastFactoryResetTimeMs(long value) {
+        CrashRecoveryProperties.lastFactoryResetTimeMs(value);
+    }
+
+    protected static void setMaxRescueLevelAttempted(int level) {
+        CrashRecoveryProperties.maxRescueLevelAttempted(level);
+    }
+
+    /**
+     * Called when {@code SettingsProvider} has been published, which is a good
+     * opportunity to reset any settings depending on our rescue level.
+     */
+    public static void onSettingsProviderPublished(Context context) {
+        handleNativeRescuePartyResets();
+        ContentResolver contentResolver = context.getContentResolver();
+        DeviceConfig.setMonitorCallback(
+                contentResolver,
+                Executors.newSingleThreadExecutor(),
+                new RescuePartyMonitorCallback(context));
+    }
+
+
+    /**
+     * Called when {@code RollbackManager} performs Mainline module rollbacks,
+     * to avoid rolled back modules consuming flag values only expected to work
+     * on modules of newer versions.
+     */
+    public static void resetDeviceConfigForPackages(List<String> packageNames) {
+        if (packageNames == null) {
+            return;
+        }
+        Set<String> namespacesToReset = new ArraySet<String>();
+        Iterator<String> it = packageNames.iterator();
+        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated();
+        // Get runtime package to namespace mapping if created.
+        if (rescuePartyObserver != null) {
+            while (it.hasNext()) {
+                String packageName = it.next();
+                Set<String> runtimeAffectedNamespaces =
+                        rescuePartyObserver.getAffectedNamespaceSet(packageName);
+                if (runtimeAffectedNamespaces != null) {
+                    namespacesToReset.addAll(runtimeAffectedNamespaces);
+                }
+            }
+        }
+        // Get preset package to namespace mapping if created.
+        Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages(
+                packageNames);
+        if (presetAffectedNamespaces != null) {
+            namespacesToReset.addAll(presetAffectedNamespaces);
+        }
+
+        // Clear flags under the namespaces mapped to these packages.
+        // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set.
+        Iterator<String> namespaceIt = namespacesToReset.iterator();
+        while (namespaceIt.hasNext()) {
+            String namespaceToReset = namespaceIt.next();
+            Properties properties = new Properties.Builder(namespaceToReset).build();
+            try {
+                if (!DeviceConfig.setProperties(properties)) {
+                    logCriticalInfo(Log.ERROR, "Failed to clear properties under "
+                            + namespaceToReset
+                            + ". Running `device_config get_sync_disabled_for_tests` will confirm"
+                            + " if config-bulk-update is enabled.");
+                }
+            } catch (DeviceConfig.BadConfigException exception) {
+                logCriticalInfo(Log.WARN, "namespace " + namespaceToReset
+                        + " is already banned, skip reset.");
+            }
+        }
+    }
+
+    private static Set<String> getPresetNamespacesForPackages(List<String> packageNames) {
+        Set<String> resultSet = new ArraySet<String>();
+        try {
+            String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION,
+                    NAMESPACE_TO_PACKAGE_MAPPING_FLAG, "");
+            String[] mappingEntries = flagVal.split(",");
+            for (int i = 0; i < mappingEntries.length; i++) {
+                if (TextUtils.isEmpty(mappingEntries[i])) {
+                    continue;
+                }
+                String[] splittedEntry = mappingEntries[i].split(":");
+                if (splittedEntry.length != 2) {
+                    throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]);
+                }
+                String namespace = splittedEntry[0];
+                String packageName = splittedEntry[1];
+
+                if (packageNames.contains(packageName)) {
+                    resultSet.add(namespace);
+                }
+            }
+        } catch (Exception e) {
+            resultSet.clear();
+            Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e);
+        } finally {
+            return resultSet;
+        }
+    }
+
+    @VisibleForTesting
+    static long getElapsedRealtime() {
+        return SystemClock.elapsedRealtime();
+    }
+
+    private static class RescuePartyMonitorCallback implements DeviceConfig.MonitorCallback {
+        Context mContext;
+
+        RescuePartyMonitorCallback(Context context) {
+            this.mContext = context;
+        }
+
+        public void onNamespaceUpdate(@NonNull String updatedNamespace) {
+            startObservingPackages(mContext, updatedNamespace);
+        }
+
+        public void onDeviceConfigAccess(@NonNull String callingPackage,
+                @NonNull String namespace) {
+            RescuePartyObserver.getInstance(mContext).recordDeviceConfigAccess(
+                            callingPackage,
+                            namespace);
+        }
+    }
+
+    private static void startObservingPackages(Context context, @NonNull String updatedNamespace) {
+        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+        Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet(updatedNamespace);
+        if (callingPackages == null) {
+            return;
+        }
+        List<String> callingPackageList = new ArrayList<>();
+        callingPackageList.addAll(callingPackages);
+        Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
+                + updatedNamespace);
+        PackageWatchdog.getInstance(context).startObservingHealth(
+                rescuePartyObserver,
+                callingPackageList,
+                DEFAULT_OBSERVING_DURATION_MS);
+    }
+
+    private static void handleNativeRescuePartyResets() {
+        if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
+            String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories();
+            for (int i = 0; i < resetNativeCategories.length; i++) {
+                // Don't let RescueParty reset the namespace for RescueParty switches.
+                if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) {
+                    continue;
+                }
+                DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE,
+                        resetNativeCategories[i]);
+            }
+        }
+    }
+
+    private static int getMaxRescueLevel(boolean mayPerformReboot) {
+        if (Flags.recoverabilityDetection()) {
+            if (!mayPerformReboot
+                    || SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
+                return SystemProperties.getInt(RESCUE_NON_REBOOT_LEVEL_LIMIT,
+                        DEFAULT_RESCUE_NON_REBOOT_LEVEL_LIMIT);
+            }
+            return RESCUE_LEVEL_FACTORY_RESET;
+        } else {
+            if (!mayPerformReboot
+                    || SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
+                return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
+            }
+            return LEVEL_FACTORY_RESET;
+        }
+    }
+
+    /**
+     * Get the rescue level to perform if this is the n-th attempt at mitigating failure.
+     *
+     * @param mitigationCount: the mitigation attempt number (1 = first attempt etc.)
+     * @param mayPerformReboot: whether or not a reboot and factory reset may be performed
+     *                          for the given failure.
+     * @return the rescue level for the n-th mitigation attempt.
+     */
+    private static int getRescueLevel(int mitigationCount, boolean mayPerformReboot) {
+        if (mitigationCount == 1) {
+            return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
+        } else if (mitigationCount == 2) {
+            return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES;
+        } else if (mitigationCount == 3) {
+            return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
+        } else if (mitigationCount == 4) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_WARM_REBOOT);
+        } else if (mitigationCount >= 5) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot), LEVEL_FACTORY_RESET);
+        } else {
+            Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
+            return LEVEL_NONE;
+        }
+    }
+
+    /**
+     * Get the rescue level to perform if this is the n-th attempt at mitigating failure.
+     * When failedPackage is null then 1st and 2nd mitigation counts are redundant (scoped and
+     * all device config reset). Behaves as if one mitigation attempt was already done.
+     *
+     * @param mitigationCount the mitigation attempt number (1 = first attempt etc.).
+     * @param mayPerformReboot whether or not a reboot and factory reset may be performed
+     * for the given failure.
+     * @param failedPackage in case of bootloop this is null.
+     * @return the rescue level for the n-th mitigation attempt.
+     */
+    private static @RescueLevels int getRescueLevel(int mitigationCount, boolean mayPerformReboot,
+            @Nullable VersionedPackage failedPackage) {
+        // Skipping RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET since it's not defined without a failed
+        // package.
+        if (failedPackage == null && mitigationCount > 0) {
+            mitigationCount += 1;
+        }
+        if (mitigationCount == 1) {
+            return RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET;
+        } else if (mitigationCount == 2) {
+            return RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET;
+        } else if (mitigationCount == 3) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_WARM_REBOOT);
+        } else if (mitigationCount == 4) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot),
+                                RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS);
+        } else if (mitigationCount == 5) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot),
+                                RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES);
+        } else if (mitigationCount == 6) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot),
+                                RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS);
+        } else if (mitigationCount >= 7) {
+            return Math.min(getMaxRescueLevel(mayPerformReboot), RESCUE_LEVEL_FACTORY_RESET);
+        } else {
+            return RESCUE_LEVEL_NONE;
+        }
+    }
+
+    private static void executeRescueLevel(Context context, @Nullable String failedPackage,
+            int level) {
+        Slog.w(TAG, "Attempting rescue level " + levelToString(level));
+        try {
+            executeRescueLevelInternal(context, level, failedPackage);
+            EventLogTags.writeRescueSuccess(level);
+            String successMsg = "Finished rescue level " + levelToString(level);
+            if (!TextUtils.isEmpty(failedPackage)) {
+                successMsg += " for package " + failedPackage;
+            }
+            logCriticalInfo(Log.DEBUG, successMsg);
+        } catch (Throwable t) {
+            logRescueException(level, failedPackage, t);
+        }
+    }
+
+    private static void executeRescueLevelInternal(Context context, int level, @Nullable
+            String failedPackage) throws Exception {
+        if (Flags.recoverabilityDetection()) {
+            executeRescueLevelInternalNew(context, level, failedPackage);
+        } else {
+            executeRescueLevelInternalOld(context, level, failedPackage);
+        }
+    }
+
+    private static void executeRescueLevelInternalOld(Context context, int level, @Nullable
+            String failedPackage) throws Exception {
+
+        // Note: DeviceConfig reset is disabled currently and would be enabled using the flag,
+        // after we have figured out a way to reset flags without interfering with trunk
+        // development. TODO: b/287618292 For enabling flag resets.
+        if (!Flags.allowRescuePartyFlagResets() && level <= LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS) {
+            return;
+        }
+
+        CrashRecoveryStatsLog.write(CrashRecoveryStatsLog.RESCUE_PARTY_RESET_REPORTED,
+                level, levelToString(level));
+        // Try our best to reset all settings possible, and once finished
+        // rethrow any exception that we encountered
+        Exception res = null;
+        switch (level) {
+            case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
+                try {
+                    resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS,
+                            level);
+                } catch (Exception e) {
+                    res = e;
+                }
+                try {
+                    resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
+                } catch (Exception e) {
+                    res = e;
+                }
+                break;
+            case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
+                try {
+                    resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES,
+                            level);
+                } catch (Exception e) {
+                    res = e;
+                }
+                try {
+                    resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
+                } catch (Exception e) {
+                    res = e;
+                }
+                break;
+            case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+                try {
+                    resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS,
+                            level);
+                } catch (Exception e) {
+                    res = e;
+                }
+                try {
+                    resetDeviceConfig(context, /*isScoped=*/false, failedPackage);
+                } catch (Exception e) {
+                    res = e;
+                }
+                break;
+            case LEVEL_WARM_REBOOT:
+                executeWarmReboot(context, level, failedPackage);
+                break;
+            case LEVEL_FACTORY_RESET:
+                // Before the completion of Reboot, if any crash happens then PackageWatchdog
+                // escalates to next level i.e. factory reset, as they happen in separate threads.
+                // Adding a check to prevent factory reset to execute before above reboot completes.
+                // Note: this reboot property is not persistent resets after reboot is completed.
+                if (isRebootPropertySet()) {
+                    return;
+                }
+                executeFactoryReset(context, level, failedPackage);
+                break;
+        }
+
+        if (res != null) {
+            throw res;
+        }
+    }
+
+    private static void executeRescueLevelInternalNew(Context context, @RescueLevels int level,
+            @Nullable String failedPackage) throws Exception {
+        CrashRecoveryStatsLog.write(CrashRecoveryStatsLog.RESCUE_PARTY_RESET_REPORTED,
+                level, levelToString(level));
+        switch (level) {
+            case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
+                // Enable deviceConfig reset behind flag
+                if (Flags.allowRescuePartyFlagResets()) {
+                    resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
+                }
+                break;
+            case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
+                // Enable deviceConfig reset behind flag
+                if (Flags.allowRescuePartyFlagResets()) {
+                    resetDeviceConfig(context, /*isScoped=*/false, failedPackage);
+                }
+                break;
+            case RESCUE_LEVEL_WARM_REBOOT:
+                executeWarmReboot(context, level, failedPackage);
+                break;
+            case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
+                resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS, level);
+                break;
+            case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
+                resetAllSettingsIfNecessary(context, Settings.RESET_MODE_UNTRUSTED_CHANGES, level);
+                break;
+            case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+                resetAllSettingsIfNecessary(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, level);
+                break;
+            case RESCUE_LEVEL_FACTORY_RESET:
+                // Before the completion of Reboot, if any crash happens then PackageWatchdog
+                // escalates to next level i.e. factory reset, as they happen in separate threads.
+                // Adding a check to prevent factory reset to execute before above reboot completes.
+                // Note: this reboot property is not persistent resets after reboot is completed.
+                if (isRebootPropertySet()) {
+                    return;
+                }
+                executeFactoryReset(context, level, failedPackage);
+                break;
+        }
+    }
+
+    private static void executeWarmReboot(Context context, int level,
+            @Nullable String failedPackage) {
+        // Request the reboot from a separate thread to avoid deadlock on PackageWatchdog
+        // when device shutting down.
+        setRebootProperty(true);
+        Runnable runnable = () -> {
+            try {
+                PowerManager pm = context.getSystemService(PowerManager.class);
+                if (pm != null) {
+                    pm.reboot(TAG);
+                }
+            } catch (Throwable t) {
+                logRescueException(level, failedPackage, t);
+            }
+        };
+        Thread thread = new Thread(runnable);
+        thread.start();
+    }
+
+    private static void executeFactoryReset(Context context, int level,
+            @Nullable String failedPackage) {
+        setFactoryResetProperty(true);
+        long now = System.currentTimeMillis();
+        setLastFactoryResetTimeMs(now);
+        Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    RecoverySystem.rebootPromptAndWipeUserData(context, TAG);
+                } catch (Throwable t) {
+                    logRescueException(level, failedPackage, t);
+                }
+            }
+        };
+        Thread thread = new Thread(runnable);
+        thread.start();
+    }
+
+
+    private static String getCompleteMessage(Throwable t) {
+        final StringBuilder builder = new StringBuilder();
+        builder.append(t.getMessage());
+        while ((t = t.getCause()) != null) {
+            builder.append(": ").append(t.getMessage());
+        }
+        return builder.toString();
+    }
+
+    private static void logRescueException(int level, @Nullable String failedPackageName,
+            Throwable t) {
+        final String msg = getCompleteMessage(t);
+        EventLogTags.writeRescueFailure(level, msg);
+        String failureMsg = "Failed rescue level " + levelToString(level);
+        if (!TextUtils.isEmpty(failedPackageName)) {
+            failureMsg += " for package " + failedPackageName;
+        }
+        logCriticalInfo(Log.ERROR, failureMsg + ": " + msg);
+    }
+
+    private static int mapRescueLevelToUserImpact(int rescueLevel) {
+        if (Flags.recoverabilityDetection()) {
+            switch (rescueLevel) {
+                case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_10;
+                case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_20;
+                case RESCUE_LEVEL_WARM_REBOOT:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_50;
+                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_71;
+                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_75;
+                case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_80;
+                case RESCUE_LEVEL_FACTORY_RESET:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
+                default:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+            }
+        } else {
+            switch (rescueLevel) {
+                case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
+                case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_10;
+                case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+                case LEVEL_WARM_REBOOT:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_50;
+                case LEVEL_FACTORY_RESET:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_100;
+                default:
+                    return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+            }
+        }
+    }
+
+    private static void resetAllSettingsIfNecessary(Context context, int mode,
+            int level) throws Exception {
+        // No need to reset Settings again if they are already reset in the current level once.
+        if (getMaxRescueLevelAttempted() >= level) {
+            return;
+        }
+        setMaxRescueLevelAttempted(level);
+        // Try our best to reset all settings possible, and once finished
+        // rethrow any exception that we encountered
+        Exception res = null;
+        final ContentResolver resolver = context.getContentResolver();
+        try {
+            Settings.Global.resetToDefaultsAsUser(resolver, null, mode,
+                    UserHandle.SYSTEM.getIdentifier());
+        } catch (Exception e) {
+            res = new RuntimeException("Failed to reset global settings", e);
+        }
+        for (int userId : getAllUserIds()) {
+            try {
+                Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
+            } catch (Exception e) {
+                res = new RuntimeException("Failed to reset secure settings for " + userId, e);
+            }
+        }
+        if (res != null) {
+            throw res;
+        }
+    }
+
+    private static void resetDeviceConfig(Context context, boolean isScoped,
+            @Nullable String failedPackage) throws Exception {
+        final ContentResolver resolver = context.getContentResolver();
+        try {
+            if (!isScoped || failedPackage == null) {
+                resetAllAffectedNamespaces(context);
+            } else {
+                performScopedReset(context, failedPackage);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to reset config settings", e);
+        }
+    }
+
+    private static void resetAllAffectedNamespaces(Context context) {
+        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+        Set<String> allAffectedNamespaces = rescuePartyObserver.getAllAffectedNamespaceSet();
+
+        Slog.w(TAG,
+                "Performing reset for all affected namespaces: "
+                        + Arrays.toString(allAffectedNamespaces.toArray()));
+        Iterator<String> it = allAffectedNamespaces.iterator();
+        while (it.hasNext()) {
+            String namespace = it.next();
+            // Don't let RescueParty reset the namespace for RescueParty switches.
+            if (NAMESPACE_CONFIGURATION.equals(namespace)) {
+                continue;
+            }
+            DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE, namespace);
+        }
+    }
+
+    private static void performScopedReset(Context context, @NonNull String failedPackage) {
+        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+        Set<String> affectedNamespaces = rescuePartyObserver.getAffectedNamespaceSet(
+                failedPackage);
+        // If we can't find namespaces affected for current package,
+        // skip this round of reset.
+        if (affectedNamespaces != null) {
+            Slog.w(TAG,
+                    "Performing scoped reset for package: " + failedPackage
+                            + ", affected namespaces: "
+                            + Arrays.toString(affectedNamespaces.toArray()));
+            Iterator<String> it = affectedNamespaces.iterator();
+            while (it.hasNext()) {
+                String namespace = it.next();
+                // Don't let RescueParty reset the namespace for RescueParty switches.
+                if (NAMESPACE_CONFIGURATION.equals(namespace)) {
+                    continue;
+                }
+                DeviceConfig.resetToDefaults(DEVICE_CONFIG_RESET_MODE, namespace);
+            }
+        }
+    }
+
+    /**
+     * Handle mitigation action for package failures. This observer will be register to Package
+     * Watchdog and will receive calls about package failures. This observer is persistent so it
+     * may choose to mitigate failures for packages it has not explicitly asked to observe.
+     */
+    public static class RescuePartyObserver implements PackageHealthObserver {
+
+        private final Context mContext;
+        private final Map<String, Set<String>> mCallingPackageNamespaceSetMap = new HashMap<>();
+        private final Map<String, Set<String>> mNamespaceCallingPackageSetMap = new HashMap<>();
+
+        @GuardedBy("RescuePartyObserver.class")
+        static RescuePartyObserver sRescuePartyObserver;
+
+        private RescuePartyObserver(Context context) {
+            mContext = context;
+        }
+
+        /** Creates or gets singleton instance of RescueParty. */
+        public static RescuePartyObserver getInstance(Context context) {
+            synchronized (RescuePartyObserver.class) {
+                if (sRescuePartyObserver == null) {
+                    sRescuePartyObserver = new RescuePartyObserver(context);
+                }
+                return sRescuePartyObserver;
+            }
+        }
+
+        /** Gets singleton instance. It returns null if the instance is not created yet.*/
+        @Nullable
+        public static RescuePartyObserver getInstanceIfCreated() {
+            synchronized (RescuePartyObserver.class) {
+                return sRescuePartyObserver;
+            }
+        }
+
+        @VisibleForTesting
+        static void reset() {
+            synchronized (RescuePartyObserver.class) {
+                sRescuePartyObserver = null;
+            }
+        }
+
+        @Override
+        public int onHealthCheckFailed(@Nullable VersionedPackage failedPackage,
+                @FailureReasons int failureReason, int mitigationCount) {
+            if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
+                    || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) {
+                if (Flags.recoverabilityDetection()) {
+                    return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+                            mayPerformReboot(failedPackage), failedPackage));
+                } else {
+                    return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+                        mayPerformReboot(failedPackage)));
+                }
+            } else {
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+            }
+        }
+
+        @Override
+        public boolean execute(@Nullable VersionedPackage failedPackage,
+                @FailureReasons int failureReason, int mitigationCount) {
+            if (isDisabled()) {
+                return false;
+            }
+            if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
+                    || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
+                final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount,
+                        mayPerformReboot(failedPackage), failedPackage)
+                        : getRescueLevel(mitigationCount,
+                                mayPerformReboot(failedPackage));
+                executeRescueLevel(mContext,
+                        failedPackage == null ? null : failedPackage.getPackageName(), level);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public boolean isPersistent() {
+            return true;
+        }
+
+        @Override
+        public boolean mayObservePackage(String packageName) {
+            PackageManager pm = mContext.getPackageManager();
+            try {
+                // A package is a module if this is non-null
+                if (pm.getModuleInfo(packageName, 0) != null) {
+                    return true;
+                }
+            } catch (PackageManager.NameNotFoundException | IllegalStateException ignore) {
+            }
+
+            return isPersistentSystemApp(packageName);
+        }
+
+        @Override
+        public int onBootLoop(int mitigationCount) {
+            if (isDisabled()) {
+                return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+            }
+            if (Flags.recoverabilityDetection()) {
+                return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+                        true, /*failedPackage=*/ null));
+            } else {
+                return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true));
+            }
+        }
+
+        @Override
+        public boolean executeBootLoopMitigation(int mitigationCount) {
+            if (isDisabled()) {
+                return false;
+            }
+            boolean mayPerformReboot = !shouldThrottleReboot();
+            final int level = Flags.recoverabilityDetection() ? getRescueLevel(mitigationCount,
+                        mayPerformReboot, /*failedPackage=*/ null)
+                        : getRescueLevel(mitigationCount, mayPerformReboot);
+            executeRescueLevel(mContext, /*failedPackage=*/ null, level);
+            return true;
+        }
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        /**
+         * Returns {@code true} if the failing package is non-null and performing a reboot or
+         * prompting a factory reset is an acceptable mitigation strategy for the package's
+         * failure, {@code false} otherwise.
+         */
+        private boolean mayPerformReboot(@Nullable VersionedPackage failingPackage) {
+            if (failingPackage == null) {
+                return false;
+            }
+            if (shouldThrottleReboot())  {
+                return false;
+            }
+
+            return isPersistentSystemApp(failingPackage.getPackageName());
+        }
+
+        /**
+         * Returns {@code true} if Rescue Party is allowed to attempt a reboot or factory reset.
+         * Will return {@code false} if a factory reset was already offered recently.
+         */
+        private boolean shouldThrottleReboot() {
+            Long lastResetTime = getLastFactoryResetTimeMs();
+            long now = System.currentTimeMillis();
+            long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG,
+                    DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN);
+            return now < lastResetTime + TimeUnit.MINUTES.toMillis(throttleDurationMin);
+        }
+
+        private boolean isPersistentSystemApp(@NonNull String packageName) {
+            PackageManager pm = mContext.getPackageManager();
+            try {
+                ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+                return (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK;
+            } catch (PackageManager.NameNotFoundException e) {
+                return false;
+            }
+        }
+
+        private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage,
+                @NonNull String namespace) {
+            // Record it in calling packages to namespace map
+            Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage);
+            if (namespaceSet == null) {
+                namespaceSet = new ArraySet<>();
+                mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet);
+            }
+            namespaceSet.add(namespace);
+            // Record it in namespace to calling packages map
+            Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace);
+            if (callingPackageSet == null) {
+                callingPackageSet = new ArraySet<>();
+            }
+            callingPackageSet.add(callingPackage);
+            mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet);
+        }
+
+        private synchronized Set<String> getAffectedNamespaceSet(String failedPackage) {
+            return mCallingPackageNamespaceSetMap.get(failedPackage);
+        }
+
+        private synchronized Set<String> getAllAffectedNamespaceSet() {
+            return new HashSet<String>(mNamespaceCallingPackageSetMap.keySet());
+        }
+
+        private synchronized Set<String> getCallingPackagesSet(String namespace) {
+            return mNamespaceCallingPackageSetMap.get(namespace);
+        }
+    }
+
+    private static int[] getAllUserIds() {
+        int systemUserId = UserHandle.SYSTEM.getIdentifier();
+        int[] userIds = { systemUserId };
+        try {
+            for (File file : FileUtils.listFilesOrEmpty(Environment.getDataSystemDeDirectory())) {
+                try {
+                    final int userId = Integer.parseInt(file.getName());
+                    if (userId != systemUserId) {
+                        userIds = ArrayUtils.appendInt(userIds, userId);
+                    }
+                } catch (NumberFormatException ignored) {
+                }
+            }
+        } catch (Throwable t) {
+            Slog.w(TAG, "Trouble discovering users", t);
+        }
+        return userIds;
+    }
+
+    /**
+     * Hacky test to check if the device has an active USB connection, which is
+     * a good proxy for someone doing local development work.
+     */
+    private static boolean isUsbActive() {
+        if (SystemProperties.getBoolean(PROP_VIRTUAL_DEVICE, false)) {
+            Slog.v(TAG, "Assuming virtual device is connected over USB");
+            return true;
+        }
+        try {
+            final String state = FileUtils
+                    .readTextFile(new File("/sys/class/android_usb/android0/state"), 128, "");
+            return "CONFIGURED".equals(state.trim());
+        } catch (Throwable t) {
+            Slog.w(TAG, "Failed to determine if device was on USB", t);
+            return false;
+        }
+    }
+
+    private static String levelToString(int level) {
+        if (Flags.recoverabilityDetection()) {
+            switch (level) {
+                case RESCUE_LEVEL_NONE:
+                    return "NONE";
+                case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
+                    return "SCOPED_DEVICE_CONFIG_RESET";
+                case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
+                    return "ALL_DEVICE_CONFIG_RESET";
+                case RESCUE_LEVEL_WARM_REBOOT:
+                    return "WARM_REBOOT";
+                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
+                    return "RESET_SETTINGS_UNTRUSTED_DEFAULTS";
+                case RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
+                    return "RESET_SETTINGS_UNTRUSTED_CHANGES";
+                case RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+                    return "RESET_SETTINGS_TRUSTED_DEFAULTS";
+                case RESCUE_LEVEL_FACTORY_RESET:
+                    return "FACTORY_RESET";
+                default:
+                    return Integer.toString(level);
+            }
+        } else {
+            switch (level) {
+                case LEVEL_NONE:
+                    return "NONE";
+                case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
+                    return "RESET_SETTINGS_UNTRUSTED_DEFAULTS";
+                case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
+                    return "RESET_SETTINGS_UNTRUSTED_CHANGES";
+                case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+                    return "RESET_SETTINGS_TRUSTED_DEFAULTS";
+                case LEVEL_WARM_REBOOT:
+                    return "WARM_REBOOT";
+                case LEVEL_FACTORY_RESET:
+                    return "FACTORY_RESET";
+                default:
+                    return Integer.toString(level);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
index ac19d8b..64bca33 100644
--- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
+++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.permission.flags.Flags.sensitiveContentImprovements;
+import static android.permission.flags.Flags.sensitiveContentMetricsBugfix;
 import static android.permission.flags.Flags.sensitiveNotificationAppProtection;
 import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;
 import static android.view.flags.Flags.sensitiveContentAppProtection;
@@ -24,6 +26,7 @@
 import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__FRAMEWORKS;
 import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START;
 import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP;
+import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_NOTIFICATION_APP_PROTECTION_SESSION;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -70,6 +73,8 @@
     NotificationListener mNotificationListener;
     @Nullable
     private MediaProjectionManager mProjectionManager;
+
+    @GuardedBy("mSensitiveContentProtectionLock")
     @Nullable
     private MediaProjectionSession mMediaProjectionSession;
 
@@ -89,15 +94,93 @@
     private boolean mProjectionActive = false;
 
     private static class MediaProjectionSession {
-        final int mUid;
-        final long mSessionId;
-        final boolean mIsExempted;
+        private final int mUid; // UID of app that started projection session
+        private final long mSessionId;
+        private final boolean mIsExempted;
+        private final ArraySet<String> mAllSeenNotificationKeys = new ArraySet<>();
+        private final ArraySet<String> mSeenOtpNotificationKeys = new ArraySet<>();
 
         MediaProjectionSession(int uid, boolean isExempted, long sessionId) {
             mUid = uid;
             mIsExempted = isExempted;
             mSessionId = sessionId;
         }
+
+        public void logProjectionSessionStart() {
+            FrameworkStatsLog.write(
+                    SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION,
+                    mSessionId,
+                    mUid,
+                    mIsExempted,
+                    SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START,
+                    SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__FRAMEWORKS
+            );
+        }
+
+        public void logProjectionSessionStop() {
+            FrameworkStatsLog.write(
+                    SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION,
+                    mSessionId,
+                    mUid,
+                    mIsExempted,
+                    SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP,
+                    SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__FRAMEWORKS
+            );
+        }
+
+        public void logAppNotificationsProtected() {
+            FrameworkStatsLog.write(
+                    SENSITIVE_NOTIFICATION_APP_PROTECTION_SESSION,
+                    mSessionId,
+                    mAllSeenNotificationKeys.size(),
+                    mSeenOtpNotificationKeys.size());
+        }
+
+        public void logAppBlocked(int uid) {
+            FrameworkStatsLog.write(
+                    FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION,
+                    mSessionId,
+                    uid,
+                    mUid,
+                    FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION__STATE__BLOCKED
+            );
+        }
+
+        public void logAppUnblocked(int uid) {
+            FrameworkStatsLog.write(
+                    FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION,
+                    mSessionId,
+                    uid,
+                    mUid,
+                    FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION__STATE__UNBLOCKED
+            );
+        }
+
+        private void addSeenNotificationKey(String key) {
+            mAllSeenNotificationKeys.add(key);
+        }
+
+        private void addSeenOtpNotificationKey(String key) {
+            mAllSeenNotificationKeys.add(key);
+            mSeenOtpNotificationKeys.add(key);
+        }
+
+        public void addSeenNotifications(
+                @NonNull StatusBarNotification[] notifications,
+                @NonNull RankingMap rankingMap) {
+            for (StatusBarNotification sbn : notifications) {
+                if (sbn == null) {
+                    Log.w(TAG, "Unable to parse null notification");
+                    continue;
+                }
+
+                if (notificationHasSensitiveContent(sbn, rankingMap)) {
+                    addSeenOtpNotificationKey(sbn.getKey());
+                } else {
+                    addSeenNotificationKey(sbn.getKey());
+                }
+            }
+        }
     }
 
     private final MediaProjectionManager.Callback mProjectionCallback =
@@ -112,28 +195,11 @@
                     } finally {
                         Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                     }
-                    FrameworkStatsLog.write(
-                            SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION,
-                            mMediaProjectionSession.mSessionId,
-                            mMediaProjectionSession.mUid,
-                            mMediaProjectionSession.mIsExempted,
-                            SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__START,
-                            SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__FRAMEWORKS
-                    );
                 }
 
                 @Override
                 public void onStop(MediaProjectionInfo info) {
                     if (DEBUG) Log.d(TAG, "onStop projection: " + info);
-                    FrameworkStatsLog.write(
-                            SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION,
-                            mMediaProjectionSession.mSessionId,
-                            mMediaProjectionSession.mUid,
-                            mMediaProjectionSession.mIsExempted,
-                            SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__STATE__STOP,
-                            SENSITIVE_CONTENT_MEDIA_PROJECTION_SESSION__SOURCE__FRAMEWORKS
-                    );
-
                     Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
                             "SensitiveContentProtectionManagerService.onProjectionStop");
                     try {
@@ -242,17 +308,25 @@
                 DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0) != 0;
         int uid = mPackageManagerInternal.getPackageUid(projectionInfo.getPackageName(), 0,
                 projectionInfo.getUserHandle().getIdentifier());
-        mMediaProjectionSession = new MediaProjectionSession(
-                uid, isPackageExempted || isFeatureDisabled, new Random().nextLong());
-
-        if (isPackageExempted || isFeatureDisabled) {
-            Log.w(TAG, "projection session is exempted, package ="
-                    + projectionInfo.getPackageName() + ", isFeatureDisabled=" + isFeatureDisabled);
-            return;
-        }
-
         synchronized (mSensitiveContentProtectionLock) {
+            mMediaProjectionSession = new MediaProjectionSession(
+                    uid, isPackageExempted || isFeatureDisabled, new Random().nextLong());
+            mMediaProjectionSession.logProjectionSessionStart();
+
+            if (isPackageExempted || isFeatureDisabled) {
+                Log.w(TAG, "projection session is exempted, package ="
+                        + projectionInfo.getPackageName() + ", isFeatureDisabled="
+                        + isFeatureDisabled);
+                return;
+            }
+
             mProjectionActive = true;
+
+            if (sensitiveContentMetricsBugfix()) {
+                mWindowManager.setBlockScreenCaptureForAppsSessionId(
+                        mMediaProjectionSession.mSessionId);
+            }
+
             if (sensitiveNotificationAppProtection()) {
                 updateAppsThatShouldBlockScreenCapture();
             }
@@ -266,7 +340,13 @@
     private void onProjectionEnd() {
         synchronized (mSensitiveContentProtectionLock) {
             mProjectionActive = false;
-            mMediaProjectionSession = null;
+            if (mMediaProjectionSession != null) {
+                mMediaProjectionSession.logProjectionSessionStop();
+                if (sensitiveContentImprovements()) {
+                    mMediaProjectionSession.logAppNotificationsProtected();
+                }
+                mMediaProjectionSession = null;
+            }
 
             // notify windowmanager to clear any sensitive notifications observed during projection
             // session
@@ -274,6 +354,7 @@
         }
     }
 
+    @GuardedBy("mSensitiveContentProtectionLock")
     private void updateAppsThatShouldBlockScreenCapture() {
         RankingMap rankingMap;
         try {
@@ -283,10 +364,16 @@
             rankingMap = null;
         }
 
+        if (rankingMap == null) {
+            Log.w(TAG, "Ranking map not initialized.");
+            return;
+        }
+
         updateAppsThatShouldBlockScreenCapture(rankingMap);
     }
 
-    private void updateAppsThatShouldBlockScreenCapture(RankingMap rankingMap) {
+    @GuardedBy("mSensitiveContentProtectionLock")
+    private void updateAppsThatShouldBlockScreenCapture(@NonNull RankingMap rankingMap) {
         StatusBarNotification[] notifications;
         try {
             notifications = mNotificationListener.getActiveNotifications();
@@ -295,23 +382,28 @@
             notifications = new StatusBarNotification[0];
         }
 
+        if (sensitiveContentImprovements() && mMediaProjectionSession != null) {
+            mMediaProjectionSession.addSeenNotifications(notifications, rankingMap);
+        }
+
         // notify windowmanager of any currently posted sensitive content notifications
         ArraySet<PackageInfo> packageInfos =
                 getSensitivePackagesFromNotifications(notifications, rankingMap);
+
         if (packageInfos.size() > 0) {
             mWindowManager.addBlockScreenCaptureForApps(packageInfos);
         }
     }
 
-    private ArraySet<PackageInfo> getSensitivePackagesFromNotifications(
-            @NonNull StatusBarNotification[] notifications, RankingMap rankingMap) {
+    private static @NonNull ArraySet<PackageInfo> getSensitivePackagesFromNotifications(
+            @NonNull StatusBarNotification[] notifications, @NonNull RankingMap rankingMap) {
         ArraySet<PackageInfo> sensitivePackages = new ArraySet<>();
-        if (rankingMap == null) {
-            Log.w(TAG, "Ranking map not initialized.");
-            return sensitivePackages;
-        }
-
         for (StatusBarNotification sbn : notifications) {
+            if (sbn == null) {
+                Log.w(TAG, "Unable to parse null notification");
+                continue;
+            }
+
             PackageInfo info = getSensitivePackageFromNotification(sbn, rankingMap);
             if (info != null) {
                 sensitivePackages.add(info);
@@ -320,24 +412,20 @@
         return sensitivePackages;
     }
 
-    private PackageInfo getSensitivePackageFromNotification(
-            StatusBarNotification sbn, RankingMap rankingMap) {
-        if (sbn == null) {
-            Log.w(TAG, "Unable to protect null notification");
-            return null;
-        }
-        if (rankingMap == null) {
-            Log.w(TAG, "Ranking map not initialized.");
-            return null;
-        }
-
-        NotificationListenerService.Ranking ranking = rankingMap.getRawRankingObject(sbn.getKey());
-        if (ranking != null && ranking.hasSensitiveContent()) {
+    private static @Nullable PackageInfo getSensitivePackageFromNotification(
+            @NonNull StatusBarNotification sbn, @NonNull RankingMap rankingMap) {
+        if (notificationHasSensitiveContent(sbn, rankingMap)) {
             return new PackageInfo(sbn.getPackageName(), sbn.getUid());
         }
         return null;
     }
 
+    private static boolean notificationHasSensitiveContent(
+            @NonNull StatusBarNotification sbn, @NonNull RankingMap rankingMap) {
+        NotificationListenerService.Ranking ranking = rankingMap.getRawRankingObject(sbn.getKey());
+        return ranking != null && ranking.hasSensitiveContent();
+    }
+
     @VisibleForTesting
     class NotificationListener extends NotificationListenerService {
         @Override
@@ -363,6 +451,16 @@
             Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
                     "SensitiveContentProtectionManagerService.onNotificationPosted");
             try {
+                if (sbn == null) {
+                    Log.w(TAG, "Unable to parse null notification");
+                    return;
+                }
+
+                if (rankingMap == null) {
+                    Log.w(TAG, "Ranking map not initialized.");
+                    return;
+                }
+
                 synchronized (mSensitiveContentProtectionLock) {
                     if (!mProjectionActive) {
                         return;
@@ -375,6 +473,14 @@
                         mWindowManager.addBlockScreenCaptureForApps(
                                 new ArraySet(Set.of(packageInfo)));
                     }
+
+                    if (sensitiveContentImprovements() && mMediaProjectionSession != null) {
+                        if (packageInfo != null) {
+                            mMediaProjectionSession.addSeenOtpNotificationKey(sbn.getKey());
+                        } else {
+                            mMediaProjectionSession.addSeenNotificationKey(sbn.getKey());
+                        }
+                    }
                 }
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -387,6 +493,11 @@
             Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
                     "SensitiveContentProtectionManagerService.onNotificationRankingUpdate");
             try {
+                if (rankingMap == null) {
+                    Log.w(TAG, "Ranking map not initialized.");
+                    return;
+                }
+
                 synchronized (mSensitiveContentProtectionLock) {
                     if (mProjectionActive) {
                         updateAppsThatShouldBlockScreenCapture(rankingMap);
@@ -437,22 +548,14 @@
             packageInfos.add(packageInfo);
             if (isShowingSensitiveContent) {
                 mWindowManager.addBlockScreenCaptureForApps(packageInfos);
-                FrameworkStatsLog.write(
-                        FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION,
-                        mMediaProjectionSession.mSessionId,
-                        uid,
-                        mMediaProjectionSession.mUid,
-                        FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION__STATE__BLOCKED
-                );
+                if (mMediaProjectionSession != null) {
+                    mMediaProjectionSession.logAppBlocked(uid);
+                }
             } else {
                 mWindowManager.removeBlockScreenCaptureForApps(packageInfos);
-                FrameworkStatsLog.write(
-                        FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION,
-                        mMediaProjectionSession.mSessionId,
-                        uid,
-                        mMediaProjectionSession.mUid,
-                        FrameworkStatsLog.SENSITIVE_CONTENT_APP_PROTECTION__STATE__UNBLOCKED
-                );
+                if (mMediaProjectionSession != null) {
+                    mMediaProjectionSession.logAppUnblocked(uid);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index e7fae24..4dd3a8f 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -107,6 +107,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.DiskInfo;
+import android.os.storage.ICeStorageLockEventListener;
 import android.os.storage.IObbActionListener;
 import android.os.storage.IStorageEventListener;
 import android.os.storage.IStorageManager;
@@ -139,6 +140,7 @@
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.AppFuseMount;
@@ -147,7 +149,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.HexDump;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.modules.utils.TypedXmlPullParser;
@@ -185,6 +186,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -602,6 +604,9 @@
     // Not guarded by lock, always used on the ActivityManager thread
     private final SparseArray<PackageMonitor> mPackageMonitorsForUser = new SparseArray<>();
 
+    /** List of listeners registered for ce storage callbacks */
+    private final CopyOnWriteArrayList<ICeStorageLockEventListener>
+            mCeStorageEventCallbacks = new CopyOnWriteArrayList<>();
 
     class ObbState implements IBinder.DeathRecipient {
         public ObbState(String rawPath, String canonicalPath, int callingUid,
@@ -3272,7 +3277,7 @@
             throws RemoteException {
         super.setCeStorageProtection_enforcePermission();
 
-        mVold.setCeStorageProtection(userId, HexDump.toHexString(secret));
+        mVold.setCeStorageProtection(userId, secret);
     }
 
     /* Only for use by LockSettingsService */
@@ -3282,7 +3287,7 @@
         super.unlockCeStorage_enforcePermission();
 
         if (StorageManager.isFileEncrypted()) {
-            mVold.unlockCeStorage(userId, HexDump.toHexString(secret));
+            mVold.unlockCeStorage(userId, secret);
         }
         synchronized (mLock) {
             mCeUnlockedUsers.append(userId);
@@ -3315,6 +3320,11 @@
         synchronized (mLock) {
             mCeUnlockedUsers.remove(userId);
         }
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
+            dispatchCeStorageLockedEvent(userId);
+        }
     }
 
     @Override
@@ -4580,6 +4590,18 @@
         return StorageManager.MOUNT_MODE_EXTERNAL_NONE;
     }
 
+    @VisibleForTesting
+    CopyOnWriteArrayList<ICeStorageLockEventListener> getCeStorageEventCallbacks() {
+        return mCeStorageEventCallbacks;
+    }
+
+    @VisibleForTesting
+    void dispatchCeStorageLockedEvent(int userId) {
+        for (ICeStorageLockEventListener listener: mCeStorageEventCallbacks) {
+            listener.onStorageLocked(userId);
+        }
+    }
+
     private static class Callbacks extends Handler {
         private static final int MSG_STORAGE_STATE_CHANGED = 1;
         private static final int MSG_VOLUME_STATE_CHANGED = 2;
@@ -5066,5 +5088,23 @@
                 throw new IOException(e);
             }
         }
+
+        @Override
+        public void registerStorageLockEventListener(
+                @NonNull ICeStorageLockEventListener listener) {
+            boolean registered = mCeStorageEventCallbacks.add(listener);
+            if (!registered) {
+                Slog.w(TAG, "Failed to register listener: " + listener);
+            }
+        }
+
+        @Override
+        public void unregisterStorageLockEventListener(
+                @NonNull ICeStorageLockEventListener listener) {
+            boolean unregistered = mCeStorageEventCallbacks.remove(listener);
+            if (!unregistered) {
+                Slog.w(TAG, "Unregistering " + listener + " that was not registered");
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 1a3ef73..a508ebf 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -106,6 +106,9 @@
     // property for runtime configuration differentiation in vendor
     private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
 
+    // property for runtime configuration differentation in product
+    private static final String PRODUCT_SKU_PROPERTY = "ro.boot.hardware.sku";
+
     private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS =
             new ArrayMap<>();
 
@@ -694,6 +697,17 @@
         readPermissions(parser, Environment.buildPath(
                 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
 
+        String productSkuProperty = SystemProperties.get(PRODUCT_SKU_PROPERTY, "");
+        if (!productSkuProperty.isEmpty()) {
+            String productSkuDir = "sku_" + productSkuProperty;
+            readPermissions(parser, Environment.buildPath(
+                    Environment.getProductDirectory(), "etc", "sysconfig", productSkuDir),
+                    productPermissionFlag);
+            readPermissions(parser, Environment.buildPath(
+                    Environment.getProductDirectory(), "etc", "permissions", productSkuDir),
+                    productPermissionFlag);
+        }
+
         // Allow /system_ext to customize all system configs
         readPermissions(parser, Environment.buildPath(
                 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 20816a1..32c7dde 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -44,6 +44,9 @@
 import com.android.server.pm.ApexManager;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.TypePattern;
+import com.android.tools.r8.keepanno.annotations.UsesReflection;
 
 import dalvik.system.PathClassLoader;
 
@@ -135,7 +138,13 @@
     }
 
     /**
-     * Starts a service by class name.
+     * Starts a service by class name from the current {@code SYSTEMSERVERCLASSPATH}.
+     *
+     * In general, this should only be used for services in the classpath that cannot
+     * be resolved by {@code services.jar} at build time, e.g., those defined in an apex jar from
+     * {@code PRODUCT_APEX_SYSTEM_SERVER_JARS} or a downstream jar in
+     * {@code PRODUCT_SYSTEM_SERVER_JARS}. Otherwise prefer the explicit type variant
+     * {@link #startService(Class)}.
      *
      * @return The service instance.
      */
@@ -147,7 +156,11 @@
     }
 
     /**
-     * Starts a service by class name and a path that specifies the jar where the service lives.
+     * Starts a service by class name and standalone jar path where the service lives.
+     *
+     * In general, this should only be used for services in {@code STANDALONE_SYSTEMSERVER_JARS},
+     * which in turn derives from {@code PRODUCT_STANDALONE_SYSTEM_SERVER_JARS} and
+     * {@code PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS}.
      *
      * @return The service instance.
      */
@@ -207,6 +220,11 @@
      * @throws RuntimeException if the service fails to start.
      */
     @android.ravenwood.annotation.RavenwoodKeep
+    @UsesReflection(
+            @KeepTarget(
+                    instanceOfClassConstantExclusive = SystemService.class,
+                    methodName = "<init>",
+                    methodParameterTypePatterns = {@TypePattern(constant = Context.class)}))
     public <T extends SystemService> T startService(Class<T> serviceClass) {
         try {
             final String name = serviceClass.getName();
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index 9c4c634..5933639 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -62,6 +62,27 @@
             "file_patterns": ["SensorPrivacyService\\.java"]
         },
         {
+            "name": "FrameworksMockingServicesTests",
+            "options": [
+                {
+                    "include-filter": "com.android.server.SensitiveContentProtectionManagerServiceContentTest"
+                },
+                {
+                    "include-filter": "com.android.server.SensitiveContentProtectionManagerServiceNotificationTest"
+                }
+            ],
+            "file_patterns": ["SensitiveContentProtectionManagerService\\.java"]
+        },
+        {
+            "name": "FrameworksMockingServicesTests",
+            "options": [
+                {
+                    "include-filter": "com.android.server.StorageManagerServiceTest"
+                }
+            ],
+            "file_patterns": ["StorageManagerService\\.java"]
+        },
+        {
             "name": "FrameworksServicesTests",
             "options": [
                 {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index bd67cf420..e171064 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -425,6 +425,8 @@
     private int[] mSCBMReason;
     private boolean[] mSCBMStarted;
 
+    private boolean[] mCarrierRoamingNtnMode = null;
+
     /**
      * Per-phone map of precise data connection state. The key of the map is the pair of transport
      * type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -723,6 +725,7 @@
             mECBMStarted = copyOf(mECBMStarted, mNumPhones);
             mSCBMReason = copyOf(mSCBMReason, mNumPhones);
             mSCBMStarted = copyOf(mSCBMStarted, mNumPhones);
+            mCarrierRoamingNtnMode = copyOf(mCarrierRoamingNtnMode, mNumPhones);
             // ds -> ss switch.
             if (mNumPhones < oldNumPhones) {
                 cutListToSize(mCellInfo, mNumPhones);
@@ -781,6 +784,7 @@
                 mECBMStarted[i] = false;
                 mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
                 mSCBMStarted[i] = false;
+                mCarrierRoamingNtnMode[i] = false;
             }
         }
     }
@@ -854,6 +858,7 @@
         mECBMStarted = new boolean[numPhones];
         mSCBMReason = new int[numPhones];
         mSCBMStarted = new boolean[numPhones];
+        mCarrierRoamingNtnMode = new boolean[numPhones];
 
         for (int i = 0; i < numPhones; i++) {
             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
@@ -897,6 +902,7 @@
             mECBMStarted[i] = false;
             mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
             mSCBMStarted[i] = false;
+            mCarrierRoamingNtnMode[i] = false;
         }
 
         mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1523,6 +1529,14 @@
                         remove(r.binder);
                     }
                 }
+                if (events.contains(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED)) {
+                    try {
+                        r.callback.onCarrierRoamingNtnModeChanged(
+                                mCarrierRoamingNtnMode[r.phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
+                }
             }
         }
     }
@@ -3512,6 +3526,41 @@
         handleRemoveListLocked();
     }
 
+    /**
+     * Notify external listeners that carrier roaming non-terrestrial network mode changed.
+     * @param subId subscription ID.
+     * @param active {@code true} If the device is connected to carrier roaming
+     *                           non-terrestrial network or was connected within the
+     *                           {CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+     *                           duration, {code false} otherwise.
+     */
+    public void notifyCarrierRoamingNtnModeChanged(int subId, boolean active) {
+        if (!checkNotifyPermission("notifyCarrierRoamingNtnModeChanged")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyCarrierRoamingNtnModeChanged: subId=" + subId + " active=" + active);
+        }
+
+        synchronized (mRecords) {
+            int phoneId = getPhoneIdFromSubId(subId);
+            mCarrierRoamingNtnMode[phoneId] = active;
+            for (Record r : mRecords) {
+                if (r.matchTelephonyCallbackEvent(
+                        TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED)
+                        && idMatch(r, subId, phoneId)) {
+                    try {
+                        r.callback.onCarrierRoamingNtnModeChanged(active);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
     @NeverCompile // Avoid size overhead of debugging code.
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 586b095..1015ad9 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -880,6 +880,14 @@
                     packagesToVisibility = Collections.emptyMap();
                     accountRemovedReceivers = Collections.emptyList();
                 }
+                if (notify) {
+                    Integer oldVisibility =
+                            accounts.accountsDb.findAccountVisibility(account, packageName);
+                    if (oldVisibility != null && oldVisibility == newVisibility) {
+                        // Database will not be updated - skip LOGIN_ACCOUNTS_CHANGED broadcast.
+                        notify = false;
+                    }
+                }
 
                 if (!updateAccountVisibilityLocked(account, packageName, newVisibility, accounts)) {
                     return false;
@@ -897,6 +905,11 @@
                         }
                     }
                     for (String packageNameToNotify : accountRemovedReceivers) {
+                        int currentVisibility =
+                                resolveAccountVisibility(account, packageNameToNotify, accounts);
+                        if (isVisible(currentVisibility)) {
+                            continue;
+                        }
                         sendAccountRemovedBroadcast(
                                 account,
                                 packageNameToNotify,
diff --git a/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java b/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java
index 0e0bf81..4da5cfc 100644
--- a/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java
+++ b/services/core/java/com/android/server/adaptiveauth/AdaptiveAuthService.java
@@ -23,7 +23,13 @@
 import android.content.pm.PackageManager;
 import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -131,30 +137,35 @@
     private final AuthenticationStateListener mAuthenticationStateListener =
             new AuthenticationStateListener.Stub() {
                 @Override
-                public void onAuthenticationStarted(int requestReason) {}
+                public void onAuthenticationAcquired(AuthenticationAcquiredInfo authInfo) {}
 
                 @Override
-                public void onAuthenticationStopped() {}
+                public void onAuthenticationError(AuthenticationErrorInfo authInfo) {}
 
                 @Override
-                public void onAuthenticationSucceeded(int requestReason, int userId) {
+                public void onAuthenticationFailed(AuthenticationFailedInfo authInfo) {
+                    Slog.i(TAG, "AuthenticationStateListener#onAuthenticationFailed");
+                    mHandler.obtainMessage(MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT, AUTH_FAILURE,
+                                    authInfo.getUserId()).sendToTarget();
+                }
+
+                @Override
+                public void onAuthenticationHelp(AuthenticationHelpInfo authInfo) {}
+
+                @Override
+                public void onAuthenticationStarted(AuthenticationStartedInfo authInfo) {}
+
+                @Override
+                public void onAuthenticationStopped(AuthenticationStoppedInfo authInfo) {}
+
+                @Override
+                public void onAuthenticationSucceeded(AuthenticationSucceededInfo authInfo) {
                     if (DEBUG) {
                         Slog.d(TAG, "AuthenticationStateListener#onAuthenticationSucceeded");
                     }
-                    mHandler.obtainMessage(MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT, AUTH_SUCCESS, userId)
-                            .sendToTarget();
+                    mHandler.obtainMessage(MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT, AUTH_SUCCESS,
+                                    authInfo.getUserId()).sendToTarget();
                 }
-
-                @Override
-                public void onAuthenticationFailed(int requestReason, int userId) {
-                    Slog.i(TAG, "AuthenticationStateListener#onAuthenticationFailed");
-                    mHandler.obtainMessage(MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT, AUTH_FAILURE, userId)
-                            .sendToTarget();
-                }
-
-                @Override
-                public void onAuthenticationAcquired(BiometricSourceType biometricSourceType,
-                        int requestReason, int acquiredInfo) {}
             };
 
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7ea82b0..eec22c9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -240,6 +240,7 @@
 import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.am.LowMemDetector.MemFactor;
 import com.android.server.am.ServiceRecord.ShortFgsInfo;
+import com.android.server.am.ServiceRecord.TimeLimitedFgsInfo;
 import com.android.server.pm.KnownPackages;
 import com.android.server.uri.NeededUriGrants;
 import com.android.server.utils.AnrTimer;
@@ -500,6 +501,12 @@
     // see ServiceRecord#getEarliestStopTypeAndTime()
     private final ServiceAnrTimer mFGSAnrTimer;
 
+    /**
+     * Mapping of uid to {fgs_type, fgs_info} for time limited fgs types such as dataSync and
+     * mediaProcessing.
+     */
+    final SparseArray<SparseArray<TimeLimitedFgsInfo>> mTimeLimitedFgsInfo = new SparseArray<>();
+
     // allowlisted packageName.
     ArraySet<String> mAllowListWhileInUsePermissionInFgs = new ArraySet<>();
 
@@ -2275,12 +2282,12 @@
 
                 // Whether to extend the SHORT_SERVICE time out.
                 boolean extendShortServiceTimeout = false;
-                // Whether to extend the timeout for a time-limited FGS type.
-                boolean extendFgsTimeout = false;
 
                 // Whether setFgsRestrictionLocked() is called in here. Only used for logging.
                 boolean fgsRestrictionRecalculated = false;
 
+                final int previousFgsType = r.foregroundServiceType;
+
                 int fgsTypeCheckCode = FGS_TYPE_POLICY_CHECK_UNKNOWN;
                 if (!ignoreForeground) {
                     if (foregroundServiceType == FOREGROUND_SERVICE_TYPE_SHORT_SERVICE
@@ -2321,19 +2328,6 @@
                     final boolean isOldTypeShortFgsAndTimedOut =
                             r.shouldTriggerShortFgsTimeout(nowUptime);
 
-                    // Calling startForeground on a FGS type which has a time limit will only be
-                    // allowed if the app is in a state where it can normally start another FGS.
-                    // The timeout will behave as follows:
-                    // A) <TIME_LIMITED_TYPE> -> another <TIME_LIMITED_TYPE>
-                    //    - If the start succeeds, the timeout is reset.
-                    // B) <TIME_LIMITED_TYPE> -> non-time-limited type
-                    //    - If the start succeeds, the timeout will stop.
-                    // C) non-time-limited type -> <TIME_LIMITED_TYPE>
-                    //    - If the start succeeds, the timeout will start.
-                    final boolean isOldTypeTimeLimited = r.isFgsTimeLimited();
-                    final boolean isNewTypeTimeLimited =
-                            r.canFgsTypeTimeOut(foregroundServiceType);
-
                     // If true, we skip the BFSL check.
                     boolean bypassBfslCheck = false;
 
@@ -2402,7 +2396,11 @@
                                 // "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
                             }
                         }
-                    } else if (r.isForeground && isOldTypeTimeLimited) {
+                    } else if (getTimeLimitedFgsType(foregroundServiceType)
+                                    != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+                        // Calling startForeground on a FGS type which has a time limit will only be
+                        // allowed if the app is in a state where it can normally start another FGS
+                        // and it hasn't hit the time limit for that type in the past 24hrs.
 
                         // See if the app could start an FGS or not.
                         r.clearFgsAllowStart();
@@ -2413,20 +2411,35 @@
 
                         final boolean fgsStartAllowed = !isBgFgsRestrictionEnabledForService
                                                             || r.isFgsAllowedStart();
-
                         if (fgsStartAllowed) {
-                            if (isNewTypeTimeLimited) {
-                                // Note: in the future, we may want to look into metrics to see if
-                                // apps are constantly switching between a time-limited type and a
-                                // non-time-limited type or constantly calling startForeground()
-                                // opportunistically on the same type to gain runtime and apply the
-                                // stricter timeout. For now, always extend the timeout if the app
-                                // is in a state where it's allowed to start a FGS.
-                                extendFgsTimeout = true;
-                            } else {
-                                // FGS type is changing from a time-restricted type to one without
-                                // a time limit so proceed as normal.
-                                // The timeout will stop later, in maybeUpdateFgsTrackingLocked().
+                            SparseArray<TimeLimitedFgsInfo> fgsInfo =
+                                    mTimeLimitedFgsInfo.get(r.appInfo.uid);
+                            if (fgsInfo == null) {
+                                fgsInfo = new SparseArray<>();
+                                mTimeLimitedFgsInfo.put(r.appInfo.uid, fgsInfo);
+                            }
+                            final int timeLimitedFgsType =
+                                    getTimeLimitedFgsType(foregroundServiceType);
+                            final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType);
+                            if (fgsTypeInfo != null) {
+                                final long before24Hr = Math.max(0,
+                                            SystemClock.elapsedRealtime() - (24 * 60 * 60 * 1000));
+                                final long lastTimeOutAt = fgsTypeInfo.getTimeLimitExceededAt();
+                                if (fgsTypeInfo.getFirstFgsStartTime() < before24Hr
+                                        || (lastTimeOutAt != Long.MIN_VALUE
+                                            && r.app.mState.getLastTopTime() > lastTimeOutAt)) {
+                                    // Reset the time limit info for this fgs type if it has been
+                                    // more than 24hrs since the first fgs start or if the app was
+                                    // in the TOP state after time limit was exhausted.
+                                    fgsTypeInfo.reset();
+                                } else if (lastTimeOutAt > 0) {
+                                    // Time limit was exhausted within the past 24 hours and the app
+                                    // has not been in the TOP state since then, throw an exception.
+                                    throw new ForegroundServiceStartNotAllowedException("Time limit"
+                                            + " already exhausted for foreground service type "
+                                            + ServiceInfo.foregroundServiceTypeToLabel(
+                                                            foregroundServiceType));
+                                }
                             }
                         } else {
                             // This case will be handled in the BFSL check below.
@@ -2673,7 +2686,7 @@
                     mAm.notifyPackageUse(r.serviceInfo.packageName,
                             PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
 
-                    maybeUpdateFgsTrackingLocked(r, extendFgsTimeout);
+                    maybeUpdateFgsTrackingLocked(r, previousFgsType);
                 } else {
                     if (DEBUG_FOREGROUND_SERVICE) {
                         Slog.d(TAG, "Suppressing startForeground() for FAS " + r);
@@ -3583,11 +3596,9 @@
                     Slog.d(TAG_SERVICE, "[STALE] Short FGS timed out: " + sr
                             + " " + sr.getShortFgsTimedEventDescription(nowUptime));
                 }
-                mShortFGSAnrTimer.discard(sr);
                 return;
             }
             Slog.e(TAG_SERVICE, "Short FGS timed out: " + sr);
-            mShortFGSAnrTimer.accept(sr);
             traceInstant("short FGS timeout: ", sr);
 
             logFGSStateChangeLocked(sr,
@@ -3667,8 +3678,10 @@
                     Slog.d(TAG_SERVICE, "[STALE] Short FGS ANR'ed: " + sr
                             + " " + sr.getShortFgsTimedEventDescription(nowUptime));
                 }
+                mShortFGSAnrTimer.discard(sr);
                 return;
             }
+            mShortFGSAnrTimer.accept(sr);
 
             final String message = "Short FGS ANR'ed: " + sr;
             if (DEBUG_SHORT_SERVICE) {
@@ -3687,75 +3700,117 @@
         }
     }
 
-    void onFgsTimeout(ServiceRecord sr) {
-        synchronized (mAm) {
-            final long nowUptime = SystemClock.uptimeMillis();
-            final int fgsType = sr.getTimedOutFgsType(nowUptime);
-            if (fgsType == -1) {
-                mFGSAnrTimer.discard(sr);
-                return;
-            }
-            Slog.e(TAG_SERVICE, "FGS (" + ServiceInfo.foregroundServiceTypeToLabel(fgsType)
-                    + ") timed out: " + sr);
-            mFGSAnrTimer.accept(sr);
-            traceInstant("FGS timed out: ", sr);
-
-            logFGSStateChangeLocked(sr,
-                    FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT,
-                    nowUptime > sr.mFgsEnterTime ? (int) (nowUptime - sr.mFgsEnterTime) : 0,
-                    FGS_STOP_REASON_UNKNOWN,
-                    FGS_TYPE_POLICY_CHECK_UNKNOWN,
-                    FOREGROUND_SERVICE_STATE_CHANGED__FGS_START_API__FGSSTARTAPI_NA,
-                    false /* fgsRestrictionRecalculated */
-            );
-            try {
-                sr.app.getThread().scheduleTimeoutServiceForType(sr, sr.getLastStartId(), fgsType);
-            } catch (RemoteException e) {
-                Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutServiceForType: " + e);
-            }
-
-            // ANR the service after giving the service some time to clean up.
-            // ServiceRecord.getEarliestStopTypeAndTime() is an absolute time with a reference that
-            // is not "now". Compute the time from "now" when starting the anr timer.
-            final long anrTime = sr.getEarliestStopTypeAndTime().second
-                    + mAm.mConstants.mFgsAnrExtraWaitDuration - SystemClock.uptimeMillis();
-            mFGSAnrTimer.start(sr, anrTime);
+    /**
+     * @return the fgs type for this service which has the most lenient time limit; if none of the
+     * types are time-restricted, return {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+     */
+    @ServiceInfo.ForegroundServiceType int getTimeLimitedFgsType(int foregroundServiceType) {
+        int fgsType = ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
+        long timeout = 0;
+        if ((foregroundServiceType & ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING)
+                == ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING) {
+            fgsType = ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING;
+            timeout = mAm.mConstants.mMediaProcessingFgsTimeoutDuration;
         }
+        if ((foregroundServiceType & ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
+                == ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) {
+            // update the timeout and type if this type has a more lenient time limit
+            if (timeout == 0 || mAm.mConstants.mDataSyncFgsTimeoutDuration > timeout) {
+                fgsType = ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC;
+                timeout = mAm.mConstants.mDataSyncFgsTimeoutDuration;
+            }
+        }
+        // Add logic for time limits introduced in the future for other fgs types above.
+        return fgsType;
     }
 
-    private void maybeUpdateFgsTrackingLocked(ServiceRecord sr, boolean extendTimeout) {
-        if (!sr.isFgsTimeLimited()) {
-            // Reset timers if they exist.
-            sr.setIsFgsTimeLimited(false);
-            mFGSAnrTimer.cancel(sr);
-            mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
+    private void maybeUpdateFgsTrackingLocked(ServiceRecord sr, int previousFgsType) {
+        final int previouslyTimeLimitedType = getTimeLimitedFgsType(previousFgsType);
+        if (previouslyTimeLimitedType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE
+                && !sr.isFgsTimeLimited()) {
+            // FGS was not previously time-limited and new type isn't either.
             return;
         }
 
-        if (extendTimeout || !sr.wasFgsPreviouslyTimeLimited()) {
-            traceInstant("FGS start: ", sr);
-            sr.setIsFgsTimeLimited(true);
+        if (previouslyTimeLimitedType != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+            // FGS is switching types and the previous type was time-limited so update the runtime.
+            final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid);
+            if (fgsInfo != null) {
+                final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(previouslyTimeLimitedType);
+                if (fgsTypeInfo != null) {
+                    // Update the total runtime for the previous time-limited fgs type.
+                    fgsTypeInfo.updateTotalRuntime();
+                    // TODO(b/330399444): handle the case where an app is running 2 services of the
+                    //  same time-limited type in parallel and stops one of them which leads to the
+                    //  second running one gaining additional runtime.
+                }
+            }
 
-            // We'll restart the timeout.
-            mFGSAnrTimer.cancel(sr);
-            mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
-
-            final Message msg = mAm.mHandler.obtainMessage(
-                    ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
-            mAm.mHandler.sendMessageAtTime(msg, sr.getEarliestStopTypeAndTime().second);
+            if (!sr.isFgsTimeLimited()) {
+                // Reset timers since new type does not have a timeout.
+                mFGSAnrTimer.cancel(sr);
+                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
+                return;
+            }
         }
+
+        traceInstant("FGS start: ", sr);
+        final long nowRealtime = SystemClock.elapsedRealtime();
+
+        // Fetch/create/update the fgs info for the time-limited type.
+        SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid);
+        if (fgsInfo == null) {
+            fgsInfo = new SparseArray<>();
+            mTimeLimitedFgsInfo.put(sr.appInfo.uid, fgsInfo);
+        }
+        final int timeLimitedFgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
+        TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType);
+        if (fgsTypeInfo == null) {
+            fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowRealtime);
+            fgsInfo.put(timeLimitedFgsType, fgsTypeInfo);
+        }
+        fgsTypeInfo.setLastFgsStartTime(nowRealtime);
+
+        // We'll cancel the previous ANR timer and start a fresh one below.
+        mFGSAnrTimer.cancel(sr);
+        mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
+
+        final Message msg = mAm.mHandler.obtainMessage(
+                ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
+        final long timeoutCallbackTime = sr.getNextFgsStopTime(timeLimitedFgsType, fgsTypeInfo);
+        if (timeoutCallbackTime == Long.MAX_VALUE) {
+            // This should never happen since we only get to this point if the service record's
+            // foregroundServiceType attribute contains a type that can be timed-out.
+            Slog.wtf(TAG, "Couldn't calculate timeout for time-limited fgs: " + sr);
+            return;
+        }
+        mAm.mHandler.sendMessageAtTime(msg, timeoutCallbackTime);
     }
 
     private void maybeStopFgsTimeoutLocked(ServiceRecord sr) {
-        sr.setIsFgsTimeLimited(false); // reset fgs boolean holding time-limited type state.
-        if (!sr.isFgsTimeLimited()) {
-            return; // if none of the types are time-limited, return.
+        final int timeLimitedType = getTimeLimitedFgsType(sr.foregroundServiceType);
+        if (timeLimitedType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+            return; // if the current fgs type is not time-limited, return.
+        }
+
+        final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid);
+        if (fgsInfo != null) {
+            final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedType);
+            if (fgsTypeInfo != null) {
+                // Update the total runtime for the previous time-limited fgs type.
+                fgsTypeInfo.updateTotalRuntime();
+            }
         }
         Slog.d(TAG_SERVICE, "Stop FGS timeout: " + sr);
         mFGSAnrTimer.cancel(sr);
         mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
     }
 
+    void onUidRemovedLocked(int uid) {
+        // Remove all time-limited fgs tracking info stored for this uid.
+        mTimeLimitedFgsInfo.delete(uid);
+    }
+
     boolean hasServiceTimedOutLocked(ComponentName className, IBinder token) {
         final int userId = UserHandle.getCallingUserId();
         final long ident = mAm.mInjector.clearCallingIdentity();
@@ -3764,25 +3819,69 @@
             if (sr == null) {
                 return false;
             }
-            final long nowUptime = SystemClock.uptimeMillis();
-            return sr.getTimedOutFgsType(nowUptime) != -1;
+            return getTimeLimitedFgsType(sr.foregroundServiceType)
+                    != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
         } finally {
             mAm.mInjector.restoreCallingIdentity(ident);
         }
     }
 
+    void onFgsTimeout(ServiceRecord sr) {
+        synchronized (mAm) {
+            final int fgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
+            if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+                mFGSAnrTimer.discard(sr);
+                return;
+            }
+            Slog.e(TAG_SERVICE, "FGS (" + ServiceInfo.foregroundServiceTypeToLabel(fgsType)
+                    + ") timed out: " + sr);
+            mFGSAnrTimer.accept(sr);
+            traceInstant("FGS timed out: ", sr);
+
+            final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid);
+            if (fgsInfo != null) {
+                final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(fgsType);
+                if (fgsTypeInfo != null) {
+                    // Update total runtime for the time-limited fgs type and mark it as timed out.
+                    final long nowRealtime = SystemClock.elapsedRealtime();
+                    fgsTypeInfo.updateTotalRuntime();
+                    fgsTypeInfo.setTimeLimitExceededAt(nowRealtime);
+
+                    logFGSStateChangeLocked(sr,
+                            FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT,
+                            nowRealtime > fgsTypeInfo.getLastFgsStartTime()
+                                    ? (int) (nowRealtime - fgsTypeInfo.getLastFgsStartTime()) : 0,
+                            FGS_STOP_REASON_UNKNOWN,
+                            FGS_TYPE_POLICY_CHECK_UNKNOWN,
+                            FOREGROUND_SERVICE_STATE_CHANGED__FGS_START_API__FGSSTARTAPI_NA,
+                            false /* fgsRestrictionRecalculated */
+                    );
+                }
+            }
+
+            try {
+                sr.app.getThread().scheduleTimeoutServiceForType(sr, sr.getLastStartId(), fgsType);
+            } catch (RemoteException e) {
+                Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutServiceForType: " + e);
+            }
+
+            if (android.app.Flags.introduceNewServiceOntimeoutCallback()) {
+                // ANR the service after giving the service some time to clean up.
+                mFGSAnrTimer.start(sr, mAm.mConstants.mFgsAnrExtraWaitDuration);
+            }
+        }
+    }
+
     void onFgsAnrTimeout(ServiceRecord sr) {
-        final long nowUptime = SystemClock.uptimeMillis();
-        final int fgsType = sr.getTimedOutFgsType(nowUptime);
-        if (fgsType == -1 || !sr.wasFgsPreviouslyTimeLimited()) {
-            return; // no timed out FGS type was found
+        final int fgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
+        if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+            return; // no timed out FGS type was found (either it was stopped or it switched types)
         }
         final String reason = "A foreground service of type "
                 + ServiceInfo.foregroundServiceTypeToLabel(fgsType)
-                + " did not stop within a timeout: " + sr.getComponentName();
+                + " did not stop within its timeout: " + sr.getComponentName();
 
         final TimeoutRecord tr = TimeoutRecord.forFgsTimeout(reason);
-
         tr.mLatencyTracker.waitingOnAMSLockStarted();
         synchronized (mAm) {
             tr.mLatencyTracker.waitingOnAMSLockEnded();
@@ -5725,14 +5824,11 @@
                 bringDownServiceLocked(r, enqueueOomAdj);
                 return msg;
             }
-            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app, r,
-                    true);
+            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app,
+                    r);
             if (isolated) {
                 r.isolationHostProc = app;
             }
-        } else {
-            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app, r,
-                    false);
         }
 
         if (r.fgRequired) {
@@ -7328,7 +7424,6 @@
                     mActiveServiceAnrTimer.discard(proc);
                     return;
                 }
-                mActiveServiceAnrTimer.accept(proc);
                 final long now = SystemClock.uptimeMillis();
                 final long maxTime =  now
                         - (psr.shouldExecServicesFg()
@@ -7347,6 +7442,7 @@
                     }
                 }
                 if (timeout != null && mAm.mProcessList.isInLruListLOSP(proc)) {
+                    mActiveServiceAnrTimer.accept(proc);
                     Slog.w(TAG, "Timeout executing service: " + timeout);
                     StringWriter sw = new StringWriter();
                     PrintWriter pw = new FastPrintWriter(sw, false, 1024);
@@ -7361,6 +7457,7 @@
                     timeoutRecord = TimeoutRecord.forServiceExec(timeout.shortInstanceName,
                             waitedMillis);
                 } else {
+                    mActiveServiceAnrTimer.discard(proc);
                     final long delay = psr.shouldExecServicesFg()
                                        ? (nextTime + mAm.mConstants.SERVICE_TIMEOUT) :
                                        (nextTime + mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT)
@@ -7395,7 +7492,6 @@
                     return;
                 }
 
-                mServiceFGAnrTimer.accept(r);
                 app = r.app;
                 if (app != null && app.isDebugging()) {
                     // The app's being debugged; let it ride
@@ -7403,6 +7499,8 @@
                     return;
                 }
 
+                mServiceFGAnrTimer.accept(r);
+
                 if (DEBUG_BACKGROUND_CHECK) {
                     Slog.i(TAG, "Service foreground-required timeout for " + r);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b20135c..cf09cfb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -37,6 +37,9 @@
 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.RESTRICTION_LEVEL_FORCE_STOPPED;
+import static android.app.ActivityManager.RESTRICTION_REASON_DEFAULT;
+import static android.app.ActivityManager.RESTRICTION_REASON_USAGE;
 import static android.app.ActivityManager.StopUserOnSwitch;
 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN;
@@ -460,6 +463,7 @@
 import com.android.server.os.NativeTombstoneManager;
 import com.android.server.pm.Computer;
 import com.android.server.pm.Installer;
+import com.android.server.pm.PackageManagerServiceUtils;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
@@ -497,6 +501,10 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -629,13 +637,17 @@
     private static final int MAX_BUGREPORT_TITLE_SIZE = 100;
     private static final int MAX_BUGREPORT_DESCRIPTION_SIZE = 150;
 
+    private static final DateTimeFormatter DROPBOX_TIME_FORMATTER =
+            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSZ");
+
     OomAdjuster mOomAdjuster;
 
     static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION";
     static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE";
     static final String EXTRA_BUGREPORT_NONCE = "android.intent.extra.BUGREPORT_NONCE";
-
+    static final String EXTRA_EXTRA_ATTACHMENT_URI =
+            "android.intent.extra.EXTRA_ATTACHMENT_URI";
     /**
      * It is now required for apps to explicitly set either
      * {@link android.content.Context#RECEIVER_EXPORTED} or
@@ -677,8 +689,6 @@
 
     public final IntentFirewall mIntentFirewall;
 
-    public OomAdjProfiler mOomAdjProfiler = new OomAdjProfiler();
-
     /**
      * The global lock for AMS, it's de-facto the ActivityManagerService object as of now.
      */
@@ -724,6 +734,9 @@
     // Whether we should use SCHED_FIFO for UI and RenderThreads.
     final boolean mUseFifoUiScheduling;
 
+    /** Whether some specified important processes are allowed to use FIFO priority. */
+    boolean mAllowSpecifiedFifoScheduling = true;
+
     @GuardedBy("this")
     private final SparseArray<IUnsafeIntentStrictModeCallback>
             mStrictModeCallbacks = new SparseArray<>();
@@ -1047,6 +1060,10 @@
     @GuardedBy("this")
     final SparseArray<ImportanceToken> mImportantProcesses = new SparseArray<ImportanceToken>();
 
+    /** The processes that are allowed to use SCHED_FIFO prorioty. */
+    @GuardedBy("mProcLock")
+    final ArrayList<ProcessRecord> mSpecifiedFifoProcesses = new ArrayList<>();
+
     /**
      * List of records for processes that someone had tried to start before the
      * system was ready.  We don't start them at that point, but ensure they
@@ -2159,22 +2176,25 @@
      */
     static class VolatileDropboxEntryStates {
         private final Boolean mIsProcessFrozen;
+        private final ZonedDateTime mTimestamp;
 
-        private VolatileDropboxEntryStates(Boolean frozenState) {
+        private VolatileDropboxEntryStates(Boolean frozenState, ZonedDateTime timestamp) {
             this.mIsProcessFrozen = frozenState;
+            this.mTimestamp = timestamp;
         }
 
-        public static VolatileDropboxEntryStates withProcessFrozenState(boolean frozenState) {
-            return new VolatileDropboxEntryStates(frozenState);
-        }
-
-        public static VolatileDropboxEntryStates emptyVolatileDropboxEnytyStates() {
-            return new VolatileDropboxEntryStates(null);
+        public static VolatileDropboxEntryStates withProcessFrozenStateAndTimestamp(
+                boolean frozenState, ZonedDateTime timestamp) {
+            return new VolatileDropboxEntryStates(frozenState, timestamp);
         }
 
         public Boolean isProcessFrozen() {
             return mIsProcessFrozen;
         }
+
+        public ZonedDateTime getTimestamp() {
+            return mTimestamp;
+        }
     }
 
     static class MemBinder extends Binder {
@@ -2580,7 +2600,6 @@
                 BackgroundThread.getHandler(), this);
         mOnBattery = DEBUG_POWER ? true
                 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
-        mOomAdjProfiler.batteryPowerChanged(mOnBattery);
 
         mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
 
@@ -2829,13 +2848,12 @@
         updateCpuStatsNow();
         synchronized (mProcLock) {
             mOnBattery = DEBUG_POWER ? true : onBattery;
-            mOomAdjProfiler.batteryPowerChanged(onBattery);
         }
     }
 
     @Override
     public void batteryStatsReset() {
-        mOomAdjProfiler.reset();
+        // Empty for now.
     }
 
     @Override
@@ -4418,9 +4436,19 @@
                         packageName, null, userId);
         }
 
-        if (packageName == null || uninstalling || packageStateStopped) {
+        final boolean clearPendingIntentsForStoppedApp = (android.content.pm.Flags.stayStopped()
+                && packageStateStopped);
+        if (packageName == null || uninstalling || clearPendingIntentsForStoppedApp) {
+            final int cancelReason;
+            if (packageName == null) {
+                cancelReason = PendingIntentRecord.CANCEL_REASON_USER_STOPPED;
+            } else if (uninstalling) {
+                cancelReason = PendingIntentRecord.CANCEL_REASON_OWNER_UNINSTALLED;
+            } else {
+                cancelReason = PendingIntentRecord.CANCEL_REASON_OWNER_FORCE_STOPPED;
+            }
             didSomething |= mPendingIntentController.removePendingIntentsForPackage(
-                    packageName, userId, appId, doit);
+                    packageName, userId, appId, doit, cancelReason);
         }
 
         if (doit) {
@@ -5081,10 +5109,19 @@
                 } // else, stopped packages in private space may still hit the logic below
             }
         }
+
+        final boolean wasForceStopped = app.wasForceStopped()
+                || app.getWindowProcessController().wasForceStopped();
+        if (android.app.Flags.appRestrictionsApi() && wasForceStopped) {
+            noteAppRestrictionEnabled(app.info.packageName, app.uid,
+                    RESTRICTION_LEVEL_FORCE_STOPPED, false,
+                    RESTRICTION_REASON_USAGE, "unknown", 0L);
+        }
+
         if (!sendBroadcast) {
             if (!android.content.pm.Flags.stayStopped()) return;
             // Nothing to do if it wasn't previously stopped
-            if (!app.wasForceStopped() && !app.getWindowProcessController().wasForceStopped()) {
+            if (!wasForceStopped) {
                 return;
             }
         }
@@ -5389,14 +5426,12 @@
         }
     }
 
-    /**
-     * Checks if feature flag is enabled and if system is Headless (HSUM), case in which 
-     * home delay should be skipped.
-     *
-     * @hide
-     */
-    public boolean isHomeLaunchDelayable() {
-        return !UserManager.isHeadlessSystemUserMode() && enableHomeDelay();
+    /** Checks whether the home launch delay feature is enabled. */
+    private boolean isHomeLaunchDelayable() {
+        // This feature is disabled on Auto since it seems to add an unacceptably long boot delay
+        // without even solving the underlying issue (it merely hits the timeout).
+        return enableHomeDelay() &&
+                !mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
     }
 
     final void ensureBootCompleted() {
@@ -7393,7 +7428,6 @@
                 mServices.updateScreenStateLocked(isAwake);
                 reportCurWakefulnessUsageEvent();
                 mActivityTaskManager.onScreenAwakeChanged(isAwake);
-                mOomAdjProfiler.onWakefulnessChanged(wakefulness);
                 mOomAdjuster.onWakefulnessChanged(wakefulness);
 
                 updateOomAdjLocked(OOM_ADJ_REASON_UI_VISIBILITY);
@@ -7654,6 +7688,16 @@
      */
     public void requestBugReportWithDescription(@Nullable String shareTitle,
             @Nullable String shareDescription, int bugreportType, long nonce) {
+        requestBugReportWithDescription(shareTitle, shareDescription, bugreportType, nonce, null);
+    }
+
+    /**
+     * Takes a bugreport using bug report API ({@code BugreportManager}) which gets
+     * triggered by sending a broadcast to Shell. Optionally adds an extra attachment.
+     */
+    public void requestBugReportWithDescription(@Nullable String shareTitle,
+            @Nullable String shareDescription, int bugreportType, long nonce,
+            @Nullable Uri extraAttachment) {
         String type = null;
         switch (bugreportType) {
             case BugreportParams.BUGREPORT_MODE_FULL:
@@ -7708,6 +7752,10 @@
         triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
         triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
         triggerShellBugreport.putExtra(EXTRA_BUGREPORT_NONCE, nonce);
+        if (extraAttachment != null) {
+            triggerShellBugreport.putExtra(EXTRA_EXTRA_ATTACHMENT_URI, extraAttachment);
+            triggerShellBugreport.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        }
         triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         if (shareTitle != null) {
@@ -7761,6 +7809,15 @@
     }
 
     /**
+     * Takes an interactive bugreport with a progress notification. Also attaches given file uri.
+     */
+    @Override
+    public void requestBugReportWithExtraAttachment(@NonNull Uri extraAttachment) {
+        requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_INTERACTIVE, 0L,
+                extraAttachment);
+    }
+
+    /**
      * Takes an interactive bugreport with a progress notification. Also, shows the given title and
      * description on the final share notification
      */
@@ -8218,6 +8275,27 @@
         return false;
     }
 
+    /**
+     * Switches the priority between SCHED_FIFO and SCHED_OTHER for the main thread and render
+     * thread of the given process.
+     */
+    @GuardedBy("mProcLock")
+    static void setFifoPriority(@NonNull ProcessRecord app, boolean enable) {
+        final int pid = app.getPid();
+        final int renderThreadTid = app.getRenderThreadTid();
+        if (enable) {
+            scheduleAsFifoPriority(pid, true /* suppressLogs */);
+            if (renderThreadTid != 0) {
+                scheduleAsFifoPriority(renderThreadTid, true /* suppressLogs */);
+            }
+        } else {
+            scheduleAsRegularPriority(pid, true /* suppressLogs */);
+            if (renderThreadTid != 0) {
+                scheduleAsRegularPriority(renderThreadTid, true /* suppressLogs */);
+            }
+        }
+    }
+
     @Override
     public void setRenderThread(int tid) {
         synchronized (mProcLock) {
@@ -8243,7 +8321,7 @@
                 // promote to FIFO now
                 if (proc.mState.getCurrentSchedulingGroup() == ProcessList.SCHED_GROUP_TOP_APP) {
                     if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
-                    if (mUseFifoUiScheduling) {
+                    if (proc.useFifoUiScheduling()) {
                         setThreadScheduler(proc.getRenderThreadTid(),
                                 SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
                     } else {
@@ -8881,8 +8959,10 @@
                     com.android.internal.R.integer.config_multiuserMaxRunningUsers);
             final boolean delayUserDataLocking = res.getBoolean(
                     com.android.internal.R.bool.config_multiuserDelayUserDataLocking);
+            final int backgroundUserScheduledStopTimeSecs = res.getInteger(
+                    com.android.internal.R.integer.config_backgroundUserScheduledStopTimeSecs);
             mUserController.setInitialConfig(userSwitchUiEnabled, maxRunningUsers,
-                    delayUserDataLocking);
+                    delayUserDataLocking, backgroundUserScheduledStopTimeSecs);
         }
         mAppErrors.loadAppsNotReportingCrashesFromConfig(res.getString(
                 com.android.internal.R.string.config_appsNotReportingCrashes));
@@ -9119,6 +9199,11 @@
     private class MyBinderProxyCountEventListener implements BinderProxyCountEventListener {
         @Override
         public void onLimitReached(int uid) {
+            // Spawn a new thread for the dump as it'll take long time.
+            new Thread(() -> handleLimitReached(uid), "BinderProxy Dump: " + uid).start();
+        }
+
+        private void handleLimitReached(int uid) {
             Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
                     + Process.myUid());
             BinderProxy.dumpProxyDebugInfo();
@@ -9624,6 +9709,11 @@
                     ? volatileStates.isProcessFrozen() : process.mOptRecord.isFrozen()
                 ).append("\n");
             }
+            if (volatileStates != null && volatileStates.getTimestamp() != null) {
+                String formattedTime = DROPBOX_TIME_FORMATTER.format(
+                    volatileStates.getTimestamp());
+                sb.append("Timestamp: ").append(formattedTime).append("\n");
+            }
             int flags = process.info.flags;
             final IPackageManager pm = AppGlobals.getPackageManager();
             sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
@@ -9767,6 +9857,11 @@
                 sb.append("Process-Runtime: ").append(runtimeMillis).append("\n");
             }
         }
+        if (eventType.equals("crash")) {
+            String formattedTime = DROPBOX_TIME_FORMATTER.format(
+                    Instant.now().atZone(ZoneId.systemDefault()));
+            sb.append("Timestamp: ").append(formattedTime).append("\n");
+        }
         if (activityShortComponentName != null) {
             sb.append("Activity: ").append(activityShortComponentName).append("\n");
         }
@@ -10100,7 +10195,11 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        mProcessList.getAppStartInfoTracker().addStartInfoCompleteListener(listener, callingUid);
+        mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, true,
+                ALLOW_NON_FULL, "addApplicationStartInfoCompleteListener", null);
+
+        mProcessList.getAppStartInfoTracker().addStartInfoCompleteListener(listener,
+                UserHandle.getUid(userId, UserHandle.getAppId(callingUid)));
     }
 
 
@@ -10115,13 +10214,30 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        mProcessList.getAppStartInfoTracker().removeStartInfoCompleteListener(listener, callingUid,
-                true);
+        mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, true,
+                ALLOW_NON_FULL, "removeApplicationStartInfoCompleteListener", null);
+
+        mProcessList.getAppStartInfoTracker().removeStartInfoCompleteListener(listener,
+                UserHandle.getUid(userId, UserHandle.getAppId(callingUid)), true);
     }
 
     @Override
     public void addStartInfoTimestamp(int key, long timestampNs, int userId) {
         enforceNotIsolatedCaller("addStartInfoTimestamp");
+
+        // For the simplification, we don't support USER_ALL nor USER_CURRENT here.
+        if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_CURRENT) {
+            throw new IllegalArgumentException("Unsupported userId");
+        }
+
+        final int callingUid = Binder.getCallingUid();
+        mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, true,
+                ALLOW_NON_FULL, "addStartInfoTimestamp", null);
+
+        final String packageName = Settings.getPackageNameForUid(mContext, callingUid);
+
+        mProcessList.getAppStartInfoTracker().addTimestampToStart(packageName,
+                UserHandle.getUid(userId, UserHandle.getAppId(callingUid)), timestampNs, key);
     }
 
     @Override
@@ -10443,12 +10559,6 @@
                     pw.println(
                             "-------------------------------------------------------------------------------");
                 }
-                mOomAdjProfiler.dump(pw);
-                pw.println();
-                if (dumpAll) {
-                    pw.println(
-                            "-------------------------------------------------------------------------------");
-                }
                 dumpLmkLocked(pw);
             }
             pw.println();
@@ -11280,6 +11390,9 @@
             if (mAlwaysFinishActivities) {
                 pw.println("  mAlwaysFinishActivities=" + mAlwaysFinishActivities);
             }
+            if (mAllowSpecifiedFifoScheduling) {
+                pw.println("  mAllowSpecifiedFifoScheduling=true");
+            }
             if (dumpAll) {
                 pw.println("  Total persistent processes: " + numPers);
                 pw.println("  mProcessesReady=" + mProcessesReady
@@ -13739,6 +13852,8 @@
             // Goodbye!
             removePidLocked(pid, app);
             mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+            mHandler.removeMessages(BIND_APPLICATION_TIMEOUT_SOFT_MSG, app);
+            mHandler.removeMessages(BIND_APPLICATION_TIMEOUT_HARD_MSG, app);
             mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
             if (app.isolated) {
                 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
@@ -14229,6 +14344,20 @@
         int newBackupUid;
 
         synchronized(this) {
+            if (android.app.Flags.appRestrictionsApi()) {
+                try {
+                    final boolean wasStopped = mPackageManagerInt.isPackageStopped(app.packageName,
+                            UserHandle.getUserId(app.uid));
+                    if (wasStopped) {
+                        noteAppRestrictionEnabled(app.packageName, app.uid,
+                                RESTRICTION_LEVEL_FORCE_STOPPED, false,
+                                RESTRICTION_REASON_DEFAULT, "restore", 0L);
+                    }
+                } catch (NameNotFoundException e) {
+                    Slog.w(TAG, "No such package", e);
+                }
+            }
+
             // !!! TODO: currently no check here that we're already bound
             // Backup agent is now in use, its package can't be stopped.
             try {
@@ -14477,6 +14606,53 @@
     public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
             String callerFeatureId, String receiverId, IIntentReceiver receiver,
             IntentFilter filter, String permission, int userId, int flags) {
+        traceRegistrationBegin(receiverId, receiver, filter, userId);
+        try {
+            return registerReceiverWithFeatureTraced(caller, callerPackage, callerFeatureId,
+                    receiverId, receiver, filter, permission, userId, flags);
+        } finally {
+            traceRegistrationEnd();
+        }
+    }
+
+    private static void traceRegistrationBegin(String receiverId, IIntentReceiver receiver,
+            IntentFilter filter, int userId) {
+        if (!Flags.traceReceiverRegistration()) {
+            return;
+        }
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            final StringBuilder sb = new StringBuilder("registerReceiver: ");
+            sb.append(Binder.getCallingUid()); sb.append('/');
+            sb.append(receiverId == null ? "null" : receiverId); sb.append('/');
+            final int actionsCount = filter.countActions();
+            if (actionsCount > 0) {
+                for (int i = 0; i < actionsCount; ++i) {
+                    sb.append(filter.getAction(i));
+                    if (i != actionsCount - 1) sb.append(',');
+                }
+            } else {
+                sb.append("null");
+            }
+            sb.append('/');
+            sb.append('u'); sb.append(userId); sb.append('/');
+            sb.append(receiver == null ? "null" : receiver.asBinder());
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, sb.toString());
+        }
+    }
+
+    private static void traceRegistrationEnd() {
+        if (!Flags.traceReceiverRegistration()) {
+            return;
+        }
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        }
+    }
+
+    private Intent registerReceiverWithFeatureTraced(IApplicationThread caller,
+            String callerPackage, String callerFeatureId, String receiverId,
+            IIntentReceiver receiver, IntentFilter filter, String permission,
+            int userId, int flags) {
         enforceNotIsolatedCaller("registerReceiver");
         ArrayList<StickyBroadcast> stickyBroadcasts = null;
         ProcessRecord callerApp = null;
@@ -14792,6 +14968,35 @@
     }
 
     public void unregisterReceiver(IIntentReceiver receiver) {
+        traceUnregistrationBegin(receiver);
+        try {
+            unregisterReceiverTraced(receiver);
+        } finally {
+            traceUnregistrationEnd();
+        }
+    }
+
+    private static void traceUnregistrationBegin(IIntentReceiver receiver) {
+        if (!Flags.traceReceiverRegistration()) {
+            return;
+        }
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                    TextUtils.formatSimple("unregisterReceiver: %d/%s", Binder.getCallingUid(),
+                            receiver == null ? "null" : receiver.asBinder()));
+        }
+    }
+
+    private static void traceUnregistrationEnd() {
+        if (!Flags.traceReceiverRegistration()) {
+            return;
+        }
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        }
+    }
+
+    private void unregisterReceiverTraced(IIntentReceiver receiver) {
         if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Unregister receiver: " + receiver);
 
         final long origId = Binder.clearCallingIdentity();
@@ -15376,6 +15581,7 @@
                                             intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME));
                                 } else {
                                     mAppOpsService.uidRemoved(uid);
+                                    mServices.onUidRemovedLocked(uid);
                                 }
                             }
                             break;
@@ -15749,6 +15955,11 @@
                 registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
                         resolvedType, false /*defaultOnly*/, userId);
             }
+            if (registeredReceivers != null) {
+                PackageManagerServiceUtils.applyNullActionBlocking(
+                        mPlatformCompat, snapshot, registeredReceivers,
+                        true, intent, callingUid);
+            }
         }
         BroadcastQueue.traceEnd(cookie);
 
@@ -17348,6 +17559,12 @@
                 }
             }
         }
+
+        if (com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses()) {
+            synchronized (mProcLock) {
+                adjustFifoProcessesIfNeeded(uid, !active /* allowFifo */);
+            }
+        }
     }
 
     final boolean isCameraActiveForUid(@UserIdInt int uid) {
@@ -17356,6 +17573,34 @@
         }
     }
 
+    /**
+     * This is called when the given uid is using camera. If the uid has top process state, then
+     * cancel the FIFO priority of the high priority processes.
+     */
+    @VisibleForTesting
+    @GuardedBy("mProcLock")
+    void adjustFifoProcessesIfNeeded(int preemptiveUid, boolean allowSpecifiedFifo) {
+        if (allowSpecifiedFifo == mAllowSpecifiedFifoScheduling) {
+            return;
+        }
+        if (!allowSpecifiedFifo) {
+            final UidRecord uidRec = mProcessList.mActiveUids.get(preemptiveUid);
+            if (uidRec == null || uidRec.getCurProcState() > PROCESS_STATE_TOP) {
+                // To avoid frequent switching by background camera usages, e.g. face unlock,
+                // face detection (auto rotation), screen attention (keep screen on).
+                return;
+            }
+        }
+        mAllowSpecifiedFifoScheduling = allowSpecifiedFifo;
+        for (int i = mSpecifiedFifoProcesses.size() - 1; i >= 0; i--) {
+            final ProcessRecord proc = mSpecifiedFifoProcesses.get(i);
+            if (proc.mState.getSetSchedGroup() != ProcessList.SCHED_GROUP_TOP_APP) {
+                continue;
+            }
+            setFifoPriority(proc, allowSpecifiedFifo /* enable */);
+        }
+    }
+
     @GuardedBy("this")
     final void doStopUidLocked(int uid, final UidRecord uidRec) {
         mServices.stopInBackgroundLocked(uid);
@@ -17622,7 +17867,8 @@
 
     @Override
     public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
-            boolean runGc, String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
+            boolean runGc, String dumpBitmaps,
+            String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
         try {
             // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
             // its own permission (same as profileControl).
@@ -17656,7 +17902,8 @@
                         }
                     }, null);
 
-                thread.dumpHeap(managed, mallocInfo, runGc, path, fd, intermediateCallback);
+                thread.dumpHeap(managed, mallocInfo, runGc, dumpBitmaps,
+                                path, fd, intermediateCallback);
                 fd = null;
                 return true;
             }
@@ -17868,9 +18115,35 @@
         mUserController.setStopUserOnSwitch(value);
     }
 
+    /** @deprecated use {@link #stopUserWithCallback(int, IStopUserCallback)} instead */
+    @Deprecated
     @Override
-    public int stopUser(final int userId, boolean force, final IStopUserCallback callback) {
-        return mUserController.stopUser(userId, force, /* allowDelayedLocking= */ false,
+    public int stopUser(final int userId,
+            boolean stopProfileRegardlessOfParent, final IStopUserCallback callback) {
+        return stopUserExceptCertainProfiles(userId, stopProfileRegardlessOfParent, callback);
+    }
+
+    /** Stops the given user. */
+    @Override
+    public int stopUserWithCallback(@UserIdInt int userId, @Nullable IStopUserCallback callback) {
+        return mUserController.stopUser(userId, /* allowDelayedLocking= */ false,
+                /* callback= */ callback, /* keyEvictedCallback= */ null);
+    }
+
+    /**
+     * Stops the given user.
+     *
+     * Usually, callers can just use @link{#stopUserWithCallback(int, IStopUserCallback)} instead.
+     *
+     * @param stopProfileRegardlessOfParent whether to stop the profile regardless of who its
+     *                                      parent is, e.g. even if the parent is the current user;
+     *                                      its value is irrelevant for non-profile users.
+     */
+    @Override
+    public int stopUserExceptCertainProfiles(@UserIdInt int userId,
+            boolean stopProfileRegardlessOfParent, @Nullable IStopUserCallback callback) {
+        return mUserController.stopUser(userId,
+                stopProfileRegardlessOfParent, /* allowDelayedLocking= */ false,
                 /* callback= */ callback, /* keyEvictedCallback= */ null);
     }
 
@@ -17879,11 +18152,9 @@
      * stopping only if {@code config_multiuserDelayUserDataLocking} overlay is set true.
      *
      * <p>When delayed locking is not enabled through the overlay, this call becomes the same
-     * with {@link #stopUser(int, boolean, IStopUserCallback)} call.
+     * with {@link #stopUserWithCallback(int, IStopUserCallback)} call.
      *
      * @param userId User id to stop.
-     * @param force Force stop the user even if the user is related with system user or current
-     *              user.
      * @param callback Callback called when user has stopped.
      *
      * @return {@link ActivityManager#USER_OP_SUCCESS} when user is stopped successfully. Returns
@@ -17893,9 +18164,8 @@
     // TODO(b/302662311): Add javadoc changes corresponding to the user property that allows
     // delayed locking behavior once the private space flag is finalized.
     @Override
-    public int stopUserWithDelayedLocking(final int userId, boolean force,
-            final IStopUserCallback callback) {
-        return mUserController.stopUser(userId, force, /* allowDelayedLocking= */ true,
+    public int stopUserWithDelayedLocking(@UserIdInt int userId, IStopUserCallback callback) {
+        return mUserController.stopUser(userId, /* allowDelayedLocking= */ true,
                 /* callback= */ callback, /* keyEvictedCallback= */ null);
     }
 
@@ -19955,6 +20225,34 @@
     }
 
     /**
+     * Log the reason for changing an app restriction. Purely used for logging purposes and does not
+     * cause any change to app state.
+     *
+     * @see ActivityManager#noteAppRestrictionEnabled(String, int, int, boolean, int, String, long)
+     */
+    @Override
+    public void noteAppRestrictionEnabled(String packageName, int uid,
+            @RestrictionLevel int restrictionType, boolean enabled,
+            @ActivityManager.RestrictionReason int reason, String subReason, long threshold) {
+        if (!android.app.Flags.appRestrictionsApi()) return;
+
+        enforceCallingPermission(android.Manifest.permission.DEVICE_POWER,
+                "noteAppRestrictionEnabled()");
+
+        final int userId = UserHandle.getCallingUserId();
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            if (uid == -1) {
+                uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
+            }
+            mAppRestrictionController.noteAppRestrictionEnabled(packageName, uid, restrictionType,
+                    enabled, reason, subReason, threshold);
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
+    /**
      * Get an app's background restriction level.
      * This interface is intended for the shell command to use.
      */
@@ -20483,7 +20781,7 @@
 
         /** @see Binder#getCallingPid */
         public int getCallingPid() {
-            return Binder.getCallingUid();
+            return Binder.getCallingPid();
         }
 
         /** @see Binder#clearCallingIdentity */
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 5a97e87..bf4f34fd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -97,6 +97,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.IProgressListener;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteCallback;
@@ -125,6 +126,8 @@
 import com.android.server.am.LowMemDetector.MemFactor;
 import com.android.server.am.nano.Capabilities;
 import com.android.server.am.nano.Capability;
+import com.android.server.am.nano.FrameworkCapability;
+import com.android.server.am.nano.VMCapability;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.utils.Slogf;
@@ -171,6 +174,8 @@
     private static final DateTimeFormatter LOG_NAME_TIME_FORMATTER =
             DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss", Locale.ROOT);
 
+    private static final String PROFILER_OUTPUT_VERSION_FLAG = "--profiler-output-version";
+
     // IPC interface to activity manager -- don't need to do additional security checks.
     final IActivityManager mInterface;
     final IActivityTaskManager mTaskInterface;
@@ -196,6 +201,7 @@
     private String mAgent;  // Agent to attach on startup.
     private boolean mAttachAgentDuringBind;  // Whether agent should be attached late.
     private int mClockType; // Whether we need thread cpu / wall clock / both.
+    private int mProfilerOutputVersion; // The version of the profiler output.
     private int mDisplayId;
     private int mTaskDisplayAreaFeatureId;
     private int mWindowingMode;
@@ -443,6 +449,22 @@
                 capabilities.values[i] = cap;
             }
 
+            String[] vmCapabilities = Debug.getVmFeatureList();
+            capabilities.vmCapabilities = new VMCapability[vmCapabilities.length];
+            for (int i = 0; i < vmCapabilities.length; i++) {
+                VMCapability cap = new VMCapability();
+                cap.name = vmCapabilities[i];
+                capabilities.vmCapabilities[i] = cap;
+            }
+
+            String[] fmCapabilities = Debug.getFeatureList();
+            capabilities.frameworkCapabilities = new FrameworkCapability[fmCapabilities.length];
+            for (int i = 0; i < fmCapabilities.length; i++) {
+                FrameworkCapability cap = new FrameworkCapability();
+                cap.name = fmCapabilities[i];
+                capabilities.frameworkCapabilities[i] = cap;
+            }
+
             try {
                 getRawOutputStream().write(Capabilities.toByteArray(capabilities));
             } catch (IOException e) {
@@ -452,10 +474,16 @@
         } else {
             // Unfortunately we don't have protobuf text format capabilities here.
             // Fallback to line separated list instead for text parser.
-            pw.println("Format: 1");
+            pw.println("Format: 2");
             for (String capability : CAPABILITIES) {
                 pw.println(capability);
             }
+            for (String capability : Debug.getVmFeatureList()) {
+                pw.println("vm:" + capability);
+            }
+            for (String capability : Debug.getFeatureList()) {
+                pw.println("framework:" + capability);
+            }
         }
         return 0;
     }
@@ -502,6 +530,8 @@
                 } else if (opt.equals("--clock-type")) {
                     String clock_type = getNextArgRequired();
                     mClockType = ProfilerInfo.getClockTypeFromString(clock_type);
+                } else if (opt.equals(PROFILER_OUTPUT_VERSION_FLAG)) {
+                    mProfilerOutputVersion = Integer.parseInt(getNextArgRequired());
                 } else if (opt.equals("--streaming")) {
                     mStreaming = true;
                 } else if (opt.equals("--attach-agent")) {
@@ -554,7 +584,7 @@
                 } else if (opt.equals("--splashscreen-show-icon")) {
                     mShowSplashScreen = true;
                 } else if (opt.equals("--dismiss-keyguard-if-insecure")
-                      || opt.equals("--dismiss-keyguard")) {
+                        || opt.equals("--dismiss-keyguard")) {
                     mDismissKeyguardIfInsecure = true;
                 } else if (opt.equals("--allow-fgs-start-reason")) {
                     final int reasonCode = Integer.parseInt(getNextArgRequired());
@@ -667,8 +697,9 @@
                         return 1;
                     }
                 }
-                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
-                        mStreaming, mAgent, mAttachAgentDuringBind, mClockType);
+                profilerInfo =
+                        new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, mStreaming,
+                                mAgent, mAttachAgentDuringBind, mClockType, mProfilerOutputVersion);
             }
 
             pw.println("Starting: " + intent);
@@ -1011,6 +1042,7 @@
         mSamplingInterval = 0;
         mStreaming = false;
         mClockType = ProfilerInfo.CLOCK_TYPE_DEFAULT;
+        mProfilerOutputVersion = ProfilerInfo.OUTPUT_VERSION_DEFAULT;
 
         String process = null;
 
@@ -1025,6 +1057,8 @@
                 } else if (opt.equals("--clock-type")) {
                     String clock_type = getNextArgRequired();
                     mClockType = ProfilerInfo.getClockTypeFromString(clock_type);
+                } else if (opt.equals(PROFILER_OUTPUT_VERSION_FLAG)) {
+                    mProfilerOutputVersion = Integer.parseInt(getNextArgRequired());
                 } else if (opt.equals("--streaming")) {
                     mStreaming = true;
                 } else if (opt.equals("--sampling")) {
@@ -1072,7 +1106,7 @@
                 return -1;
             }
             profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming,
-                    null, false, mClockType);
+                    null, false, mClockType, mProfilerOutputVersion);
         }
 
         if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
@@ -1239,6 +1273,7 @@
         final PrintWriter err = getErrPrintWriter();
         boolean managed = true;
         boolean mallocInfo = false;
+        String dumpBitmaps = null;
         int userId = UserHandle.USER_CURRENT;
         boolean runGc = false;
 
@@ -1257,6 +1292,11 @@
             } else if (opt.equals("-m")) {
                 managed = false;
                 mallocInfo = true;
+            } else if (opt.equals("-b")) {
+                dumpBitmaps = getNextArg();
+                if (dumpBitmaps == null) {
+                    dumpBitmaps = "png"; // default to PNG in dumping bitmaps
+                }
             } else {
                 err.println("Error: Unknown option: " + opt);
                 return -1;
@@ -1288,8 +1328,8 @@
             }
         }, null);
 
-        if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, heapFile, fd,
-                finishCallback)) {
+        if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, dumpBitmaps,
+                heapFile, fd, finishCallback)) {
             err.println("HEAP DUMP FAILED on process " + process);
             return -1;
         }
@@ -2554,7 +2594,8 @@
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                 "shell_runStopUser-" + userId + "-[stopUser]");
         try {
-            int res = mInterface.stopUser(userId, force, callback);
+            int res = mInterface.stopUserExceptCertainProfiles(
+                    userId, /* stopProfileRegardlessOfParent= */ force, callback);
             if (res != ActivityManager.USER_OP_SUCCESS) {
                 String txt = "";
                 switch (res) {
@@ -3974,8 +4015,12 @@
                 return ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
             case "background_restricted":
                 return ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
-            case "hibernation":
-                return ActivityManager.RESTRICTION_LEVEL_HIBERNATION;
+            case "force_stopped":
+                return ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED;
+            case "user_launch_only":
+                return ActivityManager.RESTRICTION_LEVEL_USER_LAUNCH_ONLY;
+            case "custom":
+                return ActivityManager.RESTRICTION_LEVEL_CUSTOM;
             default:
                 return ActivityManager.RESTRICTION_LEVEL_UNKNOWN;
         }
@@ -4160,6 +4205,7 @@
             pw.println("      Print this help text.");
             pw.println("  start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
             pw.println("          [--sampling INTERVAL] [--clock-type <TYPE>] [--streaming]");
+            pw.println("          [" + PROFILER_OUTPUT_VERSION_FLAG + " NUMBER]");
             pw.println("          [-R COUNT] [-S] [--track-allocation]");
             pw.println("          [--user <USER_ID> | current] [--suspend] <INTENT>");
             pw.println("      Start an Activity.  Options are:");
@@ -4175,6 +4221,8 @@
             pw.println("          The default value is dual. (use with --start-profiler)");
             pw.println("      --streaming: stream the profiling output to the specified file");
             pw.println("          (use with --start-profiler)");
+            pw.println("      " + PROFILER_OUTPUT_VERSION_FLAG + " Specify the version of the");
+            pw.println("          profiling output (use with --start-profiler)");
             pw.println("      -P <FILE>: like above, but profiling stops when app goes idle");
             pw.println("      --attach-agent <agent>: attach the given agent before binding");
             pw.println("      --attach-agent-bind <agent>: attach the given agent during binding");
@@ -4266,6 +4314,7 @@
             pw.println("      --dump-file <FILE>: Specify the file the trace should be dumped to.");
             pw.println("  profile start [--user <USER_ID> current]");
             pw.println("          [--clock-type <TYPE>]");
+            pw.println("          [" + PROFILER_OUTPUT_VERSION_FLAG + " VERSION]");
             pw.println("          [--sampling INTERVAL | --streaming] <PROCESS> <FILE>");
             pw.println("      Start profiler on a process.  The given <PROCESS> argument");
             pw.println("        may be either a process name or pid.  Options are:");
@@ -4275,6 +4324,8 @@
             pw.println("      --clock-type <TYPE>: use the specified clock to report timestamps.");
             pw.println("          The type can be one of wall | thread-cpu | dual. The default");
             pw.println("          value is dual.");
+            pw.println("      " + PROFILER_OUTPUT_VERSION_FLAG + "VERSION: specifies the output");
+            pw.println("          format version");
             pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
             pw.println("          between samples.");
             pw.println("      --streaming: stream the profiling output to the specified file.");
@@ -4284,11 +4335,14 @@
             pw.println("      --user <USER_ID> | current: When supplying a process name,");
             pw.println("          specify user of process to profile; uses current user if not");
             pw.println("          specified.");
-            pw.println("  dumpheap [--user <USER_ID> current] [-n] [-g] <PROCESS> <FILE>");
+            pw.println("  dumpheap [--user <USER_ID> current] [-n] [-g] [-b <format>] ");
+            pw.println("           <PROCESS> <FILE>");
             pw.println("      Dump the heap of a process.  The given <PROCESS> argument may");
             pw.println("        be either a process name or pid.  Options are:");
             pw.println("      -n: dump native heap instead of managed heap");
             pw.println("      -g: force GC before dumping the heap");
+            pw.println("      -b <format>: dump contents of bitmaps in the format specified,");
+            pw.println("         which can be \"png\", \"jpg\" or \"webp\".");
             pw.println("      --user <USER_ID> | current: When supplying a process name,");
             pw.println("          specify user of process to dump; uses current user if not specified.");
             pw.println("  set-debug-app [-w] [--persistent] <PACKAGE>");
@@ -4385,7 +4439,7 @@
             pw.println("      Stop execution of USER_ID, not allowing it to run any");
             pw.println("      code until a later explicit start or switch to it.");
             pw.println("      -w: wait for stop-user to complete.");
-            pw.println("      -f: force stop even if there are related users that cannot be stopped.");
+            pw.println("      -f: force stop, even if user has an unstoppable parent.");
             pw.println("  is-user-stopped <USER_ID>");
             pw.println("      Returns whether <USER_ID> has been stopped or not.");
             pw.println("  get-started-user-state <USER_ID>");
diff --git a/services/core/java/com/android/server/am/Android.bp b/services/core/java/com/android/server/am/Android.bp
index af1200e..0294ffe 100644
--- a/services/core/java/com/android/server/am/Android.bp
+++ b/services/core/java/com/android/server/am/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "am_flags",
     package: "com.android.server.am",
+    container: "system",
     srcs: ["*.aconfig"],
 }
 
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 51aae77..dda48ad 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1051,7 +1051,9 @@
                                     + mProfile.mApp + " to " + mDumpUri.getPath());
                         }
                         thread.dumpHeap(/* managed= */ true,
-                                /* mallocInfo= */ false, /* runGc= */ false,
+                                /* mallocInfo= */ false,
+                                /* runGc= */ false,
+                                /* dumpbitmaps= */ null,
                                 mDumpUri.getPath(), fd,
                                 /* finishCallback= */ null);
                     } catch (RemoteException e) {
@@ -2412,8 +2414,8 @@
                     }
                 }
             } else if (instr != null && instr.mProfileFile != null) {
-                profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
-                        null, false, 0);
+                profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false, null,
+                        false, 0, ProfilerInfo.OUTPUT_VERSION_DEFAULT);
             }
             if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
                 // We need to do a debuggable check here. See setAgentApp for why the check is
@@ -2423,7 +2425,8 @@
                     // Do not overwrite already requested agent.
                     if (profilerInfo == null) {
                         profilerInfo = new ProfilerInfo(null, null, 0, false, false,
-                                mAppAgentMap.get(processName), true, 0);
+                                mAppAgentMap.get(processName), true, 0,
+                                ProfilerInfo.OUTPUT_VERSION_DEFAULT);
                     } else if (profilerInfo.agent == null) {
                         profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
                     }
@@ -2550,14 +2553,16 @@
                 if (mProfileData.getProfilerInfo() != null) {
                     pw.println("  mProfileFile=" + mProfileData.getProfilerInfo().profileFile
                             + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
-                    pw.println("  mSamplingInterval="
-                            + mProfileData.getProfilerInfo().samplingInterval
+                    pw.println(
+                            "  mSamplingInterval=" + mProfileData.getProfilerInfo().samplingInterval
                             + " mAutoStopProfiler="
                             + mProfileData.getProfilerInfo().autoStopProfiler
                             + " mStreamingOutput="
                             + mProfileData.getProfilerInfo().streamingOutput
                             + " mClockType="
-                            + mProfileData.getProfilerInfo().clockType);
+                            + mProfileData.getProfilerInfo().clockType
+                            + " mProfilerOutputVersion="
+                            + mProfileData.getProfilerInfo().profilerOutputVersion);
                     pw.println("  mProfileType=" + mProfileType);
                 }
             }
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 8b1300b..c5cad14 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -23,11 +23,20 @@
 import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_EXEMPTED;
-import static android.app.ActivityManager.RESTRICTION_LEVEL_HIBERNATION;
+import static android.app.ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_MAX;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_UNKNOWN;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_UNRESTRICTED;
+import static android.app.ActivityManager.RESTRICTION_LEVEL_USER_LAUNCH_ONLY;
+import static android.app.ActivityManager.RESTRICTION_REASON_DEFAULT;
+import static android.app.ActivityManager.RESTRICTION_REASON_DORMANT;
+import static android.app.ActivityManager.RESTRICTION_REASON_REMOTE_TRIGGER;
+import static android.app.ActivityManager.RESTRICTION_REASON_SYSTEM_HEALTH;
+import static android.app.ActivityManager.RESTRICTION_REASON_USAGE;
+import static android.app.ActivityManager.RESTRICTION_REASON_USER;
+import static android.app.ActivityManager.RESTRICTION_REASON_USER_NUDGED;
+import static android.app.ActivityManager.RESTRICTION_SUBREASON_MAX_LENGTH;
 import static android.app.ActivityManager.UID_OBSERVER_ACTIVE;
 import static android.app.ActivityManager.UID_OBSERVER_GONE;
 import static android.app.ActivityManager.UID_OBSERVER_IDLE;
@@ -93,6 +102,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RestrictionLevel;
+import android.app.ActivityManager.RestrictionReason;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener;
 import android.app.AppOpsManager;
@@ -334,6 +344,8 @@
 
     final ActivityManagerService mActivityManagerService;
 
+    private volatile boolean mLockedBootCompleted = false;
+
     static final int TRACKER_TYPE_UNKNOWN = 0;
     static final int TRACKER_TYPE_BATTERY = 1;
     static final int TRACKER_TYPE_BATTERY_EXEMPTION = 2;
@@ -342,6 +354,7 @@
     static final int TRACKER_TYPE_PERMISSION = 5;
     static final int TRACKER_TYPE_BROADCAST_EVENTS = 6;
     static final int TRACKER_TYPE_BIND_SERVICE_EVENTS = 7;
+
     @IntDef(prefix = { "TRACKER_TYPE_" }, value = {
             TRACKER_TYPE_UNKNOWN,
             TRACKER_TYPE_BATTERY,
@@ -1712,7 +1725,7 @@
             String packageName, @UsageStatsManager.StandbyBuckets int standbyBucket,
             boolean allowRequestBgRestricted, boolean calcTrackers) {
         if (mInjector.getAppHibernationInternal().isHibernatingForUser(packageName, userId)) {
-            return new Pair<>(RESTRICTION_LEVEL_HIBERNATION, mEmptyTrackerInfo);
+            return new Pair<>(RESTRICTION_LEVEL_FORCE_STOPPED, mEmptyTrackerInfo);
         }
         @RestrictionLevel int level;
         TrackerInfo trackerInfo = null;
@@ -1721,8 +1734,10 @@
                 level = RESTRICTION_LEVEL_EXEMPTED;
                 break;
             case STANDBY_BUCKET_NEVER:
-                level = RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
-                break;
+                if (!android.app.Flags.appRestrictionsApi()) {
+                    level = RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
+                    break;
+                }
             case STANDBY_BUCKET_ACTIVE:
             case STANDBY_BUCKET_WORKING_SET:
             case STANDBY_BUCKET_FREQUENT:
@@ -1802,7 +1817,9 @@
             case STANDBY_BUCKET_EXEMPTED:
                 return RESTRICTION_LEVEL_EXEMPTED;
             case STANDBY_BUCKET_NEVER:
-                return RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
+                if (!android.app.Flags.appRestrictionsApi()) {
+                    return RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
+                }
             case STANDBY_BUCKET_ACTIVE:
             case STANDBY_BUCKET_WORKING_SET:
             case STANDBY_BUCKET_FREQUENT:
@@ -2028,7 +2045,7 @@
                 return AppBackgroundRestrictionsInfo.LEVEL_RESTRICTED_BUCKET;
             case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
                 return AppBackgroundRestrictionsInfo.LEVEL_BACKGROUND_RESTRICTED;
-            case RESTRICTION_LEVEL_HIBERNATION:
+            case RESTRICTION_LEVEL_FORCE_STOPPED:
                 return AppBackgroundRestrictionsInfo.LEVEL_HIBERNATION;
             default:
                 return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN;
@@ -2153,9 +2170,12 @@
             mRestrictionSettings.update(pkgName, uid, level, reason, subReason);
         }
 
-        if (!allowUpdateBucket || curBucket == STANDBY_BUCKET_EXEMPTED) {
+        if (!android.app.Flags.appRestrictionsApi()
+                && (!allowUpdateBucket || curBucket == STANDBY_BUCKET_EXEMPTED)) {
             return;
         }
+
+        boolean doItNow = true;
         if (level >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
                 && curLevel < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
             // Moving the app standby bucket to restricted in the meanwhile.
@@ -2168,7 +2188,6 @@
                     && (mConstantsObserver.mBgAutoRestrictedBucket
                     || level == RESTRICTION_LEVEL_RESTRICTED_BUCKET)) {
                 // restrict the app if it hasn't done so.
-                boolean doIt = true;
                 synchronized (mSettingsLock) {
                     final int index = mActiveUids.indexOfKey(uid, pkgName);
                     if (index >= 0) {
@@ -2182,14 +2201,16 @@
                             logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level,
                                     localTrackerInfo, localReason);
                         });
-                        doIt = false;
+                        doItNow = false;
                     }
                 }
-                if (doIt) {
+                if (doItNow) {
                     appStandbyInternal.restrictApp(pkgName, UserHandle.getUserId(uid),
                             reason, subReason);
-                    logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
-                            reason);
+                    if (!android.app.Flags.appRestrictionsApi()) {
+                        logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
+                                reason);
+                    }
                 }
             }
         } else if (curLevel >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
@@ -2204,6 +2225,14 @@
             appStandbyInternal.maybeUnrestrictApp(pkgName, UserHandle.getUserId(uid),
                     prevReason & REASON_MAIN_MASK, prevReason & REASON_SUB_MASK,
                     reason, subReason);
+            if (!android.app.Flags.appRestrictionsApi()) {
+                logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
+                        reason);
+            }
+        }
+
+        if (doItNow && android.app.Flags.appRestrictionsApi()
+                && curLevel != RESTRICTION_LEVEL_UNKNOWN) {
             logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
                     reason);
         }
@@ -2297,6 +2326,9 @@
 
     private void handleAppStandbyBucketChanged(int bucket, String packageName,
             @UserIdInt int userId) {
+        // Ignore spurious changes to standby bucket during early boot
+        if (android.app.Flags.appRestrictionsApi() && !mLockedBootCompleted) return;
+
         final int uid = mInjector.getPackageManagerInternal().getPackageUid(
                 packageName, STOCK_PM_FLAGS, userId);
         final Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevel(
@@ -2333,6 +2365,85 @@
         }
     }
 
+    /**
+     * Log a change in restriction state with a reason and threshold.
+     * @param packageName
+     * @param uid
+     * @param restrictionType
+     * @param enabled
+     * @param reason
+     * @param subReason Eg: settings, cli, long_wakelock, crash, binder_spam, cpu, threads
+     *                  Length should not exceed RESTRICTON_SUBREASON_MAX_LENGTH
+     * @param threshold
+     */
+    public void noteAppRestrictionEnabled(String packageName, int uid,
+            @RestrictionLevel int restrictionType, boolean enabled,
+            @RestrictionReason int reason, String subReason, long threshold) {
+        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
+            Slog.i(TAG, (enabled ? "restricted " : "unrestricted ") + packageName + " to "
+                    + restrictionType + " reason=" + reason + ", subReason=" + subReason
+                    + ", threshold=" + threshold);
+        }
+
+        // Limit the length of the free-form subReason string
+        if (subReason != null && subReason.length() > RESTRICTION_SUBREASON_MAX_LENGTH) {
+            subReason = subReason.substring(0, RESTRICTION_SUBREASON_MAX_LENGTH);
+            Slog.e(TAG, "Subreason is too long, truncating: " + subReason);
+        }
+
+        // Log the restriction reason
+        FrameworkStatsLog.write(FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED, uid,
+                getRestrictionTypeStatsd(restrictionType),
+                enabled,
+                getRestrictionChangeReasonStatsd(reason, subReason),
+                subReason,
+                threshold);
+    }
+
+    private int getRestrictionTypeStatsd(@RestrictionLevel int level) {
+        return switch (level) {
+            case RESTRICTION_LEVEL_UNKNOWN ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_UNKNOWN;
+            case RESTRICTION_LEVEL_UNRESTRICTED ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_UNRESTRICTED;
+            case RESTRICTION_LEVEL_EXEMPTED ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_EXEMPTED;
+            case RESTRICTION_LEVEL_ADAPTIVE_BUCKET ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_ADAPTIVE;
+            case RESTRICTION_LEVEL_RESTRICTED_BUCKET ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_RESTRICTED_BUCKET;
+            case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_BACKGROUND_RESTRICTED;
+            case RESTRICTION_LEVEL_FORCE_STOPPED ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_FORCE_STOPPED;
+            case RESTRICTION_LEVEL_USER_LAUNCH_ONLY ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_USER_LAUNCH_ONLY;
+            default ->
+                FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__RESTRICTION_TYPE__TYPE_CUSTOM;
+        };
+    }
+
+    private int getRestrictionChangeReasonStatsd(int reason, String subReason) {
+        return switch (reason) {
+            case RESTRICTION_REASON_DEFAULT ->
+                FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_DEFAULT;
+            case RESTRICTION_REASON_DORMANT ->
+                FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_DORMANT;
+            case RESTRICTION_REASON_USAGE ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_USAGE;
+            case RESTRICTION_REASON_USER ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_USER;
+            case RESTRICTION_REASON_USER_NUDGED ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_USER_NUDGED;
+            case RESTRICTION_REASON_SYSTEM_HEALTH ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_SYSTEM_HEALTH;
+            case RESTRICTION_REASON_REMOTE_TRIGGER ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_REMOTE_TRIGGER;
+            default ->
+                    FrameworkStatsLog.APP_RESTRICTION_STATE_CHANGED__MAIN_REASON__REASON_OTHER;
+        };
+    }
+
     static class NotificationHelper {
         static final String PACKAGE_SCHEME = "package";
         static final String GROUP_KEY = "com.android.app.abusive_bg_apps";
@@ -3380,6 +3491,7 @@
         for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
             mAppStateTrackers.get(i).onLockedBootCompleted();
         }
+        mLockedBootCompleted = true;
     }
 
     boolean isBgAutoRestrictedBucketFeatureFlagEnabled() {
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index ddf1d5f..2be1fe2 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -196,6 +196,8 @@
             start.setIntent(intent);
             start.setStartType(ApplicationStartInfo.START_TYPE_UNSET);
             start.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_LAUNCH, timestampNanos);
+
+            // TODO: handle possible alarm activity start.
             if (intent != null && intent.getCategories() != null
                     && intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
                 start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER);
@@ -313,7 +315,7 @@
     }
 
     public void handleProcessServiceStart(long startTimeNs, ProcessRecord app,
-                ServiceRecord serviceRecord, boolean cold) {
+                ServiceRecord serviceRecord) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
@@ -323,8 +325,9 @@
             start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
             start.addStartupTimestamp(
                     ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            start.setStartType(cold ? ApplicationStartInfo.START_TYPE_COLD
-                    : ApplicationStartInfo.START_TYPE_WARM);
+            start.setStartType(ApplicationStartInfo.START_TYPE_COLD);
+
+            // TODO: handle possible alarm service start.
             start.setReason(serviceRecord.permission != null
                     && serviceRecord.permission.contains("android.permission.BIND_JOB_SERVICE")
                     ? ApplicationStartInfo.START_REASON_JOB
@@ -336,8 +339,9 @@
         }
     }
 
-    public void handleProcessBroadcastStart(long startTimeNs, ProcessRecord app,
-                BroadcastRecord broadcast, boolean cold) {
+    /** Process a broadcast triggered app start. */
+    public void handleProcessBroadcastStart(long startTimeNs, ProcessRecord app, Intent intent,
+                boolean isAlarm) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
@@ -347,26 +351,19 @@
             start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
             start.addStartupTimestamp(
                     ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            start.setStartType(cold ? ApplicationStartInfo.START_TYPE_COLD
-                    : ApplicationStartInfo.START_TYPE_WARM);
-            if (broadcast == null) {
-                start.setReason(ApplicationStartInfo.START_REASON_BROADCAST);
-            } else if (broadcast.alarm) {
+            start.setStartType(ApplicationStartInfo.START_TYPE_COLD);
+            if (isAlarm) {
                 start.setReason(ApplicationStartInfo.START_REASON_ALARM);
-            } else if (broadcast.pushMessage || broadcast.pushMessageOverQuota) {
-                start.setReason(ApplicationStartInfo.START_REASON_PUSH);
-            } else if (Intent.ACTION_BOOT_COMPLETED.equals(broadcast.intent.getAction())) {
-                start.setReason(ApplicationStartInfo.START_REASON_BOOT_COMPLETE);
             } else {
                 start.setReason(ApplicationStartInfo.START_REASON_BROADCAST);
             }
-            start.setIntent(broadcast != null ? broadcast.intent : null);
+            start.setIntent(intent);
             addStartInfoLocked(start);
         }
     }
 
-    public void handleProcessContentProviderStart(long startTimeNs, ProcessRecord app,
-                boolean cold) {
+    /** Process a content provider triggered app start. */
+    public void handleProcessContentProviderStart(long startTimeNs, ProcessRecord app) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
@@ -376,8 +373,7 @@
             start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
             start.addStartupTimestamp(
                     ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            start.setStartType(cold ? ApplicationStartInfo.START_TYPE_COLD
-                    : ApplicationStartInfo.START_TYPE_WARM);
+            start.setStartType(ApplicationStartInfo.START_TYPE_COLD);
             start.setReason(ApplicationStartInfo.START_REASON_CONTENT_PROVIDER);
             addStartInfoLocked(start);
         }
@@ -464,7 +460,7 @@
         addTimestampToStart(app.info.packageName, app.uid, timeNs, key);
     }
 
-    private void addTimestampToStart(String packageName, int uid, long timeNs, int key) {
+    void addTimestampToStart(String packageName, int uid, long timeNs, int key) {
         synchronized (mLock) {
             AppStartInfoContainer container = mData.get(packageName, uid);
             if (container == null) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 4f46ecd..4f84149 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -124,13 +124,16 @@
 import com.android.server.power.stats.BatteryStatsDumpHelperImpl;
 import com.android.server.power.stats.BatteryStatsImpl;
 import com.android.server.power.stats.BatteryUsageStatsProvider;
-import com.android.server.power.stats.CpuAggregatedPowerStatsProcessor;
+import com.android.server.power.stats.CpuPowerStatsProcessor;
+import com.android.server.power.stats.MobileRadioPowerStatsProcessor;
+import com.android.server.power.stats.PhoneCallPowerStatsProcessor;
 import com.android.server.power.stats.PowerStatsAggregator;
 import com.android.server.power.stats.PowerStatsExporter;
 import com.android.server.power.stats.PowerStatsScheduler;
 import com.android.server.power.stats.PowerStatsStore;
 import com.android.server.power.stats.PowerStatsUidResolver;
 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
+import com.android.server.power.stats.WifiPowerStatsProcessor;
 import com.android.server.power.stats.wakeups.CpuWakeupStats;
 
 import java.io.File;
@@ -408,11 +411,23 @@
                 com.android.internal.R.bool.config_batteryStatsResetOnUnplugAfterSignificantCharge);
         final long powerStatsThrottlePeriodCpu = context.getResources().getInteger(
                 com.android.internal.R.integer.config_defaultPowerStatsThrottlePeriodCpu);
+        final long powerStatsThrottlePeriodMobileRadio = context.getResources().getInteger(
+                com.android.internal.R.integer.config_defaultPowerStatsThrottlePeriodMobileRadio);
+        final long powerStatsThrottlePeriodWifi = context.getResources().getInteger(
+                com.android.internal.R.integer.config_defaultPowerStatsThrottlePeriodWifi);
         mBatteryStatsConfig =
                 new BatteryStatsImpl.BatteryStatsConfig.Builder()
                         .setResetOnUnplugHighBatteryLevel(resetOnUnplugHighBatteryLevel)
                         .setResetOnUnplugAfterSignificantCharge(resetOnUnplugAfterSignificantCharge)
-                        .setPowerStatsThrottlePeriodCpu(powerStatsThrottlePeriodCpu)
+                        .setPowerStatsThrottlePeriodMillis(
+                                BatteryConsumer.POWER_COMPONENT_CPU,
+                                powerStatsThrottlePeriodCpu)
+                        .setPowerStatsThrottlePeriodMillis(
+                                BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+                                powerStatsThrottlePeriodMobileRadio)
+                        .setPowerStatsThrottlePeriodMillis(
+                                BatteryConsumer.POWER_COMPONENT_WIFI,
+                                powerStatsThrottlePeriodWifi)
                         .build();
         mPowerStatsUidResolver = new PowerStatsUidResolver();
         mStats = new BatteryStatsImpl(mBatteryStatsConfig, Clock.SYSTEM_CLOCK, mMonotonicClock,
@@ -470,7 +485,33 @@
                         AggregatedPowerStatsConfig.STATE_SCREEN,
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                 .setProcessor(
-                        new CpuAggregatedPowerStatsProcessor(mPowerProfile, mCpuScalingPolicies));
+                        new CpuPowerStatsProcessor(mPowerProfile, mCpuScalingPolicies));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessor(
+                        new MobileRadioPowerStatsProcessor(mPowerProfile));
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .setProcessor(new PhoneCallPowerStatsProcessor());
+
+        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+                .trackDeviceStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN)
+                .trackUidStates(
+                        AggregatedPowerStatsConfig.STATE_POWER,
+                        AggregatedPowerStatsConfig.STATE_SCREEN,
+                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+                .setProcessor(
+                        new WifiPowerStatsProcessor(mPowerProfile));
         return config;
     }
 
@@ -494,8 +535,24 @@
     }
 
     public void systemServicesReady() {
-        mStats.setPowerStatsCollectorEnabled(Flags.streamlinedBatteryStats());
-        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(Flags.streamlinedBatteryStats());
+        mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CPU,
+                Flags.streamlinedBatteryStats());
+        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+                BatteryConsumer.POWER_COMPONENT_CPU,
+                Flags.streamlinedBatteryStats());
+
+        mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+                Flags.streamlinedConnectivityBatteryStats());
+        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+                BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+                Flags.streamlinedConnectivityBatteryStats());
+
+        mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_WIFI,
+                Flags.streamlinedConnectivityBatteryStats());
+        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+                BatteryConsumer.POWER_COMPONENT_WIFI,
+                Flags.streamlinedConnectivityBatteryStats());
+
         mWorker.systemServicesReady();
         mStats.systemServicesReady(mContext);
         mCpuWakeupStats.systemServicesReady();
@@ -536,7 +593,7 @@
      * Notifies BatteryStatsService that the system server is ready.
      */
     public void onSystemReady() {
-        mStats.onSystemReady();
+        mStats.onSystemReady(mContext);
         mPowerStatsScheduler.start(Flags.streamlinedBatteryStats());
     }
 
@@ -1591,19 +1648,14 @@
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             final long uptime = SystemClock.uptimeMillis();
             mHandler.post(() -> {
-                final boolean update;
                 synchronized (mStats) {
                     // Ignore if no power state change.
                     if (mLastPowerStateFromRadio == powerState) return;
 
                     mLastPowerStateFromRadio = powerState;
-                    update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
+                    mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
                             elapsedRealtime, uptime);
                 }
-
-                if (update) {
-                    mWorker.scheduleSync("modem-data", BatteryExternalStatsWorker.UPDATE_RADIO);
-                }
             });
         }
         FrameworkStatsLog.write_non_chained(
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index c082889..48dd039 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1030,6 +1030,10 @@
                     "startProcessLocked failed");
             return true;
         }
+        // TODO: b/335420031 - cache receiver intent to avoid multiple calls to getReceiverIntent.
+        mService.mProcessList.getAppStartInfoTracker().handleProcessBroadcastStart(
+                SystemClock.elapsedRealtimeNanos(), queue.app, r.getReceiverIntent(receiver),
+                r.alarm /* isAlarm */);
         return false;
     }
 
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index fa6b54b..211f952 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -2371,6 +2371,14 @@
                     return;
                 }
 
+                if (opt.shouldNotFreeze()) {
+                    if (DEBUG_FREEZER) {
+                        Slog.d(TAG_AM, "Skipping freeze because process is marked "
+                                + "should not be frozen");
+                    }
+                    return;
+                }
+
                 if (pid == 0 || opt.isFrozen()) {
                     // Already frozen or not a real process, either one being
                     // launched or one being killed
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index f76bf37..28fd197 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -179,6 +179,7 @@
         final int expectedUserId = userId;
         synchronized (mService) {
             long startTime = SystemClock.uptimeMillis();
+            long startElapsedTimeNs = SystemClock.elapsedRealtimeNanos();
 
             ProcessRecord r = null;
             if (caller != null) {
@@ -585,6 +586,8 @@
                                     callingProcessState, ActivityManager.PROCESS_STATE_NONEXISTENT,
                                     firstLaunch,
                                     0L /* TODO: stoppedDuration */);
+                            mService.mProcessList.getAppStartInfoTracker()
+                                    .handleProcessContentProviderStart(startElapsedTimeNs, proc);
                         }
                         cpr.launchingApp = proc;
                         mLaunchingProviders.add(cpr);
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index a656287..b517631 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -9,7 +9,6 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
 [email protected]
 [email protected]
 
diff --git a/services/core/java/com/android/server/am/OomAdjProfiler.java b/services/core/java/com/android/server/am/OomAdjProfiler.java
deleted file mode 100644
index 0869114..0000000
--- a/services/core/java/com/android/server/am/OomAdjProfiler.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import android.os.Message;
-import android.os.PowerManagerInternal;
-import android.os.Process;
-import android.os.SystemClock;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.os.ProcessCpuTracker;
-import com.android.internal.util.RingBuffer;
-import com.android.internal.util.function.pooled.PooledLambda;
-
-import java.io.PrintWriter;
-
-public class OomAdjProfiler {
-    private static final int MSG_UPDATE_CPU_TIME = 42;
-
-    @GuardedBy("this")
-    private boolean mOnBattery;
-    @GuardedBy("this")
-    private boolean mScreenOff;
-
-    /** The value of {@link #mOnBattery} when the CPU time update was last scheduled. */
-    @GuardedBy("this")
-    private boolean mLastScheduledOnBattery;
-    /** The value of {@link #mScreenOff} when the CPU time update was last scheduled. */
-    @GuardedBy("this")
-    private boolean mLastScheduledScreenOff;
-
-    @GuardedBy("this")
-    private long mOomAdjStartTimeUs;
-    @GuardedBy("this")
-    private boolean mOomAdjStarted;
-
-    @GuardedBy("this")
-    private CpuTimes mOomAdjRunTime = new CpuTimes();
-    @GuardedBy("this")
-    private CpuTimes mSystemServerCpuTime = new CpuTimes();
-
-    @GuardedBy("this")
-    private long mLastSystemServerCpuTimeMs;
-    @GuardedBy("this")
-    private boolean mSystemServerCpuTimeUpdateScheduled;
-    private final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(false);
-
-    @GuardedBy("this")
-    final RingBuffer<CpuTimes> mOomAdjRunTimesHist = new RingBuffer<>(CpuTimes.class, 10);
-    @GuardedBy("this")
-    final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
-
-    @GuardedBy("this")
-    private long mTotalOomAdjRunTimeUs;
-    @GuardedBy("this")
-    private int mTotalOomAdjCalls;
-
-    void batteryPowerChanged(boolean onBattery) {
-        synchronized (this) {
-            scheduleSystemServerCpuTimeUpdate();
-            mOnBattery = onBattery;
-        }
-    }
-
-    void onWakefulnessChanged(int wakefulness) {
-        synchronized (this) {
-            scheduleSystemServerCpuTimeUpdate();
-            mScreenOff = wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE;
-        }
-    }
-
-    void oomAdjStarted() {
-        synchronized (this) {
-            mOomAdjStartTimeUs = SystemClock.currentThreadTimeMicro();
-            mOomAdjStarted = true;
-        }
-    }
-
-    void oomAdjEnded() {
-        synchronized (this) {
-            if (!mOomAdjStarted) {
-                return;
-            }
-            long elapsedUs = SystemClock.currentThreadTimeMicro() - mOomAdjStartTimeUs;
-            mOomAdjRunTime.addCpuTimeUs(elapsedUs);
-            mTotalOomAdjRunTimeUs += elapsedUs;
-            mTotalOomAdjCalls++;
-        }
-    }
-
-    private void scheduleSystemServerCpuTimeUpdate() {
-        synchronized (this) {
-            if (mSystemServerCpuTimeUpdateScheduled) {
-                return;
-            }
-            mLastScheduledOnBattery = mOnBattery;
-            mLastScheduledScreenOff = mScreenOff;
-            mSystemServerCpuTimeUpdateScheduled = true;
-            Message scheduledMessage = PooledLambda.obtainMessage(
-                    OomAdjProfiler::updateSystemServerCpuTime,
-                    this, mLastScheduledOnBattery, mLastScheduledScreenOff, true);
-            scheduledMessage.setWhat(MSG_UPDATE_CPU_TIME);
-
-            BackgroundThread.getHandler().sendMessage(scheduledMessage);
-        }
-    }
-
-    private void updateSystemServerCpuTime(boolean onBattery, boolean screenOff,
-            boolean onlyIfScheduled) {
-        final long cpuTimeMs = mProcessCpuTracker.getCpuTimeForPid(Process.myPid());
-        synchronized (this) {
-            if (onlyIfScheduled && !mSystemServerCpuTimeUpdateScheduled) {
-                return;
-            }
-            mSystemServerCpuTime.addCpuTimeMs(
-                    cpuTimeMs - mLastSystemServerCpuTimeMs, onBattery, screenOff);
-            mLastSystemServerCpuTimeMs = cpuTimeMs;
-            mSystemServerCpuTimeUpdateScheduled = false;
-        }
-    }
-
-    void reset() {
-        synchronized (this) {
-            if (mSystemServerCpuTime.isEmpty()) {
-                return;
-            }
-            mOomAdjRunTimesHist.append(mOomAdjRunTime);
-            mSystemServerCpuTimesHist.append(mSystemServerCpuTime);
-            mOomAdjRunTime = new CpuTimes();
-            mSystemServerCpuTime = new CpuTimes();
-        }
-    }
-
-    void dump(PrintWriter pw) {
-        synchronized (this) {
-            if (mSystemServerCpuTimeUpdateScheduled) {
-                // Cancel the scheduled update since we're going to update it here instead.
-                BackgroundThread.getHandler().removeMessages(MSG_UPDATE_CPU_TIME);
-                // Make sure the values are attributed to the right states.
-                updateSystemServerCpuTime(mLastScheduledOnBattery, mLastScheduledScreenOff, false);
-            } else {
-                updateSystemServerCpuTime(mOnBattery, mScreenOff, false);
-            }
-
-            pw.println("System server and oomAdj runtimes (ms) in recent battery sessions "
-                    + "(most recent first):");
-            if (!mSystemServerCpuTime.isEmpty()) {
-                pw.print("  ");
-                pw.print("system_server=");
-                pw.print(mSystemServerCpuTime);
-                pw.print("  ");
-                pw.print("oom_adj=");
-                pw.println(mOomAdjRunTime);
-            }
-            final CpuTimes[] systemServerCpuTimes = mSystemServerCpuTimesHist.toArray();
-            final CpuTimes[] oomAdjRunTimes = mOomAdjRunTimesHist.toArray();
-            for (int i = oomAdjRunTimes.length - 1; i >= 0; --i) {
-                pw.print("  ");
-                pw.print("system_server=");
-                pw.print(systemServerCpuTimes[i]);
-                pw.print("  ");
-                pw.print("oom_adj=");
-                pw.println(oomAdjRunTimes[i]);
-            }
-            if (mTotalOomAdjCalls != 0) {
-                pw.println("System server total oomAdj runtimes (us) since boot:");
-                pw.print("  cpu time spent=");
-                pw.print(mTotalOomAdjRunTimeUs);
-                pw.print("  number of calls=");
-                pw.print(mTotalOomAdjCalls);
-                pw.print("  average=");
-                pw.println(mTotalOomAdjRunTimeUs / mTotalOomAdjCalls);
-            }
-        }
-    }
-
-    private class CpuTimes {
-        private long mOnBatteryTimeUs;
-        private long mOnBatteryScreenOffTimeUs;
-
-        public void addCpuTimeMs(long cpuTimeMs) {
-            addCpuTimeUs(cpuTimeMs * 1000, mOnBattery, mScreenOff);
-        }
-
-        public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
-            addCpuTimeUs(cpuTimeMs * 1000, onBattery, screenOff);
-        }
-
-        public void addCpuTimeUs(long cpuTimeUs) {
-            addCpuTimeUs(cpuTimeUs, mOnBattery, mScreenOff);
-        }
-
-        public void addCpuTimeUs(long cpuTimeUs, boolean onBattery, boolean screenOff) {
-            if (onBattery) {
-                mOnBatteryTimeUs += cpuTimeUs;
-                if (screenOff) {
-                    mOnBatteryScreenOffTimeUs += cpuTimeUs;
-                }
-            }
-        }
-
-        public boolean isEmpty() {
-            return mOnBatteryTimeUs == 0 && mOnBatteryScreenOffTimeUs == 0;
-        }
-
-        public String toString() {
-            return "[" + (mOnBatteryTimeUs / 1000) + ","
-                    + (mOnBatteryScreenOffTimeUs / 1000) + "]";
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 5a750c2..9b72db8 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -72,7 +72,6 @@
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL;
 import static android.media.audio.Flags.roForegroundAudioControl;
-import static android.os.Process.SCHED_OTHER;
 import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
 import static android.os.Process.THREAD_GROUP_RESTRICTED;
@@ -81,7 +80,6 @@
 import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
 import static android.os.Process.setProcessGroup;
 import static android.os.Process.setThreadPriority;
-import static android.os.Process.setThreadScheduler;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
@@ -602,7 +600,6 @@
 
         mLastReason = oomAdjReason;
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
-        mService.mOomAdjProfiler.oomAdjStarted();
 
         final ProcessStateRecord state = app.mState;
 
@@ -632,7 +629,6 @@
         }
         mTmpProcessList.clear();
         mService.clearPendingTopAppLocked();
-        mService.mOomAdjProfiler.oomAdjEnded();
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         return true;
     }
@@ -851,7 +847,6 @@
 
         mLastReason = oomAdjReason;
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
-        mService.mOomAdjProfiler.oomAdjStarted();
         mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP();
 
         final ArrayList<ProcessRecord> processes = mTmpProcessList;
@@ -864,7 +859,6 @@
         processes.clear();
         mService.clearPendingTopAppLocked();
 
-        mService.mOomAdjProfiler.oomAdjEnded();
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
@@ -897,7 +891,6 @@
         mLastReason = oomAdjReason;
         if (startProfiling) {
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
-            mService.mOomAdjProfiler.oomAdjStarted();
         }
         final long now = SystemClock.uptimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
@@ -991,7 +984,6 @@
         postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime, true);
 
         if (startProfiling) {
-            mService.mOomAdjProfiler.oomAdjEnded();
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
     }
@@ -3315,22 +3307,10 @@
                         // do nothing if we already switched to RT
                         if (oldSchedGroup != SCHED_GROUP_TOP_APP) {
                             app.getWindowProcessController().onTopProcChanged();
-                            if (mService.mUseFifoUiScheduling) {
+                            if (app.useFifoUiScheduling()) {
                                 // Switch UI pipeline for app to SCHED_FIFO
                                 state.setSavedPriority(Process.getThreadPriority(app.getPid()));
-                                mService.scheduleAsFifoPriority(app.getPid(), true);
-                                if (renderThreadTid != 0) {
-                                    mService.scheduleAsFifoPriority(renderThreadTid,
-                                            /* suppressLogs */true);
-                                    if (DEBUG_OOM_ADJ) {
-                                        Slog.d("UI_FIFO", "Set RenderThread (TID " +
-                                                renderThreadTid + ") to FIFO");
-                                    }
-                                } else {
-                                    if (DEBUG_OOM_ADJ) {
-                                        Slog.d("UI_FIFO", "Not setting RenderThread TID");
-                                    }
-                                }
+                                ActivityManagerService.setFifoPriority(app, true /* enable */);
                             } else {
                                 // Boost priority for top app UI and render threads
                                 setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
@@ -3347,22 +3327,10 @@
                     } else if (oldSchedGroup == SCHED_GROUP_TOP_APP
                             && curSchedGroup != SCHED_GROUP_TOP_APP) {
                         app.getWindowProcessController().onTopProcChanged();
-                        if (mService.mUseFifoUiScheduling) {
-                            try {
-                                // Reset UI pipeline to SCHED_OTHER
-                                setThreadScheduler(app.getPid(), SCHED_OTHER, 0);
-                                setThreadPriority(app.getPid(), state.getSavedPriority());
-                                if (renderThreadTid != 0) {
-                                    setThreadScheduler(renderThreadTid,
-                                            SCHED_OTHER, 0);
-                                }
-                            } catch (IllegalArgumentException e) {
-                                Slog.w(TAG,
-                                        "Failed to set scheduling policy, thread does not exist:\n"
-                                                + e);
-                            } catch (SecurityException e) {
-                                Slog.w(TAG, "Failed to set scheduling policy, not allowed:\n" + e);
-                            }
+                        if (app.useFifoUiScheduling()) {
+                            // Reset UI pipeline to SCHED_OTHER
+                            ActivityManagerService.setFifoPriority(app, false /* enable */);
+                            setThreadPriority(app.getPid(), state.getSavedPriority());
                         } else {
                             // Reset priority for top app UI and render threads
                             setThreadPriority(app.getPid(), 0);
@@ -3557,7 +3525,7 @@
                 // {@link SCHED_GROUP_TOP_APP}. We don't check render thread because it
                 // is not ready when attaching.
                 app.getWindowProcessController().onTopProcChanged();
-                if (mService.mUseFifoUiScheduling) {
+                if (app.useFifoUiScheduling()) {
                     mService.scheduleAsFifoPriority(app.getPid(), true);
                 } else {
                     setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
index 00e1482..3268b66 100644
--- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
+++ b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
@@ -744,11 +744,9 @@
 
         mLastReason = oomAdjReason;
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
-        mService.mOomAdjProfiler.oomAdjStarted();
 
         fullUpdateLSP(oomAdjReason);
 
-        mService.mOomAdjProfiler.oomAdjEnded();
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
@@ -766,14 +764,12 @@
         mLastReason = oomAdjReason;
         mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP();
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
-        mService.mOomAdjProfiler.oomAdjStarted();
 
         synchronized (mProcLock) {
             partialUpdateLSP(oomAdjReason, mPendingProcessSet);
         }
         mPendingProcessSet.clear();
 
-        mService.mOomAdjProfiler.oomAdjEnded();
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index fb0d695..f336120 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -22,6 +22,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_OWNER_CANCELED;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_SUPERSEDED;
 
 import android.annotation.Nullable;
 import android.app.Activity;
@@ -54,6 +56,7 @@
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.AlarmManagerInternal;
 import com.android.server.LocalServices;
+import com.android.server.am.PendingIntentRecord.CancellationReason;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.SafeActivityOptions;
 
@@ -191,7 +194,7 @@
                     }
                     return rec;
                 }
-                makeIntentSenderCanceled(rec);
+                makeIntentSenderCanceled(rec, CANCEL_REASON_SUPERSEDED);
                 mIntentSenderRecords.remove(key);
                 decrementUidStatLocked(rec);
             }
@@ -206,7 +209,7 @@
     }
 
     boolean removePendingIntentsForPackage(String packageName, int userId, int appId,
-            boolean doIt) {
+            boolean doIt, @CancellationReason int cancelReason) {
 
         boolean didSomething = false;
         synchronized (mLock) {
@@ -256,7 +259,7 @@
                 }
                 didSomething = true;
                 it.remove();
-                makeIntentSenderCanceled(pir);
+                makeIntentSenderCanceled(pir, cancelReason);
                 decrementUidStatLocked(pir);
                 if (pir.key.activity != null) {
                     final Message m = PooledLambda.obtainMessage(
@@ -289,13 +292,14 @@
             } catch (RemoteException e) {
                 throw new SecurityException(e);
             }
-            cancelIntentSender(rec, true);
+            cancelIntentSender(rec, true, CANCEL_REASON_OWNER_CANCELED);
         }
     }
 
-    public void cancelIntentSender(PendingIntentRecord rec, boolean cleanActivity) {
+    public void cancelIntentSender(PendingIntentRecord rec, boolean cleanActivity,
+            @CancellationReason int cancelReason) {
         synchronized (mLock) {
-            makeIntentSenderCanceled(rec);
+            makeIntentSenderCanceled(rec, cancelReason);
             mIntentSenderRecords.remove(rec.key);
             decrementUidStatLocked(rec);
             if (cleanActivity && rec.key.activity != null) {
@@ -359,8 +363,10 @@
         }
     }
 
-    private void makeIntentSenderCanceled(PendingIntentRecord rec) {
+    private void makeIntentSenderCanceled(PendingIntentRecord rec,
+            @CancellationReason int cancelReason) {
         rec.canceled = true;
+        rec.cancelReason = cancelReason;
         final RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked();
         if (callbacks != null) {
             final Message m = PooledLambda.obtainMessage(
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 95e130e..da45a77 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -16,11 +16,13 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.START_SUCCESS;
 
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
@@ -51,11 +53,15 @@
 import android.util.Slog;
 import android.util.TimeUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.modules.expresslog.Counter;
 import com.android.server.wm.SafeActivityOptions;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.Objects;
 
@@ -71,12 +77,35 @@
     public static final int FLAG_BROADCAST_SENDER = 1 << 1;
     public static final int FLAG_SERVICE_SENDER = 1 << 2;
 
+    public static final int CANCEL_REASON_NULL = 0;
+    public static final int CANCEL_REASON_USER_STOPPED = 1 << 0;
+    public static final int CANCEL_REASON_OWNER_UNINSTALLED = 1 << 1;
+    public static final int CANCEL_REASON_OWNER_FORCE_STOPPED = 1 << 2;
+    public static final int CANCEL_REASON_OWNER_CANCELED = 1 << 3;
+    public static final int CANCEL_REASON_HOSTING_ACTIVITY_DESTROYED = 1 << 4;
+    public static final int CANCEL_REASON_SUPERSEDED = 1 << 5;
+    public static final int CANCEL_REASON_ONE_SHOT_SENT = 1 << 6;
+
+    @IntDef({
+            CANCEL_REASON_NULL,
+            CANCEL_REASON_USER_STOPPED,
+            CANCEL_REASON_OWNER_UNINSTALLED,
+            CANCEL_REASON_OWNER_FORCE_STOPPED,
+            CANCEL_REASON_OWNER_CANCELED,
+            CANCEL_REASON_HOSTING_ACTIVITY_DESTROYED,
+            CANCEL_REASON_SUPERSEDED,
+            CANCEL_REASON_ONE_SHOT_SENT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CancellationReason {}
+
     final PendingIntentController controller;
     final Key key;
     final int uid;
     public final WeakReference<PendingIntentRecord> ref;
     boolean sent = false;
     boolean canceled = false;
+    @CancellationReason int cancelReason = CANCEL_REASON_NULL;
     /**
      * Map IBinder to duration specified as Pair<Long, Integer>, Long is allowlist duration in
      * milliseconds, Integer is allowlist type defined at
@@ -419,12 +448,22 @@
         SafeActivityOptions mergedOptions = null;
         synchronized (controller.mLock) {
             if (canceled) {
+                if (cancelReason == CANCEL_REASON_OWNER_FORCE_STOPPED
+                        && controller.mAmInternal.getUidProcessState(callingUid)
+                                == PROCESS_STATE_TOP) {
+                    Counter.logIncrementWithUid(
+                            "app.value_force_stop_cancelled_pi_sent_from_top_per_caller",
+                            callingUid);
+                    Counter.logIncrementWithUid(
+                            "app.value_force_stop_cancelled_pi_sent_from_top_per_owner",
+                            uid);
+                }
                 return ActivityManager.START_CANCELED;
             }
 
             sent = true;
             if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) {
-                controller.cancelIntentSender(this, true);
+                controller.cancelIntentSender(this, true, CANCEL_REASON_ONE_SHOT_SENT);
             }
 
             finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent();
@@ -687,6 +726,21 @@
         }
     }
 
+    @VisibleForTesting
+    static String cancelReasonToString(@CancellationReason int cancelReason) {
+        return switch (cancelReason) {
+            case CANCEL_REASON_NULL -> "NULL";
+            case CANCEL_REASON_USER_STOPPED -> "USER_STOPPED";
+            case CANCEL_REASON_OWNER_UNINSTALLED -> "OWNER_UNINSTALLED";
+            case CANCEL_REASON_OWNER_FORCE_STOPPED -> "OWNER_FORCE_STOPPED";
+            case CANCEL_REASON_OWNER_CANCELED -> "OWNER_CANCELED";
+            case CANCEL_REASON_HOSTING_ACTIVITY_DESTROYED -> "HOSTING_ACTIVITY_DESTROYED";
+            case CANCEL_REASON_SUPERSEDED -> "SUPERSEDED";
+            case CANCEL_REASON_ONE_SHOT_SENT -> "ONE_SHOT_SENT";
+            default -> "UNKNOWN";
+        };
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("uid="); pw.print(uid);
                 pw.print(" packageName="); pw.print(key.packageName);
@@ -707,7 +761,8 @@
         }
         if (sent || canceled) {
             pw.print(prefix); pw.print("sent="); pw.print(sent);
-                    pw.print(" canceled="); pw.println(canceled);
+                    pw.print(" canceled="); pw.print(canceled);
+                    pw.print(" cancelReason="); pw.println(cancelReasonToString(cancelReason));
         }
         if (mAllowlistDuration != null) {
             pw.print(prefix);
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index a8fe734..ea92571 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -25,6 +25,8 @@
 
 import java.io.PrintWriter;
 
+import dalvik.annotation.optimization.NeverCompile;
+
 /**
  * The state info of app when it's cached, used by the optimizer.
  */
@@ -340,6 +342,7 @@
     }
 
     @GuardedBy("mProcLock")
+    @NeverCompile
     void dump(PrintWriter pw, String prefix, long nowUptime) {
         pw.print(prefix); pw.print("lastCompactTime="); pw.print(mLastCompactTime);
         pw.print(" lastCompactProfile=");
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 0aa1a69..76c5952 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -66,7 +66,7 @@
 import java.io.StringWriter;
 import java.time.Instant;
 import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
+import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.UUID;
 import java.util.concurrent.ExecutionException;
@@ -79,9 +79,6 @@
  * The error state of the process, such as if it's crashing/ANR etc.
  */
 class ProcessErrorStateRecord {
-    private static final DateTimeFormatter DROPBOX_TIME_FORMATTER =
-            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSZ");
-
     final ProcessRecord mApp;
     private final ActivityManagerService mService;
 
@@ -355,9 +352,18 @@
             synchronized (mProcLock) {
                 latencyTracker.waitingOnProcLockEnded();
                 setNotResponding(true);
+
+                ZonedDateTime timestamp = null;
+                if (timeoutRecord != null && timeoutRecord.mEndUptimeMillis > 0) {
+                    long millisSinceEndUptimeMs = anrTime - timeoutRecord.mEndUptimeMillis;
+                    timestamp = Instant.now().minusMillis(millisSinceEndUptimeMs)
+                                    .atZone(ZoneId.systemDefault());
+                }
+
                 volatileDropboxEntriyStates =
                         ActivityManagerService.VolatileDropboxEntryStates
-                                .withProcessFrozenState(mApp.mOptRecord.isFrozen());
+                                .withProcessFrozenStateAndTimestamp(
+                                        mApp.mOptRecord.isFrozen(), timestamp);
             }
 
             // Log the ANR to the event log.
@@ -450,13 +456,6 @@
             info.append("ErrorId: ").append(errorId.toString()).append("\n");
         }
         info.append("Frozen: ").append(mApp.mOptRecord.isFrozen()).append("\n");
-        if (timeoutRecord != null && timeoutRecord.mEndUptimeMillis > 0) {
-            long millisSinceEndUptimeMs = anrTime - timeoutRecord.mEndUptimeMillis;
-            String formattedTime = DROPBOX_TIME_FORMATTER.format(
-                    Instant.now().minusMillis(millisSinceEndUptimeMs)
-                            .atZone(ZoneId.systemDefault()));
-            info.append("Timestamp: ").append(formattedTime).append("\n");
-        }
 
         // Retrieve controller with max ANR delay from AnrControllers
         // Note that we retrieve the controller before dumping stacks because dumping stacks can
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index b939089..0816527 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -745,6 +745,9 @@
             mOnewayThread = thread;
         }
         mWindowProcessController.setThread(thread);
+        if (mWindowProcessController.useFifoUiScheduling()) {
+            mService.mSpecifiedFifoProcesses.add(this);
+        }
     }
 
     @GuardedBy({"mService", "mProcLock"})
@@ -752,9 +755,19 @@
         mThread = null;
         mOnewayThread = null;
         mWindowProcessController.setThread(null);
+        if (mWindowProcessController.useFifoUiScheduling()) {
+            mService.mSpecifiedFifoProcesses.remove(this);
+        }
         mProfile.onProcessInactive(tracker);
     }
 
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
+    boolean useFifoUiScheduling() {
+        return mService.mUseFifoUiScheduling
+                || (mService.mAllowSpecifiedFifoScheduling
+                        && mWindowProcessController.useFifoUiScheduling());
+    }
+
     @GuardedBy("mService")
     int getDyingPid() {
         return mDyingPid;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 5834dcd..065f3bd 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -30,6 +30,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.BackgroundStartPrivileges;
@@ -56,7 +57,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
@@ -237,8 +237,6 @@
     boolean mFgsNotificationShown;
     // Whether FGS package has permissions to show notifications.
     boolean mFgsHasNotificationPermission;
-    // Whether the FGS contains a type that is time limited.
-    private boolean mFgsIsTimeLimited;
 
     // allow the service becomes foreground service? Service started from background may not be
     // allowed to become a foreground service.
@@ -675,6 +673,62 @@
      */
     private ShortFgsInfo mShortFgsInfo;
 
+    /**
+     * Data container class to help track certain fgs info for time-restricted types.
+     */
+    static class TimeLimitedFgsInfo {
+        @ElapsedRealtimeLong
+        private long mFirstFgsStartTime;
+        @ElapsedRealtimeLong
+        private long mLastFgsStartTime;
+        @ElapsedRealtimeLong
+        private long mTimeLimitExceededAt = Long.MIN_VALUE;
+        private long mTotalRuntime = 0;
+
+        TimeLimitedFgsInfo(@ElapsedRealtimeLong long startTime) {
+            mFirstFgsStartTime = startTime;
+            mLastFgsStartTime = startTime;
+        }
+
+        @ElapsedRealtimeLong
+        public long getFirstFgsStartTime() {
+            return mFirstFgsStartTime;
+        }
+
+        public void setLastFgsStartTime(@ElapsedRealtimeLong long startTime) {
+            mLastFgsStartTime = startTime;
+        }
+
+        @ElapsedRealtimeLong
+        public long getLastFgsStartTime() {
+            return mLastFgsStartTime;
+        }
+
+        public void updateTotalRuntime() {
+            mTotalRuntime += SystemClock.elapsedRealtime() - mLastFgsStartTime;
+        }
+
+        public long getTotalRuntime() {
+            return mTotalRuntime;
+        }
+
+        public void setTimeLimitExceededAt(@ElapsedRealtimeLong long timeLimitExceededAt) {
+            mTimeLimitExceededAt = timeLimitExceededAt;
+        }
+
+        @ElapsedRealtimeLong
+        public long getTimeLimitExceededAt() {
+            return mTimeLimitExceededAt;
+        }
+
+        public void reset() {
+            mFirstFgsStartTime = 0;
+            mLastFgsStartTime = 0;
+            mTotalRuntime = 0;
+            mTimeLimitExceededAt = Long.MIN_VALUE;
+        }
+    }
+
     void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) {
         final int N = list.size();
         for (int i=0; i<N; i++) {
@@ -927,7 +981,6 @@
             pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
             pw.print(" foregroundId="); pw.print(foregroundId);
             pw.printf(" types=%08X", foregroundServiceType);
-            pw.print(" fgsHasTimeLimitedType="); pw.print(mFgsIsTimeLimited);
             pw.print(" foregroundNoti="); pw.println(foregroundNoti);
 
             if (isShortFgs() && mShortFgsInfo != null) {
@@ -1803,80 +1856,41 @@
     }
 
     /**
+     * Called when a time-limited FGS starts.
+     */
+    public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@ElapsedRealtimeLong long nowRealtime) {
+        return new TimeLimitedFgsInfo(nowRealtime);
+    }
+
+    /**
      * @return true if one of the types of this FGS has a time limit.
      */
     public boolean isFgsTimeLimited() {
-        return startRequested && isForeground && canFgsTypeTimeOut(foregroundServiceType);
+        return startRequested
+                && isForeground
+                && ams.mServices.getTimeLimitedFgsType(foregroundServiceType)
+                        != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
     }
 
     /**
-     * Called when a FGS with a time-limited type starts ({@code true}) or stops ({@code false}).
+     * @return the next stop time for the given type, based on how long it has already ran for.
+     * The total runtime is automatically reset 24hrs after the first fgs start of this type
+     * or if the app has recently been in the TOP state when the app calls startForeground().
      */
-    public void setIsFgsTimeLimited(boolean fgsIsTimeLimited) {
-        this.mFgsIsTimeLimited = fgsIsTimeLimited;
-    }
-
-    /**
-     * @return whether {@link #mFgsIsTimeLimited} was previously set or not.
-     */
-    public boolean wasFgsPreviouslyTimeLimited() {
-        return mFgsIsTimeLimited;
-    }
-
-    /**
-     * @return the FGS type if the service has reached its time limit, otherwise -1.
-     */
-    public int getTimedOutFgsType(long nowUptime) {
-        if (!isAppAlive() || !isFgsTimeLimited()) {
-            return -1;
+    long getNextFgsStopTime(int fgsType, TimeLimitedFgsInfo fgsInfo) {
+        final long timeLimit;
+        switch (ams.mServices.getTimeLimitedFgsType(fgsType)) {
+            case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING:
+                timeLimit = ams.mConstants.mMediaProcessingFgsTimeoutDuration;
+                break;
+            case ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC:
+                timeLimit = ams.mConstants.mDataSyncFgsTimeoutDuration;
+                break;
+            // Add logic for time limits introduced in the future for other fgs types above.
+            default:
+                return Long.MAX_VALUE;
         }
-
-        final Pair<Integer, Long> fgsTypeAndStopTime = getEarliestStopTypeAndTime();
-        if (fgsTypeAndStopTime.first != -1 && fgsTypeAndStopTime.second <= nowUptime) {
-            return fgsTypeAndStopTime.first;
-        }
-        return -1; // no fgs type exceeded time limit
-    }
-
-    /**
-     * @return a {@code Pair<fgs_type, stop_time>}, representing the earliest time at which the FGS
-     * should be stopped (fgs start time + time limit for most restrictive type)
-     */
-    Pair<Integer, Long> getEarliestStopTypeAndTime() {
-        int fgsType = -1;
-        long timeout = 0;
-        if ((foregroundServiceType & ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING)
-                == ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING) {
-            fgsType = ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING;
-            timeout = ams.mConstants.mMediaProcessingFgsTimeoutDuration;
-        }
-        if ((foregroundServiceType & ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
-                == ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) {
-            // update the timeout and type if this type has a more restrictive time limit
-            if (timeout == 0 || ams.mConstants.mDataSyncFgsTimeoutDuration < timeout) {
-                fgsType = ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC;
-                timeout = ams.mConstants.mDataSyncFgsTimeoutDuration;
-            }
-        }
-        // Add the logic for time limits introduced in the future for other fgs types here.
-        return Pair.create(fgsType, timeout == 0 ? 0 : (mFgsEnterTime + timeout));
-    }
-
-    /**
-     * Check if the given types contain a type which is time restricted.
-     */
-    boolean canFgsTypeTimeOut(int fgsType) {
-        // The below conditionals are not simplified on purpose to help with readability.
-        if ((fgsType & ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING)
-                == ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING) {
-            return true;
-        }
-        if ((fgsType & ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
-                == ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) {
-            return true;
-        }
-        // Additional types which have time limits should be added here in the future.
-        return false;
+        return fgsInfo.mLastFgsStartTime + Math.max(0, timeLimit - fgsInfo.mTotalRuntime);
     }
 
     private boolean isAppAlive() {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 390dca3..8b64538 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -145,6 +145,7 @@
         "core_experiments_team_internal",
         "core_graphics",
         "core_libraries",
+        "crumpet",
         "dck_framework",
         "devoptions_settings",
         "game",
@@ -162,6 +163,7 @@
         "media_reliability",
         "media_solutions",
         "media_tv",
+        "nearby",
         "nfc",
         "pdf_viewer",
         "perfetto",
@@ -169,6 +171,7 @@
         "pixel_biometrics_face",
         "pixel_bluetooth",
         "pixel_connectivity_gps",
+        "pixel_continuity",
         "pixel_sensors",
         "pixel_system_sw_video",
         "pixel_watch",
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 60a8b50..b703076 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -59,6 +59,7 @@
 import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_UNLOCKING_USER;
 import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED;
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
+import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND;
 import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND_VISIBLE;
 import static com.android.server.pm.UserManagerInternal.USER_START_MODE_FOREGROUND;
 import static com.android.server.pm.UserManagerInternal.userAssignmentResultToString;
@@ -200,6 +201,7 @@
     static final int START_USER_SWITCH_FG_MSG = 120;
     static final int COMPLETE_USER_SWITCH_MSG = 130;
     static final int USER_COMPLETED_EVENT_MSG = 140;
+    static final int SCHEDULED_STOP_BACKGROUND_USER_MSG = 150;
 
     private static final int NO_ARG2 = 0;
 
@@ -246,10 +248,19 @@
      *
      * <p>Note: Current and system user (and their related profiles) are never stopped when
      * switching users. Due to that, the actual number of running users can exceed mMaxRunningUsers
+     // TODO(b/310249114): Strongly consider *not* exempting the SYSTEM user's profile.
      */
     @GuardedBy("mLock")
     private int mMaxRunningUsers;
 
+    /**
+     * Number of seconds of uptime after a full user enters the background before we attempt
+     * to stop it due to inactivity. Set to -1 to disable scheduling stopping background users.
+     *
+     * Typically set by config_backgroundUserScheduledStopTimeSecs.
+     */
+    private int mBackgroundUserScheduledStopTimeSecs = -1;
+
     // Lock for internal state.
     private final Object mLock = new Object();
 
@@ -452,11 +463,12 @@
     }
 
     void setInitialConfig(boolean userSwitchUiEnabled, int maxRunningUsers,
-            boolean delayUserDataLocking) {
+            boolean delayUserDataLocking, int backgroundUserScheduledStopTimeSecs) {
         synchronized (mLock) {
             mUserSwitchUiEnabled = userSwitchUiEnabled;
             mMaxRunningUsers = maxRunningUsers;
             mDelayUserDataLocking = delayUserDataLocking;
+            mBackgroundUserScheduledStopTimeSecs = backgroundUserScheduledStopTimeSecs;
             mInitialized = true;
         }
     }
@@ -578,7 +590,8 @@
             // from outside.
             Slogf.i(TAG, "Too many running users (%d). Attempting to stop user %d",
                     currentlyRunningLru.size(), userId);
-            if (stopUsersLU(userId, /* force= */ false, /* allowDelayedLocking= */ true,
+            if (stopUsersLU(userId,
+                    /* stopProfileRegardlessOfParent= */ false, /* allowDelayedLocking= */ true,
                     /* stopUserCallback= */ null, /* keyEvictedCallback= */ null)
                     == USER_OP_SUCCESS) {
                 // Technically, stopUsersLU can remove more than one user when stopping a parent.
@@ -875,7 +888,7 @@
             Slogf.i(TAG, "Stopping pre-created user " + userInfo.toFullString());
             // Pre-created user was started right after creation so services could properly
             // intialize it; it should be stopped right away as it's not really a "real" user.
-            stopUser(userInfo.id, /* force= */ true, /* allowDelayedLocking= */ false,
+            stopUser(userInfo.id, /* allowDelayedLocking= */ false,
                     /* stopUserCallback= */ null, /* keyEvictedCallback= */ null);
             return;
         }
@@ -930,7 +943,7 @@
     }
 
     int restartUser(final int userId, @UserStartMode int userStartMode) {
-        return stopUser(userId, /* force= */ true, /* allowDelayedLocking= */ false,
+        return stopUser(userId, /* allowDelayedLocking= */ false,
                 /* stopUserCallback= */ null, new KeyEvictedCallback() {
                     @Override
                     public void keyEvicted(@UserIdInt int userId) {
@@ -966,18 +979,24 @@
 
         enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
         synchronized (mLock) {
-            return stopUsersLU(userId, /* force= */ true, /* allowDelayedLocking= */
-                    false, /* stopUserCallback= */ null, /* keyEvictedCallback= */ null)
+            return stopUsersLU(userId, /* allowDelayedLocking= */ false,
+                    /* stopUserCallback= */ null, /* keyEvictedCallback= */ null)
                     == ActivityManager.USER_OP_SUCCESS;
         }
     }
 
-    int stopUser(final int userId, final boolean force, boolean allowDelayedLocking,
+    int stopUser(final int userId, boolean allowDelayedLocking,
+            final IStopUserCallback stopUserCallback, KeyEvictedCallback keyEvictedCallback) {
+        return stopUser(userId, true, allowDelayedLocking, stopUserCallback, keyEvictedCallback);
+    }
+
+    int stopUser(final int userId,
+            final boolean stopProfileRegardlessOfParent, final boolean allowDelayedLocking,
             final IStopUserCallback stopUserCallback, KeyEvictedCallback keyEvictedCallback) {
         TimingsTraceAndSlog t = new TimingsTraceAndSlog();
 
         t.traceBegin("UserController"
-                + (force ? "-force" : "")
+                + (stopProfileRegardlessOfParent ? "-stopProfileRegardlessOfParent" : "")
                 + (allowDelayedLocking ? "-allowDelayedLocking" : "")
                 + (stopUserCallback != null ? "-withStopUserCallback" : "")
                 + "-" + userId + "-[stopUser]");
@@ -987,20 +1006,32 @@
 
             enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
             synchronized (mLock) {
-                return stopUsersLU(userId, force, allowDelayedLocking, stopUserCallback,
-                        keyEvictedCallback);
+                return stopUsersLU(userId, stopProfileRegardlessOfParent, allowDelayedLocking,
+                        stopUserCallback, keyEvictedCallback);
             }
         } finally {
             t.traceEnd();
         }
     }
 
+    /** Stops the user along with its profiles. */
+    @GuardedBy("mLock")
+    private int stopUsersLU(final int userId, boolean allowDelayedLocking,
+            final IStopUserCallback stopUserCallback, KeyEvictedCallback keyEvictedCallback) {
+        return stopUsersLU(userId, /* stopProfileRegardlessOfParent= */ true,
+                allowDelayedLocking, stopUserCallback, keyEvictedCallback);
+    }
+
     /**
      * Stops the user along with its profiles. The method calls
      * {@link #getUsersToStopLU(int)} to determine the list of users that should be stopped.
+     *
+     * @param stopProfileRegardlessOfParent whether to stop the profile regardless of who its
+     *                                      parent is, e.g. even if the parent is the current user
      */
     @GuardedBy("mLock")
-    private int stopUsersLU(final int userId, boolean force, boolean allowDelayedLocking,
+    private int stopUsersLU(final int userId,
+            boolean stopProfileRegardlessOfParent, boolean allowDelayedLocking,
             final IStopUserCallback stopUserCallback, KeyEvictedCallback keyEvictedCallback) {
         if (userId == UserHandle.USER_SYSTEM) {
             return USER_OP_ERROR_IS_SYSTEM;
@@ -1008,34 +1039,28 @@
         if (isCurrentUserLU(userId)) {
             return USER_OP_IS_CURRENT;
         }
-        // TODO(b/324647580): Refactor the idea of "force" and clean up. In the meantime...
-        final int parentId = mUserProfileGroupIds.get(userId, UserInfo.NO_PROFILE_GROUP_ID);
-        if (parentId != UserInfo.NO_PROFILE_GROUP_ID && parentId != userId) {
-            if ((UserHandle.USER_SYSTEM == parentId || isCurrentUserLU(parentId)) && !force) {
-                return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
+        if (!stopProfileRegardlessOfParent) {
+            final int parentId = mUserProfileGroupIds.get(userId, UserInfo.NO_PROFILE_GROUP_ID);
+            if (parentId != UserInfo.NO_PROFILE_GROUP_ID && parentId != userId) {
+                // TODO(b/310249114): Strongly consider *not* exempting the SYSTEM user's profile.
+                if ((UserHandle.USER_SYSTEM == parentId || isCurrentUserLU(parentId))) {
+                    return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
+                }
             }
         }
-        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
-        int[] usersToStop = getUsersToStopLU(userId);
-        // If one of related users is system or current, no related users should be stopped
+        final int[] usersToStop = getUsersToStopLU(userId);
+
+        // Final safety check: abort if one of the users we would plan to stop must not be stopped.
+        // This should be impossible in the current code, but just in case.
         for (int relatedUserId : usersToStop) {
             if ((UserHandle.USER_SYSTEM == relatedUserId) || isCurrentUserLU(relatedUserId)) {
-                if (DEBUG_MU) {
-                    Slogf.i(TAG, "stopUsersLocked cannot stop related user " + relatedUserId);
-                }
-                // We still need to stop the requested user if it's a force stop.
-                if (force) {
-                    Slogf.i(TAG,
-                            "Force stop user " + userId + ". Related users will not be stopped");
-                    t.traceBegin("stopSingleUserLU-force-" + userId + "-[stopUser]");
-                    stopSingleUserLU(userId, allowDelayedLocking, stopUserCallback,
-                            keyEvictedCallback);
-                    t.traceEnd();
-                    return USER_OP_SUCCESS;
-                }
+                Slogf.e(TAG, "Cannot stop user %d because it is related to user %d. ",
+                        userId, relatedUserId);
                 return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
             }
         }
+
+        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
         if (DEBUG_MU) Slogf.i(TAG, "stopUsersLocked usersToStop=" + Arrays.toString(usersToStop));
         for (int userIdToStop : usersToStop) {
             t.traceBegin("stopSingleUserLU-" + userIdToStop + "-[stopUser]");
@@ -1077,6 +1102,10 @@
             final IStopUserCallback stopUserCallback,
             KeyEvictedCallback keyEvictedCallback) {
         Slogf.i(TAG, "stopSingleUserLU userId=" + userId);
+        if (android.multiuser.Flags.scheduleStopOfBackgroundUser()) {
+            mHandler.removeEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG,
+                    Integer.valueOf(userId));
+        }
         final UserState uss = mStartedUsers.get(userId);
         if (uss == null) {  // User is not started
             // If canDelayDataLockingForUser() is true and allowDelayedLocking is false, we need
@@ -1304,8 +1333,8 @@
             mInjector.activityManagerOnUserStopped(userId);
             // Clean up all state and processes associated with the user.
             // Kill all the processes for the user.
-            t.traceBegin("forceStopUser-" + userId + "-[stopUser]");
-            forceStopUser(userId, "finish user");
+            t.traceBegin("stopPackagesOfStoppedUser-" + userId + "-[stopUser]");
+            stopPackagesOfStoppedUser(userId, "finish user");
             t.traceEnd();
         }
 
@@ -1516,8 +1545,8 @@
         return userIds.toArray();
     }
 
-    private void forceStopUser(@UserIdInt int userId, String reason) {
-        if (DEBUG_MU) Slogf.i(TAG, "forceStopUser(%d): %s", userId, reason);
+    private void stopPackagesOfStoppedUser(@UserIdInt int userId, String reason) {
+        if (DEBUG_MU) Slogf.i(TAG, "stopPackagesOfStoppedUser(%d): %s", userId, reason);
         mInjector.activityManagerForceStopPackage(userId, reason);
         if (mInjector.getUserManager().isPreCreated(userId)) {
             // Don't fire intent for precreated.
@@ -1566,8 +1595,7 @@
             // This is a user to be stopped.
             Slogf.i(TAG, "Stopping background guest or ephemeral user " + oldUserId);
             synchronized (mLock) {
-                stopUsersLU(oldUserId, /* force= */ true, /* allowDelayedLocking= */ false,
-                        null, null);
+                stopUsersLU(oldUserId, /* allowDelayedLocking= */ false, null, null);
             }
         }
     }
@@ -1866,6 +1894,10 @@
             // No matter what, the fact that we're requested to start the user (even if it is
             // already running) puts it towards the end of the mUserLru list.
             addUserToUserLru(userId);
+            if (android.multiuser.Flags.scheduleStopOfBackgroundUser()) {
+                mHandler.removeEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG,
+                        Integer.valueOf(userId));
+            }
 
             if (unlockListener != null) {
                 uss.mUnlockProgress.addListener(unlockListener);
@@ -1910,6 +1942,9 @@
                 // of mUserLru, so we need to ensure that the foreground user isn't displaced.
                 addUserToUserLru(mCurrentUserId);
             }
+            if (userStartMode == USER_START_MODE_BACKGROUND && !userInfo.isProfile()) {
+                scheduleStopOfBackgroundUser(userId);
+            }
             t.traceEnd();
 
             // Make sure user is in the started state.  If it is currently
@@ -2259,8 +2294,7 @@
             // If running in background is disabled or mStopUserOnSwitch mode, stop the user.
             if (hasRestriction || shouldStopUserOnSwitch()) {
                 Slogf.i(TAG, "Stopping user %d and its profiles on user switch", oldUserId);
-                stopUsersLU(oldUserId, /* force= */ false, /* allowDelayedLocking= */ false,
-                        null, null);
+                stopUsersLU(oldUserId, /* allowDelayedLocking= */ false, null, null);
                 return;
             }
         }
@@ -2275,12 +2309,72 @@
                 Slogf.i(TAG, "Stopping profile %d on user switch", profileUserId);
                 synchronized (mLock) {
                     stopUsersLU(profileUserId,
-                            /* force= */ true, /* allowDelayedLocking= */ false, null, null);
+                            /* stopProfileRegardlessOfParent= */ false,
+                            /* allowDelayedLocking= */ false, null, null);
                 }
             }
         }
     }
 
+    /**
+     * Possibly schedules the user to be stopped at a future point. To be used to stop background
+     * users that haven't been actively used in a long time.
+     * This is only intended for full users that are currently in the background.
+     */
+    private void scheduleStopOfBackgroundUser(@UserIdInt int oldUserId) {
+        if (!android.multiuser.Flags.scheduleStopOfBackgroundUser()) {
+            return;
+        }
+        final int delayUptimeSecs = mBackgroundUserScheduledStopTimeSecs;
+        if (delayUptimeSecs <= 0 || UserManager.isVisibleBackgroundUsersEnabled()) {
+            // Feature is not enabled on this device.
+            return;
+        }
+        if (oldUserId == UserHandle.USER_SYSTEM) {
+            // Never stop system user
+            return;
+        }
+        if (oldUserId == mInjector.getUserManagerInternal().getMainUserId()) {
+            // MainUser is currently special for things like Docking, so we'll exempt it for now.
+            Slogf.i(TAG, "Exempting user %d from being stopped due to inactivity by virtue "
+                    + "of it being the main user", oldUserId);
+            return;
+        }
+        Slogf.d(TAG, "Scheduling to stop user %d in %d seconds", oldUserId, delayUptimeSecs);
+        final int delayUptimeMs = delayUptimeSecs * 1000;
+        final Object msgObj = oldUserId;
+        mHandler.removeEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, msgObj);
+        mHandler.sendMessageDelayed(
+                mHandler.obtainMessage(SCHEDULED_STOP_BACKGROUND_USER_MSG, msgObj),
+                delayUptimeMs);
+    }
+
+    /**
+     * Possibly stops the given full user due to it having been in the background for a long time.
+     * There is no guarantee of stopping the user; it is done discretionarily.
+     *
+     * This should never be called for background visible users; devices that support this should
+     * not use {@link #scheduleStopOfBackgroundUser(int)}.
+     *
+     * @param userIdInteger a full user to be stopped if it is still in the background
+     */
+    @VisibleForTesting
+    void processScheduledStopOfBackgroundUser(Integer userIdInteger) {
+        final int userId = userIdInteger;
+        Slogf.d(TAG, "Considering stopping background user %d due to inactivity", userId);
+        synchronized (mLock) {
+            if (getCurrentOrTargetUserIdLU() == userId) {
+                return;
+            }
+            if (mPendingTargetUserIds.contains(userIdInteger)) {
+                // We'll soon want to switch to this user, so don't kill it now.
+                return;
+            }
+            Slogf.i(TAG, "Stopping background user %d due to inactivity", userId);
+            stopUsersLU(userId, /* allowDelayedLocking= */ true, null, null);
+        }
+    }
+
     private void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) {
         TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
         t.traceBegin("timeoutUserSwitch-" + oldUserId + "-to-" + newUserId);
@@ -2415,6 +2509,7 @@
         uss.switching = false;
         stopGuestOrEphemeralUserIfBackground(oldUserId);
         stopUserOnSwitchIfEnforced(oldUserId);
+        scheduleStopOfBackgroundUser(oldUserId);
 
         t.traceEnd(); // end continueUserSwitch
     }
@@ -3296,6 +3391,8 @@
             pw.println("  shouldStopUserOnSwitch():" + shouldStopUserOnSwitch());
             pw.println("  mStopUserOnSwitch:" + mStopUserOnSwitch);
             pw.println("  mMaxRunningUsers:" + mMaxRunningUsers);
+            pw.println("  mBackgroundUserScheduledStopTimeSecs:"
+                    + mBackgroundUserScheduledStopTimeSecs);
             pw.println("  mUserSwitchUiEnabled:" + mUserSwitchUiEnabled);
             pw.println("  mInitialized:" + mInitialized);
             pw.println("  mIsBroadcastSentForSystemUserStarted:"
@@ -3422,6 +3519,9 @@
             case COMPLETE_USER_SWITCH_MSG:
                 completeUserSwitch(msg.arg1, msg.arg2);
                 break;
+            case SCHEDULED_STOP_BACKGROUND_USER_MSG:
+                processScheduledStopOfBackgroundUser((Integer) msg.obj);
+                break;
         }
         return false;
     }
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index fd847f1..19be5f9 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.am"
+container: "system"
 
 flag {
     name: "oomadjuster_correctness_rewrite"
@@ -94,3 +95,14 @@
     bug: "315468967"
     is_fixed_read_only: true
 }
+
+flag {
+    namespace: "backstage_power"
+    name: "trace_receiver_registration"
+    description: "Add tracing for broadcast receiver registration and un-registration"
+    bug: "336385821"
+    is_fixed_read_only: true
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index a17b3d5..ce41079 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -461,6 +461,9 @@
                     packageName, PACKAGE_MATCH_FLAGS, userId);
             StorageStats stats = mStorageStatsManager.queryStatsForPackage(
                     info.storageUuid, packageName, new UserHandle(userId));
+            if (android.app.Flags.appRestrictionsApi()) {
+                noteHibernationChange(packageName, info.uid, true);
+            }
             mIActivityManager.forceStopPackage(packageName, userId);
             mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
                     null /* observer */);
@@ -490,6 +493,11 @@
         // Deliver LOCKED_BOOT_COMPLETE AND BOOT_COMPLETE broadcast so app can re-register
         // their alarms/jobs/etc.
         try {
+            if (android.app.Flags.appRestrictionsApi()) {
+                ApplicationInfo info = mIPackageManager.getApplicationInfo(
+                        packageName, PACKAGE_MATCH_FLAGS, userId);
+                noteHibernationChange(packageName, info.uid, false);
+            }
             Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)
                     .setPackage(packageName);
             final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED};
@@ -555,6 +563,26 @@
         Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
     }
 
+    /** Inform ActivityManager that the app being stopped or unstopped due to hibernation */
+    private void noteHibernationChange(String packageName, int uid, boolean hibernated) {
+        try {
+            if (hibernated) {
+                // TODO: Switch to an ActivityManagerInternal API
+                mIActivityManager.noteAppRestrictionEnabled(
+                        packageName, uid, ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED,
+                        true, ActivityManager.RESTRICTION_REASON_DORMANT, null,
+                        /* TODO: fetch actual timeout - 90 days */ 90 * 24 * 60 * 60_000L);
+            } else {
+                mIActivityManager.noteAppRestrictionEnabled(
+                        packageName, uid, ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED,
+                        false, ActivityManager.RESTRICTION_REASON_USAGE, null,
+                        0L);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Couldn't set restriction state change");
+        }
+    }
+
     /**
      * Initializes in-memory store of user-level hibernation states for the given user
      *
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index debd9d0..e59de6a 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -70,6 +70,7 @@
 import static android.content.Intent.EXTRA_REPLACING;
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
+import static android.permission.flags.Flags.runtimePermissionAppopsMappingEnabled;
 
 import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
 
@@ -248,6 +249,7 @@
             Process.ROOT_UID,
             Process.PHONE_UID,
             Process.BLUETOOTH_UID,
+            Process.AUDIOSERVER_UID,
             Process.NFC_UID,
             Process.NETWORK_STACK_UID,
             Process.SHELL_UID};
@@ -1364,6 +1366,9 @@
 
     @GuardedBy("this")
     private void packageRemovedLocked(int uid, String packageName) {
+        mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::clearHistory,
+                mHistoricalRegistry, uid, packageName));
+
         UidState uidState = mUidStates.get(uid);
         if (uidState == null) {
             return;
@@ -1398,9 +1403,6 @@
                 }
             }
         }
-
-        mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::clearHistory,
-                    mHistoricalRegistry, uid, packageName));
     }
 
     public void uidRemoved(int uid) {
@@ -2682,6 +2684,15 @@
         }
     }
 
+    /**
+     * When querying the mode these should always be allowed and the checking service might not
+     * have information on them.
+     */
+    private static boolean isOpAllowedForUid(int uid) {
+        return runtimePermissionAppopsMappingEnabled()
+                && (uid == Process.ROOT_UID || uid == Process.SYSTEM_UID);
+    }
+
     @Override
     public int checkOperationRaw(int code, int uid, String packageName,
             @Nullable String attributionTag) {
@@ -2757,17 +2768,20 @@
                     pvr.bypass, true)) {
                 return AppOpsManager.MODE_IGNORED;
             }
+            if (isOpAllowedForUid(uid)) {
+                return MODE_ALLOWED;
+            }
             code = AppOpsManager.opToSwitch(code);
             UidState uidState = getUidStateLocked(uid, false);
-            if (uidState != null
-                    && mAppOpsCheckingService.getUidMode(
-                                    uidState.uid, getPersistentId(virtualDeviceId), code)
-                            != AppOpsManager.opToDefaultMode(code)) {
-                final int rawMode =
-                        mAppOpsCheckingService.getUidMode(
-                                uidState.uid, getPersistentId(virtualDeviceId), code);
-                return raw ? rawMode : uidState.evalMode(code, rawMode);
+            if (uidState != null) {
+                int rawUidMode = mAppOpsCheckingService.getUidMode(
+                        uidState.uid, getPersistentId(virtualDeviceId), code);
+
+                if (rawUidMode != AppOpsManager.opToDefaultMode(code)) {
+                    return raw ? rawUidMode : uidState.evalMode(code, rawUidMode);
+                }
             }
+
             Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
@@ -3071,9 +3085,12 @@
                 return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
                         packageName);
             }
-            // If there is a non-default per UID policy (we set UID op mode only if
-            // non-default) it takes over, otherwise use the per package policy.
-            if (mAppOpsCheckingService.getUidMode(
+            if (isOpAllowedForUid(uid)) {
+                // Op is always allowed for the UID, do nothing.
+
+                // If there is a non-default per UID policy (we set UID op mode only if
+                // non-default) it takes over, otherwise use the per package policy.
+            } else if (mAppOpsCheckingService.getUidMode(
                             uidState.uid, getPersistentId(virtualDeviceId), switchCode)
                     != AppOpsManager.opToDefaultMode(switchCode)) {
                 final int uidMode =
@@ -3665,23 +3682,24 @@
             isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag,
                     virtualDeviceId, pvr.bypass, false);
             final int switchCode = AppOpsManager.opToSwitch(code);
-            // If there is a non-default per UID policy (we set UID op mode only if
-            // non-default) it takes over, otherwise use the per package policy.
-            if (mAppOpsCheckingService.getUidMode(
-                            uidState.uid, getPersistentId(virtualDeviceId), switchCode)
+
+            int rawUidMode;
+            if (isOpAllowedForUid(uid)) {
+                // Op is always allowed for the UID, do nothing.
+
+                // If there is a non-default per UID policy (we set UID op mode only if
+                // non-default) it takes over, otherwise use the per package policy.
+            } else if ((rawUidMode =
+                            mAppOpsCheckingService.getUidMode(
+                                    uidState.uid, getPersistentId(virtualDeviceId), switchCode))
                     != AppOpsManager.opToDefaultMode(switchCode)) {
-                final int uidMode =
-                        uidState.evalMode(
-                                code,
-                                mAppOpsCheckingService.getUidMode(
-                                        uidState.uid,
-                                        getPersistentId(virtualDeviceId),
-                                        switchCode));
+                final int uidMode = uidState.evalMode(code, rawUidMode);
                 if (!shouldStartForMode(uidMode, startIfModeDefault)) {
                     if (DEBUG) {
                         Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code "
                                 + switchCode + " (" + code + ") uid " + uid + " package "
-                                + packageName + " flags: " + AppOpsManager.flagsToString(flags));
+                                + packageName + " flags: "
+                                + AppOpsManager.flagsToString(flags));
                     }
                     attributedOp.rejected(uidState.getState(), flags);
                     scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
@@ -3690,8 +3708,8 @@
                     return new SyncNotedAppOp(uidMode, code, attributionTag, packageName);
                 }
             } else {
-                final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true)
-                        : op;
+                final Op switchOp =
+                        switchCode != code ? getOpLocked(ops, switchCode, uid, true) : op;
                 final int mode =
                         switchOp.uidState.evalMode(
                                 switchOp.op,
@@ -3701,9 +3719,12 @@
                                         UserHandle.getUserId(switchOp.uid)));
                 if (mode != AppOpsManager.MODE_ALLOWED
                         && (!startIfModeDefault || mode != MODE_DEFAULT)) {
-                    if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
-                            + switchCode + " (" + code + ") uid " + uid + " package "
-                            + packageName + " flags: " + AppOpsManager.flagsToString(flags));
+                    if (DEBUG) {
+                        Slog.d(TAG, "startOperation: reject #" + mode + " for code "
+                                + switchCode + " (" + code + ") uid " + uid + " package "
+                                + packageName + " flags: "
+                                + AppOpsManager.flagsToString(flags));
+                    }
                     attributedOp.rejected(uidState.getState(), flags);
                     scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
                             virtualDeviceId, flags, mode, startType, attributionFlags,
@@ -3711,6 +3732,7 @@
                     return new SyncNotedAppOp(mode, code, attributionTag, packageName);
                 }
             }
+
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName + " restricted: " + isRestricted
                     + " flags: " + AppOpsManager.flagsToString(flags));
@@ -4707,9 +4729,14 @@
         }
 
         if ((code == OP_CAMERA) && isAutomotive()) {
-            if ((Flags.cameraPrivacyAllowlist())
-                    && (mSensorPrivacyManager.isCameraPrivacyEnabled(packageName))) {
-                return true;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if ((Flags.cameraPrivacyAllowlist())
+                        && (mSensorPrivacyManager.isCameraPrivacyEnabled(packageName))) {
+                    return true;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
@@ -5523,6 +5550,20 @@
                     }
                     return 0;
                 }
+                case "note": {
+                    int res = shell.parseUserPackageOp(true, err);
+                    if (res < 0) {
+                        return res;
+                    }
+                    if (shell.packageName != null) {
+                        shell.mInterface.noteOperation(shell.op, shell.packageUid,
+                                shell.packageName, shell.attributionTag, true,
+                                "appops note shell command", true);
+                    } else {
+                        return -1;
+                    }
+                    return 0;
+                }
                 case "start": {
                     int res = shell.parseUserPackageOp(true, err);
                     if (res < 0) {
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 6f3526f..dbd47d0 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -54,13 +54,13 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.AtomicDirectory;
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.FgThread;
+import com.android.server.IoThread;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -669,7 +669,7 @@
     }
 
     private void clearHistoryOnDiskDLocked() {
-        BackgroundThread.getHandler().removeMessages(MSG_WRITE_PENDING_HISTORY);
+        IoThread.getHandler().removeMessages(MSG_WRITE_PENDING_HISTORY);
         synchronized (mInMemoryLock) {
             mCurrentHistoricalOps = null;
             mNextPersistDueTimeMillis = System.currentTimeMillis();
@@ -745,7 +745,7 @@
 
     private void persistPendingHistory(@NonNull List<HistoricalOps> pendingWrites) {
         synchronized (mOnDiskLock) {
-            BackgroundThread.getHandler().removeMessages(MSG_WRITE_PENDING_HISTORY);
+            IoThread.getHandler().removeMessages(MSG_WRITE_PENDING_HISTORY);
             if (pendingWrites.isEmpty()) {
                 return;
             }
@@ -767,7 +767,7 @@
         final Message message = PooledLambda.obtainMessage(
                 HistoricalRegistry::persistPendingHistory, HistoricalRegistry.this);
         message.what = MSG_WRITE_PENDING_HISTORY;
-        BackgroundThread.getHandler().sendMessage(message);
+        IoThread.getHandler().sendMessage(message);
         mPendingWrites.offerFirst(ops);
     }
 
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 951f676..77654d4 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1517,8 +1517,9 @@
         sendLMsgNoDelay(MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY, SENDMSG_QUEUE, deviceState);
     }
 
-    /*package*/ void postUpdatedAdiDeviceState(AdiDeviceState deviceState) {
-        sendLMsgNoDelay(MSG_L_UPDATED_ADI_DEVICE_STATE, SENDMSG_QUEUE, deviceState);
+    /*package*/ void postUpdatedAdiDeviceState(AdiDeviceState deviceState, boolean initSA) {
+        sendILMsgNoDelay(
+                MSG_IL_UPDATED_ADI_DEVICE_STATE, SENDMSG_QUEUE, initSA ? 1 : 0, deviceState);
     }
 
     /*package*/ static final class CommunicationDeviceInfo {
@@ -1820,18 +1821,17 @@
                                         + "received with null profile proxy: "
                                         + btInfo)).printLog(TAG));
                     } else {
-                        @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
+                        final Pair<Integer, Boolean> codecAndChanged =
                                 mBtHelper.getCodecWithFallback(btInfo.mDevice,
                                         btInfo.mProfile, btInfo.mIsLeOutput,
                                         "MSG_L_SET_BT_ACTIVE_DEVICE");
                         synchronized (mSetModeLock) {
                             synchronized (mDeviceStateLock) {
-                                mDeviceInventory.onSetBtActiveDevice(btInfo, codec,
-                                        (btInfo.mProfile
-                                                != BluetoothProfile.LE_AUDIO
+                                mDeviceInventory.onSetBtActiveDevice(btInfo, codecAndChanged.first,
+                                        (btInfo.mProfile != BluetoothProfile.LE_AUDIO
                                                 || btInfo.mIsLeOutput)
-                                                ? mAudioService.getBluetoothContextualVolumeStream()
-                                                : AudioSystem.STREAM_DEFAULT);
+                                            ? mAudioService.getBluetoothContextualVolumeStream()
+                                            : AudioSystem.STREAM_DEFAULT);
                                 if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
                                         || btInfo.mProfile
                                         == BluetoothProfile.HEARING_AID) {
@@ -1866,13 +1866,13 @@
                     break;
                 case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: {
                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
-                    @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
-                            mBtHelper.getCodecWithFallback(btInfo.mDevice,
-                                    btInfo.mProfile, btInfo.mIsLeOutput,
-                                    "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
+                    final Pair<Integer, Boolean> codecAndChanged = mBtHelper.getCodecWithFallback(
+                            btInfo.mDevice, btInfo.mProfile, btInfo.mIsLeOutput,
+                            "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
                     synchronized (mDeviceStateLock) {
-                        mDeviceInventory.onBluetoothDeviceConfigChange(
-                                btInfo, codec, BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
+                        mDeviceInventory.onBluetoothDeviceConfigChange(btInfo,
+                                codecAndChanged.first, codecAndChanged.second,
+                                BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
                     }
                 } break;
                 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
@@ -2049,8 +2049,8 @@
                         }
                     } break;
 
-                case MSG_L_UPDATED_ADI_DEVICE_STATE:
-                    mAudioService.onUpdatedAdiDeviceState((AdiDeviceState) msg.obj);
+                case MSG_IL_UPDATED_ADI_DEVICE_STATE:
+                    mAudioService.onUpdatedAdiDeviceState((AdiDeviceState) msg.obj, msg.arg1 == 1);
                     break;
 
                 default:
@@ -2137,7 +2137,7 @@
     private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56;
     private static final int MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES = 57;
     private static final int MSG_L_SYNCHRONIZE_ADI_DEVICES_IN_INVENTORY = 58;
-    private static final int MSG_L_UPDATED_ADI_DEVICE_STATE = 59;
+    private static final int MSG_IL_UPDATED_ADI_DEVICE_STATE = 59;
 
 
 
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 14428c4..9bdc51e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -173,7 +173,7 @@
                 if (ads.getAudioDeviceCategory() != category && (userDefined
                         || category != AUDIO_DEVICE_CATEGORY_UNKNOWN)) {
                     ads.setAudioDeviceCategory(category);
-                    mDeviceBroker.postUpdatedAdiDeviceState(ads);
+                    mDeviceBroker.postUpdatedAdiDeviceState(ads, false /*initSA*/);
                     mDeviceBroker.postPersistAudioDeviceSettings();
                 }
                 mDeviceBroker.postSynchronizeAdiDevicesInInventory(ads);
@@ -186,7 +186,7 @@
             mDeviceInventory.put(ads.getDeviceId(), ads);
             checkDeviceInventorySize_l();
 
-            mDeviceBroker.postUpdatedAdiDeviceState(ads);
+            mDeviceBroker.postUpdatedAdiDeviceState(ads, true /*initSA*/);
             mDeviceBroker.postPersistAudioDeviceSettings();
         }
     }
@@ -216,7 +216,7 @@
             checkDeviceInventorySize_l();
         }
         if (updatedCategory.get()) {
-            mDeviceBroker.postUpdatedAdiDeviceState(deviceState);
+            mDeviceBroker.postUpdatedAdiDeviceState(deviceState, false /*initSA*/);
         }
         mDeviceBroker.postSynchronizeAdiDevicesInInventory(deviceState);
     }
@@ -318,7 +318,7 @@
                     }
                     ads2.setAudioDeviceCategory(updatedDevice.getAudioDeviceCategory());
 
-                    mDeviceBroker.postUpdatedAdiDeviceState(ads2);
+                    mDeviceBroker.postUpdatedAdiDeviceState(ads2, false /*initSA*/);
                     AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                             "synchronizeBleDeviceInInventory synced device pair ads1="
                                     + updatedDevice + " ads2=" + ads2).printLog(TAG));
@@ -339,7 +339,7 @@
                     }
                     ads2.setAudioDeviceCategory(updatedDevice.getAudioDeviceCategory());
 
-                    mDeviceBroker.postUpdatedAdiDeviceState(ads2);
+                    mDeviceBroker.postUpdatedAdiDeviceState(ads2, false /*initSA*/);
                     AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                             "synchronizeBleDeviceInInventory synced device pair ads1="
                                     + updatedDevice + " peer ads2=" + ads2).printLog(TAG));
@@ -364,7 +364,7 @@
             }
             ads.setAudioDeviceCategory(updatedDevice.getAudioDeviceCategory());
 
-            mDeviceBroker.postUpdatedAdiDeviceState(ads);
+            mDeviceBroker.postUpdatedAdiDeviceState(ads, false /*initSA*/);
             AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                     "synchronizeDeviceProfilesInInventory synced device pair ads1="
                             + updatedDevice + " ads2=" + ads).printLog(TAG));
@@ -868,7 +868,8 @@
     @GuardedBy("mDeviceBroker.mDeviceStateLock")
     /*package*/ void onBluetoothDeviceConfigChange(
             @NonNull AudioDeviceBroker.BtDeviceInfo btInfo,
-            @AudioSystem.AudioFormatNativeEnumForBtCodec int codec, int event) {
+            @AudioSystem.AudioFormatNativeEnumForBtCodec int codec,
+            boolean codecChanged, int event) {
         MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
                 + "onBluetoothDeviceConfigChange")
                 .set(MediaMetrics.Property.EVENT, BtHelper.deviceEventToString(event));
@@ -916,14 +917,12 @@
 
 
             if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
-                boolean codecChange = false;
                 if (btInfo.mProfile == BluetoothProfile.A2DP
                         || btInfo.mProfile == BluetoothProfile.LE_AUDIO
                         || btInfo.mProfile == BluetoothProfile.LE_AUDIO_BROADCAST) {
-                    if (di.mDeviceCodecFormat != codec) {
+                    if (codecChanged) {
                         di.mDeviceCodecFormat = codec;
                         mConnectedDevices.replace(key, di);
-                        codecChange = true;
                         final int res = mAudioSystem.handleDeviceConfigChange(
                                 btInfo.mAudioSystemDevice, address,
                                 BtHelper.getName(btDevice), codec);
@@ -947,7 +946,7 @@
                         }
                     }
                 }
-                if (!codecChange) {
+                if (!codecChanged) {
                     updateBluetoothPreferredModes_l(btDevice /*connectedDevice*/);
                 }
             }
@@ -988,9 +987,9 @@
                     }
                     if (di.mPeerDeviceAddress.equals("")) {
                         for (Pair<String, String> addr : addresses) {
-                            if (!addr.first.equals(di.mDeviceAddress)) {
-                                di.mPeerDeviceAddress = addr.first;
-                                di.mPeerIdentityDeviceAddress = addr.second;
+                            if (!di.mDeviceAddress.equals(addr.first)) {
+                                di.mPeerDeviceAddress = TextUtils.emptyIfNull(addr.first);
+                                di.mPeerIdentityDeviceAddress = TextUtils.emptyIfNull(addr.second);
                                 break;
                             }
                         }
@@ -1001,8 +1000,8 @@
                     }
                     if (di.mDeviceIdentityAddress.equals("")) {
                         for (Pair<String, String> addr : addresses) {
-                            if (addr.first.equals(di.mDeviceAddress)) {
-                                di.mDeviceIdentityAddress = addr.second;
+                            if (di.mDeviceAddress.equals(addr.first)) {
+                                di.mDeviceIdentityAddress = TextUtils.emptyIfNull(addr.second);
                                 break;
                             }
                         }
diff --git a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
index 570d4e9..e330ed5 100644
--- a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
+++ b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
@@ -16,6 +16,11 @@
 
 package com.android.server.audio;
 
+import static android.media.AudioManager.ADJUST_LOWER;
+import static android.media.AudioManager.ADJUST_MUTE;
+import static android.media.AudioManager.ADJUST_RAISE;
+import static android.media.AudioManager.ADJUST_UNMUTE;
+
 import android.content.Context;
 import android.media.AudioManager;
 import android.os.ShellCommand;
@@ -59,6 +64,12 @@
                 return adjMute();
             case "adj-unmute":
                 return adjUnmute();
+            case "adj-volume":
+                return adjVolume();
+            case "set-group-volume":
+                return setGroupVolume();
+            case "adj-group-volume":
+                return adjGroupVolume();
         }
         return 0;
     }
@@ -90,6 +101,12 @@
         pw.println("    mutes the STREAM_TYPE");
         pw.println("  adj-unmute STREAM_TYPE");
         pw.println("    unmutes the STREAM_TYPE");
+        pw.println("  adj-volume STREAM_TYPE <RAISE|LOWER|MUTE|UNMUTE>");
+        pw.println("    Adjusts the STREAM_TYPE volume given the specified direction");
+        pw.println("  set-group-volume GROUP_ID VOLUME_INDEX");
+        pw.println("    Sets the volume for GROUP_ID to VOLUME_INDEX");
+        pw.println("  adj-group-volume GROUP_ID <RAISE|LOWER|MUTE|UNMUTE>");
+        pw.println("    Adjusts the group volume for GROUP_ID given the specified direction");
     }
 
     private int setSurroundFormatEnabled() {
@@ -260,15 +277,48 @@
         return 0;
     }
 
+    private int adjVolume() {
+        final Context context = mService.mContext;
+        final AudioManager am = context.getSystemService(AudioManager.class);
+        final int stream = readIntArg();
+        final int direction = readDirectionArg();
+        getOutPrintWriter().println("calling AudioManager.adjustStreamVolume("
+                + stream + ", " + direction + ", 0)");
+        am.adjustStreamVolume(stream, direction, 0);
+        return 0;
+    }
+
+    private int setGroupVolume() {
+        final Context context = mService.mContext;
+        final AudioManager am = context.getSystemService(AudioManager.class);
+        final int groupId = readIntArg();
+        final int index = readIntArg();
+        getOutPrintWriter().println("calling AudioManager.setVolumeGroupVolumeIndex("
+                + groupId + ", " + index + ", 0)");
+        am.setVolumeGroupVolumeIndex(groupId, index, 0);
+        return 0;
+    }
+
+    private int adjGroupVolume() {
+        final Context context = mService.mContext;
+        final AudioManager am = context.getSystemService(AudioManager.class);
+        final int groupId = readIntArg();
+        final int direction = readDirectionArg();
+        getOutPrintWriter().println("calling AudioManager.adjustVolumeGroupVolume("
+                + groupId + ", " + direction + ", 0)");
+        am.adjustVolumeGroupVolume(groupId, direction, 0);
+        return 0;
+    }
+
     private int readIntArg() throws IllegalArgumentException {
-        String argText = getNextArg();
+        final String argText = getNextArg();
 
         if (argText == null) {
             getErrPrintWriter().println("Error: no argument provided");
             throw new IllegalArgumentException("No argument provided");
         }
 
-        int argIntVal = Integer.MIN_VALUE;
+        int argIntVal;
         try {
             argIntVal = Integer.parseInt(argText);
         } catch (NumberFormatException e) {
@@ -278,4 +328,21 @@
 
         return argIntVal;
     }
+
+    private int readDirectionArg() throws IllegalArgumentException {
+        final String argText = getNextArg();
+
+        if (argText == null) {
+            getErrPrintWriter().println("Error: no argument provided");
+            throw new IllegalArgumentException("No argument provided");
+        }
+
+        return switch (argText) {
+            case "RAISE" -> ADJUST_RAISE;
+            case "LOWER" -> ADJUST_LOWER;
+            case "MUTE" -> ADJUST_MUTE;
+            case "UNMUTE" -> ADJUST_UNMUTE;
+            default -> throw new IllegalArgumentException("Wrong direction argument: " + argText);
+        };
+    }
 }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ed58c40..add8491 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -47,6 +47,7 @@
 import static com.android.media.audio.Flags.disablePrescaleAbsoluteVolume;
 import static com.android.media.audio.Flags.ringerModeAffectsAlarm;
 import static com.android.media.audio.Flags.setStreamVolumeOrder;
+import static com.android.media.audio.Flags.vgsVssSyncMuteOrder;
 import static com.android.server.audio.SoundDoseHelper.ACTION_CHECK_MUSIC_ACTIVE;
 import static com.android.server.utils.EventLogger.Event.ALOGE;
 import static com.android.server.utils.EventLogger.Event.ALOGI;
@@ -175,6 +176,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.HwBinder;
 import android.os.IBinder;
 import android.os.Looper;
@@ -685,6 +687,9 @@
     private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
 
+    // Handler for broadcast receiver
+    // TODO(b/335513647) combine handlers
+    private final HandlerThread mBroadcastHandlerThread;
     // Broadcast receiver for device connections intent broadcasts
     private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
 
@@ -1120,6 +1125,9 @@
         mAudioPolicy = audioPolicy;
         mPlatformType = AudioSystem.getPlatformType(context);
 
+        mBroadcastHandlerThread = new HandlerThread("AudioService Broadcast");
+        mBroadcastHandlerThread.start();
+
         mDeviceBroker = new AudioDeviceBroker(mContext, this, mAudioSystem);
 
         mIsSingleVolume = AudioSystem.isSingleVolume(context);
@@ -1506,7 +1514,8 @@
         intentFilter.addAction(ACTION_CHECK_MUSIC_ACTIVE);
         intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
 
-        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null,
+        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null,
+                mBroadcastHandlerThread.getThreadHandler(),
                 Context.RECEIVER_EXPORTED);
 
         SubscriptionManager subscriptionManager = mContext.getSystemService(
@@ -4544,6 +4553,8 @@
                 + setStreamVolumeOrder());
         pw.println("\tandroid.media.audio.roForegroundAudioControl:"
                 + roForegroundAudioControl());
+        pw.println("\tcom.android.media.audio.vgsVssSyncMuteOrder:"
+                + vgsVssSyncMuteOrder());
     }
 
     private void dumpAudioMode(PrintWriter pw) {
@@ -4671,6 +4682,12 @@
         int streamTypeAlias = mStreamVolumeAlias[streamType];
         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
 
+        if ((streamType == AudioManager.STREAM_VOICE_CALL)
+                && isInCommunication() && mDeviceBroker.isBluetoothScoActive()) {
+            Log.i(TAG, "setStreamVolume for STREAM_VOICE_CALL, switching to STREAM_BLUETOOTH_SCO");
+            streamType = AudioManager.STREAM_BLUETOOTH_SCO;
+        }
+
         final int device = (ada == null)
                 ? getDeviceForStream(streamType)
                 : ada.getInternalType();
@@ -5461,19 +5478,19 @@
 
     /** @see AudioManager#setMicrophoneMuteFromSwitch(boolean) */
     public void setMicrophoneMuteFromSwitch(boolean on) {
-        int userId = Binder.getCallingUid();
-        if (userId != android.os.Process.SYSTEM_UID) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != android.os.Process.SYSTEM_UID) {
             Log.e(TAG, "setMicrophoneMuteFromSwitch() called from non system user!");
             return;
         }
         mMicMuteFromSwitch = on;
         new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
-                .setUid(userId)
+                .setUid(callingUid)
                 .set(MediaMetrics.Property.EVENT, "setMicrophoneMuteFromSwitch")
                 .set(MediaMetrics.Property.REQUEST, on
                         ? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE)
                 .record();
-        setMicrophoneMuteNoCallerCheck(userId);
+        setMicrophoneMuteNoCallerCheck(UserHandle.getCallingUserId());
     }
 
     private void setMicMuteFromSwitchInput() {
@@ -5504,9 +5521,10 @@
         if (DEBUG_VOL) {
             Log.d(TAG, String.format("Mic mute %b, user=%d", muted, userId));
         }
-        // only mute for the current user
-        if (getCurrentUserId() == userId || userId == android.os.Process.SYSTEM_UID) {
+        // only mute for the current user or for the system user.
+        if (getCurrentUserId() == userId || userId == UserHandle.USER_SYSTEM) {
             final boolean currentMute = mAudioSystem.isMicrophoneMuted();
+            int callingUid = Binder.getCallingUid();
             final long identity = Binder.clearCallingIdentity();
             try {
                 final int ret = mAudioSystem.muteMicrophone(muted);
@@ -5519,7 +5537,7 @@
                 }
 
                 new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
-                        .setUid(userId)
+                        .setUid(callingUid)
                         .set(MediaMetrics.Property.EVENT, "setMicrophoneMuteNoCallerCheck")
                         .set(MediaMetrics.Property.MUTE, mMicMuteFromSystemCached
                                 ? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
@@ -7900,6 +7918,7 @@
         DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
         DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
         DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
         DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
         DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
         DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
@@ -8317,13 +8336,23 @@
                                         synced = true;
                                         continue;
                                     }
+                                    if (vgsVssSyncMuteOrder()) {
+                                        if ((isMuted() != streamMuted) && isVssMuteBijective(
+                                                stream)) {
+                                            mStreamStates[stream].mute(isMuted(),
+                                                    "VGS.applyAllVolumes#1");
+                                        }
+                                    }
                                     if (indexForStream != index) {
                                         mStreamStates[stream].setIndex(index * 10, device, caller,
                                                 true /*hasModifyAudioSettings*/);
                                     }
-                                    if ((isMuted() != streamMuted) && isVssMuteBijective(stream)) {
-                                        mStreamStates[stream].mute(isMuted(),
-                                                "VGS.applyAllVolumes#1");
+                                    if (!vgsVssSyncMuteOrder()) {
+                                        if ((isMuted() != streamMuted) && isVssMuteBijective(
+                                                stream)) {
+                                            mStreamStates[stream].mute(isMuted(),
+                                                    "VGS.applyAllVolumes#1");
+                                        }
                                     }
                                 }
                             }
@@ -8855,6 +8884,7 @@
             boolean changed;
             int oldIndex;
             final boolean isCurrentDevice;
+            final StringBuilder aliasStreamIndexes = new StringBuilder();
             synchronized (mSettingsLock) {
                 synchronized (VolumeStreamState.class) {
                     oldIndex = getIndex(device);
@@ -8881,13 +8911,17 @@
                                 (changed || !aliasStreamState.hasIndexForDevice(device))) {
                             final int scaledIndex =
                                     rescaleIndex(aliasIndex, mStreamType, streamType);
-                            aliasStreamState.setIndex(scaledIndex, device, caller,
-                                    hasModifyAudioSettings);
+                            boolean changedAlias = aliasStreamState.setIndex(scaledIndex, device,
+                                    caller, hasModifyAudioSettings);
                             if (isCurrentDevice) {
-                                aliasStreamState.setIndex(scaledIndex,
+                                changedAlias |= aliasStreamState.setIndex(scaledIndex,
                                         getDeviceForStream(streamType), caller,
                                         hasModifyAudioSettings);
                             }
+                            if (changedAlias) {
+                                aliasStreamIndexes.append(AudioSystem.streamToString(streamType))
+                                        .append(":").append((scaledIndex + 5) / 10).append(" ");
+                            }
                         }
                     }
                     // Mirror changes in SPEAKER ringtone volume on SCO when
@@ -8927,8 +8961,15 @@
                                 oldIndex);
                         mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
                                 mStreamVolumeAlias[mStreamType]);
-                        AudioService.sVolumeLogger.enqueue(new VolChangedBroadcastEvent(
-                                mStreamType, mStreamVolumeAlias[mStreamType], index, oldIndex));
+                        if (mStreamType == mStreamVolumeAlias[mStreamType]) {
+                            String aliasStreamIndexesString = "";
+                            if (!aliasStreamIndexes.isEmpty()) {
+                                aliasStreamIndexesString =
+                                        " aliased streams: " + aliasStreamIndexes;
+                            }
+                            AudioService.sVolumeLogger.enqueue(new VolChangedBroadcastEvent(
+                                    mStreamType, aliasStreamIndexesString, index, oldIndex));
+                        }
                         sendBroadcastToAll(mVolumeChanged, mVolumeChangedOptions);
                     }
                 }
@@ -11271,7 +11312,8 @@
         mDeviceBroker.addOrUpdateBtAudioDeviceCategoryInInventory(deviceState);
         mDeviceBroker.postPersistAudioDeviceSettings();
 
-        mSpatializerHelper.refreshDevice(deviceState.getAudioDeviceAttributes());
+        mSpatializerHelper.refreshDevice(deviceState.getAudioDeviceAttributes(),
+                false /* initState */);
         mSoundDoseHelper.setAudioDeviceCategory(addr, internalType,
                 btAudioDeviceCategory == AUDIO_DEVICE_CATEGORY_HEADPHONES);
     }
@@ -11342,11 +11384,11 @@
 
     /** Update the sound dose and spatializer state based on the new AdiDeviceState. */
     @VisibleForTesting(visibility = PACKAGE)
-    public void onUpdatedAdiDeviceState(AdiDeviceState deviceState) {
+    public void onUpdatedAdiDeviceState(AdiDeviceState deviceState, boolean initSA) {
         if (deviceState == null) {
             return;
         }
-        mSpatializerHelper.refreshDevice(deviceState.getAudioDeviceAttributes());
+        mSpatializerHelper.refreshDevice(deviceState.getAudioDeviceAttributes(), initSA);
         mSoundDoseHelper.setAudioDeviceCategory(deviceState.getDeviceAddress(),
                 deviceState.getInternalDeviceType(),
                 deviceState.getAudioDeviceCategory() == AUDIO_DEVICE_CATEGORY_HEADPHONES);
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index 3b1c011..749044e 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -151,13 +151,13 @@
 
     static final class VolChangedBroadcastEvent extends EventLogger.Event {
         final int mStreamType;
-        final int mAliasStreamType;
+        final String mAliasStreamIndexes;
         final int mIndex;
         final int mOldIndex;
 
-        VolChangedBroadcastEvent(int stream, int alias, int index, int oldIndex) {
+        VolChangedBroadcastEvent(int stream, String aliasIndexes, int index, int oldIndex) {
             mStreamType = stream;
-            mAliasStreamType = alias;
+            mAliasStreamIndexes = aliasIndexes;
             mIndex = index;
             mOldIndex = oldIndex;
         }
@@ -167,8 +167,8 @@
             return new StringBuilder("sending VOLUME_CHANGED stream:")
                     .append(AudioSystem.streamToString(mStreamType))
                     .append(" index:").append(mIndex)
-                    .append(" (was:").append(mOldIndex)
-                    .append(") alias:").append(AudioSystem.streamToString(mAliasStreamType))
+                    .append(" (was:").append(mOldIndex).append(")")
+                    .append(mAliasStreamIndexes)
                     .toString();
         }
     }
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index f3a5fdb..a649d34 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -98,9 +98,16 @@
 
     private @Nullable BluetoothLeAudio mLeAudio;
 
+    private @Nullable BluetoothLeAudioCodecConfig mLeAudioCodecConfig;
+
     // Reference to BluetoothA2dp to query for AbsoluteVolume.
     private @Nullable BluetoothA2dp mA2dp;
 
+    private @Nullable BluetoothCodecConfig mA2dpCodecConfig;
+
+    private @AudioSystem.AudioFormatNativeEnumForBtCodec
+            int mLeAudioBroadcastCodec = AudioSystem.AUDIO_FORMAT_DEFAULT;
+
     // If absolute volume is supported in AVRCP device
     private boolean mAvrcpAbsVolSupported = false;
 
@@ -265,12 +272,15 @@
         }
     }
 
-    /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getCodec(
+    private synchronized Pair<Integer, Boolean> getCodec(
             @NonNull BluetoothDevice device, @AudioService.BtProfile int profile) {
+
         switch (profile) {
             case BluetoothProfile.A2DP: {
+                boolean changed = mA2dpCodecConfig != null;
                 if (mA2dp == null) {
-                    return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                    mA2dpCodecConfig = null;
+                    return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
                 }
                 BluetoothCodecStatus btCodecStatus = null;
                 try {
@@ -279,17 +289,24 @@
                     Log.e(TAG, "Exception while getting status of " + device, e);
                 }
                 if (btCodecStatus == null) {
-                    return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                    mA2dpCodecConfig = null;
+                    return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
                 }
                 final BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig();
                 if (btCodecConfig == null) {
-                    return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                    mA2dpCodecConfig = null;
+                    return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
                 }
-                return AudioSystem.bluetoothA2dpCodecToAudioFormat(btCodecConfig.getCodecType());
+                changed = !btCodecConfig.equals(mA2dpCodecConfig);
+                mA2dpCodecConfig = btCodecConfig;
+                return new Pair<>(AudioSystem.bluetoothA2dpCodecToAudioFormat(
+                        btCodecConfig.getCodecType()), changed);
             }
             case BluetoothProfile.LE_AUDIO: {
+                boolean changed = mLeAudioCodecConfig != null;
                 if (mLeAudio == null) {
-                    return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                    mLeAudioCodecConfig = null;
+                    return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
                 }
                 BluetoothLeAudioCodecStatus btLeCodecStatus = null;
                 int groupId = mLeAudio.getGroupId(device);
@@ -299,42 +316,54 @@
                     Log.e(TAG, "Exception while getting status of " + device, e);
                 }
                 if (btLeCodecStatus == null) {
-                    return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                    mLeAudioCodecConfig = null;
+                    return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
                 }
                 BluetoothLeAudioCodecConfig btLeCodecConfig =
                         btLeCodecStatus.getOutputCodecConfig();
                 if (btLeCodecConfig == null) {
-                    return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                    mLeAudioCodecConfig = null;
+                    return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
                 }
-                return AudioSystem.bluetoothLeCodecToAudioFormat(btLeCodecConfig.getCodecType());
+                changed = !btLeCodecConfig.equals(mLeAudioCodecConfig);
+                mLeAudioCodecConfig = btLeCodecConfig;
+                return new Pair<>(AudioSystem.bluetoothLeCodecToAudioFormat(
+                        btLeCodecConfig.getCodecType()), changed);
+            }
+            case BluetoothProfile.LE_AUDIO_BROADCAST: {
+                // We assume LC3 for LE Audio broadcast codec as there is no API to get the codec
+                // config on LE Broadcast profile proxy.
+                boolean changed = mLeAudioBroadcastCodec != AudioSystem.AUDIO_FORMAT_LC3;
+                mLeAudioBroadcastCodec = AudioSystem.AUDIO_FORMAT_LC3;
+                return new Pair<>(mLeAudioBroadcastCodec, changed);
             }
             default:
-                return AudioSystem.AUDIO_FORMAT_DEFAULT;
+                return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, false);
         }
     }
 
-    /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec
-            int getCodecWithFallback(
-                    @NonNull BluetoothDevice device, @AudioService.BtProfile int profile,
-                    boolean isLeOutput, @NonNull String source) {
+    /*package*/ synchronized Pair<Integer, Boolean>
+                    getCodecWithFallback(@NonNull BluetoothDevice device,
+                                         @AudioService.BtProfile int profile,
+                                         boolean isLeOutput, @NonNull String source) {
         // For profiles other than A2DP and LE Audio output, the audio codec format must be
         // AUDIO_FORMAT_DEFAULT as native audio policy manager expects a specific audio format
         // only if audio HW module selection based on format is supported for the device type.
         if (!(profile == BluetoothProfile.A2DP
                 || (isLeOutput && ((profile == BluetoothProfile.LE_AUDIO)
                         || (profile == BluetoothProfile.LE_AUDIO_BROADCAST))))) {
-            return AudioSystem.AUDIO_FORMAT_DEFAULT;
+            return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, false);
         }
-        @AudioSystem.AudioFormatNativeEnumForBtCodec int codec =
+        Pair<Integer, Boolean> codecAndChanged =
                 getCodec(device, profile);
-        if (codec == AudioSystem.AUDIO_FORMAT_DEFAULT) {
+        if (codecAndChanged.first == AudioSystem.AUDIO_FORMAT_DEFAULT) {
             AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                     "getCodec DEFAULT from " + source + " fallback to "
                             + (profile == BluetoothProfile.A2DP ? "SBC" : "LC3")));
-            return profile == BluetoothProfile.A2DP
-                    ? AudioSystem.AUDIO_FORMAT_SBC : AudioSystem.AUDIO_FORMAT_LC3;
+            return new Pair<>(profile == BluetoothProfile.A2DP
+                    ? AudioSystem.AUDIO_FORMAT_SBC : AudioSystem.AUDIO_FORMAT_LC3, true);
         }
-        return codec;
+        return codecAndChanged;
     }
 
     // @GuardedBy("mDeviceBroker.mSetModeLock")
@@ -539,15 +568,19 @@
                 break;
             case BluetoothProfile.A2DP:
                 mA2dp = null;
+                mA2dpCodecConfig = null;
                 break;
             case BluetoothProfile.HEARING_AID:
                 mHearingAid = null;
                 break;
             case BluetoothProfile.LE_AUDIO:
                 mLeAudio = null;
+                mLeAudioCodecConfig = null;
+                break;
+            case BluetoothProfile.LE_AUDIO_BROADCAST:
+                mLeAudioBroadcastCodec = AudioSystem.AUDIO_FORMAT_DEFAULT;
                 break;
             case BluetoothProfile.A2DP_SINK:
-            case BluetoothProfile.LE_AUDIO_BROADCAST:
                 // nothing to do in BtHelper
                 break;
             default:
@@ -1077,6 +1110,12 @@
         return mLeAudio.getGroupId(device);
     }
 
+    /**
+     * Returns all addresses and identity addresses for LE Audio devices a group.
+     * @param groupId The ID of the group from which to get addresses.
+     * @return A List of Pair(String main_address, String identity_address). Note that the
+     * addresses returned by BluetoothDevice can be null.
+     */
     /*package*/ List<Pair<String, String>> getLeAudioGroupAddresses(int groupId) {
         List<Pair<String, String>> addresses = new ArrayList<>();
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/services/core/java/com/android/server/audio/MusicFxHelper.java b/services/core/java/com/android/server/audio/MusicFxHelper.java
index 85b3b49..ba45310 100644
--- a/services/core/java/com/android/server/audio/MusicFxHelper.java
+++ b/services/core/java/com/android/server/audio/MusicFxHelper.java
@@ -90,7 +90,6 @@
      *    observer will also be removed, and observer token reset to null
      */
     private class MySparseArray extends SparseArray<PackageSessions> {
-        private final String mMusicFxPackageName = "com.android.musicfx";
 
         @RequiresPermission(anyOf = {
                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
@@ -229,6 +228,10 @@
         if (ril != null && ril.size() != 0) {
             ResolveInfo ri = ril.get(0);
             final String senderPackageName = intent.getStringExtra(AudioEffect.EXTRA_PACKAGE_NAME);
+            if (senderPackageName == null) {
+                Log.w(TAG, "Intent package name must not be null");
+                return;
+            }
             try {
                 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
                     final int senderUid = pm.getPackageUidAsUser(senderPackageName,
@@ -265,7 +268,7 @@
                         + senderUid + ", package: " + senderPackageName + ", abort");
                 return false;
             }
-            if (pkgSessions.mPackageName != senderPackageName) {
+            if (!pkgSessions.mPackageName.equals(senderPackageName)) {
                 Log.w(TAG, "Inconsistency package names for UID open: " + senderUid + " prev: "
                         + pkgSessions.mPackageName + ", now: " + senderPackageName);
                 return false;
@@ -297,7 +300,7 @@
             Log.e(TAG, senderPackageName + " UID " + senderUid + " does not exist in map, abort");
             return false;
         }
-        if (pkgSessions.mPackageName != senderPackageName) {
+        if (!pkgSessions.mPackageName.equals(senderPackageName)) {
             Log.w(TAG, "Inconsistency package names for UID " + senderUid + " close, prev: "
                     + pkgSessions.mPackageName + ", now: " + senderPackageName);
             return false;
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 08da32e..28af222 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -235,6 +235,10 @@
     public int trackPlayer(PlayerBase.PlayerIdCard pic) {
         final int newPiid = AudioSystem.newAudioPlayerId();
         if (DEBUG) { Log.v(TAG, "trackPlayer() new piid=" + newPiid); }
+        if (newPiid == PLAYER_PIID_INVALID) {
+            Log.w(TAG, "invalid piid assigned from AudioSystem");
+            return newPiid;
+        }
         final AudioPlaybackConfiguration apc =
                 new AudioPlaybackConfiguration(pic, newPiid,
                         Binder.getCallingUid(), Binder.getCallingPid());
@@ -365,15 +369,14 @@
             sEventLogger.enqueue(new PlayerEvent(piid, event, eventValue));
 
             if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_PORT_ID) {
-                mEventHandler.sendMessage(
-                        mEventHandler.obtainMessage(MSG_II_UPDATE_PORT_EVENT, eventValue, piid));
+                mPortIdToPiid.put(eventValue, piid);
                 return;
             } else if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                 for (Integer uidInteger: mBannedUids) {
                     if (checkBanPlayer(apc, uidInteger.intValue())) {
                         // player was banned, do not update its state
                         sEventLogger.enqueue(new EventLogger.StringEvent(
-                                "not starting piid:" + piid + " ,is banned"));
+                                "not starting piid:" + piid + ", is banned"));
                         return;
                     }
                 }
@@ -429,16 +432,12 @@
         synchronized (mPlayerLock) {
             int piid = mPortIdToPiid.get(portId, PLAYER_PIID_INVALID);
             if (piid == PLAYER_PIID_INVALID) {
-                if (DEBUG) {
-                    Log.v(TAG, "No piid assigned for invalid/internal port id " + portId);
-                }
+                Log.w(TAG, "No piid assigned for invalid/internal port id " + portId);
                 return;
             }
             final AudioPlaybackConfiguration apc = mPlayers.get(piid);
             if (apc == null) {
-                if (DEBUG) {
-                    Log.v(TAG, "No AudioPlaybackConfiguration assigned for piid " + piid);
-                }
+                Log.w(TAG, "No AudioPlaybackConfiguration assigned for piid " + piid);
                 return;
             }
 
@@ -470,11 +469,18 @@
     public void releasePlayer(int piid, int binderUid) {
         if (DEBUG) { Log.v(TAG, "releasePlayer() for piid=" + piid); }
         boolean change = false;
+        if (piid == PLAYER_PIID_INVALID) {
+            Log.w(TAG, "Received releasePlayer with invalid piid: " + piid);
+            sEventLogger.enqueue(new EventLogger.StringEvent("releasePlayer with invalid piid:"
+                    + piid + ", uid:" + binderUid));
+            return;
+        }
+
         synchronized(mPlayerLock) {
             final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
             if (checkConfigurationCaller(piid, apc, binderUid)) {
                 sEventLogger.enqueue(new EventLogger.StringEvent(
-                        "releasing player piid:" + piid));
+                        "releasing player piid:" + piid + ", uid:" + binderUid));
                 mPlayers.remove(new Integer(piid));
                 mDuckingManager.removeReleased(apc);
                 mFadeOutManager.removeReleased(apc);
@@ -484,8 +490,10 @@
                         AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID);
 
                 // remove all port ids mapped to the released player
-                mEventHandler.sendMessage(
-                        mEventHandler.obtainMessage(MSG_I_CLEAR_PORTS_FOR_PIID, piid, /*arg2=*/0));
+                int portIdx;
+                while ((portIdx = mPortIdToPiid.indexOfValue(piid)) >= 0) {
+                    mPortIdToPiid.removeAt(portIdx);
+                }
 
                 if (change && mDoNotLogPiidList.contains(piid)) {
                     // do not dispatch a change for a "do not log" player
@@ -1609,14 +1617,6 @@
     private static final int MSG_L_TIMEOUT_MUTE_AWAIT_CONNECTION = 1;
 
     /**
-     * assign new port id to piid
-     * args:
-     *     msg.arg1: port id
-     *     msg.arg2: piid
-     */
-    private static final int MSG_II_UPDATE_PORT_EVENT = 2;
-
-    /**
      * event for player getting muted
      * args:
      *     msg.arg1: piid
@@ -1624,14 +1624,7 @@
      *     msg.obj: extras describing the mute reason
      *         type: PersistableBundle
      */
-    private static final int MSG_IIL_UPDATE_PLAYER_MUTED_EVENT = 3;
-
-    /**
-     * clear all ports assigned to a given piid
-     * args:
-     *     msg.arg1: the piid
-     */
-    private static final int MSG_I_CLEAR_PORTS_FOR_PIID = 4;
+    private static final int MSG_IIL_UPDATE_PLAYER_MUTED_EVENT = 2;
 
     /**
      * event for player reporting playback format and spatialization status
@@ -1641,7 +1634,7 @@
      *     msg.obj: extras describing the sample rate, channel mask, spatialized
      *         type: PersistableBundle
      */
-    private static final int MSG_IIL_UPDATE_PLAYER_FORMAT = 5;
+    private static final int MSG_IIL_UPDATE_PLAYER_FORMAT = 3;
 
     private void initEventHandler() {
         mEventThread = new HandlerThread(TAG);
@@ -1660,11 +1653,6 @@
                         mMuteAwaitConnectionTimeoutCb.accept((AudioDeviceAttributes) msg.obj);
                         break;
 
-                    case MSG_II_UPDATE_PORT_EVENT:
-                        synchronized (mPlayerLock) {
-                            mPortIdToPiid.put(/*portId*/msg.arg1, /*piid*/msg.arg2);
-                        }
-                        break;
                     case MSG_IIL_UPDATE_PLAYER_MUTED_EVENT:
                         // TODO: replace PersistableBundle with own struct
                         PersistableBundle extras = (PersistableBundle) msg.obj;
@@ -1680,10 +1668,7 @@
                             sEventLogger.enqueue(
                                     new PlayerEvent(piid, PLAYER_UPDATE_MUTED, eventValue));
 
-                            final AudioPlaybackConfiguration apc;
-                            synchronized (mPlayerLock) {
-                                apc = mPlayers.get(piid);
-                            }
+                            final AudioPlaybackConfiguration apc = mPlayers.get(piid);
                             if (apc == null || !apc.handleMutedEvent(eventValue)) {
                                 break;  // do not dispatch
                             }
@@ -1691,21 +1676,6 @@
                         }
                         break;
 
-                    case MSG_I_CLEAR_PORTS_FOR_PIID:
-                        int piid = msg.arg1;
-                        if (piid == AudioPlaybackConfiguration.PLAYER_PIID_INVALID) {
-                            Log.w(TAG, "Received clear ports with invalid piid");
-                            break;
-                        }
-
-                        synchronized (mPlayerLock) {
-                            int portIdx;
-                            while ((portIdx = mPortIdToPiid.indexOfValue(piid)) >= 0) {
-                                mPortIdToPiid.removeAt(portIdx);
-                            }
-                        }
-                        break;
-
                     case MSG_IIL_UPDATE_PLAYER_FORMAT:
                         final PersistableBundle formatExtras = (PersistableBundle) msg.obj;
                         if (formatExtras == null) {
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 3b5fa7f..38fa79f 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -295,11 +295,11 @@
             // could have been called another time after boot in case of audioserver restart
             addCompatibleAudioDevice(
                     new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""),
-                            false /*forceEnable*/);
+                            false /*forceEnable*/, false /*forceInit*/);
             // not force-enabling as this device might already be in the device list
             addCompatibleAudioDevice(
                     new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, ""),
-                            false /*forceEnable*/);
+                            false /*forceEnable*/, false /*forceInit*/);
         } catch (RemoteException e) {
             resetCapabilities();
         } finally {
@@ -526,7 +526,7 @@
     }
 
     synchronized void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) {
-        addCompatibleAudioDevice(ada, true /*forceEnable*/);
+        addCompatibleAudioDevice(ada, true /*forceEnable*/, false /*forceInit*/);
     }
 
     /**
@@ -540,7 +540,7 @@
      */
     @GuardedBy("this")
     private void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada,
-            boolean forceEnable) {
+            boolean forceEnable, boolean forceInit) {
         if (!isDeviceCompatibleWithSpatializationModes(ada)) {
             return;
         }
@@ -548,6 +548,9 @@
         final AdiDeviceState deviceState = findSACompatibleDeviceStateForAudioDeviceAttributes(ada);
         AdiDeviceState updatedDevice = null; // non-null on update.
         if (deviceState != null) {
+            if (forceInit) {
+                initSAState(deviceState);
+            }
             if (forceEnable && !deviceState.isSAEnabled()) {
                 updatedDevice = deviceState;
                 updatedDevice.setSAEnabled(true);
@@ -756,10 +759,10 @@
         }
     }
 
-    synchronized void refreshDevice(@NonNull AudioDeviceAttributes ada) {
+    synchronized void refreshDevice(@NonNull AudioDeviceAttributes ada, boolean initState) {
         final AdiDeviceState deviceState = findSACompatibleDeviceStateForAudioDeviceAttributes(ada);
         if (isAvailableForAdiDeviceState(deviceState)) {
-            addCompatibleAudioDevice(ada, /*forceEnable=*/deviceState.isSAEnabled());
+            addCompatibleAudioDevice(ada, /*forceEnable=*/deviceState.isSAEnabled(), initState);
             setHeadTrackerEnabled(deviceState.isHeadTrackerEnabled(), ada);
         } else {
             removeCompatibleAudioDevice(ada);
diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
index 5b9469b..1ea72d7 100644
--- a/services/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -34,10 +34,11 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
-import com.google.android.collect.Sets;
 
 import com.android.server.backup.Flags;
 
+import com.google.android.collect.Sets;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.Set;
@@ -64,6 +65,7 @@
     private static final String APP_LOCALES_HELPER = "app_locales";
     private static final String APP_GENDER_HELPER = "app_gender";
     private static final String COMPANION_HELPER = "companion";
+    private static final String SYSTEM_GENDER_HELPER = "system_gender";
 
     // These paths must match what the WallpaperManagerService uses.  The leaf *_FILENAME
     // are also used in the full-backup file format, so must not change unless steps are
@@ -99,7 +101,9 @@
                     NOTIFICATION_HELPER,
                     SYNC_SETTINGS_HELPER,
                     APP_LOCALES_HELPER,
-                    COMPANION_HELPER);
+                    COMPANION_HELPER,
+                    APP_GENDER_HELPER,
+                    SYSTEM_GENDER_HELPER);
 
     /** Helpers that are enabled for full, non-system users. */
     private static final Set<String> sEligibleHelpersForNonSystemUser =
@@ -139,6 +143,8 @@
         addHelperIfEligibleForUser(APP_GENDER_HELPER,
                 new AppGrammaticalGenderBackupHelper(mUserId));
         addHelperIfEligibleForUser(COMPANION_HELPER, new CompanionBackupHelper(mUserId));
+        addHelperIfEligibleForUser(SYSTEM_GENDER_HELPER,
+                new SystemGrammaticalGenderBackupHelper(mUserId));
     }
 
     @Override
diff --git a/services/core/java/com/android/server/backup/SystemGrammaticalGenderBackupHelper.java b/services/core/java/com/android/server/backup/SystemGrammaticalGenderBackupHelper.java
new file mode 100644
index 0000000..c0d398e
--- /dev/null
+++ b/services/core/java/com/android/server/backup/SystemGrammaticalGenderBackupHelper.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup;
+
+import static android.app.backup.BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
+
+import android.annotation.UserIdInt;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BlobBackupHelper;
+import android.os.ParcelFileDescriptor;
+
+import com.android.server.LocalServices;
+import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
+
+public class SystemGrammaticalGenderBackupHelper extends BlobBackupHelper {
+    private static final int BLOB_VERSION = 1;
+    private static final String KEY_SYSTEM_GENDER = "system_gender";
+
+    private final @UserIdInt int mUserId;
+    private final GrammaticalInflectionManagerInternal mGrammarInflectionManagerInternal;
+
+    public SystemGrammaticalGenderBackupHelper(int userId) {
+        super(BLOB_VERSION, KEY_SYSTEM_GENDER);
+        mUserId = userId;
+        mGrammarInflectionManagerInternal = LocalServices.getService(
+                GrammaticalInflectionManagerInternal.class);
+    }
+
+    @Override
+    public void performBackup(ParcelFileDescriptor oldStateFd, BackupDataOutput data,
+            ParcelFileDescriptor newStateFd) {
+        // Only backup the gender data if e2e encryption is present
+        if ((data.getTransportFlags() & FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) == 0) {
+            return;
+        }
+
+        super.performBackup(oldStateFd, data, newStateFd);
+    }
+
+    @Override
+    protected byte[] getBackupPayload(String key) {
+        return KEY_SYSTEM_GENDER.equals(key) && mGrammarInflectionManagerInternal != null
+                ? mGrammarInflectionManagerInternal.getSystemBackupPayload(mUserId) : null;
+    }
+
+    @Override
+    protected void applyRestoredPayload(String key, byte[] payload) {
+        if (KEY_SYSTEM_GENDER.equals(key) && mGrammarInflectionManagerInternal != null) {
+            mGrammarInflectionManagerInternal.applyRestoredSystemPayload(payload, mUserId);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/Android.bp b/services/core/java/com/android/server/biometrics/Android.bp
index 6cbe4ad..ed5de03 100644
--- a/services/core/java/com/android/server/biometrics/Android.bp
+++ b/services/core/java/com/android/server/biometrics/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "biometrics_flags",
     package: "com.android.server.biometrics",
+    container: "system",
     srcs: [
         "biometrics.aconfig",
     ],
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 7df63b1..11cca66 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -25,15 +25,12 @@
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.Manifest.permission.USE_FINGERPRINT;
-import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
-import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
 import static android.hardware.biometrics.BiometricManager.Authenticators;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -778,13 +775,7 @@
             hidlConfigs = null;
         }
 
-        if (com.android.server.biometrics.Flags.deHidl()) {
-            registerAuthenticators();
-        } else {
-            // Registers HIDL and AIDL authenticators, but only HIDL configs need to be provided.
-            registerAuthenticators(hidlConfigs);
-        }
-
+        registerAuthenticators();
         mInjector.publishBinderService(this, mImpl);
     }
 
@@ -874,7 +865,7 @@
 
             if (faceService != null) {
                 try {
-                    faceService.registerAuthenticatorsLegacy(mFaceSensorConfigurations);
+                    faceService.registerAuthenticators(mFaceSensorConfigurations);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "RemoteException when registering face authenticators", e);
                 }
@@ -912,8 +903,7 @@
 
             if (fingerprintService != null) {
                 try {
-                    fingerprintService.registerAuthenticatorsLegacy(
-                            mFingerprintSensorConfigurations);
+                    fingerprintService.registerAuthenticators(mFingerprintSensorConfigurations);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "RemoteException when registering fingerprint authenticators", e);
                 }
@@ -948,78 +938,6 @@
         return configStrings;
     }
 
-    /**
-     * Registers HIDL and AIDL authenticators for all of the available modalities.
-     *
-     * @param hidlSensors Array of {@link SensorConfig} configuration for all of the HIDL sensors
-     *                    available on the device. This array may contain configuration for
-     *                    different modalities and different sensors of the same modality in
-     *                    arbitrary order. Can be null if no HIDL sensors exist on the device.
-     */
-    private void registerAuthenticators(@Nullable SensorConfig[] hidlSensors) {
-        List<FingerprintSensorPropertiesInternal> hidlFingerprintSensors = new ArrayList<>();
-        List<FaceSensorPropertiesInternal> hidlFaceSensors = new ArrayList<>();
-        // Iris doesn't have IrisSensorPropertiesInternal, using SensorPropertiesInternal instead.
-        List<SensorPropertiesInternal> hidlIrisSensors = new ArrayList<>();
-
-        if (hidlSensors != null) {
-            for (SensorConfig sensor : hidlSensors) {
-                Slog.d(TAG, "Registering HIDL ID: " + sensor.id + " Modality: " + sensor.modality
-                        + " Strength: " + sensor.strength);
-                switch (sensor.modality) {
-                    case TYPE_FINGERPRINT:
-                        hidlFingerprintSensors.add(
-                                getHidlFingerprintSensorProps(sensor.id, sensor.strength));
-                        break;
-
-                    case TYPE_FACE:
-                        hidlFaceSensors.add(getHidlFaceSensorProps(sensor.id, sensor.strength));
-                        break;
-
-                    case TYPE_IRIS:
-                        hidlIrisSensors.add(getHidlIrisSensorProps(sensor.id, sensor.strength));
-                        break;
-
-                    default:
-                        Slog.e(TAG, "Unknown modality: " + sensor.modality);
-                }
-            }
-        }
-
-        final IFingerprintService fingerprintService = mInjector.getFingerprintService();
-        if (fingerprintService != null) {
-            try {
-                fingerprintService.registerAuthenticators(hidlFingerprintSensors);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException when registering fingerprint authenticators", e);
-            }
-        } else if (hidlFingerprintSensors.size() > 0) {
-            Slog.e(TAG, "HIDL fingerprint configuration exists, but FingerprintService is null.");
-        }
-
-        final IFaceService faceService = mInjector.getFaceService();
-        if (faceService != null) {
-            try {
-                faceService.registerAuthenticators(hidlFaceSensors);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException when registering face authenticators", e);
-            }
-        } else if (hidlFaceSensors.size() > 0) {
-            Slog.e(TAG, "HIDL face configuration exists, but FaceService is null.");
-        }
-
-        final IIrisService irisService = mInjector.getIrisService();
-        if (irisService != null) {
-            try {
-                irisService.registerAuthenticators(hidlIrisSensors);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException when registering iris authenticators", e);
-            }
-        } else if (hidlIrisSensors.size() > 0) {
-            Slog.e(TAG, "HIDL iris configuration exists, but IrisService is null.");
-        }
-    }
-
     private void checkInternalPermission() {
         getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL,
                 "Must have USE_BIOMETRIC_INTERNAL permission");
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 3d4801b..0be893c 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -56,7 +56,7 @@
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.security.KeyStore;
+import android.security.KeyStoreAuthorization;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -111,7 +111,7 @@
     @NonNull private final BiometricContext mBiometricContext;
     private final IStatusBarService mStatusBarService;
     @VisibleForTesting final IBiometricSysuiReceiver mSysuiReceiver;
-    private final KeyStore mKeyStore;
+    private final KeyStoreAuthorization mKeyStoreAuthorization;
     private final Random mRandom;
     private final ClientDeathReceiver mClientDeathReceiver;
     final PreAuthInfo mPreAuthInfo;
@@ -158,7 +158,7 @@
             @NonNull BiometricContext biometricContext,
             @NonNull IStatusBarService statusBarService,
             @NonNull IBiometricSysuiReceiver sysuiReceiver,
-            @NonNull KeyStore keystore,
+            @NonNull KeyStoreAuthorization keyStoreAuthorization,
             @NonNull Random random,
             @NonNull ClientDeathReceiver clientDeathReceiver,
             @NonNull PreAuthInfo preAuthInfo,
@@ -172,8 +172,8 @@
             @NonNull PromptInfo promptInfo,
             boolean debugEnabled,
             @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties) {
-        this(context, biometricContext, statusBarService, sysuiReceiver, keystore, random,
-                clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId,
+        this(context, biometricContext, statusBarService, sysuiReceiver, keyStoreAuthorization,
+                random, clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId,
                 sensorReceiver, clientReceiver, opPackageName, promptInfo, debugEnabled,
                 fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance());
     }
@@ -183,7 +183,7 @@
             @NonNull BiometricContext biometricContext,
             @NonNull IStatusBarService statusBarService,
             @NonNull IBiometricSysuiReceiver sysuiReceiver,
-            @NonNull KeyStore keystore,
+            @NonNull KeyStoreAuthorization keyStoreAuthorization,
             @NonNull Random random,
             @NonNull ClientDeathReceiver clientDeathReceiver,
             @NonNull PreAuthInfo preAuthInfo,
@@ -203,7 +203,7 @@
         mBiometricContext = biometricContext;
         mStatusBarService = statusBarService;
         mSysuiReceiver = sysuiReceiver;
-        mKeyStore = keystore;
+        mKeyStoreAuthorization = keyStoreAuthorization;
         mRandom = random;
         mClientDeathReceiver = clientDeathReceiver;
         mPreAuthInfo = preAuthInfo;
@@ -576,7 +576,8 @@
     }
 
     void onDialogAnimatedIn(boolean startFingerprintNow) {
-        if (mState != STATE_AUTH_STARTED && mState != STATE_ERROR_PENDING_SYSUI) {
+        if (mState != STATE_AUTH_STARTED && mState != STATE_ERROR_PENDING_SYSUI
+                && mState != STATE_AUTH_PAUSED) {
             Slog.e(TAG, "onDialogAnimatedIn, unexpected state: " + mState);
             return;
         }
@@ -814,14 +815,14 @@
             switch (reason) {
                 case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
                     if (credentialAttestation != null) {
-                        mKeyStore.addAuthToken(credentialAttestation);
+                        mKeyStoreAuthorization.addAuthToken(credentialAttestation);
                     } else {
                         Slog.e(TAG, "credentialAttestation is null");
                     }
                 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
                 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
                     if (mTokenEscrow != null) {
-                        final int result = mKeyStore.addAuthToken(mTokenEscrow);
+                        final int result = mKeyStoreAuthorization.addAuthToken(mTokenEscrow);
                         Slog.d(TAG, "addAuthToken: " + result);
                     } else {
                         Slog.e(TAG, "mTokenEscrow is null");
diff --git a/services/core/java/com/android/server/biometrics/BiometricHandlerProvider.java b/services/core/java/com/android/server/biometrics/BiometricHandlerProvider.java
index e578861..91cabb5 100644
--- a/services/core/java/com/android/server/biometrics/BiometricHandlerProvider.java
+++ b/services/core/java/com/android/server/biometrics/BiometricHandlerProvider.java
@@ -21,7 +21,6 @@
 
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.os.Looper;
 
 /**
  * This class provides the handler to process biometric operations.
@@ -76,11 +75,8 @@
     }
 
     private Handler getNewHandler(String tag, int priority) {
-        if (Flags.deHidl()) {
-            HandlerThread handlerThread = new HandlerThread(tag, priority);
-            handlerThread.start();
-            return new Handler(handlerThread.getLooper());
-        }
-        return new Handler(Looper.getMainLooper());
+        HandlerThread handlerThread = new HandlerThread(tag, priority);
+        handlerThread.start();
+        return new Handler(handlerThread.getLooper());
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 894b4d5..0e81eb9 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -65,15 +65,11 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.security.Authorization;
 import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.authorization.IKeystoreAuthorization;
-import android.security.authorization.ResponseCode;
+import android.security.KeyStoreAuthorization;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -123,11 +119,9 @@
     @VisibleForTesting
     IStatusBarService mStatusBarService;
     @VisibleForTesting
-    KeyStore mKeyStore;
-    @VisibleForTesting
     ITrustManager mTrustManager;
     @VisibleForTesting
-    IKeystoreAuthorization mKeystoreAuthorization;
+    KeyStoreAuthorization mKeyStoreAuthorization;
     @VisibleForTesting
     IGateKeeperService mGateKeeper;
 
@@ -674,19 +668,7 @@
             int[] authTypesArray = hardwareAuthenticators.stream()
                     .mapToInt(Integer::intValue)
                     .toArray();
-            try {
-                return mKeystoreAuthorization.getLastAuthTime(secureUserId, authTypesArray);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Error getting last auth time: " + e);
-                return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
-            } catch (ServiceSpecificException e) {
-                // This is returned when the feature flag test fails in keystore2
-                if (e.errorCode == ResponseCode.PERMISSION_DENIED) {
-                    throw new UnsupportedOperationException();
-                }
-
-                return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
-            }
+            return mKeyStoreAuthorization.getLastAuthTime(secureUserId, authTypesArray);
         }
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@@ -868,8 +850,10 @@
 
             Slog.d(TAG, "resetLockout(userId=" + userId
                     + ", hat=" + (hardwareAuthToken == null ? "null " : "present") + ")");
-            mBiometricContext.getAuthSessionCoordinator()
+            mHandler.post(() -> {
+                mBiometricContext.getAuthSessionCoordinator()
                     .resetLockoutFor(userId, Authenticators.BIOMETRIC_STRONG, -1);
+            });
         }
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@@ -1011,8 +995,8 @@
             return ActivityManager.getService();
         }
 
-        public IKeystoreAuthorization getKeystoreAuthorizationService() {
-            return Authorization.getService();
+        public KeyStoreAuthorization getKeyStoreAuthorization() {
+            return KeyStoreAuthorization.getInstance();
         }
 
         public IGateKeeperService getGateKeeperService() {
@@ -1036,10 +1020,6 @@
             return new SettingObserver(context, handler, callbacks);
         }
 
-        public KeyStore getKeyStore() {
-            return KeyStore.getInstance();
-        }
-
         /**
          * Allows to enable/disable debug logs.
          */
@@ -1138,7 +1118,7 @@
         mBiometricContext = injector.getBiometricContext(context);
         mUserManager = injector.getUserManager(context);
         mBiometricCameraManager = injector.getBiometricCameraManager(context);
-        mKeystoreAuthorization = injector.getKeystoreAuthorizationService();
+        mKeyStoreAuthorization = injector.getKeyStoreAuthorization();
         mGateKeeper = injector.getGateKeeperService();
         mBiometricNotificationLogger = injector.getNotificationLogger();
 
@@ -1159,7 +1139,6 @@
 
     @Override
     public void onStart() {
-        mKeyStore = mInjector.getKeyStore();
         mStatusBarService = mInjector.getStatusBarService();
         mTrustManager = mInjector.getTrustManager();
         mInjector.publishBinderService(this, mImpl);
@@ -1481,7 +1460,7 @@
 
         final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId);
         mAuthSession = new AuthSession(getContext(), mBiometricContext, mStatusBarService,
-                createSysuiReceiver(requestId), mKeyStore, mRandom,
+                createSysuiReceiver(requestId), mKeyStoreAuthorization, mRandom,
                 createClientDeathReceiver(requestId), preAuthInfo, token, requestId,
                 operationId, userId, createBiometricSensorReceiver(requestId), receiver,
                 opPackageName, promptInfo, debugEnabled,
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index f51b62d..4af30a9 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -89,11 +89,23 @@
         return true;
     }
 
-    /** If virtualized biometrics are supported (requires debug build). */
-    public static boolean isVirtualEnabled(@NonNull Context context) {
+    /** If virtualized fingerprint sensor is supported. */
+    public static boolean isFingerprintVirtualEnabled(@NonNull Context context) {
         return Build.isDebuggable()
-                && Settings.Secure.getIntForUser(context.getContentResolver(),
-                Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
+                && (Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.BIOMETRIC_FINGERPRINT_VIRTUAL_ENABLED, 0,
+                UserHandle.USER_CURRENT) == 1
+                || Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1);
+    }
+
+    /** If virtualized face sensor is supported. */
+    public static boolean isFaceVirtualEnabled(@NonNull Context context) {
+        return Build.isDebuggable()
+                && (Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.BIOMETRIC_FACE_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1
+                || Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1);
     }
 
     /**
diff --git a/services/core/java/com/android/server/biometrics/biometrics.aconfig b/services/core/java/com/android/server/biometrics/biometrics.aconfig
index b12d831..92fd9cb 100644
--- a/services/core/java/com/android/server/biometrics/biometrics.aconfig
+++ b/services/core/java/com/android/server/biometrics/biometrics.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.biometrics"
+container: "system"
 
 flag {
   name: "face_vhal_feature"
@@ -8,8 +9,8 @@
 }
 
 flag {
-    name: "de_hidl"
-    namespace: "biometrics_framework"
-    description: "feature flag for biometrics de-hidl"
-    bug: "287332354"
-}
\ No newline at end of file
+  name: "use_vhal_for_testing"
+  namespace: "biometrics_framework"
+  description: "This flag controls whether virtual HAL is used for testing instead of TestHal "
+  bug: "294254230"
+}
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContext.java b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
index 7f04628..7a8e25b 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContext.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
@@ -81,22 +81,6 @@
     boolean isHardwareIgnoringTouches();
 
     /**
-     * Subscribe to context changes.
-     *
-     * Note that this method only notifies for properties that are visible to the HAL.
-     *
-     * @param context context that will be modified when changed
-     * @param consumer callback when the context is modified
-     *
-     * @deprecated instead use {@link BiometricContext#subscribe(OperationContextExt, Consumer,
-     *                                                           Consumer, AuthenticateOptions)}
-     * TODO (b/294161627): Delete this API once Flags.DE_HIDL is removed.
-     */
-    @Deprecated
-    void subscribe(@NonNull OperationContextExt context,
-            @NonNull Consumer<OperationContext> consumer);
-
-    /**
      * Subscribe to context changes and start the HAL operation.
      *
      * Note that this method only notifies for properties that are visible to the HAL.
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
index d8dfa60..a17de3d 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
@@ -229,16 +229,6 @@
 
     @Override
     public void subscribe(@NonNull OperationContextExt context,
-            @NonNull Consumer<OperationContext> consumer) {
-        mSubscribers.put(context, consumer);
-        // TODO(b/294161627) Combine the getContext/subscribe APIs to avoid race
-        if (context.getDisplayState() != getDisplayState()) {
-            consumer.accept(context.update(this, context.isCrypto()).toAidlContext());
-        }
-    }
-
-    @Override
-    public void subscribe(@NonNull OperationContextExt context,
             @NonNull Consumer<OperationContext> startHalConsumer,
             @NonNull Consumer<OperationContext> updateContextConsumer,
             @Nullable AuthenticateOptions options) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java
index d9947dd..dc2eff4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java
@@ -235,7 +235,7 @@
             mApiCallNumber = 0;
         }
 
-        void addApiCall(String str) {
+        synchronized void addApiCall(String str) {
             mApiCalls[mCurr] = str;
             mCurr++;
             mCurr %= mSize;
@@ -243,7 +243,7 @@
         }
 
         @Override
-        public String toString() {
+        public synchronized String toString() {
             String buffer = "";
             int apiCall = mApiCallNumber > mSize ? mApiCallNumber - mSize : 0;
             for (int i = 0; i < mSize; i++) {
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 62c21cf..1e2451c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -30,12 +30,11 @@
 import android.hardware.biometrics.BiometricRequestConstants;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.security.KeyStore;
+import android.security.KeyStoreAuthorization;
 import android.util.EventLog;
 import android.util.Slog;
 
 import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
@@ -117,24 +116,20 @@
 
     @LockoutTracker.LockoutMode
     public int handleFailedAttempt(int userId) {
-        if (Flags.deHidl()) {
-            if (mLockoutTracker != null) {
-                mLockoutTracker.addFailedAttemptForUser(getTargetUserId());
-            }
-            @LockoutTracker.LockoutMode final int lockoutMode =
-                    getLockoutTracker().getLockoutModeForUser(userId);
-            final PerformanceTracker performanceTracker =
-                    PerformanceTracker.getInstanceForSensorId(getSensorId());
-            if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) {
-                performanceTracker.incrementPermanentLockoutForUser(userId);
-            } else if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) {
-                performanceTracker.incrementTimedLockoutForUser(userId);
-            }
-
-            return lockoutMode;
-        } else {
-            return LockoutTracker.LOCKOUT_NONE;
+        if (mLockoutTracker != null) {
+            mLockoutTracker.addFailedAttemptForUser(getTargetUserId());
         }
+        @LockoutTracker.LockoutMode final int lockoutMode =
+                getLockoutTracker().getLockoutModeForUser(userId);
+        final PerformanceTracker performanceTracker =
+                PerformanceTracker.getInstanceForSensorId(getSensorId());
+        if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) {
+            performanceTracker.incrementPermanentLockoutForUser(userId);
+        } else if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) {
+            performanceTracker.incrementTimedLockoutForUser(userId);
+        }
+
+        return lockoutMode;
     }
 
     protected long getStartTimeMs() {
@@ -255,7 +250,7 @@
 
             // For BP, BiometricService will add the authToken to Keystore.
             if (!isBiometricPrompt() && mIsStrongBiometric) {
-                final int result = KeyStore.getInstance().addAuthToken(byteToken);
+                final int result = KeyStoreAuthorization.getInstance().addAuthToken(byteToken);
                 if (result != 0) {
                     Slog.d(TAG, "Error adding auth token : " + result);
                 } else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java
index 1dc882e5..82419e6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java
@@ -18,8 +18,13 @@
 
 import android.annotation.NonNull;
 import android.hardware.biometrics.AuthenticationStateListener;
-import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -64,14 +69,73 @@
     }
 
     /**
-     * Defines behavior in response to authentication starting
-     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for requesting
-     * authentication starting
+     * Defines behavior in response to biometric authentication being acquired.
+     * @param authInfo information related to the biometric authentication acquired.
      */
-    public void onAuthenticationStarted(int requestReason) {
+    public void onAuthenticationAcquired(AuthenticationAcquiredInfo authInfo) {
         for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
             try {
-                listener.onAuthenticationStarted(requestReason);
+                listener.onAuthenticationAcquired(authInfo);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in notifying listener that authentication "
+                        + "acquired", e);
+            }
+        }
+    }
+
+    /**
+     * Defines behavior in response to an unrecoverable error encountered during authentication.
+     * @param authInfo information related to the unrecoverable auth error encountered
+     */
+    public void onAuthenticationError(AuthenticationErrorInfo authInfo) {
+        for (AuthenticationStateListener listener : mAuthenticationStateListeners) {
+            try {
+                listener.onAuthenticationError(authInfo);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in notifying listener of unrecoverable"
+                        + " authentication error", e);
+            }
+        }
+    }
+
+    /**
+     * Defines behavior in response to a failed authentication
+     * @param authInfo information related to the failed authentication
+     */
+    public void onAuthenticationFailed(AuthenticationFailedInfo authInfo) {
+        for (AuthenticationStateListener listener : mAuthenticationStateListeners) {
+            try {
+                listener.onAuthenticationFailed(authInfo);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in notifying listener that authentication "
+                        + "failed", e);
+            }
+        }
+    }
+
+    /**
+     * Defines behavior in response to a recoverable error encountered during authentication.
+     * @param authInfo information related to the recoverable auth error encountered
+     */
+    public void onAuthenticationHelp(AuthenticationHelpInfo authInfo) {
+        for (AuthenticationStateListener listener : mAuthenticationStateListeners) {
+            try {
+                listener.onAuthenticationHelp(authInfo);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in notifying listener of recoverable"
+                        + " authentication error", e);
+            }
+        }
+    }
+
+    /**
+     * Defines behavior in response to authentication starting
+     * @param authInfo information related to the authentication starting
+     */
+    public void onAuthenticationStarted(AuthenticationStartedInfo authInfo) {
+        for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
+            try {
+                listener.onAuthenticationStarted(authInfo);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote exception in notifying listener that authentication "
                         + "started", e);
@@ -81,11 +145,12 @@
 
     /**
      * Defines behavior in response to authentication stopping
+     * @param authInfo information related to the authentication stopping
      */
-    public void onAuthenticationStopped() {
+    public void onAuthenticationStopped(AuthenticationStoppedInfo authInfo) {
         for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
             try {
-                listener.onAuthenticationStopped();
+                listener.onAuthenticationStopped(authInfo);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote exception in notifying listener that authentication "
                         + "stopped", e);
@@ -95,14 +160,12 @@
 
     /**
      * Defines behavior in response to a successful authentication
-     * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested
-     *                      authentication
-     * @param userId The user Id for the requested authentication
+     * @param authInfo information related to the successful authentication
      */
-    public void onAuthenticationSucceeded(int requestReason, int userId) {
+    public void onAuthenticationSucceeded(AuthenticationSucceededInfo authInfo) {
         for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
             try {
-                listener.onAuthenticationSucceeded(requestReason, userId);
+                listener.onAuthenticationSucceeded(authInfo);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote exception in notifying listener that authentication "
                         + "succeeded", e);
@@ -110,44 +173,6 @@
         }
     }
 
-    /**
-     * Defines behavior in response to a failed authentication
-     * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested
-     *                      authentication
-     * @param userId The user Id for the requested authentication
-     */
-    public void onAuthenticationFailed(int requestReason, int userId) {
-        for (AuthenticationStateListener listener : mAuthenticationStateListeners) {
-            try {
-                listener.onAuthenticationFailed(requestReason, userId);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote exception in notifying listener that authentication "
-                        + "failed", e);
-            }
-        }
-    }
-
-    /**
-     * Defines behavior in response to biometric being acquired.
-     * @param biometricSourceType identifies [BiometricSourceType] biometric was acquired for
-     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for authentication
-     * @param acquiredInfo [BiometricFingerprintConstants.FingerprintAcquired] int corresponding to
-     *                     a known acquired message.
-     */
-    public void onAuthenticationAcquired(
-            BiometricSourceType biometricSourceType, int requestReason,
-            @BiometricFingerprintConstants.FingerprintAcquired int acquiredInfo
-    ) {
-        for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
-            try {
-                listener.onAuthenticationAcquired(biometricSourceType, requestReason, acquiredInfo);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote exception in notifying listener that authentication "
-                        + "stopped", e);
-            }
-        }
-    }
-
     @Override
     public void binderDied() {
         // Do nothing, handled below
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 89e08c1..82d5d4d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -19,9 +19,9 @@
 import static com.android.server.biometrics.sensors.BiometricSchedulerOperation.STATE_STARTED;
 
 import android.annotation.IntDef;
-import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.WorkerThread;
 import android.content.Context;
 import android.hardware.biometrics.IBiometricService;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -38,7 +38,6 @@
 import com.android.modules.expresslog.Counter;
 import com.android.server.biometrics.BiometricSchedulerProto;
 import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
 
 import java.io.PrintWriter;
@@ -65,9 +64,8 @@
  * @param <T> Hal instance for starting the user.
  * @param <U> Session associated with the current user id.
  *
- * TODO: (b/304604965) Update thread annotation when FLAGS_DE_HIDL is removed.
  */
-@MainThread
+@WorkerThread
 public class BiometricScheduler<T, U> {
 
     private static final String TAG = "BiometricScheduler";
@@ -176,7 +174,7 @@
                     Slog.w(TAG, "operation is already null or different (reset?): "
                             + mCurrentOperation);
                 }
-                startNextOperationIfIdle();
+                checkCurrentUserAndStartNextOperation();
             });
         }
     }
@@ -219,7 +217,7 @@
                 mRecentOperations.add(mCurrentOperation.getProtoEnum());
                 mCurrentOperation = null;
                 mTotalOperationsHandled++;
-                startNextOperationIfIdle();
+                checkCurrentUserAndStartNextOperation();
             });
         }
     };
@@ -304,15 +302,7 @@
         return mInternalCallback;
     }
 
-    protected void startNextOperationIfIdle() {
-        if (Flags.deHidl()) {
-            startNextOperation();
-        } else {
-            startNextOperationIfIdleLegacy();
-        }
-    }
-
-    protected void startNextOperation() {
+    protected void checkCurrentUserAndStartNextOperation() {
         if (mCurrentOperation != null) {
             Slog.v(TAG, "Not idle, current operation: " + mCurrentOperation);
             return;
@@ -326,7 +316,7 @@
         final int nextUserId = mPendingOperations.getFirst().getTargetUserId();
 
         if (nextUserId == currentUserId || mPendingOperations.getFirst().isStartUserOperation()) {
-            startNextOperationIfIdleLegacy();
+            startNextOperationIfIdle();
         } else if (currentUserId == UserHandle.USER_NULL && mUserSwitchProvider != null) {
             final BaseClientMonitor startClient =
                     mUserSwitchProvider.getStartUserClient(nextUserId);
@@ -357,7 +347,7 @@
         }
     }
 
-    protected void startNextOperationIfIdleLegacy() {
+    protected void startNextOperationIfIdle() {
         if (mCurrentOperation != null) {
             Slog.v(TAG, "Not idle, current operation: " + mCurrentOperation);
             return;
@@ -422,7 +412,7 @@
                 // run these. A single request from the manager layer to the service layer may
                 // actually be multiple operations (i.e. updateActiveUser + authenticate).
                 mCurrentOperation = null;
-                startNextOperationIfIdle();
+                checkCurrentUserAndStartNextOperation();
             }
         } else {
             try {
@@ -459,7 +449,7 @@
         } else {
             Slog.e(TAG, "[Unable To Start] Prepared client: " + mCurrentOperation);
             mCurrentOperation = null;
-            startNextOperationIfIdle();
+            checkCurrentUserAndStartNextOperation();
         }
     }
 
@@ -504,7 +494,7 @@
             Slog.d(TAG, "[Cancelling Interruptable]: " + mCurrentOperation);
             mCurrentOperation.cancel(mHandler, mInternalCallback);
         } else {
-            startNextOperationIfIdle();
+            checkCurrentUserAndStartNextOperation();
         }
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
index af6de5c..438367d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.face.FaceEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -136,7 +137,8 @@
         return true;
     }
 
-    protected int getRequestReasonFromEnrollReason(@FingerprintManager.EnrollReason int reason) {
+    protected int getRequestReasonFromFingerprintEnrollReason(
+            @FingerprintManager.EnrollReason int reason) {
         switch (reason) {
             case FingerprintManager.ENROLL_FIND_SENSOR:
                 return BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR;
@@ -146,4 +148,15 @@
                 return BiometricRequestConstants.REASON_UNKNOWN;
         }
     }
+
+    protected int getRequestReasonFromFaceEnrollReason(
+            @FaceEnrollOptions.EnrollReason int reason) {
+        return switch (reason) {
+            case FaceEnrollOptions.ENROLL_REASON_RE_ENROLL_NOTIFICATION,
+                    FaceEnrollOptions.ENROLL_REASON_SETTINGS,
+                    FaceEnrollOptions.ENROLL_REASON_SUW ->
+                    BiometricRequestConstants.REASON_ENROLL_ENROLLING;
+            default -> BiometricRequestConstants.REASON_UNKNOWN;
+        };
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
index 3d20efc..f5a2f34 100644
--- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
@@ -16,12 +16,10 @@
 
 package com.android.server.biometrics.sensors;
 
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.hardware.biometrics.BiometricRequestConstants;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
 import android.os.RemoteException;
@@ -45,22 +43,6 @@
 
     @NonNull private final Optional<IUdfpsOverlayController> mUdfpsOverlayController;
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @NonNull private final Optional<ISidefpsController> mSidefpsController;
-
-    /**
-     * Create an overlay controller for each modality.
-     *
-     * @param udfpsOverlayController under display fps or null if not present on device
-     * @param sidefpsController side fps or null if not present on device
-     */
-    public SensorOverlays(
-            @Nullable IUdfpsOverlayController udfpsOverlayController,
-            @Nullable ISidefpsController sidefpsController) {
-        mUdfpsOverlayController = Optional.ofNullable(udfpsOverlayController);
-        mSidefpsController = Optional.ofNullable(sidefpsController);
-    }
-
     /**
      * Create an overlay controller for each modality.
      *
@@ -68,8 +50,6 @@
      */
     public SensorOverlays(@Nullable IUdfpsOverlayController udfpsOverlayController) {
         mUdfpsOverlayController = Optional.ofNullable(udfpsOverlayController);
-        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-        mSidefpsController = Optional.empty();
     }
 
     /**
@@ -81,16 +61,6 @@
      */
     public void show(int sensorId, @BiometricRequestConstants.RequestReason int reason,
             @NonNull AcquisitionClient<?> client) {
-        if (!sidefpsControllerRefactor()) {
-            if (mSidefpsController.isPresent()) {
-                try {
-                    mSidefpsController.get().show(sensorId, reason);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception when showing the side-fps overlay", e);
-                }
-            }
-        }
-
         if (mUdfpsOverlayController.isPresent()) {
             final IUdfpsOverlayControllerCallback callback =
                     new IUdfpsOverlayControllerCallback.Stub() {
@@ -115,16 +85,6 @@
      * @param sensorId sensor id
      */
     public void hide(int sensorId) {
-        if (!sidefpsControllerRefactor()) {
-            if (mSidefpsController.isPresent()) {
-                try {
-                    mSidefpsController.get().hide(sensorId);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception when hiding the side-fps overlay", e);
-                }
-            }
-        }
-
         if (mUdfpsOverlayController.isPresent()) {
             try {
                 mUdfpsOverlayController.get().hideUdfpsOverlay(sensorId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
deleted file mode 100644
index 7ca10e3..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
+++ /dev/null
@@ -1,183 +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.biometrics.sensors;
-
-import static com.android.server.biometrics.sensors.BiometricSchedulerOperation.STATE_STARTED;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.hardware.biometrics.IBiometricService;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
-
-/**
- * A user-aware scheduler that requests user-switches based on scheduled operation's targetUserId.
- * TODO (b/304604965): Remove class when Flags.FLAG_DE_HIDL is removed.
- *
- * @param <T> Hal instance for starting the user.
- * @param <U> Session associated with the current user id.
- */
-public class UserAwareBiometricScheduler<T, U> extends BiometricScheduler<T, U> {
-
-    private static final String TAG = "UaBiometricScheduler";
-
-    /**
-     * Interface to retrieve the owner's notion of the current userId. Note that even though
-     * the scheduler can determine this based on its history of processed clients, we should still
-     * query the owner since it may be cleared due to things like HAL death, etc.
-     */
-    public interface CurrentUserRetriever {
-        int getCurrentUserId();
-    }
-
-    public interface UserSwitchCallback {
-        @NonNull StopUserClient<?> getStopUserClient(int userId);
-        @NonNull StartUserClient<?, ?> getStartUserClient(int newUserId);
-    }
-
-    @NonNull private final CurrentUserRetriever mCurrentUserRetriever;
-    @NonNull private final UserSwitchCallback mUserSwitchCallback;
-    @Nullable private StopUserClient<?> mStopUserClient;
-
-    private class ClientFinishedCallback implements ClientMonitorCallback {
-        @NonNull private final BaseClientMonitor mOwner;
-
-        ClientFinishedCallback(@NonNull BaseClientMonitor owner) {
-            mOwner = owner;
-        }
-
-        @Override
-        public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
-            mHandler.post(() -> {
-                Slog.d(TAG, "[Client finished] " + clientMonitor + ", success: " + success);
-
-                // Set mStopUserClient to null when StopUserClient fails. Otherwise it's possible
-                // for that the queue will wait indefinitely until the field is cleared.
-                if (clientMonitor instanceof StopUserClient<?>) {
-                    if (!success) {
-                        Slog.w(TAG, "StopUserClient failed(), is the HAL stuck? "
-                                + "Clearing mStopUserClient");
-                    }
-                    mStopUserClient = null;
-                }
-                if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) {
-                    mCurrentOperation = null;
-                } else {
-                    // can happen if the hal dies and is usually okay
-                    // do not unset the current operation that may be newer
-                    Slog.w(TAG, "operation is already null or different (reset?): "
-                            + mCurrentOperation);
-                }
-                startNextOperationIfIdle();
-            });
-        }
-    }
-
-    @VisibleForTesting
-    public UserAwareBiometricScheduler(@NonNull String tag,
-            @NonNull Handler handler,
-            @SensorType int sensorType,
-            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
-            @NonNull IBiometricService biometricService,
-            @NonNull CurrentUserRetriever currentUserRetriever,
-            @NonNull UserSwitchCallback userSwitchCallback) {
-        super(handler, sensorType, gestureAvailabilityDispatcher, biometricService,
-                LOG_NUM_RECENT_OPERATIONS);
-
-        mCurrentUserRetriever = currentUserRetriever;
-        mUserSwitchCallback = userSwitchCallback;
-    }
-
-    public UserAwareBiometricScheduler(@NonNull String tag,
-            @SensorType int sensorType,
-            @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
-            @NonNull CurrentUserRetriever currentUserRetriever,
-            @NonNull UserSwitchCallback userSwitchCallback) {
-        this(tag, new Handler(Looper.getMainLooper()), sensorType, gestureAvailabilityDispatcher,
-                IBiometricService.Stub.asInterface(
-                        ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
-                currentUserRetriever, userSwitchCallback);
-    }
-
-    @Override
-    protected void startNextOperationIfIdle() {
-        if (mCurrentOperation != null) {
-            Slog.v(TAG, "Not idle, current operation: " + mCurrentOperation);
-            return;
-        }
-        if (mPendingOperations.isEmpty()) {
-            Slog.d(TAG, "No operations, returning to idle");
-            return;
-        }
-
-        final int currentUserId = mCurrentUserRetriever.getCurrentUserId();
-        final int nextUserId = mPendingOperations.getFirst().getTargetUserId();
-
-        if (nextUserId == currentUserId || mPendingOperations.getFirst().isStartUserOperation()) {
-            super.startNextOperationIfIdle();
-        } else if (currentUserId == UserHandle.USER_NULL) {
-            final BaseClientMonitor startClient =
-                    mUserSwitchCallback.getStartUserClient(nextUserId);
-            final ClientFinishedCallback finishedCallback =
-                    new ClientFinishedCallback(startClient);
-
-            Slog.d(TAG, "[Starting User] " + startClient);
-            mCurrentOperation = new BiometricSchedulerOperation(
-                    startClient, finishedCallback, STATE_STARTED);
-            startClient.start(finishedCallback);
-        } else {
-            if (mStopUserClient != null) {
-                Slog.d(TAG, "[Waiting for StopUser] " + mStopUserClient);
-            } else {
-                mStopUserClient = mUserSwitchCallback
-                        .getStopUserClient(currentUserId);
-                final ClientFinishedCallback finishedCallback =
-                        new ClientFinishedCallback(mStopUserClient);
-
-                Slog.d(TAG, "[Stopping User] current: " + currentUserId
-                        + ", next: " + nextUserId + ". " + mStopUserClient);
-                mCurrentOperation = new BiometricSchedulerOperation(
-                        mStopUserClient, finishedCallback, STATE_STARTED);
-                mStopUserClient.start(finishedCallback);
-            }
-        }
-    }
-
-    @Override
-    public void onUserStopped() {
-        if (mStopUserClient == null) {
-            Slog.e(TAG, "Unexpected onUserStopped");
-            return;
-        }
-
-        Slog.d(TAG, "[OnUserStopped]: " + mStopUserClient);
-        mStopUserClient.onUserStopped();
-        mStopUserClient = null;
-    }
-
-    @VisibleForTesting
-    @Nullable public StopUserClient<?> getStopUserClient() {
-        return mStopUserClient;
-    }
-}
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 1037124..bd6d593 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
@@ -72,9 +72,6 @@
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
 import com.android.server.biometrics.sensors.LockoutTracker;
 import com.android.server.biometrics.sensors.face.aidl.FaceProvider;
-import com.android.server.biometrics.sensors.face.hidl.Face10;
-
-import com.google.android.collect.Lists;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -664,60 +661,11 @@
             provider.second.scheduleGetFeature(provider.first, token, userId, feature,
                     new ClientMonitorCallbackConverter(receiver), opPackageName);
         }
-        @NonNull
-        private List<ServiceProvider> getHidlProviders(
-                @NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
-            final List<ServiceProvider> providers = new ArrayList<>();
-
-            for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
-                providers.add(
-                        Face10.newInstance(getContext(), mBiometricStateCallback,
-                                mAuthenticationStateListeners, hidlSensor,
-                                mLockoutResetDispatcher));
-            }
-
-            return providers;
-        }
-
-        @NonNull
-        private List<ServiceProvider> getAidlProviders(@NonNull List<String> instances) {
-            final List<ServiceProvider> providers = new ArrayList<>();
-
-            for (String instance : instances) {
-                final FaceProvider provider = mFaceProvider.apply(instance);
-                Slog.i(TAG, "Adding AIDL provider: " + instance);
-                providers.add(provider);
-            }
-
-            return providers;
-        }
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         public void registerAuthenticators(
-                @NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
-            super.registerAuthenticators_enforcePermission();
-
-            mRegistry.registerAll(() -> {
-                List<String> aidlSensors = new ArrayList<>();
-                final String[] instances = mAidlInstanceNameSupplier.get();
-                if (instances != null) {
-                    aidlSensors.addAll(Lists.newArrayList(instances));
-                }
-
-                final Pair<List<FaceSensorPropertiesInternal>, List<String>>
-                        filteredInstances = filterAvailableHalInstances(hidlSensors, aidlSensors);
-
-                final List<ServiceProvider> providers = new ArrayList<>();
-                providers.addAll(getHidlProviders(filteredInstances.first));
-                providers.addAll(getAidlProviders(filteredInstances.second));
-                return providers;
-            });
-        }
-
-        @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
-        public void registerAuthenticatorsLegacy(
                 FaceSensorConfigurations faceSensorConfigurations) {
-            super.registerAuthenticatorsLegacy_enforcePermission();
+            super.registerAuthenticators_enforcePermission();
 
             if (!faceSensorConfigurations.hasSensorConfigurations()) {
                 Slog.d(TAG, "No face sensors to register.");
@@ -748,7 +696,7 @@
             final String virtualInstance = "virtual";
             final boolean isVirtualHalPresent =
                     faceSensorConfigurations.doesInstanceExist(virtualInstance);
-            if (Flags.faceVhalFeature() && Utils.isVirtualEnabled(getContext())) {
+            if (Flags.faceVhalFeature() && Utils.isFaceVirtualEnabled(getContext())) {
                 if (isVirtualHalPresent) {
                     return new Pair<>(virtualInstance,
                             faceSensorConfigurations.getSensorPropForInstance(virtualInstance));
@@ -771,40 +719,6 @@
                     .getSensorPropForInstance(finalSensorInstance));
         }
 
-        private Pair<List<FaceSensorPropertiesInternal>, List<String>>
-                filterAvailableHalInstances(
-                @NonNull List<FaceSensorPropertiesInternal> hidlInstances,
-                @NonNull List<String> aidlInstances) {
-            if ((hidlInstances.size() + aidlInstances.size()) <= 1) {
-                return new Pair(hidlInstances, aidlInstances);
-            }
-
-            if (Flags.faceVhalFeature()) {
-                Slog.i(TAG, "Face VHAL feature is on");
-            } else {
-                Slog.i(TAG, "Face VHAL feature is off");
-            }
-
-            final int virtualAt = aidlInstances.indexOf("virtual");
-            if (Flags.faceVhalFeature() && Utils.isVirtualEnabled(getContext())) {
-                if (virtualAt != -1) {
-                    //only virtual instance should be returned
-                    Slog.i(TAG, "virtual hal is used");
-                    return new Pair(new ArrayList<>(), List.of(aidlInstances.get(virtualAt)));
-                } else {
-                    Slog.e(TAG, "Could not find virtual interface while it is enabled");
-                    return new Pair(hidlInstances, aidlInstances);
-                }
-            } else {
-                //remove virtual instance
-                aidlInstances = new ArrayList<>(aidlInstances);
-                if (virtualAt != -1) {
-                    aidlInstances.remove(virtualAt);
-                }
-                return new Pair(hidlInstances, aidlInstances);
-            }
-        }
-
         @Override
         public void addAuthenticatorsRegisteredCallback(
                 IFaceAuthenticatorsRegisteredCallback callback) {
@@ -883,17 +797,13 @@
             return null;
         };
 
-        if (Flags.deHidl()) {
-            mFaceProviderFunction = faceProviderFunction != null ? faceProviderFunction :
-                    ((filteredSensorProps, resetLockoutRequiresChallenge) -> new FaceProvider(
-                            getContext(), mBiometricStateCallback, mAuthenticationStateListeners,
-                            filteredSensorProps.second,
-                            filteredSensorProps.first, mLockoutResetDispatcher,
-                            BiometricContext.getInstance(getContext()),
-                            resetLockoutRequiresChallenge));
-        } else {
-            mFaceProviderFunction = ((filteredSensorProps, resetLockoutRequiresChallenge) -> null);
-        }
+        mFaceProviderFunction = faceProviderFunction != null ? faceProviderFunction :
+                ((filteredSensorProps, resetLockoutRequiresChallenge) -> new FaceProvider(
+                        getContext(), mBiometricStateCallback, mAuthenticationStateListeners,
+                        filteredSensorProps.second,
+                        filteredSensorProps.first, mLockoutResetDispatcher,
+                        BiometricContext.getInstance(getContext()),
+                        resetLockoutRequiresChallenge));
     }
 
     @Override
@@ -928,7 +838,7 @@
 
     void syncEnrollmentsNow() {
         Utils.checkPermissionOrShell(getContext(), MANAGE_FACE);
-        if (Flags.faceVhalFeature() && Utils.isVirtualEnabled(getContext())) {
+        if (Flags.faceVhalFeature() && Utils.isFaceVirtualEnabled(getContext())) {
             Slog.i(TAG, "Sync virtual enrollments");
             final int userId = ActivityManager.getCurrentUser();
             for (ServiceProvider provider : mRegistry.getProviders()) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java
index 098be21..cf677d5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java
@@ -27,7 +27,6 @@
 import android.hardware.keymaster.HardwareAuthToken;
 import android.util.Slog;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.HardwareAuthTokenUtils;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.sensors.AcquisitionClient;
@@ -53,16 +52,6 @@
     /**
      * Interface to send results to the AidlResponseHandler's owner.
      */
-    public interface HardwareUnavailableCallback {
-        /**
-         * Invoked when the HAL sends ERROR_HW_UNAVAILABLE.
-         */
-        void onHardwareUnavailable();
-    }
-
-    /**
-     * Interface to send results to the AidlResponseHandler's owner.
-     */
     public interface AidlResponseHandlerCallback {
         /**
          * Invoked when enrollment is successful.
@@ -90,8 +79,6 @@
     @NonNull
     private final AuthSessionCoordinator mAuthSessionCoordinator;
     @NonNull
-    private final HardwareUnavailableCallback mHardwareUnavailableCallback;
-    @NonNull
     private final AidlResponseHandlerCallback mAidlResponseHandlerCallback;
 
     public AidlResponseHandler(@NonNull Context context,
@@ -99,24 +86,6 @@
             @NonNull LockoutTracker lockoutTracker,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull AuthSessionCoordinator authSessionCoordinator,
-            @NonNull HardwareUnavailableCallback hardwareUnavailableCallback) {
-        this(context, scheduler, sensorId, userId, lockoutTracker, lockoutResetDispatcher,
-                authSessionCoordinator, hardwareUnavailableCallback,
-                new AidlResponseHandlerCallback() {
-                    @Override
-                    public void onEnrollSuccess() {}
-
-                    @Override
-                    public void onHardwareUnavailable() {}
-                });
-    }
-
-    public AidlResponseHandler(@NonNull Context context,
-            @NonNull BiometricScheduler scheduler, int sensorId, int userId,
-            @NonNull LockoutTracker lockoutTracker,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull AuthSessionCoordinator authSessionCoordinator,
-            @NonNull HardwareUnavailableCallback hardwareUnavailableCallback,
             @NonNull AidlResponseHandlerCallback aidlResponseHandlerCallback) {
         mContext = context;
         mScheduler = scheduler;
@@ -125,7 +94,6 @@
         mLockoutTracker = lockoutTracker;
         mLockoutResetDispatcher = lockoutResetDispatcher;
         mAuthSessionCoordinator = authSessionCoordinator;
-        mHardwareUnavailableCallback = hardwareUnavailableCallback;
         mAidlResponseHandlerCallback = aidlResponseHandlerCallback;
     }
 
@@ -185,11 +153,7 @@
         handleResponse(ErrorConsumer.class, (c) -> {
             c.onError(error, vendorCode);
             if (error == Error.HW_UNAVAILABLE) {
-                if (Flags.deHidl()) {
-                    mAidlResponseHandlerCallback.onHardwareUnavailable();
-                } else {
-                    mHardwareUnavailableCallback.onHardwareUnavailable();
-                }
+                mAidlResponseHandlerCallback.onHardwareUnavailable();
             }
         });
     }
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 415d294..8d32235 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
@@ -17,10 +17,13 @@
 package com.android.server.biometrics.sensors.face.aidl;
 
 import static android.adaptiveauth.Flags.reportBiometricAuthAttempts;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR_BASE;
+import static android.hardware.face.FaceManager.getAuthHelpMessage;
+import static android.hardware.face.FaceManager.getErrorString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.NotificationManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.hardware.SensorPrivacyManager;
@@ -28,7 +31,15 @@
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricFaceConstants;
 import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.hardware.biometrics.face.IFace;
 import android.hardware.face.FaceAuthenticateOptions;
 import android.hardware.face.FaceAuthenticationFrame;
@@ -39,7 +50,6 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
@@ -65,13 +75,11 @@
         extends AuthenticationClient<AidlSession, FaceAuthenticateOptions>
         implements LockoutConsumer {
     private static final String TAG = "FaceAuthenticationClient";
-
     @NonNull
     private final UsageStats mUsageStats;
     @NonNull
     private final AuthSessionCoordinator mAuthSessionCoordinator;
-    @Nullable
-    private final NotificationManager mNotificationManager;
+    private final boolean mIsStrongBiometric;
     private final int[] mBiometricPromptIgnoreList;
     private final int[] mBiometricPromptIgnoreListVendor;
     private final int[] mKeyguardIgnoreList;
@@ -122,8 +130,8 @@
                 allowBackgroundAuthentication, false /* shouldVibrate */,
                 biometricStrength);
         setRequestId(requestId);
+        mIsStrongBiometric = isStrongBiometric;
         mUsageStats = usageStats;
-        mNotificationManager = context.getSystemService(NotificationManager.class);
         mSensorPrivacyManager = sensorPrivacyManager;
         mAuthSessionCoordinator = biometricContext.getAuthSessionCoordinator();
         mAuthenticationStateListeners = authenticationStateListeners;
@@ -154,6 +162,9 @@
 
     @Override
     protected void startHalOperation() {
+        mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo.Builder(
+                BiometricSourceType.FACE, getRequestReason()).build()
+        );
         try {
             if (mSensorPrivacyManager != null
                     && mSensorPrivacyManager
@@ -163,11 +174,7 @@
                         0 /* vendorCode */);
                 mCallback.onClientFinished(this, false /* success */);
             } else {
-                if (Flags.deHidl()) {
-                    startAuthenticate();
-                } else {
-                    mCancellationSignal = doAuthenticate();
-                }
+                doAuthenticate();
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception when requesting auth", e);
@@ -176,27 +183,7 @@
         }
     }
 
-    private ICancellationSignal doAuthenticate() throws RemoteException {
-        final AidlSession session = getFreshDaemon();
-
-        if (session.hasContextMethods()) {
-            final OperationContextExt opContext = getOperationContext();
-            final ICancellationSignal cancel = session.getSession().authenticateWithContext(
-                    mOperationId, opContext.toAidlContext(getOptions()));
-            getBiometricContext().subscribe(opContext, ctx -> {
-                try {
-                    session.getSession().onContextChanged(ctx);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to notify context changed", e);
-                }
-            });
-            return cancel;
-        } else {
-            return session.getSession().authenticate(mOperationId);
-        }
-    }
-
-    private void startAuthenticate() throws RemoteException {
+    private void doAuthenticate() throws RemoteException {
         final AidlSession session = getFreshDaemon();
 
         if (session.hasContextMethods()) {
@@ -225,6 +212,9 @@
 
     @Override
     protected void stopHalOperation() {
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FACE, getRequestReason()).build()
+        );
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
@@ -255,6 +245,9 @@
         // 3) Authenticated == false
         // 4) onLockout
         // 5) onLockoutTimed
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FACE, getRequestReason()).build()
+        );
         mCallback.onClientFinished(this, true /* success */);
     }
 
@@ -274,11 +267,15 @@
 
         if (reportBiometricAuthAttempts()) {
             if (authenticated) {
-                mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(),
-                        getTargetUserId());
+                mAuthenticationStateListeners.onAuthenticationSucceeded(
+                    new AuthenticationSucceededInfo.Builder(BiometricSourceType.FACE,
+                            getRequestReason(), mIsStrongBiometric, getTargetUserId()).build()
+                );
             } else {
-                mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(),
-                        getTargetUserId());
+                mAuthenticationStateListeners.onAuthenticationFailed(
+                        new AuthenticationFailedInfo.Builder(BiometricSourceType.FACE,
+                                getRequestReason(), getTargetUserId()).build()
+                );
             }
         }
     }
@@ -292,8 +289,14 @@
                 error,
                 vendorCode,
                 getTargetUserId()));
-
+        mAuthenticationStateListeners.onAuthenticationError(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FACE, getRequestReason(),
+                        getErrorString(getContext(), error, vendorCode), error).build()
+        );
         super.onError(error, vendorCode);
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FACE, getRequestReason()).build()
+        );
     }
 
     private int[] getAcquireIgnorelist() {
@@ -305,7 +308,7 @@
     }
 
     private boolean shouldSendAcquiredMessage(int acquireInfo, int vendorCode) {
-        return acquireInfo == FaceManager.FACE_ACQUIRED_VENDOR
+        return acquireInfo == FACE_ACQUIRED_VENDOR
                 ? !Utils.listContains(getAcquireVendorIgnorelist(), vendorCode)
                 : !Utils.listContains(getAcquireIgnorelist(), acquireInfo);
     }
@@ -314,6 +317,20 @@
     public void onAcquired(int acquireInfo, int vendorCode) {
         mLastAcquire = acquireInfo;
         final boolean shouldSend = shouldSendAcquiredMessage(acquireInfo, vendorCode);
+        if (shouldSend) {
+            mAuthenticationStateListeners.onAuthenticationAcquired(
+                    new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FACE,
+                            getRequestReason(), acquireInfo).build()
+            );
+            final String helpMessage = getAuthHelpMessage(getContext(), acquireInfo, vendorCode);
+            if (helpMessage != null) {
+                final int helpCode = getHelpCode(acquireInfo, vendorCode);
+                mAuthenticationStateListeners.onAuthenticationHelp(
+                        new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                                getRequestReason(), helpMessage, helpCode).build()
+                );
+            }
+        }
         onAcquiredInternal(acquireInfo, vendorCode, shouldSend);
 
         //Check if it is AIDL (lockoutTracker = null) or if it there is no lockout for HIDL
@@ -339,9 +356,27 @@
         final boolean shouldSend = shouldSendAcquiredMessage(acquireInfo, vendorCode);
         if (shouldSend) {
             try {
+                if (shouldSend) {
+                    mAuthenticationStateListeners.onAuthenticationAcquired(
+                            new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FACE,
+                                    getRequestReason(), acquireInfo).build()
+                    );
+                    final String helpMessage = getAuthHelpMessage(getContext(), acquireInfo,
+                            vendorCode);
+                    if (helpMessage != null) {
+                        final int helpCode = getHelpCode(acquireInfo, vendorCode);
+                        mAuthenticationStateListeners.onAuthenticationHelp(
+                                new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                                        getRequestReason(), helpMessage, helpCode).build()
+                        );
+                    }
+                }
                 getListener().onAuthenticationFrame(frame);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed to send authentication frame", e);
+                mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                        .Builder(BiometricSourceType.FACE, getRequestReason()).build()
+                );
                 mCallback.onClientFinished(this, false /* success */);
             }
         }
@@ -358,7 +393,6 @@
 
         PerformanceTracker.getInstanceForSensorId(getSensorId())
                 .incrementTimedLockoutForUser(getTargetUserId());
-
         onError(error, 0 /* vendorCode */);
     }
 
@@ -373,7 +407,12 @@
 
         PerformanceTracker.getInstanceForSensorId(getSensorId())
                 .incrementPermanentLockoutForUser(getTargetUserId());
-
         onError(error, 0 /* vendorCode */);
     }
+
+    private static int getHelpCode(int acquireInfo, int vendorCode) {
+        return acquireInfo == FACE_ACQUIRED_VENDOR
+                ? vendorCode + FACE_ACQUIRED_VENDOR_BASE
+                : acquireInfo;
+    }
 }
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 5ddddda..8b4da31 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
@@ -16,12 +16,19 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+import static android.hardware.face.FaceManager.getErrorString;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.SensorPrivacyManager;
 import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.face.FaceAuthenticateOptions;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -29,11 +36,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.sensors.AcquisitionClient;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.DetectionConsumer;
@@ -52,15 +59,17 @@
     private final FaceAuthenticateOptions mOptions;
     @Nullable private ICancellationSignal mCancellationSignal;
     @Nullable private SensorPrivacyManager mSensorPrivacyManager;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
 
     FaceDetectClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
             @NonNull IBinder token, long requestId,
             @NonNull ClientMonitorCallbackConverter listener,
             @NonNull FaceAuthenticateOptions options,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             boolean isStrongBiometric) {
         this(context, lazyDaemon, token, requestId, listener, options,
-                logger, biometricContext, isStrongBiometric,
+                logger, biometricContext, authenticationStateListeners, isStrongBiometric,
                 context.getSystemService(SensorPrivacyManager.class));
     }
 
@@ -70,11 +79,13 @@
             @NonNull ClientMonitorCallbackConverter listener,
             @NonNull FaceAuthenticateOptions options,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             boolean isStrongBiometric, SensorPrivacyManager sensorPrivacyManager) {
         super(context, lazyDaemon, token, listener, options.getUserId(),
                 options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
                 false /* shouldVibrate */, logger, biometricContext);
         setRequestId(requestId);
+        mAuthenticationStateListeners = authenticationStateListeners;
         mIsStrongBiometric = isStrongBiometric;
         mSensorPrivacyManager = sensorPrivacyManager;
         mOptions = options;
@@ -88,6 +99,10 @@
 
     @Override
     protected void stopHalOperation() {
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FACE, BiometricRequestConstants.REASON_AUTH_KEYGUARD)
+                .build()
+        );
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
@@ -102,6 +117,10 @@
 
     @Override
     protected void startHalOperation() {
+        mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
+                .Builder(BiometricSourceType.FACE, BiometricRequestConstants.REASON_AUTH_KEYGUARD)
+                .build()
+        );
         if (mSensorPrivacyManager != null
                 && mSensorPrivacyManager
                 .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
@@ -112,38 +131,28 @@
         }
 
         try {
-            if (Flags.deHidl()) {
-                startDetect();
-            } else {
-                mCancellationSignal = doDetectInteraction();
-            }
+            doDetectInteraction();
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception when requesting face detect", e);
             mCallback.onClientFinished(this, false /* success */);
         }
     }
 
-    private ICancellationSignal doDetectInteraction() throws RemoteException {
-        final AidlSession session = getFreshDaemon();
-
-        if (session.hasContextMethods()) {
-            final OperationContextExt opContext = getOperationContext();
-            final ICancellationSignal cancel = session.getSession().detectInteractionWithContext(
-                    opContext.toAidlContext(mOptions));
-            getBiometricContext().subscribe(opContext, ctx -> {
-                try {
-                    session.getSession().onContextChanged(ctx);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to notify context changed", e);
-                }
-            });
-            return cancel;
-        } else {
-            return session.getSession().detectInteraction();
-        }
+    @Override
+    public void onError(@BiometricConstants.Errors int error, int vendorCode) {
+        mAuthenticationStateListeners.onAuthenticationError(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD,
+                        getErrorString(getContext(), error, vendorCode), error).build()
+        );
+        super.onError(error, vendorCode);
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FACE, BiometricRequestConstants.REASON_AUTH_KEYGUARD)
+                .build()
+        );
     }
 
-    private void startDetect() throws RemoteException {
+    private void doDetectInteraction() throws RemoteException {
         final AidlSession session = getFreshDaemon();
 
         if (session.hasContextMethods()) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 781e3f4..3eecc6de 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -16,11 +16,22 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR_BASE;
+import static android.hardware.face.FaceManager.getEnrollHelpMessage;
+import static android.hardware.face.FaceManager.getErrorString;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.biometrics.face.EnrollmentType;
 import android.hardware.biometrics.face.FaceEnrollOptions;
 import android.hardware.biometrics.face.Feature;
@@ -28,7 +39,6 @@
 import android.hardware.common.NativeHandle;
 import android.hardware.face.Face;
 import android.hardware.face.FaceEnrollFrame;
-import android.hardware.face.FaceManager;
 import android.hardware.keymaster.HardwareAuthToken;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -36,12 +46,12 @@
 import android.view.Surface;
 
 import com.android.internal.R;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.HardwareAuthTokenUtils;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricNotificationUtils;
 import com.android.server.biometrics.sensors.BiometricUtils;
@@ -67,12 +77,14 @@
     @NonNull private final int[] mEnrollIgnoreList;
     @NonNull private final int[] mEnrollIgnoreListVendor;
     @NonNull private final int[] mDisabledFeatures;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
     @Nullable private final Surface mPreviewSurface;
     @Nullable private android.os.NativeHandle mOsPreviewHandle;
     @Nullable private NativeHandle mHwPreviewHandle;
     @Nullable private ICancellationSignal mCancellationSignal;
     private final int mMaxTemplatesPerUser;
     private final boolean mDebugConsent;
+    private final @android.hardware.face.FaceEnrollOptions.EnrollReason int mEnrollReason;
 
     private final ClientMonitorCallback mPreviewHandleDeleterCallback =
             new ClientMonitorCallback() {
@@ -94,11 +106,14 @@
             @Nullable Surface previewSurface, int sensorId,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
             int maxTemplatesPerUser, boolean debugConsent,
-            android.hardware.face.FaceEnrollOptions options) {
+            android.hardware.face.FaceEnrollOptions options,
+            @NonNull AuthenticationStateListeners authenticationStateListeners) {
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
                 timeoutSec, sensorId, false /* shouldVibrate */, logger, biometricContext,
                 BiometricFaceConstants.reasonToMetric(options.getEnrollReason()));
         setRequestId(requestId);
+        mAuthenticationStateListeners = authenticationStateListeners;
+        mEnrollReason = options.getEnrollReason();
         mEnrollIgnoreList = getContext().getResources()
                 .getIntArray(R.array.config_face_acquire_enroll_ignorelist);
         mEnrollIgnoreListVendor = getContext().getResources()
@@ -134,7 +149,7 @@
     }
 
     private boolean shouldSendAcquiredMessage(int acquireInfo, int vendorCode) {
-        return acquireInfo == FaceManager.FACE_ACQUIRED_VENDOR
+        return acquireInfo == FACE_ACQUIRED_VENDOR
                 ? !Utils.listContains(mEnrollIgnoreListVendor, vendorCode)
                 : !Utils.listContains(mEnrollIgnoreList, acquireInfo);
     }
@@ -142,6 +157,15 @@
     @Override
     public void onAcquired(int acquireInfo, int vendorCode) {
         final boolean shouldSend = shouldSendAcquiredMessage(acquireInfo, vendorCode);
+        if (shouldSend) {
+            final int helpCode = getHelpCode(acquireInfo, vendorCode);
+            final String helpMessage = getEnrollHelpMessage(getContext(), acquireInfo, vendorCode);
+            mAuthenticationStateListeners.onAuthenticationHelp(
+                    new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                            getRequestReasonFromFaceEnrollReason(mEnrollReason), helpMessage,
+                            helpCode).build()
+            );
+        }
         onAcquiredInternal(acquireInfo, vendorCode, shouldSend);
     }
 
@@ -159,6 +183,14 @@
         final boolean shouldSend = shouldSendAcquiredMessage(acquireInfo, vendorCode);
         if (shouldSend) {
             try {
+                final int helpCode = getHelpCode(acquireInfo, vendorCode);
+                final String helpMessage = getEnrollHelpMessage(getContext(), acquireInfo,
+                        vendorCode);
+                mAuthenticationStateListeners.onAuthenticationHelp(
+                        new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                                getRequestReasonFromFaceEnrollReason(mEnrollReason), helpMessage,
+                                helpCode).build()
+                );
                 getListener().onEnrollmentFrame(frame);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed to send enrollment frame", e);
@@ -169,6 +201,10 @@
 
     @Override
     protected void startHalOperation() {
+        mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
+                .Builder(BiometricSourceType.FACE,
+                getRequestReasonFromFaceEnrollReason(mEnrollReason)).build()
+        );
         obtainSurfaceHandlesIfNeeded();
         try {
             List<Byte> featureList = new ArrayList<Byte>();
@@ -193,11 +229,7 @@
                 features[i] = featureList.get(i);
             }
 
-            if (Flags.deHidl()) {
-                startEnroll(features);
-            } else {
-                mCancellationSignal = doEnroll(features);
-            }
+            doEnroll(features);
         } catch (RemoteException | IllegalArgumentException e) {
             Slog.e(TAG, "Exception when requesting enroll", e);
             onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
@@ -205,43 +237,21 @@
         }
     }
 
-    private ICancellationSignal doEnroll(byte[] features) throws RemoteException {
-        final AidlSession session = getFreshDaemon();
-        final HardwareAuthToken hat =
-                HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken);
-
-        if (session.hasContextMethods()) {
-            final OperationContextExt opContext = getOperationContext();
-            ICancellationSignal cancel;
-            if (session.supportsFaceEnrollOptions()) {
-                FaceEnrollOptions options = new FaceEnrollOptions();
-                options.hardwareAuthToken = hat;
-                options.enrollmentType = EnrollmentType.DEFAULT;
-                options.features = features;
-                options.nativeHandlePreview = null;
-                options.context = opContext.toAidlContext();
-                options.surfacePreview = mPreviewSurface;
-                cancel = session.getSession().enrollWithOptions(options);
-            } else {
-                cancel = session.getSession().enrollWithContext(
-                        hat, EnrollmentType.DEFAULT, features, mHwPreviewHandle,
-                        opContext.toAidlContext());
-            }
-            getBiometricContext().subscribe(opContext, ctx -> {
-                try {
-                    session.getSession().onContextChanged(ctx);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to notify context changed", e);
-                }
-            });
-            return cancel;
-        } else {
-            return session.getSession().enroll(hat, EnrollmentType.DEFAULT, features,
-                    mHwPreviewHandle);
-        }
+    @Override
+    public void onError(@BiometricConstants.Errors int error, int vendorCode) {
+        mAuthenticationStateListeners.onAuthenticationError(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FACE,
+                        getRequestReasonFromFaceEnrollReason(mEnrollReason),
+                        getErrorString(getContext(), error, vendorCode), error).build()
+        );
+        super.onError(error, vendorCode);
+        mAuthenticationStateListeners.onAuthenticationStopped(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        getRequestReasonFromFaceEnrollReason(mEnrollReason)).build()
+        );
     }
 
-    private void startEnroll(byte[] features) throws RemoteException {
+    private void doEnroll(byte[] features) throws RemoteException {
         final AidlSession session = getFreshDaemon();
         final HardwareAuthToken hat =
                 HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken);
@@ -282,9 +292,12 @@
         }
     }
 
-
     @Override
     protected void stopHalOperation() {
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FACE,
+                getRequestReasonFromFaceEnrollReason(mEnrollReason)).build()
+        );
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
@@ -348,4 +361,10 @@
             mPreviewSurface.release();
         }
     }
+
+    private static int getHelpCode(int acquireInfo, int vendorCode) {
+        return acquireInfo == FACE_ACQUIRED_VENDOR
+                ? vendorCode + FACE_ACQUIRED_VENDOR_BASE
+                : acquireInfo;
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 11db183..e71cffe 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -27,11 +27,9 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricFaceConstants;
 import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.IInvalidationCallback;
 import android.hardware.biometrics.ITestSession;
 import android.hardware.biometrics.ITestSessionCallback;
-import android.hardware.biometrics.common.ComponentInfo;
 import android.hardware.biometrics.face.IFace;
 import android.hardware.biometrics.face.SensorProps;
 import android.hardware.face.Face;
@@ -43,7 +41,6 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -56,7 +53,6 @@
 import com.android.server.biometrics.AuthenticationStatsBroadcastReceiver;
 import com.android.server.biometrics.AuthenticationStatsCollector;
 import com.android.server.biometrics.BiometricHandlerProvider;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
@@ -193,11 +189,7 @@
         mAuthenticationStateListeners = authenticationStateListeners;
         mHalInstanceName = halInstanceName;
         mFaceSensors = new SensorList<>(ActivityManager.getService());
-        if (Flags.deHidl()) {
-            mHandler = biometricHandlerProvider.getFaceHandler();
-        } else {
-            mHandler = new Handler(Looper.getMainLooper());
-        }
+        mHandler = biometricHandlerProvider.getFaceHandler();
         mUsageStats = new UsageStats(context);
         mLockoutResetDispatcher = lockoutResetDispatcher;
         mActivityTaskManager = ActivityTaskManager.getInstance();
@@ -223,50 +215,15 @@
     }
 
     private void initSensors(boolean resetLockoutRequiresChallenge, SensorProps[] props) {
-        if (Flags.deHidl()) {
-            if (resetLockoutRequiresChallenge) {
-                Slog.d(getTag(), "Adding HIDL configs");
-                for (SensorProps prop : props) {
-                    addHidlSensors(prop, resetLockoutRequiresChallenge);
-                }
-            } else {
-                Slog.d(getTag(), "Adding AIDL configs");
-                for (SensorProps prop : props) {
-                    addAidlSensors(prop, resetLockoutRequiresChallenge);
-                }
+        if (resetLockoutRequiresChallenge) {
+            Slog.d(getTag(), "Adding HIDL configs");
+            for (SensorProps prop : props) {
+                addHidlSensors(prop, resetLockoutRequiresChallenge);
             }
         } else {
+            Slog.d(getTag(), "Adding AIDL configs");
             for (SensorProps prop : props) {
-                final int sensorId = prop.commonProps.sensorId;
-
-                final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
-                if (prop.commonProps.componentInfo != null) {
-                    for (ComponentInfo info : prop.commonProps.componentInfo) {
-                        componentInfo.add(new ComponentInfoInternal(info.componentId,
-                                info.hardwareVersion, info.firmwareVersion, info.serialNumber,
-                                info.softwareVersion));
-                    }
-                }
-
-                final FaceSensorPropertiesInternal internalProp = new FaceSensorPropertiesInternal(
-                        prop.commonProps.sensorId, prop.commonProps.sensorStrength,
-                        prop.commonProps.maxEnrollmentsPerUser, componentInfo, prop.sensorType,
-                        prop.supportsDetectInteraction, prop.halControlsPreview,
-                        false /* resetLockoutRequiresChallenge */);
-                final Sensor sensor = new Sensor(this,
-                        mContext, mHandler, internalProp,
-                        mBiometricContext);
-                sensor.init(mLockoutResetDispatcher, this);
-                final int userId = sensor.getLazySession().get() == null ? UserHandle.USER_NULL :
-                        sensor.getLazySession().get().getUserId();
-                mFaceSensors.addSensor(sensorId, sensor, userId,
-                        new SynchronousUserSwitchObserver() {
-                            @Override
-                            public void onUserSwitching(int newUserId) {
-                                scheduleInternalCleanup(sensorId, newUserId, null /* callback */);
-                            }
-                        });
-                Slog.d(getTag(), "Added: " + internalProp);
+                addAidlSensors(prop, resetLockoutRequiresChallenge);
             }
         }
     }
@@ -477,12 +434,7 @@
 
     @Override
     public int getLockoutModeForUser(int sensorId, int userId) {
-        if (Flags.deHidl()) {
-            return mFaceSensors.get(sensorId).getLockoutModeForUser(userId);
-        } else {
-            return mBiometricContext.getAuthSessionCoordinator().getLockoutStateFor(userId,
-                    Utils.getCurrentStrength(sensorId));
-        }
+        return mFaceSensors.get(sensorId).getLockoutModeForUser(userId);
     }
 
     @Override
@@ -492,11 +444,7 @@
 
     @Override
     public boolean isHardwareDetected(int sensorId) {
-        if (Flags.deHidl()) {
-            return mFaceSensors.get(sensorId).isHardwareDetected(mHalInstanceName);
-        } else {
-            return hasHalInstance();
-        }
+        return mFaceSensors.get(sensorId).isHardwareDetected(mHalInstanceName);
     }
 
     @Override
@@ -548,24 +496,9 @@
                     createLogger(BiometricsProtoEnums.ACTION_ENROLL,
                             BiometricsProtoEnums.CLIENT_UNKNOWN,
                             mAuthenticationStatsCollector),
-                    mBiometricContext, maxTemplatesPerUser, debugConsent, options);
-            if (Flags.deHidl()) {
-                scheduleForSensor(sensorId, client, mBiometricStateCallback);
-            } else {
-                scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(
-                        mBiometricStateCallback, new ClientMonitorCallback() {
-                            @Override
-                            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                                    boolean success) {
-                                ClientMonitorCallback.super.onClientFinished(clientMonitor,
-                                        success);
-                                if (success) {
-                                    scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
-                                    scheduleInvalidationRequest(sensorId, userId);
-                                }
-                            }
-                        }));
-            }
+                    mBiometricContext, maxTemplatesPerUser, debugConsent, options,
+                    mAuthenticationStateListeners);
+            scheduleForSensor(sensorId, client, mBiometricStateCallback);
         });
         return id;
     }
@@ -590,7 +523,7 @@
                     token, id, callback, options,
                     createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
                             mAuthenticationStatsCollector),
-                    mBiometricContext, isStrongBiometric);
+                    mBiometricContext, mAuthenticationStateListeners, isStrongBiometric);
             scheduleForSensor(sensorId, client, mBiometricStateCallback);
         });
 
@@ -614,12 +547,8 @@
             final int sensorId = options.getSensorId();
             final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
             mFaceSensors.get(sensorId).scheduleFaceUpdateActiveUserClient(userId);
-            final LockoutTracker lockoutTracker;
-            if (Flags.deHidl()) {
-                lockoutTracker = mFaceSensors.get(sensorId).getLockoutTracker(true /* forAuth */);
-            } else {
-                lockoutTracker = null;
-            }
+            final LockoutTracker lockoutTracker = mFaceSensors.get(sensorId).getLockoutTracker(
+                    true /* forAuth */);
             final FaceAuthenticationClient client = new FaceAuthenticationClient(
                     mContext, mFaceSensors.get(sensorId).getLazySession(), token, requestId,
                     callback, operationId, restricted, options, cookie,
@@ -634,29 +563,18 @@
                 @Override
                 public void onClientStarted(
                          BaseClientMonitor clientMonitor) {
-                    if (Flags.deHidl()) {
-                        mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
-                                mAuthSessionCoordinator.authStartedFor(userId, sensorId,
-                                        requestId));
-                    } else {
-                        mAuthSessionCoordinator.authStartedFor(userId, sensorId, requestId);
-                    }
+                    mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
+                            mAuthSessionCoordinator.authStartedFor(userId, sensorId, requestId));
                 }
 
                 @Override
                 public void onClientFinished(
                         BaseClientMonitor clientMonitor,
                         boolean success) {
-                    if (Flags.deHidl()) {
-                        mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
-                                mAuthSessionCoordinator.authEndedFor(userId,
-                                        Utils.getCurrentStrength(sensorId), sensorId, requestId,
-                                        client.wasAuthSuccessful()));
-                    } else {
-                        mAuthSessionCoordinator.authEndedFor(userId,
-                                Utils.getCurrentStrength(sensorId),
-                                sensorId, requestId, client.wasAuthSuccessful());
-                    }
+                    mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
+                            mAuthSessionCoordinator.authEndedFor(userId,
+                                    Utils.getCurrentStrength(sensorId), sensorId, requestId,
+                                    client.wasAuthSuccessful()));
                 }
             });
         });
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 635e79a..6b99493 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -42,7 +42,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.SensorServiceStateProto;
 import com.android.server.biometrics.SensorStateProto;
 import com.android.server.biometrics.UserStateProto;
@@ -57,7 +56,6 @@
 import com.android.server.biometrics.sensors.LockoutTracker;
 import com.android.server.biometrics.sensors.StartUserClient;
 import com.android.server.biometrics.sensors.StopUserClient;
-import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
 import com.android.server.biometrics.sensors.UserSwitchProvider;
 import com.android.server.biometrics.sensors.face.FaceUtils;
 
@@ -89,7 +87,6 @@
     @Nullable AidlSession mCurrentSession;
     @NonNull BiometricContext mBiometricContext;
 
-
     Sensor(@NonNull FaceProvider provider, @NonNull Context context,
             @NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties,
             @NonNull BiometricContext biometricContext) {
@@ -116,11 +113,7 @@
      */
     public void init(@NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull FaceProvider provider) {
-        if (Flags.deHidl()) {
-            setScheduler(getBiometricSchedulerForInit(lockoutResetDispatcher, provider));
-        } else {
-            setScheduler(getUserAwareBiometricSchedulerForInit(lockoutResetDispatcher, provider));
-        }
+        setScheduler(getBiometricSchedulerForInit(lockoutResetDispatcher, provider));
         mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
         mLockoutTracker = new LockoutCache();
     }
@@ -149,8 +142,7 @@
                         final AidlResponseHandler resultController = new AidlResponseHandler(
                                 mContext, mScheduler, sensorId, newUserId,
                                 mLockoutTracker, lockoutResetDispatcher,
-                                mBiometricContext.getAuthSessionCoordinator(), () -> {
-                        },
+                                mBiometricContext.getAuthSessionCoordinator(),
                                 new AidlResponseHandler.AidlResponseHandlerCallback() {
                                     @Override
                                     public void onEnrollSuccess() {
@@ -173,40 +165,6 @@
                 });
     }
 
-    private UserAwareBiometricScheduler<IFace, ISession> getUserAwareBiometricSchedulerForInit(
-            LockoutResetDispatcher lockoutResetDispatcher,
-            FaceProvider provider) {
-        return new UserAwareBiometricScheduler<>(TAG,
-                BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityDispatcher */,
-                () -> mCurrentSession != null ? mCurrentSession.getUserId() : UserHandle.USER_NULL,
-                new UserAwareBiometricScheduler.UserSwitchCallback() {
-                    @NonNull
-                    @Override
-                    public StopUserClient<ISession> getStopUserClient(int userId) {
-                        return new FaceStopUserClient(mContext,
-                                () -> mLazySession.get().getSession(), mToken, userId,
-                                mSensorProperties.sensorId, BiometricLogger.ofUnknown(mContext),
-                                mBiometricContext, () -> mCurrentSession = null);
-                    }
-
-                    @NonNull
-                    @Override
-                    public StartUserClient<IFace, ISession> getStartUserClient(int newUserId) {
-                        final int sensorId = mSensorProperties.sensorId;
-                        final AidlResponseHandler resultController = new AidlResponseHandler(
-                                mContext, mScheduler, sensorId, newUserId,
-                                mLockoutTracker, lockoutResetDispatcher,
-                                mBiometricContext.getAuthSessionCoordinator(), () -> {
-                                    Slog.e(TAG, "Face sensor hardware unavailable.");
-                                    mCurrentSession = null;
-                                });
-
-                        return Sensor.this.getStartUserClient(resultController, sensorId,
-                                newUserId, provider);
-                    }
-                });
-    }
-
     private FaceStartUserClient getStartUserClient(@NonNull AidlResponseHandler resultController,
             int sensorId, int newUserId, @NonNull FaceProvider provider) {
         final StartUserClient.UserStartedCallback<ISession> userStartedCallback =
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
deleted file mode 100644
index 0e2367a..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.ITestSession;
-import android.hardware.biometrics.ITestSessionCallback;
-import android.hardware.face.Face;
-import android.hardware.face.FaceAuthenticationFrame;
-import android.hardware.face.FaceEnrollFrame;
-import android.hardware.face.FaceEnrollOptions;
-import android.hardware.face.IFaceServiceReceiver;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.face.FaceUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-public class BiometricTestSessionImpl extends ITestSession.Stub {
-    private static final String TAG = "BiometricTestSessionImpl";
-
-    @NonNull private final Context mContext;
-    private final int mSensorId;
-    @NonNull private final ITestSessionCallback mCallback;
-    @NonNull private final Face10 mFace10;
-    @NonNull private final Face10.HalResultController mHalResultController;
-    @NonNull private final Set<Integer> mEnrollmentIds;
-    @NonNull private final Random mRandom;
-
-
-    private final IFaceServiceReceiver mReceiver = new IFaceServiceReceiver.Stub() {
-        @Override
-        public void onEnrollResult(Face face, int remaining) {
-
-        }
-
-        @Override
-        public void onAcquired(int acquiredInfo, int vendorCode) {
-
-        }
-
-        @Override
-        public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) {
-
-        }
-
-        @Override
-        public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
-
-        }
-
-        @Override
-        public void onAuthenticationFailed() {
-
-        }
-
-        @Override
-        public void onError(int error, int vendorCode) {
-
-        }
-
-        @Override
-        public void onRemoved(Face face, int remaining) {
-
-        }
-
-        @Override
-        public void onFeatureSet(boolean success, int feature) {
-
-        }
-
-        @Override
-        public void onFeatureGet(boolean success, int[] features, boolean[] featureState) {
-
-        }
-
-        @Override
-        public void onChallengeGenerated(int sensorId, int userId, long challenge) {
-
-        }
-
-        @Override
-        public void onAuthenticationFrame(FaceAuthenticationFrame frame) {
-
-        }
-
-        @Override
-        public void onEnrollmentFrame(FaceEnrollFrame frame) {
-
-        }
-    };
-
-    BiometricTestSessionImpl(@NonNull Context context, int sensorId,
-            @NonNull ITestSessionCallback callback,
-            @NonNull Face10 face10,
-            @NonNull Face10.HalResultController halResultController) {
-        mContext = context;
-        mSensorId = sensorId;
-        mCallback = callback;
-        mFace10 = face10;
-        mHalResultController = halResultController;
-        mEnrollmentIds = new HashSet<>();
-        mRandom = new Random();
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void setTestHalEnabled(boolean enabled) {
-
-        super.setTestHalEnabled_enforcePermission();
-
-        mFace10.setTestHalEnabled(enabled);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void startEnroll(int userId) {
-
-        super.startEnroll_enforcePermission();
-
-        mFace10.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
-                mContext.getOpPackageName(), new int[0] /* disabledFeatures */,
-                null /* previewSurface */, false /* debugConsent */,
-                (new FaceEnrollOptions.Builder()).build());
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void finishEnroll(int userId) {
-
-        super.finishEnroll_enforcePermission();
-
-        int nextRandomId = mRandom.nextInt();
-        while (mEnrollmentIds.contains(nextRandomId)) {
-            nextRandomId = mRandom.nextInt();
-        }
-
-        mEnrollmentIds.add(nextRandomId);
-        mHalResultController.onEnrollResult(0 /* deviceId */,
-                nextRandomId /* faceId */, userId, 0);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void acceptAuthentication(int userId) {
-
-        // Fake authentication with any of the existing fingers
-        super.acceptAuthentication_enforcePermission();
-
-        List<Face> faces = FaceUtils.getLegacyInstance(mSensorId)
-                .getBiometricsForUser(mContext, userId);
-        if (faces.isEmpty()) {
-            Slog.w(TAG, "No faces, returning");
-            return;
-        }
-        final int fid = faces.get(0).getBiometricId();
-        final ArrayList<Byte> hat = new ArrayList<>(Collections.nCopies(69, (byte) 0));
-        mHalResultController.onAuthenticated(0 /* deviceId */, fid, userId, hat);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void rejectAuthentication(int userId) {
-
-        super.rejectAuthentication_enforcePermission();
-
-        mHalResultController.onAuthenticated(0 /* deviceId */, 0 /* faceId */, userId, null);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void notifyAcquired(int userId, int acquireInfo) {
-
-        super.notifyAcquired_enforcePermission();
-
-        mHalResultController.onAcquired(0 /* deviceId */, userId, acquireInfo, 0 /* vendorCode */);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void notifyError(int userId, int errorCode) {
-
-        super.notifyError_enforcePermission();
-
-        mHalResultController.onError(0 /* deviceId */, userId, errorCode, 0 /* vendorCode */);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void cleanupInternalState(int userId) {
-
-        super.cleanupInternalState_enforcePermission();
-
-        mFace10.scheduleInternalCleanup(mSensorId, userId, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                try {
-                    mCallback.onCleanupStarted(clientMonitor.getTargetUserId());
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                try {
-                    mCallback.onCleanupFinished(clientMonitor.getTargetUserId());
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-        });
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
deleted file mode 100644
index 306ddfa..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ /dev/null
@@ -1,1342 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.SynchronousUserSwitchObserver;
-import android.app.UserSwitchObserver;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.biometrics.ITestSession;
-import android.hardware.biometrics.ITestSessionCallback;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
-import android.hardware.face.Face;
-import android.hardware.face.FaceAuthenticateOptions;
-import android.hardware.face.FaceEnrollOptions;
-import android.hardware.face.FaceSensorPropertiesInternal;
-import android.hardware.face.IFaceServiceReceiver;
-import android.os.Binder;
-import android.os.Build;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.IHwBinder;
-import android.os.Looper;
-import android.os.NativeHandle;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-import android.view.Surface;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.biometrics.AuthenticationStatsBroadcastReceiver;
-import com.android.server.biometrics.AuthenticationStatsCollector;
-import com.android.server.biometrics.Flags;
-import com.android.server.biometrics.SensorServiceStateProto;
-import com.android.server.biometrics.SensorStateProto;
-import com.android.server.biometrics.UserStateProto;
-import com.android.server.biometrics.Utils;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.AcquisitionClient;
-import com.android.server.biometrics.sensors.AuthSessionCoordinator;
-import com.android.server.biometrics.sensors.AuthenticationConsumer;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
-import com.android.server.biometrics.sensors.EnumerateConsumer;
-import com.android.server.biometrics.sensors.ErrorConsumer;
-import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-import com.android.server.biometrics.sensors.LockoutTracker;
-import com.android.server.biometrics.sensors.PerformanceTracker;
-import com.android.server.biometrics.sensors.RemovalConsumer;
-import com.android.server.biometrics.sensors.face.FaceUtils;
-import com.android.server.biometrics.sensors.face.LockoutHalImpl;
-import com.android.server.biometrics.sensors.face.ServiceProvider;
-import com.android.server.biometrics.sensors.face.UsageStats;
-import com.android.server.biometrics.sensors.face.aidl.AidlResponseHandler;
-import com.android.server.biometrics.sensors.face.aidl.AidlSession;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.time.Clock;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Supplier;
-
-/**
- * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or its extended
- * minor versions.
- */
-public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
-
-    private static final String TAG = "Face10";
-
-    private static final int ENROLL_TIMEOUT_SEC = 75;
-    private static final int GENERATE_CHALLENGE_REUSE_INTERVAL_MILLIS = 60 * 1000;
-    private static final int GENERATE_CHALLENGE_COUNTER_TTL_MILLIS =
-            FaceGenerateChallengeClient.CHALLENGE_TIMEOUT_SEC * 1000;
-    @VisibleForTesting
-    public static Clock sSystemClock = Clock.systemUTC();
-
-    private boolean mTestHalEnabled;
-
-    @NonNull private final FaceSensorPropertiesInternal mSensorProperties;
-    @NonNull private final BiometricStateCallback mBiometricStateCallback;
-    @NonNull
-    private final AuthenticationStateListeners mAuthenticationStateListeners;
-    @NonNull private final Context mContext;
-    @NonNull private final BiometricScheduler<IBiometricsFace, AidlSession> mScheduler;
-    @NonNull private final Handler mHandler;
-    @NonNull private final Supplier<IBiometricsFace> mLazyDaemon;
-    @NonNull private final LockoutHalImpl mLockoutTracker;
-    @NonNull private final UsageStats mUsageStats;
-    @NonNull private final Map<Integer, Long> mAuthenticatorIds;
-    @Nullable private IBiometricsFace mDaemon;
-    @NonNull private final HalResultController mHalResultController;
-    @NonNull private final BiometricContext mBiometricContext;
-    @Nullable private AuthenticationStatsCollector mAuthenticationStatsCollector;
-    // for requests that do not use biometric prompt
-    @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0);
-    private int mCurrentUserId = UserHandle.USER_NULL;
-    private final int mSensorId;
-    private final List<Long> mGeneratedChallengeCount = new ArrayList<>();
-    private final LockoutResetDispatcher mLockoutResetDispatcher;
-    private FaceGenerateChallengeClient mGeneratedChallengeCache = null;
-    private AidlSession mSession;
-
-    private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
-        @Override
-        public void onUserSwitching(int newUserId) {
-            scheduleInternalCleanup(newUserId, null /* callback */);
-            scheduleGetFeature(mSensorId, new Binder(), newUserId,
-                    BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
-                    null, mContext.getOpPackageName());
-        }
-    };
-
-    public static class HalResultController extends IBiometricsFaceClientCallback.Stub {
-        /**
-         * Interface to sends results to the HalResultController's owner.
-         */
-        public interface Callback {
-            /**
-             * Invoked when the HAL sends ERROR_HW_UNAVAILABLE.
-             */
-            void onHardwareUnavailable();
-        }
-
-        private final int mSensorId;
-        @NonNull private final Context mContext;
-        @NonNull private final Handler mHandler;
-        @NonNull private final BiometricScheduler<IBiometricsFace, AidlSession> mScheduler;
-        @Nullable private Callback mCallback;
-        @NonNull private final LockoutHalImpl mLockoutTracker;
-        @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
-
-
-        HalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler,
-                @NonNull BiometricScheduler<IBiometricsFace, AidlSession> scheduler,
-                @NonNull LockoutHalImpl lockoutTracker,
-                @NonNull LockoutResetDispatcher lockoutResetDispatcher) {
-            mSensorId = sensorId;
-            mContext = context;
-            mHandler = handler;
-            mScheduler = scheduler;
-            mLockoutTracker = lockoutTracker;
-            mLockoutResetDispatcher = lockoutResetDispatcher;
-        }
-
-        public void setCallback(@Nullable Callback callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void onEnrollResult(long deviceId, int faceId, int userId, int remaining) {
-            mHandler.post(() -> {
-                final CharSequence name = FaceUtils.getLegacyInstance(mSensorId)
-                        .getUniqueName(mContext, userId);
-                final Face face = new Face(name, faceId, deviceId);
-
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof FaceEnrollClient)) {
-                    Slog.e(TAG, "onEnrollResult for non-enroll client: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final FaceEnrollClient enrollClient = (FaceEnrollClient) client;
-                enrollClient.onEnrollResult(face, remaining);
-            });
-        }
-
-        @Override
-        public void onAuthenticated(long deviceId, int faceId, int userId,
-                ArrayList<Byte> token) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof AuthenticationConsumer)) {
-                    Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final AuthenticationConsumer authenticationConsumer =
-                        (AuthenticationConsumer) client;
-                final boolean authenticated = faceId != 0;
-                final Face face = new Face("", faceId, deviceId);
-                authenticationConsumer.onAuthenticated(face, authenticated, token);
-            });
-        }
-
-        @Override
-        public void onAcquired(long deviceId, int userId, int acquiredInfo,
-                int vendorCode) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof AcquisitionClient)) {
-                    Slog.e(TAG, "onAcquired for non-acquire client: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final AcquisitionClient<?> acquisitionClient =
-                        (AcquisitionClient<?>) client;
-                acquisitionClient.onAcquired(acquiredInfo, vendorCode);
-            });
-        }
-
-        @Override
-        public void onError(long deviceId, int userId, int error, int vendorCode) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                Slog.d(TAG, "handleError"
-                        + ", client: " + (client != null ? client.getOwnerString() : null)
-                        + ", error: " + error
-                        + ", vendorCode: " + vendorCode);
-                if (!(client instanceof ErrorConsumer)) {
-                    Slog.e(TAG, "onError for non-error consumer: " + Utils.getClientName(
-                            client));
-                    return;
-                }
-
-                final ErrorConsumer errorConsumer = (ErrorConsumer) client;
-                errorConsumer.onError(error, vendorCode);
-
-                if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
-                    Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE");
-                    if (mCallback != null) {
-                        mCallback.onHardwareUnavailable();
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onRemoved(long deviceId, ArrayList<Integer> removed, int userId) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof RemovalConsumer)) {
-                    Slog.e(TAG, "onRemoved for non-removal consumer: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final RemovalConsumer removalConsumer = (RemovalConsumer) client;
-
-                if (!removed.isEmpty()) {
-                    // Convert to old fingerprint-like behavior, where remove() receives
-                    // one removal at a time. This way, remove can share some more common code.
-                    for (int i = 0; i < removed.size(); i++) {
-                        final int id = removed.get(i);
-                        final Face face = new Face("", id, deviceId);
-                        final int remaining = removed.size() - i - 1;
-                        Slog.d(TAG, "Removed, faceId: " + id + ", remaining: " + remaining);
-                        removalConsumer.onRemoved(face, remaining);
-                    }
-                } else {
-                    removalConsumer.onRemoved(null, 0 /* remaining */);
-                }
-
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.FACE_UNLOCK_RE_ENROLL, 0, UserHandle.USER_CURRENT);
-            });
-        }
-
-        @Override
-        public void onEnumerate(long deviceId, ArrayList<Integer> faceIds, int userId) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof EnumerateConsumer)) {
-                    Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client;
-
-                if (!faceIds.isEmpty()) {
-                    // Convert to old fingerprint-like behavior, where enumerate() receives one
-                    // template at a time. This way, enumerate can share some more common code.
-                    for (int i = 0; i < faceIds.size(); i++) {
-                        final Face face = new Face("", faceIds.get(i), deviceId);
-                        enumerateConsumer.onEnumerationResult(face, faceIds.size() - i - 1);
-                    }
-                } else {
-                    // For face, the HIDL contract is to receive an empty list when there are no
-                    // templates enrolled. Send a null identifier since we don't consume them
-                    // anywhere, and send remaining == 0 so this code can be shared with [email protected]
-                    enumerateConsumer.onEnumerationResult(null /* identifier */, 0);
-                }
-            });
-        }
-
-        @Override
-        public void onLockoutChanged(long duration) {
-            mHandler.post(() -> {
-                Slog.d(TAG, "onLockoutChanged: " + duration);
-                final @LockoutTracker.LockoutMode int lockoutMode;
-                if (duration == 0) {
-                    lockoutMode = LockoutTracker.LOCKOUT_NONE;
-                } else if (duration == -1 || duration == Long.MAX_VALUE) {
-                    lockoutMode = LockoutTracker.LOCKOUT_PERMANENT;
-                } else {
-                    lockoutMode = LockoutTracker.LOCKOUT_TIMED;
-                }
-
-                mLockoutTracker.setCurrentUserLockoutMode(lockoutMode);
-
-                if (duration == 0) {
-                    mLockoutResetDispatcher.notifyLockoutResetCallbacks(mSensorId);
-                }
-            });
-        }
-    }
-
-    @VisibleForTesting
-    Face10(@NonNull Context context,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @NonNull FaceSensorPropertiesInternal sensorProps,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull Handler handler,
-            @NonNull BiometricScheduler<IBiometricsFace, AidlSession> scheduler,
-            @NonNull BiometricContext biometricContext) {
-        mSensorProperties = sensorProps;
-        mContext = context;
-        mBiometricStateCallback = biometricStateCallback;
-        mAuthenticationStateListeners = authenticationStateListeners;
-        mSensorId = sensorProps.sensorId;
-        mScheduler = scheduler;
-        mHandler = handler;
-        mBiometricContext = biometricContext;
-        mUsageStats = new UsageStats(context);
-        mAuthenticatorIds = new HashMap<>();
-        mLazyDaemon = Face10.this::getDaemon;
-        mLockoutTracker = new LockoutHalImpl();
-        mHalResultController = new HalResultController(sensorProps.sensorId, context, mHandler,
-                mScheduler, mLockoutTracker, lockoutResetDispatcher);
-        mLockoutResetDispatcher = lockoutResetDispatcher;
-        mHalResultController.setCallback(() -> {
-            mDaemon = null;
-            mCurrentUserId = UserHandle.USER_NULL;
-        });
-
-        AuthenticationStatsBroadcastReceiver mBroadcastReceiver =
-                new AuthenticationStatsBroadcastReceiver(
-                        mContext,
-                        BiometricsProtoEnums.MODALITY_FACE,
-                        (AuthenticationStatsCollector collector) -> {
-                            Slog.d(TAG, "Initializing AuthenticationStatsCollector");
-                            mAuthenticationStatsCollector = collector;
-                        });
-
-        try {
-            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to register user switch observer");
-        }
-    }
-
-    public static Face10 newInstance(@NonNull Context context,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @NonNull FaceSensorPropertiesInternal sensorProps,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher) {
-        final Handler handler = new Handler(Looper.getMainLooper());
-        return new Face10(context, biometricStateCallback, authenticationStateListeners,
-                sensorProps, lockoutResetDispatcher, handler, new BiometricScheduler<>(
-                        BiometricScheduler.SENSOR_TYPE_FACE,
-                        null /* gestureAvailabilityTracker */),
-                BiometricContext.getInstance(context));
-    }
-
-    @Override
-    public void serviceDied(long cookie) {
-        Slog.e(TAG, "HAL died");
-        mHandler.post(() -> {
-            PerformanceTracker.getInstanceForSensorId(mSensorId)
-                    .incrementHALDeathCount();
-            mDaemon = null;
-            mCurrentUserId = UserHandle.USER_NULL;
-
-            final BaseClientMonitor client = mScheduler.getCurrentClient();
-            if (client instanceof ErrorConsumer) {
-                Slog.e(TAG, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
-                final ErrorConsumer errorConsumer = (ErrorConsumer) client;
-                errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
-                        0 /* vendorCode */);
-
-                FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
-                        BiometricsProtoEnums.MODALITY_FACE,
-                        BiometricsProtoEnums.ISSUE_HAL_DEATH,
-                        -1 /* sensorId */);
-            }
-
-            mScheduler.recordCrashState();
-            mScheduler.reset();
-        });
-    }
-
-    public int getCurrentUserId() {
-        return mCurrentUserId;
-    }
-
-    synchronized AidlSession getSession() {
-        if (mDaemon != null && mSession != null) {
-            return mSession;
-        } else {
-            return mSession = new AidlSession(mContext, this::getDaemon, mCurrentUserId,
-                    new AidlResponseHandler(mContext, mScheduler, mSensorId,
-                            mCurrentUserId, mLockoutTracker, mLockoutResetDispatcher,
-                            new AuthSessionCoordinator(), () -> {
-                        mDaemon = null;
-                        mCurrentUserId = UserHandle.USER_NULL;
-                    }));
-        }
-    }
-
-    private synchronized IBiometricsFace getDaemon() {
-        if (mTestHalEnabled) {
-            final TestHal testHal = new TestHal(mContext, mSensorId);
-            testHal.setCallback(mHalResultController);
-            return testHal;
-        }
-
-        if (mDaemon != null) {
-            return mDaemon;
-        }
-
-        Slog.d(TAG, "Daemon was null, reconnecting, current operation: "
-                + mScheduler.getCurrentClient());
-
-        try {
-            mDaemon = IBiometricsFace.getService();
-        } catch (java.util.NoSuchElementException e) {
-            // Service doesn't exist or cannot be opened.
-            Slog.w(TAG, "NoSuchElementException", e);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to get face HAL", e);
-        }
-
-        if (mDaemon == null) {
-            Slog.w(TAG, "Face HAL not available");
-            return null;
-        }
-
-        mDaemon.asBinder().linkToDeath(this, 0 /* flags */);
-
-        // HAL ID for these HIDL versions are only used to determine if callbacks have been
-        // successfully set.
-        long halId = 0;
-        try {
-            halId = mDaemon.setCallback(mHalResultController).value;
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to set callback for face HAL", e);
-            mDaemon = null;
-        }
-
-        Slog.d(TAG, "Face HAL ready, HAL ID: " + halId);
-        if (halId != 0) {
-            scheduleLoadAuthenticatorIds();
-            scheduleInternalCleanup(ActivityManager.getCurrentUser(), null /* callback */);
-            scheduleGetFeature(mSensorId, new Binder(),
-                    ActivityManager.getCurrentUser(),
-                    BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION, null,
-                    mContext.getOpPackageName());
-        } else {
-            Slog.e(TAG, "Unable to set callback");
-            mDaemon = null;
-        }
-
-        return mDaemon;
-    }
-
-    @Override
-    public boolean containsSensor(int sensorId) {
-        return mSensorId == sensorId;
-    }
-
-    @Override
-    @NonNull
-    public List<FaceSensorPropertiesInternal> getSensorProperties() {
-        final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
-        properties.add(mSensorProperties);
-        return properties;
-    }
-
-    @NonNull
-    @Override
-    public FaceSensorPropertiesInternal getSensorProperties(int sensorId) {
-        return mSensorProperties;
-    }
-
-    @Override
-    @NonNull
-    public List<Face> getEnrolledFaces(int sensorId, int userId) {
-        return FaceUtils.getLegacyInstance(mSensorId).getBiometricsForUser(mContext, userId);
-    }
-
-    @Override
-    public boolean hasEnrollments(int sensorId, int userId) {
-        return !getEnrolledFaces(sensorId, userId).isEmpty();
-    }
-
-    @Override
-    @LockoutTracker.LockoutMode
-    public int getLockoutModeForUser(int sensorId, int userId) {
-        return mLockoutTracker.getLockoutModeForUser(userId);
-    }
-
-    @Override
-    public long getAuthenticatorId(int sensorId, int userId) {
-        return mAuthenticatorIds.getOrDefault(userId, 0L);
-    }
-
-    @Override
-    public boolean isHardwareDetected(int sensorId) {
-        return getDaemon() != null;
-    }
-
-    private boolean isGeneratedChallengeCacheValid() {
-        return mGeneratedChallengeCache != null
-                && sSystemClock.millis() - mGeneratedChallengeCache.getCreatedAt()
-                < GENERATE_CHALLENGE_REUSE_INTERVAL_MILLIS;
-    }
-
-    private void incrementChallengeCount() {
-        mGeneratedChallengeCount.add(0, sSystemClock.millis());
-    }
-
-    private int decrementChallengeCount() {
-        final long now = sSystemClock.millis();
-        // ignore values that are old in case generate/revoke calls are not matched
-        // this doesn't ensure revoke if calls are mismatched but it keeps the list from growing
-        mGeneratedChallengeCount.removeIf(x -> now - x > GENERATE_CHALLENGE_COUNTER_TTL_MILLIS);
-        if (!mGeneratedChallengeCount.isEmpty()) {
-            mGeneratedChallengeCount.remove(0);
-        }
-        return mGeneratedChallengeCount.size();
-    }
-
-    /**
-     * {@link IBiometricsFace} only supports a single in-flight challenge but there are cases where
-     * two callers both need challenges (e.g. resetLockout right before enrollment).
-     */
-    @Override
-    public void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            if (Flags.deHidl()) {
-                scheduleGenerateChallengeAidl(userId, token, receiver, opPackageName);
-            } else {
-                scheduleGenerateChallengeHidl(userId, token, receiver, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleGenerateChallengeAidl(int userId, @NonNull IBinder token,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceGenerateChallengeClient client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceGenerateChallengeClient(
-                        mContext, this::getSession, token,
-                        new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
-                        mSensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                        mBiometricContext);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                if (client != clientMonitor) {
-                    Slog.e(TAG,
-                            "scheduleGenerateChallenge onClientStarted, mismatched client."
-                                    + " Expecting: " + client + ", received: "
-                                    + clientMonitor);
-                }
-            }
-        });
-    }
-
-    private void scheduleGenerateChallengeHidl(int userId, @NonNull IBinder token,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        incrementChallengeCount();
-        if (isGeneratedChallengeCacheValid()) {
-            Slog.d(TAG, "Current challenge is cached and will be reused");
-            mGeneratedChallengeCache.reuseResult(receiver);
-            return;
-        }
-
-        final FaceGenerateChallengeClient client = new FaceGenerateChallengeClient(mContext,
-                mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
-                opPackageName, mSensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, sSystemClock.millis());
-        mGeneratedChallengeCache = client;
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                if (client != clientMonitor) {
-                    Slog.e(TAG,
-                            "scheduleGenerateChallenge onClientStarted, mismatched client."
-                                    + " Expecting: " + client + ", received: "
-                                    + clientMonitor);
-                }
-            }
-        });
-    }
-
-    @Override
-    public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
-            @NonNull String opPackageName, long challenge) {
-        mHandler.post(() -> {
-            if (Flags.deHidl()) {
-                scheduleRevokeChallengeAidl(userId, token, opPackageName);
-            } else {
-                scheduleRevokeChallengeHidl(userId, token, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleRevokeChallengeAidl(int userId, @NonNull IBinder token,
-            @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceRevokeChallengeClient
-                client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceRevokeChallengeClient(
-                        mContext, this::getSession, token, userId, opPackageName, mSensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector), mBiometricContext, 0L);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                if (client != clientMonitor) {
-                    Slog.e(TAG,
-                            "scheduleRevokeChallenge, mismatched client." + "Expecting: "
-                                    + client + ", received: " + clientMonitor);
-                }
-            }
-        });
-    }
-
-    private void scheduleRevokeChallengeHidl(int userId, @NonNull IBinder token,
-            @NonNull String opPackageName) {
-        final boolean shouldRevoke = decrementChallengeCount() == 0;
-        if (!shouldRevoke) {
-            Slog.w(TAG, "scheduleRevokeChallenge skipped - challenge still in use: "
-                    + mGeneratedChallengeCount);
-            return;
-        }
-
-        Slog.d(TAG, "scheduleRevokeChallenge executing - no active clients");
-        mGeneratedChallengeCache = null;
-        final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
-                mLazyDaemon, token, userId, opPackageName, mSensorId,
-                createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                if (client != clientMonitor) {
-                    Slog.e(TAG,
-                            "scheduleRevokeChallenge, mismatched client." + "Expecting: "
-                                    + client + ", received: " + clientMonitor);
-                }
-            }
-        });
-    }
-
-    @Override
-    public long scheduleEnroll(int sensorId, @NonNull IBinder token,
-            @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
-            @NonNull String opPackageName, @NonNull int[] disabledFeatures,
-            @Nullable Surface previewSurface, boolean debugConsent,
-            @NonNull FaceEnrollOptions options) {
-        final long id = mRequestCounter.incrementAndGet();
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-            if (Flags.deHidl()) {
-                scheduleEnrollAidl(token, hardwareAuthToken, userId, receiver,
-                        opPackageName, disabledFeatures, previewSurface, id, options);
-            } else {
-                scheduleEnrollHidl(token, hardwareAuthToken, userId, receiver,
-                        opPackageName, disabledFeatures, previewSurface, id, options);
-            }
-        });
-        return id;
-    }
-
-    private void scheduleEnrollAidl(@NonNull IBinder token,
-            @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
-            @NonNull String opPackageName, @NonNull int[] disabledFeatures,
-            @Nullable Surface previewSurface, long id,
-            @NonNull FaceEnrollOptions options) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceEnrollClient client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceEnrollClient(
-                        mContext, this::getSession, token,
-                        new ClientMonitorCallbackConverter(receiver), userId,
-                        hardwareAuthToken, opPackageName, id,
-                        FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
-                        ENROLL_TIMEOUT_SEC, previewSurface, mSensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_ENROLL,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector), mBiometricContext,
-                        mContext.getResources().getInteger(
-                                com.android.internal.R.integer.config_faceMaxTemplatesPerUser),
-                        false, options);
-
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                mBiometricStateCallback.onClientStarted(clientMonitor);
-            }
-
-            @Override
-            public void onBiometricAction(int action) {
-                mBiometricStateCallback.onBiometricAction(action);
-            }
-
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                mBiometricStateCallback.onClientFinished(clientMonitor, success);
-                if (success) {
-                    // Update authenticatorIds
-                    scheduleUpdateActiveUserWithoutHandler(client.getTargetUserId());
-                }
-            }
-        });
-    }
-
-    private void scheduleEnrollHidl(@NonNull IBinder token,
-            @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
-            @NonNull String opPackageName, @NonNull int[] disabledFeatures,
-            @Nullable Surface previewSurface, long id, FaceEnrollOptions options) {
-            final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
-                    new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
-                    opPackageName, id, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
-                    ENROLL_TIMEOUT_SEC, previewSurface, mSensorId,
-                    createLogger(BiometricsProtoEnums.ACTION_ENROLL,
-                            BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                    mBiometricContext, options);
-            mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-                @Override
-                public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                    mBiometricStateCallback.onClientStarted(clientMonitor);
-                }
-
-                @Override
-                public void onBiometricAction(int action) {
-                    mBiometricStateCallback.onBiometricAction(action);
-                }
-
-                @Override
-                public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                        boolean success) {
-                    mBiometricStateCallback.onClientFinished(clientMonitor, success);
-                    if (success) {
-                        // Update authenticatorIds
-                        scheduleUpdateActiveUserWithoutHandler(client.getTargetUserId());
-                    }
-                }
-            });
-    }
-
-    @Override
-    public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
-        mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId));
-    }
-
-    @Override
-    public long scheduleFaceDetect(@NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter callback,
-            @NonNull FaceAuthenticateOptions options, int statsClient) {
-        throw new IllegalStateException("Face detect not supported by [email protected]. Did you"
-                + "forget to check the supportsFaceDetection flag?");
-    }
-
-    @Override
-    public void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId) {
-        throw new IllegalStateException("Face detect not supported by [email protected]. Did you"
-                + "forget to check the supportsFaceDetection flag?");
-    }
-
-    @Override
-    public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter receiver,
-            @NonNull FaceAuthenticateOptions options, long requestId, boolean restricted,
-            int statsClient, boolean allowBackgroundAuthentication) {
-        mHandler.post(() -> {
-            final int userId = options.getUserId();
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId);
-            if (Flags.deHidl()) {
-                scheduleAuthenticateAidl(token, operationId, cookie, receiver, options, requestId,
-                        restricted, statsClient, allowBackgroundAuthentication, isStrongBiometric);
-            } else {
-                scheduleAuthenticateHidl(token, operationId, cookie, receiver, options, requestId,
-                        restricted, statsClient, allowBackgroundAuthentication, isStrongBiometric);
-            }
-        });
-    }
-
-    private void scheduleAuthenticateAidl(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter receiver,
-            @NonNull FaceAuthenticateOptions options, long requestId, boolean restricted,
-            int statsClient, boolean allowBackgroundAuthentication, boolean isStrongBiometric) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceAuthenticationClient
-                client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceAuthenticationClient(
-                        mContext, this::getSession, token, requestId, receiver, operationId,
-                        restricted, options, cookie, false /* requireConfirmation */,
-                        createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
-                                mAuthenticationStatsCollector), mBiometricContext,
-                        isStrongBiometric, mUsageStats, mLockoutTracker,
-                        allowBackgroundAuthentication, Utils.getCurrentStrength(mSensorId),
-                        mAuthenticationStateListeners);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleAuthenticateHidl(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter receiver,
-            @NonNull FaceAuthenticateOptions options, long requestId, boolean restricted,
-            int statsClient, boolean allowBackgroundAuthentication, boolean isStrongBiometric) {
-        final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
-                mLazyDaemon, token, requestId, receiver, operationId, restricted, options,
-                cookie, false /* requireConfirmation */,
-                createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
-                        mAuthenticationStatsCollector), mBiometricContext,
-                isStrongBiometric, mLockoutTracker, mUsageStats,
-                allowBackgroundAuthentication, Utils.getCurrentStrength(mSensorId),
-                mAuthenticationStateListeners);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    @Override
-    public long scheduleAuthenticate(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter receiver,
-            @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication) {
-        final long id = mRequestCounter.incrementAndGet();
-
-        scheduleAuthenticate(token, operationId, cookie, receiver,
-                options, id, restricted, statsClient, allowBackgroundAuthentication);
-
-        return id;
-    }
-
-    @Override
-    public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
-        mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId));
-    }
-
-    @Override
-    public void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            if (Flags.deHidl()) {
-                scheduleRemoveAidl(token, userId, receiver, opPackageName, faceId);
-            } else {
-                scheduleRemoveHidl(token, userId, receiver, opPackageName, faceId);
-            }
-        });
-    }
-
-    @Override
-    public void scheduleRemoveAll(int sensorId, @NonNull IBinder token, int userId,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            // For [email protected], remove(0) means remove all enrollments
-            if (Flags.deHidl()) {
-                scheduleRemoveAidl(token, userId, receiver, opPackageName, 0);
-            } else {
-                scheduleRemoveHidl(token, userId, receiver, opPackageName, 0);
-            }
-        });
-    }
-
-    private void scheduleRemoveAidl(@NonNull IBinder token, int userId,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName, int faceId) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceRemovalClient client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceRemovalClient(
-                        mContext, this::getSession, token,
-                        new ClientMonitorCallbackConverter(receiver), new int[]{faceId}, userId,
-                        opPackageName, FaceUtils.getLegacyInstance(mSensorId), mSensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_REMOVE,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector), mBiometricContext,
-                        mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    private void scheduleRemoveHidl(@NonNull IBinder token, int userId,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName, int faceId) {
-        final FaceRemovalClient client = new FaceRemovalClient(mContext, mLazyDaemon, token,
-                new ClientMonitorCallbackConverter(receiver), faceId, userId,
-                opPackageName, FaceUtils.getLegacyInstance(mSensorId), mSensorId,
-                createLogger(BiometricsProtoEnums.ACTION_REMOVE,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    @Override
-    public void scheduleResetLockout(int sensorId, int userId, @NonNull byte[] hardwareAuthToken) {
-        mHandler.post(() -> {
-            if (getEnrolledFaces(sensorId, userId).isEmpty()) {
-                Slog.w(TAG, "Ignoring lockout reset, no templates enrolled for user: " + userId);
-                return;
-            }
-
-            scheduleUpdateActiveUserWithoutHandler(userId);
-            if (Flags.deHidl()) {
-                scheduleResetLockoutAidl(userId, hardwareAuthToken);
-            } else {
-                scheduleResetLockoutHidl(userId, hardwareAuthToken);
-            }
-        });
-    }
-
-    private void scheduleResetLockoutAidl(int userId,
-            @NonNull byte[] hardwareAuthToken) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceResetLockoutClient client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceResetLockoutClient(
-                        mContext, this::getSession, userId, mContext.getOpPackageName(),
-                        mSensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext, hardwareAuthToken, mLockoutTracker,
-                        mLockoutResetDispatcher, mSensorProperties.sensorStrength);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleResetLockoutHidl(int userId,
-            @NonNull byte[] hardwareAuthToken) {
-        final FaceResetLockoutClient client = new FaceResetLockoutClient(mContext,
-                mLazyDaemon,
-                userId, mContext.getOpPackageName(), mSensorId,
-                createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, hardwareAuthToken);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    @Override
-    public void scheduleSetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
-            boolean enabled, @NonNull byte[] hardwareAuthToken,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-            if (Flags.deHidl()) {
-                scheduleSetFeatureAidl(sensorId, token, userId, feature, enabled, hardwareAuthToken,
-                        receiver, opPackageName);
-            } else {
-                scheduleSetFeatureHidl(sensorId, token, userId, feature, enabled, hardwareAuthToken,
-                        receiver, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleSetFeatureHidl(int sensorId, @NonNull IBinder token, int userId,
-            int feature, boolean enabled, @NonNull byte[] hardwareAuthToken,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        final List<Face> faces = getEnrolledFaces(sensorId, userId);
-        if (faces.isEmpty()) {
-            Slog.w(TAG, "Ignoring setFeature, no templates enrolled for user: " + userId);
-            return;
-        }
-        final int faceId = faces.get(0).getBiometricId();
-        final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext, mLazyDaemon,
-                token, new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
-                mSensorId, BiometricLogger.ofUnknown(mContext), mBiometricContext, feature,
-                enabled, hardwareAuthToken, faceId);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleSetFeatureAidl(int sensorId, @NonNull IBinder token, int userId,
-            int feature, boolean enabled, @NonNull byte[] hardwareAuthToken,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceSetFeatureClient client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceSetFeatureClient(
-                        mContext, this::getSession, token,
-                        new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
-                        mSensorId, BiometricLogger.ofUnknown(mContext), mBiometricContext,
-                        feature, enabled, hardwareAuthToken);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-
-    @Override
-    public void scheduleGetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
-            @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            if (Flags.deHidl()) {
-                scheduleGetFeatureAidl(token, userId, feature, listener,
-                        opPackageName);
-            } else {
-                scheduleGetFeatureHidl(sensorId, token, userId, feature, listener,
-                        opPackageName);
-            }
-        });
-    }
-
-    private void scheduleGetFeatureHidl(int sensorId, @NonNull IBinder token, int userId,
-            int feature, @Nullable ClientMonitorCallbackConverter listener,
-            @NonNull String opPackageName) {
-        final List<Face> faces = getEnrolledFaces(sensorId, userId);
-        if (faces.isEmpty()) {
-            Slog.w(TAG, "Ignoring getFeature, no templates enrolled for user: " + userId);
-            return;
-        }
-
-        final int faceId = faces.get(0).getBiometricId();
-        final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
-                token, listener, userId, opPackageName, mSensorId,
-                BiometricLogger.ofUnknown(mContext), mBiometricContext, feature, faceId);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                if (success
-                        && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
-                    final int settingsValue = client.getValue() ? 1 : 0;
-                    Slog.d(TAG,
-                            "Updating attention value for user: " + userId + " to value: "
-                                    + settingsValue);
-                    Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                            Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, settingsValue,
-                            userId);
-                }
-            }
-        });
-    }
-
-    private void scheduleGetFeatureAidl(@NonNull IBinder token, int userId,
-            int feature, @Nullable ClientMonitorCallbackConverter listener,
-            @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceGetFeatureClient client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceGetFeatureClient(
-                        mContext, this::getSession, token, listener, userId, opPackageName,
-                        mSensorId, BiometricLogger.ofUnknown(mContext), mBiometricContext,
-                        feature);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleInternalCleanup(int userId,
-            @Nullable ClientMonitorCallback callback) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-            if (Flags.deHidl()) {
-                scheduleInternalCleanupAidl(userId, callback);
-            } else {
-                scheduleInternalCleanupHidl(userId, callback);
-            }
-        });
-    }
-
-    private void scheduleInternalCleanupHidl(int userId,
-            @Nullable ClientMonitorCallback callback) {
-        final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
-                mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
-                createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, FaceUtils.getLegacyInstance(mSensorId),
-                mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client,
-                new ClientMonitorCompositeCallback(callback, mBiometricStateCallback));
-    }
-
-    private void scheduleInternalCleanupAidl(int userId,
-            @Nullable ClientMonitorCallback callback) {
-        final com.android.server.biometrics.sensors.face.aidl.FaceInternalCleanupClient
-                client =
-                new com.android.server.biometrics.sensors.face.aidl.FaceInternalCleanupClient(
-                        mContext, this::getSession, userId, mContext.getOpPackageName(),
-                        mSensorId, createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                        mBiometricContext, FaceUtils.getLegacyInstance(mSensorId),
-                        mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client,
-                new ClientMonitorCompositeCallback(callback, mBiometricStateCallback));
-    }
-
-    @Override
-    public void scheduleInternalCleanup(int sensorId, int userId,
-            @Nullable ClientMonitorCallback callback) {
-        scheduleInternalCleanup(userId, mBiometricStateCallback);
-    }
-
-    @Override
-    public void scheduleInternalCleanup(int sensorId, int userId,
-            @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
-        scheduleInternalCleanup(userId, callback);
-    }
-
-    @Override
-    public void startPreparedClient(int sensorId, int cookie) {
-        mHandler.post(() -> {
-            mScheduler.startPreparedClient(cookie);
-        });
-    }
-
-    @Override
-    public void dumpProtoState(int sensorId, ProtoOutputStream proto,
-            boolean clearSchedulerBuffer) {
-        final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES);
-
-        proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId);
-        proto.write(SensorStateProto.MODALITY, SensorStateProto.FACE);
-        proto.write(SensorStateProto.CURRENT_STRENGTH,
-                Utils.getCurrentStrength(mSensorProperties.sensorId));
-        proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer));
-
-        for (UserInfo user : UserManager.get(mContext).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-
-            final long userToken = proto.start(SensorStateProto.USER_STATES);
-            proto.write(UserStateProto.USER_ID, userId);
-            proto.write(UserStateProto.NUM_ENROLLED, FaceUtils.getLegacyInstance(mSensorId)
-                    .getBiometricsForUser(mContext, userId).size());
-            proto.end(userToken);
-        }
-
-        proto.write(SensorStateProto.RESET_LOCKOUT_REQUIRES_HARDWARE_AUTH_TOKEN,
-                mSensorProperties.resetLockoutRequiresHardwareAuthToken);
-        proto.write(SensorStateProto.RESET_LOCKOUT_REQUIRES_CHALLENGE,
-                mSensorProperties.resetLockoutRequiresChallenge);
-
-        proto.end(sensorToken);
-    }
-
-    @Override
-    public void dumpProtoMetrics(int sensorId, FileDescriptor fd) {
-    }
-
-    @Override
-    public void dumpInternal(int sensorId, PrintWriter pw) {
-        PerformanceTracker performanceTracker =
-                PerformanceTracker.getInstanceForSensorId(mSensorId);
-
-        JSONObject dump = new JSONObject();
-        try {
-            dump.put("service", TAG);
-
-            JSONArray sets = new JSONArray();
-            for (UserInfo user : UserManager.get(mContext).getUsers()) {
-                final int userId = user.getUserHandle().getIdentifier();
-                final int c = FaceUtils.getLegacyInstance(mSensorId)
-                        .getBiometricsForUser(mContext, userId).size();
-                JSONObject set = new JSONObject();
-                set.put("id", userId);
-                set.put("count", c);
-                set.put("accept", performanceTracker.getAcceptForUser(userId));
-                set.put("reject", performanceTracker.getRejectForUser(userId));
-                set.put("acquire", performanceTracker.getAcquireForUser(userId));
-                set.put("lockout", performanceTracker.getTimedLockoutForUser(userId));
-                set.put("permanentLockout", performanceTracker.getPermanentLockoutForUser(userId));
-                // cryptoStats measures statistics about secure face transactions
-                // (e.g. to unlock password storage, make secure purchases, etc.)
-                set.put("acceptCrypto", performanceTracker.getAcceptCryptoForUser(userId));
-                set.put("rejectCrypto", performanceTracker.getRejectCryptoForUser(userId));
-                set.put("acquireCrypto", performanceTracker.getAcquireCryptoForUser(userId));
-                sets.put(set);
-            }
-
-            dump.put("prints", sets);
-        } catch (JSONException e) {
-            Slog.e(TAG, "dump formatting failure", e);
-        }
-        pw.println(dump);
-        pw.println("HAL deaths since last reboot: " + performanceTracker.getHALDeathCount());
-
-        mScheduler.dump(pw);
-        mUsageStats.print(pw);
-    }
-
-    private void scheduleLoadAuthenticatorIds() {
-        // Note that this can be performed on the scheduler (as opposed to being done immediately
-        // when the HAL is (re)loaded, since
-        // 1) If this is truly the first time it's being performed (e.g. system has just started),
-        //    this will be run very early and way before any applications need to generate keys.
-        // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has
-        //    just been reloaded), the framework already has a cache of the authenticatorIds. This
-        //    is safe because authenticatorIds only change when A) new template has been enrolled,
-        //    or B) all templates are removed.
-        mHandler.post(() -> {
-            for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
-                final int targetUserId = user.id;
-                if (!mAuthenticatorIds.containsKey(targetUserId)) {
-                    scheduleUpdateActiveUserWithoutHandler(targetUserId);
-                }
-            }
-        });
-    }
-
-    /**
-     * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the handler.
-     * Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
-     * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
-     * this operation on the same lambda/runnable as those operations so that the ordering is
-     * correct.
-     */
-    private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
-        final boolean hasEnrolled = !getEnrolledFaces(mSensorId, targetUserId).isEmpty();
-        final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
-                mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId,
-                createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, hasEnrolled, mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                if (success) {
-                    if (mCurrentUserId != targetUserId) {
-                        // Create new session with updated user ID
-                        mSession = null;
-                    }
-                    mCurrentUserId = targetUserId;
-                } else {
-                    Slog.w(TAG, "Failed to change user, still: " + mCurrentUserId);
-                }
-            }
-        });
-    }
-
-    private BiometricLogger createLogger(int statsAction, int statsClient,
-            AuthenticationStatsCollector authenticationStatsCollector) {
-        return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FACE,
-                statsAction, statsClient, authenticationStatsCollector);
-    }
-
-    /**
-     * Sends a debug message to the HAL with the provided FileDescriptor and arguments.
-     */
-    public void dumpHal(int sensorId, @NonNull FileDescriptor fd, @NonNull String[] args) {
-        // WARNING: CDD restricts image data from leaving TEE unencrypted on
-        //          production devices:
-        // [C-1-10] MUST not allow unencrypted access to identifiable biometric
-        //          data or any data derived from it (such as embeddings) to the
-        //         Application Processor outside the context of the TEE.
-        //  As such, this API should only be enabled for testing purposes on
-        //  engineering and userdebug builds.  All modules in the software stack
-        //  MUST enforce final build products do NOT have this functionality.
-        //  Additionally, the following check MUST NOT be removed.
-        if (!(Build.IS_ENG || Build.IS_USERDEBUG)) {
-            return;
-        }
-
-        // Additionally, this flag allows turning off face for a device
-        // (either permanently through the build or on an individual device).
-        if (SystemProperties.getBoolean("ro.face.disable_debug_data", false)
-                || SystemProperties.getBoolean("persist.face.disable_debug_data", false)) {
-            return;
-        }
-
-        // The debug method takes two file descriptors. The first is for text
-        // output, which we will drop.  The second is for binary data, which
-        // will be the protobuf data.
-        final IBiometricsFace daemon = getDaemon();
-        if (daemon != null) {
-            FileOutputStream devnull = null;
-            try {
-                devnull = new FileOutputStream("/dev/null");
-                final NativeHandle handle = new NativeHandle(
-                        new FileDescriptor[]{devnull.getFD(), fd},
-                        new int[0], false);
-                daemon.debug(handle, new ArrayList<String>(Arrays.asList(args)));
-            } catch (IOException | RemoteException ex) {
-                Slog.d(TAG, "error while reading face debugging data", ex);
-            } finally {
-                if (devnull != null) {
-                    try {
-                        devnull.close();
-                    } catch (IOException ex) {
-                    }
-                }
-            }
-        }
-    }
-
-    void setTestHalEnabled(boolean enabled) {
-        mTestHalEnabled = enabled;
-    }
-
-    @NonNull
-    @Override
-    public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
-            @NonNull String opPackageName) {
-        return new BiometricTestSessionImpl(mContext, mSensorId, callback,
-                this, mHalResultController);
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
deleted file mode 100644
index e44b263..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import static android.adaptiveauth.Flags.reportBiometricAuthAttempts;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.SensorPrivacyManager;
-import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricManager.Authenticators;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.face.FaceAuthenticateOptions;
-import android.hardware.face.FaceManager;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.internal.R;
-import com.android.server.biometrics.Utils;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.AuthenticationClient;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BiometricNotificationUtils;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
-import com.android.server.biometrics.sensors.LockoutTracker;
-import com.android.server.biometrics.sensors.PerformanceTracker;
-import com.android.server.biometrics.sensors.face.UsageStats;
-
-import java.util.ArrayList;
-import java.util.function.Supplier;
-
-/**
- * Face-specific authentication client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
- */
-class FaceAuthenticationClient
-        extends AuthenticationClient<IBiometricsFace, FaceAuthenticateOptions> {
-
-    private static final String TAG = "FaceAuthenticationClient";
-
-    private final UsageStats mUsageStats;
-
-    private final int[] mBiometricPromptIgnoreList;
-    private final int[] mBiometricPromptIgnoreListVendor;
-    private final int[] mKeyguardIgnoreList;
-    private final int[] mKeyguardIgnoreListVendor;
-
-    private int mLastAcquire;
-    private SensorPrivacyManager mSensorPrivacyManager;
-    @NonNull
-    private final AuthenticationStateListeners mAuthenticationStateListeners;
-
-    FaceAuthenticationClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFace> lazyDaemon,
-            @NonNull IBinder token, long requestId,
-            @NonNull ClientMonitorCallbackConverter listener, long operationId,
-            boolean restricted, @NonNull FaceAuthenticateOptions options, int cookie,
-            boolean requireConfirmation,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker,
-            @NonNull UsageStats usageStats, boolean allowBackgroundAuthentication,
-            @Authenticators.Types int sensorStrength,
-            @NonNull AuthenticationStateListeners authenticationStateListeners) {
-        super(context, lazyDaemon, token, listener, operationId, restricted,
-                options, cookie, requireConfirmation, logger, biometricContext,
-                isStrongBiometric, null /* taskStackListener */,
-                lockoutTracker, allowBackgroundAuthentication, false /* shouldVibrate */,
-                sensorStrength);
-        setRequestId(requestId);
-        mUsageStats = usageStats;
-        mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
-        mAuthenticationStateListeners = authenticationStateListeners;
-
-        final Resources resources = getContext().getResources();
-        mBiometricPromptIgnoreList = resources.getIntArray(
-                R.array.config_face_acquire_biometricprompt_ignorelist);
-        mBiometricPromptIgnoreListVendor = resources.getIntArray(
-                R.array.config_face_acquire_vendor_biometricprompt_ignorelist);
-        mKeyguardIgnoreList = resources.getIntArray(
-                R.array.config_face_acquire_keyguard_ignorelist);
-        mKeyguardIgnoreListVendor = resources.getIntArray(
-                R.array.config_face_acquire_vendor_keyguard_ignorelist);
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-        mState = STATE_STARTED;
-    }
-
-    @NonNull
-    @Override
-    protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
-        return new ClientMonitorCompositeCallback(
-                getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
-    }
-
-    @Override
-    protected void startHalOperation() {
-
-        if (mSensorPrivacyManager != null
-                && mSensorPrivacyManager
-                .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
-                SensorPrivacyManager.Sensors.CAMERA)) {
-            onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-            return;
-        }
-
-        try {
-            getFreshDaemon().authenticate(mOperationId);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting auth", e);
-            onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    protected void stopHalOperation() {
-        try {
-            getFreshDaemon().cancel();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting cancel", e);
-            onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public boolean wasUserDetected() {
-        // Do not provide haptic feedback if the user was not detected, and an error (usually
-        // ERROR_TIMEOUT) is received.
-        return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
-                && mLastAcquire != FaceManager.FACE_ACQUIRED_SENSOR_DIRTY;
-    }
-
-    @Override
-    protected void handleLifecycleAfterAuth(boolean authenticated) {
-        // For face, the authentication lifecycle ends either when
-        // 1) Authenticated == true
-        // 2) Error occurred
-        // 3) Authenticated == false
-        mCallback.onClientFinished(this, true /* success */);
-    }
-
-    @Override
-    public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
-        @LockoutTracker.LockoutMode final int lockoutMode =
-                getLockoutTracker().getLockoutModeForUser(userId);
-        final PerformanceTracker performanceTracker =
-                PerformanceTracker.getInstanceForSensorId(getSensorId());
-        if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) {
-            performanceTracker.incrementPermanentLockoutForUser(userId);
-        } else if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) {
-            performanceTracker.incrementTimedLockoutForUser(userId);
-        }
-
-        return lockoutMode;
-    }
-
-    @Override
-    public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
-            boolean authenticated, ArrayList<Byte> token) {
-        super.onAuthenticated(identifier, authenticated, token);
-
-        mState = STATE_STOPPED;
-        mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
-                getStartTimeMs(),
-                System.currentTimeMillis() - getStartTimeMs() /* latency */,
-                authenticated,
-                0 /* error */,
-                0 /* vendorError */,
-                getTargetUserId()));
-
-        if (reportBiometricAuthAttempts()) {
-            if (authenticated) {
-                mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(),
-                        getTargetUserId());
-            } else {
-                mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(),
-                        getTargetUserId());
-            }
-        }
-    }
-
-    @Override
-    public void onError(@BiometricConstants.Errors int error, int vendorCode) {
-        mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
-                getStartTimeMs(),
-                System.currentTimeMillis() - getStartTimeMs() /* latency */,
-                false /* authenticated */,
-                error,
-                vendorCode,
-                getTargetUserId()));
-
-        super.onError(error, vendorCode);
-    }
-
-    private int[] getAcquireIgnorelist() {
-        return isBiometricPrompt() ? mBiometricPromptIgnoreList : mKeyguardIgnoreList;
-    }
-
-    private int[] getAcquireVendorIgnorelist() {
-        return isBiometricPrompt() ? mBiometricPromptIgnoreListVendor : mKeyguardIgnoreListVendor;
-    }
-
-    private boolean shouldSend(int acquireInfo, int vendorCode) {
-        if (acquireInfo == FaceManager.FACE_ACQUIRED_VENDOR) {
-            return !Utils.listContains(getAcquireVendorIgnorelist(), vendorCode);
-        } else {
-            return !Utils.listContains(getAcquireIgnorelist(), acquireInfo);
-        }
-    }
-
-    @Override
-    public void onAcquired(int acquireInfo, int vendorCode) {
-        mLastAcquire = acquireInfo;
-
-        if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
-            BiometricNotificationUtils.showReEnrollmentNotification(getContext());
-        }
-        @LockoutTracker.LockoutMode final int lockoutMode =
-                getLockoutTracker().getLockoutModeForUser(getTargetUserId());
-        if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
-            PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId());
-            pt.incrementAcquireForUser(getTargetUserId(), isCryptoOperation());
-        }
-
-        final boolean shouldSend = shouldSend(acquireInfo, vendorCode);
-        onAcquiredInternal(acquireInfo, vendorCode, shouldSend);
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
deleted file mode 100644
index 815cf91..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.biometrics.face.V1_0.Status;
-import android.hardware.face.Face;
-import android.hardware.face.FaceEnrollOptions;
-import android.hardware.face.FaceManager;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-import android.view.Surface;
-
-import com.android.internal.R;
-import com.android.server.biometrics.Utils;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricNotificationUtils;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
-import com.android.server.biometrics.sensors.EnrollClient;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.function.Supplier;
-
-/**
- * Face-specific enroll client supporting the {@link android.hardware.biometrics.face.V1_0} HIDL
- * interface.
- */
-public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
-
-    private static final String TAG = "FaceEnrollClient";
-
-    @NonNull private final int[] mDisabledFeatures;
-    @NonNull private final int[] mEnrollIgnoreList;
-    @NonNull private final int[] mEnrollIgnoreListVendor;
-
-    FaceEnrollClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
-            @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
-            @NonNull byte[] hardwareAuthToken, @NonNull String owner, long requestId,
-            @NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
-            @Nullable Surface previewSurface, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull FaceEnrollOptions options) {
-        super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
-                timeoutSec, sensorId, false /* shouldVibrate */, logger, biometricContext,
-                BiometricFaceConstants.reasonToMetric(options.getEnrollReason()));
-        setRequestId(requestId);
-        mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
-        mEnrollIgnoreList = getContext().getResources()
-                .getIntArray(R.array.config_face_acquire_enroll_ignorelist);
-        mEnrollIgnoreListVendor = getContext().getResources()
-                .getIntArray(R.array.config_face_acquire_vendor_enroll_ignorelist);
-
-        Slog.w(TAG, "EnrollOptions "
-                + FaceEnrollOptions.enrollReasonToString(options.getEnrollReason()));
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-
-        BiometricNotificationUtils.cancelFaceEnrollNotification(getContext());
-        BiometricNotificationUtils.cancelFaceReEnrollNotification(getContext());
-    }
-
-    @NonNull
-    @Override
-    protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
-        return new ClientMonitorCompositeCallback(
-                getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
-    }
-
-    @Override
-    protected boolean hasReachedEnrollmentLimit() {
-        final int limit = getContext().getResources().getInteger(
-                com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
-        final int enrolled = mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId())
-                .size();
-        if (enrolled >= limit) {
-            Slog.w(TAG, "Too many faces registered, user: " + getTargetUserId());
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void onAcquired(int acquireInfo, int vendorCode) {
-        final boolean shouldSend;
-        if (acquireInfo == FaceManager.FACE_ACQUIRED_VENDOR) {
-            shouldSend = !Utils.listContains(mEnrollIgnoreListVendor, vendorCode);
-        } else {
-            shouldSend = !Utils.listContains(mEnrollIgnoreList, acquireInfo);
-        }
-        onAcquiredInternal(acquireInfo, vendorCode, shouldSend);
-    }
-
-    @Override
-    protected void startHalOperation() {
-        final ArrayList<Byte> token = new ArrayList<>();
-        for (byte b : mHardwareAuthToken) {
-            token.add(b);
-        }
-        final ArrayList<Integer> disabledFeatures = new ArrayList<>();
-        for (int disabledFeature : mDisabledFeatures) {
-            disabledFeatures.add(disabledFeature);
-        }
-
-        try {
-            final int status = getFreshDaemon().enroll(token, mTimeoutSec, disabledFeatures);
-
-            if (status != Status.OK) {
-                onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
-                mCallback.onClientFinished(this, false /* success */);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting enroll", e);
-            onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    protected void stopHalOperation() {
-        try {
-            getFreshDaemon().cancel();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting cancel", e);
-            onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
deleted file mode 100644
index 97838a7..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.face.IFaceServiceReceiver;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.internal.util.Preconditions;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.GenerateChallengeClient;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Supplier;
-
-/**
- * Face-specific generateChallenge client supporting the
- * {@link android.hardware.biometrics.face.V1_0} HIDL interface.
- */
-public class FaceGenerateChallengeClient extends GenerateChallengeClient<IBiometricsFace> {
-
-    private static final String TAG = "FaceGenerateChallengeClient";
-    static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes
-    private static final ClientMonitorCallback EMPTY_CALLBACK = new ClientMonitorCallback() {
-    };
-
-    private final long mCreatedAt;
-    private List<IFaceServiceReceiver> mWaiting;
-    private Long mChallengeResult;
-
-    FaceGenerateChallengeClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
-            int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext, long now) {
-        super(context, lazyDaemon, token, listener, userId, owner, sensorId, logger,
-                biometricContext);
-        mCreatedAt = now;
-        mWaiting = new ArrayList<>();
-    }
-
-    @Override
-    protected void startHalOperation() {
-        mChallengeResult = null;
-        try {
-            mChallengeResult = getFreshDaemon().generateChallenge(CHALLENGE_TIMEOUT_SEC).value;
-            // send the result to the original caller via mCallback and any waiting callers
-            // that called reuseResult
-            sendChallengeResult(getListener(), mCallback);
-            for (IFaceServiceReceiver receiver : mWaiting) {
-                sendChallengeResult(new ClientMonitorCallbackConverter(receiver), EMPTY_CALLBACK);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "generateChallenge failed", e);
-            mCallback.onClientFinished(this, false /* success */);
-        } finally {
-            mWaiting = null;
-        }
-    }
-
-    /** @return An arbitrary time value for caching provided to the constructor. */
-    public long getCreatedAt() {
-        return mCreatedAt;
-    }
-
-    /**
-     * Reuse the result of this operation when it is available. The receiver will be notified
-     * immediately if a challenge has already been generated.
-     *
-     * @param receiver receiver to be notified of challenge result
-     */
-    public void reuseResult(@NonNull IFaceServiceReceiver receiver) {
-        if (mWaiting != null) {
-            mWaiting.add(receiver);
-        } else {
-            sendChallengeResult(new ClientMonitorCallbackConverter(receiver), EMPTY_CALLBACK);
-        }
-    }
-
-    private void sendChallengeResult(@NonNull ClientMonitorCallbackConverter receiver,
-            @NonNull ClientMonitorCallback ownerCallback) {
-        Preconditions.checkState(mChallengeResult != null, "result not available");
-        try {
-            receiver.onChallengeGenerated(getSensorId(), getTargetUserId(), mChallengeResult);
-            ownerCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception", e);
-            ownerCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
deleted file mode 100644
index 47aaeec..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.biometrics.face.V1_0.OptionalBool;
-import android.hardware.biometrics.face.V1_0.Status;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.HalClientMonitor;
-
-import java.util.function.Supplier;
-
-/**
- * Face-specific getFeature client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
- */
-public class FaceGetFeatureClient extends HalClientMonitor<IBiometricsFace> {
-
-    private static final String TAG = "FaceGetFeatureClient";
-
-    private final int mFeature;
-    private final int mFaceId;
-    private boolean mValue;
-
-    FaceGetFeatureClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
-            @NonNull IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
-            @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            int feature, int faceId) {
-        super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
-                logger, biometricContext);
-        mFeature = feature;
-        mFaceId = faceId;
-    }
-
-    @Override
-    public void unableToStart() {
-        try {
-            getListener().onFeatureGet(false /* success */, new int[0], new boolean[0]);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to send error", e);
-        }
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-        startHalOperation();
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            final OptionalBool result = getFreshDaemon().getFeature(mFeature, mFaceId);
-            int[] features = new int[1];
-            boolean[] featureState = new boolean[1];
-            features[0] = mFeature;
-            featureState[0] = result.value;
-            mValue = result.value;
-
-            getListener().onFeatureGet(result.status == Status.OK, features, featureState);
-            mCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to getFeature", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    boolean getValue() {
-        return mValue;
-    }
-
-    @Override
-    public int getProtoEnum() {
-        return BiometricsProto.CM_GET_FEATURE;
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
deleted file mode 100644
index 89a17c6..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.face.Face;
-import android.os.IBinder;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.InternalCleanupClient;
-import com.android.server.biometrics.sensors.InternalEnumerateClient;
-import com.android.server.biometrics.sensors.RemovalClient;
-
-import java.util.List;
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * Face-specific internal cleanup client supporting the
- * {@link android.hardware.biometrics.face.V1_0} HIDL interface.
- */
-class FaceInternalCleanupClient extends InternalCleanupClient<Face, IBiometricsFace> {
-
-    FaceInternalCleanupClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, @NonNull String owner,
-            int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext,
-            @NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
-        super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
-                utils, authenticatorIds);
-    }
-
-    @Override
-    protected InternalEnumerateClient<IBiometricsFace> getEnumerateClient(Context context,
-            Supplier<IBiometricsFace> lazyDaemon, IBinder token, int userId, String owner,
-            List<Face> enrolledList, BiometricUtils<Face> utils, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
-        return new FaceInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
-                enrolledList, utils, sensorId, logger, biometricContext);
-    }
-
-    @Override
-    protected RemovalClient<Face, IBiometricsFace> getRemovalClient(Context context,
-            Supplier<IBiometricsFace> lazyDaemon, IBinder token,
-            int biometricId, int userId, String owner, BiometricUtils<Face> utils, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            Map<Integer, Long> authenticatorIds) {
-        // Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
-        // is all done internally.
-        return new FaceRemovalClient(context, lazyDaemon, token,
-                null /* ClientMonitorCallbackConverter */, biometricId, userId, owner, utils,
-                sensorId, logger, biometricContext, authenticatorIds);
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java
deleted file mode 100644
index 250dd7e..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.face.Face;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.InternalEnumerateClient;
-
-import java.util.List;
-import java.util.function.Supplier;
-
-/**
- * Face-specific internal enumerate client supporting the
- * {@link android.hardware.biometrics.face.V1_0} HIDL interface.
- */
-class FaceInternalEnumerateClient extends InternalEnumerateClient<IBiometricsFace> {
-    private static final String TAG = "FaceInternalEnumerateClient";
-
-    FaceInternalEnumerateClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFace> lazyDaemon, @NonNull IBinder token, int userId,
-            @NonNull String owner, @NonNull List<Face> enrolledList,
-            @NonNull BiometricUtils<Face> utils, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
-        super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
-                logger, biometricContext);
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            getFreshDaemon().enumerate();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting enumerate", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java
deleted file mode 100644
index 0ee7a35..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.face.Face;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.RemovalClient;
-
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * Face-specific removal client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
- */
-class FaceRemovalClient extends RemovalClient<Face, IBiometricsFace> {
-    private static final String TAG = "FaceRemovalClient";
-
-    private final int mBiometricId;
-
-    FaceRemovalClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
-            @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
-            int biometricId, int userId, @NonNull String owner, @NonNull BiometricUtils<Face> utils,
-            int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext,
-            @NonNull Map<Integer, Long> authenticatorIds) {
-        super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId, logger,
-                biometricContext, authenticatorIds);
-        mBiometricId = biometricId;
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            getFreshDaemon().remove(mBiometricId);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting remove", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
deleted file mode 100644
index f29b9e8..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.HalClientMonitor;
-
-import java.util.ArrayList;
-import java.util.function.Supplier;
-
-/**
- * Face-specific resetLockout client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
- */
-public class FaceResetLockoutClient extends HalClientMonitor<IBiometricsFace> {
-
-    private static final String TAG = "FaceResetLockoutClient";
-
-    private final ArrayList<Byte> mHardwareAuthToken;
-
-    FaceResetLockoutClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull byte[] hardwareAuthToken) {
-        super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
-                0 /* cookie */, sensorId, logger, biometricContext);
-
-        mHardwareAuthToken = new ArrayList<>();
-        for (byte b : hardwareAuthToken) {
-            mHardwareAuthToken.add(b);
-        }
-    }
-
-    @Override
-    public void unableToStart() {
-        // Nothing to do here
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-        startHalOperation();
-    }
-
-    public boolean interruptsPrecedingClients() {
-        return true;
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            getFreshDaemon().resetLockout(mHardwareAuthToken);
-            mCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to reset lockout", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public int getProtoEnum() {
-        return BiometricsProto.CM_RESET_LOCKOUT;
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
deleted file mode 100644
index b7b0dc04..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.RevokeChallengeClient;
-
-import java.util.function.Supplier;
-
-/**
- * Face-specific revokeChallenge client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
- */
-public class FaceRevokeChallengeClient extends RevokeChallengeClient<IBiometricsFace> {
-
-    private static final String TAG = "FaceRevokeChallengeClient";
-
-    FaceRevokeChallengeClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
-            int userId, @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
-        super(context, lazyDaemon, token, userId, owner, sensorId, logger, biometricContext);
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            getFreshDaemon().revokeChallenge();
-            mCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "revokeChallenge failed", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
deleted file mode 100644
index 3c82f9c..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.biometrics.face.V1_0.Status;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.HalClientMonitor;
-
-import java.util.ArrayList;
-import java.util.function.Supplier;
-
-/**
- * Face-specific setFeature client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
- */
-public class FaceSetFeatureClient extends HalClientMonitor<IBiometricsFace> {
-
-    private static final String TAG = "FaceSetFeatureClient";
-
-    private final int mFeature;
-    private final boolean mEnabled;
-    private final ArrayList<Byte> mHardwareAuthToken;
-    private final int mFaceId;
-
-    FaceSetFeatureClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
-            @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
-            @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            int feature, boolean enabled, byte[] hardwareAuthToken, int faceId) {
-        super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
-                logger, biometricContext);
-        mFeature = feature;
-        mEnabled = enabled;
-        mFaceId = faceId;
-
-        mHardwareAuthToken = new ArrayList<>();
-        for (byte b : hardwareAuthToken) {
-            mHardwareAuthToken.add(b);
-        }
-    }
-
-    @Override
-    public void unableToStart() {
-        try {
-            getListener().onFeatureSet(false /* success */, mFeature);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to send error", e);
-        }
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-
-        startHalOperation();
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            final int result = getFreshDaemon()
-                    .setFeature(mFeature, mEnabled, mHardwareAuthToken, mFaceId);
-            getListener().onFeatureSet(result == Status.OK, mFeature);
-            mCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to set feature: " + mFeature + " to enabled: " + mEnabled, e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public int getProtoEnum() {
-        return BiometricsProto.CM_SET_FEATURE;
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java
index a004cae4..9a4c29d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java
@@ -173,9 +173,14 @@
     }
 
     private AidlResponseHandler getAidlResponseHandler() {
-        return new AidlResponseHandler(getContext(), getScheduler(), getSensorProperties().sensorId,
-                mCurrentUserId, mLockoutTracker, mLockoutResetDispatcher,
-                mAuthSessionCoordinator, () -> {}, mAidlResponseHandlerCallback);
+        return new AidlResponseHandler(getContext(),
+                getScheduler(),
+                getSensorProperties().sensorId,
+                mCurrentUserId,
+                mLockoutTracker,
+                mLockoutResetDispatcher,
+                mAuthSessionCoordinator,
+                mAidlResponseHandlerCallback);
     }
 
     private IBiometricsFace getIBiometricsFace() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapter.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapter.java
index fa95361..45d0cfe 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapter.java
@@ -53,7 +53,7 @@
 
     private static final String TAG = "HidlToAidlSessionAdapter";
 
-    private static final int CHALLENGE_TIMEOUT_SEC = 600;
+    @VisibleForTesting static final int CHALLENGE_TIMEOUT_SEC = 600;
     @DurationMillisLong
     private static final int GENERATE_CHALLENGE_REUSE_INTERVAL_MILLIS = 60 * 1000;
     @DurationMillisLong
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 2dc03ed..4c86f57 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
@@ -57,7 +57,6 @@
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
 import android.hardware.fingerprint.IFingerprintService;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.Binder;
 import android.os.Build;
@@ -72,7 +71,6 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Pair;
 import android.util.Slog;
@@ -83,7 +81,6 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.SystemService;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.sensors.AuthenticationStateListeners;
@@ -94,12 +91,8 @@
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
 import com.android.server.biometrics.sensors.LockoutTracker;
 import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider;
-import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21;
-import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21UdfpsMock;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 
-import com.google.android.collect.Lists;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -886,9 +879,9 @@
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override // Binder call
-        public void registerAuthenticatorsLegacy(
+        public void registerAuthenticators(
                 @NonNull FingerprintSensorConfigurations fingerprintSensorConfigurations) {
-            super.registerAuthenticatorsLegacy_enforcePermission();
+            super.registerAuthenticators_enforcePermission();
             if (!fingerprintSensorConfigurations.hasSensorConfigurations()) {
                 Slog.d(TAG, "No fingerprint sensors available.");
                 return;
@@ -897,30 +890,6 @@
         }
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
-        @Override // Binder call
-        public void registerAuthenticators(
-                @NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
-            super.registerAuthenticators_enforcePermission();
-
-            mRegistry.registerAll(() -> {
-                List<String> aidlSensors = new ArrayList<>();
-                final String[] instances = mAidlInstanceNameSupplier.get();
-                if (instances != null) {
-                    aidlSensors.addAll(Lists.newArrayList(instances));
-                }
-
-                final Pair<List<FingerprintSensorPropertiesInternal>, List<String>>
-                        filteredInstances = filterAvailableHalInstances(hidlSensors, aidlSensors);
-
-                final List<ServiceProvider> providers = new ArrayList<>();
-                providers.addAll(getHidlProviders(filteredInstances.first));
-                providers.addAll(getAidlProviders(filteredInstances.second));
-
-                return providers;
-            });
-        }
-
-        @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override
         public void addAuthenticatorsRegisteredCallback(
                 IFingerprintAuthenticatorsRegisteredCallback callback) {
@@ -1004,17 +973,6 @@
             }
         }
 
-        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-        @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
-        @Override
-        public void setSidefpsController(@NonNull ISidefpsController controller) {
-            super.setSidefpsController_enforcePermission();
-
-            for (ServiceProvider provider : mRegistry.getProviders()) {
-                provider.setSidefpsController(controller);
-            }
-        }
-
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override
         public void onPowerPressed() {
@@ -1086,22 +1044,15 @@
 
                     return null;
                 };
-        if (Flags.deHidl()) {
-            mFingerprintProviderFunction = fingerprintProviderFunction == null
-                    ? (filteredSensorProps, resetLockoutRequiresHardwareAuthToken) ->
-                            new FingerprintProvider(
-                                    getContext(), mBiometricStateCallback,
-                                    mAuthenticationStateListeners,
-                                    filteredSensorProps.second,
-                                    filteredSensorProps.first, mLockoutResetDispatcher,
-                                    mGestureAvailabilityDispatcher,
-                                    mBiometricContext,
-                                    resetLockoutRequiresHardwareAuthToken)
-                    : fingerprintProviderFunction;
-        } else {
-            mFingerprintProviderFunction =
-                    (filteredSensorProps, resetLockoutRequiresHardwareAuthToken) -> null;
-        }
+        mFingerprintProviderFunction = fingerprintProviderFunction != null
+                ? fingerprintProviderFunction :
+                        (filteredSensorProps, resetLockoutRequiresHardwareAuthToken) ->
+                                new FingerprintProvider(getContext(), mBiometricStateCallback,
+                                        mAuthenticationStateListeners, filteredSensorProps.second,
+                                        filteredSensorProps.first, mLockoutResetDispatcher,
+                                        mGestureAvailabilityDispatcher, mBiometricContext,
+                                        resetLockoutRequiresHardwareAuthToken);
+
         mHandler = new Handler(Looper.getMainLooper());
         mRegistry = new FingerprintServiceRegistry(mServiceWrapper, biometricServiceSupplier);
         mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
@@ -1136,7 +1087,7 @@
         final String virtualInstance = "virtual";
         final boolean isVirtualHalPresent =
                 fingerprintSensorConfigurations.doesInstanceExist(virtualInstance);
-        if (Utils.isVirtualEnabled(getContext())) {
+        if (Utils.isFingerprintVirtualEnabled(getContext())) {
             if (isVirtualHalPresent) {
                 return new Pair<>(virtualInstance,
                         fingerprintSensorConfigurations.getSensorPropForInstance(virtualInstance));
@@ -1160,74 +1111,6 @@
                 .getSensorPropForInstance(finalSensorInstance));
     }
 
-    private Pair<List<FingerprintSensorPropertiesInternal>, List<String>>
-                filterAvailableHalInstances(
-            @NonNull List<FingerprintSensorPropertiesInternal> hidlInstances,
-            @NonNull List<String> aidlInstances) {
-        if ((hidlInstances.size() + aidlInstances.size()) <= 1) {
-            return new Pair(hidlInstances, aidlInstances);
-        }
-
-        final int virtualAt = aidlInstances.indexOf("virtual");
-        if (Utils.isVirtualEnabled(getContext())) {
-            if (virtualAt != -1) {
-                //only virtual instance should be returned
-                Slog.i(TAG, "virtual hal is used");
-                return new Pair(new ArrayList<>(), List.of(aidlInstances.get(virtualAt)));
-            } else {
-                Slog.e(TAG, "Could not find virtual interface while it is enabled");
-                return new Pair(hidlInstances, aidlInstances);
-            }
-        } else {
-            //remove virtual instance
-            aidlInstances = new ArrayList<>(aidlInstances);
-            if (virtualAt != -1) {
-                aidlInstances.remove(virtualAt);
-            }
-            return new Pair(hidlInstances, aidlInstances);
-        }
-    }
-
-    @NonNull
-    private List<ServiceProvider> getHidlProviders(
-            @NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
-        final List<ServiceProvider> providers = new ArrayList<>();
-
-        for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
-            final Fingerprint21 fingerprint21;
-            if ((Build.IS_USERDEBUG || Build.IS_ENG)
-                    && getContext().getResources().getBoolean(R.bool.allow_test_udfps)
-                    && Settings.Secure.getIntForUser(getContext().getContentResolver(),
-                    Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
-                    UserHandle.USER_CURRENT) != 0) {
-                fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
-                        mBiometricStateCallback, mAuthenticationStateListeners,
-                        hidlSensor, mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
-                        BiometricContext.getInstance(getContext()));
-            } else {
-                fingerprint21 = Fingerprint21.newInstance(getContext(),
-                        mBiometricStateCallback, mAuthenticationStateListeners, hidlSensor,
-                        mHandler, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
-            }
-            providers.add(fingerprint21);
-        }
-
-        return providers;
-    }
-
-    @NonNull
-    private List<ServiceProvider> getAidlProviders(@NonNull List<String> instances) {
-        final List<ServiceProvider> providers = new ArrayList<>();
-
-        for (String instance : instances) {
-            final FingerprintProvider provider = mFingerprintProvider.apply(instance);
-            Slog.i(TAG, "Adding AIDL provider: " + instance);
-            providers.add(provider);
-        }
-
-        return providers;
-    }
-
     @Override
     public void onStart() {
         publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper);
@@ -1295,7 +1178,7 @@
 
     void syncEnrollmentsNow() {
         Utils.checkPermissionOrShell(getContext(), MANAGE_FINGERPRINT);
-        if (Utils.isVirtualEnabled(getContext())) {
+        if (Utils.isFingerprintVirtualEnabled(getContext())) {
             Slog.i(TAG, "Sync virtual enrollments");
             final int userId = ActivityManager.getCurrentUser();
             final CountDownLatch latch = new CountDownLatch(mRegistry.getProviders().size());
@@ -1324,7 +1207,7 @@
     }
 
     void simulateVhalFingerDown() {
-        if (Utils.isVirtualEnabled(getContext())) {
+        if (Utils.isFingerprintVirtualEnabled(getContext())) {
             Slog.i(TAG, "Simulate virtual HAL finger down event");
             final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
             if (provider != null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index c2d1169..a6cf2f4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -28,7 +28,6 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.IBinder;
 
@@ -137,13 +136,6 @@
 
     void onPowerPressed();
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    /**
-     * Sets side-fps controller
-     * @param controller side-fps controller
-     */
-    void setSidefpsController(@NonNull ISidefpsController controller);
-
     @NonNull
     ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
             @NonNull String opPackageName);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java
index bd21cf4..6d1715f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java
@@ -25,7 +25,6 @@
 import android.hardware.keymaster.HardwareAuthToken;
 import android.util.Slog;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.HardwareAuthTokenUtils;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.sensors.AcquisitionClient;
@@ -53,16 +52,6 @@
     /**
      * Interface to send results to the AidlResponseHandler's owner.
      */
-    public interface HardwareUnavailableCallback {
-        /**
-         * Invoked when the HAL sends ERROR_HW_UNAVAILABLE.
-         */
-        void onHardwareUnavailable();
-    }
-
-    /**
-     * Interface to send results to the AidlResponseHandler's owner.
-     */
     public interface AidlResponseHandlerCallback {
         /**
          * Invoked when enrollment is successful.
@@ -90,8 +79,6 @@
     @NonNull
     private final AuthSessionCoordinator mAuthSessionCoordinator;
     @NonNull
-    private final HardwareUnavailableCallback mHardwareUnavailableCallback;
-    @NonNull
     private final AidlResponseHandlerCallback mAidlResponseHandlerCallback;
 
     public AidlResponseHandler(@NonNull Context context,
@@ -99,24 +86,6 @@
             @NonNull LockoutTracker lockoutTracker,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull AuthSessionCoordinator authSessionCoordinator,
-            @NonNull HardwareUnavailableCallback hardwareUnavailableCallback) {
-        this(context, scheduler, sensorId, userId, lockoutTracker, lockoutResetDispatcher,
-                authSessionCoordinator, hardwareUnavailableCallback,
-                new AidlResponseHandlerCallback() {
-                    @Override
-                    public void onEnrollSuccess() {}
-
-                    @Override
-                    public void onHardwareUnavailable() {}
-                });
-    }
-
-    public AidlResponseHandler(@NonNull Context context,
-            @NonNull BiometricScheduler scheduler, int sensorId, int userId,
-            @NonNull LockoutTracker lockoutTracker,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull AuthSessionCoordinator authSessionCoordinator,
-            @NonNull HardwareUnavailableCallback hardwareUnavailableCallback,
             @NonNull AidlResponseHandlerCallback aidlResponseHandlerCallback) {
         mContext = context;
         mScheduler = scheduler;
@@ -125,7 +94,6 @@
         mLockoutTracker = lockoutTracker;
         mLockoutResetDispatcher = lockoutResetDispatcher;
         mAuthSessionCoordinator = authSessionCoordinator;
-        mHardwareUnavailableCallback = hardwareUnavailableCallback;
         mAidlResponseHandlerCallback = aidlResponseHandlerCallback;
     }
 
@@ -171,11 +139,7 @@
         handleResponse(ErrorConsumer.class, (c) -> {
             c.onError(error, vendorCode);
             if (error == Error.HW_UNAVAILABLE) {
-                if (Flags.deHidl()) {
-                    mAidlResponseHandlerCallback.onHardwareUnavailable();
-                } else {
-                    mHardwareUnavailableCallback.onHardwareUnavailable();
-                }
+                mAidlResponseHandlerCallback.onHardwareUnavailable();
             }
         });
     }
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 93d1b6e..f9f56ee 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
@@ -17,8 +17,10 @@
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
 import static android.adaptiveauth.Flags.reportBiometricAuthAttempts;
-
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE;
+import static android.hardware.fingerprint.FingerprintManager.getAcquiredString;
+import static android.hardware.fingerprint.FingerprintManager.getErrorString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -32,22 +34,22 @@
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.ICancellationSignal;
 import android.hardware.biometrics.common.OperationState;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.Build;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.Slog;
 
-import com.android.internal.R;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.CallbackWithProbe;
@@ -67,7 +69,6 @@
 import com.android.server.biometrics.sensors.fingerprint.PowerPressHandler;
 import com.android.server.biometrics.sensors.fingerprint.Udfps;
 
-import java.time.Clock;
 import java.util.ArrayList;
 import java.util.function.Supplier;
 
@@ -79,30 +80,18 @@
         extends AuthenticationClient<AidlSession, FingerprintAuthenticateOptions>
         implements Udfps, LockoutConsumer, PowerPressHandler {
     private static final String TAG = "FingerprintAuthenticationClient";
-    private static final int MESSAGE_AUTH_SUCCESS = 2;
-    private static final int MESSAGE_FINGER_UP = 3;
     @NonNull
     private final SensorOverlays mSensorOverlays;
     @NonNull
     private final FingerprintSensorPropertiesInternal mSensorProps;
     @NonNull
     private final CallbackWithProbe<Probe> mALSProbeCallback;
-    private final Handler mHandler;
-    private final int mSkipWaitForPowerAcquireMessage;
-    private final int mSkipWaitForPowerVendorAcquireMessage;
-    private final long mFingerUpIgnoresPower = 500;
+    private final boolean mIsStrongBiometric;
     private final AuthSessionCoordinator mAuthSessionCoordinator;
     @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
     @Nullable
     private ICancellationSignal mCancellationSignal;
     private boolean mIsPointerDown;
-    private long mWaitForAuthKeyguard;
-    private long mWaitForAuthBp;
-    private long mIgnoreAuthFor;
-    private long mSideFpsLastAcquireStartTime;
-    private Runnable mAuthSuccessRunnable;
-    private final Clock mClock;
-
 
     public FingerprintAuthenticationClient(
             @NonNull Context context,
@@ -120,14 +109,10 @@
             boolean isStrongBiometric,
             @Nullable TaskStackListener taskStackListener,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
-            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-            @Nullable ISidefpsController sidefpsController,
             @NonNull AuthenticationStateListeners authenticationStateListeners,
             boolean allowBackgroundAuthentication,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
-            @NonNull Handler handler,
             @Authenticators.Types int biometricStrength,
-            @NonNull Clock clock,
             @Nullable LockoutTracker lockoutTracker) {
         super(
                 context,
@@ -148,47 +133,12 @@
                 false /* shouldVibrate */,
                 biometricStrength);
         setRequestId(requestId);
-        if (sidefpsControllerRefactor()) {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
-        } else {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
-        }
+        mSensorOverlays = new SensorOverlays(udfpsOverlayController);
         mAuthenticationStateListeners = authenticationStateListeners;
+        mIsStrongBiometric = isStrongBiometric;
         mSensorProps = sensorProps;
         mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
-        mHandler = handler;
-
-        mWaitForAuthKeyguard =
-                context.getResources()
-                        .getInteger(R.integer.config_sidefpsKeyguardPowerPressWindow);
-        mWaitForAuthBp =
-                context.getResources().getInteger(R.integer.config_sidefpsBpPowerPressWindow);
-        mIgnoreAuthFor =
-                context.getResources().getInteger(R.integer.config_sidefpsPostAuthDowntime);
-
-        mSkipWaitForPowerAcquireMessage =
-                context.getResources().getInteger(
-                        R.integer.config_sidefpsSkipWaitForPowerAcquireMessage);
-        mSkipWaitForPowerVendorAcquireMessage =
-                context.getResources().getInteger(
-                        R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage);
         mAuthSessionCoordinator = biometricContext.getAuthSessionCoordinator();
-        mSideFpsLastAcquireStartTime = -1;
-        mClock = clock;
-
-        if (mSensorProps.isAnySidefpsType()) {
-            if (Build.isDebuggable()) {
-                mWaitForAuthKeyguard = Settings.Secure.getIntForUser(context.getContentResolver(),
-                        Settings.Secure.FINGERPRINT_SIDE_FPS_KG_POWER_WINDOW,
-                        (int) mWaitForAuthKeyguard, UserHandle.USER_CURRENT);
-                mWaitForAuthBp = Settings.Secure.getIntForUser(context.getContentResolver(),
-                        Settings.Secure.FINGERPRINT_SIDE_FPS_BP_POWER_WINDOW, (int) mWaitForAuthBp,
-                        UserHandle.USER_CURRENT);
-                mIgnoreAuthFor = Settings.Secure.getIntForUser(context.getContentResolver(),
-                        Settings.Secure.FINGERPRINT_SIDE_FPS_AUTH_DOWNTIME, (int) mIgnoreAuthFor,
-                        UserHandle.USER_CURRENT);
-            }
-        }
     }
 
     @Override
@@ -234,18 +184,22 @@
             mState = STATE_STOPPED;
             resetIgnoreDisplayTouches();
             mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
             if (reportBiometricAuthAttempts()) {
-                mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(),
-                        getTargetUserId());
+                mAuthenticationStateListeners.onAuthenticationSucceeded(
+                        new AuthenticationSucceededInfo.Builder(BiometricSourceType.FINGERPRINT,
+                                getRequestReason(), mIsStrongBiometric, getTargetUserId()).build()
+                );
             }
+            mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                    .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+            );
         } else {
             mState = STATE_STARTED_PAUSED_ATTEMPTED;
             if (reportBiometricAuthAttempts()) {
-                mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(),
-                        getTargetUserId());
+                mAuthenticationStateListeners.onAuthenticationFailed(new AuthenticationFailedInfo
+                        .Builder(BiometricSourceType.FINGERPRINT, getRequestReason(),
+                        getTargetUserId()).build()
+                );
             }
         }
     }
@@ -271,9 +225,12 @@
                 // client.
                 resetIgnoreDisplayTouches();
                 mSensorOverlays.hide(getSensorId());
-                if (sidefpsControllerRefactor()) {
-                    mAuthenticationStateListeners.onAuthenticationStopped();
-                }
+                mAuthenticationStateListeners.onAuthenticationError(
+                        new AuthenticationErrorInfo.Builder(BiometricSourceType.FINGERPRINT,
+                                getRequestReason(),
+                                getErrorString(getContext(), errorCode, 0 /* vendorCode */),
+                                errorCode).build()
+                );
                 onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */);
                 cancel();
             }
@@ -282,10 +239,23 @@
 
     @Override
     public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) {
+        mAuthenticationStateListeners.onAuthenticationAcquired(
+                new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        getRequestReason(), acquiredInfo).build()
+        );
+        if (acquiredInfo != BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START) {
+            String helpMsg = getAcquiredString(getContext(), acquiredInfo, vendorCode);
+            if (helpMsg != null) {
+                int helpCode = acquiredInfo == FINGERPRINT_ACQUIRED_VENDOR
+                        ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquiredInfo;
+                mAuthenticationStateListeners.onAuthenticationHelp(
+                        new AuthenticationHelpInfo.Builder(BiometricSourceType.FINGERPRINT,
+                                getRequestReason(), helpMsg, helpCode).build()
+                );
+            }
+        }
         // For UDFPS, notify SysUI with acquiredInfo, so that the illumination can be turned off
         // for most ACQUIRED messages. See BiometricFingerprintConstants#FingerprintAcquired
-        mAuthenticationStateListeners.onAuthenticationAcquired(
-                BiometricSourceType.FINGERPRINT, getRequestReason(), acquiredInfo);
         mSensorOverlays.ifUdfps(controller -> controller.onAcquired(getSensorId(), acquiredInfo));
         super.onAcquired(acquiredInfo, vendorCode);
         PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId());
@@ -294,6 +264,11 @@
 
     @Override
     public void onError(int errorCode, int vendorCode) {
+        mAuthenticationStateListeners.onAuthenticationError(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        getRequestReason(), getErrorString(getContext(), errorCode, vendorCode),
+                        errorCode).build()
+        );
         super.onError(errorCode, vendorCode);
 
         if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION) {
@@ -302,81 +277,31 @@
 
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+        );
     }
 
     @Override
     protected void startHalOperation() {
         resetIgnoreDisplayTouches();
         mSensorOverlays.show(getSensorId(), getRequestReason(), this);
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStarted(getRequestReason());
-        }
-
+        mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
+                .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+        );
         try {
-            if (Flags.deHidl()) {
-                startAuthentication();
-            } else {
-                mCancellationSignal = doAuthenticate();
-            }
+            doAuthenticate();
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception", e);
             onError(
                     BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                     0 /* vendorCode */);
             mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
             mCallback.onClientFinished(this, false /* success */);
         }
     }
 
-    private ICancellationSignal doAuthenticate() throws RemoteException {
-        final AidlSession session = getFreshDaemon();
-
-        final OperationContextExt opContext = getOperationContext();
-        final ICancellationSignal cancel;
-        if (session.hasContextMethods()) {
-            cancel = session.getSession().authenticateWithContext(
-                    mOperationId, opContext.toAidlContext(getOptions()));
-        } else {
-            cancel = session.getSession().authenticate(mOperationId);
-        }
-
-        getBiometricContext().subscribe(opContext, ctx -> {
-            if (session.hasContextMethods()) {
-                try {
-                    session.getSession().onContextChanged(ctx);
-                    // TODO(b/317414324): Deprecate setIgnoreDisplayTouches
-                    if (ctx.operationState != null && ctx.operationState.getTag()
-                            == OperationState.fingerprintOperationState) {
-                        session.getSession().setIgnoreDisplayTouches(
-                                ctx.operationState.getFingerprintOperationState().isHardwareIgnoringTouches);
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to notify context changed", e);
-                }
-            }
-
-            // TODO(b/243836005): this should come via ctx
-            final boolean isAwake = getBiometricContext().isAwake();
-            if (isAwake) {
-                mALSProbeCallback.getProbe().enable();
-            } else {
-                mALSProbeCallback.getProbe().disable();
-            }
-        });
-        if (getBiometricContext().isAwake()) {
-            mALSProbeCallback.getProbe().enable();
-        }
-
-        return cancel;
-    }
-
-    private void startAuthentication() {
+    private void doAuthenticate() throws RemoteException {
         final AidlSession session = getFreshDaemon();
         final OperationContextExt opContext = getOperationContext();
 
@@ -398,15 +323,18 @@
                         BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                         0 /* vendorCode */);
                 mSensorOverlays.hide(getSensorId());
-                if (sidefpsControllerRefactor()) {
-                    mAuthenticationStateListeners.onAuthenticationStopped();
-                }
                 mCallback.onClientFinished(this, false /* success */);
             }
         }, ctx -> {
             if (session.hasContextMethods()) {
                 try {
                     session.getSession().onContextChanged(ctx);
+                    // TODO(b/317414324): Deprecate setIgnoreDisplayTouches
+                    if (ctx.operationState != null && ctx.operationState.getTag()
+                            == OperationState.fingerprintOperationState) {
+                        session.getSession().setIgnoreDisplayTouches(ctx.operationState
+                                .getFingerprintOperationState().isHardwareIgnoringTouches);
+                    }
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Unable to notify context changed", e);
                 }
@@ -425,9 +353,9 @@
     protected void stopHalOperation() {
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+        );
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
@@ -518,6 +446,10 @@
                 .incrementTimedLockoutForUser(getTargetUserId());
 
         try {
+            mAuthenticationStateListeners.onAuthenticationError(new AuthenticationErrorInfo
+                    .Builder(BiometricSourceType.FINGERPRINT, getRequestReason(),
+                    getErrorString(getContext(), error, 0), error).build()
+            );
             getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception", e);
@@ -525,9 +457,9 @@
 
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+        );
         mCallback.onClientFinished(this, false /* success */);
     }
 
@@ -549,6 +481,10 @@
                 .incrementPermanentLockoutForUser(getTargetUserId());
 
         try {
+            mAuthenticationStateListeners.onAuthenticationError(new AuthenticationErrorInfo
+                    .Builder(BiometricSourceType.FINGERPRINT, getRequestReason(),
+                    getErrorString(getContext(), error, 0), error).build()
+            );
             getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception", e);
@@ -556,9 +492,9 @@
 
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+        );
         mCallback.onClientFinished(this, false /* success */);
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index 8d2b46f..36af5db 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -16,14 +16,14 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.ICancellationSignal;
-import android.hardware.biometrics.common.OperationState;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.IBinder;
@@ -31,11 +31,11 @@
 import android.util.Slog;
 
 import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.sensors.AcquisitionClient;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.DetectionConsumer;
@@ -54,6 +54,9 @@
 
     private final boolean mIsStrongBiometric;
     private final FingerprintAuthenticateOptions mOptions;
+
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
+
     @NonNull private final SensorOverlays mSensorOverlays;
     @Nullable private ICancellationSignal mCancellationSignal;
 
@@ -63,19 +66,16 @@
             @NonNull ClientMonitorCallbackConverter listener,
             @NonNull FingerprintAuthenticateOptions options,
             @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
             boolean isStrongBiometric) {
         super(context, lazyDaemon, token, listener, options.getUserId(),
                 options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
                 true /* shouldVibrate */, biometricLogger, biometricContext);
         setRequestId(requestId);
+        mAuthenticationStateListeners = authenticationStateListeners;
         mIsStrongBiometric = isStrongBiometric;
-        if (sidefpsControllerRefactor()) {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
-        } else {
-            mSensorOverlays = new SensorOverlays(
-                    udfpsOverlayController, null /* sideFpsController */);
-        }
+        mSensorOverlays = new SensorOverlays(udfpsOverlayController);
         mOptions = options;
     }
 
@@ -89,6 +89,10 @@
     protected void stopHalOperation() {
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
+        mAuthenticationStateListeners.onAuthenticationStopped(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
@@ -106,47 +110,24 @@
         resetIgnoreDisplayTouches();
         mSensorOverlays.show(getSensorId(), BiometricRequestConstants.REASON_AUTH_KEYGUARD,
                 this);
-
+        mAuthenticationStateListeners.onAuthenticationStarted(
+            new AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                    BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
         try {
-            if (Flags.deHidl()) {
-                startDetectInteraction();
-            } else {
-                mCancellationSignal = doDetectInteraction();
-            }
+            doDetectInteraction();
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception when requesting finger detect", e);
             mSensorOverlays.hide(getSensorId());
+            mAuthenticationStateListeners.onAuthenticationStopped(
+                    new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                            BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+            );
             mCallback.onClientFinished(this, false /* success */);
         }
     }
 
-    private ICancellationSignal doDetectInteraction() throws RemoteException {
-        final AidlSession session = getFreshDaemon();
-
-        if (session.hasContextMethods()) {
-            final OperationContextExt opContext = getOperationContext();
-            final ICancellationSignal cancel = session.getSession().detectInteractionWithContext(
-                    opContext.toAidlContext(mOptions));
-            getBiometricContext().subscribe(opContext, ctx -> {
-                try {
-                    session.getSession().onContextChanged(ctx);
-                    // TODO(b/317414324): Deprecate setIgnoreDisplayTouches
-                    if (ctx.operationState != null && ctx.operationState.getTag()
-                            == OperationState.fingerprintOperationState) {
-                        session.getSession().setIgnoreDisplayTouches(
-                                ctx.operationState.getFingerprintOperationState().isHardwareIgnoringTouches);
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to notify context changed", e);
-                }
-            });
-            return cancel;
-        } else {
-            return session.getSession().detectInteraction();
-        }
-    }
-
-    private void startDetectInteraction() throws RemoteException {
+    private void doDetectInteraction() throws RemoteException {
         final AidlSession session = getFreshDaemon();
 
         if (session.hasContextMethods()) {
@@ -158,6 +139,12 @@
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Unable to start detect interaction", e);
                     mSensorOverlays.hide(getSensorId());
+                    mAuthenticationStateListeners.onAuthenticationStopped(
+                            new AuthenticationStoppedInfo.Builder(
+                                    BiometricSourceType.FINGERPRINT,
+                                    BiometricRequestConstants.REASON_AUTH_KEYGUARD
+                            ).build()
+                    );
                     mCallback.onClientFinished(this, false /* success */);
                 }
             }, ctx -> {
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 a24ab1d..3a72d7e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -16,7 +16,11 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE;
+import static android.hardware.fingerprint.FingerprintManager.getAcquiredString;
+import static android.hardware.fingerprint.FingerprintManager.getErrorString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -24,15 +28,19 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.BiometricStateListener;
 import android.hardware.biometrics.common.ICancellationSignal;
-import android.hardware.biometrics.common.OperationState;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.hardware.keymaster.HardwareAuthToken;
 import android.os.IBinder;
@@ -40,7 +48,6 @@
 import android.util.Slog;
 import android.view.accessibility.AccessibilityManager;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.HardwareAuthTokenUtils;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
@@ -96,8 +103,6 @@
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
-            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-            @Nullable ISidefpsController sidefpsController,
             @NonNull AuthenticationStateListeners authenticationStateListeners,
             int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason,
             @NonNull FingerprintEnrollOptions options) {
@@ -108,11 +113,7 @@
                 BiometricFingerprintConstants.reasonToMetric(options.getEnrollReason()));
         setRequestId(requestId);
         mSensorProps = sensorProps;
-        if (sidefpsControllerRefactor()) {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
-        } else {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
-        }
+        mSensorOverlays = new SensorOverlays(udfpsOverlayController);
         mAuthenticationStateListeners = authenticationStateListeners;
 
         mMaxTemplatesPerUser = maxTemplatesPerUser;
@@ -151,15 +152,35 @@
         if (remaining == 0) {
             resetIgnoreDisplayTouches();
             mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
+            mAuthenticationStateListeners.onAuthenticationStopped(
+                    new AuthenticationStoppedInfo.Builder(
+                            BiometricSourceType.FINGERPRINT,
+                            getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+            );
         }
 
     }
 
     @Override
     public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) {
+        if (acquiredInfo != FINGERPRINT_ACQUIRED_START) {
+            mAuthenticationStateListeners.onAuthenticationAcquired(
+                    new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FINGERPRINT,
+                            getRequestReasonFromFingerprintEnrollReason(mEnrollReason),
+                            acquiredInfo).build()
+            );
+        }
+        String helpMsg = getAcquiredString(getContext(), acquiredInfo, vendorCode);
+        if (helpMsg != null) {
+            int helpCode = acquiredInfo == FINGERPRINT_ACQUIRED_VENDOR
+                    ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquiredInfo;
+            mAuthenticationStateListeners.onAuthenticationHelp(
+                    new AuthenticationHelpInfo.Builder(BiometricSourceType.FINGERPRINT,
+                            getRequestReasonFromFingerprintEnrollReason(mEnrollReason),
+                            helpMsg, helpCode).build()
+            );
+        }
+
         boolean acquiredGood =
                 acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD;
         // For UDFPS, notify SysUI that the illumination can be turned off.
@@ -183,12 +204,19 @@
 
     @Override
     public void onError(int errorCode, int vendorCode) {
+        mAuthenticationStateListeners.onAuthenticationError(new AuthenticationErrorInfo
+                .Builder(BiometricSourceType.FINGERPRINT,
+                getRequestReasonFromFingerprintEnrollReason(mEnrollReason),
+                getErrorString(getContext(), errorCode, vendorCode), errorCode).build()
+        );
         super.onError(errorCode, vendorCode);
+
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
+        mAuthenticationStateListeners.onAuthenticationStopped(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+        );
     }
 
     @Override
@@ -200,20 +228,16 @@
     @Override
     protected void startHalOperation() {
         resetIgnoreDisplayTouches();
-        mSensorOverlays.show(getSensorId(), getRequestReasonFromEnrollReason(mEnrollReason),
-                this);
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStarted(
-                    getRequestReasonFromEnrollReason(mEnrollReason));
-        }
+        mSensorOverlays.show(getSensorId(),
+                getRequestReasonFromFingerprintEnrollReason(mEnrollReason), this);
+        mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
+                .Builder(BiometricSourceType.FINGERPRINT,
+                getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+        );
 
         BiometricNotificationUtils.cancelBadCalibrationNotification(getContext());
         try {
-            if (Flags.deHidl()) {
-                startEnroll();
-            } else {
-                mCancellationSignal = doEnroll();
-            }
+            doEnroll();
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception when requesting enroll", e);
             onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
@@ -222,35 +246,7 @@
         }
     }
 
-    private ICancellationSignal doEnroll() throws RemoteException {
-        final AidlSession session = getFreshDaemon();
-        final HardwareAuthToken hat =
-                HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken);
-
-        if (session.hasContextMethods()) {
-            final OperationContextExt opContext = getOperationContext();
-            final ICancellationSignal cancel = session.getSession().enrollWithContext(
-                    hat, opContext.toAidlContext());
-            getBiometricContext().subscribe(opContext, ctx -> {
-                try {
-                    session.getSession().onContextChanged(ctx);
-                    // TODO(b/317414324): Deprecate setIgnoreDisplayTouches
-                    if (ctx.operationState != null && ctx.operationState.getTag()
-                            == OperationState.fingerprintOperationState) {
-                        session.getSession().setIgnoreDisplayTouches(
-                                ctx.operationState.getFingerprintOperationState().isHardwareIgnoringTouches);
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to notify context changed", e);
-                }
-            });
-            return cancel;
-        } else {
-            return session.getSession().enroll(hat);
-        }
-    }
-
-    private void startEnroll() throws RemoteException {
+    private void doEnroll() throws RemoteException {
         final AidlSession session = getFreshDaemon();
         final HardwareAuthToken hat =
                 HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken);
@@ -283,9 +279,10 @@
     protected void stopHalOperation() {
         resetIgnoreDisplayTouches();
         mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
+        mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+                .Builder(BiometricSourceType.FINGERPRINT,
+                getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+        );
 
         unsubscribeBiometricContext();
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 9290f8a..6874c71 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -29,13 +29,12 @@
 import android.content.res.TypedArray;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.IInvalidationCallback;
 import android.hardware.biometrics.ITestSession;
 import android.hardware.biometrics.ITestSessionCallback;
 import android.hardware.biometrics.SensorLocationInternal;
-import android.hardware.biometrics.common.ComponentInfo;
 import android.hardware.biometrics.fingerprint.IFingerprint;
+import android.hardware.biometrics.fingerprint.IVirtualHal;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.biometrics.fingerprint.SensorProps;
 import android.hardware.fingerprint.Fingerprint;
@@ -44,16 +43,13 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -96,10 +92,8 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.stream.Collectors;
 
 /**
  * Provider for a single instance of the {@link IFingerprint} HAL.
@@ -136,10 +130,10 @@
     @NonNull private final BiometricHandlerProvider mBiometricHandlerProvider;
     @Nullable private IFingerprint mDaemon;
     @Nullable private IUdfpsOverlayController mUdfpsOverlayController;
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Nullable private ISidefpsController mSidefpsController;
     private final AuthSessionCoordinator mAuthSessionCoordinator;
     @Nullable private AuthenticationStatsCollector mAuthenticationStatsCollector;
+    @Nullable private IVirtualHal mVhal;
+    @Nullable private String mHalInstanceNameCurrent;
 
     private final class BiometricTaskStackListener extends TaskStackListener {
         @Override
@@ -200,11 +194,7 @@
         mAuthenticationStateListeners = authenticationStateListeners;
         mHalInstanceName = halInstanceName;
         mFingerprintSensors = new SensorList<>(ActivityManager.getService());
-        if (Flags.deHidl()) {
-            mHandler = biometricHandlerProvider.getFingerprintHandler();
-        } else {
-            mHandler = new Handler(Looper.getMainLooper());
-        }
+        mHandler = biometricHandlerProvider.getFingerprintHandler();
         mLockoutResetDispatcher = lockoutResetDispatcher;
         mActivityTaskManager = ActivityTaskManager.getInstance();
         mTaskStackListener = new BiometricTaskStackListener();
@@ -230,66 +220,19 @@
 
     private void initSensors(boolean resetLockoutRequiresHardwareAuthToken, SensorProps[] props,
             GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
-        if (Flags.deHidl()) {
-            if (!resetLockoutRequiresHardwareAuthToken) {
-                Slog.d(getTag(), "Adding HIDL configs");
-                for (SensorProps sensorConfig: props) {
-                    addHidlSensors(sensorConfig, gestureAvailabilityDispatcher,
-                            resetLockoutRequiresHardwareAuthToken);
-                }
-            } else {
-                Slog.d(getTag(), "Adding AIDL configs");
-                final List<SensorLocationInternal> workaroundLocations =
-                        getWorkaroundSensorProps(mContext);
-                for (SensorProps prop : props) {
-                    addAidlSensors(prop, gestureAvailabilityDispatcher, workaroundLocations,
-                            resetLockoutRequiresHardwareAuthToken);
-                }
+        if (!resetLockoutRequiresHardwareAuthToken) {
+            Slog.d(getTag(), "Adding HIDL configs");
+            for (SensorProps sensorConfig: props) {
+                addHidlSensors(sensorConfig, gestureAvailabilityDispatcher,
+                        resetLockoutRequiresHardwareAuthToken);
             }
         } else {
+            Slog.d(getTag(), "Adding AIDL configs");
             final List<SensorLocationInternal> workaroundLocations =
                     getWorkaroundSensorProps(mContext);
-
             for (SensorProps prop : props) {
-                final int sensorId = prop.commonProps.sensorId;
-                final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
-                if (prop.commonProps.componentInfo != null) {
-                    for (ComponentInfo info : prop.commonProps.componentInfo) {
-                        componentInfo.add(new ComponentInfoInternal(info.componentId,
-                                info.hardwareVersion, info.firmwareVersion, info.serialNumber,
-                                info.softwareVersion));
-                    }
-                }
-                final FingerprintSensorPropertiesInternal internalProp =
-                        new FingerprintSensorPropertiesInternal(prop.commonProps.sensorId,
-                                prop.commonProps.sensorStrength,
-                                prop.commonProps.maxEnrollmentsPerUser,
-                                componentInfo,
-                                prop.sensorType,
-                                prop.halControlsIllumination,
-                                true /* resetLockoutRequiresHardwareAuthToken */,
-                                !workaroundLocations.isEmpty() ? workaroundLocations :
-                                        Arrays.stream(prop.sensorLocations).map(
-                                                        location -> new SensorLocationInternal(
-                                                                location.display,
-                                                                location.sensorLocationX,
-                                                                location.sensorLocationY,
-                                                                location.sensorRadius))
-                                                .collect(Collectors.toList()));
-                final Sensor sensor = new Sensor(this, mContext, mHandler, internalProp,
-                        mBiometricContext);
-                sensor.init(gestureAvailabilityDispatcher, mLockoutResetDispatcher);
-                final int sessionUserId =
-                        sensor.getLazySession().get() == null ? UserHandle.USER_NULL :
-                                sensor.getLazySession().get().getUserId();
-                mFingerprintSensors.addSensor(sensorId, sensor, sessionUserId,
-                        new SynchronousUserSwitchObserver() {
-                            @Override
-                            public void onUserSwitching(int newUserId) {
-                                scheduleInternalCleanup(sensorId, newUserId, null /* callback */);
-                            }
-                        });
-                Slog.d(getTag(), "Added: " + mFingerprintSensors.get(sensorId).toString());
+                addAidlSensors(prop, gestureAvailabilityDispatcher, workaroundLocations,
+                        resetLockoutRequiresHardwareAuthToken);
             }
         }
     }
@@ -351,10 +294,29 @@
     @VisibleForTesting
     synchronized IFingerprint getHalInstance() {
         if (mTestHalEnabled) {
-            // Enabling the test HAL for a single sensor in a multi-sensor HAL currently enables
-            // the test HAL for all sensors under that HAL. This can be updated in the future if
-            // necessary.
-            return new TestHal();
+            if (Flags.useVhalForTesting()) {
+                if (!mHalInstanceNameCurrent.contains("virtual")) {
+                    Slog.i(getTag(), "Switching fingerprint hal from " + mHalInstanceName
+                            + " to virtual hal");
+                    mHalInstanceNameCurrent = "virtual";
+                    mDaemon = null;
+                }
+            } else {
+                // Enabling the test HAL for a single sensor in a multi-sensor HAL currently enables
+                // the test HAL for all sensors under that HAL. This can be updated in the future if
+                // necessary.
+                return new TestHal();
+            }
+        } else {
+            if (mHalInstanceNameCurrent == null) {
+                mHalInstanceNameCurrent = mHalInstanceName;
+            } else if (mHalInstanceNameCurrent.contains("virtual")
+                    && mHalInstanceNameCurrent != mHalInstanceName) {
+                Slog.i(getTag(), "Switching fingerprint from virtual hal " + "to "
+                        + mHalInstanceName);
+                mHalInstanceNameCurrent = mHalInstanceName;
+                mDaemon = null;
+            }
         }
 
         if (mDaemon != null) {
@@ -366,7 +328,7 @@
         mDaemon = IFingerprint.Stub.asInterface(
                 Binder.allowBlocking(
                         ServiceManager.waitForDeclaredService(
-                                IFingerprint.DESCRIPTOR + "/" + mHalInstanceName)));
+                                IFingerprint.DESCRIPTOR + "/" + mHalInstanceNameCurrent)));
         if (mDaemon == null) {
             Slog.e(getTag(), "Unable to get daemon");
             return null;
@@ -544,25 +506,9 @@
                             BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
                     mBiometricContext,
                     mFingerprintSensors.get(sensorId).getSensorProperties(),
-                    mUdfpsOverlayController, mSidefpsController,
-                    mAuthenticationStateListeners, maxTemplatesPerUser, enrollReason, options);
-            if (Flags.deHidl()) {
-                scheduleForSensor(sensorId, client, mBiometricStateCallback);
-            } else {
-                scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(
-                        mBiometricStateCallback, new ClientMonitorCallback() {
-                            @Override
-                            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                                    boolean success) {
-                                ClientMonitorCallback.super.onClientFinished(
-                                        clientMonitor, success);
-                                if (success) {
-                                    scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
-                                    scheduleInvalidationRequest(sensorId, userId);
-                                }
-                            }
-                        }));
-            }
+                    mUdfpsOverlayController, mAuthenticationStateListeners, maxTemplatesPerUser,
+                    enrollReason, options);
+            scheduleForSensor(sensorId, client, mBiometricStateCallback);
         });
         return id;
     }
@@ -588,7 +534,8 @@
                     options,
                     createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
                             mAuthenticationStatsCollector),
-                    mBiometricContext, mUdfpsOverlayController, isStrongBiometric);
+                    mBiometricContext, mAuthenticationStateListeners, mUdfpsOverlayController,
+                    isStrongBiometric);
             scheduleForSensor(sensorId, client, mBiometricStateCallback);
         });
 
@@ -605,13 +552,8 @@
             final int userId = options.getUserId();
             final int sensorId = options.getSensorId();
             final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
-            final LockoutTracker lockoutTracker;
-            if (Flags.deHidl()) {
-                lockoutTracker = mFingerprintSensors.get(sensorId)
-                        .getLockoutTracker(true /* forAuth */);
-            } else {
-                lockoutTracker = null;
-            }
+            final LockoutTracker lockoutTracker = mFingerprintSensors.get(sensorId)
+                    .getLockoutTracker(true /* forAuth */);
             final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
                     mContext, mFingerprintSensors.get(sensorId).getLazySession(), token, requestId,
                     callback, operationId, restricted, options, cookie,
@@ -620,24 +562,18 @@
                             mAuthenticationStatsCollector),
                     mBiometricContext, isStrongBiometric,
                     mTaskStackListener,
-                    mUdfpsOverlayController, mSidefpsController,
-                    mAuthenticationStateListeners, allowBackgroundAuthentication,
-                    mFingerprintSensors.get(sensorId).getSensorProperties(), mHandler,
+                    mUdfpsOverlayController, mAuthenticationStateListeners,
+                    allowBackgroundAuthentication,
+                    mFingerprintSensors.get(sensorId).getSensorProperties(),
                     Utils.getCurrentStrength(sensorId),
-                    SystemClock.elapsedRealtimeClock(),
                     lockoutTracker);
             scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
 
                 @Override
                 public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
                     mBiometricStateCallback.onClientStarted(clientMonitor);
-                    if (Flags.deHidl()) {
-                        mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
-                                mAuthSessionCoordinator.authStartedFor(userId, sensorId,
-                                        requestId));
-                    } else {
-                        mAuthSessionCoordinator.authStartedFor(userId, sensorId, requestId);
-                    }
+                    mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
+                            mAuthSessionCoordinator.authStartedFor(userId, sensorId, requestId));
                 }
 
                 @Override
@@ -649,15 +585,10 @@
                 public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
                         boolean success) {
                     mBiometricStateCallback.onClientFinished(clientMonitor, success);
-                    if (Flags.deHidl()) {
-                        mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
-                                mAuthSessionCoordinator.authEndedFor(userId,
-                                        Utils.getCurrentStrength(sensorId), sensorId, requestId,
-                                        success));
-                    } else {
-                        mAuthSessionCoordinator.authEndedFor(userId,
-                                Utils.getCurrentStrength(sensorId), sensorId, requestId, success);
-                    }
+                    mBiometricHandlerProvider.getBiometricCallbackHandler().post(() ->
+                            mAuthSessionCoordinator.authEndedFor(userId,
+                                    Utils.getCurrentStrength(sensorId), sensorId, requestId,
+                                    success));
                 }
             });
 
@@ -764,10 +695,7 @@
 
     @Override
     public boolean isHardwareDetected(int sensorId) {
-        if (Flags.deHidl()) {
-            return mFingerprintSensors.get(sensorId).isHardwareDetected(mHalInstanceName);
-        }
-        return hasHalInstance();
+        return mFingerprintSensors.get(sensorId).isHardwareDetected(mHalInstanceName);
     }
 
     @Override
@@ -805,12 +733,7 @@
 
     @Override
     public int getLockoutModeForUser(int sensorId, int userId) {
-        if (Flags.deHidl()) {
-            return mFingerprintSensors.get(sensorId).getLockoutModeForUser(userId);
-        } else {
-            return mBiometricContext.getAuthSessionCoordinator().getLockoutStateFor(userId,
-                    Utils.getCurrentStrength(sensorId));
-        }
+        return mFingerprintSensors.get(sensorId).getLockoutModeForUser(userId);
     }
 
     @Override
@@ -875,12 +798,6 @@
         }
     }
 
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Override
-    public void setSidefpsController(@NonNull ISidefpsController controller) {
-        mSidefpsController = controller;
-    }
-
     @Override
     public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
             boolean clearSchedulerBuffer) {
@@ -1050,4 +967,26 @@
     public void sendFingerprintReEnrollNotification() {
         mAuthenticationStatsCollector.sendFingerprintReEnrollNotification();
     }
+
+    /**
+     * Return virtual hal AIDL interface if it is used for testing
+     *
+     */
+    public IVirtualHal getVhal() throws RemoteException {
+        if (mVhal == null && useVhalForTesting()) {
+            mVhal = IVirtualHal.Stub.asInterface(mDaemon.asBinder().getExtension());
+            if (mVhal == null) {
+                Slog.e(getTag(), "Unable to get virtual hal interface");
+            }
+        }
+
+        return mVhal;
+    }
+
+    /**
+     * Return true if vhal_for_testing feature is enabled and test is active
+     */
+    public boolean useVhalForTesting() {
+        return (Flags.useVhalForTesting() && mTestHalEnabled);
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index af88c62..b7e3f70 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -42,7 +42,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.SensorServiceStateProto;
 import com.android.server.biometrics.SensorStateProto;
 import com.android.server.biometrics.UserStateProto;
@@ -58,7 +57,6 @@
 import com.android.server.biometrics.sensors.LockoutTracker;
 import com.android.server.biometrics.sensors.StartUserClient;
 import com.android.server.biometrics.sensors.StopUserClient;
-import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
 import com.android.server.biometrics.sensors.UserSwitchProvider;
 import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
@@ -110,13 +108,6 @@
     }
 
     Sensor(@NonNull FingerprintProvider provider, @NonNull Context context,
-            @NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties,
-            @NonNull BiometricContext biometricContext) {
-        this(provider, context, handler, sensorProperties,
-                biometricContext, null);
-    }
-
-    Sensor(@NonNull FingerprintProvider provider, @NonNull Context context,
             @NonNull Handler handler, @NonNull SensorProps sensorProp,
             @NonNull BiometricContext biometricContext,
             @NonNull List<SensorLocationInternal> workaroundLocation,
@@ -131,13 +122,8 @@
      */
     public void init(@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher) {
-        if (Flags.deHidl()) {
-            setScheduler(getBiometricSchedulerForInit(gestureAvailabilityDispatcher,
-                    lockoutResetDispatcher));
-        } else {
-            setScheduler(getUserAwareBiometricSchedulerForInit(gestureAvailabilityDispatcher,
-                    lockoutResetDispatcher));
-        }
+        setScheduler(getBiometricSchedulerForInit(gestureAvailabilityDispatcher,
+                lockoutResetDispatcher));
         mLockoutTracker = new LockoutCache();
         mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
     }
@@ -168,7 +154,7 @@
                         final AidlResponseHandler resultController = new AidlResponseHandler(
                                 mContext, mScheduler, sensorId, newUserId,
                                 mLockoutTracker, lockoutResetDispatcher,
-                                mBiometricContext.getAuthSessionCoordinator(), () -> {},
+                                mBiometricContext.getAuthSessionCoordinator(),
                                 new AidlResponseHandler.AidlResponseHandlerCallback() {
                                     @Override
                                     public void onEnrollSuccess() {
@@ -192,45 +178,6 @@
                 });
     }
 
-    private UserAwareBiometricScheduler<ISession, AidlSession>
-            getUserAwareBiometricSchedulerForInit(
-                    GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
-                    LockoutResetDispatcher lockoutResetDispatcher) {
-        return new UserAwareBiometricScheduler<>(TAG,
-                BiometricScheduler.sensorTypeFromFingerprintProperties(mSensorProperties),
-                gestureAvailabilityDispatcher,
-                () -> mCurrentSession != null ? mCurrentSession.getUserId() : UserHandle.USER_NULL,
-                new UserAwareBiometricScheduler.UserSwitchCallback() {
-                    @NonNull
-                    @Override
-                    public StopUserClient<ISession> getStopUserClient(int userId) {
-                        return new FingerprintStopUserClient(mContext,
-                                () -> mLazySession.get().getSession(), mToken,
-                                userId, mSensorProperties.sensorId,
-                                BiometricLogger.ofUnknown(mContext), mBiometricContext,
-                                () -> mCurrentSession = null);
-                    }
-
-                    @NonNull
-                    @Override
-                    public StartUserClient<IFingerprint, ISession> getStartUserClient(
-                            int newUserId) {
-                        final int sensorId = mSensorProperties.sensorId;
-
-                        final AidlResponseHandler resultController = new AidlResponseHandler(
-                                mContext, mScheduler, sensorId, newUserId,
-                                mLockoutTracker, lockoutResetDispatcher,
-                                mBiometricContext.getAuthSessionCoordinator(), () -> {
-                                    Slog.e(TAG, "Fingerprint hardware unavailable.");
-                                    mCurrentSession = null;
-                                });
-
-                        return Sensor.this.getStartUserClient(resultController, sensorId,
-                                newUserId);
-                    }
-                });
-    }
-
     private FingerprintStartUserClient getStartUserClient(AidlResponseHandler resultController,
             int sensorId, int newUserId) {
         final StartUserClient.UserStartedCallback<ISession> userStartedCallback =
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
deleted file mode 100644
index fc037ae..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.ITestSession;
-import android.hardware.biometrics.ITestSessionCallback;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintEnrollOptions;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * A test session implementation for the {@link Fingerprint21} provider. See
- * {@link android.hardware.biometrics.BiometricTestSession}.
- */
-public class BiometricTestSessionImpl extends ITestSession.Stub {
-
-    private static final String TAG = "BiometricTestSessionImpl";
-
-    @NonNull private final Context mContext;
-    private final int mSensorId;
-    @NonNull private final ITestSessionCallback mCallback;
-    @NonNull private final BiometricStateCallback mBiometricStateCallback;
-    @NonNull private final Fingerprint21 mFingerprint21;
-    @NonNull private final Fingerprint21.HalResultController mHalResultController;
-    @NonNull private final Set<Integer> mEnrollmentIds;
-    @NonNull private final Random mRandom;
-
-    /**
-     * Internal receiver currently only used for enroll. Results do not need to be forwarded to the
-     * test, since enrollment is a platform-only API. The authentication path is tested through
-     * the public FingerprintManager APIs and does not use this receiver.
-     */
-    private final IFingerprintServiceReceiver mReceiver = new IFingerprintServiceReceiver.Stub() {
-        @Override
-        public void onEnrollResult(Fingerprint fp, int remaining) {
-
-        }
-
-        @Override
-        public void onAcquired(int acquiredInfo, int vendorCode) {
-
-        }
-
-        @Override
-        public void onAuthenticationSucceeded(Fingerprint fp, int userId,
-                boolean isStrongBiometric) {
-
-        }
-
-        @Override
-        public void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) {
-
-        }
-
-        @Override
-        public void onAuthenticationFailed() {
-
-        }
-
-        @Override
-        public void onError(int error, int vendorCode) {
-
-        }
-
-        @Override
-        public void onRemoved(Fingerprint fp, int remaining) {
-
-        }
-
-        @Override
-        public void onChallengeGenerated(int sensorId, int userId, long challenge) {
-
-        }
-
-        @Override
-        public void onUdfpsPointerDown(int sensorId) {
-
-        }
-
-        @Override
-        public void onUdfpsPointerUp(int sensorId) {
-
-        }
-
-        @Override
-        public void onUdfpsOverlayShown() {
-
-        }
-    };
-
-    BiometricTestSessionImpl(@NonNull Context context, int sensorId,
-            @NonNull ITestSessionCallback callback,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull Fingerprint21 fingerprint21,
-            @NonNull Fingerprint21.HalResultController halResultController) {
-        mContext = context;
-        mSensorId = sensorId;
-        mCallback = callback;
-        mFingerprint21 = fingerprint21;
-        mBiometricStateCallback = biometricStateCallback;
-        mHalResultController = halResultController;
-        mEnrollmentIds = new HashSet<>();
-        mRandom = new Random();
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void setTestHalEnabled(boolean enabled) {
-
-        super.setTestHalEnabled_enforcePermission();
-
-        mFingerprint21.setTestHalEnabled(enabled);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void startEnroll(int userId) {
-
-        super.startEnroll_enforcePermission();
-
-        mFingerprint21.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
-                mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL,
-                (new FingerprintEnrollOptions.Builder()).build());
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void finishEnroll(int userId) {
-
-        super.finishEnroll_enforcePermission();
-
-        int nextRandomId = mRandom.nextInt();
-        while (mEnrollmentIds.contains(nextRandomId)) {
-            nextRandomId = mRandom.nextInt();
-        }
-
-        mEnrollmentIds.add(nextRandomId);
-        mHalResultController.onEnrollResult(0 /* deviceId */,
-                nextRandomId /* fingerId */, userId, 0);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void acceptAuthentication(int userId)  {
-
-        // Fake authentication with any of the existing fingers
-        super.acceptAuthentication_enforcePermission();
-
-        List<Fingerprint> fingerprints = FingerprintUtils.getLegacyInstance(mSensorId)
-                .getBiometricsForUser(mContext, userId);
-        if (fingerprints.isEmpty()) {
-            Slog.w(TAG, "No fingerprints, returning");
-            return;
-        }
-        final int fid = fingerprints.get(0).getBiometricId();
-        final ArrayList<Byte> hat = new ArrayList<>(Collections.nCopies(69, (byte) 0));
-        mHalResultController.onAuthenticated(0 /* deviceId */, fid, userId, hat);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void rejectAuthentication(int userId)  {
-
-        super.rejectAuthentication_enforcePermission();
-
-        mHalResultController.onAuthenticated(0 /* deviceId */, 0 /* fingerId */, userId, null);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void notifyAcquired(int userId, int acquireInfo)  {
-
-        super.notifyAcquired_enforcePermission();
-
-        mHalResultController.onAcquired(0 /* deviceId */, acquireInfo, 0 /* vendorCode */);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void notifyError(int userId, int errorCode)  {
-
-        super.notifyError_enforcePermission();
-
-        mHalResultController.onError(0 /* deviceId */, errorCode, 0 /* vendorCode */);
-    }
-
-    @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
-    @Override
-    public void cleanupInternalState(int userId)  {
-
-        super.cleanupInternalState_enforcePermission();
-
-        mFingerprint21.scheduleInternalCleanup(mSensorId, userId, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                try {
-                    mCallback.onCleanupStarted(clientMonitor.getTargetUserId());
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                try {
-                    mCallback.onCleanupFinished(clientMonitor.getTargetUserId());
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                }
-            }
-        });
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
deleted file mode 100644
index 33e448b..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ /dev/null
@@ -1,1289 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.app.SynchronousUserSwitchObserver;
-import android.app.TaskStackListener;
-import android.app.UserSwitchObserver;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.biometrics.IInvalidationCallback;
-import android.hardware.biometrics.ITestSession;
-import android.hardware.biometrics.ITestSessionCallback;
-import android.hardware.biometrics.fingerprint.PointerContext;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.biometrics.fingerprint.V2_2.IBiometricsFingerprintClientCallback;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintAuthenticateOptions;
-import android.hardware.fingerprint.FingerprintEnrollOptions;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintSensorProperties;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
-import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.IHwBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.biometrics.AuthenticationStatsBroadcastReceiver;
-import com.android.server.biometrics.AuthenticationStatsCollector;
-import com.android.server.biometrics.Flags;
-import com.android.server.biometrics.SensorServiceStateProto;
-import com.android.server.biometrics.SensorStateProto;
-import com.android.server.biometrics.UserStateProto;
-import com.android.server.biometrics.Utils;
-import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto;
-import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto;
-import com.android.server.biometrics.fingerprint.PerformanceStatsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.AcquisitionClient;
-import com.android.server.biometrics.sensors.AuthSessionCoordinator;
-import com.android.server.biometrics.sensors.AuthenticationClient;
-import com.android.server.biometrics.sensors.AuthenticationConsumer;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
-import com.android.server.biometrics.sensors.EnumerateConsumer;
-import com.android.server.biometrics.sensors.ErrorConsumer;
-import com.android.server.biometrics.sensors.LockoutCache;
-import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-import com.android.server.biometrics.sensors.LockoutTracker;
-import com.android.server.biometrics.sensors.PerformanceTracker;
-import com.android.server.biometrics.sensors.RemovalConsumer;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
-import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
-import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
-import com.android.server.biometrics.sensors.fingerprint.Udfps;
-import com.android.server.biometrics.sensors.fingerprint.aidl.AidlResponseHandler;
-import com.android.server.biometrics.sensors.fingerprint.aidl.AidlSession;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Supplier;
-
-/**
- * Supports a single instance of the {@link android.hardware.biometrics.fingerprint.V2_1} or
- * its extended minor versions.
- */
-public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider {
-
-    private static final String TAG = "Fingerprint21";
-    private static final int ENROLL_TIMEOUT_SEC = 60;
-
-    private boolean mTestHalEnabled;
-
-    final Context mContext;
-    @NonNull private final BiometricStateCallback mBiometricStateCallback;
-    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
-    private final ActivityTaskManager mActivityTaskManager;
-    @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
-    private final BiometricScheduler<IBiometricsFingerprint, AidlSession> mScheduler;
-    private final Handler mHandler;
-    private final LockoutResetDispatcher mLockoutResetDispatcher;
-    private final LockoutFrameworkImpl mLockoutTracker;
-    private final BiometricTaskStackListener mTaskStackListener;
-    private final Supplier<IBiometricsFingerprint> mLazyDaemon;
-    private final Map<Integer, Long> mAuthenticatorIds;
-
-    @Nullable private IBiometricsFingerprint mDaemon;
-    @NonNull private final HalResultController mHalResultController;
-    @Nullable private IUdfpsOverlayController mUdfpsOverlayController;
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Nullable private ISidefpsController mSidefpsController;
-    @NonNull private final BiometricContext mBiometricContext;
-    @Nullable private AuthenticationStatsCollector mAuthenticationStatsCollector;
-    // for requests that do not use biometric prompt
-    @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0);
-    private int mCurrentUserId = UserHandle.USER_NULL;
-    private final boolean mIsUdfps;
-    private final int mSensorId;
-    private final boolean mIsPowerbuttonFps;
-    private AidlSession mSession;
-
-    private final class BiometricTaskStackListener extends TaskStackListener {
-        @Override
-        public void onTaskStackChanged() {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof AuthenticationClient)) {
-                    Slog.e(TAG, "Task stack changed for client: " + client);
-                    return;
-                }
-                if (Utils.isKeyguard(mContext, client.getOwnerString())
-                        || Utils.isSystem(mContext, client.getOwnerString())) {
-                    return; // Keyguard is always allowed
-                }
-
-                if (Utils.isBackground(client.getOwnerString())
-                        && !client.isAlreadyDone()) {
-                    Slog.e(TAG, "Stopping background authentication,"
-                            + " currentClient: " + client);
-                    mScheduler.cancelAuthenticationOrDetection(
-                            client.getToken(), client.getRequestId());
-                }
-            });
-        }
-    }
-
-    private final LockoutFrameworkImpl.LockoutResetCallback mLockoutResetCallback =
-            new LockoutFrameworkImpl.LockoutResetCallback() {
-                @Override
-                public void onLockoutReset(int userId) {
-                    mLockoutResetDispatcher.notifyLockoutResetCallbacks(mSensorProperties.sensorId);
-                }
-            };
-
-    private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
-        @Override
-        public void onUserSwitching(int newUserId) {
-            scheduleInternalCleanup(newUserId, null /* callback */);
-        }
-    };
-
-    public static class HalResultController extends IBiometricsFingerprintClientCallback.Stub {
-
-        /**
-         * Interface to sends results to the HalResultController's owner.
-         */
-        public interface Callback {
-            /**
-             * Invoked when the HAL sends ERROR_HW_UNAVAILABLE.
-             */
-            void onHardwareUnavailable();
-        }
-
-        private final int mSensorId;
-        @NonNull private final Context mContext;
-        @NonNull final Handler mHandler;
-        @NonNull final BiometricScheduler<IBiometricsFingerprint, AidlSession> mScheduler;
-        @Nullable private Callback mCallback;
-
-        HalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler,
-                @NonNull BiometricScheduler<IBiometricsFingerprint, AidlSession> scheduler) {
-            mSensorId = sensorId;
-            mContext = context;
-            mHandler = handler;
-            mScheduler = scheduler;
-        }
-
-        public void setCallback(@Nullable Callback callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof FingerprintEnrollClient)) {
-                    Slog.e(TAG, "onEnrollResult for non-enroll client: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final int currentUserId = client.getTargetUserId();
-                final CharSequence name = FingerprintUtils.getLegacyInstance(mSensorId)
-                        .getUniqueName(mContext, currentUserId);
-                final Fingerprint fingerprint = new Fingerprint(name, groupId, fingerId, deviceId);
-
-                final FingerprintEnrollClient enrollClient = (FingerprintEnrollClient) client;
-                enrollClient.onEnrollResult(fingerprint, remaining);
-            });
-        }
-
-        @Override
-        public void onAcquired(long deviceId, int acquiredInfo, int vendorCode) {
-            onAcquired_2_2(deviceId, acquiredInfo, vendorCode);
-        }
-
-        @Override
-        public void onAcquired_2_2(long deviceId, int acquiredInfo, int vendorCode) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof AcquisitionClient)) {
-                    Slog.e(TAG, "onAcquired for non-acquisition client: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final AcquisitionClient<?> acquisitionClient = (AcquisitionClient<?>) client;
-                acquisitionClient.onAcquired(acquiredInfo, vendorCode);
-            });
-        }
-
-        @Override
-        public void onAuthenticated(long deviceId, int fingerId, int groupId,
-                ArrayList<Byte> token) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof AuthenticationConsumer)) {
-                    Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final AuthenticationConsumer authenticationConsumer =
-                        (AuthenticationConsumer) client;
-                final boolean authenticated = fingerId != 0;
-                final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
-                authenticationConsumer.onAuthenticated(fp, authenticated, token);
-            });
-        }
-
-        @Override
-        public void onError(long deviceId, int error, int vendorCode) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                Slog.d(TAG, "handleError"
-                        + ", client: " + Utils.getClientName(client)
-                        + ", error: " + error
-                        + ", vendorCode: " + vendorCode);
-                if (!(client instanceof ErrorConsumer)) {
-                    Slog.e(TAG, "onError for non-error consumer: " + Utils.getClientName(client));
-                    return;
-                }
-
-                final ErrorConsumer errorConsumer = (ErrorConsumer) client;
-                errorConsumer.onError(error, vendorCode);
-
-                if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
-                    Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE");
-                    if (mCallback != null) {
-                        mCallback.onHardwareUnavailable();
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
-            mHandler.post(() -> {
-                Slog.d(TAG, "Removed, fingerId: " + fingerId + ", remaining: " + remaining);
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof RemovalConsumer)) {
-                    Slog.e(TAG, "onRemoved for non-removal consumer: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
-                final RemovalConsumer removalConsumer = (RemovalConsumer) client;
-                removalConsumer.onRemoved(fp, remaining);
-            });
-        }
-
-        @Override
-        public void onEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof EnumerateConsumer)) {
-                    Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
-                            + Utils.getClientName(client));
-                    return;
-                }
-
-                final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
-                final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client;
-                enumerateConsumer.onEnumerationResult(fp, remaining);
-            });
-        }
-    }
-
-    @VisibleForTesting
-    Fingerprint21(@NonNull Context context,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @NonNull FingerprintSensorPropertiesInternal sensorProps,
-            @NonNull BiometricScheduler<IBiometricsFingerprint, AidlSession> scheduler,
-            @NonNull Handler handler,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull HalResultController controller,
-            @NonNull BiometricContext biometricContext) {
-        mContext = context;
-        mBiometricStateCallback = biometricStateCallback;
-        mAuthenticationStateListeners = authenticationStateListeners;
-        mBiometricContext = biometricContext;
-
-        mSensorProperties = sensorProps;
-        mSensorId = sensorProps.sensorId;
-        mIsUdfps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
-                || sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
-        mIsPowerbuttonFps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON;
-
-        mScheduler = scheduler;
-        mHandler = handler;
-        mActivityTaskManager = ActivityTaskManager.getInstance();
-        mTaskStackListener = new BiometricTaskStackListener();
-        mAuthenticatorIds = Collections.synchronizedMap(new HashMap<>());
-        mLazyDaemon = Fingerprint21.this::getDaemon;
-        mLockoutResetDispatcher = lockoutResetDispatcher;
-        mLockoutTracker = new LockoutFrameworkImpl(context, mLockoutResetCallback);
-        mHalResultController = controller;
-        mHalResultController.setCallback(() -> {
-            mDaemon = null;
-            mCurrentUserId = UserHandle.USER_NULL;
-        });
-
-        AuthenticationStatsBroadcastReceiver mBroadcastReceiver =
-                new AuthenticationStatsBroadcastReceiver(
-                        mContext,
-                        BiometricsProtoEnums.MODALITY_FINGERPRINT,
-                        (AuthenticationStatsCollector collector) -> {
-                            Slog.d(TAG, "Initializing AuthenticationStatsCollector");
-                            mAuthenticationStatsCollector = collector;
-                        });
-
-        try {
-            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to register user switch observer");
-        }
-    }
-
-    public static Fingerprint21 newInstance(@NonNull Context context,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @NonNull FingerprintSensorPropertiesInternal sensorProps,
-            @NonNull Handler handler,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
-        final BiometricScheduler<IBiometricsFingerprint, AidlSession> scheduler =
-                new BiometricScheduler<>(
-                        BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps),
-                        gestureAvailabilityDispatcher);
-        final HalResultController controller = new HalResultController(sensorProps.sensorId,
-                context, handler, scheduler);
-        return new Fingerprint21(context, biometricStateCallback, authenticationStateListeners,
-                sensorProps, scheduler, handler, lockoutResetDispatcher, controller,
-                BiometricContext.getInstance(context));
-    }
-
-    @Override
-    public void serviceDied(long cookie) {
-        Slog.e(TAG, "HAL died");
-        mHandler.post(() -> {
-            PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId)
-                    .incrementHALDeathCount();
-            mDaemon = null;
-            mCurrentUserId = UserHandle.USER_NULL;
-
-            final BaseClientMonitor client = mScheduler.getCurrentClient();
-            if (client instanceof ErrorConsumer) {
-                Slog.e(TAG, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
-                final ErrorConsumer errorConsumer = (ErrorConsumer) client;
-                errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
-                        0 /* vendorCode */);
-
-                FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
-                        BiometricsProtoEnums.MODALITY_FINGERPRINT,
-                        BiometricsProtoEnums.ISSUE_HAL_DEATH,
-                        -1 /* sensorId */);
-            }
-
-            mScheduler.recordCrashState();
-            mScheduler.reset();
-        });
-    }
-
-    synchronized AidlSession getSession() {
-        if (mDaemon != null && mSession != null) {
-            return mSession;
-        } else {
-            return mSession = new AidlSession(this::getDaemon,
-                    mCurrentUserId, new AidlResponseHandler(mContext,
-                    mScheduler, mSensorId, mCurrentUserId, new LockoutCache(),
-                    mLockoutResetDispatcher, new AuthSessionCoordinator(), () -> {
-                        mDaemon = null;
-                        mCurrentUserId = UserHandle.USER_NULL;
-                    }));
-        }
-    }
-
-    @VisibleForTesting
-    synchronized IBiometricsFingerprint getDaemon() {
-        if (mTestHalEnabled) {
-            final TestHal testHal = new TestHal(mContext, mSensorId);
-            testHal.setNotify(mHalResultController);
-            return testHal;
-        }
-
-        if (mDaemon != null) {
-            return mDaemon;
-        }
-
-        Slog.d(TAG, "Daemon was null, reconnecting, current operation: "
-                + mScheduler.getCurrentClient());
-        try {
-            mDaemon = IBiometricsFingerprint.getService();
-        } catch (java.util.NoSuchElementException e) {
-            // Service doesn't exist or cannot be opened.
-            Slog.w(TAG, "NoSuchElementException", e);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to get fingerprint HAL", e);
-        }
-
-        if (mDaemon == null) {
-            Slog.w(TAG, "Fingerprint HAL not available");
-            return null;
-        }
-
-        mDaemon.asBinder().linkToDeath(this, 0 /* flags */);
-
-        // HAL ID for these HIDL versions are only used to determine if callbacks have been
-        // successfully set.
-        long halId = 0;
-        try {
-            halId = mDaemon.setNotify(mHalResultController);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to set callback for fingerprint HAL", e);
-            mDaemon = null;
-        }
-
-        Slog.d(TAG, "Fingerprint HAL ready, HAL ID: " + halId);
-        if (halId != 0) {
-            scheduleLoadAuthenticatorIds();
-            scheduleInternalCleanup(ActivityManager.getCurrentUser(), null /* callback */);
-        } else {
-            Slog.e(TAG, "Unable to set callback");
-            mDaemon = null;
-        }
-
-        return mDaemon;
-    }
-
-    @Nullable IUdfpsOverlayController getUdfpsOverlayController() {
-        return mUdfpsOverlayController;
-    }
-
-    private void scheduleLoadAuthenticatorIds() {
-        // Note that this can be performed on the scheduler (as opposed to being done immediately
-        // when the HAL is (re)loaded, since
-        // 1) If this is truly the first time it's being performed (e.g. system has just started),
-        //    this will be run very early and way before any applications need to generate keys.
-        // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has
-        //    just been reloaded), the framework already has a cache of the authenticatorIds. This
-        //    is safe because authenticatorIds only change when A) new template has been enrolled,
-        //    or B) all templates are removed.
-        mHandler.post(() -> {
-            for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
-                final int targetUserId = user.id;
-                if (!mAuthenticatorIds.containsKey(targetUserId)) {
-                    scheduleUpdateActiveUserWithoutHandler(targetUserId, true /* force */);
-                }
-            }
-        });
-    }
-
-    private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
-        scheduleUpdateActiveUserWithoutHandler(targetUserId, false /* force */);
-    }
-
-    /**
-     * Schedules the {@link FingerprintUpdateActiveUserClient} without posting the work onto the
-     * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
-     * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
-     * this operation on the same lambda/runnable as those operations so that the ordering is
-     * correct.
-     *
-     * @param targetUserId Switch to this user, and update their authenticatorId
-     * @param force Always retrieve the authenticatorId, even if we are already the targetUserId
-     */
-    private void scheduleUpdateActiveUserWithoutHandler(int targetUserId, boolean force) {
-        final boolean hasEnrolled =
-                !getEnrolledFingerprints(mSensorProperties.sensorId, targetUserId).isEmpty();
-        final FingerprintUpdateActiveUserClientLegacy client =
-                new FingerprintUpdateActiveUserClientLegacy(mContext, mLazyDaemon, targetUserId,
-                        mContext.getOpPackageName(), mSensorProperties.sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext,
-                        this::getCurrentUser, hasEnrolled, mAuthenticatorIds, force);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                if (success) {
-                    if (mCurrentUserId != targetUserId) {
-                        // Create new session with updated user ID
-                        mSession = null;
-                    }
-                    mCurrentUserId = targetUserId;
-                } else {
-                    Slog.w(TAG, "Failed to change user, still: " + mCurrentUserId);
-                }
-            }
-        });
-    }
-
-    private int getCurrentUser() {
-        return mCurrentUserId;
-    }
-
-    @Override
-    public boolean containsSensor(int sensorId) {
-        return mSensorProperties.sensorId == sensorId;
-    }
-
-    @Override
-    @NonNull
-    public List<FingerprintSensorPropertiesInternal> getSensorProperties() {
-        final List<FingerprintSensorPropertiesInternal> properties = new ArrayList<>();
-        properties.add(mSensorProperties);
-        return properties;
-    }
-
-    @Nullable
-    @Override
-    public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId) {
-        return mSensorProperties;
-    }
-
-    @Override
-    public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
-        // Fingerprint2.1 keeps track of lockout in the framework. Let's just do it on the handler
-        // thread.
-        mHandler.post(() -> {
-            if (Flags.deHidl()) {
-                scheduleResetLockoutAidl(sensorId, userId, hardwareAuthToken);
-            } else {
-                scheduleResetLockoutHidl(sensorId, userId);
-            }
-        });
-    }
-
-    private void scheduleResetLockoutAidl(int sensorId, int userId,
-            @Nullable byte[] hardwareAuthToken) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintResetLockoutClient client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintResetLockoutClient(
-                        mContext, this::getSession, userId, mContext.getOpPackageName(),
-                        sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext, hardwareAuthToken, mLockoutTracker,
-                        mLockoutResetDispatcher,
-                        Utils.getCurrentStrength(sensorId));
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleResetLockoutHidl(int sensorId, int userId) {
-        final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(mContext,
-                userId, mContext.getOpPackageName(), sensorId,
-                createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN,
-                        mAuthenticationStatsCollector),
-                mBiometricContext, mLockoutTracker);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    @Override
-    public void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            if (Flags.deHidl()) {
-                scheduleGenerateChallengeAidl(userId, token, receiver, opPackageName);
-            } else {
-                scheduleGenerateChallengeHidl(userId, token, receiver, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleGenerateChallengeAidl(int userId, @NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintGenerateChallengeClient client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintGenerateChallengeClient(
-                        mContext, this::getSession, token,
-                        new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
-                        mSensorProperties.sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleGenerateChallengeHidl(int userId, @NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName) {
-        final FingerprintGenerateChallengeClient client =
-                new FingerprintGenerateChallengeClient(mContext, mLazyDaemon, token,
-                        new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
-                        mSensorProperties.sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    @Override
-    public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
-            @NonNull String opPackageName, long challenge) {
-        mHandler.post(() -> {
-            if (Flags.deHidl()) {
-                scheduleRevokeChallengeAidl(userId, token, opPackageName);
-            } else {
-                scheduleRevokeChallengeHidl(userId, token, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleRevokeChallengeAidl(int userId, @NonNull IBinder token,
-            @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintRevokeChallengeClient client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintRevokeChallengeClient(
-                        mContext, this::getSession,
-                        token, userId, opPackageName,
-                        mSensorProperties.sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext, 0L);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    private void scheduleRevokeChallengeHidl(int userId, @NonNull IBinder token,
-            @NonNull String opPackageName) {
-        final FingerprintRevokeChallengeClient client = new FingerprintRevokeChallengeClient(
-                mContext, mLazyDaemon, token, userId, opPackageName,
-                mSensorProperties.sensorId,
-                createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN,
-                        mAuthenticationStatsCollector),
-                mBiometricContext);
-        mScheduler.scheduleClientMonitor(client);
-    }
-
-    @Override
-    public long scheduleEnroll(int sensorId, @NonNull IBinder token,
-            @NonNull byte[] hardwareAuthToken, int userId,
-            @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
-            @FingerprintManager.EnrollReason int enrollReason,
-            @NonNull FingerprintEnrollOptions options) {
-        final long id = mRequestCounter.incrementAndGet();
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            if (Flags.deHidl()) {
-                scheduleEnrollAidl(token, hardwareAuthToken, userId, receiver,
-                        opPackageName, enrollReason, id, options);
-            } else {
-                scheduleEnrollHidl(token, hardwareAuthToken, userId, receiver,
-                        opPackageName, enrollReason, id, options);
-            }
-        });
-        return id;
-    }
-
-    private void scheduleEnrollHidl(@NonNull IBinder token,
-            @NonNull byte[] hardwareAuthToken, int userId,
-            @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
-            @FingerprintManager.EnrollReason int enrollReason, long id,
-            @NonNull FingerprintEnrollOptions options) {
-        final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
-                mLazyDaemon, token, id, new ClientMonitorCallbackConverter(receiver),
-                userId, hardwareAuthToken, opPackageName,
-                FingerprintUtils.getLegacyInstance(mSensorId), ENROLL_TIMEOUT_SEC,
-                mSensorProperties.sensorId,
-                createLogger(BiometricsProtoEnums.ACTION_ENROLL,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, mUdfpsOverlayController,
-                // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-                mSidefpsController,
-                mAuthenticationStateListeners, enrollReason, options);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                mBiometricStateCallback.onClientStarted(clientMonitor);
-            }
-
-            @Override
-            public void onBiometricAction(int action) {
-                mBiometricStateCallback.onBiometricAction(action);
-            }
-
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                mBiometricStateCallback.onClientFinished(clientMonitor, success);
-                if (success) {
-                    // Update authenticatorIds
-                    scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(),
-                            true /* force */);
-                }
-            }
-        });
-    }
-
-    private void scheduleEnrollAidl(@NonNull IBinder token,
-            @NonNull byte[] hardwareAuthToken, int userId,
-            @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
-            @FingerprintManager.EnrollReason int enrollReason, long id,
-            @NonNull FingerprintEnrollOptions options) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintEnrollClient
-                client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintEnrollClient(
-                        mContext,
-                        this::getSession, token, id,
-                        new ClientMonitorCallbackConverter(receiver),
-                        userId, hardwareAuthToken, opPackageName,
-                        FingerprintUtils.getLegacyInstance(mSensorId),
-                        mSensorProperties.sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_ENROLL,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext, null /* sensorProps */,
-                        mUdfpsOverlayController,
-                        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-                        mSidefpsController,
-                        mAuthenticationStateListeners,
-                        mContext.getResources().getInteger(
-                                com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser),
-                        enrollReason, options);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
-            @Override
-            public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                mBiometricStateCallback.onClientStarted(clientMonitor);
-            }
-
-            @Override
-            public void onBiometricAction(int action) {
-                mBiometricStateCallback.onBiometricAction(action);
-            }
-
-            @Override
-            public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
-                    boolean success) {
-                mBiometricStateCallback.onClientFinished(clientMonitor, success);
-                if (success) {
-                    // Update authenticatorIds
-                    scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(),
-                            true /* force */);
-                }
-            }
-        });
-    }
-
-    @Override
-    public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
-        mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId));
-    }
-
-    @Override
-    public long scheduleFingerDetect(@NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            int statsClient) {
-        final long id = mRequestCounter.incrementAndGet();
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(options.getUserId());
-
-            final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
-
-            if (Flags.deHidl()) {
-                scheduleFingerDetectAidl(token, listener, options, statsClient, id,
-                        isStrongBiometric);
-            } else {
-                scheduleFingerDetectHidl(token, listener, options, statsClient, id,
-                        isStrongBiometric);
-            }
-        });
-
-        return id;
-    }
-
-    private void scheduleFingerDetectHidl(@NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            int statsClient, long id, boolean isStrongBiometric) {
-        final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
-                mLazyDaemon, token, id, listener, options,
-                createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
-                        mAuthenticationStatsCollector),
-                mBiometricContext, mUdfpsOverlayController, isStrongBiometric);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    private void scheduleFingerDetectAidl(@NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            int statsClient, long id, boolean isStrongBiometric) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintDetectClient
-                client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintDetectClient(
-                        mContext,
-                        this::getSession, token, id, listener, options,
-                        createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext, mUdfpsOverlayController, isStrongBiometric);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    @Override
-    public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            long requestId, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(options.getUserId());
-
-            final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
-
-            if (Flags.deHidl()) {
-                scheduleAuthenticateAidl(token, operationId, cookie, listener, options, requestId,
-                        restricted, statsClient, allowBackgroundAuthentication, isStrongBiometric);
-            } else {
-                scheduleAuthenticateHidl(token, operationId, cookie, listener, options, requestId,
-                        restricted, statsClient, allowBackgroundAuthentication, isStrongBiometric);
-            }
-        });
-    }
-
-    private void scheduleAuthenticateAidl(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            long requestId, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication, boolean isStrongBiometric) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintAuthenticationClient
-                client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintAuthenticationClient(
-                        mContext, this::getSession, token, requestId, listener, operationId,
-                        restricted, options, cookie, false /* requireConfirmation */,
-                        createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext, isStrongBiometric,
-                        mTaskStackListener,
-                        mUdfpsOverlayController, mSidefpsController,
-                        mAuthenticationStateListeners,
-                        allowBackgroundAuthentication, mSensorProperties, mHandler,
-                        Utils.getCurrentStrength(mSensorId), null /* clock */, mLockoutTracker);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    private void scheduleAuthenticateHidl(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            long requestId, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication, boolean isStrongBiometric) {
-        final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
-                mContext, mLazyDaemon, token, requestId, listener, operationId,
-                restricted, options, cookie, false /* requireConfirmation */,
-                createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
-                        mAuthenticationStatsCollector),
-                mBiometricContext, isStrongBiometric,
-                mTaskStackListener, mLockoutTracker,
-                mUdfpsOverlayController, mSidefpsController,
-                mAuthenticationStateListeners,
-                allowBackgroundAuthentication, mSensorProperties,
-                Utils.getCurrentStrength(mSensorId));
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    @Override
-    public long scheduleAuthenticate(@NonNull IBinder token, long operationId,
-            int cookie, @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication) {
-        final long id = mRequestCounter.incrementAndGet();
-
-        scheduleAuthenticate(token, operationId, cookie, listener,
-                options, id, restricted, statsClient, allowBackgroundAuthentication);
-
-        return id;
-    }
-
-    @Override
-    public void startPreparedClient(int sensorId, int cookie) {
-        mHandler.post(() -> mScheduler.startPreparedClient(cookie));
-    }
-
-    @Override
-    public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
-        Slog.d(TAG, "cancelAuthentication, sensorId: " + sensorId);
-        mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId));
-    }
-
-    @Override
-    public void scheduleRemove(int sensorId, @NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
-            @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            if (Flags.deHidl()) {
-                scheduleRemoveAidl(token, receiver, fingerId, userId, opPackageName);
-            } else {
-                scheduleRemoveHidl(token, receiver, fingerId, userId, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleRemoveHidl(@NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
-            @NonNull String opPackageName) {
-        final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
-                mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), fingerId,
-                userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
-                mSensorProperties.sensorId,
-                createLogger(BiometricsProtoEnums.ACTION_REMOVE,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    private void scheduleRemoveAidl(@NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
-            @NonNull String opPackageName) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintRemovalClient client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintRemovalClient(
-                        mContext, this::getSession, token,
-                        new ClientMonitorCallbackConverter(receiver), new int[]{fingerId}, userId,
-                        opPackageName, FingerprintUtils.getLegacyInstance(mSensorId), mSensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_REMOVE,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                        mBiometricContext, mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
-    }
-
-    @Override
-    public void scheduleRemoveAll(int sensorId, @NonNull IBinder token,
-            @NonNull IFingerprintServiceReceiver receiver, int userId,
-            @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            // For [email protected], remove(0) means remove all enrollments
-            if (Flags.deHidl()) {
-                scheduleRemoveAidl(token, receiver, 0 /* fingerId */, userId, opPackageName);
-            } else {
-                scheduleRemoveHidl(token, receiver, 0 /* fingerId */, userId, opPackageName);
-            }
-        });
-    }
-
-    private void scheduleInternalCleanup(int userId,
-            @Nullable ClientMonitorCallback callback) {
-        mHandler.post(() -> {
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            if (Flags.deHidl()) {
-                scheduleInternalCleanupAidl(userId, callback);
-            } else {
-                scheduleInternalCleanupHidl(userId, callback);
-            }
-        });
-    }
-
-    private void scheduleInternalCleanupHidl(int userId,
-            @Nullable ClientMonitorCallback callback) {
-        final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
-                mContext, mLazyDaemon, userId, mContext.getOpPackageName(),
-                mSensorProperties.sensorId,
-                createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
-                        BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext,
-                FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, callback);
-    }
-
-    private void scheduleInternalCleanupAidl(int userId,
-            @Nullable ClientMonitorCallback callback) {
-        final com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintInternalCleanupClient
-                client =
-                new com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintInternalCleanupClient(
-                        mContext, this::getSession, userId, mContext.getOpPackageName(),
-                        mSensorProperties.sensorId,
-                        createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
-                                BiometricsProtoEnums.CLIENT_UNKNOWN,
-                                mAuthenticationStatsCollector),
-                        mBiometricContext,
-                        FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, callback);
-    }
-
-    @Override
-    public void scheduleInternalCleanup(int sensorId, int userId,
-            @Nullable ClientMonitorCallback callback) {
-        scheduleInternalCleanup(userId, new ClientMonitorCompositeCallback(callback,
-                mBiometricStateCallback));
-    }
-
-    @Override
-    public void scheduleInternalCleanup(int sensorId, int userId,
-            @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
-        scheduleInternalCleanup(userId, new ClientMonitorCompositeCallback(callback,
-                mBiometricStateCallback));
-    }
-
-    private BiometricLogger createLogger(int statsAction, int statsClient,
-            AuthenticationStatsCollector authenticationStatsCollector) {
-        return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FINGERPRINT,
-                statsAction, statsClient, authenticationStatsCollector);
-    }
-
-    @Override
-    public boolean isHardwareDetected(int sensorId) {
-        return getDaemon() != null;
-    }
-
-    @Override
-    public void rename(int sensorId, int fingerId, int userId, @NonNull String name) {
-        mHandler.post(() -> {
-            FingerprintUtils.getLegacyInstance(mSensorId)
-                    .renameBiometricForUser(mContext, userId, fingerId, name);
-        });
-    }
-
-    @Override
-    @NonNull
-    public List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId) {
-        return FingerprintUtils.getLegacyInstance(mSensorId).getBiometricsForUser(mContext, userId);
-    }
-
-    @Override
-    public boolean hasEnrollments(int sensorId, int userId) {
-        return !getEnrolledFingerprints(sensorId, userId).isEmpty();
-    }
-
-    @Override
-    @LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) {
-        return mLockoutTracker.getLockoutModeForUser(userId);
-    }
-
-    @Override
-    public long getAuthenticatorId(int sensorId, int userId) {
-        return mAuthenticatorIds.getOrDefault(userId, 0L);
-    }
-
-    @Override
-    public void onPointerDown(long requestId, int sensorId, PointerContext pc) {
-        mScheduler.getCurrentClientIfMatches(requestId, (client) -> {
-            if (!(client instanceof Udfps)) {
-                Slog.w(TAG, "onFingerDown received during client: " + client);
-                return;
-            }
-            ((Udfps) client).onPointerDown(pc);
-        });
-    }
-
-    @Override
-    public void onPointerUp(long requestId, int sensorId, PointerContext pc) {
-        mScheduler.getCurrentClientIfMatches(requestId, (client) -> {
-            if (!(client instanceof Udfps)) {
-                Slog.w(TAG, "onFingerDown received during client: " + client);
-                return;
-            }
-            ((Udfps) client).onPointerUp(pc);
-        });
-    }
-
-    @Override
-    public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event, long requestId,
-            int sensorId) {
-        mScheduler.getCurrentClientIfMatches(requestId, (client) -> {
-            if (!(client instanceof Udfps)) {
-                Slog.w(TAG, "onUdfpsUiEvent received during client: " + client);
-                return;
-            }
-            ((Udfps) client).onUdfpsUiEvent(event);
-        });
-    }
-
-    @Override
-    public void onPowerPressed() {
-        Slog.e(TAG, "onPowerPressed not supported for HIDL clients");
-    }
-
-    @Override
-    public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
-        mUdfpsOverlayController = controller;
-    }
-
-    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-    @Override
-    public void setSidefpsController(@NonNull ISidefpsController controller) {
-        mSidefpsController = controller;
-    }
-
-    @Override
-    public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
-            boolean clearSchedulerBuffer) {
-        final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES);
-
-        proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId);
-        proto.write(SensorStateProto.MODALITY, SensorStateProto.FINGERPRINT);
-        if (mSensorProperties.isAnyUdfpsType()) {
-            proto.write(SensorStateProto.MODALITY_FLAGS, SensorStateProto.FINGERPRINT_UDFPS);
-        }
-        proto.write(SensorStateProto.CURRENT_STRENGTH,
-                Utils.getCurrentStrength(mSensorProperties.sensorId));
-        proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer));
-
-        for (UserInfo user : UserManager.get(mContext).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-
-            final long userToken = proto.start(SensorStateProto.USER_STATES);
-            proto.write(UserStateProto.USER_ID, userId);
-            proto.write(UserStateProto.NUM_ENROLLED, FingerprintUtils.getLegacyInstance(mSensorId)
-                    .getBiometricsForUser(mContext, userId).size());
-            proto.end(userToken);
-        }
-
-        proto.write(SensorStateProto.RESET_LOCKOUT_REQUIRES_HARDWARE_AUTH_TOKEN,
-                mSensorProperties.resetLockoutRequiresHardwareAuthToken);
-        proto.write(SensorStateProto.RESET_LOCKOUT_REQUIRES_CHALLENGE,
-                mSensorProperties.resetLockoutRequiresChallenge);
-
-        proto.end(sensorToken);
-    }
-
-    @Override
-    public void dumpProtoMetrics(int sensorId, FileDescriptor fd) {
-        PerformanceTracker tracker =
-                PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId);
-
-        final ProtoOutputStream proto = new ProtoOutputStream(fd);
-        for (UserInfo user : UserManager.get(mContext).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-
-            final long userToken = proto.start(FingerprintServiceDumpProto.USERS);
-
-            proto.write(FingerprintUserStatsProto.USER_ID, userId);
-            proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS,
-                    FingerprintUtils.getLegacyInstance(mSensorId)
-                            .getBiometricsForUser(mContext, userId).size());
-
-            // Normal fingerprint authentications (e.g. lockscreen)
-            long countsToken = proto.start(FingerprintUserStatsProto.NORMAL);
-            proto.write(PerformanceStatsProto.ACCEPT, tracker.getAcceptForUser(userId));
-            proto.write(PerformanceStatsProto.REJECT, tracker.getRejectForUser(userId));
-            proto.write(PerformanceStatsProto.ACQUIRE, tracker.getAcquireForUser(userId));
-            proto.write(PerformanceStatsProto.LOCKOUT, tracker.getTimedLockoutForUser(userId));
-            proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT,
-                    tracker.getPermanentLockoutForUser(userId));
-            proto.end(countsToken);
-
-            // Statistics about secure fingerprint transactions (e.g. to unlock password
-            // storage, make secure purchases, etc.)
-            countsToken = proto.start(FingerprintUserStatsProto.CRYPTO);
-            proto.write(PerformanceStatsProto.ACCEPT, tracker.getAcceptCryptoForUser(userId));
-            proto.write(PerformanceStatsProto.REJECT, tracker.getRejectCryptoForUser(userId));
-            proto.write(PerformanceStatsProto.ACQUIRE, tracker.getAcquireCryptoForUser(userId));
-            proto.write(PerformanceStatsProto.LOCKOUT, 0); // meaningless for crypto
-            proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, 0); // meaningless for crypto
-            proto.end(countsToken);
-
-            proto.end(userToken);
-        }
-        proto.flush();
-        tracker.clear();
-    }
-
-    @Override
-    public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
-            @NonNull IInvalidationCallback callback) {
-        // TODO (b/179101888): Remove this temporary workaround.
-        try {
-            callback.onCompleted();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to complete InvalidateAuthenticatorId");
-        }
-    }
-
-    @Override
-    public void dumpInternal(int sensorId, @NonNull PrintWriter pw) {
-        PerformanceTracker performanceTracker =
-                PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId);
-
-        JSONObject dump = new JSONObject();
-        try {
-            dump.put("service", TAG);
-            dump.put("isUdfps", mIsUdfps);
-            dump.put("isPowerbuttonFps", mIsPowerbuttonFps);
-
-            JSONArray sets = new JSONArray();
-            for (UserInfo user : UserManager.get(mContext).getUsers()) {
-                final int userId = user.getUserHandle().getIdentifier();
-                final int N = FingerprintUtils.getLegacyInstance(mSensorId)
-                        .getBiometricsForUser(mContext, userId).size();
-                JSONObject set = new JSONObject();
-                set.put("id", userId);
-                set.put("count", N);
-                set.put("accept", performanceTracker.getAcceptForUser(userId));
-                set.put("reject", performanceTracker.getRejectForUser(userId));
-                set.put("acquire", performanceTracker.getAcquireForUser(userId));
-                set.put("lockout", performanceTracker.getTimedLockoutForUser(userId));
-                set.put("permanentLockout", performanceTracker.getPermanentLockoutForUser(userId));
-                // cryptoStats measures statistics about secure fingerprint transactions
-                // (e.g. to unlock password storage, make secure purchases, etc.)
-                set.put("acceptCrypto", performanceTracker.getAcceptCryptoForUser(userId));
-                set.put("rejectCrypto", performanceTracker.getRejectCryptoForUser(userId));
-                set.put("acquireCrypto", performanceTracker.getAcquireCryptoForUser(userId));
-                sets.put(set);
-            }
-
-            dump.put("prints", sets);
-        } catch (JSONException e) {
-            Slog.e(TAG, "dump formatting failure", e);
-        }
-        pw.println(dump);
-        pw.println("HAL deaths since last reboot: " + performanceTracker.getHALDeathCount());
-        mScheduler.dump(pw);
-    }
-
-    void setTestHalEnabled(boolean enabled) {
-        mTestHalEnabled = enabled;
-    }
-
-    @NonNull
-    @Override
-    public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
-            @NonNull String opPackageName) {
-        return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback,
-                mBiometricStateCallback, this, mHalResultController);
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
deleted file mode 100644
index f857946..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.trust.TrustManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.PointerContext;
-import android.hardware.fingerprint.FingerprintAuthenticateOptions;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
-import android.hardware.fingerprint.FingerprintSensorProperties;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Slog;
-import android.util.SparseBooleanArray;
-
-import com.android.internal.R;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.sensors.AuthenticationConsumer;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-/**
- * A mockable/testable provider of the {@link android.hardware.biometrics.fingerprint.V2_3} HIDL
- * interface. This class is intended simulate UDFPS logic for devices that do not have an actual
- * [email protected] HAL (where UDFPS starts to become supported)
- *
- * UDFPS "accept" can only happen within a set amount of time after a sensor authentication. This is
- * specified by {@link MockHalResultController#AUTH_VALIDITY_MS}. Touches after this duration will
- * be treated as "reject".
- *
- * This class provides framework logic to emulate, for testing only, the UDFPS functionalies below:
- *
- * 1) IF either A) the caller is keyguard, and the device is not in a trusted state (authenticated
- *    via biometric sensor or unlocked with a trust agent {@see android.app.trust.TrustManager}, OR
- *    B) the caller is not keyguard, and regardless of trusted state, AND (following applies to both
- *    (A) and (B) above) {@link FingerprintManager#onFingerDown(int, int, float, float)} is
- *    received, this class will respond with {@link AuthenticationCallback#onAuthenticationFailed()}
- *    after a tunable flat_time + variance_time.
- *
- *    In the case above (1), callers must not receive a successful authentication event here because
- *    the sensor has not actually been authenticated.
- *
- * 2) IF A) the caller is keyguard and the device is not in a trusted state, OR B) the caller is not
- *    keyguard and regardless of trusted state, AND (following applies to both (A) and (B)) the
- *    sensor is touched and the fingerprint is accepted by the HAL, and then
- *    {@link FingerprintManager#onFingerDown(int, int, float, float)} is received, this class will
- *    respond with {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)}
- *    after a tunable flat_time + variance_time. Note that the authentication callback from the
- *    sensor is held until {@link FingerprintManager#onFingerDown(int, int, float, float)} is
- *    invoked.
- *
- *    In the case above (2), callers can receive a successful authentication callback because the
- *    real sensor was authenticated. Note that even though the real sensor was touched, keyguard
- *    fingerprint authentication does not put keyguard into a trusted state because the
- *    authentication callback is held until onFingerDown was invoked. This allows callers such as
- *    keyguard to simulate a realistic path.
- *
- * 3) IF the caller is keyguard AND the device in a trusted state and then
- *    {@link FingerprintManager#onFingerDown(int, int, float, float)} is received, this class will
- *    respond with {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)}
- *    after a tunable flat_time + variance time.
- *
- *    In the case above (3), since the device is already unlockable via trust agent, it's fine to
- *    simulate the successful auth path. Non-keyguard clients will fall into either (1) or (2)
- *    above.
- *
- *  This class currently does not simulate false rejection. Conversely, this class relies on the
- *  real hardware sensor so does not affect false acceptance.
- */
-@SuppressWarnings("deprecation")
-public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManager.TrustListener {
-
-    private static final String TAG = "Fingerprint21UdfpsMock";
-
-    // Secure setting integer. If true, the system will load this class to enable udfps testing.
-    public static final String CONFIG_ENABLE_TEST_UDFPS =
-            "com.android.server.biometrics.sensors.fingerprint.test_udfps.enable";
-    // Secure setting integer. A fixed duration intended to simulate something like the duration
-    // required for image capture.
-    private static final String CONFIG_AUTH_DELAY_PT1 =
-            "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_pt1";
-    // Secure setting integer. A fixed duration intended to simulate something like the duration
-    // required for template matching to complete.
-    private static final String CONFIG_AUTH_DELAY_PT2 =
-            "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_pt2";
-    // Secure setting integer. A random value between [-randomness, randomness] will be added to the
-    // capture delay above for each accept/reject.
-    private static final String CONFIG_AUTH_DELAY_RANDOMNESS =
-            "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_randomness";
-
-    private static final int DEFAULT_AUTH_DELAY_PT1_MS = 300;
-    private static final int DEFAULT_AUTH_DELAY_PT2_MS = 400;
-    private static final int DEFAULT_AUTH_DELAY_RANDOMNESS_MS = 100;
-
-    @NonNull private final TestableBiometricScheduler mScheduler;
-    @NonNull private final Handler mHandler;
-    @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
-    @NonNull private final MockHalResultController mMockHalResultController;
-    @NonNull private final TrustManager mTrustManager;
-    @NonNull private final SparseBooleanArray mUserHasTrust;
-    @NonNull private final Random mRandom;
-    @NonNull private final FakeRejectRunnable mFakeRejectRunnable;
-    @NonNull private final FakeAcceptRunnable mFakeAcceptRunnable;
-    @NonNull private final RestartAuthRunnable mRestartAuthRunnable;
-
-    private static class TestableBiometricScheduler extends BiometricScheduler {
-        @NonNull private Fingerprint21UdfpsMock mFingerprint21;
-
-        TestableBiometricScheduler(
-                @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
-            super(BiometricScheduler.SENSOR_TYPE_FP_OTHER, gestureAvailabilityDispatcher);
-        }
-
-        void init(@NonNull Fingerprint21UdfpsMock fingerprint21) {
-            mFingerprint21 = fingerprint21;
-        }
-    }
-
-    /**
-     * All of the mocking/testing should happen in here. This way we don't need to modify the
-     * {@link BaseClientMonitor} implementations and can run the
-     * real path there.
-     */
-    private static class MockHalResultController extends HalResultController {
-
-        // Duration for which a sensor authentication can be treated as UDFPS success.
-        private static final int AUTH_VALIDITY_MS = 10 * 1000; // 10 seconds
-
-        static class LastAuthArgs {
-            @NonNull final AuthenticationConsumer lastAuthenticatedClient;
-            final long deviceId;
-            final int fingerId;
-            final int groupId;
-            @Nullable final ArrayList<Byte> token;
-
-            LastAuthArgs(@NonNull AuthenticationConsumer authenticationConsumer, long deviceId,
-                    int fingerId, int groupId, @Nullable ArrayList<Byte> token) {
-                lastAuthenticatedClient = authenticationConsumer;
-                this.deviceId = deviceId;
-                this.fingerId = fingerId;
-                this.groupId = groupId;
-                if (token == null) {
-                    this.token = null;
-                } else {
-                    // Store a copy so the owner can be GC'd
-                    this.token = new ArrayList<>(token);
-                }
-            }
-        }
-
-        // Initialized after the constructor, but before it's ever used.
-        @NonNull private RestartAuthRunnable mRestartAuthRunnable;
-        @NonNull private Fingerprint21UdfpsMock mFingerprint21;
-        @Nullable private LastAuthArgs mLastAuthArgs;
-
-        MockHalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler,
-                @NonNull BiometricScheduler scheduler) {
-            super(sensorId, context, handler, scheduler);
-        }
-
-        void init(@NonNull RestartAuthRunnable restartAuthRunnable,
-                @NonNull Fingerprint21UdfpsMock fingerprint21) {
-            mRestartAuthRunnable = restartAuthRunnable;
-            mFingerprint21 = fingerprint21;
-        }
-
-        @Nullable AuthenticationConsumer getLastAuthenticatedClient() {
-            return mLastAuthArgs != null ? mLastAuthArgs.lastAuthenticatedClient : null;
-        }
-
-        /**
-         * Intercepts the HAL authentication and holds it until the UDFPS simulation decides
-         * that authentication finished.
-         */
-        @Override
-        public void onAuthenticated(long deviceId, int fingerId, int groupId,
-                ArrayList<Byte> token) {
-            mHandler.post(() -> {
-                final BaseClientMonitor client = mScheduler.getCurrentClient();
-                if (!(client instanceof AuthenticationConsumer)) {
-                    Slog.e(TAG, "Non authentication consumer: " + client);
-                    return;
-                }
-
-                final boolean accepted = fingerId != 0;
-                if (accepted) {
-                    mFingerprint21.setDebugMessage("Finger accepted");
-                } else {
-                    mFingerprint21.setDebugMessage("Finger rejected");
-                }
-
-                final AuthenticationConsumer authenticationConsumer =
-                        (AuthenticationConsumer) client;
-                mLastAuthArgs = new LastAuthArgs(authenticationConsumer, deviceId, fingerId,
-                        groupId, token);
-
-                // Remove any existing restart runnbables since auth just started, and put a new
-                // one on the queue.
-                mHandler.removeCallbacks(mRestartAuthRunnable);
-                mRestartAuthRunnable.setLastAuthReference(authenticationConsumer);
-                mHandler.postDelayed(mRestartAuthRunnable, AUTH_VALIDITY_MS);
-            });
-        }
-
-        /**
-         * Calls through to the real interface and notifies clients of accept/reject.
-         */
-        void sendAuthenticated(long deviceId, int fingerId, int groupId,
-                ArrayList<Byte> token) {
-            Slog.d(TAG, "sendAuthenticated: " + (fingerId != 0));
-            mFingerprint21.setDebugMessage("Udfps match: " + (fingerId != 0));
-            super.onAuthenticated(deviceId, fingerId, groupId, token);
-        }
-    }
-
-    public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @NonNull FingerprintSensorPropertiesInternal sensorProps,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
-            @NonNull BiometricContext biometricContext) {
-        Slog.d(TAG, "Creating Fingerprint23Mock!");
-
-        final Handler handler = new Handler(Looper.getMainLooper());
-        final TestableBiometricScheduler scheduler =
-                new TestableBiometricScheduler(gestureAvailabilityDispatcher);
-        final MockHalResultController controller =
-                new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
-        return new Fingerprint21UdfpsMock(context, biometricStateCallback,
-                authenticationStateListeners, sensorProps, scheduler, handler,
-                lockoutResetDispatcher, controller, biometricContext);
-    }
-
-    private static abstract class FakeFingerRunnable implements Runnable {
-        private long mFingerDownTime;
-        private int mCaptureDuration;
-
-        /**
-         * @param fingerDownTime System time when onFingerDown occurred
-         * @param captureDuration Duration that the finger needs to be down for
-         */
-        void setSimulationTime(long fingerDownTime, int captureDuration) {
-            mFingerDownTime = fingerDownTime;
-            mCaptureDuration = captureDuration;
-        }
-
-        @SuppressWarnings("BooleanMethodIsAlwaysInverted")
-        boolean isImageCaptureComplete() {
-            return System.currentTimeMillis() - mFingerDownTime > mCaptureDuration;
-        }
-    }
-
-    private final class FakeRejectRunnable extends FakeFingerRunnable {
-        @Override
-        public void run() {
-            mMockHalResultController.sendAuthenticated(0, 0, 0, null);
-        }
-    }
-
-    private final class FakeAcceptRunnable extends FakeFingerRunnable {
-        @Override
-        public void run() {
-            if (mMockHalResultController.mLastAuthArgs == null) {
-                // This can happen if the user has trust agents enabled, which make lockscreen
-                // dismissable. Send a fake non-zero (accept) finger.
-                Slog.d(TAG, "Sending fake finger");
-                mMockHalResultController.sendAuthenticated(1 /* deviceId */,
-                        1 /* fingerId */, 1 /* groupId */, null /* token */);
-            } else {
-                mMockHalResultController.sendAuthenticated(
-                        mMockHalResultController.mLastAuthArgs.deviceId,
-                        mMockHalResultController.mLastAuthArgs.fingerId,
-                        mMockHalResultController.mLastAuthArgs.groupId,
-                        mMockHalResultController.mLastAuthArgs.token);
-            }
-        }
-    }
-
-    /**
-     * The fingerprint HAL allows multiple (5) fingerprint attempts per HIDL invocation of the
-     * authenticate method. However, valid fingerprint authentications are invalidated after
-     * {@link MockHalResultController#AUTH_VALIDITY_MS}, meaning UDFPS touches will be reported as
-     * rejects if touched after that duration. However, since a valid fingerprint was detected, the
-     * HAL and FingerprintService will not look for subsequent fingerprints.
-     *
-     * In order to keep the FingerprintManager API consistent (that multiple fingerprint attempts
-     * are allowed per auth lifecycle), we internally cancel and restart authentication so that the
-     * sensor is responsive again.
-     */
-    private static final class RestartAuthRunnable implements Runnable {
-        @NonNull private final Fingerprint21UdfpsMock mFingerprint21;
-        @NonNull private final TestableBiometricScheduler mScheduler;
-
-        // Store a reference to the auth consumer that should be invalidated.
-        private AuthenticationConsumer mLastAuthConsumer;
-
-        RestartAuthRunnable(@NonNull Fingerprint21UdfpsMock fingerprint21,
-                @NonNull TestableBiometricScheduler scheduler) {
-            mFingerprint21 = fingerprint21;
-            mScheduler = scheduler;
-        }
-
-        void setLastAuthReference(AuthenticationConsumer lastAuthConsumer) {
-            mLastAuthConsumer = lastAuthConsumer;
-        }
-
-        @Override
-        public void run() {
-            final BaseClientMonitor client = mScheduler.getCurrentClient();
-
-            // We don't care about FingerprintDetectClient, since accept/rejects are both OK. UDFPS
-            // rejects will just simulate the path where non-enrolled fingers are presented.
-            if (!(client instanceof FingerprintAuthenticationClient)) {
-                Slog.e(TAG, "Non-FingerprintAuthenticationClient client: " + client);
-                return;
-            }
-
-            // Perhaps the runnable is stale, or the user stopped/started auth manually. Do not
-            // restart auth in this case.
-            if (client != mLastAuthConsumer) {
-                Slog.e(TAG, "Current client: " + client
-                        + " does not match mLastAuthConsumer: " + mLastAuthConsumer);
-                return;
-            }
-
-            Slog.d(TAG, "Restarting auth, current: " + client);
-            mFingerprint21.setDebugMessage("Auth timed out");
-
-            final FingerprintAuthenticationClient authClient =
-                    (FingerprintAuthenticationClient) client;
-            // Store the authClient parameters so it can be rescheduled
-            final IBinder token = client.getToken();
-            final long operationId = authClient.getOperationId();
-            final int cookie = client.getCookie();
-            final ClientMonitorCallbackConverter listener = new ClientMonitorCallbackConverter(
-                    new IFingerprintServiceReceiver.Default());
-            final boolean restricted = authClient.isRestricted();
-            final int statsClient = client.getLogger().getStatsClient();
-            final boolean isKeyguard = authClient.isKeyguard();
-            final FingerprintAuthenticateOptions options =
-                    new FingerprintAuthenticateOptions.Builder()
-                            .setUserId(client.getTargetUserId())
-                            .setOpPackageName(client.getOwnerString())
-                            .build();
-
-            // Don't actually send cancel() to the HAL, since successful auth already finishes
-            // HAL authenticate() lifecycle. Just
-            mScheduler.getInternalCallback().onClientFinished(client, true /* success */);
-
-            // Schedule this only after we invoke onClientFinished for the previous client, so that
-            // internal preemption logic is not run.
-            mFingerprint21.scheduleAuthenticate(token,
-                    operationId, cookie, listener, options, restricted, statsClient,
-                    isKeyguard);
-        }
-    }
-
-    private Fingerprint21UdfpsMock(@NonNull Context context,
-            @NonNull BiometricStateCallback biometricStateCallback,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @NonNull FingerprintSensorPropertiesInternal sensorProps,
-            @NonNull TestableBiometricScheduler scheduler,
-            @NonNull Handler handler,
-            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-            @NonNull MockHalResultController controller,
-            @NonNull BiometricContext biometricContext) {
-        super(context, biometricStateCallback, authenticationStateListeners, sensorProps, scheduler,
-                handler, lockoutResetDispatcher, controller, biometricContext);
-        mScheduler = scheduler;
-        mScheduler.init(this);
-        mHandler = handler;
-        // resetLockout is controlled by the framework, so hardwareAuthToken is not required
-        final boolean resetLockoutRequiresHardwareAuthToken = false;
-        final int maxTemplatesAllowed = mContext.getResources()
-                .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
-        mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId,
-                sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo,
-                FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, false /* halControlsIllumination */,
-                resetLockoutRequiresHardwareAuthToken, sensorProps.getAllLocations());
-        mMockHalResultController = controller;
-        mUserHasTrust = new SparseBooleanArray();
-        mTrustManager = context.getSystemService(TrustManager.class);
-        mTrustManager.registerTrustListener(this);
-        mRandom = new Random();
-        mFakeRejectRunnable = new FakeRejectRunnable();
-        mFakeAcceptRunnable = new FakeAcceptRunnable();
-        mRestartAuthRunnable = new RestartAuthRunnable(this, mScheduler);
-
-        // We can't initialize this during MockHalresultController's constructor due to a circular
-        // dependency.
-        mMockHalResultController.init(mRestartAuthRunnable, this);
-    }
-
-    @Override
-    public void onTrustChanged(boolean enabled, boolean newlyUnlocked, int userId, int flags,
-            List<String> trustGrantedMessages) {
-        mUserHasTrust.put(userId, enabled);
-    }
-
-    @Override
-    public void onTrustManagedChanged(boolean enabled, int userId) {
-
-    }
-
-    @Override
-    public void onTrustError(CharSequence message) {
-
-    }
-
-    @Override
-    public void onEnabledTrustAgentsChanged(int userId) {
-
-    }
-
-    @Override
-    public void onIsActiveUnlockRunningChanged(boolean isRunning, int userId) {
-
-    }
-
-    @Override
-    @NonNull
-    public List<FingerprintSensorPropertiesInternal> getSensorProperties() {
-        final List<FingerprintSensorPropertiesInternal> properties = new ArrayList<>();
-        properties.add(mSensorProperties);
-        return properties;
-    }
-
-    @Override
-    public void onPointerDown(long requestId, int sensorId, PointerContext pc) {
-        mHandler.post(() -> {
-            Slog.d(TAG, "onFingerDown");
-            final AuthenticationConsumer lastAuthenticatedConsumer =
-                    mMockHalResultController.getLastAuthenticatedClient();
-            final BaseClientMonitor currentScheduledClient = mScheduler.getCurrentClient();
-
-            if (currentScheduledClient == null) {
-                Slog.d(TAG, "Not authenticating");
-                return;
-            }
-
-            mHandler.removeCallbacks(mFakeRejectRunnable);
-            mHandler.removeCallbacks(mFakeAcceptRunnable);
-
-            // The sensor was authenticated, is still the currently scheduled client, and the
-            // user touched the UDFPS affordance. Pretend that auth succeeded.
-            final boolean authenticatedClientIsCurrent = lastAuthenticatedConsumer != null
-                    && lastAuthenticatedConsumer == currentScheduledClient;
-            // User is unlocked on keyguard via Trust Agent
-            final boolean keyguardAndTrusted;
-            if (currentScheduledClient instanceof FingerprintAuthenticationClient) {
-                keyguardAndTrusted = ((FingerprintAuthenticationClient) currentScheduledClient)
-                        .isKeyguard()
-                        && mUserHasTrust.get(currentScheduledClient.getTargetUserId(), false);
-            } else {
-                keyguardAndTrusted = false;
-            }
-
-            final int captureDuration = getNewCaptureDuration();
-            final int matchingDuration = getMatchingDuration();
-            final int totalDuration = captureDuration + matchingDuration;
-            setDebugMessage("Duration: " + totalDuration
-                    + " (" + captureDuration + " + " + matchingDuration + ")");
-            if (authenticatedClientIsCurrent || keyguardAndTrusted) {
-                mFakeAcceptRunnable.setSimulationTime(System.currentTimeMillis(), captureDuration);
-                mHandler.postDelayed(mFakeAcceptRunnable, totalDuration);
-            } else if (currentScheduledClient instanceof AuthenticationConsumer) {
-                // Something is authenticating but authentication has not succeeded yet. Pretend
-                // that auth rejected.
-                mFakeRejectRunnable.setSimulationTime(System.currentTimeMillis(), captureDuration);
-                mHandler.postDelayed(mFakeRejectRunnable, totalDuration);
-            }
-        });
-    }
-
-    @Override
-    public void onPointerUp(long requestId, int sensorId, PointerContext pc) {
-        mHandler.post(() -> {
-            Slog.d(TAG, "onFingerUp");
-
-            // Only one of these can be on the handler at any given time (see onFingerDown). If
-            // image capture is not complete, send ACQUIRED_TOO_FAST and remove the runnable from
-            // the handler. Image capture (onFingerDown) needs to happen again.
-            if (mHandler.hasCallbacks(mFakeRejectRunnable)
-                    && !mFakeRejectRunnable.isImageCaptureComplete()) {
-                mHandler.removeCallbacks(mFakeRejectRunnable);
-                mMockHalResultController.onAcquired(0 /* deviceId */,
-                        FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST,
-                        0 /* vendorCode */);
-            } else if (mHandler.hasCallbacks(mFakeAcceptRunnable)
-                    && !mFakeAcceptRunnable.isImageCaptureComplete()) {
-                mHandler.removeCallbacks(mFakeAcceptRunnable);
-                mMockHalResultController.onAcquired(0 /* deviceId */,
-                        FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST,
-                        0 /* vendorCode */);
-            }
-        });
-    }
-
-    private int getNewCaptureDuration() {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-        final int captureTime = Settings.Secure.getIntForUser(contentResolver,
-                CONFIG_AUTH_DELAY_PT1,
-                DEFAULT_AUTH_DELAY_PT1_MS,
-                UserHandle.USER_CURRENT);
-        final int randomDelayRange = Settings.Secure.getIntForUser(contentResolver,
-                CONFIG_AUTH_DELAY_RANDOMNESS,
-                DEFAULT_AUTH_DELAY_RANDOMNESS_MS,
-                UserHandle.USER_CURRENT);
-        final int randomDelay = mRandom.nextInt(randomDelayRange * 2) - randomDelayRange;
-
-        // Must be at least 0
-        return Math.max(captureTime + randomDelay, 0);
-    }
-
-    private int getMatchingDuration() {
-        final int matchingTime = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                CONFIG_AUTH_DELAY_PT2,
-                DEFAULT_AUTH_DELAY_PT2_MS,
-                UserHandle.USER_CURRENT);
-
-        // Must be at least 0
-        return Math.max(matchingTime, 0);
-    }
-
-    private void setDebugMessage(String message) {
-        try {
-            final IUdfpsOverlayController controller = getUdfpsOverlayController();
-            // Things can happen before SysUI loads and sets the controller.
-            if (controller != null) {
-                Slog.d(TAG, "setDebugMessage: " + message);
-                controller.setDebugMessage(mSensorProperties.sensorId, message);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when sending message: " + message, e);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
deleted file mode 100644
index b6311af..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import static android.adaptiveauth.Flags.reportBiometricAuthAttempts;
-
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.TaskStackListener;
-import android.content.Context;
-import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricManager.Authenticators;
-import android.hardware.biometrics.BiometricSourceType;
-import android.hardware.biometrics.fingerprint.PointerContext;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.FingerprintAuthenticateOptions;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
-import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.log.CallbackWithProbe;
-import com.android.server.biometrics.log.Probe;
-import com.android.server.biometrics.sensors.AuthenticationClient;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BiometricNotificationUtils;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
-import com.android.server.biometrics.sensors.LockoutTracker;
-import com.android.server.biometrics.sensors.PerformanceTracker;
-import com.android.server.biometrics.sensors.SensorOverlays;
-import com.android.server.biometrics.sensors.fingerprint.Udfps;
-import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
-
-import java.util.ArrayList;
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific authentication client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-class FingerprintAuthenticationClient
-        extends AuthenticationClient<IBiometricsFingerprint, FingerprintAuthenticateOptions>
-        implements Udfps {
-
-    private static final String TAG = "Biometrics/FingerprintAuthClient";
-
-    private final LockoutFrameworkImpl mLockoutFrameworkImpl;
-    @NonNull private final SensorOverlays mSensorOverlays;
-    @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
-    @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
-    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
-
-    private boolean mIsPointerDown;
-
-    FingerprintAuthenticationClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
-            @NonNull IBinder token, long requestId,
-            @NonNull ClientMonitorCallbackConverter listener, long operationId,
-            boolean restricted, @NonNull FingerprintAuthenticateOptions options,
-            int cookie, boolean requireConfirmation, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext, boolean isStrongBiometric,
-            @NonNull TaskStackListener taskStackListener,
-            @NonNull LockoutFrameworkImpl lockoutTracker,
-            @Nullable IUdfpsOverlayController udfpsOverlayController,
-            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-            @Nullable ISidefpsController sidefpsController,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintSensorPropertiesInternal sensorProps,
-            @Authenticators.Types int sensorStrength) {
-        super(context, lazyDaemon, token, listener, operationId, restricted,
-                options, cookie, requireConfirmation, logger, biometricContext,
-                isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication,
-                false /* shouldVibrate */, sensorStrength);
-        setRequestId(requestId);
-        mLockoutFrameworkImpl = lockoutTracker;
-        if (sidefpsControllerRefactor()) {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
-        } else {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
-        }
-        mAuthenticationStateListeners = authenticationStateListeners;
-        mSensorProps = sensorProps;
-        mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-
-        if (mSensorProps.isAnyUdfpsType()) {
-            // UDFPS requires user to touch before becoming "active"
-            mState = STATE_STARTED_PAUSED;
-        } else {
-            mState = STATE_STARTED;
-        }
-    }
-
-    @NonNull
-    @Override
-    protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
-        return new ClientMonitorCompositeCallback(mALSProbeCallback, callback);
-    }
-
-    @Override
-    public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
-            boolean authenticated, ArrayList<Byte> token) {
-        super.onAuthenticated(identifier, authenticated, token);
-
-        // Authentication lifecycle ends either when
-        // 1) Authenticated == true
-        // 2) Error occurred (lockout or some other error)
-        // Note that authentication doesn't end when Authenticated == false
-
-        if (authenticated) {
-            mState = STATE_STOPPED;
-            resetFailedAttempts(getTargetUserId());
-            mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
-            if (reportBiometricAuthAttempts()) {
-                mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(),
-                        getTargetUserId());
-            }
-        } else {
-            mState = STATE_STARTED_PAUSED_ATTEMPTED;
-            final @LockoutTracker.LockoutMode int lockoutMode =
-                    mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId());
-            if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
-                Slog.w(TAG, "Fingerprint locked out, lockoutMode(" + lockoutMode + ")");
-                final int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
-                        ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
-                        : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
-                // Send the error, but do not invoke the FinishCallback yet. Since lockout is not
-                // controlled by the HAL, the framework must stop the sensor before finishing the
-                // client.
-                mSensorOverlays.hide(getSensorId());
-                if (sidefpsControllerRefactor()) {
-                    mAuthenticationStateListeners.onAuthenticationStopped();
-                }
-                onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */);
-                cancel();
-            }
-            if (reportBiometricAuthAttempts()) {
-                mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(),
-                        getTargetUserId());
-            }
-        }
-    }
-
-    @Override
-    public void onError(int errorCode, int vendorCode) {
-        super.onError(errorCode, vendorCode);
-
-        if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION) {
-            BiometricNotificationUtils.showBadCalibrationNotification(getContext());
-        }
-
-        mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
-    }
-
-    private void resetFailedAttempts(int userId) {
-        mLockoutFrameworkImpl.resetFailedAttemptsForUser(true /* clearAttemptCounter */, userId);
-    }
-
-    @Override
-    protected void handleLifecycleAfterAuth(boolean authenticated) {
-        if (authenticated) {
-            mCallback.onClientFinished(this, true /* success */);
-        }
-    }
-
-    @Override
-    public void onAcquired(int acquiredInfo, int vendorCode) {
-        mAuthenticationStateListeners.onAuthenticationAcquired(
-                BiometricSourceType.FINGERPRINT, getRequestReason(), acquiredInfo);
-        super.onAcquired(acquiredInfo, vendorCode);
-
-        @LockoutTracker.LockoutMode final int lockoutMode =
-                getLockoutTracker().getLockoutModeForUser(getTargetUserId());
-        if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
-            PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId());
-            pt.incrementAcquireForUser(getTargetUserId(), isCryptoOperation());
-        }
-    }
-
-    @Override
-    public boolean wasUserDetected() {
-        // TODO: Update if it needs to be used for fingerprint, i.e. success/reject, error_timeout
-        return false;
-    }
-
-    @Override
-    public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
-        mLockoutFrameworkImpl.addFailedAttemptForUser(userId);
-        @LockoutTracker.LockoutMode final int lockoutMode =
-                getLockoutTracker().getLockoutModeForUser(userId);
-        final PerformanceTracker performanceTracker =
-                PerformanceTracker.getInstanceForSensorId(getSensorId());
-        if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) {
-            performanceTracker.incrementPermanentLockoutForUser(userId);
-        } else if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) {
-            performanceTracker.incrementTimedLockoutForUser(userId);
-        }
-
-        return lockoutMode;
-    }
-
-    @Override
-    protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), getRequestReason(), this);
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStarted(getRequestReason());
-        }
-
-        try {
-            // GroupId was never used. In fact, groupId is always the same as userId.
-            getFreshDaemon().authenticate(mOperationId, getTargetUserId());
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting auth", e);
-            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                    0 /* vendorCode */);
-            mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    protected void stopHalOperation() {
-        mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
-
-        try {
-            getFreshDaemon().cancel();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting cancel", e);
-            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                    0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public void onPointerDown(PointerContext pc) {
-        mIsPointerDown = true;
-        mState = STATE_STARTED;
-        mALSProbeCallback.getProbe().enable();
-        UdfpsHelper.onFingerDown(getFreshDaemon(), (int) pc.x, (int) pc.y, pc.minor, pc.major);
-
-        try {
-            getListener().onUdfpsPointerDown(getSensorId());
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception", e);
-        }
-    }
-
-    @Override
-    public void onPointerUp(PointerContext pc) {
-        mIsPointerDown = false;
-        mState = STATE_STARTED_PAUSED_ATTEMPTED;
-        mALSProbeCallback.getProbe().disable();
-        UdfpsHelper.onFingerUp(getFreshDaemon());
-
-        try {
-            getListener().onUdfpsPointerUp(getSensorId());
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception", e);
-        }
-    }
-
-    @Override
-    public boolean isPointerDown() {
-        return mIsPointerDown;
-    }
-
-    @Override
-    public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) {
-        // Unsupported in HIDL.
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
deleted file mode 100644
index 50e48fe..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricRequestConstants;
-import android.hardware.biometrics.fingerprint.PointerContext;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.FingerprintAuthenticateOptions;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.AcquisitionClient;
-import com.android.server.biometrics.sensors.AuthenticationConsumer;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.PerformanceTracker;
-import com.android.server.biometrics.sensors.SensorOverlays;
-import com.android.server.biometrics.sensors.fingerprint.Udfps;
-import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
-
-import java.util.ArrayList;
-import java.util.function.Supplier;
-
-/**
- * Performs fingerprint detection without exposing any matching information (e.g. accept/reject
- * have the same haptic, lockout counter is not increased).
- */
-class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
-        implements AuthenticationConsumer, Udfps {
-
-    private static final String TAG = "FingerprintDetectClient";
-
-    private final boolean mIsStrongBiometric;
-    @NonNull private final SensorOverlays mSensorOverlays;
-    private boolean mIsPointerDown;
-
-    public FingerprintDetectClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
-            @NonNull IBinder token, long requestId,
-            @NonNull ClientMonitorCallbackConverter listener,
-            @NonNull FingerprintAuthenticateOptions options,
-            @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
-            @Nullable IUdfpsOverlayController udfpsOverlayController,
-            boolean isStrongBiometric) {
-        super(context, lazyDaemon, token, listener, options.getUserId(),
-                options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
-                true /* shouldVibrate */, biometricLogger, biometricContext);
-        setRequestId(requestId);
-        if (sidefpsControllerRefactor()) {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
-        } else {
-            mSensorOverlays = new SensorOverlays(
-                    udfpsOverlayController, null /* sideFpsController */);
-        }
-        mIsStrongBiometric = isStrongBiometric;
-    }
-
-    @Override
-    protected void stopHalOperation() {
-        mSensorOverlays.hide(getSensorId());
-
-        try {
-            getFreshDaemon().cancel();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting cancel", e);
-            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                    0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-        startHalOperation();
-    }
-
-    @Override
-    protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), BiometricRequestConstants.REASON_AUTH_KEYGUARD,
-                this);
-
-        try {
-            getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting auth", e);
-            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                    0 /* vendorCode */);
-            mSensorOverlays.hide(getSensorId());
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public void onPointerDown(PointerContext pc) {
-        mIsPointerDown = true;
-        UdfpsHelper.onFingerDown(getFreshDaemon(), (int) pc.x, (int) pc.y, pc.minor, pc.major);
-    }
-
-    @Override
-    public void onPointerUp(PointerContext pc) {
-        mIsPointerDown = false;
-        UdfpsHelper.onFingerUp(getFreshDaemon());
-    }
-
-    @Override
-    public boolean isPointerDown() {
-        return mIsPointerDown;
-    }
-
-    @Override
-    public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) {
-        // Unsupported in HIDL.
-    }
-
-    @Override
-    public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
-            boolean authenticated, ArrayList<Byte> hardwareAuthToken) {
-        getLogger().logOnAuthenticated(getContext(), getOperationContext(),
-                authenticated, false /* requireConfirmation */,
-                getTargetUserId(), false /* isBiometricPrompt */);
-
-        // Do not distinguish between success/failures.
-        vibrateSuccess();
-
-        final PerformanceTracker pm = PerformanceTracker.getInstanceForSensorId(getSensorId());
-        pm.incrementAuthForUser(getTargetUserId(), authenticated);
-
-        try {
-            getListener().onDetected(getSensorId(), getTargetUserId(), mIsStrongBiometric);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when sending onDetected", e);
-        }
-    }
-
-    @Override
-    public int getProtoEnum() {
-        return BiometricsProto.CM_DETECT_INTERACTION;
-    }
-
-    @Override
-    public boolean interruptsPrecedingClients() {
-        return true;
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
deleted file mode 100644
index 8f937fc..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricStateListener;
-import android.hardware.biometrics.fingerprint.PointerContext;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintEnrollOptions;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.ISidefpsController;
-import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BiometricNotificationUtils;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
-import com.android.server.biometrics.sensors.EnrollClient;
-import com.android.server.biometrics.sensors.SensorOverlays;
-import com.android.server.biometrics.sensors.fingerprint.Udfps;
-import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
-
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific enroll client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint>
-        implements Udfps {
-
-    private static final String TAG = "FingerprintEnrollClient";
-
-    @NonNull private final SensorOverlays mSensorOverlays;
-    private final @FingerprintManager.EnrollReason int mEnrollReason;
-    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
-    private boolean mIsPointerDown;
-
-    FingerprintEnrollClient(
-            @NonNull Context context, @NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
-            @NonNull IBinder token, long requestId,
-            @NonNull ClientMonitorCallbackConverter listener, int userId,
-            @NonNull byte[] hardwareAuthToken, @NonNull String owner,
-            @NonNull BiometricUtils<Fingerprint> utils, int timeoutSec, int sensorId,
-            @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
-            @Nullable IUdfpsOverlayController udfpsOverlayController,
-            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-            @Nullable ISidefpsController sidefpsController,
-            @NonNull AuthenticationStateListeners authenticationStateListeners,
-            @FingerprintManager.EnrollReason int enrollReason,
-            @NonNull FingerprintEnrollOptions options) {
-        super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
-                timeoutSec, sensorId, true /* shouldVibrate */, biometricLogger,
-                biometricContext,
-                BiometricFingerprintConstants.reasonToMetric(options.getEnrollReason()));
-        setRequestId(requestId);
-        if (sidefpsControllerRefactor()) {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
-        } else {
-            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
-        }
-        mAuthenticationStateListeners = authenticationStateListeners;
-
-        mEnrollReason = enrollReason;
-        if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) {
-            getLogger().disableMetrics();
-        }
-        Slog.w(TAG, "EnrollOptions "
-                + FingerprintEnrollOptions.enrollReasonToString(options.getEnrollReason()));
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-
-        BiometricNotificationUtils.cancelFingerprintEnrollNotification(getContext());
-    }
-
-    @NonNull
-    @Override
-    protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) {
-        return new ClientMonitorCompositeCallback(
-                getLogger().getAmbientLightProbe(true /* startWithClient */), callback);
-    }
-
-    @Override
-    protected boolean hasReachedEnrollmentLimit() {
-        final int limit = getContext().getResources().getInteger(
-                com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
-        final int enrolled = mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId())
-                .size();
-        if (enrolled >= limit) {
-            Slog.w(TAG, "Too many fingerprints registered, user: " + getTargetUserId());
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), getRequestReasonFromEnrollReason(mEnrollReason),
-                this);
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStarted(
-                    getRequestReasonFromEnrollReason(mEnrollReason));
-        }
-
-        BiometricNotificationUtils.cancelBadCalibrationNotification(getContext());
-        try {
-            // GroupId was never used. In fact, groupId is always the same as userId.
-            getFreshDaemon().enroll(mHardwareAuthToken, getTargetUserId(), mTimeoutSec);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting enroll", e);
-            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                    0 /* vendorCode */);
-            mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    protected void stopHalOperation() {
-        mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
-
-        try {
-            getFreshDaemon().cancel();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting cancel", e);
-            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                    0 /* vendorCode */);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
-        super.onEnrollResult(identifier, remaining);
-
-        mSensorOverlays.ifUdfps(
-                controller -> controller.onEnrollmentProgress(getSensorId(), remaining));
-
-        if (remaining == 0) {
-            mSensorOverlays.hide(getSensorId());
-            if (sidefpsControllerRefactor()) {
-                mAuthenticationStateListeners.onAuthenticationStopped();
-            }
-        }
-    }
-
-    @Override
-    public void onAcquired(int acquiredInfo, int vendorCode) {
-        super.onAcquired(acquiredInfo, vendorCode);
-
-        mSensorOverlays.ifUdfps(controller -> {
-            if (UdfpsHelper.isValidAcquisitionMessage(getContext(), acquiredInfo, vendorCode)) {
-                controller.onEnrollmentHelp(getSensorId());
-            }
-        });
-
-        mCallback.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
-    }
-
-    @Override
-    public void onError(int errorCode, int vendorCode) {
-        super.onError(errorCode, vendorCode);
-
-        mSensorOverlays.hide(getSensorId());
-        if (sidefpsControllerRefactor()) {
-            mAuthenticationStateListeners.onAuthenticationStopped();
-        }
-    }
-
-    @Override
-    public void onPointerDown(PointerContext pc) {
-        mIsPointerDown = true;
-        UdfpsHelper.onFingerDown(getFreshDaemon(), (int) pc.x, (int) pc.y, pc.minor, pc.major);
-    }
-
-    @Override
-    public void onPointerUp(PointerContext pc) {
-        mIsPointerDown = false;
-        UdfpsHelper.onFingerUp(getFreshDaemon());
-    }
-
-    @Override
-    public boolean isPointerDown() {
-        return mIsPointerDown;
-    }
-
-    @Override
-    public void onUdfpsUiEvent(@FingerprintManager.UdfpsUiEvent int event) {
-        // Unsupported in HIDL.
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
deleted file mode 100644
index 3bb7135..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.GenerateChallengeClient;
-
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific generateChallenge/preEnroll client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-public class FingerprintGenerateChallengeClient
-        extends GenerateChallengeClient<IBiometricsFingerprint> {
-
-    private static final String TAG = "FingerprintGenerateChallengeClient";
-
-    FingerprintGenerateChallengeClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
-            int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext) {
-        super(context, lazyDaemon, token, listener, userId, owner, sensorId, logger,
-                biometricContext);
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            final long challenge = getFreshDaemon().preEnroll();
-            try {
-                getListener().onChallengeGenerated(getSensorId(), getTargetUserId(), challenge);
-                mCallback.onClientFinished(this, true /* success */);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote exception", e);
-                mCallback.onClientFinished(this, false /* success */);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "preEnroll failed", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
deleted file mode 100644
index 8b61f59..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.Fingerprint;
-import android.os.IBinder;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.InternalCleanupClient;
-import com.android.server.biometrics.sensors.InternalEnumerateClient;
-import com.android.server.biometrics.sensors.RemovalClient;
-
-import java.util.List;
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific internal cleanup client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-class FingerprintInternalCleanupClient
-        extends InternalCleanupClient<Fingerprint, IBiometricsFingerprint> {
-
-    FingerprintInternalCleanupClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
-            @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull BiometricUtils<Fingerprint> utils,
-            @NonNull Map<Integer, Long> authenticatorIds) {
-        super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
-                utils, authenticatorIds);
-    }
-
-    @Override
-    protected InternalEnumerateClient<IBiometricsFingerprint> getEnumerateClient(
-            Context context, Supplier<IBiometricsFingerprint> lazyDaemon, IBinder token,
-            int userId, String owner, List<Fingerprint> enrolledList,
-            BiometricUtils<Fingerprint> utils, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
-        return new FingerprintInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
-                enrolledList, utils, sensorId, logger, biometricContext);
-    }
-
-    @Override
-    protected RemovalClient<Fingerprint, IBiometricsFingerprint> getRemovalClient(Context context,
-            Supplier<IBiometricsFingerprint> lazyDaemon, IBinder token,
-            int biometricId, int userId, String owner, BiometricUtils<Fingerprint> utils,
-            int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext, Map<Integer, Long> authenticatorIds) {
-        // Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
-        // is all done internally.
-        return new FingerprintRemovalClient(context, lazyDaemon, token,
-                null /* ClientMonitorCallbackConverter */, biometricId, userId, owner, utils,
-                sensorId, logger, biometricContext, authenticatorIds);
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java
deleted file mode 100644
index 0840f1b..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.Fingerprint;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.InternalEnumerateClient;
-
-import java.util.List;
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific internal enumerate client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-class FingerprintInternalEnumerateClient extends InternalEnumerateClient<IBiometricsFingerprint> {
-    private static final String TAG = "FingerprintInternalEnumerateClient";
-
-    FingerprintInternalEnumerateClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
-            int userId, @NonNull String owner, @NonNull List<Fingerprint> enrolledList,
-            @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
-        super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
-                logger, biometricContext);
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            getFreshDaemon().enumerate();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting enumerate", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java
deleted file mode 100644
index 9ec56c2..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.Fingerprint;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BiometricUtils;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.RemovalClient;
-
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific removal client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-class FingerprintRemovalClient extends RemovalClient<Fingerprint, IBiometricsFingerprint> {
-    private static final String TAG = "FingerprintRemovalClient";
-
-    private final int mBiometricId;
-
-    FingerprintRemovalClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
-            @NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId,
-            @NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull Map<Integer, Long> authenticatorIds) {
-        super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
-                logger, biometricContext, authenticatorIds);
-        mBiometricId = biometricId;
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            // GroupId was never used. In fact, groupId is always the same as userId.
-            getFreshDaemon().remove(getTargetUserId(), mBiometricId);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Remote exception when requesting remove", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
deleted file mode 100644
index 843fcc8..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
+++ /dev/null
@@ -1,61 +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.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-
-import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-
-/**
- * Clears lockout, which is handled in the framework (and not the HAL) for the
- * [email protected] interface.
- */
-public class FingerprintResetLockoutClient extends BaseClientMonitor {
-
-    @NonNull final LockoutFrameworkImpl mLockoutTracker;
-
-    public FingerprintResetLockoutClient(@NonNull Context context, int userId,
-            @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull LockoutFrameworkImpl lockoutTracker) {
-        super(context, null /* token */, null /* listener */, userId, owner, 0 /* cookie */,
-                sensorId, logger, biometricContext);
-        mLockoutTracker = lockoutTracker;
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-        mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */,
-                getTargetUserId());
-        callback.onClientFinished(this, true /* success */);
-    }
-
-    public boolean interruptsPrecedingClients() {
-        return true;
-    }
-
-    @Override
-    public int getProtoEnum() {
-        return BiometricsProto.CM_RESET_LOCKOUT;
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
deleted file mode 100644
index 6273417..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.RevokeChallengeClient;
-
-import java.util.function.Supplier;
-
-/**
- * Fingerprint-specific revokeChallenge client supporting the
- * {@link android.hardware.biometrics.fingerprint.V2_1} and
- * {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
- */
-public class FingerprintRevokeChallengeClient
-        extends RevokeChallengeClient<IBiometricsFingerprint> {
-
-    private static final String TAG = "FingerprintRevokeChallengeClient";
-
-    FingerprintRevokeChallengeClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
-            int userId, @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
-        super(context, lazyDaemon, token, userId, owner, sensorId, logger, biometricContext);
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            getFreshDaemon().postEnroll();
-            mCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "revokeChallenge/postEnroll failed", e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClientLegacy.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClientLegacy.java
deleted file mode 100644
index fc85402..0000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClientLegacy.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.os.Build;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.os.SELinux;
-import android.util.Slog;
-
-import com.android.server.biometrics.BiometricsProto;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.HalClientMonitor;
-
-import java.io.File;
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * TODO(b/304604965): Delete this class once Flags.DE_HIDL is ready for release.
- */
-public class FingerprintUpdateActiveUserClientLegacy extends
-        HalClientMonitor<IBiometricsFingerprint> {
-    private static final String TAG = "FingerprintUpdateActiveUserClient";
-    private static final String FP_DATA_DIR = "fpdata";
-
-    private final Supplier<Integer> mCurrentUserId;
-    private final boolean mForceUpdateAuthenticatorId;
-    private final boolean mHasEnrolledBiometrics;
-    private final Map<Integer, Long> mAuthenticatorIds;
-    private File mDirectory;
-
-    FingerprintUpdateActiveUserClientLegacy(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
-            @NonNull String owner, int sensorId,
-            @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull Supplier<Integer> currentUserId,
-            boolean hasEnrolledBiometrics, @NonNull Map<Integer, Long> authenticatorIds,
-            boolean forceUpdateAuthenticatorId) {
-        super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
-                0 /* cookie */, sensorId, logger, biometricContext);
-        mCurrentUserId = currentUserId;
-        mForceUpdateAuthenticatorId = forceUpdateAuthenticatorId;
-        mHasEnrolledBiometrics = hasEnrolledBiometrics;
-        mAuthenticatorIds = authenticatorIds;
-    }
-
-    @Override
-    public void start(@NonNull ClientMonitorCallback callback) {
-        super.start(callback);
-
-        if (mCurrentUserId.get() == getTargetUserId() && !mForceUpdateAuthenticatorId) {
-            Slog.d(TAG, "Already user: " + mCurrentUserId + ", returning");
-            callback.onClientFinished(this, true /* success */);
-            return;
-        }
-
-        int firstSdkInt = Build.VERSION.DEVICE_INITIAL_SDK_INT;
-        if (firstSdkInt < Build.VERSION_CODES.BASE) {
-            Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be "
-                    + "at least VERSION_CODES.BASE");
-        }
-        File baseDir;
-        if (firstSdkInt <= Build.VERSION_CODES.O_MR1) {
-            baseDir = Environment.getUserSystemDirectory(getTargetUserId());
-        } else {
-            baseDir = Environment.getDataVendorDeDirectory(getTargetUserId());
-        }
-
-        mDirectory = new File(baseDir, FP_DATA_DIR);
-        if (!mDirectory.exists()) {
-            if (!mDirectory.mkdir()) {
-                Slog.e(TAG, "Cannot make directory: " + mDirectory.getAbsolutePath());
-                callback.onClientFinished(this, false /* success */);
-                return;
-            }
-            // Calling mkdir() from this process will create a directory with our
-            // permissions (inherited from the containing dir). This command fixes
-            // the label.
-            if (!SELinux.restorecon(mDirectory)) {
-                Slog.e(TAG, "Restorecons failed. Directory will have wrong label.");
-                callback.onClientFinished(this, false /* success */);
-                return;
-            }
-        }
-
-        startHalOperation();
-    }
-
-    @Override
-    public void unableToStart() {
-        // Nothing to do here
-    }
-
-    @Override
-    protected void startHalOperation() {
-        try {
-            final int targetId = getTargetUserId();
-            Slog.d(TAG, "Setting active user: " + targetId);
-            getFreshDaemon().setActiveGroup(targetId, mDirectory.getAbsolutePath());
-            mAuthenticatorIds.put(targetId, mHasEnrolledBiometrics
-                    ? getFreshDaemon().getAuthenticatorId() : 0L);
-            mCallback.onClientFinished(this, true /* success */);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to setActiveGroup: " + e);
-            mCallback.onClientFinished(this, false /* success */);
-        }
-    }
-
-    @Override
-    public int getProtoEnum() {
-        return BiometricsProto.CM_UPDATE_ACTIVE_USER;
-    }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java
index 47fdcdb9..3214b6d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java
@@ -186,7 +186,7 @@
                 mLockoutTracker,
                 mLockoutResetDispatcher,
                 mAuthSessionCoordinator,
-                () -> {}, mAidlResponseHandlerCallback);
+                mAidlResponseHandlerCallback);
     }
 
     @VisibleForTesting IBiometricsFingerprint getIBiometricsFingerprint() {
diff --git a/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java b/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java
index 16514fa..e6de14b 100644
--- a/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java
+++ b/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java
@@ -29,7 +29,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.util.IndentingPrintWriter;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -122,7 +121,8 @@
                     + " without permission " + Manifest.permission.DUMP);
             return;
         }
-        IndentingPrintWriter radioPrintWriter = new IndentingPrintWriter(printWriter);
+        android.util.IndentingPrintWriter radioPrintWriter =
+                new android.util.IndentingPrintWriter(printWriter);
         radioPrintWriter.printf("BroadcastRadioService\n");
 
         radioPrintWriter.increaseIndent();
diff --git a/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java b/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java
index ab08342..93fb7b2 100644
--- a/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java
+++ b/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java
@@ -26,7 +26,6 @@
 import android.hardware.radio.RadioManager;
 import android.os.Binder;
 import android.os.RemoteException;
-import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Slog;
 
@@ -139,7 +138,7 @@
                     + " without permission " + Manifest.permission.DUMP);
             return;
         }
-        IndentingPrintWriter radioPw = new IndentingPrintWriter(pw);
+        android.util.IndentingPrintWriter radioPw = new android.util.IndentingPrintWriter(pw);
         radioPw.printf("BroadcastRadioService\n");
 
         radioPw.increaseIndent();
diff --git a/services/core/java/com/android/server/broadcastradio/RadioEventLogger.java b/services/core/java/com/android/server/broadcastradio/RadioEventLogger.java
new file mode 100644
index 0000000..2c8f499
--- /dev/null
+++ b/services/core/java/com/android/server/broadcastradio/RadioEventLogger.java
@@ -0,0 +1,60 @@
+/**
+ * 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.broadcastradio;
+
+import android.text.TextUtils;
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.server.utils.Slogf;
+
+/**
+ * Event logger to log and dump events of broadcast radio service client for HIDL and AIDL
+ * broadcast HAL.
+ */
+public final class RadioEventLogger {
+    private final String mTag;
+    private final boolean mDebug;
+    private final LocalLog mEventLogger;
+
+    public RadioEventLogger(String tag, int loggerQueueSize) {
+        mTag = tag;
+        mDebug = Log.isLoggable(mTag, Log.DEBUG);
+        mEventLogger = new LocalLog(loggerQueueSize);
+    }
+
+    /**
+     * Log broadcast radio service event
+     * @param logFormat String format of log message
+     * @param args Arguments of log message
+     */
+    public void logRadioEvent(String logFormat, Object... args) {
+        String log = TextUtils.formatSimple(logFormat, args);
+        mEventLogger.log(log);
+        if (mDebug) {
+            Slogf.d(mTag, logFormat, args);
+        }
+    }
+
+    /**
+     * Dump broadcast radio service event
+     * @param pw Indenting print writer for dump
+     */
+    public void dump(android.util.IndentingPrintWriter pw) {
+        mEventLogger.dump(pw);
+    }
+}
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/AnnouncementAggregator.java b/services/core/java/com/android/server/broadcastradio/aidl/AnnouncementAggregator.java
index b618aa3..9654a93 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/AnnouncementAggregator.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/AnnouncementAggregator.java
@@ -22,7 +22,6 @@
 import android.hardware.radio.ICloseHandle;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.util.IndentingPrintWriter;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -94,7 +93,7 @@
             if (mCloseHandle != null) mCloseHandle.close();
         }
 
-        public void dumpInfo(IndentingPrintWriter pw) {
+        public void dumpInfo(android.util.IndentingPrintWriter pw) {
             pw.printf("ModuleWatcher:\n");
 
             pw.increaseIndent();
@@ -192,7 +191,8 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
-        IndentingPrintWriter announcementPrintWriter = new IndentingPrintWriter(printWriter);
+        android.util.IndentingPrintWriter announcementPrintWriter =
+                new android.util.IndentingPrintWriter(printWriter);
         announcementPrintWriter.printf("AnnouncementAggregator\n");
 
         announcementPrintWriter.increaseIndent();
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java b/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java
index 086f3aa..1c42161 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java
@@ -29,7 +29,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.ArrayMap;
-import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -261,7 +260,7 @@
      *
      * @param pw The file to which {@link BroadcastRadioServiceImpl} state is dumped.
      */
-    public void dumpInfo(IndentingPrintWriter pw) {
+    public void dumpInfo(android.util.IndentingPrintWriter pw) {
         synchronized (mLock) {
             pw.printf("Next module id available: %d\n", mNextModuleId);
             pw.printf("ServiceName to module id map:\n");
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioLogger.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioLogger.java
deleted file mode 100644
index cca351b..0000000
--- a/services/core/java/com/android/server/broadcastradio/aidl/RadioLogger.java
+++ /dev/null
@@ -1,52 +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.broadcastradio.aidl;
-
-import android.text.TextUtils;
-import android.util.IndentingPrintWriter;
-import android.util.LocalLog;
-import android.util.Log;
-
-import com.android.server.utils.Slogf;
-
-/**
- * Event logger to log and dump events of radio module and tuner session
- * for AIDL broadcast radio HAL
- */
-final class RadioLogger {
-    private final String mTag;
-    private final boolean mDebug;
-    private final LocalLog mEventLogger;
-
-    RadioLogger(String tag, int loggerQueueSize) {
-        mTag = tag;
-        mDebug = Log.isLoggable(mTag, Log.DEBUG);
-        mEventLogger = new LocalLog(loggerQueueSize);
-    }
-
-    void logRadioEvent(String logFormat, Object... args) {
-        String log = TextUtils.formatSimple(logFormat, args);
-        mEventLogger.log(log);
-        if (mDebug) {
-            Slogf.d(mTag, logFormat, args);
-        }
-    }
-
-    void dump(IndentingPrintWriter pw) {
-        mEventLogger.dump(pw);
-    }
-}
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
index cd86510..0cac356 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
@@ -38,10 +38,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArraySet;
-import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.broadcastradio.RadioEventLogger;
 import com.android.server.broadcastradio.RadioServiceUserController;
 import com.android.server.utils.Slogf;
 
@@ -59,7 +59,7 @@
 
     private final Object mLock = new Object();
     private final Handler mHandler;
-    private final RadioLogger mLogger;
+    private final RadioEventLogger mLogger;
     private final RadioManager.ModuleProperties mProperties;
 
     /**
@@ -197,7 +197,7 @@
         mProperties = Objects.requireNonNull(properties, "properties cannot be null");
         mService = Objects.requireNonNull(service, "service cannot be null");
         mHandler = new Handler(Looper.getMainLooper());
-        mLogger = new RadioLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE);
+        mLogger = new RadioEventLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE);
     }
 
     @Nullable
@@ -524,7 +524,7 @@
         return BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
     }
 
-    void dumpInfo(IndentingPrintWriter pw) {
+    void dumpInfo(android.util.IndentingPrintWriter pw) {
         pw.printf("RadioModule\n");
 
         pw.increaseIndent();
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
index 4ed36ec..925f149 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
@@ -29,9 +29,9 @@
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.broadcastradio.RadioEventLogger;
 import com.android.server.broadcastradio.RadioServiceUserController;
 import com.android.server.utils.Slogf;
 
@@ -45,7 +45,7 @@
 
     private final Object mLock = new Object();
 
-    private final RadioLogger mLogger;
+    private final RadioEventLogger mLogger;
     private final RadioModule mModule;
     final int mUserId;
     final android.hardware.radio.ITunerCallback mCallback;
@@ -70,7 +70,7 @@
         mUserId = Binder.getCallingUserHandle().getIdentifier();
         mCallback = Objects.requireNonNull(callback, "callback cannot be null");
         mUid = Binder.getCallingUid();
-        mLogger = new RadioLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
+        mLogger = new RadioEventLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
     }
 
     @Override
@@ -434,7 +434,7 @@
         }
     }
 
-    void dumpInfo(IndentingPrintWriter pw) {
+    void dumpInfo(android.util.IndentingPrintWriter pw) {
         pw.printf("TunerSession\n");
 
         pw.increaseIndent();
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 3198842..e1650c2 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -30,7 +30,6 @@
 import android.os.IHwBinder.DeathRecipient;
 import android.os.RemoteException;
 import android.util.ArrayMap;
-import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -222,7 +221,7 @@
      *
      * @param pw The file to which BroadcastRadioService state is dumped.
      */
-    public void dumpInfo(IndentingPrintWriter pw) {
+    public void dumpInfo(android.util.IndentingPrintWriter pw) {
         synchronized (mLock) {
             pw.printf("Next module id available: %d\n", mNextModuleId);
             pw.printf("ServiceName to module id map:\n");
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java
deleted file mode 100644
index b8d1228..0000000
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java
+++ /dev/null
@@ -1,46 +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.broadcastradio.hal2;
-
-import android.util.IndentingPrintWriter;
-import android.util.LocalLog;
-import android.util.Log;
-
-import com.android.server.utils.Slogf;
-
-final class RadioEventLogger {
-    private final String mTag;
-    private final LocalLog mEventLogger;
-
-    RadioEventLogger(String tag, int loggerQueueSize) {
-        mTag = tag;
-        mEventLogger = new LocalLog(loggerQueueSize);
-    }
-
-    @SuppressWarnings("AnnotateFormatMethod")
-    void logRadioEvent(String logFormat, Object... args) {
-        String log = String.format(logFormat, args);
-        mEventLogger.log(log);
-        if (Log.isLoggable(mTag, Log.DEBUG)) {
-            Slogf.d(mTag, log);
-        }
-    }
-
-    void dump(IndentingPrintWriter pw) {
-        mEventLogger.dump(pw);
-    }
-}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 0e11df8..7269f24 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -40,11 +40,11 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArraySet;
-import android.util.IndentingPrintWriter;
 import android.util.MutableInt;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.broadcastradio.RadioEventLogger;
 import com.android.server.broadcastradio.RadioServiceUserController;
 import com.android.server.utils.Slogf;
 
@@ -453,7 +453,7 @@
         return BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
     }
 
-    void dumpInfo(IndentingPrintWriter pw) {
+    void dumpInfo(android.util.IndentingPrintWriter pw) {
         pw.printf("RadioModule\n");
         pw.increaseIndent();
         pw.printf("BroadcastRadioService: %s\n", mService);
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 6d435e3..b1b5d34 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -31,11 +31,11 @@
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.IndentingPrintWriter;
 import android.util.MutableBoolean;
 import android.util.MutableInt;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.broadcastradio.RadioEventLogger;
 import com.android.server.broadcastradio.RadioServiceUserController;
 import com.android.server.utils.Slogf;
 
@@ -389,7 +389,7 @@
         }
     }
 
-    void dumpInfo(IndentingPrintWriter pw) {
+    void dumpInfo(android.util.IndentingPrintWriter pw) {
         pw.printf("TunerSession\n");
         pw.increaseIndent();
         pw.printf("HIDL HAL Session: %s\n", mHwSession);
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 05e681e..645a366 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -61,6 +61,9 @@
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -69,6 +72,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Range;
 import android.util.Slog;
 import android.view.Display;
 import android.view.IDisplayWindowListener;
@@ -85,6 +89,8 @@
 import com.android.server.SystemService;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -243,6 +249,7 @@
         public int mVideoStabilizationMode;
         public boolean mUsedUltraWide;
         public boolean mUsedZoomOverride;
+        public Range<Integer> mMostRequestedFpsRange;
         public final long mLogId;
         public final int mSessionIndex;
 
@@ -265,13 +272,15 @@
             mDeviceError = deviceError;
             mLogId = logId;
             mSessionIndex = sessionIdx;
+            mMostRequestedFpsRange = new Range<Integer>(0, 0);
         }
 
         public void markCompleted(int internalReconfigure, long requestCount,
                 long resultErrorCount, boolean deviceError,
                 List<CameraStreamStats>  streamStats, String userTag,
                 int videoStabilizationMode, boolean usedUltraWide,
-                boolean usedZoomOverride, CameraExtensionSessionStats extStats) {
+                boolean usedZoomOverride, Range<Integer> mostRequestedFpsRange,
+                CameraExtensionSessionStats extStats) {
             if (mCompleted) {
                 return;
             }
@@ -287,6 +296,7 @@
             mUsedUltraWide = usedUltraWide;
             mUsedZoomOverride = usedZoomOverride;
             mExtSessionStats = extStats;
+            mMostRequestedFpsRange = mostRequestedFpsRange;
             if (CameraServiceProxy.DEBUG) {
                 Slog.v(TAG, "A camera facing " + cameraFacingToString(mCameraFacing) +
                         " was in use by " + mClientName + " for " +
@@ -637,6 +647,60 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ShellCallback callback, ResultReceiver resultReceiver)
+                throws RemoteException {
+            new CSPShellCmd(CameraServiceProxy.this)
+                .exec(this, in, out, err, args, callback, resultReceiver);
+        }
+
+        private static class CSPShellCmd extends ShellCommand {
+            private static final String TAG = "CSPShellCmd";
+            private static final String USAGE = """
+                    usage: cmd media.camera.proxy SUBCMD [args]
+
+                    SUBCMDs:
+                        dump_events: Write out all collected camera usage events to statsd.
+                            Does not print to terminal.
+                        help: You're reading it.
+                    """;
+
+            private final CameraServiceProxy mCameraServiceProxy;
+
+            CSPShellCmd(CameraServiceProxy proxy) {
+                mCameraServiceProxy = proxy;
+            }
+
+            @Override
+            public int onCommand(String cmd) {
+                if (cmd == null) {
+                    return handleDefaultCommands(cmd);
+                }
+                final PrintWriter pw = getOutPrintWriter();
+                try {
+                    switch (cmd.replace('-', '_')) {
+                        case "dump_events":
+                            int eventCount = mCameraServiceProxy.getUsageEventCount();
+                            mCameraServiceProxy.dumpUsageEvents();
+                            pw.println("Camera usage events dumped: " + eventCount);
+                            break;
+                        default:
+                            return handleDefaultCommands(cmd);
+                    }
+                } catch (Exception e) {
+                    Slog.e(mCameraServiceProxy.TAG, "Error running shell command", e);
+                    return 1;
+                }
+                return 0;
+            }
+
+            @Override
+            public void onHelp() {
+                getOutPrintWriter().println(USAGE);
+            }
+        }
     };
 
     private final FoldStateListener mFoldStateListener;
@@ -882,6 +946,9 @@
                         ? ", zoomOverrideUsage " + e.mUsedZoomOverride
                         : "";
 
+                String mostRequestedFpsRangeDebug = Flags.analytics24q3()
+                        ? ", mostRequestedFpsRange " + e.mMostRequestedFpsRange
+                        : "";
                 Slog.v(TAG, "CAMERA_ACTION_EVENT: action " + e.mAction
                         + " clientName " + e.mClientName
                         + ", duration " + e.getDuration()
@@ -900,6 +967,7 @@
                         + ", videoStabilizationMode " + e.mVideoStabilizationMode
                         + ultrawideDebug
                         + zoomOverrideDebug
+                        + mostRequestedFpsRangeDebug
                         + ", logId " + e.mLogId
                         + ", sessionIndex " + e.mSessionIndex
                         + ", mExtSessionStats {type " + extensionType
@@ -966,7 +1034,17 @@
                     e.mUserTag, e.mVideoStabilizationMode,
                     e.mLogId, e.mSessionIndex,
                     extensionType, extensionIsAdvanced, e.mUsedUltraWide,
-                    e.mUsedZoomOverride);
+                    e.mUsedZoomOverride,
+                    e.mMostRequestedFpsRange.getLower(), e.mMostRequestedFpsRange.getUpper());
+        }
+    }
+
+    /**
+     * Get camera usage event count
+     */
+    int getUsageEventCount() {
+        synchronized (mLock) {
+            return mCameraUsageHistory.size();
         }
     }
 
@@ -1173,6 +1251,10 @@
         long logId = cameraState.getLogId();
         int sessionIdx = cameraState.getSessionIndex();
         CameraExtensionSessionStats extSessionStats = cameraState.getExtensionSessionStats();
+        Range<Integer> mostRequestedFpsRange = Flags.analytics24q3()
+                ? cameraState.getMostRequestedFpsRange()
+                : new Range<Integer>(0, 0);
+
         synchronized(mLock) {
             // Update active camera list and notify NFC if necessary
             boolean wasEmpty = mActiveCameraUsage.isEmpty();
@@ -1228,7 +1310,8 @@
                         oldEvent.markCompleted(/*internalReconfigure*/0, /*requestCount*/0,
                                 /*resultErrorCount*/0, /*deviceError*/false, streamStats,
                                 /*userTag*/"", /*videoStabilizationMode*/-1, /*usedUltraWide*/false,
-                                /*usedZoomOverride*/false, new CameraExtensionSessionStats());
+                                /*usedZoomOverride*/false, new Range<Integer>(0, 0),
+                                new CameraExtensionSessionStats());
                         mCameraUsageHistory.add(oldEvent);
                     }
                     break;
@@ -1240,7 +1323,7 @@
                         doneEvent.markCompleted(internalReconfigureCount, requestCount,
                                 resultErrorCount, deviceError, streamStats, userTag,
                                 videoStabilizationMode, usedUltraWide, usedZoomOverride,
-                                extSessionStats);
+                                mostRequestedFpsRange, extSessionStats);
                         mCameraUsageHistory.add(doneEvent);
                         // Do not double count device error
                         deviceError = false;
diff --git a/services/core/java/com/android/server/connectivity/Android.bp b/services/core/java/com/android/server/connectivity/Android.bp
new file mode 100644
index 0000000..0916594
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/Android.bp
@@ -0,0 +1,11 @@
+aconfig_declarations {
+    name: "connectivity_flags",
+    package: "com.android.server.connectivity",
+    container: "system",
+    srcs: ["flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "connectivity_flags_lib",
+    aconfig_declarations: "connectivity_flags",
+}
diff --git a/services/core/java/com/android/server/connectivity/flags.aconfig b/services/core/java/com/android/server/connectivity/flags.aconfig
new file mode 100644
index 0000000..8fd3ce5
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/flags.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.server.connectivity"
+container: "system"
+
+flag {
+    name: "replace_vpn_profile_store"
+    namespace: "android_core_networking"
+    description: "This flag controls the usage of VpnBlobStore to replace LegacyVpnProfileStore."
+    bug: "307903113"
+}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 9f4b3d2..c393e92 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1651,7 +1651,7 @@
                 return AppBackgroundRestrictionsInfo.LEVEL_RESTRICTED_BUCKET;
             case ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
                 return AppBackgroundRestrictionsInfo.LEVEL_BACKGROUND_RESTRICTED;
-            case ActivityManager.RESTRICTION_LEVEL_HIBERNATION:
+            case ActivityManager.RESTRICTION_LEVEL_FORCE_STOPPED:
                 return AppBackgroundRestrictionsInfo.LEVEL_HIBERNATION;
             default:
                 return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN;
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 06dc7f5..9c020a7 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -425,7 +425,7 @@
         return mScreenAutoBrightness;
     }
 
-    float getRawAutomaticScreenBrightness() {
+    public float getRawAutomaticScreenBrightness() {
         return mRawScreenAutoBrightness;
     }
 
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index dc0e80c..9b37418 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -19,7 +19,6 @@
 import android.hardware.display.BrightnessInfo;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.PowerManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.display.brightness.clamper.HdrClamper;
@@ -148,9 +147,7 @@
 
     float getHdrBrightnessValue() {
         float hdrBrightness = mHbmController.getHdrBrightnessValue();
-        float brightnessMax = mUseHdrClamper ? mHdrClamper.getMaxBrightness()
-                : PowerManager.BRIGHTNESS_MAX;
-        return Math.min(hdrBrightness, brightnessMax);
+        return mUseHdrClamper ? mHdrClamper.clamp(hdrBrightness) : hdrBrightness;
     }
 
     float getTransitionPoint() {
diff --git a/services/core/java/com/android/server/display/DisplayBrightnessState.java b/services/core/java/com/android/server/display/DisplayBrightnessState.java
index d50a43a..baa154d 100644
--- a/services/core/java/com/android/server/display/DisplayBrightnessState.java
+++ b/services/core/java/com/android/server/display/DisplayBrightnessState.java
@@ -18,6 +18,7 @@
 
 import android.text.TextUtils;
 
+import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.brightness.BrightnessReason;
 
 import java.util.Objects;
@@ -43,6 +44,9 @@
 
     private final float mCustomAnimationRate;
 
+    private final BrightnessEvent mBrightnessEvent;
+    private final int mBrightnessAdjustmentFlag;
+
     private DisplayBrightnessState(Builder builder) {
         mBrightness = builder.getBrightness();
         mSdrBrightness = builder.getSdrBrightness();
@@ -54,6 +58,8 @@
         mMinBrightness = builder.getMinBrightness();
         mCustomAnimationRate = builder.getCustomAnimationRate();
         mShouldUpdateScreenBrightnessSetting = builder.shouldUpdateScreenBrightnessSetting();
+        mBrightnessEvent = builder.getBrightnessEvent();
+        mBrightnessAdjustmentFlag = builder.getBrightnessAdjustmentFlag();
     }
 
     /**
@@ -127,6 +133,21 @@
         return mShouldUpdateScreenBrightnessSetting;
     }
 
+    /**
+     * @return The BrightnessEvent object
+     */
+    public BrightnessEvent getBrightnessEvent() {
+        return mBrightnessEvent;
+    }
+
+    /**
+     * Gets the flag representing the reason for the brightness adjustment. This can be
+     * automatic(e.g. because of the change in the lux), or user initiated(e.g. moving the slider)
+     */
+    public int getBrightnessAdjustmentFlag() {
+        return mBrightnessAdjustmentFlag;
+    }
+
     @Override
     public String toString() {
         StringBuilder stringBuilder = new StringBuilder("DisplayBrightnessState:");
@@ -144,6 +165,9 @@
         stringBuilder.append("\n    customAnimationRate:").append(mCustomAnimationRate);
         stringBuilder.append("\n    shouldUpdateScreenBrightnessSetting:")
                 .append(mShouldUpdateScreenBrightnessSetting);
+        stringBuilder.append("\n    mBrightnessEvent:")
+                .append(Objects.toString(mBrightnessEvent, "null"));
+        stringBuilder.append("\n    mBrightnessAdjustmentFlag:").append(mBrightnessAdjustmentFlag);
         return stringBuilder.toString();
     }
 
@@ -173,7 +197,9 @@
                 && mMinBrightness == otherState.getMinBrightness()
                 && mCustomAnimationRate == otherState.getCustomAnimationRate()
                 && mShouldUpdateScreenBrightnessSetting
-                    == otherState.shouldUpdateScreenBrightnessSetting();
+                    == otherState.shouldUpdateScreenBrightnessSetting()
+                && Objects.equals(mBrightnessEvent, otherState.getBrightnessEvent())
+                && mBrightnessAdjustmentFlag == otherState.getBrightnessAdjustmentFlag();
     }
 
     @Override
@@ -181,7 +207,7 @@
         return Objects.hash(mBrightness, mSdrBrightness, mBrightnessReason,
                 mShouldUseAutoBrightness, mIsSlowChange, mMaxBrightness, mMinBrightness,
                 mCustomAnimationRate,
-                mShouldUpdateScreenBrightnessSetting);
+                mShouldUpdateScreenBrightnessSetting, mBrightnessEvent, mBrightnessAdjustmentFlag);
     }
 
     /**
@@ -206,6 +232,10 @@
         private float mCustomAnimationRate = CUSTOM_ANIMATION_RATE_NOT_SET;
         private boolean mShouldUpdateScreenBrightnessSetting;
 
+        private BrightnessEvent mBrightnessEvent;
+
+        public int mBrightnessAdjustmentFlag = 0;
+
         /**
          * Create a builder starting with the values from the specified {@link
          * DisplayBrightnessState}.
@@ -225,6 +255,8 @@
             builder.setCustomAnimationRate(state.getCustomAnimationRate());
             builder.setShouldUpdateScreenBrightnessSetting(
                     state.shouldUpdateScreenBrightnessSetting());
+            builder.setBrightnessEvent(state.getBrightnessEvent());
+            builder.setBrightnessAdjustmentFlag(state.getBrightnessAdjustmentFlag());
             return builder;
         }
 
@@ -400,5 +432,37 @@
         public DisplayBrightnessState build() {
             return new DisplayBrightnessState(this);
         }
+
+        /**
+         * This is used to get the BrightnessEvent object from its builder
+         */
+        public BrightnessEvent getBrightnessEvent() {
+            return mBrightnessEvent;
+        }
+
+
+        /**
+         * This is used to set the BrightnessEvent object
+         */
+        public Builder setBrightnessEvent(BrightnessEvent brightnessEvent) {
+            mBrightnessEvent = brightnessEvent;
+            return this;
+        }
+
+        /**
+         * This is used to get the brightness adjustment flag from its builder
+         */
+        public int getBrightnessAdjustmentFlag() {
+            return mBrightnessAdjustmentFlag;
+        }
+
+
+        /**
+         * This is used to set the brightness adjustment flag
+         */
+        public Builder setBrightnessAdjustmentFlag(int brightnessAdjustmentFlag) {
+            mBrightnessAdjustmentFlag = brightnessAdjustmentFlag;
+            return this;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 85a231f..a6335e3 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -70,6 +70,7 @@
 import com.android.server.display.config.PowerThrottlingPoint;
 import com.android.server.display.config.PredefinedBrightnessLimitNames;
 import com.android.server.display.config.RefreshRateConfigs;
+import com.android.server.display.config.RefreshRateData;
 import com.android.server.display.config.RefreshRateRange;
 import com.android.server.display.config.RefreshRateThrottlingMap;
 import com.android.server.display.config.RefreshRateThrottlingPoint;
@@ -585,7 +586,7 @@
  *              </point>
  *          </luxThresholds>
  *     </idleScreenRefreshRateTimeout>
- *
+ *     <supportsVrr>true</supportsVrr>
  *
  *    </displayConfiguration>
  *  }
@@ -617,9 +618,7 @@
     private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d";
     private static final String NO_SUFFIX_FORMAT = "%d";
     private static final long STABLE_FLAG = 1L << 62;
-    private static final int DEFAULT_PEAK_REFRESH_RATE = 0;
-    private static final int DEFAULT_REFRESH_RATE = 60;
-    private static final int DEFAULT_REFRESH_RATE_IN_HBM = 0;
+
     private static final int DEFAULT_HIGH_REFRESH_RATE = 0;
     private static final float[] DEFAULT_BRIGHTNESS_THRESHOLDS = new float[]{};
 
@@ -754,32 +753,6 @@
     private boolean mDdcAutoBrightnessAvailable = true;
 
     /**
-     * The default peak refresh rate for a given device. This value prevents the framework from
-     * using higher refresh rates, even if display modes with higher refresh rates are available
-     * from hardware composer. Only has an effect if the value is non-zero.
-     */
-    private int mDefaultPeakRefreshRate = DEFAULT_PEAK_REFRESH_RATE;
-
-    /**
-     * The default refresh rate for a given device. This value sets the higher default
-     * refresh rate. If the hardware composer on the device supports display modes with
-     * a higher refresh rate than the default value specified here, the framework may use those
-     * higher refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling
-     * setFrameRate(). We have historically allowed fallback to mDefaultPeakRefreshRate if
-     * mDefaultRefreshRate is set to 0, but this is not supported anymore.
-     */
-    private int mDefaultRefreshRate = DEFAULT_REFRESH_RATE;
-
-    /**
-     * Default refresh rate while the device has high brightness mode enabled for HDR.
-     */
-    private int mDefaultRefreshRateInHbmHdr = DEFAULT_REFRESH_RATE_IN_HBM;
-
-    /**
-     * Default refresh rate while the device has high brightness mode enabled for Sunlight.
-     */
-    private int mDefaultRefreshRateInHbmSunlight = DEFAULT_REFRESH_RATE_IN_HBM;
-    /**
      * Default refresh rate in the high zone defined by brightness and ambient thresholds.
      * If non-positive, then the refresh rate is unchanged even if thresholds are configured.
      */
@@ -867,11 +840,15 @@
     @Nullable
     public EvenDimmerBrightnessData mEvenDimmerBrightnessData;
 
+    private RefreshRateData mRefreshRateData = RefreshRateData.DEFAULT_REFRESH_RATE_DATA;
+
     /**
      * Maximum screen brightness setting when screen brightness capped in Wear Bedtime mode.
      */
     private float mBrightnessCapForWearBedtimeMode;
 
+    private boolean mVrrSupportEnabled;
+
     private final DisplayManagerFlags mFlags;
 
     @VisibleForTesting
@@ -1448,33 +1425,8 @@
         return mDisplayBrightnessMapping.getBrightnessArray(mode, preset);
     }
 
-    /**
-     * @return Default peak refresh rate of the associated display
-     */
-    public int getDefaultPeakRefreshRate() {
-        return mDefaultPeakRefreshRate;
-    }
-
-    /**
-     * @return Default refresh rate of the associated display
-     */
-    public int getDefaultRefreshRate() {
-        return mDefaultRefreshRate;
-    }
-
-    /**
-     * @return Default refresh rate while the device has high brightness mode enabled for HDR.
-     */
-    public int getDefaultRefreshRateInHbmHdr() {
-        return mDefaultRefreshRateInHbmHdr;
-    }
-
-    /**
-     * @return Default refresh rate while the device has high brightness mode enabled because of
-     * high lux.
-     */
-    public int getDefaultRefreshRateInHbmSunlight() {
-        return mDefaultRefreshRateInHbmSunlight;
+    public RefreshRateData getRefreshRateData() {
+        return mRefreshRateData;
     }
 
     /**
@@ -1606,6 +1558,13 @@
         return mBrightnessCapForWearBedtimeMode;
     }
 
+    /**
+     * @return true if display supports dvrr
+     */
+    public boolean isVrrSupportEnabled() {
+        return mVrrSupportEnabled;
+    }
+
     @Override
     public String toString() {
         return "DisplayDeviceConfig{"
@@ -1678,11 +1637,8 @@
                 + "\n"
                 + "mDefaultLowBlockingZoneRefreshRate= " + mDefaultLowBlockingZoneRefreshRate
                 + ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate
-                + ", mDefaultPeakRefreshRate= " + mDefaultPeakRefreshRate
-                + ", mDefaultRefreshRate= " + mDefaultRefreshRate
+                + ", mRefreshRateData= " + mRefreshRateData
                 + ", mRefreshRateZoneProfiles= " + mRefreshRateZoneProfiles
-                + ", mDefaultRefreshRateInHbmHdr= " + mDefaultRefreshRateInHbmHdr
-                + ", mDefaultRefreshRateInHbmSunlight= " + mDefaultRefreshRateInHbmSunlight
                 + ", mRefreshRateThrottlingMap= " + mRefreshRateThrottlingMap
                 + ", mLowBlockingZoneThermalMapId= " + mLowBlockingZoneThermalMapId
                 + ", mHighBlockingZoneThermalMapId= " + mHighBlockingZoneThermalMapId
@@ -1705,6 +1661,8 @@
                 + "\n"
                 + "mEvenDimmerBrightnessData:" + (mEvenDimmerBrightnessData != null
                 ? mEvenDimmerBrightnessData.toString() : "null")
+                + "\n"
+                + "mVrrSupported= " + mVrrSupportEnabled + "\n"
                 + "}";
     }
 
@@ -1755,7 +1713,8 @@
                 loadDensityMapping(config);
                 loadBrightnessDefaultFromDdcXml(config);
                 loadBrightnessConstraintsFromConfigXml();
-                if (mFlags.isEvenDimmerEnabled()) {
+                if (mFlags.isEvenDimmerEnabled() && mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_evenDimmerEnabled)) {
                     mEvenDimmerBrightnessData = EvenDimmerBrightnessData.loadConfig(config);
                 }
                 loadBrightnessMap(config);
@@ -1770,6 +1729,8 @@
                 mScreenOffBrightnessSensor = SensorData.loadScreenOffBrightnessSensorConfig(config);
                 mProximitySensor = SensorData.loadProxSensorConfig(mFlags, config);
                 mTempSensor = SensorData.loadTempSensorConfig(mFlags, config);
+                mRefreshRateData = RefreshRateData
+                        .loadRefreshRateData(config, mContext.getResources());
                 loadAmbientHorizonFromDdc(config);
                 loadBrightnessChangeThresholds(config);
                 loadAutoBrightnessConfigValues(config);
@@ -1779,6 +1740,7 @@
                 mHdrBrightnessData = HdrBrightnessData.loadConfig(config);
                 loadBrightnessCapForWearBedtimeMode(config);
                 loadIdleScreenRefreshRateTimeoutConfigs(config);
+                mVrrSupportEnabled = config.getSupportsVrr();
             } else {
                 Slog.w(TAG, "DisplayDeviceConfig file is null");
             }
@@ -1799,6 +1761,8 @@
         mAmbientLightSensor = SensorData.loadAmbientLightSensorConfig(mContext.getResources());
         mProximitySensor = SensorData.loadSensorUnspecifiedConfig();
         mTempSensor = SensorData.loadTempSensorUnspecifiedConfig();
+        mRefreshRateData = RefreshRateData
+                .loadRefreshRateData(null, mContext.getResources());
         loadBrightnessChangeThresholdsFromXml();
         loadAutoBrightnessConfigsFromConfigXml();
         loadAutoBrightnessAvailableFromConfigXml();
@@ -2149,33 +2113,13 @@
         BlockingZoneConfig higherBlockingZoneConfig =
                 (refreshRateConfigs == null) ? null
                         : refreshRateConfigs.getHigherBlockingZoneConfigs();
-        loadPeakDefaultRefreshRate(refreshRateConfigs);
-        loadDefaultRefreshRate(refreshRateConfigs);
-        loadDefaultRefreshRateInHbm(refreshRateConfigs);
         loadLowerRefreshRateBlockingZones(lowerBlockingZoneConfig);
         loadHigherRefreshRateBlockingZones(higherBlockingZoneConfig);
         loadRefreshRateZoneProfiles(refreshRateConfigs);
     }
 
-    private void loadPeakDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) {
-        if (refreshRateConfigs == null || refreshRateConfigs.getDefaultPeakRefreshRate() == null) {
-            mDefaultPeakRefreshRate = mContext.getResources().getInteger(
-                R.integer.config_defaultPeakRefreshRate);
-        } else {
-            mDefaultPeakRefreshRate =
-                refreshRateConfigs.getDefaultPeakRefreshRate().intValue();
-        }
-    }
 
-    private void loadDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) {
-        if (refreshRateConfigs == null || refreshRateConfigs.getDefaultRefreshRate() == null) {
-            mDefaultRefreshRate = mContext.getResources().getInteger(
-                R.integer.config_defaultRefreshRate);
-        } else {
-            mDefaultRefreshRate =
-                refreshRateConfigs.getDefaultRefreshRate().intValue();
-        }
-    }
+
 
     /** Loads the refresh rate profiles. */
     private void loadRefreshRateZoneProfiles(RefreshRateConfigs refreshRateConfigs) {
@@ -2192,26 +2136,6 @@
         }
     }
 
-    private void loadDefaultRefreshRateInHbm(RefreshRateConfigs refreshRateConfigs) {
-        if (refreshRateConfigs != null
-                && refreshRateConfigs.getDefaultRefreshRateInHbmHdr() != null) {
-            mDefaultRefreshRateInHbmHdr = refreshRateConfigs.getDefaultRefreshRateInHbmHdr()
-                    .intValue();
-        } else {
-            mDefaultRefreshRateInHbmHdr = mContext.getResources().getInteger(
-                    R.integer.config_defaultRefreshRateInHbmHdr);
-        }
-
-        if (refreshRateConfigs != null
-                && refreshRateConfigs.getDefaultRefreshRateInHbmSunlight() != null) {
-            mDefaultRefreshRateInHbmSunlight =
-                    refreshRateConfigs.getDefaultRefreshRateInHbmSunlight().intValue();
-        } else {
-            mDefaultRefreshRateInHbmSunlight = mContext.getResources().getInteger(
-                R.integer.config_defaultRefreshRateInHbmSunlight);
-        }
-    }
-
     /**
      * Loads the refresh rate configurations pertaining to the lower blocking zones.
      */
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 31092f2..68e2bd6 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -548,6 +548,17 @@
         }
     };
 
+    private final DisplayModeDirector.DisplayDeviceConfigProvider mDisplayDeviceConfigProvider =
+            displayId -> {
+                synchronized (mSyncRoot) {
+                    final DisplayDevice device = getDeviceForDisplayLocked(displayId);
+                    if (device == null) {
+                        return null;
+                    }
+                    return device.getDisplayDeviceConfig();
+                }
+            };
+
     private final BrightnessSynchronizer mBrightnessSynchronizer;
 
     private final DeviceConfigParameterProvider mConfigParameterProvider;
@@ -599,7 +610,8 @@
         mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
                 foldSettingProvider, new FoldGracePeriodProvider(),
                 mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags);
-        mDisplayModeDirector = new DisplayModeDirector(context, mHandler, mFlags);
+        mDisplayModeDirector = new DisplayModeDirector(
+                context, mHandler, mFlags, mDisplayDeviceConfigProvider);
         mBrightnessSynchronizer = new BrightnessSynchronizer(mContext,
                 mFlags.isBrightnessIntRangeUserPerceptionEnabled());
         Resources resources = mContext.getResources();
@@ -2764,6 +2776,7 @@
                             + requestedRefreshRate + " on Display: " + displayId);
                 }
             }
+
             mDisplayModeDirector.getAppRequestObserver().setAppRequest(
                     displayId, requestedModeId, requestedMinRefreshRate, requestedMaxRefreshRate);
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 404c3ad..c5d8686 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -83,7 +83,7 @@
 import com.android.server.display.brightness.BrightnessUtils;
 import com.android.server.display.brightness.DisplayBrightnessController;
 import com.android.server.display.brightness.clamper.BrightnessClamperController;
-import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
+import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
 import com.android.server.display.config.HysteresisLevels;
@@ -440,7 +440,7 @@
 
     // Responsible for evaluating and tracking the automatic brightness relevant states.
     // Todo: This is a temporary workaround. Ideally DPC2 should never talk to the strategies
-    private final AutomaticBrightnessStrategy mAutomaticBrightnessStrategy;
+    private final AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy;
 
     // A record of state for skipping brightness ramps.
     private int mSkipRampState = RAMP_STATE_SKIP_NONE;
@@ -1337,9 +1337,6 @@
                     ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT);
         }
 
-        final boolean userSetBrightnessChanged = mDisplayBrightnessController
-                .updateUserSetScreenBrightness();
-
         DisplayBrightnessState displayBrightnessState = mDisplayBrightnessController
                 .updateBrightness(mPowerRequest, state);
         float brightnessState = displayBrightnessState.getBrightness();
@@ -1348,7 +1345,12 @@
         boolean slowChange = displayBrightnessState.isSlowChange();
         // custom transition duration
         float customAnimationRate = displayBrightnessState.getCustomAnimationRate();
-
+        int brightnessAdjustmentFlags = displayBrightnessState.getBrightnessAdjustmentFlag();
+        final boolean userSetBrightnessChanged =
+                mDisplayBrightnessController.getIsUserSetScreenBrightnessUpdated();
+        if (displayBrightnessState.getBrightnessEvent() != null) {
+            mTempBrightnessEvent.copyFrom(displayBrightnessState.getBrightnessEvent());
+        }
         // Set up the ScreenOff controller used when coming out of SCREEN_OFF and the ALS sensor
         // doesn't yet have a valid lux value to use with auto-brightness.
         if (mScreenOffBrightnessSensorController != null) {
@@ -1364,11 +1366,13 @@
         // request changes.
         final boolean wasShortTermModelActive =
                 mAutomaticBrightnessStrategy.isShortTermModelActive();
-        mAutomaticBrightnessStrategy.setAutoBrightnessState(state,
-                mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig(),
-                mBrightnessReasonTemp.getReason(), mPowerRequest.policy,
-                mDisplayBrightnessController.getLastUserSetScreenBrightness(),
-                userSetBrightnessChanged);
+        if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
+            mAutomaticBrightnessStrategy.setAutoBrightnessState(state,
+                    mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig(),
+                    mBrightnessReasonTemp.getReason(), mPowerRequest.policy,
+                    mDisplayBrightnessController.getLastUserSetScreenBrightness(),
+                    userSetBrightnessChanged);
+        }
 
         // If the brightness is already set then it's been overridden by something other than the
         // user, or is a temporary adjustment.
@@ -1389,43 +1393,55 @@
                 displayBrightnessState.shouldUpdateScreenBrightnessSetting();
         float currentBrightnessSetting = mDisplayBrightnessController.getCurrentBrightness();
         // Apply auto-brightness.
-        int brightnessAdjustmentFlags = 0;
-        // AutomaticBrightnessStrategy has higher priority than OffloadBrightnessStrategy
-        if (Float.isNaN(brightnessState)
-                || mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_OFFLOAD) {
-            if (mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()) {
-                brightnessState = mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
-                        mTempBrightnessEvent);
-                if (BrightnessUtils.isValidBrightnessValue(brightnessState)
-                        || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
-                    rawBrightnessState = mAutomaticBrightnessController
-                            .getRawAutomaticScreenBrightness();
-                    brightnessState = clampScreenBrightness(brightnessState);
-                    // slowly adapt to auto-brightness
-                    // TODO(b/253226419): slowChange should be decided by strategy.updateBrightness
-                    slowChange = mAutomaticBrightnessStrategy.hasAppliedAutoBrightness()
-                            && !mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged();
-                    brightnessAdjustmentFlags =
-                            mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags();
-                    updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState;
-                    mAutomaticBrightnessStrategy.setAutoBrightnessApplied(true);
-                    mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
-                    if (mScreenOffBrightnessSensorController != null) {
-                        mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
-                    }
-                    setBrightnessFromOffload(PowerManager.BRIGHTNESS_INVALID_FLOAT);
-                } else {
-                    mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
-                    // Restore the lower-priority brightness strategy
-                    brightnessState = displayBrightnessState.getBrightness();
-                }
+        // All the conditions inside this if block will be moved to AutomaticBrightnessStrategy
+        if (mFlags.isRefactorDisplayPowerControllerEnabled()
+                && displayBrightnessState.getBrightnessReason().getReason()
+                        == BrightnessReason.REASON_AUTOMATIC) {
+            if (mScreenOffBrightnessSensorController != null) {
+                mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
             }
-        } else {
-            // Any non-auto-brightness values such as override or temporary should still be subject
-            // to clamping so that they don't go beyond the current max as specified by HBM
-            // Controller.
+        }
+
+        if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
+            // AutomaticBrightnessStrategy has higher priority than OffloadBrightnessStrategy
+            if (Float.isNaN(brightnessState)
+                    || mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_OFFLOAD) {
+                if (mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()) {
+                    brightnessState = mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
+                            mTempBrightnessEvent);
+                    if (BrightnessUtils.isValidBrightnessValue(brightnessState)
+                            || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
+                        rawBrightnessState = mAutomaticBrightnessController
+                                .getRawAutomaticScreenBrightness();
+                        // slowly adapt to auto-brightness
+                        // TODO(b/253226419): slowChange should be decided by
+                        // strategy.updateBrightness
+                        slowChange = mAutomaticBrightnessStrategy.hasAppliedAutoBrightness()
+                                && !mAutomaticBrightnessStrategy
+                                .getAutoBrightnessAdjustmentChanged();
+                        brightnessAdjustmentFlags =
+                                mAutomaticBrightnessStrategy
+                                        .getAutoBrightnessAdjustmentReasonsFlags();
+                        updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState;
+                        mAutomaticBrightnessStrategy.setAutoBrightnessApplied(true);
+                        mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
+                        if (mScreenOffBrightnessSensorController != null) {
+                            mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
+                        }
+                        setBrightnessFromOffload(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+                    } else {
+                        mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
+                        // Restore the lower-priority brightness strategy
+                        brightnessState = displayBrightnessState.getBrightness();
+                    }
+                }
+            } else {
+                mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
+            }
+        }
+
+        if (!Float.isNaN(brightnessState)) {
             brightnessState = clampScreenBrightness(brightnessState);
-            mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
         }
 
         // If there's an offload session, we need to set the initial doze brightness before
diff --git a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
index a12d248..b24caf4 100644
--- a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
+++ b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
@@ -222,7 +222,7 @@
         } else {
             // As external display is enabled by default, need to disable it now.
             // TODO(b/292196201) Remove when the display can be disabled before DPC is created.
-            logicalDisplay.setEnabledLocked(false);
+            mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, false);
         }
 
         if (!isExternalDisplayAllowed()) {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 1dfe037..182b05a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -82,11 +82,8 @@
     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular";
     // Min and max strengths for even dimmer feature.
     private static final float EVEN_DIMMER_MIN_STRENGTH = 0.0f;
-    private static final float EVEN_DIMMER_MAX_STRENGTH = 70.0f; // not too dim yet.
+    private static final float EVEN_DIMMER_MAX_STRENGTH = 90.0f;
     private static final float BRIGHTNESS_MIN = 0.0f;
-    // The brightness at which we start using color matrices rather than backlight,
-    // to dim the display
-    private static final float BACKLIGHT_COLOR_TRANSITION_POINT = 0.1f;
 
     private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
 
@@ -995,9 +992,12 @@
 
                     private void applyColorMatrixBasedDimming(float brightnessState) {
                         int strength = (int) (MathUtils.constrainedMap(
-                                EVEN_DIMMER_MAX_STRENGTH, EVEN_DIMMER_MIN_STRENGTH, // to this range
-                                BRIGHTNESS_MIN, BACKLIGHT_COLOR_TRANSITION_POINT, // from this range
-                                brightnessState) + 0.5); // map this (+ rounded up)
+                                // to this range:
+                                EVEN_DIMMER_MAX_STRENGTH, EVEN_DIMMER_MIN_STRENGTH,
+                                // from this range:
+                                BRIGHTNESS_MIN, mDisplayDeviceConfig.getEvenDimmerTransitionPoint(),
+                                // map this (+ rounded up):
+                                brightnessState) + 0.5);
 
                         if (mEvenDimmerStrength < 0 // uninitialised
                                 || MathUtils.abs(mEvenDimmerStrength - strength) > 1
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 8084685..6a88a76 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -31,7 +31,7 @@
 import com.android.server.display.BrightnessMappingStrategy;
 import com.android.server.display.BrightnessSetting;
 import com.android.server.display.DisplayBrightnessState;
-import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
+import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
 import com.android.server.display.feature.DisplayManagerFlags;
 
@@ -76,6 +76,10 @@
     @GuardedBy("mLock")
     private float mLastUserSetScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
 
+    // Represents if the system has adjusted the brightness based on the user suggested value. Will
+    // be false if the brightness change is coming from a non-user source
+    private boolean mUserSetScreenBrightnessUpdated;
+
     // The listener which is to be notified everytime there is a change in the brightness in the
     // BrightnessSetting.
     private BrightnessSetting.BrightnessSettingListener mBrightnessSettingListener;
@@ -138,12 +142,12 @@
     public DisplayBrightnessState updateBrightness(
             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
             int targetDisplayState) {
-
         DisplayBrightnessState state;
         synchronized (mLock) {
             mDisplayBrightnessStrategy = mDisplayBrightnessStrategySelector.selectStrategy(
                     constructStrategySelectionRequest(displayPowerRequest, targetDisplayState));
-            state = mDisplayBrightnessStrategy.updateBrightness(displayPowerRequest);
+            state = mDisplayBrightnessStrategy
+                        .updateBrightness(constructStrategyExecutionRequest(displayPowerRequest));
         }
 
         // This is a temporary measure until AutomaticBrightnessStrategy works as a traditional
@@ -246,28 +250,14 @@
     }
 
     /**
-     * We want to return true if the user has set the screen brightness.
-     * RBC on, off, and intensity changes will return false.
-     * Slider interactions whilst in RBC will return true, just as when in non-rbc.
+     * Returns if the system has adjusted the brightness based on the user suggested value. Will
+     * be false if the brightness change is coming from a non-user source.
+     *
+     * Todo: 294444204 This is a temporary workaround, and should be moved to the manual brightness
+     * strategy once that is introduced
      */
-    public boolean updateUserSetScreenBrightness() {
-        synchronized (mLock) {
-            if (!BrightnessUtils.isValidBrightnessValue(mPendingScreenBrightness)) {
-                return false;
-            }
-            if (mCurrentScreenBrightness == mPendingScreenBrightness) {
-                mPendingScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
-                setTemporaryBrightnessLocked(PowerManager.BRIGHTNESS_INVALID_FLOAT);
-                return false;
-            }
-            setCurrentScreenBrightnessLocked(mPendingScreenBrightness);
-            mLastUserSetScreenBrightness = mPendingScreenBrightness;
-            mPendingScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
-            setTemporaryBrightnessLocked(PowerManager.BRIGHTNESS_INVALID_FLOAT);
-        }
-        notifyCurrentScreenBrightness();
-        return true;
-
+    public boolean getIsUserSetScreenBrightnessUpdated() {
+        return mUserSetScreenBrightnessUpdated;
     }
 
     /**
@@ -355,7 +345,7 @@
     /**
      * TODO(b/253226419): Remove once auto-brightness is a fully-functioning strategy.
      */
-    public AutomaticBrightnessStrategy getAutomaticBrightnessStrategy() {
+    public AutomaticBrightnessStrategy2 getAutomaticBrightnessStrategy() {
         return mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy();
     }
 
@@ -442,6 +432,33 @@
         }
     }
 
+    /**
+     * We want to return true if the user has set the screen brightness.
+     * RBC on, off, and intensity changes will return false.
+     * Slider interactions whilst in RBC will return true, just as when in non-rbc.
+     */
+    @VisibleForTesting
+    boolean updateUserSetScreenBrightness() {
+        mUserSetScreenBrightnessUpdated = false;
+        synchronized (mLock) {
+            if (!BrightnessUtils.isValidBrightnessValue(mPendingScreenBrightness)) {
+                return false;
+            }
+            if (mCurrentScreenBrightness == mPendingScreenBrightness) {
+                mPendingScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+                setTemporaryBrightnessLocked(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+                return false;
+            }
+            setCurrentScreenBrightnessLocked(mPendingScreenBrightness);
+            mLastUserSetScreenBrightness = mPendingScreenBrightness;
+            mPendingScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+            setTemporaryBrightnessLocked(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        }
+        notifyCurrentScreenBrightness();
+        mUserSetScreenBrightnessUpdated = true;
+        return true;
+    }
+
     @VisibleForTesting
     static class Injector {
         DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(Context context,
@@ -470,7 +487,7 @@
      * TODO(b/253226419): Remove once auto-brightness is a fully-functioning strategy.
      */
     private DisplayBrightnessState addAutomaticBrightnessState(DisplayBrightnessState state) {
-        AutomaticBrightnessStrategy autoStrat = getAutomaticBrightnessStrategy();
+        AutomaticBrightnessStrategy2 autoStrat = getAutomaticBrightnessStrategy();
 
         DisplayBrightnessState.Builder builder = DisplayBrightnessState.Builder.from(state);
         builder.setShouldUseAutoBrightness(
@@ -526,6 +543,18 @@
     private StrategySelectionRequest constructStrategySelectionRequest(
             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
             int targetDisplayState) {
-        return new StrategySelectionRequest(displayPowerRequest, targetDisplayState);
+        boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
+        float lastUserSetScreenBrightness;
+        synchronized (mLock) {
+            lastUserSetScreenBrightness = mLastUserSetScreenBrightness;
+        }
+        return new StrategySelectionRequest(displayPowerRequest, targetDisplayState,
+                lastUserSetScreenBrightness, userSetBrightnessChanged);
+    }
+
+    private StrategyExecutionRequest constructStrategyExecutionRequest(
+            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+        float currentScreenBrightness = getCurrentBrightness();
+        return new StrategyExecutionRequest(displayPowerRequest, currentScreenBrightness);
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
index 165c24b..282083f 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -27,6 +27,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
+import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
 import com.android.server.display.brightness.strategy.BoostBrightnessStrategy;
 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
 import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
@@ -65,7 +66,16 @@
     // The brightness strategy used to manage the brightness state when the request is invalid.
     private final InvalidBrightnessStrategy mInvalidBrightnessStrategy;
     // Controls brightness when automatic (adaptive) brightness is running.
-    private final AutomaticBrightnessStrategy mAutomaticBrightnessStrategy;
+    private final AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy;
+
+    // The automatic strategy which controls the brightness when adaptive mode is ON.
+    private final AutomaticBrightnessStrategy mAutomaticBrightnessStrategy1;
+
+    // The deprecated AutomaticBrightnessStrategy. Avoid using it for any new features without
+    // consulting with the display frameworks team. Use {@link AutomaticBrightnessStrategy} instead.
+    // This will be removed once the flag
+    // {@link DisplayManagerFlags#isRefactorDisplayPowerControllerEnabled is fully rolled out
+    private final AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy2;
     // Controls the brightness if adaptive brightness is on and there exists an active offload
     // session. Brightness value is provided by the offload session.
     @Nullable
@@ -101,16 +111,25 @@
         mBoostBrightnessStrategy = injector.getBoostBrightnessStrategy();
         mFollowerBrightnessStrategy = injector.getFollowerBrightnessStrategy(displayId);
         mInvalidBrightnessStrategy = injector.getInvalidBrightnessStrategy();
-        mAutomaticBrightnessStrategy = injector.getAutomaticBrightnessStrategy(context, displayId);
+        mAutomaticBrightnessStrategy1 =
+                (!mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) ? null
+                        : injector.getAutomaticBrightnessStrategy1(context, displayId);
+        mAutomaticBrightnessStrategy2 =
+                (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) ? null
+                        : injector.getAutomaticBrightnessStrategy2(context, displayId);
+        mAutomaticBrightnessStrategy =
+                (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled())
+                        ? mAutomaticBrightnessStrategy1 : mAutomaticBrightnessStrategy2;
         if (flags.isDisplayOffloadEnabled()) {
-            mOffloadBrightnessStrategy = injector.getOffloadBrightnessStrategy();
+            mOffloadBrightnessStrategy = injector
+                    .getOffloadBrightnessStrategy(mDisplayManagerFlags);
         } else {
             mOffloadBrightnessStrategy = null;
         }
         mDisplayBrightnessStrategies = new DisplayBrightnessStrategy[]{mInvalidBrightnessStrategy,
                 mScreenOffBrightnessStrategy, mDozeBrightnessStrategy, mFollowerBrightnessStrategy,
                 mBoostBrightnessStrategy, mOverrideBrightnessStrategy, mTemporaryBrightnessStrategy,
-                mOffloadBrightnessStrategy};
+                mAutomaticBrightnessStrategy1, mOffloadBrightnessStrategy};
         mAllowAutoBrightnessWhileDozingConfig = context.getResources().getBoolean(
                 R.bool.config_allowAutoBrightnessWhileDozing);
         mOldBrightnessStrategyName = mInvalidBrightnessStrategy.getName();
@@ -142,6 +161,9 @@
         } else if (BrightnessUtils.isValidBrightnessValue(
                 mTemporaryBrightnessStrategy.getTemporaryScreenBrightness())) {
             displayBrightnessStrategy = mTemporaryBrightnessStrategy;
+        } else if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()
+                && isAutomaticBrightnessStrategyValid(strategySelectionRequest)) {
+            displayBrightnessStrategy = mAutomaticBrightnessStrategy1;
         } else if (mAutomaticBrightnessStrategy.shouldUseAutoBrightness()
                 && mOffloadBrightnessStrategy != null && BrightnessUtils.isValidBrightnessValue(
                 mOffloadBrightnessStrategy.getOffloadScreenBrightness())) {
@@ -149,7 +171,8 @@
         }
 
         if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
-            postProcess(constructStrategySelectionNotifyRequest(displayBrightnessStrategy));
+            postProcess(constructStrategySelectionNotifyRequest(displayBrightnessStrategy,
+                    strategySelectionRequest));
         }
 
         if (!mOldBrightnessStrategyName.equals(displayBrightnessStrategy.getName())) {
@@ -170,7 +193,7 @@
         return mFollowerBrightnessStrategy;
     }
 
-    public AutomaticBrightnessStrategy getAutomaticBrightnessStrategy() {
+    public AutomaticBrightnessStrategy2 getAutomaticBrightnessStrategy() {
         return mAutomaticBrightnessStrategy;
     }
 
@@ -206,9 +229,28 @@
         }
     }
 
+    private boolean isAutomaticBrightnessStrategyValid(
+            StrategySelectionRequest strategySelectionRequest) {
+        mAutomaticBrightnessStrategy1.setAutoBrightnessState(
+                strategySelectionRequest.getTargetDisplayState(),
+                mAllowAutoBrightnessWhileDozingConfig,
+                BrightnessReason.REASON_UNKNOWN,
+                strategySelectionRequest.getDisplayPowerRequest().policy,
+                strategySelectionRequest.getLastUserSetScreenBrightness(),
+                strategySelectionRequest.isUserSetBrightnessChanged());
+        return mAutomaticBrightnessStrategy1.isAutoBrightnessValid();
+    }
+
     private StrategySelectionNotifyRequest constructStrategySelectionNotifyRequest(
-            DisplayBrightnessStrategy selectedDisplayBrightnessStrategy) {
-        return new StrategySelectionNotifyRequest(selectedDisplayBrightnessStrategy);
+            DisplayBrightnessStrategy selectedDisplayBrightnessStrategy,
+            StrategySelectionRequest strategySelectionRequest) {
+        return new StrategySelectionNotifyRequest(
+                        strategySelectionRequest.getDisplayPowerRequest(),
+                strategySelectionRequest.getTargetDisplayState(),
+                selectedDisplayBrightnessStrategy,
+                strategySelectionRequest.getLastUserSetScreenBrightness(),
+                strategySelectionRequest.isUserSetBrightnessChanged(),
+                isAllowAutoBrightnessWhileDozingConfig());
     }
 
     private void postProcess(StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
@@ -263,12 +305,19 @@
             return new InvalidBrightnessStrategy();
         }
 
-        AutomaticBrightnessStrategy getAutomaticBrightnessStrategy(Context context, int displayId) {
+        AutomaticBrightnessStrategy getAutomaticBrightnessStrategy1(Context context,
+                int displayId) {
             return new AutomaticBrightnessStrategy(context, displayId);
         }
 
-        OffloadBrightnessStrategy getOffloadBrightnessStrategy() {
-            return new OffloadBrightnessStrategy();
+        AutomaticBrightnessStrategy2 getAutomaticBrightnessStrategy2(Context context,
+                int displayId) {
+            return new AutomaticBrightnessStrategy2(context, displayId);
+        }
+
+        OffloadBrightnessStrategy getOffloadBrightnessStrategy(
+                DisplayManagerFlags displayManagerFlags) {
+            return new OffloadBrightnessStrategy(displayManagerFlags);
         }
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/StrategyExecutionRequest.java b/services/core/java/com/android/server/display/brightness/StrategyExecutionRequest.java
new file mode 100644
index 0000000..82c0bbf
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/StrategyExecutionRequest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness;
+
+import android.hardware.display.DisplayManagerInternal;
+
+import java.util.Objects;
+
+/**
+ * A wrapper class to encapsulate the request to execute the selected strategy
+ */
+public final class StrategyExecutionRequest {
+    // The request to change the associated display's state and brightness
+    private final DisplayManagerInternal.DisplayPowerRequest mDisplayPowerRequest;
+
+    private final float mCurrentScreenBrightness;
+
+    public StrategyExecutionRequest(DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
+            float currentScreenBrightness) {
+        mDisplayPowerRequest = displayPowerRequest;
+        mCurrentScreenBrightness = currentScreenBrightness;
+    }
+
+    public DisplayManagerInternal.DisplayPowerRequest getDisplayPowerRequest() {
+        return mDisplayPowerRequest;
+    }
+
+    public float getCurrentScreenBrightness() {
+        return mCurrentScreenBrightness;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof StrategyExecutionRequest)) {
+            return false;
+        }
+        StrategyExecutionRequest other = (StrategyExecutionRequest) obj;
+        return Objects.equals(mDisplayPowerRequest, other.getDisplayPowerRequest())
+                && mCurrentScreenBrightness == other.getCurrentScreenBrightness();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDisplayPowerRequest, mCurrentScreenBrightness);
+    }
+}
diff --git a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
index d8bd2e4..6e6c972 100644
--- a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
+++ b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.display.brightness;
 
+import android.hardware.display.DisplayManagerInternal;
+
 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
 
 import java.util.Objects;
@@ -25,11 +27,36 @@
  * DisplayBrightnessStrategy
  */
 public final class StrategySelectionNotifyRequest {
+    // The request to change the associated display's state and brightness
+    private DisplayManagerInternal.DisplayPowerRequest mDisplayPowerRequest;
+
+    // The display state to which the screen is switching to
+    private int mTargetDisplayState;
+
     // The strategy that was selected with the current request
     private final DisplayBrightnessStrategy mSelectedDisplayBrightnessStrategy;
 
-    public StrategySelectionNotifyRequest(DisplayBrightnessStrategy displayBrightnessStrategy) {
+    // The last brightness that was set by the user and not temporary. Set to
+    // PowerManager.BRIGHTNESS_INVALID_FLOAT when a brightness has yet to be recorded.
+    private float mLastUserSetScreenBrightness;
+
+    // Represents if the user set screen brightness was changed or not.
+    private boolean mUserSetBrightnessChanged;
+
+    // True if light sensor is to be used to automatically determine doze screen brightness.
+    private final boolean mAllowAutoBrightnessWhileDozingConfig;
+
+    public StrategySelectionNotifyRequest(
+            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest, int targetDisplayState,
+            DisplayBrightnessStrategy displayBrightnessStrategy,
+            float lastUserSetScreenBrightness,
+            boolean userSetBrightnessChanged, boolean allowAutoBrightnessWhileDozingConfig) {
+        mDisplayPowerRequest = displayPowerRequest;
+        mTargetDisplayState = targetDisplayState;
         mSelectedDisplayBrightnessStrategy = displayBrightnessStrategy;
+        mLastUserSetScreenBrightness = lastUserSetScreenBrightness;
+        mUserSetBrightnessChanged = userSetBrightnessChanged;
+        mAllowAutoBrightnessWhileDozingConfig = allowAutoBrightnessWhileDozingConfig;
     }
 
     public DisplayBrightnessStrategy getSelectedDisplayBrightnessStrategy() {
@@ -43,11 +70,52 @@
         }
         StrategySelectionNotifyRequest other = (StrategySelectionNotifyRequest) obj;
         return other.getSelectedDisplayBrightnessStrategy()
-                == getSelectedDisplayBrightnessStrategy();
+                == getSelectedDisplayBrightnessStrategy()
+                && Objects.equals(mDisplayPowerRequest, other.getDisplayPowerRequest())
+                && mTargetDisplayState == other.getTargetDisplayState()
+                && mUserSetBrightnessChanged == other.isUserSetBrightnessChanged()
+                && mLastUserSetScreenBrightness == other.getLastUserSetScreenBrightness()
+                && mAllowAutoBrightnessWhileDozingConfig
+                == other.isAllowAutoBrightnessWhileDozingConfig();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSelectedDisplayBrightnessStrategy);
+        return Objects.hash(mSelectedDisplayBrightnessStrategy, mDisplayPowerRequest,
+                mTargetDisplayState, mUserSetBrightnessChanged, mLastUserSetScreenBrightness,
+                mAllowAutoBrightnessWhileDozingConfig);
+    }
+
+    public float getLastUserSetScreenBrightness() {
+        return mLastUserSetScreenBrightness;
+    }
+
+    public boolean isUserSetBrightnessChanged() {
+        return mUserSetBrightnessChanged;
+    }
+
+    public DisplayManagerInternal.DisplayPowerRequest getDisplayPowerRequest() {
+        return mDisplayPowerRequest;
+    }
+
+    public int getTargetDisplayState() {
+        return mTargetDisplayState;
+    }
+
+    public boolean isAllowAutoBrightnessWhileDozingConfig() {
+        return mAllowAutoBrightnessWhileDozingConfig;
+    }
+
+    /**
+     * A utility to stringify a StrategySelectionNotifyRequest
+     */
+    public String toString() {
+        return "StrategySelectionNotifyRequest:"
+                + " mDisplayPowerRequest=" + mDisplayPowerRequest
+                + " mTargetDisplayState=" + mTargetDisplayState
+                + " mSelectedDisplayBrightnessStrategy=" + mSelectedDisplayBrightnessStrategy
+                + " mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness
+                + " mUserSetBrightnessChanged=" + mUserSetBrightnessChanged
+                + " mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig;
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java b/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java
index e618596..ae745efc 100644
--- a/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java
+++ b/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java
@@ -31,10 +31,20 @@
     // The display state to which the screen is switching to
     private int mTargetDisplayState;
 
+    // The last brightness that was set by the user and not temporary. Set to
+    // PowerManager.BRIGHTNESS_INVALID_FLOAT when a brightness has yet to be recorded.
+    private float mLastUserSetScreenBrightness;
+
+    // Represents if the user set screen brightness was changed or not.
+    private boolean mUserSetBrightnessChanged;
+
     public StrategySelectionRequest(DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
-            int targetDisplayState) {
+            int targetDisplayState, float lastUserSetScreenBrightness,
+            boolean userSetBrightnessChanged) {
         mDisplayPowerRequest = displayPowerRequest;
         mTargetDisplayState = targetDisplayState;
+        mLastUserSetScreenBrightness = lastUserSetScreenBrightness;
+        mUserSetBrightnessChanged = userSetBrightnessChanged;
     }
 
     public DisplayManagerInternal.DisplayPowerRequest getDisplayPowerRequest() {
@@ -45,18 +55,30 @@
         return mTargetDisplayState;
     }
 
+
+    public float getLastUserSetScreenBrightness() {
+        return mLastUserSetScreenBrightness;
+    }
+
+    public boolean isUserSetBrightnessChanged() {
+        return mUserSetBrightnessChanged;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof StrategySelectionRequest)) {
             return false;
         }
         StrategySelectionRequest other = (StrategySelectionRequest) obj;
-        return Objects.equals(other.getDisplayPowerRequest(), getDisplayPowerRequest())
-                && other.getTargetDisplayState() == getTargetDisplayState();
+        return Objects.equals(mDisplayPowerRequest, other.getDisplayPowerRequest())
+                && mTargetDisplayState == other.getTargetDisplayState()
+                && mLastUserSetScreenBrightness == other.getLastUserSetScreenBrightness()
+                && mUserSetBrightnessChanged == other.isUserSetBrightnessChanged();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mDisplayPowerRequest, mTargetDisplayState);
+        return Objects.hash(mDisplayPowerRequest, mTargetDisplayState,
+                mLastUserSetScreenBrightness, mUserSetBrightnessChanged);
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
index f1cb66c..902daa4 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
@@ -59,6 +59,11 @@
 
     private boolean mAutoBrightnessEnabled = false;
 
+    /**
+     * Indicates that maxBrightness is changed, and we should use slow transition
+     */
+    private boolean mUseSlowTransition = false;
+
     public HdrClamper(BrightnessClamperController.ClamperChangeListener clamperChangeListener,
             Handler handler) {
         this(clamperChangeListener, handler, new Injector());
@@ -72,6 +77,7 @@
         mDebouncer = () -> {
             mTransitionRate = mDesiredTransitionRate;
             mMaxBrightness = mDesiredMaxBrightness;
+            mUseSlowTransition = true;
             mClamperChangeListener.onChanged();
         };
         mHdrListener = injector.getHdrListener((visible) -> {
@@ -80,14 +86,24 @@
         }, handler);
     }
 
-    // Called in same looper: mHandler.getLooper()
+    /**
+     * Applies clamping
+     * Called in same looper: mHandler.getLooper()
+     */
+    public float clamp(float brightness) {
+        return Math.min(brightness, mMaxBrightness);
+    }
+
+    @VisibleForTesting
     public float getMaxBrightness() {
         return mMaxBrightness;
     }
 
     // Called in same looper: mHandler.getLooper()
     public float getTransitionRate() {
-        return mTransitionRate;
+        float expectedTransitionRate =  mUseSlowTransition ? mTransitionRate : -1;
+        mUseSlowTransition = false;
+        return  expectedTransitionRate;
     }
 
     /**
@@ -173,7 +189,8 @@
         mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
         mDesiredMaxBrightness = PowerManager.BRIGHTNESS_MAX;
         mDesiredTransitionRate = -1f;
-        mTransitionRate = 1f;
+        mTransitionRate = -1f;
+        mUseSlowTransition = false;
         mClamperChangeListener.onChanged();
     }
 
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
index 08d4cfd..5c4fa842 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
@@ -27,9 +27,12 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
 
@@ -40,7 +43,8 @@
  * that it is being executed from the power thread, and hence doesn't synchronize
  * any of its resources
  */
-public class AutomaticBrightnessStrategy {
+public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2
+        implements DisplayBrightnessStrategy{
     private final Context mContext;
     // The DisplayId of the associated logical display
     private final int mDisplayId;
@@ -88,12 +92,25 @@
     @Nullable
     private BrightnessConfiguration mBrightnessConfiguration;
 
-    public AutomaticBrightnessStrategy(Context context, int displayId) {
+    // Indicates if the strategy is already configured for a request, in which case we wouldn't
+    // want to re-evaluate the auto-brightness state
+    private boolean mIsConfigured;
+
+    private Injector mInjector;
+
+    @VisibleForTesting
+    AutomaticBrightnessStrategy(Context context, int displayId, Injector injector) {
+        super(context, displayId);
         mContext = context;
         mDisplayId = displayId;
         mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
         mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mInjector = (injector == null) ? new RealInjector() : injector;
+    }
+
+    public AutomaticBrightnessStrategy(Context context, int displayId) {
+        this(context, displayId, null);
     }
 
     /**
@@ -112,7 +129,7 @@
         mAutoBrightnessDisabledDueToDisplayOff = shouldUseAutoBrightness()
                 && !(targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze);
         final int autoBrightnessState = mIsAutoBrightnessEnabled
-                    && brightnessReason != BrightnessReason.REASON_FOLLOWER
+                && brightnessReason != BrightnessReason.REASON_FOLLOWER
                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
                 : mAutoBrightnessDisabledDueToDisplayOff
                         ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
@@ -120,12 +137,36 @@
 
         accommodateUserBrightnessChanges(userSetBrightnessChanged, lastUserSetScreenBrightness,
                 policy, targetDisplayState, mBrightnessConfiguration, autoBrightnessState);
+        mIsConfigured = true;
+    }
+
+    public void setIsConfigured(boolean configure) {
+        mIsConfigured = configure;
     }
 
     public boolean isAutoBrightnessEnabled() {
         return mIsAutoBrightnessEnabled;
     }
 
+    /**
+     * Validates if the auto-brightness strategy is valid or not considering the current system
+     * state.
+     */
+    public boolean isAutoBrightnessValid() {
+        boolean isValid = false;
+        if (isAutoBrightnessEnabled()) {
+            float brightness = (mAutomaticBrightnessController != null)
+                    ? mAutomaticBrightnessController.getAutomaticScreenBrightness(null)
+                    : PowerManager.BRIGHTNESS_INVALID_FLOAT;
+            if (BrightnessUtils.isValidBrightnessValue(brightness)
+                    || brightness == PowerManager.BRIGHTNESS_OFF_FLOAT) {
+                isValid = true;
+            }
+        }
+        setAutoBrightnessApplied(isValid);
+        return isValid;
+    }
+
     public boolean isAutoBrightnessDisabledDueToDisplayOff() {
         return mAutoBrightnessDisabledDueToDisplayOff;
     }
@@ -217,6 +258,32 @@
         mTemporaryAutoBrightnessAdjustment = temporaryAutoBrightnessAdjustment;
     }
 
+    @Override
+    public DisplayBrightnessState updateBrightness(
+            StrategyExecutionRequest strategyExecutionRequest) {
+        BrightnessReason brightnessReason = new BrightnessReason();
+        brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
+        BrightnessEvent brightnessEvent = mInjector.getBrightnessEvent(mDisplayId);
+        float brightness = getAutomaticScreenBrightness(brightnessEvent);
+        return new DisplayBrightnessState.Builder()
+                .setBrightness(brightness)
+                .setSdrBrightness(brightness)
+                .setBrightnessReason(brightnessReason)
+                .setDisplayBrightnessStrategyName(getName())
+                .setIsSlowChange(hasAppliedAutoBrightness()
+                        && !getAutoBrightnessAdjustmentChanged())
+                .setBrightnessEvent(brightnessEvent)
+                .setBrightnessAdjustmentFlag(mAutoBrightnessAdjustmentReasonsFlags)
+                .setShouldUpdateScreenBrightnessSetting(
+                        brightness != strategyExecutionRequest.getCurrentScreenBrightness())
+                .build();
+    }
+
+    @Override
+    public String getName() {
+        return "AutomaticBrightnessStrategy";
+    }
+
     /**
      * Dumps the state of this class.
      */
@@ -238,6 +305,26 @@
                 + mAutoBrightnessAdjustmentReasonsFlags);
     }
 
+    @Override
+    public void strategySelectionPostProcessor(
+            StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+        if (!mIsConfigured) {
+            setAutoBrightnessState(strategySelectionNotifyRequest.getTargetDisplayState(),
+                    strategySelectionNotifyRequest.isAllowAutoBrightnessWhileDozingConfig(),
+                    strategySelectionNotifyRequest.getSelectedDisplayBrightnessStrategy()
+                            .getReason(),
+                    strategySelectionNotifyRequest.getDisplayPowerRequest().policy,
+                    strategySelectionNotifyRequest.getLastUserSetScreenBrightness(),
+                    strategySelectionNotifyRequest.isUserSetBrightnessChanged());
+        }
+        mIsConfigured = false;
+    }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_AUTOMATIC;
+    }
+
     /**
      * Indicates if any auto-brightness adjustments have happened since the last auto-brightness was
      * set.
@@ -284,13 +371,6 @@
     }
 
     /**
-     * Gets the auto-brightness adjustment flag change reason
-     */
-    public int getAutoBrightnessAdjustmentReasonsFlags() {
-        return mAutoBrightnessAdjustmentReasonsFlags;
-    }
-
-    /**
      * Returns if the auto brightness has been applied
      */
     public boolean hasAppliedAutoBrightness() {
@@ -421,4 +501,15 @@
                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
         return Float.isNaN(adj) ? 0.0f : BrightnessUtils.clampBrightnessAdjustment(adj);
     }
+
+    @VisibleForTesting
+    interface Injector {
+        BrightnessEvent getBrightnessEvent(int displayId);
+    }
+
+    static class RealInjector implements Injector {
+        public BrightnessEvent getBrightnessEvent(int displayId) {
+            return new BrightnessEvent(displayId);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
new file mode 100644
index 0000000..25e8b23
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.display.brightness.strategy;
+
+import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.display.BrightnessConfiguration;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.Display;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.brightness.BrightnessEvent;
+import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.feature.DisplayManagerFlags;
+
+import java.io.PrintWriter;
+
+/**
+ * Helps manage the brightness based on the ambient environment (Ambient Light/lux sensor) using
+ * mappings from lux to nits to brightness, configured in the
+ * {@link com.android.server.display.DisplayDeviceConfig} class. This class inherently assumes
+ * that it is being executed from the power thread, and hence doesn't synchronize
+ * any of its resources
+ *
+ * @deprecated This class is relevant only while the
+ * {@link DisplayManagerFlags#isRefactorDisplayPowerControllerEnabled()} is not fully rolled out.
+ * Till then, please replicated your changes to {@link AutomaticBrightnessStrategy} as well.
+ */
+@Deprecated
+public class AutomaticBrightnessStrategy2 {
+    private final Context mContext;
+    // The DisplayId of the associated logical display
+    private final int mDisplayId;
+    // The last auto brightness adjustment that was set by the user and is not temporary. Set to
+    // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
+    private float mAutoBrightnessAdjustment;
+    // The pending auto brightness adjustment that will take effect on the next power state update.
+    private float mPendingAutoBrightnessAdjustment;
+    // The temporary auto brightness adjustment. This was historically used when a user interacts
+    // with the adjustment slider but hasn't settled on a choice yet.
+    // Set to PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
+    private float mTemporaryAutoBrightnessAdjustment;
+    // Indicates if the temporary auto brightness adjustment has been applied while updating the
+    // associated display brightness
+    private boolean mAppliedTemporaryAutoBrightnessAdjustment;
+    // Indicates if the auto brightness adjustment has happened.
+    private boolean mAutoBrightnessAdjustmentChanged;
+    // Indicates the reasons for the auto-brightness adjustment
+    private int mAutoBrightnessAdjustmentReasonsFlags = 0;
+    // Indicates if the short term model should be reset before fetching the new brightness
+    // Todo(273543270): Short term model is an internal information of
+    //  AutomaticBrightnessController and shouldn't be exposed outside of that class
+    private boolean mShouldResetShortTermModel = false;
+    // Remembers whether the auto-brightness has been applied in the latest brightness update.
+    private boolean mAppliedAutoBrightness = false;
+    // The controller for the automatic brightness level.
+    @Nullable
+    private AutomaticBrightnessController mAutomaticBrightnessController;
+    // The system setting denoting if the auto-brightness for the current user is enabled or not
+    private boolean mUseAutoBrightness = false;
+    // Indicates if the auto-brightness is currently enabled or not. It's possible that even if
+    // the user has enabled the auto-brightness from the settings, it is disabled because the
+    // display is off
+    private boolean mIsAutoBrightnessEnabled = false;
+    // Indicates if auto-brightness is disabled due to the display being off. Needed for metric
+    // purposes.
+    private boolean mAutoBrightnessDisabledDueToDisplayOff;
+    // If the auto-brightness model for the last manual changes done by the user.
+    private boolean mIsShortTermModelActive = false;
+
+    // The BrightnessConfiguration currently being used
+    // Todo(273543270): BrightnessConfiguration is an internal implementation detail of
+    //  AutomaticBrightnessController, and AutomaticBrightnessStrategy shouldn't be aware of its
+    //  existence.
+    @Nullable
+    private BrightnessConfiguration mBrightnessConfiguration;
+
+    public AutomaticBrightnessStrategy2(Context context, int displayId) {
+        mContext = context;
+        mDisplayId = displayId;
+        mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
+        mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+    }
+
+    /**
+     * Sets up the automatic brightness states of this class. Also configures
+     * AutomaticBrightnessController accounting for any manual changes made by the user.
+     */
+    public void setAutoBrightnessState(int targetDisplayState,
+            boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy,
+            float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) {
+        final boolean autoBrightnessEnabledInDoze =
+                allowAutoBrightnessWhileDozingConfig && policy == POLICY_DOZE;
+        mIsAutoBrightnessEnabled = shouldUseAutoBrightness()
+                && (targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze)
+                && brightnessReason != BrightnessReason.REASON_OVERRIDE
+                && mAutomaticBrightnessController != null;
+        mAutoBrightnessDisabledDueToDisplayOff = shouldUseAutoBrightness()
+                && !(targetDisplayState == Display.STATE_ON || autoBrightnessEnabledInDoze);
+        final int autoBrightnessState = mIsAutoBrightnessEnabled
+                && brightnessReason != BrightnessReason.REASON_FOLLOWER
+                ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
+                : mAutoBrightnessDisabledDueToDisplayOff
+                        ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
+                        : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
+
+        accommodateUserBrightnessChanges(userSetBrightnessChanged, lastUserSetScreenBrightness,
+                policy, targetDisplayState, mBrightnessConfiguration, autoBrightnessState);
+    }
+
+    public boolean isAutoBrightnessEnabled() {
+        return mIsAutoBrightnessEnabled;
+    }
+
+    public boolean isAutoBrightnessDisabledDueToDisplayOff() {
+        return mAutoBrightnessDisabledDueToDisplayOff;
+    }
+
+    /**
+     * Updates the {@link BrightnessConfiguration} that is currently being used by the associated
+     * display.
+     */
+    public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration,
+            boolean shouldResetShortTermModel) {
+        mBrightnessConfiguration = brightnessConfiguration;
+        setShouldResetShortTermModel(shouldResetShortTermModel);
+    }
+
+    /**
+     * Promotes the pending auto-brightness adjustments which are yet to be applied to the current
+     * adjustments. Note that this is not applying the new adjustments to the AutoBrightness mapping
+     * strategies, but is only accommodating the changes in this class.
+     */
+    public boolean processPendingAutoBrightnessAdjustments() {
+        mAutoBrightnessAdjustmentChanged = false;
+        if (Float.isNaN(mPendingAutoBrightnessAdjustment)) {
+            return false;
+        }
+        if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
+            mPendingAutoBrightnessAdjustment = Float.NaN;
+            return false;
+        }
+        mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
+        mPendingAutoBrightnessAdjustment = Float.NaN;
+        mTemporaryAutoBrightnessAdjustment = Float.NaN;
+        mAutoBrightnessAdjustmentChanged = true;
+        return true;
+    }
+
+    /**
+     * Updates the associated AutomaticBrightnessController
+     */
+    public void setAutomaticBrightnessController(
+            AutomaticBrightnessController automaticBrightnessController) {
+        if (automaticBrightnessController == mAutomaticBrightnessController) {
+            return;
+        }
+        if (mAutomaticBrightnessController != null) {
+            mAutomaticBrightnessController.stop();
+        }
+        mAutomaticBrightnessController = automaticBrightnessController;
+    }
+
+    /**
+     * Returns if the auto-brightness of the associated display has been enabled or not
+     */
+    public boolean shouldUseAutoBrightness() {
+        return mUseAutoBrightness;
+    }
+
+    /**
+     * Sets the auto-brightness state of the associated display. Called when the user makes a change
+     * in the system setting to enable/disable the auto-brightness.
+     */
+    public void setUseAutoBrightness(boolean useAutoBrightness) {
+        mUseAutoBrightness = useAutoBrightness;
+    }
+
+    /**
+     * Returns if the user made brightness change events(Typically when they interact with the
+     * brightness slider) were accommodated in the auto-brightness mapping strategies. This doesn't
+     * account for the latest changes that have been made by the user.
+     */
+    public boolean isShortTermModelActive() {
+        return mIsShortTermModelActive;
+    }
+
+    /**
+     * Sets the pending auto-brightness adjustments in the system settings. Executed
+     * when there is a change in the brightness system setting, or when there is a user switch.
+     */
+    public void updatePendingAutoBrightnessAdjustments() {
+        final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
+        mPendingAutoBrightnessAdjustment = Float.isNaN(adj) ? Float.NaN
+                : BrightnessUtils.clampBrightnessAdjustment(adj);
+    }
+
+    /**
+     * Sets the temporary auto-brightness adjustments
+     */
+    public void setTemporaryAutoBrightnessAdjustment(float temporaryAutoBrightnessAdjustment) {
+        mTemporaryAutoBrightnessAdjustment = temporaryAutoBrightnessAdjustment;
+    }
+
+    /**
+     * Dumps the state of this class.
+     */
+    public void dump(PrintWriter writer) {
+        writer.println("AutomaticBrightnessStrategy:");
+        writer.println("  mDisplayId=" + mDisplayId);
+        writer.println("  mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
+        writer.println("  mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
+        writer.println(
+                "  mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
+        writer.println("  mShouldResetShortTermModel=" + mShouldResetShortTermModel);
+        writer.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
+        writer.println("  mAutoBrightnessAdjustmentChanged=" + mAutoBrightnessAdjustmentChanged);
+        writer.println("  mAppliedTemporaryAutoBrightnessAdjustment="
+                + mAppliedTemporaryAutoBrightnessAdjustment);
+        writer.println("  mUseAutoBrightness=" + mUseAutoBrightness);
+        writer.println("  mWasShortTermModelActive=" + mIsShortTermModelActive);
+        writer.println("  mAutoBrightnessAdjustmentReasonsFlags="
+                + mAutoBrightnessAdjustmentReasonsFlags);
+    }
+
+    /**
+     * Indicates if any auto-brightness adjustments have happened since the last auto-brightness was
+     * set.
+     */
+    public boolean getAutoBrightnessAdjustmentChanged() {
+        return mAutoBrightnessAdjustmentChanged;
+    }
+
+    /**
+     * Returns whether the latest temporary auto-brightness adjustments have been applied or not
+     */
+    public boolean isTemporaryAutoBrightnessAdjustmentApplied() {
+        return mAppliedTemporaryAutoBrightnessAdjustment;
+    }
+
+    /**
+     * Evaluates the target automatic brightness of the associated display.
+     * @param brightnessEvent Event object to populate with details about why the specific
+     *                        brightness was chosen.
+     */
+    public float getAutomaticScreenBrightness(BrightnessEvent brightnessEvent) {
+        float brightness = (mAutomaticBrightnessController != null)
+                ? mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent)
+                : PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        adjustAutomaticBrightnessStateIfValid(brightness);
+        return brightness;
+    }
+
+    /**
+     * Get the automatic screen brightness based on the last observed lux reading. Used e.g. when
+     * entering doze - we disable the light sensor, invalidate the lux, but we still need to set
+     * the initial brightness in doze mode.
+     * @param brightnessEvent Event object to populate with details about why the specific
+     *                        brightness was chosen.
+     */
+    public float getAutomaticScreenBrightnessBasedOnLastObservedLux(
+            BrightnessEvent brightnessEvent) {
+        float brightness = (mAutomaticBrightnessController != null)
+                ? mAutomaticBrightnessController
+                .getAutomaticScreenBrightnessBasedOnLastObservedLux(brightnessEvent)
+                : PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        adjustAutomaticBrightnessStateIfValid(brightness);
+        return brightness;
+    }
+
+    /**
+     * Gets the auto-brightness adjustment flag change reason
+     */
+    public int getAutoBrightnessAdjustmentReasonsFlags() {
+        return mAutoBrightnessAdjustmentReasonsFlags;
+    }
+
+    /**
+     * Returns if the auto brightness has been applied
+     */
+    public boolean hasAppliedAutoBrightness() {
+        return mAppliedAutoBrightness;
+    }
+
+    /**
+     * Used to adjust the state of this class when the automatic brightness value for the
+     * associated display is valid
+     */
+    @VisibleForTesting
+    void adjustAutomaticBrightnessStateIfValid(float brightnessState) {
+        mAutoBrightnessAdjustmentReasonsFlags = isTemporaryAutoBrightnessAdjustmentApplied()
+                ? BrightnessReason.ADJUSTMENT_AUTO_TEMP
+                : BrightnessReason.ADJUSTMENT_AUTO;
+        float newAutoBrightnessAdjustment =
+                (mAutomaticBrightnessController != null)
+                        ? mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()
+                        : 0.0f;
+        if (!Float.isNaN(newAutoBrightnessAdjustment)
+                && mAutoBrightnessAdjustment != newAutoBrightnessAdjustment) {
+            // If the auto-brightness controller has decided to change the adjustment value
+            // used, make sure that's reflected in settings.
+            putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
+        } else {
+            mAutoBrightnessAdjustmentReasonsFlags = 0;
+        }
+    }
+
+    /**
+     * Sets up the system to reset the short term model. Note that this will not reset the model
+     * right away, but ensures that the reset happens whenever the next brightness change happens
+     */
+    @VisibleForTesting
+    void setShouldResetShortTermModel(boolean shouldResetShortTermModel) {
+        mShouldResetShortTermModel = shouldResetShortTermModel;
+    }
+
+    @VisibleForTesting
+    boolean shouldResetShortTermModel() {
+        return mShouldResetShortTermModel;
+    }
+
+    @VisibleForTesting
+    float getAutoBrightnessAdjustment() {
+        return mAutoBrightnessAdjustment;
+    }
+
+    @VisibleForTesting
+    float getPendingAutoBrightnessAdjustment() {
+        return mPendingAutoBrightnessAdjustment;
+    }
+
+    @VisibleForTesting
+    float getTemporaryAutoBrightnessAdjustment() {
+        return mTemporaryAutoBrightnessAdjustment;
+    }
+
+    @VisibleForTesting
+    void putAutoBrightnessAdjustmentSetting(float adjustment) {
+        if (mDisplayId == Display.DEFAULT_DISPLAY) {
+            mAutoBrightnessAdjustment = adjustment;
+            Settings.System.putFloatForUser(mContext.getContentResolver(),
+                    Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment,
+                    UserHandle.USER_CURRENT);
+        }
+    }
+
+    /**
+     * Sets if the auto-brightness is applied on the latest brightness change.
+     */
+    public void setAutoBrightnessApplied(boolean autoBrightnessApplied) {
+        mAppliedAutoBrightness = autoBrightnessApplied;
+    }
+
+    /**
+     * Accommodates the latest manual changes made by the user. Also updates {@link
+     * AutomaticBrightnessController} about the changes and configures it accordingly.
+     */
+    @VisibleForTesting
+    void accommodateUserBrightnessChanges(boolean userSetBrightnessChanged,
+            float lastUserSetScreenBrightness, int policy, int displayState,
+            BrightnessConfiguration brightnessConfiguration, int autoBrightnessState) {
+        // Update the pending auto-brightness adjustments if any. This typically checks and adjusts
+        // the state of the class if the user moves the brightness slider and has settled to a
+        // different value
+        processPendingAutoBrightnessAdjustments();
+        // Update the temporary auto-brightness adjustments if any. This typically checks and
+        // adjusts the state of this class if the user is in the process of moving the brightness
+        // slider, but hasn't settled to any value yet
+        float autoBrightnessAdjustment = updateTemporaryAutoBrightnessAdjustments();
+        mIsShortTermModelActive = false;
+        // Configure auto-brightness.
+        if (mAutomaticBrightnessController != null) {
+            // Accommodate user changes if any in the auto-brightness model
+            mAutomaticBrightnessController.configure(autoBrightnessState,
+                    brightnessConfiguration,
+                    lastUserSetScreenBrightness,
+                    userSetBrightnessChanged, autoBrightnessAdjustment,
+                    mAutoBrightnessAdjustmentChanged, policy, displayState,
+                    mShouldResetShortTermModel);
+            mShouldResetShortTermModel = false;
+            // We take note if the user brightness point is still being used in the current
+            // auto-brightness model.
+            mIsShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
+        }
+    }
+
+    /**
+     * Evaluates if there are any temporary auto-brightness adjustments which is not applied yet.
+     * Temporary brightness adjustments happen when the user moves the brightness slider in the
+     * auto-brightness mode, but hasn't settled to a value yet
+     */
+    private float updateTemporaryAutoBrightnessAdjustments() {
+        mAppliedTemporaryAutoBrightnessAdjustment =
+                !Float.isNaN(mTemporaryAutoBrightnessAdjustment);
+        // We do not update the mAutoBrightnessAdjustment with mTemporaryAutoBrightnessAdjustment
+        // since we have not settled to a value yet
+        return mAppliedTemporaryAutoBrightnessAdjustment
+                ? mTemporaryAutoBrightnessAdjustment : mAutoBrightnessAdjustment;
+    }
+
+    /**
+     * Returns the auto-brightness adjustment that is set in the system setting.
+     */
+    private float getAutoBrightnessAdjustmentSetting() {
+        final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
+        return Float.isNaN(adj) ? 0.0f : BrightnessUtils.clampBrightnessAdjustment(adj);
+    }
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
index 11edde9..009a47a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
@@ -16,12 +16,12 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManager;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -37,7 +37,7 @@
     // Set the brightness to the maximum value when display brightness boost is requested
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         // Todo(b/241308599): Introduce a validator class and add validations before setting
         // the brightness
         DisplayBrightnessState displayBrightnessState =
@@ -53,6 +53,11 @@
     }
 
     @Override
+    public int getReason() {
+        return BrightnessReason.REASON_BOOST;
+    }
+
+    @Override
     public void dump(PrintWriter writer) {}
 
     @Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
index 7b49957..e96b83a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
@@ -17,9 +17,9 @@
 package com.android.server.display.brightness.strategy;
 
 import android.annotation.NonNull;
-import android.hardware.display.DisplayManagerInternal;
 
 import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -33,10 +33,10 @@
     /**
      * Decides the DisplayBrightnessState that the system should change to.
      *
-     * @param displayPowerRequest The request to evaluate the updated brightness
+     * @param strategyExecutionRequest The request to evaluate the updated brightness
      */
     DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest);
+            StrategyExecutionRequest strategyExecutionRequest);
 
     /**
      * Returns the name of the Strategy
@@ -45,6 +45,11 @@
     String getName();
 
     /**
+     * Returns the reason for the change of the brightness
+     */
+    int getReason();
+
+    /**
      * Dumps the state of the Strategy
      * @param writer
      */
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategyConstants.java b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategyConstants.java
new file mode 100644
index 0000000..504683a
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategyConstants.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+public class DisplayBrightnessStrategyConstants {
+    static final String INVALID_BRIGHTNESS_STRATEGY_NAME = "InvalidBrightnessStrategy";
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
index 5afdc42..2b493f3 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
@@ -16,11 +16,10 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
-
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -32,11 +31,12 @@
 
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         // Todo(b/241308599): Introduce a validator class and add validations before setting
         // the brightness
         return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_DOZE,
-                displayPowerRequest.dozeScreenBrightness, displayPowerRequest.dozeScreenBrightness,
+                strategyExecutionRequest.getDisplayPowerRequest().dozeScreenBrightness,
+                strategyExecutionRequest.getDisplayPowerRequest().dozeScreenBrightness,
                 getName());
     }
 
@@ -53,4 +53,9 @@
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
         // DO NOTHING
     }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_DOZE;
+    }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
index 0650c1c..5a07ce2 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
@@ -16,12 +16,12 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManager;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -49,7 +49,7 @@
 
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         // Todo(b/241308599): Introduce a validator class and add validations before setting
         // the brightness
         return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_FOLLOWER,
@@ -89,4 +89,9 @@
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
         // DO NOTHING
     }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_FOLLOWER;
+    }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
index bf37ee0..9dc6cff 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
@@ -16,12 +16,12 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManager;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -32,7 +32,7 @@
 public class InvalidBrightnessStrategy implements DisplayBrightnessStrategy {
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_UNKNOWN,
                 PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 getName());
@@ -40,7 +40,7 @@
 
     @Override
     public String getName() {
-        return "InvalidBrightnessStrategy";
+        return DisplayBrightnessStrategyConstants.INVALID_BRIGHTNESS_STRATEGY_NAME;
     }
 
     @Override
@@ -51,4 +51,9 @@
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
         // DO NOTHING
     }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_UNKNOWN;
+    }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
index d2bb1e2..b46873a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
@@ -16,12 +16,13 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManager;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
+import com.android.server.display.feature.DisplayManagerFlags;
 
 import java.io.PrintWriter;
 
@@ -32,19 +33,29 @@
 public class OffloadBrightnessStrategy implements DisplayBrightnessStrategy {
 
     private float mOffloadScreenBrightness;
+    private final DisplayManagerFlags mDisplayManagerFlags;
 
-    public OffloadBrightnessStrategy() {
+    public OffloadBrightnessStrategy(DisplayManagerFlags displayManagerFlags) {
+        mDisplayManagerFlags = displayManagerFlags;
         mOffloadScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
     }
 
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
+        float offloadBrightness = mOffloadScreenBrightness;
+        if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
+            // We reset the offload brightness to invalid so that there is no stale value lingering
+            // around. After this request is processed, the current brightness will be set to
+            // offload brightness. Hence even if the lux values don't become valid for the next
+            // request, we will fallback to the current brightness anyways.
+            mOffloadScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        }
         BrightnessReason brightnessReason = new BrightnessReason();
         brightnessReason.setReason(BrightnessReason.REASON_OFFLOAD);
         return new DisplayBrightnessState.Builder()
-                .setBrightness(mOffloadScreenBrightness)
-                .setSdrBrightness(mOffloadScreenBrightness)
+                .setBrightness(offloadBrightness)
+                .setSdrBrightness(offloadBrightness)
                 .setBrightnessReason(brightnessReason)
                 .setDisplayBrightnessStrategyName(getName())
                 .setIsSlowChange(false)
@@ -77,6 +88,19 @@
     @Override
     public void strategySelectionPostProcessor(
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
-        // DO NOTHING
+        // We reset the offload brightness only if the selected strategy is not offload or invalid,
+        // as we are yet to use the brightness to evaluate the brightness state.
+        if (!strategySelectionNotifyRequest.getSelectedDisplayBrightnessStrategy().getName()
+                .equals(getName())
+                && !strategySelectionNotifyRequest.getSelectedDisplayBrightnessStrategy().getName()
+                .equals(
+                DisplayBrightnessStrategyConstants.INVALID_BRIGHTNESS_STRATEGY_NAME)) {
+            mOffloadScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        }
+    }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_OFFLOAD;
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
index 653170c..a2982b1 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
@@ -16,11 +16,10 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
-
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -31,12 +30,13 @@
 public class OverrideBrightnessStrategy implements DisplayBrightnessStrategy {
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         // Todo(b/241308599): Introduce a validator class and add validations before setting
         // the brightness
         return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_OVERRIDE,
-                displayPowerRequest.screenBrightnessOverride,
-                displayPowerRequest.screenBrightnessOverride, getName());
+                strategyExecutionRequest.getDisplayPowerRequest().screenBrightnessOverride,
+                strategyExecutionRequest.getDisplayPowerRequest()
+                        .screenBrightnessOverride, getName());
     }
 
     @Override
@@ -52,4 +52,9 @@
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
         // DO NOTHING
     }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_OVERRIDE;
+    }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
index f0cce23..6a3162c 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
@@ -16,12 +16,12 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManager;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -32,7 +32,7 @@
 public class ScreenOffBrightnessStrategy implements DisplayBrightnessStrategy {
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         // Todo(b/241308599): Introduce a validator class and add validations before setting
         // the brightness
         return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_SCREEN_OFF,
@@ -53,4 +53,9 @@
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
         // DO NOTHING
     }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_SCREEN_OFF;
+    }
 }
diff --git a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
index 91e1d09..6b8817a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
@@ -16,12 +16,12 @@
 
 package com.android.server.display.brightness.strategy;
 
-import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManager;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 import com.android.server.display.brightness.StrategySelectionNotifyRequest;
 
 import java.io.PrintWriter;
@@ -43,7 +43,7 @@
     // WindowManager or based on the display state.
     @Override
     public DisplayBrightnessState updateBrightness(
-            DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+            StrategyExecutionRequest strategyExecutionRequest) {
         // Todo(b/241308599): Introduce a validator class and add validations before setting
         // the brightness
         DisplayBrightnessState displayBrightnessState =
@@ -80,4 +80,9 @@
             StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
         // DO NOTHING
     }
+
+    @Override
+    public int getReason() {
+        return BrightnessReason.REASON_TEMPORARY;
+    }
 }
diff --git a/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java b/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java
index 5556365..7e2e10a 100644
--- a/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java
+++ b/services/core/java/com/android/server/display/config/EvenDimmerBrightnessData.java
@@ -66,6 +66,10 @@
      * Spline, mapping between backlight and brightness
      */
     public final Spline mBacklightToBrightness;
+
+    /**
+     * Spline, mapping the minimum nits for each lux condition.
+     */
     public final Spline mMinLuxToNits;
 
     @VisibleForTesting
@@ -114,34 +118,35 @@
             return null;
         }
 
-        List<Float> nitsList = lbm.getNits();
-        List<Float> backlightList = lbm.getBacklight();
-        List<Float> brightnessList = lbm.getBrightness();
-        float transitionPoints = lbm.getTransitionPoint().floatValue();
+        ComprehensiveBrightnessMap map = lbm.getBrightnessMapping();
+        if (map == null) {
+            return null;
+        }
+        String interpolation = map.getInterpolation();
 
-        if (nitsList.isEmpty()
-                || backlightList.size() != brightnessList.size()
-                || backlightList.size() != nitsList.size()) {
-            Slog.e(TAG, "Invalid even dimmer array lengths");
+        List<BrightnessPoint> brightnessPoints = map.getBrightnessPoint();
+        if (brightnessPoints.isEmpty()) {
             return null;
         }
 
-        float[] nits = new float[nitsList.size()];
-        float[] backlight = new float[nitsList.size()];
-        float[] brightness = new float[nitsList.size()];
+        float[] nits = new float[brightnessPoints.size()];
+        float[] backlight = new float[brightnessPoints.size()];
+        float[] brightness = new float[brightnessPoints.size()];
 
-        for (int i = 0; i < nitsList.size(); i++) {
-            nits[i] = nitsList.get(i);
-            backlight[i] = backlightList.get(i);
-            brightness[i] = brightnessList.get(i);
+        for (int i = 0; i < brightnessPoints.size(); i++) {
+            BrightnessPoint val = brightnessPoints.get(i);
+            nits[i] = val.getNits().floatValue();
+            backlight[i] = val.getBacklight().floatValue();
+            brightness[i] = val.getBrightness().floatValue();
         }
 
-        final NitsMap map = lbm.getLuxToMinimumNitsMap();
-        if (map == null) {
+        float transitionPoint = lbm.getTransitionPoint().floatValue();
+        final NitsMap minimumNitsMap = lbm.getLuxToMinimumNitsMap();
+        if (minimumNitsMap == null) {
             Slog.e(TAG, "Invalid min lux to nits mapping");
             return null;
         }
-        final List<Point> points = map.getPoint();
+        final List<Point> points = minimumNitsMap.getPoint();
         final int size = points.size();
 
         float[] minLux = new float[size];
@@ -164,7 +169,18 @@
             ++i;
         }
 
-        return new EvenDimmerBrightnessData(transitionPoints, nits, backlight, brightness,
+        // Explicitly choose linear interpolation.
+        if ("linear".equals(interpolation)) {
+            return new EvenDimmerBrightnessData(transitionPoint, nits, backlight, brightness,
+                    new Spline.LinearSpline(backlight, nits),
+                    new Spline.LinearSpline(nits, backlight),
+                    new Spline.LinearSpline(brightness, backlight),
+                    new Spline.LinearSpline(backlight, brightness),
+                    new Spline.LinearSpline(minLux, minNits)
+            );
+        }
+
+        return new EvenDimmerBrightnessData(transitionPoint, nits, backlight, brightness,
                 Spline.createSpline(backlight, nits),
                 Spline.createSpline(nits, backlight),
                 Spline.createSpline(brightness, backlight),
diff --git a/services/core/java/com/android/server/display/config/RefreshRateData.java b/services/core/java/com/android/server/display/config/RefreshRateData.java
new file mode 100644
index 0000000..b186fd5
--- /dev/null
+++ b/services/core/java/com/android/server/display/config/RefreshRateData.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.config;
+
+import android.annotation.Nullable;
+import android.content.res.Resources;
+
+import com.android.internal.R;
+
+/**
+ * RefreshRates config for display
+ */
+public class RefreshRateData {
+    public static RefreshRateData DEFAULT_REFRESH_RATE_DATA = loadRefreshRateData(null, null);
+
+    private static final int DEFAULT_REFRESH_RATE = 60;
+    private static final int DEFAULT_PEAK_REFRESH_RATE = 0;
+    private static final int DEFAULT_REFRESH_RATE_IN_HBM = 0;
+
+    /**
+     * The default refresh rate for a given device. This value sets the higher default
+     * refresh rate. If the hardware composer on the device supports display modes with
+     * a higher refresh rate than the default value specified here, the framework may use those
+     * higher refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling
+     * setFrameRate(). We have historically allowed fallback to mDefaultPeakRefreshRate if
+     * defaultRefreshRate is set to 0, but this is not supported anymore.
+     */
+    public final int defaultRefreshRate;
+
+    /**
+     * The default peak refresh rate for a given device. This value prevents the framework from
+     * using higher refresh rates, even if display modes with higher refresh rates are available
+     * from hardware composer. Only has an effect if the value is non-zero.
+     */
+    public final int defaultPeakRefreshRate;
+
+    /**
+     * Default refresh rate while the device has high brightness mode enabled for HDR.
+     */
+    public final int defaultRefreshRateInHbmHdr;
+
+    /**
+     * Default refresh rate while the device has high brightness mode enabled for Sunlight.
+     */
+    public final int defaultRefreshRateInHbmSunlight;
+
+    public RefreshRateData(int defaultRefreshRate, int defaultPeakRefreshRate,
+            int defaultRefreshRateInHbmHdr, int defaultRefreshRateInHbmSunlight) {
+        this.defaultRefreshRate = defaultRefreshRate;
+        this.defaultPeakRefreshRate = defaultPeakRefreshRate;
+        this.defaultRefreshRateInHbmHdr = defaultRefreshRateInHbmHdr;
+        this.defaultRefreshRateInHbmSunlight = defaultRefreshRateInHbmSunlight;
+    }
+
+
+    @Override
+    public String toString() {
+        return "RefreshRateData {"
+                + "defaultRefreshRate: " + defaultRefreshRate
+                + "defaultPeakRefreshRate: " + defaultPeakRefreshRate
+                + "defaultRefreshRateInHbmHdr: " + defaultRefreshRateInHbmHdr
+                + "defaultRefreshRateInHbmSunlight: " + defaultRefreshRateInHbmSunlight
+                + "} ";
+    }
+
+    /**
+     * Loads RefreshRateData from DisplayConfiguration and Resources
+     */
+    public static RefreshRateData loadRefreshRateData(
+            @Nullable DisplayConfiguration config, @Nullable Resources resources) {
+        RefreshRateConfigs refreshRateConfigs = config == null ? null : config.getRefreshRate();
+
+        int defaultRefreshRate = loadDefaultRefreshRate(refreshRateConfigs, resources);
+        int defaultPeakRefreshRate = loadDefaultPeakRefreshRate(refreshRateConfigs, resources);
+        int defaultRefreshRateInHbmHdr = loadDefaultRefreshRateInHbm(refreshRateConfigs, resources);
+        int defaultRefreshRateInHbmSunlight = loadDefaultRefreshRateInHbmSunlight(
+                refreshRateConfigs, resources);
+
+        return new RefreshRateData(defaultRefreshRate, defaultPeakRefreshRate,
+                defaultRefreshRateInHbmHdr, defaultRefreshRateInHbmSunlight);
+    }
+
+    private static int loadDefaultRefreshRate(
+            @Nullable RefreshRateConfigs refreshRateConfigs, @Nullable Resources resources) {
+        if (refreshRateConfigs != null && refreshRateConfigs.getDefaultRefreshRate() != null) {
+            return refreshRateConfigs.getDefaultRefreshRate().intValue();
+        } else if (resources != null) {
+            return resources.getInteger(R.integer.config_defaultRefreshRate);
+        }
+        return DEFAULT_REFRESH_RATE;
+    }
+
+    private static int loadDefaultPeakRefreshRate(
+            @Nullable RefreshRateConfigs refreshRateConfigs, @Nullable Resources resources) {
+        if (refreshRateConfigs != null && refreshRateConfigs.getDefaultPeakRefreshRate() != null) {
+            return refreshRateConfigs.getDefaultPeakRefreshRate().intValue();
+        } else if (resources != null) {
+            return resources.getInteger(R.integer.config_defaultPeakRefreshRate);
+        }
+        return DEFAULT_PEAK_REFRESH_RATE;
+    }
+
+    private static int loadDefaultRefreshRateInHbm(
+            @Nullable RefreshRateConfigs refreshRateConfigs, @Nullable Resources resources) {
+        if (refreshRateConfigs != null
+                && refreshRateConfigs.getDefaultRefreshRateInHbmHdr() != null) {
+            return refreshRateConfigs.getDefaultRefreshRateInHbmHdr().intValue();
+        } else if (resources != null) {
+            return resources.getInteger(R.integer.config_defaultRefreshRateInHbmHdr);
+        }
+        return DEFAULT_REFRESH_RATE_IN_HBM;
+    }
+
+    private static int loadDefaultRefreshRateInHbmSunlight(
+            @Nullable RefreshRateConfigs refreshRateConfigs, @Nullable Resources resources) {
+        if (refreshRateConfigs != null
+                && refreshRateConfigs.getDefaultRefreshRateInHbmSunlight() != null) {
+            return refreshRateConfigs.getDefaultRefreshRateInHbmSunlight().intValue();
+        } else if (resources != null) {
+            return resources.getInteger(R.integer.config_defaultRefreshRateInHbmSunlight);
+        }
+        return DEFAULT_REFRESH_RATE_IN_HBM;
+    }
+}
diff --git a/services/core/java/com/android/server/display/feature/Android.bp b/services/core/java/com/android/server/display/feature/Android.bp
index a0ead38..daf8832 100644
--- a/services/core/java/com/android/server/display/feature/Android.bp
+++ b/services/core/java/com/android/server/display/feature/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "display_flags",
     package: "com.android.server.display.feature.flags",
+    container: "system",
     srcs: [
         "*.aconfig",
     ],
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index d4319cc..a7dd243 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.display.feature.flags"
+container: "system"
 
 # Important: Flags must be accessed through DisplayManagerFlags.
 
@@ -125,7 +126,7 @@
     name: "even_dimmer"
     namespace: "display_manager"
     description: "Feature flag for extending the brightness below traditional range"
-    bug: "179428400"
+    bug: "294760970"
     is_fixed_read_only: true
 }
 
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index d084d1c..1c8c8a4 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -77,6 +77,7 @@
 import com.android.server.LocalServices;
 import com.android.server.display.DisplayDeviceConfig;
 import com.android.server.display.config.IdleScreenRefreshRateTimeoutLuxThresholdPoint;
+import com.android.server.display.config.RefreshRateData;
 import com.android.server.display.feature.DeviceConfigParameterProvider;
 import com.android.server.display.feature.DisplayManagerFlags;
 import com.android.server.display.utils.AmbientFilter;
@@ -105,6 +106,7 @@
  * picked by the system based on system-wide and display-specific configuration.
  */
 public class DisplayModeDirector {
+
     public static final float SYNCHRONIZED_REFRESH_RATE_TARGET = DEFAULT_LOW_REFRESH_RATE;
     public static final float SYNCHRONIZED_REFRESH_RATE_TOLERANCE = 1;
     private static final String TAG = "DisplayModeDirector";
@@ -119,8 +121,6 @@
     private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7;
     private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8;
 
-    private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE;
-
     private final Object mLock = new Object();
     private final Context mContext;
 
@@ -148,6 +148,8 @@
     private SparseArray<Display.Mode[]> mSupportedModesByDisplay;
     // A map from the display ID to the default mode of that display.
     private SparseArray<Display.Mode> mDefaultModeByDisplay;
+    // a map from display id to display device config
+    private SparseArray<DisplayDeviceConfig> mDisplayDeviceConfigByDisplay = new SparseArray<>();
 
     private BrightnessObserver mBrightnessObserver;
 
@@ -189,19 +191,19 @@
 
     private final DisplayManagerFlags mDisplayManagerFlags;
 
-    private final boolean mDvrrSupported;
-
+    private final DisplayDeviceConfigProvider mDisplayDeviceConfigProvider;
 
     public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
-            @NonNull DisplayManagerFlags displayManagerFlags) {
-        this(context, handler, new RealInjector(context), displayManagerFlags);
+            @NonNull DisplayManagerFlags displayManagerFlags,
+            @NonNull DisplayDeviceConfigProvider displayDeviceConfigProvider) {
+        this(context, handler, new RealInjector(context),
+                displayManagerFlags, displayDeviceConfigProvider);
     }
 
     public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
             @NonNull Injector injector,
-            @NonNull DisplayManagerFlags displayManagerFlags) {
-        mDvrrSupported = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_supportsDvrr);
+            @NonNull DisplayManagerFlags displayManagerFlags,
+            @NonNull DisplayDeviceConfigProvider displayDeviceConfigProvider) {
         mIsDisplayResolutionRangeVotingEnabled = displayManagerFlags
                 .isDisplayResolutionRangeVotingEnabled();
         mIsUserPreferredModeVoteEnabled = displayManagerFlags.isUserPreferredModeVoteEnabled();
@@ -212,6 +214,7 @@
         mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled = displayManagerFlags
                 .isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled();
         mDisplayManagerFlags = displayManagerFlags;
+        mDisplayDeviceConfigProvider = displayDeviceConfigProvider;
         mContext = context;
         mHandler = new DisplayModeDirectorHandler(handler.getLooper());
         mInjector = injector;
@@ -222,20 +225,19 @@
         mAppRequestObserver = new AppRequestObserver();
         mConfigParameterProvider = new DeviceConfigParameterProvider(injector.getDeviceConfig());
         mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
-        mSettingsObserver = new SettingsObserver(context, handler, mDvrrSupported,
-                displayManagerFlags);
-        mBrightnessObserver = new BrightnessObserver(context, handler, injector, mDvrrSupported,
+        mSettingsObserver = new SettingsObserver(context, handler, displayManagerFlags);
+        mBrightnessObserver = new BrightnessObserver(context, handler, injector,
                 displayManagerFlags);
         mDefaultDisplayDeviceConfig = null;
         mUdfpsObserver = new UdfpsObserver();
         mVotesStorage = new VotesStorage(this::notifyDesiredDisplayModeSpecsChangedLocked,
                 mVotesStatsReporter);
-        mDisplayObserver = new DisplayObserver(context, handler, mVotesStorage);
+        mDisplayObserver = new DisplayObserver(context, handler, mVotesStorage, injector);
         mSensorObserver = new ProximitySensorObserver(mVotesStorage, injector);
         mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, mVotesStorage);
         mHbmObserver = new HbmObserver(injector, mVotesStorage, BackgroundThread.getHandler(),
                 mDeviceConfigDisplaySettings);
-        if (mDvrrSupported && displayManagerFlags.isRestrictDisplayModesEnabled()) {
+        if (displayManagerFlags.isRestrictDisplayModesEnabled()) {
             mSystemRequestObserver = new SystemRequestObserver(mVotesStorage);
         } else {
             mSystemRequestObserver = null;
@@ -315,7 +317,8 @@
             List<Display.Mode> availableModes = new ArrayList<>();
             availableModes.add(defaultMode);
             VoteSummary primarySummary = new VoteSummary(mIsDisplayResolutionRangeVotingEnabled,
-                    mDvrrSupported, mLoggingEnabled, mSupportsFrameRateOverride);
+                    isVrrSupportedLocked(displayId),
+                    mLoggingEnabled, mSupportsFrameRateOverride);
             int lowestConsideredPriority = Vote.MIN_PRIORITY;
             int highestConsideredPriority = Vote.MAX_PRIORITY;
 
@@ -355,7 +358,8 @@
             }
 
             VoteSummary appRequestSummary = new VoteSummary(mIsDisplayResolutionRangeVotingEnabled,
-                    mDvrrSupported, mLoggingEnabled, mSupportsFrameRateOverride);
+                    isVrrSupportedLocked(displayId),
+                    mLoggingEnabled, mSupportsFrameRateOverride);
 
             appRequestSummary.applyVotes(votes,
                     Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF,
@@ -442,6 +446,20 @@
         return mAppRequestObserver;
     }
 
+    private boolean isVrrSupportedLocked(int displayId) {
+        DisplayDeviceConfig config = mDisplayDeviceConfigByDisplay.get(displayId);
+        return config != null && config.isVrrSupportEnabled();
+    }
+
+    private boolean isVrrSupportedByAnyDisplayLocked() {
+        for (int i = 0; i < mDisplayDeviceConfigByDisplay.size(); i++) {
+            if (mDisplayDeviceConfigByDisplay.valueAt(i).isVrrSupportEnabled()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate ranges.
      */
@@ -539,7 +557,13 @@
      */
     public void requestDisplayModes(IBinder token, int displayId, int[] modeIds) {
         if (mSystemRequestObserver != null) {
-            mSystemRequestObserver.requestDisplayModes(token, displayId, modeIds);
+            boolean vrrSupported;
+            synchronized (mLock) {
+                vrrSupported = isVrrSupportedLocked(displayId);
+            }
+            if (vrrSupported) {
+                mSystemRequestObserver.requestDisplayModes(token, displayId, modeIds);
+            }
         }
     }
 
@@ -627,6 +651,11 @@
     }
 
     @VisibleForTesting
+    void injectDisplayDeviceConfigByDisplay(SparseArray<DisplayDeviceConfig> ddcByDisplay) {
+        mDisplayDeviceConfigByDisplay = ddcByDisplay;
+    }
+
+    @VisibleForTesting
     void injectVotesByDisplay(SparseArray<SparseArray<Vote>> votesByDisplay) {
         mVotesStorage.injectVotesByDisplay(votesByDisplay);
     }
@@ -672,6 +701,16 @@
     }
 
     /**
+     * Provides access to DisplayDeviceConfig for specific display
+     */
+    public interface DisplayDeviceConfigProvider {
+        /**
+         * Returns DisplayDeviceConfig for specific display
+         */
+        @Nullable DisplayDeviceConfig getDisplayDeviceConfig(int displayId);
+    }
+
+    /**
      * Listens for changes refresh rate coordination.
      */
     public interface DesiredDisplayModeSpecsListener {
@@ -906,11 +945,11 @@
         private float mDefaultPeakRefreshRate;
         private float mDefaultRefreshRate;
 
-        SettingsObserver(@NonNull Context context, @NonNull Handler handler, boolean dvrrSupported,
+        SettingsObserver(@NonNull Context context, @NonNull Handler handler,
                 DisplayManagerFlags flags) {
             super(handler);
             mContext = context;
-            mVsynLowPowerVoteEnabled = dvrrSupported && flags.isVsyncLowPowerVoteEnabled();
+            mVsynLowPowerVoteEnabled = flags.isVsyncLowPowerVoteEnabled();
             // We don't want to load from the DeviceConfig while constructing since this leads to
             // a spike in the latency of DisplayManagerService startup. This happens because
             // reading from the DeviceConfig is an intensive IO operation and having it in the
@@ -923,13 +962,15 @@
          * This is used to update the refresh rate configs from the DeviceConfig, which
          * if missing from DisplayDeviceConfig, and finally fallback to config.xml.
          */
-        public void setRefreshRates(DisplayDeviceConfig displayDeviceConfig,
+        void setRefreshRates(DisplayDeviceConfig displayDeviceConfig,
                 boolean attemptReadFromFeatureParams) {
+            RefreshRateData refreshRateData = displayDeviceConfig == null ? null
+                    : displayDeviceConfig.getRefreshRateData();
             setDefaultPeakRefreshRate(displayDeviceConfig, attemptReadFromFeatureParams);
             mDefaultRefreshRate =
-                    (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger(
-                        R.integer.config_defaultRefreshRate)
-                        : (float) displayDeviceConfig.getDefaultRefreshRate();
+                    (refreshRateData == null) ? (float) mContext.getResources().getInteger(
+                            R.integer.config_defaultRefreshRate)
+                            : (float) refreshRateData.defaultRefreshRate;
         }
 
         public void observe() {
@@ -1011,7 +1052,8 @@
                 defaultPeakRefreshRate =
                         (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger(
                                 R.integer.config_defaultPeakRefreshRate)
-                                : (float) displayDeviceConfig.getDefaultPeakRefreshRate();
+                                : (float) displayDeviceConfig.getRefreshRateData()
+                                        .defaultPeakRefreshRate;
             }
             mDefaultPeakRefreshRate = defaultPeakRefreshRate;
         }
@@ -1020,7 +1062,7 @@
             boolean inLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.LOW_POWER_MODE, 0 /*default*/) != 0;
             final Vote vote;
-            if (inLowPowerMode && mVsynLowPowerVoteEnabled) {
+            if (inLowPowerMode && mVsynLowPowerVoteEnabled && isVrrSupportedByAnyDisplayLocked()) {
                 vote = Vote.forSupportedRefreshRates(List.of(
                         new SupportedRefreshRatesVote.RefreshRates(/* peakRefreshRate= */ 60f,
                                 /* vsyncRate= */ 240f),
@@ -1065,20 +1107,6 @@
             if (Float.isInfinite(minRefreshRate)) {
                 // Infinity means that we want the highest possible refresh rate
                 minRefreshRate = highestRefreshRate;
-
-                if (!mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled
-                        && displayId == Display.DEFAULT_DISPLAY) {
-                    // The flag has been turned off, we need to restore the original value. We'll
-                    // use the peak refresh rate of the default display.
-                    Settings.System.putFloatForUser(cr, Settings.System.MIN_REFRESH_RATE,
-                            highestRefreshRate, cr.getUserId());
-                }
-            } else if (mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled
-                    && displayId == Display.DEFAULT_DISPLAY
-                    && Math.round(minRefreshRate) == Math.round(highestRefreshRate)) {
-                // The flag has been turned on, we need to upgrade the setting
-                Settings.System.putFloatForUser(cr, Settings.System.MIN_REFRESH_RATE,
-                        Float.POSITIVE_INFINITY, cr.getUserId());
             }
 
             float peakRefreshRate = Settings.System.getFloatForUser(cr,
@@ -1086,20 +1114,6 @@
             if (Float.isInfinite(peakRefreshRate)) {
                 // Infinity means that we want the highest possible refresh rate
                 peakRefreshRate = highestRefreshRate;
-
-                if (!mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled
-                        && displayId == Display.DEFAULT_DISPLAY) {
-                    // The flag has been turned off, we need to restore the original value. We'll
-                    // use the peak refresh rate of the default display.
-                    Settings.System.putFloatForUser(cr, Settings.System.PEAK_REFRESH_RATE,
-                            highestRefreshRate, cr.getUserId());
-                }
-            } else if (mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled
-                    && displayId == Display.DEFAULT_DISPLAY
-                    && Math.round(peakRefreshRate) == Math.round(highestRefreshRate)) {
-                // The flag has been turned on, we need to upgrade the setting
-                Settings.System.putFloatForUser(cr, Settings.System.PEAK_REFRESH_RATE,
-                        Float.POSITIVE_INFINITY, cr.getUserId());
             }
 
             updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate,
@@ -1190,8 +1204,8 @@
         /**
          * Sets refresh rates from app request
          */
-        public void setAppRequest(int displayId, int modeId, float requestedMinRefreshRateRange,
-                float requestedMaxRefreshRateRange) {
+        public void setAppRequest(int displayId, int modeId,
+                float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) {
             synchronized (mLock) {
                 setAppRequestedModeLocked(displayId, modeId);
                 setAppPreferredRefreshRateRangeLocked(displayId, requestedMinRefreshRateRange,
@@ -1204,7 +1218,6 @@
             if (Objects.equals(requestedMode, mAppRequestedModeByDisplay.get(displayId))) {
                 return;
             }
-
             final Vote baseModeRefreshRateVote;
             final Vote sizeVote;
             if (requestedMode != null) {
@@ -1295,13 +1308,15 @@
         private final Context mContext;
         private final Handler mHandler;
         private final VotesStorage mVotesStorage;
+
         private int mExternalDisplayPeakWidth;
         private int mExternalDisplayPeakHeight;
         private int mExternalDisplayPeakRefreshRate;
         private final boolean mRefreshRateSynchronizationEnabled;
         private final Set<Integer> mExternalDisplaysConnected = new HashSet<>();
 
-        DisplayObserver(Context context, Handler handler, VotesStorage votesStorage) {
+        DisplayObserver(Context context, Handler handler, VotesStorage votesStorage,
+                Injector injector) {
             mContext = context;
             mHandler = handler;
             mVotesStorage = votesStorage;
@@ -1342,17 +1357,21 @@
                 modes.put(displayId, info.supportedModes);
                 defaultModes.put(displayId, info.getDefaultMode());
             }
+            DisplayDeviceConfig defaultDisplayConfig = mDisplayDeviceConfigProvider
+                    .getDisplayDeviceConfig(Display.DEFAULT_DISPLAY);
             synchronized (mLock) {
                 final int size = modes.size();
                 for (int i = 0; i < size; i++) {
                     mSupportedModesByDisplay.put(modes.keyAt(i), modes.valueAt(i));
                     mDefaultModeByDisplay.put(defaultModes.keyAt(i), defaultModes.valueAt(i));
                 }
+                mDisplayDeviceConfigByDisplay.put(Display.DEFAULT_DISPLAY, defaultDisplayConfig);
             }
         }
 
         @Override
         public void onDisplayAdded(int displayId) {
+            updateDisplayDeviceConfig(displayId);
             DisplayInfo displayInfo = getDisplayInfo(displayId);
             updateDisplayModes(displayId, displayInfo);
             updateLayoutLimitedFrameRate(displayId, displayInfo);
@@ -1366,6 +1385,7 @@
             synchronized (mLock) {
                 mSupportedModesByDisplay.remove(displayId);
                 mDefaultModeByDisplay.remove(displayId);
+                mDisplayDeviceConfigByDisplay.remove(displayId);
                 mSettingsObserver.removeRefreshRateSetting(displayId);
             }
             updateLayoutLimitedFrameRate(displayId, null);
@@ -1376,6 +1396,7 @@
 
         @Override
         public void onDisplayChanged(int displayId) {
+            updateDisplayDeviceConfig(displayId);
             DisplayInfo displayInfo = getDisplayInfo(displayId);
             updateDisplayModes(displayId, displayInfo);
             updateLayoutLimitedFrameRate(displayId, displayInfo);
@@ -1505,6 +1526,14 @@
             mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE, null);
         }
 
+        private void updateDisplayDeviceConfig(int displayId) {
+            DisplayDeviceConfig config = mDisplayDeviceConfigProvider
+                    .getDisplayDeviceConfig(displayId);
+            synchronized (mLock) {
+                mDisplayDeviceConfigByDisplay.put(displayId, config);
+            }
+        }
+
         private void updateDisplayModes(int displayId, @Nullable DisplayInfo info) {
             if (info == null) {
                 return;
@@ -1631,7 +1660,7 @@
         private @Temperature.ThrottlingStatus int mThermalStatus = Temperature.THROTTLING_NONE;
 
         BrightnessObserver(Context context, Handler handler, Injector injector,
-                boolean dvrrSupported , DisplayManagerFlags flags) {
+                DisplayManagerFlags flags) {
             mContext = context;
             mHandler = handler;
             mInjector = injector;
@@ -1639,7 +1668,7 @@
                 /* attemptReadFromFeatureParams= */ false);
             mRefreshRateInHighZone = context.getResources().getInteger(
                     R.integer.config_fixedRefreshRateInHighZone);
-            mVsyncLowLightBlockingVoteEnabled = dvrrSupported && flags.isVsyncLowLightVoteEnabled();
+            mVsyncLowLightBlockingVoteEnabled = flags.isVsyncLowLightVoteEnabled();
         }
 
         /**
@@ -2225,7 +2254,8 @@
                     }
                 }
 
-                if (mVsyncLowLightBlockingVoteEnabled) {
+                if (mVsyncLowLightBlockingVoteEnabled
+                        && isVrrSupportedLocked(Display.DEFAULT_DISPLAY)) {
                     refreshRateSwitchingVote = Vote.forSupportedRefreshRatesAndDisableSwitching(
                             List.of(
                                     new SupportedRefreshRatesVote.RefreshRates(
@@ -2783,7 +2813,7 @@
         private int getRefreshRateInHbmHdr(DisplayDeviceConfig displayDeviceConfig) {
             return getRefreshRate(
                     () -> mConfigParameterProvider.getRefreshRateInHbmHdr(),
-                    () -> displayDeviceConfig.getDefaultRefreshRateInHbmHdr(),
+                    () -> displayDeviceConfig.getRefreshRateData().defaultRefreshRateInHbmHdr,
                     R.integer.config_defaultRefreshRateInHbmHdr,
                     displayDeviceConfig
             );
@@ -2792,7 +2822,7 @@
         private int getRefreshRateInHbmSunlight(DisplayDeviceConfig displayDeviceConfig) {
             return getRefreshRate(
                     () -> mConfigParameterProvider.getRefreshRateInHbmSunlight(),
-                    () -> displayDeviceConfig.getDefaultRefreshRateInHbmSunlight(),
+                    () -> displayDeviceConfig.getRefreshRateData().defaultRefreshRateInHbmSunlight,
                     R.integer.config_defaultRefreshRateInHbmSunlight,
                     displayDeviceConfig
             );
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 0e8a5fb..a818eab 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -249,6 +249,16 @@
         mCurrentDream.mAppTask = appTask;
     }
 
+    void setDreamHasFocus(boolean hasFocus) {
+        if (mCurrentDream != null) {
+            mCurrentDream.mDreamHasFocus = hasFocus;
+        }
+    }
+
+    boolean dreamHasFocus() {
+        return mCurrentDream != null && mCurrentDream.mDreamHasFocus;
+    }
+
     /**
      * Sends a user activity signal to PowerManager to stop the screen from turning off immediately
      * if there hasn't been any user interaction in a while.
@@ -271,6 +281,21 @@
         stopDreamInstance(immediate, reason, mCurrentDream);
     }
 
+    public boolean bringDreamToFront() {
+        if (mCurrentDream == null || mCurrentDream.mService == null) {
+            return false;
+        }
+
+        try {
+            mCurrentDream.mService.comeToFront();
+            return true;
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error asking dream to come to the front", e);
+        }
+
+        return false;
+    }
+
     /**
      * Stops the given dream instance.
      *
@@ -426,6 +451,7 @@
         private String mStopReason;
         private long mDreamStartTime;
         public boolean mWakingGently;
+        public boolean mDreamHasFocus;
 
         private final Runnable mStopPreviousDreamsIfNeeded = this::stopPreviousDreamsIfNeeded;
         private final Runnable mReleaseWakeLockIfNeeded = this::releaseWakeLockIfNeeded;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 42c9e08..fc63494 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.service.dreams.Flags.dreamTracksFocus;
 
 import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID;
 
@@ -406,8 +407,10 @@
     /** Whether dreaming can start given user settings and the current dock/charge state. */
     private boolean canStartDreamingInternal(boolean isScreenOn) {
         synchronized (mLock) {
-            // Can't start dreaming if we are already dreaming.
-            if (isScreenOn && isDreamingInternal()) {
+            // Can't start dreaming if we are already dreaming and the dream has focus. If we are
+            // dreaming but the dream does not have focus, then the dream can be brought to the
+            // front so it does have focus.
+            if (isScreenOn && isDreamingInternal() && dreamHasFocus()) {
                 return false;
             }
 
@@ -442,11 +445,20 @@
         }
     }
 
+    private boolean dreamHasFocus() {
+        // Dreams always had focus before they were able to track it.
+        return !dreamTracksFocus() || mController.dreamHasFocus();
+    }
+
     protected void requestStartDreamFromShell() {
         requestDreamInternal();
     }
 
     private void requestDreamInternal() {
+        if (isDreamingInternal() && !dreamHasFocus() && mController.bringDreamToFront()) {
+            return;
+        }
+
         // Ask the power manager to nap.  It will eventually call back into
         // startDream() if/when it is appropriate to start dreaming.
         // Because napping could cause the screen to turn off immediately if the dream
@@ -1128,6 +1140,16 @@
             });
         }
 
+        @Override
+        public void onDreamFocusChanged(boolean hasFocus) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mController.setDreamHasFocus(hasFocus);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         boolean canLaunchDreamActivity(String dreamPackageName, String packageName,
                 int callingUid) {
             if (dreamPackageName == null || packageName == null) {
diff --git a/services/core/java/com/android/server/feature/Android.bp b/services/core/java/com/android/server/feature/Android.bp
deleted file mode 100644
index 067288d..0000000
--- a/services/core/java/com/android/server/feature/Android.bp
+++ /dev/null
@@ -1,12 +0,0 @@
-aconfig_declarations {
-    name: "dropbox_flags",
-    package: "com.android.server.feature.flags",
-    srcs: [
-        "dropbox_flags.aconfig",
-    ],
-}
-
-java_aconfig_library {
-    name: "dropbox_flags_lib",
-    aconfig_declarations: "dropbox_flags",
-}
diff --git a/services/core/java/com/android/server/feature/dropbox_flags.aconfig b/services/core/java/com/android/server/feature/dropbox_flags.aconfig
index 14e964b..98978f0 100644
--- a/services/core/java/com/android/server/feature/dropbox_flags.aconfig
+++ b/services/core/java/com/android/server/feature/dropbox_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.feature.flags"
+container: "system"
 
 flag{
     name: "enable_read_dropbox_permission"
diff --git a/services/core/java/com/android/server/flags/services.aconfig b/services/core/java/com/android/server/flags/services.aconfig
index 8e0eb05..e43d086 100644
--- a/services/core/java/com/android/server/flags/services.aconfig
+++ b/services/core/java/com/android/server/flags/services.aconfig
@@ -6,4 +6,14 @@
      name: "enable_odp_feature_guard"
      description: "Enable guard based on system feature to prevent OnDevicePersonalization service from starting on form factors."
      bug: "322249125"
-}
\ No newline at end of file
+}
+
+flag {
+    namespace: "input"
+    name: "new_bugreport_keyboard_shortcut"
+    description: "Enable META+CTRL+BACKSPACE keyboard shortcut for taking a bug report"
+    bug: "335607520"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
index 5be0735..d494be5 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
@@ -17,6 +17,7 @@
 package com.android.server.grammaticalinflection;
 
 import android.app.backup.BackupManager;
+import android.content.AttributionSource;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -30,6 +31,7 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
 import java.time.Clock;
 import java.time.Duration;
 import java.util.HashMap;
@@ -47,6 +49,7 @@
     private final PackageManager mPackageManager;
     private final GrammaticalInflectionService mGrammaticalGenderService;
     private final Clock mClock;
+    private final AttributionSource mAttributionSource;
 
     static class StagedData {
         final long mCreationTimeMillis;
@@ -58,8 +61,9 @@
         }
     }
 
-    public GrammaticalInflectionBackupHelper(GrammaticalInflectionService grammaticalGenderService,
-            PackageManager packageManager) {
+    public GrammaticalInflectionBackupHelper(AttributionSource attributionSource,
+            GrammaticalInflectionService grammaticalGenderService, PackageManager packageManager) {
+        mAttributionSource = attributionSource;
         mGrammaticalGenderService = grammaticalGenderService;
         mPackageManager = packageManager;
         mClock = Clock.systemUTC();
@@ -115,6 +119,23 @@
         }
     }
 
+    /**
+     * Returns the system-gender to be backed up as a data-blob.
+     */
+    public byte[] getSystemBackupPayload(int userId) {
+        int gender = mGrammaticalGenderService.getSystemGrammaticalGender(mAttributionSource,
+                userId);
+        return intToByteArray(gender);
+    }
+
+    /**
+     * Restores the system-gender that were previously backed up.
+     */
+    public void applyRestoredSystemPayload(byte[] payload, int userId) {
+        int gender = convertByteArrayToInt(payload);
+        mGrammaticalGenderService.setSystemWideGrammaticalGender(gender, userId);
+    }
+
     private boolean hasSetBeforeRestoring(String pkgName, int userId) {
         return mGrammaticalGenderService.getApplicationGrammaticalGender(pkgName, userId)
                 != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
@@ -157,6 +178,17 @@
         }
     }
 
+    private byte[] intToByteArray(final int gender) {
+        ByteBuffer bb = ByteBuffer.allocate(4);
+        bb.putInt(gender);
+        return bb.array();
+    }
+
+    private int convertByteArrayToInt(byte[] intBytes) {
+        ByteBuffer byteBuffer = ByteBuffer.wrap(intBytes);
+        return byteBuffer.getInt();
+    }
+
     private HashMap<String, Integer> readFromByteArray(byte[] payload) {
         HashMap<String, Integer> data = new HashMap<>();
 
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
index c2c82ed..2816d08 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
@@ -62,5 +62,16 @@
      * Whether the package can get the system grammatical gender or not.
      */
     public abstract boolean canGetSystemGrammaticalGender(int uid, @Nullable String packageName);
+
+
+    /**
+     * Returns the system-gender to be backed up as a data-blob.
+     */
+    public abstract @Nullable byte[] getSystemBackupPayload(int userId);
+
+    /**
+     * Restores the system-gender that were previously backed up.
+     */
+    public abstract void applyRestoredSystemPayload(byte[] payload, int userId);
 }
 
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index 96d4bda..93a71b9 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -102,7 +102,8 @@
         mContext = context;
         mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
-        mBackupHelper = new GrammaticalInflectionBackupHelper(this, context.getPackageManager());
+        mBackupHelper = new GrammaticalInflectionBackupHelper(mContext.getAttributionSource(), this,
+                context.getPackageManager());
         mBinderService = new GrammaticalInflectionBinderService();
         mPermissionManager = context.getSystemService(PermissionManager.class);
     }
@@ -176,6 +177,18 @@
         }
 
         @Override
+        @Nullable
+        public byte[] getSystemBackupPayload(int userId) {
+            isCallerAllowed();
+            return mBackupHelper.getSystemBackupPayload(userId);
+        }
+
+        @Override
+        public void applyRestoredSystemPayload(byte[] payload, int userId) {
+            mBackupHelper.applyRestoredSystemPayload(payload, userId);
+        }
+
+        @Override
         public int getSystemGrammaticalGender(int userId) {
             return checkSystemTermsOfAddressIsEnabled()
                     ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
@@ -290,6 +303,7 @@
                     userId,
                     grammaticalGender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
                     preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
+            GrammaticalInflectionBackupHelper.notifyBackupManager();
         } catch (RemoteException e) {
             Log.w(TAG, "Can not update configuration", e);
         }
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 7b844a0..47f73f1 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -165,7 +165,12 @@
 
         @Override
         public void onBootPhase(int phase) {
-            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+            final int latestFontLoadBootPhase =
+                    (Flags.completeFontLoadInSystemServicesReady())
+                            // Complete font load in the phase before PHASE_SYSTEM_SERVICES_READY
+                            ? SystemService.PHASE_LOCK_SETTINGS_READY
+                            : SystemService.PHASE_ACTIVITY_MANAGER_READY;
+            if (phase == latestFontLoadBootPhase) {
                 // Wait for FontManagerService to start since it will be needed after this point.
                 mServiceStarted.join();
             }
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 9d04682..ea240c7 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -196,7 +196,12 @@
                 File signatureFile = new File(dir, FONT_SIGNATURE_FILE);
                 if (!signatureFile.exists()) {
                     Slog.i(TAG, "The signature file is missing.");
-                    return;
+                    if (com.android.text.flags.Flags.fixFontUpdateFailure()) {
+                        return;
+                    } else {
+                        FileUtils.deleteContentsAndDir(dir);
+                        continue;
+                    }
                 }
                 byte[] signature;
                 try {
@@ -221,33 +226,39 @@
 
                 FontFileInfo fontFileInfo = validateFontFile(fontFile, signature);
                 if (fontConfig == null) {
-                    // Use preinstalled font config for checking revision number.
-                    fontConfig = mConfigSupplier.apply(Collections.emptyMap());
+                    if (com.android.text.flags.Flags.fixFontUpdateFailure()) {
+                        // Use preinstalled font config for checking revision number.
+                        fontConfig = mConfigSupplier.apply(Collections.emptyMap());
+                    } else {
+                        fontConfig = getSystemFontConfig();
+                    }
                 }
                 addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, true /* deleteOldFile */);
             }
 
-            // Treat as error if post script name of font family was not installed.
-            for (int i = 0; i < config.fontFamilies.size(); ++i) {
-                FontUpdateRequest.Family family = config.fontFamilies.get(i);
-                for (int j = 0; j < family.getFonts().size(); ++j) {
-                    FontUpdateRequest.Font font = family.getFonts().get(j);
-                    if (mFontFileInfoMap.containsKey(font.getPostScriptName())) {
-                        continue;
-                    }
+            if (com.android.text.flags.Flags.fixFontUpdateFailure()) {
+                // Treat as error if post script name of font family was not installed.
+                for (int i = 0; i < config.fontFamilies.size(); ++i) {
+                    FontUpdateRequest.Family family = config.fontFamilies.get(i);
+                    for (int j = 0; j < family.getFonts().size(); ++j) {
+                        FontUpdateRequest.Font font = family.getFonts().get(j);
+                        if (mFontFileInfoMap.containsKey(font.getPostScriptName())) {
+                            continue;
+                        }
 
-                    if (fontConfig == null) {
-                        fontConfig = mConfigSupplier.apply(Collections.emptyMap());
-                    }
+                        if (fontConfig == null) {
+                            fontConfig = mConfigSupplier.apply(Collections.emptyMap());
+                        }
 
-                    if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) {
-                        continue;
-                    }
+                        if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) {
+                            continue;
+                        }
 
-                    Slog.e(TAG, "Unknown font that has PostScript name "
-                            + font.getPostScriptName() + " is requested in FontFamily "
-                            + family.getName());
-                    return;
+                        Slog.e(TAG, "Unknown font that has PostScript name "
+                                + font.getPostScriptName() + " is requested in FontFamily "
+                                + family.getName());
+                        return;
+                    }
                 }
             }
 
@@ -262,7 +273,9 @@
                 mFontFileInfoMap.clear();
                 mLastModifiedMillis = 0;
                 FileUtils.deleteContents(mFilesDir);
-                mConfigFile.delete();
+                if (com.android.text.flags.Flags.fixFontUpdateFailure()) {
+                    mConfigFile.delete();
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 77119d5..f32c11d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1197,54 +1197,11 @@
     }
 
     @Override // Binder call
-    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
-            final InputDeviceIdentifier identifier) {
-        return mKeyboardLayoutManager.getKeyboardLayoutsForInputDevice(identifier);
-    }
-
-    @Override // Binder call
     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
         return mKeyboardLayoutManager.getKeyboardLayout(keyboardLayoutDescriptor);
     }
 
     @Override // Binder call
-    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
-        return mKeyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(identifier);
-    }
-
-    @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
-    @Override // Binder call
-    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        super.setCurrentKeyboardLayoutForInputDevice_enforcePermission();
-        mKeyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
-
-    @Override // Binder call
-    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
-        return mKeyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(identifier);
-    }
-
-    @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
-    @Override // Binder call
-    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        super.addKeyboardLayoutForInputDevice_enforcePermission();
-        mKeyboardLayoutManager.addKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
-
-    @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
-    @Override // Binder call
-    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        super.removeKeyboardLayoutForInputDevice_enforcePermission();
-        mKeyboardLayoutManager.removeKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
-
-    @Override // Binder call
     public KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
             InputDeviceIdentifier identifier, @UserIdInt int userId,
             @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype) {
@@ -1270,11 +1227,6 @@
                 imeInfo, imeSubtype);
     }
 
-
-    public void switchKeyboardLayout(int deviceId, int direction) {
-        mKeyboardLayoutManager.switchKeyboardLayout(deviceId, direction);
-    }
-
     public void setFocusedApplication(int displayId, InputApplicationHandle application) {
         mNative.setFocusedApplication(displayId, application);
     }
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 6610081..97c32b9 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -60,7 +60,6 @@
 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;
@@ -69,7 +68,6 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
-import android.widget.Toast;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -96,7 +94,6 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.stream.Stream;
 
 /**
  * A component of {@link InputManagerService} responsible for managing Physical Keyboard layouts.
@@ -112,9 +109,8 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
-    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
-    private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
-    private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
+    private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 2;
+    private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 3;
 
     private final Context mContext;
     private final NativeInputManagerService mNative;
@@ -126,13 +122,14 @@
     // Connected keyboards with associated keyboard layouts (either auto-detected or manually
     // selected layout).
     private final SparseArray<KeyboardConfiguration> mConfiguredKeyboards = new SparseArray<>();
-    private Toast mSwitchedKeyboardLayoutToast;
 
     // This cache stores "best-matched" layouts so that we don't need to run the matching
     // algorithm repeatedly.
     @GuardedBy("mKeyboardLayoutCache")
     private final Map<String, KeyboardLayoutSelectionResult> mKeyboardLayoutCache =
             new ArrayMap<>();
+
+    private HashSet<String> mAvailableLayouts = new HashSet<>();
     private final Object mImeInfoLock = new Object();
     @Nullable
     @GuardedBy("mImeInfoLock")
@@ -206,68 +203,51 @@
         }
 
         boolean needToShowNotification = false;
-        if (!useNewSettingsUi()) {
-            synchronized (mDataStore) {
-                String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
-                if (layout == null) {
-                    layout = getDefaultKeyboardLayout(inputDevice);
-                    if (layout != null) {
-                        setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
-                    }
-                }
-                if (layout == null) {
-                    // In old settings show notification always until user manually selects a
-                    // layout in the settings.
+        Set<String> selectedLayouts = new HashSet<>();
+        List<ImeInfo> imeInfoList = getImeInfoListForLayoutMapping();
+        List<KeyboardLayoutSelectionResult> resultList = new ArrayList<>();
+        boolean hasMissingLayout = false;
+        for (ImeInfo imeInfo : imeInfoList) {
+            // Check if the layout has been previously configured
+            KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
+                    keyboardIdentifier, imeInfo);
+            if (result.getLayoutDescriptor() != null) {
+                selectedLayouts.add(result.getLayoutDescriptor());
+            } else {
+                hasMissingLayout = true;
+            }
+            resultList.add(result);
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG,
+                    "Layouts selected for input device: " + keyboardIdentifier
+                            + " -> selectedLayouts: " + selectedLayouts);
+        }
+
+        // If even one layout not configured properly, we need to ask user to configure
+        // the keyboard properly from the Settings.
+        if (hasMissingLayout) {
+            selectedLayouts.clear();
+        }
+
+        config.setConfiguredLayouts(selectedLayouts);
+
+        synchronized (mDataStore) {
+            try {
+                final String key = keyboardIdentifier.toString();
+                if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
+                    // Need to show the notification only if layout selection changed
+                    // from the previous configuration
                     needToShowNotification = true;
                 }
-            }
-        } else {
-            Set<String> selectedLayouts = new HashSet<>();
-            List<ImeInfo> imeInfoList = getImeInfoListForLayoutMapping();
-            List<KeyboardLayoutSelectionResult> resultList = new ArrayList<>();
-            boolean hasMissingLayout = false;
-            for (ImeInfo imeInfo : imeInfoList) {
-                // Check if the layout has been previously configured
-                KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
-                        keyboardIdentifier, imeInfo);
-                boolean noLayoutFound = result.getLayoutDescriptor() == null;
-                if (!noLayoutFound) {
-                    selectedLayouts.add(result.getLayoutDescriptor());
+
+                if (shouldLogConfiguration) {
+                    logKeyboardConfigurationEvent(inputDevice, imeInfoList, resultList,
+                            !mDataStore.hasInputDeviceEntry(key));
                 }
-                resultList.add(result);
-                hasMissingLayout |= noLayoutFound;
-            }
-
-            if (DEBUG) {
-                Slog.d(TAG,
-                        "Layouts selected for input device: " + keyboardIdentifier
-                                + " -> selectedLayouts: " + selectedLayouts);
-            }
-
-            // If even one layout not configured properly, we need to ask user to configure
-            // the keyboard properly from the Settings.
-            if (hasMissingLayout) {
-                selectedLayouts.clear();
-            }
-
-            config.setConfiguredLayouts(selectedLayouts);
-
-            synchronized (mDataStore) {
-                try {
-                    final String key = keyboardIdentifier.toString();
-                    if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
-                        // Need to show the notification only if layout selection changed
-                        // from the previous configuration
-                        needToShowNotification = true;
-                    }
-
-                    if (shouldLogConfiguration) {
-                        logKeyboardConfigurationEvent(inputDevice, imeInfoList, resultList,
-                                !mDataStore.hasInputDeviceEntry(key));
-                    }
-                } finally {
-                    mDataStore.saveIfNeeded();
-                }
+            } finally {
+                mDataStore.saveIfNeeded();
             }
         }
         if (needToShowNotification) {
@@ -275,63 +255,6 @@
         }
     }
 
-    private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
-        final Locale systemLocale = mContext.getResources().getConfiguration().locale;
-        // If our locale doesn't have a language for some reason, then we don't really have a
-        // reasonable default.
-        if (TextUtils.isEmpty(systemLocale.getLanguage())) {
-            return null;
-        }
-        final List<KeyboardLayout> layouts = new ArrayList<>();
-        visitAllKeyboardLayouts((resources, keyboardLayoutResId, layout) -> {
-            // Only select a default when we know the layout is appropriate. For now, this
-            // means it's a custom layout for a specific keyboard.
-            if (layout.getVendorId() != inputDevice.getVendorId()
-                    || layout.getProductId() != inputDevice.getProductId()) {
-                return;
-            }
-            final LocaleList locales = layout.getLocales();
-            for (int localeIndex = 0; localeIndex < locales.size(); ++localeIndex) {
-                final Locale locale = locales.get(localeIndex);
-                if (locale != null && isCompatibleLocale(systemLocale, locale)) {
-                    layouts.add(layout);
-                    break;
-                }
-            }
-        });
-
-        if (layouts.isEmpty()) {
-            return null;
-        }
-
-        // First sort so that ones with higher priority are listed at the top
-        Collections.sort(layouts);
-        // Next we want to try to find an exact match of language, country and variant.
-        for (KeyboardLayout layout : layouts) {
-            final LocaleList locales = layout.getLocales();
-            for (int localeIndex = 0; localeIndex < locales.size(); ++localeIndex) {
-                final Locale locale = locales.get(localeIndex);
-                if (locale != null && locale.getCountry().equals(systemLocale.getCountry())
-                        && locale.getVariant().equals(systemLocale.getVariant())) {
-                    return layout.getDescriptor();
-                }
-            }
-        }
-        // Then try an exact match of language and country
-        for (KeyboardLayout layout : layouts) {
-            final LocaleList locales = layout.getLocales();
-            for (int localeIndex = 0; localeIndex < locales.size(); ++localeIndex) {
-                final Locale locale = locales.get(localeIndex);
-                if (locale != null && locale.getCountry().equals(systemLocale.getCountry())) {
-                    return layout.getDescriptor();
-                }
-            }
-        }
-
-        // Give up and just use the highest priority layout with matching language
-        return layouts.get(0).getDescriptor();
-    }
-
     private static boolean isCompatibleLocale(Locale systemLocale, Locale keyboardLocale) {
         // Different languages are never compatible
         if (!systemLocale.getLanguage().equals(keyboardLocale.getLanguage())) {
@@ -343,11 +266,19 @@
                 || systemLocale.getCountry().equals(keyboardLocale.getCountry());
     }
 
+    @MainThread
     private void updateKeyboardLayouts() {
         // Scan all input devices state for keyboard layouts that have been uninstalled.
-        final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
+        final HashSet<String> availableKeyboardLayouts = new HashSet<>();
         visitAllKeyboardLayouts((resources, keyboardLayoutResId, layout) ->
                 availableKeyboardLayouts.add(layout.getDescriptor()));
+
+        // If available layouts don't change, there is no need to reload layouts.
+        if (mAvailableLayouts.equals(availableKeyboardLayouts)) {
+            return;
+        }
+        mAvailableLayouts = availableKeyboardLayouts;
+
         synchronized (mDataStore) {
             try {
                 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
@@ -374,53 +305,6 @@
     }
 
     @AnyThread
-    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
-            final InputDeviceIdentifier identifier) {
-        if (useNewSettingsUi()) {
-            // Provide all supported keyboard layouts since Ime info is not provided
-            return getKeyboardLayouts();
-        }
-        final String[] enabledLayoutDescriptors =
-                getEnabledKeyboardLayoutsForInputDevice(identifier);
-        final ArrayList<KeyboardLayout> enabledLayouts =
-                new ArrayList<>(enabledLayoutDescriptors.length);
-        final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<>();
-        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
-            boolean mHasSeenDeviceSpecificLayout;
-
-            @Override
-            public void visitKeyboardLayout(Resources resources,
-                    int keyboardLayoutResId, KeyboardLayout layout) {
-                // First check if it's enabled. If the keyboard layout is enabled then we always
-                // want to return it as a possible layout for the device.
-                for (String s : enabledLayoutDescriptors) {
-                    if (s != null && s.equals(layout.getDescriptor())) {
-                        enabledLayouts.add(layout);
-                        return;
-                    }
-                }
-                // Next find any potential layouts that aren't yet enabled for the device. For
-                // devices that have special layouts we assume there's a reason that the generic
-                // layouts don't work for them so we don't want to return them since it's likely
-                // to result in a poor user experience.
-                if (layout.getVendorId() == identifier.getVendorId()
-                        && layout.getProductId() == identifier.getProductId()) {
-                    if (!mHasSeenDeviceSpecificLayout) {
-                        mHasSeenDeviceSpecificLayout = true;
-                        potentialLayouts.clear();
-                    }
-                    potentialLayouts.add(layout);
-                } else if (layout.getVendorId() == -1 && layout.getProductId() == -1
-                        && !mHasSeenDeviceSpecificLayout) {
-                    potentialLayouts.add(layout);
-                }
-            }
-        });
-        return Stream.concat(enabledLayouts.stream(), potentialLayouts.stream()).toArray(
-                KeyboardLayout[]::new);
-    }
-
-    @AnyThread
     @Nullable
     public KeyboardLayout getKeyboardLayout(@NonNull String keyboardLayoutDescriptor) {
         Objects.requireNonNull(keyboardLayoutDescriptor,
@@ -580,195 +464,16 @@
         return LocaleList.forLanguageTags(languageTags.replace('|', ','));
     }
 
-    @AnyThread
-    @Nullable
-    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "getCurrentKeyboardLayoutForInputDevice API not supported");
-            return null;
-        }
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            String layout;
-            // try loading it using the layout descriptor if we have it
-            layout = mDataStore.getCurrentKeyboardLayout(key);
-            if (layout == null && !key.equals(identifier.getDescriptor())) {
-                // if it doesn't exist fall back to the device descriptor
-                layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
-            }
-            if (DEBUG) {
-                Slog.d(TAG, "getCurrentKeyboardLayoutForInputDevice() "
-                        + identifier.toString() + ": " + layout);
-            }
-            return layout;
-        }
-    }
-
-    @AnyThread
-    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "setCurrentKeyboardLayoutForInputDevice API not supported");
-            return;
-        }
-
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            try {
-                if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "setCurrentKeyboardLayoutForInputDevice() " + identifier
-                                + " key: " + key
-                                + " keyboardLayoutDescriptor: " + keyboardLayoutDescriptor);
-                    }
-                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
-                }
-            } finally {
-                mDataStore.saveIfNeeded();
-            }
-        }
-    }
-
-    @AnyThread
-    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "getEnabledKeyboardLayoutsForInputDevice API not supported");
-            return new String[0];
-        }
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            String[] layouts = mDataStore.getKeyboardLayouts(key);
-            if ((layouts == null || layouts.length == 0)
-                    && !key.equals(identifier.getDescriptor())) {
-                layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
-            }
-            return layouts;
-        }
-    }
-
-    @AnyThread
-    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "addKeyboardLayoutForInputDevice API not supported");
-            return;
-        }
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            try {
-                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
-                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
-                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
-                }
-                if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
-                        && !Objects.equals(oldLayout,
-                        mDataStore.getCurrentKeyboardLayout(key))) {
-                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
-                }
-            } finally {
-                mDataStore.saveIfNeeded();
-            }
-        }
-    }
-
-    @AnyThread
-    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "removeKeyboardLayoutForInputDevice API not supported");
-            return;
-        }
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            try {
-                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
-                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
-                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
-                }
-                boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
-                if (!key.equals(identifier.getDescriptor())) {
-                    // We need to remove from both places to ensure it is gone
-                    removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
-                            keyboardLayoutDescriptor);
-                }
-                if (removed && !Objects.equals(oldLayout,
-                        mDataStore.getCurrentKeyboardLayout(key))) {
-                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
-                }
-            } finally {
-                mDataStore.saveIfNeeded();
-            }
-        }
-    }
-
-    @AnyThread
-    public void switchKeyboardLayout(int deviceId, int direction) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "switchKeyboardLayout API not supported");
-            return;
-        }
-        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
-    }
-
-    @MainThread
-    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
-        final InputDevice device = getInputDevice(deviceId);
-        if (device != null) {
-            final boolean changed;
-            final String keyboardLayoutDescriptor;
-
-            String key = new KeyboardIdentifier(device.getIdentifier()).toString();
-            synchronized (mDataStore) {
-                try {
-                    changed = mDataStore.switchKeyboardLayout(key, direction);
-                    keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
-                            key);
-                } finally {
-                    mDataStore.saveIfNeeded();
-                }
-            }
-
-            if (changed) {
-                if (mSwitchedKeyboardLayoutToast != null) {
-                    mSwitchedKeyboardLayoutToast.cancel();
-                    mSwitchedKeyboardLayoutToast = null;
-                }
-                if (keyboardLayoutDescriptor != null) {
-                    KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
-                    if (keyboardLayout != null) {
-                        mSwitchedKeyboardLayoutToast = Toast.makeText(
-                                mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
-                        mSwitchedKeyboardLayoutToast.show();
-                    }
-                }
-
-                reloadKeyboardLayouts();
-            }
-        }
-    }
-
     @Nullable
     @AnyThread
     public String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag,
             String layoutType) {
         String keyboardLayoutDescriptor;
-        if (useNewSettingsUi()) {
-            synchronized (mImeInfoLock) {
-                KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
-                        new KeyboardIdentifier(identifier, languageTag, layoutType),
-                        mCurrentImeInfo);
-                keyboardLayoutDescriptor = result.getLayoutDescriptor();
-            }
-        } else {
-            keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
+        synchronized (mImeInfoLock) {
+            KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
+                    new KeyboardIdentifier(identifier, languageTag, layoutType),
+                    mCurrentImeInfo);
+            keyboardLayoutDescriptor = result.getLayoutDescriptor();
         }
         if (keyboardLayoutDescriptor == null) {
             return null;
@@ -797,10 +502,6 @@
     public KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
             InputDeviceIdentifier identifier, @UserIdInt int userId,
             @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "getKeyboardLayoutForInputDevice() API not supported");
-            return FAILED;
-        }
         InputDevice inputDevice = getInputDevice(identifier);
         if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
             return FAILED;
@@ -820,10 +521,6 @@
             @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
             @Nullable InputMethodSubtype imeSubtype,
             String keyboardLayoutDescriptor) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "setKeyboardLayoutForInputDevice() API not supported");
-            return;
-        }
         Objects.requireNonNull(keyboardLayoutDescriptor,
                 "keyboardLayoutDescriptor must not be null");
         InputDevice inputDevice = getInputDevice(identifier);
@@ -854,10 +551,6 @@
     public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
             @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
             @Nullable InputMethodSubtype imeSubtype) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "getKeyboardLayoutListForInputDevice() API not supported");
-            return new KeyboardLayout[0];
-        }
         InputDevice inputDevice = getInputDevice(identifier);
         if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
             return new KeyboardLayout[0];
@@ -923,10 +616,6 @@
     public void onInputMethodSubtypeChanged(@UserIdInt int userId,
             @Nullable InputMethodSubtypeHandle subtypeHandle,
             @Nullable InputMethodSubtype subtype) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "onInputMethodSubtypeChanged() API not supported");
-            return;
-        }
         if (subtypeHandle == null) {
             if (DEBUG) {
                 Slog.d(TAG, "No InputMethod is running, ignoring change");
@@ -975,6 +664,46 @@
         }
     }
 
+    /**
+     * <ol>
+     *     <li> Layout selection Algorithm:
+     *     <ul>
+     *         <li> Choose product specific layout(KCM file with matching vendor ID and product
+     *         ID) </li>
+     *         <li> If none, then find layout based on PK layout info (based on country code
+     *         provided by the HID descriptor of the keyboard) </li>
+     *         <li> If none, then find layout based on IME layout info associated with the IME
+     *         subtype </li>
+     *         <li> If none, return null (Generic.kcm is the default) </li>
+     *     </ul>
+     *     </li>
+     *     <li> Finding correct layout corresponding to provided layout info:
+     *     <ul>
+     *         <li> Filter all available layouts based on the IME subtype script code </li>
+     *         <li> Derive locale from the provided layout info </li>
+     *         <li> If layoutType i.e. qwerty, azerty, etc. is provided, filter layouts by
+     *         layoutType and try to find matching layout to the derived locale. </li>
+     *         <li> If none found or layoutType not provided, then ignore the layoutType and try
+     *         to find matching layout to the derived locale. </li>
+     *     </ul>
+     *     </li>
+     *     <li> Finding matching layout for the derived locale:
+     *     <ul>
+     *         <li> If language code doesn't match, ignore the layout (We can never match a
+     *         layout if language code isn't matching) </li>
+     *         <li> If country code matches, layout score +1 </li>
+     *         <li> Else if country code of layout is empty, layout score +0.5 (empty country
+     *         code is a semi match with derived locale with country code, this is to prioritize
+     *         empty country code layouts over fully mismatching layouts) </li>
+     *         <li> If variant matches, layout score +1 </li>
+     *         <li> Else if variant of layout is empty, layout score +0.5 (empty variant is a
+     *         semi match with derive locale with country code, this is to prioritize empty
+     *         variant layouts over fully mismatching layouts) </li>
+     *         <li> Choose the layout with the best score. </li>
+     *     </ul>
+     *     </li>
+     * </ol>
+     */
     @NonNull
     private static KeyboardLayoutSelectionResult getDefaultKeyboardLayoutBasedOnImeInfo(
             KeyboardIdentifier keyboardIdentifier, @Nullable ImeInfo imeInfo,
@@ -1064,8 +793,8 @@
     private static String getMatchingLayoutForProvidedLanguageTag(List<KeyboardLayout> layoutList,
             @NonNull String languageTag) {
         Locale locale = Locale.forLanguageTag(languageTag);
-        String layoutMatchingLanguage = null;
-        String layoutMatchingLanguageAndCountry = null;
+        String bestMatchingLayout = null;
+        float bestMatchingLayoutScore = 0;
 
         for (KeyboardLayout layout : layoutList) {
             final LocaleList locales = layout.getLocales();
@@ -1074,23 +803,28 @@
                 if (l == null) {
                     continue;
                 }
-                if (l.getLanguage().equals(locale.getLanguage())) {
-                    if (layoutMatchingLanguage == null) {
-                        layoutMatchingLanguage = layout.getDescriptor();
-                    }
-                    if (l.getCountry().equals(locale.getCountry())) {
-                        if (layoutMatchingLanguageAndCountry == null) {
-                            layoutMatchingLanguageAndCountry = layout.getDescriptor();
-                        }
-                        if (l.getVariant().equals(locale.getVariant())) {
-                            return layout.getDescriptor();
-                        }
-                    }
+                if (!l.getLanguage().equals(locale.getLanguage())) {
+                    // If language mismatches: NEVER choose that layout
+                    continue;
+                }
+                float layoutScore = 1; // If language matches then score +1
+                if (l.getCountry().equals(locale.getCountry())) {
+                    layoutScore += 1; // If country matches then score +1
+                } else if (TextUtils.isEmpty(l.getCountry())) {
+                    layoutScore += 0.5; // Consider empty country as semi-match
+                }
+                if (l.getVariant().equals(locale.getVariant())) {
+                    layoutScore += 1; // If variant matches then score +1
+                } else if (TextUtils.isEmpty(l.getVariant())) {
+                    layoutScore += 0.5; // Consider empty variant as semi-match
+                }
+                if (layoutScore > bestMatchingLayoutScore) {
+                    bestMatchingLayoutScore = layoutScore;
+                    bestMatchingLayout = layout.getDescriptor();
                 }
             }
         }
-        return layoutMatchingLanguageAndCountry != null
-                ? layoutMatchingLanguageAndCountry : layoutMatchingLanguage;
+        return bestMatchingLayout;
     }
 
     private void reloadKeyboardLayouts() {
@@ -1289,9 +1023,6 @@
                     onInputDeviceAdded(deviceId);
                 }
                 return true;
-            case MSG_SWITCH_KEYBOARD_LAYOUT:
-                handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
-                return true;
             case MSG_RELOAD_KEYBOARD_LAYOUTS:
                 reloadKeyboardLayouts();
                 return true;
@@ -1303,10 +1034,6 @@
         }
     }
 
-    private boolean useNewSettingsUi() {
-        return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
-    }
-
     @Nullable
     private InputDevice getInputDevice(int deviceId) {
         InputManager inputManager = mContext.getSystemService(InputManager.class);
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index 31083fd..7859253 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -27,7 +27,6 @@
 import android.view.Surface;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
@@ -42,7 +41,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -74,7 +72,7 @@
             new HashMap<String, InputDeviceState>();
 
     // The interface for methods which should be replaced by the test harness.
-    private Injector mInjector;
+    private final Injector mInjector;
 
     // True if the data has been loaded.
     private boolean mLoaded;
@@ -83,7 +81,7 @@
     private boolean mDirty;
 
     // Storing key remapping
-    private Map<Integer, Integer> mKeyRemapping = new HashMap<>();
+    private final Map<Integer, Integer> mKeyRemapping = new HashMap<>();
 
     public PersistentDataStore() {
         this(new Injector());
@@ -130,22 +128,6 @@
     }
 
     @Nullable
-    public String getCurrentKeyboardLayout(String inputDeviceDescriptor) {
-        InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
-        return state != null ? state.getCurrentKeyboardLayout() : null;
-    }
-
-    public boolean setCurrentKeyboardLayout(String inputDeviceDescriptor,
-            String keyboardLayoutDescriptor) {
-        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
-        if (state.setCurrentKeyboardLayout(keyboardLayoutDescriptor)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
-    @Nullable
     public String getKeyboardLayout(String inputDeviceDescriptor, String key) {
         InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
         return state != null ? state.getKeyboardLayout(key) : null;
@@ -171,43 +153,6 @@
         return false;
     }
 
-    public String[] getKeyboardLayouts(String inputDeviceDescriptor) {
-        InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
-        if (state == null) {
-            return (String[])ArrayUtils.emptyArray(String.class);
-        }
-        return state.getKeyboardLayouts();
-    }
-
-    public boolean addKeyboardLayout(String inputDeviceDescriptor,
-            String keyboardLayoutDescriptor) {
-        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
-        if (state.addKeyboardLayout(keyboardLayoutDescriptor)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean removeKeyboardLayout(String inputDeviceDescriptor,
-            String keyboardLayoutDescriptor) {
-        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
-        if (state.removeKeyboardLayout(keyboardLayoutDescriptor)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean switchKeyboardLayout(String inputDeviceDescriptor, int direction) {
-        InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
-        if (state != null && state.switchKeyboardLayout(direction)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
     public boolean setKeyboardBacklightBrightness(String inputDeviceDescriptor, int lightId,
             int brightness) {
         InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
@@ -417,9 +362,6 @@
                 "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };
 
         private final TouchCalibration[] mTouchCalibration = new TouchCalibration[4];
-        @Nullable
-        private String mCurrentKeyboardLayout;
-        private final ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
         private final SparseIntArray mKeyboardBacklightBrightnessMap = new SparseIntArray();
 
         private final Map<String, String> mKeyboardLayoutMap = new ArrayMap<>();
@@ -465,49 +407,6 @@
             return true;
         }
 
-        @Nullable
-        public String getCurrentKeyboardLayout() {
-            return mCurrentKeyboardLayout;
-        }
-
-        public boolean setCurrentKeyboardLayout(String keyboardLayout) {
-            if (Objects.equals(mCurrentKeyboardLayout, keyboardLayout)) {
-                return false;
-            }
-            addKeyboardLayout(keyboardLayout);
-            mCurrentKeyboardLayout = keyboardLayout;
-            return true;
-        }
-
-        public String[] getKeyboardLayouts() {
-            if (mKeyboardLayouts.isEmpty()) {
-                return (String[])ArrayUtils.emptyArray(String.class);
-            }
-            return mKeyboardLayouts.toArray(new String[mKeyboardLayouts.size()]);
-        }
-
-        public boolean addKeyboardLayout(String keyboardLayout) {
-            int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout);
-            if (index >= 0) {
-                return false;
-            }
-            mKeyboardLayouts.add(-index - 1, keyboardLayout);
-            if (mCurrentKeyboardLayout == null) {
-                mCurrentKeyboardLayout = keyboardLayout;
-            }
-            return true;
-        }
-
-        public boolean removeKeyboardLayout(String keyboardLayout) {
-            int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout);
-            if (index < 0) {
-                return false;
-            }
-            mKeyboardLayouts.remove(index);
-            updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, index);
-            return true;
-        }
-
         public boolean setKeyboardBacklightBrightness(int lightId, int brightness) {
             if (mKeyboardBacklightBrightnessMap.get(lightId, INVALID_VALUE) == brightness) {
                 return false;
@@ -521,48 +420,8 @@
             return brightness == INVALID_VALUE ? OptionalInt.empty() : OptionalInt.of(brightness);
         }
 
-        private void updateCurrentKeyboardLayoutIfRemoved(
-                String removedKeyboardLayout, int removedIndex) {
-            if (Objects.equals(mCurrentKeyboardLayout, removedKeyboardLayout)) {
-                if (!mKeyboardLayouts.isEmpty()) {
-                    int index = removedIndex;
-                    if (index == mKeyboardLayouts.size()) {
-                        index = 0;
-                    }
-                    mCurrentKeyboardLayout = mKeyboardLayouts.get(index);
-                } else {
-                    mCurrentKeyboardLayout = null;
-                }
-            }
-        }
-
-        public boolean switchKeyboardLayout(int direction) {
-            final int size = mKeyboardLayouts.size();
-            if (size < 2) {
-                return false;
-            }
-            int index = Collections.binarySearch(mKeyboardLayouts, mCurrentKeyboardLayout);
-            assert index >= 0;
-            if (direction > 0) {
-                index = (index + 1) % size;
-            } else {
-                index = (index + size - 1) % size;
-            }
-            mCurrentKeyboardLayout = mKeyboardLayouts.get(index);
-            return true;
-        }
-
         public boolean removeUninstalledKeyboardLayouts(Set<String> availableKeyboardLayouts) {
             boolean changed = false;
-            for (int i = mKeyboardLayouts.size(); i-- > 0; ) {
-                String keyboardLayout = mKeyboardLayouts.get(i);
-                if (!availableKeyboardLayouts.contains(keyboardLayout)) {
-                    Slog.i(TAG, "Removing uninstalled keyboard layout " + keyboardLayout);
-                    mKeyboardLayouts.remove(i);
-                    updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, i);
-                    changed = true;
-                }
-            }
             List<String> removedEntries = new ArrayList<>();
             for (String key : mKeyboardLayoutMap.keySet()) {
                 if (!availableKeyboardLayouts.contains(mKeyboardLayoutMap.get(key))) {
@@ -582,27 +441,7 @@
                 throws IOException, XmlPullParserException {
             final int outerDepth = parser.getDepth();
             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
-                if (parser.getName().equals("keyboard-layout")) {
-                    String descriptor = parser.getAttributeValue(null, "descriptor");
-                    if (descriptor == null) {
-                        throw new XmlPullParserException(
-                                "Missing descriptor attribute on keyboard-layout.");
-                    }
-                    String current = parser.getAttributeValue(null, "current");
-                    if (mKeyboardLayouts.contains(descriptor)) {
-                        throw new XmlPullParserException(
-                                "Found duplicate keyboard layout.");
-                    }
-
-                    mKeyboardLayouts.add(descriptor);
-                    if (current != null && current.equals("true")) {
-                        if (mCurrentKeyboardLayout != null) {
-                            throw new XmlPullParserException(
-                                    "Found multiple current keyboard layouts.");
-                        }
-                        mCurrentKeyboardLayout = descriptor;
-                    }
-                } else if (parser.getName().equals("keyed-keyboard-layout")) {
+                if (parser.getName().equals("keyed-keyboard-layout")) {
                     String key = parser.getAttributeValue(null, "key");
                     if (key == null) {
                         throw new XmlPullParserException(
@@ -676,27 +515,9 @@
                     }
                 }
             }
-
-            // Maintain invariant that layouts are sorted.
-            Collections.sort(mKeyboardLayouts);
-
-            // Maintain invariant that there is always a current keyboard layout unless
-            // there are none installed.
-            if (mCurrentKeyboardLayout == null && !mKeyboardLayouts.isEmpty()) {
-                mCurrentKeyboardLayout = mKeyboardLayouts.get(0);
-            }
         }
 
         public void saveToXml(TypedXmlSerializer serializer) throws IOException {
-            for (String layout : mKeyboardLayouts) {
-                serializer.startTag(null, "keyboard-layout");
-                serializer.attribute(null, "descriptor", layout);
-                if (layout.equals(mCurrentKeyboardLayout)) {
-                    serializer.attributeBoolean(null, "current", true);
-                }
-                serializer.endTag(null, "keyboard-layout");
-            }
-
             for (String key : mKeyboardLayoutMap.keySet()) {
                 serializer.startTag(null, "keyed-keyboard-layout");
                 serializer.attribute(null, "key", key);
diff --git a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java
index c7b60da..dd6433d 100644
--- a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java
+++ b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java
@@ -19,11 +19,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.content.Context;
 import android.content.pm.UserInfo;
 import android.os.Handler;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.DirectBootAwareness;
 import com.android.server.LocalServices;
 import com.android.server.pm.UserManagerInternal;
 
@@ -67,7 +69,7 @@
         AdditionalSubtypeUtils.save(map, inputMethodMap, userId);
     }
 
-    static void initialize(@NonNull Handler handler) {
+    static void initialize(@NonNull Handler handler, @NonNull Context context) {
         final UserManagerInternal userManagerInternal =
                 LocalServices.getService(UserManagerInternal.class);
         handler.post(() -> {
@@ -79,8 +81,16 @@
                             handler.post(() -> {
                                 synchronized (ImfLock.class) {
                                     if (!sPerUserMap.contains(userId)) {
-                                        sPerUserMap.put(userId,
-                                                AdditionalSubtypeUtils.load(userId));
+                                        final AdditionalSubtypeMap additionalSubtypeMap =
+                                                AdditionalSubtypeUtils.load(userId);
+                                        sPerUserMap.put(userId, additionalSubtypeMap);
+                                        final InputMethodSettings settings =
+                                                InputMethodManagerService
+                                                        .queryInputMethodServicesInternal(context,
+                                                                userId,
+                                                                additionalSubtypeMap,
+                                                                DirectBootAwareness.AUTO);
+                                        InputMethodSettingsRepository.put(userId, settings);
                                     }
                                 }
                             });
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
index dbbbed3..d132449 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
@@ -85,6 +85,17 @@
         mIsIntercepting = true;
     }
 
+    void setNotTouchable(boolean notTouchable) {
+        if (notTouchable) {
+            mWindowHandle.inputConfig |= InputConfig.NOT_TOUCHABLE;
+        } else {
+            mWindowHandle.inputConfig &=  ~InputConfig.NOT_TOUCHABLE;
+        }
+        new SurfaceControl.Transaction()
+                .setInputWindowInfo(mInputSurface, mWindowHandle)
+                .apply();
+    }
+
     boolean isIntercepting() {
         return mIsIntercepting;
     }
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
index dbdac41..7956e03 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
@@ -159,6 +159,13 @@
         return OptionalInt.of(mCurrentRequestId);
     }
 
+    void setNotTouchable(boolean notTouchable) {
+        if (!getCurrentRequestId().isPresent()) {
+            return;
+        }
+        mHandwritingSurface.setNotTouchable(notTouchable);
+    }
+
     boolean isStylusGestureOngoing() {
         if (mRecordingGestureAfterStylusUp && !mHandwritingBuffer.isEmpty()) {
             // If it is less than AFTER_STYLUS_UP_ALLOW_PERIOD_MS after the stylus up event, return
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
new file mode 100644
index 0000000..7890fe0
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.Manifest;
+import android.annotation.BinderThread;
+import android.annotation.EnforcePermission;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ImeTracker;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.window.ImeOnBackInvokedDispatcher;
+
+import com.android.internal.inputmethod.DirectBootAwareness;
+import com.android.internal.inputmethod.IBooleanListener;
+import com.android.internal.inputmethod.IConnectionlessHandwritingCallback;
+import com.android.internal.inputmethod.IImeTracker;
+import com.android.internal.inputmethod.IInputMethodClient;
+import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
+import com.android.internal.inputmethod.IRemoteInputConnection;
+import com.android.internal.inputmethod.InputBindResult;
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.inputmethod.StartInputFlags;
+import com.android.internal.inputmethod.StartInputReason;
+import com.android.internal.view.IInputMethodManager;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+
+/**
+ * An actual implementation class of {@link IInputMethodManager.Stub} to allow other classes to
+ * focus on handling IPC callbacks.
+ */
+final class IInputMethodManagerImpl extends IInputMethodManager.Stub {
+
+    /**
+     * Tells that the given permission is already verified before the annotated method gets called.
+     */
+    @Retention(SOURCE)
+    @Target({METHOD})
+    @interface PermissionVerified {
+        String value() default "";
+    }
+
+    @BinderThread
+    interface Callback {
+        void addClient(IInputMethodClient client, IRemoteInputConnection inputConnection,
+                int selfReportedDisplayId);
+
+        InputMethodInfo getCurrentInputMethodInfoAsUser(@UserIdInt int userId);
+
+        List<InputMethodInfo> getInputMethodList(@UserIdInt int userId,
+                @DirectBootAwareness int directBootAwareness);
+
+        List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId);
+
+        List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
+                boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId);
+
+        InputMethodSubtype getLastInputMethodSubtype(@UserIdInt int userId);
+
+        boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
+                @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
+                @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
+                @SoftInputShowHideReason int reason);
+
+        boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
+                @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
+                ResultReceiver resultReceiver, @SoftInputShowHideReason int reason);
+
+        @PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
+        void hideSoftInputFromServerForTest();
+
+        void startInputOrWindowGainedFocusAsync(
+                @StartInputReason int startInputReason, IInputMethodClient client,
+                IBinder windowToken, @StartInputFlags int startInputFlags,
+                @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, int windowFlags,
+                @Nullable EditorInfo editorInfo, IRemoteInputConnection inputConnection,
+                IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
+                int unverifiedTargetSdkVersion, @UserIdInt int userId,
+                @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq);
+
+        InputBindResult startInputOrWindowGainedFocus(
+                @StartInputReason int startInputReason, IInputMethodClient client,
+                IBinder windowToken, @StartInputFlags int startInputFlags,
+                @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, int windowFlags,
+                @Nullable EditorInfo editorInfo, IRemoteInputConnection inputConnection,
+                IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
+                int unverifiedTargetSdkVersion, @UserIdInt int userId,
+                @NonNull ImeOnBackInvokedDispatcher imeDispatcher);
+
+        void showInputMethodPickerFromClient(IInputMethodClient client, int auxiliarySubtypeMode);
+
+        @PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS)
+        void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId);
+
+        @PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
+        boolean isInputMethodPickerShownForTest();
+
+        InputMethodSubtype getCurrentInputMethodSubtype(@UserIdInt int userId);
+
+        void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes,
+                @UserIdInt int userId);
+
+        void setExplicitlyEnabledInputMethodSubtypes(String imeId,
+                @NonNull int[] subtypeHashCodes, @UserIdInt int userId);
+
+        int getInputMethodWindowVisibleHeight(IInputMethodClient client);
+
+        void reportPerceptibleAsync(IBinder windowToken, boolean perceptible);
+
+        @PermissionVerified(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+        void removeImeSurface();
+
+        void removeImeSurfaceFromWindowAsync(IBinder windowToken);
+
+        void startProtoDump(byte[] bytes, int i, String s);
+
+        boolean isImeTraceEnabled();
+
+        @PermissionVerified(Manifest.permission.CONTROL_UI_TRACING)
+        void startImeTrace();
+
+        @PermissionVerified(Manifest.permission.CONTROL_UI_TRACING)
+        void stopImeTrace();
+
+        void startStylusHandwriting(IInputMethodClient client);
+
+        void startConnectionlessStylusHandwriting(IInputMethodClient client, @UserIdInt int userId,
+                @Nullable CursorAnchorInfo cursorAnchorInfo, @Nullable String delegatePackageName,
+                @Nullable String delegatorPackageName,
+                @NonNull IConnectionlessHandwritingCallback callback);
+
+        boolean acceptStylusHandwritingDelegation(@NonNull IInputMethodClient client,
+                @UserIdInt int userId, @NonNull String delegatePackageName,
+                @NonNull String delegatorPackageName,
+                @InputMethodManager.HandwritingDelegateFlags int flags);
+
+        void acceptStylusHandwritingDelegationAsync(@NonNull IInputMethodClient client,
+                @UserIdInt int userId, @NonNull String delegatePackageName,
+                @NonNull String delegatorPackageName,
+                @InputMethodManager.HandwritingDelegateFlags int flags, IBooleanListener callback);
+
+        void prepareStylusHandwritingDelegation(@NonNull IInputMethodClient client,
+                @UserIdInt int userId, @NonNull String delegatePackageName,
+                @NonNull String delegatorPackageName);
+
+        boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId, boolean connectionless);
+
+        @PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
+        void addVirtualStylusIdForTestSession(IInputMethodClient client);
+
+        @PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
+        void setStylusWindowIdleTimeoutForTest(IInputMethodClient client, long timeout);
+
+        IImeTracker getImeTrackerService();
+
+        void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
+                @Nullable FileDescriptor err, @NonNull String[] args,
+                @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver,
+                @NonNull Binder self);
+
+        void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args);
+    }
+
+    @NonNull
+    private final Callback mCallback;
+
+    private IInputMethodManagerImpl(@NonNull Callback callback) {
+        mCallback = callback;
+    }
+
+    static IInputMethodManagerImpl create(@NonNull Callback callback) {
+        return new IInputMethodManagerImpl(callback);
+    }
+
+    @Override
+    public void addClient(IInputMethodClient client, IRemoteInputConnection inputmethod,
+            int untrustedDisplayId) {
+        mCallback.addClient(client, inputmethod, untrustedDisplayId);
+    }
+
+    @Override
+    public InputMethodInfo getCurrentInputMethodInfoAsUser(@UserIdInt int userId) {
+        return mCallback.getCurrentInputMethodInfoAsUser(userId);
+    }
+
+    @Override
+    public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId,
+            int directBootAwareness) {
+        return mCallback.getInputMethodList(userId, directBootAwareness);
+    }
+
+    @Override
+    public List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) {
+        return mCallback.getEnabledInputMethodList(userId);
+    }
+
+    @Override
+    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
+            boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) {
+        return mCallback.getEnabledInputMethodSubtypeList(imiId, allowsImplicitlyEnabledSubtypes,
+                userId);
+    }
+
+    @Override
+    public InputMethodSubtype getLastInputMethodSubtype(@UserIdInt int userId) {
+        return mCallback.getLastInputMethodSubtype(userId);
+    }
+
+    @Override
+    public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
+            @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
+            @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
+            @SoftInputShowHideReason int reason) {
+        return mCallback.showSoftInput(client, windowToken, statsToken, flags, lastClickToolType,
+                resultReceiver, reason);
+    }
+
+    @Override
+    public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
+            @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
+            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+        return mCallback.hideSoftInput(client, windowToken, statsToken, flags, resultReceiver,
+                reason);
+    }
+
+    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @Override
+    public void hideSoftInputFromServerForTest() {
+        super.hideSoftInputFromServerForTest_enforcePermission();
+
+        mCallback.hideSoftInputFromServerForTest();
+    }
+
+    @Override
+    public InputBindResult startInputOrWindowGainedFocus(
+            @StartInputReason int startInputReason, IInputMethodClient client, IBinder windowToken,
+            @StartInputFlags int startInputFlags,
+            @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode,
+            int windowFlags, @Nullable EditorInfo editorInfo,
+            IRemoteInputConnection inputConnection,
+            IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
+            int unverifiedTargetSdkVersion, @UserIdInt int userId,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
+        return mCallback.startInputOrWindowGainedFocus(
+                startInputReason, client, windowToken, startInputFlags, softInputMode,
+                windowFlags, editorInfo, inputConnection, remoteAccessibilityInputConnection,
+                unverifiedTargetSdkVersion, userId, imeDispatcher);
+    }
+
+    @Override
+    public void startInputOrWindowGainedFocusAsync(@StartInputReason int startInputReason,
+            IInputMethodClient client, IBinder windowToken,
+            @StartInputFlags int startInputFlags,
+            @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode,
+            int windowFlags, @Nullable EditorInfo editorInfo,
+            IRemoteInputConnection inputConnection,
+            IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
+            int unverifiedTargetSdkVersion, @UserIdInt int userId,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq) {
+        mCallback.startInputOrWindowGainedFocusAsync(
+                startInputReason, client, windowToken, startInputFlags, softInputMode,
+                windowFlags, editorInfo, inputConnection, remoteAccessibilityInputConnection,
+                unverifiedTargetSdkVersion, userId, imeDispatcher, startInputSeq);
+    }
+
+    @Override
+    public void showInputMethodPickerFromClient(IInputMethodClient client,
+            int auxiliarySubtypeMode) {
+        mCallback.showInputMethodPickerFromClient(client, auxiliarySubtypeMode);
+    }
+
+    @EnforcePermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    @Override
+    public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) {
+        super.showInputMethodPickerFromSystem_enforcePermission();
+
+        mCallback.showInputMethodPickerFromSystem(auxiliarySubtypeMode, displayId);
+
+    }
+
+    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @Override
+    public boolean isInputMethodPickerShownForTest() {
+        super.isInputMethodPickerShownForTest_enforcePermission();
+
+        return mCallback.isInputMethodPickerShownForTest();
+    }
+
+    @Override
+    public InputMethodSubtype getCurrentInputMethodSubtype(@UserIdInt int userId) {
+        return mCallback.getCurrentInputMethodSubtype(userId);
+    }
+
+    @Override
+    public void setAdditionalInputMethodSubtypes(String id, InputMethodSubtype[] subtypes,
+            @UserIdInt int userId) {
+        mCallback.setAdditionalInputMethodSubtypes(id, subtypes, userId);
+    }
+
+    @Override
+    public void setExplicitlyEnabledInputMethodSubtypes(String imeId, int[] subtypeHashCodes,
+            @UserIdInt int userId) {
+        mCallback.setExplicitlyEnabledInputMethodSubtypes(imeId, subtypeHashCodes, userId);
+    }
+
+    @Override
+    public int getInputMethodWindowVisibleHeight(IInputMethodClient client) {
+        return mCallback.getInputMethodWindowVisibleHeight(client);
+    }
+
+    @Override
+    public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
+        mCallback.reportPerceptibleAsync(windowToken, perceptible);
+    }
+
+    @EnforcePermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+    @Override
+    public void removeImeSurface() {
+        super.removeImeSurface_enforcePermission();
+
+        mCallback.removeImeSurface();
+    }
+
+    @Override
+    public void removeImeSurfaceFromWindowAsync(IBinder windowToken) {
+        mCallback.removeImeSurfaceFromWindowAsync(windowToken);
+    }
+
+    @Override
+    public void startProtoDump(byte[] protoDump, int source, String where) {
+        mCallback.startProtoDump(protoDump, source, where);
+    }
+
+    @Override
+    public boolean isImeTraceEnabled() {
+        return mCallback.isImeTraceEnabled();
+    }
+
+    @EnforcePermission(Manifest.permission.CONTROL_UI_TRACING)
+    @Override
+    public void startImeTrace() {
+        super.startImeTrace_enforcePermission();
+
+        mCallback.startImeTrace();
+    }
+
+    @EnforcePermission(Manifest.permission.CONTROL_UI_TRACING)
+    @Override
+    public void stopImeTrace() {
+        super.stopImeTrace_enforcePermission();
+
+        mCallback.stopImeTrace();
+    }
+
+    @Override
+    public void startStylusHandwriting(IInputMethodClient client) {
+        mCallback.startStylusHandwriting(client);
+    }
+
+    @Override
+    public void startConnectionlessStylusHandwriting(IInputMethodClient client,
+            @UserIdInt int userId, CursorAnchorInfo cursorAnchorInfo,
+            String delegatePackageName, String delegatorPackageName,
+            IConnectionlessHandwritingCallback callback) {
+        mCallback.startConnectionlessStylusHandwriting(client, userId, cursorAnchorInfo,
+                delegatePackageName, delegatorPackageName, callback);
+    }
+
+    @Override
+    public void prepareStylusHandwritingDelegation(IInputMethodClient client, @UserIdInt int userId,
+            String delegatePackageName, String delegatorPackageName) {
+        mCallback.prepareStylusHandwritingDelegation(client, userId,
+                delegatePackageName, delegatorPackageName);
+    }
+
+    @Override
+    public boolean acceptStylusHandwritingDelegation(IInputMethodClient client,
+            @UserIdInt int userId, String delegatePackageName, String delegatorPackageName,
+            @InputMethodManager.HandwritingDelegateFlags int flags) {
+        return mCallback.acceptStylusHandwritingDelegation(client, userId,
+                delegatePackageName, delegatorPackageName, flags);
+    }
+
+    @Override
+    public void acceptStylusHandwritingDelegationAsync(IInputMethodClient client,
+            @UserIdInt int userId, String delegatePackageName, String delegatorPackageName,
+            @InputMethodManager.HandwritingDelegateFlags int flags,
+            IBooleanListener callback) {
+        mCallback.acceptStylusHandwritingDelegationAsync(client, userId,
+                delegatePackageName, delegatorPackageName, flags, callback);
+    }
+
+    @Override
+    public boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId,
+            boolean connectionless) {
+        return mCallback.isStylusHandwritingAvailableAsUser(userId, connectionless);
+    }
+
+    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @Override
+    public void addVirtualStylusIdForTestSession(IInputMethodClient client) {
+        super.addVirtualStylusIdForTestSession_enforcePermission();
+
+        mCallback.addVirtualStylusIdForTestSession(client);
+    }
+
+    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @Override
+    public void setStylusWindowIdleTimeoutForTest(IInputMethodClient client, long timeout) {
+        super.setStylusWindowIdleTimeoutForTest_enforcePermission();
+
+        mCallback.setStylusWindowIdleTimeoutForTest(client, timeout);
+    }
+
+    @Override
+    public IImeTracker getImeTrackerService() {
+        return mCallback.getImeTrackerService();
+    }
+
+    @Override
+    public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
+            @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback,
+            @NonNull ResultReceiver resultReceiver) {
+        mCallback.onShellCommand(in, out, err, args, callback, resultReceiver, this);
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mCallback.dump(fd, pw, args);
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index a100fe0..3e23f97 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -16,10 +16,12 @@
 
 package com.android.server.inputmethod;
 
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -410,7 +412,7 @@
             Slog.v(TAG,
                     "Removing window token: " + mCurToken + " for display: " + curTokenDisplayId);
         }
-        mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */,
+        mWindowManagerInternal.removeWindowToken(mCurToken, true /* removeWindows */,
                 false /* animateExit */, curTokenDisplayId);
         mCurToken = null;
     }
@@ -452,9 +454,12 @@
         intent.setComponent(component);
         intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                 com.android.internal.R.string.input_method_binding_label);
+        var options = ActivityOptions.makeBasic()
+                .setPendingIntentCreatorBackgroundActivityStartMode(
+                        MODE_BACKGROUND_ACTIVITY_START_DENIED);
         intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                 mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS),
-                PendingIntent.FLAG_IMMUTABLE));
+                PendingIntent.FLAG_IMMUTABLE, options.toBundle()));
         return intent;
     }
 
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index c6a48ec..7bd47f5 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -61,7 +61,6 @@
 import android.annotation.BinderThread;
 import android.annotation.DrawableRes;
 import android.annotation.DurationMillisLong;
-import android.annotation.EnforcePermission;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -172,7 +171,6 @@
 import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
-import com.android.internal.view.IInputMethodManager;
 import com.android.server.AccessibilityManagerInternal;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
@@ -211,8 +209,9 @@
 /**
  * This class provides a system service that manages input methods.
  */
-public final class InputMethodManagerService extends IInputMethodManager.Stub
-        implements Handler.Callback {
+public final class InputMethodManagerService implements IInputMethodManagerImpl.Callback,
+        ZeroJankProxy.Callback, Handler.Callback {
+
     // Virtual device id for test.
     private static final Integer VIRTUAL_STYLUS_ID_FOR_TEST = 999999;
     static final boolean DEBUG = false;
@@ -284,9 +283,16 @@
     final Context mContext;
     final Resources mRes;
     private final Handler mHandler;
-    @NonNull
+
     @MultiUserUnawareField
-    private InputMethodSettings mSettings;
+    @UserIdInt
+    @GuardedBy("ImfLock.class")
+    private int mCurrentUserId;
+
+    /** Holds all user related data */
+    @GuardedBy("ImfLock.class")
+    private UserDataRepository mUserDataRepository;
+
     @MultiUserUnawareField
     final SettingsObserver mSettingsObserver;
     final WindowManagerInternal mWindowManagerInternal;
@@ -491,7 +497,7 @@
     @GuardedBy("ImfLock.class")
     @Nullable
     InputMethodInfo queryInputMethodForCurrentUserLocked(@NonNull String imeId) {
-        return mSettings.getMethodMap().get(imeId);
+        return InputMethodSettingsRepository.get(mCurrentUserId).getMethodMap().get(imeId);
     }
 
     /**
@@ -812,7 +818,8 @@
                     InputMethodManager.invalidateLocalStylusHandwritingAvailabilityCaches();
                 } else {
                     boolean enabledChanged = false;
-                    String newEnabled = mSettings.getEnabledInputMethodsStr();
+                    String newEnabled = InputMethodSettingsRepository.get(mCurrentUserId)
+                            .getEnabledInputMethodsStr();
                     if (!mLastEnabled.equals(newEnabled)) {
                         mLastEnabled = newEnabled;
                         enabledChanged = true;
@@ -844,9 +851,11 @@
                 // sender userId can be a real user ID or USER_ALL.
                 final int senderUserId = pendingResult.getSendingUserId();
                 if (senderUserId != UserHandle.USER_ALL) {
-                    if (senderUserId != mSettings.getUserId()) {
-                        // A background user is trying to hide the dialog. Ignore.
-                        return;
+                    synchronized (ImfLock.class) {
+                        if (senderUserId != mCurrentUserId) {
+                            // A background user is trying to hide the dialog. Ignore.
+                            return;
+                        }
                     }
                 }
                 mMenuController.hideInputMethodMenu();
@@ -870,9 +879,14 @@
             if (!mSystemReady) {
                 return;
             }
-            mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(),
-                    AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
-                    DirectBootAwareness.AUTO);
+            for (int userId : mUserManagerInternal.getUserIds()) {
+                final InputMethodSettings settings = queryInputMethodServicesInternal(
+                                mContext,
+                                userId,
+                                AdditionalSubtypeMapRepository.get(userId),
+                                DirectBootAwareness.AUTO);
+                InputMethodSettingsRepository.put(userId, settings);
+            }
             postInputMethodSettingUpdatedLocked(true /* resetDefaultEnabledIme */);
             // If the locale is changed, needs to reset the default ime
             resetDefaultImeLocked(mContext);
@@ -933,7 +947,7 @@
         @GuardedBy("ImfLock.class")
         private boolean isChangingPackagesOfCurrentUserLocked() {
             final int userId = getChangingUserId();
-            final boolean retval = userId == mSettings.getUserId();
+            final boolean retval = userId == mCurrentUserId;
             if (DEBUG) {
                 if (!retval) {
                     Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
@@ -948,8 +962,10 @@
                 if (!isChangingPackagesOfCurrentUserLocked()) {
                     return false;
                 }
-                String curInputMethodId = mSettings.getSelectedInputMethod();
-                final List<InputMethodInfo> methodList = mSettings.getMethodList();
+                final InputMethodSettings settings =
+                        InputMethodSettingsRepository.get(mCurrentUserId);
+                String curInputMethodId = settings.getSelectedInputMethod();
+                final List<InputMethodInfo> methodList = settings.getMethodList();
                 final int numImes = methodList.size();
                 if (curInputMethodId != null) {
                     for (int i = 0; i < numImes; i++) {
@@ -1066,16 +1082,10 @@
         private void onFinishPackageChangesInternal() {
             synchronized (ImfLock.class) {
                 final int userId = getChangingUserId();
-                final boolean isCurrentUser = (userId == mSettings.getUserId());
+                final boolean isCurrentUser = (userId == mCurrentUserId);
                 final AdditionalSubtypeMap additionalSubtypeMap =
                         AdditionalSubtypeMapRepository.get(userId);
-                final InputMethodSettings settings;
-                if (isCurrentUser) {
-                    settings = mSettings;
-                } else {
-                    settings = queryInputMethodServicesInternal(mContext, userId,
-                            additionalSubtypeMap, DirectBootAwareness.AUTO);
-                }
+                final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
 
                 InputMethodInfo curIm = null;
                 String curInputMethodId = settings.getSelectedInputMethod();
@@ -1093,7 +1103,7 @@
                         imesToClearAdditionalSubtypes.add(imiId);
                     }
                     int change = isPackageDisappearing(imi.getPackageName());
-                    if (change == PACKAGE_TEMPORARY_CHANGE || change == PACKAGE_PERMANENT_CHANGE) {
+                    if (change == PACKAGE_PERMANENT_CHANGE) {
                         Slog.i(TAG, "Input method uninstalled, disabling: " + imi.getComponent());
                         if (isCurrentUser) {
                             setInputMethodEnabledLocked(imi.getId(), false);
@@ -1119,16 +1129,17 @@
                     AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap,
                             settings.getMethodMap());
                 }
+                if (isCurrentUser
+                        && !(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) {
+                    return;
+                }
 
+                final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
+                        userId, newAdditionalSubtypeMap, DirectBootAwareness.AUTO);
+                InputMethodSettingsRepository.put(userId, newSettings);
                 if (!isCurrentUser) {
                     return;
                 }
-
-                if (!(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) {
-                    return;
-                }
-                mSettings = queryInputMethodServicesInternal(mContext, userId,
-                        newAdditionalSubtypeMap, DirectBootAwareness.AUTO);
                 postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
 
                 boolean changed = false;
@@ -1236,21 +1247,14 @@
         @Override
         public void onStart() {
             mService.publishLocalService();
-            IInputMethodManager.Stub service;
+            IInputMethodManagerImpl.Callback service;
             if (Flags.useZeroJankProxy()) {
-                service =
-                        new ZeroJankProxy(
-                                mService.mHandler::post,
-                                mService,
-                                () -> {
-                                    synchronized (ImfLock.class) {
-                                        return mService.isInputShown();
-                                    }
-                                });
+                service = new ZeroJankProxy(mService.mHandler::post, mService);
             } else {
                 service = mService;
             }
-            publishBinderService(Context.INPUT_METHOD_SERVICE, service, false /*allowIsolated*/,
+            publishBinderService(Context.INPUT_METHOD_SERVICE,
+                    IInputMethodManagerImpl.create(service), false /*allowIsolated*/,
                     DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
         }
 
@@ -1284,26 +1288,29 @@
         public void onUserStarting(TargetUser user) {
             // Called on ActivityManager thread.
             SecureSettingsWrapper.onUserStarting(user.getUserIdentifier());
+            synchronized (ImfLock.class) {
+                mService.mUserDataRepository.getOrCreate(user.getUserIdentifier());
+            }
         }
+
     }
 
     void onUnlockUser(@UserIdInt int userId) {
         synchronized (ImfLock.class) {
-            final int currentUserId = mSettings.getUserId();
             if (DEBUG) {
-                Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + currentUserId);
-            }
-            if (userId != currentUserId) {
-                return;
+                Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + mCurrentUserId);
             }
             if (!mSystemReady) {
                 return;
             }
-            mSettings = queryInputMethodServicesInternal(mContext, userId,
-                    AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO);
-            // We need to rebuild IMEs.
-            postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
-            updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
+            final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
+                    userId, AdditionalSubtypeMapRepository.get(userId), DirectBootAwareness.AUTO);
+            InputMethodSettingsRepository.put(userId, newSettings);
+            if (mCurrentUserId == userId) {
+                // We need to rebuild IMEs.
+                postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
+                updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
+            }
         }
     }
 
@@ -1336,83 +1343,89 @@
             Context context,
             @Nullable ServiceThread serviceThreadForTesting,
             @Nullable InputMethodBindingController bindingControllerForTesting) {
-        mContext = context;
-        mRes = context.getResources();
-        SecureSettingsWrapper.onStart(mContext);
-        // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading
-        // additional subtypes in switchUserOnHandlerLocked().
-        final ServiceThread thread =
-                serviceThreadForTesting != null
-                        ? serviceThreadForTesting
-                        : new ServiceThread(
-                                HANDLER_THREAD_NAME,
-                                Process.THREAD_PRIORITY_FOREGROUND,
-                                true /* allowIo */);
-        thread.start();
-        mHandler = Handler.createAsync(thread.getLooper(), this);
-        SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mHandler);
-        mImeTrackerService = new ImeTrackerService(serviceThreadForTesting != null
-                ? serviceThreadForTesting.getLooper() : Looper.getMainLooper());
-        // Note: SettingsObserver doesn't register observers in its constructor.
-        mSettingsObserver = new SettingsObserver(mHandler);
-        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
-        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
-        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
-        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
-        mImePlatformCompatUtils = new ImePlatformCompatUtils();
-        mInputMethodDeviceConfigs = new InputMethodDeviceConfigs();
-        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
-
-        mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
-
-        mShowOngoingImeSwitcherForPhones = false;
-
-        AdditionalSubtypeMapRepository.initialize(mHandler);
-
-        final int userId = mActivityManagerInternal.getCurrentUserId();
-
-        // mSettings should be created before buildInputMethodListLocked
-        mSettings = InputMethodSettings.createEmptyMap(userId);
-
-        mSwitchingController =
-                InputMethodSubtypeSwitchingController.createInstanceLocked(context,
-                        mSettings.getMethodMap(), userId);
-        mHardwareKeyboardShortcutController =
-                new HardwareKeyboardShortcutController(mSettings.getMethodMap(),
-                        mSettings.getUserId());
-        mMenuController = new InputMethodMenuController(this);
-        mBindingController =
-                bindingControllerForTesting != null
-                        ? bindingControllerForTesting
-                        : new InputMethodBindingController(this);
-        mAutofillController = new AutofillSuggestionsController(this);
-
-        mVisibilityStateComputer = new ImeVisibilityStateComputer(this);
-        mVisibilityApplier = new DefaultImeVisibilityApplier(this);
-
-        mClientController = new ClientController(mPackageManagerInternal);
         synchronized (ImfLock.class) {
+            mContext = context;
+            mRes = context.getResources();
+            SecureSettingsWrapper.onStart(mContext);
+
+            // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading
+            // additional subtypes in switchUserOnHandlerLocked().
+            final ServiceThread thread =
+                    serviceThreadForTesting != null
+                            ? serviceThreadForTesting
+                            : new ServiceThread(
+                                    HANDLER_THREAD_NAME,
+                                    Process.THREAD_PRIORITY_FOREGROUND,
+                                    true /* allowIo */);
+            thread.start();
+            mHandler = Handler.createAsync(thread.getLooper(), this);
+            SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mHandler);
+            mImeTrackerService = new ImeTrackerService(serviceThreadForTesting != null
+                    ? serviceThreadForTesting.getLooper() : Looper.getMainLooper());
+            // Note: SettingsObserver doesn't register observers in its constructor.
+            mSettingsObserver = new SettingsObserver(mHandler);
+            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+            mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+            mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+            mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
+            mImePlatformCompatUtils = new ImePlatformCompatUtils();
+            mInputMethodDeviceConfigs = new InputMethodDeviceConfigs();
+            mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+
+            mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
+
+            mShowOngoingImeSwitcherForPhones = false;
+
+            // InputMethodSettingsRepository should be initialized before buildInputMethodListLocked
+            InputMethodSettingsRepository.initialize(mHandler, mContext);
+            AdditionalSubtypeMapRepository.initialize(mHandler, mContext);
+
+            mCurrentUserId = mActivityManagerInternal.getCurrentUserId();
+            mUserDataRepository = new UserDataRepository(mHandler, mUserManagerInternal);
+            for (int id : mUserManagerInternal.getUserIds()) {
+                mUserDataRepository.getOrCreate(id);
+            }
+
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+
+            mSwitchingController =
+                    InputMethodSubtypeSwitchingController.createInstanceLocked(context,
+                            settings.getMethodMap(), settings.getUserId());
+            mHardwareKeyboardShortcutController =
+                    new HardwareKeyboardShortcutController(settings.getMethodMap(),
+                            settings.getUserId());
+            mMenuController = new InputMethodMenuController(this);
+            mBindingController =
+                    bindingControllerForTesting != null
+                            ? bindingControllerForTesting
+                            : new InputMethodBindingController(this);
+            mAutofillController = new AutofillSuggestionsController(this);
+
+            mVisibilityStateComputer = new ImeVisibilityStateComputer(this);
+            mVisibilityApplier = new DefaultImeVisibilityApplier(this);
+
+            mClientController = new ClientController(mPackageManagerInternal);
             mClientController.addClientControllerCallback(c -> onClientRemoved(c));
             mImeBindingState = ImeBindingState.newEmptyState();
-        }
 
-        mPreventImeStartupUnlessTextEditor = mRes.getBoolean(
-                com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor);
-        mNonPreemptibleInputMethods = mRes.getStringArray(
-                com.android.internal.R.array.config_nonPreemptibleInputMethods);
-        IntConsumer toolTypeConsumer =
-                Flags.useHandwritingListenerForTooltype()
-                        ? toolType -> onUpdateEditorToolType(toolType) : null;
-        Runnable discardDelegationTextRunnable = () -> discardHandwritingDelegationText();
-        mHwController = new HandwritingModeController(mContext, thread.getLooper(),
-                new InkWindowInitializer(), toolTypeConsumer, discardDelegationTextRunnable);
-        registerDeviceListenerAndCheckStylusSupport();
+            mPreventImeStartupUnlessTextEditor = mRes.getBoolean(
+                    com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor);
+            mNonPreemptibleInputMethods = mRes.getStringArray(
+                    com.android.internal.R.array.config_nonPreemptibleInputMethods);
+            IntConsumer toolTypeConsumer =
+                    Flags.useHandwritingListenerForTooltype()
+                            ? toolType -> onUpdateEditorToolType(toolType) : null;
+            Runnable discardDelegationTextRunnable = () -> discardHandwritingDelegationText();
+            mHwController = new HandwritingModeController(mContext, thread.getLooper(),
+                    new InkWindowInitializer(), toolTypeConsumer, discardDelegationTextRunnable);
+            registerDeviceListenerAndCheckStylusSupport();
+        }
     }
 
     @GuardedBy("ImfLock.class")
     @UserIdInt
     int getCurrentImeUserIdLocked() {
-        return mSettings.getUserId();
+        return mCurrentUserId;
     }
 
     private final class InkWindowInitializer implements Runnable {
@@ -1448,12 +1461,13 @@
     private void resetDefaultImeLocked(Context context) {
         // Do not reset the default (current) IME when it is a 3rd-party IME
         String selectedMethodId = getSelectedMethodIdLocked();
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         if (selectedMethodId != null
-                && !mSettings.getMethodMap().get(selectedMethodId).isSystem()) {
+                && !settings.getMethodMap().get(selectedMethodId).isSystem()) {
             return;
         }
         final List<InputMethodInfo> suitableImes = InputMethodInfoUtils.getDefaultEnabledImes(
-                context, mSettings.getEnabledInputMethodList());
+                context, settings.getEnabledInputMethodList());
         if (suitableImes.isEmpty()) {
             Slog.i(TAG, "No default found");
             return;
@@ -1509,7 +1523,7 @@
             IInputMethodClientInvoker clientToBeReset) {
         if (DEBUG) {
             Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
-                    + " currentUserId=" + mSettings.getUserId());
+                    + " currentUserId=" + mCurrentUserId);
         }
 
         maybeInitImeNavbarConfigLocked(newUserId);
@@ -1517,8 +1531,9 @@
         // ContentObserver should be registered again when the user is changed
         mSettingsObserver.registerContentObserverLocked(newUserId);
 
-        mSettings = InputMethodSettings.createEmptyMap(newUserId);
-        final String defaultImiId = mSettings.getSelectedInputMethod();
+        mCurrentUserId = newUserId;
+        final String defaultImiId = SecureSettingsWrapper.getString(
+                Settings.Secure.DEFAULT_INPUT_METHOD, null, newUserId);
 
         if (DEBUG) {
             Slog.d(TAG, "Switching user stage 2/3. newUserId=" + newUserId
@@ -1536,10 +1551,9 @@
         // and user switch would not happen at that time.
         resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_USER);
 
-        mSettings = queryInputMethodServicesInternal(mContext, newUserId,
-                AdditionalSubtypeMapRepository.get(newUserId), DirectBootAwareness.AUTO);
+        final InputMethodSettings newSettings = InputMethodSettingsRepository.get(newUserId);
         postInputMethodSettingUpdatedLocked(initialUserSwitch /* resetDefaultEnabledIme */);
-        if (TextUtils.isEmpty(mSettings.getSelectedInputMethod())) {
+        if (TextUtils.isEmpty(newSettings.getSelectedInputMethod())) {
             // This is the first time of the user switch and
             // set the current ime to the proper one.
             resetDefaultImeLocked(mContext);
@@ -1549,12 +1563,12 @@
         if (initialUserSwitch) {
             InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
                     getPackageManagerForUser(mContext, newUserId),
-                    mSettings.getEnabledInputMethodList());
+                    newSettings.getEnabledInputMethodList());
         }
 
         if (DEBUG) {
             Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId
-                    + " selectedIme=" + mSettings.getSelectedInputMethod());
+                    + " selectedIme=" + newSettings.getSelectedInputMethod());
         }
 
         if (mIsInteractive && clientToBeReset != null) {
@@ -1577,7 +1591,7 @@
             }
             if (!mSystemReady) {
                 mSystemReady = true;
-                final int currentUserId = mSettings.getUserId();
+                final int currentUserId = mCurrentUserId;
                 mStatusBarManagerInternal =
                         LocalServices.getService(StatusBarManagerInternal.class);
                 hideStatusBarIconLocked();
@@ -1598,7 +1612,7 @@
                     // the "mImeDrawsImeNavBarResLazyInitFuture" field.
                     synchronized (ImfLock.class) {
                         mImeDrawsImeNavBarResLazyInitFuture = null;
-                        if (currentUserId != mSettings.getUserId()) {
+                        if (currentUserId != mCurrentUserId) {
                             // This means that the current user is already switched to other user
                             // before the background task is executed. In this scenario the relevant
                             // field should already be initialized.
@@ -1617,17 +1631,19 @@
                         UserHandle.ALL, broadcastFilterForAllUsers, null, null,
                         Context.RECEIVER_EXPORTED);
 
-                final String defaultImiId = mSettings.getSelectedInputMethod();
+                final String defaultImiId = SecureSettingsWrapper.getString(
+                        Settings.Secure.DEFAULT_INPUT_METHOD, null, currentUserId);
                 final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
-                mSettings = queryInputMethodServicesInternal(mContext, currentUserId,
-                        AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
+                final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
+                        currentUserId, AdditionalSubtypeMapRepository.get(currentUserId),
                         DirectBootAwareness.AUTO);
+                InputMethodSettingsRepository.put(currentUserId, newSettings);
                 postInputMethodSettingUpdatedLocked(
                         !imeSelectedOnBoot /* resetDefaultEnabledIme */);
                 updateFromSettingsLocked(true);
                 InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
                         getPackageManagerForUser(mContext, currentUserId),
-                        mSettings.getEnabledInputMethodList());
+                        newSettings.getEnabledInputMethodList());
             }
         }
     }
@@ -1674,7 +1690,7 @@
         }
         synchronized (ImfLock.class) {
             final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId,
-                    mSettings.getUserId(), null);
+                    mCurrentUserId, null);
             if (resolvedUserIds.length != 1) {
                 return Collections.emptyList();
             }
@@ -1697,7 +1713,7 @@
         }
         synchronized (ImfLock.class) {
             final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId,
-                    mSettings.getUserId(), null);
+                    mCurrentUserId, null);
             if (resolvedUserIds.length != 1) {
                 return Collections.emptyList();
             }
@@ -1725,14 +1741,12 @@
             }
 
             // Check if selected IME of current user supports handwriting.
-            if (userId == mSettings.getUserId()) {
+            if (userId == mCurrentUserId) {
                 return mBindingController.supportsStylusHandwriting()
                         && (!connectionless
                                 || mBindingController.supportsConnectionlessStylusHandwriting());
             }
-            //TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList.
-            //TODO(b/210039666): use cache.
-            final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
             final InputMethodInfo imi = settings.getMethodMap().get(
                     settings.getSelectedInputMethod());
             return imi != null && imi.supportsStylusHandwriting()
@@ -1756,9 +1770,8 @@
     private List<InputMethodInfo> getInputMethodListLocked(@UserIdInt int userId,
             @DirectBootAwareness int directBootAwareness, int callingUid) {
         final InputMethodSettings settings;
-        if (userId == mSettings.getUserId()
-                && directBootAwareness == DirectBootAwareness.AUTO) {
-            settings = mSettings;
+        if (directBootAwareness == DirectBootAwareness.AUTO) {
+            settings = InputMethodSettingsRepository.get(userId);
         } else {
             final AdditionalSubtypeMap additionalSubtypeMap =
                     AdditionalSubtypeMapRepository.get(userId);
@@ -1776,15 +1789,8 @@
     @GuardedBy("ImfLock.class")
     private List<InputMethodInfo> getEnabledInputMethodListLocked(@UserIdInt int userId,
             int callingUid) {
-        final ArrayList<InputMethodInfo> methodList;
-        final InputMethodSettings settings;
-        if (userId == mSettings.getUserId()) {
-            methodList = mSettings.getEnabledInputMethodList();
-            settings = mSettings;
-        } else {
-            settings = queryMethodMapForUserLocked(userId);
-            methodList = settings.getEnabledInputMethodList();
-        }
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
+        final ArrayList<InputMethodInfo> methodList = settings.getEnabledInputMethodList();
         // filter caller's access to input methods
         methodList.removeIf(imi ->
                 !canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings));
@@ -1842,22 +1848,7 @@
     @GuardedBy("ImfLock.class")
     private List<InputMethodSubtype> getEnabledInputMethodSubtypeListLocked(String imiId,
             boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId, int callingUid) {
-        if (userId == mSettings.getUserId()) {
-            final InputMethodInfo imi;
-            String selectedMethodId = getSelectedMethodIdLocked();
-            if (imiId == null && selectedMethodId != null) {
-                imi = mSettings.getMethodMap().get(selectedMethodId);
-            } else {
-                imi = mSettings.getMethodMap().get(imiId);
-            }
-            if (imi == null || !canCallerAccessInputMethod(
-                    imi.getPackageName(), callingUid, userId, mSettings)) {
-                return Collections.emptyList();
-            }
-            return mSettings.getEnabledInputMethodSubtypeList(
-                    imi, allowsImplicitlyEnabledSubtypes);
-        }
-        final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
         final InputMethodInfo imi = settings.getMethodMap().get(imiId);
         if (imi == null) {
             return Collections.emptyList();
@@ -1934,10 +1925,10 @@
     }
 
     @Nullable
-    ClientState getClientState(IInputMethodClient client) {
-        synchronized (ImfLock.class) {
-            return mClientController.getClient(client.asBinder());
-        }
+    @GuardedBy("ImfLock.class")
+    @Override
+    public ClientState getClientStateLocked(IInputMethodClient client) {
+        return mClientController.getClient(client.asBinder());
     }
 
     // TODO(b/314150112): Move this to ClientController.
@@ -2016,7 +2007,8 @@
     }
 
     @GuardedBy("ImfLock.class")
-    private boolean isInputShown() {
+    @Override
+    public boolean isInputShownLocked() {
         return mVisibilityStateComputer.isInputShown();
     }
 
@@ -2037,7 +2029,7 @@
 
         final boolean restarting = !initial;
         final Binder startInputToken = new Binder();
-        final StartInputInfo info = new StartInputInfo(mSettings.getUserId(),
+        final StartInputInfo info = new StartInputInfo(mCurrentUserId,
                 getCurTokenLocked(),
                 mCurTokenDisplayId, getCurIdLocked(), startInputReason, restarting,
                 UserHandle.getUserId(mCurClient.mUid),
@@ -2051,9 +2043,9 @@
         // same-user scenarios.
         // That said ignoring cross-user scenario will never affect IMEs that do not have
         // INTERACT_ACROSS_USERS(_FULL) permissions, which is actually almost always the case.
-        if (mSettings.getUserId() == UserHandle.getUserId(
+        if (mCurrentUserId == UserHandle.getUserId(
                 mCurClient.mUid)) {
-            mPackageManagerInternal.grantImplicitAccess(mSettings.getUserId(),
+            mPackageManagerInternal.grantImplicitAccess(mCurrentUserId,
                     null /* intent */, UserHandle.getAppId(getCurMethodUidLocked()),
                     mCurClient.mUid, true /* direct */);
         }
@@ -2076,7 +2068,8 @@
         }
 
         String curId = getCurIdLocked();
-        final InputMethodInfo curInputMethodInfo = mSettings.getMethodMap().get(curId);
+        final InputMethodInfo curInputMethodInfo = InputMethodSettingsRepository.get(mCurrentUserId)
+                .getMethodMap().get(curId);
         final boolean suppressesSpellChecker =
                 curInputMethodInfo != null && curInputMethodInfo.suppressesSpellChecker();
         final SparseArray<IAccessibilityInputMethodSession> accessibilityInputMethodSessions =
@@ -2264,17 +2257,18 @@
             return currentMethodId;
         }
 
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         final int oldDeviceId = mDeviceIdToShowIme;
         mDeviceIdToShowIme = mVdmInternal.getDeviceIdForDisplayId(mDisplayIdToShowIme);
         if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) {
             if (oldDeviceId == DEVICE_ID_DEFAULT) {
                 return currentMethodId;
             }
-            final String defaultDeviceMethodId = mSettings.getSelectedDefaultDeviceInputMethod();
+            final String defaultDeviceMethodId = settings.getSelectedDefaultDeviceInputMethod();
             if (DEBUG) {
                 Slog.v(TAG, "Restoring default device input method: " + defaultDeviceMethodId);
             }
-            mSettings.putSelectedDefaultDeviceInputMethod(null);
+            settings.putSelectedDefaultDeviceInputMethod(null);
             return defaultDeviceMethodId;
         }
 
@@ -2282,7 +2276,7 @@
                 mVirtualDeviceMethodMap.get(mDeviceIdToShowIme, currentMethodId);
         if (Objects.equals(deviceMethodId, currentMethodId)) {
             return currentMethodId;
-        } else if (!mSettings.getMethodMap().containsKey(deviceMethodId)) {
+        } else if (!settings.getMethodMap().containsKey(deviceMethodId)) {
             if (DEBUG) {
                 Slog.v(TAG, "Disabling IME on virtual device with id " + mDeviceIdToShowIme
                         + " because its custom input method is not available: " + deviceMethodId);
@@ -2294,7 +2288,7 @@
             if (DEBUG) {
                 Slog.v(TAG, "Storing default device input method " + currentMethodId);
             }
-            mSettings.putSelectedDefaultDeviceInputMethod(currentMethodId);
+            settings.putSelectedDefaultDeviceInputMethod(currentMethodId);
         }
         if (DEBUG) {
             Slog.v(TAG, "Switching current input method from " + currentMethodId
@@ -2324,7 +2318,8 @@
         if (isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags)) {
             return false;
         }
-        final InputMethodInfo imi = mSettings.getMethodMap().get(selectedMethodId);
+        final InputMethodInfo imi = InputMethodSettingsRepository.get(mCurrentUserId)
+                .getMethodMap().get(selectedMethodId);
         if (imi == null) {
             return false;
         }
@@ -2668,7 +2663,7 @@
                 } else if (packageName != null) {
                     if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
                     final PackageManager userAwarePackageManager =
-                            getPackageManagerForUser(mContext, mSettings.getUserId());
+                            getPackageManagerForUser(mContext, mCurrentUserId);
                     ApplicationInfo applicationInfo = null;
                     try {
                         applicationInfo = userAwarePackageManager.getApplicationInfo(packageName,
@@ -2730,7 +2725,7 @@
             return false;
         }
         if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded()
-                && mWindowManagerInternal.isKeyguardSecure(mSettings.getUserId())) {
+                && mWindowManagerInternal.isKeyguardSecure(mCurrentUserId)) {
             return false;
         }
         if ((visibility & InputMethodService.IME_ACTIVE) == 0
@@ -2747,7 +2742,8 @@
             return false;
         }
 
-        List<InputMethodInfo> imes = mSettings.getEnabledInputMethodListWithFilter(
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+        List<InputMethodInfo> imes = settings.getEnabledInputMethodListWithFilter(
                 InputMethodInfo::shouldShowInInputMethodPicker);
         final int numImes = imes.size();
         if (numImes > 2) return true;
@@ -2759,7 +2755,7 @@
         for (int i = 0; i < numImes; ++i) {
             final InputMethodInfo imi = imes.get(i);
             final List<InputMethodSubtype> subtypes =
-                    mSettings.getEnabledInputMethodSubtypeList(imi, true);
+                    settings.getEnabledInputMethodSubtypeList(imi, true);
             final int subtypeCount = subtypes.size();
             if (subtypeCount == 0) {
                 ++nonAuxCount;
@@ -2911,11 +2907,12 @@
 
     @GuardedBy("ImfLock.class")
     void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         if (enabledMayChange) {
             final PackageManager userAwarePackageManager = getPackageManagerForUser(mContext,
-                    mSettings.getUserId());
+                    settings.getUserId());
 
-            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodList();
+            List<InputMethodInfo> enabled = settings.getEnabledInputMethodList();
             for (int i = 0; i < enabled.size(); i++) {
                 // We allow the user to select "disabled until used" apps, so if they
                 // are enabling one of those here we now need to make it enabled.
@@ -2942,20 +2939,20 @@
 
         if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) {
             String ime = SecureSettingsWrapper.getString(
-                    Settings.Secure.DEFAULT_INPUT_METHOD, null, mSettings.getUserId());
+                    Settings.Secure.DEFAULT_INPUT_METHOD, null, settings.getUserId());
             String defaultDeviceIme = SecureSettingsWrapper.getString(
-                    Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null, mSettings.getUserId());
+                    Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null, settings.getUserId());
             if (defaultDeviceIme != null && !Objects.equals(ime, defaultDeviceIme)) {
                 if (DEBUG) {
                     Slog.v(TAG, "Current input method " + ime + " differs from the stored default"
-                            + " device input method for user " + mSettings.getUserId()
+                            + " device input method for user " + settings.getUserId()
                             + " - restoring " + defaultDeviceIme);
                 }
                 SecureSettingsWrapper.putString(
                         Settings.Secure.DEFAULT_INPUT_METHOD, defaultDeviceIme,
-                        mSettings.getUserId());
+                        settings.getUserId());
                 SecureSettingsWrapper.putString(
-                        Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null, mSettings.getUserId());
+                        Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null, settings.getUserId());
             }
         }
 
@@ -2963,14 +2960,14 @@
         // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
         // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
         // enabled.
-        String id = mSettings.getSelectedInputMethod();
+        String id = settings.getSelectedInputMethod();
         // There is no input method selected, try to choose new applicable input method.
         if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
-            id = mSettings.getSelectedInputMethod();
+            id = settings.getSelectedInputMethod();
         }
         if (!TextUtils.isEmpty(id)) {
             try {
-                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
+                setInputMethodLocked(id, settings.getSelectedInputMethodSubtypeId(id));
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Unknown input method from prefs: " + id, e);
                 resetCurrentMethodAndClientLocked(UnbindReason.SWITCH_IME_FAILED);
@@ -2981,18 +2978,18 @@
         }
 
         // TODO: Instantiate mSwitchingController for each user.
-        if (mSettings.getUserId() == mSwitchingController.getUserId()) {
-            mSwitchingController.resetCircularListLocked(mSettings.getMethodMap());
+        if (settings.getUserId() == mSwitchingController.getUserId()) {
+            mSwitchingController.resetCircularListLocked(settings.getMethodMap());
         } else {
             mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
-                    mContext, mSettings.getMethodMap(), mSettings.getUserId());
+                    mContext, settings.getMethodMap(), settings.getUserId());
         }
         // TODO: Instantiate mHardwareKeyboardShortcutController for each user.
-        if (mSettings.getUserId() == mHardwareKeyboardShortcutController.getUserId()) {
-            mHardwareKeyboardShortcutController.reset(mSettings.getMethodMap());
+        if (settings.getUserId() == mHardwareKeyboardShortcutController.getUserId()) {
+            mHardwareKeyboardShortcutController.reset(settings.getMethodMap());
         } else {
             mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController(
-                    mSettings.getMethodMap(), mSettings.getUserId());
+                    settings.getMethodMap(), settings.getUserId());
         }
         sendOnNavButtonFlagsChangedLocked();
     }
@@ -3016,14 +3013,15 @@
 
     @GuardedBy("ImfLock.class")
     void setInputMethodLocked(String id, int subtypeId, int deviceId) {
-        InputMethodInfo info = mSettings.getMethodMap().get(id);
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+        InputMethodInfo info = settings.getMethodMap().get(id);
         if (info == null) {
             throw getExceptionForUnknownImeId(id);
         }
 
         // See if we need to notify a subtype change within the same IME.
         if (id.equals(getSelectedMethodIdLocked())) {
-            final int userId = mSettings.getUserId();
+            final int userId = settings.getUserId();
             final int subtypeCount = info.getSubtypeCount();
             if (subtypeCount <= 0) {
                 notifyInputMethodSubtypeChangedLocked(userId, info, null);
@@ -3064,7 +3062,7 @@
             // method is a custom one specific to a virtual device. So only update the settings
             // entry used to restore the default device input method once we want to show the IME
             // back on the default device.
-            mSettings.putSelectedDefaultDeviceInputMethod(id);
+            settings.putSelectedDefaultDeviceInputMethod(id);
             return;
         }
         IInputMethodInvoker curMethod = getCurMethodLocked();
@@ -3132,11 +3130,16 @@
     public void startConnectionlessStylusHandwriting(IInputMethodClient client, int userId,
             @Nullable CursorAnchorInfo cursorAnchorInfo, @Nullable String delegatePackageName,
             @Nullable String delegatorPackageName,
-            @NonNull IConnectionlessHandwritingCallback callback) throws RemoteException {
+            @NonNull IConnectionlessHandwritingCallback callback) {
         synchronized (ImfLock.class) {
             if (!mBindingController.supportsConnectionlessStylusHandwriting()) {
                 Slog.w(TAG, "Connectionless stylus handwriting mode unsupported by IME.");
-                callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED);
+                try {
+                    callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to report CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED", e);
+                    e.rethrowAsRuntimeException();
+                }
                 return;
             }
         }
@@ -3147,7 +3150,12 @@
             synchronized (ImfLock.class) {
                 if (!mClientController.verifyClientAndPackageMatch(client, delegatorPackageName)) {
                     Slog.w(TAG, "startConnectionlessStylusHandwriting() fail");
-                    callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_OTHER);
+                    try {
+                        callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_OTHER);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to report CONNECTIONLESS_HANDWRITING_ERROR_OTHER", e);
+                        e.rethrowAsRuntimeException();
+                    }
                     throw new IllegalArgumentException("Delegator doesn't match UID");
                 }
             }
@@ -3171,7 +3179,12 @@
 
         if (!startStylusHandwriting(
                 client, false, immsCallback, cursorAnchorInfo, isForDelegation)) {
-            callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_OTHER);
+            try {
+                callback.onError(CONNECTIONLESS_HANDWRITING_ERROR_OTHER);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to report CONNECTIONLESS_HANDWRITING_ERROR_OTHER", e);
+                e.rethrowAsRuntimeException();
+            }
         }
     }
 
@@ -3271,11 +3284,15 @@
             @UserIdInt int userId,
             @NonNull String delegatePackageName,
             @NonNull String delegatorPackageName,
-            @InputMethodManager.HandwritingDelegateFlags int flags, IBooleanListener callback)
-            throws RemoteException {
+            @InputMethodManager.HandwritingDelegateFlags int flags, IBooleanListener callback) {
         boolean result = acceptStylusHandwritingDelegation(
                 client, userId, delegatePackageName, delegatorPackageName, flags);
-        callback.onResult(result);
+        try {
+            callback.onResult(result);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to report result=" + result, e);
+            e.rethrowAsRuntimeException();
+        }
     }
 
     @Override
@@ -3366,7 +3383,7 @@
     @GuardedBy("ImfLock.class")
     boolean showCurrentInputLocked(IBinder windowToken,
             @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
-            int lastClickToolType, @Nullable ResultReceiver resultReceiver,
+            @MotionEvent.ToolType int lastClickToolType, @Nullable ResultReceiver resultReceiver,
             @SoftInputShowHideReason int reason) {
         if (!mVisibilityStateComputer.onImeShowFlags(statsToken, flags)) {
             return false;
@@ -3412,7 +3429,7 @@
                 "InputMethodManagerService#hideSoftInput");
         synchronized (ImfLock.class) {
             if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken)) {
-                if (isInputShown()) {
+                if (isInputShownLocked()) {
                     ImeTracker.forLogging().onFailed(
                             statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
                 } else {
@@ -3435,10 +3452,8 @@
     }
 
     @Override
-    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
     public void hideSoftInputFromServerForTest() {
-        super.hideSoftInputFromServerForTest_enforcePermission();
-
         synchronized (ImfLock.class) {
             hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
                     SoftInputShowHideReason.HIDE_SOFT_INPUT);
@@ -3471,7 +3486,7 @@
         // TODO(b/246309664): Clean up IMMS#mImeWindowVis
         IInputMethodInvoker curMethod = getCurMethodLocked();
         final boolean shouldHideSoftInput = curMethod != null
-                && (isInputShown() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
+                && (isInputShownLocked() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
 
         mVisibilityStateComputer.requestImeVisibility(windowToken, false);
         if (shouldHideSoftInput) {
@@ -3575,7 +3590,7 @@
                             return InputBindResult.USER_SWITCHING;
                         }
                         final int[] profileIdsWithDisabled = mUserManagerInternal.getProfileIds(
-                                mSettings.getUserId(), false /* enabledOnly */);
+                                mCurrentUserId, false /* enabledOnly */);
                         for (int profileId : profileIdsWithDisabled) {
                             if (profileId == userId) {
                                 scheduleSwitchUserTaskLocked(userId, cs.mClient);
@@ -3621,10 +3636,10 @@
                     }
 
                     // Verify if caller is a background user.
-                    final int currentUserId = mSettings.getUserId();
-                    if (userId != currentUserId) {
+                    if (userId != mCurrentUserId) {
                         if (ArrayUtils.contains(
-                                mUserManagerInternal.getProfileIds(currentUserId, false), userId)) {
+                                mUserManagerInternal.getProfileIds(mCurrentUserId, false),
+                                userId)) {
                             // cross-profile access is always allowed here to allow
                             // profile-switching.
                             scheduleSwitchUserTaskLocked(userId, cs.mClient);
@@ -3813,7 +3828,7 @@
                 && mImeBindingState.mFocusedWindowClient.mClient.asBinder() == client.asBinder()) {
             return true;
         }
-        if (mSettings.getUserId() != UserHandle.getUserId(uid)) {
+        if (mCurrentUserId != UserHandle.getUserId(uid)) {
             return false;
         }
         if (getCurIntentLocked() != null && InputMethodUtils.checkIfPackageBelongsToUid(
@@ -3844,13 +3859,11 @@
         }
     }
 
-    @EnforcePermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) {
         // Always call subtype picker, because subtype picker is a superset of input method
         // picker.
-        super.showInputMethodPickerFromSystem_enforcePermission();
-
         mHandler.obtainMessage(MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId)
                 .sendToTarget();
     }
@@ -3858,10 +3871,8 @@
     /**
      * A test API for CTS to make sure that the input method menu is showing.
      */
-    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
     public boolean isInputMethodPickerShownForTest() {
-        super.isInputMethodPickerShownForTest_enforcePermission();
-
         synchronized (ImfLock.class) {
             return mMenuController.isisInputMethodPickerShownForTestLocked();
         }
@@ -3881,9 +3892,10 @@
             if (!calledWithValidTokenLocked(token)) {
                 return;
             }
-            final InputMethodInfo imi = mSettings.getMethodMap().get(id);
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+            final InputMethodInfo imi = settings.getMethodMap().get(id);
             if (imi == null || !canCallerAccessInputMethod(
-                    imi.getPackageName(), callingUid, userId, mSettings)) {
+                    imi.getPackageName(), callingUid, userId, settings)) {
                 throw getExceptionForUnknownImeId(id);
             }
             setInputMethodWithSubtypeIdLocked(token, id, NOT_A_SUBTYPE_ID);
@@ -3899,9 +3911,10 @@
             if (!calledWithValidTokenLocked(token)) {
                 return;
             }
-            final InputMethodInfo imi = mSettings.getMethodMap().get(id);
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+            final InputMethodInfo imi = settings.getMethodMap().get(id);
             if (imi == null || !canCallerAccessInputMethod(
-                    imi.getPackageName(), callingUid, userId, mSettings)) {
+                    imi.getPackageName(), callingUid, userId, settings)) {
                 throw getExceptionForUnknownImeId(id);
             }
             if (subtype != null) {
@@ -3919,10 +3932,11 @@
             if (!calledWithValidTokenLocked(token)) {
                 return false;
             }
-            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtype();
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+            final Pair<String, String> lastIme = settings.getLastInputMethodAndSubtype();
             final InputMethodInfo lastImi;
             if (lastIme != null) {
-                lastImi = mSettings.getMethodMap().get(lastIme.first);
+                lastImi = settings.getMethodMap().get(lastIme.first);
             } else {
                 lastImi = null;
             }
@@ -3946,7 +3960,7 @@
                 // This is a safety net. If the currentSubtype can't be added to the history
                 // and the framework couldn't find the last ime, we will make the last ime be
                 // the most applicable enabled keyboard subtype of the system imes.
-                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodList();
+                final List<InputMethodInfo> enabled = settings.getEnabledInputMethodList();
                 if (enabled != null) {
                     final int enabledCount = enabled.size();
                     final String locale;
@@ -3954,7 +3968,7 @@
                             && !TextUtils.isEmpty(mCurrentSubtype.getLocale())) {
                         locale = mCurrentSubtype.getLocale();
                     } else {
-                        locale = SystemLocaleWrapper.get(mSettings.getUserId()).get(0).toString();
+                        locale = SystemLocaleWrapper.get(mCurrentUserId).get(0).toString();
                     }
                     for (int i = 0; i < enabledCount; ++i) {
                         final InputMethodInfo imi = enabled.get(i);
@@ -4001,8 +4015,9 @@
 
     @GuardedBy("ImfLock.class")
     private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme) {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
-                onlyCurrentIme, mSettings.getMethodMap().get(getSelectedMethodIdLocked()),
+                onlyCurrentIme, settings.getMethodMap().get(getSelectedMethodIdLocked()),
                 mCurrentSubtype);
         if (nextSubtype == null) {
             return false;
@@ -4018,9 +4033,10 @@
             if (!calledWithValidTokenLocked(token)) {
                 return false;
             }
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
             final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
                     false /* onlyCurrentIme */,
-                    mSettings.getMethodMap().get(getSelectedMethodIdLocked()), mCurrentSubtype);
+                    settings.getMethodMap().get(getSelectedMethodIdLocked()), mCurrentSubtype);
             return nextSubtype != null;
         }
     }
@@ -4032,12 +4048,7 @@
                     Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
         }
         synchronized (ImfLock.class) {
-            if (mSettings.getUserId() == userId) {
-                return mSettings.getLastInputMethodSubtype();
-            }
-
-            final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
-            return settings.getLastInputMethodSubtype();
+            return InputMethodSettingsRepository.get(userId).getLastInputMethodSubtype();
         }
     }
 
@@ -4068,23 +4079,20 @@
             }
 
             final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
-            final boolean isCurrentUser = (mSettings.getUserId() == userId);
-            final InputMethodSettings settings = isCurrentUser
-                    ? mSettings
-                    : queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
-                            DirectBootAwareness.AUTO);
+            final boolean isCurrentUser = (mCurrentUserId == userId);
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
             final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap(
                     imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid);
             if (additionalSubtypeMap != newAdditionalSubtypeMap) {
                 AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap,
                         settings.getMethodMap());
+                final InputMethodSettings newSettings = queryInputMethodServicesInternal(mContext,
+                        userId, AdditionalSubtypeMapRepository.get(userId),
+                        DirectBootAwareness.AUTO);
+                InputMethodSettingsRepository.put(userId, newSettings);
                 if (isCurrentUser) {
                     final long ident = Binder.clearCallingIdentity();
                     try {
-                        mSettings = queryInputMethodServicesInternal(mContext,
-                                mSettings.getUserId(),
-                                AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
-                                DirectBootAwareness.AUTO);
                         postInputMethodSettingUpdatedLocked(false /* resetDefaultEnabledIme */);
                     } finally {
                         Binder.restoreCallingIdentity(ident);
@@ -4114,9 +4122,8 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (ImfLock.class) {
-                final boolean currentUser = (mSettings.getUserId() == userId);
-                final InputMethodSettings settings = currentUser
-                        ? mSettings : queryMethodMapForUserLocked(userId);
+                final boolean currentUser = (mCurrentUserId == userId);
+                final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
                 if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) {
                     return;
                 }
@@ -4161,11 +4168,9 @@
         });
     }
 
-    @EnforcePermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
     @Override
     public void removeImeSurface() {
-        super.removeImeSurface_enforcePermission();
-
         mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE).sendToTarget();
     }
 
@@ -4274,11 +4279,9 @@
      * a stylus deviceId is not already registered on device.
      */
     @BinderThread
-    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
     @Override
     public void addVirtualStylusIdForTestSession(IInputMethodClient client) {
-        super.addVirtualStylusIdForTestSession_enforcePermission();
-
         int uid = Binder.getCallingUid();
         synchronized (ImfLock.class) {
             if (!canInteractWithImeLocked(uid, client, "addVirtualStylusIdForTestSession",
@@ -4301,12 +4304,10 @@
      * @param timeout to set in milliseconds. To reset to default, use a value <= zero.
      */
     @BinderThread
-    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
     @Override
     public void setStylusWindowIdleTimeoutForTest(
             IInputMethodClient client, @DurationMillisLong long timeout) {
-        super.setStylusWindowIdleTimeoutForTest_enforcePermission();
-
         int uid = Binder.getCallingUid();
         synchronized (ImfLock.class) {
             if (!canInteractWithImeLocked(uid, client, "setStylusWindowIdleTimeoutForTest",
@@ -4402,10 +4403,9 @@
     }
 
     @BinderThread
-    @EnforcePermission(Manifest.permission.CONTROL_UI_TRACING)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.CONTROL_UI_TRACING)
     @Override
     public void startImeTrace() {
-        super.startImeTrace_enforcePermission();
         ImeTracing.getInstance().startTrace(null /* printwriter */);
         synchronized (ImfLock.class) {
             mClientController.forAllClients(c -> c.mClient.setImeTraceEnabled(true /* enabled */));
@@ -4413,11 +4413,9 @@
     }
 
     @BinderThread
-    @EnforcePermission(Manifest.permission.CONTROL_UI_TRACING)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.CONTROL_UI_TRACING)
     @Override
     public void stopImeTrace() {
-        super.stopImeTrace_enforcePermission();
-
         ImeTracing.getInstance().stopTrace(null /* printwriter */);
         synchronized (ImfLock.class) {
             mClientController.forAllClients(c -> c.mClient.setImeTraceEnabled(false /* enabled */));
@@ -4467,11 +4465,11 @@
                 }
                 return;
             }
-            if (mSettings.getUserId() != mSwitchingController.getUserId()) {
+            if (mCurrentUserId != mSwitchingController.getUserId()) {
                 return;
             }
-            final InputMethodInfo imi =
-                    mSettings.getMethodMap().get(getSelectedMethodIdLocked());
+            final InputMethodInfo imi = InputMethodSettingsRepository.get(mCurrentUserId)
+                    .getMethodMap().get(getSelectedMethodIdLocked());
             if (imi != null) {
                 mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
             }
@@ -4531,8 +4529,9 @@
             return;
         } else {
             // Called with current IME's token.
-            if (mSettings.getMethodMap().get(id) != null
-                    && mSettings.getEnabledInputMethodListWithFilter(
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+            if (settings.getMethodMap().get(id) != null
+                    && settings.getEnabledInputMethodListWithFilter(
                             (info) -> info.getId().equals(id)).isEmpty()) {
                 throw new IllegalStateException("Requested IME is not enabled: " + id);
             }
@@ -4697,7 +4696,7 @@
                         // implemented so that auxiliary subtypes will be excluded when the soft
                         // keyboard is invisible.
                         synchronized (ImfLock.class) {
-                            showAuxSubtypes = isInputShown();
+                            showAuxSubtypes = isInputShownLocked();
                         }
                         break;
                     case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
@@ -4711,21 +4710,23 @@
                         return false;
                 }
                 synchronized (ImfLock.class) {
+                    final InputMethodSettings settings =
+                            InputMethodSettingsRepository.get(mCurrentUserId);
                     final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked()
-                            && mWindowManagerInternal.isKeyguardSecure(mSettings.getUserId());
-                    final String lastInputMethodId = mSettings.getSelectedInputMethod();
+                            && mWindowManagerInternal.isKeyguardSecure(settings.getUserId());
+                    final String lastInputMethodId = settings.getSelectedInputMethod();
                     int lastInputMethodSubtypeId =
-                            mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
+                            settings.getSelectedInputMethodSubtypeId(lastInputMethodId);
 
                     final List<ImeSubtypeListItem> imList = InputMethodSubtypeSwitchingController
                             .getSortedInputMethodAndSubtypeList(
                                     showAuxSubtypes, isScreenLocked, true /* forImeMenu */,
-                                    mContext, mSettings.getMethodMap(), mSettings.getUserId());
+                                    mContext, settings.getMethodMap(), settings.getUserId());
                     if (imList.isEmpty()) {
                         Slog.w(TAG, "Show switching menu failed, imList is empty,"
                                 + " showAuxSubtypes: " + showAuxSubtypes
                                 + " isScreenLocked: " + isScreenLocked
-                                + " userId: " + mSettings.getUserId());
+                                + " userId: " + settings.getUserId());
                         return false;
                     }
 
@@ -4911,8 +4912,9 @@
 
     @GuardedBy("ImfLock.class")
     private boolean chooseNewDefaultIMELocked() {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         final InputMethodInfo imi = InputMethodInfoUtils.getMostApplicableDefaultIME(
-                mSettings.getEnabledInputMethodList());
+                settings.getEnabledInputMethodList());
         if (imi != null) {
             if (DEBUG) {
                 Slog.d(TAG, "New default IME was selected: " + imi.getId());
@@ -5026,6 +5028,8 @@
         mMethodMapUpdateCount++;
         mMyPackageMonitor.clearKnownImePackageNamesLocked();
 
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+
         // Construct the set of possible IME packages for onPackageChanged() to avoid false
         // negatives when the package state remains to be the same but only the component state is
         // changed.
@@ -5036,7 +5040,7 @@
             final List<ResolveInfo> allInputMethodServices =
                     mContext.getPackageManager().queryIntentServicesAsUser(
                             new Intent(InputMethod.SERVICE_INTERFACE),
-                            PackageManager.MATCH_DISABLED_COMPONENTS, mSettings.getUserId());
+                            PackageManager.MATCH_DISABLED_COMPONENTS, settings.getUserId());
             final int numImes = allInputMethodServices.size();
             for (int i = 0; i < numImes; ++i) {
                 final ServiceInfo si = allInputMethodServices.get(i).serviceInfo;
@@ -5051,11 +5055,11 @@
         if (!resetDefaultEnabledIme) {
             boolean enabledImeFound = false;
             boolean enabledNonAuxImeFound = false;
-            final List<InputMethodInfo> enabledImes = mSettings.getEnabledInputMethodList();
+            final List<InputMethodInfo> enabledImes = settings.getEnabledInputMethodList();
             final int numImes = enabledImes.size();
             for (int i = 0; i < numImes; ++i) {
                 final InputMethodInfo imi = enabledImes.get(i);
-                if (mSettings.getMethodMap().containsKey(imi.getId())) {
+                if (settings.getMethodMap().containsKey(imi.getId())) {
                     enabledImeFound = true;
                     if (!imi.isAuxiliaryIme()) {
                         enabledNonAuxImeFound = true;
@@ -5079,7 +5083,7 @@
 
         if (resetDefaultEnabledIme || reenableMinimumNonAuxSystemImes) {
             final ArrayList<InputMethodInfo> defaultEnabledIme =
-                    InputMethodInfoUtils.getDefaultEnabledImes(mContext, mSettings.getMethodList(),
+                    InputMethodInfoUtils.getDefaultEnabledImes(mContext, settings.getMethodList(),
                             reenableMinimumNonAuxSystemImes);
             final int numImes = defaultEnabledIme.size();
             for (int i = 0; i < numImes; ++i) {
@@ -5091,9 +5095,9 @@
             }
         }
 
-        final String defaultImiId = mSettings.getSelectedInputMethod();
+        final String defaultImiId = settings.getSelectedInputMethod();
         if (!TextUtils.isEmpty(defaultImiId)) {
-            if (!mSettings.getMethodMap().containsKey(defaultImiId)) {
+            if (!settings.getMethodMap().containsKey(defaultImiId)) {
                 Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
                 if (chooseNewDefaultIMELocked()) {
                     updateInputMethodsFromSettingsLocked(true);
@@ -5107,26 +5111,26 @@
         updateDefaultVoiceImeIfNeededLocked();
 
         // TODO: Instantiate mSwitchingController for each user.
-        if (mSettings.getUserId() == mSwitchingController.getUserId()) {
-            mSwitchingController.resetCircularListLocked(mSettings.getMethodMap());
+        if (settings.getUserId() == mSwitchingController.getUserId()) {
+            mSwitchingController.resetCircularListLocked(settings.getMethodMap());
         } else {
             mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
-                    mContext, mSettings.getMethodMap(), mSettings.getUserId());
+                    mContext, settings.getMethodMap(), mCurrentUserId);
         }
         // TODO: Instantiate mHardwareKeyboardShortcutController for each user.
-        if (mSettings.getUserId() == mHardwareKeyboardShortcutController.getUserId()) {
-            mHardwareKeyboardShortcutController.reset(mSettings.getMethodMap());
+        if (settings.getUserId() == mHardwareKeyboardShortcutController.getUserId()) {
+            mHardwareKeyboardShortcutController.reset(settings.getMethodMap());
         } else {
             mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController(
-                    mSettings.getMethodMap(), mSettings.getUserId());
+                    settings.getMethodMap(), settings.getUserId());
         }
 
         sendOnNavButtonFlagsChangedLocked();
 
         // Notify InputMethodListListeners of the new installed InputMethods.
-        final List<InputMethodInfo> inputMethodList = mSettings.getMethodList();
+        final List<InputMethodInfo> inputMethodList = settings.getMethodList();
         mHandler.obtainMessage(MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED,
-                mSettings.getUserId(), 0 /* unused */, inputMethodList).sendToTarget();
+                settings.getUserId(), 0 /* unused */, inputMethodList).sendToTarget();
     }
 
     @GuardedBy("ImfLock.class")
@@ -5141,11 +5145,12 @@
 
     @GuardedBy("ImfLock.class")
     private void updateDefaultVoiceImeIfNeededLocked() {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         final String systemSpeechRecognizer =
                 mContext.getString(com.android.internal.R.string.config_systemSpeechRecognizer);
-        final String currentDefaultVoiceImeId = mSettings.getDefaultVoiceInputMethod();
+        final String currentDefaultVoiceImeId = settings.getDefaultVoiceInputMethod();
         final InputMethodInfo newSystemVoiceIme = InputMethodInfoUtils.chooseSystemVoiceIme(
-                mSettings.getMethodMap(), systemSpeechRecognizer, currentDefaultVoiceImeId);
+                settings.getMethodMap(), systemSpeechRecognizer, currentDefaultVoiceImeId);
         if (newSystemVoiceIme == null) {
             if (DEBUG) {
                 Slog.i(TAG, "Found no valid default Voice IME. If the user is still locked,"
@@ -5154,7 +5159,7 @@
             // Clear DEFAULT_VOICE_INPUT_METHOD when necessary.  Note that InputMethodSettings
             // does not update the actual Secure Settings until the user is unlocked.
             if (!TextUtils.isEmpty(currentDefaultVoiceImeId)) {
-                mSettings.putDefaultVoiceInputMethod("");
+                settings.putDefaultVoiceInputMethod("");
                 // We don't support disabling the voice ime when a package is removed from the
                 // config.
             }
@@ -5167,7 +5172,7 @@
             Slog.i(TAG, "Enabling the default Voice IME:" + newSystemVoiceIme);
         }
         setInputMethodEnabledLocked(newSystemVoiceIme.getId(), true);
-        mSettings.putDefaultVoiceInputMethod(newSystemVoiceIme.getId());
+        settings.putDefaultVoiceInputMethod(newSystemVoiceIme.getId());
     }
 
     // ----------------------------------------------------------------------
@@ -5182,8 +5187,9 @@
      */
     @GuardedBy("ImfLock.class")
     private boolean setInputMethodEnabledLocked(String id, boolean enabled) {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
         if (enabled) {
-            final String enabledImeIdsStr = mSettings.getEnabledInputMethodsStr();
+            final String enabledImeIdsStr = settings.getEnabledInputMethodsStr();
             final String newEnabledImeIdsStr = InputMethodUtils.concatEnabledImeIds(
                     enabledImeIdsStr, id);
             if (TextUtils.equals(enabledImeIdsStr, newEnabledImeIdsStr)) {
@@ -5191,29 +5197,29 @@
                 // Nothing to do. The previous state was enabled.
                 return true;
             }
-            mSettings.putEnabledInputMethodsStr(newEnabledImeIdsStr);
+            settings.putEnabledInputMethodsStr(newEnabledImeIdsStr);
             // Previous state was disabled.
             return false;
         } else {
-            final List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
+            final List<Pair<String, ArrayList<String>>> enabledInputMethodsList = settings
                     .getEnabledInputMethodsAndSubtypeList();
             StringBuilder builder = new StringBuilder();
-            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingId(
+            if (settings.buildAndPutEnabledInputMethodsStrRemovingId(
                     builder, enabledInputMethodsList, id)) {
                 if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) {
                     // Disabled input method is currently selected, switch to another one.
-                    final String selId = mSettings.getSelectedInputMethod();
+                    final String selId = settings.getSelectedInputMethod();
                     if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
                         Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
                         resetSelectedInputMethodAndSubtypeLocked("");
                     }
-                } else if (id.equals(mSettings.getSelectedDefaultDeviceInputMethod())) {
+                } else if (id.equals(settings.getSelectedDefaultDeviceInputMethod())) {
                     // Disabled default device IME while using a virtual device one, choose a
                     // new default one but only update the settings.
                     InputMethodInfo newDefaultIme =
                             InputMethodInfoUtils.getMostApplicableDefaultIME(
-                                        mSettings.getEnabledInputMethodList());
-                    mSettings.putSelectedDefaultDeviceInputMethod(
+                                    settings.getEnabledInputMethodList());
+                    settings.putSelectedDefaultDeviceInputMethod(
                             newDefaultIme == null ? null : newDefaultIme.getId());
                 }
                 // Previous state was enabled.
@@ -5229,29 +5235,30 @@
     @GuardedBy("ImfLock.class")
     private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
             boolean setSubtypeOnly) {
-        mSettings.saveCurrentInputMethodAndSubtypeToHistory(getSelectedMethodIdLocked(),
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+        settings.saveCurrentInputMethodAndSubtypeToHistory(getSelectedMethodIdLocked(),
                 mCurrentSubtype);
 
         // Set Subtype here
         if (imi == null || subtypeId < 0) {
-            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
+            settings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
             mCurrentSubtype = null;
         } else {
             if (subtypeId < imi.getSubtypeCount()) {
                 InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
-                mSettings.putSelectedSubtype(subtype.hashCode());
+                settings.putSelectedSubtype(subtype.hashCode());
                 mCurrentSubtype = subtype;
             } else {
-                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
+                settings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
                 // If the subtype is not specified, choose the most applicable one
                 mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
             }
         }
-        notifyInputMethodSubtypeChangedLocked(mSettings.getUserId(), imi, mCurrentSubtype);
+        notifyInputMethodSubtypeChangedLocked(settings.getUserId(), imi, mCurrentSubtype);
 
         if (!setSubtypeOnly) {
             // Set InputMethod here
-            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
+            settings.putSelectedInputMethod(imi != null ? imi.getId() : "");
         }
     }
 
@@ -5259,13 +5266,15 @@
     private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
         mDeviceIdToShowIme = DEVICE_ID_DEFAULT;
         mDisplayIdToShowIme = INVALID_DISPLAY;
-        mSettings.putSelectedDefaultDeviceInputMethod(null);
 
-        InputMethodInfo imi = mSettings.getMethodMap().get(newDefaultIme);
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+        settings.putSelectedDefaultDeviceInputMethod(null);
+
+        InputMethodInfo imi = settings.getMethodMap().get(newDefaultIme);
         int lastSubtypeId = NOT_A_SUBTYPE_ID;
         // newDefaultIme is empty when there is no candidate for the selected IME.
         if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
-            String subtypeHashCode = mSettings.getLastSubtypeForInputMethod(newDefaultIme);
+            String subtypeHashCode = settings.getLastSubtypeForInputMethod(newDefaultIme);
             if (subtypeHashCode != null) {
                 try {
                     lastSubtypeId = SubtypeUtils.getSubtypeIdFromHashCode(imi,
@@ -5292,12 +5301,12 @@
                     Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
         }
         synchronized (ImfLock.class) {
-            if (mSettings.getUserId() == userId) {
+            if (mCurrentUserId == userId) {
                 return getCurrentInputMethodSubtypeLocked();
             }
 
-            final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
-            return settings.getCurrentInputMethodSubtypeForNonCurrentUsers();
+            return InputMethodSettingsRepository.get(userId)
+                    .getCurrentInputMethodSubtypeForNonCurrentUsers();
         }
     }
 
@@ -5317,26 +5326,27 @@
         if (selectedMethodId == null) {
             return null;
         }
-        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
-        final InputMethodInfo imi = mSettings.getMethodMap().get(selectedMethodId);
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+        final boolean subtypeIsSelected = settings.isSubtypeSelected();
+        final InputMethodInfo imi = settings.getMethodMap().get(selectedMethodId);
         if (imi == null || imi.getSubtypeCount() == 0) {
             return null;
         }
         if (!subtypeIsSelected || mCurrentSubtype == null
                 || !SubtypeUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
-            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(selectedMethodId);
+            int subtypeId = settings.getSelectedInputMethodSubtypeId(selectedMethodId);
             if (subtypeId == NOT_A_SUBTYPE_ID) {
                 // If there are no selected subtypes, the framework will try to find
                 // the most applicable subtype from explicitly or implicitly enabled
                 // subtypes.
                 List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
-                        mSettings.getEnabledInputMethodSubtypeList(imi, true);
+                        settings.getEnabledInputMethodSubtypeList(imi, true);
                 // If there is only one explicitly or implicitly enabled subtype,
                 // just returns it.
                 if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
                     mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
                 } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
-                    final String locale = SystemLocaleWrapper.get(mSettings.getUserId())
+                    final String locale = SystemLocaleWrapper.get(settings.getUserId())
                             .get(0).toString();
                     mCurrentSubtype = SubtypeUtils.findLastResortApplicableSubtype(
                             explicitlyOrImplicitlyEnabledSubtypes,
@@ -5359,38 +5369,22 @@
      */
     @GuardedBy("ImfLock.class")
     private InputMethodInfo queryDefaultInputMethodForUserIdLocked(@UserIdInt int userId) {
-        final InputMethodSettings settings;
-        if (userId == mSettings.getUserId()) {
-            settings = mSettings;
-        } else {
-            final AdditionalSubtypeMap additionalSubtypeMap =
-                    AdditionalSubtypeMapRepository.get(userId);
-            settings = queryInputMethodServicesInternal(mContext, userId,
-                    additionalSubtypeMap, DirectBootAwareness.AUTO);
-        }
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
         return settings.getMethodMap().get(settings.getSelectedInputMethod());
     }
 
     @GuardedBy("ImfLock.class")
-    private InputMethodSettings queryMethodMapForUserLocked(@UserIdInt int userId) {
-        final AdditionalSubtypeMap additionalSubtypeMap =
-                AdditionalSubtypeMapRepository.get(userId);
-        return queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
-                DirectBootAwareness.AUTO);
-    }
-
-    @GuardedBy("ImfLock.class")
     private boolean switchToInputMethodLocked(String imeId, @UserIdInt int userId) {
-        if (userId == mSettings.getUserId()) {
-            if (!mSettings.getMethodMap().containsKey(imeId)
-                    || !mSettings.getEnabledInputMethodList()
-                    .contains(mSettings.getMethodMap().get(imeId))) {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
+        if (userId == mCurrentUserId) {
+            if (!settings.getMethodMap().containsKey(imeId)
+                    || !settings.getEnabledInputMethodList()
+                    .contains(settings.getMethodMap().get(imeId))) {
                 return false; // IME is not found or not enabled.
             }
             setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID);
             return true;
         }
-        final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
         if (!settings.getMethodMap().containsKey(imeId)
                 || !settings.getEnabledInputMethodList().contains(
                         settings.getMethodMap().get(imeId))) {
@@ -5431,8 +5425,9 @@
 
     @GuardedBy("ImfLock.class")
     private void switchKeyboardLayoutLocked(int direction) {
-        final InputMethodInfo currentImi = mSettings.getMethodMap().get(
-                getSelectedMethodIdLocked());
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
+
+        final InputMethodInfo currentImi = settings.getMethodMap().get(getSelectedMethodIdLocked());
         if (currentImi == null) {
             return;
         }
@@ -5444,7 +5439,7 @@
         if (nextSubtypeHandle == null) {
             return;
         }
-        final InputMethodInfo nextImi = mSettings.getMethodMap().get(nextSubtypeHandle.getImeId());
+        final InputMethodInfo nextImi = settings.getMethodMap().get(nextSubtypeHandle.getImeId());
         if (nextImi == null) {
             return;
         }
@@ -5523,17 +5518,14 @@
         @Override
         public boolean setInputMethodEnabled(String imeId, boolean enabled, @UserIdInt int userId) {
             synchronized (ImfLock.class) {
-                if (userId == mSettings.getUserId()) {
-                    if (!mSettings.getMethodMap().containsKey(imeId)) {
-                        return false; // IME is not found.
-                    }
-                    setInputMethodEnabledLocked(imeId, enabled);
-                    return true;
-                }
-                final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
+                final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
                 if (!settings.getMethodMap().containsKey(imeId)) {
                     return false; // IME is not found.
                 }
+                if (userId == mCurrentUserId) {
+                    setInputMethodEnabledLocked(imeId, enabled);
+                    return true;
+                }
                 if (enabled) {
                     final String enabledImeIdsStr = settings.getEnabledInputMethodsStr();
                     final String newEnabledImeIdsStr = InputMethodUtils.concatEnabledImeIds(
@@ -5844,7 +5836,7 @@
 
     @BinderThread
     @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
         PriorityDump.dump(mPriorityDumper, fd, pw, args);
@@ -5860,8 +5852,9 @@
         final Printer p = new PrintWriterPrinter(pw);
 
         synchronized (ImfLock.class) {
+            final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
             p.println("Current Input Method Manager state:");
-            final List<InputMethodInfo> methodList = mSettings.getMethodList();
+            final List<InputMethodInfo> methodList = settings.getMethodList();
             int numImes = methodList.size();
             p.println("  Input Methods: mMethodMapUpdateCount=" + mMethodMapUpdateCount);
             for (int i = 0; i < numImes; i++) {
@@ -5875,6 +5868,7 @@
             @SuppressWarnings("GuardedBy") Consumer<ClientState> clientControllerDump = c -> {
                 p.println("  " + c + ":");
                 p.println("    client=" + c.mClient);
+
                 p.println("    fallbackInputConnection="
                         + c.mFallbackInputConnection);
                 p.println("    sessionRequested="
@@ -5883,8 +5877,12 @@
                         "    sessionRequestedForAccessibility="
                                 + c.mSessionRequestedForAccessibility);
                 p.println("    curSession=" + c.mCurSession);
+                p.println("    selfReportedDisplayId=" + c.mSelfReportedDisplayId);
+                p.println("    uid=" + c.mUid);
+                p.println("    pid=" + c.mPid);
             };
             mClientController.forAllClients(clientControllerDump);
+            p.println("  mCurrentUserId=" + mCurrentUserId);
             p.println("  mCurMethodId=" + getSelectedMethodIdLocked());
             client = mCurClient;
             p.println("  mCurClient=" + client + " mCurSeq=" + getSequenceNumberLocked());
@@ -5910,8 +5908,6 @@
                     ? Arrays.toString(mStylusIds.toArray()) : ""));
             p.println("  mSwitchingController:");
             mSwitchingController.dump(p);
-            p.println("  mSettings:");
-            mSettings.dump(p, "    ");
 
             p.println("  mStartInputHistory:");
             mStartInputHistory.dump(pw, "    ");
@@ -5974,7 +5970,7 @@
     public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
             @Nullable FileDescriptor err,
             @NonNull String[] args, @Nullable ShellCallback callback,
-            @NonNull ResultReceiver resultReceiver) throws RemoteException {
+            @NonNull ResultReceiver resultReceiver, @NonNull Binder self) {
         final int callingUid = Binder.getCallingUid();
         // Reject any incoming calls from non-shell users, including ones from the system user.
         if (callingUid != Process.ROOT_UID && callingUid != Process.SHELL_UID) {
@@ -5995,7 +5991,7 @@
             throw new SecurityException(errorMsg);
         }
         new ShellCommandImpl(this).exec(
-                this, in, out, err, args, callback, resultReceiver);
+                self, in, out, err, args, callback, resultReceiver);
     }
 
     private static final class ShellCommandImpl extends ShellCommand {
@@ -6166,7 +6162,7 @@
         }
         synchronized (ImfLock.class) {
             final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
-                    mSettings.getUserId(), shellCommand.getErrPrintWriter());
+                    mCurrentUserId, shellCommand.getErrPrintWriter());
             try (PrintWriter pr = shellCommand.getOutPrintWriter()) {
                 for (int userId : userIds) {
                     final List<InputMethodInfo> methods = all
@@ -6211,7 +6207,7 @@
              PrintWriter error = shellCommand.getErrPrintWriter()) {
             synchronized (ImfLock.class) {
                 final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
-                        mSettings.getUserId(), shellCommand.getErrPrintWriter());
+                        mCurrentUserId, shellCommand.getErrPrintWriter());
                 for (int userId : userIds) {
                     if (!userHasDebugPriv(userId, shellCommand)) {
                         continue;
@@ -6270,14 +6266,14 @@
             PrintWriter error) {
         boolean failedToEnableUnknownIme = false;
         boolean previouslyEnabled = false;
-        if (userId == mSettings.getUserId()) {
-            if (enabled && !mSettings.getMethodMap().containsKey(imeId)) {
+        final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
+        if (userId == mCurrentUserId) {
+            if (enabled && !settings.getMethodMap().containsKey(imeId)) {
                 failedToEnableUnknownIme = true;
             } else {
                 previouslyEnabled = setInputMethodEnabledLocked(imeId, enabled);
             }
         } else {
-            final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
             if (enabled) {
                 if (!settings.getMethodMap().containsKey(imeId)) {
                     failedToEnableUnknownIme = true;
@@ -6332,7 +6328,7 @@
              PrintWriter error = shellCommand.getErrPrintWriter()) {
             synchronized (ImfLock.class) {
                 final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
-                        mSettings.getUserId(), shellCommand.getErrPrintWriter());
+                        mCurrentUserId, shellCommand.getErrPrintWriter());
                 for (int userId : userIds) {
                     if (!userHasDebugPriv(userId, shellCommand)) {
                         continue;
@@ -6372,7 +6368,7 @@
         synchronized (ImfLock.class) {
             try (PrintWriter out = shellCommand.getOutPrintWriter()) {
                 final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
-                        mSettings.getUserId(), shellCommand.getErrPrintWriter());
+                        mCurrentUserId, shellCommand.getErrPrintWriter());
                 for (int userId : userIds) {
                     if (!userHasDebugPriv(userId, shellCommand)) {
                         continue;
@@ -6384,15 +6380,16 @@
                     }
                     final String nextIme;
                     final List<InputMethodInfo> nextEnabledImes;
-                    if (userId == mSettings.getUserId()) {
+                    final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
+                    if (userId == mCurrentUserId) {
                         hideCurrentInputLocked(mImeBindingState.mFocusedWindow, 0 /* flags */,
                                 SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
                         mBindingController.unbindCurrentMethod();
 
                         // Enable default IMEs, disable others
-                        var toDisable = mSettings.getEnabledInputMethodList();
+                        var toDisable = settings.getEnabledInputMethodList();
                         var defaultEnabled = InputMethodInfoUtils.getDefaultEnabledImes(
-                                mContext, mSettings.getMethodList());
+                                mContext, settings.getMethodList());
                         toDisable.removeAll(defaultEnabled);
                         for (InputMethodInfo info : toDisable) {
                             setInputMethodEnabledLocked(info.getId(), false);
@@ -6406,16 +6403,11 @@
                         }
                         updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
                         InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
-                                getPackageManagerForUser(mContext, mSettings.getUserId()),
-                                mSettings.getEnabledInputMethodList());
-                        nextIme = mSettings.getSelectedInputMethod();
-                        nextEnabledImes = mSettings.getEnabledInputMethodList();
+                                getPackageManagerForUser(mContext, settings.getUserId()),
+                                settings.getEnabledInputMethodList());
+                        nextIme = settings.getSelectedInputMethod();
+                        nextEnabledImes = settings.getEnabledInputMethodList();
                     } else {
-                        final AdditionalSubtypeMap additionalSubtypeMap =
-                                AdditionalSubtypeMapRepository.get(userId);
-                        final InputMethodSettings settings = queryInputMethodServicesInternal(
-                                mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO);
-
                         nextEnabledImes = InputMethodInfoUtils.getDefaultEnabledImes(mContext,
                                 settings.getMethodList());
                         nextIme = InputMethodInfoUtils.getMostApplicableDefaultIME(
@@ -6556,6 +6548,12 @@
 
         @BinderThread
         @Override
+        public void setHandwritingSurfaceNotTouchable(boolean notTouchable) {
+            mImms.mHwController.setNotTouchable(notTouchable);
+        }
+
+        @BinderThread
+        @Override
         public void createInputContentUriToken(Uri contentUri, String packageName,
                 AndroidFuture future /* T=IBinder */) {
             @SuppressWarnings("unchecked")
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java b/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java
new file mode 100644
index 0000000..60b9a4c
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSettingsRepository.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.Handler;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.DirectBootAwareness;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+final class InputMethodSettingsRepository {
+    @GuardedBy("ImfLock.class")
+    @NonNull
+    private static final SparseArray<InputMethodSettings> sPerUserMap = new SparseArray<>();
+
+    /**
+     * Not intended to be instantiated.
+     */
+    private InputMethodSettingsRepository() {
+    }
+
+    @NonNull
+    @GuardedBy("ImfLock.class")
+    static InputMethodSettings get(@UserIdInt int userId) {
+        final InputMethodSettings obj = sPerUserMap.get(userId);
+        if (obj != null) {
+            return obj;
+        }
+        return InputMethodSettings.createEmptyMap(userId);
+    }
+
+    @GuardedBy("ImfLock.class")
+    static void put(@UserIdInt int userId, @NonNull InputMethodSettings obj) {
+        sPerUserMap.put(userId, obj);
+    }
+
+    static void initialize(@NonNull Handler handler, @NonNull Context context) {
+        final UserManagerInternal userManagerInternal =
+                LocalServices.getService(UserManagerInternal.class);
+        handler.post(() -> {
+            userManagerInternal.addUserLifecycleListener(
+                    new UserManagerInternal.UserLifecycleListener() {
+                        @Override
+                        public void onUserRemoved(UserInfo user) {
+                            final int userId = user.id;
+                            handler.post(() -> {
+                                synchronized (ImfLock.class) {
+                                    sPerUserMap.remove(userId);
+                                }
+                            });
+                        }
+                    });
+            synchronized (ImfLock.class) {
+                for (int userId : userManagerInternal.getUserIds()) {
+                    final InputMethodSettings settings =
+                            InputMethodManagerService.queryInputMethodServicesInternal(
+                                    context,
+                                    userId,
+                                    AdditionalSubtypeMapRepository.get(userId),
+                                    DirectBootAwareness.AUTO);
+                    sPerUserMap.put(userId, settings);
+                }
+            }
+        });
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/UserDataRepository.java b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
new file mode 100644
index 0000000..7f00229
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/UserDataRepository.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.pm.UserInfo;
+import android.os.Handler;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.pm.UserManagerInternal;
+
+import java.util.function.Consumer;
+
+final class UserDataRepository {
+
+    @GuardedBy("ImfLock.class")
+    private final SparseArray<UserData> mUserData = new SparseArray<>();
+
+    @GuardedBy("ImfLock.class")
+    @NonNull
+    UserData getOrCreate(@UserIdInt int userId) {
+        UserData userData = mUserData.get(userId);
+        if (userData == null) {
+            userData = new UserData(userId);
+            mUserData.put(userId, userData);
+        }
+        return userData;
+    }
+
+    @GuardedBy("ImfLock.class")
+    void forAllUserData(Consumer<UserData> consumer) {
+        for (int i = 0; i < mUserData.size(); i++) {
+            consumer.accept(mUserData.valueAt(i));
+        }
+    }
+
+    UserDataRepository(@NonNull Handler handler, @NonNull UserManagerInternal userManagerInternal) {
+        userManagerInternal.addUserLifecycleListener(
+                new UserManagerInternal.UserLifecycleListener() {
+                    @Override
+                    public void onUserRemoved(UserInfo user) {
+                        final int userId = user.id;
+                        handler.post(() -> {
+                            synchronized (ImfLock.class) {
+                                mUserData.remove(userId);
+                            }
+                        });
+                    }
+
+                    @Override
+                    public void onUserCreated(UserInfo user, Object unusedToken) {
+                        final int userId = user.id;
+                        handler.post(() -> {
+                            synchronized (ImfLock.class) {
+                                getOrCreate(userId);
+                            }
+                        });
+                    }
+                });
+    }
+
+    /** Placeholder for all IMMS user specific fields */
+    static final class UserData {
+        @UserIdInt
+        final int mUserId;
+
+       /**
+         * Intended to be instantiated only from this file.
+         */
+        private UserData(@UserIdInt int userId) {
+            mUserId = userId;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
index 31ce630..1cd1ddc 100644
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
@@ -36,17 +36,16 @@
 
 import android.Manifest;
 import android.annotation.BinderThread;
-import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.UserIdInt;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.util.Slog;
+import android.view.MotionEvent;
 import android.view.WindowManager;
 import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
@@ -56,6 +55,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 import android.window.ImeOnBackInvokedDispatcher;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.DirectBootAwareness;
 import com.android.internal.inputmethod.IBooleanListener;
 import com.android.internal.inputmethod.IConnectionlessHandwritingCallback;
@@ -76,22 +76,25 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
-import java.util.function.BooleanSupplier;
 
 /**
  * A proxy that processes all {@link IInputMethodManager} calls asynchronously.
- * @hide
  */
-public class ZeroJankProxy extends IInputMethodManager.Stub {
+final class ZeroJankProxy implements IInputMethodManagerImpl.Callback {
 
-    private final IInputMethodManager mInner;
+    interface Callback extends IInputMethodManagerImpl.Callback {
+        @GuardedBy("ImfLock.class")
+        ClientState getClientStateLocked(IInputMethodClient client);
+        @GuardedBy("ImfLock.class")
+        boolean isInputShownLocked();
+    }
+
+    private final Callback mInner;
     private final Executor mExecutor;
-    private final BooleanSupplier mIsInputShown;
 
-    ZeroJankProxy(Executor executor, IInputMethodManager inner, BooleanSupplier isInputShown) {
+    ZeroJankProxy(Executor executor, Callback inner) {
         mInner = inner;
         mExecutor = executor;
-        mIsInputShown = isInputShown;
     }
 
     private void offload(ThrowingRunnable r) {
@@ -126,45 +129,43 @@
 
     @Override
     public void addClient(IInputMethodClient client, IRemoteInputConnection inputConnection,
-            int selfReportedDisplayId) throws RemoteException {
+            int selfReportedDisplayId) {
         offload(() -> mInner.addClient(client, inputConnection, selfReportedDisplayId));
     }
 
     @Override
-    public InputMethodInfo getCurrentInputMethodInfoAsUser(int userId) throws RemoteException {
+    public InputMethodInfo getCurrentInputMethodInfoAsUser(int userId) {
         return mInner.getCurrentInputMethodInfoAsUser(userId);
     }
 
     @Override
     public List<InputMethodInfo> getInputMethodList(
-            int userId, @DirectBootAwareness int directBootAwareness) throws RemoteException {
+            int userId, @DirectBootAwareness int directBootAwareness) {
         return mInner.getInputMethodList(userId, directBootAwareness);
     }
 
     @Override
-    public List<InputMethodInfo> getEnabledInputMethodList(int userId) throws RemoteException {
+    public List<InputMethodInfo> getEnabledInputMethodList(int userId) {
         return mInner.getEnabledInputMethodList(userId);
     }
 
     @Override
     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
-            boolean allowsImplicitlyEnabledSubtypes, int userId)
-            throws RemoteException {
+            boolean allowsImplicitlyEnabledSubtypes, int userId) {
         return mInner.getEnabledInputMethodSubtypeList(imiId, allowsImplicitlyEnabledSubtypes,
                 userId);
     }
 
     @Override
-    public InputMethodSubtype getLastInputMethodSubtype(int userId) throws RemoteException {
+    public InputMethodSubtype getLastInputMethodSubtype(int userId) {
         return mInner.getLastInputMethodSubtype(userId);
     }
 
     @Override
     public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
             @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
-            int lastClickTooType, ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason)
-            throws RemoteException {
+            @MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
+            @SoftInputShowHideReason int reason) {
         offload(
                 () -> {
                     if (!mInner.showSoftInput(
@@ -172,7 +173,7 @@
                             windowToken,
                             statsToken,
                             flags,
-                            lastClickTooType,
+                            lastClickToolType,
                             resultReceiver,
                             reason)) {
                         sendResultReceiverFailure(resultReceiver);
@@ -184,8 +185,7 @@
     @Override
     public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
             @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
-            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason)
-            throws RemoteException {
+            ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
         offload(
                 () -> {
                     if (!mInner.hideSoftInput(
@@ -196,18 +196,23 @@
         return true;
     }
 
-    private void sendResultReceiverFailure(ResultReceiver resultReceiver) {
-        resultReceiver.send(
-                mIsInputShown.getAsBoolean()
+    private void sendResultReceiverFailure(@Nullable ResultReceiver resultReceiver) {
+        if (resultReceiver == null) {
+            return;
+        }
+        final boolean isInputShown;
+        synchronized (ImfLock.class) {
+            isInputShown = mInner.isInputShownLocked();
+        }
+        resultReceiver.send(isInputShown
                         ? InputMethodManager.RESULT_UNCHANGED_SHOWN
                         : InputMethodManager.RESULT_UNCHANGED_HIDDEN,
                 null);
     }
 
     @Override
-    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
-    public void hideSoftInputFromServerForTest() throws RemoteException {
-        super.hideSoftInputFromServerForTest_enforcePermission();
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
+    public void hideSoftInputFromServerForTest() {
         mInner.hideSoftInputFromServerForTest();
     }
 
@@ -222,8 +227,7 @@
             IRemoteInputConnection inputConnection,
             IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq)
-            throws RemoteException {
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher, int startInputSeq) {
         offload(() -> {
             InputBindResult result = mInner.startInputOrWindowGainedFocus(startInputReason, client,
                     windowToken, startInputFlags, softInputMode, windowFlags,
@@ -246,99 +250,92 @@
             IRemoteInputConnection inputConnection,
             IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher)
-            throws RemoteException {
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         // Should never be called when flag is enabled i.e. when this proxy is used.
         return null;
     }
 
     @Override
     public void showInputMethodPickerFromClient(IInputMethodClient client,
-            int auxiliarySubtypeMode)
-            throws RemoteException {
+            int auxiliarySubtypeMode) {
         offload(() -> mInner.showInputMethodPickerFromClient(client, auxiliarySubtypeMode));
     }
 
-    @EnforcePermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
-    public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId)
-            throws RemoteException {
+    public void showInputMethodPickerFromSystem(int auxiliarySubtypeMode, int displayId) {
         mInner.showInputMethodPickerFromSystem(auxiliarySubtypeMode, displayId);
     }
 
-    @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
     @Override
-    public boolean isInputMethodPickerShownForTest() throws RemoteException {
-        super.isInputMethodPickerShownForTest_enforcePermission();
+    public boolean isInputMethodPickerShownForTest() {
         return mInner.isInputMethodPickerShownForTest();
     }
 
     @Override
-    public InputMethodSubtype getCurrentInputMethodSubtype(int userId) throws RemoteException {
+    public InputMethodSubtype getCurrentInputMethodSubtype(int userId) {
         return mInner.getCurrentInputMethodSubtype(userId);
     }
 
     @Override
     public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes,
-            @UserIdInt int userId) throws RemoteException {
+            @UserIdInt int userId) {
         mInner.setAdditionalInputMethodSubtypes(imiId, subtypes, userId);
     }
 
     @Override
     public void setExplicitlyEnabledInputMethodSubtypes(String imeId,
-            @NonNull int[] subtypeHashCodes, @UserIdInt int userId) throws RemoteException {
+            @NonNull int[] subtypeHashCodes, @UserIdInt int userId) {
         mInner.setExplicitlyEnabledInputMethodSubtypes(imeId, subtypeHashCodes, userId);
     }
 
     @Override
-    public int getInputMethodWindowVisibleHeight(IInputMethodClient client)
-            throws RemoteException {
+    public int getInputMethodWindowVisibleHeight(IInputMethodClient client) {
         return mInner.getInputMethodWindowVisibleHeight(client);
     }
 
     @Override
-    public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible)
-            throws RemoteException {
+    public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
         // Already async TODO(b/293640003): ordering issues?
         mInner.reportPerceptibleAsync(windowToken, perceptible);
     }
 
-    @EnforcePermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
     @Override
-    public void removeImeSurface() throws RemoteException {
+    public void removeImeSurface() {
         mInner.removeImeSurface();
     }
 
     @Override
-    public void removeImeSurfaceFromWindowAsync(IBinder windowToken) throws RemoteException {
+    public void removeImeSurfaceFromWindowAsync(IBinder windowToken) {
         mInner.removeImeSurfaceFromWindowAsync(windowToken);
     }
 
     @Override
-    public void startProtoDump(byte[] bytes, int i, String s) throws RemoteException {
+    public void startProtoDump(byte[] bytes, int i, String s) {
         mInner.startProtoDump(bytes, i, s);
     }
 
     @Override
-    public boolean isImeTraceEnabled() throws RemoteException {
+    public boolean isImeTraceEnabled() {
         return mInner.isImeTraceEnabled();
     }
 
-    @EnforcePermission(Manifest.permission.CONTROL_UI_TRACING)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.CONTROL_UI_TRACING)
     @Override
-    public void startImeTrace() throws RemoteException {
+    public void startImeTrace() {
         mInner.startImeTrace();
     }
 
-    @EnforcePermission(Manifest.permission.CONTROL_UI_TRACING)
+    @IInputMethodManagerImpl.PermissionVerified(Manifest.permission.CONTROL_UI_TRACING)
     @Override
-    public void stopImeTrace() throws RemoteException {
+    public void stopImeTrace() {
         mInner.stopImeTrace();
     }
 
     @Override
-    public void startStylusHandwriting(IInputMethodClient client)
-            throws RemoteException {
+    public void startStylusHandwriting(IInputMethodClient client) {
         offload(() -> mInner.startStylusHandwriting(client));
     }
 
@@ -346,7 +343,7 @@
     public void startConnectionlessStylusHandwriting(IInputMethodClient client, int userId,
             @Nullable CursorAnchorInfo cursorAnchorInfo, @Nullable String delegatePackageName,
             @Nullable String delegatorPackageName,
-            @NonNull IConnectionlessHandwritingCallback callback) throws RemoteException {
+            @NonNull IConnectionlessHandwritingCallback callback) {
         offload(() -> mInner.startConnectionlessStylusHandwriting(
                 client, userId, cursorAnchorInfo, delegatePackageName, delegatorPackageName,
                 callback));
@@ -360,14 +357,11 @@
             @NonNull String delegatorPackageName,
             @InputMethodManager.HandwritingDelegateFlags int flags) {
         try {
-            return CompletableFuture.supplyAsync(() -> {
-                try {
-                    return mInner.acceptStylusHandwritingDelegation(
-                            client, userId, delegatePackageName, delegatorPackageName, flags);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
-            }, this::offload).get();
+            return CompletableFuture.supplyAsync(() ->
+                            mInner.acceptStylusHandwritingDelegation(
+                                    client, userId, delegatePackageName, delegatorPackageName,
+                                    flags),
+                    this::offload).get();
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         } catch (ExecutionException e) {
@@ -381,8 +375,7 @@
             @UserIdInt int userId,
             @NonNull String delegatePackageName,
             @NonNull String delegatorPackageName,
-            @InputMethodManager.HandwritingDelegateFlags int flags, IBooleanListener callback)
-            throws RemoteException {
+            @InputMethodManager.HandwritingDelegateFlags int flags, IBooleanListener callback) {
         offload(() -> mInner.acceptStylusHandwritingDelegationAsync(
                 client, userId, delegatePackageName, delegatorPackageName, flags, callback));
     }
@@ -398,52 +391,45 @@
     }
 
     @Override
-    public boolean isStylusHandwritingAvailableAsUser(int userId, boolean connectionless)
-            throws RemoteException {
+    public boolean isStylusHandwritingAvailableAsUser(int userId, boolean connectionless) {
         return mInner.isStylusHandwritingAvailableAsUser(userId, connectionless);
     }
 
-    @EnforcePermission("android.permission.TEST_INPUT_METHOD")
+    @IInputMethodManagerImpl.PermissionVerified("android.permission.TEST_INPUT_METHOD")
     @Override
-    public void addVirtualStylusIdForTestSession(IInputMethodClient client)
-            throws RemoteException {
+    public void addVirtualStylusIdForTestSession(IInputMethodClient client) {
         mInner.addVirtualStylusIdForTestSession(client);
     }
 
-    @EnforcePermission("android.permission.TEST_INPUT_METHOD")
+    @IInputMethodManagerImpl.PermissionVerified("android.permission.TEST_INPUT_METHOD")
     @Override
-    public void setStylusWindowIdleTimeoutForTest(IInputMethodClient client, long timeout)
-            throws RemoteException {
+    public void setStylusWindowIdleTimeoutForTest(IInputMethodClient client, long timeout) {
         mInner.setStylusWindowIdleTimeoutForTest(client, timeout);
     }
 
     @Override
-    public IImeTracker getImeTrackerService() throws RemoteException {
+    public IImeTracker getImeTrackerService() {
         return mInner.getImeTrackerService();
     }
 
     @BinderThread
     @Override
     public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
-            @Nullable FileDescriptor err,
-            @NonNull String[] args, @Nullable ShellCallback callback,
-            @NonNull ResultReceiver resultReceiver) throws RemoteException {
-        ((InputMethodManagerService) mInner).onShellCommand(
-                in, out, err, args, callback, resultReceiver);
+            @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback,
+            @NonNull ResultReceiver resultReceiver, @NonNull Binder self) {
+        mInner.onShellCommand(in, out, err, args, callback, resultReceiver, self);
     }
 
     @Override
-    protected void dump(@NonNull FileDescriptor fd,
-            @NonNull PrintWriter fout,
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
             @Nullable String[] args) {
-        ((InputMethodManagerService) mInner).dump(fd, fout, args);
+        mInner.dump(fd, fout, args);
     }
 
     private void sendOnStartInputResult(
             IInputMethodClient client, InputBindResult res, int startInputSeq) {
         synchronized (ImfLock.class) {
-            InputMethodManagerService service = (InputMethodManagerService) mInner;
-            final ClientState cs = service.getClientState(client);
+            final ClientState cs = mInner.getClientStateLocked(client);
             if (cs != null && cs.mClient != null) {
                 cs.mClient.onStartInputResult(res, startInputSeq);
             } else {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
index b18871c..a0dbfa0 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
@@ -28,6 +28,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Random;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -77,9 +78,12 @@
     private final AtomicInteger mNextAvailableId = new AtomicInteger();
 
     /**
-     * The next available message sequence number
+     * The next available message sequence number. We choose a random
+     * number to start with to avoid collisions and limit the bound to
+     * half of the max value to avoid overflow.
      */
-    private final AtomicInteger mNextAvailableMessageSequenceNumber = new AtomicInteger();
+    private final AtomicInteger mNextAvailableMessageSequenceNumber =
+            new AtomicInteger(new Random().nextInt(Integer.MAX_VALUE / 2));
 
     /*
      * An executor and the future object for scheduling timeout timers
diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
index 71a9f54..8002300 100644
--- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
@@ -18,6 +18,7 @@
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 
+import android.annotation.RequiresPermission;
 import android.content.Context;
 import android.location.flags.Flags;
 import android.net.ConnectivityManager;
@@ -32,12 +33,14 @@
 import android.os.PowerManager;
 import android.telephony.PhoneStateListener;
 import android.telephony.PreciseCallState;
+import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.server.FgThread;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -200,7 +203,12 @@
 
         SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
         if (subManager != null) {
-            subManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+            if (Flags.subscriptionsListenerThread()) {
+                subManager.addOnSubscriptionsChangedListener(FgThread.getExecutor(),
+                        mOnSubscriptionsChangeListener);
+            } else {
+                subManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+            }
         }
 
         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -566,6 +574,10 @@
         }
     }
 
+    @RequiresPermission(allOf = {
+        android.Manifest.permission.ACCESS_COARSE_LOCATION,
+        android.Manifest.permission.READ_PHONE_STATE
+    })
     private void handleRequestSuplConnection(int agpsType, byte[] suplIpAddr) {
         mAGpsDataConnectionIpAddr = null;
         mAGpsType = agpsType;
@@ -599,6 +611,19 @@
         NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
         networkRequestBuilder.addCapability(getNetworkCapability(mAGpsType));
         networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+
+        if (com.android.internal.telephony.flags.Flags.satelliteInternet()) {
+            // Add transport type NetworkCapabilities.TRANSPORT_SATELLITE on satellite network.
+            TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+            if (telephonyManager != null) {
+                ServiceState state = telephonyManager.getServiceState();
+                if (state != null && state.isUsingNonTerrestrialNetwork()) {
+                    networkRequestBuilder.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+                    networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+                }
+            }
+        }
+
         // During an emergency call, and when we have cached the Active Sub Id, we set the
         // Network Specifier so that the network request goes to the correct Sub Id
         if (mNiHandler.getInEmergency() && mActiveSubId >= 0) {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c80f988..dbdb155 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -102,12 +102,14 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.ICeStorageLockEventListener;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.security.AndroidKeyStoreMaintenance;
-import android.security.Authorization;
+import android.security.KeyStoreAuthorization;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
 import android.security.keystore.recovery.KeyChainProtectionParams;
@@ -293,6 +295,7 @@
     private final SyntheticPasswordManager mSpManager;
 
     private final KeyStore mKeyStore;
+    private final KeyStoreAuthorization mKeyStoreAuthorization;
     private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
     private final UnifiedProfilePasswordCache mUnifiedProfilePasswordCache;
 
@@ -337,6 +340,8 @@
     private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners =
             new CopyOnWriteArrayList<>();
 
+    private final StorageManagerInternal mStorageManagerInternal;
+
     // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
     // devices. The most basic of these is to show/hide notifications about missing features until
     // the user unlocks the account and credential-encrypted storage is available.
@@ -576,6 +581,10 @@
             return null;
         }
 
+        public StorageManagerInternal getStorageManagerInternal() {
+            return LocalServices.getService(StorageManagerInternal.class);
+        }
+
         public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
             return new SyntheticPasswordManager(getContext(), storage, getUserManager(),
                     new PasswordSlotManager());
@@ -627,6 +636,10 @@
             }
         }
 
+        public KeyStoreAuthorization getKeyStoreAuthorization() {
+            return KeyStoreAuthorization.getInstance();
+        }
+
         public @NonNull UnifiedProfilePasswordCache getUnifiedProfilePasswordCache(KeyStore ks) {
             return new UnifiedProfilePasswordCache(ks);
         }
@@ -650,6 +663,7 @@
         mInjector = injector;
         mContext = injector.getContext();
         mKeyStore = injector.getKeyStore();
+        mKeyStoreAuthorization = injector.getKeyStoreAuthorization();
         mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager();
         mHandler = injector.getHandler(injector.getServiceThread());
         mStrongAuth = injector.getStrongAuth();
@@ -666,6 +680,7 @@
         mNotificationManager = injector.getNotificationManager();
         mUserManager = injector.getUserManager();
         mStorageManager = injector.getStorageManager();
+        mStorageManagerInternal = injector.getStorageManagerInternal();
         mStrongAuthTracker = injector.getStrongAuthTracker();
         mStrongAuthTracker.register(mStrongAuth);
         mGatekeeperPasswords = new LongSparseArray<>();
@@ -919,8 +934,39 @@
         mStorage.prefetchUser(UserHandle.USER_SYSTEM);
         mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(),
                 mInjector.getFaceManager(), mInjector.getBiometricManager());
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
+            mStorageManagerInternal.registerStorageLockEventListener(mCeStorageLockEventListener);
+        }
     }
 
+    private final ICeStorageLockEventListener mCeStorageLockEventListener =
+            new ICeStorageLockEventListener() {
+                @Override
+                public void onStorageLocked(int userId) {
+                    Slog.i(TAG, "Storage lock event received for " + userId);
+                    if (android.os.Flags.allowPrivateProfile()
+                            && android.multiuser.Flags.enablePrivateSpaceFeatures()
+                            && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
+                        mHandler.post(() -> {
+                            try {
+                                UserProperties userProperties =
+                                        mUserManager.getUserProperties(UserHandle.of(userId));
+                                if (userProperties != null && userProperties
+                                        .getAllowStoppingUserWithDelayedLocking()) {
+                                    int strongAuthRequired = LockPatternUtils.StrongAuthTracker
+                                            .getDefaultFlags(mContext);
+                                    requireStrongAuth(strongAuthRequired, userId);
+                                }
+                            } catch (IllegalArgumentException e) {
+                                Slogf.d(TAG, "User %d does not exist or has been removed",
+                                        userId);
+                            }
+                        });
+                    }
+                }};
+
     private void loadEscrowData() {
         mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler);
     }
@@ -1460,7 +1506,7 @@
     }
 
     private void unlockKeystore(int userId, SyntheticPassword sp) {
-        Authorization.onDeviceUnlocked(userId, sp.deriveKeyStorePassword());
+        mKeyStoreAuthorization.onDeviceUnlocked(userId, sp.deriveKeyStorePassword());
     }
 
     @VisibleForTesting /** Note: this method is overridden in unit tests */
diff --git a/services/core/java/com/android/server/locksettings/TEST_MAPPING b/services/core/java/com/android/server/locksettings/TEST_MAPPING
index ddf3d76..256d9ba 100644
--- a/services/core/java/com/android/server/locksettings/TEST_MAPPING
+++ b/services/core/java/com/android/server/locksettings/TEST_MAPPING
@@ -24,5 +24,11 @@
                 }
             ]
         }
+    ],
+    "postsubmit": [
+        {
+            // TODO(b/332974906): Promote in presubmit-large.
+            "name": "CtsDevicePolicyManagerTestCases_LockSettings_NoFlakes"
+        }
     ]
 }
diff --git a/services/core/java/com/android/server/media/AudioManagerRouteController.java b/services/core/java/com/android/server/media/AudioManagerRouteController.java
index e7f717a..f27ade4 100644
--- a/services/core/java/com/android/server/media/AudioManagerRouteController.java
+++ b/services/core/java/com/android/server/media/AudioManagerRouteController.java
@@ -136,7 +136,7 @@
 
         mBluetoothRouteController =
                 new BluetoothDeviceRoutesManager(
-                        mContext, btAdapter, this::rebuildAvailableRoutesAndNotify);
+                        mContext, mHandler, btAdapter, this::rebuildAvailableRoutesAndNotify);
         // Just build routes but don't notify. The caller may not expect the listener to be invoked
         // before this constructor has finished executing.
         rebuildAvailableRoutes();
@@ -204,23 +204,24 @@
             Slog.w(TAG, "transferTo: Ignoring transfer request to unknown route id : " + routeId);
             return;
         }
-        // TODO: b/329929065 - Push audio manager and bluetooth operations to the handler, so that
-        // they don't run on a binder thread, so as to prevent possible deadlocks (these operations
-        // may need system_server binder threads to complete).
-        if (mediaRoute2InfoHolder.mCorrespondsToInactiveBluetoothRoute) {
-            // By default, the last connected device is the active route so we don't need to apply a
-            // routing audio policy.
-            mBluetoothRouteController.activateBluetoothDeviceWithAddress(
-                    mediaRoute2InfoHolder.mMediaRoute2Info.getAddress());
-            mAudioManager.removePreferredDeviceForStrategy(mStrategyForMedia);
-        } else {
-            AudioDeviceAttributes attr =
-                    new AudioDeviceAttributes(
-                            AudioDeviceAttributes.ROLE_OUTPUT,
-                            mediaRoute2InfoHolder.mAudioDeviceInfoType,
-                            /* address= */ ""); // This is not a BT device, hence no address needed.
-            mAudioManager.setPreferredDeviceForStrategy(mStrategyForMedia, attr);
-        }
+        Runnable transferAction = getTransferActionForRoute(mediaRoute2InfoHolder);
+        Runnable guardedTransferAction =
+                () -> {
+                    try {
+                        transferAction.run();
+                    } catch (Throwable throwable) {
+                        // We swallow the exception to avoid crashing system_server, since this
+                        // doesn't run on a binder thread.
+                        Slog.e(
+                                TAG,
+                                "Unexpected exception while transferring to route id: " + routeId,
+                                throwable);
+                        mHandler.post(this::rebuildAvailableRoutesAndNotify);
+                    }
+                };
+        // We post the transfer operation to the handler to avoid making these calls on a binder
+        // thread. See class javadoc for details.
+        mHandler.post(guardedTransferAction);
     }
 
     @RequiresPermission(
@@ -236,6 +237,28 @@
         return true;
     }
 
+    private Runnable getTransferActionForRoute(MediaRoute2InfoHolder mediaRoute2InfoHolder) {
+        if (mediaRoute2InfoHolder.mCorrespondsToInactiveBluetoothRoute) {
+            String deviceAddress = mediaRoute2InfoHolder.mMediaRoute2Info.getAddress();
+            return () -> {
+                // By default, the last connected device is the active route so we don't
+                // need to apply a routing audio policy.
+                mBluetoothRouteController.activateBluetoothDeviceWithAddress(deviceAddress);
+                mAudioManager.removePreferredDeviceForStrategy(mStrategyForMedia);
+            };
+
+        } else {
+            AudioDeviceAttributes deviceAttributes =
+                    new AudioDeviceAttributes(
+                            AudioDeviceAttributes.ROLE_OUTPUT,
+                            mediaRoute2InfoHolder.mAudioDeviceInfoType,
+                            /* address= */ ""); // This is not a BT device, hence no address needed.
+            return () ->
+                    mAudioManager.setPreferredDeviceForStrategy(
+                            mStrategyForMedia, deviceAttributes);
+        }
+    }
+
     @RequiresPermission(
             anyOf = {
                 Manifest.permission.MODIFY_AUDIO_ROUTING,
diff --git a/services/core/java/com/android/server/media/BluetoothDeviceRoutesManager.java b/services/core/java/com/android/server/media/BluetoothDeviceRoutesManager.java
index b881ef6..8b65ea3 100644
--- a/services/core/java/com/android/server/media/BluetoothDeviceRoutesManager.java
+++ b/services/core/java/com/android/server/media/BluetoothDeviceRoutesManager.java
@@ -31,6 +31,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.media.MediaRoute2Info;
+import android.os.Handler;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
@@ -77,26 +78,35 @@
 
     @NonNull
     private final Context mContext;
-    @NonNull
-    private final BluetoothAdapter mBluetoothAdapter;
+    @NonNull private final Handler mHandler;
+    @NonNull private final BluetoothAdapter mBluetoothAdapter;
     @NonNull
     private final BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
     @NonNull
     private final BluetoothProfileMonitor mBluetoothProfileMonitor;
 
-    BluetoothDeviceRoutesManager(@NonNull Context context,
+    BluetoothDeviceRoutesManager(
+            @NonNull Context context,
+            @NonNull Handler handler,
             @NonNull BluetoothAdapter bluetoothAdapter,
             @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
-        this(context, bluetoothAdapter,
-                new BluetoothProfileMonitor(context, bluetoothAdapter), listener);
+        this(
+                context,
+                handler,
+                bluetoothAdapter,
+                new BluetoothProfileMonitor(context, bluetoothAdapter),
+                listener);
     }
 
     @VisibleForTesting
-    BluetoothDeviceRoutesManager(@NonNull Context context,
+    BluetoothDeviceRoutesManager(
+            @NonNull Context context,
+            @NonNull Handler handler,
             @NonNull BluetoothAdapter bluetoothAdapter,
             @NonNull BluetoothProfileMonitor bluetoothProfileMonitor,
             @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
         mContext = Objects.requireNonNull(context);
+        mHandler = handler;
         mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
         mBluetoothProfileMonitor = Objects.requireNonNull(bluetoothProfileMonitor);
         mListener = Objects.requireNonNull(listener);
@@ -298,6 +308,26 @@
         };
     }
 
+    private void handleBluetoothAdapterStateChange(int state) {
+        if (state == BluetoothAdapter.STATE_OFF || state == BluetoothAdapter.STATE_TURNING_OFF) {
+            synchronized (BluetoothDeviceRoutesManager.this) {
+                mBluetoothRoutes.clear();
+            }
+            notifyBluetoothRoutesUpdated();
+        } else if (state == BluetoothAdapter.STATE_ON) {
+            updateBluetoothRoutes();
+
+            boolean shouldCallListener;
+            synchronized (BluetoothDeviceRoutesManager.this) {
+                shouldCallListener = !mBluetoothRoutes.isEmpty();
+            }
+
+            if (shouldCallListener) {
+                notifyBluetoothRoutesUpdated();
+            }
+        }
+    }
+
     private static class BluetoothRouteInfo {
         private BluetoothDevice mBtDevice;
         private MediaRoute2Info mRoute;
@@ -308,23 +338,10 @@
         @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 (BluetoothDeviceRoutesManager.this) {
-                    mBluetoothRoutes.clear();
-                }
-                notifyBluetoothRoutesUpdated();
-            } else if (state == BluetoothAdapter.STATE_ON) {
-                updateBluetoothRoutes();
-
-                boolean shouldCallListener;
-                synchronized (BluetoothDeviceRoutesManager.this) {
-                    shouldCallListener = !mBluetoothRoutes.isEmpty();
-                }
-
-                if (shouldCallListener) {
-                    notifyBluetoothRoutesUpdated();
-                }
+            if (Flags.enableMr2ServiceNonMainBgThread()) {
+                mHandler.post(() -> handleBluetoothAdapterStateChange(state));
+            } else {
+                handleBluetoothAdapterStateChange(state);
             }
         }
     }
@@ -337,8 +354,16 @@
                 case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
                 case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
                 case BluetoothDevice.ACTION_ALIAS_CHANGED:
-                    updateBluetoothRoutes();
-                    notifyBluetoothRoutesUpdated();
+                    if (Flags.enableMr2ServiceNonMainBgThread()) {
+                        mHandler.post(
+                                () -> {
+                                    updateBluetoothRoutes();
+                                    notifyBluetoothRoutesUpdated();
+                                });
+                    } else {
+                        updateBluetoothRoutes();
+                        notifyBluetoothRoutesUpdated();
+                    }
             }
         }
     }
diff --git a/services/core/java/com/android/server/media/MediaKeyDispatcher.java b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
index 66cafab..e4f2ec3 100644
--- a/services/core/java/com/android/server/media/MediaKeyDispatcher.java
+++ b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
@@ -44,7 +44,6 @@
  * Note: When instantiating this class, {@link MediaSessionService} will only use the constructor
  * without any parameters.
  */
-// TODO: Move this class to apex/media/
 public abstract class MediaKeyDispatcher {
     @IntDef(flag = true, value = {
             KEY_EVENT_SINGLE_TAP,
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 67d3fe9..a7fd750 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -232,7 +232,9 @@
         if (!mRunning) {
             return false;
         }
-        if (!getSessionInfos().isEmpty() || mIsManagerScanning) {
+        boolean bindDueToManagerScan =
+                mIsManagerScanning && !Flags.enablePreventionOfManagerScansWhenNoAppsScan();
+        if (!getSessionInfos().isEmpty() || bindDueToManagerScan) {
             // We bind if any manager is scanning (regardless of whether an app is scanning) to give
             // the opportunity for providers to publish routing sessions that were established
             // directly between the app and the provider (typically via AndroidX MediaRouter). See
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index aa71e05..869b89a 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -189,12 +189,10 @@
         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
 
-        if (!Flags.disableScreenOffBroadcastReceiver()) {
-            IntentFilter screenOnOffIntentFilter = new IntentFilter();
-            screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON);
-            screenOnOffIntentFilter.addAction(ACTION_SCREEN_OFF);
-            mContext.registerReceiver(mScreenOnOffReceiver, screenOnOffIntentFilter);
-        }
+        IntentFilter screenOnOffIntentFilter = new IntentFilter();
+        screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON);
+        screenOnOffIntentFilter.addAction(ACTION_SCREEN_OFF);
+        mContext.registerReceiver(mScreenOnOffReceiver, screenOnOffIntentFilter);
 
         // Passing null package name to listen to all events.
         mAppOpsManager.startWatchingMode(
@@ -3413,7 +3411,14 @@
             for (RouterRecord activeRouterRecord : activeRouterRecords) {
                 RouteDiscoveryPreference preference = activeRouterRecord.mDiscoveryPreference;
                 preferredFeatures.addAll(preference.getPreferredFeatures());
-                if (activeRouterRecord.isActivelyScanning()) {
+
+                boolean isRouterRecordActivelyScanning =
+                        Flags.enablePreventionOfManagerScansWhenNoAppsScan()
+                                ? (activeRouterRecord.isActivelyScanning() || shouldForceActiveScan)
+                                        && !preference.getPreferredFeatures().isEmpty()
+                                : activeRouterRecord.isActivelyScanning();
+
+                if (isRouterRecordActivelyScanning) {
                     activeScan = true;
                     activelyScanningPackages.add(activeRouterRecord.mPackageName);
                 }
@@ -3435,9 +3440,7 @@
         @NonNull
         private static List<RouterRecord> getIndividuallyActiveRouters(
                 MediaRouter2ServiceImpl service, List<RouterRecord> allRouterRecords) {
-            if (!Flags.disableScreenOffBroadcastReceiver()
-                    && !service.mPowerManager.isInteractive()
-                    && !Flags.enableScreenOffScanning()) {
+            if (!service.mPowerManager.isInteractive() && !Flags.enableScreenOffScanning()) {
                 return Collections.emptyList();
             }
 
@@ -3453,9 +3456,7 @@
 
         private static boolean areManagersScanning(
                 MediaRouter2ServiceImpl service, List<ManagerRecord> managerRecords) {
-            if (!Flags.disableScreenOffBroadcastReceiver()
-                    && !service.mPowerManager.isInteractive()
-                    && !Flags.enableScreenOffScanning()) {
+            if (!service.mPowerManager.isInteractive() && !Flags.enableScreenOffScanning()) {
                 return false;
             }
 
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 4bdca29..064443c 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -53,6 +53,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
@@ -70,6 +71,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.DumpUtils;
+import com.android.media.flags.Flags;
 import com.android.server.LocalServices;
 import com.android.server.Watchdog;
 import com.android.server.pm.UserManagerInternal;
@@ -94,6 +96,7 @@
         implements Watchdog.Monitor {
     private static final String TAG = "MediaRouterService";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final String WORKER_THREAD_NAME = "MediaRouterServiceThread";
 
     /**
      * Timeout in milliseconds for a selected route to transition from a disconnected state to a
@@ -126,7 +129,7 @@
 
     private final IAudioService mAudioService;
     private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
-    private final Handler mHandler = new Handler();
+    private final Handler mHandler;
     private final IntArray mActivePlayerMinPriorityQueue = new IntArray();
     private final IntArray mActivePlayerUidMinPriorityQueue = new IntArray();
 
@@ -142,7 +145,14 @@
 
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public MediaRouterService(Context context) {
-        mLooper = Looper.getMainLooper();
+        if (Flags.enableMr2ServiceNonMainBgThread()) {
+            HandlerThread handlerThread = new HandlerThread(WORKER_THREAD_NAME);
+            handlerThread.start();
+            mLooper = handlerThread.getLooper();
+        } else {
+            mLooper = Looper.myLooper();
+        }
+        mHandler = new Handler(mLooper);
         mService2 = new MediaRouter2ServiceImpl(context, mLooper);
         mContext = context;
         Watchdog.getInstance().addMonitor(this);
@@ -257,9 +267,11 @@
     // Binder call
     @Override
     public boolean showMediaOutputSwitcher(String packageName) {
-        if (!validatePackageName(Binder.getCallingUid(), packageName)) {
+        int uid = Binder.getCallingUid();
+        if (!validatePackageName(uid, packageName)) {
             throw new SecurityException("packageName must match the calling identity");
         }
+        UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
         final long token = Binder.clearCallingIdentity();
         try {
             if (mContext.getSystemService(ActivityManager.class).getPackageImportance(packageName)
@@ -270,7 +282,7 @@
             synchronized (mLock) {
                 StatusBarManagerInternal statusBar =
                         LocalServices.getService(StatusBarManagerInternal.class);
-                statusBar.showMediaOutputSwitcher(packageName);
+                statusBar.showMediaOutputSwitcher(packageName, userHandle);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/media/MediaServerUtils.java b/services/core/java/com/android/server/media/MediaServerUtils.java
index 6a954d6..f16d426 100644
--- a/services/core/java/com/android/server/media/MediaServerUtils.java
+++ b/services/core/java/com/android/server/media/MediaServerUtils.java
@@ -74,10 +74,7 @@
         }
         final PackageManagerInternal packageManagerInternal =
                 LocalServices.getService(PackageManagerInternal.class);
-        final int actualUid =
-                packageManagerInternal.getPackageUid(
-                        packageName, 0 /* flags */, UserHandle.getUserId(uid));
-        if (!UserHandle.isSameApp(uid, actualUid)) {
+        if (!packageManagerInternal.isSameApp(packageName, uid, UserHandle.getUserId(uid))) {
             String[] uidPackages = context.getPackageManager().getPackagesForUid(uid);
             throw new IllegalArgumentException(
                     "packageName does not belong to the calling uid; "
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java
index 0cd7654..dfb2b0a 100644
--- a/services/core/java/com/android/server/media/MediaSession2Record.java
+++ b/services/core/java/com/android/server/media/MediaSession2Record.java
@@ -157,6 +157,11 @@
     }
 
     @Override
+    public void expireTempEngaged() {
+        // NA as MediaSession2 doesn't support UserEngagementStates for FGS.
+    }
+
+    @Override
     public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
             KeyEvent ke, int sequenceId, ResultReceiver cb) {
         // TODO(jaewan): Implement.
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index eb4e6e4..a3c5d2d 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -24,6 +24,7 @@
 import static android.media.session.MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -65,7 +66,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -85,9 +85,10 @@
 import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Objects;
@@ -188,6 +189,9 @@
     private final ForegroundServiceDelegationOptions mForegroundServiceDelegationOptions;
 
     private final Object mLock = new Object();
+    // This field is partially guarded by mLock. Writes and non-atomic iterations (for example:
+    // index-based-iterations) must be guarded by mLock. But it is safe to acquire an iterator
+    // without acquiring mLock.
     private final CopyOnWriteArrayList<ISessionControllerCallbackHolder>
             mControllerCallbackHolders = new CopyOnWriteArrayList<>();
 
@@ -225,6 +229,49 @@
 
     private int mPolicies;
 
+    private @UserEngagementState int mUserEngagementState = USER_DISENGAGED;
+
+    @IntDef({USER_PERMANENTLY_ENGAGED, USER_TEMPORARY_ENGAGED, USER_DISENGAGED})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface UserEngagementState {}
+
+    /**
+     * Indicates that the session is active and in one of the user engaged states.
+     *
+     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
+     */
+    private static final int USER_PERMANENTLY_ENGAGED = 0;
+
+    /**
+     * Indicates that the session is active and in {@link PlaybackState#STATE_PAUSED} state.
+     *
+     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
+     */
+    private static final int USER_TEMPORARY_ENGAGED = 1;
+
+    /**
+     * Indicates that the session is either not active or in one of the user disengaged states
+     *
+     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
+     */
+    private static final int USER_DISENGAGED = 2;
+
+    /**
+     * Indicates the duration of the temporary engaged states.
+     *
+     * <p>Some {@link MediaSession} states like {@link PlaybackState#STATE_PAUSED} are temporarily
+     * engaged, meaning the corresponding session is only considered in an engaged state for the
+     * duration of this timeout, and only if coming from an engaged state.
+     *
+     * <p>For example, if a session is transitioning from a user-engaged state {@link
+     * PlaybackState#STATE_PLAYING} to a temporary user-engaged state {@link
+     * PlaybackState#STATE_PAUSED}, then the session will be considered in a user-engaged state for
+     * the duration of this timeout, starting at the transition instant. However, a temporary
+     * user-engaged state is not considered user-engaged when transitioning from a non-user engaged
+     * state {@link PlaybackState#STATE_STOPPED}.
+     */
+    private static final int TEMP_USER_ENGAGED_TIMEOUT = 600000;
+
     public MediaSessionRecord(
             int ownerPid,
             int ownerUid,
@@ -548,6 +595,7 @@
             mSessionCb.mCb.asBinder().unlinkToDeath(this, 0);
             mDestroyed = true;
             mPlaybackState = null;
+            updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
             mHandler.post(MessageHandler.MSG_DESTROYED);
         }
     }
@@ -559,6 +607,12 @@
         }
     }
 
+    @Override
+    public void expireTempEngaged() {
+        mHandler.removeCallbacks(mHandleTempEngagedSessionTimeout);
+        updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
+    }
+
     /**
      * Sends media button.
      *
@@ -833,24 +887,9 @@
             }
             playbackState = mPlaybackState;
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            try {
-                holder.mCallback.onPlaybackStateChanged(playbackState);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushPlaybackStateUpdate", holder,
-                        e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushPlaybackStateUpdate", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders(
+                "pushPlaybackStateUpdate",
+                holder -> holder.mCallback.onPlaybackStateChanged(playbackState));
     }
 
     private void pushMetadataUpdate() {
@@ -861,23 +900,8 @@
             }
             metadata = mMetadata;
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            try {
-                holder.mCallback.onMetadataChanged(metadata);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushMetadataUpdate", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushMetadataUpdate", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders(
+                "pushMetadataUpdate", holder -> holder.mCallback.onMetadataChanged(metadata));
     }
 
     private void pushQueueUpdate() {
@@ -888,31 +912,18 @@
             }
             toSend = mQueue == null ? null : new ArrayList<>(mQueue);
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            ParceledListSlice<QueueItem> parcelableQueue = null;
-            if (toSend != null) {
-                parcelableQueue = new ParceledListSlice<>(toSend);
-                // Limit the size of initial Parcel to prevent binder buffer overflow
-                // as onQueueChanged is an async binder call.
-                parcelableQueue.setInlineCountLimit(1);
-            }
-
-            try {
-                holder.mCallback.onQueueChanged(parcelableQueue);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushQueueUpdate", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushQueueUpdate", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders(
+                "pushQueueUpdate",
+                holder -> {
+                    ParceledListSlice<QueueItem> parcelableQueue = null;
+                    if (toSend != null) {
+                        parcelableQueue = new ParceledListSlice<>(toSend);
+                        // Limit the size of initial Parcel to prevent binder buffer overflow
+                        // as onQueueChanged is an async binder call.
+                        parcelableQueue.setInlineCountLimit(1);
+                    }
+                    holder.mCallback.onQueueChanged(parcelableQueue);
+                });
     }
 
     private void pushQueueTitleUpdate() {
@@ -923,23 +934,8 @@
             }
             queueTitle = mQueueTitle;
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            try {
-                holder.mCallback.onQueueTitleChanged(queueTitle);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushQueueTitleUpdate", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushQueueTitleUpdate", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders(
+                "pushQueueTitleUpdate", holder -> holder.mCallback.onQueueTitleChanged(queueTitle));
     }
 
     private void pushExtrasUpdate() {
@@ -950,23 +946,8 @@
             }
             extras = mExtras;
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            try {
-                holder.mCallback.onExtrasChanged(extras);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushExtrasUpdate", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushExtrasUpdate", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders(
+                "pushExtrasUpdate", holder -> holder.mCallback.onExtrasChanged(extras));
     }
 
     private void pushVolumeUpdate() {
@@ -977,23 +958,8 @@
             }
             info = getVolumeAttributes();
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            try {
-                holder.mCallback.onVolumeInfoChanged(info);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushVolumeUpdate", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushVolumeUpdate", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders(
+                "pushVolumeUpdate", holder -> holder.mCallback.onVolumeInfoChanged(info));
     }
 
     private void pushEvent(String event, Bundle data) {
@@ -1002,23 +968,7 @@
                 return;
             }
         }
-        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
-        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
-            try {
-                holder.mCallback.onEvent(event, data);
-            } catch (DeadObjectException e) {
-                if (deadCallbackHolders == null) {
-                    deadCallbackHolders = new ArrayList<>();
-                }
-                deadCallbackHolders.add(holder);
-                logCallbackException("Removing dead callback in pushEvent", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushEvent", holder, e);
-            }
-        }
-        if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
-        }
+        performOnCallbackHolders("pushEvent", holder -> holder.mCallback.onEvent(event, data));
     }
 
     private void pushSessionDestroyed() {
@@ -1029,20 +979,37 @@
                 return;
             }
         }
+        performOnCallbackHolders(
+                "pushSessionDestroyed",
+                holder -> {
+                    holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
+                    holder.mCallback.onSessionDestroyed();
+                });
+        // After notifying clear all listeners
+        synchronized (mLock) {
+            mControllerCallbackHolders.clear();
+        }
+    }
+
+    private interface ControllerCallbackCall {
+
+        void performOn(ISessionControllerCallbackHolder holder) throws RemoteException;
+    }
+
+    private void performOnCallbackHolders(String operationName, ControllerCallbackCall call) {
+        ArrayList<ISessionControllerCallbackHolder> deadCallbackHolders = new ArrayList<>();
         for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
             try {
-                holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
-                holder.mCallback.onSessionDestroyed();
-            } catch (NoSuchElementException e) {
-                logCallbackException("error unlinking to binder death", holder, e);
-            } catch (DeadObjectException e) {
-                logCallbackException("Removing dead callback in pushSessionDestroyed", holder, e);
-            } catch (RemoteException e) {
-                logCallbackException("unexpected exception in pushSessionDestroyed", holder, e);
+                call.performOn(holder);
+            } catch (RemoteException | NoSuchElementException exception) {
+                deadCallbackHolders.add(holder);
+                logCallbackException(
+                        "Exception while executing: " + operationName, holder, exception);
             }
         }
-        // After notifying clear all listeners
-        mControllerCallbackHolders.clear();
+        synchronized (mLock) {
+            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+        }
     }
 
     private PlaybackState getStateWithUpdatedPosition() {
@@ -1118,6 +1085,11 @@
                 }
             };
 
+    private final Runnable mHandleTempEngagedSessionTimeout =
+            () -> {
+                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
+            };
+
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     private static boolean componentNameExists(
             @NonNull ComponentName componentName, @NonNull Context context, int userId) {
@@ -1134,6 +1106,40 @@
         return !resolveInfos.isEmpty();
     }
 
+    private void updateUserEngagedStateIfNeededLocked(boolean isTimeoutExpired) {
+        int oldUserEngagedState = mUserEngagementState;
+        int newUserEngagedState;
+        if (!isActive() || mPlaybackState == null) {
+            newUserEngagedState = USER_DISENGAGED;
+        } else if (isActive() && mPlaybackState.isActive()) {
+            newUserEngagedState = USER_PERMANENTLY_ENGAGED;
+        } else if (mPlaybackState.getState() == PlaybackState.STATE_PAUSED) {
+            newUserEngagedState =
+                    oldUserEngagedState == USER_PERMANENTLY_ENGAGED || !isTimeoutExpired
+                            ? USER_TEMPORARY_ENGAGED
+                            : USER_DISENGAGED;
+        } else {
+            newUserEngagedState = USER_DISENGAGED;
+        }
+        if (oldUserEngagedState == newUserEngagedState) {
+            return;
+        }
+
+        if (newUserEngagedState == USER_TEMPORARY_ENGAGED) {
+            mHandler.postDelayed(mHandleTempEngagedSessionTimeout, TEMP_USER_ENGAGED_TIMEOUT);
+        } else if (oldUserEngagedState == USER_TEMPORARY_ENGAGED) {
+            mHandler.removeCallbacks(mHandleTempEngagedSessionTimeout);
+        }
+
+        boolean wasUserEngaged = oldUserEngagedState != USER_DISENGAGED;
+        boolean isNowUserEngaged = newUserEngagedState != USER_DISENGAGED;
+        mUserEngagementState = newUserEngagedState;
+        if (wasUserEngaged != isNowUserEngaged) {
+            mService.onSessionUserEngagementStateChange(
+                    /* mediaSessionRecord= */ this, /* isUserEngaged= */ isNowUserEngaged);
+        }
+    }
+
     private final class SessionStub extends ISession.Stub {
         @Override
         public void destroySession() throws RemoteException {
@@ -1171,8 +1177,10 @@
                         .logFgsApiEnd(ActivityManager.FOREGROUND_SERVICE_API_TYPE_MEDIA_PLAYBACK,
                                 callingUid, callingPid);
             }
-
-            mIsActive = active;
+            synchronized (mLock) {
+                mIsActive = active;
+                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
+            }
             long token = Binder.clearCallingIdentity();
             try {
                 mService.onSessionActiveStateChanged(MediaSessionRecord.this, mPlaybackState);
@@ -1330,6 +1338,7 @@
                     && TRANSITION_PRIORITY_STATES.contains(newState));
             synchronized (mLock) {
                 mPlaybackState = state;
+                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
             }
             final long token = Binder.clearCallingIdentity();
             try {
@@ -1351,12 +1360,14 @@
 
         @Override
         public IBinder getBinderForSetQueue() throws RemoteException {
-            return new ParcelableListBinder<QueueItem>((list) -> {
-                synchronized (mLock) {
-                    mQueue = list;
-                }
-                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
-            });
+            return new ParcelableListBinder<QueueItem>(
+                    QueueItem.class,
+                    (list) -> {
+                        synchronized (mLock) {
+                            mQueue = list;
+                        }
+                        mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
+                    });
         }
 
         @Override
diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
index 0999199..b57b148 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
@@ -196,6 +196,12 @@
      */
     public abstract boolean isClosed();
 
+    /**
+     * Note: This method is only used for testing purposes If the session is temporary engaged, the
+     * timeout will expire and it will become disengaged.
+     */
+    public abstract void expireTempEngaged();
+
     @Override
     public final boolean equals(Object o) {
         if (this == o) return true;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 53c32cf..74adf5e 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -367,11 +367,13 @@
             }
             boolean isUserEngaged = isUserEngaged(record, playbackState);
 
-            Log.d(TAG, "onSessionActiveStateChanged: "
-                    + "record=" + record
-                    + "playbackState=" + playbackState
-                    + "allowRunningInForeground=" + isUserEngaged);
-            setForegroundServiceAllowance(record, /* allowRunningInForeground= */ isUserEngaged);
+            Log.d(
+                    TAG,
+                    "onSessionActiveStateChanged:"
+                            + " record="
+                            + record
+                            + " playbackState="
+                            + playbackState);
             reportMediaInteractionEvent(record, isUserEngaged);
             mHandler.postSessionsChanged(record);
         }
@@ -479,11 +481,13 @@
             }
             user.mPriorityStack.onPlaybackStateChanged(record, shouldUpdatePriority);
             boolean isUserEngaged = isUserEngaged(record, playbackState);
-            Log.d(TAG, "onSessionPlaybackStateChanged: "
-                    + "record=" + record
-                    + "playbackState=" + playbackState
-                    + "allowRunningInForeground=" + isUserEngaged);
-            setForegroundServiceAllowance(record, /* allowRunningInForeground= */ isUserEngaged);
+            Log.d(
+                    TAG,
+                    "onSessionPlaybackStateChanged:"
+                            + " record="
+                            + record
+                            + " playbackState="
+                            + playbackState);
             reportMediaInteractionEvent(record, isUserEngaged);
         }
     }
@@ -650,68 +654,112 @@
         session.close();
 
         Log.d(TAG, "destroySessionLocked: record=" + session);
-        setForegroundServiceAllowance(session, /* allowRunningInForeground= */ false);
+
         reportMediaInteractionEvent(session, /* userEngaged= */ false);
         mHandler.postSessionsChanged(session);
     }
 
-    private void setForegroundServiceAllowance(
-            MediaSessionRecordImpl record, boolean allowRunningInForeground) {
-        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
-            return;
-        }
-        ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
-                record.getForegroundServiceDelegationOptions();
-        if (foregroundServiceDelegationOptions == null) {
-            return;
-        }
-        if (allowRunningInForeground) {
-            onUserSessionEngaged(record);
+    void onSessionUserEngagementStateChange(
+            MediaSessionRecordImpl mediaSessionRecord, boolean isUserEngaged) {
+        if (isUserEngaged) {
+            addUserEngagedSession(mediaSessionRecord);
+            startFgsIfSessionIsLinkedToNotification(mediaSessionRecord);
         } else {
-            onUserDisengaged(record);
+            removeUserEngagedSession(mediaSessionRecord);
+            stopFgsIfNoSessionIsLinkedToNotification(mediaSessionRecord);
         }
     }
 
-    private void onUserSessionEngaged(MediaSessionRecordImpl mediaSessionRecord) {
+    private void addUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
         synchronized (mLock) {
             int uid = mediaSessionRecord.getUid();
             mUserEngagedSessionsForFgs.putIfAbsent(uid, new HashSet<>());
             mUserEngagedSessionsForFgs.get(uid).add(mediaSessionRecord);
+        }
+    }
+
+    private void removeUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
+        synchronized (mLock) {
+            int uid = mediaSessionRecord.getUid();
+            Set<MediaSessionRecordImpl> mUidUserEngagedSessionsForFgs =
+                    mUserEngagedSessionsForFgs.get(uid);
+            if (mUidUserEngagedSessionsForFgs == null) {
+                return;
+            }
+
+            mUidUserEngagedSessionsForFgs.remove(mediaSessionRecord);
+            if (mUidUserEngagedSessionsForFgs.isEmpty()) {
+                mUserEngagedSessionsForFgs.remove(uid);
+            }
+        }
+    }
+
+    private void startFgsIfSessionIsLinkedToNotification(
+            MediaSessionRecordImpl mediaSessionRecord) {
+        Log.d(TAG, "startFgsIfSessionIsLinkedToNotification: record=" + mediaSessionRecord);
+        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+            return;
+        }
+        synchronized (mLock) {
+            int uid = mediaSessionRecord.getUid();
             for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid, Set.of())) {
                 if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
-                    mActivityManagerInternal.startForegroundServiceDelegate(
-                            mediaSessionRecord.getForegroundServiceDelegationOptions(),
-                            /* connection= */ null);
+                    startFgsDelegate(mediaSessionRecord.getForegroundServiceDelegationOptions());
                     return;
                 }
             }
         }
     }
 
-    private void onUserDisengaged(MediaSessionRecordImpl mediaSessionRecord) {
+    private void startFgsDelegate(
+            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mActivityManagerInternal.startForegroundServiceDelegate(
+                    foregroundServiceDelegationOptions, /* connection= */ null);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private void stopFgsIfNoSessionIsLinkedToNotification(
+            MediaSessionRecordImpl mediaSessionRecord) {
+        Log.d(TAG, "stopFgsIfNoSessionIsLinkedToNotification: record=" + mediaSessionRecord);
+        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+            return;
+        }
         synchronized (mLock) {
             int uid = mediaSessionRecord.getUid();
-            if (mUserEngagedSessionsForFgs.containsKey(uid)) {
-                mUserEngagedSessionsForFgs.get(uid).remove(mediaSessionRecord);
-                if (mUserEngagedSessionsForFgs.get(uid).isEmpty()) {
-                    mUserEngagedSessionsForFgs.remove(uid);
-                }
+            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
+                    mediaSessionRecord.getForegroundServiceDelegationOptions();
+            if (foregroundServiceDelegationOptions == null) {
+                return;
             }
 
-            boolean shouldStopFgs = true;
-            for (MediaSessionRecordImpl sessionRecord :
+            for (MediaSessionRecordImpl record :
                     mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
-                for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid,
-                        Set.of())) {
-                    if (sessionRecord.isLinkedToNotification(mediaNotification)) {
-                        shouldStopFgs = false;
+                for (Notification mediaNotification :
+                        mMediaNotifications.getOrDefault(uid, Set.of())) {
+                    if (record.isLinkedToNotification(mediaNotification)) {
+                        // A user engaged session linked with a media notification is found.
+                        // We shouldn't call stop FGS in this case.
+                        return;
                     }
                 }
             }
-            if (shouldStopFgs) {
-                mActivityManagerInternal.stopForegroundServiceDelegate(
-                        mediaSessionRecord.getForegroundServiceDelegationOptions());
-            }
+
+            stopFgsDelegate(foregroundServiceDelegationOptions);
+        }
+    }
+
+    private void stopFgsDelegate(
+            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mActivityManagerInternal.stopForegroundServiceDelegate(
+                    foregroundServiceDelegationOptions);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
@@ -2502,7 +2550,6 @@
             }
             MediaSessionRecord session = null;
             MediaButtonReceiverHolder mediaButtonReceiverHolder = null;
-
             if (mCustomMediaKeyDispatcher != null) {
                 MediaSession.Token token = mCustomMediaKeyDispatcher.getMediaSession(
                         keyEvent, uid, asSystemService);
@@ -2630,6 +2677,18 @@
                     && streamType <= AudioManager.STREAM_NOTIFICATION;
         }
 
+        @Override
+        public void expireTempEngagedSessions() {
+            synchronized (mLock) {
+                for (Set<MediaSessionRecordImpl> uidSessions :
+                        mUserEngagedSessionsForFgs.values()) {
+                    for (MediaSessionRecordImpl sessionRecord : uidSessions) {
+                        sessionRecord.expireTempEngaged();
+                    }
+                }
+            }
+        }
+
         private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
             private final String mPackageName;
             private final int mPid;
@@ -3127,7 +3186,6 @@
             super.onNotificationPosted(sbn);
             Notification postedNotification = sbn.getNotification();
             int uid = sbn.getUid();
-
             if (!postedNotification.isMediaNotification()) {
                 return;
             }
@@ -3138,11 +3196,9 @@
                         mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                     ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                             mediaSessionRecord.getForegroundServiceDelegationOptions();
-                    if (mediaSessionRecord.isLinkedToNotification(postedNotification)
-                            && foregroundServiceDelegationOptions != null) {
-                        mActivityManagerInternal.startForegroundServiceDelegate(
-                                foregroundServiceDelegationOptions,
-                                /* connection= */ null);
+                    if (foregroundServiceDelegationOptions != null
+                            && mediaSessionRecord.isLinkedToNotification(postedNotification)) {
+                        startFgsDelegate(foregroundServiceDelegationOptions);
                         return;
                     }
                 }
@@ -3173,21 +3229,7 @@
                     return;
                 }
 
-                boolean shouldStopFgs = true;
-                for (MediaSessionRecordImpl mediaSessionRecord :
-                        mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
-                    for (Notification mediaNotification :
-                            mMediaNotifications.getOrDefault(uid, Set.of())) {
-                        if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
-                            shouldStopFgs = false;
-                        }
-                    }
-                }
-                if (shouldStopFgs
-                        && notificationRecord.getForegroundServiceDelegationOptions() != null) {
-                    mActivityManagerInternal.stopForegroundServiceDelegate(
-                            notificationRecord.getForegroundServiceDelegationOptions());
-                }
+                stopFgsIfNoSessionIsLinkedToNotification(notificationRecord);
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaShellCommand.java b/services/core/java/com/android/server/media/MediaShellCommand.java
index a563808..a20de31 100644
--- a/services/core/java/com/android/server/media/MediaShellCommand.java
+++ b/services/core/java/com/android/server/media/MediaShellCommand.java
@@ -92,6 +92,8 @@
                 runMonitor();
             } else if (cmd.equals("volume")) {
                 runVolume();
+            } else if (cmd.equals("expire-temp-engaged-sessions")) {
+                expireTempEngagedSessions();
             } else {
                 showError("Error: unknown command '" + cmd + "'");
                 return -1;
@@ -367,4 +369,8 @@
     private void runVolume() throws Exception {
         VolumeCtrl.run(this);
     }
+
+    private void expireTempEngagedSessions() throws Exception {
+        mSessionService.expireTempEngagedSessions();
+    }
 }
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 802acba..c105b9c 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -473,6 +473,10 @@
                                 .setProviderId(mUniqueId)
                                 .setSystemSession(true)
                                 .addSelectedRoute(MediaRoute2Info.ROUTE_ID_DEFAULT)
+                                .setTransferReason(newSessionInfo.getTransferReason())
+                                .setTransferInitiator(
+                                        newSessionInfo.getTransferInitiatorUserHandle(),
+                                        newSessionInfo.getTransferInitiatorPackageName())
                                 .build();
                 return true;
             }
@@ -653,9 +657,11 @@
                 return;
             }
 
-            // TODO: b/310145678 - Post this to mHandler once mHandler does not run on the main
-            // thread.
-            updateVolume();
+            if (Flags.enableMr2ServiceNonMainBgThread()) {
+                mHandler.post(SystemMediaRoute2Provider.this::updateVolume);
+            } else {
+                updateVolume();
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/net/Android.bp b/services/core/java/com/android/server/net/Android.bp
index 71d8e6b..3ac2d23 100644
--- a/services/core/java/com/android/server/net/Android.bp
+++ b/services/core/java/com/android/server/net/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "net_flags",
     package: "com.android.server.net",
+    container: "system",
     srcs: ["*.aconfig"],
 }
 
diff --git a/services/core/java/com/android/server/net/flags.aconfig b/services/core/java/com/android/server/net/flags.aconfig
index 419665a..d9491de5 100644
--- a/services/core/java/com/android/server/net/flags.aconfig
+++ b/services/core/java/com/android/server/net/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.net"
+container: "system"
 
 flag {
     name: "network_blocked_for_top_sleeping_and_above"
diff --git a/services/core/java/com/android/server/notification/Android.bp b/services/core/java/com/android/server/notification/Android.bp
index 9be4358..d757470 100644
--- a/services/core/java/com/android/server/notification/Android.bp
+++ b/services/core/java/com/android/server/notification/Android.bp
@@ -10,6 +10,7 @@
 aconfig_declarations {
     name: "notification_flags",
     package: "com.android.server.notification",
+    container: "system",
     srcs: [
         "flags.aconfig",
     ],
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index e1e2b3e..3949dfe 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1617,7 +1617,8 @@
         intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
 
         final ActivityOptions activityOptions = ActivityOptions.makeBasic();
-        activityOptions.setIgnorePendingIntentCreatorForegroundState(true);
+        activityOptions.setPendingIntentCreatorBackgroundActivityStartMode(
+                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED);
         final PendingIntent pendingIntent = PendingIntent.getActivity(
                 mContext, 0, new Intent(mConfig.settingsAction), PendingIntent.FLAG_IMMUTABLE,
                 activityOptions.toBundle());
diff --git a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
index bd73cb6..1938642 100644
--- a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
@@ -23,9 +23,15 @@
 
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.LoggingOnly;
 import android.content.Context;
 import android.media.AudioAttributes;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Slog;
+import com.android.internal.compat.IPlatformCompat;
 
 /**
  * Stores the latest notification channel information for this notification
@@ -34,14 +40,26 @@
     private static final String TAG = "ChannelExtractor";
     private static final boolean DBG = false;
 
+    /**
+     * Corrects audio attributes for notifications based on characteristics of the notifications.
+     */
+    @ChangeId
+    @LoggingOnly
+    static final long RESTRICT_AUDIO_ATTRIBUTES = 331793339L;
+
     private RankingConfig mConfig;
     private Context mContext;
+    private IPlatformCompat mPlatformCompat;
 
     public void initialize(Context ctx, NotificationUsageStats usageStats) {
         mContext = ctx;
         if (DBG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
     }
 
+    public void setCompatChangeLogger(IPlatformCompat platformCompat) {
+        mPlatformCompat = platformCompat;
+    }
+
     public RankingReconsideration process(NotificationRecord record) {
         if (record == null || record.getNotification() == null) {
             if (DBG) Slog.d(TAG, "skipping empty notification");
@@ -80,6 +98,7 @@
             }
 
             if (updateAttributes) {
+                reportAudioAttributesChanged(record.getUid());
                 NotificationChannel clone = record.getChannel().copy();
                 clone.setSound(clone.getSound(), new AudioAttributes.Builder(attributes)
                         .setUsage(USAGE_NOTIFICATION)
@@ -91,6 +110,17 @@
         return null;
     }
 
+    private void reportAudioAttributesChanged(int uid) {
+        final long id = Binder.clearCallingIdentity();
+        try {
+            mPlatformCompat.reportChangeByUid(RESTRICT_AUDIO_ATTRIBUTES, uid);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unexpected exception while reporting to changecompat", e);
+        } finally {
+            Binder.restoreCallingIdentity(id);
+        }
+    }
+
     @Override
     public void setConfig(RankingConfig config) {
         mConfig = config;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerPrivate.java b/services/core/java/com/android/server/notification/NotificationManagerPrivate.java
index 2cc63eb..a3a91e2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerPrivate.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerPrivate.java
@@ -25,4 +25,6 @@
 interface NotificationManagerPrivate {
     @Nullable
     NotificationRecord getNotificationByKey(String key);
+
+    void timeoutNotification(String key);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 24f6c70..bff3d39 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -22,6 +22,7 @@
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR;
 import static android.app.Flags.lifetimeExtensionRefactor;
 import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
@@ -97,6 +98,7 @@
 import static android.os.UserHandle.USER_SYSTEM;
 import static android.service.notification.Flags.callstyleCallbackApi;
 import static android.service.notification.Flags.redactSensitiveNotificationsFromUntrustedListeners;
+import static android.service.notification.Flags.redactSensitiveNotificationsBigTextStyle;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
@@ -220,6 +222,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.LauncherApps;
+import android.content.pm.ModuleInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
@@ -237,6 +240,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.DeadObjectException;
 import android.os.DeviceIdleManager;
 import android.os.Environment;
 import android.os.Handler;
@@ -520,7 +524,7 @@
     /**
      * Apps that post custom toasts in the background will have those blocked. Apps can
      * still post toasts created with
-     * {@link android.widget.Toast#makeText(Context, CharSequence, int)} and its variants while
+     * {@link Toast#makeText(Context, CharSequence, int)} and its variants while
      * in the background.
      */
     @ChangeId
@@ -555,7 +559,7 @@
     /**
      * Rate limit showing toasts, on a per package basis.
      *
-     * It limits the number of {@link android.widget.Toast#show()} calls to prevent overburdening
+     * It limits the number of {@link Toast#show()} calls to prevent overburdening
      * the user with too many toasts in a limited time. Any attempt to show more toasts than allowed
      * in a certain time frame will result in the toast being discarded.
      */
@@ -579,9 +583,9 @@
     static final long ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION = 264179692L;
 
     /**
-     * App calls to {@link android.app.NotificationManager#setInterruptionFilter} and
-     * {@link android.app.NotificationManager#setNotificationPolicy} manage DND through the
-     * creation and activation of an implicit {@link android.app.AutomaticZenRule}.
+     * App calls to {@link NotificationManager#setInterruptionFilter} and
+     * {@link NotificationManager#setNotificationPolicy} manage DND through the
+     * creation and activation of an implicit {@link AutomaticZenRule}.
      */
     @ChangeId
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
@@ -623,6 +627,8 @@
     private PowerManager mPowerManager;
     private PostNotificationTrackerFactory mPostNotificationTrackerFactory;
 
+    private LockPatternUtils mLockUtils;
+
     final IBinder mForegroundToken = new Binder();
     @VisibleForTesting
     WorkerHandler mHandler;
@@ -675,6 +681,10 @@
 
     private static final int DB_VERSION = 1;
 
+
+    private static final String ADSERVICES_MODULE_PKG_NAME =
+            "com.android.adservices";
+
     private static final String TAG_NOTIFICATION_POLICY = "notification-policy";
     private static final String ATTR_VERSION = "version";
 
@@ -701,13 +711,14 @@
 
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
-    private static final IBinder ALLOWLIST_TOKEN = new Binder();
+    static final IBinder ALLOWLIST_TOKEN = new Binder();
     protected RankingHandler mRankingHandler;
     private long mLastOverRateLogTime;
     private float mMaxPackageEnqueueRate = DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
 
     private NotificationHistoryManager mHistoryManager;
     protected SnoozeHelper mSnoozeHelper;
+    private TimeToLiveHelper mTtlHelper;
     private GroupHelper mGroupHelper;
     private int mAutoGroupAtCount;
     private boolean mIsTelevision;
@@ -733,6 +744,10 @@
     // Broadcast intent receiver for notification permissions review-related intents
     private ReviewNotificationPermissionsReceiver mReviewNotificationPermissionsReceiver;
 
+    private AppOpsManager.OnOpChangedListener mAppOpsListener;
+
+    private ModuleInfo mAdservicesModuleInfo;
+
     static class Archive {
         final SparseArray<Boolean> mEnabled;
         final int mBufferSize;
@@ -778,7 +793,7 @@
 
         public StatusBarNotification[] getArray(UserManager um, int count, boolean includeSnoozed) {
             ArrayList<Integer> currentUsers = new ArrayList<>();
-            currentUsers.add(UserHandle.USER_ALL);
+            currentUsers.add(USER_ALL);
             Binder.withCleanCallingIdentity(() -> {
                 for (int user : um.getProfileIds(ActivityManager.getCurrentUser(), false)) {
                     currentUsers.add(user);
@@ -901,14 +916,14 @@
 
     @VisibleForTesting
     boolean isDNDMigrationDone(int userId) {
-        return Settings.Secure.getIntForUser(getContext().getContentResolver(),
-                Settings.Secure.DND_CONFIGS_MIGRATED, 0, userId) == 1;
+        return Secure.getIntForUser(getContext().getContentResolver(),
+                Secure.DND_CONFIGS_MIGRATED, 0, userId) == 1;
     }
 
     @VisibleForTesting
     void setDNDMigrationDone(int userId) {
-        Settings.Secure.putIntForUser(getContext().getContentResolver(),
-                Settings.Secure.DND_CONFIGS_MIGRATED, 1, userId);
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.DND_CONFIGS_MIGRATED, 1, userId);
     }
 
     protected void migrateDefaultNAS() {
@@ -935,15 +950,15 @@
     @VisibleForTesting
     void setNASMigrationDone(int baseUserId) {
         for (int profileId : mUm.getProfileIds(baseUserId, false)) {
-            Settings.Secure.putIntForUser(getContext().getContentResolver(),
-                    Settings.Secure.NAS_SETTINGS_UPDATED, 1, profileId);
+            Secure.putIntForUser(getContext().getContentResolver(),
+                    Secure.NAS_SETTINGS_UPDATED, 1, profileId);
         }
     }
 
     @VisibleForTesting
     boolean isNASMigrationDone(int userId) {
-        return (Settings.Secure.getIntForUser(getContext().getContentResolver(),
-                Settings.Secure.NAS_SETTINGS_UPDATED, 0, userId) == 1);
+        return (Secure.getIntForUser(getContext().getContentResolver(),
+                Secure.NAS_SETTINGS_UPDATED, 0, userId) == 1);
     }
 
     boolean isProfileUser(UserInfo userInfo) {
@@ -1096,7 +1111,7 @@
                 mSnoozeHelper.readXml(parser, System.currentTimeMillis());
             }
             if (LOCKSCREEN_ALLOW_SECURE_NOTIFICATIONS_TAG.equals(parser.getName())) {
-                if (forRestore && userId != UserHandle.USER_SYSTEM) {
+                if (forRestore && userId != USER_SYSTEM) {
                     continue;
                 }
                 mLockScreenAllowSecureNotifications = parser.getAttributeBoolean(null,
@@ -1140,7 +1155,7 @@
             InputStream infile = null;
             try {
                 infile = mPolicyFile.openRead();
-                readPolicyXml(infile, false /*forRestore*/, UserHandle.USER_ALL);
+                readPolicyXml(infile, false /*forRestore*/, USER_ALL);
 
                 // We re-load the default dnd packages to allow the newly added and denined.
                 final boolean isWatch = mPackageManagerClient.hasSystemFeature(
@@ -1190,7 +1205,7 @@
                 }
 
                 try {
-                    writePolicyXml(stream, false /*forBackup*/, UserHandle.USER_ALL);
+                    writePolicyXml(stream, false /*forBackup*/, USER_ALL);
                     mPolicyFile.finishWrite(stream);
                 } catch (IOException e) {
                     Slog.w(TAG, "Failed to save policy file, restoring backup", e);
@@ -1219,7 +1234,7 @@
         mAssistants.writeXml(out, forBackup, userId);
         mSnoozeHelper.writeXml(out);
         mConditionProviders.writeXml(out, forBackup, userId);
-        if (!forBackup || userId == UserHandle.USER_SYSTEM) {
+        if (!forBackup || userId == USER_SYSTEM) {
             writeSecureNotificationsPolicy(out);
         }
         out.endTag(null, TAG_NOTIFICATION_POLICY);
@@ -1272,7 +1287,7 @@
 
                 StatusBarNotification sbn = r.getSbn();
                 cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(),
-                        sbn.getId(), Notification.FLAG_AUTO_CANCEL,
+                        sbn.getId(), FLAG_AUTO_CANCEL,
                         FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_BUBBLE,
                         false, r.getUserId(), REASON_CLICK, nv.rank, nv.count, null);
                 nv.recycle();
@@ -1320,7 +1335,7 @@
                 // Notifications that have been interacted with should no longer be lifetime
                 // extended.
                 if (lifetimeExtensionRefactor()) {
-                    // Enqueue a cancellation; this cancellation should only work if
+                    // This cancellation should only work if
                     // the notification still has FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY
                     // We wait for 200 milliseconds before posting the cancel, to allow the app
                     // time to update the notification in response instead.
@@ -1337,7 +1352,7 @@
                                     FLAG_NO_DISMISS /*=mustNotHaveFlags*/,
                                     false /*=sendDelete*/,
                                     r.getUserId(),
-                                    REASON_APP_CANCEL,
+                                    REASON_CLICK,
                                     -1 /*=rank*/,
                                     -1 /*=count*/,
                                     null /*=listener*/,
@@ -1760,9 +1775,50 @@
 
     };
 
-    NotificationManagerPrivate mNotificationManagerPrivate = key -> {
-        synchronized (mNotificationLock) {
-            return mNotificationsByKey.get(key);
+    NotificationManagerPrivate mNotificationManagerPrivate = new NotificationManagerPrivate() {
+        @Nullable
+        @Override
+        public NotificationRecord getNotificationByKey(String key) {
+            synchronized (mNotificationLock) {
+                return mNotificationsByKey.get(key);
+            }
+        }
+
+        @Override
+        @FlaggedApi(Flags.FLAG_ALL_NOTIFS_NEED_TTL)
+        public void timeoutNotification(String key) {
+            boolean foundNotification = false;
+            int uid = 0;
+            int pid = 0;
+            String packageName = null;
+            String tag = null;
+            int id = 0;
+            int userId = 0;
+
+            synchronized (mNotificationLock) {
+                NotificationRecord record = findNotificationByKeyLocked(key);
+                if (record != null) {
+                    foundNotification = true;
+                    uid = record.getUid();
+                    pid = record.getSbn().getInitialPid();
+                    packageName = record.getSbn().getPackageName();
+                    tag = record.getSbn().getTag();
+                    id = record.getSbn().getId();
+                    userId = record.getUserId();
+                }
+            }
+            if (foundNotification) {
+                if (lifetimeExtensionRefactor()) {
+                    cancelNotification(uid, pid, packageName, tag, id, 0,
+                            FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB
+                                    | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY,
+                            true, userId, REASON_TIMEOUT, null);
+                } else {
+                    cancelNotification(uid, pid, packageName, tag, id, 0,
+                            FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB,
+                            true, userId, REASON_TIMEOUT, null);
+                }
+            }
         }
     };
 
@@ -1855,14 +1911,6 @@
                                 FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB
                                         | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY,
                                 true, record.getUserId(), REASON_TIMEOUT, null);
-                        // If cancellation will be prevented due to lifetime extension, we send an
-                        // update to system UI.
-                        final int packageImportance = getPackageImportanceWithIdentity(
-                                record.getSbn().getPackageName());
-                        synchronized (mNotificationLock) {
-                            maybeNotifySystemUiListenerLifetimeExtendedLocked(record,
-                                    record.getSbn().getPackageName(), packageImportance);
-                        }
                     } else {
                         cancelNotification(record.getSbn().getUid(),
                                 record.getSbn().getInitialPid(),
@@ -1900,7 +1948,7 @@
                     || action.equals(Intent.ACTION_PACKAGES_UNSUSPENDED)
                     || action.equals(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED)) {
                 int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_ALL);
+                        USER_ALL);
                 String pkgList[] = null;
                 int uidList[] = null;
                 boolean removingPackage = queryRemove &&
@@ -1949,7 +1997,7 @@
                         try {
                             final int enabled = mPackageManager.getApplicationEnabledSetting(
                                     pkgName,
-                                    changeUserId != UserHandle.USER_ALL ? changeUserId :
+                                    changeUserId != USER_ALL ? changeUserId :
                                             USER_SYSTEM);
                             if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                                     || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
@@ -2062,22 +2110,22 @@
 
     private final class SettingsObserver extends ContentObserver {
         private final Uri NOTIFICATION_BADGING_URI
-                = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BADGING);
+                = Secure.getUriFor(Secure.NOTIFICATION_BADGING);
         private final Uri NOTIFICATION_BUBBLES_URI
-                = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BUBBLES);
+                = Secure.getUriFor(Secure.NOTIFICATION_BUBBLES);
         private final Uri NOTIFICATION_RATE_LIMIT_URI
                 = Settings.Global.getUriFor(Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE);
         private final Uri NOTIFICATION_HISTORY_ENABLED
-                = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
+                = Secure.getUriFor(Secure.NOTIFICATION_HISTORY_ENABLED);
         private final Uri NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI
                 = Settings.Global.getUriFor(Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS);
         private final Uri LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS
-                = Settings.Secure.getUriFor(
-                        Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+                = Secure.getUriFor(
+                        Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
         private final Uri LOCK_SCREEN_SHOW_NOTIFICATIONS
-                = Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
+                = Secure.getUriFor(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
         private final Uri SHOW_NOTIFICATION_SNOOZE
-                = Settings.Secure.getUriFor(Settings.Secure.SHOW_NOTIFICATION_SNOOZE);
+                = Secure.getUriFor(Secure.SHOW_NOTIFICATION_SNOOZE);
 
         SettingsObserver(Handler handler) {
             super(handler);
@@ -2086,27 +2134,31 @@
         void observe() {
             ContentResolver resolver = getContext().getContentResolver();
             resolver.registerContentObserver(NOTIFICATION_BADGING_URI,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_RATE_LIMIT_URI,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_BUBBLES_URI,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_HISTORY_ENABLED,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
 
             resolver.registerContentObserver(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
             resolver.registerContentObserver(LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
 
             resolver.registerContentObserver(SHOW_NOTIFICATION_SNOOZE,
-                    false, this, UserHandle.USER_ALL);
+                    false, this, USER_ALL);
 
             update(null);
         }
 
+        void destroy() {
+            getContext().getContentResolver().unregisterContentObserver(this);
+        }
+
         @Override public void onChange(boolean selfChange, Uri uri, int userId) {
             update(uri);
         }
@@ -2138,7 +2190,7 @@
                 mPreferencesHelper.updateLockScreenShowNotifications();
             }
             if (SHOW_NOTIFICATION_SNOOZE.equals(uri)) {
-                final boolean snoozeEnabled = Settings.Secure.getIntForUser(resolver,
+                final boolean snoozeEnabled = Secure.getIntForUser(resolver,
                         Secure.SHOW_NOTIFICATION_SNOOZE, 0, UserHandle.USER_CURRENT)
                         != 0;
                 if (!snoozeEnabled) {
@@ -2151,8 +2203,8 @@
             ContentResolver resolver = getContext().getContentResolver();
             if (uri == null || NOTIFICATION_HISTORY_ENABLED.equals(uri)) {
                 mArchive.updateHistoryEnabled(userId,
-                        Settings.Secure.getIntForUser(resolver,
-                                Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0,
+                        Secure.getIntForUser(resolver,
+                                Secure.NOTIFICATION_HISTORY_ENABLED, 0,
                                 userId) == 1);
                 // note: this setting is also handled in NotificationHistoryManager
             }
@@ -2236,6 +2288,11 @@
     }
 
     @VisibleForTesting
+    void setLockPatternUtils(LockPatternUtils lockUtils) {
+        mLockUtils = lockUtils;
+    }
+
+    @VisibleForTesting
     ShortcutHelper getShortcutHelper() {
         return mShortcutHelper;
     }
@@ -2407,7 +2464,7 @@
                     getContext().sendBroadcastAsUser(
                             new Intent(ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL)
                                     .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT),
-                            UserHandle.ALL, permission.MANAGE_NOTIFICATIONS);
+                            UserHandle.ALL, android.Manifest.permission.MANAGE_NOTIFICATIONS);
                     synchronized (mNotificationLock) {
                         updateInterruptionFilterLocked();
                     }
@@ -2462,16 +2519,16 @@
                 mNotificationChannelLogger,
                 mAppOps,
                 mUserProfiles,
-                mShowReviewPermissionsNotification);
-        mRankingHelper = new RankingHelper(getContext(),
-                mRankingHandler,
-                mPreferencesHelper,
-                mZenModeHelper,
-                mUsageStats,
-                extractorNames);
+                mShowReviewPermissionsNotification,
+                Clock.systemUTC());
+        mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper,
+                mZenModeHelper, mUsageStats, extractorNames, mPlatformCompat);
         mSnoozeHelper = snoozeHelper;
         mGroupHelper = groupHelper;
         mHistoryManager = historyManager;
+        if (Flags.allNotifsNeedTtl()) {
+            mTtlHelper = new TimeToLiveHelper(mNotificationManagerPrivate, getContext());
+        }
 
         // This is a ManagedServices object that keeps track of the listeners.
         mListeners = notificationListeners;
@@ -2558,10 +2615,12 @@
         getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, sdFilter, null,
                 null);
 
-        IntentFilter timeoutFilter = new IntentFilter(ACTION_NOTIFICATION_TIMEOUT);
-        timeoutFilter.addDataScheme(SCHEME_TIMEOUT);
-        getContext().registerReceiver(mNotificationTimeoutReceiver, timeoutFilter,
-                Context.RECEIVER_EXPORTED_UNAUDITED);
+        if (!Flags.allNotifsNeedTtl()) {
+            IntentFilter timeoutFilter = new IntentFilter(ACTION_NOTIFICATION_TIMEOUT);
+            timeoutFilter.addDataScheme(SCHEME_TIMEOUT);
+            getContext().registerReceiver(mNotificationTimeoutReceiver, timeoutFilter,
+                    Context.RECEIVER_EXPORTED_UNAUDITED);
+        }
 
         IntentFilter settingsRestoredFilter = new IntentFilter(Intent.ACTION_SETTING_RESTORED);
         getContext().registerReceiver(mRestoreReceiver, settingsRestoredFilter);
@@ -2574,15 +2633,16 @@
                 ReviewNotificationPermissionsReceiver.getFilter(),
                 Context.RECEIVER_NOT_EXPORTED);
 
-        mAppOps.startWatchingMode(AppOpsManager.OP_POST_NOTIFICATION, null,
-                new AppOpsManager.OnOpChangedInternalListener() {
-                    @Override
-                    public void onOpChanged(@NonNull String op, @NonNull String packageName,
-                            int userId) {
-                        mHandler.post(
-                                () -> handleNotificationPermissionChange(packageName, userId));
-                    }
-                });
+        mAppOpsListener = new AppOpsManager.OnOpChangedInternalListener() {
+            @Override
+            public void onOpChanged(@NonNull String op, @NonNull String packageName,
+                    int userId) {
+                mHandler.post(
+                        () -> handleNotificationPermissionChange(packageName, userId));
+            }
+        };
+
+        mAppOps.startWatchingMode(AppOpsManager.OP_POST_NOTIFICATION, null, mAppOpsListener);
     }
 
     /**
@@ -2591,10 +2651,26 @@
     public void onDestroy() {
         getContext().unregisterReceiver(mIntentReceiver);
         getContext().unregisterReceiver(mPackageIntentReceiver);
-        getContext().unregisterReceiver(mNotificationTimeoutReceiver);
+        if (Flags.allNotifsNeedTtl()) {
+            mTtlHelper.destroy();
+        } else {
+            getContext().unregisterReceiver(mNotificationTimeoutReceiver);
+        }
         getContext().unregisterReceiver(mRestoreReceiver);
         getContext().unregisterReceiver(mLocaleChangeReceiver);
 
+        mSettingsObserver.destroy();
+        mRoleObserver.destroy();
+        if (mShortcutHelper != null) {
+            mShortcutHelper.destroy();
+        }
+        mStatsManager.clearPullAtomCallback(PACKAGE_NOTIFICATION_PREFERENCES);
+        mStatsManager.clearPullAtomCallback(PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES);
+        mStatsManager.clearPullAtomCallback(PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES);
+        mStatsManager.clearPullAtomCallback(DND_MODE_RULE);
+        mAppOps.stopWatchingMode(mAppOpsListener);
+        mAlarmManager.cancelAll();
+
         if (mDeviceConfigChangedListener != null) {
             DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigChangedListener);
         }
@@ -2849,7 +2925,10 @@
                 bubbsExtractor.setShortcutHelper(mShortcutHelper);
             }
             registerNotificationPreferencesPullers();
-            new LockPatternUtils(getContext()).registerStrongAuthTracker(mStrongAuthTracker);
+            if (mLockUtils == null) {
+                mLockUtils = new LockPatternUtils(getContext());
+            }
+            mLockUtils.registerStrongAuthTracker(mStrongAuthTracker);
             mAttentionHelper.onSystemReady();
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             // This observer will force an update when observe is called, causing us to
@@ -2868,6 +2947,15 @@
                 mZenModeHelper.setDeviceEffectsApplier(
                         new DefaultDeviceEffectsApplier(getContext()));
             }
+            List<ModuleInfo> moduleInfoList =
+            mPackageManagerClient.getInstalledModules(
+                PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
+            // Cache adservices module info
+            for (ModuleInfo mi : moduleInfoList) {
+                if (Objects.equals(mi.getApexModuleName(), ADSERVICES_MODULE_PKG_NAME)) {
+                    mAdservicesModuleInfo = mi;
+                }
+            }
         } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
             mSnoozeHelper.scheduleRepostsForPersistedNotifications(System.currentTimeMillis());
         } else if (phase == SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY) {
@@ -2959,7 +3047,7 @@
 
     void updateNotificationChannelInt(String pkg, int uid, NotificationChannel channel,
             boolean fromListener) {
-        if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
+        if (channel.getImportance() == IMPORTANCE_NONE) {
             // cancel
             cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0,
                     UserHandle.getUserId(uid), REASON_CHANNEL_BANNED
@@ -3224,14 +3312,14 @@
                         | SUPPRESSED_EFFECT_SCREEN_OFF);
 
                 // set the deprecated effects according to the new more specific effects
-                if ((newSuppressedVisualEffects & Policy.SUPPRESSED_EFFECT_PEEK) != 0) {
+                if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_PEEK) != 0) {
                     newSuppressedVisualEffects |= SUPPRESSED_EFFECT_SCREEN_ON;
                 }
-                if ((newSuppressedVisualEffects & Policy.SUPPRESSED_EFFECT_LIGHTS) != 0
+                if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_LIGHTS) != 0
                         && (newSuppressedVisualEffects
-                        & Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) != 0
+                        & SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) != 0
                         && (newSuppressedVisualEffects
-                        & Policy.SUPPRESSED_EFFECT_AMBIENT) != 0) {
+                        & SUPPRESSED_EFFECT_AMBIENT) != 0) {
                     newSuppressedVisualEffects |= SUPPRESSED_EFFECT_SCREEN_OFF;
                 }
             } else {
@@ -3299,7 +3387,7 @@
         if (n.extras != null) {
             title = n.extras.getCharSequence(Notification.EXTRA_TITLE);
             if (title == null) {
-                title = n.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
+                title = n.extras.getCharSequence(EXTRA_TITLE_BIG);
             }
         }
         return title == null ? getContext().getResources().getString(
@@ -3318,9 +3406,9 @@
 
             if (nb.getStyle() instanceof Notification.BigTextStyle) {
                 text = ((Notification.BigTextStyle) nb.getStyle()).getBigText();
-            } else if (nb.getStyle() instanceof Notification.MessagingStyle) {
-                Notification.MessagingStyle ms = (Notification.MessagingStyle) nb.getStyle();
-                final List<Notification.MessagingStyle.Message> messages = ms.getMessages();
+            } else if (nb.getStyle() instanceof MessagingStyle) {
+                MessagingStyle ms = (MessagingStyle) nb.getStyle();
+                final List<MessagingStyle.Message> messages = ms.getMessages();
                 if (messages != null && messages.size() > 0) {
                     text = messages.get(messages.size() - 1).getText();
                 }
@@ -3371,7 +3459,7 @@
     }
 
     private int getRealUserId(int userId) {
-        return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
+        return userId == USER_ALL ? USER_SYSTEM : userId;
     }
 
     private ToastRecord getToastRecord(int uid, int pid, String packageName, boolean isSystemToast,
@@ -3407,21 +3495,21 @@
         // ============================================================================
 
         @Override
-        public void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration,
+        public boolean enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration,
                 boolean isUiContext, int displayId,
                 @Nullable ITransientNotificationCallback textCallback) {
-            enqueueToast(pkg, token, text, /* callback= */ null, duration, isUiContext, displayId,
-                    textCallback);
+            return enqueueToast(pkg, token, text, /* callback= */ null, duration, isUiContext,
+                    displayId, textCallback);
         }
 
         @Override
-        public void enqueueToast(String pkg, IBinder token, ITransientNotification callback,
+        public boolean enqueueToast(String pkg, IBinder token, ITransientNotification callback,
                 int duration, boolean isUiContext, int displayId) {
-            enqueueToast(pkg, token, /* text= */ null, callback, duration, isUiContext, displayId,
-                    /* textCallback= */ null);
+            return enqueueToast(pkg, token, /* text= */ null, callback, duration, isUiContext,
+                    displayId, /* textCallback= */ null);
         }
 
-        private void enqueueToast(String pkg, IBinder token, @Nullable CharSequence text,
+        private boolean enqueueToast(String pkg, IBinder token, @Nullable CharSequence text,
                 @Nullable ITransientNotification callback, int duration, boolean isUiContext,
                 int displayId, @Nullable ITransientNotificationCallback textCallback) {
             if (DBG) {
@@ -3433,7 +3521,7 @@
                     || (text != null && callback != null) || token == null) {
                 Slog.e(TAG, "Not enqueuing toast. pkg=" + pkg + " text=" + text + " callback="
                         + " token=" + token);
-                return;
+                return false;
             }
 
             final int callingUid = Binder.getCallingUid();
@@ -3459,7 +3547,7 @@
             boolean isAppRenderedToast = (callback != null);
             if (!checkCanEnqueueToast(pkg, callingUid, displayId, isAppRenderedToast,
                     isSystemToast)) {
-                return;
+                return false;
             }
 
             synchronized (mToastQueue) {
@@ -3485,7 +3573,7 @@
                                 if (count >= MAX_PACKAGE_TOASTS) {
                                     Slog.e(TAG, "Package has already queued " + count
                                             + " toasts. Not showing more. Package=" + pkg);
-                                    return;
+                                    return false;
                                 }
                             }
                         }
@@ -3521,6 +3609,7 @@
                     Binder.restoreCallingIdentity(callingId);
                 }
             }
+            return true;
         }
 
         @GuardedBy("mToastQueue")
@@ -3605,8 +3694,8 @@
             }
         }
 
-        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_TOAST_RATE_LIMITING)
         @Override
+        @EnforcePermission(android.Manifest.permission.MANAGE_TOAST_RATE_LIMITING)
         public void setToastRateLimitingEnabled(boolean enable) {
 
             super.setToastRateLimitingEnabled_enforcePermission();
@@ -3673,15 +3762,6 @@
             if (lifetimeExtensionRefactor()) {
                 // Also don't allow client apps to cancel lifetime extended notifs.
                 mustNotHaveFlags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
-                // If cancellation will be prevented due to lifetime extension, we send an update to
-                // system UI.
-                NotificationRecord record = null;
-                final int packageImportance = getPackageImportanceWithIdentity(pkg);
-                synchronized (mNotificationLock) {
-                    record = findNotificationLocked(pkg, tag, id, userId);
-                    maybeNotifySystemUiListenerLifetimeExtendedLocked(record, pkg,
-                            packageImportance);
-                }
             }
 
             cancelNotificationInternal(pkg, opPkg, Binder.getCallingUid(), Binder.getCallingPid(),
@@ -3705,9 +3785,9 @@
                 // If cancellation will be prevented due to lifetime extension, we send updates
                 // to system UI.
                 synchronized (mNotificationLock) {
-                    notifySystemUiListenerLifetimeExtendedListLocked(mNotificationList,
+                    maybeNotifySystemUiListenerLifetimeExtendedListLocked(mNotificationList,
                             packageImportance);
-                    notifySystemUiListenerLifetimeExtendedListLocked(mEnqueuedNotifications,
+                    maybeNotifySystemUiListenerLifetimeExtendedListLocked(mEnqueuedNotifications,
                             packageImportance);
                 }
             } else {
@@ -4111,8 +4191,8 @@
         public void createConversationNotificationChannelForPackage(String pkg, int uid,
                 NotificationChannel parentChannel, String conversationId) {
             enforceSystemOrSystemUI("only system can call this");
-            Preconditions.checkNotNull(parentChannel);
-            Preconditions.checkNotNull(conversationId);
+            checkNotNull(parentChannel);
+            checkNotNull(conversationId);
             String parentId = parentChannel.getId();
             NotificationChannel conversationChannel = parentChannel;
             conversationChannel.setId(String.format(
@@ -4540,7 +4620,6 @@
             return getActiveNotificationsWithAttribution(callingPkg, null);
         }
 
-        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of current (i.e. not cleared) notifications.
          *
@@ -4548,6 +4627,7 @@
          * @returns A list of all the notifications, in natural order.
          */
         @Override
+        @EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         public StatusBarNotification[] getActiveNotificationsWithAttribution(String callingPkg,
                 String callingAttributionTag) {
             // enforce() will ensure the calling uid has the correct permission
@@ -4557,7 +4637,7 @@
             int uid = Binder.getCallingUid();
 
             ArrayList<Integer> currentUsers = new ArrayList<>();
-            currentUsers.add(UserHandle.USER_ALL);
+            currentUsers.add(USER_ALL);
             Binder.withCleanCallingIdentity(() -> {
                 for (int user : mUm.getProfileIds(ActivityManager.getCurrentUser(), false)) {
                     currentUsers.add(user);
@@ -4565,9 +4645,9 @@
             });
 
             // noteOp will check to make sure the callingPkg matches the uid
-            if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
-                    callingAttributionTag, null)
-                    == MODE_ALLOWED) {
+            int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
+                        callingAttributionTag, null);
+            if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) {
                 synchronized (mNotificationLock) {
                     final int N = mNotificationList.size();
                     for (int i = 0; i < N; i++) {
@@ -4643,7 +4723,7 @@
                     // Remove background token before returning notification to untrusted app, this
                     // ensures the app isn't able to perform background operations that are
                     // associated with notification interactions.
-                    notification.clearAllowlistToken();
+                    notification.overrideAllowlistToken(null);
                     return new StatusBarNotification(
                             sbn.getPackageName(),
                             sbn.getOpPkg(),
@@ -4667,12 +4747,12 @@
                     includeSnoozed);
         }
 
-        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of recent (cleared, no longer shown) notifications.
          */
         @Override
         @RequiresPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
+        @EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         public StatusBarNotification[] getHistoricalNotificationsWithAttribution(String callingPkg,
                 String callingAttributionTag, int count, boolean includeSnoozed) {
             // enforce() will ensure the calling uid has the correct permission
@@ -4682,9 +4762,9 @@
             int uid = Binder.getCallingUid();
 
             // noteOp will check to make sure the callingPkg matches the uid
-            if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
-                    callingAttributionTag, null)
-                    == MODE_ALLOWED) {
+            int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
+                        callingAttributionTag, null);
+            if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) {
                 synchronized (mArchive) {
                     tmp = mArchive.getArray(mUm, count, includeSnoozed);
                 }
@@ -4692,7 +4772,6 @@
             return tmp;
         }
 
-        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of historical notifications. May contain multiple days
          * of notifications.
@@ -4700,6 +4779,7 @@
         @Override
         @WorkerThread
         @RequiresPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
+        @EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         public NotificationHistory getNotificationHistory(String callingPkg,
                 String callingAttributionTag) {
             // enforce() will ensure the calling uid has the correct permission
@@ -4707,9 +4787,9 @@
             int uid = Binder.getCallingUid();
 
             // noteOp will check to make sure the callingPkg matches the uid
-            if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
-                    callingAttributionTag, null)
-                    == MODE_ALLOWED) {
+            int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
+                        callingAttributionTag, null);
+            if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) {
                 IntArray currentUserIds = mUserProfiles.getCurrentProfileIds();
                 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "notifHistoryReadHistory");
                 try {
@@ -4813,7 +4893,7 @@
          * Register a listener binder directly with the notification manager.
          *
          * Only works with system callers. Apps should extend
-         * {@link android.service.notification.NotificationListenerService}.
+         * {@link NotificationListenerService}.
          */
         @Override
         public void registerListener(final INotificationListener listener,
@@ -4870,7 +4950,7 @@
                             NotificationRecord r = mNotificationsByKey.get(keys[i]);
                             if (r == null) continue;
                             final int userId = r.getSbn().getUserId();
-                            if (userId != info.userid && userId != UserHandle.USER_ALL &&
+                            if (userId != info.userid && userId != USER_ALL &&
                                     !mUserProfiles.isCurrentProfile(userId)) {
                                 continue;
                             }
@@ -4878,7 +4958,7 @@
                                     || isNotificationRecent(r.getUpdateTimeMs());
                             cancelNotificationFromListenerLocked(info, callingUid, callingPid,
                                     r.getSbn().getPackageName(), r.getSbn().getTag(),
-                                    r.getSbn().getId(), userId, reason, packageImportance);
+                                    r.getSbn().getId(), userId, reason);
                         }
                     } else {
                         for (NotificationRecord notificationRecord : mNotificationList) {
@@ -4894,10 +4974,10 @@
                                             | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY);
                             // If cancellation will be prevented due to lifetime extension, we send
                             // an update to system UI.
-                            notifySystemUiListenerLifetimeExtendedListLocked(mNotificationList,
-                                    packageImportance);
-                            notifySystemUiListenerLifetimeExtendedListLocked(mEnqueuedNotifications,
-                                    packageImportance);
+                            maybeNotifySystemUiListenerLifetimeExtendedListLocked(
+                                    mNotificationList, packageImportance);
+                            maybeNotifySystemUiListenerLifetimeExtendedListLocked(
+                                    mEnqueuedNotifications, packageImportance);
                         } else {
                             cancelAllLocked(callingUid, callingPid, info.userid,
                                     REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles(),
@@ -4987,7 +5067,7 @@
                         NotificationRecord r = mNotificationsByKey.get(keys[i]);
                         if (r == null) continue;
                         final int userId = r.getSbn().getUserId();
-                        if (userId != info.userid && userId != UserHandle.USER_ALL
+                        if (userId != info.userid && userId != USER_ALL
                                 && !mUserProfiles.isCurrentProfile(userId)) {
                             continue;
                         }
@@ -5018,14 +5098,10 @@
         @GuardedBy("mNotificationLock")
         private void cancelNotificationFromListenerLocked(ManagedServiceInfo info,
                 int callingUid, int callingPid, String pkg, String tag, int id, int userId,
-                int reason, int packageImportance) {
+                int reason) {
             int mustNotHaveFlags = FLAG_ONGOING_EVENT;
             if (lifetimeExtensionRefactor()) {
                 mustNotHaveFlags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
-                // If cancellation will be prevented due to lifetime extension, we send an update
-                // to system UI.
-                NotificationRecord record = findNotificationLocked(pkg, tag, id, userId);
-                maybeNotifySystemUiListenerLifetimeExtendedLocked(record, pkg, packageImportance);
             }
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0 /* mustHaveFlags */,
                     mustNotHaveFlags,
@@ -5168,13 +5244,7 @@
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final long identity = Binder.clearCallingIdentity();
-            final int packageImportance;
             try {
-                if (lifetimeExtensionRefactor()) {
-                    packageImportance = getPackageImportanceWithIdentity(pkg);
-                } else {
-                    packageImportance = IMPORTANCE_NONE;
-                }
                 synchronized (mNotificationLock) {
                     final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                     int cancelReason = REASON_LISTENER_CANCEL;
@@ -5187,7 +5257,7 @@
                                 + " use cancelNotification(key) instead.");
                     } else {
                         cancelNotificationFromListenerLocked(info, callingUid, callingPid,
-                                pkg, tag, id, info.userid, cancelReason, packageImportance);
+                                pkg, tag, id, info.userid, cancelReason);
                     }
                 }
             } finally {
@@ -5664,7 +5734,7 @@
         }
 
         private void enforcePolicyAccess(int uid, String method) {
-            if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
+            if (PERMISSION_GRANTED == getContext().checkCallingPermission(
                     android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
                 return;
             }
@@ -5695,7 +5765,7 @@
         }
 
         private void enforcePolicyAccess(String pkg, String method) {
-            if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
+            if (PERMISSION_GRANTED == getContext().checkCallingPermission(
                     android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
                 return;
             }
@@ -5716,7 +5786,7 @@
             try {
                 uid = getContext().getPackageManager().getPackageUidAsUser(pkg,
                         UserHandle.getCallingUserId());
-                if (PackageManager.PERMISSION_GRANTED == checkComponentPermission(
+                if (PERMISSION_GRANTED == checkComponentPermission(
                         android.Manifest.permission.MANAGE_NOTIFICATIONS, uid,
                         -1, true)) {
                     return true;
@@ -5911,7 +5981,7 @@
 
         /**
          * Sets the notification policy.  Apps that target API levels below
-         * {@link android.os.Build.VERSION_CODES#P} cannot change user-designated values to
+         * {@link Build.VERSION_CODES#P} cannot change user-designated values to
          * allow or disallow {@link Policy#PRIORITY_CATEGORY_ALARMS},
          * {@link Policy#PRIORITY_CATEGORY_SYSTEM} and
          * {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd
@@ -6279,7 +6349,7 @@
 
         @Override
         public void setPrivateNotificationsAllowed(boolean allow) {
-            if (PackageManager.PERMISSION_GRANTED
+            if (PERMISSION_GRANTED
                     != getContext().checkCallingPermission(CONTROL_KEYGUARD_SECURE_NOTIFICATIONS)) {
                 throw new SecurityException(
                         "Requires CONTROL_KEYGUARD_SECURE_NOTIFICATIONS permission");
@@ -6300,7 +6370,7 @@
 
         @Override
         public boolean getPrivateNotificationsAllowed() {
-            if (PackageManager.PERMISSION_GRANTED
+            if (PERMISSION_GRANTED
                     != getContext().checkCallingPermission(CONTROL_KEYGUARD_SECURE_NOTIFICATIONS)) {
                 throw new SecurityException(
                         "Requires CONTROL_KEYGUARD_SECURE_NOTIFICATIONS permission");
@@ -6588,9 +6658,9 @@
                 // Add summary
                 final ApplicationInfo appInfo =
                         adjustedSbn.getNotification().extras.getParcelable(
-                                Notification.EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class);
+                                EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class);
                 final Bundle extras = new Bundle();
-                extras.putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, appInfo);
+                extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, appInfo);
                 final String channelId = notificationRecord.getChannel().getId();
 
                 final Notification summaryNotification =
@@ -6884,6 +6954,11 @@
             if (!zenOnly) {
                 pw.println("\n  Usage Stats:");
                 mUsageStats.dump(pw, "    ", filter);
+
+                if (Flags.allNotifsNeedTtl()) {
+                    pw.println("\n  TimeToLive alarms:");
+                    mTtlHelper.dump(pw, "    ");
+                }
             }
         }
     }
@@ -7165,6 +7240,10 @@
                 }
             }
         }
+        if (Flags.traceCancelEvents()) {
+            Trace.instant(Trace.TRACE_TAG_SYSTEM_SERVER, "cancelNotificationInternal: " +
+                    SmallHash.hash(Objects.hashCode(tag) ^ id));
+        }
 
         cancelNotification(uid, callingPid, pkg, tag, id, 0,
                 mustNotHaveFlags, false, userId, REASON_APP_CANCEL, null);
@@ -7240,6 +7319,17 @@
                     + " trying to post for invalid pkg " + pkg + " in user " + incomingUserId);
         }
 
+        if (android.app.Flags.secureAllowlistToken()) {
+            IBinder allowlistToken = notification.getAllowlistToken();
+            if (allowlistToken != null && allowlistToken != ALLOWLIST_TOKEN) {
+                throw new SecurityException(
+                        "Unexpected allowlist token received from " + callingUid);
+            }
+            // allowlistToken is populated by unparceling, so it can be null if the notification was
+            // posted from inside system_server. Ensure it's the expected value.
+            notification.overrideAllowlistToken(ALLOWLIST_TOKEN);
+        }
+
         checkRestrictedCategories(notification);
 
         // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE,
@@ -7469,7 +7559,7 @@
             throws NameNotFoundException, RemoteException {
         final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
                 pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
+                (userId == USER_ALL) ? USER_SYSTEM : userId);
         Notification.addFieldsFromContext(ai, notification);
 
         if (notification.isForegroundService() && fgsPolicy == NOT_FOREGROUND_SERVICE) {
@@ -7584,7 +7674,7 @@
             // Enforce NO_CLEAR flag on MediaStyle notification for apps with targetSdk >= V.
             if (CompatChanges.isChangeEnabled(ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION,
                     notificationUid)) {
-                notification.flags |= Notification.FLAG_NO_CLEAR;
+                notification.flags |= FLAG_NO_CLEAR;
             }
         }
 
@@ -7619,13 +7709,27 @@
     private boolean canBeNonDismissible(ApplicationInfo ai, Notification notification) {
         return notification.isMediaNotification() || isEnterpriseExempted(ai)
                 || notification.isStyle(Notification.CallStyle.class)
-                || isDefaultSearchSelectorPackage(ai.packageName);
+                || isDefaultSearchSelectorPackage(ai.packageName)
+                || isDefaultAdservicesPackage(ai.packageName);
     }
 
     private boolean isDefaultSearchSelectorPackage(String pkg) {
         return Objects.equals(mDefaultSearchSelectorPkg, pkg);
     }
 
+    private boolean isDefaultAdservicesPackage(String pkg) {
+        if (mAdservicesModuleInfo == null) {
+            return false;
+        }
+        // Handles the special package structure for mainline modules
+        for (String apkName : mAdservicesModuleInfo.getApkInApexPackageNames()) {
+            if (Objects.equals(apkName, pkg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private boolean isEnterpriseExempted(ApplicationInfo ai) {
         // Check if the app is an organization admin app
         // TODO(b/234609037): Replace with new DPM APIs to check if organization admin
@@ -7636,7 +7740,7 @@
         // Check if an app has been given system exemption
         return mSystemExemptFromDismissal && mAppOps.checkOpNoThrow(
                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
-                ai.packageName) == AppOpsManager.MODE_ALLOWED;
+                ai.packageName) == MODE_ALLOWED;
     }
 
     private boolean checkUseFullScreenIntentPermission(@NonNull AttributionSource attributionSource,
@@ -7741,7 +7845,7 @@
                             // Enqueue will trigger resort & flag is updated that way.
                             r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
                             mHandler.post(
-                                    new NotificationManagerService.EnqueueNotificationRunnable(
+                                    new EnqueueNotificationRunnable(
                                             r.getUser().getIdentifier(), r, isAppForeground,
                                             mPostNotificationTrackerFactory.newTracker(null)));
                         }
@@ -7763,7 +7867,7 @@
 
     @VisibleForTesting
     int resolveNotificationUid(String callingPkg, String targetPkg, int callingUid, int userId) {
-        if (userId == UserHandle.USER_ALL) {
+        if (userId == USER_ALL) {
             userId = USER_SYSTEM;
         }
         // posted from app A on behalf of app A
@@ -8022,7 +8126,7 @@
         final String pkg = r.getSbn().getPackageName();
         final int callingUid = r.getSbn().getUid();
         return mPreferencesHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup())
-                || r.getImportance() == NotificationManager.IMPORTANCE_NONE;
+                || r.getImportance() == IMPORTANCE_NONE;
     }
 
     protected class SnoozeNotificationRunnable implements Runnable {
@@ -8178,13 +8282,16 @@
                 EventLogTags.writeNotificationCancel(mCallingUid, mCallingPid, mPkg, mId, mTag,
                         mUserId, mMustHaveFlags, mMustNotHaveFlags, mReason, listenerName);
             }
-
+            int packageImportance = IMPORTANCE_NONE;
+            if (lifetimeExtensionRefactor()) {
+                packageImportance = getPackageImportanceWithIdentity(mPkg);
+            }
             synchronized (mNotificationLock) {
                 // Look for the notification, searching both the posted and enqueued lists.
                 NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId);
+
                 if (r != null) {
                     // The notification was found, check if it should be removed.
-
                     // Ideally we'd do this in the caller of this method. However, that would
                     // require the caller to also find the notification.
                     if (mReason == REASON_CLICK) {
@@ -8207,6 +8314,12 @@
                         return;
                     }
                     if ((r.getNotification().flags & mMustNotHaveFlags) != 0) {
+                        if (lifetimeExtensionRefactor()) {
+                            // If cancellation will be prevented due to lifetime extension,
+                            // we need to send an update to system UI first.
+                            maybeNotifySystemUiListenerLifetimeExtendedLocked(r, mPkg,
+                                    packageImportance);
+                        }
                         return;
                     }
 
@@ -8350,7 +8463,11 @@
                 }
 
                 mEnqueuedNotifications.add(r);
-                scheduleTimeoutLocked(r);
+                if (Flags.allNotifsNeedTtl()) {
+                    mTtlHelper.scheduleTimeoutLocked(r, SystemClock.elapsedRealtime());
+                } else {
+                    scheduleTimeoutLocked(r);
+                }
 
                 final StatusBarNotification n = r.getSbn();
                 if (DBG) Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
@@ -8570,7 +8687,7 @@
                         Slog.e(TAG, "Not posting notification without small icon: " + notification);
                         if (old != null && !old.isCanceled) {
                             mListeners.notifyRemovedLocked(r,
-                                    NotificationListenerService.REASON_ERROR, r.getStats());
+                                    REASON_ERROR, r.getStats());
                             mHandler.post(new Runnable() {
                                 @Override
                                 public void run() {
@@ -8938,7 +9055,7 @@
         try {
             isExemptFromRateLimiting = mPackageManager.checkPermission(
                     android.Manifest.permission.UNLIMITED_TOASTS, pkg, userId)
-                    == PackageManager.PERMISSION_GRANTED;
+                    == PERMISSION_GRANTED;
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to connect with package manager");
         }
@@ -9463,7 +9580,11 @@
             int rank, int count, boolean wasPosted, String listenerName,
             @ElapsedRealtimeLong long cancellationElapsedTimeMs) {
         final String canceledKey = r.getKey();
-        cancelScheduledTimeoutLocked(r);
+        if (Flags.allNotifsNeedTtl()) {
+            mTtlHelper.cancelScheduledTimeoutLocked(r);
+        } else {
+            cancelScheduledTimeoutLocked(r);
+        }
 
         // Record caller.
         recordCallerLocked(r);
@@ -9640,7 +9761,7 @@
                         // Uri, not when removing an individual listener.
                         revokeUriPermission(permissionOwner, uri,
                                 UserHandle.getUserId(oldRecord.getUid()),
-                                null, UserHandle.USER_ALL);
+                                null, USER_ALL);
                     }
                 }
             }
@@ -9738,9 +9859,9 @@
         } else {
             return
                 // looking for USER_ALL notifications? match everything
-                userId == UserHandle.USER_ALL
+                userId == USER_ALL
                         // a notification sent to USER_ALL matches any query
-                        || r.getUserId() == UserHandle.USER_ALL
+                        || r.getUserId() == USER_ALL
                         // an exact user match
                         || r.getUserId() == userId;
         }
@@ -9819,7 +9940,7 @@
                 continue;
             }
             // Don't remove notifications to all, if there's no package name specified
-            if (nullPkgIndicatesUserSwitch && pkg == null && r.getUserId() == UserHandle.USER_ALL) {
+            if (nullPkgIndicatesUserSwitch && pkg == null && r.getUserId() == USER_ALL) {
                 continue;
             }
             if (!flagChecker.apply(r.getFlags())) {
@@ -10317,7 +10438,7 @@
             return false;
         }
 
-        if (userId == UserHandle.USER_ALL) {
+        if (userId == USER_ALL) {
             userId = USER_SYSTEM;
         }
 
@@ -10540,7 +10661,7 @@
         if (requiredPermission != null) {
             try {
                 if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
-                        != PackageManager.PERMISSION_GRANTED) {
+                        != PERMISSION_GRANTED) {
                     canUseManagedServices = false;
                 }
             } catch (RemoteException e) {
@@ -10666,7 +10787,7 @@
             c.caption = "notification assistant";
             c.serviceInterface = NotificationAssistantService.SERVICE_INTERFACE;
             c.xmlTag = TAG_ENABLED_NOTIFICATION_ASSISTANTS;
-            c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT;
+            c.secureSettingName = Secure.ENABLED_NOTIFICATION_ASSISTANT;
             c.bindPermission = Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE;
             c.settingsAction = Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS;
             c.clientLabel = R.string.notification_ranker_binding_label;
@@ -11121,7 +11242,7 @@
 
     @FlaggedApi(FLAG_LIFETIME_EXTENSION_REFACTOR)
     @GuardedBy("mNotificationLock")
-    private void notifySystemUiListenerLifetimeExtendedListLocked(
+    private void maybeNotifySystemUiListenerLifetimeExtendedListLocked(
             List<NotificationRecord> notificationList, int packageImportance) {
         for (int i = notificationList.size() - 1; i >= 0; --i) {
             NotificationRecord record = notificationList.get(i);
@@ -11262,7 +11383,7 @@
             c.caption = "notification listener";
             c.serviceInterface = NotificationListenerService.SERVICE_INTERFACE;
             c.xmlTag = TAG_ENABLED_NOTIFICATION_LISTENERS;
-            c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
+            c.secureSettingName = Secure.ENABLED_NOTIFICATION_LISTENERS;
             c.bindPermission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
             c.settingsAction = Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS;
             c.clientLabel = R.string.notification_listener_binding_label;
@@ -11661,18 +11782,26 @@
                     }
 
                     if (lifetimeExtensionRefactor()) {
+                        if (sendRedacted && redactedSbn == null) {
+                            redactedSbn = redactStatusBarNotification(sbn);
+                            redactedCache = new TrimCache(redactedSbn);
+                        }
+                        final StatusBarNotification sbnToPost = sendRedacted
+                                ? redactedCache.ForListener(info) : trimCache.ForListener(info);
+
                         // Checks if this is a request to notify system UI about a notification that
                         // has been lifetime extended.
                         // (We only need to check old for the flag, because in both cancellation and
-                        // update cases, old should have the flag.)
+                        // update cases, old should have the flag, whereas in update cases the
+                        // new will NOT have the flag.)
                         // If it is such a request, and this is system UI, we send the post request
                         // only to System UI, and break as we don't need to continue checking other
                         // Managed Services.
                         if (info.isSystemUi() && old != null && old.getNotification() != null
                                 && (old.getNotification().flags
-                                & Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) > 0) {
+                                & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) > 0) {
                             final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
-                            listenerCalls.add(() -> notifyPosted(info, oldSbn, update));
+                            listenerCalls.add(() -> notifyPosted(info, sbnToPost, update));
                             break;
                         }
                     }
@@ -11699,8 +11828,8 @@
                         continue;
                     }
                     // Grant access before listener is notified
-                    final int targetUserId = (info.userid == UserHandle.USER_ALL)
-                            ? UserHandle.USER_SYSTEM : info.userid;
+                    final int targetUserId = (info.userid == USER_ALL)
+                            ? USER_SYSTEM : info.userid;
                     updateUriPermissions(r, old, info.component.getPackageName(), targetUserId);
 
                     mPackageManagerInternal.grantImplicitAccess(
@@ -11803,6 +11932,14 @@
                         redactedText, System.currentTimeMillis(), empty));
                 redactedNotifBuilder.setStyle(messageStyle);
             }
+            if (redactSensitiveNotificationsBigTextStyle()
+                    && oldNotif.isStyle(Notification.BigTextStyle.class)) {
+                Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle();
+                bigTextStyle.bigText(mContext.getString(R.string.redacted_notification_message));
+                bigTextStyle.setBigContentTitle("");
+                bigTextStyle.setSummaryText("");
+                redactedNotifBuilder.setStyle(bigTextStyle);
+            }
 
             Notification redacted = redactedNotifBuilder.build();
             // Notification extras can't always be overridden by a builder (configured by a system
@@ -11849,8 +11986,8 @@
                         continue;
                     }
                     // Grant or revoke access synchronously
-                    final int targetUserId = (info.userid == UserHandle.USER_ALL)
-                            ? UserHandle.USER_SYSTEM : info.userid;
+                    final int targetUserId = (info.userid == USER_ALL)
+                            ? USER_SYSTEM : info.userid;
                     if (grant) {
                         // Grant permissions by passing arguments as if the notification is new.
                         updateUriPermissions(/* newRecord */ r, /* oldRecord */ null,
@@ -11922,7 +12059,7 @@
             }
 
             // Revoke access after all listeners have been updated
-            mHandler.post(() -> updateUriPermissions(null, r, null, UserHandle.USER_SYSTEM));
+            mHandler.post(() -> updateUriPermissions(null, r, null, USER_SYSTEM));
         }
 
         /**
@@ -12082,7 +12219,7 @@
             StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
                 listener.onNotificationPosted(sbnHolder, rankingUpdate);
-            } catch (android.os.DeadObjectException ex) {
+            } catch (DeadObjectException ex) {
                 Slog.wtf(TAG, "unable to notify listener (posted): " + info, ex);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "unable to notify listener (posted): " + info, ex);
@@ -12105,7 +12242,7 @@
                     reason = REASON_LISTENER_CANCEL;
                 }
                 listener.onNotificationRemoved(sbnHolder, rankingUpdate, stats, reason);
-            } catch (android.os.DeadObjectException ex) {
+            } catch (DeadObjectException ex) {
                 Slog.wtf(TAG, "unable to notify listener (removed): " + info, ex);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "unable to notify listener (removed): " + info, ex);
@@ -12117,7 +12254,7 @@
             final INotificationListener listener = (INotificationListener) info.service;
             try {
                 listener.onNotificationRankingUpdate(rankingUpdate);
-            } catch (android.os.DeadObjectException ex) {
+            } catch (DeadObjectException ex) {
                 Slog.wtf(TAG, "unable to notify listener (ranking update): " + info, ex);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "unable to notify listener (ranking update): " + info, ex);
@@ -12336,6 +12473,10 @@
             mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
         }
 
+        void destroy() {
+            mRm.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.ALL);
+        }
+
         @VisibleForTesting
         public boolean isApprovedPackageForRoleForUser(String role, String pkg, int userId) {
             return mNonBlockableDefaultApps.get(role).get(userId).contains(pkg);
@@ -12624,7 +12765,7 @@
                 .setContentIntent(PendingIntent.getActivity(getContext(), 0, tapIntent,
                         PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
                 .setStyle(new Notification.BigTextStyle())
-                .setFlag(Notification.FLAG_NO_CLEAR, true)
+                .setFlag(FLAG_NO_CLEAR, true)
                 .setAutoCancel(true)
                 .addAction(remindMe)
                 .addAction(dismiss)
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 97d2620..38c95f7 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -66,19 +66,21 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.widget.RemoteViews;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.uri.UriGrantsManagerInternal;
+
 import dalvik.annotation.optimization.NeverCompile;
 
 import java.io.PrintWriter;
 import java.lang.reflect.Array;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -500,8 +502,8 @@
         pw.println(prefix + "uid=" + getSbn().getUid() + " userId=" + getSbn().getUserId());
         pw.println(prefix + "opPkg=" + getSbn().getOpPkg());
         pw.println(prefix + "icon=" + notification.getSmallIcon());
-        pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
-        pw.println(prefix + "originalFlags=0x" + Integer.toHexString(mOriginalFlags));
+        pw.println(prefix + "flags=" + Notification.flagsToString(notification.flags));
+        pw.println(prefix + "originalFlags=" + Notification.flagsToString(mOriginalFlags));
         pw.println(prefix + "pri=" + notification.priority);
         pw.println(prefix + "key=" + getSbn().getKey());
         pw.println(prefix + "seen=" + mStats.hasSeen());
@@ -536,8 +538,7 @@
         pw.println(prefix + "mInterruptionTimeMs=" + mInterruptionTimeMs);
         pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
         if (mPreChannelsNotification) {
-            pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
-                    notification.defaults, notification.flags));
+            pw.println(prefix + "defaults=" + Notification.defaultsToString(notification.defaults));
             pw.println(prefix + "n.sound=" + notification.sound);
             pw.println(prefix + "n.audioStreamType=" + notification.audioStreamType);
             pw.println(prefix + "n.audioAttributes=" + notification.audioAttributes);
@@ -600,8 +601,7 @@
         pw.println(prefix + "headsUpContentView="
                 + formatRemoteViews(notification.headsUpContentView));
         pw.println(prefix + String.format("color=0x%08x", notification.color));
-        pw.println(prefix + "timeout="
-                + TimeUtils.formatForLogging(notification.getTimeoutAfter()));
+        pw.println(prefix + "timeout=" + Duration.ofMillis(notification.getTimeoutAfter()));
         if (notification.actions != null && notification.actions.length > 0) {
             pw.println(prefix + "actions={");
             final int N = notification.actions.length;
@@ -1165,7 +1165,11 @@
             mVibration = calculateVibration();
             if (restrictAudioAttributesCall() || restrictAudioAttributesAlarm()
                     || restrictAudioAttributesMedia()) {
-                mAttributes = channel.getAudioAttributes();
+                if (channel.getAudioAttributes() != null) {
+                    mAttributes = channel.getAudioAttributes();
+                } else {
+                    mAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
index 24c1d59..f0358d1 100644
--- a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
@@ -17,6 +17,7 @@
 package com.android.server.notification;
 
 import android.content.Context;
+import com.android.internal.compat.IPlatformCompat;
 
 /**
  * Extracts signals that will be useful to the {@link NotificationComparator} and caches them
@@ -52,4 +53,6 @@
      *               DND.
      */
     void setZenHelper(ZenModeHelper helper);
+
+    default void setCompatChangeLogger(IPlatformCompat platformCompat){};
 }
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 50ca984..1f2ad07e 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -93,6 +93,8 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.time.Clock;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -113,6 +115,8 @@
     private static final int XML_VERSION_REVIEW_PERMISSIONS_NOTIFICATION = 4;
     @VisibleForTesting
     static final int UNKNOWN_UID = UserHandle.USER_NULL;
+    // The amount of time pacakage preferences can exist without the app being installed.
+    private static final long PREF_GRACE_PERIOD_MS = Duration.ofDays(2).toMillis();
 
     @VisibleForTesting
     static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
@@ -149,6 +153,8 @@
     private static final String ATT_USER_DEMOTED_INVALID_MSG_APP = "user_demote_msg_app";
     private static final String ATT_SENT_VALID_BUBBLE = "sent_valid_bubble";
 
+    private static final String ATT_CREATION_TIME = "creation_time";
+
     private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
     private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
     private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
@@ -208,11 +214,13 @@
     private boolean mHideSilentStatusBarIcons = DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS;
     private final boolean mShowReviewPermissionsNotification;
 
+    Clock mClock;
+
     public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager,
             NotificationChannelLogger notificationChannelLogger,
             AppOpsManager appOpsManager, ManagedServices.UserProfiles userProfiles,
-            boolean showReviewPermissionsNotification) {
+            boolean showReviewPermissionsNotification, Clock clock) {
         mContext = context;
         mZenModeHelper = zenHelper;
         mRankingHandler = rankingHandler;
@@ -225,7 +233,7 @@
         mShowReviewPermissionsNotification = showReviewPermissionsNotification;
         mIsMediaNotificationFilteringEnabled = context.getResources()
                 .getBoolean(R.bool.config_quickSettingsShowMediaPlayer);
-
+        mClock = clock;
         XML_VERSION = 4;
 
         updateBadgingEnabled();
@@ -309,7 +317,7 @@
                     parser.getAttributeInt(null, ATT_PRIORITY, DEFAULT_PRIORITY),
                     parser.getAttributeInt(null, ATT_VISIBILITY, DEFAULT_VISIBILITY),
                     parser.getAttributeBoolean(null, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE),
-                    bubblePref);
+                    bubblePref, parser.getAttributeLong(null, ATT_CREATION_TIME, mClock.millis()));
             r.bubblePreference = bubblePref;
             r.priority = parser.getAttributeInt(null, ATT_PRIORITY, DEFAULT_PRIORITY);
             r.visibility = parser.getAttributeInt(null, ATT_VISIBILITY, DEFAULT_VISIBILITY);
@@ -463,12 +471,12 @@
         // TODO (b/194833441): use permissionhelper instead of DEFAULT_IMPORTANCE
         return getOrCreatePackagePreferencesLocked(pkg, UserHandle.getUserId(uid), uid,
                 DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE,
-                DEFAULT_BUBBLE_PREFERENCE);
+                DEFAULT_BUBBLE_PREFERENCE, mClock.millis());
     }
 
     private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg,
             @UserIdInt int userId, int uid, int importance, int priority, int visibility,
-            boolean showBadge, int bubblePreference) {
+            boolean showBadge, int bubblePreference, long creationTime) {
         final String key = packagePreferencesKey(pkg, uid);
         PackagePreferences
                 r = (uid == UNKNOWN_UID)
@@ -483,6 +491,11 @@
             r.visibility = visibility;
             r.showBadge = showBadge;
             r.bubblePreference = bubblePreference;
+            if (Flags.persistIncompleteRestoreData()) {
+                if (r.uid == UNKNOWN_UID) {
+                    r.creationTime = creationTime;
+                }
+            }
 
             try {
                 createDefaultChannelIfNeededLocked(r);
@@ -496,6 +509,12 @@
                 mPackagePreferences.put(key, r);
             }
         }
+        if (r.uid == UNKNOWN_UID) {
+            if (Flags.persistIncompleteRestoreData()
+                    && PREF_GRACE_PERIOD_MS < (mClock.millis() - r.creationTime)) {
+                mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, userId));
+            }
+        }
         return r;
     }
 
@@ -590,70 +609,16 @@
                 if (forBackup && UserHandle.getUserId(r.uid) != userId) {
                     continue;
                 }
-                out.startTag(null, TAG_PACKAGE);
-                out.attribute(null, ATT_NAME, r.pkg);
-                if (!notifPermissions.isEmpty()) {
-                    Pair<Integer, String> app = new Pair(r.uid, r.pkg);
-                    final Pair<Boolean, Boolean> permission = notifPermissions.get(app);
-                    out.attributeInt(null, ATT_IMPORTANCE,
-                            permission != null && permission.first ? IMPORTANCE_DEFAULT
-                                    : IMPORTANCE_NONE);
-                    notifPermissions.remove(app);
-                } else {
-                    if (r.importance != DEFAULT_IMPORTANCE) {
-                        out.attributeInt(null, ATT_IMPORTANCE, r.importance);
-                    }
+                writePackageXml(r, out, notifPermissions, forBackup);
+            }
+        }
+        if (Flags.persistIncompleteRestoreData() && !forBackup) {
+            synchronized (mRestoredWithoutUids) {
+                final int N = mRestoredWithoutUids.size();
+                for (int i = 0; i < N; i++) {
+                    final PackagePreferences r = mRestoredWithoutUids.valueAt(i);
+                    writePackageXml(r, out, notifPermissions, false);
                 }
-                if (r.priority != DEFAULT_PRIORITY) {
-                    out.attributeInt(null, ATT_PRIORITY, r.priority);
-                }
-                if (r.visibility != DEFAULT_VISIBILITY) {
-                    out.attributeInt(null, ATT_VISIBILITY, r.visibility);
-                }
-                if (r.bubblePreference != DEFAULT_BUBBLE_PREFERENCE) {
-                    out.attributeInt(null, ATT_ALLOW_BUBBLE, r.bubblePreference);
-                }
-                out.attributeBoolean(null, ATT_SHOW_BADGE, r.showBadge);
-                out.attributeInt(null, ATT_APP_USER_LOCKED_FIELDS,
-                        r.lockedAppFields);
-                out.attributeBoolean(null, ATT_SENT_INVALID_MESSAGE,
-                        r.hasSentInvalidMessage);
-                out.attributeBoolean(null, ATT_SENT_VALID_MESSAGE,
-                        r.hasSentValidMessage);
-                out.attributeBoolean(null, ATT_USER_DEMOTED_INVALID_MSG_APP,
-                        r.userDemotedMsgApp);
-                out.attributeBoolean(null, ATT_SENT_VALID_BUBBLE, r.hasSentValidBubble);
-
-                if (!forBackup) {
-                    out.attributeInt(null, ATT_UID, r.uid);
-                }
-
-                if (r.delegate != null) {
-                    out.startTag(null, TAG_DELEGATE);
-
-                    out.attribute(null, ATT_NAME, r.delegate.mPkg);
-                    out.attributeInt(null, ATT_UID, r.delegate.mUid);
-                    if (r.delegate.mEnabled != Delegate.DEFAULT_ENABLED) {
-                        out.attributeBoolean(null, ATT_ENABLED, r.delegate.mEnabled);
-                    }
-                    out.endTag(null, TAG_DELEGATE);
-                }
-
-                for (NotificationChannelGroup group : r.groups.values()) {
-                    group.writeXml(out);
-                }
-
-                for (NotificationChannel channel : r.channels.values()) {
-                    if (forBackup) {
-                        if (!channel.isDeleted()) {
-                            channel.writeXmlForBackup(out, mContext);
-                        }
-                    } else {
-                        channel.writeXml(out);
-                    }
-                }
-
-                out.endTag(null, TAG_PACKAGE);
             }
         }
         // Some apps have permissions set but don't have expanded notification settings
@@ -669,6 +634,80 @@
         out.endTag(null, TAG_RANKING);
     }
 
+    public void writePackageXml(PackagePreferences r, TypedXmlSerializer out,
+            ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> notifPermissions,
+            boolean forBackup) throws
+            IOException {
+        out.startTag(null, TAG_PACKAGE);
+        out.attribute(null, ATT_NAME, r.pkg);
+        if (!notifPermissions.isEmpty()) {
+            Pair<Integer, String> app = new Pair(r.uid, r.pkg);
+            final Pair<Boolean, Boolean> permission = notifPermissions.get(app);
+            out.attributeInt(null, ATT_IMPORTANCE,
+                    permission != null && permission.first ? IMPORTANCE_DEFAULT
+                            : IMPORTANCE_NONE);
+            notifPermissions.remove(app);
+        } else {
+            if (r.importance != DEFAULT_IMPORTANCE) {
+                out.attributeInt(null, ATT_IMPORTANCE, r.importance);
+            }
+        }
+        if (r.priority != DEFAULT_PRIORITY) {
+            out.attributeInt(null, ATT_PRIORITY, r.priority);
+        }
+        if (r.visibility != DEFAULT_VISIBILITY) {
+            out.attributeInt(null, ATT_VISIBILITY, r.visibility);
+        }
+        if (r.bubblePreference != DEFAULT_BUBBLE_PREFERENCE) {
+            out.attributeInt(null, ATT_ALLOW_BUBBLE, r.bubblePreference);
+        }
+        out.attributeBoolean(null, ATT_SHOW_BADGE, r.showBadge);
+        out.attributeInt(null, ATT_APP_USER_LOCKED_FIELDS,
+                r.lockedAppFields);
+        out.attributeBoolean(null, ATT_SENT_INVALID_MESSAGE,
+                r.hasSentInvalidMessage);
+        out.attributeBoolean(null, ATT_SENT_VALID_MESSAGE,
+                r.hasSentValidMessage);
+        out.attributeBoolean(null, ATT_USER_DEMOTED_INVALID_MSG_APP,
+                r.userDemotedMsgApp);
+        out.attributeBoolean(null, ATT_SENT_VALID_BUBBLE, r.hasSentValidBubble);
+
+        if (Flags.persistIncompleteRestoreData() && r.uid == UNKNOWN_UID) {
+            out.attributeLong(null, ATT_CREATION_TIME, r.creationTime);
+        }
+
+        if (!forBackup) {
+            out.attributeInt(null, ATT_UID, r.uid);
+        }
+
+        if (r.delegate != null) {
+            out.startTag(null, TAG_DELEGATE);
+
+            out.attribute(null, ATT_NAME, r.delegate.mPkg);
+            out.attributeInt(null, ATT_UID, r.delegate.mUid);
+            if (r.delegate.mEnabled != Delegate.DEFAULT_ENABLED) {
+                out.attributeBoolean(null, ATT_ENABLED, r.delegate.mEnabled);
+            }
+            out.endTag(null, TAG_DELEGATE);
+        }
+
+        for (NotificationChannelGroup group : r.groups.values()) {
+            group.writeXml(out);
+        }
+
+        for (NotificationChannel channel : r.channels.values()) {
+            if (forBackup) {
+                if (!channel.isDeleted()) {
+                    channel.writeXmlForBackup(out, mContext);
+                }
+            } else {
+                channel.writeXml(out);
+            }
+        }
+
+        out.endTag(null, TAG_PACKAGE);
+    }
+
     /**
      * Sets whether bubbles are allowed.
      *
@@ -1387,8 +1426,7 @@
     public void updateFixedImportance(List<UserInfo> users) {
         for (UserInfo user : users) {
             List<PackageInfo> packages = mPm.getInstalledPackagesAsUser(
-                    PackageManager.PackageInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY),
-                    user.getUserHandle().getIdentifier());
+                    0, user.getUserHandle().getIdentifier());
             for (PackageInfo pi : packages) {
                 boolean fixed = mPermissionHelper.isPermissionFixed(
                         pi.packageName, user.getUserHandle().getIdentifier());
@@ -2907,6 +2945,7 @@
         boolean hasSentValidBubble = false;
 
         boolean migrateToPm = false;
+        long creationTime;
 
         Delegate delegate = null;
         ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7b12d86..7756801 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,6 +15,9 @@
  */
 package com.android.server.notification;
 
+import static android.app.Flags.restrictAudioAttributesAlarm;
+import static android.app.Flags.restrictAudioAttributesCall;
+import static android.app.Flags.restrictAudioAttributesMedia;
 import static android.app.Flags.sortSectionByTime;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.text.TextUtils.formatSimple;
@@ -27,6 +30,11 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.compat.IPlatformCompat;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.UsesReflection;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -44,9 +52,16 @@
     private final Context mContext;
     private final RankingHandler mRankingHandler;
 
-
+    @UsesReflection(
+            value = {
+                @KeepTarget(
+                        kind = KeepItemKind.CLASS_AND_MEMBERS,
+                        instanceOfClassConstantExclusive = NotificationSignalExtractor.class,
+                        methodName = "<init>")
+            })
     public RankingHelper(Context context, RankingHandler rankingHandler, RankingConfig config,
-            ZenModeHelper zenHelper, NotificationUsageStats usageStats, String[] extractorNames) {
+            ZenModeHelper zenHelper, NotificationUsageStats usageStats, String[] extractorNames,
+            IPlatformCompat platformCompat) {
         mContext = context;
         mRankingHandler = rankingHandler;
         if (sortSectionByTime()) {
@@ -65,6 +80,10 @@
                 extractor.initialize(mContext, usageStats);
                 extractor.setConfig(config);
                 extractor.setZenHelper(zenHelper);
+                if (restrictAudioAttributesAlarm() || restrictAudioAttributesMedia()
+                        || restrictAudioAttributesCall()) {
+                    extractor.setCompatChangeLogger(platformCompat);
+                }
                 mSignalExtractors[i] = extractor;
             } catch (ClassNotFoundException e) {
                 Slog.w(TAG, "Couldn't find extractor " + extractorNames[i] + ".", e);
diff --git a/services/core/java/com/android/server/notification/ShortcutHelper.java b/services/core/java/com/android/server/notification/ShortcutHelper.java
index fc106b8..86dcecf 100644
--- a/services/core/java/com/android/server/notification/ShortcutHelper.java
+++ b/services/core/java/com/android/server/notification/ShortcutHelper.java
@@ -287,4 +287,11 @@
             }
         }
     }
+
+    void destroy() {
+        if (mLauncherAppsCallbackRegistered) {
+            mLauncherAppsService.unregisterCallback(mLauncherAppsCallback);
+            mLauncherAppsCallbackRegistered = false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/notification/TimeToLiveHelper.java b/services/core/java/com/android/server/notification/TimeToLiveHelper.java
new file mode 100644
index 0000000..2facab7
--- /dev/null
+++ b/services/core/java/com/android/server/notification/TimeToLiveHelper.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.util.Pair;
+import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.PackageManagerService;
+
+import java.io.PrintWriter;
+import java.util.TreeSet;
+
+/**
+ * Handles canceling notifications when their time to live expires
+ */
+@FlaggedApi(Flags.FLAG_ALL_NOTIFS_NEED_TTL)
+public class TimeToLiveHelper {
+    private static final String TAG = TimeToLiveHelper.class.getSimpleName();
+    private static final String ACTION = "com.android.server.notification.TimeToLiveHelper";
+
+    private static final int REQUEST_CODE_TIMEOUT = 1;
+    private static final String SCHEME_TIMEOUT = "timeout";
+    static final String EXTRA_KEY = "key";
+    private final Context mContext;
+    private final NotificationManagerPrivate mNm;
+    private final AlarmManager mAm;
+
+    @VisibleForTesting
+    final TreeSet<Pair<Long, String>> mKeys;
+
+    public TimeToLiveHelper(NotificationManagerPrivate nm, Context context) {
+        mContext = context;
+        mNm = nm;
+        mAm = context.getSystemService(AlarmManager.class);
+        mKeys = new TreeSet<>((left, right) -> Long.compare(left.first, right.first));
+
+        IntentFilter timeoutFilter = new IntentFilter(ACTION);
+        timeoutFilter.addDataScheme(SCHEME_TIMEOUT);
+        mContext.registerReceiver(mNotificationTimeoutReceiver, timeoutFilter,
+                Context.RECEIVER_NOT_EXPORTED);
+    }
+
+    void destroy() {
+        mContext.unregisterReceiver(mNotificationTimeoutReceiver);
+    }
+
+    void dump(PrintWriter pw, String indent) {
+        pw.println(indent + "mKeys " + mKeys);
+    }
+
+    private @NonNull PendingIntent getAlarmPendingIntent(String nextKey, int flags) {
+        flags |= PendingIntent.FLAG_IMMUTABLE;
+        return PendingIntent.getBroadcast(mContext,
+                REQUEST_CODE_TIMEOUT,
+                new Intent(ACTION)
+                        .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
+                        .setData(new Uri.Builder()
+                                .scheme(SCHEME_TIMEOUT)
+                                .appendPath(nextKey)
+                                .build())
+                        .putExtra(EXTRA_KEY, nextKey)
+                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+                flags);
+    }
+
+    @VisibleForTesting
+    void scheduleTimeoutLocked(NotificationRecord record, long currentTime) {
+        removeMatchingEntry(record.getKey());
+
+        final long timeoutAfter = currentTime + record.getNotification().getTimeoutAfter();
+        if (record.getNotification().getTimeoutAfter() > 0) {
+            final Long currentEarliestTime = mKeys.isEmpty() ? null : mKeys.first().first;
+
+            // Maybe replace alarm with an earlier one
+            if (currentEarliestTime == null || timeoutAfter < currentEarliestTime) {
+                if (currentEarliestTime != null) {
+                    cancelFirstAlarm();
+                }
+                mKeys.add(Pair.create(timeoutAfter, record.getKey()));
+                maybeScheduleFirstAlarm();
+            } else {
+                mKeys.add(Pair.create(timeoutAfter, record.getKey()));
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void cancelScheduledTimeoutLocked(NotificationRecord record) {
+        removeMatchingEntry(record.getKey());
+    }
+
+    private void removeMatchingEntry(String key) {
+        if (!mKeys.isEmpty() && key.equals(mKeys.first().second)) {
+            // cancel the first alarm, remove the first entry, maybe schedule the alarm for the new
+            // first entry
+            cancelFirstAlarm();
+            mKeys.remove(mKeys.first());
+            maybeScheduleFirstAlarm();
+        } else {
+            // just remove the entry
+            Pair<Long, String> trackedPair = null;
+            for (Pair<Long, String> entry : mKeys) {
+                if (key.equals(entry.second)) {
+                    trackedPair = entry;
+                    break;
+                }
+            }
+            if (trackedPair != null) {
+                mKeys.remove(trackedPair);
+            }
+        }
+    }
+
+    private void cancelFirstAlarm() {
+        final PendingIntent pi = getAlarmPendingIntent(mKeys.first().second, FLAG_CANCEL_CURRENT);
+        mAm.cancel(pi);
+    }
+
+    private void maybeScheduleFirstAlarm() {
+        if (!mKeys.isEmpty()) {
+            final PendingIntent piNewFirst = getAlarmPendingIntent(mKeys.first().second,
+                    FLAG_UPDATE_CURRENT);
+            mAm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    mKeys.first().first, piNewFirst);
+        }
+    }
+
+    @VisibleForTesting
+    final BroadcastReceiver mNotificationTimeoutReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action == null) {
+                return;
+            }
+            if (ACTION.equals(action)) {
+                Pair<Long, String> earliest = mKeys.first();
+                String key = intent.getStringExtra(EXTRA_KEY);
+                if (!earliest.second.equals(key)) {
+                    Slog.wtf(TAG, "Alarm triggered but wasn't the earliest we were tracking");
+                }
+                removeMatchingEntry(key);
+                mNm.timeoutNotification(earliest.second);
+            }
+        }
+    };
+}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 20b7fd4..4747689 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1105,9 +1105,12 @@
      * {@link ZenRule#equals} or {@link AutomaticZenRule#equals}, for various reasons:
      * <ul>
      *     <li>some metadata-related fields are not considered
-     *     <li>some fields (like {@code condition} are always reset, and ignored for this result
+     *     <li>some fields (like {@code condition} are normally reset, and ignored for this result
      *     <li>an app may provide changes that are not actually applied, as described above
      * </ul>
+     *
+     * <p>The rule's {@link ZenRule#condition} is cleared (meaning that an active rule will be
+     * deactivated) unless the update has origin == {@link ZenModeConfig#UPDATE_ORIGIN_USER}.
      */
     private boolean populateZenRule(String pkg, AutomaticZenRule azr, ZenRule rule,
                          @ConfigChangeOrigin int origin, boolean isNew) {
@@ -1122,11 +1125,20 @@
                 modified = true;
             }
 
-            rule.condition = null;
             if (!Objects.equals(rule.conditionId, azr.getConditionId())) {
                 rule.conditionId = azr.getConditionId();
                 modified = true;
             }
+            boolean shouldPreserveCondition = Flags.modesApi() && Flags.modesUi()
+                    && !isNew && origin == UPDATE_ORIGIN_USER
+                    && rule.enabled == azr.isEnabled()
+                    && rule.conditionId != null && rule.condition != null
+                    && rule.conditionId.equals(rule.condition.id);
+            if (!shouldPreserveCondition) {
+                // Do not update 'modified'. If only this changes we treat it as a no-op updateAZR.
+                rule.condition = null;
+            }
+
             if (rule.enabled != azr.isEnabled()) {
                 rule.enabled = azr.isEnabled();
                 rule.snoozing = false;
@@ -1493,9 +1505,13 @@
             newConfig = mConfig.copy();
             if (zenMode == Global.ZEN_MODE_OFF) {
                 newConfig.manualRule = null;
-                for (ZenRule automaticRule : newConfig.automaticRules.values()) {
-                    if (automaticRule.isAutomaticActive()) {
-                        automaticRule.snoozing = true;
+                if (!Flags.modesUi() || origin != UPDATE_ORIGIN_USER) {
+                    // User deactivation of DND means just turning off the manual DND rule.
+                    // For API calls (different origin) keep old behavior of snoozing all rules.
+                    for (ZenRule automaticRule : newConfig.automaticRules.values()) {
+                        if (automaticRule.isAutomaticActive()) {
+                            automaticRule.snoozing = true;
+                        }
                     }
                 }
             } else {
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index d4641c4..af3db6c 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.notification"
+container: "system"
 
 flag {
   name: "expire_bitmaps"
@@ -94,3 +95,36 @@
   bug: "331967355"
 }
 
+flag {
+  name: "persist_incomplete_restore_data"
+  namespace: "systemui"
+  description: "Stores restore data for not-yet-installed pkgs for 48 hours"
+  bug: "334999659"
+}
+
+flag {
+  name: "trace_cancel_events"
+  namespace: "systemui"
+  description: "Adds performance tracing for binder cancel calls"
+  bug: "331677193"
+  metadata {
+      purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+  name: "exit_invalid_cancel_early"
+  namespace: "systemui"
+  description: "aborts cancel binder events early if notif doesn't exist"
+  bug: "331677193"
+  metadata {
+      purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
+  name: "use_ipcdatacache_channels"
+  namespace: "systemui"
+  description: "Adds an IPCDataCache for notification channel/group lookups"
+  bug: "331677193"
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 4b8e485..6c93fe7 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -32,6 +32,7 @@
 import static android.os.Trace.TRACE_TAG_RRO;
 import static android.os.Trace.traceBegin;
 import static android.os.Trace.traceEnd;
+
 import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;
 
 import android.annotation.NonNull;
@@ -279,7 +280,8 @@
 
             HandlerThread packageMonitorThread = new HandlerThread(TAG);
             packageMonitorThread.start();
-            mPackageMonitor.register(context, packageMonitorThread.getLooper(), true);
+            mPackageMonitor.register(
+                    context, packageMonitorThread.getLooper(), UserHandle.ALL, true);
 
             final IntentFilter userFilter = new IntentFilter();
             userFilter.addAction(ACTION_USER_ADDED);
@@ -369,17 +371,17 @@
 
         @Override
         public void onPackageAppearedWithExtras(String packageName, Bundle extras) {
-            handlePackageAdd(packageName, extras);
+            handlePackageAdd(packageName, extras, getChangingUserId());
         }
 
         @Override
         public void onPackageChangedWithExtras(String packageName, Bundle extras) {
-            handlePackageChange(packageName, extras);
+            handlePackageChange(packageName, extras, getChangingUserId());
         }
 
         @Override
         public void onPackageDisappearedWithExtras(String packageName, Bundle extras) {
-            handlePackageRemove(packageName, extras);
+            handlePackageRemove(packageName, extras, getChangingUserId());
         }
     }
 
@@ -393,54 +395,45 @@
         return userIds;
     }
 
-    private void handlePackageAdd(String packageName, Bundle extras) {
+    private void handlePackageAdd(String packageName, Bundle extras, int userId) {
         final boolean replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
-        final int uid = extras.getInt(Intent.EXTRA_UID, 0);
-        final int[] userIds = getUserIds(uid);
         if (replacing) {
-            onPackageReplaced(packageName, userIds);
+            onPackageReplaced(packageName, userId);
         } else {
-            onPackageAdded(packageName, userIds);
+            onPackageAdded(packageName, userId);
         }
     }
 
-    private void handlePackageChange(String packageName, Bundle extras) {
-        final int uid = extras.getInt(Intent.EXTRA_UID, 0);
-        final int[] userIds = getUserIds(uid);
+    private void handlePackageChange(String packageName, Bundle extras, int userId) {
         if (!ACTION_OVERLAY_CHANGED.equals(extras.getString(EXTRA_REASON))) {
-            onPackageChanged(packageName, userIds);
+            onPackageChanged(packageName, userId);
         }
     }
 
-    private void handlePackageRemove(String packageName, Bundle extras) {
+    private void handlePackageRemove(String packageName, Bundle extras, int userId) {
         final boolean replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
         final boolean systemUpdateUninstall =
                 extras.getBoolean(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, false);
-        final int uid = extras.getInt(Intent.EXTRA_UID, 0);
-        final int[] userIds = getUserIds(uid);
 
         if (replacing) {
-            onPackageReplacing(packageName, systemUpdateUninstall, userIds);
+            onPackageReplacing(packageName, systemUpdateUninstall, userId);
         } else {
-            onPackageRemoved(packageName, userIds);
+            onPackageRemoved(packageName, userId);
         }
     }
 
-    private void onPackageAdded(@NonNull final String packageName,
-            @NonNull final int[] userIds) {
+    private void onPackageAdded(@NonNull final String packageName, final int userId) {
         try {
             traceBegin(TRACE_TAG_RRO, "OMS#onPackageAdded " + packageName);
-            for (final int userId : userIds) {
-                synchronized (mLock) {
-                    var packageState = mPackageManager.onPackageAdded(packageName, userId);
-                    if (packageState != null && !mPackageManager.isInstantApp(packageName,
-                            userId)) {
-                        try {
-                            updateTargetPackagesLocked(
-                                    mImpl.onPackageAdded(packageName, userId));
-                        } catch (OperationFailedException e) {
-                            Slog.e(TAG, "onPackageAdded internal error", e);
-                        }
+            synchronized (mLock) {
+                var packageState = mPackageManager.onPackageAdded(packageName, userId);
+                if (packageState != null && !mPackageManager.isInstantApp(packageName,
+                        userId)) {
+                    try {
+                        updateTargetPackagesLocked(
+                                mImpl.onPackageAdded(packageName, userId));
+                    } catch (OperationFailedException e) {
+                        Slog.e(TAG, "onPackageAdded internal error", e);
                     }
                 }
             }
@@ -449,21 +442,18 @@
         }
     }
 
-    private void onPackageChanged(@NonNull final String packageName,
-            @NonNull final int[] userIds) {
+    private void onPackageChanged(@NonNull final String packageName, final int userId) {
         try {
             traceBegin(TRACE_TAG_RRO, "OMS#onPackageChanged " + packageName);
-            for (int userId : userIds) {
-                synchronized (mLock) {
-                    var packageState = mPackageManager.onPackageUpdated(packageName, userId);
-                    if (packageState != null && !mPackageManager.isInstantApp(packageName,
-                            userId)) {
-                        try {
-                            updateTargetPackagesLocked(
-                                    mImpl.onPackageChanged(packageName, userId));
-                        } catch (OperationFailedException e) {
-                            Slog.e(TAG, "onPackageChanged internal error", e);
-                        }
+            synchronized (mLock) {
+                var packageState = mPackageManager.onPackageUpdated(packageName, userId);
+                if (packageState != null && !mPackageManager.isInstantApp(packageName,
+                        userId)) {
+                    try {
+                        updateTargetPackagesLocked(
+                                mImpl.onPackageChanged(packageName, userId));
+                    } catch (OperationFailedException e) {
+                        Slog.e(TAG, "onPackageChanged internal error", e);
                     }
                 }
             }
@@ -473,20 +463,18 @@
     }
 
     private void onPackageReplacing(@NonNull final String packageName,
-            boolean systemUpdateUninstall, @NonNull final int[] userIds) {
+                                    boolean systemUpdateUninstall, final int userId) {
         try {
             traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplacing " + packageName);
-            for (int userId : userIds) {
-                synchronized (mLock) {
-                    var packageState = mPackageManager.onPackageUpdated(packageName, userId);
-                    if (packageState != null && !mPackageManager.isInstantApp(packageName,
-                            userId)) {
-                        try {
-                            updateTargetPackagesLocked(mImpl.onPackageReplacing(packageName,
-                                    systemUpdateUninstall, userId));
-                        } catch (OperationFailedException e) {
-                            Slog.e(TAG, "onPackageReplacing internal error", e);
-                        }
+            synchronized (mLock) {
+                var packageState = mPackageManager.onPackageUpdated(packageName, userId);
+                if (packageState != null && !mPackageManager.isInstantApp(packageName,
+                        userId)) {
+                    try {
+                        updateTargetPackagesLocked(mImpl.onPackageReplacing(packageName,
+                                systemUpdateUninstall, userId));
+                    } catch (OperationFailedException e) {
+                        Slog.e(TAG, "onPackageReplacing internal error", e);
                     }
                 }
             }
@@ -495,21 +483,18 @@
         }
     }
 
-    private void onPackageReplaced(@NonNull final String packageName,
-            @NonNull final int[] userIds) {
+    private void onPackageReplaced(@NonNull final String packageName, final int userId) {
         try {
             traceBegin(TRACE_TAG_RRO, "OMS#onPackageReplaced " + packageName);
-            for (int userId : userIds) {
-                synchronized (mLock) {
-                    var packageState = mPackageManager.onPackageUpdated(packageName, userId);
-                    if (packageState != null && !mPackageManager.isInstantApp(packageName,
-                            userId)) {
-                        try {
-                            updateTargetPackagesLocked(
-                                    mImpl.onPackageReplaced(packageName, userId));
-                        } catch (OperationFailedException e) {
-                            Slog.e(TAG, "onPackageReplaced internal error", e);
-                        }
+            synchronized (mLock) {
+                var packageState = mPackageManager.onPackageUpdated(packageName, userId);
+                if (packageState != null && !mPackageManager.isInstantApp(packageName,
+                        userId)) {
+                    try {
+                        updateTargetPackagesLocked(
+                                mImpl.onPackageReplaced(packageName, userId));
+                    } catch (OperationFailedException e) {
+                        Slog.e(TAG, "onPackageReplaced internal error", e);
                     }
                 }
             }
@@ -518,15 +503,12 @@
         }
     }
 
-    private void onPackageRemoved(@NonNull final String packageName,
-            @NonNull final int[] userIds) {
+    private void onPackageRemoved(@NonNull final String packageName, final int userId) {
         try {
             traceBegin(TRACE_TAG_RRO, "OMS#onPackageRemoved " + packageName);
-            for (int userId : userIds) {
-                synchronized (mLock) {
-                    mPackageManager.onPackageRemoved(packageName, userId);
-                    updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
-                }
+            synchronized (mLock) {
+                mPackageManager.onPackageRemoved(packageName, userId);
+                updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
             }
         } finally {
             traceEnd(TRACE_TAG_RRO);
diff --git a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
index af339df..99401a1 100644
--- a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
+++ b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
@@ -207,8 +207,9 @@
                     return;
                 }
                 ensureRemoteIntelligenceServiceInitialized();
+                int callerUid = Binder.getCallingUid();
                 mRemoteOnDeviceIntelligenceService.run(
-                        service -> service.getFeature(Binder.getCallingUid(), id, featureCallback));
+                        service -> service.getFeature(callerUid, id, featureCallback));
             }
 
             @Override
@@ -227,8 +228,9 @@
                     return;
                 }
                 ensureRemoteIntelligenceServiceInitialized();
+                int callerUid = Binder.getCallingUid();
                 mRemoteOnDeviceIntelligenceService.run(
-                        service -> service.listFeatures(Binder.getCallingUid(),
+                        service -> service.listFeatures(callerUid,
                                 listFeaturesCallback));
             }
 
@@ -250,8 +252,9 @@
                     return;
                 }
                 ensureRemoteIntelligenceServiceInitialized();
+                int callerUid = Binder.getCallingUid();
                 mRemoteOnDeviceIntelligenceService.run(
-                        service -> service.getFeatureDetails(Binder.getCallingUid(), feature,
+                        service -> service.getFeatureDetails(callerUid, feature,
                                 featureDetailsCallback));
             }
 
@@ -272,8 +275,9 @@
                             PersistableBundle.EMPTY);
                 }
                 ensureRemoteIntelligenceServiceInitialized();
+                int callerUid = Binder.getCallingUid();
                 mRemoteOnDeviceIntelligenceService.run(
-                        service -> service.requestFeatureDownload(Binder.getCallingUid(), feature,
+                        service -> service.requestFeatureDownload(callerUid, feature,
                                 wrapCancellationFuture(cancellationSignalFuture),
                                 downloadCallback));
             }
@@ -301,9 +305,9 @@
                                 PersistableBundle.EMPTY);
                     }
                     ensureRemoteInferenceServiceInitialized();
-
+                    int callerUid = Binder.getCallingUid();
                     result = mRemoteInferenceService.post(
-                            service -> service.requestTokenInfo(Binder.getCallingUid(), feature,
+                            service -> service.requestTokenInfo(callerUid, feature,
                                     request,
                                     wrapCancellationFuture(cancellationSignalFuture),
                                     wrapWithValidation(tokenInfoCallback)));
@@ -340,8 +344,9 @@
                                 PersistableBundle.EMPTY);
                     }
                     ensureRemoteInferenceServiceInitialized();
+                    int callerUid = Binder.getCallingUid();
                     result = mRemoteInferenceService.post(
-                            service -> service.processRequest(Binder.getCallingUid(), feature,
+                            service -> service.processRequest(callerUid, feature,
                                     request,
                                     requestType,
                                     wrapCancellationFuture(cancellationSignalFuture),
@@ -379,8 +384,9 @@
                                 PersistableBundle.EMPTY);
                     }
                     ensureRemoteInferenceServiceInitialized();
+                    int callerUid = Binder.getCallingUid();
                     result = mRemoteInferenceService.post(
-                            service -> service.processRequestStreaming(Binder.getCallingUid(),
+                            service -> service.processRequestStreaming(callerUid,
                                     feature,
                                     request, requestType,
                                     wrapCancellationFuture(cancellationSignalFuture),
@@ -662,7 +668,11 @@
         }
     }
 
+    @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE)
     public void resetTemporaryServices() {
+        enforceShellOnly(Binder.getCallingUid(), "resetTemporaryServices");
+        mContext.enforceCallingPermission(
+                Manifest.permission.USE_ON_DEVICE_INTELLIGENCE, TAG);
         synchronized (mLock) {
             if (mTemporaryHandler != null) {
                 mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
diff --git a/services/core/java/com/android/server/os/Android.bp b/services/core/java/com/android/server/os/Android.bp
index 565dc3b..c588670 100644
--- a/services/core/java/com/android/server/os/Android.bp
+++ b/services/core/java/com/android/server/os/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "core_os_flags",
     package: "com.android.server.os",
+    container: "system",
     srcs: [
         "*.aconfig",
     ],
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 4eb8b2b..c8fd7e4 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -184,6 +184,16 @@
                         throwInvalidBugreportFileForCallerException(
                                 bugreportFile, callingInfo.second);
                     }
+
+                    boolean keepBugreportOnRetrieval = false;
+                    if (onboardingBugreportV2Enabled()) {
+                        keepBugreportOnRetrieval = mBugreportFilesToPersist.contains(
+                                bugreportFile);
+                    }
+
+                    if (!keepBugreportOnRetrieval) {
+                        bugreportFilesForUid.remove(bugreportFile);
+                    }
                 } else {
                     ArraySet<String> bugreportFilesForCaller = mBugreportFiles.get(callingInfo);
                     if (bugreportFilesForCaller != null
diff --git a/services/core/java/com/android/server/os/TEST_MAPPING b/services/core/java/com/android/server/os/TEST_MAPPING
index d937af1..50c8964 100644
--- a/services/core/java/com/android/server/os/TEST_MAPPING
+++ b/services/core/java/com/android/server/os/TEST_MAPPING
@@ -45,6 +45,10 @@
     },
     {
       "file_patterns": ["Bugreport[^/]*\\.java"],
+      "name": "CtsRootBugreportTestCases"
+    },
+    {
+      "file_patterns": ["Bugreport[^/]*\\.java"],
       "name": "ShellTests"
     }
   ]
diff --git a/services/core/java/com/android/server/os/core_os_flags.aconfig b/services/core/java/com/android/server/os/core_os_flags.aconfig
index cbc0d54..ae33df8 100644
--- a/services/core/java/com/android/server/os/core_os_flags.aconfig
+++ b/services/core/java/com/android/server/os/core_os_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.os"
+container: "system"
 
 flag {
     name: "proto_tombstone"
diff --git a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
index 5ebcca8..2c14532 100644
--- a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
@@ -275,10 +275,7 @@
             if (mFrpEnforced) {
                 automaticallyDeactivateFrpIfPossible();
                 setOemUnlockEnabledProperty(doGetOemUnlockEnabled());
-                // Set the SECURE_FRP_MODE flag, for backward compatibility with clients who use it.
-                // They should switch to calling #isFrpActive().
-                Settings.Global.putInt(mContext.getContentResolver(),
-                        Settings.Global.SECURE_FRP_MODE, mFrpActive ? 1 : 0);
+                setOldSettingForBackworkCompatibility(mFrpActive);
             } else {
                 formatIfOemUnlockEnabled();
             }
@@ -292,6 +289,13 @@
         mInitDoneSignal.countDown();
     }
 
+    private void setOldSettingForBackworkCompatibility(boolean isActive) {
+        // Set the SECURE_FRP_MODE flag, for backward compatibility with clients who use it.
+        // They should switch to calling #isFrpActive().
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SECURE_FRP_MODE, isActive ? 1 : 0);
+    }
+
     private void setOemUnlockEnabledProperty(boolean oemUnlockEnabled) {
         setProperty(OEM_UNLOCK_PROP, oemUnlockEnabled ? "1" : "0");
     }
@@ -628,6 +632,7 @@
                 Slog.w(TAG, "Upgrading from Android 14 or lower, defaulting FRP secret");
                 writeFrpMagicAndDefaultSecret();
                 mFrpActive = false;
+                setOldSettingForBackworkCompatibility(mFrpActive);
                 return true;
             }
 
@@ -699,6 +704,7 @@
     void activateFrp() {
         synchronized (mLock) {
             mFrpActive = true;
+            setOldSettingForBackworkCompatibility(mFrpActive);
         }
     }
 
@@ -740,6 +746,7 @@
         if (MessageDigest.isEqual(secret, partitionSecret)) {
             mFrpActive = false;
             Slog.i(TAG, "FRP secret matched, FRP deactivated.");
+            setOldSettingForBackworkCompatibility(mFrpActive);
             return true;
         } else {
             Slog.e(TAG,
@@ -1315,6 +1322,7 @@
         public boolean deactivateFactoryResetProtectionWithoutSecret() {
             synchronized (mLock) {
                 mFrpActive = false;
+                setOldSettingForBackworkCompatibility(/* isActive */ mFrpActive);
             }
             return true;
         }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 2005b17..6a25f64 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -584,8 +584,8 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            mInjector.getCompatibility(), mComponentResolver,
-                            list, false, intent, resolvedType, filterCallingUid);
+                            mInjector.getCompatibility(), this, list, false, intent,
+                            resolvedType, filterCallingUid);
                 }
             }
         } else {
@@ -609,13 +609,15 @@
                 }
                 list = lockedResult.result;
             }
+            PackageManagerServiceUtils.applyNullActionBlocking(
+                    mInjector.getCompatibility(), this, list, false, intent, filterCallingUid);
         }
 
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    mInjector.getCompatibility(), mComponentResolver,
-                    list, false, originalIntent, resolvedType, filterCallingUid);
+                    mInjector.getCompatibility(), this, list, false, originalIntent,
+                    resolvedType, filterCallingUid);
         }
 
         return skipPostResolution ? list : applyPostResolutionFilter(
@@ -698,20 +700,22 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            mInjector.getCompatibility(), mComponentResolver,
-                            list, false, intent, resolvedType, callingUid);
+                            mInjector.getCompatibility(), this, list, false, intent,
+                            resolvedType, callingUid);
                 }
             }
         } else {
             list = queryIntentServicesInternalBody(intent, resolvedType, flags,
                     userId, callingUid, instantAppPkgName);
+            PackageManagerServiceUtils.applyNullActionBlocking(
+                    mInjector.getCompatibility(), this, list, false, intent, callingUid);
         }
 
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    mInjector.getCompatibility(), mComponentResolver,
-                    list, false, originalIntent, resolvedType, callingUid);
+                    mInjector.getCompatibility(), this, list, false, originalIntent,
+                    resolvedType, callingUid);
         }
 
         return list;
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 017cf55..306f77d 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -25,6 +25,7 @@
 
 import android.content.Intent;
 import android.hardware.usb.UsbManager;
+import android.nfc.NfcAdapter;
 import android.provider.AlarmClock;
 import android.provider.MediaStore;
 
@@ -361,6 +362,7 @@
                     .addCategory(Intent.CATEGORY_DEFAULT)
                     .build();
 
+
     public static List<DefaultCrossProfileIntentFilter> getDefaultManagedProfileFilters() {
         List<DefaultCrossProfileIntentFilter> filters =
                 new ArrayList<DefaultCrossProfileIntentFilter>();
@@ -637,6 +639,33 @@
                     .addDataType("video/*")
                     .build();
 
+    /** NFC TAG intent is always resolved by the primary user. */
+    static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_TAG_DISCOVERED =
+            new DefaultCrossProfileIntentFilter.Builder(
+                    DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
+                    /* flags= */0,
+                    /* letsPersonalDataIntoProfile= */ false)
+                    .addAction(NfcAdapter.ACTION_TAG_DISCOVERED)
+                    .build();
+
+    /** NFC TAG intent is always resolved by the primary user. */
+    static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_TECH_DISCOVERED =
+            new DefaultCrossProfileIntentFilter.Builder(
+                    DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
+                    /* flags= */0,
+                    /* letsPersonalDataIntoProfile= */ false)
+                    .addAction(NfcAdapter.ACTION_TECH_DISCOVERED)
+                    .build();
+
+    /** NFC TAG intent is always resolved by the primary user. */
+    static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_NDEF_DISCOVERED =
+            new DefaultCrossProfileIntentFilter.Builder(
+                    DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
+                    /* flags= */0,
+                    /* letsPersonalDataIntoProfile= */ false)
+                    .addAction(NfcAdapter.ACTION_NDEF_DISCOVERED)
+                    .build();
+
     public static List<DefaultCrossProfileIntentFilter> getDefaultCloneProfileFilters() {
         return Arrays.asList(
                 PARENT_TO_CLONE_SEND_ACTION,
@@ -652,7 +681,10 @@
                 CLONE_TO_PARENT_SMS_MMS,
                 CLONE_TO_PARENT_PHOTOPICKER_SELECTION,
                 CLONE_TO_PARENT_ACTION_PICK_IMAGES,
-                CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES
+                CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES,
+                PARENT_TO_CLONE_NFC_TAG_DISCOVERED,
+                PARENT_TO_CLONE_NFC_TECH_DISCOVERED,
+                PARENT_TO_CLONE_NFC_NDEF_DISCOVERED
         );
     }
 
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index fd16221..b2c6c49 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -461,7 +461,7 @@
 
         final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
         // Remember which users are affected, before the installed states are modified
-        outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
+        outInfo.mRemovedUsers = userId == UserHandle.USER_ALL
                 ? ps.queryUsersInstalledOrHasData(allUserHandles)
                 : new int[]{userId};
         outInfo.populateBroadcastUsers(ps);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 2a3b939..d41727f 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -48,6 +48,7 @@
 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
 
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
+import static com.android.server.pm.PackageManagerException.INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE;
 import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME;
 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
@@ -1050,6 +1051,20 @@
                     request.setError("Scanning Failed.", e);
                     return;
                 }
+                if (request.isArchived()) {
+                    final SparseArray<String> responsibleInstallerTitles =
+                            PackageArchiver.getResponsibleInstallerTitles(mContext,
+                                    mPm.snapshotComputer(), request.getInstallSource(),
+                                    request.getUserId(), mPm.mUserManager.getUserIds());
+                    if (responsibleInstallerTitles == null
+                            || responsibleInstallerTitles.size() == 0) {
+                        request.setError(PackageManagerException.ofInternalError(
+                                "Failed to obtain the responsible installer info",
+                                INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE));
+                        return;
+                    }
+                    request.setResponsibleInstallerTitles(responsibleInstallerTitles);
+                }
             }
 
             List<ReconciledPackage> reconciledPackages;
@@ -2226,6 +2241,7 @@
                 // to figure out which users were changed.
                 mPm.markPackageAsArchivedIfNeeded(ps,
                         installRequest.getArchivedPackage(),
+                        installRequest.getResponsibleInstallerTitles(),
                         installRequest.getNewUsers());
                 mPm.updateSequenceNumberLP(ps, installRequest.getNewUsers());
                 mPm.updateInstantAppInstallerLocked(packageName);
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 4dcee04..6d38517 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -49,6 +49,7 @@
 import android.util.ArrayMap;
 import android.util.ExceptionUtils;
 import android.util.Slog;
+import android.util.SparseArray;
 
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
@@ -130,6 +131,12 @@
     @Nullable
     private String mApexModuleName;
 
+    /**
+     * The title of the responsible installer for the archive behavior used
+     */
+    @Nullable
+    private SparseArray<String> mResponsibleInstallerTitles;
+
     @Nullable
     private ScanResult mScanResult;
 
@@ -418,6 +425,12 @@
     public String getApexModuleName() {
         return mApexModuleName;
     }
+
+    @Nullable
+    public SparseArray<String> getResponsibleInstallerTitles() {
+        return mResponsibleInstallerTitles;
+    }
+
     public boolean isRollback() {
         return mInstallArgs != null
                 && mInstallArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK;
@@ -756,6 +769,11 @@
         mApexModuleName = apexModuleName;
     }
 
+    public void setResponsibleInstallerTitles(
+            @NonNull SparseArray<String> responsibleInstallerTitles) {
+        mResponsibleInstallerTitles = responsibleInstallerTitles;
+    }
+
     public void setPkg(AndroidPackage pkg) {
         mPkg = pkg;
     }
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index b87256d..712413c 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -60,9 +60,12 @@
     public static boolean isIntentRedirectionAllowed(Context context,
             AppCloningDeviceConfigHelper appCloningDeviceConfigHelper, boolean resolveForStart,
             long flags) {
+        boolean canMatchCloneProfile = (flags & PackageManager.MATCH_CLONE_PROFILE) != 0
+                || (flags & PackageManager.MATCH_CLONE_PROFILE_LONG) != 0;
         return isAppCloningBuildingBlocksEnabled(context, appCloningDeviceConfigHelper)
-                    && (resolveForStart || (((flags & PackageManager.MATCH_CLONE_PROFILE) != 0)
-                    && hasPermission(context, Manifest.permission.QUERY_CLONED_APPS)));
+                && (resolveForStart
+                    || (canMatchCloneProfile
+                        && hasPermission(context, Manifest.permission.QUERY_CLONED_APPS)));
     }
 
     public NoFilteringResolver(ComponentResolverApi componentResolver,
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index e2f4d18..9bdf613 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -85,13 +85,13 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SELinux;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.ExceptionUtils;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -187,7 +187,7 @@
     }
 
     public static boolean isArchivingEnabled() {
-        return Flags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false);
+        return Flags.archiving();
     }
 
     @VisibleForTesting
@@ -463,8 +463,10 @@
         final CompletableFuture<Void> archiveStateStored = new CompletableFuture<>();
         mPm.mHandler.post(() -> {
             try {
+                final String installerTitle = getResponsibleInstallerTitle(
+                        mContext, installerInfo, responsibleInstallerPackage, userId);
                 var archiveState = createArchiveStateInternal(packageName, userId, mainActivities,
-                        installerInfo.loadLabel(mContext.getPackageManager()).toString());
+                        installerTitle);
                 storeArchiveState(packageName, archiveState, userId);
                 archiveStateStored.complete(null);
             } catch (IOException | PackageManager.NameNotFoundException e) {
@@ -476,7 +478,7 @@
 
     @Nullable
     ArchiveState createArchiveState(@NonNull ArchivedPackageParcel archivedPackage,
-            int userId, String installerPackage) {
+            int userId, String installerPackage, String responsibleInstallerTitle) {
         ApplicationInfo installerInfo = mPm.snapshotComputer().getApplicationInfo(
                 installerPackage, /* flags= */ 0, userId);
         if (installerInfo == null) {
@@ -484,6 +486,11 @@
             Slog.e(TAG, "Couldn't find installer " + installerPackage);
             return null;
         }
+        if (responsibleInstallerTitle == null) {
+            Slog.e(TAG, "Couldn't get the title of the installer");
+            return null;
+        }
+
         final int iconSize = mContext.getSystemService(
                 ActivityManager.class).getLauncherLargeIconSize();
 
@@ -508,8 +515,7 @@
                 archiveActivityInfos.add(activityInfo);
             }
 
-            return new ArchiveState(archiveActivityInfos,
-                    installerInfo.loadLabel(mContext.getPackageManager()).toString());
+            return new ArchiveState(archiveActivityInfos, responsibleInstallerTitle);
         } catch (IOException e) {
             Slog.e(TAG, "Failed to create archive state", e);
             return null;
@@ -1106,10 +1112,61 @@
         return DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS;
     }
 
+    private static String getResponsibleInstallerPackage(InstallSource installSource) {
+        return TextUtils.isEmpty(installSource.mUpdateOwnerPackageName)
+                ? installSource.mInstallerPackageName
+                : installSource.mUpdateOwnerPackageName;
+    }
+
+    private static String getResponsibleInstallerTitle(Context context, ApplicationInfo appInfo,
+            String responsibleInstallerPackage, int userId)
+            throws PackageManager.NameNotFoundException {
+        final Context userContext = context.createPackageContextAsUser(
+                responsibleInstallerPackage, /* flags= */ 0, new UserHandle(userId));
+        return appInfo.loadLabel(userContext.getPackageManager()).toString();
+    }
+
     static String getResponsibleInstallerPackage(PackageStateInternal ps) {
-        return TextUtils.isEmpty(ps.getInstallSource().mUpdateOwnerPackageName)
-                ? ps.getInstallSource().mInstallerPackageName
-                : ps.getInstallSource().mUpdateOwnerPackageName;
+        return getResponsibleInstallerPackage(ps.getInstallSource());
+    }
+
+    @Nullable
+    static SparseArray<String> getResponsibleInstallerTitles(Context context, Computer snapshot,
+            InstallSource installSource, int requestUserId, int[] allUserIds) {
+        final String responsibleInstallerPackage = getResponsibleInstallerPackage(installSource);
+        final SparseArray<String> responsibleInstallerTitles = new SparseArray<>();
+        try {
+            if (requestUserId != UserHandle.USER_ALL) {
+                final ApplicationInfo responsibleInstallerInfo = snapshot.getApplicationInfo(
+                        responsibleInstallerPackage, /* flags= */ 0, requestUserId);
+                if (responsibleInstallerInfo == null) {
+                    return null;
+                }
+
+                final String title = getResponsibleInstallerTitle(context,
+                        responsibleInstallerInfo, responsibleInstallerPackage, requestUserId);
+                responsibleInstallerTitles.put(requestUserId, title);
+            } else {
+                // Go through all userIds.
+                for (int i = 0; i < allUserIds.length; i++) {
+                    final int userId = allUserIds[i];
+                    final ApplicationInfo responsibleInstallerInfo = snapshot.getApplicationInfo(
+                            responsibleInstallerPackage, /* flags= */ 0, userId);
+                    // Can't get the applicationInfo on the user.
+                    // Maybe the installer isn't installed on the user.
+                    if (responsibleInstallerInfo == null) {
+                        continue;
+                    }
+
+                    final String title = getResponsibleInstallerTitle(context,
+                            responsibleInstallerInfo, responsibleInstallerPackage, userId);
+                    responsibleInstallerTitles.put(userId, title);
+                }
+            }
+        } catch (PackageManager.NameNotFoundException ex) {
+            return null;
+        }
+        return responsibleInstallerTitles;
     }
 
     void notifyUnarchivalListener(int status, String installerPackageName, String appPackageName,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 29320ae..a5cd821 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -838,7 +838,8 @@
 
         if ((params.installFlags & PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK) != 0
                 && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)
-                && !Build.IS_DEBUGGABLE) {
+                && !Build.IS_DEBUGGABLE
+                && !PackageManagerServiceUtils.isAdoptedShell(callingUid, mContext)) {
             // If the bypass flag is set, but not running as system root or shell then remove
             // the flag
             params.installFlags &= ~PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 3eeeae7..80a5f3a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1085,11 +1085,17 @@
         final boolean isUpdateOwnershipEnforcementEnabled =
                 mPm.isUpdateOwnershipEnforcementAvailable()
                         && existingUpdateOwnerPackageName != null;
+        // For an installation that un-archives an app, if the installer doesn't have the
+        // INSTALL_PACKAGES permission, the user should have already been prompted to confirm the
+        // un-archive request. There's no need for another confirmation during the installation.
+        final boolean isInstallUnarchive =
+                (params.installFlags & PackageManager.INSTALL_UNARCHIVE) != 0;
 
         // Device owners and affiliated profile owners are allowed to silently install packages, so
         // the permission check is waived if the installer is the device owner.
         final boolean noUserActionNecessary = isInstallerRoot || isInstallerSystem
-                || isInstallerDeviceOwnerOrAffiliatedProfileOwner() || isEmergencyInstall;
+                || isInstallerDeviceOwnerOrAffiliatedProfileOwner() || isEmergencyInstall
+                || isInstallUnarchive;
 
         if (noUserActionNecessary) {
             return userActionNotTypicallyNeededResponse;
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index d69737a..9206759 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -64,6 +64,7 @@
     public static final int INTERNAL_ERROR_APEX_NOT_DIRECTORY = -36;
     public static final int INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE = -37;
     public static final int INTERNAL_ERROR_MISSING_USER = -38;
+    public static final int INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE = -39;
 
     @IntDef(prefix = { "INTERNAL_ERROR_" }, value = {
             INTERNAL_ERROR_NATIVE_LIBRARY_COPY,
@@ -103,7 +104,8 @@
             INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS,
             INTERNAL_ERROR_APEX_NOT_DIRECTORY,
             INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE,
-            INTERNAL_ERROR_MISSING_USER
+            INTERNAL_ERROR_MISSING_USER,
+            INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InternalErrorCode {}
diff --git a/services/core/java/com/android/server/pm/PackageManagerNative.java b/services/core/java/com/android/server/pm/PackageManagerNative.java
index d035084..66ecd6e6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerNative.java
+++ b/services/core/java/com/android/server/pm/PackageManagerNative.java
@@ -68,6 +68,11 @@
         }
     }
 
+    @Override
+    public int getPackageUid(String packageName, long flags, int userId) throws RemoteException {
+        return mPm.snapshotComputer().getPackageUid(packageName, flags, userId);
+    }
+
     // NB: this differentiates between preloads and sideloads
     @Override
     public String getInstallerForPackage(String packageName) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 68cd3e4..0f4e482 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1523,10 +1523,12 @@
     }
 
     void markPackageAsArchivedIfNeeded(PackageSetting pkgSetting,
-                                       ArchivedPackageParcel archivePackage, int[] userIds) {
+            ArchivedPackageParcel archivePackage, SparseArray<String> responsibleInstallerTitles,
+            int[] userIds) {
         if (pkgSetting == null || archivePackage == null
-                || archivePackage.archivedActivities == null || userIds == null
-                || userIds.length == 0) {
+                || archivePackage.archivedActivities == null
+                || responsibleInstallerTitles == null
+                || userIds == null || userIds.length == 0) {
             return;
         }
 
@@ -1552,7 +1554,8 @@
         }
         for (int userId : userIds) {
             var archiveState = mInstallerService.mPackageArchiver.createArchiveState(
-                    archivePackage, userId, responsibleInstallerPackage);
+                    archivePackage, userId, responsibleInstallerPackage,
+                    responsibleInstallerTitles.get(userId));
             if (archiveState != null) {
                 pkgSetting
                     .modifyUserState(userId)
@@ -5753,17 +5756,22 @@
         @Override
         public void setApplicationCategoryHint(String packageName, int categoryHint,
                 String callerPackageName) {
+            final int callingUid = Binder.getCallingUid();
+            final int userId = UserHandle.getCallingUserId();
             final FunctionalUtils.ThrowingBiFunction<PackageStateMutator.InitialState, Computer,
                     PackageStateMutator.Result> implementation = (initialState, computer) -> {
-                if (computer.getInstantAppPackageName(Binder.getCallingUid()) != null) {
+                if (computer.getInstantAppPackageName(callingUid) != null) {
                     throw new SecurityException(
                             "Instant applications don't have access to this method");
                 }
-                mInjector.getSystemService(AppOpsManager.class)
-                        .checkPackage(Binder.getCallingUid(), callerPackageName);
+                final int callerPackageUid = computer.getPackageUid(callerPackageName, 0, userId);
+                if (callerPackageUid != callingUid) {
+                    throw new SecurityException(
+                            "Package " + callerPackageName + " does not belong to " + callingUid);
+                }
 
                 PackageStateInternal packageState = computer.getPackageStateForInstalledAndFiltered(
-                        packageName, Binder.getCallingUid(), UserHandle.getCallingUserId());
+                        packageName, callingUid, userId);
                 if (packageState == null) {
                     throw new IllegalArgumentException("Unknown target package " + packageName);
                 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 9484d0d..5f04a0b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -27,6 +27,7 @@
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
 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.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH;
 import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
 import static com.android.server.pm.PackageInstallerSession.APP_METADATA_FILE_ACCESS_MODE;
 import static com.android.server.pm.PackageInstallerSession.getAppMetadataSizeLimit;
@@ -115,6 +116,7 @@
 import com.android.server.pm.pkg.AndroidPackageSplit;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.resolution.ComponentResolverApi;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 
 import dalvik.system.VMRuntime;
@@ -1198,9 +1200,77 @@
         return (ps.getFlags() & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
-    // Static to give access to ComputeEngine
+    private static ParsedMainComponent componentInfoToComponent(
+            ComponentInfo info, ComponentResolverApi resolver, boolean isReceiver) {
+        if (info instanceof ActivityInfo) {
+            if (isReceiver) {
+                return resolver.getReceiver(info.getComponentName());
+            } else {
+                return resolver.getActivity(info.getComponentName());
+            }
+        } else if (info instanceof ServiceInfo) {
+            return resolver.getService(info.getComponentName());
+        } else {
+            // This shall never happen
+            throw new IllegalArgumentException("Unsupported component type");
+        }
+    }
+
+    /**
+     * Under the correct conditions, remove components if the intent has null action.
+     *
+     * `compat` and `snapshot` may be null when this method is called in ActivityManagerService
+     * CTS tests. The code in this method will properly avoid control flows using these arguments.
+     */
+    public static void applyNullActionBlocking(
+            @Nullable PlatformCompat compat, @Nullable PackageDataSnapshot snapshot,
+            List componentList, boolean isReceiver, Intent intent, int filterCallingUid) {
+        if (ActivityManager.canAccessUnexportedComponents(filterCallingUid)) return;
+
+        final Computer computer = (Computer) snapshot;
+        ComponentResolverApi resolver = null;
+
+        final boolean enforce = android.security.Flags.blockNullActionIntents()
+                && (compat == null || compat.isChangeEnabledByUidInternal(
+                        IntentFilter.BLOCK_NULL_ACTION_INTENTS, filterCallingUid));
+
+        for (int i = componentList.size() - 1; i >= 0; --i) {
+            boolean match = true;
+
+            Object c = componentList.get(i);
+            if (c instanceof ResolveInfo resolveInfo) {
+                if (computer == null) {
+                    // PackageManagerService is not started
+                    return;
+                }
+                if (resolver == null) {
+                    resolver = computer.getComponentResolver();
+                }
+                final ParsedMainComponent comp = componentInfoToComponent(
+                        resolveInfo.getComponentInfo(), resolver, isReceiver);
+                if (!comp.getIntents().isEmpty() && intent.getAction() == null) {
+                    match = false;
+                }
+            } else if (c instanceof IntentFilter) {
+                if (intent.getAction() == null) {
+                    match = false;
+                }
+            }
+
+            if (!match) {
+                ActivityManagerUtils.logUnsafeIntentEvent(
+                        UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH,
+                        filterCallingUid, intent, null, enforce);
+                if (enforce) {
+                    Slog.w(TAG, "Blocking intent with null action: " + intent);
+                    componentList.remove(i);
+                }
+            }
+        }
+    }
+
     public static void applyEnforceIntentFilterMatching(
-            PlatformCompat compat, ComponentResolverApi resolver,
+            PlatformCompat compat, PackageDataSnapshot snapshot,
             List<ResolveInfo> resolveInfos, boolean isReceiver,
             Intent intent, String resolvedType, int filterCallingUid) {
         if (DISABLE_ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS.get()) return;
@@ -1208,13 +1278,19 @@
         // Do not enforce filter matching when the caller is system or root
         if (ActivityManager.canAccessUnexportedComponents(filterCallingUid)) return;
 
+        final Computer computer = (Computer) snapshot;
+        final ComponentResolverApi resolver = computer.getComponentResolver();
+
         final Printer logPrinter = DEBUG_INTENT_MATCHING
                 ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
                 : null;
 
-        final boolean enforce = android.security.Flags.enforceIntentFilterMatch()
+        final boolean enforceMatch = android.security.Flags.enforceIntentFilterMatch()
                 && compat.isChangeEnabledByUidInternal(
                         ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, filterCallingUid);
+        final boolean blockNullAction = android.security.Flags.blockNullActionIntents()
+                && compat.isChangeEnabledByUidInternal(
+                        IntentFilter.BLOCK_NULL_ACTION_INTENTS, filterCallingUid);
 
         for (int i = resolveInfos.size() - 1; i >= 0; --i) {
             final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
@@ -1224,40 +1300,53 @@
                 continue;
             }
 
-            final ParsedMainComponent comp;
-            if (info instanceof ActivityInfo) {
-                if (isReceiver) {
-                    comp = resolver.getReceiver(info.getComponentName());
-                } else {
-                    comp = resolver.getActivity(info.getComponentName());
-                }
-            } else if (info instanceof ServiceInfo) {
-                comp = resolver.getService(info.getComponentName());
-            } else {
-                // This shall never happen
-                throw new IllegalArgumentException("Unsupported component type");
-            }
+            final ParsedMainComponent comp = componentInfoToComponent(info, resolver, isReceiver);
 
             if (comp == null || comp.getIntents().isEmpty()) {
                 continue;
             }
 
-            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)) {
-                    match = true;
-                    break;
+            Boolean match = null;
+
+            if (intent.getAction() == null) {
+                ActivityManagerUtils.logUnsafeIntentEvent(
+                        UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH,
+                        filterCallingUid, intent, resolvedType, enforceMatch && blockNullAction);
+                if (blockNullAction) {
+                    // Skip intent filter matching if blocking null action
+                    match = false;
                 }
             }
-            if (!match) {
+
+            if (match == null) {
+                // Check if any intent filter matches
+                for (int j = 0, size = comp.getIntents().size(); j < size; ++j) {
+                    IntentFilter intentFilter = comp.getIntents().get(j).getIntentFilter();
+                    if (IntentResolver.intentMatchesFilter(intentFilter, intent, resolvedType)) {
+                        match = true;
+                        break;
+                    }
+                }
+            }
+
+            // At this point, the value `match` has the following states:
+            // null : Intent does not match any intent filter
+            // false: Null action intent detected AND blockNullAction == true
+            // true : The intent matches at least one intent filter
+
+            if (match == null) {
                 ActivityManagerUtils.logUnsafeIntentEvent(
                         UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__EXPLICIT_INTENT_FILTER_UNMATCH,
-                        filterCallingUid, intent, resolvedType, enforce);
+                        filterCallingUid, intent, resolvedType, enforceMatch);
+                match = false;
+            }
+
+            if (!match) {
+                // All non-matching intents has to be marked accordingly
                 if (android.security.Flags.enforceIntentFilterMatch()) {
                     intent.addExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
                 }
-                if (enforce) {
+                if (enforceMatch) {
                     Slog.w(TAG, "Intent does not match component's intent filter: " + intent);
                     Slog.w(TAG, "Access blocked: " + comp.getComponentName());
                     if (DEBUG_INTENT_MATCHING) {
@@ -1271,7 +1360,6 @@
         }
     }
 
-
     /**
      * Do NOT use for intent resolution filtering. That should be done with
      * {@link DomainVerificationManagerInternal#filterToApprovedApp(Intent, List, int, Function)}.
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 034e467..1793794 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3387,6 +3387,18 @@
                     }
                     sessionParams.setEnableRollback(true, rollbackStrategy);
                     break;
+                case "--rollback-impact-level":
+                    if (!Flags.recoverabilityDetection()) {
+                        throw new IllegalArgumentException("Unknown option " + opt);
+                    }
+                    int rollbackImpactLevel = Integer.parseInt(peekNextArg());
+                    if (rollbackImpactLevel < PackageManager.ROLLBACK_USER_IMPACT_LOW
+                            || rollbackImpactLevel
+                                    > PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) {
+                        throw new IllegalArgumentException(
+                            rollbackImpactLevel + " is not a valid rollback impact level.");
+                    }
+                    sessionParams.setRollbackImpactLevel(rollbackImpactLevel);
                 case "--staged-ready-timeout":
                     params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired());
                     break;
@@ -4571,6 +4583,11 @@
         pw.println("      --full: cause the app to be installed as a non-ephemeral full app");
         pw.println("      --enable-rollback: enable rollbacks for the upgrade.");
         pw.println("          0=restore (default), 1=wipe, 2=retain");
+        if (Flags.recoverabilityDetection()) {
+            pw.println(
+                    "      --rollback-impact-level: set device impact required for rollback.");
+            pw.println("          0=low (default), 1=high, 2=manual only");
+        }
         pw.println("      --install-location: force the install location:");
         pw.println("          0=auto, 1=internal only, 2=prefer external");
         pw.println("      --install-reason: indicates why the app is being installed:");
diff --git a/services/core/java/com/android/server/pm/PackageSessionVerifier.java b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
index 1fe49c7..7ef7ce7 100644
--- a/services/core/java/com/android/server/pm/PackageSessionVerifier.java
+++ b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
@@ -16,6 +16,8 @@
 
 package com.android.server.pm;
 
+import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.PARSE_APEX;
+
 import android.apex.ApexInfo;
 import android.apex.ApexInfoList;
 import android.apex.ApexSessionInfo;
@@ -399,7 +401,7 @@
             final ParsedPackage parsedPackage;
             try (PackageParser2 packageParser = mPackageParserSupplier.get()) {
                 File apexFile = new File(apexInfo.modulePath);
-                parsedPackage = packageParser.parsePackage(apexFile, 0, false);
+                parsedPackage = packageParser.parsePackage(apexFile, PARSE_APEX, false);
             } catch (PackageParserException e) {
                 throw new PackageManagerException(
                         PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index b664e39..309a448 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -458,7 +458,7 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            mPlatformCompat, componentResolver, list, true, intent,
+                            mPlatformCompat, computer, list, true, intent,
                             resolvedType, filterCallingUid);
                 }
             }
@@ -479,12 +479,14 @@
                     list = result;
                 }
             }
+            PackageManagerServiceUtils.applyNullActionBlocking(
+                    mPlatformCompat, computer, list, true, intent, filterCallingUid);
         }
 
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    mPlatformCompat, componentResolver,
+                    mPlatformCompat, computer,
                     list, true, originalIntent, resolvedType, filterCallingUid);
         }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 4c653f6..fe9c3f2 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -50,6 +50,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.IShortcutService;
 import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutChangeCallback;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -151,6 +152,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Consumer;
@@ -320,12 +322,11 @@
 
     private final Handler mHandler;
 
-    @GuardedBy("mLock")
-    private final ArrayList<ShortcutChangeListener> mListeners = new ArrayList<>(1);
+    private final CopyOnWriteArrayList<ShortcutChangeListener> mListeners =
+            new CopyOnWriteArrayList<>();
 
-    @GuardedBy("mLock")
-    private final ArrayList<LauncherApps.ShortcutChangeCallback> mShortcutChangeCallbacks =
-            new ArrayList<>(1);
+    private final CopyOnWriteArrayList<ShortcutChangeCallback> mShortcutChangeCallbacks =
+            new CopyOnWriteArrayList<>();
 
     private final AtomicLong mRawLastResetTime = new AtomicLong(0);
 
@@ -1841,18 +1842,11 @@
             @UserIdInt final int userId) {
         return () -> {
             try {
-                final ArrayList<ShortcutChangeListener> copy;
-                synchronized (mLock) {
-                    if (!isUserUnlockedL(userId)) {
-                        return;
-                    }
-
-                    copy = new ArrayList<>(mListeners);
+                if (!isUserUnlockedL(userId)) {
+                    return;
                 }
                 // Note onShortcutChanged() needs to be called with the system service permissions.
-                for (int i = copy.size() - 1; i >= 0; i--) {
-                    copy.get(i).onShortcutChanged(packageName, userId);
-                }
+                mListeners.forEach(listener -> listener.onShortcutChanged(packageName, userId));
             } catch (Exception ignore) {
             }
         };
@@ -1867,22 +1861,17 @@
         final UserHandle user = UserHandle.of(userId);
         injectPostToHandler(() -> {
             try {
-                final ArrayList<LauncherApps.ShortcutChangeCallback> copy;
-                synchronized (mLock) {
-                    if (!isUserUnlockedL(userId)) {
-                        return;
-                    }
-
-                    copy = new ArrayList<>(mShortcutChangeCallbacks);
+                if (!isUserUnlockedL(userId)) {
+                    return;
                 }
-                for (int i = copy.size() - 1; i >= 0; i--) {
+                mShortcutChangeCallbacks.forEach(callback -> {
                     if (!CollectionUtils.isEmpty(changedList)) {
-                        copy.get(i).onShortcutsAddedOrUpdated(packageName, changedList, user);
+                        callback.onShortcutsAddedOrUpdated(packageName, changedList, user);
                     }
                     if (!CollectionUtils.isEmpty(removedList)) {
-                        copy.get(i).onShortcutsRemoved(packageName, removedList, user);
+                        callback.onShortcutsRemoved(packageName, removedList, user);
                     }
-                }
+                });
             } catch (Exception ignore) {
             }
         });
@@ -3425,17 +3414,13 @@
 
         @Override
         public void addListener(@NonNull ShortcutChangeListener listener) {
-            synchronized (mLock) {
-                mListeners.add(Objects.requireNonNull(listener));
-            }
+            mListeners.add(Objects.requireNonNull(listener));
         }
 
         @Override
         public void addShortcutChangeCallback(
                 @NonNull LauncherApps.ShortcutChangeCallback callback) {
-            synchronized (mLock) {
-                mShortcutChangeCallbacks.add(Objects.requireNonNull(callback));
-            }
+            mShortcutChangeCallbacks.add(Objects.requireNonNull(callback));
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ff41245..bb6708a 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1882,11 +1882,10 @@
                 && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
             // Allow delayed locking since some profile types want to be able to unlock again via
             // biometrics.
-            ActivityManager.getService()
-                    .stopUserWithDelayedLocking(userId, /* force= */ true, null);
+            ActivityManager.getService().stopUserWithDelayedLocking(userId, null);
             return;
         }
-        ActivityManager.getService().stopUser(userId, /* force= */ true, null);
+        ActivityManager.getService().stopUserWithCallback(userId, null);
     }
 
     private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
@@ -2006,26 +2005,27 @@
     public void setUserAdmin(@UserIdInt int userId) {
         checkManageUserAndAcrossUsersFullPermission("set user admin");
         mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_GRANT_ADMIN);
-        UserInfo info;
+        UserData user;
         synchronized (mPackagesLock) {
             synchronized (mUsersLock) {
-                info = getUserInfoLU(userId);
-            }
-            if (info == null) {
-                // Exit if no user found with that id,
-                mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
+                user = getUserDataLU(userId);
+                if (user == null) {
+                    // Exit if no user found with that id,
+                    mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
                         getCurrentUserId(), userId, /* userType */ "", /* userFlags */ -1);
-                return;
-            } else if (info.isAdmin()) {
-                // Exit if the user is already an Admin.
-                mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), info,
-                        USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_USER_ALREADY_AN_ADMIN);
-                return;
+                    return;
+                } else if (user.info.isAdmin()) {
+                    // Exit if the user is already an Admin.
+                    mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(),
+                        user.info, USER_JOURNEY_GRANT_ADMIN,
+                        ERROR_CODE_USER_ALREADY_AN_ADMIN);
+                    return;
+                }
+                user.info.flags ^= UserInfo.FLAG_ADMIN;
+                writeUserLP(user);
             }
-            info.flags ^= UserInfo.FLAG_ADMIN;
-            writeUserLP(getUserDataLU(info.id));
         }
-        mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), info,
+        mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), user.info,
                 USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_UNSPECIFIED);
     }
 
@@ -6132,7 +6132,7 @@
             if (DBG) Slog.i(LOG_TAG, "Stopping user " + userId);
             int res;
             try {
-                res = ActivityManager.getService().stopUser(userId, /* force= */ true,
+                res = ActivityManager.getService().stopUserWithCallback(userId,
                 new IStopUserCallback.Stub() {
                             @Override
                             public void userStopped(int userIdParam) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 324637c..4e02470 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -721,7 +721,8 @@
                         if (!am.isProfileForeground(UserHandle.of(userId))
                                 && userId != UserHandle.USER_SYSTEM) {
                             try {
-                                ActivityManager.getService().stopUser(userId, false, null);
+                                ActivityManager.getService().stopUserExceptCertainProfiles(
+                                        userId, false, null);
                             } catch (RemoteException e) {
                                 throw e.rethrowAsRuntimeException();
                             }
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 33b5a70..1e7fdfe 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -306,7 +306,7 @@
                         R.color.black)
                 .setDarkThemeBadgeColors(
                         R.color.white)
-                .setDefaultRestrictions(getDefaultProfileRestrictions())
+                .setDefaultRestrictions(getDefaultPrivateProfileRestrictions())
                 .setDefaultCrossProfileIntentFilters(getDefaultPrivateCrossProfileIntentFilter())
                 .setDefaultUserProperties(new UserProperties.Builder()
                         .setStartWithParent(true)
@@ -430,6 +430,13 @@
         return restrictions;
     }
 
+    @VisibleForTesting
+    static Bundle getDefaultPrivateProfileRestrictions() {
+        final Bundle restrictions = getDefaultProfileRestrictions();
+        restrictions.putBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING, true);
+        return restrictions;
+    }
+
     private static Bundle getDefaultManagedProfileSecureSettings() {
         // Only add String values to the bundle, settings are written as Strings eventually
         final Bundle settings = new Bundle();
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 f7f76aa..57ea233 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -807,7 +807,7 @@
                     getDefaultSystemHandlerActivityPackage(pm,
                             SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
                     userId, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
-                    NOTIFICATION_PERMISSIONS, PHONE_PERMISSIONS);
+                    NOTIFICATION_PERMISSIONS, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS);
         }
 
         // Voice recognition
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index bd0501d9..28254d0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -462,6 +462,11 @@
     }
 
     @Override
+    public int getRegisteredAttributionSourceCount(int uid) {
+        return mAttributionSourceRegistry.getRegisteredAttributionSourceCount(uid);
+    }
+
+    @Override
     public List<String> getAutoRevokeExemptionRequestedPackages(int userId) {
         return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId);
     }
@@ -938,6 +943,25 @@
             }
         }
 
+        public int getRegisteredAttributionSourceCount(int uid) {
+            mContext.enforceCallingOrSelfPermission(UPDATE_APP_OPS_STATS,
+                    "getting the number of registered AttributionSources requires "
+                            + "UPDATE_APP_OPS_STATS");
+            // Influence the system to perform a garbage collection, so the provided number is as
+            // accurate as possible
+            System.gc();
+            System.gc();
+            synchronized (mLock) {
+                int numForUid = 0;
+                for (Map.Entry<IBinder, AttributionSource> entry : mAttributions.entrySet()) {
+                    if (entry.getValue().getUid() == uid) {
+                        numForUid++;
+                    }
+                }
+                return numForUid;
+            }
+        }
+
         private int resolveUid(int uid) {
             final VoiceInteractionManagerInternal vimi = LocalServices
                     .getService(VoiceInteractionManagerInternal.class);
diff --git a/services/core/java/com/android/server/policy/Android.bp b/services/core/java/com/android/server/policy/Android.bp
index fa55bf0..325b6cb 100644
--- a/services/core/java/com/android/server/policy/Android.bp
+++ b/services/core/java/com/android/server/policy/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "policy_flags",
     package: "com.android.server.policy",
+    container: "system",
     srcs: ["*.aconfig"],
 }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7db83d7..db18276 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -76,6 +76,7 @@
 import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled;
 
 import static com.android.hardware.input.Flags.emojiAndScreenshotKeycodesAvailable;
+import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
@@ -174,7 +175,6 @@
 import android.service.vr.IPersistentVrStateCallbacks;
 import android.speech.RecognizerIntent;
 import android.telecom.TelecomManager;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.MutableBoolean;
@@ -467,8 +467,8 @@
     // Assigned on main thread, accessed on UI thread
     volatile VrManagerInternal mVrManagerInternal;
 
-    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
-    boolean mEnableShiftMenuBugReports = false;
+    /** If true, can use a keyboard shortcut to trigger a bugreport. */
+    boolean mEnableBugReportKeyboardShortcut = false;
 
     /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
     private AccessibilityShortcutController mAccessibilityShortcutController;
@@ -2304,7 +2304,7 @@
                 "PhoneWindowManager.mBroadcastWakeLock");
         mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                 "PhoneWindowManager.mPowerKeyWakeLock");
-        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
+        mEnableBugReportKeyboardShortcut = "1".equals(SystemProperties.get("ro.debuggable"));
         mLidKeyboardAccessibility = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
         mLidNavigationAccessibility = mContext.getResources().getInteger(
@@ -2361,8 +2361,7 @@
 
         mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
 
-        mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
-                Context.ACCESSIBILITY_SERVICE);
+        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
 
         // register for dock events
         IntentFilter filter = new IntentFilter();
@@ -3410,19 +3409,6 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_HOME:
                 return handleHomeShortcuts(focusedToken, event);
-            case KeyEvent.KEYCODE_MENU:
-                // Hijack modified menu keys for debugging features
-                final int chordBug = KeyEvent.META_SHIFT_ON;
-
-                if (mEnableShiftMenuBugReports && firstDown
-                        && (metaState & chordBug) == chordBug) {
-                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
-                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
-                            null, null, null, 0, null, null);
-                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
-                    return true;
-                }
-                break;
             case KeyEvent.KEYCODE_RECENT_APPS:
                 if (firstDown) {
                     showRecentApps(false /* triggeredFromAltTab */);
@@ -3488,6 +3474,19 @@
                 }
                 break;
             case KeyEvent.KEYCODE_DEL:
+                if (newBugreportKeyboardShortcut()) {
+                    if (mEnableBugReportKeyboardShortcut && firstDown
+                            && event.isMetaPressed() && event.isCtrlPressed()) {
+                        try {
+                            mActivityManagerService.requestInteractiveBugReport();
+                        } catch (RemoteException e) {
+                            Slog.d(TAG, "Error taking bugreport", e);
+                        }
+                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
+                        return true;
+                    }
+                }
+                // fall through
             case KeyEvent.KEYCODE_ESCAPE:
                 if (firstDown && event.isMetaPressed()) {
                     logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
@@ -4121,14 +4120,10 @@
 
     private void handleSwitchKeyboardLayout(@NonNull KeyEvent event, int direction,
             IBinder focusedToken) {
-        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
-            IBinder targetWindowToken =
-                    mWindowManagerInternal.getTargetWindowTokenFromInputToken(focusedToken);
-            InputMethodManagerInternal.get().onSwitchKeyboardLayoutShortcut(direction,
-                    event.getDisplayId(), targetWindowToken);
-        } else {
-            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
-        }
+        IBinder targetWindowToken =
+                mWindowManagerInternal.getTargetWindowTokenFromInputToken(focusedToken);
+        InputMethodManagerInternal.get().onSwitchKeyboardLayoutShortcut(direction,
+                event.getDisplayId(), targetWindowToken);
     }
 
     private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 2623025..9ca4e27 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -251,12 +251,6 @@
          */
         public int getCameraLensCoverState();
 
-        /**
-         * Switch the keyboard layout for the given device.
-         * Direction should be +1 or -1 to go to the next or previous keyboard layout.
-         */
-        public void switchKeyboardLayout(int deviceId, int direction);
-
         public void shutdown(boolean confirm);
         public void reboot(boolean confirm);
         public void rebootSafeMode(boolean confirm);
diff --git a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
index a790950..af1ad13 100644
--- a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
@@ -34,7 +34,9 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.Display;
 import android.view.KeyEvent;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.Clock;
@@ -48,6 +50,7 @@
 
     private final Context mContext;
     private final PowerManager mPowerManager;
+    private final WindowManager mWindowManager;
     private final Clock mClock;
 
     private final boolean mAllowTheaterModeWakeFromKey;
@@ -68,6 +71,7 @@
     WindowWakeUpPolicy(Context context, Clock clock) {
         mContext = context;
         mPowerManager = context.getSystemService(PowerManager.class);
+        mWindowManager = context.getSystemService(WindowManager.class);
         mClock = clock;
 
         final Resources res = context.getResources();
@@ -212,12 +216,23 @@
     }
 
     private boolean canWakeUp(boolean wakeInTheaterMode) {
+        if (supportInputWakeupDelegate() && isDefaultDisplayOn()) {
+            // If the default display is on, theater mode should not influence whether or not
+            // waking up is allowed. This is because the theater mode checks are there to block
+            // the display from being on in situations where the user may not want it to be
+            // on (so if the display is already on, no need to check for theater mode at all).
+            return true;
+        }
         final boolean isTheaterModeEnabled =
                 Settings.Global.getInt(
                         mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0) == 1;
         return wakeInTheaterMode || !isTheaterModeEnabled;
     }
 
+    private boolean isDefaultDisplayOn() {
+        return Display.isOnState(mWindowManager.getDefaultDisplay().getState());
+    }
+
     /** Wakes up {@link PowerManager}. */
     private void wakeUp(long wakeTime, @WakeReason int reason, String details) {
         mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
diff --git a/services/core/java/com/android/server/policy/window_policy_flags.aconfig b/services/core/java/com/android/server/policy/window_policy_flags.aconfig
index 2154a26..7914b94 100644
--- a/services/core/java/com/android/server/policy/window_policy_flags.aconfig
+++ b/services/core/java/com/android/server/policy/window_policy_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.policy"
+container: "system"
 
 flag {
     name: "support_input_wakeup_delegate"
diff --git a/services/core/java/com/android/server/power/Android.bp b/services/core/java/com/android/server/power/Android.bp
deleted file mode 100644
index 863ff76..0000000
--- a/services/core/java/com/android/server/power/Android.bp
+++ /dev/null
@@ -1,13 +0,0 @@
-aconfig_declarations {
-    name: "backstage_power_flags",
-    package: "com.android.server.power.optimization",
-    srcs: [
-        "stats/*.aconfig",
-    ],
-}
-
-java_aconfig_library {
-    name: "backstage_power_flags_lib",
-    aconfig_declarations: "backstage_power_flags",
-    sdk_version: "system_current",
-}
diff --git a/services/core/java/com/android/server/power/FaceDownDetector.java b/services/core/java/com/android/server/power/FaceDownDetector.java
index b237ca2..84ed87a 100644
--- a/services/core/java/com/android/server/power/FaceDownDetector.java
+++ b/services/core/java/com/android/server/power/FaceDownDetector.java
@@ -76,6 +76,8 @@
     private static final boolean DEFAULT_FEATURE_ENABLED = true;
 
     private boolean mIsEnabled;
+    // Defaults to true, we only want to disable if this is specifically requested.
+    private boolean mEnabledOverride = true;
 
     private int mSensorMaxLatencyMicros;
 
@@ -240,6 +242,7 @@
         pw.println("  mZAccelerationThreshold=" + mZAccelerationThreshold);
         pw.println("  mAccelerationThreshold=" + mAccelerationThreshold);
         pw.println("  mTimeThreshold=" + mTimeThreshold);
+        pw.println("  mEnabledOverride=" + mEnabledOverride);
     }
 
     @Override
@@ -336,10 +339,9 @@
     }
 
     private boolean isEnabled() {
-        return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, KEY_FEATURE_ENABLED,
-                DEFAULT_FEATURE_ENABLED)
-                && mContext.getResources().getBoolean(
-                        com.android.internal.R.bool.config_flipToScreenOffEnabled);
+        return mEnabledOverride && DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                KEY_FEATURE_ENABLED, DEFAULT_FEATURE_ENABLED) && mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_flipToScreenOffEnabled);
     }
 
     private float getAccelerationThreshold() {
@@ -450,6 +452,15 @@
     }
 
     /**
+     * Allows detector to be enabled & disabled.
+     * @param enabled whether to enable detector.
+     */
+    public void setEnabledOverride(boolean enabled) {
+        mEnabledOverride = enabled;
+        mIsEnabled = isEnabled();
+    }
+
+    /**
      * Sets how much screen on time might be saved as a result of this detector. Currently used for
      * logging purposes.
      */
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b5d49b3..eb1f720 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -6921,6 +6921,16 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
+
+        public void setUseFaceDownDetector(boolean enable) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mFaceDownDetector.setEnabledOverride(enable);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/power/PowerManagerShellCommand.java b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
index 9439b76..20184e9f 100644
--- a/services/core/java/com/android/server/power/PowerManagerShellCommand.java
+++ b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
@@ -63,6 +63,8 @@
                     return runListAmbientDisplaySuppressionTokens();
                 case "set-prox":
                     return runSetProx();
+                case "set-face-down-detector":
+                    return runSetFaceDownDetector();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -178,6 +180,20 @@
         return 0;
     }
 
+    /**
+     * To be used for testing - allowing us to disable the usage of face down detector.
+     */
+    private int runSetFaceDownDetector() {
+        try {
+            mService.setUseFaceDownDetector(Boolean.parseBoolean(getNextArgRequired()));
+        } catch (Exception e) {
+            PrintWriter pw = getOutPrintWriter();
+            pw.println("Error: " + e);
+            return -1;
+        }
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -203,6 +219,8 @@
         pw.println("    Acquires the proximity sensor wakelock. Wakelock is associated with");
         pw.println("    a specific display if specified. 'list' lists wakelocks previously");
         pw.println("    created by set-prox including their held status.");
+        pw.println("  set-face-down-detector [true|false]");
+        pw.println("    sets whether we use face down detector timeouts or not");
 
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
diff --git a/services/core/java/com/android/server/power/batterysaver/OWNERS b/services/core/java/com/android/server/power/batterysaver/OWNERS
index cf23bea..dc2d0b3 100644
--- a/services/core/java/com/android/server/power/batterysaver/OWNERS
+++ b/services/core/java/com/android/server/power/batterysaver/OWNERS
@@ -1,3 +1,2 @@
[email protected]
 [email protected]
[email protected]
\ No newline at end of file
[email protected]
diff --git a/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING b/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING
index c091b8e..eb91a72 100644
--- a/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING
+++ b/services/core/java/com/android/server/power/batterysaver/TEST_MAPPING
@@ -5,12 +5,7 @@
     },
     {
       "name": "CtsLocationFineTestCases",
-      "options": [
-          {
-             // TODO: Wait for test to deflake - b/293934372
-             "exclude-filter":"android.location.cts.fine.ScanningSettingsTest"
-          }
-      ]
+      "options": []
     },
     {
       "name": "CtsLocationNoneTestCases"
diff --git a/services/core/java/com/android/server/power/feature/Android.bp b/services/core/java/com/android/server/power/feature/Android.bp
index 2295b41..fee3114 100644
--- a/services/core/java/com/android/server/power/feature/Android.bp
+++ b/services/core/java/com/android/server/power/feature/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "power_flags",
     package: "com.android.server.power.feature.flags",
+    container: "system",
     srcs: [
         "*.aconfig",
     ],
diff --git a/services/core/java/com/android/server/power/feature/power_flags.aconfig b/services/core/java/com/android/server/power/feature/power_flags.aconfig
index f5dfb5c..ca58153 100644
--- a/services/core/java/com/android/server/power/feature/power_flags.aconfig
+++ b/services/core/java/com/android/server/power/feature/power_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.power.feature.flags"
+container: "system"
 
 # Important: Flags must be accessed through PowerManagerFlags.
 
diff --git a/services/core/java/com/android/server/power/hint/Android.bp b/services/core/java/com/android/server/power/hint/Android.bp
index 8a98de6..6dadf8f 100644
--- a/services/core/java/com/android/server/power/hint/Android.bp
+++ b/services/core/java/com/android/server/power/hint/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "power_hint_flags",
     package: "com.android.server.power.hint",
+    container: "system",
     srcs: [
         "flags.aconfig",
     ],
@@ -10,3 +11,10 @@
     name: "power_hint_flags_lib",
     aconfig_declarations: "power_hint_flags",
 }
+
+java_aconfig_library {
+    name: "power_hint_flags_lib_host",
+    aconfig_declarations: "power_hint_flags",
+    host_supported: true,
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 101983e..6e17fd3 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -20,11 +20,14 @@
 import static com.android.server.power.hint.Flags.powerhintThreadCleanup;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.StatsManager;
 import android.app.UidObserver;
 import android.content.Context;
+import android.hardware.power.SessionConfig;
+import android.hardware.power.SessionTag;
 import android.hardware.power.WorkDuration;
 import android.os.Binder;
 import android.os.Handler;
@@ -67,6 +70,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /** An hint service implementation that runs in System Server process. */
 public final class HintManagerService extends SystemService {
@@ -87,7 +91,7 @@
     @GuardedBy("mLock")
     private final ArrayMap<Integer, ArrayMap<IBinder, ArraySet<AppHintSession>>> mActiveSessions;
 
-    /** Lock to protect HAL handles and listen list. */
+    /** Lock to protect mActiveSessions. */
     private final Object mLock = new Object();
 
     @GuardedBy("mNonIsolatedTidsLock")
@@ -104,6 +108,8 @@
 
     private final Context mContext;
 
+    private AtomicBoolean mConfigCreationSupport = new AtomicBoolean(true);
+
     private static final String PROPERTY_SF_ENABLE_CPU_HINT = "debug.sf.enable_adpf_cpu_hint";
     private static final String PROPERTY_HWUI_ENABLE_HINT_MANAGER = "debug.hwui.use_hint_manager";
 
@@ -217,6 +223,9 @@
         private static native long nativeCreateHintSession(int tgid, int uid, int[] tids,
                 long durationNanos);
 
+        private static native long nativeCreateHintSessionWithConfig(int tgid, int uid, int[] tids,
+                long durationNanos, int tag, SessionConfig config);
+
         private static native void nativePauseHintSession(long halPtr);
 
         private static native void nativeResumeHintSession(long halPtr);
@@ -253,6 +262,12 @@
             return nativeCreateHintSession(tgid, uid, tids, durationNanos);
         }
 
+        /** Wrapper for HintManager.nativeCreateHintSessionWithConfig */
+        public long halCreateHintSessionWithConfig(
+                int tgid, int uid, int[] tids, long durationNanos, int tag, SessionConfig config) {
+            return nativeCreateHintSessionWithConfig(tgid, uid, tids, durationNanos, tag, config);
+        }
+
         /** Wrapper for HintManager.nativePauseHintSession */
         public void halPauseHintSession(long halPtr) {
             nativePauseHintSession(halPtr);
@@ -612,8 +627,12 @@
     @VisibleForTesting
     final class BinderService extends IHintManager.Stub {
         @Override
-        public IHintSession createHintSession(IBinder token, int[] tids, long durationNanos) {
-            if (!isHalSupported()) return null;
+        public IHintSession createHintSessionWithConfig(@NonNull IBinder token,
+                @NonNull int[] tids, long durationNanos, @SessionTag int tag,
+                @Nullable SessionConfig config) {
+            if (!isHalSupported()) {
+                throw new UnsupportedOperationException("PowerHAL is not supported!");
+            }
 
             java.util.Objects.requireNonNull(token);
             java.util.Objects.requireNonNull(tids);
@@ -634,8 +653,35 @@
                     throw new SecurityException(errMsg);
                 }
 
-                long halSessionPtr = mNativeWrapper.halCreateHintSession(callingTgid, callingUid,
-                        tids, durationNanos);
+                Long halSessionPtr = null;
+                if (mConfigCreationSupport.get()) {
+                    try {
+                        halSessionPtr = mNativeWrapper.halCreateHintSessionWithConfig(
+                                callingTgid, callingUid, tids, durationNanos, tag, config);
+                    } catch (UnsupportedOperationException e) {
+                        mConfigCreationSupport.set(false);
+                    } catch (IllegalStateException e) {
+                        Slog.e("createHintSessionWithConfig failed: ", e.getMessage());
+                        throw new IllegalStateException(
+                            "createHintSessionWithConfig failed: " + e.getMessage());
+                    }
+                }
+
+                if (halSessionPtr == null) {
+                    try {
+                        halSessionPtr = mNativeWrapper.halCreateHintSession(callingTgid,
+                                callingUid, tids, durationNanos);
+                    } catch (UnsupportedOperationException e) {
+                        Slog.w("createHintSession unsupported: ", e.getMessage());
+                        throw new UnsupportedOperationException(
+                            "createHintSession unsupported: " + e.getMessage());
+                    } catch (IllegalStateException e) {
+                        Slog.e("createHintSession failed: ", e.getMessage());
+                        throw new IllegalStateException(
+                            "createHintSession failed: " + e.getMessage());
+                    }
+                }
+
                 if (powerhintThreadCleanup()) {
                     synchronized (mNonIsolatedTidsLock) {
                         for (int i = nonIsolated.size() - 1; i >= 0; i--) {
@@ -644,9 +690,6 @@
                         }
                     }
                 }
-                if (halSessionPtr == 0) {
-                    return null;
-                }
 
                 AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
                         halSessionPtr, durationNanos);
diff --git a/services/core/java/com/android/server/power/hint/flags.aconfig b/services/core/java/com/android/server/power/hint/flags.aconfig
index f4afcb1..0997744 100644
--- a/services/core/java/com/android/server/power/hint/flags.aconfig
+++ b/services/core/java/com/android/server/power/hint/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.power.hint"
+container: "system"
 
 flag {
     name: "powerhint_thread_cleanup"
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
index 894226c..e1b4b88 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
@@ -34,11 +34,14 @@
 
 import java.io.IOException;
 import java.io.StringWriter;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.TimeZone;
 
 /**
  * This class represents aggregated power stats for a variety of power components (CPU, WiFi,
@@ -66,7 +69,7 @@
                 aggregatedPowerStatsConfig.getPowerComponentsAggregatedStatsConfigs();
         mPowerComponentStats = new PowerComponentAggregatedPowerStats[configs.size()];
         for (int i = 0; i < configs.size(); i++) {
-            mPowerComponentStats[i] = new PowerComponentAggregatedPowerStats(configs.get(i));
+            mPowerComponentStats[i] = new PowerComponentAggregatedPowerStats(this, configs.get(i));
         }
     }
 
@@ -223,7 +226,7 @@
             if (i == 0) {
                 baseTime = clockUpdate.monotonicTime;
                 sb.append("Start time: ")
-                        .append(DateFormat.format("yyyy-MM-dd-HH-mm-ss", clockUpdate.currentTime))
+                        .append(formatDateTime(clockUpdate.currentTime))
                         .append(" (")
                         .append(baseTime)
                         .append(") duration: ")
@@ -235,8 +238,7 @@
                 TimeUtils.formatDuration(
                         clockUpdate.monotonicTime - baseTime, sb,
                         TimeUtils.HUNDRED_DAY_FIELD_LEN + 3);
-                sb.append(" ").append(
-                        DateFormat.format("yyyy-MM-dd-HH-mm-ss", clockUpdate.currentTime));
+                sb.append(" ").append(formatDateTime(clockUpdate.currentTime));
                 ipw.increaseIndent();
                 ipw.println(sb);
                 ipw.decreaseIndent();
@@ -267,6 +269,12 @@
         }
     }
 
+    private static String formatDateTime(long timeInMillis) {
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+        format.getCalendar().setTimeZone(TimeZone.getTimeZone("GMT"));
+        return format.format(new Date(timeInMillis));
+    }
+
     @Override
     public String toString() {
         StringWriter sw = new StringWriter();
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
index 6fbbc0f..5aad570 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
+++ b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
@@ -75,7 +75,7 @@
         private final int mPowerComponentId;
         private @TrackedState int[] mTrackedDeviceStates;
         private @TrackedState int[] mTrackedUidStates;
-        private AggregatedPowerStatsProcessor mProcessor = NO_OP_PROCESSOR;
+        private PowerStatsProcessor mProcessor = NO_OP_PROCESSOR;
 
         PowerComponent(int powerComponentId) {
             this.mPowerComponentId = powerComponentId;
@@ -85,6 +85,9 @@
          * Configures which states should be tracked as separate dimensions for the entire device.
          */
         public PowerComponent trackDeviceStates(@TrackedState int... states) {
+            if (mTrackedDeviceStates != null) {
+                throw new IllegalStateException("Component is already configured");
+            }
             mTrackedDeviceStates = states;
             return this;
         }
@@ -93,6 +96,9 @@
          * Configures which states should be tracked as separate dimensions on a per-UID basis.
          */
         public PowerComponent trackUidStates(@TrackedState int... states) {
+            if (mTrackedUidStates != null) {
+                throw new IllegalStateException("Component is already configured");
+            }
             mTrackedUidStates = states;
             return this;
         }
@@ -102,7 +108,7 @@
          * before giving the aggregates stats to consumers. The processor can complete the
          * aggregation process, for example by computing estimated power usage.
          */
-        public PowerComponent setProcessor(@NonNull AggregatedPowerStatsProcessor processor) {
+        public PowerComponent setProcessor(@NonNull PowerStatsProcessor processor) {
             mProcessor = processor;
             return this;
         }
@@ -137,7 +143,7 @@
         }
 
         @NonNull
-        public AggregatedPowerStatsProcessor getProcessor() {
+        public PowerStatsProcessor getProcessor() {
             return mProcessor;
         }
 
@@ -153,6 +159,7 @@
             }
             return false;
         }
+
     }
 
     private final List<PowerComponent> mPowerComponents = new ArrayList<>();
@@ -168,23 +175,55 @@
         return builder;
     }
 
+    /**
+     * Creates a configuration for the specified power component, which is a subcomponent
+     * of a different power component.  The tracked states will be the same as the parent
+     * component's.
+     */
+    public PowerComponent trackPowerComponent(int powerComponentId,
+            int parentPowerComponentId) {
+        PowerComponent parent = null;
+        for (int i = 0; i < mPowerComponents.size(); i++) {
+            PowerComponent powerComponent = mPowerComponents.get(i);
+            if (powerComponent.getPowerComponentId() == parentPowerComponentId) {
+                parent = powerComponent;
+                break;
+            }
+        }
+
+        if (parent == null) {
+            throw new IllegalArgumentException(
+                    "Parent component " + parentPowerComponentId + " is not configured");
+        }
+
+        PowerComponent powerComponent = trackPowerComponent(powerComponentId);
+        powerComponent.mTrackedDeviceStates = parent.mTrackedDeviceStates;
+        powerComponent.mTrackedUidStates = parent.mTrackedUidStates;
+        return powerComponent;
+    }
+
     public List<PowerComponent> getPowerComponentsAggregatedStatsConfigs() {
         return mPowerComponents;
     }
 
-    private static final AggregatedPowerStatsProcessor NO_OP_PROCESSOR =
-            new AggregatedPowerStatsProcessor() {
+    private static final PowerStatsProcessor NO_OP_PROCESSOR =
+            new PowerStatsProcessor() {
                 @Override
-                public void finish(PowerComponentAggregatedPowerStats stats) {
+                void finish(PowerComponentAggregatedPowerStats stats) {
                 }
 
                 @Override
-                public String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+                String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
                     return Arrays.toString(stats);
                 }
 
                 @Override
-                public String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+                String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats) {
+                    return descriptor.getStateLabel(key) + " " + Arrays.toString(stats);
+                }
+
+                @Override
+                String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
                     return Arrays.toString(stats);
                 }
             };
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java
deleted file mode 100644
index 7feb964..0000000
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java
+++ /dev/null
@@ -1,347 +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.power.stats;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.Log;
-
-import com.android.internal.os.PowerStats;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/*
- * The power estimation algorithm used by AggregatedPowerStatsProcessor can roughly be
- * described like this:
- *
- * 1. Estimate power usage for each state combination (e.g. power-battery/screen-on) using
- * a metric such as CPU time-in-state.
- *
- * 2. Combine estimates obtain in step 1, aggregating across states that are *not* tracked
- * per UID.
- *
- * 2. For each UID, compute the proportion of the combined estimates in each state
- * and attribute the corresponding portion of the total power estimate in that state to the UID.
- */
-abstract class AggregatedPowerStatsProcessor {
-    private static final String TAG = "AggregatedPowerStatsProcessor";
-
-    private static final int INDEX_DOES_NOT_EXIST = -1;
-    private static final double MILLIAMPHOUR_PER_MICROCOULOMB = 1.0 / 1000.0 / 60.0 / 60.0;
-
-    abstract void finish(PowerComponentAggregatedPowerStats stats);
-
-    abstract String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats);
-
-    abstract String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats);
-
-    protected static class PowerEstimationPlan {
-        private final AggregatedPowerStatsConfig.PowerComponent mConfig;
-        public List<DeviceStateEstimation> deviceStateEstimations = new ArrayList<>();
-        public List<CombinedDeviceStateEstimate> combinedDeviceStateEstimations = new ArrayList<>();
-        public List<UidStateEstimate> uidStateEstimates = new ArrayList<>();
-
-        public PowerEstimationPlan(AggregatedPowerStatsConfig.PowerComponent config) {
-            mConfig = config;
-            addDeviceStateEstimations();
-            combineDeviceStateEstimations();
-            addUidStateEstimations();
-        }
-
-        private void addDeviceStateEstimations() {
-            MultiStateStats.States[] config = mConfig.getDeviceStateConfig();
-            int[][] deviceStateCombinations = getAllTrackedStateCombinations(config);
-            for (int[] deviceStateCombination : deviceStateCombinations) {
-                deviceStateEstimations.add(
-                        new DeviceStateEstimation(config, deviceStateCombination));
-            }
-        }
-
-        private void combineDeviceStateEstimations() {
-            MultiStateStats.States[] deviceStateConfig = mConfig.getDeviceStateConfig();
-            MultiStateStats.States[] uidStateConfig = mConfig.getUidStateConfig();
-            MultiStateStats.States[] deviceStatesTrackedPerUid =
-                    new MultiStateStats.States[deviceStateConfig.length];
-
-            for (int i = 0; i < deviceStateConfig.length; i++) {
-                if (!deviceStateConfig[i].isTracked()) {
-                    continue;
-                }
-
-                int index = findTrackedStateByName(uidStateConfig, deviceStateConfig[i].getName());
-                if (index != INDEX_DOES_NOT_EXIST && uidStateConfig[index].isTracked()) {
-                    deviceStatesTrackedPerUid[i] = deviceStateConfig[i];
-                }
-            }
-
-            combineDeviceStateEstimationsRecursively(deviceStateConfig, deviceStatesTrackedPerUid,
-                    new int[deviceStateConfig.length], 0);
-        }
-
-        private void combineDeviceStateEstimationsRecursively(
-                MultiStateStats.States[] deviceStateConfig,
-                MultiStateStats.States[] deviceStatesTrackedPerUid, int[] stateValues, int state) {
-            if (state >= deviceStateConfig.length) {
-                DeviceStateEstimation dse = getDeviceStateEstimate(stateValues);
-                CombinedDeviceStateEstimate cdse = getCombinedDeviceStateEstimate(
-                        deviceStatesTrackedPerUid, stateValues);
-                if (cdse == null) {
-                    cdse = new CombinedDeviceStateEstimate(deviceStatesTrackedPerUid, stateValues);
-                    combinedDeviceStateEstimations.add(cdse);
-                }
-                cdse.deviceStateEstimations.add(dse);
-                return;
-            }
-
-            if (deviceStateConfig[state].isTracked()) {
-                for (int stateValue = 0;
-                        stateValue < deviceStateConfig[state].getLabels().length;
-                        stateValue++) {
-                    stateValues[state] = stateValue;
-                    combineDeviceStateEstimationsRecursively(deviceStateConfig,
-                            deviceStatesTrackedPerUid, stateValues, state + 1);
-                }
-            } else {
-                combineDeviceStateEstimationsRecursively(deviceStateConfig,
-                        deviceStatesTrackedPerUid, stateValues, state + 1);
-            }
-        }
-
-        private void addUidStateEstimations() {
-            MultiStateStats.States[] deviceStateConfig = mConfig.getDeviceStateConfig();
-            MultiStateStats.States[] uidStateConfig = mConfig.getUidStateConfig();
-            MultiStateStats.States[] uidStatesTrackedForDevice =
-                    new MultiStateStats.States[uidStateConfig.length];
-            MultiStateStats.States[] uidStatesNotTrackedForDevice =
-                    new MultiStateStats.States[uidStateConfig.length];
-
-            for (int i = 0; i < uidStateConfig.length; i++) {
-                if (!uidStateConfig[i].isTracked()) {
-                    continue;
-                }
-
-                int index = findTrackedStateByName(deviceStateConfig, uidStateConfig[i].getName());
-                if (index != INDEX_DOES_NOT_EXIST && deviceStateConfig[index].isTracked()) {
-                    uidStatesTrackedForDevice[i] = uidStateConfig[i];
-                } else {
-                    uidStatesNotTrackedForDevice[i] = uidStateConfig[i];
-                }
-            }
-
-            @AggregatedPowerStatsConfig.TrackedState
-            int[][] uidStateCombinations = getAllTrackedStateCombinations(uidStateConfig);
-            for (int[] stateValues : uidStateCombinations) {
-                CombinedDeviceStateEstimate combined =
-                        getCombinedDeviceStateEstimate(uidStatesTrackedForDevice, stateValues);
-                if (combined == null) {
-                    // This is not supposed to be possible
-                    Log.wtf(TAG, "Mismatch in UID and combined device states: "
-                                 + concatLabels(uidStatesTrackedForDevice, stateValues));
-                    continue;
-                }
-                UidStateEstimate uidStateEstimate = getUidStateEstimate(combined);
-                if (uidStateEstimate == null) {
-                    uidStateEstimate = new UidStateEstimate(combined, uidStatesNotTrackedForDevice);
-                    uidStateEstimates.add(uidStateEstimate);
-                }
-                uidStateEstimate.proportionalEstimates.add(
-                        new UidStateProportionalEstimate(stateValues));
-            }
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            sb.append("Step 1. Compute device-wide power estimates for state combinations:\n");
-            for (DeviceStateEstimation deviceStateEstimation : deviceStateEstimations) {
-                sb.append("    ").append(deviceStateEstimation.id).append("\n");
-            }
-            sb.append("Step 2. Combine device-wide estimates that are untracked per UID:\n");
-            boolean any = false;
-            for (CombinedDeviceStateEstimate cdse : combinedDeviceStateEstimations) {
-                if (cdse.deviceStateEstimations.size() <= 1) {
-                    continue;
-                }
-                any = true;
-                sb.append("    ").append(cdse.id).append(": ");
-                for (int i = 0; i < cdse.deviceStateEstimations.size(); i++) {
-                    if (i != 0) {
-                        sb.append(" + ");
-                    }
-                    sb.append(cdse.deviceStateEstimations.get(i).id);
-                }
-                sb.append("\n");
-            }
-            if (!any) {
-                sb.append("    N/A\n");
-            }
-            sb.append("Step 3. Proportionally distribute power estimates to UIDs:\n");
-            for (UidStateEstimate uidStateEstimate : uidStateEstimates) {
-                sb.append("    ").append(uidStateEstimate.combinedDeviceStateEstimate.id)
-                        .append("\n        among: ");
-                for (int i = 0; i < uidStateEstimate.proportionalEstimates.size(); i++) {
-                    UidStateProportionalEstimate uspe =
-                            uidStateEstimate.proportionalEstimates.get(i);
-                    if (i != 0) {
-                        sb.append(", ");
-                    }
-                    sb.append(concatLabels(uidStateEstimate.states, uspe.stateValues));
-                }
-                sb.append("\n");
-            }
-            return sb.toString();
-        }
-
-        @Nullable
-        public DeviceStateEstimation getDeviceStateEstimate(
-                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
-            String label = concatLabels(mConfig.getDeviceStateConfig(), stateValues);
-            for (int i = 0; i < deviceStateEstimations.size(); i++) {
-                DeviceStateEstimation deviceStateEstimation = this.deviceStateEstimations.get(i);
-                if (deviceStateEstimation.id.equals(label)) {
-                    return deviceStateEstimation;
-                }
-            }
-            return null;
-        }
-
-        public CombinedDeviceStateEstimate getCombinedDeviceStateEstimate(
-                MultiStateStats.States[] deviceStates,
-                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
-            String label = concatLabels(deviceStates, stateValues);
-            for (int i = 0; i < combinedDeviceStateEstimations.size(); i++) {
-                CombinedDeviceStateEstimate cdse = combinedDeviceStateEstimations.get(i);
-                if (cdse.id.equals(label)) {
-                    return cdse;
-                }
-            }
-            return null;
-        }
-
-        public UidStateEstimate getUidStateEstimate(CombinedDeviceStateEstimate combined) {
-            for (int i = 0; i < uidStateEstimates.size(); i++) {
-                UidStateEstimate uidStateEstimate = uidStateEstimates.get(i);
-                if (uidStateEstimate.combinedDeviceStateEstimate == combined) {
-                    return uidStateEstimate;
-                }
-            }
-            return null;
-        }
-
-        public void resetIntermediates() {
-            for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) {
-                deviceStateEstimations.get(i).intermediates = null;
-            }
-            for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) {
-                deviceStateEstimations.get(i).intermediates = null;
-            }
-            for (int i = uidStateEstimates.size() - 1; i >= 0; i--) {
-                UidStateEstimate uidStateEstimate = uidStateEstimates.get(i);
-                List<UidStateProportionalEstimate> proportionalEstimates =
-                        uidStateEstimate.proportionalEstimates;
-                for (int j = proportionalEstimates.size() - 1; j >= 0; j--) {
-                    proportionalEstimates.get(j).intermediates = null;
-                }
-            }
-        }
-    }
-
-    protected static class DeviceStateEstimation {
-        public final String id;
-        @AggregatedPowerStatsConfig.TrackedState
-        public final int[] stateValues;
-        public Object intermediates;
-
-        public DeviceStateEstimation(MultiStateStats.States[] config,
-                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
-            id = concatLabels(config, stateValues);
-            this.stateValues = stateValues;
-        }
-    }
-
-    protected static class CombinedDeviceStateEstimate {
-        public final String id;
-        public List<DeviceStateEstimation> deviceStateEstimations = new ArrayList<>();
-        public Object intermediates;
-
-        public CombinedDeviceStateEstimate(MultiStateStats.States[] config,
-                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
-            id = concatLabels(config, stateValues);
-        }
-    }
-
-    protected static class UidStateEstimate {
-        public final MultiStateStats.States[] states;
-        public CombinedDeviceStateEstimate combinedDeviceStateEstimate;
-        public List<UidStateProportionalEstimate> proportionalEstimates = new ArrayList<>();
-
-        public UidStateEstimate(CombinedDeviceStateEstimate combined,
-                MultiStateStats.States[] states) {
-            combinedDeviceStateEstimate = combined;
-            this.states = states;
-        }
-    }
-
-    protected static class UidStateProportionalEstimate {
-        @AggregatedPowerStatsConfig.TrackedState
-        public final int[] stateValues;
-        public Object intermediates;
-
-        protected UidStateProportionalEstimate(
-                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
-            this.stateValues = stateValues;
-        }
-    }
-
-    private static int findTrackedStateByName(MultiStateStats.States[] states, String name) {
-        for (int i = 0; i < states.length; i++) {
-            if (states[i].getName().equals(name)) {
-                return i;
-            }
-        }
-        return INDEX_DOES_NOT_EXIST;
-    }
-
-    @NonNull
-    private static String concatLabels(MultiStateStats.States[] config,
-            @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
-        List<String> labels = new ArrayList<>();
-        for (int state = 0; state < config.length; state++) {
-            if (config[state] != null && config[state].isTracked()) {
-                labels.add(config[state].getName()
-                           + "=" + config[state].getLabels()[stateValues[state]]);
-            }
-        }
-        Collections.sort(labels);
-        return labels.toString();
-    }
-
-    @AggregatedPowerStatsConfig.TrackedState
-    private static int[][] getAllTrackedStateCombinations(MultiStateStats.States[] states) {
-        List<int[]> combinations = new ArrayList<>();
-        MultiStateStats.States.forEachTrackedStateCombination(states, stateValues -> {
-            combinations.add(Arrays.copyOf(stateValues, stateValues.length));
-        });
-        return combinations.toArray(new int[combinations.size()][0]);
-    }
-
-    public static double uCtoMah(long chargeUC) {
-        return chargeUC * MILLIAMPHOUR_PER_MICROCOULOMB;
-    }
-}
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index a8eda3c..cb10da9 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -24,6 +24,7 @@
 import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.OutcomeReceiver;
@@ -603,24 +604,31 @@
         }
 
         if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
-            // We were asked to fetch Telephony data.
-            if (mTelephony != null) {
-                CompletableFuture<ModemActivityInfo> temp = new CompletableFuture<>();
-                mTelephony.requestModemActivityInfo(Runnable::run,
-                        new OutcomeReceiver<ModemActivityInfo,
-                                TelephonyManager.ModemActivityInfoException>() {
-                            @Override
-                            public void onResult(ModemActivityInfo result) {
-                                temp.complete(result);
-                            }
+            @SuppressWarnings("GuardedBy")
+            PowerStatsCollector collector = mStats.getPowerStatsCollector(
+                    BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
+            if (collector.isEnabled()) {
+                collector.schedule();
+            } else {
+                // We were asked to fetch Telephony data.
+                if (mTelephony != null) {
+                    CompletableFuture<ModemActivityInfo> temp = new CompletableFuture<>();
+                    mTelephony.requestModemActivityInfo(Runnable::run,
+                            new OutcomeReceiver<ModemActivityInfo,
+                                    TelephonyManager.ModemActivityInfoException>() {
+                                @Override
+                                public void onResult(ModemActivityInfo result) {
+                                    temp.complete(result);
+                                }
 
-                            @Override
-                            public void onError(TelephonyManager.ModemActivityInfoException e) {
-                                Slog.w(TAG, "error reading modem stats:" + e);
-                                temp.complete(null);
-                            }
-                        });
-                modemFuture = temp;
+                                @Override
+                                public void onError(TelephonyManager.ModemActivityInfoException e) {
+                                    Slog.w(TAG, "error reading modem stats:" + e);
+                                    temp.complete(null);
+                                }
+                            });
+                    modemFuture = temp;
+                }
             }
             if (!railUpdated) {
                 synchronized (mStats) {
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 3a84897..49c4000 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -19,9 +19,12 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
+import static android.os.BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS;
 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
 
+import static com.android.server.power.stats.MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -35,6 +38,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.hardware.usb.UsbManager;
 import android.location.GnssSignalQuality;
@@ -71,6 +75,7 @@
 import android.os.connectivity.GpsBatteryStats;
 import android.os.connectivity.WifiActivityEnergyInfo;
 import android.os.connectivity.WifiBatteryStats;
+import android.power.PowerStatsInternal;
 import android.provider.Settings;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation.NetworkType;
@@ -99,6 +104,7 @@
 import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.SparseDoubleArray;
 import android.util.SparseIntArray;
 import android.util.SparseLongArray;
@@ -137,6 +143,7 @@
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.LocalServices;
 import com.android.server.power.optimization.Flags;
 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
 
@@ -166,8 +173,12 @@
 import java.util.Map;
 import java.util.Queue;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
 
 /**
  * All information we are collecting about things that can happen that impact
@@ -281,7 +292,26 @@
     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
     private int[] mCpuPowerBracketMap;
     private final CpuPowerStatsCollector mCpuPowerStatsCollector;
-    private boolean mPowerStatsCollectorEnabled;
+    private final MobileRadioPowerStatsCollector mMobileRadioPowerStatsCollector;
+    private final WifiPowerStatsCollector mWifiPowerStatsCollector;
+    private final SparseBooleanArray mPowerStatsCollectorEnabled = new SparseBooleanArray();
+    private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
+            new WifiPowerStatsCollector.WifiStatsRetriever() {
+                @Override
+                public void retrieveWifiScanTimes(Callback callback) {
+                    synchronized (BatteryStatsImpl.this) {
+                        retrieveWifiScanTimesLocked(callback);
+                    }
+                }
+
+                @Override
+                public long getWifiActiveDuration() {
+                    synchronized (BatteryStatsImpl.this) {
+                        return getGlobalWifiRunningTime(mClock.elapsedRealtime() * 1000,
+                                STATS_SINCE_CHARGED) / 1000;
+                    }
+                }
+            };
 
     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
         return mKernelMemoryStats;
@@ -433,9 +463,11 @@
     public static class BatteryStatsConfig {
         static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0;
         static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1;
+        static final long DEFAULT_POWER_STATS_COLLECTION_THROTTLE_PERIOD =
+                TimeUnit.HOURS.toMillis(1);
 
         private final int mFlags;
-        private final long mPowerStatsThrottlePeriodCpu;
+        private SparseLongArray mPowerStatsThrottlePeriods;
 
         private BatteryStatsConfig(Builder builder) {
             int flags = 0;
@@ -446,7 +478,7 @@
                 flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
             }
             mFlags = flags;
-            mPowerStatsThrottlePeriodCpu = builder.mPowerStatsThrottlePeriodCpu;
+            mPowerStatsThrottlePeriods = builder.mPowerStatsThrottlePeriods;
         }
 
         /**
@@ -467,8 +499,9 @@
                     == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
         }
 
-        long getPowerStatsThrottlePeriodCpu() {
-            return mPowerStatsThrottlePeriodCpu;
+        long getPowerStatsThrottlePeriod(@BatteryConsumer.PowerComponent int powerComponent) {
+            return mPowerStatsThrottlePeriods.get(powerComponent,
+                    DEFAULT_POWER_STATS_COLLECTION_THROTTLE_PERIOD);
         }
 
         /**
@@ -477,12 +510,18 @@
         public static class Builder {
             private boolean mResetOnUnplugHighBatteryLevel;
             private boolean mResetOnUnplugAfterSignificantCharge;
-            private long mPowerStatsThrottlePeriodCpu;
+            private SparseLongArray mPowerStatsThrottlePeriods;
 
             public Builder() {
                 mResetOnUnplugHighBatteryLevel = true;
                 mResetOnUnplugAfterSignificantCharge = true;
-                mPowerStatsThrottlePeriodCpu = 60000;
+                mPowerStatsThrottlePeriods = new SparseLongArray();
+                setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_CPU,
+                        TimeUnit.MINUTES.toMillis(1));
+                setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+                        TimeUnit.HOURS.toMillis(1));
+                setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_WIFI,
+                        TimeUnit.HOURS.toMillis(1));
             }
 
             /**
@@ -512,10 +551,11 @@
 
             /**
              * Sets the minimum amount of time (in millis) to wait between passes
-             * of CPU power stats collection.
+             * of power stats collection for the specified power component.
              */
-            public Builder setPowerStatsThrottlePeriodCpu(long periodMs) {
-                mPowerStatsThrottlePeriodCpu = periodMs;
+            public Builder setPowerStatsThrottlePeriodMillis(
+                    @BatteryConsumer.PowerComponent int powerComponent, long periodMs) {
+                mPowerStatsThrottlePeriods.put(powerComponent, periodMs);
                 return this;
             }
         }
@@ -597,7 +637,7 @@
     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
     @VisibleForTesting
     public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
-        if (mPowerStatsCollectorEnabled) {
+        if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
             return;
         }
 
@@ -653,7 +693,7 @@
      */
     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
     public void updateCpuTimesForAllUids() {
-        if (mPowerStatsCollectorEnabled && mCpuPowerStatsCollector != null) {
+        if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
             mCpuPowerStatsCollector.schedule();
             return;
         }
@@ -713,7 +753,8 @@
 
     @GuardedBy("this")
     private void ensureKernelSingleUidTimeReaderLocked() {
-        if (mPowerStatsCollectorEnabled || mKernelSingleUidTimeReader != null) {
+        if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
+                || mKernelSingleUidTimeReader != null) {
             return;
         }
 
@@ -830,8 +871,6 @@
     private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
     private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator =
             new HistoryStepDetailsCalculatorImpl();
-    private final PowerStats.DescriptorRegistry mPowerStatsDescriptorRegistry =
-            new PowerStats.DescriptorRegistry();
 
     private boolean mHaveBatteryLevel = false;
     private boolean mBatteryPluggedIn;
@@ -1759,7 +1798,7 @@
         return mMaxLearnedBatteryCapacityUah;
     }
 
-    public class FrameworkStatsLogger {
+    public static class FrameworkStatsLogger {
         public void uidProcessStateChanged(int uid, int state) {
             // TODO(b/155216561): It is possible for isolated uids to be in a higher
             // state than its parent uid. We should track the highest state within the union of host
@@ -1768,25 +1807,24 @@
                     ActivityManager.processStateAmToProto(state));
         }
 
-        public void wakelockStateChanged(int uid, WorkChain wc, String name, int type,
-                int procState, boolean acquired) {
+        public void wakelockStateChanged(int uid, WorkChain wc, String name,
+                int procState, boolean acquired, int powerManagerWakeLockLevel) {
             int event = acquired
                     ? FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE
                     : FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE;
             if (wc != null) {
                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
-                        wc.getTags(), getPowerManagerWakeLockLevel(type), name,
-                        event, procState);
+                        wc.getTags(), powerManagerWakeLockLevel, name, event, procState);
             } else {
-                FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
-                        mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
-                        event, procState);
+                FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
+                        null, powerManagerWakeLockLevel, name, event, procState);
             }
         }
 
-        public void kernelWakeupReported(long deltaUptimeUs) {
-            FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
-                    /* duration_usec */ deltaUptimeUs, mLastWakeupElapsedTimeMs);
+        public void kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason,
+                long lastWakeupElapsedTimeMs) {
+            FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, lastWakeupReason,
+                    /* duration_usec */ deltaUptimeUs, lastWakeupElapsedTimeMs);
         }
 
         public void gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn) {
@@ -1838,44 +1876,18 @@
             FrameworkStatsLog.write(
                     FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
         }
+
+        /**
+         * Records a statsd event when the batterystats config file is written to disk.
+         */
+        public void writeCommitSysConfigFile(String fileName, long durationMs) {
+            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(fileName,
+                    durationMs);
+        }
     }
 
     private final FrameworkStatsLogger mFrameworkStatsLogger;
 
-    @VisibleForTesting
-    public BatteryStatsImpl(Clock clock, File historyDirectory, @NonNull Handler handler,
-            @NonNull PowerStatsUidResolver powerStatsUidResolver,
-            @NonNull FrameworkStatsLogger frameworkStatsLogger,
-            @NonNull BatteryStatsHistory.TraceDelegate traceDelegate,
-            @NonNull BatteryStatsHistory.EventLogger eventLogger) {
-        mClock = clock;
-        initKernelStatsReaders();
-        mBatteryStatsConfig = new BatteryStatsConfig.Builder().build();
-        mHandler = handler;
-        mPowerStatsUidResolver = powerStatsUidResolver;
-        mFrameworkStatsLogger = frameworkStatsLogger;
-        mConstants = new Constants(mHandler);
-        mStartClockTimeMs = clock.currentTimeMillis();
-        mDailyFile = null;
-        mMonotonicClock = new MonotonicClock(0, mClock);
-        if (historyDirectory == null) {
-            mCheckinFile = null;
-            mStatsFile = null;
-            mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_BUFFER,
-                    mStepDetailsCalculator, mClock, mMonotonicClock, traceDelegate, eventLogger);
-        } else {
-            mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin"));
-            mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
-            mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES,
-                    mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock, mMonotonicClock,
-                    traceDelegate, eventLogger);
-        }
-        mPlatformIdleStateCallback = null;
-        mEnergyConsumerRetriever = null;
-        mUserInfoProvider = null;
-        mCpuPowerStatsCollector = null;
-    }
-
     private void initKernelStatsReaders() {
         if (!isKernelStatsAvailable()) {
             return;
@@ -1893,6 +1905,109 @@
         mTmpRailStats = new RailStats();
     }
 
+    private class PowerStatsCollectorInjector implements CpuPowerStatsCollector.Injector,
+            MobileRadioPowerStatsCollector.Injector, WifiPowerStatsCollector.Injector {
+        private PackageManager mPackageManager;
+        private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+        private NetworkStatsManager mNetworkStatsManager;
+        private TelephonyManager mTelephonyManager;
+        private WifiManager mWifiManager;
+
+        void setContext(Context context) {
+            mPackageManager = context.getPackageManager();
+            mConsumedEnergyRetriever = new PowerStatsCollector.ConsumedEnergyRetrieverImpl(
+                    LocalServices.getService(PowerStatsInternal.class));
+            mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
+            mTelephonyManager = context.getSystemService(TelephonyManager.class);
+            mWifiManager = context.getSystemService(WifiManager.class);
+        }
+
+        @Override
+        public Handler getHandler() {
+            return mHandler;
+        }
+
+        @Override
+        public Clock getClock() {
+            return mClock;
+        }
+
+        @Override
+        public PowerStatsUidResolver getUidResolver() {
+            return mPowerStatsUidResolver;
+        }
+
+        @Override
+        public CpuScalingPolicies getCpuScalingPolicies() {
+            return mCpuScalingPolicies;
+        }
+
+        @Override
+        public PowerProfile getPowerProfile() {
+            return mPowerProfile;
+        }
+
+        @Override
+        public CpuPowerStatsCollector.KernelCpuStatsReader getKernelCpuStatsReader() {
+            return new CpuPowerStatsCollector.KernelCpuStatsReader();
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManager;
+        }
+
+        @Override
+        public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+            return mConsumedEnergyRetriever;
+        }
+
+        @Override
+        public IntSupplier getVoltageSupplier() {
+            return () -> mBatteryVoltageMv;
+        }
+
+        @Override
+        public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
+            return () -> readMobileNetworkStatsLocked(mNetworkStatsManager);
+        }
+
+        @Override
+        public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
+            return () -> readWifiNetworkStatsLocked(mNetworkStatsManager);
+        }
+
+        @Override
+        public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+            return mWifiStatsRetriever;
+        }
+
+        @Override
+        public TelephonyManager getTelephonyManager() {
+            return mTelephonyManager;
+        }
+
+        @Override
+        public WifiManager getWifiManager() {
+            return mWifiManager;
+        }
+
+        @Override
+        public LongSupplier getCallDurationSupplier() {
+            return () -> mPhoneOnTimer.getTotalTimeLocked(mClock.elapsedRealtime() * 1000,
+                    STATS_SINCE_CHARGED);
+        }
+
+        @Override
+        public LongSupplier getPhoneSignalScanDurationSupplier() {
+            return () -> mPhoneSignalScanningTimer.getTotalTimeLocked(
+                    mClock.elapsedRealtime() * 1000, STATS_SINCE_CHARGED);
+        }
+    }
+
+    private final PowerStatsCollectorInjector mPowerStatsCollectorInjector =
+            new PowerStatsCollectorInjector();
+
     /**
      * TimeBase observer.
      */
@@ -4808,7 +4923,6 @@
         if (type == WAKE_TYPE_PARTIAL) {
             // Only care about partial wake locks, since full wake locks
             // will be canceled when the user puts the screen to sleep.
-            aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
             if (historyName == null) {
                 historyName = name;
             }
@@ -4849,8 +4963,9 @@
             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
             uidStats.noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
 
-            mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name, type,
-                    uidStats.mProcessState, true /* acquired */);
+            mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
+                    uidStats.mProcessState, true /* acquired */,
+                    getPowerManagerWakeLockLevel(type));
         }
     }
 
@@ -4893,8 +5008,9 @@
             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
             uidStats.noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
 
-            mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name, type,
-                    uidStats.mProcessState, false /* acquired */);
+            mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
+                    uidStats.mProcessState, false/* acquired */,
+                    getPowerManagerWakeLockLevel(type));
 
             if (mappedUid != uid) {
                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
@@ -4910,8 +5026,8 @@
      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
      * PowerManager's Notifier.
      */
-    private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
-        switch (battertStatsWakelockType) {
+    private int getPowerManagerWakeLockLevel(int batteryStatsWakelockType) {
+        switch (batteryStatsWakelockType) {
             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
             case BatteryStats.WAKE_TYPE_PARTIAL:
                 return PowerManager.PARTIAL_WAKE_LOCK;
@@ -4929,7 +5045,7 @@
                 return -1;
 
             default:
-                Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
+                Slog.e(TAG, "Illegal wakelock type in batterystats: " + batteryStatsWakelockType);
                 return -1;
         }
     }
@@ -5126,19 +5242,14 @@
     }
 
     @GuardedBy("this")
-    void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
+    public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
         if (mLastWakeupReason != null) {
             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
-            mFrameworkStatsLogger.kernelWakeupReported(deltaUptimeMs * 1000);
-            mLastWakeupReason = null;
+            mFrameworkStatsLogger.kernelWakeupReported(deltaUptimeMs * 1000, mLastWakeupReason,
+                    mLastWakeupElapsedTimeMs);
         }
-    }
-
-    @GuardedBy("this")
-    public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
-        aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
         mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
         mLastWakeupReason = reason;
         mLastWakeupUptimeMs = uptimeMs;
@@ -5738,16 +5849,19 @@
                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
 
-                if (mLastModemActivityInfo != null) {
-                    if (elapsedRealtimeMs < mLastModemActivityInfo.getTimestampMillis()
+                if (mMobileRadioPowerStatsCollector.isEnabled()) {
+                    mMobileRadioPowerStatsCollector.schedule();
+                } else {
+                    // Check if modem Activity info has been collected recently, don't bother
+                    // triggering another update.
+                    if (mLastModemActivityInfo == null
+                            || elapsedRealtimeMs >= mLastModemActivityInfo.getTimestampMillis()
                             + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
-                        // Modem Activity info has been collected recently, don't bother
-                        // triggering another update.
-                        return false;
+                        mExternalSync.scheduleSync("modem-data",
+                                BatteryExternalStatsWorker.UPDATE_RADIO);
+                        return true;
                     }
                 }
-                // Tell the caller to collect radio network/power stats.
-                return true;
             }
         }
         return false;
@@ -5915,6 +6029,7 @@
             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
             if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
                 scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
+                mMobileRadioPowerStatsCollector.schedule();
             }
         }
     }
@@ -5927,6 +6042,7 @@
             mPhoneOn = false;
             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
             scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
+            mMobileRadioPowerStatsCollector.schedule();
         }
     }
 
@@ -6269,27 +6385,6 @@
         }
     }
 
-    @RadioAccessTechnology
-    private static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
-            @AccessNetworkConstants.RadioAccessNetworkType int dataType) {
-        switch (dataType) {
-            case AccessNetworkConstants.AccessNetworkType.NGRAN:
-                return RADIO_ACCESS_TECHNOLOGY_NR;
-            case AccessNetworkConstants.AccessNetworkType.EUTRAN:
-                return RADIO_ACCESS_TECHNOLOGY_LTE;
-            case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
-            case AccessNetworkConstants.AccessNetworkType.IWLAN:
-                return RADIO_ACCESS_TECHNOLOGY_OTHER;
-            default:
-                Slog.w(TAG,
-                        "Unhandled RadioAccessNetworkType (" + dataType + "), mapping to OTHER");
-                return RADIO_ACCESS_TECHNOLOGY_OTHER;
-        }
-    }
-
     @GuardedBy("this")
     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
         if (!mWifiOn) {
@@ -6297,7 +6392,11 @@
                     HistoryItem.STATE2_WIFI_ON_FLAG);
             mWifiOn = true;
             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
-            scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
+            if (mWifiPowerStatsCollector.isEnabled()) {
+                mWifiPowerStatsCollector.schedule();
+            } else {
+                scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
+            }
         }
     }
 
@@ -6308,7 +6407,11 @@
                     HistoryItem.STATE2_WIFI_ON_FLAG);
             mWifiOn = false;
             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
-            scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
+            if (mWifiPowerStatsCollector.isEnabled()) {
+                mWifiPowerStatsCollector.schedule();
+            } else {
+                scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
+            }
         }
     }
 
@@ -6700,8 +6803,11 @@
                             .noteWifiRunningLocked(elapsedRealtimeMs);
                 }
             }
-
-            scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
+            if (mWifiPowerStatsCollector.isEnabled()) {
+                mWifiPowerStatsCollector.schedule();
+            } else {
+                scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
+            }
         } else {
             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
         }
@@ -6770,7 +6876,11 @@
                 }
             }
 
-            scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
+            if (mWifiPowerStatsCollector.isEnabled()) {
+                mWifiPowerStatsCollector.schedule();
+            } else {
+                scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
+            }
         } else {
             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
         }
@@ -6785,7 +6895,11 @@
             }
             mWifiState = wifiState;
             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
-            scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
+            if (mWifiPowerStatsCollector.isEnabled()) {
+                mWifiPowerStatsCollector.schedule();
+            } else {
+                scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
+            }
         }
     }
 
@@ -6908,6 +7022,25 @@
                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
     }
 
+    private void retrieveWifiScanTimesLocked(
+            WifiPowerStatsCollector.WifiStatsRetriever.Callback callback) {
+        long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
+        for (int i = mUidStats.size() - 1; i >= 0; i--) {
+            int uid = mUidStats.keyAt(i);
+            Uid uidStats = mUidStats.valueAt(i);
+            long scanTimeUs = uidStats.getWifiScanTime(elapsedTimeUs, STATS_SINCE_CHARGED);
+            long batchScanTimeUs = 0;
+            for (int bucket = 0; bucket < NUM_WIFI_BATCHED_SCAN_BINS; bucket++) {
+                batchScanTimeUs += uidStats.getWifiBatchedScanTime(bucket, elapsedTimeUs,
+                        STATS_SINCE_CHARGED);
+            }
+            if (scanTimeUs != 0 || batchScanTimeUs != 0) {
+                callback.onWifiScanTime(uid, (scanTimeUs + 500) / 1000,
+                        (batchScanTimeUs + 500) / 1000);
+            }
+        }
+    }
+
     private int mWifiMulticastNesting = 0;
 
     @GuardedBy("this")
@@ -8311,7 +8444,7 @@
 
         @GuardedBy("mBsi")
         private void ensureMultiStateCounters(long timestampMs) {
-            if (mBsi.mPowerStatsCollectorEnabled) {
+            if (mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
                 throw new IllegalStateException("Multi-state counters used in streamlined mode");
             }
 
@@ -10612,7 +10745,8 @@
                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
                 }
 
-                if (!mBsi.mPowerStatsCollectorEnabled && mBsi.trackPerProcStateCpuTimes()) {
+                if (!mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
+                        && mBsi.trackPerProcStateCpuTimes()) {
                     mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs);
 
                     LongArrayMultiStateCounter onBatteryCounter =
@@ -10634,7 +10768,8 @@
 
                 final int batteryConsumerProcessState =
                         mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
-                if (mBsi.mSystemReady && mBsi.mPowerStatsCollectorEnabled) {
+                if (mBsi.mSystemReady && mBsi.mPowerStatsCollectorEnabled.get(
+                        BatteryConsumer.POWER_COMPONENT_CPU)) {
                     mBsi.mHistory.recordProcessStateChange(elapsedRealtimeMs, uptimeMs, mUid,
                             batteryConsumerProcessState);
                 }
@@ -10982,11 +11117,27 @@
 
     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
-            @NonNull Handler handler, @Nullable PlatformIdleStateCallback cb,
-            @Nullable EnergyStatsRetriever energyStatsCb,
+            @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
+            @Nullable EnergyStatsRetriever energyStatsRetriever,
             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
             @NonNull CpuScalingPolicies cpuScalingPolicies,
             @NonNull PowerStatsUidResolver powerStatsUidResolver) {
+        this(config, clock, monotonicClock, systemDir, handler, platformIdleStateCallback,
+                energyStatsRetriever, userInfoProvider, powerProfile, cpuScalingPolicies,
+                powerStatsUidResolver, new FrameworkStatsLogger(),
+                new BatteryStatsHistory.TraceDelegate(), new BatteryStatsHistory.EventLogger());
+    }
+
+    public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
+            @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
+            @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
+            @Nullable EnergyStatsRetriever energyStatsRetriever,
+            @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
+            @NonNull CpuScalingPolicies cpuScalingPolicies,
+            @NonNull PowerStatsUidResolver powerStatsUidResolver,
+            @NonNull FrameworkStatsLogger frameworkStatsLogger,
+            @NonNull BatteryStatsHistory.TraceDelegate traceDelegate,
+            @NonNull BatteryStatsHistory.EventLogger eventLogger) {
         mClock = clock;
         initKernelStatsReaders();
 
@@ -10998,29 +11149,39 @@
         mPowerProfile = powerProfile;
         mCpuScalingPolicies = cpuScalingPolicies;
         mPowerStatsUidResolver = powerStatsUidResolver;
-        mFrameworkStatsLogger = new FrameworkStatsLogger();
+        mFrameworkStatsLogger = frameworkStatsLogger;
 
         initPowerProfile();
 
-        if (systemDir == null) {
-            mStatsFile = null;
-            mCheckinFile = null;
-            mDailyFile = null;
-            mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_BUFFER,
-                    mStepDetailsCalculator, mClock, mMonotonicClock);
-        } else {
+        if (systemDir != null) {
             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
             mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
             mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
-            mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES,
-                    mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock, mMonotonicClock);
+        } else {
+            mStatsFile = null;
+            mCheckinFile = null;
+            mDailyFile = null;
         }
 
-        mCpuPowerStatsCollector = new CpuPowerStatsCollector(mCpuScalingPolicies, mPowerProfile,
-                mPowerStatsUidResolver, () -> mBatteryVoltageMv, mHandler,
-                mBatteryStatsConfig.getPowerStatsThrottlePeriodCpu());
+        mHistory = new BatteryStatsHistory(null /* historyBuffer */, systemDir,
+                mConstants.MAX_HISTORY_FILES, mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator,
+                mClock, mMonotonicClock, traceDelegate, eventLogger);
+
+        mCpuPowerStatsCollector = new CpuPowerStatsCollector(mPowerStatsCollectorInjector,
+                mBatteryStatsConfig.getPowerStatsThrottlePeriod(
+                        BatteryConsumer.POWER_COMPONENT_CPU));
         mCpuPowerStatsCollector.addConsumer(this::recordPowerStats);
 
+        mMobileRadioPowerStatsCollector = new MobileRadioPowerStatsCollector(
+                mPowerStatsCollectorInjector, mBatteryStatsConfig.getPowerStatsThrottlePeriod(
+                BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
+        mMobileRadioPowerStatsCollector.addConsumer(this::recordPowerStats);
+
+        mWifiPowerStatsCollector = new WifiPowerStatsCollector(
+                mPowerStatsCollectorInjector, mBatteryStatsConfig.getPowerStatsThrottlePeriod(
+                BatteryConsumer.POWER_COMPONENT_WIFI));
+        mWifiPowerStatsCollector.addConsumer(this::recordPowerStats);
+
         mStartCount++;
         initTimersAndCounters();
         mOnBattery = mOnBatteryInternal = false;
@@ -11030,8 +11191,8 @@
         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
         initDischarge(realtimeUs);
         updateDailyDeadlineLocked();
-        mPlatformIdleStateCallback = cb;
-        mEnergyConsumerRetriever = energyStatsCb;
+        mPlatformIdleStateCallback = platformIdleStateCallback;
+        mEnergyConsumerRetriever = energyStatsRetriever;
         mUserInfoProvider = userInfoProvider;
 
         mPowerStatsUidResolver.addListener(new PowerStatsUidResolver.Listener() {
@@ -11296,8 +11457,7 @@
                                 memStream.writeTo(stream);
                                 stream.flush();
                                 mDailyFile.finishWrite(stream);
-                                com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
-                                        "batterystats-daily",
+                                mFrameworkStatsLogger.writeCommitSysConfigFile("batterystats-daily",
                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
                             } catch (IOException e) {
                                 Slog.w("BatteryStats",
@@ -11809,7 +11969,7 @@
         // Store the empty state to disk to ensure consistency
         writeSyncLocked();
 
-        if (mPowerStatsCollectorEnabled) {
+        if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
             schedulePowerStatsSampleCollection();
         }
 
@@ -11953,7 +12113,7 @@
         return networkStatsManager.getWifiUidStats();
     }
 
-    private static class NetworkStatsDelta {
+    static class NetworkStatsDelta {
         int mUid;
         int mSet;
         long mRxBytes;
@@ -11985,9 +12145,16 @@
         public long getTxPackets() {
             return mTxPackets;
         }
+
+        @Override
+        public String toString() {
+            return "NetworkStatsDelta{mUid=" + mUid + ", mSet=" + mSet + ", mRxBytes=" + mRxBytes
+                    + ", mRxPackets=" + mRxPackets + ", mTxBytes=" + mTxBytes + ", mTxPackets="
+                    + mTxPackets + '}';
+        }
     }
 
-    private List<NetworkStatsDelta> computeDelta(NetworkStats currentStats,
+    static List<NetworkStatsDelta> computeDelta(NetworkStats currentStats,
             NetworkStats lastStats) {
         List<NetworkStatsDelta> deltaList = new ArrayList<>();
         for (NetworkStats.Entry entry : currentStats) {
@@ -12009,10 +12176,10 @@
                 }
             }
             if (lastEntry != null) {
-                delta.mRxBytes = entry.getRxBytes() - lastEntry.getRxBytes();
-                delta.mRxPackets = entry.getRxPackets() - lastEntry.getRxPackets();
-                delta.mTxBytes = entry.getTxBytes() - lastEntry.getTxBytes();
-                delta.mTxPackets = entry.getTxPackets() - lastEntry.getTxPackets();
+                delta.mRxBytes = Math.max(0, entry.getRxBytes() - lastEntry.getRxBytes());
+                delta.mRxPackets = Math.max(0, entry.getRxPackets() - lastEntry.getRxPackets());
+                delta.mTxBytes = Math.max(0, entry.getTxBytes() - lastEntry.getTxBytes());
+                delta.mTxPackets = Math.max(0, entry.getTxPackets() - lastEntry.getTxPackets());
             } else {
                 delta.mRxBytes = entry.getRxBytes();
                 delta.mRxPackets = entry.getRxPackets();
@@ -12033,6 +12200,10 @@
     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
             @NonNull NetworkStatsManager networkStatsManager) {
+        if (mWifiPowerStatsCollector.isEnabled()) {
+            return;
+        }
+
         if (DEBUG_ENERGY) {
             synchronized (mWifiNetworkLock) {
                 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
@@ -12418,13 +12589,11 @@
         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
 
         // Grab a separate lock to acquire the network stats, which may do I/O.
-        NetworkStats delta = null;
+        List<NetworkStatsDelta> delta = null;
         synchronized (mModemNetworkLock) {
             final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
             if (latestStats != null) {
-                delta = latestStats.subtract(mLastModemNetworkStats != null
-                        ? mLastModemNetworkStats
-                        : new NetworkStats(0, -1));
+                delta = computeDelta(latestStats, mLastModemNetworkStats);
                 mLastModemNetworkStats = latestStats;
             }
         }
@@ -12527,7 +12696,7 @@
             long totalRxPackets = 0;
             long totalTxPackets = 0;
             if (delta != null) {
-                for (NetworkStats.Entry entry : delta) {
+                for (NetworkStatsDelta entry : delta) {
                     if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
                         continue;
                     }
@@ -12568,7 +12737,7 @@
                 // Now distribute proportional blame to the apps that did networking.
                 long totalPackets = totalRxPackets + totalTxPackets;
                 if (totalPackets > 0) {
-                    for (NetworkStats.Entry entry : delta) {
+                    for (NetworkStatsDelta entry : delta) {
                         if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
                             continue;
                         }
@@ -14408,17 +14577,47 @@
     /**
      * Notifies BatteryStatsImpl that the system server is ready.
      */
-    public void onSystemReady() {
+    public void onSystemReady(Context context) {
         if (mCpuUidFreqTimeReader != null) {
             mCpuUidFreqTimeReader.onSystemReady();
         }
-        if (mCpuPowerStatsCollector != null) {
-            mCpuPowerStatsCollector.setEnabled(mPowerStatsCollectorEnabled);
-        }
+
+        mPowerStatsCollectorInjector.setContext(context);
+
+        mCpuPowerStatsCollector.setEnabled(
+                mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU));
+        mCpuPowerStatsCollector.schedule();
+
+        mMobileRadioPowerStatsCollector.setEnabled(
+                mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
+        mMobileRadioPowerStatsCollector.schedule();
+
+        mWifiPowerStatsCollector.setEnabled(
+                mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI));
+        mWifiPowerStatsCollector.schedule();
+
         mSystemReady = true;
     }
 
     /**
+     * Returns a PowerStatsCollector for the specified power component or null if unavailable.
+     */
+    @Nullable
+    PowerStatsCollector getPowerStatsCollector(
+            @BatteryConsumer.PowerComponent int powerComponent) {
+        switch (powerComponent) {
+            case BatteryConsumer.POWER_COMPONENT_CPU:
+                return mCpuPowerStatsCollector;
+            case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO:
+                return mMobileRadioPowerStatsCollector;
+            case BatteryConsumer.POWER_COMPONENT_WIFI:
+                return mWifiPowerStatsCollector;
+        }
+        return null;
+    }
+
+
+    /**
      * Force recording of all history events regardless of the "charging" state.
      */
     @VisibleForTesting
@@ -14561,9 +14760,10 @@
                                     stream.write(parcel.marshall());
                                     stream.flush();
                                     mCheckinFile.finishWrite(stream);
-                                    com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
-                                            "batterystats-checkin", initialTimeMs
-                                            + SystemClock.uptimeMillis() - startTimeMs2);
+                                    mFrameworkStatsLogger.writeCommitSysConfigFile(
+                                            "batterystats-checkin",
+                                            initialTimeMs + SystemClock.uptimeMillis()
+                                                    - startTimeMs2);
                                 } catch (IOException e) {
                                     Slog.w("BatteryStats",
                                             "Error writing checkin battery statistics", e);
@@ -15437,9 +15637,10 @@
     /**
      * Enables or disables the PowerStatsCollector mode.
      */
-    public void setPowerStatsCollectorEnabled(boolean enabled) {
+    public void setPowerStatsCollectorEnabled(@BatteryConsumer.PowerComponent int powerComponent,
+            boolean enabled) {
         synchronized (this) {
-            mPowerStatsCollectorEnabled = enabled;
+            mPowerStatsCollectorEnabled.put(powerComponent, enabled);
         }
     }
 
@@ -15944,10 +16145,9 @@
      * Callers will need to wait for the collection to complete on the handler thread.
      */
     public void schedulePowerStatsSampleCollection() {
-        if (mCpuPowerStatsCollector == null) {
-            return;
-        }
         mCpuPowerStatsCollector.forceSchedule();
+        mMobileRadioPowerStatsCollector.forceSchedule();
+        mWifiPowerStatsCollector.forceSchedule();
     }
 
     /**
@@ -15965,6 +16165,8 @@
      */
     public void dumpStatsSample(PrintWriter pw) {
         mCpuPowerStatsCollector.collectAndDump(pw);
+        mMobileRadioPowerStatsCollector.collectAndDump(pw);
+        mWifiPowerStatsCollector.collectAndDump(pw);
     }
 
     private final Runnable mWriteAsyncRunnable = () -> {
@@ -16036,7 +16238,7 @@
                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
                         + " bytes:" + p.dataSize());
             }
-            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+            mFrameworkStatsLogger.writeCommitSysConfigFile(
                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
         } catch (IOException e) {
             Slog.w(TAG, "Error writing battery statistics", e);
@@ -17262,10 +17464,8 @@
             pw.println();
             dumpConstantsLocked(pw);
 
-            if (mCpuPowerStatsCollector != null) {
-                pw.println();
-                mCpuPowerStatsCollector.dumpCpuPowerBracketsLocked(pw);
-            }
+            pw.println();
+            mCpuPowerStatsCollector.dumpCpuPowerBracketsLocked(pw);
 
             pw.println();
             dumpEnergyConsumerStatsLocked(pw);
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 30b80ae..0d5eabc 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -27,6 +27,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.CpuScalingPolicies;
@@ -43,7 +44,7 @@
 public class BatteryUsageStatsProvider {
     private static final String TAG = "BatteryUsageStatsProv";
     private final Context mContext;
-    private boolean mPowerStatsExporterEnabled;
+    private final SparseBooleanArray mPowerStatsExporterEnabled = new SparseBooleanArray();
     private final PowerStatsExporter mPowerStatsExporter;
     private final PowerStatsStore mPowerStatsStore;
     private final PowerProfile mPowerProfile;
@@ -71,16 +72,24 @@
 
                 // Power calculators are applied in the order of registration
                 mPowerCalculators.add(new BatteryChargeCalculator());
-                if (!mPowerStatsExporterEnabled) {
+                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
                     mPowerCalculators.add(
                             new CpuPowerCalculator(mCpuScalingPolicies, mPowerProfile));
                 }
                 mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
                 if (!BatteryStats.checkWifiOnly(mContext)) {
-                    mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
+                    if (!mPowerStatsExporterEnabled.get(
+                            BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) {
+                        mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
+                    }
+                    if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_PHONE)) {
+                        mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
+                    }
                 }
-                mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
+                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI)) {
+                    mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
+                }
                 mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new SensorPowerCalculator(
                         mContext.getSystemService(SensorManager.class)));
@@ -89,7 +98,6 @@
                 mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new AudioPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new VideoPowerCalculator(mPowerProfile));
-                mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));
@@ -228,7 +236,7 @@
             }
         }
 
-        if (mPowerStatsExporterEnabled) {
+        if (mPowerStatsExporterEnabled.indexOfValue(true) >= 0) {
             mPowerStatsExporter.exportAggregatedPowerStats(batteryUsageStatsBuilder,
                     monotonicStartTime, monotonicEndTime);
         }
@@ -393,7 +401,10 @@
         return builder.build();
     }
 
-    public void setPowerStatsExporterEnabled(boolean enabled) {
-        mPowerStatsExporterEnabled = enabled;
+    /**
+     * Specify whether PowerStats based attribution is supported for the specified component.
+     */
+    public void setPowerStatsExporterEnabled(int powerComponentId, boolean enabled) {
+        mPowerStatsExporterEnabled.put(powerComponentId, enabled);
     }
 }
diff --git a/services/core/java/com/android/server/power/stats/CpuAggregatedPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/CpuAggregatedPowerStatsProcessor.java
deleted file mode 100644
index ed9414f..0000000
--- a/services/core/java/com/android/server/power/stats/CpuAggregatedPowerStatsProcessor.java
+++ /dev/null
@@ -1,545 +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.power.stats;
-
-import android.os.BatteryStats;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.os.CpuScalingPolicies;
-import com.android.internal.os.PowerProfile;
-import com.android.internal.os.PowerStats;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-public class CpuAggregatedPowerStatsProcessor extends AggregatedPowerStatsProcessor {
-    private static final String TAG = "CpuAggregatedPowerStatsProcessor";
-
-    private static final double HOUR_IN_MILLIS = TimeUnit.HOURS.toMillis(1);
-    private static final int UNKNOWN = -1;
-
-    private final CpuScalingPolicies mCpuScalingPolicies;
-    // Number of CPU core clusters
-    private final int mCpuClusterCount;
-    // Total number of CPU scaling steps across all clusters
-    private final int mCpuScalingStepCount;
-    // Map of scaling step to the corresponding core cluster mScalingStepToCluster[step]->cluster
-    private final int[] mScalingStepToCluster;
-    // Average power consumed by the CPU when it is powered up (per power_profile.xml)
-    private final double mPowerMultiplierForCpuActive;
-    // Average power consumed by each cluster when it is powered up (per power_profile.xml)
-    private final double[] mPowerMultipliersByCluster;
-    // Average power consumed by each scaling step when running code (per power_profile.xml)
-    private final double[] mPowerMultipliersByScalingStep;
-    // A map used to combine energy consumers into a smaller set, in case power brackets
-    // are defined in a way that does not allow an unambiguous mapping of energy consumers to
-    // brackets
-    private int[] mEnergyConsumerToCombinedEnergyConsumerMap;
-    // A map of combined energy consumers to the corresponding collections of power brackets.
-    // For example, if there are two CPU_CLUSTER rails and each maps to three brackets,
-    // this map will look like this:
-    //     0 : [0, 1, 2]
-    //     1 : [3, 4, 5]
-    private int[][] mCombinedEnergyConsumerToPowerBracketMap;
-
-    // Cached reference to a PowerStats descriptor. Almost never changes in practice,
-    // helping to avoid reparsing the descriptor for every PowerStats span.
-    private PowerStats.Descriptor mLastUsedDescriptor;
-    // Cached results of parsing of current PowerStats.Descriptor. Only refreshed when
-    // mLastUsedDescriptor changes
-    private CpuPowerStatsCollector.CpuStatsArrayLayout mStatsLayout;
-    // Sequence of steps for power estimation and intermediate results.
-    private PowerEstimationPlan mPlan;
-
-    // Temp array for retrieval of device power stats, to avoid repeated allocations
-    private long[] mTmpDeviceStatsArray;
-    // Temp array for retrieval of UID power stats, to avoid repeated allocations
-    private long[] mTmpUidStatsArray;
-
-    public CpuAggregatedPowerStatsProcessor(PowerProfile powerProfile,
-            CpuScalingPolicies scalingPolicies) {
-        mCpuScalingPolicies = scalingPolicies;
-        mCpuScalingStepCount = scalingPolicies.getScalingStepCount();
-        mScalingStepToCluster = new int[mCpuScalingStepCount];
-        mPowerMultipliersByScalingStep = new double[mCpuScalingStepCount];
-
-        int step = 0;
-        int[] policies = scalingPolicies.getPolicies();
-        mCpuClusterCount = policies.length;
-        mPowerMultipliersByCluster = new double[mCpuClusterCount];
-        for (int cluster = 0; cluster < mCpuClusterCount; cluster++) {
-            int policy = policies[cluster];
-            mPowerMultipliersByCluster[cluster] =
-                    powerProfile.getAveragePowerForCpuScalingPolicy(policy) / HOUR_IN_MILLIS;
-            int[] frequencies = scalingPolicies.getFrequencies(policy);
-            for (int i = 0; i < frequencies.length; i++) {
-                mScalingStepToCluster[step] = cluster;
-                mPowerMultipliersByScalingStep[step] =
-                        powerProfile.getAveragePowerForCpuScalingStep(policy, i) / HOUR_IN_MILLIS;
-                step++;
-            }
-        }
-        mPowerMultiplierForCpuActive =
-                powerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE) / HOUR_IN_MILLIS;
-    }
-
-    private void unpackPowerStatsDescriptor(PowerStats.Descriptor descriptor) {
-        if (descriptor.equals(mLastUsedDescriptor)) {
-            return;
-        }
-
-        mLastUsedDescriptor = descriptor;
-        mStatsLayout = new CpuPowerStatsCollector.CpuStatsArrayLayout();
-        mStatsLayout.fromExtras(descriptor.extras);
-
-        mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
-        mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
-    }
-
-    /**
-     * Temporary struct to capture intermediate results of power estimation.
-     */
-    private static final class Intermediates {
-        public long uptime;
-        // Sum of all time-in-step values, combining all time-in-step durations across all cores.
-        public long cumulativeTime;
-        // CPU activity durations per cluster
-        public long[] timeByCluster;
-        // Sums of time-in-step values, aggregated by cluster, combining all cores in the cluster.
-        public long[] cumulativeTimeByCluster;
-        public long[] timeByScalingStep;
-        public double[] powerByCluster;
-        public double[] powerByScalingStep;
-        public long[] powerByEnergyConsumer;
-    }
-
-    /**
-     * Temporary struct to capture intermediate results of power estimation.
-     */
-    private static class DeviceStatsIntermediates {
-        public double power;
-        public long[] timeByBracket;
-        public double[] powerByBracket;
-    }
-
-    @Override
-    public void finish(PowerComponentAggregatedPowerStats stats) {
-        if (stats.getPowerStatsDescriptor() == null) {
-            return;
-        }
-
-        unpackPowerStatsDescriptor(stats.getPowerStatsDescriptor());
-
-        if (mPlan == null) {
-            mPlan = new PowerEstimationPlan(stats.getConfig());
-            if (mStatsLayout.getEnergyConsumerCount() != 0) {
-                initEnergyConsumerToPowerBracketMaps();
-            }
-        }
-
-        Intermediates intermediates = new Intermediates();
-
-        int cpuScalingStepCount = mStatsLayout.getCpuScalingStepCount();
-        if (cpuScalingStepCount != mCpuScalingStepCount) {
-            Log.e(TAG, "Mismatched CPU scaling step count in PowerStats: " + cpuScalingStepCount
-                       + ", expected: " + mCpuScalingStepCount);
-            return;
-        }
-
-        int clusterCount = mStatsLayout.getCpuClusterCount();
-        if (clusterCount != mCpuClusterCount) {
-            Log.e(TAG, "Mismatched CPU cluster count in PowerStats: " + clusterCount
-                       + ", expected: " + mCpuClusterCount);
-            return;
-        }
-
-        computeTotals(stats, intermediates);
-        if (intermediates.cumulativeTime == 0) {
-            return;
-        }
-
-        estimatePowerByScalingStep(intermediates);
-        estimatePowerByDeviceState(stats, intermediates);
-        combineDeviceStateEstimates();
-
-        ArrayList<Integer> uids = new ArrayList<>();
-        stats.collectUids(uids);
-        if (!uids.isEmpty()) {
-            for (int uid : uids) {
-                for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
-                    estimateUidPowerConsumption(stats, uid, mPlan.uidStateEstimates.get(i));
-                }
-            }
-        }
-        mPlan.resetIntermediates();
-    }
-
-    /*
-     * Populate data structures (two maps) needed to use power rail data, aka energy consumers,
-     * to attribute power usage to apps.
-     *
-     * At this point, the algorithm covers only the most basic cases:
-     * - Each cluster is mapped to unique power brackets (possibly multiple for each cluster):
-     *          CL_0: [bracket0, bracket1]
-     *          CL_1: [bracket3]
-     *      In this case, the consumed energy is distributed  to the corresponding brackets
-     *      proportionally.
-     * - Brackets span multiple clusters:
-     *          CL_0: [bracket0, bracket1]
-     *          CL_1: [bracket1, bracket2]
-     *          CL_2: [bracket3, bracket4]
-     *      In this case, we combine energy consumers into groups unambiguously mapped to
-     *      brackets. In the above example, consumed energy for CL_0 and CL_1 will be combined
-     *      because they both map to the same power bracket (bracket1):
-     *          (CL_0+CL_1): [bracket0, bracket1, bracket2]
-     *          CL_2: [bracket3, bracket4]
-     */
-    private void initEnergyConsumerToPowerBracketMaps() {
-        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
-        int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
-
-        mEnergyConsumerToCombinedEnergyConsumerMap = new int[energyConsumerCount];
-        mCombinedEnergyConsumerToPowerBracketMap = new int[energyConsumerCount][];
-
-        int[] policies = mCpuScalingPolicies.getPolicies();
-        if (energyConsumerCount == policies.length) {
-            int[] scalingStepToPowerBracketMap = mStatsLayout.getScalingStepToPowerBracketMap();
-            ArraySet<Integer>[] clusterToBrackets = new ArraySet[policies.length];
-            int step = 0;
-            for (int cluster = 0; cluster < policies.length; cluster++) {
-                int[] freqs = mCpuScalingPolicies.getFrequencies(policies[cluster]);
-                clusterToBrackets[cluster] = new ArraySet<>(freqs.length);
-                for (int j = 0; j < freqs.length; j++) {
-                    clusterToBrackets[cluster].add(scalingStepToPowerBracketMap[step++]);
-                }
-            }
-
-            ArraySet<Integer>[] combinedEnergyConsumers = new ArraySet[policies.length];
-            int combinedEnergyConsumersCount = 0;
-
-            for (int cluster = 0; cluster < clusterToBrackets.length; cluster++) {
-                int combineWith = UNKNOWN;
-                for (int i = 0; i < combinedEnergyConsumersCount; i++) {
-                    if (containsAny(combinedEnergyConsumers[i], clusterToBrackets[cluster])) {
-                        combineWith = i;
-                        break;
-                    }
-                }
-                if (combineWith != UNKNOWN) {
-                    mEnergyConsumerToCombinedEnergyConsumerMap[cluster] = combineWith;
-                    combinedEnergyConsumers[combineWith].addAll(clusterToBrackets[cluster]);
-                } else {
-                    mEnergyConsumerToCombinedEnergyConsumerMap[cluster] =
-                            combinedEnergyConsumersCount;
-                    combinedEnergyConsumers[combinedEnergyConsumersCount++] =
-                            clusterToBrackets[cluster];
-                }
-            }
-
-            for (int i = combinedEnergyConsumers.length - 1; i >= 0; i--) {
-                mCombinedEnergyConsumerToPowerBracketMap[i] =
-                        new int[combinedEnergyConsumers[i].size()];
-                for (int j = combinedEnergyConsumers[i].size() - 1; j >= 0; j--) {
-                    mCombinedEnergyConsumerToPowerBracketMap[i][j] =
-                            combinedEnergyConsumers[i].valueAt(j);
-                }
-            }
-        } else {
-            // All CPU cluster energy consumers are combined into one, which is
-            // distributed proportionally to all power brackets.
-            int[] map = new int[powerBracketCount];
-            for (int i = 0; i < map.length; i++) {
-                map[i] = i;
-            }
-            mCombinedEnergyConsumerToPowerBracketMap[0] = map;
-        }
-    }
-
-    private static boolean containsAny(ArraySet<Integer> set1, ArraySet<Integer> set2) {
-        for (int i = 0; i < set2.size(); i++) {
-            if (set1.contains(set2.valueAt(i))) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void computeTotals(PowerComponentAggregatedPowerStats stats,
-            Intermediates intermediates) {
-        intermediates.timeByScalingStep = new long[mCpuScalingStepCount];
-        intermediates.timeByCluster = new long[mCpuClusterCount];
-        intermediates.cumulativeTimeByCluster = new long[mCpuClusterCount];
-
-        List<DeviceStateEstimation> deviceStateEstimations = mPlan.deviceStateEstimations;
-        for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) {
-            DeviceStateEstimation deviceStateEstimation = deviceStateEstimations.get(i);
-            if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStateEstimation.stateValues)) {
-                continue;
-            }
-
-            intermediates.uptime += mStatsLayout.getUsageDuration(mTmpDeviceStatsArray);
-
-            for (int cluster = 0; cluster < mCpuClusterCount; cluster++) {
-                intermediates.timeByCluster[cluster] +=
-                        mStatsLayout.getTimeByCluster(mTmpDeviceStatsArray, cluster);
-            }
-
-            for (int step = 0; step < mCpuScalingStepCount; step++) {
-                long timeInStep = mStatsLayout.getTimeByScalingStep(mTmpDeviceStatsArray, step);
-                intermediates.cumulativeTime += timeInStep;
-                intermediates.timeByScalingStep[step] += timeInStep;
-                intermediates.cumulativeTimeByCluster[mScalingStepToCluster[step]] += timeInStep;
-            }
-        }
-    }
-
-    private void estimatePowerByScalingStep(Intermediates intermediates) {
-        // CPU consumes some power when it's on - no matter which cores are running.
-        double cpuActivePower = mPowerMultiplierForCpuActive * intermediates.uptime;
-
-        // Additionally, every cluster consumes some power when any of its cores are running
-        intermediates.powerByCluster = new double[mCpuClusterCount];
-        for (int cluster = 0; cluster < mCpuClusterCount; cluster++) {
-            intermediates.powerByCluster[cluster] =
-                    mPowerMultipliersByCluster[cluster] * intermediates.timeByCluster[cluster];
-        }
-
-        // Finally, additional power is consumed depending on the frequency scaling
-        intermediates.powerByScalingStep = new double[mCpuScalingStepCount];
-        for (int step = 0; step < mCpuScalingStepCount; step++) {
-            int cluster = mScalingStepToCluster[step];
-
-            double power;
-
-            // Distribute base power proportionally
-            power = cpuActivePower * intermediates.timeByScalingStep[step]
-                    / intermediates.cumulativeTime;
-
-            // Distribute per-cluster power proportionally
-            long cumulativeTimeInCluster = intermediates.cumulativeTimeByCluster[cluster];
-            if (cumulativeTimeInCluster != 0) {
-                power += intermediates.powerByCluster[cluster]
-                         * intermediates.timeByScalingStep[step]
-                         / cumulativeTimeInCluster;
-            }
-
-            power += mPowerMultipliersByScalingStep[step] * intermediates.timeByScalingStep[step];
-
-            intermediates.powerByScalingStep[step] = power;
-        }
-    }
-
-    private void estimatePowerByDeviceState(PowerComponentAggregatedPowerStats stats,
-            Intermediates intermediates) {
-        int cpuScalingStepCount = mStatsLayout.getCpuScalingStepCount();
-        int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
-        int[] scalingStepToBracketMap = mStatsLayout.getScalingStepToPowerBracketMap();
-        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
-        List<DeviceStateEstimation> deviceStateEstimations = mPlan.deviceStateEstimations;
-        for (int dse = deviceStateEstimations.size() - 1; dse >= 0; dse--) {
-            DeviceStateEstimation deviceStateEstimation = deviceStateEstimations.get(dse);
-            deviceStateEstimation.intermediates = new DeviceStatsIntermediates();
-            DeviceStatsIntermediates deviceStatsIntermediates =
-                    (DeviceStatsIntermediates) deviceStateEstimation.intermediates;
-            deviceStatsIntermediates.timeByBracket = new long[powerBracketCount];
-            deviceStatsIntermediates.powerByBracket = new double[powerBracketCount];
-
-            stats.getDeviceStats(mTmpDeviceStatsArray, deviceStateEstimation.stateValues);
-            for (int step = 0; step < cpuScalingStepCount; step++) {
-                if (intermediates.timeByScalingStep[step] == 0) {
-                    continue;
-                }
-
-                long timeInStep = mStatsLayout.getTimeByScalingStep(mTmpDeviceStatsArray, step);
-                double stepPower = intermediates.powerByScalingStep[step] * timeInStep
-                                   / intermediates.timeByScalingStep[step];
-
-                int bracket = scalingStepToBracketMap[step];
-                deviceStatsIntermediates.timeByBracket[bracket] += timeInStep;
-                deviceStatsIntermediates.powerByBracket[bracket] += stepPower;
-            }
-
-            if (energyConsumerCount != 0) {
-                adjustEstimatesUsingEnergyConsumers(intermediates, deviceStatsIntermediates);
-            }
-
-            double power = 0;
-            for (int i = deviceStatsIntermediates.powerByBracket.length - 1; i >= 0; i--) {
-                power += deviceStatsIntermediates.powerByBracket[i];
-            }
-            deviceStatsIntermediates.power = power;
-            mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, power);
-            stats.setDeviceStats(deviceStateEstimation.stateValues, mTmpDeviceStatsArray);
-        }
-    }
-
-    private void adjustEstimatesUsingEnergyConsumers(
-            Intermediates intermediates, DeviceStatsIntermediates deviceStatsIntermediates) {
-        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
-        if (energyConsumerCount == 0) {
-            return;
-        }
-
-        if (intermediates.powerByEnergyConsumer == null) {
-            intermediates.powerByEnergyConsumer = new long[energyConsumerCount];
-        } else {
-            Arrays.fill(intermediates.powerByEnergyConsumer, 0);
-        }
-        for (int i = 0; i < energyConsumerCount; i++) {
-            intermediates.powerByEnergyConsumer[mEnergyConsumerToCombinedEnergyConsumerMap[i]] +=
-                    mStatsLayout.getConsumedEnergy(mTmpDeviceStatsArray, i);
-        }
-
-        for (int combinedConsumer = mCombinedEnergyConsumerToPowerBracketMap.length - 1;
-                combinedConsumer >= 0; combinedConsumer--) {
-            int[] combinedEnergyConsumerToPowerBracketMap =
-                    mCombinedEnergyConsumerToPowerBracketMap[combinedConsumer];
-            if (combinedEnergyConsumerToPowerBracketMap == null) {
-                continue;
-            }
-
-            double consumedEnergy = uCtoMah(intermediates.powerByEnergyConsumer[combinedConsumer]);
-
-            double totalModeledPower = 0;
-            for (int bracket : combinedEnergyConsumerToPowerBracketMap) {
-                totalModeledPower += deviceStatsIntermediates.powerByBracket[bracket];
-            }
-            if (totalModeledPower == 0) {
-                continue;
-            }
-
-            for (int bracket : combinedEnergyConsumerToPowerBracketMap) {
-                deviceStatsIntermediates.powerByBracket[bracket] =
-                        consumedEnergy * deviceStatsIntermediates.powerByBracket[bracket]
-                        / totalModeledPower;
-            }
-        }
-    }
-
-    private void combineDeviceStateEstimates() {
-        for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
-            CombinedDeviceStateEstimate cdse = mPlan.combinedDeviceStateEstimations.get(i);
-            DeviceStatsIntermediates cdseIntermediates = new DeviceStatsIntermediates();
-            cdse.intermediates = cdseIntermediates;
-            int bracketCount = mStatsLayout.getCpuPowerBracketCount();
-            cdseIntermediates.timeByBracket = new long[bracketCount];
-            cdseIntermediates.powerByBracket = new double[bracketCount];
-            List<DeviceStateEstimation> deviceStateEstimations = cdse.deviceStateEstimations;
-            for (int j = deviceStateEstimations.size() - 1; j >= 0; j--) {
-                DeviceStateEstimation dse = deviceStateEstimations.get(j);
-                DeviceStatsIntermediates intermediates =
-                        (DeviceStatsIntermediates) dse.intermediates;
-                cdseIntermediates.power += intermediates.power;
-                for (int k = 0; k < bracketCount; k++) {
-                    cdseIntermediates.timeByBracket[k] += intermediates.timeByBracket[k];
-                    cdseIntermediates.powerByBracket[k] += intermediates.powerByBracket[k];
-                }
-            }
-        }
-    }
-
-    private void estimateUidPowerConsumption(PowerComponentAggregatedPowerStats stats, int uid,
-            UidStateEstimate uidStateEstimate) {
-        CombinedDeviceStateEstimate combinedDeviceStateEstimate =
-                uidStateEstimate.combinedDeviceStateEstimate;
-        DeviceStatsIntermediates cdsIntermediates =
-                (DeviceStatsIntermediates) combinedDeviceStateEstimate.intermediates;
-        for (int i = 0; i < uidStateEstimate.proportionalEstimates.size(); i++) {
-            UidStateProportionalEstimate proportionalEstimate =
-                    uidStateEstimate.proportionalEstimates.get(i);
-            if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
-                continue;
-            }
-
-            double power = 0;
-            for (int bracket = 0; bracket < mStatsLayout.getCpuPowerBracketCount(); bracket++) {
-                if (cdsIntermediates.timeByBracket[bracket] == 0) {
-                    continue;
-                }
-
-                long timeInBracket = mStatsLayout.getUidTimeByPowerBracket(mTmpUidStatsArray,
-                        bracket);
-                if (timeInBracket == 0) {
-                    continue;
-                }
-
-                power += cdsIntermediates.powerByBracket[bracket] * timeInBracket
-                            / cdsIntermediates.timeByBracket[bracket];
-            }
-
-            mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
-            stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
-        }
-    }
-
-    @Override
-    public String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
-        unpackPowerStatsDescriptor(descriptor);
-        StringBuilder sb = new StringBuilder();
-        int cpuScalingStepCount = mStatsLayout.getCpuScalingStepCount();
-        sb.append("steps: [");
-        for (int step = 0; step < cpuScalingStepCount; step++) {
-            if (step != 0) {
-                sb.append(", ");
-            }
-            sb.append(mStatsLayout.getTimeByScalingStep(stats, step));
-        }
-        int clusterCount = mStatsLayout.getCpuClusterCount();
-        sb.append("] clusters: [");
-        for (int cluster = 0; cluster < clusterCount; cluster++) {
-            if (cluster != 0) {
-                sb.append(", ");
-            }
-            sb.append(mStatsLayout.getTimeByCluster(stats, cluster));
-        }
-        sb.append("] uptime: ").append(mStatsLayout.getUsageDuration(stats));
-        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
-        if (energyConsumerCount > 0) {
-            sb.append(" energy: [");
-            for (int i = 0; i < energyConsumerCount; i++) {
-                if (i != 0) {
-                    sb.append(", ");
-                }
-                sb.append(mStatsLayout.getConsumedEnergy(stats, i));
-            }
-            sb.append("]");
-        }
-        sb.append(" power: ").append(
-                BatteryStats.formatCharge(mStatsLayout.getDevicePowerEstimate(stats)));
-        return sb.toString();
-    }
-
-    @Override
-    public String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
-        unpackPowerStatsDescriptor(descriptor);
-        StringBuilder sb = new StringBuilder();
-        sb.append("[");
-        int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
-        for (int bracket = 0; bracket < powerBracketCount; bracket++) {
-            if (bracket != 0) {
-                sb.append(", ");
-            }
-            sb.append(mStatsLayout.getUidTimeByPowerBracket(stats, bracket));
-        }
-        sb.append("] power: ").append(
-                BatteryStats.formatCharge(mStatsLayout.getUidPowerEstimate(stats)));
-        return sb.toString();
-    }
-}
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
index 1af1271..f53a1b0 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
@@ -16,14 +16,11 @@
 
 package com.android.server.power.stats;
 
-import android.hardware.power.stats.EnergyConsumer;
-import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.Handler;
 import android.os.PersistableBundle;
 import android.os.Process;
-import android.power.PowerStatsInternal;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -34,20 +31,11 @@
 import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
-import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
 import java.util.Locale;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.function.IntSupplier;
-import java.util.function.Supplier;
 
 /**
  * Collects snapshots of power-related system statistics.
@@ -61,215 +49,55 @@
     private static final long ENERGY_UNSPECIFIED = -1;
     private static final int DEFAULT_CPU_POWER_BRACKETS = 3;
     private static final int DEFAULT_CPU_POWER_BRACKETS_PER_ENERGY_CONSUMER = 2;
-    private static final long POWER_STATS_ENERGY_CONSUMERS_TIMEOUT = 20000;
+
+    interface Injector {
+        Handler getHandler();
+        Clock getClock();
+        PowerStatsUidResolver getUidResolver();
+        CpuScalingPolicies getCpuScalingPolicies();
+        PowerProfile getPowerProfile();
+        KernelCpuStatsReader getKernelCpuStatsReader();
+        ConsumedEnergyRetriever getConsumedEnergyRetriever();
+        IntSupplier getVoltageSupplier();
+
+        default int getDefaultCpuPowerBrackets() {
+            return DEFAULT_CPU_POWER_BRACKETS;
+        }
+
+        default int getDefaultCpuPowerBracketsPerEnergyConsumer() {
+            return DEFAULT_CPU_POWER_BRACKETS_PER_ENERGY_CONSUMER;
+        }
+    }
+
+    private final Injector mInjector;
 
     private boolean mIsInitialized;
-    private final CpuScalingPolicies mCpuScalingPolicies;
-    private final PowerProfile mPowerProfile;
-    private final KernelCpuStatsReader mKernelCpuStatsReader;
-    private final PowerStatsUidResolver mUidResolver;
-    private final Supplier<PowerStatsInternal> mPowerStatsSupplier;
-    private final IntSupplier mVoltageSupplier;
-    private final int mDefaultCpuPowerBrackets;
-    private final int mDefaultCpuPowerBracketsPerEnergyConsumer;
+    private CpuScalingPolicies mCpuScalingPolicies;
+    private PowerProfile mPowerProfile;
+    private KernelCpuStatsReader mKernelCpuStatsReader;
+    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    private IntSupplier mVoltageSupplier;
+    private int mDefaultCpuPowerBrackets;
+    private int mDefaultCpuPowerBracketsPerEnergyConsumer;
     private long[] mCpuTimeByScalingStep;
     private long[] mTempCpuTimeByScalingStep;
     private long[] mTempUidStats;
     private final SparseArray<UidStats> mUidStats = new SparseArray<>();
     private boolean mIsPerUidTimeInStateSupported;
-    private PowerStatsInternal mPowerStatsInternal;
     private int[] mCpuEnergyConsumerIds = new int[0];
     private PowerStats.Descriptor mPowerStatsDescriptor;
     // Reusable instance
     private PowerStats mCpuPowerStats;
-    private CpuStatsArrayLayout mLayout;
+    private CpuPowerStatsLayout mLayout;
     private long mLastUpdateTimestampNanos;
     private long mLastUpdateUptimeMillis;
     private int mLastVoltageMv;
     private long[] mLastConsumedEnergyUws;
 
-    /**
-     * Captures the positions and lengths of sections of the stats array, such as time-in-state,
-     * power usage estimates etc.
-     */
-    public static class CpuStatsArrayLayout extends StatsArrayLayout {
-        private static final String EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION = "dt";
-        private static final String EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT = "dtc";
-        private static final String EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION = "dc";
-        private static final String EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT = "dcc";
-        private static final String EXTRA_UID_BRACKETS_POSITION = "ub";
-        private static final String EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET = "us";
-
-        private int mDeviceCpuTimeByScalingStepPosition;
-        private int mDeviceCpuTimeByScalingStepCount;
-        private int mDeviceCpuTimeByClusterPosition;
-        private int mDeviceCpuTimeByClusterCount;
-
-        private int mUidPowerBracketsPosition;
-        private int mUidPowerBracketCount;
-
-        private int[] mScalingStepToPowerBracketMap;
-
-        /**
-         * Declare that the stats array has a section capturing CPU time per scaling step
-         */
-        public void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
-            mDeviceCpuTimeByScalingStepPosition = addDeviceSection(scalingStepCount);
-            mDeviceCpuTimeByScalingStepCount = scalingStepCount;
-        }
-
-        public int getCpuScalingStepCount() {
-            return mDeviceCpuTimeByScalingStepCount;
-        }
-
-        /**
-         * Saves the time duration in the <code>stats</code> element
-         * corresponding to the CPU scaling <code>state</code>.
-         */
-        public void setTimeByScalingStep(long[] stats, int step, long value) {
-            stats[mDeviceCpuTimeByScalingStepPosition + step] = value;
-        }
-
-        /**
-         * Extracts the time duration from the <code>stats</code> element
-         * corresponding to the CPU scaling <code>step</code>.
-         */
-        public long getTimeByScalingStep(long[] stats, int step) {
-            return stats[mDeviceCpuTimeByScalingStepPosition + step];
-        }
-
-        /**
-         * Declare that the stats array has a section capturing CPU time in each cluster
-         */
-        public void addDeviceSectionCpuTimeByCluster(int clusterCount) {
-            mDeviceCpuTimeByClusterPosition = addDeviceSection(clusterCount);
-            mDeviceCpuTimeByClusterCount = clusterCount;
-        }
-
-        public int getCpuClusterCount() {
-            return mDeviceCpuTimeByClusterCount;
-        }
-
-        /**
-         * Saves the time duration in the <code>stats</code> element
-         * corresponding to the CPU <code>cluster</code>.
-         */
-        public void setTimeByCluster(long[] stats, int cluster, long value) {
-            stats[mDeviceCpuTimeByClusterPosition + cluster] = value;
-        }
-
-        /**
-         * Extracts the time duration from the <code>stats</code> element
-         * corresponding to the CPU <code>cluster</code>.
-         */
-        public long getTimeByCluster(long[] stats, int cluster) {
-            return stats[mDeviceCpuTimeByClusterPosition + cluster];
-        }
-
-        /**
-         * Declare that the UID stats array has a section capturing CPU time per power bracket.
-         */
-        public void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
-            mScalingStepToPowerBracketMap = scalingStepToPowerBracketMap;
-            updatePowerBracketCount();
-            mUidPowerBracketsPosition = addUidSection(mUidPowerBracketCount);
-        }
-
-        private void updatePowerBracketCount() {
-            mUidPowerBracketCount = 1;
-            for (int bracket : mScalingStepToPowerBracketMap) {
-                if (bracket >= mUidPowerBracketCount) {
-                    mUidPowerBracketCount = bracket + 1;
-                }
-            }
-        }
-
-        public int[] getScalingStepToPowerBracketMap() {
-            return mScalingStepToPowerBracketMap;
-        }
-
-        public int getCpuPowerBracketCount() {
-            return mUidPowerBracketCount;
-        }
-
-        /**
-         * Saves time in <code>bracket</code> in the corresponding section of <code>stats</code>.
-         */
-        public void setUidTimeByPowerBracket(long[] stats, int bracket, long value) {
-            stats[mUidPowerBracketsPosition + bracket] = value;
-        }
-
-        /**
-         * Extracts the time in <code>bracket</code> from a UID stats array.
-         */
-        public long getUidTimeByPowerBracket(long[] stats, int bracket) {
-            return stats[mUidPowerBracketsPosition + bracket];
-        }
-
-        /**
-         * Copies the elements of the stats array layout into <code>extras</code>
-         */
-        public void toExtras(PersistableBundle extras) {
-            super.toExtras(extras);
-            extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
-                    mDeviceCpuTimeByScalingStepPosition);
-            extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
-                    mDeviceCpuTimeByScalingStepCount);
-            extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
-                    mDeviceCpuTimeByClusterPosition);
-            extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
-                    mDeviceCpuTimeByClusterCount);
-            extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
-            putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
-                    mScalingStepToPowerBracketMap);
-        }
-
-        /**
-         * Retrieves elements of the stats array layout from <code>extras</code>
-         */
-        public void fromExtras(PersistableBundle extras) {
-            super.fromExtras(extras);
-            mDeviceCpuTimeByScalingStepPosition =
-                    extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
-            mDeviceCpuTimeByScalingStepCount =
-                    extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
-            mDeviceCpuTimeByClusterPosition =
-                    extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
-            mDeviceCpuTimeByClusterCount =
-                    extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
-            mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
-            mScalingStepToPowerBracketMap =
-                    getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
-            if (mScalingStepToPowerBracketMap == null) {
-                mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
-            }
-            updatePowerBracketCount();
-        }
-    }
-
-    public CpuPowerStatsCollector(CpuScalingPolicies cpuScalingPolicies, PowerProfile powerProfile,
-            PowerStatsUidResolver uidResolver, IntSupplier voltageSupplier, Handler handler,
-            long throttlePeriodMs) {
-        this(cpuScalingPolicies, powerProfile, handler, new KernelCpuStatsReader(), uidResolver,
-                () -> LocalServices.getService(PowerStatsInternal.class), voltageSupplier,
-                throttlePeriodMs, Clock.SYSTEM_CLOCK, DEFAULT_CPU_POWER_BRACKETS,
-                DEFAULT_CPU_POWER_BRACKETS_PER_ENERGY_CONSUMER);
-    }
-
-    public CpuPowerStatsCollector(CpuScalingPolicies cpuScalingPolicies, PowerProfile powerProfile,
-            Handler handler, KernelCpuStatsReader kernelCpuStatsReader,
-            PowerStatsUidResolver uidResolver, Supplier<PowerStatsInternal> powerStatsSupplier,
-            IntSupplier voltageSupplier, long throttlePeriodMs, Clock clock,
-            int defaultCpuPowerBrackets, int defaultCpuPowerBracketsPerEnergyConsumer) {
-        super(handler, throttlePeriodMs, clock);
-        mCpuScalingPolicies = cpuScalingPolicies;
-        mPowerProfile = powerProfile;
-        mKernelCpuStatsReader = kernelCpuStatsReader;
-        mUidResolver = uidResolver;
-        mPowerStatsSupplier = powerStatsSupplier;
-        mVoltageSupplier = voltageSupplier;
-        mDefaultCpuPowerBrackets = defaultCpuPowerBrackets;
-        mDefaultCpuPowerBracketsPerEnergyConsumer = defaultCpuPowerBracketsPerEnergyConsumer;
+    public CpuPowerStatsCollector(Injector injector, long throttlePeriodMs) {
+        super(injector.getHandler(), throttlePeriodMs, injector.getUidResolver(),
+                injector.getClock());
+        mInjector = injector;
     }
 
     private boolean ensureInitialized() {
@@ -281,19 +109,27 @@
             return false;
         }
 
-        mIsPerUidTimeInStateSupported = mKernelCpuStatsReader.nativeIsSupportedFeature();
-        mPowerStatsInternal = mPowerStatsSupplier.get();
+        mCpuScalingPolicies = mInjector.getCpuScalingPolicies();
+        mPowerProfile = mInjector.getPowerProfile();
+        mKernelCpuStatsReader = mInjector.getKernelCpuStatsReader();
+        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
+        mVoltageSupplier = mInjector.getVoltageSupplier();
+        mDefaultCpuPowerBrackets = mInjector.getDefaultCpuPowerBrackets();
+        mDefaultCpuPowerBracketsPerEnergyConsumer =
+                mInjector.getDefaultCpuPowerBracketsPerEnergyConsumer();
 
-        if (mPowerStatsInternal != null) {
-            readCpuEnergyConsumerIds();
-        }
+        mIsPerUidTimeInStateSupported = mKernelCpuStatsReader.isSupportedFeature();
+        mCpuEnergyConsumerIds =
+                mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER);
+        mLastConsumedEnergyUws = new long[mCpuEnergyConsumerIds.length];
+        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
 
         int cpuScalingStepCount = mCpuScalingPolicies.getScalingStepCount();
         mCpuTimeByScalingStep = new long[cpuScalingStepCount];
         mTempCpuTimeByScalingStep = new long[cpuScalingStepCount];
         int[] scalingStepToPowerBracketMap = initPowerBrackets();
 
-        mLayout = new CpuStatsArrayLayout();
+        mLayout = new CpuPowerStatsLayout();
         mLayout.addDeviceSectionCpuTimeByScalingStep(cpuScalingStepCount);
         mLayout.addDeviceSectionCpuTimeByCluster(mCpuScalingPolicies.getPolicies().length);
         mLayout.addDeviceSectionUsageDuration();
@@ -306,7 +142,8 @@
         mLayout.toExtras(extras);
 
         mPowerStatsDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
-                mLayout.getDeviceStatsArrayLength(), mLayout.getUidStatsArrayLength(), extras);
+                mLayout.getDeviceStatsArrayLength(), /* stateLabels */null,
+                /* stateStatsArrayLength */ 0, mLayout.getUidStatsArrayLength(), extras);
         mCpuPowerStats = new PowerStats(mPowerStatsDescriptor);
 
         mTempUidStats = new long[mLayout.getCpuPowerBracketCount()];
@@ -315,32 +152,6 @@
         return true;
     }
 
-    private void readCpuEnergyConsumerIds() {
-        EnergyConsumer[] energyConsumerInfo = mPowerStatsInternal.getEnergyConsumerInfo();
-        if (energyConsumerInfo == null) {
-            return;
-        }
-
-        List<EnergyConsumer> cpuEnergyConsumers = new ArrayList<>();
-        for (EnergyConsumer energyConsumer : energyConsumerInfo) {
-            if (energyConsumer.type == EnergyConsumerType.CPU_CLUSTER) {
-                cpuEnergyConsumers.add(energyConsumer);
-            }
-        }
-        if (cpuEnergyConsumers.isEmpty()) {
-            return;
-        }
-
-        cpuEnergyConsumers.sort(Comparator.comparing(c -> c.ordinal));
-
-        mCpuEnergyConsumerIds = new int[cpuEnergyConsumers.size()];
-        for (int i = 0; i < mCpuEnergyConsumerIds.length; i++) {
-            mCpuEnergyConsumerIds[i] = cpuEnergyConsumers.get(i).id;
-        }
-        mLastConsumedEnergyUws = new long[cpuEnergyConsumers.size()];
-        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
-    }
-
     private int[] initPowerBrackets() {
         if (mPowerProfile.getCpuPowerBracketCount() != PowerProfile.POWER_BRACKETS_UNSPECIFIED) {
             return initPowerBracketsFromPowerProfile();
@@ -372,6 +183,7 @@
         return stepToBracketMap;
     }
 
+
     private int[] initPowerBracketsByCluster(int defaultBracketCountPerCluster) {
         int[] stepToBracketMap = new int[mCpuScalingPolicies.getScalingStepCount()];
         int index = 0;
@@ -531,7 +343,7 @@
 
         mCpuPowerStats.uidStats.clear();
         // TODO(b/305120724): additionally retrieve time-in-cluster for each CPU cluster
-        long newTimestampNanos = mKernelCpuStatsReader.nativeReadCpuStats(this::processUidStats,
+        long newTimestampNanos = mKernelCpuStatsReader.readCpuStats(this::processUidStats,
                 mLayout.getScalingStepToPowerBracketMap(), mLastUpdateTimestampNanos,
                 mTempCpuTimeByScalingStep, mTempUidStats);
         for (int step = mLayout.getCpuScalingStepCount() - 1; step >= 0; step--) {
@@ -571,35 +383,20 @@
         int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
         mLastVoltageMv = voltageMv;
 
-        CompletableFuture<EnergyConsumerResult[]> future =
-                mPowerStatsInternal.getEnergyConsumedAsync(mCpuEnergyConsumerIds);
-        EnergyConsumerResult[] results = null;
-        try {
-            results = future.get(
-                    POWER_STATS_ENERGY_CONSUMERS_TIMEOUT, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException | ExecutionException | TimeoutException e) {
-            Slog.e(TAG, "Could not obtain energy consumers from PowerStatsService", e);
-        }
-        if (results == null) {
+        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mCpuEnergyConsumerIds);
+        if (energyUws == null) {
             return;
         }
 
-        for (int i = 0; i < mCpuEnergyConsumerIds.length; i++) {
-            int id = mCpuEnergyConsumerIds[i];
-            for (EnergyConsumerResult result : results) {
-                if (result.id == id) {
-                    long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
-                            ? result.energyUWs - mLastConsumedEnergyUws[i] : 0;
-                    if (energyDelta < 0) {
-                        // Likely, restart of powerstats HAL
-                        energyDelta = 0;
-                    }
-                    mLayout.setConsumedEnergy(mCpuPowerStats.stats, i,
-                            uJtoUc(energyDelta, averageVoltage));
-                    mLastConsumedEnergyUws[i] = result.energyUWs;
-                    break;
-                }
+        for (int i = energyUws.length - 1; i >= 0; i--) {
+            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
+                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
+            if (energyDelta < 0) {
+                // Likely, restart of powerstats HAL
+                energyDelta = 0;
             }
+            mLayout.setConsumedEnergy(mCpuPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
+            mLastConsumedEnergyUws[i] = energyUws[i];
         }
     }
 
@@ -622,7 +419,8 @@
 
         boolean nonzero = false;
         for (int bracket = powerBracketCount - 1; bracket >= 0; bracket--) {
-            long delta = timeByPowerBracket[bracket] - uidStats.timeByPowerBracket[bracket];
+            long delta = Math.max(0,
+                    timeByPowerBracket[bracket] - uidStats.timeByPowerBracket[bracket]);
             if (delta != 0) {
                 nonzero = true;
             }
@@ -648,10 +446,27 @@
         }
     }
 
+    @Override
+    protected void onUidRemoved(int uid) {
+        super.onUidRemoved(uid);
+        mUidStats.remove(uid);
+    }
+
     /**
      * Native class that retrieves CPU stats from the kernel.
      */
     public static class KernelCpuStatsReader {
+        protected boolean isSupportedFeature() {
+            return nativeIsSupportedFeature();
+        }
+
+        protected long readCpuStats(KernelCpuStatsCallback callback,
+                int[] scalingStepToPowerBracketMap, long lastUpdateTimestampNanos,
+                long[] outCpuTimeByScalingStep, long[] tempForUidStats) {
+            return nativeReadCpuStats(callback, scalingStepToPowerBracketMap,
+                    lastUpdateTimestampNanos, outCpuTimeByScalingStep, tempForUidStats);
+        }
+
         protected native boolean nativeIsSupportedFeature();
 
         protected native long nativeReadCpuStats(KernelCpuStatsCallback callback,
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java
new file mode 100644
index 0000000..1bcb2c4
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.os.PersistableBundle;
+
+/**
+ * Captures the positions and lengths of sections of the stats array, such as time-in-state,
+ * power usage estimates etc.
+ */
+public class CpuPowerStatsLayout extends PowerStatsLayout {
+    private static final String EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION = "dt";
+    private static final String EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT = "dtc";
+    private static final String EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION = "dc";
+    private static final String EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT = "dcc";
+    private static final String EXTRA_UID_BRACKETS_POSITION = "ub";
+    private static final String EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET = "us";
+
+    private int mDeviceCpuTimeByScalingStepPosition;
+    private int mDeviceCpuTimeByScalingStepCount;
+    private int mDeviceCpuTimeByClusterPosition;
+    private int mDeviceCpuTimeByClusterCount;
+
+    private int mUidPowerBracketsPosition;
+    private int mUidPowerBracketCount;
+
+    private int[] mScalingStepToPowerBracketMap;
+
+    /**
+     * Declare that the stats array has a section capturing CPU time per scaling step
+     */
+    public void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
+        mDeviceCpuTimeByScalingStepPosition = addDeviceSection(scalingStepCount);
+        mDeviceCpuTimeByScalingStepCount = scalingStepCount;
+    }
+
+    public int getCpuScalingStepCount() {
+        return mDeviceCpuTimeByScalingStepCount;
+    }
+
+    /**
+     * Saves the time duration in the <code>stats</code> element
+     * corresponding to the CPU scaling <code>state</code>.
+     */
+    public void setTimeByScalingStep(long[] stats, int step, long value) {
+        stats[mDeviceCpuTimeByScalingStepPosition + step] = value;
+    }
+
+    /**
+     * Extracts the time duration from the <code>stats</code> element
+     * corresponding to the CPU scaling <code>step</code>.
+     */
+    public long getTimeByScalingStep(long[] stats, int step) {
+        return stats[mDeviceCpuTimeByScalingStepPosition + step];
+    }
+
+    /**
+     * Declare that the stats array has a section capturing CPU time in each cluster
+     */
+    public void addDeviceSectionCpuTimeByCluster(int clusterCount) {
+        mDeviceCpuTimeByClusterPosition = addDeviceSection(clusterCount);
+        mDeviceCpuTimeByClusterCount = clusterCount;
+    }
+
+    public int getCpuClusterCount() {
+        return mDeviceCpuTimeByClusterCount;
+    }
+
+    /**
+     * Saves the time duration in the <code>stats</code> element
+     * corresponding to the CPU <code>cluster</code>.
+     */
+    public void setTimeByCluster(long[] stats, int cluster, long value) {
+        stats[mDeviceCpuTimeByClusterPosition + cluster] = value;
+    }
+
+    /**
+     * Extracts the time duration from the <code>stats</code> element
+     * corresponding to the CPU <code>cluster</code>.
+     */
+    public long getTimeByCluster(long[] stats, int cluster) {
+        return stats[mDeviceCpuTimeByClusterPosition + cluster];
+    }
+
+    /**
+     * Declare that the UID stats array has a section capturing CPU time per power bracket.
+     */
+    public void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
+        mScalingStepToPowerBracketMap = scalingStepToPowerBracketMap;
+        updatePowerBracketCount();
+        mUidPowerBracketsPosition = addUidSection(mUidPowerBracketCount);
+    }
+
+    private void updatePowerBracketCount() {
+        mUidPowerBracketCount = 1;
+        for (int bracket : mScalingStepToPowerBracketMap) {
+            if (bracket >= mUidPowerBracketCount) {
+                mUidPowerBracketCount = bracket + 1;
+            }
+        }
+    }
+
+    public int[] getScalingStepToPowerBracketMap() {
+        return mScalingStepToPowerBracketMap;
+    }
+
+    public int getCpuPowerBracketCount() {
+        return mUidPowerBracketCount;
+    }
+
+    /**
+     * Saves time in <code>bracket</code> in the corresponding section of <code>stats</code>.
+     */
+    public void setUidTimeByPowerBracket(long[] stats, int bracket, long value) {
+        stats[mUidPowerBracketsPosition + bracket] = value;
+    }
+
+    /**
+     * Extracts the time in <code>bracket</code> from a UID stats array.
+     */
+    public long getUidTimeByPowerBracket(long[] stats, int bracket) {
+        return stats[mUidPowerBracketsPosition + bracket];
+    }
+
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
+                mDeviceCpuTimeByScalingStepPosition);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
+                mDeviceCpuTimeByScalingStepCount);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
+                mDeviceCpuTimeByClusterPosition);
+        extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
+                mDeviceCpuTimeByClusterCount);
+        extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
+        putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
+                mScalingStepToPowerBracketMap);
+    }
+
+    /**
+     * Retrieves elements of the stats array layout from <code>extras</code>
+     */
+    public void fromExtras(PersistableBundle extras) {
+        super.fromExtras(extras);
+        mDeviceCpuTimeByScalingStepPosition =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
+        mDeviceCpuTimeByScalingStepCount =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
+        mDeviceCpuTimeByClusterPosition =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
+        mDeviceCpuTimeByClusterCount =
+                extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
+        mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
+        mScalingStepToPowerBracketMap =
+                getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
+        if (mScalingStepToPowerBracketMap == null) {
+            mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
+        }
+        updatePowerBracketCount();
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java
new file mode 100644
index 0000000..c34b8a8
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.power.stats;
+
+import android.os.BatteryStats;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.os.CpuScalingPolicies;
+import com.android.internal.os.PowerProfile;
+import com.android.internal.os.PowerStats;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class CpuPowerStatsProcessor extends PowerStatsProcessor {
+    private static final String TAG = "CpuPowerStatsProcessor";
+
+    private static final double HOUR_IN_MILLIS = TimeUnit.HOURS.toMillis(1);
+    private static final int UNKNOWN = -1;
+
+    private final CpuScalingPolicies mCpuScalingPolicies;
+    // Number of CPU core clusters
+    private final int mCpuClusterCount;
+    // Total number of CPU scaling steps across all clusters
+    private final int mCpuScalingStepCount;
+    // Map of scaling step to the corresponding core cluster mScalingStepToCluster[step]->cluster
+    private final int[] mScalingStepToCluster;
+    // Average power consumed by the CPU when it is powered up (per power_profile.xml)
+    private final double mPowerMultiplierForCpuActive;
+    // Average power consumed by each cluster when it is powered up (per power_profile.xml)
+    private final double[] mPowerMultipliersByCluster;
+    // Average power consumed by each scaling step when running code (per power_profile.xml)
+    private final double[] mPowerMultipliersByScalingStep;
+    // A map used to combine energy consumers into a smaller set, in case power brackets
+    // are defined in a way that does not allow an unambiguous mapping of energy consumers to
+    // brackets
+    private int[] mEnergyConsumerToCombinedEnergyConsumerMap;
+    // A map of combined energy consumers to the corresponding collections of power brackets.
+    // For example, if there are two CPU_CLUSTER rails and each maps to three brackets,
+    // this map will look like this:
+    //     0 : [0, 1, 2]
+    //     1 : [3, 4, 5]
+    private int[][] mCombinedEnergyConsumerToPowerBracketMap;
+
+    // Cached reference to a PowerStats descriptor. Almost never changes in practice,
+    // helping to avoid reparsing the descriptor for every PowerStats span.
+    private PowerStats.Descriptor mLastUsedDescriptor;
+    // Cached results of parsing of current PowerStats.Descriptor. Only refreshed when
+    // mLastUsedDescriptor changes
+    private CpuPowerStatsLayout mStatsLayout;
+    // Sequence of steps for power estimation and intermediate results.
+    private PowerEstimationPlan mPlan;
+
+    // Temp array for retrieval of device power stats, to avoid repeated allocations
+    private long[] mTmpDeviceStatsArray;
+    // Temp array for retrieval of UID power stats, to avoid repeated allocations
+    private long[] mTmpUidStatsArray;
+
+    public CpuPowerStatsProcessor(PowerProfile powerProfile, CpuScalingPolicies scalingPolicies) {
+        mCpuScalingPolicies = scalingPolicies;
+        mCpuScalingStepCount = scalingPolicies.getScalingStepCount();
+        mScalingStepToCluster = new int[mCpuScalingStepCount];
+        mPowerMultipliersByScalingStep = new double[mCpuScalingStepCount];
+
+        int step = 0;
+        int[] policies = scalingPolicies.getPolicies();
+        mCpuClusterCount = policies.length;
+        mPowerMultipliersByCluster = new double[mCpuClusterCount];
+        for (int cluster = 0; cluster < mCpuClusterCount; cluster++) {
+            int policy = policies[cluster];
+            mPowerMultipliersByCluster[cluster] =
+                    powerProfile.getAveragePowerForCpuScalingPolicy(policy) / HOUR_IN_MILLIS;
+            int[] frequencies = scalingPolicies.getFrequencies(policy);
+            for (int i = 0; i < frequencies.length; i++) {
+                mScalingStepToCluster[step] = cluster;
+                mPowerMultipliersByScalingStep[step] =
+                        powerProfile.getAveragePowerForCpuScalingStep(policy, i) / HOUR_IN_MILLIS;
+                step++;
+            }
+        }
+        mPowerMultiplierForCpuActive =
+                powerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE) / HOUR_IN_MILLIS;
+    }
+
+    private void unpackPowerStatsDescriptor(PowerStats.Descriptor descriptor) {
+        if (descriptor.equals(mLastUsedDescriptor)) {
+            return;
+        }
+
+        mLastUsedDescriptor = descriptor;
+        mStatsLayout = new CpuPowerStatsLayout();
+        mStatsLayout.fromExtras(descriptor.extras);
+
+        mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
+        mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
+    }
+
+    /**
+     * Temporary struct to capture intermediate results of power estimation.
+     */
+    private static final class Intermediates {
+        public long uptime;
+        // Sum of all time-in-step values, combining all time-in-step durations across all cores.
+        public long cumulativeTime;
+        // CPU activity durations per cluster
+        public long[] timeByCluster;
+        // Sums of time-in-step values, aggregated by cluster, combining all cores in the cluster.
+        public long[] cumulativeTimeByCluster;
+        public long[] timeByScalingStep;
+        public double[] powerByCluster;
+        public double[] powerByScalingStep;
+        public long[] powerByEnergyConsumer;
+    }
+
+    /**
+     * Temporary struct to capture intermediate results of power estimation.
+     */
+    private static class DeviceStatsIntermediates {
+        public double power;
+        public long[] timeByBracket;
+        public double[] powerByBracket;
+    }
+
+    @Override
+    public void finish(PowerComponentAggregatedPowerStats stats) {
+        if (stats.getPowerStatsDescriptor() == null) {
+            return;
+        }
+
+        unpackPowerStatsDescriptor(stats.getPowerStatsDescriptor());
+
+        if (mPlan == null) {
+            mPlan = new PowerEstimationPlan(stats.getConfig());
+            if (mStatsLayout.getEnergyConsumerCount() != 0) {
+                initEnergyConsumerToPowerBracketMaps();
+            }
+        }
+
+        Intermediates intermediates = new Intermediates();
+
+        int cpuScalingStepCount = mStatsLayout.getCpuScalingStepCount();
+        if (cpuScalingStepCount != mCpuScalingStepCount) {
+            Log.e(TAG, "Mismatched CPU scaling step count in PowerStats: " + cpuScalingStepCount
+                       + ", expected: " + mCpuScalingStepCount);
+            return;
+        }
+
+        int clusterCount = mStatsLayout.getCpuClusterCount();
+        if (clusterCount != mCpuClusterCount) {
+            Log.e(TAG, "Mismatched CPU cluster count in PowerStats: " + clusterCount
+                       + ", expected: " + mCpuClusterCount);
+            return;
+        }
+
+        computeTotals(stats, intermediates);
+        if (intermediates.cumulativeTime == 0) {
+            return;
+        }
+
+        estimatePowerByScalingStep(intermediates);
+        estimatePowerByDeviceState(stats, intermediates);
+        combineDeviceStateEstimates();
+
+        ArrayList<Integer> uids = new ArrayList<>();
+        stats.collectUids(uids);
+        if (!uids.isEmpty()) {
+            for (int uid : uids) {
+                for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+                    estimateUidPowerConsumption(stats, uid, mPlan.uidStateEstimates.get(i));
+                }
+            }
+        }
+        mPlan.resetIntermediates();
+    }
+
+    /*
+     * Populate data structures (two maps) needed to use power rail data, aka energy consumers,
+     * to attribute power usage to apps.
+     *
+     * At this point, the algorithm covers only the most basic cases:
+     * - Each cluster is mapped to unique power brackets (possibly multiple for each cluster):
+     *          CL_0: [bracket0, bracket1]
+     *          CL_1: [bracket3]
+     *      In this case, the consumed energy is distributed  to the corresponding brackets
+     *      proportionally.
+     * - Brackets span multiple clusters:
+     *          CL_0: [bracket0, bracket1]
+     *          CL_1: [bracket1, bracket2]
+     *          CL_2: [bracket3, bracket4]
+     *      In this case, we combine energy consumers into groups unambiguously mapped to
+     *      brackets. In the above example, consumed energy for CL_0 and CL_1 will be combined
+     *      because they both map to the same power bracket (bracket1):
+     *          (CL_0+CL_1): [bracket0, bracket1, bracket2]
+     *          CL_2: [bracket3, bracket4]
+     */
+    private void initEnergyConsumerToPowerBracketMaps() {
+        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
+        int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
+
+        mEnergyConsumerToCombinedEnergyConsumerMap = new int[energyConsumerCount];
+        mCombinedEnergyConsumerToPowerBracketMap = new int[energyConsumerCount][];
+
+        int[] policies = mCpuScalingPolicies.getPolicies();
+        if (energyConsumerCount == policies.length) {
+            int[] scalingStepToPowerBracketMap = mStatsLayout.getScalingStepToPowerBracketMap();
+            ArraySet<Integer>[] clusterToBrackets = new ArraySet[policies.length];
+            int step = 0;
+            for (int cluster = 0; cluster < policies.length; cluster++) {
+                int[] freqs = mCpuScalingPolicies.getFrequencies(policies[cluster]);
+                clusterToBrackets[cluster] = new ArraySet<>(freqs.length);
+                for (int j = 0; j < freqs.length; j++) {
+                    clusterToBrackets[cluster].add(scalingStepToPowerBracketMap[step++]);
+                }
+            }
+
+            ArraySet<Integer>[] combinedEnergyConsumers = new ArraySet[policies.length];
+            int combinedEnergyConsumersCount = 0;
+
+            for (int cluster = 0; cluster < clusterToBrackets.length; cluster++) {
+                int combineWith = UNKNOWN;
+                for (int i = 0; i < combinedEnergyConsumersCount; i++) {
+                    if (containsAny(combinedEnergyConsumers[i], clusterToBrackets[cluster])) {
+                        combineWith = i;
+                        break;
+                    }
+                }
+                if (combineWith != UNKNOWN) {
+                    mEnergyConsumerToCombinedEnergyConsumerMap[cluster] = combineWith;
+                    combinedEnergyConsumers[combineWith].addAll(clusterToBrackets[cluster]);
+                } else {
+                    mEnergyConsumerToCombinedEnergyConsumerMap[cluster] =
+                            combinedEnergyConsumersCount;
+                    combinedEnergyConsumers[combinedEnergyConsumersCount++] =
+                            clusterToBrackets[cluster];
+                }
+            }
+
+            for (int i = combinedEnergyConsumers.length - 1; i >= 0; i--) {
+                mCombinedEnergyConsumerToPowerBracketMap[i] =
+                        new int[combinedEnergyConsumers[i].size()];
+                for (int j = combinedEnergyConsumers[i].size() - 1; j >= 0; j--) {
+                    mCombinedEnergyConsumerToPowerBracketMap[i][j] =
+                            combinedEnergyConsumers[i].valueAt(j);
+                }
+            }
+        } else {
+            // All CPU cluster energy consumers are combined into one, which is
+            // distributed proportionally to all power brackets.
+            int[] map = new int[powerBracketCount];
+            for (int i = 0; i < map.length; i++) {
+                map[i] = i;
+            }
+            mCombinedEnergyConsumerToPowerBracketMap[0] = map;
+        }
+    }
+
+    private static boolean containsAny(ArraySet<Integer> set1, ArraySet<Integer> set2) {
+        for (int i = 0; i < set2.size(); i++) {
+            if (set1.contains(set2.valueAt(i))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void computeTotals(PowerComponentAggregatedPowerStats stats,
+            Intermediates intermediates) {
+        intermediates.timeByScalingStep = new long[mCpuScalingStepCount];
+        intermediates.timeByCluster = new long[mCpuClusterCount];
+        intermediates.cumulativeTimeByCluster = new long[mCpuClusterCount];
+
+        List<DeviceStateEstimation> deviceStateEstimations = mPlan.deviceStateEstimations;
+        for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) {
+            DeviceStateEstimation deviceStateEstimation = deviceStateEstimations.get(i);
+            if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStateEstimation.stateValues)) {
+                continue;
+            }
+
+            intermediates.uptime += mStatsLayout.getUsageDuration(mTmpDeviceStatsArray);
+
+            for (int cluster = 0; cluster < mCpuClusterCount; cluster++) {
+                intermediates.timeByCluster[cluster] +=
+                        mStatsLayout.getTimeByCluster(mTmpDeviceStatsArray, cluster);
+            }
+
+            for (int step = 0; step < mCpuScalingStepCount; step++) {
+                long timeInStep = mStatsLayout.getTimeByScalingStep(mTmpDeviceStatsArray, step);
+                intermediates.cumulativeTime += timeInStep;
+                intermediates.timeByScalingStep[step] += timeInStep;
+                intermediates.cumulativeTimeByCluster[mScalingStepToCluster[step]] += timeInStep;
+            }
+        }
+    }
+
+    private void estimatePowerByScalingStep(Intermediates intermediates) {
+        // CPU consumes some power when it's on - no matter which cores are running.
+        double cpuActivePower = mPowerMultiplierForCpuActive * intermediates.uptime;
+
+        // Additionally, every cluster consumes some power when any of its cores are running
+        intermediates.powerByCluster = new double[mCpuClusterCount];
+        for (int cluster = 0; cluster < mCpuClusterCount; cluster++) {
+            intermediates.powerByCluster[cluster] =
+                    mPowerMultipliersByCluster[cluster] * intermediates.timeByCluster[cluster];
+        }
+
+        // Finally, additional power is consumed depending on the frequency scaling
+        intermediates.powerByScalingStep = new double[mCpuScalingStepCount];
+        for (int step = 0; step < mCpuScalingStepCount; step++) {
+            int cluster = mScalingStepToCluster[step];
+
+            double power;
+
+            // Distribute base power proportionally
+            power = cpuActivePower * intermediates.timeByScalingStep[step]
+                    / intermediates.cumulativeTime;
+
+            // Distribute per-cluster power proportionally
+            long cumulativeTimeInCluster = intermediates.cumulativeTimeByCluster[cluster];
+            if (cumulativeTimeInCluster != 0) {
+                power += intermediates.powerByCluster[cluster]
+                         * intermediates.timeByScalingStep[step]
+                         / cumulativeTimeInCluster;
+            }
+
+            power += mPowerMultipliersByScalingStep[step] * intermediates.timeByScalingStep[step];
+
+            intermediates.powerByScalingStep[step] = power;
+        }
+    }
+
+    private void estimatePowerByDeviceState(PowerComponentAggregatedPowerStats stats,
+            Intermediates intermediates) {
+        int cpuScalingStepCount = mStatsLayout.getCpuScalingStepCount();
+        int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
+        int[] scalingStepToBracketMap = mStatsLayout.getScalingStepToPowerBracketMap();
+        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
+        List<DeviceStateEstimation> deviceStateEstimations = mPlan.deviceStateEstimations;
+        for (int dse = deviceStateEstimations.size() - 1; dse >= 0; dse--) {
+            DeviceStateEstimation deviceStateEstimation = deviceStateEstimations.get(dse);
+            deviceStateEstimation.intermediates = new DeviceStatsIntermediates();
+            DeviceStatsIntermediates deviceStatsIntermediates =
+                    (DeviceStatsIntermediates) deviceStateEstimation.intermediates;
+            deviceStatsIntermediates.timeByBracket = new long[powerBracketCount];
+            deviceStatsIntermediates.powerByBracket = new double[powerBracketCount];
+
+            stats.getDeviceStats(mTmpDeviceStatsArray, deviceStateEstimation.stateValues);
+            for (int step = 0; step < cpuScalingStepCount; step++) {
+                if (intermediates.timeByScalingStep[step] == 0) {
+                    continue;
+                }
+
+                long timeInStep = mStatsLayout.getTimeByScalingStep(mTmpDeviceStatsArray, step);
+                double stepPower = intermediates.powerByScalingStep[step] * timeInStep
+                                   / intermediates.timeByScalingStep[step];
+
+                int bracket = scalingStepToBracketMap[step];
+                deviceStatsIntermediates.timeByBracket[bracket] += timeInStep;
+                deviceStatsIntermediates.powerByBracket[bracket] += stepPower;
+            }
+
+            if (energyConsumerCount != 0) {
+                adjustEstimatesUsingEnergyConsumers(intermediates, deviceStatsIntermediates);
+            }
+
+            double power = 0;
+            for (int i = deviceStatsIntermediates.powerByBracket.length - 1; i >= 0; i--) {
+                power += deviceStatsIntermediates.powerByBracket[i];
+            }
+            deviceStatsIntermediates.power = power;
+            mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, power);
+            stats.setDeviceStats(deviceStateEstimation.stateValues, mTmpDeviceStatsArray);
+        }
+    }
+
+    private void adjustEstimatesUsingEnergyConsumers(
+            Intermediates intermediates, DeviceStatsIntermediates deviceStatsIntermediates) {
+        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
+        if (energyConsumerCount == 0) {
+            return;
+        }
+
+        if (intermediates.powerByEnergyConsumer == null) {
+            intermediates.powerByEnergyConsumer = new long[energyConsumerCount];
+        } else {
+            Arrays.fill(intermediates.powerByEnergyConsumer, 0);
+        }
+        for (int i = 0; i < energyConsumerCount; i++) {
+            intermediates.powerByEnergyConsumer[mEnergyConsumerToCombinedEnergyConsumerMap[i]] +=
+                    mStatsLayout.getConsumedEnergy(mTmpDeviceStatsArray, i);
+        }
+
+        for (int combinedConsumer = mCombinedEnergyConsumerToPowerBracketMap.length - 1;
+                combinedConsumer >= 0; combinedConsumer--) {
+            int[] combinedEnergyConsumerToPowerBracketMap =
+                    mCombinedEnergyConsumerToPowerBracketMap[combinedConsumer];
+            if (combinedEnergyConsumerToPowerBracketMap == null) {
+                continue;
+            }
+
+            double consumedEnergy = uCtoMah(intermediates.powerByEnergyConsumer[combinedConsumer]);
+
+            double totalModeledPower = 0;
+            for (int bracket : combinedEnergyConsumerToPowerBracketMap) {
+                totalModeledPower += deviceStatsIntermediates.powerByBracket[bracket];
+            }
+            if (totalModeledPower == 0) {
+                continue;
+            }
+
+            for (int bracket : combinedEnergyConsumerToPowerBracketMap) {
+                deviceStatsIntermediates.powerByBracket[bracket] =
+                        consumedEnergy * deviceStatsIntermediates.powerByBracket[bracket]
+                        / totalModeledPower;
+            }
+        }
+    }
+
+    private void combineDeviceStateEstimates() {
+        for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
+            CombinedDeviceStateEstimate cdse = mPlan.combinedDeviceStateEstimations.get(i);
+            DeviceStatsIntermediates cdseIntermediates = new DeviceStatsIntermediates();
+            cdse.intermediates = cdseIntermediates;
+            int bracketCount = mStatsLayout.getCpuPowerBracketCount();
+            cdseIntermediates.timeByBracket = new long[bracketCount];
+            cdseIntermediates.powerByBracket = new double[bracketCount];
+            List<DeviceStateEstimation> deviceStateEstimations = cdse.deviceStateEstimations;
+            for (int j = deviceStateEstimations.size() - 1; j >= 0; j--) {
+                DeviceStateEstimation dse = deviceStateEstimations.get(j);
+                DeviceStatsIntermediates intermediates =
+                        (DeviceStatsIntermediates) dse.intermediates;
+                cdseIntermediates.power += intermediates.power;
+                for (int k = 0; k < bracketCount; k++) {
+                    cdseIntermediates.timeByBracket[k] += intermediates.timeByBracket[k];
+                    cdseIntermediates.powerByBracket[k] += intermediates.powerByBracket[k];
+                }
+            }
+        }
+    }
+
+    private void estimateUidPowerConsumption(PowerComponentAggregatedPowerStats stats, int uid,
+            UidStateEstimate uidStateEstimate) {
+        CombinedDeviceStateEstimate combinedDeviceStateEstimate =
+                uidStateEstimate.combinedDeviceStateEstimate;
+        DeviceStatsIntermediates cdsIntermediates =
+                (DeviceStatsIntermediates) combinedDeviceStateEstimate.intermediates;
+        for (int i = 0; i < uidStateEstimate.proportionalEstimates.size(); i++) {
+            UidStateProportionalEstimate proportionalEstimate =
+                    uidStateEstimate.proportionalEstimates.get(i);
+            if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+                continue;
+            }
+
+            double power = 0;
+            for (int bracket = 0; bracket < mStatsLayout.getCpuPowerBracketCount(); bracket++) {
+                if (cdsIntermediates.timeByBracket[bracket] == 0) {
+                    continue;
+                }
+
+                long timeInBracket = mStatsLayout.getUidTimeByPowerBracket(mTmpUidStatsArray,
+                        bracket);
+                if (timeInBracket == 0) {
+                    continue;
+                }
+
+                power += cdsIntermediates.powerByBracket[bracket] * timeInBracket
+                            / cdsIntermediates.timeByBracket[bracket];
+            }
+
+            mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+            stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+        }
+    }
+
+    @Override
+    public String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        StringBuilder sb = new StringBuilder();
+        int cpuScalingStepCount = mStatsLayout.getCpuScalingStepCount();
+        sb.append("steps: [");
+        for (int step = 0; step < cpuScalingStepCount; step++) {
+            if (step != 0) {
+                sb.append(", ");
+            }
+            sb.append(mStatsLayout.getTimeByScalingStep(stats, step));
+        }
+        int clusterCount = mStatsLayout.getCpuClusterCount();
+        sb.append("] clusters: [");
+        for (int cluster = 0; cluster < clusterCount; cluster++) {
+            if (cluster != 0) {
+                sb.append(", ");
+            }
+            sb.append(mStatsLayout.getTimeByCluster(stats, cluster));
+        }
+        sb.append("] uptime: ").append(mStatsLayout.getUsageDuration(stats));
+        int energyConsumerCount = mStatsLayout.getEnergyConsumerCount();
+        if (energyConsumerCount > 0) {
+            sb.append(" energy: [");
+            for (int i = 0; i < energyConsumerCount; i++) {
+                if (i != 0) {
+                    sb.append(", ");
+                }
+                sb.append(mStatsLayout.getConsumedEnergy(stats, i));
+            }
+            sb.append("]");
+        }
+        sb.append(" power: ").append(
+                BatteryStats.formatCharge(mStatsLayout.getDevicePowerEstimate(stats)));
+        return sb.toString();
+    }
+
+    @Override
+    String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats) {
+        // Unsupported for this power component
+        return null;
+    }
+
+    @Override
+    public String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        int powerBracketCount = mStatsLayout.getCpuPowerBracketCount();
+        for (int bracket = 0; bracket < powerBracketCount; bracket++) {
+            if (bracket != 0) {
+                sb.append(", ");
+            }
+            sb.append(mStatsLayout.getUidTimeByPowerBracket(stats, bracket));
+        }
+        sb.append("] power: ").append(
+                BatteryStats.formatCharge(mStatsLayout.getUidPowerEstimate(stats)));
+        return sb.toString();
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
index 9ea143e..c01363a9 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
@@ -387,92 +387,14 @@
         return consumptionMah;
     }
 
-    private static long buildModemPowerProfileKey(@ModemPowerProfile.ModemDrainType int drainType,
-            @BatteryStats.RadioAccessTechnology int rat, @ServiceState.FrequencyRange int freqRange,
-            int txLevel) {
-        long key = PowerProfile.SUBSYSTEM_MODEM;
-
-        // Attach Modem drain type to the key if specified.
-        if (drainType != IGNORE) {
-            key |= drainType;
-        }
-
-        // Attach RadioAccessTechnology to the key if specified.
-        switch (rat) {
-            case IGNORE:
-                // do nothing
-                break;
-            case BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER:
-                key |= ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT;
-                break;
-            case BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE:
-                key |= ModemPowerProfile.MODEM_RAT_TYPE_LTE;
-                break;
-            case BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR:
-                key |= ModemPowerProfile.MODEM_RAT_TYPE_NR;
-                break;
-            default:
-                Log.w(TAG, "Unexpected RadioAccessTechnology : " + rat);
-        }
-
-        // Attach NR Frequency Range to the key if specified.
-        switch (freqRange) {
-            case IGNORE:
-                // do nothing
-                break;
-            case ServiceState.FREQUENCY_RANGE_UNKNOWN:
-                key |= ModemPowerProfile.MODEM_NR_FREQUENCY_RANGE_DEFAULT;
-                break;
-            case ServiceState.FREQUENCY_RANGE_LOW:
-                key |= ModemPowerProfile.MODEM_NR_FREQUENCY_RANGE_LOW;
-                break;
-            case ServiceState.FREQUENCY_RANGE_MID:
-                key |= ModemPowerProfile.MODEM_NR_FREQUENCY_RANGE_MID;
-                break;
-            case ServiceState.FREQUENCY_RANGE_HIGH:
-                key |= ModemPowerProfile.MODEM_NR_FREQUENCY_RANGE_HIGH;
-                break;
-            case ServiceState.FREQUENCY_RANGE_MMWAVE:
-                key |= ModemPowerProfile.MODEM_NR_FREQUENCY_RANGE_MMWAVE;
-                break;
-            default:
-                Log.w(TAG, "Unexpected NR frequency range : " + freqRange);
-        }
-
-        // Attach transmission level to the key if specified.
-        switch (txLevel) {
-            case IGNORE:
-                // do nothing
-                break;
-            case 0:
-                key |= ModemPowerProfile.MODEM_TX_LEVEL_0;
-                break;
-            case 1:
-                key |= ModemPowerProfile.MODEM_TX_LEVEL_1;
-                break;
-            case 2:
-                key |= ModemPowerProfile.MODEM_TX_LEVEL_2;
-                break;
-            case 3:
-                key |= ModemPowerProfile.MODEM_TX_LEVEL_3;
-                break;
-            case 4:
-                key |= ModemPowerProfile.MODEM_TX_LEVEL_4;
-                break;
-            default:
-                Log.w(TAG, "Unexpected transmission level : " + txLevel);
-        }
-        return key;
-    }
-
     /**
      * Calculates active receive radio power consumption (in milliamp-hours) from the given state's
      * duration.
      */
     public double calcRxStatePowerMah(@BatteryStats.RadioAccessTechnology int rat,
             @ServiceState.FrequencyRange int freqRange, long rxDurationMs) {
-        final long rxKey = buildModemPowerProfileKey(ModemPowerProfile.MODEM_DRAIN_TYPE_RX, rat,
-                freqRange, IGNORE);
+        final long rxKey = ModemPowerProfile.getAverageBatteryDrainKey(
+                ModemPowerProfile.MODEM_DRAIN_TYPE_RX, rat, freqRange, IGNORE);
         final double drainRateMa = mPowerProfile.getAverageBatteryDrainOrDefaultMa(rxKey,
                 Double.NaN);
         if (Double.isNaN(drainRateMa)) {
@@ -495,8 +417,8 @@
      */
     public double calcTxStatePowerMah(@BatteryStats.RadioAccessTechnology int rat,
             @ServiceState.FrequencyRange int freqRange, int txLevel, long txDurationMs) {
-        final long txKey = buildModemPowerProfileKey(ModemPowerProfile.MODEM_DRAIN_TYPE_TX, rat,
-                freqRange, txLevel);
+        final long txKey = ModemPowerProfile.getAverageBatteryDrainKey(
+                ModemPowerProfile.MODEM_DRAIN_TYPE_TX, rat, freqRange, txLevel);
         final double drainRateMa = mPowerProfile.getAverageBatteryDrainOrDefaultMa(txKey,
                 Double.NaN);
         if (Double.isNaN(drainRateMa)) {
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
new file mode 100644
index 0000000..7bc68175
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.os.BatteryConsumer;
+import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.OutcomeReceiver;
+import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.ModemActivityInfo;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
+
+public class MobileRadioPowerStatsCollector extends PowerStatsCollector {
+    private static final String TAG = "MobileRadioPowerStatsCollector";
+
+    /**
+     * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
+     * after it was last updated.
+     */
+    @VisibleForTesting
+    protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
+
+    private static final long MODEM_ACTIVITY_REQUEST_TIMEOUT = 20000;
+
+    private static final long ENERGY_UNSPECIFIED = -1;
+
+    @VisibleForTesting
+    @AccessNetworkConstants.RadioAccessNetworkType
+    static final int[] NETWORK_TYPES = {
+            AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+            AccessNetworkConstants.AccessNetworkType.GERAN,
+            AccessNetworkConstants.AccessNetworkType.UTRAN,
+            AccessNetworkConstants.AccessNetworkType.EUTRAN,
+            AccessNetworkConstants.AccessNetworkType.CDMA2000,
+            AccessNetworkConstants.AccessNetworkType.IWLAN,
+            AccessNetworkConstants.AccessNetworkType.NGRAN
+    };
+
+    interface Injector {
+        Handler getHandler();
+        Clock getClock();
+        PowerStatsUidResolver getUidResolver();
+        PackageManager getPackageManager();
+        ConsumedEnergyRetriever getConsumedEnergyRetriever();
+        IntSupplier getVoltageSupplier();
+        Supplier<NetworkStats> getMobileNetworkStatsSupplier();
+        TelephonyManager getTelephonyManager();
+        LongSupplier getCallDurationSupplier();
+        LongSupplier getPhoneSignalScanDurationSupplier();
+    }
+
+    private final Injector mInjector;
+
+    private MobileRadioPowerStatsLayout mLayout;
+    private boolean mIsInitialized;
+
+    private PowerStats mPowerStats;
+    private long[] mDeviceStats;
+    private volatile TelephonyManager mTelephonyManager;
+    private LongSupplier mCallDurationSupplier;
+    private LongSupplier mScanDurationSupplier;
+    private volatile Supplier<NetworkStats> mNetworkStatsSupplier;
+    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    private IntSupplier mVoltageSupplier;
+    private int[] mEnergyConsumerIds = new int[0];
+    private long mLastUpdateTimestampMillis;
+    private ModemActivityInfo mLastModemActivityInfo;
+    private NetworkStats mLastNetworkStats;
+    private long[] mLastConsumedEnergyUws;
+    private int mLastVoltageMv;
+    private long mLastCallDuration;
+    private long mLastScanDuration;
+
+    public MobileRadioPowerStatsCollector(Injector injector, long throttlePeriodMs) {
+        super(injector.getHandler(), throttlePeriodMs, injector.getUidResolver(),
+                injector.getClock());
+        mInjector = injector;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (enabled) {
+            PackageManager packageManager = mInjector.getPackageManager();
+            super.setEnabled(packageManager != null
+                    && packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+        } else {
+            super.setEnabled(false);
+        }
+    }
+
+    private boolean ensureInitialized() {
+        if (mIsInitialized) {
+            return true;
+        }
+
+        if (!isEnabled()) {
+            return false;
+        }
+
+        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
+        mVoltageSupplier = mInjector.getVoltageSupplier();
+
+        mTelephonyManager = mInjector.getTelephonyManager();
+        mNetworkStatsSupplier = mInjector.getMobileNetworkStatsSupplier();
+        mCallDurationSupplier = mInjector.getCallDurationSupplier();
+        mScanDurationSupplier = mInjector.getPhoneSignalScanDurationSupplier();
+
+        mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
+                EnergyConsumerType.MOBILE_RADIO);
+        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
+        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+
+        mLayout = new MobileRadioPowerStatsLayout();
+        mLayout.addDeviceMobileActivity();
+        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
+        mLayout.addStateStats();
+        mLayout.addUidNetworkStats();
+        mLayout.addDeviceSectionUsageDuration();
+        mLayout.addDeviceSectionPowerEstimate();
+        mLayout.addUidSectionPowerEstimate();
+
+        SparseArray<String> stateLabels = new SparseArray<>();
+        for (int rat = 0; rat < BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+            final int freqCount = rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR
+                    ? ServiceState.FREQUENCY_RANGE_COUNT : 1;
+            for (int freq = 0; freq < freqCount; freq++) {
+                int stateKey = makeStateKey(rat, freq);
+                StringBuilder sb = new StringBuilder();
+                if (rat != BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER) {
+                    sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+                }
+                if (freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                    if (!sb.isEmpty()) {
+                        sb.append(" ");
+                    }
+                    sb.append(ServiceState.frequencyRangeToString(freq));
+                }
+                stateLabels.put(stateKey, !sb.isEmpty() ? sb.toString() : "other");
+            }
+        }
+
+        PersistableBundle extras = new PersistableBundle();
+        mLayout.toExtras(extras);
+        PowerStats.Descriptor powerStatsDescriptor = new PowerStats.Descriptor(
+                BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, mLayout.getDeviceStatsArrayLength(),
+                stateLabels, mLayout.getStateStatsArrayLength(), mLayout.getUidStatsArrayLength(),
+                extras);
+        mPowerStats = new PowerStats(powerStatsDescriptor);
+        mDeviceStats = mPowerStats.stats;
+
+        mIsInitialized = true;
+        return true;
+    }
+
+    @Override
+    protected PowerStats collectStats() {
+        if (!ensureInitialized()) {
+            return null;
+        }
+
+        collectModemActivityInfo();
+
+        collectNetworkStats();
+
+        if (mEnergyConsumerIds.length != 0) {
+            collectEnergyConsumers();
+        }
+
+        if (mPowerStats.durationMs == 0) {
+            setTimestamp(mClock.elapsedRealtime());
+        }
+
+        return mPowerStats;
+    }
+
+    private void collectModemActivityInfo() {
+        if (mTelephonyManager == null) {
+            return;
+        }
+
+        CompletableFuture<ModemActivityInfo> immediateFuture = new CompletableFuture<>();
+        mTelephonyManager.requestModemActivityInfo(Runnable::run,
+                new OutcomeReceiver<>() {
+                    @Override
+                    public void onResult(ModemActivityInfo result) {
+                        immediateFuture.complete(result);
+                    }
+
+                    @Override
+                    public void onError(TelephonyManager.ModemActivityInfoException e) {
+                        Slog.w(TAG, "error reading modem stats:" + e);
+                        immediateFuture.complete(null);
+                    }
+                });
+
+        ModemActivityInfo activityInfo;
+        try {
+            activityInfo = immediateFuture.get(MODEM_ACTIVITY_REQUEST_TIMEOUT,
+                    TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            Slog.e(TAG, "Cannot acquire ModemActivityInfo");
+            activityInfo = null;
+        }
+
+        ModemActivityInfo deltaInfo = mLastModemActivityInfo == null
+                ? (activityInfo == null ? null : activityInfo.getDelta(activityInfo))
+                : mLastModemActivityInfo.getDelta(activityInfo);
+
+        mLastModemActivityInfo = activityInfo;
+
+        if (deltaInfo == null) {
+            return;
+        }
+
+        setTimestamp(deltaInfo.getTimestampMillis());
+        mLayout.setDeviceSleepTime(mDeviceStats, deltaInfo.getSleepTimeMillis());
+        mLayout.setDeviceIdleTime(mDeviceStats, deltaInfo.getIdleTimeMillis());
+
+        long callDuration = mCallDurationSupplier.getAsLong();
+        if (callDuration >= mLastCallDuration) {
+            mLayout.setDeviceCallTime(mDeviceStats, callDuration - mLastCallDuration);
+        }
+        mLastCallDuration = callDuration;
+
+        long scanDuration = mScanDurationSupplier.getAsLong();
+        if (scanDuration >= mLastScanDuration) {
+            mLayout.setDeviceScanTime(mDeviceStats, scanDuration - mLastScanDuration);
+        }
+        mLastScanDuration = scanDuration;
+
+        SparseArray<long[]> stateStats = mPowerStats.stateStats;
+        stateStats.clear();
+
+        if (deltaInfo.getSpecificInfoLength() == 0) {
+            mLayout.addRxTxTimesForRat(stateStats,
+                    AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+                    ServiceState.FREQUENCY_RANGE_UNKNOWN,
+                    deltaInfo.getReceiveTimeMillis(),
+                    deltaInfo.getTransmitTimeMillis());
+        } else {
+            for (int rat = 0; rat < NETWORK_TYPES.length; rat++) {
+                if (rat == AccessNetworkConstants.AccessNetworkType.NGRAN) {
+                    for (int freq = 0; freq < ServiceState.FREQUENCY_RANGE_COUNT; freq++) {
+                        mLayout.addRxTxTimesForRat(stateStats, rat, freq,
+                                deltaInfo.getReceiveTimeMillis(rat, freq),
+                                deltaInfo.getTransmitTimeMillis(rat, freq));
+                    }
+                } else {
+                    mLayout.addRxTxTimesForRat(stateStats, rat,
+                            ServiceState.FREQUENCY_RANGE_UNKNOWN,
+                            deltaInfo.getReceiveTimeMillis(rat),
+                            deltaInfo.getTransmitTimeMillis(rat));
+                }
+            }
+        }
+    }
+
+    private void collectNetworkStats() {
+        mPowerStats.uidStats.clear();
+
+        NetworkStats networkStats = mNetworkStatsSupplier.get();
+        if (networkStats == null) {
+            return;
+        }
+
+        List<BatteryStatsImpl.NetworkStatsDelta> delta =
+                BatteryStatsImpl.computeDelta(networkStats, mLastNetworkStats);
+        mLastNetworkStats = networkStats;
+        for (int i = delta.size() - 1; i >= 0; i--) {
+            BatteryStatsImpl.NetworkStatsDelta uidDelta = delta.get(i);
+            long rxBytes = uidDelta.getRxBytes();
+            long txBytes = uidDelta.getTxBytes();
+            long rxPackets = uidDelta.getRxPackets();
+            long txPackets = uidDelta.getTxPackets();
+            if (rxBytes == 0 && txBytes == 0 && rxPackets == 0 && txPackets == 0) {
+                continue;
+            }
+
+            int uid = mUidResolver.mapUid(uidDelta.getUid());
+            long[] stats = mPowerStats.uidStats.get(uid);
+            if (stats == null) {
+                stats = new long[mLayout.getUidStatsArrayLength()];
+                mPowerStats.uidStats.put(uid, stats);
+                mLayout.setUidRxBytes(stats, rxBytes);
+                mLayout.setUidTxBytes(stats, txBytes);
+                mLayout.setUidRxPackets(stats, rxPackets);
+                mLayout.setUidTxPackets(stats, txPackets);
+            } else {
+                mLayout.setUidRxBytes(stats, mLayout.getUidRxBytes(stats) + rxBytes);
+                mLayout.setUidTxBytes(stats, mLayout.getUidTxBytes(stats) + txBytes);
+                mLayout.setUidRxPackets(stats, mLayout.getUidRxPackets(stats) + rxPackets);
+                mLayout.setUidTxPackets(stats, mLayout.getUidTxPackets(stats) + txPackets);
+            }
+        }
+    }
+
+    private void collectEnergyConsumers() {
+        int voltageMv = mVoltageSupplier.getAsInt();
+        if (voltageMv <= 0) {
+            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
+                    + " mV) when querying energy consumers");
+            return;
+        }
+
+        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
+        mLastVoltageMv = voltageMv;
+
+        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
+        if (energyUws == null) {
+            return;
+        }
+
+        for (int i = energyUws.length - 1; i >= 0; i--) {
+            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
+                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
+            if (energyDelta < 0) {
+                // Likely, restart of powerstats HAL
+                energyDelta = 0;
+            }
+            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
+            mLastConsumedEnergyUws[i] = energyUws[i];
+        }
+    }
+
+    static int makeStateKey(int rat, int freqRange) {
+        if (rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR) {
+            return rat | (freqRange << 8);
+        } else {
+            return rat;
+        }
+    }
+
+    private void setTimestamp(long timestamp) {
+        mPowerStats.durationMs = Math.max(timestamp - mLastUpdateTimestampMillis, 0);
+        mLastUpdateTimestampMillis = timestamp;
+    }
+
+    @BatteryStats.RadioAccessTechnology
+    static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
+            @AccessNetworkConstants.RadioAccessNetworkType int networkType) {
+        switch (networkType) {
+            case AccessNetworkConstants.AccessNetworkType.NGRAN:
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
+            case AccessNetworkConstants.AccessNetworkType.EUTRAN:
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE;
+            case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.IWLAN:
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+            default:
+                Slog.w(TAG,
+                        "Unhandled RadioAccessNetworkType (" + networkType + "), mapping to OTHER");
+                return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java
new file mode 100644
index 0000000..81d7c2f
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+import android.telephony.ModemActivityInfo;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.os.PowerStats;
+
+/**
+ * Captures the positions and lengths of sections of the stats array, such as time-in-state,
+ * power usage estimates etc.
+ */
+class MobileRadioPowerStatsLayout extends PowerStatsLayout {
+    private static final String TAG = "MobileRadioPowerStatsLayout";
+    private static final String EXTRA_DEVICE_SLEEP_TIME_POSITION = "dt-sleep";
+    private static final String EXTRA_DEVICE_IDLE_TIME_POSITION = "dt-idle";
+    private static final String EXTRA_DEVICE_SCAN_TIME_POSITION = "dt-scan";
+    private static final String EXTRA_DEVICE_CALL_TIME_POSITION = "dt-call";
+    private static final String EXTRA_DEVICE_CALL_POWER_POSITION = "dp-call";
+    private static final String EXTRA_STATE_RX_TIME_POSITION = "srx";
+    private static final String EXTRA_STATE_TX_TIMES_POSITION = "stx";
+    private static final String EXTRA_STATE_TX_TIMES_COUNT = "stxc";
+    private static final String EXTRA_UID_RX_BYTES_POSITION = "urxb";
+    private static final String EXTRA_UID_TX_BYTES_POSITION = "utxb";
+    private static final String EXTRA_UID_RX_PACKETS_POSITION = "urxp";
+    private static final String EXTRA_UID_TX_PACKETS_POSITION = "utxp";
+
+    private int mDeviceSleepTimePosition;
+    private int mDeviceIdleTimePosition;
+    private int mDeviceScanTimePosition;
+    private int mDeviceCallTimePosition;
+    private int mDeviceCallPowerPosition;
+    private int mStateRxTimePosition;
+    private int mStateTxTimesPosition;
+    private int mStateTxTimesCount;
+    private int mUidRxBytesPosition;
+    private int mUidTxBytesPosition;
+    private int mUidRxPacketsPosition;
+    private int mUidTxPacketsPosition;
+
+    MobileRadioPowerStatsLayout() {
+    }
+
+    MobileRadioPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+        super(descriptor);
+    }
+
+    void addDeviceMobileActivity() {
+        mDeviceSleepTimePosition = addDeviceSection(1);
+        mDeviceIdleTimePosition = addDeviceSection(1);
+        mDeviceScanTimePosition = addDeviceSection(1);
+        mDeviceCallTimePosition = addDeviceSection(1);
+    }
+
+    void addStateStats() {
+        mStateRxTimePosition = addStateSection(1);
+        mStateTxTimesCount = ModemActivityInfo.getNumTxPowerLevels();
+        mStateTxTimesPosition = addStateSection(mStateTxTimesCount);
+    }
+
+    void addUidNetworkStats() {
+        mUidRxBytesPosition = addUidSection(1);
+        mUidTxBytesPosition = addUidSection(1);
+        mUidRxPacketsPosition = addUidSection(1);
+        mUidTxPacketsPosition = addUidSection(1);
+    }
+
+    @Override
+    public void addDeviceSectionPowerEstimate() {
+        super.addDeviceSectionPowerEstimate();
+        mDeviceCallPowerPosition = addDeviceSection(1);
+    }
+
+    public void setDeviceSleepTime(long[] stats, long durationMillis) {
+        stats[mDeviceSleepTimePosition] = durationMillis;
+    }
+
+    public long getDeviceSleepTime(long[] stats) {
+        return stats[mDeviceSleepTimePosition];
+    }
+
+    public void setDeviceIdleTime(long[] stats, long durationMillis) {
+        stats[mDeviceIdleTimePosition] = durationMillis;
+    }
+
+    public long getDeviceIdleTime(long[] stats) {
+        return stats[mDeviceIdleTimePosition];
+    }
+
+    public void setDeviceScanTime(long[] stats, long durationMillis) {
+        stats[mDeviceScanTimePosition] = durationMillis;
+    }
+
+    public long getDeviceScanTime(long[] stats) {
+        return stats[mDeviceScanTimePosition];
+    }
+
+    public void setDeviceCallTime(long[] stats, long durationMillis) {
+        stats[mDeviceCallTimePosition] = durationMillis;
+    }
+
+    public long getDeviceCallTime(long[] stats) {
+        return stats[mDeviceCallTimePosition];
+    }
+
+    public void setDeviceCallPowerEstimate(long[] stats, double power) {
+        stats[mDeviceCallPowerPosition] = (long) (power * MILLI_TO_NANO_MULTIPLIER);
+    }
+
+    public double getDeviceCallPowerEstimate(long[] stats) {
+        return stats[mDeviceCallPowerPosition] / MILLI_TO_NANO_MULTIPLIER;
+    }
+
+    public void setStateRxTime(long[] stats, long durationMillis) {
+        stats[mStateRxTimePosition] = durationMillis;
+    }
+
+    public long getStateRxTime(long[] stats) {
+        return stats[mStateRxTimePosition];
+    }
+
+    public void setStateTxTime(long[] stats, int level, int durationMillis) {
+        stats[mStateTxTimesPosition + level] = durationMillis;
+    }
+
+    public long getStateTxTime(long[] stats, int level) {
+        return stats[mStateTxTimesPosition + level];
+    }
+
+    public void setUidRxBytes(long[] stats, long count) {
+        stats[mUidRxBytesPosition] = count;
+    }
+
+    public long getUidRxBytes(long[] stats) {
+        return stats[mUidRxBytesPosition];
+    }
+
+    public void setUidTxBytes(long[] stats, long count) {
+        stats[mUidTxBytesPosition] = count;
+    }
+
+    public long getUidTxBytes(long[] stats) {
+        return stats[mUidTxBytesPosition];
+    }
+
+    public void setUidRxPackets(long[] stats, long count) {
+        stats[mUidRxPacketsPosition] = count;
+    }
+
+    public long getUidRxPackets(long[] stats) {
+        return stats[mUidRxPacketsPosition];
+    }
+
+    public void setUidTxPackets(long[] stats, long count) {
+        stats[mUidTxPacketsPosition] = count;
+    }
+
+    public long getUidTxPackets(long[] stats) {
+        return stats[mUidTxPacketsPosition];
+    }
+
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putInt(EXTRA_DEVICE_SLEEP_TIME_POSITION, mDeviceSleepTimePosition);
+        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_CALL_TIME_POSITION, mDeviceCallTimePosition);
+        extras.putInt(EXTRA_DEVICE_CALL_POWER_POSITION, mDeviceCallPowerPosition);
+        extras.putInt(EXTRA_STATE_RX_TIME_POSITION, mStateRxTimePosition);
+        extras.putInt(EXTRA_STATE_TX_TIMES_POSITION, mStateTxTimesPosition);
+        extras.putInt(EXTRA_STATE_TX_TIMES_COUNT, mStateTxTimesCount);
+        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+        extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
+        extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
+    }
+
+    /**
+     * Retrieves elements of the stats array layout from <code>extras</code>
+     */
+    public void fromExtras(PersistableBundle extras) {
+        super.fromExtras(extras);
+        mDeviceSleepTimePosition = extras.getInt(EXTRA_DEVICE_SLEEP_TIME_POSITION);
+        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+        mDeviceCallTimePosition = extras.getInt(EXTRA_DEVICE_CALL_TIME_POSITION);
+        mDeviceCallPowerPosition = extras.getInt(EXTRA_DEVICE_CALL_POWER_POSITION);
+        mStateRxTimePosition = extras.getInt(EXTRA_STATE_RX_TIME_POSITION);
+        mStateTxTimesPosition = extras.getInt(EXTRA_STATE_TX_TIMES_POSITION);
+        mStateTxTimesCount = extras.getInt(EXTRA_STATE_TX_TIMES_COUNT);
+        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+        mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
+        mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
+    }
+
+    public void addRxTxTimesForRat(SparseArray<long[]> stateStats, int networkType, int freqRange,
+            long rxTime, int[] txTime) {
+        if (txTime.length != mStateTxTimesCount) {
+            Slog.wtf(TAG, "Invalid TX time array size: " + txTime.length);
+            return;
+        }
+
+        boolean nonZero = false;
+        if (rxTime != 0) {
+            nonZero = true;
+        } else {
+            for (int i = txTime.length - 1; i >= 0; i--) {
+                if (txTime[i] != 0) {
+                    nonZero = true;
+                    break;
+                }
+            }
+        }
+
+        if (!nonZero) {
+            return;
+        }
+
+        int rat = MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology(
+                networkType);
+        int stateKey = MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange);
+        long[] stats = stateStats.get(stateKey);
+        if (stats == null) {
+            stats = new long[getStateStatsArrayLength()];
+            stateStats.put(stateKey, stats);
+        }
+
+        stats[mStateRxTimePosition] += rxTime;
+        for (int i = mStateTxTimesCount - 1; i >= 0; i--) {
+            stats[mStateTxTimesPosition + i] += txTime[i];
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java
new file mode 100644
index 0000000..c97c64b
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import android.os.BatteryStats;
+import android.telephony.CellSignalStrength;
+import android.telephony.ModemActivityInfo;
+import android.telephony.ServiceState;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.os.PowerProfile;
+import com.android.internal.os.PowerStats;
+import com.android.internal.power.ModemPowerProfile;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MobileRadioPowerStatsProcessor extends PowerStatsProcessor {
+    private static final String TAG = "MobileRadioPowerStatsProcessor";
+    private static final boolean DEBUG = false;
+
+    private static final int NUM_SIGNAL_STRENGTH_LEVELS =
+            CellSignalStrength.getNumSignalStrengthLevels();
+    private static final int IGNORE = -1;
+
+    private final UsageBasedPowerEstimator mSleepPowerEstimator;
+    private final UsageBasedPowerEstimator mIdlePowerEstimator;
+    private final UsageBasedPowerEstimator mCallPowerEstimator;
+    private final UsageBasedPowerEstimator mScanPowerEstimator;
+
+    private static class RxTxPowerEstimators {
+        UsageBasedPowerEstimator mRxPowerEstimator;
+        UsageBasedPowerEstimator[] mTxPowerEstimators =
+                new UsageBasedPowerEstimator[ModemActivityInfo.getNumTxPowerLevels()];
+    }
+
+    private final SparseArray<RxTxPowerEstimators> mRxTxPowerEstimators = new SparseArray<>();
+
+    private PowerStats.Descriptor mLastUsedDescriptor;
+    private MobileRadioPowerStatsLayout mStatsLayout;
+    // Sequence of steps for power estimation and intermediate results.
+    private PowerEstimationPlan mPlan;
+
+    private long[] mTmpDeviceStatsArray;
+    private long[] mTmpStateStatsArray;
+    private long[] mTmpUidStatsArray;
+
+    public MobileRadioPowerStatsProcessor(PowerProfile powerProfile) {
+        final double sleepDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(
+                PowerProfile.SUBSYSTEM_MODEM | ModemPowerProfile.MODEM_DRAIN_TYPE_SLEEP,
+                Double.NaN);
+        if (Double.isNaN(sleepDrainRateMa)) {
+            mSleepPowerEstimator = null;
+        } else {
+            mSleepPowerEstimator = new UsageBasedPowerEstimator(sleepDrainRateMa);
+        }
+
+        final double idleDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(
+                PowerProfile.SUBSYSTEM_MODEM | ModemPowerProfile.MODEM_DRAIN_TYPE_IDLE,
+                Double.NaN);
+        if (Double.isNaN(idleDrainRateMa)) {
+            mIdlePowerEstimator = null;
+        } else {
+            mIdlePowerEstimator = new UsageBasedPowerEstimator(idleDrainRateMa);
+        }
+
+        // Instantiate legacy power estimators
+        double powerRadioActiveMa =
+                powerProfile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_ACTIVE, Double.NaN);
+        if (Double.isNaN(powerRadioActiveMa)) {
+            double sum = 0;
+            sum += powerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
+            for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
+                sum += powerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
+            }
+            powerRadioActiveMa = sum / (NUM_SIGNAL_STRENGTH_LEVELS + 1);
+        }
+        mCallPowerEstimator = new UsageBasedPowerEstimator(powerRadioActiveMa);
+
+        mScanPowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_SCANNING, 0));
+
+        for (int rat = 0; rat < BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+            final int freqCount = rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR
+                    ? ServiceState.FREQUENCY_RANGE_COUNT : 1;
+            for (int freqRange = 0; freqRange < freqCount; freqRange++) {
+                mRxTxPowerEstimators.put(
+                        MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange),
+                        buildRxTxPowerEstimators(powerProfile, rat, freqRange));
+            }
+        }
+    }
+
+    private static RxTxPowerEstimators buildRxTxPowerEstimators(PowerProfile powerProfile, int rat,
+            int freqRange) {
+        RxTxPowerEstimators estimators = new RxTxPowerEstimators();
+        long rxKey = ModemPowerProfile.getAverageBatteryDrainKey(
+                ModemPowerProfile.MODEM_DRAIN_TYPE_RX, rat, freqRange, IGNORE);
+        double rxDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(rxKey, Double.NaN);
+        if (Double.isNaN(rxDrainRateMa)) {
+            Log.w(TAG, "Unavailable Power Profile constant for key 0x"
+                    + Long.toHexString(rxKey));
+            rxDrainRateMa = 0;
+        }
+        estimators.mRxPowerEstimator = new UsageBasedPowerEstimator(rxDrainRateMa);
+        for (int txLevel = 0; txLevel < ModemActivityInfo.getNumTxPowerLevels(); txLevel++) {
+            long txKey = ModemPowerProfile.getAverageBatteryDrainKey(
+                    ModemPowerProfile.MODEM_DRAIN_TYPE_TX, rat, freqRange, txLevel);
+            double txDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(txKey,
+                    Double.NaN);
+            if (Double.isNaN(txDrainRateMa)) {
+                Log.w(TAG, "Unavailable Power Profile constant for key 0x"
+                        + Long.toHexString(txKey));
+                txDrainRateMa = 0;
+            }
+            estimators.mTxPowerEstimators[txLevel] = new UsageBasedPowerEstimator(txDrainRateMa);
+        }
+        return estimators;
+    }
+
+    private static class Intermediates {
+        /**
+         * Number of received packets
+         */
+        public long rxPackets;
+        /**
+         * Number of transmitted packets
+         */
+        public long txPackets;
+        /**
+         * Estimated power for the RX state of the modem.
+         */
+        public double rxPower;
+        /**
+         * Estimated power for the TX state of the modem.
+         */
+        public double txPower;
+        /**
+         * Estimated power for IDLE, SLEEP and CELL-SCAN states of the modem.
+         */
+        public double inactivePower;
+        /**
+         * Estimated power for IDLE, SLEEP and CELL-SCAN states of the modem.
+         */
+        public double callPower;
+        /**
+         * Measured consumed energy from power monitoring hardware (micro-coulombs)
+         */
+        public long consumedEnergy;
+    }
+
+    @Override
+    void finish(PowerComponentAggregatedPowerStats stats) {
+        if (stats.getPowerStatsDescriptor() == null) {
+            return;
+        }
+
+        unpackPowerStatsDescriptor(stats.getPowerStatsDescriptor());
+
+        if (mPlan == null) {
+            mPlan = new PowerEstimationPlan(stats.getConfig());
+        }
+
+        for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+            DeviceStateEstimation estimation = mPlan.deviceStateEstimations.get(i);
+            Intermediates intermediates = new Intermediates();
+            estimation.intermediates = intermediates;
+            computeDevicePowerEstimates(stats, estimation.stateValues, intermediates);
+        }
+
+        if (mStatsLayout.getEnergyConsumerCount() != 0) {
+            double ratio = computeEstimateAdjustmentRatioUsingConsumedEnergy();
+            if (ratio != 1) {
+                for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+                    DeviceStateEstimation estimation = mPlan.deviceStateEstimations.get(i);
+                    adjustDevicePowerEstimates(stats, estimation.stateValues,
+                            (Intermediates) estimation.intermediates, ratio);
+                }
+            }
+        }
+
+        combineDeviceStateEstimates();
+
+        ArrayList<Integer> uids = new ArrayList<>();
+        stats.collectUids(uids);
+        if (!uids.isEmpty()) {
+            for (int uid : uids) {
+                for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+                    computeUidRxTxTotals(stats, uid, mPlan.uidStateEstimates.get(i));
+                }
+            }
+
+            for (int uid : uids) {
+                for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+                    computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(i));
+                }
+            }
+        }
+        mPlan.resetIntermediates();
+    }
+
+    private void unpackPowerStatsDescriptor(PowerStats.Descriptor descriptor) {
+        if (descriptor.equals(mLastUsedDescriptor)) {
+            return;
+        }
+
+        mLastUsedDescriptor = descriptor;
+        mStatsLayout = new MobileRadioPowerStatsLayout(descriptor);
+        mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
+        mTmpStateStatsArray = new long[descriptor.stateStatsArrayLength];
+        mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
+    }
+
+    /**
+     * Compute power estimates using the power profile.
+     */
+    private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
+            int[] deviceStates, Intermediates intermediates) {
+        if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStates)) {
+            return;
+        }
+
+        for (int i = mStatsLayout.getEnergyConsumerCount() - 1; i >= 0; i--) {
+            intermediates.consumedEnergy += mStatsLayout.getConsumedEnergy(mTmpDeviceStatsArray, i);
+        }
+
+        if (mSleepPowerEstimator != null) {
+            intermediates.inactivePower += mSleepPowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceSleepTime(mTmpDeviceStatsArray));
+        }
+
+        if (mIdlePowerEstimator != null) {
+            intermediates.inactivePower += mIdlePowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceIdleTime(mTmpDeviceStatsArray));
+        }
+
+        if (mScanPowerEstimator != null) {
+            intermediates.inactivePower += mScanPowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceScanTime(mTmpDeviceStatsArray));
+        }
+
+        stats.forEachStateStatsKey(key -> {
+            RxTxPowerEstimators estimators = mRxTxPowerEstimators.get(key);
+            stats.getStateStats(mTmpStateStatsArray, key, deviceStates);
+            long rxTime = mStatsLayout.getStateRxTime(mTmpStateStatsArray);
+            intermediates.rxPower += estimators.mRxPowerEstimator.calculatePower(rxTime);
+            for (int txLevel = 0; txLevel < ModemActivityInfo.getNumTxPowerLevels(); txLevel++) {
+                long txTime = mStatsLayout.getStateTxTime(mTmpStateStatsArray, txLevel);
+                intermediates.txPower +=
+                        estimators.mTxPowerEstimators[txLevel].calculatePower(txTime);
+            }
+        });
+
+        if (mCallPowerEstimator != null) {
+            intermediates.callPower = mCallPowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceCallTime(mTmpDeviceStatsArray));
+        }
+
+        mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
+                intermediates.rxPower + intermediates.txPower + intermediates.inactivePower);
+        mStatsLayout.setDeviceCallPowerEstimate(mTmpDeviceStatsArray, intermediates.callPower);
+        stats.setDeviceStats(deviceStates, mTmpDeviceStatsArray);
+    }
+
+    /**
+     * Compute an adjustment ratio using the total power estimated using the power profile
+     * and the total power measured by hardware.
+     */
+    private double computeEstimateAdjustmentRatioUsingConsumedEnergy() {
+        long totalConsumedEnergy = 0;
+        double totalPower = 0;
+
+        for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+            Intermediates intermediates =
+                    (Intermediates) mPlan.deviceStateEstimations.get(i).intermediates;
+            totalPower += intermediates.rxPower + intermediates.txPower
+                    + intermediates.inactivePower + intermediates.callPower;
+            totalConsumedEnergy += intermediates.consumedEnergy;
+        }
+
+        if (totalPower == 0) {
+            return 1;
+        }
+
+        return uCtoMah(totalConsumedEnergy) / totalPower;
+    }
+
+    /**
+     * Uniformly apply the same adjustment to all power estimates in order to ensure that the total
+     * estimated power matches the measured consumed power.  We are not claiming that all
+     * averages captured in the power profile have to be off by the same percentage in reality.
+     */
+    private void adjustDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
+            int[] deviceStates, Intermediates intermediates, double ratio) {
+        intermediates.rxPower *= ratio;
+        intermediates.txPower *= ratio;
+        intermediates.inactivePower *= ratio;
+        intermediates.callPower *= ratio;
+
+        if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStates)) {
+            return;
+        }
+
+        mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
+                intermediates.rxPower + intermediates.txPower + intermediates.inactivePower);
+        mStatsLayout.setDeviceCallPowerEstimate(mTmpDeviceStatsArray, intermediates.callPower);
+        stats.setDeviceStats(deviceStates, mTmpDeviceStatsArray);
+    }
+
+    /**
+     * This step is effectively a no-op in the cases where we track the same states for
+     * the entire device and all UIDs (e.g. screen on/off, on-battery/on-charger etc). However,
+     * if the lists of tracked states are not the same, we need to combine some estimates
+     * before distributing them proportionally to UIDs.
+     */
+    private void combineDeviceStateEstimates() {
+        for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
+            CombinedDeviceStateEstimate cdse = mPlan.combinedDeviceStateEstimations.get(i);
+            Intermediates cdseIntermediates = new Intermediates();
+            cdse.intermediates = cdseIntermediates;
+            List<DeviceStateEstimation> deviceStateEstimations = cdse.deviceStateEstimations;
+            for (int j = deviceStateEstimations.size() - 1; j >= 0; j--) {
+                DeviceStateEstimation dse = deviceStateEstimations.get(j);
+                Intermediates intermediates = (Intermediates) dse.intermediates;
+                cdseIntermediates.rxPower += intermediates.rxPower;
+                cdseIntermediates.txPower += intermediates.txPower;
+                cdseIntermediates.inactivePower += intermediates.inactivePower;
+                cdseIntermediates.consumedEnergy += intermediates.consumedEnergy;
+            }
+        }
+    }
+
+    private void computeUidRxTxTotals(PowerComponentAggregatedPowerStats stats, int uid,
+            UidStateEstimate uidStateEstimate) {
+        Intermediates intermediates =
+                (Intermediates) uidStateEstimate.combinedDeviceStateEstimate.intermediates;
+        for (UidStateProportionalEstimate proportionalEstimate :
+                uidStateEstimate.proportionalEstimates) {
+            if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+                continue;
+            }
+
+            intermediates.rxPackets += mStatsLayout.getUidRxPackets(mTmpUidStatsArray);
+            intermediates.txPackets += mStatsLayout.getUidTxPackets(mTmpUidStatsArray);
+        }
+    }
+
+    private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats, int uid,
+            UidStateEstimate uidStateEstimate) {
+        Intermediates intermediates =
+                (Intermediates) uidStateEstimate.combinedDeviceStateEstimate.intermediates;
+        for (UidStateProportionalEstimate proportionalEstimate :
+                uidStateEstimate.proportionalEstimates) {
+            if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+                continue;
+            }
+
+            double power = 0;
+            if (intermediates.rxPackets != 0) {
+                power += intermediates.rxPower * mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+                        / intermediates.rxPackets;
+            }
+            if (intermediates.txPackets != 0) {
+                power += intermediates.txPower * mStatsLayout.getUidTxPackets(mTmpUidStatsArray)
+                        / intermediates.txPackets;
+            }
+
+            mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+            stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+
+            if (DEBUG) {
+                Slog.d(TAG, "UID: " + uid
+                        + " states: " + Arrays.toString(proportionalEstimate.stateValues)
+                        + " stats: " + Arrays.toString(mTmpUidStatsArray)
+                        + " rx: " + mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+                        + " rx-power: " + intermediates.rxPower
+                        + " rx-packets: " + intermediates.rxPackets
+                        + " tx: " + mStatsLayout.getUidTxPackets(mTmpUidStatsArray)
+                        + " tx-power: " + intermediates.txPower
+                        + " tx-packets: " + intermediates.txPackets
+                        + " power: " + power);
+            }
+        }
+    }
+
+    @Override
+    String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        return "idle: " + mStatsLayout.getDeviceIdleTime(stats)
+                + " sleep: " + mStatsLayout.getDeviceSleepTime(stats)
+                + " scan: " + mStatsLayout.getDeviceScanTime(stats)
+                + " power: " + mStatsLayout.getDevicePowerEstimate(stats);
+    }
+
+    @Override
+    String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        StringBuilder sb = new StringBuilder();
+        sb.append(descriptor.getStateLabel(key));
+        sb.append(" rx: ").append(mStatsLayout.getStateRxTime(stats));
+        sb.append(" tx: ");
+        for (int txLevel = 0; txLevel < ModemActivityInfo.getNumTxPowerLevels(); txLevel++) {
+            if (txLevel != 0) {
+                sb.append(", ");
+            }
+            sb.append(mStatsLayout.getStateTxTime(stats, txLevel));
+        }
+        return sb.toString();
+    }
+
+    @Override
+    String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        return "rx: " + mStatsLayout.getUidRxPackets(stats)
+                + " tx: " + mStatsLayout.getUidTxPackets(stats)
+                + " power: " + mStatsLayout.getUidPowerEstimate(stats);
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/MultiStateStats.java b/services/core/java/com/android/server/power/stats/MultiStateStats.java
index 9356950..6c4a2b6 100644
--- a/services/core/java/com/android/server/power/stats/MultiStateStats.java
+++ b/services/core/java/com/android/server/power/stats/MultiStateStats.java
@@ -288,6 +288,14 @@
     }
 
     /**
+     * Copies time-in-state and timestamps from the supplied prototype. Does not
+     * copy accumulated counts.
+     */
+    public void copyStatesFrom(MultiStateStats otherStats) {
+        mCounter.copyStatesFrom(otherStats.mCounter);
+    }
+
+    /**
      * Updates the current composite state by changing one of the States supplied to the Factory
      * constructor.
      *
diff --git a/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java
new file mode 100644
index 0000000..62b653f
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import android.os.BatteryConsumer;
+import android.os.PersistableBundle;
+
+import com.android.internal.os.PowerStats;
+
+public class PhoneCallPowerStatsProcessor extends PowerStatsProcessor {
+    private final PowerStatsLayout mStatsLayout;
+    private final PowerStats.Descriptor mDescriptor;
+    private final long[] mTmpDeviceStats;
+    private PowerStats.Descriptor mMobileRadioStatsDescriptor;
+    private MobileRadioPowerStatsLayout mMobileRadioStatsLayout;
+    private long[] mTmpMobileRadioDeviceStats;
+
+    public PhoneCallPowerStatsProcessor() {
+        mStatsLayout = new PowerStatsLayout();
+        mStatsLayout.addDeviceSectionPowerEstimate();
+        PersistableBundle extras = new PersistableBundle();
+        mStatsLayout.toExtras(extras);
+        mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_PHONE,
+                mStatsLayout.getDeviceStatsArrayLength(), null, 0, 0, extras);
+        mTmpDeviceStats = new long[mDescriptor.statsArrayLength];
+    }
+
+    @Override
+    void finish(PowerComponentAggregatedPowerStats stats) {
+        stats.setPowerStatsDescriptor(mDescriptor);
+
+        PowerComponentAggregatedPowerStats mobileRadioStats =
+                stats.getAggregatedPowerStats().getPowerComponentStats(
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
+        if (mobileRadioStats == null) {
+            return;
+        }
+
+        if (mMobileRadioStatsDescriptor == null) {
+            mMobileRadioStatsDescriptor = mobileRadioStats.getPowerStatsDescriptor();
+            if (mMobileRadioStatsDescriptor == null) {
+                return;
+            }
+
+            mMobileRadioStatsLayout =
+                    new MobileRadioPowerStatsLayout(
+                            mMobileRadioStatsDescriptor);
+            mTmpMobileRadioDeviceStats = new long[mMobileRadioStatsDescriptor.statsArrayLength];
+        }
+
+        MultiStateStats.States[] deviceStateConfig =
+                mobileRadioStats.getConfig().getDeviceStateConfig();
+
+        // Phone call power estimates have already been calculated by the mobile radio stats
+        // processor. All that remains to be done is copy the estimates over.
+        MultiStateStats.States.forEachTrackedStateCombination(deviceStateConfig,
+                states -> {
+                    mobileRadioStats.getDeviceStats(mTmpMobileRadioDeviceStats, states);
+                    double callPowerEstimate =
+                            mMobileRadioStatsLayout.getDeviceCallPowerEstimate(
+                                    mTmpMobileRadioDeviceStats);
+                    mStatsLayout.setDevicePowerEstimate(mTmpDeviceStats, callPowerEstimate);
+                    stats.setDeviceStats(states, mTmpDeviceStats);
+                });
+    }
+
+    @Override
+    String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        return "power: " + mStatsLayout.getDevicePowerEstimate(stats);
+    }
+
+    @Override
+    String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats) {
+        // Unsupported for this power component
+        return null;
+    }
+
+    @Override
+    String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        // Unsupported for this power component
+        return null;
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
index 1637022..6d58307 100644
--- a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.UserHandle;
 import android.util.IndentingPrintWriter;
 import android.util.SparseArray;
 
@@ -29,7 +30,10 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.function.IntConsumer;
 
 /**
  * Aggregated power stats for a specific power component (e.g. CPU, WiFi, etc). This class
@@ -41,22 +45,28 @@
     static final String XML_TAG_POWER_COMPONENT = "power_component";
     static final String XML_ATTR_ID = "id";
     private static final String XML_TAG_DEVICE_STATS = "device-stats";
+    private static final String XML_TAG_STATE_STATS = "state-stats";
+    private static final String XML_ATTR_KEY = "key";
     private static final String XML_TAG_UID_STATS = "uid-stats";
     private static final String XML_ATTR_UID = "uid";
     private static final long UNKNOWN = -1;
 
     public final int powerComponentId;
-    private final MultiStateStats.States[] mDeviceStateConfig;
-    private final MultiStateStats.States[] mUidStateConfig;
+    @NonNull
+    private final AggregatedPowerStats mAggregatedPowerStats;
     @NonNull
     private final AggregatedPowerStatsConfig.PowerComponent mConfig;
+    private final MultiStateStats.States[] mDeviceStateConfig;
+    private final MultiStateStats.States[] mUidStateConfig;
     private final int[] mDeviceStates;
 
     private MultiStateStats.Factory mStatsFactory;
+    private MultiStateStats.Factory mStateStatsFactory;
     private MultiStateStats.Factory mUidStatsFactory;
     private PowerStats.Descriptor mPowerStatsDescriptor;
     private long mPowerStatsTimestamp;
     private MultiStateStats mDeviceStats;
+    private final SparseArray<MultiStateStats> mStateStats = new SparseArray<>();
     private final SparseArray<UidStats> mUidStats = new SparseArray<>();
 
     private static class UidStats {
@@ -64,7 +74,9 @@
         public MultiStateStats stats;
     }
 
-    PowerComponentAggregatedPowerStats(AggregatedPowerStatsConfig.PowerComponent config) {
+    PowerComponentAggregatedPowerStats(@NonNull AggregatedPowerStats aggregatedPowerStats,
+            @NonNull AggregatedPowerStatsConfig.PowerComponent config) {
+        mAggregatedPowerStats = aggregatedPowerStats;
         mConfig = config;
         powerComponentId = config.getPowerComponentId();
         mDeviceStateConfig = config.getDeviceStateConfig();
@@ -74,6 +86,11 @@
     }
 
     @NonNull
+    AggregatedPowerStats getAggregatedPowerStats() {
+        return mAggregatedPowerStats;
+    }
+
+    @NonNull
     public AggregatedPowerStatsConfig.PowerComponent getConfig() {
         return mConfig;
     }
@@ -83,16 +100,25 @@
         return mPowerStatsDescriptor;
     }
 
-    void setState(@AggregatedPowerStatsConfig.TrackedState int stateId, int state, long time) {
+    public void setPowerStatsDescriptor(PowerStats.Descriptor powerStatsDescriptor) {
+        mPowerStatsDescriptor = powerStatsDescriptor;
+    }
+
+    void setState(@AggregatedPowerStatsConfig.TrackedState int stateId, int state,
+            long timestampMs) {
         if (mDeviceStats == null) {
-            createDeviceStats();
+            createDeviceStats(timestampMs);
         }
 
         mDeviceStates[stateId] = state;
 
         if (mDeviceStateConfig[stateId].isTracked()) {
             if (mDeviceStats != null) {
-                mDeviceStats.setState(stateId, state, time);
+                mDeviceStats.setState(stateId, state, timestampMs);
+            }
+            for (int i = mStateStats.size() - 1; i >= 0; i--) {
+                MultiStateStats stateStats = mStateStats.valueAt(i);
+                stateStats.setState(stateId, state, timestampMs);
             }
         }
 
@@ -100,36 +126,39 @@
             for (int i = mUidStats.size() - 1; i >= 0; i--) {
                 PowerComponentAggregatedPowerStats.UidStats uidStats = mUidStats.valueAt(i);
                 if (uidStats.stats == null) {
-                    createUidStats(uidStats);
+                    createUidStats(uidStats, timestampMs);
                 }
 
                 uidStats.states[stateId] = state;
                 if (uidStats.stats != null) {
-                    uidStats.stats.setState(stateId, state, time);
+                    uidStats.stats.setState(stateId, state, timestampMs);
                 }
             }
         }
     }
 
     void setUidState(int uid, @AggregatedPowerStatsConfig.TrackedState int stateId, int state,
-            long time) {
+            long timestampMs) {
         if (!mUidStateConfig[stateId].isTracked()) {
             return;
         }
 
         UidStats uidStats = getUidStats(uid);
         if (uidStats.stats == null) {
-            createUidStats(uidStats);
+            createUidStats(uidStats, timestampMs);
         }
 
         uidStats.states[stateId] = state;
 
         if (uidStats.stats != null) {
-            uidStats.stats.setState(stateId, state, time);
+            uidStats.stats.setState(stateId, state, timestampMs);
         }
     }
 
     void setDeviceStats(@AggregatedPowerStatsConfig.TrackedState int[] states, long[] values) {
+        if (mDeviceStats == null) {
+            createDeviceStats(0);
+        }
         mDeviceStats.setStats(states, values);
     }
 
@@ -147,16 +176,24 @@
         mPowerStatsDescriptor = powerStats.descriptor;
 
         if (mDeviceStats == null) {
-            createDeviceStats();
+            createDeviceStats(timestampMs);
         }
 
+        for (int i = powerStats.stateStats.size() - 1; i >= 0; i--) {
+            int key = powerStats.stateStats.keyAt(i);
+            MultiStateStats stateStats = mStateStats.get(key);
+            if (stateStats == null) {
+                stateStats = createStateStats(key, timestampMs);
+            }
+            stateStats.increment(powerStats.stateStats.valueAt(i), timestampMs);
+        }
         mDeviceStats.increment(powerStats.stats, timestampMs);
 
         for (int i = powerStats.uidStats.size() - 1; i >= 0; i--) {
             int uid = powerStats.uidStats.keyAt(i);
             PowerComponentAggregatedPowerStats.UidStats uidStats = getUidStats(uid);
             if (uidStats.stats == null) {
-                createUidStats(uidStats);
+                createUidStats(uidStats, timestampMs);
             }
             uidStats.stats.increment(powerStats.uidStats.valueAt(i), timestampMs);
         }
@@ -168,6 +205,7 @@
         mStatsFactory = null;
         mUidStatsFactory = null;
         mDeviceStats = null;
+        mStateStats.clear();
         for (int i = mUidStats.size() - 1; i >= 0; i--) {
             mUidStats.valueAt(i).stats = null;
         }
@@ -178,6 +216,13 @@
         if (uidStats == null) {
             uidStats = new UidStats();
             uidStats.states = new int[mUidStateConfig.length];
+            for (int stateId = 0; stateId < mUidStateConfig.length; stateId++) {
+                if (mUidStateConfig[stateId].isTracked()
+                        && stateId < mDeviceStateConfig.length
+                        && mDeviceStateConfig[stateId].isTracked()) {
+                    uidStats.states[stateId] = mDeviceStates[stateId];
+                }
+            }
             mUidStats.put(uid, uidStats);
         }
         return uidStats;
@@ -204,6 +249,26 @@
         return false;
     }
 
+    boolean getStateStats(long[] outValues, int key, int[] deviceStates) {
+        if (deviceStates.length != mDeviceStateConfig.length) {
+            throw new IllegalArgumentException(
+                    "Invalid number of tracked states: " + deviceStates.length
+                            + " expected: " + mDeviceStateConfig.length);
+        }
+        MultiStateStats stateStats = mStateStats.get(key);
+        if (stateStats != null) {
+            stateStats.getStats(outValues, deviceStates);
+            return true;
+        }
+        return false;
+    }
+
+    void forEachStateStatsKey(IntConsumer consumer) {
+        for (int i = mStateStats.size() - 1; i >= 0; i--) {
+            consumer.accept(mStateStats.keyAt(i));
+        }
+    }
+
     boolean getUidStats(long[] outValues, int uid, int[] uidStates) {
         if (uidStates.length != mUidStateConfig.length) {
             throw new IllegalArgumentException(
@@ -218,7 +283,7 @@
         return false;
     }
 
-    private void createDeviceStats() {
+    private void createDeviceStats(long timestampMs) {
         if (mStatsFactory == null) {
             if (mPowerStatsDescriptor == null) {
                 return;
@@ -229,13 +294,39 @@
 
         mDeviceStats = mStatsFactory.create();
         if (mPowerStatsTimestamp != UNKNOWN) {
+            timestampMs = mPowerStatsTimestamp;
+        }
+        if (timestampMs != UNKNOWN) {
             for (int stateId = 0; stateId < mDeviceStateConfig.length; stateId++) {
-                mDeviceStats.setState(stateId, mDeviceStates[stateId], mPowerStatsTimestamp);
+                int state = mDeviceStates[stateId];
+                mDeviceStats.setState(stateId, state, timestampMs);
+                for (int i = mStateStats.size() - 1; i >= 0; i--) {
+                    MultiStateStats stateStats = mStateStats.valueAt(i);
+                    stateStats.setState(stateId, state, timestampMs);
+                }
             }
         }
     }
 
-    private void createUidStats(UidStats uidStats) {
+    private MultiStateStats createStateStats(int key, long timestampMs) {
+        if (mStateStatsFactory == null) {
+            if (mPowerStatsDescriptor == null) {
+                return null;
+            }
+            mStateStatsFactory = new MultiStateStats.Factory(
+                    mPowerStatsDescriptor.stateStatsArrayLength, mDeviceStateConfig);
+        }
+
+        MultiStateStats stateStats = mStateStatsFactory.create();
+        mStateStats.put(key, stateStats);
+        if (mDeviceStats != null) {
+            stateStats.copyStatesFrom(mDeviceStats);
+        }
+
+        return stateStats;
+    }
+
+    private void createUidStats(UidStats uidStats, long timestampMs) {
         if (mUidStatsFactory == null) {
             if (mPowerStatsDescriptor == null) {
                 return;
@@ -245,9 +336,13 @@
         }
 
         uidStats.stats = mUidStatsFactory.create();
-        for (int stateId = 0; stateId < mUidStateConfig.length; stateId++) {
-            if (mPowerStatsTimestamp != UNKNOWN) {
-                uidStats.stats.setState(stateId, uidStats.states[stateId], mPowerStatsTimestamp);
+
+        if (mPowerStatsTimestamp != UNKNOWN) {
+            timestampMs = mPowerStatsTimestamp;
+        }
+        if (timestampMs != UNKNOWN) {
+            for (int stateId = 0; stateId < mUidStateConfig.length; stateId++) {
+                uidStats.stats.setState(stateId, uidStats.states[stateId], timestampMs);
             }
         }
     }
@@ -268,6 +363,13 @@
             serializer.endTag(null, XML_TAG_DEVICE_STATS);
         }
 
+        for (int i = 0; i < mStateStats.size(); i++) {
+            serializer.startTag(null, XML_TAG_STATE_STATS);
+            serializer.attributeInt(null, XML_ATTR_KEY, mStateStats.keyAt(i));
+            mStateStats.valueAt(i).writeXml(serializer);
+            serializer.endTag(null, XML_TAG_STATE_STATS);
+        }
+
         for (int i = mUidStats.size() - 1; i >= 0; i--) {
             int uid = mUidStats.keyAt(i);
             UidStats uidStats = mUidStats.valueAt(i);
@@ -285,8 +387,10 @@
 
     public boolean readFromXml(TypedXmlPullParser parser) throws XmlPullParserException,
             IOException {
+        String outerTag = parser.getName();
         int eventType = parser.getEventType();
-        while (eventType != XmlPullParser.END_DOCUMENT) {
+        while (eventType != XmlPullParser.END_DOCUMENT
+                && !(eventType == XmlPullParser.END_TAG && parser.getName().equals(outerTag))) {
             if (eventType == XmlPullParser.START_TAG) {
                 switch (parser.getName()) {
                     case PowerStats.Descriptor.XML_TAG_DESCRIPTOR:
@@ -297,17 +401,27 @@
                         break;
                     case XML_TAG_DEVICE_STATS:
                         if (mDeviceStats == null) {
-                            createDeviceStats();
+                            createDeviceStats(UNKNOWN);
                         }
                         if (!mDeviceStats.readFromXml(parser)) {
                             return false;
                         }
                         break;
+                    case XML_TAG_STATE_STATS:
+                        int key = parser.getAttributeInt(null, XML_ATTR_KEY);
+                        MultiStateStats stats = mStateStats.get(key);
+                        if (stats == null) {
+                            stats = createStateStats(key, UNKNOWN);
+                        }
+                        if (!stats.readFromXml(parser)) {
+                            return false;
+                        }
+                        break;
                     case XML_TAG_UID_STATS:
                         int uid = parser.getAttributeInt(null, XML_ATTR_UID);
                         UidStats uidStats = getUidStats(uid);
                         if (uidStats.stats == null) {
-                            createUidStats(uidStats);
+                            createUidStats(uidStats, UNKNOWN);
                         }
                         if (!uidStats.stats.readFromXml(parser)) {
                             return false;
@@ -328,6 +442,21 @@
                     mConfig.getProcessor().deviceStatsToString(mPowerStatsDescriptor, stats));
             ipw.decreaseIndent();
         }
+
+        if (mStateStats.size() != 0) {
+            ipw.increaseIndent();
+            ipw.println(mPowerStatsDescriptor.name + " states");
+            ipw.increaseIndent();
+            for (int i = 0; i < mStateStats.size(); i++) {
+                int key = mStateStats.keyAt(i);
+                MultiStateStats stateStats = mStateStats.valueAt(i);
+                stateStats.dump(ipw, stats ->
+                        mConfig.getProcessor().stateStatsToString(mPowerStatsDescriptor, key,
+                                stats));
+            }
+            ipw.decreaseIndent();
+            ipw.decreaseIndent();
+        }
     }
 
     void dumpUid(IndentingPrintWriter ipw, int uid) {
@@ -340,4 +469,29 @@
             ipw.decreaseIndent();
         }
     }
+
+    @Override
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        IndentingPrintWriter ipw = new IndentingPrintWriter(sw);
+        ipw.increaseIndent();
+        dumpDevice(ipw);
+        ipw.decreaseIndent();
+
+        int[] uids = new int[mUidStats.size()];
+        for (int i = uids.length - 1; i >= 0; i--) {
+            uids[i] = mUidStats.keyAt(i);
+        }
+        Arrays.sort(uids);
+        for (int uid : uids) {
+            ipw.println(UserHandle.formatUid(uid));
+            ipw.increaseIndent();
+            dumpUid(ipw, uid);
+            ipw.decreaseIndent();
+        }
+
+        ipw.flush();
+
+        return sw.toString();
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
index ba4c127..6a4c1f0 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
@@ -32,7 +32,7 @@
     private static final long UNINITIALIZED = -1;
     private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
     private final BatteryStatsHistory mHistory;
-    private final SparseArray<AggregatedPowerStatsProcessor> mProcessors = new SparseArray<>();
+    private final SparseArray<PowerStatsProcessor> mProcessors = new SparseArray<>();
     private AggregatedPowerStats mStats;
     private int mCurrentBatteryState = AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
     private int mCurrentScreenState = AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
@@ -43,7 +43,7 @@
         mHistory = history;
         for (AggregatedPowerStatsConfig.PowerComponent powerComponentsConfig :
                 aggregatedPowerStatsConfig.getPowerComponentsAggregatedStatsConfigs()) {
-            AggregatedPowerStatsProcessor processor = powerComponentsConfig.getProcessor();
+            PowerStatsProcessor processor = powerComponentsConfig.getProcessor();
             mProcessors.put(powerComponentsConfig.getPowerComponentId(), processor);
         }
     }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
index c76797b..b82c021 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
@@ -17,9 +17,12 @@
 package com.android.server.power.stats;
 
 import android.annotation.Nullable;
+import android.hardware.power.stats.EnergyConsumer;
+import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyConsumerType;
 import android.os.ConditionVariable;
 import android.os.Handler;
-import android.os.PersistableBundle;
+import android.power.PowerStatsInternal;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
@@ -30,7 +33,12 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
 
 /**
@@ -43,214 +51,38 @@
 public abstract class PowerStatsCollector {
     private static final String TAG = "PowerStatsCollector";
     private static final int MILLIVOLTS_PER_VOLT = 1000;
+    private static final long POWER_STATS_ENERGY_CONSUMERS_TIMEOUT = 20000;
     private final Handler mHandler;
+    protected final PowerStatsUidResolver mUidResolver;
     protected final Clock mClock;
     private final long mThrottlePeriodMs;
     private final Runnable mCollectAndDeliverStats = this::collectAndDeliverStats;
     private boolean mEnabled;
     private long mLastScheduledUpdateMs = -1;
 
-    /**
-     * Captures the positions and lengths of sections of the stats array, such as usage duration,
-     * power usage estimates etc.
-     */
-    public static class StatsArrayLayout {
-        private static final String EXTRA_DEVICE_POWER_POSITION = "dp";
-        private static final String EXTRA_DEVICE_DURATION_POSITION = "dd";
-        private static final String EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION = "de";
-        private static final String EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT = "dec";
-        private static final String EXTRA_UID_POWER_POSITION = "up";
-
-        protected static final double MILLI_TO_NANO_MULTIPLIER = 1000000.0;
-
-        private int mDeviceStatsArrayLength;
-        private int mUidStatsArrayLength;
-
-        protected int mDeviceDurationPosition;
-        private int mDeviceEnergyConsumerPosition;
-        private int mDeviceEnergyConsumerCount;
-        private int mDevicePowerEstimatePosition;
-        private int mUidPowerEstimatePosition;
-
-        public int getDeviceStatsArrayLength() {
-            return mDeviceStatsArrayLength;
-        }
-
-        public int getUidStatsArrayLength() {
-            return mUidStatsArrayLength;
-        }
-
-        protected int addDeviceSection(int length) {
-            int position = mDeviceStatsArrayLength;
-            mDeviceStatsArrayLength += length;
-            return position;
-        }
-
-        protected int addUidSection(int length) {
-            int position = mUidStatsArrayLength;
-            mUidStatsArrayLength += length;
-            return position;
-        }
-
-        /**
-         * Declare that the stats array has a section capturing usage duration
-         */
-        public void addDeviceSectionUsageDuration() {
-            mDeviceDurationPosition = addDeviceSection(1);
-        }
-
-        /**
-         * Saves the usage duration in the corresponding <code>stats</code> element.
-         */
-        public void setUsageDuration(long[] stats, long value) {
-            stats[mDeviceDurationPosition] = value;
-        }
-
-        /**
-         * Extracts the usage duration from the corresponding <code>stats</code> element.
-         */
-        public long getUsageDuration(long[] stats) {
-            return stats[mDeviceDurationPosition];
-        }
-
-        /**
-         * Declares that the stats array has a section capturing EnergyConsumer data from
-         * PowerStatsService.
-         */
-        public void addDeviceSectionEnergyConsumers(int energyConsumerCount) {
-            mDeviceEnergyConsumerPosition = addDeviceSection(energyConsumerCount);
-            mDeviceEnergyConsumerCount = energyConsumerCount;
-        }
-
-        public int getEnergyConsumerCount() {
-            return mDeviceEnergyConsumerCount;
-        }
-
-        /**
-         * Saves the accumulated energy for the specified rail the corresponding
-         * <code>stats</code> element.
-         */
-        public void setConsumedEnergy(long[] stats, int index, long energy) {
-            stats[mDeviceEnergyConsumerPosition + index] = energy;
-        }
-
-        /**
-         * Extracts the EnergyConsumer data from a device stats array for the specified
-         * EnergyConsumer.
-         */
-        public long getConsumedEnergy(long[] stats, int index) {
-            return stats[mDeviceEnergyConsumerPosition + index];
-        }
-
-        /**
-         * Declare that the stats array has a section capturing a power estimate
-         */
-        public void addDeviceSectionPowerEstimate() {
-            mDevicePowerEstimatePosition = addDeviceSection(1);
-        }
-
-        /**
-         * Converts the supplied mAh power estimate to a long and saves it in the corresponding
-         * element of <code>stats</code>.
-         */
-        public void setDevicePowerEstimate(long[] stats, double power) {
-            stats[mDevicePowerEstimatePosition] = (long) (power * MILLI_TO_NANO_MULTIPLIER);
-        }
-
-        /**
-         * Extracts the power estimate from a device stats array and converts it to mAh.
-         */
-        public double getDevicePowerEstimate(long[] stats) {
-            return stats[mDevicePowerEstimatePosition] / MILLI_TO_NANO_MULTIPLIER;
-        }
-
-        /**
-         * Declare that the UID stats array has a section capturing a power estimate
-         */
-        public void addUidSectionPowerEstimate() {
-            mUidPowerEstimatePosition = addUidSection(1);
-        }
-
-        /**
-         * Converts the supplied mAh power estimate to a long and saves it in the corresponding
-         * element of <code>stats</code>.
-         */
-        public void setUidPowerEstimate(long[] stats, double power) {
-            stats[mUidPowerEstimatePosition] = (long) (power * MILLI_TO_NANO_MULTIPLIER);
-        }
-
-        /**
-         * Extracts the power estimate from a UID stats array and converts it to mAh.
-         */
-        public double getUidPowerEstimate(long[] stats) {
-            return stats[mUidPowerEstimatePosition] / MILLI_TO_NANO_MULTIPLIER;
-        }
-
-        /**
-         * Copies the elements of the stats array layout into <code>extras</code>
-         */
-        public void toExtras(PersistableBundle extras) {
-            extras.putInt(EXTRA_DEVICE_DURATION_POSITION, mDeviceDurationPosition);
-            extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION,
-                    mDeviceEnergyConsumerPosition);
-            extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT,
-                    mDeviceEnergyConsumerCount);
-            extras.putInt(EXTRA_DEVICE_POWER_POSITION, mDevicePowerEstimatePosition);
-            extras.putInt(EXTRA_UID_POWER_POSITION, mUidPowerEstimatePosition);
-        }
-
-        /**
-         * Retrieves elements of the stats array layout from <code>extras</code>
-         */
-        public void fromExtras(PersistableBundle extras) {
-            mDeviceDurationPosition = extras.getInt(EXTRA_DEVICE_DURATION_POSITION);
-            mDeviceEnergyConsumerPosition = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION);
-            mDeviceEnergyConsumerCount = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT);
-            mDevicePowerEstimatePosition = extras.getInt(EXTRA_DEVICE_POWER_POSITION);
-            mUidPowerEstimatePosition = extras.getInt(EXTRA_UID_POWER_POSITION);
-        }
-
-        protected void putIntArray(PersistableBundle extras, String key, int[] array) {
-            if (array == null) {
-                return;
-            }
-
-            StringBuilder sb = new StringBuilder();
-            for (int value : array) {
-                if (!sb.isEmpty()) {
-                    sb.append(',');
-                }
-                sb.append(value);
-            }
-            extras.putString(key, sb.toString());
-        }
-
-        protected int[] getIntArray(PersistableBundle extras, String key) {
-            String string = extras.getString(key);
-            if (string == null) {
-                return null;
-            }
-            String[] values = string.trim().split(",");
-            int[] result = new int[values.length];
-            for (int i = 0; i < values.length; i++) {
-                try {
-                    result[i] = Integer.parseInt(values[i]);
-                } catch (NumberFormatException e) {
-                    Slog.wtf(TAG, "Invalid CSV format: " + string);
-                    return null;
-                }
-            }
-            return result;
-        }
-    }
-
     @GuardedBy("this")
     @SuppressWarnings("unchecked")
     private volatile List<Consumer<PowerStats>> mConsumerList = Collections.emptyList();
 
-    public PowerStatsCollector(Handler handler, long throttlePeriodMs, Clock clock) {
+    public PowerStatsCollector(Handler handler, long throttlePeriodMs,
+            PowerStatsUidResolver uidResolver, Clock clock) {
         mHandler = handler;
         mThrottlePeriodMs = throttlePeriodMs;
+        mUidResolver = uidResolver;
+        mUidResolver.addListener(new PowerStatsUidResolver.Listener() {
+            @Override
+            public void onIsolatedUidAdded(int isolatedUid, int parentUid) {
+            }
+
+            @Override
+            public void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
+            }
+
+            @Override
+            public void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
+                mHandler.post(()->onUidRemoved(isolatedUid));
+            }
+        });
         mClock = clock;
     }
 
@@ -388,10 +220,87 @@
         done.block();
     }
 
+    protected void onUidRemoved(int uid) {
+    }
+
     /** Calculate charge consumption (in microcoulombs) from a given energy and voltage */
-    protected long uJtoUc(long deltaEnergyUj, int avgVoltageMv) {
+    protected static long uJtoUc(long deltaEnergyUj, int avgVoltageMv) {
         // To overflow, a 3.7V 10000mAh battery would need to completely drain 69244 times
         // since the last snapshot. Round off to the nearest whole long.
         return (deltaEnergyUj * MILLIVOLTS_PER_VOLT + (avgVoltageMv / 2)) / avgVoltageMv;
     }
+
+    interface ConsumedEnergyRetriever {
+        int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType);
+
+        @Nullable
+        long[] getConsumedEnergyUws(int[] energyConsumerIds);
+    }
+
+    static class ConsumedEnergyRetrieverImpl implements ConsumedEnergyRetriever {
+        private final PowerStatsInternal mPowerStatsInternal;
+
+        ConsumedEnergyRetrieverImpl(PowerStatsInternal powerStatsInternal) {
+            mPowerStatsInternal = powerStatsInternal;
+        }
+
+        @Override
+        public int[] getEnergyConsumerIds(int energyConsumerType) {
+            if (mPowerStatsInternal == null) {
+                return new int[0];
+            }
+
+            EnergyConsumer[] energyConsumerInfo = mPowerStatsInternal.getEnergyConsumerInfo();
+            if (energyConsumerInfo == null) {
+                return new int[0];
+            }
+
+            List<EnergyConsumer> energyConsumers = new ArrayList<>();
+            for (EnergyConsumer energyConsumer : energyConsumerInfo) {
+                if (energyConsumer.type == energyConsumerType) {
+                    energyConsumers.add(energyConsumer);
+                }
+            }
+            if (energyConsumers.isEmpty()) {
+                return new int[0];
+            }
+
+            energyConsumers.sort(Comparator.comparing(c -> c.ordinal));
+
+            int[] ids = new int[energyConsumers.size()];
+            for (int i = 0; i < ids.length; i++) {
+                ids[i] = energyConsumers.get(i).id;
+            }
+            return ids;
+        }
+
+        @Override
+        public long[] getConsumedEnergyUws(int[] energyConsumerIds) {
+            CompletableFuture<EnergyConsumerResult[]> future =
+                    mPowerStatsInternal.getEnergyConsumedAsync(energyConsumerIds);
+            EnergyConsumerResult[] results = null;
+            try {
+                results = future.get(
+                        POWER_STATS_ENERGY_CONSUMERS_TIMEOUT, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException | ExecutionException | TimeoutException e) {
+                Slog.e(TAG, "Could not obtain energy consumers from PowerStatsService", e);
+            }
+
+            if (results == null) {
+                return null;
+            }
+
+            long[] energy = new long[energyConsumerIds.length];
+            for (int i = 0; i < energyConsumerIds.length; i++) {
+                int id = energyConsumerIds[i];
+                for (EnergyConsumerResult result : results) {
+                    if (result.id == id) {
+                        energy[i] = result.energyUWs;
+                        break;
+                    }
+                }
+            }
+            return energy;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
index 4f4ddca..f6b198a8 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
@@ -139,7 +139,7 @@
             return;
         }
 
-        PowerStatsCollector.StatsArrayLayout layout = new PowerStatsCollector.StatsArrayLayout();
+        PowerStatsLayout layout = new PowerStatsLayout();
         layout.fromExtras(descriptor.extras);
 
         long[] deviceStats = new long[descriptor.statsArrayLength];
@@ -164,9 +164,20 @@
         deviceScope.addConsumedPower(powerComponentId,
                 totalPower[0], BatteryConsumer.POWER_MODEL_UNDEFINED);
 
+        if (layout.isUidPowerAttributionSupported()) {
+            populateUidBatteryConsumers(batteryUsageStatsBuilder, powerComponent,
+                    powerComponentStats, layout);
+        }
+    }
+
+    private static void populateUidBatteryConsumers(
+            BatteryUsageStats.Builder batteryUsageStatsBuilder,
+            AggregatedPowerStatsConfig.PowerComponent powerComponent,
+            PowerComponentAggregatedPowerStats powerComponentStats,
+            PowerStatsLayout layout) {
+        int powerComponentId = powerComponent.getPowerComponentId();
+        PowerStats.Descriptor descriptor = powerComponentStats.getPowerStatsDescriptor();
         long[] uidStats = new long[descriptor.uidStatsArrayLength];
-        ArrayList<Integer> uids = new ArrayList<>();
-        powerComponentStats.collectUids(uids);
 
         boolean breakDownByProcState =
                 batteryUsageStatsBuilder.isProcessStateDataNeeded()
@@ -177,6 +188,8 @@
         double[] powerByProcState =
                 new double[breakDownByProcState ? BatteryConsumer.PROCESS_STATE_COUNT : 1];
         double powerAllApps = 0;
+        ArrayList<Integer> uids = new ArrayList<>();
+        powerComponentStats.collectUids(uids);
         for (int uid : uids) {
             UidBatteryConsumer.Builder builder =
                     batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uid);
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsLayout.java b/services/core/java/com/android/server/power/stats/PowerStatsLayout.java
new file mode 100644
index 0000000..aa96409
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/PowerStatsLayout.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.os.PersistableBundle;
+import android.util.Slog;
+
+import com.android.internal.os.PowerStats;
+
+/**
+ * Captures the positions and lengths of sections of the stats array, such as usage duration,
+ * power usage estimates etc.
+ */
+public class PowerStatsLayout {
+    private static final String TAG = "PowerStatsLayout";
+    private static final String EXTRA_DEVICE_POWER_POSITION = "dp";
+    private static final String EXTRA_DEVICE_DURATION_POSITION = "dd";
+    private static final String EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION = "de";
+    private static final String EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT = "dec";
+    private static final String EXTRA_UID_POWER_POSITION = "up";
+
+    protected static final double MILLI_TO_NANO_MULTIPLIER = 1000000.0;
+    protected static final int UNSUPPORTED = -1;
+
+    private int mDeviceStatsArrayLength;
+    private int mStateStatsArrayLength;
+    private int mUidStatsArrayLength;
+
+    protected int mDeviceDurationPosition = UNSUPPORTED;
+    private int mDeviceEnergyConsumerPosition;
+    private int mDeviceEnergyConsumerCount;
+    private int mDevicePowerEstimatePosition = UNSUPPORTED;
+    private int mUidPowerEstimatePosition = UNSUPPORTED;
+
+    public PowerStatsLayout() {
+    }
+
+    public PowerStatsLayout(PowerStats.Descriptor descriptor) {
+        fromExtras(descriptor.extras);
+    }
+
+    public int getDeviceStatsArrayLength() {
+        return mDeviceStatsArrayLength;
+    }
+
+    public int getStateStatsArrayLength() {
+        return mStateStatsArrayLength;
+    }
+
+    public int getUidStatsArrayLength() {
+        return mUidStatsArrayLength;
+    }
+
+    protected int addDeviceSection(int length) {
+        int position = mDeviceStatsArrayLength;
+        mDeviceStatsArrayLength += length;
+        return position;
+    }
+
+    protected int addStateSection(int length) {
+        int position = mStateStatsArrayLength;
+        mStateStatsArrayLength += length;
+        return position;
+    }
+
+    protected int addUidSection(int length) {
+        int position = mUidStatsArrayLength;
+        mUidStatsArrayLength += length;
+        return position;
+    }
+
+    /**
+     * Declare that the stats array has a section capturing usage duration
+     */
+    public void addDeviceSectionUsageDuration() {
+        mDeviceDurationPosition = addDeviceSection(1);
+    }
+
+    /**
+     * Saves the usage duration in the corresponding <code>stats</code> element.
+     */
+    public void setUsageDuration(long[] stats, long value) {
+        stats[mDeviceDurationPosition] = value;
+    }
+
+    /**
+     * Extracts the usage duration from the corresponding <code>stats</code> element.
+     */
+    public long getUsageDuration(long[] stats) {
+        return stats[mDeviceDurationPosition];
+    }
+
+    /**
+     * Declares that the stats array has a section capturing EnergyConsumer data from
+     * PowerStatsService.
+     */
+    public void addDeviceSectionEnergyConsumers(int energyConsumerCount) {
+        mDeviceEnergyConsumerPosition = addDeviceSection(energyConsumerCount);
+        mDeviceEnergyConsumerCount = energyConsumerCount;
+    }
+
+    public int getEnergyConsumerCount() {
+        return mDeviceEnergyConsumerCount;
+    }
+
+    /**
+     * Saves the accumulated energy for the specified rail the corresponding
+     * <code>stats</code> element.
+     */
+    public void setConsumedEnergy(long[] stats, int index, long energy) {
+        stats[mDeviceEnergyConsumerPosition + index] = energy;
+    }
+
+    /**
+     * Extracts the EnergyConsumer data from a device stats array for the specified
+     * EnergyConsumer.
+     */
+    public long getConsumedEnergy(long[] stats, int index) {
+        return stats[mDeviceEnergyConsumerPosition + index];
+    }
+
+    /**
+     * Declare that the stats array has a section capturing a power estimate
+     */
+    public void addDeviceSectionPowerEstimate() {
+        mDevicePowerEstimatePosition = addDeviceSection(1);
+    }
+
+    /**
+     * Converts the supplied mAh power estimate to a long and saves it in the corresponding
+     * element of <code>stats</code>.
+     */
+    public void setDevicePowerEstimate(long[] stats, double power) {
+        stats[mDevicePowerEstimatePosition] = (long) (power * MILLI_TO_NANO_MULTIPLIER);
+    }
+
+    /**
+     * Extracts the power estimate from a device stats array and converts it to mAh.
+     */
+    public double getDevicePowerEstimate(long[] stats) {
+        return stats[mDevicePowerEstimatePosition] / MILLI_TO_NANO_MULTIPLIER;
+    }
+
+    /**
+     * Declare that the UID stats array has a section capturing a power estimate
+     */
+    public void addUidSectionPowerEstimate() {
+        mUidPowerEstimatePosition = addUidSection(1);
+    }
+
+    /**
+     * Returns true if power for this component is attributed to UIDs (apps).
+     */
+    public boolean isUidPowerAttributionSupported() {
+        return mUidPowerEstimatePosition != UNSUPPORTED;
+    }
+
+    /**
+     * Converts the supplied mAh power estimate to a long and saves it in the corresponding
+     * element of <code>stats</code>.
+     */
+    public void setUidPowerEstimate(long[] stats, double power) {
+        stats[mUidPowerEstimatePosition] = (long) (power * MILLI_TO_NANO_MULTIPLIER);
+    }
+
+    /**
+     * Extracts the power estimate from a UID stats array and converts it to mAh.
+     */
+    public double getUidPowerEstimate(long[] stats) {
+        return stats[mUidPowerEstimatePosition] / MILLI_TO_NANO_MULTIPLIER;
+    }
+
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        extras.putInt(EXTRA_DEVICE_DURATION_POSITION, mDeviceDurationPosition);
+        extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION,
+                mDeviceEnergyConsumerPosition);
+        extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT,
+                mDeviceEnergyConsumerCount);
+        extras.putInt(EXTRA_DEVICE_POWER_POSITION, mDevicePowerEstimatePosition);
+        extras.putInt(EXTRA_UID_POWER_POSITION, mUidPowerEstimatePosition);
+    }
+
+    /**
+     * Retrieves elements of the stats array layout from <code>extras</code>
+     */
+    public void fromExtras(PersistableBundle extras) {
+        mDeviceDurationPosition = extras.getInt(EXTRA_DEVICE_DURATION_POSITION);
+        mDeviceEnergyConsumerPosition = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION);
+        mDeviceEnergyConsumerCount = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT);
+        mDevicePowerEstimatePosition = extras.getInt(EXTRA_DEVICE_POWER_POSITION);
+        mUidPowerEstimatePosition = extras.getInt(EXTRA_UID_POWER_POSITION);
+    }
+
+    protected void putIntArray(PersistableBundle extras, String key, int[] array) {
+        if (array == null) {
+            return;
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (int value : array) {
+            if (!sb.isEmpty()) {
+                sb.append(',');
+            }
+            sb.append(value);
+        }
+        extras.putString(key, sb.toString());
+    }
+
+    protected int[] getIntArray(PersistableBundle extras, String key) {
+        String string = extras.getString(key);
+        if (string == null) {
+            return null;
+        }
+        String[] values = string.trim().split(",");
+        int[] result = new int[values.length];
+        for (int i = 0; i < values.length; i++) {
+            try {
+                result[i] = Integer.parseInt(values[i]);
+            } catch (NumberFormatException e) {
+                Slog.wtf(TAG, "Invalid CSV format: " + string);
+                return null;
+            }
+        }
+        return result;
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java
new file mode 100644
index 0000000..0d5c542
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.power.stats;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import com.android.internal.os.PowerStats;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/*
+ * The power estimation algorithm used by PowerStatsProcessor can roughly be
+ * described like this:
+ *
+ * 1. Estimate power usage for each state combination (e.g. power-battery/screen-on) using
+ * a metric such as CPU time-in-state.
+ *
+ * 2. Combine estimates obtain in step 1, aggregating across states that are *not* tracked
+ * per UID.
+ *
+ * 2. For each UID, compute the proportion of the combined estimates in each state
+ * and attribute the corresponding portion of the total power estimate in that state to the UID.
+ */
+abstract class PowerStatsProcessor {
+    private static final String TAG = "PowerStatsProcessor";
+
+    private static final int INDEX_DOES_NOT_EXIST = -1;
+    private static final double MILLIAMPHOUR_PER_MICROCOULOMB = 1.0 / 1000.0 / 60.0 / 60.0;
+
+    abstract void finish(PowerComponentAggregatedPowerStats stats);
+
+    abstract String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats);
+
+    abstract String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats);
+
+    abstract String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats);
+
+    protected static class PowerEstimationPlan {
+        private final AggregatedPowerStatsConfig.PowerComponent mConfig;
+        public List<DeviceStateEstimation> deviceStateEstimations = new ArrayList<>();
+        public List<CombinedDeviceStateEstimate> combinedDeviceStateEstimations = new ArrayList<>();
+        public List<UidStateEstimate> uidStateEstimates = new ArrayList<>();
+
+        public PowerEstimationPlan(AggregatedPowerStatsConfig.PowerComponent config) {
+            mConfig = config;
+            addDeviceStateEstimations();
+            combineDeviceStateEstimations();
+            addUidStateEstimations();
+        }
+
+        private void addDeviceStateEstimations() {
+            MultiStateStats.States[] config = mConfig.getDeviceStateConfig();
+            int[][] deviceStateCombinations = getAllTrackedStateCombinations(config);
+            for (int[] deviceStateCombination : deviceStateCombinations) {
+                deviceStateEstimations.add(
+                        new DeviceStateEstimation(config, deviceStateCombination));
+            }
+        }
+
+        private void combineDeviceStateEstimations() {
+            MultiStateStats.States[] deviceStateConfig = mConfig.getDeviceStateConfig();
+            MultiStateStats.States[] uidStateConfig = mConfig.getUidStateConfig();
+            MultiStateStats.States[] deviceStatesTrackedPerUid =
+                    new MultiStateStats.States[deviceStateConfig.length];
+
+            for (int i = 0; i < deviceStateConfig.length; i++) {
+                if (!deviceStateConfig[i].isTracked()) {
+                    continue;
+                }
+
+                int index = findTrackedStateByName(uidStateConfig, deviceStateConfig[i].getName());
+                if (index != INDEX_DOES_NOT_EXIST && uidStateConfig[index].isTracked()) {
+                    deviceStatesTrackedPerUid[i] = deviceStateConfig[i];
+                }
+            }
+
+            combineDeviceStateEstimationsRecursively(deviceStateConfig, deviceStatesTrackedPerUid,
+                    new int[deviceStateConfig.length], 0);
+        }
+
+        private void combineDeviceStateEstimationsRecursively(
+                MultiStateStats.States[] deviceStateConfig,
+                MultiStateStats.States[] deviceStatesTrackedPerUid, int[] stateValues, int state) {
+            if (state >= deviceStateConfig.length) {
+                DeviceStateEstimation dse = getDeviceStateEstimate(stateValues);
+                CombinedDeviceStateEstimate cdse = getCombinedDeviceStateEstimate(
+                        deviceStatesTrackedPerUid, stateValues);
+                if (cdse == null) {
+                    cdse = new CombinedDeviceStateEstimate(deviceStatesTrackedPerUid, stateValues);
+                    combinedDeviceStateEstimations.add(cdse);
+                }
+                cdse.deviceStateEstimations.add(dse);
+                return;
+            }
+
+            if (deviceStateConfig[state].isTracked()) {
+                for (int stateValue = 0;
+                        stateValue < deviceStateConfig[state].getLabels().length;
+                        stateValue++) {
+                    stateValues[state] = stateValue;
+                    combineDeviceStateEstimationsRecursively(deviceStateConfig,
+                            deviceStatesTrackedPerUid, stateValues, state + 1);
+                }
+            } else {
+                combineDeviceStateEstimationsRecursively(deviceStateConfig,
+                        deviceStatesTrackedPerUid, stateValues, state + 1);
+            }
+        }
+
+        private void addUidStateEstimations() {
+            MultiStateStats.States[] deviceStateConfig = mConfig.getDeviceStateConfig();
+            MultiStateStats.States[] uidStateConfig = mConfig.getUidStateConfig();
+            MultiStateStats.States[] uidStatesTrackedForDevice =
+                    new MultiStateStats.States[uidStateConfig.length];
+            MultiStateStats.States[] uidStatesNotTrackedForDevice =
+                    new MultiStateStats.States[uidStateConfig.length];
+
+            for (int i = 0; i < uidStateConfig.length; i++) {
+                if (!uidStateConfig[i].isTracked()) {
+                    continue;
+                }
+
+                int index = findTrackedStateByName(deviceStateConfig, uidStateConfig[i].getName());
+                if (index != INDEX_DOES_NOT_EXIST && deviceStateConfig[index].isTracked()) {
+                    uidStatesTrackedForDevice[i] = uidStateConfig[i];
+                } else {
+                    uidStatesNotTrackedForDevice[i] = uidStateConfig[i];
+                }
+            }
+
+            @AggregatedPowerStatsConfig.TrackedState
+            int[][] uidStateCombinations = getAllTrackedStateCombinations(uidStateConfig);
+            for (int[] stateValues : uidStateCombinations) {
+                CombinedDeviceStateEstimate combined =
+                        getCombinedDeviceStateEstimate(uidStatesTrackedForDevice, stateValues);
+                if (combined == null) {
+                    // This is not supposed to be possible
+                    Log.wtf(TAG, "Mismatch in UID and combined device states: "
+                                 + concatLabels(uidStatesTrackedForDevice, stateValues));
+                    continue;
+                }
+                UidStateEstimate uidStateEstimate = getUidStateEstimate(combined);
+                if (uidStateEstimate == null) {
+                    uidStateEstimate = new UidStateEstimate(combined, uidStatesNotTrackedForDevice);
+                    uidStateEstimates.add(uidStateEstimate);
+                }
+                uidStateEstimate.proportionalEstimates.add(
+                        new UidStateProportionalEstimate(stateValues));
+            }
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Step 1. Compute device-wide power estimates for state combinations:\n");
+            for (DeviceStateEstimation deviceStateEstimation : deviceStateEstimations) {
+                sb.append("    ").append(deviceStateEstimation.id).append("\n");
+            }
+            sb.append("Step 2. Combine device-wide estimates that are untracked per UID:\n");
+            boolean any = false;
+            for (CombinedDeviceStateEstimate cdse : combinedDeviceStateEstimations) {
+                if (cdse.deviceStateEstimations.size() <= 1) {
+                    continue;
+                }
+                any = true;
+                sb.append("    ").append(cdse.id).append(": ");
+                for (int i = 0; i < cdse.deviceStateEstimations.size(); i++) {
+                    if (i != 0) {
+                        sb.append(" + ");
+                    }
+                    sb.append(cdse.deviceStateEstimations.get(i).id);
+                }
+                sb.append("\n");
+            }
+            if (!any) {
+                sb.append("    N/A\n");
+            }
+            sb.append("Step 3. Proportionally distribute power estimates to UIDs:\n");
+            for (UidStateEstimate uidStateEstimate : uidStateEstimates) {
+                sb.append("    ").append(uidStateEstimate.combinedDeviceStateEstimate.id)
+                        .append("\n        among: ");
+                for (int i = 0; i < uidStateEstimate.proportionalEstimates.size(); i++) {
+                    UidStateProportionalEstimate uspe =
+                            uidStateEstimate.proportionalEstimates.get(i);
+                    if (i != 0) {
+                        sb.append(", ");
+                    }
+                    sb.append(concatLabels(uidStateEstimate.states, uspe.stateValues));
+                }
+                sb.append("\n");
+            }
+            return sb.toString();
+        }
+
+        @Nullable
+        public DeviceStateEstimation getDeviceStateEstimate(
+                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
+            String label = concatLabels(mConfig.getDeviceStateConfig(), stateValues);
+            for (int i = 0; i < deviceStateEstimations.size(); i++) {
+                DeviceStateEstimation deviceStateEstimation = this.deviceStateEstimations.get(i);
+                if (deviceStateEstimation.id.equals(label)) {
+                    return deviceStateEstimation;
+                }
+            }
+            return null;
+        }
+
+        public CombinedDeviceStateEstimate getCombinedDeviceStateEstimate(
+                MultiStateStats.States[] deviceStates,
+                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
+            String label = concatLabels(deviceStates, stateValues);
+            for (int i = 0; i < combinedDeviceStateEstimations.size(); i++) {
+                CombinedDeviceStateEstimate cdse = combinedDeviceStateEstimations.get(i);
+                if (cdse.id.equals(label)) {
+                    return cdse;
+                }
+            }
+            return null;
+        }
+
+        public UidStateEstimate getUidStateEstimate(CombinedDeviceStateEstimate combined) {
+            for (int i = 0; i < uidStateEstimates.size(); i++) {
+                UidStateEstimate uidStateEstimate = uidStateEstimates.get(i);
+                if (uidStateEstimate.combinedDeviceStateEstimate == combined) {
+                    return uidStateEstimate;
+                }
+            }
+            return null;
+        }
+
+        public void resetIntermediates() {
+            for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) {
+                deviceStateEstimations.get(i).intermediates = null;
+            }
+            for (int i = deviceStateEstimations.size() - 1; i >= 0; i--) {
+                deviceStateEstimations.get(i).intermediates = null;
+            }
+            for (int i = uidStateEstimates.size() - 1; i >= 0; i--) {
+                UidStateEstimate uidStateEstimate = uidStateEstimates.get(i);
+                List<UidStateProportionalEstimate> proportionalEstimates =
+                        uidStateEstimate.proportionalEstimates;
+                for (int j = proportionalEstimates.size() - 1; j >= 0; j--) {
+                    proportionalEstimates.get(j).intermediates = null;
+                }
+            }
+        }
+    }
+
+    protected static class DeviceStateEstimation {
+        public final String id;
+        @AggregatedPowerStatsConfig.TrackedState
+        public final int[] stateValues;
+        public Object intermediates;
+
+        public DeviceStateEstimation(MultiStateStats.States[] config,
+                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
+            id = concatLabels(config, stateValues);
+            this.stateValues = stateValues;
+        }
+    }
+
+    protected static class CombinedDeviceStateEstimate {
+        public final String id;
+        public List<DeviceStateEstimation> deviceStateEstimations = new ArrayList<>();
+        public Object intermediates;
+
+        public CombinedDeviceStateEstimate(MultiStateStats.States[] config,
+                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
+            id = concatLabels(config, stateValues);
+        }
+    }
+
+    protected static class UidStateEstimate {
+        public final MultiStateStats.States[] states;
+        public CombinedDeviceStateEstimate combinedDeviceStateEstimate;
+        public List<UidStateProportionalEstimate> proportionalEstimates = new ArrayList<>();
+
+        public UidStateEstimate(CombinedDeviceStateEstimate combined,
+                MultiStateStats.States[] states) {
+            combinedDeviceStateEstimate = combined;
+            this.states = states;
+        }
+    }
+
+    protected static class UidStateProportionalEstimate {
+        @AggregatedPowerStatsConfig.TrackedState
+        public final int[] stateValues;
+        public Object intermediates;
+
+        protected UidStateProportionalEstimate(
+                @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
+            this.stateValues = stateValues;
+        }
+    }
+
+    private static int findTrackedStateByName(MultiStateStats.States[] states, String name) {
+        for (int i = 0; i < states.length; i++) {
+            if (states[i].getName().equals(name)) {
+                return i;
+            }
+        }
+        return INDEX_DOES_NOT_EXIST;
+    }
+
+    @NonNull
+    private static String concatLabels(MultiStateStats.States[] config,
+            @AggregatedPowerStatsConfig.TrackedState int[] stateValues) {
+        List<String> labels = new ArrayList<>();
+        for (int state = 0; state < config.length; state++) {
+            if (config[state] != null && config[state].isTracked()) {
+                labels.add(config[state].getName()
+                           + "=" + config[state].getLabels()[stateValues[state]]);
+            }
+        }
+        Collections.sort(labels);
+        return labels.toString();
+    }
+
+    @AggregatedPowerStatsConfig.TrackedState
+    private static int[][] getAllTrackedStateCombinations(MultiStateStats.States[] states) {
+        List<int[]> combinations = new ArrayList<>();
+        MultiStateStats.States.forEachTrackedStateCombination(states, stateValues -> {
+            combinations.add(Arrays.copyOf(stateValues, stateValues.length));
+        });
+        return combinations.toArray(new int[combinations.size()][0]);
+    }
+
+    public static double uCtoMah(long chargeUC) {
+        return chargeUC * MILLIAMPHOUR_PER_MICROCOULOMB;
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
new file mode 100644
index 0000000..6321053
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
+import android.os.Handler;
+import android.os.PersistableBundle;
+import android.os.connectivity.WifiActivityEnergyInfo;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class WifiPowerStatsCollector extends PowerStatsCollector {
+    private static final String TAG = "WifiPowerStatsCollector";
+
+    private static final long WIFI_ACTIVITY_REQUEST_TIMEOUT = 20000;
+
+    private static final long ENERGY_UNSPECIFIED = -1;
+
+    interface WifiStatsRetriever {
+        interface Callback {
+            void onWifiScanTime(int uid, long scanTimeMs, long batchScanTimeMs);
+        }
+
+        void retrieveWifiScanTimes(Callback callback);
+        long getWifiActiveDuration();
+    }
+
+    interface Injector {
+        Handler getHandler();
+        Clock getClock();
+        PowerStatsUidResolver getUidResolver();
+        PackageManager getPackageManager();
+        ConsumedEnergyRetriever getConsumedEnergyRetriever();
+        IntSupplier getVoltageSupplier();
+        Supplier<NetworkStats> getWifiNetworkStatsSupplier();
+        WifiManager getWifiManager();
+        WifiStatsRetriever getWifiStatsRetriever();
+    }
+
+    private final Injector mInjector;
+
+    private WifiPowerStatsLayout mLayout;
+    private boolean mIsInitialized;
+    private boolean mPowerReportingSupported;
+
+    private PowerStats mPowerStats;
+    private long[] mDeviceStats;
+    private volatile WifiManager mWifiManager;
+    private volatile Supplier<NetworkStats> mNetworkStatsSupplier;
+    private volatile WifiStatsRetriever mWifiStatsRetriever;
+    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    private IntSupplier mVoltageSupplier;
+    private int[] mEnergyConsumerIds = new int[0];
+    private WifiActivityEnergyInfo mLastWifiActivityInfo =
+            new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+    private NetworkStats mLastNetworkStats;
+    private long[] mLastConsumedEnergyUws;
+    private int mLastVoltageMv;
+
+    private static class WifiScanTimes {
+        public long basicScanTimeMs;
+        public long batchedScanTimeMs;
+    }
+    private final WifiScanTimes mScanTimes = new WifiScanTimes();
+    private final SparseArray<WifiScanTimes> mLastScanTimes = new SparseArray<>();
+    private long mLastWifiActiveDuration;
+
+    public WifiPowerStatsCollector(Injector injector, long throttlePeriodMs) {
+        super(injector.getHandler(), throttlePeriodMs, injector.getUidResolver(),
+                injector.getClock());
+        mInjector = injector;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (enabled) {
+            PackageManager packageManager = mInjector.getPackageManager();
+            super.setEnabled(packageManager != null
+                    && packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI));
+        } else {
+            super.setEnabled(false);
+        }
+    }
+
+    private boolean ensureInitialized() {
+        if (mIsInitialized) {
+            return true;
+        }
+
+        if (!isEnabled()) {
+            return false;
+        }
+
+        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
+        mVoltageSupplier = mInjector.getVoltageSupplier();
+        mWifiManager = mInjector.getWifiManager();
+        mNetworkStatsSupplier = mInjector.getWifiNetworkStatsSupplier();
+        mWifiStatsRetriever = mInjector.getWifiStatsRetriever();
+        mPowerReportingSupported =
+                mWifiManager != null && mWifiManager.isEnhancedPowerReportingSupported();
+
+        mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI);
+        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
+        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+
+        mLayout = new WifiPowerStatsLayout();
+        mLayout.addDeviceWifiActivity(mPowerReportingSupported);
+        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
+        mLayout.addUidNetworkStats();
+        mLayout.addDeviceSectionUsageDuration();
+        mLayout.addDeviceSectionPowerEstimate();
+        mLayout.addUidSectionPowerEstimate();
+
+        PersistableBundle extras = new PersistableBundle();
+        mLayout.toExtras(extras);
+        PowerStats.Descriptor powerStatsDescriptor = new PowerStats.Descriptor(
+                BatteryConsumer.POWER_COMPONENT_WIFI, mLayout.getDeviceStatsArrayLength(),
+                null, 0, mLayout.getUidStatsArrayLength(),
+                extras);
+        mPowerStats = new PowerStats(powerStatsDescriptor);
+        mDeviceStats = mPowerStats.stats;
+
+        mIsInitialized = true;
+        return true;
+    }
+
+    @Override
+    protected PowerStats collectStats() {
+        if (!ensureInitialized()) {
+            return null;
+        }
+
+        if (mPowerReportingSupported) {
+            collectWifiActivityInfo();
+        } else {
+            collectWifiActivityStats();
+        }
+        collectNetworkStats();
+        collectWifiScanTime();
+
+        if (mEnergyConsumerIds.length != 0) {
+            collectEnergyConsumers();
+        }
+
+        return mPowerStats;
+    }
+
+    private void collectWifiActivityInfo() {
+        CompletableFuture<WifiActivityEnergyInfo> immediateFuture = new CompletableFuture<>();
+        mWifiManager.getWifiActivityEnergyInfoAsync(Runnable::run,
+                immediateFuture::complete);
+
+        WifiActivityEnergyInfo activityInfo;
+        try {
+            activityInfo = immediateFuture.get(WIFI_ACTIVITY_REQUEST_TIMEOUT,
+                    TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            Slog.e(TAG, "Cannot acquire WifiActivityEnergyInfo", e);
+            activityInfo = null;
+        }
+
+        if (activityInfo == null) {
+            return;
+        }
+
+        long rxDuration = activityInfo.getControllerRxDurationMillis()
+                - mLastWifiActivityInfo.getControllerRxDurationMillis();
+        long txDuration = activityInfo.getControllerTxDurationMillis()
+                - mLastWifiActivityInfo.getControllerTxDurationMillis();
+        long scanDuration = activityInfo.getControllerScanDurationMillis()
+                - mLastWifiActivityInfo.getControllerScanDurationMillis();
+        long idleDuration = activityInfo.getControllerIdleDurationMillis()
+                - mLastWifiActivityInfo.getControllerIdleDurationMillis();
+
+        mLayout.setDeviceRxTime(mDeviceStats, rxDuration);
+        mLayout.setDeviceTxTime(mDeviceStats, txDuration);
+        mLayout.setDeviceScanTime(mDeviceStats, scanDuration);
+        mLayout.setDeviceIdleTime(mDeviceStats, idleDuration);
+
+        mPowerStats.durationMs = rxDuration + txDuration + scanDuration + idleDuration;
+
+        mLastWifiActivityInfo = activityInfo;
+    }
+
+    private void collectWifiActivityStats() {
+        long duration = mWifiStatsRetriever.getWifiActiveDuration();
+        mLayout.setDeviceActiveTime(mDeviceStats, Math.max(0, duration - mLastWifiActiveDuration));
+        mLastWifiActiveDuration = duration;
+        mPowerStats.durationMs = duration;
+    }
+
+    private void collectNetworkStats() {
+        mPowerStats.uidStats.clear();
+
+        NetworkStats networkStats = mNetworkStatsSupplier.get();
+        if (networkStats == null) {
+            return;
+        }
+
+        List<BatteryStatsImpl.NetworkStatsDelta> delta =
+                BatteryStatsImpl.computeDelta(networkStats, mLastNetworkStats);
+        mLastNetworkStats = networkStats;
+        for (int i = delta.size() - 1; i >= 0; i--) {
+            BatteryStatsImpl.NetworkStatsDelta uidDelta = delta.get(i);
+            long rxBytes = uidDelta.getRxBytes();
+            long txBytes = uidDelta.getTxBytes();
+            long rxPackets = uidDelta.getRxPackets();
+            long txPackets = uidDelta.getTxPackets();
+            if (rxBytes == 0 && txBytes == 0 && rxPackets == 0 && txPackets == 0) {
+                continue;
+            }
+
+            int uid = mUidResolver.mapUid(uidDelta.getUid());
+            long[] stats = mPowerStats.uidStats.get(uid);
+            if (stats == null) {
+                stats = new long[mLayout.getUidStatsArrayLength()];
+                mPowerStats.uidStats.put(uid, stats);
+                mLayout.setUidRxBytes(stats, rxBytes);
+                mLayout.setUidTxBytes(stats, txBytes);
+                mLayout.setUidRxPackets(stats, rxPackets);
+                mLayout.setUidTxPackets(stats, txPackets);
+            } else {
+                mLayout.setUidRxBytes(stats, mLayout.getUidRxBytes(stats) + rxBytes);
+                mLayout.setUidTxBytes(stats, mLayout.getUidTxBytes(stats) + txBytes);
+                mLayout.setUidRxPackets(stats, mLayout.getUidRxPackets(stats) + rxPackets);
+                mLayout.setUidTxPackets(stats, mLayout.getUidTxPackets(stats) + txPackets);
+            }
+        }
+    }
+
+    private void collectWifiScanTime() {
+        mScanTimes.basicScanTimeMs = 0;
+        mScanTimes.batchedScanTimeMs = 0;
+        mWifiStatsRetriever.retrieveWifiScanTimes((uid, scanTimeMs, batchScanTimeMs) -> {
+            WifiScanTimes lastScanTimes = mLastScanTimes.get(uid);
+            if (lastScanTimes == null) {
+                lastScanTimes = new WifiScanTimes();
+                mLastScanTimes.put(uid, lastScanTimes);
+            }
+
+            long scanTimeDelta = Math.max(0, scanTimeMs - lastScanTimes.basicScanTimeMs);
+            long batchScanTimeDelta = Math.max(0,
+                    batchScanTimeMs - lastScanTimes.batchedScanTimeMs);
+            if (scanTimeDelta != 0 || batchScanTimeDelta != 0) {
+                mScanTimes.basicScanTimeMs += scanTimeDelta;
+                mScanTimes.batchedScanTimeMs += batchScanTimeDelta;
+                uid = mUidResolver.mapUid(uid);
+                long[] stats = mPowerStats.uidStats.get(uid);
+                if (stats == null) {
+                    stats = new long[mLayout.getUidStatsArrayLength()];
+                    mPowerStats.uidStats.put(uid, stats);
+                    mLayout.setUidScanTime(stats, scanTimeDelta);
+                    mLayout.setUidBatchScanTime(stats, batchScanTimeDelta);
+                } else {
+                    mLayout.setUidScanTime(stats, mLayout.getUidScanTime(stats) + scanTimeDelta);
+                    mLayout.setUidBatchScanTime(stats,
+                            mLayout.getUidBatchedScanTime(stats) + batchScanTimeDelta);
+                }
+            }
+            lastScanTimes.basicScanTimeMs = scanTimeMs;
+            lastScanTimes.batchedScanTimeMs = batchScanTimeMs;
+        });
+
+        mLayout.setDeviceBasicScanTime(mDeviceStats, mScanTimes.basicScanTimeMs);
+        mLayout.setDeviceBatchedScanTime(mDeviceStats, mScanTimes.batchedScanTimeMs);
+    }
+
+    private void collectEnergyConsumers() {
+        int voltageMv = mVoltageSupplier.getAsInt();
+        if (voltageMv <= 0) {
+            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
+                    + " mV) when querying energy consumers");
+            return;
+        }
+
+        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
+        mLastVoltageMv = voltageMv;
+
+        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
+        if (energyUws == null) {
+            return;
+        }
+
+        for (int i = energyUws.length - 1; i >= 0; i--) {
+            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
+                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
+            if (energyDelta < 0) {
+                // Likely, restart of powerstats HAL
+                energyDelta = 0;
+            }
+            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
+            mLastConsumedEnergyUws[i] = energyUws[i];
+        }
+    }
+
+    @Override
+    protected void onUidRemoved(int uid) {
+        super.onUidRemoved(uid);
+        mLastScanTimes.remove(uid);
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
new file mode 100644
index 0000000..0fa6ec6
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+
+import com.android.internal.os.PowerStats;
+
+public class WifiPowerStatsLayout extends PowerStatsLayout {
+    private static final String TAG = "WifiPowerStatsLayout";
+    private static final int UNSPECIFIED = -1;
+    private static final String EXTRA_POWER_REPORTING_SUPPORTED = "prs";
+    private static final String EXTRA_DEVICE_RX_TIME_POSITION = "dt-rx";
+    private static final String EXTRA_DEVICE_TX_TIME_POSITION = "dt-tx";
+    private static final String EXTRA_DEVICE_SCAN_TIME_POSITION = "dt-scan";
+    private static final String EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION = "dt-basic-scan";
+    private static final String EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION = "dt-batch-scan";
+    private static final String EXTRA_DEVICE_IDLE_TIME_POSITION = "dt-idle";
+    private static final String EXTRA_DEVICE_ACTIVE_TIME_POSITION = "dt-on";
+    private static final String EXTRA_UID_RX_BYTES_POSITION = "urxb";
+    private static final String EXTRA_UID_TX_BYTES_POSITION = "utxb";
+    private static final String EXTRA_UID_RX_PACKETS_POSITION = "urxp";
+    private static final String EXTRA_UID_TX_PACKETS_POSITION = "utxp";
+    private static final String EXTRA_UID_SCAN_TIME_POSITION = "ut-scan";
+    private static final String EXTRA_UID_BATCH_SCAN_TIME_POSITION = "ut-bscan";
+
+    private boolean mPowerReportingSupported;
+    private int mDeviceRxTimePosition;
+    private int mDeviceTxTimePosition;
+    private int mDeviceIdleTimePosition;
+    private int mDeviceScanTimePosition;
+    private int mDeviceBasicScanTimePosition;
+    private int mDeviceBatchedScanTimePosition;
+    private int mDeviceActiveTimePosition;
+    private int mUidRxBytesPosition;
+    private int mUidTxBytesPosition;
+    private int mUidRxPacketsPosition;
+    private int mUidTxPacketsPosition;
+    private int mUidScanTimePosition;
+    private int mUidBatchScanTimePosition;
+
+    WifiPowerStatsLayout() {
+    }
+
+    WifiPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+        super(descriptor);
+    }
+
+    void addDeviceWifiActivity(boolean powerReportingSupported) {
+        mPowerReportingSupported = powerReportingSupported;
+        if (mPowerReportingSupported) {
+            mDeviceActiveTimePosition = UNSPECIFIED;
+            mDeviceRxTimePosition = addDeviceSection(1);
+            mDeviceTxTimePosition = addDeviceSection(1);
+            mDeviceIdleTimePosition = addDeviceSection(1);
+            mDeviceScanTimePosition = addDeviceSection(1);
+        } else {
+            mDeviceActiveTimePosition = addDeviceSection(1);
+            mDeviceRxTimePosition = UNSPECIFIED;
+            mDeviceTxTimePosition = UNSPECIFIED;
+            mDeviceIdleTimePosition = UNSPECIFIED;
+            mDeviceScanTimePosition = UNSPECIFIED;
+        }
+        mDeviceBasicScanTimePosition = addDeviceSection(1);
+        mDeviceBatchedScanTimePosition = addDeviceSection(1);
+    }
+
+    void addUidNetworkStats() {
+        mUidRxBytesPosition = addUidSection(1);
+        mUidTxBytesPosition = addUidSection(1);
+        mUidRxPacketsPosition = addUidSection(1);
+        mUidTxPacketsPosition = addUidSection(1);
+        mUidScanTimePosition = addUidSection(1);
+        mUidBatchScanTimePosition = addUidSection(1);
+    }
+
+    public boolean isPowerReportingSupported() {
+        return mPowerReportingSupported;
+    }
+
+    public void setDeviceRxTime(long[] stats, long durationMillis) {
+        stats[mDeviceRxTimePosition] = durationMillis;
+    }
+
+    public long getDeviceRxTime(long[] stats) {
+        return stats[mDeviceRxTimePosition];
+    }
+
+    public void setDeviceTxTime(long[] stats, long durationMillis) {
+        stats[mDeviceTxTimePosition] = durationMillis;
+    }
+
+    public long getDeviceTxTime(long[] stats) {
+        return stats[mDeviceTxTimePosition];
+    }
+
+    public void setDeviceScanTime(long[] stats, long durationMillis) {
+        stats[mDeviceScanTimePosition] = durationMillis;
+    }
+
+    public long getDeviceScanTime(long[] stats) {
+        return stats[mDeviceScanTimePosition];
+    }
+
+    public void setDeviceBasicScanTime(long[] stats, long durationMillis) {
+        stats[mDeviceBasicScanTimePosition] = durationMillis;
+    }
+
+    public long getDeviceBasicScanTime(long[] stats) {
+        return stats[mDeviceBasicScanTimePosition];
+    }
+
+    public void setDeviceBatchedScanTime(long[] stats, long durationMillis) {
+        stats[mDeviceBatchedScanTimePosition] = durationMillis;
+    }
+
+    public long getDeviceBatchedScanTime(long[] stats) {
+        return stats[mDeviceBatchedScanTimePosition];
+    }
+
+    public void setDeviceIdleTime(long[] stats, long durationMillis) {
+        stats[mDeviceIdleTimePosition] = durationMillis;
+    }
+
+    public long getDeviceIdleTime(long[] stats) {
+        return stats[mDeviceIdleTimePosition];
+    }
+
+    public void setDeviceActiveTime(long[] stats, long durationMillis) {
+        stats[mDeviceActiveTimePosition] = durationMillis;
+    }
+
+    public long getDeviceActiveTime(long[] stats) {
+        return stats[mDeviceActiveTimePosition];
+    }
+
+    public void setUidRxBytes(long[] stats, long count) {
+        stats[mUidRxBytesPosition] = count;
+    }
+
+    public long getUidRxBytes(long[] stats) {
+        return stats[mUidRxBytesPosition];
+    }
+
+    public void setUidTxBytes(long[] stats, long count) {
+        stats[mUidTxBytesPosition] = count;
+    }
+
+    public long getUidTxBytes(long[] stats) {
+        return stats[mUidTxBytesPosition];
+    }
+
+    public void setUidRxPackets(long[] stats, long count) {
+        stats[mUidRxPacketsPosition] = count;
+    }
+
+    public long getUidRxPackets(long[] stats) {
+        return stats[mUidRxPacketsPosition];
+    }
+
+    public void setUidTxPackets(long[] stats, long count) {
+        stats[mUidTxPacketsPosition] = count;
+    }
+
+    public long getUidTxPackets(long[] stats) {
+        return stats[mUidTxPacketsPosition];
+    }
+
+    public void setUidScanTime(long[] stats, long count) {
+        stats[mUidScanTimePosition] = count;
+    }
+
+    public long getUidScanTime(long[] stats) {
+        return stats[mUidScanTimePosition];
+    }
+
+    public void setUidBatchScanTime(long[] stats, long count) {
+        stats[mUidBatchScanTimePosition] = count;
+    }
+
+    public long getUidBatchedScanTime(long[] stats) {
+        return stats[mUidBatchScanTimePosition];
+    }
+
+    /**
+     * Copies the elements of the stats array layout into <code>extras</code>
+     */
+    public void toExtras(PersistableBundle extras) {
+        super.toExtras(extras);
+        extras.putBoolean(EXTRA_POWER_REPORTING_SUPPORTED, mPowerReportingSupported);
+        extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
+        extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
+        extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION, mDeviceBasicScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION, mDeviceBatchedScanTimePosition);
+        extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+        extras.putInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION, mDeviceActiveTimePosition);
+        extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+        extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+        extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
+        extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
+        extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
+        extras.putInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION, mUidBatchScanTimePosition);
+    }
+
+    /**
+     * Retrieves elements of the stats array layout from <code>extras</code>
+     */
+    public void fromExtras(PersistableBundle extras) {
+        super.fromExtras(extras);
+        mPowerReportingSupported = extras.getBoolean(EXTRA_POWER_REPORTING_SUPPORTED);
+        mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
+        mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
+        mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+        mDeviceBasicScanTimePosition = extras.getInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION);
+        mDeviceBatchedScanTimePosition = extras.getInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION);
+        mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+        mDeviceActiveTimePosition = extras.getInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION);
+        mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+        mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+        mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
+        mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
+        mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
+        mUidBatchScanTimePosition = extras.getInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION);
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
new file mode 100644
index 0000000..5e9cc40
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import android.util.Slog;
+
+import com.android.internal.os.PowerProfile;
+import com.android.internal.os.PowerStats;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class WifiPowerStatsProcessor extends PowerStatsProcessor {
+    private static final String TAG = "WifiPowerStatsProcessor";
+    private static final boolean DEBUG = false;
+
+    private final UsageBasedPowerEstimator mRxPowerEstimator;
+    private final UsageBasedPowerEstimator mTxPowerEstimator;
+    private final UsageBasedPowerEstimator mIdlePowerEstimator;
+
+    private final UsageBasedPowerEstimator mActivePowerEstimator;
+    private final UsageBasedPowerEstimator mScanPowerEstimator;
+    private final UsageBasedPowerEstimator mBatchedScanPowerEstimator;
+
+    private PowerStats.Descriptor mLastUsedDescriptor;
+    private WifiPowerStatsLayout mStatsLayout;
+    // Sequence of steps for power estimation and intermediate results.
+    private PowerEstimationPlan mPlan;
+
+    private long[] mTmpDeviceStatsArray;
+    private long[] mTmpUidStatsArray;
+    private boolean mHasWifiPowerController;
+
+    public WifiPowerStatsProcessor(PowerProfile powerProfile) {
+        mRxPowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX));
+        mTxPowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX));
+        mIdlePowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE));
+        mActivePowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE));
+        mScanPowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN));
+        mBatchedScanPowerEstimator = new UsageBasedPowerEstimator(
+                powerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN));
+    }
+
+    private static class Intermediates {
+        /**
+         * Estimated power for the RX state.
+         */
+        public double rxPower;
+        /**
+         * Estimated power for the TX state.
+         */
+        public double txPower;
+        /**
+         * Estimated power in the SCAN state
+         */
+        public double scanPower;
+        /**
+         * Estimated power for IDLE, SCAN states.
+         */
+        public double idlePower;
+        /**
+         * Number of received packets
+         */
+        public long rxPackets;
+        /**
+         * Number of transmitted packets
+         */
+        public long txPackets;
+        /**
+         * Total duration of unbatched scans across all UIDs.
+         */
+        public long basicScanDuration;
+        /**
+         * Estimated power in the unbatched SCAN state
+         */
+        public double basicScanPower;
+        /**
+         * Total duration of batched scans across all UIDs.
+         */
+        public long batchedScanDuration;
+        /**
+         * Estimated power in the BATCHED SCAN state
+         */
+        public double batchedScanPower;
+        /**
+         * Estimated total power when active; used only in the absence of WiFiManager power
+         * reporting.
+         */
+        public double activePower;
+        /**
+         * Measured consumed energy from power monitoring hardware (micro-coulombs)
+         */
+        public long consumedEnergy;
+    }
+
+    @Override
+    void finish(PowerComponentAggregatedPowerStats stats) {
+        if (stats.getPowerStatsDescriptor() == null) {
+            return;
+        }
+
+        unpackPowerStatsDescriptor(stats.getPowerStatsDescriptor());
+
+        if (mPlan == null) {
+            mPlan = new PowerEstimationPlan(stats.getConfig());
+        }
+
+        for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+            DeviceStateEstimation estimation = mPlan.deviceStateEstimations.get(i);
+            Intermediates intermediates = new Intermediates();
+            estimation.intermediates = intermediates;
+            computeDevicePowerEstimates(stats, estimation.stateValues, intermediates);
+        }
+
+        double ratio = 1.0;
+        if (mStatsLayout.getEnergyConsumerCount() != 0) {
+            ratio = computeEstimateAdjustmentRatioUsingConsumedEnergy();
+            if (ratio != 1) {
+                for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+                    DeviceStateEstimation estimation = mPlan.deviceStateEstimations.get(i);
+                    adjustDevicePowerEstimates(stats, estimation.stateValues,
+                            (Intermediates) estimation.intermediates, ratio);
+                }
+            }
+        }
+
+        combineDeviceStateEstimates();
+
+        ArrayList<Integer> uids = new ArrayList<>();
+        stats.collectUids(uids);
+        if (!uids.isEmpty()) {
+            for (int uid : uids) {
+                for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+                    computeUidActivityTotals(stats, uid, mPlan.uidStateEstimates.get(i));
+                }
+            }
+
+            for (int uid : uids) {
+                for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+                    computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(i));
+                }
+            }
+        }
+        mPlan.resetIntermediates();
+    }
+
+    private void unpackPowerStatsDescriptor(PowerStats.Descriptor descriptor) {
+        if (descriptor.equals(mLastUsedDescriptor)) {
+            return;
+        }
+
+        mLastUsedDescriptor = descriptor;
+        mStatsLayout = new WifiPowerStatsLayout(descriptor);
+        mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
+        mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
+        mHasWifiPowerController = mStatsLayout.isPowerReportingSupported();
+    }
+
+    /**
+     * Compute power estimates using the power profile.
+     */
+    private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
+            int[] deviceStates, Intermediates intermediates) {
+        if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStates)) {
+            return;
+        }
+
+        for (int i = mStatsLayout.getEnergyConsumerCount() - 1; i >= 0; i--) {
+            intermediates.consumedEnergy += mStatsLayout.getConsumedEnergy(mTmpDeviceStatsArray, i);
+        }
+
+        intermediates.basicScanDuration =
+                mStatsLayout.getDeviceBasicScanTime(mTmpDeviceStatsArray);
+        intermediates.batchedScanDuration =
+                mStatsLayout.getDeviceBatchedScanTime(mTmpDeviceStatsArray);
+        if (mHasWifiPowerController) {
+            intermediates.rxPower = mRxPowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceRxTime(mTmpDeviceStatsArray));
+            intermediates.txPower = mTxPowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceTxTime(mTmpDeviceStatsArray));
+            intermediates.scanPower = mScanPowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceScanTime(mTmpDeviceStatsArray));
+            intermediates.idlePower = mIdlePowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceIdleTime(mTmpDeviceStatsArray));
+            mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
+                    intermediates.rxPower + intermediates.txPower + intermediates.scanPower
+                            + intermediates.idlePower);
+        } else {
+            intermediates.activePower = mActivePowerEstimator.calculatePower(
+                    mStatsLayout.getDeviceActiveTime(mTmpDeviceStatsArray));
+            intermediates.basicScanPower =
+                    mScanPowerEstimator.calculatePower(intermediates.basicScanDuration);
+            intermediates.batchedScanPower =
+                    mBatchedScanPowerEstimator.calculatePower(intermediates.batchedScanDuration);
+            mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
+                    intermediates.activePower + intermediates.basicScanPower
+                            + intermediates.batchedScanPower);
+        }
+
+        stats.setDeviceStats(deviceStates, mTmpDeviceStatsArray);
+    }
+
+    /**
+     * Compute an adjustment ratio using the total power estimated using the power profile
+     * and the total power measured by hardware.
+     */
+    private double computeEstimateAdjustmentRatioUsingConsumedEnergy() {
+        long totalConsumedEnergy = 0;
+        double totalPower = 0;
+
+        for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+            Intermediates intermediates =
+                    (Intermediates) mPlan.deviceStateEstimations.get(i).intermediates;
+            if (mHasWifiPowerController) {
+                totalPower += intermediates.rxPower + intermediates.txPower
+                        + intermediates.scanPower + intermediates.idlePower;
+            } else {
+                totalPower += intermediates.activePower + intermediates.basicScanPower
+                        + intermediates.batchedScanPower;
+            }
+            totalConsumedEnergy += intermediates.consumedEnergy;
+        }
+
+        if (totalPower == 0) {
+            return 1;
+        }
+
+        return uCtoMah(totalConsumedEnergy) / totalPower;
+    }
+
+    /**
+     * Uniformly apply the same adjustment to all power estimates in order to ensure that the total
+     * estimated power matches the measured consumed power.  We are not claiming that all
+     * averages captured in the power profile have to be off by the same percentage in reality.
+     */
+    private void adjustDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
+            int[] deviceStates, Intermediates intermediates, double ratio) {
+        double adjutedPower;
+        if (mHasWifiPowerController) {
+            intermediates.rxPower *= ratio;
+            intermediates.txPower *= ratio;
+            intermediates.scanPower *= ratio;
+            intermediates.idlePower *= ratio;
+            adjutedPower = intermediates.rxPower + intermediates.txPower + intermediates.scanPower
+                    + intermediates.idlePower;
+        } else {
+            intermediates.activePower *= ratio;
+            intermediates.basicScanPower *= ratio;
+            intermediates.batchedScanPower *= ratio;
+            adjutedPower = intermediates.activePower + intermediates.basicScanPower
+                    + intermediates.batchedScanPower;
+        }
+
+        if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStates)) {
+            return;
+        }
+
+        mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, adjutedPower);
+        stats.setDeviceStats(deviceStates, mTmpDeviceStatsArray);
+    }
+
+    /**
+     * Combine power estimates before distributing them proportionally to UIDs.
+     */
+    private void combineDeviceStateEstimates() {
+        for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
+            CombinedDeviceStateEstimate cdse = mPlan.combinedDeviceStateEstimations.get(i);
+            Intermediates
+                    cdseIntermediates = new Intermediates();
+            cdse.intermediates = cdseIntermediates;
+            List<DeviceStateEstimation> deviceStateEstimations = cdse.deviceStateEstimations;
+            for (int j = deviceStateEstimations.size() - 1; j >= 0; j--) {
+                DeviceStateEstimation dse = deviceStateEstimations.get(j);
+                Intermediates intermediates = (Intermediates) dse.intermediates;
+                if (mHasWifiPowerController) {
+                    cdseIntermediates.rxPower += intermediates.rxPower;
+                    cdseIntermediates.txPower += intermediates.txPower;
+                    cdseIntermediates.scanPower += intermediates.scanPower;
+                    cdseIntermediates.idlePower += intermediates.idlePower;
+                } else {
+                    cdseIntermediates.activePower += intermediates.activePower;
+                    cdseIntermediates.basicScanPower += intermediates.basicScanPower;
+                    cdseIntermediates.batchedScanPower += intermediates.batchedScanPower;
+                }
+                cdseIntermediates.basicScanDuration += intermediates.basicScanDuration;
+                cdseIntermediates.batchedScanDuration += intermediates.batchedScanDuration;
+                cdseIntermediates.consumedEnergy += intermediates.consumedEnergy;
+            }
+        }
+    }
+
+    private void computeUidActivityTotals(PowerComponentAggregatedPowerStats stats, int uid,
+            UidStateEstimate uidStateEstimate) {
+        Intermediates intermediates =
+                (Intermediates) uidStateEstimate.combinedDeviceStateEstimate.intermediates;
+        for (UidStateProportionalEstimate proportionalEstimate :
+                uidStateEstimate.proportionalEstimates) {
+            if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+                continue;
+            }
+
+            intermediates.rxPackets += mStatsLayout.getUidRxPackets(mTmpUidStatsArray);
+            intermediates.txPackets += mStatsLayout.getUidTxPackets(mTmpUidStatsArray);
+        }
+    }
+
+    private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats, int uid,
+            UidStateEstimate uidStateEstimate) {
+        Intermediates intermediates =
+                (Intermediates) uidStateEstimate.combinedDeviceStateEstimate.intermediates;
+        for (UidStateProportionalEstimate proportionalEstimate :
+                uidStateEstimate.proportionalEstimates) {
+            if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+                continue;
+            }
+
+            double power = 0;
+            if (mHasWifiPowerController) {
+                if (intermediates.rxPackets != 0) {
+                    power += intermediates.rxPower * mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+                            / intermediates.rxPackets;
+                }
+                if (intermediates.txPackets != 0) {
+                    power += intermediates.txPower * mStatsLayout.getUidTxPackets(mTmpUidStatsArray)
+                            / intermediates.txPackets;
+                }
+                long totalScanDuration =
+                        intermediates.basicScanDuration + intermediates.batchedScanDuration;
+                if (totalScanDuration != 0) {
+                    long scanDuration = mStatsLayout.getUidScanTime(mTmpUidStatsArray)
+                            + mStatsLayout.getUidBatchedScanTime(mTmpUidStatsArray);
+                    power += intermediates.scanPower * scanDuration / totalScanDuration;
+                }
+            } else {
+                long totalPackets = intermediates.rxPackets + intermediates.txPackets;
+                if (totalPackets != 0) {
+                    long packets = mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+                            + mStatsLayout.getUidTxPackets(mTmpUidStatsArray);
+                    power += intermediates.activePower * packets / totalPackets;
+                }
+
+                if (intermediates.basicScanDuration != 0) {
+                    long scanDuration = mStatsLayout.getUidScanTime(mTmpUidStatsArray);
+                    power += intermediates.basicScanPower * scanDuration
+                            / intermediates.basicScanDuration;
+                }
+
+                if (intermediates.batchedScanDuration != 0) {
+                    long batchedScanDuration = mStatsLayout.getUidBatchedScanTime(
+                            mTmpUidStatsArray);
+                    power += intermediates.batchedScanPower * batchedScanDuration
+                            / intermediates.batchedScanDuration;
+                }
+            }
+            mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+            stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+
+            if (DEBUG) {
+                Slog.d(TAG, "UID: " + uid
+                        + " states: " + Arrays.toString(proportionalEstimate.stateValues)
+                        + " stats: " + Arrays.toString(mTmpUidStatsArray)
+                        + " rx: " + mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+                        + " rx-power: " + intermediates.rxPower
+                        + " rx-packets: " + intermediates.rxPackets
+                        + " tx: " + mStatsLayout.getUidTxPackets(mTmpUidStatsArray)
+                        + " tx-power: " + intermediates.txPower
+                        + " tx-packets: " + intermediates.txPackets
+                        + " power: " + power);
+            }
+        }
+    }
+
+    @Override
+    String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        if (mHasWifiPowerController) {
+            return "rx: " + mStatsLayout.getDeviceRxTime(stats)
+                    + " tx: " + mStatsLayout.getDeviceTxTime(stats)
+                    + " scan: " + mStatsLayout.getDeviceScanTime(stats)
+                    + " idle: " + mStatsLayout.getDeviceIdleTime(stats)
+                    + " power: " + mStatsLayout.getDevicePowerEstimate(stats);
+        } else {
+            return "active: " + mStatsLayout.getDeviceActiveTime(stats)
+                    + " scan: " + mStatsLayout.getDeviceBasicScanTime(stats)
+                    + " batched-scan: " + mStatsLayout.getDeviceBatchedScanTime(stats)
+                    + " power: " + mStatsLayout.getDevicePowerEstimate(stats);
+        }
+    }
+
+    @Override
+    String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats) {
+        // Unsupported for this power component
+        return null;
+    }
+
+    @Override
+    String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+        unpackPowerStatsDescriptor(descriptor);
+        return "rx: " + mStatsLayout.getUidRxPackets(stats)
+                + " tx: " + mStatsLayout.getUidTxPackets(stats)
+                + " scan: " + mStatsLayout.getUidScanTime(stats)
+                + " batched-scan: " + mStatsLayout.getUidBatchedScanTime(stats)
+                + " power: " + mStatsLayout.getUidPowerEstimate(stats);
+    }
+}
diff --git a/services/core/java/com/android/server/power/stats/flags.aconfig b/services/core/java/com/android/server/power/stats/flags.aconfig
index c42ccea..9283fe9 100644
--- a/services/core/java/com/android/server/power/stats/flags.aconfig
+++ b/services/core/java/com/android/server/power/stats/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.power.optimization"
+container: "system"
 
 flag {
     name: "power_monitor_api"
@@ -29,3 +30,10 @@
     description: "Feature flag for streamlined connectivity battery stats"
     bug: "323970018"
 }
+
+flag {
+    name: "streamlined_misc_battery_stats"
+    namespace: "backstage_power"
+    description: "Feature flag for streamlined misc (excluding CPU, Cell, Wifi, BT) battery stats"
+    bug: "333941740"
+}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 9f0a975..8f99d28 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -568,23 +568,25 @@
             int index = 0;
 
             Channel[] channels = getEnergyMeterInfo();
-            for (Channel channel : channels) {
-                PowerMonitor monitor = new PowerMonitor(index++,
-                        PowerMonitor.POWER_MONITOR_TYPE_MEASUREMENT,
-                        getChannelName(channel));
-                monitors.add(monitor);
-                states.add(new PowerMonitorState(monitor, channel.id));
+            if (channels != null) {
+                for (Channel channel : channels) {
+                    PowerMonitor monitor = new PowerMonitor(index++,
+                            PowerMonitor.POWER_MONITOR_TYPE_MEASUREMENT,
+                            getChannelName(channel));
+                    monitors.add(monitor);
+                    states.add(new PowerMonitorState(monitor, channel.id));
+                }
             }
-
             EnergyConsumer[] energyConsumers = getEnergyConsumerInfo();
-            for (EnergyConsumer consumer : energyConsumers) {
-                PowerMonitor monitor = new PowerMonitor(index++,
-                        PowerMonitor.POWER_MONITOR_TYPE_CONSUMER,
-                        getEnergyConsumerName(consumer, energyConsumers));
-                monitors.add(monitor);
-                states.add(new PowerMonitorState(monitor, consumer.id));
+            if (energyConsumers != null) {
+                for (EnergyConsumer consumer : energyConsumers) {
+                    PowerMonitor monitor = new PowerMonitor(index++,
+                            PowerMonitor.POWER_MONITOR_TYPE_CONSUMER,
+                            getEnergyConsumerName(consumer, energyConsumers));
+                    monitors.add(monitor);
+                    states.add(new PowerMonitorState(monitor, consumer.id));
+                }
             }
-
             mPowerMonitors = monitors.toArray(new PowerMonitor[monitors.size()]);
             mPowerMonitorStates = states.toArray(new PowerMonitorState[monitors.size()]);
         }
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 3c0547e..c24240b 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -30,6 +30,7 @@
 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.apex.CompressedApexInfo;
 import android.apex.CompressedApexInfoList;
 import android.content.Context;
@@ -37,6 +38,7 @@
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.hardware.boot.IBootControl;
+import android.hardware.security.secretkeeper.ISecretkeeper;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.os.Binder;
@@ -52,6 +54,7 @@
 import android.os.ShellCallback;
 import android.os.SystemProperties;
 import android.provider.DeviceConfig;
+import android.security.AndroidKeyStoreMaintenance;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.FastImmutableArraySet;
@@ -68,6 +71,7 @@
 import com.android.server.Watchdog;
 import com.android.server.pm.ApexManager;
 import com.android.server.recoverysystem.hal.BootControlHIDL;
+import com.android.server.utils.Slogf;
 
 import libcore.io.IoUtils;
 
@@ -122,6 +126,8 @@
     static final String LSKF_CAPTURED_TIMESTAMP_PREF = "lskf_captured_timestamp";
     static final String LSKF_CAPTURED_COUNT_PREF = "lskf_captured_count";
 
+    static final String RECOVERY_WIPE_DATA_COMMAND = "--wipe_data";
+
     private final Injector mInjector;
     private final Context mContext;
 
@@ -525,18 +531,57 @@
     @Override // Binder call
     public void rebootRecoveryWithCommand(String command) {
         if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
+
+        boolean isForcedWipe = command != null && command.contains(RECOVERY_WIPE_DATA_COMMAND);
         synchronized (sRequestLock) {
             if (!setupOrClearBcb(true, command)) {
                 Slog.e(TAG, "rebootRecoveryWithCommand failed to setup BCB");
                 return;
             }
 
+            if (isForcedWipe) {
+                deleteSecrets();
+                // TODO: consider adding a dedicated forced-wipe-reboot method to PowerManager and
+                // calling here.
+            }
+
             // Having set up the BCB, go ahead and reboot.
             PowerManager pm = mInjector.getPowerManager();
             pm.reboot(PowerManager.REBOOT_RECOVERY);
         }
     }
 
+    private static void deleteSecrets() {
+        Slogf.w(TAG, "deleteSecrets");
+        try {
+            AndroidKeyStoreMaintenance.deleteAllKeys();
+        } catch (android.security.KeyStoreException e) {
+            Log.wtf(TAG, "Failed to delete all keys from keystore.", e);
+        }
+
+        try {
+            ISecretkeeper secretKeeper = getSecretKeeper();
+            if (secretKeeper != null) {
+                Slogf.i(TAG, "ISecretkeeper.deleteAll();");
+                secretKeeper.deleteAll();
+            }
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Failed to delete all secrets from secretkeeper.", e);
+        }
+    }
+
+    private static @Nullable ISecretkeeper getSecretKeeper() {
+        ISecretkeeper result = null;
+        try {
+            result = ISecretkeeper.Stub.asInterface(
+                ServiceManager.waitForDeclaredService(ISecretkeeper.DESCRIPTOR + "/default"));
+        } catch (SecurityException e) {
+            Slog.w(TAG, "Does not have permissions to get AIDL secretkeeper service");
+        }
+
+        return result;
+    }
+
     private void enforcePermissionForResumeOnReboot() {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
                 != PackageManager.PERMISSION_GRANTED
diff --git a/services/core/java/com/android/server/rollback/README.md b/services/core/java/com/android/server/rollback/README.md
index f6bcbd0..a38315c 100644
--- a/services/core/java/com/android/server/rollback/README.md
+++ b/services/core/java/com/android/server/rollback/README.md
@@ -203,6 +203,15 @@
 $ adb install --enable-rollback 1 FooV2.apk
 ```
 
+### Setting Rollback Impact Level
+
+The `adb install` command accepts the `--rollback-impact-level [0/1/2]` flag to control
+when a rollback can be performed by `PackageWatchdog`.
+
+The default rollback impact level is `ROLLBACK_USER_IMPACT_LOW` (0). To use a
+different impact level, use `ROLLBACK_USER_IMPACT_HIGH` (1) or `ROLLBACK_USER_IMPACT_ONLY_MANUAL`
+(2).
+
 ### Triggering Rollback Manually
 
 If rollback is available for an application, the pm command can be used to
@@ -225,6 +234,8 @@
 469808841:
   -state: committed
   -timestamp: 2019-04-23T14:57:35.944Z
+  -rollbackLifetimeMillis: 0
+  -rollbackUserImpact: 1
   -packages:
     com.android.tests.rollback.testapp.B 2 -> 1 [0]
   -causePackages:
@@ -232,6 +243,8 @@
 649899517:
   -state: committed
   -timestamp: 2019-04-23T12:55:21.342Z
+  -rollbackLifetimeMillis: 0
+  -rollbackUserImpact: 0
   -stagedSessionId: 343374391
   -packages:
     com.android.tests.rollback.testapex 2 -> 1 [0]
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index d1f91c8..8f39ffb 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -27,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.Flags;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -960,6 +961,9 @@
         ipw.println("-stateDescription: " + mStateDescription);
         ipw.println("-timestamp: " + getTimestamp());
         ipw.println("-rollbackLifetimeMillis: " + getRollbackLifetimeMillis());
+        if (Flags.recoverabilityDetection()) {
+            ipw.println("-rollbackImpactLevel: " + info.getRollbackImpactLevel());
+        }
         ipw.println("-isStaged: " + isStaged());
         ipw.println("-originalSessionId: " + getOriginalSessionId());
         ipw.println("-packages:");
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 2a93255..c8bcc51 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -54,8 +54,10 @@
 import android.os.UserManager;
 import android.os.ext.SdkExtensions;
 import android.provider.DeviceConfig;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LongArrayQueue;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
@@ -173,6 +175,8 @@
     // Accessed on the handler thread only.
     private long  mRelativeBootTime = calculateRelativeBootTime();
 
+    private final ArrayMap<Integer, Pair<Context, BroadcastReceiver>> mUserBroadcastReceivers;
+
     RollbackManagerServiceImpl(Context context) {
         mContext = context;
         // Note that we're calling onStart here because this object is only constructed on
@@ -210,6 +214,8 @@
             }
         });
 
+        mUserBroadcastReceivers = new ArrayMap<>();
+
         UserManager userManager = mContext.getSystemService(UserManager.class);
         for (UserHandle user : userManager.getUserHandles(true)) {
             registerUserCallbacks(user);
@@ -275,7 +281,9 @@
             }
         }, enableRollbackTimedOutFilter, null, getHandler());
 
-        IntentFilter userAddedIntentFilter = new IntentFilter(Intent.ACTION_USER_ADDED);
+        IntentFilter userIntentFilter = new IntentFilter();
+        userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
+        userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
@@ -287,9 +295,15 @@
                         return;
                     }
                     registerUserCallbacks(UserHandle.of(newUserId));
+                } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+                    final int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                    if (newUserId == -1) {
+                        return;
+                    }
+                    unregisterUserCallbacks(UserHandle.of(newUserId));
                 }
             }
-        }, userAddedIntentFilter, null, getHandler());
+        }, userIntentFilter, null, getHandler());
 
         registerTimeChangeReceiver();
     }
@@ -335,7 +349,7 @@
         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
         filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
         filter.addDataScheme("package");
-        context.registerReceiver(new BroadcastReceiver() {
+        BroadcastReceiver receiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 assertInWorkerThread();
@@ -354,7 +368,21 @@
                     onPackageFullyRemoved(packageName);
                 }
             }
-        }, filter, null, getHandler());
+        };
+        context.registerReceiver(receiver, filter, null, getHandler());
+        mUserBroadcastReceivers.put(user.getIdentifier(), new Pair(context, receiver));
+    }
+
+    @AnyThread
+    private void unregisterUserCallbacks(UserHandle user) {
+        Pair<Context, BroadcastReceiver> pair = mUserBroadcastReceivers.get(user.getIdentifier());
+        if (pair == null || pair.first == null || pair.second == null) {
+            Slog.e(TAG, "No receiver found for the user" + user);
+            return;
+        }
+
+        pair.first.unregisterReceiver(pair.second);
+        mUserBroadcastReceivers.remove(user.getIdentifier());
     }
 
     @ExtThread
diff --git a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
similarity index 100%
rename from packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
rename to services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
diff --git a/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
similarity index 100%
rename from packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java
rename to services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index bb4876b..587be07 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.security;
 
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
@@ -27,6 +28,7 @@
 import android.os.Environment;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.PermissionEnforcer;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
@@ -79,7 +81,11 @@
         return LocalServices.getService(FileIntegrityService.class);
     }
 
-    private final IBinder mService = new IFileIntegrityService.Stub() {
+    private final class BinderService extends IFileIntegrityService.Stub {
+        BinderService(Context context) {
+            super(PermissionEnforcer.fromContext(context));
+        }
+
         @Override
         public boolean isApkVeritySupported() {
             return VerityUtils.isFsVeritySupported();
@@ -168,8 +174,10 @@
         }
 
         @Override
+        @EnforcePermission(android.Manifest.permission.SETUP_FSVERITY)
         public int setupFsverity(android.os.IInstalld.IFsveritySetupAuthToken authToken,
                 String filePath, String packageName) throws RemoteException {
+            setupFsverity_enforcePermission();
             Objects.requireNonNull(authToken);
             Objects.requireNonNull(filePath);
             Objects.requireNonNull(packageName);
@@ -181,10 +189,12 @@
                 throw new RemoteException(e);
             }
         }
-    };
+    }
+    private final IBinder mService;
 
     public FileIntegrityService(final Context context) {
         super(context);
+        mService = new BinderService(context);
         try {
             sCertFactory = CertificateFactory.getInstance("X.509");
         } catch (CertificateException e) {
diff --git a/services/core/java/com/android/server/selinux/QuotaLimiter.java b/services/core/java/com/android/server/selinux/QuotaLimiter.java
index e89ddfd..34d18ce 100644
--- a/services/core/java/com/android/server/selinux/QuotaLimiter.java
+++ b/services/core/java/com/android/server/selinux/QuotaLimiter.java
@@ -34,10 +34,10 @@
 
     private final Clock mClock;
     private final Duration mWindowSize;
-    private final int mMaxPermits;
 
-    private long mCurrentWindow = 0;
-    private int mPermitsGranted = 0;
+    private int mMaxPermits;
+    private long mCurrentWindow;
+    private int mPermitsGranted;
 
     @VisibleForTesting
     QuotaLimiter(Clock clock, Duration windowSize, int maxPermits) {
@@ -75,4 +75,8 @@
 
         return false;
     }
+
+    public void setMaxPermits(int maxPermits) {
+        this.mMaxPermits = maxPermits;
+    }
 }
diff --git a/services/core/java/com/android/server/selinux/SelinuxAuditLogBuilder.java b/services/core/java/com/android/server/selinux/SelinuxAuditLogBuilder.java
index 8d8d596..d69150d 100644
--- a/services/core/java/com/android/server/selinux/SelinuxAuditLogBuilder.java
+++ b/services/core/java/com/android/server/selinux/SelinuxAuditLogBuilder.java
@@ -15,35 +15,66 @@
  */
 package com.android.server.selinux;
 
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Optional;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 import java.util.stream.Stream;
 
 /** Builder for SelinuxAuditLogs. */
 class SelinuxAuditLogBuilder {
 
-    // Currently logs collection is hardcoded for the sdk_sandbox_audit.
-    private static final String SDK_SANDBOX_AUDIT = "sdk_sandbox_audit";
-    static final Matcher SCONTEXT_MATCHER =
-            Pattern.compile(
-                            "u:r:(?<stype>"
-                                    + SDK_SANDBOX_AUDIT
-                                    + "):s0(:c)?(?<scategories>((,c)?\\d+)+)*")
-                    .matcher("");
+    private static final String TAG = "SelinuxAuditLogs";
 
-    static final Matcher TCONTEXT_MATCHER =
-            Pattern.compile("u:object_r:(?<ttype>\\w+):s0(:c)?(?<tcategories>((,c)?\\d+)+)*")
-                    .matcher("");
+    // This config indicates which Selinux logs for source domains to collect. The string will be
+    // inserted into a regex, so it must follow the regex syntax. For example, a valid value would
+    // be "system_server|untrusted_app".
+    @VisibleForTesting static final String CONFIG_SELINUX_AUDIT_DOMAIN = "selinux_audit_domain";
+    private static final Matcher NO_OP_MATCHER = Pattern.compile("no-op^").matcher("");
+    private static final String TCONTEXT_PATTERN =
+            "u:object_r:(?<ttype>\\w+):s0(:c)?(?<tcategories>((,c)?\\d+)+)*";
+    private static final String PATH_PATTERN = "\"(?<path>/\\w+(/\\w+)?)(/\\w+)*\"";
 
-    static final Matcher PATH_MATCHER =
-            Pattern.compile("\"(?<path>/\\w+(/\\w+)?)(/\\w+)*\"").matcher("");
+    @VisibleForTesting final Matcher mScontextMatcher;
+    @VisibleForTesting final Matcher mTcontextMatcher;
+    @VisibleForTesting final Matcher mPathMatcher;
 
     private Iterator<String> mTokens;
     private final SelinuxAuditLog mAuditLog = new SelinuxAuditLog();
 
+    SelinuxAuditLogBuilder() {
+        Matcher scontextMatcher = NO_OP_MATCHER;
+        Matcher tcontextMatcher = NO_OP_MATCHER;
+        Matcher pathMatcher = NO_OP_MATCHER;
+        try {
+            scontextMatcher =
+                    Pattern.compile(
+                                    TextUtils.formatSimple(
+                                            "u:r:(?<stype>%s):s0(:c)?(?<scategories>((,c)?\\d+)+)*",
+                                            DeviceConfig.getString(
+                                                    DeviceConfig.NAMESPACE_ADSERVICES,
+                                                    CONFIG_SELINUX_AUDIT_DOMAIN,
+                                                    "no_match^")))
+                            .matcher("");
+            tcontextMatcher = Pattern.compile(TCONTEXT_PATTERN).matcher("");
+            pathMatcher = Pattern.compile(PATH_PATTERN).matcher("");
+        } catch (PatternSyntaxException e) {
+            Slog.e(TAG, "Invalid pattern, setting every matcher to no-op.", e);
+        }
+
+        mScontextMatcher = scontextMatcher;
+        mTcontextMatcher = tcontextMatcher;
+        mPathMatcher = pathMatcher;
+    }
+
     void reset(String denialString) {
         mTokens =
                 Arrays.asList(
@@ -82,18 +113,18 @@
                     mAuditLog.mPermissions = permissionsStream.build().toArray(String[]::new);
                     break;
                 case "scontext":
-                    if (!nextTokenMatches(SCONTEXT_MATCHER)) {
+                    if (!nextTokenMatches(mScontextMatcher)) {
                         return null;
                     }
-                    mAuditLog.mSType = SCONTEXT_MATCHER.group("stype");
-                    mAuditLog.mSCategories = toCategories(SCONTEXT_MATCHER.group("scategories"));
+                    mAuditLog.mSType = mScontextMatcher.group("stype");
+                    mAuditLog.mSCategories = toCategories(mScontextMatcher.group("scategories"));
                     break;
                 case "tcontext":
-                    if (!nextTokenMatches(TCONTEXT_MATCHER)) {
+                    if (!nextTokenMatches(mTcontextMatcher)) {
                         return null;
                     }
-                    mAuditLog.mTType = TCONTEXT_MATCHER.group("ttype");
-                    mAuditLog.mTCategories = toCategories(TCONTEXT_MATCHER.group("tcategories"));
+                    mAuditLog.mTType = mTcontextMatcher.group("ttype");
+                    mAuditLog.mTCategories = toCategories(mTcontextMatcher.group("tcategories"));
                     break;
                 case "tclass":
                     if (!mTokens.hasNext()) {
@@ -102,8 +133,8 @@
                     mAuditLog.mTClass = mTokens.next();
                     break;
                 case "path":
-                    if (nextTokenMatches(PATH_MATCHER)) {
-                        mAuditLog.mPath = PATH_MATCHER.group("path");
+                    if (nextTokenMatches(mPathMatcher)) {
+                        mAuditLog.mPath = mPathMatcher.group("path");
                     }
                     break;
                 case "permissive":
diff --git a/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java b/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java
index 03822aa..c655d46 100644
--- a/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java
+++ b/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java
@@ -18,10 +18,12 @@
 import android.util.EventLog;
 import android.util.EventLog.Event;
 import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.selinux.SelinuxAuditLogBuilder.SelinuxAuditLog;
+import com.android.server.utils.Slogf;
 
 import java.io.IOException;
 import java.time.Instant;
@@ -37,6 +39,7 @@
 class SelinuxAuditLogsCollector {
 
     private static final String TAG = "SelinuxAuditLogs";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String SELINUX_PATTERN = "^.*\\bavc:\\s+(?<denial>.*)$";
 
@@ -48,13 +51,17 @@
 
     @VisibleForTesting Instant mLastWrite = Instant.MIN;
 
-    final AtomicBoolean mStopRequested = new AtomicBoolean(false);
+    AtomicBoolean mStopRequested = new AtomicBoolean(false);
 
     SelinuxAuditLogsCollector(RateLimiter rateLimiter, QuotaLimiter quotaLimiter) {
         mRateLimiter = rateLimiter;
         mQuotaLimiter = quotaLimiter;
     }
 
+    public void setStopRequested(boolean stopRequested) {
+        mStopRequested.set(stopRequested);
+    }
+
     /**
      * Collect and push SELinux audit logs for the provided {@code tagCode}.
      *
@@ -66,7 +73,7 @@
 
         boolean quotaExceeded = writeAuditLogs(logLines);
         if (quotaExceeded) {
-            Log.w(TAG, "Too many SELinux logs in the queue, I am giving up.");
+            Slog.w(TAG, "Too many SELinux logs in the queue, I am giving up.");
             mLastWrite = latestTimestamp; // next run we will ignore all these logs.
             logLines.clear();
         }
@@ -79,7 +86,7 @@
         try {
             EventLog.readEvents(new int[] {tagCode}, events);
         } catch (IOException e) {
-            Log.e(TAG, "Error reading event logs", e);
+            Slog.e(TAG, "Error reading event logs", e);
         }
 
         Instant latestTimestamp = mLastWrite;
@@ -102,6 +109,7 @@
 
     private boolean writeAuditLogs(Queue<Event> logLines) {
         final SelinuxAuditLogBuilder auditLogBuilder = new SelinuxAuditLogBuilder();
+        int auditsWritten = 0;
 
         while (!mStopRequested.get() && !logLines.isEmpty()) {
             Event event = logLines.poll();
@@ -118,6 +126,9 @@
             }
 
             if (!mQuotaLimiter.acquire()) {
+                if (DEBUG) {
+                    Slogf.d(TAG, "Running out of quota after %d logs.", auditsWritten);
+                }
                 return true;
             }
             mRateLimiter.acquire();
@@ -133,12 +144,16 @@
                     auditLog.mTClass,
                     auditLog.mPath,
                     auditLog.mPermissive);
+            auditsWritten++;
 
             if (logTime.isAfter(mLastWrite)) {
                 mLastWrite = logTime;
             }
         }
 
+        if (DEBUG) {
+            Slogf.d(TAG, "Written %d logs", auditsWritten);
+        }
         return false;
     }
 }
diff --git a/services/core/java/com/android/server/selinux/SelinuxAuditLogsJob.java b/services/core/java/com/android/server/selinux/SelinuxAuditLogsJob.java
new file mode 100644
index 0000000..0092c37
--- /dev/null
+++ b/services/core/java/com/android/server/selinux/SelinuxAuditLogsJob.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.selinux;
+
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.util.Slog;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * This class handles the start and stop requests for the logs collector job, in particular making
+ * sure that at most one job is running at any given moment.
+ */
+final class SelinuxAuditLogsJob {
+
+    private static final String TAG = "SelinuxAuditLogs";
+
+    private final AtomicBoolean mIsRunning = new AtomicBoolean(false);
+    private final SelinuxAuditLogsCollector mAuditLogsCollector;
+
+    SelinuxAuditLogsJob(SelinuxAuditLogsCollector auditLogsCollector) {
+        mAuditLogsCollector = auditLogsCollector;
+    }
+
+    void requestStop() {
+        mAuditLogsCollector.mStopRequested.set(true);
+    }
+
+    boolean isRunning() {
+        return mIsRunning.get();
+    }
+
+    public void start(JobService jobService, JobParameters params) {
+        mAuditLogsCollector.mStopRequested.set(false);
+        if (mIsRunning.get()) {
+            Slog.i(TAG, "Selinux audit job is already running, ignore start request.");
+            return;
+        }
+        mIsRunning.set(true);
+        boolean done = mAuditLogsCollector.collect(SelinuxAuditLogsService.AUDITD_TAG_CODE);
+        if (done) {
+            jobService.jobFinished(params, /* wantsReschedule= */ false);
+        }
+        mIsRunning.set(false);
+    }
+}
diff --git a/services/core/java/com/android/server/selinux/SelinuxAuditLogsService.java b/services/core/java/com/android/server/selinux/SelinuxAuditLogsService.java
index 8a661bc..d46e891 100644
--- a/services/core/java/com/android/server/selinux/SelinuxAuditLogsService.java
+++ b/services/core/java/com/android/server/selinux/SelinuxAuditLogsService.java
@@ -23,14 +23,16 @@
 import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.Context;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
 import android.util.EventLog;
-import android.util.Log;
+import android.util.Slog;
 
 import java.time.Duration;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Scheduled jobs related to logging of SELinux denials and audits. The job runs daily on idle
@@ -43,58 +45,68 @@
 
     static final int AUDITD_TAG_CODE = EventLog.getTagCode("auditd");
 
+    private static final String CONFIG_SELINUX_AUDIT_JOB_FREQUENCY_HOURS =
+            "selinux_audit_job_frequency_hours";
+    private static final String CONFIG_SELINUX_ENABLE_AUDIT_JOB = "selinux_enable_audit_job";
+    private static final String CONFIG_SELINUX_AUDIT_CAP = "selinux_audit_cap";
+    private static final int MAX_PERMITS_CAP_DEFAULT = 50000;
+
     private static final int SELINUX_AUDIT_JOB_ID = 25327386;
-    private static final JobInfo SELINUX_AUDIT_JOB =
-            new JobInfo.Builder(
-                            SELINUX_AUDIT_JOB_ID,
-                            new ComponentName("android", SelinuxAuditLogsService.class.getName()))
-                    .setPeriodic(TimeUnit.DAYS.toMillis(1))
-                    .setRequiresDeviceIdle(true)
-                    .setRequiresCharging(true)
-                    .setRequiresBatteryNotLow(true)
-                    .build();
+    private static final ComponentName SELINUX_AUDIT_JOB_COMPONENT =
+            new ComponentName("android", SelinuxAuditLogsService.class.getName());
 
     private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
-    private static final AtomicReference<Boolean> IS_RUNNING = new AtomicReference<>(false);
 
-    // Audit logging is subject to both rate and quota limiting. We can only push one atom every 10
-    // milliseconds, and no more than 50K atoms can be pushed each day.
-    private static final SelinuxAuditLogsCollector AUDIT_LOGS_COLLECTOR =
-            new SelinuxAuditLogsCollector(
-                    new RateLimiter(/* window= */ Duration.ofMillis(10)),
-                    new QuotaLimiter(/* maxPermitsPerDay= */ 50000));
+    // Audit logging is subject to both rate and quota limiting. A {@link RateLimiter} makes sure
+    // that we push no more than one atom every 10 milliseconds. A {@link QuotaLimiter} caps the
+    // number of atoms pushed per day to CONFIG_SELINUX_AUDIT_CAP. The quota limiter is static
+    // because new job executions happen in a new instance of this class. Making the quota limiter
+    // an instance reference would reset the quota limitations between jobs executions.
+    private static final Duration RATE_LIMITER_WINDOW = Duration.ofMillis(10);
+    private static final QuotaLimiter QUOTA_LIMITER =
+            new QuotaLimiter(
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_ADSERVICES,
+                            CONFIG_SELINUX_AUDIT_CAP,
+                            MAX_PERMITS_CAP_DEFAULT));
+    private static final SelinuxAuditLogsJob LOGS_COLLECTOR_JOB =
+            new SelinuxAuditLogsJob(
+                    new SelinuxAuditLogsCollector(
+                            new RateLimiter(RATE_LIMITER_WINDOW), QUOTA_LIMITER));
 
     /** Schedule jobs with the {@link JobScheduler}. */
     public static void schedule(Context context) {
         if (!selinuxSdkSandboxAudit()) {
-            Log.d(TAG, "SelinuxAuditLogsService not enabled");
+            Slog.d(TAG, "SelinuxAuditLogsService not enabled");
             return;
         }
 
         if (AUDITD_TAG_CODE == -1) {
-            Log.e(TAG, "auditd is not a registered tag on this system");
+            Slog.e(TAG, "auditd is not a registered tag on this system");
             return;
         }
 
-        if (context.getSystemService(JobScheduler.class)
-                        .forNamespace(SELINUX_AUDIT_NAMESPACE)
-                        .schedule(SELINUX_AUDIT_JOB)
-                == JobScheduler.RESULT_FAILURE) {
-            Log.e(TAG, "SelinuxAuditLogsService could not be started.");
-        }
+        LogsCollectorJobScheduler propertiesListener =
+                new LogsCollectorJobScheduler(
+                        context.getSystemService(JobScheduler.class)
+                                .forNamespace(SELINUX_AUDIT_NAMESPACE));
+        propertiesListener.schedule();
+        DeviceConfig.addOnPropertiesChangedListener(
+                DeviceConfig.NAMESPACE_ADSERVICES, context.getMainExecutor(), propertiesListener);
     }
 
     @Override
     public boolean onStartJob(JobParameters params) {
         if (params.getJobId() != SELINUX_AUDIT_JOB_ID) {
-            Log.e(TAG, "The job id does not match the expected selinux job id.");
+            Slog.e(TAG, "The job id does not match the expected selinux job id.");
+            return false;
+        }
+        if (!selinuxSdkSandboxAudit()) {
+            Slog.i(TAG, "Selinux audit job disabled.");
             return false;
         }
 
-        AUDIT_LOGS_COLLECTOR.mStopRequested.set(false);
-        IS_RUNNING.set(true);
-        EXECUTOR_SERVICE.execute(new LogsCollectorJob(this, params));
-
+        EXECUTOR_SERVICE.execute(() -> LOGS_COLLECTOR_JOB.start(this, params));
         return true; // the job is running
     }
 
@@ -104,29 +116,69 @@
             return false;
         }
 
-        AUDIT_LOGS_COLLECTOR.mStopRequested.set(true);
-        return IS_RUNNING.get();
+        if (LOGS_COLLECTOR_JOB.isRunning()) {
+            LOGS_COLLECTOR_JOB.requestStop();
+            return true;
+        }
+        return false;
     }
 
-    private static class LogsCollectorJob implements Runnable {
-        private final JobService mAuditLogService;
-        private final JobParameters mParams;
+    /**
+     * This class is in charge of scheduling the job service, and keeping the scheduling up to date
+     * when the parameters change.
+     */
+    private static final class LogsCollectorJobScheduler
+            implements DeviceConfig.OnPropertiesChangedListener {
 
-        LogsCollectorJob(JobService auditLogService, JobParameters params) {
-            mAuditLogService = auditLogService;
-            mParams = params;
+        private final JobScheduler mJobScheduler;
+
+        private LogsCollectorJobScheduler(JobScheduler jobScheduler) {
+            mJobScheduler = jobScheduler;
         }
 
         @Override
-        public void run() {
-            IS_RUNNING.updateAndGet(
-                    isRunning -> {
-                        boolean done = AUDIT_LOGS_COLLECTOR.collect(AUDITD_TAG_CODE);
-                        if (done) {
-                            mAuditLogService.jobFinished(mParams, /* wantsReschedule= */ false);
-                        }
-                        return !done;
-                    });
+        public void onPropertiesChanged(Properties changedProperties) {
+            Set<String> keyset = changedProperties.getKeyset();
+
+            if (keyset.contains(CONFIG_SELINUX_AUDIT_CAP)) {
+                QUOTA_LIMITER.setMaxPermits(
+                        changedProperties.getInt(
+                                CONFIG_SELINUX_AUDIT_CAP, MAX_PERMITS_CAP_DEFAULT));
+            }
+
+            if (keyset.contains(CONFIG_SELINUX_ENABLE_AUDIT_JOB)) {
+                boolean enabled =
+                        changedProperties.getBoolean(
+                                CONFIG_SELINUX_ENABLE_AUDIT_JOB, /* defaultValue= */ false);
+                if (enabled) {
+                    schedule();
+                } else {
+                    mJobScheduler.cancel(SELINUX_AUDIT_JOB_ID);
+                }
+            } else if (keyset.contains(CONFIG_SELINUX_AUDIT_JOB_FREQUENCY_HOURS)) {
+                // The job frequency changed, reschedule.
+                schedule();
+            }
+        }
+
+        private void schedule() {
+            long frequencyMillis =
+                    TimeUnit.HOURS.toMillis(
+                            DeviceConfig.getInt(
+                                    DeviceConfig.NAMESPACE_ADSERVICES,
+                                    CONFIG_SELINUX_AUDIT_JOB_FREQUENCY_HOURS,
+                                    24));
+            if (mJobScheduler.schedule(
+                            new JobInfo.Builder(SELINUX_AUDIT_JOB_ID, SELINUX_AUDIT_JOB_COMPONENT)
+                                    .setPeriodic(frequencyMillis)
+                                    .setRequiresDeviceIdle(true)
+                                    .setRequiresBatteryNotLow(true)
+                                    .build())
+                    == JobScheduler.RESULT_FAILURE) {
+                Slog.e(TAG, "SelinuxAuditLogsService could not be scheduled.");
+            } else {
+                Slog.d(TAG, "SelinuxAuditLogsService scheduled successfully.");
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/stats/Android.bp b/services/core/java/com/android/server/stats/Android.bp
index e597c3a..f7955e8 100644
--- a/services/core/java/com/android/server/stats/Android.bp
+++ b/services/core/java/com/android/server/stats/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "stats_flags",
     package: "com.android.server.stats",
+    container: "system",
     srcs: [
         "stats_flags.aconfig",
     ],
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b5df30f..e3e478d 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -61,6 +61,7 @@
 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.stats.Flags.addMobileBytesTransferByProcStatePuller;
+import static com.android.server.stats.Flags.statsPullNetworkStatsManagerInitOrderFix;
 import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
 import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines;
@@ -355,7 +356,17 @@
     private TelephonyManager mTelephony;
     private UwbManager mUwbManager;
     private SubscriptionManager mSubscriptionManager;
-    private NetworkStatsManager mNetworkStatsManager;
+
+    /**
+     * NetworkStatsManager initialization happens from one thread before any worker thread
+     * is going to access the networkStatsManager instance:
+     * - @initNetworkStatsManager() - initialization happens no worker thread to access are
+     *   active yet
+     * - @initAndRegisterNetworkStatsPullers Network stats dependant pullers can only be
+     *   initialized after service is ready. Worker thread is spawn here only after the
+     *   initialization is completed in a thread safe way (no async access expected)
+     */
+    private NetworkStatsManager mNetworkStatsManager = null;
 
     @GuardedBy("mKernelWakelockLock")
     private KernelWakelockReader mKernelWakelockReader;
@@ -420,6 +431,12 @@
     public static final boolean ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER =
                 addMobileBytesTransferByProcStatePuller();
 
+    /**
+     * Whether or not to enable the mNetworkStatsManager initialization order fix
+     */
+    private static final boolean ENABLE_NETWORK_STATS_MANAGER_INIT_ORDER_FIX =
+                statsPullNetworkStatsManagerInitOrderFix();
+
     // Puller locks
     private final Object mDataBytesTransferLock = new Object();
     private final Object mBluetoothBytesTransferLock = new Object();
@@ -823,6 +840,9 @@
                 registerEventListeners();
             });
         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            if (ENABLE_NETWORK_STATS_MANAGER_INIT_ORDER_FIX) {
+                initNetworkStatsManager();
+            }
             BackgroundThread.getHandler().post(() -> {
                 // Network stats related pullers can only be initialized after service is ready.
                 initAndRegisterNetworkStatsPullers();
@@ -843,7 +863,9 @@
                 mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager);
         mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
-        mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
+        if (!ENABLE_NETWORK_STATS_MANAGER_INIT_ORDER_FIX) {
+            initNetworkStatsManager();
+        }
 
         // Initialize DiskIO
         mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();
@@ -1019,6 +1041,24 @@
         }
     }
 
+    /**
+     * Calling getNetworkStatsManager() before PHASE_THIRD_PARTY_APPS_CAN_START is unexpected
+     * Callers use before PHASE_THIRD_PARTY_APPS_CAN_START stage is not legit
+     */
+    @NonNull
+    private NetworkStatsManager getNetworkStatsManager() {
+        if (ENABLE_NETWORK_STATS_MANAGER_INIT_ORDER_FIX) {
+            if (mNetworkStatsManager == null) {
+                throw new IllegalStateException("NetworkStatsManager is not ready");
+            }
+        }
+        return mNetworkStatsManager;
+    }
+
+    private void initNetworkStatsManager() {
+        mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
+    }
+
     private void initAndRegisterNetworkStatsPullers() {
         if (DEBUG) {
             Slog.d(TAG, "Registering NetworkStats pullers with statsd");
@@ -1514,11 +1554,11 @@
         //  I/O and also block main thread when polling.
         //  Consider making perfd queries NetworkStatsService directly.
         if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) {
-            mNetworkStatsManager.forceUpdate();
+            getNetworkStatsManager().forceUpdate();
         }
 
         final android.app.usage.NetworkStats queryNonTaggedStats =
-                mNetworkStatsManager.querySummary(
+                getNetworkStatsManager().querySummary(
                         template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                         currentTimeInMillis);
 
@@ -1528,7 +1568,7 @@
         if (!includeTags) return nonTaggedStats;
 
         final android.app.usage.NetworkStats queryTaggedStats =
-                mNetworkStatsManager.queryTaggedSummary(template,
+                getNetworkStatsManager().queryTaggedSummary(template,
                         currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                         currentTimeInMillis);
         final NetworkStats taggedStats =
diff --git a/services/core/java/com/android/server/stats/stats_flags.aconfig b/services/core/java/com/android/server/stats/stats_flags.aconfig
index 5101a69..c479c6d 100644
--- a/services/core/java/com/android/server/stats/stats_flags.aconfig
+++ b/services/core/java/com/android/server/stats/stats_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.stats"
+container: "system"
 
 flag {
     name: "add_mobile_bytes_transfer_by_proc_state_puller"
@@ -6,4 +7,12 @@
     description: "Adds mobile_bytes_transfer_by_proc_state atom with system server side aggregation"
     bug: "309512867"
     is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+    name: "stats_pull_network_stats_manager_init_order_fix"
+    namespace: "statsd"
+    description: "Fix the mNetworkStatsManager initialization order"
+    bug: "331989853"
+    is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 2ff3861..e4f60ec 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -22,6 +22,7 @@
 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowInsetsController.Behavior;
@@ -248,10 +249,10 @@
     /**
      * Shows the media output switcher dialog.
      *
-     * @param packageName of the session for which the output switcher is shown.
+     * @param targetPackageName of the session for which the output switcher is shown.
      * @see com.android.internal.statusbar.IStatusBar#showMediaOutputSwitcher
      */
-    void showMediaOutputSwitcher(String packageName);
+    void showMediaOutputSwitcher(String targetPackageName, UserHandle targetUserHandle);
 
     /**
      * Add a tile to the Quick Settings Panel
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index cca5beb..2c67207 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -850,11 +850,11 @@
         }
 
         @Override
-        public void showMediaOutputSwitcher(String packageName) {
+        public void showMediaOutputSwitcher(String targetPackageName, UserHandle targetUserHandle) {
             IStatusBar bar = mBar;
             if (bar != null) {
                 try {
-                    bar.showMediaOutputSwitcher(packageName);
+                    bar.showMediaOutputSwitcher(targetPackageName, targetUserHandle);
                 } catch (RemoteException ex) {
                 }
             }
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index 58c31d5..ad2c3e8 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -39,6 +39,9 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IUserRestrictionsListener;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -136,9 +139,11 @@
             }
         }, filter, null, null /* main thread */);
 
+        Handler mainThreadHandler = mContext.getMainThreadHandler();
+
         // Add async callbacks for global settings being changed.
         ContentResolver contentResolver = mContext.getContentResolver();
-        ContentObserver contentObserver = new ContentObserver(mContext.getMainThreadHandler()) {
+        ContentObserver contentObserver = new ContentObserver(mainThreadHandler) {
             @Override
             public void onChange(boolean selfChange) {
                 handleConfigurationInternalChangeOnMainThread();
@@ -150,6 +155,20 @@
         // Watch server flags.
         mServerFlags.addListener(this::handleConfigurationInternalChangeOnMainThread,
                 SERVER_FLAGS_KEYS_TO_WATCH);
+
+        // Watch for policy changes that affect what the user is permitted to do.
+        mUserManager.addUserRestrictionsListener(
+                new IUserRestrictionsListener.Stub() {
+                    @Override
+                    public void onUserRestrictionsChanged(
+                            int userId, Bundle newRestrictions, Bundle prevRestrictions) {
+                        // This callback currently delivered on main thread, but this post() is
+                        // defensive and doesn't rely on that in case it changes.
+                        mainThreadHandler.post(
+                                () -> handleUserRestrictionsChangeOnMainThread(
+                                        userId, newRestrictions, prevRestrictions));
+                    }
+                });
     }
 
     /** Returns the singleton instance. */
@@ -174,6 +193,13 @@
         }
     }
 
+    private void handleUserRestrictionsChangeOnMainThread(
+            int userId, Bundle newRestrictions, Bundle prevRestrictions) {
+        // No attempt at optimisation here. If the policy changes in any way for any user, just
+        // notify.
+        handleConfigurationInternalChangeOnMainThread();
+    }
+
     @Override
     public synchronized void addConfigurationInternalChangeListener(
             @NonNull StateChangeListener listener) {
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
index a71f9c7..40353a2 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
@@ -32,6 +32,9 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IUserRestrictionsListener;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -175,9 +178,11 @@
             }
         }, filter, null, null /* main thread */);
 
+        Handler mainThreadHandler = mContext.getMainThreadHandler();
+
         // Add async callbacks for changes to global settings that influence behavior.
         ContentResolver contentResolver = mContext.getContentResolver();
-        ContentObserver contentObserver = new ContentObserver(mContext.getMainThreadHandler()) {
+        ContentObserver contentObserver = new ContentObserver(mainThreadHandler) {
             @Override
             public void onChange(boolean selfChange) {
                 handleConfigurationInternalChangeOnMainThread();
@@ -197,6 +202,20 @@
         // Watch server flags.
         mServerFlags.addListener(this::handleConfigurationInternalChangeOnMainThread,
                 CONFIGURATION_INTERNAL_SERVER_FLAGS_KEYS_TO_WATCH);
+
+        // Watch for policy changes that affect what the user is permitted to do.
+        mUserManager.addUserRestrictionsListener(
+                new IUserRestrictionsListener.Stub() {
+                    @Override
+                    public void onUserRestrictionsChanged(
+                            int userId, Bundle newRestrictions, Bundle prevRestrictions) {
+                        // This callback currently delivered on main thread, but this post() is
+                        // defensive and doesn't rely on that in case it changes.
+                        mainThreadHandler.post(
+                                () -> handleUserRestrictionsChangeOnMainThread(
+                                        userId, newRestrictions, prevRestrictions));
+                    }
+                });
     }
 
     /** Returns the singleton instance. */
@@ -221,6 +240,13 @@
         }
     }
 
+    private void handleUserRestrictionsChangeOnMainThread(
+            int userId, Bundle newRestrictions, Bundle prevRestrictions) {
+        // No attempt at optimisation here. If the policy changes in any way for any user, just
+        // notify.
+        handleConfigurationInternalChangeOnMainThread();
+    }
+
     @Override
     public synchronized void addConfigurationInternalChangeListener(
             @NonNull StateChangeListener listener) {
diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
index 10e868d..c1d92cf 100644
--- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java
+++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
@@ -119,8 +119,13 @@
     }
 
     @Override
-    public void onStart() {
-        publishBinderService(TRACING_SERVICE_PROXY_BINDER_NAME, mTracingServiceProxy);
+    public void onStart() {}
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+            publishBinderService(TRACING_SERVICE_PROXY_BINDER_NAME, mTracingServiceProxy);
+        }
     }
 
     private void notifyTraceur(boolean sessionStolen) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 2b05993..f62c76e 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -61,7 +61,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.security.Authorization;
+import android.security.KeyStoreAuthorization;
 import android.service.trust.GrantTrustResult;
 import android.service.trust.TrustAgentService;
 import android.text.TextUtils;
@@ -155,6 +155,7 @@
     /* package */ final TrustArchive mArchive = new TrustArchive();
     private final Context mContext;
     private final LockPatternUtils mLockPatternUtils;
+    private final KeyStoreAuthorization mKeyStoreAuthorization;
     private final UserManager mUserManager;
     private final ActivityManager mActivityManager;
     private FingerprintManager mFingerprintManager;
@@ -252,25 +253,27 @@
      * cases.
      */
     protected static class Injector {
-        private final LockPatternUtils mLockPatternUtils;
-        private final Looper mLooper;
+        private final Context mContext;
 
-        public Injector(LockPatternUtils lockPatternUtils, Looper looper) {
-            mLockPatternUtils = lockPatternUtils;
-            mLooper = looper;
+        public Injector(Context context) {
+            mContext = context;
         }
 
         LockPatternUtils getLockPatternUtils() {
-            return mLockPatternUtils;
+            return new LockPatternUtils(mContext);
+        }
+
+        KeyStoreAuthorization getKeyStoreAuthorization() {
+            return KeyStoreAuthorization.getInstance();
         }
 
         Looper getLooper() {
-            return mLooper;
+            return Looper.myLooper();
         }
     }
 
     public TrustManagerService(Context context) {
-        this(context, new Injector(new LockPatternUtils(context), Looper.myLooper()));
+        this(context, new Injector(context));
     }
 
     protected TrustManagerService(Context context, Injector injector) {
@@ -280,6 +283,7 @@
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         mLockPatternUtils = injector.getLockPatternUtils();
+        mKeyStoreAuthorization = injector.getKeyStoreAuthorization();
         mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper());
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
     }
@@ -915,16 +919,16 @@
                 int authUserId = mLockPatternUtils.isProfileWithUnifiedChallenge(userId)
                         ? resolveProfileParent(userId) : userId;
 
-                Authorization.onDeviceLocked(userId, getBiometricSids(authUserId),
+                mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(authUserId),
                         isWeakUnlockMethodEnabled(authUserId));
             } else {
-                Authorization.onDeviceLocked(userId, getBiometricSids(userId), false);
+                mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(userId), false);
             }
         } else {
             // Notify Keystore that the device is now unlocked for the user.  Note that for unlocks
             // with LSKF, this is redundant with the call from LockSettingsService which provides
             // the password.  However, for unlocks with biometric or trust agent, this is required.
-            Authorization.onDeviceUnlocked(userId, /* password= */ null);
+            mKeyStoreAuthorization.onDeviceUnlocked(userId, /* password= */ null);
         }
     }
 
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java
index 4a81c95..440d2514 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java
@@ -89,8 +89,34 @@
      * @param ownerId the removing client id of the owner.
      */
     public void removeOwner(int ownerId) {
-        mAvailableSessionNum += mOwnerClientIdsToSessionNum.get(ownerId);
-        mOwnerClientIdsToSessionNum.remove(ownerId);
+        if (mOwnerClientIdsToSessionNum.containsKey(ownerId)) {
+            mAvailableSessionNum += mOwnerClientIdsToSessionNum.get(ownerId);
+            mOwnerClientIdsToSessionNum.remove(ownerId);
+        }
+    }
+
+    /**
+     * Remove a single session from resource
+     *
+     * @param ownerId the client Id of the owner of the session
+     */
+    public void removeSession(int ownerId) {
+        if (mOwnerClientIdsToSessionNum.containsKey(ownerId)) {
+            int sessionNum = mOwnerClientIdsToSessionNum.get(ownerId);
+            if (sessionNum > 0) {
+                mOwnerClientIdsToSessionNum.put(ownerId, --sessionNum);
+                mAvailableSessionNum++;
+            }
+        }
+    }
+
+    /**
+     * Check if there are any open sessions owned by a client
+     *
+     * @param ownerId the client Id of the owner of the sessions
+     */
+    public boolean hasOpenSessions(int ownerId) {
+        return mOwnerClientIdsToSessionNum.get(ownerId) > 0;
     }
 
     public Set<Integer> getOwnerClientIds() {
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index cddc79d..0afb049 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -1924,11 +1924,13 @@
         ownerProfile.useCiCam(grantingId);
     }
 
-    private void updateCasClientMappingOnRelease(
-            @NonNull CasResource releasingCas, int ownerClientId) {
-        ClientProfile ownerProfile = getClientProfile(ownerClientId);
-        releasingCas.removeOwner(ownerClientId);
-        ownerProfile.releaseCas();
+    private void updateCasClientMappingOnRelease(@NonNull CasResource cas, int ownerClientId) {
+        cas.removeSession(ownerClientId);
+        if (!cas.hasOpenSessions(ownerClientId)) {
+            ClientProfile ownerProfile = getClientProfile(ownerClientId);
+            cas.removeOwner(ownerClientId);
+            ownerProfile.releaseCas();
+        }
     }
 
     private void updateCiCamClientMappingOnRelease(
diff --git a/services/core/java/com/android/server/utils/Android.bp b/services/core/java/com/android/server/utils/Android.bp
index 3a334be..ffb9aec 100644
--- a/services/core/java/com/android/server/utils/Android.bp
+++ b/services/core/java/com/android/server/utils/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "com.android.server.utils-aconfig",
     package: "com.android.server.utils",
+    container: "system",
     srcs: ["*.aconfig"],
 }
 
diff --git a/services/core/java/com/android/server/utils/AnrTimer.java b/services/core/java/com/android/server/utils/AnrTimer.java
index b7d8cfc..e944eca 100644
--- a/services/core/java/com/android/server/utils/AnrTimer.java
+++ b/services/core/java/com/android/server/utils/AnrTimer.java
@@ -193,6 +193,10 @@
     @GuardedBy("mLock")
     private int mTotalStarted = 0;
 
+    /** The total number of timers that were restarted without an explicit cancel. */
+    @GuardedBy("mLock")
+    private int mTotalRestarted = 0;
+
     /** The total number of errors detected. */
     @GuardedBy("mLock")
     private int mTotalErrors = 0;
@@ -434,10 +438,10 @@
         @Override
         void start(@NonNull V arg, int pid, int uid, long timeoutMs) {
             synchronized (mLock) {
-                if (mTimerIdMap.containsKey(arg)) {
-                    // There is an existing timer.  Cancel it.
-                    cancel(arg);
-                }
+                // If there is an existing timer, cancel it.  This is a nop if the timer does not
+                // exist.
+                if (cancel(arg)) mTotalRestarted++;
+
                 int timerId = nativeAnrTimerStart(mNative, pid, uid, timeoutMs, mExtend);
                 if (timerId > 0) {
                     mTimerIdMap.put(arg, timerId);
@@ -546,9 +550,7 @@
         private Integer removeLocked(V arg) {
             Integer r = mTimerIdMap.remove(arg);
             if (r != null) {
-                synchronized (mTimerArgMap) {
-                    mTimerArgMap.remove(r);
-                }
+                mTimerArgMap.remove(r);
             }
             return r;
         }
@@ -672,8 +674,8 @@
         synchronized (mLock) {
             pw.format("timer: %s\n", mLabel);
             pw.increaseIndent();
-            pw.format("started=%d maxStarted=%d running=%d expired=%d errors=%d\n",
-                    mTotalStarted, mMaxStarted, mTimerIdMap.size(),
+            pw.format("started=%d maxStarted=%d  restarted=%d running=%d expired=%d errors=%d\n",
+                    mTotalStarted, mMaxStarted, mTotalRestarted, mTimerIdMap.size(),
                     mTotalExpired, mTotalErrors);
             pw.decreaseIndent();
             mFeature.dump(pw, false);
diff --git a/services/core/java/com/android/server/utils/flags.aconfig b/services/core/java/com/android/server/utils/flags.aconfig
index 163116b..6f37837 100644
--- a/services/core/java/com/android/server/utils/flags.aconfig
+++ b/services/core/java/com/android/server/utils/flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.utils"
+container: "system"
 
 flag {
      name: "anr_timer_service"
diff --git a/services/core/java/com/android/server/utils/quota/OWNERS b/services/core/java/com/android/server/utils/quota/OWNERS
index a2943f3..469acb2 100644
--- a/services/core/java/com/android/server/utils/quota/OWNERS
+++ b/services/core/java/com/android/server/utils/quota/OWNERS
@@ -1,4 +1,3 @@
 [email protected]
[email protected]
 [email protected]
 [email protected]
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 37f0450..5a5f7ef 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -626,8 +626,12 @@
      * Dumps the state of this Vcn for logging and debugging purposes.
      *
      * <p>PII and credentials MUST NEVER be dumped here.
+     *
+     * <p>This method is not thread safe and MUST run on the VCN thread.
      */
     public void dump(IndentingPrintWriter pw) {
+        mVcnContext.ensureRunningOnLooperThread();
+
         pw.println("Vcn (" + mSubscriptionGroup + "):");
         pw.increaseIndent();
 
diff --git a/services/core/java/com/android/server/vcn/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java
index 1383708..6a4c9c2 100644
--- a/services/core/java/com/android/server/vcn/VcnContext.java
+++ b/services/core/java/com/android/server/vcn/VcnContext.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.net.IpSecTransformState;
 import android.net.vcn.FeatureFlags;
 import android.net.vcn.FeatureFlagsImpl;
 import android.os.Looper;
@@ -34,7 +35,6 @@
     @NonNull private final Looper mLooper;
     @NonNull private final VcnNetworkProvider mVcnNetworkProvider;
     @NonNull private final FeatureFlags mFeatureFlags;
-    @NonNull private final android.net.platform.flags.FeatureFlags mCoreNetFeatureFlags;
     private final boolean mIsInTestMode;
 
     public VcnContext(
@@ -49,7 +49,6 @@
 
         // Auto-generated class
         mFeatureFlags = new FeatureFlagsImpl();
-        mCoreNetFeatureFlags = new android.net.platform.flags.FeatureFlagsImpl();
     }
 
     @NonNull
@@ -76,7 +75,16 @@
     }
 
     public boolean isFlagIpSecTransformStateEnabled() {
-        return mCoreNetFeatureFlags.ipsecTransformState();
+        // TODO: b/328844044: Ideally this code should gate the behavior by checking the
+        // android.net.platform.flags.ipsec_transform_state flag but that flag is not accessible
+        // right now. We should either update the code when the flag is accessible or remove the
+        // legacy behavior after VIC SDK finalization
+        try {
+            new IpSecTransformState.Builder();
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     @NonNull
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 3094b18..8d378a0 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -2580,8 +2580,12 @@
      * Dumps the state of this VcnGatewayConnection for logging and debugging purposes.
      *
      * <p>PII and credentials MUST NEVER be dumped here.
+     *
+     * <p>This method is not thread safe and MUST run on the VCN thread.
      */
     public void dump(IndentingPrintWriter pw) {
+        mVcnContext.ensureRunningOnLooperThread();
+
         pw.println("VcnGatewayConnection (" + mConnectionConfig.getGatewayConnectionName() + "):");
         pw.increaseIndent();
 
@@ -2602,6 +2606,19 @@
         mUnderlyingNetworkController.dump(pw);
         pw.println();
 
+        if (mIkeSession == null) {
+            pw.println("mIkeSession: null");
+        } else {
+            pw.println("mIkeSession:");
+
+            // Add a try catch block in case IkeSession#dump is not thread-safe
+            try {
+                mIkeSession.dump(pw);
+            } catch (Exception e) {
+                Slog.wtf(TAG, "Failed to dump IkeSession: " + e);
+            }
+        }
+
         pw.decreaseIndent();
     }
 
@@ -2905,6 +2922,11 @@
         public void setNetwork(@NonNull Network network) {
             mImpl.setNetwork(network);
         }
+
+        /** Dumps the state of the IkeSession */
+        public void dump(@NonNull IndentingPrintWriter pw) {
+            mImpl.dump(pw);
+        }
     }
 
     /** Proxy Implementation of WakeLock, used for testing. */
diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index ed9fa65..3619253 100644
--- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -16,8 +16,10 @@
 
 package com.android.server.vcn.routeselection;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
 import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
@@ -38,6 +40,10 @@
 import com.android.internal.annotations.VisibleForTesting.Visibility;
 import com.android.server.vcn.VcnContext;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.BitSet;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
@@ -56,8 +62,51 @@
 public class IpSecPacketLossDetector extends NetworkMetricMonitor {
     private static final String TAG = IpSecPacketLossDetector.class.getSimpleName();
 
+    private static final int PACKET_LOSS_PERCENT_UNAVAILABLE = -1;
+
+    // Ignore the packet loss detection result if the expected packet number is smaller than 10.
+    // Solarwinds NPM uses 10 ICMP echos to calculate packet loss rate (as per
+    // https://thwack.solarwinds.com/products/network-performance-monitor-npm/f/forum/63829/how-is-packet-loss-calculated)
     @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PACKET_LOSS_UNAVALAIBLE = -1;
+    static final int MIN_VALID_EXPECTED_RX_PACKET_NUM = 10;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            prefix = {"PACKET_LOSS_"},
+            value = {
+                PACKET_LOSS_RATE_VALID,
+                PACKET_LOSS_RATE_INVALID,
+                PACKET_LOSS_UNUSUAL_SEQ_NUM_LEAP,
+            })
+    @Target({ElementType.TYPE_USE})
+    private @interface PacketLossResultType {}
+
+    /** Indicates a valid packet loss rate is available */
+    private static final int PACKET_LOSS_RATE_VALID = 0;
+
+    /**
+     * Indicates that the detector cannot get a valid packet loss rate due to one of the following
+     * reasons:
+     *
+     * <ul>
+     *   <li>The replay window did not proceed and thus all packets might have been delivered out of
+     *       order
+     *   <li>The expected received packet number is too small and thus the detection result is not
+     *       reliable
+     *   <li>There are unexpected errors
+     * </ul>
+     */
+    private static final int PACKET_LOSS_RATE_INVALID = 1;
+
+    /**
+     * The sequence number increase is unusually large and might be caused an intentional leap on
+     * the server's downlink
+     *
+     * <p>Inbound sequence number will not always increase consecutively. During load balancing the
+     * server might add a big leap on the sequence number intentionally. In such case a high packet
+     * loss rate does not always indicate a lossy network
+     */
+    private static final int PACKET_LOSS_UNUSUAL_SEQ_NUM_LEAP = 2;
 
     // For VoIP, losses between 5% and 10% of the total packet stream will affect the quality
     // significantly (as per "Computer Networking for LANS to WANS: Hardware, Software and
@@ -68,8 +117,12 @@
 
     private static final int POLL_IPSEC_STATE_INTERVAL_SECONDS_DEFAULT = 20;
 
+    // By default, there's no maximum limit enforced
+    private static final int MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED = -1;
+
     private long mPollIpSecStateIntervalMs;
-    private final int mPacketLossRatePercentThreshold;
+    private int mPacketLossRatePercentThreshold;
+    private int mMaxSeqNumIncreasePerSecond;
 
     @NonNull private final Handler mHandler;
     @NonNull private final PowerManager mPowerManager;
@@ -108,6 +161,7 @@
 
         mPollIpSecStateIntervalMs = getPollIpSecStateIntervalMs(carrierConfig);
         mPacketLossRatePercentThreshold = getPacketLossRatePercentThreshold(carrierConfig);
+        mMaxSeqNumIncreasePerSecond = getMaxSeqNumIncreasePerSecond(carrierConfig);
 
         // Register for system broadcasts to monitor idle mode change
         final IntentFilter intentFilter = new IntentFilter();
@@ -172,6 +226,24 @@
         return IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DEFAULT;
     }
 
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static int getMaxSeqNumIncreasePerSecond(@Nullable PersistableBundleWrapper carrierConfig) {
+        int maxSeqNumIncrease = MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED;
+        if (Flags.handleSeqNumLeap() && carrierConfig != null) {
+            maxSeqNumIncrease =
+                    carrierConfig.getInt(
+                            VcnManager.VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY,
+                            MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED);
+        }
+
+        if (maxSeqNumIncrease < MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED) {
+            logE(TAG, "Invalid value of MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY " + maxSeqNumIncrease);
+            return MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED;
+        }
+
+        return maxSeqNumIncrease;
+    }
+
     @Override
     protected void onSelectedUnderlyingNetworkChanged() {
         if (!isSelectedUnderlyingNetwork()) {
@@ -207,6 +279,11 @@
         // The already scheduled event will not be affected. The followup events will be scheduled
         // with the new interval
         mPollIpSecStateIntervalMs = getPollIpSecStateIntervalMs(carrierConfig);
+
+        if (Flags.handleSeqNumLeap()) {
+            mPacketLossRatePercentThreshold = getPacketLossRatePercentThreshold(carrierConfig);
+            mMaxSeqNumIncreasePerSecond = getMaxSeqNumIncreasePerSecond(carrierConfig);
+        }
     }
 
     @Override
@@ -307,30 +384,40 @@
             return;
         }
 
-        final int packetLossRate =
+        final PacketLossCalculationResult calculateResult =
                 mPacketLossCalculator.getPacketLossRatePercentage(
-                        mLastIpSecTransformState, state, getLogPrefix());
+                        mLastIpSecTransformState,
+                        state,
+                        mMaxSeqNumIncreasePerSecond,
+                        getLogPrefix());
 
-        if (packetLossRate == PACKET_LOSS_UNAVALAIBLE) {
+        if (calculateResult.getResultType() == PACKET_LOSS_RATE_INVALID) {
             return;
         }
 
         final String logMsg =
-                "packetLossRate: "
-                        + packetLossRate
+                "calculateResult: "
+                        + calculateResult
                         + "% in the past "
                         + (state.getTimestampMillis()
                                 - mLastIpSecTransformState.getTimestampMillis())
                         + "ms";
 
         mLastIpSecTransformState = state;
-        if (packetLossRate < mPacketLossRatePercentThreshold) {
+        if (calculateResult.getPacketLossRatePercent() < mPacketLossRatePercentThreshold) {
             logV(logMsg);
+
+            // In both "valid" or "unusual_seq_num_leap" cases, notify that the network has passed
+            // the validation
             onValidationResultReceivedInternal(false /* isFailed */);
         } else {
             logInfo(logMsg);
-            onValidationResultReceivedInternal(true /* isFailed */);
 
+            if (calculateResult.getResultType() == PACKET_LOSS_RATE_VALID) {
+                onValidationResultReceivedInternal(true /* isFailed */);
+            }
+
+            // In both "valid" or "unusual_seq_num_leap" cases, trigger network validation
             if (Flags.validateNetworkOnIpsecLoss()) {
                 // Trigger re-validation of the underlying network; if it fails, the VCN will
                 // attempt to migrate away.
@@ -343,9 +430,10 @@
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     public static class PacketLossCalculator {
         /** Calculate the packet loss rate between two timestamps */
-        public int getPacketLossRatePercentage(
+        public PacketLossCalculationResult getPacketLossRatePercentage(
                 @NonNull IpSecTransformState oldState,
                 @NonNull IpSecTransformState newState,
+                int maxSeqNumIncreasePerSecond,
                 String logPrefix) {
             logVIpSecTransform("oldState", oldState, logPrefix);
             logVIpSecTransform("newState", newState, logPrefix);
@@ -359,7 +447,23 @@
             if (oldSeqHi == newSeqHi || newSeqHi < replayWindowSize) {
                 // The replay window did not proceed and all packets might have been delivered out
                 // of order
-                return PACKET_LOSS_UNAVALAIBLE;
+                return PacketLossCalculationResult.invalid();
+            }
+
+            boolean isUnusualSeqNumLeap = false;
+
+            // Handle sequence number leap
+            if (Flags.handleSeqNumLeap()
+                    && maxSeqNumIncreasePerSecond != MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED) {
+                final long timeDiffMillis =
+                        newState.getTimestampMillis() - oldState.getTimestampMillis();
+                final long maxSeqNumIncrease = timeDiffMillis * maxSeqNumIncreasePerSecond / 1000;
+
+                // Sequence numbers are unsigned 32-bit values. If maxSeqNumIncrease overflows,
+                // isUnusualSeqNumLeap can never be true.
+                if (maxSeqNumIncrease >= 0 && newSeqHi - oldSeqHi >= maxSeqNumIncrease) {
+                    isUnusualSeqNumLeap = true;
+                }
             }
 
             // Get the expected packet count by assuming there is no packet loss. In this case, SA
@@ -381,15 +485,23 @@
                             + " actualPktCntDiff: "
                             + actualPktCntDiff);
 
+            if (Flags.handleSeqNumLeap() && expectedPktCntDiff < MIN_VALID_EXPECTED_RX_PACKET_NUM) {
+                // The sample size is too small to ensure a reliable detection result
+                return PacketLossCalculationResult.invalid();
+            }
+
             if (expectedPktCntDiff < 0
                     || expectedPktCntDiff == 0
                     || actualPktCntDiff < 0
                     || actualPktCntDiff > expectedPktCntDiff) {
                 logWtf(TAG, "Impossible values for expectedPktCntDiff or" + " actualPktCntDiff");
-                return PACKET_LOSS_UNAVALAIBLE;
+                return PacketLossCalculationResult.invalid();
             }
 
-            return 100 - (int) (actualPktCntDiff * 100 / expectedPktCntDiff);
+            final int percent = 100 - (int) (actualPktCntDiff * 100 / expectedPktCntDiff);
+            return isUnusualSeqNumLeap
+                    ? PacketLossCalculationResult.unusualSeqNumLeap(percent)
+                    : PacketLossCalculationResult.valid(percent);
         }
     }
 
@@ -409,4 +521,64 @@
     private static long getPacketCntInReplayWindow(@NonNull IpSecTransformState state) {
         return BitSet.valueOf(state.getReplayBitmap()).cardinality();
     }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static class PacketLossCalculationResult {
+        @PacketLossResultType private final int mResultType;
+        private final int mPacketLossRatePercent;
+
+        private PacketLossCalculationResult(@PacketLossResultType int type, int percent) {
+            mResultType = type;
+            mPacketLossRatePercent = percent;
+        }
+
+        /** Construct an instance that contains a valid packet loss rate */
+        public static PacketLossCalculationResult valid(int percent) {
+            return new PacketLossCalculationResult(PACKET_LOSS_RATE_VALID, percent);
+        }
+
+        /** Construct an instance indicating the inability to get a valid packet loss rate */
+        public static PacketLossCalculationResult invalid() {
+            return new PacketLossCalculationResult(
+                    PACKET_LOSS_RATE_INVALID, PACKET_LOSS_PERCENT_UNAVAILABLE);
+        }
+
+        /** Construct an instance indicating that there is an unusual sequence number leap */
+        public static PacketLossCalculationResult unusualSeqNumLeap(int percent) {
+            return new PacketLossCalculationResult(PACKET_LOSS_UNUSUAL_SEQ_NUM_LEAP, percent);
+        }
+
+        @PacketLossResultType
+        public int getResultType() {
+            return mResultType;
+        }
+
+        public int getPacketLossRatePercent() {
+            return mPacketLossRatePercent;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mResultType, mPacketLossRatePercent);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object other) {
+            if (!(other instanceof PacketLossCalculationResult)) {
+                return false;
+            }
+
+            final PacketLossCalculationResult rhs = (PacketLossCalculationResult) other;
+            return mResultType == rhs.mResultType
+                    && mPacketLossRatePercent == rhs.mPacketLossRatePercent;
+        }
+
+        @Override
+        public String toString() {
+            return "mResultType: "
+                    + mResultType
+                    + " | mPacketLossRatePercent: "
+                    + mPacketLossRatePercent;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
index a1b212f..b9b1060 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
@@ -272,6 +272,11 @@
         }
     }
 
+    protected static void logE(String className, String msgWithPrefix) {
+        Slog.w(className, msgWithPrefix);
+        LOCAL_LOG.log("[ERROR ] " + className + msgWithPrefix);
+    }
+
     protected static void logWtf(String className, String msgWithPrefix) {
         Slog.wtf(className, msgWithPrefix);
         LOCAL_LOG.log("[WTF ] " + className + msgWithPrefix);
diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
index 96f045d..8138168 100644
--- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
+++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
@@ -44,6 +44,8 @@
             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION);
     private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
+    private static final VibrationAttributes COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST);
 
     private final VibratorInfo mVibratorInfo;
     private final boolean mHapticTextHandleEnabled;
@@ -120,7 +122,6 @@
                 return getKeyboardVibration(effectId);
 
             case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
-            case HapticFeedbackConstants.ENTRY_BUMP:
             case HapticFeedbackConstants.DRAG_CROSSING:
                 return getVibration(
                         effectId,
@@ -131,6 +132,7 @@
             case HapticFeedbackConstants.EDGE_RELEASE:
             case HapticFeedbackConstants.CALENDAR_DATE:
             case HapticFeedbackConstants.CONFIRM:
+            case HapticFeedbackConstants.BIOMETRIC_CONFIRM:
             case HapticFeedbackConstants.GESTURE_START:
             case HapticFeedbackConstants.SCROLL_ITEM_FOCUS:
             case HapticFeedbackConstants.SCROLL_LIMIT:
@@ -143,6 +145,7 @@
                 return getVibration(effectId, VibrationEffect.EFFECT_HEAVY_CLICK);
 
             case HapticFeedbackConstants.REJECT:
+            case HapticFeedbackConstants.BIOMETRIC_REJECT:
                 return getVibration(effectId, VibrationEffect.EFFECT_DOUBLE_CLICK);
 
             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
@@ -207,6 +210,10 @@
             case HapticFeedbackConstants.KEYBOARD_RELEASE:
                 attrs = createKeyboardVibrationAttributes(fromIme);
                 break;
+            case HapticFeedbackConstants.BIOMETRIC_CONFIRM:
+            case HapticFeedbackConstants.BIOMETRIC_REJECT:
+                attrs = COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES;
+                break;
             default:
                 attrs = TOUCH_VIBRATION_ATTRIBUTES;
         }
@@ -225,6 +232,23 @@
         return flags == 0 ? attrs : new VibrationAttributes.Builder(attrs).setFlags(flags).build();
     }
 
+    /**
+     * Returns true if given haptic feedback is restricted to system apps with permission
+     * {@code android.permission.VIBRATE_SYSTEM_CONSTANTS}.
+     *
+     * @param effectId the haptic feedback effect ID to check.
+     * @return true if the haptic feedback is restricted, false otherwise.
+     */
+    public boolean isRestrictedHapticFeedback(int effectId) {
+        switch (effectId) {
+            case HapticFeedbackConstants.BIOMETRIC_CONFIRM:
+            case HapticFeedbackConstants.BIOMETRIC_REJECT:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     /** Dumps relevant state. */
     public void dump(String prefix, PrintWriter pw) {
         pw.print("mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled);
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index 6fc9d9a..ad54efc 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -32,8 +32,9 @@
 import android.util.proto.ProtoOutputStream;
 
 import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.Locale;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -42,10 +43,11 @@
  * The base class for all vibrations.
  */
 abstract class Vibration {
-    private static final SimpleDateFormat DEBUG_TIME_FORMAT =
-            new SimpleDateFormat("HH:mm:ss.SSS");
-    private static final SimpleDateFormat DEBUG_DATE_TIME_FORMAT =
-            new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+    private static final DateTimeFormatter DEBUG_TIME_FORMATTER = DateTimeFormatter.ofPattern(
+            "HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
+    private static final DateTimeFormatter DEBUG_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(
+            "MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
+
     // Used to generate globally unique vibration ids.
     private static final AtomicInteger sNextVibrationId = new AtomicInteger(1); // 0 = no callback
 
@@ -240,10 +242,12 @@
 
         @Override
         public String toString() {
-            return "createTime: " + DEBUG_DATE_TIME_FORMAT.format(new Date(mCreateTime))
-                    + ", startTime: " + DEBUG_DATE_TIME_FORMAT.format(new Date(mStartTime))
-                    + ", endTime: "
-                    + (mEndTime == 0 ? null : DEBUG_DATE_TIME_FORMAT.format(new Date(mEndTime)))
+            return "createTime: " + DEBUG_DATE_TIME_FORMATTER.format(
+                    Instant.ofEpochMilli(mCreateTime))
+                    + ", startTime: " + DEBUG_DATE_TIME_FORMATTER.format(
+                    Instant.ofEpochMilli(mStartTime))
+                    + ", endTime: " + (mEndTime == 0 ? null : DEBUG_DATE_TIME_FORMATTER.format(
+                    Instant.ofEpochMilli(mEndTime)))
                     + ", durationMs: " + mDurationMs
                     + ", status: " + mStatus.name().toLowerCase(Locale.ROOT)
                     + ", playedEffect: " + mPlayedEffect
@@ -267,12 +271,14 @@
             boolean isExternalVibration = mPlayedEffect == null;
             String timingsStr = String.format(Locale.ROOT,
                     "%s | %8s | %20s | duration: %5dms | start: %12s | end: %12s",
-                    DEBUG_DATE_TIME_FORMAT.format(new Date(mCreateTime)),
+                    DEBUG_DATE_TIME_FORMATTER.format(Instant.ofEpochMilli(mCreateTime)),
                     isExternalVibration ? "external" : "effect",
                     mStatus.name().toLowerCase(Locale.ROOT),
                     mDurationMs,
-                    mStartTime == 0 ? "" : DEBUG_TIME_FORMAT.format(new Date(mStartTime)),
-                    mEndTime == 0 ? "" : DEBUG_TIME_FORMAT.format(new Date(mEndTime)));
+                    mStartTime == 0 ? ""
+                            : DEBUG_TIME_FORMATTER.format(Instant.ofEpochMilli(mStartTime)),
+                    mEndTime == 0 ? ""
+                            : DEBUG_TIME_FORMATTER.format(Instant.ofEpochMilli(mEndTime)));
             String paramStr = String.format(Locale.ROOT,
                     " | scale: %8s (adaptive=%.2f) | flags: %4s | usage: %s",
                     VibrationScaler.scaleLevelToString(mScaleLevel), mAdaptiveScale,
@@ -307,10 +313,12 @@
             pw.increaseIndent();
             pw.println("status = " + mStatus.name().toLowerCase(Locale.ROOT));
             pw.println("durationMs = " + mDurationMs);
-            pw.println("createTime = " + DEBUG_DATE_TIME_FORMAT.format(new Date(mCreateTime)));
-            pw.println("startTime = " + DEBUG_DATE_TIME_FORMAT.format(new Date(mStartTime)));
-            pw.println("endTime = "
-                    + (mEndTime == 0 ? null : DEBUG_DATE_TIME_FORMAT.format(new Date(mEndTime))));
+            pw.println("createTime = " + DEBUG_DATE_TIME_FORMATTER.format(
+                    Instant.ofEpochMilli(mCreateTime)));
+            pw.println("startTime = " + DEBUG_DATE_TIME_FORMATTER.format(
+                    Instant.ofEpochMilli(mStartTime)));
+            pw.println("endTime = " + (mEndTime == 0 ? null
+                    : DEBUG_DATE_TIME_FORMATTER.format(Instant.ofEpochMilli(mEndTime))));
             pw.println("playedEffect = " + mPlayedEffect);
             pw.println("originalEffect = " + mOriginalEffect);
             pw.println("scale = " + VibrationScaler.scaleLevelToString(mScaleLevel));
diff --git a/services/core/java/com/android/server/vibrator/VibratorControlService.java b/services/core/java/com/android/server/vibrator/VibratorControlService.java
index 10317c9..f82ff67 100644
--- a/services/core/java/com/android/server/vibrator/VibratorControlService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorControlService.java
@@ -51,8 +51,9 @@
 import com.android.internal.util.ArrayUtils;
 
 import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.Locale;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
@@ -66,8 +67,8 @@
     private static final int UNRECOGNIZED_VIBRATION_TYPE = -1;
     private static final int NO_SCALE = -1;
 
-    private static final SimpleDateFormat DEBUG_DATE_TIME_FORMAT =
-            new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+    private static final DateTimeFormatter DEBUG_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(
+            "MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
 
     private final VibrationParamsRecords mVibrationParamsRecords;
     private final VibratorControllerHolder mVibratorControllerHolder;
@@ -100,7 +101,9 @@
     }
 
     @Override
-    public void registerVibratorController(IVibratorController controller) {
+    public void registerVibratorController(@NonNull IVibratorController controller) {
+        Objects.requireNonNull(controller);
+
         synchronized (mLock) {
             mVibratorControllerHolder.setVibratorController(controller);
         }
@@ -133,6 +136,7 @@
     public void setVibrationParams(@SuppressLint("ArrayReturn") VibrationParam[] params,
             @NonNull IVibratorController token) {
         Objects.requireNonNull(token);
+        requireContainsNoNullElement(params);
 
         synchronized (mLock) {
             if (mVibratorControllerHolder.getVibratorController() == null) {
@@ -147,6 +151,13 @@
                         + "controller doesn't match the registered one. " + this);
                 return;
             }
+            if (params == null) {
+                // Adaptive haptics scales cannot be set to null. Ignoring request.
+                Slog.d(TAG,
+                        "New vibration params received but are null. New vibration "
+                                + "params ignored.");
+                return;
+            }
 
             updateAdaptiveHapticsScales(params);
             recordUpdateVibrationParams(params, /* fromRequest= */ false);
@@ -180,6 +191,7 @@
     public void onRequestVibrationParamsComplete(
             @NonNull IBinder requestToken, @SuppressLint("ArrayReturn") VibrationParam[] result) {
         Objects.requireNonNull(requestToken);
+        requireContainsNoNullElement(result);
 
         synchronized (mLock) {
             if (mVibrationParamRequest == null) {
@@ -201,6 +213,13 @@
             long latencyMs = SystemClock.uptimeMillis() - mVibrationParamRequest.uptimeMs;
             mStatsLogger.logVibrationParamRequestLatency(mVibrationParamRequest.uid, latencyMs);
 
+            if (result == null) {
+                Slog.d(TAG,
+                        "New vibration params received but are null. New vibration "
+                                + "params ignored.");
+                return;
+            }
+
             updateAdaptiveHapticsScales(result);
             endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ false);
             recordUpdateVibrationParams(result, /* fromRequest= */ true);
@@ -400,10 +419,9 @@
      *
      * @param params the new vibration params.
      */
-    private void updateAdaptiveHapticsScales(@Nullable VibrationParam[] params) {
-        if (params == null) {
-            return;
-        }
+    private void updateAdaptiveHapticsScales(@NonNull VibrationParam[] params) {
+        Objects.requireNonNull(params);
+
         for (VibrationParam param : params) {
             if (param.getTag() != VibrationParam.scale) {
                 Slog.e(TAG, "Unsupported vibration param: " + param);
@@ -447,11 +465,10 @@
         mVibrationScaler.updateAdaptiveHapticsScale(usageHint, scale);
     }
 
-    private void recordUpdateVibrationParams(@Nullable VibrationParam[] params,
+    private void recordUpdateVibrationParams(@NonNull VibrationParam[] params,
             boolean fromRequest) {
-        if (params == null) {
-            return;
-        }
+        Objects.requireNonNull(params);
+
         VibrationParamsRecords.Operation operation =
                 fromRequest ? VibrationParamsRecords.Operation.PULL
                         : VibrationParamsRecords.Operation.PUSH;
@@ -473,6 +490,13 @@
                 VibrationParamsRecords.Operation.CLEAR, createTime, typesMask, NO_SCALE));
     }
 
+    private void requireContainsNoNullElement(VibrationParam[] params) {
+        if (ArrayUtils.contains(params, null)) {
+            throw new IllegalArgumentException(
+                    "Invalid vibration params received: null values are not permitted.");
+        }
+    }
+
     /**
      * Keep records of {@link VibrationParam} values received by this service from a registered
      * {@link VibratorController} and provide debug information for this service.
@@ -567,7 +591,7 @@
         public void dump(IndentingPrintWriter pw) {
             String line = String.format(Locale.ROOT,
                     "%s | %6s | scale: %5s | typesMask: %6s | usages: %s",
-                    DEBUG_DATE_TIME_FORMAT.format(new Date(mCreateTime)),
+                    DEBUG_DATE_TIME_FORMATTER.format(Instant.ofEpochMilli(mCreateTime)),
                     mOperation.name().toLowerCase(Locale.ROOT),
                     (mScale == NO_SCALE) ? "" : String.format(Locale.ROOT, "%.2f", mScale),
                     Long.toBinaryString(mTypesMask), createVibrationUsagesString());
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 9e9025e..8281ac1 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -439,6 +439,11 @@
             Slog.w(TAG, "performHapticFeedback; haptic vibration provider not ready.");
             return null;
         }
+        if (hapticVibrationProvider.isRestrictedHapticFeedback(constant)
+                && !hasPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS)) {
+            Slog.w(TAG, "performHapticFeedback; no permission for effect " + constant);
+            return null;
+        }
         VibrationEffect effect = hapticVibrationProvider.getVibrationForHapticFeedback(constant);
         if (effect == null) {
             Slog.w(TAG, "performHapticFeedback; vibration absent for effect " + constant);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
index 5175b74..f6e0168 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wallpaper;
 
+import static android.app.WallpaperManager.ORIENTATION_UNKNOWN;
 import static android.app.WallpaperManager.getOrientation;
 import static android.app.WallpaperManager.getRotatedOrientation;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -86,7 +87,7 @@
     public interface WallpaperCropUtils {
 
         /**
-         * Equivalent to {@link #getCrop(Point, Point, SparseArray, boolean)}
+         * Equivalent to {@link WallpaperCropper#getCrop(Point, Point, SparseArray, boolean)}
          */
         Rect getCrop(Point displaySize, Point bitmapSize,
                 SparseArray<Rect> suggestedCrops, boolean rtl);
@@ -120,16 +121,44 @@
     public Rect getCrop(Point displaySize, Point bitmapSize,
             SparseArray<Rect> suggestedCrops, boolean rtl) {
 
-        // Case 1: if no crops are provided, center align the full image
+        int orientation = getOrientation(displaySize);
+
+        // Case 1: if no crops are provided, show the full image (from the left, or right if RTL).
         if (suggestedCrops == null || suggestedCrops.size() == 0) {
-            Rect crop = new Rect(0, 0, displaySize.x, displaySize.y);
-            float scale = Math.min(
-                    ((float) bitmapSize.x) / displaySize.x,
-                    ((float) bitmapSize.y) / displaySize.y);
-            crop.scale(scale);
-            crop.offset((bitmapSize.x - crop.width()) / 2,
-                    (bitmapSize.y - crop.height()) / 2);
-            return crop;
+            Rect crop = new Rect(0, 0, bitmapSize.x, bitmapSize.y);
+
+            // The first exception is if the device is a foldable and we're on the folded screen.
+            // In that case, show the center of what's on the unfolded screen.
+            int unfoldedOrientation = mWallpaperDisplayHelper.getUnfoldedOrientation(orientation);
+            if (unfoldedOrientation != ORIENTATION_UNKNOWN) {
+                // Let the system know that we're showing the full image on the unfolded screen
+                SparseArray<Rect> newSuggestedCrops = new SparseArray<>();
+                newSuggestedCrops.put(unfoldedOrientation, crop);
+                // This will fall into "Case 4" of this function and center the folded screen
+                return getCrop(displaySize, bitmapSize, newSuggestedCrops, rtl);
+            }
+
+            // The second exception is if we're on tablet and we're on portrait mode.
+            // In that case, center the wallpaper relatively to landscape and put some parallax.
+            boolean isTablet = mWallpaperDisplayHelper.isLargeScreen()
+                    && !mWallpaperDisplayHelper.isFoldable();
+            if (isTablet && displaySize.x < displaySize.y) {
+                Point rotatedDisplaySize = new Point(displaySize.y, displaySize.x);
+                // compute the crop on landscape (without parallax)
+                Rect landscapeCrop = getCrop(rotatedDisplaySize, bitmapSize, suggestedCrops, rtl);
+                landscapeCrop = noParallax(landscapeCrop, rotatedDisplaySize, bitmapSize, rtl);
+                // compute the crop on portrait at the center of the landscape crop
+                crop = getAdjustedCrop(landscapeCrop, bitmapSize, displaySize, false, rtl, ADD);
+
+                // add some parallax (until the border of the landscape crop without parallax)
+                if (rtl) {
+                    crop.left = landscapeCrop.left;
+                } else {
+                    crop.right = landscapeCrop.right;
+                }
+            }
+
+            return getAdjustedCrop(crop, bitmapSize, displaySize, true, rtl, ADD);
         }
 
         // If any suggested crop is invalid, fallback to case 1
@@ -142,8 +171,6 @@
             }
         }
 
-        int orientation = getOrientation(displaySize);
-
         // Case 2: if the orientation exists in the suggested crops, adjust the suggested crop
         Rect suggestedCrop = suggestedCrops.get(orientation);
         if (suggestedCrop != null) {
@@ -168,11 +195,21 @@
         suggestedCrop = suggestedCrops.get(unfoldedOrientation);
         suggestedDisplaySize = defaultDisplaySizes.get(unfoldedOrientation);
         if (suggestedCrop != null) {
-            // only keep the visible part (without parallax)
+            // compute the visible part (without parallax) of the unfolded screen
             Rect adjustedCrop = noParallax(suggestedCrop, suggestedDisplaySize, bitmapSize, rtl);
-            return getAdjustedCrop(adjustedCrop, bitmapSize, displaySize, false, rtl, REMOVE);
+            // compute the folded crop, at the center of the crop of the unfolded screen
+            Rect res = getAdjustedCrop(adjustedCrop, bitmapSize, displaySize, false, rtl, REMOVE);
+            // if we removed some width, add it back to add a parallax effect
+            if (res.width() < adjustedCrop.width()) {
+                if (rtl) res.left = Math.min(res.left, adjustedCrop.left);
+                else res.right = Math.max(res.right, adjustedCrop.right);
+                // use getAdjustedCrop(parallax=true) to make sure we don't exceed MAX_PARALLAX
+                res = getAdjustedCrop(res, bitmapSize, displaySize, true, rtl, ADD);
+            }
+            return res;
         }
 
+
         // Case 5: if the device is a foldable, if we're looking for an unfolded orientation and
         // have the suggested crop of the relative folded orientation, reuse it by adding content.
         int foldedOrientation = mWallpaperDisplayHelper.getFoldedOrientation(orientation);
@@ -274,11 +311,8 @@
             if (additionalWidthForParallax > MAX_PARALLAX) {
                 int widthToRemove = (int) Math.ceil(
                         (additionalWidthForParallax - MAX_PARALLAX) * screenRatio * crop.height());
-                if (rtl) {
-                    adjustedCrop.left += widthToRemove;
-                } else {
-                    adjustedCrop.right -= widthToRemove;
-                }
+                adjustedCrop.left += widthToRemove / 2;
+                adjustedCrop.right -= widthToRemove / 2 + widthToRemove % 2;
             }
         } else {
             // TODO (b/281648899) the third case is not always correct, fix that.
@@ -366,6 +400,24 @@
      */
     SparseArray<Rect> getDefaultCrops(SparseArray<Rect> suggestedCrops, Point bitmapSize) {
 
+        // If the suggested crops is single-element map with (ORIENTATION_UNKNOWN, cropHint),
+        // Crop the bitmap using the cropHint and compute the crops for cropped bitmap.
+        Rect cropHint = suggestedCrops.get(ORIENTATION_UNKNOWN);
+        if (cropHint != null) {
+            Rect bitmapRect = new Rect(0, 0, bitmapSize.x, bitmapSize.y);
+            if (suggestedCrops.size() != 1 || !bitmapRect.contains(cropHint)) {
+                Slog.w(TAG, "Couldn't get default crops from suggested crops " + suggestedCrops
+                        + " for bitmap of size " + bitmapSize + "; ignoring suggested crops");
+                return getDefaultCrops(new SparseArray<>(), bitmapSize);
+            }
+            Point cropSize = new Point(cropHint.width(), cropHint.height());
+            SparseArray<Rect> relativeDefaultCrops = getDefaultCrops(new SparseArray<>(), cropSize);
+            for (int i = 0; i < relativeDefaultCrops.size(); i++) {
+                relativeDefaultCrops.valueAt(i).offset(cropHint.left, cropHint.top);
+            }
+            return relativeDefaultCrops;
+        }
+
         SparseArray<Point> defaultDisplaySizes = mWallpaperDisplayHelper.getDefaultDisplaySizes();
         boolean rtl = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
                 == View.LAYOUT_DIRECTION_RTL;
@@ -422,28 +474,78 @@
         } else {
             boolean needCrop = false;
             boolean needScale;
-            boolean multiCrop = multiCrop() && wallpaper.mSupportsMultiCrop;
 
             Point bitmapSize = new Point(options.outWidth, options.outHeight);
+            Rect bitmapRect = new Rect(0, 0, bitmapSize.x, bitmapSize.y);
 
+            if (multiCrop()) {
+                // Check that the suggested crops per screen orientation are all within the bitmap.
+                for (int i = 0; i < wallpaper.mCropHints.size(); i++) {
+                    int orientation = wallpaper.mCropHints.keyAt(i);
+                    Rect crop = wallpaper.mCropHints.valueAt(i);
+                    if (crop.isEmpty() || !bitmapRect.contains(crop)) {
+                        Slog.w(TAG, "Invalid crop " + crop + " for orientation " + orientation
+                                + " and bitmap size " + bitmapSize + "; clearing suggested crops.");
+                        wallpaper.mCropHints.clear();
+                        wallpaper.cropHint.set(bitmapRect);
+                        break;
+                    }
+                }
+            }
             final Rect cropHint;
-            if (multiCrop) {
-                SparseArray<Rect> defaultDisplayCrops =
-                        getDefaultCrops(wallpaper.mCropHints, bitmapSize);
-                // adapt the entries in wallpaper.mCropHints for the actual display
+            final SparseArray<Rect> defaultCrops;
+
+            // A wallpaper with cropHints = Map.of(ORIENTATION_UNKNOWN, rect) is treated like
+            // a wallpaper with cropHints = null and  cropHint = rect.
+            Rect tempCropHint = wallpaper.mCropHints.get(ORIENTATION_UNKNOWN);
+            if (multiCrop() && tempCropHint != null) {
+                wallpaper.cropHint.set(tempCropHint);
+                wallpaper.mCropHints.clear();
+            }
+            if (multiCrop() && wallpaper.mCropHints.size() > 0) {
+                // Some suggested crops per screen orientation were provided,
+                // use them to compute the default crops for this device
+                defaultCrops = getDefaultCrops(wallpaper.mCropHints, bitmapSize);
+                // Adapt the provided crops to match the actual crops for the default display
                 SparseArray<Rect> updatedCropHints = new SparseArray<>();
                 for (int i = 0; i < wallpaper.mCropHints.size(); i++) {
                     int orientation = wallpaper.mCropHints.keyAt(i);
-                    Rect defaultCrop = defaultDisplayCrops.get(orientation);
+                    Rect defaultCrop = defaultCrops.get(orientation);
                     if (defaultCrop != null) {
                         updatedCropHints.put(orientation, defaultCrop);
                     }
                 }
                 wallpaper.mCropHints = updatedCropHints;
-                cropHint = getTotalCrop(defaultDisplayCrops);
+
+                // Finally, compute the cropHint based on the default crops
+                cropHint = getTotalCrop(defaultCrops);
                 wallpaper.cropHint.set(cropHint);
+                if (DEBUG) {
+                    Slog.d(TAG, "Generated default crops for wallpaper: " + defaultCrops
+                            + " based on suggested crops: " + wallpaper.mCropHints);
+                }
+            } else if (multiCrop()) {
+                // No crops per screen orientation were provided, but an overall cropHint may be
+                // defined in wallpaper.cropHint. Compute the default crops for the sub-image
+                // defined by the cropHint, then recompute the cropHint based on the default crops.
+                // If the cropHint is empty or invalid, ignore it and use the full image.
+                if (wallpaper.cropHint.isEmpty()) wallpaper.cropHint.set(bitmapRect);
+                if (!bitmapRect.contains(wallpaper.cropHint)) {
+                    Slog.w(TAG, "Ignoring wallpaper.cropHint = " + wallpaper.cropHint
+                            + "; not within the bitmap of size " + bitmapSize);
+                    wallpaper.cropHint.set(bitmapRect);
+                }
+                Point cropSize = new Point(wallpaper.cropHint.width(), wallpaper.cropHint.height());
+                defaultCrops = getDefaultCrops(new SparseArray<>(), cropSize);
+                cropHint = getTotalCrop(defaultCrops);
+                cropHint.offset(wallpaper.cropHint.left, wallpaper.cropHint.top);
+                wallpaper.cropHint.set(cropHint);
+                if (DEBUG) {
+                    Slog.d(TAG, "Generated default crops for wallpaper: " + defaultCrops);
+                }
             } else {
                 cropHint = new Rect(wallpaper.cropHint);
+                defaultCrops = null;
             }
 
             if (DEBUG) {
@@ -455,11 +557,11 @@
             }
 
             // Empty crop means use the full image
-            if (cropHint.isEmpty()) {
+            if (!multiCrop() && cropHint.isEmpty()) {
                 cropHint.left = cropHint.top = 0;
                 cropHint.right = options.outWidth;
                 cropHint.bottom = options.outHeight;
-            } else {
+            } else if (!multiCrop()) {
                 // force the crop rect to lie within the measured bounds
                 int dx = cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0;
                 int dy = cropHint.bottom > options.outHeight
@@ -473,19 +575,46 @@
                 if (cropHint.top < 0) {
                     cropHint.top = 0;
                 }
-
-                // Don't bother cropping if what we're left with is identity
-                needCrop = (options.outHeight > cropHint.height()
-                        || options.outWidth > cropHint.width());
             }
 
+            // Don't bother cropping if what we're left with is identity
+            needCrop = (options.outHeight > cropHint.height()
+                    || options.outWidth > cropHint.width());
+
             // scale if the crop height winds up not matching the recommended metrics
             needScale = cropHint.height() > wpData.mHeight
                     || cropHint.height() > GLHelper.getMaxTextureSize()
                     || cropHint.width() > GLHelper.getMaxTextureSize();
 
+            float sampleSize = Float.MAX_VALUE;
+            if (multiCrop()) {
+                // If all crops for all orientations have more width and height in pixel
+                // than the display for this orientation, downsample the image
+                for (int i = 0; i < defaultCrops.size(); i++) {
+                    int orientation = defaultCrops.keyAt(i);
+                    Rect crop = defaultCrops.valueAt(i);
+                    Point displayForThisOrientation = mWallpaperDisplayHelper
+                            .getDefaultDisplaySizes().get(orientation);
+                    if (displayForThisOrientation == null) continue;
+                    float sampleSizeForThisOrientation = Math.max(1f, Math.min(
+                            crop.width() / displayForThisOrientation.x,
+                            crop.height() / displayForThisOrientation.y));
+                    sampleSize = Math.min(sampleSize, sampleSizeForThisOrientation);
+                }
+                // If the total crop has more width or height than either the max texture size
+                // or twice the largest display dimension, downsample the image
+                int maxCropSize = Math.min(
+                        2 * mWallpaperDisplayHelper.getDefaultDisplayLargestDimension(),
+                        GLHelper.getMaxTextureSize());
+                float minimumSampleSize = Math.max(1f, Math.max(
+                        (float) cropHint.height() / maxCropSize,
+                        (float) cropHint.width()) / maxCropSize);
+                sampleSize = Math.max(sampleSize, minimumSampleSize);
+                needScale = sampleSize > 1f;
+            }
+
             //make sure screen aspect ratio is preserved if width is scaled under screen size
-            if (needScale && !multiCrop) {
+            if (needScale && !multiCrop()) {
                 final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
                 final int newWidth = (int) (cropHint.width() * scaleByHeight);
                 if (newWidth < displayInfo.logicalWidth) {
@@ -498,7 +627,8 @@
 
             if (DEBUG_CROP) {
                 Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
-                Slog.v(TAG, "dims: w=" + wpData.mWidth + " h=" + wpData.mHeight);
+                if (multiCrop()) Slog.v(TAG, "defaultCrops: " + defaultCrops);
+                if (!multiCrop()) Slog.v(TAG, "dims: w=" + wpData.mWidth + " h=" + wpData.mHeight);
                 Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
                 Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
             }
@@ -541,28 +671,17 @@
                     options.inJustDecodeBounds = false;
 
                     final Rect estimateCrop = new Rect(cropHint);
-                    estimateCrop.scale(1f / options.inSampleSize);
+                    if (!multiCrop()) estimateCrop.scale(1f / options.inSampleSize);
+                    else estimateCrop.scale(1f / sampleSize);
                     float hRatio = (float) wpData.mHeight / estimateCrop.height();
-                    if (multiCrop) {
-                        // make sure the crop height is at most the display largest dimension
-                        hRatio = (float) mWallpaperDisplayHelper.getDefaultDisplayLargestDimension()
-                                / estimateCrop.height();
-                        hRatio = Math.min(hRatio, 1f);
-                    }
                     final int destHeight = (int) (estimateCrop.height() * hRatio);
                     final int destWidth = (int) (estimateCrop.width() * hRatio);
 
                     // We estimated an invalid crop, try to adjust the cropHint to get a valid one.
-                    if (destWidth > GLHelper.getMaxTextureSize()) {
+                    if (!multiCrop() && destWidth > GLHelper.getMaxTextureSize()) {
                         if (DEBUG) {
                             Slog.w(TAG, "Invalid crop dimensions, trying to adjust.");
                         }
-                        if (multiCrop) {
-                            // clear custom crop guidelines, fallback to system default
-                            wallpaper.mCropHints.clear();
-                            generateCropInternal(wallpaper);
-                            return;
-                        }
 
                         int newHeight = (int) (wpData.mHeight / hRatio);
                         int newWidth = (int) (wpData.mWidth / hRatio);
@@ -579,16 +698,27 @@
                     // We've got the safe cropHint; now we want to scale it properly to
                     // the desired rectangle.
                     // That's a height-biased operation: make it fit the hinted height.
-                    final int safeHeight = (int) (estimateCrop.height() * hRatio + 0.5f);
-                    final int safeWidth = (int) (estimateCrop.width() * hRatio + 0.5f);
+                    final int safeHeight = !multiCrop()
+                            ? (int) (estimateCrop.height() * hRatio + 0.5f)
+                            : (int) (cropHint.height() / sampleSize + 0.5f);
+                    final int safeWidth = !multiCrop()
+                            ? (int) (estimateCrop.width() * hRatio + 0.5f)
+                            : (int) (cropHint.width() / sampleSize + 0.5f);
 
                     if (DEBUG_CROP) {
                         Slog.v(TAG, "Decode parameters:");
-                        Slog.v(TAG, "  cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
-                        Slog.v(TAG, "  down sampling=" + options.inSampleSize
-                                + ", hRatio=" + hRatio);
-                        Slog.v(TAG, "  dest=" + destWidth + "x" + destHeight);
-                        Slog.v(TAG, "  safe=" + safeWidth + "x" + safeHeight);
+                        if (!multiCrop()) {
+                            Slog.v(TAG,
+                                    "  cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
+                            Slog.v(TAG, "  down sampling=" + options.inSampleSize
+                                    + ", hRatio=" + hRatio);
+                            Slog.v(TAG, "  dest=" + destWidth + "x" + destHeight);
+                        }
+                        if (multiCrop()) {
+                            Slog.v(TAG, "  cropHint=" + cropHint);
+                            Slog.v(TAG, "  sampleSize=" + sampleSize);
+                        }
+                        Slog.v(TAG, "  targetSize=" + safeWidth + "x" + safeHeight);
                         Slog.v(TAG, "  maxTextureSize=" + GLHelper.getMaxTextureSize());
                     }
 
@@ -603,24 +733,28 @@
 
                     final ImageDecoder.Source srcData =
                             ImageDecoder.createSource(wallpaper.getWallpaperFile());
-                    final int sampleSize = scale;
+                    final int finalScale = scale;
+                    final int rescaledBitmapWidth = (int) (0.5f + bitmapSize.x / sampleSize);
+                    final int rescaledBitmapHeight = (int) (0.5f + bitmapSize.y / sampleSize);
                     Bitmap cropped = ImageDecoder.decodeBitmap(srcData, (decoder, info, src) -> {
-                        decoder.setTargetSampleSize(sampleSize);
+                        if (!multiCrop()) decoder.setTargetSampleSize(finalScale);
+                        if (multiCrop()) {
+                            decoder.setTargetSize(rescaledBitmapWidth, rescaledBitmapHeight);
+                        }
                         decoder.setCrop(estimateCrop);
                     });
 
                     record.delete();
 
-                    if (cropped == null) {
+                    if (!multiCrop() && cropped == null) {
                         Slog.e(TAG, "Could not decode new wallpaper");
                     } else {
                         // We are safe to create final crop with safe dimensions now.
-                        final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
-                                safeWidth, safeHeight, true);
+                        final Bitmap finalCrop = multiCrop() ? cropped
+                                : Bitmap.createScaledBitmap(cropped, safeWidth, safeHeight, true);
 
-                        if (multiCrop) {
-                            wallpaper.mSampleSize =
-                                    ((float) cropHint.height()) / finalCrop.getHeight();
+                        if (multiCrop()) {
+                            wallpaper.mSampleSize = sampleSize;
                         }
 
                         if (DEBUG) {
@@ -639,9 +773,7 @@
                         success = true;
                     }
                 } catch (Exception e) {
-                    if (DEBUG) {
-                        Slog.e(TAG, "Error decoding crop", e);
-                    }
+                    Slog.e(TAG, "Error decoding crop", e);
                 } finally {
                     IoUtils.closeQuietly(bos);
                     IoUtils.closeQuietly(f);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperData.java b/services/core/java/com/android/server/wallpaper/WallpaperData.java
index 02594d2..b792f79 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperData.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperData.java
@@ -172,11 +172,6 @@
     SparseArray<Rect> mCropHints = new SparseArray<>();
 
     /**
-     * cropHints will be ignored if this flag is false
-     */
-    boolean mSupportsMultiCrop;
-
-    /**
      * The phone orientation when the wallpaper was set. Only relevant for image wallpapers
      */
     int mOrientationWhenSet = ORIENTATION_UNKNOWN;
@@ -204,7 +199,6 @@
         if (source.mCropHints != null) {
             this.mCropHints = source.mCropHints.clone();
         }
-        this.mSupportsMultiCrop = source.mSupportsMultiCrop;
         this.allowBackup = source.allowBackup;
         this.primaryColors = source.primaryColors;
         this.mWallpaperDimAmount = source.mWallpaperDimAmount;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
index 7f53ea3..4aefb54 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
@@ -324,10 +324,7 @@
                 getAttributeInt(parser, "totalCropTop", 0),
                 getAttributeInt(parser, "totalCropRight", 0),
                 getAttributeInt(parser, "totalCropBottom", 0));
-        wallpaper.mSupportsMultiCrop = multiCrop() && (
-                parser.getAttributeBoolean(null, "supportsMultiCrop", false)
-                || mImageWallpaper.equals(wallpaper.wallpaperComponent));
-        if (wallpaper.mSupportsMultiCrop) {
+        if (multiCrop() && mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
             wallpaper.mCropHints = new SparseArray<>();
             for (Pair<Integer, String> pair: screenDimensionPairs()) {
                 Rect cropHint = new Rect(
@@ -342,16 +339,14 @@
             }
             if (wallpaper.mCropHints.size() == 0 && totalCropHint.isEmpty()) {
                 // migration case: the crops per screen orientation are not specified.
-                int orientation = legacyCropHint.width() < legacyCropHint.height()
-                        ? WallpaperManager.PORTRAIT : WallpaperManager.LANDSCAPE;
                 if (!legacyCropHint.isEmpty()) {
-                    wallpaper.mCropHints.put(orientation, legacyCropHint);
+                    wallpaper.cropHint.set(legacyCropHint);
                 }
             } else {
                 wallpaper.cropHint.set(totalCropHint);
             }
             wallpaper.mSampleSize = parser.getAttributeFloat(null, "sampleSize", 1f);
-        } else {
+        } else if (!multiCrop()) {
             wallpaper.cropHint.set(legacyCropHint);
         }
         final DisplayData wpData = mWallpaperDisplayHelper
@@ -467,13 +462,12 @@
         out.startTag(null, tag);
         out.attributeInt(null, "id", wallpaper.wallpaperId);
 
-        out.attributeBoolean(null, "supportsMultiCrop", wallpaper.mSupportsMultiCrop);
-
-        if (multiCrop() && wallpaper.mSupportsMultiCrop) {
+        if (multiCrop() && mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
             if (wallpaper.mCropHints == null) {
                 Slog.e(TAG, "cropHints should not be null when saved");
                 wallpaper.mCropHints = new SparseArray<>();
             }
+            Rect rectToPutInLegacyCrop = new Rect(wallpaper.cropHint);
             for (Pair<Integer, String> pair : screenDimensionPairs()) {
                 Rect cropHint = wallpaper.mCropHints.get(pair.first);
                 if (cropHint == null) continue;
@@ -493,12 +487,14 @@
                     }
                 }
                 if (pair.first == orientationToPutInLegacyCrop) {
-                    out.attributeInt(null, "cropLeft", cropHint.left);
-                    out.attributeInt(null, "cropTop", cropHint.top);
-                    out.attributeInt(null, "cropRight", cropHint.right);
-                    out.attributeInt(null, "cropBottom", cropHint.bottom);
+                    rectToPutInLegacyCrop.set(cropHint);
                 }
             }
+            out.attributeInt(null, "cropLeft", rectToPutInLegacyCrop.left);
+            out.attributeInt(null, "cropTop", rectToPutInLegacyCrop.top);
+            out.attributeInt(null, "cropRight", rectToPutInLegacyCrop.right);
+            out.attributeInt(null, "cropBottom", rectToPutInLegacyCrop.bottom);
+
             out.attributeInt(null, "totalCropLeft", wallpaper.cropHint.left);
             out.attributeInt(null, "totalCropTop", wallpaper.cropHint.top);
             out.attributeInt(null, "totalCropRight", wallpaper.cropHint.right);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java b/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java
index 9e1b5d2..3636f5a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java
@@ -59,6 +59,8 @@
     }
 
     private static final String TAG = WallpaperDisplayHelper.class.getSimpleName();
+    private static final float LARGE_SCREEN_MIN_DP = 600f;
+
     private final SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
     private final DisplayManager mDisplayManager;
     private final WindowManagerInternal mWindowManagerInternal;
@@ -67,7 +69,8 @@
     // related orientations pairs for foldable (folded orientation, unfolded orientation)
     private final List<Pair<Integer, Integer>> mFoldableOrientationPairs = new ArrayList<>();
 
-    private boolean mIsFoldable;
+    private final boolean mIsFoldable;
+    private boolean mIsLargeScreen = false;
 
     WallpaperDisplayHelper(
             DisplayManager displayManager,
@@ -94,6 +97,9 @@
                     mDefaultDisplaySizes.put(orientation, point);
                 }
             }
+
+            mIsLargeScreen |= (displaySize.x / metric.getDensity() >= LARGE_SCREEN_MIN_DP);
+
             if (populateOrientationPairs) {
                 int orientation = WallpaperManager.getOrientation(displaySize);
                 float newSurface = displaySize.x * displaySize.y
@@ -215,6 +221,13 @@
     }
 
     /**
+     * Return true if any of the screens of the default display is considered large (DP >= 600)
+     */
+    boolean isLargeScreen() {
+        return mIsLargeScreen;
+    }
+
+    /**
      * If a given orientation corresponds to an unfolded orientation on foldable, return the
      * corresponding folded orientation. Otherwise, return UNKNOWN. Always return UNKNOWN if the
      * device is not a foldable.
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 885baf6..f1ba755 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -42,6 +42,7 @@
 import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
 import static com.android.server.wallpaper.WallpaperUtils.makeWallpaperIdLocked;
 import static com.android.window.flags.Flags.multiCrop;
+import static com.android.window.flags.Flags.offloadColorExtraction;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
@@ -131,6 +132,9 @@
 import com.android.server.wallpaper.WallpaperData.BindSource;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.UsesReflection;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -166,6 +170,13 @@
         }
 
         @Override
+        @UsesReflection(
+                value = {
+                    @KeepTarget(
+                            kind = KeepItemKind.CLASS_AND_MEMBERS,
+                            instanceOfClassConstantExclusive = IWallpaperManagerService.class,
+                            methodName = "<init>")
+                })
         public void onStart() {
             try {
                 final Class<? extends IWallpaperManagerService> klass =
@@ -380,7 +391,7 @@
             }
 
             // Outside of the lock since it will synchronize itself
-            notifyWallpaperColorsChanged(wallpaper);
+            if (!offloadColorExtraction()) notifyWallpaperColorsChanged(wallpaper);
         }
 
         @Override
@@ -403,12 +414,16 @@
     }
 
     void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper) {
+        notifyWallpaperColorsChanged(wallpaper, wallpaper.mWhich);
+    }
+
+    private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
         if (DEBUG) {
             Slog.i(TAG, "Notifying wallpaper colors changed");
         }
         if (wallpaper.connection != null) {
             wallpaper.connection.forEachDisplayConnector(connector ->
-                    notifyWallpaperColorsChangedOnDisplay(wallpaper, connector.mDisplayId));
+                    notifyWallpaperColorsChangedOnDisplay(wallpaper, connector.mDisplayId, which));
         }
     }
 
@@ -425,6 +440,11 @@
 
     private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper,
             int displayId) {
+        notifyWallpaperColorsChangedOnDisplay(wallpaper, displayId, wallpaper.mWhich);
+    }
+
+    private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper,
+            int displayId, int which) {
         boolean needsExtraction;
         synchronized (mLock) {
             final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
@@ -449,8 +469,8 @@
             notify = extractColors(wallpaper);
         }
         if (notify) {
-            notifyColorListeners(getAdjustedWallpaperColorsOnDimming(wallpaper),
-                    wallpaper.mWhich, wallpaper.userId, displayId);
+            notifyColorListeners(getAdjustedWallpaperColorsOnDimming(wallpaper), which,
+                    wallpaper.userId, displayId);
         }
     }
 
@@ -504,6 +524,7 @@
      * @return true unless the wallpaper changed during the color computation
      */
     private boolean extractColors(WallpaperData wallpaper) {
+        if (offloadColorExtraction()) return !mImageWallpaper.equals(wallpaper.wallpaperComponent);
         String cropFile = null;
         boolean defaultImageWallpaper = false;
         int wallpaperId;
@@ -803,7 +824,7 @@
                     null /* options */);
             mWindowManagerInternal.setWallpaperShowWhenLocked(
                     mToken, (wallpaper.mWhich & FLAG_LOCK) != 0);
-            if (multiCrop() && wallpaper.mSupportsMultiCrop) {
+            if (multiCrop() && mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
                 mWindowManagerInternal.setWallpaperCropHints(mToken,
                         mWallpaperCropper.getRelativeCropHints(wallpaper));
             } else {
@@ -1148,10 +1169,16 @@
             synchronized (mLock) {
                 // Do not broadcast changes on ImageWallpaper since it's handled
                 // internally by this class.
-                if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
+                boolean isImageWallpaper = mImageWallpaper.equals(mWallpaper.wallpaperComponent);
+                if (isImageWallpaper && (!offloadColorExtraction() || primaryColors == null)) {
                     return;
                 }
                 mWallpaper.primaryColors = primaryColors;
+                // only save the colors for ImageWallpaper - for live wallpapers, the colors
+                // are always recomputed after a reboot.
+                if (offloadColorExtraction() && isImageWallpaper) {
+                    saveSettingsLocked(mWallpaper.userId);
+                }
             }
             notifyWallpaperColorsChangedOnDisplay(mWallpaper, displayId);
         }
@@ -1177,7 +1204,9 @@
                 try {
                     // This will trigger onComputeColors in the wallpaper engine.
                     // It's fine to be locked in here since the binder is oneway.
-                    connector.mEngine.requestWallpaperColors();
+                    if (!offloadColorExtraction() || mWallpaper.primaryColors == null) {
+                        connector.mEngine.requestWallpaperColors();
+                    }
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to request wallpaper colors", e);
                 }
@@ -1811,6 +1840,7 @@
             // Offload color extraction to another thread since switchUser will be called
             // from the main thread.
             FgThread.getHandler().post(() -> {
+                if (offloadColorExtraction()) return;
                 notifyWallpaperColorsChanged(systemWallpaper);
                 if (lockWallpaper != systemWallpaper) notifyWallpaperColorsChanged(lockWallpaper);
                 notifyWallpaperColorsChanged(mFallbackWallpaper);
@@ -1917,11 +1947,17 @@
             final ComponentName component;
             final int finalWhich;
 
-            if ((which & FLAG_LOCK) > 0 && lockWallpaper != null) {
-                clearWallpaperBitmaps(lockWallpaper);
-            }
-            if ((which & FLAG_SYSTEM) > 0) {
-                clearWallpaperBitmaps(wallpaper);
+            // Clear any previous ImageWallpaper related fields
+            List<WallpaperData> toClear = new ArrayList<>();
+            if ((which & FLAG_LOCK) > 0 && lockWallpaper != null) toClear.add(lockWallpaper);
+            if ((which & FLAG_SYSTEM) > 0) toClear.add(wallpaper);
+            for (WallpaperData wallpaperToClear : toClear) {
+                clearWallpaperBitmaps(wallpaperToClear);
+                if (multiCrop()) {
+                    wallpaperToClear.mCropHints.clear();
+                    wallpaperToClear.cropHint.set(0, 0, 0, 0);
+                    wallpaperToClear.mSampleSize = 1;
+                }
             }
 
             // lock only case: set the system wallpaper component to both screens
@@ -2225,12 +2261,20 @@
             checkPermission(READ_WALLPAPER_INTERNAL);
             WallpaperData wallpaper = (which == FLAG_LOCK) ? mLockWallpaperMap.get(userId)
                     : mWallpaperMap.get(userId);
-            if (wallpaper == null || !wallpaper.mSupportsMultiCrop) return null;
+            if (wallpaper == null || !mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
+                return null;
+            }
             SparseArray<Rect> relativeSuggestedCrops =
                     mWallpaperCropper.getRelativeCropHints(wallpaper);
             Point croppedBitmapSize = new Point(
                     (int) (0.5f + wallpaper.cropHint.width() / wallpaper.mSampleSize),
                     (int) (0.5f + wallpaper.cropHint.height() / wallpaper.mSampleSize));
+            if (croppedBitmapSize.equals(0, 0)) {
+                // There is an ImageWallpaper, but there are no crop hints and the bitmap size is
+                // unknown (e.g. the default wallpaper). Return a special "null" value that will be
+                // handled by WallpaperManager, which will fetch the dimensions of the wallpaper.
+                return null;
+            }
             SparseArray<Rect> relativeDefaultCrops =
                     mWallpaperCropper.getDefaultCrops(relativeSuggestedCrops, croppedBitmapSize);
             SparseArray<Rect> adjustedRelativeSuggestedCrops = new SparseArray<>();
@@ -2255,7 +2299,7 @@
     @Override
     public List<Rect> getFutureBitmapCrops(Point bitmapSize, List<Point> displaySizes,
             int[] screenOrientations, List<Rect> crops) {
-        SparseArray<Rect> cropMap = getCropMap(screenOrientations, crops, ORIENTATION_UNKNOWN);
+        SparseArray<Rect> cropMap = getCropMap(screenOrientations, crops);
         SparseArray<Rect> defaultCrops = mWallpaperCropper.getDefaultCrops(cropMap, bitmapSize);
         List<Rect> result = new ArrayList<>();
         boolean rtl = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
@@ -2272,7 +2316,7 @@
             throw new UnsupportedOperationException(
                     "This method should only be called with the multi crop flag enabled");
         }
-        SparseArray<Rect> cropMap = getCropMap(screenOrientations, crops, ORIENTATION_UNKNOWN);
+        SparseArray<Rect> cropMap = getCropMap(screenOrientations, crops);
         SparseArray<Rect> defaultCrops = mWallpaperCropper.getDefaultCrops(cropMap, bitmapSize);
         return WallpaperCropper.getTotalCrop(defaultCrops);
     }
@@ -2714,8 +2758,10 @@
                         });
                         // Need to extract colors again to re-calculate dark hints after
                         // applying dimming.
-                        wp.mIsColorExtractedFromDim = true;
-                        pendingColorExtraction.add(wp);
+                        if (!offloadColorExtraction()) {
+                            wp.mIsColorExtractedFromDim = true;
+                            pendingColorExtraction.add(wp);
+                        }
                         changed = true;
                     }
                 }
@@ -2724,7 +2770,7 @@
                 }
             }
             for (WallpaperData wp: pendingColorExtraction) {
-                notifyWallpaperColorsChanged(wp);
+                if (!offloadColorExtraction()) notifyWallpaperColorsChanged(wp);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -2860,10 +2906,8 @@
             return null;
         }
 
-        int currentOrientation = mWallpaperDisplayHelper.getDefaultDisplayCurrentOrientation();
-        SparseArray<Rect> cropMap = !multiCrop() ? null
-                : getCropMap(screenOrientations, crops, currentOrientation);
-        Rect cropHint = multiCrop() || crops == null ? null : crops.get(0);
+        SparseArray<Rect> cropMap = !multiCrop() ? null : getCropMap(screenOrientations, crops);
+        Rect cropHint = multiCrop() || crops == null || crops.isEmpty() ? new Rect() : crops.get(0);
         final boolean fromForegroundApp = !multiCrop() ? false
                 : isFromForegroundApp(callingPackage);
 
@@ -2912,12 +2956,16 @@
                     wallpaper.setComplete = completion;
                     wallpaper.fromForegroundApp = multiCrop() ? fromForegroundApp
                             : isFromForegroundApp(callingPackage);
-                    if (!multiCrop()) wallpaper.cropHint.set(cropHint);
-                    if (multiCrop()) wallpaper.mSupportsMultiCrop = true;
-                    if (multiCrop()) wallpaper.mCropHints = cropMap;
+                    wallpaper.cropHint.set(cropHint);
+                    if (multiCrop()) {
+                        wallpaper.mCropHints = cropMap;
+                        wallpaper.mSampleSize = 1f;
+                        wallpaper.mOrientationWhenSet =
+                                mWallpaperDisplayHelper.getDefaultDisplayCurrentOrientation();
+                    }
                     wallpaper.allowBackup = allowBackup;
                     wallpaper.mWallpaperDimAmount = getWallpaperDimAmount();
-                    wallpaper.mOrientationWhenSet = currentOrientation;
+                    if (offloadColorExtraction()) wallpaper.primaryColors = null;
                 }
                 return pfd;
             } finally {
@@ -2926,16 +2974,14 @@
         }
     }
 
-    private SparseArray<Rect> getCropMap(int[] screenOrientations, List<Rect> crops,
-            int currentOrientation) {
+    private SparseArray<Rect> getCropMap(int[] screenOrientations, List<Rect> crops) {
         if ((crops == null ^ screenOrientations == null)
                 || (crops != null && crops.size() != screenOrientations.length)) {
             throw new IllegalArgumentException(
                     "Illegal crops/orientations lists: must both be null, or both the same size");
         }
         SparseArray<Rect> cropMap = new SparseArray<>();
-        boolean unknown = false;
-        if (crops != null && crops.size() != 0) {
+        if (crops != null && !crops.isEmpty()) {
             for (int i = 0; i < crops.size(); i++) {
                 Rect crop = crops.get(i);
                 int width = crop.width(), height = crop.height();
@@ -2943,22 +2989,13 @@
                     throw new IllegalArgumentException("Invalid crop rect supplied: " + crop);
                 }
                 int orientation = screenOrientations[i];
-                if (orientation == ORIENTATION_UNKNOWN) {
-                    if (currentOrientation == ORIENTATION_UNKNOWN) {
-                        throw new IllegalArgumentException(
-                                "Invalid orientation: " + ORIENTATION_UNKNOWN);
-                    }
-                    unknown = true;
-                    orientation = currentOrientation;
+                if (orientation == ORIENTATION_UNKNOWN && cropMap.size() > 1) {
+                    throw new IllegalArgumentException("Invalid crops supplied: the UNKNOWN"
+                            + "screen orientation should only be used in a singleton map");
                 }
                 cropMap.put(orientation, crop);
             }
         }
-        if (unknown && cropMap.size() > 1) {
-            throw new IllegalArgumentException("Invalid crops supplied: the UNKNOWN screen "
-                    + "orientation should only be used in a singleton map (in which case it"
-                    + "represents the current orientation of the default display)");
-        }
         return cropMap;
     }
 
@@ -2975,7 +3012,6 @@
         WallpaperData lockWP = new WallpaperData(userId, FLAG_LOCK);
         lockWP.wallpaperId = sysWP.wallpaperId;
         lockWP.cropHint.set(sysWP.cropHint);
-        lockWP.mSupportsMultiCrop = sysWP.mSupportsMultiCrop;
         if (sysWP.mCropHints != null) {
             lockWP.mCropHints = sysWP.mCropHints.clone();
         }
@@ -3072,6 +3108,10 @@
         checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
 
         boolean shouldNotifyColors = false;
+
+        // If the lockscreen wallpaper is set to the same as the home screen, notify that the
+        // lockscreen wallpaper colors changed, even if we don't bind a new wallpaper engine.
+        boolean shouldNotifyLockscreenColors = false;
         boolean bindSuccess;
         final WallpaperData newWallpaper;
 
@@ -3096,7 +3136,6 @@
             final long ident = Binder.clearCallingIdentity();
 
             try {
-                newWallpaper.mSupportsMultiCrop = mImageWallpaper.equals(name);
                 newWallpaper.imageWallpaperPending = false;
                 newWallpaper.mWhich = which;
                 newWallpaper.mSystemWasBoth = systemIsBoth;
@@ -3118,7 +3157,7 @@
                 bindSuccess = bindWallpaperComponentLocked(name, /* force */
                         forceRebind, /* fromUser */ true, newWallpaper, reply);
                 if (bindSuccess) {
-                    if (!same) {
+                    if (!same || (offloadColorExtraction() && forceRebind)) {
                         newWallpaper.primaryColors = null;
                     } else {
                         if (newWallpaper.connection != null) {
@@ -3142,6 +3181,11 @@
                     newWallpaper.wallpaperId = makeWallpaperIdLocked();
                     notifyCallbacksLocked(newWallpaper);
                     shouldNotifyColors = true;
+                    if (offloadColorExtraction()) {
+                        shouldNotifyColors = false;
+                        shouldNotifyLockscreenColors = !force && same && !systemIsBoth
+                                && which == (FLAG_SYSTEM | FLAG_LOCK);
+                    }
 
                     if (which == (FLAG_SYSTEM | FLAG_LOCK)) {
                         if (DEBUG) {
@@ -3170,6 +3214,10 @@
         if (shouldNotifyColors) {
             notifyWallpaperColorsChanged(newWallpaper);
         }
+        if (shouldNotifyLockscreenColors) {
+            notifyWallpaperColorsChanged(newWallpaper, FLAG_LOCK);
+        }
+
         return bindSuccess;
     }
 
diff --git a/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java b/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java
index eb170b7..36e5200 100644
--- a/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java
+++ b/services/core/java/com/android/server/wearable/WearableSensingManagerPerUserService.java
@@ -17,6 +17,9 @@
 package com.android.server.wearable;
 
 import static android.service.wearable.WearableSensingService.HOTWORD_AUDIO_STREAM_BUNDLE_KEY;
+import static android.system.OsConstants.F_GETFL;
+import static android.system.OsConstants.O_ACCMODE;
+import static android.system.OsConstants.O_RDONLY;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -42,6 +45,8 @@
 import android.service.voice.HotwordAudioStream;
 import android.service.voice.VoiceInteractionManagerInternal;
 import android.service.voice.VoiceInteractionManagerInternal.WearableHotwordDetectionCallback;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.system.OsConstants;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
@@ -276,7 +281,10 @@
             ParcelFileDescriptor parcelFileDescriptor,
             @Nullable IWearableSensingCallback wearableSensingCallback,
             RemoteCallback statusCallback) {
-        Slog.i(TAG, "onProvideDataStream in per user service.");
+        Slog.i(
+                TAG,
+                "onProvideDataStream in per user service. Is data stream read-only? "
+                        + isReadOnly(parcelFileDescriptor));
         synchronized (mLock) {
             if (!setUpServiceIfNeeded()) {
                 Slog.w(TAG, "Detection service is not available at this moment.");
@@ -505,10 +513,53 @@
                     String filename,
                     AndroidFuture<ParcelFileDescriptor> futureFromWearableSensingService)
                     throws RemoteException {
-                // TODO(b/331395522): Intercept the PFD received from the app process and verify it
-                // is read-only
-                callbackFromAppProcess.openFile(filename, futureFromWearableSensingService);
+                AndroidFuture<ParcelFileDescriptor> futureFromSystemServer =
+                        new AndroidFuture<ParcelFileDescriptor>()
+                                .whenComplete(
+                                        (pfdFromApp, throwable) -> {
+                                            if (throwable != null) {
+                                                Slog.e(
+                                                        TAG,
+                                                        "Error when reading file " + filename,
+                                                        throwable);
+                                                futureFromWearableSensingService.complete(null);
+                                                return;
+                                            }
+                                            if (pfdFromApp == null) {
+                                                futureFromWearableSensingService.complete(null);
+                                                return;
+                                            }
+                                            if (isReadOnly(pfdFromApp)) {
+                                                futureFromWearableSensingService.complete(
+                                                        pfdFromApp);
+                                            } else {
+                                                Slog.w(
+                                                        TAG,
+                                                        "Received writable ParcelFileDescriptor"
+                                                            + " from app process. To prevent"
+                                                            + " arbitrary data egress, sending null"
+                                                            + " to WearableSensingService"
+                                                            + " instead.");
+                                                futureFromWearableSensingService.complete(null);
+                                            }
+                                        });
+                callbackFromAppProcess.openFile(filename, futureFromSystemServer);
             }
         };
     }
+
+    private static boolean isReadOnly(ParcelFileDescriptor parcelFileDescriptor) {
+        try {
+            int readMode =
+                    Os.fcntlInt(parcelFileDescriptor.getFileDescriptor(), F_GETFL, 0) & O_ACCMODE;
+            return readMode == O_RDONLY;
+        } catch (ErrnoException ex) {
+            Slog.w(
+                    TAG,
+                    "Error encountered when trying to determine if the parcelFileDescriptor is"
+                        + " read-only. Treating it as not read-only",
+                    ex);
+        }
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 5e34596..a821f545 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -35,6 +35,7 @@
 import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
+import android.util.Slog;
 import android.webkit.UserPackage;
 import android.webkit.WebViewFactory;
 import android.webkit.WebViewProviderInfo;
@@ -201,6 +202,7 @@
             ActivityManager.getService().killPackageDependents(packageName,
                     UserHandle.USER_ALL);
         } catch (RemoteException e) {
+            Slog.wtf(TAG, "failed to call killPackageDependents for " + packageName, e);
         }
     }
 
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 532ff98..dcf20f9 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -186,9 +186,12 @@
                 }
                 onWebViewProviderChanged(mCurrentWebViewPackage);
             }
+        } catch (WebViewPackageMissingException e) {
+            Slog.e(TAG, "Could not find valid WebView package to create relro with", e);
         } catch (Throwable t) {
-            // Log and discard errors at this stage as we must not crash the system server.
-            Slog.e(TAG, "error preparing webview provider from system server", t);
+            // We don't know a case when this should happen but we log and discard errors at this
+            // stage as we must not crash the system server.
+            Slog.wtf(TAG, "error preparing webview provider from system server", t);
         }
 
         if (getCurrentWebViewPackage() == null) {
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java
index fb338ba..993597e 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java
@@ -247,9 +247,12 @@
                 attemptRepair();
             }
 
+        } catch (WebViewPackageMissingException e) {
+            Slog.e(TAG, "Could not find valid WebView package to create relro with", e);
         } catch (Throwable t) {
-            // Log and discard errors at this stage as we must not crash the system server.
-            Slog.e(TAG, "error preparing webview provider from system server", t);
+            // We don't know a case when this should happen but we log and discard errors at this
+            // stage as we must not crash the system server.
+            Slog.wtf(TAG, "error preparing webview provider from system server", t);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 2b43326..e280bdc 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -466,20 +466,17 @@
         }
     }
 
-    void drawMagnifiedRegionBorderIfNeeded(int displayId) {
-        if (Flags.alwaysDrawMagnificationFullscreenBorder()) {
-            return;
-        }
-
+    void recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded(int displayId) {
         if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
             mAccessibilityTracing.logTrace(
-                    TAG + ".drawMagnifiedRegionBorderIfNeeded",
+                    TAG + ".recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded",
                     FLAGS_MAGNIFICATION_CALLBACK,
                     "displayId=" + displayId);
         }
+
         final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
         if (displayMagnifier != null) {
-            displayMagnifier.drawMagnifiedRegionBorderIfNeeded();
+            displayMagnifier.recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded();
         }
         // Not relevant for the window observer.
     }
@@ -936,11 +933,13 @@
             }
         }
 
-        void drawMagnifiedRegionBorderIfNeeded() {
+        void recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded() {
             if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
-                mAccessibilityTracing.logTrace(LOG_TAG + ".drawMagnifiedRegionBorderIfNeeded",
+                mAccessibilityTracing.logTrace(LOG_TAG
+                                + ".recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded",
                         FLAGS_MAGNIFICATION_CALLBACK);
             }
+            recomputeBounds();
 
             if (!Flags.alwaysDrawMagnificationFullscreenBorder()) {
                 mMagnifiedViewport.drawWindowIfNeeded();
@@ -1245,7 +1244,6 @@
             }
 
             void drawWindowIfNeeded() {
-                recomputeBounds();
                 mWindow.postDrawIfNeeded();
             }
 
diff --git a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
index 9647a62..521f64f 100644
--- a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
+++ b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
@@ -389,7 +389,11 @@
             return mCheckedOptions;
         }
 
-        /** Returns the {@link Runnable} object to clear options Animation. */
+        /**
+         * Returns the {@link Runnable} object to clear options Animation. Note that the runnable
+         * should not be executed inside a lock because the implementation of runnable holds window
+         * manager's lock.
+         */
         @Nullable
         public Runnable getClearOptionsAnimationRunnable() {
             return mClearOptionsAnimation;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 19f3449..6ec557a 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -4,10 +4,10 @@
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
 import static android.app.ActivityManager.processStateAmToProto;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.app.WaitResult.INVALID_DELAY;
 import static android.app.WaitResult.LAUNCH_STATE_COLD;
 import static android.app.WaitResult.LAUNCH_STATE_HOT;
@@ -88,7 +88,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.ActivityOptions.SourceInfo;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.WaitResult;
 import android.app.WindowConfiguration.WindowingMode;
 import android.content.ComponentName;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4036d55..42efc2d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -31,12 +31,13 @@
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
 import static android.app.ActivityOptions.ANIM_UNDEFINED;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.cameraCompatControlStateToString;
 import static android.app.WaitResult.INVALID_DELAY;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
@@ -76,6 +77,7 @@
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
 import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION;
 import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED;
 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
@@ -274,8 +276,7 @@
 import android.app.Activity;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
-import android.app.AppCompatTaskInfo;
-import android.app.AppCompatTaskInfo.CameraCompatControlState;
+import android.app.CameraCompatTaskInfo.CameraCompatControlState;
 import android.app.ICompatCameraControlCallback;
 import android.app.IScreenCaptureObserver;
 import android.app.PendingIntent;
@@ -658,6 +659,8 @@
      */
     private CompatDisplayInsets mCompatDisplayInsets;
 
+    private final TaskFragment.ConfigOverrideHint mResolveConfigHint;
+
     private static ConstrainDisplayApisConfig sConstrainDisplayApisConfig;
 
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
@@ -819,6 +822,12 @@
     @Nullable
     private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio;
 
+    // Bounds populated in resolveAspectRatioRestriction when this activity is letterboxed for
+    // aspect ratio. If not null, they are used as parent container in
+    // resolveSizeCompatModeConfiguration and in a constructor of CompatDisplayInsets.
+    @Nullable
+    private Rect mLetterboxBoundsForAspectRatio;
+
     // Whether the activity is eligible to be letterboxed for fixed orientation with respect to its
     // requested orientation, even when it's letterbox for another reason (e.g., size compat mode)
     // and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false.
@@ -1312,6 +1321,7 @@
                 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
                 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
                         + supportsEnterPipOnTaskSwitch);
+                pw.println(prefix + "mPauseSchedulePendingForPip=" + mPauseSchedulePendingForPip);
             }
             if (getMaxAspectRatio() != 0) {
                 pw.println(prefix + "maxAspectRatio=" + getMaxAspectRatio());
@@ -1348,7 +1358,7 @@
         mLetterboxUiController.dump(pw, prefix);
 
         pw.println(prefix + "mCameraCompatControlState="
-                + AppCompatTaskInfo.cameraCompatControlStateToString(mCameraCompatControlState));
+                + cameraCompatControlStateToString(mCameraCompatControlState));
         pw.println(prefix + "mCameraCompatControlEnabled=" + mCameraCompatControlEnabled);
     }
 
@@ -2109,6 +2119,20 @@
         mLetterboxUiController = new LetterboxUiController(mWmService, this);
         mCameraCompatControlEnabled = mWmService.mContext.getResources()
                 .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
+        mResolveConfigHint = new TaskFragment.ConfigOverrideHint();
+        if (mWmService.mFlags.mInsetsDecoupledConfiguration) {
+            // When the stable configuration is the default behavior, override for the legacy apps
+            // without forward override flag.
+            mResolveConfigHint.mUseOverrideInsetsForStableBounds =
+                    !info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
+                            && !info.isChangeEnabled(
+                                    OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION);
+        } else {
+            // When the stable configuration is not the default behavior, forward overriding the
+            // listed apps.
+            mResolveConfigHint.mUseOverrideInsetsForStableBounds =
+                    info.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION);
+        }
 
         mTargetSdk = info.applicationInfo.targetSdkVersion;
 
@@ -4259,7 +4283,8 @@
                 PendingIntentRecord rec = apr.get();
                 if (rec != null) {
                     mAtmService.mPendingIntentController.cancelIntentSender(rec,
-                            false /* cleanActivity */);
+                            false /* cleanActivity */,
+                            PendingIntentRecord.CANCEL_REASON_HOSTING_ACTIVITY_DESTROYED);
                 }
             }
             pendingResults = null;
@@ -4477,6 +4502,7 @@
         getDisplayContent().mOpeningApps.remove(this);
         getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
         mWmService.mSnapshotController.onAppRemoved(this);
+        mAtmService.mStartingProcessActivities.remove(this);
 
         mTaskSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this);
         mTaskSupervisor.mStoppingActivities.remove(this);
@@ -4643,6 +4669,12 @@
                 // at #postWindowRemoveCleanupLocked
                 return false;
             }
+            // Do not transfer if the orientation doesn't match, redraw starting window while it is
+            // on top will cause flicker.
+            if (fromActivity.getRequestedConfigurationOrientation()
+                    != getRequestedConfigurationOrientation()) {
+                return false;
+            }
             // In this case, the starting icon has already been displayed, so start
             // letting windows get shown immediately without any more transitions.
             if (fromActivity.mVisible) {
@@ -6219,6 +6251,10 @@
     }
 
     boolean shouldBeVisible() {
+        return shouldBeVisible(false /* ignoringKeyguard */);
+    }
+
+    boolean shouldBeVisible(boolean ignoringKeyguard) {
         final Task task = getTask();
         if (task == null) {
             return false;
@@ -6226,7 +6262,7 @@
 
         final boolean behindOccludedContainer = !task.shouldBeVisible(null /* starting */)
                 || task.getOccludingActivityAbove(this) != null;
-        return shouldBeVisible(behindOccludedContainer, false /* ignoringKeyguard */);
+        return shouldBeVisible(behindOccludedContainer, ignoringKeyguard);
     }
 
     void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
@@ -8344,7 +8380,7 @@
      *         aspect ratio.
      */
     boolean shouldCreateCompatDisplayInsets() {
-        if (mLetterboxUiController.shouldApplyUserFullscreenOverride()) {
+        if (mLetterboxUiController.hasFullscreenOverride()) {
             // If the user has forced the applications aspect ratio to be fullscreen, don't use size
             // compatibility mode in any situation. The user has been warned and therefore accepts
             // the risk of the application misbehaving.
@@ -8359,7 +8395,11 @@
             default:
                 // Fall through
         }
-        if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) {
+        // Use root activity's info for tasks in multi-window mode, or fullscreen tasks in freeform
+        // task display areas, to ensure visual consistency across activity launches and exits in
+        // the same task.
+        final TaskDisplayArea tda = getTaskDisplayArea();
+        if (inMultiWindowMode() || (tda != null && tda.inFreeformWindowingMode())) {
             final ActivityRecord root = task != null ? task.getRootActivity() : null;
             if (root != null && root != this && !root.shouldCreateCompatDisplayInsets()) {
                 // If the root activity doesn't use size compatibility mode, the activities above
@@ -8429,10 +8469,15 @@
                     fullConfig.windowConfiguration.getRotation());
         }
 
+        final Rect letterboxedContainerBounds =
+                mLetterboxBoundsForFixedOrientationAndAspectRatio != null
+                        ? mLetterboxBoundsForFixedOrientationAndAspectRatio
+                        : mLetterboxBoundsForAspectRatio;
         // The role of CompatDisplayInsets is like the override bounds.
         mCompatDisplayInsets =
                 new CompatDisplayInsets(
-                        mDisplayContent, this, mLetterboxBoundsForFixedOrientationAndAspectRatio);
+                        mDisplayContent, this, letterboxedContainerBounds,
+                        mResolveConfigHint.mUseOverrideInsetsForStableBounds);
     }
 
     private void clearSizeCompatModeAttributes() {
@@ -8504,6 +8549,7 @@
         mIsAspectRatioApplied = false;
         mIsEligibleForFixedOrientationLetterbox = false;
         mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
+        mLetterboxBoundsForAspectRatio = null;
 
         // Can't use resolvedConfig.windowConfiguration.getWindowingMode() because it can be
         // different from windowing mode of the task (PiP) during transition from fullscreen to PiP
@@ -8539,12 +8585,15 @@
             // If the activity has requested override bounds, the configuration needs to be
             // computed accordingly.
             if (!matchParentBounds()) {
-                getTaskFragment().computeConfigResourceOverrides(resolvedConfig,
-                        newParentConfiguration);
+                computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
             }
         // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
-        // are already calculated in resolveFixedOrientationConfiguration.
-        } else if (!isLetterboxedForFixedOrientationAndAspectRatio()) {
+        // are already calculated in resolveFixedOrientationConfiguration, or if in size compat
+        // mode, it should already be calculated in resolveSizeCompatModeConfiguration.
+        // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
+        }
+        if (!isLetterboxedForFixedOrientationAndAspectRatio() && !mInSizeCompatModeForBounds
+                && !mLetterboxUiController.hasFullscreenOverride()) {
             resolveAspectRatioRestriction(newParentConfiguration);
         }
 
@@ -8627,16 +8676,14 @@
         if (mDisplayContent == null) {
             return;
         }
-        final Rect fullBounds = newParentConfiguration.windowConfiguration.getAppBounds();
+        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
         int rotation = newParentConfiguration.windowConfiguration.getRotation();
         if (rotation == ROTATION_UNDEFINED && !isFixedRotationTransforming()) {
             rotation = mDisplayContent.getRotation();
         }
-        if (!mWmService.mFlags.mInsetsDecoupledConfiguration
-                || info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
-                || getCompatDisplayInsets() != null
-                || isFloating(parentWindowingMode) || fullBounds == null
-                || fullBounds.isEmpty() || rotation == ROTATION_UNDEFINED) {
+        if (!mResolveConfigHint.mUseOverrideInsetsForStableBounds
+                || getCompatDisplayInsets() != null || isFloating(parentWindowingMode)
+                || rotation == ROTATION_UNDEFINED) {
             // If the insets configuration decoupled logic is not enabled for the app, or the app
             // already has a compat override, or the context doesn't contain enough info to
             // calculate the override, skip the override.
@@ -8644,15 +8691,20 @@
         }
 
         // Override starts here.
-        final Rect stableInsets = mDisplayContent.getDisplayPolicy().getDecorInsetsInfo(
-                rotation, fullBounds.width(), fullBounds.height()).mLegacyConfigInsets;
+        final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
+        final int dw = rotated ? mDisplayContent.mBaseDisplayHeight
+                : mDisplayContent.mBaseDisplayWidth;
+        final int dh = rotated ? mDisplayContent.mBaseDisplayWidth
+                : mDisplayContent.mBaseDisplayHeight;
+        final  Rect nonDecorInsets = mDisplayContent.getDisplayPolicy()
+                .getDecorInsetsInfo(rotation, dw, dh).mOverrideNonDecorInsets;
         // This should be the only place override the configuration for ActivityRecord. Override
         // the value if not calculated yet.
         Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
         if (outAppBounds == null || outAppBounds.isEmpty()) {
-            inOutConfig.windowConfiguration.setAppBounds(fullBounds);
+            inOutConfig.windowConfiguration.setAppBounds(parentBounds);
             outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
-            outAppBounds.inset(stableInsets);
+            outAppBounds.inset(nonDecorInsets);
         }
         float density = inOutConfig.densityDpi;
         if (density == Configuration.DENSITY_DPI_UNDEFINED) {
@@ -8661,14 +8713,11 @@
         density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
         if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
             final int overrideScreenWidthDp = (int) (outAppBounds.width() / density + 0.5f);
-            inOutConfig.screenWidthDp =
-                    Math.min(overrideScreenWidthDp, newParentConfiguration.screenWidthDp);
+            inOutConfig.screenWidthDp = overrideScreenWidthDp;
         }
         if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
-            final int overrideScreenHeightDp =
-                    (int) (outAppBounds.height() / density + 0.5f);
-            inOutConfig.screenHeightDp =
-                    Math.min(overrideScreenHeightDp, newParentConfiguration.screenHeightDp);
+            final int overrideScreenHeightDp = (int) (outAppBounds.height() / density + 0.5f);
+            inOutConfig.screenHeightDp = overrideScreenHeightDp;
         }
         if (inOutConfig.smallestScreenWidthDp
                 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
@@ -8676,12 +8725,11 @@
             // For the case of PIP transition and multi-window environment, the
             // smallestScreenWidthDp is handled already. Override only if the app is in
             // fullscreen.
-            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
             DisplayInfo info = new DisplayInfo();
             mDisplayContent.getDisplay().getDisplayInfo(info);
-            mDisplayContent.computeSizeRanges(info, rotated, info.logicalWidth,
-                    info.logicalHeight, mDisplayContent.getDisplayMetrics().density,
-                    inOutConfig, true /* legacyConfig */);
+            mDisplayContent.computeSizeRanges(info, rotated, dw, dh,
+                    mDisplayContent.getDisplayMetrics().density,
+                    inOutConfig, true /* overrideConfig */);
         }
 
         // It's possible that screen size will be considered in different orientation with or
@@ -8693,14 +8741,12 @@
         }
     }
 
-    /**
-     * @return The orientation to use to understand if reachability is enabled.
-     */
-    @Configuration.Orientation
-    int getOrientationForReachability() {
-        return mLetterboxUiController.hasInheritedLetterboxBehavior()
-                ? mLetterboxUiController.getInheritedOrientation()
-                : getRequestedConfigurationOrientation();
+    private void computeConfigByResolveHint(@NonNull Configuration resolvedConfig,
+            @NonNull Configuration parentConfig) {
+        task.computeConfigResourceOverrides(resolvedConfig, parentConfig, mResolveConfigHint);
+        // Reset the temp info which should only take effect for the specified computation.
+        mResolveConfigHint.mTmpCompatInsets = null;
+        mResolveConfigHint.mTmpOverrideDisplayInfo = null;
     }
 
     /**
@@ -8843,7 +8889,7 @@
         }
 
         // Since bounds has changed, the configuration needs to be computed accordingly.
-        getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
+        computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
 
         // The position of configuration bounds were calculated in screen space because that is
         // easier to resolve the relative position in parent container. However, if the activity is
@@ -8937,17 +8983,18 @@
      *                     to compute the stable bounds.
      * @param outStableBounds will store the stable bounds, which are the bounds with insets
      *                        applied, if orientation is not respected when insets are applied.
-     *                        Otherwise outStableBounds will be empty. Stable bounds should be used
-     *                        to compute letterboxed bounds if orientation is not respected when
-     *                        insets are applied.
+     *                        Stable bounds should be used to compute letterboxed bounds if
+     *                        orientation is not respected when insets are applied.
+     * @param outNonDecorBounds will store the non decor bounds, which are the bounds with non
+     *                          decor insets applied, like display cutout and nav bar.
      */
-    private boolean orientationRespectedWithInsets(Rect parentBounds, Rect outStableBounds) {
+    private boolean orientationRespectedWithInsets(Rect parentBounds, Rect outStableBounds,
+            Rect outNonDecorBounds) {
         outStableBounds.setEmpty();
         if (mDisplayContent == null) {
             return true;
         }
-        if (mWmService.mFlags.mInsetsDecoupledConfiguration
-                && info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)) {
+        if (!mResolveConfigHint.mUseOverrideInsetsForStableBounds) {
             // No insets should be considered any more.
             return true;
         }
@@ -8964,9 +9011,9 @@
                 ? getFixedRotationTransformDisplayInfo()
                 : mDisplayContent.getDisplayInfo();
         final Task task = getTask();
-        task.calculateInsetFrames(mTmpBounds /* outNonDecorBounds */,
+        task.calculateInsetFrames(outNonDecorBounds /* outNonDecorBounds */,
                 outStableBounds /* outStableBounds */, parentBounds /* bounds */, di,
-                true /* useLegacyInsetsForStableBounds */);
+                mResolveConfigHint.mUseOverrideInsetsForStableBounds);
         final int orientationWithInsets = outStableBounds.height() >= outStableBounds.width()
                 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
         // If orientation does not match the orientation with insets applied, then a
@@ -8976,9 +9023,6 @@
         // have the desired orientation.
         final boolean orientationRespectedWithInsets = orientation == orientationWithInsets
                 || orientationWithInsets == requestedOrientation;
-        if (orientationRespectedWithInsets) {
-            outStableBounds.setEmpty();
-        }
         return orientationRespectedWithInsets;
     }
 
@@ -9004,9 +9048,10 @@
     private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig) {
         final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
         final Rect stableBounds = new Rect();
+        final Rect outNonDecorBounds = mTmpBounds;
         // If orientation is respected when insets are applied, then stableBounds will be empty.
         boolean orientationRespectedWithInsets =
-                orientationRespectedWithInsets(parentBounds, stableBounds);
+                orientationRespectedWithInsets(parentBounds, stableBounds, outNonDecorBounds);
         if (orientationRespectedWithInsets && handlesOrientationChangeFromDescendant(
                 getOverrideOrientation())) {
             // No need to letterbox because of fixed orientation. Display will handle
@@ -9023,7 +9068,10 @@
 
         final Rect resolvedBounds =
                 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
-        final int parentOrientation = newParentConfig.orientation;
+        final int stableBoundsOrientation = stableBounds.width() > stableBounds.height()
+                ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
+        final int parentOrientation = mResolveConfigHint.mUseOverrideInsetsForStableBounds
+                ? stableBoundsOrientation : newParentConfig.orientation;
 
         // If the activity requires a different orientation (either by override or activityInfo),
         // make it fit the available bounds by scaling down its bounds.
@@ -9038,7 +9086,8 @@
         }
         final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
 
-        if (compatDisplayInsets != null && !compatDisplayInsets.mIsInFixedOrientationLetterbox) {
+        if (compatDisplayInsets != null
+                && !compatDisplayInsets.mIsInFixedOrientationOrAspectRatioLetterbox) {
             // App prefers to keep its original size.
             // If the size compat is from previous fixed orientation letterboxing, we may want to
             // have fixed orientation letterbox again, otherwise it will show the size compat
@@ -9046,10 +9095,12 @@
             return;
         }
 
+        final Rect parentAppBounds = mResolveConfigHint.mUseOverrideInsetsForStableBounds
+                ? outNonDecorBounds : newParentConfig.windowConfiguration.getAppBounds();
         // TODO(b/182268157): Explore using only one type of parentBoundsWithInsets, either app
         // bounds or stable bounds to unify aspect ratio logic.
         final Rect parentBoundsWithInsets = orientationRespectedWithInsets
-                ? newParentConfig.windowConfiguration.getAppBounds() : stableBounds;
+                ? parentAppBounds : stableBounds;
         final Rect containingBounds = new Rect();
         final Rect containingBoundsWithInsets = new Rect();
         // Need to shrink the containing bounds into a square because the parent orientation
@@ -9060,8 +9111,8 @@
             // vertically centered within parent bounds with insets, so position vertical bounds
             // within parent bounds with insets to prevent insets from unnecessarily trimming
             // vertical bounds.
-            final int bottom = Math.min(parentBoundsWithInsets.top + parentBounds.width() - 1,
-                    parentBoundsWithInsets.bottom);
+            final int bottom = Math.min(parentBoundsWithInsets.top
+                            + parentBoundsWithInsets.width() - 1, parentBoundsWithInsets.bottom);
             containingBounds.set(parentBounds.left, parentBoundsWithInsets.top, parentBounds.right,
                     bottom);
             containingBoundsWithInsets.set(parentBoundsWithInsets.left, parentBoundsWithInsets.top,
@@ -9072,8 +9123,8 @@
             // horizontally centered within parent bounds with insets, so position horizontal bounds
             // within parent bounds with insets to prevent insets from unnecessarily trimming
             // horizontal bounds.
-            final int right = Math.min(parentBoundsWithInsets.left + parentBounds.height(),
-                    parentBoundsWithInsets.right);
+            final int right = Math.min(parentBoundsWithInsets.left
+                            + parentBoundsWithInsets.height(), parentBoundsWithInsets.right);
             containingBounds.set(parentBoundsWithInsets.left, parentBounds.top, right,
                     parentBounds.bottom);
             containingBoundsWithInsets.set(parentBoundsWithInsets.left, parentBoundsWithInsets.top,
@@ -9126,8 +9177,8 @@
 
         // Calculate app bounds using fixed orientation bounds because they will be needed later
         // for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
-        getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
-                newParentConfig, compatDisplayInsets);
+        mResolveConfigHint.mTmpCompatInsets = compatDisplayInsets;
+        computeConfigByResolveHint(getResolvedOverrideConfiguration(), newParentConfig);
         mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
     }
 
@@ -9168,8 +9219,9 @@
         if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
             // Compute the configuration based on the resolved bounds. If aspect ratio doesn't
             // restrict, the bounds should be the requested override bounds.
-            getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
-                    getFixedRotationTransformDisplayInfo());
+            mResolveConfigHint.mTmpOverrideDisplayInfo = getFixedRotationTransformDisplayInfo();
+            computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
+            mLetterboxBoundsForAspectRatio = new Rect(resolvedBounds);
         }
     }
 
@@ -9233,8 +9285,8 @@
         // Use resolvedBounds to compute other override configurations such as appBounds. The bounds
         // 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,
-                compatDisplayInsets);
+        mResolveConfigHint.mTmpCompatInsets = compatDisplayInsets;
+        computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
         // Use current screen layout as source because the size of app is independent to parent.
         resolvedConfig.screenLayout = computeScreenLayout(
                 getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
@@ -10507,8 +10559,7 @@
         if (!getTurnScreenOnFlag()) {
             return false;
         }
-        final Task rootTask = getRootTask();
-        return mCurrentLaunchCanTurnScreenOn && rootTask != null
+        return mCurrentLaunchCanTurnScreenOn
                 && mTaskSupervisor.getKeyguardController().checkKeyguardVisibility(this);
     }
 
@@ -10734,10 +10785,10 @@
         /** Whether the {@link Task} windowingMode represents a floating window*/
         final boolean mIsFloating;
         /**
-         * Whether is letterboxed because of fixed orientation when the unresizable activity is
-         * first shown.
+         * Whether is letterboxed because of fixed orientation or aspect ratio when
+         * the unresizable activity is first shown.
          */
-        final boolean mIsInFixedOrientationLetterbox;
+        final boolean mIsInFixedOrientationOrAspectRatioLetterbox;
         /**
          * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
          * is used to compute the appBounds.
@@ -10752,7 +10803,7 @@
 
         /** Constructs the environment to simulate the bounds behavior of the given container. */
         CompatDisplayInsets(DisplayContent display, ActivityRecord container,
-                @Nullable Rect fixedOrientationBounds) {
+                @Nullable Rect letterboxedContainerBounds, boolean useOverrideInsets) {
             mOriginalRotation = display.getRotation();
             mIsFloating = container.getWindowConfiguration().tasksAreFloating();
             mOriginalRequestedOrientation = container.getRequestedConfigurationOrientation();
@@ -10767,22 +10818,22 @@
                     mNonDecorInsets[rotation] = emptyRect;
                     mStableInsets[rotation] = emptyRect;
                 }
-                mIsInFixedOrientationLetterbox = false;
+                mIsInFixedOrientationOrAspectRatioLetterbox = false;
                 return;
             }
 
             final Task task = container.getTask();
 
-            mIsInFixedOrientationLetterbox = fixedOrientationBounds != null;
+            mIsInFixedOrientationOrAspectRatioLetterbox = letterboxedContainerBounds != null;
 
             // Store the bounds of the Task for the non-resizable activity to use in size compat
             // mode so that the activity will not be resized regardless the windowing mode it is
             // currently in.
-            // When an activity needs to be letterboxed because of fixed orientation, use fixed
-            // orientation bounds instead of task bounds since the activity will be displayed
-            // within these even if it is in size compat mode.
-            final Rect filledContainerBounds = mIsInFixedOrientationLetterbox
-                    ? fixedOrientationBounds
+            // When an activity needs to be letterboxed because of fixed orientation or aspect
+            // ratio, use resolved bounds instead of task bounds since the activity will be
+            // displayed within these even if it is in size compat mode.
+            final Rect filledContainerBounds = mIsInFixedOrientationOrAspectRatioLetterbox
+                    ? letterboxedContainerBounds
                     : task != null ? task.getBounds() : display.getBounds();
             final int filledContainerRotation = task != null
                     ? task.getConfiguration().windowConfiguration.getRotation()
@@ -10804,8 +10855,13 @@
                 final int dh = rotated ? display.mBaseDisplayWidth : display.mBaseDisplayHeight;
                 final DisplayPolicy.DecorInsets.Info decorInfo =
                         policy.getDecorInsetsInfo(rotation, dw, dh);
-                mNonDecorInsets[rotation].set(decorInfo.mNonDecorInsets);
-                mStableInsets[rotation].set(decorInfo.mConfigInsets);
+                if (useOverrideInsets) {
+                    mStableInsets[rotation].set(decorInfo.mOverrideConfigInsets);
+                    mNonDecorInsets[rotation].set(decorInfo.mOverrideNonDecorInsets);
+                } else {
+                    mStableInsets[rotation].set(decorInfo.mConfigInsets);
+                    mNonDecorInsets[rotation].set(decorInfo.mNonDecorInsets);
+                }
 
                 if (unfilledContainerBounds == null) {
                     continue;
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 182e1c1..2cccd33 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -523,8 +523,11 @@
     void onActivityLaunched(TaskInfo taskInfo, ActivityRecord r) {
         final SparseArray<ActivityInterceptorCallback> callbacks =
                 mService.getActivityInterceptorCallbacks();
-        ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo(
-                r::clearOptionsAnimationForSiblings);
+        final ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo(() -> {
+            synchronized (mService.mGlobalLock) {
+                r.clearOptionsAnimationForSiblings();
+            }
+        });
         for (int i = 0; i < callbacks.size(); i++) {
             final ActivityInterceptorCallback callback = callbacks.valueAt(i);
             callback.onActivityLaunched(taskInfo, r.info, info);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 2c39c58..3303367 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1728,7 +1728,7 @@
         // Get top task at beginning because the order may be changed when reusing existing task.
         final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
         final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null;
-        final Task reusedTask = getReusableTask();
+        final Task reusedTask = resolveReusableTask();
 
         // If requested, freeze the task list
         if (mOptions != null && mOptions.freezeRecentTasksReordering()
@@ -2524,7 +2524,9 @@
         // If the caller has asked not to resume at this point, we make note
         // of this in the record so that we can skip it when trying to find
         // the top running activity.
-        if (!r.showToCurrentUser() || mLaunchTaskBehind) {
+        final boolean canShowActivity = r.showToCurrentUser();
+        if (!canShowActivity) Slog.w(TAG, "Can't resume non-current user r=" + r);
+        if (!canShowActivity || mLaunchTaskBehind) {
             r.delayedResume = true;
             mDoResume = false;
         } else {
@@ -2727,7 +2729,7 @@
      * Decide whether the new activity should be inserted into an existing task. Returns null
      * if not or an ActivityRecord with the task into which the new activity should be added.
      */
-    private Task getReusableTask() {
+    private Task resolveReusableTask() {
         // If a target task is specified, try to reuse that one
         if (mOptions != null && mOptions.getLaunchTaskId() != INVALID_TASK_ID) {
             Task launchTask = mRootWindowContainer.anyTaskForId(mOptions.getLaunchTaskId());
@@ -2755,7 +2757,14 @@
                 // There can be one and only one instance of single instance activity in the
                 // history, and it is always in its own unique task, so we do a special search.
                 intentActivity = mRootWindowContainer.findActivity(mIntent, mStartActivity.info,
-                       mStartActivity.isActivityTypeHome());
+                       false /* compareIntentFilters */);
+                // Removes the existing singleInstance Activity if we're starting it as home
+                // activity, while the existing one is not.
+                if (intentActivity != null && mStartActivity.isActivityTypeHome()
+                        && !intentActivity.isActivityTypeHome()) {
+                    intentActivity.destroyIfPossible("Removes redundant singleInstance");
+                    intentActivity = null;
+                }
             } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                 // For the launch adjacent case we only want to put the activity in an existing
                 // task if the activity already exists in the history.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 354cab3..b3c43bc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -390,6 +390,9 @@
 
     final VisibleActivityProcessTracker mVisibleActivityProcessTracker;
 
+    /** The starting activities which are waiting for their processes to attach. */
+    final ArrayList<ActivityRecord> mStartingProcessActivities = new ArrayList<>();
+
     /* Global service lock used by the package the owns this service. */
     final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
     /**
@@ -883,6 +886,7 @@
             mRecentTasks.onSystemReadyLocked();
             mTaskSupervisor.onSystemReady();
             mActivityClientController.onSystemReady();
+            mAppWarnings.onSystemReady();
             // TODO(b/258792202) Cleanup once ASM is ready to launch
             ActivitySecurityModelFeatureFlags.initialize(mContext.getMainExecutor());
             mGrammaticalManagerInternal = LocalServices.getService(
@@ -3732,16 +3736,25 @@
             return false;
         }
 
-        // If PiP2 flag is on and client-request to enter PiP comes in,
-        // we request a direct transition from Shell to TRANSIT_PIP to get the startWct
-        // with the right entry bounds. So PiP activity isn't moved to a pinned task until after
-        // Shell calls back into Core with the entry bounds passed through.
+        // If the app is using auto-enter, and it explicitly requests entering PiP while pausing,
+        // return false immediately since auto-enter should take in place instead.
+        if (fromClient && r.isState(PAUSING) && params.isAutoEnterEnabled()) {
+            Slog.w(TAG, "Skip client enterPictureInPictureMode request while pausing,"
+                    + " auto-enter-pip is enabled");
+            return false;
+        }
+
         if (isPip2ExperimentEnabled()) {
-            final Transition legacyEnterPipTransition = new Transition(TRANSIT_PIP,
+            // If PiP2 flag is on and request to enter PiP comes in,
+            // we request a direct transition TRANSIT_PIP from Shell to get the right entry bounds.
+            // So PiP activity isn't moved to a pinned task until after
+            // Shell calls back into Core with the entry bounds to be applied with startWCT.
+            final Transition enterPipTransition = new Transition(TRANSIT_PIP,
                     0 /* flags */, getTransitionController(), mWindowManager.mSyncEngine);
-            legacyEnterPipTransition.setPipActivity(r);
-            getTransitionController().startCollectOrQueue(legacyEnterPipTransition, (deferred) -> {
-                getTransitionController().requestStartTransition(legacyEnterPipTransition,
+            enterPipTransition.setPipActivity(r);
+            r.mAutoEnteringPip = isAutoEnter;
+            getTransitionController().startCollectOrQueue(enterPipTransition, (deferred) -> {
+                getTransitionController().requestStartTransition(enterPipTransition,
                         r.getTask(), null /* remoteTransition */, null /* displayChange */);
             });
             return true;
@@ -3786,7 +3799,8 @@
                 // Continue the pausing process after entering pip.
                 if (r.isState(PAUSING) && r.mPauseSchedulePendingForPip) {
                     r.getTask().schedulePauseActivity(r, false /* userLeaving */,
-                            false /* pauseImmediately */, true /* autoEnteringPip */, "auto-pip");
+                            false /* pauseImmediately */, true /* autoEnteringPip */,
+                            "auto-pip");
                 }
                 r.mAutoEnteringPip = false;
             }
@@ -4322,6 +4336,9 @@
             if (mDemoteTopAppReasons != 0) {
                 pw.println("  mDemoteTopAppReasons=" + mDemoteTopAppReasons);
             }
+            if (!mStartingProcessActivities.isEmpty()) {
+                pw.println("  mStartingProcessActivities=" + mStartingProcessActivities);
+            }
         }
 
         if (!printedAnything) {
@@ -5169,6 +5186,13 @@
 
     void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
             String hostingType) {
+        if (!mStartingProcessActivities.contains(activity)) {
+            mStartingProcessActivities.add(activity);
+        } else if (mProcessNames.get(
+                activity.processName, activity.info.applicationInfo.uid) != null) {
+            // The process is already starting. Wait for it to attach.
+            return;
+        }
         try {
             if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
@@ -6165,7 +6189,20 @@
         @Override
         public void onProcessRemoved(String name, int uid) {
             synchronized (mGlobalLockWithoutBoost) {
-                mProcessNames.remove(name, uid);
+                final WindowProcessController proc = mProcessNames.remove(name, uid);
+                if (proc != null && !mStartingProcessActivities.isEmpty()) {
+                    for (int i = mStartingProcessActivities.size() - 1; i >= 0; i--) {
+                        final ActivityRecord r = mStartingProcessActivities.get(i);
+                        if (uid == r.info.applicationInfo.uid && name.equals(r.processName)) {
+                            Slog.w(TAG, proc + " is removed with pending start " + r);
+                            mStartingProcessActivities.remove(i);
+                            // If visible, finish it to avoid getting stuck on screen.
+                            if (r.isVisibleRequested()) {
+                                r.finishIfPossible("starting-proc-removed", false /* oomAdj */);
+                            }
+                        }
+                    }
+                }
             }
         }
 
@@ -6325,7 +6362,7 @@
         public void onPackageDataCleared(String name, int userId) {
             synchronized (mGlobalLock) {
                 mCompatModePackages.handlePackageDataClearedLocked(name);
-                mAppWarnings.onPackageDataCleared(name);
+                mAppWarnings.onPackageDataCleared(name, userId);
                 mPackageConfigPersister.onPackageDataCleared(name, userId);
             }
         }
@@ -6333,7 +6370,7 @@
         @Override
         public void onPackageUninstalled(String name, int userId) {
             synchronized (mGlobalLock) {
-                mAppWarnings.onPackageUninstalled(name);
+                mAppWarnings.onPackageUninstalled(name, userId);
                 mCompatModePackages.handlePackageUninstalledLocked(name);
                 mPackageConfigPersister.onPackageUninstall(name, userId);
             }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 430232c..c74284e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2311,8 +2311,12 @@
             mService.setLastResumedActivityUncheckLocked(mTopResumedActivity, reason);
         }
         scheduleTopResumedActivityStateIfNeeded();
-
-        mService.updateTopApp(mTopResumedActivity);
+        // If the device is not sleeping and there is no top resumed, do not update top app because
+        // it may be an intermediate state while moving a task to front. The actual top will be set
+        // when TaskFragment#setResumedActivity is called.
+        if (mTopResumedActivity != null || mService.isSleepingLocked()) {
+            mService.updateTopApp(mTopResumedActivity);
+        }
 
         return mTopResumedActivity;
     }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 5184e49..c2b9128 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -96,7 +96,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
-import static com.android.server.wm.WindowManagerInternal.KeyguardExitAnimationStartListener;
 import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM;
 import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_NONE;
 
@@ -105,7 +104,6 @@
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -117,7 +115,6 @@
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.Pair;
 import android.util.Slog;
@@ -137,6 +134,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.TransitionAnimation;
+import com.android.internal.protolog.common.LogLevel;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.DumpUtils.Dump;
 import com.android.internal.util.function.pooled.PooledLambda;
@@ -244,7 +242,7 @@
         mHandler = new Handler(service.mH.getLooper());
         mDisplayContent = displayContent;
         mTransitionAnimation = new TransitionAnimation(
-                context, ProtoLog.isEnabled(WM_DEBUG_ANIM), TAG);
+                context, ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.DEBUG), TAG);
 
         final TypedArray windowStyle = mContext.getTheme().obtainStyledAttributes(
                 com.android.internal.R.styleable.Window);
diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java
index ad5f442..9fd543f 100644
--- a/services/core/java/com/android/server/wm/AppWarnings.java
+++ b/services/core/java/com/android/server/wm/AppWarnings.java
@@ -16,8 +16,14 @@
 
 package com.android.server.wm;
 
+import static android.os.UserHandle.USER_NULL;
+import static android.os.UserHandle.USER_SYSTEM;
+import static android.os.UserManager.isHeadlessSystemUserMode;
+import static android.os.UserManager.isVisibleBackgroundUsersEnabled;
+
 import android.annotation.NonNull;
 import android.annotation.UiThread;
+import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
@@ -26,17 +32,21 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.DisplayMetrics;
+import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
@@ -44,6 +54,8 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.IoThread;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -65,19 +77,30 @@
     public static final int FLAG_HIDE_DEPRECATED_SDK = 0x04;
     public static final int FLAG_HIDE_DEPRECATED_ABI = 0x08;
 
+    /**
+     * Map of package flags for each user.
+     * Key: {@literal Pair<userId, packageName>}
+     * Value: Flags
+     */
     @GuardedBy("mPackageFlags")
-    private final ArrayMap<String, Integer> mPackageFlags = new ArrayMap<>();
+    private final ArrayMap<Pair<Integer, String>, Integer> mPackageFlags = new ArrayMap<>();
 
     private final ActivityTaskManagerService mAtm;
-    private final Context mUiContext;
     private final WriteConfigTask mWriteConfigTask;
     private final UiHandler mUiHandler;
     private final AtomicFile mConfigFile;
 
-    private UnsupportedDisplaySizeDialog mUnsupportedDisplaySizeDialog;
-    private UnsupportedCompileSdkDialog mUnsupportedCompileSdkDialog;
-    private DeprecatedTargetSdkVersionDialog mDeprecatedTargetSdkVersionDialog;
-    private DeprecatedAbiDialog mDeprecatedAbiDialog;
+    private UserManagerInternal mUserManagerInternal;
+
+    /**
+     * Maps of app warning dialogs for each user.
+     * Key: userId
+     * Value: The warning dialog for specific user
+     */
+    private SparseArray<UnsupportedDisplaySizeDialog> mUnsupportedDisplaySizeDialogs;
+    private SparseArray<UnsupportedCompileSdkDialog> mUnsupportedCompileSdkDialogs;
+    private SparseArray<DeprecatedTargetSdkVersionDialog> mDeprecatedTargetSdkVersionDialogs;
+    private SparseArray<DeprecatedAbiDialog> mDeprecatedAbiDialogs;
 
     /** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
     private final ArraySet<ComponentName> mAlwaysShowUnsupportedCompileSdkWarningActivities =
@@ -92,12 +115,35 @@
     public AppWarnings(ActivityTaskManagerService atm, Context uiContext, Handler handler,
             Handler uiHandler, File systemDir) {
         mAtm = atm;
-        mUiContext = uiContext;
         mWriteConfigTask = new WriteConfigTask();
         mUiHandler = new UiHandler(uiHandler.getLooper());
         mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME), "warnings-config");
+    }
 
+    /**
+     * Called when ActivityManagerService receives its systemReady call during boot.
+     */
+    void onSystemReady() {
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
         readConfigFromFileAmsThread();
+
+        if (!isVisibleBackgroundUsersEnabled()) {
+            return;
+        }
+
+        mUserManagerInternal.addUserLifecycleListener(
+                new UserManagerInternal.UserLifecycleListener() {
+                    @Override
+                    public void onUserRemoved(UserInfo user) {
+                        // Ignore profile user.
+                        if (!user.isFull()) {
+                            return;
+                        }
+                        // Dismiss all warnings and clear all package flags for the user.
+                        mUiHandler.hideDialogsForPackage(/* name= */ null, user.id);
+                        clearAllPackageFlagsForUser(user.id);
+                    }
+                });
     }
 
     /**
@@ -227,18 +273,20 @@
      * Called by ActivityManagerService when package data has been cleared.
      *
      * @param name the package whose data has been cleared
+     * @param userId the user where the package resides.
      */
-    public void onPackageDataCleared(String name) {
-        removePackageAndHideDialogs(name);
+    public void onPackageDataCleared(String name, int userId) {
+        removePackageAndHideDialogs(name, userId);
     }
 
     /**
      * Called by ActivityManagerService when a package has been uninstalled.
      *
      * @param name the package that has been uninstalled
+     * @param userId the user where the package resides.
      */
-    public void onPackageUninstalled(String name) {
-        removePackageAndHideDialogs(name);
+    public void onPackageUninstalled(String name, int userId) {
+        removePackageAndHideDialogs(name, userId);
     }
 
     /**
@@ -251,11 +299,24 @@
     /**
      * Does what it says on the tin.
      */
-    private void removePackageAndHideDialogs(String name) {
-        mUiHandler.hideDialogsForPackage(name);
+    private void removePackageAndHideDialogs(String name, int userId) {
+        // Per-user AppWarnings only affects the behavior of the devices that enable the visible
+        // background users.
+        // To preserve existing behavior of the other devices, handle AppWarnings as a system user
+        // regardless of the actual user.
+        if (!isVisibleBackgroundUsersEnabled()) {
+            userId = USER_SYSTEM;
+        } else {
+            // If the userId is of a profile, use the parent user ID,
+            // since the warning dialogs and the flags for a package are handled per profile group.
+            userId = mUserManagerInternal.getProfileParentId(userId);
+        }
+
+        mUiHandler.hideDialogsForPackage(name, userId);
 
         synchronized (mPackageFlags) {
-            if (mPackageFlags.remove(name) != null) {
+            final Pair<Integer, String> packageKey = Pair.create(userId, name);
+            if (mPackageFlags.remove(packageKey) != null) {
                 mWriteConfigTask.schedule();
             }
         }
@@ -268,10 +329,14 @@
      */
     @UiThread
     private void hideUnsupportedDisplaySizeDialogUiThread() {
-        if (mUnsupportedDisplaySizeDialog != null) {
-            mUnsupportedDisplaySizeDialog.dismiss();
-            mUnsupportedDisplaySizeDialog = null;
+        if (mUnsupportedDisplaySizeDialogs == null) {
+            return;
         }
+
+        for (int i = 0; i < mUnsupportedDisplaySizeDialogs.size(); i++) {
+            mUnsupportedDisplaySizeDialogs.valueAt(i).dismiss();
+        }
+        mUnsupportedDisplaySizeDialogs.clear();
     }
 
     /**
@@ -282,16 +347,24 @@
      * @param ar record for the activity that triggered the warning
      */
     @UiThread
-    private void showUnsupportedDisplaySizeDialogUiThread(ActivityRecord ar) {
-        if (mUnsupportedDisplaySizeDialog != null) {
-            mUnsupportedDisplaySizeDialog.dismiss();
-            mUnsupportedDisplaySizeDialog = null;
+    private void showUnsupportedDisplaySizeDialogUiThread(@NonNull ActivityRecord ar) {
+        final int userId = getUserIdForActivity(ar);
+        UnsupportedDisplaySizeDialog unsupportedDisplaySizeDialog;
+        if (mUnsupportedDisplaySizeDialogs != null) {
+            unsupportedDisplaySizeDialog = mUnsupportedDisplaySizeDialogs.get(userId);
+            if (unsupportedDisplaySizeDialog != null) {
+                unsupportedDisplaySizeDialog.dismiss();
+                mUnsupportedDisplaySizeDialogs.remove(userId);
+            }
         }
-        if (ar != null && !hasPackageFlag(
-                ar.packageName, FLAG_HIDE_DISPLAY_SIZE)) {
-            mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
-                    AppWarnings.this, mUiContext, ar.info.applicationInfo);
-            mUnsupportedDisplaySizeDialog.show();
+        if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_DISPLAY_SIZE)) {
+            unsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
+                    AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId);
+            unsupportedDisplaySizeDialog.show();
+            if (mUnsupportedDisplaySizeDialogs == null) {
+                mUnsupportedDisplaySizeDialogs = new SparseArray<>();
+            }
+            mUnsupportedDisplaySizeDialogs.put(userId, unsupportedDisplaySizeDialog);
         }
     }
 
@@ -303,16 +376,24 @@
      * @param ar record for the activity that triggered the warning
      */
     @UiThread
-    private void showUnsupportedCompileSdkDialogUiThread(ActivityRecord ar) {
-        if (mUnsupportedCompileSdkDialog != null) {
-            mUnsupportedCompileSdkDialog.dismiss();
-            mUnsupportedCompileSdkDialog = null;
+    private void showUnsupportedCompileSdkDialogUiThread(@NonNull ActivityRecord ar) {
+        final int userId = getUserIdForActivity(ar);
+        UnsupportedCompileSdkDialog unsupportedCompileSdkDialog;
+        if (mUnsupportedCompileSdkDialogs != null) {
+            unsupportedCompileSdkDialog = mUnsupportedCompileSdkDialogs.get(userId);
+            if (unsupportedCompileSdkDialog != null) {
+                unsupportedCompileSdkDialog.dismiss();
+                mUnsupportedCompileSdkDialogs.remove(userId);
+            }
         }
-        if (ar != null && !hasPackageFlag(
-                ar.packageName, FLAG_HIDE_COMPILE_SDK)) {
-            mUnsupportedCompileSdkDialog = new UnsupportedCompileSdkDialog(
-                    AppWarnings.this, mUiContext, ar.info.applicationInfo);
-            mUnsupportedCompileSdkDialog.show();
+        if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_COMPILE_SDK)) {
+            unsupportedCompileSdkDialog = new UnsupportedCompileSdkDialog(
+                    AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId);
+            unsupportedCompileSdkDialog.show();
+            if (mUnsupportedCompileSdkDialogs == null) {
+                mUnsupportedCompileSdkDialogs = new SparseArray<>();
+            }
+            mUnsupportedCompileSdkDialogs.put(userId, unsupportedCompileSdkDialog);
         }
     }
 
@@ -324,16 +405,24 @@
      * @param ar record for the activity that triggered the warning
      */
     @UiThread
-    private void showDeprecatedTargetSdkDialogUiThread(ActivityRecord ar) {
-        if (mDeprecatedTargetSdkVersionDialog != null) {
-            mDeprecatedTargetSdkVersionDialog.dismiss();
-            mDeprecatedTargetSdkVersionDialog = null;
+    private void showDeprecatedTargetSdkDialogUiThread(@NonNull ActivityRecord ar) {
+        final int userId = getUserIdForActivity(ar);
+        DeprecatedTargetSdkVersionDialog deprecatedTargetSdkVersionDialog;
+        if (mDeprecatedTargetSdkVersionDialogs != null) {
+            deprecatedTargetSdkVersionDialog = mDeprecatedTargetSdkVersionDialogs.get(userId);
+            if (deprecatedTargetSdkVersionDialog != null) {
+                deprecatedTargetSdkVersionDialog.dismiss();
+                mDeprecatedTargetSdkVersionDialogs.remove(userId);
+            }
         }
-        if (ar != null && !hasPackageFlag(
-                ar.packageName, FLAG_HIDE_DEPRECATED_SDK)) {
-            mDeprecatedTargetSdkVersionDialog = new DeprecatedTargetSdkVersionDialog(
-                    AppWarnings.this, mUiContext, ar.info.applicationInfo);
-            mDeprecatedTargetSdkVersionDialog.show();
+        if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_DEPRECATED_SDK)) {
+            deprecatedTargetSdkVersionDialog = new DeprecatedTargetSdkVersionDialog(
+                    AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId);
+            deprecatedTargetSdkVersionDialog.show();
+            if (mDeprecatedTargetSdkVersionDialogs == null) {
+                mDeprecatedTargetSdkVersionDialogs = new SparseArray<>();
+            }
+            mDeprecatedTargetSdkVersionDialogs.put(userId, deprecatedTargetSdkVersionDialog);
         }
     }
 
@@ -345,16 +434,24 @@
      * @param ar record for the activity that triggered the warning
      */
     @UiThread
-    private void showDeprecatedAbiDialogUiThread(ActivityRecord ar) {
-        if (mDeprecatedAbiDialog != null) {
-            mDeprecatedAbiDialog.dismiss();
-            mDeprecatedAbiDialog = null;
+    private void showDeprecatedAbiDialogUiThread(@NonNull ActivityRecord ar) {
+        final int userId = getUserIdForActivity(ar);
+        DeprecatedAbiDialog deprecatedAbiDialog;
+        if (mDeprecatedAbiDialogs != null) {
+            deprecatedAbiDialog = mDeprecatedAbiDialogs.get(userId);
+            if (deprecatedAbiDialog != null) {
+                deprecatedAbiDialog.dismiss();
+                mDeprecatedAbiDialogs.remove(userId);
+            }
         }
-        if (ar != null && !hasPackageFlag(
-                ar.packageName, FLAG_HIDE_DEPRECATED_ABI)) {
-            mDeprecatedAbiDialog = new DeprecatedAbiDialog(
-                    AppWarnings.this, mUiContext, ar.info.applicationInfo);
-            mDeprecatedAbiDialog.show();
+        if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_DEPRECATED_ABI)) {
+            deprecatedAbiDialog = new DeprecatedAbiDialog(
+                    AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId);
+            deprecatedAbiDialog.show();
+            if (mDeprecatedAbiDialogs == null) {
+                mDeprecatedAbiDialogs = new SparseArray<>();
+            }
+            mDeprecatedAbiDialogs.put(userId, deprecatedAbiDialog);
         }
     }
 
@@ -365,65 +462,84 @@
      *
      * @param name the package for which warnings should be dismissed, or {@code null} to dismiss
      *             all warnings
+     * @param userId the user where the package resides.
      */
     @UiThread
-    private void hideDialogsForPackageUiThread(String name) {
+    private void hideDialogsForPackageUiThread(String name, int userId) {
         // Hides the "unsupported display" dialog if necessary.
-        if (mUnsupportedDisplaySizeDialog != null && (name == null || name.equals(
-                mUnsupportedDisplaySizeDialog.mPackageName))) {
-            mUnsupportedDisplaySizeDialog.dismiss();
-            mUnsupportedDisplaySizeDialog = null;
+        if (mUnsupportedDisplaySizeDialogs != null) {
+            UnsupportedDisplaySizeDialog unsupportedDisplaySizeDialog =
+                    mUnsupportedDisplaySizeDialogs.get(userId);
+            if (unsupportedDisplaySizeDialog != null && (name == null || name.equals(
+                    unsupportedDisplaySizeDialog.mPackageName))) {
+                unsupportedDisplaySizeDialog.dismiss();
+                mUnsupportedDisplaySizeDialogs.remove(userId);
+            }
         }
 
         // Hides the "unsupported compile SDK" dialog if necessary.
-        if (mUnsupportedCompileSdkDialog != null && (name == null || name.equals(
-                mUnsupportedCompileSdkDialog.mPackageName))) {
-            mUnsupportedCompileSdkDialog.dismiss();
-            mUnsupportedCompileSdkDialog = null;
+        if (mUnsupportedCompileSdkDialogs != null) {
+            UnsupportedCompileSdkDialog unsupportedCompileSdkDialog =
+                    mUnsupportedCompileSdkDialogs.get(userId);
+            if (unsupportedCompileSdkDialog != null && (name == null || name.equals(
+                    unsupportedCompileSdkDialog.mPackageName))) {
+                unsupportedCompileSdkDialog.dismiss();
+                mUnsupportedCompileSdkDialogs.remove(userId);
+            }
         }
 
         // Hides the "deprecated target sdk version" dialog if necessary.
-        if (mDeprecatedTargetSdkVersionDialog != null && (name == null || name.equals(
-                mDeprecatedTargetSdkVersionDialog.mPackageName))) {
-            mDeprecatedTargetSdkVersionDialog.dismiss();
-            mDeprecatedTargetSdkVersionDialog = null;
+        if (mDeprecatedTargetSdkVersionDialogs != null) {
+            DeprecatedTargetSdkVersionDialog deprecatedTargetSdkVersionDialog =
+                    mDeprecatedTargetSdkVersionDialogs.get(userId);
+            if (deprecatedTargetSdkVersionDialog != null && (name == null || name.equals(
+                    deprecatedTargetSdkVersionDialog.mPackageName))) {
+                deprecatedTargetSdkVersionDialog.dismiss();
+                mDeprecatedTargetSdkVersionDialogs.remove(userId);
+            }
         }
 
         // Hides the "deprecated abi" dialog if necessary.
-        if (mDeprecatedAbiDialog != null && (name == null || name.equals(
-                mDeprecatedAbiDialog.mPackageName))) {
-            mDeprecatedAbiDialog.dismiss();
-            mDeprecatedAbiDialog = null;
+        if (mDeprecatedAbiDialogs != null) {
+            DeprecatedAbiDialog deprecatedAbiDialog = mDeprecatedAbiDialogs.get(userId);
+            if (deprecatedAbiDialog != null && (name == null || name.equals(
+                    deprecatedAbiDialog.mPackageName))) {
+                deprecatedAbiDialog.dismiss();
+                mDeprecatedAbiDialogs.remove(userId);
+            }
         }
     }
 
     /**
      * Returns the value of the flag for the given package.
      *
+     * @param userId the user where the package resides.
      * @param name the package from which to retrieve the flag
      * @param flag the bitmask for the flag to retrieve
      * @return {@code true} if the flag is enabled, {@code false} otherwise
      */
-    boolean hasPackageFlag(String name, int flag) {
-        return (getPackageFlags(name) & flag) == flag;
+    boolean hasPackageFlag(int userId, String name, int flag) {
+        return (getPackageFlags(userId, name) & flag) == flag;
     }
 
     /**
      * Sets the flag for the given package to the specified value.
      *
+     * @param userId the user where the package resides.
      * @param name the package on which to set the flag
      * @param flag the bitmask for flag to set
      * @param enabled the value to set for the flag
      */
-    void setPackageFlag(String name, int flag, boolean enabled) {
+    void setPackageFlag(int userId, String name, int flag, boolean enabled) {
         synchronized (mPackageFlags) {
-            final int curFlags = getPackageFlags(name);
+            final int curFlags = getPackageFlags(userId, name);
             final int newFlags = enabled ? (curFlags | flag) : (curFlags & ~flag);
             if (curFlags != newFlags) {
+                final Pair<Integer, String> packageKey = Pair.create(userId, name);
                 if (newFlags != 0) {
-                    mPackageFlags.put(name, newFlags);
+                    mPackageFlags.put(packageKey, newFlags);
                 } else {
-                    mPackageFlags.remove(name);
+                    mPackageFlags.remove(packageKey);
                 }
                 mWriteConfigTask.schedule();
             }
@@ -433,13 +549,95 @@
     /**
      * Returns the bitmask of flags set for the specified package.
      */
-    private int getPackageFlags(String name) {
+    private int getPackageFlags(int userId, String packageName) {
         synchronized (mPackageFlags) {
-            return mPackageFlags.getOrDefault(name, 0);
+            final Pair<Integer, String> packageKey = Pair.create(userId, packageName);
+            return mPackageFlags.getOrDefault(packageKey, 0);
         }
     }
 
     /**
+     * Clear all the package flags for given user.
+     */
+    private void clearAllPackageFlagsForUser(int userId) {
+        synchronized (mPackageFlags) {
+            boolean hasPackageFlagsForUser = false;
+            for (int i = mPackageFlags.size() - 1; i >= 0; i--) {
+                Pair<Integer, String> key = mPackageFlags.keyAt(i);
+                if (key.first == userId) {
+                    hasPackageFlagsForUser = true;
+                    mPackageFlags.remove(key);
+                }
+            }
+
+            if (hasPackageFlagsForUser) {
+                mWriteConfigTask.schedule();
+            }
+        }
+    }
+
+    /**
+     * Returns the user ID for handling AppWarnings per user.
+     * Per-user AppWarnings only affects the behavior of the devices that enable
+     * the visible background users.
+     * If the device doesn't enable visible background users, it will return the system user ID
+     * for handling AppWarnings as a system user regardless of the actual user
+     * to preserve existing behavior of the device.
+     * Otherwise, it will return the main user (i.e., not a profile) that is assigned to the display
+     * where the activity is launched.
+     */
+    private @UserIdInt int getUserIdForActivity(@NonNull ActivityRecord ar) {
+        if (!isVisibleBackgroundUsersEnabled()) {
+            return USER_SYSTEM;
+        }
+
+        if (ar.mUserId == USER_SYSTEM) {
+            return getUserAssignedToDisplay(ar.mDisplayContent.getDisplayId());
+        }
+
+        return mUserManagerInternal.getProfileParentId(ar.mUserId);
+    }
+
+    /**
+     * Returns the UI context for handling AppWarnings per user.
+     * Per-user AppWarnings only affects the behavior of the devices that enable
+     * the visible background users.
+     * If the device enables the visible background users, it will return the UI context associated
+     * with the assigned user and the display where the activity is launched.
+     * If the HSUM device doesn't enable the visible background users, it will return the UI context
+     * associated with the current user and the default display.
+     * Otherwise, it will return the UI context associated with the system user and the default
+     * display.
+     */
+    private Context getUiContextForActivity(@NonNull ActivityRecord ar) {
+        if (!isVisibleBackgroundUsersEnabled()) {
+            if (!isHeadlessSystemUserMode()) {
+                return mAtm.getUiContext();
+            }
+
+            Context uiContextForCurrentUser = mAtm.getUiContext().createContextAsUser(
+                    new UserHandle(mAtm.getCurrentUserId()), /* flags= */ 0);
+            return uiContextForCurrentUser;
+        }
+
+        DisplayContent dc = ar.mDisplayContent;
+        Context systemUiContext = dc.getDisplayPolicy().getSystemUiContext();
+        int assignedUser = getUserAssignedToDisplay(dc.getDisplayId());
+        Context uiContextForUser = systemUiContext.createContextAsUser(
+                new UserHandle(assignedUser), /* flags= */ 0);
+        return uiContextForUser;
+    }
+
+    /**
+     * Returns the main user that is assigned to the display.
+     *
+     * See {@link UserManagerInternal#getUserAssignedToDisplay(int)}.
+     */
+    private @UserIdInt int getUserAssignedToDisplay(int displayId) {
+        return mUserManagerInternal.getUserAssignedToDisplay(displayId);
+    }
+
+    /**
      * Handles messages on the system process UI thread.
      */
     private final class UiHandler extends Handler {
@@ -470,7 +668,8 @@
                 } break;
                 case MSG_HIDE_DIALOGS_FOR_PACKAGE: {
                     final String name = (String) msg.obj;
-                    hideDialogsForPackageUiThread(name);
+                    final int userId = (int) msg.arg1;
+                    hideDialogsForPackageUiThread(name, userId);
                 } break;
                 case MSG_SHOW_DEPRECATED_TARGET_SDK_DIALOG: {
                     final ActivityRecord ar = (ActivityRecord) msg.obj;
@@ -508,20 +707,24 @@
             obtainMessage(MSG_SHOW_DEPRECATED_ABI_DIALOG, r).sendToTarget();
         }
 
-        public void hideDialogsForPackage(String name) {
-            obtainMessage(MSG_HIDE_DIALOGS_FOR_PACKAGE, name).sendToTarget();
+        public void hideDialogsForPackage(String name, int userId) {
+            obtainMessage(MSG_HIDE_DIALOGS_FOR_PACKAGE, userId, 0, name).sendToTarget();
         }
     }
 
     static class BaseDialog {
         final AppWarnings mManager;
+        final Context mUiContext;
         final String mPackageName;
+        final int mUserId;
         AlertDialog mDialog;
         private BroadcastReceiver mCloseReceiver;
 
-        BaseDialog(AppWarnings manager, String packageName) {
+        BaseDialog(AppWarnings manager, Context uiContext, String packageName, int userId) {
             mManager = manager;
+            mUiContext = uiContext;
             mPackageName = packageName;
+            mUserId = userId;
         }
 
         @UiThread
@@ -532,11 +735,11 @@
                     @Override
                     public void onReceive(Context context, Intent intent) {
                         if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
-                            mManager.mUiHandler.hideDialogsForPackage(mPackageName);
+                            mManager.mUiHandler.hideDialogsForPackage(mPackageName, mUserId);
                         }
                     }
                 };
-                mManager.mUiContext.registerReceiver(mCloseReceiver,
+                mUiContext.registerReceiver(mCloseReceiver,
                         new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
                         Context.RECEIVER_EXPORTED);
             }
@@ -548,7 +751,7 @@
         void dismiss() {
             if (mDialog == null) return;
             if (mCloseReceiver != null) {
-                mManager.mUiContext.unregisterReceiver(mCloseReceiver);
+                mUiContext.unregisterReceiver(mCloseReceiver);
                 mCloseReceiver = null;
             }
             mDialog.dismiss();
@@ -558,12 +761,13 @@
 
     private final class WriteConfigTask implements Runnable {
         private static final long WRITE_CONFIG_DELAY_MS = 10000;
-        final AtomicReference<ArrayMap<String, Integer>> mPendingPackageFlags =
+        final AtomicReference<ArrayMap<Pair<Integer, String>, Integer>> mPendingPackageFlags =
                 new AtomicReference<>();
 
         @Override
         public void run() {
-            final ArrayMap<String, Integer> packageFlags = mPendingPackageFlags.getAndSet(null);
+            final ArrayMap<Pair<Integer, String>, Integer> packageFlags =
+                    mPendingPackageFlags.getAndSet(null);
             if (packageFlags != null) {
                 writeConfigToFile(packageFlags);
             }
@@ -579,7 +783,7 @@
 
     /** Writes the configuration file. */
     @WorkerThread
-    private void writeConfigToFile(@NonNull ArrayMap<String, Integer> packageFlags) {
+    private void writeConfigToFile(@NonNull ArrayMap<Pair<Integer, String>, Integer> packageFlags) {
         FileOutputStream fos = null;
         try {
             fos = mConfigFile.startWrite();
@@ -590,13 +794,16 @@
             out.startTag(null, "packages");
 
             for (int i = 0; i < packageFlags.size(); i++) {
-                final String pkg = packageFlags.keyAt(i);
+                final Pair<Integer, String> key = packageFlags.keyAt(i);
+                final int userId = key.first;
+                final String packageName = key.second;
                 final int mode = packageFlags.valueAt(i);
                 if (mode == 0) {
                     continue;
                 }
                 out.startTag(null, "package");
-                out.attribute(null, "name", pkg);
+                out.attributeInt(null, "user", userId);
+                out.attribute(null, "name", packageName);
                 out.attributeInt(null, "flags", mode);
                 out.endTag(null, "package");
             }
@@ -616,7 +823,7 @@
     /**
      * Reads the configuration file and populates the package flags.
      * <p>
-     * <strong>Note:</strong> Must be called from the constructor (and thus on the
+     * <strong>Note:</strong> Must be called from #onSystemReady() (and thus on the
      * ActivityManagerService thread) since we don't synchronize on config.
      */
     private void readConfigFromFileAmsThread() {
@@ -639,21 +846,58 @@
             String tagName = parser.getName();
             if ("packages".equals(tagName)) {
                 eventType = parser.next();
+                boolean writeConfigToFileNeeded = false;
                 do {
                     if (eventType == XmlPullParser.START_TAG) {
                         tagName = parser.getName();
                         if (parser.getDepth() == 2) {
                             if ("package".equals(tagName)) {
+                                final int userId = parser.getAttributeInt(
+                                        null, "user", USER_NULL);
                                 final String name = parser.getAttributeValue(null, "name");
                                 if (name != null) {
                                     int flagsInt = parser.getAttributeInt(null, "flags", 0);
-                                    mPackageFlags.put(name, flagsInt);
+                                    if (userId != USER_NULL) {
+                                        final Pair<Integer, String> packageKey =
+                                                Pair.create(userId, name);
+                                        mPackageFlags.put(packageKey, flagsInt);
+                                    } else {
+                                        // This is for compatibility with existing configuration
+                                        // file written from legacy logic(pre-V) which does not have
+                                        // the flags per-user. (b/296334639)
+                                        writeConfigToFileNeeded = true;
+                                        if (!isVisibleBackgroundUsersEnabled()) {
+                                            // To preserve existing behavior of the devices that
+                                            // doesn't enable visible background users, populate
+                                            // the flags for a package as the system user.
+                                            final Pair<Integer, String> packageKey =
+                                                    Pair.create(USER_SYSTEM, name);
+                                            mPackageFlags.put(packageKey, flagsInt);
+                                        } else {
+                                            // To manage the flags per user in the device that
+                                            // enable visible background users, populate the flags
+                                            // for all existing non-profile human user.
+                                            UserInfo[] users = mUserManagerInternal.getUserInfos();
+                                            for (UserInfo userInfo : users) {
+                                                if (!userInfo.isFull()) {
+                                                    continue;
+                                                }
+                                                final Pair<Integer, String> packageKey =
+                                                        Pair.create(userInfo.id, name);
+                                                mPackageFlags.put(packageKey, flagsInt);
+                                            }
+                                        }
+                                    }
                                 }
                             }
                         }
                     }
                     eventType = parser.next();
                 } while (eventType != XmlPullParser.END_DOCUMENT);
+
+                if (writeConfigToFileNeeded) {
+                    mWriteConfigTask.schedule();
+                }
             }
         } catch (XmlPullParserException e) {
             Slog.w(TAG, "Error reading package metadata", e);
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index f6681c5..d0c6e15 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -20,6 +20,7 @@
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_NONE;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -173,27 +174,6 @@
                 }
             }
 
-            // This is needed to bridge the old and new back behavior with recents.  While in
-            // Overview with live tile enabled, the previous app is technically focused but we
-            // add an input consumer to capture all input that would otherwise go to the apps
-            // being controlled by the animation. This means that the window resolved is not
-            // the right window to consume back while in overview, so we need to route it to
-            // launcher and use the legacy behavior of injecting KEYCODE_BACK since the existing
-            // compat callback in VRI only works when the window is focused.
-            // This symptom also happen while shell transition enabled, we can check that by
-            // isTransientLaunch to know whether the focus window is point to live tile.
-            final RecentsAnimationController recentsAnimationController =
-                    wmService.getRecentsAnimationController();
-            final ActivityRecord tmpAR = window.mActivityRecord;
-            if ((tmpAR != null && tmpAR.isActivityTypeHomeOrRecents()
-                    && tmpAR.mTransitionController.isTransientLaunch(tmpAR))
-                    || (recentsAnimationController != null
-                    && recentsAnimationController.shouldApplyInputConsumer(tmpAR))) {
-                ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Current focused window being animated by "
-                        + "recents. Overriding back callback to recents controller callback.");
-                return null;
-            }
-
             if (!window.isDrawn()) {
                 ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
                         "Focused window didn't have a valid surface drawn.");
@@ -779,6 +759,10 @@
                     && wc.asTaskFragment() == null) {
                 continue;
             }
+            // Only care if visibility changed.
+            if (targets.get(i).getTransitMode(wc) == TRANSIT_CHANGE) {
+                continue;
+            }
             // WC can be visible due to setLaunchBehind
             if (wc.isVisibleRequested()) {
                 mTmpOpenApps.add(wc);
@@ -827,6 +811,13 @@
         return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
     }
 
+    boolean shouldPauseTouch(WindowContainer wc) {
+        // Once the close transition is ready, it means the onBackInvoked callback has invoked, and
+        // app is ready to trigger next transition, no matter what it will be.
+        return mAnimationHandler.mComposed && mWaitTransitionFinish == null
+                && mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
+    }
+
     /**
      * Cleanup animation, this can either happen when legacy transition ready, or when the Shell
      * transition finish.
@@ -843,14 +834,14 @@
      * @param targets The final animation targets derived in transition.
      * @param finishedTransition The finished transition target.
     */
-    boolean onTransitionFinish(ArrayList<Transition.ChangeInfo> targets,
+    void onTransitionFinish(ArrayList<Transition.ChangeInfo> targets,
             @NonNull Transition finishedTransition) {
         if (finishedTransition == mWaitTransitionFinish) {
             clearBackAnimations();
         }
 
         if (!mBackAnimationInProgress || mPendingAnimationBuilder == null) {
-            return false;
+            return;
         }
         ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
                 "Handling the deferred animation after transition finished");
@@ -878,7 +869,7 @@
                     + " open: " + Arrays.toString(mPendingAnimationBuilder.mOpenTargets)
                     + " close: " + mPendingAnimationBuilder.mCloseTarget);
             cancelPendingAnimation();
-            return false;
+            return;
         }
 
         // Ensure the final animation targets which hidden by transition could be visible.
@@ -887,9 +878,14 @@
             wc.prepareSurfaces();
         }
 
-        scheduleAnimation(mPendingAnimationBuilder);
-        mPendingAnimationBuilder = null;
-        return true;
+        // The pending builder could be cleared due to prepareSurfaces
+        // => updateNonSystemOverlayWindowsVisibilityIfNeeded
+        // => setForceHideNonSystemOverlayWindowIfNeeded
+        // => updateFocusedWindowLocked => onFocusWindowChanged.
+        if (mPendingAnimationBuilder != null) {
+            scheduleAnimation(mPendingAnimationBuilder);
+            mPendingAnimationBuilder = null;
+        }
     }
 
     private void cancelPendingAnimation() {
@@ -1552,15 +1548,17 @@
                 return this;
             }
 
+            // WC must be Activity/TaskFragment/Task
             boolean containTarget(@NonNull WindowContainer wc) {
                 if (mOpenTargets != null) {
                     for (int i = mOpenTargets.length - 1; i >= 0; --i) {
-                        if (wc == mOpenTargets[i] || mOpenTargets[i].hasChild(wc)) {
+                        if (wc == mOpenTargets[i] || mOpenTargets[i].hasChild(wc)
+                                || wc.hasChild(mOpenTargets[i])) {
                             return true;
                         }
                     }
                 }
-                return wc == mCloseTarget || mCloseTarget.hasChild(wc);
+                return wc == mCloseTarget || mCloseTarget.hasChild(wc) || wc.hasChild(mCloseTarget);
             }
 
             /**
@@ -1771,18 +1769,39 @@
     }
 
     private void onBackNavigationDone(Bundle result, int backType) {
-        boolean triggerBack = result != null && result.getBoolean(
-                BackNavigationInfo.KEY_TRIGGER_BACK);
-        ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
-                + "triggerBack=%b", backType, triggerBack);
+        if (result == null) {
+            return;
+        }
+        if (result.containsKey(BackNavigationInfo.KEY_NAVIGATION_FINISHED)) {
+            final boolean triggerBack = result.getBoolean(
+                    BackNavigationInfo.KEY_NAVIGATION_FINISHED);
+            ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+                    + "triggerBack=%b", backType, triggerBack);
 
-        synchronized (mWindowManagerService.mGlobalLock) {
-            mNavigationMonitor.stopMonitorForRemote();
-            mBackAnimationInProgress = false;
-            mShowWallpaper = false;
-            // All animation should be done, clear any un-send animation.
-            mPendingAnimation = null;
-            mPendingAnimationBuilder = null;
+            synchronized (mWindowManagerService.mGlobalLock) {
+                mNavigationMonitor.stopMonitorForRemote();
+                mBackAnimationInProgress = false;
+                mShowWallpaper = false;
+                // All animation should be done, clear any un-send animation.
+                mPendingAnimation = null;
+                mPendingAnimationBuilder = null;
+            }
+        }
+        if (result.getBoolean(BackNavigationInfo.KEY_GESTURE_FINISHED)) {
+            synchronized (mWindowManagerService.mGlobalLock) {
+                final AnimationHandler ah = mAnimationHandler;
+                if (!ah.mComposed || ah.mWaitTransition || ah.mOpenActivities == null
+                        || (ah.mSwitchType != AnimationHandler.TASK_SWITCH
+                        && ah.mSwitchType != AnimationHandler.ACTIVITY_SWITCH)) {
+                    return;
+                }
+                for (int i = mAnimationHandler.mOpenActivities.length - 1; i >= 0; --i) {
+                    final ActivityRecord preDrawActivity = mAnimationHandler.mOpenActivities[i];
+                    if (!preDrawActivity.mLaunchTaskBehind) {
+                        setLaunchBehind(preDrawActivity);
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 47f4a66..0e446b8 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -38,9 +38,11 @@
 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
 import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
 import static com.android.server.wm.PendingRemoteAnimationRegistry.TIMEOUT_MS;
+import static com.android.window.flags.Flags.balDontBringExistingBackgroundTaskStackToFg;
 import static com.android.window.flags.Flags.balImproveRealCallerVisibilityCheck;
 import static com.android.window.flags.Flags.balRequireOptInByPendingIntentCreator;
 import static com.android.window.flags.Flags.balRequireOptInSameUid;
+import static com.android.window.flags.Flags.balRespectAppSwitchStateWhenCheckBoundByForegroundUid;
 import static com.android.window.flags.Flags.balShowToastsBlocked;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -539,6 +541,16 @@
                 sb.append("; balAllowedByPiSender: ").append(mBalAllowedByPiSender);
                 sb.append("; resultIfPiSenderAllowsBal: ").append(mResultForRealCaller);
             }
+            // features
+            sb.append("; balImproveRealCallerVisibilityCheck: ")
+                    .append(balImproveRealCallerVisibilityCheck());
+            sb.append("; balRequireOptInByPendingIntentCreator: ")
+                    .append(balRequireOptInByPendingIntentCreator());
+            sb.append("; balRequireOptInSameUid: ").append(balRequireOptInSameUid());
+            sb.append("; balRespectAppSwitchStateWhenCheckBoundByForegroundUid: ")
+                    .append(balRespectAppSwitchStateWhenCheckBoundByForegroundUid());
+            sb.append("; balDontBringExistingBackgroundTaskStackToFg: ")
+                    .append(balDontBringExistingBackgroundTaskStackToFg());
             sb.append("]");
             return sb.toString();
         }
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index be7c18c..31754bf 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -467,13 +467,6 @@
         onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
-    /** Sets the windowing mode for the configuration container. */
-    void setDisplayWindowingMode(int windowingMode) {
-        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mRequestsTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
-        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
-    }
-
     /**
      * Returns true if this container is currently in multi-window mode. I.e. sharing the screen
      * with another activity.
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index 8020516..d70a880 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -109,7 +109,8 @@
         this(displayContent, new RemoteMediaProjectionManagerWrapper(displayContent.mDisplayId),
                 new DisplayManagerFlags().isConnectedDisplayManagementEnabled()
                         && !new DisplayManagerFlags()
-                                    .isPixelAnisotropyCorrectionInLogicalDisplayEnabled());
+                                    .isPixelAnisotropyCorrectionInLogicalDisplayEnabled()
+                        && displayContent.getDisplayInfo().type == Display.TYPE_EXTERNAL);
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java b/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java
index e96208d..46b34a1 100644
--- a/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java
+++ b/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java
@@ -28,8 +28,8 @@
 
 class DeprecatedAbiDialog extends AppWarnings.BaseDialog {
     DeprecatedAbiDialog(final AppWarnings manager, Context context,
-            ApplicationInfo appInfo) {
-        super(manager, appInfo.packageName);
+            ApplicationInfo appInfo, int userId) {
+        super(manager, context, appInfo.packageName, userId);
 
         final PackageManager pm = context.getPackageManager();
         final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -41,7 +41,7 @@
         final AlertDialog.Builder builder = new AlertDialog.Builder(context)
                 .setPositiveButton(R.string.ok, (dialog, which) ->
                     manager.setPackageFlag(
-                            mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_ABI, true))
+                            mUserId, mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_ABI, true))
                 .setMessage(message)
                 .setTitle(label);
 
diff --git a/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java b/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java
index 1a7a9b2..ce42385 100644
--- a/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java
+++ b/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java
@@ -31,8 +31,8 @@
 class DeprecatedTargetSdkVersionDialog extends AppWarnings.BaseDialog {
 
     DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context,
-            ApplicationInfo appInfo) {
-        super(manager, appInfo.packageName);
+            ApplicationInfo appInfo, int userId) {
+        super(manager, context, appInfo.packageName, userId);
 
         final PackageManager pm = context.getPackageManager();
         final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -44,7 +44,7 @@
         final AlertDialog.Builder builder = new AlertDialog.Builder(context)
                 .setPositiveButton(R.string.ok, (dialog, which) ->
                     manager.setPackageFlag(
-                            mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true))
+                            mUserId, mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true))
                 .setMessage(message)
                 .setTitle(label);
 
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index efeb85f..d49a507 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -40,6 +40,10 @@
 import android.os.Bundle;
 import android.text.TextUtils;
 
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.UsesReflection;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -184,6 +188,13 @@
         /**
          * Instantiates the device-specific {@link Provider}.
          */
+        @UsesReflection(
+                value = {
+                        @KeepTarget(
+                                kind = KeepItemKind.CLASS_AND_MEMBERS,
+                                instanceOfClassConstantExclusive = Provider.class,
+                                methodName = "<init>")
+                })
         static Provider fromResources(Resources res) {
             String name = res.getString(
                     com.android.internal.R.string.config_deviceSpecificDisplayAreaPolicyProvider);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index cde3e68..95ec75c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -197,6 +197,7 @@
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.ArrayMap;
@@ -245,6 +246,7 @@
 import android.window.DisplayWindowPolicyController;
 import android.window.IDisplayAreaOrganizer;
 import android.window.ScreenCapture;
+import android.window.ScreenCapture.LayerCaptureArgs;
 import android.window.SystemPerformanceHinter;
 import android.window.TransitionRequestInfo;
 
@@ -289,6 +291,9 @@
 
     static final float INVALID_DPI = 0.0f;
 
+    private final boolean mVisibleBackgroundUserEnabled =
+            UserManager.isVisibleBackgroundUsersEnabled();
+
     @IntDef(prefix = { "FORCE_SCALING_MODE_" }, value = {
             FORCE_SCALING_MODE_AUTO,
             FORCE_SCALING_MODE_DISABLED
@@ -1007,8 +1012,6 @@
 
     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
-        final boolean obscuredChanged = w.mObscured !=
-                mTmpApplySurfaceChangesTransactionState.obscured;
         final RootWindowContainer root = mWmService.mRoot;
 
         if (w.mHasSurface) {
@@ -1107,12 +1110,6 @@
             }
         }
 
-        if (obscuredChanged && w.isVisible() && mWallpaperController.isWallpaperTarget(w)) {
-            // This is the wallpaper target and its obscured state changed... make sure the
-            // current wallpaper's visibility has been updated accordingly.
-            mWallpaperController.updateWallpaperTokens(mDisplayContent.isKeyguardLocked());
-        }
-
         w.handleWindowMovedIfNeeded();
 
         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
@@ -2007,7 +2004,12 @@
         }
         // Update directly because the app which will change the orientation of display is ready.
         if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
-            sendNewConfiguration();
+            // Run rotation change on display thread. See Transition#shouldApplyOnDisplayThread().
+            mWmService.mH.post(() -> {
+                synchronized (mWmService.mGlobalLock) {
+                    sendNewConfiguration();
+                }
+            });
             return;
         }
         if (mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange()) {
@@ -2277,7 +2279,7 @@
         }
 
         computeSizeRanges(mDisplayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig,
-                false /* legacyConfig */);
+                false /* overrideConfig */);
 
         setDisplayInfoOverride();
 
@@ -2414,7 +2416,7 @@
         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation);
         displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
         computeSizeRanges(displayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig,
-                false /* legacyConfig */);
+                false /* overrideConfig */);
         return displayInfo;
     }
 
@@ -2455,7 +2457,6 @@
         config.windowConfiguration.setBounds(mTmpRect);
         config.windowConfiguration.setMaxBounds(mTmpRect);
         config.windowConfiguration.setWindowingMode(getWindowingMode());
-        config.windowConfiguration.setDisplayWindowingMode(getWindowingMode());
 
         computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation);
 
@@ -2588,11 +2589,10 @@
      * @param dh Display Height in current rotation.
      * @param density Display density.
      * @param outConfig The output configuration to
-     * @param legacyConfig Whether we need to report the legacy result, which is excluding system
-     *                     decorations.
+     * @param overrideConfig Whether we need to report the override config result
      */
     void computeSizeRanges(DisplayInfo displayInfo, boolean rotated,
-            int dw, int dh, float density, Configuration outConfig, boolean legacyConfig) {
+            int dw, int dh, float density, Configuration outConfig, boolean overrideConfig) {
 
         // We need to determine the smallest width that will occur under normal
         // operation.  To this, start with the base screen size and compute the
@@ -2610,10 +2610,12 @@
         displayInfo.smallestNominalAppHeight = 1<<30;
         displayInfo.largestNominalAppWidth = 0;
         displayInfo.largestNominalAppHeight = 0;
-        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh, legacyConfig);
-        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw, legacyConfig);
-        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh, legacyConfig);
-        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw, legacyConfig);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh, overrideConfig);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw, overrideConfig);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh,
+                overrideConfig);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw,
+                overrideConfig);
 
         if (outConfig == null) {
             return;
@@ -2623,17 +2625,17 @@
     }
 
     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh,
-            boolean legacyConfig) {
+            boolean overrideConfig) {
         final DisplayPolicy.DecorInsets.Info info = mDisplayPolicy.getDecorInsetsInfo(
                 rotation, dw, dh);
         final int w;
         final int h;
-        if (!legacyConfig) {
+        if (!overrideConfig) {
             w = info.mConfigFrame.width();
             h = info.mConfigFrame.height();
         } else {
-            w = info.mLegacyConfigFrame.width();
-            h = info.mLegacyConfigFrame.height();
+            w = info.mOverrideConfigFrame.width();
+            h = info.mOverrideConfigFrame.height();
         }
         if (w < displayInfo.smallestNominalAppWidth) {
             displayInfo.smallestNominalAppWidth = w;
@@ -2705,11 +2707,15 @@
      * Returns true if the specified UID has access to this display.
      */
     boolean hasAccess(int uid) {
-        int userId = UserHandle.getUserId(uid);
-        boolean isUserVisibleOnDisplay = mWmService.mUmInternal.isUserVisible(
-                userId, mDisplayId);
-        return mDisplay.hasAccess(uid)
-                && (userId == UserHandle.USER_SYSTEM || isUserVisibleOnDisplay);
+        if (!mDisplay.hasAccess(uid)) {
+            return false;
+        }
+        if (!mVisibleBackgroundUserEnabled) {
+            return true;
+        }
+        final int userId = UserHandle.getUserId(uid);
+        return userId == UserHandle.USER_SYSTEM
+                || mWmService.mUmInternal.isUserVisible(userId, mDisplayId);
     }
 
     boolean isPrivate() {
@@ -2828,11 +2834,6 @@
         }
     }
 
-    @Override
-    void setDisplayWindowingMode(int windowingMode) {
-        setWindowingMode(windowingMode);
-    }
-
     /**
      * See {@code WindowState#applyImeWindowsIfNeeded} for the details that we won't traverse the
      * IME window in some cases.
@@ -2950,7 +2951,6 @@
     void onDisplayChanged(DisplayContent dc) {
         super.onDisplayChanged(dc);
         updateSystemGestureExclusionLimit();
-        updateKeepClearAreas();
     }
 
     void updateSystemGestureExclusionLimit() {
@@ -4029,7 +4029,6 @@
         }
 
         adjustForImeIfNeeded();
-        updateKeepClearAreas();
 
         // We may need to schedule some toast windows to be removed. The toasts for an app that
         // does not have input focus are removed within a timeout to prevent apps to redress
@@ -5226,7 +5225,7 @@
     /**
      * Creates a LayerCaptureArgs object to represent the entire DisplayContent
      */
-    ScreenCapture.LayerCaptureArgs getLayerCaptureArgs() {
+    LayerCaptureArgs getLayerCaptureArgs(Set<Integer> windowTypesToExclude) {
         if (!mWmService.mPolicy.isScreenOn()) {
             if (DEBUG_SCREENSHOT) {
                 Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
@@ -5236,8 +5235,23 @@
 
         getBounds(mTmpRect);
         mTmpRect.offsetTo(0, 0);
-        return new ScreenCapture.LayerCaptureArgs.Builder(getSurfaceControl())
-                .setSourceCrop(mTmpRect).build();
+        LayerCaptureArgs.Builder builder = new LayerCaptureArgs.Builder(getSurfaceControl())
+                .setSourceCrop(mTmpRect);
+
+        if (!windowTypesToExclude.isEmpty()) {
+            ArrayList<SurfaceControl> surfaceControls = new ArrayList<>();
+            forAllWindows(
+                    window -> {
+                        if (windowTypesToExclude.contains(window.getWindowType())) {
+                            surfaceControls.add(window.mSurfaceControl);
+                        }
+                    }, true
+            );
+            if (!surfaceControls.isEmpty()) {
+                builder.setExcludeLayers(surfaceControls.toArray(new SurfaceControl[0]));
+            }
+        }
+        return builder.build();
     }
 
     @Override
@@ -6150,6 +6164,7 @@
                     Region touchableRegion = Region.obtain();
                     w.getEffectiveTouchableRegion(touchableRegion);
                     RegionUtils.forEachRect(touchableRegion, rect -> outUnrestricted.add(rect));
+                    touchableRegion.recycle();
                 }
             }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a5037ea..84dadab 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -41,7 +41,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_CONSUME_IME_INSETS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IMMERSIVE_CONFIRMATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
@@ -986,19 +985,6 @@
                                 + " to fit insets. fitInsetsTypes=" + WindowInsets.Type.toString(
                                         attrs.getFitInsetsTypes()));
                     }
-                    if ((attrs.privateFlags & PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED) != 0
-                            && attrs.layoutInDisplayCutoutMode
-                                    != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
-                        // A non-translucent main window of the app enforced to go edge-to-edge
-                        // isn't allowed to fit display cutout, or it will cause software bezels.
-                        throw new IllegalArgumentException("Illegal attributes: Main window of "
-                                + win.mActivityRecord.getName() + " that isn't translucent and"
-                                + " targets SDK level " + win.mActivityRecord.mTargetSdk
-                                + " (>= 35) trying to specify layoutInDisplayCutoutMode as '"
-                                + WindowManager.LayoutParams.layoutInDisplayCutoutModeToString(
-                                        attrs.layoutInDisplayCutoutMode)
-                                + "' instead of 'always'");
-                    }
                 }
                 break;
         }
@@ -1935,9 +1921,14 @@
             final Rect mConfigInsets = new Rect();
 
             /**
-             * Legacy value of mConfigInsets for app compatibility purpose.
+             * Override value of mConfigInsets for app compatibility purpose.
              */
-            final Rect mLegacyConfigInsets = new Rect();
+            final Rect mOverrideConfigInsets = new Rect();
+
+            /**
+             * Override value of mNonDecorInsets for app compatibility purpose.
+             */
+            final Rect mOverrideNonDecorInsets = new Rect();
 
             /** The display frame available after excluding {@link #mNonDecorInsets}. */
             final Rect mNonDecorFrame = new Rect();
@@ -1950,9 +1941,14 @@
             final Rect mConfigFrame = new Rect();
 
             /**
-             * Legacy value of mConfigFrame for app compatibility purpose.
+             * Override value of mConfigFrame for app compatibility purpose.
              */
-            final Rect mLegacyConfigFrame = new Rect();
+            final Rect mOverrideConfigFrame = new Rect();
+
+            /**
+             * Override value of mNonDecorFrame for app compatibility purpose.
+             */
+            final Rect mOverrideNonDecorFrame = new Rect();
 
             private boolean mNeedUpdate = true;
 
@@ -1968,22 +1964,31 @@
                         ? decor
                         : insetsState.calculateInsets(displayFrame, dc.mWmService.mConfigTypes,
                                 true /* ignoreVisibility */);
-                final Insets legacyConfigInsets = dc.mWmService.mConfigTypes
-                        == dc.mWmService.mLegacyConfigTypes
+                final Insets overrideConfigInsets = dc.mWmService.mConfigTypes
+                        == dc.mWmService.mOverrideConfigTypes
                         ? configInsets
                         : insetsState.calculateInsets(displayFrame,
-                                dc.mWmService.mLegacyConfigTypes, true /* ignoreVisibility */);
+                                dc.mWmService.mOverrideConfigTypes, true /* ignoreVisibility */);
+                final Insets overrideDecorInsets = dc.mWmService.mDecorTypes
+                        == dc.mWmService.mOverrideDecorTypes
+                        ? decor
+                        : insetsState.calculateInsets(displayFrame,
+                                dc.mWmService.mOverrideDecorTypes, true /* ignoreVisibility */);
                 mNonDecorInsets.set(decor.left, decor.top, decor.right, decor.bottom);
                 mConfigInsets.set(configInsets.left, configInsets.top, configInsets.right,
                         configInsets.bottom);
-                mLegacyConfigInsets.set(legacyConfigInsets.left, legacyConfigInsets.top,
-                        legacyConfigInsets.right, legacyConfigInsets.bottom);
+                mOverrideConfigInsets.set(overrideConfigInsets.left, overrideConfigInsets.top,
+                        overrideConfigInsets.right, overrideConfigInsets.bottom);
+                mOverrideNonDecorInsets.set(overrideDecorInsets.left, overrideDecorInsets.top,
+                        overrideDecorInsets.right, overrideDecorInsets.bottom);
                 mNonDecorFrame.set(displayFrame);
                 mNonDecorFrame.inset(mNonDecorInsets);
                 mConfigFrame.set(displayFrame);
                 mConfigFrame.inset(mConfigInsets);
-                mLegacyConfigFrame.set(displayFrame);
-                mLegacyConfigFrame.inset(mLegacyConfigInsets);
+                mOverrideConfigFrame.set(displayFrame);
+                mOverrideConfigFrame.inset(mOverrideConfigInsets);
+                mOverrideNonDecorFrame.set(displayFrame);
+                mOverrideNonDecorFrame.inset(mOverrideNonDecorInsets);
                 mNeedUpdate = false;
                 return insetsState;
             }
@@ -1991,10 +1996,12 @@
             void set(Info other) {
                 mNonDecorInsets.set(other.mNonDecorInsets);
                 mConfigInsets.set(other.mConfigInsets);
-                mLegacyConfigInsets.set(other.mLegacyConfigInsets);
+                mOverrideConfigInsets.set(other.mOverrideConfigInsets);
+                mOverrideNonDecorInsets.set(other.mOverrideNonDecorInsets);
                 mNonDecorFrame.set(other.mNonDecorFrame);
                 mConfigFrame.set(other.mConfigFrame);
-                mLegacyConfigFrame.set(other.mLegacyConfigFrame);
+                mOverrideConfigFrame.set(other.mOverrideConfigFrame);
+                mOverrideNonDecorFrame.set(other.mOverrideNonDecorFrame);
                 mNeedUpdate = false;
             }
 
@@ -2107,7 +2114,7 @@
         final InsetsState newInsetsState = newInfo.update(mDisplayContent, rotation, dw, dh);
         final DecorInsets.Info currentInfo = getDecorInsetsInfo(rotation, dw, dh);
         if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)
-                && newInfo.mLegacyConfigFrame.equals(currentInfo.mLegacyConfigFrame)) {
+                && newInfo.mOverrideConfigFrame.equals(currentInfo.mOverrideConfigFrame)) {
             // Even if the config frame is not changed in current rotation, it may change the
             // insets in other rotations if the frame of insets source is changed.
             final InsetsState currentInsetsState = mDisplayContent.mDisplayFrames.mInsetsState;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 4a97128..afcf364 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.Display.TYPE_EXTERNAL;
 import static android.view.Display.TYPE_OVERLAY;
+import static android.view.Display.TYPE_VIRTUAL;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
@@ -1794,20 +1795,36 @@
         }
     }
 
+    @VisibleForTesting
+    int getDemoUserRotationOverride() {
+        return SystemProperties.getInt("persist.demo.userrotation", Surface.ROTATION_0);
+    }
+
+    @VisibleForTesting
+    @NonNull
+    String getDemoUserRotationPackage() {
+        return SystemProperties.get("persist.demo.userrotation.package_name");
+    }
+
     @Surface.Rotation
     private int getUserRotationOverride() {
-        final int userRotationOverride = SystemProperties.getInt("persist.demo.userrotation",
-                Surface.ROTATION_0);
+        final int userRotationOverride = getDemoUserRotationOverride();
         if (userRotationOverride == Surface.ROTATION_0) {
             return userRotationOverride;
         }
 
-        final var display = mDisplayContent.mDisplay;
+        final var display = mDisplayContent.getDisplay();
         if (display.getType() == TYPE_EXTERNAL || display.getType() == TYPE_OVERLAY) {
-            // TODO b/329442350 add chromecast virtual displays here
             return userRotationOverride;
         }
 
+        if (display.getType() == TYPE_VIRTUAL) {
+            final var packageName = getDemoUserRotationPackage();
+            if (!packageName.isEmpty() && packageName.equals(display.getOwnerPackageName())) {
+                return userRotationOverride;
+            }
+        }
+
         return Surface.ROTATION_0;
     }
 
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 2dbb370..092ff3d 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -181,8 +181,10 @@
         }
         WindowToken imeToken = mWindowContainer.asWindowState() != null
                 ? mWindowContainer.asWindowState().mToken : null;
-        if (mDisplayContent.getAsyncRotationController() != null
-                && mDisplayContent.getAsyncRotationController().isTargetToken(imeToken)) {
+        final var rotationController = mDisplayContent.getAsyncRotationController();
+        if ((rotationController != null && rotationController.isTargetToken(imeToken))
+                || (imeToken != null && imeToken.isSelfAnimating(
+                        0 /* flags */, SurfaceAnimator.ANIMATION_TYPE_TOKEN_TRANSFORM))) {
             // Skip reporting IME drawn state when the control target is in fixed
             // rotation, AsyncRotationController will report after the animation finished.
             return;
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index a8cbc62..8858766 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -519,8 +519,17 @@
         final SurfaceControl leash = mAdapter.mCapturedLeash;
         mControlTarget = target;
         updateVisibility();
+        boolean initiallyVisible = mClientVisible;
+        if (mSource.getType() == WindowInsets.Type.ime()) {
+            // The IME cannot be initially visible, see ControlAdapter#startAnimation below.
+            // Also, the ImeInsetsSourceConsumer clears the client visibility upon losing control,
+            // but this won't have reached here yet by the time the new control is created.
+            // Note: The DisplayImeController needs the correct previous client's visibility, so we
+            // only override the initiallyVisible here.
+            initiallyVisible = false;
+        }
         mControl = new InsetsSourceControl(mSource.getId(), mSource.getType(), leash,
-                mClientVisible, surfacePosition, getInsetsHint());
+                initiallyVisible, surfacePosition, getInsetsHint());
 
         ProtoLog.d(WM_DEBUG_WINDOW_INSETS,
                 "InsetsSource Control %s for target %s", mControl, mControlTarget);
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 3a04bcd..dfee164 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -224,7 +224,6 @@
         if (changed) {
             notifyInsetsChanged();
             mDisplayContent.updateSystemGestureExclusion();
-            mDisplayContent.updateKeepClearAreas();
             mDisplayContent.getDisplayPolicy().updateSystemBarAttributes();
         }
     }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index b8bb258..0ad601d 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -61,6 +61,7 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.policy.WindowManagerPolicy;
+import com.android.window.flags.Flags;
 
 import java.io.PrintWriter;
 
@@ -225,13 +226,16 @@
             if (keyguardShowing) {
                 state.mDismissalRequested = false;
             }
-            if (goingAwayRemoved) {
-                // Keyguard dismiss is canceled. Send a transition to undo the changes and clean up
-                // before holding the sleep token again.
+            if (goingAwayRemoved || (keyguardShowing && Flags.keyguardAppearTransition())) {
+                // Keyguard decided to show or stopped going away. Send a transition to animate back
+                // to the locked state before holding the sleep token again
                 final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
                 dc.requestTransitionAndLegacyPrepare(
                         TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING);
-                mWindowManager.executeAppTransition();
+                if (Flags.keyguardAppearTransition()) {
+                    dc.mWallpaperController.adjustWallpaperWindows();
+                }
+                dc.executeAppTransition();
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 45cf10b..5aa0ed7c 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -327,14 +327,14 @@
                 R.dimen.config_letterboxBackgroundWallpaperBlurRadius);
         mLetterboxBackgroundWallpaperDarkScrimAlpha = mContext.getResources().getFloat(
                 R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha);
-        mLetterboxHorizontalPositionMultiplier = mContext.getResources().getFloat(
-                R.dimen.config_letterboxHorizontalPositionMultiplier);
-        mLetterboxVerticalPositionMultiplier = mContext.getResources().getFloat(
-                R.dimen.config_letterboxVerticalPositionMultiplier);
-        mLetterboxBookModePositionMultiplier = mContext.getResources().getFloat(
-                R.dimen.config_letterboxBookModePositionMultiplier);
-        mLetterboxTabletopModePositionMultiplier = mContext.getResources().getFloat(
-                R.dimen.config_letterboxTabletopModePositionMultiplier);
+        setLetterboxHorizontalPositionMultiplier(mContext.getResources().getFloat(
+                R.dimen.config_letterboxHorizontalPositionMultiplier));
+        setLetterboxVerticalPositionMultiplier(mContext.getResources().getFloat(
+                R.dimen.config_letterboxVerticalPositionMultiplier));
+        setLetterboxBookModePositionMultiplier(mContext.getResources().getFloat(
+                R.dimen.config_letterboxBookModePositionMultiplier));
+        setLetterboxTabletopModePositionMultiplier(mContext.getResources()
+                .getFloat(R.dimen.config_letterboxTabletopModePositionMultiplier));
         mIsHorizontalReachabilityEnabled = mContext.getResources().getBoolean(
                 R.bool.config_letterboxIsHorizontalReachabilityEnabled);
         mIsVerticalReachabilityEnabled = mContext.getResources().getBoolean(
@@ -657,29 +657,8 @@
      * right side.
      */
     float getLetterboxHorizontalPositionMultiplier(boolean isInBookMode) {
-        if (isInBookMode) {
-            if (mLetterboxBookModePositionMultiplier < 0.0f
-                    || mLetterboxBookModePositionMultiplier > 1.0f) {
-                Slog.w(TAG,
-                        "mLetterboxBookModePositionMultiplier out of bounds (isInBookMode=true): "
-                        + mLetterboxBookModePositionMultiplier);
-                // Default to left position if invalid value is provided.
-                return 0.0f;
-            } else {
-                return mLetterboxBookModePositionMultiplier;
-            }
-        } else {
-            if (mLetterboxHorizontalPositionMultiplier < 0.0f
-                    || mLetterboxHorizontalPositionMultiplier > 1.0f) {
-                Slog.w(TAG,
-                        "mLetterboxBookModePositionMultiplier out of bounds (isInBookMode=false):"
-                        + mLetterboxBookModePositionMultiplier);
-                // Default to central position if invalid value is provided.
-                return 0.5f;
-            } else {
-                return mLetterboxHorizontalPositionMultiplier;
-            }
-        }
+        return isInBookMode ? mLetterboxBookModePositionMultiplier
+                : mLetterboxHorizontalPositionMultiplier;
     }
 
     /*
@@ -689,37 +668,28 @@
      * bottom side.
      */
     float getLetterboxVerticalPositionMultiplier(boolean isInTabletopMode) {
-        if (isInTabletopMode) {
-            return (mLetterboxTabletopModePositionMultiplier < 0.0f
-                    || mLetterboxTabletopModePositionMultiplier > 1.0f)
-                    // Default to top position if invalid value is provided.
-                    ? 0.0f : mLetterboxTabletopModePositionMultiplier;
-        } else {
-            return (mLetterboxVerticalPositionMultiplier < 0.0f
-                    || mLetterboxVerticalPositionMultiplier > 1.0f)
-                    // Default to central position if invalid value is provided.
-                    ? 0.5f : mLetterboxVerticalPositionMultiplier;
-        }
+        return isInTabletopMode ? mLetterboxTabletopModePositionMultiplier
+                : mLetterboxVerticalPositionMultiplier;
     }
 
     /**
-     * Overrides horizontal position of a center of the letterboxed app window. If given value < 0
-     * or > 1, then it and a value of {@link
-     * com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier} are ignored and
-     * central position (0.5) is used.
+     * Overrides horizontal position of a center of the letterboxed app window.
+     *
+     * @throws IllegalArgumentException If given value < 0 or > 1.
      */
     void setLetterboxHorizontalPositionMultiplier(float multiplier) {
-        mLetterboxHorizontalPositionMultiplier = multiplier;
+        mLetterboxHorizontalPositionMultiplier = assertValidMultiplier(multiplier,
+                "mLetterboxHorizontalPositionMultiplier");
     }
 
     /**
-     * Overrides vertical position of a center of the letterboxed app window. If given value < 0
-     * or > 1, then it and a value of {@link
-     * com.android.internal.R.dimen.config_letterboxVerticalPositionMultiplier} are ignored and
-     * central position (0.5) is used.
+     * Overrides vertical position of a center of the letterboxed app window.
+     *
+     * @throws IllegalArgumentException If given value < 0 or > 1.
      */
     void setLetterboxVerticalPositionMultiplier(float multiplier) {
-        mLetterboxVerticalPositionMultiplier = multiplier;
+        mLetterboxVerticalPositionMultiplier = assertValidMultiplier(multiplier,
+                "mLetterboxVerticalPositionMultiplier");
     }
 
     /**
@@ -740,6 +710,28 @@
                 com.android.internal.R.dimen.config_letterboxVerticalPositionMultiplier);
     }
 
+    /**
+     * Sets tabletop mode position multiplier.
+     *
+     * @throws IllegalArgumentException If given value < 0 or > 1.
+     */
+    @VisibleForTesting
+    void setLetterboxTabletopModePositionMultiplier(float multiplier) {
+        mLetterboxTabletopModePositionMultiplier = assertValidMultiplier(multiplier,
+                "mLetterboxTabletopModePositionMultiplier");
+    }
+
+    /**
+     * Sets tabletop mode position multiplier.
+     *
+     * @throws IllegalArgumentException If given value < 0 or > 1.
+     */
+    @VisibleForTesting
+    void setLetterboxBookModePositionMultiplier(float multiplier) {
+        mLetterboxBookModePositionMultiplier = assertValidMultiplier(multiplier,
+                "mLetterboxBookModePositionMultiplier");
+    }
+
     /*
      * Whether horizontal reachability repositioning is allowed for letterboxed fullscreen apps in
      * landscape device orientation.
@@ -1356,4 +1348,21 @@
     void resetUserAppAspectRatioFullscreenEnabled() {
         setUserAppAspectRatioFullscreenOverrideEnabled(false);
     }
+
+    /**
+     * Checks whether the multiplier is between [0,1].
+     *
+     * @param multiplierName sent in the exception if multiplier is invalid, for easier debugging.
+     *
+     * @return multiplier, if valid
+     * @throws IllegalArgumentException if outside bounds.
+     */
+    private float assertValidMultiplier(float multiplier, String multiplierName)
+            throws IllegalArgumentException {
+        if (multiplier < 0.0f || multiplier > 1.0f) {
+            throw new IllegalArgumentException("Trying to set " + multiplierName
+                    + " out of bounds: " + multiplier);
+        }
+        return multiplier;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 3f24545..da1581e 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -905,13 +905,11 @@
     // Note that we check the task rather than the parent as with ActivityEmbedding the parent might
     // be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
     // actually fullscreen.
-    private boolean isDisplayFullScreenAndInPosture(DeviceStateController.DeviceState state,
-            boolean isTabletop) {
+    private boolean isDisplayFullScreenAndInPosture(boolean isTabletop) {
         Task task = mActivityRecord.getTask();
-        return mActivityRecord.mDisplayContent != null
-                && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(state,
-                    isTabletop)
-                && task != null
+        return mActivityRecord.mDisplayContent != null && task != null
+                && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(
+                        DeviceStateController.DeviceState.HALF_FOLDED, isTabletop)
                 && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
     }
 
@@ -939,16 +937,14 @@
     }
 
     private boolean isFullScreenAndBookModeEnabled() {
-        return isDisplayFullScreenAndInPosture(
-                DeviceStateController.DeviceState.HALF_FOLDED, false /* isTabletop */)
+        return isDisplayFullScreenAndInPosture(/* isTabletop */ false)
                 && mLetterboxConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
     }
 
     float getVerticalPositionMultiplier(Configuration parentConfiguration) {
         // Don't check resolved configuration because it may not be updated yet during
         // configuration change.
-        boolean tabletopMode = isDisplayFullScreenAndInPosture(
-                DeviceStateController.DeviceState.HALF_FOLDED, true /* isTabletop */);
+        boolean tabletopMode = isDisplayFullScreenAndInPosture(/* isTabletop */ true);
         return isVerticalReachabilityEnabled(parentConfiguration)
                 // Using the last global dynamic position to avoid "jumps" when moving
                 // between apps or activities.
@@ -981,16 +977,15 @@
     }
 
     private boolean shouldUseSplitScreenAspectRatio(@NonNull Configuration parentConfiguration) {
-        final boolean isBookMode = isDisplayFullScreenAndInPosture(
-                DeviceStateController.DeviceState.HALF_FOLDED,
-                /* isTabletop */ false);
+        final boolean isBookMode = isDisplayFullScreenAndInPosture(/* isTabletop */ false);
         final boolean isNotCenteredHorizontally = getHorizontalPositionMultiplier(
                 parentConfiguration) != LETTERBOX_POSITION_MULTIPLIER_CENTER;
-        final boolean isTabletopMode = isDisplayFullScreenAndInPosture(
-                DeviceStateController.DeviceState.HALF_FOLDED,
-                /* isTabletop */ true);
+        final boolean isTabletopMode = isDisplayFullScreenAndInPosture(/* isTabletop */ true);
+        final boolean isLandscape = isFixedOrientationLandscape(
+                mActivityRecord.getOverrideOrientation());
+
         // Don't resize to split screen size when in book mode if letterbox position is centered
-        return ((isBookMode && isNotCenteredHorizontally) || isTabletopMode)
+        return (isBookMode && isNotCenteredHorizontally || isTabletopMode && isLandscape)
                     || isCameraCompatSplitScreenAspectRatioAllowed()
                         && isCameraCompatTreatmentActive();
     }
@@ -1084,6 +1079,10 @@
                     || mUserAspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN);
     }
 
+    boolean hasFullscreenOverride() {
+        return isSystemOverrideToFullscreenEnabled() || shouldApplyUserFullscreenOverride();
+    }
+
     float getUserMinAspectRatio() {
         switch (mUserAspectRatio) {
             case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE:
@@ -1304,7 +1303,8 @@
         }
 
         final boolean shouldShowLetterboxUi =
-                (mActivityRecord.isInLetterboxAnimation() || isSurfaceVisible(mainWindow))
+                (mActivityRecord.isInLetterboxAnimation() || mActivityRecord.isVisible()
+                        || mActivityRecord.isVisibleRequested())
                 && mainWindow.areAppWindowBoundsLetterboxed()
                 // Check for FLAG_SHOW_WALLPAPER explicitly instead of using
                 // WindowContainer#showWallpaper because the later will return true when this
@@ -1316,12 +1316,6 @@
         return shouldShowLetterboxUi;
     }
 
-    @VisibleForTesting
-    boolean isSurfaceVisible(WindowState mainWindow) {
-        return mainWindow.isOnScreen() && (mActivityRecord.isVisible()
-                || mActivityRecord.isVisibleRequested());
-    }
-
     private Color getLetterboxBackgroundColor() {
         final WindowState w = mActivityRecord.findMainWindow();
         if (w == null || w.isLetterboxedForDisplayCutout()) {
@@ -1648,17 +1642,13 @@
         if (isHorizontalReachabilityEnabled()) {
             int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
                     .getLetterboxPositionForHorizontalReachability(
-                            isDisplayFullScreenAndInPosture(
-                                    DeviceStateController.DeviceState.HALF_FOLDED,
-                                    false /* isTabletop */));
+                            isDisplayFullScreenAndInPosture(/* isTabletop */ false));
             positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
                     letterboxPositionForHorizontalReachability);
         } else if (isVerticalReachabilityEnabled()) {
             int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
                     .getLetterboxPositionForVerticalReachability(
-                            isDisplayFullScreenAndInPosture(
-                                    DeviceStateController.DeviceState.HALF_FOLDED,
-                                    true /* isTabletop */));
+                            isDisplayFullScreenAndInPosture(/* isTabletop */ true));
             positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
                     letterboxPositionForVerticalReachability);
         }
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 79eb0dc..ce47f5c 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -26,3 +26,6 @@
 
 # File related to activity callers
 per-file ActivityCallerState.java = file:/core/java/android/app/COMPONENT_CALLER_OWNERS
+
+# Files related to tracing
+per-file *TransitionTracer.java = file:platform/development:/tools/winscope/OWNERS
diff --git a/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java b/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
index d08f043..883d27f 100644
--- a/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
+++ b/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
@@ -17,7 +17,8 @@
 package com.android.server.wm;
 
 import android.annotation.NonNull;
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellTransition;
+import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.tracing.perfetto.DataSourceParams;
@@ -71,18 +72,18 @@
         mDataSource.trace((ctx) -> {
             final ProtoOutputStream os = ctx.newTracePacket();
 
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
 
-            os.write(PerfettoTrace.ShellTransition.ID, transition.getSyncId());
-            os.write(PerfettoTrace.ShellTransition.CREATE_TIME_NS,
+            os.write(ShellTransition.ID, transition.getSyncId());
+            os.write(ShellTransition.CREATE_TIME_NS,
                     transition.mLogger.mCreateTimeNs);
-            os.write(PerfettoTrace.ShellTransition.SEND_TIME_NS, transition.mLogger.mSendTimeNs);
-            os.write(PerfettoTrace.ShellTransition.START_TRANSACTION_ID,
+            os.write(ShellTransition.SEND_TIME_NS, transition.mLogger.mSendTimeNs);
+            os.write(ShellTransition.START_TRANSACTION_ID,
                     transition.getStartTransaction().getId());
-            os.write(PerfettoTrace.ShellTransition.FINISH_TRANSACTION_ID,
+            os.write(ShellTransition.FINISH_TRANSACTION_ID,
                     transition.getFinishTransaction().getId());
-            os.write(PerfettoTrace.ShellTransition.TYPE, transition.mType);
-            os.write(PerfettoTrace.ShellTransition.FLAGS, transition.getFlags());
+            os.write(ShellTransition.TYPE, transition.mType);
+            os.write(ShellTransition.FLAGS, transition.getFlags());
 
             addTransitionTargetsToProto(os, targets);
 
@@ -114,9 +115,9 @@
         mDataSource.trace((ctx) -> {
             final ProtoOutputStream os = ctx.newTracePacket();
 
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, transition.getSyncId());
-            os.write(PerfettoTrace.ShellTransition.FINISH_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, transition.getSyncId());
+            os.write(ShellTransition.FINISH_TIME_NS,
                     transition.mLogger.mFinishTimeNs);
             os.end(token);
         });
@@ -146,9 +147,9 @@
         mDataSource.trace((ctx) -> {
             final ProtoOutputStream os = ctx.newTracePacket();
 
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, transition.getSyncId());
-            os.write(PerfettoTrace.ShellTransition.WM_ABORT_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, transition.getSyncId());
+            os.write(ShellTransition.WM_ABORT_TIME_NS,
                     transition.mLogger.mAbortTimeNs);
             os.end(token);
         });
@@ -172,9 +173,9 @@
         mDataSource.trace((ctx) -> {
             final ProtoOutputStream os = ctx.newTracePacket();
 
-            final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
-            os.write(PerfettoTrace.ShellTransition.ID, startingData.mTransitionId);
-            os.write(PerfettoTrace.ShellTransition.STARTING_WINDOW_REMOVE_TIME_NS,
+            final long token = os.start(TracePacket.SHELL_TRANSITION);
+            os.write(ShellTransition.ID, startingData.mTransitionId);
+            os.write(ShellTransition.STARTING_WINDOW_REMOVE_TIME_NS,
                     SystemClock.elapsedRealtimeNanos());
             os.end(token);
         });
@@ -215,11 +216,11 @@
             }
             final int windowId = System.identityHashCode(target.mContainer);
 
-            final long token = os.start(PerfettoTrace.ShellTransition.TARGETS);
-            os.write(PerfettoTrace.ShellTransition.Target.MODE, target.mReadyMode);
-            os.write(PerfettoTrace.ShellTransition.Target.FLAGS, target.mReadyFlags);
-            os.write(PerfettoTrace.ShellTransition.Target.LAYER_ID, layerId);
-            os.write(PerfettoTrace.ShellTransition.Target.WINDOW_ID, windowId);
+            final long token = os.start(ShellTransition.TARGETS);
+            os.write(ShellTransition.Target.MODE, target.mReadyMode);
+            os.write(ShellTransition.Target.FLAGS, target.mReadyFlags);
+            os.write(ShellTransition.Target.LAYER_ID, layerId);
+            os.write(ShellTransition.Target.WINDOW_ID, windowId);
             os.end(token);
         }
     }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 7a3124d..469cc64 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -112,11 +112,11 @@
                 mTargetActivityType);
         ActivityRecord targetActivity = getTargetActivity(targetRootTask);
         if (targetActivity != null) {
-            if (targetActivity.isVisibleRequested() || targetActivity.isTopRunningActivity()) {
-                // The activity is ready.
-                return;
-            }
             if (targetActivity.attachedToProcess()) {
+                if (targetActivity.isVisibleRequested() || targetActivity.isTopRunningActivity()) {
+                    // The activity is ready.
+                    return;
+                }
                 if (targetActivity.app.getCurrentProcState() >= PROCESS_STATE_CACHED_ACTIVITY) {
                     Slog.v(TAG, "Skip preload recents for cached proc " + targetActivity.app);
                     // The process may be frozen that cannot receive binder call.
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 3ef6eeb..63bbb31 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -44,6 +44,7 @@
 import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.LogLevel;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.FastPrintWriter;
 import com.android.server.wm.SurfaceAnimator.AnimationType;
@@ -209,7 +210,7 @@
                 Slog.e(TAG, "Failed to start remote animation", e);
                 onAnimationFinished();
             }
-            if (ProtoLog.isEnabled(WM_DEBUG_REMOTE_ANIMATIONS)) {
+            if (ProtoLog.isEnabled(WM_DEBUG_REMOTE_ANIMATIONS, LogLevel.DEBUG)) {
                 ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation(): Notify animation start:");
                 writeStartDebugStatement();
             }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 9dba8c6..622a809 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -72,7 +72,6 @@
 import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
 import static com.android.server.wm.Task.REPARENT_LEAVE_ROOT_TASK_IN_PLACE;
 import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
-import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_INVISIBLE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -175,6 +174,7 @@
     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
     private static final int MSG_SEND_SLEEP_TRANSITION = 3;
+    private static final int PINNED_TASK_ABORT_TIMEOUT = 1000;
 
     static final String TAG_TASKS = TAG + POSTFIX_TASKS;
     static final String TAG_STATES = TAG + POSTFIX_STATES;
@@ -270,8 +270,6 @@
     private int mTmpTaskLayerRank;
     private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable();
 
-    private final AttachApplicationHelper mAttachApplicationHelper = new AttachApplicationHelper();
-
     private String mDestroyAllActivitiesReason;
     private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
         @Override
@@ -298,6 +296,9 @@
 
     };
 
+    // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on.
+    @Nullable private Runnable mMaybeAbortPipEnterRunnable = null;
+
     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
 
     static class FindTaskResult implements Predicate<Task> {
@@ -1838,11 +1839,39 @@
     }
 
     boolean attachApplication(WindowProcessController app) throws RemoteException {
-        try {
-            return mAttachApplicationHelper.process(app);
-        } finally {
-            mAttachApplicationHelper.reset();
+        final ArrayList<ActivityRecord> activities = mService.mStartingProcessActivities;
+        RemoteException remoteException = null;
+        boolean hasActivityStarted = false;
+        for (int i = activities.size() - 1; i >= 0; i--) {
+            final ActivityRecord r = activities.get(i);
+            if (app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
+                // The attaching process does not match the starting activity.
+                continue;
+            }
+            // Consume the pending record.
+            activities.remove(i);
+            final TaskFragment tf = r.getTaskFragment();
+            if (tf == null || r.finishing || r.app != null
+                    // Ignore keyguard because the app may use show-when-locked when creating.
+                    || !r.shouldBeVisible(true /* ignoringKeyguard */)
+                    || !r.showToCurrentUser()) {
+                continue;
+            }
+            try {
+                final boolean canResume = r.isFocusable() && r == tf.topRunningActivity();
+                if (mTaskSupervisor.realStartActivityLocked(r, app, canResume,
+                        true /* checkConfig */)) {
+                    hasActivityStarted = true;
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Exception in new process when starting " + r, e);
+                remoteException = e;
+            }
         }
+        if (remoteException != null) {
+            throw remoteException;
+        }
+        return hasActivityStarted;
     }
 
     /**
@@ -2244,13 +2273,70 @@
             newTransition.setReady(rootTask, true /* ready */);
         }
 
-        if (!isPip2ExperimentEnabled()) {
-            resumeFocusedTasksTopActivities();
-        }
+        resumeFocusedTasksTopActivities();
 
         notifyActivityPipModeChanged(r.getTask(), r);
+
+        if (!isPip2ExperimentEnabled()) {
+            // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on.
+            // Set up a timeout callback to potentially abort PiP enter if in an inconsistent state.
+            scheduleTimeoutAbortPipEnter(rootTask);
+        }
     }
 
+    private void scheduleTimeoutAbortPipEnter(Task rootTask) {
+        if (mMaybeAbortPipEnterRunnable != null) {
+            // If there is an abort enter PiP check pending already remove it and abort
+            // immediately since we are trying to enter PiP in an inconsistent state
+            mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable);
+            mMaybeAbortPipEnterRunnable.run();
+        }
+        // Snapshot a throwable early on to display the callstack upon abort later on timeout.
+        final Throwable enterPipThrowable = new Throwable();
+        // Set up a timeout to potentially roll back the task change to PINNED mode
+        // by aborting PiP.
+        mMaybeAbortPipEnterRunnable = new Runnable() {
+            @Override
+            public void run() {
+                synchronized (mService.mGlobalLock) {
+                    if (mTransitionController.inTransition()) {
+                        // If this task is a part an active transition aborting PiP might break
+                        // it; so run the timeout callback directly once idle.
+
+                        final Runnable expectedMaybeAbortAtTimeout = mMaybeAbortPipEnterRunnable;
+                        mTransitionController.mStateValidators.add(() -> {
+                            // If a second PiP transition comes in, it runs the abort runnable for
+                            // the first transition pre-emptively, so we need to avoid calling
+                            // the same runnable twice when validating states.
+                            if (expectedMaybeAbortAtTimeout != mMaybeAbortPipEnterRunnable) return;
+                            mMaybeAbortPipEnterRunnable = null;
+                            run();
+                        });
+                        return;
+                    } else {
+                        mMaybeAbortPipEnterRunnable = null;
+                    }
+                    mService.deferWindowLayout();
+                    final ActivityRecord top = rootTask.getTopMostActivity();
+                    final ActivityManager.RunningTaskInfo beforeTaskInfo =
+                            rootTask.getTaskInfo();
+                    if (top != null && !top.inPinnedWindowingMode()
+                            && rootTask.abortPipEnter(top)) {
+                        Slog.wtf(TAG, "Enter PiP was aborted via a scheduled timeout"
+                                        + "task_state_before=" + beforeTaskInfo
+                                        + "task_state_after=" + rootTask.getTaskInfo(),
+                                enterPipThrowable);
+                    }
+                    mService.continueWindowLayout();
+                }
+            }
+        };
+        mHandler.postDelayed(mMaybeAbortPipEnterRunnable, PINNED_TASK_ABORT_TIMEOUT);
+        Slog.d(TAG, "a delayed check for potentially aborting PiP if "
+                + "in a wrong state is scheduled.");
+    }
+
+
     /**
      * Notifies when an activity enters or leaves PIP mode.
      *
@@ -2869,6 +2955,14 @@
         mService.mH.post(mDestroyAllActivitiesRunnable);
     }
 
+    void removeAllMaybeAbortPipEnterRunnable() {
+        if (mMaybeAbortPipEnterRunnable == null) {
+            return;
+        }
+        mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable);
+        mMaybeAbortPipEnterRunnable = null;
+    }
+
     // Tries to put all activity tasks to sleep. Returns true if all tasks were
     // successfully put to sleep.
     boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) {
@@ -3742,67 +3836,4 @@
             }
         }
     }
-
-    private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
-        private boolean mHasActivityStarted;
-        private RemoteException mRemoteException;
-        private WindowProcessController mApp;
-        private ActivityRecord mTop;
-
-        void reset() {
-            mHasActivityStarted = false;
-            mRemoteException = null;
-            mApp = null;
-            mTop = null;
-        }
-
-        boolean process(WindowProcessController app) throws RemoteException {
-            mApp = app;
-            for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
-                getChildAt(displayNdx).forAllRootTasks(this);
-                if (mRemoteException != null) {
-                    throw mRemoteException;
-                }
-            }
-            if (!mHasActivityStarted) {
-                ensureActivitiesVisible();
-            }
-            return mHasActivityStarted;
-        }
-
-        @Override
-        public void accept(Task rootTask) {
-            if (mRemoteException != null) {
-                return;
-            }
-            if (rootTask.getVisibility(null /* starting */)
-                    == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
-                return;
-            }
-            mTop = rootTask.topRunningActivity();
-            rootTask.forAllActivities(this);
-        }
-
-        @Override
-        public boolean test(ActivityRecord r) {
-            if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
-                    || r.app != null || mApp.mUid != r.info.applicationInfo.uid
-                    || !mApp.mName.equals(r.processName)) {
-                return false;
-            }
-
-            try {
-                if (mTaskSupervisor.realStartActivityLocked(r, mApp,
-                        mTop == r && r.getTask().canBeResumed(r) /* andResume */,
-                        true /* checkConfig */)) {
-                    mHasActivityStarted = true;
-                }
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
-                mRemoteException = e;
-                return true;
-            }
-            return false;
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index e157318..f8aa69b 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -912,7 +912,7 @@
     @Override
     public void grantInputChannel(int displayId, SurfaceControl surface,
             IBinder clientToken, @Nullable InputTransferToken hostInputTransferToken, int flags,
-            int privateFlags, int type, int inputFeatures, IBinder windowToken,
+            int privateFlags, int inputFeatures, int type, IBinder windowToken,
             InputTransferToken inputTransferToken, String inputHandleName,
             InputChannel outInputChannel) {
         if (hostInputTransferToken == null && !mCanAddInternalSystemWindow) {
@@ -925,7 +925,7 @@
         try {
             mService.grantInputChannel(this, mUid, mPid, displayId, surface, clientToken,
                     hostInputTransferToken, flags, mCanAddInternalSystemWindow ? privateFlags : 0,
-                    type, inputFeatures, windowToken, inputTransferToken, inputHandleName,
+                    inputFeatures, type, windowToken, inputTransferToken, inputHandleName,
                     outInputChannel);
         } finally {
             Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index d67684c..c632714 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -32,6 +32,7 @@
 import android.view.SurfaceControl.Transaction;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.LogLevel;
 import com.android.internal.protolog.common.ProtoLog;
 
 import java.io.PrintWriter;
@@ -192,7 +193,7 @@
             return;
         }
         mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
-        if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) {
+        if (ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.DEBUG)) {
             StringWriter sw = new StringWriter();
             PrintWriter pw = new PrintWriter(sw);
             mAnimation.dump(pw, "");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d79d113..f23a440 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -137,6 +137,7 @@
 import android.app.ActivityTaskManager;
 import android.app.AppCompatTaskInfo;
 import android.app.AppGlobals;
+import android.app.CameraCompatTaskInfo;
 import android.app.IActivityController;
 import android.app.PictureInPictureParams;
 import android.app.TaskInfo;
@@ -3537,9 +3538,9 @@
         appCompatTaskInfo.topActivityEligibleForLetterboxEducation = isTopActivityResumed
                 && top.isEligibleForLetterboxEducation();
         // Whether the direct top activity requested showing camera compat control.
-        appCompatTaskInfo.cameraCompatControlState = isTopActivityResumed
+        appCompatTaskInfo.cameraCompatTaskInfo.cameraCompatControlState = isTopActivityResumed
                 ? top.getCameraCompatControlState()
-                : AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+                : CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
 
         final Task parentTask = getParent() != null ? getParent().asTask() : null;
         info.parentTaskId = parentTask != null && parentTask.mCreatedByOrganizer
@@ -4748,14 +4749,6 @@
             // transferring the transform on the leash to the task, reset this state once we're
             // moving out of pip
             setCanAffectSystemUiFlags(true);
-            // Turn on userLeaveHint so other app can enter PiP mode.
-            mTaskSupervisor.mUserLeaving = true;
-            // Allow entering PiP from current top most activity when we are leaving PiP.
-            final Task topFocused = mRootWindowContainer.getTopDisplayFocusedRootTask();
-            if (topFocused != null) {
-                final ActivityRecord ar = topFocused.getTopResumedActivity();
-                enableEnterPipOnTaskSwitch(ar, null /* toFrontTask */, ar, null /* opts */);
-            }
             mRootWindowContainer.notifyActivityPipModeChanged(this, null);
         }
         if (likelyResolvedMode == WINDOWING_MODE_PINNED) {
@@ -4813,6 +4806,14 @@
                                 topActivity.getSyncTransaction());
                     }
                     lastParentBeforePip.moveToFront("movePinnedActivityToOriginalTask");
+                    // If the reparent is not included in transition, make sure the visibility of
+                    // task is still updated by core. Otherwise if the task is collected (e.g.
+                    // rotation change) after leaving this scope, the visibility operation will be
+                    // put in sync transaction, then it is not synced with reparent.
+                    if (com.android.window.flags.Flags.removePrepareSurfaceInPlacement()
+                            && lastParentBeforePip.mSyncState == SYNC_STATE_NONE) {
+                        lastParentBeforePip.prepareSurfaces();
+                    }
                 }
                 if (isPip2ExperimentEnabled) {
                     super.setWindowingMode(windowingMode);
@@ -4851,11 +4852,13 @@
     /**
      * Abort an incomplete pip-entry. If left in this state, it will cover everything but remain
      * paused. If this is needed, there is a bug -- this should only be used for recovery.
+     *
+     * @return true if there is an inconsistency in the task and activity state.
      */
-    void abortPipEnter(ActivityRecord top) {
+    boolean abortPipEnter(ActivityRecord top) {
         // an incomplete state has the task PINNED but the activity not.
         if (!inPinnedWindowingMode() || top.inPinnedWindowingMode() || !canMoveTaskToBack(this)) {
-            return;
+            return false;
         }
         final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
                 mTransitionController, mWmService.mSyncEngine);
@@ -4877,6 +4880,7 @@
             top.setWindowingMode(WINDOWING_MODE_UNDEFINED);
             top.mWaitForEnteringPinnedMode = false;
         }
+        return true;
     }
 
     void resumeNextFocusAfterReparent() {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 90a3b25..2c27b98 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1880,7 +1880,6 @@
         mTempConfiguration.setTo(getRequestedOverrideConfiguration());
         WindowConfiguration tempRequestWindowConfiguration = mTempConfiguration.windowConfiguration;
         tempRequestWindowConfiguration.setWindowingMode(windowingMode);
-        tempRequestWindowConfiguration.setDisplayWindowingMode(windowingMode);
         onRequestedOverrideConfigurationChanged(mTempConfiguration);
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index bd1503f..2b631f7 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -906,8 +906,12 @@
         return mForceTranslucent;
     }
 
-    void setForceTranslucent(boolean set) {
+    boolean setForceTranslucent(boolean set) {
+        if (mForceTranslucent == set) {
+            return false;
+        }
         mForceTranslucent = set;
+        return true;
     }
 
     boolean isLeafTaskFragment() {
@@ -1967,6 +1971,15 @@
         return SCREEN_ORIENTATION_UNSET;
     }
 
+    @ActivityInfo.ScreenOrientation
+    @Override
+    protected int getOverrideOrientation() {
+        if (isEmbedded() && !isVisibleRequested()) {
+            return SCREEN_ORIENTATION_UNSPECIFIED;
+        }
+        return super.getOverrideOrientation();
+    }
+
     /**
      * Whether or not to allow this container to specify an app requested orientation.
      *
@@ -2188,38 +2201,20 @@
         return getTask() != null ? getTask().mTaskId : INVALID_TASK_ID;
     }
 
+    static class ConfigOverrideHint {
+        @Nullable DisplayInfo mTmpOverrideDisplayInfo;
+        @Nullable ActivityRecord.CompatDisplayInsets mTmpCompatInsets;
+        boolean mUseOverrideInsetsForStableBounds;
+    }
+
     void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
             @NonNull Configuration parentConfig) {
-        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
-                null /* compatInsets */);
-    }
-
-    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
-            @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
-        if (overrideDisplayInfo != null) {
-            // Make sure the screen related configs can be computed by the provided display info.
-            inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
-            invalidateAppBoundsConfig(inOutConfig);
-        }
-        computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
-                null /* compatInsets */);
-    }
-
-    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
-            @NonNull Configuration parentConfig,
-            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
-        if (compatInsets != null) {
-            // Make sure the app bounds can be computed by the compat insets.
-            invalidateAppBoundsConfig(inOutConfig);
-        }
-        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
-                compatInsets);
+        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* configOverrideHint */);
     }
 
     /**
      * Forces the app bounds related configuration can be computed by
-     * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
-     * ActivityRecord.CompatDisplayInsets)}.
+     * {@link #computeConfigResourceOverrides(Configuration, Configuration, ConfigOverrideHint)}.
      */
     private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
         final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
@@ -2239,8 +2234,24 @@
      * just be inherited from the parent configuration.
      **/
     void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
-            @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
-            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
+            @NonNull Configuration parentConfig, @Nullable ConfigOverrideHint overrideHint) {
+        DisplayInfo overrideDisplayInfo = null;
+        ActivityRecord.CompatDisplayInsets compatInsets = null;
+        boolean useOverrideInsetsForStableBounds = false;
+        if (overrideHint != null) {
+            overrideDisplayInfo = overrideHint.mTmpOverrideDisplayInfo;
+            compatInsets = overrideHint.mTmpCompatInsets;
+            useOverrideInsetsForStableBounds = overrideHint.mUseOverrideInsetsForStableBounds;
+            if (overrideDisplayInfo != null) {
+                // Make sure the screen related configs can be computed by the provided
+                // display info.
+                inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
+            }
+            if (overrideDisplayInfo != null || compatInsets != null) {
+                // Make sure the app bounds can be computed by the compat insets.
+                invalidateAppBoundsConfig(inOutConfig);
+            }
+        }
         int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
             windowingMode = parentConfig.windowConfiguration.getWindowingMode();
@@ -2310,7 +2321,7 @@
                 // The non decor inset are areas that could never be removed in Honeycomb. See
                 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
                 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di,
-                        false /* useLegacyInsetsForStableBounds */);
+                        useOverrideInsetsForStableBounds);
             } else {
                 // Apply the given non-decor and stable insets to calculate the corresponding bounds
                 // for screen size of configuration.
@@ -2423,11 +2434,12 @@
         final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
         final DisplayPolicy.DecorInsets.Info info = policy.getDecorInsetsInfo(
                 displayInfo.rotation, displayInfo.logicalWidth, displayInfo.logicalHeight);
-        intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mNonDecorInsets);
         if (!useLegacyInsetsForStableBounds) {
             intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mConfigInsets);
+            intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mNonDecorInsets);
         } else {
-            intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mLegacyConfigInsets);
+            intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mOverrideConfigInsets);
+            intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mOverrideNonDecorInsets);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 74dad91..b24d53b 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -17,7 +17,7 @@
 package com.android.server.wm;
 
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.AppCompatTaskInfo.cameraCompatControlStateToString;
+import static android.app.CameraCompatTaskInfo.cameraCompatControlStateToString;
 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NONE;
 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NORMAL;
 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_ROTATION;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 1b380aa..1543263 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -112,7 +112,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
-import java.util.concurrent.Executor;
 import java.util.function.Predicate;
 
 /**
@@ -1430,20 +1429,17 @@
                 }
             }
             if (mTransientLaunches != null) {
-                InsetsControlTarget prevImeTarget = dc.getImeTarget(
-                        DisplayContent.IME_TARGET_CONTROL);
-                InsetsControlTarget newImeTarget = null;
                 TaskDisplayArea transientTDA = null;
-                // Transient-launch activities cannot be IME target (WindowState#canBeImeTarget),
-                // so re-compute in case the IME target is changed after transition.
                 for (int t = 0; t < mTransientLaunches.size(); ++t) {
                     if (mTransientLaunches.keyAt(t).getDisplayContent() == dc) {
-                        newImeTarget = dc.computeImeTarget(true /* updateImeTarget */);
+                        if (hasVisibleTransientLaunch) {
+                            updateImeForVisibleTransientLaunch(dc);
+                        }
                         transientTDA = mTransientLaunches.keyAt(i).getTaskDisplayArea();
                         break;
                     }
                 }
-                if (mRecentsDisplayId != INVALID_DISPLAY && prevImeTarget == newImeTarget) {
+                if (!hasVisibleTransientLaunch && mRecentsDisplayId == dc.mDisplayId) {
                     // Restore IME icon only when moving the original app task to front from
                     // recents, in case IME icon may missing if the moving task has already been
                     // the current focused task.
@@ -1541,6 +1537,35 @@
         return null;
     }
 
+    /**
+     * Transient-launch activities cannot be IME target (see {@link WindowState#canBeImeTarget}),
+     * so re-compute in case the IME target is changed after transition.
+     */
+    private void updateImeForVisibleTransientLaunch(@NonNull DisplayContent dc) {
+        final WindowState imeTarget = dc.computeImeTarget(true /* updateImeTarget */);
+        final WindowState imeWindow = dc.mInputMethodWindow;
+        if (imeWindow == null || imeTarget == null
+                || !mController.hasCollectingRotationChange(dc, dc.getRotation())) {
+            return;
+        }
+        // Drop the insets leash if it is still controlled by previous (invisible) app. This avoids
+        // showing IME with old rotation on an app with new rotation if IME parent is updated
+        // but insets leash hasn't been refreshed, i.e. DisplayContent#updateImeParent is called
+        // but InsetsStateController#notifyControlTargetChanged still waits for IME to redraw.
+        final InsetsSourceProvider sourceProvider = imeWindow.getControllableInsetProvider();
+        if (sourceProvider == null || sourceProvider.mControl == null
+                || !sourceProvider.isClientVisible()
+                || imeTarget == sourceProvider.getControlTarget()) {
+            return;
+        }
+        final SurfaceControl imeInsetsLeash = sourceProvider.mControl.getLeash();
+        final InsetsControlTarget controlTarget = sourceProvider.getControlTarget();
+        if (imeInsetsLeash != null && controlTarget != null && controlTarget.getWindow() != null
+                && !controlTarget.getWindow().mToken.isVisible()) {
+            dc.getSyncTransaction().reparent(imeInsetsLeash, null);
+        }
+    }
+
     void abort() {
         // This calls back into itself via controller.abort, so just early return here.
         if (mState == STATE_ABORT) return;
@@ -3254,9 +3279,15 @@
                     // Whether this is in a Task with embedded activity.
                     flags |= FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
                 }
-                if (parentTask.forAllActivities(ActivityRecord::hasStartingWindow)) {
-                    // The starting window should cover all windows inside the leaf Task.
-                    flags |= FLAG_IS_BEHIND_STARTING_WINDOW;
+                final ActivityRecord starting = parentTask.topActivityContainsStartingWindow();
+                if (starting != null) {
+                    if (starting == record || (starting.mStartingData != null
+                            && starting.mStartingData.mAssociatedTask != null)) {
+                        flags |= FLAG_IS_BEHIND_STARTING_WINDOW;
+                    } else if (record != null && parentTask.mChildren.indexOf(record)
+                            < parentTask.mChildren.indexOf(starting)) {
+                        flags |= FLAG_IS_BEHIND_STARTING_WINDOW;
+                    }
                 }
                 if (isWindowFillingTask(wc, parentTask)) {
                     // Whether the container fills its parent Task bounds.
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 222abc3..ce53290 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -565,6 +565,9 @@
         if (isTransientCollect(ar)) {
             return true;
         }
+        for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) {
+            if (mWaitingTransitions.get(i).isTransientLaunch(ar)) return true;
+        }
         for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
             if (mPlayingTransitions.get(i).isTransientLaunch(ar)) return true;
         }
diff --git a/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java b/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java
index f376e8b..0655068 100644
--- a/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java
+++ b/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java
@@ -32,8 +32,8 @@
 class UnsupportedCompileSdkDialog extends AppWarnings.BaseDialog {
 
     UnsupportedCompileSdkDialog(final AppWarnings manager, Context context,
-            ApplicationInfo appInfo) {
-        super(manager, appInfo.packageName);
+            ApplicationInfo appInfo, int userId) {
+        super(manager, context, appInfo.packageName, userId);
 
         final PackageManager pm = context.getPackageManager();
         final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -68,6 +68,6 @@
         final CheckBox alwaysShow = mDialog.findViewById(R.id.ask_checkbox);
         alwaysShow.setChecked(true);
         alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> manager.setPackageFlag(
-                mPackageName, AppWarnings.FLAG_HIDE_COMPILE_SDK, !isChecked));
+                mUserId, mPackageName, AppWarnings.FLAG_HIDE_COMPILE_SDK, !isChecked));
     }
 }
diff --git a/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java b/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java
index b11c22d..5e40d9c 100644
--- a/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java
+++ b/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java
@@ -30,8 +30,8 @@
 class UnsupportedDisplaySizeDialog extends AppWarnings.BaseDialog {
 
     UnsupportedDisplaySizeDialog(final AppWarnings manager, Context context,
-            ApplicationInfo appInfo) {
-        super(manager, appInfo.packageName);
+            ApplicationInfo appInfo, int userId) {
+        super(manager, context, appInfo.packageName, userId);
 
         final PackageManager pm = context.getPackageManager();
         final CharSequence label = appInfo.loadSafeLabel(pm,
@@ -59,6 +59,6 @@
         final CheckBox alwaysShow = mDialog.findViewById(R.id.ask_checkbox);
         alwaysShow.setChecked(true);
         alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> manager.setPackageFlag(
-                mPackageName, AppWarnings.FLAG_HIDE_DISPLAY_SIZE, !isChecked));
+                mUserId, mPackageName, AppWarnings.FLAG_HIDE_DISPLAY_SIZE, !isChecked));
     }
 }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index a2f6fb4..65e1761 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -22,7 +22,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER;
@@ -857,19 +856,12 @@
         result.setWallpaperTarget(wallpaperTarget);
     }
 
-    public void updateWallpaperTokens(boolean keyguardLocked) {
-        if (DEBUG_WALLPAPER) {
-            Slog.v(TAG, "Wallpaper vis: target " + mWallpaperTarget + " prev="
-                    + mPrevWallpaperTarget);
-        }
-        updateWallpaperTokens(mWallpaperTarget != null || mPrevWallpaperTarget != null,
-                keyguardLocked);
-    }
-
     /**
      * Change the visibility of the top wallpaper to {@param visibility} and hide all the others.
      */
     private void updateWallpaperTokens(boolean visibility, boolean keyguardLocked) {
+        ProtoLog.v(WM_DEBUG_WALLPAPER, "updateWallpaperTokens requestedVisibility=%b on"
+                + " keyguardLocked=%b", visibility, keyguardLocked);
         WindowState topWallpaper = mFindResults.getTopWallpaper(keyguardLocked);
         WallpaperWindowToken topWallpaperToken =
                 topWallpaper == null ? null : topWallpaper.mToken.asWallpaperToken();
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 55eeaf2..9d1551c 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -193,11 +193,11 @@
         if (mVisibleRequested != visible) {
             // Before setting mVisibleRequested so we can track changes.
             final WindowState wpTarget = mDisplayContent.mWallpaperController.getWallpaperTarget();
-            final boolean isTargetNotCollectedActivity = wpTarget != null
-                    && wpTarget.mActivityRecord != null
-                    && !mTransitionController.isCollecting(wpTarget.mActivityRecord);
-            // Skip collecting requesting-invisible wallpaper if the wallpaper target is an activity
-            // and it is not collected. Because the visibility change may be called after the
+            final boolean isTargetNotCollectedActivity = wpTarget == null
+                    || (wpTarget.mActivityRecord != null
+                            && !mTransitionController.isCollecting(wpTarget.mActivityRecord));
+            // Skip collecting requesting-invisible wallpaper if the wallpaper target is empty or
+            // a non-collected activity. Because the visibility change may be called after the
             // transition of activity is finished, e.g. WallpaperController#hideWallpapers from
             // hiding surface of the target. Then if there is a next transition, the wallpaper
             // change may be collected into the unrelated transition and cause a weird animation.
@@ -274,6 +274,12 @@
     }
 
     @Override
+    boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
+        // TODO(b/233286785): Support sync state for wallpaper. See WindowState#prepareSync.
+        return !mVisibleRequested || !hasVisibleNotDrawnWallpaper();
+    }
+
+    @Override
     public String toString() {
         if (stringName == null) {
             StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index b43a454..8afcf0e 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -150,7 +150,9 @@
                     dc.checkAppWindowsReadyToShow();
                 }
                 if (accessibilityController.hasCallbacks()) {
-                    accessibilityController.drawMagnifiedRegionBorderIfNeeded(dc.mDisplayId);
+                    accessibilityController
+                            .recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded(
+                                    dc.mDisplayId);
                 }
 
                 if (dc.isAnimating(animationFlags, ANIMATION_TYPE_ALL)) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 80889d1a..90ac576 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -113,6 +113,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
+import com.android.internal.protolog.common.LogLevel;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.server.wm.SurfaceAnimator.Animatable;
@@ -3405,7 +3406,7 @@
                 // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
                 a.restrictDuration(MAX_APP_TRANSITION_DURATION);
             }
-            if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) {
+            if (ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.DEBUG)) {
                 ProtoLog.i(WM_DEBUG_ANIM, "Loaded animation %s for %s, duration: %d, stack=%s",
                         a, this, ((a != null) ? a.getDuration() : 0), Debug.getCallers(20));
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 7e2ffd4..eeedec3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -50,6 +50,7 @@
 import android.view.WindowManager.DisplayImePolicy;
 import android.view.inputmethod.ImeTracker;
 import android.window.ScreenCapture;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
 
 import com.android.internal.policy.KeyInterceptionInfo;
 import com.android.server.input.InputManagerService;
@@ -1043,6 +1044,13 @@
             int[] fromOrientations, int[] toOrientations);
 
     /**
+     * Set current screen capture session id that will be used during sensitive content protections.
+     *
+     * @param sessionId Session id for this screen capture protection
+     */
+    public abstract void setBlockScreenCaptureForAppsSessionId(long sessionId);
+
+    /**
      * Set whether screen capture should be disabled for all windows of a specific app windows based
      * on sensitive content protections.
      *
@@ -1073,8 +1081,9 @@
     public abstract boolean moveFocusToAdjacentEmbeddedActivityIfNeeded();
 
     /**
-     * Returns an instance of {@link ScreenCapture.ScreenshotHardwareBuffer} containing the current
+     * Returns an instance of {@link ScreenshotHardwareBuffer} containing the current
      * screenshot.
      */
-    public abstract ScreenCapture.ScreenshotHardwareBuffer takeAssistScreenshot();
+    public abstract ScreenshotHardwareBuffer takeAssistScreenshot(
+            Set<Integer> windowTypesToExclude);
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2e72121..de7c0eb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -44,6 +44,7 @@
 import static android.os.Process.myUid;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.permission.flags.Flags.sensitiveContentImprovements;
+import static android.permission.flags.Flags.sensitiveContentMetricsBugfix;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
@@ -113,6 +114,7 @@
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
 import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_NOTIFICATION_APP_PROTECTION_APPLIED;
 import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
 import static com.android.server.LockGuard.INDEX_WINDOW;
 import static com.android.server.LockGuard.installLock;
@@ -241,6 +243,7 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
+import android.util.IntArray;
 import android.util.MergedConfiguration;
 import android.util.Pair;
 import android.util.Slog;
@@ -319,6 +322,7 @@
 import android.window.ITrustedPresentationListener;
 import android.window.InputTransferToken;
 import android.window.ScreenCapture;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
 import android.window.SystemPerformanceHinter;
 import android.window.TaskSnapshot;
 import android.window.TrustedPresentationThresholds;
@@ -338,6 +342,7 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.view.WindowManagerPolicyThread;
 import com.android.server.AnimationThread;
@@ -383,6 +388,7 @@
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
@@ -567,7 +573,9 @@
     /** Device default insets types shall be excluded from config app sizes. */
     final int mConfigTypes;
 
-    final int mLegacyConfigTypes;
+    final int mOverrideConfigTypes;
+
+    final int mOverrideDecorTypes;
 
     final boolean mLimitedAlphaCompositing;
     final int mMaxUiWidth;
@@ -1105,7 +1113,18 @@
     SystemPerformanceHinter mSystemPerformanceHinter;
 
     @GuardedBy("mGlobalLock")
+    private long mSensitiveContentProtectionSessionId = 0;
+
+    @GuardedBy("mGlobalLock")
     final SensitiveContentPackages mSensitiveContentPackages = new SensitiveContentPackages();
+    /**
+     * UIDs for which a Toast has been shown to indicate
+     * {@link LocalService#addBlockScreenCaptureForApps(ArraySet) screen capture blocking}. This is
+     * used to ensure we don't keep re-showing the Toast every time the window becomes visible.
+     * UIDs are removed when the app is removed from the block list.
+     */
+    @GuardedBy("mGlobalLock")
+    private final IntArray mCaptureBlockedToastShownUids = new IntArray();
 
     /** Listener to notify activity manager about app transitions. */
     final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
@@ -1238,19 +1257,20 @@
         if (mFlags.mInsetsDecoupledConfiguration) {
             mDecorTypes = 0;
             mConfigTypes = 0;
-        } else if (isScreenSizeDecoupledFromStatusBarAndCutout) {
-            mDecorTypes = WindowInsets.Type.navigationBars();
-            mConfigTypes = WindowInsets.Type.navigationBars();
         } else {
             mDecorTypes = WindowInsets.Type.displayCutout() | WindowInsets.Type.navigationBars();
             mConfigTypes = WindowInsets.Type.displayCutout() | WindowInsets.Type.statusBars()
                     | WindowInsets.Type.navigationBars();
         }
-        if (isScreenSizeDecoupledFromStatusBarAndCutout) {
-            // Do not fallback to legacy value for enabled devices.
-            mLegacyConfigTypes = WindowInsets.Type.navigationBars();
+        if (isScreenSizeDecoupledFromStatusBarAndCutout && !mFlags.mInsetsDecoupledConfiguration) {
+            // If the global new behavior is not there, but the partial decouple flag is on.
+            mOverrideConfigTypes = 0;
+            mOverrideDecorTypes = 0;
         } else {
-            mLegacyConfigTypes = WindowInsets.Type.displayCutout() | WindowInsets.Type.statusBars()
+            mOverrideConfigTypes =
+                    WindowInsets.Type.displayCutout() | WindowInsets.Type.statusBars()
+                            | WindowInsets.Type.navigationBars();
+            mOverrideDecorTypes = WindowInsets.Type.displayCutout()
                     | WindowInsets.Type.navigationBars();
         }
 
@@ -2439,6 +2459,9 @@
             ProtoLog.i(WM_DEBUG_SCREEN_ON,
                     "Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,
                             viewVisibility, new RuntimeException().fillInStackTrace());
+            if (becameVisible) {
+                onWindowVisible(win);
+            }
 
             win.setDisplayLayoutNeeded();
             win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
@@ -3685,12 +3708,6 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public void switchKeyboardLayout(int deviceId, int direction) {
-        mInputManager.switchKeyboardLayout(deviceId, direction);
-    }
-
-    // Called by window manager policy.  Not exposed externally.
-    @Override
     public void shutdown(boolean confirm) {
         // Pass in the UI context, since ShutdownThread requires it (to show UI).
         ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
@@ -4163,7 +4180,7 @@
     }
 
     @Nullable
-    private ScreenCapture.ScreenshotHardwareBuffer takeAssistScreenshot() {
+    private ScreenshotHardwareBuffer takeAssistScreenshot(Set<Integer> windowTypesToExclude) {
         if (!checkCallingPermission(READ_FRAME_BUFFER, "requestAssistScreenshot()")) {
             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
         }
@@ -4178,11 +4195,11 @@
                 }
                 captureArgs = null;
             } else {
-                captureArgs = displayContent.getLayerCaptureArgs();
+                captureArgs = displayContent.getLayerCaptureArgs(windowTypesToExclude);
             }
         }
 
-        final ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer;
+        final ScreenshotHardwareBuffer screenshotBuffer;
         if (captureArgs != null) {
             ScreenCapture.SynchronousScreenCaptureListener syncScreenCapture =
                     ScreenCapture.createSyncCaptureListener();
@@ -4208,7 +4225,8 @@
      */
     @Override
     public boolean requestAssistScreenshot(final IAssistDataReceiver receiver) {
-        final ScreenCapture.ScreenshotHardwareBuffer shb = takeAssistScreenshot();
+        final ScreenshotHardwareBuffer shb =
+                takeAssistScreenshot(/* windowTypesToExclude= */ Set.of());
         final Bitmap bm = shb != null ? shb.asBitmap() : null;
         FgThread.getHandler().post(() -> {
             try {
@@ -4263,7 +4281,7 @@
             mTmpRect.offsetTo(0, 0);
 
             final SurfaceControl sc = task.getSurfaceControl();
-            final ScreenCapture.ScreenshotHardwareBuffer buffer = ScreenCapture.captureLayers(
+            final ScreenshotHardwareBuffer buffer = ScreenCapture.captureLayers(
                     layerCaptureArgsBuilder.setLayer(sc).setSourceCrop(mTmpRect).build());
             if (buffer == null) {
                 Slog.w(TAG, "Could not get screenshot buffer for taskId: " + taskId);
@@ -4507,7 +4525,8 @@
         }
     }
 
-    int getDisplayUserRotation(int displayId) {
+    @Override
+    public int getDisplayUserRotation(int displayId) {
         synchronized (mGlobalLock) {
             final DisplayContent display = mRoot.getDisplayContent(displayId);
             if (display == null) {
@@ -8727,6 +8746,16 @@
         }
 
         @Override
+        public void setBlockScreenCaptureForAppsSessionId(long sessionId) {
+            synchronized (mGlobalLock) {
+                if (sensitiveContentMetricsBugfix()
+                        && mSensitiveContentProtectionSessionId != sessionId) {
+                    mSensitiveContentProtectionSessionId = sessionId;
+                }
+            }
+        }
+
+        @Override
         public void addBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos) {
             synchronized (mGlobalLock) {
                 boolean modified =
@@ -8754,6 +8783,15 @@
                 if (modified) {
                     WindowManagerService.this.refreshScreenCaptureDisabled();
                 }
+                if (sensitiveContentImprovements()) {
+                    for (int i = 0; i < packageInfos.size(); i++) {
+                        int uid = packageInfos.valueAt(i).getUid();
+                        if (mCaptureBlockedToastShownUids.contains(uid)) {
+                            mCaptureBlockedToastShownUids.remove(
+                                    mCaptureBlockedToastShownUids.indexOf(uid));
+                        }
+                    }
+                }
             }
         }
 
@@ -8764,6 +8802,9 @@
                 if (modified) {
                     WindowManagerService.this.refreshScreenCaptureDisabled();
                 }
+                if (sensitiveContentImprovements()) {
+                    mCaptureBlockedToastShownUids.clear();
+                }
             }
         }
 
@@ -8786,9 +8827,9 @@
         }
 
         @Override
-        public ScreenCapture.ScreenshotHardwareBuffer takeAssistScreenshot() {
+        public ScreenshotHardwareBuffer takeAssistScreenshot(Set<Integer> windowTypesToExclude) {
             // WMS.takeAssistScreenshot takes care of the locking.
-            return WindowManagerService.this.takeAssistScreenshot();
+            return WindowManagerService.this.takeAssistScreenshot(windowTypesToExclude);
         }
     }
 
@@ -10155,7 +10196,7 @@
      * Called to notify WMS that the specified window has become visible. This shows a Toast if the
      * window is deemed to hold sensitive content.
      */
-    void onWindowVisible(@NonNull WindowState w) {
+    private void onWindowVisible(@NonNull WindowState w) {
         showToastIfBlockingScreenCapture(w);
     }
 
@@ -10165,13 +10206,28 @@
      * on sensitive content protections.
      */
     private void showToastIfBlockingScreenCapture(@NonNull WindowState w) {
-        // TODO(b/323580163): Check if already shown and update shown state.
-        if (mSensitiveContentPackages.shouldBlockScreenCaptureForApp(w.getOwningPackage(),
-                w.getOwningUid(), w.getWindowToken())) {
-            Toast.makeText(mContext, Looper.getMainLooper(),
-                            mContext.getString(R.string.screen_not_shared_sensitive_content),
-                            Toast.LENGTH_SHORT)
-                    .show();
+        int uid = w.getOwningUid();
+        if (mCaptureBlockedToastShownUids.contains(uid)) {
+            return;
+        }
+        if (mSensitiveContentPackages.shouldBlockScreenCaptureForApp(w.getOwningPackage(), uid,
+                w.getWindowToken())) {
+            mCaptureBlockedToastShownUids.add(uid);
+            mH.post(() -> {
+                Toast.makeText(mContext, Looper.getMainLooper(),
+                                mContext.getString(R.string.screen_not_shared_sensitive_content),
+                                Toast.LENGTH_SHORT)
+                        .show();
+            });
+            // If blocked due to notification protection (null window token) log protection applied
+            if (sensitiveContentMetricsBugfix()
+                    && mSensitiveContentPackages
+                    .shouldBlockScreenCaptureForApp(w.getOwningPackage(), uid, null)) {
+                FrameworkStatsLog.write(
+                        SENSITIVE_NOTIFICATION_APP_PROTECTION_APPLIED,
+                        mSensitiveContentProtectionSessionId,
+                        uid);
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 731184f..1f06bfa 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -848,7 +848,12 @@
             return -1;
         }
         synchronized (mInternal.mGlobalLock) {
-            mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(multiplier);
+            try {
+                mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(multiplier);
+            } catch (IllegalArgumentException  e) {
+                getErrPrintWriter().println("Error: invalid multiplier value " + e);
+                return -1;
+            }
         }
         return 0;
     }
@@ -867,7 +872,12 @@
             return -1;
         }
         synchronized (mInternal.mGlobalLock) {
-            mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(multiplier);
+            try {
+                mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(multiplier);
+            } catch (IllegalArgumentException  e) {
+                getErrPrintWriter().println("Error: invalid multiplier value " + e);
+                return -1;
+            }
         }
         return 0;
     }
@@ -1539,9 +1549,9 @@
         pw.println("        both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will");
         pw.println("        be ignored and framework implementation will determine aspect ratio.");
         pw.println("      --cornerRadius radius");
-        pw.println("        Corners radius for activities in the letterbox mode. If radius < 0,");
-        pw.println("        both it and R.integer.config_letterboxActivityCornersRadius will be");
-        pw.println("        ignored and corners of the activity won't be rounded.");
+        pw.println("        Corners radius (in pixels) for activities in the letterbox mode.");
+        pw.println("        If radius < 0, both R.integer.config_letterboxActivityCornersRadius");
+        pw.println("        and it will be ignored and corners of the activity won't be rounded.");
         pw.println("      --backgroundType [reset|solid_color|app_color_background");
         pw.println("          |app_color_background_floating|wallpaper]");
         pw.println("        Type of background used in the letterbox mode.");
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 14ec41f..1573d09 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityManager.isStartResultSuccessful;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
@@ -67,6 +68,7 @@
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
 import static com.android.server.wm.ActivityRecord.State.PAUSING;
+import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
@@ -607,6 +609,11 @@
         ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
         mService.deferWindowLayout();
         mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
+        final boolean shouldDeferTransitionReady = transition != null && !t.isEmpty()
+                && (transition.isCollecting() || Flags.alwaysDeferTransitionWhenApplyWct());
+        if (shouldDeferTransitionReady) {
+            transition.deferTransitionReady();
+        }
         try {
             final ArraySet<WindowContainer<?>> haveConfigChanges = new ArraySet<>();
             if (transition != null) {
@@ -759,6 +766,9 @@
                 mService.mWindowManager.mWindowPlacerLocked.requestTraversal();
             }
         } finally {
+            if (shouldDeferTransitionReady) {
+                transition.continueTransitionReady();
+            }
             mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
             mService.continueWindowLayout();
         }
@@ -833,13 +843,14 @@
 
         if ((c.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) {
             if (tr.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, c.getHidden())) {
-                effects = TRANSACT_EFFECTS_LIFECYCLE;
+                effects |= TRANSACT_EFFECTS_LIFECYCLE;
             }
         }
 
         if ((c.getChangeMask() & CHANGE_FORCE_TRANSLUCENT) != 0) {
-            tr.setForceTranslucent(c.getForceTranslucent());
-            effects = TRANSACT_EFFECTS_LIFECYCLE;
+            if (tr.setForceTranslucent(c.getForceTranslucent())) {
+                effects |= TRANSACT_EFFECTS_LIFECYCLE;
+            }
         }
 
         if ((c.getChangeMask() & WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING) != 0) {
@@ -847,6 +858,17 @@
         }
 
         final int childWindowingMode = c.getActivityWindowingMode();
+        if (!ActivityTaskManagerService.isPip2ExperimentEnabled()
+                && tr.getWindowingMode() == WINDOWING_MODE_PINNED
+                && (childWindowingMode == WINDOWING_MODE_PINNED
+                || childWindowingMode == WINDOWING_MODE_UNDEFINED)) {
+            // If setActivityWindowingMode requested to match its pinned task's windowing mode,
+            // remove any inconsistency checking timeout callbacks for PiP.
+            Slog.d(TAG, "Task and activity windowing modes match, so remove any timeout "
+                    + "abort PiP callbacks scheduled if needed; task_win_mode="
+                    + tr.getWindowingMode() + ", activity_win_mode=" + childWindowingMode);
+            mService.mRootWindowContainer.removeAllMaybeAbortPipEnterRunnable();
+        }
         if (childWindowingMode > -1) {
             tr.forAllActivities(a -> { a.setWindowingMode(childWindowingMode); });
         }
@@ -946,8 +968,9 @@
             }
         }
         if ((c.getChangeMask() & CHANGE_FORCE_TRANSLUCENT) != 0) {
-            taskFragment.setForceTranslucent(c.getForceTranslucent());
-            effects = TRANSACT_EFFECTS_LIFECYCLE;
+            if (taskFragment.setForceTranslucent(c.getForceTranslucent())) {
+                effects |= TRANSACT_EFFECTS_LIFECYCLE;
+            }
         }
 
         effects |= applyChanges(taskFragment, c);
@@ -997,7 +1020,9 @@
                     break;
                 }
                 final Task task = wc.asTask();
-
+                if (task.isVisibleRequested() || task.isVisible()) {
+                    effects |= TRANSACT_EFFECTS_LIFECYCLE;
+                }
                 if (task.isLeafTask()) {
                     mService.mTaskSupervisor
                             .removeTask(task, true, REMOVE_FROM_RECENTS, "remove-task"
@@ -1082,14 +1107,8 @@
                 launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
                 final SafeActivityOptions safeOptions =
                         SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
-                if (transition != null) {
-                    transition.deferTransitionReady();
-                }
                 waitAsyncStart(() -> mService.mTaskSupervisor.startActivityFromRecents(
                         caller.mPid, caller.mUid, taskId, safeOptions));
-                if (transition != null) {
-                    transition.continueTransitionReady();
-                }
                 break;
             }
             case HIERARCHY_OP_TYPE_REORDER:
@@ -1167,17 +1186,11 @@
                     activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
                 }
                 final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
-                if (transition != null) {
-                    transition.deferTransitionReady();
-                }
                 int res = waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
                         hop.getPendingIntent().getTarget(),
                         hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
                         hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
                         null /* requiredPermission */, options));
-                if (transition != null) {
-                    transition.continueTransitionReady();
-                }
                 if (ActivityManager.isStartResultSuccessful(res)) {
                     effects |= TRANSACT_EFFECTS_LIFECYCLE;
                 }
@@ -1225,17 +1238,32 @@
                 ActivityRecord pipActivity = pipTask.getActivity(
                         (activity) -> activity.pictureInPictureArgs != null);
 
+                if (pipActivity.isState(RESUMED)) {
+                    // schedulePauseActivity() call uses this flag when entering PiP after Recents
+                    // swipe-up TO_FRONT transition. In this case the state of the activity is
+                    // RESUMED until ActivityRecord#makeActiveIfNeeded() makes it PAUSING followed
+                    // by the scheduling for PAUSE. See moveActivityToPinnedRootTask()'s call into
+                    // resumeFocusedTasksTopActivities().
+                    pipActivity.mAutoEnteringPip =
+                            pipActivity.pictureInPictureArgs.isAutoEnterEnabled();
+                }
                 Rect entryBounds = hop.getBounds();
                 mService.mRootWindowContainer.moveActivityToPinnedRootTask(
                         pipActivity, null /* launchIntoPipHostActivity */,
                         "moveActivityToPinnedRootTask", null /* transition */, entryBounds);
 
-                // Continue the pausing process after potential task reparenting.
                 if (pipActivity.isState(PAUSING) && pipActivity.mPauseSchedulePendingForPip) {
+                    // Continue the pausing process. This must be done after moving PiP activity to
+                    // a potentially new pinned task (multi-activity case). This case is only
+                    // triggered if TaskFragment#startPausing() deems this an auto-enter case;
+                    // i.e. we enter this flow during button-nav auto-enter but not gesture-nav
+                    // auto-enter PiP for example.
                     pipActivity.getTask().schedulePauseActivity(
                             pipActivity, false /* userLeaving */,
                             false /* pauseImmediately */, true /* autoEnteringPip */, "auto-pip");
                 }
+                // Reset auto-entering PiP info since any internal state updates are finished.
+                pipActivity.mAutoEnteringPip = false;
 
                 effects |= TRANSACT_EFFECTS_LIFECYCLE;
                 break;
@@ -1367,10 +1395,10 @@
                 final IBinder callerActivityToken = operation.getActivityToken();
                 final Intent activityIntent = operation.getActivityIntent();
                 final Bundle activityOptions = operation.getBundle();
-                final int result = mService.getActivityStartController()
+                final int result = waitAsyncStart(() -> mService.getActivityStartController()
                         .startActivityInTaskFragment(taskFragment, activityIntent, activityOptions,
                                 callerActivityToken, caller.mUid, caller.mPid,
-                                errorCallbackToken);
+                                errorCallbackToken));
                 if (!isStartResultSuccessful(result)) {
                     sendTaskFragmentOperationFailure(organizer, errorCallbackToken, taskFragment,
                             opType, convertStartFailureToThrowable(result, activityIntent));
@@ -1528,33 +1556,39 @@
                 break;
             }
             case OP_TYPE_SET_ISOLATED_NAVIGATION: {
-                final boolean isolatedNav = operation.isIsolatedNav();
+                final boolean isolatedNav = operation.getBooleanValue();
                 taskFragment.setIsolatedNav(isolatedNav);
                 break;
             }
             case OP_TYPE_REORDER_TO_BOTTOM_OF_TASK: {
                 final Task task = taskFragment.getTask();
                 if (task != null) {
-                    task.mChildren.remove(taskFragment);
-                    task.mChildren.add(0, taskFragment);
-                    if (!taskFragment.hasChild()) {
-                        // Ensure that the child layers are updated if the TaskFragment is empty.
-                        task.assignChildLayers();
+                    if (task.mChildren.peekFirst() != taskFragment) {
+                        task.mChildren.remove(taskFragment);
+                        task.mChildren.add(0, taskFragment);
+                        if (!taskFragment.hasChild()) {
+                            // Ensure that the child layers are updated if the TaskFragment is
+                            // empty.
+                            task.assignChildLayers();
+                        }
+                        effects |= TRANSACT_EFFECTS_LIFECYCLE;
                     }
-                    effects |= TRANSACT_EFFECTS_LIFECYCLE;
                 }
                 break;
             }
             case OP_TYPE_REORDER_TO_TOP_OF_TASK: {
                 final Task task = taskFragment.getTask();
                 if (task != null) {
-                    task.mChildren.remove(taskFragment);
-                    task.mChildren.add(taskFragment);
-                    if (!taskFragment.hasChild()) {
-                        // Ensure that the child layers are updated if the TaskFragment is empty.
-                        task.assignChildLayers();
+                    if (task.mChildren.peekLast() != taskFragment) {
+                        task.mChildren.remove(taskFragment);
+                        task.mChildren.add(taskFragment);
+                        if (!taskFragment.hasChild()) {
+                            // Ensure that the child layers are updated if the TaskFragment is
+                            // empty.
+                            task.assignChildLayers();
+                        }
+                        effects |= TRANSACT_EFFECTS_LIFECYCLE;
                     }
-                    effects |= TRANSACT_EFFECTS_LIFECYCLE;
                 }
                 break;
             }
@@ -1567,14 +1601,13 @@
                 break;
             }
             case OP_TYPE_SET_DIM_ON_TASK: {
-                final boolean dimOnTask = operation.isDimOnTask();
+                final boolean dimOnTask = operation.getBooleanValue();
                 taskFragment.setEmbeddedDimArea(dimOnTask ? EMBEDDED_DIM_AREA_PARENT_TASK
                         : EMBEDDED_DIM_AREA_TASK_FRAGMENT);
                 break;
             }
             case OP_TYPE_SET_MOVE_TO_BOTTOM_IF_CLEAR_WHEN_LAUNCH: {
-                taskFragment.setMoveToBottomIfClearWhenLaunch(
-                        operation.isMoveToBottomIfClearWhenLaunch());
+                taskFragment.setMoveToBottomIfClearWhenLaunch(operation.getBooleanValue());
                 break;
             }
             case OP_TYPE_SET_DECOR_SURFACE_BOOSTED: {
@@ -2277,6 +2310,9 @@
         TaskFragmentOrganizerToken organizerToken = creationParams.getOrganizer();
         taskFragment.setTaskFragmentOrganizer(organizerToken,
                 ownerActivity.getUid(), ownerActivity.info.processName);
+        if (mTaskFragmentOrganizerController.isSystemOrganizer(organizerToken.asBinder())) {
+            taskFragment.setOverrideOrientation(creationParams.getOverrideOrientation());
+        }
         final int position;
         if (creationParams.getPairedPrimaryFragmentToken() != null) {
             // When there is a paired primary TaskFragment, we want to place the new TaskFragment
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 6ac2774..d91a211 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -110,8 +110,8 @@
     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
 
-    private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 500;
-    private static final long RAPID_ACTIVITY_LAUNCH_MS = 300;
+    private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 50;
+    private static final long RAPID_ACTIVITY_LAUNCH_MS = 500;
     private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 5 * RAPID_ACTIVITY_LAUNCH_MS;
 
     public static final int STOPPED_STATE_NOT_STOPPED = 0;
@@ -202,6 +202,12 @@
     // Whether this process has ever started a service with the BIND_INPUT_METHOD permission.
     private volatile boolean mHasImeService;
 
+    /**
+     * Whether this process can use realtime prioirity (SCHED_FIFO) for its UI and render threads
+     * when this process is SCHED_GROUP_TOP_APP.
+     */
+    private final boolean mUseFifoUiScheduling;
+
     /** Whether {@link #mActivities} is not empty. */
     private volatile boolean mHasActivities;
     /** All activities running in the process (exclude destroying). */
@@ -340,6 +346,8 @@
             // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs.
             mIsActivityConfigOverrideAllowed = false;
         }
+        mUseFifoUiScheduling = com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses()
+                && (isSysUiPackage || mAtm.isCallerRecents(uid));
 
         mCanUseSystemGrammaticalGender = mAtm.mGrammaticalManagerInternal != null
                 && mAtm.mGrammaticalManagerInternal.canGetSystemGrammaticalGender(mUid,
@@ -623,6 +631,11 @@
             return;
         }
 
+        final WindowProcessController caller = mAtm.mProcessMap.getProcess(r.launchedFromPid);
+        if (caller != null && caller.mInstrumenting) {
+            return;
+        }
+
         final long diff = launchTime - lastLaunchTime;
         if (diff < RAPID_ACTIVITY_LAUNCH_MS) {
             mRapidActivityLaunchCount++;
@@ -631,9 +644,15 @@
         }
 
         if (mRapidActivityLaunchCount > MAX_RAPID_ACTIVITY_LAUNCH_COUNT) {
-            Slog.w(TAG, "Killing " + mPid + " because of rapid activity launch");
-            r.getRootTask().moveTaskToBack(r.getTask());
-            mAtm.mH.post(() -> mAtm.mAmInternal.killProcess(mName, mUid, "rapidActivityLaunch"));
+            mRapidActivityLaunchCount = 0;
+            final Task task = r.getTask();
+            Slog.w(TAG, "Removing task " + task.mTaskId + " because of rapid activity launch");
+            mAtm.mH.post(() -> {
+                synchronized (mAtm.mGlobalLock) {
+                    task.removeImmediately("rapid-activity-launch");
+                }
+                mAtm.mAmInternal.killProcess(mName, mUid, "rapidActivityLaunch");
+            });
         }
     }
 
@@ -1901,6 +1920,11 @@
         }
     }
 
+    /** Returns {@code true} if the process prefers to use fifo scheduling. */
+    public boolean useFifoUiScheduling() {
+        return mUseFifoUiScheduling;
+    }
+
     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public void onTopProcChanged() {
         if (mAtm.mVrController.isInterestingToSchedGroup()) {
@@ -2078,6 +2102,9 @@
             }
             pw.println();
         }
+        if (mUseFifoUiScheduling) {
+            pw.println(prefix + " mUseFifoUiScheduling=true");
+        }
 
         final int stateFlags = mActivityStateFlags;
         if (stateFlags != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b716dc6..2fcee50 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -28,7 +28,6 @@
 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
 import static android.os.PowerManager.DRAW_WAKE_LOCK;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.permission.flags.Flags.sensitiveContentImprovements;
 import static android.view.SurfaceControl.Transaction;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
@@ -247,6 +246,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.KeyInterceptionInfo;
+import com.android.internal.protolog.common.LogLevel;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.ToBooleanFunction;
@@ -2138,9 +2138,6 @@
                 }
             }
             setDisplayLayoutNeeded();
-            if (sensitiveContentImprovements() && visible) {
-                mWmService.onWindowVisible(this);
-            }
         }
     }
 
@@ -2973,6 +2970,11 @@
             return true;
         }
 
+        // Do not allow back predictive animation target to receive touch, app can trigger an
+        // unexpected transition so basically unable to polish it.
+        if (mWmService.mAtmService.mBackNavigationController.shouldPauseTouch(mActivityRecord)) {
+            return false;
+        }
         return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput()
                 && mActivityRecord.isVisibleRequested();
     }
@@ -3700,22 +3702,11 @@
         mDragResizingChangeReported = true;
         mWindowFrames.clearReportResizeHints();
 
-        // App window resize may trigger Activity#onConfigurationChanged, so we need to update
-        // ActivityWindowInfo as well.
-        final IBinder activityToken;
-        final ActivityWindowInfo activityWindowInfo;
-        if (mLastReportedActivityWindowInfo != null) {
-            activityToken = mActivityRecord.token;
-            activityWindowInfo = mLastReportedActivityWindowInfo;
-        } else {
-            activityToken = null;
-            activityWindowInfo = null;
-        }
-
         final int prevRotation = mLastReportedConfiguration
                 .getMergedConfiguration().windowConfiguration.getRotation();
         fillClientWindowFramesAndConfiguration(mClientWindowFrames, mLastReportedConfiguration,
-                activityWindowInfo, true /* useLatestConfig */, false /* relayoutVisible */);
+                mLastReportedActivityWindowInfo, true /* useLatestConfig */,
+                false /* relayoutVisible */);
         final boolean syncRedraw = shouldSendRedrawForSync();
         final boolean syncWithBuffers = syncRedraw && shouldSyncWithBuffers();
         final boolean reportDraw = syncRedraw || drawPending;
@@ -3739,14 +3730,15 @@
                             mLastReportedConfiguration, getCompatInsetsState(), forceRelayout,
                             alwaysConsumeSystemBars, displayId,
                             syncWithBuffers ? mSyncSeqId : -1, isDragResizing,
-                            activityToken, activityWindowInfo));
+                            mLastReportedActivityWindowInfo));
             onResizePostDispatched(drawPending, prevRotation, displayId);
         } else {
             // TODO(b/301870955): cleanup after launch
             try {
                 mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
                         getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId,
-                        syncWithBuffers ? mSyncSeqId : -1, isDragResizing, activityWindowInfo);
+                        syncWithBuffers ? mSyncSeqId : -1, isDragResizing,
+                        mLastReportedActivityWindowInfo);
                 onResizePostDispatched(drawPending, prevRotation, displayId);
             } catch (RemoteException e) {
                 // Cancel orientation change of this window to avoid blocking unfreeze display.
@@ -4739,7 +4731,7 @@
     }
 
     void onExitAnimationDone() {
-        if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) {
+        if (ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.VERBOSE)) {
             final AnimationAdapter animationAdapter = mSurfaceAnimator.getAnimation();
             StringWriter sw = new StringWriter();
             if (animationAdapter != null) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a242d42..6fd7aa0 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -61,6 +61,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
+import com.android.internal.protolog.common.LogLevel;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.policy.WindowManagerPolicy;
 
@@ -586,7 +587,7 @@
                             mWin.mAttrs, attr, TRANSIT_OLD_NONE);
                 }
             }
-            if (ProtoLog.isEnabled(WM_DEBUG_ANIM)) {
+            if (ProtoLog.isEnabled(WM_DEBUG_ANIM, LogLevel.VERBOSE)) {
                 ProtoLog.v(WM_DEBUG_ANIM, "applyAnimation: win=%s"
                         + " anim=%d attr=0x%x a=%s transit=%d type=%d isEntrance=%b Callers %s",
                         this, anim, attr, a, transit, mAttrType, isEntrance, Debug.getCallers(20));
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index b999305f..736b051 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -1,12 +1,8 @@
-# Display
-per-file com_android_server_lights_LightsService.cpp = [email protected], [email protected]
-
 # Input
 per-file com_android_server_input_* = file:/INPUT_OWNERS
 
 # Power
-per-file com_android_server_HardwarePropertiesManagerService.cpp = [email protected], [email protected]
-per-file com_android_server_power_PowerManagerService.* = [email protected], [email protected]
+per-file com_android_server_HardwarePropertiesManagerService.cpp = file:/services/core/java/com/android/server/power/OWNERS
 
 # BatteryStats
 per-file com_android_server_am_BatteryStatsService.cpp = file:/BATTERY_STATS_OWNERS
@@ -16,6 +12,7 @@
 per-file com_android_server_Usb* = file:/services/usb/OWNERS
 per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
 per-file com_android_server_accessibility_* = file:/services/accessibility/OWNERS
+per-file com_android_server_display_* = file:/services/core/java/com/android/server/display/OWNERS
 per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
 per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS
 per-file com_android_server_location_* = file:/location/java/android/location/OWNERS
diff --git a/services/core/jni/com_android_server_am_OomConnection.cpp b/services/core/jni/com_android_server_am_OomConnection.cpp
index 054937f..4d07776 100644
--- a/services/core/jni/com_android_server_am_OomConnection.cpp
+++ b/services/core/jni/com_android_server_am_OomConnection.cpp
@@ -92,9 +92,11 @@
             memevent_listener.deregisterAllEvents();
             jniThrowRuntimeException(env, "Failed creating java string for process name");
         }
-        jobject java_oom_kill = env->NewObject(sOomKillRecordInfo.clazz, sOomKillRecordInfo.ctor,
-                                               oom_kill.timestamp_ms, oom_kill.pid, oom_kill.uid,
-                                               process_name, oom_kill.oom_score_adj);
+        jobject java_oom_kill =
+                env->NewObject(sOomKillRecordInfo.clazz, sOomKillRecordInfo.ctor,
+                               oom_kill.timestamp_ms, oom_kill.pid, oom_kill.uid, process_name,
+                               oom_kill.oom_score_adj, oom_kill.total_vm_kb, oom_kill.anon_rss_kb,
+                               oom_kill.file_rss_kb, oom_kill.shmem_rss_kb, oom_kill.pgtables_kb);
         if (java_oom_kill == NULL) {
             memevent_listener.deregisterAllEvents();
             jniThrowRuntimeException(env, "Failed to create OomKillRecord object");
@@ -115,8 +117,8 @@
     sOomKillRecordInfo.clazz = FindClassOrDie(env, "android/os/OomKillRecord");
     sOomKillRecordInfo.clazz = MakeGlobalRefOrDie(env, sOomKillRecordInfo.clazz);
 
-    sOomKillRecordInfo.ctor =
-            GetMethodIDOrDie(env, sOomKillRecordInfo.clazz, "<init>", "(JIILjava/lang/String;S)V");
+    sOomKillRecordInfo.ctor = GetMethodIDOrDie(env, sOomKillRecordInfo.clazz, "<init>",
+                                               "(JIILjava/lang/String;SJJJJJ)V");
 
     return RegisterMethodsOrDie(env, "com/android/server/am/OomConnection", sOomConnectionMethods,
                                 NELEM(sOomConnectionMethods));
diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp
index 5b8ef19..be18835 100644
--- a/services/core/jni/com_android_server_hint_HintManagerService.cpp
+++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp
@@ -34,13 +34,13 @@
 
 #include "jni.h"
 
+using aidl::android::hardware::power::SessionConfig;
 using aidl::android::hardware::power::SessionHint;
 using aidl::android::hardware::power::SessionMode;
+using aidl::android::hardware::power::SessionTag;
 using aidl::android::hardware::power::WorkDuration;
 using android::power::PowerHintSessionWrapper;
 
-using android::base::StringPrintf;
-
 namespace android {
 
 static struct {
@@ -66,6 +66,15 @@
     return rate;
 }
 
+void throwUnsupported(JNIEnv* env, const char* msg) {
+    env->ThrowNew(env->FindClass("java/lang/UnsupportedOperationException"), msg);
+}
+
+void throwFailed(JNIEnv* env, const char* msg) {
+    // We throw IllegalStateException for all errors other than the "unsupported" ones
+    env->ThrowNew(env->FindClass("java/lang/IllegalStateException"), msg);
+}
+
 static jlong createHintSession(JNIEnv* env, int32_t tgid, int32_t uid,
                                std::vector<int32_t>& threadIds, int64_t durationNanos) {
     auto result = gPowerHalController.createHintSession(tgid, uid, threadIds, durationNanos);
@@ -76,10 +85,38 @@
         return res.second ? session_ptr : 0;
     } else if (result.isFailed()) {
         ALOGW("createHintSession failed with message: %s", result.errorMessage());
+        throwFailed(env, result.errorMessage());
+    } else if (result.isUnsupported()) {
+        throwUnsupported(env, result.errorMessage());
+        return -1;
     }
     return 0;
 }
 
+static jlong createHintSessionWithConfig(JNIEnv* env, int32_t tgid, int32_t uid,
+                                         std::vector<int32_t> threadIds, int64_t durationNanos,
+                                         int32_t sessionTag, SessionConfig& config) {
+    auto result =
+            gPowerHalController.createHintSessionWithConfig(tgid, uid, threadIds, durationNanos,
+                                                            static_cast<SessionTag>(sessionTag),
+                                                            &config);
+    if (result.isOk()) {
+        jlong session_ptr = reinterpret_cast<jlong>(result.value().get());
+        std::scoped_lock sessionLock(gSessionMapLock);
+        auto res = gSessionMap.insert({session_ptr, result.value()});
+        if (!res.second) {
+            throwFailed(env, "PowerHAL provided an invalid session");
+            return 0;
+        }
+        return session_ptr;
+    } else if (result.isUnsupported()) {
+        throwUnsupported(env, result.errorMessage());
+        return -1;
+    }
+    throwFailed(env, result.errorMessage());
+    return 0;
+}
+
 static void pauseHintSession(JNIEnv* env, int64_t session_ptr) {
     auto appSession = reinterpret_cast<PowerHintSessionWrapper*>(session_ptr);
     appSession->pause();
@@ -136,13 +173,34 @@
                                      jintArray tids, jlong durationNanos) {
     ScopedIntArrayRO tidArray(env, tids);
     if (nullptr == tidArray.get() || tidArray.size() == 0) {
-        ALOGW("GetIntArrayElements returns nullptr.");
+        ALOGW("nativeCreateHintSession: GetIntArrayElements returns nullptr.");
         return 0;
     }
     std::vector<int32_t> threadIds(tidArray.get(), tidArray.get() + tidArray.size());
     return createHintSession(env, tgid, uid, threadIds, durationNanos);
 }
 
+static jlong nativeCreateHintSessionWithConfig(JNIEnv* env, jclass /* clazz */, jint tgid, jint uid,
+                                               jintArray tids, jlong durationNanos, jint sessionTag,
+                                               jobject sessionConfig) {
+    ScopedIntArrayRO tidArray(env, tids);
+    if (nullptr == tidArray.get() || tidArray.size() == 0) {
+        ALOGW("nativeCreateHintSessionWithConfig: GetIntArrayElements returns nullptr.");
+        return 0;
+    }
+    std::vector<int32_t> threadIds(tidArray.get(), tidArray.get() + tidArray.size());
+    SessionConfig config;
+    jlong out = createHintSessionWithConfig(env, tgid, uid, std::move(threadIds), durationNanos,
+                                            sessionTag, config);
+    if (out <= 0) {
+        return out;
+    }
+    static jclass configClass = env->FindClass("android/hardware/power/SessionConfig");
+    static jfieldID fid = env->GetFieldID(configClass, "id", "J");
+    env->SetLongField(sessionConfig, fid, config.id);
+    return out;
+}
+
 static void nativePauseHintSession(JNIEnv* env, jclass /* clazz */, jlong session_ptr) {
     pauseHintSession(env, session_ptr);
 }
@@ -215,6 +273,8 @@
         {"nativeInit", "()V", (void*)nativeInit},
         {"nativeGetHintSessionPreferredRate", "()J", (void*)nativeGetHintSessionPreferredRate},
         {"nativeCreateHintSession", "(II[IJ)J", (void*)nativeCreateHintSession},
+        {"nativeCreateHintSessionWithConfig", "(II[IJILandroid/hardware/power/SessionConfig;)J",
+         (void*)nativeCreateHintSessionWithConfig},
         {"nativePauseHintSession", "(J)V", (void*)nativePauseHintSession},
         {"nativeResumeHintSession", "(J)V", (void*)nativeResumeHintSession},
         {"nativeCloseHintSession", "(J)V", (void*)nativeCloseHintSession},
diff --git a/services/core/jni/com_android_server_utils_AnrTimer.cpp b/services/core/jni/com_android_server_utils_AnrTimer.cpp
index 8ca5333..da95666 100644
--- a/services/core/jni/com_android_server_utils_AnrTimer.cpp
+++ b/services/core/jni/com_android_server_utils_AnrTimer.cpp
@@ -487,7 +487,6 @@
         timer_id_t front = headTimerId();
         auto found = running_.find(key);
         if (found != running_.end()) running_.erase(found);
-        if (front != headTimerId()) restartLocked();
     }
 
     // Remove every timer associated with the service.
@@ -501,7 +500,6 @@
                 i++;
             }
         }
-        if (front != headTimerId()) restartLocked();
     }
 
     // Return the number of timers still running.
diff --git a/services/core/jni/linux/usb/f_accessory.h b/services/core/jni/linux/usb/f_accessory.h
new file mode 100644
index 0000000..abd864c
--- /dev/null
+++ b/services/core/jni/linux/usb/f_accessory.h
@@ -0,0 +1,34 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_LINUX_USB_F_ACCESSORY_H
+#define _UAPI_LINUX_USB_F_ACCESSORY_H
+#define USB_ACCESSORY_VENDOR_ID 0x18D1
+#define USB_ACCESSORY_PRODUCT_ID 0x2D00
+#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
+#define ACCESSORY_STRING_MANUFACTURER 0
+#define ACCESSORY_STRING_MODEL 1
+#define ACCESSORY_STRING_DESCRIPTION 2
+#define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+#define ACCESSORY_GET_PROTOCOL 51
+#define ACCESSORY_SEND_STRING 52
+#define ACCESSORY_START 53
+#define ACCESSORY_REGISTER_HID 54
+#define ACCESSORY_UNREGISTER_HID 55
+#define ACCESSORY_SET_HID_REPORT_DESC 56
+#define ACCESSORY_SEND_HID_EVENT 57
+#define ACCESSORY_SET_AUDIO_MODE 58
+#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
+#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
+#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256])
+#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
+#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256])
+#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
+#define ACCESSORY_IS_START_REQUESTED _IO('M', 7)
+#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8)
+#endif
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 8598023..6143f1d 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -176,7 +176,9 @@
                 <xs:element type="idleScreenRefreshRateTimeout" name="idleScreenRefreshRateTimeout" minOccurs="0">
                     <xs:annotation name="final"/>
                 </xs:element>
-
+                <xs:element name="supportsVrr" type="xs:boolean" minOccurs="0">
+                    <xs:annotation name="final"/>
+                </xs:element>
             </xs:sequence>
         </xs:complexType>
     </xs:element>
@@ -226,11 +228,8 @@
             <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1"
                 maxOccurs="1">
             </xs:element>
-            <xs:element name="nits" type="xs:float" maxOccurs="unbounded">
-            </xs:element>
-            <xs:element name="backlight" type="xs:float" maxOccurs="unbounded">
-            </xs:element>
-            <xs:element name="brightness" type="xs:float" maxOccurs="unbounded">
+            <!-- Mapping of nits -> backlight -> brightness -->
+            <xs:element name="brightnessMapping" type="comprehensiveBrightnessMap" maxOccurs="1">
             </xs:element>
             <!-- Mapping of current lux to minimum allowed nits values. -->
             <xs:element name="luxToMinimumNitsMap" type="nitsMap" maxOccurs="1">
@@ -449,6 +448,35 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:complexType name="comprehensiveBrightnessMap">
+        <xs:sequence>
+            <xs:element name="brightnessPoint" type="brightnessPoint" maxOccurs="unbounded" minOccurs="2">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+        <!-- valid value of interpolation if specified: linear -->
+        <xs:attribute name="interpolation" type="xs:string" use="optional"/>
+    </xs:complexType>
+
+    <xs:complexType name="brightnessPoint">
+        <xs:sequence>
+            <xs:element type="nonNegativeDecimal" name="nits">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <xs:element type="nonNegativeDecimal" name="backlight">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <xs:element type="nonNegativeDecimal" name="brightness">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+
     <xs:complexType name="sdrHdrRatioMap">
         <xs:sequence>
             <xs:element name="point" type="sdrHdrRatioPoint" maxOccurs="unbounded" minOccurs="2">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 4ce4cc3..45ec8f2 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -53,6 +53,16 @@
     method public final void setType(@NonNull com.android.server.display.config.PredefinedBrightnessLimitNames);
   }
 
+  public class BrightnessPoint {
+    ctor public BrightnessPoint();
+    method @NonNull public final java.math.BigDecimal getBacklight();
+    method @NonNull public final java.math.BigDecimal getBrightness();
+    method @NonNull public final java.math.BigDecimal getNits();
+    method public final void setBacklight(@NonNull java.math.BigDecimal);
+    method public final void setBrightness(@NonNull java.math.BigDecimal);
+    method public final void setNits(@NonNull java.math.BigDecimal);
+  }
+
   public class BrightnessThresholds {
     ctor public BrightnessThresholds();
     method public final com.android.server.display.config.ThresholdPoints getBrightnessThresholdPoints();
@@ -76,6 +86,13 @@
     method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
   }
 
+  public class ComprehensiveBrightnessMap {
+    ctor public ComprehensiveBrightnessMap();
+    method @NonNull public final java.util.List<com.android.server.display.config.BrightnessPoint> getBrightnessPoint();
+    method public String getInterpolation();
+    method public void setInterpolation(String);
+  }
+
   public class Density {
     ctor public Density();
     method @NonNull public final java.math.BigInteger getDensity();
@@ -135,6 +152,7 @@
     method public final java.math.BigDecimal getScreenBrightnessRampSlowIncreaseIdle();
     method public final com.android.server.display.config.SensorDetails getScreenOffBrightnessSensor();
     method public final com.android.server.display.config.IntegerArray getScreenOffBrightnessSensorValueToLux();
+    method public final boolean getSupportsVrr();
     method public final com.android.server.display.config.SensorDetails getTempSensor();
     method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
     method public final com.android.server.display.config.UsiVersion getUsiVersion();
@@ -171,6 +189,7 @@
     method public final void setScreenBrightnessRampSlowIncreaseIdle(java.math.BigDecimal);
     method public final void setScreenOffBrightnessSensor(com.android.server.display.config.SensorDetails);
     method public final void setScreenOffBrightnessSensorValueToLux(com.android.server.display.config.IntegerArray);
+    method public final void setSupportsVrr(boolean);
     method public final void setTempSensor(com.android.server.display.config.SensorDetails);
     method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
     method public final void setUsiVersion(com.android.server.display.config.UsiVersion);
@@ -183,12 +202,11 @@
 
   public class EvenDimmerMode {
     ctor public EvenDimmerMode();
-    method public java.util.List<java.lang.Float> getBacklight();
-    method public java.util.List<java.lang.Float> getBrightness();
+    method public com.android.server.display.config.ComprehensiveBrightnessMap getBrightnessMapping();
     method public boolean getEnabled();
     method public com.android.server.display.config.NitsMap getLuxToMinimumNitsMap();
-    method public java.util.List<java.lang.Float> getNits();
     method public java.math.BigDecimal getTransitionPoint();
+    method public void setBrightnessMapping(com.android.server.display.config.ComprehensiveBrightnessMap);
     method public void setEnabled(boolean);
     method public void setLuxToMinimumNitsMap(com.android.server.display.config.NitsMap);
     method public void setTransitionPoint(java.math.BigDecimal);
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index f5ba50d..73e53e2 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -21,13 +21,13 @@
 import android.content.Context;
 import android.credentials.ClearCredentialStateException;
 import android.credentials.ClearCredentialStateRequest;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.IClearCredentialStateCallback;
 import android.credentials.selection.ProviderData;
 import android.credentials.selection.RequestInfo;
 import android.os.CancellationSignal;
 import android.os.RemoteException;
-import android.os.ResultReceiver;
 import android.service.credentials.CallingAppInfo;
 import android.util.Slog;
 
@@ -41,7 +41,7 @@
 public final class ClearRequestSession extends RequestSession<ClearCredentialStateRequest,
         IClearCredentialStateCallback, Void>
         implements ProviderSession.ProviderInternalCallback<Void> {
-    private static final String TAG = "GetRequestSession";
+    private static final String TAG = CredentialManager.TAG;
 
     public ClearRequestSession(Context context, RequestSession.SessionLifetime sessionCallback,
             Object lock, int userId, int callingUid,
@@ -150,7 +150,7 @@
     }
 
     @Override
-    public void onUiCancellation(boolean isUserCancellation, ResultReceiver resultReceiver) {
+    public void onUiCancellation(boolean isUserCancellation) {
         // Not needed since UI is not involved
     }
 
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index cac42b1..9781fb9 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -31,7 +31,6 @@
 import android.credentials.selection.RequestInfo;
 import android.os.CancellationSignal;
 import android.os.RemoteException;
-import android.os.ResultReceiver;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.PermissionUtils;
 import android.util.Slog;
@@ -50,7 +49,7 @@
 public final class CreateRequestSession extends RequestSession<CreateCredentialRequest,
         ICreateCredentialCallback, CreateCredentialResponse>
         implements ProviderSession.ProviderInternalCallback<CreateCredentialResponse> {
-    private static final String TAG = "CreateRequestSession";
+    private static final String TAG = CredentialManager.TAG;
     private final Set<ComponentName> mPrimaryProviders;
 
     CreateRequestSession(@NonNull Context context, RequestSession.SessionLifetime sessionCallback,
@@ -164,7 +163,7 @@
     }
 
     @Override
-    public void onUiCancellation(boolean isUserCancellation, ResultReceiver resultReceiver) {
+    public void onUiCancellation(boolean isUserCancellation) {
         String exception = CreateCredentialException.TYPE_USER_CANCELED;
         String message = "User cancelled the selector";
         if (!isUserCancellation) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 281fb1c..6ef1436 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -34,6 +34,7 @@
 import android.credentials.ClearCredentialStateRequest;
 import android.credentials.CreateCredentialException;
 import android.credentials.CreateCredentialRequest;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialOption;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCandidateCredentialsException;
@@ -92,7 +93,7 @@
         extends AbstractMasterSystemService<
         CredentialManagerService, CredentialManagerServiceImpl> {
 
-    private static final String TAG = "CredManSysService";
+    private static final String TAG = CredentialManager.TAG;
     private static final String PERMISSION_DENIED_ERROR = "permission_denied";
     private static final String PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR =
             "Caller is missing WRITE_SECURE_SETTINGS permission";
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
index 379800b..38ad5b6 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.service.credentials.CredentialProviderInfoFactory;
 import android.util.Slog;
@@ -36,7 +37,7 @@
  */
 public final class CredentialManagerServiceImpl extends
         AbstractPerUserSystemService<CredentialManagerServiceImpl, CredentialManagerService> {
-    private static final String TAG = "CredManSysServiceImpl";
+    private static final String TAG = CredentialManager.TAG;
 
     @GuardedBy("mLock")
     @NonNull
@@ -93,7 +94,10 @@
     public ProviderSession initiateProviderSessionForRequestLocked(
             RequestSession requestSession, List<String> requestOptions) {
         if (!requestOptions.isEmpty() && !isServiceCapableLocked(requestOptions)) {
-            Slog.i(TAG, "Service does not have the required capabilities");
+            if (mInfo != null) {
+                Slog.i(TAG, "Service does not have the required capabilities: "
+                        + mInfo.getComponentName());
+            }
             return null;
         }
         if (mInfo == null) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
index 24f6697..e73dacb 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
@@ -15,8 +15,6 @@
  */
 package com.android.server.credentials;
 
-import static android.credentials.selection.Constants.EXTRA_FINAL_RESPONSE_RECEIVER;
-
 import android.annotation.NonNull;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -48,7 +46,6 @@
 
 /** Initiates the Credential Manager UI and receives results. */
 public class CredentialManagerUi {
-    private static final String TAG = "CredentialManagerUi";
     @NonNull
     private final CredentialManagerUiCallback mCallbacks;
     @NonNull
@@ -83,25 +80,18 @@
                 UserSelectionDialogResult selection = UserSelectionDialogResult
                         .fromResultData(resultData);
                 if (selection != null) {
-                    ResultReceiver resultReceiver = resultData.getParcelable(
-                            EXTRA_FINAL_RESPONSE_RECEIVER,
-                            ResultReceiver.class);
-                    mCallbacks.onUiSelection(selection, resultReceiver);
+                    mCallbacks.onUiSelection(selection);
                 }
                 break;
             case UserSelectionDialogResult.RESULT_CODE_DIALOG_USER_CANCELED:
 
                 mStatus = UiStatus.TERMINATED;
-                mCallbacks.onUiCancellation(/* isUserCancellation= */ true,
-                        resultData.getParcelable(EXTRA_FINAL_RESPONSE_RECEIVER,
-                                ResultReceiver.class));
+                mCallbacks.onUiCancellation(/* isUserCancellation= */ true);
                 break;
             case UserSelectionDialogResult.RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS:
 
                 mStatus = UiStatus.TERMINATED;
-                mCallbacks.onUiCancellation(/* isUserCancellation= */ false,
-                        resultData.getParcelable(EXTRA_FINAL_RESPONSE_RECEIVER,
-                                ResultReceiver.class));
+                mCallbacks.onUiCancellation(/* isUserCancellation= */ false);
                 break;
             case UserSelectionDialogResult.RESULT_CODE_DATA_PARSING_FAILURE:
                 mStatus = UiStatus.TERMINATED;
@@ -125,10 +115,10 @@
      */
     public interface CredentialManagerUiCallback {
         /** Called when the user makes a selection. */
-        void onUiSelection(UserSelectionDialogResult selection, ResultReceiver resultReceiver);
+        void onUiSelection(UserSelectionDialogResult selection);
 
         /** Called when the UI is canceled without a successful provider result. */
-        void onUiCancellation(boolean isUserCancellation, ResultReceiver resultReceiver);
+        void onUiCancellation(boolean isUserCancellation);
 
         /** Called when the selector UI fails to come up (mostly due to parsing issue today). */
         void onUiSelectorInvocationFailure();
diff --git a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java
index fd2a9a2..b1673e2 100644
--- a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java
@@ -22,9 +22,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.credentials.Constants;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCandidateCredentialsException;
 import android.credentials.GetCandidateCredentialsResponse;
+import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialRequest;
 import android.credentials.GetCredentialResponse;
 import android.credentials.IGetCandidateCredentialsCallback;
@@ -54,7 +56,7 @@
 public class GetCandidateRequestSession extends RequestSession<GetCredentialRequest,
         IGetCandidateCredentialsCallback, GetCandidateCredentialsResponse>
         implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
-    private static final String TAG = "GetCandidateRequestSession";
+    private static final String TAG = CredentialManager.TAG;
 
     private static final String SESSION_ID_KEY = "autofill_session_id";
     private static final String REQUEST_ID_KEY = "autofill_request_id";
@@ -63,6 +65,8 @@
     private final int mAutofillSessionId;
     private final int mAutofillRequestId;
 
+    private final ResultReceiver mAutofillCallback;
+
     public GetCandidateRequestSession(
             Context context, SessionLifetime sessionCallback,
             Object lock, int userId, int callingUid,
@@ -76,6 +80,8 @@
         mClientBinder = clientBinder;
         mAutofillSessionId = request.getData().getInt(SESSION_ID_KEY, -1);
         mAutofillRequestId = request.getData().getInt(REQUEST_ID_KEY, -1);
+        mAutofillCallback = request.getData().getParcelable(
+                CredentialManager.EXTRA_AUTOFILL_RESULT_RECEIVER, ResultReceiver.class);
         if (mClientBinder != null) {
             setUpClientCallbackListener(mClientBinder);
         }
@@ -154,34 +160,34 @@
     public void onFinalErrorReceived(ComponentName componentName, String errorType,
             String message) {
         Slog.d(TAG, "onFinalErrorReceived");
-        respondToFinalReceiverWithFailureAndFinish(this.mFinalResponseReceiver, errorType, message);
+        if (GetCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+            Slog.d(TAG, "User canceled but session is not being terminated");
+            return;
+        }
+        respondToFinalReceiverWithFailureAndFinish(errorType, message);
     }
 
     @Override
-    public void onUiCancellation(boolean isUserCancellation,
-            @Nullable ResultReceiver finalResponseReceiver) {
-        String exception = GetCandidateCredentialsException.TYPE_USER_CANCELED;
-        String message = "User cancelled the selector";
-        if (!isUserCancellation) {
-            exception = GetCandidateCredentialsException.TYPE_INTERRUPTED;
-            message = "The UI was interrupted - please try again.";
-        }
-        mRequestSessionMetric.collectFrameworkException(exception);
-        respondToFinalReceiverWithFailureAndFinish(finalResponseReceiver, exception, message);
+    public void onUiCancellation(boolean isUserCancellation) {
+        Slog.d(TAG, "User canceled but session is not being terminated");
     }
 
     private void respondToFinalReceiverWithFailureAndFinish(
-            ResultReceiver finalResponseReceiver,
             String exception, String message
     ) {
-        if (finalResponseReceiver != null) {
+        if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
+            Slog.w(TAG, "Request has already been completed. This is strange.");
+            return;
+        }
+
+        if (mAutofillCallback != null) {
             Bundle resultData = new Bundle();
             resultData.putStringArray(
                     CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION,
                     new String[] {exception, message});
-            finalResponseReceiver.send(Constants.FAILURE_CREDMAN_SELECTOR, resultData);
+            mAutofillCallback.send(Constants.FAILURE_CREDMAN_SELECTOR, resultData);
         } else {
-            Slog.w(TAG, "onUiCancellation called but finalResponseReceiver not found");
+            Slog.w(TAG, "onUiCancellation called but mAutofillCallback not found");
         }
         finishSession(/*propagateCancellation=*/false, ApiStatus.FAILURE.getMetricCode());
     }
@@ -218,12 +224,25 @@
     public void onFinalResponseReceived(ComponentName componentName,
             GetCredentialResponse response) {
         Slog.d(TAG, "onFinalResponseReceived");
-        if (this.mFinalResponseReceiver != null) {
+        if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
+            Slog.w(TAG, "Request has already been completed. This is strange.");
+            return;
+        }
+        respondToFinalReceiverWithResponseAndFinish(response);
+    }
+
+    private void respondToFinalReceiverWithResponseAndFinish(GetCredentialResponse response) {
+        if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
+            Slog.w(TAG, "Request has already been completed. This is strange.");
+            return;
+        }
+
+        if (this.mAutofillCallback != null) {
             Slog.d(TAG, "onFinalResponseReceived sending through final receiver");
             Bundle resultData = new Bundle();
             resultData.putParcelable(
                     CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, response);
-            mFinalResponseReceiver.send(Constants.SUCCESS_CREDMAN_SELECTOR, resultData);
+            mAutofillCallback.send(Constants.SUCCESS_CREDMAN_SELECTOR, resultData);
             finishSession(/*propagateCancellation=*/ false, ApiStatus.SUCCESS.getMetricCode());
         } else {
             Slog.w(TAG, "onFinalResponseReceived result receiver not found for pinned entry");
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index d55d8ef..be36b6c 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialOption;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCredentialException;
@@ -31,7 +32,6 @@
 import android.os.Binder;
 import android.os.CancellationSignal;
 import android.os.RemoteException;
-import android.os.ResultReceiver;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.PermissionUtils;
 import android.util.Slog;
@@ -48,7 +48,7 @@
 public class GetRequestSession extends RequestSession<GetCredentialRequest,
         IGetCredentialCallback, GetCredentialResponse>
         implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
-    private static final String TAG = "GetRequestSession";
+    private static final String TAG = CredentialManager.TAG;
 
     public GetRequestSession(Context context, RequestSession.SessionLifetime sessionCallback,
             Object lock, int userId, int callingUid,
@@ -165,7 +165,7 @@
     }
 
     @Override
-    public void onUiCancellation(boolean isUserCancellation, ResultReceiver resultReceiver) {
+    public void onUiCancellation(boolean isUserCancellation) {
         String exception = GetCredentialException.TYPE_USER_CANCELED;
         String message = "User cancelled the selector";
         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 16bf1778..ac4aac6 100644
--- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java
+++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.credentials.CredentialManager;
 import android.util.Slog;
 
 import com.android.internal.util.FrameworkStatsLog;
@@ -44,7 +45,7 @@
 public class MetricUtilities {
     private static final boolean LOG_FLAG = true;
 
-    private static final String TAG = "MetricUtilities";
+    private static final String TAG = CredentialManager.TAG;
     public static final String USER_CANCELED_SUBSTRING = "TYPE_USER_CANCELED";
     public static final int MIN_EMIT_WAIT_TIME_MS = 10;
 
diff --git a/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java b/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java
index e4b5c77..f6b107b 100644
--- a/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java
@@ -21,6 +21,7 @@
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialOption;
 import android.credentials.GetCredentialRequest;
 import android.credentials.IGetCredentialCallback;
@@ -44,7 +45,7 @@
  * responses from providers, and the UX app, and updates the provider(s) state.
  */
 public class PrepareGetRequestSession extends GetRequestSession {
-    private static final String TAG = "PrepareGetRequestSession";
+    private static final String TAG = CredentialManager.TAG;
 
     private final IPrepareGetCredentialCallback mPrepareGetCredentialCallback;
 
diff --git a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
index 6a1b1db7..6759dbb 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
@@ -20,6 +20,7 @@
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.credentials.ClearCredentialStateException;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.selection.ProviderData;
 import android.credentials.selection.ProviderPendingIntentResponse;
@@ -37,7 +38,7 @@
         Void>
         implements
         RemoteCredentialService.ProviderCallbacks<Void> {
-    private static final String TAG = "ProviderClearSession";
+    private static final String TAG = CredentialManager.TAG;
 
     private ClearCredentialStateException mProviderException;
 
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 6361aeb..bee7f6c 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.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.selection.CreateCredentialProviderData;
 import android.credentials.selection.Entry;
@@ -51,7 +52,7 @@
  */
 public final class ProviderCreateSession extends ProviderSession<
         BeginCreateCredentialRequest, BeginCreateCredentialResponse> {
-    private static final String TAG = "ProviderCreateSession";
+    private static final String TAG = CredentialManager.TAG;
 
     // Key to be used as an entry key for a save entry
     public static final String SAVE_ENTRY_KEY = "save_entry_key";
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index c5f2921..e18ef2b 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialOption;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCredentialException;
@@ -61,7 +62,7 @@
         BeginGetCredentialResponse>
         implements
         RemoteCredentialService.ProviderCallbacks<BeginGetCredentialResponse> {
-    private static final String TAG = "ProviderGetSession";
+    private static final String TAG = CredentialManager.TAG;
     // Key to be used as the entry key for an action entry
     public static final String ACTION_ENTRY_KEY = "action_key";
     // Key to be used as the entry key for the authentication entry
diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
index f162916..83f9c24 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialOption;
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialResponse;
@@ -58,7 +59,7 @@
 public class ProviderRegistryGetSession extends ProviderSession<CredentialOption,
         Set<CredentialDescriptionRegistry.FilterResult>> {
 
-    private static final String TAG = "ProviderRegistryGetSession";
+    private static final String TAG = CredentialManager.TAG;
     @VisibleForTesting
     static final String CREDENTIAL_ENTRY_KEY = "credential_key";
 
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index dfc08f0..8f0ae90 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -24,6 +24,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.credentials.Credential;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.selection.ProviderData;
 import android.credentials.selection.ProviderPendingIntentResponse;
@@ -44,7 +45,7 @@
 public abstract class ProviderSession<T, R>
         implements RemoteCredentialService.ProviderCallbacks<R> {
 
-    private static final String TAG = "ProviderSession";
+    private static final String TAG = CredentialManager.TAG;
 
     @NonNull
     protected final Context mContext;
diff --git a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
index 4bcf8be..c361406 100644
--- a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
+++ b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.credentials.ClearCredentialStateException;
 import android.credentials.CreateCredentialException;
+import android.credentials.CredentialManager;
 import android.credentials.GetCredentialException;
 import android.os.Binder;
 import android.os.Handler;
@@ -58,7 +59,7 @@
  */
 public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialProviderService> {
 
-    private static final String TAG = "RemoteCredentialService";
+    private static final String TAG = CredentialManager.TAG;
     /** Timeout for a single request. */
     private static final long TIMEOUT_REQUEST_MILLIS = 3 * DateUtils.SECOND_IN_MILLIS;
     /** Timeout to unbind after the task queue is empty. */
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index a5b9aa6..c0bc8e0 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -17,12 +17,12 @@
 package com.android.server.credentials;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.credentials.CredentialManager;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.flags.Flags;
 import android.credentials.selection.ProviderData;
@@ -34,7 +34,6 @@
 import android.os.IInterface;
 import android.os.Looper;
 import android.os.RemoteException;
-import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.service.credentials.CallingAppInfo;
 import android.util.Slog;
@@ -56,7 +55,7 @@
  * every time a new response type is expected from the providers.
  */
 abstract class RequestSession<T, U, V> implements CredentialManagerUi.CredentialManagerUiCallback {
-    private static final String TAG = "RequestSession";
+    private static final String TAG = CredentialManager.TAG;
 
     public interface SessionLifetime {
         /** Called when the user makes a selection. */
@@ -103,9 +102,6 @@
 
     protected PendingIntent mPendingIntent;
 
-    @Nullable
-    protected ResultReceiver mFinalResponseReceiver;
-
     @NonNull
     protected RequestSessionStatus mRequestSessionStatus =
             RequestSessionStatus.IN_PROGRESS;
@@ -224,8 +220,7 @@
     // UI callbacks
 
     @Override // from CredentialManagerUiCallbacks
-    public void onUiSelection(UserSelectionDialogResult selection,
-            ResultReceiver finalResponseReceiver) {
+    public void onUiSelection(UserSelectionDialogResult selection) {
         if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
             Slog.w(TAG, "Request has already been completed. This is strange.");
             return;
@@ -241,7 +236,7 @@
             Slog.w(TAG, "providerSession not found in onUiSelection. This is strange.");
             return;
         }
-        mFinalResponseReceiver = finalResponseReceiver;
+
         ProviderSessionMetric providerSessionMetric = providerSession.mProviderSessionMetric;
         int initialAuthMetricsProvider = providerSessionMetric.getBrowsedAuthenticationMetric()
                 .size();
diff --git a/services/devicepolicy/TEST_MAPPING b/services/devicepolicy/TEST_MAPPING
index 0d5534b..b8cb4a9 100644
--- a/services/devicepolicy/TEST_MAPPING
+++ b/services/devicepolicy/TEST_MAPPING
@@ -26,5 +26,12 @@
         }
       ]
     }
+  ],
+  "postsubmit": [
+    {
+      // TODO(b/332974906): Promote in presubmit presubmit-devicepolicy.
+      "name": "CtsDevicePolicyManagerTestCases_NoFlakes_NoLarge",
+      "name": "CtsDevicePolicyManagerTestCases_ParentProfileApiDisabled"
+    }
   ]
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
index 82f9aad..d24afabe 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
@@ -92,7 +92,7 @@
                 while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                     if (type == XmlPullParser.START_TAG
                             && parser.getName().equals(TAG_VALUE)) {
-                        values.add(parser.nextText().trim());
+                        values.add(parser.nextText());
                         count--;
                     }
                 }
@@ -111,7 +111,7 @@
                 restrictions.putParcelableArray(key,
                         bundleList.toArray(new Bundle[bundleList.size()]));
             } else {
-                String value = parser.nextText().trim();
+                String value = parser.nextText();
                 if (ATTR_TYPE_BOOLEAN.equals(valType)) {
                     restrictions.putBoolean(key, Boolean.parseBoolean(value));
                 } else if (ATTR_TYPE_INTEGER.equals(valType)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index c4e2dc8..b76279b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -32,7 +32,6 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
@@ -48,18 +47,11 @@
     private final Object mLock = new Object();
 
     /**
-     * Indicates which user is screen capture disallowed on. Can be {@link UserHandle#USER_NULL},
-     * {@link UserHandle#USER_ALL} or a concrete user ID.
-     */
-    @GuardedBy("mLock")
-    private int mScreenCaptureDisallowedUser = UserHandle.USER_NULL;
-
-    /**
      * Indicates if screen capture is disallowed on a specific user or all users if
      * it contains {@link UserHandle#USER_ALL}.
      */
     @GuardedBy("mLock")
-    private Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>();
+    private final Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>();
 
     @GuardedBy("mLock")
     private final SparseIntArray mPasswordQuality = new SparseIntArray();
@@ -70,9 +62,8 @@
     @GuardedBy("mLock")
     private ArrayMap<String, String> mLauncherShortcutOverrides = new ArrayMap<>();
 
-
     /** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */
-    private final AtomicBoolean mCanGrantSensorsPermissions = new AtomicBoolean(false);
+    private volatile boolean mCanGrantSensorsPermissions = false;
 
     @GuardedBy("mLock")
     private final SparseIntArray mContentProtectionPolicy = new SparseIntArray();
@@ -87,10 +78,6 @@
 
     @Override
     public boolean isScreenCaptureAllowed(int userHandle) {
-        return isScreenCaptureAllowedInPolicyEngine(userHandle);
-    }
-
-    private boolean isScreenCaptureAllowedInPolicyEngine(int userHandle) {
         // This won't work if resolution mechanism is not strictest applies, but it's ok for now.
         synchronized (mLock) {
             return !mScreenCaptureDisallowedUsers.contains(userHandle)
@@ -98,18 +85,6 @@
         }
     }
 
-    public int getScreenCaptureDisallowedUser() {
-        synchronized (mLock) {
-            return mScreenCaptureDisallowedUser;
-        }
-    }
-
-    public void setScreenCaptureDisallowedUser(int userHandle) {
-        synchronized (mLock) {
-            mScreenCaptureDisallowedUser = userHandle;
-        }
-    }
-
     public void setScreenCaptureDisallowedUser(int userHandle, boolean disallowed) {
         synchronized (mLock) {
             if (disallowed) {
@@ -170,12 +145,12 @@
 
     @Override
     public boolean canAdminGrantSensorsPermissions() {
-        return mCanGrantSensorsPermissions.get();
+        return mCanGrantSensorsPermissions;
     }
 
     /** Sets admin control over permission grants. */
     public void setAdminCanGrantSensorsPermissions(boolean canGrant) {
-        mCanGrantSensorsPermissions.set(canGrant);
+        mCanGrantSensorsPermissions = canGrant;
     }
 
     @Override
@@ -205,7 +180,7 @@
             pw.println("Password quality: " + mPasswordQuality);
             pw.println("Permission policy: " + mPermissionPolicy);
             pw.println("Content protection policy: " + mContentProtectionPolicy);
-            pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions.get());
+            pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions);
             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 f39d019..d114337 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -103,7 +103,7 @@
                     UserManager.DISALLOW_CELLULAR_2G);
 
     //TODO(b/295504706) : Speak to security team to decide what to set Policy_Size_Limit
-    private static final int DEFAULT_POLICY_SIZE_LIMIT = -1;
+    static final int DEFAULT_POLICY_SIZE_LIMIT = -1;
 
     private final Context mContext;
     private final UserManager mUserManager;
@@ -225,7 +225,7 @@
 
         synchronized (mLock) {
             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
-            if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 if (!handleAdminPolicySizeLimit(localPolicyState, enforcingAdmin, value,
                         policyDefinition, userId)) {
                     return;
@@ -350,7 +350,7 @@
             }
             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
 
-            if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 decreasePolicySizeForAdmin(localPolicyState, enforcingAdmin);
             }
 
@@ -496,7 +496,7 @@
 
         synchronized (mLock) {
             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
-            if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 if (!handleAdminPolicySizeLimit(globalPolicyState, enforcingAdmin, value,
                         policyDefinition, UserHandle.USER_ALL)) {
                     return;
@@ -568,7 +568,7 @@
         synchronized (mLock) {
             PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
 
-            if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 decreasePolicySizeForAdmin(policyState, enforcingAdmin);
             }
 
@@ -1598,6 +1598,7 @@
             existingPolicySize = sizeOf(policyState.getPoliciesSetByAdmins().get(admin));
         }
         int policySize = sizeOf(value);
+
         // Policy size limit is disabled if mPolicySizeLimit is -1.
         if (mPolicySizeLimit == -1
                 || currentAdminPoliciesSize + policySize - existingPolicySize < mPolicySizeLimit) {
@@ -1635,15 +1636,14 @@
      * active policies for that admin.
      */
     private <V> void decreasePolicySizeForAdmin(PolicyState<V> policyState, EnforcingAdmin admin) {
-        if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
-            mAdminPolicySize.get(admin.getUserId()).put(admin,
-                    mAdminPolicySize.get(admin.getUserId()).get(admin) - sizeOf(
-                            policyState.getPoliciesSetByAdmins().get(admin)));
-        }
-        if (!mAdminPolicySize.contains(admin.getUserId())
+        if (!policyState.getPoliciesSetByAdmins().containsKey(admin)
+                || !mAdminPolicySize.contains(admin.getUserId())
                 || !mAdminPolicySize.get(admin.getUserId()).containsKey(admin)) {
             return;
         }
+        mAdminPolicySize.get(admin.getUserId()).put(admin,
+                mAdminPolicySize.get(admin.getUserId()).get(admin) - sizeOf(
+                        policyState.getPoliciesSetByAdmins().get(admin)));
         if (mAdminPolicySize.get(admin.getUserId()).get(admin) <= 0) {
             mAdminPolicySize.get(admin.getUserId()).remove(admin);
         }
@@ -1657,10 +1657,6 @@
      * the limitation.
      */
     void setMaxPolicyStorageLimit(int storageLimit) {
-        if (storageLimit < DEFAULT_POLICY_SIZE_LIMIT && storageLimit != -1) {
-            throw new IllegalArgumentException("Can't set a size limit less than the minimum "
-                    + "allowed size.");
-        }
         mPolicySizeLimit = storageLimit;
     }
 
@@ -1672,6 +1668,15 @@
         return mPolicySizeLimit;
     }
 
+    int getPolicySizeForAdmin(EnforcingAdmin admin) {
+        if (mAdminPolicySize.contains(admin.getUserId())
+                && mAdminPolicySize.get(
+                admin.getUserId()).containsKey(admin)) {
+            return mAdminPolicySize.get(admin.getUserId()).get(admin);
+        }
+        return 0;
+    }
+
     public void dump(IndentingPrintWriter pw) {
         synchronized (mLock) {
             pw.println("Local Policies: ");
@@ -1698,6 +1703,25 @@
                 pw.println();
             }
             pw.decreaseIndent();
+            if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
+                pw.println();
+
+                pw.println("Default admin policy size limit: " + DEFAULT_POLICY_SIZE_LIMIT);
+                pw.println("Current admin policy size limit: " + mPolicySizeLimit);
+                pw.println("Admin Policies size: ");
+                for (int i = 0; i < mAdminPolicySize.size(); i++) {
+                    int userId = mAdminPolicySize.keyAt(i);
+                    pw.printf("User %d:\n", userId);
+                    pw.increaseIndent();
+                    for (EnforcingAdmin admin : mAdminPolicySize.get(userId).keySet()) {
+                        pw.printf("Admin : " + admin + " : " + mAdminPolicySize.get(userId).get(
+                                admin));
+                        pw.println();
+                    }
+                    pw.decreaseIndent();
+                }
+                pw.decreaseIndent();
+            }
         }
     }
 
@@ -1906,7 +1930,7 @@
 
         private void writeEnforcingAdminSizeInner(TypedXmlSerializer serializer)
                 throws IOException {
-            if (Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 if (mAdminPolicySize != null) {
                     for (int i = 0; i < mAdminPolicySize.size(); i++) {
                         int userId = mAdminPolicySize.keyAt(i);
@@ -1930,7 +1954,7 @@
 
         private void writeMaxPolicySizeInner(TypedXmlSerializer serializer)
                 throws IOException {
-            if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 return;
             }
             serializer.startTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT);
@@ -2095,7 +2119,7 @@
 
         private void readMaxPolicySizeInner(TypedXmlPullParser parser)
                 throws XmlPullParserException, IOException {
-            if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 return;
             }
             mPolicySizeLimit = parser.getAttributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b34092c..6458eac 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -76,6 +76,7 @@
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SMS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STATUS_BAR;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
@@ -106,6 +107,8 @@
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION;
+import static android.app.AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
+import static android.app.AppOpsManager.OP_RUN_IN_BACKGROUND;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
@@ -113,7 +116,6 @@
 import static android.app.admin.DeviceAdminInfo.USES_POLICY_WIPE_DATA;
 import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY;
 import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_FINANCING_STATE_CHANGED;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
@@ -268,6 +270,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
 import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
+import static com.android.server.devicepolicy.DevicePolicyEngine.DEFAULT_POLICY_SIZE_LIMIT;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -403,7 +406,6 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.media.AudioManager;
-import android.media.IAudioService;
 import android.net.ConnectivityManager;
 import android.net.ConnectivitySettingsManager;
 import android.net.IIpConnectivityMetrics;
@@ -742,7 +744,8 @@
      * These cannot be set on the managed profile's parent DPM instance
      */
     private static final int PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY =
-            DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+            DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS
+                    | DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL;
 
     /** Keyguard features that are allowed to be set on a managed profile */
     private static final int PROFILE_KEYGUARD_FEATURES =
@@ -816,6 +819,13 @@
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     public static final long THROW_SECURITY_EXCEPTION_FOR_SENSOR_PERMISSIONS = 277035314L;
 
+    /**
+     * Allows DPCs to provisioning fully managed headless devices in single-user mode.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = 35)
+    public static final long PROVISION_SINGLE_USER_MODE = 289515470L;
+
     // Only add to the end of the list. Do not change or rearrange these values, that will break
     // historical data. Do not use negative numbers or zero, logger only handles positive
     // integers.
@@ -883,10 +893,6 @@
             "enable_permission_based_access";
     private static final boolean DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG = false;
 
-    // TODO(b/266831522) remove the flag after rollout.
-    private static final String APPLICATION_EXEMPTIONS_FLAG = "application_exemptions";
-    private static final boolean DEFAULT_APPLICATION_EXEMPTIONS_FLAG = true;
-
     private static final int RETRY_COPY_ACCOUNT_ATTEMPTS = 3;
 
     /**
@@ -1762,10 +1768,6 @@
                     ServiceManager.getService(Context.BACKUP_SERVICE));
         }
 
-        IAudioService getIAudioService() {
-            return IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE));
-        }
-
         PersistentDataBlockManagerInternal getPersistentDataBlockManagerInternal() {
             return LocalServices.getService(PersistentDataBlockManagerInternal.class);
         }
@@ -1938,10 +1940,6 @@
                     name, value, userHandle);
         }
 
-        void settingsSecurePutInt(String name, int value) {
-            Settings.Secure.putInt(mContext.getContentResolver(), name, value);
-        }
-
         int settingsGlobalGetInt(String name, int def) {
             return Settings.Global.getInt(mContext.getContentResolver(), name, def);
         }
@@ -1955,10 +1953,6 @@
             Settings.Global.putInt(mContext.getContentResolver(), name, value);
         }
 
-        void settingsSecurePutString(String name, String value) {
-            Settings.Secure.putString(mContext.getContentResolver(), name, value);
-        }
-
         void settingsGlobalPutString(String name, String value) {
             Settings.Global.putString(mContext.getContentResolver(), name, value);
         }
@@ -2251,11 +2245,41 @@
                 if (userHandle == UserHandle.USER_SYSTEM) {
                     mStateCache.setDeviceProvisioned(policy.mUserSetupComplete);
                 }
+                if (Flags.headlessSingleUserBadDeviceAdminStateFix()) {
+                    fixBadDeviceAdminStateForInternalUsers(userHandle, policy);
+                }
             }
             return policy;
         }
     }
 
+    private void fixBadDeviceAdminStateForInternalUsers(int userId, DevicePolicyData policy) {
+        ComponentName component = mOwners.getDeviceOwnerComponent();
+        int doUserId = mOwners.getDeviceOwnerUserId();
+        ComponentName cloudDpc = new ComponentName(
+                "com.google.android.apps.work.clouddpc",
+                "com.google.android.apps.work.clouddpc.receivers.CloudDeviceAdminReceiver");
+        if (component == null || doUserId != userId || !component.equals(cloudDpc)) {
+            return;
+        }
+        Slogf.i(LOG_TAG, "Attempting to apply a temp fix for cloudpc internal users' bad state.");
+        final int n = policy.mAdminList.size();
+        for (int i = 0; i < n; i++) {
+            ActiveAdmin admin = policy.mAdminList.get(i);
+            if (component.equals(admin.info.getComponent())) {
+                Slogf.i(LOG_TAG, "An ActiveAdmin already exists, fix not required.");
+                return;
+            }
+        }
+        DeviceAdminInfo dai = findAdmin(component, userId, /* throwForMissingPermission= */ false);
+        if (dai != null) {
+            ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
+            policy.mAdminMap.put(ap.info.getComponent(), ap);
+            policy.mAdminList.add(ap);
+            Slogf.i(LOG_TAG, "Fix applied, an ActiveAdmin has been added.");
+        }
+    }
+
     /**
      * Creates and loads the policy data from xml for data that is shared between
      * various profiles of a user. In contrast to {@link #getUserData(int)}
@@ -2869,16 +2893,6 @@
         return poAdmin;
     }
 
-    @NonNull ActiveAdmin getOrganizationOwnedProfileOwnerLocked(final CallerIdentity caller) {
-        Preconditions.checkCallAuthorization(
-                mOwners.isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()),
-                "Caller %s is not an admin of an org-owned device",
-                caller.getComponentName());
-        final ActiveAdmin profileOwner = getProfileOwnerLocked(caller.getUserId());
-
-        return profileOwner;
-    }
-
     ActiveAdmin getProfileOwnerOrDeviceOwnerLocked(@UserIdInt int userId) {
         ensureLocked();
         // Try to find an admin which can use reqPolicy
@@ -2891,18 +2905,6 @@
         return getDeviceOwnerLocked(userId);
     }
 
-    ActiveAdmin getProfileOwnerOrDefaultDeviceOwnerLocked(@UserIdInt int userId) {
-        ensureLocked();
-        // Try to find an admin which can use reqPolicy
-        final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(userId);
-
-        if (poAdminComponent != null) {
-            return getProfileOwnerLocked(userId);
-        }
-
-        return getDefaultDeviceOwnerLocked(userId);
-    }
-
     @NonNull ActiveAdmin getParentOfAdminIfRequired(ActiveAdmin admin, boolean parent) {
         Objects.requireNonNull(admin);
         return parent ? admin.getParentActiveAdmin() : admin;
@@ -3656,26 +3658,6 @@
         mDevicePolicyEngine.handleStartUser(userId);
     }
 
-    void pushUserControlDisabledPackagesLocked(int userId) {
-        final int targetUserId;
-        final ActiveAdmin owner;
-        if (getDeviceOwnerUserIdUncheckedLocked() == userId) {
-            owner = getDeviceOwnerAdminLocked();
-            targetUserId = UserHandle.USER_ALL;
-        } else {
-            owner = getProfileOwnerAdminLocked(userId);
-            targetUserId = userId;
-        }
-
-        List<String> protectedPackages = (owner == null || owner.protectedPackages == null)
-                ? null : owner.protectedPackages;
-        mInjector.binderWithCleanCallingIdentity(() ->
-                mInjector.getPackageManagerInternal().setOwnerProtectedPackages(
-                        targetUserId, protectedPackages));
-        mUsageStatsManagerInternal.setAdminProtectedPackages(new ArraySet(protectedPackages),
-                targetUserId);
-    }
-
     void handleUnlockUser(int userId) {
         startOwnerService(userId, "unlock-user");
         mDevicePolicyEngine.handleUnlockUser(userId);
@@ -3924,7 +3906,7 @@
         if (policy.mPasswordOwner == oldAdminUid) {
             policy.mPasswordOwner = adminToTransfer.getUid();
         }
-
+        transferSubscriptionOwnership(outgoingReceiver, incomingReceiver);
         saveSettingsLocked(userHandle);
         sendAdminCommandLocked(adminToTransfer, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                 null, null);
@@ -4435,25 +4417,6 @@
      * <ul>
      * <li>The active admins associated with the userHandle itself</li>
      * <li>The parent active admins for each managed profile associated with the userHandle</li>
-     * </ul>
-     *
-     * @param userHandle the affected user for whom to get the active admins
-     * @return the list of active admins for the affected user
-     */
-    @GuardedBy("getLockObject()")
-    private List<ActiveAdmin> getActiveAdminsForAffectedUserLocked(int userHandle) {
-        if (isManagedProfile(userHandle)) {
-            return getUserDataUnchecked(userHandle).mAdminList;
-        }
-        return getActiveAdminsForUserAndItsManagedProfilesLocked(userHandle,
-                /* shouldIncludeProfileAdmins */ (user) -> false);
-    }
-
-    /**
-     * Get the list of active admins for an affected user:
-     * <ul>
-     * <li>The active admins associated with the userHandle itself</li>
-     * <li>The parent active admins for each managed profile associated with the userHandle</li>
      * <li>The permission based admin associated with the userHandle itself</li>
      * </ul>
      *
@@ -6823,7 +6786,10 @@
 
         // If there is a profile owner, redirect to that; otherwise query the device owner.
         ComponentName aliasChooser = getProfileOwnerAsUser(caller.getUserId());
-        if (aliasChooser == null && caller.getUserHandle().isSystem()) {
+        boolean isDoUser = Flags.headlessSingleUserFixes()
+                ? caller.getUserId() == getDeviceOwnerUserId()
+                : caller.getUserHandle().isSystem();
+        if (aliasChooser == null && isDoUser) {
             synchronized (getLockObject()) {
                 final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
                 if (deviceOwnerAdmin != null) {
@@ -7817,7 +7783,12 @@
         mInjector.binderWithCleanCallingIdentity(() -> {
             // First check whether the admin is allowed to wipe the device/user/profile.
             final String restriction;
-            if (userId == UserHandle.USER_SYSTEM) {
+            boolean shouldFactoryReset = userId == UserHandle.USER_SYSTEM;
+            if (Flags.headlessSingleUserFixes() && getHeadlessDeviceOwnerModeForDeviceOwner()
+                    == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
+                shouldFactoryReset = userId == getMainUserId();
+            }
+            if (shouldFactoryReset) {
                 restriction = UserManager.DISALLOW_FACTORY_RESET;
             } else if (isManagedProfile(userId)) {
                 restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
@@ -7831,12 +7802,15 @@
         });
 
         boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
+        boolean isMainUser = userId == getMainUserId();
         boolean wipeDevice;
         if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
                 adminPackage,
                 userId)) {
             // Legacy mode
-            wipeDevice = isSystemUser;
+            wipeDevice = Flags.headlessSingleUserFixes()
+                    && getHeadlessDeviceOwnerModeForDeviceOwner()
+                    == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser;
         } else {
             // Explicit behaviour
             if (factoryReset) {
@@ -8174,6 +8148,7 @@
                             userHandle, /* parent= */ false);
                     int max = strictestAdmin != null
                             ? strictestAdmin.maximumFailedPasswordsForWipe : 0;
+
                     if (max > 0 && policy.mFailedPasswordAttempts >= max) {
                         wipeData = true;
                     }
@@ -8658,17 +8633,6 @@
                 .write();
     }
 
-    // Set the latest screen capture policy, overriding any existing ones.
-    // userHandle can be one of USER_ALL, USER_NULL or a concrete userId.
-    private void setScreenCaptureDisabled(int userHandle) {
-        int current = mPolicyCache.getScreenCaptureDisallowedUser();
-        if (userHandle == current) {
-            return;
-        }
-        mPolicyCache.setScreenCaptureDisallowedUser(userHandle);
-        updateScreenCaptureDisabled();
-    }
-
     /**
      * Returns whether or not screen capture is disabled for  any active admin.
      */
@@ -9885,16 +9849,6 @@
         return doOrPo;
     }
 
-    ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(int userId) {
-        ensureLocked();
-        ActiveAdmin admin = getDeviceOwnerAdminLocked();
-        if (admin != null) {
-            return admin;
-        }
-        admin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
-        return admin != null ? admin.getParentActiveAdmin() : null;
-    }
-
     @Override
     public void clearDeviceOwner(String packageName) {
         Objects.requireNonNull(packageName, "packageName is null");
@@ -10223,13 +10177,6 @@
         return mInjector.hasUserSetupCompleted(getUserData(userHandle));
     }
 
-    private boolean hasPaired(int userHandle) {
-        if (!mHasFeature) {
-            return true;
-        }
-        return getUserData(userHandle).mPaired;
-    }
-
     @Override
     public int getUserProvisioningState(int userHandle) {
         if (!mHasFeature) {
@@ -11024,16 +10971,6 @@
         return enforcingAdmin;
     }
 
-    private void enforceCanCallLockTaskLocked(CallerIdentity caller) {
-        Preconditions.checkCallAuthorization(isProfileOwner(caller)
-                || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
-
-        final int userId =  caller.getUserId();
-        if (!canDPCManagedUserUseLockTaskLocked(userId)) {
-            throw new SecurityException("User " + userId + " is not allowed to use lock task");
-        }
-    }
-
     private boolean isSystemUid(CallerIdentity caller) {
         return UserHandle.isSameApp(caller.getUid(), Process.SYSTEM_UID);
     }
@@ -11509,10 +11446,17 @@
 
     @Override
     public void setApplicationRestrictions(ComponentName who, String callerPackage,
-            String packageName, Bundle restrictions) {
+            String packageName, Bundle restrictions, boolean parent) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_APPLICATION_RESTRICTIONS);
 
+        // This check is eventually made in UMS, checking here to fail early.
+        String validationResult =
+                FrameworkParsingPackageUtils.validateName(packageName, false, false);
+        if (validationResult != null) {
+            throw new IllegalArgumentException("Invalid package name: " + validationResult);
+        }
+
         if (isUnicornFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     who,
@@ -11520,12 +11464,6 @@
                     caller.getPackageName(),
                     caller.getUserId()
             );
-            // This check is eventually made in UMS, checking here to fail early.
-            String validationResult =
-                    FrameworkParsingPackageUtils.validateName(packageName, false, false);
-            if (validationResult != null) {
-                throw new IllegalArgumentException("Invalid package name: " + validationResult);
-            }
 
             if (restrictions == null || restrictions.isEmpty()) {
                 mDevicePolicyEngine.removeLocalPolicy(
@@ -11541,6 +11479,57 @@
             }
             setBackwardsCompatibleAppRestrictions(
                     caller, packageName, restrictions, caller.getUserHandle());
+        } else if (Flags.dmrhCanSetAppRestriction()) {
+            final boolean isRoleHolder;
+            if (who != null) {
+                // DO or PO
+                Preconditions.checkCallAuthorization(
+                        (isProfileOwner(caller) || isDefaultDeviceOwner(caller)));
+                Preconditions.checkCallAuthorization(!parent,
+                        "DO or PO cannot call this on parent");
+                // Caller has opted to be treated as DPC (by passing a non-null who), so don't
+                // consider it as the DMRH, even if the caller is both the DPC and the DMRH.
+                isRoleHolder = false;
+            } else {
+                // Delegates, or the DMRH. Only DMRH can call this on COPE parent
+                isRoleHolder = isCallerDevicePolicyManagementRoleHolder(caller);
+                if (parent) {
+                    Preconditions.checkCallAuthorization(isRoleHolder);
+                    Preconditions.checkState(isOrganizationOwnedDeviceWithManagedProfile(),
+                            "Role Holder can only operate parent app restriction on COPE devices");
+                } else {
+                    Preconditions.checkCallAuthorization(isRoleHolder
+                            || isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS));
+                }
+            }
+            // DMRH caller uses policy engine, others still use legacy code path
+            if (isRoleHolder) {
+                EnforcingAdmin enforcingAdmin = getEnforcingAdminForCaller(/* who */ null,
+                        caller.getPackageName());
+                int affectedUserId = parent
+                        ? getProfileParentId(caller.getUserId()) : caller.getUserId();
+                if (restrictions == null || restrictions.isEmpty()) {
+                    mDevicePolicyEngine.removeLocalPolicy(
+                            PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
+                            enforcingAdmin,
+                            affectedUserId);
+                } else {
+                    mDevicePolicyEngine.setLocalPolicy(
+                            PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
+                            enforcingAdmin,
+                            new BundlePolicyValue(restrictions),
+                            affectedUserId);
+                }
+                Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
+                changeIntent.setPackage(packageName);
+                changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(affectedUserId));
+            } else {
+                mInjector.binderWithCleanCallingIdentity(() -> {
+                    mUserManager.setApplicationRestrictions(packageName, restrictions,
+                            caller.getUserHandle());
+                });
+            }
         } else {
             Preconditions.checkCallAuthorization((caller.hasAdminComponent()
                     && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
@@ -12086,7 +12075,7 @@
         }
 
         if (packageList != null) {
-            if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+            if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
                 for (String pkg : packageList) {
                     PolicySizeVerifier.enforceMaxPackageNameLength(pkg);
                 }
@@ -12331,7 +12320,8 @@
         if (Flags.headlessDeviceOwnerSingleUserEnabled()) {
             // Block this method if the device is in headless main user mode
             Preconditions.checkCallAuthorization(
-                    getHeadlessDeviceOwnerModeForDeviceOwner()
+                    !mInjector.userManagerIsHeadlessSystemUserMode()
+                            || getHeadlessDeviceOwnerModeForDeviceOwner()
                             != HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER,
                     "createAndManageUser was called while in headless single user mode");
         }
@@ -12823,7 +12813,7 @@
         Slogf.i(LOG_TAG, "Stopping user %d", userId);
         final long id = mInjector.binderClearCallingIdentity();
         try {
-            switch (mInjector.getIActivityManager().stopUser(userId, true /*force*/, null)) {
+            switch (mInjector.getIActivityManager().stopUserWithCallback(userId, null)) {
                 case ActivityManager.USER_OP_SUCCESS:
                     return UserManager.USER_OPERATION_SUCCESS;
                 case ActivityManager.USER_OP_IS_CURRENT:
@@ -12872,7 +12862,7 @@
 
     @Override
     public Bundle getApplicationRestrictions(ComponentName who, String callerPackage,
-            String packageName) {
+            String packageName, boolean parent) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
 
         if (isUnicornFlagEnabled()) {
@@ -12891,6 +12881,50 @@
                 return Bundle.EMPTY;
             }
             return policies.get(enforcingAdmin).getValue();
+        } else if (Flags.dmrhCanSetAppRestriction()) {
+            final boolean isRoleHolder;
+            if (who != null) {
+                // Caller is DO or PO. They cannot call this on parent
+                Preconditions.checkCallAuthorization(!parent
+                        && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)));
+                // Caller has opted to be treated as DPC (by passing a non-null who), so don't
+                // consider it as the DMRH, even if the caller is both the DPC and the DMRH.
+                isRoleHolder = false;
+            } else {
+                // Caller is delegates or the DMRH. Only DMRH can call this on parent
+                isRoleHolder = isCallerDevicePolicyManagementRoleHolder(caller);
+                if (parent) {
+                    Preconditions.checkCallAuthorization(isRoleHolder);
+                    Preconditions.checkState(isOrganizationOwnedDeviceWithManagedProfile(),
+                            "Role Holder can only operate parent app restriction on COPE devices");
+                } else {
+                    Preconditions.checkCallAuthorization(isRoleHolder
+                            || isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS));
+                }
+            }
+            if (isRoleHolder) {
+                EnforcingAdmin enforcingAdmin = getEnforcingAdminForCaller(/* who */ null,
+                        caller.getPackageName());
+                int affectedUserId = parent
+                        ? getProfileParentId(caller.getUserId()) : caller.getUserId();
+                LinkedHashMap<EnforcingAdmin, PolicyValue<Bundle>> policies =
+                        mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
+                                PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
+                                affectedUserId);
+                if (!policies.containsKey(enforcingAdmin)) {
+                    return Bundle.EMPTY;
+                }
+                return policies.get(enforcingAdmin).getValue();
+            } else {
+                return mInjector.binderWithCleanCallingIdentity(() -> {
+                    Bundle bundle = mUserManager.getApplicationRestrictions(packageName,
+                            caller.getUserHandle());
+                    // if no restrictions were saved, mUserManager.getApplicationRestrictions
+                    // returns null, but DPM method should return an empty Bundle as per JavaDoc
+                    return bundle != null ? bundle : Bundle.EMPTY;
+                });
+            }
+
         } else {
             Preconditions.checkCallAuthorization((caller.hasAdminComponent()
                     && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
@@ -13817,7 +13851,7 @@
             return;
         }
 
-        if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             PolicySizeVerifier.enforceMaxStringLength(accountType, "account type");
         }
 
@@ -14431,7 +14465,7 @@
     public void setLockTaskPackages(ComponentName who, String callerPackageName, String[] packages)
             throws SecurityException {
         Objects.requireNonNull(packages, "packages is null");
-        if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             for (String pkg : packages) {
                 PolicySizeVerifier.enforceMaxPackageNameLength(pkg);
             }
@@ -14469,15 +14503,6 @@
         }
     }
 
-    private void setLockTaskPackagesLocked(int userHandle, List<String> packages) {
-        DevicePolicyData policy = getUserData(userHandle);
-        policy.mLockTaskPackages = packages;
-
-        // Store the settings persistently.
-        saveSettingsLocked(userHandle);
-        updateLockTaskPackagesLocked(mContext, packages, userHandle);
-    }
-
     @Override
     public String[] getLockTaskPackages(ComponentName who, String callerPackageName) {
         CallerIdentity caller = getCallerIdentity(who, callerPackageName);
@@ -14527,7 +14552,6 @@
             "Cannot use LOCK_TASK_FEATURE_NOTIFICATIONS without LOCK_TASK_FEATURE_HOME");
 
         CallerIdentity caller = getCallerIdentity(who, callerPackageName);
-        final int userHandle = caller.getUserId();
         synchronized (getLockObject()) {
             checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES);
         }
@@ -14563,13 +14587,6 @@
         }
     }
 
-    private void setLockTaskFeaturesLocked(int userHandle, int flags) {
-        DevicePolicyData policy = getUserData(userHandle);
-        policy.mLockTaskFeatures = flags;
-        saveSettingsLocked(userHandle);
-        updateLockTaskFeaturesLocked(flags, userHandle);
-    }
-
     @Override
     public int getLockTaskFeatures(ComponentName who, String callerPackageName) {
         CallerIdentity caller = getCallerIdentity(who, callerPackageName);
@@ -15784,14 +15801,6 @@
         }
 
         @Override
-        public boolean isApplicationExemptionsFlagEnabled() {
-            return DeviceConfig.getBoolean(
-                    NAMESPACE_DEVICE_POLICY_MANAGER,
-                    APPLICATION_EXEMPTIONS_FLAG,
-                    DEFAULT_APPLICATION_EXEMPTIONS_FLAG);
-        }
-
-        @Override
         public List<Bundle> getApplicationRestrictionsPerAdminForUser(
                 String packageName, @UserIdInt int userId) {
             if (UserHandle.getCallingUserId() != userId
@@ -15811,19 +15820,16 @@
             for (EnforcingAdmin admin : policies.keySet()) {
                 restrictions.add(policies.get(admin).getValue());
             }
-            if (!restrictions.isEmpty()) {
-                return restrictions;
-            }
 
             return mInjector.binderWithCleanCallingIdentity(() -> {
-                // Could be a device that has a DPC that hasn't migrated yet, so just return any
+                // Could be a device that has a DPC that hasn't migrated yet, so also return any
                 // restrictions saved in userManager.
                 Bundle bundle = mUserManager.getApplicationRestrictions(
                         packageName, UserHandle.of(userId));
-                if (bundle == null || bundle.isEmpty()) {
-                    return new ArrayList<>();
+                if (bundle != null && !bundle.isEmpty()) {
+                    restrictions.add(bundle);
                 }
-                return List.of(bundle);
+                return restrictions;
             });
         }
 
@@ -16056,29 +16062,6 @@
         }
     }
 
-
-    /**
-     *  Excludes restrictions imposed by UserManager.
-     */
-    private List<UserManager.EnforcingUser> getDevicePolicySources(
-            List<UserManager.EnforcingUser> sources) {
-        int sizeBefore = sources.size();
-        List<UserManager.EnforcingUser> realSources = new ArrayList<>(sizeBefore);
-        for (int i = 0; i < sizeBefore; i++) {
-            UserManager.EnforcingUser source = sources.get(i);
-            int type = source.getUserRestrictionSource();
-            if (type != UserManager.RESTRICTION_SOURCE_PROFILE_OWNER
-                    && type != UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
-                // TODO(b/128928355): add unit test
-                Slogf.d(LOG_TAG, "excluding source of type %s at index %d",
-                        userRestrictionSourceToString(type), i);
-                continue;
-            }
-            realSources.add(source);
-        }
-        return realSources;
-    }
-
     private static String userRestrictionSourceToString(@UserRestrictionSource int source) {
         return DebugUtils.flagsToString(UserManager.class, "RESTRICTION_", source);
     }
@@ -18302,6 +18285,14 @@
         Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
                 || isProfileOwner(caller) || isFinancedDeviceOwner(caller));
 
+        // Backup service has to be enabled on the main user in order for it to be enabled on
+        // secondary users.
+        if (Flags.headlessSingleUserFixes() && isDeviceOwner(caller)
+                && getHeadlessDeviceOwnerModeForDeviceOwner()
+                == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
+            toggleBackupServiceActive(UserHandle.USER_SYSTEM, enabled);
+        }
+
         toggleBackupServiceActive(caller.getUserId(), enabled);
 
         if (Flags.backupServiceSecurityLogEventEnabled()) {
@@ -19375,6 +19366,21 @@
                 .write();
     }
 
+    private void transferSubscriptionOwnership(ComponentName admin, ComponentName target) {
+        if (Flags.esimManagementEnabled()) {
+            SubscriptionManager subscriptionManager = mContext.getSystemService(
+                    SubscriptionManager.class);
+            for (int subId : getSubscriptionIdsInternal(admin.getPackageName()).toArray()) {
+                try {
+                    subscriptionManager.setGroupOwner(subId, target.getPackageName());
+                } catch (Exception e) {
+                    // Shouldn't happen.
+                    Slogf.e(LOG_TAG, e, "Error setting group owner for subId: " + subId);
+                }
+            }
+        }
+    }
+
     private void prepareTransfer(ComponentName admin, ComponentName target,
             PersistableBundle bundle, int callingUserId, String adminType) {
         saveTransferOwnershipBundleLocked(bundle, callingUserId);
@@ -20252,34 +20258,47 @@
                 hasCallingOrSelfPermission(permission.MANAGE_DEVICE_POLICY_APP_EXEMPTIONS));
 
         final CallerIdentity caller = getCallerIdentity(callerPackage);
-        final ApplicationInfo packageInfo;
-        packageInfo = getPackageInfoWithNullCheck(packageName, caller);
+        final AppOpsManager appOpsMgr = mInjector.getAppOpsManager();
+        final ApplicationInfo appInfo = getPackageInfoWithNullCheck(packageName, caller);
+        final int uid = appInfo.uid;
 
-        for (Map.Entry<Integer, String> entry :
-                APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.entrySet()) {
-            int currentMode = mInjector.getAppOpsManager().unsafeCheckOpNoThrow(
-                    entry.getValue(), packageInfo.uid, packageInfo.packageName);
-            int newMode = ArrayUtils.contains(exemptions, entry.getKey())
-                    ? MODE_ALLOWED : MODE_DEFAULT;
-            mInjector.binderWithCleanCallingIdentity(() -> {
+        mInjector.binderWithCleanCallingIdentity(() -> {
+            APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.forEach((exemption, appOp) -> {
+                int currentMode = appOpsMgr.unsafeCheckOpNoThrow(appOp, uid, packageName);
+                int newMode = ArrayUtils.contains(exemptions, exemption)
+                        ? MODE_ALLOWED : MODE_DEFAULT;
                 if (currentMode != newMode) {
-                    mInjector.getAppOpsManager()
-                            .setMode(entry.getValue(),
-                                    packageInfo.uid,
-                                    packageName,
-                                    newMode);
+                    appOpsMgr.setMode(appOp, uid, packageName, newMode);
+
+                    // If the user has already disabled background usage for the package, it won't
+                    // have OP_RUN_ANY_IN_BACKGROUND app op and won't execute in the background. The
+                    // code below grants that app op, and once the exemption is in place, the user
+                    // won't be able to disable background usage anymore.
+                    if (Flags.powerExemptionBgUsageFix()
+                            && exemption == EXEMPT_FROM_POWER_RESTRICTIONS
+                            && newMode == MODE_ALLOWED) {
+                        setBgUsageAppOp(appOpsMgr, appInfo);
+                    }
                 }
             });
-        }
+        });
+
         String[] appOpExemptions = new String[exemptions.length];
         for (int i = 0; i < exemptions.length; i++) {
             appOpExemptions[i] = APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.get(exemptions[i]);
         }
         DevicePolicyEventLogger
-            .createEvent(DevicePolicyEnums.SET_APPLICATION_EXEMPTIONS)
-            .setAdmin(caller.getPackageName())
-            .setStrings(packageName, appOpExemptions)
-            .write();
+                .createEvent(DevicePolicyEnums.SET_APPLICATION_EXEMPTIONS)
+                .setAdmin(caller.getPackageName())
+                .setStrings(packageName, appOpExemptions)
+                .write();
+    }
+
+    static void setBgUsageAppOp(AppOpsManager appOpsMgr, ApplicationInfo appInfo) {
+        appOpsMgr.setMode(OP_RUN_ANY_IN_BACKGROUND, appInfo.uid, appInfo.packageName, MODE_ALLOWED);
+        if (appInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+            appOpsMgr.setMode(OP_RUN_IN_BACKGROUND, appInfo.uid, appInfo.packageName, MODE_ALLOWED);
+        }
     }
 
     @Override
@@ -20719,17 +20738,6 @@
         }
     }
 
-    private void suspendPersonalAppsInPackageManager(int userId) {
-        mInjector.binderWithCleanCallingIdentity(() -> {
-            final String[] appsToSuspend = mInjector.getPersonalAppsForSuspension(userId);
-            final String[] failedApps = mInjector.getPackageManagerInternal()
-                    .setPackagesSuspendedByAdmin(userId, appsToSuspend, true);
-            if (!ArrayUtils.isEmpty(failedApps)) {
-                Slogf.wtf(LOG_TAG, "Failed to suspend apps: " + String.join(",", failedApps));
-            }
-        });
-    }
-
     private void notifyIfManagedSubscriptionsAreUnavailable(
             UserHandle managedProfile, boolean managedProfileAvailable) {
         if (!isManagedProfile(managedProfile.getIdentifier())) {
@@ -21621,7 +21629,7 @@
         Objects.requireNonNull(deviceAdmin, "admin is null.");
         Objects.requireNonNull(provisioningParams.getOwnerName(), "owner name is null.");
 
-        final CallerIdentity caller = getCallerIdentity();
+        final CallerIdentity caller = getCallerIdentity(callerPackage);
         Preconditions.checkCallAuthorization(
                 hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
                         || (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE)
@@ -21631,6 +21639,23 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
+            boolean isSingleUserMode;
+            if (Flags.headlessDeviceOwnerProvisioningFixEnabled()) {
+                int headlessDeviceOwnerMode = getHeadlessDeviceOwnerModeForDeviceAdmin(
+                        deviceAdmin, caller.getUserId());
+                isSingleUserMode =
+                        headlessDeviceOwnerMode == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
+            } else {
+                isSingleUserMode =
+                        getHeadlessDeviceOwnerModeForDeviceOwner()
+                                == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
+            }
+
+            if (Flags.headlessSingleUserFixes() && isSingleUserMode && !mInjector.isChangeEnabled(
+                    PROVISION_SINGLE_USER_MODE, deviceAdmin.getPackageName(), caller.getUserId())) {
+                throw new IllegalStateException("Device admin is not targeting Android V.");
+            }
+
             int result = checkProvisioningPreconditionSkipPermission(
                     ACTION_PROVISION_MANAGED_DEVICE, deviceAdmin, caller.getUserId());
             if (result != STATUS_OK) {
@@ -21644,17 +21669,6 @@
             setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime());
             setLocale(provisioningParams.getLocale());
 
-            boolean isSingleUserMode;
-            if (Flags.headlessDeviceOwnerProvisioningFixEnabled()) {
-                int headlessDeviceOwnerMode = getHeadlessDeviceOwnerModeForDeviceAdmin(
-                        deviceAdmin, caller.getUserId());
-                isSingleUserMode =
-                        headlessDeviceOwnerMode == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
-            } else {
-                isSingleUserMode =
-                        getHeadlessDeviceOwnerModeForDeviceOwner()
-                                == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
-            }
             int deviceOwnerUserId = Flags.headlessDeviceOwnerSingleUserEnabled()
                     && isSingleUserMode
                     ? mUserManagerInternal.getMainUserId() : UserHandle.USER_SYSTEM;
@@ -23172,14 +23186,6 @@
         return getEnforcingAdminForCaller(admin, callerPackageName);
     }
 
-    private static final HashMap<String, String> POLICY_IDENTIFIER_TO_PERMISSION = new HashMap<>();
-    {
-        POLICY_IDENTIFIER_TO_PERMISSION.put(AUTO_TIMEZONE_POLICY, SET_TIME_ZONE);
-    }
-
-    private static final HashMap<String, Integer> POLICY_IDENTIFIER_TO_ACTIVE_ADMIN_POLICY =
-            new HashMap<>();
-
     /**
      * Checks if the calling process has been granted permission to apply a device policy.
      *
@@ -23198,7 +23204,6 @@
         }
     }
 
-
     /**
      * Checks if the calling process has been granted permission to apply a device policy on a
      * specific user. Only one permission provided in the list needs to be granted to pass this
@@ -23315,10 +23320,12 @@
     }
 
     private boolean hasAdminPolicy(int adminPolicy, String callerPackageName) {
-        CallerIdentity caller = getCallerIdentity(callerPackageName);
-        ActiveAdmin deviceAdmin = getActiveAdminWithPolicyForUidLocked(
-                null, adminPolicy, caller.getUid());
-        return deviceAdmin != null;
+        synchronized (getLockObject()) {
+            CallerIdentity caller = getCallerIdentity(callerPackageName);
+            ActiveAdmin deviceAdmin = getActiveAdminWithPolicyForUidLocked(
+                    null, adminPolicy, caller.getUid());
+            return deviceAdmin != null;
+        }
     }
 
     /**
@@ -24298,52 +24305,6 @@
         }
     }
 
-    // We need to add a mapping of policyId to permission in POLICY_IDENTIFIER_TO_PERMISSION
-    // for each migrated permission.
-    private List<ActiveAdmin> getNonDPCActiveAdminsForPolicyLocked(String policyIdentifier) {
-        Integer activeAdminPolicy = POLICY_IDENTIFIER_TO_ACTIVE_ADMIN_POLICY.get(policyIdentifier);
-        if (activeAdminPolicy == null) {
-            Slogf.e(LOG_TAG,
-                    "Can't find a active admin policy for %s in POLICY_IDENTIFIER_TO_PERMISSION",
-                    policyIdentifier);
-            return new ArrayList<>();
-        }
-
-        List<ActiveAdmin> admins = new ArrayList<>();
-        for (UserInfo userInfo : mUserManager.getUsers()) {
-            List<ComponentName> activeAdmins = getActiveAdmins(userInfo.id);
-            for (ComponentName admin : activeAdmins) {
-                if (isDeviceOwner(admin, userInfo.id) || isProfileOwner(admin, userInfo.id)) {
-                    continue;
-                }
-                DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
-                if (isActiveAdminWithPolicyForUserLocked(
-                        policy.mAdminMap.get(admin), activeAdminPolicy,
-                        userInfo.id)) {
-                    admins.add(policy.mAdminMap.get(admin));
-                }
-            }
-        }
-        return admins;
-    }
-
-    // TODO: this can actually accept an EnforcingAdmin that gets created in the permission
-    //  check method.
-    private boolean isCallerActiveAdminOrDelegate(
-            CallerIdentity caller, @Nullable String delegateScope) {
-        return mInjector.binderWithCleanCallingIdentity(() -> {
-            List<ComponentName> activeAdmins = getActiveAdmins(caller.getUserId());
-            if (activeAdmins != null) {
-                for (ComponentName admin : activeAdmins) {
-                    if (admin.getPackageName().equals(caller.getPackageName())) {
-                        return true;
-                    }
-                }
-            }
-            return delegateScope != null && isCallerDelegate(caller, delegateScope);
-        });
-    }
-
     private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who,
             CallerIdentity caller) {
         synchronized (getLockObject()) {
@@ -24443,19 +24404,23 @@
 
     @Override
     public void setMaxPolicyStorageLimit(String callerPackageName, int storageLimit) {
-        if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             return;
         }
         CallerIdentity caller = getCallerIdentity(callerPackageName);
         enforcePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS, caller.getPackageName(),
                 caller.getUserId());
 
+        if (storageLimit < DEFAULT_POLICY_SIZE_LIMIT && storageLimit != -1) {
+            throw new IllegalArgumentException("Can't set a size limit less than the minimum "
+                    + "allowed size.");
+        }
         mDevicePolicyEngine.setMaxPolicyStorageLimit(storageLimit);
     }
 
     @Override
     public int getMaxPolicyStorageLimit(String callerPackageName) {
-        if (!Flags.devicePolicySizeTrackingInternalEnabled()) {
+        if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
             return -1;
         }
         CallerIdentity caller = getCallerIdentity(callerPackageName);
@@ -24466,6 +24431,32 @@
     }
 
     @Override
+    public void forceSetMaxPolicyStorageLimit(String callerPackageName, int storageLimit) {
+        if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
+            return;
+        }
+        CallerIdentity caller = getCallerIdentity(callerPackageName);
+        enforcePermission(MANAGE_DEVICE_POLICY_STORAGE_LIMIT, caller.getPackageName(),
+                caller.getUserId());
+
+        mDevicePolicyEngine.setMaxPolicyStorageLimit(storageLimit);
+    }
+
+    @Override
+    public int getPolicySizeForAdmin(
+            String callerPackageName, android.app.admin.EnforcingAdmin admin) {
+        if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
+            return -1;
+        }
+        CallerIdentity caller = getCallerIdentity(callerPackageName);
+        enforcePermission(MANAGE_DEVICE_POLICY_STORAGE_LIMIT, caller.getPackageName(),
+                caller.getUserId());
+
+        return mDevicePolicyEngine.getPolicySizeForAdmin(
+                EnforcingAdmin.createEnforcingAdmin(admin));
+    }
+
+    @Override
     public int getHeadlessDeviceOwnerMode(String callerPackageName) {
         final CallerIdentity caller = getCallerIdentity(callerPackageName);
         enforcePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS, caller.getPackageName(),
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
index d234dee..02590f9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
@@ -21,6 +21,7 @@
 import android.app.admin.Authority;
 import android.app.admin.DeviceAdminAuthority;
 import android.app.admin.DpcAuthority;
+import android.app.admin.PackagePermissionPolicyKey;
 import android.app.admin.RoleAuthority;
 import android.app.admin.UnknownAuthority;
 import android.content.ComponentName;
@@ -105,6 +106,32 @@
                 userId, activeAdmin);
     }
 
+    static EnforcingAdmin createEnforcingAdmin(android.app.admin.EnforcingAdmin admin) {
+        Objects.requireNonNull(admin);
+        Authority authority = admin.getAuthority();
+        Set<String> internalAuthorities = new HashSet<>();
+        if (DpcAuthority.DPC_AUTHORITY.equals(authority)) {
+            return new EnforcingAdmin(
+                    admin.getPackageName(), admin.getComponentName(),
+                    Set.of(DPC_AUTHORITY), admin.getUserHandle().getIdentifier(),
+                    /* activeAdmin = */ null);
+        } else if (DeviceAdminAuthority.DEVICE_ADMIN_AUTHORITY.equals(authority)) {
+            return new EnforcingAdmin(
+                    admin.getPackageName(), admin.getComponentName(),
+                    Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier(),
+                    /* activeAdmin = */ null);
+        } else if (authority instanceof RoleAuthority roleAuthority) {
+            return new EnforcingAdmin(
+                    admin.getPackageName(), admin.getComponentName(),
+                    Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier(),
+                    /* activeAdmin = */ null,
+                    /* isRoleAuthority = */ true);
+        }
+        return new EnforcingAdmin(admin.getPackageName(), admin.getComponentName(),
+                Set.of(), admin.getUserHandle().getIdentifier(),
+                /* activeAdmin = */ null);
+    }
+
     static String getRoleAuthorityOf(String roleName) {
         return ROLE_AUTHORITY_PREFIX + roleName;
     }
@@ -154,6 +181,20 @@
         mActiveAdmin = activeAdmin;
     }
 
+    private EnforcingAdmin(
+            String packageName, @Nullable ComponentName componentName, Set<String> authorities,
+            int userId, @Nullable ActiveAdmin activeAdmin, boolean isRoleAuthority) {
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(authorities);
+
+        mIsRoleAuthority = isRoleAuthority;
+        mPackageName = packageName;
+        mComponentName = componentName;
+        mAuthorities = new HashSet<>(authorities);
+        mUserId = userId;
+        mActiveAdmin = activeAdmin;
+    }
+
     private static Set<String> getRoleAuthoritiesOrDefault(String packageName, int userId) {
         Set<String> roles = getRoles(packageName, userId);
         Set<String> authorities = new HashSet<>();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 94c1374..d1830126 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -215,6 +215,9 @@
         } catch (PackageManager.NameNotFoundException e) {
             return false;
         }
+        if (packageInfo.applicationInfo == null || packageInfo.applicationInfo.metaData == null) {
+            return false;
+        }
         final String metadataKey = sActionToMetadataKeyMap.get(provisioningAction);
         return packageInfo.applicationInfo.metaData.getBoolean(metadataKey);
     }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
index 42ac998..d02cfee 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
@@ -357,7 +357,8 @@
 
         @Override
         boolean shouldWrite() {
-            return (mDeviceOwner != null) || (mSystemUpdatePolicy != null)
+            return Flags.alwaysPersistDo()
+                    || (mDeviceOwner != null) || (mSystemUpdatePolicy != null)
                     || (mSystemUpdateInfo != null);
         }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index e713a82..7a9fa0f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -163,8 +163,7 @@
                     new NoArgsPolicyKey(
                             DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY),
                     new StringSetUnion(),
-                    (Set<String> value, Context context, Integer userId, PolicyKey policyKey) ->
-                            PolicyEnforcerCallbacks.setUserControlDisabledPackages(value, userId),
+                    PolicyEnforcerCallbacks::setUserControlDisabledPackages,
                     new StringSetPolicySerializer());
 
     // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
index a7adc5b..a0d9be54 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppGlobals;
+import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyCache;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
@@ -29,6 +30,7 @@
 import android.app.admin.PackagePolicyKey;
 import android.app.admin.PolicyKey;
 import android.app.admin.UserRestrictionPolicyKey;
+import android.app.admin.flags.Flags;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ComponentName;
 import android.content.Context;
@@ -37,6 +39,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -183,15 +186,31 @@
     }
 
     static boolean setUserControlDisabledPackages(
-            @Nullable Set<String> packages, int userId) {
+            @Nullable Set<String> packages, Context context, int userId, PolicyKey policyKey) {
         Binder.withCleanCallingIdentity(() -> {
-            LocalServices.getService(PackageManagerInternal.class)
-                    .setOwnerProtectedPackages(
-                            userId,
-                            packages == null ? null : packages.stream().toList());
+            PackageManagerInternal pmi =
+                    LocalServices.getService(PackageManagerInternal.class);
+            pmi.setOwnerProtectedPackages(userId,
+                    packages == null ? null : packages.stream().toList());
             LocalServices.getService(UsageStatsManagerInternal.class)
-                            .setAdminProtectedPackages(
+                    .setAdminProtectedPackages(
                             packages == null ? null : new ArraySet<>(packages), userId);
+
+            if (Flags.disallowUserControlBgUsageFix()) {
+                if (packages == null) {
+                    return;
+                }
+                final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+                for (var pkg : packages) {
+                    final var appInfo = pmi.getApplicationInfo(pkg,
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                            Process.myUid(), userId);
+                    if (appInfo != null) {
+                        DevicePolicyManagerService.setBgUsageAppOp(appOpsManager, appInfo);
+                    }
+                }
+            }
         });
         return true;
     }
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java
index 95c4407..cc5573b 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java
@@ -103,6 +103,12 @@
         final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
 
         mEnablePostureBasedClosedState = featureFlags.enableFoldablesPostureBasedClosedState();
+        if (mEnablePostureBasedClosedState) {
+            // This configuration doesn't require listening to hall sensor, it solely relies
+            // on the fused hinge angle sensor
+            hallSensor = null;
+        }
+
         mIsDualDisplayBlockingEnabled = featureFlags.enableDualDisplayBlocking();
 
         final DeviceStatePredicateWrapper[] configuration = createConfiguration(
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java
index 16daacb..aa7532a 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java
@@ -412,7 +412,7 @@
                 /* stickyKeepInnerUntil45Degrees */ true,
                 PreferredScreen.INNER,
                 /* setStickyKeepOuterUntil90Degrees */ null,
-                /* setStickyKeepInnerUntil45Degrees */ false
+                /* setStickyKeepInnerUntil45Degrees */ null
         ));
         DEFAULT_STATE_TRANSITIONS.add(new StateTransition(
                 HingeAngle.ANGLE_45_TO_90,
@@ -492,7 +492,7 @@
                 /* stickyKeepInnerUntil45Degrees */ true,
                 PreferredScreen.INNER,
                 /* setStickyKeepOuterUntil90Degrees */ null,
-                /* setStickyKeepInnerUntil45Degrees */ false
+                /* setStickyKeepInnerUntil45Degrees */ null
         ));
         DEFAULT_STATE_TRANSITIONS.add(new StateTransition(
                 HingeAngle.ANGLE_45_TO_90,
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
index bc8643f..daeaa98 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
@@ -95,6 +95,7 @@
 
     private final Sensor mHingeAngleSensor;
     private final DisplayManager mDisplayManager;
+    @Nullable
     private final Sensor mHallSensor;
     private static final Predicate<FoldableDeviceStateProvider> ALLOWED = p -> true;
 
@@ -122,7 +123,7 @@
             @NonNull Context context,
             @NonNull SensorManager sensorManager,
             @NonNull Sensor hingeAngleSensor,
-            @NonNull Sensor hallSensor,
+            @Nullable Sensor hallSensor,
             @NonNull DisplayManager displayManager,
             @NonNull DeviceStatePredicateWrapper[] deviceStatePredicateWrappers) {
         this(new FeatureFlagsImpl(), context, sensorManager, hingeAngleSensor, hallSensor,
@@ -135,7 +136,7 @@
             @NonNull Context context,
             @NonNull SensorManager sensorManager,
             @NonNull Sensor hingeAngleSensor,
-            @NonNull Sensor hallSensor,
+            @Nullable Sensor hallSensor,
             @NonNull DisplayManager displayManager,
             @NonNull DeviceStatePredicateWrapper[] deviceStatePredicateWrappers) {
 
@@ -149,7 +150,9 @@
         mIsDualDisplayBlockingEnabled = featureFlags.enableDualDisplayBlocking();
 
         sensorManager.registerListener(this, mHingeAngleSensor, SENSOR_DELAY_FASTEST);
-        sensorManager.registerListener(this, mHallSensor, SENSOR_DELAY_FASTEST);
+        if (hallSensor != null) {
+            sensorManager.registerListener(this, mHallSensor, SENSOR_DELAY_FASTEST);
+        }
 
         mOrderedStates = new DeviceState[deviceStatePredicateWrappers.length];
         for (int i = 0; i < deviceStatePredicateWrappers.length; i++) {
@@ -324,7 +327,7 @@
     @Override
     public void onSensorChanged(SensorEvent event) {
         synchronized (mLock) {
-            if (event.sensor == mHallSensor) {
+            if (mHallSensor != null && event.sensor == mHallSensor) {
                 mLastHallSensorEvent = event;
             } else if (event.sensor == mHingeAngleSensor) {
                 mLastHingeAngleSensorEvent = event;
@@ -359,11 +362,11 @@
     }
 
     @GuardedBy("mLock")
-    private void dumpSensorValues(Sensor sensor, @Nullable SensorEvent event) {
+    private void dumpSensorValues(@Nullable Sensor sensor, @Nullable SensorEvent event) {
         Slog.i(TAG, toSensorValueString(sensor, event));
     }
 
-    private String toSensorValueString(Sensor sensor, @Nullable SensorEvent event) {
+    private String toSensorValueString(@Nullable Sensor sensor, @Nullable SensorEvent event) {
         String sensorString = sensor == null ? "null" : sensor.getName();
         String eventValues = event == null ? "null" : Arrays.toString(event.values);
         return sensorString + " : " + eventValues;
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
index 6ad8d79..6393e11 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
@@ -1,6 +1,7 @@
 aconfig_declarations {
     name: "device_state_flags",
     package: "com.android.server.policy.feature.flags",
+    container: "system",
     srcs: [
         "device_state_flags.aconfig",
     ],
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
index 29e258c..21e33dd 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.policy.feature.flags"
+container: "system"
 
 flag {
     name: "enable_dual_display_blocking"
diff --git a/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java b/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java
index 901f24d..2d725d1e2 100644
--- a/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java
+++ b/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java
@@ -219,6 +219,26 @@
     }
 
     @Test
+    public void test_postureBasedClosedState_createPolicy_doesNotRegisterHallSensor() {
+        mFakeFeatureFlags.setFlag(Flags.FLAG_ENABLE_FOLDABLES_POSTURE_BASED_CLOSED_STATE, true);
+        clearInvocations(mSensorManager);
+
+        mInstrumentation.runOnMainSync(() -> mProvider = createProvider());
+
+        verify(mSensorManager, never()).registerListener(any(), eq(mHallSensor), anyInt());
+    }
+
+    @Test
+    public void test_postureBasedClosedStateDisabled_createPolicy_registersHallSensor() {
+        mFakeFeatureFlags.setFlag(Flags.FLAG_ENABLE_FOLDABLES_POSTURE_BASED_CLOSED_STATE, false);
+        clearInvocations(mSensorManager);
+
+        mInstrumentation.runOnMainSync(() -> mProvider = createProvider());
+
+        verify(mSensorManager).registerListener(any(), eq(mHallSensor), anyInt());
+    }
+
+    @Test
     public void test_noSensorEventsYet_reportOpenedState() {
         mProvider.setListener(mListener);
         verify(mListener).onStateChanged(mDeviceStateCaptor.capture());
@@ -491,7 +511,7 @@
     }
 
     @Test
-    public void test_unfoldTo60Degrees_andFoldTo10_switchesToClosedState() {
+    public void test_unfoldTo60Degrees_andFoldTo10_doesNotSwitchToClosedState() {
         sendHingeAngle(0f);
         sendRightSideFlatSensorEvent(false);
         mProvider.setListener(mListener);
@@ -502,6 +522,36 @@
 
         sendHingeAngle(10f);
 
+        verify(mListener, never()).onStateChanged(anyInt());
+    }
+
+    @Test
+    public void test_unfoldTo100Degrees_andFoldTo10_switchesToClosedState() {
+        sendHingeAngle(0f);
+        sendRightSideFlatSensorEvent(false);
+        mProvider.setListener(mListener);
+        assertLatestReportedState(DEVICE_STATE_CLOSED);
+        sendHingeAngle(100f);
+        assertLatestReportedState(DEVICE_STATE_HALF_OPENED);
+        clearInvocations(mListener);
+
+        sendHingeAngle(10f);
+
+        verify(mListener).onStateChanged(DEVICE_STATE_CLOSED);
+    }
+
+    @Test
+    public void test_unfoldTo10Degrees_andFoldTo0_switchesToClosedState() {
+        sendHingeAngle(0f);
+        sendRightSideFlatSensorEvent(false);
+        mProvider.setListener(mListener);
+        assertLatestReportedState(DEVICE_STATE_CLOSED);
+        sendHingeAngle(10f);
+        assertLatestReportedState(DEVICE_STATE_HALF_OPENED);
+        clearInvocations(mListener);
+
+        sendHingeAngle(0f);
+
         verify(mListener).onStateChanged(DEVICE_STATE_CLOSED);
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0a7f49d..8caf5ae 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -91,6 +91,7 @@
 import android.util.Dumpable;
 import android.util.EventLog;
 import android.util.IndentingPrintWriter;
+import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -108,29 +109,50 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockSettingsInternal;
+import com.android.server.accessibility.AccessibilityManagerService;
+import com.android.server.accounts.AccountManagerService;
 import com.android.server.adaptiveauth.AdaptiveAuthService;
+import com.android.server.adb.AdbService;
+import com.android.server.alarm.AlarmManagerService;
 import com.android.server.am.ActivityManagerService;
+import com.android.server.ambientcontext.AmbientContextManagerService;
+import com.android.server.app.GameManagerService;
 import com.android.server.appbinding.AppBindingService;
+import com.android.server.apphibernation.AppHibernationService;
 import com.android.server.appop.AppOpMigrationHelper;
 import com.android.server.appop.AppOpMigrationHelperImpl;
+import com.android.server.appprediction.AppPredictionManagerService;
+import com.android.server.appwidget.AppWidgetService;
 import com.android.server.art.ArtModuleServiceInitializer;
 import com.android.server.art.DexUseManagerLocal;
 import com.android.server.attention.AttentionManagerService;
 import com.android.server.audio.AudioService;
+import com.android.server.autofill.AutofillManagerService;
+import com.android.server.backup.BackupManagerService;
 import com.android.server.biometrics.AuthService;
 import com.android.server.biometrics.BiometricService;
 import com.android.server.biometrics.sensors.face.FaceService;
 import com.android.server.biometrics.sensors.fingerprint.FingerprintService;
 import com.android.server.biometrics.sensors.iris.IrisService;
+import com.android.server.blob.BlobStoreManagerService;
 import com.android.server.broadcastradio.BroadcastRadioService;
 import com.android.server.camera.CameraServiceProxy;
 import com.android.server.clipboard.ClipboardService;
+import com.android.server.companion.CompanionDeviceManagerService;
+import com.android.server.companion.virtual.VirtualDeviceManagerService;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.compat.PlatformCompatNative;
+import com.android.server.compat.overrides.AppCompatOverridesService;
+import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.PacProxyService;
+import com.android.server.content.ContentService;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerService;
+import com.android.server.contentsuggestions.ContentSuggestionsManagerService;
+import com.android.server.contextualsearch.ContextualSearchManagerService;
 import com.android.server.coverage.CoverageService;
 import com.android.server.cpu.CpuMonitorService;
+import com.android.server.credentials.CredentialManagerService;
 import com.android.server.criticalevents.CriticalEventLog;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
 import com.android.server.devicestate.DeviceStateManagerService;
@@ -147,14 +169,20 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.inputmethod.InputMethodManagerService;
 import com.android.server.integrity.AppIntegrityManagerService;
+import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
 import com.android.server.locales.LocaleManagerService;
 import com.android.server.location.LocationManagerService;
 import com.android.server.location.altitude.AltitudeService;
+import com.android.server.locksettings.LockSettingsService;
 import com.android.server.logcat.LogcatManagerService;
+import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
+import com.android.server.media.MediaSessionService;
 import com.android.server.media.metrics.MediaMetricsManagerService;
 import com.android.server.media.projection.MediaProjectionManagerService;
+import com.android.server.midi.MidiService;
+import com.android.server.musicrecognition.MusicRecognitionManagerService;
 import com.android.server.net.NetworkManagementService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.watchlist.NetworkWatchlistService;
@@ -195,12 +223,16 @@
 import com.android.server.power.ThermalManagerService;
 import com.android.server.power.hint.HintManagerService;
 import com.android.server.powerstats.PowerStatsService;
+import com.android.server.print.PrintManagerService;
 import com.android.server.profcollect.ProfcollectForwardingService;
 import com.android.server.recoverysystem.RecoverySystemService;
 import com.android.server.resources.ResourcesManagerService;
 import com.android.server.restrictions.RestrictionsManagerService;
 import com.android.server.role.RoleServicePlatformHelper;
+import com.android.server.rollback.RollbackManagerService;
 import com.android.server.rotationresolver.RotationResolverManagerService;
+import com.android.server.search.SearchManagerService;
+import com.android.server.searchui.SearchUiManagerService;
 import com.android.server.security.AttestationVerificationManagerService;
 import com.android.server.security.FileIntegrityService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
@@ -210,16 +242,28 @@
 import com.android.server.sensorprivacy.SensorPrivacyService;
 import com.android.server.sensors.SensorService;
 import com.android.server.signedconfig.SignedConfigService;
+import com.android.server.slice.SliceManagerService;
+import com.android.server.smartspace.SmartspaceManagerService;
 import com.android.server.soundtrigger.SoundTriggerService;
 import com.android.server.soundtrigger_middleware.SoundTriggerMiddlewareService;
+import com.android.server.speech.SpeechRecognitionManagerService;
+import com.android.server.stats.bootstrap.StatsBootstrapAtomService;
+import com.android.server.stats.pull.StatsPullAtomService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.storage.DeviceStorageMonitorService;
+import com.android.server.systemcaptions.SystemCaptionsManagerService;
 import com.android.server.telecom.TelecomLoaderService;
 import com.android.server.testharness.TestHarnessModeService;
 import com.android.server.textclassifier.TextClassificationManagerService;
 import com.android.server.textservices.TextServicesManagerService;
+import com.android.server.texttospeech.TextToSpeechManagerService;
+import com.android.server.timedetector.GnssTimeUpdateService;
 import com.android.server.timedetector.NetworkTimeUpdateService;
+import com.android.server.timedetector.TimeDetectorService;
+import com.android.server.timezonedetector.TimeZoneDetectorService;
+import com.android.server.timezonedetector.location.LocationTimeZoneManagerService;
 import com.android.server.tracing.TracingServiceProxy;
+import com.android.server.translation.TranslationManagerService;
 import com.android.server.trust.TrustManagerService;
 import com.android.server.tv.TvInputManagerService;
 import com.android.server.tv.TvRemoteService;
@@ -227,10 +271,15 @@
 import com.android.server.tv.tunerresourcemanager.TunerResourceManagerService;
 import com.android.server.twilight.TwilightService;
 import com.android.server.uri.UriGrantsManagerService;
+import com.android.server.usage.StorageStatsService;
 import com.android.server.usage.UsageStatsService;
+import com.android.server.usb.UsbService;
 import com.android.server.utils.TimingsTraceAndSlog;
 import com.android.server.vibrator.VibratorManagerService;
+import com.android.server.voiceinteraction.VoiceInteractionManagerService;
 import com.android.server.vr.VrManagerService;
+import com.android.server.wallpaper.WallpaperManagerService;
+import com.android.server.wallpapereffectsgeneration.WallpaperEffectsGenerationManagerService;
 import com.android.server.wearable.WearableSensingManagerService;
 import com.android.server.webkit.WebViewUpdateService;
 import com.android.server.wm.ActivityTaskManagerService;
@@ -265,71 +314,17 @@
     private static final long SLOW_DELIVERY_THRESHOLD_MS = 200;
 
     /*
-     * Implementation class names. TODO: Move them to a codegen class or load
-     * them from the build system somehow.
+     * Implementation class names for services in the {@code SYSTEMSERVERCLASSPATH}
+     * from {@code PRODUCT_SYSTEM_SERVER_JARS} that are *not* in {@code services.jar}.
      */
-    private static final String BACKUP_MANAGER_SERVICE_CLASS =
-            "com.android.server.backup.BackupManagerService$Lifecycle";
-    private static final String APPWIDGET_SERVICE_CLASS =
-            "com.android.server.appwidget.AppWidgetService";
     private static final String ARC_NETWORK_SERVICE_CLASS =
             "com.android.server.arc.net.ArcNetworkService";
     private static final String ARC_PERSISTENT_DATA_BLOCK_SERVICE_CLASS =
             "com.android.server.arc.persistent_data_block.ArcPersistentDataBlockService";
     private static final String ARC_SYSTEM_HEALTH_SERVICE =
             "com.android.server.arc.health.ArcSystemHealthService";
-    private static final String VOICE_RECOGNITION_MANAGER_SERVICE_CLASS =
-            "com.android.server.voiceinteraction.VoiceInteractionManagerService";
-    private static final String APP_HIBERNATION_SERVICE_CLASS =
-            "com.android.server.apphibernation.AppHibernationService";
-    private static final String PRINT_MANAGER_SERVICE_CLASS =
-            "com.android.server.print.PrintManagerService";
-    private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
-            "com.android.server.companion.CompanionDeviceManagerService";
-    private static final String VIRTUAL_DEVICE_MANAGER_SERVICE_CLASS =
-            "com.android.server.companion.virtual.VirtualDeviceManagerService";
-    private static final String STATS_COMPANION_APEX_PATH =
-            "/apex/com.android.os.statsd/javalib/service-statsd.jar";
-    private static final String SCHEDULING_APEX_PATH =
-            "/apex/com.android.scheduling/javalib/service-scheduling.jar";
-    private static final String REBOOT_READINESS_LIFECYCLE_CLASS =
-            "com.android.server.scheduling.RebootReadinessManagerService$Lifecycle";
-    private static final String CONNECTIVITY_SERVICE_APEX_PATH =
-            "/apex/com.android.tethering/javalib/service-connectivity.jar";
-    private static final String STATS_COMPANION_LIFECYCLE_CLASS =
-            "com.android.server.stats.StatsCompanion$Lifecycle";
-    private static final String STATS_PULL_ATOM_SERVICE_CLASS =
-            "com.android.server.stats.pull.StatsPullAtomService";
-    private static final String STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS =
-            "com.android.server.stats.bootstrap.StatsBootstrapAtomService$Lifecycle";
-    private static final String USB_SERVICE_CLASS =
-            "com.android.server.usb.UsbService$Lifecycle";
-    private static final String MIDI_SERVICE_CLASS =
-            "com.android.server.midi.MidiService$Lifecycle";
-    private static final String WIFI_APEX_SERVICE_JAR_PATH =
-            "/apex/com.android.wifi/javalib/service-wifi.jar";
-    private static final String WIFI_SERVICE_CLASS =
-            "com.android.server.wifi.WifiService";
-    private static final String WIFI_SCANNING_SERVICE_CLASS =
-            "com.android.server.wifi.scanner.WifiScanningService";
-    private static final String WIFI_RTT_SERVICE_CLASS =
-            "com.android.server.wifi.rtt.RttService";
-    private static final String WIFI_AWARE_SERVICE_CLASS =
-            "com.android.server.wifi.aware.WifiAwareService";
-    private static final String WIFI_P2P_SERVICE_CLASS =
-            "com.android.server.wifi.p2p.WifiP2pService";
     private static final String LOWPAN_SERVICE_CLASS =
             "com.android.server.lowpan.LowpanService";
-    private static final String JOB_SCHEDULER_SERVICE_CLASS =
-            "com.android.server.job.JobSchedulerService";
-    private static final String LOCK_SETTINGS_SERVICE_CLASS =
-            "com.android.server.locksettings.LockSettingsService$Lifecycle";
-    private static final String STORAGE_MANAGER_SERVICE_CLASS =
-            "com.android.server.StorageManagerService$Lifecycle";
-    private static final String STORAGE_STATS_SERVICE_CLASS =
-            "com.android.server.usage.StorageStatsService$Lifecycle";
-    private static final String SEARCH_MANAGER_SERVICE_CLASS =
-            "com.android.server.search.SearchManagerService$Lifecycle";
     private static final String THERMAL_OBSERVER_CLASS =
             "com.android.clockwork.ThermalObserver";
     private static final String WEAR_CONNECTIVITY_SERVICE_CLASS =
@@ -354,104 +349,28 @@
             "com.android.clockwork.settings.WearSettingsService";
     private static final String WRIST_ORIENTATION_SERVICE_CLASS =
             "com.android.clockwork.wristorientation.WristOrientationService";
-    private static final String ACCOUNT_SERVICE_CLASS =
-            "com.android.server.accounts.AccountManagerService$Lifecycle";
-    private static final String CONTENT_SERVICE_CLASS =
-            "com.android.server.content.ContentService$Lifecycle";
-    private static final String WALLPAPER_SERVICE_CLASS =
-            "com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
-    private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
-            "com.android.server.autofill.AutofillManagerService";
-    private static final String CREDENTIAL_MANAGER_SERVICE_CLASS =
-            "com.android.server.credentials.CredentialManagerService";
-    private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
-            "com.android.server.contentcapture.ContentCaptureManagerService";
-    private static final String TRANSLATION_MANAGER_SERVICE_CLASS =
-            "com.android.server.translation.TranslationManagerService";
-    private static final String MUSIC_RECOGNITION_MANAGER_SERVICE_CLASS =
-            "com.android.server.musicrecognition.MusicRecognitionManagerService";
-    private static final String AMBIENT_CONTEXT_MANAGER_SERVICE_CLASS =
-            "com.android.server.ambientcontext.AmbientContextManagerService";
-    private static final String SYSTEM_CAPTIONS_MANAGER_SERVICE_CLASS =
-            "com.android.server.systemcaptions.SystemCaptionsManagerService";
-    private static final String TEXT_TO_SPEECH_MANAGER_SERVICE_CLASS =
-            "com.android.server.texttospeech.TextToSpeechManagerService";
     private static final String IOT_SERVICE_CLASS =
             "com.android.things.server.IoTSystemService";
-    private static final String SLICE_MANAGER_SERVICE_CLASS =
-            "com.android.server.slice.SliceManagerService$Lifecycle";
     private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
             "com.android.internal.car.CarServiceHelperService";
-    private static final String TIME_DETECTOR_SERVICE_CLASS =
-            "com.android.server.timedetector.TimeDetectorService$Lifecycle";
-    private static final String TIME_ZONE_DETECTOR_SERVICE_CLASS =
-            "com.android.server.timezonedetector.TimeZoneDetectorService$Lifecycle";
-    private static final String LOCATION_TIME_ZONE_MANAGER_SERVICE_CLASS =
-            "com.android.server.timezonedetector.location.LocationTimeZoneManagerService$Lifecycle";
-    private static final String GNSS_TIME_UPDATE_SERVICE_CLASS =
-            "com.android.server.timedetector.GnssTimeUpdateService$Lifecycle";
-    private static final String ACCESSIBILITY_MANAGER_SERVICE_CLASS =
-            "com.android.server.accessibility.AccessibilityManagerService$Lifecycle";
-    private static final String ADB_SERVICE_CLASS =
-            "com.android.server.adb.AdbService$Lifecycle";
-    private static final String SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS =
-            "com.android.server.speech.SpeechRecognitionManagerService";
-    private static final String WALLPAPER_EFFECTS_GENERATION_MANAGER_SERVICE_CLASS =
-            "com.android.server.wallpapereffectsgeneration.WallpaperEffectsGenerationManagerService";
-    private static final String APP_PREDICTION_MANAGER_SERVICE_CLASS =
-            "com.android.server.appprediction.AppPredictionManagerService";
-    private static final String CONTENT_SUGGESTIONS_SERVICE_CLASS =
-            "com.android.server.contentsuggestions.ContentSuggestionsManagerService";
-    private static final String SEARCH_UI_MANAGER_SERVICE_CLASS =
-            "com.android.server.searchui.SearchUiManagerService";
-    private static final String SMARTSPACE_MANAGER_SERVICE_CLASS =
-            "com.android.server.smartspace.SmartspaceManagerService";
-    private static final String CONTEXTUAL_SEARCH_MANAGER_SERVICE_CLASS =
-            "com.android.server.contextualsearch.ContextualSearchManagerService";
-    private static final String DEVICE_IDLE_CONTROLLER_CLASS =
-            "com.android.server.DeviceIdleController";
-    private static final String BLOB_STORE_MANAGER_SERVICE_CLASS =
-            "com.android.server.blob.BlobStoreManagerService";
+
+    /*
+     * Implementation class names for services in the {@code SYSTEMSERVERCLASSPATH}
+     * from {@code PRODUCT_APEX_SYSTEM_SERVER_JARS}.
+     */
     private static final String APPSEARCH_MODULE_LIFECYCLE_CLASS =
             "com.android.server.appsearch.AppSearchModule$Lifecycle";
     private static final String ISOLATED_COMPILATION_SERVICE_CLASS =
             "com.android.server.compos.IsolatedCompilationService";
-    private static final String ROLLBACK_MANAGER_SERVICE_CLASS =
-            "com.android.server.rollback.RollbackManagerService";
-    private static final String ALARM_MANAGER_SERVICE_CLASS =
-            "com.android.server.alarm.AlarmManagerService";
-    private static final String MEDIA_SESSION_SERVICE_CLASS =
-            "com.android.server.media.MediaSessionService";
-    private static final String MEDIA_RESOURCE_MONITOR_SERVICE_CLASS =
-            "com.android.server.media.MediaResourceMonitorService";
-    private static final String CONNECTIVITY_SERVICE_INITIALIZER_CLASS =
-            "com.android.server.ConnectivityServiceInitializer";
-    private static final String NETWORK_STATS_SERVICE_INITIALIZER_CLASS =
-            "com.android.server.NetworkStatsServiceInitializer";
-    private static final String IP_CONNECTIVITY_METRICS_CLASS =
-            "com.android.server.connectivity.IpConnectivityMetrics";
     private static final String MEDIA_COMMUNICATION_SERVICE_CLASS =
             "com.android.server.media.MediaCommunicationService";
-    private static final String APP_COMPAT_OVERRIDES_SERVICE_CLASS =
-            "com.android.server.compat.overrides.AppCompatOverridesService$Lifecycle";
     private static final String HEALTHCONNECT_MANAGER_SERVICE_CLASS =
             "com.android.server.healthconnect.HealthConnectManagerService";
     private static final String ROLE_SERVICE_CLASS = "com.android.role.RoleService";
-    private static final String GAME_MANAGER_SERVICE_CLASS =
-            "com.android.server.app.GameManagerService$Lifecycle";
     private static final String ENHANCED_CONFIRMATION_SERVICE_CLASS =
             "com.android.ecm.EnhancedConfirmationService";
-
-    private static final String UWB_APEX_SERVICE_JAR_PATH =
-            "/apex/com.android.uwb/javalib/service-uwb.jar";
-    private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService";
-    private static final String BLUETOOTH_APEX_SERVICE_JAR_PATH =
-            "/apex/com.android.btservices/javalib/service-bluetooth.jar";
-    private static final String BLUETOOTH_SERVICE_CLASS =
-            "com.android.server.bluetooth.BluetoothService";
     private static final String SAFETY_CENTER_SERVICE_CLASS =
             "com.android.safetycenter.SafetyCenterService";
-
     private static final String SDK_SANDBOX_MANAGER_SERVICE_CLASS =
             "com.android.server.sdksandbox.SdkSandboxManagerService$Lifecycle";
     private static final String AD_SERVICES_MANAGER_SERVICE_CLASS =
@@ -461,11 +380,48 @@
                     + "OnDevicePersonalizationSystemService$Lifecycle";
     private static final String UPDATABLE_DEVICE_CONFIG_SERVICE_CLASS =
             "com.android.server.deviceconfig.DeviceConfigInit$Lifecycle";
+
+    /*
+     * Implementation class names and jar locations for services in
+     * {@code STANDALONE_SYSTEMSERVER_JARS}.
+     */
+    private static final String STATS_COMPANION_APEX_PATH =
+            "/apex/com.android.os.statsd/javalib/service-statsd.jar";
+    private static final String STATS_COMPANION_LIFECYCLE_CLASS =
+            "com.android.server.stats.StatsCompanion$Lifecycle";
+    private static final String SCHEDULING_APEX_PATH =
+            "/apex/com.android.scheduling/javalib/service-scheduling.jar";
+    private static final String REBOOT_READINESS_LIFECYCLE_CLASS =
+            "com.android.server.scheduling.RebootReadinessManagerService$Lifecycle";
+    private static final String WIFI_APEX_SERVICE_JAR_PATH =
+            "/apex/com.android.wifi/javalib/service-wifi.jar";
+    private static final String WIFI_SERVICE_CLASS =
+            "com.android.server.wifi.WifiService";
+    private static final String WIFI_SCANNING_SERVICE_CLASS =
+            "com.android.server.wifi.scanner.WifiScanningService";
+    private static final String WIFI_RTT_SERVICE_CLASS =
+            "com.android.server.wifi.rtt.RttService";
+    private static final String WIFI_AWARE_SERVICE_CLASS =
+            "com.android.server.wifi.aware.WifiAwareService";
+    private static final String WIFI_P2P_SERVICE_CLASS =
+            "com.android.server.wifi.p2p.WifiP2pService";
+    private static final String CONNECTIVITY_SERVICE_APEX_PATH =
+            "/apex/com.android.tethering/javalib/service-connectivity.jar";
+    private static final String CONNECTIVITY_SERVICE_INITIALIZER_CLASS =
+            "com.android.server.ConnectivityServiceInitializer";
+    private static final String NETWORK_STATS_SERVICE_INITIALIZER_CLASS =
+            "com.android.server.NetworkStatsServiceInitializer";
+    private static final String UWB_APEX_SERVICE_JAR_PATH =
+            "/apex/com.android.uwb/javalib/service-uwb.jar";
+    private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService";
+    private static final String BLUETOOTH_APEX_SERVICE_JAR_PATH =
+            "/apex/com.android.btservices/javalib/service-bluetooth.jar";
+    private static final String BLUETOOTH_SERVICE_CLASS =
+            "com.android.server.bluetooth.BluetoothService";
     private static final String DEVICE_LOCK_SERVICE_CLASS =
             "com.android.server.devicelock.DeviceLockService";
     private static final String DEVICE_LOCK_APEX_PATH =
             "/apex/com.android.devicelock/javalib/service-devicelock.jar";
-
     private static final String PROFILING_SERVICE_LIFECYCLE_CLASS =
             "android.os.profiling.ProfilingService$Lifecycle";
     private static final String PROFILING_SERVICE_JAR_PATH =
@@ -1435,7 +1391,7 @@
 
         // Manages apk rollbacks.
         t.traceBegin("StartRollbackManagerService");
-        mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);
+        mSystemServiceManager.startService(RollbackManagerService.class);
         t.traceEnd();
 
         // Tracks native tombstones.
@@ -1580,11 +1536,11 @@
 
             // The AccountManager must come before the ContentService
             t.traceBegin("StartAccountManagerService");
-            mSystemServiceManager.startService(ACCOUNT_SERVICE_CLASS);
+            mSystemServiceManager.startService(AccountManagerService.Lifecycle.class);
             t.traceEnd();
 
             t.traceBegin("StartContentService");
-            mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
+            mSystemServiceManager.startService(ContentService.Lifecycle.class);
             t.traceEnd();
 
             t.traceBegin("InstallSystemProviders");
@@ -1639,7 +1595,7 @@
 
             // TODO(aml-jobscheduler): Think about how to do it properly.
             t.traceBegin("StartAlarmManagerService");
-            mSystemServiceManager.startService(ALARM_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(AlarmManagerService.class);
             t.traceEnd();
 
             t.traceBegin("StartInputManagerService");
@@ -1721,7 +1677,7 @@
             }
 
             t.traceBegin("IpConnectivityMetrics");
-            mSystemServiceManager.startService(IP_CONNECTIVITY_METRICS_CLASS);
+            mSystemServiceManager.startService(IpConnectivityMetrics.class);
             t.traceEnd();
 
             t.traceBegin("NetworkWatchlistService");
@@ -1796,7 +1752,7 @@
 
             t.traceBegin("StartAccessibilityManagerService");
             try {
-                mSystemServiceManager.startService(ACCESSIBILITY_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(AccessibilityManagerService.Lifecycle.class);
             } catch (Throwable e) {
                 reportWtf("starting Accessibility Manager", e);
             }
@@ -1819,7 +1775,7 @@
                      * NotificationManagerService is dependant on StorageManagerService,
                      * (for media / usb notifications) so we must start StorageManagerService first.
                      */
-                    mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);
+                    mSystemServiceManager.startService(StorageManagerService.Lifecycle.class);
                     storageManager = IStorageManager.Stub.asInterface(
                             ServiceManager.getService("mount"));
                 } catch (Throwable e) {
@@ -1829,7 +1785,7 @@
 
                 t.traceBegin("StartStorageStatsService");
                 try {
-                    mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS);
+                    mSystemServiceManager.startService(StorageStatsService.Lifecycle.class);
                 } catch (Throwable e) {
                     reportWtf("starting StorageStatsService", e);
                 }
@@ -1860,7 +1816,7 @@
         t.traceEnd();
 
         t.traceBegin("StartAppHibernationService");
-        mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
+        mSystemServiceManager.startService(AppHibernationService.class);
         t.traceEnd();
 
         t.traceBegin("ArtManagerLocal");
@@ -1892,7 +1848,7 @@
         } else {
             t.traceBegin("StartLockSettingsService");
             try {
-                mSystemServiceManager.startService(LOCK_SETTINGS_SERVICE_CLASS);
+                mSystemServiceManager.startService(LockSettingsService.Lifecycle.class);
                 lockSettings = ILockSettings.Stub.asInterface(
                         ServiceManager.getService("lock_settings"));
             } catch (Throwable e) {
@@ -1925,7 +1881,7 @@
             }
 
             t.traceBegin("StartDeviceIdleController");
-            mSystemServiceManager.startService(DEVICE_IDLE_CONTROLLER_CLASS);
+            mSystemServiceManager.startService(DeviceIdleController.class);
             t.traceEnd();
 
             // Always start the Device Policy Manager, so that the API is compatible with
@@ -1948,7 +1904,7 @@
             if (deviceHasConfigString(context,
                     R.string.config_defaultMusicRecognitionService)) {
                 t.traceBegin("StartMusicRecognitionManagerService");
-                mSystemServiceManager.startService(MUSIC_RECOGNITION_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(MusicRecognitionManagerService.class);
                 t.traceEnd();
             } else {
                 Slog.d(TAG,
@@ -1966,7 +1922,7 @@
             if (deviceHasConfigString(
                     context, R.string.config_defaultAmbientContextDetectionService)) {
                 t.traceBegin("StartAmbientContextService");
-                mSystemServiceManager.startService(AMBIENT_CONTEXT_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(AmbientContextManagerService.class);
                 t.traceEnd();
             } else {
                 Slog.d(TAG, "AmbientContextManagerService not defined by OEM or disabled by flag");
@@ -1974,13 +1930,13 @@
 
             // System Speech Recognition Service
             t.traceBegin("StartSpeechRecognitionManagerService");
-            mSystemServiceManager.startService(SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(SpeechRecognitionManagerService.class);
             t.traceEnd();
 
             // App prediction manager service
             if (deviceHasConfigString(context, R.string.config_defaultAppPredictionService)) {
                 t.traceBegin("StartAppPredictionService");
-                mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(AppPredictionManagerService.class);
                 t.traceEnd();
             } else {
                 Slog.d(TAG, "AppPredictionService not defined by OEM");
@@ -1989,7 +1945,7 @@
             // Content suggestions manager service
             if (deviceHasConfigString(context, R.string.config_defaultContentSuggestionsService)) {
                 t.traceBegin("StartContentSuggestionsService");
-                mSystemServiceManager.startService(CONTENT_SUGGESTIONS_SERVICE_CLASS);
+                mSystemServiceManager.startService(ContentSuggestionsManagerService.class);
                 t.traceEnd();
             } else {
                 Slog.d(TAG, "ContentSuggestionsService not defined by OEM");
@@ -1998,14 +1954,14 @@
             // Search UI manager service
             if (deviceHasConfigString(context, R.string.config_defaultSearchUiService)) {
                 t.traceBegin("StartSearchUiService");
-                mSystemServiceManager.startService(SEARCH_UI_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(SearchUiManagerService.class);
                 t.traceEnd();
             }
 
             // Smartspace manager service
             if (deviceHasConfigString(context, R.string.config_defaultSmartspaceService)) {
                 t.traceBegin("StartSmartspaceService");
-                mSystemServiceManager.startService(SMARTSPACE_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(SmartspaceManagerService.class);
                 t.traceEnd();
             } else {
                 Slog.d(TAG, "SmartspaceManagerService not defined by OEM or disabled by flag");
@@ -2015,7 +1971,7 @@
             if (deviceHasConfigString(context,
                     R.string.config_defaultContextualSearchPackageName)) {
                 t.traceBegin("StartContextualSearchService");
-                mSystemServiceManager.startService(CONTEXTUAL_SEARCH_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(ContextualSearchManagerService.class);
                 t.traceEnd();
             } else {
                 Slog.d(TAG, "ContextualSearchManagerService not defined or disabled by flag");
@@ -2050,9 +2006,11 @@
             mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
             t.traceEnd();
 
-            t.traceBegin("StartTextServicesManager");
-            mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
-            t.traceEnd();
+            if (!isWatch || !android.server.Flags.removeTextService()) {
+                t.traceBegin("StartTextServicesManager");
+                mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
+                t.traceEnd();
+            }
 
             if (!disableSystemTextClassifier) {
                 t.traceBegin("StartTextClassificationManagerService");
@@ -2214,7 +2172,7 @@
 
             t.traceBegin("StartTimeDetectorService");
             try {
-                mSystemServiceManager.startService(TIME_DETECTOR_SERVICE_CLASS);
+                mSystemServiceManager.startService(TimeDetectorService.Lifecycle.class);
             } catch (Throwable e) {
                 reportWtf("starting TimeDetectorService service", e);
             }
@@ -2235,7 +2193,7 @@
 
             t.traceBegin("StartTimeZoneDetectorService");
             try {
-                mSystemServiceManager.startService(TIME_ZONE_DETECTOR_SERVICE_CLASS);
+                mSystemServiceManager.startService(TimeZoneDetectorService.Lifecycle.class);
             } catch (Throwable e) {
                 reportWtf("starting TimeZoneDetectorService service", e);
             }
@@ -2251,7 +2209,7 @@
 
             t.traceBegin("StartLocationTimeZoneManagerService");
             try {
-                mSystemServiceManager.startService(LOCATION_TIME_ZONE_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(LocationTimeZoneManagerService.Lifecycle.class);
             } catch (Throwable e) {
                 reportWtf("starting LocationTimeZoneManagerService service", e);
             }
@@ -2260,7 +2218,7 @@
             if (context.getResources().getBoolean(R.bool.config_enableGnssTimeUpdateService)) {
                 t.traceBegin("StartGnssTimeUpdateService");
                 try {
-                    mSystemServiceManager.startService(GNSS_TIME_UPDATE_SERVICE_CLASS);
+                    mSystemServiceManager.startService(GnssTimeUpdateService.Lifecycle.class);
                 } catch (Throwable e) {
                     reportWtf("starting GnssTimeUpdateService service", e);
                 }
@@ -2270,7 +2228,7 @@
             if (!isWatch) {
                 t.traceBegin("StartSearchManagerService");
                 try {
-                    mSystemServiceManager.startService(SEARCH_MANAGER_SERVICE_CLASS);
+                    mSystemServiceManager.startService(SearchManagerService.Lifecycle.class);
                 } catch (Throwable e) {
                     reportWtf("starting Search Service", e);
                 }
@@ -2279,7 +2237,7 @@
 
             if (context.getResources().getBoolean(R.bool.config_enableWallpaperService)) {
                 t.traceBegin("StartWallpaperManagerService");
-                mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
+                mSystemServiceManager.startService(WallpaperManagerService.Lifecycle.class);
                 t.traceEnd();
             } else {
                 Slog.i(TAG, "Wallpaper service disabled by config");
@@ -2289,8 +2247,7 @@
             if (deviceHasConfigString(context,
                 R.string.config_defaultWallpaperEffectsGenerationService)) {
                 t.traceBegin("StartWallpaperEffectsGenerationService");
-                mSystemServiceManager.startService(
-                    WALLPAPER_EFFECTS_GENERATION_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(WallpaperEffectsGenerationManagerService.class);
                 t.traceEnd();
             }
 
@@ -2345,14 +2302,14 @@
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
                 // Start MIDI Manager service
                 t.traceBegin("StartMidiManager");
-                mSystemServiceManager.startService(MIDI_SERVICE_CLASS);
+                mSystemServiceManager.startService(MidiService.Lifecycle.class);
                 t.traceEnd();
             }
 
             // Start ADB Debugging Service
             t.traceBegin("StartAdbService");
             try {
-                mSystemServiceManager.startService(ADB_SERVICE_CLASS);
+                mSystemServiceManager.startService(AdbService.Lifecycle.class);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting AdbService");
             }
@@ -2364,7 +2321,7 @@
                     || Build.IS_EMULATOR) {
                 // Manage USB host and device support
                 t.traceBegin("StartUsbService");
-                mSystemServiceManager.startService(USB_SERVICE_CLASS);
+                mSystemServiceManager.startService(UsbService.Lifecycle.class);
                 t.traceEnd();
             }
 
@@ -2396,7 +2353,7 @@
 
             // TODO(aml-jobscheduler): Think about how to do it properly.
             t.traceBegin("StartJobScheduler");
-            mSystemServiceManager.startService(JOB_SCHEDULER_SERVICE_CLASS);
+            mSystemServiceManager.startService(JobSchedulerService.class);
             t.traceEnd();
 
             t.traceBegin("StartSoundTrigger");
@@ -2409,14 +2366,14 @@
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP)) {
                 t.traceBegin("StartBackupManager");
-                mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(BackupManagerService.Lifecycle.class);
                 t.traceEnd();
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)
                     || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
                 t.traceBegin("StartAppWidgetService");
-                mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
+                mSystemServiceManager.startService(AppWidgetService.class);
                 t.traceEnd();
             }
 
@@ -2425,7 +2382,7 @@
             // of initializing various settings.  It will internally modify its behavior
             // based on that feature.
             t.traceBegin("StartVoiceRecognitionManager");
-            mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(VoiceInteractionManagerService.class);
             t.traceEnd();
 
             if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) {
@@ -2486,7 +2443,7 @@
             }
 
             t.traceBegin(START_BLOB_STORE_SERVICE);
-            mSystemServiceManager.startService(BLOB_STORE_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(BlobStoreManagerService.class);
             t.traceEnd();
 
             // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode)
@@ -2507,7 +2464,7 @@
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
                 t.traceBegin("StartPrintManager");
-                mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(PrintManagerService.class);
                 t.traceEnd();
             }
 
@@ -2517,13 +2474,13 @@
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
                 t.traceBegin("StartCompanionDeviceManager");
-                mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(CompanionDeviceManagerService.class);
                 t.traceEnd();
             }
 
             if (context.getResources().getBoolean(R.bool.config_enableVirtualDeviceManager)) {
                 t.traceBegin("StartVirtualDeviceManager");
-                mSystemServiceManager.startService(VIRTUAL_DEVICE_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startService(VirtualDeviceManagerService.class);
                 t.traceEnd();
             }
 
@@ -2532,7 +2489,7 @@
             t.traceEnd();
 
             t.traceBegin("StartMediaSessionService");
-            mSystemServiceManager.startService(MEDIA_SESSION_SERVICE_CLASS);
+            mSystemServiceManager.startService(MediaSessionService.class);
             t.traceEnd();
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
@@ -2563,7 +2520,7 @@
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
                 t.traceBegin("StartMediaResourceMonitor");
-                mSystemServiceManager.startService(MEDIA_RESOURCE_MONITOR_SERVICE_CLASS);
+                mSystemServiceManager.startService(MediaResourceMonitorService.class);
                 t.traceEnd();
             }
 
@@ -2735,7 +2692,7 @@
 
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED)) {
             t.traceBegin("StartSliceManagerService");
-            mSystemServiceManager.startService(SLICE_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(SliceManagerService.Lifecycle.class);
             t.traceEnd();
         }
 
@@ -2759,12 +2716,12 @@
 
         // Statsd pulled atoms
         t.traceBegin("StartStatsPullAtomService");
-        mSystemServiceManager.startService(STATS_PULL_ATOM_SERVICE_CLASS);
+        mSystemServiceManager.startService(StatsPullAtomService.class);
         t.traceEnd();
 
         // Log atoms to statsd from bootstrap processes.
         t.traceBegin("StatsBootstrapAtomService");
-        mSystemServiceManager.startService(STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS);
+        mSystemServiceManager.startService(StatsBootstrapAtomService.Lifecycle.class);
         t.traceEnd();
 
         // Incidentd and dumpstated helper
@@ -2811,7 +2768,7 @@
 
         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
             t.traceBegin("StartAutoFillService");
-            mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(AutofillManagerService.class);
             t.traceEnd();
         }
 
@@ -2820,13 +2777,12 @@
                     DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CREDENTIAL,
                     CredentialManager.DEVICE_CONFIG_ENABLE_CREDENTIAL_MANAGER, true);
             if (credentialManagerEnabled) {
-                if(isWatch &&
-                  !android.credentials.flags.Flags.wearCredentialManagerEnabled()) {
-                  Slog.d(TAG, "CredentialManager disabled on wear.");
+                if (isWatch && !android.credentials.flags.Flags.wearCredentialManagerEnabled()) {
+                    Slog.d(TAG, "CredentialManager disabled on wear.");
                 } else {
-                  t.traceBegin("StartCredentialManagerService");
-                  mSystemServiceManager.startService(CREDENTIAL_MANAGER_SERVICE_CLASS);
-                  t.traceEnd();
+                    t.traceBegin("StartCredentialManagerService");
+                    mSystemServiceManager.startService(CredentialManagerService.class);
+                    t.traceEnd();
                 }
             } else {
                 Slog.d(TAG, "CredentialManager disabled.");
@@ -2836,7 +2792,7 @@
         // Translation manager service
         if (deviceHasConfigString(context, R.string.config_defaultTranslationService)) {
             t.traceBegin("StartTranslationManagerService");
-            mSystemServiceManager.startService(TRANSLATION_MANAGER_SERVICE_CLASS);
+            mSystemServiceManager.startService(TranslationManagerService.class);
             t.traceEnd();
         } else {
             Slog.d(TAG, "TranslationService not defined by OEM");
@@ -2980,7 +2936,7 @@
         t.traceEnd();
 
         t.traceBegin("GameManagerService");
-        mSystemServiceManager.startService(GAME_MANAGER_SERVICE_CLASS);
+        mSystemServiceManager.startService(GameManagerService.Lifecycle.class);
         t.traceEnd();
 
         if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
@@ -3012,7 +2968,7 @@
         t.traceEnd();
 
         t.traceBegin("AppCompatOverridesService");
-        mSystemServiceManager.startService(APP_COMPAT_OVERRIDES_SERVICE_CLASS);
+        mSystemServiceManager.startService(AppCompatOverridesService.Lifecycle.class);
         t.traceEnd();
 
         t.traceBegin("HealthConnectManagerService");
@@ -3397,14 +3353,14 @@
         }
 
         t.traceBegin("StartSystemCaptionsManagerService");
-        mSystemServiceManager.startService(SYSTEM_CAPTIONS_MANAGER_SERVICE_CLASS);
+        mSystemServiceManager.startService(SystemCaptionsManagerService.class);
         t.traceEnd();
     }
 
     private void startTextToSpeechManagerService(@NonNull Context context,
             @NonNull TimingsTraceAndSlog t) {
         t.traceBegin("StartTextToSpeechManagerService");
-        mSystemServiceManager.startService(TEXT_TO_SPEECH_MANAGER_SERVICE_CLASS);
+        mSystemServiceManager.startService(TextToSpeechManagerService.class);
         t.traceEnd();
     }
 
@@ -3439,7 +3395,7 @@
         }
 
         t.traceBegin("StartContentCaptureService");
-        mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
+        mSystemServiceManager.startService(ContentCaptureManagerService.class);
 
         ContentCaptureManagerInternal ccmi =
                 LocalServices.getService(ContentCaptureManagerInternal.class);
diff --git a/services/java/com/android/server/flags.aconfig b/services/java/com/android/server/flags.aconfig
index 854bc0f..38354e8 100644
--- a/services/java/com/android/server/flags.aconfig
+++ b/services/java/com/android/server/flags.aconfig
@@ -8,3 +8,10 @@
      is_fixed_read_only: true
      bug: "324153471"
 }
+
+flag {
+     name: "remove_text_service"
+     namespace: "wear_frameworks"
+     description: "Remove TextServiceManagerService on Wear"
+     bug: "323720705"
+}
\ No newline at end of file
diff --git a/services/permission/TEST_MAPPING b/services/permission/TEST_MAPPING
index 00bfcd3..4de4a56 100644
--- a/services/permission/TEST_MAPPING
+++ b/services/permission/TEST_MAPPING
@@ -103,6 +103,28 @@
                     "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest"
                 }
             ]
+        },
+        {
+            "name": "CtsVirtualDevicesAudioTestCases",
+            "options": [
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "include-filter": "android.virtualdevice.cts.audio.VirtualAudioPermissionTest"
+                }
+            ]
+        },
+        {
+            "name": "CtsVirtualDevicesAppLaunchTestCases",
+            "options": [
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "include-filter": "android.virtualdevice.cts.applaunch.VirtualDevicePermissionTest"
+                }
+            ]
         }
     ],
     "imports": [
diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
index 36bea7d..69a88e9 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
@@ -78,6 +78,9 @@
             setPackageStates(packageStates)
             setDisabledSystemPackageStates(disabledSystemPackageStates)
             packageStates.forEach { (_, packageState) ->
+                if (packageState.isApex) {
+                    return@forEach
+                }
                 mutateAppIdPackageNames()
                     .mutateOrPut(packageState.appId) { MutableIndexedListSet() }
                     .add(packageState.packageName)
@@ -103,6 +106,9 @@
         newState.mutateUserStatesNoWrite()[userId] = MutableUserState()
         forEachSchemePolicy { with(it) { onUserAdded(userId) } }
         newState.externalState.packageStates.forEach { (_, packageState) ->
+            if (packageState.isApex) {
+                return@forEach
+            }
             upgradePackageVersion(packageState, userId)
         }
     }
@@ -126,6 +132,9 @@
             setPackageStates(packageStates)
             setDisabledSystemPackageStates(disabledSystemPackageStates)
             packageStates.forEach { (packageName, packageState) ->
+                if (packageState.isApex) {
+                    return@forEach
+                }
                 if (packageState.volumeUuid == volumeUuid) {
                     // The APK for a package on a mounted storage volume may still be unavailable
                     // due to APK being deleted, e.g. after an OTA.
@@ -151,6 +160,9 @@
             with(it) { onStorageVolumeMounted(volumeUuid, packageNames, isSystemUpdated) }
         }
         packageStates.forEach { (_, packageState) ->
+            if (packageState.isApex) {
+                return@forEach
+            }
             if (packageState.volumeUuid == volumeUuid) {
                 newState.userStates.forEachIndexed { _, userId, _ ->
                     upgradePackageVersion(packageState, userId)
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
index c0d988d..b0c7073 100644
--- a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
@@ -20,6 +20,7 @@
 import android.companion.virtual.VirtualDeviceManager
 import android.os.Handler
 import android.os.UserHandle
+import android.permission.PermissionManager
 import android.permission.flags.Flags
 import android.util.ArrayMap
 import android.util.ArraySet
@@ -142,7 +143,7 @@
         }
     }
 
-    override fun getNonDefaultUidModes(uid: Int, persistentDeviceId: String): SparseIntArray {
+    override fun getNonDefaultUidModes(uid: Int, deviceId: String): SparseIntArray {
         val appId = UserHandle.getAppId(uid)
         val userId = UserHandle.getUserId(uid)
         service.getState {
@@ -150,7 +151,8 @@
                 with(appIdPolicy) { opNameMapToOpSparseArray(getAppOpModes(appId, userId)?.map) }
             if (Flags.runtimePermissionAppopsMappingEnabled()) {
                 runtimePermissionNameToAppOp.forEachIndexed { _, permissionName, appOpCode ->
-                    val mode = getUidModeFromPermissionState(appId, userId, permissionName)
+                    val mode =
+                        getUidModeFromPermissionState(appId, userId, permissionName, deviceId)
                     if (mode != AppOpsManager.opToDefaultMode(appOpCode)) {
                         modes[appOpCode] = mode
                     }
@@ -165,7 +167,7 @@
         return opNameMapToOpSparseArray(getPackageModes(packageName, userId))
     }
 
-    override fun getUidMode(uid: Int, persistentDeviceId: String, op: Int): Int {
+    override fun getUidMode(uid: Int, deviceId: String, op: Int): Int {
         val appId = UserHandle.getAppId(uid)
         val userId = UserHandle.getUserId(uid)
         val opName = AppOpsManager.opToPublicName(op)
@@ -174,7 +176,9 @@
         return if (!Flags.runtimePermissionAppopsMappingEnabled() || permissionName == null) {
             service.getState { with(appIdPolicy) { getAppOpMode(appId, userId, opName) } }
         } else {
-            service.getState { getUidModeFromPermissionState(appId, userId, permissionName) }
+            service.getState {
+                getUidModeFromPermissionState(appId, userId, permissionName, deviceId)
+            }
         }
     }
 
@@ -187,15 +191,31 @@
     private fun GetStateScope.getUidModeFromPermissionState(
         appId: Int,
         userId: Int,
-        permissionName: String
+        permissionName: String,
+        deviceId: String
     ): Int {
+        val checkDevicePermissionFlags =
+            deviceId != VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT &&
+                permissionName in PermissionManager.DEVICE_AWARE_PERMISSIONS
         val permissionFlags =
-            with(permissionPolicy) { getPermissionFlags(appId, userId, permissionName) }
+            if (checkDevicePermissionFlags) {
+                with(devicePermissionPolicy) {
+                    getPermissionFlags(appId, deviceId, userId, permissionName)
+                }
+            } else {
+                with(permissionPolicy) { getPermissionFlags(appId, userId, permissionName) }
+            }
         val backgroundPermissionName = foregroundToBackgroundPermissionName[permissionName]
         val backgroundPermissionFlags =
             if (backgroundPermissionName != null) {
-                with(permissionPolicy) {
-                    getPermissionFlags(appId, userId, backgroundPermissionName)
+                if (checkDevicePermissionFlags) {
+                    with(devicePermissionPolicy) {
+                        getPermissionFlags(appId, deviceId, userId, backgroundPermissionName)
+                    }
+                } else {
+                    with(permissionPolicy) {
+                        getPermissionFlags(appId, userId, backgroundPermissionName)
+                    }
                 }
             } else {
                 PermissionFlags.RUNTIME_GRANTED
@@ -207,7 +227,7 @@
 
         val fullerPermissionName =
             PermissionService.getFullerPermission(permissionName) ?: return result
-        return getUidModeFromPermissionState(appId, userId, fullerPermissionName)
+        return getUidModeFromPermissionState(appId, userId, fullerPermissionName, deviceId)
     }
 
     private fun evaluateModeFromPermissionFlags(
@@ -224,7 +244,7 @@
             MODE_IGNORED
         }
 
-    override fun setUidMode(uid: Int, persistentDeviceId: String, code: Int, mode: Int): Boolean {
+    override fun setUidMode(uid: Int, deviceId: String, code: Int, mode: Int): Boolean {
         if (
             Flags.runtimePermissionAppopsMappingEnabled() && code in runtimeAppOpToPermissionNames
         ) {
@@ -308,7 +328,7 @@
         // and we have our own persistence.
     }
 
-    override fun getForegroundOps(uid: Int, persistentDeviceId: String): SparseBooleanArray {
+    override fun getForegroundOps(uid: Int, deviceId: String): SparseBooleanArray {
         return SparseBooleanArray().apply {
             getUidModes(uid)?.forEachIndexed { _, op, mode ->
                 if (mode == AppOpsManager.MODE_FOREGROUND) {
@@ -317,7 +337,7 @@
             }
             if (Flags.runtimePermissionAppopsMappingEnabled()) {
                 foregroundableOps.forEachIndexed { _, op, _ ->
-                    if (getUidMode(uid, persistentDeviceId, op) == AppOpsManager.MODE_FOREGROUND) {
+                    if (getUidMode(uid, deviceId, op) == AppOpsManager.MODE_FOREGROUND) {
                         this[op] = true
                     }
                 }
@@ -501,7 +521,7 @@
                         )
                     }
                 }
-                ?: runtimePermissionNameToAppOp[permissionName]?.let { appOpCode ->
+                    ?: runtimePermissionNameToAppOp[permissionName]?.let { appOpCode ->
                     addPendingChangedModeIfNeeded(
                         appId,
                         userId,
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 47fd970..87af841 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -81,6 +81,9 @@
 
     override fun MutateStateScope.onUserAdded(userId: Int) {
         newState.externalState.packageStates.forEach { (_, packageState) ->
+            if (packageState.isApex) {
+                return@forEach
+            }
             evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null)
         }
         newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ ->
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index b32c544..65feeb0 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -1445,6 +1445,9 @@
         val packageStates = packageManagerLocal.withUnfilteredSnapshot().use { it.packageStates }
         service.mutateState {
             packageStates.forEach { (packageName, packageState) ->
+                if (packageState.isApex) {
+                    return@forEach
+                }
                 val androidPackage = packageState.androidPackage ?: return@forEach
                 androidPackage.requestedPermissions.forEach { permissionName ->
                     updatePermissionFlags(
@@ -1598,7 +1601,7 @@
         ) {
             with(policy) { getPermissionFlags(appId, userId, permissionName) }
         } else {
-            if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
+            if (permissionName !in PermissionManager.DEVICE_AWARE_PERMISSIONS) {
                 Slog.i(
                     LOG_TAG,
                     "$permissionName is not device aware permission, " +
@@ -1623,7 +1626,7 @@
         ) {
             with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
         } else {
-            if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
+            if (permissionName !in PermissionManager.DEVICE_AWARE_PERMISSIONS) {
                 Slog.i(
                     LOG_TAG,
                     "$permissionName is not device aware permission, " +
@@ -1877,6 +1880,9 @@
         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
             service.mutateState {
                 snapshot.packageStates.forEach { (_, packageState) ->
+                    if (packageState.isApex) {
+                        return@forEach
+                    }
                     with(policy) { resetRuntimePermissions(packageState.packageName, userId) }
                     with(devicePolicy) { resetRuntimePermissions(packageState.packageName, userId) }
                 }
@@ -1918,8 +1924,11 @@
         }
 
         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
-            snapshot.packageStates.forEach packageStates@{ (_, packageState) ->
-                val androidPackage = packageState.androidPackage ?: return@packageStates
+            snapshot.packageStates.forEach { (_, packageState) ->
+                if (packageState.isApex) {
+                    return@forEach
+                }
+                val androidPackage = packageState.androidPackage ?: return@forEach
                 if (permissionName in androidPackage.requestedPermissions) {
                     packageNames += androidPackage.packageName
                 }
@@ -1934,6 +1943,9 @@
         val permissions = service.getState { with(policy) { getPermissions() } }
         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
             snapshot.packageStates.forEach packageStates@{ (_, packageState) ->
+                if (packageState.isApex) {
+                    return@packageStates
+                }
                 val androidPackage = packageState.androidPackage ?: return@packageStates
                 androidPackage.requestedPermissions.forEach requestedPermissions@{ permissionName ->
                     val permission = permissions[permissionName] ?: return@requestedPermissions
@@ -2060,6 +2072,9 @@
 
         val appIdPackageNames = MutableIndexedMap<Int, MutableIndexedSet<String>>()
         packageStates.forEach { (_, packageState) ->
+            if (packageState.isApex) {
+                return@forEach
+            }
             appIdPackageNames
                 .getOrPut(packageState.appId) { MutableIndexedSet() }
                 .add(packageState.packageName)
@@ -2313,6 +2328,10 @@
         isInstantApp: Boolean,
         oldPackage: AndroidPackage?
     ) {
+        if (packageState.isApex) {
+            return
+        }
+
         synchronized(storageVolumeLock) {
             // Accumulating the package names here because we want to maintain the same call order
             // of onPackageAdded() and reuse this order in onStorageVolumeAdded(). We need the
@@ -2339,6 +2358,10 @@
         params: PermissionManagerServiceInternal.PackageInstalledParams,
         userId: Int
     ) {
+        if (androidPackage.isApex) {
+            return
+        }
+
         if (params === PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT) {
             // TODO: We should actually stop calling onPackageInstalled() when we are passing
             //  PackageInstalledParams.DEFAULT in InstallPackageHelper, because there's actually no
@@ -2391,6 +2414,10 @@
         sharedUserPkgs: List<AndroidPackage>,
         userId: Int
     ) {
+        if (packageState.isApex) {
+            return
+        }
+
         val userIds =
             if (userId == UserHandle.USER_ALL) {
                 userManagerService.userIdsIncludingPreCreated
@@ -2820,15 +2847,6 @@
                 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM or
                 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
 
-        /** These permissions are supported for virtual devices. */
-        // TODO: b/298661870 - Use new API to get the list of device aware permissions.
-        val DEVICE_AWARE_PERMISSIONS =
-            if (Flags.deviceAwarePermissionsEnabled()) {
-                setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
-            } else {
-                emptySet<String>()
-            }
-
         fun getFullerPermission(permissionName: String): String? =
             FULLER_PERMISSIONS[permissionName]
     }
diff --git a/services/proguard.flags b/services/proguard.flags
index a01e7dc..bf30781 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -29,17 +29,6 @@
   public protected *;
 }
 
-# Derivatives of SystemService and other services created via reflection
--keep,allowoptimization,allowaccessmodification class * extends com.android.server.SystemService {
-  public <methods>;
-}
--keep,allowoptimization,allowaccessmodification class * extends com.android.server.devicepolicy.BaseIDevicePolicyManager {
-  public <init>(...);
-}
--keep,allowoptimization,allowaccessmodification class com.android.server.wallpaper.WallpaperManagerService {
-  public <init>(...);
-}
-
 # Accessed from com.android.compos APEX
 -keep,allowoptimization,allowaccessmodification class com.android.internal.art.ArtStatsLog {
    public static void write(...);
@@ -68,13 +57,6 @@
 -keep public class android.hidl.manager.** { *; }
 -keep public class com.android.server.wm.WindowManagerInternal { *; }
 
-# Notification extractors
-# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
--keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
-
-# OEM provided DisplayAreaPolicy.Provider defined in frameworks/base/core/res/res/values/config.xml.
--keep,allowoptimization,allowaccessmodification class com.android.server.wm.** implements com.android.server.wm.DisplayAreaPolicy$Provider
-
 # JNI keep rules
 # The global keep rule for native methods allows stripping of such methods if they're unreferenced
 # in Java. However, because system_server explicitly registers these methods from native code,
@@ -118,9 +100,6 @@
 
 # Miscellaneous reflection keep rules
 # TODO(b/210510433): Revisit and fix with @Keep.
--keep,allowoptimization,allowaccessmodification class com.android.server.usage.AppStandbyController {
-  public <init>(...);
-}
 -keep,allowoptimization,allowaccessmodification class android.hardware.usb.gadget.** { *; }
 
 # Needed when optimizations enabled
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
index 94ee0a8..a547d0f 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
@@ -17,9 +17,7 @@
 package com.android.server.backup;
 
 import static android.Manifest.permission.BACKUP;
-import static android.Manifest.permission.DUMP;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.PACKAGE_USAGE_STATS;
 
 import static com.android.server.backup.testing.TransportData.backupTransport;
 
@@ -73,10 +71,7 @@
 import org.robolectric.shadows.ShadowContextWrapper;
 
 import java.io.File;
-import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
 
 /** Tests for {@link BackupManagerService}. */
 @RunWith(RobolectricTestRunner.class)
@@ -1461,67 +1456,12 @@
     //  Service tests
     // ---------------------------------------------
 
-    /** Test that the backup service routes methods correctly to the user that requests it. */
-    @Test
-    public void testDump_onRegisteredUser_callsMethodForUser() throws Exception {
-        grantDumpPermissions();
-        BackupManagerService backupManagerService = createSystemRegisteredService();
-        File testFile = createTestFile();
-        FileDescriptor fileDescriptor = new FileDescriptor();
-        PrintWriter printWriter = new PrintWriter(testFile);
-        String[] args = {"1", "2"};
-        ShadowBinder.setCallingUserHandle(UserHandle.of(UserHandle.USER_SYSTEM));
-
-        backupManagerService.dump(fileDescriptor, printWriter, args);
-
-        verify(mUserSystemService).dump(fileDescriptor, printWriter, args);
-    }
-
-    /** Test that the backup service does not route methods for non-registered users. */
-    @Test
-    public void testDump_onUnknownUser_doesNotPropagateCall() throws Exception {
-        grantDumpPermissions();
-        BackupManagerService backupManagerService = createService();
-        File testFile = createTestFile();
-        FileDescriptor fileDescriptor = new FileDescriptor();
-        PrintWriter printWriter = new PrintWriter(testFile);
-        String[] args = {"1", "2"};
-
-        backupManagerService.dump(fileDescriptor, printWriter, args);
-
-        verify(mUserOneService, never()).dump(fileDescriptor, printWriter, args);
-    }
-
-    /** Test that 'dumpsys backup users' dumps the list of users registered in backup service*/
-    @Test
-    public void testDump_users_dumpsListOfRegisteredUsers() {
-        grantDumpPermissions();
-        BackupManagerService backupManagerService = createSystemRegisteredService();
-        registerUser(backupManagerService, mUserOneId, mUserOneService);
-        StringWriter out = new StringWriter();
-        PrintWriter writer = new PrintWriter(out);
-        String[] args = {"users"};
-
-        backupManagerService.dump(null, writer, args);
-
-        writer.flush();
-        assertEquals(
-                String.format("%s %d %d\n", BackupManagerService.DUMP_RUNNING_USERS_MESSAGE,
-                        UserHandle.USER_SYSTEM, mUserOneId),
-                out.toString());
-    }
-
     private File createTestFile() throws IOException {
         File testFile = new File(mContext.getFilesDir(), "test");
         testFile.createNewFile();
         return testFile;
     }
 
-    private void grantDumpPermissions() {
-        mShadowContext.grantPermissions(DUMP);
-        mShadowContext.grantPermissions(PACKAGE_USAGE_STATS);
-    }
-
     /**
      * Test that the backup services throws a {@link SecurityException} if the caller does not have
      * INTERACT_ACROSS_USERS_FULL permission and passes a different user id.
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 3bce9b5..0da17e1 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -84,6 +84,7 @@
     ],
     srcs: [
         "src/com/android/server/inputmethod/**/ClientControllerTest.java",
+        "src/com/android/server/inputmethod/**/UserDataRepositoryTest.java",
     ],
     auto_gen_config: true,
 }
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index 2134278..1535298 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -38,7 +38,6 @@
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.WindowManagerGlobal;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -601,28 +600,6 @@
                 false /* orientationPortrait */);
     }
 
-    @Test
-    public void switchesKeyboardLayout_withShortcut_onlyIfImeVisible() throws Exception {
-        setShowImeWithHardKeyboard(true /* enabled */);
-
-        assertThat(mInputMethodService.isInputViewShown()).isFalse();
-        assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
-                new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
-                        KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isFalse();
-
-        verifyInputViewStatusOnMainSync(
-                () -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
-                true /* expected */,
-                true /* inputViewStarted */);
-
-        assertThat(mInputMethodService.isInputViewShown()).isTrue();
-        assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
-                new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
-                        KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isTrue();
-    }
-
     /**
      * This checks that when the system navigation bar is not created (e.g. emulator),
      * then the IME caption bar is also not created.
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
new file mode 100644
index 0000000..a15b170
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.pm.UserInfo;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import com.android.server.pm.UserManagerInternal;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// This test is designed to run on both device and host (Ravenwood) side.
+public final class UserDataRepositoryTest {
+
+    private static final int ANY_USER_ID = 1;
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true).build();
+
+    @Mock
+    private UserManagerInternal mMockUserManagerInternal;
+
+    private Handler mHandler;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mHandler = new Handler(Looper.getMainLooper());
+    }
+
+    @Test
+    public void testUserDataRepository_addsNewUserInfoOnUserCreatedEvent() {
+        // Create UserDataRepository and capture the user lifecycle listener
+        final var captor = ArgumentCaptor.forClass(UserManagerInternal.UserLifecycleListener.class);
+        final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal);
+        verify(mMockUserManagerInternal, times(1)).addUserLifecycleListener(captor.capture());
+        final var listener = captor.getValue();
+
+        // Assert that UserDataRepository is empty and then call onUserCreated
+        assertThat(collectUserData(repository)).isEmpty();
+        final var userInfo = new UserInfo();
+        userInfo.id = ANY_USER_ID;
+        listener.onUserCreated(userInfo, /* unused token */ new Object());
+        waitForIdle();
+
+        // Assert UserDataRepository contains the expected UserData
+        final var allUserData = collectUserData(repository);
+        assertThat(allUserData).hasSize(1);
+        assertThat(allUserData.get(0).mUserId).isEqualTo(userInfo.id);
+    }
+
+    @Test
+    public void testUserDataRepository_removesUserInfoOnUserRemovedEvent() {
+        // Create UserDataRepository and capture the user lifecycle listener
+        final var captor = ArgumentCaptor.forClass(UserManagerInternal.UserLifecycleListener.class);
+        final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal);
+        verify(mMockUserManagerInternal, times(1)).addUserLifecycleListener(captor.capture());
+        final var listener = captor.getValue();
+
+        // Add one UserData ...
+        final var userInfo = new UserInfo();
+        userInfo.id = ANY_USER_ID;
+        listener.onUserCreated(userInfo, /* unused token */ new Object());
+        waitForIdle();
+        // ... and then call onUserRemoved
+        assertThat(collectUserData(repository)).hasSize(1);
+        listener.onUserRemoved(userInfo);
+        waitForIdle();
+
+        // Assert UserDataRepository is now empty
+        assertThat(collectUserData(repository)).isEmpty();
+    }
+
+    @Test
+    public void testGetOrCreate() {
+        final var repository = new UserDataRepository(mHandler, mMockUserManagerInternal);
+
+        synchronized (ImfLock.class) {
+            final var userData = repository.getOrCreate(ANY_USER_ID);
+            assertThat(userData.mUserId).isEqualTo(ANY_USER_ID);
+        }
+
+        final var allUserData = collectUserData(repository);
+        assertThat(allUserData).hasSize(1);
+        assertThat(allUserData.get(0).mUserId).isEqualTo(ANY_USER_ID);
+    }
+
+    private List<UserDataRepository.UserData> collectUserData(UserDataRepository repository) {
+        final var collected = new ArrayList<UserDataRepository.UserData>();
+        synchronized (ImfLock.class) {
+            repository.forAllUserData(userData -> collected.add(userData));
+        }
+        return collected;
+    }
+
+    private void waitForIdle() {
+        final var done = new ConditionVariable();
+        mHandler.post(done::open);
+        done.block();
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java
index ad4d91f..8db896b 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java
@@ -27,6 +27,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Objects;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class DisplayBrightnessStateTest {
@@ -45,6 +47,7 @@
         float sdrBrightness = 0.2f;
         boolean shouldUseAutoBrightness = true;
         boolean shouldUpdateScreenBrightnessSetting = true;
+        int brightnessAdjustmentFlag = 2;
         BrightnessReason brightnessReason = new BrightnessReason();
         brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
         brightnessReason.setModifier(BrightnessReason.MODIFIER_DIMMED);
@@ -54,6 +57,7 @@
                 .setBrightnessReason(brightnessReason)
                 .setShouldUseAutoBrightness(shouldUseAutoBrightness)
                 .setShouldUpdateScreenBrightnessSetting(shouldUpdateScreenBrightnessSetting)
+                .setBrightnessAdjustmentFlag(brightnessAdjustmentFlag)
                 .build();
 
         assertEquals(displayBrightnessState.getBrightness(), brightness, FLOAT_DELTA);
@@ -101,7 +105,11 @@
                 .append("\n    customAnimationRate:")
                 .append(displayBrightnessState.getCustomAnimationRate())
                 .append("\n    shouldUpdateScreenBrightnessSetting:")
-                .append(displayBrightnessState.shouldUpdateScreenBrightnessSetting());
+                .append(displayBrightnessState.shouldUpdateScreenBrightnessSetting())
+                .append("\n    mBrightnessEvent:")
+                .append(Objects.toString(displayBrightnessState.getBrightnessEvent(), "null"))
+                .append("\n    mBrightnessAdjustmentFlag:")
+                .append(displayBrightnessState.getBrightnessAdjustmentFlag());
         return sb.toString();
     }
 }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index b80d44f..a0a611f 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -57,6 +57,7 @@
 import com.android.server.display.config.HdrBrightnessData;
 import com.android.server.display.config.HysteresisLevels;
 import com.android.server.display.config.IdleScreenRefreshRateTimeoutLuxThresholdPoint;
+import com.android.server.display.config.RefreshRateData;
 import com.android.server.display.config.ThermalStatus;
 import com.android.server.display.feature.DisplayManagerFlags;
 import com.android.server.display.feature.flags.Flags;
@@ -222,17 +223,18 @@
         assertArrayEquals(new float[]{0.23f, 0.24f, 0.25f},
                 ambientIdleHysteresis.getDarkeningThresholdsPercentages(), ZERO_DELTA);
 
+        RefreshRateData refreshRateData = mDisplayDeviceConfig.getRefreshRateData();
         assertEquals(75, mDisplayDeviceConfig.getDefaultLowBlockingZoneRefreshRate());
         assertEquals(90, mDisplayDeviceConfig.getDefaultHighBlockingZoneRefreshRate());
-        assertEquals(85, mDisplayDeviceConfig.getDefaultPeakRefreshRate());
-        assertEquals(45, mDisplayDeviceConfig.getDefaultRefreshRate());
+        assertEquals(85, refreshRateData.defaultPeakRefreshRate);
+        assertEquals(45, refreshRateData.defaultRefreshRate);
         assertEquals(2, mDisplayDeviceConfig.getRefreshRangeProfiles().size());
         assertEquals(60, mDisplayDeviceConfig.getRefreshRange("test1").min, SMALL_DELTA);
         assertEquals(60, mDisplayDeviceConfig.getRefreshRange("test1").max, SMALL_DELTA);
         assertEquals(80, mDisplayDeviceConfig.getRefreshRange("test2").min, SMALL_DELTA);
         assertEquals(90, mDisplayDeviceConfig.getRefreshRange("test2").max, SMALL_DELTA);
-        assertEquals(82, mDisplayDeviceConfig.getDefaultRefreshRateInHbmHdr());
-        assertEquals(83, mDisplayDeviceConfig.getDefaultRefreshRateInHbmSunlight());
+        assertEquals(82, refreshRateData.defaultRefreshRateInHbmHdr);
+        assertEquals(83, refreshRateData.defaultRefreshRateInHbmSunlight);
 
         assertNotNull(mDisplayDeviceConfig.getHostUsiVersion());
         assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMajorVersion(), 2);
@@ -697,6 +699,7 @@
         HysteresisLevels screenHysteresis = mDisplayDeviceConfig.getScreenBrightnessHysteresis();
         HysteresisLevels screenIdleHysteresis =
                 mDisplayDeviceConfig.getScreenBrightnessIdleHysteresis();
+
         // Test thresholds
         assertEquals(0, ambientHysteresis.getMinBrightening(), ZERO_DELTA);
         assertEquals(0, ambientIdleHysteresis.getMinBrightening(), ZERO_DELTA);
@@ -737,6 +740,8 @@
         assertArrayEquals(new float[]{0.37f, 0.38f, 0.39f},
                 screenIdleHysteresis.getDarkeningThresholdsPercentages(), ZERO_DELTA);
 
+        RefreshRateData refreshRateData = mDisplayDeviceConfig.getRefreshRateData();
+
         assertArrayEquals(new float[]{0, 30, 31},
                 ambientIdleHysteresis.getBrighteningThresholdLevels(), ZERO_DELTA);
         assertArrayEquals(new float[]{0.27f, 0.28f, 0.29f},
@@ -749,13 +754,12 @@
                 DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE);
         assertEquals(mDisplayDeviceConfig.getDefaultHighBlockingZoneRefreshRate(),
                 DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE);
-        assertEquals(mDisplayDeviceConfig.getDefaultPeakRefreshRate(), DEFAULT_PEAK_REFRESH_RATE);
-        assertEquals(mDisplayDeviceConfig.getDefaultRefreshRate(), DEFAULT_REFRESH_RATE);
+        assertEquals(refreshRateData.defaultPeakRefreshRate, DEFAULT_PEAK_REFRESH_RATE);
+        assertEquals(refreshRateData.defaultRefreshRate, DEFAULT_REFRESH_RATE);
         assertEquals(0, mDisplayDeviceConfig.getRefreshRangeProfiles().size());
-        assertEquals(mDisplayDeviceConfig.getDefaultRefreshRateInHbmSunlight(),
+        assertEquals(refreshRateData.defaultRefreshRateInHbmSunlight,
                 DEFAULT_REFRESH_RATE_IN_HBM_SUNLIGHT);
-        assertEquals(mDisplayDeviceConfig.getDefaultRefreshRateInHbmHdr(),
-                DEFAULT_REFRESH_RATE_IN_HBM_HDR);
+        assertEquals(refreshRateData.defaultRefreshRateInHbmHdr, DEFAULT_REFRESH_RATE_IN_HBM_HDR);
 
         assertEquals("test_light_sensor", mDisplayDeviceConfig.getAmbientLightSensor().type);
         assertEquals("", mDisplayDeviceConfig.getAmbientLightSensor().name);
@@ -920,11 +924,12 @@
     @Test
     public void testEvenDimmer() throws IOException {
         when(mFlags.isEvenDimmerEnabled()).thenReturn(true);
+        when(mResources.getBoolean(R.bool.config_evenDimmerEnabled)).thenReturn(true);
         setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getValidLuxThrottling(),
                 getValidProxSensor(), /* includeIdleMode= */ false, /* enableEvenDimmer */ true));
 
         assertTrue(mDisplayDeviceConfig.isEvenDimmerAvailable());
-        assertEquals(0.0001f, mDisplayDeviceConfig.getBacklightFromBrightness(0.1f), ZERO_DELTA);
+        assertEquals(0.01f, mDisplayDeviceConfig.getBacklightFromBrightness(0.002f), ZERO_DELTA);
         assertEquals(0.2f, mDisplayDeviceConfig.getNitsFromBacklight(0.0f), ZERO_DELTA);
     }
 
@@ -1649,18 +1654,28 @@
     private String evenDimmerConfig(boolean enabled) {
         return (enabled ? "<evenDimmer enabled=\"true\">" : "<evenDimmer enabled=\"false\">")
                 + "  <transitionPoint>0.1</transitionPoint>\n"
-                + "  <nits>0.2</nits>\n"
-                + "  <nits>2.0</nits>\n"
-                + "  <nits>500.0</nits>\n"
-                + "  <nits>1000.0</nits>\n"
-                + "  <backlight>0</backlight>\n"
-                + "  <backlight>0.0001</backlight>\n"
-                + "  <backlight>0.5</backlight>\n"
-                + "  <backlight>1.0</backlight>\n"
-                + "  <brightness>0</brightness>\n"
-                + "  <brightness>0.1</brightness>\n"
-                + "  <brightness>0.5</brightness>\n"
-                + "  <brightness>1.0</brightness>\n"
+                + "  <brightnessMapping>\n"
+                + "      <brightnessPoint>\n"
+                + "        <nits>0.2</nits>\n"
+                + "        <backlight>0</backlight>\n"
+                + "        <brightness>0</brightness>\n"
+                + "      </brightnessPoint>\n"
+                + "      <brightnessPoint>\n"
+                + "        <nits>2.0</nits>\n"
+                + "        <backlight>0.01</backlight>\n"
+                + "        <brightness>0.002</brightness>\n"
+                + "      </brightnessPoint>\n"
+                + "      <brightnessPoint>\n"
+                + "        <nits>500.0</nits>\n"
+                + "        <backlight>0.5</backlight>\n"
+                + "        <brightness>0.5</brightness>\n"
+                + "      </brightnessPoint>\n"
+                + "      <brightnessPoint>\n"
+                + "        <nits>1000</nits>\n"
+                + "        <backlight>1.0</backlight>\n"
+                + "        <brightness>1.0</brightness>\n"
+                + "      </brightnessPoint>\n"
+                + "  </brightnessMapping>\n"
                 + " <luxToMinimumNitsMap>\n"
                 + "     <point>\n"
                 + "         <value>10</value> <nits>0.3</nits>\n"
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index b7fa7ea..1666fef 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -133,8 +133,8 @@
 import com.android.internal.R;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
+import com.android.internal.util.test.LocalServiceKeeperRule;
 import com.android.modules.utils.testing.ExtendedMockitoRule;
-import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.display.DisplayManagerService.DeviceStateListener;
@@ -218,6 +218,9 @@
     @Rule
     public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
+    @Rule(order = 2)
+    public LocalServiceKeeperRule mLocalServiceKeeperRule = new LocalServiceKeeperRule();
+
     private Context mContext;
 
     private Resources mResources;
@@ -354,6 +357,7 @@
     @Mock SensorManager mSensorManager;
     @Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
     @Mock PackageManagerInternal mMockPackageManagerInternal;
+    @Mock DisplayManagerInternal mMockDisplayManagerInternal;
     @Mock DisplayAdapter mMockDisplayAdapter;
 
     @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@@ -371,20 +375,20 @@
         when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
         mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
 
-        LocalServices.removeServiceForTest(InputManagerInternal.class);
-        LocalServices.addService(InputManagerInternal.class, mMockInputManagerInternal);
-        LocalServices.removeServiceForTest(WindowManagerInternal.class);
-        LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
-        LocalServices.removeServiceForTest(LightsManager.class);
-        LocalServices.addService(LightsManager.class, mMockLightsManager);
-        LocalServices.removeServiceForTest(SensorManagerInternal.class);
-        LocalServices.addService(SensorManagerInternal.class, mMockSensorManagerInternal);
-        LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
-        LocalServices.addService(
+        mLocalServiceKeeperRule.overrideLocalService(
+                InputManagerInternal.class, mMockInputManagerInternal);
+        mLocalServiceKeeperRule.overrideLocalService(
+                WindowManagerInternal.class, mMockWindowManagerInternal);
+        mLocalServiceKeeperRule.overrideLocalService(
+                LightsManager.class, mMockLightsManager);
+        mLocalServiceKeeperRule.overrideLocalService(
+                SensorManagerInternal.class, mMockSensorManagerInternal);
+        mLocalServiceKeeperRule.overrideLocalService(
                 VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
-        LocalServices.removeServiceForTest(PackageManagerInternal.class);
-        LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
-        // TODO: b/287945043
+        mLocalServiceKeeperRule.overrideLocalService(
+                PackageManagerInternal.class, mMockPackageManagerInternal);
+        mLocalServiceKeeperRule.overrideLocalService(
+                DisplayManagerInternal.class, mMockDisplayManagerInternal);
         Display display = mock(Display.class);
         when(display.getDisplayAdjustments()).thenReturn(new DisplayAdjustments());
         when(display.getBrightnessInfo()).thenReturn(mock(BrightnessInfo.class));
@@ -960,6 +964,9 @@
         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
         builder.setUniqueId(uniqueId);
+        builder.setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR);
+        when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
         final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
@@ -972,6 +979,7 @@
                 VIRTUAL_DISPLAY_NAME, width, height, dpi).setUniqueId(uniqueId2);
         builder2.setUniqueId(uniqueId2);
         builder2.setDisplayIdToMirror(firstDisplayId);
+        builder2.setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR);
         final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
                 mMockAppToken2 /* callback */, null /* projection */,
                 PACKAGE_NAME);
@@ -1700,7 +1708,6 @@
      * {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
      */
     @Test
-    @FlakyTest(bugId = 127687569)
     public void testCreateVirtualDisplay_setSurface() throws Exception {
         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         registerDefaultDisplays(displayManager);
@@ -2448,8 +2455,9 @@
         LogicalDisplay display =
                 logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
         assertThat(display.isEnabledLocked()).isFalse();
+        // TODO(b/332711269) make sure only one DISPLAY_GROUP_EVENT_ADDED sent.
         assertThat(callback.receivedEvents()).containsExactly(DISPLAY_GROUP_EVENT_ADDED,
-                EVENT_DISPLAY_CONNECTED).inOrder();
+                DISPLAY_GROUP_EVENT_ADDED, EVENT_DISPLAY_CONNECTED).inOrder();
     }
 
     @Test
@@ -2624,11 +2632,19 @@
         // Create default display device
         createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
         callback.waitForExpectedEvent();
+
+        callback.expectsEvent(EVENT_DISPLAY_ADDED);
         FakeDisplayDevice displayDevice =
                 createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
+        callback.waitForExpectedEvent();
+
+        callback.expectsEvent(EVENT_DISPLAY_REMOVED);
+        displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+        callback.waitForExpectedEvent();
+
+        callback.expectsEvent(EVENT_DISPLAY_ADDED);
         LogicalDisplay display =
                 logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
-        callback.expectsEvent(EVENT_DISPLAY_ADDED);
         logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ true);
         logicalDisplayMapper.updateLogicalDisplays();
         callback.waitForExpectedEvent();
@@ -2651,6 +2667,7 @@
         LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
         FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
         bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+        displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
         callback.expectsEvent(EVENT_DISPLAY_ADDED);
         // Create default display device
         createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
@@ -2664,7 +2681,6 @@
         logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ true);
         logicalDisplayMapper.updateLogicalDisplays();
         callback.waitForExpectedEvent();
-        callback.clear();
 
         assertThrows(SecurityException.class, () -> bs.disableConnectedDisplay(displayId));
     }
@@ -2835,6 +2851,7 @@
 
         float brightness1 = 0.3f;
         float brightness2 = 0.45f;
+        waitForIdleHandler(mPowerHandler);
 
         int userId1 = 123;
         int userId2 = 456;
@@ -2844,8 +2861,8 @@
         userInfo2.id = userId2;
         when(mUserManager.getUserSerialNumber(userId1)).thenReturn(12345);
         when(mUserManager.getUserSerialNumber(userId2)).thenReturn(45678);
-        final SystemService.TargetUser from = new SystemService.TargetUser(userInfo1);
-        final SystemService.TargetUser to = new SystemService.TargetUser(userInfo2);
+        final SystemService.TargetUser user1 = new SystemService.TargetUser(userInfo1);
+        final SystemService.TargetUser user2 = new SystemService.TargetUser(userInfo2);
 
         // The same brightness will be restored for a user only if auto-brightness is off,
         // otherwise the current lux will be used to determine the brightness.
@@ -2853,20 +2870,20 @@
                 Settings.System.SCREEN_BRIGHTNESS_MODE,
                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
 
-        displayManager.onUserSwitching(to, from);
+        displayManager.onUserSwitching(/* from= */ user2, /* to= */ user1);
         waitForIdleHandler(mPowerHandler);
         displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, brightness1);
-        displayManager.onUserSwitching(from, to);
+        displayManager.onUserSwitching(/* from= */ user1, /* to= */ user2);
         waitForIdleHandler(mPowerHandler);
         displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, brightness2);
 
-        displayManager.onUserSwitching(to, from);
+        displayManager.onUserSwitching(/* from= */ user2, /* to= */ user1);
         waitForIdleHandler(mPowerHandler);
         assertEquals(brightness1,
                 displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
                 FLOAT_TOLERANCE);
 
-        displayManager.onUserSwitching(from, to);
+        displayManager.onUserSwitching(/* from= */ user1, /* to= */ user2);
         waitForIdleHandler(mPowerHandler);
         assertEquals(brightness2,
                 displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
@@ -3000,6 +3017,7 @@
                 new DisplayManagerService(mContext, mBasicInjector);
 
         displayManager.systemReady(false /* safeMode */);
+        displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
         ArgumentMatcher<IntentFilter> matchesFilter =
                 (filter) -> Intent.ACTION_SETTING_RESTORED.equals(filter.getAction(0));
         verify(mContext, times(0)).registerReceiver(any(BroadcastReceiver.class),
@@ -3365,7 +3383,7 @@
 
         void waitForExpectedEvent(Duration timeout) {
             try {
-                assertWithMessage("Event '" + mExpectedEvent + "' is received.")
+                assertWithMessage("Expected '" + mExpectedEvent + "'")
                         .that(mLatch.await(timeout.toMillis(), TimeUnit.MILLISECONDS)).isTrue();
             } catch (InterruptedException ex) {
                 throw new AssertionError("Waiting for expected event interrupted", ex);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index de93914..78ebdb1 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1312,7 +1312,7 @@
         when(mHolder.hbmController.getHighBrightnessMode()).thenReturn(
                 BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR);
         when(mHolder.hbmController.getHdrBrightnessValue()).thenReturn(PowerManager.BRIGHTNESS_MAX);
-        when(mHolder.hdrClamper.getMaxBrightness()).thenReturn(clampedBrightness);
+        when(mHolder.hdrClamper.clamp(PowerManager.BRIGHTNESS_MAX)).thenReturn(clampedBrightness);
         when(mHolder.hdrClamper.getTransitionRate()).thenReturn(transitionRate);
 
         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
index 1a71e77..ea08be4 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
@@ -317,7 +317,8 @@
                 mDisplayEventCaptor.capture());
         assertThat(mLogicalDisplayCaptor.getValue()).isEqualTo(mMockedLogicalDisplay);
         assertThat(mDisplayEventCaptor.getValue()).isEqualTo(EVENT_DISPLAY_CONNECTED);
-        verify(mMockedLogicalDisplay).setEnabledLocked(false);
+        verify(mMockedLogicalDisplayMapper).setDisplayEnabledLocked(eq(mMockedLogicalDisplay),
+                eq(false));
         clearInvocations(mMockedLogicalDisplayMapper);
         clearInvocations(mMockedLogicalDisplay);
     }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index 6ed8238..13a1445 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
@@ -111,10 +112,10 @@
         DisplayBrightnessStrategy displayBrightnessStrategy = mock(DisplayBrightnessStrategy.class);
         int targetDisplayState = Display.STATE_DOZE;
         when(mDisplayBrightnessStrategySelector.selectStrategy(
-                eq(new StrategySelectionRequest(displayPowerRequest, targetDisplayState))))
-                .thenReturn(displayBrightnessStrategy);
+                any(StrategySelectionRequest.class))).thenReturn(displayBrightnessStrategy);
         mDisplayBrightnessController.updateBrightness(displayPowerRequest, targetDisplayState);
-        verify(displayBrightnessStrategy).updateBrightness(displayPowerRequest);
+        verify(displayBrightnessStrategy).updateBrightness(
+                eq(new StrategyExecutionRequest(displayPowerRequest, DEFAULT_BRIGHTNESS)));
         assertEquals(mDisplayBrightnessController.getCurrentDisplayBrightnessStrategy(),
                 displayBrightnessStrategy);
     }
@@ -164,6 +165,7 @@
         // No brightness is set if the pending brightness is invalid
         mDisplayBrightnessController.setPendingScreenBrightness(Float.NaN);
         assertFalse(mDisplayBrightnessController.updateUserSetScreenBrightness());
+        assertFalse(mDisplayBrightnessController.getIsUserSetScreenBrightnessUpdated());
 
         // user set brightness is not set if the current and the pending brightness are same.
         float currentBrightness = 0.4f;
@@ -175,6 +177,7 @@
         mDisplayBrightnessController.setPendingScreenBrightness(currentBrightness);
         mDisplayBrightnessController.setTemporaryBrightness(currentBrightness);
         assertFalse(mDisplayBrightnessController.updateUserSetScreenBrightness());
+        assertFalse(mDisplayBrightnessController.getIsUserSetScreenBrightnessUpdated());
         verify(temporaryBrightnessStrategy).setTemporaryScreenBrightness(
                 PowerManager.BRIGHTNESS_INVALID_FLOAT);
         assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(),
@@ -188,6 +191,7 @@
         mDisplayBrightnessController.setPendingScreenBrightness(pendingScreenBrightness);
         mDisplayBrightnessController.setTemporaryBrightness(temporaryScreenBrightness);
         assertTrue(mDisplayBrightnessController.updateUserSetScreenBrightness());
+        assertTrue(mDisplayBrightnessController.getIsUserSetScreenBrightnessUpdated());
         assertEquals(mDisplayBrightnessController.getCurrentBrightness(),
                 pendingScreenBrightness, /* delta= */ 0.0f);
         assertEquals(mDisplayBrightnessController.getLastUserSetScreenBrightness(),
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index 4c9dd58..f270650 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -22,6 +22,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
@@ -40,6 +41,7 @@
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
 import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
+import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy2;
 import com.android.server.display.brightness.strategy.BoostBrightnessStrategy;
 import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
 import com.android.server.display.brightness.strategy.FollowerBrightnessStrategy;
@@ -80,6 +82,8 @@
     @Mock
     private AutomaticBrightnessStrategy mAutomaticBrightnessStrategy;
     @Mock
+    private AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy2;
+    @Mock
     private OffloadBrightnessStrategy mOffloadBrightnessStrategy;
     @Mock
     private Resources mResources;
@@ -126,13 +130,20 @@
                 }
 
                 @Override
-                AutomaticBrightnessStrategy getAutomaticBrightnessStrategy(Context context,
+                AutomaticBrightnessStrategy getAutomaticBrightnessStrategy1(Context context,
                         int displayId) {
                     return mAutomaticBrightnessStrategy;
                 }
 
                 @Override
-                OffloadBrightnessStrategy getOffloadBrightnessStrategy() {
+                AutomaticBrightnessStrategy2 getAutomaticBrightnessStrategy2(Context context,
+                        int displayId) {
+                    return mAutomaticBrightnessStrategy2;
+                }
+
+                @Override
+                OffloadBrightnessStrategy getOffloadBrightnessStrategy(
+                        DisplayManagerFlags displayManagerFlags) {
                     return mOffloadBrightnessStrategy;
                 }
             };
@@ -162,7 +173,8 @@
         when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
                 DISALLOW_AUTO_BRIGHTNESS_WHILE_DOZING);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
+                                0.1f, false)),
                 mDozeBrightnessModeStrategy);
     }
 
@@ -175,7 +187,8 @@
         when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
                 DISALLOW_AUTO_BRIGHTNESS_WHILE_DOZING);
         assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE)),
+                new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
+                        0.1f, false)),
                 mDozeBrightnessModeStrategy);
     }
 
@@ -184,7 +197,8 @@
         DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
                 DisplayManagerInternal.DisplayPowerRequest.class);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_OFF)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_OFF,
+                                0.1f, false)),
                 mScreenOffBrightnessModeStrategy);
     }
 
@@ -195,7 +209,8 @@
         displayPowerRequest.screenBrightnessOverride = 0.4f;
         when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(Float.NaN);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
                 mOverrideBrightnessStrategy);
     }
 
@@ -207,7 +222,8 @@
         when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(Float.NaN);
         when(mTemporaryBrightnessStrategy.getTemporaryScreenBrightness()).thenReturn(0.3f);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
                 mTemporaryBrightnessStrategy);
     }
 
@@ -220,7 +236,8 @@
         displayPowerRequest.screenBrightnessOverride = Float.NaN;
         when(mTemporaryBrightnessStrategy.getTemporaryScreenBrightness()).thenReturn(Float.NaN);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
                 mBoostBrightnessStrategy);
     }
 
@@ -233,7 +250,8 @@
         when(mTemporaryBrightnessStrategy.getTemporaryScreenBrightness()).thenReturn(Float.NaN);
         when(mOffloadBrightnessStrategy.getOffloadScreenBrightness()).thenReturn(Float.NaN);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
                 mInvalidBrightnessStrategy);
     }
 
@@ -243,7 +261,8 @@
                 DisplayManagerInternal.DisplayPowerRequest.class);
         when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(0.3f);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
                 mFollowerBrightnessStrategy);
     }
 
@@ -257,14 +276,39 @@
         displayPowerRequest.screenBrightnessOverride = Float.NaN;
         when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(Float.NaN);
         when(mTemporaryBrightnessStrategy.getTemporaryScreenBrightness()).thenReturn(Float.NaN);
-        when(mAutomaticBrightnessStrategy.shouldUseAutoBrightness()).thenReturn(true);
+        when(mAutomaticBrightnessStrategy2.shouldUseAutoBrightness()).thenReturn(true);
         when(mOffloadBrightnessStrategy.getOffloadScreenBrightness()).thenReturn(0.3f);
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)),
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
                 mOffloadBrightnessStrategy);
     }
 
     @Test
+    public void selectStrategy_selectsAutomaticStrategyWhenValid() {
+        when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
+        mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
+                mInjector, DISPLAY_ID, mDisplayManagerFlags);
+        DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+                DisplayManagerInternal.DisplayPowerRequest.class);
+        displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+        displayPowerRequest.screenBrightnessOverride = Float.NaN;
+        when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(Float.NaN);
+        when(mTemporaryBrightnessStrategy.getTemporaryScreenBrightness()).thenReturn(Float.NaN);
+        when(mAutomaticBrightnessStrategy.shouldUseAutoBrightness()).thenReturn(true);
+        when(mAutomaticBrightnessStrategy.isAutoBrightnessValid()).thenReturn(true);
+        assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)),
+                mAutomaticBrightnessStrategy);
+        verifyZeroInteractions(mOffloadBrightnessStrategy);
+        verify(mAutomaticBrightnessStrategy).setAutoBrightnessState(Display.STATE_ON,
+                false, BrightnessReason.REASON_UNKNOWN,
+                DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, 0.1f, false);
+
+    }
+
+    @Test
     public void selectStrategyDoesNotSelectOffloadStrategyWhenFeatureFlagDisabled() {
         when(mDisplayManagerFlags.isDisplayOffloadEnabled()).thenReturn(false);
         mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
@@ -277,7 +321,8 @@
         when(mOffloadBrightnessStrategy.getOffloadScreenBrightness()).thenReturn(0.3f);
         assertNotEquals(mOffloadBrightnessStrategy,
                 mDisplayBrightnessStrategySelector.selectStrategy(
-                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON)));
+                        new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                                0.1f, false)));
     }
 
     @Test
@@ -290,10 +335,13 @@
         when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(0.3f);
 
         mDisplayBrightnessStrategySelector.selectStrategy(
-                new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON));
+                new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
+                        0.1f, false));
 
         StrategySelectionNotifyRequest strategySelectionNotifyRequest =
-                new StrategySelectionNotifyRequest(mFollowerBrightnessStrategy);
+                new StrategySelectionNotifyRequest(displayPowerRequest, Display.STATE_ON,
+                        mFollowerBrightnessStrategy, 0.1f,
+                        false, false);
         verify(mInvalidBrightnessStrategy).strategySelectionPostProcessor(
                 eq(strategySelectionNotifyRequest));
         verify(mScreenOffBrightnessModeStrategy).strategySelectionPostProcessor(
@@ -308,5 +356,22 @@
                 eq(strategySelectionNotifyRequest));
         verify(mTemporaryBrightnessStrategy).strategySelectionPostProcessor(
                 eq(strategySelectionNotifyRequest));
+        verify(mAutomaticBrightnessStrategy).strategySelectionPostProcessor(
+                eq(strategySelectionNotifyRequest));
+    }
+
+    @Test
+    public void getAutomaticBrightnessStrategy_getsAutomaticStrategy2IfRefactoringFlagIsNotSet() {
+        assertEquals(mAutomaticBrightnessStrategy2,
+                mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy());
+    }
+
+    @Test
+    public void getAutomaticBrightnessStrategy_getsAutomaticStrategyIfRefactoringFlagIsSet() {
+        when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
+        mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
+                mInjector, DISPLAY_ID, mDisplayManagerFlags);
+        assertEquals(mAutomaticBrightnessStrategy,
+                mDisplayBrightnessStrategySelector.getAutomaticBrightnessStrategy());
     }
 }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
index 39ffe5b..c785ea6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
@@ -221,6 +221,18 @@
         assertEquals(0.04f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
     }
 
+    @Test
+    public void testCalmper_transitionRateOverriddenByOtherRequest() {
+        mHdrClamper.onAmbientLuxChange(499);
+
+        mClock.fastForward(3000);
+        mTestHandler.timeAdvance();
+        assertEquals(0.6f, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+        assertEquals(0.04, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+        // getTransitionRate should reset transitionRate
+        assertEquals(-1f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+    }
+
     // MsgInfo.sendTime is calculated first by adding SystemClock.uptimeMillis()
     // (in Handler.sendMessageDelayed) and then by subtracting SystemClock.uptimeMillis()
     // (in TestHandler.sendMessageAtTime, there might be several milliseconds difference between
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
new file mode 100644
index 0000000..fd43720
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.display.brightness.strategy;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+import android.view.Display;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.util.test.FakeSettingsProviderRule;
+import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.brightness.BrightnessEvent;
+import com.android.server.display.brightness.BrightnessReason;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AutomaticBrightnessStrategy2Test {
+    private static final int DISPLAY_ID = 0;
+    @Rule
+    public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+
+    @Mock
+    private AutomaticBrightnessController mAutomaticBrightnessController;
+
+    private BrightnessConfiguration mBrightnessConfiguration;
+    private float mDefaultScreenAutoBrightnessAdjustment;
+    private Context mContext;
+    private AutomaticBrightnessStrategy2 mAutomaticBrightnessStrategy;
+
+    @Before
+    public void before() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
+        final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
+        when(mContext.getContentResolver()).thenReturn(resolver);
+        mDefaultScreenAutoBrightnessAdjustment = Settings.System.getFloat(
+                mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, Float.NaN);
+        Settings.System.putFloat(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.5f);
+        mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy2(mContext, DISPLAY_ID);
+
+        mBrightnessConfiguration = new BrightnessConfiguration.Builder(
+                new float[]{0f, 1f}, new float[]{0, PowerManager.BRIGHTNESS_ON}).build();
+        when(mAutomaticBrightnessController.hasUserDataPoints()).thenReturn(true);
+        mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
+                mAutomaticBrightnessController);
+        mAutomaticBrightnessStrategy.setBrightnessConfiguration(mBrightnessConfiguration,
+                true);
+    }
+
+    @After
+    public void after() {
+        Settings.System.putFloat(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, mDefaultScreenAutoBrightnessAdjustment);
+    }
+
+    @Test
+    public void testAutoBrightnessState_AutoBrightnessDisabled() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(false);
+        int targetDisplayState = Display.STATE_ON;
+        boolean allowAutoBrightnessWhileDozing = false;
+        int brightnessReason = BrightnessReason.REASON_UNKNOWN;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+        float lastUserSetBrightness = 0.2f;
+        boolean userSetBrightnessChanged = true;
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness,
+                userSetBrightnessChanged);
+        verify(mAutomaticBrightnessController)
+                .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
+                        mBrightnessConfiguration,
+                        lastUserSetBrightness,
+                        userSetBrightnessChanged, /* adjustment */ 0.5f,
+                        /* userChangedAutoBrightnessAdjustment= */ false, policy,
+                        targetDisplayState, /* shouldResetShortTermModel */ true);
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled());
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff());
+    }
+
+    @Test
+    public void testAutoBrightnessState_DisplayIsOff() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        int targetDisplayState = Display.STATE_OFF;
+        boolean allowAutoBrightnessWhileDozing = false;
+        int brightnessReason = BrightnessReason.REASON_UNKNOWN;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
+        float lastUserSetBrightness = 0.2f;
+        boolean userSetBrightnessChanged = true;
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness,
+                userSetBrightnessChanged);
+        verify(mAutomaticBrightnessController)
+                .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
+                        mBrightnessConfiguration,
+                        lastUserSetBrightness,
+                        userSetBrightnessChanged, /* adjustment */ 0.5f,
+                        /* userChangedAutoBrightnessAdjustment= */ false, policy,
+                        targetDisplayState, /* shouldResetShortTermModel */ true);
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled());
+        assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff());
+    }
+
+    @Test
+    public void testAutoBrightnessState_DisplayIsInDoze_ConfigDoesNotAllow() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        int targetDisplayState = Display.STATE_DOZE;
+        boolean allowAutoBrightnessWhileDozing = false;
+        int brightnessReason = BrightnessReason.REASON_UNKNOWN;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+        float lastUserSetBrightness = 0.2f;
+        boolean userSetBrightnessChanged = true;
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness,
+                userSetBrightnessChanged);
+        verify(mAutomaticBrightnessController)
+                .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
+                        mBrightnessConfiguration,
+                        lastUserSetBrightness,
+                        userSetBrightnessChanged, /* adjustment */ 0.5f,
+                        /* userChangedAutoBrightnessAdjustment= */ false, policy,
+                        targetDisplayState, /* shouldResetShortTermModel */ true);
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled());
+        assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff());
+    }
+
+    @Test
+    public void testAutoBrightnessState_BrightnessReasonIsOverride() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        int targetDisplayState = Display.STATE_ON;
+        boolean allowAutoBrightnessWhileDozing = false;
+        int brightnessReason = BrightnessReason.REASON_OVERRIDE;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+        float lastUserSetBrightness = 0.2f;
+        boolean userSetBrightnessChanged = true;
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness,
+                userSetBrightnessChanged);
+        verify(mAutomaticBrightnessController)
+                .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
+                        mBrightnessConfiguration,
+                        lastUserSetBrightness,
+                        userSetBrightnessChanged, /* adjustment */ 0.5f,
+                        /* userChangedAutoBrightnessAdjustment= */ false, policy,
+                        targetDisplayState, /* shouldResetShortTermModel */ true);
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled());
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff());
+    }
+
+    @Test
+    public void testAutoBrightnessState_DisplayIsInDoze_ConfigDoesAllow() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        int targetDisplayState = Display.STATE_DOZE;
+        boolean allowAutoBrightnessWhileDozing = true;
+        int brightnessReason = BrightnessReason.REASON_UNKNOWN;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+        float lastUserSetBrightness = 0.2f;
+        boolean userSetBrightnessChanged = true;
+        Settings.System.putFloat(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.4f);
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness,
+                userSetBrightnessChanged);
+        verify(mAutomaticBrightnessController)
+                .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
+                        mBrightnessConfiguration,
+                        lastUserSetBrightness,
+                        userSetBrightnessChanged, /* adjustment */ 0.4f,
+                        /* userChangedAutoBrightnessAdjustment= */ true, policy,
+                        targetDisplayState, /* shouldResetShortTermModel */ true);
+        assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled());
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff());
+    }
+
+    @Test
+    public void testAutoBrightnessState_DisplayIsOn() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        int targetDisplayState = Display.STATE_ON;
+        boolean allowAutoBrightnessWhileDozing = false;
+        int brightnessReason = BrightnessReason.REASON_UNKNOWN;
+        float lastUserSetBrightness = 0.2f;
+        boolean userSetBrightnessChanged = true;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+        float pendingBrightnessAdjustment = 0.1f;
+        Settings.System.putFloat(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment);
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness,
+                userSetBrightnessChanged);
+        verify(mAutomaticBrightnessController)
+                .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
+                        mBrightnessConfiguration,
+                        lastUserSetBrightness,
+                        userSetBrightnessChanged, pendingBrightnessAdjustment,
+                        /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState,
+                        /* shouldResetShortTermModel */ true);
+        assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled());
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff());
+    }
+
+    @Test
+    public void accommodateUserBrightnessChangesWorksAsExpected() {
+        // Verify the state if automaticBrightnessController is configured.
+        assertFalse(mAutomaticBrightnessStrategy.isShortTermModelActive());
+        boolean userSetBrightnessChanged = true;
+        float lastUserSetScreenBrightness = 0.2f;
+        int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT;
+        int targetDisplayState = Display.STATE_ON;
+        BrightnessConfiguration brightnessConfiguration = new BrightnessConfiguration.Builder(
+                new float[]{0f, 1f}, new float[]{0, PowerManager.BRIGHTNESS_ON}).build();
+        int autoBrightnessState = AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
+        float temporaryAutoBrightnessAdjustments = 0.4f;
+        mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true);
+        setTemporaryAutoBrightnessAdjustment(temporaryAutoBrightnessAdjustments);
+        mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged,
+                lastUserSetScreenBrightness, policy, targetDisplayState, brightnessConfiguration,
+                autoBrightnessState);
+        verify(mAutomaticBrightnessController).configure(autoBrightnessState,
+                brightnessConfiguration,
+                lastUserSetScreenBrightness,
+                userSetBrightnessChanged, temporaryAutoBrightnessAdjustments,
+                /* userChangedAutoBrightnessAdjustment= */ false, policy, targetDisplayState,
+                /* shouldResetShortTermModel= */ true);
+        assertTrue(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied());
+        assertFalse(mAutomaticBrightnessStrategy.shouldResetShortTermModel());
+        assertTrue(mAutomaticBrightnessStrategy.isShortTermModelActive());
+        // Verify the state when automaticBrightnessController is not configured
+        setTemporaryAutoBrightnessAdjustment(Float.NaN);
+        mAutomaticBrightnessStrategy.setAutomaticBrightnessController(null);
+        mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true);
+        mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged,
+                lastUserSetScreenBrightness, policy, targetDisplayState, brightnessConfiguration,
+                autoBrightnessState);
+        assertFalse(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied());
+        assertTrue(mAutomaticBrightnessStrategy.shouldResetShortTermModel());
+        assertFalse(mAutomaticBrightnessStrategy.isShortTermModelActive());
+    }
+
+    @Test
+    public void adjustAutomaticBrightnessStateIfValid() throws Settings.SettingNotFoundException {
+        float brightnessState = 0.3f;
+        float autoBrightnessAdjustment = 0.2f;
+        when(mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()).thenReturn(
+                autoBrightnessAdjustment);
+        mAutomaticBrightnessStrategy.adjustAutomaticBrightnessStateIfValid(brightnessState);
+        assertEquals(autoBrightnessAdjustment,
+                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f);
+        assertEquals(autoBrightnessAdjustment, Settings.System.getFloatForUser(
+                mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
+                UserHandle.USER_CURRENT), 0.0f);
+        assertEquals(BrightnessReason.ADJUSTMENT_AUTO,
+                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags());
+        float invalidBrightness = -0.5f;
+        mAutomaticBrightnessStrategy
+                .adjustAutomaticBrightnessStateIfValid(invalidBrightness);
+        assertEquals(autoBrightnessAdjustment,
+                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f);
+        assertEquals(0,
+                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags());
+    }
+
+    @Test
+    public void updatePendingAutoBrightnessAdjustments() {
+        // Verify the state when the pendingAutoBrightnessAdjustments are not present
+        setPendingAutoBrightnessAdjustment(Float.NaN);
+        assertFalse(mAutomaticBrightnessStrategy.processPendingAutoBrightnessAdjustments());
+        assertFalse(mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged());
+        // Verify the state when the pendingAutoBrightnessAdjustments are present, but
+        // pendingAutoBrightnessAdjustments and autoBrightnessAdjustments are the same
+        float autoBrightnessAdjustment = 0.3f;
+        setPendingAutoBrightnessAdjustment(autoBrightnessAdjustment);
+        setAutoBrightnessAdjustment(autoBrightnessAdjustment);
+        assertFalse(mAutomaticBrightnessStrategy.processPendingAutoBrightnessAdjustments());
+        assertFalse(mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged());
+        assertEquals(Float.NaN, mAutomaticBrightnessStrategy.getPendingAutoBrightnessAdjustment(),
+                0.0f);
+        // Verify the state when the pendingAutoBrightnessAdjustments are present, and
+        // pendingAutoBrightnessAdjustments and autoBrightnessAdjustments are not the same
+        float pendingAutoBrightnessAdjustment = 0.2f;
+        setPendingAutoBrightnessAdjustment(pendingAutoBrightnessAdjustment);
+        setTemporaryAutoBrightnessAdjustment(0.1f);
+        assertTrue(mAutomaticBrightnessStrategy.processPendingAutoBrightnessAdjustments());
+        assertTrue(mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged());
+        assertEquals(pendingAutoBrightnessAdjustment,
+                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f);
+        assertEquals(Float.NaN, mAutomaticBrightnessStrategy.getPendingAutoBrightnessAdjustment(),
+                0.0f);
+        assertEquals(Float.NaN, mAutomaticBrightnessStrategy.getTemporaryAutoBrightnessAdjustment(),
+                0.0f);
+    }
+
+    @Test
+    public void setAutomaticBrightnessWorksAsExpected() {
+        float automaticScreenBrightness = 0.3f;
+        AutomaticBrightnessController automaticBrightnessController = mock(
+                AutomaticBrightnessController.class);
+        when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class)))
+                .thenReturn(automaticScreenBrightness);
+        when(automaticBrightnessController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+                any(BrightnessEvent.class)))
+                .thenReturn(automaticScreenBrightness);
+        mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
+                automaticBrightnessController);
+        assertEquals(automaticScreenBrightness,
+                mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
+                        new BrightnessEvent(DISPLAY_ID)), 0.0f);
+        assertEquals(automaticScreenBrightness,
+                mAutomaticBrightnessStrategy.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+                        new BrightnessEvent(DISPLAY_ID)), 0.0f);
+    }
+
+    @Test
+    public void shouldUseAutoBrightness() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        assertTrue(mAutomaticBrightnessStrategy.shouldUseAutoBrightness());
+    }
+
+    @Test
+    public void setPendingAutoBrightnessAdjustments() throws Settings.SettingNotFoundException {
+        float pendingAutoBrightnessAdjustments = 0.3f;
+        setPendingAutoBrightnessAdjustment(pendingAutoBrightnessAdjustments);
+        assertEquals(pendingAutoBrightnessAdjustments,
+                mAutomaticBrightnessStrategy.getPendingAutoBrightnessAdjustment(), 0.0f);
+        assertEquals(pendingAutoBrightnessAdjustments, Settings.System.getFloatForUser(
+                mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
+                UserHandle.USER_CURRENT), 0.0f);
+    }
+
+    @Test
+    public void setTemporaryAutoBrightnessAdjustment() {
+        float temporaryAutoBrightnessAdjustment = 0.3f;
+        mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment(
+                temporaryAutoBrightnessAdjustment);
+        assertEquals(temporaryAutoBrightnessAdjustment,
+                mAutomaticBrightnessStrategy.getTemporaryAutoBrightnessAdjustment(), 0.0f);
+    }
+
+    @Test
+    public void setAutoBrightnessApplied() {
+        mAutomaticBrightnessStrategy.setAutoBrightnessApplied(true);
+        assertTrue(mAutomaticBrightnessStrategy.hasAppliedAutoBrightness());
+    }
+
+    @Test
+    public void testVerifyNoAutoBrightnessAdjustmentsArePopulatedForNonDefaultDisplay() {
+        int newDisplayId = 1;
+        mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy2(mContext, newDisplayId);
+        mAutomaticBrightnessStrategy.putAutoBrightnessAdjustmentSetting(0.3f);
+        assertEquals(0.5f, mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(),
+                0.0f);
+    }
+
+    private void setPendingAutoBrightnessAdjustment(float pendingAutoBrightnessAdjustment) {
+        Settings.System.putFloat(mContext.getContentResolver(),
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingAutoBrightnessAdjustment);
+        mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
+    }
+
+    private void setTemporaryAutoBrightnessAdjustment(float temporaryAutoBrightnessAdjustment) {
+        mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment(
+                temporaryAutoBrightnessAdjustment);
+    }
+
+    private void setAutoBrightnessAdjustment(float autoBrightnessAdjustment) {
+        mAutomaticBrightnessStrategy.putAutoBrightnessAdjustmentSetting(autoBrightnessAdjustment);
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
index 4e55270..54f2268 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
@@ -41,8 +41,10 @@
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
 import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.After;
 import org.junit.Before;
@@ -295,15 +297,11 @@
                 mContext.getContentResolver(),
                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
                 UserHandle.USER_CURRENT), 0.0f);
-        assertEquals(BrightnessReason.ADJUSTMENT_AUTO,
-                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags());
         float invalidBrightness = -0.5f;
         mAutomaticBrightnessStrategy
                 .adjustAutomaticBrightnessStateIfValid(invalidBrightness);
         assertEquals(autoBrightnessAdjustment,
                 mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f);
-        assertEquals(0,
-                mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags());
     }
 
     @Test
@@ -398,6 +396,108 @@
                 0.0f);
     }
 
+    @Test
+    public void isAutoBrightnessValid_returnsFalseWhenAutoBrightnessIsDisabled() {
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessValid());
+    }
+
+    @Test
+    public void isAutoBrightnessValid_returnsFalseWhenBrightnessIsInvalid() {
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, true,
+                BrightnessReason.REASON_UNKNOWN,
+                DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, 0.1f,
+                false);
+        when(mAutomaticBrightnessController.getAutomaticScreenBrightness(null))
+                .thenReturn(Float.NaN);
+        assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessValid());
+    }
+
+    @Test
+    public void isAutoBrightnessValid_returnsTrueWhenBrightnessIsValid() {
+        mAutomaticBrightnessStrategy.setUseAutoBrightness(true);
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, true,
+                BrightnessReason.REASON_UNKNOWN,
+                DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, 0.1f,
+                false);
+        when(mAutomaticBrightnessController.getAutomaticScreenBrightness(null))
+                .thenReturn(0.2f);
+        assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessValid());
+    }
+
+    @Test
+    public void
+            updateBrightness_constructsDisplayBrightnessState_withAdjustmentAutoAdjustmentFlag() {
+        BrightnessEvent brightnessEvent = new BrightnessEvent(DISPLAY_ID);
+        mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(
+                mContext, DISPLAY_ID, displayId -> brightnessEvent);
+        new AutomaticBrightnessStrategy(mContext, DISPLAY_ID);
+        mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
+                mAutomaticBrightnessController);
+        float brightness = 0.4f;
+        BrightnessReason brightnessReason = new BrightnessReason();
+        brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
+        when(mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent))
+                .thenReturn(brightness);
+
+        DisplayManagerInternal.DisplayPowerRequest displayPowerRequest =
+                mock(DisplayManagerInternal.DisplayPowerRequest.class);
+        DisplayBrightnessState expectedDisplayBrightnessState = new DisplayBrightnessState.Builder()
+                .setBrightness(brightness)
+                .setSdrBrightness(brightness)
+                .setBrightnessReason(brightnessReason)
+                .setDisplayBrightnessStrategyName(mAutomaticBrightnessStrategy.getName())
+                .setIsSlowChange(false)
+                .setBrightnessEvent(brightnessEvent)
+                .setBrightnessAdjustmentFlag(BrightnessReason.ADJUSTMENT_AUTO)
+                .setShouldUpdateScreenBrightnessSetting(true)
+                .build();
+        DisplayBrightnessState actualDisplayBrightnessState = mAutomaticBrightnessStrategy
+                .updateBrightness(new StrategyExecutionRequest(displayPowerRequest, 0.6f));
+        assertEquals(expectedDisplayBrightnessState, actualDisplayBrightnessState);
+    }
+
+    @Test
+    public void
+            updateBrightness_constructsDisplayBrightnessState_withAdjustmentTempAdjustmentFlag() {
+        BrightnessEvent brightnessEvent = new BrightnessEvent(DISPLAY_ID);
+        mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(
+                mContext, DISPLAY_ID, displayId -> brightnessEvent);
+        new AutomaticBrightnessStrategy(mContext, DISPLAY_ID);
+        mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
+                mAutomaticBrightnessController);
+        float brightness = 0.4f;
+        BrightnessReason brightnessReason = new BrightnessReason();
+        brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
+        when(mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent))
+                .thenReturn(brightness);
+
+        DisplayManagerInternal.DisplayPowerRequest displayPowerRequest =
+                mock(DisplayManagerInternal.DisplayPowerRequest.class);
+        float temporaryBrightness = 0.3f;
+        float autoBrightnessAdjustment = 0.1f;
+        mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment(temporaryBrightness);
+        mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(true,
+                brightness, DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT,
+                Display.STATE_ON, mock(BrightnessConfiguration.class),
+                AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED);
+        when(mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()).thenReturn(
+                autoBrightnessAdjustment);
+
+        DisplayBrightnessState expectedDisplayBrightnessState = new DisplayBrightnessState.Builder()
+                .setBrightness(brightness)
+                .setSdrBrightness(brightness)
+                .setBrightnessReason(brightnessReason)
+                .setDisplayBrightnessStrategyName(mAutomaticBrightnessStrategy.getName())
+                .setIsSlowChange(false)
+                .setBrightnessEvent(brightnessEvent)
+                .setBrightnessAdjustmentFlag(BrightnessReason.ADJUSTMENT_AUTO_TEMP)
+                .setShouldUpdateScreenBrightnessSetting(true)
+                .build();
+        DisplayBrightnessState actualDisplayBrightnessState = mAutomaticBrightnessStrategy
+                .updateBrightness(new StrategyExecutionRequest(displayPowerRequest, 0.6f));
+        assertEquals(expectedDisplayBrightnessState, actualDisplayBrightnessState);
+    }
+
     private void setPendingAutoBrightnessAdjustment(float pendingAutoBrightnessAdjustment) {
         Settings.System.putFloat(mContext.getContentResolver(),
                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingAutoBrightnessAdjustment);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
index c434631..47f1746 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
@@ -27,6 +27,7 @@
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -58,7 +59,8 @@
                         .setDisplayBrightnessStrategyName(mBoostBrightnessStrategy.getName())
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mBoostBrightnessStrategy.updateBrightness(displayPowerRequest);
+                mBoostBrightnessStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
     }
 
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
index d60caf6..9246780 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
@@ -25,6 +25,7 @@
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -55,7 +56,8 @@
                         .setDisplayBrightnessStrategyName(mDozeBrightnessModeStrategy.getName())
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mDozeBrightnessModeStrategy.updateBrightness(displayPowerRequest);
+                mDozeBrightnessModeStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
     }
 }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
index d8569f7..682c9cc 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -59,7 +60,8 @@
                         .setIsSlowChange(slowChange)
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mFollowerBrightnessStrategy.updateBrightness(displayPowerRequest);
+                mFollowerBrightnessStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(expectedDisplayBrightnessState, updatedDisplayBrightnessState);
     }
 
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java
index 36719af..ccf6309 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java
@@ -17,32 +17,45 @@
 package com.android.server.display.brightness.strategy;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.hardware.display.DisplayManagerInternal;
+import android.os.PowerManager;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
+import com.android.server.display.feature.DisplayManagerFlags;
 
 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)
 public class OffloadBrightnessStrategyTest {
 
+    @Mock
+    private DisplayManagerFlags mDisplayManagerFlags;
+
     private OffloadBrightnessStrategy mOffloadBrightnessStrategy;
 
     @Before
     public void before() {
-        mOffloadBrightnessStrategy = new OffloadBrightnessStrategy();
+        MockitoAnnotations.initMocks(this);
+        mOffloadBrightnessStrategy = new OffloadBrightnessStrategy(mDisplayManagerFlags);
     }
 
     @Test
     public void testUpdateBrightnessWhenOffloadBrightnessIsSet() {
+        when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
         DisplayManagerInternal.DisplayPowerRequest
                 displayPowerRequest = new DisplayManagerInternal.DisplayPowerRequest();
         float brightness = 0.2f;
@@ -58,7 +71,44 @@
                         .setShouldUpdateScreenBrightnessSetting(true)
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mOffloadBrightnessStrategy.updateBrightness(displayPowerRequest);
+                mOffloadBrightnessStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
+        assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT, mOffloadBrightnessStrategy
+                .getOffloadScreenBrightness(), 0.0f);
+    }
+
+    @Test
+    public void strategySelectionPostProcessor_resetsOffloadBrightness() {
+        StrategySelectionNotifyRequest strategySelectionNotifyRequest =
+                mock(StrategySelectionNotifyRequest.class);
+        DisplayBrightnessStrategy displayBrightnessStrategy = mock(DisplayBrightnessStrategy.class);
+        when(strategySelectionNotifyRequest.getSelectedDisplayBrightnessStrategy())
+                .thenReturn(displayBrightnessStrategy);
+
+        float offloadBrightness = 0.3f;
+        mOffloadBrightnessStrategy.setOffloadScreenBrightness(offloadBrightness);
+
+        // Brightness is not reset if offload strategy is selected
+        when(displayBrightnessStrategy.getName())
+                .thenReturn(mOffloadBrightnessStrategy.getName());
+        mOffloadBrightnessStrategy.strategySelectionPostProcessor(strategySelectionNotifyRequest);
+        assertEquals(offloadBrightness,
+                mOffloadBrightnessStrategy.getOffloadScreenBrightness(), 0.0f);
+
+        // Brightness is not reset if invalid strategy is selected
+        when(displayBrightnessStrategy.getName())
+                .thenReturn(DisplayBrightnessStrategyConstants.INVALID_BRIGHTNESS_STRATEGY_NAME);
+        mOffloadBrightnessStrategy.strategySelectionPostProcessor(strategySelectionNotifyRequest);
+        assertEquals(offloadBrightness,
+                mOffloadBrightnessStrategy.getOffloadScreenBrightness(), 0.0f);
+
+
+        // Brightness is reset if neither of invalid or offload strategy is selected
+        when(displayBrightnessStrategy.getName())
+                .thenReturn("DisplayBrightnessStrategy");
+        mOffloadBrightnessStrategy.strategySelectionPostProcessor(strategySelectionNotifyRequest);
+        assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
+                mOffloadBrightnessStrategy.getOffloadScreenBrightness(), 0.0f);
     }
 }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
index 530245d..8e7b463 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -58,7 +59,8 @@
                         .setDisplayBrightnessStrategyName(mOverrideBrightnessStrategy.getName())
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mOverrideBrightnessStrategy.updateBrightness(displayPowerRequest);
+                mOverrideBrightnessStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
     }
 
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
index 7147aa8..e799d0e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -56,7 +57,8 @@
                                 .getName())
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mScreenOffBrightnessModeStrategy.updateBrightness(displayPowerRequest);
+                mScreenOffBrightnessModeStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
     }
 }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
index 9830edb..aaada41 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
 
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -58,7 +59,8 @@
                         .setDisplayBrightnessStrategyName(mTemporaryBrightnessStrategy.getName())
                         .build();
         DisplayBrightnessState updatedDisplayBrightnessState =
-                mTemporaryBrightnessStrategy.updateBrightness(displayPowerRequest);
+                mTemporaryBrightnessStrategy.updateBrightness(
+                        new StrategyExecutionRequest(displayPowerRequest, 0.2f));
         assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
     }
 
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/BrightnessObserverTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/BrightnessObserverTest.kt
index b182cce..88c0daa 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/BrightnessObserverTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/BrightnessObserverTest.kt
@@ -19,11 +19,13 @@
 import android.content.Context
 import android.content.ContextWrapper
 import android.hardware.display.BrightnessInfo
+import android.util.SparseArray
 import android.view.Display
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.SmallTest
 import com.android.server.display.DisplayDeviceConfig
 import com.android.server.display.feature.DisplayManagerFlags
+import com.android.server.display.mode.DisplayModeDirector.DisplayDeviceConfigProvider
 import com.android.server.testutils.TestHandler
 import com.google.common.truth.Truth.assertThat
 import com.google.testing.junit.testparameterinjector.TestParameter
@@ -48,6 +50,7 @@
     private val mockInjector = mock<DisplayModeDirector.Injector>()
     private val mockFlags = mock<DisplayManagerFlags>()
     private val mockDeviceConfig = mock<DisplayDeviceConfig>()
+    private val mockDisplayDeviceConfigProvider = mock<DisplayDeviceConfigProvider>()
 
     private val testHandler = TestHandler(null)
 
@@ -61,9 +64,13 @@
         setUpLowBrightnessZone()
         whenever(mockFlags.isVsyncLowLightVoteEnabled).thenReturn(testCase.vsyncLowLightVoteEnabled)
         val displayModeDirector = DisplayModeDirector(
-                spyContext, testHandler, mockInjector, mockFlags)
+                spyContext, testHandler, mockInjector, mockFlags, mockDisplayDeviceConfigProvider)
+        val ddcByDisplay = SparseArray<DisplayDeviceConfig>()
+        whenever(mockDeviceConfig.isVrrSupportEnabled).thenReturn(testCase.vrrSupported)
+        ddcByDisplay.put(Display.DEFAULT_DISPLAY, mockDeviceConfig)
+        displayModeDirector.injectDisplayDeviceConfigByDisplay(ddcByDisplay)
         val brightnessObserver = displayModeDirector.BrightnessObserver(
-                spyContext, testHandler, mockInjector, testCase.vrrSupported, mockFlags)
+                spyContext, testHandler, mockInjector, mockFlags)
 
         brightnessObserver.onRefreshRateSettingChangedLocked(0.0f, 120.0f)
         brightnessObserver.updateBlockingZoneThresholds(mockDeviceConfig, false)
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index fbc38a2..a2a4773 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -94,6 +94,7 @@
 import com.android.server.display.DisplayDeviceConfig;
 import com.android.server.display.TestUtils;
 import com.android.server.display.config.IdleScreenRefreshRateTimeoutLuxThresholdPoint;
+import com.android.server.display.config.RefreshRateData;
 import com.android.server.display.feature.DisplayManagerFlags;
 import com.android.server.display.mode.DisplayModeDirector.BrightnessObserver;
 import com.android.server.display.mode.DisplayModeDirector.DesiredDisplayModeSpecs;
@@ -128,6 +129,12 @@
 @SmallTest
 @RunWith(JUnitParamsRunner.class)
 public class DisplayModeDirectorTest {
+    private static final RefreshRateData EMPTY_REFRESH_RATE_DATA = new RefreshRateData(
+            /* defaultRefreshRate= */ 0,
+            /* defaultPeakRefreshRate= */ 0,
+            /* defaultRefreshRateInHbmHdr= */ 0,
+            /* defaultRefreshRateInHbmSunlight= */ 0);
+
     public static Collection<Object[]> getAppRequestedSizeTestCases() {
         var appRequestedSizeTestCases = Arrays.asList(new Object[][] {
                 {/*expectedBaseModeId*/ DEFAULT_MODE_75.getModeId(),
@@ -312,6 +319,8 @@
     public DisplayManagerInternal mDisplayManagerInternalMock;
     @Mock
     private DisplayManagerFlags mDisplayManagerFlags;
+    @Mock
+    private DisplayModeDirector.DisplayDeviceConfigProvider mDisplayDeviceConfigProvider;
 
     @Rule
     public final ExtendedMockitoRule mExtendedMockitoRule =
@@ -338,8 +347,6 @@
                 .thenReturn(false);
         when(resources.getBoolean(R.bool.config_refreshRateSynchronizationEnabled))
                 .thenReturn(false);
-        when(resources.getBoolean(R.bool.config_supportsDvrr))
-                .thenReturn(false);
         when(resources.getInteger(R.integer.config_displayWhiteBalanceBrightnessFilterHorizon))
                 .thenReturn(10000);
         when(resources.getInteger(R.integer.config_defaultPeakRefreshRate))
@@ -393,41 +400,88 @@
 
     private DisplayModeDirector createDirectorFromRefreshRateArray(
             float[] refreshRates, int baseModeId, float defaultRefreshRate) {
-        Display.Mode[] modes = new Display.Mode[refreshRates.length];
-        Display.Mode defaultMode = null;
-        for (int i = 0; i < refreshRates.length; i++) {
-            modes[i] = new Display.Mode(
-                    /*modeId=*/baseModeId + i, /*width=*/1000, /*height=*/1000, refreshRates[i]);
-            if (refreshRates[i] == defaultRefreshRate) {
-                defaultMode = modes[i];
-            }
-        }
+        return createDirectorFromRefreshRateArray(refreshRates, baseModeId, defaultRefreshRate,
+                new int[]{DISPLAY_ID});
+    }
+
+    private DisplayModeDirector createDirectorFromRefreshRateArray(
+            float[] refreshRates, int baseModeId, float defaultRefreshRate, int[] displayIds) {
+        Display.Mode[] modes = createDisplayModes(refreshRates, baseModeId);
+        Display.Mode defaultMode = getDefaultMode(modes, defaultRefreshRate);
+
         assertThat(defaultMode).isNotNull();
-        return createDirectorFromModeArray(modes, defaultMode);
+        return createDirectorFromModeArray(modes, defaultMode, displayIds);
     }
 
     private DisplayModeDirector createDirectorFromModeArray(Display.Mode[] modes,
             Display.Mode defaultMode) {
+        return createDirectorFromModeArray(modes, defaultMode, new int[]{DISPLAY_ID});
+    }
+
+    private DisplayModeDirector createDirectorFromModeArray(Display.Mode[] modes,
+            Display.Mode defaultMode, int[] displayIds) {
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.setLoggingEnabled(true);
-        SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
-        supportedModesByDisplay.put(DISPLAY_ID, modes);
-        director.injectSupportedModesByDisplay(supportedModesByDisplay);
-        SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>();
-        defaultModesByDisplay.put(DISPLAY_ID, defaultMode);
-        director.injectDefaultModeByDisplay(defaultModesByDisplay);
+        setupModesForDisplays(director, displayIds , modes, defaultMode);
         return director;
     }
 
     private DisplayModeDirector createDirectorFromFpsRange(int minFps, int maxFps) {
+        return createDirectorFromRefreshRateArray(
+                createRefreshRateRanges(minFps, maxFps),
+                /*baseModeId=*/minFps,
+                /*defaultRefreshRate=*/minFps,
+                new int[]{DISPLAY_ID});
+    }
+
+    private DisplayModeDirector createDirectorFromFpsRange(
+            int minFps, int maxFps, int[] displayIds) {
+        return createDirectorFromRefreshRateArray(
+                createRefreshRateRanges(minFps, maxFps),
+                /*baseModeId=*/minFps,
+                /*defaultRefreshRate=*/minFps,
+                displayIds);
+    }
+
+    private void setupModesForDisplays(DisplayModeDirector director, int[] displayIds,
+            Display.Mode[] modes, Display.Mode defaultMode) {
+        SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
+        SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>();
+        for (int displayId: displayIds) {
+            supportedModesByDisplay.put(displayId, modes);
+            defaultModesByDisplay.put(displayId, defaultMode);
+        }
+        director.injectSupportedModesByDisplay(supportedModesByDisplay);
+        director.injectDefaultModeByDisplay(defaultModesByDisplay);
+    }
+
+    private Display.Mode[] createDisplayModes(float[] refreshRates, int baseModeId) {
+        Display.Mode[] modes = new Display.Mode[refreshRates.length];
+        for (int i = 0; i < refreshRates.length; i++) {
+            modes[i] = new Display.Mode(
+                    /*modeId=*/baseModeId + i, /*width=*/1000, /*height=*/1000, refreshRates[i]);
+        }
+        return modes;
+    }
+
+    private Display.Mode getDefaultMode(Display.Mode[] modes, float defaultRefreshRate) {
+        for (Display.Mode mode : modes) {
+            if (mode.getRefreshRate() == defaultRefreshRate) {
+                return mode;
+            }
+        }
+        return null;
+    }
+
+    private float[] createRefreshRateRanges(int minFps, int maxFps) {
         int numRefreshRates = maxFps - minFps + 1;
         float[] refreshRates = new float[numRefreshRates];
         for (int i = 0; i < numRefreshRates; i++) {
             refreshRates[i] = minFps + i;
         }
-        return createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/minFps,
-                /*defaultRefreshRate=*/minFps);
+        return refreshRates;
     }
 
     @Test
@@ -1102,7 +1156,8 @@
     @Test
     public void testStaleAppRequestSize() {
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         Display.Mode[] modes = new Display.Mode[] {
                 new Display.Mode(1, 1280, 720, 60),
         };
@@ -1353,7 +1408,8 @@
         when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
                 .thenReturn(true);
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
 
         Display.Mode[] modes1 = new Display.Mode[] {
@@ -1496,6 +1552,7 @@
 
         // Set the DisplayDeviceConfig
         DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
+        when(ddcMock.getRefreshRateData()).thenReturn(EMPTY_REFRESH_RATE_DATA);
         when(ddcMock.getDefaultHighBlockingZoneRefreshRate()).thenReturn(90);
         when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new float[] { 200 });
         when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new float[] { 8000 });
@@ -1576,6 +1633,7 @@
 
         // Set the thresholds for High Zone
         DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
+        when(ddcMock.getRefreshRateData()).thenReturn(EMPTY_REFRESH_RATE_DATA);
         when(ddcMock.getDefaultHighBlockingZoneRefreshRate()).thenReturn(90);
         when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new float[] { 200 });
         when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new float[] { 8000 });
@@ -1675,6 +1733,7 @@
 
         // Set the thresholds for Low Zone
         DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
+        when(ddcMock.getRefreshRateData()).thenReturn(EMPTY_REFRESH_RATE_DATA);
         when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(90);
         when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new float[] { 200 });
         when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new float[] { 8000 });
@@ -1764,7 +1823,8 @@
         when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
                 .thenReturn(true);
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
 
         Display.Mode[] modes1 = new Display.Mode[] {
@@ -1844,7 +1904,8 @@
         when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
                 .thenReturn(true);
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
         mInjector.mDisplayInfo.supportedModes = new Display.Mode[] {
                 new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
@@ -1893,6 +1954,7 @@
         mInjector.mDisplayInfo.displayId = DISPLAY_ID_2;
 
         DisplayModeDirector director = createDirectorFromModeArray(TEST_MODES, DEFAULT_MODE_60);
+        director.start(createMockSensorManager());
 
         SparseArray<Vote> votes = new SparseArray<>();
         votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 50f));
@@ -1913,7 +1975,8 @@
         when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
                 .thenReturn(true);
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
 
         Display.Mode[] modes1 = new Display.Mode[] {
@@ -1993,7 +2056,8 @@
         when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
                 .thenReturn(true);
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
         mInjector.mDisplayInfo.supportedModes = new Display.Mode[] {
                 new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720,
@@ -2031,7 +2095,8 @@
         when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled())
                 .thenReturn(true);
         DisplayModeDirector director =
-                new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+                new DisplayModeDirector(mContext, mHandler, mInjector,
+                        mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
 
         Display.Mode[] modes1 = new Display.Mode[] {
@@ -3312,10 +3377,14 @@
 
         // Notify that the default display is updated, such that DisplayDeviceConfig has new values
         DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
+        RefreshRateData refreshRateData = new RefreshRateData(
+                /* defaultRefreshRate= */ 60,
+                /* defaultPeakRefreshRate= */ 65,
+                /* defaultRefreshRateInHbmHdr= */ 65,
+                /* defaultRefreshRateInHbmSunlight= */ 75);
+        when(displayDeviceConfig.getRefreshRateData()).thenReturn(refreshRateData);
         when(displayDeviceConfig.getDefaultLowBlockingZoneRefreshRate()).thenReturn(50);
         when(displayDeviceConfig.getDefaultHighBlockingZoneRefreshRate()).thenReturn(55);
-        when(displayDeviceConfig.getDefaultRefreshRate()).thenReturn(60);
-        when(displayDeviceConfig.getDefaultPeakRefreshRate()).thenReturn(65);
         when(displayDeviceConfig.getLowDisplayBrightnessThresholds())
                 .thenReturn(new float[]{0.025f});
         when(displayDeviceConfig.getLowAmbientBrightnessThresholds())
@@ -3324,8 +3393,6 @@
                 .thenReturn(new float[]{0.21f});
         when(displayDeviceConfig.getHighAmbientBrightnessThresholds())
                 .thenReturn(new float[]{2100});
-        when(displayDeviceConfig.getDefaultRefreshRateInHbmHdr()).thenReturn(65);
-        when(displayDeviceConfig.getDefaultRefreshRateInHbmSunlight()).thenReturn(75);
         director.defaultDisplayDeviceUpdated(displayDeviceConfig);
 
         // Verify the new values are from the freshly loaded DisplayDeviceConfig.
@@ -3435,6 +3502,7 @@
                         any(Handler.class));
 
         DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
+        when(ddcMock.getRefreshRateData()).thenReturn(EMPTY_REFRESH_RATE_DATA);
         when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(50);
         when(ddcMock.getDefaultHighBlockingZoneRefreshRate()).thenReturn(55);
         when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new float[]{0.025f});
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java
index 92016df..2d317af 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java
@@ -39,6 +39,7 @@
 import android.content.ContextWrapper;
 import android.content.res.Resources;
 import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.DeviceConfigInterface;
@@ -112,6 +113,8 @@
     private Resources mResources;
     @Mock
     private DisplayManagerFlags mDisplayManagerFlags;
+    @Mock
+    private DisplayModeDirector.DisplayDeviceConfigProvider mDisplayDeviceConfigProvider;
     private int mExternalDisplayUserPreferredModeId = INVALID_MODE_ID;
     private int mInternalDisplayUserPreferredModeId = INVALID_MODE_ID;
     private Display mDefaultDisplay;
@@ -426,8 +429,12 @@
             return true;
         }).when(mInjector).getDisplayInfo(eq(EXTERNAL_DISPLAY), /*displayInfo=*/ any());
 
-        doAnswer(c -> mock(SensorManagerInternal.class)).when(mInjector).getSensorManagerInternal();
+        doAnswer(c -> mock(SensorManagerInternal.class))
+                .when(mInjector).getSensorManagerInternal();
         doAnswer(c -> mock(DeviceConfigInterface.class)).when(mInjector).getDeviceConfig();
+        doAnswer(c -> mock(DisplayManagerInternal.class))
+                .when(mInjector).getDisplayManagerInternal();
+
 
         mDefaultDisplay = mock(Display.class);
         when(mDefaultDisplay.getDisplayId()).thenReturn(DEFAULT_DISPLAY);
@@ -441,7 +448,8 @@
 
         when(mInjector.getDisplays()).thenReturn(new Display[] {mDefaultDisplay, mExternalDisplay});
 
-        mDmd = new DisplayModeDirector(mContext, mHandler, mInjector, mDisplayManagerFlags);
+        mDmd = new DisplayModeDirector(mContext, mHandler, mInjector,
+                mDisplayManagerFlags, mDisplayDeviceConfigProvider);
         mDmd.start(null);
         assertThat(mObserver).isNotNull();
     }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
index 230317b..3c87261 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
@@ -19,10 +19,14 @@
 import android.content.Context
 import android.content.ContextWrapper
 import android.provider.Settings
+import android.util.SparseArray
+import android.view.Display
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.SmallTest
 import com.android.internal.util.test.FakeSettingsProvider
+import com.android.server.display.DisplayDeviceConfig
 import com.android.server.display.feature.DisplayManagerFlags
+import com.android.server.display.mode.DisplayModeDirector.DisplayDeviceConfigProvider
 import com.android.server.testutils.TestHandler
 import com.google.common.truth.Truth.assertThat
 import com.google.testing.junit.testparameterinjector.TestParameter
@@ -39,7 +43,6 @@
 @SmallTest
 @RunWith(TestParameterInjector::class)
 class SettingsObserverTest {
-
     @get:Rule
     val mockitoRule = MockitoJUnit.rule()
 
@@ -49,6 +52,8 @@
     private lateinit var spyContext: Context
     private val mockInjector = mock<DisplayModeDirector.Injector>()
     private val mockFlags = mock<DisplayManagerFlags>()
+    private val mockDeviceConfig = mock<DisplayDeviceConfig>()
+    private val mockDisplayDeviceConfigProvider = mock<DisplayDeviceConfigProvider>()
 
     private val testHandler = TestHandler(null)
 
@@ -67,9 +72,13 @@
                 spyContext.contentResolver, Settings.Global.LOW_POWER_MODE, lowPowerModeSetting)
 
         val displayModeDirector = DisplayModeDirector(
-                spyContext, testHandler, mockInjector, mockFlags)
+                spyContext, testHandler, mockInjector, mockFlags, mockDisplayDeviceConfigProvider)
+        val ddcByDisplay = SparseArray<DisplayDeviceConfig>()
+        whenever(mockDeviceConfig.isVrrSupportEnabled).thenReturn(testCase.vrrSupported)
+        ddcByDisplay.put(Display.DEFAULT_DISPLAY, mockDeviceConfig)
+        displayModeDirector.injectDisplayDeviceConfigByDisplay(ddcByDisplay)
         val settingsObserver = displayModeDirector.SettingsObserver(
-                spyContext, testHandler, testCase.dvrrSupported, mockFlags)
+                spyContext, testHandler, mockFlags)
 
         settingsObserver.onChange(
                 false, Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE), 1)
@@ -79,7 +88,7 @@
     }
 
     enum class SettingsObserverTestCase(
-            val dvrrSupported: Boolean,
+            val vrrSupported: Boolean,
             val vsyncLowPowerVoteEnabled: Boolean,
             val lowPowerModeEnabled: Boolean,
             internal val expectedVote: Vote?
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java
new file mode 100644
index 0000000..99968d5
--- /dev/null
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.dreams;
+
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.service.dreams.utils.DreamAccessibility;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DreamAccessibilityTest {
+
+    @Mock
+    private View mView;
+
+    @Mock
+    private Context mContext;
+
+    @Mock
+    private Resources mResources;
+
+    @Mock
+    private AccessibilityNodeInfo mAccessibilityNodeInfo;
+
+    @Captor
+    private ArgumentCaptor<View.AccessibilityDelegate> mAccessibilityDelegateArgumentCaptor;
+
+    private DreamAccessibility mDreamAccessibility;
+    private static final String CUSTOM_ACTION = "Custom Action";
+    private static final String EXISTING_ACTION = "Existing Action";
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mDreamAccessibility = new DreamAccessibility(mContext, mView);
+
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getString(R.string.dream_accessibility_action_click))
+                .thenReturn(CUSTOM_ACTION);
+    }
+    /**
+     * Test to verify the configuration of accessibility actions within a view delegate.
+     */
+    @Test
+    public void testConfigureAccessibilityActions() {
+        when(mAccessibilityNodeInfo.getActionList()).thenReturn(new ArrayList<>());
+
+        mDreamAccessibility.updateAccessibilityConfiguration(false);
+
+        verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture());
+        View.AccessibilityDelegate capturedDelegate =
+                mAccessibilityDelegateArgumentCaptor.getValue();
+
+        capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo);
+
+        verify(mAccessibilityNodeInfo).addAction(argThat(action ->
+                action.getId() == AccessibilityNodeInfo.ACTION_CLICK
+                        && TextUtils.equals(action.getLabel(), CUSTOM_ACTION)));
+    }
+
+    /**
+     * Test to verify the configuration of accessibility actions within a view delegate,
+     * specifically checking the removal of an existing click action and addition
+     * of a new custom action.
+     */
+    @Test
+    public void testConfigureAccessibilityActions_RemovesExistingClickAction() {
+        AccessibilityNodeInfo.AccessibilityAction existingAction =
+                new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK,
+                        EXISTING_ACTION);
+        when(mAccessibilityNodeInfo.getActionList())
+                .thenReturn(Collections.singletonList(existingAction));
+
+        mDreamAccessibility.updateAccessibilityConfiguration(false);
+
+        verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture());
+        View.AccessibilityDelegate capturedDelegate =
+                mAccessibilityDelegateArgumentCaptor.getValue();
+
+        capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo);
+
+        verify(mAccessibilityNodeInfo).removeAction(existingAction);
+        verify(mAccessibilityNodeInfo).addAction(argThat(action ->
+                action.getId() == AccessibilityNodeInfo.ACTION_CLICK
+                        && TextUtils.equals(action.getLabel(), CUSTOM_ACTION)));
+
+    }
+
+    /**
+     * Test to verify the removal of a custom accessibility action within a view delegate.
+     */
+    @Test
+    public void testRemoveCustomAccessibilityAction() {
+
+        AccessibilityNodeInfo.AccessibilityAction existingAction =
+                new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK,
+                        EXISTING_ACTION);
+        when(mAccessibilityNodeInfo.getActionList())
+                .thenReturn(Collections.singletonList(existingAction));
+
+        mDreamAccessibility.updateAccessibilityConfiguration(false);
+        verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture());
+        View.AccessibilityDelegate capturedDelegate =
+                mAccessibilityDelegateArgumentCaptor.getValue();
+        when(mView.getAccessibilityDelegate()).thenReturn(capturedDelegate);
+        clearInvocations(mView);
+
+        mDreamAccessibility.updateAccessibilityConfiguration(true);
+        verify(mView).setAccessibilityDelegate(null);
+    }
+
+    /**
+     * Test to verify the removal of custom accessibility action is not called if delegate is not
+     * set by the dreamService.
+     */
+    @Test
+    public void testRemoveCustomAccessibility_DoesNotRemoveDelegateNotSetByDreamAccessibility() {
+        mDreamAccessibility.updateAccessibilityConfiguration(true);
+        verify(mView, never()).setAccessibilityDelegate(any());
+    }
+}
+
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java
index db70434..88ab871 100644
--- a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java
@@ -19,6 +19,8 @@
 import static android.os.PowerManager.USER_ACTIVITY_EVENT_OTHER;
 import static android.os.PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -270,6 +272,31 @@
                 eq(USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS));
     }
 
+    @Test
+    public void setDreamHasFocus_true_dreamHasFocus() {
+        mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/,
+                0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/);
+
+        mDreamController.setDreamHasFocus(true);
+        assertTrue(mDreamController.dreamHasFocus());
+    }
+
+    @Test
+    public void setDreamHasFocus_false_dreamDoesNotHaveFocus() {
+        mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/,
+                0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/);
+
+        mDreamController.setDreamHasFocus(false);
+        assertFalse(mDreamController.dreamHasFocus());
+    }
+
+    @Test
+    public void setDreamHasFocus_notDreaming_dreamDoesNotHaveFocus() {
+        mDreamController.setDreamHasFocus(true);
+        // Dream still doesn't have focus because it was never started.
+        assertFalse(mDreamController.dreamHasFocus());
+    }
+
     private ServiceConnection captureServiceConnection() {
         verify(mContext).bindServiceAsUser(any(), mServiceConnectionACaptor.capture(), anyInt(),
                 any());
diff --git a/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java b/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java
index a918be2..8bdfc50 100644
--- a/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java
+++ b/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java
@@ -69,6 +69,13 @@
 public class AudioManagerRouteControllerTest {
 
     private static final String FAKE_ROUTE_NAME = "fake name";
+
+    /**
+     * The number of milliseconds to wait for an asynchronous operation before failing an associated
+     * assertion.
+     */
+    private static final int ASYNC_CALL_TIMEOUTS_MS = 1000;
+
     private static final AudioDeviceInfo FAKE_AUDIO_DEVICE_INFO_BUILTIN_SPEAKER =
             createAudioDeviceInfo(
                     AudioSystem.DEVICE_OUT_SPEAKER, "name_builtin", /* address= */ null);
@@ -231,7 +238,7 @@
         MediaRoute2Info builtInSpeakerRoute =
                 getAvailableRouteWithType(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
         mControllerUnderTest.transferTo(builtInSpeakerRoute.getId());
-        verify(mMockAudioManager)
+        verify(mMockAudioManager, Mockito.timeout(ASYNC_CALL_TIMEOUTS_MS))
                 .setPreferredDeviceForStrategy(
                         mMediaAudioProductStrategy,
                         createAudioDeviceAttribute(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER));
@@ -239,7 +246,7 @@
         MediaRoute2Info wiredHeadsetRoute =
                 getAvailableRouteWithType(MediaRoute2Info.TYPE_WIRED_HEADSET);
         mControllerUnderTest.transferTo(wiredHeadsetRoute.getId());
-        verify(mMockAudioManager)
+        verify(mMockAudioManager, Mockito.timeout(ASYNC_CALL_TIMEOUTS_MS))
                 .setPreferredDeviceForStrategy(
                         mMediaAudioProductStrategy,
                         createAudioDeviceAttribute(AudioDeviceInfo.TYPE_WIRED_HEADSET));
diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS
index f801560..dc5cb8d6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS
@@ -1,5 +1,7 @@
 per-file *Alarm* = file:/apex/jobscheduler/OWNERS
 per-file *AppStateTracker* = file:/apex/jobscheduler/OWNERS
 per-file *DeviceIdleController* = file:/apex/jobscheduler/OWNERS
-per-file SensitiveContentProtectionManagerServiceTest.java = file:/core/java/android/permission/OWNERS
+per-file SensitiveContentProtectionManagerService* = file:/core/java/android/permission/OWNERS
 per-file RescuePartyTest.java = file:/packages/CrashRecovery/OWNERS
+per-file *Storage* = file:/core/java/android/os/storage/OWNERS
+
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 682569f..4a21645 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -25,6 +25,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 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.RescueParty.DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN;
 import static com.android.server.RescueParty.LEVEL_FACTORY_RESET;
 import static com.android.server.RescueParty.RESCUE_LEVEL_FACTORY_RESET;
 
@@ -103,8 +104,6 @@
     private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
             "persist.device_config.configuration.disable_rescue_party_factory_reset";
 
-    private static final int THROTTLING_DURATION_MIN = 10;
-
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
@@ -228,6 +227,9 @@
         setCrashRecoveryPropRescueBootCount(0);
         SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
         SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false));
+
+        // enable flag resets for tests
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_RESCUE_PARTY_FLAG_RESETS);
     }
 
     @After
@@ -312,6 +314,9 @@
 
     @Test
     public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
+        // this is old test where the flag needs to be disabled
+        mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
         noteAppCrash(1, true);
 
         verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
@@ -378,6 +383,9 @@
 
     @Test
     public void testNonPersistentAppOnlyPerformsFlagResets() {
+        // this is old test where the flag needs to be disabled
+        mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
         noteAppCrash(1, false);
 
         verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
@@ -628,7 +636,8 @@
     public void testThrottlingOnBootFailures() {
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
         setCrashRecoveryPropLastFactoryReset(beforeTimeout);
         for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
             noteBoot(i);
@@ -641,7 +650,8 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
         setCrashRecoveryPropLastFactoryReset(beforeTimeout);
         for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
             noteBoot(i);
@@ -653,7 +663,8 @@
     public void testThrottlingOnAppCrash() {
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
         setCrashRecoveryPropLastFactoryReset(beforeTimeout);
         for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
             noteAppCrash(i + 1, true);
@@ -666,7 +677,8 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+        long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
         setCrashRecoveryPropLastFactoryReset(beforeTimeout);
         for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
             noteAppCrash(i + 1, true);
@@ -678,7 +690,8 @@
     public void testNotThrottlingAfterTimeoutOnBootFailures() {
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+        long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
         setCrashRecoveryPropLastFactoryReset(afterTimeout);
         for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
             noteBoot(i);
@@ -691,7 +704,8 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+        long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
         setCrashRecoveryPropLastFactoryReset(afterTimeout);
         for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
             noteBoot(i);
@@ -703,7 +717,8 @@
     public void testNotThrottlingAfterTimeoutOnAppCrash() {
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+        long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
         setCrashRecoveryPropLastFactoryReset(afterTimeout);
         for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
             noteAppCrash(i + 1, true);
@@ -716,7 +731,8 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
         setCrashRecoveryPropAttemptingReboot(false);
         long now = System.currentTimeMillis();
-        long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+        long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+                DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
         setCrashRecoveryPropLastFactoryReset(afterTimeout);
         for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
             noteAppCrash(i + 1, true);
@@ -794,6 +810,9 @@
 
     @Test
     public void testHealthCheckLevels() {
+        // this is old test where the flag needs to be disabled
+        mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
         RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
 
         // Ensure that no action is taken for cases where the failure reason is unknown
@@ -1111,16 +1130,9 @@
 
         // mock properties in BootThreshold
         try {
-            if (Flags.recoverabilityDetection()) {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-            } else {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
+            mSpyBootThreshold = spy(watchdog.new BootThreshold(
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
-            }
             mCrashRecoveryPropertiesMap = new HashMap<>();
 
             doAnswer((Answer<Integer>) invocationOnMock -> {
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
index 5065144..a20d935 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
@@ -16,16 +16,18 @@
 
 package com.android.server;
 
+import static android.permission.flags.Flags.FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX;
 import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
-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.verifyZeroInteractions;
@@ -34,6 +36,8 @@
 import android.content.pm.PackageManagerInternal;
 import android.media.projection.MediaProjectionInfo;
 import android.media.projection.MediaProjectionManager;
+import android.os.Process;
+import android.platform.test.annotations.RequiresFlagsDisabled;
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -79,7 +83,8 @@
     private static final String NOTIFICATION_PKG_1 = "com.android.server.notification.one";
     private static final String NOTIFICATION_PKG_2 = "com.android.server.notification.two";
 
-    private static final String EXEMPTED_SCREEN_RECORDER_PACKAGE = "test.screen.recorder.package";
+    private static final String SCREEN_RECORDER_PACKAGE = "test.screen.recorder.package";
+    private static final String EXEMPTED_SCREEN_RECORDER_PACKAGE = "exempt.screen.recorder.package";
 
     private static final int NOTIFICATION_UID_1 = 5;
     private static final int NOTIFICATION_UID_2 = 6;
@@ -281,10 +286,26 @@
                 .getActiveNotifications();
     }
 
+    private void setupNullNotifications() {
+        // Setup Notification Values
+        StatusBarNotification[] mNotifications = new StatusBarNotification[] { null, null};
+        doReturn(mNotifications)
+                .when(mSensitiveContentProtectionManagerService.mNotificationListener)
+                .getActiveNotifications();
+    }
+
+    private MediaProjectionInfo createMediaProjectionInfo() {
+        return new MediaProjectionInfo(SCREEN_RECORDER_PACKAGE, Process.myUserHandle(), null);
+    }
+
+    private MediaProjectionInfo createExemptMediaProjectionInfo() {
+        return new MediaProjectionInfo(
+                EXEMPTED_SCREEN_RECORDER_PACKAGE, Process.myUserHandle(), null);
+    }
+
     @Test
     public void mediaProjectionOnStart_verifyExemptedRecorderPackage() {
-        MediaProjectionInfo mediaProjectionInfo = mock(MediaProjectionInfo.class);
-        when(mediaProjectionInfo.getPackageName()).thenReturn(EXEMPTED_SCREEN_RECORDER_PACKAGE);
+        MediaProjectionInfo mediaProjectionInfo = createExemptMediaProjectionInfo();
 
         mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
 
@@ -292,10 +313,30 @@
     }
 
     @Test
+    @RequiresFlagsDisabled(FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX)
+    public void mediaProjectionOnStart_flagDisabled_neverSetBlockScreenCaptureForAppsSessionId() {
+        setupSensitiveNotification();
+
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
+
+        verify(mWindowManager, never()).setBlockScreenCaptureForAppsSessionId(anyLong());
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX)
+    public void mediaProjectionOnStart_setBlockScreenCaptureForAppsSessionId() {
+        setupSensitiveNotification();
+
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
+
+        verify(mWindowManager).setBlockScreenCaptureForAppsSessionId(anyLong());
+    }
+
+    @Test
     public void mediaProjectionOnStart_onProjectionStart_setWmBlockedPackages() {
         ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
         verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages);
     }
@@ -304,18 +345,18 @@
     public void mediaProjectionOnStart_noSensitiveNotifications_noBlockedPackages() {
         setupNoSensitiveNotifications();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
     }
 
     @Test
     public void mediaProjectionOnStart_noNotifications_noBlockedPackages() {
         setupNoNotifications();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
     }
 
     @Test
@@ -323,7 +364,7 @@
         ArraySet<PackageInfo> expectedBlockedPackages =
                 setupMultipleSensitiveNotificationsFromSamePackageAndUid();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
         verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages);
     }
@@ -333,7 +374,7 @@
         ArraySet<PackageInfo> expectedBlockedPackages =
                 setupMultipleSensitiveNotificationsFromDifferentPackage();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
         verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages);
     }
@@ -343,7 +384,7 @@
         ArraySet<PackageInfo> expectedBlockedPackages =
                 setupMultipleSensitiveNotificationsFromDifferentUid();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
         verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages);
     }
@@ -352,7 +393,7 @@
     public void mediaProjectionOnStop_onProjectionEnd_clearWmBlockedPackages() {
         setupSensitiveNotification();
 
-        MediaProjectionInfo mediaProjectionInfo = mock(MediaProjectionInfo.class);
+        MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
         mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
         Mockito.reset(mWindowManager);
 
@@ -365,7 +406,7 @@
     public void mediaProjectionOnStart_afterOnStop_onProjectionStart_setWmBlockedPackages() {
         ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification();
 
-        MediaProjectionInfo mediaProjectionInfo = mock(MediaProjectionInfo.class);
+        MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
         mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
         mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo);
         Mockito.reset(mWindowManager);
@@ -381,9 +422,9 @@
                 .when(mSensitiveContentProtectionManagerService.mNotificationListener)
                 .getActiveNotifications();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
     }
 
     @Test
@@ -392,9 +433,9 @@
                 .when(mSensitiveContentProtectionManagerService.mNotificationListener)
                 .getCurrentRanking();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
     }
 
     @Test
@@ -403,9 +444,9 @@
                 .when(mSensitiveContentProtectionManagerService.mNotificationListener)
                 .getCurrentRanking();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
     }
 
     @Test
@@ -416,9 +457,9 @@
                 .when(mSensitiveContentProtectionManagerService.mNotificationListener)
                 .getCurrentRanking();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
     }
 
     @Test
@@ -426,7 +467,7 @@
         mockDisabledViaDevelopOption();
         setupSensitiveNotification();
 
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
 
         verifyZeroInteractions(mWindowManager);
     }
@@ -447,8 +488,9 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
-        mMediaProjectionCallbackCaptor.getValue().onStop(mock(MediaProjectionInfo.class));
+        MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
+        mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
+        mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo);
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
@@ -461,7 +503,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
@@ -472,23 +514,34 @@
     @Test
     public void nlsOnListenerConnected_noSensitiveNotifications_noBlockedPackages() {
         setupNoSensitiveNotifications();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
     public void nlsOnListenerConnected_noNotifications_noBlockedPackages() {
         setupNoNotifications();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
+    }
+
+    @Test
+    public void nlsOnListenerConnected_nullNotifications_noBlockedPackages() {
+        setupNullNotifications();
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
+        Mockito.reset(mWindowManager);
+
+        mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
+
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -496,7 +549,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
         doReturn(null)
                 .when(mSensitiveContentProtectionManagerService.mNotificationListener)
@@ -504,7 +557,7 @@
 
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -512,7 +565,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
         when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null);
         doReturn(mRankingMap)
@@ -521,7 +574,7 @@
 
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -530,7 +583,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();
 
         verifyZeroInteractions(mWindowManager);
@@ -553,8 +606,9 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
-        mMediaProjectionCallbackCaptor.getValue().onStop(mock(MediaProjectionInfo.class));
+        MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
+        mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
+        mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo);
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -568,7 +622,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -580,25 +634,25 @@
     @Test
     public void nlsOnNotificationRankingUpdate_noSensitiveNotifications_noBlockedPackages() {
         setupNoSensitiveNotifications();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationRankingUpdate(mRankingMap);
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
     public void nlsOnNotificationRankingUpdate_noNotifications_noBlockedPackages() {
         setupNoNotifications();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationRankingUpdate(mRankingMap);
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -606,13 +660,13 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationRankingUpdate(null);
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -620,7 +674,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
         when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null);
         doReturn(mRankingMap)
@@ -630,7 +684,7 @@
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationRankingUpdate(mRankingMap);
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -638,7 +692,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         doThrow(SecurityException.class)
@@ -648,7 +702,7 @@
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationRankingUpdate(mRankingMap);
 
-        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
+        verifyZeroInteractions(mWindowManager);
     }
 
     @Test
@@ -657,7 +711,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationRankingUpdate(mRankingMap);
 
@@ -681,8 +735,9 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
-        mMediaProjectionCallbackCaptor.getValue().onStop(mock(MediaProjectionInfo.class));
+        MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo();
+        mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo);
+        mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo);
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -696,7 +751,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -712,7 +767,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -726,7 +781,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -740,7 +795,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
 
         mSensitiveContentProtectionManagerService.mNotificationListener
@@ -754,7 +809,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         Mockito.reset(mWindowManager);
         when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null);
 
@@ -770,7 +825,7 @@
         // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
         // as non-sensitive
         setupSensitiveNotification();
-        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
+        mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
         mSensitiveContentProtectionManagerService.mNotificationListener
                 .onNotificationPosted(mNotification1, mRankingMap);
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/StorageManagerServiceTest.java
new file mode 100644
index 0000000..2e4b97e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.multiuser.Flags;
+import android.os.UserManager;
+import android.os.storage.ICeStorageLockEventListener;
+import android.os.storage.StorageManagerInternal;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import com.android.modules.utils.testing.ExtendedMockitoRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class StorageManagerServiceTest {
+
+    private final Context mRealContext = androidx.test.platform.app.InstrumentationRegistry
+            .getInstrumentation().getTargetContext();
+    private StorageManagerService mStorageManagerService;
+    private StorageManagerInternal mStorageManagerInternal;
+
+    private static final int TEST_USER_ID = 1001;
+
+    @Rule
+    public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+            .spyStatic(UserManager.class)
+            .build();
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    private static class TestStorageEventListener implements ICeStorageLockEventListener {
+
+        private int mExpectedUserId;
+
+        private TestStorageEventListener(int userId) {
+            mExpectedUserId = userId;
+        }
+
+        @Override
+        public void onStorageLocked(int userId) {
+            assertThat(userId).isEqualTo(mExpectedUserId);
+        }
+    }
+
+
+    @Before
+    public void setFixtures() {
+        // Called when WatchedUserStates is constructed
+        doNothing().when(() -> UserManager.invalidateIsUserUnlockedCache());
+
+        mStorageManagerService = new StorageManagerService(mRealContext);
+        mStorageManagerInternal = LocalServices.getService(StorageManagerInternal.class);
+        assertWithMessage("LocalServices.getService(StorageManagerInternal.class)")
+                .that(mStorageManagerInternal).isNotNull();
+    }
+
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(StorageManagerInternal.class);
+    }
+
+    @Test
+    public void testRegisterLockEventListener() {
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        CopyOnWriteArrayList<ICeStorageLockEventListener> storageLockEventListeners =
+                mStorageManagerService.getCeStorageEventCallbacks();
+        assertThat(storageLockEventListeners).isNotNull();
+        int registeredCallbackCount = storageLockEventListeners.size();
+        TestStorageEventListener testStorageEventListener =
+                new TestStorageEventListener(TEST_USER_ID);
+        mStorageManagerInternal.registerStorageLockEventListener(testStorageEventListener);
+        assertNumberOfStorageCallbackReceivers(registeredCallbackCount + 1);
+
+        mStorageManagerInternal.unregisterStorageLockEventListener(testStorageEventListener);
+        assertNumberOfStorageCallbackReceivers(registeredCallbackCount);
+    }
+
+    @Test
+    public void testDispatchCeStorageLockEvent() {
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
+                Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+
+        assertThat(mStorageManagerService.getCeStorageEventCallbacks()).isNotNull();
+        int callbackReceiverSize = mStorageManagerService.getCeStorageEventCallbacks().size();
+        TestStorageEventListener testStorageEventListener =
+                spy(new TestStorageEventListener(TEST_USER_ID));
+
+        // Add testStorageEventListener to the list of storage callback listeners
+        mStorageManagerService.getCeStorageEventCallbacks().add(testStorageEventListener);
+        assertNumberOfStorageCallbackReceivers(callbackReceiverSize + 1);
+
+        mStorageManagerService.dispatchCeStorageLockedEvent(TEST_USER_ID);
+        verify(testStorageEventListener).onStorageLocked(eq(TEST_USER_ID));
+
+        // Remove testStorageEventListener from the list of storage callback listeners
+        mStorageManagerService.getCeStorageEventCallbacks().remove(testStorageEventListener);
+        assertNumberOfStorageCallbackReceivers(callbackReceiverSize);
+    }
+
+    private void assertNumberOfStorageCallbackReceivers(int callbackReceiverSize) {
+        assertThat(mStorageManagerService.getCeStorageEventCallbacks()).isNotNull();
+        assertThat(mStorageManagerService.getCeStorageEventCallbacks().size())
+                    .isEqualTo(callbackReceiverSize);
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index a7430e5..419bcb8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -38,6 +38,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.am.ActivityManagerInternalTest.CustomThread;
 import static com.android.server.am.ActivityManagerService.Injector;
@@ -692,6 +693,31 @@
         assertEquals(uid, -1);
     }
 
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testFifoSwitch() {
+        addUidRecord(TEST_UID, TEST_PACKAGE);
+        final ProcessRecord fifoProc = mAms.getProcessRecordLocked(TEST_PACKAGE, TEST_UID);
+        final var wpc = fifoProc.getWindowProcessController();
+        spyOn(wpc);
+        doReturn(true).when(wpc).useFifoUiScheduling();
+        fifoProc.makeActive(fifoProc.getThread(), mAms.mProcessStats);
+        assertTrue(fifoProc.useFifoUiScheduling());
+        assertTrue(mAms.mSpecifiedFifoProcesses.contains(fifoProc));
+
+        // If there is a request to use more CPU resource (e.g. camera), the current fifo process
+        // should switch the capability of using fifo.
+        final UidRecord uidRecord = addUidRecord(TEST_UID + 1, TEST_PACKAGE + 1);
+        uidRecord.setCurProcState(PROCESS_STATE_TOP);
+        mAms.adjustFifoProcessesIfNeeded(uidRecord.getUid(), false /* allowSpecifiedFifo */);
+        assertFalse(fifoProc.useFifoUiScheduling());
+        mAms.adjustFifoProcessesIfNeeded(uidRecord.getUid(), true /* allowSpecifiedFifo */);
+        assertTrue(fifoProc.useFifoUiScheduling());
+
+        fifoProc.makeInactive(mAms.mProcessStats);
+        assertFalse(mAms.mSpecifiedFifoProcesses.contains(fifoProc));
+    }
+
     @Test
     public void testGlobalIsolatedUidAllocator() {
         final IsolatedUidRange globalUidRange = mAms.mProcessList.mGlobalIsolatedUids;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java
index 7d3a110..c1f4fee 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java
@@ -321,8 +321,7 @@
                 app1PackageName);            // packageName
         ServiceRecord service = ServiceRecord.newEmptyInstanceForTest(mAms);
 
-        mAppStartInfoTracker.handleProcessServiceStart(appStartTimestampService, app, service,
-                false);
+        mAppStartInfoTracker.handleProcessServiceStart(appStartTimestampService, app, service);
         list.clear();
         mAppStartInfoTracker.getStartInfo(app1PackageName, app1Uid, 0, 0, list);
         assertEquals(list.size(), 2);
@@ -336,7 +335,7 @@
                 app1ProcessName,                                      // processName
                 ApplicationStartInfo.START_REASON_SERVICE,            // reason
                 ApplicationStartInfo.STARTUP_STATE_STARTED,           // startup state
-                ApplicationStartInfo.START_TYPE_WARM,                 // state type
+                ApplicationStartInfo.START_TYPE_COLD,                 // state type
                 ApplicationStartInfo.LAUNCH_MODE_STANDARD);           // launch mode
 
         // Case 5: Create an instance of app1 with a different user started for a broadcast
@@ -350,7 +349,7 @@
                 app1PackageName);                // packageName
 
         mAppStartInfoTracker.handleProcessBroadcastStart(appStartTimestampBroadcast, app,
-                null, true /* isColdStart */);
+                buildIntent(COMPONENT), false /* isAlarm */);
         list.clear();
         mAppStartInfoTracker.getStartInfo(app1PackageName, app1UidUser2, app1PidUser2, 0, list);
         assertEquals(list.size(), 1);
@@ -395,7 +394,7 @@
                 app2PackageName);                // packageName
 
         mAppStartInfoTracker.handleProcessContentProviderStart(appStartTimestampRContentProvider,
-                app, false);
+                app);
         list.clear();
         mAppStartInfoTracker.getStartInfo(app2PackageName, app2UidUser2, app2PidUser2, 0, list);
         assertEquals(list.size(), 1);
@@ -409,7 +408,7 @@
                 app2ProcessName,                                      // processName
                 ApplicationStartInfo.START_REASON_CONTENT_PROVIDER,   // reason
                 ApplicationStartInfo.STARTUP_STATE_STARTED,           // startup state
-                ApplicationStartInfo.START_TYPE_WARM,                 // state type
+                ApplicationStartInfo.START_TYPE_COLD,                 // state type
                 ApplicationStartInfo.LAUNCH_MODE_STANDARD);           // launch mode
 
         // Case 8: Save and load again
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
index ce281da..5861917 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
@@ -112,6 +112,9 @@
     @Mock
     ProcessList mProcessList;
 
+    @Mock
+    AppStartInfoTracker mAppStartInfoTracker;
+
     Context mContext;
     ActivityManagerService mAms;
     BroadcastConstants mConstants;
@@ -172,6 +175,8 @@
         mSkipPolicy = spy(new BroadcastSkipPolicy(mAms));
         doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any());
         doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any());
+
+        doReturn(mAppStartInfoTracker).when(mProcessList).getAppStartInfoTracker();
     }
 
     public void tearDown() throws Exception {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 97ae0bd..13ba1e5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -2393,6 +2393,20 @@
         assertNull(mAms.getProcessRecordLocked(PACKAGE_BLUE, getUidForPackage(PACKAGE_BLUE)));
     }
 
+    @Test
+    public void testBroadcastAppStartInfoReported() throws Exception {
+        final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+
+        final Intent timezone = new Intent(Intent.ACTION_TIME_TICK);
+        enqueueBroadcast(makeBroadcastRecord(timezone, callerApp,
+                List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN))));
+
+        waitForIdle();
+
+        verify(mAppStartInfoTracker, times(1)).handleProcessBroadcastStart(anyLong(), any(), any(),
+                anyBoolean());
+    }
+
     private long getReceiverScheduledTime(@NonNull BroadcastRecord r, @NonNull Object receiver) {
         for (int i = 0; i < r.receivers.size(); ++i) {
             if (isReceiverEquals(receiver, r.receivers.get(i))) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 4c7a8fe..9590783 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -205,8 +205,6 @@
                 new ProcessStatsService(sService, new File(sContext.getFilesDir(), "procstats")));
         setFieldValue(ActivityManagerService.class, sService, "mBackupTargets",
                 mock(SparseArray.class));
-        setFieldValue(ActivityManagerService.class, sService, "mOomAdjProfiler",
-                mock(OomAdjProfiler.class));
         setFieldValue(ActivityManagerService.class, sService, "mUserController",
                 mock(UserController.class));
         setFieldValue(ActivityManagerService.class, sService, "mAppProfiler", profiler);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
index 783971a..89b48ba 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -16,9 +16,18 @@
 
 package com.android.server.am;
 
+import static android.os.Process.INVALID_UID;
+
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_NULL;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_ONE_SHOT_SENT;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_OWNER_CANCELED;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_OWNER_FORCE_STOPPED;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_SUPERSEDED;
+import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_USER_STOPPED;
+import static com.android.server.am.PendingIntentRecord.cancelReasonToString;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -34,6 +43,7 @@
 import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.os.Looper;
+import android.os.UserHandle;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -54,6 +64,7 @@
     private static final String TEST_PACKAGE_NAME = "test-package-1";
     private static final String TEST_FEATURE_ID = "test-feature-1";
     private static final int TEST_CALLING_UID = android.os.Process.myUid();
+    private static final int TEST_USER_ID = 0;
     private static final Intent[] TEST_INTENTS = new Intent[]{new Intent("com.test.intent")};
 
     @Mock
@@ -92,7 +103,7 @@
 
     private PendingIntentRecord createPendingIntentRecord(int flags) {
         return mPendingIntentController.getIntentSender(ActivityManager.INTENT_SENDER_BROADCAST,
-                TEST_PACKAGE_NAME, TEST_FEATURE_ID, TEST_CALLING_UID, 0, null, null, 0,
+                TEST_PACKAGE_NAME, TEST_FEATURE_ID, TEST_CALLING_UID, TEST_USER_ID, null, null, 0,
                 TEST_INTENTS, null, flags, null);
     }
 
@@ -126,6 +137,54 @@
                 piCaptor.getValue().getTarget());
     }
 
+    @Test
+    public void testCancellationReason() {
+        {
+            final PendingIntentRecord pir = createPendingIntentRecord(0);
+            assertCancelReason(CANCEL_REASON_NULL, pir.cancelReason);
+        }
+
+        {
+            final PendingIntentRecord pir = createPendingIntentRecord(0);
+            mPendingIntentController.cancelIntentSender(pir);
+            assertCancelReason(CANCEL_REASON_OWNER_CANCELED, pir.cancelReason);
+        }
+
+        {
+            final PendingIntentRecord pir = createPendingIntentRecord(0);
+            createPendingIntentRecord(PendingIntent.FLAG_CANCEL_CURRENT);
+            assertCancelReason(CANCEL_REASON_SUPERSEDED, pir.cancelReason);
+        }
+
+        {
+            final PendingIntentRecord pir = createPendingIntentRecord(PendingIntent.FLAG_ONE_SHOT);
+            pir.send(0, null, null, null, null, null, null);
+            assertCancelReason(CANCEL_REASON_ONE_SHOT_SENT, pir.cancelReason);
+        }
+
+        {
+            final PendingIntentRecord pir = createPendingIntentRecord(0);
+            mPendingIntentController.removePendingIntentsForPackage(TEST_PACKAGE_NAME,
+                    TEST_USER_ID, UserHandle.getAppId(TEST_CALLING_UID), true,
+                    CANCEL_REASON_OWNER_FORCE_STOPPED);
+            assertCancelReason(CANCEL_REASON_OWNER_FORCE_STOPPED, pir.cancelReason);
+        }
+
+        {
+            final PendingIntentRecord pir = createPendingIntentRecord(0);
+            mPendingIntentController.removePendingIntentsForPackage(null,
+                    TEST_USER_ID, INVALID_UID, true,
+                    CANCEL_REASON_USER_STOPPED);
+            assertCancelReason(CANCEL_REASON_USER_STOPPED, pir.cancelReason);
+        }
+    }
+
+    private void assertCancelReason(int expectedReason, int actualReason) {
+        final String errMsg = "Expected: " + cancelReasonToString(expectedReason)
+                + "; Actual: " + cancelReasonToString(actualReason);
+        assertEquals(errMsg, expectedReason, actualReason);
+    }
+
     @After
     public void tearDown() {
         if (mMockingSession != null) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java
index b203cf6..c4a0423 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -38,7 +38,6 @@
 import static org.mockito.Mockito.when;
 
 import android.Manifest;
-import android.annotation.UserIdInt;
 import android.app.backup.BackupManager;
 import android.app.backup.ISelectBackupTransportCallback;
 import android.app.job.JobScheduler;
@@ -59,10 +58,12 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
 import com.android.server.backup.utils.RandomAccessFileUtils;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -74,6 +75,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.io.Writer;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 
@@ -85,8 +87,6 @@
             "class");
     private static final int NON_SYSTEM_USER = UserHandle.USER_SYSTEM + 1;
 
-    @UserIdInt
-    private int mUserId;
     @Mock
     private UserBackupManagerService mSystemUserBackupManagerService;
     @Mock
@@ -94,8 +94,6 @@
     @Mock
     private Context mContextMock;
     @Mock
-    private PrintWriter mPrintWriterMock;
-    @Mock
     private UserManager mUserManagerMock;
     @Mock
     private UserInfo mUserInfoMock;
@@ -104,6 +102,7 @@
 
     private BackupManagerServiceTestable mService;
     private BackupManagerService.Lifecycle mServiceLifecycle;
+    private FakePrintWriter mFakePrintWriter;
     private static File sTestDir;
     private MockitoSession mSession;
 
@@ -114,6 +113,7 @@
                                 this)
                         .strictness(Strictness.LENIENT)
                         .spyStatic(UserBackupManagerService.class)
+                        .spyStatic(DumpUtils.class)
                         .startMocking();
         doReturn(mSystemUserBackupManagerService).when(
                 () -> UserBackupManagerService.createAndInitializeService(
@@ -122,8 +122,7 @@
                 () -> UserBackupManagerService.createAndInitializeService(eq(NON_SYSTEM_USER),
                         any(), any(), any()));
 
-        mUserId = UserHandle.USER_SYSTEM;
-
+        when(mNonSystemUserBackupManagerService.getUserId()).thenReturn(NON_SYSTEM_USER);
         when(mUserManagerMock.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(mUserInfoMock);
         when(mUserManagerMock.getUserInfo(NON_SYSTEM_USER)).thenReturn(mUserInfoMock);
         // Null main user means there is no main user on the device.
@@ -139,6 +138,8 @@
 
         when(mContextMock.getSystemService(Context.JOB_SCHEDULER_SERVICE))
                 .thenReturn(mock(JobScheduler.class));
+
+        mFakePrintWriter = new FakePrintWriter();
     }
 
     @After
@@ -552,7 +553,8 @@
                     }
                 };
 
-        mService.selectBackupTransportAsyncForUser(mUserId, TRANSPORT_COMPONENT_NAME, listener);
+        mService.selectBackupTransportAsyncForUser(
+                UserHandle.USER_SYSTEM, TRANSPORT_COMPONENT_NAME, listener);
 
         assertEquals(BackupManager.ERROR_BACKUP_NOT_ALLOWED, (int) future.get(5, TimeUnit.SECONDS));
     }
@@ -560,9 +562,10 @@
     @Test
     public void selectBackupTransportAsyncForUser_beforeUserUnlockedWithNullListener_doesNotThrow()
             throws Exception {
-        createBackupManagerServiceAndUnlockSystemUser();
+        mService = new BackupManagerServiceTestable(mContextMock);
 
-        mService.selectBackupTransportAsyncForUser(mUserId, TRANSPORT_COMPONENT_NAME, null);
+        mService.selectBackupTransportAsyncForUser(
+                UserHandle.USER_SYSTEM, TRANSPORT_COMPONENT_NAME, null);
 
         // No crash.
     }
@@ -570,13 +573,11 @@
     @Test
     public void selectBackupTransportAsyncForUser_beforeUserUnlockedListenerThrowing_doesNotThrow()
             throws Exception {
-        createBackupManagerServiceAndUnlockSystemUser();
-
+        mService = new BackupManagerServiceTestable(mContextMock);
         ISelectBackupTransportCallback.Stub listener =
                 new ISelectBackupTransportCallback.Stub() {
                     @Override
-                    public void onSuccess(String transportName) {
-                    }
+                    public void onSuccess(String transportName) {}
 
                     @Override
                     public void onFailure(int reason) throws RemoteException {
@@ -584,55 +585,91 @@
                     }
                 };
 
-        mService.selectBackupTransportAsyncForUser(mUserId, TRANSPORT_COMPONENT_NAME, listener);
+        mService.selectBackupTransportAsyncForUser(
+                UserHandle.USER_SYSTEM, TRANSPORT_COMPONENT_NAME, listener);
 
         // No crash.
     }
 
     @Test
-    public void dump_callerDoesNotHaveDumpPermission_ignored() {
+    public void dump_callerDoesNotHaveDumpOrUsageStatsPermission_ignored() {
+        mockDumpPermissionsGranted(false);
         createBackupManagerServiceAndUnlockSystemUser();
-        when(mContextMock.checkCallingOrSelfPermission(
-                Manifest.permission.DUMP)).thenReturn(
-                PackageManager.PERMISSION_DENIED);
+        when(mContextMock.checkCallingOrSelfPermission(Manifest.permission.DUMP))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
 
-        mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
+        mService.dump(mFileDescriptorStub, mFakePrintWriter, new String[0]);
 
         verify(mSystemUserBackupManagerService, never()).dump(any(), any(), any());
         verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
     }
 
     @Test
-    public void dump_callerDoesNotHavePackageUsageStatsPermission_ignored() {
-        createBackupManagerServiceAndUnlockSystemUser();
-        when(mContextMock.checkCallingOrSelfPermission(
-                Manifest.permission.PACKAGE_USAGE_STATS)).thenReturn(
-                PackageManager.PERMISSION_DENIED);
-
-        mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
-
-        verify(mSystemUserBackupManagerService, never()).dump(any(), any(), any());
-        verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
-    }
-
-    /**
-     * Test that {@link BackupManagerService#dump(FileDescriptor, PrintWriter, String[])} dumps
-     * system user information before non-system user information.
-     */
-    @Test
-    public void testDump_systemUserFirst() {
+    public void dump_forOneUser_callerDoesNotHaveInteractAcrossUsersFullPermission_ignored() {
+        mockDumpPermissionsGranted(true);
         createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
         simulateUserUnlocked(NON_SYSTEM_USER);
+        doThrow(new SecurityException())
+                .when(mContextMock)
+                .enforceCallingOrSelfPermission(
+                        eq(Manifest.permission.INTERACT_ACROSS_USERS_FULL), anyString());
+
+        String[] args = new String[] {"--user", Integer.toString(NON_SYSTEM_USER)};
+        Assert.assertThrows(
+                SecurityException.class,
+                () -> mService.dump(mFileDescriptorStub, mFakePrintWriter, args));
+
+        verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
+    }
+
+    @Test
+    public void dump_forOneUser_callerHasInteractAcrossUsersFullPermission_dumpsSpecifiedUser() {
+        mockDumpPermissionsGranted(true);
+        createBackupManagerServiceAndUnlockSystemUser();
+        mService.setBackupServiceActive(NON_SYSTEM_USER, true);
+        simulateUserUnlocked(NON_SYSTEM_USER);
+
+        String[] args = new String[] {"--user", Integer.toString(UserHandle.USER_SYSTEM)};
+        mService.dump(mFileDescriptorStub, mFakePrintWriter, args);
+
+        verify(mSystemUserBackupManagerService).dump(any(), any(), any());
+    }
+
+    @Test
+    public void dump_users_callerHasInteractAcrossUsersFullPermission_dumpsUsers() {
+        mockDumpPermissionsGranted(true);
+        createBackupManagerServiceAndUnlockSystemUser();
+        mService.setBackupServiceActive(NON_SYSTEM_USER, true);
+        simulateUserUnlocked(NON_SYSTEM_USER);
+
+        String[] args = new String[] {"users"};
+        mService.dump(mFileDescriptorStub, mFakePrintWriter, args);
+
+        // Check that dump() invocations are not called on user's Backup service,
+        // as 'dumpsys backup users' only list users for whom Backup service is running.
+        verify(mSystemUserBackupManagerService, never()).dump(any(), any(), any());
+        verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
+        assertThat(mFakePrintWriter.mPrintedSoFar)
+                .isEqualTo("Backup Manager is running for users: 0 1");
+    }
+
+    @Test
+    public void dump_allUsers_dumpsSystemUserFirst() {
+        mockDumpPermissionsGranted(true);
+        createBackupManagerServiceAndUnlockSystemUser();
+        mService.setBackupServiceActive(NON_SYSTEM_USER, true);
+        simulateUserUnlocked(NON_SYSTEM_USER);
+
         String[] args = new String[0];
-        mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args);
+        mService.dump(mFileDescriptorStub, mFakePrintWriter, args);
 
         InOrder inOrder =
                 inOrder(mSystemUserBackupManagerService, mNonSystemUserBackupManagerService);
         inOrder.verify(mSystemUserBackupManagerService)
-                .dump(mFileDescriptorStub, mPrintWriterMock, args);
+                .dump(mFileDescriptorStub, mFakePrintWriter, args);
         inOrder.verify(mNonSystemUserBackupManagerService)
-                .dump(mFileDescriptorStub, mPrintWriterMock, args);
+                .dump(mFileDescriptorStub, mFakePrintWriter, args);
         inOrder.verifyNoMoreInteractions();
     }
 
@@ -753,6 +790,11 @@
         return new File(sTestDir, "rememberActivated-" + userId);
     }
 
+    private static void mockDumpPermissionsGranted(boolean granted) {
+        doReturn(granted)
+                .when(() -> DumpUtils.checkDumpAndUsageStatsPermission(any(), any(), any()));
+    }
+
     private static class BackupManagerServiceTestable extends BackupManagerService {
         static boolean sBackupDisabled = false;
         static int sCallingUserId = -1;
@@ -803,4 +845,17 @@
             runnable.run();
         }
     }
+
+    private static class FakePrintWriter extends PrintWriter {
+        String mPrintedSoFar = "";
+
+        FakePrintWriter() {
+            super(Writer.nullWriter());
+        }
+
+        @Override
+        public void print(String s) {
+            mPrintedSoFar = mPrintedSoFar + s;
+        }
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
index 18dc114..7e17909 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.when;
+
 import android.annotation.NonNull;
 import android.app.backup.BackupHelper;
 import android.app.backup.BackupHelperWithLogger;
@@ -29,8 +31,6 @@
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.util.ArraySet;
 
-import static org.mockito.Mockito.when;
-
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
@@ -92,7 +92,8 @@
                         "people",
                         "app_locales",
                         "app_gender",
-                        "companion");
+                        "companion",
+                        "system_gender");
     }
 
     @Test
@@ -116,7 +117,8 @@
                         "people",
                         "app_locales",
                         "app_gender",
-                        "companion");
+                        "companion",
+                        "system_gender");
     }
 
     @Test
@@ -132,7 +134,9 @@
                         "notifications",
                         "permissions",
                         "app_locales",
-                        "companion");
+                        "companion",
+                        "app_gender",
+                        "system_gender");
     }
 
     @Test
@@ -152,7 +156,9 @@
                         "account_manager",
                         "usage_stats",
                         "shortcut_manager",
-                        "companion");
+                        "companion",
+                        "app_gender",
+                        "system_gender");
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 671472d..584fd62 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -24,6 +24,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.job.Flags.FLAG_COUNT_QUOTA_FIX;
 import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
 import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX;
 import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
@@ -75,6 +76,9 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.provider.DeviceConfig;
 import android.util.ArraySet;
 import android.util.SparseBooleanArray;
@@ -98,6 +102,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -154,6 +159,10 @@
     @Mock
     private UsageStatsManagerInternal mUsageStatsManager;
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule =
+            DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private JobStore mJobStore;
 
     @Before
@@ -2167,6 +2176,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(FLAG_COUNT_QUOTA_FIX)
     public void testIsWithinQuotaLocked_UnderDuration_OverJobCountInWindow() {
         setDischarging();
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index 4535ece..8d0b279 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -191,6 +191,8 @@
         when(mContext.checkCallingOrSelfPermission(
                 eq(Manifest.permission.REQUEST_DELETE_PACKAGES))).thenReturn(
                 PackageManager.PERMISSION_DENIED);
+        when(mContext.createPackageContextAsUser(
+                eq(INSTALLER_PACKAGE), anyInt(), eq(UserHandle.CURRENT))).thenReturn(mContext);
 
         when(mAppOpsManager.checkOp(
                 eq(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED),
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 759a974..79f1574 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -34,6 +34,7 @@
 
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -58,6 +59,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.util.Log;
@@ -139,7 +141,8 @@
             .mockStatic(Settings.Secure.class)
             .build();
 
-    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
+            SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
 
     private final Object mPackagesLock = new Object();
     private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
@@ -584,10 +587,12 @@
     public void testAutoLockPrivateProfile() {
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+        int mainUser = mUms.getMainUserId();
+        assumeTrue(mUms.canAddPrivateProfile(mainUser));
         UserManagerService mSpiedUms = spy(mUms);
         UserInfo privateProfileUser =
                 mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
-                        USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
+                        USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null);
         Mockito.doNothing().when(mSpiedUms).setQuietModeEnabledAsync(
                 eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), any(),
                 any());
@@ -604,10 +609,12 @@
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+        int mainUser = mUms.getMainUserId();
+        assumeTrue(mUms.canAddPrivateProfile(mainUser));
         UserManagerService mSpiedUms = spy(mUms);
         UserInfo privateProfileUser =
                 mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
-                USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
+                USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null);
         mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK);
         Mockito.doNothing().when(mSpiedUms).setQuietModeEnabledAsync(
                 eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), any(),
@@ -625,6 +632,7 @@
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+        assumeTrue(mUms.canAddPrivateProfile(0));
         UserManagerService mSpiedUms = spy(mUms);
         UserInfo privateProfileUser =
                 mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
@@ -644,10 +652,12 @@
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.disableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+        int mainUser = mUms.getMainUserId();
+        assumeTrue(mUms.canAddPrivateProfile(mainUser));
         UserManagerService mSpiedUms = spy(mUms);
         UserInfo privateProfileUser =
                 mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
-                USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
+                USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null);
 
         mSpiedUms.tryAutoLockingPrivateSpaceOnKeyguardChanged(true);
 
@@ -664,13 +674,15 @@
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+        int mainUser = mUms.getMainUserId();
+        assumeTrue(mUms.canAddPrivateProfile(mainUser));
         UserManagerService mSpiedUms = spy(mUms);
         mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY);
         when(mPowerManager.isInteractive()).thenReturn(false);
 
         UserInfo privateProfileUser =
                 mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
-                        USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
+                        USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null);
         Mockito.doNothing().when(mSpiedUms).scheduleMessageToAutoLockPrivateSpace(
                 eq(privateProfileUser.getUserHandle().getIdentifier()), any(),
                 anyLong());
@@ -702,8 +714,10 @@
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
+        int mainUser = mUms.getMainUserId();
+        assumeTrue(mUms.canAddPrivateProfile(mainUser));
         mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
-                        USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
+                        USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null);
 
         // Set the preference to auto lock on device lock
         mUms.setOrUpdateAutoLockPreferenceForPrivateProfile(
@@ -754,6 +768,7 @@
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_HIDING_PROFILES);
+        assumeTrue(mUms.canAddPrivateProfile(0));
         UserInfo privateProfileUser =
                 mUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
                         USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
@@ -763,23 +778,23 @@
     }
 
     @Test
+    @RequiresFlagsEnabled({android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION, Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void testCreatePrivateProfileOnHeadlessSystemUser_shouldAllowCreation() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
         UserManagerService mSpiedUms = spy(mUms);
+        assumeTrue(mUms.isHeadlessSystemUserMode());
         int mainUser = mSpiedUms.getMainUserId();
-        doReturn(true).when(mSpiedUms).isHeadlessSystemUserMode();
-        assertThat(mSpiedUms.canAddPrivateProfile(mainUser)).isTrue();
+        // Check whether private space creation is blocked on the device
+        assumeTrue(mSpiedUms.canAddPrivateProfile(mainUser));
         assertThat(mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(
                 PRIVATE_PROFILE_NAME, USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null)).isNotNull();
     }
 
     @Test
+    @RequiresFlagsEnabled({android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION, Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void testCreatePrivateProfileOnSecondaryUser_shouldNotAllowCreation() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+        assumeTrue(mUms.canAddMoreUsersOfType(USER_TYPE_FULL_SECONDARY));
         UserInfo user = mUms.createUserWithThrow(generateLongString(), USER_TYPE_FULL_SECONDARY, 0);
         assertThat(mUms.canAddPrivateProfile(user.id)).isFalse();
         assertThrows(ServiceSpecificException.class,
@@ -788,52 +803,48 @@
     }
 
     @Test
+    @RequiresFlagsEnabled({android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION, Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void testCreatePrivateProfileOnAutoDevices_shouldNotAllowCreation() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
         doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_AUTOMOTIVE), anyInt());
         int mainUser = mUms.getMainUserId();
-        assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+        assertThat(mUms.canAddPrivateProfile(mainUser)).isFalse();
         assertThrows(ServiceSpecificException.class,
                 () -> mUms.createProfileForUserWithThrow(PRIVATE_PROFILE_NAME,
                         USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
     }
 
     @Test
+    @RequiresFlagsEnabled({android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION, Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void testCreatePrivateProfileOnTV_shouldNotAllowCreation() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
         doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_LEANBACK), anyInt());
         int mainUser = mUms.getMainUserId();
-        assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+        assertThat(mUms.canAddPrivateProfile(mainUser)).isFalse();
         assertThrows(ServiceSpecificException.class,
                 () -> mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
                         USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
     }
 
     @Test
+    @RequiresFlagsEnabled({android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION, Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void testCreatePrivateProfileOnEmbedded_shouldNotAllowCreation() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
         doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_EMBEDDED), anyInt());
         int mainUser = mUms.getMainUserId();
-        assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+        assertThat(mUms.canAddPrivateProfile(mainUser)).isFalse();
         assertThrows(ServiceSpecificException.class,
                 () -> mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
                         USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
     }
 
     @Test
+    @RequiresFlagsEnabled({android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+            Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION, Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
     public void testCreatePrivateProfileOnWatch_shouldNotAllowCreation() {
-        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
-                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
-        mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
         doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_WATCH), anyInt());
         int mainUser = mUms.getMainUserId();
-        assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+        assertThat(mUms.canAddPrivateProfile(mainUser)).isFalse();
         assertThrows(ServiceSpecificException.class,
                 () -> mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
                         USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
index b415682..0532e04 100644
--- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
@@ -55,6 +55,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -63,8 +64,7 @@
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.provider.Settings;
-import android.security.Authorization;
-import android.security.authorization.IKeystoreAuthorization;
+import android.security.KeyStoreAuthorization;
 import android.service.trust.TrustAgentService;
 import android.testing.TestableContext;
 import android.view.IWindowManager;
@@ -96,7 +96,6 @@
     @Rule
     public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
             .spyStatic(ActivityManager.class)
-            .spyStatic(Authorization.class)
             .mockStatic(ServiceManager.class)
             .mockStatic(WindowManagerGlobal.class)
             .build();
@@ -126,14 +125,13 @@
     private @Mock DevicePolicyManager mDevicePolicyManager;
     private @Mock FaceManager mFaceManager;
     private @Mock FingerprintManager mFingerprintManager;
-    private @Mock IKeystoreAuthorization mKeystoreAuthorization;
+    private @Mock KeyStoreAuthorization mKeyStoreAuthorization;
     private @Mock LockPatternUtils mLockPatternUtils;
     private @Mock PackageManager mPackageManager;
     private @Mock UserManager mUserManager;
     private @Mock IWindowManager mWindowManager;
 
     private HandlerThread mHandlerThread;
-    private TrustManagerService.Injector mInjector;
     private TrustManagerService mService;
     private ITrustManager mTrustManager;
 
@@ -145,8 +143,6 @@
         when(mFaceManager.getSensorProperties()).thenReturn(List.of());
         when(mFingerprintManager.getSensorProperties()).thenReturn(List.of());
 
-        doReturn(mKeystoreAuthorization).when(() -> Authorization.getService());
-
         when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
         when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true);
         when(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).thenReturn(mKnownTrustAgents);
@@ -193,8 +189,7 @@
 
         mHandlerThread = new HandlerThread("handler");
         mHandlerThread.start();
-        mInjector = new TrustManagerService.Injector(mLockPatternUtils, mHandlerThread.getLooper());
-        mService = new TrustManagerService(mMockContext, mInjector);
+        mService = new TrustManagerService(mMockContext, new MockInjector(mMockContext));
 
         // Get the ITrustManager from the new TrustManagerService.
         mService.onStart();
@@ -204,6 +199,27 @@
         mTrustManager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
     }
 
+    private class MockInjector extends TrustManagerService.Injector {
+        MockInjector(Context context) {
+            super(context);
+        }
+
+        @Override
+        LockPatternUtils getLockPatternUtils() {
+            return mLockPatternUtils;
+        }
+
+        @Override
+        KeyStoreAuthorization getKeyStoreAuthorization() {
+            return mKeyStoreAuthorization;
+        }
+
+        @Override
+        Looper getLooper() {
+            return mHandlerThread.getLooper();
+        }
+    }
+
     @After
     public void tearDown() {
         LocalServices.removeServiceForTest(SystemServiceManager.class);
@@ -371,14 +387,14 @@
 
         when(mWindowManager.isKeyguardLocked()).thenReturn(false);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization).onDeviceUnlocked(PARENT_USER_ID, null);
-        verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(PARENT_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
 
         when(mWindowManager.isKeyguardLocked()).thenReturn(true);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization)
+        verify(mKeyStoreAuthorization)
                 .onDeviceLocked(eq(PARENT_USER_ID), eq(PARENT_BIOMETRIC_SIDS), eq(false));
-        verify(mKeystoreAuthorization)
+        verify(mKeyStoreAuthorization)
                 .onDeviceLocked(eq(PROFILE_USER_ID), eq(PARENT_BIOMETRIC_SIDS), eq(false));
     }
 
@@ -392,10 +408,10 @@
         setupMocksForProfile(/* unifiedChallenge= */ false);
 
         mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, false);
-        verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
 
         mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, true);
-        verify(mKeystoreAuthorization)
+        verify(mKeyStoreAuthorization)
                 .onDeviceLocked(eq(PROFILE_USER_ID), eq(PROFILE_BIOMETRIC_SIDS), eq(false));
     }
 
@@ -572,11 +588,11 @@
     private void verifyWeakUnlockValue(boolean expectedWeakUnlockEnabled) throws Exception {
         when(mWindowManager.isKeyguardLocked()).thenReturn(false);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization).onDeviceUnlocked(TEST_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(TEST_USER_ID, null);
 
         when(mWindowManager.isKeyguardLocked()).thenReturn(true);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization).onDeviceLocked(eq(TEST_USER_ID), any(),
+        verify(mKeyStoreAuthorization).onDeviceLocked(eq(TEST_USER_ID), any(),
                 eq(expectedWeakUnlockEnabled));
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java
index 7ecc7fd..29f3720 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperCropperTest.java
@@ -235,12 +235,11 @@
         int expectedWidth = (int) (displaySize.x * (1 + WallpaperCropper.MAX_PARALLAX));
         Point expectedCropSize = new Point(expectedWidth, 1000);
         for (int mode: ALL_MODES) {
-            assertThat(WallpaperCropper.getAdjustedCrop(
-                    crop, bitmapSize, displaySize, true, false, mode))
-                    .isEqualTo(leftOf(crop, expectedCropSize));
-            assertThat(WallpaperCropper.getAdjustedCrop(
-                    crop, bitmapSize, displaySize, true, true, mode))
-                    .isEqualTo(rightOf(crop, expectedCropSize));
+            for (boolean rtl: List.of(false, true)) {
+                assertThat(WallpaperCropper.getAdjustedCrop(
+                        crop, bitmapSize, displaySize, true, rtl, mode))
+                        .isEqualTo(centerOf(crop, expectedCropSize));
+            }
         }
     }
 
@@ -362,11 +361,13 @@
     }
 
     /**
-     * Test that {@link WallpaperCropper#getCrop} follows a simple centre-align strategy when
-     * no suggested crops are provided.
+     * Test that {@link WallpaperCropper#getCrop} uses the full image when no crops are provided.
+     * If the image has more width/height ratio than the screen, keep that width for parallax up
+     * to {@link WallpaperCropper#MAX_PARALLAX}. If the crop has less width/height ratio, remove the
+     * surplus height, on both sides to keep the wallpaper centered.
      */
     @Test
-    public void testGetCrop_noSuggestedCrops_centersWallpaper() {
+    public void testGetCrop_noSuggestedCrops() {
         setUpWithDisplays(STANDARD_DISPLAY);
         Point bitmapSize = new Point(800, 1000);
         Rect bitmapRect = new Rect(0, 0, bitmapSize.x, bitmapSize.y);
@@ -374,9 +375,11 @@
 
         List<Point> displaySizes = List.of(
                 new Point(500, 1000),
+                new Point(200, 1000),
                 new Point(1000, 500));
         List<Point> expectedCropSizes = List.of(
-                new Point(500, 1000),
+                new Point(Math.min(800, (int) (500 * (1 + WallpaperCropper.MAX_PARALLAX))), 1000),
+                new Point(Math.min(800, (int) (200 * (1 + WallpaperCropper.MAX_PARALLAX))), 1000),
                 new Point(800, 400));
 
         for (int i = 0; i < displaySizes.size(); i++) {
@@ -450,7 +453,8 @@
     /**
      * Test that {@link WallpaperCropper#getCrop}, when asked for a folded crop with a suggested
      * crop only for the relative unfolded orientation, creates the folded crop at the center of the
-     * unfolded crop, by removing content on two sides to match the folded screen dimensions.
+     * unfolded crop, by removing content on two sides to match the folded screen dimensions, and
+     * then adds some width for parallax.
      * <p>
      * To simplify, in this test case all crops have the same size as the display (no zoom)
      * and are at the center of the image.
@@ -468,6 +472,7 @@
             int unfoldedTwo = getRotatedOrientation(unfoldedOne);
             Rect unfoldedCropOne = centerOf(bitmapRect, mDisplaySizes.get(unfoldedOne));
             Rect unfoldedCropTwo = centerOf(bitmapRect, mDisplaySizes.get(unfoldedTwo));
+            List<Rect> unfoldedCrops = List.of(unfoldedCropOne, unfoldedCropTwo);
             SparseArray<Rect> suggestedCrops = new SparseArray<>();
             suggestedCrops.put(unfoldedOne, unfoldedCropOne);
             suggestedCrops.put(unfoldedTwo, unfoldedCropTwo);
@@ -476,15 +481,28 @@
             int foldedTwo = getFoldedOrientation(unfoldedTwo);
             Point foldedDisplayOne = mDisplaySizes.get(foldedOne);
             Point foldedDisplayTwo = mDisplaySizes.get(foldedTwo);
+            List<Point> foldedDisplays = List.of(foldedDisplayOne, foldedDisplayTwo);
 
             for (boolean rtl : List.of(false, true)) {
-                assertThat(mWallpaperCropper.getCrop(
-                        foldedDisplayOne, bitmapSize, suggestedCrops, rtl))
-                        .isEqualTo(centerOf(unfoldedCropOne, foldedDisplayOne));
+                for (int i = 0; i < 2; i++) {
+                    Rect unfoldedCrop = unfoldedCrops.get(i);
+                    Point foldedDisplay = foldedDisplays.get(i);
+                    Rect expectedCrop = centerOf(unfoldedCrop, foldedDisplay);
+                    int maxParallax = (int) (WallpaperCropper.MAX_PARALLAX * unfoldedCrop.width());
 
-                assertThat(mWallpaperCropper.getCrop(
-                        foldedDisplayTwo, bitmapSize, suggestedCrops, rtl))
-                        .isEqualTo(centerOf(unfoldedCropTwo, foldedDisplayTwo));
+                    // the expected behaviour is that we add width for parallax until we reach
+                    // either MAX_PARALLAX or the edge of the crop for the unfolded screen.
+                    if (rtl) {
+                        expectedCrop.left = Math.max(
+                                unfoldedCrop.left, expectedCrop.left - maxParallax);
+                    } else {
+                        expectedCrop.right = Math.min(
+                                unfoldedCrop.right, unfoldedCrop.right + maxParallax);
+                    }
+                    assertThat(mWallpaperCropper.getCrop(
+                            foldedDisplay, bitmapSize, suggestedCrops, rtl))
+                            .isEqualTo(expectedCrop);
+                }
             }
         }
     }
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index 51c9d0a..f2b4136 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -4,58 +4,6 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-filegroup {
-    name: "power_stats_ravenwood_tests",
-    srcs: [
-        "src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java",
-        "src/com/android/server/power/stats/AggregatedPowerStatsTest.java",
-        "src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/AudioPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/BatteryChargeCalculatorTest.java",
-        "src/com/android/server/power/stats/BatteryStatsCounterTest.java",
-        "src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java",
-        "src/com/android/server/power/stats/BatteryStatsDualTimerTest.java",
-        "src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java",
-        "src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java",
-        "src/com/android/server/power/stats/BatteryStatsHistoryTest.java",
-        "src/com/android/server/power/stats/BatteryStatsImplTest.java",
-        "src/com/android/server/power/stats/BatteryStatsNoteTest.java",
-        "src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java",
-        "src/com/android/server/power/stats/BatteryStatsSensorTest.java",
-        "src/com/android/server/power/stats/BatteryStatsServTest.java",
-        "src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java",
-        "src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java",
-        "src/com/android/server/power/stats/BatteryStatsTimerTest.java",
-        "src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java",
-        "src/com/android/server/power/stats/BatteryUsageStatsTest.java",
-        "src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/CameraPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java",
-        "src/com/android/server/power/stats/CpuPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java",
-        "src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/GnssPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/IdlePowerCalculatorTest.java",
-        "src/com/android/server/power/stats/LongSamplingCounterArrayTest.java",
-        "src/com/android/server/power/stats/LongSamplingCounterTest.java",
-        "src/com/android/server/power/stats/MemoryPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/MultiStateStatsTest.java",
-        "src/com/android/server/power/stats/PowerStatsAggregatorTest.java",
-        "src/com/android/server/power/stats/PowerStatsCollectorTest.java",
-        "src/com/android/server/power/stats/PowerStatsExporterTest.java",
-        "src/com/android/server/power/stats/PowerStatsSchedulerTest.java",
-        "src/com/android/server/power/stats/PowerStatsStoreTest.java",
-        "src/com/android/server/power/stats/PowerStatsUidResolverTest.java",
-        "src/com/android/server/power/stats/ScreenPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/SensorPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/UserPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/VideoPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/WakelockPowerCalculatorTest.java",
-        "src/com/android/server/power/stats/WifiPowerCalculatorTest.java",
-    ],
-}
-
 android_test {
     name: "PowerStatsTests",
 
@@ -79,7 +27,6 @@
         "servicestests-utils",
         "platform-test-annotations",
         "flag-junit",
-        "ravenwood-junit",
     ],
 
     libs: [
@@ -112,17 +59,20 @@
     name: "PowerStatsTestsRavenwood",
     static_libs: [
         "services.core",
-        "modules-utils-binary-xml",
+        "coretests-aidl",
+        "ravenwood-junit",
+        "truth",
         "androidx.annotation_annotation",
         "androidx.test.rules",
-        "truth",
+        "androidx.test.uiautomator_uiautomator",
+        "modules-utils-binary-xml",
+        "flag-junit",
     ],
     srcs: [
-        ":power_stats_ravenwood_tests",
-
-        "src/com/android/server/power/stats/BatteryUsageStatsRule.java",
-        "src/com/android/server/power/stats/MockBatteryStatsImpl.java",
-        "src/com/android/server/power/stats/MockClock.java",
+        "src/com/android/server/power/stats/*.java",
+    ],
+    java_resources: [
+        "res/xml/power_profile*.xml",
     ],
     auto_gen_config: true,
 }
diff --git a/services/tests/powerstatstests/TEST_MAPPING b/services/tests/powerstatstests/TEST_MAPPING
index 6d3db1c..fb24361 100644
--- a/services/tests/powerstatstests/TEST_MAPPING
+++ b/services/tests/powerstatstests/TEST_MAPPING
@@ -12,7 +12,11 @@
   "ravenwood-presubmit": [
     {
       "name": "PowerStatsTestsRavenwood",
-      "host": true
+      "host": true,
+      "options": [
+        {"include-filter": "com.android.server.power.stats"},
+        {"exclude-annotation": "android.platform.test.annotations.DisabledOnRavenwood"}
+      ]
     }
   ],
   "postsubmit": [
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java
deleted file mode 100644
index af83be0..0000000
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java
+++ /dev/null
@@ -1,137 +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.power.stats;
-
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.BatteryConsumer;
-
-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.List;
-import java.util.Objects;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class AggregatedPowerStatsProcessorTest {
-
-    @Test
-    public void createPowerEstimationPlan_allDeviceStatesPresentInUidStates() {
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_ANY)
-                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE);
-
-        AggregatedPowerStatsProcessor.PowerEstimationPlan plan =
-                new AggregatedPowerStatsProcessor.PowerEstimationPlan(config);
-        assertThat(deviceStateEstimatesToStrings(plan))
-                .containsExactly("[0, 0]", "[0, 1]", "[1, 0]", "[1, 1]");
-        assertThat(combinedDeviceStatsToStrings(plan))
-                .containsExactly("[[0, 0]]", "[[0, 1]]", "[[1, 0]]", "[[1, 1]]");
-        assertThat(uidStateEstimatesToStrings(plan, config))
-                .containsExactly(
-                        "[[0, 0]]: [ps]: [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 0, 4]]",
-                        "[[0, 1]]: [ps]: [[0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 1, 4]]",
-                        "[[1, 0]]: [ps]: [[1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 0, 3], [1, 0, 4]]",
-                        "[[1, 1]]: [ps]: [[1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4]]");
-    }
-
-    @Test
-    public void createPowerEstimationPlan_combineDeviceStats() {
-        AggregatedPowerStatsConfig.PowerComponent config =
-                new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_ANY)
-                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                        .trackUidStates(STATE_POWER, STATE_PROCESS_STATE);
-
-        AggregatedPowerStatsProcessor.PowerEstimationPlan plan =
-                new AggregatedPowerStatsProcessor.PowerEstimationPlan(config);
-
-        assertThat(deviceStateEstimatesToStrings(plan))
-                .containsExactly("[0, 0]", "[0, 1]", "[1, 0]", "[1, 1]");
-        assertThat(combinedDeviceStatsToStrings(plan))
-                .containsExactly(
-                        "[[0, 0], [0, 1]]",
-                        "[[1, 0], [1, 1]]");
-        assertThat(uidStateEstimatesToStrings(plan, config))
-                .containsExactly(
-                        "[[0, 0], [0, 1]]: [ps]: [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]]",
-                        "[[1, 0], [1, 1]]: [ps]: [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4]]");
-    }
-
-    private static List<String> deviceStateEstimatesToStrings(
-            AggregatedPowerStatsProcessor.PowerEstimationPlan plan) {
-        return plan.deviceStateEstimations.stream()
-                .map(dse -> dse.stateValues).map(Arrays::toString).toList();
-    }
-
-    private static List<String> combinedDeviceStatsToStrings(
-            AggregatedPowerStatsProcessor.PowerEstimationPlan plan) {
-        return plan.combinedDeviceStateEstimations.stream()
-                .map(cds -> cds.deviceStateEstimations)
-                .map(dses -> dses.stream()
-                        .map(dse -> dse.stateValues).map(Arrays::toString).toList())
-                .map(Object::toString)
-                .toList();
-    }
-
-    private static List<String> uidStateEstimatesToStrings(
-            AggregatedPowerStatsProcessor.PowerEstimationPlan plan,
-            AggregatedPowerStatsConfig.PowerComponent config) {
-        MultiStateStats.States[] uidStateConfig = config.getUidStateConfig();
-        return plan.uidStateEstimates.stream()
-                .map(use ->
-                        use.combinedDeviceStateEstimate.deviceStateEstimations.stream()
-                                .map(dse -> dse.stateValues).map(Arrays::toString).toList()
-                        + ": "
-                        + Arrays.stream(use.states)
-                                .filter(Objects::nonNull)
-                                .map(MultiStateStats.States::getName).toList()
-                        + ": "
-                        + use.proportionalEstimates.stream()
-                                .map(pe -> trackedStatesToString(uidStateConfig, pe.stateValues))
-                                .toList())
-                .toList();
-    }
-
-    private static Object trackedStatesToString(MultiStateStats.States[] states,
-            int[] stateValues) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[");
-        boolean first = true;
-        for (int i = 0; i < states.length; i++) {
-            if (!states[i].isTracked()) {
-                continue;
-            }
-
-            if (!first) {
-                sb.append(", ");
-            }
-            first = false;
-            sb.append(stateValues[i]);
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
index ca7de7c..9975190 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
@@ -20,6 +20,7 @@
 
 import android.os.BatteryConsumer;
 import android.os.PersistableBundle;
+import android.util.SparseArray;
 import android.util.Xml;
 
 import androidx.test.filters.SmallTest;
@@ -43,6 +44,9 @@
     private static final int TEST_POWER_COMPONENT = 1077;
     private static final int APP_1 = 27;
     private static final int APP_2 = 42;
+    private static final int COMPONENT_STATE_0 = 0;
+    private static final int COMPONENT_STATE_1 = 1;
+    private static final int COMPONENT_STATE_2 = 2;
 
     private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
     private PowerStats.Descriptor mPowerComponentDescriptor;
@@ -59,8 +63,10 @@
                         AggregatedPowerStatsConfig.STATE_SCREEN,
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
 
-        mPowerComponentDescriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT, "fan", 2, 3,
-                PersistableBundle.forPair("speed", "fast"));
+        SparseArray<String> stateLabels = new SparseArray<>();
+        stateLabels.put(COMPONENT_STATE_1, "one");
+        mPowerComponentDescriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT, "fan", 2,
+                stateLabels, 1, 3, PersistableBundle.forPair("speed", "fast"));
     }
 
     @Test
@@ -107,6 +113,9 @@
         ps.stats[0] = 100;
         ps.stats[1] = 987;
 
+        ps.stateStats.put(COMPONENT_STATE_0, new long[]{1111});
+        ps.stateStats.put(COMPONENT_STATE_1, new long[]{5000});
+
         ps.uidStats.put(APP_1, new long[]{389, 0, 739});
         ps.uidStats.put(APP_2, new long[]{278, 314, 628});
 
@@ -120,11 +129,14 @@
         ps.stats[0] = 444;
         ps.stats[1] = 0;
 
+        ps.stateStats.clear();
+        ps.stateStats.put(COMPONENT_STATE_1, new long[]{1000});
+        ps.stateStats.put(COMPONENT_STATE_2, new long[]{9000});
+
         ps.uidStats.put(APP_1, new long[]{0, 0, 400});
         ps.uidStats.put(APP_2, new long[]{100, 200, 300});
 
         stats.addPowerStats(ps, 5000);
-
         return stats;
     }
 
@@ -147,6 +159,31 @@
                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER))
                 .isEqualTo(new long[]{222, 0});
 
+        assertThat(getStateStats(stats, COMPONENT_STATE_0,
+                AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
+                AggregatedPowerStatsConfig.SCREEN_STATE_ON))
+                .isEqualTo(new long[]{1111});
+
+        assertThat(getStateStats(stats, COMPONENT_STATE_1,
+                AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
+                AggregatedPowerStatsConfig.SCREEN_STATE_ON))
+                .isEqualTo(new long[]{5500});
+
+        assertThat(getStateStats(stats, COMPONENT_STATE_1,
+                AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
+                AggregatedPowerStatsConfig.SCREEN_STATE_OTHER))
+                .isEqualTo(new long[]{500});
+
+        assertThat(getStateStats(stats, COMPONENT_STATE_2,
+                AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
+                AggregatedPowerStatsConfig.SCREEN_STATE_ON))
+                .isEqualTo(new long[]{4500});
+
+        assertThat(getStateStats(stats, COMPONENT_STATE_2,
+                AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
+                AggregatedPowerStatsConfig.SCREEN_STATE_OTHER))
+                .isEqualTo(new long[]{4500});
+
         assertThat(getUidDeviceStats(stats,
                 APP_1,
                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
@@ -191,14 +228,26 @@
     }
 
     private static long[] getDeviceStats(AggregatedPowerStats stats, int... states) {
-        long[] out = new long[states.length];
-        stats.getPowerComponentStats(TEST_POWER_COMPONENT).getDeviceStats(out, states);
+        PowerComponentAggregatedPowerStats powerComponentStats =
+                stats.getPowerComponentStats(TEST_POWER_COMPONENT);
+        long[] out = new long[powerComponentStats.getPowerStatsDescriptor().statsArrayLength];
+        powerComponentStats.getDeviceStats(out, states);
+        return out;
+    }
+
+    private static long[] getStateStats(AggregatedPowerStats stats, int key, int... states) {
+        PowerComponentAggregatedPowerStats powerComponentStats =
+                stats.getPowerComponentStats(TEST_POWER_COMPONENT);
+        long[] out = new long[powerComponentStats.getPowerStatsDescriptor().stateStatsArrayLength];
+        powerComponentStats.getStateStats(out, key, states);
         return out;
     }
 
     private static long[] getUidDeviceStats(AggregatedPowerStats stats, int uid, int... states) {
-        long[] out = new long[states.length];
-        stats.getPowerComponentStats(TEST_POWER_COMPONENT).getUidStats(out, uid, states);
+        PowerComponentAggregatedPowerStats powerComponentStats =
+                stats.getPowerComponentStats(TEST_POWER_COMPONENT);
+        long[] out = new long[powerComponentStats.getPowerStatsDescriptor().uidStatsArrayLength];
+        powerComponentStats.getUidStats(out, uid, states);
         return out;
     }
 }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java
index 3ab1c2e..9b45ca7 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java
@@ -16,9 +16,11 @@
 
 package com.android.server.power.stats;
 
-
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
 import android.os.BatteryManager;
 import android.os.BatteryUsageStats;
 import android.platform.test.ravenwood.RavenwoodRule;
@@ -28,6 +30,7 @@
 
 import com.android.internal.os.PowerProfile;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -46,6 +49,11 @@
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
                     .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0);
 
+    @Before
+    public void setup() {
+        mStatsRule.getBatteryStats().onSystemReady(mock(Context.class));
+    }
+
     @Test
     public void testDischargeTotals() {
         // Nominal battery capacity should be ignored
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
index 997b771..bbab0ee 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
@@ -36,6 +36,9 @@
 import android.hardware.power.stats.EnergyMeasurement;
 import android.hardware.power.stats.PowerEntity;
 import android.hardware.power.stats.StateResidencyResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.power.PowerStatsInternal;
 import android.util.IntArray;
 import android.util.SparseArray;
@@ -44,9 +47,11 @@
 
 import com.android.internal.os.Clock;
 import com.android.internal.os.CpuScalingPolicies;
+import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerProfile;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -59,19 +64,27 @@
  * atest FrameworksServicesTests:BatteryExternalStatsWorkerTest
  */
 @SuppressWarnings("GuardedBy")
[email protected]
 public class BatteryExternalStatsWorkerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private BatteryExternalStatsWorker mBatteryExternalStatsWorker;
-    private TestBatteryStatsImpl mBatteryStatsImpl;
     private TestPowerStatsInternal mPowerStatsInternal;
 
     @Before
     public void setUp() {
         final Context context = InstrumentationRegistry.getContext();
 
-        mBatteryStatsImpl = new TestBatteryStatsImpl(context);
+        BatteryStatsImpl batteryStats = new BatteryStatsImpl(
+                new BatteryStatsImpl.BatteryStatsConfig.Builder().build(), Clock.SYSTEM_CLOCK,
+                new MonotonicClock(0, Clock.SYSTEM_CLOCK), null,
+                new Handler(Looper.getMainLooper()), null, null, null,
+                new PowerProfile(context, true /* forTest */), buildScalingPolicies(),
+                new PowerStatsUidResolver());
         mPowerStatsInternal = new TestPowerStatsInternal();
-        mBatteryExternalStatsWorker = new BatteryExternalStatsWorker(new TestInjector(context),
-                mBatteryStatsImpl);
+        mBatteryExternalStatsWorker =
+                new BatteryExternalStatsWorker(new TestInjector(context), batteryStats);
     }
 
     @Test
@@ -213,24 +226,17 @@
         }
     }
 
-    public class TestBatteryStatsImpl extends BatteryStatsImpl {
-        public TestBatteryStatsImpl(Context context) {
-            super(Clock.SYSTEM_CLOCK, null, null, null, null, null, null);
-            mPowerProfile = new PowerProfile(context, true /* forTest */);
-
-            SparseArray<int[]> cpusByPolicy = new SparseArray<>();
-            cpusByPolicy.put(0, new int[]{0, 1, 2, 3});
-            cpusByPolicy.put(4, new int[]{4, 5, 6, 7});
-            SparseArray<int[]> freqsByPolicy = new SparseArray<>();
-            freqsByPolicy.put(0, new int[]{300000, 1000000, 2000000});
-            freqsByPolicy.put(4, new int[]{300000, 1000000, 2500000, 3000000});
-            mCpuScalingPolicies = new CpuScalingPolicies(freqsByPolicy, freqsByPolicy);
-
-            initTimersAndCounters();
-        }
+    private static CpuScalingPolicies buildScalingPolicies() {
+        SparseArray<int[]> cpusByPolicy = new SparseArray<>();
+        cpusByPolicy.put(0, new int[]{0, 1, 2, 3});
+        cpusByPolicy.put(4, new int[]{4, 5, 6, 7});
+        SparseArray<int[]> freqsByPolicy = new SparseArray<>();
+        freqsByPolicy.put(0, new int[]{300000, 1000000, 2000000});
+        freqsByPolicy.put(4, new int[]{300000, 1000000, 2500000, 3000000});
+        return new CpuScalingPolicies(freqsByPolicy, freqsByPolicy);
     }
 
-    public class TestPowerStatsInternal extends PowerStatsInternal {
+    private static class TestPowerStatsInternal extends PowerStatsInternal {
         private final SparseArray<EnergyConsumer> mEnergyConsumers = new SparseArray();
         private final SparseArray<EnergyConsumerResult> mEnergyConsumerResults = new SparseArray();
         private final int mTimeSinceBoot = 0;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java
index 4d3fcb6..ad05b51 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java
@@ -18,25 +18,37 @@
 
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.app.ActivityManager;
 import android.os.BatteryStats;
 import android.os.WorkSource;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArrayMap;
 import android.view.Display;
 
 import androidx.test.filters.SmallTest;
 
-import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.Test;
 
 /**
  * Test BatteryStatsImpl onBatteryBackgroundTimeBase TimeBase.
  */
-public class BatteryStatsBackgroundStatsTest extends TestCase {
+public class BatteryStatsBackgroundStatsTest {
+
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
 
     private static final int UID = 10500;
 
     /** Test that BatteryStatsImpl.Uid.mOnBatteryBackgroundTimeBase works correctly. */
     @SmallTest
+    @Test
     public void testBgTimeBase() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
@@ -105,6 +117,7 @@
 
     /** Test that BatteryStatsImpl.Uid.mOnBatteryScreenOffBackgroundTimeBase works correctly. */
     @SmallTest
+    @Test
     public void testScreenOffBgTimeBase() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
@@ -153,6 +166,7 @@
     }
 
     @SmallTest
+    @Test
     public void testWifiScan() throws Exception {
         final MockClock clocks = new MockClock();
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
@@ -195,11 +209,13 @@
     }
 
     @SmallTest
+    @Test
     public void testAppBluetoothScan() throws Exception {
         doTestAppBluetoothScanInternal(new WorkSource(UID));
     }
 
     @SmallTest
+    @Test
     public void testAppBluetoothScan_workChain() throws Exception {
         WorkSource ws = new WorkSource();
         ws.createWorkChain().addNode(UID, "foo");
@@ -275,6 +291,7 @@
     }
 
     @SmallTest
+    @Test
     public void testJob() throws Exception {
         final MockClock clocks = new MockClock();
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
@@ -336,6 +353,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSyncs() throws Exception {
         final MockClock clocks = new MockClock();
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java
index 3f101a9..4dfc3fc 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java
@@ -16,20 +16,20 @@
 
 package com.android.server.power.stats;
 
+import static org.junit.Assert.assertEquals;
+
 import android.os.Binder;
 import android.os.Process;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderTransactionNameResolver;
 
-import junit.framework.TestCase;
-
+import org.junit.Rule;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -37,9 +37,14 @@
 /**
  * Test cases for android.os.BatteryStats, system server Binder call stats.
  */
-@RunWith(AndroidJUnit4.class)
 @SmallTest
-public class BatteryStatsBinderCallStatsTest extends TestCase {
[email protected](blockedBy = BinderCallsStats.class)
+public class BatteryStatsBinderCallStatsTest {
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
 
     private static final int TRANSACTION_CODE1 = 100;
     private static final int TRANSACTION_CODE2 = 101;
@@ -89,7 +94,6 @@
         assertEquals(500, value.recordedCpuTimeMicros);
     }
 
-
     @Test
     public void testProportionalSystemServiceUsage_noStatsForSomeMethods() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java
index 6e62147..eff1b7b 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java
@@ -118,7 +118,8 @@
         mClocks = new MockClock();
         Handler handler = new Handler(Looper.getMainLooper());
         mPowerStatsUidResolver = new PowerStatsUidResolver();
-        mBatteryStatsImpl = new MockBatteryStatsImpl(mClocks, null, handler, mPowerStatsUidResolver)
+        mBatteryStatsImpl = new MockBatteryStatsImpl(MockBatteryStatsImpl.DEFAULT_CONFIG,
+                mClocks, null, handler, mPowerStatsUidResolver)
                 .setTestCpuScalingPolicies()
                 .setKernelCpuUidUserSysTimeReader(mCpuUidUserSysTimeReader)
                 .setKernelCpuUidFreqTimeReader(mCpuUidFreqTimeReader)
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index c58c92b..e40a3e3 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -403,7 +403,7 @@
 
     @Test
     public void recordPowerStats() {
-        PowerStats.Descriptor descriptor = new PowerStats.Descriptor(42, "foo", 1, 2,
+        PowerStats.Descriptor descriptor = new PowerStats.Descriptor(42, "foo", 1, null, 0, 2,
                 new PersistableBundle());
         PowerStats powerStats = new PowerStats(descriptor);
         powerStats.durationMs = 100;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
index 7ae1117..9a64ce1 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
@@ -25,15 +25,21 @@
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
 import android.os.UidBatteryConsumer;
+import android.platform.test.ravenwood.RavenwoodRule;
 
+import org.junit.Rule;
 import org.junit.Test;
 
 /**
  * Test BatteryStatsManager and CellularBatteryStats to ensure that valid data is being reported
  * and that invalid data is not reported.
  */
[email protected](reason = "Integration test")
 public class BatteryStatsManagerTest {
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
     public void testBatteryUsageStatsDataConsistency() {
         BatteryStatsManager bsm = getContext().getSystemService(BatteryStatsManager.class);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
index 07cefa9..afbe9159 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
@@ -170,8 +170,8 @@
     public void testNoteStartWakeLocked_isolatedUid() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
         PowerStatsUidResolver uidResolver = new PowerStatsUidResolver();
-        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks, null,
-                new Handler(Looper.getMainLooper()), uidResolver);
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(MockBatteryStatsImpl.DEFAULT_CONFIG,
+                clocks, null, new Handler(Looper.getMainLooper()), uidResolver);
 
         int pid = 10;
         String name = "name";
@@ -212,8 +212,8 @@
     public void testNoteStartWakeLocked_isolatedUidRace() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
         PowerStatsUidResolver uidResolver = new PowerStatsUidResolver();
-        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks, null,
-                new Handler(Looper.getMainLooper()), uidResolver);
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(MockBatteryStatsImpl.DEFAULT_CONFIG,
+                clocks, null, new Handler(Looper.getMainLooper()), uidResolver);
 
         int pid = 10;
         String name = "name";
@@ -256,8 +256,8 @@
     public void testNoteLongPartialWakelockStart_isolatedUid() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
         PowerStatsUidResolver uidResolver = new PowerStatsUidResolver();
-        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks, null,
-                new Handler(Looper.getMainLooper()), uidResolver);
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(MockBatteryStatsImpl.DEFAULT_CONFIG,
+                clocks, null, new Handler(Looper.getMainLooper()), uidResolver);
 
         bi.setRecordAllHistoryLocked(true);
         bi.forceRecordAllHistory();
@@ -311,8 +311,8 @@
     public void testNoteLongPartialWakelockStart_isolatedUidRace() throws Exception {
         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
         PowerStatsUidResolver uidResolver = new PowerStatsUidResolver();
-        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks, null,
-                new Handler(Looper.getMainLooper()), uidResolver);
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(MockBatteryStatsImpl.DEFAULT_CONFIG,
+                clocks, null, new Handler(Looper.getMainLooper()), uidResolver);
 
         bi.setRecordAllHistoryLocked(true);
         bi.forceRecordAllHistory();
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java
index a0fb631..d29bf1a 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java
@@ -18,21 +18,32 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
+
 import android.content.Context;
 import android.os.BatteryManager;
+import android.platform.test.ravenwood.RavenwoodRule;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.IOException;
+import java.nio.file.Files;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class BatteryStatsResetTest {
 
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
     private static final int BATTERY_NOMINAL_VOLTAGE_MV = 3700;
     private static final int BATTERY_CAPACITY_UAH = 4_000_000;
     private static final int BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL = 100;
@@ -79,13 +90,11 @@
     private long mBatteryChargeTimeToFullSeconds;
 
     @Before
-    public void setUp() {
-        final Context context = InstrumentationRegistry.getContext();
-
+    public void setUp() throws IOException {
         mMockClock = new MockClock();
-        mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock, context.getFilesDir());
-        mBatteryStatsImpl.onSystemReady();
-
+        mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock,
+                Files.createTempDirectory("BatteryStatsResetTest").toFile());
+        mBatteryStatsImpl.onSystemReady(mock(Context.class));
 
         // Set up the battery state. Start off with a fully charged plugged in battery.
         mBatteryStatus = BatteryManager.BATTERY_STATUS_FULL;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
index 05d8a00..3931201 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
@@ -28,6 +28,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArraySet;
 
 import androidx.test.InstrumentationRegistry;
@@ -38,6 +39,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -46,8 +48,10 @@
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
[email protected]
[email protected](reason = "Integration test")
 public class BatteryStatsUserLifecycleTests {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static final long POLL_INTERVAL_MS = 500;
     private static final long USER_REMOVE_TIMEOUT_MS = 5_000;
@@ -65,6 +69,10 @@
 
     @BeforeClass
     public static void setUpOnce() {
+        if (RavenwoodRule.isOnRavenwood()) {
+            return;
+        }
+
         assumeTrue(UserManager.getMaxSupportedUsers() > 1);
     }
 
@@ -87,7 +95,7 @@
 
         final boolean[] userStopped = new boolean[1];
         CountDownLatch stopUserLatch = new CountDownLatch(1);
-        mIam.stopUser(mTestUserId, true, new IStopUserCallback.Stub() {
+        mIam.stopUserWithCallback(mTestUserId, new IStopUserCallback.Stub() {
             @Override
             public void userStopped(int userId) throws RemoteException {
                 userStopped[0] = true;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
index 296ad0e..2d7cb22 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
@@ -24,7 +24,8 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import android.annotation.XmlRes;
+import android.content.Context;
+import android.content.res.Resources;
 import android.net.NetworkStats;
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
@@ -35,9 +36,9 @@
 import android.os.HandlerThread;
 import android.os.UidBatteryConsumer;
 import android.os.UserBatteryConsumer;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
-
-import androidx.test.InstrumentationRegistry;
+import android.util.Xml;
 
 import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.PowerProfile;
@@ -47,6 +48,7 @@
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 import org.mockito.stubbing.Answer;
+import org.xmlpull.v1.XmlPullParser;
 
 import java.io.File;
 import java.io.IOException;
@@ -81,6 +83,7 @@
     private boolean[] mSupportedStandardBuckets;
     private String[] mCustomPowerComponentNames;
     private Throwable mThrowable;
+    private final BatteryStatsImpl.BatteryStatsConfig.Builder mBatteryStatsConfigBuilder;
 
     public BatteryUsageStatsRule() {
         this(0);
@@ -94,6 +97,11 @@
         mCpusByPolicy.put(4, new int[]{4, 5, 6, 7});
         mFreqsByPolicy.put(0, new int[]{300000, 1000000, 2000000});
         mFreqsByPolicy.put(4, new int[]{300000, 1000000, 2500000, 3000000});
+        mBatteryStatsConfigBuilder = new BatteryStatsImpl.BatteryStatsConfig.Builder()
+                .setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_CPU,
+                        10000)
+                .setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+                        10000);
     }
 
     private void initBatteryStats() {
@@ -107,7 +115,8 @@
             }
             clearDirectory();
         }
-        mBatteryStats = new MockBatteryStatsImpl(mMockClock, mHistoryDir, mHandler);
+        mBatteryStats = new MockBatteryStatsImpl(mBatteryStatsConfigBuilder.build(),
+                mMockClock, mHistoryDir, mHandler, new PowerStatsUidResolver());
         mBatteryStats.setPowerProfile(mPowerProfile);
         mBatteryStats.setCpuScalingPolicies(new CpuScalingPolicies(mCpusByPolicy, mFreqsByPolicy));
         synchronized (mBatteryStats) {
@@ -116,8 +125,6 @@
         }
         mBatteryStats.informThatAllExternalStatsAreFlushed();
 
-        mBatteryStats.onSystemReady();
-
         if (mDisplayCount != -1) {
             mBatteryStats.setDisplayCountLocked(mDisplayCount);
         }
@@ -148,11 +155,27 @@
         return this;
     }
 
-    public BatteryUsageStatsRule setTestPowerProfile(@XmlRes int xmlId) {
-        mPowerProfile.forceInitForTesting(InstrumentationRegistry.getContext(), xmlId);
+    public BatteryUsageStatsRule setTestPowerProfile(String resourceName) {
+        mPowerProfile.initForTesting(resolveParser(resourceName));
         return this;
     }
 
+    public static XmlPullParser resolveParser(String resourceName) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            try {
+                return Xml.resolvePullParser(BatteryUsageStatsRule.class.getClassLoader()
+                        .getResourceAsStream("res/xml/" + resourceName + ".xml"));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            Context context = androidx.test.InstrumentationRegistry.getContext();
+            Resources resources = context.getResources();
+            int resId = resources.getIdentifier(resourceName, "xml", context.getPackageName());
+            return resources.getXml(resId);
+        }
+    }
+
     public BatteryUsageStatsRule setCpuScalingPolicy(int policy, int[] relatedCpus,
             int[] frequencies) {
         if (mDefaultCpuScalingPolicy) {
@@ -265,6 +288,12 @@
         return this;
     }
 
+    public BatteryUsageStatsRule setPowerStatsThrottlePeriodMillis(int powerComponent,
+            long throttleMs) {
+        mBatteryStatsConfigBuilder.setPowerStatsThrottlePeriodMillis(powerComponent, throttleMs);
+        return this;
+    }
+
     public BatteryUsageStatsRule startWithScreenOn(boolean screenOn) {
         mScreenOn = screenOn;
         return this;
@@ -291,23 +320,21 @@
     }
 
     private void before() {
-        initBatteryStats();
         HandlerThread bgThread = new HandlerThread("bg thread");
         bgThread.setUncaughtExceptionHandler((thread, throwable)-> {
             mThrowable = throwable;
         });
         bgThread.start();
         mHandler = new Handler(bgThread.getLooper());
-        mBatteryStats.setHandler(mHandler);
+
+        initBatteryStats();
         mBatteryStats.setOnBatteryInternal(true);
         mBatteryStats.getOnBatteryTimeBase().setRunning(true, 0, 0);
         mBatteryStats.getOnBatteryScreenOffTimeBase().setRunning(!mScreenOn, 0, 0);
     }
 
     private void after() throws Throwable {
-        if (mHandler != null) {
-            waitForBackgroundThread();
-        }
+        waitForBackgroundThread();
     }
 
     public void waitForBackgroundThread() throws Throwable {
@@ -316,11 +343,12 @@
         }
 
         ConditionVariable done = new ConditionVariable();
-        mHandler.post(done::open);
-        assertThat(done.block(10000)).isTrue();
-
-        if (mThrowable != null) {
-            throw mThrowable;
+        if (mHandler.post(done::open)) {
+            boolean success = done.block(5000);
+            if (mThrowable != null) {
+                throw mThrowable;
+            }
+            assertThat(success).isTrue();
         }
     }
 
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
index 29e2f5e..e4ab227 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
@@ -46,6 +46,7 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.SystemClock;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
@@ -74,9 +75,11 @@
 import java.util.regex.Pattern;
 
 @LargeTest
-@RunWith(AndroidJUnit4.class)
[email protected]
[email protected](reason = "Integration test")
 public class BstatsCpuTimesValidationTest {
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final String TAG = BstatsCpuTimesValidationTest.class.getSimpleName();
 
     private static final String TEST_PKG = "com.android.coretests.apps.bstatstestapp";
@@ -112,10 +115,15 @@
     private static boolean sCpuFreqTimesAvailable;
     private static boolean sPerProcStateTimesAvailable;
 
-    @Rule public TestName testName = new TestName();
+    @Rule(order = 1)
+    public TestName testName = new TestName();
 
     @BeforeClass
     public static void setupOnce() throws Exception {
+        if (RavenwoodRule.isOnRavenwood()) {
+            return;
+        }
+
         sContext = InstrumentationRegistry.getContext();
         sUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         sContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
@@ -127,6 +135,10 @@
 
     @AfterClass
     public static void tearDownOnce() throws Exception {
+        if (RavenwoodRule.isOnRavenwood()) {
+            return;
+        }
+
         executeCmd("cmd deviceidle whitelist -" + TEST_PKG);
         if (sBatteryStatsConstsUpdated) {
             Settings.Global.putString(sContext.getContentResolver(),
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java
deleted file mode 100644
index 5c0e268..0000000
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java
+++ /dev/null
@@ -1,323 +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.power.stats;
-
-import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
-import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
-import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
-
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.fail;
-
-import android.os.BatteryConsumer;
-import android.os.PersistableBundle;
-import android.platform.test.ravenwood.RavenwoodRule;
-import android.util.LongArray;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.os.PowerProfile;
-import com.android.internal.os.PowerStats;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class CpuAggregatedPowerStatsProcessorTest {
-    @Rule(order = 0)
-    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
-            .setProvideMainThread(true)
-            .build();
-
-    @Rule(order = 1)
-    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
-            .setAveragePower(PowerProfile.POWER_CPU_ACTIVE, 720)
-            .setCpuScalingPolicy(0, new int[]{0, 1}, new int[]{100, 200})
-            .setCpuScalingPolicy(2, new int[]{2, 3}, new int[]{300})
-            .setAveragePowerForCpuScalingPolicy(0, 360)
-            .setAveragePowerForCpuScalingPolicy(2, 480)
-            .setAveragePowerForCpuScalingStep(0, 0, 300)
-            .setAveragePowerForCpuScalingStep(0, 1, 400)
-            .setAveragePowerForCpuScalingStep(2, 0, 500)
-            .setCpuPowerBracketCount(3)
-            .setCpuPowerBracket(0, 0, 0)
-            .setCpuPowerBracket(0, 1, 1)
-            .setCpuPowerBracket(2, 0, 2);
-
-    private AggregatedPowerStatsConfig.PowerComponent mConfig;
-    private CpuAggregatedPowerStatsProcessor mProcessor;
-    private MockPowerComponentAggregatedPowerStats mStats;
-
-    @Before
-    public void setup() {
-        mConfig = new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
-                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
-                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE);
-
-        mProcessor = new CpuAggregatedPowerStatsProcessor(
-                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies());
-    }
-
-    @Test
-    public void powerProfileModel() {
-        mStats = new MockPowerComponentAggregatedPowerStats(mConfig, false);
-        mStats.setDeviceStats(
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON),
-                concat(
-                        values(3500, 4500, 3000),   // scaling steps
-                        values(2000, 1000),         // clusters
-                        values(5000)),              // uptime
-                3.113732);
-        mStats.setDeviceStats(
-                states(POWER_STATE_OTHER, SCREEN_STATE_ON),
-                concat(
-                        values(6000, 6500, 4000),
-                        values(5000, 3000),
-                        values(7000)),
-                4.607245);
-        mStats.setDeviceStats(
-                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER),
-                concat(
-                        values(9000, 10000, 7000),
-                        values(8000, 6000),
-                        values(20000)),
-                7.331799);
-        mStats.setUidStats(24,
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
-                values(400, 1500, 2000),  1.206947);
-        mStats.setUidStats(42,
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
-                values(900, 1000, 1500), 1.016182);
-        mStats.setUidStats(42,
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_BACKGROUND),
-                values(600, 500, 300), 0.385042);
-        mStats.setUidStats(42,
-                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED),
-                values(1500, 2000, 1000), 1.252578);
-
-        mProcessor.finish(mStats);
-
-        mStats.verifyPowerEstimates();
-    }
-
-    @Test
-    public void energyConsumerModel() {
-        mStats = new MockPowerComponentAggregatedPowerStats(mConfig, true);
-        mStats.setDeviceStats(
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON),
-                concat(
-                        values(3500, 4500, 3000),           // scaling steps
-                        values(2000, 1000),                 // clusters
-                        values(5000),                       // uptime
-                        values(5_000_000L, 6_000_000L)),    // energy, uC
-                3.055555);
-        mStats.setDeviceStats(
-                states(POWER_STATE_OTHER, SCREEN_STATE_ON),
-                concat(
-                        values(6000, 6500, 4000),
-                        values(5000, 3000),
-                        values(7000),
-                        values(5_000_000L, 6_000_000L)),    // same as above
-                3.055555);                                  // same as above - WAI
-        mStats.setDeviceStats(
-                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER),
-                concat(
-                        values(9000, 10000, 7000),
-                        values(8000, 6000),
-                        values(20000),
-                        values(8_000_000L, 18_000_000L)),
-                7.222222);
-        mStats.setUidStats(24,
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
-                values(400, 1500, 2000),  1.449078);
-        mStats.setUidStats(42,
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
-                values(900, 1000, 1500), 1.161902);
-        mStats.setUidStats(42,
-                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_BACKGROUND),
-                values(600, 500, 300), 0.355406);
-        mStats.setUidStats(42,
-                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED),
-                values(1500, 2000, 1000), 0.80773);
-
-        mProcessor.finish(mStats);
-
-        mStats.verifyPowerEstimates();
-    }
-
-    private int[] states(int... states) {
-        return states;
-    }
-
-    private long[] values(long... values) {
-        return values;
-    }
-
-    private long[] concat(long[]... arrays) {
-        LongArray all = new LongArray();
-        for (long[] array : arrays) {
-            for (long value : array) {
-                all.add(value);
-            }
-        }
-        return all.toArray();
-    }
-
-    private static class MockPowerComponentAggregatedPowerStats extends
-            PowerComponentAggregatedPowerStats {
-        private final CpuPowerStatsCollector.CpuStatsArrayLayout mStatsLayout;
-        private final PowerStats.Descriptor mDescriptor;
-        private HashMap<String, long[]> mDeviceStats = new HashMap<>();
-        private HashMap<String, long[]> mUidStats = new HashMap<>();
-        private HashSet<Integer> mUids = new HashSet<>();
-        private HashMap<String, Double> mExpectedDevicePower = new HashMap<>();
-        private HashMap<String, Double> mExpectedUidPower = new HashMap<>();
-
-        MockPowerComponentAggregatedPowerStats(AggregatedPowerStatsConfig.PowerComponent config,
-                boolean useEnergyConsumers) {
-            super(config);
-            mStatsLayout = new CpuPowerStatsCollector.CpuStatsArrayLayout();
-            mStatsLayout.addDeviceSectionCpuTimeByScalingStep(3);
-            mStatsLayout.addDeviceSectionCpuTimeByCluster(2);
-            mStatsLayout.addDeviceSectionUsageDuration();
-            if (useEnergyConsumers) {
-                mStatsLayout.addDeviceSectionEnergyConsumers(2);
-            }
-            mStatsLayout.addDeviceSectionPowerEstimate();
-            mStatsLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0, 1, 2});
-            mStatsLayout.addUidSectionPowerEstimate();
-
-            PersistableBundle extras = new PersistableBundle();
-            mStatsLayout.toExtras(extras);
-            mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
-                    mStatsLayout.getDeviceStatsArrayLength(), mStatsLayout.getUidStatsArrayLength(),
-                    extras);
-        }
-
-        @Override
-        public PowerStats.Descriptor getPowerStatsDescriptor() {
-            return mDescriptor;
-        }
-
-        @Override
-        boolean getDeviceStats(long[] outValues, int[] deviceStates) {
-            long[] values = getDeviceStats(deviceStates);
-            System.arraycopy(values, 0, outValues, 0, values.length);
-            return true;
-        }
-
-        private long[] getDeviceStats(int[] deviceStates) {
-            String key = statesToString(getConfig().getDeviceStateConfig(), deviceStates);
-            long[] values = mDeviceStats.get(key);
-            return values == null ? new long[mDescriptor.statsArrayLength] : values;
-        }
-
-        void setDeviceStats(int[] states, long[] values, double expectedPowerEstimate) {
-            setDeviceStats(states, values);
-            mExpectedDevicePower.put(statesToString(getConfig().getDeviceStateConfig(), states),
-                    expectedPowerEstimate);
-        }
-
-        @Override
-        void setDeviceStats(int[] states, long[] values) {
-            String key = statesToString(getConfig().getDeviceStateConfig(), states);
-            mDeviceStats.put(key, Arrays.copyOf(values, mDescriptor.statsArrayLength));
-        }
-
-        @Override
-        boolean getUidStats(long[] outValues, int uid, int[] uidStates) {
-            long[] values = getUidStats(uid, uidStates);
-            assertThat(values).isNotNull();
-            System.arraycopy(values, 0, outValues, 0, values.length);
-            return true;
-        }
-
-        private long[] getUidStats(int uid, int[] uidStates) {
-            String key = uid + " " + statesToString(getConfig().getUidStateConfig(), uidStates);
-            long[] values = mUidStats.get(key);
-            return values == null ? new long[mDescriptor.uidStatsArrayLength] : values;
-        }
-
-        void setUidStats(int uid, int[] states, long[] values, double expectedPowerEstimate) {
-            setUidStats(uid, states, values);
-            mExpectedUidPower.put(
-                    uid + " " + statesToString(getConfig().getUidStateConfig(), states),
-                    expectedPowerEstimate);
-        }
-
-        @Override
-        void setUidStats(int uid, int[] states, long[] values) {
-            mUids.add(uid);
-            String key = uid + " " + statesToString(getConfig().getUidStateConfig(), states);
-            mUidStats.put(key, Arrays.copyOf(values, mDescriptor.uidStatsArrayLength));
-        }
-
-        @Override
-        void collectUids(Collection<Integer> uids) {
-            uids.addAll(mUids);
-        }
-
-        void verifyPowerEstimates() {
-            StringBuilder mismatches = new StringBuilder();
-            for (Map.Entry<String, Double> entry : mExpectedDevicePower.entrySet()) {
-                String key = entry.getKey();
-                double expected = mExpectedDevicePower.get(key);
-                double actual = mStatsLayout.getDevicePowerEstimate(mDeviceStats.get(key));
-                if (Math.abs(expected - actual) > 0.005) {
-                    mismatches.append(key + " expected: " + expected + " actual: " + actual + "\n");
-                }
-            }
-            for (Map.Entry<String, Double> entry : mExpectedUidPower.entrySet()) {
-                String key = entry.getKey();
-                double expected = mExpectedUidPower.get(key);
-                double actual = mStatsLayout.getUidPowerEstimate(mUidStats.get(key));
-                if (Math.abs(expected - actual) > 0.005) {
-                    mismatches.append(key + " expected: " + expected + " actual: " + actual + "\n");
-                }
-            }
-            if (!mismatches.isEmpty()) {
-                fail("Unexpected power estimations:\n" + mismatches);
-            }
-        }
-
-        private String statesToString(MultiStateStats.States[] config, int[] states) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < states.length; i++) {
-                sb.append(config[i].getName()).append("=").append(states[i]).append(" ");
-            }
-            return sb.toString();
-        }
-    }
-}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
index 64d5414..d51828e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
@@ -23,79 +23,134 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
 
-import android.content.Context;
-import android.hardware.power.stats.EnergyConsumer;
-import android.hardware.power.stats.EnergyConsumerResult;
 import android.hardware.power.stats.EnergyConsumerType;
 import android.os.BatteryConsumer;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.power.PowerStatsInternal;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.frameworks.powerstatstests.R;
+import com.android.internal.os.Clock;
 import com.android.internal.os.CpuScalingPolicies;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParserException;
 
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
+import java.io.IOException;
+import java.util.function.IntSupplier;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class CpuPowerStatsCollectorTest {
+
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
     private static final int ISOLATED_UID = 99123;
     private static final int UID_1 = 42;
     private static final int UID_2 = 99;
-    private Context mContext;
     private final MockClock mMockClock = new MockClock();
     private final HandlerThread mHandlerThread = new HandlerThread("test");
+    private final PowerStatsUidResolver mUidResolver = new PowerStatsUidResolver();
     private Handler mHandler;
     private PowerStats mCollectedStats;
-    private PowerProfile mPowerProfile;
-    @Mock
-    private PowerStatsUidResolver mUidResolver;
+    private PowerProfile mPowerProfile = new PowerProfile();
     @Mock
     private CpuPowerStatsCollector.KernelCpuStatsReader mMockKernelCpuStatsReader;
     @Mock
-    private PowerStatsInternal mPowerStatsInternal;
+    private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
     private CpuScalingPolicies mCpuScalingPolicies;
 
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mContext = InstrumentationRegistry.getContext();
+    private class TestInjector implements CpuPowerStatsCollector.Injector {
+        private final int mDefaultCpuPowerBrackets;
+        private final int mDefaultCpuPowerBracketsPerEnergyConsumer;
 
+        TestInjector(int defaultCpuPowerBrackets, int defaultCpuPowerBracketsPerEnergyConsumer) {
+            mDefaultCpuPowerBrackets = defaultCpuPowerBrackets;
+            mDefaultCpuPowerBracketsPerEnergyConsumer = defaultCpuPowerBracketsPerEnergyConsumer;
+        }
+
+        @Override
+        public Handler getHandler() {
+            return mHandler;
+        }
+
+        @Override
+        public Clock getClock() {
+            return mMockClock;
+        }
+
+        @Override
+        public PowerStatsUidResolver getUidResolver() {
+            return mUidResolver;
+        }
+
+        @Override
+        public CpuScalingPolicies getCpuScalingPolicies() {
+            return mCpuScalingPolicies;
+        }
+
+        @Override
+        public PowerProfile getPowerProfile() {
+            return mPowerProfile;
+        }
+
+        @Override
+        public CpuPowerStatsCollector.KernelCpuStatsReader getKernelCpuStatsReader() {
+            return mMockKernelCpuStatsReader;
+        }
+
+        @Override
+        public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+            return mConsumedEnergyRetriever;
+        }
+
+        @Override
+        public IntSupplier getVoltageSupplier() {
+            return () -> 3500;
+        }
+
+        @Override
+        public int getDefaultCpuPowerBrackets() {
+            return mDefaultCpuPowerBrackets;
+        }
+
+        @Override
+        public int getDefaultCpuPowerBracketsPerEnergyConsumer() {
+            return mDefaultCpuPowerBracketsPerEnergyConsumer;
+        }
+    };
+
+    @Before
+    public void setup() throws XmlPullParserException, IOException {
+        MockitoAnnotations.initMocks(this);
         mHandlerThread.start();
         mHandler = mHandlerThread.getThreadHandler();
-        when(mMockKernelCpuStatsReader.nativeIsSupportedFeature()).thenReturn(true);
-        when(mUidResolver.mapUid(anyInt())).thenAnswer(invocation -> {
-            int uid = invocation.getArgument(0);
-            if (uid == ISOLATED_UID) {
-                return UID_2;
-            } else {
-                return uid;
-            }
-        });
+        when(mMockKernelCpuStatsReader.isSupportedFeature()).thenReturn(true);
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(anyInt())).thenReturn(new int[0]);
+        mUidResolver.noteIsolatedUidAdded(ISOLATED_UID, UID_2);
     }
 
     @Test
     public void powerBrackets_specifiedInPowerProfile() {
-        mPowerProfile = new PowerProfile(mContext);
-        mPowerProfile.forceInitForTesting(mContext, R.xml.power_profile_test_power_brackets);
+        mPowerProfile.initForTesting(
+                BatteryUsageStatsRule.resolveParser("power_profile_test_power_brackets"));
         mCpuScalingPolicies = new CpuScalingPolicies(
                 new SparseArray<>() {{
                     put(0, new int[]{0});
@@ -114,8 +169,7 @@
 
     @Test
     public void powerBrackets_default_noEnergyConsumers() {
-        mPowerProfile = new PowerProfile(mContext);
-        mPowerProfile.forceInitForTesting(mContext, R.xml.power_profile_test);
+        mPowerProfile.initForTesting(BatteryUsageStatsRule.resolveParser("power_profile_test"));
         mockCpuScalingPolicies(2);
 
         CpuPowerStatsCollector collector = createCollector(3, 0);
@@ -134,8 +188,7 @@
 
     @Test
     public void powerBrackets_moreBracketsThanStates() {
-        mPowerProfile = new PowerProfile(mContext);
-        mPowerProfile.forceInitForTesting(mContext, R.xml.power_profile_test);
+        mPowerProfile.initForTesting(BatteryUsageStatsRule.resolveParser("power_profile_test"));
         mockCpuScalingPolicies(2);
 
         CpuPowerStatsCollector collector = createCollector(8, 0);
@@ -146,8 +199,7 @@
 
     @Test
     public void powerBrackets_energyConsumers() throws Exception {
-        mPowerProfile = new PowerProfile(mContext);
-        mPowerProfile.forceInitForTesting(mContext, R.xml.power_profile_test);
+        mPowerProfile.initForTesting(BatteryUsageStatsRule.resolveParser("power_profile_test"));
         mockCpuScalingPolicies(2);
         mockEnergyConsumers();
 
@@ -159,8 +211,7 @@
 
     @Test
     public void powerStatsDescriptor() throws Exception {
-        mPowerProfile = new PowerProfile(mContext);
-        mPowerProfile.forceInitForTesting(mContext, R.xml.power_profile_test);
+        mPowerProfile.initForTesting(BatteryUsageStatsRule.resolveParser("power_profile_test"));
         mockCpuScalingPolicies(2);
         mockEnergyConsumers();
 
@@ -170,8 +221,8 @@
         assertThat(descriptor.name).isEqualTo("cpu");
         assertThat(descriptor.statsArrayLength).isEqualTo(13);
         assertThat(descriptor.uidStatsArrayLength).isEqualTo(5);
-        CpuPowerStatsCollector.CpuStatsArrayLayout layout =
-                new CpuPowerStatsCollector.CpuStatsArrayLayout();
+        CpuPowerStatsLayout layout =
+                new CpuPowerStatsLayout();
         layout.fromExtras(descriptor.extras);
 
         long[] deviceStats = new long[descriptor.statsArrayLength];
@@ -209,8 +260,7 @@
         mockEnergyConsumers();
 
         CpuPowerStatsCollector collector = createCollector(8, 0);
-        CpuPowerStatsCollector.CpuStatsArrayLayout layout =
-                new CpuPowerStatsCollector.CpuStatsArrayLayout();
+        CpuPowerStatsLayout layout = new CpuPowerStatsLayout();
         layout.fromExtras(collector.getPowerStatsDescriptor().extras);
 
         mockKernelCpuStats(new long[]{1111, 2222, 3333},
@@ -274,6 +324,45 @@
                 .isEqualTo(78);
     }
 
+    @Test
+    public void isolatedUidReuse() {
+        mockCpuScalingPolicies(1);
+        mockPowerProfile();
+        mockEnergyConsumers();
+
+        CpuPowerStatsCollector collector = createCollector(8, 0);
+        CpuPowerStatsLayout layout = new CpuPowerStatsLayout();
+        layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+
+        mockKernelCpuStats(new long[]{1111, 2222, 3333},
+                new SparseArray<>() {{
+                    put(UID_2, new long[]{100, 150});
+                    put(ISOLATED_UID, new long[]{10000, 20000});
+                }}, 0, 1234);
+
+        mMockClock.uptime = 1000;
+        collector.forceSchedule();
+        waitForIdle();
+
+        mUidResolver.noteIsolatedUidRemoved(ISOLATED_UID, UID_2);
+        mUidResolver.noteIsolatedUidAdded(ISOLATED_UID, UID_2);
+
+        mockKernelCpuStats(new long[]{5555, 4444, 3333},
+                new SparseArray<>() {{
+                    put(UID_2, new long[]{100, 150});
+                    put(ISOLATED_UID, new long[]{245, 528});
+                }}, 1234, 3421);
+
+        mMockClock.uptime = 2000;
+        collector.forceSchedule();
+        waitForIdle();
+
+        assertThat(layout.getUidTimeByPowerBracket(mCollectedStats.uidStats.get(UID_2), 0))
+                .isEqualTo(245);
+        assertThat(layout.getUidTimeByPowerBracket(mCollectedStats.uidStats.get(UID_2), 1))
+                .isEqualTo(528);
+    }
+
     private void mockCpuScalingPolicies(int clusterCount) {
         SparseArray<int[]> cpus = new SparseArray<>();
         SparseArray<int[]> freqs = new SparseArray<>();
@@ -296,10 +385,9 @@
 
     private CpuPowerStatsCollector createCollector(int defaultCpuPowerBrackets,
             int defaultCpuPowerBracketsPerEnergyConsumer) {
-        CpuPowerStatsCollector collector = new CpuPowerStatsCollector(mCpuScalingPolicies,
-                mPowerProfile, mHandler, mMockKernelCpuStatsReader, mUidResolver,
-                () -> mPowerStatsInternal, () -> 3500, 60_000, mMockClock,
-                defaultCpuPowerBrackets, defaultCpuPowerBracketsPerEnergyConsumer);
+        CpuPowerStatsCollector collector = new CpuPowerStatsCollector(
+                new TestInjector(defaultCpuPowerBrackets, defaultCpuPowerBracketsPerEnergyConsumer),
+                0);
         collector.addConsumer(stats -> mCollectedStats = stats);
         collector.setEnabled(true);
         return collector;
@@ -307,7 +395,7 @@
 
     private void mockKernelCpuStats(long[] deviceStats, SparseArray<long[]> uidToCpuStats,
             long expectedLastUpdateTimestampMs, long newLastUpdateTimestampMs) {
-        when(mMockKernelCpuStatsReader.nativeReadCpuStats(
+        when(mMockKernelCpuStatsReader.readCpuStats(
                 any(CpuPowerStatsCollector.KernelCpuStatsCallback.class),
                 any(int[].class), anyLong(), any(long[].class), any(long[].class)))
                 .thenAnswer(invocation -> {
@@ -335,63 +423,18 @@
                 });
     }
 
-    @SuppressWarnings("unchecked")
-    private void mockEnergyConsumers() throws Exception {
-        when(mPowerStatsInternal.getEnergyConsumerInfo())
-                .thenReturn(new EnergyConsumer[]{
-                        new EnergyConsumer() {{
-                            id = 1;
-                            type = EnergyConsumerType.CPU_CLUSTER;
-                            ordinal = 0;
-                            name = "CPU0";
-                        }},
-                        new EnergyConsumer() {{
-                            id = 2;
-                            type = EnergyConsumerType.CPU_CLUSTER;
-                            ordinal = 1;
-                            name = "CPU4";
-                        }},
-                        new EnergyConsumer() {{
-                            id = 3;
-                            type = EnergyConsumerType.BLUETOOTH;
-                            name = "BT";
-                        }},
-                });
-
-        CompletableFuture<EnergyConsumerResult[]> future1 = mock(CompletableFuture.class);
-        when(future1.get(anyLong(), any(TimeUnit.class)))
-                .thenReturn(new EnergyConsumerResult[]{
-                        new EnergyConsumerResult() {{
-                            id = 1;
-                            energyUWs = 1000;
-                        }},
-                        new EnergyConsumerResult() {{
-                            id = 2;
-                            energyUWs = 2000;
-                        }}
-                });
-
-        CompletableFuture<EnergyConsumerResult[]> future2 = mock(CompletableFuture.class);
-        when(future2.get(anyLong(), any(TimeUnit.class)))
-                .thenReturn(new EnergyConsumerResult[]{
-                        new EnergyConsumerResult() {{
-                            id = 1;
-                            energyUWs = 1500;
-                        }},
-                        new EnergyConsumerResult() {{
-                            id = 2;
-                            energyUWs = 2700;
-                        }}
-                });
-
-        when(mPowerStatsInternal.getEnergyConsumedAsync(eq(new int[]{1, 2})))
-                .thenReturn(future1)
-                .thenReturn(future2);
+    private void mockEnergyConsumers() {
+        reset(mConsumedEnergyRetriever);
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER))
+                .thenReturn(new int[]{1, 2});
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{1, 2})))
+                .thenReturn(new long[]{1000, 2000})
+                .thenReturn(new long[]{1500, 2700});
     }
 
     private static int[] getScalingStepToPowerBracketMap(CpuPowerStatsCollector collector) {
-        CpuPowerStatsCollector.CpuStatsArrayLayout layout =
-                new CpuPowerStatsCollector.CpuStatsArrayLayout();
+        CpuPowerStatsLayout layout =
+                new CpuPowerStatsLayout();
         layout.fromExtras(collector.getPowerStatsDescriptor().extras);
         return layout.getScalingStepToPowerBracketMap();
     }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java
index cbce7e8..70c40f5 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorValidationTest.java
@@ -28,6 +28,8 @@
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.DeviceConfig;
 
 import androidx.test.InstrumentationRegistry;
@@ -52,11 +54,15 @@
 
 @RunWith(AndroidJUnit4.class)
 @LargeTest
[email protected]
[email protected](reason = "Integration test")
 public class CpuPowerStatsCollectorValidationTest {
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Rule(order = 1)
+    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isOnRavenwood()
+            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
+            : DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private static final int WORK_DURATION_MS = 2000;
     private static final String TEST_PKG = "com.android.coretests.apps.bstatstestapp";
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java
new file mode 100644
index 0000000..6b5da81
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.power.stats;
+
+import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
+
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+import android.os.BatteryConsumer;
+import android.os.PersistableBundle;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.LongArray;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.PowerProfile;
+import com.android.internal.os.PowerStats;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CpuPowerStatsProcessorTest {
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    @Rule(order = 1)
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+            .setAveragePower(PowerProfile.POWER_CPU_ACTIVE, 720)
+            .setCpuScalingPolicy(0, new int[]{0, 1}, new int[]{100, 200})
+            .setCpuScalingPolicy(2, new int[]{2, 3}, new int[]{300})
+            .setAveragePowerForCpuScalingPolicy(0, 360)
+            .setAveragePowerForCpuScalingPolicy(2, 480)
+            .setAveragePowerForCpuScalingStep(0, 0, 300)
+            .setAveragePowerForCpuScalingStep(0, 1, 400)
+            .setAveragePowerForCpuScalingStep(2, 0, 500)
+            .setCpuPowerBracketCount(3)
+            .setCpuPowerBracket(0, 0, 0)
+            .setCpuPowerBracket(0, 1, 1)
+            .setCpuPowerBracket(2, 0, 2);
+
+    private AggregatedPowerStatsConfig.PowerComponent mConfig;
+    private CpuPowerStatsProcessor mProcessor;
+    private MockPowerComponentAggregatedPowerStats mStats;
+
+    @Before
+    public void setup() {
+        mConfig = new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
+                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE);
+
+        mProcessor = new CpuPowerStatsProcessor(
+                mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies());
+    }
+
+    @Test
+    public void powerProfileModel() {
+        mStats = new MockPowerComponentAggregatedPowerStats(mConfig, false);
+        mStats.setDeviceStats(
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON),
+                concat(
+                        values(3500, 4500, 3000),   // scaling steps
+                        values(2000, 1000),         // clusters
+                        values(5000)),              // uptime
+                3.113732);
+        mStats.setDeviceStats(
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON),
+                concat(
+                        values(6000, 6500, 4000),
+                        values(5000, 3000),
+                        values(7000)),
+                4.607245);
+        mStats.setDeviceStats(
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER),
+                concat(
+                        values(9000, 10000, 7000),
+                        values(8000, 6000),
+                        values(20000)),
+                7.331799);
+        mStats.setUidStats(24,
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
+                values(400, 1500, 2000),  1.206947);
+        mStats.setUidStats(42,
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
+                values(900, 1000, 1500), 1.016182);
+        mStats.setUidStats(42,
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_BACKGROUND),
+                values(600, 500, 300), 0.385042);
+        mStats.setUidStats(42,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED),
+                values(1500, 2000, 1000), 1.252578);
+
+        mProcessor.finish(mStats);
+
+        mStats.verifyPowerEstimates();
+    }
+
+    @Test
+    public void energyConsumerModel() {
+        mStats = new MockPowerComponentAggregatedPowerStats(mConfig, true);
+        mStats.setDeviceStats(
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON),
+                concat(
+                        values(3500, 4500, 3000),           // scaling steps
+                        values(2000, 1000),                 // clusters
+                        values(5000),                       // uptime
+                        values(5_000_000L, 6_000_000L)),    // energy, uC
+                3.055555);
+        mStats.setDeviceStats(
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON),
+                concat(
+                        values(6000, 6500, 4000),
+                        values(5000, 3000),
+                        values(7000),
+                        values(5_000_000L, 6_000_000L)),    // same as above
+                3.055555);                                  // same as above - WAI
+        mStats.setDeviceStats(
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER),
+                concat(
+                        values(9000, 10000, 7000),
+                        values(8000, 6000),
+                        values(20000),
+                        values(8_000_000L, 18_000_000L)),
+                7.222222);
+        mStats.setUidStats(24,
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
+                values(400, 1500, 2000),  1.449078);
+        mStats.setUidStats(42,
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND),
+                values(900, 1000, 1500), 1.161902);
+        mStats.setUidStats(42,
+                states(POWER_STATE_BATTERY, SCREEN_STATE_ON, PROCESS_STATE_BACKGROUND),
+                values(600, 500, 300), 0.355406);
+        mStats.setUidStats(42,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED),
+                values(1500, 2000, 1000), 0.80773);
+
+        mProcessor.finish(mStats);
+
+        mStats.verifyPowerEstimates();
+    }
+
+    private int[] states(int... states) {
+        return states;
+    }
+
+    private long[] values(long... values) {
+        return values;
+    }
+
+    private long[] concat(long[]... arrays) {
+        LongArray all = new LongArray();
+        for (long[] array : arrays) {
+            for (long value : array) {
+                all.add(value);
+            }
+        }
+        return all.toArray();
+    }
+
+    private static class MockPowerComponentAggregatedPowerStats extends
+            PowerComponentAggregatedPowerStats {
+        private final CpuPowerStatsLayout mStatsLayout;
+        private final PowerStats.Descriptor mDescriptor;
+        private HashMap<String, long[]> mDeviceStats = new HashMap<>();
+        private HashMap<String, long[]> mUidStats = new HashMap<>();
+        private HashSet<Integer> mUids = new HashSet<>();
+        private HashMap<String, Double> mExpectedDevicePower = new HashMap<>();
+        private HashMap<String, Double> mExpectedUidPower = new HashMap<>();
+
+        MockPowerComponentAggregatedPowerStats(AggregatedPowerStatsConfig.PowerComponent config,
+                boolean useEnergyConsumers) {
+            super(new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+            mStatsLayout = new CpuPowerStatsLayout();
+            mStatsLayout.addDeviceSectionCpuTimeByScalingStep(3);
+            mStatsLayout.addDeviceSectionCpuTimeByCluster(2);
+            mStatsLayout.addDeviceSectionUsageDuration();
+            if (useEnergyConsumers) {
+                mStatsLayout.addDeviceSectionEnergyConsumers(2);
+            }
+            mStatsLayout.addDeviceSectionPowerEstimate();
+            mStatsLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0, 1, 2});
+            mStatsLayout.addUidSectionPowerEstimate();
+
+            PersistableBundle extras = new PersistableBundle();
+            mStatsLayout.toExtras(extras);
+            mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
+                    mStatsLayout.getDeviceStatsArrayLength(), null, 0,
+                    mStatsLayout.getUidStatsArrayLength(), extras);
+        }
+
+        @Override
+        public PowerStats.Descriptor getPowerStatsDescriptor() {
+            return mDescriptor;
+        }
+
+        @Override
+        boolean getDeviceStats(long[] outValues, int[] deviceStates) {
+            long[] values = getDeviceStats(deviceStates);
+            System.arraycopy(values, 0, outValues, 0, values.length);
+            return true;
+        }
+
+        private long[] getDeviceStats(int[] deviceStates) {
+            String key = statesToString(getConfig().getDeviceStateConfig(), deviceStates);
+            long[] values = mDeviceStats.get(key);
+            return values == null ? new long[mDescriptor.statsArrayLength] : values;
+        }
+
+        void setDeviceStats(int[] states, long[] values, double expectedPowerEstimate) {
+            setDeviceStats(states, values);
+            mExpectedDevicePower.put(statesToString(getConfig().getDeviceStateConfig(), states),
+                    expectedPowerEstimate);
+        }
+
+        @Override
+        void setDeviceStats(int[] states, long[] values) {
+            String key = statesToString(getConfig().getDeviceStateConfig(), states);
+            mDeviceStats.put(key, Arrays.copyOf(values, mDescriptor.statsArrayLength));
+        }
+
+        @Override
+        boolean getUidStats(long[] outValues, int uid, int[] uidStates) {
+            long[] values = getUidStats(uid, uidStates);
+            assertThat(values).isNotNull();
+            System.arraycopy(values, 0, outValues, 0, values.length);
+            return true;
+        }
+
+        private long[] getUidStats(int uid, int[] uidStates) {
+            String key = uid + " " + statesToString(getConfig().getUidStateConfig(), uidStates);
+            long[] values = mUidStats.get(key);
+            return values == null ? new long[mDescriptor.uidStatsArrayLength] : values;
+        }
+
+        void setUidStats(int uid, int[] states, long[] values, double expectedPowerEstimate) {
+            setUidStats(uid, states, values);
+            mExpectedUidPower.put(
+                    uid + " " + statesToString(getConfig().getUidStateConfig(), states),
+                    expectedPowerEstimate);
+        }
+
+        @Override
+        void setUidStats(int uid, int[] states, long[] values) {
+            mUids.add(uid);
+            String key = uid + " " + statesToString(getConfig().getUidStateConfig(), states);
+            mUidStats.put(key, Arrays.copyOf(values, mDescriptor.uidStatsArrayLength));
+        }
+
+        @Override
+        void collectUids(Collection<Integer> uids) {
+            uids.addAll(mUids);
+        }
+
+        void verifyPowerEstimates() {
+            StringBuilder mismatches = new StringBuilder();
+            for (Map.Entry<String, Double> entry : mExpectedDevicePower.entrySet()) {
+                String key = entry.getKey();
+                double expected = mExpectedDevicePower.get(key);
+                double actual = mStatsLayout.getDevicePowerEstimate(mDeviceStats.get(key));
+                if (Math.abs(expected - actual) > 0.005) {
+                    mismatches.append(key + " expected: " + expected + " actual: " + actual + "\n");
+                }
+            }
+            for (Map.Entry<String, Double> entry : mExpectedUidPower.entrySet()) {
+                String key = entry.getKey();
+                double expected = mExpectedUidPower.get(key);
+                double actual = mStatsLayout.getUidPowerEstimate(mUidStats.get(key));
+                if (Math.abs(expected - actual) > 0.005) {
+                    mismatches.append(key + " expected: " + expected + " actual: " + actual + "\n");
+                }
+            }
+            if (!mismatches.isEmpty()) {
+                fail("Unexpected power estimations:\n" + mismatches);
+            }
+        }
+
+        private String statesToString(MultiStateStats.States[] config, int[] states) {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < states.length; i++) {
+                sb.append(config[i].getName()).append("=").append(states[i]).append(" ");
+            }
+            return sb.toString();
+        }
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
index e023866..f035465 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
@@ -16,16 +16,26 @@
 
 package com.android.server.power.stats;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.system.suspend.internal.WakeLockInfo;
 
 import androidx.test.filters.SmallTest;
 
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
 
 import java.nio.charset.Charset;
 
[email protected]
-public class KernelWakelockReaderTest extends TestCase {
[email protected](reason = "Kernel dependency")
+public class KernelWakelockReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     /**
      * Helper class that builds the mock Kernel module file /d/wakeup_sources.
      */
@@ -105,14 +115,14 @@
 
     private KernelWakelockReader mReader;
 
-    @Override
+    @Before
     public void setUp() throws Exception {
-        super.setUp();
         mReader = new KernelWakelockReader();
     }
 
 // ------------------------- Legacy Wakelock Stats Test ------------------------
     @SmallTest
+    @Test
     public void testParseEmptyFile() throws Exception {
         KernelWakelockStats staleStats = mReader.parseProcWakelocks(new byte[0], 0, true,
                 new KernelWakelockStats());
@@ -121,6 +131,7 @@
     }
 
     @SmallTest
+    @Test
     public void testOnlyHeader() throws Exception {
         byte[] buffer = new ProcFileBuilder().getBytes();
 
@@ -131,6 +142,7 @@
     }
 
     @SmallTest
+    @Test
     public void testOneWakelock() throws Exception {
         byte[] buffer = new ProcFileBuilder()
                 .addLine("Wakelock", 34, 123, 456) // Milliseconds
@@ -150,6 +162,7 @@
     }
 
     @SmallTest
+    @Test
     public void testTwoWakelocks() throws Exception {
         byte[] buffer = new ProcFileBuilder()
                 .addLine("Wakelock", 1, 10)
@@ -166,6 +179,7 @@
     }
 
     @SmallTest
+    @Test
     public void testDuplicateWakelocksAccumulate() throws Exception {
         byte[] buffer = new ProcFileBuilder()
                 .addLine("Wakelock", 1, 10) // Milliseconds
@@ -184,6 +198,7 @@
     }
 
     @SmallTest
+    @Test
     public void testWakelocksBecomeStale() throws Exception {
         KernelWakelockStats staleStats = new KernelWakelockStats();
 
@@ -209,6 +224,7 @@
 
 // -------------------- SystemSuspend Wakelock Stats Test -------------------
     @SmallTest
+    @Test
     public void testEmptyWakeLockInfoList() {
         KernelWakelockStats staleStats = mReader.updateWakelockStats(new WakeLockInfo[0],
                 new KernelWakelockStats());
@@ -217,6 +233,7 @@
     }
 
     @SmallTest
+    @Test
     public void testOneWakeLockInfo() {
         WakeLockInfo[] wlStats = new WakeLockInfo[1];
         wlStats[0] = createWakeLockInfo("WakeLock", 20, 1000, 500);   // Milliseconds
@@ -235,6 +252,7 @@
     }
 
     @SmallTest
+    @Test
     public void testTwoWakeLockInfos() {
         WakeLockInfo[] wlStats = new WakeLockInfo[2];
         wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); // Milliseconds
@@ -258,6 +276,7 @@
     }
 
     @SmallTest
+    @Test
     public void testWakeLockInfosBecomeStale() {
         WakeLockInfo[] wlStats = new WakeLockInfo[1];
         wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); // Milliseconds
@@ -288,6 +307,7 @@
 
 // -------------------- Aggregate  Wakelock Stats Tests --------------------
     @SmallTest
+    @Test
     public void testAggregateStatsEmpty() throws Exception {
         KernelWakelockStats staleStats = new KernelWakelockStats();
 
@@ -300,6 +320,7 @@
     }
 
     @SmallTest
+    @Test
     public void testAggregateStatsNoNativeWakelocks() throws Exception {
         KernelWakelockStats staleStats = new KernelWakelockStats();
 
@@ -320,6 +341,7 @@
     }
 
     @SmallTest
+    @Test
     public void testAggregateStatsNoKernelWakelocks() throws Exception {
         KernelWakelockStats staleStats = new KernelWakelockStats();
 
@@ -339,6 +361,7 @@
     }
 
     @SmallTest
+    @Test
     public void testAggregateStatsBothKernelAndNativeWakelocks() throws Exception {
         KernelWakelockStats staleStats = new KernelWakelockStats();
 
@@ -364,6 +387,7 @@
     }
 
     @SmallTest
+    @Test
     public void testAggregateStatsUpdate() throws Exception {
         KernelWakelockStats staleStats = new KernelWakelockStats();
 
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
index 888a168..9b810bc 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.annotation.Nullable;
 import android.app.usage.NetworkStatsManager;
 import android.net.NetworkCapabilities;
 import android.net.NetworkStats;
@@ -34,6 +35,7 @@
 import android.os.BatteryUsageStatsQuery;
 import android.os.Process;
 import android.os.UidBatteryConsumer;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.ActivityStatsTechSpecificInfo;
 import android.telephony.CellSignalStrength;
@@ -46,8 +48,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.frameworks.powerstatstests.R;
-
 import com.google.common.collect.Range;
 
 import org.junit.Rule;
@@ -56,23 +56,29 @@
 import org.mockito.Mock;
 
 import java.util.ArrayList;
+import java.util.List;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 @SuppressWarnings("GuardedBy")
 public class MobileRadioPowerCalculatorTest {
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
     private static final double PRECISION = 0.00001;
     private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
     private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 101;
     @Mock
     NetworkStatsManager mNetworkStatsManager;
 
-    @Rule
+    @Rule(order = 1)
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
 
     @Test
     public void testCounterBasedModel() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_modem_calculator)
+        mStatsRule.setTestPowerProfile("power_profile_test_modem_calculator")
                 .initMeasuredEnergyStatsLocked();
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
 
@@ -126,10 +132,10 @@
         stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
 
         // Note application network activity
-        NetworkStats networkStats = new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 2000, 30, 100))
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID2, 0, 0,
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 2000, 30, 100),
+                mockNetworkStatsEntry("cellular", APP_UID2, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500, 50, 300, 10, 111));
         mStatsRule.setNetworkStats(networkStats);
 
@@ -192,7 +198,7 @@
 
     @Test
     public void testCounterBasedModel_multipleDefinedRat() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_modem_calculator_multiactive)
+        mStatsRule.setTestPowerProfile("power_profile_test_modem_calculator_multiactive")
                 .initMeasuredEnergyStatsLocked();
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
 
@@ -246,10 +252,10 @@
         stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
 
         // Note application network activity
-        NetworkStats networkStats = new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 2000, 30, 100))
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID2, 0, 0,
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 2000, 30, 100),
+                mockNetworkStatsEntry("cellular", APP_UID2, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500, 50, 300, 10, 111));
         mStatsRule.setNetworkStats(networkStats);
 
@@ -349,7 +355,7 @@
 
     @Test
     public void testCounterBasedModel_legacyPowerProfile() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
                 .initMeasuredEnergyStatsLocked();
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
 
@@ -403,10 +409,10 @@
         stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
 
         // Note application network activity
-        NetworkStats networkStats = new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 2000, 30, 100))
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID2, 0, 0,
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 2000, 30, 100),
+                mockNetworkStatsEntry("cellular", APP_UID2, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500, 50, 300, 10, 111));
         mStatsRule.setNetworkStats(networkStats);
 
@@ -469,7 +475,7 @@
 
     @Test
     public void testTimerBasedModel_byProcessState() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
                 .initMeasuredEnergyStatsLocked();
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
         BatteryStatsImpl.Uid uid = stats.getUidStatsLocked(APP_UID);
@@ -521,8 +527,8 @@
         stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
 
         // Note application network activity
-        mStatsRule.setNetworkStats(new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+        mStatsRule.setNetworkStats(mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100)));
 
         stats.noteModemControllerActivity(null, POWER_DATA_UNAVAILABLE, 10000, 10000,
@@ -531,8 +537,8 @@
         uid.setProcessStateForTest(
                 BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 11000);
 
-        mStatsRule.setNetworkStats(new NetworkStats(12000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+        mStatsRule.setNetworkStats(mockNetworkStats(12000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 250, 2000, 80, 200)));
 
         stats.noteModemControllerActivity(null, POWER_DATA_UNAVAILABLE, 12000, 12000,
@@ -586,7 +592,7 @@
 
     @Test
     public void testMeasuredEnergyBasedModel_mobileRadioActiveTimeModel() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
                 .setPerUidModemModel(
                         BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME)
                 .initMeasuredEnergyStatsLocked();
@@ -619,8 +625,8 @@
         stats.notePhoneOnLocked(9800, 9800);
 
         // Note application network activity
-        NetworkStats networkStats = new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
         mStatsRule.setNetworkStats(networkStats);
 
@@ -662,11 +668,9 @@
                 .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
     }
 
-
-
     @Test
     public void testMeasuredEnergyBasedModel_modemActivityInfoRxTxModel() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_modem_calculator_multiactive)
+        mStatsRule.setTestPowerProfile("power_profile_test_modem_calculator_multiactive")
                 .setPerUidModemModel(
                         BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX)
                 .initMeasuredEnergyStatsLocked();
@@ -728,10 +732,10 @@
         stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
 
         // Note application network activity
-        NetworkStats networkStats = new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
-                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 300, 10, 100))
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID2, 0, 0,
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 300, 10, 100),
+                mockNetworkStatsEntry("cellular", APP_UID2, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500, 50, 2000, 30, 111));
         mStatsRule.setNetworkStats(networkStats);
 
@@ -850,7 +854,7 @@
 
     @Test
     public void testMeasuredEnergyBasedModel_modemActivityInfoRxTxModel_legacyPowerProfile() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
                 .setPerUidModemModel(
                         BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX)
                 .initMeasuredEnergyStatsLocked();
@@ -908,8 +912,8 @@
         stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
 
         // Note application network activity
-        NetworkStats networkStats = new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
         mStatsRule.setNetworkStats(networkStats);
 
@@ -957,7 +961,7 @@
 
     @Test
     public void testMeasuredEnergyBasedModel_byProcessState() {
-        mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
                 .initMeasuredEnergyStatsLocked();
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
         BatteryStatsImpl.Uid uid = stats.getUidStatsLocked(APP_UID);
@@ -988,8 +992,8 @@
                 new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
 
         // Note application network activity
-        mStatsRule.setNetworkStats(new NetworkStats(10000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+        mStatsRule.setNetworkStats(mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100)));
 
         stats.noteModemControllerActivity(null, 10_000_000, 10000, 10000, mNetworkStatsManager);
@@ -997,8 +1001,8 @@
         uid.setProcessStateForTest(
                 BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 11000);
 
-        mStatsRule.setNetworkStats(new NetworkStats(12000, 1)
-                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+        mStatsRule.setNetworkStats(mockNetworkStats(12000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
                         METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 250, 2000, 80, 200)));
 
         stats.noteModemControllerActivity(null, 15_000_000, 12000, 12000, mNetworkStatsManager);
@@ -1047,4 +1051,40 @@
         final ModemActivityInfo emptyMai = new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L);
         stats.noteModemControllerActivity(emptyMai, 0, 0, 0, mNetworkStatsManager);
     }
+
+    private NetworkStats mockNetworkStats(int elapsedTime, int initialSize,
+            NetworkStats.Entry... entries) {
+        NetworkStats stats;
+        if (RavenwoodRule.isOnRavenwood()) {
+            stats = mock(NetworkStats.class);
+            when(stats.iterator()).thenAnswer(inv -> List.of(entries).iterator());
+        } else {
+            stats = new NetworkStats(elapsedTime, initialSize);
+            for (NetworkStats.Entry entry : entries) {
+                stats = stats.addEntry(entry);
+            }
+        }
+        return stats;
+    }
+
+    private static NetworkStats.Entry mockNetworkStatsEntry(@Nullable String iface, int uid,
+            int set, int tag, int metered, int roaming, int defaultNetwork, long rxBytes,
+            long rxPackets, long txBytes, long txPackets, long operations) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+            when(entry.getUid()).thenReturn(uid);
+            when(entry.getMetered()).thenReturn(metered);
+            when(entry.getRoaming()).thenReturn(roaming);
+            when(entry.getDefaultNetwork()).thenReturn(defaultNetwork);
+            when(entry.getRxBytes()).thenReturn(rxBytes);
+            when(entry.getRxPackets()).thenReturn(rxPackets);
+            when(entry.getTxBytes()).thenReturn(txBytes);
+            when(entry.getTxPackets()).thenReturn(txPackets);
+            when(entry.getOperations()).thenReturn(operations);
+            return entry;
+        } else {
+            return new NetworkStats.Entry(iface, uid, set, tag, metered,
+                    roaming, defaultNetwork, rxBytes, rxPackets, txBytes, txPackets, operations);
+        }
+    }
 }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
new file mode 100644
index 0000000..f93c4da
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
@@ -0,0 +1,497 @@
+/*
+ * 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.power.stats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.os.BatteryConsumer;
+import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.OutcomeReceiver;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.ActivityStatsTechSpecificInfo;
+import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
+
+public class MobileRadioPowerStatsCollectorTest {
+    private static final int APP_UID1 = 42;
+    private static final int APP_UID2 = 24;
+    private static final int APP_UID3 = 44;
+    private static final int ISOLATED_UID = 99123;
+
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    @Rule(order = 1)
+    public final BatteryUsageStatsRule mStatsRule =
+            new BatteryUsageStatsRule().setPowerStatsThrottlePeriodMillis(
+                    BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, 10000);
+
+    private MockBatteryStatsImpl mBatteryStats;
+
+    private final MockClock mClock = mStatsRule.getMockClock();
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private TelephonyManager mTelephony;
+    @Mock
+    private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    @Mock
+    private Supplier<NetworkStats> mNetworkStatsSupplier;
+    @Mock
+    private PowerStatsUidResolver mPowerStatsUidResolver;
+    @Mock
+    private LongSupplier mCallDurationSupplier;
+    @Mock
+    private LongSupplier mScanDurationSupplier;
+
+    private final List<PowerStats> mRecordedPowerStats = new ArrayList<>();
+
+    private MobileRadioPowerStatsCollector.Injector mInjector =
+            new MobileRadioPowerStatsCollector.Injector() {
+        @Override
+        public Handler getHandler() {
+            return mStatsRule.getHandler();
+        }
+
+        @Override
+        public Clock getClock() {
+            return mStatsRule.getMockClock();
+        }
+
+        @Override
+        public PowerStatsUidResolver getUidResolver() {
+            return mPowerStatsUidResolver;
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManager;
+        }
+
+        @Override
+        public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+            return mConsumedEnergyRetriever;
+        }
+
+        @Override
+        public IntSupplier getVoltageSupplier() {
+            return () -> 3500;
+        }
+
+        @Override
+        public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
+            return mNetworkStatsSupplier;
+        }
+
+        @Override
+        public TelephonyManager getTelephonyManager() {
+            return mTelephony;
+        }
+
+        @Override
+        public LongSupplier getCallDurationSupplier() {
+            return mCallDurationSupplier;
+        }
+
+        @Override
+        public LongSupplier getPhoneSignalScanDurationSupplier() {
+            return mScanDurationSupplier;
+        }
+    };
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+        when(mPowerStatsUidResolver.mapUid(anyInt())).thenAnswer(invocation -> {
+            int uid = invocation.getArgument(0);
+            if (uid == ISOLATED_UID) {
+                return APP_UID2;
+            } else {
+                return uid;
+            }
+        });
+        mBatteryStats = mStatsRule.getBatteryStats();
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void triggering() throws Throwable {
+        PowerStatsCollector collector = mBatteryStats.getPowerStatsCollector(
+                BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
+        collector.addConsumer(mRecordedPowerStats::add);
+
+        mBatteryStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+                true);
+
+        mockModemActivityInfo(1000, 2000, 3000, 600, new int[]{100, 200, 300, 400, 500});
+
+        // This should trigger a sample collection
+        mBatteryStats.onSystemReady(mContext);
+
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(20000, 20000);
+        mBatteryStats.notePhoneOnLocked(mClock.realtime, mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(40000, 40000);
+        mBatteryStats.notePhoneOffLocked(mClock.realtime, mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(45000, 55000);
+        mBatteryStats.noteMobileRadioPowerStateLocked(
+                DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, APP_UID1, mClock.realtime,
+                mClock.uptime);
+        mStatsRule.setTime(50001, 50001);
+        // Elapsed time under the throttling threshold - shouldn't trigger stats collection
+        mBatteryStats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
+                0, APP_UID1, mClock.realtime, mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(50002, 50002);
+        mBatteryStats.noteMobileRadioPowerStateLocked(
+                DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, APP_UID1, mClock.realtime,
+                mClock.uptime);
+        mStatsRule.setTime(55000, 50000);
+        // Elapsed time under the throttling threshold - shouldn't trigger stats collection
+        mBatteryStats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
+                0, APP_UID1, mClock.realtime, mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).isEmpty();
+    }
+
+    @Test
+    public void collectStats() throws Throwable {
+        PowerStats powerStats = collectPowerStats(true);
+        assertThat(powerStats.durationMs).isEqualTo(100);
+
+        PowerStats.Descriptor descriptor = powerStats.descriptor;
+        MobileRadioPowerStatsLayout layout =
+                new MobileRadioPowerStatsLayout(descriptor);
+        assertThat(layout.getDeviceSleepTime(powerStats.stats)).isEqualTo(200);
+        assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
+        assertThat(layout.getDeviceCallTime(powerStats.stats)).isEqualTo(40000);
+        assertThat(layout.getDeviceScanTime(powerStats.stats)).isEqualTo(60000);
+        assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
+                .isEqualTo((64321 - 10000) * 1000 / 3500);
+
+        assertThat(powerStats.stateStats.size()).isEqualTo(2);
+        long[] state1 = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+                ServiceState.FREQUENCY_RANGE_MMWAVE
+        ));
+        assertThat(layout.getStateRxTime(state1)).isEqualTo(6000);
+        assertThat(layout.getStateTxTime(state1, 0)).isEqualTo(1000);
+        assertThat(layout.getStateTxTime(state1, 1)).isEqualTo(2000);
+        assertThat(layout.getStateTxTime(state1, 2)).isEqualTo(3000);
+        assertThat(layout.getStateTxTime(state1, 3)).isEqualTo(4000);
+        assertThat(layout.getStateTxTime(state1, 4)).isEqualTo(5000);
+
+        long[] state2 = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                ServiceState.FREQUENCY_RANGE_LOW
+        ));
+        assertThat(layout.getStateRxTime(state2)).isEqualTo(7000);
+        assertThat(layout.getStateTxTime(state2, 0)).isEqualTo(8000);
+        assertThat(layout.getStateTxTime(state2, 1)).isEqualTo(9000);
+        assertThat(layout.getStateTxTime(state2, 2)).isEqualTo(1000);
+        assertThat(layout.getStateTxTime(state2, 3)).isEqualTo(2000);
+        assertThat(layout.getStateTxTime(state2, 4)).isEqualTo(3000);
+
+        assertThat(powerStats.uidStats.size()).isEqualTo(2);
+        long[] actual1 = powerStats.uidStats.get(APP_UID1);
+        assertThat(layout.getUidRxBytes(actual1)).isEqualTo(1000);
+        assertThat(layout.getUidTxBytes(actual1)).isEqualTo(2000);
+        assertThat(layout.getUidRxPackets(actual1)).isEqualTo(100);
+        assertThat(layout.getUidTxPackets(actual1)).isEqualTo(200);
+
+        // Combines APP_UID2 and ISOLATED_UID
+        long[] actual2 = powerStats.uidStats.get(APP_UID2);
+        assertThat(layout.getUidRxBytes(actual2)).isEqualTo(6000);
+        assertThat(layout.getUidTxBytes(actual2)).isEqualTo(3000);
+        assertThat(layout.getUidRxPackets(actual2)).isEqualTo(60);
+        assertThat(layout.getUidTxPackets(actual2)).isEqualTo(30);
+
+        assertThat(powerStats.uidStats.get(ISOLATED_UID)).isNull();
+        assertThat(powerStats.uidStats.get(APP_UID3)).isNull();
+    }
+
+    @Test
+    public void collectStats_noPerNetworkTypeData() throws Throwable {
+        PowerStats powerStats = collectPowerStats(false);
+        assertThat(powerStats.durationMs).isEqualTo(100);
+
+        PowerStats.Descriptor descriptor = powerStats.descriptor;
+        MobileRadioPowerStatsLayout layout =
+                new MobileRadioPowerStatsLayout(descriptor);
+        assertThat(layout.getDeviceSleepTime(powerStats.stats)).isEqualTo(200);
+        assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
+        assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
+                .isEqualTo((64321 - 10000) * 1000 / 3500);
+
+        assertThat(powerStats.stateStats.size()).isEqualTo(1);
+        long[] stateStats = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+                AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN
+        ));
+        assertThat(layout.getStateRxTime(stateStats)).isEqualTo(6000);
+        assertThat(layout.getStateTxTime(stateStats, 0)).isEqualTo(1000);
+        assertThat(layout.getStateTxTime(stateStats, 1)).isEqualTo(2000);
+        assertThat(layout.getStateTxTime(stateStats, 2)).isEqualTo(3000);
+        assertThat(layout.getStateTxTime(stateStats, 3)).isEqualTo(4000);
+        assertThat(layout.getStateTxTime(stateStats, 4)).isEqualTo(5000);
+
+        assertThat(powerStats.uidStats.size()).isEqualTo(2);
+        long[] actual1 = powerStats.uidStats.get(APP_UID1);
+        assertThat(layout.getUidRxBytes(actual1)).isEqualTo(1000);
+        assertThat(layout.getUidTxBytes(actual1)).isEqualTo(2000);
+        assertThat(layout.getUidRxPackets(actual1)).isEqualTo(100);
+        assertThat(layout.getUidTxPackets(actual1)).isEqualTo(200);
+
+        // Combines APP_UID2 and ISOLATED_UID
+        long[] actual2 = powerStats.uidStats.get(APP_UID2);
+        assertThat(layout.getUidRxBytes(actual2)).isEqualTo(6000);
+        assertThat(layout.getUidTxBytes(actual2)).isEqualTo(3000);
+        assertThat(layout.getUidRxPackets(actual2)).isEqualTo(60);
+        assertThat(layout.getUidTxPackets(actual2)).isEqualTo(30);
+
+        assertThat(powerStats.uidStats.get(ISOLATED_UID)).isNull();
+        assertThat(powerStats.uidStats.get(APP_UID3)).isNull();
+    }
+
+    @Test
+    public void dump() throws Throwable {
+        PowerStats powerStats = collectPowerStats(true);
+        StringWriter sw = new StringWriter();
+        IndentingPrintWriter pw = new IndentingPrintWriter(sw);
+        powerStats.dump(pw);
+        pw.flush();
+        String dump = sw.toString();
+        assertThat(dump).contains("duration=100");
+        assertThat(dump).contains(
+                "stats=[200, 300, 60000, 40000, " + ((64321 - 10000) * 1000 / 3500) + ", 0, 0, 0]");
+        assertThat(dump).contains("state LTE: [7000, 8000, 9000, 1000, 2000, 3000]");
+        assertThat(dump).contains("state NR MMWAVE: [6000, 1000, 2000, 3000, 4000, 5000]");
+        assertThat(dump).contains("UID 24: [6000, 3000, 60, 30, 0]");
+        assertThat(dump).contains("UID 42: [1000, 2000, 100, 200, 0]");
+    }
+
+    private PowerStats collectPowerStats(boolean perNetworkTypeData) throws Throwable {
+        MobileRadioPowerStatsCollector collector = new MobileRadioPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(
+                EnergyConsumerType.MOBILE_RADIO)).thenReturn(new int[]{777});
+
+        if (perNetworkTypeData) {
+            mockModemActivityInfo(1000, 2000, 3000,
+                    AccessNetworkConstants.AccessNetworkType.NGRAN,
+                    ServiceState.FREQUENCY_RANGE_MMWAVE,
+                    600, new int[]{100, 200, 300, 400, 500},
+                    AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                    ServiceState.FREQUENCY_RANGE_LOW,
+                    700, new int[]{800, 900, 100, 200, 300});
+        } else {
+            mockModemActivityInfo(1000, 2000, 3000, 600, new int[]{100, 200, 300, 400, 500});
+        }
+        mockNetworkStats(1000,
+                4321, 321, 1234, 23,
+                4000, 40, 2000, 20);
+
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
+                .thenReturn(new long[]{10000});
+
+        when(mCallDurationSupplier.getAsLong()).thenReturn(10000L);
+        when(mScanDurationSupplier.getAsLong()).thenReturn(20000L);
+
+        collector.collectStats();
+
+        if (perNetworkTypeData) {
+            mockModemActivityInfo(1100, 2200, 3300,
+                    AccessNetworkConstants.AccessNetworkType.NGRAN,
+                    ServiceState.FREQUENCY_RANGE_MMWAVE,
+                    6600, new int[]{1100, 2200, 3300, 4400, 5500},
+                    AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                    ServiceState.FREQUENCY_RANGE_LOW,
+                    7700, new int[]{8800, 9900, 1100, 2200, 3300});
+        } else {
+            mockModemActivityInfo(1100, 2200, 3300, 6600, new int[]{1100, 2200, 3300, 4400, 5500});
+        }
+        mockNetworkStats(1100,
+                5321, 421, 3234, 223,
+                8000, 80, 4000, 40);
+
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
+                .thenReturn(new long[]{64321});
+        when(mCallDurationSupplier.getAsLong()).thenReturn(50000L);
+        when(mScanDurationSupplier.getAsLong()).thenReturn(80000L);
+
+        mStatsRule.setTime(20000, 20000);
+        return collector.collectStats();
+    }
+
+    private void mockModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
+            int networkType1, int freqRange1, int rxTimeMs1, @NonNull int[] txTimeMs1,
+            int networkType2, int freqRange2, int rxTimeMs2, @NonNull int[] txTimeMs2) {
+        ModemActivityInfo info = new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
+                new ActivityStatsTechSpecificInfo[]{
+                        new ActivityStatsTechSpecificInfo(networkType1, freqRange1, txTimeMs1,
+                                rxTimeMs1),
+                        new ActivityStatsTechSpecificInfo(networkType2, freqRange2, txTimeMs2,
+                                rxTimeMs2)});
+        doAnswer(invocation -> {
+            OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
+                    receiver = invocation.getArgument(1);
+            receiver.onResult(info);
+            return null;
+        }).when(mTelephony).requestModemActivityInfo(any(), any());
+    }
+
+    private void mockModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
+            int rxTimeMs, @NonNull int[] txTimeMs) {
+        ModemActivityInfo info = new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs, txTimeMs,
+                rxTimeMs);
+        doAnswer(invocation -> {
+            OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
+                    receiver = invocation.getArgument(1);
+            receiver.onResult(info);
+            return null;
+        }).when(mTelephony).requestModemActivityInfo(any(), any());
+    }
+
+    private void mockNetworkStats(long elapsedRealtime,
+            long rxBytes1, long rxPackets1, long txBytes1, long txPackets1,
+            long rxBytes2, long rxPackets2, long txBytes2, long txPackets2) {
+        NetworkStats stats;
+        if (RavenwoodRule.isOnRavenwood()) {
+            stats = mock(NetworkStats.class);
+            List<NetworkStats.Entry> entries = List.of(
+                    mockNetworkStatsEntry(APP_UID1, rxBytes1, rxPackets1, txBytes1, txPackets1),
+                    mockNetworkStatsEntry(APP_UID2, rxBytes2, rxPackets2, txBytes2, txPackets2),
+                    mockNetworkStatsEntry(ISOLATED_UID, rxBytes2 / 2, rxPackets2 / 2, txBytes2 / 2,
+                            txPackets2 / 2),
+                    mockNetworkStatsEntry(APP_UID3, 314, 281, 314, 281));
+            when(stats.iterator()).thenAnswer(inv -> entries.iterator());
+        } else {
+            stats = new NetworkStats(elapsedRealtime, 1)
+                    .addEntry(new NetworkStats.Entry("mobile", APP_UID1, 0, 0,
+                            METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes1, rxPackets1,
+                            txBytes1, txPackets1, 100))
+                    .addEntry(new NetworkStats.Entry("mobile", APP_UID2, 0, 0,
+                            METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes2, rxPackets2,
+                            txBytes2, txPackets2, 111))
+                    .addEntry(new NetworkStats.Entry("mobile", ISOLATED_UID, 0, 0, METERED_NO,
+                            ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes2 / 2, rxPackets2 / 2,
+                            txBytes2 / 2, txPackets2 / 2, 111))
+                    .addEntry(new NetworkStats.Entry("mobile", APP_UID3, 0, 0, METERED_NO,
+                            ROAMING_NO, DEFAULT_NETWORK_NO, 314, 281, 314, 281, 111));
+        }
+        when(mNetworkStatsSupplier.get()).thenReturn(stats);
+    }
+
+    private static NetworkStats.Entry mockNetworkStatsEntry(int uid, long rxBytes, long rxPackets,
+            long txBytes, long txPackets) {
+        NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+        when(entry.getUid()).thenReturn(uid);
+        when(entry.getMetered()).thenReturn(METERED_NO);
+        when(entry.getRoaming()).thenReturn(ROAMING_NO);
+        when(entry.getDefaultNetwork()).thenReturn(DEFAULT_NETWORK_NO);
+        when(entry.getRxBytes()).thenReturn(rxBytes);
+        when(entry.getRxPackets()).thenReturn(rxPackets);
+        when(entry.getTxBytes()).thenReturn(txBytes);
+        when(entry.getTxPackets()).thenReturn(txPackets);
+        when(entry.getOperations()).thenReturn(100L);
+        return entry;
+    }
+
+    @Test
+    public void networkTypeConstants() throws Throwable {
+        Class<AccessNetworkConstants.AccessNetworkType> clazz =
+                AccessNetworkConstants.AccessNetworkType.class;
+        for (Field field : clazz.getDeclaredFields()) {
+            final int modifiers = field.getModifiers();
+            if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
+                    && field.getType().equals(int.class)) {
+                boolean found = false;
+                int value = field.getInt(null);
+                for (int i = 0; i < MobileRadioPowerStatsCollector.NETWORK_TYPES.length; i++) {
+                    if (MobileRadioPowerStatsCollector.NETWORK_TYPES[i] == value) {
+                        found = true;
+                        break;
+                    }
+                }
+                assertWithMessage("New network type, " + field.getName() + " not represented in "
+                        + MobileRadioPowerStatsCollector.class).that(found).isTrue();
+            }
+        }
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java
new file mode 100644
index 0000000..4ac7ad8
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
+
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+
+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.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.os.BatteryConsumer;
+import android.os.Handler;
+import android.os.OutcomeReceiver;
+import android.os.Process;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.telephony.ModemActivityInfo;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
+
+public class MobileRadioPowerStatsProcessorTest {
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    private static final double PRECISION = 0.00001;
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+    private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 101;
+    private static final int MOBILE_RADIO_ENERGY_CONSUMER_ID = 1;
+    private static final int VOLTAGE_MV = 3500;
+
+    @Rule(order = 1)
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
+    @Mock
+    private Context mContext;
+    @Mock
+    private PowerStatsUidResolver mPowerStatsUidResolver;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    @Mock
+    private Supplier<NetworkStats> mNetworkStatsSupplier;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private LongSupplier mCallDurationSupplier;
+    @Mock
+    private LongSupplier mScanDurationSupplier;
+
+    private final MobileRadioPowerStatsCollector.Injector mInjector =
+            new MobileRadioPowerStatsCollector.Injector() {
+                @Override
+                public Handler getHandler() {
+                    return mStatsRule.getHandler();
+                }
+
+                @Override
+                public Clock getClock() {
+                    return mStatsRule.getMockClock();
+                }
+
+                @Override
+                public PowerStatsUidResolver getUidResolver() {
+                    return mPowerStatsUidResolver;
+                }
+
+                @Override
+                public PackageManager getPackageManager() {
+                    return mPackageManager;
+                }
+
+                @Override
+                public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+                    return mConsumedEnergyRetriever;
+                }
+
+                @Override
+                public IntSupplier getVoltageSupplier() {
+                    return () -> VOLTAGE_MV;
+                }
+
+                @Override
+                public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
+                    return mNetworkStatsSupplier;
+                }
+
+                @Override
+                public TelephonyManager getTelephonyManager() {
+                    return mTelephonyManager;
+                }
+
+                @Override
+                public LongSupplier getCallDurationSupplier() {
+                    return mCallDurationSupplier;
+                }
+
+                @Override
+                public LongSupplier getPhoneSignalScanDurationSupplier() {
+                    return mScanDurationSupplier;
+                }
+            };
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+        when(mPowerStatsUidResolver.mapUid(anyInt()))
+                .thenAnswer(invocation -> invocation.getArgument(0));
+    }
+
+    @Test
+    public void powerProfileModel() {
+        // No power monitoring hardware
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.MOBILE_RADIO))
+                .thenReturn(new int[0]);
+
+        mStatsRule.setTestPowerProfile("power_profile_test_modem_calculator");
+
+        MobileRadioPowerStatsProcessor processor =
+                new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+        AggregatedPowerStatsConfig.PowerComponent config =
+                new AggregatedPowerStatsConfig.PowerComponent(
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                        .setProcessor(processor);
+
+        PowerComponentAggregatedPowerStats aggregatedStats =
+                new PowerComponentAggregatedPowerStats(
+                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+
+        aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
+        aggregatedStats.setUidState(APP_UID, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, 0);
+        aggregatedStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, 0);
+
+        MobileRadioPowerStatsCollector collector = new MobileRadioPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        // Initial empty ModemActivityInfo.
+        mockModemActivityInfo(new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L));
+
+        // Establish a baseline
+        aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+        // Turn the screen off after 2.5 seconds
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+        aggregatedStats.setUidState(APP_UID, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+        aggregatedStats.setUidState(APP_UID, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+                5000);
+
+        // Note application network activity
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+                mockNetworkStatsEntry("cellular", APP_UID2, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+
+        when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+        ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
+                new int[]{100, 200, 300, 400, 500}, 600);
+        mockModemActivityInfo(mai);
+
+        when(mCallDurationSupplier.getAsLong()).thenReturn(200L);
+        when(mScanDurationSupplier.getAsLong()).thenReturn(5555L);
+
+        mStatsRule.setTime(10_000, 10_000);
+
+        PowerStats powerStats = collector.collectStats();
+
+        aggregatedStats.addPowerStats(powerStats, 10_000);
+
+        processor.finish(aggregatedStats);
+
+        MobileRadioPowerStatsLayout statsLayout =
+                new MobileRadioPowerStatsLayout(
+                        aggregatedStats.getPowerStatsDescriptor());
+
+        //    720 mA * 100 ms  (level 0 TX drain rate * level 0 TX duration)
+        // + 1080 mA * 200 ms  (level 1 TX drain rate * level 1 TX duration)
+        // + 1440 mA * 300 ms  (level 2 TX drain rate * level 2 TX duration)
+        // + 1800 mA * 400 ms  (level 3 TX drain rate * level 3 TX duration)
+        // + 2160 mA * 500 ms  (level 4 TX drain rate * level 4 TX duration)
+        // + 1440 mA * 600 ms  (RX drain rate * RX duration)
+        // +  360 mA * 3000 ms (idle drain rate * idle duration)
+        // +   70 mA * 2000 ms (sleep drain rate * sleep duration)
+        // _________________
+        // =    4604000 mA-ms or 1.27888 mA-h
+        //   25% of 1.27888 = 0.319722
+        //   75% of 1.27888 = 0.959166
+        double totalPower = 0;
+        long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(0.319722);
+        totalPower += statsLayout.getDevicePowerEstimate(deviceStats);
+
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(0.959166);
+        totalPower += statsLayout.getDevicePowerEstimate(deviceStats);
+
+        assertThat(totalPower).isWithin(PRECISION).of(1.27888);
+
+        //    720 mA * 100 ms  (level 0 TX drain rate * level 0 TX duration)
+        // + 1080 mA * 200 ms  (level 1 TX drain rate * level 1 TX duration)
+        // + 1440 mA * 300 ms  (level 2 TX drain rate * level 2 TX duration)
+        // + 1800 mA * 400 ms  (level 3 TX drain rate * level 3 TX duration)
+        // + 2160 mA * 500 ms  (level 4 TX drain rate * level 4 TX duration)
+        // + 1440 mA * 600 ms  (RX drain rate * RX duration)
+        // _________________
+        // =    3384000 mA-ms or 0.94 mA-h
+        double uidPower1 = 0;
+        long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+        aggregatedStats.getUidStats(uidStats, APP_UID,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.17625);
+        uidPower1 += statsLayout.getUidPowerEstimate(uidStats);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.17625);
+        uidPower1 += statsLayout.getUidPowerEstimate(uidStats);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.3525);
+        uidPower1 += statsLayout.getUidPowerEstimate(uidStats);
+
+        double uidPower2 = 0;
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.05875);
+        uidPower2 += statsLayout.getUidPowerEstimate(uidStats);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.17625);
+        uidPower2 += statsLayout.getUidPowerEstimate(uidStats);
+
+        assertThat(uidPower1 + uidPower2)
+                .isWithin(PRECISION).of(0.94);
+
+        // 3/4 of total packets were sent by APP_UID so 75% of total
+        assertThat(uidPower1 / (uidPower1 + uidPower2))
+                .isWithin(PRECISION).of(0.75);
+    }
+
+    @Test
+    public void measuredEnergyModel() {
+        // PowerStats hardware is available
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.MOBILE_RADIO))
+                .thenReturn(new int[] {MOBILE_RADIO_ENERGY_CONSUMER_ID});
+
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
+                .initMeasuredEnergyStatsLocked();
+
+        MobileRadioPowerStatsProcessor processor =
+                new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+        AggregatedPowerStatsConfig.PowerComponent config =
+                new AggregatedPowerStatsConfig.PowerComponent(
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                        .setProcessor(processor);
+
+        PowerComponentAggregatedPowerStats aggregatedStats =
+                new PowerComponentAggregatedPowerStats(
+                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+
+        aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
+        aggregatedStats.setUidState(APP_UID, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, 0);
+        aggregatedStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, 0);
+
+        MobileRadioPowerStatsCollector collector = new MobileRadioPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        // Initial empty ModemActivityInfo.
+        mockModemActivityInfo(new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L));
+
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+                new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID}))
+                .thenReturn(new long[]{0});
+
+        // Establish a baseline
+        aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+        // Turn the screen off after 2.5 seconds
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+        aggregatedStats.setUidState(APP_UID, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+        aggregatedStats.setUidState(APP_UID, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+                5000);
+
+        // Note application network activity
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+                mockNetworkStatsEntry("cellular", APP_UID2, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+
+        when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+        ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
+                new int[]{100, 200, 300, 400, 500}, 600);
+        mockModemActivityInfo(mai);
+
+        mStatsRule.setTime(10_000, 10_000);
+
+        long energyUws = 10_000_000L * VOLTAGE_MV / 1000L;
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+                new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+
+        when(mCallDurationSupplier.getAsLong()).thenReturn(200L);
+        when(mScanDurationSupplier.getAsLong()).thenReturn(5555L);
+
+        PowerStats powerStats = collector.collectStats();
+
+        aggregatedStats.addPowerStats(powerStats, 10_000);
+
+        processor.finish(aggregatedStats);
+
+        MobileRadioPowerStatsLayout statsLayout =
+                new MobileRadioPowerStatsLayout(
+                        aggregatedStats.getPowerStatsDescriptor());
+
+        // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
+        double totalPower = 0;
+        long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(0.671837);
+        totalPower += statsLayout.getDevicePowerEstimate(deviceStats);
+        assertThat(statsLayout.getDeviceCallPowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(0.022494);
+        totalPower += statsLayout.getDeviceCallPowerEstimate(deviceStats);
+
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(2.01596);
+        totalPower += statsLayout.getDevicePowerEstimate(deviceStats);
+        assertThat(statsLayout.getDeviceCallPowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(0.067484);
+        totalPower += statsLayout.getDeviceCallPowerEstimate(deviceStats);
+
+        // These estimates are supposed to add up to the measured energy, 2.77778 mAh
+        assertThat(totalPower).isWithin(PRECISION).of(2.77778);
+
+        double uidPower1 = 0;
+        long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+        aggregatedStats.getUidStats(uidStats, APP_UID,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.198236);
+        uidPower1 += statsLayout.getUidPowerEstimate(uidStats);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.198236);
+        uidPower1 += statsLayout.getUidPowerEstimate(uidStats);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.396473);
+        uidPower1 += statsLayout.getUidPowerEstimate(uidStats);
+
+        double uidPower2 = 0;
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.066078);
+        uidPower2 += statsLayout.getUidPowerEstimate(uidStats);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(0.198236);
+        uidPower2 += statsLayout.getUidPowerEstimate(uidStats);
+
+        // Total power attributed to apps is significantly less than the grand total,
+        // because we only attribute TX/RX to apps but not maintaining a connection with the cell.
+        assertThat(uidPower1 + uidPower2)
+                .isWithin(PRECISION).of(1.057259);
+
+        // 3/4 of total packets were sent by APP_UID so 75% of total RX/TX power is attributed to it
+        assertThat(uidPower1 / (uidPower1 + uidPower2))
+                .isWithin(PRECISION).of(0.75);
+    }
+
+    private int[] states(int... states) {
+        return states;
+    }
+
+    private void mockModemActivityInfo(ModemActivityInfo emptyMai) {
+        doAnswer(invocation -> {
+            OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
+                    receiver = invocation.getArgument(1);
+            receiver.onResult(emptyMai);
+            return null;
+        }).when(mTelephonyManager).requestModemActivityInfo(any(), any());
+    }
+
+    private NetworkStats mockNetworkStats(int elapsedTime, int initialSize,
+            NetworkStats.Entry... entries) {
+        NetworkStats stats;
+        if (RavenwoodRule.isOnRavenwood()) {
+            stats = mock(NetworkStats.class);
+            when(stats.iterator()).thenAnswer(inv -> List.of(entries).iterator());
+        } else {
+            stats = new NetworkStats(elapsedTime, initialSize);
+            for (NetworkStats.Entry entry : entries) {
+                stats = stats.addEntry(entry);
+            }
+        }
+        return stats;
+    }
+
+    private static NetworkStats.Entry mockNetworkStatsEntry(@Nullable String iface, int uid,
+            int set, int tag, int metered, int roaming, int defaultNetwork, long rxBytes,
+            long rxPackets, long txBytes, long txPackets, long operations) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+            when(entry.getUid()).thenReturn(uid);
+            when(entry.getMetered()).thenReturn(metered);
+            when(entry.getRoaming()).thenReturn(roaming);
+            when(entry.getDefaultNetwork()).thenReturn(defaultNetwork);
+            when(entry.getRxBytes()).thenReturn(rxBytes);
+            when(entry.getRxPackets()).thenReturn(rxPackets);
+            when(entry.getTxBytes()).thenReturn(txBytes);
+            when(entry.getTxPackets()).thenReturn(txPackets);
+            when(entry.getOperations()).thenReturn(operations);
+            return entry;
+        } else {
+            return new NetworkStats.Entry(iface, uid, set, tag, metered,
+                    roaming, defaultNetwork, rxBytes, rxPackets, txBytes, txPackets, operations);
+        }
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 9f06913..1d48975 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -35,6 +35,7 @@
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 import com.android.internal.os.KernelSingleUidTimeReader;
+import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.power.EnergyConsumerStats;
 
@@ -52,6 +53,8 @@
     // The mNetworkStats will be used for both wifi and mobile categories
     private NetworkStats mNetworkStats;
     private DummyExternalStatsSync mExternalStatsSync = new DummyExternalStatsSync();
+    public static final BatteryStatsConfig DEFAULT_CONFIG =
+            new BatteryStatsConfig.Builder().build();
 
     MockBatteryStatsImpl() {
         this(new MockClock());
@@ -66,15 +69,18 @@
     }
 
     MockBatteryStatsImpl(Clock clock, File historyDirectory, Handler handler) {
-        this(clock, historyDirectory, handler, new PowerStatsUidResolver());
+        this(DEFAULT_CONFIG, clock, historyDirectory, handler, new PowerStatsUidResolver());
     }
 
-    MockBatteryStatsImpl(Clock clock, File historyDirectory, Handler handler,
-            PowerStatsUidResolver powerStatsUidResolver) {
-        super(clock, historyDirectory, handler, powerStatsUidResolver,
-                mock(FrameworkStatsLogger.class), mock(BatteryStatsHistory.TraceDelegate.class),
+    MockBatteryStatsImpl(BatteryStatsConfig config, Clock clock, File historyDirectory,
+            Handler handler, PowerStatsUidResolver powerStatsUidResolver) {
+        super(config, clock, new MonotonicClock(0, clock), historyDirectory, handler,
+                mock(PlatformIdleStateCallback.class), mock(EnergyStatsRetriever.class),
+                mock(UserInfoProvider.class), mock(PowerProfile.class),
+                new CpuScalingPolicies(new SparseArray<>(), new SparseArray<>()),
+                powerStatsUidResolver, mock(FrameworkStatsLogger.class),
+                mock(BatteryStatsHistory.TraceDelegate.class),
                 mock(BatteryStatsHistory.EventLogger.class));
-        initTimersAndCounters();
         setMaxHistoryBuffer(128 * 1024);
 
         setExternalStatsSyncLocked(mExternalStatsSync);
@@ -276,10 +282,6 @@
     public void writeSyncLocked() {
     }
 
-    public void setHandler(Handler handler) {
-        mHandler = handler;
-    }
-
     @Override
     protected void updateBatteryPropertiesLocked() {
     }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java
new file mode 100644
index 0000000..dadcf3f
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+
+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.doAnswer;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.os.BatteryConsumer;
+import android.os.Handler;
+import android.os.OutcomeReceiver;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.telephony.ModemActivityInfo;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.os.Clock;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
+
+public class PhoneCallPowerStatsProcessorTest {
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    private static final double PRECISION = 0.00001;
+    private static final int VOLTAGE_MV = 3500;
+
+    @Rule(order = 1)
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
+    @Mock
+    private Context mContext;
+    @Mock
+    private PowerStatsUidResolver mPowerStatsUidResolver;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    @Mock
+    private Supplier<NetworkStats> mNetworkStatsSupplier;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private LongSupplier mCallDurationSupplier;
+    @Mock
+    private LongSupplier mScanDurationSupplier;
+
+    private final MobileRadioPowerStatsCollector.Injector mInjector =
+            new MobileRadioPowerStatsCollector.Injector() {
+                @Override
+                public Handler getHandler() {
+                    return mStatsRule.getHandler();
+                }
+
+                @Override
+                public Clock getClock() {
+                    return mStatsRule.getMockClock();
+                }
+
+                @Override
+                public PowerStatsUidResolver getUidResolver() {
+                    return mPowerStatsUidResolver;
+                }
+
+                @Override
+                public PackageManager getPackageManager() {
+                    return mPackageManager;
+                }
+
+                @Override
+                public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+                    return mConsumedEnergyRetriever;
+                }
+
+                @Override
+                public IntSupplier getVoltageSupplier() {
+                    return () -> VOLTAGE_MV;
+                }
+
+                @Override
+                public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
+                    return mNetworkStatsSupplier;
+                }
+
+                @Override
+                public TelephonyManager getTelephonyManager() {
+                    return mTelephonyManager;
+                }
+
+                @Override
+                public LongSupplier getCallDurationSupplier() {
+                    return mCallDurationSupplier;
+                }
+
+                @Override
+                public LongSupplier getPhoneSignalScanDurationSupplier() {
+                    return mScanDurationSupplier;
+                }
+            };
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+        when(mPowerStatsUidResolver.mapUid(anyInt()))
+                .thenAnswer(invocation -> invocation.getArgument(0));
+
+        // No power monitoring hardware
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.MOBILE_RADIO))
+                .thenReturn(new int[0]);
+
+        mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem");
+    }
+
+    @Test
+    public void copyEstimatesFromMobileRadioPowerStats() {
+        MobileRadioPowerStatsProcessor mobileStatsProcessor =
+                new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+        PhoneCallPowerStatsProcessor phoneStatsProcessor =
+                new PhoneCallPowerStatsProcessor();
+
+        AggregatedPowerStatsConfig aggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
+        aggregatedPowerStatsConfig.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                .setProcessor(mobileStatsProcessor);
+        aggregatedPowerStatsConfig.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+                .setProcessor(phoneStatsProcessor);
+
+        AggregatedPowerStats aggregatedPowerStats =
+                new AggregatedPowerStats(aggregatedPowerStatsConfig);
+        PowerComponentAggregatedPowerStats mobileRadioStats =
+                aggregatedPowerStats.getPowerComponentStats(
+                        BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
+
+        aggregatedPowerStats.setDeviceState(STATE_POWER, POWER_STATE_OTHER, 0);
+        aggregatedPowerStats.setDeviceState(STATE_SCREEN, SCREEN_STATE_ON, 0);
+
+        MobileRadioPowerStatsCollector collector = new MobileRadioPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        // Initial empty ModemActivityInfo.
+        mockModemActivityInfo(new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L));
+
+        // Establish a baseline
+        aggregatedPowerStats.addPowerStats(collector.collectStats(), 0);
+
+        // Turn the screen off after 2.5 seconds
+        aggregatedPowerStats.setDeviceState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+
+        ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
+                new int[]{100, 200, 300, 400, 500}, 600);
+        mockModemActivityInfo(mai);
+
+        // A phone call was made
+        when(mCallDurationSupplier.getAsLong()).thenReturn(7000L);
+
+        mStatsRule.setTime(10_000, 10_000);
+
+        aggregatedPowerStats.addPowerStats(collector.collectStats(), 10_000);
+
+        mobileStatsProcessor.finish(mobileRadioStats);
+
+        PowerComponentAggregatedPowerStats stats =
+                aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_PHONE);
+        phoneStatsProcessor.finish(stats);
+
+        PowerStatsLayout statsLayout =
+                new PowerStatsLayout(stats.getPowerStatsDescriptor());
+
+        long[] deviceStats = new long[stats.getPowerStatsDescriptor().statsArrayLength];
+        stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(0.7);
+        stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(2.1);
+    }
+
+    private void mockModemActivityInfo(ModemActivityInfo emptyMai) {
+        doAnswer(invocation -> {
+            OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
+                    receiver = invocation.getArgument(1);
+            receiver.onResult(emptyMai);
+            return null;
+        }).when(mTelephonyManager).requestModemActivityInfo(any(), any());
+    }
+
+    private int[] states(int... states) {
+        return states;
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
index 2ea86a4..3929137 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
@@ -58,7 +58,7 @@
 
     @Before
     public void setup() throws ParseException {
-        mHistory = new BatteryStatsHistory(1024,
+        mHistory = new BatteryStatsHistory(null, null, 0, 1024,
                 mock(BatteryStatsHistory.HistoryStepDetailsCalculator.class), mClock,
                 mMonotonicClock, mock(BatteryStatsHistory.TraceDelegate.class), null);
 
@@ -76,9 +76,8 @@
 
     @Test
     public void stateUpdates() {
-        PowerStats.Descriptor descriptor =
-                new PowerStats.Descriptor(TEST_POWER_COMPONENT, "majorDrain", 1, 1,
-                        new PersistableBundle());
+        PowerStats.Descriptor descriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT,
+                "majorDrain", 1, null, 0, 1, new PersistableBundle());
         PowerStats powerStats = new PowerStats(descriptor);
 
         mClock.currentTime = 1222156800000L;    // An important date in world history
@@ -186,9 +185,8 @@
 
     @Test
     public void incompatiblePowerStats() {
-        PowerStats.Descriptor descriptor =
-                new PowerStats.Descriptor(TEST_POWER_COMPONENT, "majorDrain", 1, 1,
-                        new PersistableBundle());
+        PowerStats.Descriptor descriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT,
+                "majorDrain", 1, null, 0, 1, new PersistableBundle());
         PowerStats powerStats = new PowerStats(descriptor);
 
         mHistory.forceRecordAllHistory();
@@ -209,7 +207,7 @@
 
         advance(1000);
 
-        descriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT, "majorDrain", 1, 1,
+        descriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT, "majorDrain", 1, null, 0, 1,
                 PersistableBundle.forPair("something", "changed"));
         powerStats = new PowerStats(descriptor);
         powerStats.stats = new long[]{20000};
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
index 17a7d3e..89d6c1c 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
@@ -18,11 +18,22 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.hardware.power.stats.EnergyConsumer;
+import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyConsumerType;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.PersistableBundle;
+import android.platform.test.annotations.DisabledOnRavenwood;
 import android.platform.test.ravenwood.RavenwoodRule;
+import android.power.PowerStatsInternal;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -34,6 +45,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PowerStatsCollectorTest {
@@ -52,12 +66,12 @@
     public void setup() {
         mHandlerThread.start();
         mHandler = mHandlerThread.getThreadHandler();
-        mCollector = new PowerStatsCollector(mHandler,
-                60000,
+        mCollector = new PowerStatsCollector(mHandler, 60000, mock(PowerStatsUidResolver.class),
                 mMockClock) {
             @Override
             protected PowerStats collectStats() {
-                return new PowerStats(new PowerStats.Descriptor(0, 0, 0, new PersistableBundle()));
+                return new PowerStats(
+                        new PowerStats.Descriptor(0, 0, null, 0, 0, new PersistableBundle()));
             }
         };
         mCollector.addConsumer(stats -> mCollectedStats = stats);
@@ -92,4 +106,74 @@
         mHandler.post(done::open);
         done.block();
     }
+
+    @Test
+    @DisabledOnRavenwood
+    public void consumedEnergyRetriever() throws Exception {
+        PowerStatsInternal powerStatsInternal = mock(PowerStatsInternal.class);
+        mockEnergyConsumers(powerStatsInternal);
+
+        PowerStatsCollector.ConsumedEnergyRetrieverImpl retriever =
+                new PowerStatsCollector.ConsumedEnergyRetrieverImpl(powerStatsInternal);
+        int[] energyConsumerIds = retriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER);
+        assertThat(energyConsumerIds).isEqualTo(new int[]{1, 2});
+        long[] energy = retriever.getConsumedEnergyUws(energyConsumerIds);
+        assertThat(energy).isEqualTo(new long[]{1000, 2000});
+        energy = retriever.getConsumedEnergyUws(energyConsumerIds);
+        assertThat(energy).isEqualTo(new long[]{1500, 2700});
+    }
+
+    @SuppressWarnings("unchecked")
+    private void mockEnergyConsumers(PowerStatsInternal powerStatsInternal) throws Exception {
+        when(powerStatsInternal.getEnergyConsumerInfo())
+                .thenReturn(new EnergyConsumer[]{
+                        new EnergyConsumer() {{
+                            id = 1;
+                            type = EnergyConsumerType.CPU_CLUSTER;
+                            ordinal = 0;
+                            name = "CPU0";
+                        }},
+                        new EnergyConsumer() {{
+                            id = 2;
+                            type = EnergyConsumerType.CPU_CLUSTER;
+                            ordinal = 1;
+                            name = "CPU4";
+                        }},
+                        new EnergyConsumer() {{
+                            id = 3;
+                            type = EnergyConsumerType.BLUETOOTH;
+                            name = "BT";
+                        }},
+                });
+
+        CompletableFuture<EnergyConsumerResult[]> future1 = mock(CompletableFuture.class);
+        when(future1.get(anyLong(), any(TimeUnit.class)))
+                .thenReturn(new EnergyConsumerResult[]{
+                        new EnergyConsumerResult() {{
+                            id = 1;
+                            energyUWs = 1000;
+                        }},
+                        new EnergyConsumerResult() {{
+                            id = 2;
+                            energyUWs = 2000;
+                        }}
+                });
+
+        CompletableFuture<EnergyConsumerResult[]> future2 = mock(CompletableFuture.class);
+        when(future2.get(anyLong(), any(TimeUnit.class)))
+                .thenReturn(new EnergyConsumerResult[]{
+                        new EnergyConsumerResult() {{
+                            id = 1;
+                            energyUWs = 1500;
+                        }},
+                        new EnergyConsumerResult() {{
+                            id = 2;
+                            energyUWs = 2700;
+                        }}
+                });
+
+        when(powerStatsInternal.getEnergyConsumedAsync(eq(new int[]{1, 2})))
+                .thenReturn(future1)
+                .thenReturn(future2);
+    }
 }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
index 18d7b90..412fc88d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
@@ -77,7 +77,7 @@
     private PowerStatsStore mPowerStatsStore;
     private PowerStatsAggregator mPowerStatsAggregator;
     private BatteryStatsHistory mHistory;
-    private CpuPowerStatsCollector.CpuStatsArrayLayout mCpuStatsArrayLayout;
+    private CpuPowerStatsLayout mCpuStatsArrayLayout;
     private PowerStats.Descriptor mPowerStatsDescriptor;
 
     @Before
@@ -93,7 +93,7 @@
                         AggregatedPowerStatsConfig.STATE_SCREEN,
                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                 .setProcessor(
-                        new CpuAggregatedPowerStatsProcessor(mStatsRule.getPowerProfile(),
+                        new CpuPowerStatsProcessor(mStatsRule.getPowerProfile(),
                                 mStatsRule.getCpuScalingPolicies()));
 
         mPowerStatsStore = new PowerStatsStore(storeDirectory, new TestHandler(), config);
@@ -102,9 +102,10 @@
                 mMonotonicClock, null, null);
         mPowerStatsAggregator = new PowerStatsAggregator(config, mHistory);
 
-        mCpuStatsArrayLayout = new CpuPowerStatsCollector.CpuStatsArrayLayout();
+        mCpuStatsArrayLayout = new CpuPowerStatsLayout();
         mCpuStatsArrayLayout.addDeviceSectionCpuTimeByScalingStep(1);
         mCpuStatsArrayLayout.addDeviceSectionCpuTimeByCluster(1);
+        mCpuStatsArrayLayout.addDeviceSectionUsageDuration();
         mCpuStatsArrayLayout.addDeviceSectionPowerEstimate();
         mCpuStatsArrayLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0});
         mCpuStatsArrayLayout.addUidSectionPowerEstimate();
@@ -113,7 +114,7 @@
 
         mPowerStatsDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
                 mCpuStatsArrayLayout.getDeviceStatsArrayLength(),
-                mCpuStatsArrayLayout.getUidStatsArrayLength(), extras);
+                null, 0, mCpuStatsArrayLayout.getUidStatsArrayLength(), extras);
     }
 
     @Test
@@ -126,20 +127,20 @@
         BatteryUsageStats actual = builder.build();
         String message = "Actual BatteryUsageStats: " + actual;
 
-        assertDevicePowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 25.53);
-        assertAllAppsPowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 25.53);
+        assertDevicePowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 7.51016);
+        assertAllAppsPowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 7.51016);
 
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_ANY, 13.5);
+                BatteryConsumer.PROCESS_STATE_ANY, 3.97099);
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_FOREGROUND, 7.47);
+                BatteryConsumer.PROCESS_STATE_FOREGROUND, 2.198082);
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_BACKGROUND, 6.03);
+                BatteryConsumer.PROCESS_STATE_BACKGROUND, 1.772916);
 
         assertUidPowerEstimate(message, actual, APP_UID2, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_ANY, 12.03);
+                BatteryConsumer.PROCESS_STATE_ANY, 3.538999);
         assertUidPowerEstimate(message, actual, APP_UID2, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE, 12.03);
+                BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE, 3.538999);
 
         actual.close();
     }
@@ -154,20 +155,20 @@
         BatteryUsageStats actual = builder.build();
         String message = "Actual BatteryUsageStats: " + actual;
 
-        assertDevicePowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 15.4);
-        assertAllAppsPowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 15.4);
+        assertDevicePowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 4.526749);
+        assertAllAppsPowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 4.526749);
 
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_ANY, 4.06);
+                BatteryConsumer.PROCESS_STATE_ANY, 1.193332);
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_FOREGROUND, 1.35);
+                BatteryConsumer.PROCESS_STATE_FOREGROUND, 0.397749);
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_BACKGROUND, 2.70);
+                BatteryConsumer.PROCESS_STATE_BACKGROUND, 0.795583);
 
         assertUidPowerEstimate(message, actual, APP_UID2, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_ANY, 11.33);
+                BatteryConsumer.PROCESS_STATE_ANY, 3.333249);
         assertUidPowerEstimate(message, actual, APP_UID2, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE, 11.33);
+                BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE, 3.333249);
 
         actual.close();
     }
@@ -182,13 +183,13 @@
         BatteryUsageStats actual = builder.build();
         String message = "Actual BatteryUsageStats: " + actual;
 
-        assertDevicePowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 25.53);
-        assertAllAppsPowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 25.53);
+        assertDevicePowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 7.51016);
+        assertAllAppsPowerEstimate(message, actual, BatteryConsumer.POWER_COMPONENT_CPU, 7.51016);
 
         assertUidPowerEstimate(message, actual, APP_UID1, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_ANY, 13.5);
+                BatteryConsumer.PROCESS_STATE_ANY, 3.97099);
         assertUidPowerEstimate(message, actual, APP_UID2, BatteryConsumer.POWER_COMPONENT_CPU,
-                BatteryConsumer.PROCESS_STATE_ANY, 12.03);
+                BatteryConsumer.PROCESS_STATE_ANY, 3.538999);
         UidBatteryConsumer uidScope = actual.getUidBatteryConsumers().stream()
                 .filter(us -> us.getUid() == APP_UID1).findFirst().orElse(null);
         // There shouldn't be any per-procstate data
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java
new file mode 100644
index 0000000..02e446a
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.BatteryConsumer;
+
+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.List;
+import java.util.Objects;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PowerStatsProcessorTest {
+
+    @Test
+    public void createPowerEstimationPlan_allDeviceStatesPresentInUidStates() {
+        AggregatedPowerStatsConfig.PowerComponent config =
+                new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_ANY)
+                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE);
+
+        PowerStatsProcessor.PowerEstimationPlan plan =
+                new PowerStatsProcessor.PowerEstimationPlan(config);
+        assertThat(deviceStateEstimatesToStrings(plan))
+                .containsExactly("[0, 0]", "[0, 1]", "[1, 0]", "[1, 1]");
+        assertThat(combinedDeviceStatsToStrings(plan))
+                .containsExactly("[[0, 0]]", "[[0, 1]]", "[[1, 0]]", "[[1, 1]]");
+        assertThat(uidStateEstimatesToStrings(plan, config))
+                .containsExactly(
+                        "[[0, 0]]: [ps]: [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 0, 4]]",
+                        "[[0, 1]]: [ps]: [[0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 1, 4]]",
+                        "[[1, 0]]: [ps]: [[1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 0, 3], [1, 0, 4]]",
+                        "[[1, 1]]: [ps]: [[1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4]]");
+    }
+
+    @Test
+    public void createPowerEstimationPlan_combineDeviceStats() {
+        AggregatedPowerStatsConfig.PowerComponent config =
+                new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_ANY)
+                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                        .trackUidStates(STATE_POWER, STATE_PROCESS_STATE);
+
+        PowerStatsProcessor.PowerEstimationPlan plan =
+                new PowerStatsProcessor.PowerEstimationPlan(config);
+
+        assertThat(deviceStateEstimatesToStrings(plan))
+                .containsExactly("[0, 0]", "[0, 1]", "[1, 0]", "[1, 1]");
+        assertThat(combinedDeviceStatsToStrings(plan))
+                .containsExactly(
+                        "[[0, 0], [0, 1]]",
+                        "[[1, 0], [1, 1]]");
+        assertThat(uidStateEstimatesToStrings(plan, config))
+                .containsExactly(
+                        "[[0, 0], [0, 1]]: [ps]: [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]]",
+                        "[[1, 0], [1, 1]]: [ps]: [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4]]");
+    }
+
+    private static List<String> deviceStateEstimatesToStrings(
+            PowerStatsProcessor.PowerEstimationPlan plan) {
+        return plan.deviceStateEstimations.stream()
+                .map(dse -> dse.stateValues).map(Arrays::toString).toList();
+    }
+
+    private static List<String> combinedDeviceStatsToStrings(
+            PowerStatsProcessor.PowerEstimationPlan plan) {
+        return plan.combinedDeviceStateEstimations.stream()
+                .map(cds -> cds.deviceStateEstimations)
+                .map(dses -> dses.stream()
+                        .map(dse -> dse.stateValues).map(Arrays::toString).toList())
+                .map(Object::toString)
+                .toList();
+    }
+
+    private static List<String> uidStateEstimatesToStrings(
+            PowerStatsProcessor.PowerEstimationPlan plan,
+            AggregatedPowerStatsConfig.PowerComponent config) {
+        MultiStateStats.States[] uidStateConfig = config.getUidStateConfig();
+        return plan.uidStateEstimates.stream()
+                .map(use ->
+                        use.combinedDeviceStateEstimate.deviceStateEstimations.stream()
+                                .map(dse -> dse.stateValues).map(Arrays::toString).toList()
+                        + ": "
+                        + Arrays.stream(use.states)
+                                .filter(Objects::nonNull)
+                                .map(MultiStateStats.States::getName).toList()
+                        + ": "
+                        + use.proportionalEstimates.stream()
+                                .map(pe -> trackedStatesToString(uidStateConfig, pe.stateValues))
+                                .toList())
+                .toList();
+    }
+
+    private static Object trackedStatesToString(MultiStateStats.States[] states,
+            int[] stateValues) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        boolean first = true;
+        for (int i = 0; i < states.length; i++) {
+            if (!states[i].isTracked()) {
+                continue;
+            }
+
+            if (!first) {
+                sb.append(", ");
+            }
+            first = false;
+            sb.append(stateValues[i]);
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java
index 80cbe0d..d67d408 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java
@@ -18,11 +18,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.KernelSingleProcessCpuThreadReader;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -30,7 +33,10 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
[email protected](reason = "Kernel dependency")
 public class SystemServerCpuThreadReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     @Test
     public void testReadDelta() throws IOException {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
index 8e53d52..ef0b570 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
@@ -31,9 +31,10 @@
 import android.platform.test.annotations.RequiresFlagsDisabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.KernelCpuSpeedReader;
@@ -46,7 +47,6 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -55,17 +55,21 @@
 import java.util.Collection;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
 @SuppressWarnings("GuardedBy")
 public class SystemServicePowerCalculatorTest {
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Rule(order = 1)
+    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isOnRavenwood()
+            ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
+            : DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private static final double PRECISION = 0.000001;
     private static final int APP_UID1 = 100;
     private static final int APP_UID2 = 200;
 
-    @Rule
+    @Rule(order = 2)
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
             .setAveragePower(PowerProfile.POWER_CPU_ACTIVE, 720)
             .setCpuScalingPolicy(0, new int[]{0, 1}, new int[]{100, 200})
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
new file mode 100644
index 0000000..8b1d423
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
+
+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.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
+import android.os.BatteryStatsManager;
+import android.os.Handler;
+import android.os.WorkSource;
+import android.os.connectivity.WifiActivityEnergyInfo;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.IndentingPrintWriter;
+import android.util.SparseArray;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class WifiPowerStatsCollectorTest {
+    private static final int APP_UID1 = 42;
+    private static final int APP_UID2 = 24;
+    private static final int APP_UID3 = 44;
+    private static final int ISOLATED_UID = 99123;
+
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    @Rule(order = 1)
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+            .setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_WIFI, 1000);
+
+    private MockBatteryStatsImpl mBatteryStats;
+
+    private final MockClock mClock = mStatsRule.getMockClock();
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    @Mock
+    private Supplier<NetworkStats> mNetworkStatsSupplier;
+    @Mock
+    private PowerStatsUidResolver mPowerStatsUidResolver;
+
+    private NetworkStats mNetworkStats;
+    private List<NetworkStats.Entry> mNetworkStatsEntries;
+
+    private static class ScanTimes {
+        public long scanTimeMs;
+        public long batchScanTimeMs;
+    }
+
+    private final SparseArray<ScanTimes> mScanTimes = new SparseArray<>();
+    private long mWifiActiveDuration;
+
+    private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
+            new WifiPowerStatsCollector.WifiStatsRetriever() {
+        @Override
+        public void retrieveWifiScanTimes(Callback callback) {
+            for (int i = 0; i < mScanTimes.size(); i++) {
+                int uid = mScanTimes.keyAt(i);
+                ScanTimes scanTimes = mScanTimes.valueAt(i);
+                callback.onWifiScanTime(uid, scanTimes.scanTimeMs, scanTimes.batchScanTimeMs);
+            }
+        }
+
+        @Override
+        public long getWifiActiveDuration() {
+            return mWifiActiveDuration;
+        }
+    };
+
+    private final List<PowerStats> mRecordedPowerStats = new ArrayList<>();
+
+    private WifiPowerStatsCollector.Injector mInjector = new WifiPowerStatsCollector.Injector() {
+        @Override
+        public Handler getHandler() {
+            return mStatsRule.getHandler();
+        }
+
+        @Override
+        public Clock getClock() {
+            return mStatsRule.getMockClock();
+        }
+
+        @Override
+        public PowerStatsUidResolver getUidResolver() {
+            return mPowerStatsUidResolver;
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManager;
+        }
+
+        @Override
+        public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+            return mConsumedEnergyRetriever;
+        }
+
+        @Override
+        public IntSupplier getVoltageSupplier() {
+            return () -> 3500;
+        }
+
+        @Override
+        public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
+            return mNetworkStatsSupplier;
+        }
+
+        @Override
+        public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+            return mWifiStatsRetriever;
+        }
+
+        @Override
+        public WifiManager getWifiManager() {
+            return mWifiManager;
+        }
+    };
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
+        when(mPowerStatsUidResolver.mapUid(anyInt())).thenAnswer(invocation -> {
+            int uid = invocation.getArgument(0);
+            if (uid == ISOLATED_UID) {
+                return APP_UID2;
+            } else {
+                return uid;
+            }
+        });
+        mBatteryStats = mStatsRule.getBatteryStats();
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void triggering() throws Throwable {
+        PowerStatsCollector collector = mBatteryStats.getPowerStatsCollector(
+                BatteryConsumer.POWER_COMPONENT_WIFI);
+        collector.addConsumer(mRecordedPowerStats::add);
+
+        mBatteryStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_WIFI, true);
+
+        mockWifiActivityInfo(1000, 2000, 3000, 600, 100);
+
+        // This should trigger a sample collection to establish a baseline
+        mBatteryStats.onSystemReady(mContext);
+
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(20000, 20000);
+        mBatteryStats.noteWifiOnLocked(mClock.realtime, mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(40000, 40000);
+        mBatteryStats.noteWifiOffLocked(mClock.realtime, mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(50000, 50000);
+        mBatteryStats.noteWifiRunningLocked(new WorkSource(APP_UID1), mClock.realtime,
+                mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(60000, 60000);
+        mBatteryStats.noteWifiStoppedLocked(new WorkSource(APP_UID1), mClock.realtime,
+                mClock.uptime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+
+        mRecordedPowerStats.clear();
+        mStatsRule.setTime(70000, 70000);
+        mBatteryStats.noteWifiStateLocked(BatteryStatsManager.WIFI_STATE_ON_CONNECTED_STA,
+                "mywyfy", mClock.realtime);
+        mStatsRule.waitForBackgroundThread();
+        assertThat(mRecordedPowerStats).hasSize(1);
+    }
+
+    @Test
+    public void collectStats_powerReportingSupported() throws Throwable {
+        PowerStats powerStats = collectPowerStats(true);
+        assertThat(powerStats.durationMs).isEqualTo(7500);
+
+        PowerStats.Descriptor descriptor = powerStats.descriptor;
+        WifiPowerStatsLayout layout = new WifiPowerStatsLayout(descriptor);
+        assertThat(layout.isPowerReportingSupported()).isTrue();
+        assertThat(layout.getDeviceRxTime(powerStats.stats)).isEqualTo(6000);
+        assertThat(layout.getDeviceTxTime(powerStats.stats)).isEqualTo(1000);
+        assertThat(layout.getDeviceScanTime(powerStats.stats)).isEqualTo(200);
+        assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
+        assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
+                .isEqualTo((64321 - 10000) * 1000 / 3500);
+
+        verifyUidStats(powerStats);
+    }
+
+    @Test
+    public void collectStats_powerReportingUnsupported() {
+        PowerStats powerStats = collectPowerStats(false);
+        assertThat(powerStats.durationMs).isEqualTo(13200);
+
+        PowerStats.Descriptor descriptor = powerStats.descriptor;
+        WifiPowerStatsLayout layout = new WifiPowerStatsLayout(descriptor);
+        assertThat(layout.isPowerReportingSupported()).isFalse();
+        assertThat(layout.getDeviceActiveTime(powerStats.stats)).isEqualTo(7500);
+        assertThat(layout.getDeviceBasicScanTime(powerStats.stats)).isEqualTo(234 + 100 + 300);
+        assertThat(layout.getDeviceBatchedScanTime(powerStats.stats)).isEqualTo(345 + 200 + 400);
+        assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
+                .isEqualTo((64321 - 10000) * 1000 / 3500);
+
+        verifyUidStats(powerStats);
+    }
+
+    private void verifyUidStats(PowerStats powerStats) {
+        WifiPowerStatsLayout layout = new WifiPowerStatsLayout(powerStats.descriptor);
+        assertThat(powerStats.uidStats.size()).isEqualTo(2);
+        long[] actual1 = powerStats.uidStats.get(APP_UID1);
+        assertThat(layout.getUidRxBytes(actual1)).isEqualTo(1000);
+        assertThat(layout.getUidTxBytes(actual1)).isEqualTo(2000);
+        assertThat(layout.getUidRxPackets(actual1)).isEqualTo(100);
+        assertThat(layout.getUidTxPackets(actual1)).isEqualTo(200);
+        assertThat(layout.getUidScanTime(actual1)).isEqualTo(234);
+        assertThat(layout.getUidBatchedScanTime(actual1)).isEqualTo(345);
+
+        // Combines APP_UID2 and ISOLATED_UID
+        long[] actual2 = powerStats.uidStats.get(APP_UID2);
+        assertThat(layout.getUidRxBytes(actual2)).isEqualTo(6000);
+        assertThat(layout.getUidTxBytes(actual2)).isEqualTo(3000);
+        assertThat(layout.getUidRxPackets(actual2)).isEqualTo(60);
+        assertThat(layout.getUidTxPackets(actual2)).isEqualTo(30);
+        assertThat(layout.getUidScanTime(actual2)).isEqualTo(100 + 300);
+        assertThat(layout.getUidBatchedScanTime(actual2)).isEqualTo(200 + 400);
+
+        assertThat(powerStats.uidStats.get(ISOLATED_UID)).isNull();
+        assertThat(powerStats.uidStats.get(APP_UID3)).isNull();
+    }
+
+    @Test
+    public void dump() throws Throwable {
+        PowerStats powerStats = collectPowerStats(true);
+        StringWriter sw = new StringWriter();
+        IndentingPrintWriter pw = new IndentingPrintWriter(sw);
+        powerStats.dump(pw);
+        pw.flush();
+        String dump = sw.toString();
+        assertThat(dump).contains("duration=7500");
+        assertThat(dump).contains(
+                "stats=[6000, 1000, 300, 200, 634, 945, " + ((64321 - 10000) * 1000 / 3500)
+                        + ", 0, 0]");
+        assertThat(dump).contains("UID 24: [6000, 3000, 60, 30, 400, 600, 0]");
+        assertThat(dump).contains("UID 42: [1000, 2000, 100, 200, 234, 345, 0]");
+    }
+
+    private PowerStats collectPowerStats(boolean hasPowerReporting) {
+        when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(hasPowerReporting);
+
+        WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+                .thenReturn(new int[]{777});
+
+        if (hasPowerReporting) {
+            mockWifiActivityInfo(1000, 600, 100, 2000, 3000);
+        } else {
+            mWifiActiveDuration = 5700;
+        }
+        mockNetworkStats(1000);
+        mockNetworkStatsEntry(APP_UID1, 4321, 321, 1234, 23);
+        mockNetworkStatsEntry(APP_UID2, 4000, 40, 2000, 20);
+        mockNetworkStatsEntry(ISOLATED_UID, 2000, 20, 1000, 10);
+        mockNetworkStatsEntry(APP_UID3, 314, 281, 314, 281);
+        mockWifiScanTimes(APP_UID1, 1000, 2000);
+        mockWifiScanTimes(APP_UID2, 3000, 4000);
+        mockWifiScanTimes(ISOLATED_UID, 5000, 6000);
+
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
+                .thenReturn(new long[]{10000});
+
+        collector.collectStats();
+
+        if (hasPowerReporting) {
+            mockWifiActivityInfo(1100, 6600, 1100, 2200, 3300);
+        } else {
+            mWifiActiveDuration = 13200;
+        }
+        mockNetworkStats(1100);
+        mockNetworkStatsEntry(APP_UID1, 5321, 421, 3234, 223);
+        mockNetworkStatsEntry(APP_UID2, 8000, 80, 4000, 40);
+        mockNetworkStatsEntry(ISOLATED_UID, 4000, 40, 2000, 20);
+        mockNetworkStatsEntry(APP_UID3, 314, 281, 314, 281);    // Unchanged
+        mockWifiScanTimes(APP_UID1, 1234, 2345);
+        mockWifiScanTimes(APP_UID2, 3100, 4200);
+        mockWifiScanTimes(ISOLATED_UID, 5300, 6400);
+
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
+                .thenReturn(new long[]{64321});
+
+        mStatsRule.setTime(20000, 20000);
+        return collector.collectStats();
+    }
+
+    private void mockWifiActivityInfo(long timestamp, long rxTimeMs, long txTimeMs, int scanTimeMs,
+            int idleTimeMs) {
+        int stackState = 0;
+        WifiActivityEnergyInfo info = new WifiActivityEnergyInfo(timestamp, stackState, txTimeMs,
+                rxTimeMs, scanTimeMs, idleTimeMs);
+        doAnswer(invocation -> {
+            WifiManager.OnWifiActivityEnergyInfoListener listener = invocation.getArgument(1);
+            listener.onWifiActivityEnergyInfo(info);
+            return null;
+        }).when(mWifiManager).getWifiActivityEnergyInfoAsync(any(), any());
+    }
+
+    private void mockNetworkStats(long elapsedRealtime) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            mNetworkStats = mock(NetworkStats.class);
+            ArrayList<NetworkStats.Entry> networkStatsEntries = new ArrayList<>();
+            when(mNetworkStats.iterator()).thenAnswer(inv -> networkStatsEntries.iterator());
+            mNetworkStatsEntries = networkStatsEntries;
+        } else {
+            mNetworkStats = new NetworkStats(elapsedRealtime, 1);
+        }
+        when(mNetworkStatsSupplier.get()).thenReturn(mNetworkStats);
+    }
+
+    private void mockNetworkStatsEntry(int uid, long rxBytes, long rxPackets, long txBytes,
+            long txPackets) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+            when(entry.getUid()).thenReturn(uid);
+            when(entry.getMetered()).thenReturn(METERED_NO);
+            when(entry.getRoaming()).thenReturn(ROAMING_NO);
+            when(entry.getDefaultNetwork()).thenReturn(DEFAULT_NETWORK_NO);
+            when(entry.getRxBytes()).thenReturn(rxBytes);
+            when(entry.getRxPackets()).thenReturn(rxPackets);
+            when(entry.getTxBytes()).thenReturn(txBytes);
+            when(entry.getTxPackets()).thenReturn(txPackets);
+            when(entry.getOperations()).thenReturn(100L);
+            mNetworkStatsEntries.add(entry);
+        } else {
+            mNetworkStats = mNetworkStats
+                    .addEntry(new NetworkStats.Entry("wifi", uid, 0, 0,
+                            METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes, rxPackets,
+                            txBytes, txPackets, 100));
+            reset(mNetworkStatsSupplier);
+            when(mNetworkStatsSupplier.get()).thenReturn(mNetworkStats);
+        }
+    }
+
+    private void mockWifiScanTimes(int uid, long scanTimeMs, long batchScanTimeMs) {
+        ScanTimes scanTimes = new ScanTimes();
+        scanTimes.scanTimeMs = scanTimeMs;
+        scanTimes.batchScanTimeMs = batchScanTimeMs;
+        mScanTimes.put(uid, scanTimes);
+    }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
new file mode 100644
index 0000000..257a1a6
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
@@ -0,0 +1,592 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.power.stats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
+
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+
+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.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
+import android.os.Handler;
+import android.os.Process;
+import android.os.connectivity.WifiActivityEnergyInfo;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.SparseArray;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerProfile;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class WifiPowerStatsProcessorTest {
+    @Rule(order = 0)
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
+    private static final double PRECISION = 0.00001;
+    private static final int APP_UID1 = Process.FIRST_APPLICATION_UID + 42;
+    private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 101;
+    private static final int WIFI_ENERGY_CONSUMER_ID = 1;
+    private static final int VOLTAGE_MV = 3500;
+
+    @Rule(order = 1)
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+            .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX, 480.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX, 720.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 360.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_SCAN, 480.0)
+            .setAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, 720.0)
+            .initMeasuredEnergyStatsLocked();
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PowerStatsUidResolver mPowerStatsUidResolver;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+    @Mock
+    private Supplier<NetworkStats> mNetworkStatsSupplier;
+    @Mock
+    private WifiManager mWifiManager;
+
+    private static class ScanTimes {
+        public long scanTimeMs;
+        public long batchScanTimeMs;
+    }
+
+    private final SparseArray<ScanTimes> mScanTimes = new SparseArray<>();
+    private long mWifiActiveDuration;
+
+    private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
+            new WifiPowerStatsCollector.WifiStatsRetriever() {
+        @Override
+        public void retrieveWifiScanTimes(Callback callback) {
+            for (int i = 0; i < mScanTimes.size(); i++) {
+                int uid = mScanTimes.keyAt(i);
+                ScanTimes scanTimes = mScanTimes.valueAt(i);
+                callback.onWifiScanTime(uid, scanTimes.scanTimeMs, scanTimes.batchScanTimeMs);
+            }
+        }
+
+        @Override
+        public long getWifiActiveDuration() {
+            return mWifiActiveDuration;
+        }
+    };
+
+    private final WifiPowerStatsCollector.Injector mInjector =
+            new WifiPowerStatsCollector.Injector() {
+                @Override
+                public Handler getHandler() {
+                    return mStatsRule.getHandler();
+                }
+
+                @Override
+                public Clock getClock() {
+                    return mStatsRule.getMockClock();
+                }
+
+                @Override
+                public PowerStatsUidResolver getUidResolver() {
+                    return mPowerStatsUidResolver;
+                }
+
+                @Override
+                public PackageManager getPackageManager() {
+                    return mPackageManager;
+                }
+
+                @Override
+                public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+                    return mConsumedEnergyRetriever;
+                }
+
+                @Override
+                public IntSupplier getVoltageSupplier() {
+                    return () -> VOLTAGE_MV;
+                }
+
+                @Override
+                public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
+                    return mNetworkStatsSupplier;
+                }
+
+                @Override
+                public WifiManager getWifiManager() {
+                    return mWifiManager;
+                }
+
+                @Override
+                public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+                    return mWifiStatsRetriever;
+                }
+            };
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
+        when(mPowerStatsUidResolver.mapUid(anyInt()))
+                .thenAnswer(invocation -> invocation.getArgument(0));
+    }
+
+    @Test
+    public void powerProfileModel_powerController() {
+        when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
+
+        // No power monitoring hardware
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+                .thenReturn(new int[0]);
+
+        WifiPowerStatsProcessor processor =
+                new WifiPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+        PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats(processor);
+
+        WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        // Initial empty WifiActivityEnergyInfo.
+        mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(0L,
+                WifiActivityEnergyInfo.STACK_STATE_INVALID, 0L, 0L, 0L, 0L));
+
+        // Establish a baseline
+        aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+        // Turn the screen off after 2.5 seconds
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+                5000);
+
+        // Note application network activity
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("wifi", APP_UID1, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+                mockNetworkStatsEntry("wifi", APP_UID2, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+        when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+        mockWifiScanTimes(APP_UID1, 300, 400);
+        mockWifiScanTimes(APP_UID2, 100, 200);
+
+        mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(10000,
+                WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 2000, 3000, 100, 600));
+
+        mStatsRule.setTime(10_000, 10_000);
+
+        aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
+
+        processor.finish(aggregatedStats);
+
+        WifiPowerStatsLayout statsLayout =
+                new WifiPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
+
+        // RX power = 'rx-duration * PowerProfile[wifi.controller.rx]`
+        //        RX power = 3000 * 480 = 1440000 mA-ms = 0.4 mAh
+        // TX power = 'tx-duration * PowerProfile[wifi.controller.tx]`
+        //        TX power = 2000 * 720 = 1440000 mA-ms = 0.4 mAh
+        // Scan power = 'scan-duration * PowerProfile[wifi.scan]`
+        //        Scan power = 100 * 480 = 48000 mA-ms = 0.013333 mAh
+        // Idle power = 'idle-duration * PowerProfile[wifi.idle]`
+        //        Idle power = 600 * 360 = 216000 mA-ms = 0.06 mAh
+        // Total power = RX + TX + Scan + Idle = 0.873333
+        // Screen-on  - 25%
+        // Screen-off - 75%
+        double expectedPower = 0.873333;
+        long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(expectedPower * 0.25);
+
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(expectedPower * 0.75);
+
+        // UID1 =
+        //     (1500 / 2000) * 0.4        // rx
+        //     + (300 / 400) * 0.4        // tx
+        //     + (700 / 1000) * 0.013333  // scan (basic + batched)
+        //   = 0.609333 mAh
+        double expectedPower1 = 0.609333;
+        long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.5);
+
+        // UID2 =
+        //     (500 / 2000) * 0.4         // rx
+        //     + (100 / 400) * 0.4        // tx
+        //     + (300 / 1000) * 0.013333  // scan (basic + batched)
+        //   = 0.204 mAh
+        double expectedPower2 = 0.204;
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower2 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower2 * 0.75);
+    }
+
+    @Test
+    public void consumedEnergyModel_powerController() {
+        when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
+
+        // PowerStats hardware is available
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+                .thenReturn(new int[] {WIFI_ENERGY_CONSUMER_ID});
+
+        WifiPowerStatsProcessor processor =
+                new WifiPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+        PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats(processor);
+
+        WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        // Initial empty WifiActivityEnergyInfo.
+        mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(0L,
+                WifiActivityEnergyInfo.STACK_STATE_INVALID, 0L, 0L, 0L, 0L));
+
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+                new int[]{WIFI_ENERGY_CONSUMER_ID}))
+                .thenReturn(new long[]{0});
+
+        // Establish a baseline
+        aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+        // Turn the screen off after 2.5 seconds
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+                5000);
+
+        // Note application network activity
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("wifi", APP_UID1, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+                mockNetworkStatsEntry("wifi", APP_UID2, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+        when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+        mockWifiScanTimes(APP_UID1, 300, 400);
+        mockWifiScanTimes(APP_UID2, 100, 200);
+
+        mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(10000,
+                WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 2000, 3000, 100, 600));
+
+        mStatsRule.setTime(10_000, 10_000);
+
+        // 10 mAh represented as microWattSeconds
+        long energyUws = 10 * 3600 * VOLTAGE_MV;
+        when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+                new int[]{WIFI_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+
+        aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
+
+        processor.finish(aggregatedStats);
+
+        WifiPowerStatsLayout statsLayout =
+                new WifiPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
+
+        // All estimates are computed as in the #powerProfileModel_powerController test,
+        // except they are all scaled by the same ratio to ensure that the total estimated
+        // energy is equal to the measured energy
+        double expectedPower = 10;
+        long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(expectedPower * 0.25);
+
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(expectedPower * 0.75);
+
+        // UID1
+        //   0.609333           // power profile model estimate
+        //   0.873333           // power profile model estimate for total power
+        //   10                 // total consumed energy
+        //   = 0.609333 * (10 / 0.873333) = 6.9771
+        double expectedPower1 = 6.9771;
+        long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.5);
+
+        // UID2
+        //   0.204              // power profile model estimate
+        //   0.873333           // power profile model estimate for total power
+        //   10                 // total consumed energy
+        //   = 0.204 * (10 / 0.873333) = 2.33588
+        double expectedPower2 = 2.33588;
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower2 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower2 * 0.75);
+    }
+
+    @Test
+    public void powerProfileModel_noPowerController() {
+        when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(false);
+
+        // No power monitoring hardware
+        when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+                .thenReturn(new int[0]);
+
+        WifiPowerStatsProcessor processor =
+                new WifiPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+        PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats(processor);
+
+        WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+        collector.setEnabled(true);
+
+        // Establish a baseline
+        aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+        // Turn the screen off after 2.5 seconds
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+                5000);
+
+        // Note application network activity
+        NetworkStats networkStats = mockNetworkStats(10000, 1,
+                mockNetworkStatsEntry("wifi", APP_UID1, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+                mockNetworkStatsEntry("wifi", APP_UID2, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+        when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+        mScanTimes.clear();
+        mWifiActiveDuration = 8000;
+        mockWifiScanTimes(APP_UID1, 300, 400);
+        mockWifiScanTimes(APP_UID2, 100, 200);
+
+        mStatsRule.setTime(10_000, 10_000);
+
+        aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
+
+        processor.finish(aggregatedStats);
+
+        WifiPowerStatsLayout statsLayout =
+                new WifiPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
+
+        // Total active power = 'active-duration * PowerProfile[wifi.on]`
+        //        active = 8000 * 360 = 2880000 mA-ms = 0.8 mAh
+        // UID1 rxPackets + txPackets = 1800
+        // UID2 rxPackets + txPackets = 600
+        // Total rx+tx packets = 2400
+        // Total scan power = `scan-duration * PowerProfile[wifi.scan]`
+        //        scan = (100 + 300) * 480 = 192000 mA-ms = 0.05333 mAh
+        // Total batch scan power = `(200 + 400) * PowerProfile[wifi.batchedscan]`
+        //        bscan = (200 + 400) * 720 = 432000 mA-ms = 0.12 mAh
+        //
+        // Expected power = active + scan + bscan = 0.97333
+        double expectedPower = 0.97333;
+        long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(expectedPower * 0.25);
+
+        aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+        assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+                .isWithin(PRECISION).of(expectedPower * 0.75);
+
+        // UID1 =
+        //     (1800 / 2400) * 0.8      // active
+        //     + (300 / 400) * 0.05333  // scan
+        //     + (400 / 600) * 0.12     // batched scan
+        //   = 0.72 mAh
+        double expectedPower1 = 0.72;
+        long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID1,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower1 * 0.5);
+
+        // UID2 =
+        //     (600 / 2400) * 0.8       // active
+        //     + (100 / 400) * 0.05333  // scan
+        //     + (200 / 600) * 0.12     // batched scan
+        //   = 0.253333 mAh
+        double expectedPower2 = 0.25333;
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower2 * 0.25);
+
+        aggregatedStats.getUidStats(uidStats, APP_UID2,
+                states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+        assertThat(statsLayout.getUidPowerEstimate(uidStats))
+                .isWithin(PRECISION).of(expectedPower2 * 0.75);
+    }
+
+    private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
+            WifiPowerStatsProcessor processor) {
+        AggregatedPowerStatsConfig.PowerComponent config =
+                new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+                        .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+                        .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+                        .setProcessor(processor);
+
+        PowerComponentAggregatedPowerStats aggregatedStats =
+                new PowerComponentAggregatedPowerStats(
+                        new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+
+        aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
+        aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
+        aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, 0);
+        aggregatedStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, 0);
+
+        return aggregatedStats;
+    }
+
+    private int[] states(int... states) {
+        return states;
+    }
+
+    private void mockWifiActivityEnergyInfo(WifiActivityEnergyInfo waei) {
+        doAnswer(invocation -> {
+            WifiManager.OnWifiActivityEnergyInfoListener
+                    listener = invocation.getArgument(1);
+            listener.onWifiActivityEnergyInfo(waei);
+            return null;
+        }).when(mWifiManager).getWifiActivityEnergyInfoAsync(any(), any());
+    }
+
+    private NetworkStats mockNetworkStats(int elapsedTime, int initialSize,
+            NetworkStats.Entry... entries) {
+        NetworkStats stats;
+        if (RavenwoodRule.isOnRavenwood()) {
+            stats = mock(NetworkStats.class);
+            when(stats.iterator()).thenAnswer(inv -> List.of(entries).iterator());
+        } else {
+            stats = new NetworkStats(elapsedTime, initialSize);
+            for (NetworkStats.Entry entry : entries) {
+                stats = stats.addEntry(entry);
+            }
+        }
+        return stats;
+    }
+
+    private static NetworkStats.Entry mockNetworkStatsEntry(@Nullable String iface, int uid,
+            int set, int tag, int metered, int roaming, int defaultNetwork, long rxBytes,
+            long rxPackets, long txBytes, long txPackets, long operations) {
+        if (RavenwoodRule.isOnRavenwood()) {
+            NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+            when(entry.getUid()).thenReturn(uid);
+            when(entry.getMetered()).thenReturn(metered);
+            when(entry.getRoaming()).thenReturn(roaming);
+            when(entry.getDefaultNetwork()).thenReturn(defaultNetwork);
+            when(entry.getRxBytes()).thenReturn(rxBytes);
+            when(entry.getRxPackets()).thenReturn(rxPackets);
+            when(entry.getTxBytes()).thenReturn(txBytes);
+            when(entry.getTxPackets()).thenReturn(txPackets);
+            when(entry.getOperations()).thenReturn(operations);
+            return entry;
+        } else {
+            return new NetworkStats.Entry(iface, uid, set, tag, metered,
+                    roaming, defaultNetwork, rxBytes, rxPackets, txBytes, txPackets, operations);
+        }
+    }
+
+    private void mockWifiScanTimes(int uid, long scanTimeMs, long batchScanTimeMs) {
+        ScanTimes scanTimes = new ScanTimes();
+        scanTimes.scanTimeMs = scanTimeMs;
+        scanTimes.batchScanTimeMs = batchScanTimeMs;
+        mScanTimes.put(uid, scanTimes);
+    }
+}
diff --git a/services/tests/selinux/Android.bp b/services/tests/selinux/Android.bp
index f387238..12a7038 100644
--- a/services/tests/selinux/Android.bp
+++ b/services/tests/selinux/Android.bp
@@ -52,6 +52,7 @@
         "androidx.test.ext.junit",
         "androidx.test.ext.truth",
         "androidx.test.runner",
+        "compatibility-device-util-axt",
         "services.core",
     ],
     test_suites: [
diff --git a/services/tests/selinux/AndroidTest.xml b/services/tests/selinux/AndroidTest.xml
new file mode 100644
index 0000000..16d8e07
--- /dev/null
+++ b/services/tests/selinux/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs Selinux Frameworks Tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="SelinuxFrameworksTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="SelinuxFrameworksTests" />
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.frameworks.selinuxtests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsBuilderTest.java b/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsBuilderTest.java
index b36c9bd..e86108d 100644
--- a/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsBuilderTest.java
+++ b/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsBuilderTest.java
@@ -15,98 +15,144 @@
  */
 package com.android.server.selinux;
 
-import static com.android.server.selinux.SelinuxAuditLogBuilder.PATH_MATCHER;
-import static com.android.server.selinux.SelinuxAuditLogBuilder.SCONTEXT_MATCHER;
-import static com.android.server.selinux.SelinuxAuditLogBuilder.TCONTEXT_MATCHER;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 import static com.android.server.selinux.SelinuxAuditLogBuilder.toCategories;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.provider.DeviceConfig;
+
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.server.selinux.SelinuxAuditLogBuilder.SelinuxAuditLog;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.regex.Matcher;
+
 @RunWith(AndroidJUnit4.class)
 public class SelinuxAuditLogsBuilderTest {
 
-    private final SelinuxAuditLogBuilder mAuditLogBuilder = new SelinuxAuditLogBuilder();
+    private static final String TEST_DOMAIN = "test_domain";
+
+    private SelinuxAuditLogBuilder mAuditLogBuilder;
+    private Matcher mScontextMatcher;
+    private Matcher mTcontextMatcher;
+    private Matcher mPathMatcher;
+
+    @Before
+    public void setUp() {
+        runWithShellPermissionIdentity(
+                () ->
+                        DeviceConfig.setLocalOverride(
+                                DeviceConfig.NAMESPACE_ADSERVICES,
+                                SelinuxAuditLogBuilder.CONFIG_SELINUX_AUDIT_DOMAIN,
+                                TEST_DOMAIN));
+
+        mAuditLogBuilder = new SelinuxAuditLogBuilder();
+        mScontextMatcher = mAuditLogBuilder.mScontextMatcher;
+        mTcontextMatcher = mAuditLogBuilder.mTcontextMatcher;
+        mPathMatcher = mAuditLogBuilder.mPathMatcher;
+    }
+
+    @After
+    public void tearDown() {
+        runWithShellPermissionIdentity(() -> DeviceConfig.clearAllLocalOverrides());
+    }
 
     @Test
     public void testMatcher_scontext() {
-        assertThat(SCONTEXT_MATCHER.reset("u:r:sdk_sandbox_audit:s0").matches()).isTrue();
-        assertThat(SCONTEXT_MATCHER.group("stype")).isEqualTo("sdk_sandbox_audit");
-        assertThat(SCONTEXT_MATCHER.group("scategories")).isNull();
+        assertThat(mScontextMatcher.reset("u:r:" + TEST_DOMAIN + ":s0").matches()).isTrue();
+        assertThat(mScontextMatcher.group("stype")).isEqualTo(TEST_DOMAIN);
+        assertThat(mScontextMatcher.group("scategories")).isNull();
 
-        assertThat(SCONTEXT_MATCHER.reset("u:r:sdk_sandbox_audit:s0:c123,c456").matches()).isTrue();
-        assertThat(SCONTEXT_MATCHER.group("stype")).isEqualTo("sdk_sandbox_audit");
-        assertThat(toCategories(SCONTEXT_MATCHER.group("scategories")))
+        assertThat(mScontextMatcher.reset("u:r:" + TEST_DOMAIN + ":s0:c123,c456").matches())
+                .isTrue();
+        assertThat(mScontextMatcher.group("stype")).isEqualTo(TEST_DOMAIN);
+        assertThat(toCategories(mScontextMatcher.group("scategories")))
                 .isEqualTo(new int[] {123, 456});
 
-        assertThat(SCONTEXT_MATCHER.reset("u:r:not_sdk_sandbox:s0").matches()).isFalse();
-        assertThat(SCONTEXT_MATCHER.reset("u:object_r:sdk_sandbox_audit:s0").matches()).isFalse();
-        assertThat(SCONTEXT_MATCHER.reset("u:r:sdk_sandbox_audit:s0:p123").matches()).isFalse();
+        assertThat(mScontextMatcher.reset("u:r:wrong_domain:s0").matches()).isFalse();
+        assertThat(mScontextMatcher.reset("u:object_r:" + TEST_DOMAIN + ":s0").matches()).isFalse();
+        assertThat(mScontextMatcher.reset("u:r:" + TEST_DOMAIN + ":s0:p123").matches()).isFalse();
     }
 
     @Test
     public void testMatcher_tcontext() {
-        assertThat(TCONTEXT_MATCHER.reset("u:object_r:target_type:s0").matches()).isTrue();
-        assertThat(TCONTEXT_MATCHER.group("ttype")).isEqualTo("target_type");
-        assertThat(TCONTEXT_MATCHER.group("tcategories")).isNull();
+        assertThat(mTcontextMatcher.reset("u:object_r:target_type:s0").matches()).isTrue();
+        assertThat(mTcontextMatcher.group("ttype")).isEqualTo("target_type");
+        assertThat(mTcontextMatcher.group("tcategories")).isNull();
 
-        assertThat(TCONTEXT_MATCHER.reset("u:object_r:target_type2:s0:c666").matches()).isTrue();
-        assertThat(TCONTEXT_MATCHER.group("ttype")).isEqualTo("target_type2");
-        assertThat(toCategories(TCONTEXT_MATCHER.group("tcategories"))).isEqualTo(new int[] {666});
+        assertThat(mTcontextMatcher.reset("u:object_r:target_type2:s0:c666").matches()).isTrue();
+        assertThat(mTcontextMatcher.group("ttype")).isEqualTo("target_type2");
+        assertThat(toCategories(mTcontextMatcher.group("tcategories"))).isEqualTo(new int[] {666});
 
-        assertThat(TCONTEXT_MATCHER.reset("u:r:target_type:s0").matches()).isFalse();
-        assertThat(TCONTEXT_MATCHER.reset("u:r:sdk_sandbox_audit:s0:x456").matches()).isFalse();
+        assertThat(mTcontextMatcher.reset("u:r:target_type:s0").matches()).isFalse();
+        assertThat(mTcontextMatcher.reset("u:r:" + TEST_DOMAIN + ":s0:x456").matches()).isFalse();
     }
 
     @Test
     public void testMatcher_path() {
-        assertThat(PATH_MATCHER.reset("\"/data\"").matches()).isTrue();
-        assertThat(PATH_MATCHER.group("path")).isEqualTo("/data");
-        assertThat(PATH_MATCHER.reset("\"/data/local\"").matches()).isTrue();
-        assertThat(PATH_MATCHER.group("path")).isEqualTo("/data/local");
-        assertThat(PATH_MATCHER.reset("\"/data/local/tmp\"").matches()).isTrue();
-        assertThat(PATH_MATCHER.group("path")).isEqualTo("/data/local");
+        assertThat(mPathMatcher.reset("\"/data\"").matches()).isTrue();
+        assertThat(mPathMatcher.group("path")).isEqualTo("/data");
+        assertThat(mPathMatcher.reset("\"/data/local\"").matches()).isTrue();
+        assertThat(mPathMatcher.group("path")).isEqualTo("/data/local");
+        assertThat(mPathMatcher.reset("\"/data/local/tmp\"").matches()).isTrue();
+        assertThat(mPathMatcher.group("path")).isEqualTo("/data/local");
 
-        assertThat(PATH_MATCHER.reset("\"/data/local").matches()).isFalse();
-        assertThat(PATH_MATCHER.reset("\"_data_local\"").matches()).isFalse();
+        assertThat(mPathMatcher.reset("\"/data/local").matches()).isFalse();
+        assertThat(mPathMatcher.reset("\"_data_local\"").matches()).isFalse();
+    }
+
+    @Test
+    public void testMatcher_scontextDefaultConfig() {
+        runWithShellPermissionIdentity(
+                () ->
+                        DeviceConfig.clearLocalOverride(
+                                DeviceConfig.NAMESPACE_ADSERVICES,
+                                SelinuxAuditLogBuilder.CONFIG_SELINUX_AUDIT_DOMAIN));
+
+        Matcher scontexMatcher = new SelinuxAuditLogBuilder().mScontextMatcher;
+
+        assertThat(scontexMatcher.reset("u:r:" + TEST_DOMAIN + ":s0").matches()).isFalse();
+        assertThat(scontexMatcher.reset("u:r:" + TEST_DOMAIN + ":s0:c123,c456").matches())
+                .isFalse();
+        assertThat(scontexMatcher.reset("u:r:wrong_domain:s0").matches()).isFalse();
     }
 
     @Test
     public void testSelinuxAuditLogsBuilder_noOptionals() {
         mAuditLogBuilder.reset(
-                "granted { p } scontext=u:r:sdk_sandbox_audit:s0 tcontext=u:object_r:t:s0"
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 tcontext=u:object_r:t:s0"
                         + " tclass=c");
-        assertAuditLog(
-                mAuditLogBuilder.build(), true, new String[] {"p"}, "sdk_sandbox_audit", "t", "c");
+        assertAuditLog(mAuditLogBuilder.build(), true, new String[] {"p"}, TEST_DOMAIN, "t", "c");
 
         mAuditLogBuilder.reset(
                 "tclass=c2 granted { p2 } tcontext=u:object_r:t2:s0"
-                        + " scontext=u:r:sdk_sandbox_audit:s0");
+                        + " scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0");
         assertAuditLog(
-                mAuditLogBuilder.build(),
-                true,
-                new String[] {"p2"},
-                "sdk_sandbox_audit",
-                "t2",
-                "c2");
+                mAuditLogBuilder.build(), true, new String[] {"p2"}, TEST_DOMAIN, "t2", "c2");
     }
 
     @Test
     public void testSelinuxAuditLogsBuilder_withCategories() {
         mAuditLogBuilder.reset(
-                "granted { p } scontext=u:r:sdk_sandbox_audit:s0:c123"
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0:c123"
                         + " tcontext=u:object_r:t:s0:c456,c666 tclass=c");
         assertAuditLog(
                 mAuditLogBuilder.build(),
                 true,
                 new String[] {"p"},
-                "sdk_sandbox_audit",
+                TEST_DOMAIN,
                 new int[] {123},
                 "t",
                 new int[] {456, 666},
@@ -118,13 +164,15 @@
     @Test
     public void testSelinuxAuditLogsBuilder_withPath() {
         mAuditLogBuilder.reset(
-                "granted { p } scontext=u:r:sdk_sandbox_audit:s0 path=\"/very/long/path\""
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 path=\"/very/long/path\""
                         + " tcontext=u:object_r:t:s0 tclass=c");
         assertAuditLog(
                 mAuditLogBuilder.build(),
                 true,
                 new String[] {"p"},
-                "sdk_sandbox_audit",
+                TEST_DOMAIN,
                 null,
                 "t",
                 null,
@@ -136,13 +184,15 @@
     @Test
     public void testSelinuxAuditLogsBuilder_withPermissive() {
         mAuditLogBuilder.reset(
-                "granted { p } scontext=u:r:sdk_sandbox_audit:s0 permissive=0"
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 permissive=0"
                         + " tcontext=u:object_r:t:s0 tclass=c");
         assertAuditLog(
                 mAuditLogBuilder.build(),
                 true,
                 new String[] {"p"},
-                "sdk_sandbox_audit",
+                TEST_DOMAIN,
                 null,
                 "t",
                 null,
@@ -151,13 +201,15 @@
                 false);
 
         mAuditLogBuilder.reset(
-                "granted { p } scontext=u:r:sdk_sandbox_audit:s0 tcontext=u:object_r:t:s0 tclass=c"
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 tcontext=u:object_r:t:s0 tclass=c"
                         + " permissive=1");
         assertAuditLog(
                 mAuditLogBuilder.build(),
                 true,
                 new String[] {"p"},
-                "sdk_sandbox_audit",
+                TEST_DOMAIN,
                 null,
                 "t",
                 null,
@@ -166,6 +218,40 @@
                 true);
     }
 
+    @Test
+    public void testSelinuxAuditLogsBuilder_wrongConfig() {
+        String notARegexDomain = "not]a[regex";
+        runWithShellPermissionIdentity(
+                () ->
+                        DeviceConfig.setLocalOverride(
+                                DeviceConfig.NAMESPACE_ADSERVICES,
+                                SelinuxAuditLogBuilder.CONFIG_SELINUX_AUDIT_DOMAIN,
+                                notARegexDomain));
+        SelinuxAuditLogBuilder noOpBuilder = new SelinuxAuditLogBuilder();
+
+        noOpBuilder.reset(
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 tcontext=u:object_r:t:s0 tclass=c");
+        assertThat(noOpBuilder.build()).isNull();
+        noOpBuilder.reset(
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0:c123 tcontext=u:object_r:t:s0:c456,c666 tclass=c");
+        assertThat(noOpBuilder.build()).isNull();
+        noOpBuilder.reset(
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 path=\"/very/long/path\""
+                        + " tcontext=u:object_r:t:s0 tclass=c");
+        assertThat(noOpBuilder.build()).isNull();
+        noOpBuilder.reset(
+                "granted { p } scontext=u:r:"
+                        + TEST_DOMAIN
+                        + ":s0 permissive=0 tcontext=u:object_r:t:s0 tclass=c");
+        assertThat(noOpBuilder.build()).isNull();
+    }
+
     private void assertAuditLog(
             SelinuxAuditLog auditLog,
             boolean granted,
diff --git a/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsCollectorTest.java b/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsCollectorTest.java
index 4a70ad3..b6ccf5e 100644
--- a/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsCollectorTest.java
+++ b/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsCollectorTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.selinux;
 
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
@@ -27,6 +28,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 
+import android.provider.DeviceConfig;
 import android.util.EventLog;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -50,6 +52,7 @@
 
     // Fake tag to use for testing
     private static final int ANSWER_TAG = 42;
+    private static final String TEST_DOMAIN = "test_domain";
 
     private final MockClock mClock = new MockClock();
 
@@ -64,6 +67,14 @@
 
     @Before
     public void setUp() {
+        runWithShellPermissionIdentity(
+                () ->
+                        DeviceConfig.setLocalOverride(
+                                DeviceConfig.NAMESPACE_ADSERVICES,
+                                SelinuxAuditLogBuilder.CONFIG_SELINUX_AUDIT_DOMAIN,
+                                TEST_DOMAIN));
+
+        mSelinuxAutidLogsCollector.setStopRequested(false);
         // move the clock forward for the limiters.
         mClock.currentTimeMillis += Duration.ofHours(1).toMillis();
         // Ignore what was written in the event logs by previous tests.
@@ -74,13 +85,14 @@
 
     @After
     public void tearDown() {
+        runWithShellPermissionIdentity(() -> DeviceConfig.clearAllLocalOverrides());
         mMockitoSession.finishMocking();
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs() {
-        writeTestLog("granted", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm1", "sdk_sandbox_audit", "ttype1", "tclass1");
+    public void testWriteAuditLogs() {
+        writeTestLog("granted", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm1", TEST_DOMAIN, "ttype1", "tclass1");
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
 
@@ -91,7 +103,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 true,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -104,7 +116,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm1"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype1",
                                 null,
@@ -114,9 +126,9 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_multiplePerms() {
-        writeTestLog("denied", "perm1 perm2", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm3 perm4", "sdk_sandbox_audit", "ttype", "tclass");
+    public void testWriteAuditLogs_multiplePerms() {
+        writeTestLog("denied", "perm1 perm2", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm3 perm4", TEST_DOMAIN, "ttype", "tclass");
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
 
@@ -127,7 +139,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm1", "perm2"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -140,7 +152,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm3", "perm4"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -150,11 +162,11 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_withPaths() {
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass", "/good/path");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass", "/very/long/path");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass", "/short_path");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass", "not_a_path");
+    public void testWriteAuditLogs_withPaths() {
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/good/path");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/very/long/path");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/short_path");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "not_a_path");
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
 
@@ -165,7 +177,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -178,7 +190,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -191,7 +203,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -204,7 +216,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -214,23 +226,14 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_withCategories() {
-        writeTestLog(
-                "denied", "perm", "sdk_sandbox_audit", new int[] {123}, "ttype", null, "tclass");
+    public void testWriteAuditLogs_withCategories() {
+        writeTestLog("denied", "perm", TEST_DOMAIN, new int[] {123}, "ttype", null, "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, new int[] {123, 456}, "ttype", null, "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, null, "ttype", new int[] {666}, "tclass");
         writeTestLog(
                 "denied",
                 "perm",
-                "sdk_sandbox_audit",
-                new int[] {123, 456},
-                "ttype",
-                null,
-                "tclass");
-        writeTestLog(
-                "denied", "perm", "sdk_sandbox_audit", null, "ttype", new int[] {666}, "tclass");
-        writeTestLog(
-                "denied",
-                "perm",
-                "sdk_sandbox_audit",
+                TEST_DOMAIN,
                 new int[] {123, 456},
                 "ttype",
                 new int[] {666, 777},
@@ -245,7 +248,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 new int[] {123},
                                 "ttype",
                                 null,
@@ -258,7 +261,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 new int[] {123, 456},
                                 "ttype",
                                 null,
@@ -271,7 +274,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 new int[] {666},
@@ -284,7 +287,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 new int[] {123, 456},
                                 "ttype",
                                 new int[] {666, 777},
@@ -294,11 +297,11 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_withPathAndCategories() {
+    public void testWriteAuditLogs_withPathAndCategories() {
         writeTestLog(
                 "denied",
                 "perm",
-                "sdk_sandbox_audit",
+                TEST_DOMAIN,
                 new int[] {123},
                 "ttype",
                 new int[] {666},
@@ -314,7 +317,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 new int[] {123},
                                 "ttype",
                                 new int[] {666},
@@ -324,10 +327,10 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_permissive() {
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass", true);
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass", false);
+    public void testWriteAuditLogs_permissive() {
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", true);
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", false);
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
 
@@ -338,7 +341,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -352,7 +355,7 @@
                                 FrameworkStatsLog.SELINUX_AUDIT_LOG,
                                 false,
                                 new String[] {"perm"},
-                                "sdk_sandbox_audit",
+                                TEST_DOMAIN,
                                 null,
                                 "ttype",
                                 null,
@@ -362,7 +365,7 @@
     }
 
     @Test
-    public void testNotWriteAuditLogs_notSdkSandbox() {
+    public void testNotWriteAuditLogs_notTestDomain() {
         writeTestLog("denied", "perm", "stype", "ttype", "tclass");
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
@@ -385,15 +388,15 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_upToQuota() {
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
+    public void testWriteAuditLogs_upToQuota() {
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
         // These are not pushed.
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
 
@@ -415,14 +418,14 @@
     }
 
     @Test
-    public void testWriteSdkSandboxAuditLogs_resetQuota() {
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
+    public void testWriteAuditLogs_resetQuota() {
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
         assertThat(done).isTrue();
@@ -441,11 +444,11 @@
                                 anyBoolean()),
                 times(5));
 
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
         // move the clock forward to reset the quota limiter.
         mClock.currentTimeMillis += Duration.ofHours(1).toMillis();
         done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
@@ -468,16 +471,16 @@
 
     @Test
     public void testNotWriteAuditLogs_stopRequested() {
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
         // These are not pushed.
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
 
-        mSelinuxAutidLogsCollector.mStopRequested.set(true);
+        mSelinuxAutidLogsCollector.setStopRequested(true);
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
         assertThat(done).isFalse();
         verify(
@@ -495,7 +498,7 @@
                                 anyBoolean()),
                 never());
 
-        mSelinuxAutidLogsCollector.mStopRequested.set(false);
+        mSelinuxAutidLogsCollector.setStopRequested(false);
         done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
         assertThat(done).isTrue();
         verify(
@@ -516,8 +519,8 @@
 
     @Test
     public void testAuditLogs_resumeJobDoesNotExceedLimit() {
-        writeTestLog("denied", "perm", "sdk_sandbox_audit", "ttype", "tclass");
-        mSelinuxAutidLogsCollector.mStopRequested.set(true);
+        writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass");
+        mSelinuxAutidLogsCollector.setStopRequested(true);
 
         boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG);
 
diff --git a/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsJobTest.java b/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsJobTest.java
new file mode 100644
index 0000000..2aea8a0
--- /dev/null
+++ b/services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsJobTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.selinux;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+@RunWith(AndroidJUnit4.class)
+public class SelinuxAuditLogsJobTest {
+
+    private final JobService mJobService = mock(JobService.class);
+    private final SelinuxAuditLogsCollector mAuditLogsCollector =
+            mock(SelinuxAuditLogsCollector.class);
+    private final JobParameters mParams = createJobParameters(666);
+    private final SelinuxAuditLogsJob mAuditLogsJob = new SelinuxAuditLogsJob(mAuditLogsCollector);
+
+    @Before
+    public void setUp() {
+        mAuditLogsCollector.mStopRequested = new AtomicBoolean();
+    }
+
+    @Test
+    public void testFinishSuccessfully() {
+        when(mAuditLogsCollector.collect(anyInt())).thenReturn(true);
+
+        mAuditLogsJob.start(mJobService, mParams);
+
+        verify(mJobService).jobFinished(mParams, /* wantsReschedule= */ false);
+        assertThat(mAuditLogsJob.isRunning()).isFalse();
+    }
+
+    @Test
+    public void testInterrupt() {
+        when(mAuditLogsCollector.collect(anyInt())).thenReturn(false);
+
+        mAuditLogsJob.start(mJobService, mParams);
+
+        verify(mJobService, never()).jobFinished(any(), anyBoolean());
+        assertThat(mAuditLogsJob.isRunning()).isFalse();
+    }
+
+    @Test
+    public void testInterruptAndResume() {
+        when(mAuditLogsCollector.collect(anyInt())).thenReturn(false);
+        mAuditLogsJob.start(mJobService, mParams);
+        verify(mJobService, never()).jobFinished(any(), anyBoolean());
+
+        when(mAuditLogsCollector.collect(anyInt())).thenReturn(true);
+        mAuditLogsJob.start(mJobService, mParams);
+        verify(mJobService).jobFinished(mParams, /* wantsReschedule= */ false);
+        assertThat(mAuditLogsJob.isRunning()).isFalse();
+    }
+
+    @Test
+    public void testRequestStop() throws InterruptedException {
+        Semaphore isRunning = new Semaphore(0);
+        Semaphore stopRequested = new Semaphore(0);
+        AtomicReference<Throwable> uncaughtException = new AtomicReference<>();
+
+        // Set up a logs collector that runs in a worker thread until a stop is requested.
+        when(mAuditLogsCollector.collect(anyInt()))
+                .thenAnswer(
+                        invocation -> {
+                            assertThat(mAuditLogsCollector.mStopRequested.get()).isFalse();
+                            isRunning.release();
+                            stopRequested.acquire();
+                            assertThat(mAuditLogsCollector.mStopRequested.get()).isTrue();
+                            return true;
+                        });
+        Thread jobThread =
+                new Thread(
+                        () -> {
+                            mAuditLogsJob.start(mJobService, mParams);
+                        });
+        jobThread.setUncaughtExceptionHandler(
+                (thread, exception) -> uncaughtException.set(exception));
+        assertThat(mAuditLogsJob.isRunning()).isFalse();
+        jobThread.start();
+
+        // Wait until the worker thread is running.
+        isRunning.acquire();
+        assertThat(mAuditLogsJob.isRunning()).isTrue();
+
+        // Request for the worker thread to stop, and wait to verify.
+        mAuditLogsJob.requestStop();
+        stopRequested.release();
+        jobThread.join();
+        assertThat(uncaughtException.get()).isNull();
+        assertThat(mAuditLogsJob.isRunning()).isFalse();
+    }
+
+    private static JobParameters createJobParameters(int jobId) {
+        JobParameters jobParameters = mock(JobParameters.class);
+        when(jobParameters.getJobId()).thenReturn(jobId);
+        return jobParameters;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index 4e059b4..8024915 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -17,7 +17,6 @@
 package com.android.server;
 
 import static com.android.server.GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS;
-import static com.android.server.GestureLauncherService.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -773,6 +772,9 @@
 
     @Test
     public void testInterceptPowerKeyDown_triggerEmergency_fiveFastTaps_gestureIgnored() {
+        when(mResources.getInteger(
+                com.android.internal.R.integer.config_defaultMinEmergencyGestureTapDurationMillis))
+                .thenReturn(200);
         // Trigger emergency by tapping button 5 times
         long eventTime = triggerEmergencyGesture(/* tapIntervalMs= */ 1);
 
@@ -1449,7 +1451,7 @@
         long emergencyGestureTapDetectionMinTimeMs = Settings.Global.getInt(
                 mContext.getContentResolver(),
                 Settings.Global.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS,
-                EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS);
+                200);
         assertTrue(intercepted);
         if (tapIntervalMs * 4 > emergencyGestureTapDetectionMinTimeMs) {
             assertTrue(outLaunched.value);
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 1bf9a9d..cb4fc75 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -26,6 +26,7 @@
 import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME;
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
 import static com.android.server.accessibility.AccessibilityManagerService.ACTION_LAUNCH_HEARING_DEVICES_DIALOG;
+import static com.android.window.flags.Flags.FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -68,11 +69,13 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.LocaleList;
+import android.os.PermissionEnforcer;
+import android.os.RemoteException;
 import android.os.UserHandle;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.os.test.FakePermissionEnforcer;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableContext;
@@ -111,6 +114,7 @@
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.After;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -144,8 +148,7 @@
             ApplicationProvider.getApplicationContext());
 
     @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private static final int ACTION_ID = 20;
     private static final String LABEL = "label";
@@ -199,31 +202,34 @@
     private AccessibilityManagerService mA11yms;
     private TestableLooper mTestableLooper;
     private Handler mHandler;
+    private FakePermissionEnforcer mFakePermissionEnforcer;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
         mHandler = new Handler(mTestableLooper.getLooper());
-
+        mFakePermissionEnforcer = new FakePermissionEnforcer();
         LocalServices.removeServiceForTest(WindowManagerInternal.class);
         LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
         LocalServices.removeServiceForTest(UserManagerInternal.class);
         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+        LocalServices.removeServiceForTest(PermissionEnforcer.class);
         LocalServices.addService(
                 WindowManagerInternal.class, mMockWindowManagerService);
         LocalServices.addService(
                 ActivityTaskManagerInternal.class, mMockActivityTaskManagerInternal);
         LocalServices.addService(
                 UserManagerInternal.class, mMockUserManagerInternal);
-        LocalServices.addService(
-                StatusBarManagerInternal.class, mStatusBarManagerInternal);
+        LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
         mInputFilter = Mockito.mock(FakeInputFilter.class);
 
         when(mMockMagnificationController.getMagnificationConnectionManager()).thenReturn(
                 mMockMagnificationConnectionManager);
         when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
                 mMockFullScreenMagnificationController);
+        when(mMockMagnificationController.isFullScreenMagnificationControllerInitialized())
+                .thenReturn(true);
         when(mMockMagnificationController.supportWindowMagnification()).thenReturn(true);
         when(mMockWindowManagerService.getAccessibilityController()).thenReturn(
                 mMockA11yController);
@@ -250,7 +256,8 @@
                 mMockA11yDisplayListener,
                 mMockMagnificationController,
                 mInputFilter,
-                mProxyManager);
+                mProxyManager,
+                mFakePermissionEnforcer);
 
         final AccessibilityUserState userState = new AccessibilityUserState(
                 mA11yms.getCurrentUserIdLocked(), mTestableContext, mA11yms);
@@ -307,9 +314,7 @@
     @SmallTest
     @Test
     public void testRegisterSystemActionWithoutPermission() throws Exception {
-        doThrow(SecurityException.class).when(mMockSecurityPolicy)
-                .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
-
+        mFakePermissionEnforcer.revoke(Manifest.permission.MANAGE_ACCESSIBILITY);
         assertThrows(SecurityException.class,
                 () -> mA11yms.registerSystemAction(TEST_ACTION, ACTION_ID));
         verify(mMockSystemActionPerformer, never()).registerSystemAction(ACTION_ID, TEST_ACTION);
@@ -318,15 +323,14 @@
     @SmallTest
     @Test
     public void testRegisterSystemAction() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         mA11yms.registerSystemAction(TEST_ACTION, ACTION_ID);
         verify(mMockSystemActionPerformer).registerSystemAction(ACTION_ID, TEST_ACTION);
     }
 
     @Test
     public void testUnregisterSystemActionWithoutPermission() throws Exception {
-        doThrow(SecurityException.class).when(mMockSecurityPolicy)
-                .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
-
+        mFakePermissionEnforcer.revoke(Manifest.permission.MANAGE_ACCESSIBILITY);
         assertThrows(SecurityException.class,
                 () -> mA11yms.unregisterSystemAction(ACTION_ID));
         verify(mMockSystemActionPerformer, never()).unregisterSystemAction(ACTION_ID);
@@ -335,6 +339,7 @@
     @SmallTest
     @Test
     public void testUnregisterSystemAction() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         mA11yms.unregisterSystemAction(ACTION_ID);
         verify(mMockSystemActionPerformer).unregisterSystemAction(ACTION_ID);
     }
@@ -355,6 +360,7 @@
     @SmallTest
     @Test
     public void testRegisterProxy() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         when(mProxyManager.displayBelongsToCaller(anyInt(), anyInt())).thenReturn(true);
         mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
         verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY), anyInt(),
@@ -366,6 +372,7 @@
     @SmallTest
     @Test
     public void testRegisterProxyWithoutA11yPermissionOrRole() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         doThrow(SecurityException.class).when(mMockSecurityPolicy)
                 .checkForAccessibilityPermissionOrRole();
 
@@ -378,9 +385,7 @@
     @SmallTest
     @Test
     public void testRegisterProxyWithoutDevicePermission() throws Exception {
-        doThrow(SecurityException.class).when(mMockSecurityPolicy)
-                .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
-
+        mFakePermissionEnforcer.revoke(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         assertThrows(SecurityException.class,
                 () -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
         verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
@@ -399,6 +404,7 @@
     @SmallTest
     @Test
     public void testRegisterProxyForInvalidDisplay() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         assertThrows(IllegalArgumentException.class,
                 () -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.INVALID_DISPLAY));
         verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
@@ -408,6 +414,7 @@
     @SmallTest
     @Test
     public void testUnRegisterProxyWithPermission() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         when(mProxyManager.displayBelongsToCaller(anyInt(), anyInt())).thenReturn(true);
         mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
         mA11yms.unregisterProxyForDisplay(TEST_DISPLAY);
@@ -429,9 +436,7 @@
     @SmallTest
     @Test
     public void testUnRegisterProxyWithoutDevicePermission() {
-        doThrow(SecurityException.class).when(mMockSecurityPolicy)
-                .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
-
+        mFakePermissionEnforcer.revoke(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         assertThrows(SecurityException.class,
                 () -> mA11yms.unregisterProxyForDisplay(TEST_DISPLAY));
         verify(mProxyManager, never()).unregisterProxy(TEST_DISPLAY);
@@ -570,6 +575,17 @@
         verify(mMockMagnificationController).setAlwaysOnMagnificationEnabled(eq(true));
     }
 
+    @Test
+    @EnableFlags(FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER)
+    public void testSetConnectionNull_borderFlagEnabled_unregisterFullScreenMagnification()
+            throws RemoteException {
+        mFakePermissionEnforcer.grant(Manifest.permission.STATUS_BAR_SERVICE);
+        mA11yms.setMagnificationConnection(null);
+
+        verify(mMockFullScreenMagnificationController, atLeastOnce()).reset(
+                /* displayId= */ anyInt(), /* animate= */ anyBoolean());
+    }
+
     @SmallTest
     @Test
     public void testOnClientChange_magnificationEnabledAndCapabilityAll_requestConnection() {
@@ -624,7 +640,7 @@
 
     @SmallTest
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
     public void testOnClientChange_magnificationTwoFingerTripleTapEnabled_requestConnection() {
         when(mProxyManager.canRetrieveInteractiveWindowsLocked()).thenReturn(false);
 
@@ -642,7 +658,7 @@
 
     @SmallTest
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
     public void testOnClientChange_magnificationTwoFingerTripleTapDisabled_requestDisconnection() {
         when(mProxyManager.canRetrieveInteractiveWindowsLocked()).thenReturn(false);
 
@@ -704,7 +720,7 @@
 
     @SmallTest
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
     public void onClientChange_magnificationTwoFingerTripleTapDisabled_removeMagnificationButton() {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
@@ -720,7 +736,7 @@
 
     @SmallTest
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
     public void onClientChange_magnificationTwoFingerTripleTapEnabled_keepMagnificationButton() {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
@@ -772,11 +788,11 @@
 
     @SmallTest
     @Test
-    @RequiresFlagsDisabled(com.android.systemui.Flags.FLAG_HEARING_AIDS_QS_TILE_DIALOG)
+    @DisableFlags(com.android.systemui.Flags.FLAG_HEARING_AIDS_QS_TILE_DIALOG)
     public void testPerformAccessibilityShortcut_hearingAids_startActivityWithExpectedComponent() {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         userState.mAccessibilityShortcutKeyTargets.add(
                 ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString());
 
@@ -790,11 +806,11 @@
 
     @SmallTest
     @Test
-    @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_HEARING_AIDS_QS_TILE_DIALOG)
+    @EnableFlags(com.android.systemui.Flags.FLAG_HEARING_AIDS_QS_TILE_DIALOG)
     public void testPerformAccessibilityShortcut_hearingAids_sendExpectedBroadcast() {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         userState.mAccessibilityShortcutKeyTargets.add(
                 ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString());
 
@@ -908,7 +924,7 @@
 
     @Test
     public void testIsAccessibilityServiceWarningRequired_requiredByDefault() {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         final AccessibilityServiceInfo info = mockAccessibilityServiceInfo(COMPONENT_NAME);
 
         assertThat(mA11yms.isAccessibilityServiceWarningRequired(info)).isTrue();
@@ -916,7 +932,7 @@
 
     @Test
     public void testIsAccessibilityServiceWarningRequired_notRequiredIfAlreadyEnabled() {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo(COMPONENT_NAME);
         final AccessibilityServiceInfo info_b = mockAccessibilityServiceInfo(
                 new ComponentName("package_b", "class_b"));
@@ -930,7 +946,7 @@
 
     @Test
     public void testIsAccessibilityServiceWarningRequired_notRequiredIfExistingShortcut() {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo(
                 new ComponentName("package_a", "class_a"));
         final AccessibilityServiceInfo info_b = mockAccessibilityServiceInfo(
@@ -949,9 +965,9 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(FLAG_SKIP_ACCESSIBILITY_WARNING_DIALOG_FOR_TRUSTED_SERVICES)
+    @EnableFlags(FLAG_SKIP_ACCESSIBILITY_WARNING_DIALOG_FOR_TRUSTED_SERVICES)
     public void testIsAccessibilityServiceWarningRequired_notRequiredIfAllowlisted() {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo(
                 new ComponentName("package_a", "class_a"),
                 /* isSystemApp= */ true, /* isAlwaysOnService= */ false);
@@ -991,7 +1007,10 @@
     @Test
     public void enableShortcutsForTargets_enableSoftwareShortcut_shortcutTurnedOn()
             throws Exception {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
         String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
 
@@ -1008,8 +1027,41 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_HARDWARE_SHORTCUT_DISABLES_WARNING)
+    public void enableHardwareShortcutsForTargets_shortcutDialogSetting_isShown() {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        Settings.Secure.putInt(
+                mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN
+        );
+
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
+        setupShortcutTargetServices();
+        String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
+
+        mA11yms.enableShortcutsForTargets(
+                /* enable= */ true,
+                UserShortcutType.HARDWARE,
+                List.of(target),
+                mA11yms.getCurrentUserIdLocked());
+        mTestableLooper.processAllMessages();
+
+        assertThat(Settings.Secure.getInt(
+                mTestableContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                AccessibilityShortcutController.DialogStatus.NOT_SHOWN))
+                .isEqualTo(AccessibilityShortcutController.DialogStatus.SHOWN);
+    }
+
+    @Test
     public void enableShortcutsForTargets_disableSoftwareShortcut_shortcutTurnedOff()
             throws Exception {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
         enableShortcutsForTargets_enableSoftwareShortcut_shortcutTurnedOn();
 
@@ -1027,7 +1079,10 @@
 
     @Test
     public void enableShortcutsForTargets_enableSoftwareShortcutWithMagnification_menuSizeIncreased() {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
 
         mA11yms.enableShortcutsForTargets(
                 /* enable= */ true,
@@ -1046,7 +1101,7 @@
 
     @Test
     public void enableShortcutsForTargets_enableSoftwareShortcutWithMagnification_userConfigureSmallMenuSize_menuSizeNotChanged() {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         Settings.Secure.putInt(
                 mTestableContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
@@ -1070,7 +1125,10 @@
     @Test
     public void enableShortcutsForTargets_enableAlwaysOnServiceSoftwareShortcut_turnsOnAlwaysOnService()
             throws Exception {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
 
         mA11yms.enableShortcutsForTargets(
@@ -1090,6 +1148,9 @@
     @Test
     public void enableShortcutsForTargets_disableAlwaysOnServiceSoftwareShortcut_turnsOffAlwaysOnService()
             throws Exception {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         enableShortcutsForTargets_enableAlwaysOnServiceSoftwareShortcut_turnsOnAlwaysOnService();
 
         mA11yms.enableShortcutsForTargets(
@@ -1109,7 +1170,7 @@
     @Test
     public void enableShortcutsForTargets_enableStandardServiceSoftwareShortcut_wontTurnOnService()
             throws Exception {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
 
         mA11yms.enableShortcutsForTargets(
@@ -1129,6 +1190,9 @@
     @Test
     public void enableShortcutsForTargets_disableStandardServiceSoftwareShortcutWithServiceOn_wontTurnOffService()
             throws Exception {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         enableShortcutsForTargets_enableStandardServiceSoftwareShortcut_wontTurnOnService();
         AccessibilityUtils.setAccessibilityServiceState(
                 mTestableContext, TARGET_STANDARD_A11Y_SERVICE, /* enabled= */ true);
@@ -1149,7 +1213,10 @@
 
     @Test
     public void enableShortcutsForTargets_enableTripleTapShortcut_settingUpdated() {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
 
         mA11yms.enableShortcutsForTargets(
                 /* enable= */ true,
@@ -1168,6 +1235,9 @@
 
     @Test
     public void enableShortcutsForTargets_disableTripleTapShortcut_settingUpdated() {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         enableShortcutsForTargets_enableTripleTapShortcut_settingUpdated();
 
         mA11yms.enableShortcutsForTargets(
@@ -1186,7 +1256,10 @@
 
     @Test
     public void enableShortcutsForTargets_enableMultiFingerMultiTapsShortcut_settingUpdated() {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
 
         mA11yms.enableShortcutsForTargets(
                 /* enable= */ true,
@@ -1205,6 +1278,9 @@
 
     @Test
     public void enableShortcutsForTargets_disableMultiFingerMultiTapsShortcut_settingUpdated() {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         enableShortcutsForTargets_enableMultiFingerMultiTapsShortcut_settingUpdated();
 
         mA11yms.enableShortcutsForTargets(
@@ -1224,7 +1300,10 @@
 
     @Test
     public void enableShortcutsForTargets_enableVolumeKeysShortcut_shortcutSet() {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
 
         mA11yms.enableShortcutsForTargets(
@@ -1243,6 +1322,9 @@
 
     @Test
     public void enableShortcutsForTargets_disableVolumeKeysShortcut_shortcutNotSet() {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         enableShortcutsForTargets_enableVolumeKeysShortcut_shortcutSet();
 
         mA11yms.enableShortcutsForTargets(
@@ -1253,15 +1335,19 @@
         mTestableLooper.processAllMessages();
 
         assertThat(
-                ShortcutUtils.isComponentIdExistingInSettings(
-                        mTestableContext, ShortcutConstants.UserShortcutType.HARDWARE,
-                        TARGET_STANDARD_A11Y_SERVICE.flattenToString())
-        ).isFalse();
+                        ShortcutUtils.isComponentIdExistingInSettings(
+                                mTestableContext,
+                                ShortcutConstants.UserShortcutType.HARDWARE,
+                                TARGET_STANDARD_A11Y_SERVICE.flattenToString()))
+                .isFalse();
     }
 
     @Test
     public void enableShortcutsForTargets_enableQuickSettings_shortcutSet() {
-        mockManageAccessibilityGranted(mTestableContext);
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
 
         mA11yms.enableShortcutsForTargets(
@@ -1286,6 +1372,9 @@
 
     @Test
     public void enableShortcutsForTargets_disableQuickSettings_shortcutNotSet() {
+        // TODO(b/111889696): Remove the user 0 assumption once we support multi-user
+        Assume.assumeTrue("The test is setup to run as a user 0",
+                isSameCurrentUser(mA11yms, mTestableContext));
         enableShortcutsForTargets_enableQuickSettings_shortcutSet();
 
         mA11yms.enableShortcutsForTargets(
@@ -1318,7 +1407,7 @@
 
     @Test
     public void getA11yFeatureToTileMap() {
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
 
         Bundle bundle = mA11yms.getA11yFeatureToTileMap(mA11yms.getCurrentUserIdLocked());
@@ -1341,11 +1430,10 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_statusBarServiceNotGranted_throwsException() {
-        mTestableContext.getTestablePermissions().setPermission(
-                Manifest.permission.STATUS_BAR_SERVICE, PackageManager.PERMISSION_DENIED);
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.revoke(Manifest.permission.STATUS_BAR_SERVICE);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
 
         assertThrows(SecurityException.class,
                 () -> mA11yms.notifyQuickSettingsTilesChanged(
@@ -1355,9 +1443,9 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_manageAccessibilityNotGranted_throwsException() {
-        mockStatusBarServiceGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.STATUS_BAR_SERVICE);
         mTestableContext.getTestablePermissions().setPermission(
                 Manifest.permission.STATUS_BAR_SERVICE, PackageManager.PERMISSION_DENIED);
 
@@ -1369,10 +1457,10 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_qsTileChanges_updateA11yTilesInQsPanel() {
-        mockStatusBarServiceGranted(mTestableContext);
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.STATUS_BAR_SERVICE);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         List<ComponentName> tiles = List.of(
                 AccessibilityShortcutController.DALTONIZER_TILE_COMPONENT_NAME,
                 AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME
@@ -1389,7 +1477,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_sameQsTiles_noUpdateToA11yTilesInQsPanel() {
         notifyQuickSettingsTilesChanged_qsTileChanges_updateA11yTilesInQsPanel();
         List<ComponentName> tiles =
@@ -1406,10 +1494,10 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_serviceWarningRequired_qsShortcutRemainDisabled() {
-        mockStatusBarServiceGranted(mTestableContext);
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.STATUS_BAR_SERVICE);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
         ComponentName tile = new ComponentName(
                 TARGET_ALWAYS_ON_A11Y_SERVICE.getPackageName(),
@@ -1424,10 +1512,10 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_serviceWarningNotRequired_qsShortcutEnabled() {
-        mockStatusBarServiceGranted(mTestableContext);
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.STATUS_BAR_SERVICE);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         setupShortcutTargetServices();
         final AccessibilityUserState userState = mA11yms.getCurrentUserState();
         userState.mAccessibilityButtonTargets.clear();
@@ -1446,10 +1534,10 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_addFrameworkTile_qsShortcutEnabled() {
-        mockStatusBarServiceGranted(mTestableContext);
-        mockManageAccessibilityGranted(mTestableContext);
+        mFakePermissionEnforcer.grant(Manifest.permission.STATUS_BAR_SERVICE);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
         List<ComponentName> tiles = List.of(
                 AccessibilityShortcutController.DALTONIZER_TILE_COMPONENT_NAME,
                 AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME
@@ -1469,7 +1557,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void notifyQuickSettingsTilesChanged_removeFrameworkTile_qsShortcutDisabled() {
         notifyQuickSettingsTilesChanged_addFrameworkTile_qsShortcutEnabled();
         Set<ComponentName> qsTiles = mA11yms.getCurrentUserState().getA11yQsTilesInQsPanel();
@@ -1487,7 +1575,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void restoreAccessibilityQsTargets_a11yQsTargetsRestored() {
         String daltonizerTile =
                 AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME.flattenToString();
@@ -1510,7 +1598,7 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+    @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
     public void restoreAccessibilityQsTargets_a11yQsTargetsNotRestored() {
         String daltonizerTile =
                 AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME.flattenToString();
@@ -1576,16 +1664,6 @@
         return lockState;
     }
 
-    private void mockManageAccessibilityGranted(TestableContext context) {
-        context.getTestablePermissions().setPermission(Manifest.permission.MANAGE_ACCESSIBILITY,
-                PackageManager.PERMISSION_GRANTED);
-    }
-
-    private void mockStatusBarServiceGranted(TestableContext context) {
-        context.getTestablePermissions().setPermission(Manifest.permission.STATUS_BAR_SERVICE,
-                PackageManager.PERMISSION_GRANTED);
-    }
-
     private void assertStartActivityWithExpectedComponentName(Context mockContext,
             String componentName) {
         verify(mockContext).startActivityAsUser(mIntentArgumentCaptor.capture(),
@@ -1670,4 +1748,8 @@
             return mBroadcastReceivers;
         }
     }
+
+    private static boolean isSameCurrentUser(AccessibilityManagerService service, Context context) {
+        return service.getCurrentUserIdLocked() == context.getUserId();
+    }
 }
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 f3cd0d6..7b71f85 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
@@ -20,6 +20,7 @@
 
 import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
 import static com.android.server.accessibility.magnification.MockMagnificationConnection.TEST_DISPLAY;
+import static com.android.window.flags.Flags.FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -139,6 +140,8 @@
 
     private final TimeAnimator mMockTimeAnimator = mock(TimeAnimator.class);
 
+    private boolean mMockMagnificationConnectionState;
+
     FullScreenMagnificationController mFullScreenMagnificationController;
 
     public DisplayManagerInternal mDisplayManagerInternalMock = mock(DisplayManagerInternal.class);
@@ -175,6 +178,8 @@
 
         mScaleProvider = new MagnificationScaleProvider(mMockContext);
 
+        // Assume the connection is established by default
+        mMockMagnificationConnectionState = true;
         mFullScreenMagnificationController =
                 new FullScreenMagnificationController(
                         mMockControllerCtx,
@@ -184,7 +189,8 @@
                         () -> mMockThumbnail,
                         ConcurrentUtils.DIRECT_EXECUTOR,
                         () -> mMockScroller,
-                        () -> mMockTimeAnimator);
+                        () -> mMockTimeAnimator,
+                        () -> mMockMagnificationConnectionState);
     }
 
     @After
@@ -196,7 +202,6 @@
                 CURRENT_USER_ID);
     }
 
-
     @Test
     public void testRegister_WindowManagerAndContextRegisterListeners() {
         register(DISPLAY_0);
@@ -291,6 +296,21 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER)
+    public void testSetScale_noConnection_doNothing() {
+        register(TEST_DISPLAY);
+
+        // Assume that the connection does not exist.
+        mMockMagnificationConnectionState = false;
+
+        final float scale = 2.0f;
+        final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        assertFalse(mFullScreenMagnificationController
+                .setScale(TEST_DISPLAY, scale, center.x, center.y, false, SERVICE_ID_1));
+        assertFalse(mFullScreenMagnificationController.isActivated(TEST_DISPLAY));
+    }
+
+    @Test
     public void testSetScale_noAnimation_shouldGoStraightToWindowManagerAndUpdateState() {
         for (int i = 0; i < DISPLAY_COUNT; i++) {
             setScale_noAnimation_shouldGoStraightToWindowManagerAndUpdateState(i);
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 7fbd521..f482ddc 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
@@ -197,6 +197,8 @@
 
     private final Scroller mMockScroller = spy(new Scroller(mContext));
 
+    private boolean mMockMagnificationConnectionState;
+
     private OffsettableClock mClock;
     private FullScreenMagnificationGestureHandler mMgh;
     private TestHandler mHandler;
@@ -229,6 +231,7 @@
         Settings.Secure.putFloatForUser(mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
                 UserHandle.USER_SYSTEM);
+        mMockMagnificationConnectionState = true;
         mFullScreenMagnificationController =
                 new FullScreenMagnificationController(
                         mockController,
@@ -238,7 +241,8 @@
                         () -> null,
                         ConcurrentUtils.DIRECT_EXECUTOR,
                         () -> mMockScroller,
-                        TimeAnimator::new) {
+                        TimeAnimator::new,
+                        () -> mMockMagnificationConnectionState) {
                     @Override
                     public boolean magnificationRegionContains(int displayId, float x, float y) {
                         return true;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 58567ca..2528177 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -220,7 +220,8 @@
                                 () -> null,
                                 ConcurrentUtils.DIRECT_EXECUTOR,
                                 () -> mMockScroller,
-                                () -> mTimeAnimator));
+                                () -> mTimeAnimator,
+                                () -> true));
         mScreenMagnificationController.register(TEST_DISPLAY);
 
         mMagnificationConnectionManager = spy(
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 e0a99b0..0c92abc 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.nullable;
 import static org.mockito.Mockito.times;
@@ -45,6 +46,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -57,6 +59,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
@@ -155,6 +158,8 @@
         mPackageInfo.applicationInfo = new ApplicationInfo();
         mPackageInfo.applicationInfo.privateFlags = ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo);
+        when(mMockPackageManager.getPackageInfoAsUser(
+                        anyString(), anyInt(), anyInt())).thenReturn(mPackageInfo);
         when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager);
         when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
         when(mMockContext.getSystemServiceName(AppOpsManager.class)).thenReturn(
@@ -3156,6 +3161,111 @@
     }
 
     @SmallTest
+    public void testAccountRemovedBroadcastMarkedAccountAsVisibleTwice() throws Exception {
+        unlockSystemUser();
+
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put("testpackage1", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
+
+        addAccountRemovedReceiver("testpackage1");
+        mAms.registerAccountListener(
+                new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1},
+                "testpackage1");
+        mAms.addAccountExplicitlyWithVisibility(
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                /* password= */ "p11",
+                /* extras= */ null,
+                visibility,
+                /* callerPackage= */ null);
+
+        updateBroadcastCounters(2);
+        assertEquals(mVisibleAccountsChangedBroadcasts, 1);
+        assertEquals(mLoginAccountsChangedBroadcasts, 1);
+        assertEquals(mAccountRemovedBroadcasts, 0);
+
+        mAms.setAccountVisibility(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "testpackage1",
+                AccountManager.VISIBILITY_VISIBLE);
+
+        updateBroadcastCounters(3);
+        assertEquals(mVisibleAccountsChangedBroadcasts, 1); // visibility was not changed
+        assertEquals(mLoginAccountsChangedBroadcasts, 2);
+        assertEquals(mAccountRemovedBroadcasts, 0);
+    }
+
+    @SmallTest
+    public void testAccountsChangedBroadcastMarkedAccountAsVisibleThreeTimes() throws Exception {
+        unlockSystemUser();
+
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put("testpackage1", AccountManager.VISIBILITY_VISIBLE);
+
+        addAccountRemovedReceiver("testpackage1");
+        mAms.registerAccountListener(
+                new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1},
+                "testpackage1");
+        mAms.addAccountExplicitlyWithVisibility(
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                /* password= */ "p11",
+                /* extras= */ null,
+                visibility,
+                /* callerPackage= */ null);
+
+        updateBroadcastCounters(2);
+        assertEquals(mVisibleAccountsChangedBroadcasts, 1);
+        assertEquals(mLoginAccountsChangedBroadcasts, 1);
+        assertEquals(mAccountRemovedBroadcasts, 0);
+
+        mAms.setAccountVisibility(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "testpackage1",
+                AccountManager.VISIBILITY_VISIBLE);
+        mAms.setAccountVisibility(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "testpackage1",
+                AccountManager.VISIBILITY_VISIBLE);
+
+        updateBroadcastCounters(2);
+        assertEquals(mVisibleAccountsChangedBroadcasts, 1);
+        assertEquals(mLoginAccountsChangedBroadcasts, 1);
+        assertEquals(mAccountRemovedBroadcasts, 0);
+    }
+
+    @SmallTest
+    public void testAccountsChangedBroadcastChangedVisibilityTwoTimes() throws Exception {
+        unlockSystemUser();
+
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put("testpackage1", AccountManager.VISIBILITY_VISIBLE);
+
+        addAccountRemovedReceiver("testpackage1");
+        mAms.registerAccountListener(
+                new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1},
+                "testpackage1");
+        mAms.addAccountExplicitlyWithVisibility(
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                /* password= */ "p11",
+                /* extras= */ null,
+                visibility,
+                /* callerPackage= */ null);
+
+        updateBroadcastCounters(2);
+        assertEquals(mVisibleAccountsChangedBroadcasts, 1);
+        assertEquals(mLoginAccountsChangedBroadcasts, 1);
+        assertEquals(mAccountRemovedBroadcasts, 0);
+
+        mAms.setAccountVisibility(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "testpackage1",
+                AccountManager.VISIBILITY_NOT_VISIBLE);
+        mAms.setAccountVisibility(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "testpackage1",
+                AccountManager.VISIBILITY_VISIBLE);
+
+        updateBroadcastCounters(7);
+        assertEquals(mVisibleAccountsChangedBroadcasts, 3);
+        assertEquals(mLoginAccountsChangedBroadcasts, 3);
+        assertEquals(mAccountRemovedBroadcasts, 1);
+    }
+
+    @SmallTest
     public void testRegisterAccountListenerCredentialsUpdate() throws Exception {
         unlockSystemUser();
         mAms.registerAccountListener(
@@ -3493,6 +3603,12 @@
         }
 
         @Override
+        public boolean bindServiceAsUser(Intent service, ServiceConnection conn,
+                Context.BindServiceFlags flags, UserHandle user) {
+            return mTestContext.bindServiceAsUser(service, conn, flags, user);
+        }
+
+        @Override
         public void unbindService(ServiceConnection conn) {
             mTestContext.unbindService(conn);
         }
@@ -3547,6 +3663,19 @@
         }
 
         @Override
+        public Resources getResources() {
+            Resources mockResources = mock(Resources.class);
+            // config_canRemoveFirstAccount = true
+            when(mockResources.getBoolean(anyInt())).thenReturn(true);
+            return mockResources;
+        }
+
+        @Override
+        public ContentResolver getContentResolver() {
+            return mock(ContentResolver.class);
+        }
+
+        @Override
         public void sendBroadcastAsUser(Intent intent, UserHandle user) {
             sendBroadcastAsUser(intent, user, null, null);
         }
diff --git a/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java b/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java
index 1acb8ac..d180688 100644
--- a/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/adaptiveauth/AdaptiveAuthServiceTest.java
@@ -36,6 +36,9 @@
 import android.content.pm.PackageManager;
 import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -194,8 +197,8 @@
     @Test
     public void testReportAuthAttempt_biometricAuthSucceeded()
             throws RemoteException {
-        mAuthenticationStateListenerCaptor.getValue()
-                .onAuthenticationSucceeded(REASON_UNKNOWN, PRIMARY_USER_ID);
+        mAuthenticationStateListenerCaptor.getValue().onAuthenticationSucceeded(
+                authSuccessInfo(PRIMARY_USER_ID));
         waitForAuthCompletion();
 
         verifyNotLockDevice(DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
@@ -205,8 +208,8 @@
     @Test
     public void testReportAuthAttempt_biometricAuthFailed_once()
             throws RemoteException {
-        mAuthenticationStateListenerCaptor.getValue()
-                .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+        mAuthenticationStateListenerCaptor.getValue().onAuthenticationFailed(
+                authFailedInfo(PRIMARY_USER_ID));
         waitForAuthCompletion();
 
         verifyNotLockDevice(1 /* expectedCntFailedAttempts */, PRIMARY_USER_ID);
@@ -220,8 +223,8 @@
         when(mKeyguardManager.isKeyguardLocked()).thenReturn(true);
 
         for (int i = 0; i < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS; i++) {
-            mAuthenticationStateListenerCaptor.getValue()
-                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+            mAuthenticationStateListenerCaptor.getValue().onAuthenticationFailed(
+                    authFailedInfo(PRIMARY_USER_ID));
         }
         waitForAuthCompletion();
 
@@ -237,8 +240,8 @@
         when(mKeyguardManager.isKeyguardLocked()).thenReturn(false);
 
         for (int i = 0; i < MAX_ALLOWED_FAILED_AUTH_ATTEMPTS; i++) {
-            mAuthenticationStateListenerCaptor.getValue()
-                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+            mAuthenticationStateListenerCaptor.getValue().onAuthenticationFailed(
+                    authFailedInfo(PRIMARY_USER_ID));
         }
         waitForAuthCompletion();
 
@@ -250,8 +253,8 @@
             throws RemoteException {
         // Three failed biometric auth attempts
         for (int i = 0; i < 3; i++) {
-            mAuthenticationStateListenerCaptor.getValue()
-                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+            mAuthenticationStateListenerCaptor.getValue().onAuthenticationFailed(
+                    authFailedInfo(PRIMARY_USER_ID));
         }
         // One successful primary auth attempt
         mLockSettingsStateListenerCaptor.getValue().onAuthenticationSucceeded(PRIMARY_USER_ID);
@@ -269,8 +272,8 @@
             mLockSettingsStateListenerCaptor.getValue().onAuthenticationFailed(PRIMARY_USER_ID);
         }
         // One successful biometric auth attempt
-        mAuthenticationStateListenerCaptor.getValue()
-                .onAuthenticationSucceeded(REASON_UNKNOWN, PRIMARY_USER_ID);
+        mAuthenticationStateListenerCaptor.getValue().onAuthenticationSucceeded(
+                authSuccessInfo(PRIMARY_USER_ID));
         waitForAuthCompletion();
 
         verifyNotLockDevice(DEFAULT_COUNT_FAILED_AUTH_ATTEMPTS /* expectedCntFailedAttempts */,
@@ -286,8 +289,8 @@
         }
         // Two failed biometric auth attempts
         for (int i = 0; i < 2; i++) {
-            mAuthenticationStateListenerCaptor.getValue()
-                    .onAuthenticationFailed(REASON_UNKNOWN, PRIMARY_USER_ID);
+            mAuthenticationStateListenerCaptor.getValue().onAuthenticationFailed(
+                    authFailedInfo(PRIMARY_USER_ID));
         }
         waitForAuthCompletion();
 
@@ -304,8 +307,8 @@
         }
         // Two failed biometric auth attempts
         for (int i = 0; i < 2; i++) {
-            mAuthenticationStateListenerCaptor.getValue()
-                    .onAuthenticationFailed(REASON_UNKNOWN, MANAGED_PROFILE_USER_ID);
+            mAuthenticationStateListenerCaptor.getValue().onAuthenticationFailed(
+                    authFailedInfo(MANAGED_PROFILE_USER_ID));
         }
         waitForAuthCompletion();
 
@@ -338,4 +341,16 @@
     private static void waitForAuthCompletion() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
+
+    private AuthenticationSucceededInfo authSuccessInfo(int userId) {
+        return new AuthenticationSucceededInfo.Builder(BiometricSourceType.FINGERPRINT,
+                REASON_UNKNOWN, true, userId).build();
+    }
+
+
+    private AuthenticationFailedInfo authFailedInfo(int userId) {
+        return new AuthenticationFailedInfo.Builder(BiometricSourceType.FINGERPRINT, REASON_UNKNOWN,
+                userId).build();
+    }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 0a2a855..c6f3eb3 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -34,6 +34,7 @@
 import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
 import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
 import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
+import static com.android.server.am.UserController.SCHEDULED_STOP_BACKGROUND_USER_MSG;
 import static com.android.server.am.UserController.USER_COMPLETED_EVENT_MSG;
 import static com.android.server.am.UserController.USER_CURRENT_MSG;
 import static com.android.server.am.UserController.USER_START_MSG;
@@ -323,7 +324,8 @@
     @Test
     public void testStartUserUIDisabled() {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
         verify(mInjector, never()).showUserSwitchingDialog(
@@ -393,7 +395,8 @@
     @Test
     public void testFailedStartUserInForeground() {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         mUserController.startUserInForeground(NONEXIST_USER_ID);
         verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
@@ -470,7 +473,8 @@
     @Test
     public void testContinueUserSwitch() {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         // Start user -- this will update state of mUserController
         mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -483,7 +487,7 @@
         continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
         verify(mInjector, times(0)).dismissKeyguard(any());
         verify(mInjector, times(1)).dismissUserSwitchingDialog(any());
-        continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
+        continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false, false);
         verifySystemUserVisibilityChangesNeverNotified();
     }
 
@@ -491,7 +495,8 @@
     public void testContinueUserSwitchDismissKeyguard() {
         when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(false);
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         // Start user -- this will update state of mUserController
         mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -504,14 +509,15 @@
         continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
         verify(mInjector, times(1)).dismissKeyguard(any());
         verify(mInjector, times(1)).dismissUserSwitchingDialog(any());
-        continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
+        continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false, false);
         verifySystemUserVisibilityChangesNeverNotified();
     }
 
     @Test
     public void testContinueUserSwitchUIDisabled() {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         // Start user -- this will update state of mUserController
         mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
@@ -524,11 +530,11 @@
         // Verify that continueUserSwitch worked as expected
         continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
         verify(mInjector, never()).dismissUserSwitchingDialog(any());
-        continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
+        continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false, false);
     }
 
     private void continueUserSwitchAssertions(int expectedOldUserId, int expectedNewUserId,
-            boolean backgroundUserStopping) {
+            boolean backgroundUserStopping, boolean expectScheduleBackgroundUserStopping) {
         Set<Integer> expectedCodes = new LinkedHashSet<>();
         expectedCodes.add(COMPLETE_USER_SWITCH_MSG);
         expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
@@ -536,6 +542,9 @@
             expectedCodes.add(CLEAR_USER_JOURNEY_SESSION_MSG);
             expectedCodes.add(0); // this is for directly posting in stopping.
         }
+        if (expectScheduleBackgroundUserStopping) {
+            expectedCodes.add(SCHEDULED_STOP_BACKGROUND_USER_MSG);
+        }
         Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
         assertEquals("Unexpected message sent", expectedCodes, actualCodes);
         Message msg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_COMPLETE_MSG);
@@ -571,6 +580,112 @@
                 ).collect(Collectors.toList()), Collections.emptySet());
     }
 
+    /** Test scheduling stopping of background users after a user-switch. */
+    @Test
+    public void testScheduleStopOfBackgroundUser_switch() {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);
+
+        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
+                /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ 2);
+
+        setUpUser(TEST_USER_ID1, NO_USERINFO_FLAGS);
+
+        // Switch to TEST_USER_ID from user 0
+        int numberOfUserSwitches = 0;
+        addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM,
+                ++numberOfUserSwitches,
+                /* expectOldUserStopping= */false,
+                /* expectScheduleBackgroundUserStopping= */ false);
+        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID),
+                mUserController.getRunningUsersLU());
+
+        // Allow the post-switch processing to complete (there should be no scheduled stopping).
+        assertAndProcessScheduledStopBackgroundUser(false, null);
+        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID),
+                mUserController.getRunningUsersLU());
+
+        // Switch to TEST_USER_ID1 from TEST_USER_ID
+        addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID,
+                ++numberOfUserSwitches,
+                /* expectOldUserStopping= */false,
+                /* expectScheduleBackgroundUserStopping= */ true);
+        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_ID1),
+                mUserController.getRunningUsersLU());
+
+        // Switch back to TEST_USER_ID from TEST_USER_ID1
+        addForegroundUserAndContinueUserSwitch(TEST_USER_ID, TEST_USER_ID1,
+                ++numberOfUserSwitches,
+                /* expectOldUserStopping= */false,
+                /* expectScheduleBackgroundUserStopping= */ true);
+        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID1, TEST_USER_ID),
+                mUserController.getRunningUsersLU());
+
+        // Allow the post-switch processing to complete.
+        assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_ID);
+        assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID1);
+        assertAndProcessScheduledStopBackgroundUser(false, null);
+        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID),
+                mUserController.getRunningUsersLU());
+    }
+
+    /** Test scheduling stopping of background users that were started in the background. */
+    @Test
+    public void testScheduleStopOfBackgroundUser_startInBackground() throws Exception {
+        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);
+
+        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
+                /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ 2);
+
+        // Start two full background users (which should both get scheduled for stopping)
+        // and one profile (which should not).
+        setUpAndStartUserInBackground(TEST_USER_ID);
+        setUpAndStartUserInBackground(TEST_USER_ID1);
+        setUpAndStartProfileInBackground(TEST_USER_ID2, UserManager.USER_TYPE_PROFILE_MANAGED);
+
+        assertEquals(newHashSet(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_ID1, TEST_USER_ID2),
+                new HashSet<>(mUserController.getRunningUsersLU()));
+
+        assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID);
+        assertEquals(newHashSet(SYSTEM_USER_ID, TEST_USER_ID1, TEST_USER_ID2),
+                new HashSet<>(mUserController.getRunningUsersLU()));
+
+        assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID1);
+        assertEquals(newHashSet(SYSTEM_USER_ID, TEST_USER_ID2),
+                new HashSet<>(mUserController.getRunningUsersLU()));
+
+        assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_ID2);
+        assertAndProcessScheduledStopBackgroundUser(false, null);
+
+        // Now that we've processed the stops, let's make sure that a subsequent one will work too.
+        setUpAndStartUserInBackground(TEST_USER_ID3);
+        assertEquals(newHashSet(SYSTEM_USER_ID, TEST_USER_ID2, TEST_USER_ID3),
+                new HashSet<>(mUserController.getRunningUsersLU()));
+        assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID3);
+        assertAndProcessScheduledStopBackgroundUser(false, null);
+        assertEquals(newHashSet(SYSTEM_USER_ID, TEST_USER_ID2),
+                new HashSet<>(mUserController.getRunningUsersLU()));
+    }
+
+    /**
+     * Process queued SCHEDULED_STOP_BACKGROUND_USER_MSG message, if expected.
+     * @param userId the user we are checking to see whether it is scheduled.
+     *               Can be null, when expectScheduled is false, to indicate no user should be
+     *               scheduled.
+     */
+    private void assertAndProcessScheduledStopBackgroundUser(
+            boolean expectScheduled, @Nullable Integer userId) {
+        TestHandler handler = mInjector.mHandler;
+        if (expectScheduled) {
+            assertTrue(handler.hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId));
+            handler.removeMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId);
+            mUserController.processScheduledStopOfBackgroundUser(userId);
+        } else {
+            assertFalse(handler.hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId));
+        }
+    }
+
     @Test
     public void testExplicitSystemUserStartInBackground() {
         setUpUser(UserHandle.USER_SYSTEM, 0);
@@ -587,13 +702,14 @@
     public void testUserLockingFromUserSwitchingForMultipleUsersNonDelayedLocking()
             throws InterruptedException, RemoteException {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         setUpUser(TEST_USER_ID1, 0);
         setUpUser(TEST_USER_ID2, 0);
         int numberOfUserSwitches = 1;
         addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         // running: user 0, USER_ID
         assertTrue(mUserController.canStartMoreUsers());
         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID}),
@@ -601,7 +717,7 @@
 
         numberOfUserSwitches++;
         addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         // running: user 0, USER_ID, USER_ID1
         assertFalse(mUserController.canStartMoreUsers());
         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID, TEST_USER_ID1}),
@@ -609,7 +725,7 @@
 
         numberOfUserSwitches++;
         addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         UserState ussUser2 = mUserStates.get(TEST_USER_ID2);
         // skip middle step and call this directly.
         mUserController.finishUserSwitch(ussUser2);
@@ -631,13 +747,14 @@
     public void testUserLockingFromUserSwitchingForMultipleUsersDelayedLockingMode()
             throws Exception {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ true);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ true,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         setUpUser(TEST_USER_ID1, 0);
         setUpUser(TEST_USER_ID2, 0);
         int numberOfUserSwitches = 1;
         addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         // running: user 0, USER_ID
         assertTrue(mUserController.canStartMoreUsers());
         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID}),
@@ -645,7 +762,7 @@
         numberOfUserSwitches++;
 
         addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID,
-                numberOfUserSwitches, true);
+                numberOfUserSwitches, true, false);
         // running: user 0, USER_ID1
         // stopped + unlocked: USER_ID
         numberOfUserSwitches++;
@@ -663,7 +780,7 @@
                 .lockCeStorage(anyInt());
 
         addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
-                numberOfUserSwitches, true);
+                numberOfUserSwitches, true, false);
         // running: user 0, USER_ID2
         // stopped + unlocked: USER_ID1
         // stopped + locked: USER_ID
@@ -686,7 +803,8 @@
     public void testStoppingExcessRunningUsersAfterSwitch_currentProfileNotStopped()
             throws Exception {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 5, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 5, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         final int PARENT_ID = 200;
         final int PROFILE1_ID = 201;
@@ -707,7 +825,7 @@
 
         int numberOfUserSwitches = 1;
         addForegroundUserAndContinueUserSwitch(PARENT_ID, UserHandle.USER_SYSTEM,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         mUserController.finishUserSwitch(mUserStates.get(PARENT_ID));
         waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS);
         assertTrue(mUserController.canStartMoreUsers());
@@ -722,7 +840,7 @@
 
         numberOfUserSwitches++;
         addForegroundUserAndContinueUserSwitch(FG_USER_ID, PARENT_ID,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         mUserController.finishUserSwitch(mUserStates.get(FG_USER_ID));
         waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS);
         assertTrue(mUserController.canStartMoreUsers());
@@ -747,7 +865,7 @@
 
         numberOfUserSwitches++;
         addForegroundUserAndContinueUserSwitch(PARENT_ID, FG_USER_ID,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         mUserController.finishUserSwitch(mUserStates.get(PARENT_ID));
         waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS);
         // We've now done a user switch and should notice that we've exceeded the maximum number of
@@ -766,7 +884,8 @@
     @Test
     public void testRunningUsersListOrder_parentAfterProfile() {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 7, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 7, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         final int PARENT_ID = 200;
         final int PROFILE1_ID = 201;
@@ -787,7 +906,7 @@
 
         int numberOfUserSwitches = 1;
         addForegroundUserAndContinueUserSwitch(PARENT_ID, UserHandle.USER_SYSTEM,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         assertEquals(Arrays.asList(
                 new Integer[] {SYSTEM_USER_ID, PARENT_ID}),
                 mUserController.getRunningUsersLU());
@@ -799,7 +918,7 @@
 
         numberOfUserSwitches++;
         addForegroundUserAndContinueUserSwitch(FG_USER_ID, PARENT_ID,
-                numberOfUserSwitches, false);
+                numberOfUserSwitches, false, false);
         assertEquals(Arrays.asList(
                 new Integer[] {SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID, FG_USER_ID}),
                 mUserController.getRunningUsersLU());
@@ -827,7 +946,8 @@
     @Test
     public void testRunningUsersListOrder_currentAtEnd() {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 7, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 7, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         final int CURRENT_ID = 200;
         final int PROFILE_ID = 201;
@@ -842,7 +962,7 @@
                 new Integer[] {SYSTEM_USER_ID}),
                 mUserController.getRunningUsersLU());
 
-        addForegroundUserAndContinueUserSwitch(CURRENT_ID, UserHandle.USER_SYSTEM, 1, false);
+        addForegroundUserAndContinueUserSwitch(CURRENT_ID, UserHandle.USER_SYSTEM, 1, false, false);
         assertEquals(Arrays.asList(
                 new Integer[] {SYSTEM_USER_ID, CURRENT_ID}),
                 mUserController.getRunningUsersLU());
@@ -864,7 +984,8 @@
     @Test
     public void testUserLockingWithStopUserForNonDelayedLockingMode() throws Exception {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         setUpAndStartUserInBackground(TEST_USER_ID);
         assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID, /* allowDelayedLocking= */ true,
@@ -888,7 +1009,7 @@
         int userId = -1;
 
         assertThrows(IllegalArgumentException.class,
-                () -> mUserController.stopUser(userId, /* force= */ true,
+                () -> mUserController.stopUser(userId,
                         /* allowDelayedLocking= */ true, /* stopUserCallback= */ null,
                         /* keyEvictedCallback= */ null));
     }
@@ -897,7 +1018,7 @@
     public void testStopUser_systemUser() {
         int userId = UserHandle.USER_SYSTEM;
 
-        int r = mUserController.stopUser(userId, /* force= */ true,
+        int r = mUserController.stopUser(userId,
                 /* allowDelayedLocking= */ true, /* stopUserCallback= */ null,
                 /* keyEvictedCallback= */ null);
 
@@ -909,7 +1030,7 @@
         setUpUser(TEST_USER_ID1, /* flags= */ 0);
         mUserController.startUser(TEST_USER_ID1, USER_START_MODE_FOREGROUND);
 
-        int r = mUserController.stopUser(TEST_USER_ID1, /* force= */ true,
+        int r = mUserController.stopUser(TEST_USER_ID1,
                 /* allowDelayedLocking= */ true, /* stopUserCallback= */ null,
                 /* keyEvictedCallback= */ null);
 
@@ -922,7 +1043,8 @@
     @Test
     public void testUserLockingForDelayedLockingMode() throws Exception {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ true);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ true,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         // allowDelayedLocking set and no KeyEvictedCallback, so it should not lock.
         setUpAndStartUserInBackground(TEST_USER_ID);
@@ -973,7 +1095,8 @@
     @Test
     public void testStopProfile_doesNotStopItsParent() throws Exception {
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 5, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 5, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         final Range<Integer> RUNNING_RANGE =
                 Range.closed(UserState.STATE_BOOTING, UserState.STATE_RUNNING_UNLOCKED);
@@ -1053,7 +1176,8 @@
     @Test
     public void testStopPrivateProfile() throws Exception {
         mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
@@ -1071,7 +1195,8 @@
     @Test
     public void testStopPrivateProfileWithDelayedLocking() throws Exception {
         mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
@@ -1083,7 +1208,8 @@
     @Test
     public void testStopPrivateProfileWithDelayedLocking_flagDisabled() throws Exception {
         mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
         mSetFlagsRule.disableFlags(
@@ -1113,7 +1239,8 @@
     public void testStopPrivateProfileWithDelayedLocking_imperviousToNumberOfRunningUsers()
             throws Exception {
         mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
-                /* maxRunningUsers= */ 1, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 1, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
@@ -1130,7 +1257,8 @@
     @Test
     public void testStopManagedProfileWithDelayedLocking() throws Exception {
         mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
         mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                 android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE,
                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
@@ -1285,7 +1413,8 @@
     public void testStallUserSwitchUntilTheKeyguardIsShown() throws Exception {
         // enable user switch ui, because keyguard is only shown then
         mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
-                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+                /* backgroundUserScheduledStopTimeSecs= */ -1);
 
         // mock the device to be secure in order to expect the keyguard to be shown
         when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
@@ -1338,7 +1467,7 @@
 
     private void assertUserLockedOrUnlockedAfterStopping(int userId, boolean allowDelayedLocking,
             KeyEvictedCallback keyEvictedCallback, boolean expectLocking) throws Exception {
-        int r = mUserController.stopUser(userId, /* force= */ true, /* allowDelayedLocking= */
+        int r = mUserController.stopUser(userId, /* allowDelayedLocking= */
                 allowDelayedLocking, null, keyEvictedCallback);
         assertThat(r).isEqualTo(ActivityManager.USER_OP_SUCCESS);
         assertUserLockedOrUnlockedState(userId, allowDelayedLocking, expectLocking);
@@ -1365,7 +1494,8 @@
     }
 
     private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId,
-            int expectedNumberOfCalls, boolean expectOldUserStopping) {
+            int expectedNumberOfCalls, boolean expectOldUserStopping,
+            boolean expectScheduleBackgroundUserStopping) {
         // Start user -- this will update state of mUserController
         mUserController.startUser(newUserId, USER_START_MODE_FOREGROUND);
         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -1378,8 +1508,12 @@
         mInjector.mHandler.clearAllRecordedMessages();
         // Verify that continueUserSwitch worked as expected
         continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
+        assertEquals(mInjector.mHandler
+                        .hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, expectedOldUserId),
+                expectScheduleBackgroundUserStopping);
         verify(mInjector, times(expectedNumberOfCalls)).dismissUserSwitchingDialog(any());
-        continueUserSwitchAssertions(oldUserId, newUserId, expectOldUserStopping);
+        continueUserSwitchAssertions(oldUserId, newUserId, expectOldUserStopping,
+                expectScheduleBackgroundUserStopping);
     }
 
     private UserInfo setUpUser(@UserIdInt int userId, @UserInfoFlag int flags) {
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
index b487dc6..c970a3e 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
@@ -16,7 +16,8 @@
 
 package com.android.server.appop;
 
-import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -31,6 +32,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OnOpActiveChangedListener;
 import android.companion.virtual.VirtualDeviceManager;
@@ -38,7 +40,8 @@
 import android.content.AttributionSource;
 import android.content.Context;
 import android.os.Process;
-import android.virtualdevice.cts.common.FakeAssociationRule;
+import android.permission.PermissionManager;
+import android.virtualdevice.cts.common.VirtualDeviceRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -49,7 +52,6 @@
 import org.junit.runner.RunWith;
 
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Tests app ops version upgrades
@@ -59,7 +61,13 @@
 public class AppOpsActiveWatcherTest {
 
     @Rule
-    public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule();
+    public VirtualDeviceRule virtualDeviceRule =
+            VirtualDeviceRule.withAdditionalPermissions(
+                    Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+                    Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+                    Manifest.permission.CREATE_VIRTUAL_DEVICE,
+                    Manifest.permission.GET_APP_OPS_STATS
+            );
     private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
 
     @Test
@@ -145,20 +153,28 @@
 
     @Test
     public void testWatchActiveOpsForExternalDevice() {
-        final VirtualDeviceManager virtualDeviceManager = getContext().getSystemService(
-                VirtualDeviceManager.class);
-        AtomicInteger virtualDeviceId = new AtomicInteger();
-        runWithShellPermissionIdentity(() -> {
-            final VirtualDeviceManager.VirtualDevice virtualDevice =
-                    virtualDeviceManager.createVirtualDevice(
-                            mFakeAssociationRule.getAssociationInfo().getId(),
-                            new VirtualDeviceParams.Builder().setName("virtual_device").build());
-            virtualDeviceId.set(virtualDevice.getDeviceId());
-        });
+        VirtualDeviceManager.VirtualDevice virtualDevice =
+                virtualDeviceRule.createManagedVirtualDevice(
+                        new VirtualDeviceParams.Builder()
+                                .setDevicePolicy(POLICY_TYPE_CAMERA, DEVICE_POLICY_CUSTOM)
+                                .build()
+                );
+
+        PermissionManager permissionManager =
+                getContext().getSystemService(PermissionManager.class);
+
+        // Unlike runtime permission being automatically granted to the default device, we need to
+        // grant camera permission to the external device first before we can start op.
+        permissionManager.grantRuntimePermission(
+                getContext().getOpPackageName(),
+                Manifest.permission.CAMERA,
+                virtualDevice.getPersistentDeviceId()
+        );
+
         final OnOpActiveChangedListener listener = mock(OnOpActiveChangedListener.class);
         AttributionSource attributionSource = new AttributionSource(Process.myUid(),
                 getContext().getOpPackageName(), getContext().getAttributionTag(),
-                virtualDeviceId.get());
+                virtualDevice.getDeviceId());
 
         final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
         appOpsManager.startWatchingActive(new String[]{AppOpsManager.OPSTR_CAMERA,
@@ -171,7 +187,7 @@
         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
                 eq(Process.myUid()), eq(getContext().getOpPackageName()),
-                eq(getContext().getAttributionTag()), eq(virtualDeviceId.get()), eq(true),
+                eq(getContext().getAttributionTag()), eq(virtualDevice.getDeviceId()), eq(true),
                 eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
                 eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
         verifyNoMoreInteractions(listener);
@@ -182,7 +198,7 @@
         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
                 eq(Process.myUid()), eq(getContext().getOpPackageName()),
-                eq(getContext().getAttributionTag()), eq(virtualDeviceId.get()), eq(false),
+                eq(getContext().getAttributionTag()), eq(virtualDevice.getDeviceId()), eq(false),
                 eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
                 eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
         verifyNoMoreInteractions(listener);
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index f1c1dc3..59f4d56b 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
@@ -315,7 +316,7 @@
                                 mFakeBtDevice.getAddress()));
                 verify(mMockAudioService,
                         timeout(MAX_MESSAGE_HANDLING_DELAY_MS).times(0)).onUpdatedAdiDeviceState(
-                        eq(devState));
+                        eq(devState), anyBoolean());
             }
 
             // metadata set
@@ -326,7 +327,7 @@
                                 mFakeBtDevice.getAddress()));
                 verify(mMockAudioService,
                         timeout(MAX_MESSAGE_HANDLING_DELAY_MS)).onUpdatedAdiDeviceState(
-                        any());
+                        any(), anyBoolean());
             }
         } finally {
             // reset the metadata device type
@@ -354,7 +355,7 @@
         verify(mMockAudioService,
                 timeout(MAX_MESSAGE_HANDLING_DELAY_MS).atLeast(1)).onUpdatedAdiDeviceState(
                 ArgumentMatchers.argThat(devState -> devState.getAudioDeviceCategory()
-                        == AudioManager.AUDIO_DEVICE_CATEGORY_OTHER));
+                        == AudioManager.AUDIO_DEVICE_CATEGORY_OTHER), anyBoolean());
     }
 
     private void doTestConnectionDisconnectionReconnection(int delayAfterDisconnection,
diff --git a/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
index 472a82c..d5638e9 100644
--- a/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
@@ -57,8 +57,9 @@
 
     private ResolveInfo mResolveInfo1 = new ResolveInfo();
     private ResolveInfo mResolveInfo2 = new ResolveInfo();
-    private final String mTestPkg1 = "testPkg1", mTestPkg2 = "testPkg2", mTestPkg3 = "testPkg3";
-    private final String mMusicFxPkgName = "com.android.musicfx";
+    private final String mTestPkg1 = new String("testPkg1"), mTestPkg2 = new String("testPkg2"),
+            mTestPkg3 = new String("testPkg3"), mTestPkg1Equivalent = new String("testPkg1");
+    private final String mMusicFxPkgName = new String("com.android.musicfx");
     private final int mTestUid1 = 1, mTestUid2 = 2, mTestUid3 = 3, mMusicFxUid = 78;
     private final int mTestSession1 = 11, mTestSession2 = 22, mTestSession3 = 33;
 
@@ -191,7 +192,8 @@
     public void testCloseBroadcastIntent() {
         Log.i(TAG, "running testCloseBroadcastIntent");
 
-        closeSessionWithResList(null, 0, 0, null, mTestSession1, mTestUid1);
+        closeSessionWithResList(null, 0 /* unbind */, 0 /* broadcast */, null /* packageName */,
+                mTestSession1, mTestUid1);
     }
 
     /**
@@ -225,8 +227,10 @@
     public void testBroadcastIntentWithNoPackageAndNoBroadcastReceiver() {
         Log.i(TAG, "running testBroadcastIntentWithNoPackageAndNoBroadcastReceiver");
 
-        openSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
-        closeSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
+        openSessionWithResList(mEmptyList, 0 /* bind */, 0 /* broadcast */, null /* packageName */,
+                mTestSession1, mTestUid1);
+        closeSessionWithResList(mEmptyList, 0 /* unbind */, 0 /* broadcast */,
+                null /* packageName */, mTestSession1, mTestUid1);
     }
 
     /**
@@ -236,26 +240,10 @@
     public void testBroadcastIntentWithNoPackageAndOneBroadcastReceiver() {
         Log.i(TAG, "running testBroadcastIntentWithNoPackageAndOneBroadcastReceiver");
 
-        int broadcasts = 1, bind = 1, unbind = 1;
-        openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid1);
-        broadcasts = broadcasts + 1;
-        closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid1);
-
-        // repeat with different session ID
-        broadcasts = broadcasts + 1;
-        bind = bind + 1;
-        unbind = unbind + 1;
-        openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession2, mTestUid1);
-        broadcasts = broadcasts + 1;
-        closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession2, mTestUid1);
-
-        // repeat with different UID
-        broadcasts = broadcasts + 1;
-        bind = bind + 1;
-        unbind = unbind + 1;
-        openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid2);
-        broadcasts = broadcasts + 1;
-        closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid2);
+        openSessionWithResList(mSingleList, 0 /* bind */, 0 /* broadcast */,
+                null /* packageName */, mTestSession1, mTestUid1);
+        closeSessionWithResList(mSingleList, 0 /* unbind */, 0 /* broadcast */,
+                null /* packageName */, mTestSession1, mTestUid1);
     }
 
     /**
@@ -265,8 +253,50 @@
     public void testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers() {
         Log.i(TAG, "running testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers");
 
-        openSessionWithResList(mDoubleList, 1, 1, null, mTestSession1, mTestUid1);
-        closeSessionWithResList(mDoubleList, 1, 2, null, mTestSession1, mTestUid1);
+        openSessionWithResList(mDoubleList, 0 /* bind */, 0 /* broadcast */,
+                null /* packageName */, mTestSession1, mTestUid1);
+        closeSessionWithResList(mDoubleList, 0 /* bind */, 0 /* broadcast */,
+                null /* packageName */, mTestSession1, mTestUid1);
+    }
+
+    @Test
+    public void testBroadcastIntentWithPackageAndOneBroadcastReceiver() {
+        Log.i(TAG, "running testBroadcastIntentWithPackageAndOneBroadcastReceiver");
+
+        int broadcasts = 1, bind = 1, unbind = 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                mTestUid1);
+
+        // repeat with different session ID
+        broadcasts = broadcasts + 1;
+        bind = bind + 1;
+        unbind = unbind + 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid1);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+                mTestUid1);
+
+        // repeat with different UID
+        broadcasts = broadcasts + 1;
+        bind = bind + 1;
+        unbind = unbind + 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid2);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg3, mTestSession1,
+                mTestUid2);
+    }
+
+    @Test
+    public void testBroadcastIntentWithPackageAndTwoBroadcastReceivers() {
+        Log.i(TAG, "running testBroadcastIntentWithPackageAndTwoBroadcastReceivers");
+
+        openSessionWithResList(mDoubleList, 1 /* bind */, 1 /* broadcast */,
+                mTestPkg1 /* packageName */, mTestSession1, mTestUid1);
+        closeSessionWithResList(mDoubleList, 1 /* unbind */, 2 /* broadcast */,
+                mTestPkg1 /* packageName */, mTestSession1, mTestUid1);
     }
 
     /**
@@ -639,4 +669,18 @@
         unbind = unbind + 1;
         sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid3, unbind, broadcasts);
     }
+
+    /**
+     * Test audio session open/close with same package name value but different String object.
+     */
+    @Test
+    public void testSessionOpenCloseWithSamePackageNameValueButDiffObject() {
+        Log.i(TAG, "running testSessionOpenCloseWithSamePackageNameValueButDiffObject");
+        int broadcasts = 1;
+        openSessionWithResList(mSingleList, 1 /* bind */, broadcasts, mTestPkg1, mTestSession1,
+                mTestUid1);
+        closeSessionWithResList(mSingleList, 1 /* unbind */, broadcasts + 1, mTestPkg1Equivalent,
+                mTestSession1, mTestUid1);
+    }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 7e04277..3dc375c 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -16,16 +16,14 @@
 
 package com.android.server.biometrics;
 
-import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS;
 import static android.Manifest.permission.MANAGE_BIOMETRIC;
 import static android.Manifest.permission.TEST_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
+import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
 
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
-
 import static junit.framework.Assert.assertEquals;
 
 import static org.junit.Assert.assertThrows;
@@ -65,8 +63,6 @@
 import android.os.UserHandle;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -204,43 +200,7 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(com.android.server.biometrics.Flags.FLAG_DE_HIDL)
-    public void testRegisterAuthenticator_registerAuthenticators() throws Exception {
-        final int fingerprintId = 0;
-        final int fingerprintStrength = 15;
-
-        final int faceId = 1;
-        final int faceStrength = 15;
-
-        final String[] config = {
-                // ID0:Fingerprint:Strong
-                String.format("%d:2:%d", fingerprintId, fingerprintStrength),
-                // ID2:Face:Convenience
-                String.format("%d:8:%d", faceId, faceStrength)
-        };
-
-        when(mInjector.getConfiguration(any())).thenReturn(config);
-
-        mAuthService = new AuthService(mContext, mInjector);
-        mAuthService.onStart();
-
-        verify(mFingerprintService).registerAuthenticators(mFingerprintPropsCaptor.capture());
-        final FingerprintSensorPropertiesInternal fingerprintProp =
-                mFingerprintPropsCaptor.getValue().get(0);
-        assertEquals(fingerprintProp.sensorId, fingerprintId);
-        assertEquals(fingerprintProp.sensorStrength,
-                Utils.authenticatorStrengthToPropertyStrength(fingerprintStrength));
-
-        verify(mFaceService).registerAuthenticators(mFacePropsCaptor.capture());
-        final FaceSensorPropertiesInternal faceProp = mFacePropsCaptor.getValue().get(0);
-        assertEquals(faceProp.sensorId, faceId);
-        assertEquals(faceProp.sensorStrength,
-                Utils.authenticatorStrengthToPropertyStrength(faceStrength));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(com.android.server.biometrics.Flags.FLAG_DE_HIDL)
-    public void testRegisterAuthenticator_registerAuthenticatorsLegacy() throws RemoteException {
+    public void testRegisterAuthenticator_registerAuthenticators() throws RemoteException {
         final int fingerprintId = 0;
         final int fingerprintStrength = 15;
 
@@ -265,7 +225,7 @@
         mFingerprintLooper.dispatchAll();
         mFaceLooper.dispatchAll();
 
-        verify(mFingerprintService).registerAuthenticatorsLegacy(
+        verify(mFingerprintService).registerAuthenticators(
                 mFingerprintSensorConfigurationsCaptor.capture());
 
         final SensorProps[] fingerprintProp = mFingerprintSensorConfigurationsCaptor.getValue()
@@ -275,8 +235,7 @@
         assertEquals(fingerprintProp[0].commonProps.sensorStrength,
                 Utils.authenticatorStrengthToPropertyStrength(fingerprintStrength));
 
-        verify(mFaceService).registerAuthenticatorsLegacy(
-                mFaceSensorConfigurationsCaptor.capture());
+        verify(mFaceService).registerAuthenticators(mFaceSensorConfigurationsCaptor.capture());
 
         final android.hardware.biometrics.face.SensorProps[] faceProp =
                 mFaceSensorConfigurationsCaptor.getValue()
@@ -491,7 +450,6 @@
     @Test
     public void testRegisterAuthenticationStateListener_callsFingerprintService()
             throws Exception {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
 
         mAuthService = new AuthService(mContext, mInjector);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 74eb79d..48f1286 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -25,6 +25,7 @@
 
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED;
+import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED;
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING;
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI;
 
@@ -68,7 +69,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.security.KeyStore;
+import android.security.KeyStoreAuthorization;
 
 import androidx.test.filters.SmallTest;
 
@@ -105,7 +106,7 @@
     @Mock private IBiometricServiceReceiver mClientReceiver;
     @Mock private IStatusBarService mStatusBarService;
     @Mock private IBiometricSysuiReceiver mSysuiReceiver;
-    @Mock private KeyStore mKeyStore;
+    @Mock private KeyStoreAuthorization mKeyStoreAuthorization;
     @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver;
     @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
     @Mock private BiometricCameraManager mBiometricCameraManager;
@@ -289,6 +290,44 @@
     }
 
     @Test
+    public void testOnRejectionReceivedBeforeOnDialogAnimatedIn() throws RemoteException {
+        final int fingerprintId = 0;
+        final int faceId = 1;
+        setupFingerprint(fingerprintId, FingerprintSensorProperties.TYPE_REAR);
+        setupFace(faceId, false /* confirmationAlwaysRequired */,
+                mock(IBiometricAuthenticator.class));
+        final AuthSession session = createAuthSession(mSensors,
+                false /* checkDevicePolicyManager */,
+                Authenticators.BIOMETRIC_STRONG,
+                TEST_REQUEST_ID,
+                0 /* operationId */,
+                0 /* userId */);
+        session.goToInitialState();
+
+        for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
+            assertThat(sensor.getSensorState()).isEqualTo(BiometricSensor.STATE_WAITING_FOR_COOKIE);
+            session.onCookieReceived(
+                    session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
+        }
+        assertThat(session.allCookiesReceived()).isTrue();
+        assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED);
+
+        final BiometricSensor faceSensor = session.mPreAuthInfo.eligibleSensors.get(faceId);
+        final BiometricSensor fingerprintSensor = session.mPreAuthInfo.eligibleSensors.get(
+                fingerprintId);
+        session.onAuthenticationRejected(faceId);
+
+        assertThat(faceSensor.getSensorState()).isEqualTo(BiometricSensor.STATE_CANCELING);
+        assertThat(session.getState()).isEqualTo(STATE_AUTH_PAUSED);
+
+        session.onDialogAnimatedIn(true);
+
+        assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED_UI_SHOWING);
+        assertThat(fingerprintSensor.getSensorState()).isEqualTo(
+                BiometricSensor.STATE_AUTHENTICATING);
+    }
+
+    @Test
     public void testCancelReducesAppetiteForCookies() throws Exception {
         setupFace(0 /* id */, false /* confirmationAlwaysRequired */,
                 mock(IBiometricAuthenticator.class));
@@ -665,9 +704,10 @@
         final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo,
                 checkDevicePolicyManager);
         return new AuthSession(mContext, mBiometricContext, mStatusBarService, mSysuiReceiver,
-                mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, mToken, requestId,
-                operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE, promptInfo,
-                false /* debugEnabled */, mFingerprintSensorProps, mBiometricFrameworkStatsLogger);
+                mKeyStoreAuthorization, mRandom, mClientDeathReceiver, preAuthInfo, mToken,
+                requestId, operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE,
+                promptInfo, false /* debugEnabled */, mFingerprintSensorProps,
+                mBiometricFrameworkStatsLogger);
     }
 
     private PromptInfo createPromptInfo(@Authenticators.Types int authenticators) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index a852677..503ab8e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -76,14 +76,12 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.authorization.IKeystoreAuthorization;
+import android.security.KeyStoreAuthorization;
 import android.service.gatekeeper.IGateKeeperService;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -91,7 +89,6 @@
 import android.view.DisplayInfo;
 import android.view.WindowManager;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
@@ -182,7 +179,7 @@
     private BiometricHandlerProvider mBiometricHandlerProvider;
 
     @Mock
-    private IKeystoreAuthorization mKeystoreAuthService;
+    private KeyStoreAuthorization mKeyStoreAuthorization;
 
     @Mock
     private IGateKeeperService mGateKeeperService;
@@ -207,7 +204,7 @@
         when(mInjector.getStatusBarService()).thenReturn(mock(IStatusBarService.class));
         when(mInjector.getSettingObserver(any(), any(), any()))
                 .thenReturn(mock(BiometricService.SettingObserver.class));
-        when(mInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
+        when(mInjector.getKeyStoreAuthorization()).thenReturn(mock(KeyStoreAuthorization.class));
         when(mInjector.isDebugEnabled(any(), anyInt())).thenReturn(false);
         when(mInjector.getBiometricStrengthController(any()))
                 .thenReturn(mock(BiometricStrengthController.class));
@@ -243,18 +240,12 @@
                 mStatusBarService, null /* handler */,
                 mAuthSessionCoordinator);
         when(mInjector.getBiometricContext(any())).thenReturn(mBiometricContextProvider);
-        when(mInjector.getKeystoreAuthorizationService()).thenReturn(mKeystoreAuthService);
+        when(mInjector.getKeyStoreAuthorization()).thenReturn(mKeyStoreAuthorization);
         when(mInjector.getGateKeeperService()).thenReturn(mGateKeeperService);
         when(mInjector.getNotificationLogger()).thenReturn(mNotificationLogger);
         when(mGateKeeperService.getSecureUserId(anyInt())).thenReturn(42L);
-
-        if (com.android.server.biometrics.Flags.deHidl()) {
-            when(mBiometricHandlerProvider.getBiometricCallbackHandler()).thenReturn(
-                    new Handler(TestableLooper.get(this).getLooper()));
-        } else {
-            when(mBiometricHandlerProvider.getBiometricCallbackHandler()).thenReturn(
-                    new Handler(Looper.getMainLooper()));
-        }
+        when(mBiometricHandlerProvider.getBiometricCallbackHandler()).thenReturn(
+                new Handler(TestableLooper.get(this).getLooper()));
 
         final String[] config = {
                 "0:2:15",  // ID0:Fingerprint:Strong
@@ -682,9 +673,9 @@
         waitForIdle();
         // HAT sent to keystore
         if (isStrongBiometric) {
-            verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT));
+            verify(mKeyStoreAuthorization).addAuthToken(AdditionalMatchers.aryEq(HAT));
         } else {
-            verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+            verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
         }
         // Send onAuthenticated to client
         verify(mReceiver1).onAuthenticationSucceeded(
@@ -747,7 +738,7 @@
         waitForIdle();
         // Waiting for SystemUI to send confirmation callback
         assertEquals(STATE_AUTH_PENDING_CONFIRM, mBiometricService.mAuthSession.getState());
-        verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+        verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
 
         // SystemUI sends confirm, HAT is sent to keystore and client is notified.
         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
@@ -755,9 +746,9 @@
                 null /* credentialAttestation */);
         waitForIdle();
         if (isStrongBiometric) {
-            verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT));
+            verify(mKeyStoreAuthorization).addAuthToken(AdditionalMatchers.aryEq(HAT));
         } else {
-            verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+            verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
         }
         verify(mReceiver1).onAuthenticationSucceeded(
                 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
@@ -1313,7 +1304,7 @@
                 eq(TYPE_FACE),
                 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
                 eq(0 /* vendorCode */));
-        verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+        verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
         assertNull(mBiometricService.mAuthSession);
     }
 
@@ -1839,7 +1830,7 @@
 
         final long expectedResult = 31337L;
 
-        when(mKeystoreAuthService.getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators)))
+        when(mKeyStoreAuthorization.getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators)))
                 .thenReturn(expectedResult);
 
         mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
@@ -1848,7 +1839,8 @@
                 Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL);
 
         assertEquals(expectedResult, result);
-        verify(mKeystoreAuthService).getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators));
+        verify(mKeyStoreAuthorization).getLastAuthTime(eq(secureUserId),
+                eq(hardwareAuthenticators));
     }
 
     // Helper methods
@@ -2037,11 +2029,7 @@
     }
 
     private void waitForIdle() {
-        if (com.android.server.biometrics.Flags.deHidl()) {
-            TestableLooper.get(this).processAllMessages();
-        } else {
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        }
+        TestableLooper.get(this).processAllMessages();
     }
 
     private byte[] generateRandomHAT() {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
index c7300bb..960357f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -87,8 +87,12 @@
     private ISessionListener mSessionListener;
     @Mock
     private WindowManager mWindowManager;
+    @Mock
+    private Consumer<OperationContext> mStartHalConsumer;
 
-    private OperationContextExt mOpContext = new OperationContextExt(true);
+    private final FingerprintAuthenticateOptions mAuthenticateOptions =
+            new FingerprintAuthenticateOptions.Builder().build();
+    private final OperationContextExt mOpContext = new OperationContextExt(true);
     private IBiometricContextListener mListener;
     private BiometricContextProvider mProvider;
 
@@ -200,11 +204,11 @@
         final List<Integer> actual = new ArrayList<>();
         final List<Integer> expected = List.of(FoldState.FULLY_CLOSED, FoldState.FULLY_OPENED,
                 FoldState.UNKNOWN, FoldState.HALF_OPENED);
-        mProvider.subscribe(mOpContext, ctx -> {
+        mProvider.subscribe(mOpContext, mStartHalConsumer, ctx -> {
             assertThat(ctx).isSameInstanceAs(mOpContext.toAidlContext());
             assertThat(mProvider.getFoldState()).isEqualTo(ctx.foldState);
             actual.add(ctx.foldState);
-        });
+        }, mAuthenticateOptions);
 
         for (int v : expected) {
             mListener.onFoldChanged(v);
@@ -228,11 +232,11 @@
                 AuthenticateOptions.DISPLAY_STATE_NO_UI,
                 AuthenticateOptions.DISPLAY_STATE_LOCKSCREEN);
 
-        mProvider.subscribe(mOpContext, ctx -> {
+        mProvider.subscribe(mOpContext, mStartHalConsumer, ctx -> {
             assertThat(ctx).isSameInstanceAs(mOpContext.toAidlContext());
             assertThat(mProvider.getDisplayState()).isEqualTo(ctx.displayState);
             actual.add(ctx.displayState);
-        });
+        }, mAuthenticateOptions);
 
         for (int v : expected) {
             mListener.onDisplayStateChanged(v);
@@ -250,11 +254,11 @@
     public void testSubscribesToAod() throws RemoteException {
         final List<Boolean> actual = new ArrayList<>();
 
-        mProvider.subscribe(mOpContext, ctx -> {
+        mProvider.subscribe(mOpContext, mStartHalConsumer, ctx -> {
             assertThat(ctx).isSameInstanceAs(mOpContext.toAidlContext());
             assertThat(mProvider.isAod()).isEqualTo(ctx.isAod);
             actual.add(ctx.isAod);
-        });
+        }, mAuthenticateOptions);
 
         for (int v : List.of(
                 AuthenticateOptions.DISPLAY_STATE_AOD,
@@ -273,10 +277,10 @@
     public void testSubscribesToAwake() throws RemoteException {
         final List<Boolean> actual = new ArrayList<>();
 
-        mProvider.subscribe(mOpContext, ctx -> {
+        mProvider.subscribe(mOpContext, mStartHalConsumer, ctx -> {
             assertThat(ctx).isSameInstanceAs(mOpContext.toAidlContext());
             actual.add(mProvider.isAwake());
-        });
+        }, mAuthenticateOptions);
 
         for (int v : List.of(
                 AuthenticateOptions.DISPLAY_STATE_LOCKSCREEN,
@@ -295,14 +299,15 @@
     public void testSubscribesWithDifferentState() throws RemoteException {
         final Consumer<OperationContext> nonEmptyConsumer = mock(Consumer.class);
         mListener.onDisplayStateChanged(AuthenticateOptions.DISPLAY_STATE_AOD);
-        mProvider.subscribe(mOpContext, nonEmptyConsumer);
-        verify(nonEmptyConsumer).accept(same(mOpContext.toAidlContext()));
+        mProvider.subscribe(mOpContext, mStartHalConsumer, nonEmptyConsumer, mAuthenticateOptions);
+
+        assertThat(mOpContext.getDisplayState()).isEqualTo(AuthenticateOptions.DISPLAY_STATE_AOD);
     }
 
     @Test
     public void testUnsubscribes() throws RemoteException {
         final Consumer<OperationContext> emptyConsumer = mock(Consumer.class);
-        mProvider.subscribe(mOpContext, emptyConsumer);
+        mProvider.subscribe(mOpContext, mStartHalConsumer, emptyConsumer, mAuthenticateOptions);
         mProvider.unsubscribe(mOpContext);
 
         mListener.onDisplayStateChanged(AuthenticateOptions.DISPLAY_STATE_AOD);
@@ -311,7 +316,7 @@
         mListener.onDisplayStateChanged(AuthenticateOptions.DISPLAY_STATE_UNKNOWN);
 
         final Consumer<OperationContext> nonEmptyConsumer = mock(Consumer.class);
-        mProvider.subscribe(mOpContext, nonEmptyConsumer);
+        mProvider.subscribe(mOpContext, mStartHalConsumer, nonEmptyConsumer, mAuthenticateOptions);
         mListener.onDisplayStateChanged(AuthenticateOptions.DISPLAY_STATE_LOCKSCREEN);
         mProvider.unsubscribe(mOpContext);
         mListener.onDisplayStateChanged(AuthenticateOptions.DISPLAY_STATE_NO_UI);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 971323a..fc573d2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -52,13 +52,12 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableContext;
-import android.testing.TestableLooper;
 import android.util.Slog;
 
 import androidx.annotation.NonNull;
@@ -66,7 +65,6 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.nano.BiometricSchedulerProto;
@@ -79,7 +77,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -90,7 +89,6 @@
 @Presubmit
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
[email protected](setAsMainLooper = true)
 public class BiometricSchedulerTest {
 
     private static final String TAG = "BiometricSchedulerTest";
@@ -105,6 +103,9 @@
     @Rule
     public final CheckFlagsRule mCheckFlagsRule =
             DeviceFlagsValueProvider.createCheckFlagsRule();
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
     private BiometricScheduler<IFingerprint, ISession> mScheduler;
     private IBinder mToken;
     private int mCurrentUserId = UserHandle.USER_SYSTEM;
@@ -121,8 +122,10 @@
                 mUsersStoppedCount++;
                 mCurrentUserId = UserHandle.USER_NULL;
             };
+    private TestLooper mLooper;
     private boolean mStartOperationsFinish = true;
     private int mStartUserClientCount = 0;
+
     @Mock
     private IBiometricService mBiometricService;
     @Mock
@@ -140,44 +143,39 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mToken = new Binder();
+        mLooper = new TestLooper();
+
         when(mAuthSessionCoordinator.getLockoutStateFor(anyInt(), anyInt())).thenReturn(
                 BIOMETRIC_SUCCESS);
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
-        if (Flags.deHidl()) {
-            mScheduler = new BiometricScheduler<>(
-                    new Handler(TestableLooper.get(this).getLooper()),
-                    BiometricScheduler.SENSOR_TYPE_UNKNOWN,
-                    null /* gestureAvailabilityDispatcher */,
-                    mBiometricService,
-                    LOG_NUM_RECENT_OPERATIONS,
-                    () -> mCurrentUserId,
-                    new UserSwitchProvider<IFingerprint, ISession>() {
-                        @NonNull
-                        @Override
-                        public StopUserClient<ISession> getStopUserClient(int userId) {
-                            return new TestStopUserClient(mContext, () -> mSession, mToken, userId,
-                                    TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
-                                    mUserStoppedCallback, () -> mShouldFailStopUser);
-                        }
 
-                        @NonNull
-                        @Override
-                        public StartUserClient<IFingerprint, ISession> getStartUserClient(
-                                int newUserId) {
-                            mStartUserClientCount++;
-                            return new TestStartUserClient(mContext, () -> mFingerprint, mToken,
-                                    newUserId, TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
-                                    mUserStartedCallback, mStartOperationsFinish);
-                        }
-                    });
-        } else {
-            mScheduler = new BiometricScheduler<>(
-                    new Handler(TestableLooper.get(this).getLooper()),
-                    BiometricScheduler.SENSOR_TYPE_UNKNOWN, null /* gestureAvailabilityTracker */,
-                    mBiometricService, LOG_NUM_RECENT_OPERATIONS);
-        }
+        mScheduler = new BiometricScheduler<>(
+                new Handler(mLooper.getLooper()),
+                BiometricScheduler.SENSOR_TYPE_UNKNOWN,
+                null /* gestureAvailabilityDispatcher */,
+                mBiometricService,
+                LOG_NUM_RECENT_OPERATIONS,
+                () -> mCurrentUserId,
+                new UserSwitchProvider<IFingerprint, ISession>() {
+                    @NonNull
+                    @Override
+                    public StopUserClient<ISession> getStopUserClient(int userId) {
+                        return new TestStopUserClient(mContext, () -> mSession, mToken, userId,
+                                TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
+                                mUserStoppedCallback, () -> mShouldFailStopUser);
+                    }
+
+                    @NonNull
+                    @Override
+                    public StartUserClient<IFingerprint, ISession> getStartUserClient(
+                            int newUserId) {
+                        mStartUserClientCount++;
+                        return new TestStartUserClient(mContext, () -> mFingerprint, mToken,
+                                newUserId, TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
+                                mUserStartedCallback, mStartOperationsFinish);
+                    }
+                });
     }
 
     @Test
@@ -657,7 +655,6 @@
     @Test
     public void testClearBiometricQueue_clearsHungAuthOperation() {
         // Creating a hung client
-        final TestableLooper looper = TestableLooper.get(this);
         final Supplier<Object> lazyDaemon1 = () -> mock(Object.class);
         final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext,
                 lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */,
@@ -676,9 +673,9 @@
         assertNotNull(mScheduler.mCurrentOperation);
         assertEquals(0, mScheduler.getCurrentPendingCount());
 
-        looper.moveTimeForward(10000);
+        mLooper.moveTimeForward(10000);
         waitForIdle();
-        looper.moveTimeForward(3000);
+        mLooper.moveTimeForward(3000);
         waitForIdle();
 
         // The hung client did not honor this operation, verify onError and authenticated
@@ -693,7 +690,6 @@
     @Test
     public void testAuthWorks_afterClearBiometricQueue() {
         // Creating a hung client
-        final TestableLooper looper = TestableLooper.get(this);
         final Supplier<Object> lazyDaemon1 = () -> mock(Object.class);
         final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext,
                 lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */,
@@ -714,10 +710,10 @@
         waitForIdle();
 
         // The watchdog should kick off the cancellation
-        looper.moveTimeForward(10000);
+        mLooper.moveTimeForward(10000);
         waitForIdle();
         // After 10 seconds the HAL has 3 seconds to respond to a cancel
-        looper.moveTimeForward(3000);
+        mLooper.moveTimeForward(3000);
         waitForIdle();
 
         // The hung client did not honor this operation, verify onError and authenticated
@@ -752,10 +748,10 @@
         client2.getCallback().onClientFinished(client2, true);
         waitForIdle();
 
-        looper.moveTimeForward(10000);
+        mLooper.moveTimeForward(10000);
         waitForIdle();
         // After 10 seconds the HAL has 3 seconds to respond to a cancel
-        looper.moveTimeForward(3000);
+        mLooper.moveTimeForward(3000);
         waitForIdle();
 
         //Asserting auth client passes
@@ -766,7 +762,6 @@
     @Test
     public void testClearBiometricQueue_doesNotClearOperationsWhenQueueNotStuck() {
         //Creating clients
-        final TestableLooper looper = TestableLooper.get(this);
         final Supplier<Object> lazyDaemon1 = () -> mock(Object.class);
         final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext,
                 lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */,
@@ -793,10 +788,10 @@
         waitForIdle();
 
         // The watchdog should kick off the cancellation
-        looper.moveTimeForward(10000);
+        mLooper.moveTimeForward(10000);
         waitForIdle();
         // After 10 seconds the HAL has 3 seconds to respond to a cancel
-        looper.moveTimeForward(3000);
+        mLooper.moveTimeForward(3000);
         waitForIdle();
 
         //Watchdog does not clear pending operations
@@ -855,7 +850,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testScheduleOperation_whenNoUser() {
         mCurrentUserId = UserHandle.USER_NULL;
 
@@ -871,7 +865,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testScheduleOperation_whenNoUser_notStarted() {
         mCurrentUserId = UserHandle.USER_NULL;
         mStartOperationsFinish = false;
@@ -896,7 +889,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testScheduleOperation_whenNoUser_notStarted_andReset() {
         mCurrentUserId = UserHandle.USER_NULL;
         mStartOperationsFinish = false;
@@ -923,7 +915,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testScheduleOperation_whenSameUser() {
         mCurrentUserId = 10;
 
@@ -940,7 +931,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testScheduleOperation_whenDifferentUser() {
         mCurrentUserId = 10;
 
@@ -961,7 +951,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testStartUser_alwaysStartsNextOperation() {
         mCurrentUserId = UserHandle.USER_NULL;
 
@@ -990,7 +979,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testStartUser_failsClearsStopUserClient() {
         mCurrentUserId = UserHandle.USER_NULL;
 
@@ -1033,7 +1021,7 @@
     }
 
     private void waitForIdle() {
-        TestableLooper.get(this).processAllMessages();
+        mLooper.dispatchAll();
     }
 
     private static class TestAuthenticateOptions implements AuthenticateOptions {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
index 74f8f08..d6eadf2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
@@ -16,8 +16,6 @@
 
 package com.android.server.biometrics.sensors;
 
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -26,7 +24,6 @@
 import static org.mockito.Mockito.when;
 
 import android.hardware.biometrics.BiometricRequestConstants;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -52,21 +49,18 @@
     private static final long REQUEST_ID = 8;
 
     @Rule public final MockitoRule mockito = MockitoJUnit.rule();
-
     @Mock private IUdfpsOverlayController mUdfpsOverlayController;
-    @Mock private ISidefpsController mSidefpsController;
     @Mock private AcquisitionClient<?> mAcquisitionClient;
 
     @Before
     public void setup() {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         when(mAcquisitionClient.getRequestId()).thenReturn(REQUEST_ID);
         when(mAcquisitionClient.hasRequestId()).thenReturn(true);
     }
 
     @Test
     public void noopWhenBothNull() {
-        final SensorOverlays useless = new SensorOverlays(null, null);
+        final SensorOverlays useless = new SensorOverlays(null);
         useless.show(SENSOR_ID, 2, null);
         useless.hide(SENSOR_ID);
     }
@@ -74,34 +68,24 @@
     @Test
     public void testProvidesUdfps() {
         final List<IUdfpsOverlayController> udfps = new ArrayList<>();
-        SensorOverlays sensorOverlays = new SensorOverlays(null, mSidefpsController);
+        SensorOverlays sensorOverlays = new SensorOverlays(null);
 
         sensorOverlays.ifUdfps(udfps::add);
         assertThat(udfps).isEmpty();
 
-        sensorOverlays = new SensorOverlays(mUdfpsOverlayController, mSidefpsController);
+        sensorOverlays = new SensorOverlays(mUdfpsOverlayController);
         sensorOverlays.ifUdfps(udfps::add);
         assertThat(udfps).containsExactly(mUdfpsOverlayController);
     }
 
     @Test
-    public void testShow() throws Exception {
-        testShow(mUdfpsOverlayController, mSidefpsController);
-    }
-
-    @Test
     public void testShowUdfps() throws Exception {
-        testShow(mUdfpsOverlayController, null);
+        testShow(mUdfpsOverlayController);
     }
 
-    @Test
-    public void testShowSidefps() throws Exception {
-        testShow(null, mSidefpsController);
-    }
-
-    private void testShow(IUdfpsOverlayController udfps, ISidefpsController sidefps)
+    private void testShow(IUdfpsOverlayController udfps)
             throws Exception {
-        final SensorOverlays sensorOverlays = new SensorOverlays(udfps, sidefps);
+        final SensorOverlays sensorOverlays = new SensorOverlays(udfps);
         final int reason = BiometricRequestConstants.REASON_UNKNOWN;
         sensorOverlays.show(SENSOR_ID, reason, mAcquisitionClient);
 
@@ -109,36 +93,20 @@
             verify(mUdfpsOverlayController).showUdfpsOverlay(
                     eq(REQUEST_ID), eq(SENSOR_ID), eq(reason), any());
         }
-        if (sidefps != null) {
-            verify(mSidefpsController).show(eq(SENSOR_ID), eq(reason));
-        }
-    }
-
-    @Test
-    public void testHide() throws Exception {
-        testHide(mUdfpsOverlayController, mSidefpsController);
     }
 
     @Test
     public void testHideUdfps() throws Exception {
-        testHide(mUdfpsOverlayController, null);
+        testHide(mUdfpsOverlayController);
     }
 
-    @Test
-    public void testHideSidefps() throws Exception {
-        testHide(null, mSidefpsController);
-    }
-
-    private void testHide(IUdfpsOverlayController udfps, ISidefpsController sidefps)
+    private void testHide(IUdfpsOverlayController udfps)
             throws Exception {
-        final SensorOverlays sensorOverlays = new SensorOverlays(udfps, sidefps);
+        final SensorOverlays sensorOverlays = new SensorOverlays(udfps);
         sensorOverlays.hide(SENSOR_ID);
 
         if (udfps != null) {
             verify(mUdfpsOverlayController).hideUdfpsOverlay(eq(SENSOR_ID));
         }
-        if (sidefps != null) {
-            verify(mSidefpsController).hide(eq(SENSOR_ID));
-        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
deleted file mode 100644
index dd5d826..0000000
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
+++ /dev/null
@@ -1,393 +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.biometrics.sensors;
-
-import static android.testing.TestableLooper.RunWithLooper;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.biometrics.IBiometricService;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.UserHandle;
-import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.SmallTest;
-
-import com.android.server.biometrics.Flags;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Supplier;
-
-@Presubmit
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-@SmallTest
-public class UserAwareBiometricSchedulerTest {
-
-    private static final String TAG = "UserAwareBiometricSchedulerTest";
-    private static final int TEST_SENSOR_ID = 0;
-
-    @Rule
-    public final MockitoRule mockito = MockitoJUnit.rule();
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
-
-    private Handler mHandler;
-    private UserAwareBiometricScheduler mScheduler;
-    private final IBinder mToken = new Binder();
-
-    @Mock
-    private Context mContext;
-    @Mock
-    private IBiometricService mBiometricService;
-    @Mock
-    private BiometricLogger mBiometricLogger;
-    @Mock
-    private BiometricContext mBiometricContext;
-
-    private boolean mShouldFailStopUser = false;
-    private final StopUserClientShouldFail mStopUserClientShouldFail =
-            () -> {
-                return mShouldFailStopUser;
-            };
-    private final TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback();
-    private final TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback();
-    private int mCurrentUserId = UserHandle.USER_NULL;
-    private boolean mStartOperationsFinish = true;
-    private int mStartUserClientCount = 0;
-
-    @Before
-    public void setUp() {
-        mShouldFailStopUser = false;
-        mHandler = new Handler(TestableLooper.get(this).getLooper());
-        mScheduler = new UserAwareBiometricScheduler(TAG,
-                mHandler,
-                BiometricScheduler.SENSOR_TYPE_UNKNOWN,
-                null /* gestureAvailabilityDispatcher */,
-                mBiometricService,
-                () -> mCurrentUserId,
-                new UserAwareBiometricScheduler.UserSwitchCallback() {
-                    @NonNull
-                    @Override
-                    public StopUserClient<?> getStopUserClient(int userId) {
-                        return new TestStopUserClient(mContext, Object::new, mToken, userId,
-                                TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
-                                mUserStoppedCallback, mStopUserClientShouldFail);
-                    }
-
-                    @NonNull
-                    @Override
-                    public StartUserClient<?, ?> getStartUserClient(int newUserId) {
-                        mStartUserClientCount++;
-                        return new TestStartUserClient(mContext, Object::new, mToken, newUserId,
-                                TEST_SENSOR_ID,  mBiometricLogger, mBiometricContext,
-                                mUserStartedCallback, mStartOperationsFinish);
-                    }
-                });
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void testScheduleOperation_whenNoUser() {
-        mCurrentUserId = UserHandle.USER_NULL;
-
-        final BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(0);
-
-        mScheduler.scheduleClientMonitor(nextClient);
-        waitForIdle();
-
-        assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
-        assertThat(mUserStartedCallback.mStartedUsers).containsExactly(0);
-        verify(nextClient).start(any());
-    }
-
-    @Test
-    public void testScheduleOperation_whenNoUser_notStarted() {
-        mCurrentUserId = UserHandle.USER_NULL;
-        mStartOperationsFinish = false;
-
-        final BaseClientMonitor[] nextClients = new BaseClientMonitor[]{
-                mock(BaseClientMonitor.class),
-                mock(BaseClientMonitor.class),
-                mock(BaseClientMonitor.class)
-        };
-        for (BaseClientMonitor client : nextClients) {
-            when(client.getTargetUserId()).thenReturn(5);
-            mScheduler.scheduleClientMonitor(client);
-            waitForIdle();
-        }
-
-        assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
-        assertThat(mUserStartedCallback.mStartedUsers).isEmpty();
-        assertThat(mStartUserClientCount).isEqualTo(1);
-        for (BaseClientMonitor client : nextClients) {
-            verify(client, never()).start(any());
-        }
-    }
-
-    @Test
-    public void testScheduleOperation_whenNoUser_notStarted_andReset() {
-        mCurrentUserId = UserHandle.USER_NULL;
-        mStartOperationsFinish = false;
-
-        final BaseClientMonitor client = mock(BaseClientMonitor.class);
-        when(client.getTargetUserId()).thenReturn(5);
-        mScheduler.scheduleClientMonitor(client);
-        waitForIdle();
-
-        final TestStartUserClient startUserClient =
-                (TestStartUserClient) mScheduler.mCurrentOperation.getClientMonitor();
-        mScheduler.reset();
-        assertThat(mScheduler.mCurrentOperation).isNull();
-
-        final BiometricSchedulerOperation fakeOperation = new BiometricSchedulerOperation(
-                mock(BaseClientMonitor.class), new ClientMonitorCallback() {});
-        mScheduler.mCurrentOperation = fakeOperation;
-        startUserClient.mCallback.onClientFinished(startUserClient, true);
-        assertThat(fakeOperation).isSameInstanceAs(mScheduler.mCurrentOperation);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void testScheduleOperation_whenSameUser() {
-        mCurrentUserId = 10;
-
-        BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(mCurrentUserId);
-
-        mScheduler.scheduleClientMonitor(nextClient);
-
-        waitForIdle();
-
-        verify(nextClient).start(any());
-        assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
-        assertThat(mUserStartedCallback.mStartedUsers).isEmpty();
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void testScheduleOperation_whenDifferentUser() {
-        mCurrentUserId = 10;
-
-        final int nextUserId = 11;
-        BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(nextUserId);
-
-        mScheduler.scheduleClientMonitor(nextClient);
-
-        waitForIdle();
-        assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(1);
-
-        waitForIdle();
-        assertThat(mUserStartedCallback.mStartedUsers).containsExactly(nextUserId);
-
-        waitForIdle();
-        verify(nextClient).start(any());
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void testStartUser_alwaysStartsNextOperation() {
-        BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(10);
-
-        mScheduler.scheduleClientMonitor(nextClient);
-
-        waitForIdle();
-        verify(nextClient).start(any());
-
-        // finish first operation
-        mScheduler.getInternalCallback().onClientFinished(nextClient, true /* success */);
-        waitForIdle();
-
-        // schedule second operation but swap out the current operation
-        // before it runs so that it's not current when it's completion callback runs
-        nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(11);
-        mUserStartedCallback.mAfterStart = () -> mScheduler.mCurrentOperation = null;
-        mScheduler.scheduleClientMonitor(nextClient);
-
-        waitForIdle();
-        verify(nextClient).start(any());
-        assertThat(mUserStartedCallback.mStartedUsers).containsExactly(10, 11).inOrder();
-        assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(1);
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void testStartUser_failsClearsStopUserClient() {
-        // When a stop user client fails, check that mStopUserClient
-        // is set to null to prevent the scheduler from getting stuck.
-        BaseClientMonitor nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(10);
-
-        mScheduler.scheduleClientMonitor(nextClient);
-
-        waitForIdle();
-        verify(nextClient).start(any());
-
-        // finish first operation
-        mScheduler.getInternalCallback().onClientFinished(nextClient, true /* success */);
-        waitForIdle();
-
-        // schedule second operation but swap out the current operation
-        // before it runs so that it's not current when it's completion callback runs
-        nextClient = mock(BaseClientMonitor.class);
-        when(nextClient.getTargetUserId()).thenReturn(11);
-        mUserStartedCallback.mAfterStart = () -> mScheduler.mCurrentOperation = null;
-        mShouldFailStopUser = true;
-        mScheduler.scheduleClientMonitor(nextClient);
-
-        waitForIdle();
-        assertThat(mUserStartedCallback.mStartedUsers).containsExactly(10, 11).inOrder();
-        assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0);
-        assertThat(mScheduler.getStopUserClient()).isEqualTo(null);
-    }
-
-    private void waitForIdle() {
-        TestableLooper.get(this).processAllMessages();
-    }
-
-    private class TestUserStoppedCallback implements StopUserClient.UserStoppedCallback {
-        int mNumInvocations;
-
-        @Override
-        public void onUserStopped() {
-            mNumInvocations++;
-            mCurrentUserId = UserHandle.USER_NULL;
-        }
-    }
-
-    private class TestUserStartedCallback implements StartUserClient.UserStartedCallback<Object> {
-        final List<Integer> mStartedUsers = new ArrayList<>();
-        Runnable mAfterStart = null;
-
-        @Override
-        public void onUserStarted(int newUserId, Object newObject, int halInterfaceVersion) {
-            mStartedUsers.add(newUserId);
-            mCurrentUserId = newUserId;
-            if (mAfterStart != null) {
-                mAfterStart.run();
-            }
-        }
-    }
-
-    private interface StopUserClientShouldFail {
-        boolean shouldFail();
-    }
-
-    private class TestStopUserClient extends StopUserClient<Object> {
-        private StopUserClientShouldFail mShouldFailClient;
-        public TestStopUserClient(@NonNull Context context,
-                @NonNull Supplier<Object> lazyDaemon, @Nullable IBinder token, int userId,
-                int sensorId, @NonNull BiometricLogger logger,
-                @NonNull BiometricContext biometricContext,
-                @NonNull UserStoppedCallback callback, StopUserClientShouldFail shouldFail) {
-            super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
-            mShouldFailClient = shouldFail;
-        }
-
-        @Override
-        protected void startHalOperation() {
-
-        }
-
-        @Override
-        public void start(@NonNull ClientMonitorCallback callback) {
-            super.start(callback);
-            if (mShouldFailClient.shouldFail()) {
-                getCallback().onClientFinished(this, false /* success */);
-                // When the above fails, it means that the HAL has died, in this case we
-                // need to ensure the UserSwitchCallback correctly returns the NULL user handle.
-                mCurrentUserId = UserHandle.USER_NULL;
-            } else {
-                onUserStopped();
-            }
-        }
-
-        @Override
-        public void unableToStart() {
-
-        }
-    }
-
-    private static class TestStartUserClient extends StartUserClient<Object, Object> {
-        private final boolean mShouldFinish;
-
-        ClientMonitorCallback mCallback;
-
-        public TestStartUserClient(@NonNull Context context,
-                @NonNull Supplier<Object> lazyDaemon, @Nullable IBinder token, int userId,
-                int sensorId, @NonNull BiometricLogger logger,
-                @NonNull BiometricContext biometricContext,
-                @NonNull UserStartedCallback<Object> callback, boolean shouldFinish) {
-            super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
-            mShouldFinish = shouldFinish;
-        }
-
-        @Override
-        protected void startHalOperation() {
-
-        }
-
-        @Override
-        public void start(@NonNull ClientMonitorCallback callback) {
-            super.start(callback);
-
-            mCallback = callback;
-            if (mShouldFinish) {
-                mUserStartedCallback.onUserStarted(
-                        getTargetUserId(), new Object(), 1 /* halInterfaceVersion */);
-                callback.onClientFinished(this, true /* success */);
-            }
-        }
-
-        @Override
-        public void unableToStart() {
-
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java
index 9f3f297..1ca36a3 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java
@@ -147,11 +147,10 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
-    public void registerAuthenticatorsLegacy_defaultOnly() throws Exception {
+    public void registerAuthenticators_defaultOnly() throws Exception {
         initService();
 
-        mFaceService.mServiceWrapper.registerAuthenticatorsLegacy(mFaceSensorConfigurations);
+        mFaceService.mServiceWrapper.registerAuthenticators(mFaceSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT),
@@ -161,13 +160,13 @@
     }
 
     @Test
-    @RequiresFlagsEnabled({Flags.FLAG_DE_HIDL, Flags.FLAG_FACE_VHAL_FEATURE})
+    @RequiresFlagsEnabled(Flags.FLAG_FACE_VHAL_FEATURE)
     public void registerAuthenticatorsLegacy_virtualOnly() throws Exception {
         initService();
         Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
                 Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1);
 
-        mFaceService.mServiceWrapper.registerAuthenticatorsLegacy(mFaceSensorConfigurations);
+        mFaceService.mServiceWrapper.registerAuthenticators(mFaceSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL),
@@ -176,13 +175,27 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
-    public void registerAuthenticatorsLegacy_virtualAlwaysWhenNoOther() throws Exception {
+    @RequiresFlagsEnabled(Flags.FLAG_FACE_VHAL_FEATURE)
+    public void registerAuthenticators_virtualFaceOnly() throws Exception {
+        initService();
+        Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
+                Settings.Secure.BIOMETRIC_FACE_VIRTUAL_ENABLED, 1);
+
+        mFaceService.mServiceWrapper.registerAuthenticators(mFaceSensorConfigurations);
+        waitForRegistration();
+
+        verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL),
+                eq(BiometricAuthenticator.TYPE_FACE),
+                eq(Utils.propertyStrengthToAuthenticatorStrength(STRENGTH_STRONG)), any());
+    }
+
+    @Test
+    public void registerAuthenticators_virtualAlwaysWhenNoOther() throws Exception {
         mFaceSensorConfigurations = new FaceSensorConfigurations(false);
         mFaceSensorConfigurations.addAidlConfigs(new String[]{NAME_VIRTUAL});
         initService();
 
-        mFaceService.mServiceWrapper.registerAuthenticatorsLegacy(mFaceSensorConfigurations);
+        mFaceService.mServiceWrapper.registerAuthenticators(mFaceSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL),
@@ -195,7 +208,7 @@
         FaceAuthenticateOptions faceAuthenticateOptions = new FaceAuthenticateOptions.Builder()
                 .build();
         initService();
-        mFaceService.mServiceWrapper.registerAuthenticators(List.of());
+        mFaceService.mServiceWrapper.registerAuthenticators(mFaceSensorConfigurations);
         waitForRegistration();
 
         final long operationId = 5;
@@ -215,7 +228,7 @@
                 R.string.config_keyguardComponent,
                 OP_PACKAGE_NAME);
         initService();
-        mFaceService.mServiceWrapper.registerAuthenticators(List.of());
+        mFaceService.mServiceWrapper.registerAuthenticators(mFaceSensorConfigurations);
         waitForRegistration();
         mFaceService.mServiceWrapper.detectFace(mToken, mFaceServiceReceiver,
                 faceAuthenticateOptions);
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 84c3684..9873805 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
@@ -18,6 +18,8 @@
 
 import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
 
@@ -38,11 +40,21 @@
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricFaceConstants;
 import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 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.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.hardware.biometrics.face.ISession;
 import android.hardware.face.Face;
 import android.hardware.face.FaceAuthenticateOptions;
@@ -50,8 +62,6 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -60,7 +70,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.biometrics.Flags;
+import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
@@ -137,6 +147,22 @@
     private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mStartHalConsumerCaptor;
+    @Captor
+    private ArgumentCaptor<FaceAuthenticateOptions> mFaceAuthenticateOptionsCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationAcquiredInfo> mAuthenticationAcquiredCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationErrorInfo> mAuthenticationErrorCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationFailedInfo> mAuthenticationFailedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationHelpInfo> mAuthenticationHelpCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStartedInfo> mAuthenticationStartedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStoppedInfo> mAuthenticationStoppedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationSucceededInfo> mAuthenticationSucceededCaptor;
 
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
@@ -144,6 +170,10 @@
     @Before
     public void setup() {
         mContext.addMockSystemService(BiometricManager.class, mBiometricManager);
+        mContext.getOrCreateTestableResources().addOverride(R.string.face_error_hw_not_available,
+                "hw not available");
+        mContext.getOrCreateTestableResources().addOverride(R.string.face_acquired_too_dark,
+                "too dark");
         when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
                 i -> i.getArgument(0));
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
@@ -159,21 +189,26 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
     public void authWithContext_v2() throws RemoteException {
         final FaceAuthenticationClient client = createClient(2);
         client.start(mCallback);
 
+        verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
+                mStartHalConsumerCaptor.capture(), mContextInjector.capture(),
+                mFaceAuthenticateOptionsCaptor.capture());
+
+        mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor.getValue().toAidlContext(
+                mFaceAuthenticateOptionsCaptor.getValue()));
         InOrder order = inOrder(mHal, mBiometricContext);
         order.verify(mBiometricContext).updateContext(
                 mOperationContextCaptor.capture(), anyBoolean());
 
         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());
     }
 
@@ -200,30 +235,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void notifyHalWhenContextChanges() throws RemoteException {
-        final FaceAuthenticationClient client = createClient();
-        client.start(mCallback);
-
-        final ArgumentCaptor<OperationContext> captor =
-                ArgumentCaptor.forClass(OperationContext.class);
-        verify(mHal).authenticateWithContext(eq(OP_ID), captor.capture());
-        OperationContext opContext = captor.getValue();
-
-        // fake an update to the context
-        verify(mBiometricContext).subscribe(
-                mOperationContextCaptor.capture(), mContextInjector.capture());
-        assertThat(opContext).isSameInstanceAs(
-                mOperationContextCaptor.getValue().toAidlContext());
-        mContextInjector.getValue().accept(opContext);
-        verify(mHal).onContextChanged(same(opContext));
-
-        client.stopHalOperation();
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void subscribeContextAndStartHal() throws RemoteException {
         final FaceAuthenticationClient client = createClient();
         client.start(mCallback);
@@ -314,6 +325,90 @@
     }
 
     @Test
+    public void testAuthenticationStateListeners_onAuthenticationStartedAndStopped()
+            throws RemoteException {
+        final FaceAuthenticationClient client = createClient();
+        client.start(mCallback);
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(
+                mAuthenticationStartedCaptor.capture());
+
+        assertThat(mAuthenticationStartedCaptor.getValue()).isEqualTo(
+                new AuthenticationStartedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
+        client.stopHalOperation();
+
+        verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onAuthenticationAcquired_onAuthenticationHelp()
+            throws RemoteException {
+        final FaceAuthenticationClient client = createClient();
+        client.start(mCallback);
+        client.onAcquired(FACE_ACQUIRED_START, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationAcquired(
+                mAuthenticationAcquiredCaptor.capture());
+        assertThat(mAuthenticationAcquiredCaptor.getValue()).isEqualTo(
+                new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP, FACE_ACQUIRED_START)
+                        .build()
+        );
+
+        client.onAcquired(FACE_ACQUIRED_TOO_DARK, 0);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationAcquired(
+                mAuthenticationAcquiredCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationHelp(
+                mAuthenticationHelpCaptor.capture());
+
+        assertThat(mAuthenticationAcquiredCaptor.getValue()).isEqualTo(
+                new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP, FACE_ACQUIRED_TOO_DARK)
+                        .build()
+        );
+        assertThat(mAuthenticationHelpCaptor.getValue()).isEqualTo(
+                new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP,
+                        mContext.getString(R.string.face_acquired_too_dark),
+                        FACE_ACQUIRED_TOO_DARK)
+                        .build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onAuthenticationError()
+            throws RemoteException {
+        final FaceAuthenticationClient client = createClient();
+        client.start(mCallback);
+        client.onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationError(
+                mAuthenticationErrorCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationErrorCaptor.getValue()).isEqualTo(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP,
+                        mContext.getString(R.string.face_error_hw_not_available),
+                        BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE).build()
+        );
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
+    }
+
+    @Test
     public void testAuthenticationStateListeners_onAuthenticationSucceeded()
             throws RemoteException {
         mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS);
@@ -322,7 +417,14 @@
         client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */),
                 true /* authenticated */, new ArrayList<>());
 
-        verify(mAuthenticationStateListeners).onAuthenticationSucceeded(anyInt(), anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationSucceeded(
+                mAuthenticationSucceededCaptor.capture());
+
+        assertThat(mAuthenticationSucceededCaptor.getValue()).isEqualTo(
+                new AuthenticationSucceededInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP, true, USER_ID)
+                        .build()
+        );
     }
 
     @Test
@@ -333,7 +435,14 @@
         client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */),
                 false /* authenticated */, new ArrayList<>());
 
-        verify(mAuthenticationStateListeners).onAuthenticationFailed(anyInt(), anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationFailed(
+                mAuthenticationFailedCaptor.capture());
+
+        assertThat(mAuthenticationFailedCaptor.getValue()).isEqualTo(
+                new AuthenticationFailedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_BP, USER_ID)
+                        .build()
+        );
     }
 
     private FaceAuthenticationClient createClient() throws RemoteException {
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 e626f73..7a77033 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
@@ -27,9 +27,15 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.AuthenticateReason;
 import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.common.WakeReason;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.biometrics.face.ISession;
 import android.hardware.face.FaceAuthenticateOptions;
 import android.os.IBinder;
@@ -37,8 +43,6 @@
 import android.os.RemoteException;
 import android.os.Vibrator;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.testing.TestableContext;
@@ -46,10 +50,11 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.biometrics.Flags;
+import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 
@@ -96,12 +101,20 @@
     private ClientMonitorCallback mCallback;
     @Mock
     private AidlResponseHandler mAidlResponseHandler;
+    @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
     @Captor
     private ArgumentCaptor<OperationContextExt> mOperationContextCaptor;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mStartHalCaptor;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
+    @Captor
+    private ArgumentCaptor<AuthenticationErrorInfo> mAuthenticationErrorCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStartedInfo> mAuthenticationStartedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStoppedInfo> mAuthenticationStoppedCaptor;
 
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
@@ -109,7 +122,8 @@
     @Before
     public void setup() {
         mContext.addMockSystemService(Vibrator.class, mVibrator);
-
+        mContext.getOrCreateTestableResources().addOverride(R.string.face_error_hw_not_available,
+                "hw not available");
         when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
                 i -> i.getArgument(0));
     }
@@ -124,49 +138,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void detectWithContext_v2() throws RemoteException {
-        final FaceDetectClient client = createClient(2);
-        client.start(mCallback);
-
-        InOrder order = inOrder(mHal, mBiometricContext);
-        order.verify(mBiometricContext).updateContext(
-                mOperationContextCaptor.capture(), anyBoolean());
-
-        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();
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void notifyHalWhenContextChanges() throws RemoteException {
-        final FaceDetectClient client = createClient();
-        client.start(mCallback);
-
-        final ArgumentCaptor<OperationContext> captor =
-                ArgumentCaptor.forClass(OperationContext.class);
-        verify(mHal).detectInteractionWithContext(captor.capture());
-        OperationContext opContext = captor.getValue();
-
-        // fake an update to the context
-        verify(mBiometricContext).subscribe(
-                mOperationContextCaptor.capture(), mContextInjector.capture());
-        assertThat(opContext).isSameInstanceAs(
-                mOperationContextCaptor.getValue().toAidlContext());
-        mContextInjector.getValue().accept(opContext);
-        verify(mHal).onContextChanged(same(opContext));
-
-        client.stopHalOperation();
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void subscribeContextAndStartHal() throws RemoteException {
         final FaceDetectClient client = createClient();
         client.start(mCallback);
@@ -222,7 +193,55 @@
                         .setAuthenticateReason(
                                 FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
                         .build(),
-                mBiometricLogger, mBiometricContext,
+                mBiometricLogger, mBiometricContext, mAuthenticationStateListeners,
                 false /* isStrongBiometric */, null /* sensorPrivacyManager */);
     }
+
+    @Test
+    public void testAuthenticationStateListeners_onDetectionStartedAndStopped()
+            throws RemoteException {
+        final FaceDetectClient client = createClient();
+        client.start(mCallback);
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(
+                mAuthenticationStartedCaptor.capture());
+
+        assertThat(mAuthenticationStartedCaptor.getValue()).isEqualTo(
+                new AuthenticationStartedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
+        client.stopHalOperation();
+
+        verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onDetectionError()
+            throws RemoteException {
+        final FaceDetectClient client = createClient();
+        client.start(mCallback);
+        client.onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationError(
+                mAuthenticationErrorCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationErrorCaptor.getValue()).isEqualTo(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD,
+                        mContext.getString(R.string.face_error_hw_not_available),
+                        BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE).build()
+        );
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
index 02363cd..f477682 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -30,16 +33,21 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.biometrics.face.ISession;
 import android.hardware.face.Face;
 import android.hardware.face.FaceEnrollOptions;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.testing.TestableContext;
@@ -47,10 +55,11 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.biometrics.Flags;
+import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -98,18 +107,32 @@
     private ClientMonitorCallback mCallback;
     @Mock
     private AidlResponseHandler mAidlResponseHandler;
+    @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
     @Captor
     private ArgumentCaptor<OperationContextExt> mOperationContextCaptor;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mStartHalConsumer;
+    @Captor
+    private ArgumentCaptor<AuthenticationErrorInfo> mAuthenticationErrorCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationHelpInfo> mAuthenticationHelpCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStartedInfo> mAuthenticationStartedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStoppedInfo> mAuthenticationStoppedCaptor;
 
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
 
     @Before
     public void setup() {
+        mContext.getOrCreateTestableResources().addOverride(R.string.face_error_hw_not_available,
+                "hw not available");
+        mContext.getOrCreateTestableResources().addOverride(R.string.face_acquired_too_dark,
+                "too dark");
         when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
                 i -> i.getArgument(0));
     }
@@ -124,45 +147,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void enrollWithContext_v2() throws RemoteException {
-        final FaceEnrollClient client = createClient(2);
-        client.start(mCallback);
-
-        InOrder order = inOrder(mHal, mBiometricContext);
-        order.verify(mBiometricContext).updateContext(
-                mOperationContextCaptor.capture(), anyBoolean());
-
-        final OperationContext aidlContext = mOperationContextCaptor.getValue().toAidlContext();
-        order.verify(mHal).enrollWithContext(any(), anyByte(), any(), any(), same(aidlContext));
-        verify(mHal, never()).enroll(any(), anyByte(), any(), any());
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void notifyHalWhenContextChanges() throws RemoteException {
-        final FaceEnrollClient client = createClient(3);
-        client.start(mCallback);
-
-        final ArgumentCaptor<OperationContext> captor =
-                ArgumentCaptor.forClass(OperationContext.class);
-        verify(mHal).enrollWithContext(any(), anyByte(), any(), any(), captor.capture());
-        OperationContext opContext = captor.getValue();
-
-        // fake an update to the context
-        verify(mBiometricContext).subscribe(
-                mOperationContextCaptor.capture(), mContextInjector.capture());
-        assertThat(opContext).isSameInstanceAs(
-                mOperationContextCaptor.getValue().toAidlContext());
-        mContextInjector.getValue().accept(opContext);
-        verify(mHal).onContextChanged(same(opContext));
-
-        client.stopHalOperation();
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void subscribeContextAndStartHal() throws RemoteException {
         final FaceEnrollClient client = createClient(3);
         client.start(mCallback);
@@ -192,16 +176,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void enrollWithFaceOptions() throws RemoteException {
-        final FaceEnrollClient client = createClient(4);
-        client.start(mCallback);
-
-        verify(mHal).enrollWithOptions(any());
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void enrollWithFaceOptionsAfterSubscribingContext() throws RemoteException {
         final FaceEnrollClient client = createClient(4);
         client.start(mCallback);
@@ -238,6 +212,85 @@
                 null /* previewSurface */, 8 /* sensorId */,
                 mBiometricLogger, mBiometricContext, 5 /* maxTemplatesPerUser */,
                 true /* debugConsent */,
-                (new FaceEnrollOptions.Builder()).setEnrollReason(ENROLL_SOURCE).build());
+                (new FaceEnrollOptions.Builder()).setEnrollReason(ENROLL_SOURCE).build(),
+                mAuthenticationStateListeners);
     }
+
+    @Test
+    public void testAuthenticationStateListeners_onEnrollmentStartedAndStopped()
+            throws RemoteException {
+        final FaceEnrollClient client = createClient();
+        client.start(mCallback);
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(
+                mAuthenticationStartedCaptor.capture());
+
+        assertThat(mAuthenticationStartedCaptor.getValue()).isEqualTo(
+                new AuthenticationStartedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING).build()
+        );
+        client.stopHalOperation();
+
+        verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING).build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onEnrollmentError()
+            throws RemoteException {
+        final FaceEnrollClient client = createClient();
+        client.start(mCallback);
+        client.onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationError(
+                mAuthenticationErrorCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationErrorCaptor.getValue()).isEqualTo(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING,
+                        mContext.getString(R.string.face_error_hw_not_available),
+                        BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE).build()
+        );
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING).build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onAuthenticationHelp()
+            throws RemoteException {
+        final FaceEnrollClient client = createClient();
+        client.start(mCallback);
+        client.onAcquired(FACE_ACQUIRED_START, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationHelp(
+                mAuthenticationHelpCaptor.capture());
+        assertThat(mAuthenticationHelpCaptor.getValue()).isEqualTo(
+                new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING,
+                        null, FACE_ACQUIRED_START)
+                        .build()
+        );
+
+        client.onAcquired(FACE_ACQUIRED_TOO_DARK, 0);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationHelp(
+                mAuthenticationHelpCaptor.capture());
+        assertThat(mAuthenticationHelpCaptor.getValue()).isEqualTo(
+                new AuthenticationHelpInfo.Builder(BiometricSourceType.FACE,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING,
+                        mContext.getString(R.string.face_acquired_too_dark),
+                        FACE_ACQUIRED_TOO_DARK)
+                        .build()
+        );
+    }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
index 9eca93e..c4e51f8 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
@@ -44,22 +44,18 @@
 import android.hardware.face.HidlFaceSensorConfig;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
 import com.android.server.biometrics.BiometricHandlerProvider;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
 import com.android.server.biometrics.sensors.AuthenticationStateListeners;
@@ -134,13 +130,8 @@
         when(mBiometricHandlerProvider.getBiometricCallbackHandler()).thenReturn(
                 mBiometricCallbackHandler);
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
-        if (Flags.deHidl()) {
-            when(mBiometricHandlerProvider.getFaceHandler()).thenReturn(new Handler(
-                    mLooper.getLooper()));
-        } else {
-            when(mBiometricHandlerProvider.getFaceHandler()).thenReturn(new Handler(
-                    Looper.getMainLooper()));
-        }
+        when(mBiometricHandlerProvider.getFaceHandler()).thenReturn(new Handler(
+                mLooper.getLooper()));
 
         final SensorProps sensor1 = new SensorProps();
         sensor1.commonProps = new CommonProps();
@@ -176,7 +167,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testAddingHidlSensors() {
         when(mResources.getIntArray(anyInt())).thenReturn(new int[]{});
         when(mResources.getBoolean(anyInt())).thenReturn(false);
@@ -247,7 +237,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testAuthenticateCallbackHandler() {
         waitForIdle();
 
@@ -295,10 +284,6 @@
     }
 
     private void waitForIdle() {
-        if (Flags.deHidl()) {
-            mLooper.dispatchAll();
-        } else {
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        }
+        mLooper.dispatchAll();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
index fe9cd43..6780e60 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
@@ -41,7 +41,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
@@ -50,7 +49,6 @@
 import com.android.server.biometrics.sensors.LockoutCache;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
 import com.android.server.biometrics.sensors.LockoutTracker;
-import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
 import com.android.server.biometrics.sensors.UserSwitchProvider;
 
 import org.junit.Before;
@@ -75,12 +73,8 @@
     @Mock
     private ISession mSession;
     @Mock
-    private UserAwareBiometricScheduler.UserSwitchCallback mUserSwitchCallback;
-    @Mock
     private UserSwitchProvider<IFace, ISession> mUserSwitchProvider;
     @Mock
-    private AidlResponseHandler.HardwareUnavailableCallback mHardwareUnavailableCallback;
-    @Mock
     private LockoutResetDispatcher mLockoutResetDispatcher;
     @Mock
     private BiometricLogger mBiometricLogger;
@@ -94,6 +88,8 @@
     private BaseClientMonitor mClientMonitor;
     @Mock
     private AidlSession mCurrentSession;
+    @Mock
+    private AidlResponseHandler.AidlResponseHandlerCallback mAidlResponseHandlerCallback;
 
     private final TestLooper mLooper = new TestLooper();
     private final LockoutCache mLockoutCache = new LockoutCache();
@@ -108,27 +104,17 @@
         when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService);
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
 
-        if (Flags.deHidl()) {
-            mScheduler = new BiometricScheduler<>(
-                    new Handler(mLooper.getLooper()),
-                    BiometricScheduler.SENSOR_TYPE_FACE,
-                    null /* gestureAvailabilityDispatcher */,
-                    mBiometricService,
-                    2 /* recentOperationsLimit */,
-                    () -> USER_ID,
-                    mUserSwitchProvider);
-        } else {
-            mScheduler = new UserAwareBiometricScheduler<>(TAG,
-                    new Handler(mLooper.getLooper()),
-                    BiometricScheduler.SENSOR_TYPE_FACE,
-                    null /* gestureAvailabilityDispatcher */,
-                    mBiometricService,
-                    () -> USER_ID,
-                    mUserSwitchCallback);
-        }
+        mScheduler = new BiometricScheduler<>(
+                new Handler(mLooper.getLooper()),
+                BiometricScheduler.SENSOR_TYPE_FACE,
+                null /* gestureAvailabilityDispatcher */,
+                mBiometricService,
+                2 /* recentOperationsLimit */,
+                () -> USER_ID,
+                mUserSwitchProvider);
         mHalCallback = new AidlResponseHandler(mContext, mScheduler, SENSOR_ID, USER_ID,
                 mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator,
-                mHardwareUnavailableCallback);
+                mAidlResponseHandlerCallback);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
deleted file mode 100644
index 949d6ee..0000000
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.face.hidl;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.biometrics.ComponentInfoInternal;
-import android.hardware.biometrics.SensorProperties;
-import android.hardware.face.FaceSensorProperties;
-import android.hardware.face.FaceSensorPropertiesInternal;
-import android.hardware.face.IFaceServiceReceiver;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.UserManager;
-import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.R;
-import com.android.server.biometrics.Flags;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
-import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.time.Clock;
-import java.time.Instant;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.IntStream;
-
-@Presubmit
-@SmallTest
-public class Face10Test {
-
-    private static final String TAG = "Face10Test";
-    private static final int SENSOR_ID = 1;
-    private static final int USER_ID = 20;
-    private static final float FRR_THRESHOLD = 0.2f;
-
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
-
-    @Mock
-    private Context mContext;
-    @Mock
-    private UserManager mUserManager;
-    @Mock
-    private Resources mResources;
-    @Mock
-    private BiometricScheduler mScheduler;
-    @Mock
-    private BiometricContext mBiometricContext;
-    @Mock
-    private BiometricStateCallback mBiometricStateCallback;
-    @Mock
-    private AuthenticationStateListeners mAuthenticationStateListeners;
-
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-    private LockoutResetDispatcher mLockoutResetDispatcher;
-    private com.android.server.biometrics.sensors.face.hidl.Face10 mFace10;
-    private IBinder mBinder;
-
-    private static void waitForIdle() {
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
-
-        when(mContext.getResources()).thenReturn(mResources);
-        when(mResources.getFraction(R.fraction.config_biometricNotificationFrrThreshold, 1, 1))
-                .thenReturn(FRR_THRESHOLD);
-
-        mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
-
-        final int maxEnrollmentsPerUser = 1;
-        final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
-        final boolean supportsFaceDetection = false;
-        final boolean supportsSelfIllumination = false;
-        final boolean resetLockoutRequiresChallenge = false;
-        final FaceSensorPropertiesInternal sensorProps = new FaceSensorPropertiesInternal(SENSOR_ID,
-                SensorProperties.STRENGTH_STRONG, maxEnrollmentsPerUser, componentInfo,
-                FaceSensorProperties.TYPE_UNKNOWN, supportsFaceDetection, supportsSelfIllumination,
-                resetLockoutRequiresChallenge);
-
-        Face10.sSystemClock = Clock.fixed(
-                Instant.ofEpochMilli(100), ZoneId.of("America/Los_Angeles"));
-        mFace10 = new Face10(mContext, mBiometricStateCallback, mAuthenticationStateListeners,
-                sensorProps, mLockoutResetDispatcher, mHandler, mScheduler, mBiometricContext);
-        mBinder = new Binder();
-    }
-
-    private void tick(long seconds) {
-        waitForIdle();
-        Face10.sSystemClock = Clock.fixed(Instant.ofEpochSecond(
-                Face10.sSystemClock.instant().getEpochSecond() + seconds),
-                ZoneId.of("America/Los_Angeles"));
-    }
-
-    @Test
-    public void getAuthenticatorId_doesNotCrashWhenIdNotFound() {
-        assertEquals(0, mFace10.getAuthenticatorId(0 /* sensorId */, 111 /* userId */));
-        waitForIdle();
-    }
-
-    @Test
-    public void scheduleRevokeChallenge_doesNotCrash() {
-        mFace10.scheduleRevokeChallenge(0 /* sensorId */, 0 /* userId */, mBinder, TAG,
-                0 /* challenge */);
-        waitForIdle();
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void scheduleGenerateChallenge_cachesResult() {
-        final IFaceServiceReceiver[] mocks = IntStream.range(0, 3)
-                .mapToObj(i -> mock(IFaceServiceReceiver.class))
-                .toArray(IFaceServiceReceiver[]::new);
-        for (IFaceServiceReceiver mock : mocks) {
-            mFace10.scheduleGenerateChallenge(SENSOR_ID, USER_ID, mBinder, mock, TAG);
-            tick(10);
-        }
-        tick(120);
-        mFace10.scheduleGenerateChallenge(
-                SENSOR_ID, USER_ID, mBinder, mock(IFaceServiceReceiver.class), TAG);
-        waitForIdle();
-
-        verify(mScheduler, times(2))
-                .scheduleClientMonitor(isA(FaceGenerateChallengeClient.class), any());
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void scheduleRevokeChallenge_waitsUntilEmpty() {
-        final long challenge = 22;
-        final IFaceServiceReceiver[] mocks = IntStream.range(0, 3)
-                .mapToObj(i -> mock(IFaceServiceReceiver.class))
-                .toArray(IFaceServiceReceiver[]::new);
-        for (IFaceServiceReceiver mock : mocks) {
-            mFace10.scheduleGenerateChallenge(SENSOR_ID, USER_ID, mBinder, mock, TAG);
-            tick(10);
-        }
-        for (IFaceServiceReceiver mock : mocks) {
-            mFace10.scheduleRevokeChallenge(SENSOR_ID, USER_ID, mBinder, TAG, challenge);
-            tick(10);
-        }
-        waitForIdle();
-
-        verify(mScheduler).scheduleClientMonitor(isA(FaceRevokeChallengeClient.class), any());
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void scheduleRevokeChallenge_doesNotWaitForever() {
-        mFace10.scheduleGenerateChallenge(
-                SENSOR_ID, USER_ID, mBinder, mock(IFaceServiceReceiver.class), TAG);
-        mFace10.scheduleGenerateChallenge(
-                SENSOR_ID, USER_ID, mBinder, mock(IFaceServiceReceiver.class), TAG);
-        tick(10000);
-        mFace10.scheduleGenerateChallenge(
-                SENSOR_ID, USER_ID, mBinder, mock(IFaceServiceReceiver.class), TAG);
-        mFace10.scheduleRevokeChallenge(
-                SENSOR_ID, USER_ID, mBinder, TAG, 8 /* challenge */);
-        waitForIdle();
-
-        verify(mScheduler).scheduleClientMonitor(isA(FaceRevokeChallengeClient.class), any());
-    }
-
-    @Test
-    public void halServiceDied_resetsScheduler() {
-        // It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
-        // serviceDied directly.
-        mFace10.serviceDied(0 /* cookie */);
-        waitForIdle();
-        verify(mScheduler).reset();
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java
deleted file mode 100644
index ec08329..0000000
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java
+++ /dev/null
@@ -1,111 +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.biometrics.sensors.face.hidl;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.biometrics.face.V1_0.IBiometricsFace;
-import android.hardware.biometrics.face.V1_0.OptionalUint64;
-import android.hardware.face.IFaceServiceReceiver;
-import android.os.Binder;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.filters.SmallTest;
-
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.log.BiometricLogger;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@Presubmit
-@SmallTest
-public class FaceGenerateChallengeClientTest {
-
-    private static final String TAG = "FaceGenerateChallengeClientTest";
-    private static final int USER_ID = 2;
-    private static final int SENSOR_ID = 4;
-    private static final long START_TIME = 5000;
-    private static final long CHALLENGE = 200;
-
-    private final Context mContext = ApplicationProvider.getApplicationContext();
-
-    @Mock
-    private IBiometricsFace mIBiometricsFace;
-    @Mock
-    private IFaceServiceReceiver mClientReceiver;
-    @Mock
-    private IFaceServiceReceiver mOtherReceiver;
-    @Mock
-    private ClientMonitorCallback mMonitorCallback;
-    @Mock
-    private BiometricLogger mBiometricLogger;
-    @Mock
-    private BiometricContext mBiometricContext;
-
-    private FaceGenerateChallengeClient mClient;
-
-    @Before
-    public void setup() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        final OptionalUint64 challenge = new OptionalUint64();
-        challenge.value = CHALLENGE;
-        when(mIBiometricsFace.generateChallenge(anyInt())).thenReturn(challenge);
-
-        mClient = new FaceGenerateChallengeClient(mContext, () -> mIBiometricsFace, new Binder(),
-                new ClientMonitorCallbackConverter(mClientReceiver), USER_ID,
-                TAG, SENSOR_ID, mBiometricLogger, mBiometricContext , START_TIME);
-    }
-
-    @Test
-    public void getCreatedAt() {
-        assertEquals(START_TIME, mClient.getCreatedAt());
-    }
-
-    @Test
-    public void reuseResult_whenNotReady() throws Exception {
-        mClient.reuseResult(mOtherReceiver);
-        verify(mOtherReceiver, never()).onChallengeGenerated(anyInt(), anyInt(), anyInt());
-    }
-
-    @Test
-    public void reuseResult_whenReady() throws Exception {
-        mClient.start(mMonitorCallback);
-        mClient.reuseResult(mOtherReceiver);
-        verify(mOtherReceiver).onChallengeGenerated(eq(SENSOR_ID), eq(USER_ID), eq(CHALLENGE));
-    }
-
-    @Test
-    public void reuseResult_whenReallyReady() throws Exception {
-        mClient.reuseResult(mOtherReceiver);
-        mClient.start(mMonitorCallback);
-        verify(mOtherReceiver).onChallengeGenerated(eq(SENSOR_ID), eq(USER_ID), eq(CHALLENGE));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java
index 7a778d5..4248e5e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java
@@ -46,6 +46,7 @@
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
 import com.android.server.biometrics.sensors.LockoutTracker;
@@ -91,6 +92,8 @@
     private AidlResponseHandler.AidlResponseHandlerCallback mAidlResponseHandlerCallback;
     @Mock
     private BiometricUtils<Face> mBiometricUtils;
+    @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
 
     private final TestLooper mLooper = new TestLooper();
     private HidlToAidlSensorAdapter mHidlToAidlSensorAdapter;
@@ -202,7 +205,8 @@
                 USER_ID, HAT, TAG, 1 /* requestId */, mBiometricUtils,
                 new int[]{} /* disabledFeatures */, ENROLL_TIMEOUT_SEC, null /* previewSurface */,
                 SENSOR_ID, mLogger, mBiometricContext, 1 /* maxTemplatesPerUser */,
-                false /* debugConsent */, (new FaceEnrollOptions.Builder()).build()));
+                false /* debugConsent */, (new FaceEnrollOptions.Builder()).build(),
+                mAuthenticationStateListeners));
         mLooper.dispatchAll();
 
         verify(mAidlResponseHandlerCallback).onEnrollSuccess();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapterTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapterTest.java
index b5d73d2..44da431 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSessionAdapterTest.java
@@ -16,8 +16,8 @@
 
 package com.android.server.biometrics.sensors.face.hidl;
 
-import static com.android.server.biometrics.sensors.face.hidl.FaceGenerateChallengeClient.CHALLENGE_TIMEOUT_SEC;
 import static com.android.server.biometrics.sensors.face.hidl.HidlToAidlSessionAdapter.ENROLL_TIMEOUT_SEC;
+import static com.android.server.biometrics.sensors.face.hidl.HidlToAidlSessionAdapter.CHALLENGE_TIMEOUT_SEC;
 
 import static com.google.common.truth.Truth.assertThat;
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
index 20961a9..6126af5 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
@@ -51,7 +51,6 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.provider.Settings;
@@ -64,7 +63,6 @@
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
 import com.android.server.LocalServices;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
@@ -90,8 +88,6 @@
     private static final int ID_VIRTUAL = 6;
     private static final String NAME_DEFAULT = "default";
     private static final String NAME_VIRTUAL = "virtual";
-    private static final List<FingerprintSensorPropertiesInternal> HIDL_AUTHENTICATORS =
-            List.of();
     private static final String OP_PACKAGE_NAME = "FingerprintServiceTest/SystemUi";
 
     @Rule
@@ -185,7 +181,7 @@
 
     private void initServiceWithAndWait(String... aidlInstances) throws Exception {
         initServiceWith(aidlInstances);
-        mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
+        mService.mServiceWrapper.registerAuthenticators(mFingerprintSensorConfigurations);
         waitForRegistration();
     }
 
@@ -193,18 +189,7 @@
     public void registerAuthenticators_defaultOnly() throws Exception {
         initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
 
-        mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
-        waitForRegistration();
-
-        verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT), anyInt(), anyInt(), any());
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
-    public void registerAuthenticatorsLegacy_defaultOnly() throws Exception {
-        initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
-
-        mService.mServiceWrapper.registerAuthenticatorsLegacy(mFingerprintSensorConfigurations);
+        mService.mServiceWrapper.registerAuthenticators(mFingerprintSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT), anyInt(), anyInt(), any());
@@ -216,20 +201,19 @@
         Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
                 Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1);
 
-        mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
+        mService.mServiceWrapper.registerAuthenticators(mFingerprintSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
-    public void registerAuthenticatorsLegacy_virtualOnly() throws Exception {
+    public void registerAuthenticators_virtualFingerprintOnly() throws Exception {
         initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
         Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
-                Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1);
+                Settings.Secure.BIOMETRIC_FINGERPRINT_VIRTUAL_ENABLED, 1);
 
-        mService.mServiceWrapper.registerAuthenticatorsLegacy(mFingerprintSensorConfigurations);
+        mService.mServiceWrapper.registerAuthenticators(mFingerprintSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
@@ -237,23 +221,12 @@
 
     @Test
     public void registerAuthenticators_virtualAlwaysWhenNoOther() throws Exception {
-        initServiceWith(NAME_VIRTUAL);
-
-        mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
-        waitForRegistration();
-
-        verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
-    public void registerAuthenticatorsLegacy_virtualAlwaysWhenNoOther() throws Exception {
         mFingerprintSensorConfigurations =
                 new FingerprintSensorConfigurations(true);
         mFingerprintSensorConfigurations.addAidlSensors(new String[]{NAME_VIRTUAL});
         initServiceWith(NAME_VIRTUAL);
 
-        mService.mServiceWrapper.registerAuthenticatorsLegacy(mFingerprintSensorConfigurations);
+        mService.mServiceWrapper.registerAuthenticators(mFingerprintSensorConfigurations);
         waitForRegistration();
 
         verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
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 7a77392..40de1b2 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
@@ -19,8 +19,9 @@
 import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
-
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_TOO_FAST;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -42,23 +43,28 @@
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.ICancellationSignal;
 import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.common.OperationState;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationFailedInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
+import android.hardware.biometrics.events.AuthenticationSucceededInfo;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -67,13 +73,14 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.biometrics.Flags;
+import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.CallbackWithProbe;
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.log.Probe;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
+import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -135,8 +142,6 @@
     @Mock
     private IUdfpsOverlayController mUdfpsOverlayController;
     @Mock
-    private ISidefpsController mSideFpsController;
-    @Mock
     private AuthenticationStateListeners mAuthenticationStateListeners;
     @Mock
     private FingerprintSensorPropertiesInternal mSensorProps;
@@ -162,13 +167,32 @@
     private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mStartHalConsumerCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationAcquiredInfo> mAuthenticationAcquiredCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationErrorInfo> mAuthenticationErrorCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationFailedInfo> mAuthenticationFailedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationHelpInfo> mAuthenticationHelpCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStartedInfo> mAuthenticationStartedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStoppedInfo> mAuthenticationStoppedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationSucceededInfo> mAuthenticationSucceededCaptor;
 
     private final TestLooper mLooper = new TestLooper();
 
     @Before
     public void setup() {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         mContext.addMockSystemService(BiometricManager.class, mBiometricManager);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.string.fingerprint_error_hw_not_available, "hw not available");
+        mContext.getOrCreateTestableResources().addOverride(
+                R.string.fingerprint_error_lockout_permanent, "lockout permanent");
+        mContext.getOrCreateTestableResources().addOverride(
+                R.string.fingerprint_acquired_too_fast, "too fast");
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
         when(mBiometricLogger.getAmbientLightProbe(anyBoolean())).thenAnswer(i ->
                 new CallbackWithProbe<>(mLuxProbe, i.getArgument(0)));
@@ -180,36 +204,18 @@
     public void authNoContext_v1() throws RemoteException {
         final FingerprintAuthenticationClient client = createClient(1);
         client.start(mCallback);
-        if (Flags.deHidl()) {
-            verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
-                    mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
-            mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
-                    .getValue().toAidlContext());
-        }
+
+        verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
+                mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
+
+        mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
+                .getValue().toAidlContext());
 
         verify(mHal).authenticate(eq(OP_ID));
         verify(mHal, never()).authenticateWithContext(anyLong(), any());
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void authWithContext_v2() throws RemoteException {
-        final FingerprintAuthenticationClient client = createClient(2);
-        client.start(mCallback);
-
-        InOrder order = inOrder(mHal, mBiometricContext);
-        order.verify(mBiometricContext).updateContext(
-                mOperationContextCaptor.capture(), anyBoolean());
-
-        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());
-    }
-
-    @Test
     public void pointerUp_v1() throws RemoteException {
         final FingerprintAuthenticationClient client = createClient(1);
         client.start(mCallback);
@@ -277,21 +283,18 @@
 
         final FingerprintAuthenticationClient client = createClient();
         client.start(mCallback);
-        if (Flags.deHidl()) {
-            verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
-                    mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
-            mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
-                    .getValue().toAidlContext());
-        }
+
+        verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
+                mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
+
+        mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
+                .getValue().toAidlContext());
 
         final ArgumentCaptor<OperationContext> captor =
                 ArgumentCaptor.forClass(OperationContext.class);
         verify(mHal).authenticateWithContext(eq(OP_ID), captor.capture());
         OperationContext opContext = captor.getValue();
-        if (!Flags.deHidl()) {
-            verify(mBiometricContext).subscribe(
-                    mOperationContextCaptor.capture(), mContextInjector.capture());
-        }
+
         assertThat(mOperationContextCaptor.getValue().toAidlContext())
                 .isSameInstanceAs(opContext);
 
@@ -326,12 +329,12 @@
         when(mBiometricContext.isAod()).thenReturn(false);
         final FingerprintAuthenticationClient client = createClient();
         client.start(mCallback);
-        if (Flags.deHidl()) {
-            verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
-                    mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
-            mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
-                    .getValue().toAidlContext());
-        }
+
+        verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
+                mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
+
+        mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
+                .getValue().toAidlContext());
 
         verify(mLuxProbe, isAwake ? times(1) : never()).enable();
     }
@@ -342,21 +345,18 @@
         when(mBiometricContext.isAod()).thenReturn(true);
         final FingerprintAuthenticationClient client = createClient();
         client.start(mCallback);
-        if (Flags.deHidl()) {
-            verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
-                    mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
-            mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
-                    .getValue().toAidlContext());
-        }
+
+        verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
+                mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
+
+        mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
+                .getValue().toAidlContext());
 
         final ArgumentCaptor<OperationContext> captor =
                 ArgumentCaptor.forClass(OperationContext.class);
         verify(mHal).authenticateWithContext(eq(OP_ID), captor.capture());
         OperationContext opContext = captor.getValue();
-        if (!Flags.deHidl()) {
-            verify(mBiometricContext).subscribe(
-                    mOperationContextCaptor.capture(), mContextInjector.capture());
-        }
+
         assertThat(opContext).isSameInstanceAs(
                 mOperationContextCaptor.getValue().toAidlContext());
 
@@ -380,30 +380,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void notifyHalWhenContextChanges() throws RemoteException {
-        final FingerprintAuthenticationClient client = createClient();
-        client.start(mCallback);
-
-        final ArgumentCaptor<OperationContext> captor =
-                ArgumentCaptor.forClass(OperationContext.class);
-        verify(mHal).authenticateWithContext(eq(OP_ID), captor.capture());
-        OperationContext opContext = captor.getValue();
-
-        // fake an update to the context
-        verify(mBiometricContext).subscribe(
-                mOperationContextCaptor.capture(), mContextInjector.capture());
-        assertThat(opContext).isSameInstanceAs(
-                mOperationContextCaptor.getValue().toAidlContext());
-        mContextInjector.getValue().accept(opContext);
-        verify(mHal).onContextChanged(same(opContext));
-
-        client.stopHalOperation();
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void subscribeContextAndStartHal() throws RemoteException {
         final FingerprintAuthenticationClient client = createClient();
         client.start(mCallback);
@@ -411,8 +387,8 @@
         verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
                 mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
 
-        mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
-                .getValue().toAidlContext());
+        final OperationContextExt operationContext = mOperationContextCaptor.getValue();
+        mStartHalConsumerCaptor.getValue().accept(operationContext.toAidlContext());
         final ArgumentCaptor<OperationContext> captor =
                 ArgumentCaptor.forClass(OperationContext.class);
 
@@ -420,26 +396,30 @@
 
         OperationContext opContext = captor.getValue();
 
-        assertThat(opContext).isSameInstanceAs(
-                mOperationContextCaptor.getValue().toAidlContext());
+        assertThat(opContext).isSameInstanceAs(operationContext.toAidlContext());
 
+        opContext.operationState = new OperationState();
+        opContext.operationState.setFingerprintOperationState(
+                new OperationState.FingerprintOperationState());
         mContextInjector.getValue().accept(opContext);
 
         verify(mHal).onContextChanged(same(opContext));
+        verify(mHal, times(2)).setIgnoreDisplayTouches(
+                opContext.operationState.getFingerprintOperationState().isHardwareIgnoringTouches);
 
         client.stopHalOperation();
 
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
+        verify(mBiometricContext).unsubscribe(same(operationContext));
     }
 
     @Test
     public void showHideOverlay_cancel() throws RemoteException {
-        showHideOverlay(c -> c.cancel());
+        showHideOverlay(AuthenticationClient::cancel);
     }
 
     @Test
     public void showHideOverlay_stop() throws RemoteException {
-        showHideOverlay(c -> c.stopHalOperation());
+        showHideOverlay(FingerprintAuthenticationClient::stopHalOperation);
     }
 
     @Test
@@ -454,78 +434,124 @@
     }
 
     @Test
-    public void showHideOverlay_lockoutPerm() throws RemoteException {
-        showHideOverlay(c -> c.onLockoutPermanent());
-    }
-
-    private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block)
+    public void showHideOverlay_lockoutPerm()
             throws RemoteException {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
-        final FingerprintAuthenticationClient client = createClient();
-
-        client.start(mCallback);
-
-        verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
-        verify(mSideFpsController).show(anyInt(), anyInt());
-
-        block.accept(client);
-
-        verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
-        verify(mSideFpsController).hide(anyInt());
-        verify(mHal, times(2)).setIgnoreDisplayTouches(false);
+        showHideOverlay(FingerprintAuthenticationClient::onLockoutPermanent);
     }
 
-    @Test
-    public void showHideOverlay_cancel_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.cancel());
-    }
-
-    @Test
-    public void showHideOverlay_stop_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.stopHalOperation());
-    }
-
-    @Test
-    public void showHideOverlay_error_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onError(0, 0));
-        verify(mCallback).onClientFinished(any(), eq(false));
-    }
-
-    @Test
-    public void showHideOverlay_lockout_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onLockoutTimed(5000));
-    }
-
-    @Test
-    public void showHideOverlay_lockoutPerm_sidefpsControllerRemovalRefactor()
-            throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onLockoutPermanent());
-    }
-
-    private void showHideOverlay_sidefpsControllerRemovalRefactor(
+    private void showHideOverlay(
             Consumer<FingerprintAuthenticationClient> block) throws RemoteException {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         final FingerprintAuthenticationClient client = createClient();
 
         client.start(mCallback);
 
         verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
-        verify(mAuthenticationStateListeners).onAuthenticationStarted(anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(
+                mAuthenticationStartedCaptor.capture());
+
+        assertThat(mAuthenticationStartedCaptor.getValue()).isEqualTo(
+                new AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
 
         block.accept(client);
 
         verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
-        verify(mAuthenticationStateListeners).onAuthenticationStopped();
+        verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
     }
 
     @Test
-    public void testAuthenticationStateListeners_onAuthenticationAcquired()
+    public void testAuthenticationStateListeners_onAuthenticationAcquired_onAuthenticationHelp()
             throws RemoteException {
         final FingerprintAuthenticationClient client = createClient();
         client.start(mCallback);
         client.onAcquired(FINGERPRINT_ACQUIRED_START, 0);
 
-        verify(mAuthenticationStateListeners).onAuthenticationAcquired(any(), anyInt(), anyInt());
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationAcquired(
+                mAuthenticationAcquiredCaptor.capture());
+
+        assertThat(mAuthenticationAcquiredCaptor.getValue()).isEqualTo(
+                new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP, FINGERPRINT_ACQUIRED_START)
+                        .build()
+        );
+
+        client.onAcquired(FINGERPRINT_ACQUIRED_TOO_FAST, 0);
+
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationAcquired(
+                mAuthenticationAcquiredCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationHelp(
+                mAuthenticationHelpCaptor.capture());
+
+        assertThat(mAuthenticationAcquiredCaptor.getValue()).isEqualTo(
+                new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP, FINGERPRINT_ACQUIRED_TOO_FAST)
+                        .build()
+        );
+        assertThat(mAuthenticationHelpCaptor.getValue()).isEqualTo(
+                new AuthenticationHelpInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP,
+                        mContext.getString(R.string.fingerprint_acquired_too_fast),
+                        FINGERPRINT_ACQUIRED_TOO_FAST)
+                        .build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onError()
+            throws RemoteException {
+        final FingerprintAuthenticationClient client = createClient();
+        client.start(mCallback);
+        client.onError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationError(
+                mAuthenticationErrorCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationErrorCaptor.getValue()).isEqualTo(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP,
+                        mContext.getString(R.string.fingerprint_error_hw_not_available),
+                        FINGERPRINT_ERROR_HW_UNAVAILABLE).build()
+        );
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onLockoutPermanent()
+            throws RemoteException {
+        final FingerprintAuthenticationClient client = createClient();
+        client.start(mCallback);
+        client.onLockoutPermanent();
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationError(
+                mAuthenticationErrorCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationErrorCaptor.getValue()).isEqualTo(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP,
+                        mContext.getString(R.string.fingerprint_error_lockout_permanent),
+                        FINGERPRINT_ERROR_LOCKOUT_PERMANENT).build()
+        );
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP).build()
+        );
     }
 
     @Test
@@ -537,7 +563,13 @@
         client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */,
                 2 /* deviceId */), true /* authenticated */, new ArrayList<>());
 
-        verify(mAuthenticationStateListeners).onAuthenticationSucceeded(anyInt(), anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationSucceeded(
+                mAuthenticationSucceededCaptor.capture());
+        assertThat(mAuthenticationSucceededCaptor.getValue()).isEqualTo(
+                new AuthenticationSucceededInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP, true, USER_ID)
+                        .build()
+        );
     }
 
     @Test
@@ -548,7 +580,12 @@
         client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */,
                 2 /* deviceId */), false /* authenticated */, new ArrayList<>());
 
-        verify(mAuthenticationStateListeners).onAuthenticationFailed(anyInt(), anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationFailed(
+                mAuthenticationFailedCaptor.capture());
+        assertThat(mAuthenticationFailedCaptor.getValue()).isEqualTo(
+                new AuthenticationFailedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_BP, USER_ID).build()
+        );
     }
 
     @Test
@@ -603,7 +640,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testLockoutTracker_authFailed() throws RemoteException {
         final FingerprintAuthenticationClient client = createClient(1 /* version */,
                 true /* allowBackgroundAuthentication */, mClientMonitorCallbackConverter,
@@ -649,18 +685,12 @@
                 .setUserId(USER_ID)
                 .setSensorId(SENSOR_ID)
                 .build();
-        return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
-                REQUEST_ID, listener, OP_ID,
-                false /* restricted */, options, 4 /* cookie */,
-                false /* requireConfirmation */,
-                mBiometricLogger, mBiometricContext,
-                true /* isStrongBiometric */,
-                null /* taskStackListener */,
-                mUdfpsOverlayController, mSideFpsController, mAuthenticationStateListeners,
-                allowBackgroundAuthentication,
-                mSensorProps,
-                new Handler(mLooper.getLooper()), 0 /* biometricStrength */, mClock,
-                lockoutTracker) {
+        return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken, REQUEST_ID,
+                listener, OP_ID, false /* restricted */, options, 4 /* cookie */,
+                false /* requireConfirmation */, mBiometricLogger, mBiometricContext,
+                true /* isStrongBiometric */, null /* taskStackListener */, mUdfpsOverlayController,
+                mAuthenticationStateListeners, allowBackgroundAuthentication, mSensorProps,
+                0 /* biometricStrength */, lockoutTracker) {
             @Override
             protected ActivityTaskManager getActivityTaskManager() {
                 return mActivityTaskManager;
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 9edb8dd..6885342 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
@@ -21,22 +21,22 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.same;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.testing.TestableContext;
@@ -44,10 +44,10 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.OperationContextExt;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 
@@ -56,7 +56,6 @@
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
-import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
@@ -77,6 +76,8 @@
             DeviceFlagsValueProvider.createCheckFlagsRule();
 
     @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
+    @Mock
     private ISession mHal;
     @Mock
     private IBinder mToken;
@@ -98,6 +99,10 @@
     private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mStartHalConsumerCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStartedInfo> mAuthenticationStartedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStoppedInfo> mAuthenticationStoppedCaptor;
 
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
@@ -119,49 +124,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void detectNoContext_v2() throws RemoteException {
-        final FingerprintDetectClient client = createClient(2);
-
-        client.start(mCallback);
-
-        InOrder order = inOrder(mHal, mBiometricContext);
-        order.verify(mBiometricContext).updateContext(
-                mOperationContextCaptor.capture(), anyBoolean());
-
-        final OperationContext aidlContext = mOperationContextCaptor.getValue().toAidlContext();
-        order.verify(mHal).detectInteractionWithContext(same(aidlContext));
-        assertThat(aidlContext.authenticateReason.getFingerprintAuthenticateReason())
-                .isEqualTo(AuthenticateReason.Fingerprint.UNKNOWN);
-
-        verify(mHal, never()).detectInteraction();
-    }
-
-    @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void notifyHalWhenContextChanges() throws RemoteException {
-        final FingerprintDetectClient client = createClient();
-        client.start(mCallback);
-
-        final ArgumentCaptor<OperationContext> captor =
-                ArgumentCaptor.forClass(OperationContext.class);
-        verify(mHal).detectInteractionWithContext(captor.capture());
-        OperationContext opContext = captor.getValue();
-
-        // fake an update to the context
-        verify(mBiometricContext).subscribe(
-                mOperationContextCaptor.capture(), mContextInjector.capture());
-        assertThat(opContext).isSameInstanceAs(
-                mOperationContextCaptor.getValue().toAidlContext());
-        mContextInjector.getValue().accept(opContext);
-        verify(mHal).onContextChanged(same(opContext));
-
-        client.stopHalOperation();
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void subscribeContextAndStartHal() throws RemoteException {
         final FingerprintDetectClient client = createClient();
         client.start(mCallback);
@@ -195,7 +157,7 @@
                         .setSensorId(1)
                         .setOpPackageName("a-test")
                         .build(),
-                mBiometricLogger, mBiometricContext,
+                mBiometricLogger, mBiometricContext, mAuthenticationStateListeners,
                 mUdfpsOverlayController, true /* isStrongBiometric */);
         client.start(mCallback);
         client.onInteractionDetected();
@@ -218,7 +180,30 @@
                         .setSensorId(1)
                         .setOpPackageName("a-test")
                         .build(),
-                mBiometricLogger, mBiometricContext,
+                mBiometricLogger, mBiometricContext, mAuthenticationStateListeners,
                 mUdfpsOverlayController, true /* isStrongBiometric */);
     }
+
+    @Test
+    public void testAuthenticationStateListeners_onAuthenticationStartedAndStopped()
+            throws RemoteException {
+        final FingerprintDetectClient client = createClient();
+        client.start(mCallback);
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(
+                mAuthenticationStartedCaptor.capture());
+
+        assertThat(mAuthenticationStartedCaptor.getValue()).isEqualTo(
+                new AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
+
+        client.stopHalOperation();
+        verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+        );
+    }
 }
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 916f696..5c6513d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -16,7 +16,11 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_TOO_FAST;
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_TIMEOUT;
+
+import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -27,25 +31,28 @@
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.same;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.biometrics.BiometricRequestConstants;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
+import android.hardware.biometrics.events.AuthenticationErrorInfo;
+import android.hardware.biometrics.events.AuthenticationHelpInfo;
+import android.hardware.biometrics.events.AuthenticationStartedInfo;
+import android.hardware.biometrics.events.AuthenticationStoppedInfo;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -54,12 +61,13 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.biometrics.Flags;
+import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.log.CallbackWithProbe;
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.log.Probe;
+import com.android.server.biometrics.sensors.AcquisitionClient;
 import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -116,8 +124,6 @@
     @Mock
     private IUdfpsOverlayController mUdfpsOverlayController;
     @Mock
-    private ISidefpsController mSideFpsController;
-    @Mock
     private AuthenticationStateListeners mAuthenticationStateListeners;
     @Mock
     private FingerprintSensorPropertiesInternal mSensorProps;
@@ -133,6 +139,16 @@
     private ArgumentCaptor<Consumer<OperationContext>> mContextInjector;
     @Captor
     private ArgumentCaptor<Consumer<OperationContext>> mStartHalConsumerCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationAcquiredInfo> mAuthenticationAcquiredCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationErrorInfo> mAuthenticationErrorCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationHelpInfo> mAuthenticationHelpCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStartedInfo> mAuthenticationStartedCaptor;
+    @Captor
+    private ArgumentCaptor<AuthenticationStoppedInfo> mAuthenticationStoppedCaptor;
 
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
@@ -143,6 +159,10 @@
                 new CallbackWithProbe<>(mLuxProbe, i.getArgument(0)));
         when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
                 i -> i.getArgument(0));
+        mContext.getOrCreateTestableResources().addOverride(
+                R.string.fingerprint_acquired_too_fast, "too fast");
+        mContext.getOrCreateTestableResources().addOverride(
+                R.string.fingerprint_error_timeout, "timeout");
     }
 
     @Test
@@ -156,21 +176,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void enrollWithContext_v2() throws RemoteException {
-        final FingerprintEnrollClient client = createClient(2);
-
-        client.start(mCallback);
-
-        InOrder order = inOrder(mHal, mBiometricContext);
-        order.verify(mBiometricContext).updateContext(
-                mOperationContextCaptor.capture(), anyBoolean());
-        order.verify(mHal).enrollWithContext(any(),
-                same(mOperationContextCaptor.getValue().toAidlContext()));
-        verify(mHal, never()).enroll(any());
-    }
-
-    @Test
     public void pointerUp_v1() throws RemoteException {
         final FingerprintEnrollClient client = createClient(1);
         client.start(mCallback);
@@ -253,29 +258,6 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_DE_HIDL)
-    public void notifyHalWhenContextChanges() throws RemoteException {
-        final FingerprintEnrollClient client = createClient();
-        client.start(mCallback);
-
-        final ArgumentCaptor<OperationContext> captor =
-                ArgumentCaptor.forClass(OperationContext.class);
-        verify(mHal).enrollWithContext(any(), captor.capture());
-        OperationContext opContext = captor.getValue();
-
-        // fake an update to the context
-        verify(mBiometricContext).subscribe(
-                mOperationContextCaptor.capture(), mContextInjector.capture());
-        mContextInjector.getValue().accept(
-                mOperationContextCaptor.getValue().toAidlContext());
-        verify(mHal).onContextChanged(same(opContext));
-
-        client.stopHalOperation();
-        verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void subscribeContextAndStartHal() throws RemoteException {
         final FingerprintEnrollClient client = createClient();
         client.start(mCallback);
@@ -300,12 +282,12 @@
 
     @Test
     public void showHideOverlay_cancel() throws RemoteException {
-        showHideOverlay(c -> c.cancel());
+        showHideOverlay(AcquisitionClient::cancel);
     }
 
     @Test
     public void showHideOverlay_stop() throws RemoteException {
-        showHideOverlay(c -> c.stopHalOperation());
+        showHideOverlay(FingerprintEnrollClient::stopHalOperation);
     }
 
     @Test
@@ -316,45 +298,7 @@
 
     @Test
     public void showHideOverlay_result() throws RemoteException {
-        showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
-    }
-
-    private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
-            throws RemoteException {
-        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
-        final FingerprintEnrollClient client = createClient();
-
-        client.start(mCallback);
-
-        verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
-        verify(mSideFpsController).show(anyInt(), anyInt());
-
-        block.accept(client);
-
-        verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
-        verify(mSideFpsController).hide(anyInt());
-        verify(mHal, times(2)).setIgnoreDisplayTouches(false);
-    }
-
-    @Test
-    public void showHideOverlay_cancel_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.cancel());
-    }
-
-    @Test
-    public void showHideOverlay_stop_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.stopHalOperation());
-    }
-
-    @Test
-    public void showHideOverlay_error_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onError(0, 0));
-        verify(mCallback).onClientFinished(any(), eq(false));
-    }
-
-    @Test
-    public void showHideOverlay_result_sidefpsControllerRemovalRefactor() throws RemoteException {
-        showHideOverlay_sidefpsControllerRemovalRefactor(
+        showHideOverlay(
                 c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
     }
 
@@ -368,20 +312,84 @@
                 eq(BiometricsProtoEnums.ENROLLMENT_SOURCE_SUW));
     }
 
-    private void showHideOverlay_sidefpsControllerRemovalRefactor(
+    private void showHideOverlay(
             Consumer<FingerprintEnrollClient> block) throws RemoteException {
-        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         final FingerprintEnrollClient client = createClient();
 
         client.start(mCallback);
 
         verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
-        verify(mAuthenticationStateListeners).onAuthenticationStarted(anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(
+                mAuthenticationStartedCaptor.capture());
+
+        assertThat(mAuthenticationStartedCaptor.getValue()).isEqualTo(
+                new AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING).build()
+        );
 
         block.accept(client);
 
         verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
-        verify(mAuthenticationStateListeners).onAuthenticationStopped();
+        verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING).build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onAuthenticationAcquired_onAuthenticationHelp()
+            throws RemoteException {
+        final FingerprintEnrollClient client = createClient();
+        client.start(mCallback);
+        client.onAcquired(FINGERPRINT_ACQUIRED_START, 0);
+        client.onAcquired(FINGERPRINT_ACQUIRED_TOO_FAST, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationAcquired(
+                mAuthenticationAcquiredCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationHelp(
+                mAuthenticationHelpCaptor.capture());
+
+        assertThat(mAuthenticationAcquiredCaptor.getValue()).isEqualTo(
+                new AuthenticationAcquiredInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING,
+                        FINGERPRINT_ACQUIRED_TOO_FAST).build()
+        );
+        assertThat(mAuthenticationHelpCaptor.getValue()).isEqualTo(
+                new AuthenticationHelpInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING,
+                        mContext.getString(R.string.fingerprint_acquired_too_fast),
+                        FINGERPRINT_ACQUIRED_TOO_FAST)
+                        .build()
+        );
+    }
+
+    @Test
+    public void testAuthenticationStateListeners_onError()
+            throws RemoteException {
+        final FingerprintEnrollClient client = createClient();
+        client.start(mCallback);
+        client.onError(FINGERPRINT_ERROR_TIMEOUT, 0);
+
+        InOrder inOrder = inOrder(mAuthenticationStateListeners);
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationError(
+                mAuthenticationErrorCaptor.capture());
+        inOrder.verify(mAuthenticationStateListeners).onAuthenticationStopped(
+                mAuthenticationStoppedCaptor.capture());
+
+        assertThat(mAuthenticationErrorCaptor.getValue()).isEqualTo(
+                new AuthenticationErrorInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING,
+                        mContext.getString(R.string.fingerprint_error_timeout),
+                        FINGERPRINT_ERROR_TIMEOUT).build()
+        );
+        assertThat(mAuthenticationStoppedCaptor.getValue()).isEqualTo(
+                new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+                        BiometricRequestConstants.REASON_ENROLL_ENROLLING).build()
+        );
     }
 
     private FingerprintEnrollClient createClient() throws RemoteException {
@@ -396,7 +404,7 @@
         mClientMonitorCallbackConverter, 0 /* userId */,
         HAT, "owner", mBiometricUtils, 8 /* sensorId */,
         mBiometricLogger, mBiometricContext, mSensorProps, mUdfpsOverlayController,
-        mSideFpsController, mAuthenticationStateListeners, 6 /* maxTemplatesPerUser */,
+                mAuthenticationStateListeners, 6 /* maxTemplatesPerUser */,
         FingerprintManager.ENROLL_ENROLL, (new FingerprintEnrollOptions.Builder())
                 .setEnrollReason(ENROLL_SOURCE).build()
         );
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index 0a35037..1f288b2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -47,21 +47,17 @@
 import android.hardware.fingerprint.HidlFingerprintSensorConfig;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.server.biometrics.BiometricHandlerProvider;
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
 import com.android.server.biometrics.sensors.AuthenticationStateListeners;
@@ -136,13 +132,8 @@
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
         when(mBiometricHandlerProvider.getBiometricCallbackHandler()).thenReturn(
                 mBiometricCallbackHandler);
-        if (Flags.deHidl()) {
-            when(mBiometricHandlerProvider.getFingerprintHandler()).thenReturn(
-                    new Handler(mLooper.getLooper()));
-        } else {
-            when(mBiometricHandlerProvider.getFingerprintHandler()).thenReturn(
-                    new Handler(Looper.getMainLooper()));
-        }
+        when(mBiometricHandlerProvider.getFingerprintHandler()).thenReturn(
+                new Handler(mLooper.getLooper()));
 
         final SensorProps sensor1 = new SensorProps();
         sensor1.commonProps = new CommonProps();
@@ -176,7 +167,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testAddingHidlSensors() {
         when(mResources.getIntArray(anyInt())).thenReturn(new int[]{});
         when(mResources.getBoolean(anyInt())).thenReturn(false);
@@ -252,7 +242,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_DE_HIDL)
     public void testScheduleAuthenticate() {
         waitForIdle();
 
@@ -302,10 +291,6 @@
     }
 
     private void waitForIdle() {
-        if (Flags.deHidl()) {
-            mLooper.dispatchAll();
-        } else {
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        }
+        mLooper.dispatchAll();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
index b4c2ee8..698db2e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
@@ -42,7 +42,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.server.biometrics.Flags;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
@@ -51,7 +50,6 @@
 import com.android.server.biometrics.sensors.LockoutCache;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
 import com.android.server.biometrics.sensors.LockoutTracker;
-import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
 import com.android.server.biometrics.sensors.UserSwitchProvider;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
 
@@ -77,12 +75,8 @@
     @Mock
     private ISession mSession;
     @Mock
-    private UserAwareBiometricScheduler.UserSwitchCallback mUserSwitchCallback;
-    @Mock
     private UserSwitchProvider<IFingerprint, ISession> mUserSwitchProvider;
     @Mock
-    private AidlResponseHandler.HardwareUnavailableCallback mHardwareUnavailableCallback;
-    @Mock
     private LockoutResetDispatcher mLockoutResetDispatcher;
     @Mock
     private BiometricLogger mLogger;
@@ -100,6 +94,8 @@
     private BaseClientMonitor mClientMonitor;
     @Mock
     private HandlerThread mThread;
+    @Mock
+    AidlResponseHandler.AidlResponseHandlerCallback mAidlResponseHandlerCallback;
 
     private final TestLooper mLooper = new TestLooper();
     private final LockoutCache mLockoutCache = new LockoutCache();
@@ -115,27 +111,17 @@
         when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
         when(mThread.getLooper()).thenReturn(mLooper.getLooper());
 
-        if (Flags.deHidl()) {
-            mScheduler = new BiometricScheduler<>(
-                    new Handler(mLooper.getLooper()),
-                    BiometricScheduler.SENSOR_TYPE_FP_OTHER,
-                    null /* gestureAvailabilityDispatcher */,
-                    mBiometricService,
-                    2 /* recentOperationsLimit */,
-                    () -> USER_ID,
-                    mUserSwitchProvider);
-        } else {
-            mScheduler = new UserAwareBiometricScheduler<>(TAG,
-                    new Handler(mLooper.getLooper()),
-                    BiometricScheduler.SENSOR_TYPE_FP_OTHER,
-                    null /* gestureAvailabilityDispatcher */,
-                    mBiometricService,
-                    () -> USER_ID,
-                    mUserSwitchCallback);
-        }
+        mScheduler = new BiometricScheduler<>(
+                new Handler(mLooper.getLooper()),
+                BiometricScheduler.SENSOR_TYPE_FP_OTHER,
+                null /* gestureAvailabilityDispatcher */,
+                mBiometricService,
+                2 /* recentOperationsLimit */,
+                () -> USER_ID,
+                mUserSwitchProvider);
         mHalCallback = new AidlResponseHandler(mContext, mScheduler, SENSOR_ID, USER_ID,
                 mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator,
-                mHardwareUnavailableCallback);
+                mAidlResponseHandlerCallback);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
deleted file mode 100644
index 0d3f192..0000000
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint.hidl;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.biometrics.ComponentInfoInternal;
-import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.fingerprint.FingerprintSensorProperties;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserManager;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.annotation.NonNull;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.R;
-import com.android.server.biometrics.log.BiometricContext;
-import com.android.server.biometrics.sensors.AuthenticationStateListeners;
-import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
-import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Presubmit
-@SmallTest
-public class Fingerprint21Test {
-
-    private static final String TAG = "Fingerprint21Test";
-    private static final int SENSOR_ID = 1;
-
-    @Mock
-    private Context mContext;
-    @Mock
-    private Resources mResources;
-    @Mock
-    private UserManager mUserManager;
-    @Mock
-    Fingerprint21.HalResultController mHalResultController;
-    @Mock
-    private BiometricScheduler mScheduler;
-    @Mock
-    private AuthenticationStateListeners mAuthenticationStateListeners;
-    @Mock
-    private BiometricStateCallback mBiometricStateCallback;
-    @Mock
-    private BiometricContext mBiometricContext;
-
-    private LockoutResetDispatcher mLockoutResetDispatcher;
-    private Fingerprint21 mFingerprint21;
-
-    private static void waitForIdle() {
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
-        when(mContext.getResources()).thenReturn(mResources);
-        when(mResources.getInteger(eq(R.integer.config_fingerprintMaxTemplatesPerUser)))
-                .thenReturn(5);
-
-        mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
-
-        final int maxEnrollmentsPerUser = 1;
-        final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
-        final boolean resetLockoutRequiresHardwareAuthToken = false;
-        final FingerprintSensorPropertiesInternal sensorProps =
-                new FingerprintSensorPropertiesInternal(SENSOR_ID,
-                        FingerprintSensorProperties.STRENGTH_WEAK, maxEnrollmentsPerUser,
-                        componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN,
-                        resetLockoutRequiresHardwareAuthToken);
-
-        mFingerprint21 = new TestableFingerprint21(mContext, mBiometricStateCallback,
-                mAuthenticationStateListeners, sensorProps, mScheduler,
-                new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController,
-                mBiometricContext);
-    }
-
-    @Test
-    public void getAuthenticatorId_doesNotCrashWhenIdNotFound() {
-        assertEquals(0, mFingerprint21.getAuthenticatorId(0 /* sensorId */, 111 /* userId */));
-        waitForIdle();
-    }
-
-    @Test
-    public void halServiceDied_resetsScheduler() {
-        // It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
-        // serviceDied directly.
-        mFingerprint21.serviceDied(0 /* cookie */);
-        waitForIdle();
-        verify(mScheduler).reset();
-    }
-
-    private static class TestableFingerprint21 extends Fingerprint21 {
-
-        TestableFingerprint21(@NonNull Context context,
-                @NonNull BiometricStateCallback biometricStateCallback,
-                @NonNull AuthenticationStateListeners authenticationStateListeners,
-                @NonNull FingerprintSensorPropertiesInternal sensorProps,
-                @NonNull BiometricScheduler scheduler, @NonNull Handler handler,
-                @NonNull LockoutResetDispatcher lockoutResetDispatcher,
-                @NonNull HalResultController controller,
-                @NonNull BiometricContext biometricContext) {
-            super(context, biometricStateCallback, authenticationStateListeners, sensorProps,
-                    scheduler, handler, lockoutResetDispatcher, controller, biometricContext);
-        }
-
-        @Override
-        synchronized IBiometricsFingerprint getDaemon() {
-            return mock(IBiometricsFingerprint.class);
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java
index 6c3bfe8..1db74b4 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java
@@ -217,7 +217,7 @@
                 mContext, mHidlToAidlSensorAdapter.getLazySession(), null /* token */,
                 1 /* requestId */, null /* listener */, USER_ID, HAT, TAG, mBiometricUtils,
                 SENSOR_ID, mLogger, mBiometricContext,
-                mHidlToAidlSensorAdapter.getSensorProperties(), null, null,
+                mHidlToAidlSensorAdapter.getSensorProperties(), null,
                 mAuthenticationStateListeners, 5 /* maxTemplatesPerUser */, ENROLL_ENROLL,
                 (new FingerprintEnrollOptions.Builder()).build()));
         mLooper.dispatchAll();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index de3cfbf..855c658 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -30,8 +30,6 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
-import android.hardware.usb.UsbManager;
-import android.media.IAudioService;
 import android.net.IIpConnectivityMetrics;
 import android.net.Uri;
 import android.os.Bundle;
@@ -216,11 +214,6 @@
         }
 
         @Override
-        IAudioService getIAudioService() {
-            return services.iaudioService;
-        }
-
-        @Override
         PersistentDataBlockManagerInternal getPersistentDataBlockManagerInternal() {
             return services.persistentDataBlockManagerInternal;
         }
@@ -244,11 +237,6 @@
         }
 
         @Override
-        UsbManager getUsbManager() {
-            return services.usbManager;
-        }
-
-        @Override
         boolean storageManagerIsFileBasedEncryptionEnabled() {
             return services.storageManager.isFileBasedEncryptionEnabled();
         }
@@ -380,21 +368,11 @@
         }
 
         @Override
-        void settingsSecurePutInt(String name, int value) {
-            services.settings.settingsSecurePutInt(name, value);
-        }
-
-        @Override
         void settingsGlobalPutInt(String name, int value) {
             services.settings.settingsGlobalPutInt(name, value);
         }
 
         @Override
-        void settingsSecurePutString(String name, String value) {
-            services.settings.settingsSecurePutString(name, value);
-        }
-
-        @Override
         void settingsGlobalPutString(String name, String value) {
             services.settings.settingsGlobalPutString(name, value);
         }
diff --git a/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java b/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
index 6c5a569..af6f6f2 100644
--- a/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
+++ b/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
@@ -18,6 +18,7 @@
 
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertEquals;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -46,6 +47,7 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.List;
 
@@ -67,7 +69,7 @@
     @Before
     public void setUp() throws Exception {
         mBackupHelper = new GrammaticalInflectionBackupHelper(
-                mGrammaticalInflectionService, mMockPackageManager);
+                null, mGrammaticalInflectionService, mMockPackageManager);
     }
 
     @Test
@@ -106,6 +108,28 @@
                 eq(Configuration.GRAMMATICAL_GENDER_NEUTRAL));
     }
 
+    @Test
+    public void testSystemBackupPayload_returnsGender()
+            throws IOException, ClassNotFoundException {
+        doReturn(Configuration.GRAMMATICAL_GENDER_MASCULINE).when(mGrammaticalInflectionService)
+                .getSystemGrammaticalGender(any(), eq(DEFAULT_USER_ID));
+
+        int gender = convertByteArrayToInt(mBackupHelper.getSystemBackupPayload(DEFAULT_USER_ID));
+
+        assertEquals(gender, Configuration.GRAMMATICAL_GENDER_MASCULINE);
+    }
+
+    @Test
+    public void testApplySystemPayload_setSystemWideGrammaticalGender()
+            throws IOException {
+        mBackupHelper.applyRestoredSystemPayload(
+                intToByteArray(Configuration.GRAMMATICAL_GENDER_NEUTRAL), DEFAULT_USER_ID);
+
+        verify(mGrammaticalInflectionService).setSystemWideGrammaticalGender(
+                eq(Configuration.GRAMMATICAL_GENDER_NEUTRAL),
+                eq(DEFAULT_USER_ID));
+    }
+
     private void mockAppInstalled() {
         ApplicationInfo dummyApp = new ApplicationInfo();
         dummyApp.packageName = DEFAULT_PACKAGE_NAME;
@@ -141,4 +165,15 @@
         }
         return data;
     }
+
+    private byte[] intToByteArray(final int gender) {
+        ByteBuffer bb = ByteBuffer.allocate(4);
+        bb.putInt(gender);
+        return bb.array();
+    }
+
+    private int convertByteArrayToInt(byte[] intBytes) {
+        ByteBuffer byteBuffer = ByteBuffer.wrap(intBytes);
+        return byteBuffer.getInt();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index fa89278..44aa868 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -30,6 +30,9 @@
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.system.Os;
 import android.text.FontConfig;
 import android.util.Xml;
@@ -38,8 +41,11 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.text.flags.Flags;
+
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.xmlpull.v1.XmlPullParser;
@@ -69,6 +75,9 @@
 
     private static final String LEGACY_FONTS_XML = "/system/etc/fonts.xml";
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     /**
      * A {@link UpdatableFontDir.FontFileParser} for testing. Instead of using real font files,
      * this test uses fake font files. A fake font file has its PostScript naem and revision as the
@@ -1097,6 +1106,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1116,6 +1126,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureMissingCase_fontFamilyInstalled_fontInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1);
@@ -1135,6 +1146,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureMissingCase_fontFileInstalled_fontFamilyInstallLater() {
         // Install font file, foo.ttf and bar.ttf
         installTestFontFile(2 /* numFonts */, 1 /* version */);
@@ -1154,6 +1166,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureMissingCase_fontFileInstalled_fontFileInstallLater() {
         // Install font file, foo.ttf and bar.ttf
         installTestFontFile(2 /* numFonts */, 1 /* version */);
@@ -1173,6 +1186,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1192,6 +1206,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureAllMissingCase_fontFamilyInstalled_fontInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1211,6 +1226,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1230,6 +1246,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void signatureAllMissingCase_fontFileInstalled_fontFileInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1249,6 +1266,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1268,6 +1286,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontMissingCase_fontFamilyInstalled_fontInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1);
@@ -1287,6 +1306,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontMissingCase_fontFileInstalled_fontFamilyInstallLater() {
         // Install font file, foo.ttf and bar.ttf
         installTestFontFile(2 /* numFonts */, 1 /* version */);
@@ -1306,6 +1326,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontMissingCase_fontFileInstalled_fontFileInstallLater() {
         // Install font file, foo.ttf and bar.ttf
         installTestFontFile(2 /* numFonts */, 1 /* version */);
@@ -1325,6 +1346,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1344,6 +1366,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontAllMissingCase_fontFamilyInstalled_fontInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1363,6 +1386,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1382,6 +1406,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontAllMissingCase_fontFileInstalled_fontFileInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1401,6 +1426,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontDirAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1420,6 +1446,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontDirAllMissingCase_fontFamilyInstalled_fontInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1439,6 +1466,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontDirAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1458,6 +1486,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void fontDirAllMissingCase_fontFileInstalled_fontFileInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1477,6 +1506,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void dirContentAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1497,6 +1527,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void dirContentAllMissingCase_fontFamilyInstalled_fontInstallLater() {
         // Install font families, foo.ttf, bar.ttf.
         installTestFontFamilies(1 /* version */);
@@ -1517,6 +1548,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void dirContentAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
@@ -1537,6 +1569,7 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE)
     public void dirContentAllMissingCase_fontFileInstalled_fontFileInstallLater() {
         // Install font file, foo.ttf
         installTestFontFile(1 /* numFonts */, 1 /* version */);
diff --git a/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
index 861562d..305108e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
+++ b/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
@@ -1,31 +1,11 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.pm."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
+      "name": "FrameworksServicesTests_pm_presubmit"
     }
   ],
   "postsubmit": [
     {
-      // Presubmit is intentional here while testing with SLO checker.
-      // Tests are flaky, waiting to bypass.
-      "name": "FrameworksServicesTests_pm_presubmit"
-    },
-    {
-      // Leave postsubmit here when migrating
       "name": "FrameworksServicesTests_pm_postsubmit"
     }
   ]
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
index 43bf537..72caae3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
@@ -242,7 +242,7 @@
     private void stopUser(int userId) throws RemoteException, InterruptedException {
         runWithLatch("stop user", countDownLatch -> {
             ActivityManager.getService()
-                    .stopUser(userId, /* force= */ true, new IStopUserCallback.Stub() {
+                    .stopUserWithCallback(userId, new IStopUserCallback.Stub() {
                         @Override
                         public void userStopped(int userId) {
                             countDownLatch.countDown();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 4405a20..b91ef7c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -1256,6 +1256,30 @@
 
     @MediumTest
     @Test
+    public void testDefaultUserRestrictionsForPrivateProfile() {
+        assumeTrue(mUserManager.canAddPrivateProfile());
+        final int currentUserId = ActivityManager.getCurrentUser();
+        UserInfo privateProfileInfo = null;
+        try {
+            privateProfileInfo = createProfileForUser("Private",
+                    UserManager.USER_TYPE_PROFILE_PRIVATE, currentUserId);
+            assertThat(privateProfileInfo).isNotNull();
+        } catch (Exception e) {
+            fail("Creation of private profile failed due to " + e.getMessage());
+        }
+        assertDefaultPrivateProfileRestrictions(privateProfileInfo.getUserHandle());
+    }
+
+    private void assertDefaultPrivateProfileRestrictions(UserHandle userHandle) {
+        Bundle defaultPrivateProfileRestrictions =
+                UserTypeFactory.getDefaultPrivateProfileRestrictions();
+        for (String restriction : defaultPrivateProfileRestrictions.keySet()) {
+            assertThat(mUserManager.hasUserRestrictionForUser(restriction, userHandle)).isTrue();
+        }
+    }
+
+    @MediumTest
+    @Test
     public void testAddRestrictedProfile() throws Exception {
         if (isAutomotive() || UserManager.isHeadlessSystemUserMode()) return;
         assertWithMessage("There should be no associated restricted profiles before the test")
diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
index 510e7c4..5902caa 100644
--- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -22,6 +22,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
@@ -41,6 +42,8 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.content.Context;
+import android.hardware.power.SessionConfig;
+import android.hardware.power.SessionTag;
 import android.hardware.power.WorkDuration;
 import android.os.Binder;
 import android.os.IBinder;
@@ -63,6 +66,8 @@
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -97,6 +102,7 @@
 
     private static final long DEFAULT_HINT_PREFERRED_RATE = 16666666L;
     private static final long DEFAULT_TARGET_DURATION = 16666666L;
+    private static final long DOUBLED_TARGET_DURATION = 33333333L;
     private static final long CONCURRENCY_TEST_DURATION_SEC = 10;
     private static final int UID = Process.myUid();
     private static final int TID = Process.myPid();
@@ -106,6 +112,8 @@
     private static final int[] SESSION_TIDS_C = new int[] {TID};
     private static final long[] DURATIONS_THREE = new long[] {1L, 100L, 1000L};
     private static final long[] TIMESTAMPS_THREE = new long[] {1L, 2L, 3L};
+    private static final long[] SESSION_PTRS = new long[] {11L, 22L, 33L};
+    private static final long[] SESSION_IDS = new long[] {1L, 11L, 111L};
     private static final long[] DURATIONS_ZERO = new long[] {};
     private static final long[] TIMESTAMPS_ZERO = new long[] {};
     private static final long[] TIMESTAMPS_TWO = new long[] {1L, 2L};
@@ -129,21 +137,61 @@
 
     private HintManagerService mService;
 
+    private static Answer<Long> fakeCreateWithConfig(Long ptr, Long sessionId) {
+        return new Answer<Long>() {
+            public Long answer(InvocationOnMock invocation) {
+                ((SessionConfig) invocation.getArguments()[5]).id = sessionId;
+                return ptr;
+            }
+        };
+    }
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mNativeWrapperMock.halGetHintSessionPreferredRate())
                 .thenReturn(DEFAULT_HINT_PREFERRED_RATE);
         when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_A),
-                eq(DEFAULT_TARGET_DURATION))).thenReturn(1L);
+                eq(DEFAULT_TARGET_DURATION))).thenReturn(SESSION_PTRS[0]);
         when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_B),
-                eq(DEFAULT_TARGET_DURATION))).thenReturn(2L);
+                eq(DOUBLED_TARGET_DURATION))).thenReturn(SESSION_PTRS[1]);
         when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_C),
-                eq(0L))).thenReturn(1L);
+                eq(0L))).thenReturn(SESSION_PTRS[2]);
+        when(mNativeWrapperMock.halCreateHintSessionWithConfig(eq(TGID), eq(UID),
+                eq(SESSION_TIDS_A), eq(DEFAULT_TARGET_DURATION), anyInt(),
+                any(SessionConfig.class))).thenAnswer(fakeCreateWithConfig(SESSION_PTRS[0],
+                    SESSION_IDS[0]));
+        when(mNativeWrapperMock.halCreateHintSessionWithConfig(eq(TGID), eq(UID),
+                eq(SESSION_TIDS_B), eq(DOUBLED_TARGET_DURATION), anyInt(),
+                any(SessionConfig.class))).thenAnswer(fakeCreateWithConfig(SESSION_PTRS[1],
+                    SESSION_IDS[1]));
+        when(mNativeWrapperMock.halCreateHintSessionWithConfig(eq(TGID), eq(UID),
+                eq(SESSION_TIDS_C), eq(0L), anyInt(),
+                any(SessionConfig.class))).thenAnswer(fakeCreateWithConfig(SESSION_PTRS[2],
+                    SESSION_IDS[2]));
+
         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
         LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
     }
 
+    /**
+     * Mocks the creation calls, but without support for new createHintSessionWithConfig method
+     */
+    public void makeConfigCreationUnsupported() {
+        reset(mNativeWrapperMock);
+        when(mNativeWrapperMock.halGetHintSessionPreferredRate())
+                .thenReturn(DEFAULT_HINT_PREFERRED_RATE);
+        when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_A),
+                eq(DEFAULT_TARGET_DURATION))).thenReturn(SESSION_PTRS[0]);
+        when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_B),
+                eq(DOUBLED_TARGET_DURATION))).thenReturn(SESSION_PTRS[1]);
+        when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_C),
+                eq(0L))).thenReturn(SESSION_PTRS[2]);
+        when(mNativeWrapperMock.halCreateHintSessionWithConfig(anyInt(), anyInt(),
+            any(int[].class), anyLong(), anyInt(),
+            any(SessionConfig.class))).thenThrow(new UnsupportedOperationException());
+    }
+
     static class NativeWrapperFake extends NativeWrapper {
         @Override
         public void halInit() {
@@ -160,6 +208,12 @@
         }
 
         @Override
+        public long halCreateHintSessionWithConfig(int tgid, int uid, int[] tids,
+                long durationNanos, int tag, SessionConfig config) {
+            return 1;
+        }
+
+        @Override
         public void halPauseHintSession(long halPtr) {
         }
 
@@ -224,27 +278,57 @@
         IBinder token = new Binder();
         // Make sure we throw exception when adding a TID doesn't belong to the processes
         // In this case, we add `init` PID into the list.
+        SessionConfig config = new SessionConfig();
         assertThrows(SecurityException.class,
-                () -> service.getBinderServiceInstance().createHintSession(token,
-                        new int[]{TID, 1}, DEFAULT_TARGET_DURATION));
+                () -> service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                        new int[]{TID, 1}, DEFAULT_TARGET_DURATION, SessionTag.OTHER, config));
     }
 
     @Test
-    public void testCreateHintSession() throws Exception {
+    public void testCreateHintSessionFallback() throws Exception {
+        HintManagerService service = createService();
+        IBinder token = new Binder();
+        makeConfigCreationUnsupported();
+
+        IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_A, DEFAULT_TARGET_DURATION, SessionTag.OTHER, new SessionConfig());
+        assertNotNull(a);
+
+        IHintSession b = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_B, DOUBLED_TARGET_DURATION, SessionTag.OTHER, new SessionConfig());
+        assertNotEquals(a, b);
+
+        IHintSession c = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_C, 0L, SessionTag.OTHER, new SessionConfig());
+        assertNotNull(c);
+        verify(mNativeWrapperMock, times(3)).halCreateHintSession(anyInt(), anyInt(),
+                                                                  any(int[].class), anyLong());
+    }
+
+    @Test
+    public void testCreateHintSessionWithConfig() throws Exception {
         HintManagerService service = createService();
         IBinder token = new Binder();
 
-        IHintSession a = service.getBinderServiceInstance().createHintSession(token,
-                SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+        SessionConfig config = new SessionConfig();
+        IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_A, DEFAULT_TARGET_DURATION, SessionTag.OTHER, config);
         assertNotNull(a);
+        assertEquals(SESSION_IDS[0], config.id);
 
-        IHintSession b = service.getBinderServiceInstance().createHintSession(token,
-                SESSION_TIDS_B, DEFAULT_TARGET_DURATION);
+        SessionConfig config2 = new SessionConfig();
+        IHintSession b = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_B, DOUBLED_TARGET_DURATION, SessionTag.APP, config2);
         assertNotEquals(a, b);
+        assertEquals(SESSION_IDS[1], config2.id);
 
-        IHintSession c = service.getBinderServiceInstance().createHintSession(token,
-                SESSION_TIDS_C, 0L);
+        SessionConfig config3 = new SessionConfig();
+        IHintSession c = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_C, 0L, SessionTag.GAME, config3);
         assertNotNull(c);
+        assertEquals(SESSION_IDS[2], config3.id);
+        verify(mNativeWrapperMock, times(3)).halCreateHintSessionWithConfig(anyInt(), anyInt(),
+                any(int[].class), anyLong(), anyInt(), any(SessionConfig.class));
     }
 
     @Test
@@ -253,7 +337,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
 
         // Set session to background and calling updateHintAllowed() would invoke pause();
         service.mUidObserver.onUidStateChanged(
@@ -288,8 +373,8 @@
         HintManagerService service = createService();
         IBinder token = new Binder();
 
-        IHintSession a = service.getBinderServiceInstance().createHintSession(token,
-                SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+        IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_A, DEFAULT_TARGET_DURATION, SessionTag.OTHER, new SessionConfig());
 
         a.close();
         verify(mNativeWrapperMock, times(1)).halCloseHintSession(anyLong());
@@ -300,8 +385,8 @@
         HintManagerService service = createService();
         IBinder token = new Binder();
 
-        IHintSession a = service.getBinderServiceInstance().createHintSession(token,
-                SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+        IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                SESSION_TIDS_A, DEFAULT_TARGET_DURATION, SessionTag.OTHER, new SessionConfig());
 
         assertThrows(IllegalArgumentException.class, () -> {
             a.updateTargetWorkDuration(-1L);
@@ -321,7 +406,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
 
         a.updateTargetWorkDuration(100L);
         a.reportActualWorkDuration(DURATIONS_THREE, TIMESTAMPS_THREE);
@@ -363,7 +449,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                    SessionTag.OTHER, new SessionConfig());
 
         a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET);
         verify(mNativeWrapperMock, times(1)).halSendHint(anyLong(),
@@ -389,7 +476,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                    SessionTag.OTHER, new SessionConfig());
 
         service.mUidObserver.onUidStateChanged(
                 a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
@@ -410,7 +498,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
 
         service.mUidObserver.onUidStateChanged(
                 a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0);
@@ -423,7 +512,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
 
         a.updateTargetWorkDuration(100L);
 
@@ -454,10 +544,12 @@
         int threadCount = 3;
         int[] tids1 = createThreads(threadCount, stopLatch1);
         long sessionPtr1 = 111;
-        when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(tids1),
-                eq(DEFAULT_TARGET_DURATION))).thenReturn(sessionPtr1);
+        when(mNativeWrapperMock.halCreateHintSessionWithConfig(eq(TGID), eq(UID), eq(tids1),
+                eq(DEFAULT_TARGET_DURATION), anyInt(), any(SessionConfig.class)))
+                .thenReturn(sessionPtr1);
         AppHintSession session1 = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, tids1, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, tids1, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
         assertNotNull(session1);
 
         // for test only to avoid conflicting with any real thread that exists on device
@@ -473,10 +565,12 @@
         tids2WithIsolated[threadCount] = isoProc1;
         tids2WithIsolated[threadCount + 1] = isoProc2;
         long sessionPtr2 = 222;
-        when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(tids2WithIsolated),
-                eq(DEFAULT_TARGET_DURATION))).thenReturn(sessionPtr2);
+        when(mNativeWrapperMock.halCreateHintSessionWithConfig(eq(TGID), eq(UID),
+                eq(tids2WithIsolated), eq(DEFAULT_TARGET_DURATION), anyInt(),
+                any(SessionConfig.class))).thenReturn(sessionPtr2);
         AppHintSession session2 = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, tids2WithIsolated, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, tids2WithIsolated,
+                        DEFAULT_TARGET_DURATION, SessionTag.OTHER, new SessionConfig());
         assertNotNull(session2);
 
         // trigger clean up through UID state change by making the process background
@@ -608,7 +702,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
 
         a.setMode(0, true);
         verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(),
@@ -726,7 +821,8 @@
             AtomicReference<Boolean> shouldRun) throws Exception {
         IBinder token = new Binder();
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
         // we will start some threads and get their valid TIDs to update
         int threadCount = 3;
         // the list of TIDs
@@ -793,7 +889,8 @@
         IBinder token = new Binder();
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
-                .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
+                .createHintSessionWithConfig(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION,
+                        SessionTag.OTHER, new SessionConfig());
 
         a.updateTargetWorkDuration(100L);
         a.reportActualWorkDuration2(WORK_DURATIONS_FIVE);
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 515898a..e6cf0c38 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -50,6 +50,7 @@
         "SettingsLib",
         "libprotobuf-java-lite",
         "platformprotoslite",
+        "platform-parametric-runner-lib",
     ],
 
     libs: [
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java
index ad25d76..770712a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java
@@ -26,14 +26,18 @@
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 import static android.media.AudioAttributes.USAGE_UNKNOWN;
 import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
+import static com.android.server.notification.NotificationChannelExtractor.RESTRICT_AUDIO_ATTRIBUTES;
 import static com.google.common.truth.Truth.assertThat;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
 
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Flags;
@@ -43,12 +47,14 @@
 import android.app.Person;
 import android.media.AudioAttributes;
 import android.net.Uri;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 
+import com.android.internal.compat.IPlatformCompat;
 import com.android.server.UiServiceTestCase;
 
 import org.junit.Before;
@@ -60,6 +66,8 @@
 public class NotificationChannelExtractorTest extends UiServiceTestCase {
 
     @Mock RankingConfig mConfig;
+    @Mock
+    IPlatformCompat mPlatformCompat;
 
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
@@ -73,6 +81,7 @@
         mExtractor = new NotificationChannelExtractor();
         mExtractor.setConfig(mConfig);
         mExtractor.initialize(mContext, null);
+        mExtractor.setCompatChangeLogger(mPlatformCompat);
     }
 
     private NotificationRecord getRecord(NotificationChannel channel, Notification n) {
@@ -82,7 +91,7 @@
     }
 
     @Test
-    public void testExtractsUpdatedConversationChannel() {
+    public void testExtractsUpdatedConversationChannel() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
         final Notification n = new Notification.Builder(getContext())
                 .setContentTitle("foo")
@@ -101,7 +110,7 @@
     }
 
     @Test
-    public void testInvalidShortcutFlagEnabled_looksUpCorrectNonChannel() {
+    public void testInvalidShortcutFlagEnabled_looksUpCorrectNonChannel() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
         final Notification n = new Notification.Builder(getContext())
                 .setContentTitle("foo")
@@ -122,7 +131,7 @@
     }
 
     @Test
-    public void testInvalidShortcutFlagDisabled_looksUpCorrectChannel() {
+    public void testInvalidShortcutFlagDisabled_looksUpCorrectChannel() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
         final Notification n = new Notification.Builder(getContext())
                 .setContentTitle("foo")
@@ -143,7 +152,7 @@
 
     @Test
     @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_CALL)
-    public void testAudioAttributes_callStyleCanUseCallUsage() {
+    public void testAudioAttributes_callStyleCanUseCallUsage() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         channel.setSound(Uri.EMPTY, new AudioAttributes.Builder()
                 .setUsage(USAGE_NOTIFICATION_RINGTONE)
@@ -162,11 +171,12 @@
         assertThat(mExtractor.process(r)).isNull();
         assertThat(r.getAudioAttributes().getUsage()).isEqualTo(USAGE_NOTIFICATION_RINGTONE);
         assertThat(r.getChannel()).isEqualTo(channel);
+        verify(mPlatformCompat, never()).reportChangeByUid(anyLong(), anyInt());
     }
 
     @Test
     @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_CALL)
-    public void testAudioAttributes_nonCallStyleCannotUseCallUsage() {
+    public void testAudioAttributes_nonCallStyleCannotUseCallUsage() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         channel.setSound(Uri.EMPTY, new AudioAttributes.Builder()
                 .setUsage(USAGE_NOTIFICATION_RINGTONE)
@@ -180,13 +190,14 @@
         assertThat(mExtractor.process(r)).isNull();
         // instance updated
         assertThat(r.getAudioAttributes().getUsage()).isEqualTo(USAGE_NOTIFICATION);
+        verify(mPlatformCompat).reportChangeByUid(RESTRICT_AUDIO_ATTRIBUTES, r.getUid());
         // in-memory channel unchanged
         assertThat(channel.getAudioAttributes().getUsage()).isEqualTo(USAGE_NOTIFICATION_RINGTONE);
     }
 
     @Test
     @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_ALARM)
-    public void testAudioAttributes_alarmCategoryCanUseAlarmUsage() {
+    public void testAudioAttributes_alarmCategoryCanUseAlarmUsage() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         channel.setSound(Uri.EMPTY, new AudioAttributes.Builder()
                 .setUsage(USAGE_ALARM)
@@ -201,11 +212,12 @@
         assertThat(mExtractor.process(r)).isNull();
         assertThat(r.getAudioAttributes().getUsage()).isEqualTo(USAGE_ALARM);
         assertThat(r.getChannel()).isEqualTo(channel);
+        verify(mPlatformCompat, never()).reportChangeByUid(anyLong(), anyInt());
     }
 
     @Test
     @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_ALARM)
-    public void testAudioAttributes_nonAlarmCategoryCannotUseAlarmUsage() {
+    public void testAudioAttributes_nonAlarmCategoryCannotUseAlarmUsage() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         channel.setSound(Uri.EMPTY, new AudioAttributes.Builder()
                 .setUsage(USAGE_ALARM)
@@ -219,13 +231,14 @@
         assertThat(mExtractor.process(r)).isNull();
         // instance updated
         assertThat(r.getAudioAttributes().getUsage()).isEqualTo(USAGE_NOTIFICATION);
+        verify(mPlatformCompat).reportChangeByUid(RESTRICT_AUDIO_ATTRIBUTES, r.getUid());
         // in-memory channel unchanged
         assertThat(channel.getAudioAttributes().getUsage()).isEqualTo(USAGE_ALARM);
     }
 
     @Test
     @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_MEDIA)
-    public void testAudioAttributes_noMediaUsage() {
+    public void testAudioAttributes_noMediaUsage() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         channel.setSound(Uri.EMPTY, new AudioAttributes.Builder()
                 .setUsage(USAGE_MEDIA)
@@ -239,13 +252,14 @@
         assertThat(mExtractor.process(r)).isNull();
         // instance updated
         assertThat(r.getAudioAttributes().getUsage()).isEqualTo(USAGE_NOTIFICATION);
+        verify(mPlatformCompat).reportChangeByUid(RESTRICT_AUDIO_ATTRIBUTES, r.getUid());
         // in-memory channel unchanged
         assertThat(channel.getAudioAttributes().getUsage()).isEqualTo(USAGE_MEDIA);
     }
 
     @Test
     @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_MEDIA)
-    public void testAudioAttributes_noUnknownUsage() {
+    public void testAudioAttributes_noUnknownUsage() throws RemoteException {
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         channel.setSound(Uri.EMPTY, new AudioAttributes.Builder()
                 .setUsage(USAGE_UNKNOWN)
@@ -259,6 +273,7 @@
         assertThat(mExtractor.process(r)).isNull();
         // instance updated
         assertThat(r.getAudioAttributes().getUsage()).isEqualTo(USAGE_NOTIFICATION);
+        verify(mPlatformCompat).reportChangeByUid(RESTRICT_AUDIO_ATTRIBUTES, r.getUid());
         // in-memory channel unchanged
         assertThat(channel.getAudioAttributes().getUsage()).isEqualTo(USAGE_UNKNOWN);
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index ae36839..983e694 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -70,6 +70,7 @@
 import android.os.UserHandle;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.service.notification.INotificationListener;
+import android.service.notification.IStatusBarNotificationHolder;
 import android.service.notification.NotificationListenerFilter;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRankingUpdate;
@@ -90,6 +91,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -154,6 +156,11 @@
                 .thenReturn(new ArrayList<>());
         mNm.mHandler = mock(NotificationManagerService.WorkerHandler.class);
         mNm.mAssistants = mock(NotificationManagerService.NotificationAssistants.class);
+        FieldSetter.setField(mNm,
+                NotificationManagerService.class.getDeclaredField("mListeners"),
+                mListeners);
+        doReturn(android.service.notification.NotificationListenerService.TRIM_FULL)
+                .when(mListeners).getOnNotificationPostedTrim(any());
     }
 
     @Test
@@ -827,6 +834,68 @@
         verify(mListeners, never()).redactStatusBarNotification(eq(sbn));
     }
 
+    @Test
+    public void testListenerPost_UpdateLifetimeExtended() throws Exception {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
+
+        // Create original notification, with FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY.
+        String pkg = "pkg";
+        int uid = 9;
+        UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+        NotificationChannel channel = new NotificationChannel("id", "name",
+                NotificationManager.IMPORTANCE_HIGH);
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setFlag(Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, true);
+        StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, 8, "tag", uid, 0,
+                nb.build(), userHandle, null, 0);
+        NotificationRecord old = new NotificationRecord(mContext, sbn, channel);
+
+        // Creates updated notification (without FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY)
+        Notification.Builder nb2 = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("new title")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setFlag(Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, false);
+        StatusBarNotification sbn2 = new StatusBarNotification(pkg, pkg, 8, "tag", uid, 0,
+                nb2.build(), userHandle, null, 0);
+        NotificationRecord toPost = new NotificationRecord(mContext, sbn2, channel);
+
+        // Create system ui-like service.
+        ManagedServices.ManagedServiceInfo info = mListeners.new ManagedServiceInfo(
+                null, new ComponentName("a", "a"), sbn2.getUserId(), false, null, 33, 33);
+        info.isSystemUi = true;
+        INotificationListener l1 = mock(INotificationListener.class);
+        info.service = l1;
+        List<ManagedServices.ManagedServiceInfo> services = ImmutableList.of(info);
+        when(mListeners.getServices()).thenReturn(services);
+
+        FieldSetter.setField(mNm,
+                NotificationManagerService.class.getDeclaredField("mHandler"),
+                mock(NotificationManagerService.WorkerHandler.class));
+        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
+        doReturn(mock(NotificationRankingUpdate.class)).when(mNm).makeRankingUpdateLocked(info);
+        doReturn(false).when(mNm).isInLockDownMode(anyInt());
+        doNothing().when(mNm).updateUriPermissions(any(), any(), any(), anyInt());
+        doReturn(sbn2).when(mListeners).redactStatusBarNotification(sbn2);
+        doReturn(sbn2).when(mListeners).redactStatusBarNotification(any());
+
+        // The notification change is posted to the service listener.
+        mListeners.notifyPostedLocked(toPost, old);
+
+        // Verify that the post occcurs with the updated notification value.
+        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        verify(mNm.mHandler, times(1)).post(runnableCaptor.capture());
+        runnableCaptor.getValue().run();
+        ArgumentCaptor<IStatusBarNotificationHolder> sbnCaptor =
+                ArgumentCaptor.forClass(IStatusBarNotificationHolder.class);
+        verify(l1, times(1)).onNotificationPosted(sbnCaptor.capture(), any());
+        StatusBarNotification sbnResult = sbnCaptor.getValue().get();
+        assertThat(sbnResult.getNotification()
+                .extras.getCharSequence(Notification.EXTRA_TITLE).toString())
+                .isEqualTo("new title");
+    }
+
     /**
      * Helper method to test the thread safety of some operations.
      *
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 6106278..ce7a0a0 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -111,9 +111,11 @@
 import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
+import static com.android.server.notification.Flags.FLAG_ALL_NOTIFS_NEED_TTL;
 import static com.android.server.notification.NotificationManagerService.BITMAP_DURATION;
 import static com.android.server.notification.NotificationManagerService.DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
 import static com.android.server.notification.NotificationManagerService.NOTIFICATION_TTL;
+import static com.android.server.notification.NotificationManagerService.TAG;
 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED;
 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED;
@@ -138,7 +140,24 @@
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+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.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
@@ -168,6 +187,8 @@
 import android.app.RemoteInputHistoryItem;
 import android.app.StatsManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.app.job.JobScheduler;
+import android.app.role.RoleManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.companion.AssociationInfo;
 import android.companion.AssociationRequest;
@@ -184,9 +205,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.LauncherApps;
+import android.content.pm.ModuleInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.UserInfo;
@@ -217,6 +240,7 @@
 import android.permission.PermissionManager;
 import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.platform.test.rule.LimitDevicesRule;
 import android.provider.DeviceConfig;
@@ -235,7 +259,8 @@
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
 import android.telecom.TelecomManager;
-import android.testing.AndroidTestingRunner;
+import android.testing.TestWithLooperRule;
+import android.testing.TestableContentResolver;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.testing.TestablePermissions;
@@ -245,8 +270,10 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
+import android.util.Log;
 import android.util.Pair;
 import android.util.Xml;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.RemoteViews;
 
 import androidx.test.InstrumentationRegistry;
@@ -259,6 +286,7 @@
 import com.android.internal.logging.InstanceIdSequenceFake;
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.DeviceIdleInternal;
@@ -285,7 +313,6 @@
 
 import com.google.android.collect.Lists;
 import com.google.common.collect.ImmutableList;
-
 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
@@ -306,6 +333,8 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -322,9 +351,9 @@
 import java.util.function.Consumer;
 
 @SmallTest
-@RunWith(AndroidTestingRunner.class)
-@SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
+@RunWith(ParameterizedAndroidJunit4.class)
 @RunWithLooper
+@SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
 public class NotificationManagerServiceTest extends UiServiceTestCase {
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
     private static final String TEST_PACKAGE = "The.name.is.Package.Test.Package";
@@ -369,6 +398,8 @@
     @Mock
     private PermissionHelper mPermissionHelper;
     private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();
+    @Rule(order = Integer.MAX_VALUE)
+    public TestWithLooperRule mlooperRule = new TestWithLooperRule();
     private TestableLooper mTestableLooper;
     @Mock
     private RankingHelper mRankingHelper;
@@ -415,8 +446,8 @@
     private final TestPostNotificationTrackerFactory mPostNotificationTrackerFactory =
             new TestPostNotificationTrackerFactory();
 
-    @Mock
-    IIntentSender pi1;
+    private PendingIntent mActivityIntent;
+    private PendingIntent mActivityIntentImmutable;
 
     private static final int MAX_POST_DELAY = 1000;
 
@@ -429,6 +460,9 @@
 
     private static final String VALID_CONVO_SHORTCUT_ID = "shortcut";
     private static final String SEARCH_SELECTOR_PKG = "searchSelector";
+    private static final String ADSERVICES_MODULE_PKG = "com.android.adservices";
+    private static final String ADSERVICES_APK_PKG = "com.android.adservices.api";
+
     @Mock
     private NotificationListeners mListeners;
     @Mock
@@ -465,6 +499,7 @@
     StatsManager mStatsManager;
     @Mock
     AlarmManager mAlarmManager;
+    @Mock JobScheduler mJobScheduler;
     @Mock
     MultiRateLimiter mToastRateLimiter;
     BroadcastReceiver mPackageIntentReceiver;
@@ -508,6 +543,16 @@
         }
     }
 
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getParams() {
+        return FlagsParameterization.allCombinationsOf(
+                FLAG_ALL_NOTIFS_NEED_TTL);
+    }
+
+    public NotificationManagerServiceTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
     @Before
     public void setUp() throws Exception {
         // Shell permisssions will override permissions of our app, so add all necessary permissions
@@ -540,12 +585,22 @@
         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
         LocalServices.removeServiceForTest(PermissionPolicyInternal.class);
         LocalServices.addService(PermissionPolicyInternal.class, mPermissionPolicyInternal);
+        LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+        LocalServices.addService(ShortcutServiceInternal.class, mShortcutServiceInternal);
         mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
         mContext.addMockSystemService(NotificationManager.class, mMockNm);
+        mContext.addMockSystemService(RoleManager.class, mock(RoleManager.class));
+        mContext.addMockSystemService(Context.LAUNCHER_APPS_SERVICE, mLauncherApps);
+        mContext.addMockSystemService(Context.USER_SERVICE, mUm);
+        mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE,
+                mock(AccessibilityManager.class));
 
         doNothing().when(mContext).sendBroadcast(any(), anyString());
         doNothing().when(mContext).sendBroadcastAsUser(any(), any());
         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
+        TestableContentResolver cr = mock(TestableContentResolver.class);
+        when(mContext.getContentResolver()).thenReturn(cr);
+        doNothing().when(cr).registerContentObserver(any(), anyBoolean(), any(), anyInt());
 
         setDpmAppOppsExemptFromDismissal(false);
 
@@ -648,11 +703,16 @@
                 });
 
         // TODO (b/291907312): remove feature flag
-        // NOTE: Prefer using the @EnableFlag annotation where possible. Do not add any android.app
+        // NOTE: Prefer using the @EnableFlags annotation where possible. Do not add any android.app
         //  flags here.
         mSetFlagsRule.disableFlags(
                 Flags.FLAG_POLITE_NOTIFICATIONS, Flags.FLAG_AUTOGROUP_SUMMARY_ICON_UPDATE);
 
+        mActivityIntent = spy(PendingIntent.getActivity(mContext, 0,
+                new Intent().setPackage(mPkg), PendingIntent.FLAG_MUTABLE));
+        mActivityIntentImmutable = spy(PendingIntent.getActivity(mContext, 0,
+                new Intent().setPackage(mPkg), FLAG_IMMUTABLE));
+
         initNMS();
     }
 
@@ -689,10 +749,15 @@
                 mPowerManager, mPostNotificationTrackerFactory);
 
         mService.setAttentionHelper(mAttentionHelper);
+        mService.setLockPatternUtils(mock(LockPatternUtils.class));
 
         // Return first true for RoleObserver main-thread check
         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
-
+        ModuleInfo moduleInfo = new ModuleInfo();
+        moduleInfo.setApexModuleName(ADSERVICES_MODULE_PKG);
+        moduleInfo.setApkInApexPackageNames(List.of(ADSERVICES_APK_PKG));
+        when(mPackageManagerClient.getInstalledModules(anyInt()))
+                .thenReturn(List.of(moduleInfo));
         if (upToBootPhase >= SystemService.PHASE_SYSTEM_SERVICES_READY) {
             mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
         }
@@ -749,7 +814,10 @@
         }
         assertNotNull("package intent receiver should exist", mPackageIntentReceiver);
         assertNotNull("User-switch receiver should exist", mUserSwitchIntentReceiver);
-        assertNotNull("Notification timeout receiver should exist", mNotificationTimeoutReceiver);
+        if (!Flags.allNotifsNeedTtl()) {
+            assertNotNull("Notification timeout receiver should exist",
+                    mNotificationTimeoutReceiver);
+        }
 
         // Pretend the shortcut exists
         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
@@ -834,9 +902,17 @@
         if (mFile != null) mFile.delete();
         clearDeviceConfig();
 
+        if (mActivityIntent != null) {
+            mActivityIntent.cancel();
+        }
+
+        mService.clearNotifications();
+        TestableLooper.get(this).processAllMessages();
+
         try {
             mService.onDestroy();
         } catch (IllegalStateException | IllegalArgumentException e) {
+            Log.e(TAG, "failed to destroy", e);
             // can throw if a broadcast receiver was never registered
         }
 
@@ -846,6 +922,11 @@
         // could cause issues, for example, messages that remove/cancel shown toasts (this causes
         // problematic interactions with mocks when they're no longer working as expected).
         mWorkerHandler.removeCallbacksAndMessages(null);
+
+        if (TestableLooper.get(this) != null) {
+            // Must remove static reference to this test object to prevent leak (b/261039202)
+            TestableLooper.remove(this);
+        }
     }
 
     private void simulatePackageSuspendBroadcast(boolean suspend, String pkg,
@@ -1005,7 +1086,9 @@
         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
                 .setContentTitle("foo")
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
-                .addAction(new Notification.Action.Builder(null, "test", null).build());
+                .addAction(new Notification.Action.Builder(null, "test", mActivityIntent).build())
+                .addAction(new Notification.Action.Builder(
+                        null, "test", mActivityIntentImmutable).build());
         if (extender != null) {
             nb.extend(extender);
         }
@@ -1045,18 +1128,20 @@
 
     private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
             String tag) {
-        return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false);
+        return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false, true);
     }
 
     private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata,
-            NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) {
+            NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary,
+            boolean mutable) {
         if (channel == null) {
             channel = mTestNotificationChannel;
         }
         if (tag == null) {
             tag = "tag";
         }
-        Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary);
+        Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey,
+                isSummary, mutable);
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id,
                 tag, mUid, 0,
                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -1129,18 +1214,15 @@
     }
 
     private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
-            String groupKey, boolean isSummary) {
+            String groupKey, boolean isSummary, boolean mutable) {
         // Give it a person
         Person person = new Person.Builder()
                 .setName("bubblebot")
                 .build();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
-                new Intent().setPackage(mContext.getPackageName()),
-                PendingIntent.FLAG_MUTABLE);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
-                inputIntent).addRemoteInput(remoteInput)
+                mutable ? mActivityIntent : mActivityIntentImmutable).addRemoteInput(remoteInput)
                 .build();
         // Make it messaging style
         Notification.Builder nb = new Notification.Builder(mContext,
@@ -1167,17 +1249,14 @@
     }
 
     private Notification.BubbleMetadata getBubbleMetadata() {
-        PendingIntent pendingIntent = mock(PendingIntent.class);
-        Intent intent = mock(Intent.class);
-        when(pendingIntent.getIntent()).thenReturn(intent);
-        when(pendingIntent.getTarget()).thenReturn(pi1);
-
         ActivityInfo info = new ActivityInfo();
         info.resizeMode = RESIZE_MODE_RESIZEABLE;
-        when(intent.resolveActivityInfo(any(), anyInt())).thenReturn(info);
+        ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = info;
+        when(mPackageManagerClient.resolveActivity(any(), anyInt())).thenReturn(ri);
 
         return new Notification.BubbleMetadata.Builder(
-                pendingIntent,
+                mActivityIntent,
                 Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon))
                 .build();
     }
@@ -1189,7 +1268,8 @@
 
         // Notification that has bubble metadata
         NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */,
-                mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */);
+                mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */,
+                true);
 
         mBinderService.enqueueNotificationWithTag(mPkg, mPkg, nrBubble.getSbn().getTag(),
                 nrBubble.getSbn().getId(), nrBubble.getSbn().getNotification(),
@@ -1203,7 +1283,8 @@
 
         // Notification without bubble metadata
         NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */,
-                mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */);
+                mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */,
+                true);
 
         mBinderService.enqueueNotificationWithTag(mPkg, mPkg, nrPlain.getSbn().getTag(),
                 nrPlain.getSbn().getId(), nrPlain.getSbn().getNotification(),
@@ -1215,7 +1296,8 @@
 
         // Summary notification for both of those
         NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */,
-                mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */);
+                mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */,
+                true);
 
         if (summaryAutoCancel) {
             nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL;
@@ -1232,6 +1314,7 @@
     }
 
     @Test
+    @DisableFlags(FLAG_ALL_NOTIFS_NEED_TTL)
     public void testLimitTimeOutBroadcast() {
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
@@ -2501,8 +2584,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testCancelWithTagDoesNotCancelLifetimeExtended() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         final NotificationRecord notif = generateNotificationRecord(null);
         notif.getSbn().getNotification().flags =
                 Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
@@ -2529,19 +2612,34 @@
         assertThat(captor.getValue().getNotification().flags
                 & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(
                 FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY);
-
-        mSetFlagsRule.disableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
-        mBinderService.cancelNotificationWithTag(mPkg, mPkg, sbn.getTag(), sbn.getId(),
-                sbn.getUserId());
-        waitForIdle();
-
-        assertThat(mBinderService.getActiveNotifications(sbn.getPackageName()).length).isEqualTo(0);
-        assertThat(mService.getNotificationRecordCount()).isEqualTo(0);
     }
 
     @Test
-    public void testCancelAllDoesNotCancelLifetimeExtended() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
+    public void testCancelAllClearsLifetimeExtended() throws Exception {
+        final NotificationRecord notif = generateNotificationRecord(
+                mTestNotificationChannel, 1, "group", true);
+        notif.getNotification().flags |= Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
+        mService.addNotification(notif);
+        StatusBarNotification[] notifs =
+                mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
+        assertThat(notifs.length).isEqualTo(1);
+
+        // Simulate a "cancel all" received.
+        mService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
+                notif.getUserId());
+        waitForIdle();
+        notifs = mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
+        assertThat(notifs.length).isEqualTo(0);
+
+        // Test that no update post is sent to System UI.
+        verify(mWorkerHandler, never())
+                .post(any(NotificationManagerService.EnqueueNotificationRunnable.class));
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
+    public void testAppCancelAllDoesNotCancelLifetimeExtended() throws Exception {
         // Adds a lifetime extended notification.
         final NotificationRecord notif = generateNotificationRecord(mTestNotificationChannel, 1,
                 null, false);
@@ -2978,9 +3076,9 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testCancelNotificationsFromListener_clearAll_NoClearLifetimeExt()
             throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         final NotificationRecord notif = generateNotificationRecord(
                 mTestNotificationChannel, 1, null, false);
         notif.getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
@@ -3211,9 +3309,9 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testCancelNotificationsFromListener_byKey_NoClearLifetimeExt()
             throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         final NotificationRecord notif = generateNotificationRecord(
                 mTestNotificationChannel, 3, null, false);
         notif.getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
@@ -5695,12 +5793,16 @@
         verify(mZenModeHelper).updateZenRulesOnLocaleChange();
     }
 
-    private void simulateNotificationTimeoutBroadcast(String notificationKey) {
-        final Bundle extras = new Bundle();
-        extras.putString(EXTRA_KEY, notificationKey);
-        final Intent intent = new Intent(ACTION_NOTIFICATION_TIMEOUT);
-        intent.putExtras(extras);
-        mNotificationTimeoutReceiver.onReceive(getContext(), intent);
+    private void simulateNotificationTimeout(String notificationKey) {
+        if (Flags.allNotifsNeedTtl()) {
+            mService.mNotificationManagerPrivate.timeoutNotification(notificationKey);
+        } else {
+            final Bundle extras = new Bundle();
+            extras.putString(EXTRA_KEY, notificationKey);
+            final Intent intent = new Intent(ACTION_NOTIFICATION_TIMEOUT);
+            intent.putExtras(extras);
+            mNotificationTimeoutReceiver.onReceive(getContext(), intent);
+        }
     }
 
     @Test
@@ -5709,7 +5811,7 @@
                 mTestNotificationChannel, 1, null, false);
         mService.addNotification(notif);
 
-        simulateNotificationTimeoutBroadcast(notif.getKey());
+        simulateNotificationTimeout(notif.getKey());
         waitForIdle();
 
         // Check that the notification was cancelled.
@@ -5725,7 +5827,7 @@
         notif.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mService.addNotification(notif);
 
-        simulateNotificationTimeoutBroadcast(notif.getKey());
+        simulateNotificationTimeout(notif.getKey());
         waitForIdle();
 
         // Check that the notification was not cancelled.
@@ -5741,7 +5843,7 @@
         notif.getSbn().getNotification().flags = Notification.FLAG_USER_INITIATED_JOB;
         mService.addNotification(notif);
 
-        simulateNotificationTimeoutBroadcast(notif.getKey());
+        simulateNotificationTimeout(notif.getKey());
         waitForIdle();
 
         // Check that the notification was not cancelled.
@@ -5751,15 +5853,15 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testTimeout_NoCancelLifetimeExtensionNotification() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         // Create a notification with FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY
         final NotificationRecord notif = generateNotificationRecord(null);
         notif.getSbn().getNotification().flags =
                 Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
         mService.addNotification(notif);
 
-        simulateNotificationTimeoutBroadcast(notif.getKey());
+        simulateNotificationTimeout(notif.getKey());
         waitForIdle();
 
         // Check that the notification was not cancelled.
@@ -5839,8 +5941,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testStats_DirectReplyLifetimeExtendedPostsUpdate() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
         mService.addNotification(r);
@@ -5864,6 +5966,45 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
+    public void testUpdate_DirectReplyLifetimeExtendedUpdateSucceeds() throws Exception {
+        // Creates a lifetime extended notification.
+        NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
+        original.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
+        mService.addNotification(original);
+
+        // Post an update for that notification.
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, original.getSbn().getId(),
+                original.getSbn().getTag(), mUid, 0,
+                new Notification.Builder(mContext, mTestNotificationChannel.getId())
+                        .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                        .setContentTitle("new title").build(),
+                UserHandle.getUserHandleForUid(mUid), null, 0);
+        NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+        mService.addEnqueuedNotification(update);
+
+        NotificationManagerService.PostNotificationRunnable runnable =
+                mService.new PostNotificationRunnable(update.getKey(),
+                        update.getSbn().getPackageName(),
+                        update.getUid(),
+                        mPostNotificationTrackerFactory.newTracker(null));
+        runnable.run();
+        waitForIdle();
+
+        // Checks the update was sent, and that update contains the new title, and does not contain
+        // the lifetime extension flag.
+        ArgumentCaptor<NotificationRecord> captor =
+                ArgumentCaptor.forClass(NotificationRecord.class);
+        verify(mListeners, times(1)).prepareNotifyPostedLocked(captor.capture(), any(),
+                anyBoolean());
+        assertThat(captor.getValue().getNotification().flags
+                & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0);
+        assertThat(captor.getValue()
+                .getNotification().extras.getCharSequence(Notification.EXTRA_TITLE).toString())
+                .isEqualTo("new title");
+    }
+
+    @Test
     public void testStats_updatedOnUserExpansion() throws Exception {
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
@@ -6662,6 +6803,7 @@
         verify(visitor, times(1)).accept(eq(personIcon.getUri()));
         verify(visitor, times(1)).accept(eq(verificationIcon.getUri()));
         verify(visitor, times(1)).accept(eq(hangUpUri));
+        hangUpIntent.cancel();
     }
 
     @Test
@@ -6691,6 +6833,8 @@
         verify(visitor, times(1)).accept(eq(verificationIcon.getUri()));
         verify(visitor, times(1)).accept(eq(answerIntent.getIntent().getData()));
         verify(visitor, times(1)).accept(eq(declineUri));
+        answerIntent.cancel();
+        declineIntent.cancel();
     }
 
     @Test
@@ -6767,6 +6911,9 @@
         verify(visitor, times(1)).accept(eq(actionIntentUri));
         verify(visitor).accept(eq(wearActionIcon.getUri()));
         verify(visitor, times(1)).accept(eq(wearActionIntentUri));
+        displayIntent.cancel();
+        actionIntent.cancel();
+        wearActionIntent.cancel();
     }
 
     @Test
@@ -6788,6 +6935,8 @@
 
         verify(visitor, times(1)).accept(eq(contentIntentUri));
         verify(visitor, times(1)).accept(eq(deleteIntentUri));
+        contentIntent.cancel();
+        deleteIntent.cancel();
     }
 
     @Test
@@ -6813,6 +6962,8 @@
 
         verify(visitor, times(1)).accept(eq(readPendingIntentUri));
         verify(visitor, times(1)).accept(eq(replyPendingIntentUri));
+        readPendingIntent.cancel();
+        replyPendingIntent.cancel();
     }
 
     @Test
@@ -7916,8 +8067,9 @@
         setAppInForegroundForToasts(mUid, true);
 
         // enqueue toast -> toast should still enqueue
-        enqueueToast(testPackage, new TestableToastCallback());
+        boolean wasEnqueued = enqueueToast(testPackage, new TestableToastCallback());
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
     }
 
     @Test
@@ -7936,8 +8088,9 @@
         setAppInForegroundForToasts(mUid, false);
 
         // enqueue toast -> no toasts enqueued
-        enqueueToast(testPackage, new TestableToastCallback());
+        boolean wasEnqueued = enqueueToast(testPackage, new TestableToastCallback());
         assertEquals(0, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isFalse();
     }
 
     @Test
@@ -8045,8 +8198,9 @@
         setAppInForegroundForToasts(mUid, true);
 
         // enqueue toast -> toast should still enqueue
-        enqueueTextToast(testPackage, "Text");
+        boolean wasEnqueued = enqueueTextToast(testPackage, "Text");
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
     }
 
     @Test
@@ -8065,8 +8219,9 @@
         setAppInForegroundForToasts(mUid, false);
 
         // enqueue toast -> toast should still enqueue
-        enqueueTextToast(testPackage, "Text");
+        boolean wasEnqueued = enqueueTextToast(testPackage, "Text");
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
     }
 
     @Test
@@ -8220,8 +8375,9 @@
         setAppInForegroundForToasts(mUid, false);
 
         // enqueue toast -> toast should still enqueue
-        enqueueToast(testPackage, new TestableToastCallback());
+        boolean wasEnqueued = enqueueToast(testPackage, new TestableToastCallback());
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
         verify(mAm).setProcessImportant(any(), anyInt(), eq(true), any());
     }
 
@@ -8242,8 +8398,9 @@
         setAppInForegroundForToasts(mUid, true);
 
         // enqueue toast -> toast should still enqueue
-        enqueueTextToast(testPackage, "Text");
+        boolean wasEnqueued = enqueueTextToast(testPackage, "Text");
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
         verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
     }
 
@@ -8264,8 +8421,9 @@
         setAppInForegroundForToasts(mUid, false);
 
         // enqueue toast -> toast should still enqueue
-        enqueueTextToast(testPackage, "Text");
+        boolean wasEnqueued = enqueueTextToast(testPackage, "Text");
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
         verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
     }
 
@@ -8274,7 +8432,8 @@
         allowTestPackageToToast();
 
         // enqueue toast -> no toasts enqueued
-        enqueueTextToast(TEST_PACKAGE, "Text");
+        boolean wasEnqueued = enqueueTextToast(TEST_PACKAGE, "Text");
+        assertThat(wasEnqueued).isTrue();
 
         verifyToastShownForTestPackage("Text", DEFAULT_DISPLAY);
     }
@@ -8367,10 +8526,11 @@
                 .thenReturn(false);
 
         // enqueue toast -> no toasts enqueued
-        enqueueTextToast(testPackage, "Text");
+        boolean wasEnqueued = enqueueTextToast(testPackage, "Text");
         verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
                 anyInt());
         assertEquals(0, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isFalse();
     }
 
     @Test
@@ -8390,10 +8550,11 @@
         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
 
         // enqueue toast -> no toasts enqueued
-        enqueueToast(testPackage, new TestableToastCallback());
+        boolean wasEnqueued = enqueueToast(testPackage, new TestableToastCallback());
         verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
                 anyInt());
         assertEquals(0, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isFalse();
     }
 
     @Test
@@ -8415,8 +8576,9 @@
         setAppInForegroundForToasts(mUid, false);
 
         // enqueue toast -> no toasts enqueued
-        enqueueToast(testPackage, new TestableToastCallback());
+        boolean wasEnqueued = enqueueToast(testPackage, new TestableToastCallback());
         assertEquals(0, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isFalse();
     }
 
     @Test
@@ -8437,8 +8599,9 @@
         setAppInForegroundForToasts(mUid, false);
 
         // enqueue toast -> system toast can still be enqueued
-        enqueueToast(testPackage, new TestableToastCallback());
+        boolean wasEnqueued = enqueueToast(testPackage, new TestableToastCallback());
         assertEquals(1, mService.mToastQueue.size());
+        assertThat(wasEnqueued).isTrue();
     }
 
     @Test
@@ -8458,7 +8621,12 @@
 
         // Trying to quickly enqueue more toast than allowed.
         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS + 1; i++) {
-            enqueueTextToast(testPackage, "Text");
+            boolean wasEnqueued = enqueueTextToast(testPackage, "Text");
+            if (i < NotificationManagerService.MAX_PACKAGE_TOASTS) {
+                assertThat(wasEnqueued).isTrue();
+            } else {
+                assertThat(wasEnqueued).isFalse();
+            }
         }
         // Only allowed number enqueued, rest ignored.
         assertEquals(NotificationManagerService.MAX_PACKAGE_TOASTS, mService.mToastQueue.size());
@@ -8570,8 +8738,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testOnNotificationSmartReplySent() {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         final int replyIndex = 2;
         final String reply = "Hello";
         final boolean modifiedBeforeSending = true;
@@ -8596,8 +8764,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testStats_SmartReplyAlreadyLifetimeExtendedPostsUpdate() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         final int replyIndex = 2;
         final String reply = "Hello";
         final boolean modifiedBeforeSending = true;
@@ -8630,8 +8798,7 @@
     public void testOnNotificationActionClick() {
         final int actionIndex = 2;
         final Notification.Action action =
-                new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
-                        mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
+                new Notification.Action.Builder(null, "text", mActivityIntent).build();
         final boolean generatedByAssistant = false;
 
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
@@ -8652,9 +8819,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testActionClickLifetimeExtendedCancel() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
-
         final Notification.Action action =
                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
@@ -8693,9 +8859,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testActionClickLifetimeExtendedCancel_PreventByNoDismiss() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
-
         final Notification.Action action =
                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
@@ -8736,9 +8901,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testUpdateOnActionClickDropsLifetimeExtendedCancel() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
-
         final Notification.Action action =
                 new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
                         mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
@@ -8780,8 +8944,7 @@
     public void testOnAssistantNotificationActionClick() {
         final int actionIndex = 1;
         final Notification.Action action =
-                new Notification.Action.Builder(null, "text", PendingIntent.getActivity(
-                        mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build();
+                new Notification.Action.Builder(null, "text", mActivityIntent).build();
         final boolean generatedByAssistant = true;
 
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
@@ -9296,7 +9459,7 @@
                 BUBBLE_PREFERENCE_ALL /* app */,
                 true /* channel */);
 
-        Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false);
+        Notification.Builder nb = getMessageStyleNotifBuilder(true, null, false, true);
         nb.setShortcutId(null);
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
                 null, mUid, 0,
@@ -9340,7 +9503,7 @@
 
         // Messaging notif WITHOUT bubble metadata
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
 
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
                 "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0,
@@ -10598,7 +10761,7 @@
         Notification.BubbleMetadata metadata =
                 new Notification.BubbleMetadata.Builder(VALID_CONVO_SHORTCUT_ID).build();
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
         nb.setBubbleMetadata(metadata);
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
@@ -10658,7 +10821,7 @@
         Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
                 shortcutId).build();
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(shortcutId);
         nb.setBubbleMetadata(metadata);
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
@@ -11051,7 +11214,7 @@
 
         //Create notification record
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
         nb.setChannelId(originalChannel.getId());
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
@@ -11087,7 +11250,7 @@
 
         //Create notification record
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
         nb.setChannelId(originalChannel.getId());
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
@@ -11131,7 +11294,7 @@
 
         //Create notification record
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(VALID_CONVO_SHORTCUT_ID);
         nb.setChannelId(originalChannel.getId());
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
@@ -11176,7 +11339,7 @@
 
         //Create notification record without a shortcutId
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(null);
         nb.setChannelId(originalChannel.getId());
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
@@ -11311,7 +11474,7 @@
     @Test
     public void testRecordMessages_invalidMsg() throws RemoteException {
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(null);
         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
                 "testRecordMessages_invalidMsg", mUid, 0, nb.build(),
@@ -11352,7 +11515,7 @@
     @Test
     public void testRecordMessages_validMsg() throws RemoteException {
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(null);
         StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, 1,
                 "testRecordMessages_validMsg", mUid, 0, nb.build(),
@@ -11388,7 +11551,7 @@
         waitForIdle();
 
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
-                null /* groupKey */, false /* isSummary */);
+                null /* groupKey */, false /* isSummary */, true);
         nb.setShortcutId(null);
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 1,
                 "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
@@ -11608,10 +11771,9 @@
 
     @Test
     public void testImmutableBubbleIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(pi1))
-                .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
+        when(mAmi.getPendingIntentFlags(any())).thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
         NotificationRecord r = generateMessageBubbleNotifRecord(true,
-                mTestNotificationChannel, 7, "testImmutableBubbleIntent", null, false);
+                mTestNotificationChannel, 7, "testImmutableBubbleIntent", null, false, false);
         try {
             mBinderService.enqueueNotificationWithTag(mPkg, mPkg, r.getSbn().getTag(),
                     r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
@@ -11625,10 +11787,8 @@
 
     @Test
     public void testMutableBubbleIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(pi1))
-                .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
         NotificationRecord r = generateMessageBubbleNotifRecord(true,
-                mTestNotificationChannel, 7, "testMutableBubbleIntent", null, false);
+                mTestNotificationChannel, 7, "testMutableBubbleIntent", null, false, true);
 
         mBinderService.enqueueNotificationWithTag(mPkg, mPkg, r.getSbn().getTag(),
                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
@@ -11641,10 +11801,10 @@
 
     @Test
     public void testImmutableDirectReplyActionIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
+        when(mAmi.getPendingIntentFlags(any())).thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
         NotificationRecord r = generateMessageBubbleNotifRecord(false,
-                mTestNotificationChannel, 7, "testImmutableDirectReplyActionIntent", null, false);
+                mTestNotificationChannel, 7, "testImmutableDirectReplyActionIntent", null, false,
+                false);
         try {
             mBinderService.enqueueNotificationWithTag(mPkg, mPkg, r.getSbn().getTag(),
                     r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
@@ -11658,10 +11818,9 @@
 
     @Test
     public void testMutableDirectReplyActionIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
         NotificationRecord r = generateMessageBubbleNotifRecord(false,
-                mTestNotificationChannel, 7, "testMutableDirectReplyActionIntent", null, false);
+                mTestNotificationChannel, 7, "testMutableDirectReplyActionIntent", null, false,
+                true);
         mBinderService.enqueueNotificationWithTag(mPkg, mPkg, r.getSbn().getTag(),
                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
 
@@ -11673,18 +11832,15 @@
 
     @Test
     public void testImmutableDirectReplyContextualActionIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
+        when(mAmi.getPendingIntentFlags(any())).thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
 
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
-                PendingIntent.FLAG_IMMUTABLE);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
-                inputIntent).addRemoteInput(remoteInput)
+                mActivityIntentImmutable).addRemoteInput(remoteInput)
                 .build();
         extraAction.add(replyAction);
         Bundle signals = new Bundle();
@@ -11705,18 +11861,13 @@
 
     @Test
     public void testMutableDirectReplyContextualActionIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
-                new Intent().setPackage(mContext.getPackageName()),
-                PendingIntent.FLAG_MUTABLE);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
-                inputIntent).addRemoteInput(remoteInput)
+                mActivityIntent).addRemoteInput(remoteInput)
                 .build();
         extraAction.add(replyAction);
         Bundle signals = new Bundle();
@@ -11732,10 +11883,8 @@
 
     @Test
     public void testImmutableActionIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
+        when(mAmi.getPendingIntentFlags(any())).thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
-
         mBinderService.enqueueNotificationWithTag(mPkg, mPkg, r.getSbn().getTag(),
                 r.getSbn().getId(), r.getNotification(), r.getSbn().getUserId());
 
@@ -11747,12 +11896,11 @@
 
     @Test
     public void testImmutableContextualActionIntent() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
+        when(mAmi.getPendingIntentFlags(any())).thenReturn(FLAG_IMMUTABLE | FLAG_ONE_SHOT);
         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
-        extraAction.add(new Notification.Action(0, "hello", null));
+        extraAction.add(new Notification.Action(0, "hello", mActivityIntentImmutable));
         Bundle signals = new Bundle();
         signals.putParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, extraAction);
         Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals, "",
@@ -12104,8 +12252,6 @@
 
     @Test
     public void testCallNotificationsBypassBlock() throws Exception {
-        when(mAmi.getPendingIntentFlags(any(IIntentSender.class)))
-                .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT);
         when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
 
         Notification.Builder nb = new Notification.Builder(
@@ -12128,8 +12274,8 @@
                 .setName("caller")
                 .build();
         nb.setStyle(Notification.CallStyle.forOngoingCall(
-                person, mock(PendingIntent.class)));
-        nb.setFullScreenIntent(mock(PendingIntent.class), true);
+                person, mActivityIntent));
+        nb.setFullScreenIntent(mActivityIntent, true);
         sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
@@ -12197,8 +12343,8 @@
         mService.clearNotifications();
         reset(mUsageStats);
         Person person = new Person.Builder().setName("caller").build();
-        nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class)));
-        nb.setFullScreenIntent(mock(PendingIntent.class), true);
+        nb.setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent));
+        nb.setFullScreenIntent(mActivityIntent, true);
         sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0, nb.build(),
                 UserHandle.getUserHandleForUid(mUid), null, 0);
         r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
@@ -12525,7 +12671,6 @@
 
         // the notifyPostedLocked function is called twice.
         verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong());
-        //verify(mListeners, times(2)).notifyPostedLocked(any(), any());
     }
 
     @Test
@@ -12692,7 +12837,7 @@
                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
                 NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
         mService.maybeShowInitialReviewPermissionsNotification();
-        verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
+        verify(mMockNm, times(1)).notify(eq(TAG),
                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
                 any(Notification.class));
     }
@@ -12727,7 +12872,7 @@
                 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
                 NotificationManagerService.REVIEW_NOTIF_STATE_RESHOWN);
         mService.maybeShowInitialReviewPermissionsNotification();
-        verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
+        verify(mMockNm, times(1)).notify(eq(TAG),
                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
                 any(Notification.class));
     }
@@ -12743,7 +12888,7 @@
         mInternalService.sendReviewPermissionsNotification();
 
         // Notification should be sent
-        verify(mMockNm, times(1)).notify(eq(NotificationManagerService.TAG),
+        verify(mMockNm, times(1)).notify(eq(TAG),
                 eq(SystemMessageProto.SystemMessage.NOTE_REVIEW_NOTIFICATION_PERMISSIONS),
                 any(Notification.class));
 
@@ -12775,7 +12920,7 @@
                 .thenReturn(permissionState);
 
         Notification n = new Notification.Builder(mContext, "test")
-                .setFullScreenIntent(mock(PendingIntent.class), true)
+                .setFullScreenIntent(mActivityIntent, true)
                 .build();
 
         mService.fixNotification(n, mPkg, "tag", 9, mUserId, mUid, NOT_FOREGROUND_SERVICE, true);
@@ -12843,7 +12988,7 @@
         Person person = new Person.Builder().setName("caller").build();
         Notification n = new Notification.Builder(mContext, "test")
                 .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                        person, mActivityIntent))
                 .build();
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -12864,7 +13009,7 @@
         Notification n = new Notification.Builder(mContext, "test")
                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
                 .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                        person, mActivityIntent))
                 .build();
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -13023,8 +13168,7 @@
         Notification n = new Notification.Builder(mContext, "test")
                 // Without FLAG_FOREGROUND_SERVICE.
                 //.setFlag(FLAG_FOREGROUND_SERVICE, true)
-                .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                .setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent))
                 .build();
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -13040,8 +13184,7 @@
         Person person = new Person.Builder().setName("caller").build();
         Notification n = new Notification.Builder(mContext, "test")
                 .setFlag(FLAG_USER_INITIATED_JOB, true)
-                .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                .setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent))
                 .build();
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -13055,9 +13198,8 @@
     public void checkCallStyleNotification_allowedForFsiAllowed() throws Exception {
         Person person = new Person.Builder().setName("caller").build();
         Notification n = new Notification.Builder(mContext, "test")
-                .setFullScreenIntent(mock(PendingIntent.class), true)
-                .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                .setFullScreenIntent(mActivityIntent, true)
+                .setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent))
                 .build();
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -13072,8 +13214,7 @@
         Person person = new Person.Builder().setName("caller").build();
         Notification n = new Notification.Builder(mContext, "test")
                 .setFlag(Notification.FLAG_FSI_REQUESTED_BUT_DENIED, true)
-                .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                .setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent))
                 .build();
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, "tag", mUid, 0,
                 n, UserHandle.getUserHandleForUid(mUid), null, 0);
@@ -13153,6 +13294,33 @@
     }
 
     @Test
+    public void fixSystemNotification_defaultAdservices_withOnGoingFlag_nondismissible()
+            throws Exception {
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = ADSERVICES_APK_PKG;
+        ai.uid = mUid;
+        ai.flags |= ApplicationInfo.FLAG_SYSTEM;
+
+        when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(ai);
+        when(mAppOpsManager.checkOpNoThrow(
+                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
+                ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED);
+        // Given: a notification from an app on the system partition has the flag
+        // FLAG_ONGOING_EVENT set
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, ADSERVICES_APK_PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE,
+                 true);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be set
+        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
+    }
+
+    @Test
     public void fixCallNotification_withOnGoingFlag_shouldNotBeNonDismissible()
             throws Exception {
         // Given: a call notification has the flag FLAG_ONGOING_EVENT set
@@ -13161,8 +13329,7 @@
                 .build();
         Notification n = new Notification.Builder(mContext, "test")
                 .setOngoing(true)
-                .setStyle(Notification.CallStyle.forOngoingCall(
-                        person, mock(PendingIntent.class)))
+                .setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent))
                 .build();
 
         // When: fix the notification with NotificationManagerService
@@ -13994,6 +14161,314 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
+    public void enqueueNotification_acceptsCorrectToken() throws RemoteException {
+        Notification sent = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentIntent(createPendingIntent("content"))
+                .build();
+        Notification received = parcelAndUnparcel(sent, Notification.CREATOR);
+        assertThat(received.getAllowlistToken()).isEqualTo(
+                NotificationManagerService.ALLOWLIST_TOKEN);
+
+        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "tag", 1,
+                parcelAndUnparcel(received, Notification.CREATOR), mUserId);
+        waitForIdle();
+
+        assertThat(mService.mNotificationList).hasSize(1);
+        assertThat(mService.mNotificationList.get(0).getNotification().getAllowlistToken())
+                .isEqualTo(NotificationManagerService.ALLOWLIST_TOKEN);
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
+    public void enqueueNotification_acceptsNullToken_andPopulatesIt() throws RemoteException {
+        Notification receivedWithoutParceling = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentIntent(createPendingIntent("content"))
+                .build();
+        assertThat(receivedWithoutParceling.getAllowlistToken()).isNull();
+
+        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "tag", 1,
+                parcelAndUnparcel(receivedWithoutParceling, Notification.CREATOR), mUserId);
+        waitForIdle();
+
+        assertThat(mService.mNotificationList).hasSize(1);
+        assertThat(mService.mNotificationList.get(0).getNotification().getAllowlistToken())
+                .isEqualTo(NotificationManagerService.ALLOWLIST_TOKEN);
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
+    public void enqueueNotification_rejectsOtherToken() throws RemoteException {
+        Notification sent = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentIntent(createPendingIntent("content"))
+                .build();
+        sent.overrideAllowlistToken(new Binder());
+        Notification received = parcelAndUnparcel(sent, Notification.CREATOR);
+        assertThat(received.getAllowlistToken()).isEqualTo(sent.getAllowlistToken());
+
+        assertThrows(SecurityException.class, () ->
+                mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "tag", 1,
+                        parcelAndUnparcel(received, Notification.CREATOR), mUserId));
+        waitForIdle();
+
+        assertThat(mService.mNotificationList).isEmpty();
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
+    public void enqueueNotification_customParcelingWithFakeInnerToken_hasCorrectTokenInIntents()
+            throws RemoteException {
+        Notification sentFromApp = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentIntent(createPendingIntent("content"))
+                .setPublicVersion(new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                        .setContentIntent(createPendingIntent("public"))
+                        .build())
+                .build();
+        sentFromApp.publicVersion.overrideAllowlistToken(new Binder());
+
+        // Instead of using the normal parceling, assume the caller parcels it by hand, including a
+        // null token in the outer notification (as would be expected, and as is verified by
+        // enqueue) but trying to sneak in a different one in the inner notification, hoping it gets
+        // propagated to the PendingIntents.
+        Parcel parcelSentFromApp = Parcel.obtain();
+        writeNotificationToParcelCustom(parcelSentFromApp, sentFromApp, new ArraySet<>(
+                Lists.newArrayList(sentFromApp.contentIntent,
+                        sentFromApp.publicVersion.contentIntent)));
+
+        // Use the unparceling as received in enqueueNotificationWithTag()
+        parcelSentFromApp.setDataPosition(0);
+        Notification receivedByNms = new Notification(parcelSentFromApp);
+
+        // Verify that all the pendingIntents have the correct token.
+        assertThat(receivedByNms.contentIntent.getWhitelistToken()).isEqualTo(
+                NotificationManagerService.ALLOWLIST_TOKEN);
+        assertThat(receivedByNms.publicVersion.contentIntent.getWhitelistToken()).isEqualTo(
+                NotificationManagerService.ALLOWLIST_TOKEN);
+    }
+
+    /**
+     * Replicates the behavior of {@link Notification#writeToParcel} but excluding the
+     * "always use the same allowlist token as the root notification" parts.
+     */
+    private static void writeNotificationToParcelCustom(Parcel parcel, Notification notif,
+            ArraySet<PendingIntent> allPendingIntents) {
+        int flags = 0;
+        parcel.writeInt(1); // version?
+
+        parcel.writeStrongBinder(notif.getAllowlistToken());
+        parcel.writeLong(notif.when);
+        parcel.writeLong(notif.creationTime);
+        if (notif.getSmallIcon() != null) {
+            parcel.writeInt(1);
+            notif.getSmallIcon().writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+        parcel.writeInt(notif.number);
+        if (notif.contentIntent != null) {
+            parcel.writeInt(1);
+            notif.contentIntent.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+        if (notif.deleteIntent != null) {
+            parcel.writeInt(1);
+            notif.deleteIntent.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+        if (notif.tickerText != null) {
+            parcel.writeInt(1);
+            TextUtils.writeToParcel(notif.tickerText, parcel, flags);
+        } else {
+            parcel.writeInt(0);
+        }
+        if (notif.tickerView != null) {
+            parcel.writeInt(1);
+            notif.tickerView.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+        if (notif.contentView != null) {
+            parcel.writeInt(1);
+            notif.contentView.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+        if (notif.getLargeIcon() != null) {
+            parcel.writeInt(1);
+            notif.getLargeIcon().writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(notif.defaults);
+        parcel.writeInt(notif.flags);
+
+        if (notif.sound != null) {
+            parcel.writeInt(1);
+            notif.sound.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+        parcel.writeInt(notif.audioStreamType);
+
+        if (notif.audioAttributes != null) {
+            parcel.writeInt(1);
+            notif.audioAttributes.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeLongArray(notif.vibrate);
+        parcel.writeInt(notif.ledARGB);
+        parcel.writeInt(notif.ledOnMS);
+        parcel.writeInt(notif.ledOffMS);
+        parcel.writeInt(notif.iconLevel);
+
+        if (notif.fullScreenIntent != null) {
+            parcel.writeInt(1);
+            notif.fullScreenIntent.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(notif.priority);
+
+        parcel.writeString8(notif.category);
+
+        parcel.writeString8(notif.getGroup());
+
+        parcel.writeString8(notif.getSortKey());
+
+        parcel.writeBundle(notif.extras); // null ok
+
+        parcel.writeTypedArray(notif.actions, 0); // null ok
+
+        if (notif.bigContentView != null) {
+            parcel.writeInt(1);
+            notif.bigContentView.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        if (notif.headsUpContentView != null) {
+            parcel.writeInt(1);
+            notif.headsUpContentView.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(notif.visibility);
+
+        if (notif.publicVersion != null) {
+            parcel.writeInt(1);
+            writeNotificationToParcelCustom(parcel, notif.publicVersion, new ArraySet<>());
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(notif.color);
+
+        if (notif.getChannelId() != null) {
+            parcel.writeInt(1);
+            parcel.writeString8(notif.getChannelId());
+        } else {
+            parcel.writeInt(0);
+        }
+        parcel.writeLong(notif.getTimeoutAfter());
+
+        if (notif.getShortcutId() != null) {
+            parcel.writeInt(1);
+            parcel.writeString8(notif.getShortcutId());
+        } else {
+            parcel.writeInt(0);
+        }
+
+        if (notif.getLocusId() != null) {
+            parcel.writeInt(1);
+            notif.getLocusId().writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(notif.getBadgeIconType());
+
+        if (notif.getSettingsText() != null) {
+            parcel.writeInt(1);
+            TextUtils.writeToParcel(notif.getSettingsText(), parcel, flags);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(notif.getGroupAlertBehavior());
+
+        if (notif.getBubbleMetadata() != null) {
+            parcel.writeInt(1);
+            notif.getBubbleMetadata().writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeBoolean(notif.getAllowSystemGeneratedContextualActions());
+
+        parcel.writeInt(Notification.FOREGROUND_SERVICE_DEFAULT); // no getter for mFgsDeferBehavior
+
+        // mUsesStandardHeader is not written because it should be recomputed in listeners
+
+        parcel.writeArraySet(allPendingIntents);
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    @EnableFlags(android.app.Flags.FLAG_SECURE_ALLOWLIST_TOKEN)
+    public void getActiveNotifications_doesNotLeakAllowlistToken() throws RemoteException {
+        Notification sentFromApp = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentIntent(createPendingIntent("content"))
+                .setPublicVersion(new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                        .setContentIntent(createPendingIntent("public"))
+                        .build())
+                .extend(new Notification.WearableExtender()
+                        .addPage(new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                                .setContentIntent(createPendingIntent("wearPage"))
+                                .build()))
+                .build();
+        // Binder transition: app -> NMS
+        Notification receivedByNms = parcelAndUnparcel(sentFromApp, Notification.CREATOR);
+        assertThat(receivedByNms.getAllowlistToken()).isEqualTo(
+                NotificationManagerService.ALLOWLIST_TOKEN);
+        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "tag", 1,
+                parcelAndUnparcel(receivedByNms, Notification.CREATOR), mUserId);
+        waitForIdle();
+        assertThat(mService.mNotificationList).hasSize(1);
+        Notification posted = mService.mNotificationList.get(0).getNotification();
+        assertThat(posted.getAllowlistToken()).isEqualTo(
+                NotificationManagerService.ALLOWLIST_TOKEN);
+        assertThat(posted.contentIntent.getWhitelistToken()).isEqualTo(
+                NotificationManagerService.ALLOWLIST_TOKEN);
+
+        ParceledListSlice<StatusBarNotification> listSentFromNms =
+                mBinderService.getAppActiveNotifications(mPkg, mUserId);
+        // Binder transition: NMS -> app. App doesn't have the allowlist token so clear it
+        // (having a different one would produce the same effect; the relevant thing is to not let
+        // out ALLOWLIST_TOKEN).
+        // Note: for other tests, this is restored by constructing TestableNMS in setup().
+        Notification.processAllowlistToken = null;
+        ParceledListSlice<StatusBarNotification> listReceivedByApp = parcelAndUnparcel(
+                listSentFromNms, ParceledListSlice.CREATOR);
+        Notification gottenBackByApp = listReceivedByApp.getList().get(0).getNotification();
+
+        assertThat(gottenBackByApp.getAllowlistToken()).isNull();
+        assertThat(gottenBackByApp.contentIntent.getWhitelistToken()).isNull();
+        assertThat(gottenBackByApp.publicVersion.getAllowlistToken()).isNull();
+        assertThat(gottenBackByApp.publicVersion.contentIntent.getWhitelistToken()).isNull();
+        assertThat(new Notification.WearableExtender(gottenBackByApp).getPages()
+                .get(0).getAllowlistToken()).isNull();
+        assertThat(new Notification.WearableExtender(gottenBackByApp).getPages()
+                .get(0).contentIntent.getWhitelistToken()).isNull();
+    }
+
+    @Test
     public void enqueueNotification_allowlistsPendingIntents() throws RemoteException {
         PendingIntent contentIntent = createPendingIntent("content");
         PendingIntent actionIntent1 = createPendingIntent("action1");
@@ -14013,6 +14488,9 @@
                 eq(REASON_NOTIFICATION_SERVICE), any());
         verify(mAmi, times(3)).setPendingIntentAllowBgActivityStarts(any(),
                 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
+        contentIntent.cancel();
+        actionIntent2.cancel();
+        actionIntent1.cancel();
     }
 
     @Test
@@ -14041,6 +14519,10 @@
                 eq(REASON_NOTIFICATION_SERVICE), any());
         verify(mAmi, times(4)).setPendingIntentAllowBgActivityStarts(any(),
                 any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
+        contentIntent.cancel();
+        publicContentIntent.cancel();
+        actionIntent.cancel();
+        publicActionIntent.cancel();
     }
 
     @Test
@@ -14566,8 +15048,8 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
     public void testFixNotification_clearsLifetimeExtendedFlag() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);
         Notification n = new Notification.Builder(mContext, "test")
                 .setFlag(FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, true)
                 .build();
@@ -14996,7 +15478,7 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ALL_NOTIFS_NEED_TTL)
+    @EnableFlags(FLAG_ALL_NOTIFS_NEED_TTL)
     public void testFixNotification_missingTtl() throws Exception {
         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -15008,7 +15490,7 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ALL_NOTIFS_NEED_TTL)
+    @EnableFlags(FLAG_ALL_NOTIFS_NEED_TTL)
     public void testFixNotification_doesNotOverwriteTtl() throws Exception {
         Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -15026,8 +15508,7 @@
         Notification.Builder nb = new Notification.Builder(mContext,
                 mTestNotificationChannel.getId())
                 .setFlag(FLAG_USER_INITIATED_JOB, true)
-                .setStyle(Notification.CallStyle.forOngoingCall(
-                    person, mock(PendingIntent.class)))
+                .setStyle(Notification.CallStyle.forOngoingCall(person, mActivityIntent))
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
         StatusBarNotification sbn = new StatusBarNotification(packageName, packageName, 1,
                 testName, mUid, 0, nb.build(), userHandle, null, 0);
@@ -15089,25 +15570,27 @@
                 .thenReturn(false);
     }
 
-    private void enqueueToast(String testPackage, ITransientNotification callback)
+    private boolean enqueueToast(String testPackage, ITransientNotification callback)
             throws RemoteException {
-        enqueueToast((INotificationManager) mService.mService, testPackage, new Binder(), callback);
+        return enqueueToast((INotificationManager) mService.mService, testPackage, new Binder(),
+                callback);
     }
 
-    private void enqueueToast(INotificationManager service, String testPackage,
+    private boolean enqueueToast(INotificationManager service, String testPackage,
             IBinder token, ITransientNotification callback) throws RemoteException {
-        service.enqueueToast(testPackage, token, callback, TOAST_DURATION, /* isUiContext= */ true,
-                DEFAULT_DISPLAY);
+        return service.enqueueToast(testPackage, token, callback, TOAST_DURATION, /* isUiContext= */
+                true, DEFAULT_DISPLAY);
     }
 
-    private void enqueueTextToast(String testPackage, CharSequence text) throws RemoteException {
-        enqueueTextToast(testPackage, text, /* isUiContext= */ true, DEFAULT_DISPLAY);
+    private boolean enqueueTextToast(String testPackage, CharSequence text) throws RemoteException {
+        return enqueueTextToast(testPackage, text, /* isUiContext= */ true, DEFAULT_DISPLAY);
     }
 
-    private void enqueueTextToast(String testPackage, CharSequence text, boolean isUiContext,
+    private boolean enqueueTextToast(String testPackage, CharSequence text, boolean isUiContext,
             int displayId) throws RemoteException {
-        ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), text,
-                TOAST_DURATION, isUiContext, displayId, /* textCallback= */ null);
+        return ((INotificationManager) mService.mService).enqueueTextToast(testPackage,
+                new Binder(), text, TOAST_DURATION, isUiContext, displayId,
+                /* textCallback= */ null);
     }
 
     private void mockIsVisibleBackgroundUsersSupported(boolean supported) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 130a8ca..f572e7a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -20,6 +20,7 @@
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.media.AudioAttributes.USAGE_ALARM;
 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
 import static android.service.notification.Adjustment.KEY_NOT_CONVERSATION;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
@@ -68,6 +69,7 @@
 import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
@@ -1565,4 +1567,31 @@
         assertTrue(record.getPhoneNumbers().contains("16175552121"));
         assertTrue(record.getPhoneNumbers().contains("16175553434"));
     }
+
+    @Test
+    @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_ALARM)
+    public void updateChannel_nullAudioAttributes() {
+        StatusBarNotification sbn = getStyledNotification(true, true, true,
+                new Notification.DecoratedCustomViewStyle());
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        record.updateNotificationChannel(new NotificationChannel("new", "new", 3));
+
+        assertThat(record.getAudioAttributes()).isNotNull();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_RESTRICT_AUDIO_ATTRIBUTES_ALARM)
+    public void updateChannel_nonNullAudioAttributes() {
+        StatusBarNotification sbn = getStyledNotification(true, true, true,
+                new Notification.DecoratedCustomViewStyle());
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        NotificationChannel update = new NotificationChannel("new", "new", 3);
+        update.setSound(Uri.EMPTY,
+                new AudioAttributes.Builder().setUsage(USAGE_ALARM).build());
+        record.updateNotificationChannel(update);
+
+        assertThat(record.getAudioAttributes().getUsage()).isEqualTo(USAGE_ALARM);
+    }
 }
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 aeeca2ae..9a58594 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -46,10 +46,13 @@
 import static android.os.UserHandle.USER_ALL;
 import static android.os.UserHandle.USER_SYSTEM;
 
+import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.PROPAGATE_CHANNEL_UPDATES_TO_CONVERSATIONS;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
+import static com.android.server.notification.Flags.FLAG_ALL_NOTIFS_NEED_TTL;
+import static com.android.server.notification.Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA;
 import static com.android.server.notification.NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER;
 import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE;
 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
@@ -110,6 +113,9 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.permission.PermissionManager;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
@@ -140,6 +146,9 @@
 import com.android.server.UiServiceTestCase;
 import com.android.server.notification.PermissionHelper.PackagePermission;
 
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.protobuf.InvalidProtocolBufferException;
@@ -148,6 +157,7 @@
 import org.json.JSONObject;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -160,6 +170,8 @@
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.time.Clock;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -171,7 +183,7 @@
 import java.util.concurrent.ThreadLocalRandom;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(ParameterizedAndroidJunit4.class)
 public class PreferencesHelperTest extends UiServiceTestCase {
     private static final int UID_HEADLESS = 1000000;
     private static final UserHandle USER = UserHandle.of(0);
@@ -212,6 +224,22 @@
     private AudioAttributes mAudioAttributes;
     private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
+
+    @Mock
+    Clock mClock;
+
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getParams() {
+        return FlagsParameterization.allCombinationsOf(
+                FLAG_PERSIST_INCOMPLETE_RESTORE_DATA);
+    }
+
+    public PreferencesHelperTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -326,13 +354,14 @@
             currentProfileIds.add(UserHandle.getUserId(UID_HEADLESS));
         }
         when(mUserProfiles.getCurrentProfileIds()).thenReturn(currentProfileIds);
+        when(mClock.millis()).thenReturn(System.currentTimeMillis());
 
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                false);
+                false, mClock);
         mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                false);
+                false, mClock);
         resetZenModeHelper();
 
         mAudioAttributes = new AudioAttributes.Builder()
@@ -680,7 +709,7 @@
     public void testReadXml_oldXml_migrates() throws Exception {
         mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                /* showReviewPermissionsNotification= */ true);
+                /* showReviewPermissionsNotification= */ true, mClock);
 
         String xml = "<ranking version=\"2\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1
@@ -816,7 +845,7 @@
     public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception {
         mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                /* showReviewPermissionsNotification= */ true);
+                /* showReviewPermissionsNotification= */ true, mClock);
 
         String xml = "<ranking version=\"3\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -875,7 +904,7 @@
     public void testReadXml_newXml_permissionNotificationOff() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                /* showReviewPermissionsNotification= */ false);
+                /* showReviewPermissionsNotification= */ false, mClock);
 
         String xml = "<ranking version=\"3\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -934,7 +963,7 @@
     public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                /* showReviewPermissionsNotification= */ true);
+                /* showReviewPermissionsNotification= */ true, mClock);
 
         String xml = "<ranking version=\"4\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -1010,7 +1039,8 @@
         when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(1234);
         final ApplicationInfo app = new ApplicationInfo();
         app.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
-        when(mPm.getApplicationInfoAsUser(eq("something"), anyInt(), anyInt())).thenReturn(app);
+        when(mPm.getApplicationInfoAsUser(
+                eq("something"), anyInt(), eq(USER_SYSTEM))).thenReturn(app);
 
         mXmlHelper.onPackagesChanged(false, 0, new String[] {"something"}, new int[] {1234});
 
@@ -1452,6 +1482,149 @@
         assertTrue(actualChannel.isSoundRestored());
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
+    public void testRestoreXml_delayedRestore() throws Exception {
+        // simulate package not installed
+        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
+        when(mPm.getApplicationInfoAsUser(eq(PKG_R), anyInt(), anyInt())).thenThrow(
+                new PackageManager.NameNotFoundException());
+        when(mClock.millis()).thenReturn(System.currentTimeMillis());
+
+        String id = "id";
+        String xml = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_R + "\" show_badge=\"true\">\n"
+                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
+                + "show_badge=\"true\" />\n"
+                + "</package>\n"
+                + "</ranking>\n";
+
+        loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);
+
+        // settings are not available with real uid because pkg is not installed
+        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UID_P, id, false)).isNull();
+        // but the settings are in memory with unknown_uid
+        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UNKNOWN_UID, id, false)).isNotNull();
+
+        // package is "installed"
+        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_P);
+
+        // Trigger 2nd restore pass
+        mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
+                new int[]{UID_P});
+
+        NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_P, id,
+                false);
+        assertThat(channel.getImportance()).isEqualTo(2);
+        assertThat(channel.canShowBadge()).isTrue();
+        assertThat(channel.canBypassDnd()).isFalse();
+
+        // removed from 'pending install' set
+        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UNKNOWN_UID, id,false)).isNull();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
+    public void testRestoreXml_delayedRestore_afterReboot() throws Exception {
+        // load restore data
+        ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
+        appPermissions.put(new Pair<>(UID_R, PKG_R), new Pair<>(true, false));
+        when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
+                .thenReturn(appPermissions);
+
+        // simulate package not installed
+        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
+        when(mPm.getApplicationInfoAsUser(eq(PKG_R), anyInt(), anyInt())).thenThrow(
+                new PackageManager.NameNotFoundException());
+        when(mClock.millis()).thenReturn(System.currentTimeMillis());
+
+        String id = "id";
+        String xml = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_R + "\" show_badge=\"true\">\n"
+                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
+                + "show_badge=\"true\" />\n"
+                + "</package>\n"
+                + "</ranking>\n";
+
+        loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);
+
+        // simulate write to disk
+        TypedXmlSerializer serializer = Xml.newFastSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        mXmlHelper.writeXml(serializer, false, USER_SYSTEM);
+        serializer.endDocument();
+        serializer.flush();
+
+        // simulate load after reboot
+        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
+                false, mClock);
+        loadByteArrayXml(baos.toByteArray(), false, USER_SYSTEM);
+
+        // Trigger 2nd restore pass
+        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_P);
+        mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
+                new int[]{UID_P});
+
+        NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_P, id,
+                false);
+        assertThat(channel.getImportance()).isEqualTo(2);
+        assertThat(channel.canShowBadge()).isTrue();
+        assertThat(channel.canBypassDnd()).isFalse();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
+    public void testRestoreXml_delayedRestore_packageMissingAfterTwoDays() throws Exception {
+        // load restore data
+        ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
+        appPermissions.put(new Pair<>(UID_R, PKG_R), new Pair<>(true, false));
+        when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
+                .thenReturn(appPermissions);
+
+        // simulate package not installed
+        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
+        when(mPm.getApplicationInfoAsUser(eq(PKG_R), anyInt(), anyInt())).thenThrow(
+                new PackageManager.NameNotFoundException());
+
+        String id = "id";
+        String xml = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_R + "\" show_badge=\"true\">\n"
+                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
+                + "show_badge=\"true\" />\n"
+                + "</package>\n"
+                + "</ranking>\n";
+
+        loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);
+
+        // simulate write to disk
+        TypedXmlSerializer serializer = Xml.newFastSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        mXmlHelper.writeXml(serializer, false, USER_SYSTEM);
+        serializer.endDocument();
+        serializer.flush();
+
+        // advance time by 2 days
+        when(mClock.millis()).thenReturn(
+                Duration.ofDays(2).toMillis() + System.currentTimeMillis());
+
+        // simulate load after reboot
+        mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
+                false, mClock);
+        loadByteArrayXml(xml.getBytes(), false, USER_SYSTEM);
+
+        // Trigger 2nd restore pass
+        mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
+                new int[]{UID_P});
+
+        // verify the 2nd restore pass failed because the restore data had been removed
+        assertThat(mXmlHelper.getNotificationChannel(PKG_R, UNKNOWN_UID, id, false)).isNull();
+    }
 
     /**
      * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to
@@ -1520,10 +1693,10 @@
 
         mHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                false);
+                false, mClock);
         mXmlHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
-                false);
+                false, mClock);
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -3981,7 +4154,7 @@
         pm.applicationInfo = new ApplicationInfo();
         pm.applicationInfo.uid = UID_O;
         List<PackageInfo> packages = ImmutableList.of(pm);
-        when(mPm.getInstalledPackagesAsUser(any(), anyInt())).thenReturn(packages);
+        when(mPm.getInstalledPackagesAsUser(eq(0), anyInt())).thenReturn(packages);
         mHelper.updateFixedImportance(users);
 
         assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O));
@@ -4097,7 +4270,7 @@
         pm.applicationInfo = new ApplicationInfo();
         pm.applicationInfo.uid = UID_O;
         List<PackageInfo> packages = ImmutableList.of(pm);
-        when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
+        when(mPm.getInstalledPackagesAsUser(0, 0)).thenReturn(packages);
         mHelper.updateFixedImportance(users);
 
         assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
@@ -4120,7 +4293,7 @@
         pm.applicationInfo = new ApplicationInfo();
         pm.applicationInfo.uid = UID_O;
         List<PackageInfo> packages = ImmutableList.of(pm);
-        when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
+        when(mPm.getInstalledPackagesAsUser(0, 0)).thenReturn(packages);
         mHelper.updateFixedImportance(users);
 
         NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
@@ -4309,7 +4482,7 @@
         pm.applicationInfo = new ApplicationInfo();
         pm.applicationInfo.uid = UID_O;
         List<PackageInfo> packages = ImmutableList.of(pm);
-        when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
+        when(mPm.getInstalledPackagesAsUser(0, 0)).thenReturn(packages);
         mHelper.updateFixedImportance(users);
 
         ArraySet<String> toRemove = new ArraySet<>();
@@ -4341,7 +4514,7 @@
         pm.applicationInfo = new ApplicationInfo();
         pm.applicationInfo.uid = UID_O;
         List<PackageInfo> packages = ImmutableList.of(pm);
-        when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
+        when(mPm.getInstalledPackagesAsUser(0, 0)).thenReturn(packages);
         mHelper.updateFixedImportance(users);
 
         assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index ad420f6..527001d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -55,6 +55,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.compat.IPlatformCompat;
 import com.android.server.UiServiceTestCase;
 
 import org.junit.Before;
@@ -155,7 +156,8 @@
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new RankingHelper(getContext(), mHandler, mConfig, mMockZenModeHelper,
-                mUsageStats, new String[] {ImportanceExtractor.class.getName()});
+                mUsageStats, new String[] {ImportanceExtractor.class.getName()},
+                mock(IPlatformCompat.class));
 
         mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentTitle("A")
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TimeToLiveHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/TimeToLiveHelperTest.java
new file mode 100644
index 0000000..8b46c8c
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TimeToLiveHelperTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import static com.android.server.notification.TimeToLiveHelper.EXTRA_KEY;
+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.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.SuppressLint;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.server.UiServiceTestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.quality.Strictness;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
+public class TimeToLiveHelperTest extends UiServiceTestCase {
+
+    TimeToLiveHelper mHelper;
+    @Mock
+    NotificationManagerPrivate mNm;
+    @Mock
+    AlarmManager mAm;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext.addMockSystemService(AlarmManager.class, mAm);
+        mHelper = new TimeToLiveHelper(mNm, mContext);
+    }
+
+    @After
+    public void tearDown() {
+        mHelper.destroy();
+    }
+
+    private NotificationRecord getRecord(String tag, int timeoutAfter) {
+        NotificationChannel channel = new NotificationChannel("id", "name",
+                NotificationManager.IMPORTANCE_HIGH);
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setTimeoutAfter(timeoutAfter);
+
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 8, tag, mUid, 0,
+                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
+        return new NotificationRecord(mContext, sbn, channel);
+    }
+
+    @Test
+    public void testTimeout() {
+        mHelper.scheduleTimeoutLocked(getRecord("testTimeout", 1), 1);
+
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), any());
+        assertThat(mHelper.mKeys).hasSize(1);
+    }
+
+    @Test
+    public void testTimeoutExpires() {
+        NotificationRecord r = getRecord("testTimeoutExpires", 1);
+
+        mHelper.scheduleTimeoutLocked(r, 1);
+        ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), captor.capture());
+
+        mHelper.mNotificationTimeoutReceiver.onReceive(mContext, captor.getValue().getIntent());
+
+        assertThat(mHelper.mKeys).isEmpty();
+    }
+
+    @Test
+    public void testTimeoutExpires_twoEntries() {
+        NotificationRecord first = getRecord("testTimeoutFirst", 1);
+        NotificationRecord later = getRecord("testTimeoutSecond", 2);
+
+        mHelper.scheduleTimeoutLocked(first, 1);
+        mHelper.scheduleTimeoutLocked(later, 1);
+
+        ArgumentCaptor<PendingIntent> captorSet = ArgumentCaptor.forClass(PendingIntent.class);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), captorSet.capture());
+
+        ArgumentCaptor<PendingIntent> captorNewSet = ArgumentCaptor.forClass(PendingIntent.class);
+        mHelper.mNotificationTimeoutReceiver.onReceive(mContext, captorSet.getValue().getIntent());
+
+        assertThat(mHelper.mKeys).hasSize(1);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(3L), captorNewSet.capture());
+        assertThat(captorSet.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(first.getKey());
+    }
+
+    @Test
+    public void testTimeout_earlierEntryAddedSecond() {
+        NotificationRecord later = getRecord("testTimeoutSecond", 2);
+        mHelper.scheduleTimeoutLocked(later, 1);
+
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(3L), any());
+        assertThat(mHelper.mKeys).hasSize(1);
+
+        NotificationRecord first = getRecord("testTimeoutFirst", 1);
+        ArgumentCaptor<PendingIntent> captorSet = ArgumentCaptor.forClass(PendingIntent.class);
+        ArgumentCaptor<PendingIntent> captorCancel = ArgumentCaptor.forClass(PendingIntent.class);
+
+        mHelper.scheduleTimeoutLocked(first, 1);
+
+        assertThat(mHelper.mKeys).hasSize(2);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), captorSet.capture());
+        assertThat(captorSet.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(first.getKey());
+        assertThat(mHelper.mKeys.first().second).isEqualTo(first.getKey());
+
+        verify(mAm).cancel(captorCancel.capture());
+        assertThat(captorCancel.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(later.getKey());
+    }
+
+    @Test
+    public void testTimeout_earlierEntryAddedFirst() {
+        NotificationRecord first = getRecord("testTimeoutFirst", 1);
+        NotificationRecord later = getRecord("testTimeoutSecond", 2);
+
+        mHelper.scheduleTimeoutLocked(first, 1);
+        mHelper.scheduleTimeoutLocked(later, 1);
+
+        assertThat(mHelper.mKeys).hasSize(2);
+        assertThat(mHelper.mKeys.first().second).isEqualTo(first.getKey());
+        verify(mAm, never()).cancel((PendingIntent) any());
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), any());
+    }
+
+    @Test
+    public void testTimeout_updateEarliestEntry() {
+        NotificationRecord first = getRecord("testTimeoutFirst", 1);
+
+        mHelper.scheduleTimeoutLocked(first, 1);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), any());
+
+        NotificationRecord firstUpdated = getRecord("testTimeoutFirst", 3);
+        ArgumentCaptor<PendingIntent> captorSet = ArgumentCaptor.forClass(PendingIntent.class);
+        ArgumentCaptor<PendingIntent> captorCancel = ArgumentCaptor.forClass(PendingIntent.class);
+
+        mHelper.scheduleTimeoutLocked(firstUpdated, 1);
+
+        assertThat(mHelper.mKeys).hasSize(1);
+
+        // cancel original alarm
+        verify(mAm).cancel(captorCancel.capture());
+        assertThat(captorCancel.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(first.getKey());
+
+        // schedule later alarm
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(4L), captorSet.capture());
+        assertThat(captorSet.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(first.getKey());
+    }
+
+    @Test
+    public void testTimeout_twoEntries_updateEarliestEntry() {
+        NotificationRecord first = getRecord("testTimeoutFirst", 1);
+        NotificationRecord later = getRecord("testTimeoutSecond", 2);
+
+        mHelper.scheduleTimeoutLocked(first, 1);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(2L), any());
+
+        mHelper.scheduleTimeoutLocked(later, 1);
+
+        NotificationRecord firstUpdated = getRecord("testTimeoutFirst", 3);
+        ArgumentCaptor<PendingIntent> captorSet = ArgumentCaptor.forClass(PendingIntent.class);
+        ArgumentCaptor<PendingIntent> captorCancel = ArgumentCaptor.forClass(PendingIntent.class);
+
+        mHelper.scheduleTimeoutLocked(firstUpdated, 1);
+
+        assertThat(mHelper.mKeys).hasSize(2);
+        assertThat(mHelper.mKeys.first().second).isEqualTo(later.getKey());
+
+        // "first" was canceled because it's now later
+        verify(mAm).cancel(captorCancel.capture());
+        assertThat(captorCancel.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(first.getKey());
+
+        // "later" is now the first entry, and needs the matching alarm
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq(3L), captorSet.capture());
+        assertThat(captorSet.getValue().getIntent().getStringExtra(EXTRA_KEY))
+                .isEqualTo(later.getKey());
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenEnumTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenEnumTest.java
index f724510..8add2f9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenEnumTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenEnumTest.java
@@ -21,8 +21,8 @@
 import android.app.AutomaticZenRule;
 import android.provider.Settings;
 import android.service.notification.ZenPolicy;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.os.dnd.ActiveRuleType;
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 3df52c7..9559a25 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -322,6 +322,27 @@
         mZenModeEventLogger.reset();
     }
 
+    private enum ChangeOrigin {
+        ORIGIN_UNKNOWN(ZenModeConfig.UPDATE_ORIGIN_UNKNOWN),
+        ORIGIN_INIT(ZenModeConfig.UPDATE_ORIGIN_INIT),
+        ORIGIN_INIT_USER(ZenModeConfig.UPDATE_ORIGIN_INIT_USER),
+        ORIGIN_USER(ZenModeConfig.UPDATE_ORIGIN_USER),
+        ORIGIN_APP(ZenModeConfig.UPDATE_ORIGIN_APP),
+        ORIGIN_SYSTEM_OR_SYSTEMUI(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI),
+        ORIGIN_RESTORE_BACKUP(ZenModeConfig.UPDATE_ORIGIN_RESTORE_BACKUP);
+
+        private final int mValue;
+
+        ChangeOrigin(@ZenModeConfig.ConfigChangeOrigin int value) {
+            mValue = value;
+        }
+
+        @ZenModeConfig.ConfigChangeOrigin
+        public int value() {
+            return mValue;
+        }
+    }
+
     private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException {
         String xml = "<zen version=\"10\">\n"
                 + "<allow alarms=\"true\" media=\"true\" system=\"false\" calls=\"true\" "
@@ -2898,6 +2919,72 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    @DisableFlags(Flags.FLAG_MODES_UI)
+    public void setManualZenMode_off_snoozesActiveRules(@TestParameter ChangeOrigin setZenOrigin) {
+        // Start with an active rule and an inactive rule.
+        mZenModeHelper.mConfig.automaticRules.clear();
+        AutomaticZenRule activeRule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+                .build();
+        String activeRuleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+                activeRule, UPDATE_ORIGIN_APP, "add it", CUSTOM_PKG_UID);
+        mZenModeHelper.setAutomaticZenRuleState(activeRuleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        AutomaticZenRule inactiveRule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+                .build();
+        String inactiveRuleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+                inactiveRule, UPDATE_ORIGIN_APP, "add it", CUSTOM_PKG_UID);
+
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        // User turns DND off.
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, setZenOrigin.value(),
+                "snoozing", "systemui", Process.SYSTEM_UID);
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
+        assertThat(mZenModeHelper.mConfig.automaticRules.get(activeRuleId).snoozing).isTrue();
+        assertThat(mZenModeHelper.mConfig.automaticRules.get(inactiveRuleId).snoozing).isFalse();
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+    public void setManualZenMode_off_doesNotSnoozeRulesIfFromUser(
+            @TestParameter ChangeOrigin setZenOrigin) {
+        // Start with an active rule and an inactive rule
+        mZenModeHelper.mConfig.automaticRules.clear();
+        AutomaticZenRule activeRule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+                .build();
+        String activeRuleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+                activeRule, UPDATE_ORIGIN_APP, "add it", CUSTOM_PKG_UID);
+        mZenModeHelper.setAutomaticZenRuleState(activeRuleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        AutomaticZenRule inactiveRule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+                .build();
+        String inactiveRuleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+                inactiveRule, UPDATE_ORIGIN_APP, "add it", CUSTOM_PKG_UID);
+
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        // User turns DND off.
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, setZenOrigin.value(),
+                "snoozing", "systemui", Process.SYSTEM_UID);
+        ZenModeConfig config = mZenModeHelper.mConfig;
+        if (setZenOrigin == ChangeOrigin.ORIGIN_USER) {
+            // Other rule was unaffected.
+            assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+            assertThat(config.automaticRules.get(activeRuleId).snoozing).isFalse();
+            assertThat(config.automaticRules.get(inactiveRuleId).snoozing).isFalse();
+        } else {
+            assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
+            assertThat(config.automaticRules.get(activeRuleId).snoozing).isTrue();
+            assertThat(config.automaticRules.get(inactiveRuleId).snoozing).isFalse();
+        }
+    }
+
+    @Test
     public void testSetManualZenMode_legacy() {
         setupZenConfig();
 
@@ -3655,6 +3742,7 @@
         // Create immersive rule
         AutomaticZenRule immersive = new AutomaticZenRule.Builder("Immersed", CONDITION_ID)
                 .setType(TYPE_IMMERSIVE)
+                .setZenPolicy(mZenModeHelper.mConfig.toZenPolicy()) // same as the manual rule
                 .build();
         String immersiveId = mZenModeHelper.addAutomaticZenRule(mPkg, immersive, UPDATE_ORIGIN_APP,
                 "reason", CUSTOM_PKG_UID);
@@ -4242,6 +4330,7 @@
     public void updateAutomaticZenRule_fromUser_updatesBitmaskAndValue() {
         // Adds a starting rule with empty zen policies and device effects
         AutomaticZenRule azrBase = new AutomaticZenRule.Builder(NAME, CONDITION_ID)
+                .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS)
                 .setZenPolicy(new ZenPolicy.Builder().build())
                 .setDeviceEffects(new ZenDeviceEffects.Builder().build())
                 .build();
@@ -4250,7 +4339,7 @@
                 azrBase, UPDATE_ORIGIN_APP, "reason", Process.SYSTEM_UID);
         AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
 
-        // Modifies the zen policy and device effects
+        // Modifies the filter, zen policy, and device effects
         ZenPolicy policy = new ZenPolicy.Builder(rule.getZenPolicy())
                 .allowPriorityChannels(false)
                 .build();
@@ -4867,6 +4956,56 @@
     }
 
     @Test
+    @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+    public void updateAutomaticZenRule_ruleChangedByUser_doesNotDeactivateRule() {
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", CONDITION_ID)
+                .setConfigurationActivity(new ComponentName(mPkg, "cls"))
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+                .build();
+        String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, rule, UPDATE_ORIGIN_APP, "reason",
+                CUSTOM_PKG_UID);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        AutomaticZenRule updateWithDiff = new AutomaticZenRule.Builder(rule)
+                .setTriggerDescription("Whenever")
+                .build();
+        mZenModeHelper.updateAutomaticZenRule(ruleId, updateWithDiff, UPDATE_ORIGIN_USER, "reason",
+                CUSTOM_PKG_UID);
+
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+        assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).condition).isEqualTo(
+                CONDITION_TRUE);
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+    public void updateAutomaticZenRule_ruleDisabledByUser_doesNotReactivateOnReenable() {
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", CONDITION_ID)
+                .setConfigurationActivity(new ComponentName(mPkg, "cls"))
+                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+                .build();
+        String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, rule, UPDATE_ORIGIN_APP, "reason",
+                CUSTOM_PKG_UID);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        mZenModeHelper.updateAutomaticZenRule(ruleId,
+                new AutomaticZenRule.Builder(rule).setEnabled(false).build(), UPDATE_ORIGIN_USER,
+                "disable", CUSTOM_PKG_UID);
+        mZenModeHelper.updateAutomaticZenRule(ruleId,
+                new AutomaticZenRule.Builder(rule).setEnabled(true).build(), UPDATE_ORIGIN_USER,
+                "enable", CUSTOM_PKG_UID);
+
+        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
+        assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).condition).isNull();
+    }
+
+    @Test
     @EnableFlags(Flags.FLAG_MODES_API)
     public void removeAutomaticZenRule_propagatesOriginToEffectsApplier() {
         mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
diff --git a/services/tests/vibrator/AndroidManifest.xml b/services/tests/vibrator/AndroidManifest.xml
index a14ea55..c0f514f 100644
--- a/services/tests/vibrator/AndroidManifest.xml
+++ b/services/tests/vibrator/AndroidManifest.xml
@@ -30,6 +30,8 @@
     <uses-permission android:name="android.permission.ACCESS_VIBRATOR_STATE" />
     <!-- Required to set always-on vibrations -->
     <uses-permission android:name="android.permission.VIBRATE_ALWAYS_ON" />
+    <!-- Required to play system-only haptic feedback constants -->
+    <uses-permission android:name="android.permission.VIBRATE_SYSTEM_CONSTANTS" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.mock" android:required="true" />
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
index e3d4596..633a3c9 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
@@ -27,6 +27,8 @@
 import static android.os.VibrationEffect.EFFECT_CLICK;
 import static android.os.VibrationEffect.EFFECT_TEXTURE_TICK;
 import static android.os.VibrationEffect.EFFECT_TICK;
+import static android.view.HapticFeedbackConstants.BIOMETRIC_CONFIRM;
+import static android.view.HapticFeedbackConstants.BIOMETRIC_REJECT;
 import static android.view.HapticFeedbackConstants.CLOCK_TICK;
 import static android.view.HapticFeedbackConstants.CONTEXT_CLICK;
 import static android.view.HapticFeedbackConstants.KEYBOARD_RELEASE;
@@ -80,6 +82,8 @@
             new int[] {SCROLL_ITEM_FOCUS, SCROLL_LIMIT, SCROLL_TICK};
     private static final int[] KEYBOARD_FEEDBACK_CONSTANTS =
             new int[] {KEYBOARD_TAP, KEYBOARD_RELEASE};
+    private static final int[] BIOMETRIC_FEEDBACK_CONSTANTS =
+            new int[] {BIOMETRIC_CONFIRM, BIOMETRIC_REJECT};
 
     private static final float KEYBOARD_VIBRATION_FIXED_AMPLITUDE = 0.62f;
 
@@ -283,6 +287,17 @@
     }
 
     @Test
+    public void testVibrationAttribute_biometricConstants_returnsCommunicationRequestUsage() {
+        HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
+
+        for (int effectId : BIOMETRIC_FEEDBACK_CONSTANTS) {
+            VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+                    effectId, /* bypassVibrationIntensitySetting= */ false, /* fromIme= */ false);
+            assertThat(attrs.getUsage()).isEqualTo(VibrationAttributes.USAGE_COMMUNICATION_REQUEST);
+        }
+    }
+
+    @Test
     public void testVibrationAttribute_forNotBypassingIntensitySettings() {
         HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
 
@@ -422,6 +437,15 @@
         }
     }
 
+    @Test
+    public void testIsRestricted_biometricConstants_returnsTrue() {
+        HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
+
+        for (int effectId : BIOMETRIC_FEEDBACK_CONSTANTS) {
+            assertThat(hapticProvider.isRestrictedHapticFeedback(effectId)).isTrue();
+        }
+    }
+
     private HapticFeedbackVibrationProvider createProviderWithDefaultCustomizations() {
         return createProvider(/* customizations= */ null);
     }
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
index 3f5217c..8ca8623 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
@@ -39,6 +39,7 @@
 import android.content.ComponentName;
 import android.content.pm.PackageManagerInternal;
 import android.frameworks.vibrator.ScaleParam;
+import android.frameworks.vibrator.VibrationParam;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -59,6 +60,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 
@@ -177,6 +180,24 @@
         verifyZeroInteractions(mMockVibrationScaler);
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testOnRequestVibrationParamsComplete_withNullVibrationParams_throwsException() {
+        mVibratorControlService.registerVibratorController(mFakeVibratorController);
+        int timeoutInMillis = 10;
+        CompletableFuture<Void> unusedFuture =
+                mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE,
+                        timeoutInMillis);
+        IBinder token = mVibratorControlService.getRequestVibrationParamsToken();
+
+        List<VibrationParam> vibrationParamList = Arrays.asList(
+                VibrationParamGenerator.generateVibrationParam(ScaleParam.TYPE_ALARM, 0.7f),
+                null,
+                VibrationParamGenerator.generateVibrationParam(ScaleParam.TYPE_NOTIFICATION, 0.4f));
+
+        mVibratorControlService.onRequestVibrationParamsComplete(token,
+                vibrationParamList.toArray(new VibrationParam[0]));
+    }
+
     @Test
     public void testSetVibrationParams_cachesAdaptiveHapticsScalesCorrectly() {
         mVibratorControlService.registerVibratorController(mFakeVibratorController);
@@ -214,6 +235,19 @@
         verifyZeroInteractions(mMockVibrationScaler);
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testSetVibrationParams_withNullVibrationParams_throwsException() {
+        mVibratorControlService.registerVibratorController(mFakeVibratorController);
+        List<VibrationParam> vibrationParamList = Arrays.asList(
+                VibrationParamGenerator.generateVibrationParam(ScaleParam.TYPE_ALARM, 0.7f),
+                null,
+                VibrationParamGenerator.generateVibrationParam(ScaleParam.TYPE_NOTIFICATION, 0.4f));
+
+        mVibratorControlService.setVibrationParams(
+                vibrationParamList.toArray(new VibrationParam[0]),
+                mFakeVibratorController);
+    }
+
     @Test
     public void testClearVibrationParams_clearsCachedAdaptiveHapticsScales() {
         mVibratorControlService.registerVibratorController(mFakeVibratorController);
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 185677f..d6c0fef 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -1410,6 +1410,70 @@
     }
 
     @Test
+    public void performHapticFeedback_restrictedConstantsWithoutPermission_doesNotVibrate()
+            throws Exception {
+        // Deny permission to vibrate with restricted constants
+        denyPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS);
+        // Public constant, no permission required
+        mHapticFeedbackVibrationMap.put(
+                HapticFeedbackConstants.CONFIRM,
+                VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
+        // Hidden system-only constant, permission required
+        mHapticFeedbackVibrationMap.put(
+                HapticFeedbackConstants.BIOMETRIC_CONFIRM,
+                VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK));
+        mockVibrators(1);
+        FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+        fakeVibrator.setSupportedEffects(
+                VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_HEAVY_CLICK);
+        VibratorManagerService service = createSystemReadyService();
+
+        performHapticFeedbackAndWaitUntilFinished(
+                service, HapticFeedbackConstants.CONFIRM, /* always= */ false);
+
+        performHapticFeedbackAndWaitUntilFinished(
+                service, HapticFeedbackConstants.BIOMETRIC_CONFIRM, /* always= */ false);
+
+        List<VibrationEffectSegment> playedSegments = fakeVibrator.getAllEffectSegments();
+        assertEquals(1, playedSegments.size());
+        PrebakedSegment segment = (PrebakedSegment) playedSegments.get(0);
+        assertEquals(VibrationEffect.EFFECT_CLICK, segment.getEffectId());
+    }
+
+    @Test
+    public void performHapticFeedback_restrictedConstantsWithPermission_playsVibration()
+            throws Exception {
+        // Grant permission to vibrate with restricted constants
+        grantPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS);
+        // Public constant, no permission required
+        mHapticFeedbackVibrationMap.put(
+                HapticFeedbackConstants.CONFIRM,
+                VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
+        // Hidden system-only constant, permission required
+        mHapticFeedbackVibrationMap.put(
+                HapticFeedbackConstants.BIOMETRIC_CONFIRM,
+                VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK));
+        mockVibrators(1);
+        FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+        fakeVibrator.setSupportedEffects(
+                VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_HEAVY_CLICK);
+        VibratorManagerService service = createSystemReadyService();
+
+        performHapticFeedbackAndWaitUntilFinished(
+                service, HapticFeedbackConstants.CONFIRM, /* always= */ false);
+
+        performHapticFeedbackAndWaitUntilFinished(
+                service, HapticFeedbackConstants.BIOMETRIC_CONFIRM, /* always= */ false);
+
+        List<VibrationEffectSegment> playedSegments = fakeVibrator.getAllEffectSegments();
+        assertEquals(2, playedSegments.size());
+        assertEquals(VibrationEffect.EFFECT_CLICK,
+                ((PrebakedSegment) playedSegments.get(0)).getEffectId());
+        assertEquals(VibrationEffect.EFFECT_HEAVY_CLICK,
+                ((PrebakedSegment) playedSegments.get(1)).getEffectId());
+    }
+
+    @Test
     public void performHapticFeedback_doesNotVibrateWhenVibratorInfoNotReady() throws Exception {
         denyPermission(android.Manifest.permission.VIBRATE);
         mHapticFeedbackVibrationMap.put(
diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java b/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java
index a606388..c17d11e 100644
--- a/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java
+++ b/services/tests/vibrator/utils/com/android/server/vibrator/VibrationParamGenerator.java
@@ -42,7 +42,10 @@
         return vibrationParamList.toArray(new VibrationParam[0]);
     }
 
-    private static VibrationParam generateVibrationParam(int type, float scale) {
+    /**
+     * Generates a {@link VibrationParam} with the specified type and scale.
+     */
+    public static VibrationParam generateVibrationParam(int type, float scale) {
         ScaleParam scaleParam = new ScaleParam();
         scaleParam.typesMask = type;
         scaleParam.scale = scale;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index d6c5173..777f618 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -51,6 +51,7 @@
     <uses-permission android:name="android.permission.MONITOR_INPUT"/>
     <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"/>
     <uses-permission android:name="android.permission.MANAGE_DEFAULT_APPLICATIONS"/>
+    <uses-permission android:name="android.permission.DUMP"/>
 
     <!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
     <application android:debuggable="true"
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 3c02eee..0ed02dd 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -21,6 +21,7 @@
 import static android.view.KeyEvent.KEYCODE_BRIGHTNESS_DOWN;
 import static android.view.KeyEvent.KEYCODE_C;
 import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
+import static android.view.KeyEvent.KEYCODE_DEL;
 import static android.view.KeyEvent.KEYCODE_E;
 import static android.view.KeyEvent.KEYCODE_ENTER;
 import static android.view.KeyEvent.KEYCODE_H;
@@ -42,16 +43,25 @@
 import android.content.Intent;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.util.SparseArray;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 @Presubmit
 @SmallTest
 public class ModifierShortcutTests extends ShortcutKeyTestBase {
+
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private static final SparseArray<String> INTENT_SHORTCUTS =  new SparseArray<>();
     private static final SparseArray<String> ROLE_SHORTCUTS =  new SparseArray<>();
     static {
@@ -228,4 +238,25 @@
         sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0);
         mPhoneWindowManager.assertTakeScreenshotNotCalled();
     }
+
+    /**
+     * META+CTRL+BACKSPACE for taking a bugreport when the flag is enabled.
+     */
+    @Test
+    @RequiresFlagsEnabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+    public void testTakeBugReport_flagEnabled() throws RemoteException {
+        sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
+        mPhoneWindowManager.assertTakeBugreport(true);
+    }
+
+    /**
+     * META+CTRL+BACKSPACE for taking a bugreport does nothing when the flag is disabledd.
+     */
+    @Test
+    @RequiresFlagsDisabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+    public void testTakeBugReport_flagDisabled() throws RemoteException {
+        sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
+        mPhoneWindowManager.assertTakeBugreport(false);
+    }
+
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
index 60716cb..fd69217 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
@@ -23,6 +23,9 @@
 import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL;
 
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.view.KeyEvent;
 
 import androidx.test.filters.MediumTest;
@@ -34,6 +37,7 @@
 import junitparams.Parameters;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -42,6 +46,10 @@
 @RunWith(JUnitParamsRunner.class)
 public class ShortcutLoggingTests extends ShortcutKeyTestBase {
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule =
+            DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private static final int VENDOR_ID = 0x123;
     private static final int PRODUCT_ID = 0x456;
     private static final int DEVICE_BUS = 0x789;
@@ -153,8 +161,6 @@
                         new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_RIGHT},
                         KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION, KeyEvent.KEYCODE_DPAD_RIGHT,
                         META_ON | CTRL_ON},
-                {"Shift + Menu -> Trigger Bug Report", new int[]{SHIFT_KEY, KeyEvent.KEYCODE_MENU},
-                        KeyboardLogEvent.TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_MENU, SHIFT_ON},
                 {"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L},
                         KeyboardLogEvent.LOCK_SCREEN, KeyEvent.KEYCODE_L, META_ON},
                 {"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
@@ -353,4 +359,13 @@
                 expectedKey, expectedModifierState, DEVICE_BUS,
                 "Failed while executing " + testName);
     }
+
+    @Test
+    @RequiresFlagsEnabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+    public void testBugreportShortcutPress() {
+        sendKeyCombination(new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL}, 0);
+        mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID,
+                KeyboardLogEvent.TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL, META_ON | CTRL_ON,
+                DEVICE_BUS, "Failed to log bugreport shortcut.");
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 52df010..dd9d05a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -85,10 +85,10 @@
 import android.os.test.TestLooper;
 import android.service.dreams.DreamManagerInternal;
 import android.telecom.TelecomManager;
-import android.util.FeatureFlagUtils;
 import android.view.Display;
 import android.view.InputDevice;
 import android.view.KeyEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.autofill.AutofillManagerInternal;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
@@ -156,6 +156,7 @@
     @Mock private AudioManagerInternal mAudioManagerInternal;
     @Mock private SearchManager mSearchManager;
     @Mock private RoleManager mRoleManager;
+    @Mock private AccessibilityManager mAccessibilityManager;
 
     @Mock private Display mDisplay;
     @Mock private DisplayRotation mDisplayRotation;
@@ -306,6 +307,9 @@
                 eq(SensorPrivacyManager.class));
         doReturn(mSearchManager).when(mContext).getSystemService(eq(SearchManager.class));
         doReturn(mRoleManager).when(mContext).getSystemService(eq(RoleManager.class));
+        doReturn(mAccessibilityManager).when(mContext).getSystemService(
+                eq(AccessibilityManager.class));
+        doReturn(false).when(mAccessibilityManager).isEnabled();
         doReturn(false).when(mPackageManager).hasSystemFeature(any());
         try {
             doThrow(new PackageManager.NameNotFoundException("test")).when(mPackageManager)
@@ -603,7 +607,7 @@
     }
 
     void overrideEnableBugReportTrigger(boolean enable) {
-        mPhoneWindowManager.mEnableShiftMenuBugReports = enable;
+        mPhoneWindowManager.mEnableBugReportKeyboardShortcut = enable;
     }
 
     void overrideStartActivity() {
@@ -743,23 +747,18 @@
 
     void assertSwitchKeyboardLayout(int direction, int displayId) {
         mTestLooper.dispatchAll();
-        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
-            verify(mInputMethodManagerInternal).onSwitchKeyboardLayoutShortcut(eq(direction),
-                    eq(displayId), eq(mImeTargetWindowToken));
-            verify(mWindowManagerFuncsImpl, never()).switchKeyboardLayout(anyInt(), anyInt());
-        } else {
-            verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
-            verify(mInputMethodManagerInternal, never())
-                    .onSwitchKeyboardLayoutShortcut(anyInt(), anyInt(), any());
-        }
+        verify(mInputMethodManagerInternal).onSwitchKeyboardLayoutShortcut(eq(direction),
+                eq(displayId), eq(mImeTargetWindowToken));
     }
 
-    void assertTakeBugreport() {
+    void assertTakeBugreport(boolean wasCalled) throws RemoteException {
         mTestLooper.dispatchAll();
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext).sendOrderedBroadcastAsUser(intentCaptor.capture(), any(), any(), any(),
-                any(), anyInt(), any(), any());
-        Assert.assertTrue(intentCaptor.getValue().getAction() == Intent.ACTION_BUG_REPORT);
+        if (wasCalled) {
+            verify(mActivityManagerService).requestInteractiveBugReport();
+        } else {
+            verify(mActivityManagerService, never()).requestInteractiveBugReport();
+        }
+
     }
 
     void assertTogglePanel() throws RemoteException {
diff --git a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
index c3da903..7322e5a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
@@ -54,6 +54,8 @@
 import android.os.PowerManager;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
+import android.view.Display;
+import android.view.WindowManager;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -82,6 +84,8 @@
     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     @Mock PowerManager mPowerManager;
+    @Mock WindowManager mWindowManager;
+    @Mock Display mDefaultDisplay;
     @Mock Clock mClock;
     @Mock WindowWakeUpPolicyInternal.InputWakeUpDelegate mInputWakeUpDelegate;
 
@@ -96,7 +100,10 @@
         mResourcesSpy = spy(mContextSpy.getResources());
         when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
         when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
+        when(mContextSpy.getSystemService(WindowManager.class)).thenReturn(mWindowManager);
+        when(mWindowManager.getDefaultDisplay()).thenReturn(mDefaultDisplay);
         LocalServices.removeServiceForTest(WindowWakeUpPolicyInternal.class);
+        setDefaultDisplayState(Display.STATE_OFF);
     }
 
     @Test
@@ -199,6 +206,19 @@
     }
 
     @Test
+    public void testTheaterModeChecksNotAppliedWhenScreenIsOn() {
+        mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
+        setDefaultDisplayState(Display.STATE_ON);
+        setTheaterModeEnabled(true);
+        setBooleanRes(config_allowTheaterModeWakeFromMotion, false);
+        mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
+
+        mPolicy.wakeUpFromMotion(200L, SOURCE_TOUCHSCREEN, true);
+
+        verify(mPowerManager).wakeUp(200L, WAKE_REASON_WAKE_MOTION, "android.policy:MOTION");
+    }
+
+    @Test
     public void testWakeUpFromMotion() {
         runPowerManagerUpChecks(
                 () -> mPolicy.wakeUpFromMotion(mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, true),
@@ -291,6 +311,7 @@
 
         Mockito.reset(mPowerManager);
         setBooleanRes(theatherModeWakeResId, true);
+        LocalServices.removeServiceForTest(WindowWakeUpPolicyInternal.class);
         mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
         setUptimeMillis(200);
         assertWithMessage("Wake should happen in theater mode when config allows it.")
@@ -299,6 +320,7 @@
 
         Mockito.reset(mPowerManager);
         setBooleanRes(theatherModeWakeResId, false);
+        LocalServices.removeServiceForTest(WindowWakeUpPolicyInternal.class);
         mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
         setUptimeMillis(250);
         assertWithMessage("Wake should not happen in theater mode when config disallows it.")
@@ -310,6 +332,7 @@
 
         Mockito.reset(mPowerManager);
         setBooleanRes(theatherModeWakeResId, true);
+        LocalServices.removeServiceForTest(WindowWakeUpPolicyInternal.class);
         mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
         setUptimeMillis(300);
         assertWithMessage("Wake should happen when not in theater mode.")
@@ -318,6 +341,7 @@
 
         Mockito.reset(mPowerManager);
         setBooleanRes(theatherModeWakeResId, false);
+        LocalServices.removeServiceForTest(WindowWakeUpPolicyInternal.class);
         mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
         setUptimeMillis(350);
         assertWithMessage("Wake should happen when not in theater mode.")
@@ -351,4 +375,8 @@
         when(mInputWakeUpDelegate.wakeUpFromKey(anyLong(), anyInt(), anyBoolean()))
                 .thenReturn(result);
     }
+
+    private void setDefaultDisplayState(int displayState) {
+        when(mDefaultDisplay.getState()).thenReturn(displayState);
+    }
 }
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 e42acba..30eb5ef 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -18,10 +18,10 @@
 
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
-import static android.app.AppCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
+import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
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 1355092..10eae57 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -46,6 +46,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Process.SYSTEM_UID;
+import static android.server.wm.ActivityManagerTestBase.isTablet;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -75,6 +76,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -122,6 +124,7 @@
 import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
 import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
 import com.android.server.wm.utils.MockTracker;
+import com.android.window.flags.Flags;
 
 import org.junit.After;
 import org.junit.Before;
@@ -1295,6 +1298,12 @@
      */
     @Test
     public void testDeliverIntentToTopActivityOfNonTopDisplay() {
+        // TODO(b/330152508): Remove check once legacy multi-display behaviour can coexist with
+        //  desktop windowing mode
+        // Ignore test if desktop windowing is enabled on tablets as legacy multi-display
+        // behaviour will not be respected
+        assumeFalse(Flags.enableDesktopWindowingMode() && isTablet());
+
         final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
                 false /* mockGetRootTask */);
 
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 400f9bb..4f94704 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -317,6 +317,70 @@
     }
 
     @Test
+    public void testEnterPipModeWhenResumed_autoEnterEnabled_returnTrue() {
+        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+        final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+        PictureInPictureParams params = mock(PictureInPictureParams.class);
+        activity.pictureInPictureArgs = params;
+
+        doReturn(true).when(activity).isState(RESUMED);
+        doReturn(false).when(activity).inPinnedWindowingMode();
+        doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+        doReturn(true).when(params).isAutoEnterEnabled();
+
+        assertTrue(mAtm.enterPictureInPictureMode(activity, params,
+                true /* fromClient */, true /* isAutoEnter */));
+    }
+
+    @Test
+    public void testEnterPipModeWhenResumed_autoEnterDisabled_returnTrue() {
+        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+        final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+        PictureInPictureParams params = mock(PictureInPictureParams.class);
+        activity.pictureInPictureArgs = params;
+
+        doReturn(true).when(activity).isState(RESUMED);
+        doReturn(false).when(activity).inPinnedWindowingMode();
+        doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+        doReturn(false).when(params).isAutoEnterEnabled();
+
+        assertTrue(mAtm.enterPictureInPictureMode(activity, params,
+                true /* fromClient */, false /* isAutoEnter */));
+    }
+
+    @Test
+    public void testEnterPipModeWhenPausing_autoEnterEnabled_returnFalse() {
+        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+        final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+        PictureInPictureParams params = mock(PictureInPictureParams.class);
+        activity.pictureInPictureArgs = params;
+
+        doReturn(true).when(activity).isState(PAUSING);
+        doReturn(false).when(activity).inPinnedWindowingMode();
+        doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+        doReturn(true).when(params).isAutoEnterEnabled();
+
+        assertFalse(mAtm.enterPictureInPictureMode(activity, params,
+                true /* fromClient */, true /* isAutoEnter */));
+    }
+
+    @Test
+    public void testEnterPipModeWhenPausing_autoEnterDisabled_returnTrue() {
+        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+        final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+        PictureInPictureParams params = mock(PictureInPictureParams.class);
+        activity.pictureInPictureArgs = params;
+
+        doReturn(true).when(activity).isState(PAUSING);
+        doReturn(false).when(activity).inPinnedWindowingMode();
+        doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+        doReturn(false).when(params).isAutoEnterEnabled();
+
+        assertTrue(mAtm.enterPictureInPictureMode(activity, params,
+                true /* fromClient */, false /* isAutoEnter */));
+    }
+
+    @Test
     public void testResumeNextActivityOnCrashedAppDied() {
         mSupervisor.beginDeferResume();
         final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
index 6b614fa..27a4a2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
@@ -343,6 +343,20 @@
         verify(mAtm).setLastResumedActivityUncheckLocked(any(), eq("test"));
     }
 
+    @Test
+    public void testUpdateTopResumed_moveToFront() {
+        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        activity2.setState(ActivityRecord.State.RESUMED, "test");
+        assertEquals(activity2.app, mAtm.mTopApp);
+        activity1.getTask().moveToFront("test");
+        // If the device is not sleeping, the app should be only set with resumed state.
+        assertEquals(activity2.app, mAtm.mTopApp);
+        activity2.setState(ActivityRecord.State.PAUSED, "test");
+        activity1.setState(ActivityRecord.State.RESUMED, "test");
+        assertEquals(activity1.app, mAtm.mTopApp);
+    }
+
     /**
      * We need to launch home again after user unlocked for those displays that do not have
      * encryption aware home app.
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
index 5aa4ba3e..695faa5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
@@ -504,22 +504,37 @@
         assertThat(balState.callerExplicitOptInOrOut()).isFalse();
         assertThat(balState.realCallerExplicitOptInOrAutoOptIn()).isTrue();
         assertThat(balState.realCallerExplicitOptInOrOut()).isFalse();
-        assertThat(balState.toString()).isEqualTo(
-                "[callingPackage: package.app1; callingPackageTargetSdk: -1; callingUid: 10001; "
-                        + "callingPid: 11001; appSwitchState: 0; callingUidHasAnyVisibleWindow: "
-                        + "false; callingUidProcState: NONEXISTENT; "
-                        + "isCallingUidPersistentSystemProcess: false; forcedBalByPiSender: BSP"
-                        + ".NONE; intent: Intent { cmp=package.app3/someClass }; callerApp: "
-                        + "mCallerApp; inVisibleTask: false; balAllowedByPiCreator: BSP"
-                        + ".ALLOW_BAL; balAllowedByPiCreatorWithHardening: BSP.ALLOW_BAL; "
-                        + "resultIfPiCreatorAllowsBal: null; hasRealCaller: true; "
-                        + "isCallForResult: false; isPendingIntent: false; autoOptInReason: "
-                        + "notPendingIntent; realCallingPackage: uid=1[debugOnly]; "
-                        + "realCallingPackageTargetSdk: -1; realCallingUid: 1; realCallingPid: 1;"
-                        + " realCallingUidHasAnyVisibleWindow: false; realCallingUidProcState: "
-                        + "NONEXISTENT; isRealCallingUidPersistentSystemProcess: false; "
-                        + "originatingPendingIntent: null; realCallerApp: null; "
-                        + "balAllowedByPiSender: BSP.ALLOW_BAL; resultIfPiSenderAllowsBal: null]");
+        assertThat(balState.toString()).contains(
+                "[callingPackage: package.app1; "
+                        + "callingPackageTargetSdk: -1; "
+                        + "callingUid: 10001; "
+                        + "callingPid: 11001; "
+                        + "appSwitchState: 0; "
+                        + "callingUidHasAnyVisibleWindow: false; "
+                        + "callingUidProcState: NONEXISTENT; "
+                        + "isCallingUidPersistentSystemProcess: false; "
+                        + "forcedBalByPiSender: BSP.NONE; "
+                        + "intent: Intent { cmp=package.app3/someClass }; "
+                        + "callerApp: mCallerApp; "
+                        + "inVisibleTask: false; "
+                        + "balAllowedByPiCreator: BSP.ALLOW_BAL; "
+                        + "balAllowedByPiCreatorWithHardening: BSP.ALLOW_BAL; "
+                        + "resultIfPiCreatorAllowsBal: null; "
+                        + "hasRealCaller: true; "
+                        + "isCallForResult: false; "
+                        + "isPendingIntent: false; "
+                        + "autoOptInReason: notPendingIntent; "
+                        + "realCallingPackage: uid=1[debugOnly]; "
+                        + "realCallingPackageTargetSdk: -1; "
+                        + "realCallingUid: 1; "
+                        + "realCallingPid: 1; "
+                        + "realCallingUidHasAnyVisibleWindow: false; "
+                        + "realCallingUidProcState: NONEXISTENT; "
+                        + "isRealCallingUidPersistentSystemProcess: false; "
+                        + "originatingPendingIntent: null; "
+                        + "realCallerApp: null; "
+                        + "balAllowedByPiSender: BSP.ALLOW_BAL; "
+                        + "resultIfPiSenderAllowsBal: null");
     }
 
     @Test
@@ -588,21 +603,36 @@
         assertThat(balState.callerExplicitOptInOrOut()).isFalse();
         assertThat(balState.realCallerExplicitOptInOrAutoOptIn()).isFalse();
         assertThat(balState.realCallerExplicitOptInOrOut()).isFalse();
-        assertThat(balState.toString()).isEqualTo(
-                "[callingPackage: package.app1; callingPackageTargetSdk: -1; callingUid: 10001; "
-                        + "callingPid: 11001; appSwitchState: 0; callingUidHasAnyVisibleWindow: "
-                        + "false; callingUidProcState: NONEXISTENT; "
-                        + "isCallingUidPersistentSystemProcess: false; forcedBalByPiSender: BSP"
-                        + ".NONE; intent: Intent { cmp=package.app3/someClass }; callerApp: "
-                        + "mCallerApp; inVisibleTask: false; balAllowedByPiCreator: BSP"
-                        + ".NONE; balAllowedByPiCreatorWithHardening: BSP.NONE; "
-                        + "resultIfPiCreatorAllowsBal: null; hasRealCaller: true; "
-                        + "isCallForResult: false; isPendingIntent: true; autoOptInReason: "
-                        + "null; realCallingPackage: uid=1[debugOnly]; "
-                        + "realCallingPackageTargetSdk: -1; realCallingUid: 1; realCallingPid: 1;"
-                        + " realCallingUidHasAnyVisibleWindow: false; realCallingUidProcState: "
-                        + "NONEXISTENT; isRealCallingUidPersistentSystemProcess: false; "
-                        + "originatingPendingIntent: PendingIntentRecord; realCallerApp: null; "
-                        + "balAllowedByPiSender: BSP.ALLOW_FGS; resultIfPiSenderAllowsBal: null]");
+        assertThat(balState.toString()).contains(
+                "[callingPackage: package.app1; "
+                        + "callingPackageTargetSdk: -1; "
+                        + "callingUid: 10001; "
+                        + "callingPid: 11001; "
+                        + "appSwitchState: 0; "
+                        + "callingUidHasAnyVisibleWindow: false; "
+                        + "callingUidProcState: NONEXISTENT; "
+                        + "isCallingUidPersistentSystemProcess: false; "
+                        + "forcedBalByPiSender: BSP.NONE; "
+                        + "intent: Intent { cmp=package.app3/someClass }; "
+                        + "callerApp: mCallerApp; "
+                        + "inVisibleTask: false; "
+                        + "balAllowedByPiCreator: BSP.NONE; "
+                        + "balAllowedByPiCreatorWithHardening: BSP.NONE; "
+                        + "resultIfPiCreatorAllowsBal: null; "
+                        + "hasRealCaller: true; "
+                        + "isCallForResult: false; "
+                        + "isPendingIntent: true; "
+                        + "autoOptInReason: null; "
+                        + "realCallingPackage: uid=1[debugOnly]; "
+                        + "realCallingPackageTargetSdk: -1; "
+                        + "realCallingUid: 1; "
+                        + "realCallingPid: 1; "
+                        + "realCallingUidHasAnyVisibleWindow: false; "
+                        + "realCallingUidProcState: NONEXISTENT; "
+                        + "isRealCallingUidPersistentSystemProcess: false; "
+                        + "originatingPendingIntent: PendingIntentRecord; "
+                        + "realCallerApp: null; "
+                        + "balAllowedByPiSender: BSP.ALLOW_FGS; "
+                        + "resultIfPiSenderAllowsBal: null");
     }
 }
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 2c88ed2..7356b43 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1717,6 +1717,7 @@
         // The display should be rotated after the launch is finished.
         doReturn(false).when(app).isAnimating(anyInt(), anyInt());
         mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
+        waitHandlerIdle(mWm.mH);
         mStatusBarWindow.finishSeamlessRotation(t);
         mNavBarWindow.finishSeamlessRotation(t);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index e14568d..e3a8542 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -38,6 +38,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
+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.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -66,6 +67,7 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
+import android.view.Display;
 import android.view.DisplayAddress;
 import android.view.IRotationWatcher;
 import android.view.Surface;
@@ -217,6 +219,79 @@
     }
 
     @Test
+    public void testUserRotationSystemProperty_NonDefault_InternalDisplay() throws Exception {
+        mBuilder.setIsDefaultDisplay(false).build();
+        when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_INTERNAL);
+        spyOn(mTarget);
+        when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+        mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+                /*fixedToUserRotation=*/ 0);
+
+        assertEquals(Surface.ROTATION_270, mTarget.getUserRotation());
+        assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+        assertEquals(0, mTarget.getFixedToUserRotationMode());
+    }
+
+    @Test
+    public void testUserRotationSystemProperty_NonDefault_ExternalDisplay() throws Exception {
+        mBuilder.setIsDefaultDisplay(false).build();
+        when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_EXTERNAL);
+        spyOn(mTarget);
+        when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+        mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+                /*fixedToUserRotation=*/ 0);
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+        assertEquals(Surface.ROTATION_90, mTarget.getUserRotation());
+        assertEquals(0, mTarget.getFixedToUserRotationMode());
+    }
+
+    @Test
+    public void testUserRotationSystemProperty_NonDefault_OverlayDisplay() throws Exception {
+        mBuilder.setIsDefaultDisplay(false).build();
+        when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_OVERLAY);
+        spyOn(mTarget);
+        when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+        mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+                /*fixedToUserRotation=*/ 0);
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+        assertEquals(Surface.ROTATION_90, mTarget.getUserRotation());
+        assertEquals(0, mTarget.getFixedToUserRotationMode());
+    }
+
+    @Test
+    public void testUserRotationSystemProperty_NonDefault_VirtualDisplay() throws Exception {
+        mBuilder.setIsDefaultDisplay(false).build();
+        when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_VIRTUAL);
+        final var packageName = "abc";
+        when(mMockDisplayContent.getDisplay().getOwnerPackageName()).thenReturn(packageName);
+        spyOn(mTarget);
+        when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+        // Without package name
+        when(mTarget.getDemoUserRotationPackage()).thenReturn("");
+        mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+                /*fixedToUserRotation=*/ 0);
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+        assertEquals(Surface.ROTATION_270, mTarget.getUserRotation());
+        assertEquals(0, mTarget.getFixedToUserRotationMode());
+
+        // Use package name
+        when(mTarget.getDemoUserRotationPackage()).thenReturn(packageName);
+        mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+                /*fixedToUserRotation=*/ 0);
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotation());
+        assertEquals(Surface.ROTATION_90, mTarget.getUserRotationMode());
+        assertEquals(0, mTarget.getFixedToUserRotationMode());
+    }
+
+    @Test
     public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception {
         mBuilder.build();
 
@@ -1450,6 +1525,7 @@
             mMockContext = mock(Context.class);
 
             mMockDisplayContent = mock(DisplayContent.class);
+            when(mMockDisplayContent.getDisplay()).thenReturn(mock(Display.class));
             mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
             when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt()))
                     .thenReturn(NO_CUTOUT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
index 80e169d..b90fa21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
@@ -25,6 +25,8 @@
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
 
+import static com.android.server.wm.testing.Assert.assertThrows;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -37,6 +39,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.wm.testing.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 
@@ -288,4 +292,56 @@
                 false /* forTabletopMode */,
                 LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
     }
+
+    @Test
+    public void test_setLetterboxHorizontalPositionMultiplier_validValues() {
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(-1));
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(2));
+
+        // Does not throw an exception for values [0,1].
+        mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0);
+        mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f);
+        mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(1);
+    }
+
+    @Test
+    public void test_setLetterboxVerticalPositionMultiplier_validValues() {
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(-1));
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(2));
+
+        // Does not throw an exception for values [0,1].
+        mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(0);
+        mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(0.5f);
+        mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(1);
+    }
+
+    @Test
+    public void test_setLetterboxBookModePositionMultiplier_validValues() {
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxBookModePositionMultiplier(-1));
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxBookModePositionMultiplier(2));
+
+        // Does not throw an exception for values [0,1].
+        mLetterboxConfiguration.setLetterboxBookModePositionMultiplier(0);
+        mLetterboxConfiguration.setLetterboxBookModePositionMultiplier(0.5f);
+        mLetterboxConfiguration.setLetterboxBookModePositionMultiplier(1);
+    }
+
+    @Test
+    public void test_setLetterboxTabletopModePositionMultiplier_validValues() {
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxTabletopModePositionMultiplier(-1));
+        assertThrows(IllegalArgumentException.class,
+                () -> mLetterboxConfiguration.setLetterboxTabletopModePositionMultiplier(2));
+
+        // Does not throw an exception for values [0,1].
+        mLetterboxConfiguration.setLetterboxTabletopModePositionMultiplier(0);
+        mLetterboxConfiguration.setLetterboxTabletopModePositionMultiplier(0.5f);
+        mLetterboxConfiguration.setLetterboxTabletopModePositionMultiplier(1);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 5aabea3..b41db31 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -643,7 +643,8 @@
         doReturn(false).when(mActivity).isInLetterboxAnimation();
         assertEquals(expectedRadius, mController.getRoundedCornersRadius(mainWindow));
 
-        doReturn(false).when(mainWindow).isOnScreen();
+        doReturn(false).when(mActivity).isVisibleRequested();
+        doReturn(false).when(mActivity).isVisible();
         assertEquals(0, mController.getRoundedCornersRadius(mainWindow));
 
         doReturn(true).when(mActivity).isInLetterboxAnimation();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 649f520..dcf3dadc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -74,6 +74,7 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.os.PowerManager;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
@@ -237,6 +238,24 @@
         assertFalse(wpc.hasActivities());
     }
 
+    @Test
+    public void testAttachApplication() {
+        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        activity.detachFromProcess();
+        mAtm.startProcessAsync(activity, false /* knownToBeDead */,
+                true /* isTop */, "test" /* hostingType */);
+        final WindowProcessController proc = mSystemServicesTestRule.addProcess(
+                activity.packageName, activity.processName,
+                6789 /* pid */, activity.info.applicationInfo.uid);
+        try {
+            mRootWindowContainer.attachApplication(proc);
+            verify(mSupervisor).realStartActivityLocked(eq(activity), eq(proc), anyBoolean(),
+                    anyBoolean());
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
     /**
      * This test ensures that we do not try to restore a task based off an invalid task id. We
      * should expect {@code null} to be returned in this case.
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 856ad2a..ac1dc08 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -502,7 +502,6 @@
         final WindowConfiguration translucentWinConf = requestedConfig.windowConfiguration;
         translucentWinConf.setActivityType(ACTIVITY_TYPE_STANDARD);
         translucentWinConf.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        translucentWinConf.setDisplayWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         translucentWinConf.setAlwaysOnTop(true);
         translucentActivity.onRequestedOverrideConfigurationChanged(requestedConfig);
 
@@ -511,7 +510,6 @@
         // The original override of WindowConfiguration should keep.
         assertEquals(ACTIVITY_TYPE_STANDARD, translucentActivity.getActivityType());
         assertEquals(WINDOWING_MODE_MULTI_WINDOW, translucentWinConf.getWindowingMode());
-        assertEquals(WINDOWING_MODE_MULTI_WINDOW, translucentWinConf.getDisplayWindowingMode());
         assertTrue(translucentWinConf.isAlwaysOnTop());
         // Unless display is going to be rotated, it should always inherit from parent.
         assertEquals(ROTATION_UNDEFINED, translucentWinConf.getDisplayRotation());
@@ -915,8 +913,7 @@
         assertEquals(window, mActivity.findMainWindow());
 
         spyOn(mActivity.mLetterboxUiController);
-        doReturn(true).when(mActivity.mLetterboxUiController)
-                .isSurfaceVisible(any());
+        doReturn(true).when(mActivity).isVisibleRequested();
 
         assertTrue(mActivity.mLetterboxUiController.shouldShowLetterboxUi(
                 mActivity.findMainWindow()));
@@ -1385,6 +1382,25 @@
     }
 
     @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_ANY_ORIENTATION_TO_USER})
+    public void testShouldNotCreateCompatDisplays_systemFullscreenOverride() {
+        setUpDisplaySizeWithApp(1000, 2500);
+
+        // Make the task root resizable.
+        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
+
+        // Create an activity on the same task.
+        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
+                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+        // Simulate the user selecting the fullscreen user aspect ratio override
+        spyOn(activity.mLetterboxUiController);
+        doReturn(true).when(activity.mLetterboxUiController)
+                .isSystemOverrideToFullscreenEnabled();
+        assertFalse(activity.shouldCreateCompatDisplayInsets());
+    }
+
+    @Test
     @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
     public void testNeverSandboxDisplayApis_configEnabled_sandboxingNotApplied() {
         setUpDisplaySizeWithApp(1000, 1200);
@@ -1942,8 +1958,7 @@
         assertThat(mActivity.inSizeCompatMode()).isTrue();
         assertActivityMaxBoundsSandboxed();
 
-
-	final int scale = dh / dw;
+        final int scale = dh / dw;
 
         // App bounds should be dh / scale x dw / scale
         assertEquals(dw, rotatedDisplayBounds.width());
@@ -2363,6 +2378,92 @@
     }
 
     @Test
+    public void testUserOverrideFullscreenForLandscapeDisplay() {
+        final int displayWidth = 1600;
+        final int displayHeight = 1400;
+        setUpDisplaySizeWithApp(displayWidth, displayHeight);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        spyOn(mActivity.mWmService.mLetterboxConfiguration);
+        doReturn(true).when(mActivity.mWmService.mLetterboxConfiguration)
+                .isUserAppAspectRatioFullscreenEnabled();
+
+        // Set user aspect ratio override
+        spyOn(mActivity.mLetterboxUiController);
+        doReturn(USER_MIN_ASPECT_RATIO_FULLSCREEN).when(mActivity.mLetterboxUiController)
+                .getUserMinAspectRatioOverrideCode();
+
+        prepareMinAspectRatio(mActivity, 16 / 9f, SCREEN_ORIENTATION_PORTRAIT);
+
+        final Rect bounds = mActivity.getBounds();
+
+        // bounds should be fullscreen
+        assertEquals(displayHeight, bounds.height());
+        assertEquals(displayWidth, bounds.width());
+    }
+
+    @Test
+    public void testUserOverrideFullscreenForPortraitDisplay() {
+        final int displayWidth = 1400;
+        final int displayHeight = 1600;
+        setUpDisplaySizeWithApp(displayWidth, displayHeight);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        spyOn(mActivity.mWmService.mLetterboxConfiguration);
+        doReturn(true).when(mActivity.mWmService.mLetterboxConfiguration)
+                .isUserAppAspectRatioFullscreenEnabled();
+
+        // Set user aspect ratio override
+        spyOn(mActivity.mLetterboxUiController);
+        doReturn(USER_MIN_ASPECT_RATIO_FULLSCREEN).when(mActivity.mLetterboxUiController)
+                .getUserMinAspectRatioOverrideCode();
+
+        prepareMinAspectRatio(mActivity, 16 / 9f, SCREEN_ORIENTATION_LANDSCAPE);
+
+        final Rect bounds = mActivity.getBounds();
+
+        // bounds should be fullscreen
+        assertEquals(displayHeight, bounds.height());
+        assertEquals(displayWidth, bounds.width());
+    }
+
+    @Test
+    public void testSystemFullscreenOverrideForLandscapeDisplay() {
+        final int displayWidth = 1600;
+        final int displayHeight = 1400;
+        setUpDisplaySizeWithApp(displayWidth, displayHeight);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        spyOn(mActivity.mLetterboxUiController);
+        doReturn(true).when(mActivity.mLetterboxUiController)
+                .isSystemOverrideToFullscreenEnabled();
+
+        prepareMinAspectRatio(mActivity, 16 / 9f, SCREEN_ORIENTATION_PORTRAIT);
+
+        final Rect bounds = mActivity.getBounds();
+
+        // bounds should be fullscreen
+        assertEquals(displayHeight, bounds.height());
+        assertEquals(displayWidth, bounds.width());
+    }
+
+    @Test
+    public void testSystemFullscreenOverrideForPortraitDisplay() {
+        final int displayWidth = 1400;
+        final int displayHeight = 1600;
+        setUpDisplaySizeWithApp(displayWidth, displayHeight);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        spyOn(mActivity.mLetterboxUiController);
+        doReturn(true).when(mActivity.mLetterboxUiController)
+                .isSystemOverrideToFullscreenEnabled();
+
+        prepareMinAspectRatio(mActivity, 16 / 9f, SCREEN_ORIENTATION_LANDSCAPE);
+
+        final Rect bounds = mActivity.getBounds();
+
+        // bounds should be fullscreen
+        assertEquals(displayHeight, bounds.height());
+        assertEquals(displayWidth, bounds.width());
+    }
+
+    @Test
     public void testUserOverrideSplitScreenAspectRatioForLandscapeDisplay() {
         final int displayWidth = 1600;
         final int displayHeight = 1400;
@@ -4056,31 +4157,6 @@
     }
 
     @Test
-    public void testUpdateResolvedBoundsHorizontalPosition_invalidMultiplier_defaultToCenter() {
-        // Display configured as (2800, 1400).
-
-        // Below 0.0.
-        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
-                /* letterboxHorizontalPositionMultiplier */ -1.0f,
-                // At launch.
-                /* fixedOrientationLetterbox */ new Rect(1050, 0, 1750, 1400),
-                // After 90 degree rotation.
-                /* sizeCompatUnscaled */ new Rect(350, 0, 1050, 1400),
-                // After the display is resized to (700, 1400).
-                /* sizeCompatScaled */ new Rect(525, 0, 875, 700));
-
-        // Above 1.0
-        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
-                /* letterboxHorizontalPositionMultiplier */ 2.0f,
-                // At launch.
-                /* fixedOrientationLetterbox */ new Rect(1050, 0, 1750, 1400),
-                // After 90 degree rotation.
-                /* sizeCompatUnscaled */ new Rect(350, 0, 1050, 1400),
-                // After the display is resized to (700, 1400).
-                /* sizeCompatScaled */ new Rect(525, 0, 875, 700));
-    }
-
-    @Test
     public void testUpdateResolvedBoundsHorizontalPosition_right() {
         // Display configured as (2800, 1400).
         assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
@@ -4117,12 +4193,8 @@
     }
 
     @Test
-    public void testPortraitCloseToSquareDisplayWithTaskbar_notLetterboxed() {
-        if (Flags.insetsDecoupledConfiguration()) {
-            // TODO (b/151861875): Re-enable it. This is disabled temporarily because the config
-            //  bounds no longer contains display cutout.
-            return;
-        }
+    @DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
+    public void testPortraitCloseToSquareDisplayWithTaskbar_letterboxed() {
         // Set up portrait close to square display
         setUpDisplaySizeWithApp(2200, 2280);
         final DisplayContent display = mActivity.mDisplayContent;
@@ -4135,16 +4207,58 @@
                         .setInsetsSize(Insets.of(0, 0, 0, 150))
         };
         display.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
-        assertTrue(navbar.providesDisplayDecorInsets()
-                && display.getDisplayPolicy().updateDecorInsetsInfo());
+        assertTrue(display.getDisplayPolicy().updateDecorInsetsInfo());
         display.sendNewConfiguration();
 
-        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(mTask)
+                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+                .setComponent(ComponentName.createRelative(mContext,
+                        SizeCompatTests.class.getName()))
+                .setUid(android.os.Process.myUid())
+                .build();
 
-        // Activity is fullscreen even though orientation is not respected with insets, because
-        // the display still matches or is less than the activity aspect ratio
-        assertEquals(display.getBounds(), mActivity.getBounds());
-        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+        final Rect bounds = activity.getBounds();
+        // Activity should be letterboxed and should have portrait app bounds
+        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+        assertTrue(bounds.height() > bounds.width());
+    }
+
+    @Test
+    @DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
+    public void testFixedAspectRatioAppInPortraitCloseToSquareDisplay_notInSizeCompat() {
+        setUpDisplaySizeWithApp(2200, 2280);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        final DisplayContent dc = mActivity.mDisplayContent;
+        // Simulate taskbar, final app bounds are (0, 0, 2200, 2130) - landscape
+        final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
+                "navbar");
+        final Binder owner = new Binder();
+        navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars())
+                        .setInsetsSize(Insets.of(0, 0, 0, 150))
+        };
+        dc.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
+        assertTrue(dc.getDisplayPolicy().updateDecorInsetsInfo());
+        dc.sendNewConfiguration();
+
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(mTask)
+                .setComponent(ComponentName.createRelative(mContext,
+                        SizeCompatTests.class.getName()))
+                .setUid(android.os.Process.myUid())
+                .build();
+        prepareMinAspectRatio(activity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
+                SCREEN_ORIENTATION_LANDSCAPE);
+        // To force config to update again but with the same landscape orientation.
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+
+        assertTrue(activity.shouldCreateCompatDisplayInsets());
+        assertNotNull(activity.getCompatDisplayInsets());
+        // Activity is not letterboxed for fixed orientation because orientation is respected
+        // with insets, and should not be in size compat mode
+        assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+        assertFalse(activity.inSizeCompatMode());
     }
 
     @Test
@@ -4166,6 +4280,7 @@
         // can be aligned inside parentAppBounds
         assertEquals(mActivity.getBounds(), new Rect(0, 0, 1000, 2200));
     }
+
     @Test
     public void testApplyAspectRatio_activityCannotAlignWithParentAppVertical() {
         if (Flags.insetsDecoupledConfiguration()) {
@@ -4310,31 +4425,6 @@
     }
 
     @Test
-    public void testUpdateResolvedBoundsVerticalPosition_invalidMultiplier_defaultToCenter() {
-        // Display configured as (1400, 2800).
-
-        // Below 0.0.
-        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
-                /* letterboxVerticalPositionMultiplier */ -1.0f,
-                // At launch.
-                /* fixedOrientationLetterbox */ new Rect(0, 1050, 1400, 1750),
-                // After 90 degree rotation.
-                /* sizeCompatUnscaled */ new Rect(700, 350, 2100, 1050),
-                // After the display is resized to (1400, 700).
-                /* sizeCompatScaled */ new Rect(0, 525, 700, 875));
-
-        // Above 1.0
-        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
-                /* letterboxVerticalPositionMultiplier */ 2.0f,
-                // At launch.
-                /* fixedOrientationLetterbox */ new Rect(0, 1050, 1400, 1750),
-                // After 90 degree rotation.
-                /* sizeCompatUnscaled */ new Rect(700, 350, 2100, 1050),
-                // After the display is resized to (1400, 700).
-                /* sizeCompatScaled */ new Rect(0, 525, 700, 875));
-    }
-
-    @Test
     public void testUpdateResolvedBoundsVerticalPosition_bottom() {
         // Display configured as (1400, 2800).
         assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
@@ -4394,6 +4484,21 @@
     }
 
     @Test
+    public void testPortraitAppInTabletop_notSplitScreen() {
+        final int dw = 2400;
+        setUpDisplaySizeWithApp(dw, 2000);
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+        final int initialWidth = mActivity.getBounds().width();
+
+        setFoldablePosture(true /* isHalfFolded */, true /* isTabletop */);
+
+        final int finalWidth = mActivity.getBounds().width();
+        assertEquals(initialWidth, finalWidth);
+        assertNotEquals(finalWidth, getExpectedSplitSize(dw));
+    }
+
+    @Test
     public void testUpdateResolvedBoundsHorizontalPosition_bookModeEnabled() {
         // Set up a display in landscape with a fixed-orientation PORTRAIT app
         setUpDisplaySizeWithApp(2800, 1400);
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 413d003..b9fe074 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -68,6 +68,7 @@
 import android.os.PowerSaveState;
 import android.os.StrictMode;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.Log;
 import android.view.DisplayInfo;
@@ -194,6 +195,7 @@
         mMockitoSession = mockitoSession()
                 .mockStatic(LocalServices.class, spyStubOnly)
                 .mockStatic(DeviceConfig.class, spyStubOnly)
+                .mockStatic(UserManager.class, spyStubOnly)
                 .mockStatic(SurfaceControl.class, mockStubOnly)
                 .mockStatic(DisplayControl.class, mockStubOnly)
                 .mockStatic(LockGuard.class, mockStubOnly)
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 52485ee..83e4151 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -19,6 +19,8 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -879,7 +881,7 @@
         mTransaction.addTaskFragmentOperation(mFragmentToken, operation);
         final TaskFragmentOperation dimOperation = new TaskFragmentOperation.Builder(
                 OP_TYPE_SET_DIM_ON_TASK)
-                .setDimOnTask(true)
+                .setBooleanValue(true)
                 .build();
         mTransaction.addTaskFragmentOperation(mFragmentToken, dimOperation);
         mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
@@ -1024,6 +1026,60 @@
     }
 
     @Test
+    public void testApplyTransaction_createTaskFragment_overrideOrientation_systemOrganizer() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_TASK_FRAGMENT_SYSTEM_ORGANIZER_FLAG);
+        mController.unregisterOrganizer(mIOrganizer);
+        registerTaskFragmentOrganizer(mIOrganizer, true /* isSystemOrganizer */);
+
+        final Task task = createTask(mDisplayContent);
+        final ActivityRecord activity = createActivityRecord(task);
+        final int uid = Binder.getCallingUid();
+        activity.info.applicationInfo.uid = uid;
+        activity.getTask().effectiveUid = uid;
+        final IBinder fragmentToken = new Binder();
+
+        // Create a TaskFragment with OverrideOrientation set.
+        final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+                mOrganizerToken, fragmentToken, activity.token)
+                .setOverrideOrientation(SCREEN_ORIENTATION_BEHIND)
+                .build();
+        mTransaction.setTaskFragmentOrganizer(mIOrganizer);
+        mTransaction.createTaskFragment(params);
+        assertApplyTransactionAllowed(mTransaction);
+
+        // TaskFragment override orientation should be set for a system organizer.
+        final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
+        assertNotNull(taskFragment);
+
+        taskFragment.setVisibleRequested(true);
+        assertEquals(SCREEN_ORIENTATION_BEHIND, taskFragment.getOverrideOrientation());
+    }
+
+    @Test
+    public void testApplyTransaction_createTaskFragment_overrideOrientation_nonSystemOrganizer() {
+        final Task task = createTask(mDisplayContent);
+        final ActivityRecord activity = createActivityRecord(task);
+        final int uid = Binder.getCallingUid();
+        activity.info.applicationInfo.uid = uid;
+        activity.getTask().effectiveUid = uid;
+        final IBinder fragmentToken = new Binder();
+
+        // Create a TaskFragment with OverrideOrientation set.
+        final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+                mOrganizerToken, fragmentToken, activity.token)
+                .setOverrideOrientation(SCREEN_ORIENTATION_BEHIND)
+                .build();
+        mTransaction.setTaskFragmentOrganizer(mIOrganizer);
+        mTransaction.createTaskFragment(params);
+        assertApplyTransactionAllowed(mTransaction);
+
+        // TaskFragment override orientation is ignored for a non-system organizer.
+        final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
+        assertNotNull(taskFragment);
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, taskFragment.getOverrideOrientation());
+    }
+
+    @Test
     public void testApplyTransaction_reparentActivityToTaskFragment_triggerLifecycleUpdate() {
         final Task task = createTask(mDisplayContent);
         final ActivityRecord activity = createActivityRecord(task);
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 3c5b12c..a90a158 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -22,6 +22,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -752,6 +753,42 @@
     }
 
     @Test
+    public void testGetOrientation_reportOverrideOrientation() {
+        final Task task = createTask(mDisplayContent);
+        final TaskFragment tf = createTaskFragmentWithActivity(task);
+        final ActivityRecord activity = tf.getTopMostActivity();
+        tf.setVisibleRequested(true);
+        tf.setOverrideOrientation(SCREEN_ORIENTATION_BEHIND);
+
+        // Should report the override orientation
+        assertEquals(SCREEN_ORIENTATION_BEHIND, tf.getOrientation(SCREEN_ORIENTATION_UNSET));
+
+        // Should report the override orientation even if the activity requests a different value
+        activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_BEHIND, tf.getOrientation(SCREEN_ORIENTATION_UNSET));
+    }
+
+    @Test
+    public void testGetOrientation_reportOverrideOrientation_whenInvisible() {
+        final Task task = createTask(mDisplayContent);
+        final TaskFragment tf = createTaskFragmentWithActivity(task);
+        final ActivityRecord activity = tf.getTopMostActivity();
+        tf.setVisibleRequested(false);
+        tf.setOverrideOrientation(SCREEN_ORIENTATION_BEHIND);
+
+        // Should report SCREEN_ORIENTATION_UNSPECIFIED for the override orientation when invisible
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, tf.getOverrideOrientation());
+
+        // Should report SCREEN_ORIENTATION_UNSET for the orientation
+        assertEquals(SCREEN_ORIENTATION_UNSET, tf.getOrientation(SCREEN_ORIENTATION_UNSET));
+
+        // Should report SCREEN_ORIENTATION_UNSET even if the activity requests a different
+        // value
+        activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_UNSET, tf.getOrientation(SCREEN_ORIENTATION_UNSET));
+    }
+
+    @Test
     public void testUpdateImeParentForActivityEmbedding() {
         // Setup two activities in ActivityEmbedding.
         final Task task = createTask(mDisplayContent);
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 1ca808f..225e85e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -833,8 +833,11 @@
         final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
         final ActivityRecord.CompatDisplayInsets compatInsets =
                 new ActivityRecord.CompatDisplayInsets(
-                        display, activity, /* fixedOrientationBounds= */ null);
-        task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatInsets);
+                        display, activity, /* letterboxedContainerBounds */ null,
+                        /* useOverrideInsets */ false);
+        final TaskFragment.ConfigOverrideHint overrideHint = new TaskFragment.ConfigOverrideHint();
+        overrideHint.mTmpCompatInsets = compatInsets;
+        task.computeConfigResourceOverrides(inOutConfig, parentConfig, overrideHint);
 
         assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds());
         final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
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 0186006..3288788 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -23,6 +23,7 @@
 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;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -1630,6 +1631,7 @@
         assertTrue(controller.mWaitingTransitions.contains(transition));
         assertTrue(controller.isTransientHide(appTask));
         assertTrue(controller.isTransientVisible(appTask));
+        assertTrue(controller.isTransientLaunch(recent));
     }
 
     @Test
@@ -1664,7 +1666,11 @@
         final Task task = createTask(mDisplayContent);
         final ActivityRecord activity0 = createActivityRecord(task);
         final ActivityRecord activity1 = createActivityRecord(task);
-        doReturn(true).when(activity1).hasStartingWindow();
+        final WindowManager.LayoutParams attrs =
+                new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
+        final TestWindowState startingWindow = createWindowState(attrs, activity1);
+        activity1.mStartingData = mock(StartingData.class);
+        activity1.addWindow(startingWindow);
 
         // Start states.
         changes.put(activity0,
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 72bedf2..5b1a18d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -410,6 +410,8 @@
         final WindowState wallpaperWindow = createWallpaperWindow(dc);
         final WallpaperWindowToken token = wallpaperWindow.mToken.asWallpaperToken();
         wallpaperWindow.setHasSurface(true);
+        spyOn(dc.mWallpaperController);
+        doReturn(wallpaperWindow).when(dc.mWallpaperController).getWallpaperTarget();
 
         // Set-up mock shell transitions
         registerTestTransitionPlayer();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index 38aac7c..eca51ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -16,9 +16,7 @@
 
 package com.android.server.wm;
 
-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.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -208,43 +206,6 @@
 
     /** Ensure the window always has a caption in Freeform window mode or display mode. */
     @Test
-    public void testCaptionShownForFreeformWindowingMode() {
-        final WindowConfiguration config = new WindowConfiguration();
-        config.setActivityType(ACTIVITY_TYPE_STANDARD);
-        config.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        config.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertTrue(config.hasWindowDecorCaption());
-
-        config.setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertTrue(config.hasWindowDecorCaption());
-
-        config.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertTrue(config.hasWindowDecorCaption());
-
-        config.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertFalse(config.hasWindowDecorCaption());
-    }
-
-    /** Caption should not show for non-standard activity window. */
-    @Test
-    public void testCaptionNotShownForNonStandardActivityType() {
-        final WindowConfiguration config = new WindowConfiguration();
-        config.setActivityType(ACTIVITY_TYPE_HOME);
-        config.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        config.setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertFalse(config.hasWindowDecorCaption());
-
-        config.setActivityType(ACTIVITY_TYPE_ASSISTANT);
-        assertFalse(config.hasWindowDecorCaption());
-
-        config.setActivityType(ACTIVITY_TYPE_RECENTS);
-        assertFalse(config.hasWindowDecorCaption());
-
-        config.setActivityType(ACTIVITY_TYPE_STANDARD);
-        assertTrue(config.hasWindowDecorCaption());
-    }
-
-    @Test
     public void testMaskedSetTo() {
         final WindowConfiguration config = new WindowConfiguration();
         final WindowConfiguration other = new WindowConfiguration();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index ec2c968..5fe71a1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -25,7 +25,6 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_OWN_FOCUS;
 import static android.view.Display.INVALID_DISPLAY;
-import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_TRACING;
@@ -38,6 +37,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION;
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -82,6 +82,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.annotations.RequiresFlagsDisabled;
 import android.platform.test.annotations.RequiresFlagsEnabled;
@@ -1162,7 +1163,8 @@
             invocationOnMock.callRealMethod();
             return null;
         }).when(surface).lockCanvas(any());
-        mWm.mAccessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId);
+        mWm.mAccessibilityController
+                .recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded(displayId);
         waitUntilHandlersIdle();
         try {
             verify(surface).lockCanvas(any());
@@ -1170,7 +1172,8 @@
             clearInvocations(surface);
             // Invalidate and redraw.
             mWm.mAccessibilityController.onDisplaySizeChanged(mDisplayContent);
-            mWm.mAccessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId);
+            mWm.mAccessibilityController
+                    .recomputeMagnifiedRegionAndDrawMagnifiedRegionBorderIfNeeded(displayId);
             // Turn off magnification to release surface.
             mWm.mAccessibilityController.setMagnificationCallbacks(displayId, null);
             waitUntilHandlersIdle();
@@ -1302,7 +1305,8 @@
     }
 
     @Test
-    public void testAddOverlayWindowToUnassignedDisplay_notAllowed() {
+    public void testAddOverlayWindowToUnassignedDisplay_notAllowed_ForVisibleBackgroundUsers() {
+        doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
         int uid = 100000; // uid for non-system user
         Session session = createTestSession(mAtm, 1234 /* pid */, uid);
         DisplayContent dc = createNewDisplay();
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 400e4b6..059fed20 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -406,6 +406,7 @@
         verify(tracker).onActivityResumedWhileVisible(mWpc);
         assertTrue(tracker.hasResumedActivity(mWpc.mUid));
 
+        mAtm.mTopApp = null;
         activity.makeFinishingLocked();
         activity.setState(PAUSING, "test");
 
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index e8ffe54..e00627e 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -44,6 +44,7 @@
 aconfig_declarations {
     name: "usb_flags",
     package: "com.android.server.usb.flags",
+    container: "system",
     srcs: ["**/usb_flags.aconfig"],
 }
 
diff --git a/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig b/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
index ea6e502..a7c5ddb 100644
--- a/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
+++ b/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.server.usb.flags"
+container: "system"
 
 flag {
     name: "allow_restriction_of_overlay_activities"
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index ae4faa8..e5d7b40e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -127,6 +127,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -180,7 +181,8 @@
                 LocalServices.getService(ActivityManagerInternal.class));
         mAtmInternal = Objects.requireNonNull(
                 LocalServices.getService(ActivityTaskManagerInternal.class));
-        mWmInternal = LocalServices.getService(WindowManagerInternal.class);
+        mWmInternal = Objects.requireNonNull(
+                LocalServices.getService(WindowManagerInternal.class));
         mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
         LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService(
                 LegacyPermissionManagerInternal.class);
@@ -2737,12 +2739,8 @@
                     isManagedProfileVisible = true;
                 }
             }
-            final ScreenCapture.ScreenshotHardwareBuffer shb;
-            if (mWmInternal != null) {
-                shb = mWmInternal.takeAssistScreenshot();
-            } else {
-                shb = null;
-            }
+            final ScreenCapture.ScreenshotHardwareBuffer shb =
+                    mWmInternal.takeAssistScreenshot(/* windowTypesToExclude= */ Set.of());
             final Bitmap bm = shb != null ? shb.asBitmap() : null;
             // Now that everything is fetched, putting it in the launchIntent.
             if (bm != null) {
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index ec60c67..0ddc38a 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -35,8 +35,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.internal.telephony.flags.FeatureFlagsImpl;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -48,8 +46,7 @@
     private static final String LOG_TAG = "TelephonyPermissions";
 
     private static final boolean DBG = false;
-    /** Feature flags */
-    private static final FeatureFlags sFeatureFlag = new FeatureFlagsImpl();
+
     /**
      * Whether to disable the new device identifier access restrictions.
      */
@@ -886,12 +883,6 @@
      */
     public static boolean checkSubscriptionAssociatedWithUser(@NonNull Context context, int subId,
             @NonNull UserHandle callerUserHandle) {
-        if (!sFeatureFlag.rejectBadSubIdInteraction()
-                && !SubscriptionManager.isValidSubscriptionId(subId)) {
-            // Return true for invalid sub Id.
-            return true;
-        }
-
         SubscriptionManager subManager = (SubscriptionManager) context.getSystemService(
                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         final long token = Binder.clearCallingIdentity();
@@ -906,7 +897,7 @@
         } catch (IllegalArgumentException e) {
             // Found no record of this sub Id.
             Log.e(LOG_TAG, "Subscription[Subscription ID:" + subId + "] has no records on device");
-            return !sFeatureFlag.rejectBadSubIdInteraction();
+            return false;
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 7b5b07c..f31a87f 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -349,15 +349,16 @@
     }
 
     /**
-     * @param plmn target plmn for validation.
-     * @return {@code true} if the target plmn is valid {@code false} otherwise.
+     * @param input string that want to be compared.
+     * @param regex string that express regular expression
+     * @return {@code true} if matched  {@code false} otherwise.
      */
-    public static boolean isValidPlmn(@Nullable String plmn) {
-        if (TextUtils.isEmpty(plmn)) {
+    private static boolean isValidPattern(@Nullable String input, @Nullable String regex) {
+        if (TextUtils.isEmpty(input) || TextUtils.isEmpty(regex)) {
             return false;
         }
-        Pattern pattern = Pattern.compile("^(?:[0-9]{3})(?:[0-9]{2}|[0-9]{3})$");
-        Matcher matcher = pattern.matcher(plmn);
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(input);
         if (!matcher.matches()) {
             return false;
         }
@@ -365,6 +366,22 @@
     }
 
     /**
+     * @param countryCode two letters country code based on the ISO 3166-1.
+     * @return {@code true} if the countryCode is valid {@code false} otherwise.
+     */
+    public static boolean isValidCountryCode(@Nullable String countryCode) {
+        return isValidPattern(countryCode, "^[A-Za-z]{2}$");
+    }
+
+    /**
+     * @param plmn target plmn for validation.
+     * @return {@code true} if the target plmn is valid {@code false} otherwise.
+     */
+    public static boolean isValidPlmn(@Nullable String plmn) {
+        return isValidPattern(plmn, "^(?:[0-9]{3})(?:[0-9]{2}|[0-9]{3})$");
+    }
+
+    /**
      * @param serviceType target serviceType for validation.
      * @return {@code true} if the target serviceType is valid {@code false} otherwise.
      */
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 10c17c1..7db4180 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9898,6 +9898,50 @@
      */
     public static final String KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING =
             "satellite_information_redirect_url_string";
+    /**
+     * Indicate whether a carrier supports emergency messaging. When this config is {@code  false},
+     * emergency call to satellite T911 handover will be disabled.
+     *
+     * This will need agreement with carriers before enabling this flag.
+     *
+     * The default value is false.
+     *
+     * @hide
+     */
+    public static final String KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL =
+            "emergency_messaging_supported_bool";
+
+    /**
+     * An integer key holds the timeout duration in milliseconds used to determine whether to hand
+     * over an emergency call to satellite T911.
+     *
+     * The timer is started when there is an ongoing emergency call, and the IMS is not registered,
+     * and cellular service is not available. When the timer expires,
+     * {@link com.android.internal.telephony.satellite.SatelliteSOSMessageRecommender} will send the
+     * event {@link TelephonyManager#EVENT_DISPLAY_EMERGENCY_MESSAGE} to Dialer, which will then
+     * prompt user to switch to using satellite emergency messaging.
+     *
+     * The default value is 30 seconds.
+     *
+     * @hide
+     */
+    public static final String KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT =
+            "emergency_call_to_satellite_t911_handover_timeout_millis_int";
+
+    /**
+     * An int array that contains default capabilities for carrier enabled satellite roaming.
+     * If any PLMN is provided from the entitlement server, and it is not listed in
+     * {@link #KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE}, default capabilities
+     * will be used instead.
+     * <p>
+     * The default capabilities are
+     * {@link NetworkRegistrationInfo#SERVICE_TYPE_SMS}, and
+     * {@link NetworkRegistrationInfo#SERVICE_TYPE_MMS}
+     *
+     * @hide
+     */
+    public static final String KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY =
+            "carrier_roaming_satellite_default_services_int_array";
 
     /**
      * Indicating whether DUN APN should be disabled when the device is roaming. In that case,
@@ -11045,7 +11089,15 @@
         sDefaults.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
         sDefaults.putString(KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING, "androidSatmode");
         sDefaults.putString(KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING, "");
+        sDefaults.putIntArray(KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+                new int[] {
+                        NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+                        NetworkRegistrationInfo.SERVICE_TYPE_MMS
+                });
         sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
+        sDefaults.putBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, false);
+        sDefaults.putInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
+                (int) TimeUnit.SECONDS.toMillis(30));
         sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c5f2d42..8fe45cb 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3137,7 +3137,7 @@
             if (useRootLocale) {
                 configurationKey.setLocale(Locale.ROOT);
             }
-            cacheKey = Pair.create(context.getPackageName(), configurationKey);
+            cacheKey = Pair.create(context.getPackageName() + ", subid=" + subId, configurationKey);
             synchronized (sResourcesCache) {
                 Resources cached = sResourcesCache.get(cacheKey);
                 if (cached != null) {
@@ -4614,6 +4614,31 @@
     }
 
     /**
+     * Set owner for this subscription.
+     *
+     * @param subscriptionId the subId of the subscription.
+     * @param groupOwner The group owner to assign to the subscription
+     *
+     * @throws SecurityException if caller is not authorized.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setGroupOwner(int subscriptionId, @NonNull String groupOwner) {
+        try {
+            ISub iSub = TelephonyManager.getSubscriptionService();
+            if (iSub != null) {
+                iSub.setGroupOwner(subscriptionId, groupOwner);
+            } else {
+                throw new IllegalStateException("[setGroupOwner]: "
+                        + "subscription service unavailable");
+            }
+        } catch (RemoteException ex) {
+            ex.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * Set userHandle for a subscription.
      *
      * Used to set an association between a subscription and a user on the device so that voice
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0a8a18dc..f076de3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -289,7 +289,7 @@
     @SystemApi
     public static final int RADIO_POWER_REASON_NEARBY_DEVICE = 3;
 
-    /** The otaspMode passed to PhoneStateListener#onOtaspChanged */
+    /** The otaspMode passed to SercvieState changes */
     /** @hide */
     static public final int OTASP_UNINITIALIZED = 0;
     /** @hide */
@@ -995,9 +995,9 @@
             "android.intent.action.CALL_DISCONNECT_CAUSE";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
-     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
-     * containing the disconnect cause.
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and {@link
+     * TelephonyCallback.PreciseCallStateListener#onPreciseCallStateChanged(PreciseCallState)} for
+     * an integer containing the disconnect cause.
      *
      * @see DisconnectCause
      *
@@ -1012,9 +1012,9 @@
     public static final String EXTRA_DISCONNECT_CAUSE = "disconnect_cause";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
-     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
-     * containing the disconnect cause provided by the RIL.
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and {@link
+     * TelephonyCallback.PreciseCallStateListener#onPreciseCallStateChanged(PreciseCallState)} for
+     * an integer containing the disconnect cause provided by the RIL.
      *
      * @see PreciseDisconnectCause
      *
@@ -6437,8 +6437,8 @@
      * This method considers not only calls in the Telephony stack, but also calls via other
      * {@link android.telecom.ConnectionService} implementations.
      * <p>
-     * Note: The call state returned via this method may differ from what is reported by
-     * {@link PhoneStateListener#onCallStateChanged(int, String)}, as that callback only considers
+     * Note: The call state returned via this method may differ from what is reported by {@link
+     * TelephonyCallback.CallStateListener#onCallStateChanged(int)}, as that callback only considers
      * Telephony (mobile) calls.
      * <p>
      * Requires Permission:
@@ -6996,7 +6996,7 @@
      *
      * <p>Beginning with {@link android.os.Build.VERSION_CODES#Q Android Q},
      * if this API results in a change of the cached CellInfo, that change will be reported via
-     * {@link android.telephony.PhoneStateListener#onCellInfoChanged onCellInfoChanged()}.
+     * {@link TelephonyCallback.CellInfoListener#onCellInfoChanged(List) onCellInfoChanged()}.
      *
      * <p>Apps targeting {@link android.os.Build.VERSION_CODES#Q Android Q} or higher will no
      * longer trigger a refresh of the cached CellInfo by invoking this API. Instead, those apps
@@ -7109,7 +7109,7 @@
      * camped/registered, serving, and neighboring cells.
      *
      * <p>Any available results from this request will be provided by calls to
-     * {@link android.telephony.PhoneStateListener#onCellInfoChanged onCellInfoChanged()}
+     * {@link TelephonyCallback.CellInfoListener#onCellInfoChanged(List) onCellInfoChanged()}
      * for each active subscription.
      *
      * <p>This method returns valid data for devices with
@@ -7172,7 +7172,7 @@
      * camped/registered, serving, and neighboring cells.
      *
      * <p>Any available results from this request will be provided by calls to
-     * {@link android.telephony.PhoneStateListener#onCellInfoChanged onCellInfoChanged()}
+     * {@link TelephonyCallback.CellInfoListener#onCellInfoChanged(List) onCellInfoChanged()}
      * for each active subscription.
      *
      * <p>This method returns valid data for devices with
@@ -7248,8 +7248,8 @@
     }
 
     /**
-     * Sets the minimum time in milli-seconds between {@link PhoneStateListener#onCellInfoChanged
-     * PhoneStateListener.onCellInfoChanged} will be invoked.
+     * Sets the minimum time in milli-seconds between {@link
+     * TelephonyCallback.CellInfoListener#onCellInfoChanged(List)} will be invoked.
      *<p>
      * The default, 0, means invoke onCellInfoChanged when any of the reported
      * information changes. Setting the value to INT_MAX(0x7fffffff) means never issue
@@ -11364,7 +11364,7 @@
      * Shut down all the live radios over all the slot indexes.
      *
      * <p>To know when the radio has completed powering off, use
-     * {@link PhoneStateListener#LISTEN_SERVICE_STATE LISTEN_SERVICE_STATE}.
+     * {@link TelephonyCallback.ServiceStateListener}.
      *
      * @throws UnsupportedOperationException If the device does not have
      *          {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
@@ -13058,8 +13058,9 @@
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
      * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
      *
-     * If you want continuous updates of service state info, register a {@link PhoneStateListener}
-     * via {@link #listen} with the {@link PhoneStateListener#LISTEN_SERVICE_STATE} event.
+     * If you want continuous updates of service state info, register a {@link TelephonyCallback}
+     * that implements {@link TelephonyCallback.ServiceStateListener} through {@link
+     * #registerTelephonyCallback}.
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
@@ -13086,8 +13087,9 @@
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
      * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
      *
-     * If you want continuous updates of service state info, register a {@link PhoneStateListener}
-     * via {@link #listen} with the {@link PhoneStateListener#LISTEN_SERVICE_STATE} event.
+     * If you want continuous updates of service state info, register a {@link TelephonyCallback}
+     * that implements {@link TelephonyCallback.ServiceStateListener} through {@link
+     * #registerTelephonyCallback}.
      *
      * There's another way to renounce permissions with a custom context
      * {@code AttributionSource.Builder#setRenouncedPermissions(Set<String>)} but only for system
@@ -17892,9 +17894,9 @@
      * measurements breach the specified thresholds.
      *
      * To be notified, set the signal strength update request and then register
-     * {@link TelephonyManager#listen(PhoneStateListener, int)} with
-     * {@link PhoneStateListener#LISTEN_SIGNAL_STRENGTHS}. The notification will arrive through
-     * {@link PhoneStateListener#onSignalStrengthsChanged(SignalStrength)}.
+     * {@link TelephonyCallback} that implements {@link TelephonyCallback.SignalStrengthsListener}
+     * through {@link #registerTelephonyCallback}. The notification will arrive through
+     * {@link TelephonyCallback.SignalStrengthsListener#onSignalStrengthsChanged(SignalStrength)}.
      *
      * To stop receiving the notification over the specified thresholds, pass the same
      * {@link SignalStrengthUpdateRequest} object to
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index ebabbf9..ca4a643 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -1039,17 +1039,18 @@
      * subscription on the
      * current eUICC and the subscription to be downloaded according to the subscription metadata.
      * Without the former, an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be
-     * eturned in the callback intent to prompt the user to accept the download.
+     * returned in the callback intent to prompt the user to accept the download.
      *
      * <p> Starting from Android {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM},
      * if the caller has the
      * {@code android.Manifest.permission#MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS} permission or
-     * is a profile owner or device owner, and
-     * {@code switchAfterDownload} is {@code false}, then the downloaded subscription
-     * will be managed by that caller. If {@code switchAfterDownload} is true,
-     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be
-     * returned in the callback intent to prompt the user to accept the download and the
-     * subscription will not be managed.
+     * is a profile owner or device owner, then the downloaded subscription
+     * will be managed by that caller.
+     * In case the caller is device owner or profile owner of an organization-owned device, {@code
+     * switchAfterDownload} can be set to true to automatically enable the subscription after
+     * download. If the caller is a profile owner on non organization owned device
+     * {@code switchAfterDownload} should be false otherwise the operation will fail with
+     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_ERROR}.
      *
      * <p>On a multi-active SIM device, requires the
      * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
diff --git a/telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl
index 06fc3c6..579fda3 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl
@@ -26,11 +26,13 @@
     /**
      * Called when satellite datagram send state changed.
      *
+     * @param datagramType The datagram type of currently being sent.
      * @param state The new send datagram transfer state.
      * @param sendPendingCount The number of datagrams that are currently being sent.
      * @param errorCode If datagram transfer failed, the reason for failure.
      */
-    void onSendDatagramStateChanged(in int state, in int sendPendingCount, in int errorCode);
+    void onSendDatagramStateChanged(int datagramType, int state, int sendPendingCount,
+            int errorCode);
 
     /**
      * Called when satellite datagram receive state changed.
@@ -39,7 +41,7 @@
      * @param receivePendingCount The number of datagrams that are currently pending to be received.
      * @param errorCode If datagram transfer failed, the reason for failure.
      */
-    void onReceiveDatagramStateChanged(in int state, in int receivePendingCount, in int errorCode);
+    void onReceiveDatagramStateChanged(int state, int receivePendingCount, int errorCode);
 
     /**
      * Called when the satellite position changed.
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 20b24b9..b005715 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -954,6 +954,11 @@
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
     public static final int SATELLITE_MODEM_STATE_CONNECTED = 7;
     /**
+     * The satellite modem is being powered on.
+     * @hide
+     */
+    public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8;
+    /**
      * 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.
      */
@@ -970,6 +975,7 @@
             SATELLITE_MODEM_STATE_UNAVAILABLE,
             SATELLITE_MODEM_STATE_NOT_CONNECTED,
             SATELLITE_MODEM_STATE_CONNECTED,
+            SATELLITE_MODEM_STATE_ENABLING_SATELLITE,
             SATELLITE_MODEM_STATE_UNKNOWN
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -992,12 +998,19 @@
      */
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
     public static final int DATAGRAM_TYPE_LOCATION_SHARING = 2;
+    /**
+     * This type of datagram is used to keep the device in satellite connected state or check if
+     * there is any incoming message.
+     * @hide
+     */
+    public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3;
 
     /** @hide */
     @IntDef(prefix = "DATAGRAM_TYPE_", value = {
             DATAGRAM_TYPE_UNKNOWN,
             DATAGRAM_TYPE_SOS_MESSAGE,
-            DATAGRAM_TYPE_LOCATION_SHARING
+            DATAGRAM_TYPE_LOCATION_SHARING,
+            DATAGRAM_TYPE_KEEP_ALIVE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DatagramType {}
@@ -1077,8 +1090,13 @@
                             }
 
                             @Override
-                            public void onSendDatagramStateChanged(int state, int sendPendingCount,
-                                    int errorCode) {
+                            public void onSendDatagramStateChanged(int datagramType, int state,
+                                    int sendPendingCount, int errorCode) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSendDatagramStateChanged(datagramType,
+                                                state, sendPendingCount, errorCode)));
+
+                                // For backward compatibility
                                 executor.execute(() -> Binder.withCleanCallingIdentity(
                                         () -> callback.onSendDatagramStateChanged(
                                                 state, sendPendingCount, errorCode)));
diff --git a/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
index e020970..d8bd662 100644
--- a/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
@@ -52,6 +52,19 @@
             @SatelliteManager.SatelliteResult int errorCode);
 
     /**
+     * Called when satellite datagram send state changed.
+     *
+     * @param datagramType The datagram type of currently being sent.
+     * @param state The new send datagram transfer state.
+     * @param sendPendingCount The number of datagrams that are currently being sent.
+     * @param errorCode If datagram transfer failed, the reason for failure.
+     *
+     * @hide
+     */
+    void onSendDatagramStateChanged(@SatelliteManager.DatagramType int datagramType,
+            @SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
+            @SatelliteManager.SatelliteResult int errorCode);
+    /**
      * Called when satellite datagram receive state changed.
      *
      * @param state The new receive datagram transfer state.
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6678f40..1bfec29 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -309,6 +309,18 @@
      */
     int setUsageSetting(int usageSetting, int subId, String callingPackage);
 
+    /**
+      * Set owner for this subscription.
+      *
+      * @param subId the unique SubscriptionInfo index in database
+      * @param groupOwner The group owner to assign to the subscription
+      *
+      * @throws SecurityException if caller is not authorized.
+      *
+      * @hide
+      */
+     void setGroupOwner(int subId, String groupOwner);
+
      /**
       * Set userHandle for this subscription.
       *
diff --git a/test-runner/tests/Android.bp b/test-runner/tests/Android.bp
index aad2bee..0c0c080 100644
--- a/test-runner/tests/Android.bp
+++ b/test-runner/tests/Android.bp
@@ -33,7 +33,10 @@
         "android.test.base",
         "android.test.mock",
     ],
-    static_libs: ["junit"],
+    static_libs: [
+        "junit",
+        "androidx.test.rules",
+    ],
 
     // Include all test java files.
     srcs: ["src/**/*.java"],
diff --git a/test-runner/tests/src/android/test/AndroidTestRunnerTest.java b/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
index bd6c04bc..9b7ea59 100644
--- a/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
+++ b/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
@@ -17,7 +17,8 @@
 package android.test;
 
 import android.test.mock.MockContext;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
diff --git a/test-runner/tests/src/android/test/InstrumentationTestRunnerTest.java b/test-runner/tests/src/android/test/InstrumentationTestRunnerTest.java
index d98b217..0929e8b 100644
--- a/test-runner/tests/src/android/test/InstrumentationTestRunnerTest.java
+++ b/test-runner/tests/src/android/test/InstrumentationTestRunnerTest.java
@@ -22,7 +22,8 @@
 import android.test.mock.MockContext;
 import android.test.suitebuilder.ListTestCaseNames;
 import android.test.suitebuilder.ListTestCaseNames.TestDescriptor;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
diff --git a/test-runner/tests/src/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java b/test-runner/tests/src/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java
index 3ca0f70..f48443d 100644
--- a/test-runner/tests/src/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java
+++ b/test-runner/tests/src/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java
@@ -16,7 +16,7 @@
 
 package android.test.suitebuilder.examples.suppress;
 
-import android.test.suitebuilder.annotation.Suppress;
+import androidx.test.filters.Suppress;
 
 import junit.framework.TestCase;
 
diff --git a/test-runner/tests/src/android/test/suitebuilder/examples/suppress/SuppressedTest.java b/test-runner/tests/src/android/test/suitebuilder/examples/suppress/SuppressedTest.java
index c4e0e07..c85238c 100644
--- a/test-runner/tests/src/android/test/suitebuilder/examples/suppress/SuppressedTest.java
+++ b/test-runner/tests/src/android/test/suitebuilder/examples/suppress/SuppressedTest.java
@@ -16,7 +16,7 @@
 
 package android.test.suitebuilder.examples.suppress;
 
-import android.test.suitebuilder.annotation.Suppress;
+import androidx.test.filters.Suppress;
 
 import junit.framework.TestCase;
 
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java
index 5d6a4a3..1c78e5b 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/OomAdjPerfTest.java
@@ -90,6 +90,9 @@
         TargetPackageUtils.startStubPackage(mContext, STUB_PACKAGE1_NAME);
         TargetPackageUtils.startStubPackage(mContext, STUB_PACKAGE2_NAME);
         TargetPackageUtils.startStubPackage(mContext, STUB_PACKAGE3_NAME);
+
+        Utils.wakeUp();
+        Utils.runShellCommand("wm dismiss-keyguard");
     }
 
     @After
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
index d7f4d9d..705fe29 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
@@ -175,6 +175,7 @@
             context.startService(intent);
             Assert.assertTrue("Timeout when waiting for starting package " +  pkgName,
                     pair.second.await(AWAIT_SERVICE_CONNECT_MS, TimeUnit.MILLISECONDS));
+            Utils.runShellCommand("am unfreeze --sticky " + pkgName);
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
index 9bd94f2..421ae57d 100644
--- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
@@ -66,4 +66,15 @@
         ResultReceiver resultReceiver = intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER);
         resultReceiver.send(0, null);
     }
+
+    /**
+     * Wake up the device.
+     */
+    public static void wakeUp() {
+        try {
+            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).wakeUp();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/tests/ChoreographerTests/Android.bp b/tests/ChoreographerTests/Android.bp
index 5d49120..3f48d70 100644
--- a/tests/ChoreographerTests/Android.bp
+++ b/tests/ChoreographerTests/Android.bp
@@ -19,6 +19,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_android_core_graphics_stack",
 }
 
 android_test {
diff --git a/tests/CompanionDeviceMultiDeviceTests/client/Android.bp b/tests/CompanionDeviceMultiDeviceTests/client/Android.bp
index 1e68c9d..9994826 100644
--- a/tests/CompanionDeviceMultiDeviceTests/client/Android.bp
+++ b/tests/CompanionDeviceMultiDeviceTests/client/Android.bp
@@ -19,10 +19,11 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_framework_cdm",
 }
 
 android_test {
-    name: "cdm_snippet",
+    name: "cdm_snippet_legacy",
     srcs: ["src/**/*.kt"],
     manifest: "AndroidManifest.xml",
 
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/Android.bp b/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
index 03335c7..37cb850 100644
--- a/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
+++ b/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
@@ -19,6 +19,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_framework_cdm",
 }
 
 python_test_host {
@@ -36,7 +37,7 @@
         tags: ["mobly"],
     },
     data: [
-        ":cdm_snippet",
+        ":cdm_snippet_legacy",
     ],
     version: {
         py2: {
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml b/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
index 9d1813f..7c7ef63 100644
--- a/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
+++ b/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
@@ -24,12 +24,12 @@
 
     <device name="device1">
         <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-            <option name="test-file-name" value="cdm_snippet.apk" />
+            <option name="test-file-name" value="cdm_snippet_legacy.apk" />
         </target_preparer>
     </device>
     <device name="device2">
         <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-            <option name="test-file-name" value="cdm_snippet.apk" />
+            <option name="test-file-name" value="cdm_snippet_legacy.apk" />
         </target_preparer>
     </device>
 
diff --git a/tests/CtsSurfaceControlTestsStaging/Android.bp b/tests/CtsSurfaceControlTestsStaging/Android.bp
index 96e4a9e..1038c9e 100644
--- a/tests/CtsSurfaceControlTestsStaging/Android.bp
+++ b/tests/CtsSurfaceControlTestsStaging/Android.bp
@@ -19,6 +19,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_android_core_graphics_stack",
 }
 
 android_test {
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
index 46ad77e..519b429 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding.close
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -122,7 +122,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
         /**
          * Creates the test configurations.
          *
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt
index af4f7a7..4cd6d15b 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding.layoutchange
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -114,11 +114,11 @@
             // Compare dimensions of two splits, given we're using default split attributes,
             // both activities take up the same visible size on the display.
             check { "height" }
-                .that(topLayerRegion.region.height)
-                .isEqual(bottomLayerRegion.region.height)
+                .that(topLayerRegion.region.bounds.height())
+                .isEqual(bottomLayerRegion.region.bounds.height())
             check { "width" }
-                .that(topLayerRegion.region.width)
-                .isEqual(bottomLayerRegion.region.width)
+                .that(topLayerRegion.region.bounds.width())
+                .isEqual(bottomLayerRegion.region.bounds.width())
             topLayerRegion.notOverlaps(bottomLayerRegion.region)
             // Layers of two activities sum to be fullscreen size on display.
             topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
@@ -132,14 +132,17 @@
             // Compare dimensions of two splits, given we're using default split attributes,
             // both activities take up the same visible size on the display.
             check { "height" }
-                .that(topLayerRegion.region.height)
-                .isLower(bottomLayerRegion.region.height)
+                .that(topLayerRegion.region.bounds.height())
+                .isLower(bottomLayerRegion.region.bounds.height())
             check { "height" }
-                .that(topLayerRegion.region.height / 0.3f - bottomLayerRegion.region.height / 0.7f)
+                .that(
+                    topLayerRegion.region.bounds.height() / 0.3f -
+                        bottomLayerRegion.region.bounds.height() / 0.7f
+                )
                 .isLower(0.1f)
             check { "width" }
-                .that(topLayerRegion.region.width)
-                .isEqual(bottomLayerRegion.region.width)
+                .that(topLayerRegion.region.bounds.width())
+                .isEqual(bottomLayerRegion.region.bounds.width())
             topLayerRegion.notOverlaps(bottomLayerRegion.region)
             // Layers of two activities sum to be fullscreen size on display.
             topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
@@ -148,7 +151,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
index e511b72..5df8b572 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding.open
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -132,7 +132,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
index 4352177..78004cc 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding.open
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -143,7 +143,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
         /**
          * Creates the test configurations.
          *
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt
index 62cf6cd..cf4edd5 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding.open
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -156,11 +156,11 @@
                             it.timestamp
                         )
                     check { "height" }
-                        .that(mainActivityRegion.region.height)
-                        .isEqual(secondaryActivityRegion.region.height)
+                        .that(mainActivityRegion.region.bounds.height())
+                        .isEqual(secondaryActivityRegion.region.bounds.height())
                     check { "width" }
-                        .that(mainActivityRegion.region.width)
-                        .isEqual(secondaryActivityRegion.region.width)
+                        .that(mainActivityRegion.region.bounds.width())
+                        .isEqual(secondaryActivityRegion.region.bounds.width())
                     mainActivityRegion
                         .plus(secondaryActivityRegion.region)
                         .coversExactly(startDisplayBounds)
@@ -192,11 +192,11 @@
             // Compare dimensions of two splits, given we're using default split attributes,
             // both activities take up the same visible size on the display.
             check { "height" }
-                .that(leftLayerRegion.region.height)
-                .isEqual(rightLayerRegion.region.height)
+                .that(leftLayerRegion.region.bounds.height())
+                .isEqual(rightLayerRegion.region.bounds.height())
             check { "width" }
-                .that(leftLayerRegion.region.width)
-                .isEqual(rightLayerRegion.region.width)
+                .that(leftLayerRegion.region.bounds.width())
+                .isEqual(rightLayerRegion.region.bounds.width())
             leftLayerRegion.notOverlaps(rightLayerRegion.region)
             // Layers of two activities sum to be fullscreen size on display.
             leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds)
@@ -211,7 +211,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
index aa8b4ce..bc3696b 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding.pip
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -79,11 +79,11 @@
             // Compare dimensions of two splits, given we're using default split attributes,
             // both activities take up the same visible size on the display.
             check { "height" }
-                .that(leftLayerRegion.region.height)
-                .isEqual(rightLayerRegion.region.height)
+                .that(leftLayerRegion.region.bounds.height())
+                .isEqual(rightLayerRegion.region.bounds.height())
             check { "width" }
-                .that(leftLayerRegion.region.width)
-                .isEqual(rightLayerRegion.region.width)
+                .that(leftLayerRegion.region.bounds.width())
+                .isEqual(rightLayerRegion.region.bounds.width())
             leftLayerRegion.notOverlaps(rightLayerRegion.region)
             leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds)
         }
@@ -136,9 +136,11 @@
             val pipWindowRegion =
                 visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
             check { "height" }
-                .that(pipWindowRegion.region.height)
-                .isLower(startDisplayBounds.height / 2)
-            check { "width" }.that(pipWindowRegion.region.width).isLower(startDisplayBounds.width)
+                .that(pipWindowRegion.region.bounds.height())
+                .isLower(startDisplayBounds.height() / 2)
+            check { "width" }
+                .that(pipWindowRegion.region.bounds.width())
+                .isLower(startDisplayBounds.width())
         }
     }
 
@@ -151,7 +153,7 @@
                 ComponentNameMatcher.PIP_CONTENT_OVERLAY.layerMatchesAnyOf(it) && it.isVisible
             }
             pipLayerList.zipWithNext { previous, current ->
-                if (startDisplayBounds.width > startDisplayBounds.height) {
+                if (startDisplayBounds.width() > startDisplayBounds.height()) {
                     // Only verify when the display is landscape, because otherwise the final pip
                     // window can be to the left of the original secondary activity.
                     current.screenBounds.isToTheRightBottom(previous.screenBounds.region, 3)
@@ -162,8 +164,12 @@
         }
         flicker.assertLayersEnd {
             val pipRegion = visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
-            check { "height" }.that(pipRegion.region.height).isLower(startDisplayBounds.height / 2)
-            check { "width" }.that(pipRegion.region.width).isLower(startDisplayBounds.width)
+            check { "height" }
+                .that(pipRegion.region.bounds.height())
+                .isLower(startDisplayBounds.height() / 2)
+            check { "width" }
+                .that(pipRegion.region.bounds.width())
+                .isLower(startDisplayBounds.width())
         }
     }
 
@@ -175,7 +181,7 @@
             invoke("secondaryLayerNotJumpToLeft") {
                 val secondaryVisibleRegion =
                     it.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
-                if (secondaryVisibleRegion.region.isNotEmpty) {
+                if (!secondaryVisibleRegion.region.isEmpty) {
                     check { "left" }.that(secondaryVisibleRegion.region.bounds.left).isGreater(0)
                 }
             }
@@ -222,7 +228,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
         /**
          * Creates the test configurations.
          *
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
index 3d834c1..f5e6c78 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
@@ -85,11 +85,11 @@
                 // Compare dimensions of two splits, given we're using default split attributes,
                 // both activities take up the same visible size on the display.
                 check { "height" }
-                    .that(leftLayerRegion.region.height)
-                    .isEqual(rightLayerRegion.region.height)
+                    .that(leftLayerRegion.region.bounds.height())
+                    .isEqual(rightLayerRegion.region.bounds.height())
                 check { "width" }
-                    .that(leftLayerRegion.region.width)
-                    .isEqual(rightLayerRegion.region.width)
+                    .that(leftLayerRegion.region.bounds.width())
+                    .isEqual(rightLayerRegion.region.bounds.width())
                 leftLayerRegion.notOverlaps(rightLayerRegion.region)
                 // Layers of two activities sum to be fullscreen size on display.
                 leftLayerRegion.plus(rightLayerRegion.region).coversExactly(display.layerStackSpace)
@@ -108,11 +108,11 @@
                 val rightLayerRegion =
                     this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
                 check { "height" }
-                    .that(leftLayerRegion.region.height)
-                    .isEqual(rightLayerRegion.region.height)
+                    .that(leftLayerRegion.region.bounds.height())
+                    .isEqual(rightLayerRegion.region.bounds.height())
                 check { "width" }
-                    .that(leftLayerRegion.region.width)
-                    .isEqual(rightLayerRegion.region.width)
+                    .that(leftLayerRegion.region.bounds.width())
+                    .isEqual(rightLayerRegion.region.bounds.width())
                 leftLayerRegion.notOverlaps(rightLayerRegion.region)
                 leftLayerRegion.plus(rightLayerRegion.region).coversExactly(display.layerStackSpace)
             }
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
index 511c948..ee2c05e 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
@@ -16,9 +16,13 @@
 
 package com.android.server.wm.flicker.activityembedding.rotation
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
+import android.tools.Position
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.Condition
+import android.tools.traces.DeviceStateDump
 import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase
 import com.android.server.wm.flicker.helpers.setRotation
@@ -30,7 +34,14 @@
     override val transition: FlickerBuilder.() -> Unit = {
         setup { this.setRotation(flicker.scenario.startRotation) }
         teardown { testApp.exit(wmHelper) }
-        transitions { this.setRotation(flicker.scenario.endRotation) }
+        transitions {
+            this.setRotation(flicker.scenario.endRotation)
+            if (!flicker.scenario.isTablet) {
+                wmHelper.StateSyncBuilder()
+                    .add(navBarInPosition(flicker.scenario.isGesturalNavigation))
+                    .waitForAndVerify()
+            }
+        }
     }
 
     /** {@inheritDoc} */
@@ -76,4 +87,37 @@
         appLayerRotates_StartingPos()
         appLayerRotates_EndingPos()
     }
+
+    private fun navBarInPosition(isGesturalNavigation: Boolean): Condition<DeviceStateDump> {
+        return Condition("navBarPosition") { dump ->
+            val display =
+                dump.layerState.displays.filterNot { it.isOff }.minByOrNull { it.id }
+                    ?: error("There is no display!")
+            val displayArea = display.layerStackSpace
+            val navBarPosition = display.navBarPosition(isGesturalNavigation)
+            val navBarRegion = dump.layerState
+                .getLayerWithBuffer(ComponentNameMatcher.NAV_BAR)
+                ?.visibleRegion?.bounds ?: Rect()
+
+            when (navBarPosition) {
+                Position.TOP ->
+                    navBarRegion.top == displayArea.top &&
+                        navBarRegion.left == displayArea.left &&
+                        navBarRegion.right == displayArea.right
+                Position.BOTTOM ->
+                    navBarRegion.bottom == displayArea.bottom &&
+                        navBarRegion.left == displayArea.left &&
+                        navBarRegion.right == displayArea.right
+                Position.LEFT ->
+                    navBarRegion.left == displayArea.left &&
+                        navBarRegion.top == displayArea.top &&
+                        navBarRegion.bottom == displayArea.bottom
+                Position.RIGHT ->
+                    navBarRegion.right == displayArea.right &&
+                        navBarRegion.top == displayArea.top &&
+                        navBarRegion.bottom == displayArea.bottom
+                else -> error("Unknown position $navBarPosition")
+            }
+        }
+    }
 }
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
index 7298e5f..fb92583 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.server.wm.flicker.activityembedding.splitscreen
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
 import android.platform.test.annotations.RequiresDevice
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -32,6 +32,7 @@
 import com.android.wm.shell.flicker.utils.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.utils.splitAppLayerBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.utils.splitScreenDividerBecomesVisible
+import kotlin.math.abs
 import org.junit.FixMethodOrder
 import org.junit.Ignore
 import org.junit.Test
@@ -135,19 +136,25 @@
                 .plus(systemDivider.region)
                 .coversExactly(startDisplayBounds)
             check { "ActivityEmbeddingSplitHeight" }
-                .that(leftAELayerRegion.region.height)
-                .isEqual(rightAELayerRegion.region.height)
+                .that(leftAELayerRegion.region.bounds.height())
+                .isEqual(rightAELayerRegion.region.bounds.height())
             check { "SystemSplitHeight" }
-                .that(rightAELayerRegion.region.height)
-                .isEqual(secondaryAppLayerRegion.region.height)
+                .that(rightAELayerRegion.region.bounds.height())
+                .isEqual(secondaryAppLayerRegion.region.bounds.height())
             // TODO(b/292283182): Remove this special case handling.
             check { "ActivityEmbeddingSplitWidth" }
-                .that(Math.abs(leftAELayerRegion.region.width - rightAELayerRegion.region.width))
+                .that(
+                    abs(
+                        leftAELayerRegion.region.bounds.width() -
+                            rightAELayerRegion.region.bounds.width()
+                    )
+                )
                 .isLower(2)
             check { "SystemSplitWidth" }
                 .that(
-                    Math.abs(
-                        secondaryAppLayerRegion.region.width - 2 * rightAELayerRegion.region.width
+                    abs(
+                        secondaryAppLayerRegion.region.bounds.width() -
+                            2 * rightAELayerRegion.region.bounds.width()
                     )
                 )
                 .isLower(2)
@@ -167,18 +174,24 @@
             val secondaryAppLayerRegion =
                 visibleRegion(ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent())
             check { "ActivityEmbeddingSplitHeight" }
-                .that(leftAEWindowRegion.region.height)
-                .isEqual(rightAEWindowRegion.region.height)
+                .that(leftAEWindowRegion.region.bounds.height())
+                .isEqual(rightAEWindowRegion.region.bounds.height())
             check { "SystemSplitHeight" }
-                .that(rightAEWindowRegion.region.height)
-                .isEqual(secondaryAppLayerRegion.region.height)
+                .that(rightAEWindowRegion.region.bounds.height())
+                .isEqual(secondaryAppLayerRegion.region.bounds.height())
             check { "ActivityEmbeddingSplitWidth" }
-                .that(Math.abs(leftAEWindowRegion.region.width - rightAEWindowRegion.region.width))
+                .that(
+                    abs(
+                        leftAEWindowRegion.region.bounds.width() -
+                            rightAEWindowRegion.region.bounds.width()
+                    )
+                )
                 .isLower(2)
             check { "SystemSplitWidth" }
                 .that(
-                    Math.abs(
-                        secondaryAppLayerRegion.region.width - 2 * rightAEWindowRegion.region.width
+                    abs(
+                        secondaryAppLayerRegion.region.bounds.width() -
+                            2 * rightAEWindowRegion.region.bounds.width()
                     )
                 )
                 .isLower(2)
@@ -190,7 +203,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
         /**
          * Creates the test configurations.
          *
diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index b1d78cb..a71599d 100644
--- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -19,8 +19,9 @@
 import android.app.Instrumentation
 import android.app.WallpaperManager
 import android.content.res.Resources
+import android.graphics.Rect
+import android.graphics.Region
 import android.platform.test.annotations.Presubmit
-import android.tools.datatypes.Region
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -213,6 +214,12 @@
 
         private fun LayersTraceSubject.visibleRegionCovers(
             component: IComponentMatcher,
+            expectedArea: Rect,
+            isOptional: Boolean = true
+        ): LayersTraceSubject = visibleRegionCovers(component, Region(expectedArea), isOptional)
+
+        private fun LayersTraceSubject.visibleRegionCovers(
+            component: IComponentMatcher,
             expectedArea: Region,
             isOptional: Boolean = true
         ): LayersTraceSubject =
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index 7e486ab..da8368f 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -83,11 +83,12 @@
                     }
                 if (imeSnapshotLayers.isNotEmpty()) {
                     val visibleAreas =
-                        imeSnapshotLayers
-                            .mapNotNull { imeSnapshotLayer -> imeSnapshotLayer.layer.visibleRegion }
+                        imeSnapshotLayers.mapNotNull { imeSnapshotLayer ->
+                            imeSnapshotLayer.layer.visibleRegion
+                        }
                     val imeVisibleRegion = RegionSubject(visibleAreas, timestamp)
                     val appVisibleRegion = it.visibleRegion(imeTestApp)
-                    if (imeVisibleRegion.region.isNotEmpty) {
+                    if (!imeVisibleRegion.region.isEmpty) {
                         imeVisibleRegion.coversAtMost(appVisibleRegion.region)
                     }
                 }
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
index e8249bc..48ec4d1f 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
@@ -115,7 +115,10 @@
                 .isEqual(true)
 
             imeLayerSubjects.forEach { imeLayerSubject ->
-                imeLayerSubject.check { "alpha" }.that(imeLayerSubject.layer.color.a).isEqual(1.0f)
+                imeLayerSubject
+                    .check { "alpha" }
+                    .that(imeLayerSubject.layer.color.alpha())
+                    .isEqual(1.0f)
             }
         }
     }
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index 617237d..063088d 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -50,7 +50,10 @@
             testApp.launchViaIntent(wmHelper)
             testApp.openIME(wmHelper)
             this.setRotation(flicker.scenario.startRotation)
-            device.pressRecentApps()
+            if (flicker.scenario.isTablet) {
+                tapl.launchedAppState.swipeUpToUnstashTaskbar()
+            }
+            tapl.launchedAppState.switchToOverview()
             wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
         }
         transitions {
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index a14dc62..7aa525f 100644
--- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -191,7 +191,7 @@
             this.invoke("imeLayerIsVisibleAndAlignAppWidow") {
                 val imeVisibleRegion = it.visibleRegion(ComponentNameMatcher.IME)
                 val appVisibleRegion = it.visibleRegion(imeTestApp)
-                if (imeVisibleRegion.region.isNotEmpty) {
+                if (!imeVisibleRegion.region.isEmpty) {
                     it.isVisible(ComponentNameMatcher.IME)
                     imeVisibleRegion.coversAtMost(appVisibleRegion.region)
                 }
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
index 8e210d4..f1df8a6 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
@@ -123,7 +123,9 @@
     @Test
     override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
 
-    @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+    @FlakyTest(bugId = 227143265)
+    @Test
+    override fun entireScreenCovered() = super.entireScreenCovered()
 
     @FlakyTest(bugId = 278227468)
     @Test
diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 8b09b59..9bb62e1 100644
--- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.server.wm.flicker.quickswitch
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
 import android.tools.NavBar
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -237,7 +237,7 @@
     override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
 
     companion object {
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index c54ddcf..491b994 100644
--- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.quickswitch
 
+import android.graphics.Rect
 import android.tools.NavBar
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -285,7 +285,7 @@
         super.visibleWindowsShownMoreThanOneConsecutiveEntry()
 
     companion object {
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index 69a84a0..de54c95 100644
--- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -16,10 +16,10 @@
 
 package com.android.server.wm.flicker.quickswitch
 
+import android.graphics.Rect
 import android.platform.test.annotations.Presubmit
 import android.tools.NavBar
 import android.tools.Rotation
-import android.tools.datatypes.Rect
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
@@ -266,7 +266,7 @@
 
     companion object {
         /** {@inheritDoc} */
-        private var startDisplayBounds = Rect.EMPTY
+        private var startDisplayBounds = Rect()
 
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
diff --git a/tests/FlickerTests/README.md b/tests/FlickerTests/README.md
index 6b28fdf..7429250 100644
--- a/tests/FlickerTests/README.md
+++ b/tests/FlickerTests/README.md
@@ -7,82 +7,17 @@
 
 ## Adding a Test
 
-By default tests should inherit from `RotationTestBase` or `NonRotationTestBase` and must override the variable `transitionToRun` (Kotlin) or the function `getTransitionToRun()` (Java).
-Only tests that are not supported by these classes should inherit directly from the `FlickerTestBase` class.
+By default, tests should inherit from `TestBase` and override the variable `transition` (Kotlin) or the function `getTransition()` (Java).
 
-### Rotation animations and transitions
+Inheriting from this class ensures the common assertions will be executed, namely:
 
-Tests that rotate the device should inherit from `RotationTestBase`.
-Tests that inherit from the class automatically receive start and end rotation values.  
-Moreover, these tests inherit the following checks:
 * all regions on the screen are covered
 * status bar is always visible
-* status bar rotates
+* status bar is at the correct position at the start and end of the transition
 * nav bar is always visible
-* nav bar is rotates
+* nav bar is at the correct position at the start and end of the transition
 
 The default tests can be disabled by overriding the respective methods and including an `@Ignore` annotation.
 
-### Non-Rotation animations and transitions
+For more examples of how a test looks like check `ChangeAppRotationTest` within the `Rotation` subdirectory.
 
-`NonRotationTestBase` was created to make it easier to write tests that do not involve rotation (e.g., `Pip`, `split screen` or `IME`).
-Tests that inherit from the class are automatically executed twice: once in portrait and once in landscape mode and the assertions are checked independently.
-Moreover, these tests inherit the following checks:
-* all regions on the screen are covered
-* status bar is always visible
-* nav bar is always visible
-
-The default tests can be disabled by overriding the respective methods and including an `@Ignore` annotation.
-
-### Exceptional cases
-
-Tests that rotate the device should inherit from `RotationTestBase`.
-This class allows the test to be freely configured and does not provide any assertions.  
-
-
-### Example
-
-Start by defining common or error prone transitions using `TransitionRunner`.
-```kotlin
-@LargeTest
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class MyTest(
-    beginRotationName: String,
-    beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
-    init {
-        mTestApp = MyAppHelper(InstrumentationRegistry.getInstrumentation())
-    }
-
-    override val transitionToRun: TransitionRunner
-        get() = TransitionRunner.newBuilder()
-            .withTag("myTest")
-            .recordAllRuns()
-            .runBefore { device.pressHome() }
-            .runBefore { device.waitForIdle() }
-            .run { testApp.open() }
-            .runAfter{ testApp.exit() }
-            .repeat(2)
-            .includeJankyRuns()
-            .build()
-
-    @Test
-    fun myWMTest() {
-        checkResults {
-            WmTraceSubject.assertThat(it)
-                    .showsAppWindow(MyTestApp)
-                    .forAllEntries()
-        }
-    }
-
-    @Test
-    fun mySFTest() {
-        checkResults {
-            LayersTraceSubject.assertThat(it)
-                    .showsLayer(MyTestApp)
-                    .forAllEntries()
-        }
-    }
-}
-```
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 8853c1d..348d0af 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -279,12 +279,11 @@
                         subject.isVisible
                 }
             val visibleAreas =
-                snapshotLayers
-                    .mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
+                snapshotLayers.mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
             val snapshotRegion = RegionSubject(visibleAreas, it.timestamp)
             val appVisibleRegion = it.visibleRegion(component)
             // Verify the size of snapshotRegion covers appVisibleRegion exactly in animation.
-            if (snapshotRegion.region.isNotEmpty && appVisibleRegion.region.isNotEmpty) {
+            if (!snapshotRegion.region.isEmpty && !appVisibleRegion.region.isEmpty) {
                 snapshotRegion.coversExactly(appVisibleRegion.region)
             }
         }
diff --git a/tests/FlickerTests/test-apps/app-helpers/OWNERS b/tests/FlickerTests/test-apps/app-helpers/OWNERS
new file mode 100644
index 0000000..ab62532
--- /dev/null
+++ b/tests/FlickerTests/test-apps/app-helpers/OWNERS
@@ -0,0 +1,2 @@
[email protected]
[email protected]
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
new file mode 100644
index 0000000..461dfec
--- /dev/null
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.helpers
+
+import android.tools.device.apphelpers.IStandardAppHelper
+import android.tools.helpers.SYSTEMUI_PACKAGE
+import android.tools.traces.parsers.WindowManagerStateHelper
+import android.tools.traces.wm.WindowingMode
+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
+
+/**
+ * Wrapper class around App helper classes. This class adds functionality to the apps that the
+ * desktop apps would have.
+ */
+open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
+    IStandardAppHelper by innerHelper {
+    private val TIMEOUT_MS = 3_000L
+    private val CAPTION = "desktop_mode_caption"
+    private val CAPTION_HANDLE = "caption_handle"
+    private val MAXIMIZE_BUTTON = "maximize_window"
+    private val MAXIMIZE_BUTTON_VIEW = "maximize_button_view"
+    private val CLOSE_BUTTON = "close_window"
+
+    private val caption: BySelector
+        get() = By.res(SYSTEMUI_PACKAGE, CAPTION)
+
+    /** Wait for an app moved to desktop to finish its transition. */
+    private fun waitForAppToMoveToDesktop(wmHelper: WindowManagerStateHelper) {
+        wmHelper
+            .StateSyncBuilder()
+            .withWindowSurfaceAppeared(innerHelper)
+            .withFreeformApp(innerHelper)
+            .withAppTransitionIdle()
+            .waitForAndVerify()
+    }
+
+    /** Move an app to Desktop by dragging the app handle at the top. */
+    fun enterDesktopWithDrag(
+        wmHelper: WindowManagerStateHelper,
+        device: UiDevice,
+    ) {
+        innerHelper.launchViaIntent(wmHelper)
+        dragToDesktop(wmHelper, device)
+        waitForAppToMoveToDesktop(wmHelper)
+    }
+
+    private fun dragToDesktop(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+        val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
+        val startX = windowRect.centerX()
+
+        // Start dragging a little under the top to prevent dragging the notification shade.
+        val startY = 10
+
+        val displayRect =
+            wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
+                ?: throw IllegalStateException("Default display is null")
+
+        // The position we want to drag to
+        val endY = displayRect.centerY() / 2
+
+        // drag the window to move to desktop
+        device.drag(startX, startY, startX, endY, 100)
+    }
+
+    /** Click maximise button on the app header for the given app. */
+    fun maximiseDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+        val caption = getCaptionForTheApp(wmHelper, device)
+        val maximizeButton =
+            caption
+                ?.children
+                ?.find { it.resourceName.endsWith(MAXIMIZE_BUTTON_VIEW) }
+                ?.children
+                ?.get(0)
+        maximizeButton?.click()
+        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
+    }
+    /** Click close button on the app header for the given app. */
+    fun closeDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+        val caption = getCaptionForTheApp(wmHelper, device)
+        val closeButton = caption?.children?.find { it.resourceName.endsWith(CLOSE_BUTTON) }
+        closeButton?.click()
+        wmHelper
+            .StateSyncBuilder()
+            .withAppTransitionIdle()
+            .withWindowSurfaceDisappeared(innerHelper)
+            .waitForAndVerify()
+    }
+
+    private fun getCaptionForTheApp(
+        wmHelper: WindowManagerStateHelper,
+        device: UiDevice
+    ): UiObject2? {
+        if (
+            wmHelper.getWindow(innerHelper)?.windowingMode !=
+                WindowingMode.WINDOWING_MODE_FREEFORM.value
+        )
+            error("expected a freeform window with caption but window is not in freeform mode")
+        val captions =
+            device.wait(Until.findObjects(caption), TIMEOUT_MS)
+                ?: error("Unable to find view $caption\n")
+
+        return captions.find {
+            wmHelper.getWindowRegion(innerHelper).bounds.contains(it.visibleBounds)
+        }
+    }
+}
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index ffed408..ef8d84f 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -45,13 +45,7 @@
         require(gameView != null) { "Mock game app view not found." }
 
         val bound = gameView.getVisibleBounds()
-        return uiDevice.swipe(
-            bound.centerX(),
-            0,
-            bound.centerX(),
-            bound.centerY(),
-            SWIPE_STEPS
-        )
+        return uiDevice.swipe(bound.centerX(), 0, bound.centerX(), bound.centerY(), SWIPE_STEPS)
     }
 
     /**
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
index b09e53b..634b6ee 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
@@ -17,8 +17,8 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
-import android.tools.datatypes.Rect
-import android.tools.datatypes.Region
+import android.graphics.Rect
+import android.graphics.Region
 import android.tools.device.apphelpers.StandardAppHelper
 import android.tools.helpers.FIND_TIMEOUT
 import android.tools.helpers.SYSTEMUI_PACKAGE
@@ -86,7 +86,7 @@
             .add("letterboxAppRepositioned") {
                 val letterboxAppWindow = getWindowRegion(wmHelper)
                 val appRegionBounds = letterboxAppWindow.bounds
-                val appWidth = appRegionBounds.width
+                val appWidth = appRegionBounds.width()
                 return@add if (right)
                     appRegionBounds.left == displayBounds.right - appWidth &&
                         appRegionBounds.right == displayBounds.right
@@ -108,7 +108,7 @@
             .add("letterboxAppRepositioned") {
                 val letterboxAppWindow = getWindowRegion(wmHelper)
                 val appRegionBounds = letterboxAppWindow.bounds
-                val appHeight = appRegionBounds.height
+                val appHeight = appRegionBounds.height()
                 return@add if (bottom)
                     appRegionBounds.bottom == displayBounds.bottom &&
                         appRegionBounds.top == (displayBounds.bottom - appHeight + navBarHeight)
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index db933b3..43fd57b 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -18,10 +18,11 @@
 
 import android.app.Instrumentation
 import android.content.Intent
+import android.graphics.Rect
+import android.graphics.Region
 import android.media.session.MediaController
 import android.media.session.MediaSessionManager
-import android.tools.datatypes.Rect
-import android.tools.datatypes.Region
+import android.tools.datatypes.coversMoreThan
 import android.tools.device.apphelpers.StandardAppHelper
 import android.tools.helpers.FIND_TIMEOUT
 import android.tools.helpers.SYSTEMUI_PACKAGE
@@ -62,7 +63,7 @@
 
     /** Drags the PIP window to the provided final coordinates without releasing the pointer. */
     fun dragPipWindowAwayFromEdgeWithoutRelease(wmHelper: WindowManagerStateHelper, steps: Int) {
-        val initWindowRect = getWindowRect(wmHelper).clone()
+        val initWindowRect = Rect(getWindowRect(wmHelper))
 
         // initial pointer at the center of the window
         val initialCoord =
@@ -101,7 +102,7 @@
      * @throws IllegalStateException if default display bounds are not available
      */
     fun dragPipWindowAwayFromEdge(wmHelper: WindowManagerStateHelper, steps: Int) {
-        val initWindowRect = getWindowRect(wmHelper).clone()
+        val initWindowRect = Rect(getWindowRect(wmHelper))
 
         // initial pointer at the center of the window
         val startX = initWindowRect.centerX()
@@ -153,12 +154,12 @@
         val windowRect = getWindowRect(wmHelper)
 
         // first pointer's initial x coordinate is halfway between the left edge and the center
-        val initLeftX = (windowRect.centerX() - windowRect.width / 4).toFloat()
+        val initLeftX = (windowRect.centerX() - windowRect.width() / 4).toFloat()
         // second pointer's initial x coordinate is halfway between the right edge and the center
-        val initRightX = (windowRect.centerX() + windowRect.width / 4).toFloat()
+        val initRightX = (windowRect.centerX() + windowRect.width() / 4).toFloat()
 
         // horizontal distance the window should increase by
-        val distIncrease = windowRect.width * percent
+        val distIncrease = windowRect.width() * percent
 
         // final x-coordinates
         val finalLeftX = initLeftX - (distIncrease / 2)
@@ -183,7 +184,7 @@
             adjustedSteps
         )
 
-        waitForPipWindowToExpandFrom(wmHelper, Region.from(windowRect))
+        waitForPipWindowToExpandFrom(wmHelper, Region(windowRect))
     }
 
     /**
@@ -201,12 +202,12 @@
         val windowRect = getWindowRect(wmHelper)
 
         // first pointer's initial x coordinate is halfway between the left edge and the center
-        val initLeftX = (windowRect.centerX() - windowRect.width / 4).toFloat()
+        val initLeftX = (windowRect.centerX() - windowRect.width() / 4).toFloat()
         // second pointer's initial x coordinate is halfway between the right edge and the center
-        val initRightX = (windowRect.centerX() + windowRect.width / 4).toFloat()
+        val initRightX = (windowRect.centerX() + windowRect.width() / 4).toFloat()
 
         // decrease by the distance specified through the percentage
-        val distDecrease = windowRect.width * percent
+        val distDecrease = windowRect.width() * percent
 
         // get the final x-coordinates and make sure they are not passing the center of the window
         val finalLeftX = Math.min(initLeftX + (distDecrease / 2), windowRect.centerX().toFloat())
@@ -231,7 +232,7 @@
             adjustedSteps
         )
 
-        waitForPipWindowToMinimizeFrom(wmHelper, Region.from(windowRect))
+        waitForPipWindowToMinimizeFrom(wmHelper, Region(windowRect))
     }
 
     /**
@@ -375,7 +376,7 @@
         uiDevice.click(windowRect.centerX(), windowRect.centerY())
         Log.d(TAG, "Wait for app transition to end")
         wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
-        waitForPipWindowToExpandFrom(wmHelper, Region.from(windowRect))
+        waitForPipWindowToExpandFrom(wmHelper, Region(windowRect))
     }
 
     private fun waitForPipWindowToExpandFrom(
diff --git a/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java b/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
index 2ed4fec..c52be7c 100644
--- a/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
+++ b/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
@@ -27,6 +27,9 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.io.FileOutputStream;
@@ -46,6 +49,12 @@
 
     private static final long BLOCK_SIZE = 4096;
 
+    @Rule
+    public final AdoptShellPermissionsRule mAdoptShellPermissionsRule =
+            new AdoptShellPermissionsRule(
+                    InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+                    android.Manifest.permission.SETUP_FSVERITY);
+
     @Test
     public void prepareTest() throws Exception {
         Context context = ApplicationProvider.getApplicationContext();
diff --git a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index e60764f..93f97cb 100644
--- a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -33,7 +33,6 @@
 import android.os.Bundle
 import android.os.test.TestLooper
 import android.platform.test.annotations.Presubmit
-import android.provider.Settings
 import android.util.proto.ProtoOutputStream
 import android.view.InputDevice
 import android.view.inputmethod.InputMethodInfo
@@ -47,9 +46,7 @@
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotEquals
-import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
-import org.junit.Assert.assertThrows
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -234,631 +231,332 @@
     }
 
     @Test
-    fun testDefaultUi_getKeyboardLayouts() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
-            assertNotEquals(
-                "Default UI: Keyboard layout API should not return empty array",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue(
-                "Default UI: Keyboard layout API should provide English(US) layout",
-                hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-        }
+    fun testGetKeyboardLayouts() {
+        val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
+        assertNotEquals(
+            "Keyboard layout API should not return empty array",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue(
+            "Keyboard layout API should provide English(US) layout",
+            hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
     }
 
     @Test
-    fun testNewUi_getKeyboardLayouts() {
-        NewSettingsApiFlag(true).use {
-            val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
-            assertNotEquals(
-                "New UI: Keyboard layout API should not return empty array",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue(
-                "New UI: Keyboard layout API should provide English(US) layout",
-                hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-        }
+    fun testGetKeyboardLayout() {
+        val keyboardLayout =
+            keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
+        assertEquals("getKeyboardLayout API should return correct Layout from " +
+                "available layouts",
+            ENGLISH_US_LAYOUT_DESCRIPTOR,
+            keyboardLayout!!.descriptor
+        )
     }
 
     @Test
-    fun testDefaultUi_getKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutsForInputDevice(keyboardDevice.identifier)
-            assertNotEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should not return empty array",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue(
-                "Default UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
-                        "layout",
-                hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
+    fun testGetSetKeyboardLayoutForInputDevice_withImeInfo() {
+        val imeSubtype = createImeSubtype()
 
-            val vendorSpecificKeyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutsForInputDevice(
-                    vendorSpecificKeyboardDevice.identifier
-                )
-            assertEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should return only vendor " +
-                        "specific layout",
+        keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+            keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+            ENGLISH_UK_LAYOUT_DESCRIPTOR
+        )
+        var result =
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+            )
+        assertEquals(
+            "getKeyboardLayoutForInputDevice API should return the set layout",
+            ENGLISH_UK_LAYOUT_DESCRIPTOR,
+            result.layoutDescriptor
+        )
+
+        // This should replace previously set layout
+        keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+            keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        result =
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+            )
+        assertEquals(
+            "getKeyboardLayoutForInputDevice API should return the last set layout",
+            ENGLISH_US_LAYOUT_DESCRIPTOR,
+            result.layoutDescriptor
+        )
+    }
+
+    @Test
+    fun testGetKeyboardLayoutListForInputDevice() {
+        // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
+        var keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("hi-Latn")
+            )
+        assertNotEquals(
+            "getKeyboardLayoutListForInputDevice API should return the list of " +
+                    "supported layouts with matching script code",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(US) layout for hi-Latn",
+            containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(No script code) layout for hi-Latn",
+            containsLayout(
+                keyboardLayouts,
+                createLayoutDescriptor("keyboard_layout_english_without_script_code")
+            )
+        )
+
+        // Check Layouts for "hi" which by default uses 'Deva' script.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("hi")
+            )
+        assertEquals("getKeyboardLayoutListForInputDevice API should return empty " +
+                "list if no supported layouts available",
+            0,
+            keyboardLayouts.size
+        )
+
+        // If user manually selected some layout, always provide it in the layout list
+        val imeSubtype = createImeSubtypeForLanguageTag("hi")
+        keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+            keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                imeSubtype
+            )
+        assertEquals("getKeyboardLayoutListForInputDevice API should return user " +
+                "selected layout even if the script is incompatible with IME",
                 1,
-                vendorSpecificKeyboardLayouts.size
-            )
-            assertEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should return vendor specific " +
-                        "layout",
-                VENDOR_SPECIFIC_LAYOUT_DESCRIPTOR,
-                vendorSpecificKeyboardLayouts[0].descriptor
-            )
-        }
-    }
+            keyboardLayouts.size
+        )
 
-    @Test
-    fun testNewUi_getKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            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)
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getSetCurrentKeyboardLayoutForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            assertNull(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null if " +
-                        "nothing was set",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-
-            keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            val keyboardLayout =
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            assertEquals(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return the set " +
-                        "layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayout
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getSetCurrentKeyboardLayoutForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertNull(
-                "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null " +
-                        "even after setCurrentKeyboardLayoutForInputDevice",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getEnabledKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-
-            val keyboardLayouts =
-                keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
-                    keyboardDevice.identifier
-                )
-            assertEquals(
-                "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return added " +
-                        "layout",
-                1,
-                keyboardLayouts.size
-            )
-            assertEquals(
-                "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return " +
-                        "English(US) layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayouts[0]
-            )
-            assertEquals(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
-                        "English(US) layout (Auto select the first enabled layout)",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-
-            keyboardLayoutManager.removeKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should return 0 layouts",
-                0,
-                keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
-                    keyboardDevice.identifier
-                ).size
-            )
-            assertNull(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null after " +
-                        "the enabled layout is removed",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getEnabledKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-
-            assertEquals(
-                "New UI: getEnabledKeyboardLayoutsForInputDevice API should return always return " +
-                        "an empty array",
-                0,
-                keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
-                    keyboardDevice.identifier
-                ).size
-            )
-            assertNull(
-                "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_switchKeyboardLayout() {
-        NewSettingsApiFlag(false).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertEquals(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
-                        "English(US) layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-
-            keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
-
-            // Throws null pointer because trying to show toast using TestLooper
-            assertThrows(NullPointerException::class.java) { testLooper.dispatchAll() }
-            assertEquals("Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
-                    "English(UK) layout",
-                ENGLISH_UK_LAYOUT_DESCRIPTOR,
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_switchKeyboardLayout() {
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-
-            keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
-            testLooper.dispatchAll()
-
-            assertNull("New UI: getCurrentKeyboardLayoutForInputDevice API should always return " +
-                    "null",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getKeyboardLayout() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayout =
-                keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
-            assertEquals("Default UI: getKeyboardLayout API should return correct Layout from " +
-                    "available layouts",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayout!!.descriptor
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getKeyboardLayout() {
-        NewSettingsApiFlag(true).use {
-            val keyboardLayout =
-                keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
-            assertEquals("New UI: getKeyboardLayout API should return correct Layout from " +
-                    "available layouts",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayout!!.descriptor
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getSetKeyboardLayoutForInputDevice_WithImeInfo() {
-        NewSettingsApiFlag(false).use {
-            val imeSubtype = createImeSubtype()
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertEquals(
-                "Default UI: getKeyboardLayoutForInputDevice API should always return " +
-                        "KeyboardLayoutSelectionResult.FAILED",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getSetKeyboardLayoutForInputDevice_withImeInfo() {
-        NewSettingsApiFlag(true).use {
-            val imeSubtype = createImeSubtype()
-
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            var result =
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
-                )
-            assertEquals(
-                "New UI: getKeyboardLayoutForInputDevice API should return the set layout",
-                ENGLISH_UK_LAYOUT_DESCRIPTOR,
-                result.layoutDescriptor
-            )
-
-            // This should replace previously set layout
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            result =
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
-                )
-            assertEquals(
-                "New UI: getKeyboardLayoutForInputDevice API should return the last set layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                result.layoutDescriptor
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getKeyboardLayoutListForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+        // Special case Japanese: UScript ignores provided script code for certain language tags
+        // Should manually match provided script codes and then rely on Uscript to derive
+        // script from language tags and match those.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
                     keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtype()
-                )
-            assertEquals("Default UI: getKeyboardLayoutListForInputDevice API should always " +
-                    "return empty array",
-                0,
-                keyboardLayouts.size
+                    createImeSubtypeForLanguageTag("ja-Latn-JP")
             )
-        }
-    }
+        assertNotEquals(
+            "getKeyboardLayoutListForInputDevice API should return the list of " +
+                    "supported layouts with matching script code for ja-Latn-JP",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(US) layout for ja-Latn-JP",
+            containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(No script code) layout for ja-Latn-JP",
+            containsLayout(
+                keyboardLayouts,
+                createLayoutDescriptor("keyboard_layout_english_without_script_code")
+            )
+        )
 
-    @Test
-    fun testNewUi_getKeyboardLayoutListForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
-            var keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+        // If script code not explicitly provided for Japanese should rely on Uscript to find
+        // derived script code and hence no suitable layout will be found.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
                     keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("hi-Latn")
-                )
-            assertNotEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
-                        "supported layouts with matching script code",
-                0,
-                keyboardLayouts.size
+                    createImeSubtypeForLanguageTag("ja-JP")
             )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(US) layout for hi-Latn",
-                containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(No script code) layout for hi-Latn",
-                containsLayout(
-                    keyboardLayouts,
-                    createLayoutDescriptor("keyboard_layout_english_without_script_code")
-                )
-            )
+        assertEquals(
+            "getKeyboardLayoutListForInputDevice API should return empty list of " +
+                    "supported layouts with matching script code for ja-JP",
+            0,
+            keyboardLayouts.size
+        )
 
-            // Check Layouts for "hi" which by default uses 'Deva' script.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("hi")
-                )
-            assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return empty " +
-                    "list if no supported layouts available",
-                0,
-                keyboardLayouts.size
+        // If IME doesn't have a corresponding language tag, then should show all available
+        // layouts no matter the script code.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo, null
             )
-
-            // If user manually selected some layout, always provide it in the layout list
-            val imeSubtype = createImeSubtypeForLanguageTag("hi")
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    imeSubtype
-                )
-            assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return user " +
-                    "selected layout even if the script is incompatible with IME",
-                    1,
-                keyboardLayouts.size
-            )
-
-            // Special case Japanese: UScript ignores provided script code for certain language tags
-            // Should manually match provided script codes and then rely on Uscript to derive
-            // script from language tags and match those.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                        keyboardDevice.identifier, USER_ID, imeInfo,
-                        createImeSubtypeForLanguageTag("ja-Latn-JP")
-                )
-            assertNotEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
-                        "supported layouts with matching script code for ja-Latn-JP",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(US) layout for ja-Latn-JP",
-                containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(No script code) layout for ja-Latn-JP",
-                containsLayout(
-                    keyboardLayouts,
-                    createLayoutDescriptor("keyboard_layout_english_without_script_code")
-                )
-            )
-
-            // If script code not explicitly provided for Japanese should rely on Uscript to find
-            // derived script code and hence no suitable layout will be found.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                        keyboardDevice.identifier, USER_ID, imeInfo,
-                        createImeSubtypeForLanguageTag("ja-JP")
-                )
-            assertEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return empty list of " +
-                        "supported layouts with matching script code for ja-JP",
-                0,
-                keyboardLayouts.size
-            )
-
-            // If IME doesn't have a corresponding language tag, then should show all available
-            // layouts no matter the script code.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, null
-                )
-            assertNotEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return all layouts if" +
-                    "language tag or subtype not provided",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Latin " +
-                "layouts if language tag or subtype not provided",
-                containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
-                "layouts if language tag or subtype not provided",
-                containsLayout(
-                    keyboardLayouts,
-                    createLayoutDescriptor("keyboard_layout_russian")
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
-        NewSettingsApiFlag(true).use {
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("en-US"),
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("en-GB"),
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("de"),
-                GERMAN_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("fr-FR"),
-                createLayoutDescriptor("keyboard_layout_french")
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("ru"),
+        assertNotEquals(
+            "getKeyboardLayoutListForInputDevice API should return all layouts if" +
+                "language tag or subtype not provided",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should contain Latin " +
+            "layouts if language tag or subtype not provided",
+            containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
+            "layouts if language tag or subtype not provided",
+            containsLayout(
+                keyboardLayouts,
                 createLayoutDescriptor("keyboard_layout_russian")
             )
-            assertEquals(
-                "New UI: getDefaultKeyboardLayoutForInputDevice should return " +
-                        "KeyboardLayoutSelectionResult.FAILED when no layout available",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("it")
-                )
-            )
-            assertEquals(
-                "New UI: getDefaultKeyboardLayoutForInputDevice should return " +
-                        "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
-                        "available",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("en-Deva")
-                )
-            )
-        }
+        )
     }
 
     @Test
-    fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
-        NewSettingsApiFlag(true).use {
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
-                ENGLISH_US_LAYOUT_DESCRIPTOR
+    fun testGetDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("en-US"),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("en-GB"),
+            ENGLISH_UK_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("de"),
+            GERMAN_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("fr-FR"),
+            createLayoutDescriptor("keyboard_layout_french")
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("ru"),
+            createLayoutDescriptor("keyboard_layout_russian")
+        )
+        assertEquals(
+            "getDefaultKeyboardLayoutForInputDevice should return " +
+                    "KeyboardLayoutSelectionResult.FAILED when no layout available",
+            KeyboardLayoutSelectionResult.FAILED,
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("it")
             )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
-                createLayoutDescriptor("keyboard_layout_english_us_dvorak")
-            )
-            // Try to match layout type even if country doesn't match
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
-                createLayoutDescriptor("keyboard_layout_english_us_dvorak")
-            )
-            // Choose layout based on layout type priority, if layout type is not provided by IME
-            // (Qwerty > Dvorak > Extended)
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
-                GERMAN_LAYOUT_DESCRIPTOR
-            )
-            // Wrong layout type should match with language if provided layout type not available
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
-                GERMAN_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
-                createLayoutDescriptor("keyboard_layout_french")
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
-                createLayoutDescriptor("keyboard_layout_russian_qwerty")
-            )
-            // If layout type is empty then prioritize KCM with empty layout type
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
-                createLayoutDescriptor("keyboard_layout_russian")
-            )
-            assertEquals("New UI: getDefaultKeyboardLayoutForInputDevice should return " +
+        )
+        assertEquals(
+            "getDefaultKeyboardLayoutForInputDevice should return " +
                     "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
                     "available",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
-                )
+            KeyboardLayoutSelectionResult.FAILED,
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("en-Deva")
             )
-        }
+        )
     }
 
     @Test
-    fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
-        NewSettingsApiFlag(true).use {
-            val frenchSubtype = createImeSubtypeForLanguageTagAndLayoutType("fr", "azerty")
-            // Should return English dvorak even if IME current layout is French, since HW says the
-            // keyboard is a Dvorak keyboard
-            assertCorrectLayout(
-                englishDvorakKeyboardDevice,
-                frenchSubtype,
-                createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+    fun testGetDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
+            createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+        )
+        // Try to match layout type even if country doesn't match
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
+            createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+        )
+        // Choose layout based on layout type priority, if layout type is not provided by IME
+        // (Qwerty > Dvorak > Extended)
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
+            ENGLISH_UK_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
+            GERMAN_LAYOUT_DESCRIPTOR
+        )
+        // Wrong layout type should match with language if provided layout type not available
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
+            GERMAN_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
+            createLayoutDescriptor("keyboard_layout_french")
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
+            createLayoutDescriptor("keyboard_layout_russian_qwerty")
+        )
+        // If layout type is empty then prioritize KCM with empty layout type
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+            createLayoutDescriptor("keyboard_layout_russian")
+        )
+        assertEquals("getDefaultKeyboardLayoutForInputDevice should return " +
+                "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
+                "available",
+            KeyboardLayoutSelectionResult.FAILED,
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
             )
+        )
+        // If prefer layout with empty country over mismatched country
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-AU", "qwerty"),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+    }
 
-            // Back to back changing HW keyboards with same product and vendor ID but different
-            // language and layout type should configure the layouts correctly.
-            assertCorrectLayout(
-                englishQwertyKeyboardDevice,
-                frenchSubtype,
-                createLayoutDescriptor("keyboard_layout_english_us")
-            )
+    @Test
+    fun testGetDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
+        val frenchSubtype = createImeSubtypeForLanguageTagAndLayoutType("fr", "azerty")
+        // Should return English dvorak even if IME current layout is French, since HW says the
+        // keyboard is a Dvorak keyboard
+        assertCorrectLayout(
+            englishDvorakKeyboardDevice,
+            frenchSubtype,
+            createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+        )
 
-            // Fallback to IME information if the HW provided layout script is incompatible with the
-            // provided IME subtype
-            assertCorrectLayout(
-                englishDvorakKeyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
-                createLayoutDescriptor("keyboard_layout_russian")
-            )
-        }
+        // Back to back changing HW keyboards with same product and vendor ID but different
+        // language and layout type should configure the layouts correctly.
+        assertCorrectLayout(
+            englishQwertyKeyboardDevice,
+            frenchSubtype,
+            createLayoutDescriptor("keyboard_layout_english_us")
+        )
+
+        // Fallback to IME information if the HW provided layout script is incompatible with the
+        // provided IME subtype
+        assertCorrectLayout(
+            englishDvorakKeyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+            createLayoutDescriptor("keyboard_layout_russian")
+        )
     }
 
     @Test
@@ -867,27 +565,25 @@
                 KeyboardLayoutManager.ImeInfo(0, imeInfo,
                         createImeSubtypeForLanguageTagAndLayoutType("de-Latn", "qwertz")))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
-            ExtendedMockito.verify {
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.eq(keyboardDevice.vendorId),
-                        ArgumentMatchers.eq(keyboardDevice.productId),
-                        ArgumentMatchers.eq(
-                            createByteArray(
-                                KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
-                                LAYOUT_TYPE_DEFAULT,
-                                GERMAN_LAYOUT_NAME,
-                                KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD,
-                                "de-Latn",
-                                LAYOUT_TYPE_QWERTZ
-                            ),
+        keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
+        ExtendedMockito.verify {
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.eq(keyboardDevice.vendorId),
+                    ArgumentMatchers.eq(keyboardDevice.productId),
+                    ArgumentMatchers.eq(
+                        createByteArray(
+                            KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+                            LAYOUT_TYPE_DEFAULT,
+                            GERMAN_LAYOUT_NAME,
+                            KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD,
+                            "de-Latn",
+                            LAYOUT_TYPE_QWERTZ
                         ),
-                        ArgumentMatchers.eq(keyboardDevice.deviceBus),
-                )
-            }
+                    ),
+                    ArgumentMatchers.eq(keyboardDevice.deviceBus),
+            )
         }
     }
 
@@ -897,27 +593,25 @@
                 KeyboardLayoutManager.ImeInfo(0, imeInfo,
                         createImeSubtypeForLanguageTagAndLayoutType("de-Latn", "qwertz")))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceAdded(englishQwertyKeyboardDevice.id)
-            ExtendedMockito.verify {
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.eq(englishQwertyKeyboardDevice.vendorId),
-                        ArgumentMatchers.eq(englishQwertyKeyboardDevice.productId),
-                        ArgumentMatchers.eq(
-                            createByteArray(
-                                "en",
-                                LAYOUT_TYPE_QWERTY,
-                                ENGLISH_US_LAYOUT_NAME,
-                                KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE,
-                                "de-Latn",
-                                LAYOUT_TYPE_QWERTZ
-                            )
-                        ),
-                        ArgumentMatchers.eq(keyboardDevice.deviceBus),
-                )
-            }
+        keyboardLayoutManager.onInputDeviceAdded(englishQwertyKeyboardDevice.id)
+        ExtendedMockito.verify {
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.eq(englishQwertyKeyboardDevice.vendorId),
+                    ArgumentMatchers.eq(englishQwertyKeyboardDevice.productId),
+                    ArgumentMatchers.eq(
+                        createByteArray(
+                            "en",
+                            LAYOUT_TYPE_QWERTY,
+                            ENGLISH_US_LAYOUT_NAME,
+                            KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE,
+                            "de-Latn",
+                            LAYOUT_TYPE_QWERTZ
+                        )
+                    ),
+                    ArgumentMatchers.eq(keyboardDevice.deviceBus),
+            )
         }
     }
 
@@ -925,27 +619,25 @@
     fun testConfigurationLogged_onInputDeviceAdded_DefaultSelection() {
         val imeInfos = listOf(KeyboardLayoutManager.ImeInfo(0, imeInfo, createImeSubtype()))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
-            ExtendedMockito.verify {
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.eq(keyboardDevice.vendorId),
-                        ArgumentMatchers.eq(keyboardDevice.productId),
-                        ArgumentMatchers.eq(
-                            createByteArray(
-                                KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
-                                LAYOUT_TYPE_DEFAULT,
-                                "Default",
-                                KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEFAULT,
-                                KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
-                                LAYOUT_TYPE_DEFAULT
-                            ),
+        keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
+        ExtendedMockito.verify {
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.eq(keyboardDevice.vendorId),
+                    ArgumentMatchers.eq(keyboardDevice.productId),
+                    ArgumentMatchers.eq(
+                        createByteArray(
+                            KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+                            LAYOUT_TYPE_DEFAULT,
+                            "Default",
+                            KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEFAULT,
+                            KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+                            LAYOUT_TYPE_DEFAULT
                         ),
-                        ArgumentMatchers.eq(keyboardDevice.deviceBus),
-                )
-            }
+                    ),
+                    ArgumentMatchers.eq(keyboardDevice.deviceBus),
+            )
         }
     }
 
@@ -953,19 +645,17 @@
     fun testConfigurationNotLogged_onInputDeviceChanged() {
         val imeInfos = listOf(KeyboardLayoutManager.ImeInfo(0, imeInfo, createImeSubtype()))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
-            ExtendedMockito.verify({
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.anyInt(),
-                        ArgumentMatchers.anyInt(),
-                        ArgumentMatchers.any(ByteArray::class.java),
-                        ArgumentMatchers.anyInt(),
-                )
-            }, Mockito.times(0))
-        }
+        keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+        ExtendedMockito.verify({
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.anyInt(),
+                    ArgumentMatchers.anyInt(),
+                    ArgumentMatchers.any(ByteArray::class.java),
+                    ArgumentMatchers.anyInt(),
+            )
+        }, Mockito.times(0))
     }
 
     @Test
@@ -975,18 +665,16 @@
         Mockito.doReturn(false).`when`(keyboardLayoutManager).isVirtualDevice(
             ArgumentMatchers.eq(keyboardDevice.id)
         )
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
-            ExtendedMockito.verify(
-                notificationManager,
-                Mockito.times(1)
-            ).notifyAsUser(
-                ArgumentMatchers.isNull(),
-                ArgumentMatchers.anyInt(),
-                ArgumentMatchers.any(),
-                ArgumentMatchers.any()
-            )
-        }
+        keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+        ExtendedMockito.verify(
+            notificationManager,
+            Mockito.times(1)
+        ).notifyAsUser(
+            ArgumentMatchers.isNull(),
+            ArgumentMatchers.anyInt(),
+            ArgumentMatchers.any(),
+            ArgumentMatchers.any()
+        )
     }
 
     @Test
@@ -996,18 +684,16 @@
         Mockito.doReturn(true).`when`(keyboardLayoutManager).isVirtualDevice(
             ArgumentMatchers.eq(keyboardDevice.id)
         )
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
-            ExtendedMockito.verify(
-                notificationManager,
-                Mockito.never()
-            ).notifyAsUser(
-                ArgumentMatchers.isNull(),
-                ArgumentMatchers.anyInt(),
-                ArgumentMatchers.any(),
-                ArgumentMatchers.any()
-            )
-        }
+        keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+        ExtendedMockito.verify(
+            notificationManager,
+            Mockito.never()
+        ).notifyAsUser(
+            ArgumentMatchers.isNull(),
+            ArgumentMatchers.anyInt(),
+            ArgumentMatchers.any(),
+            ArgumentMatchers.any()
+        )
     }
 
     private fun assertCorrectLayout(
@@ -1019,7 +705,7 @@
             device.identifier, USER_ID, imeInfo, imeSubtype
         )
         assertEquals(
-            "New UI: getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
+            "getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
             expectedLayout,
             result.layoutDescriptor
         )
@@ -1123,21 +809,4 @@
         info.serviceInfo.name = RECEIVER_NAME
         return info
     }
-
-    private inner class NewSettingsApiFlag constructor(enabled: Boolean) : AutoCloseable {
-        init {
-            Settings.Global.putString(
-                context.contentResolver,
-                "settings_new_keyboard_ui", enabled.toString()
-            )
-        }
-
-        override fun close() {
-            Settings.Global.putString(
-                context.contentResolver,
-                "settings_new_keyboard_ui",
-                ""
-            )
-        }
-    }
 }
diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
index d9a4c26..5cdfb28 100644
--- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java
@@ -90,7 +90,7 @@
         //noinspection ResultOfMethodCallIgnored
         mFile.delete();
         mProtoLog = new LegacyProtoLogImpl(mFile, mViewerConfigFilename,
-                1024 * 1024, mReader, 1024, new TreeMap<>());
+                1024 * 1024, mReader, 1024, new TreeMap<>(), () -> {});
     }
 
     @After
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java
index a963890..001a09a 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoDataSourceTest.java
@@ -67,7 +67,7 @@
 
     @Test
     public void allEnabledTraceMode() {
-        final ProtoLogDataSource ds = new ProtoLogDataSource(() -> {}, () -> {}, () -> {});
+        final ProtoLogDataSource ds = new ProtoLogDataSource((c) -> {}, () -> {}, (c) -> {});
 
         final ProtoLogDataSource.TlsState tlsState = createTlsState(
                 DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig(
@@ -154,7 +154,7 @@
     private ProtoLogDataSource.TlsState createTlsState(
             DataSourceConfigOuterClass.DataSourceConfig config) {
         final ProtoLogDataSource ds =
-                Mockito.spy(new ProtoLogDataSource(() -> {}, () -> {}, () -> {}));
+                Mockito.spy(new ProtoLogDataSource((c) -> {}, () -> {}, (c) -> {}));
 
         ProtoInputStream configStream = new ProtoInputStream(config.toByteArray());
         final ProtoLogDataSource.Instance dsInstance = Mockito.spy(
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index 548adef..f6ac080 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -65,6 +65,7 @@
 import java.util.List;
 import java.util.Random;
 import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import perfetto.protos.Protolog;
 import perfetto.protos.ProtologCommon;
@@ -95,6 +96,7 @@
     private PerfettoProtoLogImpl mProtoLog;
     private Protolog.ProtoLogViewerConfig.Builder mViewerConfigBuilder;
     private File mFile;
+    private Runnable mCacheUpdater;
 
     private ProtoLogViewerConfigReader mReader;
 
@@ -152,9 +154,11 @@
         Mockito.when(viewerConfigInputStreamProvider.getInputStream())
                 .thenAnswer(it -> new ProtoInputStream(mViewerConfigBuilder.build().toByteArray()));
 
+        mCacheUpdater = () -> {};
         mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
-        mProtoLog =
-                new PerfettoProtoLogImpl(viewerConfigInputStreamProvider, mReader, new TreeMap<>());
+        mProtoLog = new PerfettoProtoLogImpl(
+                viewerConfigInputStreamProvider, mReader, new TreeMap<>(),
+                () -> mCacheUpdater.run());
     }
 
     @After
@@ -500,7 +504,8 @@
         PerfettoTraceMonitor traceMonitor =
                 PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
                         List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
-                                TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG, true)))
+                                TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
+                                true)))
                         .build();
         try {
             traceMonitor.start();
@@ -526,6 +531,142 @@
         Truth.assertThat(stacktrace).contains("stackTraceTrimmed");
     }
 
+    @Test
+    public void cacheIsUpdatedWhenTracesStartAndStop() {
+        final AtomicInteger cacheUpdateCallCount = new AtomicInteger(0);
+        mCacheUpdater = cacheUpdateCallCount::incrementAndGet;
+
+        PerfettoTraceMonitor traceMonitor1 =
+                PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+                                List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+                                        TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
+                                        false)))
+                        .build();
+
+        PerfettoTraceMonitor traceMonitor2 =
+                PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+                                List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+                                        TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
+                                        false)))
+                        .build();
+
+        Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(0);
+
+        try {
+            traceMonitor1.start();
+
+            Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(1);
+
+            try {
+                traceMonitor2.start();
+
+                Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(2);
+            } finally {
+                traceMonitor2.stop(mWriter);
+            }
+
+            Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(3);
+
+        } finally {
+            traceMonitor1.stop(mWriter);
+        }
+
+        Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(4);
+    }
+
+    @Test
+    public void isEnabledUpdatesBasedOnRunningTraces() {
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF)).isTrue();
+
+        PerfettoTraceMonitor traceMonitor1 =
+                PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+                                List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+                                        TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
+                                        false)))
+                        .build();
+
+        PerfettoTraceMonitor traceMonitor2 =
+                PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+                                List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+                                        TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
+                                        false)))
+                        .build();
+
+        try {
+            traceMonitor1.start();
+
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+                    .isFalse();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+                    .isFalse();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+                    .isFalse();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+                    .isTrue();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+                    .isTrue();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+                    .isTrue();
+
+            try {
+                traceMonitor2.start();
+
+                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+                        .isTrue();
+                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP,
+                        LogLevel.VERBOSE)).isTrue();
+                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+                        .isTrue();
+                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+                        .isTrue();
+                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+                        .isTrue();
+                Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+                        .isTrue();
+            } finally {
+                traceMonitor2.stop(mWriter);
+            }
+
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+                    .isFalse();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+                    .isFalse();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+                    .isFalse();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+                    .isTrue();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+                    .isTrue();
+            Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+                    .isTrue();
+        } finally {
+            traceMonitor1.stop(mWriter);
+        }
+
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+                .isFalse();
+        Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+                .isTrue();
+    }
+
     private enum TestProtoLogGroup implements IProtoLogGroup {
         TEST_GROUP(true, true, false, "TEST_TAG");
 
diff --git a/tests/OneMedia/Android.bp b/tests/OneMedia/Android.bp
index 5c73177..a43cd39 100644
--- a/tests/OneMedia/Android.bp
+++ b/tests/OneMedia/Android.bp
@@ -16,6 +16,7 @@
     platform_apis: true,
     certificate: "platform",
     libs: ["org.apache.http.legacy"],
+    optional_uses_libs: ["org.apache.http.legacy"],
     optimize: {
         enabled: false,
     },
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 081da11..489ef44 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -66,6 +66,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
@@ -220,43 +221,36 @@
         RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
 
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(1);
-        int bootCounter = 0;
+
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
-            bootCounter += 1;
         }
+
         verify(rescuePartyObserver).executeBootLoopMitigation(1);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-            bootCounter += 1;
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(2);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
 
-        int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
-        for (int i = 0; i < bootLoopThreshold; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(3);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(4);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(4);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(5);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(5);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(6);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(7);
     }
@@ -268,11 +262,11 @@
                 setUpRollbackPackageHealthObserver(watchdog);
 
         verify(rollbackObserver, never()).executeBootLoopMitigation(1);
-        int bootCounter = 0;
+
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
-            bootCounter += 1;
         }
+
         verify(rollbackObserver).executeBootLoopMitigation(1);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
@@ -280,19 +274,16 @@
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_HIGH,
                 ROLLBACK_INFO_MANUAL));
 
-        int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
-        for (int i = 0; i < bootLoopThreshold; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rollbackObserver).executeBootLoopMitigation(2);
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
 
         // Update the list of available rollbacks after executing bootloop mitigation once
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_MANUAL));
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
     }
 
@@ -305,27 +296,21 @@
 
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(1);
         verify(rollbackObserver, never()).executeBootLoopMitigation(1);
-        int bootCounter = 0;
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
-            bootCounter += 1;
         }
         verify(rescuePartyObserver).executeBootLoopMitigation(1);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
         verify(rollbackObserver, never()).executeBootLoopMitigation(1);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-            bootCounter += 1;
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(2);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-            bootCounter += 1;
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
         verify(rollbackObserver).executeBootLoopMitigation(1);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
@@ -333,43 +318,46 @@
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_HIGH,
                 ROLLBACK_INFO_MANUAL));
 
-        int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
-        for (int i = 0; i < bootLoopThreshold; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(3);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(4);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(4);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(5);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(5);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
         verify(rollbackObserver).executeBootLoopMitigation(2);
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
         // Update the list of available rollbacks after executing bootloop mitigation
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_MANUAL));
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(6);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(7);
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
+
+        moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
+        Mockito.reset(rescuePartyObserver);
+
+        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
+            watchdog.noteBoot();
+        }
+        verify(rescuePartyObserver).executeBootLoopMitigation(1);
+        verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
     }
 
     RollbackPackageHealthObserver setUpRollbackPackageHealthObserver(PackageWatchdog watchdog) {
@@ -506,16 +494,9 @@
         }
 
         try {
-            if (Flags.recoverabilityDetection()) {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-            } else {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
+            mSpyBootThreshold = spy(watchdog.new BootThreshold(
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
-            }
 
             doAnswer((Answer<Integer>) invocationOnMock -> {
                 String storedValue = mCrashRecoveryPropertiesMap
@@ -640,5 +621,16 @@
         public long uptimeMillis() {
             return mUpTimeMillis;
         }
+        public void moveTimeForward(long milliSeconds) {
+            mUpTimeMillis += milliSeconds;
+        }
+    }
+
+    private void moveTimeForwardAndDispatch(long milliSeconds) {
+        // Exhaust all due runnables now which shouldn't be executed after time-leap
+        mTestLooper.dispatchAll();
+        mTestClock.moveTimeForward(milliSeconds);
+        mTestLooper.moveTimeForward(milliSeconds);
+        mTestLooper.dispatchAll();
     }
 }
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 4f27e06..093923f 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -45,13 +45,13 @@
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.DeviceConfig;
 import android.util.AtomicFile;
+import android.util.LongArrayQueue;
 import android.util.Xml;
-import android.utils.LongArrayQueue;
-import android.utils.XmlUtils;
 
 import androidx.test.InstrumentationRegistry;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.PackageWatchdog.HealthCheckState;
@@ -1224,7 +1224,7 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
         watchdog.registerHealthObserver(bootObserver);
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD; i++) {
+        for (int i = 0; i < 15; i++) {
             watchdog.noteBoot();
         }
         assertThat(bootObserver.mitigatedBootLoop()).isTrue();
@@ -1262,22 +1262,6 @@
     }
 
     /**
-     * Ensure that boot loop mitigation is not done when the number of boots does not meet the
-     * threshold.
-     */
-    @Test
-    public void testBootLoopDetection_doesNotMeetThresholdRecoverabilityHighImpact() {
-        PackageWatchdog watchdog = createWatchdog();
-        TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_LEVEL_80);
-        watchdog.registerHealthObserver(bootObserver);
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; i++) {
-            watchdog.noteBoot();
-        }
-        assertThat(bootObserver.mitigatedBootLoop()).isFalse();
-    }
-
-    /**
      * Ensure that boot loop mitigation is done for the observer with the lowest user impact
      */
     @Test
@@ -1306,7 +1290,7 @@
         bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
         watchdog.registerHealthObserver(bootObserver1);
         watchdog.registerHealthObserver(bootObserver2);
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD; i++) {
+        for (int i = 0; i < 15; i++) {
             watchdog.noteBoot();
         }
         assertThat(bootObserver1.mitigatedBootLoop()).isTrue();
@@ -1349,9 +1333,7 @@
             watchdog.noteBoot();
         }
         for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
                 watchdog.noteBoot();
-            }
         }
 
         moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
@@ -1360,38 +1342,7 @@
             watchdog.noteBoot();
         }
         for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
                 watchdog.noteBoot();
-            }
-        }
-
-        assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
-    }
-
-    @Test
-    public void testMultipleBootLoopMitigationRecoverabilityHighImpact() {
-        PackageWatchdog watchdog = createWatchdog();
-        TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_LEVEL_80);
-        watchdog.registerHealthObserver(bootObserver);
-        for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; j++) {
-            watchdog.noteBoot();
-        }
-        for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
-                watchdog.noteBoot();
-            }
-        }
-
-        moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
-
-        for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; j++) {
-            watchdog.noteBoot();
-        }
-        for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
-                watchdog.noteBoot();
-            }
         }
 
         assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
@@ -1642,8 +1593,7 @@
 
         mSpyBootThreshold = spy(watchdog.new BootThreshold(
                 PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
+                PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
 
         watchdog.saveAllObserversBootMitigationCountToMetadata(filePath);
 
@@ -1798,16 +1748,9 @@
         mCrashRecoveryPropertiesMap = new HashMap<>();
 
         try {
-            if (Flags.recoverabilityDetection()) {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-            } else {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
+            mSpyBootThreshold = spy(watchdog.new BootThreshold(
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
-            }
 
             doAnswer((Answer<Integer>) invocationOnMock -> {
                 String storedValue = mCrashRecoveryPropertiesMap
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
index 7558332..f88d82b 100644
--- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
@@ -85,6 +85,8 @@
         assertTrue(TelephonyUtils.isValidPlmn("45006"));
         assertFalse(TelephonyUtils.isValidPlmn("1234567"));
         assertFalse(TelephonyUtils.isValidPlmn("1234"));
+        assertFalse(TelephonyUtils.isValidPlmn(""));
+        assertFalse(TelephonyUtils.isValidPlmn(null));
     }
 
     @Test
@@ -94,6 +96,19 @@
         assertFalse(TelephonyUtils.isValidService(FIRST_SERVICE_TYPE - 1));
         assertFalse(TelephonyUtils.isValidService(LAST_SERVICE_TYPE + 1));
     }
+
+    @Test
+    public void testIsValidCountryCode() {
+        assertTrue(TelephonyUtils.isValidCountryCode("US"));
+        assertTrue(TelephonyUtils.isValidCountryCode("cn"));
+        assertFalse(TelephonyUtils.isValidCountryCode("11"));
+        assertFalse(TelephonyUtils.isValidCountryCode("USA"));
+        assertFalse(TelephonyUtils.isValidCountryCode("chn"));
+        assertFalse(TelephonyUtils.isValidCountryCode("U"));
+        assertFalse(TelephonyUtils.isValidCountryCode("G7"));
+        assertFalse(TelephonyUtils.isValidCountryCode(""));
+        assertFalse(TelephonyUtils.isValidCountryCode(null));
+    }
 }
 
 
diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp
index 4ef1ead..7990732 100644
--- a/tests/TouchLatency/Android.bp
+++ b/tests/TouchLatency/Android.bp
@@ -5,6 +5,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_android_core_graphics_stack",
 }
 
 android_test {
diff --git a/tests/TouchLatency/app/src/main/res/values/styles.xml b/tests/TouchLatency/app/src/main/res/values/styles.xml
index b23a87e..fa352cf 100644
--- a/tests/TouchLatency/app/src/main/res/values/styles.xml
+++ b/tests/TouchLatency/app/src/main/res/values/styles.xml
@@ -18,6 +18,7 @@
     <!-- Base application theme. -->
     <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
         <!-- Customize your theme here. -->
+        <item name="android:windowLayoutInDisplayCutoutMode">default</item>
     </style>
 
 </resources>
diff --git a/tests/UsbTests/TEST_MAPPING b/tests/UsbTests/TEST_MAPPING
new file mode 100644
index 0000000..70134b8
--- /dev/null
+++ b/tests/UsbTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+    {
+      "name": "UsbTests"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java
index b506d74..56845ae 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java
@@ -21,10 +21,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
@@ -34,9 +33,7 @@
 import android.hardware.usb.flags.Flags;
 import android.os.RemoteException;
 import android.os.UserManager;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -64,7 +61,7 @@
     @Mock
     private UsbSettingsManager mUsbSettingsManager;
     @Mock
-    private IUsbOperationInternal mIUsbOperationInternal;
+    private IUsbOperationInternal mCallback;
 
     private static final String TEST_PORT_ID = "123";
 
@@ -77,98 +74,105 @@
     private UsbService mUsbService;
 
     @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     @Before
     public void setUp() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING);
         MockitoAnnotations.initMocks(this);
-        mUsbService = new UsbService(mContext, mUsbPortManager, mUsbAlsaManager, mUserManager,
-                mUsbSettingsManager);
+
+        when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(), eq(TEST_TRANSACTION_ID),
+                eq(mCallback), any())).thenReturn(true);
+
+        mUsbService = new UsbService(mContext, mUsbPortManager, mUsbAlsaManager,
+                mUserManager, mUsbSettingsManager);
+    }
+
+    private void assertToggleUsbSuccessfully(int uid, boolean enable) {
+        assertTrue(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable,
+                TEST_TRANSACTION_ID, mCallback, uid));
+
+        verify(mUsbPortManager).enableUsbData(TEST_PORT_ID,
+                enable, TEST_TRANSACTION_ID, mCallback, null);
+        verifyZeroInteractions(mCallback);
+
+        clearInvocations(mUsbPortManager);
+        clearInvocations(mCallback);
+    }
+
+    private void assertToggleUsbFailed(int uid, boolean enable) throws Exception {
+        assertFalse(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable,
+                TEST_TRANSACTION_ID, mCallback, uid));
+
+        verifyZeroInteractions(mUsbPortManager);
+        verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+
+        clearInvocations(mUsbPortManager);
+        clearInvocations(mCallback);
     }
 
     /**
      * Verify enableUsbData successfully disables USB port without error
      */
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING)
-    public void usbPort_SuccessfullyDisabled() {
-        boolean enableState = false;
-        when(mUsbPortManager.enableUsbData(TEST_PORT_ID, enableState, TEST_TRANSACTION_ID,
-                mIUsbOperationInternal, null)).thenReturn(true);
-
-        assertTrue(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enableState,
-                TEST_TRANSACTION_ID, mIUsbOperationInternal, TEST_FIRST_CALLER_ID));
-
-        verify(mUsbPortManager, times(1)).enableUsbData(TEST_PORT_ID,
-                enableState, TEST_TRANSACTION_ID, mIUsbOperationInternal, null);
-        verifyZeroInteractions(mIUsbOperationInternal);
+    public void disableUsb_successfullyDisable() {
+        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
     }
 
     /**
      * Verify enableUsbData successfully enables USB port without error given no other stakers
      */
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING)
-    public void usbPortWhenNoOtherStakers_SuccessfullyEnabledUsb() {
-        boolean enableState = true;
-        when(mUsbPortManager.enableUsbData(TEST_PORT_ID, enableState, TEST_TRANSACTION_ID,
-                mIUsbOperationInternal, null))
-                .thenReturn(true);
-
-        assertTrue(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enableState,
-                TEST_TRANSACTION_ID, mIUsbOperationInternal, TEST_FIRST_CALLER_ID));
-        verifyZeroInteractions(mIUsbOperationInternal);
+    public void enableUsbWhenNoOtherStakers_successfullyEnable() {
+        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true);
     }
 
     /**
      * Verify enableUsbData does not enable USB port if other stakers are present
      */
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING)
-    public void usbPortWithOtherStakers_DoesNotToEnableUsb() throws RemoteException {
-        mUsbService.enableUsbDataInternal(TEST_PORT_ID, false, TEST_TRANSACTION_ID,
-                mIUsbOperationInternal, TEST_FIRST_CALLER_ID);
-        clearInvocations(mUsbPortManager);
+    public void enableUsbPortWithOtherStakers_failsToEnable() throws Exception {
+        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
 
-        assertFalse(mUsbService.enableUsbDataInternal(TEST_PORT_ID, true,
-                TEST_TRANSACTION_ID, mIUsbOperationInternal, TEST_SECOND_CALLER_ID));
+        assertToggleUsbFailed(TEST_SECOND_CALLER_ID, true);
+    }
 
-        verifyZeroInteractions(mUsbPortManager);
-        verify(mIUsbOperationInternal).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+    /**
+     * Verify enableUsbData successfully enables USB port when the last staker is removed
+     */
+    @Test
+    public void enableUsbByTheOnlyStaker_successfullyEnable() {
+        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
+
+        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true);
     }
 
     /**
      * Verify enableUsbDataWhileDockedInternal does not enable USB port if other stakers are present
      */
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING)
-    public void enableUsbWhileDockedWhenThereAreOtherStakers_DoesNotEnableUsb()
+    public void enableUsbWhileDockedWhenThereAreOtherStakers_failsToEnable()
             throws RemoteException {
-        mUsbService.enableUsbDataInternal(TEST_PORT_ID, false, TEST_TRANSACTION_ID,
-                mIUsbOperationInternal, TEST_FIRST_CALLER_ID);
+        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false);
 
-        mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, 0,
-                mIUsbOperationInternal, TEST_SECOND_CALLER_ID);
+        mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID,
+                mCallback, TEST_SECOND_CALLER_ID);
 
-        verify(mUsbPortManager, never()).enableUsbDataWhileDocked(any(),
-                anyLong(), any(), any());
-        verify(mIUsbOperationInternal).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+        verifyZeroInteractions(mUsbPortManager);
+        verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
     }
 
     /**
-     * Verify enableUsbDataWhileDockedInternal does  enable USB port if other stakers are
+     * Verify enableUsbDataWhileDockedInternal does enable USB port if other stakers are
      * not present
      */
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING)
-    public void enableUsbWhileDockedWhenThereAreNoStakers_SuccessfullyEnableUsb()
-            throws RemoteException {
+    public void enableUsbWhileDockedWhenThereAreNoStakers_SuccessfullyEnable() {
         mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID,
-                mIUsbOperationInternal, TEST_SECOND_CALLER_ID);
+                mCallback, TEST_SECOND_CALLER_ID);
 
-        verify(mUsbPortManager, times(1))
-                .enableUsbDataWhileDocked(TEST_PORT_ID, TEST_TRANSACTION_ID,
-                        mIUsbOperationInternal, null);
-        verifyZeroInteractions(mIUsbOperationInternal);
+        verify(mUsbPortManager).enableUsbDataWhileDocked(TEST_PORT_ID, TEST_TRANSACTION_ID,
+                        mCallback, null);
+        verifyZeroInteractions(mCallback);
     }
 }
diff --git a/tests/WindowInsetsTests/AndroidManifest.xml b/tests/WindowInsetsTests/AndroidManifest.xml
index 61dd9d4..dbe9d36 100644
--- a/tests/WindowInsetsTests/AndroidManifest.xml
+++ b/tests/WindowInsetsTests/AndroidManifest.xml
@@ -18,7 +18,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.google.android.test.windowinsetstests">
 
-    <application android:label="@string/application_title">
+    <application android:label="@string/application_title"
+                 android:theme="@style/base">
         <activity android:name=".WindowInsetsTestsMainActivity"
                   android:exported="true">
             <intent-filter>
@@ -29,11 +30,9 @@
 
         <activity android:name=".ChatActivity"
                   android:label="@string/chat_activity_title"
-                  android:theme="@style/chat"
                   android:windowSoftInputMode="adjustResize" />
 
         <activity android:name=".ControllerActivity"
-                  android:label="@string/controller_activity_title"
-                  android:theme="@style/controller" />
+                  android:label="@string/controller_activity_title" />
     </application>
 </manifest>
diff --git a/tests/WindowInsetsTests/res/layout/controller_activity.xml b/tests/WindowInsetsTests/res/layout/controller_activity.xml
index 5550eab..7013059 100644
--- a/tests/WindowInsetsTests/res/layout/controller_activity.xml
+++ b/tests/WindowInsetsTests/res/layout/controller_activity.xml
@@ -15,92 +15,110 @@
 -->
 
 
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <LinearLayout
-        android:id="@+id/content"
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+    />
+
+    <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="vertical">
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp">
 
-        <Spinner
-            android:id="@+id/spinnerBehavior"
+        <LinearLayout
+            android:id="@+id/content"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:layout_marginBottom="20dp" />
+            android:orientation="vertical">
 
-        <ToggleButton
-            android:id="@+id/toggleButtonStatus"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:checked="true"
-            android:text="Status Bars Toggle Button"
-            android:textOff="Status Bars Invisible"
-            android:textOn="Status Bars Visible" />
+            <Spinner
+                android:id="@+id/spinnerBehavior"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="20dp" />
 
-        <SeekBar
-            android:id="@+id/seekBarStatus"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:layout_marginBottom="20dp"
-            android:max="10000"
-            android:progress="10000" />
+            <ToggleButton
+                android:id="@+id/toggleButtonStatus"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:text="@string/status_bars_toggle_button"
+                android:textOff="@string/status_bars_invisible"
+                android:textOn="@string/status_bars_visible" />
 
-        <ToggleButton
-            android:id="@+id/toggleButtonNavigation"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:checked="true"
-            android:text="Navigation Bars Toggle Button"
-            android:textOff="Navigation Bars Invisible"
-            android:textOn="Navigation Bars Visible" />
+            <SeekBar
+                android:id="@+id/seekBarStatus"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="20dp"
+                android:max="10000"
+                android:progress="10000" />
 
-        <SeekBar
-            android:id="@+id/seekBarNavigation"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:layout_marginBottom="20dp"
-            android:max="10000"
-            android:progress="10000" />
+            <ToggleButton
+                android:id="@+id/toggleButtonNavigation"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:text="@string/navigation_bars_toggle_button"
+                android:textOff="@string/navigation_bars_invisible"
+                android:textOn="@string/navigation_bars_visible" />
 
-        <ToggleButton
-            android:id="@+id/toggleButtonIme"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:checked="true"
-            android:text="IME Toggle Button"
-            android:textOff="IME Invisible"
-            android:textOn="IME Visible" />
+            <SeekBar
+                android:id="@+id/seekBarNavigation"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="20dp"
+                android:max="10000"
+                android:progress="10000" />
 
-        <SeekBar
-            android:id="@+id/seekBarIme"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:layout_marginBottom="20dp"
-            android:max="10000"
-            android:progress="0" />
+            <ToggleButton
+                android:id="@+id/toggleButtonIme"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:text="@string/ime_toggle_button"
+                android:textOff="@string/ime_invisible"
+                android:textOn="@string/ime_visible" />
 
-        <TextView
-            android:id="@+id/textViewControllableInsets"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_margin="5dp" />
+            <SeekBar
+                android:id="@+id/seekBarIme"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="20dp"
+                android:max="10000"
+                android:progress="0" />
 
-        <EditText
-            android:id="@+id/editText"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ems="10"
-            android:hint="For testing IME..."
-            android:inputType="text"
-            android:text="" />
+            <TextView
+                android:id="@+id/textViewControllableInsets"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dp" />
 
-    </LinearLayout>
+            <EditText
+                android:id="@+id/editText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:autofillHints="@string/for_testing_ime"
+                android:hint="@string/for_testing_ime"
+                android:inputType="text"
+                android:text="" />
 
-</ScrollView>
\ No newline at end of file
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/tests/WindowInsetsTests/res/layout/main_activity.xml b/tests/WindowInsetsTests/res/layout/main_activity.xml
index 621ed89..d6d4ff9 100644
--- a/tests/WindowInsetsTests/res/layout/main_activity.xml
+++ b/tests/WindowInsetsTests/res/layout/main_activity.xml
@@ -16,22 +16,38 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-    <Button
-        android:id="@+id/chat_button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/chat_activity_title"
-        android:textAllCaps="false"/>
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+    />
 
-    <Button
-        android:id="@+id/controller_button"
-        android:layout_width="wrap_content"
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/controller_activity_title"
-        android:textAllCaps="false"/>
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp">
+
+        <Button
+            android:id="@+id/chat_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/chat_activity_title"
+            android:textAllCaps="false"/>
+
+        <Button
+            android:id="@+id/controller_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/controller_activity_title"
+            android:textAllCaps="false"/>
+
+    </LinearLayout>
 
 </LinearLayout>
diff --git a/tests/WindowInsetsTests/res/values-night/styles.xml b/tests/WindowInsetsTests/res/values-night/styles.xml
new file mode 100644
index 0000000..323c5fd
--- /dev/null
+++ b/tests/WindowInsetsTests/res/values-night/styles.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+
+    <style name="base" parent="@style/Theme.MaterialComponents">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+
+        <item name="colorPrimary">@color/primaryColor</item>
+        <item name="colorPrimaryDark">@color/primaryDarkColor</item>
+        <item name="colorSecondary">?attr/colorPrimary</item>
+        <item name="colorOnSecondary">@color/primaryTextColor</item>
+
+        <!-- Window decor -->
+        <item name="android:windowLightStatusBar">false</item>
+        <item name="android:windowLightNavigationBar">false</item>
+
+    </style>
+
+    <color name="primaryColor">#639ff9</color>
+    <color name="primaryLightColor">#6f6bff</color>
+    <color name="primaryDarkColor">#0016bb</color>
+    <color name="primaryTextColor">#ffffff</color>
+
+    <color name="bubble">#333333</color>
+    <color name="bubble_self">#185abc</color>
+
+</resources>
diff --git a/tests/WindowInsetsTests/res/values/strings.xml b/tests/WindowInsetsTests/res/values/strings.xml
index 516d458..7b70852 100644
--- a/tests/WindowInsetsTests/res/values/strings.xml
+++ b/tests/WindowInsetsTests/res/values/strings.xml
@@ -19,6 +19,16 @@
     <string name="application_title">Window Insets Tests</string>
     <string name="chat_activity_title">New Insets Chat</string>
     <string name="controller_activity_title">Window Insets Controller</string>
+    <string name="status_bars_toggle_button">Status Bars Toggle Button</string>
+    <string name="status_bars_invisible">Status Bars Invisible</string>
+    <string name="status_bars_visible">Status Bars Visible</string>
+    <string name="navigation_bars_toggle_button">Navigation Bars Toggle Button</string>
+    <string name="navigation_bars_invisible">Navigation Bars Invisible</string>
+    <string name="navigation_bars_visible">Navigation Bars Visible</string>
+    <string name="ime_toggle_button">IME Bars Toggle Button</string>
+    <string name="ime_invisible">IME Bars Invisible</string>
+    <string name="ime_visible">IME Bars Visible</string>
+    <string name="for_testing_ime">For testing IME&#8230;</string>
 
     <!-- The item positions should match the flag values respectively. -->
     <string-array name="behaviors">
diff --git a/tests/WindowInsetsTests/res/values/styles.xml b/tests/WindowInsetsTests/res/values/styles.xml
index a84ffbed..4ce6323 100644
--- a/tests/WindowInsetsTests/res/values/styles.xml
+++ b/tests/WindowInsetsTests/res/values/styles.xml
@@ -17,7 +17,7 @@
 
 <resources>
 
-    <style name="chat" parent="@style/Theme.MaterialComponents.Light">
+    <style name="base" parent="@style/Theme.MaterialComponents.Light">
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
 
@@ -27,10 +27,8 @@
         <item name="colorOnSecondary">@color/primaryTextColor</item>
 
         <!-- Window decor -->
-        <item name="android:statusBarColor">#ffffff</item>
         <item name="android:windowLightStatusBar">true</item>
         <item name="android:windowLightNavigationBar">true</item>
-        <item name="android:navigationBarColor">#ffffff</item>
 
     </style>
 
@@ -63,11 +61,4 @@
     <dimen name="bubble_padding">8dp</dimen>
     <dimen name="bubble_padding_side">16dp</dimen>
 
-    <style name="controller" parent="android:Theme.Material">
-        <item name="android:colorPrimaryDark">#111111</item>
-        <item name="android:navigationBarColor">#111111</item>
-        <item name="android:colorPrimary">#222222</item>
-        <item name="android:colorAccent">#33ccff</item>
-    </style>
-
-</resources>
\ No newline at end of file
+</resources>
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java
index 167d560..1dd87df 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java
@@ -16,12 +16,18 @@
 
 package com.google.android.test.windowinsetstests;
 
-import android.app.Activity;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowInsets.Type.systemGestures;
+
 import android.graphics.Insets;
 import android.os.Bundle;
 import android.view.View;
 import android.view.WindowInsets;
-import android.view.WindowInsets.Type;
+import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsAnimationControlListener;
 import android.view.WindowInsetsAnimationController;
 import android.widget.AdapterView;
@@ -32,7 +38,9 @@
 import android.widget.TextView;
 import android.widget.ToggleButton;
 
-public class ControllerActivity extends Activity implements View.OnApplyWindowInsetsListener {
+import androidx.appcompat.app.AppCompatActivity;
+
+public class ControllerActivity extends AppCompatActivity {
 
     private ToggleButton mToggleStatus;
     private SeekBar mSeekStatus;
@@ -48,6 +56,29 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.controller_activity);
+        setSupportActionBar(findViewById(R.id.toolbar));
+        getWindow().setDecorFitsSystemWindows(false);
+        findViewById(R.id.root).setOnApplyWindowInsetsListener(
+                (v, insets) -> {
+                    final int visibleTypes = systemBars() | displayCutout();
+                    final Insets i = insets.getInsets(visibleTypes);
+                    v.setPadding(i.left, i.top, i.right, i.bottom);
+
+                    // Make the content view not obscured by gesture insets to prevent triggering
+                    // system gestures while controlling seek bars.
+                    final Insets gi = Insets.subtract(
+                            insets.getInsets(systemGestures() | visibleTypes), i);
+                    findViewById(R.id.content).setPadding(gi.left, gi.top, gi.right, gi.bottom);
+
+                    mNotFromUser[0] = true;
+                    updateWidgets(insets, statusBars(), mToggleStatus, mSeekStatus);
+                    updateWidgets(insets, navigationBars(), mToggleNavigation, mSeekNavigation);
+                    updateWidgets(insets, ime(), mToggleIme, mSeekIme);
+                    mLastInsets = insets;
+                    mNotFromUser[0] = false;
+
+                    return WindowInsets.CONSUMED;
+                });
         final Spinner spinnerBehavior = findViewById(R.id.spinnerBehavior);
         ArrayAdapter<CharSequence> adapterBehavior = ArrayAdapter.createFromResource(this,
                 R.array.behaviors, android.R.layout.simple_spinner_item);
@@ -66,23 +97,21 @@
         });
         mToggleStatus = findViewById(R.id.toggleButtonStatus);
         mToggleStatus.setTag(mNotFromUser);
-        mToggleStatus.setOnCheckedChangeListener(new ToggleListener(Type.statusBars()));
+        mToggleStatus.setOnCheckedChangeListener(new ToggleListener(statusBars()));
         mSeekStatus = findViewById(R.id.seekBarStatus);
-        mSeekStatus.setOnSeekBarChangeListener(new SeekBarListener(Type.statusBars()));
+        mSeekStatus.setOnSeekBarChangeListener(new SeekBarListener(statusBars()));
         mToggleNavigation = findViewById(R.id.toggleButtonNavigation);
         mToggleNavigation.setTag(mNotFromUser);
-        mToggleNavigation.setOnCheckedChangeListener(new ToggleListener(Type.navigationBars()));
+        mToggleNavigation.setOnCheckedChangeListener(new ToggleListener(navigationBars()));
         mSeekNavigation = findViewById(R.id.seekBarNavigation);
-        mSeekNavigation.setOnSeekBarChangeListener(new SeekBarListener(Type.navigationBars()));
+        mSeekNavigation.setOnSeekBarChangeListener(new SeekBarListener(navigationBars()));
         mToggleIme = findViewById(R.id.toggleButtonIme);
         mToggleIme.setTag(mNotFromUser);
-        mToggleIme.setOnCheckedChangeListener(new ToggleListener(Type.ime()));
+        mToggleIme.setOnCheckedChangeListener(new ToggleListener(ime()));
         mSeekIme = findViewById(R.id.seekBarIme);
-        mSeekIme.setOnSeekBarChangeListener(new SeekBarListener(Type.ime()));
+        mSeekIme.setOnSeekBarChangeListener(new SeekBarListener(ime()));
         mTextControllableInsets = findViewById(R.id.textViewControllableInsets);
-        final View contentView = findViewById(R.id.content);
-        contentView.setOnApplyWindowInsetsListener(this);
-        contentView.getWindowInsetsController().addOnControllableInsetsChangedListener(
+        mTextControllableInsets.getWindowInsetsController().addOnControllableInsetsChangedListener(
                 (c, types) -> mTextControllableInsets.setText(
                         "ControllableInsetsTypes:\n" + insetsTypesToString(types)));
     }
@@ -91,22 +120,6 @@
         return types == 0 ? "none" : WindowInsets.Type.toString(types);
     }
 
-    @Override
-    public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
-        mNotFromUser[0] = true;
-        updateWidgets(insets, Type.statusBars(), mToggleStatus, mSeekStatus);
-        updateWidgets(insets, Type.navigationBars(), mToggleNavigation, mSeekNavigation);
-        updateWidgets(insets, Type.ime(), mToggleIme, mSeekIme);
-        mLastInsets = insets;
-        mNotFromUser[0] = false;
-
-        // Prevent triggering system gestures while controlling seek bars.
-        final Insets gestureInsets =  insets.getInsets(Type.systemGestures());
-        v.setPadding(gestureInsets.left, 0, gestureInsets.right, 0);
-
-        return v.onApplyWindowInsets(insets);
-    }
-
     private void updateWidgets(WindowInsets insets, int types, ToggleButton toggle, SeekBar seek) {
         final boolean isVisible = insets.isVisible(types);
         final boolean wasVisible = mLastInsets != null ? mLastInsets.isVisible(types) : !isVisible;
@@ -121,7 +134,7 @@
 
     private static class ToggleListener implements CompoundButton.OnCheckedChangeListener {
 
-        private final @Type.InsetsType int mTypes;
+        private final @InsetsType int mTypes;
 
         ToggleListener(int types) {
             mTypes = types;
@@ -143,7 +156,7 @@
 
     private static class SeekBarListener implements SeekBar.OnSeekBarChangeListener {
 
-        private final @Type.InsetsType int mTypes;
+        private final @InsetsType int mTypes;
 
         private WindowInsetsAnimationController mController;
 
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java
index 8b77a78..278ad84 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java
@@ -16,16 +16,30 @@
 
 package com.google.android.test.windowinsetstests;
 
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.systemBars;
 
-public class WindowInsetsTestsMainActivity extends Activity {
+import android.content.Intent;
+import android.graphics.Insets;
+import android.os.Bundle;
+import android.view.WindowInsets;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+public class WindowInsetsTestsMainActivity extends AppCompatActivity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main_activity);
+        setSupportActionBar(findViewById(R.id.toolbar));
+
+        findViewById(R.id.root).setOnApplyWindowInsetsListener(
+                (v, insets) -> {
+                    final Insets i = insets.getInsets(systemBars() | displayCutout());
+                    v.setPadding(i.left, i.top, i.right, i.bottom);
+                    return WindowInsets.CONSUMED;
+                });
 
         findViewById(R.id.chat_button).setOnClickListener(
                 v -> startActivity(new Intent(this, ChatActivity.class)));
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
index fdf8fb8..c8b60e5 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
@@ -17,9 +17,11 @@
 package com.android.server.vcn.routeselection;
 
 import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY;
+import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY;
 import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY;
 
-import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.PACKET_LOSS_UNAVALAIBLE;
+import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.MIN_VALID_EXPECTED_RX_PACKET_NUM;
+import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.getMaxSeqNumIncreasePerSecond;
 import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
 
 import static org.junit.Assert.assertEquals;
@@ -44,6 +46,7 @@
 import android.os.OutcomeReceiver;
 import android.os.PowerManager;
 
+import com.android.server.vcn.routeselection.IpSecPacketLossDetector.PacketLossCalculationResult;
 import com.android.server.vcn.routeselection.IpSecPacketLossDetector.PacketLossCalculator;
 import com.android.server.vcn.routeselection.NetworkMetricMonitor.IpSecTransformWrapper;
 import com.android.server.vcn.routeselection.NetworkMetricMonitor.NetworkMetricMonitorCallback;
@@ -65,6 +68,7 @@
     private static final int REPLAY_BITMAP_LEN_BYTE = 512;
     private static final int REPLAY_BITMAP_LEN_BIT = REPLAY_BITMAP_LEN_BYTE * 8;
     private static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD = 5;
+    private static final int MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED = -1;
     private static final long POLL_IPSEC_STATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(30L);
 
     @Mock private IpSecTransformWrapper mIpSecTransform;
@@ -91,6 +95,9 @@
                         eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
                         anyInt()))
                 .thenReturn(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD);
+        when(mCarrierConfig.getInt(
+                        eq(VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY), anyInt()))
+                .thenReturn(MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED);
 
         when(mDependencies.getPacketLossCalculator()).thenReturn(mPacketLossCalculator);
 
@@ -112,6 +119,20 @@
                 .build();
     }
 
+    private static IpSecTransformState newNextTransformState(
+            IpSecTransformState before,
+            long timeDiffMillis,
+            long rxSeqNoDiff,
+            long packtCountDiff,
+            int packetInWin) {
+        return new IpSecTransformState.Builder()
+                .setTimestampMillis(before.getTimestampMillis() + timeDiffMillis)
+                .setRxHighestSequenceNumber(before.getRxHighestSequenceNumber() + rxSeqNoDiff)
+                .setPacketCount(before.getPacketCount() + packtCountDiff)
+                .setReplayBitmap(newReplayBitmap(packetInWin))
+                .build();
+    }
+
     private static byte[] newReplayBitmap(int receivedPktCnt) {
         final BitSet bitSet = new BitSet(REPLAY_BITMAP_LEN_BIT);
         for (int i = 0; i < receivedPktCnt; i++) {
@@ -165,7 +186,7 @@
         // Verify the first polled state is stored
         assertEquals(mTransformStateInitial, mIpSecPacketLossDetector.getLastTransformState());
         verify(mPacketLossCalculator, never())
-                .getPacketLossRatePercentage(any(), any(), anyString());
+                .getPacketLossRatePercentage(any(), any(), anyInt(), anyString());
 
         // Verify next poll is scheduled
         assertNull(mTestLooper.nextMessage());
@@ -278,7 +299,7 @@
 
         xfrmStateReceiver.onResult(newTransformState(1, 1, newReplayBitmap(1)));
         verify(mPacketLossCalculator, never())
-                .getPacketLossRatePercentage(any(), any(), anyString());
+                .getPacketLossRatePercentage(any(), any(), anyInt(), anyString());
     }
 
     @Test
@@ -289,17 +310,19 @@
 
         xfrmStateReceiver.onError(new RuntimeException("Test"));
         verify(mPacketLossCalculator, never())
-                .getPacketLossRatePercentage(any(), any(), anyString());
+                .getPacketLossRatePercentage(any(), any(), anyInt(), anyString());
     }
 
     private void checkHandleLossRate(
-            int mockPacketLossRate, boolean isLastStateExpectedToUpdate, boolean isCallbackExpected)
+            PacketLossCalculationResult mockPacketLossRate,
+            boolean isLastStateExpectedToUpdate,
+            boolean isCallbackExpected)
             throws Exception {
         final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
                 startMonitorAndCaptureStateReceiver();
         doReturn(mockPacketLossRate)
                 .when(mPacketLossCalculator)
-                .getPacketLossRatePercentage(any(), any(), anyString());
+                .getPacketLossRatePercentage(any(), any(), anyInt(), anyString());
 
         // Mock receiving two states with mTransformStateInitial and an arbitrary transformNew
         final IpSecTransformState transformNew = newTransformState(1, 1, newReplayBitmap(1));
@@ -309,7 +332,10 @@
         // Verifications
         verify(mPacketLossCalculator)
                 .getPacketLossRatePercentage(
-                        eq(mTransformStateInitial), eq(transformNew), anyString());
+                        eq(mTransformStateInitial),
+                        eq(transformNew),
+                        eq(MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED),
+                        anyString());
 
         if (isLastStateExpectedToUpdate) {
             assertEquals(transformNew, mIpSecPacketLossDetector.getLastTransformState());
@@ -327,30 +353,53 @@
     @Test
     public void testHandleLossRate_validationPass() throws Exception {
         checkHandleLossRate(
-                2, true /* isLastStateExpectedToUpdate */, true /* isCallbackExpected */);
+                PacketLossCalculationResult.valid(2),
+                true /* isLastStateExpectedToUpdate */,
+                true /* isCallbackExpected */);
     }
 
     @Test
     public void testHandleLossRate_validationFail() throws Exception {
         checkHandleLossRate(
-                22, true /* isLastStateExpectedToUpdate */, true /* isCallbackExpected */);
+                PacketLossCalculationResult.valid(22),
+                true /* isLastStateExpectedToUpdate */,
+                true /* isCallbackExpected */);
         verify(mConnectivityManager).reportNetworkConnectivity(mNetwork, false);
     }
 
     @Test
     public void testHandleLossRate_resultUnavalaible() throws Exception {
         checkHandleLossRate(
-                PACKET_LOSS_UNAVALAIBLE,
+                PacketLossCalculationResult.invalid(),
                 false /* isLastStateExpectedToUpdate */,
                 false /* isCallbackExpected */);
     }
 
+    @Test
+    public void testHandleLossRate_unusualSeqNumLeap_highLossRate() throws Exception {
+        checkHandleLossRate(
+                PacketLossCalculationResult.unusualSeqNumLeap(22),
+                true /* isLastStateExpectedToUpdate */,
+                false /* isCallbackExpected */);
+    }
+
+    @Test
+    public void testHandleLossRate_unusualSeqNumLeap_lowLossRate() throws Exception {
+        checkHandleLossRate(
+                PacketLossCalculationResult.unusualSeqNumLeap(2),
+                true /* isLastStateExpectedToUpdate */,
+                true /* isCallbackExpected */);
+    }
+
     private void checkGetPacketLossRate(
-            IpSecTransformState oldState, IpSecTransformState newState, int expectedLossRate)
+            IpSecTransformState oldState,
+            IpSecTransformState newState,
+            PacketLossCalculationResult expectedLossRate)
             throws Exception {
         assertEquals(
                 expectedLossRate,
-                mPacketLossCalculator.getPacketLossRatePercentage(oldState, newState, TAG));
+                mPacketLossCalculator.getPacketLossRatePercentage(
+                        oldState, newState, MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED, TAG));
     }
 
     private void checkGetPacketLossRate(
@@ -362,14 +411,45 @@
             throws Exception {
         final IpSecTransformState newState =
                 newTransformState(rxSeqNo, packetCount, newReplayBitmap(packetInWin));
+        checkGetPacketLossRate(
+                oldState, newState, PacketLossCalculationResult.valid(expectedDataLossRate));
+    }
+
+    private void checkGetPacketLossRate(
+            IpSecTransformState oldState,
+            int rxSeqNo,
+            int packetCount,
+            int packetInWin,
+            PacketLossCalculationResult expectedDataLossRate)
+            throws Exception {
+        final IpSecTransformState newState =
+                newTransformState(rxSeqNo, packetCount, newReplayBitmap(packetInWin));
         checkGetPacketLossRate(oldState, newState, expectedDataLossRate);
     }
 
     @Test
     public void testGetPacketLossRate_replayWindowUnchanged() throws Exception {
         checkGetPacketLossRate(
-                mTransformStateInitial, mTransformStateInitial, PACKET_LOSS_UNAVALAIBLE);
-        checkGetPacketLossRate(mTransformStateInitial, 3000, 2000, 2000, PACKET_LOSS_UNAVALAIBLE);
+                mTransformStateInitial,
+                mTransformStateInitial,
+                PacketLossCalculationResult.invalid());
+        checkGetPacketLossRate(
+                mTransformStateInitial, 3000, 2000, 2000, PacketLossCalculationResult.invalid());
+    }
+
+    @Test
+    public void testGetPacketLossRate_expectedPacketNumTooFew() throws Exception {
+        final int oldRxNo = 4096;
+        final int oldPktCnt = 4096;
+        final int pktCntDiff = MIN_VALID_EXPECTED_RX_PACKET_NUM - 1;
+        final byte[] bitmapReceiveAll = newReplayBitmap(4096);
+
+        final IpSecTransformState oldState =
+                newTransformState(oldRxNo, oldPktCnt, bitmapReceiveAll);
+        final IpSecTransformState newState =
+                newTransformState(oldRxNo + pktCntDiff, oldPktCnt + pktCntDiff, bitmapReceiveAll);
+
+        checkGetPacketLossRate(oldState, newState, PacketLossCalculationResult.invalid());
     }
 
     @Test
@@ -419,6 +499,45 @@
         checkGetPacketLossRate(oldState, 20000, 14000, 3000, 10);
     }
 
+    private void checkGetPktLossRate_unusualSeqNumLeap(
+            int maxSeqNumIncreasePerSecond,
+            int timeDiffMillis,
+            int rxSeqNoDiff,
+            PacketLossCalculationResult expected)
+            throws Exception {
+        final IpSecTransformState oldState = mTransformStateInitial;
+        final IpSecTransformState newState =
+                newNextTransformState(
+                        oldState,
+                        timeDiffMillis,
+                        rxSeqNoDiff,
+                        1 /* packtCountDiff */,
+                        1 /* packetInWin */);
+
+        assertEquals(
+                expected,
+                mPacketLossCalculator.getPacketLossRatePercentage(
+                        oldState, newState, maxSeqNumIncreasePerSecond, TAG));
+    }
+
+    @Test
+    public void testGetPktLossRate_unusualSeqNumLeap() throws Exception {
+        checkGetPktLossRate_unusualSeqNumLeap(
+                10000 /* maxSeqNumIncreasePerSecond */,
+                (int) TimeUnit.SECONDS.toMillis(2L),
+                30000 /* rxSeqNoDiff */,
+                PacketLossCalculationResult.unusualSeqNumLeap(100));
+    }
+
+    @Test
+    public void testGetPktLossRate_unusualSeqNumLeap_smallSeqNumDiff() throws Exception {
+        checkGetPktLossRate_unusualSeqNumLeap(
+                10000 /* maxSeqNumIncreasePerSecond */,
+                (int) TimeUnit.SECONDS.toMillis(2L),
+                5000 /* rxSeqNoDiff */,
+                PacketLossCalculationResult.valid(100));
+    }
+
     // Verify the polling event is scheduled with expected delays
     private void verifyPollEventDelayAndScheduleNext(long expectedDelayMs) {
         if (expectedDelayMs > 0) {
@@ -445,4 +564,24 @@
         // Verify the 3rd poll is scheduled with configured delay
         verifyPollEventDelayAndScheduleNext(POLL_IPSEC_STATE_INTERVAL_MS);
     }
+
+    @Test
+    public void testGetMaxSeqNumIncreasePerSecond() throws Exception {
+        final int seqNumLeapNegative = 500_000;
+        when(mCarrierConfig.getInt(
+                        eq(VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY), anyInt()))
+                .thenReturn(seqNumLeapNegative);
+        assertEquals(seqNumLeapNegative, getMaxSeqNumIncreasePerSecond(mCarrierConfig));
+    }
+
+    @Test
+    public void testGetMaxSeqNumIncreasePerSecond_negativeValue() throws Exception {
+        final int seqNumLeapNegative = -10;
+        when(mCarrierConfig.getInt(
+                        eq(VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY), anyInt()))
+                .thenReturn(seqNumLeapNegative);
+        assertEquals(
+                MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED,
+                getMaxSeqNumIncreasePerSecond(mCarrierConfig));
+    }
 }
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
index af6daa1..edad678 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
@@ -107,7 +107,6 @@
     @Mock protected Context mContext;
     @Mock protected Network mNetwork;
     @Mock protected FeatureFlags mFeatureFlags;
-    @Mock protected android.net.platform.flags.FeatureFlags mCoreNetFeatureFlags;
     @Mock protected TelephonySubscriptionSnapshot mSubscriptionSnapshot;
     @Mock protected ConnectivityManager mConnectivityManager;
     @Mock protected TelephonyManager mTelephonyManager;
@@ -123,6 +122,7 @@
 
         mSetFlagsRule.enableFlags(Flags.FLAG_VALIDATE_NETWORK_ON_IPSEC_LOSS);
         mSetFlagsRule.enableFlags(Flags.FLAG_EVALUATE_IPSEC_LOSS_ON_LP_NC_CHANGE);
+        mSetFlagsRule.enableFlags(Flags.FLAG_HANDLE_SEQ_NUM_LEAP);
 
         when(mNetwork.getNetId()).thenReturn(-1);
 
diff --git a/tools/app_metadata_bundles/Android.bp b/tools/app_metadata_bundles/Android.bp
index a012dca..dced50d 100644
--- a/tools/app_metadata_bundles/Android.bp
+++ b/tools/app_metadata_bundles/Android.bp
@@ -13,6 +13,9 @@
     srcs: [
         "src/lib/java/**/*.java",
     ],
+    static_libs: [
+        "guava",
+    ],
 }
 
 java_binary_host {
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java
deleted file mode 100644
index cdb559b..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class AndroidSafetyLabel implements AslMarshallable {
-
-    private final Long mVersion;
-    private final SystemAppSafetyLabel mSystemAppSafetyLabel;
-    private final SafetyLabels mSafetyLabels;
-    private final TransparencyInfo mTransparencyInfo;
-
-    public SafetyLabels getSafetyLabels() {
-        return mSafetyLabels;
-    }
-
-    public AndroidSafetyLabel(
-            Long version,
-            SystemAppSafetyLabel systemAppSafetyLabel,
-            SafetyLabels safetyLabels,
-            TransparencyInfo transparencyInfo) {
-        this.mVersion = version;
-        this.mSystemAppSafetyLabel = systemAppSafetyLabel;
-        this.mSafetyLabels = safetyLabels;
-        this.mTransparencyInfo = transparencyInfo;
-    }
-
-    /** Creates an on-device DOM element from an {@link AndroidSafetyLabel} */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element aslEle = doc.createElement(XmlUtils.OD_TAG_BUNDLE);
-        aslEle.appendChild(XmlUtils.createOdLongEle(doc, XmlUtils.OD_NAME_VERSION, mVersion));
-        if (mSafetyLabels != null) {
-            XmlUtils.appendChildren(aslEle, mSafetyLabels.toOdDomElements(doc));
-        }
-        if (mSystemAppSafetyLabel != null) {
-            XmlUtils.appendChildren(aslEle, mSystemAppSafetyLabel.toOdDomElements(doc));
-        }
-        if (mTransparencyInfo != null) {
-            XmlUtils.appendChildren(aslEle, mTransparencyInfo.toOdDomElements(doc));
-        }
-        return XmlUtils.listOf(aslEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabelFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabelFactory.java
deleted file mode 100644
index 3dc725b..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabelFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class AndroidSafetyLabelFactory implements AslMarshallableFactory<AndroidSafetyLabel> {
-
-    /** Creates an {@link AndroidSafetyLabel} from human-readable DOM element */
-    @Override
-    public AndroidSafetyLabel createFromHrElements(List<Element> appMetadataBundles)
-            throws MalformedXmlException {
-        Element appMetadataBundlesEle = XmlUtils.getSingleElement(appMetadataBundles);
-        long version = XmlUtils.tryGetVersion(appMetadataBundlesEle);
-
-        Element safetyLabelsEle =
-                XmlUtils.getSingleChildElement(
-                        appMetadataBundlesEle, XmlUtils.HR_TAG_SAFETY_LABELS, false);
-        SafetyLabels safetyLabels =
-                new SafetyLabelsFactory().createFromHrElements(XmlUtils.listOf(safetyLabelsEle));
-
-        Element systemAppSafetyLabelEle =
-                XmlUtils.getSingleChildElement(
-                        appMetadataBundlesEle, XmlUtils.HR_TAG_SYSTEM_APP_SAFETY_LABEL, false);
-        SystemAppSafetyLabel systemAppSafetyLabel =
-                new SystemAppSafetyLabelFactory()
-                        .createFromHrElements(XmlUtils.listOf(systemAppSafetyLabelEle));
-
-        Element transparencyInfoEle =
-                XmlUtils.getSingleChildElement(
-                        appMetadataBundlesEle, XmlUtils.HR_TAG_TRANSPARENCY_INFO, false);
-        TransparencyInfo transparencyInfo =
-                new TransparencyInfoFactory()
-                        .createFromHrElements(XmlUtils.listOf(transparencyInfoEle));
-
-        return new AndroidSafetyLabel(
-                version, systemAppSafetyLabel, safetyLabels, transparencyInfo);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AppInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AppInfo.java
deleted file mode 100644
index f94b659..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AppInfo.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-/** AppInfo representation */
-public class AppInfo implements AslMarshallable {
-    private final String mTitle;
-    private final String mDescription;
-    private final Boolean mContainsAds;
-    private final Boolean mObeyAps;
-    private final Boolean mAdsFingerprinting;
-    private final Boolean mSecurityFingerprinting;
-    private final String mPrivacyPolicy;
-    private final List<String> mSecurityEndpoints;
-    private final List<String> mFirstPartyEndpoints;
-    private final List<String> mServiceProviderEndpoints;
-    private final String mCategory;
-    private final String mEmail;
-    private final String mWebsite;
-
-    public AppInfo(
-            String title,
-            String description,
-            Boolean containsAds,
-            Boolean obeyAps,
-            Boolean adsFingerprinting,
-            Boolean securityFingerprinting,
-            String privacyPolicy,
-            List<String> securityEndpoints,
-            List<String> firstPartyEndpoints,
-            List<String> serviceProviderEndpoints,
-            String category,
-            String email,
-            String website) {
-        this.mTitle = title;
-        this.mDescription = description;
-        this.mContainsAds = containsAds;
-        this.mObeyAps = obeyAps;
-        this.mAdsFingerprinting = adsFingerprinting;
-        this.mSecurityFingerprinting = securityFingerprinting;
-        this.mPrivacyPolicy = privacyPolicy;
-        this.mSecurityEndpoints = securityEndpoints;
-        this.mFirstPartyEndpoints = firstPartyEndpoints;
-        this.mServiceProviderEndpoints = serviceProviderEndpoints;
-        this.mCategory = category;
-        this.mEmail = email;
-        this.mWebsite = website;
-    }
-
-    /** Creates an on-device DOM element from the {@link SafetyLabels}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element appInfoEle = XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_APP_INFO);
-        if (this.mTitle != null) {
-            appInfoEle.appendChild(XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_TITLE, mTitle));
-        }
-        if (this.mDescription != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_DESCRIPTION, mDescription));
-        }
-        if (this.mContainsAds != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdBooleanEle(doc, XmlUtils.OD_NAME_CONTAINS_ADS, mContainsAds));
-        }
-        if (this.mObeyAps != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdBooleanEle(doc, XmlUtils.OD_NAME_OBEY_APS, mObeyAps));
-        }
-        if (this.mAdsFingerprinting != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdBooleanEle(
-                            doc, XmlUtils.OD_NAME_ADS_FINGERPRINTING, mAdsFingerprinting));
-        }
-        if (this.mSecurityFingerprinting != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdBooleanEle(
-                            doc,
-                            XmlUtils.OD_NAME_SECURITY_FINGERPRINTING,
-                            mSecurityFingerprinting));
-        }
-        if (this.mPrivacyPolicy != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(
-                            doc, XmlUtils.OD_NAME_PRIVACY_POLICY, mPrivacyPolicy));
-        }
-        if (this.mSecurityEndpoints != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdArray(
-                            doc,
-                            XmlUtils.OD_TAG_STRING_ARRAY,
-                            XmlUtils.OD_NAME_SECURITY_ENDPOINT,
-                            mSecurityEndpoints));
-        }
-        if (this.mFirstPartyEndpoints != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdArray(
-                            doc,
-                            XmlUtils.OD_TAG_STRING_ARRAY,
-                            XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINT,
-                            mFirstPartyEndpoints));
-        }
-        if (this.mServiceProviderEndpoints != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdArray(
-                            doc,
-                            XmlUtils.OD_TAG_STRING_ARRAY,
-                            XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINT,
-                            mServiceProviderEndpoints));
-        }
-        if (this.mCategory != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_CATEGORY, this.mCategory));
-        }
-        if (this.mEmail != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_EMAIL, this.mEmail));
-        }
-        if (this.mWebsite != null) {
-            appInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_WEBSITE, this.mWebsite));
-        }
-        return XmlUtils.listOf(appInfoEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AppInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AppInfoFactory.java
deleted file mode 100644
index 26d94c1..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AppInfoFactory.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class AppInfoFactory implements AslMarshallableFactory<AppInfo> {
-
-    /** Creates a {@link AppInfo} from the human-readable DOM element. */
-    @Override
-    public AppInfo createFromHrElements(List<Element> elements) throws MalformedXmlException {
-        Element appInfoEle = XmlUtils.getSingleElement(elements);
-        if (appInfoEle == null) {
-            AslgenUtil.logI("No AppInfo found in hr format.");
-            return null;
-        }
-
-        String title = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_TITLE);
-        String description = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_DESCRIPTION);
-        Boolean containsAds = XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_CONTAINS_ADS);
-        Boolean obeyAps = XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_OBEY_APS);
-        Boolean adsFingerprinting =
-                XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_ADS_FINGERPRINTING);
-        Boolean securityFingerprinting =
-                XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_SECURITY_FINGERPRINTING);
-        String privacyPolicy = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_PRIVACY_POLICY);
-        List<String> securityEndpoints =
-                Arrays.stream(
-                                appInfoEle
-                                        .getAttribute(XmlUtils.HR_ATTR_SECURITY_ENDPOINTS)
-                                        .split("\\|"))
-                        .toList();
-        List<String> firstPartyEndpoints =
-                Arrays.stream(
-                                appInfoEle
-                                        .getAttribute(XmlUtils.HR_ATTR_FIRST_PARTY_ENDPOINTS)
-                                        .split("\\|"))
-                        .toList();
-        List<String> serviceProviderEndpoints =
-                Arrays.stream(
-                                appInfoEle
-                                        .getAttribute(XmlUtils.HR_ATTR_SERVICE_PROVIDER_ENDPOINTS)
-                                        .split("\\|"))
-                        .toList();
-        String category = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_CATEGORY);
-        String email = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_EMAIL);
-        String website = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_WEBSITE, false);
-
-        return new AppInfo(
-                title,
-                description,
-                containsAds,
-                obeyAps,
-                adsFingerprinting,
-                securityFingerprinting,
-                privacyPolicy,
-                securityEndpoints,
-                firstPartyEndpoints,
-                serviceProviderEndpoints,
-                category,
-                email,
-                website);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslConverter.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslConverter.java
index 9dd5531..191f38d 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslConverter.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslConverter.java
@@ -16,7 +16,10 @@
 
 package com.android.asllib;
 
+import com.android.asllib.marshallable.AndroidSafetyLabel;
+import com.android.asllib.marshallable.AndroidSafetyLabelFactory;
 import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -56,13 +59,16 @@
         switch (format) {
             case HUMAN_READABLE:
                 Element appMetadataBundles =
-                        XmlUtils.getSingleElement(document, XmlUtils.HR_TAG_APP_METADATA_BUNDLES);
+                        XmlUtils.getSingleChildElement(
+                                document, XmlUtils.HR_TAG_APP_METADATA_BUNDLES, true);
 
                 return new AndroidSafetyLabelFactory()
                         .createFromHrElements(XmlUtils.listOf(appMetadataBundles));
             case ON_DEVICE:
-                throw new IllegalArgumentException(
-                        "Parsing from on-device format is not supported at this time.");
+                Element bundleEle =
+                        XmlUtils.getSingleChildElement(document, XmlUtils.OD_TAG_BUNDLE, true);
+                return new AndroidSafetyLabelFactory()
+                        .createFromOdElements(XmlUtils.listOf(bundleEle));
             default:
                 throw new IllegalStateException("Unrecognized input format.");
         }
@@ -85,8 +91,10 @@
 
         switch (format) {
             case HUMAN_READABLE:
-                throw new IllegalArgumentException(
-                        "Outputting human-readable format is not supported at this time.");
+                for (var child : asl.toHrDomElements(document)) {
+                    document.appendChild(child);
+                }
+                break;
             case ON_DEVICE:
                 for (var child : asl.toOdDomElements(document)) {
                     document.appendChild(child);
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslMarshallable.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslMarshallable.java
deleted file mode 100644
index 4e64ab0..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslMarshallable.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public interface AslMarshallable {
-
-    /** Creates the on-device DOM element from the AslMarshallable Java Object. */
-    List<Element> toOdDomElements(Document doc);
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslMarshallableFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslMarshallableFactory.java
deleted file mode 100644
index b8f9f0e..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AslMarshallableFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public interface AslMarshallableFactory<T extends AslMarshallable> {
-
-    /** Creates an {@link AslMarshallableFactory} from human-readable DOM element */
-    T createFromHrElements(List<Element> elements) throws MalformedXmlException;
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategory.java
deleted file mode 100644
index b9e06fb..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategory.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Data usage category representation containing one or more {@link DataType}. Valid category keys
- * are defined in {@link DataCategoryConstants}, each category has a valid set of types {@link
- * DataType}, which are mapped in {@link DataTypeConstants}
- */
-public class DataCategory implements AslMarshallable {
-    private final String mCategoryName;
-    private final Map<String, DataType> mDataTypes;
-
-    public DataCategory(String categoryName, Map<String, DataType> dataTypes) {
-        this.mCategoryName = categoryName;
-        this.mDataTypes = dataTypes;
-    }
-
-    public String getCategoryName() {
-        return mCategoryName;
-    }
-
-    /** Return the type {@link Map} of String type key to {@link DataType} */
-
-    public Map<String, DataType> getDataTypes() {
-        return mDataTypes;
-    }
-
-    /** Creates on-device DOM element(s) from the {@link DataCategory}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element dataCategoryEle = XmlUtils.createPbundleEleWithName(doc, this.getCategoryName());
-        for (DataType dataType : mDataTypes.values()) {
-            XmlUtils.appendChildren(dataCategoryEle, dataType.toOdDomElements(doc));
-        }
-        return XmlUtils.listOf(dataCategoryEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategoryConstants.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategoryConstants.java
deleted file mode 100644
index b364c8b..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategoryConstants.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Constants for determining valid {@link String} data types for usage within {@link SafetyLabels},
- * {@link DataCategory}, and {@link DataType}
- */
-public class DataCategoryConstants {
-
-    public static final String CATEGORY_PERSONAL = "personal";
-    public static final String CATEGORY_FINANCIAL = "financial";
-    public static final String CATEGORY_LOCATION = "location";
-    public static final String CATEGORY_EMAIL_TEXT_MESSAGE = "email_text_message";
-    public static final String CATEGORY_PHOTO_VIDEO = "photo_video";
-    public static final String CATEGORY_AUDIO = "audio";
-    public static final String CATEGORY_STORAGE = "storage";
-    public static final String CATEGORY_HEALTH_FITNESS = "health_fitness";
-    public static final String CATEGORY_CONTACTS = "contacts";
-    public static final String CATEGORY_CALENDAR = "calendar";
-    public static final String CATEGORY_IDENTIFIERS = "identifiers";
-    public static final String CATEGORY_APP_PERFORMANCE = "app_performance";
-    public static final String CATEGORY_ACTIONS_IN_APP = "actions_in_app";
-    public static final String CATEGORY_SEARCH_AND_BROWSING = "search_and_browsing";
-
-    /** Set of valid categories */
-    public static final Set<String> VALID_CATEGORIES =
-            Collections.unmodifiableSet(
-                    new HashSet<>(
-                            Arrays.asList(
-                                    CATEGORY_PERSONAL,
-                                    CATEGORY_FINANCIAL,
-                                    CATEGORY_LOCATION,
-                                    CATEGORY_EMAIL_TEXT_MESSAGE,
-                                    CATEGORY_PHOTO_VIDEO,
-                                    CATEGORY_AUDIO,
-                                    CATEGORY_STORAGE,
-                                    CATEGORY_HEALTH_FITNESS,
-                                    CATEGORY_CONTACTS,
-                                    CATEGORY_CALENDAR,
-                                    CATEGORY_IDENTIFIERS,
-                                    CATEGORY_APP_PERFORMANCE,
-                                    CATEGORY_ACTIONS_IN_APP,
-                                    CATEGORY_SEARCH_AND_BROWSING)));
-
-    /** Returns {@link Set} of valid {@link String} category keys */
-    public static Set<String> getValidDataCategories() {
-        return VALID_CATEGORIES;
-    }
-
-    private DataCategoryConstants() {
-        /* do nothing - hide constructor */
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategoryFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategoryFactory.java
deleted file mode 100644
index d2b6712..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataCategoryFactory.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-public class DataCategoryFactory implements AslMarshallableFactory<DataCategory> {
-    @Override
-    public DataCategory createFromHrElements(List<Element> elements) throws MalformedXmlException {
-        String categoryName = null;
-        Map<String, DataType> dataTypeMap = new LinkedHashMap<String, DataType>();
-        for (Element ele : elements) {
-            categoryName = ele.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY);
-            String dataTypeName = ele.getAttribute(XmlUtils.HR_ATTR_DATA_TYPE);
-            if (!DataTypeConstants.getValidDataTypes().contains(dataTypeName)) {
-                throw new MalformedXmlException(
-                        String.format("Unrecognized data type name: %s", dataTypeName));
-            }
-            dataTypeMap.put(
-                    dataTypeName, new DataTypeFactory().createFromHrElements(XmlUtils.listOf(ele)));
-        }
-
-        return new DataCategory(categoryName, dataTypeMap);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataLabels.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataLabels.java
deleted file mode 100644
index 96ec93c..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataLabels.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Data label representation with data shared and data collected maps containing zero or more {@link
- * DataCategory}
- */
-public class DataLabels implements AslMarshallable {
-    private final Map<String, DataCategory> mDataAccessed;
-    private final Map<String, DataCategory> mDataCollected;
-    private final Map<String, DataCategory> mDataShared;
-
-    public DataLabels(
-            Map<String, DataCategory> dataAccessed,
-            Map<String, DataCategory> dataCollected,
-            Map<String, DataCategory> dataShared) {
-        mDataAccessed = dataAccessed;
-        mDataCollected = dataCollected;
-        mDataShared = dataShared;
-    }
-
-    /**
-     * Returns the data accessed {@link Map} of {@link com.android.asllib.DataCategoryConstants} to
-     * {@link DataCategory}
-     */
-    public Map<String, DataCategory> getDataAccessed() {
-        return mDataAccessed;
-    }
-
-    /**
-     * Returns the data collected {@link Map} of {@link com.android.asllib.DataCategoryConstants} to
-     * {@link DataCategory}
-     */
-    public Map<String, DataCategory> getDataCollected() {
-        return mDataCollected;
-    }
-
-    /**
-     * Returns the data shared {@link Map} of {@link com.android.asllib.DataCategoryConstants} to
-     * {@link DataCategory}
-     */
-    public Map<String, DataCategory> getDataShared() {
-        return mDataShared;
-    }
-
-    /** Gets the on-device DOM element for the {@link DataLabels}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element dataLabelsEle =
-                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_DATA_LABELS);
-
-        maybeAppendDataUsages(doc, dataLabelsEle, mDataCollected, XmlUtils.OD_NAME_DATA_ACCESSED);
-        maybeAppendDataUsages(doc, dataLabelsEle, mDataCollected, XmlUtils.OD_NAME_DATA_COLLECTED);
-        maybeAppendDataUsages(doc, dataLabelsEle, mDataShared, XmlUtils.OD_NAME_DATA_SHARED);
-
-        return XmlUtils.listOf(dataLabelsEle);
-    }
-
-    private void maybeAppendDataUsages(
-            Document doc,
-            Element dataLabelsEle,
-            Map<String, DataCategory> dataCategoriesMap,
-            String dataUsageTypeName) {
-        if (dataCategoriesMap.isEmpty()) {
-            return;
-        }
-        Element dataUsageEle = XmlUtils.createPbundleEleWithName(doc, dataUsageTypeName);
-
-        for (String dataCategoryName : dataCategoriesMap.keySet()) {
-            Element dataCategoryEle = XmlUtils.createPbundleEleWithName(doc, dataCategoryName);
-            DataCategory dataCategory = dataCategoriesMap.get(dataCategoryName);
-            for (String dataTypeName : dataCategory.getDataTypes().keySet()) {
-                DataType dataType = dataCategory.getDataTypes().get(dataTypeName);
-                XmlUtils.appendChildren(dataCategoryEle, dataType.toOdDomElements(doc));
-            }
-            dataUsageEle.appendChild(dataCategoryEle);
-        }
-        dataLabelsEle.appendChild(dataUsageEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataLabelsFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataLabelsFactory.java
deleted file mode 100644
index 79edab7..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataLabelsFactory.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class DataLabelsFactory implements AslMarshallableFactory<DataLabels> {
-
-    /** Creates a {@link DataLabels} from the human-readable DOM element. */
-    @Override
-    public DataLabels createFromHrElements(List<Element> elements) throws MalformedXmlException {
-        Element ele = XmlUtils.getSingleElement(elements);
-        if (ele == null) {
-            AslgenUtil.logI("Found no DataLabels in hr format.");
-            return null;
-        }
-        Map<String, DataCategory> dataAccessed =
-                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_ACCESSED);
-        Map<String, DataCategory> dataCollected =
-                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_COLLECTED);
-        Map<String, DataCategory> dataShared =
-                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_SHARED);
-
-        // Validate booleans such as isCollectionOptional, isSharingOptional.
-        for (DataCategory dataCategory : dataAccessed.values()) {
-            for (DataType dataType : dataCategory.getDataTypes().values()) {
-                if (dataType.getIsSharingOptional() != null) {
-                    throw new MalformedXmlException(
-                            String.format(
-                                    "isSharingOptional was unexpectedly defined on a DataType"
-                                            + " belonging to data accessed: %s",
-                                    dataType.getDataTypeName()));
-                }
-                if (dataType.getIsCollectionOptional() != null) {
-                    throw new MalformedXmlException(
-                            String.format(
-                                    "isCollectionOptional was unexpectedly defined on a DataType"
-                                            + " belonging to data accessed: %s",
-                                    dataType.getDataTypeName()));
-                }
-            }
-        }
-        for (DataCategory dataCategory : dataCollected.values()) {
-            for (DataType dataType : dataCategory.getDataTypes().values()) {
-                if (dataType.getIsSharingOptional() != null) {
-                    throw new MalformedXmlException(
-                            String.format(
-                                    "isSharingOptional was unexpectedly defined on a DataType"
-                                            + " belonging to data collected: %s",
-                                    dataType.getDataTypeName()));
-                }
-            }
-        }
-        for (DataCategory dataCategory : dataShared.values()) {
-            for (DataType dataType : dataCategory.getDataTypes().values()) {
-                if (dataType.getIsCollectionOptional() != null) {
-                    throw new MalformedXmlException(
-                            String.format(
-                                    "isCollectionOptional was unexpectedly defined on a DataType"
-                                            + " belonging to data shared: %s",
-                                    dataType.getDataTypeName()));
-                }
-            }
-        }
-
-        return new DataLabels(dataAccessed, dataCollected, dataShared);
-    }
-
-    private static Map<String, DataCategory> getDataCategoriesWithTag(
-            Element dataLabelsEle, String dataCategoryUsageTypeTag) throws MalformedXmlException {
-        NodeList dataUsedNodeList = dataLabelsEle.getElementsByTagName(dataCategoryUsageTypeTag);
-        Map<String, DataCategory> dataCategoryMap = new LinkedHashMap<String, DataCategory>();
-
-        Set<String> dataCategoryNames = new HashSet<String>();
-        for (int i = 0; i < dataUsedNodeList.getLength(); i++) {
-            Element dataUsedEle = (Element) dataUsedNodeList.item(i);
-            String dataCategoryName = dataUsedEle.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY);
-            if (!DataCategoryConstants.getValidDataCategories().contains(dataCategoryName)) {
-                throw new MalformedXmlException(
-                        String.format("Unrecognized category name: %s", dataCategoryName));
-            }
-            dataCategoryNames.add(dataCategoryName);
-        }
-        for (String dataCategoryName : dataCategoryNames) {
-            var dataCategoryElements =
-                    XmlUtils.asElementList(dataUsedNodeList).stream()
-                            .filter(
-                                    ele ->
-                                            ele.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY)
-                                                    .equals(dataCategoryName))
-                            .toList();
-            DataCategory dataCategory =
-                    new DataCategoryFactory().createFromHrElements(dataCategoryElements);
-            dataCategoryMap.put(dataCategoryName, dataCategory);
-        }
-        return dataCategoryMap;
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataType.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataType.java
deleted file mode 100644
index d011cfe..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataType.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Data usage type representation. Types are specific to a {@link DataCategory} and contains
- * metadata related to the data usage purpose.
- */
-public class DataType implements AslMarshallable {
-
-    public enum Purpose {
-        APP_FUNCTIONALITY(1),
-        ANALYTICS(2),
-        DEVELOPER_COMMUNICATIONS(3),
-        FRAUD_PREVENTION_SECURITY(4),
-        ADVERTISING(5),
-        PERSONALIZATION(6),
-        ACCOUNT_MANAGEMENT(7);
-
-        private final int mValue;
-
-        Purpose(int value) {
-            this.mValue = value;
-        }
-
-        /** Get the int value associated with the Purpose. */
-        public int getValue() {
-            return mValue;
-        }
-
-        /** Get the Purpose associated with the int value. */
-        public static Purpose forValue(int value) {
-            for (Purpose e : values()) {
-                if (e.getValue() == value) {
-                    return e;
-                }
-            }
-            throw new IllegalArgumentException("No Purpose enum for value: " + value);
-        }
-
-        /** Get the Purpose associated with the human-readable String. */
-        public static Purpose forString(String s) {
-            for (Purpose e : values()) {
-                if (e.toString().equals(s)) {
-                    return e;
-                }
-            }
-            throw new IllegalArgumentException("No Purpose enum for str: " + s);
-        }
-
-        /** Human-readable String representation of Purpose. */
-        public String toString() {
-            return this.name().toLowerCase();
-        }
-    }
-
-    private final String mDataTypeName;
-
-    private final List<Purpose> mPurposes;
-    private final Boolean mIsCollectionOptional;
-    private final Boolean mIsSharingOptional;
-    private final Boolean mEphemeral;
-
-    public DataType(
-            String dataTypeName,
-            List<Purpose> purposes,
-            Boolean isCollectionOptional,
-            Boolean isSharingOptional,
-            Boolean ephemeral) {
-        this.mDataTypeName = dataTypeName;
-        this.mPurposes = purposes;
-        this.mIsCollectionOptional = isCollectionOptional;
-        this.mIsSharingOptional = isSharingOptional;
-        this.mEphemeral = ephemeral;
-    }
-
-    public String getDataTypeName() {
-        return mDataTypeName;
-    }
-
-    /**
-     * Returns {@link Set} of valid {@link Integer} purposes for using the associated data category
-     * and type
-     */
-    public List<Purpose> getPurposes() {
-        return mPurposes;
-    }
-
-    /**
-     * For data-collected, returns {@code true} if data usage is user optional and {@code false} if
-     * data usage is required. Should return {@code null} for data-accessed and data-shared.
-     */
-    public Boolean getIsCollectionOptional() {
-        return mIsCollectionOptional;
-    }
-
-    /**
-     * For data-shared, returns {@code true} if data usage is user optional and {@code false} if
-     * data usage is required. Should return {@code null} for data-accessed and data-collected.
-     */
-    public Boolean getIsSharingOptional() {
-        return mIsSharingOptional;
-    }
-
-    /**
-     * For data-collected, returns {@code true} if data usage is user optional and {@code false} if
-     * data usage is processed ephemerally. Should return {@code null} for data-shared.
-     */
-    public Boolean getEphemeral() {
-        return mEphemeral;
-    }
-
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element dataTypeEle = XmlUtils.createPbundleEleWithName(doc, this.getDataTypeName());
-        if (!this.getPurposes().isEmpty()) {
-            dataTypeEle.appendChild(
-                    XmlUtils.createOdArray(
-                            doc,
-                            XmlUtils.OD_TAG_INT_ARRAY,
-                            XmlUtils.OD_NAME_PURPOSES,
-                            this.getPurposes().stream()
-                                    .map(p -> String.valueOf(p.getValue()))
-                                    .toList()));
-        }
-
-        maybeAddBoolToOdElement(
-                doc,
-                dataTypeEle,
-                this.getIsCollectionOptional(),
-                XmlUtils.OD_NAME_IS_COLLECTION_OPTIONAL);
-        maybeAddBoolToOdElement(
-                doc,
-                dataTypeEle,
-                this.getIsSharingOptional(),
-                XmlUtils.OD_NAME_IS_SHARING_OPTIONAL);
-        maybeAddBoolToOdElement(doc, dataTypeEle, this.getEphemeral(), XmlUtils.OD_NAME_EPHEMERAL);
-        return XmlUtils.listOf(dataTypeEle);
-    }
-
-    private static void maybeAddBoolToOdElement(
-            Document doc, Element parentEle, Boolean b, String odName) {
-        if (b == null) {
-            return;
-        }
-        Element ele = XmlUtils.createOdBooleanEle(doc, odName, b);
-        parentEle.appendChild(ele);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataTypeConstants.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataTypeConstants.java
deleted file mode 100644
index a0a7537..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataTypeConstants.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Constants for determining valid {@link String} data types for usage within {@link SafetyLabels},
- * {@link DataCategory}, and {@link DataType}
- */
-public class DataTypeConstants {
-    /** Data types for {@link DataCategoryConstants.CATEGORY_PERSONAL} */
-    public static final String TYPE_NAME = "name";
-
-    public static final String TYPE_EMAIL_ADDRESS = "email_address";
-    public static final String TYPE_PHONE_NUMBER = "phone_number";
-    public static final String TYPE_RACE_ETHNICITY = "race_ethnicity";
-    public static final String TYPE_POLITICAL_OR_RELIGIOUS_BELIEFS =
-            "political_or_religious_beliefs";
-    public static final String TYPE_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY =
-            "sexual_orientation_or_gender_identity";
-    public static final String TYPE_PERSONAL_IDENTIFIERS = "personal_identifiers";
-    public static final String TYPE_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_FINANCIAL} */
-    public static final String TYPE_CARD_BANK_ACCOUNT = "card_bank_account";
-
-    public static final String TYPE_PURCHASE_HISTORY = "purchase_history";
-    public static final String TYPE_CREDIT_SCORE = "credit_score";
-    public static final String TYPE_FINANCIAL_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_LOCATION} */
-    public static final String TYPE_APPROX_LOCATION = "approx_location";
-
-    public static final String TYPE_PRECISE_LOCATION = "precise_location";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_EMAIL_TEXT_MESSAGE} */
-    public static final String TYPE_EMAILS = "emails";
-
-    public static final String TYPE_TEXT_MESSAGES = "text_messages";
-    public static final String TYPE_EMAIL_TEXT_MESSAGE_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_PHOTO_VIDEO} */
-    public static final String TYPE_PHOTOS = "photos";
-
-    public static final String TYPE_VIDEOS = "videos";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_AUDIO} */
-    public static final String TYPE_SOUND_RECORDINGS = "sound_recordings";
-
-    public static final String TYPE_MUSIC_FILES = "music_files";
-    public static final String TYPE_AUDIO_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_STORAGE} */
-    public static final String TYPE_FILES_DOCS = "files_docs";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_HEALTH_FITNESS} */
-    public static final String TYPE_HEALTH = "health";
-
-    public static final String TYPE_FITNESS = "fitness";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_CONTACTS} */
-    public static final String TYPE_CONTACTS = "contacts";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_CALENDAR} */
-    public static final String TYPE_CALENDAR = "calendar";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_IDENTIFIERS} */
-    public static final String TYPE_IDENTIFIERS_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_APP_PERFORMANCE} */
-    public static final String TYPE_CRASH_LOGS = "crash_logs";
-
-    public static final String TYPE_PERFORMANCE_DIAGNOSTICS = "performance_diagnostics";
-    public static final String TYPE_APP_PERFORMANCE_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_ACTIONS_IN_APP} */
-    public static final String TYPE_USER_INTERACTION = "user_interaction";
-
-    public static final String TYPE_IN_APP_SEARCH_HISTORY = "in_app_search_history";
-    public static final String TYPE_INSTALLED_APPS = "installed_apps";
-    public static final String TYPE_USER_GENERATED_CONTENT = "user_generated_content";
-    public static final String TYPE_ACTIONS_IN_APP_OTHER = "other";
-
-    /** Data types for {@link DataCategoryConstants.CATEGORY_SEARCH_AND_BROWSING} */
-    public static final String TYPE_WEB_BROWSING_HISTORY = "web_browsing_history";
-
-    /** Set of valid categories */
-    public static final Set<String> VALID_TYPES =
-            Collections.unmodifiableSet(
-                    new HashSet<>(
-                            Arrays.asList(
-                                    TYPE_NAME,
-                                    TYPE_EMAIL_ADDRESS,
-                                    TYPE_PHONE_NUMBER,
-                                    TYPE_RACE_ETHNICITY,
-                                    TYPE_POLITICAL_OR_RELIGIOUS_BELIEFS,
-                                    TYPE_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY,
-                                    TYPE_PERSONAL_IDENTIFIERS,
-                                    TYPE_OTHER,
-                                    TYPE_CARD_BANK_ACCOUNT,
-                                    TYPE_PURCHASE_HISTORY,
-                                    TYPE_CREDIT_SCORE,
-                                    TYPE_FINANCIAL_OTHER,
-                                    TYPE_APPROX_LOCATION,
-                                    TYPE_PRECISE_LOCATION,
-                                    TYPE_EMAILS,
-                                    TYPE_TEXT_MESSAGES,
-                                    TYPE_EMAIL_TEXT_MESSAGE_OTHER,
-                                    TYPE_PHOTOS,
-                                    TYPE_VIDEOS,
-                                    TYPE_SOUND_RECORDINGS,
-                                    TYPE_MUSIC_FILES,
-                                    TYPE_AUDIO_OTHER,
-                                    TYPE_FILES_DOCS,
-                                    TYPE_HEALTH,
-                                    TYPE_FITNESS,
-                                    TYPE_CONTACTS,
-                                    TYPE_CALENDAR,
-                                    TYPE_IDENTIFIERS_OTHER,
-                                    TYPE_CRASH_LOGS,
-                                    TYPE_PERFORMANCE_DIAGNOSTICS,
-                                    TYPE_APP_PERFORMANCE_OTHER,
-                                    TYPE_USER_INTERACTION,
-                                    TYPE_IN_APP_SEARCH_HISTORY,
-                                    TYPE_INSTALLED_APPS,
-                                    TYPE_USER_GENERATED_CONTENT,
-                                    TYPE_ACTIONS_IN_APP_OTHER,
-                                    TYPE_WEB_BROWSING_HISTORY)));
-
-    /** Returns {@link Set} of valid {@link String} category keys */
-    public static Set<String> getValidDataTypes() {
-        return VALID_TYPES;
-    }
-
-    private DataTypeConstants() {
-        /* do nothing - hide constructor */
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataTypeFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataTypeFactory.java
deleted file mode 100644
index 27c1b59..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DataTypeFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Element;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public class DataTypeFactory implements AslMarshallableFactory<DataType> {
-    /** Creates a {@link DataType} from the human-readable DOM element. */
-    @Override
-    public DataType createFromHrElements(List<Element> elements) {
-        Element hrDataTypeEle = XmlUtils.getSingleElement(elements);
-        String dataTypeName = hrDataTypeEle.getAttribute(XmlUtils.HR_ATTR_DATA_TYPE);
-        List<DataType.Purpose> purposes =
-                Arrays.stream(hrDataTypeEle.getAttribute(XmlUtils.HR_ATTR_PURPOSES).split("\\|"))
-                        .map(DataType.Purpose::forString)
-                        .collect(Collectors.toList());
-        Boolean isCollectionOptional =
-                XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_IS_COLLECTION_OPTIONAL);
-        Boolean isSharingOptional =
-                XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_IS_SHARING_OPTIONAL);
-        Boolean ephemeral = XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_EPHEMERAL);
-        return new DataType(
-                dataTypeName, purposes, isCollectionOptional, isSharingOptional, ephemeral);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DeveloperInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DeveloperInfo.java
deleted file mode 100644
index 44a5b12..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DeveloperInfo.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-/** DeveloperInfo representation */
-public class DeveloperInfo implements AslMarshallable {
-    public enum DeveloperRelationship {
-        OEM(0),
-        ODM(1),
-        SOC(2),
-        OTA(3),
-        CARRIER(4),
-        AOSP(5),
-        OTHER(6);
-
-        private final int mValue;
-
-        DeveloperRelationship(int value) {
-            this.mValue = value;
-        }
-
-        /** Get the int value associated with the DeveloperRelationship. */
-        public int getValue() {
-            return mValue;
-        }
-
-        /** Get the DeveloperRelationship associated with the int value. */
-        public static DeveloperInfo.DeveloperRelationship forValue(int value) {
-            for (DeveloperInfo.DeveloperRelationship e : values()) {
-                if (e.getValue() == value) {
-                    return e;
-                }
-            }
-            throw new IllegalArgumentException("No DeveloperRelationship enum for value: " + value);
-        }
-
-        /** Get the DeveloperRelationship associated with the human-readable String. */
-        public static DeveloperInfo.DeveloperRelationship forString(String s) {
-            for (DeveloperInfo.DeveloperRelationship e : values()) {
-                if (e.toString().equals(s)) {
-                    return e;
-                }
-            }
-            throw new IllegalArgumentException("No DeveloperRelationship enum for str: " + s);
-        }
-
-        /** Human-readable String representation of DeveloperRelationship. */
-        public String toString() {
-            return this.name().toLowerCase();
-        }
-    }
-
-    private final String mName;
-    private final String mEmail;
-    private final String mAddress;
-    private final String mCountryRegion;
-    private final DeveloperRelationship mDeveloperRelationship;
-    private final String mWebsite;
-    private final String mAppDeveloperRegistryId;
-
-    public DeveloperInfo(
-            String name,
-            String email,
-            String address,
-            String countryRegion,
-            DeveloperRelationship developerRelationship,
-            String website,
-            String appDeveloperRegistryId) {
-        this.mName = name;
-        this.mEmail = email;
-        this.mAddress = address;
-        this.mCountryRegion = countryRegion;
-        this.mDeveloperRelationship = developerRelationship;
-        this.mWebsite = website;
-        this.mAppDeveloperRegistryId = appDeveloperRegistryId;
-    }
-
-    /** Creates an on-device DOM element from the {@link SafetyLabels}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element developerInfoEle =
-                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_DEVELOPER_INFO);
-        if (mName != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_NAME, mName));
-        }
-        if (mEmail != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_EMAIL, mEmail));
-        }
-        if (mAddress != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_ADDRESS, mAddress));
-        }
-        if (mCountryRegion != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(
-                            doc, XmlUtils.OD_NAME_COUNTRY_REGION, mCountryRegion));
-        }
-        if (mDeveloperRelationship != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdLongEle(
-                            doc,
-                            XmlUtils.OD_NAME_DEVELOPER_RELATIONSHIP,
-                            mDeveloperRelationship.getValue()));
-        }
-        if (mWebsite != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_WEBSITE, mWebsite));
-        }
-        if (mAppDeveloperRegistryId != null) {
-            developerInfoEle.appendChild(
-                    XmlUtils.createOdStringEle(
-                            doc,
-                            XmlUtils.OD_NAME_APP_DEVELOPER_REGISTRY_ID,
-                            mAppDeveloperRegistryId));
-        }
-
-        return XmlUtils.listOf(developerInfoEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DeveloperInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DeveloperInfoFactory.java
deleted file mode 100644
index 4961892..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/DeveloperInfoFactory.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class DeveloperInfoFactory implements AslMarshallableFactory<DeveloperInfo> {
-
-    /** Creates a {@link DeveloperInfo} from the human-readable DOM element. */
-    @Override
-    public DeveloperInfo createFromHrElements(List<Element> elements) throws MalformedXmlException {
-        Element developerInfoEle = XmlUtils.getSingleElement(elements);
-        if (developerInfoEle == null) {
-            AslgenUtil.logI("No DeveloperInfo found in hr format.");
-            return null;
-        }
-        String name = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_NAME);
-        String email = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_EMAIL);
-        String address = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_ADDRESS);
-        String countryRegion =
-                XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_COUNTRY_REGION);
-        DeveloperInfo.DeveloperRelationship developerRelationship =
-                DeveloperInfo.DeveloperRelationship.forString(
-                        XmlUtils.getStringAttr(
-                                developerInfoEle, XmlUtils.HR_ATTR_DEVELOPER_RELATIONSHIP));
-        String website = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_WEBSITE, false);
-        String appDeveloperRegistryId =
-                XmlUtils.getStringAttr(
-                        developerInfoEle, XmlUtils.HR_ATTR_APP_DEVELOPER_REGISTRY_ID, false);
-
-        return new DeveloperInfo(
-                name,
-                email,
-                address,
-                countryRegion,
-                developerRelationship,
-                website,
-                appDeveloperRegistryId);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SafetyLabels.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SafetyLabels.java
deleted file mode 100644
index 40ef48d..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SafetyLabels.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-/** Safety Label representation containing zero or more {@link DataCategory} for data shared */
-public class SafetyLabels implements AslMarshallable {
-
-    private final Long mVersion;
-    private final DataLabels mDataLabels;
-
-    public SafetyLabels(Long version, DataLabels dataLabels) {
-        this.mVersion = version;
-        this.mDataLabels = dataLabels;
-    }
-
-    /** Returns the data label for the safety label */
-    public DataLabels getDataLabel() {
-        return mDataLabels;
-    }
-
-    /** Gets the version of the {@link SafetyLabels}. */
-    public Long getVersion() {
-        return mVersion;
-    }
-
-    /** Creates an on-device DOM element from the {@link SafetyLabels}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element safetyLabelsEle =
-                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_SAFETY_LABELS);
-        safetyLabelsEle.appendChild(
-                XmlUtils.createOdLongEle(doc, XmlUtils.OD_NAME_VERSION, mVersion));
-        if (mDataLabels != null) {
-            XmlUtils.appendChildren(safetyLabelsEle, mDataLabels.toOdDomElements(doc));
-        }
-        return XmlUtils.listOf(safetyLabelsEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SafetyLabelsFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SafetyLabelsFactory.java
deleted file mode 100644
index ab81b1d..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SafetyLabelsFactory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class SafetyLabelsFactory implements AslMarshallableFactory<SafetyLabels> {
-
-    /** Creates a {@link SafetyLabels} from the human-readable DOM element. */
-    @Override
-    public SafetyLabels createFromHrElements(List<Element> elements) throws MalformedXmlException {
-        Element safetyLabelsEle = XmlUtils.getSingleElement(elements);
-        if (safetyLabelsEle == null) {
-            AslgenUtil.logI("No SafetyLabels found in hr format.");
-            return null;
-        }
-        long version = XmlUtils.tryGetVersion(safetyLabelsEle);
-
-        DataLabels dataLabels =
-                new DataLabelsFactory()
-                        .createFromHrElements(
-                                XmlUtils.listOf(
-                                        XmlUtils.getSingleChildElement(
-                                                safetyLabelsEle, XmlUtils.HR_TAG_DATA_LABELS)));
-        return new SafetyLabels(version, dataLabels);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SystemAppSafetyLabel.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SystemAppSafetyLabel.java
deleted file mode 100644
index 93d9c2b..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SystemAppSafetyLabel.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-/** Safety Label representation containing zero or more {@link DataCategory} for data shared */
-public class SystemAppSafetyLabel implements AslMarshallable {
-
-    private final String mUrl;
-
-    public SystemAppSafetyLabel(String url) {
-        this.mUrl = url;
-    }
-
-    /** Returns the system app safety label URL. */
-    public String getUrl() {
-        return mUrl;
-    }
-
-    /** Creates an on-device DOM element from the {@link SystemAppSafetyLabel}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element systemAppSafetyLabelEle =
-                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_SYSTEM_APP_SAFETY_LABEL);
-        systemAppSafetyLabelEle.appendChild(
-                XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_URL, mUrl));
-        return XmlUtils.listOf(systemAppSafetyLabelEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SystemAppSafetyLabelFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SystemAppSafetyLabelFactory.java
deleted file mode 100644
index c8c1c7b..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/SystemAppSafetyLabelFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class SystemAppSafetyLabelFactory implements AslMarshallableFactory<SystemAppSafetyLabel> {
-
-    /** Creates a {@link SystemAppSafetyLabel} from the human-readable DOM element. */
-    @Override
-    public SystemAppSafetyLabel createFromHrElements(List<Element> elements)
-            throws MalformedXmlException {
-        Element systemAppSafetyLabelEle = XmlUtils.getSingleElement(elements);
-        if (systemAppSafetyLabelEle == null) {
-            AslgenUtil.logI("No SystemAppSafetyLabel found in hr format.");
-            return null;
-        }
-
-        String url = XmlUtils.getStringAttr(systemAppSafetyLabelEle, XmlUtils.HR_ATTR_URL);
-        return new SystemAppSafetyLabel(url);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/TransparencyInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/TransparencyInfo.java
deleted file mode 100644
index 88717b9..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/TransparencyInfo.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-/** TransparencyInfo representation containing {@link DeveloperInfo} and {@link AppInfo} */
-public class TransparencyInfo implements AslMarshallable {
-
-    private final DeveloperInfo mDeveloperInfo;
-    private final AppInfo mAppInfo;
-
-    public TransparencyInfo(DeveloperInfo developerInfo, AppInfo appInfo) {
-        this.mDeveloperInfo = developerInfo;
-        this.mAppInfo = appInfo;
-    }
-
-    /** Gets the {@link DeveloperInfo} of the {@link TransparencyInfo}. */
-    public DeveloperInfo getDeveloperInfo() {
-        return mDeveloperInfo;
-    }
-
-    /** Gets the {@link AppInfo} of the {@link TransparencyInfo}. */
-    public AppInfo getAppInfo() {
-        return mAppInfo;
-    }
-
-    /** Creates an on-device DOM element from the {@link TransparencyInfo}. */
-    @Override
-    public List<Element> toOdDomElements(Document doc) {
-        Element transparencyInfoEle =
-                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_TRANSPARENCY_INFO);
-        if (mDeveloperInfo != null) {
-            XmlUtils.appendChildren(transparencyInfoEle, mDeveloperInfo.toOdDomElements(doc));
-        }
-        if (mAppInfo != null) {
-            XmlUtils.appendChildren(transparencyInfoEle, mAppInfo.toOdDomElements(doc));
-        }
-        return XmlUtils.listOf(transparencyInfoEle);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/TransparencyInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/TransparencyInfoFactory.java
deleted file mode 100644
index 13a7eb6..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/TransparencyInfoFactory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class TransparencyInfoFactory implements AslMarshallableFactory<TransparencyInfo> {
-
-    /** Creates a {@link TransparencyInfo} from the human-readable DOM element. */
-    @Override
-    public TransparencyInfo createFromHrElements(List<Element> elements)
-            throws MalformedXmlException {
-        Element transparencyInfoEle = XmlUtils.getSingleElement(elements);
-        if (transparencyInfoEle == null) {
-            AslgenUtil.logI("No TransparencyInfo found in hr format.");
-            return null;
-        }
-
-        Element developerInfoEle =
-                XmlUtils.getSingleChildElement(
-                        transparencyInfoEle, XmlUtils.HR_TAG_DEVELOPER_INFO, false);
-        DeveloperInfo developerInfo =
-                new DeveloperInfoFactory().createFromHrElements(XmlUtils.listOf(developerInfoEle));
-
-        Element appInfoEle =
-                XmlUtils.getSingleChildElement(
-                        transparencyInfoEle, XmlUtils.HR_TAG_APP_INFO, false);
-        AppInfo appInfo = new AppInfoFactory().createFromHrElements(XmlUtils.listOf(appInfoEle));
-
-        return new TransparencyInfo(developerInfo, appInfo);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java
deleted file mode 100644
index cc8fe79..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.asllib;
-
-import com.android.asllib.util.MalformedXmlException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class XmlUtils {
-    public static final String HR_TAG_APP_METADATA_BUNDLES = "app-metadata-bundles";
-    public static final String HR_TAG_SYSTEM_APP_SAFETY_LABEL = "system-app-safety-label";
-    public static final String HR_TAG_SAFETY_LABELS = "safety-labels";
-    public static final String HR_TAG_TRANSPARENCY_INFO = "transparency-info";
-    public static final String HR_TAG_DEVELOPER_INFO = "developer-info";
-    public static final String HR_TAG_APP_INFO = "app-info";
-    public static final String HR_TAG_DATA_LABELS = "data-labels";
-    public static final String HR_TAG_DATA_ACCESSED = "data-accessed";
-    public static final String HR_TAG_DATA_COLLECTED = "data-collected";
-    public static final String HR_TAG_DATA_SHARED = "data-shared";
-    public static final String HR_ATTR_NAME = "name";
-    public static final String HR_ATTR_EMAIL = "email";
-    public static final String HR_ATTR_ADDRESS = "address";
-    public static final String HR_ATTR_COUNTRY_REGION = "countryRegion";
-    public static final String HR_ATTR_DEVELOPER_RELATIONSHIP = "relationship";
-    public static final String HR_ATTR_WEBSITE = "website";
-    public static final String HR_ATTR_APP_DEVELOPER_REGISTRY_ID = "registryId";
-    public static final String HR_ATTR_DATA_CATEGORY = "dataCategory";
-    public static final String HR_ATTR_DATA_TYPE = "dataType";
-    public static final String HR_ATTR_IS_COLLECTION_OPTIONAL = "isCollectionOptional";
-    public static final String HR_ATTR_IS_SHARING_OPTIONAL = "isSharingOptional";
-    public static final String HR_ATTR_EPHEMERAL = "ephemeral";
-    public static final String HR_ATTR_PURPOSES = "purposes";
-    public static final String HR_ATTR_VERSION = "version";
-    public static final String HR_ATTR_URL = "url";
-    public static final String HR_ATTR_TITLE = "title";
-    public static final String HR_ATTR_DESCRIPTION = "description";
-    public static final String HR_ATTR_CONTAINS_ADS = "containsAds";
-    public static final String HR_ATTR_OBEY_APS = "obeyAps";
-    public static final String HR_ATTR_ADS_FINGERPRINTING = "adsFingerprinting";
-    public static final String HR_ATTR_SECURITY_FINGERPRINTING = "securityFingerprinting";
-    public static final String HR_ATTR_PRIVACY_POLICY = "privacyPolicy";
-    public static final String HR_ATTR_SECURITY_ENDPOINTS = "securityEndpoints";
-    public static final String HR_ATTR_FIRST_PARTY_ENDPOINTS = "firstPartyEndpoints";
-    public static final String HR_ATTR_SERVICE_PROVIDER_ENDPOINTS = "serviceProviderEndpoints";
-    public static final String HR_ATTR_CATEGORY = "category";
-
-    public static final String OD_TAG_BUNDLE = "bundle";
-    public static final String OD_TAG_PBUNDLE_AS_MAP = "pbundle_as_map";
-    public static final String OD_TAG_BOOLEAN = "boolean";
-    public static final String OD_TAG_LONG = "long";
-    public static final String OD_TAG_STRING = "string";
-    public static final String OD_TAG_INT_ARRAY = "int-array";
-    public static final String OD_TAG_STRING_ARRAY = "string-array";
-    public static final String OD_TAG_ITEM = "item";
-    public static final String OD_ATTR_NAME = "name";
-    public static final String OD_ATTR_VALUE = "value";
-    public static final String OD_ATTR_NUM = "num";
-    public static final String OD_NAME_SAFETY_LABELS = "safety_labels";
-    public static final String OD_NAME_TRANSPARENCY_INFO = "transparency_info";
-    public static final String OD_NAME_DEVELOPER_INFO = "developer_info";
-    public static final String OD_NAME_NAME = "name";
-    public static final String OD_NAME_EMAIL = "email";
-    public static final String OD_NAME_ADDRESS = "address";
-    public static final String OD_NAME_COUNTRY_REGION = "country_region";
-    public static final String OD_NAME_DEVELOPER_RELATIONSHIP = "relationship";
-    public static final String OD_NAME_WEBSITE = "website";
-    public static final String OD_NAME_APP_DEVELOPER_REGISTRY_ID = "app_developer_registry_id";
-    public static final String OD_NAME_APP_INFO = "app_info";
-    public static final String OD_NAME_TITLE = "title";
-    public static final String OD_NAME_DESCRIPTION = "description";
-    public static final String OD_NAME_CONTAINS_ADS = "contains_ads";
-    public static final String OD_NAME_OBEY_APS = "obey_aps";
-    public static final String OD_NAME_ADS_FINGERPRINTING = "ads_fingerprinting";
-    public static final String OD_NAME_SECURITY_FINGERPRINTING = "security_fingerprinting";
-    public static final String OD_NAME_PRIVACY_POLICY = "privacy_policy";
-    public static final String OD_NAME_SECURITY_ENDPOINT = "security_endpoint";
-    public static final String OD_NAME_FIRST_PARTY_ENDPOINT = "first_party_endpoint";
-    public static final String OD_NAME_SERVICE_PROVIDER_ENDPOINT = "service_provider_endpoint";
-    public static final String OD_NAME_CATEGORY = "category";
-    public static final String OD_NAME_VERSION = "version";
-    public static final String OD_NAME_URL = "url";
-    public static final String OD_NAME_SYSTEM_APP_SAFETY_LABEL = "system_app_safety_label";
-    public static final String OD_NAME_DATA_LABELS = "data_labels";
-    public static final String OD_NAME_DATA_ACCESSED = "data_accessed";
-    public static final String OD_NAME_DATA_COLLECTED = "data_collected";
-    public static final String OD_NAME_DATA_SHARED = "data_shared";
-    public static final String OD_NAME_PURPOSES = "purposes";
-    public static final String OD_NAME_IS_COLLECTION_OPTIONAL = "is_collection_optional";
-    public static final String OD_NAME_IS_SHARING_OPTIONAL = "is_sharing_optional";
-    public static final String OD_NAME_EPHEMERAL = "ephemeral";
-
-    public static final String TRUE_STR = "true";
-    public static final String FALSE_STR = "false";
-
-    /** Gets the single top-level {@link Element} having the {@param tagName}. */
-    public static Element getSingleElement(Document doc, String tagName)
-            throws MalformedXmlException {
-        var elements = doc.getElementsByTagName(tagName);
-        return getSingleElement(elements, tagName);
-    }
-
-    /**
-     * Gets the single {@link Element} within {@param parentEle} and having the {@param tagName}.
-     */
-    public static Element getSingleChildElement(Element parentEle, String tagName)
-            throws MalformedXmlException {
-        var elements = parentEle.getElementsByTagName(tagName);
-        return getSingleElement(elements, tagName, true);
-    }
-
-    /**
-     * Gets the single {@link Element} within {@param parentEle} and having the {@param tagName}.
-     */
-    public static Element getSingleChildElement(Element parentEle, String tagName, boolean required)
-            throws MalformedXmlException {
-        var elements = parentEle.getElementsByTagName(tagName);
-        return getSingleElement(elements, tagName, required);
-    }
-
-    /** Gets the single {@link Element} from {@param elements} */
-    public static Element getSingleElement(NodeList elements, String tagName)
-            throws MalformedXmlException {
-        return getSingleElement(elements, tagName, true);
-    }
-
-    /** Gets the single {@link Element} from {@param elements} */
-    public static Element getSingleElement(NodeList elements, String tagName, boolean required)
-            throws MalformedXmlException {
-        if (elements.getLength() > 1) {
-            throw new MalformedXmlException(
-                    String.format(
-                            "Expected 1 element \"%s\" in NodeList but got %s.",
-                            tagName, elements.getLength()));
-        } else if (elements.getLength() == 0) {
-            if (required) {
-                throw new MalformedXmlException(
-                        String.format("Found no element \"%s\" in NodeList.", tagName));
-            } else {
-                return null;
-            }
-        }
-        var elementAsNode = elements.item(0);
-        if (!(elementAsNode instanceof Element)) {
-            throw new MalformedXmlException(
-                    String.format("%s was not a valid XML element.", tagName));
-        }
-        return ((Element) elementAsNode);
-    }
-
-    /** Gets the single {@link Element} within {@param elements}. */
-    public static Element getSingleElement(List<Element> elements) {
-        if (elements.size() != 1) {
-            throw new IllegalStateException(
-                    String.format("Expected 1 element in list but got %s.", elements.size()));
-        }
-        return elements.get(0);
-    }
-
-    /** Converts {@param nodeList} into List of {@link Element}. */
-    public static List<Element> asElementList(NodeList nodeList) {
-        List<Element> elementList = new ArrayList<Element>();
-        for (int i = 0; i < nodeList.getLength(); i++) {
-            var elementAsNode = nodeList.item(i);
-            if (elementAsNode instanceof Element) {
-                elementList.add(((Element) elementAsNode));
-            }
-        }
-        return elementList;
-    }
-
-    /** Appends {@param children} to the {@param ele}. */
-    public static void appendChildren(Element ele, List<Element> children) {
-        for (Element c : children) {
-            ele.appendChild(c);
-        }
-    }
-
-    /** Gets the Boolean from the String value. */
-    private static Boolean fromString(String s) {
-        if (s == null) {
-            return null;
-        }
-        if (s.equals(TRUE_STR)) {
-            return true;
-        } else if (s.equals(FALSE_STR)) {
-            return false;
-        }
-        return null;
-    }
-
-    /** Creates an on-device PBundle DOM Element with the given attribute name. */
-    public static Element createPbundleEleWithName(Document doc, String name) {
-        var ele = doc.createElement(XmlUtils.OD_TAG_PBUNDLE_AS_MAP);
-        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
-        return ele;
-    }
-
-    /** Create an on-device Boolean DOM Element with the given attribute name. */
-    public static Element createOdBooleanEle(Document doc, String name, boolean b) {
-        var ele = doc.createElement(XmlUtils.OD_TAG_BOOLEAN);
-        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
-        ele.setAttribute(XmlUtils.OD_ATTR_VALUE, String.valueOf(b));
-        return ele;
-    }
-
-    /** Create an on-device Long DOM Element with the given attribute name. */
-    public static Element createOdLongEle(Document doc, String name, long l) {
-        var ele = doc.createElement(XmlUtils.OD_TAG_LONG);
-        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
-        ele.setAttribute(XmlUtils.OD_ATTR_VALUE, String.valueOf(l));
-        return ele;
-    }
-
-    /** Create an on-device Long DOM Element with the given attribute name. */
-    public static Element createOdStringEle(Document doc, String name, String val) {
-        var ele = doc.createElement(XmlUtils.OD_TAG_STRING);
-        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
-        ele.setAttribute(XmlUtils.OD_ATTR_VALUE, val);
-        return ele;
-    }
-
-    /** Create OD style array DOM Element, which can represent any time but is stored as Strings. */
-    public static Element createOdArray(
-            Document doc, String arrayTag, String arrayName, List<String> arrayVals) {
-        Element arrEle = doc.createElement(arrayTag);
-        arrEle.setAttribute(XmlUtils.OD_ATTR_NAME, arrayName);
-        arrEle.setAttribute(XmlUtils.OD_ATTR_NUM, String.valueOf(arrayVals.size()));
-        for (String s : arrayVals) {
-            Element itemEle = doc.createElement(XmlUtils.OD_TAG_ITEM);
-            itemEle.setAttribute(XmlUtils.OD_ATTR_VALUE, s);
-            arrEle.appendChild(itemEle);
-        }
-        return arrEle;
-    }
-
-    /** Returns whether the String is null or empty. */
-    public static boolean isNullOrEmpty(String s) {
-        return s == null || s.isEmpty();
-    }
-
-    /** Tries getting required version attribute and throws exception if it doesn't exist */
-    public static Long tryGetVersion(Element ele) {
-        long version;
-        try {
-            version = Long.parseLong(ele.getAttribute(XmlUtils.HR_ATTR_VERSION));
-        } catch (Exception e) {
-            throw new IllegalArgumentException(
-                    String.format(
-                            "Malformed or missing required version in: %s", ele.getTagName()));
-        }
-        return version;
-    }
-
-    /** Gets an optional Boolean attribute. */
-    public static Boolean getBoolAttr(Element ele, String attrName) {
-        return XmlUtils.fromString(ele.getAttribute(attrName));
-    }
-
-    /** Gets a required String attribute. */
-    public static String getStringAttr(Element ele, String attrName) throws MalformedXmlException {
-        return getStringAttr(ele, attrName, true);
-    }
-
-    /** Gets a String attribute; throws exception if required and non-existent. */
-    public static String getStringAttr(Element ele, String attrName, boolean required)
-            throws MalformedXmlException {
-        String s = ele.getAttribute(attrName);
-        if (isNullOrEmpty(s)) {
-            if (required) {
-                throw new MalformedXmlException(
-                        String.format(
-                                "Malformed or missing required %s in: %s",
-                                attrName, ele.getTagName()));
-            } else {
-                return null;
-            }
-        }
-        return s;
-    }
-
-    /**
-     * Utility method for making a List from one element, to support easier refactoring if needed.
-     * For example, List.of() doesn't support null elements.
-     */
-    public static List<Element> listOf(Element e) {
-        return Arrays.asList(e);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AndroidSafetyLabel.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AndroidSafetyLabel.java
new file mode 100644
index 0000000..72140a1
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AndroidSafetyLabel.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class AndroidSafetyLabel implements AslMarshallable {
+
+    private final Long mVersion;
+    private final SystemAppSafetyLabel mSystemAppSafetyLabel;
+    private final SafetyLabels mSafetyLabels;
+    private final TransparencyInfo mTransparencyInfo;
+
+    public SafetyLabels getSafetyLabels() {
+        return mSafetyLabels;
+    }
+
+    public AndroidSafetyLabel(
+            Long version,
+            SystemAppSafetyLabel systemAppSafetyLabel,
+            SafetyLabels safetyLabels,
+            TransparencyInfo transparencyInfo) {
+        this.mVersion = version;
+        this.mSystemAppSafetyLabel = systemAppSafetyLabel;
+        this.mSafetyLabels = safetyLabels;
+        this.mTransparencyInfo = transparencyInfo;
+    }
+
+    /** Creates an on-device DOM element from an {@link AndroidSafetyLabel} */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element aslEle = doc.createElement(XmlUtils.OD_TAG_BUNDLE);
+        aslEle.appendChild(XmlUtils.createOdLongEle(doc, XmlUtils.OD_NAME_VERSION, mVersion));
+        if (mSafetyLabels != null) {
+            XmlUtils.appendChildren(aslEle, mSafetyLabels.toOdDomElements(doc));
+        }
+        if (mSystemAppSafetyLabel != null) {
+            XmlUtils.appendChildren(aslEle, mSystemAppSafetyLabel.toOdDomElements(doc));
+        }
+        if (mTransparencyInfo != null) {
+            XmlUtils.appendChildren(aslEle, mTransparencyInfo.toOdDomElements(doc));
+        }
+        return XmlUtils.listOf(aslEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element aslEle = doc.createElement(XmlUtils.HR_TAG_APP_METADATA_BUNDLES);
+        aslEle.setAttribute(XmlUtils.HR_ATTR_VERSION, String.valueOf(mVersion));
+        if (mSafetyLabels != null) {
+            XmlUtils.appendChildren(aslEle, mSafetyLabels.toHrDomElements(doc));
+        }
+        if (mSystemAppSafetyLabel != null) {
+            XmlUtils.appendChildren(aslEle, mSystemAppSafetyLabel.toHrDomElements(doc));
+        }
+        if (mTransparencyInfo != null) {
+            XmlUtils.appendChildren(aslEle, mTransparencyInfo.toHrDomElements(doc));
+        }
+        return XmlUtils.listOf(aslEle);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AndroidSafetyLabelFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AndroidSafetyLabelFactory.java
new file mode 100644
index 0000000..c53cbbf
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AndroidSafetyLabelFactory.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class AndroidSafetyLabelFactory implements AslMarshallableFactory<AndroidSafetyLabel> {
+
+    /** Creates an {@link AndroidSafetyLabel} from human-readable DOM element */
+    @Override
+    public AndroidSafetyLabel createFromHrElements(List<Element> appMetadataBundles)
+            throws MalformedXmlException {
+        Element appMetadataBundlesEle = XmlUtils.getSingleElement(appMetadataBundles);
+        long version = XmlUtils.tryGetVersion(appMetadataBundlesEle);
+
+        Element safetyLabelsEle =
+                XmlUtils.getSingleChildElement(
+                        appMetadataBundlesEle, XmlUtils.HR_TAG_SAFETY_LABELS, false);
+        SafetyLabels safetyLabels =
+                new SafetyLabelsFactory().createFromHrElements(XmlUtils.listOf(safetyLabelsEle));
+
+        Element systemAppSafetyLabelEle =
+                XmlUtils.getSingleChildElement(
+                        appMetadataBundlesEle, XmlUtils.HR_TAG_SYSTEM_APP_SAFETY_LABEL, false);
+        SystemAppSafetyLabel systemAppSafetyLabel =
+                new SystemAppSafetyLabelFactory()
+                        .createFromHrElements(XmlUtils.listOf(systemAppSafetyLabelEle));
+
+        Element transparencyInfoEle =
+                XmlUtils.getSingleChildElement(
+                        appMetadataBundlesEle, XmlUtils.HR_TAG_TRANSPARENCY_INFO, false);
+        TransparencyInfo transparencyInfo =
+                new TransparencyInfoFactory()
+                        .createFromHrElements(XmlUtils.listOf(transparencyInfoEle));
+
+        return new AndroidSafetyLabel(
+                version, systemAppSafetyLabel, safetyLabels, transparencyInfo);
+    }
+
+    /** Creates an {@link AndroidSafetyLabel} from on-device DOM elements */
+    @Override
+    public AndroidSafetyLabel createFromOdElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element bundleEle = XmlUtils.getSingleElement(elements);
+        Long version = XmlUtils.getOdLongEle(bundleEle, XmlUtils.OD_NAME_VERSION, true);
+
+        Element safetyLabelsEle =
+                XmlUtils.getOdPbundleWithName(bundleEle, XmlUtils.OD_NAME_SAFETY_LABELS, false);
+        SafetyLabels safetyLabels =
+                new SafetyLabelsFactory().createFromOdElements(XmlUtils.listOf(safetyLabelsEle));
+
+        Element systemAppSafetyLabelEle =
+                XmlUtils.getOdPbundleWithName(
+                        bundleEle, XmlUtils.OD_NAME_SYSTEM_APP_SAFETY_LABEL, false);
+        SystemAppSafetyLabel systemAppSafetyLabel =
+                new SystemAppSafetyLabelFactory()
+                        .createFromOdElements(XmlUtils.listOf(systemAppSafetyLabelEle));
+
+        Element transparencyInfoEle =
+                XmlUtils.getOdPbundleWithName(bundleEle, XmlUtils.OD_NAME_TRANSPARENCY_INFO, false);
+        TransparencyInfo transparencyInfo =
+                new TransparencyInfoFactory()
+                        .createFromOdElements(XmlUtils.listOf(transparencyInfoEle));
+
+        return new AndroidSafetyLabel(
+                version, systemAppSafetyLabel, safetyLabels, transparencyInfo);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java
new file mode 100644
index 0000000..129733e
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** AppInfo representation */
+public class AppInfo implements AslMarshallable {
+    private final String mTitle;
+    private final String mDescription;
+    private final Boolean mContainsAds;
+    private final Boolean mObeyAps;
+    private final Boolean mAdsFingerprinting;
+    private final Boolean mSecurityFingerprinting;
+    private final String mPrivacyPolicy;
+    private final List<String> mSecurityEndpoints;
+    private final List<String> mFirstPartyEndpoints;
+    private final List<String> mServiceProviderEndpoints;
+    private final String mCategory;
+    private final String mEmail;
+    private final String mWebsite;
+
+    public AppInfo(
+            String title,
+            String description,
+            Boolean containsAds,
+            Boolean obeyAps,
+            Boolean adsFingerprinting,
+            Boolean securityFingerprinting,
+            String privacyPolicy,
+            List<String> securityEndpoints,
+            List<String> firstPartyEndpoints,
+            List<String> serviceProviderEndpoints,
+            String category,
+            String email,
+            String website) {
+        this.mTitle = title;
+        this.mDescription = description;
+        this.mContainsAds = containsAds;
+        this.mObeyAps = obeyAps;
+        this.mAdsFingerprinting = adsFingerprinting;
+        this.mSecurityFingerprinting = securityFingerprinting;
+        this.mPrivacyPolicy = privacyPolicy;
+        this.mSecurityEndpoints = securityEndpoints;
+        this.mFirstPartyEndpoints = firstPartyEndpoints;
+        this.mServiceProviderEndpoints = serviceProviderEndpoints;
+        this.mCategory = category;
+        this.mEmail = email;
+        this.mWebsite = website;
+    }
+
+    /** Creates an on-device DOM element from the {@link SafetyLabels}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element appInfoEle = XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_APP_INFO);
+        if (this.mTitle != null) {
+            appInfoEle.appendChild(XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_TITLE, mTitle));
+        }
+        if (this.mDescription != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_DESCRIPTION, mDescription));
+        }
+        if (this.mContainsAds != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdBooleanEle(doc, XmlUtils.OD_NAME_CONTAINS_ADS, mContainsAds));
+        }
+        if (this.mObeyAps != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdBooleanEle(doc, XmlUtils.OD_NAME_OBEY_APS, mObeyAps));
+        }
+        if (this.mAdsFingerprinting != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdBooleanEle(
+                            doc, XmlUtils.OD_NAME_ADS_FINGERPRINTING, mAdsFingerprinting));
+        }
+        if (this.mSecurityFingerprinting != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdBooleanEle(
+                            doc,
+                            XmlUtils.OD_NAME_SECURITY_FINGERPRINTING,
+                            mSecurityFingerprinting));
+        }
+        if (this.mPrivacyPolicy != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(
+                            doc, XmlUtils.OD_NAME_PRIVACY_POLICY, mPrivacyPolicy));
+        }
+        if (this.mSecurityEndpoints != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdArray(
+                            doc,
+                            XmlUtils.OD_TAG_STRING_ARRAY,
+                            XmlUtils.OD_NAME_SECURITY_ENDPOINT,
+                            mSecurityEndpoints));
+        }
+        if (this.mFirstPartyEndpoints != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdArray(
+                            doc,
+                            XmlUtils.OD_TAG_STRING_ARRAY,
+                            XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINT,
+                            mFirstPartyEndpoints));
+        }
+        if (this.mServiceProviderEndpoints != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdArray(
+                            doc,
+                            XmlUtils.OD_TAG_STRING_ARRAY,
+                            XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINT,
+                            mServiceProviderEndpoints));
+        }
+        if (this.mCategory != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_CATEGORY, this.mCategory));
+        }
+        if (this.mEmail != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_EMAIL, this.mEmail));
+        }
+        if (this.mWebsite != null) {
+            appInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_WEBSITE, this.mWebsite));
+        }
+        return XmlUtils.listOf(appInfoEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element appInfoEle = doc.createElement(XmlUtils.HR_TAG_APP_INFO);
+        if (this.mTitle != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_TITLE, this.mTitle);
+        }
+        if (this.mDescription != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_DESCRIPTION, this.mDescription);
+        }
+        if (this.mContainsAds != null) {
+            appInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_CONTAINS_ADS, String.valueOf(this.mContainsAds));
+        }
+        if (this.mObeyAps != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_OBEY_APS, String.valueOf(this.mObeyAps));
+        }
+        if (this.mAdsFingerprinting != null) {
+            appInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_ADS_FINGERPRINTING, String.valueOf(this.mAdsFingerprinting));
+        }
+        if (this.mSecurityFingerprinting != null) {
+            appInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_SECURITY_FINGERPRINTING,
+                    String.valueOf(this.mSecurityFingerprinting));
+        }
+        if (this.mPrivacyPolicy != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_PRIVACY_POLICY, this.mPrivacyPolicy);
+        }
+        if (this.mSecurityEndpoints != null) {
+            appInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_SECURITY_ENDPOINTS, String.join("|", this.mSecurityEndpoints));
+        }
+        if (this.mFirstPartyEndpoints != null) {
+            appInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_FIRST_PARTY_ENDPOINTS,
+                    String.join("|", this.mFirstPartyEndpoints));
+        }
+        if (this.mServiceProviderEndpoints != null) {
+            appInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_SERVICE_PROVIDER_ENDPOINTS,
+                    String.join("|", this.mServiceProviderEndpoints));
+        }
+        if (this.mCategory != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_CATEGORY, this.mCategory);
+        }
+        if (this.mEmail != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_EMAIL, this.mEmail);
+        }
+        if (this.mWebsite != null) {
+            appInfoEle.setAttribute(XmlUtils.HR_ATTR_WEBSITE, this.mWebsite);
+        }
+        return XmlUtils.listOf(appInfoEle);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java
new file mode 100644
index 0000000..c506961
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class AppInfoFactory implements AslMarshallableFactory<AppInfo> {
+
+    /** Creates a {@link AppInfo} from the human-readable DOM element. */
+    @Override
+    public AppInfo createFromHrElements(List<Element> elements) throws MalformedXmlException {
+        Element appInfoEle = XmlUtils.getSingleElement(elements);
+        if (appInfoEle == null) {
+            AslgenUtil.logI("No AppInfo found in hr format.");
+            return null;
+        }
+
+        String title = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_TITLE, true);
+        String description = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_DESCRIPTION, true);
+        Boolean containsAds = XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_CONTAINS_ADS, true);
+        Boolean obeyAps = XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_OBEY_APS, true);
+        Boolean adsFingerprinting =
+                XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_ADS_FINGERPRINTING, true);
+        Boolean securityFingerprinting =
+                XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_SECURITY_FINGERPRINTING, true);
+        String privacyPolicy =
+                XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_PRIVACY_POLICY, true);
+        List<String> securityEndpoints =
+                XmlUtils.getPipelineSplitAttr(
+                        appInfoEle, XmlUtils.HR_ATTR_SECURITY_ENDPOINTS, true);
+        List<String> firstPartyEndpoints =
+                XmlUtils.getPipelineSplitAttr(
+                        appInfoEle, XmlUtils.HR_ATTR_FIRST_PARTY_ENDPOINTS, true);
+        List<String> serviceProviderEndpoints =
+                XmlUtils.getPipelineSplitAttr(
+                        appInfoEle, XmlUtils.HR_ATTR_SERVICE_PROVIDER_ENDPOINTS, true);
+        String category = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_CATEGORY, true);
+        String email = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_EMAIL, true);
+        String website = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_WEBSITE, false);
+
+        return new AppInfo(
+                title,
+                description,
+                containsAds,
+                obeyAps,
+                adsFingerprinting,
+                securityFingerprinting,
+                privacyPolicy,
+                securityEndpoints,
+                firstPartyEndpoints,
+                serviceProviderEndpoints,
+                category,
+                email,
+                website);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public AppInfo createFromOdElements(List<Element> elements) throws MalformedXmlException {
+        Element appInfoEle = XmlUtils.getSingleElement(elements);
+        if (appInfoEle == null) {
+            AslgenUtil.logI("No AppInfo found in od format.");
+            return null;
+        }
+
+        String title = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_TITLE, true);
+        String description =
+                XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_DESCRIPTION, true);
+        Boolean containsAds =
+                XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_CONTAINS_ADS, true);
+        Boolean obeyAps = XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_OBEY_APS, true);
+        Boolean adsFingerprinting =
+                XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_ADS_FINGERPRINTING, true);
+        Boolean securityFingerprinting =
+                XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_SECURITY_FINGERPRINTING, true);
+        String privacyPolicy =
+                XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_PRIVACY_POLICY, true);
+        List<String> securityEndpoints =
+                XmlUtils.getOdStringArray(appInfoEle, XmlUtils.OD_NAME_SECURITY_ENDPOINT, true);
+        List<String> firstPartyEndpoints =
+                XmlUtils.getOdStringArray(appInfoEle, XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINT, true);
+        List<String> serviceProviderEndpoints =
+                XmlUtils.getOdStringArray(
+                        appInfoEle, XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINT, true);
+        String category = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_CATEGORY, true);
+        String email = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_EMAIL, true);
+        String website = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_WEBSITE, false);
+
+        return new AppInfo(
+                title,
+                description,
+                containsAds,
+                obeyAps,
+                adsFingerprinting,
+                securityFingerprinting,
+                privacyPolicy,
+                securityEndpoints,
+                firstPartyEndpoints,
+                serviceProviderEndpoints,
+                category,
+                email,
+                website);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AslMarshallable.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AslMarshallable.java
new file mode 100644
index 0000000..0a70e7d0
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AslMarshallable.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public interface AslMarshallable {
+
+    /** Creates the on-device DOM elements from the AslMarshallable Java Object. */
+    List<Element> toOdDomElements(Document doc);
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    List<Element> toHrDomElements(Document doc);
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AslMarshallableFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AslMarshallableFactory.java
new file mode 100644
index 0000000..3958290
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AslMarshallableFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.MalformedXmlException;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public interface AslMarshallableFactory<T extends AslMarshallable> {
+
+    /** Creates an {@link AslMarshallableFactory} from human-readable DOM elements */
+    T createFromHrElements(List<Element> elements) throws MalformedXmlException;
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    T createFromOdElements(List<Element> elements) throws MalformedXmlException;
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataCategory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataCategory.java
new file mode 100644
index 0000000..d551953
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataCategory.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.DataCategoryConstants;
+import com.android.asllib.util.DataTypeConstants;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data usage category representation containing one or more {@link DataType}. Valid category keys
+ * are defined in {@link DataCategoryConstants}, each category has a valid set of types {@link
+ * DataType}, which are mapped in {@link DataTypeConstants}
+ */
+public class DataCategory implements AslMarshallable {
+    private final String mCategoryName;
+    private final Map<String, DataType> mDataTypes;
+
+    public DataCategory(String categoryName, Map<String, DataType> dataTypes) {
+        this.mCategoryName = categoryName;
+        this.mDataTypes = dataTypes;
+    }
+
+    public String getCategoryName() {
+        return mCategoryName;
+    }
+
+    /** Return the type {@link Map} of String type key to {@link DataType} */
+
+    public Map<String, DataType> getDataTypes() {
+        return mDataTypes;
+    }
+
+    /** Creates on-device DOM element(s) from the {@link DataCategory}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element dataCategoryEle = XmlUtils.createPbundleEleWithName(doc, this.getCategoryName());
+        for (DataType dataType : mDataTypes.values()) {
+            XmlUtils.appendChildren(dataCategoryEle, dataType.toOdDomElements(doc));
+        }
+        return XmlUtils.listOf(dataCategoryEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        throw new IllegalStateException(
+                "Turning DataCategory or DataType into human-readable DOM elements requires"
+                        + " visibility into parent elements. The logic resides in DataLabels.");
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataCategoryFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataCategoryFactory.java
new file mode 100644
index 0000000..90424fe
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataCategoryFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.DataTypeConstants;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DataCategoryFactory implements AslMarshallableFactory<DataCategory> {
+    @Override
+    public DataCategory createFromHrElements(List<Element> elements) throws MalformedXmlException {
+        String categoryName = null;
+        Map<String, DataType> dataTypeMap = new LinkedHashMap<String, DataType>();
+        for (Element ele : elements) {
+            categoryName = XmlUtils.getStringAttr(ele, XmlUtils.HR_ATTR_DATA_CATEGORY, true);
+            String dataTypeName = XmlUtils.getStringAttr(ele, XmlUtils.HR_ATTR_DATA_TYPE, true);
+            if (!DataTypeConstants.getValidDataTypes().containsKey(categoryName)) {
+                throw new MalformedXmlException(
+                        String.format("Unrecognized data category %s", categoryName));
+            }
+            if (!DataTypeConstants.getValidDataTypes().get(categoryName).contains(dataTypeName)) {
+                throw new MalformedXmlException(
+                        String.format(
+                                "Unrecognized data type name %s for category %s",
+                                dataTypeName, categoryName));
+            }
+            dataTypeMap.put(
+                    dataTypeName, new DataTypeFactory().createFromHrElements(XmlUtils.listOf(ele)));
+        }
+
+        return new DataCategory(categoryName, dataTypeMap);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public DataCategory createFromOdElements(List<Element> elements) throws MalformedXmlException {
+        Element dataCategoryEle = XmlUtils.getSingleElement(elements);
+        Map<String, DataType> dataTypeMap = new LinkedHashMap<String, DataType>();
+        String categoryName = dataCategoryEle.getAttribute(XmlUtils.OD_ATTR_NAME);
+        var odDataTypes = XmlUtils.asElementList(dataCategoryEle.getChildNodes());
+        for (Element odDataTypeEle : odDataTypes) {
+            String dataTypeName = odDataTypeEle.getAttribute(XmlUtils.OD_ATTR_NAME);
+            if (!DataTypeConstants.getValidDataTypes().containsKey(categoryName)) {
+                throw new MalformedXmlException(
+                        String.format("Unrecognized data category %s", categoryName));
+            }
+            if (!DataTypeConstants.getValidDataTypes().get(categoryName).contains(dataTypeName)) {
+                throw new MalformedXmlException(
+                        String.format(
+                                "Unrecognized data type name %s for category %s",
+                                dataTypeName, categoryName));
+            }
+            dataTypeMap.put(
+                    dataTypeName,
+                    new DataTypeFactory().createFromOdElements(XmlUtils.listOf(odDataTypeEle)));
+        }
+
+        return new DataCategory(categoryName, dataTypeMap);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataLabels.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataLabels.java
new file mode 100644
index 0000000..4a0d759
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataLabels.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.DataCategoryConstants;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data label representation with data shared and data collected maps containing zero or more {@link
+ * DataCategory}
+ */
+public class DataLabels implements AslMarshallable {
+    private final Map<String, DataCategory> mDataAccessed;
+    private final Map<String, DataCategory> mDataCollected;
+    private final Map<String, DataCategory> mDataShared;
+
+    public DataLabels(
+            Map<String, DataCategory> dataAccessed,
+            Map<String, DataCategory> dataCollected,
+            Map<String, DataCategory> dataShared) {
+        mDataAccessed = dataAccessed;
+        mDataCollected = dataCollected;
+        mDataShared = dataShared;
+    }
+
+    /**
+     * Returns the data accessed {@link Map} of {@link DataCategoryConstants} to {@link
+     * DataCategory}
+     */
+    public Map<String, DataCategory> getDataAccessed() {
+        return mDataAccessed;
+    }
+
+    /**
+     * Returns the data collected {@link Map} of {@link DataCategoryConstants} to {@link
+     * DataCategory}
+     */
+    public Map<String, DataCategory> getDataCollected() {
+        return mDataCollected;
+    }
+
+    /**
+     * Returns the data shared {@link Map} of {@link DataCategoryConstants} to {@link DataCategory}
+     */
+    public Map<String, DataCategory> getDataShared() {
+        return mDataShared;
+    }
+
+    /** Gets the on-device DOM element for the {@link DataLabels}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element dataLabelsEle =
+                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_DATA_LABELS);
+
+        maybeAppendDataUsages(doc, dataLabelsEle, mDataAccessed, XmlUtils.OD_NAME_DATA_ACCESSED);
+        maybeAppendDataUsages(doc, dataLabelsEle, mDataCollected, XmlUtils.OD_NAME_DATA_COLLECTED);
+        maybeAppendDataUsages(doc, dataLabelsEle, mDataShared, XmlUtils.OD_NAME_DATA_SHARED);
+
+        return XmlUtils.listOf(dataLabelsEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element dataLabelsEle = doc.createElement(XmlUtils.HR_TAG_DATA_LABELS);
+        maybeAppendHrDataUsages(doc, dataLabelsEle, mDataAccessed, XmlUtils.HR_TAG_DATA_ACCESSED);
+        maybeAppendHrDataUsages(doc, dataLabelsEle, mDataCollected, XmlUtils.HR_TAG_DATA_COLLECTED);
+        maybeAppendHrDataUsages(doc, dataLabelsEle, mDataShared, XmlUtils.HR_TAG_DATA_SHARED);
+        return XmlUtils.listOf(dataLabelsEle);
+    }
+
+    private void maybeAppendDataUsages(
+            Document doc,
+            Element dataLabelsEle,
+            Map<String, DataCategory> dataCategoriesMap,
+            String dataUsageTypeName) {
+        if (dataCategoriesMap.isEmpty()) {
+            return;
+        }
+        Element dataUsageEle = XmlUtils.createPbundleEleWithName(doc, dataUsageTypeName);
+
+        for (String dataCategoryName : dataCategoriesMap.keySet()) {
+            Element dataCategoryEle = XmlUtils.createPbundleEleWithName(doc, dataCategoryName);
+            DataCategory dataCategory = dataCategoriesMap.get(dataCategoryName);
+            for (String dataTypeName : dataCategory.getDataTypes().keySet()) {
+                DataType dataType = dataCategory.getDataTypes().get(dataTypeName);
+                XmlUtils.appendChildren(dataCategoryEle, dataType.toOdDomElements(doc));
+            }
+            dataUsageEle.appendChild(dataCategoryEle);
+        }
+        dataLabelsEle.appendChild(dataUsageEle);
+    }
+
+    private void maybeAppendHrDataUsages(
+            Document doc,
+            Element dataLabelsEle,
+            Map<String, DataCategory> dataCategoriesMap,
+            String dataUsageTypeName) {
+        if (dataCategoriesMap.isEmpty()) {
+            return;
+        }
+        for (String dataCategoryName : dataCategoriesMap.keySet()) {
+            DataCategory dataCategory = dataCategoriesMap.get(dataCategoryName);
+            for (String dataTypeName : dataCategory.getDataTypes().keySet()) {
+                DataType dataType = dataCategory.getDataTypes().get(dataTypeName);
+                // XmlUtils.appendChildren(dataLabelsEle, dataType.toHrDomElements(doc));
+                Element hrDataTypeEle = doc.createElement(dataUsageTypeName);
+                hrDataTypeEle.setAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY, dataCategoryName);
+                hrDataTypeEle.setAttribute(XmlUtils.HR_ATTR_DATA_TYPE, dataTypeName);
+                XmlUtils.maybeSetHrBoolAttr(
+                        hrDataTypeEle,
+                        XmlUtils.HR_ATTR_IS_COLLECTION_OPTIONAL,
+                        dataType.getIsCollectionOptional());
+                XmlUtils.maybeSetHrBoolAttr(
+                        hrDataTypeEle,
+                        XmlUtils.HR_ATTR_IS_SHARING_OPTIONAL,
+                        dataType.getIsSharingOptional());
+                XmlUtils.maybeSetHrBoolAttr(
+                        hrDataTypeEle, XmlUtils.HR_ATTR_EPHEMERAL, dataType.getEphemeral());
+                hrDataTypeEle.setAttribute(
+                        XmlUtils.HR_ATTR_PURPOSES,
+                        String.join(
+                                "|",
+                                dataType.getPurposes().stream()
+                                        .map(DataType.Purpose::toString)
+                                        .toList()));
+                dataLabelsEle.appendChild(hrDataTypeEle);
+            }
+        }
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataLabelsFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataLabelsFactory.java
new file mode 100644
index 0000000..5473e01
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataLabelsFactory.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.DataCategoryConstants;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class DataLabelsFactory implements AslMarshallableFactory<DataLabels> {
+
+    /** Creates a {@link DataLabels} from the human-readable DOM element. */
+    @Override
+    public DataLabels createFromHrElements(List<Element> elements) throws MalformedXmlException {
+        Element ele = XmlUtils.getSingleElement(elements);
+        if (ele == null) {
+            AslgenUtil.logI("Found no DataLabels in hr format.");
+            return null;
+        }
+        Map<String, DataCategory> dataAccessed =
+                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_ACCESSED);
+        Map<String, DataCategory> dataCollected =
+                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_COLLECTED);
+        Map<String, DataCategory> dataShared =
+                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_SHARED);
+        DataLabels dataLabels = new DataLabels(dataAccessed, dataCollected, dataShared);
+        validateIsXOptional(dataLabels);
+        return dataLabels;
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public DataLabels createFromOdElements(List<Element> elements) throws MalformedXmlException {
+        Element dataLabelsEle = XmlUtils.getSingleElement(elements);
+        if (dataLabelsEle == null) {
+            AslgenUtil.logI("Found no DataLabels in od format.");
+            return null;
+        }
+        Map<String, DataCategory> dataAccessed =
+                getOdDataCategoriesWithTag(dataLabelsEle, XmlUtils.OD_NAME_DATA_ACCESSED);
+        Map<String, DataCategory> dataCollected =
+                getOdDataCategoriesWithTag(dataLabelsEle, XmlUtils.OD_NAME_DATA_COLLECTED);
+        Map<String, DataCategory> dataShared =
+                getOdDataCategoriesWithTag(dataLabelsEle, XmlUtils.OD_NAME_DATA_SHARED);
+        DataLabels dataLabels = new DataLabels(dataAccessed, dataCollected, dataShared);
+        validateIsXOptional(dataLabels);
+        return dataLabels;
+    }
+
+    private static Map<String, DataCategory> getOdDataCategoriesWithTag(
+            Element dataLabelsEle, String dataCategoryUsageTypeTag) throws MalformedXmlException {
+        Map<String, DataCategory> dataCategoryMap = new LinkedHashMap<String, DataCategory>();
+        Element dataUsageEle =
+                XmlUtils.getOdPbundleWithName(dataLabelsEle, dataCategoryUsageTypeTag, false);
+        if (dataUsageEle == null) {
+            return dataCategoryMap;
+        }
+        List<Element> dataCategoryEles = XmlUtils.asElementList(dataUsageEle.getChildNodes());
+        for (Element dataCategoryEle : dataCategoryEles) {
+            String dataCategoryName = dataCategoryEle.getAttribute(XmlUtils.OD_ATTR_NAME);
+            DataCategory dataCategory =
+                    new DataCategoryFactory().createFromOdElements(List.of(dataCategoryEle));
+            dataCategoryMap.put(dataCategoryName, dataCategory);
+        }
+        return dataCategoryMap;
+    }
+
+    private static Map<String, DataCategory> getDataCategoriesWithTag(
+            Element dataLabelsEle, String dataCategoryUsageTypeTag) throws MalformedXmlException {
+        List<Element> dataUsedElements =
+                XmlUtils.getChildrenByTagName(dataLabelsEle, dataCategoryUsageTypeTag);
+        Map<String, DataCategory> dataCategoryMap = new LinkedHashMap<String, DataCategory>();
+
+        Set<String> dataCategoryNames = new HashSet<String>();
+        for (int i = 0; i < dataUsedElements.size(); i++) {
+            Element dataUsedEle = dataUsedElements.get(i);
+            String dataCategoryName = dataUsedEle.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY);
+            if (!DataCategoryConstants.getValidDataCategories().contains(dataCategoryName)) {
+                throw new MalformedXmlException(
+                        String.format("Unrecognized category name: %s", dataCategoryName));
+            }
+            dataCategoryNames.add(dataCategoryName);
+        }
+        for (String dataCategoryName : dataCategoryNames) {
+            var dataCategoryElements =
+                    dataUsedElements.stream()
+                            .filter(
+                                    ele ->
+                                            ele.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY)
+                                                    .equals(dataCategoryName))
+                            .toList();
+            DataCategory dataCategory =
+                    new DataCategoryFactory().createFromHrElements(dataCategoryElements);
+            dataCategoryMap.put(dataCategoryName, dataCategory);
+        }
+        return dataCategoryMap;
+    }
+
+    private void validateIsXOptional(DataLabels dataLabels) throws MalformedXmlException {
+        // Validate booleans such as isCollectionOptional, isSharingOptional.
+        for (DataCategory dataCategory : dataLabels.getDataAccessed().values()) {
+            for (DataType dataType : dataCategory.getDataTypes().values()) {
+                if (dataType.getIsSharingOptional() != null) {
+                    throw new MalformedXmlException(
+                            String.format(
+                                    "isSharingOptional was unexpectedly defined on a DataType"
+                                            + " belonging to data accessed: %s",
+                                    dataType.getDataTypeName()));
+                }
+                if (dataType.getIsCollectionOptional() != null) {
+                    throw new MalformedXmlException(
+                            String.format(
+                                    "isCollectionOptional was unexpectedly defined on a DataType"
+                                            + " belonging to data accessed: %s",
+                                    dataType.getDataTypeName()));
+                }
+            }
+        }
+        for (DataCategory dataCategory : dataLabels.getDataCollected().values()) {
+            for (DataType dataType : dataCategory.getDataTypes().values()) {
+                if (dataType.getIsSharingOptional() != null) {
+                    throw new MalformedXmlException(
+                            String.format(
+                                    "isSharingOptional was unexpectedly defined on a DataType"
+                                            + " belonging to data collected: %s",
+                                    dataType.getDataTypeName()));
+                }
+            }
+        }
+        for (DataCategory dataCategory : dataLabels.getDataShared().values()) {
+            for (DataType dataType : dataCategory.getDataTypes().values()) {
+                if (dataType.getIsCollectionOptional() != null) {
+                    throw new MalformedXmlException(
+                            String.format(
+                                    "isCollectionOptional was unexpectedly defined on a DataType"
+                                            + " belonging to data shared: %s",
+                                    dataType.getDataTypeName()));
+                }
+            }
+        }
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataType.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataType.java
new file mode 100644
index 0000000..97304cb
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataType.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Data usage type representation. Types are specific to a {@link DataCategory} and contains
+ * metadata related to the data usage purpose.
+ */
+public class DataType implements AslMarshallable {
+
+    public enum Purpose {
+        APP_FUNCTIONALITY(1),
+        ANALYTICS(2),
+        DEVELOPER_COMMUNICATIONS(3),
+        FRAUD_PREVENTION_SECURITY(4),
+        ADVERTISING(5),
+        PERSONALIZATION(6),
+        ACCOUNT_MANAGEMENT(7);
+
+        private final int mValue;
+
+        Purpose(int value) {
+            this.mValue = value;
+        }
+
+        /** Get the int value associated with the Purpose. */
+        public int getValue() {
+            return mValue;
+        }
+
+        /** Get the Purpose associated with the int value. */
+        public static Purpose forValue(int value) {
+            for (Purpose e : values()) {
+                if (e.getValue() == value) {
+                    return e;
+                }
+            }
+            throw new IllegalArgumentException("No Purpose enum for value: " + value);
+        }
+
+        /** Get the Purpose associated with the human-readable String. */
+        public static Purpose forString(String s) {
+            for (Purpose e : values()) {
+                if (e.toString().equals(s)) {
+                    return e;
+                }
+            }
+            throw new IllegalArgumentException("No Purpose enum for str: " + s);
+        }
+
+        /** Human-readable String representation of Purpose. */
+        public String toString() {
+            return this.name().toLowerCase();
+        }
+    }
+
+    private final String mDataTypeName;
+
+    private final List<Purpose> mPurposes;
+    private final Boolean mIsCollectionOptional;
+    private final Boolean mIsSharingOptional;
+    private final Boolean mEphemeral;
+
+    public DataType(
+            String dataTypeName,
+            List<Purpose> purposes,
+            Boolean isCollectionOptional,
+            Boolean isSharingOptional,
+            Boolean ephemeral) {
+        this.mDataTypeName = dataTypeName;
+        this.mPurposes = purposes;
+        this.mIsCollectionOptional = isCollectionOptional;
+        this.mIsSharingOptional = isSharingOptional;
+        this.mEphemeral = ephemeral;
+    }
+
+    public String getDataTypeName() {
+        return mDataTypeName;
+    }
+
+    /**
+     * Returns {@link Set} of valid {@link Integer} purposes for using the associated data category
+     * and type
+     */
+    public List<Purpose> getPurposes() {
+        return mPurposes;
+    }
+
+    /**
+     * For data-collected, returns {@code true} if data usage is user optional and {@code false} if
+     * data usage is required. Should return {@code null} for data-accessed and data-shared.
+     */
+    public Boolean getIsCollectionOptional() {
+        return mIsCollectionOptional;
+    }
+
+    /**
+     * For data-shared, returns {@code true} if data usage is user optional and {@code false} if
+     * data usage is required. Should return {@code null} for data-accessed and data-collected.
+     */
+    public Boolean getIsSharingOptional() {
+        return mIsSharingOptional;
+    }
+
+    /**
+     * For data-collected, returns {@code true} if data usage is user optional and {@code false} if
+     * data usage is processed ephemerally. Should return {@code null} for data-shared.
+     */
+    public Boolean getEphemeral() {
+        return mEphemeral;
+    }
+
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element dataTypeEle = XmlUtils.createPbundleEleWithName(doc, this.getDataTypeName());
+        if (!this.getPurposes().isEmpty()) {
+            dataTypeEle.appendChild(
+                    XmlUtils.createOdArray(
+                            doc,
+                            XmlUtils.OD_TAG_INT_ARRAY,
+                            XmlUtils.OD_NAME_PURPOSES,
+                            this.getPurposes().stream()
+                                    .map(p -> String.valueOf(p.getValue()))
+                                    .toList()));
+        }
+
+        maybeAddBoolToOdElement(
+                doc,
+                dataTypeEle,
+                this.getIsCollectionOptional(),
+                XmlUtils.OD_NAME_IS_COLLECTION_OPTIONAL);
+        maybeAddBoolToOdElement(
+                doc,
+                dataTypeEle,
+                this.getIsSharingOptional(),
+                XmlUtils.OD_NAME_IS_SHARING_OPTIONAL);
+        maybeAddBoolToOdElement(doc, dataTypeEle, this.getEphemeral(), XmlUtils.OD_NAME_EPHEMERAL);
+        return XmlUtils.listOf(dataTypeEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        throw new IllegalStateException(
+                "Turning DataCategory or DataType into human-readable DOM elements requires"
+                        + " visibility into parent elements. The logic resides in DataLabels.");
+    }
+
+    private static void maybeAddBoolToOdElement(
+            Document doc, Element parentEle, Boolean b, String odName) {
+        if (b == null) {
+            return;
+        }
+        Element ele = XmlUtils.createOdBooleanEle(doc, odName, b);
+        parentEle.appendChild(ele);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataTypeFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataTypeFactory.java
new file mode 100644
index 0000000..488c259
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DataTypeFactory.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class DataTypeFactory implements AslMarshallableFactory<DataType> {
+    /** Creates a {@link DataType} from the human-readable DOM element. */
+    @Override
+    public DataType createFromHrElements(List<Element> elements) throws MalformedXmlException {
+        Element hrDataTypeEle = XmlUtils.getSingleElement(elements);
+        String dataTypeName = hrDataTypeEle.getAttribute(XmlUtils.HR_ATTR_DATA_TYPE);
+        List<DataType.Purpose> purposes =
+                XmlUtils.getPipelineSplitAttr(hrDataTypeEle, XmlUtils.HR_ATTR_PURPOSES, true)
+                        .stream()
+                        .map(DataType.Purpose::forString)
+                        .collect(Collectors.toList());
+        if (purposes.isEmpty()) {
+            throw new MalformedXmlException(String.format("Found no purpose in: %s", dataTypeName));
+        }
+        if (new HashSet<>(purposes).size() != purposes.size()) {
+            throw new MalformedXmlException(
+                    String.format("Found non-unique purposes in: %s", dataTypeName));
+        }
+        Boolean isCollectionOptional =
+                XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_IS_COLLECTION_OPTIONAL, false);
+        Boolean isSharingOptional =
+                XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_IS_SHARING_OPTIONAL, false);
+        Boolean ephemeral = XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_EPHEMERAL, false);
+        return new DataType(
+                dataTypeName, purposes, isCollectionOptional, isSharingOptional, ephemeral);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public DataType createFromOdElements(List<Element> elements) throws MalformedXmlException {
+        Element odDataTypeEle = XmlUtils.getSingleElement(elements);
+        String dataTypeName = odDataTypeEle.getAttribute(XmlUtils.OD_ATTR_NAME);
+        List<Integer> purposeInts =
+                XmlUtils.getOdIntArray(odDataTypeEle, XmlUtils.OD_NAME_PURPOSES, true);
+        List<DataType.Purpose> purposes =
+                purposeInts.stream().map(DataType.Purpose::forValue).collect(Collectors.toList());
+        if (purposes.isEmpty()) {
+            throw new MalformedXmlException(String.format("Found no purpose in: %s", dataTypeName));
+        }
+        if (new HashSet<>(purposes).size() != purposes.size()) {
+            throw new MalformedXmlException(
+                    String.format("Found non-unique purposes in: %s", dataTypeName));
+        }
+        Boolean isCollectionOptional =
+                XmlUtils.getOdBoolEle(
+                        odDataTypeEle, XmlUtils.OD_NAME_IS_COLLECTION_OPTIONAL, false);
+        Boolean isSharingOptional =
+                XmlUtils.getOdBoolEle(odDataTypeEle, XmlUtils.OD_NAME_IS_SHARING_OPTIONAL, false);
+        Boolean ephemeral = XmlUtils.getOdBoolEle(odDataTypeEle, XmlUtils.OD_NAME_EPHEMERAL, false);
+
+        return new DataType(
+                dataTypeName, purposes, isCollectionOptional, isSharingOptional, ephemeral);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfo.java
new file mode 100644
index 0000000..94fad96
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfo.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** DeveloperInfo representation */
+public class DeveloperInfo implements AslMarshallable {
+    public enum DeveloperRelationship {
+        OEM(0),
+        ODM(1),
+        SOC(2),
+        OTA(3),
+        CARRIER(4),
+        AOSP(5),
+        OTHER(6);
+
+        private final int mValue;
+
+        DeveloperRelationship(int value) {
+            this.mValue = value;
+        }
+
+        /** Get the int value associated with the DeveloperRelationship. */
+        public int getValue() {
+            return mValue;
+        }
+
+        /** Get the DeveloperRelationship associated with the int value. */
+        public static DeveloperInfo.DeveloperRelationship forValue(int value) {
+            for (DeveloperInfo.DeveloperRelationship e : values()) {
+                if (e.getValue() == value) {
+                    return e;
+                }
+            }
+            throw new IllegalArgumentException("No DeveloperRelationship enum for value: " + value);
+        }
+
+        /** Get the DeveloperRelationship associated with the human-readable String. */
+        public static DeveloperInfo.DeveloperRelationship forString(String s) {
+            for (DeveloperInfo.DeveloperRelationship e : values()) {
+                if (e.toString().equals(s)) {
+                    return e;
+                }
+            }
+            throw new IllegalArgumentException("No DeveloperRelationship enum for str: " + s);
+        }
+
+        /** Human-readable String representation of DeveloperRelationship. */
+        public String toString() {
+            return this.name().toLowerCase();
+        }
+    }
+
+    private final String mName;
+    private final String mEmail;
+    private final String mAddress;
+    private final String mCountryRegion;
+    private final DeveloperRelationship mDeveloperRelationship;
+    private final String mWebsite;
+    private final String mAppDeveloperRegistryId;
+
+    public DeveloperInfo(
+            String name,
+            String email,
+            String address,
+            String countryRegion,
+            DeveloperRelationship developerRelationship,
+            String website,
+            String appDeveloperRegistryId) {
+        this.mName = name;
+        this.mEmail = email;
+        this.mAddress = address;
+        this.mCountryRegion = countryRegion;
+        this.mDeveloperRelationship = developerRelationship;
+        this.mWebsite = website;
+        this.mAppDeveloperRegistryId = appDeveloperRegistryId;
+    }
+
+    /** Creates an on-device DOM element from the {@link SafetyLabels}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element developerInfoEle =
+                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_DEVELOPER_INFO);
+        if (mName != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_NAME, mName));
+        }
+        if (mEmail != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_EMAIL, mEmail));
+        }
+        if (mAddress != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_ADDRESS, mAddress));
+        }
+        if (mCountryRegion != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(
+                            doc, XmlUtils.OD_NAME_COUNTRY_REGION, mCountryRegion));
+        }
+        if (mDeveloperRelationship != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdLongEle(
+                            doc,
+                            XmlUtils.OD_NAME_DEVELOPER_RELATIONSHIP,
+                            mDeveloperRelationship.getValue()));
+        }
+        if (mWebsite != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_WEBSITE, mWebsite));
+        }
+        if (mAppDeveloperRegistryId != null) {
+            developerInfoEle.appendChild(
+                    XmlUtils.createOdStringEle(
+                            doc,
+                            XmlUtils.OD_NAME_APP_DEVELOPER_REGISTRY_ID,
+                            mAppDeveloperRegistryId));
+        }
+
+        return XmlUtils.listOf(developerInfoEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element developerInfoEle = doc.createElement(XmlUtils.HR_TAG_DEVELOPER_INFO);
+        if (mName != null) {
+            developerInfoEle.setAttribute(XmlUtils.HR_ATTR_NAME, mName);
+        }
+        if (mEmail != null) {
+            developerInfoEle.setAttribute(XmlUtils.HR_ATTR_EMAIL, mEmail);
+        }
+        if (mAddress != null) {
+            developerInfoEle.setAttribute(XmlUtils.HR_ATTR_ADDRESS, mAddress);
+        }
+        if (mCountryRegion != null) {
+            developerInfoEle.setAttribute(XmlUtils.HR_ATTR_COUNTRY_REGION, mCountryRegion);
+        }
+        if (mDeveloperRelationship != null) {
+            developerInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_DEVELOPER_RELATIONSHIP, mDeveloperRelationship.toString());
+        }
+        if (mWebsite != null) {
+            developerInfoEle.setAttribute(XmlUtils.HR_ATTR_WEBSITE, mWebsite);
+        }
+        if (mAppDeveloperRegistryId != null) {
+            developerInfoEle.setAttribute(
+                    XmlUtils.HR_ATTR_APP_DEVELOPER_REGISTRY_ID, mAppDeveloperRegistryId);
+        }
+
+        return XmlUtils.listOf(developerInfoEle);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfoFactory.java
new file mode 100644
index 0000000..0f3b41c
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfoFactory.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class DeveloperInfoFactory implements AslMarshallableFactory<DeveloperInfo> {
+
+    /** Creates a {@link DeveloperInfo} from the human-readable DOM element. */
+    @Override
+    public DeveloperInfo createFromHrElements(List<Element> elements) throws MalformedXmlException {
+        Element developerInfoEle = XmlUtils.getSingleElement(elements);
+        if (developerInfoEle == null) {
+            AslgenUtil.logI("No DeveloperInfo found in hr format.");
+            return null;
+        }
+        String name = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_NAME, true);
+        String email = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_EMAIL, true);
+        String address = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_ADDRESS, true);
+        String countryRegion =
+                XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_COUNTRY_REGION, true);
+        DeveloperInfo.DeveloperRelationship developerRelationship =
+                DeveloperInfo.DeveloperRelationship.forString(
+                        XmlUtils.getStringAttr(
+                                developerInfoEle, XmlUtils.HR_ATTR_DEVELOPER_RELATIONSHIP, true));
+        String website = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_WEBSITE, false);
+        String appDeveloperRegistryId =
+                XmlUtils.getStringAttr(
+                        developerInfoEle, XmlUtils.HR_ATTR_APP_DEVELOPER_REGISTRY_ID, false);
+
+        return new DeveloperInfo(
+                name,
+                email,
+                address,
+                countryRegion,
+                developerRelationship,
+                website,
+                appDeveloperRegistryId);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public DeveloperInfo createFromOdElements(List<Element> elements) throws MalformedXmlException {
+        Element developerInfoEle = XmlUtils.getSingleElement(elements);
+        if (developerInfoEle == null) {
+            AslgenUtil.logI("No DeveloperInfo found in od format.");
+            return null;
+        }
+        String name = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_NAME, true);
+        String email = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_EMAIL, true);
+        String address = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_ADDRESS, true);
+        String countryRegion =
+                XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_COUNTRY_REGION, true);
+        DeveloperInfo.DeveloperRelationship developerRelationship =
+                DeveloperInfo.DeveloperRelationship.forValue(
+                        (int)
+                                (long)
+                                        XmlUtils.getOdLongEle(
+                                                developerInfoEle,
+                                                XmlUtils.OD_NAME_DEVELOPER_RELATIONSHIP,
+                                                true));
+        String website = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_WEBSITE, false);
+        String appDeveloperRegistryId =
+                XmlUtils.getOdStringEle(
+                        developerInfoEle, XmlUtils.OD_NAME_APP_DEVELOPER_REGISTRY_ID, false);
+
+        return new DeveloperInfo(
+                name,
+                email,
+                address,
+                countryRegion,
+                developerRelationship,
+                website,
+                appDeveloperRegistryId);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java
new file mode 100644
index 0000000..6af8071
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** Safety Label representation containing zero or more {@link DataCategory} for data shared */
+public class SafetyLabels implements AslMarshallable {
+
+    private final Long mVersion;
+    private final DataLabels mDataLabels;
+    private final SecurityLabels mSecurityLabels;
+    private final ThirdPartyVerification mThirdPartyVerification;
+
+    public SafetyLabels(
+            Long version,
+            DataLabels dataLabels,
+            SecurityLabels securityLabels,
+            ThirdPartyVerification thirdPartyVerification) {
+        this.mVersion = version;
+        this.mDataLabels = dataLabels;
+        this.mSecurityLabels = securityLabels;
+        this.mThirdPartyVerification = thirdPartyVerification;
+    }
+
+    /** Returns the data label for the safety label */
+    public DataLabels getDataLabel() {
+        return mDataLabels;
+    }
+
+    /** Gets the version of the {@link SafetyLabels}. */
+    public Long getVersion() {
+        return mVersion;
+    }
+
+    /** Creates an on-device DOM element from the {@link SafetyLabels}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element safetyLabelsEle =
+                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_SAFETY_LABELS);
+        safetyLabelsEle.appendChild(
+                XmlUtils.createOdLongEle(doc, XmlUtils.OD_NAME_VERSION, mVersion));
+        if (mDataLabels != null) {
+            XmlUtils.appendChildren(safetyLabelsEle, mDataLabels.toOdDomElements(doc));
+        }
+        if (mSecurityLabels != null) {
+            XmlUtils.appendChildren(safetyLabelsEle, mSecurityLabels.toOdDomElements(doc));
+        }
+        if (mThirdPartyVerification != null) {
+            XmlUtils.appendChildren(safetyLabelsEle, mThirdPartyVerification.toOdDomElements(doc));
+        }
+        return XmlUtils.listOf(safetyLabelsEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element safetyLabelsEle = doc.createElement(XmlUtils.HR_TAG_SAFETY_LABELS);
+        safetyLabelsEle.setAttribute(XmlUtils.HR_ATTR_VERSION, String.valueOf(mVersion));
+
+        if (mDataLabels != null) {
+            XmlUtils.appendChildren(safetyLabelsEle, mDataLabels.toHrDomElements(doc));
+        }
+        if (mSecurityLabels != null) {
+            XmlUtils.appendChildren(safetyLabelsEle, mSecurityLabels.toHrDomElements(doc));
+        }
+        if (mThirdPartyVerification != null) {
+            XmlUtils.appendChildren(safetyLabelsEle, mThirdPartyVerification.toHrDomElements(doc));
+        }
+        return XmlUtils.listOf(safetyLabelsEle);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java
new file mode 100644
index 0000000..2644b43
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class SafetyLabelsFactory implements AslMarshallableFactory<SafetyLabels> {
+
+    /** Creates a {@link SafetyLabels} from the human-readable DOM element. */
+    @Override
+    public SafetyLabels createFromHrElements(List<Element> elements) throws MalformedXmlException {
+        Element safetyLabelsEle = XmlUtils.getSingleElement(elements);
+        if (safetyLabelsEle == null) {
+            AslgenUtil.logI("No SafetyLabels found in hr format.");
+            return null;
+        }
+        long version = XmlUtils.tryGetVersion(safetyLabelsEle);
+
+        DataLabels dataLabels =
+                new DataLabelsFactory()
+                        .createFromHrElements(
+                                XmlUtils.listOf(
+                                        XmlUtils.getSingleChildElement(
+                                                safetyLabelsEle,
+                                                XmlUtils.HR_TAG_DATA_LABELS,
+                                                false)));
+        SecurityLabels securityLabels =
+                new SecurityLabelsFactory()
+                        .createFromHrElements(
+                                XmlUtils.listOf(
+                                        XmlUtils.getSingleChildElement(
+                                                safetyLabelsEle,
+                                                XmlUtils.HR_TAG_SECURITY_LABELS,
+                                                false)));
+        ThirdPartyVerification thirdPartyVerification =
+                new ThirdPartyVerificationFactory()
+                        .createFromHrElements(
+                                XmlUtils.listOf(
+                                        XmlUtils.getSingleChildElement(
+                                                safetyLabelsEle,
+                                                XmlUtils.HR_TAG_THIRD_PARTY_VERIFICATION,
+                                                false)));
+        return new SafetyLabels(version, dataLabels, securityLabels, thirdPartyVerification);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public SafetyLabels createFromOdElements(List<Element> elements) throws MalformedXmlException {
+        Element safetyLabelsEle = XmlUtils.getSingleElement(elements);
+        if (safetyLabelsEle == null) {
+            AslgenUtil.logI("No SafetyLabels found in od format.");
+            return null;
+        }
+        Long version = XmlUtils.getOdLongEle(safetyLabelsEle, XmlUtils.OD_NAME_VERSION, true);
+
+        DataLabels dataLabels =
+                new DataLabelsFactory()
+                        .createFromOdElements(
+                                XmlUtils.listOf(
+                                        XmlUtils.getOdPbundleWithName(
+                                                safetyLabelsEle,
+                                                XmlUtils.OD_NAME_DATA_LABELS,
+                                                false)));
+        SecurityLabels securityLabels =
+                new SecurityLabelsFactory()
+                        .createFromOdElements(
+                                XmlUtils.listOf(
+                                        XmlUtils.getOdPbundleWithName(
+                                                safetyLabelsEle,
+                                                XmlUtils.OD_NAME_SECURITY_LABELS,
+                                                false)));
+        ThirdPartyVerification thirdPartyVerification =
+                new ThirdPartyVerificationFactory()
+                        .createFromOdElements(
+                                XmlUtils.listOf(
+                                        XmlUtils.getOdPbundleWithName(
+                                                safetyLabelsEle,
+                                                XmlUtils.OD_NAME_THIRD_PARTY_VERIFICATION,
+                                                false)));
+        return new SafetyLabels(version, dataLabels, securityLabels, thirdPartyVerification);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SecurityLabels.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SecurityLabels.java
new file mode 100644
index 0000000..48643ba
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SecurityLabels.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** Security Labels representation */
+public class SecurityLabels implements AslMarshallable {
+
+    private final Boolean mIsDataDeletable;
+    private final Boolean mIsDataEncrypted;
+
+    public SecurityLabels(Boolean isDataDeletable, Boolean isDataEncrypted) {
+        this.mIsDataDeletable = isDataDeletable;
+        this.mIsDataEncrypted = isDataEncrypted;
+    }
+
+    /** Creates an on-device DOM element from the {@link SecurityLabels}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element ele = XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_SECURITY_LABELS);
+        if (mIsDataDeletable != null) {
+            ele.appendChild(
+                    XmlUtils.createOdBooleanEle(
+                            doc, XmlUtils.OD_NAME_IS_DATA_DELETABLE, mIsDataDeletable));
+        }
+        if (mIsDataEncrypted != null) {
+            ele.appendChild(
+                    XmlUtils.createOdBooleanEle(
+                            doc, XmlUtils.OD_NAME_IS_DATA_ENCRYPTED, mIsDataEncrypted));
+        }
+        return XmlUtils.listOf(ele);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element ele = doc.createElement(XmlUtils.HR_TAG_SECURITY_LABELS);
+        if (mIsDataDeletable != null) {
+            ele.setAttribute(XmlUtils.HR_ATTR_IS_DATA_DELETABLE, String.valueOf(mIsDataDeletable));
+        }
+        if (mIsDataEncrypted != null) {
+            ele.setAttribute(XmlUtils.HR_ATTR_IS_DATA_ENCRYPTED, String.valueOf(mIsDataEncrypted));
+        }
+        return XmlUtils.listOf(ele);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SecurityLabelsFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SecurityLabelsFactory.java
new file mode 100644
index 0000000..525a803
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SecurityLabelsFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class SecurityLabelsFactory implements AslMarshallableFactory<SecurityLabels> {
+
+    /** Creates a {@link SecurityLabels} from the human-readable DOM element. */
+    @Override
+    public SecurityLabels createFromHrElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element ele = XmlUtils.getSingleElement(elements);
+        if (ele == null) {
+            AslgenUtil.logI("No SecurityLabels found in hr format.");
+            return null;
+        }
+        Boolean isDataDeletable =
+                XmlUtils.getBoolAttr(ele, XmlUtils.HR_ATTR_IS_DATA_DELETABLE, false);
+        Boolean isDataEncrypted =
+                XmlUtils.getBoolAttr(ele, XmlUtils.HR_ATTR_IS_DATA_ENCRYPTED, false);
+        return new SecurityLabels(isDataDeletable, isDataEncrypted);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public SecurityLabels createFromOdElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element ele = XmlUtils.getSingleElement(elements);
+        if (ele == null) {
+            AslgenUtil.logI("No SecurityLabels found in od format.");
+            return null;
+        }
+        Boolean isDataDeletable =
+                XmlUtils.getOdBoolEle(ele, XmlUtils.OD_NAME_IS_DATA_DELETABLE, false);
+        Boolean isDataEncrypted =
+                XmlUtils.getOdBoolEle(ele, XmlUtils.OD_NAME_IS_DATA_ENCRYPTED, false);
+        return new SecurityLabels(isDataDeletable, isDataEncrypted);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SystemAppSafetyLabel.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SystemAppSafetyLabel.java
new file mode 100644
index 0000000..854c0d0
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SystemAppSafetyLabel.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** Safety Label representation containing zero or more {@link DataCategory} for data shared */
+public class SystemAppSafetyLabel implements AslMarshallable {
+
+    private final String mUrl;
+
+    public SystemAppSafetyLabel(String url) {
+        this.mUrl = url;
+    }
+
+    /** Returns the system app safety label URL. */
+    public String getUrl() {
+        return mUrl;
+    }
+
+    /** Creates an on-device DOM element from the {@link SystemAppSafetyLabel}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element systemAppSafetyLabelEle =
+                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_SYSTEM_APP_SAFETY_LABEL);
+        systemAppSafetyLabelEle.appendChild(
+                XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_URL, mUrl));
+        return XmlUtils.listOf(systemAppSafetyLabelEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element systemAppSafetyLabelEle =
+                doc.createElement(XmlUtils.HR_TAG_SYSTEM_APP_SAFETY_LABEL);
+        systemAppSafetyLabelEle.setAttribute(XmlUtils.HR_ATTR_URL, mUrl);
+        return XmlUtils.listOf(systemAppSafetyLabelEle);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SystemAppSafetyLabelFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SystemAppSafetyLabelFactory.java
new file mode 100644
index 0000000..c8e22b6
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SystemAppSafetyLabelFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class SystemAppSafetyLabelFactory implements AslMarshallableFactory<SystemAppSafetyLabel> {
+
+    /** Creates a {@link SystemAppSafetyLabel} from the human-readable DOM element. */
+    @Override
+    public SystemAppSafetyLabel createFromHrElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element systemAppSafetyLabelEle = XmlUtils.getSingleElement(elements);
+        if (systemAppSafetyLabelEle == null) {
+            AslgenUtil.logI("No SystemAppSafetyLabel found in hr format.");
+            return null;
+        }
+
+        String url = XmlUtils.getStringAttr(systemAppSafetyLabelEle, XmlUtils.HR_ATTR_URL, true);
+        return new SystemAppSafetyLabel(url);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public SystemAppSafetyLabel createFromOdElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element systemAppSafetyLabelEle = XmlUtils.getSingleElement(elements);
+        if (systemAppSafetyLabelEle == null) {
+            AslgenUtil.logI("No SystemAppSafetyLabel found in od format.");
+            return null;
+        }
+        String url = XmlUtils.getOdStringEle(systemAppSafetyLabelEle, XmlUtils.OD_NAME_URL, true);
+        return new SystemAppSafetyLabel(url);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/ThirdPartyVerification.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/ThirdPartyVerification.java
new file mode 100644
index 0000000..d74f3f0
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/ThirdPartyVerification.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** ThirdPartyVerification representation. */
+public class ThirdPartyVerification implements AslMarshallable {
+
+    private final String mUrl;
+
+    public ThirdPartyVerification(String url) {
+        this.mUrl = url;
+    }
+
+    /** Creates an on-device DOM element from the {@link ThirdPartyVerification}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element ele =
+                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_THIRD_PARTY_VERIFICATION);
+        ele.appendChild(XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_URL, mUrl));
+        return XmlUtils.listOf(ele);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element ele = doc.createElement(XmlUtils.HR_TAG_THIRD_PARTY_VERIFICATION);
+        ele.setAttribute(XmlUtils.HR_ATTR_URL, mUrl);
+        return XmlUtils.listOf(ele);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/ThirdPartyVerificationFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/ThirdPartyVerificationFactory.java
new file mode 100644
index 0000000..197e7aa
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/ThirdPartyVerificationFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class ThirdPartyVerificationFactory
+        implements AslMarshallableFactory<ThirdPartyVerification> {
+
+    /** Creates a {@link ThirdPartyVerification} from the human-readable DOM element. */
+    @Override
+    public ThirdPartyVerification createFromHrElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element ele = XmlUtils.getSingleElement(elements);
+        if (ele == null) {
+            AslgenUtil.logI("No ThirdPartyVerification found in hr format.");
+            return null;
+        }
+
+        String url = XmlUtils.getStringAttr(ele, XmlUtils.HR_ATTR_URL, true);
+        return new ThirdPartyVerification(url);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public ThirdPartyVerification createFromOdElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element ele = XmlUtils.getSingleElement(elements);
+        if (ele == null) {
+            AslgenUtil.logI("No ThirdPartyVerification found in od format.");
+            return null;
+        }
+
+        String url = XmlUtils.getOdStringEle(ele, XmlUtils.OD_NAME_URL, true);
+        return new ThirdPartyVerification(url);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java
new file mode 100644
index 0000000..6a8700a
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+/** TransparencyInfo representation containing {@link DeveloperInfo} and {@link AppInfo} */
+public class TransparencyInfo implements AslMarshallable {
+
+    private final DeveloperInfo mDeveloperInfo;
+    private final AppInfo mAppInfo;
+
+    public TransparencyInfo(DeveloperInfo developerInfo, AppInfo appInfo) {
+        this.mDeveloperInfo = developerInfo;
+        this.mAppInfo = appInfo;
+    }
+
+    /** Gets the {@link DeveloperInfo} of the {@link TransparencyInfo}. */
+    public DeveloperInfo getDeveloperInfo() {
+        return mDeveloperInfo;
+    }
+
+    /** Gets the {@link AppInfo} of the {@link TransparencyInfo}. */
+    public AppInfo getAppInfo() {
+        return mAppInfo;
+    }
+
+    /** Creates an on-device DOM element from the {@link TransparencyInfo}. */
+    @Override
+    public List<Element> toOdDomElements(Document doc) {
+        Element transparencyInfoEle =
+                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_TRANSPARENCY_INFO);
+        if (mDeveloperInfo != null) {
+            XmlUtils.appendChildren(transparencyInfoEle, mDeveloperInfo.toOdDomElements(doc));
+        }
+        if (mAppInfo != null) {
+            XmlUtils.appendChildren(transparencyInfoEle, mAppInfo.toOdDomElements(doc));
+        }
+        return XmlUtils.listOf(transparencyInfoEle);
+    }
+
+    /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
+    @Override
+    public List<Element> toHrDomElements(Document doc) {
+        Element transparencyInfoEle = doc.createElement(XmlUtils.HR_TAG_TRANSPARENCY_INFO);
+        if (mDeveloperInfo != null) {
+            XmlUtils.appendChildren(transparencyInfoEle, mDeveloperInfo.toHrDomElements(doc));
+        }
+        if (mAppInfo != null) {
+            XmlUtils.appendChildren(transparencyInfoEle, mAppInfo.toHrDomElements(doc));
+        }
+        return XmlUtils.listOf(transparencyInfoEle);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java
new file mode 100644
index 0000000..94c5640
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.util.AslgenUtil;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+
+public class TransparencyInfoFactory implements AslMarshallableFactory<TransparencyInfo> {
+
+    /** Creates a {@link TransparencyInfo} from the human-readable DOM element. */
+    @Override
+    public TransparencyInfo createFromHrElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element transparencyInfoEle = XmlUtils.getSingleElement(elements);
+        if (transparencyInfoEle == null) {
+            AslgenUtil.logI("No TransparencyInfo found in hr format.");
+            return null;
+        }
+
+        Element developerInfoEle =
+                XmlUtils.getSingleChildElement(
+                        transparencyInfoEle, XmlUtils.HR_TAG_DEVELOPER_INFO, false);
+        DeveloperInfo developerInfo =
+                new DeveloperInfoFactory().createFromHrElements(XmlUtils.listOf(developerInfoEle));
+
+        Element appInfoEle =
+                XmlUtils.getSingleChildElement(
+                        transparencyInfoEle, XmlUtils.HR_TAG_APP_INFO, false);
+        AppInfo appInfo = new AppInfoFactory().createFromHrElements(XmlUtils.listOf(appInfoEle));
+
+        return new TransparencyInfo(developerInfo, appInfo);
+    }
+
+    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
+    @Override
+    public TransparencyInfo createFromOdElements(List<Element> elements)
+            throws MalformedXmlException {
+        Element transparencyInfoEle = XmlUtils.getSingleElement(elements);
+        if (transparencyInfoEle == null) {
+            AslgenUtil.logI("No TransparencyInfo found in od format.");
+            return null;
+        }
+
+        Element developerInfoEle =
+                XmlUtils.getOdPbundleWithName(
+                        transparencyInfoEle, XmlUtils.OD_NAME_DEVELOPER_INFO, false);
+        DeveloperInfo developerInfo =
+                new DeveloperInfoFactory().createFromOdElements(XmlUtils.listOf(developerInfoEle));
+
+        Element appInfoEle =
+                XmlUtils.getOdPbundleWithName(
+                        transparencyInfoEle, XmlUtils.OD_NAME_APP_INFO, false);
+        AppInfo appInfo = new AppInfoFactory().createFromOdElements(XmlUtils.listOf(appInfoEle));
+
+        return new TransparencyInfo(developerInfo, appInfo);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/DataCategoryConstants.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/DataCategoryConstants.java
new file mode 100644
index 0000000..b5ae54c
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/DataCategoryConstants.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.util;
+
+import com.android.asllib.marshallable.DataCategory;
+import com.android.asllib.marshallable.DataType;
+import com.android.asllib.marshallable.SafetyLabels;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Constants for determining valid {@link String} data types for usage within {@link SafetyLabels},
+ * {@link DataCategory}, and {@link DataType}
+ */
+public class DataCategoryConstants {
+
+    public static final String CATEGORY_PERSONAL = "personal";
+    public static final String CATEGORY_FINANCIAL = "financial";
+    public static final String CATEGORY_LOCATION = "location";
+    public static final String CATEGORY_EMAIL_TEXT_MESSAGE = "email_text_message";
+    public static final String CATEGORY_PHOTO_VIDEO = "photo_video";
+    public static final String CATEGORY_AUDIO = "audio";
+    public static final String CATEGORY_STORAGE = "storage";
+    public static final String CATEGORY_HEALTH_FITNESS = "health_fitness";
+    public static final String CATEGORY_CONTACTS = "contacts";
+    public static final String CATEGORY_CALENDAR = "calendar";
+    public static final String CATEGORY_IDENTIFIERS = "identifiers";
+    public static final String CATEGORY_APP_PERFORMANCE = "app_performance";
+    public static final String CATEGORY_ACTIONS_IN_APP = "actions_in_app";
+    public static final String CATEGORY_SEARCH_AND_BROWSING = "search_and_browsing";
+
+    /** Set of valid categories */
+    public static final Set<String> VALID_CATEGORIES =
+            Collections.unmodifiableSet(
+                    new HashSet<>(
+                            Arrays.asList(
+                                    CATEGORY_PERSONAL,
+                                    CATEGORY_FINANCIAL,
+                                    CATEGORY_LOCATION,
+                                    CATEGORY_EMAIL_TEXT_MESSAGE,
+                                    CATEGORY_PHOTO_VIDEO,
+                                    CATEGORY_AUDIO,
+                                    CATEGORY_STORAGE,
+                                    CATEGORY_HEALTH_FITNESS,
+                                    CATEGORY_CONTACTS,
+                                    CATEGORY_CALENDAR,
+                                    CATEGORY_IDENTIFIERS,
+                                    CATEGORY_APP_PERFORMANCE,
+                                    CATEGORY_ACTIONS_IN_APP,
+                                    CATEGORY_SEARCH_AND_BROWSING)));
+
+    /** Returns {@link Set} of valid {@link String} category keys */
+    public static Set<String> getValidDataCategories() {
+        return VALID_CATEGORIES;
+    }
+
+    private DataCategoryConstants() {
+        /* do nothing - hide constructor */
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/DataTypeConstants.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/DataTypeConstants.java
new file mode 100644
index 0000000..358d575
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/DataTypeConstants.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.util;
+
+import com.android.asllib.marshallable.DataCategory;
+import com.android.asllib.marshallable.DataType;
+import com.android.asllib.marshallable.SafetyLabels;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Constants for determining valid {@link String} data types for usage within {@link SafetyLabels},
+ * {@link DataCategory}, and {@link DataType}
+ */
+public class DataTypeConstants {
+    /** Data types for {@link DataCategoryConstants.CATEGORY_PERSONAL} */
+    public static final String TYPE_NAME = "name";
+
+    public static final String TYPE_EMAIL_ADDRESS = "email_address";
+    public static final String TYPE_PHYSICAL_ADDRESS = "physical_address";
+    public static final String TYPE_PHONE_NUMBER = "phone_number";
+    public static final String TYPE_RACE_ETHNICITY = "race_ethnicity";
+    public static final String TYPE_POLITICAL_OR_RELIGIOUS_BELIEFS =
+            "political_or_religious_beliefs";
+    public static final String TYPE_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY =
+            "sexual_orientation_or_gender_identity";
+    public static final String TYPE_PERSONAL_IDENTIFIERS = "personal_identifiers";
+    public static final String TYPE_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_FINANCIAL} */
+    public static final String TYPE_CARD_BANK_ACCOUNT = "card_bank_account";
+
+    public static final String TYPE_PURCHASE_HISTORY = "purchase_history";
+    public static final String TYPE_CREDIT_SCORE = "credit_score";
+    public static final String TYPE_FINANCIAL_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_LOCATION} */
+    public static final String TYPE_APPROX_LOCATION = "approx_location";
+
+    public static final String TYPE_PRECISE_LOCATION = "precise_location";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_EMAIL_TEXT_MESSAGE} */
+    public static final String TYPE_EMAILS = "emails";
+
+    public static final String TYPE_TEXT_MESSAGES = "text_messages";
+    public static final String TYPE_EMAIL_TEXT_MESSAGE_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_PHOTO_VIDEO} */
+    public static final String TYPE_PHOTOS = "photos";
+
+    public static final String TYPE_VIDEOS = "videos";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_AUDIO} */
+    public static final String TYPE_SOUND_RECORDINGS = "sound_recordings";
+
+    public static final String TYPE_MUSIC_FILES = "music_files";
+    public static final String TYPE_AUDIO_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_STORAGE} */
+    public static final String TYPE_FILES_DOCS = "files_docs";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_HEALTH_FITNESS} */
+    public static final String TYPE_HEALTH = "health";
+
+    public static final String TYPE_FITNESS = "fitness";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_CONTACTS} */
+    public static final String TYPE_CONTACTS = "contacts";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_CALENDAR} */
+    public static final String TYPE_CALENDAR = "calendar";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_IDENTIFIERS} */
+    public static final String TYPE_IDENTIFIERS_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_APP_PERFORMANCE} */
+    public static final String TYPE_CRASH_LOGS = "crash_logs";
+
+    public static final String TYPE_PERFORMANCE_DIAGNOSTICS = "performance_diagnostics";
+    public static final String TYPE_APP_PERFORMANCE_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_ACTIONS_IN_APP} */
+    public static final String TYPE_USER_INTERACTION = "user_interaction";
+
+    public static final String TYPE_IN_APP_SEARCH_HISTORY = "in_app_search_history";
+    public static final String TYPE_INSTALLED_APPS = "installed_apps";
+    public static final String TYPE_USER_GENERATED_CONTENT = "user_generated_content";
+    public static final String TYPE_ACTIONS_IN_APP_OTHER = "other";
+
+    /** Data types for {@link DataCategoryConstants.CATEGORY_SEARCH_AND_BROWSING} */
+    public static final String TYPE_WEB_BROWSING_HISTORY = "web_browsing_history";
+
+    /** Set of valid categories */
+    private static final Map<String, Set<String>> VALID_DATA_TYPES =
+            new ImmutableMap.Builder<String, Set<String>>()
+                    .put(
+                            DataCategoryConstants.CATEGORY_PERSONAL,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_NAME,
+                                    DataTypeConstants.TYPE_EMAIL_ADDRESS,
+                                    DataTypeConstants.TYPE_PHYSICAL_ADDRESS,
+                                    DataTypeConstants.TYPE_PHONE_NUMBER,
+                                    DataTypeConstants.TYPE_RACE_ETHNICITY,
+                                    DataTypeConstants.TYPE_POLITICAL_OR_RELIGIOUS_BELIEFS,
+                                    DataTypeConstants.TYPE_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY,
+                                    DataTypeConstants.TYPE_PERSONAL_IDENTIFIERS,
+                                    DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_FINANCIAL,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_CARD_BANK_ACCOUNT,
+                                    DataTypeConstants.TYPE_PURCHASE_HISTORY,
+                                    DataTypeConstants.TYPE_CREDIT_SCORE,
+                                    DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_LOCATION,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_APPROX_LOCATION,
+                                    DataTypeConstants.TYPE_PRECISE_LOCATION))
+                    .put(
+                            DataCategoryConstants.CATEGORY_EMAIL_TEXT_MESSAGE,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_EMAILS,
+                                    DataTypeConstants.TYPE_TEXT_MESSAGES,
+                                    DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_PHOTO_VIDEO,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_PHOTOS, DataTypeConstants.TYPE_VIDEOS))
+                    .put(
+                            DataCategoryConstants.CATEGORY_AUDIO,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_SOUND_RECORDINGS,
+                                    DataTypeConstants.TYPE_MUSIC_FILES,
+                                    DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_STORAGE,
+                            ImmutableSet.of(DataTypeConstants.TYPE_FILES_DOCS))
+                    .put(
+                            DataCategoryConstants.CATEGORY_HEALTH_FITNESS,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_HEALTH, DataTypeConstants.TYPE_FITNESS))
+                    .put(
+                            DataCategoryConstants.CATEGORY_CONTACTS,
+                            ImmutableSet.of(DataTypeConstants.TYPE_CONTACTS))
+                    .put(
+                            DataCategoryConstants.CATEGORY_CALENDAR,
+                            ImmutableSet.of(DataTypeConstants.TYPE_CALENDAR))
+                    .put(
+                            DataCategoryConstants.CATEGORY_IDENTIFIERS,
+                            ImmutableSet.of(DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_APP_PERFORMANCE,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_CRASH_LOGS,
+                                    DataTypeConstants.TYPE_PERFORMANCE_DIAGNOSTICS,
+                                    DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_ACTIONS_IN_APP,
+                            ImmutableSet.of(
+                                    DataTypeConstants.TYPE_USER_INTERACTION,
+                                    DataTypeConstants.TYPE_IN_APP_SEARCH_HISTORY,
+                                    DataTypeConstants.TYPE_INSTALLED_APPS,
+                                    DataTypeConstants.TYPE_USER_GENERATED_CONTENT,
+                                    DataTypeConstants.TYPE_OTHER))
+                    .put(
+                            DataCategoryConstants.CATEGORY_SEARCH_AND_BROWSING,
+                            ImmutableSet.of(DataTypeConstants.TYPE_WEB_BROWSING_HISTORY))
+                    .buildOrThrow();
+
+    /** Returns {@link Set} of valid {@link String} category keys */
+    public static Map<String, Set<String>> getValidDataTypes() {
+        return VALID_DATA_TYPES;
+    }
+
+    private DataTypeConstants() {
+        /* do nothing - hide constructor */
+    }
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java
new file mode 100644
index 0000000..1d54ead
--- /dev/null
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.util;
+
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class XmlUtils {
+    public static final String HR_TAG_APP_METADATA_BUNDLES = "app-metadata-bundles";
+    public static final String HR_TAG_SYSTEM_APP_SAFETY_LABEL = "system-app-safety-label";
+    public static final String HR_TAG_SAFETY_LABELS = "safety-labels";
+    public static final String HR_TAG_TRANSPARENCY_INFO = "transparency-info";
+    public static final String HR_TAG_DEVELOPER_INFO = "developer-info";
+    public static final String HR_TAG_APP_INFO = "app-info";
+    public static final String HR_TAG_DATA_LABELS = "data-labels";
+    public static final String HR_TAG_SECURITY_LABELS = "security-labels";
+    public static final String HR_TAG_THIRD_PARTY_VERIFICATION = "third-party-verification";
+    public static final String HR_TAG_DATA_ACCESSED = "data-accessed";
+    public static final String HR_TAG_DATA_COLLECTED = "data-collected";
+    public static final String HR_TAG_DATA_SHARED = "data-shared";
+    public static final String HR_ATTR_NAME = "name";
+    public static final String HR_ATTR_EMAIL = "email";
+    public static final String HR_ATTR_ADDRESS = "address";
+    public static final String HR_ATTR_COUNTRY_REGION = "countryRegion";
+    public static final String HR_ATTR_DEVELOPER_RELATIONSHIP = "relationship";
+    public static final String HR_ATTR_WEBSITE = "website";
+    public static final String HR_ATTR_APP_DEVELOPER_REGISTRY_ID = "registryId";
+    public static final String HR_ATTR_DATA_CATEGORY = "dataCategory";
+    public static final String HR_ATTR_DATA_TYPE = "dataType";
+    public static final String HR_ATTR_IS_COLLECTION_OPTIONAL = "isCollectionOptional";
+    public static final String HR_ATTR_IS_SHARING_OPTIONAL = "isSharingOptional";
+    public static final String HR_ATTR_IS_DATA_DELETABLE = "isDataDeletable";
+    public static final String HR_ATTR_IS_DATA_ENCRYPTED = "isDataEncrypted";
+    public static final String HR_ATTR_EPHEMERAL = "ephemeral";
+    public static final String HR_ATTR_PURPOSES = "purposes";
+    public static final String HR_ATTR_VERSION = "version";
+    public static final String HR_ATTR_URL = "url";
+    public static final String HR_ATTR_TITLE = "title";
+    public static final String HR_ATTR_DESCRIPTION = "description";
+    public static final String HR_ATTR_CONTAINS_ADS = "containsAds";
+    public static final String HR_ATTR_OBEY_APS = "obeyAps";
+    public static final String HR_ATTR_ADS_FINGERPRINTING = "adsFingerprinting";
+    public static final String HR_ATTR_SECURITY_FINGERPRINTING = "securityFingerprinting";
+    public static final String HR_ATTR_PRIVACY_POLICY = "privacyPolicy";
+    public static final String HR_ATTR_SECURITY_ENDPOINTS = "securityEndpoints";
+    public static final String HR_ATTR_FIRST_PARTY_ENDPOINTS = "firstPartyEndpoints";
+    public static final String HR_ATTR_SERVICE_PROVIDER_ENDPOINTS = "serviceProviderEndpoints";
+    public static final String HR_ATTR_CATEGORY = "category";
+
+    public static final String OD_TAG_BUNDLE = "bundle";
+    public static final String OD_TAG_PBUNDLE_AS_MAP = "pbundle_as_map";
+    public static final String OD_TAG_BOOLEAN = "boolean";
+    public static final String OD_TAG_LONG = "long";
+    public static final String OD_TAG_STRING = "string";
+    public static final String OD_TAG_INT_ARRAY = "int-array";
+    public static final String OD_TAG_STRING_ARRAY = "string-array";
+    public static final String OD_TAG_ITEM = "item";
+    public static final String OD_ATTR_NAME = "name";
+    public static final String OD_ATTR_VALUE = "value";
+    public static final String OD_ATTR_NUM = "num";
+    public static final String OD_NAME_SAFETY_LABELS = "safety_labels";
+    public static final String OD_NAME_TRANSPARENCY_INFO = "transparency_info";
+    public static final String OD_NAME_DEVELOPER_INFO = "developer_info";
+    public static final String OD_NAME_NAME = "name";
+    public static final String OD_NAME_EMAIL = "email";
+    public static final String OD_NAME_ADDRESS = "address";
+    public static final String OD_NAME_COUNTRY_REGION = "country_region";
+    public static final String OD_NAME_DEVELOPER_RELATIONSHIP = "relationship";
+    public static final String OD_NAME_WEBSITE = "website";
+    public static final String OD_NAME_APP_DEVELOPER_REGISTRY_ID = "app_developer_registry_id";
+    public static final String OD_NAME_APP_INFO = "app_info";
+    public static final String OD_NAME_TITLE = "title";
+    public static final String OD_NAME_DESCRIPTION = "description";
+    public static final String OD_NAME_CONTAINS_ADS = "contains_ads";
+    public static final String OD_NAME_OBEY_APS = "obey_aps";
+    public static final String OD_NAME_ADS_FINGERPRINTING = "ads_fingerprinting";
+    public static final String OD_NAME_SECURITY_FINGERPRINTING = "security_fingerprinting";
+    public static final String OD_NAME_PRIVACY_POLICY = "privacy_policy";
+    public static final String OD_NAME_SECURITY_ENDPOINT = "security_endpoint";
+    public static final String OD_NAME_FIRST_PARTY_ENDPOINT = "first_party_endpoint";
+    public static final String OD_NAME_SERVICE_PROVIDER_ENDPOINT = "service_provider_endpoint";
+    public static final String OD_NAME_CATEGORY = "category";
+    public static final String OD_NAME_VERSION = "version";
+    public static final String OD_NAME_URL = "url";
+    public static final String OD_NAME_SYSTEM_APP_SAFETY_LABEL = "system_app_safety_label";
+    public static final String OD_NAME_SECURITY_LABELS = "security_labels";
+    public static final String OD_NAME_THIRD_PARTY_VERIFICATION = "third_party_verification";
+    public static final String OD_NAME_DATA_LABELS = "data_labels";
+    public static final String OD_NAME_DATA_ACCESSED = "data_accessed";
+    public static final String OD_NAME_DATA_COLLECTED = "data_collected";
+    public static final String OD_NAME_DATA_SHARED = "data_shared";
+    public static final String OD_NAME_PURPOSES = "purposes";
+    public static final String OD_NAME_IS_COLLECTION_OPTIONAL = "is_collection_optional";
+    public static final String OD_NAME_IS_SHARING_OPTIONAL = "is_sharing_optional";
+    public static final String OD_NAME_IS_DATA_DELETABLE = "is_data_deletable";
+    public static final String OD_NAME_IS_DATA_ENCRYPTED = "is_data_encrypted";
+    public static final String OD_NAME_EPHEMERAL = "ephemeral";
+
+    public static final String TRUE_STR = "true";
+    public static final String FALSE_STR = "false";
+
+    /** Gets the top-level children with the tag name.. */
+    public static List<Element> getChildrenByTagName(Node parentEle, String tagName) {
+        var elements = XmlUtils.asElementList(parentEle.getChildNodes());
+        return elements.stream().filter(e -> e.getTagName().equals(tagName)).toList();
+    }
+
+    /**
+     * Gets the single {@link Element} within {@param parentEle} and having the {@param tagName}.
+     */
+    public static Element getSingleChildElement(Node parentEle, String tagName, boolean required)
+            throws MalformedXmlException {
+        String parentTagNameForErrorMsg =
+                (parentEle instanceof Element) ? ((Element) parentEle).getTagName() : "Node";
+        var elements = getChildrenByTagName(parentEle, tagName);
+
+        if (elements.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "Expected 1 %s in %s but got %s.",
+                            tagName, parentTagNameForErrorMsg, elements.size()));
+        } else if (elements.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format(
+                                "Expected 1 %s in %s but got 0.",
+                                tagName, parentTagNameForErrorMsg));
+            } else {
+                return null;
+            }
+        }
+        return elements.get(0);
+    }
+
+    /** Gets the single {@link Element} within {@param elements}. */
+    public static Element getSingleElement(List<Element> elements) {
+        if (elements.size() != 1) {
+            throw new IllegalStateException(
+                    String.format("Expected 1 element in list but got %s.", elements.size()));
+        }
+        return elements.get(0);
+    }
+
+    /** Converts {@param nodeList} into List of {@link Element}. */
+    public static List<Element> asElementList(NodeList nodeList) {
+        List<Element> elementList = new ArrayList<Element>();
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            var elementAsNode = nodeList.item(i);
+            if (elementAsNode instanceof Element) {
+                elementList.add(((Element) elementAsNode));
+            }
+        }
+        return elementList;
+    }
+
+    /** Appends {@param children} to the {@param ele}. */
+    public static void appendChildren(Element ele, List<Element> children) {
+        for (Element c : children) {
+            ele.appendChild(c);
+        }
+    }
+
+    /** Gets the Boolean from the String value. */
+    private static Boolean fromString(String s) {
+        if (s == null) {
+            return null;
+        }
+        if (s.equals(TRUE_STR)) {
+            return true;
+        } else if (s.equals(FALSE_STR)) {
+            return false;
+        }
+        return null;
+    }
+
+    /** Creates an on-device PBundle DOM Element with the given attribute name. */
+    public static Element createPbundleEleWithName(Document doc, String name) {
+        var ele = doc.createElement(XmlUtils.OD_TAG_PBUNDLE_AS_MAP);
+        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
+        return ele;
+    }
+
+    /** Create an on-device Boolean DOM Element with the given attribute name. */
+    public static Element createOdBooleanEle(Document doc, String name, boolean b) {
+        var ele = doc.createElement(XmlUtils.OD_TAG_BOOLEAN);
+        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
+        ele.setAttribute(XmlUtils.OD_ATTR_VALUE, String.valueOf(b));
+        return ele;
+    }
+
+    /** Sets human-readable bool attribute if non-null. */
+    public static void maybeSetHrBoolAttr(Element ele, String attrName, Boolean b) {
+        if (b != null) {
+            ele.setAttribute(attrName, String.valueOf(b));
+        }
+    }
+
+    /** Create an on-device Long DOM Element with the given attribute name. */
+    public static Element createOdLongEle(Document doc, String name, long l) {
+        var ele = doc.createElement(XmlUtils.OD_TAG_LONG);
+        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
+        ele.setAttribute(XmlUtils.OD_ATTR_VALUE, String.valueOf(l));
+        return ele;
+    }
+
+    /** Create an on-device Long DOM Element with the given attribute name. */
+    public static Element createOdStringEle(Document doc, String name, String val) {
+        var ele = doc.createElement(XmlUtils.OD_TAG_STRING);
+        ele.setAttribute(XmlUtils.OD_ATTR_NAME, name);
+        ele.setAttribute(XmlUtils.OD_ATTR_VALUE, val);
+        return ele;
+    }
+
+    /** Create OD style array DOM Element, which can represent any time but is stored as Strings. */
+    public static Element createOdArray(
+            Document doc, String arrayTag, String arrayName, List<String> arrayVals) {
+        Element arrEle = doc.createElement(arrayTag);
+        arrEle.setAttribute(XmlUtils.OD_ATTR_NAME, arrayName);
+        arrEle.setAttribute(XmlUtils.OD_ATTR_NUM, String.valueOf(arrayVals.size()));
+        for (String s : arrayVals) {
+            Element itemEle = doc.createElement(XmlUtils.OD_TAG_ITEM);
+            itemEle.setAttribute(XmlUtils.OD_ATTR_VALUE, s);
+            arrEle.appendChild(itemEle);
+        }
+        return arrEle;
+    }
+
+    /** Returns whether the String is null or empty. */
+    public static boolean isNullOrEmpty(String s) {
+        return s == null || s.isEmpty();
+    }
+
+    /** Tries getting required version attribute and throws exception if it doesn't exist */
+    public static Long tryGetVersion(Element ele) throws MalformedXmlException {
+        long version;
+        try {
+            version = Long.parseLong(ele.getAttribute(XmlUtils.HR_ATTR_VERSION));
+        } catch (Exception e) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "Malformed or missing required version in: %s", ele.getTagName()));
+        }
+        return version;
+    }
+
+    /** Gets a pipeline-split attribute. */
+    public static List<String> getPipelineSplitAttr(Element ele, String attrName, boolean required)
+            throws MalformedXmlException {
+        List<String> list = Arrays.stream(ele.getAttribute(attrName).split("\\|")).toList();
+        if ((list.isEmpty() || list.get(0).isEmpty()) && required) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "Delimited string %s was required but missing, in %s.",
+                            attrName, ele.getTagName()));
+        }
+        return list;
+    }
+
+    /** Gets a Boolean attribute. */
+    public static Boolean getBoolAttr(Element ele, String attrName, boolean required)
+            throws MalformedXmlException {
+        Boolean b = XmlUtils.fromString(ele.getAttribute(attrName));
+        if (b == null && required) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "Boolean %s was required but missing, in %s.",
+                            attrName, ele.getTagName()));
+        }
+        return b;
+    }
+
+    /** Gets a Boolean attribute. */
+    public static Boolean getOdBoolEle(Element ele, String nameName, boolean required)
+            throws MalformedXmlException {
+        List<Element> boolEles =
+                XmlUtils.getChildrenByTagName(ele, XmlUtils.OD_TAG_BOOLEAN).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(nameName))
+                        .toList();
+        if (boolEles.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format("Found more than one %s in %s.", nameName, ele.getTagName()));
+        }
+        if (boolEles.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format("Found no %s in %s.", nameName, ele.getTagName()));
+            }
+            return null;
+        }
+        Element boolEle = boolEles.get(0);
+
+        Boolean b = XmlUtils.fromString(boolEle.getAttribute(XmlUtils.OD_ATTR_VALUE));
+        if (b == null && required) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "Boolean %s was required but missing, in %s.",
+                            nameName, ele.getTagName()));
+        }
+        return b;
+    }
+
+    /** Gets an on-device Long attribute. */
+    public static Long getOdLongEle(Element ele, String nameName, boolean required)
+            throws MalformedXmlException {
+        List<Element> longEles =
+                XmlUtils.getChildrenByTagName(ele, XmlUtils.OD_TAG_LONG).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(nameName))
+                        .toList();
+        if (longEles.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format("Found more than one %s in %s.", nameName, ele.getTagName()));
+        }
+        if (longEles.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format("Found no %s in %s.", nameName, ele.getTagName()));
+            }
+            return null;
+        }
+        Element longEle = longEles.get(0);
+        Long l = null;
+        try {
+            l = Long.parseLong(longEle.getAttribute(XmlUtils.OD_ATTR_VALUE));
+        } catch (NumberFormatException e) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "%s in %s was not formatted as long", nameName, ele.getTagName()));
+        }
+        return l;
+    }
+
+    /** Gets an on-device String attribute. */
+    public static String getOdStringEle(Element ele, String nameName, boolean required)
+            throws MalformedXmlException {
+        List<Element> eles =
+                XmlUtils.getChildrenByTagName(ele, XmlUtils.OD_TAG_STRING).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(nameName))
+                        .toList();
+        if (eles.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format("Found more than one %s in %s.", nameName, ele.getTagName()));
+        }
+        if (eles.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format("Found no %s in %s.", nameName, ele.getTagName()));
+            }
+            return null;
+        }
+        String str = eles.get(0).getAttribute(XmlUtils.OD_ATTR_VALUE);
+        if (XmlUtils.isNullOrEmpty(str) && required) {
+            throw new MalformedXmlException(
+                    String.format(
+                            "%s in %s was empty or missing value", nameName, ele.getTagName()));
+        }
+        return str;
+    }
+
+    /** Gets a OD Pbundle Element attribute with the specified name. */
+    public static Element getOdPbundleWithName(Element ele, String nameName, boolean required)
+            throws MalformedXmlException {
+        List<Element> eles =
+                XmlUtils.getChildrenByTagName(ele, XmlUtils.OD_TAG_PBUNDLE_AS_MAP).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(nameName))
+                        .toList();
+        if (eles.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format("Found more than one %s in %s.", nameName, ele.getTagName()));
+        }
+        if (eles.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format("Found no %s in %s.", nameName, ele.getTagName()));
+            }
+            return null;
+        }
+        return eles.get(0);
+    }
+
+    /** Gets a required String attribute. */
+    public static String getStringAttr(Element ele, String attrName) throws MalformedXmlException {
+        return getStringAttr(ele, attrName, true);
+    }
+
+    /** Gets a String attribute; throws exception if required and non-existent. */
+    public static String getStringAttr(Element ele, String attrName, boolean required)
+            throws MalformedXmlException {
+        String s = ele.getAttribute(attrName);
+        if (isNullOrEmpty(s)) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format(
+                                "Malformed or missing required %s in: %s",
+                                attrName, ele.getTagName()));
+            } else {
+                return null;
+            }
+        }
+        return s;
+    }
+
+    /** Gets on-device style int array. */
+    public static List<Integer> getOdIntArray(Element ele, String nameName, boolean required)
+            throws MalformedXmlException {
+        List<Element> intArrayEles =
+                XmlUtils.getChildrenByTagName(ele, XmlUtils.OD_TAG_INT_ARRAY).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(nameName))
+                        .toList();
+        if (intArrayEles.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format("Found more than one %s in %s.", nameName, ele.getTagName()));
+        }
+        if (intArrayEles.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format("Found no %s in %s.", nameName, ele.getTagName()));
+            }
+            return null;
+        }
+        Element intArrayEle = intArrayEles.get(0);
+        List<Element> itemEles = XmlUtils.getChildrenByTagName(intArrayEle, XmlUtils.OD_TAG_ITEM);
+        List<Integer> ints = new ArrayList<Integer>();
+        for (Element itemEle : itemEles) {
+            ints.add(Integer.parseInt(XmlUtils.getStringAttr(itemEle, XmlUtils.OD_ATTR_VALUE)));
+        }
+        return ints;
+    }
+
+    /** Gets on-device style String array. */
+    public static List<String> getOdStringArray(Element ele, String nameName, boolean required)
+            throws MalformedXmlException {
+        List<Element> arrayEles =
+                XmlUtils.getChildrenByTagName(ele, XmlUtils.OD_TAG_STRING_ARRAY).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(nameName))
+                        .toList();
+        if (arrayEles.size() > 1) {
+            throw new MalformedXmlException(
+                    String.format("Found more than one %s in %s.", nameName, ele.getTagName()));
+        }
+        if (arrayEles.isEmpty()) {
+            if (required) {
+                throw new MalformedXmlException(
+                        String.format("Found no %s in %s.", nameName, ele.getTagName()));
+            }
+            return null;
+        }
+        Element arrayEle = arrayEles.get(0);
+        List<Element> itemEles = XmlUtils.getChildrenByTagName(arrayEle, XmlUtils.OD_TAG_ITEM);
+        List<String> strs = new ArrayList<String>();
+        for (Element itemEle : itemEles) {
+            strs.add(XmlUtils.getStringAttr(itemEle, XmlUtils.OD_ATTR_VALUE, true));
+        }
+        return strs;
+    }
+
+    /**
+     * Utility method for making a List from one element, to support easier refactoring if needed.
+     * For example, List.of() doesn't support null elements.
+     */
+    public static List<Element> listOf(Element e) {
+        return Arrays.asList(e);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java b/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java
deleted file mode 100644
index 7ebb7a1..0000000
--- a/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.aslgen;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@RunWith(Suite.class)
[email protected]({
-    AslgenTests.class,
-})
-public class AllTests {}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java b/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java
deleted file mode 100644
index 3026f8b..0000000
--- a/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.aslgen;
-
-import static org.junit.Assert.assertEquals;
-
-import com.android.asllib.AndroidSafetyLabel;
-import com.android.asllib.AslConverter;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-@RunWith(JUnit4.class)
-public class AslgenTests {
-    private static final String VALID_MAPPINGS_PATH = "com/android/aslgen/validmappings";
-    private static final List<String> VALID_MAPPINGS_SUBDIRS = List.of("location", "contacts");
-    private static final String HR_XML_FILENAME = "hr.xml";
-    private static final String OD_XML_FILENAME = "od.xml";
-
-    /** Logic for setting up tests (empty if not yet needed). */
-    public static void main(String[] params) throws Exception {}
-
-    /** Tests valid mappings between HR and OD. */
-    @Test
-    public void testValidMappings() throws Exception {
-        System.out.println("start testing valid mappings.");
-
-        for (String subdir : VALID_MAPPINGS_SUBDIRS) {
-            Path hrPath = Paths.get(VALID_MAPPINGS_PATH, subdir, HR_XML_FILENAME);
-            Path odPath = Paths.get(VALID_MAPPINGS_PATH, subdir, OD_XML_FILENAME);
-
-            System.out.println("hr path: " + hrPath.toString());
-            System.out.println("od path: " + odPath.toString());
-
-            InputStream hrStream =
-                    getClass().getClassLoader().getResourceAsStream(hrPath.toString());
-            String hrContents = new String(hrStream.readAllBytes(), StandardCharsets.UTF_8);
-            InputStream odStream =
-                    getClass().getClassLoader().getResourceAsStream(odPath.toString());
-            String odContents = new String(odStream.readAllBytes(), StandardCharsets.UTF_8);
-            AndroidSafetyLabel asl =
-                    AslConverter.readFromString(hrContents, AslConverter.Format.HUMAN_READABLE);
-            String out = AslConverter.getXmlAsString(asl, AslConverter.Format.ON_DEVICE);
-            System.out.println("out: " + out);
-
-            assertEquals(getFormattedXml(out), getFormattedXml(odContents));
-        }
-    }
-
-    private static String getFormattedXml(String xmlStr)
-            throws ParserConfigurationException, IOException, SAXException, TransformerException {
-        InputStream stream = new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8));
-        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        factory.setNamespaceAware(true);
-        Document document = factory.newDocumentBuilder().parse(stream);
-
-        TransformerFactory transformerFactory = TransformerFactory.newInstance();
-        Transformer transformer = transformerFactory.newTransformer();
-        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
-        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
-
-        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-        StreamResult streamResult = new StreamResult(outStream); // out
-        DOMSource domSource = new DOMSource(document);
-        transformer.transform(domSource, streamResult);
-
-        return outStream.toString(StandardCharsets.UTF_8);
-    }
-}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java
new file mode 100644
index 0000000..54c80f6
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib;
+
+import com.android.asllib.marshallable.AndroidSafetyLabelTest;
+import com.android.asllib.marshallable.AppInfoTest;
+import com.android.asllib.marshallable.DataCategoryTest;
+import com.android.asllib.marshallable.DataLabelsTest;
+import com.android.asllib.marshallable.DeveloperInfoTest;
+import com.android.asllib.marshallable.SafetyLabelsTest;
+import com.android.asllib.marshallable.SecurityLabelsTest;
+import com.android.asllib.marshallable.SystemAppSafetyLabelTest;
+import com.android.asllib.marshallable.ThirdPartyVerificationTest;
+import com.android.asllib.marshallable.TransparencyInfoTest;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
[email protected]({
+    AslgenTests.class,
+    AndroidSafetyLabelTest.class,
+    AppInfoTest.class,
+    DataCategoryTest.class,
+    DataLabelsTest.class,
+    DeveloperInfoTest.class,
+    SafetyLabelsTest.class,
+    SecurityLabelsTest.class,
+    SystemAppSafetyLabelTest.class,
+    ThirdPartyVerificationTest.class,
+    TransparencyInfoTest.class
+})
+public class AllTests {}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/AslgenTests.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/AslgenTests.java
new file mode 100644
index 0000000..d2e0fc3
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/AslgenTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.asllib.marshallable.AndroidSafetyLabel;
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class AslgenTests {
+    private static final String VALID_MAPPINGS_PATH = "com/android/asllib/validmappings";
+    private static final List<String> VALID_MAPPINGS_SUBDIRS =
+            List.of("location", "contacts", "general");
+    private static final String HR_XML_FILENAME = "hr.xml";
+    private static final String OD_XML_FILENAME = "od.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    /** Tests valid mappings between HR and OD. */
+    @Test
+    public void testValidMappings() throws Exception {
+        System.out.println("start testing valid mappings.");
+
+        for (String subdir : VALID_MAPPINGS_SUBDIRS) {
+            Path hrPath = Paths.get(VALID_MAPPINGS_PATH, subdir, HR_XML_FILENAME);
+            Path odPath = Paths.get(VALID_MAPPINGS_PATH, subdir, OD_XML_FILENAME);
+
+            System.out.println("hr path: " + hrPath.toString());
+            System.out.println("od path: " + odPath.toString());
+
+            InputStream hrStream =
+                    getClass().getClassLoader().getResourceAsStream(hrPath.toString());
+            String hrContents =
+                    TestUtils.getFormattedXml(
+                            new String(hrStream.readAllBytes(), StandardCharsets.UTF_8), false);
+            InputStream odStream =
+                    getClass().getClassLoader().getResourceAsStream(odPath.toString());
+            String odContents =
+                    TestUtils.getFormattedXml(
+                            new String(odStream.readAllBytes(), StandardCharsets.UTF_8), false);
+            AndroidSafetyLabel aslFromHr =
+                    AslConverter.readFromString(hrContents, AslConverter.Format.HUMAN_READABLE);
+            String aslToOdStr =
+                    TestUtils.getFormattedXml(
+                            AslConverter.getXmlAsString(aslFromHr, AslConverter.Format.ON_DEVICE),
+                            false);
+            AndroidSafetyLabel aslFromOd =
+                    AslConverter.readFromString(odContents, AslConverter.Format.ON_DEVICE);
+            String aslToHrStr =
+                    TestUtils.getFormattedXml(
+                            AslConverter.getXmlAsString(
+                                    aslFromOd, AslConverter.Format.HUMAN_READABLE),
+                            false);
+
+            System.out.println("od expected: " + odContents);
+            System.out.println("asl to od: " + aslToOdStr);
+            assertEquals(odContents, aslToOdStr);
+
+            System.out.println("hr expected: " + hrContents);
+            System.out.println("asl to hr: " + aslToHrStr);
+            assertEquals(hrContents, aslToHrStr);
+        }
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AndroidSafetyLabelTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AndroidSafetyLabelTest.java
new file mode 100644
index 0000000..61a7823
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AndroidSafetyLabelTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AndroidSafetyLabelTest {
+    private static final String ANDROID_SAFETY_LABEL_HR_PATH =
+            "com/android/asllib/androidsafetylabel/hr";
+    private static final String ANDROID_SAFETY_LABEL_OD_PATH =
+            "com/android/asllib/androidsafetylabel/od";
+
+    private static final String MISSING_VERSION_FILE_NAME = "missing-version.xml";
+    private static final String VALID_EMPTY_FILE_NAME = "valid-empty.xml";
+    private static final String WITH_SAFETY_LABELS_FILE_NAME = "with-safety-labels.xml";
+    private static final String WITH_SYSTEM_APP_SAFETY_LABEL_FILE_NAME =
+            "with-system-app-safety-label.xml";
+    private static final String WITH_TRANSPARENCY_INFO_FILE_NAME = "with-transparency-info.xml";
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for android safety label missing version. */
+    @Test
+    public void testAndroidSafetyLabelMissingVersion() throws Exception {
+        System.out.println("starting testAndroidSafetyLabelMissingVersion.");
+        hrToOdExpectException(MISSING_VERSION_FILE_NAME);
+        odToHrExpectException(MISSING_VERSION_FILE_NAME);
+    }
+
+    /** Test for android safety label valid empty. */
+    @Test
+    public void testAndroidSafetyLabelValidEmptyFile() throws Exception {
+        System.out.println("starting testAndroidSafetyLabelValidEmptyFile.");
+        testHrToOdAndroidSafetyLabel(VALID_EMPTY_FILE_NAME);
+        testOdToHrAndroidSafetyLabel(VALID_EMPTY_FILE_NAME);
+    }
+
+    /** Test for android safety label with safety labels. */
+    @Test
+    public void testAndroidSafetyLabelWithSafetyLabels() throws Exception {
+        System.out.println("starting testAndroidSafetyLabelWithSafetyLabels.");
+        testHrToOdAndroidSafetyLabel(WITH_SAFETY_LABELS_FILE_NAME);
+        testOdToHrAndroidSafetyLabel(WITH_SAFETY_LABELS_FILE_NAME);
+    }
+
+    /** Test for android safety label with system app safety label. */
+    @Test
+    public void testAndroidSafetyLabelWithSystemAppSafetyLabel() throws Exception {
+        System.out.println("starting testAndroidSafetyLabelWithSystemAppSafetyLabel.");
+        testHrToOdAndroidSafetyLabel(WITH_SYSTEM_APP_SAFETY_LABEL_FILE_NAME);
+        testOdToHrAndroidSafetyLabel(WITH_SYSTEM_APP_SAFETY_LABEL_FILE_NAME);
+    }
+
+    /** Test for android safety label with transparency info. */
+    @Test
+    public void testAndroidSafetyLabelWithTransparencyInfo() throws Exception {
+        System.out.println("starting testAndroidSafetyLabelWithTransparencyInfo.");
+        testHrToOdAndroidSafetyLabel(WITH_TRANSPARENCY_INFO_FILE_NAME);
+        testOdToHrAndroidSafetyLabel(WITH_TRANSPARENCY_INFO_FILE_NAME);
+    }
+
+    private void hrToOdExpectException(String fileName) {
+        TestUtils.hrToOdExpectException(
+                new AndroidSafetyLabelFactory(), ANDROID_SAFETY_LABEL_HR_PATH, fileName);
+    }
+
+    private void odToHrExpectException(String fileName) {
+        TestUtils.odToHrExpectException(
+                new AndroidSafetyLabelFactory(), ANDROID_SAFETY_LABEL_OD_PATH, fileName);
+    }
+
+    private void testHrToOdAndroidSafetyLabel(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new AndroidSafetyLabelFactory(),
+                ANDROID_SAFETY_LABEL_HR_PATH,
+                ANDROID_SAFETY_LABEL_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrAndroidSafetyLabel(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new AndroidSafetyLabelFactory(),
+                ANDROID_SAFETY_LABEL_OD_PATH,
+                ANDROID_SAFETY_LABEL_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java
new file mode 100644
index 0000000..9e91c6f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import static org.junit.Assert.assertThrows;
+
+import com.android.asllib.testutils.TestUtils;
+import com.android.asllib.util.MalformedXmlException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.nio.file.Paths;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class AppInfoTest {
+    private static final String APP_INFO_HR_PATH = "com/android/asllib/appinfo/hr";
+    private static final String APP_INFO_OD_PATH = "com/android/asllib/appinfo/od";
+    public static final List<String> REQUIRED_FIELD_NAMES =
+            List.of(
+                    "title",
+                    "description",
+                    "containsAds",
+                    "obeyAps",
+                    "adsFingerprinting",
+                    "securityFingerprinting",
+                    "privacyPolicy",
+                    "securityEndpoints",
+                    "firstPartyEndpoints",
+                    "serviceProviderEndpoints",
+                    "category",
+                    "email");
+    public static final List<String> REQUIRED_FIELD_NAMES_OD =
+            List.of(
+                    "title",
+                    "description",
+                    "contains_ads",
+                    "obey_aps",
+                    "ads_fingerprinting",
+                    "security_fingerprinting",
+                    "privacy_policy",
+                    "security_endpoint",
+                    "first_party_endpoint",
+                    "service_provider_endpoint",
+                    "category",
+                    "email");
+    public static final List<String> OPTIONAL_FIELD_NAMES = List.of("website");
+    public static final List<String> OPTIONAL_FIELD_NAMES_OD = List.of("website");
+
+    private static final String ALL_FIELDS_VALID_FILE_NAME = "all-fields-valid.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for all fields valid. */
+    @Test
+    public void testAllFieldsValid() throws Exception {
+        System.out.println("starting testAllFieldsValid.");
+        testHrToOdAppInfo(ALL_FIELDS_VALID_FILE_NAME);
+        testOdToHrAppInfo(ALL_FIELDS_VALID_FILE_NAME);
+    }
+
+    /** Tests missing required fields fails. */
+    @Test
+    public void testMissingRequiredFields() throws Exception {
+        System.out.println("Starting testMissingRequiredFields");
+        for (String reqField : REQUIRED_FIELD_NAMES) {
+            System.out.println("testing missing required field hr: " + reqField);
+            var appInfoEle =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(APP_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            appInfoEle.get(0).removeAttribute(reqField);
+
+            assertThrows(
+                    MalformedXmlException.class,
+                    () -> new AppInfoFactory().createFromHrElements(appInfoEle));
+        }
+
+        for (String reqField : REQUIRED_FIELD_NAMES_OD) {
+            System.out.println("testing missing required field od: " + reqField);
+            var appInfoEle =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(APP_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            TestUtils.removeOdChildEleWithName(appInfoEle.get(0), reqField);
+            assertThrows(
+                    MalformedXmlException.class,
+                    () -> new AppInfoFactory().createFromOdElements(appInfoEle));
+        }
+    }
+
+    /** Tests missing optional fields passes. */
+    @Test
+    public void testMissingOptionalFields() throws Exception {
+        for (String optField : OPTIONAL_FIELD_NAMES) {
+            var ele =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(APP_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            ele.get(0).removeAttribute(optField);
+            AppInfo appInfo = new AppInfoFactory().createFromHrElements(ele);
+            appInfo.toOdDomElements(TestUtils.document());
+        }
+
+        for (String optField : OPTIONAL_FIELD_NAMES_OD) {
+            var ele =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(APP_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            TestUtils.removeOdChildEleWithName(ele.get(0), optField);
+            AppInfo appInfo = new AppInfoFactory().createFromOdElements(ele);
+            appInfo.toHrDomElements(TestUtils.document());
+        }
+    }
+
+    private void testHrToOdAppInfo(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new AppInfoFactory(),
+                APP_INFO_HR_PATH,
+                APP_INFO_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrAppInfo(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new AppInfoFactory(),
+                APP_INFO_OD_PATH,
+                APP_INFO_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DataCategoryTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DataCategoryTest.java
new file mode 100644
index 0000000..ebb3186
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DataCategoryTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DataCategoryTest {
+    private static final String DATA_CATEGORY_HR_PATH = "com/android/asllib/datacategory/hr";
+    private static final String DATA_CATEGORY_OD_PATH = "com/android/asllib/datacategory/od";
+
+    private static final String VALID_PERSONAL_FILE_NAME = "data-category-personal.xml";
+    private static final String VALID_PARTIAL_PERSONAL_FILE_NAME =
+            "data-category-personal-partial.xml";
+    private static final String VALID_FINANCIAL_FILE_NAME = "data-category-financial.xml";
+    private static final String VALID_LOCATION_FILE_NAME = "data-category-location.xml";
+    private static final String VALID_EMAIL_TEXT_MESSAGE_FILE_NAME =
+            "data-category-email-text-message.xml";
+    private static final String VALID_PHOTO_VIDEO_FILE_NAME = "data-category-photo-video.xml";
+    private static final String VALID_AUDIO_FILE_NAME = "data-category-audio.xml";
+    private static final String VALID_STORAGE_FILE_NAME = "data-category-storage.xml";
+    private static final String VALID_HEALTH_FITNESS_FILE_NAME = "data-category-health-fitness.xml";
+    private static final String VALID_CONTACTS_FILE_NAME = "data-category-contacts.xml";
+    private static final String VALID_CALENDAR_FILE_NAME = "data-category-calendar.xml";
+    private static final String VALID_IDENTIFIERS_FILE_NAME = "data-category-identifiers.xml";
+    private static final String VALID_APP_PERFORMANCE_FILE_NAME =
+            "data-category-app-performance.xml";
+    private static final String VALID_ACTIONS_IN_APP_FILE_NAME = "data-category-actions-in-app.xml";
+    private static final String VALID_SEARCH_AND_BROWSING_FILE_NAME =
+            "data-category-search-and-browsing.xml";
+
+    private static final String EMPTY_PURPOSE_PERSONAL_FILE_NAME =
+            "data-category-personal-empty-purpose.xml";
+    private static final String MISSING_PURPOSE_PERSONAL_FILE_NAME =
+            "data-category-personal-missing-purpose.xml";
+    private static final String UNRECOGNIZED_TYPE_PERSONAL_FILE_NAME =
+            "data-category-personal-unrecognized-type.xml";
+    private static final String UNRECOGNIZED_CATEGORY_FILE_NAME = "data-category-unrecognized.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for data category personal. */
+    @Test
+    public void testDataCategoryPersonal() throws Exception {
+        System.out.println("starting testDataCategoryPersonal.");
+        testHrToOdDataCategory(VALID_PERSONAL_FILE_NAME);
+    }
+
+    /** Test for data category financial. */
+    @Test
+    public void testDataCategoryFinancial() throws Exception {
+        System.out.println("starting testDataCategoryFinancial.");
+        testHrToOdDataCategory(VALID_FINANCIAL_FILE_NAME);
+    }
+
+    /** Test for data category location. */
+    @Test
+    public void testDataCategoryLocation() throws Exception {
+        System.out.println("starting testDataCategoryLocation.");
+        testHrToOdDataCategory(VALID_LOCATION_FILE_NAME);
+    }
+
+    /** Test for data category email text message. */
+    @Test
+    public void testDataCategoryEmailTextMessage() throws Exception {
+        System.out.println("starting testDataCategoryEmailTextMessage.");
+        testHrToOdDataCategory(VALID_EMAIL_TEXT_MESSAGE_FILE_NAME);
+    }
+
+    /** Test for data category photo video. */
+    @Test
+    public void testDataCategoryPhotoVideo() throws Exception {
+        System.out.println("starting testDataCategoryPhotoVideo.");
+        testHrToOdDataCategory(VALID_PHOTO_VIDEO_FILE_NAME);
+    }
+
+    /** Test for data category audio. */
+    @Test
+    public void testDataCategoryAudio() throws Exception {
+        System.out.println("starting testDataCategoryAudio.");
+        testHrToOdDataCategory(VALID_AUDIO_FILE_NAME);
+    }
+
+    /** Test for data category storage. */
+    @Test
+    public void testDataCategoryStorage() throws Exception {
+        System.out.println("starting testDataCategoryStorage.");
+        testHrToOdDataCategory(VALID_STORAGE_FILE_NAME);
+    }
+
+    /** Test for data category health fitness. */
+    @Test
+    public void testDataCategoryHealthFitness() throws Exception {
+        System.out.println("starting testDataCategoryHealthFitness.");
+        testHrToOdDataCategory(VALID_HEALTH_FITNESS_FILE_NAME);
+    }
+
+    /** Test for data category contacts. */
+    @Test
+    public void testDataCategoryContacts() throws Exception {
+        System.out.println("starting testDataCategoryContacts.");
+        testHrToOdDataCategory(VALID_CONTACTS_FILE_NAME);
+    }
+
+    /** Test for data category calendar. */
+    @Test
+    public void testDataCategoryCalendar() throws Exception {
+        System.out.println("starting testDataCategoryCalendar.");
+        testHrToOdDataCategory(VALID_CALENDAR_FILE_NAME);
+    }
+
+    /** Test for data category identifiers. */
+    @Test
+    public void testDataCategoryIdentifiers() throws Exception {
+        System.out.println("starting testDataCategoryIdentifiers.");
+        testHrToOdDataCategory(VALID_IDENTIFIERS_FILE_NAME);
+    }
+
+    /** Test for data category app performance. */
+    @Test
+    public void testDataCategoryAppPerformance() throws Exception {
+        System.out.println("starting testDataCategoryAppPerformance.");
+        testHrToOdDataCategory(VALID_APP_PERFORMANCE_FILE_NAME);
+    }
+
+    /** Test for data category actions in app. */
+    @Test
+    public void testDataCategoryActionsInApp() throws Exception {
+        System.out.println("starting testDataCategoryActionsInApp.");
+        testHrToOdDataCategory(VALID_ACTIONS_IN_APP_FILE_NAME);
+    }
+
+    /** Test for data category search and browsing. */
+    @Test
+    public void testDataCategorySearchAndBrowsing() throws Exception {
+        System.out.println("starting testDataCategorySearchAndBrowsing.");
+        testHrToOdDataCategory(VALID_SEARCH_AND_BROWSING_FILE_NAME);
+    }
+
+    /** Test for data category search and browsing. */
+    @Test
+    public void testMissingOptionalsAllowed() throws Exception {
+        System.out.println("starting testMissingOptionalsAllowed.");
+        testHrToOdDataCategory(VALID_PARTIAL_PERSONAL_FILE_NAME);
+    }
+
+    /** Test for empty purposes. */
+    @Test
+    public void testEmptyPurposesNotAllowed() throws Exception {
+        System.out.println("starting testEmptyPurposesNotAllowed.");
+        hrToOdExpectException(EMPTY_PURPOSE_PERSONAL_FILE_NAME);
+    }
+
+    /** Test for missing purposes. */
+    @Test
+    public void testMissingPurposesNotAllowed() throws Exception {
+        System.out.println("starting testMissingPurposesNotAllowed.");
+        hrToOdExpectException(MISSING_PURPOSE_PERSONAL_FILE_NAME);
+    }
+
+    /** Test for unrecognized type. */
+    @Test
+    public void testUnrecognizedTypeNotAllowed() throws Exception {
+        System.out.println("starting testUnrecognizedTypeNotAllowed.");
+        hrToOdExpectException(UNRECOGNIZED_TYPE_PERSONAL_FILE_NAME);
+    }
+
+    /** Test for unrecognized category. */
+    @Test
+    public void testUnrecognizedCategoryNotAllowed() throws Exception {
+        System.out.println("starting testUnrecognizedCategoryNotAllowed.");
+        hrToOdExpectException(UNRECOGNIZED_CATEGORY_FILE_NAME);
+    }
+
+    private void hrToOdExpectException(String fileName) {
+        TestUtils.hrToOdExpectException(new DataCategoryFactory(), DATA_CATEGORY_HR_PATH, fileName);
+    }
+
+    private void testHrToOdDataCategory(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new DataCategoryFactory(),
+                DATA_CATEGORY_HR_PATH,
+                DATA_CATEGORY_OD_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DataLabelsTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DataLabelsTest.java
new file mode 100644
index 0000000..2661726
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DataLabelsTest.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DataLabelsTest {
+    private static final String DATA_LABELS_HR_PATH = "com/android/asllib/datalabels/hr";
+    private static final String DATA_LABELS_OD_PATH = "com/android/asllib/datalabels/od";
+
+    private static final String ACCESSED_VALID_BOOL_FILE_NAME =
+            "data-labels-accessed-valid-bool.xml";
+    private static final String ACCESSED_INVALID_BOOL_FILE_NAME =
+            "data-labels-accessed-invalid-bool.xml";
+    private static final String COLLECTED_VALID_BOOL_FILE_NAME =
+            "data-labels-collected-valid-bool.xml";
+    private static final String COLLECTED_INVALID_BOOL_FILE_NAME =
+            "data-labels-collected-invalid-bool.xml";
+    private static final String SHARED_VALID_BOOL_FILE_NAME = "data-labels-shared-valid-bool.xml";
+    private static final String SHARED_INVALID_BOOL_FILE_NAME =
+            "data-labels-shared-invalid-bool.xml";
+
+    private static final String ACTIONS_IN_APP_FILE_NAME = "data-category-actions-in-app.xml";
+    private static final String APP_PERFORMANCE_FILE_NAME = "data-category-app-performance.xml";
+    private static final String AUDIO_FILE_NAME = "data-category-audio.xml";
+    private static final String CALENDAR_FILE_NAME = "data-category-calendar.xml";
+    private static final String CONTACTS_FILE_NAME = "data-category-contacts.xml";
+    private static final String EMAIL_TEXT_MESSAGE_FILE_NAME =
+            "data-category-email-text-message.xml";
+    private static final String FINANCIAL_FILE_NAME = "data-category-financial.xml";
+    private static final String HEALTH_FITNESS_FILE_NAME = "data-category-health-fitness.xml";
+    private static final String IDENTIFIERS_FILE_NAME = "data-category-identifiers.xml";
+    private static final String LOCATION_FILE_NAME = "data-category-location.xml";
+    private static final String PERSONAL_FILE_NAME = "data-category-personal.xml";
+    private static final String PERSONAL_PARTIAL_FILE_NAME = "data-category-personal-partial.xml";
+    private static final String PHOTO_VIDEO_FILE_NAME = "data-category-photo-video.xml";
+    private static final String SEARCH_AND_BROWSING_FILE_NAME =
+            "data-category-search-and-browsing.xml";
+    private static final String STORAGE_FILE_NAME = "data-category-storage.xml";
+    private static final String PERSONAL_MISSING_PURPOSE_FILE_NAME =
+            "data-category-personal-missing-purpose.xml";
+    private static final String PERSONAL_EMPTY_PURPOSE_FILE_NAME =
+            "data-category-personal-empty-purpose.xml";
+    private static final String UNRECOGNIZED_FILE_NAME = "data-category-unrecognized.xml";
+    private static final String UNRECOGNIZED_TYPE_FILE_NAME = "data-category-unrecognized-type.xml";
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for data labels accessed valid bool. */
+    @Test
+    public void testDataLabelsAccessedValidBool() throws Exception {
+        System.out.println("starting testDataLabelsAccessedValidBool.");
+        testHrToOdDataLabels(ACCESSED_VALID_BOOL_FILE_NAME);
+        testOdToHrDataLabels(ACCESSED_VALID_BOOL_FILE_NAME);
+    }
+
+    /** Test for data labels accessed invalid bool. */
+    @Test
+    public void testDataLabelsAccessedInvalidBool() throws Exception {
+        System.out.println("starting testDataLabelsAccessedInvalidBool.");
+        hrToOdExpectException(ACCESSED_INVALID_BOOL_FILE_NAME);
+    }
+
+    /** Test for data labels collected valid bool. */
+    @Test
+    public void testDataLabelsCollectedValidBool() throws Exception {
+        System.out.println("starting testDataLabelsCollectedValidBool.");
+        testHrToOdDataLabels(COLLECTED_VALID_BOOL_FILE_NAME);
+        testOdToHrDataLabels(COLLECTED_VALID_BOOL_FILE_NAME);
+    }
+
+    /** Test for data labels collected invalid bool. */
+    @Test
+    public void testDataLabelsCollectedInvalidBool() throws Exception {
+        System.out.println("starting testDataLabelsCollectedInvalidBool.");
+        hrToOdExpectException(COLLECTED_INVALID_BOOL_FILE_NAME);
+        odToHrExpectException(COLLECTED_INVALID_BOOL_FILE_NAME);
+    }
+
+    /** Test for data labels shared valid bool. */
+    @Test
+    public void testDataLabelsSharedValidBool() throws Exception {
+        System.out.println("starting testDataLabelsSharedValidBool.");
+        testHrToOdDataLabels(SHARED_VALID_BOOL_FILE_NAME);
+        testOdToHrDataLabels(SHARED_VALID_BOOL_FILE_NAME);
+    }
+
+    /** Test for data labels shared invalid bool. */
+    @Test
+    public void testDataLabelsSharedInvalidBool() throws Exception {
+        System.out.println("starting testDataLabelsSharedInvalidBool.");
+        hrToOdExpectException(SHARED_INVALID_BOOL_FILE_NAME);
+    }
+
+    /* Data categories bidirectional tests... */
+
+    /** Test for data labels actions in app. */
+    @Test
+    public void testDataLabelsActionsInApp() throws Exception {
+        System.out.println("starting testDataLabelsActionsInApp.");
+        testHrToOdDataLabels(ACTIONS_IN_APP_FILE_NAME);
+        testOdToHrDataLabels(ACTIONS_IN_APP_FILE_NAME);
+    }
+
+    /** Test for data labels app performance. */
+    @Test
+    public void testDataLabelsAppPerformance() throws Exception {
+        System.out.println("starting testDataLabelsAppPerformance.");
+        testHrToOdDataLabels(APP_PERFORMANCE_FILE_NAME);
+        testOdToHrDataLabels(APP_PERFORMANCE_FILE_NAME);
+    }
+
+    /** Test for data labels audio. */
+    @Test
+    public void testDataLabelsAudio() throws Exception {
+        System.out.println("starting testDataLabelsAudio.");
+        testHrToOdDataLabels(AUDIO_FILE_NAME);
+        testOdToHrDataLabels(AUDIO_FILE_NAME);
+    }
+
+    /** Test for data labels calendar. */
+    @Test
+    public void testDataLabelsCalendar() throws Exception {
+        System.out.println("starting testDataLabelsCalendar.");
+        testHrToOdDataLabels(CALENDAR_FILE_NAME);
+        testOdToHrDataLabels(CALENDAR_FILE_NAME);
+    }
+
+    /** Test for data labels contacts. */
+    @Test
+    public void testDataLabelsContacts() throws Exception {
+        System.out.println("starting testDataLabelsContacts.");
+        testHrToOdDataLabels(CONTACTS_FILE_NAME);
+        testOdToHrDataLabels(CONTACTS_FILE_NAME);
+    }
+
+    /** Test for data labels email text message. */
+    @Test
+    public void testDataLabelsEmailTextMessage() throws Exception {
+        System.out.println("starting testDataLabelsEmailTextMessage.");
+        testHrToOdDataLabels(EMAIL_TEXT_MESSAGE_FILE_NAME);
+        testOdToHrDataLabels(EMAIL_TEXT_MESSAGE_FILE_NAME);
+    }
+
+    /** Test for data labels financial. */
+    @Test
+    public void testDataLabelsFinancial() throws Exception {
+        System.out.println("starting testDataLabelsFinancial.");
+        testHrToOdDataLabels(FINANCIAL_FILE_NAME);
+        testOdToHrDataLabels(FINANCIAL_FILE_NAME);
+    }
+
+    /** Test for data labels health fitness. */
+    @Test
+    public void testDataLabelsHealthFitness() throws Exception {
+        System.out.println("starting testDataLabelsHealthFitness.");
+        testHrToOdDataLabels(HEALTH_FITNESS_FILE_NAME);
+        testOdToHrDataLabels(HEALTH_FITNESS_FILE_NAME);
+    }
+
+    /** Test for data labels identifiers. */
+    @Test
+    public void testDataLabelsIdentifiers() throws Exception {
+        System.out.println("starting testDataLabelsIdentifiers.");
+        testHrToOdDataLabels(IDENTIFIERS_FILE_NAME);
+        testOdToHrDataLabels(IDENTIFIERS_FILE_NAME);
+    }
+
+    /** Test for data labels location. */
+    @Test
+    public void testDataLabelsLocation() throws Exception {
+        System.out.println("starting testDataLabelsLocation.");
+        testHrToOdDataLabels(LOCATION_FILE_NAME);
+        testOdToHrDataLabels(LOCATION_FILE_NAME);
+    }
+
+    /** Test for data labels personal. */
+    @Test
+    public void testDataLabelsPersonal() throws Exception {
+        System.out.println("starting testDataLabelsPersonal.");
+        testHrToOdDataLabels(PERSONAL_FILE_NAME);
+        testOdToHrDataLabels(PERSONAL_FILE_NAME);
+    }
+
+    /** Test for data labels personal partial. */
+    @Test
+    public void testDataLabelsPersonalPartial() throws Exception {
+        System.out.println("starting testDataLabelsPersonalPartial.");
+        testHrToOdDataLabels(PERSONAL_PARTIAL_FILE_NAME);
+        testOdToHrDataLabels(PERSONAL_PARTIAL_FILE_NAME);
+    }
+
+    /** Test for data labels photo video. */
+    @Test
+    public void testDataLabelsPhotoVideo() throws Exception {
+        System.out.println("starting testDataLabelsPhotoVideo.");
+        testHrToOdDataLabels(PHOTO_VIDEO_FILE_NAME);
+        testOdToHrDataLabels(PHOTO_VIDEO_FILE_NAME);
+    }
+
+    /** Test for data labels search and browsing. */
+    @Test
+    public void testDataLabelsSearchAndBrowsing() throws Exception {
+        System.out.println("starting testDataLabelsSearchAndBrowsing.");
+        testHrToOdDataLabels(SEARCH_AND_BROWSING_FILE_NAME);
+        testOdToHrDataLabels(SEARCH_AND_BROWSING_FILE_NAME);
+    }
+
+    /** Test for data labels storage. */
+    @Test
+    public void testDataLabelsStorage() throws Exception {
+        System.out.println("starting testDataLabelsStorage.");
+        testHrToOdDataLabels(STORAGE_FILE_NAME);
+        testOdToHrDataLabels(STORAGE_FILE_NAME);
+    }
+
+    /** Test for data labels hr unrecognized data category. */
+    @Test
+    public void testDataLabelsHrUnrecognizedDataCategory() throws Exception {
+        System.out.println("starting testDataLabelsHrUnrecognizedDataCategory.");
+        hrToOdExpectException(UNRECOGNIZED_FILE_NAME);
+    }
+
+    /** Test for data labels hr unrecognized data type. */
+    @Test
+    public void testDataLabelsHrUnrecognizedDataType() throws Exception {
+        System.out.println("starting testDataLabelsHrUnrecognizedDataType.");
+        hrToOdExpectException(UNRECOGNIZED_TYPE_FILE_NAME);
+    }
+
+    /** Test for data labels hr missing purpose. */
+    @Test
+    public void testDataLabelsHrMissingPurpose() throws Exception {
+        System.out.println("starting testDataLabelsHrMissingPurpose.");
+        hrToOdExpectException(PERSONAL_MISSING_PURPOSE_FILE_NAME);
+    }
+
+    /** Test for data labels hr empty purpose. */
+    @Test
+    public void testDataLabelsHrEmptyPurpose() throws Exception {
+        System.out.println("starting testDataLabelsHrEmptyPurpose.");
+        hrToOdExpectException(PERSONAL_EMPTY_PURPOSE_FILE_NAME);
+    }
+
+    /** Test for data labels od unrecognized data category. */
+    @Test
+    public void testDataLabelsOdUnrecognizedDataCategory() throws Exception {
+        System.out.println("starting testDataLabelsOdUnrecognizedDataCategory.");
+        odToHrExpectException(UNRECOGNIZED_FILE_NAME);
+    }
+
+    /** Test for data labels od unrecognized data type. */
+    @Test
+    public void testDataLabelsOdUnrecognizedDataType() throws Exception {
+        System.out.println("starting testDataLabelsOdUnrecognizedDataCategory.");
+        odToHrExpectException(UNRECOGNIZED_TYPE_FILE_NAME);
+    }
+
+    /** Test for data labels od missing purpose. */
+    @Test
+    public void testDataLabelsOdMissingPurpose() throws Exception {
+        System.out.println("starting testDataLabelsOdMissingPurpose.");
+        odToHrExpectException(PERSONAL_MISSING_PURPOSE_FILE_NAME);
+    }
+
+    /** Test for data labels od empty purpose. */
+    @Test
+    public void testDataLabelsOdEmptyPurpose() throws Exception {
+        System.out.println("starting testDataLabelsOdEmptyPurpose.");
+        odToHrExpectException(PERSONAL_EMPTY_PURPOSE_FILE_NAME);
+    }
+
+    private void hrToOdExpectException(String fileName) {
+        TestUtils.hrToOdExpectException(new DataLabelsFactory(), DATA_LABELS_HR_PATH, fileName);
+    }
+
+    private void odToHrExpectException(String fileName) {
+        TestUtils.odToHrExpectException(new DataLabelsFactory(), DATA_LABELS_OD_PATH, fileName);
+    }
+
+    private void testHrToOdDataLabels(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new DataLabelsFactory(),
+                DATA_LABELS_HR_PATH,
+                DATA_LABELS_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrDataLabels(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new DataLabelsFactory(),
+                DATA_LABELS_OD_PATH,
+                DATA_LABELS_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DeveloperInfoTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DeveloperInfoTest.java
new file mode 100644
index 0000000..72e8d65
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DeveloperInfoTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import static org.junit.Assert.assertThrows;
+
+import com.android.asllib.testutils.TestUtils;
+import com.android.asllib.util.MalformedXmlException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.nio.file.Paths;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class DeveloperInfoTest {
+    private static final String DEVELOPER_INFO_HR_PATH = "com/android/asllib/developerinfo/hr";
+    private static final String DEVELOPER_INFO_OD_PATH = "com/android/asllib/developerinfo/od";
+    public static final List<String> REQUIRED_FIELD_NAMES =
+            List.of("address", "countryRegion", "email", "name", "relationship");
+    public static final List<String> REQUIRED_FIELD_NAMES_OD =
+            List.of("address", "country_region", "email", "name", "relationship");
+    public static final List<String> OPTIONAL_FIELD_NAMES = List.of("website", "registryId");
+    public static final List<String> OPTIONAL_FIELD_NAMES_OD =
+            List.of("website", "app_developer_registry_id");
+
+    private static final String ALL_FIELDS_VALID_FILE_NAME = "all-fields-valid.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for all fields valid. */
+    @Test
+    public void testAllFieldsValid() throws Exception {
+        System.out.println("starting testAllFieldsValid.");
+        testHrToOdDeveloperInfo(ALL_FIELDS_VALID_FILE_NAME);
+        testOdToHrDeveloperInfo(ALL_FIELDS_VALID_FILE_NAME);
+    }
+
+    /** Tests missing required fields fails. */
+    @Test
+    public void testMissingRequiredFields() throws Exception {
+        System.out.println("Starting testMissingRequiredFields");
+        for (String reqField : REQUIRED_FIELD_NAMES) {
+            System.out.println("testing missing required field: " + reqField);
+            var developerInfoEle =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(DEVELOPER_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            developerInfoEle.get(0).removeAttribute(reqField);
+
+            assertThrows(
+                    MalformedXmlException.class,
+                    () -> new DeveloperInfoFactory().createFromHrElements(developerInfoEle));
+        }
+
+        for (String reqField : REQUIRED_FIELD_NAMES_OD) {
+            System.out.println("testing missing required field od: " + reqField);
+            var developerInfoEle =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(DEVELOPER_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            TestUtils.removeOdChildEleWithName(developerInfoEle.get(0), reqField);
+
+            assertThrows(
+                    MalformedXmlException.class,
+                    () -> new DeveloperInfoFactory().createFromOdElements(developerInfoEle));
+        }
+    }
+
+    /** Tests missing optional fields passes. */
+    @Test
+    public void testMissingOptionalFields() throws Exception {
+        for (String optField : OPTIONAL_FIELD_NAMES) {
+            var developerInfoEle =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(DEVELOPER_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            developerInfoEle.get(0).removeAttribute(optField);
+            DeveloperInfo developerInfo =
+                    new DeveloperInfoFactory().createFromHrElements(developerInfoEle);
+            developerInfo.toOdDomElements(TestUtils.document());
+        }
+
+        for (String optField : OPTIONAL_FIELD_NAMES_OD) {
+            var developerInfoEle =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(DEVELOPER_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            TestUtils.removeOdChildEleWithName(developerInfoEle.get(0), optField);
+            DeveloperInfo developerInfo =
+                    new DeveloperInfoFactory().createFromOdElements(developerInfoEle);
+            developerInfo.toHrDomElements(TestUtils.document());
+        }
+    }
+
+    private void testHrToOdDeveloperInfo(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new DeveloperInfoFactory(),
+                DEVELOPER_INFO_HR_PATH,
+                DEVELOPER_INFO_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrDeveloperInfo(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new DeveloperInfoFactory(),
+                DEVELOPER_INFO_OD_PATH,
+                DEVELOPER_INFO_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java
new file mode 100644
index 0000000..bba6b54
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SafetyLabelsTest {
+    private static final String SAFETY_LABELS_HR_PATH = "com/android/asllib/safetylabels/hr";
+    private static final String SAFETY_LABELS_OD_PATH = "com/android/asllib/safetylabels/od";
+
+    private static final String MISSING_VERSION_FILE_NAME = "missing-version.xml";
+    private static final String VALID_EMPTY_FILE_NAME = "valid-empty.xml";
+    private static final String WITH_DATA_LABELS_FILE_NAME = "with-data-labels.xml";
+    private static final String WITH_SECURITY_LABELS_FILE_NAME = "with-security-labels.xml";
+    private static final String WITH_THIRD_PARTY_VERIFICATION_FILE_NAME =
+            "with-third-party-verification.xml";
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for safety labels missing version. */
+    @Test
+    public void testSafetyLabelsMissingVersion() throws Exception {
+        System.out.println("starting testSafetyLabelsMissingVersion.");
+        hrToOdExpectException(MISSING_VERSION_FILE_NAME);
+        odToHrExpectException(MISSING_VERSION_FILE_NAME);
+    }
+
+    /** Test for safety labels valid empty. */
+    @Test
+    public void testSafetyLabelsValidEmptyFile() throws Exception {
+        System.out.println("starting testSafetyLabelsValidEmptyFile.");
+        testHrToOdSafetyLabels(VALID_EMPTY_FILE_NAME);
+        testOdToHrSafetyLabels(VALID_EMPTY_FILE_NAME);
+    }
+
+    /** Test for safety labels with data labels. */
+    @Test
+    public void testSafetyLabelsWithDataLabels() throws Exception {
+        System.out.println("starting testSafetyLabelsWithDataLabels.");
+        testHrToOdSafetyLabels(WITH_DATA_LABELS_FILE_NAME);
+        testOdToHrSafetyLabels(WITH_DATA_LABELS_FILE_NAME);
+    }
+
+    /** Test for safety labels with security labels. */
+    @Test
+    public void testSafetyLabelsWithSecurityLabels() throws Exception {
+        System.out.println("starting testSafetyLabelsWithSecurityLabels.");
+        testHrToOdSafetyLabels(WITH_SECURITY_LABELS_FILE_NAME);
+        testOdToHrSafetyLabels(WITH_SECURITY_LABELS_FILE_NAME);
+    }
+
+    /** Test for safety labels with third party verification. */
+    @Test
+    public void testSafetyLabelsWithThirdPartyVerification() throws Exception {
+        System.out.println("starting testSafetyLabelsWithThirdPartyVerification.");
+        testHrToOdSafetyLabels(WITH_THIRD_PARTY_VERIFICATION_FILE_NAME);
+        testOdToHrSafetyLabels(WITH_THIRD_PARTY_VERIFICATION_FILE_NAME);
+    }
+
+    private void hrToOdExpectException(String fileName) {
+        TestUtils.hrToOdExpectException(new SafetyLabelsFactory(), SAFETY_LABELS_HR_PATH, fileName);
+    }
+
+    private void odToHrExpectException(String fileName) {
+        TestUtils.odToHrExpectException(new SafetyLabelsFactory(), SAFETY_LABELS_OD_PATH, fileName);
+    }
+
+    private void testHrToOdSafetyLabels(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new SafetyLabelsFactory(),
+                SAFETY_LABELS_HR_PATH,
+                SAFETY_LABELS_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrSafetyLabels(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new SafetyLabelsFactory(),
+                SAFETY_LABELS_OD_PATH,
+                SAFETY_LABELS_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SecurityLabelsTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SecurityLabelsTest.java
new file mode 100644
index 0000000..a940bc6
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SecurityLabelsTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.nio.file.Paths;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class SecurityLabelsTest {
+    private static final String SECURITY_LABELS_HR_PATH = "com/android/asllib/securitylabels/hr";
+    private static final String SECURITY_LABELS_OD_PATH = "com/android/asllib/securitylabels/od";
+
+    public static final List<String> OPTIONAL_FIELD_NAMES =
+            List.of("isDataDeletable", "isDataEncrypted");
+    public static final List<String> OPTIONAL_FIELD_NAMES_OD =
+            List.of("is_data_deletable", "is_data_encrypted");
+
+    private static final String ALL_FIELDS_VALID_FILE_NAME = "all-fields-valid.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for all fields valid. */
+    @Test
+    public void testAllFieldsValid() throws Exception {
+        System.out.println("starting testAllFieldsValid.");
+        testHrToOdSecurityLabels(ALL_FIELDS_VALID_FILE_NAME);
+        testOdToHrSecurityLabels(ALL_FIELDS_VALID_FILE_NAME);
+    }
+
+    /** Tests missing optional fields passes. */
+    @Test
+    public void testMissingOptionalFields() throws Exception {
+        for (String optField : OPTIONAL_FIELD_NAMES) {
+            var ele =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(SECURITY_LABELS_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            ele.get(0).removeAttribute(optField);
+            SecurityLabels securityLabels = new SecurityLabelsFactory().createFromHrElements(ele);
+            securityLabels.toOdDomElements(TestUtils.document());
+        }
+        for (String optField : OPTIONAL_FIELD_NAMES_OD) {
+            var ele =
+                    TestUtils.getElementsFromResource(
+                            Paths.get(SECURITY_LABELS_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
+            TestUtils.removeOdChildEleWithName(ele.get(0), optField);
+            SecurityLabels securityLabels = new SecurityLabelsFactory().createFromOdElements(ele);
+            securityLabels.toHrDomElements(TestUtils.document());
+        }
+    }
+
+    private void testHrToOdSecurityLabels(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new SecurityLabelsFactory(),
+                SECURITY_LABELS_HR_PATH,
+                SECURITY_LABELS_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrSecurityLabels(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new SecurityLabelsFactory(),
+                SECURITY_LABELS_OD_PATH,
+                SECURITY_LABELS_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SystemAppSafetyLabelTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SystemAppSafetyLabelTest.java
new file mode 100644
index 0000000..33c2764
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SystemAppSafetyLabelTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SystemAppSafetyLabelTest {
+    private static final String SYSTEM_APP_SAFETY_LABEL_HR_PATH =
+            "com/android/asllib/systemappsafetylabel/hr";
+    private static final String SYSTEM_APP_SAFETY_LABEL_OD_PATH =
+            "com/android/asllib/systemappsafetylabel/od";
+
+    private static final String VALID_FILE_NAME = "valid.xml";
+    private static final String MISSING_URL_FILE_NAME = "missing-url.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for valid. */
+    @Test
+    public void testValid() throws Exception {
+        System.out.println("starting testValid.");
+        testHrToOdSystemAppSafetyLabel(VALID_FILE_NAME);
+        testOdToHrSystemAppSafetyLabel(VALID_FILE_NAME);
+    }
+
+    /** Tests missing url. */
+    @Test
+    public void testMissingUrl() throws Exception {
+        System.out.println("starting testMissingUrl.");
+        hrToOdExpectException(MISSING_URL_FILE_NAME);
+        odToHrExpectException(MISSING_URL_FILE_NAME);
+    }
+
+    private void hrToOdExpectException(String fileName) {
+        TestUtils.hrToOdExpectException(
+                new SystemAppSafetyLabelFactory(), SYSTEM_APP_SAFETY_LABEL_HR_PATH, fileName);
+    }
+
+    private void odToHrExpectException(String fileName) {
+        TestUtils.odToHrExpectException(
+                new SystemAppSafetyLabelFactory(), SYSTEM_APP_SAFETY_LABEL_OD_PATH, fileName);
+    }
+
+    private void testHrToOdSystemAppSafetyLabel(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new SystemAppSafetyLabelFactory(),
+                SYSTEM_APP_SAFETY_LABEL_HR_PATH,
+                SYSTEM_APP_SAFETY_LABEL_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrSystemAppSafetyLabel(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new SystemAppSafetyLabelFactory(),
+                SYSTEM_APP_SAFETY_LABEL_OD_PATH,
+                SYSTEM_APP_SAFETY_LABEL_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/ThirdPartyVerificationTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/ThirdPartyVerificationTest.java
new file mode 100644
index 0000000..ec86d0f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/ThirdPartyVerificationTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ThirdPartyVerificationTest {
+    private static final String THIRD_PARTY_VERIFICATION_HR_PATH =
+            "com/android/asllib/thirdpartyverification/hr";
+    private static final String THIRD_PARTY_VERIFICATION_OD_PATH =
+            "com/android/asllib/thirdpartyverification/od";
+
+    private static final String VALID_FILE_NAME = "valid.xml";
+    private static final String MISSING_URL_FILE_NAME = "missing-url.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for valid. */
+    @Test
+    public void testValid() throws Exception {
+        System.out.println("starting testValid.");
+        testHrToOdThirdPartyVerification(VALID_FILE_NAME);
+        testOdToHrThirdPartyVerification(VALID_FILE_NAME);
+    }
+
+    /** Tests missing url. */
+    @Test
+    public void testMissingUrl() throws Exception {
+        System.out.println("starting testMissingUrl.");
+        hrToOdExpectException(MISSING_URL_FILE_NAME);
+        odToHrExpectException(MISSING_URL_FILE_NAME);
+    }
+
+    private void hrToOdExpectException(String fileName) {
+        TestUtils.hrToOdExpectException(
+                new ThirdPartyVerificationFactory(), THIRD_PARTY_VERIFICATION_HR_PATH, fileName);
+    }
+
+    private void odToHrExpectException(String fileName) {
+        TestUtils.odToHrExpectException(
+                new ThirdPartyVerificationFactory(), THIRD_PARTY_VERIFICATION_OD_PATH, fileName);
+    }
+
+    private void testHrToOdThirdPartyVerification(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new ThirdPartyVerificationFactory(),
+                THIRD_PARTY_VERIFICATION_HR_PATH,
+                THIRD_PARTY_VERIFICATION_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrThirdPartyVerification(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new ThirdPartyVerificationFactory(),
+                THIRD_PARTY_VERIFICATION_OD_PATH,
+                THIRD_PARTY_VERIFICATION_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java
new file mode 100644
index 0000000..f494240
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.marshallable;
+
+import com.android.asllib.testutils.TestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransparencyInfoTest {
+    private static final String TRANSPARENCY_INFO_HR_PATH =
+            "com/android/asllib/transparencyinfo/hr";
+    private static final String TRANSPARENCY_INFO_OD_PATH =
+            "com/android/asllib/transparencyinfo/od";
+
+    private static final String VALID_EMPTY_FILE_NAME = "valid-empty.xml";
+    private static final String WITH_DEVELOPER_INFO_FILE_NAME = "with-developer-info.xml";
+    private static final String WITH_APP_INFO_FILE_NAME = "with-app-info.xml";
+
+    @Before
+    public void setUp() throws Exception {
+        System.out.println("set up.");
+    }
+
+    /** Test for transparency info valid empty. */
+    @Test
+    public void testTransparencyInfoValidEmptyFile() throws Exception {
+        System.out.println("starting testTransparencyInfoValidEmptyFile.");
+        testHrToOdTransparencyInfo(VALID_EMPTY_FILE_NAME);
+        testOdToHrTransparencyInfo(VALID_EMPTY_FILE_NAME);
+    }
+
+    /** Test for transparency info with developer info. */
+    @Test
+    public void testTransparencyInfoWithDeveloperInfo() throws Exception {
+        System.out.println("starting testTransparencyInfoWithDeveloperInfo.");
+        testHrToOdTransparencyInfo(WITH_DEVELOPER_INFO_FILE_NAME);
+        testOdToHrTransparencyInfo(WITH_DEVELOPER_INFO_FILE_NAME);
+    }
+
+    /** Test for transparency info with app info. */
+    @Test
+    public void testTransparencyInfoWithAppInfo() throws Exception {
+        System.out.println("starting testTransparencyInfoWithAppInfo.");
+        testHrToOdTransparencyInfo(WITH_APP_INFO_FILE_NAME);
+        testOdToHrTransparencyInfo(WITH_APP_INFO_FILE_NAME);
+    }
+
+    private void testHrToOdTransparencyInfo(String fileName) throws Exception {
+        TestUtils.testHrToOd(
+                TestUtils.document(),
+                new TransparencyInfoFactory(),
+                TRANSPARENCY_INFO_HR_PATH,
+                TRANSPARENCY_INFO_OD_PATH,
+                fileName);
+    }
+
+    private void testOdToHrTransparencyInfo(String fileName) throws Exception {
+        TestUtils.testOdToHr(
+                TestUtils.document(),
+                new TransparencyInfoFactory(),
+                TRANSPARENCY_INFO_OD_PATH,
+                TRANSPARENCY_INFO_HR_PATH,
+                fileName);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/testutils/TestUtils.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/testutils/TestUtils.java
new file mode 100644
index 0000000..ea90993
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/testutils/TestUtils.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.asllib.testutils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import com.android.asllib.marshallable.AslMarshallable;
+import com.android.asllib.marshallable.AslMarshallableFactory;
+import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Optional;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+public class TestUtils {
+    public static final String HOLDER_TAG_NAME = "holder_of_flattened_for_testing";
+
+    /** Reads a Resource file into a String. */
+    public static String readStrFromResource(Path filePath) throws IOException {
+        InputStream hrStream =
+                TestUtils.class.getClassLoader().getResourceAsStream(filePath.toString());
+        return new String(hrStream.readAllBytes(), StandardCharsets.UTF_8);
+    }
+
+    /** Gets List of Element from a path to an existing Resource. */
+    public static List<Element> getElementsFromResource(Path filePath)
+            throws ParserConfigurationException, IOException, SAXException {
+        String str = readStrFromResource(filePath);
+        InputStream stream = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = factory.newDocumentBuilder().parse(stream);
+        Element root = document.getDocumentElement();
+        if (root.getTagName().equals(HOLDER_TAG_NAME)) {
+            String tagName =
+                    XmlUtils.asElementList(root.getChildNodes()).stream()
+                            .findFirst()
+                            .get()
+                            .getTagName();
+            return XmlUtils.getChildrenByTagName(root, tagName);
+        } else {
+            return List.of(root);
+        }
+    }
+
+    /** Reads a Document into a String. */
+    public static String docToStr(Document doc, boolean omitXmlDeclaration)
+            throws TransformerException {
+        TransformerFactory transformerFactory = TransformerFactory.newInstance();
+        Transformer transformer = transformerFactory.newTransformer();
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        transformer.setOutputProperty(
+                OutputKeys.OMIT_XML_DECLARATION, omitXmlDeclaration ? "yes" : "no");
+
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        StreamResult streamResult = new StreamResult(outStream); // out
+        DOMSource domSource = new DOMSource(doc);
+        transformer.transform(domSource, streamResult);
+
+        return outStream.toString(StandardCharsets.UTF_8);
+    }
+
+    /** Removes on-device style child with the corresponding name */
+    public static void removeOdChildEleWithName(Element ele, String childNameName) {
+        Optional<Element> childEle =
+                XmlUtils.asElementList(ele.getChildNodes()).stream()
+                        .filter(e -> e.getAttribute(XmlUtils.OD_ATTR_NAME).equals(childNameName))
+                        .findFirst();
+        if (childEle.isEmpty()) {
+            throw new IllegalStateException(
+                    String.format("%s was not found in %s", childNameName, ele.getTagName()));
+        }
+        ele.removeChild(childEle.get());
+    }
+
+    /**
+     * Gets formatted XML for slightly more robust comparison checking than naive string comparison.
+     */
+    public static String getFormattedXml(String xmlStr, boolean omitXmlDeclaration)
+            throws ParserConfigurationException, IOException, SAXException, TransformerException {
+        InputStream stream = new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8));
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = factory.newDocumentBuilder().parse(stream);
+        stripEmptyElements(document);
+        return docToStr(document, omitXmlDeclaration);
+    }
+
+    /** Helper for getting a new Document */
+    public static Document document() throws ParserConfigurationException {
+        return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+    }
+
+    /** Helper for testing human-readable to on-device conversion expecting exception */
+    public static <T extends AslMarshallable> void hrToOdExpectException(
+            AslMarshallableFactory<T> factory, String hrFolderPath, String fileName) {
+        assertThrows(
+                MalformedXmlException.class,
+                () -> {
+                    factory.createFromHrElements(
+                            TestUtils.getElementsFromResource(Paths.get(hrFolderPath, fileName)));
+                });
+    }
+
+    /** Helper for testing on-device to human-readable conversion expecting exception */
+    public static <T extends AslMarshallable> void odToHrExpectException(
+            AslMarshallableFactory<T> factory, String odFolderPath, String fileName) {
+        assertThrows(
+                MalformedXmlException.class,
+                () -> {
+                    factory.createFromOdElements(
+                            TestUtils.getElementsFromResource(Paths.get(odFolderPath, fileName)));
+                });
+    }
+
+    /** Helper for testing human-readable to on-device conversion */
+    public static <T extends AslMarshallable> void testHrToOd(
+            Document doc,
+            AslMarshallableFactory<T> factory,
+            String hrFolderPath,
+            String odFolderPath,
+            String fileName)
+            throws Exception {
+        testFormatToFormat(doc, factory, hrFolderPath, odFolderPath, fileName, true);
+    }
+
+    /** Helper for testing on-device to human-readable conversion */
+    public static <T extends AslMarshallable> void testOdToHr(
+            Document doc,
+            AslMarshallableFactory<T> factory,
+            String odFolderPath,
+            String hrFolderPath,
+            String fileName)
+            throws Exception {
+        testFormatToFormat(doc, factory, odFolderPath, hrFolderPath, fileName, false);
+    }
+
+    /** Helper for testing format to format conversion */
+    private static <T extends AslMarshallable> void testFormatToFormat(
+            Document doc,
+            AslMarshallableFactory<T> factory,
+            String inFolderPath,
+            String outFolderPath,
+            String fileName,
+            boolean hrToOd)
+            throws Exception {
+        AslMarshallable marshallable =
+                hrToOd
+                        ? factory.createFromHrElements(
+                                TestUtils.getElementsFromResource(
+                                        Paths.get(inFolderPath, fileName)))
+                        : factory.createFromOdElements(
+                                TestUtils.getElementsFromResource(
+                                        Paths.get(inFolderPath, fileName)));
+
+        List<Element> elements =
+                hrToOd ? marshallable.toOdDomElements(doc) : marshallable.toHrDomElements(doc);
+        if (elements.isEmpty()) {
+            throw new IllegalStateException("elements was empty.");
+        } else if (elements.size() == 1) {
+            doc.appendChild(elements.get(0));
+        } else {
+            Element root = doc.createElement(TestUtils.HOLDER_TAG_NAME);
+            for (var child : elements) {
+                root.appendChild(child);
+            }
+            doc.appendChild(root);
+        }
+        String converted = TestUtils.getFormattedXml(TestUtils.docToStr(doc, true), true);
+        System.out.println("Converted: " + converted);
+        String expectedOutContents =
+                TestUtils.getFormattedXml(
+                        TestUtils.readStrFromResource(Paths.get(outFolderPath, fileName)), true);
+        System.out.println("Expected: " + expectedOutContents);
+        assertEquals(expectedOutContents, converted);
+    }
+
+    private static void stripEmptyElements(Node node) {
+        NodeList children = node.getChildNodes();
+        for (int i = 0; i < children.getLength(); ++i) {
+            Node child = children.item(i);
+            if (child.getNodeType() == Node.TEXT_NODE) {
+                if (child.getTextContent().trim().length() == 0) {
+                    child.getParentNode().removeChild(child);
+                    i--;
+                }
+            }
+            stripEmptyElements(child);
+        }
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/missing-version.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/missing-version.xml
new file mode 100644
index 0000000..ec0cd70
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/missing-version.xml
@@ -0,0 +1,3 @@
+<app-metadata-bundles>
+
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/valid-empty.xml
new file mode 100644
index 0000000..19bfd82
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/valid-empty.xml
@@ -0,0 +1 @@
+<app-metadata-bundles version="123456"></app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml
new file mode 100644
index 0000000..53794a1
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml
@@ -0,0 +1,4 @@
+<app-metadata-bundles version="123456">
+    <safety-labels version="12345">
+    </safety-labels>
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-system-app-safety-label.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-system-app-safety-label.xml
new file mode 100644
index 0000000..7bcde45
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-system-app-safety-label.xml
@@ -0,0 +1,4 @@
+<app-metadata-bundles version="123456">
+<system-app-safety-label url="www.example.com">
+</system-app-safety-label>
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml
new file mode 100644
index 0000000..00bcfa8
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml
@@ -0,0 +1,4 @@
+<app-metadata-bundles version="123456">
+<transparency-info>
+</transparency-info>
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/missing-version.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/missing-version.xml
new file mode 100644
index 0000000..1aa3aa9
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/missing-version.xml
@@ -0,0 +1,2 @@
+<bundle>
+</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/valid-empty.xml
new file mode 100644
index 0000000..37bdfad
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/valid-empty.xml
@@ -0,0 +1,3 @@
+<bundle>
+    <long name="version" value="123456"/>
+</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml
new file mode 100644
index 0000000..74644ed
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml
@@ -0,0 +1,6 @@
+<bundle>
+    <long name="version" value="123456"/>
+    <pbundle_as_map name="safety_labels">
+        <long name="version" value="12345"/>
+    </pbundle_as_map>
+</bundle>
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-system-app-safety-label.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-system-app-safety-label.xml
new file mode 100644
index 0000000..ef0f549
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-system-app-safety-label.xml
@@ -0,0 +1,6 @@
+<bundle>
+    <long name="version" value="123456"/>
+    <pbundle_as_map name="system_app_safety_label">
+        <string name="url" value="www.example.com"/>
+    </pbundle_as_map>
+</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml
new file mode 100644
index 0000000..63c5094
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml
@@ -0,0 +1,4 @@
+<bundle>
+    <long name="version" value="123456"/>
+    <pbundle_as_map name="transparency_info"/>
+</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml
new file mode 100644
index 0000000..883170a2
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml
@@ -0,0 +1,14 @@
+<app-info
+    title="beervision"
+    description="a beer app"
+    containsAds="true"
+    obeyAps="false"
+    adsFingerprinting="false"
+    securityFingerprinting="false"
+    privacyPolicy="www.example.com"
+    securityEndpoints="url1|url2|url3"
+    firstPartyEndpoints="url1"
+    serviceProviderEndpoints="url55|url56"
+    category="Food and drink"
+    email="[email protected]"
+    website="www.example.com" />
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml
new file mode 100644
index 0000000..6e976a3
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml
@@ -0,0 +1,25 @@
+
+<pbundle_as_map name="app_info">
+    <string name="title" value="beervision"/>
+    <string name="description" value="a beer app"/>
+    <boolean name="contains_ads" value="true"/>
+    <boolean name="obey_aps" value="false"/>
+    <boolean name="ads_fingerprinting" value="false"/>
+    <boolean name="security_fingerprinting" value="false"/>
+    <string name="privacy_policy" value="www.example.com"/>
+    <string-array name="security_endpoint" num="3">
+        <item value="url1"/>
+        <item value="url2"/>
+        <item value="url3"/>
+    </string-array>
+    <string-array name="first_party_endpoint" num="1">
+        <item value="url1"/>
+    </string-array>
+    <string-array name="service_provider_endpoint" num="2">
+        <item value="url55"/>
+        <item value="url56"/>
+    </string-array>
+    <string name="category" value="Food and drink"/>
+    <string name="email" value="[email protected]"/>
+    <string name="website" value="www.example.com"/>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-actions-in-app.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-actions-in-app.xml
new file mode 100644
index 0000000..520e525
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-actions-in-app.xml
@@ -0,0 +1,17 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="actions_in_app"
+        dataType="user_interaction"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="in_app_search_history"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="installed_apps"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="user_generated_content"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="other"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-app-performance.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-app-performance.xml
new file mode 100644
index 0000000..0d08e5b
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-app-performance.xml
@@ -0,0 +1,11 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="app_performance"
+        dataType="crash_logs"
+        purposes="analytics" />
+    <data-shared dataCategory="app_performance"
+        dataType="performance_diagnostics"
+        purposes="analytics" />
+    <data-shared dataCategory="app_performance"
+        dataType="other"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-audio.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-audio.xml
new file mode 100644
index 0000000..b1cf3b4
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-audio.xml
@@ -0,0 +1,11 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="audio"
+        dataType="sound_recordings"
+        purposes="analytics" />
+    <data-shared dataCategory="audio"
+        dataType="music_files"
+        purposes="analytics" />
+    <data-shared dataCategory="audio"
+        dataType="other"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-calendar.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-calendar.xml
new file mode 100644
index 0000000..a723070
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-calendar.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="calendar"
+        dataType="calendar"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-contacts.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-contacts.xml
new file mode 100644
index 0000000..2fe28ff
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-contacts.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="contacts"
+        dataType="contacts"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-email-text-message.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-email-text-message.xml
new file mode 100644
index 0000000..49a326f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-email-text-message.xml
@@ -0,0 +1,11 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="email_text_message"
+        dataType="emails"
+        purposes="analytics" />
+    <data-shared dataCategory="email_text_message"
+        dataType="text_messages"
+        purposes="analytics" />
+    <data-shared dataCategory="email_text_message"
+        dataType="other"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-financial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-financial.xml
new file mode 100644
index 0000000..f5de370
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-financial.xml
@@ -0,0 +1,14 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="financial"
+        dataType="card_bank_account"
+        purposes="analytics" />
+    <data-shared dataCategory="financial"
+    dataType="purchase_history"
+    purposes="analytics" />
+    <data-shared dataCategory="financial"
+        dataType="credit_score"
+        purposes="analytics" />
+    <data-shared dataCategory="financial"
+        dataType="other"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-health-fitness.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-health-fitness.xml
new file mode 100644
index 0000000..9891f81
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-health-fitness.xml
@@ -0,0 +1,8 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="health_fitness"
+        dataType="health"
+        purposes="analytics" />
+    <data-shared dataCategory="health_fitness"
+        dataType="fitness"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-identifiers.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-identifiers.xml
new file mode 100644
index 0000000..3e74da1
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-identifiers.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="identifiers"
+        dataType="other"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-location.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-location.xml
new file mode 100644
index 0000000..4762f16
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-location.xml
@@ -0,0 +1,8 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="location"
+        dataType="approx_location"
+        purposes="analytics" />
+    <data-shared dataCategory="location"
+        dataType="precise_location"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-empty-purpose.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-empty-purpose.xml
new file mode 100644
index 0000000..964e178
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-empty-purpose.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="personal"
+    dataType="email_address"
+    purposes="" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-missing-purpose.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-missing-purpose.xml
new file mode 100644
index 0000000..3ce1288
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-missing-purpose.xml
@@ -0,0 +1,4 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="personal"
+    dataType="email_address" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-partial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-partial.xml
new file mode 100644
index 0000000..68baae3
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-partial.xml
@@ -0,0 +1,8 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="personal"
+        dataType="name"
+        purposes="analytics|developer_communications" />
+    <data-shared dataCategory="personal"
+    dataType="email_address"
+    purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-unrecognized-type.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-unrecognized-type.xml
new file mode 100644
index 0000000..921a90a
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal-unrecognized-type.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="personal"
+    dataType="unrecognized"
+    purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal.xml
new file mode 100644
index 0000000..4533773
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-personal.xml
@@ -0,0 +1,31 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="personal"
+        dataType="name"
+        ephemeral="true"
+        isCollectionOptional="true"
+        purposes="analytics|developer_communications" />
+    <data-shared dataCategory="personal"
+    dataType="email_address"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="physical_address"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="phone_number"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="race_ethnicity"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="political_or_religious_beliefs"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="sexual_orientation_or_gender_identity"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="personal_identifiers"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="other"
+    purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-photo-video.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-photo-video.xml
new file mode 100644
index 0000000..234fb26
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-photo-video.xml
@@ -0,0 +1,8 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="photo_video"
+        dataType="photos"
+        purposes="analytics" />
+    <data-shared dataCategory="photo_video"
+        dataType="videos"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-search-and-browsing.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-search-and-browsing.xml
new file mode 100644
index 0000000..db85163
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-search-and-browsing.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="search_and_browsing"
+        dataType="web_browsing_history"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-storage.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-storage.xml
new file mode 100644
index 0000000..9aad02d
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-storage.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="storage"
+        dataType="files_docs"
+        purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-unrecognized.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-unrecognized.xml
new file mode 100644
index 0000000..64b9ea7
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/hr/data-category-unrecognized.xml
@@ -0,0 +1,5 @@
+<holder_of_flattened_for_testing>
+    <data-shared dataCategory="unrecognized"
+    dataType="email_address"
+    purposes="analytics" />
+</holder_of_flattened_for_testing>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-actions-in-app.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-actions-in-app.xml
new file mode 100644
index 0000000..5b99900
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-actions-in-app.xml
@@ -0,0 +1,27 @@
+<pbundle_as_map name="actions_in_app">
+    <pbundle_as_map name="user_interaction">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="in_app_search_history">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="installed_apps">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="user_generated_content">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-app-performance.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-app-performance.xml
new file mode 100644
index 0000000..0fe1022
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-app-performance.xml
@@ -0,0 +1,17 @@
+<pbundle_as_map name="app_performance">
+    <pbundle_as_map name="crash_logs">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="performance_diagnostics">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-audio.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-audio.xml
new file mode 100644
index 0000000..51f1dfd
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-audio.xml
@@ -0,0 +1,17 @@
+<pbundle_as_map name="audio">
+    <pbundle_as_map name="sound_recordings">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="music_files">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-calendar.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-calendar.xml
new file mode 100644
index 0000000..326da47
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-calendar.xml
@@ -0,0 +1,7 @@
+<pbundle_as_map name="calendar">
+    <pbundle_as_map name="calendar">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-contacts.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-contacts.xml
new file mode 100644
index 0000000..5d4387d
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-contacts.xml
@@ -0,0 +1,7 @@
+<pbundle_as_map name="contacts">
+    <pbundle_as_map name="contacts">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-email-text-message.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-email-text-message.xml
new file mode 100644
index 0000000..5ac98f5
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-email-text-message.xml
@@ -0,0 +1,17 @@
+<pbundle_as_map name="email_text_message">
+    <pbundle_as_map name="emails">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="text_messages">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-financial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-financial.xml
new file mode 100644
index 0000000..a66f1a4
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-financial.xml
@@ -0,0 +1,22 @@
+<pbundle_as_map name="financial">
+    <pbundle_as_map name="card_bank_account">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="purchase_history">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="credit_score">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-health-fitness.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-health-fitness.xml
new file mode 100644
index 0000000..8e697b4
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-health-fitness.xml
@@ -0,0 +1,12 @@
+<pbundle_as_map name="health_fitness">
+    <pbundle_as_map name="health">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="fitness">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-identifiers.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-identifiers.xml
new file mode 100644
index 0000000..34b4016
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-identifiers.xml
@@ -0,0 +1,7 @@
+<pbundle_as_map name="identifiers">
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-location.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-location.xml
new file mode 100644
index 0000000..db2e696
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-location.xml
@@ -0,0 +1,12 @@
+<pbundle_as_map name="location">
+    <pbundle_as_map name="approx_location">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="precise_location">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-personal-partial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-personal-partial.xml
new file mode 100644
index 0000000..839922a
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-personal-partial.xml
@@ -0,0 +1,13 @@
+<pbundle_as_map name="personal">
+    <pbundle_as_map name="name">
+        <int-array name="purposes" num="2">
+            <item value="2" />
+            <item value="3" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="email_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-personal.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-personal.xml
new file mode 100644
index 0000000..43650b6
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-personal.xml
@@ -0,0 +1,50 @@
+<pbundle_as_map name="personal">
+    <pbundle_as_map name="name">
+        <int-array name="purposes" num="2">
+            <item value="2" />
+            <item value="3" />
+        </int-array>
+        <boolean name="is_collection_optional" value="true" />
+        <boolean name="ephemeral" value="true" />
+    </pbundle_as_map>
+    <pbundle_as_map name="email_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="physical_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="phone_number">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="race_ethnicity">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="political_or_religious_beliefs">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="sexual_orientation_or_gender_identity">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="personal_identifiers">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-photo-video.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-photo-video.xml
new file mode 100644
index 0000000..2a31780
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-photo-video.xml
@@ -0,0 +1,12 @@
+<pbundle_as_map name="photo_video">
+    <pbundle_as_map name="photos">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="videos">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-search-and-browsing.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-search-and-browsing.xml
new file mode 100644
index 0000000..9e654ef
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-search-and-browsing.xml
@@ -0,0 +1,7 @@
+<pbundle_as_map name="search_and_browsing">
+    <pbundle_as_map name="web_browsing_history">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-storage.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-storage.xml
new file mode 100644
index 0000000..9abc37f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datacategory/od/data-category-storage.xml
@@ -0,0 +1,7 @@
+<pbundle_as_map name="storage">
+    <pbundle_as_map name="files_docs">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-actions-in-app.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-actions-in-app.xml
new file mode 100644
index 0000000..68e191e
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-actions-in-app.xml
@@ -0,0 +1,17 @@
+<data-labels>
+    <data-shared dataCategory="actions_in_app"
+        dataType="user_interaction"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="in_app_search_history"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="installed_apps"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="user_generated_content"
+        purposes="analytics" />
+    <data-shared dataCategory="actions_in_app"
+        dataType="other"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-app-performance.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-app-performance.xml
new file mode 100644
index 0000000..a6bd17d
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-app-performance.xml
@@ -0,0 +1,11 @@
+<data-labels>
+    <data-shared dataCategory="app_performance"
+        dataType="crash_logs"
+        purposes="analytics" />
+    <data-shared dataCategory="app_performance"
+        dataType="performance_diagnostics"
+        purposes="analytics" />
+    <data-shared dataCategory="app_performance"
+        dataType="other"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-audio.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-audio.xml
new file mode 100644
index 0000000..6274604
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-audio.xml
@@ -0,0 +1,11 @@
+<data-labels>
+    <data-shared dataCategory="audio"
+        dataType="sound_recordings"
+        purposes="analytics" />
+    <data-shared dataCategory="audio"
+        dataType="music_files"
+        purposes="analytics" />
+    <data-shared dataCategory="audio"
+        dataType="other"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-calendar.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-calendar.xml
new file mode 100644
index 0000000..f7201f6
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-calendar.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="calendar"
+        dataType="calendar"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-contacts.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-contacts.xml
new file mode 100644
index 0000000..e8d40be
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-contacts.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="contacts"
+        dataType="contacts"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-email-text-message.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-email-text-message.xml
new file mode 100644
index 0000000..69e9b87
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-email-text-message.xml
@@ -0,0 +1,11 @@
+<data-labels>
+    <data-shared dataCategory="email_text_message"
+        dataType="emails"
+        purposes="analytics" />
+    <data-shared dataCategory="email_text_message"
+        dataType="text_messages"
+        purposes="analytics" />
+    <data-shared dataCategory="email_text_message"
+        dataType="other"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-financial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-financial.xml
new file mode 100644
index 0000000..fdd8456
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-financial.xml
@@ -0,0 +1,14 @@
+<data-labels>
+    <data-shared dataCategory="financial"
+        dataType="card_bank_account"
+        purposes="analytics" />
+    <data-shared dataCategory="financial"
+    dataType="purchase_history"
+    purposes="analytics" />
+    <data-shared dataCategory="financial"
+        dataType="credit_score"
+        purposes="analytics" />
+    <data-shared dataCategory="financial"
+        dataType="other"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-health-fitness.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-health-fitness.xml
new file mode 100644
index 0000000..bac58e6
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-health-fitness.xml
@@ -0,0 +1,8 @@
+<data-labels>
+    <data-shared dataCategory="health_fitness"
+        dataType="health"
+        purposes="analytics" />
+    <data-shared dataCategory="health_fitness"
+        dataType="fitness"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-identifiers.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-identifiers.xml
new file mode 100644
index 0000000..ee45f26
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-identifiers.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="identifiers"
+        dataType="other"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-location.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-location.xml
new file mode 100644
index 0000000..e8e5911
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-location.xml
@@ -0,0 +1,8 @@
+<data-labels>
+    <data-shared dataCategory="location"
+        dataType="approx_location"
+        purposes="analytics" />
+    <data-shared dataCategory="location"
+        dataType="precise_location"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-empty-purpose.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-empty-purpose.xml
new file mode 100644
index 0000000..0b220f4
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-empty-purpose.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="personal"
+    dataType="email_address"
+    purposes="" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-missing-purpose.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-missing-purpose.xml
new file mode 100644
index 0000000..ac221f2
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-missing-purpose.xml
@@ -0,0 +1,4 @@
+<data-labels>
+    <data-shared dataCategory="personal"
+    dataType="email_address" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-partial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-partial.xml
new file mode 100644
index 0000000..11b7368
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-partial.xml
@@ -0,0 +1,8 @@
+<data-labels>
+    <data-shared dataCategory="personal"
+        dataType="name"
+        purposes="analytics|developer_communications" />
+    <data-shared dataCategory="personal"
+    dataType="email_address"
+    purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-unrecognized-type.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-unrecognized-type.xml
new file mode 100644
index 0000000..f1fbd56
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal-unrecognized-type.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="personal"
+    dataType="unrecognized"
+    purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal.xml
new file mode 100644
index 0000000..5907462
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-personal.xml
@@ -0,0 +1,31 @@
+<data-labels>
+    <data-shared dataCategory="personal"
+        dataType="name"
+        ephemeral="true"
+        isSharingOptional="true"
+        purposes="analytics|developer_communications" />
+    <data-shared dataCategory="personal"
+    dataType="email_address"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="physical_address"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="phone_number"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="race_ethnicity"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="political_or_religious_beliefs"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="sexual_orientation_or_gender_identity"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="personal_identifiers"
+    purposes="analytics" />
+    <data-shared dataCategory="personal"
+    dataType="other"
+    purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-photo-video.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-photo-video.xml
new file mode 100644
index 0000000..05fe159
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-photo-video.xml
@@ -0,0 +1,8 @@
+<data-labels>
+    <data-shared dataCategory="photo_video"
+        dataType="photos"
+        purposes="analytics" />
+    <data-shared dataCategory="photo_video"
+        dataType="videos"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-search-and-browsing.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-search-and-browsing.xml
new file mode 100644
index 0000000..a5de7be
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-search-and-browsing.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="search_and_browsing"
+        dataType="web_browsing_history"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-storage.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-storage.xml
new file mode 100644
index 0000000..f01e2df
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-storage.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="storage"
+        dataType="files_docs"
+        purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-unrecognized-type.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-unrecognized-type.xml
new file mode 100644
index 0000000..f1fbd56
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-unrecognized-type.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="personal"
+    dataType="unrecognized"
+    purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-unrecognized.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-unrecognized.xml
new file mode 100644
index 0000000..c5be684
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-category-unrecognized.xml
@@ -0,0 +1,5 @@
+<data-labels>
+    <data-shared dataCategory="unrecognized"
+    dataType="email_address"
+    purposes="analytics" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-collected-shared.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-collected-shared.xml
new file mode 100644
index 0000000..161057a
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-collected-shared.xml
@@ -0,0 +1,11 @@
+<data-labels>
+    <data-accessed dataCategory="location"
+        dataType="approx_location"
+        purposes="app_functionality" />
+    <data-collected dataCategory="location"
+        dataType="precise_location"
+        purposes="app_functionality" />
+    <data-shared dataCategory="personal"
+        dataType="name"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-invalid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-invalid-bool.xml
new file mode 100644
index 0000000..bb45f42
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-invalid-bool.xml
@@ -0,0 +1,7 @@
+<data-labels>
+    <data-accessed dataCategory="location"
+        dataType="approx_location"
+        ephemeral="false"
+        isSharingOptional="false"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-valid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-valid-bool.xml
new file mode 100644
index 0000000..f927bba
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-accessed-valid-bool.xml
@@ -0,0 +1,6 @@
+<data-labels>
+    <data-accessed dataCategory="location"
+        dataType="approx_location"
+        ephemeral="false"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-collected-invalid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-collected-invalid-bool.xml
new file mode 100644
index 0000000..ba11afb
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-collected-invalid-bool.xml
@@ -0,0 +1,7 @@
+<data-labels>
+    <data-collected dataCategory="location"
+        dataType="approx_location"
+        ephemeral="false"
+        isSharingOptional="false"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-collected-valid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-collected-valid-bool.xml
new file mode 100644
index 0000000..4b6d3977
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-collected-valid-bool.xml
@@ -0,0 +1,7 @@
+<data-labels>
+    <data-collected dataCategory="location"
+        dataType="approx_location"
+        ephemeral="false"
+        isCollectionOptional="false"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-shared-invalid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-shared-invalid-bool.xml
new file mode 100644
index 0000000..7840b98
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-shared-invalid-bool.xml
@@ -0,0 +1,7 @@
+<data-labels>
+    <data-shared dataCategory="location"
+        dataType="approx_location"
+        ephemeral="false"
+        isCollectionOptional="false"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-shared-valid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-shared-valid-bool.xml
new file mode 100644
index 0000000..ccf77b0
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/hr/data-labels-shared-valid-bool.xml
@@ -0,0 +1,7 @@
+<data-labels>
+    <data-shared dataCategory="location"
+        dataType="approx_location"
+        ephemeral="false"
+        isSharingOptional="false"
+        purposes="app_functionality" />
+</data-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-actions-in-app.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-actions-in-app.xml
new file mode 100644
index 0000000..c5fef58
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-actions-in-app.xml
@@ -0,0 +1,31 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="actions_in_app">
+            <pbundle_as_map name="user_interaction">
+                <int-array name="purposes" num="1">
+                    <item value="2" />
+                </int-array>
+            </pbundle_as_map>
+            <pbundle_as_map name="in_app_search_history">
+                <int-array name="purposes" num="1">
+                    <item value="2" />
+                </int-array>
+            </pbundle_as_map>
+            <pbundle_as_map name="installed_apps">
+                <int-array name="purposes" num="1">
+                    <item value="2" />
+                </int-array>
+            </pbundle_as_map>
+            <pbundle_as_map name="user_generated_content">
+                <int-array name="purposes" num="1">
+                    <item value="2" />
+                </int-array>
+            </pbundle_as_map>
+            <pbundle_as_map name="other">
+                <int-array name="purposes" num="1">
+                    <item value="2" />
+                </int-array>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-app-performance.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-app-performance.xml
new file mode 100644
index 0000000..4570145
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-app-performance.xml
@@ -0,0 +1,21 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="app_performance">
+    <pbundle_as_map name="crash_logs">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="performance_diagnostics">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-audio.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-audio.xml
new file mode 100644
index 0000000..120f626
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-audio.xml
@@ -0,0 +1,21 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="audio">
+    <pbundle_as_map name="sound_recordings">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="music_files">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-calendar.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-calendar.xml
new file mode 100644
index 0000000..59eb938
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-calendar.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="calendar">
+    <pbundle_as_map name="calendar">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-contacts.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-contacts.xml
new file mode 100644
index 0000000..f952bfb
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-contacts.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="contacts">
+    <pbundle_as_map name="contacts">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-email-text-message.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-email-text-message.xml
new file mode 100644
index 0000000..bcaa716
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-email-text-message.xml
@@ -0,0 +1,21 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="email_text_message">
+    <pbundle_as_map name="emails">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="text_messages">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-financial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-financial.xml
new file mode 100644
index 0000000..a7bc82e
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-financial.xml
@@ -0,0 +1,26 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="financial">
+    <pbundle_as_map name="card_bank_account">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="purchase_history">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="credit_score">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-health-fitness.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-health-fitness.xml
new file mode 100644
index 0000000..f3ab2bd9
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-health-fitness.xml
@@ -0,0 +1,16 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="health_fitness">
+    <pbundle_as_map name="health">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="fitness">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-identifiers.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-identifiers.xml
new file mode 100644
index 0000000..05c07e5
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-identifiers.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="identifiers">
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-location.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-location.xml
new file mode 100644
index 0000000..931d1ad
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-location.xml
@@ -0,0 +1,16 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="location">
+    <pbundle_as_map name="approx_location">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="precise_location">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-empty-purpose.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-empty-purpose.xml
new file mode 100644
index 0000000..83f4a67
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-empty-purpose.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="personal">
+    <pbundle_as_map name="email_address">
+
+        <int-array name="purposes" num="2">
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-missing-purpose.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-missing-purpose.xml
new file mode 100644
index 0000000..532f5de
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-missing-purpose.xml
@@ -0,0 +1,8 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="personal">
+    <pbundle_as_map name="email_address">
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-partial.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-partial.xml
new file mode 100644
index 0000000..14f9ef2
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal-partial.xml
@@ -0,0 +1,17 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="personal">
+    <pbundle_as_map name="name">
+        <int-array name="purposes" num="2">
+            <item value="2" />
+            <item value="3" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="email_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal.xml
new file mode 100644
index 0000000..1c87de9
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-personal.xml
@@ -0,0 +1,54 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="personal">
+    <pbundle_as_map name="name">
+        <int-array name="purposes" num="2">
+            <item value="2" />
+            <item value="3" />
+        </int-array>
+        <boolean name="is_sharing_optional" value="true" />
+        <boolean name="ephemeral" value="true" />
+    </pbundle_as_map>
+    <pbundle_as_map name="email_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="physical_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="phone_number">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="race_ethnicity">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="political_or_religious_beliefs">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="sexual_orientation_or_gender_identity">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="personal_identifiers">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="other">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-photo-video.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-photo-video.xml
new file mode 100644
index 0000000..a752b51
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-photo-video.xml
@@ -0,0 +1,16 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="photo_video">
+    <pbundle_as_map name="photos">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+    <pbundle_as_map name="videos">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-search-and-browsing.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-search-and-browsing.xml
new file mode 100644
index 0000000..99bc188
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-search-and-browsing.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="search_and_browsing">
+    <pbundle_as_map name="web_browsing_history">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-storage.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-storage.xml
new file mode 100644
index 0000000..a4d2a62
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-storage.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="storage">
+    <pbundle_as_map name="files_docs">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-unrecognized-type.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-unrecognized-type.xml
new file mode 100644
index 0000000..16195df
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-unrecognized-type.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="personal">
+    <pbundle_as_map name="unrecognized">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-unrecognized.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-unrecognized.xml
new file mode 100644
index 0000000..511940e
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-category-unrecognized.xml
@@ -0,0 +1,11 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="unrecognized">
+    <pbundle_as_map name="email_address">
+        <int-array name="purposes" num="1">
+            <item value="2" />
+        </int-array>
+    </pbundle_as_map>
+</pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-accessed-collected-shared.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-accessed-collected-shared.xml
new file mode 100644
index 0000000..f86dbc1
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-accessed-collected-shared.xml
@@ -0,0 +1,29 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_accessed">
+        <pbundle_as_map name="location">
+            <pbundle_as_map name="approx_location">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+    <pbundle_as_map name="data_collected">
+        <pbundle_as_map name="location">
+            <pbundle_as_map name="precise_location">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+    <pbundle_as_map name="data_shared">
+        <pbundle_as_map name="personal">
+            <pbundle_as_map name="name">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-accessed-valid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-accessed-valid-bool.xml
new file mode 100644
index 0000000..ddefc18
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-accessed-valid-bool.xml
@@ -0,0 +1,12 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_accessed">
+        <pbundle_as_map name="location">
+            <pbundle_as_map name="approx_location">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+                <boolean name="ephemeral" value="false"/>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-collected-invalid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-collected-invalid-bool.xml
new file mode 100644
index 0000000..54cc8e7
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-collected-invalid-bool.xml
@@ -0,0 +1,13 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_collected">
+        <pbundle_as_map name="location">
+            <pbundle_as_map name="approx_location">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+                <boolean name="is_sharing_optional" value="false"/>
+                <boolean name="ephemeral" value="false"/>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-collected-valid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-collected-valid-bool.xml
new file mode 100644
index 0000000..252c728
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-collected-valid-bool.xml
@@ -0,0 +1,13 @@
+<pbundle_as_map name="data_labels">
+    <pbundle_as_map name="data_collected">
+        <pbundle_as_map name="location">
+            <pbundle_as_map name="approx_location">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+                <boolean name="is_collection_optional" value="false"/>
+                <boolean name="ephemeral" value="false"/>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-shared-valid-bool.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-shared-valid-bool.xml
new file mode 100644
index 0000000..3864f98
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/datalabels/od/data-labels-shared-valid-bool.xml
@@ -0,0 +1,13 @@
+<pbundle_as_map name="data_labels">
+<pbundle_as_map name="data_shared">
+        <pbundle_as_map name="location">
+            <pbundle_as_map name="approx_location">
+                <int-array name="purposes" num="1">
+                    <item value="1"/>
+                </int-array>
+                <boolean name="is_sharing_optional" value="false"/>
+                <boolean name="ephemeral" value="false"/>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/developerinfo/hr/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/developerinfo/hr/all-fields-valid.xml
new file mode 100644
index 0000000..908d8ea2
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/developerinfo/hr/all-fields-valid.xml
@@ -0,0 +1,8 @@
+<developer-info
+    name="max"
+    email="[email protected]"
+    address="111 blah lane"
+    countryRegion="US"
+    relationship="aosp"
+    website="example.com"
+    registryId="registry_id" />
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/developerinfo/od/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/developerinfo/od/all-fields-valid.xml
new file mode 100644
index 0000000..784ec61
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/developerinfo/od/all-fields-valid.xml
@@ -0,0 +1,9 @@
+<pbundle_as_map name="developer_info">
+    <string name="name" value="max"/>
+    <string name="email" value="[email protected]"/>
+    <string name="address" value="111 blah lane"/>
+    <string name="country_region" value="US"/>
+    <long name="relationship" value="5"/>
+    <string name="website" value="example.com"/>
+    <string name="app_developer_registry_id" value="registry_id"/>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/missing-version.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/missing-version.xml
new file mode 100644
index 0000000..762f3bd
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/missing-version.xml
@@ -0,0 +1,2 @@
+<safety-labels>
+</safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml
new file mode 100644
index 0000000..7decfd4
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml
@@ -0,0 +1 @@
+<safety-labels version="12345"></safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml
new file mode 100644
index 0000000..8997f4f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml
@@ -0,0 +1,9 @@
+<safety-labels version="12345">
+    <data-labels>
+        <data-shared dataCategory="location"
+            dataType="approx_location"
+            isSharingOptional="false"
+            ephemeral="false"
+            purposes="app_functionality" />
+    </data-labels>
+</safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml
new file mode 100644
index 0000000..940e48a
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml
@@ -0,0 +1,6 @@
+<safety-labels version="12345">
+    <security-labels
+        isDataDeletable="true"
+        isDataEncrypted="false"
+    />
+</safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml
new file mode 100644
index 0000000..bfbc5ae
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml
@@ -0,0 +1,4 @@
+<safety-labels version="12345">
+<third-party-verification url="www.example.com">
+    </third-party-verification>
+</safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/missing-version.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/missing-version.xml
new file mode 100644
index 0000000..3fbe359
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/missing-version.xml
@@ -0,0 +1,2 @@
+<pbundle_as_map name="safety_labels">
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml
new file mode 100644
index 0000000..4f03d88
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml
@@ -0,0 +1,3 @@
+<pbundle_as_map name="safety_labels">
+    <long name="version" value="12345"/>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml
new file mode 100644
index 0000000..a966fda
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml
@@ -0,0 +1,16 @@
+<pbundle_as_map name="safety_labels">
+    <long name="version" value="12345"/>
+    <pbundle_as_map name="data_labels">
+        <pbundle_as_map name="data_shared">
+            <pbundle_as_map name="location">
+                <pbundle_as_map name="approx_location">
+                    <int-array name="purposes" num="1">
+                        <item value="1"/>
+                    </int-array>
+                    <boolean name="is_sharing_optional" value="false"/>
+                    <boolean name="ephemeral" value="false"/>
+                </pbundle_as_map>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml
new file mode 100644
index 0000000..b39c562b
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml
@@ -0,0 +1,7 @@
+<pbundle_as_map name="safety_labels">
+    <long name="version" value="12345"/>
+    <pbundle_as_map name="security_labels">
+        <boolean name="is_data_deletable" value="true" />
+        <boolean name="is_data_encrypted" value="false" />
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml
new file mode 100644
index 0000000..10653ff
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml
@@ -0,0 +1,6 @@
+<pbundle_as_map name="safety_labels">
+    <long name="version" value="12345"/>
+    <pbundle_as_map name="third_party_verification">
+        <string name="url" value="www.example.com"/>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/securitylabels/hr/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/securitylabels/hr/all-fields-valid.xml
new file mode 100644
index 0000000..e2fb592
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/securitylabels/hr/all-fields-valid.xml
@@ -0,0 +1,4 @@
+<security-labels
+    isDataDeletable="true"
+    isDataEncrypted="false">
+</security-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/securitylabels/od/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/securitylabels/od/all-fields-valid.xml
new file mode 100644
index 0000000..7b2f656
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/securitylabels/od/all-fields-valid.xml
@@ -0,0 +1,4 @@
+<pbundle_as_map name="security_labels">
+    <boolean name="is_data_deletable" value="true" />
+    <boolean name="is_data_encrypted" value="false" />
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/hr/missing-url.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/hr/missing-url.xml
new file mode 100644
index 0000000..ff26c05
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/hr/missing-url.xml
@@ -0,0 +1 @@
+<system-app-safety-label></system-app-safety-label>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/hr/valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/hr/valid.xml
new file mode 100644
index 0000000..6fe86c3
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/hr/valid.xml
@@ -0,0 +1 @@
+<system-app-safety-label url="www.example.com"></system-app-safety-label>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/od/missing-url.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/od/missing-url.xml
new file mode 100644
index 0000000..33b7965
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/od/missing-url.xml
@@ -0,0 +1,2 @@
+<pbundle_as_map name="system_app_safety_label">
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/od/valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/od/valid.xml
new file mode 100644
index 0000000..f96535b
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/systemappsafetylabel/od/valid.xml
@@ -0,0 +1,3 @@
+<pbundle_as_map name="system_app_safety_label">
+    <string name="url" value="www.example.com"/>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/hr/missing-url.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/hr/missing-url.xml
new file mode 100644
index 0000000..6738ac2
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/hr/missing-url.xml
@@ -0,0 +1 @@
+<third-party-verification></third-party-verification>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/hr/valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/hr/valid.xml
new file mode 100644
index 0000000..2a664f2
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/hr/valid.xml
@@ -0,0 +1 @@
+<third-party-verification url="www.example.com"></third-party-verification>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/od/missing-url.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/od/missing-url.xml
new file mode 100644
index 0000000..0b5a46f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/od/missing-url.xml
@@ -0,0 +1,2 @@
+<pbundle_as_map name="third_party_verification">
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/od/valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/od/valid.xml
new file mode 100644
index 0000000..dbeb592
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/thirdpartyverification/od/valid.xml
@@ -0,0 +1,3 @@
+<pbundle_as_map name="third_party_verification">
+    <string name="url" value="www.example.com"/>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/valid-empty.xml
new file mode 100644
index 0000000..254a37f
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/valid-empty.xml
@@ -0,0 +1,4 @@
+
+<transparency-info>
+
+</transparency-info>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml
new file mode 100644
index 0000000..a7c48fc
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml
@@ -0,0 +1,4 @@
+
+<transparency-info>
+    <app-info title="beervision" description="a beer app" containsAds="true" obeyAps="false" adsFingerprinting="false" securityFingerprinting="false" privacyPolicy="www.example.com" securityEndpoints="url1|url2|url3" firstPartyEndpoints="url1" serviceProviderEndpoints="url55|url56" category="Food and drink" email="[email protected]" />
+</transparency-info>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-developer-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-developer-info.xml
new file mode 100644
index 0000000..d16caae
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-developer-info.xml
@@ -0,0 +1,11 @@
+
+<transparency-info>
+    <developer-info
+        name="max"
+        email="[email protected]"
+        address="111 blah lane"
+        countryRegion="US"
+        relationship="aosp"
+        website="example.com"
+        registryId="registry_id" />
+</transparency-info>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/valid-empty.xml
new file mode 100644
index 0000000..af574cf
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/valid-empty.xml
@@ -0,0 +1 @@
+<pbundle_as_map name="transparency_info"/>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml
new file mode 100644
index 0000000..b813641
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml
@@ -0,0 +1,26 @@
+
+<pbundle_as_map name="transparency_info">
+    <pbundle_as_map name="app_info">
+        <string name="title" value="beervision"/>
+        <string name="description" value="a beer app"/>
+        <boolean name="contains_ads" value="true"/>
+        <boolean name="obey_aps" value="false"/>
+        <boolean name="ads_fingerprinting" value="false"/>
+        <boolean name="security_fingerprinting" value="false"/>
+        <string name="privacy_policy" value="www.example.com"/>
+        <string-array name="security_endpoint" num="3">
+            <item value="url1"/>
+            <item value="url2"/>
+            <item value="url3"/>
+        </string-array>
+        <string-array name="first_party_endpoint" num="1">
+            <item value="url1"/>
+        </string-array>
+        <string-array name="service_provider_endpoint" num="2">
+            <item value="url55"/>
+            <item value="url56"/>
+        </string-array>
+        <string name="category" value="Food and drink"/>
+        <string name="email" value="[email protected]"/>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-developer-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-developer-info.xml
new file mode 100644
index 0000000..d7a4e1a
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-developer-info.xml
@@ -0,0 +1,12 @@
+
+<pbundle_as_map name="transparency_info">
+    <pbundle_as_map name="developer_info">
+        <string name="name" value="max"/>
+        <string name="email" value="[email protected]"/>
+        <string name="address" value="111 blah lane"/>
+        <string name="country_region" value="US"/>
+        <long name="relationship" value="5"/>
+        <string name="website" value="example.com"/>
+        <string name="app_developer_registry_id" value="registry_id"/>
+    </pbundle_as_map>
+</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/hr.xml
similarity index 100%
rename from tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/hr.xml
rename to tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/hr.xml
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/od.xml
similarity index 100%
rename from tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/od.xml
rename to tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/od.xml
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml
new file mode 100644
index 0000000..8f854ad
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml
@@ -0,0 +1,35 @@
+<app-metadata-bundles version="123">
+    <safety-labels version="12345">
+        <data-labels>
+            <data-shared dataCategory="location"
+                dataType="approx_location"
+                isSharingOptional="false"
+                ephemeral="false"
+                purposes="app_functionality" />
+            <data-shared dataCategory="location"
+                dataType="precise_location"
+                isSharingOptional="true"
+                ephemeral="true"
+                purposes="app_functionality|analytics" />
+        </data-labels>
+        <security-labels
+            isDataDeletable="true"
+            isDataEncrypted="false"
+        />
+        <third-party-verification url="www.example.com">
+        </third-party-verification>
+    </safety-labels>
+    <system-app-safety-label url="www.example.com">
+    </system-app-safety-label>
+    <transparency-info>
+        <developer-info
+            name="max"
+            email="[email protected]"
+            address="111 blah lane"
+            countryRegion="US"
+            relationship="aosp"
+            website="example.com"
+            registryId="registry_id" />
+        <app-info title="beervision" description="a beer app" containsAds="true" obeyAps="false" adsFingerprinting="false" securityFingerprinting="false" privacyPolicy="www.example.com" securityEndpoints="url1|url2|url3" firstPartyEndpoints="url1" serviceProviderEndpoints="url55|url56" category="Food and drink" email="[email protected]" />
+    </transparency-info>
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml
new file mode 100644
index 0000000..8f1dc64
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml
@@ -0,0 +1,71 @@
+<bundle>
+    <long name="version" value="123"/>
+    <pbundle_as_map name="safety_labels">
+        <long name="version" value="12345"/>
+        <pbundle_as_map name="data_labels">
+            <pbundle_as_map name="data_shared">
+                <pbundle_as_map name="location">
+                    <pbundle_as_map name="approx_location">
+                        <int-array name="purposes" num="1">
+                            <item value="1"/>
+                        </int-array>
+                        <boolean name="is_sharing_optional" value="false"/>
+                        <boolean name="ephemeral" value="false"/>
+                    </pbundle_as_map>
+                    <pbundle_as_map name="precise_location">
+                        <int-array name="purposes" num="2">
+                            <item value="1"/>
+                            <item value="2"/>
+                        </int-array>
+                        <boolean name="is_sharing_optional" value="true"/>
+                        <boolean name="ephemeral" value="true"/>
+                    </pbundle_as_map>
+                </pbundle_as_map>
+            </pbundle_as_map>
+        </pbundle_as_map>
+        <pbundle_as_map name="security_labels">
+            <boolean name="is_data_deletable" value="true"/>
+            <boolean name="is_data_encrypted" value="false"/>
+        </pbundle_as_map>
+        <pbundle_as_map name="third_party_verification">
+            <string name="url" value="www.example.com"/>
+        </pbundle_as_map>
+    </pbundle_as_map>
+    <pbundle_as_map name="system_app_safety_label">
+        <string name="url" value="www.example.com"/>
+    </pbundle_as_map>
+    <pbundle_as_map name="transparency_info">
+        <pbundle_as_map name="developer_info">
+            <string name="name" value="max"/>
+            <string name="email" value="[email protected]"/>
+            <string name="address" value="111 blah lane"/>
+            <string name="country_region" value="US"/>
+            <long name="relationship" value="5"/>
+            <string name="website" value="example.com"/>
+            <string name="app_developer_registry_id" value="registry_id"/>
+        </pbundle_as_map>
+        <pbundle_as_map name="app_info">
+            <string name="title" value="beervision"/>
+            <string name="description" value="a beer app"/>
+            <boolean name="contains_ads" value="true"/>
+            <boolean name="obey_aps" value="false"/>
+            <boolean name="ads_fingerprinting" value="false"/>
+            <boolean name="security_fingerprinting" value="false"/>
+            <string name="privacy_policy" value="www.example.com"/>
+            <string-array name="security_endpoint" num="3">
+                <item value="url1"/>
+                <item value="url2"/>
+                <item value="url3"/>
+            </string-array>
+            <string-array name="first_party_endpoint" num="1">
+                <item value="url1"/>
+            </string-array>
+            <string-array name="service_provider_endpoint" num="2">
+                <item value="url55"/>
+                <item value="url56"/>
+            </string-array>
+            <string name="category" value="Food and drink"/>
+            <string name="email" value="[email protected]"/>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/hr.xml
similarity index 100%
rename from tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/hr.xml
rename to tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/hr.xml
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/od.xml
similarity index 100%
rename from tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/od.xml
rename to tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/od.xml
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
index 30333da..682adbc 100644
--- a/tools/hoststubgen/hoststubgen/Android.bp
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -82,13 +82,30 @@
     jarjar_rules: "jarjar-rules.txt",
 }
 
-// Host-side stub generator tool.
-java_binary_host {
-    name: "hoststubgen",
-    main_class: "com.android.hoststubgen.Main",
+// For sharing the code with other tools
+java_library_host {
+    name: "hoststubgen-lib",
+    defaults: ["ravenwood-internal-only-visibility-java"],
     srcs: ["src/**/*.kt"],
     static_libs: [
         "hoststubgen-helper-runtime",
+    ],
+    libs: [
+        "junit",
+        "ow2-asm",
+        "ow2-asm-analysis",
+        "ow2-asm-commons",
+        "ow2-asm-tree",
+        "ow2-asm-util",
+    ],
+}
+
+// Host-side stub generator tool.
+java_binary_host {
+    name: "hoststubgen",
+    main_class: "com.android.hoststubgen.HostStubGenMain",
+    static_libs: [
+        "hoststubgen-lib",
         "junit",
         "ow2-asm",
         "ow2-asm-analysis",
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 1089f82..803dc28 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -32,7 +32,6 @@
 import org.objectweb.asm.ClassReader
 import org.objectweb.asm.ClassVisitor
 import org.objectweb.asm.ClassWriter
-import org.objectweb.asm.tree.ClassNode
 import org.objectweb.asm.util.CheckClassAdapter
 import java.io.BufferedInputStream
 import java.io.FileOutputStream
@@ -52,7 +51,7 @@
         val stats = HostStubGenStats()
 
         // Load all classes.
-        val allClasses = loadClassStructures(options.inJar.get)
+        val allClasses = ClassNodes.loadClassStructures(options.inJar.get)
 
         // Dump the classes, if specified.
         options.inputJarDumpFile.ifSet {
@@ -92,55 +91,6 @@
     }
 
     /**
-     * Load all the classes, without code.
-     */
-    private fun loadClassStructures(inJar: String): ClassNodes {
-        log.i("Reading class structure from $inJar ...")
-        val start = System.currentTimeMillis()
-
-        val allClasses = ClassNodes()
-
-        log.withIndent {
-            ZipFile(inJar).use { inZip ->
-                val inEntries = inZip.entries()
-
-                while (inEntries.hasMoreElements()) {
-                    val entry = inEntries.nextElement()
-
-                    BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
-                        if (entry.name.endsWith(".class")) {
-                            val cr = ClassReader(bis)
-                            val cn = ClassNode()
-                            cr.accept(cn, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG
-                                    or ClassReader.SKIP_FRAMES)
-                            if (!allClasses.addClass(cn)) {
-                                log.w("Duplicate class found: ${cn.name}")
-                            }
-                        } else if (entry.name.endsWith(".dex")) {
-                            // Seems like it's an ART jar file. We can't process it.
-                            // It's a fatal error.
-                            throw InvalidJarFileException(
-                                    "$inJar is not a desktop jar file. It contains a *.dex file.")
-                        } else {
-                            // Unknown file type. Skip.
-                            while (bis.available() > 0) {
-                                bis.skip((1024 * 1024).toLong())
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        if (allClasses.size == 0) {
-            log.w("$inJar contains no *.class files.")
-        }
-
-        val end = System.currentTimeMillis()
-        log.i("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
-        return allClasses
-    }
-
-    /**
      * Build the filter, which decides what classes/methods/fields should be put in stub or impl
      * jars, and "how". (e.g. with substitution?)
      */
@@ -229,7 +179,7 @@
         val intersectingJars = mutableMapOf<String, ClassNodes>()
 
         filenames.forEach { filename ->
-            intersectingJars[filename] = loadClassStructures(filename)
+            intersectingJars[filename] = ClassNodes.loadClassStructures(filename)
         }
         return intersectingJars
     }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
new file mode 100644
index 0000000..45e7e30
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:JvmName("HostStubGenMain")
+
+package com.android.hoststubgen
+
+import java.io.PrintWriter
+
+/**
+ * Entry point.
+ */
+fun main(args: Array<String>) {
+    executableName = "HostStubGen"
+
+    var success = false
+    var clanupOnError = false
+
+    try {
+        // Parse the command line arguments.
+        val options = HostStubGenOptions.parseArgs(args)
+        clanupOnError = options.cleanUpOnError.get
+
+        log.v("$executableName started")
+        log.v("Options: $options")
+
+        // Run.
+        HostStubGen(options).run()
+
+        success = true
+    } catch (e: Throwable) {
+        log.e("$executableName: Error: ${e.message}")
+        if (e !is UserErrorException) {
+            e.printStackTrace(PrintWriter(log.getWriter(LogLevel.Error)))
+        }
+        if (clanupOnError) {
+            TODO("Remove output jars here")
+        }
+    } finally {
+        log.i("$executableName finished")
+        log.flush()
+    }
+
+    System.exit(if (success) 0 else 1 )
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 9f5d524..9ff798a 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -268,7 +268,7 @@
             }
             if (!ret.outStubJar.isSet && !ret.outImplJar.isSet) {
                 log.w("Neither --out-stub-jar nor --out-impl-jar is set." +
-                        " $COMMAND_NAME will not generate jar files.")
+                        " $executableName will not generate jar files.")
             }
 
             if (ret.enableNonStubMethodCallDetection.get) {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
deleted file mode 100644
index 4882c00..0000000
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-@file:JvmName("Main")
-
-package com.android.hoststubgen
-
-import java.io.PrintWriter
-
-const val COMMAND_NAME = "HostStubGen"
-
-/**
- * Entry point.
- */
-fun main(args: Array<String>) {
-    var success = false
-    var clanupOnError = false
-
-    try {
-        // Parse the command line arguments.
-        val options = HostStubGenOptions.parseArgs(args)
-        clanupOnError = options.cleanUpOnError.get
-
-        log.v("HostStubGen started")
-        log.v("Options: $options")
-
-        // Run.
-        HostStubGen(options).run()
-
-        success = true
-    } catch (e: Throwable) {
-        log.e("$COMMAND_NAME: Error: ${e.message}")
-        if (e !is UserErrorException) {
-            e.printStackTrace(PrintWriter(log.getWriter(LogLevel.Error)))
-        }
-        if (clanupOnError) {
-            TODO("Remove output jars here")
-        }
-    } finally {
-        log.i("$COMMAND_NAME finished")
-        log.flush()
-    }
-
-    System.exit(if (success) 0 else 1 )
-}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
index 937e56c..aa63d8d9 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
@@ -16,6 +16,11 @@
 package com.android.hoststubgen
 
 /**
+ * Name of this executable. Set it in the main method.
+ */
+var executableName = "[command name not set]"
+
+/**
  * A regex that maches whitespate.
  */
 val whitespaceRegex = """\s+""".toRegex()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 0579c2b..83e122f 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -34,6 +34,9 @@
 /** Descriptor of the class initializer method. */
 val CLASS_INITIALIZER_DESC = "()V"
 
+/** Name of constructors. */
+val CTOR_NAME = "<init>"
+
 /**
  * Find any of [anyAnnotations] from the list of visible / invisible annotations.
  */
@@ -135,10 +138,10 @@
         // Note, long and double will consume two local variable spaces, so the extra `i++`.
         when (type) {
             Type.VOID_TYPE -> throw HostStubGenInternalException("VOID_TYPE not expected")
-            Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+            Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.BYTE_TYPE, Type.SHORT_TYPE, Type.INT_TYPE
                 -> writer.visitVarInsn(Opcodes.ILOAD, i)
-            Type.LONG_TYPE -> writer.visitVarInsn(Opcodes.LLOAD, i++)
             Type.FLOAT_TYPE -> writer.visitVarInsn(Opcodes.FLOAD, i)
+            Type.LONG_TYPE -> writer.visitVarInsn(Opcodes.LLOAD, i++)
             Type.DOUBLE_TYPE -> writer.visitVarInsn(Opcodes.DLOAD, i++)
             else -> writer.visitVarInsn(Opcodes.ALOAD, i)
         }
@@ -154,10 +157,10 @@
         // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
         when (type) {
             Type.VOID_TYPE -> writer.visitInsn(Opcodes.RETURN)
-            Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+            Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.BYTE_TYPE, Type.SHORT_TYPE, Type.INT_TYPE
                 -> writer.visitInsn(Opcodes.IRETURN)
-            Type.LONG_TYPE -> writer.visitInsn(Opcodes.LRETURN)
             Type.FLOAT_TYPE -> writer.visitInsn(Opcodes.FRETURN)
+            Type.LONG_TYPE -> writer.visitInsn(Opcodes.LRETURN)
             Type.DOUBLE_TYPE -> writer.visitInsn(Opcodes.DRETURN)
             else -> writer.visitInsn(Opcodes.ARETURN)
         }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
index bc34ef0..92906a7 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
@@ -16,13 +16,18 @@
 package com.android.hoststubgen.asm
 
 import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.InvalidJarFileException
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassReader
 import org.objectweb.asm.tree.AnnotationNode
 import org.objectweb.asm.tree.ClassNode
 import org.objectweb.asm.tree.FieldNode
 import org.objectweb.asm.tree.MethodNode
 import org.objectweb.asm.tree.TypeAnnotationNode
+import java.io.BufferedInputStream
 import java.io.PrintWriter
 import java.util.Arrays
+import java.util.zip.ZipFile
 
 /**
  * Stores all classes loaded from a jar file, in a form of [ClassNode]
@@ -62,8 +67,8 @@
 
     /** Find a field, which may not exist. */
     fun findField(
-            className: String,
-            fieldName: String,
+        className: String,
+        fieldName: String,
     ): FieldNode? {
         return findClass(className)?.fields?.firstOrNull { it.name == fieldName }?.let { fn ->
             return fn
@@ -72,14 +77,14 @@
 
     /** Find a method, which may not exist. */
     fun findMethod(
-            className: String,
-            methodName: String,
-            descriptor: String,
+        className: String,
+        methodName: String,
+        descriptor: String,
     ): MethodNode? {
         return findClass(className)?.methods
-                ?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
-            return mn
-        }
+            ?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+                return mn
+            }
     }
 
     /** @return true if a class has a class initializer. */
@@ -106,26 +111,33 @@
 
     private fun dumpClass(pw: PrintWriter, cn: ClassNode) {
         pw.printf("Class: %s [access: %x]\n", cn.name, cn.access)
-        dumpAnnotations(pw, "  ",
-                cn.visibleTypeAnnotations, cn.invisibleTypeAnnotations,
-                cn.visibleAnnotations, cn.invisibleAnnotations,
-                )
+        dumpAnnotations(
+            pw, "  ",
+            cn.visibleTypeAnnotations, cn.invisibleTypeAnnotations,
+            cn.visibleAnnotations, cn.invisibleAnnotations,
+        )
 
         for (f in cn.fields ?: emptyList()) {
-            pw.printf("  Field: %s [sig: %s] [desc: %s] [access: %x]\n",
-                    f.name, f.signature, f.desc, f.access)
-            dumpAnnotations(pw, "    ",
-                    f.visibleTypeAnnotations, f.invisibleTypeAnnotations,
-                    f.visibleAnnotations, f.invisibleAnnotations,
-                    )
+            pw.printf(
+                "  Field: %s [sig: %s] [desc: %s] [access: %x]\n",
+                f.name, f.signature, f.desc, f.access
+            )
+            dumpAnnotations(
+                pw, "    ",
+                f.visibleTypeAnnotations, f.invisibleTypeAnnotations,
+                f.visibleAnnotations, f.invisibleAnnotations,
+            )
         }
         for (m in cn.methods ?: emptyList()) {
-            pw.printf("  Method: %s [sig: %s] [desc: %s] [access: %x]\n",
-                    m.name, m.signature, m.desc, m.access)
-            dumpAnnotations(pw, "    ",
-                    m.visibleTypeAnnotations, m.invisibleTypeAnnotations,
-                    m.visibleAnnotations, m.invisibleAnnotations,
-                    )
+            pw.printf(
+                "  Method: %s [sig: %s] [desc: %s] [access: %x]\n",
+                m.name, m.signature, m.desc, m.access
+            )
+            dumpAnnotations(
+                pw, "    ",
+                m.visibleTypeAnnotations, m.invisibleTypeAnnotations,
+                m.visibleAnnotations, m.invisibleAnnotations,
+            )
         }
     }
 
@@ -136,7 +148,7 @@
         invisibleTypeAnnotations: List<TypeAnnotationNode>?,
         visibleAnnotations: List<AnnotationNode>?,
         invisibleAnnotations: List<AnnotationNode>?,
-        ) {
+    ) {
         for (an in visibleTypeAnnotations ?: emptyList()) {
             pw.printf("%sTypeAnnotation(vis): %s\n", prefix, an.desc)
         }
@@ -166,4 +178,55 @@
             }
         }
     }
+
+    companion object {
+        /**
+         * Load all the classes, without code.
+         */
+        fun loadClassStructures(inJar: String): ClassNodes {
+            log.i("Reading class structure from $inJar ...")
+            val start = System.currentTimeMillis()
+
+            val allClasses = ClassNodes()
+
+            log.withIndent {
+                ZipFile(inJar).use { inZip ->
+                    val inEntries = inZip.entries()
+
+                    while (inEntries.hasMoreElements()) {
+                        val entry = inEntries.nextElement()
+
+                        BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+                            if (entry.name.endsWith(".class")) {
+                                val cr = ClassReader(bis)
+                                val cn = ClassNode()
+                                cr.accept(cn, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG
+                                        or ClassReader.SKIP_FRAMES)
+                                if (!allClasses.addClass(cn)) {
+                                    log.w("Duplicate class found: ${cn.name}")
+                                }
+                            } else if (entry.name.endsWith(".dex")) {
+                                // Seems like it's an ART jar file. We can't process it.
+                                // It's a fatal error.
+                                throw InvalidJarFileException(
+                                    "$inJar is not a desktop jar file. It contains a *.dex file.")
+                            } else {
+                                // Unknown file type. Skip.
+                                while (bis.available() > 0) {
+                                    bis.skip((1024 * 1024).toLong())
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (allClasses.size == 0) {
+                log.w("$inJar contains no *.class files.")
+            }
+
+            val end = System.currentTimeMillis()
+            log.i("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
+            return allClasses
+        }
+    }
 }
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
index 78b13fd..5a26fc6 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
@@ -19,14 +19,14 @@
 import com.android.hoststubgen.HostStubGenInternalException
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
-import com.android.hoststubgen.asm.isAnonymousInnerClass
-import com.android.hoststubgen.log
 import com.android.hoststubgen.asm.ClassNodes
 import com.android.hoststubgen.asm.isAnnotation
+import com.android.hoststubgen.asm.isAnonymousInnerClass
 import com.android.hoststubgen.asm.isAutoGeneratedEnumMember
 import com.android.hoststubgen.asm.isEnum
 import com.android.hoststubgen.asm.isSynthetic
 import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+import com.android.hoststubgen.log
 import org.objectweb.asm.tree.ClassNode
 
 /**
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index f70a17d..fa8fe6c 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -1833,7 +1833,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 10, attributes: 2
+  interfaces: 0, fields: 1, methods: 11, attributes: 2
   int value;
     descriptor: I
     flags: (0x0000)
@@ -1938,6 +1938,10 @@
          x: invokespecial #x                 // Method java/lang/RuntimeException."<init>":()V
          x: athrow
       LineNumberTable:
+
+  public static native byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeInvisibleAnnotations:
@@ -1955,7 +1959,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 2
+  interfaces: 0, fields: 0, methods: 5, attributes: 2
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
     descriptor: ()V
     flags: (0x0001) ACC_PUBLIC
@@ -2013,6 +2017,22 @@
         Start  Length  Slot  Name   Signature
             0       7     0 source   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
             0       7     1   arg   I
+
+  public static byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: iload_0
+         x: iload_1
+         x: iadd
+         x: i2b
+         x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       5     0  arg1   B
+            0       5     1  arg2   B
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeInvisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
index 37de857..c605f76 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
@@ -1554,7 +1554,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 9, attributes: 3
+  interfaces: 0, fields: 1, methods: 10, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
@@ -1686,6 +1686,15 @@
         com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+  public static native byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
index c9c607c..11d5939 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
@@ -2236,7 +2236,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 10, attributes: 3
+  interfaces: 0, fields: 1, methods: 11, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
@@ -2435,6 +2435,23 @@
         com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+  public static byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: iload_0
+         x: iload_1
+         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B
+         x: ireturn
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
@@ -2457,7 +2474,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 3
+  interfaces: 0, fields: 0, methods: 5, attributes: 3
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
     descriptor: ()V
     flags: (0x0001) ACC_PUBLIC
@@ -2551,6 +2568,31 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+  public static byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+         x: ldc           #x                 // String nativeBytePlus
+         x: ldc           #x                 // String (BB)B
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+         x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+        x: iload_0
+        x: iload_1
+        x: iadd
+        x: i2b
+        x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           15       5     0  arg1   B
+           15       5     1  arg2   B
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeVisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
index 37de857..c605f76 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
@@ -1554,7 +1554,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 9, attributes: 3
+  interfaces: 0, fields: 1, methods: 10, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
@@ -1686,6 +1686,15 @@
         com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+  public static native byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
index a57907d..088bc80 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
@@ -2743,7 +2743,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 1, methods: 11, attributes: 3
+  interfaces: 0, fields: 1, methods: 12, attributes: 3
   int value;
     descriptor: I
     flags: (0x0000)
@@ -3002,6 +3002,28 @@
         com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+  public static byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+         x: ldc           #x                // String nativeBytePlus
+         x: ldc           #x                // String (BB)B
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: iload_0
+        x: iload_1
+        x: invokestatic  #x                // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B
+        x: ireturn
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkNative.java"
 RuntimeVisibleAnnotations:
@@ -3024,7 +3046,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 3
+  interfaces: 0, fields: 0, methods: 6, attributes: 3
   private static {};
     descriptor: ()V
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -3148,6 +3170,36 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+
+  public static byte nativeBytePlus(byte, byte);
+    descriptor: (BB)B
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+         x: ldc           #x                 // String nativeBytePlus
+         x: ldc           #x                 // String (BB)B
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: ldc           #x                 // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+        x: ldc           #x                 // String nativeBytePlus
+        x: ldc           #x                 // String (BB)B
+        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+        x: invokevirtual #x                 // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+        x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+        x: iload_0
+        x: iload_1
+        x: iadd
+        x: i2b
+        x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           26       5     0  arg1   B
+           26       5     1  arg2   B
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
 }
 SourceFile: "TinyFrameworkNative_host.java"
 RuntimeVisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
index 5a5e22d..09ee183 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -52,4 +52,6 @@
     public static void nativeStillNotSupported_should_be_like_this() {
         throw new RuntimeException();
     }
+
+    public static native byte nativeBytePlus(byte arg1, byte arg2);
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
index 749ebaa..b23c216 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
@@ -34,4 +34,8 @@
     public static int nativeNonStaticAddToValue(TinyFrameworkNative source, int arg) {
         return source.value + arg;
     }
+
+    public static byte nativeBytePlus(byte arg1, byte arg2) {
+        return (byte) (arg1 + arg2);
+    }
 }
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
index ba17c75..762180d 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -154,13 +154,22 @@
     }
 
     @Test
+    public void testNativeSubstitutionLong() {
+        assertThat(TinyFrameworkNative.nativeLongPlus(1L, 2L)).isEqualTo(3L);
+    }
+
+    @Test
+    public void testNativeSubstitutionByte() {
+        assertThat(TinyFrameworkNative.nativeBytePlus((byte) 3, (byte) 4)).isEqualTo(7);
+    }
+
+    @Test
     public void testNativeSubstitutionClass_nonStatic() {
         TinyFrameworkNative instance = new TinyFrameworkNative();
         instance.setValue(5);
         assertThat(instance.nativeNonStaticAddToValue(3)).isEqualTo(8);
     }
 
-
     @Test
     public void testSubstituteNativeWithThrow() throws Exception {
         // We can't use TinyFrameworkNative.nativeStillNotSupported() directly in this class,
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 837dae9..0f1373c 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -24,11 +24,20 @@
 import com.github.javaparser.ParserConfiguration
 import com.github.javaparser.StaticJavaParser
 import com.github.javaparser.ast.CompilationUnit
+import com.github.javaparser.ast.Modifier
 import com.github.javaparser.ast.NodeList
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
 import com.github.javaparser.ast.body.InitializerDeclaration
+import com.github.javaparser.ast.expr.ArrayAccessExpr
+import com.github.javaparser.ast.expr.ArrayCreationExpr
+import com.github.javaparser.ast.expr.ArrayInitializerExpr
+import com.github.javaparser.ast.expr.AssignExpr
+import com.github.javaparser.ast.expr.BooleanLiteralExpr
+import com.github.javaparser.ast.expr.Expression
 import com.github.javaparser.ast.expr.FieldAccessExpr
+import com.github.javaparser.ast.expr.IntegerLiteralExpr
 import com.github.javaparser.ast.expr.MethodCallExpr
+import com.github.javaparser.ast.expr.MethodReferenceExpr
 import com.github.javaparser.ast.expr.NameExpr
 import com.github.javaparser.ast.expr.NullLiteralExpr
 import com.github.javaparser.ast.expr.ObjectCreationExpr
@@ -168,6 +177,8 @@
         val classNameNode = classDeclaration.findFirst(SimpleName::class.java).get()
         classNameNode.setId(protoLogImplGenName)
 
+        injectCacheClass(classDeclaration, groups, protoLogGroupsClassName)
+
         injectConstants(classDeclaration,
             viewerConfigFilePath, legacyViewerConfigFilePath, legacyOutputFilePath, groups,
             protoLogGroupsClassName)
@@ -238,6 +249,12 @@
                                     field.setFinal(true)
                                     field.variables.first().setInitializer(treeMapCreation)
                                 }
+                                ProtoLogToolInjected.Value.CACHE_UPDATER.name -> {
+                                    field.setFinal(true)
+                                    field.variables.first().setInitializer(MethodReferenceExpr()
+                                            .setScope(NameExpr("Cache"))
+                                            .setIdentifier("update"))
+                                }
                                 else -> error("Unhandled ProtoLogToolInjected value: $valueName.")
                             }
                         }
@@ -245,6 +262,61 @@
         }
     }
 
+    private fun injectCacheClass(
+        classDeclaration: ClassOrInterfaceDeclaration,
+        groups: Map<String, LogGroup>,
+        protoLogGroupsClassName: String,
+    ) {
+        val cacheClass = ClassOrInterfaceDeclaration()
+            .setName("Cache")
+            .setPublic(true)
+            .setStatic(true)
+        for (group in groups) {
+            val nodeList = NodeList<Expression>()
+            val defaultVal = BooleanLiteralExpr(group.value.textEnabled || group.value.enabled)
+            repeat(LogLevel.entries.size) { nodeList.add(defaultVal) }
+            cacheClass.addFieldWithInitializer(
+                "boolean[]",
+                "${group.key}_enabled",
+                ArrayCreationExpr().setElementType("boolean[]").setInitializer(
+                    ArrayInitializerExpr().setValues(nodeList)
+                ),
+                Modifier.Keyword.PUBLIC,
+                Modifier.Keyword.STATIC
+            )
+        }
+
+        val updateBlockStmt = BlockStmt()
+        for (group in groups) {
+            for (level in LogLevel.entries) {
+                updateBlockStmt.addStatement(
+                    AssignExpr()
+                        .setTarget(
+                            ArrayAccessExpr()
+                                .setName(NameExpr("${group.key}_enabled"))
+                                .setIndex(IntegerLiteralExpr(level.ordinal))
+                        ).setValue(
+                            MethodCallExpr()
+                                .setName("isEnabled")
+                                .setArguments(NodeList(
+                                    FieldAccessExpr()
+                                        .setScope(NameExpr(protoLogGroupsClassName))
+                                        .setName(group.value.name),
+                                    FieldAccessExpr()
+                                        .setScope(NameExpr("LogLevel"))
+                                        .setName(level.toString()),
+                                ))
+                        )
+                )
+            }
+        }
+
+        cacheClass.addMethod("update").setPrivate(true).setStatic(true)
+            .setBody(updateBlockStmt)
+
+        classDeclaration.addMember(cacheClass)
+    }
+
     private fun tryParse(code: String, fileName: String): CompilationUnit {
         try {
             return StaticJavaParser.parse(code)
diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
index 2b71641..6a8a071 100644
--- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
@@ -22,6 +22,7 @@
 import com.github.javaparser.ast.CompilationUnit
 import com.github.javaparser.ast.NodeList
 import com.github.javaparser.ast.body.VariableDeclarator
+import com.github.javaparser.ast.expr.ArrayAccessExpr
 import com.github.javaparser.ast.expr.CastExpr
 import com.github.javaparser.ast.expr.Expression
 import com.github.javaparser.ast.expr.FieldAccessExpr
@@ -35,6 +36,8 @@
 import com.github.javaparser.ast.expr.VariableDeclarationExpr
 import com.github.javaparser.ast.stmt.BlockStmt
 import com.github.javaparser.ast.stmt.ExpressionStmt
+import com.github.javaparser.ast.stmt.IfStmt
+import com.github.javaparser.ast.stmt.Statement
 import com.github.javaparser.ast.type.ArrayType
 import com.github.javaparser.ast.type.ClassOrInterfaceType
 import com.github.javaparser.ast.type.PrimitiveType
@@ -74,6 +77,8 @@
 
     private val protoLogImplClassNode =
             StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogImplClassName)
+    private val protoLogImplCacheClassNode =
+        StaticJavaParser.parseExpression<FieldAccessExpr>("$protoLogImplClassName.Cache")
     private var processedCode: MutableList<String> = mutableListOf()
     private var offsets: IntArray = IntArray(0)
     /** The path of the file being processed, relative to $ANDROID_BUILD_TOP */
@@ -121,8 +126,9 @@
         group: LogGroup,
         level: LogLevel,
         messageString: String
-    ): BlockStmt {
+    ): Statement {
         val hash = CodeUtils.hash(packagePath, messageString, level, group)
+
         val newCall = call.clone()
         if (!group.textEnabled) {
             // Remove message string if text logging is not enabled by default.
@@ -166,11 +172,15 @@
         }
         blockStmt.addStatement(ExpressionStmt(newCall))
 
-        return blockStmt
+        val isLogEnabled = ArrayAccessExpr()
+            .setName(NameExpr("$protoLogImplCacheClassNode.${group.name}_enabled"))
+            .setIndex(IntegerLiteralExpr(level.ordinal))
+
+        return IfStmt(isLogEnabled, blockStmt, null)
     }
 
     private fun injectProcessedCallStatementInCode(
-        processedCallStatement: BlockStmt,
+        processedCallStatement: Statement,
         parentStmt: ExpressionStmt
     ) {
         // Inline the new statement.
diff --git a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
index de0b5ba..82aa93d 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
@@ -76,7 +76,7 @@
 
             class Test {
                 void test() {
-                    { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); }
                 }
             }
             """.trimIndent()
@@ -86,7 +86,7 @@
 
             class Test {
                 void test() {
-                    { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, -4447034859795564700L, 9, "test %d %f " + "abc %s\n test", protoLogParam0, protoLogParam1, protoLogParam2); 
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, -4447034859795564700L, 9, "test %d %f " + "abc %s\n test", protoLogParam0, protoLogParam1, protoLogParam2); 
             
             }
                 }
@@ -98,8 +98,8 @@
 
             class Test {
                 void test() {
-                    { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); } /* ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); */ { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); }
-                    { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); } /* ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); */ if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, "test %d %f", protoLogParam0, protoLogParam1); }
                 }
             }
             """.trimIndent()
@@ -109,7 +109,7 @@
 
             class Test {
                 void test() {
-                    { org.example.ProtoLogImpl.w(TEST_GROUP, 3218600869538902408L, 0, "test", (Object[]) null); }
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { org.example.ProtoLogImpl.w(TEST_GROUP, 3218600869538902408L, 0, "test", (Object[]) null); }
                 }
             }
             """.trimIndent()
@@ -119,7 +119,7 @@
 
             class Test {
                 void test() {
-                    { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, null, protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, -1473209266730422156L, 9, null, protoLogParam0, protoLogParam1); }
                 }
             }
             """.trimIndent()
@@ -129,7 +129,7 @@
 
             class Test {
                 void test() {
-                    { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, -4447034859795564700L, 9, null, protoLogParam0, protoLogParam1, protoLogParam2); 
+                    if (org.example.ProtoLogImpl.Cache.TEST_GROUP_enabled[3]) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, -4447034859795564700L, 9, null, protoLogParam0, protoLogParam1, protoLogParam2); 
             
             }
                 }
diff --git a/tools/streaming_proto/java/java_proto_stream_code_generator.cpp b/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
index 9d61111..be5c197 100644
--- a/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
+++ b/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
@@ -18,11 +18,13 @@
 
 #include <stdio.h>
 
+#include <algorithm>
 #include <iomanip>
 #include <iostream>
 #include <map>
 #include <sstream>
 #include <string>
+#include <unordered_set>
 
 #include "Errors.h"
 
@@ -30,21 +32,39 @@
 using namespace google::protobuf::io;
 using namespace std;
 
+static bool outer_class_name_clashes_with_any_message(const string& outer_class_name,
+                                                      const vector<DescriptorProto>& messages) {
+    return any_of(messages.cbegin(), messages.cend(), [&](const DescriptorProto& message) {
+        return message.name() == outer_class_name;
+    });
+}
+
 /**
  * If the descriptor gives us a class name, use that. Otherwise make one up from
  * the filename of the .proto file.
  */
-static string make_outer_class_name(const FileDescriptorProto& file_descriptor) {
+static string make_outer_class_name(const FileDescriptorProto& file_descriptor,
+                                    const vector<DescriptorProto>& messages) {
     string name = file_descriptor.options().java_outer_classname();
-    if (name.size() == 0) {
-        name = to_camel_case(file_base_name(file_descriptor.name()));
-        if (name.size() == 0) {
-            ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
-                       "Unable to make an outer class name for file: %s",
-                       file_descriptor.name().c_str());
-            name = "Unknown";
-        }
+    if (!name.empty()) {
+        return name;
     }
+
+    // Outer class and messages with the same name would result in invalid java (outer class and
+    // inner class cannot have same names).
+    // If the outer class name clashes with any message, let's append an "OuterClass" suffix.
+    // This behavior is consistent with the standard protoc.
+    name = to_camel_case(file_base_name(file_descriptor.name()));
+    while (outer_class_name_clashes_with_any_message(name, messages)) {
+        name += "OuterClass";
+    }
+
+    if (name.empty()) {
+        ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE, "Unable to make an outer class name for file: %s",
+                   file_descriptor.name().c_str());
+        name = "Unknown";
+    }
+
     return name;
 }
 
@@ -149,6 +169,12 @@
         write_field(text, message.field(i), indented);
     }
 
+    // Extensions
+    N = message.extension_size();
+    for (int i = 0; i < N; i++) {
+        write_field(text, message.extension(i), indented);
+    }
+
     text << indent << "}" << endl;
     text << endl;
 }
@@ -165,7 +191,7 @@
     stringstream text;
 
     string const package_name = make_java_package(file_descriptor);
-    string const outer_class_name = make_outer_class_name(file_descriptor);
+    string const outer_class_name = make_outer_class_name(file_descriptor, messages);
 
     text << "// Generated by protoc-gen-javastream. DO NOT MODIFY." << endl;
     text << "// source: " << file_descriptor.name() << endl << endl;
@@ -214,7 +240,7 @@
  */
 static void write_multiple_files(CodeGeneratorResponse* response,
                                  const FileDescriptorProto& file_descriptor,
-                                 set<string> messages_to_compile) {
+                                 const unordered_set<string>& messages_allowlist) {
     // If there is anything to put in the outer class file, create one
     if (file_descriptor.enum_type_size() > 0) {
         vector<EnumDescriptorProto> enums;
@@ -222,7 +248,7 @@
         for (int i = 0; i < N; i++) {
             auto enum_full_name =
                     file_descriptor.package() + "." + file_descriptor.enum_type(i).name();
-            if (!messages_to_compile.empty() && !messages_to_compile.count(enum_full_name)) {
+            if (!messages_allowlist.empty() && !messages_allowlist.count(enum_full_name)) {
                 continue;
             }
             enums.push_back(file_descriptor.enum_type(i));
@@ -230,9 +256,10 @@
 
         vector<DescriptorProto> messages;
 
-        if (messages_to_compile.empty() || !enums.empty()) {
+        if (messages_allowlist.empty() || !enums.empty()) {
             write_file(response, file_descriptor,
-                       make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+                       make_file_name(file_descriptor,
+                                      make_outer_class_name(file_descriptor, messages)),
                        true, enums, messages);
         }
     }
@@ -246,12 +273,12 @@
 
         auto message_full_name =
                 file_descriptor.package() + "." + file_descriptor.message_type(i).name();
-        if (!messages_to_compile.empty() && !messages_to_compile.count(message_full_name)) {
+        if (!messages_allowlist.empty() && !messages_allowlist.count(message_full_name)) {
             continue;
         }
         messages.push_back(file_descriptor.message_type(i));
 
-        if (messages_to_compile.empty() || !messages.empty()) {
+        if (messages_allowlist.empty() || !messages.empty()) {
             write_file(response, file_descriptor,
                        make_file_name(file_descriptor, file_descriptor.message_type(i).name()),
                        false, enums, messages);
@@ -261,14 +288,14 @@
 
 static void write_single_file(CodeGeneratorResponse* response,
                               const FileDescriptorProto& file_descriptor,
-                              set<string> messages_to_compile) {
+                              const unordered_set<string>& messages_allowlist) {
     int N;
 
     vector<EnumDescriptorProto> enums;
     N = file_descriptor.enum_type_size();
     for (int i = 0; i < N; i++) {
         auto enum_full_name = file_descriptor.package() + "." + file_descriptor.enum_type(i).name();
-        if (!messages_to_compile.empty() && !messages_to_compile.count(enum_full_name)) {
+        if (!messages_allowlist.empty() && !messages_allowlist.count(enum_full_name)) {
             continue;
         }
 
@@ -281,22 +308,23 @@
         auto message_full_name =
                 file_descriptor.package() + "." + file_descriptor.message_type(i).name();
 
-        if (!messages_to_compile.empty() && !messages_to_compile.count(message_full_name)) {
+        if (!messages_allowlist.empty() && !messages_allowlist.count(message_full_name)) {
             continue;
         }
 
         messages.push_back(file_descriptor.message_type(i));
     }
 
-    if (messages_to_compile.empty() || !enums.empty() || !messages.empty()) {
+    if (messages_allowlist.empty() || !enums.empty() || !messages.empty()) {
         write_file(response, file_descriptor,
-                   make_file_name(file_descriptor, make_outer_class_name(file_descriptor)), true,
-                   enums, messages);
+                   make_file_name(file_descriptor,
+                                  make_outer_class_name(file_descriptor, messages)),
+                   true, enums, messages);
     }
 }
 
 static void parse_args_string(stringstream args_string_stream,
-                              set<string>* messages_to_compile_out) {
+                              unordered_set<string>& messages_allowlist_out) {
     string line;
     while (getline(args_string_stream, line, ';')) {
         stringstream line_ss(line);
@@ -305,7 +333,7 @@
         if (arg_name == "include_filter") {
             string full_message_name;
             while (getline(line_ss, full_message_name, ',')) {
-                messages_to_compile_out->insert(full_message_name);
+                messages_allowlist_out.insert(full_message_name);
             }
         } else {
             ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE, "Unexpected argument '%s'.", arg_name.c_str());
@@ -316,10 +344,10 @@
 CodeGeneratorResponse generate_java_protostream_code(CodeGeneratorRequest request) {
     CodeGeneratorResponse response;
 
-    set<string> messages_to_compile;
+    unordered_set<string> messages_allowlist;
     auto request_params = request.parameter();
     if (!request_params.empty()) {
-        parse_args_string(stringstream(request_params), &messages_to_compile);
+        parse_args_string(stringstream(request_params), messages_allowlist);
     }
 
     // Build the files we need.
@@ -328,9 +356,9 @@
         const FileDescriptorProto& file_descriptor = request.proto_file(i);
         if (should_generate_for_file(request, file_descriptor.name())) {
             if (file_descriptor.options().java_multiple_files()) {
-                write_multiple_files(&response, file_descriptor, messages_to_compile);
+                write_multiple_files(&response, file_descriptor, messages_allowlist);
             } else {
-                write_single_file(&response, file_descriptor, messages_to_compile);
+                write_single_file(&response, file_descriptor, messages_allowlist);
             }
         }
     }
diff --git a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
index 45ab986..2ba5705 100644
--- a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
+++ b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
@@ -993,6 +993,16 @@
      * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
      * or {@link #setupInterfaceForSoftApMode(String)}.
      *
+     * <p>
+     * When an Access Point’s beacon or probe response includes a Multi-BSSID Element, the
+     * returned scan results should include separate scan result for each BSSID within the
+     * Multi-BSSID Information Element. This includes both transmitted and non-transmitted BSSIDs.
+     * Original Multi-BSSID Element will be included in the Information Elements attached to
+     * each of the scan results.
+     * Note: This is the expected behavior for devices supporting 11ax (WiFi-6) and above, and an
+     * optional requirement for devices running with older WiFi generations.
+     * </p>
+     *
      * @param ifaceName Name of the interface.
      * @param scanType The type of scan result to be returned, can be
      * {@link #SCAN_TYPE_SINGLE_SCAN} or {@link #SCAN_TYPE_PNO_SCAN}.